Index: vis_dev/vis-2.3/INSTALL
===================================================================
--- vis_dev/vis-2.3/INSTALL	(revision 14)
+++ vis_dev/vis-2.3/INSTALL	(revision 14)
@@ -0,0 +1,176 @@
+Basic Installation
+==================
+
+   These are generic installation instructions.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+   The file `configure.in' is used to create `configure' by a program
+called `autoconf'.  You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.  If you're
+     using `csh' on an old version of System V, you might need to type
+     `sh ./configure' instead to prevent `csh' from trying to execute
+     `configure' itself.
+
+     Running `configure' takes awhile.  While running, it prints some
+     messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the `configure' script does not know about.  You can give `configure'
+initial values for variables by setting them in the environment.  Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+     CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+     env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory.  After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+   By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc.  You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+   Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+   There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on.  Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+     CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+   If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+     Use and save the results of the tests in FILE instead of
+     `./config.cache'.  Set FILE to `/dev/null' to disable caching, for
+     debugging `configure'.
+
+`--help'
+     Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`--version'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
+
Index: vis_dev/vis-2.3/Makefile.in
===================================================================
--- vis_dev/vis-2.3/Makefile.in	(revision 14)
+++ vis_dev/vis-2.3/Makefile.in	(revision 14)
@@ -0,0 +1,1164 @@
+# FileName	[ Makefile.in ]
+#
+# PackageName	[ vis ]
+#
+# Synopsis	[ Package-wide Makefile ]
+#
+# Description	[ This file requires GNU's make program.
+#		  Run "configure" to generate the Makefile, or use
+#		  "config.status" (created by configure) to regenerate the
+#		  Makefile after modifying this file.
+#
+#		  Type "gmake help" for help about valid targets.
+#		 ]
+#
+# SeeAlso	[ configure.in ]
+#
+# Author	[ Stephen Edwards <sedwards@eecs.berkeley.edu>
+#		  Tom Shiple <shiple@eecs.berkeley.edu> ]
+#
+# Copyright	[
+#  Copyright (c) 1994-1996 The Regents of the Univ. of California.
+#  All rights reserved.
+#
+#  Permission is hereby granted, without written agreement and without license
+#  or royalty fees, to use, copy, modify, and distribute this software and its
+#  documentation for any purpose, provided that the above copyright notice and
+#  the following two paragraphs appear in all copies of this software.
+#
+#  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+#  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+#  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+#  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+#  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+#  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+#  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+#  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+#  ]
+#
+# Revision	[$Id: Makefile.in,v 1.127 2010/04/09 23:06:15 hsv Exp $]
+
+# Default target:
+
+.PHONY : default
+
+default : all
+
+#----------------------------------------------------------------------
+# The list of packages to compile.  Change this if you are only compiling
+# part of VIS
+#----------------------------------------------------------------------
+
+#PKGS = tst
+PKGS = $(ALL_PKGS)
+
+# The name of the BDD package to use
+
+BDDPKG =	@BDDLIB@
+
+#----------------------------------------------------------------------
+# This Makefile is designed for three different situations:
+#
+# 1. Single platform build (the default)
+#
+#    All packages listed in the PKGS variable
+#    local_srcdir = master_srcdir = .
+#
+# 2. Multi-platform build
+#
+#    All packages listed in the PKGS variable
+#    local_srcdir = master_srcdir = /where/source/files/reside
+#
+# 3. Multi-platform development (used at Berkeley)
+#
+#    Packages under development listed in the PKGS variable
+#    local_srcdir = ../common
+#    master_srcdir = /projects/vis/vis-devel/common
+#
+#    User has a directory structure that looks like
+#
+#	vis/common/src/		Subdirectory with package source files
+#				under development.
+#
+#	vis/$PLATFORM/		Subdirectory with this Makefile.
+#				Compilation is invoked here.
+#
+#	$PLATFORM is something like "alpha-g" (DEC Alpha, debug version)
+#
+#----------------------------------------------------------------------
+
+#----------------------------------------------------------------------
+# Information about all the packages
+#----------------------------------------------------------------------
+
+ALL_PKGS = abs amc baig bmc cmd ctlp ctlsp eqv fsm grab hrc imc img io ltl \
+	maig mark mc mvf mvfaig ntk ntm ntmaig ord part puresat rst res restr \
+	rt sat sim spfd synth tbl truesim tst var vm
+# Generate the list of all packages NOT in the PKGS list
+
+MISSING_PKGS = $(filter-out $(PKGS), $(ALL_PKGS))
+
+# All the BDD packages
+BDDPKGS = cu cmu cal
+
+#----------------------------------------------------------------------
+# For safety
+#----------------------------------------------------------------------
+
+SHELL = /bin/sh
+.SUFFIXES:
+
+#----------------------------------------------------------------------
+# The name of the product and its version
+#----------------------------------------------------------------------
+
+PRODUCT = vis
+VERSION = 2.3
+
+# Compile and version information
+#
+# CUR_DATE and CUR_VER are strings surrounded by double quotes that contain
+# spaces, e.g., "vis release 2.0"
+
+VERDATE := -DCUR_DATE="\"$(shell date)\"" -DCUR_VER="\"$(PRODUCT) release $(VERSION)\""
+
+#----------------------------------------------------------------------
+# Source directories
+#----------------------------------------------------------------------
+
+# Directory containing master source files.  This directory is searched
+# for packages NOT listed in the PKGS variable.  Defaults to "."
+# Override with  ./configure --srcdir=
+master_srcdir = @srcdir@
+
+# Directory containing local source files.  This directory is searched
+# for packages listed in the PKGS variable.  Defaults to the master source
+# directory (see above).
+# Override with ./configure --with-local-srcdir=
+local_srcdir =  @local_srcdir@
+
+#----------------------------------------------------------------------
+# Directories used while building
+#----------------------------------------------------------------------
+
+# Directories to search for glu .h files (space-separated)
+gluincdir1 =	@gluincdir@
+
+# Directories to search for libglu.a (space-separated)
+glulibdir1 =	@glulibdir@
+
+# Directory where object files will be placed during the build
+objectdir =	obj
+
+# Directory where links to header files will be placed during the build
+headerdir =	$(local_srcdir)/include
+
+# Directories where documentation will be placed during the build
+docdir =	$(master_srcdir)/doc
+htmldocdir =	$(docdir)/html
+txtdocdir =	$(docdir)/txt
+helpdir =	$(master_srcdir)/share/help
+
+# Directories to search for VIS library files
+# Set by ./configure --with-vis-libdir=
+vislibdir =	@vislibdir@
+
+# Full path of platform-independent library files during the build.
+# Using this variable as an environment variable allows VIS to work
+# before it is installed.
+#
+# Note: This is NOT where they will be installed
+
+VIS_LIBRARY_PATH = $(shell cd $(master_srcdir)/share ; pwd)
+
+#----------------------------------------------------------------------
+# Defaults for GLU library and header files
+#----------------------------------------------------------------------
+
+ifndef gluincdir1
+  gluincdir = ../glu-$(VERSION)/include ../../glu-$(VERSION)/include
+else
+  gluincdir = $(gluincdir1)  $(gluincdir1)/../src/cudd
+endif
+
+ifndef glulibdir1
+  glulibdir = ../glu-$(VERSION) ../../glu-$(VERSION)
+else
+  glulibdir = $(glulibdir1)
+endif
+
+#----------------------------------------------------------------------
+# Installation names and directories
+#----------------------------------------------------------------------
+
+# Name of the library to create
+LIBRARY =	lib$(PRODUCT).a
+
+# Name of the man page
+MANPAGE =       vis.1
+
+# Directory in which to install architecture-independent files
+# Set by ./configure --prefix=...
+prefix =	@prefix@
+
+# Directory in which to install architecture-dependent files
+# Set by ./configure --exec-prefix=...
+exec_prefix =	@exec_prefix@
+
+# Directory in which to install binaries
+bindir =	$(exec_prefix)/bin
+
+# Directory in which to install libraries
+libdir =	$(exec_prefix)/lib
+
+# Directory in which to install headers
+includedir =	$(prefix)/include
+
+# Directory in which to install architecture-independent library files
+datadir =	$(prefix)/share/vis
+
+# Directory for the man page
+mandir = $(prefix)/man/man1
+
+#----------------------------------------------------------------------
+# The following are set by the configure script
+#----------------------------------------------------------------------
+
+AC_FLAGS =	@DEFS@
+LIBDIRS =	@LIBDIRS@
+RANLIB =	@RANLIB@
+CC =		@CC@
+LINKER =	@LINKER@
+LDFLAGS =	@LDFLAGS@
+#
+# Define the linker for the executable with "memory_profile" activated
+#
+PLINKER =       @PLINKER@
+CFLAGS =	@CFLAGS@
+OTHERLIBS =	-lm @LIBS@ @LEXLIB@
+YACC =		@YACC@
+LEX =		@LEX@
+NAWK =		@AWK@
+INSTALL =	@INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA =	@INSTALL_DATA@
+AR =		@AR@
+ZCHAFF=         @ZCHAFF@
+#----------------------------------------------------------------------
+# Examples included in the distribution
+#----------------------------------------------------------------------
+
+# Each example is declared only once. If some checking through is done
+# make check, then it is declared in one of CHECK_COMMON_EXAMPLES,
+# CHECK_EXAMPLES_cu, CHECK_EXAMPLES_cmu or CHECK_EXAMPLES_cu. If the example
+# is just being added to the examples directory in VIS, then add it here.
+
+EXAMPLES = $(CHECK_COMMON_EXAMPLES) $(CHECK_EXAMPLES_cu) \
+		$(CHECK_EXAMPLES_cmu) $(CHECK_EXAMPLES_cal) \
+		bpb eight_queens minmax ping_pong_new rcnum
+
+# The "interesting" example files are anything in the examples subdirectories
+# except the RCS subdirectories
+#
+# This is a rather messy way to look for filenames in the local_srcdir,
+# then remove the local_srcdir prefix
+
+EXAMPLEFILES = $(patsubst $(local_srcdir)/%, %, \
+		$(filter-out %RCS, $(foreach example, $(EXAMPLES), \
+		  $(wildcard $(local_srcdir)/examples/$(example)/*))))
+
+# $(pathsubst $(local_srcdir)/%, %, \
+#	$(filter-out %/RCS, $(foreach example, $(EXAMPLES), \
+
+
+#----------------------------------------------------------------------
+# Distributed files in the doc directory
+#----------------------------------------------------------------------
+
+DOCUMENTATION = blifmv.ps ctl.ps vis_user.ps two_phase.ps
+
+#----------------------------------------------------------------------
+# Files in the share directory
+#----------------------------------------------------------------------
+
+SHAREFILES = master.visrc ioBlifToMv.nawk ioBlifToMvForIncremental.nawk\
+	     script_compute_reach.simple script_compute_reach.robust\
+	     script_model_check.simple script_model_check.robust\
+	     script_fair_model_check.simple script_fair_model_check.robust\
+	     script_lang_empty_check.simple script_lang_empty_check.robust\
+	     script_generic.simple script_generic.robust\
+	     sislib.mv createfunctionmap memoryaccount visdbgpp
+
+HELPFILES = $(notdir $(wildcard $(helpdir)/*.txt))
+
+#----------------------------------------------------------------------
+# Include the make templates from all the packages
+#
+# Each of these templates (e.g., array/array.make) should contains lines
+# of the form
+#
+# CSRC += source1.c source2.c
+# HEADERS += header1.h header2.h
+# LEXSRC += file1.l
+# YACCSRC += file2.y
+# GENERATEDCSRC += ctlpLex.c ctlpRead.c
+#----------------------------------------------------------------------
+
+MAKEINCLUDES = $(foreach package, $(PKGS), \
+	$(local_srcdir)/src/$(package)/$(package).make)
+
+include $(MAKEINCLUDES)
+
+OBJECTS = $(addprefix $(objectdir)/,$(GENERATEDCSRC:.c=.o) $(CSRC:.c=.o))
+
+#----------------------------------------------------------------------
+# Include the dependency files from each package directory.
+# A missing dependency file does not produce an error.
+#----------------------------------------------------------------------
+
+DEPENDENCIES = $(foreach package, $(PKGS), \
+	$(local_srcdir)/src/$(package)/$(package).d)
+
+-include $(DEPENDENCIES)
+
+#----------------------------------------------------------------------
+# Header files and library search paths and names
+#
+# INCLUDEDIRS looks like "-I/projects/glu/ -I/projects/vis/ ..."
+# LIBRARYDIRS looks like "-L/projects/glu/ -L/projects/vis/ ..."
+# LIBS looks like "-lm -lglu -lvis"
+#----------------------------------------------------------------------
+
+INCLUDEDIRS = $(addprefix -I,$(gluincdir)) \
+		$(foreach package, $(PKGS), -I$(local_srcdir)/src/$(package)) \
+		$(foreach package, $(MISSING_PKGS), \
+		-I$(master_srcdir)/src/$(package)) \
+		-I$(objectdir)
+
+LIBRARYDIRS = $(addprefix -L,$(vislibdir)) $(addprefix -L,$(glulibdir)) \
+		$(LIBDIRS)
+
+# Link against the VIS library only if some packages are missing
+# (i.e., we are compiling only a few packages locally)
+
+ifneq ($(strip $(MISSING_PKGS)),)
+  VISLIBS = -l$(PRODUCT)
+else
+  VISLIBS =
+endif
+
+GLULIBS = -l$(BDDPKG) -lglu
+
+# g++ on Linux RH requires -lstdc++
+ifeq ($(CC),g++)
+OTHERLIBS += -lstdc++
+endif
+
+LIBS = $(VISLIBS) $(GLULIBS) $(OTHERLIBS)
+
+#----------------------------------------------------------------------
+# Form the the list of directories to search for header files.
+#
+# VPATH looks like /projects/vis:/projects/glu/: ...
+#----------------------------------------------------------------------
+
+VPATH = $(local_srcdir): \
+	$(master_srcdir): \
+	$(addprefix :$(local_srcdir)/src/,$(PKGS)): \
+	$(addprefix :$(master_srcdir)/src/,$(MISSING_PKGS)): \
+	$(objectdir): \
+	$(local_srcdir)/share
+
+#----------------------------------------------------------------------
+# Definitions for the distribution file
+#----------------------------------------------------------------------
+
+DISTRIBUTION = $(PRODUCT)-$(VERSION)
+
+# Directories to include in the distribution file
+
+DISTDIRS = src helpers share share/help obj doc examples \
+	$(addprefix examples/,$(EXAMPLES)) $(addprefix src/,$(PKGS))
+
+# Build/install helper files
+
+HELPERS = $(addprefix helpers/, \
+	install-sh mkinstalldirs config.guess config.sub dependency.make)
+
+# Files to include in the distribution file
+
+DISTFILES = \
+	README INSTALL NEWS \
+	configure configure.in Makefile.in $(HELPERS) \
+	vis.1 \
+	xsimv \
+	$(CSRC) $(HEADERS) $(LEXSRC) $(YACCSRC) $(MAKEINCLUDES) \
+	$(EXAMPLEFILES) \
+	$(addprefix doc/,$(DOCUMENTATION)) \
+	$(addprefix share/,$(SHAREFILES)) \
+	$(addprefix share/help/,$(HELPFILES))
+
+#----------------------------------------------------------------------
+# Variables used by for Revision Control
+#----------------------------------------------------------------------
+
+# The root RCS directory
+rcs_rootdir          = /projects/vis/rcsRoot/common
+
+RCSFILES        = $(CSRC) $(HEADERS) $(LEXSRC) $(YACCSRC) $(MAKEINCLUDES)
+
+RCSMISCFILES      = Makefile.in configure.in localconfigure \
+	masterconfigure README INSTALL NEWS xsimv $(addprefix helpers/, mkinstalldirs install-sh \
+		config.guess config.sub dependency.make )
+
+RCSSHAREFILES        = $(SHAREFILES)
+
+#----------------------------------------------------------------------
+# Implicit rules
+#----------------------------------------------------------------------
+
+ALLCFLAGS = $(CFLAGS) $(AC_FLAGS) $(VERDATE) \
+		-DNAWK=\"$(NAWK)\" -DLIBRARY=\"$(datadir)\"
+
+# For compiling a source file into the object directory
+
+$(objectdir)/%.o : %.c
+	umask 2 ; $(CC) -c $(ALLCFLAGS) $(INCLUDEDIRS) -o $@ $<
+
+# Place object files into an archive
+
+%.a :
+	rm -f $@
+	umask 2; $(AR) cq $@ $^
+	$(RANLIB) $@
+
+######################################################################
+#				RULES				     #
+######################################################################
+
+#:
+#: Useful targets:
+#:
+
+#----------------------------------------------------------------------
+# Rule for getting help
+#----------------------------------------------------------------------
+
+.PHONY : help
+
+#: help -- Print a list of targets
+
+# This prints all lines in this Makefile that begin with #:
+
+help :
+	@sed -n "s/^#://p" Makefile
+
+#----------------------------------------------------------------------
+# Always executed once when the Makefile is run
+#----------------------------------------------------------------------
+
+# Make sure the directory in which to place the objects exists
+
+ignored := $(shell umask 2; test -d $(objectdir) || mkdir $(objectdir))
+
+#----------------------------------------------------------------------
+# Rules to compile and build libraries and executables
+#----------------------------------------------------------------------
+
+.PHONY : all allprods library allprods-mp exe-mp compile-version delete-version
+
+#:
+#: all (the default) -- Compile the main executable
+# (force the version to be recompiled)
+
+all : ALLCFLAGS += -DBDD$(BDDPKG)
+
+all : compile-version $(PRODUCT)
+
+# Create the main executable
+$(PRODUCT) : $(OBJECTS) $(glulibdir)/libglu.a $(glulibdir)/lib$(BDDPKG).a
+	umask 2 ; $(LINKER) -o $(PRODUCT) $(LDFLAGS) \
+		$(OBJECTS) $(LIBRARYDIRS) $(LIBS)
+
+#: allprods -- Compile an executable linked with each BDD package
+
+allprods : $(OBJECTS) $(glulibdir)/libglu.a $(foreach bddpkg, $(BDDPKGS), \
+	   $(glulibdir)/lib$(bddpkg).a)
+	@for bddpkg in $(BDDPKGS) ; \
+	do \
+	  rm -f $(objectdir)/satBDD.o; \
+	  umask 2 ; $(CC) -c $(ALLCFLAGS) -DBDD$$bddpkg $(INCLUDEDIRS) -o $(objectdir)/satBDD.o  $(master_srcdir)/src/sat/satBDD.c; \
+	  echo "Creating vis-$$bddpkg";\
+	  umask 2 ; $(LINKER) -o $(PRODUCT)-$$bddpkg $(LDFLAGS) $(OBJECTS) \
+		$(LIBRARYDIRS) $(VISLIBS) -l$$bddpkg -lglu $(OTHERLIBS); \
+	done
+
+# Force the "version" information to be recompiled
+
+compile-version : delete-version $(objectdir)/vmVers.o $(objectdir)/satBDD.o
+
+# Delete the object file related to the version
+
+delete-version :
+	rm -f $(objectdir)/vmVers.o $(objectdir)/satBDD.o
+
+# Build a library containing all the objects
+
+#: library -- Create a library of all the objects (useful in a central area)
+
+library : $(LIBRARY)
+
+$(LIBRARY) : $(OBJECTS)
+
+ifdef PLINKER
+$(PRODUCT)-mp : $(LIBRARY) $(glulibdir)/libglu.a \
+		$(foreach bddpkg, $(BDDPKGS), \
+		$(glulibdir)/lib$(bddpkg).a)
+	umask 2 ; $(PLINKER) -o $(PRODUCT)-mp $(OBJECTS) \
+		`purify -printhomedir`/libpurify_stubs.a \
+		$(LIBRARYDIRS) $(LIBS)
+
+allprods-mp : $(LIBRARY) $(glulibdir)/libglu.a \
+		$(foreach bddpkg, $(BDDPKGS), \
+		$(glulibdir)/lib$(bddpkg).a)
+	@for bddpkg in $(BDDPKGS) ; \
+	do \
+	  echo "Creating vis-$$bddpkg";\
+	  umask 2 ; $(PLINKER) -o $(PRODUCT)-$$bddpkg-mp $(OBJECTS) \
+		`purify -printhomedir`/libpurify_stubs.a \
+		$(LIBRARYDIRS) $(VISLIBS) -l$$bddpkg -lglu $(OTHERLIBS) ; \
+	done
+
+exe-mp : $(OBJECTS)
+	$(PLINKER) -o $(PRODUCT)-mp $(OBJECTS) \
+		`purify -printhomedir`/libpurify_stubs.a \
+		$(LIBRARYDIRS) $(LIBS)
+endif
+
+#----------------------------------------------------------------------
+# Rule to produce the function map for the memory_profile command
+#----------------------------------------------------------------------
+
+.PHONY : functionmap
+
+FMAPFILE = .fmap
+functionmap: $(CSRC)
+	$(VIS)/common/share/createfunctionmap $^ >$(FMAPFILE)
+
+#----------------------------------------------------------------------
+# Rules for installation
+#----------------------------------------------------------------------
+
+.PHONY : install uninstall installdirs
+
+#:
+#: install -- Install the product and libraries in bindir, libdir,
+#:            datadir, etc.
+
+install : $(PRODUCT) $(LIBRARY) installdirs
+	@echo "Installing $(bindir)/$(PRODUCT)"
+	@$(INSTALL_PROGRAM) $(PRODUCT) $(bindir)/$(PRODUCT)
+	@echo "Installing $(libdir)/$(LIBRARY)"
+	@$(INSTALL_DATA) $(LIBRARY) $(libdir)/$(LIBRARY)
+	@for file in $(SHAREFILES) ; do \
+		echo "Installing $(datadir)/$$file"; \
+		$(INSTALL_DATA) $(master_srcdir)/share/$$file \
+			$(datadir)/$$file; \
+	done
+	@for file in $(HELPFILES) ; do \
+		echo "Installing $(datadir)/help/$$file"; \
+		$(INSTALL_DATA) $(master_srcdir)/share/help/$$file \
+			$(datadir)/help/$$file; \
+	done
+	@echo "Installing $(mandir)/vis.1"
+	@$(INSTALL_DATA) vis.1 $(mandir)/vis.1
+	@for header in $(HEADERS); do \
+		echo "Installing $(includedir)/$$header"; \
+		$(INSTALL_DATA) $(master_srcdir)/src/*/$$header \
+			$(includedir)/$$header; \
+	done
+
+#: uninstall -- Reverse the effects of "install"
+
+uninstall :
+	rm -f $(bindir)/$(PRODUCT)
+	rm -f $(libdir)/$(LIBRARY)
+	@for file in $(SHAREFILES) ; \
+	do \
+	  echo "Removing $(datadir)/$$file"; \
+	  rm -f $(datadir)/$$file; \
+	done
+	@for file in $(HELPFILES) ; \
+	do \
+	  echo "Removing $(datadir)/help/$$file"; \
+	  rm -f $(datadir)/help/$$file; \
+	done
+	@for header in $(HEADERS); \
+	do \
+	  echo "Removing $(includedir)/$$header"; \
+	  rm -f $(includedir)/$$header; \
+	done
+
+installdirs :
+	$(master_srcdir)/helpers/mkinstalldirs \
+		$(bindir) $(libdir) $(includedir) $(datadir) $(datadir)/help \
+		$(mandir)
+
+#----------------------------------------------------------------------
+# Rules for checking the build
+#----------------------------------------------------------------------
+
+.PHONY : check check-examples
+
+# This is a lengthy sed command used to filter out the irrelevant VIS
+# output that appears when the examples are running.
+#
+# Sed does not permit space between the trailing p ("print matching
+# lines") and the semicolon (end of command).  Hashes are escaped --
+# otherwise they are Makefile comments.  This was once a long egrep
+# expression, but the string was too long for Ultrix's egrep.
+
+SED_CMD = \
+	/^FSM depth/p; \
+	/^computation depth/p; \
+	/^reachable states =/p; \
+	/^\# MC: formula passed/p; \
+	/^\# MC: formula failed/p; \
+	/^\# MC: the number of non-trivial forced segments/p; \
+	/^\# MC: Vacuous/p; \
+	/^\# MC: No vacuous/p; \
+	/[sS]tates covered/p; \
+	/covered states/p; \
+	/Percentage of coverage/p; \
+	/^\# LTL_MC: formula passed/p; \
+	/^\# LTL_MC: formula failed/p; \
+	/^\# INV: formula passed/p; \
+	/^\# INV: formula failed/p; \
+	/^\# LE: language is not empty/p; \
+	/^\# LE: language emptiness check passes/p; \
+	/^\# ABS: formula passed/p; \
+	/^\# ABS: formula failed/p; \
+	/^\# BMC: formula failed/p;\
+	/^\# BMC: no counterexample found/p; \
+	/Residue/p; \
+	/^\# AMC: Verified formula TRUE/p; \
+	/^\# AMC: Verified formula FALSE/p; \
+	/Equivalence Classes/p; \
+	/Total number of literals/p; \
+	/Networks are combinationally equivalent\./p; \
+	/Networks are sequentially equivalent\./p; \
+	/;.*;/p;
+
+CHECK_EXAMPLES_cu = daio_receiver mult6x6 s1269 fpmpy restruct synthesis \
+	production_cell
+CHECK_EXAMPLES_cmu =
+CHECK_EXAMPLES_cal =
+
+# List of all examples to check (A subset of EXAMPLES)
+
+CHECK_COMMON_EXAMPLES = abp amp arbiter bakery coherence counter crd ctlp3 \
+	dcnew eisenberg elevator ethernet exampleS gcd gigamax ping_pong \
+	scheduler short slider tbl_one_bug tcp tlc treearbiter
+
+CHECK_EXAMPLES = $(CHECK_COMMON_EXAMPLES) $(CHECK_EXAMPLES_$(BDDPKG))
+
+# Determine the absolute executable path
+#
+# Starting from the current directory, change directory to the directory
+# part of the product name, then tack on the filename part of EXECUTABLE
+
+EXECUTABLE = $(PRODUCT)
+
+EXECUTABLEPATH := \
+	$(shell cd $(dir $(EXECUTABLE)) ; pwd)/$(notdir $(EXECUTABLE))
+
+# Determine the rootname of the examples
+#
+
+EXAMPLEPATH = $(master_srcdir)/examples
+
+FULLEXAMPLEPATH := $(shell cd $(EXAMPLEPATH) ; pwd)
+
+#:
+#: check -- Test the locally-built executable (runs check-examples)
+
+check : check-examples
+
+# Run check on each of the bdd versions (named e.g., vis-cmu)
+
+#: check-allprods -- Test each of the BDD executables (see allprods)
+
+check-allprods :
+	@for bddpkg in $(BDDPKGS) ; \
+	do \
+	  echo "Checking $(PRODUCT)-$$bddpkg";\
+	  $(MAKE) PRODUCT=$(PRODUCT)-$$bddpkg BDDPKG=$$bddpkg check ; \
+	done
+
+#: check-examples -- Test each of the examples listed in CHECK_EXAMPLES
+#:	    You may want to invoke this with
+#:            gmake "CHECK_EXAMPLES=abp bakery" check-examples
+#:            gmake EXECUTABLE=vis-cmu check-examples
+#:            gmake EXECUTABLE=/projects/vis/vis-devel/alpha-g/vis \
+#:                    check-examples
+#:            gmake EXAMPLEPATH=/projects/vis/vis-devel/common/examples \
+#:                    check-examples
+#:            gmake EXAMPLEPATH=../common/examples check-examples
+#:            gmake VIS_LIBRARY_PATH=/projects/vis/vis-devel/share
+
+# For each example,
+#
+# 1) create the directory checkresults/<example>
+# 2) enter that directory
+# 3) create "check_script" by prepending a "set open_path" command
+#    to the example's check_script in the master source directory.  This
+#    makes VIS look in the master source directory for example files
+# 4) run VIS on that script, producing "result.raw"
+# 5) filter out relevant lines in the result, producing "result.filtered"
+#    and compare this with the "check_result" file in the master source
+#    directory.  Differences are written to "result.differences"
+
+check-examples :
+	@test -d checkresults || mkdir checkresults
+	@echo "Checking examples.  Results will be in checkresults/<example>/result.raw"
+	@echo "Running executable $(EXECUTABLEPATH)"
+	@echo " (change with EXECUTABLE=...)"
+	@echo "Taking examples from $(FULLEXAMPLEPATH)"
+	@echo " (change with EXAMPLEPATH=...)"
+	@cwd=`pwd` ; \
+	VIS_LIBRARY_PATH=$(VIS_LIBRARY_PATH) ; \
+	export VIS_LIBRARY_PATH ; \
+	for example in $(CHECK_EXAMPLES) ; \
+	do \
+	  echo -n "Checking $$example ... " ; \
+	  cd $$cwd ; \
+	  test -d checkresults/$$example || \
+		mkdir checkresults/$$example ; \
+	  cd checkresults/$$example ; \
+	  rm -f check_script ; \
+	  echo "set open_path $(FULLEXAMPLEPATH)/$$example" > check_script ; \
+	  cat $(FULLEXAMPLEPATH)/$$example/check_script >> check_script ; \
+	  $(EXECUTABLEPATH) -f check_script -x > result.raw 2> result.stderr ; \
+	  sed -n '$(SED_CMD)' result.raw > result.filtered ; \
+	  if diff result.filtered \
+		$(FULLEXAMPLEPATH)/$$example/check_result > result.differences ; \
+	  then \
+	    echo "passed" ; \
+	    rm result.differences ; \
+	  else \
+	    echo "failed (more checkresults/$$example/result.differences)" ; \
+	  fi ; \
+	done
+
+#	  egrep '$(KEY_WORDS)' result.raw > result.filtered ; \
+
+#----------------------------------------------------------------------
+# Rules that produce/delete the dependency file for every package
+#----------------------------------------------------------------------
+
+.PHONY : dependencies cleandependencies
+
+#:
+#: dependencies -- Create a list of dependency files.
+#:                 Useful when modifying header files.
+
+# Invoke the "dependency.make" Makefile on each package subdirectory,
+# passing the path, etc. to it.
+#
+# There's a strange feature in autoconf where lines of the form " VPATH="
+# are removed from the Makefile.  Thus, a flag is placed before the
+# VPATH= argument below.
+
+dependencies:
+ifneq ($(findstring <$(CC)>,<gcc> <g++> <icc> <icpc>),)
+	for pkg in $(PKGS) ; \
+	do \
+	  $(MAKE) --no-print-directory \
+		-f $(master_srcdir)/helpers/dependency.make \
+		CC="$(CC)" \
+		CFLAGS="$(CFLAGS)" VPATH="$(local_srcdir)/src/$$pkg" \
+		AC_FLAGS="$(AC_FLAGS)" \
+		INCLUDEDIRS="$(INCLUDEDIRS)" objectdir=$(objectdir) \
+		PKGNAME=$(local_srcdir)/src/$$pkg/$$pkg \
+		$(local_srcdir)/src/$$pkg/$$pkg.d ; \
+	done
+else
+	@echo "dependency requires gcc, g++, icc, or icpc"
+	@echo "Reconfigure with gcc, g++, icc, or icpc"
+endif
+
+cleandependencies:
+	rm -f $(local_srcdir)/src/*/*.d
+
+#----------------------------------------------------------------------
+# Rules for making a distribution file
+#----------------------------------------------------------------------
+
+.PHONY : dist
+
+#:
+#: dist -- Create a tarred, gzipped distribution file
+
+# Warning: "tar" under Digital Unix (on DEC Alphas) writes directories
+# that don't work under SunOS tar
+
+dist : $(DISTRIBUTION).tar.gz
+
+$(DISTRIBUTION).tar.gz : $(DISTFILES)
+ifeq ($(strip $(FULL_MISSING_PKGS)),)
+	rm -rf $(DISTRIBUTION)
+	umask 022; mkdir $(DISTRIBUTION)
+	for dir in $(DISTDIRS); \
+	do \
+	  umask 022; mkdir $(DISTRIBUTION)/$$dir; \
+	done
+	@echo "Copying distribution files"
+	@for file in $(patsubst $(local_srcdir)/%, %, $^); \
+	do \
+	  echo "  $$file"; \
+	  cp -p $(local_srcdir)/$$file $(DISTRIBUTION)/$$file; \
+	done
+	- chmod -R a+r $(DISTRIBUTION)
+	- chmod -R u+w $(DISTRIBUTION)
+	tar cf - $(DISTRIBUTION) | gzip -9 > $(DISTRIBUTION).tar.gz
+	rm -rf $(DISTRIBUTION)
+else
+	@echo "Missing packages: $(FULL_MISSING_PKGS)"
+	@echo "Make sure PKGS lists all the packages"
+	@exit 1
+endif
+
+#----------------------------------------------------------------------
+# Rules for rebuilding the configure file and Makefile
+#----------------------------------------------------------------------
+
+${master_srcdir}/configure : configure.in
+	cd ${master_srcdir} && autoconf
+	chmod 0775 ${master_srcdir}/config*
+
+config.status : configure
+	./config.status --recheck
+
+Makefile : Makefile.in config.status
+	@echo "The master Makefile.in has been changed:"
+	@echo "run config.status"
+	@echo "Warning: This will overwrite any local Makefile modifications"
+	@exit 1
+
+#----------------------------------------------------------------------
+# Rules for cleaning
+#----------------------------------------------------------------------
+
+.PHONY : clean mostlyclean distclean
+
+#:
+#: clean -- Remove every file created by building
+
+clean mostlyclean :
+	rm -rf $(objectdir)/* $(LIBRARY) $(PRODUCT) \
+		$(foreach bddpkg, $(BDDPKGS), $(PRODUCT)-$(bddpkg)) \
+		checkresults include
+
+#: distclean -- Remove every file created by building or configuring
+
+distclean : clean cleandependencies
+	rm -f Makefile config.status config.cache config.log
+
+#----------------------------------------------------------------------
+# Rule for performing a lint-like check on the source code
+#
+# Note: This requires gcc or g++
+#----------------------------------------------------------------------
+
+.PHONY : check-code
+
+#:
+#: check-code -- Run a lint-like check on the source code.
+#:               (useful for development)
+
+CHECK_FLAGS := -Wall -pedantic -DBDD$(BDDPKG)
+ifeq ($(CC),gcc)
+  CHECK_FLAGS += -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations
+endif
+
+check-code : $(CSRC) $(BDD_CSRC) $(MDD_CSRC)
+ifneq ($(findstring <$(CC)>,<gcc> <g++>),)
+	@rm -f *.o_checkcode
+	@for file in $^; \
+	do \
+	  echo "------------------------ Checking $$file"; \
+	  $(CC) -c $(CFLAGS) $(AC_FLAGS) $(CHECK_FLAGS) \
+		$(VERDATE) $(INCLUDEDIRS) \
+		-o $(objectdir)/checkcode_output.o $$file; \
+	  rm -f $(objectdir)/checkcode_output.o; \
+	done
+	@rm -f *.o_checkcode
+else
+	@echo "check-code requires gcc or g++"
+	@echo "Reconfigure with gcc or g++"
+endif
+
+#----------------------------------------------------------------------
+# Rule for generating function prototypes for all the
+# source and header files in all the PKGS
+#
+# Note: This requires "extproto," part of the ext package available from
+# ftp://ic.eecs.berkeley.edu/pub/Ext
+#----------------------------------------------------------------------
+
+.PHONY : proto
+
+#:
+#: proto -- Regenerate all the function prototypes in the packages
+#:	    Useful during development.  You may want to invoke it with
+#:	      gmake "PKGS=tst tbl" proto
+
+proto :
+	@cd $(local_srcdir)/src ; \
+	for pkg in $(PKGS); \
+	do \
+	  cd $$pkg ; \
+	  extproto *.h *.c ; \
+	  cd .. ; \
+	done
+
+#----------------------------------------------------------------------
+# Rules for generating the documentation and command help files
+# for all the packages
+#
+# Note: This requires "extdoc," part of the ext package, and
+# lynx, a textual WWW browser
+#----------------------------------------------------------------------
+
+.PHONY : allDoc doc indices helpfiles cleandoc
+
+#:
+#: allDoc -- Extract all the documentation (runs doc, indices, and helpfiles)
+
+allDoc : cleandoc doc indices helpfiles
+
+#: doc -- Extract HTML and text documentation on all the functions
+
+doc : $(htmldocdir) $(txtdocdir)
+	for pkg in $(PKGS); \
+	do \
+	  umask 2 ; extdoc --html=$(htmldocdir) --text=$(txtdocdir) \
+		$(local_srcdir)/src/$$pkg/$$pkg; \
+	done
+
+#: indices -- Generate function and command indices for the HTML documentation
+
+indices : $(htmldocdir)
+	umask 2 ; extindex $(htmldocdir)
+
+#: helpfiles -- Generate the help files from the HTML documentation
+
+helpfiles : $(helpdir)
+	for file in $(htmldocdir)/*Cmd.html ; \
+	do \
+	  echo Converting $$file ; \
+	  umask 2 ; lynx -dump $$file > $(helpdir)/`basename $$file .html`.txt ; \
+	done
+
+#: cleandoc -- Remove all the documentation generated by "allDoc"
+
+cleandoc :
+	-rm -f $(htmldocdir)/*.html
+	-rm -f $(txtdocdir)/*.txt
+	-rm -f $(helpdir)/*Cmd.txt
+
+$(htmldocdir) :
+	- umask 2 ; mkdir $(htmldocdir)
+
+$(txtdocdir) :
+	- umask 2 ; mkdir $(txtdocdir)
+
+$(helpdir) :
+	- umask 2 ; mkdir $(helpdir)
+
+
+#----------------------------------------------------------------------
+# Revision control rules
+#
+# May be invoked with command-line overrides, e.g.,
+# gmake RCSFILES=foo.c rcs_co
+# gmake PKGS=array rcs_ci
+#----------------------------------------------------------------------
+
+.PHONY: rcs_ci rcs_co rcs_diff rcs_ident rcs_status
+
+#:
+#:       You may want to invoke the RCS rules with
+#:         gmake "PKGS=tst tbl" rcs_ci
+#:         gmake "RCSFILES=tstMain.c" rcs_co
+#:
+#: rcs_ci -- check in user-modified files and put an updated copy
+#:           in the central area
+
+rcs_ci: $(RCSFILES)
+	@for file in $(patsubst $(local_srcdir)/%, %, $^); \
+	do \
+	  ci -u $(RCSFLAGS) $(local_srcdir)/$$file $(rcs_rootdir)/$$file,v; \
+	  co -u $(RCSFLAGS) $(master_srcdir)/$$file $(rcs_rootdir)/$$file,v; \
+	done
+
+#: rcs_co -- check out files for modification
+
+rcs_co: $(RCSFILES)
+	@for file in $(patsubst $(local_srcdir)/%, %, $^); \
+	do \
+	  co -l $(RCSFLAGS) $(local_srcdir)/$$file $(rcs_rootdir)/$$file,v; \
+	done
+
+#: rcs_diff -- Report differences between local files and checked-in versions
+
+rcs_diff: $(RCSFILES)
+	@for file in $(patsubst $(local_srcdir)/%, %, $^); \
+	do \
+	  rcsdiff $(RCSFLAGS) $(local_srcdir)/$$file $(rcs_rootdir)/$$file,v; \
+	done
+
+#: rcs_ident -- Print the RCS identifier in each file
+
+rcs_ident: $(RCSFILES)
+	@for file in $(patsubst $(local_srcdir)/%, %, $^); \
+	do \
+	  ident $(RCSFLAGS) $(local_srcdir)/$$file; \
+	done
+
+#: rcs_status -- Report who has checked out files
+
+rcs_status: $(RCSFILES)
+	@for file in $(patsubst $(local_srcdir)/%, %, $^); \
+	do \
+	  rlog -L -h $(RCSFLAGS) $(rcs_rootdir)/$$file,v; \
+	done
+
+#----------------------------------------------------------------------
+# RCS rules for common/{Makefile.in, configure.in, localconfigure,
+# masterconfigure, mkinstalldirs, install-sh}
+#----------------------------------------------------------------------
+
+.PHONY : rcs_ci_misc rcs_co_misc rcs_diff_misc
+
+#: rcs_ci_misc -- Check in miscellaneous files, updating central area
+
+rcs_ci_misc: $(RCSMISCFILES)
+	@for file in $(patsubst $(local_srcdir)/%, %, $^); \
+	do \
+	  ci -u $(RCSFLAGS) $(local_srcdir)/$$file $(rcs_rootdir)/$$file,v; \
+	  co -u $(RCSFLAGS) $(master_srcdir)/$$file $(rcs_rootdir)/$$file,v; \
+	done
+
+#: rcs_co_misc -- Check out miscellaneous files
+
+rcs_co_misc: $(RCSMISCFILES)
+	@for file in $(patsubst $(local_srcdir)/%, %, $^); \
+	do \
+	  co -l $(RCSFLAGS) $(local_srcdir)/$$file $(rcs_rootdir)/$$file,v; \
+	done
+
+#: rcs_diff_misc -- Report differences in miscellaneous files
+
+rcs_diff_misc: $(RCSMISCFILES)
+	@for file in $(patsubst $(local_srcdir)/%, %, $^); \
+	do \
+	  rcsdiff $(RCSFLAGS) $(local_srcdir)/$$file $(rcs_rootdir)/$$file,v; \
+	done
+
+#: rcs_ident_misc -- Report RCS identifiers
+
+rcs_ident_misc: $(RCSMISCFILES)
+	@for file in $(patsubst $(local_srcdir)/%, %, $^); \
+	do \
+	  ident $(RCSFLAGS) $(local_srcdir)/$$file; \
+	done
+
+#: rcs_status_misc -- Report checked in/out status, ownership
+
+rcs_status_misc: $(RCSMISCFILES)
+	@for file in $(patsubst $(local_srcdir)/%, %, $^); \
+	do \
+	  rlog -L -h $(RCSFLAGS) $(rcs_rootdir)/$$file,v; \
+	done
+
+#----------------------------------------------------------------------
+# RCS rules for files in common/share
+#----------------------------------------------------------------------
+
+.PHONY : rcs_ci_share rcs_co_share rcs_diff_share
+
+#: rcs_ci_share -- Check in files in the share/ directory
+
+rcs_ci_share: $(RCSSHAREFILES)
+	@for file in $(patsubst $(local_srcdir)/%, %, $^); \
+	do \
+	  ci -u $(RCSFLAGS) $(local_srcdir)/$$file $(rcs_rootdir)/$$file,v; \
+	  co -u $(RCSFLAGS) $(master_srcdir)/$$file $(rcs_rootdir)/$$file,v; \
+	done
+
+#: rcs_co_share -- Check out share files
+
+rcs_co_share: $(RCSSHAREFILES)
+	@for file in $(patsubst $(local_srcdir)/%, %, $^); \
+	do \
+	  co -l $(RCSFLAGS) $(local_srcdir)/$$file $(rcs_rootdir)/$$file,v; \
+	done
+
+#: rcs_diff_share -- Report differences in share files
+
+rcs_diff_share: $(RCSSHAREFILES)
+	@for file in $(patsubst $(local_srcdir)/%, %, $^); \
+	do \
+	  rcsdiff $(RCSFLAGS) $(local_srcdir)/$$file $(rcs_rootdir)/$$file,v; \
+	done
+
+#: rcs_ident_share -- Report RCS identifiers
+
+rcs_ident_share: $(RCSSHAREFILES)
+	@for file in $(patsubst $(local_srcdir)/%, %, $^); \
+	do \
+	  ident $(RCSFLAGS) $(local_srcdir)/$$file; \
+	done
+
+#: rcs_status_share -- Report checked in/out status, ownership
+
+rcs_status_share: $(RCSSHAREFILES)
+	@for file in $(patsubst $(local_srcdir)/%, %, $^); \
+	do \
+	  rlog -L -h $(RCSFLAGS) $(rcs_rootdir)/$$file,v; \
+	done
+
+#----------------------------------------------------------------------
+# Rules for debugging the Makefile
+#----------------------------------------------------------------------
+
+.PHONY : debug-make
+
+DEBUG_VARS =	ALL_PKGS \
+		PKGS \
+		MISSING_PKGS \
+		VPATH \
+		INCLUDEDIRS \
+		CSRC \
+		OBJECTS \
+		HEADERS \
+		MAKEINCLUDES \
+		CFLAGS \
+		AC_FLAGS \
+		master_srcdir \
+		local_srcdir \
+		RCSFILES \
+		RCSDIR \
+		LIBS \
+		VISLIBS \
+		DISTFILES \
+		EXAMPLEFILES
+
+#:
+#: debug-make -- Print a list of Makefile variables
+
+debug-make:
+	@$(foreach var, $(DEBUG_VARS), echo $(var)=$($(var)) ; )
Index: vis_dev/vis-2.3/NEWS
===================================================================
--- vis_dev/vis-2.3/NEWS	(revision 14)
+++ vis_dev/vis-2.3/NEWS	(revision 14)
@@ -0,0 +1,1676 @@
+VIS NEWS					-*-indented-text-*-
+  History of user-visible changes.
+
+Please sent bug reports to vis-users@colorado.edu.  Please let us know what
+version of VIS you are running and what architecture you are running it on.
+
+======================================================================
+Version 2.3
+
+Release 2.3 of VIS improves VIS 2.2 in the following areas:
+
+* Builds with bison 2.4.1 and gcc 4.4.1
+
+* Supports cusp-1.1 as external SAT solver for bounded model checking
+  instead of zchaff
+
+* Bug fixes
+
+======================================================================
+
+Version 2.2
+
+Release 2.2 of VIS improves VIS 2.1 in the following areas:
+
+* Compiles with gcc 4.3 and bison 2.3
+* Supports both 64-bit and 32-bit compilation on x86_64 machines
+* Allows the use of up to 4 GB of memory with 32-bit pointers
+  (previously 2 GB)
+* improved vl2mv produces smaller blif-MV files
+* vl2mv 2.2 drops support of obsolete output formats (e.g., Shift)
+* Support for weak until operator in both CTL and LTL
+* Improved node matching for combinational equivalence (comb_verify)
+* Fixed bug in the translation of LTL properties to Buechi automata
+* New command write_network_blif_mv
+* faster flatten_hierarchy
+* new functions mdd_array_dump_dot mdd_array_print_cover make
+  debugging easier
+* CUDD 2.4.2
+* vis-verilog-models-1.2
+
+======================================================================
+
+Version 2.1
+
+Release 2.1 of VIS improves VIS 2.0 in the following areas:
+
+1. Revamped Bounded Model Checker with efficient termination criteria
+2. Grab and Puresat algorithms for invariant checking based on
+   abstraction refinement
+3. DnC algorithm for language emptiness check based on abstraction
+   refinement
+4. CirCUs SAT solver.
+5. Fate and Free Will algorithm for the analysis of counterexamples
+6. Vacuity detection for CTL
+7. Coverage estimation for CTL
+8. Far Side algorithm for image computation
+9. CUDD 2.4.1
+10. Miscellaneous
+
+
+Bounded Model Checking
+----------------------
+
+BMC in VIS 2.1 is much faster than it was in VIS 2.0.  The
+construction of the circuit data structure, the encoding of the
+property, the use of a faster SAT solver all have contributed to this
+improvement.
+
+BMC in VIS 2.1 can prove properties rather than just falsifying them.
+The following sequence of commands is used to perform bounded model
+checking with termination check:
+
+  read_blif_mv model.mv
+  flatten_hierarchy
+  build_partition_maigs
+  bounded_model_check -k 10 -r 2 model.ltl
+
+The termination check will be performed every other step.  The
+construction of the MDDs is not needed if termination check is needed
+for invariant properties only.  For details on the stopping criteria,
+see
+
+M. Awedh and F. Somenzi, "Proving More Properties with Bounded Model
+Checking," CAV 2004, pp. 96-108, LNCS 3114.
+
+Other new options to the bounded_model_check command allow one to
+control the formula encoding, the solver to be applied (CirCUs or
+zChaff) and, for the former, the incremental solving algorithm.
+
+A new command ltl2snf allows one to translate an LTL formula to
+separation normal form.
+
+
+Abstraction Refinement for Invariants
+-------------------------------------
+
+The check_invariant command allows the user the choice of one of two
+abstraction refinement algorithms for invariants.  The Grab algorithm 
+uses BDD-based model checking on the abstract model and SAT for
+counterexample concretization check.  Its refinement strategy is
+game-theoretic.  It is run as follows:
+
+  read_blif_mv model.mv
+  flatten_hierarchy
+  build_partition_maigs
+  check_invariant -A3 model.inv
+
+By default, grab enables dynamic variable reordering for the abstract
+model.  One can override this behavior by explicitly building
+partition MDDs.  For details of the algorithm, see
+
+C. Wang, B. Li, H. Jin, G. D. Hachtel, and F. Somenzi, "Improving
+Ariadne's Bundle by Following Multiple Threads in Abstraction
+Refinement," ICCAD 2003, pp. 408-415.
+
+The puresat algorithm uses SAT as the only decision procedure for both
+abstract and concrete model.  It analyzes the proofs of
+unsatisfiability to produce refinements.  It is invoked as follows:
+
+  read_blif_mv model.mv
+  flatten_hierarchy
+  build_partition_maigs
+  check_invariant -A4 model.inv
+
+The algorithm is described in
+
+B. Li, C. Wang, and F. Somenzi, "Abstraction Refinement in Symbolic
+Model Checking Using Satisfiability as the Only Decision Procedure,"
+STTT, vol.7, n. 2, pp. 143-155.
+
+
+Abstraction Refinement for Language Emptiness
+--------------------------------------------
+
+The lang_empty command has a new option that runs the "Divide and
+Compose" (DnC) algorithm described in
+
+C. Wang, R. Bloem, G. D. Hachtel, K. Ravi, and F. Somenzi, "Divide and
+Compose: SCC Refinement for Language Emptiness", CONCUR 2001,
+pp. 456-471, LNCS 2154.
+
+The algorithm, which is based on refinement of the strongly connected
+components of the model, is invoked as follows:
+
+  read_blif_mv model.mv
+  init_verify
+  lang_empty -A 1
+
+
+CirCUs SAT solver
+-----------------
+
+VIS 2.1 includes the SAT solver CirCUs, a short description of which
+can be found in
+
+H. Jin, M. Awedh, and F. Somenzi, "CirCUs: A Satisfiability Solver
+Geared Towards Bounded Model Checking," CAV 2004, pp. 519-522, LNCS
+3114.
+
+CirCUs is an incremental SAT solver that accepts input in either
+circuit or CNF form.  It is the default solver for bounded model
+checking and abstraction refinement algorithms.  It can also be
+invoked from the VIS prompt as a stand-alone CNF SAT solver on a set
+of clauses described in DIMACS format:
+
+  cnf_sat input.cnf
+
+
+Fate and Free Will Algorithm
+----------------------------
+
+The counterexamples produced by model_check and check_invariant can be
+optionally generated with the Fate and Free Will algorithm of
+
+H. Jin, K. Ravi, and F. Somenzi, "Fate and Free Will in Error Traces,"
+STTT, vol. 6, n. 2, pp. 102-116.
+
+This algorithm is only available when vis is linked with the cu BDD
+package.  It assumes a partition of the inputs into variables
+controlled by the environment and variables controlled by the system,
+and divides a counterexample into fated and free segments.  In a fated
+segment, the values of the variables controlled by the environment
+suffice to impose progress toward violation of the property.  In a
+free segment, the other variables are also required.
+
+To run the Fate and Free Will algorithm, one prepares a file with the
+inputs that the system controls.  For a failing invariant, the
+invocation is like this:
+
+  read_blif_mv model.mv
+  init_verify
+  check_invariant -d1 -i -w system_inputs
+
+The last command is replaced by
+
+  model_check -d2 -i -w system_inputs
+
+for a CTL property.  The -W option can be used to assign all inputs to
+the system, while the -G option invokes a variant of the algorithm.
+
+
+Vacuity Detection for CTL
+-------------------------
+
+VIS 2.1 implements two algorithms for the detection of vacuity in CTL
+model checking.  A formula passes vacuously if it can be strengthened
+by replacement of one of its subformulae with "bottom" and still pass.
+Likewise, a formula fails vacuously if it can be weakened by
+replacement of one of its subformulae with "top" and still fail.
+
+The algorithm of Beer et al. (CAV 97) is invoked with the -B option as
+follows:
+
+  read_blif_mv model.mv
+  init_verify
+  model_check -B model.ctl
+
+This algorithm applies to a subset of ACTL and considers only passing
+properties.  If an error trace is requested with -d, in case of
+vacuous pass, an interesting witness is produced.
+
+The second algorithm for vacuity detection is an extension of the one
+describe in
+
+M. Purandare and F. Somenzi, "Vacuum Cleaning CTL Formulae," CAV 2002,
+pp. 485-499, LNCS 2404.
+
+This algorithm applies a thorough vacuity detection to all of CTL and
+to both passing and failing properties.  With -d, it produces
+interesting witnesses for passing properties and interesting
+counterexamples for failing ones.
+
+The current implementation is limited in its treatment of the
+operators <-> (equivalence) and ^ (exclusive or).
+
+
+Coverage Estimation for CTL
+---------------------------
+
+VIS 2.1 provides two algorithms for coverage estimation in CTL model
+checking.  Both are invoked with options passed to the model_check
+command.
+
+The first algorithm is the one of Hoskote et al. (DAC 1999).  It
+applies to a subset of ACTL.  The option is -C.  The second algorithm
+is an improved version of the same described in
+
+N. Jayakumar, M. Purandare, and F. Somenzi, "Dos and Don'ts of CTL
+State Coverage Estimation," DAC 2003, pp. 292-295.
+
+To invoke the improved coverage estimation algorithm one writes:
+
+  read_blif_mv model.mv
+  init_verify
+  model_check -I model.ctl
+
+
+Far Side Algorithm for Image Computation
+----------------------------------------
+
+By setting image_farside_method to 1, a user of VIS 2.1 can invoke the
+Far Side approach to image computation which applies a compositional
+method based on don't cares to speed up reachability analysis.  The
+algorithm is described in
+
+C. Wang, G. D. Hachtel, and F. Somenzi, "The Compositional Far Side of
+Image Computation," ICCAD 2003, pp. 334-340.
+
+See the documentation of the "set" command for the details.
+
+
+CUDD 2.4.1
+----------
+
+VIS-2.0 includes CUDD 2.4.1.  Compared to the version that was
+included in VIS-2.0, the new version has faster grabage collection,
+provides improved support for C++ compilation, contains a number of
+bug fixes and several new functions, including functions for the
+manipulation of prime implicants of a function.
+
+
+Miscellaneous
+-------------
+
+* Glu and vis can be built using g++ as compiler by configuring as
+  follows:
+
+  ./configure --enable-gcc=g++
+
+* The code in glu has gone through another round of rejuvenation.
+  This process allows vis to be built with recent versions of gcc (3.3
+  and later) without producing any type-punning warning.
+
+* Two bugs have been fixed in early termination detection in CTL model
+  checking.
+
+* A bug has been fixed in the treatment of multi-valued inputs.
+
+* Vis no longer crashes when compute_reach is invoked with the -i
+  option.
+
+* Timeout values for model_check, check_invariant, and lang_empty are
+  now in CPU time instead of elapsed time.  This is beneficial when
+  running regression tests in the presence of other processes.
+
+* The ctime command is no longer supported.
+
+
+======================================================================
+
+Version 2.0
+
+Release 2.0 of VIS improves VIS 1.4 in the following areas:
+
+1. LTL model checking
+2. SAT-based Bounded Model Checking (BMC)
+3. Minimum Lifetime Permutation (MLP) algorithm for conjuction scheduling
+4. Generalized SCC Hull (GSH) algorithm for greatest fixpoint
+   computation
+5. Lockstep algorithm for language emptiness
+6. Built-in regression test facility
+7. CUDD 2.3.2
+8. Miscellaneous
+
+
+LTL model checking
+------------------
+
+VIS-2.0 has a new command ltl_model_check that model checks LTL
+formulae.  The syntax for LTL is quite similar to that used for CTL.
+Another new command, ltl_to_aut, translates LTL formulae into Buechi
+automata.
+
+
+SAT-Based Bounded Model Checking
+--------------------------------
+
+VIS-2.0 has a new command bounded_model_check for bounded LTL model
+checking.  The SAT solver zchaff (http://www.ee.princeton.edu/~chaff/)
+must be in the executable path for this command to work.  The following
+sequence of commands is used to perform bounded model checking:
+
+  read_blif_mv model.mv
+  flatten_hierarchy
+  build_partition_maigs
+  bounded_model_check -k 10 model.ltl
+
+where "-k 10" specifies the bound on the length of the counterexample.
+
+
+Minimum Lifetime Permutation (MLP) Algorithm for Conjuction Scheduling
+----------------------------------------------------------------------
+
+The MLP algorithm can considerably speed up image computations.  It is
+selected by typing
+
+  set image_method mlp
+
+For details on the algorithm, see
+
+I-H. Moon, G. D. Hachtel, and F. Somenzi, "Border-Block Triangular
+Form and Conjunction Schedule in Image Computation," FMCAD 2000,
+pp. 73-90, LNCS 1954.
+
+
+Generalized SCC Hull (GSH) Algorithm for Greatest Fixpoint Computation
+----------------------------------------------------------------------
+
+The commands model_check, ltl_model_check, and lang_empty use a new
+algorithm for greatest fixpoint computations.  This algorithm has
+different "schedules" that can be controlled with the -S option.  For
+details on the algorithm, see
+
+K. Ravi, R. Bloem, and F. Somenzi, "A Comparative Study of Symbolic
+Algorithms for the Computation of Fair Cycles," FMCAD 2000,
+pp. 143-160, LNCS 1954.
+
+F. Somenzi, K. Ravi, and R. Bloem, "Analysis of Symbolic {SCC} Hull
+Algorithms," FMCAD 2002, To appear.
+
+
+Lockstep Algorithm for Language Emptiness
+-----------------------------------------
+
+In VIS-2.0, the commands ltl_model_check and lang_empty can use the
+lockstep algorithm to perform the language emptiness check.  The use
+of the lockstep algorithm as an alternative to the GSH algorithm is
+controlled by the -L option.  For details of Lockstep, see
+
+R. Bloem, H. N. Gabow, and F. Somenzi, "An Algorithm for Strongly
+Connected Component Analysis in n log n Symbolic Steps," FMCAD 2000,
+pp. 37-54, LNCS 1954.
+
+
+Built-in Regression Test Facility
+---------------------------------
+
+VIS-2.0 has a new command regression_test which allows users to
+compare runs of two different versions of vis, or runs with different
+options.
+
+
+CUDD 2.3.2
+----------
+
+VIS-2.0 includes CUDD 2.3.2.  Compared to the version that was
+included in VIS-1.4, the new version contains a number of bug fixes
+and several new functions.
+
+In particular, there is a new function that will compute the AND of
+two BDDs only if the result does not require the creation of too many
+nodes.  This function is used by VIS-2.0 to make clustering of the
+transition relation more robust.
+
+
+Miscellaneous
+-------------
+
+* Improved counterexample generation in model_check with -d3 and -d4.
+
+* Changes in verbosity level (-v option) of model_check.  The new
+  verbosity levels are:
+  -v0: unchanged (minimum verbosity)
+  -v1: essential statistics (new)
+  -v2: equivalent to the old -v1
+  -v3: equivalent to the old -v2
+
+* Fixed bug and extended early termination detection in CTL model
+  checking.
+
+* Fixed bug in guided search for CTL model checking which affected
+  counterexample generation with global hints.
+
+* Vis no longer crashes when a directory name is specified in a
+  command line instead of a regular file name.
+
+* Fixed several bugs in approximate_model_check,
+  incremental_ctl_verification, and iterative_model_check.
+
+* The code in glu has been substantially rejuvenated.
+
+======================================================================
+
+Version 1.4
+
+Release 1.4 of VIS improves VIS 1.3 in the following areas:
+
+ 1. Hybrid Image Computation
+ 2. Guided Search for Reachability Analysis and Invariant Checking
+ 3. Guided Search for CTL Model Checking
+ 4. Least Fix-point Machine-By-Machine Approximate FSM Traversal (LMBM)
+ 5. Iterative Abstraction-based Model Checking (IMC)
+ 6. Lazy Sifting
+ 7. SPFD-based Placement and Logic Optimization 
+ 8. Truesim
+ 9. Arithmetic Functions with Extended Double Precision (EPD)
+10. CUDD 2.3.1
+11. Miscellaneous
+
+
+1. Hybrid Image Computation
+---------------------------
+Image computation is the key step in fix-point computation.
+Traditionally two techniques have been used: The transition relation
+method is based on conjunction of a partitioned transition relation,
+whereas the transition function method is based on splitting on an
+input or output variable recursively.
+
+The hybrid method chooses either splitting or conjunction at each
+recursion dynamically using the dependence matrix.  This hybrid
+approach combines, in a unified framework, conjunction, input and
+output splitting, and a host of auxiliary techniques that can
+significantly speed up the computation. See: I.-H. Moon, J.H. Kukula,
+K. Ravi, F. Somenzi, "To Split or to Conjoin: The Question in Image
+Computation", Proceedings of the Design Automation Conference (DAC),
+pages 73-90, 2000.
+
+Also, the transition function method is implemented as a part of the
+hybrid computation.  The transition function method itself can be used
+as an independent image method.  However, we do not recommend to use
+this method in general cases, even though it may work well for
+approximate reachability analysis.  The implementation of the
+transition function method is basically for experimental purposes.
+
+** Usage:
+    set image_method hybrid
+    set image_method tfm
+
+Also refer to: print_hybrid_options and print_tfm_options
+
+
+2. Guided Search for Reachability Analysis
+------------------------------------------
+VIS-1.4 introduces the use of hints to guide the exploration of the
+state space.  This may result in orders-of-magnitude reductions in
+time and space requirements.  Good hints can often be found with the
+help of simple heuristics by someone who understands the circuit well
+enough to devise simulation stimuli or verification properties for it.
+Hints are applied by constraining the transition relation of the
+system to be verified.  They specify possible values for (subsets of)
+the primary inputs and state variables.  The constrained traversal of
+the state space may proceed much faster than the standard
+breadth-first search, because the traversal with hints is designed to
+produce smaller BDDs.  Once all states reachable following the hints
+have been visited, the system is unconstrained and reachability
+analysis proceeds on the original system.  Given enough resources, the
+algorithm will therefore search all reachable states, unless a state
+that violates the invariant is found.  See: K. Ravi, F. Somenzi,
+"Hints to accelerate Symbolic Traversal", Correct Hardware Design and
+Verification Methods (CHARME), pages 250-264, 1999.
+
+** Usage:
+    compute_reach -g <HintsFileName> : guided symbolic state space 
+                                       traverse
+    check_invariant -g <HintsFileName> : guided search for invariant
+                                         checking
+
+The file HintsFileName contains a series of hints.  A hint is a
+formula that does not contain any temporal operators, so hints_file
+has the same syntax as a file of invariants used for check_invariant.
+
+Also refer to: model_check -g <HintsFileName>
+
+
+3. Guided Search for CTL Model Checking
+---------------------------------------
+Guided Search for CTL is an extension of Guided Search for
+reachability.  It works much along the same lines, and has the same
+benefits.  There are a few differences.  First, for greatest fixpoints
+(EG, AU, and AF), it uses overapproximations of the transition
+relation, instead of underapproximations.  Second, there is a
+distinction between local and global hints.  Local hints are the
+default.  They can be used for any kind of CTL formula, and will apply
+all hints to a subformula before moving up in the parse tree.  Global
+hints are only applicable to ACTL and ECTL formulae, and evaluate the
+entire formula once for every hint.  See: R. Bloem, K. Ravi, and
+F. Somenzi, "Symbolic Guided Search for CTL Model Checking",
+Proceedings of the Design Automation Conference (DAC), pages 29-34,
+2000.
+
+** usage:
+    model_check -g HintsFileName : perform model check guided by the
+                                   hints specified in HintsFileName
+ 
+Also refer to: compute_reach -g <HintsFileName>
+               check_invariant -g <HintsFileName>
+
+
+4. Least Fix-point Machine-By-Machine Approximate FSM Traversal (LMBM)
+----------------------------------------------------------------------
+The knowledge of the reachable states of a sequential circuit can
+dramatically speed up optimization and model checking.  Since exact
+reachability may be intractable, approximate techniques are often
+preferable.  Least Fix-point MBM (LMBM) method is such a technique.
+It is as efficient as MBM, but provably more accurate.  LMBM can
+compute RFBF-quality approximations for all the large ISCAS-89
+benchmark circuit in a total of less than 9000 seconds.  For more
+information, see: I.-H. Moon, J. Kukula, T. Shiple, F. Somenzi, "Least
+Fixpoint Approximation for Reachability Analysis," International
+Conference on Computer-Aided Design (ICCAD), pages 41-44, 1999.
+
+** Usage:
+    set ardc_traversal_method 4: LMBM(least fix-point MBM, default)
+                                 is selected for ARDC
+    set ardc_traversal_method 5: TLMBM(combination of LMBM and TFBF)
+                                 is selected for ARDC
+    model_check -D 3           : model checking with ARDCs
+    compute_reach -A 2         : compute over-approximate reachable
+                                 states
+    compute_reach -D           : compute exact reachable states with
+                                 the help of ARDCs
+    check_invariant -D         : check invariants with the help of
+                                 ARDCs
+    synthesize_network -r 3    : synthesize sequential network
+                                 with ARDCs
+             
+Also refer to:  print_ardc_options
+
+
+5. Iterative Abstraction-Based Model Checking (IMC)
+---------------------------------------------------
+VIS-1.4 introduces an automatic abstraction/refinement algorithm for
+symbolic CTL model checking.  This algorithm supports full CTL
+language without fairness constraints.  The algorithm begins with
+initial upper- and/or lower-bound approximations that include some
+exact sub-transition relations of a determined set of latches for a
+given CTL formula.  As long as a conclusive verification decision
+can't be reached due to potentially false positives and negatives, the
+system is refined.  Two refinement methods are implemented: Latch Name
+Sorting and Latch Affinity Scheduling.  For more information, See:
+J.-Y. Jang, I.-H. Moon, G.D. Hachtel, "Iterative Abstraction-based CTL
+Model Checking," Design Automation and Test in Europe (DATE), pages
+502-507, 2000.  IMC supersedes the AMC package, which may disappear in
+future releases.
+
+** Usage:
+    iterative_model_check -i 8 : iterative model checking with 
+                                 incremental refinement step set 
+                                 to 8 latches
+    iterative_model_check -r 0 : iterative model checking using 
+                                 Latch Name Sorting refinement 
+                                 scheduling     
+    iterative_model_check -g 1 : iterative model checking using 
+                                 Positive Operational Graph only
+
+Also refer to: model_check, approximate_model_check,
+incremental_ctl_verification
+
+
+6. Lazy Sifting
+---------------
+Lazy sifting is a new variable reordering option that is specifically
+designed for sequential verification with the transition relation
+method (i.e., IWLS95 in VIS).  Lazy sifting groups together
+corresponding present state and next state variables only when it
+expects the grouping to be beneficial.  See: H. Higuchi and
+F. Somenzi, "Lazy Group Sifting for Efficient Symbolic State Traversal
+of FSMs," Proceedings of the International Conference on
+Computer-Aided Design (ICCAD), pages 45-49, 1999.
+
+** Usage:
+   dynamic_var_ordering -e lazy_sift
+
+
+7. SPFD-based placement and logic optimization
+----------------------------------------------
+This is an algorithm based on Sets of Pairs of Functions to be
+Distinguished (SPFDs) that combines logic and placement optimization
+of combinational circuits mapped to LUT-based Field-Programmable Gate
+Arrays to improve circuit area and speed.  The flexibilities in the
+circuit are represented by SPFDs.  The package contains two commands:
+spfd_pilo - perform SPFD-based placement-independent logic optimization;
+and spfd_pdlo - simultaneous placement and logic optimization.
+
+spfd_pilo performs SPFD-based wire and node removal/replacement and
+reprogramming of combinational circuits mapped to LUT-based FPGAs to
+reduce the number of wires and nodes in the circuit.  Instead of
+computing the flexibilities for every node in the network at once, the
+algorithm computes the flexibilities for one `cluster' at a time.
+Working with clusters allows us to avoid the BDD explosion problem and
+hence handle large circuits.  The SPFDs are computed for the cluster
+and the cluster nodes are reprogrammed based on the flexibility
+derived.  Switching activity (computed via simulation of user specified bit
+vectors or randomly generated bit vectors) is used to drive the choice
+of alternate function to be implemented at the node, in such a way that
+the total switching activity in the circuit is minimized. In the absence
+of bit vectors, an arbitrary implementation for a node is chosen from
+the bounds represented by SPFDs.
+
+The command spfd_pdlo implements a technique that tightly links the
+logic and placement optimization steps.  The algorithm is based on
+simulated annealing.  Two types of moves (directed towards global
+reduction in the cost function of total wire length), are performed:
+(1) wire removal/replacement, and (2) swapping of a pair of blocks in
+the FPGA.  Feedback from placement is valuable in making informed
+choice of a target wire during logic optimization moves.  This command
+produces a placement file which is used by VPR for routing. spfd_pdlo
+can be used only if VIS is linked with VPR 4.22, an
+FPGA place and route tool from the University of Toronto
+(http://www.eecg.toronto.edu/~vaughn/vpr/vpr.html). VPack, a tool to
+convert circuits (mapped to FPGA blocks) in .BLIF format to the .net
+format (used by VPR), is also needed.
+
+Please contact Balakrishna Kumthekar (kumtheka@avanticorp.com) for details 
+on integrating VPR with VIS.
+
+See: B. Kumthekar and F. Somenzi, "Power and Delay Reduction via
+Simultaneous Logic and Placement Optimization in FPGAs," Design
+Automation and Test in Europe (DATE), pages 202-207, 2000.
+
+** usage:
+     spfd_pilo -D <depth> : sets the cluster depth for SPFD
+			    computation. 
+     spfd_pilo -f <file>  : use simulation vectors from specified
+			    file. These vectors are used to compute 
+			    switching activity of nodes in the circuit.
+     spfd_pilo -S <method-number> : selects one of several methods to
+			    choose the node to be optimized.
+     spfd_pilo -m <method-number> : selects the heuristic to use in
+			    optimizing a selected node.
+
+     See 'help spfd_pilo' and 'help spfd_pdlo' for various options. 
+
+8. Truesim
+----------
+Simulates a network with a set of input vectors. Before calling this
+command, the user should create a partition (using the command
+build_partition_mdds). The simulation vectors can be provided by the
+user (using -f vectors_file), or generated randomly. When -d option is
+used, it performs event-driven true delay simulation. The fanout count
+of the nodes is used as an estimate for the node delay. Primary inputs
+are assumed to have arrival times of zero. 
+
+9. Arithmetic Functions with extended double precision (EPD)
+------------------------------------------------------------
+This is an arithmetic function package for extended double precision
+format floating-point numbers.  It supports the IEEE-754 double
+(64-bit) precision floating-point number format: both the big_endian
+and the little_endian.  The range is from 2.2631E-4932 to
+1.1897E+4932.  This package is used internally to provide fast and
+accurate counting of the states in large FSMs like those encountered
+in approximate reachability analysis.
+
+10. New version of the CUDD package.
+----------------------------------- 
+VIS-1.4 includes CUDD 2.3.1.  Compared to the version that was
+included in VIS-1.3, the new version contains a number of bug fixes
+and several new functions.
+
+* Miscellaneous
+---------------
+
+** One bug in the CAL package has been fixed.  It affected platforms without
+the valloc function.
+
+** Changes in supported platforms.  Support for SunOS 5.8 (Solaris
+2.8) on the Intel x86 platform has been added.  Ultrix and SunOs 4 are
+no longer supported.
+
+** Change of Verbosity level for debugging in model_check
+Debugging refers to the printing of an error-trace when a formula
+fails.  The new debug levels are:
+-d0: no debugging (the old -d0)
+-d1: minimal debugging, with less verbosity than the old -d1 had
+-d2: minimal debugging with more verbosity (the old -d1)
+-d3: recursive debugging (the old -d2)
+-d4: interactive debugging (the old -d3)
+
+** Early termination in Model Checking.  In limited cases, VIS will
+terminate a model checking run before reaching a fixpoint.  This may
+lead to a speedup.
+
+** The set of fair states is not computed of there are no fairness
+constraints.  This may lead to a speedup of the model_check command.
+
+** Perl Script for pretty printing counter-examples.  The Perl script
+visdbgpp, contributed by Toshi Isogai, can be run on counterexamples
+produced by vis to improve their readability.  In particular, the
+script collects the bits of vectors and displays them on a single
+line.
+
+** Counterexample generation.  The states on an error trace now lie
+closer together, which means that, on average, fewer signal
+transitions will occur.
+
+** Variable reordering.  In flatten_hierarchy In VIS-1.4, variable
+reordering is invoked automatically during flatten_hierarchy.
+
+** Changes of passing BDD cube arguments in VIS to CUDD.  Some
+arguments in the CUDD functions are BDD cubes that are generated by
+the conjunctions of BDD variables on demand.  VIS-1.4 pre-builds some
+BDD cubes that do not change, such as for present state variables,
+next state variables, and primary input variables.  This speeds up
+significantly large runs, especially for approximate reachability
+analysis.
+
+
+============================================================
+
+Version 1.3
+
+* Introduction
+
+Release 1.3 of VIS improves VIS 1.2 in the following areas:
+
+** Approximate Reachability Don't Cares (ARDCs)
+** High Density Reachability Analysis.
+** On-the-Fly Invariant Checking.
+** Seeding Reachability Analysis via Simulation
+** Forward Model Checking
+** Abstraction-refinement based Incremental CTL Verification
+** Synthesis
+** State Transition Graph Restructuring for Low Power
+** Miscellaneous
+
+* Approximate Reachability Don't Cares (ARDCs)
+
+VIS-1.3 includes the use of ARDCs in model checking and reachability
+analysis. The power of using reachable states as a care set (RDCs) is
+well known; however, computing reachable states exactly is intractable
+in many large designs.  ARDCs are an overapproximation of the
+reachable states, which are then used as the care set.  Computing
+ARDCs is much cheaper than computing RDCs while their effectiveness in
+speeding up model checking is comparable to that of RDCs.  Therefore,
+ARDCs are good for large designs, especially those in which exact
+reachability analysis is intractable.  See: I.-H. Moon, J.-Y. Jang,
+G. D. Hachtel, F. Somenzi, "Approximate reachability don't cares for
+CTL model checking", ICCAD'98.
+
+** Usage:
+           model_check -D 3    : model checking with ARDCs
+           compute_reach -A 2  : compute over-approximate reachable
+                                 states 
+	   compute_reach -D    : compute exact reachable states with 
+                                 the help of ARDCs
+           check_invariant -D  : check invariants with the help of
+                                 ARDCs 
+	   synthesize_network -r 3 : synthesize sequential network
+                                     with ARDCs 
+
+Also refer to: print_ardc_options
+
+
+* High Density Reachability Analysis (HD)
+
+HD is an alternate approach to performing exact reachability
+analysis.  Using BDD subsetting techniques, the HD method tries to keep
+the sizes of the BDDs small during the traversal.  This is intended to
+keep the memory occupation under control as well as make the traversal
+more efficient by manipulating smaller BDDs.
+
+On large circuits, for which the default (breadth-first search) method
+does not complete, HD is likely to find many more reachable states.
+This is useful in invariant checking.
+For mid-size circuits, HD is sometimes faster in completing
+reachability analysis, but for smaller circuits, HD may result in too
+much overhead.  It is recommended to use this option when the default
+method for reachability analysis fails (runs out of memory or takes
+very long).  Refer to Ravi and Somenzi, "High-density reachability
+analysis", ICCAD'95.
+
+HD analysis only works with the CUDD package.
+ 
+** Usage:
+           compute_reach -A 1: reachability analysis with HD approach.
+
+Also refer to: print_hd_options
+
+
+* On-the-Fly Invariant Checking 
+
+Checking invariants is done by performing reachability analysis and
+checking if all invariants hold in the reachable states.  VIS-1.3
+does invariant checking during reachability computation (on-the-fly
+verification).  Invariants that fail are reported early, along with the
+counter examples if requested.
+
+Since reachability analysis can be expensive, one may use HD in
+invariant checking.  For circuits on which the default reachability
+analysis runs out of resources, HD will typically explore more
+reachable states, and more invariants may prove false.  However, the
+counter examples provided by using HD may not be of shortest length.
+
+HD invariant checking only works with the CUDD package.
+
+** Usage:
+           check_invariant -A 1 : check_invariant where HD is used for
+				  reachability analysis
+
+One may also start with an overapproximation of the reachable
+states.  In this case, if all invariants hold on the overapproximation,
+verification is successfully completed.  If not, the algorithm will
+compute the exact reachable states as before, and check the
+invariants that failed with the overapproximation.
+
+** Usage:
+           check_invariant -A 2 : check_invariant where over
+                                  approximation is used for reachability
+                                  analysis.
+
+* Seeding Reachability Analysis via Simulation
+
+A new option rch_simulate can be used to use simulation to augment the
+set of initial states for reachability analysis. The value of the
+variable is the number of random input vectors that are simulated. The
+states reached in this way are considered as initial
+states. Augmenting the set of initial states may sometimes lead to
+faster reachability analysis, or may sometimes lead to better
+underapproximations, when reachability analysis is not carried out to
+completion. The commands affected by this option are compute_reach and
+check_invariant.
+
+** Usage:
+	   set rch_simulate n : simulate n vectors prior to
+				reachability analysis
+
+
+* Forward Model Checking
+
+VIS-1.3 includes the capability of forward model checking based on
+H. Iwashita, T. Nakata, F. Hirose, "CTL model checking based on 
+forward state traversal", ICCAD'96.  Standard "backward" CTL model
+checking uses only preimage computations.  Forward model checking tries
+to use image computations in place of preimage computations as much as
+possible, because they are typically faster.
+According to our experiments, forward model checking gives drastic
+performance improvement in many designs, but we have also seen many
+cases in which forward model checking does much worse.  Performance
+depends on the design.
+
+** Usage:
+           model_check -F  : model checking based on forward traversal
+
+
+* Incremental CTL Verification
+
+The command "incremental_ctl_verification" (aliased to "icv")
+performs verification of CTL formulas following the incremental
+paradigm described in A. Pardo, G. Hachtel, "Incremental CTL model
+checking using BDD subsetting", DAC'98.  The algorithm starts with an
+initial simple approximation of the verification and then proceeds at
+refining the different evaluations until the formula can be proved
+conclusively.  The approximation technique currently adopted makes use
+of BDD approximation techniques.  As implemented in release 1.3,
+incremental_ctl_verification supports fairness constraints, but tends
+to be less efficient than model_check when they are specified.
+
+Incremental verification works only with the CUDD package.
+
+** Usage:
+	   incremental_ctl_verification [options] ctl_file
+
+
+* Synthesis
+
+VIS 1.3 includes a new command "synthesize_network" (aliased to
+"synth") to transform both combinational and sequential circuits into
+multi-level boolean networks using symbolic factorization based on
+Zero-suppressed BDDs (ZDDs).  In the case of sequential circuits, only
+the combinational part of the circuit is synthesized: state encoding
+is not altered.  The emphasis of this algorithm is on the reduction of
+the number of literals in the factored form of the network.  The final
+multi-level circuit can be obtained in either the BLIF format or the
+equation format.  Designs described in BLIF or BLIF-MV format can be
+used as an input to this command.  However, multiple valued variables
+are not supported.  Hence, signals in the designs described in BLIF-MV
+need to be restricted to binary values.
+
+Synthesis can be used only when VIS is linked with the CUDD package.
+
+** Usage:
+	   synthesize_network [options]
+
+* STG Restructuring for Low Power 
+
+VIS-1.3 includes a new command "restruct_fsm".  This command
+implements a State Transition Graph (STG) restructuring algorithm
+that exploits the existence of equivalent states to decrease power
+dissipation, not necessarily by collapsing the equivalence states, but
+by redirecting transitions in the graph.  This algorithm is based on
+the monolithic transition relation.  The complexity of the algorithm
+in general increases with an increase in the size of the state
+transition graph, which depends on the number of state variables and
+primary inputs.  The algorithm can handle circuits described in both
+BLIF and BLIF-MV formats.  However, multi-valued variables are not
+supported.  Also, the final synthesized circuit (network implementation
+of the restructured STG) is available only in BLIF format.  The
+sequential circuit should have a single initial state.  For more
+details see, B. Kumthekar, I.-H. Moon, F. Somenzi, "A Symbolic
+Algorithm for Low-Power Sequential Synthesis", ISLPED 97.
+
+STG restructuring works only with the CUDD package.
+
+** Usage:
+	   restruct_fsm [options]
+
+* Miscellaneous
+
+** New versions of CUDD and CAL packages.
+VIS-1.3 includes CUDD 2.3.0 and CAL 2.0.1.  Compared to the versions
+that were included in VIS-1.2, the new packages have better
+performance and improved statistics reporting.
+
+** Changes in configure
+Configure now defaults to using 32-bit pointers on DEC Alpha machines.  
+To use 64-bit pointers, invoke "configure" with "--enable-64."
+
+** gmake check
+"gmake check" now consistently runs the local executable using the
+examples in the master source directory.  Previously, there were
+different versions for local-area and central-area checks.
+
+** Native Compiler.
+The configuration scripts now try to use the native C compiler (cc) by
+default.  The use of gcc can be forced by running configure with the
+option --enable-gcc.  On AIX and SunOS, however, only gcc is
+supported.
+
+As a result, the following configuration options have been removed
+
+    --with-comp-mode=solaris
+    --with-comp-mode=mips
+    --with-comp-mode=alpha32
+    --with-comp-mode=alpha64
+
+Configure now defaults to using 32-bit pointers on DEC Alpha machines.  
+To use 64-bit pointers, invoke "configure" with "--enable-64."
+
+** Changes in supported platforms.
+VIS-1.3 has been tested under IRIX 5.3 with both cc and gcc.
+VIS-1.3 has been tested under HP-UX with cc. (Previously only gcc was
+supported.)
+VIS-1.3 linked with the CAL BDD package currently does not work under
+CYGWIN32.  When the problems are fixed, we shall issue a patch.
+
+** Uniformity across platforms.
+VIS-1.3 provides enhanced architecture independence.  For the commands
+model_check, approximate_model_check, compute_reach,
+incremental_ctl_verification, check_invariant, and lang_empty, the runs
+will be exactly the same on every platform with the same memory limits.
+Previously, invocations of reordering, and hence BDD sizes could differ
+from platform to platform.
+
+** Changes to static_order.
+The static_order command has changed substantially.  For combinational
+circuits, VIS-1.2 and earlier releases effectively generated random
+orders regardless of the method specified by the user.  (Sequential
+circuits did not have this problem.) The randomness of the orders was
+due to a bug that has been fixed in VIS-1.3.  For all
+circuits---combinational and sequential---the default ordering method
+is a new algorithm called "interleave."  The new default method is
+substantially more memory efficient than the previous default method
+(merge_left).  The quality of the resulting orders is comparable.
+
+** New -v option for dynamic_var_ordering.
+The option -v 1 can be specified to cause VIS to write a one-line
+message whenever dynamic reordering is executed.  The message reports
+the reduction in BDD or ZDD size, and on the time taken by reordering.
+This option is only effective with CUDD.
+
+** New -i option for comb_verify and seq_verify.
+It is now possible to print statistics on BDD usage and performance
+when running combinational or sequential verification.  This is done
+by specifying the -i option for comb_verify and seq_verify.  It is
+important to notice that these two commands use a local BDD manager,
+which is destroyed before control is returned to the user.  It is not
+therefore possible to use print_bdd_stats to inspect the statistics of
+the BDD package when invoking either of the two commands.
+
+** Default method for build_partition_mdds changed to inout.
+The default method has been changed to inout, because this has been
+found to produce better results than frontier in many cases.  The
+frontier method can build the partition MDDs in more cases than the
+inout method; the latter, however, tends to give better performance
+during model checking.
+
+** set ctl_change_bracket [yes/no]
+VIS-1.3 includes this set command option for the CTL parser.  VL2MV
+automatically converts "[]" to "<>" in node names, therefore the CTL
+parser does the same thing.  However, in some cases a user does not
+want to change bracket type in the CTL formulas.  This can be
+accomplished by setting this set command option to "no."  The default
+is "yes". The commands affected are check_invariant, model_check,
+approximate_model_check, and incremental_ctl_verification.
+
+** Printing time for model checking
+VIS-1.3 includes printing time for model checking.  If verbosity is set on,
+then the model checking time for both each formula and total will be printed
+out.
+
+** Incremental reachability analysis and invariant checking.
+In VIS-1.3 it is possible to perform reachability analysis
+incrementally.  The -d option of compute_reach specifies how many
+steps (image computations) should be performed at most before
+returning control to the user.  If compute_reach is invoked more than
+once with the -d option, each time reachability analysis starts from
+the previous result.  If check_invariant is invoked after
+compute_reach has been invoked with the -d option, the partial
+reachability results are used to speed up verification.
+
+** Completeness and determinism check in flatten_hierarchy
+The check for completeness and determinism performed by
+flatten_hierarchy that was previously optional is now always
+performed. The -b option to flatten_hierarchy and init_verify has no
+effect in VIS-1.3 and is retained for compatibility with existing
+scripts. It may disappear in future releases. Users of VIS-1.3 will
+observe modest increases in the time taken to flatten the
+hierarchy.
+
+
+
+Version 1.2
+
+* Introduction
+
+** Improvements
+
+*** Over 10x performance improvement in model checking for many  examples
+*** extended CTL syntax
+*** better access to the BDD parameters and statistics
+*** enhanced user interface
+*** improved portability and flexibility of configuration
+
+** New verification algorithms
+
+*** approximate_model_check: model checking of ACTL formulae for systems
+    that are too large for model_check
+*** res_verify: residue based verification of arithmetic circuits
+
+* Performance improvement in model checking
+
+** We have changed image computation (the underlying operation of
+   model checking) to make the best use of don't care sets. The don't
+   cares arise from unreachable states, and using them appropriately
+   reduces the BDD sizes significantly, leading to improved
+   performance of model checking. In addition, we have fixed a
+   performance bug that caused repeated computation of simplified
+   transition relations. We performed a performance comparison with
+   VIS 1.1 on a set of examples, and on some cases we observed more
+   than 30x performance improvement. In fact, on some examples VIS 1.2
+   could finish model checking in about 26 secs whereas VIS 1.1 took
+   about 2400 secs.
+
+** The model checking runs that use don't cares (-D option different
+   from 0) are those that benefit the most from the changes in VIS
+   1.2. In general it is not trivial to tell whether -D 1 or -D 0 will
+   produce the faster CPU time. An empirical approach consists of
+   running "compute_reach -t 300" (reachability for 5
+   minutes). Depending upon the progress in reachable state
+   computation, one can then invoke model checking with -D 0 or -D 1.
+
+* Approximate Model Checking
+
+** VIS 1.2 includes a new command approximate_model_check, a model
+   checker that performs ACTL model checking on an abstracted and
+   flattened network.  The command is designed to tackle the state
+   explosion problem we encounter when dealing with large and complex
+   circuits. Based on the initial size of the group (of latches), the
+   command constructs an over- or under-approximation of the
+   transition relation of the system. These approximations may not
+   contain every detail of the exact system. However they may contain
+   enough information to determine whether the formula is positive or
+   negative.  Starting from an initial coarse approximation, the
+   command makes its effort to prove whether the given ACTL formula is
+   true or false. When the procedure fails to prove correctness of the
+   formula with initial approximations, it automatically refines the
+   approximations. It repeats the process until the algorithm produces
+   a reliable result or the available resources are exhausted.  For
+   detailed description, refer to the relevant manual page ("help
+   approximate_model_check from" the VIS shell).
+
+** approximate_model_check is faster than model_check for some of the
+   VIS 1.2 distribution examples. However, significant improvements
+   over the exact computation can be seen for even larger examples
+   such as s15850. The current version of the code does not perform
+   any refinements.  The refinement techniques similar to the "machine
+   by machine" and "frame by frame" may be implemented in future
+   version. Furthermore, more aggressive reduction of the initial
+   states can be performed while proving whether the ACTL formula is
+   positive. The reduction of the initial states are made for each
+   level of the lattice of approximations in this version.
+
+** The current version includes two distinct "grouping method". More
+   experiments are required to determine better grouping method(s).
+
+** The current version only supports ACTL formulae. 
+
+* Residue Based Verification
+
+** VIS 1.2 includes a new command "res_verify" for combinational
+   verification based on residue arithmetic. Residue-based
+   verification is especially suited to multipliers and other
+   arithmetic circuits. See below, however, for a discussion of the
+   application of "res_verify" to other circuits. This command is only
+   available if VIS has been linked with the cu library (default).
+
+** The command res_verify takes two circuits (specification and
+   implementation) whose equivalence is to be established, and an
+   order for the outputs. The order for the outputs allows res_verify
+   to interpret the output vectors as integers. Based on this
+   interpretation, res_verify applies the Chinese remainder theorem to
+   the equivalence verification: the specification and the
+   implementation are equivalent if, for a suitable set of relatively
+   prime numbers, the residues of their outputs are equivalent. The
+   residues are computed by composing the two circuits into a function
+   representing the residue computation.
+
+** res_verify allows the user to specify what pairs of outputs of the
+   circuits should be compared directly by building their BDDs,
+   instead of computing residues for them. The -d <n> option controls
+   this feature; n pairs of outputs, starting from the least
+   significant bits of the output vectors, are verified directly if -d
+   n is specified.
+
+** As a special case, the user can specify -d all. This causes
+   res_verify to directly verify all the output pairs, effectively
+   foregoing residue verification. This can be useful for
+   non-arithmetic circuits that are not suited to residue
+   verification. In this case res_verify works similarly to
+   comb_verify, with a significant exception: res_verify verifies one
+   output at the time. This often translates into reduced memory
+   requirements and CPU times.
+
+** res_verify can be applied to pairs of sequential circuits with the
+   same state encoding. Several options and VIS variables control the
+   detailed behavior of the command. Refer to the on-line
+   documentation for the details (help res_verify).
+
+
+* Extended CTL Syntax
+
+** Users can now write CTL fomulae using vector notation. Vector
+   variables have the form of var[i:j] and each bit can be written as
+   either var<i> or var[i]. For instance, the following formulae are
+   valid.
+
+   counter[3:0] = 10        
+   counter[3:0] = b1010
+   counter[3:0] = {1,2,10}
+
+   The formula in the last line is true if counter has one of the listed
+   values.
+
+** Macros can be defined and used in CTL formulae to stand for subformulae.
+   For instance:
+
+     \define VALID_INPUT (a[3:0]=0 -> b=1)
+
+   defines the macro VALID_INPUT, which can be later used in a formula
+   like this:
+
+     AG(start=1 * \VALID_INPUT -> AF(res[7:0]=b10101010));
+
+** The CTL parser allows users to write the following formulae:
+
+     var1 == var2
+     var1[i:j] == var2[k:l]
+
+   The first formula is equivalent to (var1=1) * (var2=1) + (var1=0) *
+   (var2=0) and currently is allowed only in the boolean domain.  (It
+   cannot be used for variables of enumerated types.)  The second formula
+   can be used if the lengths of two vectors match.
+
+** AX:n(f) is allowed as a shorthand for AX(AX(...AX(f)...)), where n
+   is the number of invocations of AX. EX:n(f) is defined similarly.
+
+
+* BDD manipulation
+
+** VIS 1.2 incorporates Release 2.1.1 of CUDD and an improved version of
+   CAL. Improvements specific to CUDD and relevant to VIS are:
+
+** All reordering methods preserve variable groups. Variable groups are
+   created by VIS to keep corresponding present and next state variables
+   adjacent. In VIS 1.1 only method "sift" retained the variable groups.
+
+** CUDD determines the maximum size of the computed table based on the
+   amount of main memory available. On systems where getrlimit is
+   available, the datasize limit is used to determine how much memory
+   is available. CUDD allows the computed table to grow up to one
+   fourth of that amount. This feature allows VIS to self-calibrate
+   for optimum performance. The computed table will not necessarily
+   grow to its maximum value, and VIS is not guaranteed to stay within
+   the memory bound returned by getrlimit. If the datasize limit is
+   not set, if getrlimit is not available, or if it is available but
+   does not know about datasize, then a suitable default value is used
+   instead. The default value is normally 16MB. This value can be
+   changed at configuration time. Even a value as low as 16MB gives a
+   reasonably sized computed table for small-medium runs. However, for
+   large runs--hundreds of MB--the ability to set the memory limit may
+   produce much faster execution. The maximum computed table size can
+   be set also from within VIS with set_bdd_parameters.
+
+** CUDD now provides access to the package parameters and statistics
+   via the commands bdd_print_stats and set_bdd_parameters. The
+   parameters that can be set control the sizing of CUDD's main data
+   structures (unique table and computed table) and many aspects of
+   the variable reordering algorithms. The parameters reported refer
+   to memory occupation, computed table (cache) performance, and
+   variable reordering.
+
+** It is now possible to impose a limit on the number of variable
+   swaps performed during reordering.
+
+
+* User Interface
+
+** New VIS command "set_bdd_parameters".  
+
+   The command "print_bdd_stats" prints two sets of data from the
+   underlying BDD package, parameters and statistics. The parameters
+   can be modified as follows. By using the "set" command, set the
+   value of a variable whose prefix is "BDD." and whose suffix is
+   exactly the name seen in the output of the command
+   "print_bdd_stats", for example:
+
+     vis> set "BDD.Garbage collection enabled" no
+
+   Then, the command "set_bdd_parameters" reprograms the underlying BDD
+   core based on the values of the variables of this type.
+
+** Readline Library.
+
+   The Readline library is a GNU package that provides command line
+   editing, command history, and file name completion capabilities. If
+   the system where VIS is built has this library and it is installed
+   so that the linker can use it, the configure script will detect
+   this situation and the executable will be linked with
+   libreadline.a.
+
+** Variable Interpolation.
+
+   The VIS shell now allows variable interpolation. For instance, typing
+
+    vis> echo $open_path
+
+   causes vis to echo the current value of open_path. Typing
+
+    vis> set open_path $open_path:/some/path
+
+   will append /some/path to open_path. Variable interpolation can be
+   used also to exchange parameters with scripts. This allows reliable
+   parameter passing even when "source" is called with options.
+
+** PAGER
+
+   If the PAGER environment variable is set, VIS uses it to choose the
+   program used to display the help pages. If PAGER is not set, VIS
+   uses 'more.'
+
+** File Buffering.
+
+   The output of VIS when run in batch mode is now line buffered on
+   systems that provide setvbuf. This makes it more convenient to
+   observe the evolution of long-running jobs.
+
+* Portability and Configuration
+
+** VIS 1.2 runs on two new platforms: IBM RS6000 running AIX and Intel
+   Pentium running Windows95 with Gnu-Win32. The Gnu-Win32 environment
+   (http://www.cygnus.com/misc/gnu-win32/) is a freely available GNU
+   environment for Windows 95 and Windows NT.
+
+** This release of VIS has been tested with some native compilers
+   (Ultrix, Solaris, Digital Unix). In particular, when building with
+   the native compiler on a DEC Alpha running Digital Unix, the option
+   is provided to compile with 32 bit pointers. Please see the README
+   file for specific instructions on how to compile with the different
+   native compilers.
+
+** The GLU library now provides portable functions for random number
+   generation and sorting that help make results reproducible across
+   different platforms.
+
+** The GLU library now provides a function to read the available
+   memory (based on getrlimit). This function is currently used by the
+   CUDD package to choose the optimal size of data structures. For
+   systems without getrlimit a suitable default is provided and can be
+   changed at configuration time.
+
+
+
+Version 1.1
+
+* Introduction
+
+** Improvements over 1.0
+
+*** multiple BDD packages
+*** more synthesis capability
+*** hierarchy restructuring
+*** new methods for partitioning
+*** automatic reduction during model checking
+*** support for multi-phase clocking and transparent latches
+*** support for invoking standard scripts
+*** support for graphically viewing simulation output
+
+  These significantly improve VIS's performance in terms of computer 
+  time, memory usage, and ability to complete on larger designs. 
+  Further, additional capability for synthesis is provided.
+
+  One particular example of the improved performance of VIS 1.1 is the
+  first (to our knowledge) reported exact state space traversal of
+  benchmark s5378. It was run with the cu BDD package on an Alpha
+  300MHz (using 32 bit pointers). The datasize limit was set at
+  1GB. The process grew to about 440MB. Dynamic reordering was enabled
+  all the time and occurred more than 50 times. The orginal ISCAS89
+  circuit was used, which has 179 latches.
+
+*** Multiple BDD packages 
+
+    We have added the capability to run VIS with three different BDD
+    packages, cu - from University of Colorado, cal - from UC Berkeley
+    and cmu - from Carnegie Mellon University. Further details are in
+    the section "BDD Packages" below.
+
+*** Synthesis 
+
+    VIS synthesis is represented by a number of commands, write_blif,
+    read_blif, collapse_child, and decompose_child. These allow the
+    user to manipulate the hierarchy and to write blif files to SIS
+    and then later read in an optimized file. Each of these commands
+    can be executed on sub-nodes or sub-trees of the
+    hierarchy. Details about these commands are in the section
+    "Collapsing and decomposing a hierarchy" and "Reading and writing
+    blif files" below.
+
+*** Partitioning
+
+    Partitioning in VIS is used in a number of places: simulation,
+    model checking, computing the set of reached states, etc.  Recall
+    that the VIS data structure is simply a set of tables with outputs
+    (signals) which can be inputs to other tables. There are also
+    primary input signals and inputs from latches. Some signals are
+    primary outputs and/or inputs to latches. A partition is simply a
+    subset of nodes (signals) which are to be preserved, the remaining
+    are to be eliminated. Of course, primary outputs and inputs to
+    latches cannot be eliminated. We provide some new partitioning
+    methods as described below (in the section "Creating partitions of
+    the network").
+
+    In many cases, a formula to be model checked does not depend on
+    all of the signals in the design. In such cases, the design can be
+    reduced to include only signals in the transitive fan-in of the
+    latches mentioned in the CTL formula plus the fairness
+    constraints. This reduction can result in vastly more efficient
+    model checking.
+
+*** Multi-phase clocking
+
+    One question that is asked frequently is how does VIS support
+    multi-phase clocking and transparent latches in Verilog. We
+    provide this capability in our Verilog compiler "vl2mv" and detail
+    this in a document that describes exactly the steps to be
+    taken. This document is in the vis-1.1/doc directory and is called
+    two_phase.ps.
+
+*** Standard scripts
+
+    Standard scripts have been provided which should help the new user
+    select certain options that we have determined to be good choices
+    on a variety of examples. The scripts are divided into two
+    categories: simple - which are recommended for small/medium
+    examples, and robust - recommended for large examples where
+    completion rather than compute time is the most important
+    concern. The 10 scripts provided are summarized below in the
+    section "Standard scripts".
+
+*** xsimv
+
+    Finally, we have included "xsimv", which provides a graphical
+    method for viewing simulation output. This is detailed in the
+    section "Using Xsimv".
+
+* Multiple BDD packages
+
+  We have added the capability to run VIS with three different BDD
+  packages, cu - from University of Colorado, cal - from UC Berkeley
+  and cmu - from Carnegie Mellon University. The commands for these
+  respectively are vis-cu, vis-cal, and vis-cmu. The cmu package is
+  the same as in VIS 1.0. The cu package is very strong in having a
+  fast dynamic variable reordering capability. In addition, cu has
+  been upgraded for the DEC alpha machines so that it uses 32 bit
+  pointers, instead of 64 bit pointers; hence it realizes a factor of
+  2 in memory savings on such machines. The other two packages remain
+  to be upgraded for 32 bit pointers on the DEC alphas.  The cal
+  package uses the BFS BDD technique and is particularly good at
+  avoiding paging on large designs. For most problems, we recommend
+  the cu package.
+
+* Reading and writing BLIF files
+
+  The "write_blif" command in vis-1.0 only wrote out the combinational
+  part of an hnode (a node of the hierarchy).  Now this functionality
+  is performed by the "write_blif -c" command. Other options have been
+  added as well. The options are:
+
+  (1) write_blif -l
+
+      writes out the latches of the hnode as well.  Additionally, all
+      latch IOs are made into POs in the blif file that is
+      created. This ensures that the these nodes do not get optimized
+      away by SIS, so that mv-latches can be re-inserted by the
+      read_blif command in VIS.
+
+  (2) write_blif -c
+
+      same as "write_blif" of vis-1.0
+
+  (3) write_blif
+
+      writes out latches of the hnode, but does not make latch IOs
+      into POs in the blif file. The .blif and .enc files that are
+      generated by this command currently cannot be guaranteed to read
+      back into VIS correctly using the read_blif command.
+
+  (4) write_blif -R
+
+      recursively writes out the entire hnode hierarchy rooted at the
+      current hnode, to a blif file. This command opens up a direct
+      path from Verilog to pure blif files and hence to synthesis in
+      the SIS framework.  For this command to work, 1) all variables
+      in the hnode hierarchy rooted at the current hnode must be
+      binary, 2) all tables should be deterministic, and 3) there must
+      be a unique initial state.
+
+* Collapsing and decomposing a hierarchy
+
+  If the user travels (via "cd" commands) to a particular node in the
+  hierarchy and does a "write_blif", only the logic in the *current*
+  node gets written out. The user might want to collapse some of the
+  child nodes together and do synthesis in the "collapsed" node. The
+  "collapse_child" command does just that. The usage is:
+
+      collapse_child <child_name>
+
+  and the effect is that the child node is absorbed by the parent. By
+  successive invocations of this command, multiple nodes can be
+  collapsed into a single node.
+
+  "decompose_child" is a command that effects the inverse operation of
+  collapse_child. The user can specify components of the current node
+  to be grouped as a separate newly created child node. The user must
+  also specify the name of the new child. Successive invocations of
+  "decompose_child" can be used to effect multiple
+  decompositions. "decompose_child" provides the infra-structure for
+  implementing and testing FSM decomposition algorithms (to appear
+  later).
+
+  Together, collapse_child and decompose_child provide powerful
+  primitives that can be used to restructure the design hierarchy.
+
+* Creating a flattened network for verification
+
+  The important change to note is the "-b" option in the
+  "flatten_hierarchy" command.  By default this option is off,
+  implying that the system is not checked for complete and
+  deterministic specification. However, if the given design does not
+  meet this criteria, model checking may produce wrong results. (Note:
+  In VIS nondeterminism is handled by providing pseudo-inputs.
+  Internally all the tables are deterministic and completely
+  specified.)  Invoking this "-b" option forces the necessary
+  checking. However this can be computationally expensive.  The best
+  strategy is to invoke "flatten_hierarchy" with "-b" option the first
+  time and if the check passes, use it without "-b" option in
+  subsequent runs.
+
+* Creating partitions of the network
+
+  Three new methods for creating partitions for the "build_partition_mdds" 
+  command have been added.
+
+      - partial
+
+        This can be used to perform partitioning while forcing a
+	user-specified set of signals (nodes) in the partition. The
+	set of nodes to be included can either be supplied in a file,
+	or on the command line.
+
+      - boundary
+
+	In this method, all nodes that are sub-circuit IOs are
+	included in the partition.
+
+      - frontier
+
+	In this method (the default method), the user specifies a
+        parameter "partition_threshold" which is used to include an
+        intermediate variable whenever the BDD size for a node in the
+        network increases beyond the threshold value. This method is
+        very useful when it is not possible to create the next state
+        functions in terms of primary inputs because of large BDD
+        sizes. This method encompasses both "in_out" and "total"
+        partitioning methods (corresponds to very large and 0 value of
+        "partition_threshold", respectively). The parameter can be set
+        by invoking the following from the VIS commandline: "set
+        partition_threshold <integer>".
+
+* Reachability computation
+
+  A few new options to reachability computation have been added 
+  (command: compute_reach).
+
+
+	-d depthValue
+
+	   Used to perform reachability up to a certain number of
+	   steps.
+
+	-r threshold_value
+
+	   Invokes dynamic reordering of variables ONCE, after the
+           size of the reached state set crosses the threshold_value.
+
+* CTL Syntax
+
+  For Verilog compatibility, && and || are supported in addition to *
+  (Boolean AND) and + (Boolean OR) respectively.
+
+* Model checking
+
+  The mc command, by default, now reduces the model FSM with respect
+  to the union of all the formulas in the CTL file and uses the
+  reachability don't cares (thus reachablilty is done first before any
+  model checking). Also, -d 0 is the default now, i.e. no error trace
+  is computed. The -r option has been modified and a new capability
+  for sharing sub-formulas has been added.
+
+  -r
+
+    (This option has been modified). If this option is used, each
+    formula is model checked individually on an FSM reduced with
+    respect to the formula.
+
+  -c
+
+    This disables the default that sub-formulas of the formulas given
+    in the CTL file are shared. The sharing of sub-formulas makes sure
+    that a sub-formula in the set of all sub-formulas of the formulas
+    in the CTL file is evaluated only once. If both -r (formula
+    dependent FSM reduction) or "-D 1" (use reachability don't cares)
+    are enabled, this facility is automatically disabled.  (Note that
+    currently if the same sub-formula occurs more than once within a
+    single formula, it may be checked twice.)
+
+* Standard scripts
+
+  There are 10 standard scripts provided (in the "share" directory),
+  divided into two categories, simple and robust. The simple scripts
+  work best on small/medium size examples. The robust scripts are
+  recommended for large problems where the objective is to complete
+  the computation without too much concern for computation time. Below
+  are the scripts with their required arguments.  All scripts assume
+  that a BLIV-MV file has already been read in.
+
+	script_generic.simple
+	script_compute_reach.simple     
+	script_model_check.simple foo.ctl
+	script_fair_model_check.simple foo.fair foo.ctl
+	script_lang_empty_check.simple foo.fair
+
+	script_generic.robust
+	script_compute_reach.robust
+	script_model_check.robust foo.ctl
+	script_fair_model_check.robust foo.fair foo.ctl 
+	script_lang_empty_check.robust foo.fair
+
+  In all cases, "script_generic" is a preample to the other scripts.
+  Generally, we recommend trying a "simple" script first, since it
+  should be the fastest.
+
+* Using "xsimv"
+
+  Before invoking xsimv, please modify the first line of the file
+  "xsimv" and put the complete path name for "expectk".
+
+  xsimv is invoked by the command 
+
+	xsimv <sim-file>
+
+  where <sim-file> is a file produced by the vis command 
+
+	simulate -n <num> -o <sim-file>
+
+  When xsimv executes, it comes up with a window with 4 buttons in it,
+  GO, ReDraw, Save and Quit. At the same time it produces a file,
+  "strk.simv", with the signal names in it. For example
+
+    sensor.rand_choice
+    timer.rand_choice
+    car_present
+    farm_light
+    hwy_light
+    timer.state
+
+  If only a subset of these names are required the user can edit this
+  file and comment out a line using "#". For example,
+
+    #sensor.rand_choice
+    #timer.rand_choice
+    car_present
+    farm_light
+    hwy_light
+    timer.state
+
+  will cause the first two signals' simulation to be not displayed.
+
+  Pushing GO or ReDraw then produces a new window with the simulation
+  results shown where time increases from left to right.  The signal
+  value names not commented out are shown vertically, one for each
+  row. The "edit strk.simv" and REDRAW sequence can be iterated.
+
+
+Version 1.0
+
+* Initial release
Index: vis_dev/vis-2.3/README
===================================================================
--- vis_dev/vis-2.3/README	(revision 14)
+++ vis_dev/vis-2.3/README	(revision 14)
@@ -0,0 +1,477 @@
+This is release 2.3 of VIS, a system for verifying and synthesizing
+finite-state systems.  VIS builds on GLU, a collection of BDD packages
+and low-level utilities.
+
+To build VIS and GLU, you will need
+
+   * An ANSI C compiler (gcc will do, as will several versions of cc)
+   * GNU Flex version 2.5 or greater
+   * GNU Bison version 1.22 or greater
+   * GNU's make utility
+   * GNU's gzip utility
+   * Approximately 90 MB of free disk space for the build of both
+     vis and glu
+   * Approximately 60 MB of free disk space for the installation
+
+---------------------------------------------------------------------------
+* Useful Addresses
+
+The most recent version of vl2mv, the Verilog compiler designed to work 
+with VIS:
+
+        ftp://vlsi.colorado.edu/pub/vis/vl2mv-2.3.tar.gz
+
+The most recent versions of VIS and GLU:
+
+        ftp://vlsi.colorado.edu/pub/vis/{glu-2.3.tar.gz,vis-2.3.tar.gz}
+
+The VIS home page, which includes additional documentation:
+
+	http://vlsi.colorado.edu/~vis
+
+The most recent version of the GNU tools:
+
+	http://www.gnu.org
+
+The most recent version of perl, which is required to run 'visdbgpp':
+
+	http://www.cpan.org
+
+The most recent version of expectk, which is required to run 'xsimv':
+
+	http://expect.nist.gov
+
+The most recent version of Tcl/Tk, which is required to run 'expectk':
+
+	http://www.scriptics.com/
+
+Optionally, the most recent version of cusp, the SAT solver which
+can be used instead of CirCUs 1.0 (included in VIS) to execute the
+bounded_model_check command:
+
+	ftp://vlsi.colorado.edu/pub/CUSP/cusp-1.1.tar.gz
+
+---------------------------------------------------------------------------
+* Platforms
+
+This is the list of architecture/operating system/compiler
+combinations we have tested. (For installation with compilers marked
+with (*) please refer to the Platform Specific Instructions.)
+
+        * Intel ia32 / Linux / gcc, g++
+        * Intel x86_64 / Linux / gcc, g++, icc(*)
+        * Intel ia32/x86_64 / Windows XP with Cygwin 1.5.16-1 / gcc, g++(*)
+        * Intel ia32 / Mac OS X / gcc(*)
+
+The following platforms are no longer supported, but should still work.
+
+	* IBM RISC System/6000 / AIX Version 4.3.3 / gcc(*)
+        * Intel ia64 / Linux / gcc
+        * Sun Sparc/ Solaris 2.8 / gcc, g++, cc(*)
+
+The following instructions are for the generic build process.  Before
+building the tool please refer to the section "Platform Specific
+Instructions".
+
+---------------------------------------------------------------------------
+* Building VIS
+
+To build a VIS executable for a single operating system:
+
+1. Download the most recent versions of VIS and GLU from the address
+   above into a convenient directory, (e.g., /tmp).
+
+2. Move to where you would like to build VIS and GLU and unpack the
+   distributions:
+
+	% cd /home/vis					# for example
+	% gzip -dc /tmp/glu-2.3.tar.gz | tar xf -
+	% gzip -dc /tmp/vis-2.3.tar.gz | tar xf -
+
+3. Move into the glu-2.3 directory and run configure, which will
+   determine some system-specific parameters and create the Makefile:
+
+	% cd glu-2.3
+	% ./configure
+
+   By default, this will use your system's native compiler.  To use gcc,
+
+        % ./configure --enable-gcc
+
+   (You may want to do this because you don't have the native compiler
+   installed or because it is not ANSI.)
+
+   Note: For platforms where VIS is not supported for the native compiler,
+   the default compiler is set to gcc.
+
+   Note: Not all checks in ./configure will return "yes."  This is
+   normal and should not affect compilation.  However, do be concerned
+   with any warnings "configure" produces.
+
+   Note: Occasionally, configure will make a bad guess or will choose
+   a default you do not want.  In this case, simply edit the Makefile
+   after configure finishes.
+
+   Note: You may want to specify parameters to configure -- see the
+   "Installing" sections below.
+
+   Note: To parallelize the installation procedure, you can begin steps 
+   5 and 6 at this point, as long as step 4 completes before step 6
+   (since VIS must link against the GLU library).
+
+   Note: The Makefile by default uses the "-g" option for
+   compilation.  The resultant "vis" executable may be much larger than
+   the executable generated without using the "-g" option.  Using the
+   "-g" option however, provides debugging capabilities.
+
+   Note: The following is of interest only to people developing code
+   within vis.  For full debugging support, specify
+   --with-comp-mode=debug.  This will turn off optimization, and turn
+   on the assertions (sanity checks) in the code.  Similarly,
+   --with-comp-mode=purify and --with-comp-mode=quantify will link vis
+   with IBM Rational's Purify or Quantify tool, if it is installed.
+
+4. Build the GLU system by running GNU's gmake utility:
+
+	% gmake
+
+   You may not have GNU make installed on your system under the name
+   'gmake' -- try make.  If this fails, you probably need the latest
+   version of GNU's make program -- download it from the address
+   above.
+
+5. Move into the vis-2.3 directory and run configure:
+
+	% cd ../vis-2.3
+	% ./configure
+
+   By default, this will use your system's native compiler.  To use gcc,
+  
+        % ./configure --enable-gcc
+
+   (You may wish to do this because you don't have the native compiler  
+   installed or because it is not ANSI.)
+
+   Note: For platforms where VIS is not supported for the native compiler,
+   the default compiler is set to gcc.
+
+   Note: If you supplied compilation-option flags (e.g., --enable-64)
+   to the GLU configure, provide the same to the VIS configure.
+ 
+   Note: Not all checks in ./configure will return "yes."  This is
+   normal and should not affect compilation.  However, do be concerned
+   with any warnings "configure" produces.
+
+   Note: Occasionally, configure will make a bad guess or will choose
+   a default you do not want.  In this case, simply edit the Makefile
+   after configure finishes.
+
+   Note: You may want to specify parameters to configure -- see the
+   "Installing" sections below.
+
+   Note: You may want to remove the "-g" flag from the make file.  See
+   under 3.
+
+6. Build the VIS system by running GNU's gmake utility:
+
+	% gmake
+
+   This builds an executable "vis" in the current directory.
+
+   WARNING: If you are not successful in building a VIS executable, 
+   double check that you are using Flex version 2.5 or greater (check 
+   using "flex -V") and GNU Bison version 1.22 or greater (check with 
+   "bison -V").  Having out-of-date versions of these programs can 
+   lead to obscure compilation and linking errors.  You can download
+   the new versions from the GNU FTP address above.
+
+   VIS expects to find master.visrc, two .nawk files, and a directory
+   of help files in the directory given by the environment variable
+   VIS_LIBRARY_PATH.  Set this to the "share" directory in the source
+   tree:
+
+	% setenv VIS_LIBRARY_PATH $cwd/share
+
+7. OPTIONAL: Verify VIS works by running it on some of the examples
+   included in the distribution:
+
+	% gmake check
+
+   This step finishes in less than five minutes on most machines
+   and requires approximately 32 MB of RAM.
+
+---------------------------------------------------------------------------
+* Installing GLU:
+
+Developers will want to install the GLU library and its associated header
+files in a central area:
+
+To install the GLU library and its header files, type, while in the
+glu-2.3 directory,
+
+	% gmake install	
+
+By default, this will put libraries and headers in /usr/local/lib
+and /usr/local/include respectively.  To choose a different
+location, provide a default prefix when you invoke configure, e.g.,
+to install in /projects/glu/bin, etc., use
+
+	% ./configure --prefix=/projects/glu
+
+when configuring GLU.  Note that "tilde expansion" doesn't work for the  
+prefix (i.e., don't specify --prefix=~smith/glu).
+
+---------------------------------------------------------------------------
+* Installing VIS:
+
+Administrators and people who want to discard the source files after
+building VIS may install VIS in a central area:
+
+To install the VIS executable, library, headers, and help files, type,
+while in the vis-2.3 directory,
+
+	% gmake install
+
+By default, this will put binaries, libraries, headers, and help files
+in /usr/local/bin, /usr/local/lib, /usr/local/include, and
+/usr/local/share respectively.  To choose a different location,
+provide a default prefix when you invoke configure, e.g., to install
+in /projects/vis/bin, etc., use
+
+	% ./configure --prefix=/projects/vis
+
+when configuring VIS.
+
+"gmake clean" removes all the files generated during "gmake."  This is
+useful when you want to rebuild VIS with a different prefix,
+different compiler options, etc.
+
+During configure if --prefix option is used, files found in the
+"share" directory will be installed in $prefix/share/vis; otherwise
+they will be installed in /usr/local/share/vis by default.  Set the
+environment variable "VIS_LIBRARY_PATH" to the appropriate directory so
+that VIS can find master.visrc, the two .nawk files and the "help"
+directory.  The above mentioned files can also be present in a
+different directory, but "VIS_LIBRARY_PATH" should be set to that
+directory.  For example,
+
+	% setenv VIS_LIBRARY_PATH /projects/vis/common
+
+---------------------------------------------------------------------------
+* Installation for multiple platforms
+
+To install VIS on multiple operating systems depending on the same
+source tree, see the file "INSTALL" included in the distribution.
+
+In this case, when the build directory is different from the source
+directory, it's necessary to configure VIS to look elsewhere for the
+GLU libraries and headers, e.g.,
+
+	% ./configure --with-glu-libdir=/tmp/glu-2.2/alpha \
+		--with-glu-incdir=/tmp/glu-2.1/include
+
+Also, make sure that there is an obj/ directory in the directory in
+which you are compiling.  See ./configure --help for more information.
+
+---------------------------------------------------------------------------
+* Selecting a different BDD package
+
+To create VIS with a different BDD library (say cal) than the default
+one (cu), use the following command:
+
+	%./configure --with-bdd=cal
+
+The same can be achieved by changing the "BDDPKG" definition in the
+Makefile from "cu" to "cal".
+
+VIS can work with three different BDD packages (cmu, cal, cu), all of
+which are supplied with glu-2.3.  However, some commands in VIS are
+available only with the cu BDD package.  Please refer to the NEWS file
+for more details. 
+
+---------------------------------------------------------------------------
+To create three versions of VIS, each with different BDD libraries,
+run 'gmake allprods'.  This will create vis-cal, vis-cu, and
+vis-cmu.  To verify whether all these executables are compiled
+correctly, use 'gmake check-allprods' at the end.
+---------------------------------------------------------------------------
+
+* Files in the VIS distribution:
+
+README		This file.
+
+INSTALL		Generic installation instructions for use with configure, 
+                including instructions for simultaneous multi-platform 
+                builds.  These are not specific to VIS nor GLU, so don't 
+                follow them word for word.
+
+NEWS		Changes since the last version/release.
+
+configure	An executable shell script that creates "Makefile" from
+		Makefile.in after determining system-specific parameters.
+
+configure.in	Autoconf source for generating the configure file.
+		Only needed if you want to modify the configure script.
+
+Makefile.in	The template Makefile.
+
+vis.1		Unix-style man page documenting vis invocation
+		parameters.
+
+xsimv		An expectk script to visualize VIS simulation traces.
+
+helpers/	Programs useful during configuration and building
+ install-sh	Shell scripts used by "gmake install."
+ mkinstalldirs
+ config.guess
+ config.sub
+ dependency.make
+
+doc/vis_user.ps
+		A user's manual for the VIS system, describing our approach
+		to formal verification and how to use the tool.
+
+doc/blifmv.ps	Documentation on the BLIF-MV file format, a low-level 
+		language for specifying designs.
+
+doc/ctl.ps	Documentation on the CTL file format, a language
+		for specifying properties.
+
+examples/*/	A collection of small systems and properties to be
+		verified.  Used by "gmake check."
+
+share/master.visrc
+		A VIS script designed to be run automatically at
+		start-up: contains aliases for commonly used commands
+		and some default parameter settings.
+
+share/*.nawk	nawk scripts for converting BLIF files to BLIF-MV,
+		used by the "read_blif" command.
+
+share/script*	Sample scripts.
+
+share/sislib.mv	Library of gates used by models translated by vl2mv
+		from gate-level Verilog descriptions.
+
+share/visdbgpp	A perl script to pretty-print counterexamples produced
+		by the model_check and check_invariant commands.
+
+share/help/	ASCII documentation for each VIS command, accessible
+		through the "help" command within VIS.
+
+src/*/		Source code and headers for the VIS system.
+
+obj/		Directory where .o files and generated .c files are
+		placed during a build.
+
+checkresults/	Directory where tests (i.e., gmake check) are run.
+		Results of the tests are placed here.  The directory
+		is only created when 'gmake check' is run.
+
+---------------------------------------------------------------------------
+* Platform Specific Instructions
+
+Note: some instructions apply to platforms we no longer support.
+
+** Little-endian machines:
+
+  vis-cal will occasionally fail when compiled with
+  --with-comp-mode=debug on little-endian machines like the Alphas and
+  the Intel ix86 CPUs.
+
+** x86_64 machines:
+
+  Compilation is possible in both 64 and 32-bit modes.  
+
+  For 32-bit compilation with gcc, make sure the appropriate libraries
+  are installed.  On Ubuntu, for instance, you need the multilib-g++
+  package.  Configure both glu and vis with --enable-gcc="gcc -m32".
+
+  With the Intel compiler (icc), the choice between 64 and 32-bit
+  modes is made when the compiler variables are initialized.  Once
+  that is done, configure both glu and vis with --enable-gcc=icc.
+
+** Mac OS X:
+
+  For correct operation of vis-cmu, uncomment the definition
+  of USE_MALLOC_FREE at line 126 of src/mem/memint.h before building glu.
+
+** Solaris (Sparc and ix86):
+
+  If Sun's C compiler is not installed on your system, use gcc
+  (./configure --enable-gcc).
+
+  Warnings about redefined symbol are harmless, so are the warnings
+  that say "end-of-loop code not reached".
+
+  The sun cc compiler (Workshop 6 update 1) on ix86 appears to have a
+  bug in the optimization routines.  The -xO4 an -xO5 compiler options
+  will make vis crash in some runs.  As a safety precaution, we have
+  changed the optimization flag to be -xO3 for all Sun platforms that
+  use the cc compiler.  You can try higher optimization flags on your
+  machine.  In general, it is hard to determine cc options that will
+  give optimal results on every platform, so it may pay off to play
+  atound with the optimization options.
+
+** MS Windows with Cygwin:
+
+  You need Red Hat's Cygwin environment (freely available from
+  http://www.cygwin.com) to build GLU and VIS.
+
+  With Cygwin the configuration script automatically selects gcc.
+
+** HP-UX:
+
+  Some operating systems on HP machines have a built-in command called
+  "vis" under /usr/ucb.  In light of this, be careful about the
+  definition of your  path.
+
+** AIX:
+ 
+  The configuration script automatically selects gcc.  vis-cal
+  occasionally produces incorrect results when optimization is turned
+  on.  If you plan to use vis-cal with AIX, you should configure glu
+  and vis with --with-comp-mode=debug.
+
+** Intel A64:
+
+  vis-cal compiled with gcc 3.2.3 crashes when sifting is invoked.
+
+** DEC Alpha:
+
+  Warnings about MIN and MAX are harmless.
+  Warnings about Olimit are harmless.  They can be gotten rid of by
+  increasing the number following Olimit under CFLAGS.
+
+  By default, configure uses 32-bit pointers when using DEC's OSF/1 C
+  compiler for the Alpha, which is more efficient if your processes
+  use less than 2GB.  To use 64-bit pointers, invoke configure as follows:
+
+	% ./configure --enable-64
+
+  The gcc compiler always compiles with 64-bit pointers.
+
+  Note that you must also specify this flag when configuring GLU.
+
+  Some machines do not have the program 'om'.  In this case, simply
+  removing the om flag from LDFLAGS is sufficient to complete
+  compilation.
+
+** IRIX
+
+  When compiling VIS with gcc, you may get the error message
+
+  gcc.x: cannot specify -o with -c or -S and multiple compilations
+
+  If this happens, edit Makefile, and replace the definition of
+  VERDATE with the following:
+
+  VERDATE := -DCUR_DATE="\"N/A\"" -DCUR_VER="\"$(PRODUCT)-$(VERSION)\""
+
+---------------------------------------------------------------------------
+* Verilog front-end
+
+vl2mv, written by Szu-Tsung Cheng, allows one to translate a subset of
+Verilog into blif-MV, the input format of VIS.  The most recent
+version of vl2mv can be found in ftp://vlsi.colorado.edu/pub/vl2mv-2.3.tar.gz.
+This version requires glu-2.3 to compile and link.
Index: vis_dev/vis-2.3/configure
===================================================================
--- vis_dev/vis-2.3/configure	(revision 14)
+++ vis_dev/vis-2.3/configure	(revision 14)
@@ -0,0 +1,6391 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.57.
+#
+# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
+# Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+
+# Support unset when possible.
+if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)$' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+  	  /^X\/\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\/\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+	 case $as_dir in
+	 /*)
+	   if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+	     $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+	     $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+	     CONFIG_SHELL=$as_dir/$as_base
+	     export CONFIG_SHELL
+	     exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+	   fi;;
+	 esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='	' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" 	$as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_config_libobj_dir=.
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete.  It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="src/cmd/cmd.h"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+#  include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS glulibdir gluincdir vislibdir local_srcdir BDDLIB ZCHAFF AR RANLIB ac_ct_RANLIB build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LINKER PLINKER LEX LEXLIB LEX_OUTPUT_ROOT YACC CPP EGREP LIBDIRS LIBOBJS AWK LTLIBOBJS'
+ac_subst_files=''
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+ac_prev=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval "$ac_prev=\$ac_option"
+    ac_prev=
+    continue
+  fi
+
+  ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_option in
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    eval "enable_$ac_feature=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_$ac_feature='$ac_optarg'" ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_$ac_package='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/-/_/g'`
+    eval "with_$ac_package=no" ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+    eval "$ac_envvar='$ac_optarg'"
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  { echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+              localstatedir libdir includedir oldincludedir infodir mandir
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then its parent.
+  ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+         X"$0" : 'X\(//\)[^/]' \| \
+         X"$0" : 'X\(//\)$' \| \
+         X"$0" : 'X\(/\)' \| \
+         .     : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r $srcdir/$ac_unique_file; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+   { (exit 1); exit 1; }; }
+  else
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+  fi
+fi
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+  { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+   { (exit 1); exit 1; }; }
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+  cat <<_ACEOF
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR           user executables [EPREFIX/bin]
+  --sbindir=DIR          system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR       program executables [EPREFIX/libexec]
+  --datadir=DIR          read-only architecture-independent data [PREFIX/share]
+  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
+  --libdir=DIR           object code libraries [EPREFIX/lib]
+  --includedir=DIR       C header files [PREFIX/include]
+  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
+  --infodir=DIR          info documentation [PREFIX/info]
+  --mandir=DIR           man documentation [PREFIX/man]
+_ACEOF
+
+  cat <<\_ACEOF
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+  --target=TARGET   configure for building compilers for TARGET [HOST]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --enable-gcc            Allow use of gcc if available
+  --enable-64             Use 64-bit pointers on 64-bit Alpha machines
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-glu-libdir=<libdir> Specify directories to search for the GLU library.
+                          Expects to find <libdir>/libglu.a
+  --with-glu-incdir=<incdir> Specify directories to search for the GLU headers
+  --with-vis-libdir=<libdir> Specify directories to search for the VIS
+			  and headers.  Defaults to \".\".
+                          Expects to find <libdir>/libvis.a
+  --with-local-srcdir=<srcdir> Specify the root directory to search for
+			  source for packages (the PKGS list).
+			  Expects to find, e.g., <srcdir>/tbl/tbl.c
+  --with-bdd=<bddPackage> Specify the BDD library to link against.
+                          Defaults to --with-bdd=cu.
+  --with-comp-mode=<mode> Specify a special compilation mode:
+			  optimize (the default): Produce optimized
+				code, with symbol table information
+				if supported on the platform/compiler,
+				and without asserts.
+			  debug: Produce unoptimized code with symbol table
+				information and asserts enabled
+			  purify: Unoptimized code linked with purify
+			  quantify: Optimized code without asserts
+				linked with quantify
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
+              headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  ac_popdir=`pwd`
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d $ac_dir || continue
+    ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be
+# absolute.
+ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd`
+ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd`
+ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd`
+ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd`
+
+    cd $ac_dir
+    # Check for guested configure; otherwise get Cygnus style configure.
+    if test -f $ac_srcdir/configure.gnu; then
+      echo
+      $SHELL $ac_srcdir/configure.gnu  --help=recursive
+    elif test -f $ac_srcdir/configure; then
+      echo
+      $SHELL $ac_srcdir/configure  --help=recursive
+    elif test -f $ac_srcdir/configure.ac ||
+           test -f $ac_srcdir/configure.in; then
+      echo
+      $ac_configure --help
+    else
+      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi
+    cd $ac_popdir
+  done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+  cat <<\_ACEOF
+
+Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
+Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.57.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo               = `(hostinfo) 2>/dev/null               || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+    2)
+      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+        ac_must_keep_next=false # Got value, back to normal.
+      else
+        case $ac_arg in
+          *=* | --config-cache | -C | -disable-* | --disable-* \
+          | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+          | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+          | -with-* | --with-* | -without-* | --without-* | --x)
+            case "$ac_configure_args0 " in
+              "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+            esac
+            ;;
+          -* ) ac_must_keep_next=true ;;
+        esac
+      fi
+      ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+      # Get rid of the leading space.
+      ac_sep=" "
+      ;;
+    esac
+  done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+{
+  (set) 2>&1 |
+    case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      sed -n \
+        "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+    	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+      ;;
+    *)
+      sed -n \
+        "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+}
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=$`echo $ac_var`
+      echo "$ac_var='"'"'$ac_val'"'"'"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=$`echo $ac_var`
+        echo "$ac_var='"'"'$ac_val'"'"'"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      sed "/^$/d" confdefs.h | sort
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      echo "$as_me: caught signal $ac_signal"
+    echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core core.* *.core &&
+  rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+     ' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . $cache_file;;
+      *)                      . ./$cache_file;;
+    esac
+  fi
+else
+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+               sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+  eval ac_new_val="\$ac_env_${ac_var}_value"
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+        { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+        { echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
+echo "$as_me:   former value:  $ac_old_val" >&2;}
+        { echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
+echo "$as_me:   current value: $ac_new_val" >&2;}
+        ac_cache_corrupted=:
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Look for install.sh, config.guess, and config.sub in the "helpers" dir
+ac_aux_dir=
+for ac_dir in helpers $srcdir/helpers; do
+  if test -f $ac_dir/install-sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f $ac_dir/install.sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f $ac_dir/shtool; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in helpers $srcdir/helpers" >&5
+echo "$as_me: error: cannot find install-sh or install.sh in helpers $srcdir/helpers" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"
+ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
+
+
+#----------------------------------------------------------------------
+# Configuration options
+#----------------------------------------------------------------------
+
+# Give the configurer a chance to set the location of the GLU tree
+
+
+
+# Check whether --with-glu-libdir or --without-glu-libdir was given.
+if test "${with_glu_libdir+set}" = set; then
+  withval="$with_glu_libdir"
+  glulibdir=$withval
+else
+  glulibdir=""
+fi;
+
+
+
+# Check whether --with-glu-incdir or --without-glu-incdir was given.
+if test "${with_glu_incdir+set}" = set; then
+  withval="$with_glu_incdir"
+  gluincdir=$withval
+else
+  gluincdir=""
+fi;
+
+# Give the configurer a chance to set a different location for the VIS
+# headers and library
+
+
+
+# Check whether --with-vis-libdir or --without-vis-libdir was given.
+if test "${with_vis_libdir+set}" = set; then
+  withval="$with_vis_libdir"
+  vislibdir=$withval
+else
+  vislibdir="."
+fi;
+
+# Give the configurer a chance to set a different location for the VIS
+# source.  When specified, "srcdir" points to "master" source, and
+# "local_srcdir" points to the source under local development.
+
+
+
+# Check whether --with-local-srcdir or --without-local-srcdir was given.
+if test "${with_local_srcdir+set}" = set; then
+  withval="$with_local_srcdir"
+  local_srcdir=$withval
+else
+  local_srcdir=$srcdir
+fi;
+
+# Give the configurer a chance to set the BDD library
+
+
+
+# Check whether --with-bdd or --without-bdd was given.
+if test "${with_bdd+set}" = set; then
+  withval="$with_bdd"
+  BDDLIB=$withval
+else
+  BDDLIB=cu
+fi;
+
+#----------------------------------------------------------------------
+# Checks for programs we need
+#----------------------------------------------------------------------
+# Extract the first word of "zchaff", so it can be a program name with args.
+set dummy zchaff; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_ZCHAFF+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $ZCHAFF in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ZCHAFF="$ZCHAFF" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_ZCHAFF="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  ;;
+esac
+fi
+ZCHAFF=$ac_cv_path_ZCHAFF
+
+if test -n "$ZCHAFF"; then
+  echo "$as_me:$LINENO: result: $ZCHAFF" >&5
+echo "${ECHO_T}$ZCHAFF" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+# Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_AR+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $AR in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_AR="$AR" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_AR="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_path_AR" && ac_cv_path_AR="ar"
+  ;;
+esac
+fi
+AR=$ac_cv_path_AR
+
+if test -n "$AR"; then
+  echo "$as_me:$LINENO: result: $AR" >&5
+echo "${ECHO_T}$AR" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":"
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  RANLIB=$ac_ct_RANLIB
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+
+# Make sure we can run config.sub.
+$ac_config_sub sun4 >/dev/null 2>&1 ||
+  { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5
+echo "$as_me: error: cannot run $ac_config_sub" >&2;}
+   { (exit 1); exit 1; }; }
+
+echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6
+if test "${ac_cv_build+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_build_alias=$build_alias
+test -z "$ac_cv_build_alias" &&
+  ac_cv_build_alias=`$ac_config_guess`
+test -z "$ac_cv_build_alias" &&
+  { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+   { (exit 1); exit 1; }; }
+ac_cv_build=`$ac_config_sub $ac_cv_build_alias` ||
+  { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6
+build=$ac_cv_build
+build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6
+if test "${ac_cv_host+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_host_alias=$host_alias
+test -z "$ac_cv_host_alias" &&
+  ac_cv_host_alias=$ac_cv_build_alias
+ac_cv_host=`$ac_config_sub $ac_cv_host_alias` ||
+  { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6
+host=$ac_cv_host
+host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+echo "$as_me:$LINENO: checking target system type" >&5
+echo $ECHO_N "checking target system type... $ECHO_C" >&6
+if test "${ac_cv_target+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_target_alias=$target_alias
+test "x$ac_cv_target_alias" = "x" &&
+  ac_cv_target_alias=$ac_cv_host_alias
+ac_cv_target=`$ac_config_sub $ac_cv_target_alias` ||
+  { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_target_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_target_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_target" >&5
+echo "${ECHO_T}$ac_cv_target" >&6
+target=$ac_cv_target
+target_cpu=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+  test "$program_prefix$program_suffix$program_transform_name" = \
+    NONENONEs,x,x, &&
+  program_prefix=${target_alias}-
+
+
+# Determine the name of the C compiler we're going to use
+
+# Check whether --enable-gcc or --disable-gcc was given.
+if test "${enable_gcc+set}" = set; then
+  enableval="$enable_gcc"
+  gcc_ok=$enableval
+else
+  gcc_ok=no
+fi;
+
+# We cannot set CC=g++ directly because many configuration test programs
+# do not compile with g++.  Hence, when the user specifies --enable-gcc=g++,
+# we set CC=gcc during configuration, and then CC=g++ at the end.
+# The same applies to icpc and icc.
+if test "$gcc_ok" != no; then
+  case "$gcc_ok" in
+    yes | g++)
+      CC=gcc ;;
+    icpc)
+      CC=icc ;;
+    *)
+      CC=$gcc_ok
+  esac
+else
+  if test -z "$CC" ; then
+    # Balakrishna Kumthekar <kumtheka@colorado.edu>
+    # As we do not support cc on RS6000, Cygwin and SunOS.
+    case "$target" in
+    rs6000-ibm-aix* | *-pc-cygwin32 | sparc-sun-sunos*)
+      CC=gcc ;;
+    *)
+      CC=cc ;;
+    esac
+  fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$ac_ct_CC" && break
+done
+
+  CC=$ac_ct_CC
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+     "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C compiler default output" >&5
+echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+  (eval $ac_link_default) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Find the output, starting from the most likely.  This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+        ;;
+    conftest.$ac_ext )
+        # This is the source file.
+        ;;
+    [ab].out )
+        # We found the default executable, but exeext='' is most
+        # certainly right.
+        break;;
+    *.* )
+        ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+        # FIXME: I believe we export ac_cv_exeext for Libtool,
+        # but it would be cool to find out if it's true.  Does anybody
+        # maintain Libtool? --akim.
+        export ac_cv_exeext
+        break;;
+    * )
+        break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  fi
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+          export ac_cv_exeext
+          break;;
+    * ) break;;
+  esac
+done
+else
+  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX			-qlanglvl=ansi
+# Ultrix and OSF/1	-std1
+# HP-UX 10.20 and later	-Ae
+# HP-UX older versions	-Aa -D_HPUX_SOURCE
+# SVR4			-Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
+
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+  x|xno)
+    echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+  *)
+    echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+    CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+# Some people use a C++ compiler to compile C.  Since we use `exit',
+# in C++ we need to declare it.  In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+  choke me
+#endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  for ac_declaration in \
+   ''\
+   '#include <stdlib.h>' \
+   'extern "C" void std::exit (int) throw (); using std::exit;' \
+   'extern "C" void std::exit (int); using std::exit;' \
+   'extern "C" void exit (int) throw ();' \
+   'extern "C" void exit (int);' \
+   'void exit (int);'
+do
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+$ac_declaration
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+  echo '#ifdef __cplusplus' >>confdefs.h
+  echo $ac_declaration      >>confdefs.h
+  echo '#endif'             >>confdefs.h
+fi
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Check whether --enable-64 or --disable-64 was given.
+if test "${enable_64+set}" = set; then
+  enableval="$enable_64"
+  use_sixty_four=$enableval
+else
+  use_sixty_four=no
+fi;
+
+# Gcc does not support 32-bit pointers on the Alphas.
+if test "$gcc_ok" != no; then
+  use_sixty_four=yes
+fi
+
+
+# Roderick Bloem (rbloem@colorado.edu): making a special case for
+# ultrix install, since it's annoying about setting groupids.
+case "$target" in
+  mips-dec-ultrix*)
+    INSTALL="helpers/install-sh -c"
+    INSTALL_PROGRAM="\${INSTALL}"
+    INSTALL_DATA="\${INSTALL} -m 644";;
+
+  *)
+  # Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+  ./ | .// | /cC/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+        if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+          if test $ac_prog = install &&
+            grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+            # AIX install.  It has an incompatible calling convention.
+            :
+          elif test $ac_prog = install &&
+            grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+            # program-specific install script used by HP pwplus--don't use.
+            :
+          else
+            ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+            break 3
+          fi
+        fi
+      done
+    done
+    ;;
+esac
+done
+
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  We don't cache a
+    # path for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the path is relative.
+    INSTALL=$ac_install_sh
+  fi
+fi
+echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+ ;;
+esac
+
+# Determine the compiler flags to use
+
+DEBUG_CFLAGS="-g"
+DEBUG_LDFLAGS=""
+
+case "$target" in
+
+  i686-pc-linux-gnu)
+	# Linux with Intel compiler
+	# -ansi: ANSI C conformance
+	# -ip: inter-procedural optimization
+	OPTIMIZE_CFLAGS="-g -O3 -ansi -ip"
+	;;
+
+  sparc-sun-solaris* | i386-pc-solaris*)
+	# Sparc and X86 Solaris:
+	# -xO3: Highest safe level of optimization
+	# -native: Optimize for the native processor (if supported)
+	# -dalign: Generate double-word load/store for performance
+	#          (only for SPARC)
+	# and other arcane compilation flags.
+	if test "$GCC" = yes; then
+	  OPTIMIZE_CFLAGS="-O"
+	else
+	  case "$target" in
+            sparc-sun-solaris*)
+	      ALIGN=" -dalign" ;;
+	    *)
+	      ALIGN="" ;;
+          esac
+	  echo "$as_me:$LINENO: checking for -native" >&5
+echo $ECHO_N "checking for -native... $ECHO_C" >&6
+	  CFLAGS="-xO3 -native$ALIGN"
+
+if test "${ac_cv_have_native+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+   if test "$cross_compiling" = yes; then
+  ac_cv_have_native=no
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+	  main(){exit(0);}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_have_native=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_have_native=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+
+	  if test $ac_cv_have_native = yes ; then
+	    echo "$as_me:$LINENO: result: working" >&5
+echo "${ECHO_T}working" >&6
+	    OPTIMIZE_CFLAGS="-xO3 -native$ALIGN"
+	  else
+	    echo "$as_me:$LINENO: result: broken" >&5
+echo "${ECHO_T}broken" >&6
+	    echo "$as_me:$LINENO: checking for fallback optimization flags" >&5
+echo $ECHO_N "checking for fallback optimization flags... $ECHO_C" >&6
+	    CFLAGS="-xO3 -fns -fsimple=2$ALIGN -ftrap=%none -xlibmil"
+	    if test "${ac_cv_have_fallback+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+   if test "$cross_compiling" = yes; then
+  ac_cv_have_fallback=no
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+	    main(){exit(0);}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_have_fallback=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_have_fallback=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+
+	    if test $ac_cv_have_fallback = yes ; then
+	      echo "$as_me:$LINENO: result: working" >&5
+echo "${ECHO_T}working" >&6
+	      OPTIMIZE_CFLAGS="-xO3 -fns -fsimple=2$ALIGN -ftrap=%none -xlibmil"
+	    else
+	      echo "$as_me:$LINENO: result: broken" >&5
+echo "${ECHO_T}broken" >&6
+	      OPTIMIZE_CFLAGS="-O"
+	    fi
+	  fi
+	fi
+        ;;
+
+  mips-dec-ultrix*)
+	# MIPS-based DECstations running Ultrix:
+	# -std1: Produce non-ANSI code warnings, and define __STDC__
+	# -O: Use the global "ucode" optimizer
+	# -Olimit 5000: Don't optimize routines bigger than 5000 basic blocks
+	OPTIMIZE_CFLAGS="-std1 -O -Olimit 5000" ;;
+
+  alpha-dec-osf*)
+	# DEC Alpha running OSF:
+
+	# 64-bit mode:
+	# -g3: Produce symbol table information for optimized code
+	# -O4: Enable every optimization
+	# -std: Enforce the ANSI standard with extensions, define __STDC__
+	# -ieee_with_no_inexact: Disable (potentially slow) signaling
+	#   for inexact floating-point results
+	# -tune host: Tune instructions for the compilation host machine
+	OPTIMIZE_CFLAGS="-g3 -O4 -std -ieee_with_no_inexact -tune host"
+	DEBUG_CFLAGS="-g -std -ieee_with_no_inexact"
+
+	# -non_shared: Do not use shared libraries
+	# -om: Generate an OMAGIC file for the om optimizer
+	OPTIMIZE_LDFLAGS="-non_shared"
+
+	if test "$use_sixty_four" = "no"; then
+	  # 32-bit mode:
+	  # -xtaso: Make the compiler respond to #pragma pointer_size directives
+          OPTIMIZE_CFLAGS="$OPTIMIZE_CFLAGS -xtaso"
+          DEBUG_CFLAGS="$DEBUG_CFLAGS -xtaso"
+
+	  # -taso: Load the executable into the lower 31-bit address space
+	  OPTIMIZE_LDFLAGS="$OPTIMIZE_LDFLAGS -om -taso"
+	  DEBUG_LDFLAGS="$DEBUG_LDFLAGS -taso"
+
+	  cat >>confdefs.h <<\_ACEOF
+#define SIZEOF_VOID_P 4
+_ACEOF
+
+          ac_sizeof_voidp=4
+        fi
+	;;
+
+  hppa*-*-hpux*)
+	# HP running HPUX
+	# -Aa: Behave as an ANSI compiler
+	# -D_HPUX_SOURCE: Include "HP-specific" symbols in the header
+	#   files (e.g., this means sys/resource.h has struct rusage)
+	# +Onolimit: removes resource restrictions for optimization
+	OPTIMIZE_CFLAGS="-O -Aa +Onolimit -D_HPUX_SOURCE"
+	DEBUG_CFLAGS="-g -Aa -D_HPUX_SOURCE" ;;
+
+     *)
+	# Other systems:
+	OPTIMIZE_CFLAGS="-O" ;;
+
+esac
+
+if test "$GCC" = yes; then
+  case "$target" in
+    i686-pc-linux-gnu | i386-pc-solaris* | i386-pc-cygwin32 | i386-*-freebsd*)
+      echo "$as_me:$LINENO: checking for -mcpu and -malign compiler options" >&5
+echo $ECHO_N "checking for -mcpu and -malign compiler options... $ECHO_C" >&6
+      CFLAGS="-g -O6 -mcpu=pentiumpro -malign-double"
+      cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_have_mcpu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_have_mcpu=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+      if test "$ac_have_mcpu" = yes; then
+        echo "$as_me:$LINENO: result: working" >&5
+echo "${ECHO_T}working" >&6
+        OPTIMIZE_CFLAGS="-g -O6 -mcpu=pentiumpro -malign-double"
+      else
+        echo "$as_me:$LINENO: result: broken" >&5
+echo "${ECHO_T}broken" >&6
+        OPTIMIZE_CFLAGS="-g -O3"
+      fi
+      ;;
+    sparc-sun-solaris*)
+      echo "$as_me:$LINENO: checking for -mtune compiler option" >&5
+echo $ECHO_N "checking for -mtune compiler option... $ECHO_C" >&6
+      CFLAGS="-g -O6 -mtune=ultrasparc"
+      cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_have_mtune=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_have_mtune=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+      if test "$ac_have_mtune" = yes; then
+        echo "$as_me:$LINENO: result: working" >&5
+echo "${ECHO_T}working" >&6
+        OPTIMIZE_CFLAGS="-g -O6 -mtune=ultrasparc"
+      else
+        echo "$as_me:$LINENO: result: not working" >&5
+echo "${ECHO_T}not working" >&6
+        OPTIMIZE_CFLAGS="-g -O3"
+      fi
+      ;;
+    *)
+      OPTIMIZE_CFLAGS="-g -O3"
+      ;;
+  esac
+  OPTIMIZE_LDFLAGS=""
+  DEBUG_CFLAGS="-g"
+  DEBUG_LDFLAGS=""
+fi
+
+
+# Check whether --with-comp-mode or --without-comp-mode was given.
+if test "${with_comp_mode+set}" = set; then
+  withval="$with_comp_mode"
+  comp_mode=$withval
+else
+  comp_mode=optimize
+fi;
+
+
+
+LINKER="$CC"
+
+case "$comp_mode" in
+  debug)
+       CFLAGS="$DEBUG_CFLAGS"
+       LDFLAGS="$DEBUG_LDFLAGS" ;;
+  purify)
+       CFLAGS="$DEBUG_CFLAGS"
+       LDFLAGS="$DEBUG_LDFLAGS"
+       cat >>confdefs.h <<\_ACEOF
+#define PURIFY 1
+_ACEOF
+
+       LINKER="purify -cache-dir=/tmp $CC"
+       PLINKER="purify -log-file=./purify.log -cachedir=/tmp $CC" ;;
+  quantify)
+       CFLAGS="$OPTIMIZE_CFLAGS"
+       LDFLAGS="$OPTIMIZE_LDFLAGS"
+       cat >>confdefs.h <<\_ACEOF
+#define QUANTIFY 1
+_ACEOF
+
+       cat >>confdefs.h <<\_ACEOF
+#define NDEBUG 1
+_ACEOF
+
+       LINKER="quantify $CC" ;;
+  optimize | *)
+       CFLAGS="$OPTIMIZE_CFLAGS"
+       LDFLAGS="$OPTIMIZE_LDFLAGS"
+       cat >>confdefs.h <<\_ACEOF
+#define NDEBUG 1
+_ACEOF
+ ;;
+esac
+
+for ac_prog in flex lex
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_LEX+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$LEX"; then
+  ac_cv_prog_LEX="$LEX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_LEX="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+LEX=$ac_cv_prog_LEX
+if test -n "$LEX"; then
+  echo "$as_me:$LINENO: result: $LEX" >&5
+echo "${ECHO_T}$LEX" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$LEX" && break
+done
+test -n "$LEX" || LEX=":"
+
+if test -z "$LEXLIB"
+then
+  echo "$as_me:$LINENO: checking for yywrap in -lfl" >&5
+echo $ECHO_N "checking for yywrap in -lfl... $ECHO_C" >&6
+if test "${ac_cv_lib_fl_yywrap+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lfl  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char yywrap ();
+int
+main ()
+{
+yywrap ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_fl_yywrap=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_fl_yywrap=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_fl_yywrap" >&5
+echo "${ECHO_T}$ac_cv_lib_fl_yywrap" >&6
+if test $ac_cv_lib_fl_yywrap = yes; then
+  LEXLIB="-lfl"
+else
+  echo "$as_me:$LINENO: checking for yywrap in -ll" >&5
+echo $ECHO_N "checking for yywrap in -ll... $ECHO_C" >&6
+if test "${ac_cv_lib_l_yywrap+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ll  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char yywrap ();
+int
+main ()
+{
+yywrap ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_l_yywrap=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_l_yywrap=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_l_yywrap" >&5
+echo "${ECHO_T}$ac_cv_lib_l_yywrap" >&6
+if test $ac_cv_lib_l_yywrap = yes; then
+  LEXLIB="-ll"
+fi
+
+fi
+
+fi
+
+if test "x$LEX" != "x:"; then
+  echo "$as_me:$LINENO: checking lex output file root" >&5
+echo $ECHO_N "checking lex output file root... $ECHO_C" >&6
+if test "${ac_cv_prog_lex_root+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # The minimal lex program is just a single line: %%.  But some broken lexes
+# (Solaris, I think it was) want two %% lines, so accommodate them.
+cat >conftest.l <<_ACEOF
+%%
+%%
+_ACEOF
+{ (eval echo "$as_me:$LINENO: \"$LEX conftest.l\"") >&5
+  (eval $LEX conftest.l) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+if test -f lex.yy.c; then
+  ac_cv_prog_lex_root=lex.yy
+elif test -f lexyy.c; then
+  ac_cv_prog_lex_root=lexyy
+else
+  { { echo "$as_me:$LINENO: error: cannot find output from $LEX; giving up" >&5
+echo "$as_me: error: cannot find output from $LEX; giving up" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_lex_root" >&5
+echo "${ECHO_T}$ac_cv_prog_lex_root" >&6
+rm -f conftest.l
+LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root
+
+echo "$as_me:$LINENO: checking whether yytext is a pointer" >&5
+echo $ECHO_N "checking whether yytext is a pointer... $ECHO_C" >&6
+if test "${ac_cv_prog_lex_yytext_pointer+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # POSIX says lex can declare yytext either as a pointer or an array; the
+# default is implementation-dependent. Figure out which it is, since
+# not all implementations provide the %pointer and %array declarations.
+ac_cv_prog_lex_yytext_pointer=no
+echo 'extern char *yytext;' >>$LEX_OUTPUT_ROOT.c
+ac_save_LIBS=$LIBS
+LIBS="$LIBS $LEXLIB"
+cat >conftest.$ac_ext <<_ACEOF
+`cat $LEX_OUTPUT_ROOT.c`
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_lex_yytext_pointer=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_save_LIBS
+rm -f "${LEX_OUTPUT_ROOT}.c"
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_lex_yytext_pointer" >&5
+echo "${ECHO_T}$ac_cv_prog_lex_yytext_pointer" >&6
+if test $ac_cv_prog_lex_yytext_pointer = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define YYTEXT_POINTER 1
+_ACEOF
+
+fi
+
+fi
+echo "$as_me:$LINENO: checking if $LEX accepts the -o and -P options" >&5
+echo $ECHO_N "checking if $LEX accepts the -o and -P options... $ECHO_C" >&6
+
+if test "${ac_cv_flex_accepts_op+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+   ac_cv_flex_accepts_op=yes ;
+echo "%%\
+%%" | $LEX -Ptest -o/dev/null >/dev/null 2>&1 || ac_cv_flex_accepts_op=no
+fi
+
+if test $ac_cv_flex_accepts_op = yes ; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+  { echo "$as_me:$LINENO: WARNING: You either need a newer version of flex, or need to modify
+the defintion of LEX in the Makefile to point to a version that does
+accept -p -t and -o." >&5
+echo "$as_me: WARNING: You either need a newer version of flex, or need to modify
+the defintion of LEX in the Makefile to point to a version that does
+accept -p -t and -o." >&2;}
+fi
+
+for ac_prog in 'bison -y' byacc
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_YACC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$YACC"; then
+  ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_YACC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+YACC=$ac_cv_prog_YACC
+if test -n "$YACC"; then
+  echo "$as_me:$LINENO: result: $YACC" >&5
+echo "${ECHO_T}$YACC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
+
+echo "$as_me:$LINENO: checking if $YACC accepts the -p, -t, and -o options" >&5
+echo $ECHO_N "checking if $YACC accepts the -p, -t, and -o options... $ECHO_C" >&6
+if test "${ac_cv_yacc_accepts_pto+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+   ac_cv_yacc_accepts_pto=yes ;
+echo "%token terminal\
+%%\
+nonterminal: terminal\
+%%" > config.in
+$YACC -ptest -o /dev/null config.in >/dev/null 2>&1 || ac_cv_yacc_accepts_pto=no
+rm -f config.in
+fi
+
+if test $ac_cv_yacc_accepts_pto = yes ; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+  { echo "$as_me:$LINENO: WARNING: You either need a newer version of bison, or need to modify
+the defintion of YACC in the Makefile to point to a version that does
+accept -p -t and -o." >&5
+echo "$as_me: WARNING: You either need a newer version of bison, or need to modify
+the defintion of YACC in the Makefile to point to a version that does
+accept -p -t and -o." >&2;}
+fi
+
+#----------------------------------------------------------------------
+# Checks for headers and libraries
+#----------------------------------------------------------------------
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                     Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                     Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6
+if test "${ac_cv_prog_egrep+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+    then ac_cv_prog_egrep='grep -E'
+    else ac_cv_prog_egrep='egrep'
+    fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
+echo "${ECHO_T}$ac_cv_prog_egrep" >&6
+ EGREP=$ac_cv_prog_egrep
+
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+                   (('a' <= (c) && (c) <= 'i') \
+                     || ('j' <= (c) && (c) <= 'r') \
+                     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+        || toupper (i) != TOUPPER (i))
+      exit(2);
+  exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+
+
+
+# add -lucb to LIBS and -L/usr/ucblib to LIBDIRS
+# if there's a libucb.a available
+# (Solaris needs this for signals)
+
+ac_save_ldflags="$LDFLAGS"
+LDFLAGS=-L/usr/ucblib
+echo "$as_me:$LINENO: checking for main in -lucb" >&5
+echo $ECHO_N "checking for main in -lucb... $ECHO_C" >&6
+if test "${ac_cv_lib_ucb_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lucb  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_ucb_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_ucb_main=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_ucb_main" >&5
+echo "${ECHO_T}$ac_cv_lib_ucb_main" >&6
+if test $ac_cv_lib_ucb_main = yes; then
+  LIBDIRS="$LIBDIRS -L/usr/ucblib"
+fi
+
+LDFLAGS="$ac_save_ldflags"
+
+# add -lbsd if there's a libbsd.a available
+# (e.g., Linux needs this for bsd_ioctl)
+
+echo "$as_me:$LINENO: checking for main in -lbsd" >&5
+echo $ECHO_N "checking for main in -lbsd... $ECHO_C" >&6
+if test "${ac_cv_lib_bsd_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lbsd  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_bsd_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_bsd_main=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_bsd_main" >&5
+echo "${ECHO_T}$ac_cv_lib_bsd_main" >&6
+if test $ac_cv_lib_bsd_main = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBBSD 1
+_ACEOF
+
+  LIBS="-lbsd $LIBS"
+
+fi
+
+
+# Check if libreadline exists and the function readline can be used.
+# This implies checking for the availability of libtermcap or of a
+# suitable replacement.  (We only look for libncurses.)
+if test "${vis_cv_termcap_lib+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  echo "$as_me:$LINENO: checking for tgetent in -ltermcap" >&5
+echo $ECHO_N "checking for tgetent in -ltermcap... $ECHO_C" >&6
+if test "${ac_cv_lib_termcap_tgetent+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ltermcap  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char tgetent ();
+int
+main ()
+{
+tgetent ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_termcap_tgetent=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_termcap_tgetent=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_termcap_tgetent" >&5
+echo "${ECHO_T}$ac_cv_lib_termcap_tgetent" >&6
+if test $ac_cv_lib_termcap_tgetent = yes; then
+  vis_cv_termcap_lib=-ltermcap
+else
+  echo "$as_me:$LINENO: checking for tgetent in -lncurses" >&5
+echo $ECHO_N "checking for tgetent in -lncurses... $ECHO_C" >&6
+if test "${ac_cv_lib_ncurses_tgetent+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lncurses  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char tgetent ();
+int
+main ()
+{
+tgetent ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_ncurses_tgetent=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_ncurses_tgetent=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_ncurses_tgetent" >&5
+echo "${ECHO_T}$ac_cv_lib_ncurses_tgetent" >&6
+if test $ac_cv_lib_ncurses_tgetent = yes; then
+  vis_cv_termcap_lib=-lncurses
+else
+  bash_cv_termcap_lib=none
+fi
+
+fi
+
+fi
+
+if test "$vis_cv_termcap_lib" != none; then
+  echo "$as_me:$LINENO: checking for readline in -lreadline" >&5
+echo $ECHO_N "checking for readline in -lreadline... $ECHO_C" >&6
+if test "${ac_cv_lib_readline_readline+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lreadline $vis_cv_termcap_lib $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char readline ();
+int
+main ()
+{
+readline ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_readline_readline=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_readline_readline=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_readline_readline" >&5
+echo "${ECHO_T}$ac_cv_lib_readline_readline" >&6
+if test $ac_cv_lib_readline_readline = yes; then
+  ac_readline_flag=1
+else
+  ac_readline_flag=0
+fi
+
+  if test $ac_readline_flag = 1 ; then
+    LIBS="$LIBS -lreadline $vis_cv_termcap_lib" ; cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBREADLINE 1
+_ACEOF
+
+  fi
+fi
+
+# Check for the dirent header file, which is quite a mess
+
+
+
+
+
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do
+  as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5
+echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <$ac_hdr>
+
+int
+main ()
+{
+if ((DIR *) 0)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1
+_ACEOF
+
+ac_header_dirent=$ac_hdr; break
+fi
+
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+  echo "$as_me:$LINENO: checking for library containing opendir" >&5
+echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6
+if test "${ac_cv_search_opendir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+ac_cv_search_opendir=no
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
+int
+main ()
+{
+opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_opendir="none required"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_opendir" = no; then
+  for ac_lib in dir; do
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+    cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
+int
+main ()
+{
+opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_opendir="-l$ac_lib"
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+  done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
+echo "${ECHO_T}$ac_cv_search_opendir" >&6
+if test "$ac_cv_search_opendir" != no; then
+  test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS"
+
+fi
+
+else
+  echo "$as_me:$LINENO: checking for library containing opendir" >&5
+echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6
+if test "${ac_cv_search_opendir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+ac_cv_search_opendir=no
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
+int
+main ()
+{
+opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_opendir="none required"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_opendir" = no; then
+  for ac_lib in x; do
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+    cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
+int
+main ()
+{
+opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_opendir="-l$ac_lib"
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+  done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
+echo "${ECHO_T}$ac_cv_search_opendir" >&6
+if test "$ac_cv_search_opendir" != no; then
+  test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS"
+
+fi
+
+fi
+
+
+# Check for these system header files
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+                  inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+
+
+
+
+
+for ac_header in sys/termios.h sys/ioctl.h sys/time.h signal.h sys/signal.h readline/readline.h readline/history.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc in
+  yes:no )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------ ##
+## Report this to bug-autoconf@gnu.org. ##
+## ------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+  no:yes )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------ ##
+## Report this to bug-autoconf@gnu.org. ##
+## ------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+# This is for Linux
+
+for ac_header in bsd/sgtty.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc in
+  yes:no )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------ ##
+## Report this to bug-autoconf@gnu.org. ##
+## ------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+  no:yes )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------ ##
+## Report this to bug-autoconf@gnu.org. ##
+## ------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+# Some systems want both sys/ioctl.h and sys/termios.h, but others can
+# only have one -- check for that
+
+echo "$as_me:$LINENO: checking whether sys/termios.h and sys/ioctl.h should both be included" >&5
+echo $ECHO_N "checking whether sys/termios.h and sys/ioctl.h should both be included... $ECHO_C" >&6
+
+if test "${ac_cv_ioctl_with_termios+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <sys/termios.h>
+#include <sys/ioctl.h>
+
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_cv_ioctl_with_termios=1
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_cv_ioctl_with_termios=0
+fi
+rm -f conftest.err conftest.$ac_ext
+fi
+
+if test $ac_cv_ioctl_with_termios = 1 ; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6 ; cat >>confdefs.h <<\_ACEOF
+#define IOCTL_WITH_TERMIOS 1
+_ACEOF
+
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+# cmdFile.c wants to be able to use TIOCGETC to do file completion,
+# but some systems (e.g., HPUX) don't have this
+#
+
+echo "$as_me:$LINENO: checking for TIOCGETC" >&5
+echo $ECHO_N "checking for TIOCGETC... $ECHO_C" >&6
+
+if test "${ac_cv_have_ioctl_with_tiocgetc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test $ac_cv_ioctl_with_termios = 1 ; then
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/termios.h>
+#include <sys/ioctl.h>
+#ifdef TIOCGETC
+  yes
+#endif
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "yes" >/dev/null 2>&1; then
+  ac_cv_have_ioctl_with_tiocgetc=yes
+else
+  ac_cv_have_ioctl_with_tiocgetc=no
+fi
+rm -f conftest*
+
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/ioctl.h>
+#ifdef TIOCGETC
+  yes
+#endif
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "yes" >/dev/null 2>&1; then
+  ac_cv_have_ioctl_with_tiocgetc=yes
+else
+  ac_cv_have_ioctl_with_tiocgetc=no
+fi
+rm -f conftest*
+
+fi
+fi
+
+if test $ac_cv_have_ioctl_with_tiocgetc = "yes" ; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6 ; cat >>confdefs.h <<\_ACEOF
+#define HAVE_IOCTL_WITH_TIOCGETC 1
+_ACEOF
+
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+#  # cmdFile.c wants to turn off interrupts, but some systems don't
+#  # seem to know how to do that using TIOCLBIS
+#  #
+#  # This is probably fairly fragile, and it's probably cmdFile.c that should
+#  # be fixed
+#  #
+#  # This has been very unreliable (e.g., on Solaris), so the facility has
+#  # been turned off
+#
+#  if test $ac_cv_have_ioctl_with_tiocgetc = "yes" ; then
+#
+#    AC_MSG_CHECKING(for TIOCLBIS)
+#
+#    AC_CACHE_VAL(ac_cv_have_term_interrupts,
+#    [AC_EGREP_CPP(yes,
+#    [#include <sys/ioctl.h>
+#  #include <sys/termios.h>
+#  #ifdef TIOCLBIS
+#   yes
+#  #endif
+#  ], ac_cv_have_term_interrupts=1,
+#    ac_cv_have_term_interrupts=0 )])
+#
+#    if test $ac_cv_have_term_interrupts = 1 ; then
+#      AC_MSG_RESULT(yes) ; AC_DEFINE(HAVE_TERM_INTERRUPTS)
+#    else
+#      AC_MSG_RESULT(no)
+#    fi
+#
+#  fi	# ac_cv_have_ioctl_with_tiocgetc
+
+#----------------------------------------------------------------------
+# Checks for typedefs, structures, and compiler characteristics.
+#----------------------------------------------------------------------
+
+# Check to see if the compiler understands "const"
+# #define it empty otherwise
+echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
+echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6
+if test "${ac_cv_c_const+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+  /* Ultrix mips cc rejects this.  */
+  typedef int charset[2];
+  const charset x;
+  /* SunOS 4.1.1 cc rejects this.  */
+  char const *const *ccp;
+  char **p;
+  /* NEC SVR4.0.2 mips cc rejects this.  */
+  struct point {int x, y;};
+  static struct point const zero = {0,0};
+  /* AIX XL C 1.02.0.0 rejects this.
+     It does not let you subtract one const X* pointer from another in
+     an arm of an if-expression whose if-part is not a constant
+     expression */
+  const char *g = "string";
+  ccp = &g + (g ? g-g : 0);
+  /* HPUX 7.0 cc rejects these. */
+  ++ccp;
+  p = (char**) ccp;
+  ccp = (char const *const *) p;
+  { /* SCO 3.2v4 cc rejects this.  */
+    char *t;
+    char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+    *t++ = 0;
+  }
+  { /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */
+    int x[] = {25, 17};
+    const int *foo = &x[0];
+    ++foo;
+  }
+  { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+    typedef const int *iptr;
+    iptr p = 0;
+    ++p;
+  }
+  { /* AIX XL C 1.02.0.0 rejects this saying
+       "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+    struct s { int j; const int *ap[3]; };
+    struct s *b; b->j = 5;
+  }
+  { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+    const int foo = 10;
+  }
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_const=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_c_const=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
+echo "${ECHO_T}$ac_cv_c_const" >&6
+if test $ac_cv_c_const = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define const
+_ACEOF
+
+fi
+
+
+# Sort out "time.h" nonsense
+echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5
+echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6
+if test "${ac_cv_header_time+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+
+int
+main ()
+{
+if ((struct tm *) 0)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_header_time=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_time=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5
+echo "${ECHO_T}$ac_cv_header_time" >&6
+if test $ac_cv_header_time = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TIME_WITH_SYS_TIME 1
+_ACEOF
+
+fi
+
+
+echo "$as_me:$LINENO: checking whether struct tm is in sys/time.h or time.h" >&5
+echo $ECHO_N "checking whether struct tm is in sys/time.h or time.h... $ECHO_C" >&6
+if test "${ac_cv_struct_tm+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <time.h>
+
+int
+main ()
+{
+struct tm *tp; tp->tm_sec;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_struct_tm=time.h
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_struct_tm=sys/time.h
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_struct_tm" >&5
+echo "${ECHO_T}$ac_cv_struct_tm" >&6
+if test $ac_cv_struct_tm = sys/time.h; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TM_IN_SYS_TIME 1
+_ACEOF
+
+fi
+
+
+# Set RETSIGTYPE to the proper return type for a signal handler (void or int)
+echo "$as_me:$LINENO: checking return type of signal handlers" >&5
+echo $ECHO_N "checking return type of signal handlers... $ECHO_C" >&6
+if test "${ac_cv_type_signal+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <signal.h>
+#ifdef signal
+# undef signal
+#endif
+#ifdef __cplusplus
+extern "C" void (*signal (int, void (*)(int)))(int);
+#else
+void (*signal ()) ();
+#endif
+
+int
+main ()
+{
+int i;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_signal=void
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_signal=int
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_signal" >&5
+echo "${ECHO_T}$ac_cv_type_signal" >&6
+
+cat >>confdefs.h <<_ACEOF
+#define RETSIGTYPE $ac_cv_type_signal
+_ACEOF
+
+
+
+# Roderick Bloem (rbloem@colorado.edu) :  On Irix we need ttold
+case "$target" in
+  mips-sgi-irix*)
+    cat >>confdefs.h <<\_ACEOF
+#define NEED_TTOLD 1
+_ACEOF
+;;
+esac
+
+#----------------------------------------------------------------------
+# Checks for library functions.
+#----------------------------------------------------------------------
+
+if test $ac_cv_c_compiler_gnu = yes; then
+    echo "$as_me:$LINENO: checking whether $CC needs -traditional" >&5
+echo $ECHO_N "checking whether $CC needs -traditional... $ECHO_C" >&6
+if test "${ac_cv_prog_gcc_traditional+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+    ac_pattern="Autoconf.*'x'"
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sgtty.h>
+Autoconf TIOCGETP
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "$ac_pattern" >/dev/null 2>&1; then
+  ac_cv_prog_gcc_traditional=yes
+else
+  ac_cv_prog_gcc_traditional=no
+fi
+rm -f conftest*
+
+
+  if test $ac_cv_prog_gcc_traditional = no; then
+    cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <termio.h>
+Autoconf TCGETA
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "$ac_pattern" >/dev/null 2>&1; then
+  ac_cv_prog_gcc_traditional=yes
+fi
+rm -f conftest*
+
+  fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_gcc_traditional" >&5
+echo "${ECHO_T}$ac_cv_prog_gcc_traditional" >&6
+  if test $ac_cv_prog_gcc_traditional = yes; then
+    CC="$CC -traditional"
+  fi
+fi
+
+echo "$as_me:$LINENO: checking for working memcmp" >&5
+echo $ECHO_N "checking for working memcmp... $ECHO_C" >&6
+if test "${ac_cv_func_memcmp_working+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_memcmp_working=no
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  /* Some versions of memcmp are not 8-bit clean.  */
+  char c0 = 0x40, c1 = 0x80, c2 = 0x81;
+  if (memcmp(&c0, &c2, 1) >= 0 || memcmp(&c1, &c2, 1) >= 0)
+    exit (1);
+
+  /* The Next x86 OpenStep bug shows up only when comparing 16 bytes
+     or more and with at least one buffer not starting on a 4-byte boundary.
+     William Lewis provided this test program.   */
+  {
+    char foo[21];
+    char bar[21];
+    int i;
+    for (i = 0; i < 4; i++)
+      {
+        char *a = foo + i;
+        char *b = bar + i;
+        strcpy (a, "--------01111111");
+        strcpy (b, "--------10000000");
+        if (memcmp (a, b, 16) >= 0)
+          exit (1);
+      }
+    exit (0);
+  }
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_memcmp_working=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_memcmp_working=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_memcmp_working" >&5
+echo "${ECHO_T}$ac_cv_func_memcmp_working" >&6
+test $ac_cv_func_memcmp_working = no && LIBOBJS="$LIBOBJS memcmp.$ac_objext"
+
+echo "$as_me:$LINENO: checking return type of signal handlers" >&5
+echo $ECHO_N "checking return type of signal handlers... $ECHO_C" >&6
+if test "${ac_cv_type_signal+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <signal.h>
+#ifdef signal
+# undef signal
+#endif
+#ifdef __cplusplus
+extern "C" void (*signal (int, void (*)(int)))(int);
+#else
+void (*signal ()) ();
+#endif
+
+int
+main ()
+{
+int i;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_signal=void
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_signal=int
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_signal" >&5
+echo "${ECHO_T}$ac_cv_type_signal" >&6
+
+cat >>confdefs.h <<_ACEOF
+#define RETSIGTYPE $ac_cv_type_signal
+_ACEOF
+
+
+
+
+
+
+
+
+
+
+for ac_func in gettimeofday strchr strstr setvbuf getenv unlink mkstemp close
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+#-----------------------------------------------------------------------
+# Check for mawk, gawk, nawk, awk in that order
+#-----------------------------------------------------------------------
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_AWK+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AWK="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  echo "$as_me:$LINENO: result: $AWK" >&5
+echo "${ECHO_T}$AWK" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$AWK" && break
+done
+
+
+#----------------------------------------------------------------------
+# Create the Makefile from Makefile.in
+#----------------------------------------------------------------------
+if test "$gcc_ok" = "g++"; then
+  CC=$gcc_ok
+fi
+          ac_config_files="$ac_config_files Makefile"
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+  (set) 2>&1 |
+    case `(ac_space=' '; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+        "s/'/'\\\\''/g;
+    	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;;
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n \
+        "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+} |
+  sed '
+     t clear
+     : clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
+  if test -w $cache_file; then
+    test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+    cat confcache >$cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[ 	]*VPATH[ 	]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[ 	]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[ 	]*$//;
+}'
+fi
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then we branch to the quote section.  Otherwise,
+# look for a macro that doesn't take arguments.
+cat >confdef2opt.sed <<\_ACEOF
+t clear
+: clear
+s,^[ 	]*#[ 	]*define[ 	][ 	]*\([^ 	(][^ 	(]*([^)]*)\)[ 	]*\(.*\),-D\1=\2,g
+t quote
+s,^[ 	]*#[ 	]*define[ 	][ 	]*\([^ 	][^ 	]*\)[ 	]*\(.*\),-D\1=\2,g
+t quote
+d
+: quote
+s,[ 	`~#$^&*(){}\\|;'"<>?],\\&,g
+s,\[,\\&,g
+s,\],\\&,g
+s,\$,$$,g
+p
+_ACEOF
+# We use echo to avoid assuming a particular line-breaking character.
+# The extra dot is to prevent the shell from consuming trailing
+# line-breaks from the sub-command output.  A line-break within
+# single-quotes doesn't work because, if this script is created in a
+# platform that uses two characters for line-breaks (e.g., DOS), tr
+# would break.
+ac_LF_and_DOT=`echo; echo .`
+DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'`
+rm -f confdef2opt.sed
+
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_i=`echo "$ac_i" |
+         sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+  # 2. Add them.
+  ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+
+# Support unset when possible.
+if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)$' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+  	  /^X\/\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\/\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+	 case $as_dir in
+	 /*)
+	   if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+	     $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+	     $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+	     CONFIG_SHELL=$as_dir/$as_base
+	     export CONFIG_SHELL
+	     exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+	   fi;;
+	 esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='	' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" 	$as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.  Logging --version etc. is OK.
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.57.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+  echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+  echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+  echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+  echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number, then exit
+  -q, --quiet      do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+  --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.57,
+  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+INSTALL="$INSTALL"
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value.  By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "x$1" : 'x\([^=]*\)='`
+    ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  -*)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  *) # This is not an option, so the user has probably given explicit
+     # arguments.
+     ac_option=$1
+     ac_need_defaults=false;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --vers* | -V )
+    echo "$ac_cs_version"; exit 0 ;;
+  --he | --h)
+    # Conflict between --help and --header
+    { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    echo "$ac_cs_usage"; exit 0 ;;
+  --debug | --d* | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+    ac_need_defaults=false;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$ac_config_targets $1" ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+  echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+  exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+
+
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+  case "$ac_config_target" in
+  # Handling of arguments.
+  "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./confstat$$-$RANDOM
+  (umask 077 && mkdir $tmp)
+} ||
+{
+   echo "$me: cannot create a temporary directory in ." >&2
+   { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+  # Protect against being on the right side of a sed subst in config.status.
+  sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+   s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@glulibdir@,$glulibdir,;t t
+s,@gluincdir@,$gluincdir,;t t
+s,@vislibdir@,$vislibdir,;t t
+s,@local_srcdir@,$local_srcdir,;t t
+s,@BDDLIB@,$BDDLIB,;t t
+s,@ZCHAFF@,$ZCHAFF,;t t
+s,@AR@,$AR,;t t
+s,@RANLIB@,$RANLIB,;t t
+s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
+s,@build@,$build,;t t
+s,@build_cpu@,$build_cpu,;t t
+s,@build_vendor@,$build_vendor,;t t
+s,@build_os@,$build_os,;t t
+s,@host@,$host,;t t
+s,@host_cpu@,$host_cpu,;t t
+s,@host_vendor@,$host_vendor,;t t
+s,@host_os@,$host_os,;t t
+s,@target@,$target,;t t
+s,@target_cpu@,$target_cpu,;t t
+s,@target_vendor@,$target_vendor,;t t
+s,@target_os@,$target_os,;t t
+s,@CC@,$CC,;t t
+s,@CFLAGS@,$CFLAGS,;t t
+s,@LDFLAGS@,$LDFLAGS,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@ac_ct_CC@,$ac_ct_CC,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
+s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
+s,@INSTALL_DATA@,$INSTALL_DATA,;t t
+s,@LINKER@,$LINKER,;t t
+s,@PLINKER@,$PLINKER,;t t
+s,@LEX@,$LEX,;t t
+s,@LEXLIB@,$LEXLIB,;t t
+s,@LEX_OUTPUT_ROOT@,$LEX_OUTPUT_ROOT,;t t
+s,@YACC@,$YACC,;t t
+s,@CPP@,$CPP,;t t
+s,@EGREP@,$EGREP,;t t
+s,@LIBDIRS@,$LIBDIRS,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@AWK@,$AWK,;t t
+s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+CEOF
+
+_ACEOF
+
+  cat >>$CONFIG_STATUS <<\_ACEOF
+  # Split the substitutions into bite-sized pieces for seds with
+  # small command number limits, like on Digital OSF/1 and HP-UX.
+  ac_max_sed_lines=48
+  ac_sed_frag=1 # Number of current file.
+  ac_beg=1 # First line for current file.
+  ac_end=$ac_max_sed_lines # Line after last line for current file.
+  ac_more_lines=:
+  ac_sed_cmds=
+  while $ac_more_lines; do
+    if test $ac_beg -gt 1; then
+      sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    else
+      sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    fi
+    if test ! -s $tmp/subs.frag; then
+      ac_more_lines=false
+    else
+      # The purpose of the label and of the branching condition is to
+      # speed up the sed processing (if there are no `@' at all, there
+      # is no need to browse any of the substitutions).
+      # These are the two extra sed commands mentioned above.
+      (echo ':t
+  /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+      if test -z "$ac_sed_cmds"; then
+  	ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+      else
+  	ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+      fi
+      ac_sed_frag=`expr $ac_sed_frag + 1`
+      ac_beg=$ac_end
+      ac_end=`expr $ac_end + $ac_max_sed_lines`
+    fi
+  done
+  if test -z "$ac_sed_cmds"; then
+    ac_sed_cmds=cat
+  fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+        cat >$tmp/stdin
+        ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+        ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+        ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+  ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+         X"$ac_file" : 'X\(//\)[^/]' \| \
+         X"$ac_file" : 'X\(//\)$' \| \
+         X"$ac_file" : 'X\(/\)' \| \
+         .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+  { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+         X"$as_dir" : 'X\(//\)[^/]' \| \
+         X"$as_dir" : 'X\(//\)$' \| \
+         X"$as_dir" : 'X\(/\)' \| \
+         .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+  ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be
+# absolute.
+ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd`
+ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd`
+ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd`
+ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd`
+
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_builddir$INSTALL ;;
+  esac
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    configure_input=
+  else
+    configure_input="$ac_file.  "
+  fi
+  configure_input=$configure_input"Generated from `echo $ac_file_in |
+                                     sed 's,.*/,,'` by configure."
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+         # Absolute (can't be DOS-style, as IFS=:)
+         test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+         echo $f;;
+      *) # Relative
+         if test -f "$f"; then
+           # Build tree
+           echo $f
+         elif test -f "$srcdir/$f"; then
+           # Source tree
+           echo $srcdir/$f
+         else
+           # /dev/null tree
+           { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+         fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+s,@INSTALL@,$ac_INSTALL,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+  rm -f $tmp/stdin
+  if test x"$ac_file" != x-; then
+    mv $tmp/out $ac_file
+  else
+    cat $tmp/out
+    rm -f $tmp/out
+  fi
+
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || { (exit 1); exit 1; }
+fi
+
Index: vis_dev/vis-2.3/configure.in
===================================================================
--- vis_dev/vis-2.3/configure.in	(revision 14)
+++ vis_dev/vis-2.3/configure.in	(revision 14)
@@ -0,0 +1,547 @@
+dnl	Run autoconf on this file to produce the system configuration
+dnl	script "configure"
+
+# FileName	[ configure.in ]
+#
+# PackageName	[ vis ]
+#
+# Synopsis	[ System configuration script for autoconf ]
+#
+# SeeAlso	[ Makefile.in ]
+#
+# Author	[ Stephen Edwards <sedwards@eecs.berkeley.edu> ]
+#
+# Copyright	[
+#  Copyright (c) 1994-1996 The Regents of the Univ. of California.
+#  All rights reserved.
+#
+#  Permission is hereby granted, without written agreement and without license
+#  or royalty fees, to use, copy, modify, and distribute this software and its
+#  documentation for any purpose, provided that the above copyright notice and
+#  the following two paragraphs appear in all copies of this software.
+#
+#  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+#  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+#  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+#  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+#  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+#  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+#  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+#  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+#  ]
+#
+# Revision	[$Id: configure.in,v 1.62 2004/08/20 18:31:32 fabio Exp $]
+
+# Require autoconf version 2.11 or above -- it checks to see if the C
+# compiler actually works!
+
+AC_PREREQ(2.11)
+
+AC_INIT(src/cmd/cmd.h)
+
+# Look for install.sh, config.guess, and config.sub in the "helpers" dir
+AC_CONFIG_AUX_DIR(helpers)
+
+#----------------------------------------------------------------------
+# Configuration options
+#----------------------------------------------------------------------
+
+# Give the configurer a chance to set the location of the GLU tree
+
+AC_SUBST(glulibdir)
+AC_ARG_WITH(glu-libdir,
+[  --with-glu-libdir=<libdir> Specify directories to search for the GLU library.
+                          Expects to find <libdir>/libglu.a],
+[glulibdir=$withval], [glulibdir=""])
+
+AC_SUBST(gluincdir)
+AC_ARG_WITH(glu-incdir,
+[  --with-glu-incdir=<incdir> Specify directories to search for the GLU headers],
+[gluincdir=$withval], [gluincdir=""])
+
+# Give the configurer a chance to set a different location for the VIS
+# headers and library
+
+AC_SUBST(vislibdir)
+AC_ARG_WITH(vis-libdir,
+[  --with-vis-libdir=<libdir> Specify directories to search for the VIS
+			  and headers.  Defaults to \".\".
+                          Expects to find <libdir>/libvis.a],
+[vislibdir=$withval],
+[vislibdir="."])
+
+# Give the configurer a chance to set a different location for the VIS
+# source.  When specified, "srcdir" points to "master" source, and
+# "local_srcdir" points to the source under local development.
+
+AC_SUBST(local_srcdir)
+AC_ARG_WITH(local-srcdir,
+[  --with-local-srcdir=<srcdir> Specify the root directory to search for
+			  source for packages (the PKGS list).
+			  Expects to find, e.g., <srcdir>/tbl/tbl.c],
+[local_srcdir=$withval],
+[local_srcdir=$srcdir])
+
+# Give the configurer a chance to set the BDD library
+
+AC_SUBST(BDDLIB)
+AC_ARG_WITH(bdd,
+[  --with-bdd=<bddPackage> Specify the BDD library to link against.
+                          Defaults to --with-bdd=cu.],
+[BDDLIB=$withval],
+[BDDLIB=cu])
+
+#----------------------------------------------------------------------
+# Checks for programs we need
+#----------------------------------------------------------------------
+AC_PATH_PROG(ZCHAFF,zchaff)
+AC_PATH_PROG(AR, ar, ar)
+AC_PROG_RANLIB
+
+AC_CANONICAL_SYSTEM
+AC_SUBST(target)
+
+# Determine the name of the C compiler we're going to use
+
+AC_ARG_ENABLE(gcc,
+  [  --enable-gcc            Allow use of gcc if available],
+  [gcc_ok=$enableval], [gcc_ok=no])
+
+# We cannot set CC=g++ directly because many configuration test programs
+# do not compile with g++.  Hence, when the user specifies --enable-gcc=g++,
+# we set CC=gcc during configuration, and then CC=g++ at the end.
+# The same applies to icpc and icc.
+if test "$gcc_ok" != no; then
+  case "$gcc_ok" in
+    yes | g++)
+      CC=gcc ;;
+    icpc)
+      CC=icc ;;
+    *)
+      CC=$gcc_ok
+  esac
+else
+  if test -z "$CC" ; then
+    # Balakrishna Kumthekar <kumtheka@colorado.edu>
+    # As we do not support cc on RS6000, Cygwin and SunOS.
+    case "$target" in
+    rs6000-ibm-aix* | *-pc-cygwin32 | sparc-sun-sunos*)
+      CC=gcc ;;
+    *)
+      CC=cc ;;
+    esac
+  fi
+fi
+AC_PROG_CC
+
+AC_ARG_ENABLE(64,
+  [  --enable-64             Use 64-bit pointers on 64-bit Alpha machines],
+  [use_sixty_four=$enableval], [use_sixty_four=no])
+
+# Gcc does not support 32-bit pointers on the Alphas.
+if test "$gcc_ok" != no; then
+  use_sixty_four=yes
+fi
+
+
+# Roderick Bloem (rbloem@colorado.edu): making a special case for
+# ultrix install, since it's annoying about setting groupids.
+case "$target" in
+  mips-dec-ultrix*)
+    INSTALL="helpers/install-sh -c"
+    INSTALL_PROGRAM="\${INSTALL}"
+    INSTALL_DATA="\${INSTALL} -m 644";;
+
+  *)
+  AC_PROG_INSTALL ;;
+esac
+
+# Determine the compiler flags to use
+
+DEBUG_CFLAGS="-g"
+DEBUG_LDFLAGS=""
+
+case "$target" in
+
+  i686-pc-linux-gnu)
+	# Linux with Intel compiler
+	# -ansi: ANSI C conformance
+	# -ip: inter-procedural optimization
+	OPTIMIZE_CFLAGS="-g -O3 -ansi -ip"
+	;;
+
+  sparc-sun-solaris* | i386-pc-solaris*)
+	# Sparc and X86 Solaris:
+	# -xO3: Highest safe level of optimization
+	# -native: Optimize for the native processor (if supported)
+	# -dalign: Generate double-word load/store for performance
+	#          (only for SPARC)
+	# and other arcane compilation flags.
+	if test "$GCC" = yes; then
+	  OPTIMIZE_CFLAGS="-O"
+	else
+	  case "$target" in
+            sparc-sun-solaris*)
+	      ALIGN=" -dalign" ;;
+	    *)
+	      ALIGN="" ;;
+          esac
+	  AC_MSG_CHECKING([for -native])
+	  CFLAGS="-xO3 -native$ALIGN"
+	  AC_CACHE_VAL(ac_cv_have_native,
+	  [ AC_TRY_RUN([
+	  main(){exit(0);}
+	  ],ac_cv_have_native=yes,ac_cv_have_native=no,ac_cv_have_native=no)])
+	  if test $ac_cv_have_native = yes ; then
+	    AC_MSG_RESULT(working)
+	    OPTIMIZE_CFLAGS="-xO3 -native$ALIGN"
+	  else
+	    AC_MSG_RESULT(broken)
+	    AC_MSG_CHECKING([for fallback optimization flags])
+	    CFLAGS="-xO3 -fns -fsimple=2$ALIGN -ftrap=%none -xlibmil"
+	    AC_CACHE_VAL(ac_cv_have_fallback,
+	    [ AC_TRY_RUN([
+	    main(){exit(0);}
+	    ],ac_cv_have_fallback=yes,ac_cv_have_fallback=no,ac_cv_have_fallback=no)])
+	    if test $ac_cv_have_fallback = yes ; then
+	      AC_MSG_RESULT(working)
+	      OPTIMIZE_CFLAGS="-xO3 -fns -fsimple=2$ALIGN -ftrap=%none -xlibmil"
+	    else
+	      AC_MSG_RESULT(broken)
+	      OPTIMIZE_CFLAGS="-O"
+	    fi
+	  fi
+	fi
+        ;;
+
+  mips-dec-ultrix*)
+	# MIPS-based DECstations running Ultrix:
+	# -std1: Produce non-ANSI code warnings, and define __STDC__
+	# -O: Use the global "ucode" optimizer
+	# -Olimit 5000: Don't optimize routines bigger than 5000 basic blocks
+	OPTIMIZE_CFLAGS="-std1 -O -Olimit 5000" ;;
+   
+  alpha-dec-osf*)
+	# DEC Alpha running OSF:
+
+	# 64-bit mode:
+	# -g3: Produce symbol table information for optimized code
+	# -O4: Enable every optimization
+	# -std: Enforce the ANSI standard with extensions, define __STDC__
+	# -ieee_with_no_inexact: Disable (potentially slow) signaling
+	#   for inexact floating-point results
+	# -tune host: Tune instructions for the compilation host machine
+	OPTIMIZE_CFLAGS="-g3 -O4 -std -ieee_with_no_inexact -tune host"
+	DEBUG_CFLAGS="-g -std -ieee_with_no_inexact"
+
+	# -non_shared: Do not use shared libraries
+	# -om: Generate an OMAGIC file for the om optimizer
+	OPTIMIZE_LDFLAGS="-non_shared"
+
+	if test "$use_sixty_four" = "no"; then
+	  # 32-bit mode:
+	  # -xtaso: Make the compiler respond to #pragma pointer_size directives
+          OPTIMIZE_CFLAGS="$OPTIMIZE_CFLAGS -xtaso"
+          DEBUG_CFLAGS="$DEBUG_CFLAGS -xtaso"
+
+	  # -taso: Load the executable into the lower 31-bit address space
+	  OPTIMIZE_LDFLAGS="$OPTIMIZE_LDFLAGS -om -taso"
+	  DEBUG_LDFLAGS="$DEBUG_LDFLAGS -taso" 
+
+	  AC_DEFINE(SIZEOF_VOID_P, 4)
+          ac_sizeof_voidp=4
+        fi
+	;;
+
+  hppa*-*-hpux*)
+	# HP running HPUX
+	# -Aa: Behave as an ANSI compiler
+	# -D_HPUX_SOURCE: Include "HP-specific" symbols in the header
+	#   files (e.g., this means sys/resource.h has struct rusage)
+	# +Onolimit: removes resource restrictions for optimization
+	OPTIMIZE_CFLAGS="-O -Aa +Onolimit -D_HPUX_SOURCE"
+	DEBUG_CFLAGS="-g -Aa -D_HPUX_SOURCE" ;;
+
+     *)
+	# Other systems:
+	OPTIMIZE_CFLAGS="-O" ;;
+
+esac
+
+if test "$GCC" = yes; then
+  case "$target" in
+    i686-pc-linux-gnu | i386-pc-solaris* | i386-pc-cygwin32 | i386-*-freebsd*)
+      AC_MSG_CHECKING([for -mcpu and -malign compiler options])
+      CFLAGS="-g -O6 -mcpu=pentiumpro -malign-double"
+      AC_TRY_COMPILE(,,ac_have_mcpu=yes,ac_have_mcpu=no)
+      if test "$ac_have_mcpu" = yes; then
+        AC_MSG_RESULT(working)
+        OPTIMIZE_CFLAGS="-g -O6 -mcpu=pentiumpro -malign-double"
+      else
+        AC_MSG_RESULT(broken)
+        OPTIMIZE_CFLAGS="-g -O3"
+      fi
+      ;;
+    sparc-sun-solaris*)
+      AC_MSG_CHECKING([for -mtune compiler option])
+      CFLAGS="-g -O6 -mtune=ultrasparc"
+      AC_TRY_COMPILE(,,ac_have_mtune=yes,ac_have_mtune=no)
+      if test "$ac_have_mtune" = yes; then
+        AC_MSG_RESULT(working)
+        OPTIMIZE_CFLAGS="-g -O6 -mtune=ultrasparc"
+      else
+        AC_MSG_RESULT(not working)
+        OPTIMIZE_CFLAGS="-g -O3"
+      fi
+      ;;
+    *)
+      OPTIMIZE_CFLAGS="-g -O3"
+      ;;
+  esac
+  OPTIMIZE_LDFLAGS=""
+  DEBUG_CFLAGS="-g"
+  DEBUG_LDFLAGS=""
+fi
+
+AC_ARG_WITH(comp-mode,
+[  --with-comp-mode=<mode> Specify a special compilation mode:
+			  optimize (the default): Produce optimized
+				code, with symbol table information
+				if supported on the platform/compiler,
+				and without asserts.
+			  debug: Produce unoptimized code with symbol table
+				information and asserts enabled
+			  purify: Unoptimized code linked with purify
+			  quantify: Optimized code without asserts
+				linked with quantify],
+[comp_mode=$withval],
+[comp_mode=optimize])
+AC_SUBST(LINKER)
+AC_SUBST(PLINKER)
+
+LINKER="$CC"
+
+case "$comp_mode" in
+  debug)
+       CFLAGS="$DEBUG_CFLAGS"
+       LDFLAGS="$DEBUG_LDFLAGS" ;;
+  purify)
+       CFLAGS="$DEBUG_CFLAGS"
+       LDFLAGS="$DEBUG_LDFLAGS"
+       AC_DEFINE(PURIFY)
+       LINKER="purify -cache-dir=/tmp $CC"
+       PLINKER="purify -log-file=./purify.log -cachedir=/tmp $CC" ;;
+  quantify)
+       CFLAGS="$OPTIMIZE_CFLAGS"
+       LDFLAGS="$OPTIMIZE_LDFLAGS"
+       AC_DEFINE(QUANTIFY)
+       AC_DEFINE(NDEBUG)
+       LINKER="quantify $CC" ;;
+  optimize | *)
+       CFLAGS="$OPTIMIZE_CFLAGS"
+       LDFLAGS="$OPTIMIZE_LDFLAGS"
+       AC_DEFINE(NDEBUG) ;;
+esac
+
+AC_PROG_LEX
+AC_MSG_CHECKING(if $LEX accepts the -o and -P options)
+
+AC_CACHE_VAL(ac_cv_flex_accepts_op,
+[ ac_cv_flex_accepts_op=yes ;
+echo "%%\
+%%" | $LEX -Ptest -o/dev/null >/dev/null 2>&1 || ac_cv_flex_accepts_op=no ])
+if test $ac_cv_flex_accepts_op = yes ; then
+  AC_MSG_RESULT(yes)
+else
+  AC_MSG_RESULT(no)
+  AC_MSG_WARN([You either need a newer version of flex, or need to modify
+the defintion of LEX in the Makefile to point to a version that does
+accept -p -t and -o.])
+fi
+
+AC_PROG_YACC
+AC_MSG_CHECKING([if $YACC accepts the -p, -t, and -o options])
+AC_CACHE_VAL(ac_cv_yacc_accepts_pto,
+[ ac_cv_yacc_accepts_pto=yes ;
+echo "%token terminal\
+%%\
+nonterminal: terminal\
+%%" > config.in
+$YACC -ptest -o /dev/null config.in >/dev/null 2>&1 || ac_cv_yacc_accepts_pto=no
+rm -f config.in ])
+if test $ac_cv_yacc_accepts_pto = yes ; then
+  AC_MSG_RESULT(yes)
+else
+  AC_MSG_RESULT(no)
+  AC_MSG_WARN([You either need a newer version of bison, or need to modify
+the defintion of YACC in the Makefile to point to a version that does
+accept -p -t and -o.])
+fi
+
+#----------------------------------------------------------------------
+# Checks for headers and libraries
+#----------------------------------------------------------------------
+AC_HEADER_STDC
+
+AC_SUBST(LIBDIRS)
+
+# add -lucb to LIBS and -L/usr/ucblib to LIBDIRS
+# if there's a libucb.a available
+# (Solaris needs this for signals)
+
+ac_save_ldflags="$LDFLAGS"
+LDFLAGS=-L/usr/ucblib
+AC_CHECK_LIB(ucb,main,LIBDIRS="$LIBDIRS -L/usr/ucblib")
+LDFLAGS="$ac_save_ldflags"
+
+# add -lbsd if there's a libbsd.a available
+# (e.g., Linux needs this for bsd_ioctl)
+AC_CHECK_LIB(bsd,main)
+
+# Check if libreadline exists and the function readline can be used.
+# This implies checking for the availability of libtermcap or of a
+# suitable replacement.  (We only look for libncurses.)
+AC_CACHE_VAL(vis_cv_termcap_lib,
+[AC_CHECK_LIB(termcap, tgetent, vis_cv_termcap_lib=-ltermcap,
+  [AC_CHECK_LIB(ncurses, tgetent, vis_cv_termcap_lib=-lncurses,
+    bash_cv_termcap_lib=none)])])
+if test "$vis_cv_termcap_lib" != none; then
+  AC_CHECK_LIB(readline, readline, ac_readline_flag=1,
+               ac_readline_flag=0, $vis_cv_termcap_lib)
+  if test $ac_readline_flag = 1 ; then
+    LIBS="$LIBS -lreadline $vis_cv_termcap_lib" ; AC_DEFINE(HAVE_LIBREADLINE)
+  fi
+fi
+
+# Check for the dirent header file, which is quite a mess
+AC_HEADER_DIRENT
+
+# Check for these system header files
+AC_CHECK_HEADERS(sys/termios.h sys/ioctl.h sys/time.h signal.h sys/signal.h readline/readline.h readline/history.h)
+
+# This is for Linux
+AC_CHECK_HEADERS(bsd/sgtty.h)
+
+# Some systems want both sys/ioctl.h and sys/termios.h, but others can
+# only have one -- check for that
+
+AC_MSG_CHECKING(whether sys/termios.h and sys/ioctl.h should both be included)
+
+AC_CACHE_VAL(ac_cv_ioctl_with_termios,
+[AC_TRY_CPP([
+#include <sys/termios.h>
+#include <sys/ioctl.h>
+], ac_cv_ioctl_with_termios=1, ac_cv_ioctl_with_termios=0 )])
+if test $ac_cv_ioctl_with_termios = 1 ; then
+  AC_MSG_RESULT(yes) ; AC_DEFINE(IOCTL_WITH_TERMIOS)
+else
+  AC_MSG_RESULT(no)
+fi
+
+# cmdFile.c wants to be able to use TIOCGETC to do file completion,
+# but some systems (e.g., HPUX) don't have this
+#
+  
+AC_MSG_CHECKING(for TIOCGETC)
+
+AC_CACHE_VAL(ac_cv_have_ioctl_with_tiocgetc,
+[if test $ac_cv_ioctl_with_termios = 1 ; then
+  AC_EGREP_CPP(yes,
+[#include <sys/termios.h>
+#include <sys/ioctl.h>
+#ifdef TIOCGETC
+  yes
+#endif],
+  ac_cv_have_ioctl_with_tiocgetc=yes,
+  ac_cv_have_ioctl_with_tiocgetc=no)
+else
+  AC_EGREP_CPP(yes,
+[#include <sys/ioctl.h>
+#ifdef TIOCGETC
+  yes
+#endif],
+  ac_cv_have_ioctl_with_tiocgetc=yes,
+  ac_cv_have_ioctl_with_tiocgetc=no)
+fi])
+if test $ac_cv_have_ioctl_with_tiocgetc = "yes" ; then
+  AC_MSG_RESULT(yes) ; AC_DEFINE(HAVE_IOCTL_WITH_TIOCGETC)
+else
+  AC_MSG_RESULT(no)
+fi
+
+#  # cmdFile.c wants to turn off interrupts, but some systems don't
+#  # seem to know how to do that using TIOCLBIS
+#  #
+#  # This is probably fairly fragile, and it's probably cmdFile.c that should
+#  # be fixed
+#  #
+#  # This has been very unreliable (e.g., on Solaris), so the facility has
+#  # been turned off
+#
+#  if test $ac_cv_have_ioctl_with_tiocgetc = "yes" ; then
+#  
+#    AC_MSG_CHECKING(for TIOCLBIS)
+#  
+#    AC_CACHE_VAL(ac_cv_have_term_interrupts,
+#    [AC_EGREP_CPP(yes,
+#    [#include <sys/ioctl.h>
+#  #include <sys/termios.h>
+#  #ifdef TIOCLBIS
+#   yes
+#  #endif
+#  ], ac_cv_have_term_interrupts=1,
+#    ac_cv_have_term_interrupts=0 )])
+#  
+#    if test $ac_cv_have_term_interrupts = 1 ; then
+#      AC_MSG_RESULT(yes) ; AC_DEFINE(HAVE_TERM_INTERRUPTS)
+#    else
+#      AC_MSG_RESULT(no)
+#    fi
+#  
+#  fi	# ac_cv_have_ioctl_with_tiocgetc
+
+#----------------------------------------------------------------------
+# Checks for typedefs, structures, and compiler characteristics.
+#----------------------------------------------------------------------
+
+# Check to see if the compiler understands "const"
+# #define it empty otherwise
+AC_C_CONST
+
+# Sort out "time.h" nonsense
+AC_HEADER_TIME
+
+AC_STRUCT_TM
+
+# Set RETSIGTYPE to the proper return type for a signal handler (void or int)
+AC_TYPE_SIGNAL
+
+# Roderick Bloem (rbloem@colorado.edu) :  On Irix we need ttold
+case "$target" in
+  mips-sgi-irix*) 
+    AC_DEFINE(NEED_TTOLD);;
+esac
+
+#----------------------------------------------------------------------
+# Checks for library functions.
+#----------------------------------------------------------------------
+
+AC_PROG_GCC_TRADITIONAL
+AC_FUNC_MEMCMP
+AC_TYPE_SIGNAL
+AC_CHECK_FUNCS(gettimeofday strchr strstr setvbuf getenv unlink mkstemp close)
+
+#-----------------------------------------------------------------------
+# Check for mawk, gawk, nawk, awk in that order
+#-----------------------------------------------------------------------
+AC_PROG_AWK
+
+#----------------------------------------------------------------------
+# Create the Makefile from Makefile.in
+#----------------------------------------------------------------------
+if test "$gcc_ok" = "g++"; then
+  CC=$gcc_ok
+fi
+AC_OUTPUT(Makefile)
Index: vis_dev/vis-2.3/helpers/config.guess
===================================================================
--- vis_dev/vis-2.3/helpers/config.guess	(revision 14)
+++ vis_dev/vis-2.3/helpers/config.guess	(revision 14)
@@ -0,0 +1,1526 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+#   Free Software Foundation, Inc.
+
+timestamp='2008-01-23'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+	for c in cc gcc c89 c99 ; do
+	  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+	     CC_FOR_BUILD="$c"; break ;
+	  fi ;
+	done ;
+	if test x"$CC_FOR_BUILD" = x ; then
+	  CC_FOR_BUILD=no_compiler_found ;
+	fi
+	;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+	# NetBSD (nbsd) targets should (where applicable) match one or
+	# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+	# switched to ELF, *-*-netbsd* would select the old
+	# object file format.  This provides both forward
+	# compatibility and a consistent mechanism for selecting the
+	# object file format.
+	#
+	# Note: NetBSD doesn't particularly care about the vendor
+	# portion of the name.  We always set it to "unknown".
+	sysctl="sysctl -n hw.machine_arch"
+	UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+	    /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+	case "${UNAME_MACHINE_ARCH}" in
+	    armeb) machine=armeb-unknown ;;
+	    arm*) machine=arm-unknown ;;
+	    sh3el) machine=shl-unknown ;;
+	    sh3eb) machine=sh-unknown ;;
+	    sh5el) machine=sh5le-unknown ;;
+	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+	esac
+	# The Operating System including object format, if it has switched
+	# to ELF recently, or will in the future.
+	case "${UNAME_MACHINE_ARCH}" in
+	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+		eval $set_cc_for_build
+		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+			| grep __ELF__ >/dev/null
+		then
+		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+		    # Return netbsd for either.  FIX?
+		    os=netbsd
+		else
+		    os=netbsdelf
+		fi
+		;;
+	    *)
+	        os=netbsd
+		;;
+	esac
+	# The OS release
+	# Debian GNU/NetBSD machines have a different userland, and
+	# thus, need a distinct triplet. However, they do not need
+	# kernel version information, so it can be replaced with a
+	# suitable tag, in the style of linux-gnu.
+	case "${UNAME_VERSION}" in
+	    Debian*)
+		release='-gnu'
+		;;
+	    *)
+		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+		;;
+	esac
+	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+	# contains redundant information, the shorter form:
+	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+	echo "${machine}-${os}${release}"
+	exit ;;
+    *:OpenBSD:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+	exit ;;
+    *:ekkoBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+	exit ;;
+    *:SolidBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+	exit ;;
+    macppc:MirBSD:*:*)
+	echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    *:MirBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    alpha:OSF1:*:*)
+	case $UNAME_RELEASE in
+	*4.0)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+		;;
+	*5.*)
+	        UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+		;;
+	esac
+	# According to Compaq, /usr/sbin/psrinfo has been available on
+	# OSF/1 and Tru64 systems produced since 1995.  I hope that
+	# covers most systems running today.  This code pipes the CPU
+	# types through head -n 1, so we only detect the type of CPU 0.
+	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+	case "$ALPHA_CPU_TYPE" in
+	    "EV4 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV4.5 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "LCA4 (21066/21068)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV5 (21164)")
+		UNAME_MACHINE="alphaev5" ;;
+	    "EV5.6 (21164A)")
+		UNAME_MACHINE="alphaev56" ;;
+	    "EV5.6 (21164PC)")
+		UNAME_MACHINE="alphapca56" ;;
+	    "EV5.7 (21164PC)")
+		UNAME_MACHINE="alphapca57" ;;
+	    "EV6 (21264)")
+		UNAME_MACHINE="alphaev6" ;;
+	    "EV6.7 (21264A)")
+		UNAME_MACHINE="alphaev67" ;;
+	    "EV6.8CB (21264C)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8AL (21264B)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8CX (21264D)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.9A (21264/EV69A)")
+		UNAME_MACHINE="alphaev69" ;;
+	    "EV7 (21364)")
+		UNAME_MACHINE="alphaev7" ;;
+	    "EV7.9 (21364A)")
+		UNAME_MACHINE="alphaev79" ;;
+	esac
+	# A Pn.n version is a patched version.
+	# A Vn.n version is a released version.
+	# A Tn.n version is a released field test version.
+	# A Xn.n version is an unreleased experimental baselevel.
+	# 1.2 uses "1.2" for uname -r.
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	exit ;;
+    Alpha\ *:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# Should we change UNAME_MACHINE based on the output of uname instead
+	# of the specific Alpha model?
+	echo alpha-pc-interix
+	exit ;;
+    21064:Windows_NT:50:3)
+	echo alpha-dec-winnt3.5
+	exit ;;
+    Amiga*:UNIX_System_V:4.0:*)
+	echo m68k-unknown-sysv4
+	exit ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-amigaos
+	exit ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-morphos
+	exit ;;
+    *:OS/390:*:*)
+	echo i370-ibm-openedition
+	exit ;;
+    *:z/VM:*:*)
+	echo s390-ibm-zvmoe
+	exit ;;
+    *:OS400:*:*)
+        echo powerpc-ibm-os400
+	exit ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix${UNAME_RELEASE}
+	exit ;;
+    arm:riscos:*:*|arm:RISCOS:*:*)
+	echo arm-unknown-riscos
+	exit ;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit ;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+		echo pyramid-pyramid-sysv3
+	else
+		echo pyramid-pyramid-bsd
+	fi
+	exit ;;
+    NILE*:*:*:dcosx)
+	echo pyramid-pyramid-svr4
+	exit ;;
+    DRS?6000:unix:4.0:6*)
+	echo sparc-icl-nx6
+	exit ;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+	case `/usr/bin/uname -p` in
+	    sparc) echo sparc-icl-nx7; exit ;;
+	esac ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+	echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:*:*)
+	case "`/usr/bin/arch -k`" in
+	    Series*|S4*)
+		UNAME_RELEASE=`uname -v`
+		;;
+	esac
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+	exit ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos${UNAME_RELEASE}
+	exit ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos${UNAME_RELEASE}
+		;;
+	    sun4)
+		echo sparc-sun-sunos${UNAME_RELEASE}
+		;;
+	esac
+	exit ;;
+    aushp:SunOS:*:*)
+	echo sparc-auspex-sunos${UNAME_RELEASE}
+	exit ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+        exit ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit ;;
+    m68k:machten:*:*)
+	echo m68k-apple-machten${UNAME_RELEASE}
+	exit ;;
+    powerpc:machten:*:*)
+	echo powerpc-apple-machten${UNAME_RELEASE}
+	exit ;;
+    RISC*:Mach:*:*)
+	echo mips-dec-mach_bsd4.3
+	exit ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	echo clipper-intergraph-clix${UNAME_RELEASE}
+	exit ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c &&
+	  dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+	  SYSTEM_NAME=`$dummy $dummyarg` &&
+	    { echo "$SYSTEM_NAME"; exit; }
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit ;;
+    Motorola:*:4.3:PL8-*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:Power_UNIX:*:*)
+	echo powerpc-harris-powerunix
+	exit ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+	then
+	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+	       [ ${TARGET_BINARY_INTERFACE}x = x ]
+	    then
+		echo m88k-dg-dgux${UNAME_RELEASE}
+	    else
+		echo m88k-dg-dguxbcs${UNAME_RELEASE}
+	    fi
+	else
+	    echo i586-dg-dgux${UNAME_RELEASE}
+	fi
+ 	exit ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit ;;
+    *:IRIX*:*:*)
+	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+	exit ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+	echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
+	exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	echo i386-ibm-aix
+	exit ;;
+    ia64:AIX:*:*)
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		eval $set_cc_for_build
+		sed 's/^		//' << EOF >$dummy.c
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+		then
+			echo "$SYSTEM_NAME"
+		else
+			echo rs6000-ibm-aix3.2.5
+		fi
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		echo rs6000-ibm-aix3.2.4
+	else
+		echo rs6000-ibm-aix3.2
+	fi
+	exit ;;
+    *:AIX:*:[456])
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+	echo romp-ibm-bsd4.4
+	exit ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+	exit ;;                             # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit ;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	case "${UNAME_MACHINE}" in
+	    9000/31? )            HP_ARCH=m68000 ;;
+	    9000/[34]?? )         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+		if [ -x /usr/bin/getconf ]; then
+		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+                        esac ;;
+                    esac
+		fi
+		if [ "${HP_ARCH}" = "" ]; then
+		    eval $set_cc_for_build
+		    sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+              	{
+              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+              	case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+              	    switch (bits)
+              		{
+              		case 64: puts ("hppa2.0w"); break;
+              		case 32: puts ("hppa2.0n"); break;
+              		default: puts ("hppa2.0"); break;
+              		} break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+              	    puts ("hppa2.0"); break;
+              #endif
+              	default: puts ("hppa1.0"); break;
+              	}
+                  exit (0);
+              }
+EOF
+		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+		    test -z "$HP_ARCH" && HP_ARCH=hppa
+		fi ;;
+	esac
+	if [ ${HP_ARCH} = "hppa2.0w" ]
+	then
+	    eval $set_cc_for_build
+
+	    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+	    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+	    # generating 64-bit code.  GNU and HP use different nomenclature:
+	    #
+	    # $ CC_FOR_BUILD=cc ./config.guess
+	    # => hppa2.0w-hp-hpux11.23
+	    # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+	    # => hppa64-hp-hpux11.23
+
+	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+		grep __LP64__ >/dev/null
+	    then
+		HP_ARCH="hppa2.0w"
+	    else
+		HP_ARCH="hppa64"
+	    fi
+	fi
+	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+	exit ;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	echo ia64-hp-hpux${HPUX_REV}
+	exit ;;
+    3050*:HI-UX:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+		{ echo "$SYSTEM_NAME"; exit; }
+	echo unknown-hitachi-hiuxwe2
+	exit ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+	echo hppa1.1-hp-bsd
+	exit ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+	echo hppa1.0-hp-mpeix
+	exit ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+	echo hppa1.1-hp-osf
+	exit ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit ;;
+    i*86:OSF1:*:*)
+	if [ -x /usr/sbin/sysversion ] ; then
+	    echo ${UNAME_MACHINE}-unknown-osf1mk
+	else
+	    echo ${UNAME_MACHINE}-unknown-osf1
+	fi
+	exit ;;
+    parisc*:Lites*:*:*)
+	echo hppa1.1-hp-lites
+	exit ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+        exit ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+        exit ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+        exit ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+        exit ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+        exit ;;
+    CRAY*Y-MP:*:*:*)
+	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*[A-Z]90:*:*:*)
+	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+	      -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*TS:*:*:*)
+	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*T3E:*:*:*)
+	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*SV1:*:*:*)
+	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    *:UNICOS/mp:*:*)
+	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit ;;
+    5000:UNIX_System_V:4.*:*)
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+	exit ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:BSD/OS:*:*)
+	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:FreeBSD:*:*)
+	case ${UNAME_MACHINE} in
+	    pc98)
+		echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	    amd64)
+		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	    *)
+		echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	esac
+	exit ;;
+    i*:CYGWIN*:*)
+	echo ${UNAME_MACHINE}-pc-cygwin
+	exit ;;
+    *:MINGW*:*)
+	echo ${UNAME_MACHINE}-pc-mingw32
+	exit ;;
+    i*:windows32*:*)
+    	# uname -m includes "-pc" on this system.
+    	echo ${UNAME_MACHINE}-mingw32
+	exit ;;
+    i*:PW*:*)
+	echo ${UNAME_MACHINE}-pc-pw32
+	exit ;;
+    *:Interix*:[3456]*)
+    	case ${UNAME_MACHINE} in
+	    x86)
+		echo i586-pc-interix${UNAME_RELEASE}
+		exit ;;
+	    EM64T | authenticamd)
+		echo x86_64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	    IA64)
+		echo ia64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	esac ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+	echo i${UNAME_MACHINE}-pc-mks
+	exit ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+	# UNAME_MACHINE based on the output of uname instead of i386?
+	echo i586-pc-interix
+	exit ;;
+    i*:UWIN*:*)
+	echo ${UNAME_MACHINE}-pc-uwin
+	exit ;;
+    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+	echo x86_64-unknown-cygwin
+	exit ;;
+    p*:CYGWIN*:*)
+	echo powerpcle-unknown-cygwin
+	exit ;;
+    prep*:SunOS:5.*:*)
+	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    *:GNU:*:*)
+	# the GNU system
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit ;;
+    *:GNU/*:*:*)
+	# other systems with GNU libc and userland
+	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+	exit ;;
+    i*86:Minix:*:*)
+	echo ${UNAME_MACHINE}-pc-minix
+	exit ;;
+    arm*:Linux:*:*)
+	eval $set_cc_for_build
+	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+	    | grep -q __ARM_EABI__
+	then
+	    echo ${UNAME_MACHINE}-unknown-linux-gnu
+	else
+	    echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+	fi
+	exit ;;
+    avr32*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    cris:Linux:*:*)
+	echo cris-axis-linux-gnu
+	exit ;;
+    crisv32:Linux:*:*)
+	echo crisv32-axis-linux-gnu
+	exit ;;
+    frv:Linux:*:*)
+    	echo frv-unknown-linux-gnu
+	exit ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    m32r*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    m68*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    mips:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef mips
+	#undef mipsel
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=mipsel
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=mips
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+	    /^CPU/{
+		s: ::g
+		p
+	    }'`"
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+	;;
+    mips64:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef mips64
+	#undef mips64el
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=mips64el
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=mips64
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+	    /^CPU/{
+		s: ::g
+		p
+	    }'`"
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+	;;
+    or32:Linux:*:*)
+	echo or32-unknown-linux-gnu
+	exit ;;
+    ppc:Linux:*:*)
+	echo powerpc-unknown-linux-gnu
+	exit ;;
+    ppc64:Linux:*:*)
+	echo powerpc64-unknown-linux-gnu
+	exit ;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev68 ;;
+        esac
+	objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+	if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+	exit ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+	# Look for CPU level
+	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	  PA7*) echo hppa1.1-unknown-linux-gnu ;;
+	  PA8*) echo hppa2.0-unknown-linux-gnu ;;
+	  *)    echo hppa-unknown-linux-gnu ;;
+	esac
+	exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-gnu
+	exit ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	echo ${UNAME_MACHINE}-ibm-linux
+	exit ;;
+    sh64*:Linux:*:*)
+    	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    sh*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    vax:Linux:*:*)
+	echo ${UNAME_MACHINE}-dec-linux-gnu
+	exit ;;
+    x86_64:Linux:*:*)
+	echo x86_64-unknown-linux-gnu
+	exit ;;
+    xtensa*:Linux:*:*)
+    	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    i*86:Linux:*:*)
+	# The BFD linker knows what the default object file format is, so
+	# first see if it will tell us. cd to the root directory to prevent
+	# problems with other programs or directories called `ld' in the path.
+	# Set LC_ALL=C to ensure ld outputs messages in English.
+	ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+			 | sed -ne '/supported targets:/!d
+				    s/[ 	][ 	]*/ /g
+				    s/.*supported targets: *//
+				    s/ .*//
+				    p'`
+        case "$ld_supported_targets" in
+	  elf32-i386)
+		TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+		;;
+	  a.out-i386-linux)
+		echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+		exit ;;
+	  coff-i386)
+		echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+		exit ;;
+	  "")
+		# Either a pre-BFD a.out linker (linux-gnuoldld) or
+		# one that does not give us useful --help.
+		echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+		exit ;;
+	esac
+	# Determine whether the default compiler is a.out or elf
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <features.h>
+	#ifdef __ELF__
+	# ifdef __GLIBC__
+	#  if __GLIBC__ >= 2
+	LIBC=gnu
+	#  else
+	LIBC=gnulibc1
+	#  endif
+	# else
+	LIBC=gnulibc1
+	# endif
+	#else
+	#if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+	LIBC=gnu
+	#else
+	LIBC=gnuaout
+	#endif
+	#endif
+	#ifdef __dietlibc__
+	LIBC=dietlibc
+	#endif
+EOF
+	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+	    /^LIBC/{
+		s: ::g
+		p
+	    }'`"
+	test x"${LIBC}" != x && {
+		echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+		exit
+	}
+	test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+	;;
+    i*86:DYNIX/ptx:4*:*)
+	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+	# earlier versions are messed up and put the nodename in both
+	# sysname and nodename.
+	echo i386-sequent-sysv4
+	exit ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+        # Use sysv4.2uw... so that sysv4* matches it.
+	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+	exit ;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo ${UNAME_MACHINE}-pc-os2-emx
+	exit ;;
+    i*86:XTS-300:*:STOP)
+	echo ${UNAME_MACHINE}-unknown-stop
+	exit ;;
+    i*86:atheos:*:*)
+	echo ${UNAME_MACHINE}-unknown-atheos
+	exit ;;
+    i*86:syllable:*:*)
+	echo ${UNAME_MACHINE}-pc-syllable
+	exit ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	exit ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+	else
+		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+	fi
+	exit ;;
+    i*86:*:5:[678]*)
+    	# UnixWare 7.x, OpenUNIX and OpenServer 6.
+	case `/bin/uname -X | grep "^Machine"` in
+	    *486*)	     UNAME_MACHINE=i486 ;;
+	    *Pentium)	     UNAME_MACHINE=i586 ;;
+	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+	esac
+	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+	exit ;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+	elif /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-pc-sysv32
+	fi
+	exit ;;
+    pc:*:*:*)
+	# Left here for compatibility:
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i386.
+	echo i386-pc-msdosdjgpp
+        exit ;;
+    Intel:Mach:3*:*)
+	echo i386-pc-mach3
+	exit ;;
+    paragon:*:*:*)
+	echo i860-intel-osf1
+	exit ;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+	fi
+	exit ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+	echo m68k-convergent-sysv
+	exit ;;
+    M680?0:D-NIX:5.3:*)
+	echo m68k-diab-dnix
+	exit ;;
+    M68*:*:R3V[5678]*:*)
+	test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+	OS_REL=''
+	test -r /etc/.relid \
+	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && { echo i486-ncr-sysv4; exit; } ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	echo m68k-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit ;;
+    TSUNAMI:LynxOS:2.*:*)
+	echo sparc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    rs6000:LynxOS:2.*:*)
+	echo rs6000-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+	echo powerpc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    SM[BE]S:UNIX_SV:*:*)
+	echo mips-dde-sysv${UNAME_RELEASE}
+	exit ;;
+    RM*:ReliantUNIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		echo ${UNAME_MACHINE}-sni-sysv4
+	else
+		echo ns32k-sni-sysv
+	fi
+	exit ;;
+    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                      # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <hewes@openmarket.com>.
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit ;;
+    *:*:*:FTX*)
+	# From seanf@swdc.stratus.com.
+	echo i860-stratus-sysv4
+	exit ;;
+    i*86:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo ${UNAME_MACHINE}-stratus-vos
+	exit ;;
+    *:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo hppa1.1-stratus-vos
+	exit ;;
+    mc68*:A/UX:*:*)
+	echo m68k-apple-aux${UNAME_RELEASE}
+	exit ;;
+    news*:NEWS-OS:6*:*)
+	echo mips-sony-newsos6
+	exit ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+	if [ -d /usr/nec ]; then
+	        echo mips-nec-sysv${UNAME_RELEASE}
+	else
+	        echo mips-unknown-sysv${UNAME_RELEASE}
+	fi
+        exit ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit ;;
+    SX-4:SUPER-UX:*:*)
+	echo sx4-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-5:SUPER-UX:*:*)
+	echo sx5-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-6:SUPER-UX:*:*)
+	echo sx6-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-7:SUPER-UX:*:*)
+	echo sx7-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8:SUPER-UX:*:*)
+	echo sx8-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8R:SUPER-UX:*:*)
+	echo sx8r-nec-superux${UNAME_RELEASE}
+	exit ;;
+    Power*:Rhapsody:*:*)
+	echo powerpc-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Rhapsody:*:*)
+	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Darwin:*:*)
+	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+	case $UNAME_PROCESSOR in
+	    unknown) UNAME_PROCESSOR=powerpc ;;
+	esac
+	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+	exit ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+	UNAME_PROCESSOR=`uname -p`
+	if test "$UNAME_PROCESSOR" = "x86"; then
+		UNAME_PROCESSOR=i386
+		UNAME_MACHINE=pc
+	fi
+	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+	exit ;;
+    *:QNX:*:4*)
+	echo i386-pc-qnx
+	exit ;;
+    NSE-?:NONSTOP_KERNEL:*:*)
+	echo nse-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    *:NonStop-UX:*:*)
+	echo mips-compaq-nonstopux
+	exit ;;
+    BS2000:POSIX*:*:*)
+	echo bs2000-siemens-sysv
+	exit ;;
+    DS/*:UNIX_System_V:*:*)
+	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+	exit ;;
+    *:Plan9:*:*)
+	# "uname -m" is not consistent, so use $cputype instead. 386
+	# is converted to i386 for consistency with other x86
+	# operating systems.
+	if test "$cputype" = "386"; then
+	    UNAME_MACHINE=i386
+	else
+	    UNAME_MACHINE="$cputype"
+	fi
+	echo ${UNAME_MACHINE}-unknown-plan9
+	exit ;;
+    *:TOPS-10:*:*)
+	echo pdp10-unknown-tops10
+	exit ;;
+    *:TENEX:*:*)
+	echo pdp10-unknown-tenex
+	exit ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	echo pdp10-dec-tops20
+	exit ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	echo pdp10-xkl-tops20
+	exit ;;
+    *:TOPS-20:*:*)
+	echo pdp10-unknown-tops20
+	exit ;;
+    *:ITS:*:*)
+	echo pdp10-unknown-its
+	exit ;;
+    SEI:*:*:SEIUX)
+        echo mips-sei-seiux${UNAME_RELEASE}
+	exit ;;
+    *:DragonFly:*:*)
+	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+	exit ;;
+    *:*VMS:*:*)
+    	UNAME_MACHINE=`(uname -p) 2>/dev/null`
+	case "${UNAME_MACHINE}" in
+	    A*) echo alpha-dec-vms ; exit ;;
+	    I*) echo ia64-dec-vms ; exit ;;
+	    V*) echo vax-dec-vms ; exit ;;
+	esac ;;
+    *:XENIX:*:SysV)
+	echo i386-pc-xenix
+	exit ;;
+    i*86:skyos:*:*)
+	echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+	exit ;;
+    i*86:rdos:*:*)
+	echo ${UNAME_MACHINE}-pc-rdos
+	exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+	  ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+	printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+	printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+	{ echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+	echo c1-convex-bsd
+	exit ;;
+    c2*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit ;;
+    c34*)
+	echo c34-convex-bsd
+	exit ;;
+    c38*)
+	echo c38-convex-bsd
+	exit ;;
+    c4*)
+	echo c4-convex-bsd
+	exit ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
Index: vis_dev/vis-2.3/helpers/config.sub
===================================================================
--- vis_dev/vis-2.3/helpers/config.sub	(revision 14)
+++ vis_dev/vis-2.3/helpers/config.sub	(revision 14)
@@ -0,0 +1,1658 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+#   Free Software Foundation, Inc.
+
+timestamp='2008-01-16'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit ;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+  uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+	-sun*os*)
+		# Prevent following clause from handling this invalid input.
+		;;
+	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+	-apple | -axis | -knuth | -cray)
+		os=
+		basic_machine=$1
+		;;
+	-sim | -cisco | -oki | -wec | -winbond)
+		os=
+		basic_machine=$1
+		;;
+	-scout)
+		;;
+	-wrs)
+		os=-vxworks
+		basic_machine=$1
+		;;
+	-chorusos*)
+		os=-chorusos
+		basic_machine=$1
+		;;
+ 	-chorusrdb)
+ 		os=-chorusrdb
+		basic_machine=$1
+ 		;;
+	-hiux*)
+		os=-hiuxwe2
+		;;
+	-sco6)
+		os=-sco5v6
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5)
+		os=-sco3.2v5
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco4)
+		os=-sco3.2v4
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2.[4-9]*)
+		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2v[4-9]*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5v6*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco*)
+		os=-sco3.2v2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-udk*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-isc)
+		os=-isc2.2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-clix*)
+		basic_machine=clipper-intergraph
+		;;
+	-isc*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-lynx*)
+		os=-lynxos
+		;;
+	-ptx*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+		;;
+	-windowsnt*)
+		os=`echo $os | sed -e 's/windowsnt/winnt/'`
+		;;
+	-psos*)
+		os=-psos
+		;;
+	-mint | -mint[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+	# Recognize the basic CPU types without company name.
+	# Some are omitted here because they have special meanings below.
+	1750a | 580 \
+	| a29k \
+	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+	| am33_2.0 \
+	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+	| bfin \
+	| c4x | clipper \
+	| d10v | d30v | dlx | dsp16xx \
+	| fido | fr30 | frv \
+	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+	| i370 | i860 | i960 | ia64 \
+	| ip2k | iq2000 \
+	| m32c | m32r | m32rle | m68000 | m68k | m88k \
+	| maxq | mb | microblaze | mcore | mep \
+	| mips | mipsbe | mipseb | mipsel | mipsle \
+	| mips16 \
+	| mips64 | mips64el \
+	| mips64vr | mips64vrel \
+	| mips64orion | mips64orionel \
+	| mips64vr4100 | mips64vr4100el \
+	| mips64vr4300 | mips64vr4300el \
+	| mips64vr5000 | mips64vr5000el \
+	| mips64vr5900 | mips64vr5900el \
+	| mipsisa32 | mipsisa32el \
+	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa64 | mipsisa64el \
+	| mipsisa64r2 | mipsisa64r2el \
+	| mipsisa64sb1 | mipsisa64sb1el \
+	| mipsisa64sr71k | mipsisa64sr71kel \
+	| mipstx39 | mipstx39el \
+	| mn10200 | mn10300 \
+	| mt \
+	| msp430 \
+	| nios | nios2 \
+	| ns16k | ns32k \
+	| or32 \
+	| pdp10 | pdp11 | pj | pjl \
+	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+	| pyramid \
+	| score \
+	| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+	| sh64 | sh64le \
+	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+	| spu | strongarm \
+	| tahoe | thumb | tic4x | tic80 | tron \
+	| v850 | v850e \
+	| we32k \
+	| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+	| z8k)
+		basic_machine=$basic_machine-unknown
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12)
+		# Motorola 68HC11/12.
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+		;;
+	ms1)
+		basic_machine=mt-unknown
+		;;
+
+	# We use `pc' rather than `unknown'
+	# because (1) that's what they normally are, and
+	# (2) the word "unknown" tends to confuse beginning users.
+	i*86 | x86_64)
+	  basic_machine=$basic_machine-pc
+	  ;;
+	# Object if more than one company name word.
+	*-*-*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+	# Recognize the basic CPU types with company name.
+	580-* \
+	| a29k-* \
+	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+	| avr-* | avr32-* \
+	| bfin-* | bs2000-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+	| clipper-* | craynv-* | cydra-* \
+	| d10v-* | d30v-* | dlx-* \
+	| elxsi-* \
+	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+	| h8300-* | h8500-* \
+	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+	| i*86-* | i860-* | i960-* | ia64-* \
+	| ip2k-* | iq2000-* \
+	| m32c-* | m32r-* | m32rle-* \
+	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+	| m88110-* | m88k-* | maxq-* | mcore-* \
+	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+	| mips16-* \
+	| mips64-* | mips64el-* \
+	| mips64vr-* | mips64vrel-* \
+	| mips64orion-* | mips64orionel-* \
+	| mips64vr4100-* | mips64vr4100el-* \
+	| mips64vr4300-* | mips64vr4300el-* \
+	| mips64vr5000-* | mips64vr5000el-* \
+	| mips64vr5900-* | mips64vr5900el-* \
+	| mipsisa32-* | mipsisa32el-* \
+	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa64-* | mipsisa64el-* \
+	| mipsisa64r2-* | mipsisa64r2el-* \
+	| mipsisa64sb1-* | mipsisa64sb1el-* \
+	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipstx39-* | mipstx39el-* \
+	| mmix-* \
+	| mt-* \
+	| msp430-* \
+	| nios-* | nios2-* \
+	| none-* | np1-* | ns16k-* | ns32k-* \
+	| orion-* \
+	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+	| pyramid-* \
+	| romp-* | rs6000-* \
+	| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+	| sparclite-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
+	| tahoe-* | thumb-* \
+	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+	| tron-* \
+	| v850-* | v850e-* | vax-* \
+	| we32k-* \
+	| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+	| xstormy16-* | xtensa*-* \
+	| ymp-* \
+	| z8k-*)
+		;;
+	# Recognize the basic CPU types without company name, with glob match.
+	xtensa*)
+		basic_machine=$basic_machine-unknown
+		;;
+	# Recognize the various machine names and aliases which stand
+	# for a CPU type and a company and sometimes even an OS.
+	386bsd)
+		basic_machine=i386-unknown
+		os=-bsd
+		;;
+	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+		basic_machine=m68000-att
+		;;
+	3b*)
+		basic_machine=we32k-att
+		;;
+	a29khif)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+    	abacus)
+		basic_machine=abacus-unknown
+		;;
+	adobe68k)
+		basic_machine=m68010-adobe
+		os=-scout
+		;;
+	alliant | fx80)
+		basic_machine=fx80-alliant
+		;;
+	altos | altos3068)
+		basic_machine=m68k-altos
+		;;
+	am29k)
+		basic_machine=a29k-none
+		os=-bsd
+		;;
+	amd64)
+		basic_machine=x86_64-pc
+		;;
+	amd64-*)
+		basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	amdahl)
+		basic_machine=580-amdahl
+		os=-sysv
+		;;
+	amiga | amiga-*)
+		basic_machine=m68k-unknown
+		;;
+	amigaos | amigados)
+		basic_machine=m68k-unknown
+		os=-amigaos
+		;;
+	amigaunix | amix)
+		basic_machine=m68k-unknown
+		os=-sysv4
+		;;
+	apollo68)
+		basic_machine=m68k-apollo
+		os=-sysv
+		;;
+	apollo68bsd)
+		basic_machine=m68k-apollo
+		os=-bsd
+		;;
+	aux)
+		basic_machine=m68k-apple
+		os=-aux
+		;;
+	balance)
+		basic_machine=ns32k-sequent
+		os=-dynix
+		;;
+	blackfin)
+		basic_machine=bfin-unknown
+		os=-linux
+		;;
+	blackfin-*)
+		basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	c90)
+		basic_machine=c90-cray
+		os=-unicos
+		;;
+	convex-c1)
+		basic_machine=c1-convex
+		os=-bsd
+		;;
+	convex-c2)
+		basic_machine=c2-convex
+		os=-bsd
+		;;
+	convex-c32)
+		basic_machine=c32-convex
+		os=-bsd
+		;;
+	convex-c34)
+		basic_machine=c34-convex
+		os=-bsd
+		;;
+	convex-c38)
+		basic_machine=c38-convex
+		os=-bsd
+		;;
+	cray | j90)
+		basic_machine=j90-cray
+		os=-unicos
+		;;
+	craynv)
+		basic_machine=craynv-cray
+		os=-unicosmp
+		;;
+	cr16)
+		basic_machine=cr16-unknown
+		os=-elf
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	crisv32 | crisv32-* | etraxfs*)
+		basic_machine=crisv32-axis
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	crx)
+		basic_machine=crx-unknown
+		os=-elf
+		;;
+	da30 | da30-*)
+		basic_machine=m68k-da30
+		;;
+	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+		basic_machine=mips-dec
+		;;
+	decsystem10* | dec10*)
+		basic_machine=pdp10-dec
+		os=-tops10
+		;;
+	decsystem20* | dec20*)
+		basic_machine=pdp10-dec
+		os=-tops20
+		;;
+	delta | 3300 | motorola-3300 | motorola-delta \
+	      | 3300-motorola | delta-motorola)
+		basic_machine=m68k-motorola
+		;;
+	delta88)
+		basic_machine=m88k-motorola
+		os=-sysv3
+		;;
+	djgpp)
+		basic_machine=i586-pc
+		os=-msdosdjgpp
+		;;
+	dpx20 | dpx20-*)
+		basic_machine=rs6000-bull
+		os=-bosx
+		;;
+	dpx2* | dpx2*-bull)
+		basic_machine=m68k-bull
+		os=-sysv3
+		;;
+	ebmon29k)
+		basic_machine=a29k-amd
+		os=-ebmon
+		;;
+	elxsi)
+		basic_machine=elxsi-elxsi
+		os=-bsd
+		;;
+	encore | umax | mmax)
+		basic_machine=ns32k-encore
+		;;
+	es1800 | OSE68k | ose68k | ose | OSE)
+		basic_machine=m68k-ericsson
+		os=-ose
+		;;
+	fx2800)
+		basic_machine=i860-alliant
+		;;
+	genix)
+		basic_machine=ns32k-ns
+		;;
+	gmicro)
+		basic_machine=tron-gmicro
+		os=-sysv
+		;;
+	go32)
+		basic_machine=i386-pc
+		os=-go32
+		;;
+	h3050r* | hiux*)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	h8300hms)
+		basic_machine=h8300-hitachi
+		os=-hms
+		;;
+	h8300xray)
+		basic_machine=h8300-hitachi
+		os=-xray
+		;;
+	h8500hms)
+		basic_machine=h8500-hitachi
+		os=-hms
+		;;
+	harris)
+		basic_machine=m88k-harris
+		os=-sysv3
+		;;
+	hp300-*)
+		basic_machine=m68k-hp
+		;;
+	hp300bsd)
+		basic_machine=m68k-hp
+		os=-bsd
+		;;
+	hp300hpux)
+		basic_machine=m68k-hp
+		os=-hpux
+		;;
+	hp3k9[0-9][0-9] | hp9[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k2[0-9][0-9] | hp9k31[0-9])
+		basic_machine=m68000-hp
+		;;
+	hp9k3[2-9][0-9])
+		basic_machine=m68k-hp
+		;;
+	hp9k6[0-9][0-9] | hp6[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k7[0-79][0-9] | hp7[0-79][0-9])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k78[0-9] | hp78[0-9])
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][13679] | hp8[0-9][13679])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][0-9] | hp8[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hppa-next)
+		os=-nextstep3
+		;;
+	hppaosf)
+		basic_machine=hppa1.1-hp
+		os=-osf
+		;;
+	hppro)
+		basic_machine=hppa1.1-hp
+		os=-proelf
+		;;
+	i370-ibm* | ibm*)
+		basic_machine=i370-ibm
+		;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+	i*86v32)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv32
+		;;
+	i*86v4*)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv4
+		;;
+	i*86v)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv
+		;;
+	i*86sol2)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-solaris2
+		;;
+	i386mach)
+		basic_machine=i386-mach
+		os=-mach
+		;;
+	i386-vsta | vsta)
+		basic_machine=i386-unknown
+		os=-vsta
+		;;
+	iris | iris4d)
+		basic_machine=mips-sgi
+		case $os in
+		    -irix*)
+			;;
+		    *)
+			os=-irix4
+			;;
+		esac
+		;;
+	isi68 | isi)
+		basic_machine=m68k-isi
+		os=-sysv
+		;;
+	m68knommu)
+		basic_machine=m68k-unknown
+		os=-linux
+		;;
+	m68knommu-*)
+		basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	m88k-omron*)
+		basic_machine=m88k-omron
+		;;
+	magnum | m3230)
+		basic_machine=mips-mips
+		os=-sysv
+		;;
+	merlin)
+		basic_machine=ns32k-utek
+		os=-sysv
+		;;
+	mingw32)
+		basic_machine=i386-pc
+		os=-mingw32
+		;;
+	mingw32ce)
+		basic_machine=arm-unknown
+		os=-mingw32ce
+		;;
+	miniframe)
+		basic_machine=m68000-convergent
+		;;
+	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+	mips3*-*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+		;;
+	mips3*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+		;;
+	monitor)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	morphos)
+		basic_machine=powerpc-unknown
+		os=-morphos
+		;;
+	msdos)
+		basic_machine=i386-pc
+		os=-msdos
+		;;
+	ms1-*)
+		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+		;;
+	mvs)
+		basic_machine=i370-ibm
+		os=-mvs
+		;;
+	ncr3000)
+		basic_machine=i486-ncr
+		os=-sysv4
+		;;
+	netbsd386)
+		basic_machine=i386-unknown
+		os=-netbsd
+		;;
+	netwinder)
+		basic_machine=armv4l-rebel
+		os=-linux
+		;;
+	news | news700 | news800 | news900)
+		basic_machine=m68k-sony
+		os=-newsos
+		;;
+	news1000)
+		basic_machine=m68030-sony
+		os=-newsos
+		;;
+	news-3600 | risc-news)
+		basic_machine=mips-sony
+		os=-newsos
+		;;
+	necv70)
+		basic_machine=v70-nec
+		os=-sysv
+		;;
+	next | m*-next )
+		basic_machine=m68k-next
+		case $os in
+		    -nextstep* )
+			;;
+		    -ns2*)
+		      os=-nextstep2
+			;;
+		    *)
+		      os=-nextstep3
+			;;
+		esac
+		;;
+	nh3000)
+		basic_machine=m68k-harris
+		os=-cxux
+		;;
+	nh[45]000)
+		basic_machine=m88k-harris
+		os=-cxux
+		;;
+	nindy960)
+		basic_machine=i960-intel
+		os=-nindy
+		;;
+	mon960)
+		basic_machine=i960-intel
+		os=-mon960
+		;;
+	nonstopux)
+		basic_machine=mips-compaq
+		os=-nonstopux
+		;;
+	np1)
+		basic_machine=np1-gould
+		;;
+	nsr-tandem)
+		basic_machine=nsr-tandem
+		;;
+	op50n-* | op60c-*)
+		basic_machine=hppa1.1-oki
+		os=-proelf
+		;;
+	openrisc | openrisc-*)
+		basic_machine=or32-unknown
+		;;
+	os400)
+		basic_machine=powerpc-ibm
+		os=-os400
+		;;
+	OSE68000 | ose68000)
+		basic_machine=m68000-ericsson
+		os=-ose
+		;;
+	os68k)
+		basic_machine=m68k-none
+		os=-os68k
+		;;
+	pa-hitachi)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	paragon)
+		basic_machine=i860-intel
+		os=-osf
+		;;
+	parisc)
+		basic_machine=hppa-unknown
+		os=-linux
+		;;
+	parisc-*)
+		basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	pbd)
+		basic_machine=sparc-tti
+		;;
+	pbb)
+		basic_machine=m68k-tti
+		;;
+	pc532 | pc532-*)
+		basic_machine=ns32k-pc532
+		;;
+	pc98)
+		basic_machine=i386-pc
+		;;
+	pc98-*)
+		basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium | p5 | k5 | k6 | nexgen | viac3)
+		basic_machine=i586-pc
+		;;
+	pentiumpro | p6 | 6x86 | athlon | athlon_*)
+		basic_machine=i686-pc
+		;;
+	pentiumii | pentium2 | pentiumiii | pentium3)
+		basic_machine=i686-pc
+		;;
+	pentium4)
+		basic_machine=i786-pc
+		;;
+	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumpro-* | p6-* | 6x86-* | athlon-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium4-*)
+		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pn)
+		basic_machine=pn-gould
+		;;
+	power)	basic_machine=power-ibm
+		;;
+	ppc)	basic_machine=powerpc-unknown
+		;;
+	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppcle | powerpclittle | ppc-le | powerpc-little)
+		basic_machine=powerpcle-unknown
+		;;
+	ppcle-* | powerpclittle-*)
+		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64)	basic_machine=powerpc64-unknown
+		;;
+	ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+		basic_machine=powerpc64le-unknown
+		;;
+	ppc64le-* | powerpc64little-*)
+		basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ps2)
+		basic_machine=i386-ibm
+		;;
+	pw32)
+		basic_machine=i586-unknown
+		os=-pw32
+		;;
+	rdos)
+		basic_machine=i386-pc
+		os=-rdos
+		;;
+	rom68k)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	rm[46]00)
+		basic_machine=mips-siemens
+		;;
+	rtpc | rtpc-*)
+		basic_machine=romp-ibm
+		;;
+	s390 | s390-*)
+		basic_machine=s390-ibm
+		;;
+	s390x | s390x-*)
+		basic_machine=s390x-ibm
+		;;
+	sa29200)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	sb1)
+		basic_machine=mipsisa64sb1-unknown
+		;;
+	sb1el)
+		basic_machine=mipsisa64sb1el-unknown
+		;;
+	sde)
+		basic_machine=mipsisa32-sde
+		os=-elf
+		;;
+	sei)
+		basic_machine=mips-sei
+		os=-seiux
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh)
+		basic_machine=sh-hitachi
+		os=-hms
+		;;
+	sh5el)
+		basic_machine=sh5le-unknown
+		;;
+	sh64)
+		basic_machine=sh64-unknown
+		;;
+	sparclite-wrs | simso-wrs)
+		basic_machine=sparclite-wrs
+		os=-vxworks
+		;;
+	sps7)
+		basic_machine=m68k-bull
+		os=-sysv2
+		;;
+	spur)
+		basic_machine=spur-unknown
+		;;
+	st2000)
+		basic_machine=m68k-tandem
+		;;
+	stratus)
+		basic_machine=i860-stratus
+		os=-sysv4
+		;;
+	sun2)
+		basic_machine=m68000-sun
+		;;
+	sun2os3)
+		basic_machine=m68000-sun
+		os=-sunos3
+		;;
+	sun2os4)
+		basic_machine=m68000-sun
+		os=-sunos4
+		;;
+	sun3os3)
+		basic_machine=m68k-sun
+		os=-sunos3
+		;;
+	sun3os4)
+		basic_machine=m68k-sun
+		os=-sunos4
+		;;
+	sun4os3)
+		basic_machine=sparc-sun
+		os=-sunos3
+		;;
+	sun4os4)
+		basic_machine=sparc-sun
+		os=-sunos4
+		;;
+	sun4sol2)
+		basic_machine=sparc-sun
+		os=-solaris2
+		;;
+	sun3 | sun3-*)
+		basic_machine=m68k-sun
+		;;
+	sun4)
+		basic_machine=sparc-sun
+		;;
+	sun386 | sun386i | roadrunner)
+		basic_machine=i386-sun
+		;;
+	sv1)
+		basic_machine=sv1-cray
+		os=-unicos
+		;;
+	symmetry)
+		basic_machine=i386-sequent
+		os=-dynix
+		;;
+	t3e)
+		basic_machine=alphaev5-cray
+		os=-unicos
+		;;
+	t90)
+		basic_machine=t90-cray
+		os=-unicos
+		;;
+	tic54x | c54x*)
+		basic_machine=tic54x-unknown
+		os=-coff
+		;;
+	tic55x | c55x*)
+		basic_machine=tic55x-unknown
+		os=-coff
+		;;
+	tic6x | c6x*)
+		basic_machine=tic6x-unknown
+		os=-coff
+		;;
+	tile*)
+		basic_machine=tile-unknown
+		os=-linux-gnu
+		;;
+	tx39)
+		basic_machine=mipstx39-unknown
+		;;
+	tx39el)
+		basic_machine=mipstx39el-unknown
+		;;
+	toad1)
+		basic_machine=pdp10-xkl
+		os=-tops20
+		;;
+	tower | tower-32)
+		basic_machine=m68k-ncr
+		;;
+	tpf)
+		basic_machine=s390x-ibm
+		os=-tpf
+		;;
+	udi29k)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	ultra3)
+		basic_machine=a29k-nyu
+		os=-sym1
+		;;
+	v810 | necv810)
+		basic_machine=v810-nec
+		os=-none
+		;;
+	vaxv)
+		basic_machine=vax-dec
+		os=-sysv
+		;;
+	vms)
+		basic_machine=vax-dec
+		os=-vms
+		;;
+	vpp*|vx|vx-*)
+		basic_machine=f301-fujitsu
+		;;
+	vxworks960)
+		basic_machine=i960-wrs
+		os=-vxworks
+		;;
+	vxworks68)
+		basic_machine=m68k-wrs
+		os=-vxworks
+		;;
+	vxworks29k)
+		basic_machine=a29k-wrs
+		os=-vxworks
+		;;
+	w65*)
+		basic_machine=w65-wdc
+		os=-none
+		;;
+	w89k-*)
+		basic_machine=hppa1.1-winbond
+		os=-proelf
+		;;
+	xbox)
+		basic_machine=i686-pc
+		os=-mingw32
+		;;
+	xps | xps100)
+		basic_machine=xps100-honeywell
+		;;
+	ymp)
+		basic_machine=ymp-cray
+		os=-unicos
+		;;
+	z8k-*-coff)
+		basic_machine=z8k-unknown
+		os=-sim
+		;;
+	none)
+		basic_machine=none-none
+		os=-none
+		;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+	w89k)
+		basic_machine=hppa1.1-winbond
+		;;
+	op50n)
+		basic_machine=hppa1.1-oki
+		;;
+	op60c)
+		basic_machine=hppa1.1-oki
+		;;
+	romp)
+		basic_machine=romp-ibm
+		;;
+	mmix)
+		basic_machine=mmix-knuth
+		;;
+	rs6000)
+		basic_machine=rs6000-ibm
+		;;
+	vax)
+		basic_machine=vax-dec
+		;;
+	pdp10)
+		# there are many clones, so DEC is not a safe bet
+		basic_machine=pdp10-unknown
+		;;
+	pdp11)
+		basic_machine=pdp11-dec
+		;;
+	we32k)
+		basic_machine=we32k-att
+		;;
+	sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+		basic_machine=sh-unknown
+		;;
+	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+		basic_machine=sparc-sun
+		;;
+	cydra)
+		basic_machine=cydra-cydrome
+		;;
+	orion)
+		basic_machine=orion-highlevel
+		;;
+	orion105)
+		basic_machine=clipper-highlevel
+		;;
+	mac | mpw | mac-mpw)
+		basic_machine=m68k-apple
+		;;
+	pmac | pmac-mpw)
+		basic_machine=powerpc-apple
+		;;
+	*-unknown)
+		# Make sure to match an already-canonicalized machine name.
+		;;
+	*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+	*-digital*)
+		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+		;;
+	*-commodore*)
+		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+		;;
+	*)
+		;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+        # First match some system type aliases
+        # that might get confused with valid system types.
+	# -solaris* is a basic system type, with this one exception.
+	-solaris1 | -solaris1.*)
+		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		;;
+	-solaris)
+		os=-solaris2
+		;;
+	-svr4*)
+		os=-sysv4
+		;;
+	-unixware*)
+		os=-sysv4.2uw
+		;;
+	-gnu/linux*)
+		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+		;;
+	# First accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST END IN A *, to match a version number.
+	# -sysv* is not here because it comes later, after sysvr4.
+	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+	      | -aos* \
+	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+	      | -openbsd* | -solidbsd* \
+	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+	      | -chorusos* | -chorusrdb* \
+	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+	      | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
+	# Remember, each alternative MUST END IN *, to match a version number.
+		;;
+	-qnx*)
+		case $basic_machine in
+		    x86-* | i*86-*)
+			;;
+		    *)
+			os=-nto$os
+			;;
+		esac
+		;;
+	-nto-qnx*)
+		;;
+	-nto*)
+		os=`echo $os | sed -e 's|nto|nto-qnx|'`
+		;;
+	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+		;;
+	-mac*)
+		os=`echo $os | sed -e 's|mac|macos|'`
+		;;
+	-linux-dietlibc)
+		os=-linux-dietlibc
+		;;
+	-linux*)
+		os=`echo $os | sed -e 's|linux|linux-gnu|'`
+		;;
+	-sunos5*)
+		os=`echo $os | sed -e 's|sunos5|solaris2|'`
+		;;
+	-sunos6*)
+		os=`echo $os | sed -e 's|sunos6|solaris3|'`
+		;;
+	-opened*)
+		os=-openedition
+		;;
+        -os400*)
+		os=-os400
+		;;
+	-wince*)
+		os=-wince
+		;;
+	-osfrose*)
+		os=-osfrose
+		;;
+	-osf*)
+		os=-osf
+		;;
+	-utek*)
+		os=-bsd
+		;;
+	-dynix*)
+		os=-bsd
+		;;
+	-acis*)
+		os=-aos
+		;;
+	-atheos*)
+		os=-atheos
+		;;
+	-syllable*)
+		os=-syllable
+		;;
+	-386bsd)
+		os=-bsd
+		;;
+	-ctix* | -uts*)
+		os=-sysv
+		;;
+	-nova*)
+		os=-rtmk-nova
+		;;
+	-ns2 )
+		os=-nextstep2
+		;;
+	-nsk*)
+		os=-nsk
+		;;
+	# Preserve the version number of sinix5.
+	-sinix5.*)
+		os=`echo $os | sed -e 's|sinix|sysv|'`
+		;;
+	-sinix*)
+		os=-sysv4
+		;;
+        -tpf*)
+		os=-tpf
+		;;
+	-triton*)
+		os=-sysv3
+		;;
+	-oss*)
+		os=-sysv3
+		;;
+	-svr4)
+		os=-sysv4
+		;;
+	-svr3)
+		os=-sysv3
+		;;
+	-sysvr4)
+		os=-sysv4
+		;;
+	# This must come after -sysvr4.
+	-sysv*)
+		;;
+	-ose*)
+		os=-ose
+		;;
+	-es1800*)
+		os=-ose
+		;;
+	-xenix)
+		os=-xenix
+		;;
+	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+		os=-mint
+		;;
+	-aros*)
+		os=-aros
+		;;
+	-kaos*)
+		os=-kaos
+		;;
+	-zvmoe)
+		os=-zvmoe
+		;;
+	-none)
+		;;
+	*)
+		# Get rid of the `-' at the beginning of $os.
+		os=`echo $os | sed 's/[^-]*-//'`
+		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+		exit 1
+		;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+        score-*)
+		os=-elf
+		;;
+        spu-*)
+		os=-elf
+		;;
+	*-acorn)
+		os=-riscix1.2
+		;;
+	arm*-rebel)
+		os=-linux
+		;;
+	arm*-semi)
+		os=-aout
+		;;
+        c4x-* | tic4x-*)
+        	os=-coff
+		;;
+	# This must come before the *-dec entry.
+	pdp10-*)
+		os=-tops20
+		;;
+	pdp11-*)
+		os=-none
+		;;
+	*-dec | vax-*)
+		os=-ultrix4.2
+		;;
+	m68*-apollo)
+		os=-domain
+		;;
+	i386-sun)
+		os=-sunos4.0.2
+		;;
+	m68000-sun)
+		os=-sunos3
+		# This also exists in the configure program, but was not the
+		# default.
+		# os=-sunos4
+		;;
+	m68*-cisco)
+		os=-aout
+		;;
+        mep-*)
+		os=-elf
+		;;
+	mips*-cisco)
+		os=-elf
+		;;
+	mips*-*)
+		os=-elf
+		;;
+	or32-*)
+		os=-coff
+		;;
+	*-tti)	# must be before sparc entry or we get the wrong os.
+		os=-sysv3
+		;;
+	sparc-* | *-sun)
+		os=-sunos4.1.1
+		;;
+	*-be)
+		os=-beos
+		;;
+	*-haiku)
+		os=-haiku
+		;;
+	*-ibm)
+		os=-aix
+		;;
+    	*-knuth)
+		os=-mmixware
+		;;
+	*-wec)
+		os=-proelf
+		;;
+	*-winbond)
+		os=-proelf
+		;;
+	*-oki)
+		os=-proelf
+		;;
+	*-hp)
+		os=-hpux
+		;;
+	*-hitachi)
+		os=-hiux
+		;;
+	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+		os=-sysv
+		;;
+	*-cbm)
+		os=-amigaos
+		;;
+	*-dg)
+		os=-dgux
+		;;
+	*-dolphin)
+		os=-sysv3
+		;;
+	m68k-ccur)
+		os=-rtu
+		;;
+	m88k-omron*)
+		os=-luna
+		;;
+	*-next )
+		os=-nextstep
+		;;
+	*-sequent)
+		os=-ptx
+		;;
+	*-crds)
+		os=-unos
+		;;
+	*-ns)
+		os=-genix
+		;;
+	i370-*)
+		os=-mvs
+		;;
+	*-next)
+		os=-nextstep3
+		;;
+	*-gould)
+		os=-sysv
+		;;
+	*-highlevel)
+		os=-bsd
+		;;
+	*-encore)
+		os=-bsd
+		;;
+	*-sgi)
+		os=-irix
+		;;
+	*-siemens)
+		os=-sysv4
+		;;
+	*-masscomp)
+		os=-rtu
+		;;
+	f30[01]-fujitsu | f700-fujitsu)
+		os=-uxpv
+		;;
+	*-rom68k)
+		os=-coff
+		;;
+	*-*bug)
+		os=-coff
+		;;
+	*-apple)
+		os=-macos
+		;;
+	*-atari*)
+		os=-mint
+		;;
+	*)
+		os=-none
+		;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+	*-unknown)
+		case $os in
+			-riscix*)
+				vendor=acorn
+				;;
+			-sunos*)
+				vendor=sun
+				;;
+			-aix*)
+				vendor=ibm
+				;;
+			-beos*)
+				vendor=be
+				;;
+			-hpux*)
+				vendor=hp
+				;;
+			-mpeix*)
+				vendor=hp
+				;;
+			-hiux*)
+				vendor=hitachi
+				;;
+			-unos*)
+				vendor=crds
+				;;
+			-dgux*)
+				vendor=dg
+				;;
+			-luna*)
+				vendor=omron
+				;;
+			-genix*)
+				vendor=ns
+				;;
+			-mvs* | -opened*)
+				vendor=ibm
+				;;
+			-os400*)
+				vendor=ibm
+				;;
+			-ptx*)
+				vendor=sequent
+				;;
+			-tpf*)
+				vendor=ibm
+				;;
+			-vxsim* | -vxworks* | -windiss*)
+				vendor=wrs
+				;;
+			-aux*)
+				vendor=apple
+				;;
+			-hms*)
+				vendor=hitachi
+				;;
+			-mpw* | -macos*)
+				vendor=apple
+				;;
+			-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+				vendor=atari
+				;;
+			-vos*)
+				vendor=stratus
+				;;
+		esac
+		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+		;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
Index: vis_dev/vis-2.3/helpers/dependency.make
===================================================================
--- vis_dev/vis-2.3/helpers/dependency.make	(revision 14)
+++ vis_dev/vis-2.3/helpers/dependency.make	(revision 14)
@@ -0,0 +1,32 @@
+# FileName	[dependency.make]
+#
+# PackageName	[vis]
+#
+# Synopsis	[Makefile to automatically create the dependency files.]
+#
+# Description	[This file is called from the main Makefile.]
+#
+# SeeAlso	[Makefile.in]
+#
+# Author	[Abelardo Pardo <abel@boulder.colorado.edu>]
+#
+# Copyright	[This file was created at the University of Colorado at Boulder.
+#  The University of Colorado at Boulder makes no warranty about the suitability
+#  of this software for any purpose.  It is presented on an AS IS basis.]
+#
+# Revision	[$Id: dependency.make,v 1.3 1998/09/18 18:30:23 hsv Exp $]
+
+include $(PKGNAME).make
+
+ifdef DEPENDENCYFILES
+$(PKGNAME).d : $(DEPENDENCYFILES) $(HEADERS) $(PKGNAME).make
+	@echo -n "Dependency file $(PKGNAME).d->"
+	@$(CC) -MM $(CFLAGS) $(AC_FLAGS) $(INCLUDEDIRS) \
+	$(filter %.c, $^) | \
+	sed 's/^[a-zA-Z0-9_]*\.o[ :]*/$(objectdir)\/&/g' > $@
+	@echo "Created."
+else
+$(PKGNAME).d :
+	@echo "No dependency files given in $(PKGNAME).make"
+	@echo "Define the variable DEPENDENCYFILES to create the dependencies"
+endif
Index: vis_dev/vis-2.3/helpers/install-sh
===================================================================
--- vis_dev/vis-2.3/helpers/install-sh	(revision 14)
+++ vis_dev/vis-2.3/helpers/install-sh	(revision 14)
@@ -0,0 +1,276 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission.  M.I.T. makes no representations about the
+# suitability of this software for any purpose.  It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.  It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+	-c) instcmd=$cpprog
+	    shift
+	    continue;;
+
+	-d) dir_arg=true
+	    shift
+	    continue;;
+
+	-m) chmodcmd="$chmodprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-o) chowncmd="$chownprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-g) chgrpcmd="$chgrpprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-s) stripcmd=$stripprog
+	    shift
+	    continue;;
+
+	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
+	    shift
+	    continue;;
+
+	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+	    shift
+	    continue;;
+
+	*)  if [ x"$src" = x ]
+	    then
+		src=$1
+	    else
+		# this colon is to work around a 386BSD /bin/sh bug
+		:
+		dst=$1
+	    fi
+	    shift
+	    continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+	echo "$0: no input file specified" >&2
+	exit 1
+else
+	:
+fi
+
+if [ x"$dir_arg" != x ]; then
+	dst=$src
+	src=""
+
+	if [ -d "$dst" ]; then
+		instcmd=:
+		chmodcmd=""
+	else
+		instcmd=$mkdirprog
+	fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+	if [ -f "$src" ] || [ -d "$src" ]
+	then
+		:
+	else
+		echo "$0: $src does not exist" >&2
+		exit 1
+	fi
+
+	if [ x"$dst" = x ]
+	then
+		echo "$0: no destination specified" >&2
+		exit 1
+	else
+		:
+	fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+	if [ -d "$dst" ]
+	then
+		dst=$dst/`basename "$src"`
+	else
+		:
+	fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+	'
+IFS="${IFS-$defaultIFS}"
+
+oIFS=$IFS
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS=$oIFS
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+	pathcomp=$pathcomp$1
+	shift
+
+	if [ ! -d "$pathcomp" ] ;
+        then
+		$mkdirprog "$pathcomp"
+	else
+		:
+	fi
+
+	pathcomp=$pathcomp/
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+	$doit $instcmd "$dst" &&
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+	if [ x"$transformarg" = x ]
+	then
+		dstfile=`basename "$dst"`
+	else
+		dstfile=`basename "$dst" $transformbasename |
+			sed $transformarg`$transformbasename
+	fi
+
+# don't allow the sed command to completely eliminate the filename
+
+	if [ x"$dstfile" = x ]
+	then
+		dstfile=`basename "$dst"`
+	else
+		:
+	fi
+
+# Make a couple of temp file names in the proper directory.
+
+	dsttmp=$dstdir/#inst.$$#
+	rmtmp=$dstdir/#rm.$$#
+
+# Trap to clean up temp files at exit.
+
+	trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
+	trap '(exit $?); exit' 1 2 13 15
+
+# Move or copy the file name to the temp name
+
+	$doit $instcmd "$src" "$dsttmp" &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
+
+# Now remove or move aside any old file at destination location.  We try this
+# two ways since rm can't unlink itself on some systems and the destination
+# file might be busy for other reasons.  In this case, the final cleanup
+# might fail but the new file should still install successfully.
+
+{
+	if [ -f "$dstdir/$dstfile" ]
+	then
+		$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
+		$doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
+		{
+		  echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
+		  (exit 1); exit
+		}
+	else
+		:
+	fi
+} &&
+
+# Now rename the file to the real destination.
+
+	$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
+
+fi &&
+
+# The final little trick to "correctly" pass the exit status to the exit trap.
+
+{
+	(exit 0); exit
+}
Index: vis_dev/vis-2.3/helpers/mkinstalldirs
===================================================================
--- vis_dev/vis-2.3/helpers/mkinstalldirs	(revision 14)
+++ vis_dev/vis-2.3/helpers/mkinstalldirs	(revision 14)
@@ -0,0 +1,111 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+errstatus=0
+dirmode=""
+
+usage="\
+Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..."
+
+# process command line arguments
+while test $# -gt 0 ; do
+  case $1 in
+    -h | --help | --h*)         # -h for help
+      echo "$usage" 1>&2
+      exit 0
+      ;;
+    -m)                         # -m PERM arg
+      shift
+      test $# -eq 0 && { echo "$usage" 1>&2; exit 1; }
+      dirmode=$1
+      shift
+      ;;
+    --)                         # stop option processing
+      shift
+      break
+      ;;
+    -*)                         # unknown option
+      echo "$usage" 1>&2
+      exit 1
+      ;;
+    *)                          # first non-opt arg
+      break
+      ;;
+  esac
+done
+
+for file
+do
+  if test -d "$file"; then
+    shift
+  else
+    break
+  fi
+done
+
+case $# in
+  0) exit 0 ;;
+esac
+
+case $dirmode in
+  '')
+    if mkdir -p -- . 2>/dev/null; then
+      echo "mkdir -p -- $*"
+      exec mkdir -p -- "$@"
+    fi
+    ;;
+  *)
+    if mkdir -m "$dirmode" -p -- . 2>/dev/null; then
+      echo "mkdir -m $dirmode -p -- $*"
+      exec mkdir -m "$dirmode" -p -- "$@"
+    fi
+    ;;
+esac
+
+for file
+do
+  set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+  shift
+
+  pathcomp=
+  for d
+  do
+    pathcomp="$pathcomp$d"
+    case $pathcomp in
+      -*) pathcomp=./$pathcomp ;;
+    esac
+
+    if test ! -d "$pathcomp"; then
+      echo "mkdir $pathcomp"
+
+      mkdir "$pathcomp" || lasterr=$?
+
+      if test ! -d "$pathcomp"; then
+  	errstatus=$lasterr
+      else
+  	if test ! -z "$dirmode"; then
+	  echo "chmod $dirmode $pathcomp"
+    	  lasterr=""
+  	  chmod "$dirmode" "$pathcomp" || lasterr=$?
+
+  	  if test ! -z "$lasterr"; then
+  	    errstatus=$lasterr
+  	  fi
+  	fi
+      fi
+    fi
+
+    pathcomp="$pathcomp/"
+  done
+done
+
+exit $errstatus
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# End:
+# mkinstalldirs ends here
Index: vis_dev/vis-2.3/share/createfunctionmap
===================================================================
--- vis_dev/vis-2.3/share/createfunctionmap	(revision 14)
+++ vis_dev/vis-2.3/share/createfunctionmap	(revision 14)
@@ -0,0 +1,98 @@
+#!/usr/local/bin/perl
+#
+# Script to process the output of purify in terms of memory use.
+#
+# Abelardo Pardo <abel@vlsi.colorado.edu>
+#
+# Revision [$Id: createfunctionmap,v 1.4 1996/12/18 23:43:46 hsv Exp $]
+
+require 5.001;
+use Getopt::Long;
+
+# Define default variables
+#
+$version = 1.3;
+
+# Initialize the different options 
+#
+$opt_h = 0;
+$opt_v = 0;
+
+# Read the options
+# 
+$optionResult = GetOptions("h","v");
+
+# Print the version if required
+#
+if ($opt_v) {
+    print <<ENDOFMESSAGE;
+$0 -- Version: $version -- by Abelardo Pardo <abel\@vlsi.colorado.edu>
+ENDOFMESSAGE
+    exit;
+}
+
+# Print the help message if required
+#
+if ($opt_h || !$optionResult) {
+    print <<ENDOFMESSAGE;
+
+$0 - Program to extract the function declarations from C source code files and 
+     create a map of functions to files. The files must contain the declaration
+     of the functions encapsulated between the keywords "AutomaticStart" and
+     "AutomaticEnd". The tool "extproto" provides an automatic way to create
+     this encapsulations in any *.[ch] file. The file must also contain a
+     "FileName" and a "PackageName" field on its header in order for the map to
+     be extracted correctly.
+
+Usage:
+  $0 [-h] [-v] <files>
+
+Options:
+  -h                Print this message
+  -v                Print the version
+
+Author: Abelardo Pardo <abel\@vlsi.colorado.edu>
+
+ENDOFMESSAGE
+    exit;
+}
+
+# Open the input files
+#
+foreach $filename (@ARGV) {
+
+    if (open(INPUT, $filename)) {
+
+	$indefinition = 0;
+	while(<INPUT>) {
+	    chop;
+	    
+	    if (/FileName\s+\[\s*(.+)\s*\]/) {
+		$cfilename = $1;
+	    }
+	    if (/PackageName\s+\[\s*(.+)\s*\]/) {
+		$pkgname = $1;
+	    }
+	    if (/^\/\*\*AutomaticStart\*+\/$/) {
+		$indefinition = 1;
+	    }
+	    if (/^\/\*\*AutomaticEnd\*+\/$/) {
+		$indefinition = 0;
+	    }
+	    
+	    if ($indefinition == 1) {
+		if (/static\s*.*\s+([a-zA-Z0-9_]+\(.*\))/) {
+		    $function = $1;
+		    $function =~ /([a-zA-Z0-9_]+)\(.*\)/;
+		    print "$pkgname $cfilename $1\n";
+		}
+	    }
+	}
+	close(INPUT);
+    }
+    else {
+	print "Unable to open $filename. Ignoring it.\n";
+    }
+} 
+
+exit;
Index: vis_dev/vis-2.3/share/help/Cmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/Cmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/Cmd.txt	(revision 14)
@@ -0,0 +1,6 @@
+
+  -
+     _________________________________________________________________
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/_ctlp_testCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/_ctlp_testCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/_ctlp_testCmd.txt	(revision 14)
@@ -0,0 +1,29 @@
+
+  _ctlp_test - test the CTL parser
+     _________________________________________________________________
+
+   _ctlp_test [-h] <file_name>
+
+   Test the CTL parser. If the entire file of CTL formulas is successfully
+   parsed, then each formula is printed to stdout, followed by the equivalent
+   existential normal form formula. The formulas read are not stored. For the
+   input file containing:
+ AG(foo=bar); 
+
+   the following is produced:
+ original
+  formula: AG(foo=bar) => equivalent existential formula: !(E(TRUE U
+  !(foo=bar))) 
+
+   For the syntax of CTL formulas, refer to [1]the VIS CTL and LTL syntax
+   manual. Command options:
+
+   -h
+          Print the command usage.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
+
+References
+
+   1. file://localhost/projects/development/hsv/vis/common/doc/ctl/ctl/ctl.html
Index: vis_dev/vis-2.3/share/help/_ctlsp_testCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/_ctlsp_testCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/_ctlsp_testCmd.txt	(revision 14)
@@ -0,0 +1,29 @@
+
+  _ctlsp_test - test the CTL* parser
+     _________________________________________________________________
+
+   _ctlsp_test [-h] <file_name>
+
+   Test the CTL* parser. If the entire file of CTL* formulas is successfully
+   parsed, then each formula is printed to stdout, followed by the equivalent
+   existential normal form formula. The formulas read are not stored. For the
+   input file containing:
+ AG(foo=bar); 
+
+   the following is produced:
+ original
+  formula: AG(foo=bar) => equivalent existential formula: !(E(TRUE U
+  !(foo=bar))) 
+
+   For the syntax of CTL formulas, refer to [1]the VIS CTL and LTL syntax
+   manual. Command options:
+
+   -h
+          Print the command usage.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
+
+References
+
+   1. file://localhost/projects/development/hsv/vis/common/doc/ctl/ctl/ctl.html
Index: vis_dev/vis-2.3/share/help/_grab_testCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/_grab_testCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/_grab_testCmd.txt	(revision 14)
@@ -0,0 +1,115 @@
+
+  _grab_test - Performs invairant checking on a flattened network with the GRAB
+  abstraction refinement algorithm.
+     _________________________________________________________________
+
+   _grab_test [-a <refine_algorithm>] [-c <cex_type>] [-d <dbg_level>] [-F]
+   [-M] [-i] [-m] [-t <time_out_period>] [-v <verbosity_level>] [-f <dbg_file>]
+   [-h] <inv_file>
+
+   Performs invairant checking on a flattened network with the GRAB abstraction
+   refinement algorithm. Before calling this command, the user should have
+   created the flattened netowrk by calling the commands [1]flatten_hierarchy
+   and [2]build_partition_maigs. The default BDD manager and network partition
+   are not mandatory for calling this command, though they will be used if
+   available.  (In other words, the user doesn't have to run the commands
+   [3]static_order and [4]build_partition_mdds before calling this command.)
+   Regardless of the options, no 'false positive' or 'false negatives' will
+   occurs: the result is correct for the given model. Properties to be verified
+   should be provided as invariant formulae in the file inv_file. Node that the
+   support of any wire referred to in a formula should consist only of latches.
+   For the precise syntax of CTL and LTL formulas, see the [5]VIS CTL and LTL
+   syntax manual.
+
+   If  a  formula  does  not  pass,  a proof of failure (referred to as a
+   counter-example) is demonstrated. Whether demostrate the proof or not can be
+   specified (see option -d).
+
+   Command options:
+
+   -a <refine_algorithm>
+          Specify the refinement variable selection algorithm.
+
+          refine_algorithm must be one of the following:
+
+          GRAB: the GRAB refinement method (Default).
+
+   -c <cex_type>
+          Specify the type of abstract counter-examples used in the analysis.
+
+          cex_type must be one of the following:
+
+          0: minterm state counter-example.
+
+          1: cube state counter-example.
+
+          2: synchronous onion rings (Default).
+
+   -d <dbg_level>
+          Specify whether to demonstrate a counter-example when the system
+          fails a formula being checked.
+
+          dbg_level must be one of the following:
+
+          0: No debugging performed. dbg_level=0 is the default.
+
+          1: Generate a counter-example (a path to a fair cycle).
+
+   -F <finegrain_flag>
+          Enable or disable the use of fine-grain abstraction.
+
+          finegrain_flag must be one of the following:
+
+          0: disable fine-grain abstraction.
+
+          1: enable fine-grain abstraction (Default).
+
+   -M <refinemin_flag>
+          Enable or disable the use of greedy refinement minimization.
+
+          refinemin_flag must be one of the following:
+
+          0: disable greedy refinement minimization.
+
+          1: enable greedy refinement minimization (Default).
+
+   -i
+          Print  input  values  causing transitions between states during
+          debugging. Both primary and pseudo inputs are printed.
+
+   -m
+          Pipe debugger output through the UNIX utility more.
+
+   -t <timeOutPeriod>
+          Specify the time out period (in seconds) after which the command
+          aborts. By default this option is set to infinity.
+
+   -v <verbosity_level>
+          Specify verbosity level. This sets the amount of feedback on CPU
+          usage and code status.
+          verbosity_level must be one of the following:
+
+          0: No feedback provided. This is the default.
+
+          1: Feedback on code location.
+
+          2: Feedback on code location and CPU usage.
+
+   -f <dbg_out>
+          Specify the name of the file ot which error trace is written.
+
+   -h
+          Print the command usage.
+
+          See also commands : model_check, check_invariant
+            __________________________________________________________
+
+          Last updated on 20100410 00h02
+
+References
+
+   1. file://localhost/projects/development/hsv/vis/common/doc/html/flatten_hierarchyCmd.html
+   2. file://localhost/projects/development/hsv/vis/common/doc/html/build_partition_maigsCmd.html
+   3. file://localhost/projects/development/hsv/vis/common/doc/html/static_orderCmd.html
+   4. file://localhost/projects/development/hsv/vis/common/doc/html/build_partition_mddsCmd.html
+   5. file://localhost/projects/development/hsv/vis/common/doc/ctl/ctl/ctl.html
Index: vis_dev/vis-2.3/share/help/_init_state_formulaCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/_init_state_formulaCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/_init_state_formulaCmd.txt	(revision 14)
@@ -0,0 +1,11 @@
+
+  _init_state_formula - write resettability condition as a CTL formula
+     _________________________________________________________________
+
+   _init_state_formula [-h] [<init_file>]
+
+   Write resettability condition as a CTL formula. Writes to init_file is
+   specified, else stdout.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/_mAig_testCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/_mAig_testCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/_mAig_testCmd.txt	(revision 14)
@@ -0,0 +1,8 @@
+
+  _mAig_test -
+     _________________________________________________________________
+
+   _mAig_test
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/_memory_profileCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/_memory_profileCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/_memory_profileCmd.txt	(revision 14)
@@ -0,0 +1,57 @@
+
+  _memory_profile - It shows the amount of memory used by every pacakge.
+     _________________________________________________________________
+
+   _memory_profile [-f <filename>] [-h] [-p] [-u <units>]
+
+   This  command  intregrates  the output from purify with a function map
+   generated by a perlscript plus another perlscript to generate a memory
+   profile of vis.
+
+   This command relies on the output of purify to a file to call the script
+   "memoryaccount" and produce a summary of how much memory has been allocated
+   by each package. Although this command may appear simple it requires the
+   interaction of two scripts and three files, so special care should be taken
+   when attempting to modify it.
+
+   Here is the way it works. The code in this command is conditionally compiled
+   depending on the definition of the symbol PURIFY. If the symbol is not
+   defined, the program prints a message notifying that the command is not
+   operative in this executable. If PURIFY has been defined, there are certain
+   things that are assumed. The executable has been linked with purify. The
+   output of purify is being redirected to a file with name purify.log. The
+   perl script memoryaccount is in $VIS/common/share and it is executable.
+   There exists a file mapping function names to packages in the same place
+   whose name is .fmap.
+
+   The command then calls purify_all_inuse() to force purify to dump to the
+   file purify.log the information about the memory that is currently visible
+   to the program. This memory is not the total memory allocated by the program
+   since there may be leaked memory that is no longer accessible. A temporary
+   file is created and the script memoryaccount is called to analyze the file
+   purify.log and write in the temporary file the memory profile obtained from
+   it. Once the script is done, the temporary file is dumped to vis_stdout and
+   deleted.
+
+   Since most of the computation in this command is done by the pearlscript
+   memoryaccount, for more information please refer to the message printed when
+   the script is invoked with the option -h. Command options:
+
+   -f <filename>
+          File to read the dump from. The default is purify.log. This option
+          should be used if and only if the option -log-file has been used at
+          the linking stage when building the executable.
+
+   -h
+          Print the command usage.
+
+   -p
+          Print also the packages that did not allocated any visible memory
+
+   -u <units>
+          Units to print the memory usage in. It may be "b" for bytes, "k" for
+          kilobytes, "m" for megabytes and "g" for gigabytes. The default is
+          bytes.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/_ntm_testCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/_ntm_testCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/_ntm_testCmd.txt	(revision 14)
@@ -0,0 +1,22 @@
+
+  _ntm_test - test the ntm package
+     _________________________________________________________________
+
+   _ntm_test [-h] [-v]
+
+   Test  the  ntm  package.  This package is responsible for building the
+   multi-valued functions (represented as MDDs) of the flattened network. This
+   command builds the multi-valued functions of the combinational outputs in
+   terms of the combinational inputs. The multi-valued functions are then
+   deleted.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   -v
+          Print the sizes of the MDDs built.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/_tbl_testCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/_tbl_testCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/_tbl_testCmd.txt	(revision 14)
@@ -0,0 +1,18 @@
+
+  _tbl_test - test the functionality of the tbl package.
+     _________________________________________________________________
+
+   _tbl_test [-h] [-v]
+
+   Tests the functionality of the tbl package.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   -v
+          Verbose mode.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/_tst_testCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/_tst_testCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/_tst_testCmd.txt	(revision 14)
@@ -0,0 +1,19 @@
+
+  _tst_test - template for implementing commands
+     _________________________________________________________________
+
+   _tst_test [-h] [-v]
+
+   This command does nothing useful. It merely serves as a template for the
+   implementation of new commands.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   -v
+   Verbose mode.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/aliasCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/aliasCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/aliasCmd.txt	(revision 14)
@@ -0,0 +1,61 @@
+
+  alias - provide an alias for a command
+     _________________________________________________________________
+
+   alias [-h] [<name> [<string>]]
+
+   The "alias" command, if given no arguments, will print the definition of all
+   current aliases.
+
+   Given a single argument, it will print the definition of that alias (if
+   any). Given two arguments, the keyword "name" becomes an alias for the
+   command string "string", replacing any other alias with the same name.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   <name>
+          Alias
+
+   <string>
+          Command string
+
+   It is possible to create aliases that take arguments by using the history
+   substitution mechanism. To protect the history substitution character `%'
+   from immediate expansion, it must be preceded by a `\' when entering the
+   alias.
+
+   For example:
+
+   vis> alias read read_\%:1 \%:2.\%:1
+   vis> read blif lion
+  
+
+   will create an alias `read', execute "read_blif lion.blif".
+
+   And...
+
+  vis> alias echo2 "echo Hi ; echo \%* !"
+  vis> echo2 happy birthday
+  
+
+   will print:
+
+  Hi
+  happy birthday !
+  
+
+   CAVEAT: Currently there is no check to see if there is a circular dependency
+   in the alias definition. e.g.
+
+  vis> alias foo "print_network_stats; print_network; foo"
+  
+
+   creates an alias which refers to itself. Executing the command "foo" will
+   result an infinite loop during which the commands "print_network_stats" and
+   "print_network" will be executed.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/approximate_model_checkCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/approximate_model_checkCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/approximate_model_checkCmd.txt	(revision 14)
@@ -0,0 +1,178 @@
+
+  approximate_model_check - perform ACTL model checking on an abstracted and
+  flattened network
+     _________________________________________________________________
+
+   approximate_model_check [-h] [-v <verbosity_level>] <ctl_file>
+
+   Performs  ACTL  model checking on an abstracted and flattened network.
+   Predefined  abstractions are performed prior to model checking. Before
+   calling this command, the user should have initialized the design by calling
+   the command [1]init_verify.
+
+   The command includes two dual algorithms. The user should set appropriate
+   environment  parameters  associated with the command to execute proper
+   algorithm. By default, the command makes its effort to prove whether given
+   ACTL formula is positive. To check whether the ACTL formula is negative,
+   user should set the environment parameter amc_prove_false prior to executing
+   the command. See [2]below for the environment parameters associated with
+   this command.
+
+   Properties to be verified should be provided as ACTL formulas in the file
+   <ctl_file>. The command only accepts ACTL formulas. Mixed, ECTL expressions
+   are not supported. ACTL formulas are those in which all quantifiers are
+   universal and negation is only allowed at the level of atomic propositions.
+   For the precise syntax of CTL formulas, see the [3]VIS CTL and LTL syntax
+   manual.
+
+   The command is designed to tackle the state explosion problem we encounter
+   when dealing with large and complex circuits. Based on the initial size of
+   the  group, the command constructs over- or under-approximation of the
+   transition relation of the system. A group (subsystem) is a portion of the
+   original circuit containing a subset of the latches and their next state
+   functions.   The  initial  size  of  a  group  can  be  set  with  the
+   [4]amc_sizeof_group environment variable. These initial approximations may
+   not contain every detail of the exact system. However they may contain
+   enough information to determine whether the formula is positive or negative.
+   Starting from an initial coarse approximation, the command makes its effort
+   to  prove whether given ACTL formula is positive or negative. When the
+   procedure  fails  to  prove  correctness  of  the formula with initial
+   approximations, it automatically refines the approximations. It repeats the
+   process until the algorithm produces a reliable result or the available
+   resources are exhausted.
+
+   Due to the overhead procedures, for some circuits, the exact [5]model_check
+   method may evaluate formulas faster with less resources. If any formula
+   evaluates to false, a debug trace is reported.
+
+   The command does not use fairness constraints even if they have been read
+   with the [6]read_fairness command.
+
+   Command options: 
+
+   -h
+          Print the command usage.
+
+   -v <verbosity_level>
+          Specify  verbosity  level.  verbosity_level  must be one of the
+          following:
+
+          0 : No feedback provided. This is the default.
+          1 : Some feedback.
+          2 : Lots of feedback.
+
+   -t <timeOutPeriod>
+          Specify the time out period (in seconds) after which the command
+          aborts. By default this option is set to infinity.
+
+   <ctl_file>
+          File containing ACTL formulas to be model checked.
+
+   Environment Parameters:
+
+   Environment parameters should be set using the set command from the VIS
+   shell
+   (e.g. vis> set amc_prove_false).
+
+   amc_prove_false 
+          When the parameter is set, the command makes its effort to prove
+          whether given ACTL formula is negative. The command constructs a set
+          of under-approximations of the transition relations of the system.
+          When the formula evaluates to false, a debug trace is reported by
+          default.
+
+   amc_grouping_method <grouping method> 
+          Specifies grouping method. Grouping method is a method for grouping
+          number of latches into single subsystem. Two methods are supported.
+
+          Grouping based on hierarchy(default) : The method groups latches
+          based on the hierarchy of the system. Normally, complex circuits are
+          designed  in  multiple processes. Furthermore, processes form a
+          hierarchy. The method uses this information provided by the original
+          design. When a design described in high level description language is
+          transformed into low level BLIF format, the processes are transformed
+          into subcircuits. The method groups those latches that are within
+          same subcircuit.
+
+          Grouping based on latch dependencies(latch_dependency): The method
+          groups  those latches that are closely related. Closely related
+          latches are those who has many (transitive) connections between them.
+
+          When the parameter is not specified, the command by default uses
+          hierarchical grouping method.
+
+   amc_sizeof_group <integer value> 
+          Determines the number of latches in each group(subsystem). The
+          default value is 8. The initial size of the subsystem determines the
+          initial degree of approximations of the transition relations. There's
+          no proven rule of setting the value. Some experimental results show
+          that setting the value to about 5-20% of overall number of latches is
+          reasonable(e.g. if the system contains 100 latches set the value to
+          5-20). However, the suggested range may not work well with some
+          examples.
+
+   amc_DC_level <integer value> 
+          Specifies don't care levels. Default level is 0. Absence of the
+          parameter sets the amc_DC_level to 0.
+          amc_DC_level must be one of the following:
+
+        0: No don't cares are used. This is the default.
+
+        1: Use unreachable states as don't cares.
+
+        2: Aggressively use DC's to simplify MDD's in model checking.
+
+          Using don't cares may take more time for some examples since the
+          approximate model checker computes the reachable states for each
+          subsystem. For some large circuits it is undesirable to set don't
+          care level.
+
+   Related "set" options:
+
+   ctl_change_bracket <yes/no>
+          Vl2mv automatically converts "[]" to "<>" in node names, therefore
+          CTL parser does the same thing. However, in some cases a user does
+          not want to change node names in CTL parsing. Then, use this set
+          option by giving "no". Default is "yes".
+
+   See also commands : model_check, incremental_ctl_verification
+
+   Examples:
+   Here are some example sequences of the VIS executions using the approximate
+   model checker.
+
+   read_blif_mv abp/abp.mv
+   flatten_hierarchy
+   static_order
+   build_partition_mdds
+   set amc_sizeof_group 4
+   approximate_model_check abp/abpt.ctl
+   time
+   quit
+
+   read_blif_mv coherence/coherence.mv
+   flatten_hierarchy
+   static_order
+   build_partition_mdds
+   set amc_sizeof_group 8
+   set amc_prove_false
+   set amc_DC_level 0
+   approximate_model_check coherence/coherence2.ctl
+   time
+   quit
+
+   The algorithm used by approximate_model_check is described in detail in
+   [7]ftp://vlsi.colorado.edu/pub/iccad96.ps
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
+
+References
+
+   1. file://localhost/projects/development/hsv/vis/common/doc/html/init_verifyCmd.html
+   2. file://localhost/projects/development/hsv/vis/common/doc/html/approximate_model_checkCmd.html#environment
+   3. file://localhost/projects/development/hsv/vis/common/doc/ctl/ctl/ctl.html
+   4. file://localhost/projects/development/hsv/vis/common/doc/html/approximate_model_checkCmd.html#sizeofgroup
+   5. file://localhost/projects/development/hsv/vis/common/doc/html/model_checkCmd.html
+   6. file://localhost/projects/development/hsv/vis/common/doc/html/read_fairnessCmd.html
+   7. ftp://vlsi.colorado.edu/pub/iccad96.ps
Index: vis_dev/vis-2.3/share/help/bdd_sat_bounded_model_checkCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/bdd_sat_bounded_model_checkCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/bdd_sat_bounded_model_checkCmd.txt	(revision 14)
@@ -0,0 +1,91 @@
+
+  bdd_sat_bounded_model_check - performs an LTL bounded model checking on a
+  flattened network
+     _________________________________________________________________
+
+   bdd_sat_bounded_model_check [-h] [-v <verbosity_level>] [-d <dbg_level>]
+   [-i] -m <minimum_length> -k <maximum_length> -s <step_value> -o <cnf_file>
+   <ltl_file>
+
+   Performs an LTL bounded model checking on a flattened network. This command
+   looks for a counterexample of length â¥ minimum_length and â€ maximum_length.
+   It increments the length by step_value. Before calling this command, the
+   user  should  have  initialized  the  design  by  calling  the command
+   [1]flatten_hierarchy, and then calling the command [2]build_partition_maigs.
+
+   The value of maximum length must be >= minimum length.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   -m <minimum_length>
+          Minimum length of counterexample to be checked (default is 0).
+
+   -k <maximum_length>
+          Maximum length of counterexample to be checked (default is 1).
+
+   -s <step_value>
+          Incrementing value of counterexample length (default is 1).
+
+   -r <inductive_Step>
+          Use inductive proof at each step_value to check if the property
+          passes (default is 0). 0 means don't use the inductive proof. BMC
+          will check using the indcution if the property passes if the current
+          length of the counterexample is a multiple of inductive_Step.
+
+   -F <fairness_file>
+          Read fairness constraints from <fairness_file>. Each formula in the
+          file is a condition that must hold infinitely often on a fair path.
+
+   -o <cnf_file> Save the CNF formula in <cnf_file>
+   -t <timeOutPeriod>
+          Specify the time out period (in seconds) after which the command
+          aborts. By default this option is set to infinity.
+
+   -v <verbosity_level>
+          Specify verbosity level. This sets the amount of feedback on CPU
+          usage and code status.
+          verbosity_level must be one of the following:
+
+          0: No feedback provided. This is the default.
+
+          1: Feedback on code location.
+
+          2: Feedback on code location and CPU usage.
+
+   -d <dbg_level>
+          Specify the amount of debugging performed when the BMC models check
+          the LTL formula.
+
+          dbg_level must be one of the following:
+
+          0: No debugging performed. dbg_level=0 is the default.
+
+          1: Debugging with minimal output: generate counter-example if the LTL
+          formula fails and the counterexample length.
+
+   -h
+          Print the command usage.
+
+   -i
+          Print  input  values  causing transitions between states during
+          debugging.
+
+   -o <cnf_file>;
+          File containing CNF of the counterexample if exist. If specifies, the
+          user can exam this file looking for information about the generated
+          path. This file will be the input to the SAT solver. The contents of
+          this file is in dimacs format.
+
+   <ltl_file>
+          File containing LTL formulas to be model checked.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
+
+References
+
+   1. file://localhost/projects/development/hsv/vis/common/doc/html/flatten_hierarchyCmd.html
+   2. file://localhost/projects/development/hsv/vis/common/doc/html/build_partition_maigsCmd.html
Index: vis_dev/vis-2.3/share/help/bounded_model_checkCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/bounded_model_checkCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/bounded_model_checkCmd.txt	(revision 14)
@@ -0,0 +1,140 @@
+
+  bounded_model_check - Performs a SAT-based LTL model checking on a flattened
+  network
+     _________________________________________________________________
+
+   bounded_model_check [-h] [-v <verbosity_level>] [-m <minimum_length>] [-k
+   <maximum_length>] [-s <step_value>] [-r <termination_check_step>] [-e] [-F
+   <fairness_file>] [-S <sat_solver>] [-E <encoding>] [-C <clause_type>] [-I
+   <inc_level>] [-d <dbg_level>] [-t <timeOutPeriod>] [-o <cnf_file>] [-i] [-O
+   <debug_file>] <ltl_file>
+
+   Performs  a  SAT-based LTL bounded model checking (BMC) on a flattened
+   network.  This  command  looks  for  a  counterexample  of  length k (
+   minimum_length â€ k â€ maximum_length). If -r is specified, this command
+   performs check for termination after each termination_check_step . If no
+   counterexample is found, this command increases k by step_value (specifies
+   by  the -s option) until a counterexample is found, the search becomes
+   intractable (timed out), or k reaches a bound (determine by the check for
+   termination),  and then we conclude that the LTL property passes. This
+   command implements the basic encoding of Bounded Model Checking (BMC) as
+   descibed in the paper "Symbolic Model Checking without BDDs". However, the
+   -E option can be used to select other encoding scheme. We also applied some
+   of the improvements in the BMC encoding described in the paper "Improving
+   the Encoding of LTL Model Checking into SAT". To prove that an LTL property
+   passes, we implement the termination methods that are descirebed in the
+   papers "Checking Safety Properties Using Induction and a SAT-Solver" and
+   "Proving More Properties with Bounded Model Checking". Before calling this
+   command, the user should have initialized the design by calling the command
+   [1]flatten_hierarchy. If the user uses the -r option and the LTL property is
+   a general LTL property, the command [2]build_partition_maigs must be called.
+   The aig graph must be built by calling the command [3]build_partition_mdds
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   -m <minimum_length>
+          Minimum length of counterexample to be checked (default is 0).
+
+   -k <maximum_length>
+          Maximum length of counterexample to be checked (default is 1).
+
+   -s <step_value>
+          Incrementing value of counterexample length (default is 1).
+
+   -r <termination_check_step>
+          Check for termination for each termination_check_step (default is 0).
+          0 means don't check for termination.
+
+   -e
+          Activate early termination check. Check if there is no simple path
+          starts from an initial state. Valid only for general LTL and safety
+          properties. Must be used with -r option.
+
+   -S <sat_solver>
+          Specify SAT solver
+          sat_solver must be one of the following:
+
+          0: CirCUs (Default)
+
+          1: zChaff
+
+   -E <encoding>
+          Specify encoding scheme
+          encoding must be one of the following:
+
+          0: The original BMC encoding (Default)
+
+          1: SNF encoding
+
+          2: Fixpoint encoding
+
+   -C <clause_type>
+          Specify clause type
+          encoding must be one of the following:
+
+          0: Apply CirCUs SAT solver on circuit (Default)
+
+          1: Apply SAT solver on CNF generated form circuit
+
+          2: Apply SAT solver on CNF
+
+   -I <inc_level>
+          Specify increment sat solver type
+          encoding must be one of the following:
+
+          1: Trace Objective (Default)
+
+          2: Distill
+
+          3: Trace Objective + Distill
+
+   -F <fairness_file>
+          Read fairness constraints from <fairness_file>. Each formula in the
+          file is a condition that must hold infinitely often on a fair path.
+
+   -o <cnf_file> Save CNF formula in <cnf_file>
+   -O <debug_file> Save counterexample to <debug_file>
+   -t <timeOutPeriod>
+          Specify the time out period (in seconds) after which the command
+          aborts. By default this option is set to infinity.
+
+   -v <verbosity_level>
+          Specify verbosity level. This sets the amount of feedback on CPU
+          usage and code status.
+          verbosity_level must be one of the following:
+
+          0: No feedback provided. This is the default.
+
+          1: Feedback on code location.
+
+          2: Feedback on code location and CPU usage.
+
+   -d <dbg_level>
+          Specify the amount of debugging performed when the BMC models check
+          the LTL formula.
+
+          dbg_level must be one of the following:
+
+          0: No debugging performed. dbg_level=0 is the default.
+
+          1: Debugging with minimal output: generate counter-example if the LTL
+          formula fails and the counterexample length.
+
+   -i
+          Print  input  values  causing transitions between states during
+          debugging.
+
+   <ltl_file>
+          File containing LTL formulae to be checked.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
+
+References
+
+   1. file://localhost/projects/development/hsv/vis/common/doc/html/flatten_hierarchyCmd.html
+   2. file://localhost/projects/development/hsv/vis/common/doc/html/build_partition_maigsCmd.html
+   3. file://localhost/projects/development/hsv/vis/common/doc/html/build_partition_mddsCmd.html
Index: vis_dev/vis-2.3/share/help/build_partition_maigsCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/build_partition_maigsCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/build_partition_maigsCmd.txt	(revision 14)
@@ -0,0 +1,23 @@
+
+  build_partition_maigs - build a partition of MAIGs for the flattened network
+     _________________________________________________________________
+
+   build_partition_maigs [-h] [-d] [-n]
+
+   Build the multi-valued AND/INVERTER graph (MAIG) of a flattened network. It
+   builds  the  MAIG  for the combinational outputs (COs) in terms of the
+   combinational inputs (CIs). The pointer to this graph is stored in the
+   network to be used by other commands, such as bounded_model_check. This
+   command must be preceded by the commands flatten_hierarchy. This command
+   will remove any previous build to this graph.
+
+   Command options:
+
+   -n
+          Disable BDD sweeping.
+
+   -d
+          Build aig structure in depth first manner.
+            __________________________________________________________
+
+          Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/build_partition_mddsCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/build_partition_mddsCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/build_partition_mddsCmd.txt	(revision 14)
@@ -0,0 +1,84 @@
+
+  build_partition_mdds - build a partition of MDDs for the flattened network
+     _________________________________________________________________
+
+   build_partition_mdds [-h] [-i] [-n <list>] [-s <num>] [-t <seconds>] [-v]
+   [<method>]
+
+   Build the MDDs of a flattened network. Depending on the method selected, the
+   MDDs for the combinational outputs (COs) are built in terms of either the
+   combinational inputs (CIs) or in terms of some subset of intermediate nodes
+   of the network. The MDDs built are stored in a DAG called a "partition". The
+   vertices of a partition correspond to the CIs, COs, and any intermediate
+   nodes used. Each vertex has a multi-valued function (represented by MDDs)
+   expressing the function of the corresponding network node in terms of the
+   partition vertices in its transitive fanin. Hence, the MDDs of the partition
+   represent a partial collapsing of the network.
+
+   This  command  must  be preceded by the commands flatten_hierarchy and
+   static_order. The partition built is stored with the network for use by
+   other commands, such as simulate, compute_reach, model_check, etc. This
+   command  has  no  affect  when invoked on a network that already has a
+   partition.  To  remove  the  existing partition of a network, reinvoke
+   flatten_hierarchy.
+
+   The choice of method determines which intermediate nodes are used. The inout
+   method represents one extreme where no intermediate nodes are used, and
+   total represents the other extreme where every node in the network has a
+   corresponding vertex in the partition. If no method is specified on the
+   command line, then the value of the flag partition_method is used (this flag
+   is set by the command set partition_method), unless it does not have a
+   value, in which case the forntier method is used. The different methods
+   available are:
+
+     inout Expresses the combinational outputs in terms of the combinational
+          inputs.
+
+     total The partition built is isomorphic to the combinational part of the
+          network. The function of each node is expressed in terms of its
+          immediate fanins. If the -i is used the function attached to each
+          vertex is computed as a function of the combinational inputs.
+
+     partial Builds a partition using the intermediate nodes specified with the
+          -n option or the -f option.
+
+     frontier  (default)  Builds  a  partition  creating vertices for the
+          intermediate nodes as needed in order to control the BDD size. The
+          threshold  value  for  the BDD size can be set by the parameter
+          "partition_threshold". This method encompasses both "inout" (set
+          partition_threshold  parameter  to  infinity)  and "total" (set
+          partition_threshold parameter to 0).
+
+     boundary Builds a partition in a fashion that preserves all nodes that are
+          Input/Output  nodes of any hnode in the hierarchy rooted at the
+          current hnode.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   -i
+          Build the multi-valued functions of each partition vertex in terms of
+          the combinational inputs, rather than in terms of its transitive
+          fanin vertices.
+
+   -n <list>
+          Used  in  conjunction  with the partial method. List is a comma
+          separated list of network nodes to use as intermediate nodes in the
+          partition.
+
+   -s <num>
+          Level  of  severity  of a post-computation check applied to the
+          partition data structure (0 by default, meaning no check).
+
+   -t <seconds>
+          Time in seconds allowed to build the partition. If the computation
+          time goes above that limit, the process of building the partition is
+          aborted. The default is no limit.
+
+   -v
+          Turn on the verbosity.
+            __________________________________________________________
+
+          Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/cdCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/cdCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/cdCmd.txt	(revision 14)
@@ -0,0 +1,17 @@
+
+  cd - change the current node
+     _________________________________________________________________
+
+   cd [-h] <child_instance_name> or <..>
+
+   Changes the current node in the existing hierarchy. The argument should be
+   either the name of a child node or .. meaning the parent node. Note that cd
+   ../foo is not allowed.
+
+   Command options:
+
+   -h
+          Print the command usage.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/check_invariantCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/check_invariantCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/check_invariantCmd.txt	(revision 14)
@@ -0,0 +1,262 @@
+
+  check_invariant - check all states reachable in flattened network satisfy
+  specified invariants
+     _________________________________________________________________
+
+   check_invariant [-c] [-d <dbg_level>] [-g <hints_file>] [-f] [-h] [-i] [-m]
+   [-r]     [-t    <time_out_period>]    [-v    <verbosity_level>]    [-A
+   <reachability_analysis_type>] [-D] <invar_file>
+
+   Performs invariant checking on a flattened network. Before calling this
+   command, the user should have initialized the design by calling the command
+   [1]init_verify.
+
+   If the option -A3 (abstraction refinement method GRAB) is used, the command
+   [2]build_partition_maigs should also have been executed. However, in this
+   case, the default BDD manager and network partition are not mandatory,
+   though they will be used if available. (In other words, the user must run
+   the commands [3]flatten_hierarchy and [4]build_partition_maigs, but doesn't
+   have to run the commands [5]static_order and [6]build_partition_mdds before
+   calling  this  command.)  For extremely large networks, it is actually
+   favorable not to build them for the entire concrete model, but let this
+   procedure assign bdd ids and construct the partition incrementally.
+
+   Option -A4 means abstraction refinement approach using puresat algorithm,
+   which is entirely based on SAT solver.
+
+   An invariant is a set of states. Checking the invariant is the process of
+   determining that all states reachable from the initial states lie in the
+   invariant.
+
+   One way of defining an invariant is through a CTL formula which has no path
+   operators. Such formulas should be specified in the file invar_file. Note
+   that the support of any wire referred to in a formula should consist only of
+   latches. For the precise syntax of CTL formulas, see the [7]VIS CTL and LTL
+   syntax manual.
+
+   check_invariant ignores all fairness conditions associated with the FSM.
+
+   check_invariant involves reachability analysis where at every step of the
+   reachability computation all the specified invariants are checked in the
+   reachable states computed thus far. If some invariant does not hold, a proof
+   of failure is demonstrated. This consists of a path starting from an initial
+   state to a state lying outside the invariant. This path is made as short as
+   possible. For the -A 0 option or default -A option, it is the shortest path
+   leading  to  a  state outside the invariant. If a set of invariants is
+   specified, the failed formulas are reported as soon as they are detected.
+   The check is continued with the remaining invariants.
+
+   Command options:
+
+   -d <dbg_level>
+          Specify the amount of debugging performed when the system fails a
+          formula being checked.
+
+          dbg_level must be one of the following:
+
+          0 : No debugging performed. This is the default.
+
+          1 : Generate a path from an initial state to a state lying outside
+          the invariant. This option stores the onion rings just as specifying
+          -f would have. Therefore, it may take more time and memory if the
+          formula passes. This option is incompatible with -A 2 option.
+
+   -f
+          Store the set of new states (onion rings) reached at each step of
+          invariant. This option is likely to use more memory but possibly
+          faster  results  for invariants that fail. Therefore, the debug
+          information for a failed invariant, if requested, may be provided
+          faster. This option is not compatible with -A 2 options.
+
+   -g <hints_file>
+          Use guided search. The file hints_file contains a series of hints. A
+          hint is a formula that does not contain any temporal operators, so
+          hints_file has the same syntax as a file of invariants used for
+          check_invariant. The hints are used in the order given to change the
+          transition relation. The transition relation is conjoined with the
+          hint to yield an underapproximation of the transition relation. If
+          the hints are cleverly chosen, this may speed up the computation
+          considerably, because a search with the changed transition relation
+          may be much simpler than one with the original transition relation,
+          and results obtained can be reused, so that we may never have to do
+          an expensive search with the original relation. See also: Ravi and
+          Somenzi, Hints to accelerate symbolic traversal. CHARME'99; Bloem,
+          Ravi, and Somenzi, Efficient Decision Procedures for Model Checking
+          of Linear Time Logic Properties, CAV'99; Bloem, Ravi, and Somenzi,
+          Symbolic Guided Search for CTL Model Checking, DAC'00. This option is
+          not compatible with -A 2 option. The description of some options for
+          guided   search   can   be   found   in   the   help  page  for
+          print_guided_search_options.
+
+   -h
+          Print the command usage.
+
+   -c
+          Use the formula tree so that subformulae are not shared among the CTL
+          formulae in the input file. This option is useful in the following
+          scenario - formulae A, B and C are being checked in order and there
+          is sub-formula sharing between A and C. If the BDDs corresponding to
+          the shared sub-formula is huge then computation for B might not be
+          able to finish without using this option.
+
+   -i
+          Print  input  values  causing transitions between states during
+          debugging. Both primary and pseudo inputs are printed.
+
+   -m
+          Pipe debugger output through the UNIX utility more.
+
+   -r
+          Reduce the FSM derived from the flattened network with respect to
+          each of the invariants in the input file. By default, the FSM is
+          reduced with respect to the conjunction of the invariants in the
+          input file. If this option is used and don't cares are being used for
+          simplification, then subformula sharing is disabled (result might be
+          incorrect otherwise).
+
+          The truth of an invariant may be independant of parts of the network
+          (such as when wires have been abstracted; see [8]flatten_hierarchy).
+          These parts are effectively removed when this option is invoked; this
+          may result in more efficient invariant checking.
+
+   -t <timeOutPeriod>
+          Specify the time out period (in seconds) after which the command
+          aborts. By default this option is set to infinity.
+
+   -v <verbosity_level>
+          Specify verbosity level. This sets the amount of feedback on CPU
+          usage and code status.
+
+          verbosity_level must be one of the following:
+
+          0 : No feedback provided. This is the default.
+
+          1 : Feedback on code location.
+
+          2 : Feedback on code location and CPU usage.
+
+   -A <reachability_analysis_type>
+          This  option  allows  specification of the type of reachability
+          computation.
+
+          0:  (default) Breadth First Search. No approximate reachability
+          computation.
+
+          1: High Density Reachability Analysis (HD). Computes reachable states
+          in a manner that keeps BDD sizes under control. May be faster than
+          BFS in some cases. For larger circuits, this option could compute
+          more  reachable states than the -A 0 option for the same memory
+          constraints, consequently may prove more invariants false. For help
+          on  controlling  options  for  HD, look up help on the command:
+          print_hd_options [9]print_hd_options. Refer Ravi & Somenzi, ICCAD95.
+          The path generated for a failed invariant using this method may not
+          be the shortest path. This option is available only when compiled
+          with the CUDD package.
+
+          2.   Approximate   Reachability   Don't  Cares(ARDC).  Computes
+          over-approximated reachable states in the reachability analysis step.
+          This may be faster than the -A 0 option . The invariants are checked
+          in the over-approximation. This may produce false negatives, but
+          these are resolved internally using the exact reachable states. The
+          final results produced are the same as those for exact reachable
+          states. For help on controlling options for ARDC, look up help on the
+          command: print_ardc_options. [10]print_ardc_options Refer 2 papers in
+          TCAD96 Dec. Cho et al, one is for State Space Decomposition and the
+          other is for Approximate FSM Traversal. This option is incompatible
+          with -d 1 and -g options.
+
+          3. The GRAB Abstraction Refinement Method. Conducts the reachability
+          analysis on an abstract model. If the invariants are true in the
+          abstract model, they are also true in the original model. If the
+          invariants are false, the abstract counter-examples are used to
+          refine the abstract model (since it is still inconclusive). This
+          procedure iterates until a conclusive result is reached. Note that,
+          with this option, "build_partitioned_mdds" and "static_order" does
+          not have to be executed before calling "check_invariants," though the
+          default BDD partition and order will be reused if available. (When
+          checking  extremely  large  models,  skipping  either  or  both
+          "static_order"  and "build_partitioned_mdds" can often make the
+          verification much faster.) The grainularity of abstraction refinement
+          also depends on the parameter "partition_threshold", which by default
+          is 5000; one can use the VIS command "set partition_threshold 1000"
+          to change its value. For experienced users who want to fine-tune the
+          different  parameters  of  GRAB,  please  try  the test command
+          "_grab_test" ("_grab_test -h" prints out its usage information).
+          Refer to Wang et al., ICCAD2003 and ICCD2004 for more information
+          about the GRAB algorithm. Note that this option is incompatible with
+          the "-d 1" and "-g" options.
+
+          4. Abstraction refinement approach using puresat algorithm, which is
+          entirely based on SAT solver. It has several parts: * Localization
+          base Abstraction * K-induction to prove the truth of a property *
+          Bounded Model Checking to find bugs * Incremental concretization
+          based methods to verify abstract bugs * UNSAT proof based method to
+          obtain refinement * Refinement minization to guarrantee a minimal
+          refinement For more information, please check the BMC'03 and STTT'05
+          paper of Li et al., "A satisfiability-based appraoch to abstraction
+          refinement in model checking", and " Abstraction in symbolic model
+          checking using satisfiability as the only decision procedure"
+
+   -D
+          First compute an overapproximation to the reachable states. Minimize
+          the transition relation using this approximation, and then compute
+          the set of reachable states exactly. This may accelerate reachability
+          analysis.  Refer  to  the paper by Moon et al, ICCAD98. The BDD
+          minimizing method can be chosen by using "set image_minimize_method "
+          [11]set. This option is incompatible with -g.
+
+   -F <dbg_file>
+          Write the debugger output to dbg_file.
+
+   -w <node_file> This option invokes the algorithm to generate an error trace
+          divided into fated and free segements. Fate represents the
+          inevitability and free is asserted when there is no inevitability.
+          This can be formulated as a two-player concurrent reachability game.
+          The two players are the environment and the system. The node_file is
+          given to specify the variables the are controlled by the system.
+
+   -W
+   This option represents the case that all input variables are controlled by
+          system.
+
+   -G
+   We proposed two algorithms to generate segmented counterexamples: general
+          and restricted. By default we use the restricted algorithm. We can
+          invoke the general algorithm with -G option. For more information,
+          please read the STTT'04 paper by Jin et al., "Fate and Free Will in
+          Error Traces"
+
+   <invarFile>
+          File containing invariants to be checked.
+
+   Related "set" options:
+
+   rch_simulate <#>
+   The set option can be used to set this flag rch_simulate to specify the
+   number of random vectors to be simulated. Default value for this number is
+   0.
+
+   ctl_change_bracket <yes/no>
+   Vl2mv automatically converts "[]" to "<>" in node names, therefore CTL
+   parser does the same thing. However, in some cases a user does not want to
+   change node names in CTL parsing. Then, use this set option by giving "no".
+   Default is "yes".
+
+   See also command : compute_reach
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
+
+References
+
+   1. file://localhost/projects/development/hsv/vis/common/doc/html/init_verifyCmd.html
+   2. file://localhost/projects/development/hsv/vis/common/doc/html/build_partition_maigsCmd.html
+   3. file://localhost/projects/development/hsv/vis/common/doc/html/flatten_hierarchyCmd.html
+   4. file://localhost/projects/development/hsv/vis/common/doc/html/build_partition_maigsCmd.html
+   5. file://localhost/projects/development/hsv/vis/common/doc/html/static_orderCmd.html
+   6. file://localhost/projects/development/hsv/vis/common/doc/html/build_partition_mddsCmd.html
+   7. file://localhost/projects/development/hsv/vis/common/doc/ctl/ctl/ctl.html
+   8. file://localhost/projects/development/hsv/vis/common/doc/html/flatten_hierarchyCmd.html
+   9. file://localhost/projects/development/hsv/vis/common/doc/html/print_hd_optionsCmd.html
+  10. file://localhost/projects/development/hsv/vis/common/doc/html/print_ardc_optionsCmd.html
+  11. file://localhost/projects/development/hsv/vis/common/doc/html/setCmd.html
Index: vis_dev/vis-2.3/share/help/check_invariant_satCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/check_invariant_satCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/check_invariant_satCmd.txt	(revision 14)
@@ -0,0 +1,34 @@
+
+  check_invariant_sat - Check invariant property using sat based unmounded
+  model checking
+     _________________________________________________________________
+
+   check_invariant_sat  [-h]  [-d] [-t <timeOutPeriod>] [-m <method>] [-v
+   <verbosity_level>] <inv_file>
+
+   Perform  SAT-based unbounded model checking on And-Inverter-Graph. The
+   command compute fixed point of AG using AX operation. AX is implemented
+   using AllSAT enumeration algorithm. Command options:
+
+   -d
+          Disable inclusion test on initial states.
+
+   -v <verbosity_level>
+          Specify verbosity level. This sets the amount of feedback on CPU
+          usage and code status.
+
+   -t <timeOutPeriod>
+          Specify the time out period (in seconds) after which the command
+          aborts. By default this option is set to infinity.
+
+   -m <method>
+          Specify the method for AllSAT algorithm.
+
+   -h
+          Print the command usage.
+
+   <inv_file>
+   File containing Invariant formulae to be checked.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/cnf_satCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/cnf_satCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/cnf_satCmd.txt	(revision 14)
@@ -0,0 +1,24 @@
+
+  cnf_sat - Perform SAT solving with CNF input
+     _________________________________________________________________
+
+   cnf_sat [-h] [-a <assgined_filename>] [-f <output_filename>] [-t <timeout>]
+   [-v <verbose>] [-b] <cnf_filename>
+
+   Perform SAT solving with CirCUs after reading CNF file
+
+   -b
+   If the given CNF has small number of variables and clause then the BDD is
+   built from the CNF clauses. If the monolithic BDD is built then we can
+   conclude SAT or UNSAT, otherwise the normal SAT algorithm is invoked.
+
+   -t <timeOutPeriod>
+   Specify the time out period (in seconds) after which the command aborts. By
+   default this option is set to infinity.
+
+   -f <output_filename>
+   Specify the output filename to save the satisfying assignments and the
+   statistics of SAT solving.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/collapse_childCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/collapse_childCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/collapse_childCmd.txt	(revision 14)
@@ -0,0 +1,41 @@
+
+  collapse_child - Collapses a parent (which is the current node) and a given
+  child node into the parent
+     _________________________________________________________________
+
+   collapse_child [-h] [-v] <child_instance_name>
+
+   This command collapses the given child into the current node. After this
+   command, the number of children of the current node will decrease by one.
+   The variables in the child node will be renamed to reflect their original
+   name.  For  example, if the current node is named "foo" and it has two
+   children, "bar1" and "bar2", then after
+
+   collapse_child bar1
+
+   is executed, the name of any variable occuring in bar1, say "xvar" will be
+   renamed "bar1$xvar". The new parent will have only the single child "bar2"
+   (which can be seen by typing "ls").
+
+   The user can use "cd" to traverse a hierarchy, go to a particular node. When
+   the  user uses "write_blif" from a particular node, vis will write the
+   circuit in this node out. However, the user might want to do synthesis on
+   the entire circuit in the hierarchy. In that case, the hierarchy can be
+   collapsed into a single node, by repeatedly using this command.
+
+   Examples:
+
+   collapse_child P1
+
+   Collapse P1 into the current node.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   -v
+   Verbose mode.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/comb_verifyCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/comb_verifyCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/comb_verifyCmd.txt	(revision 14)
@@ -0,0 +1,98 @@
+
+  comb_verify - verify the combinational equivalence of two flattened networks
+     _________________________________________________________________
+
+   comb_verify [-b] [-f <filename>] [-h] [-o <ordering method>] [-t <timeOut>]
+   [-1  <partition  method>]  [-2  <partition  method>]  [-i] <filename1>
+   [<filename2>]
+
+   This  command  verifies the combinational equivalence of two flattened
+   networks. In particular, any set of functions (the roots), defined over any
+   set of intermediate variables (the leaves), can be checked for equivalence
+   between the two networks. Roots and leaves are subsets of the nodes of a
+   network, with the restriction that the leaves should form a complete support
+   for the roots. The correspondence between the roots and the leaves in the
+   two networks is specified in a file given by the option -f . The default
+   option assumes that the roots are the combinational outputs and the leaves
+   are the combinational inputs.
+
+   When there is a pseudo input in the set of leaves, the range of values it
+   can  take  should  be  the  same  as that of the multi-valued variable
+   corresponding to it, for comb_verify to function correctly. This restriction
+   will be removed in future.
+
+   There are two ways to do combinational verification. In the first mode, two
+   BLIF-MV files are given as arguments to the command, e.g.
+
+  vis> comb_verify foo.mv bar.mv
+  
+
+   Verification is done for the flattened networks at the root nodes of the two
+   BLIF-MV hierarchies. In any error messages printed, "network1" refers to the
+   first file, and "network2" refers to the second. Both of these networks are
+   freed at the end of the command. This mode is totally independent from any
+   existing hierarchy previously read in. In the second mode, it is assumed
+   that a hierarchy has already been read in. Then, comb_verify can be called
+   with a single BLIF-MV file, and this will do the comparison between the
+   network  present  at  the  current  node  ("network1") and the network
+   corresponding  to  the  root  node  of  the  hierarchy  in the BLIF-MV
+   file("network2"). A typical sequence of commands is:
+
+  vis> read_blifmv foo.mv
+  vis> init_verify
+  vis> comb_verify bar.mv
+  
+
+   If a hierarchy has been read in but a flattened network does not exist at
+   the current node (flatten_hierarchy has not been invoked), the command does
+   nothing. If a network exists at the current node, but the variables haven't
+   been ordered, then the variables are ordered and a partition created. This
+   partition is freed at the end. A side-effect is that the variables are
+   ordered.  If  a  partition  exists,  then  it  is used if the vertices
+   corresponding to the roots specified are present in it, otherwise a new
+   partition is created with the current ordering. The partition created for
+   the new network read in is always freed at the end.
+
+   Command options:
+
+   -b
+          Specifies that the files are BLIF files and not BLIF-MV files.
+
+   -f <filename>
+          Provides the correspondence between the leaves and roots of network1
+          and network2. If this option is not used, it is assumed that the
+          correspondence is by name, except that two latch inputs match if
+          either they have the same name or the corresponding latch outputs
+          have the same name. Leaves are the combinational inputs, and roots
+          are the combinational outputs.
+
+   -h
+          Print the command usage.
+
+   -t <timeOut>
+          Time in seconds allowed to perform equivalence checking. The default
+          is infinity.
+
+   -o <ordering method>
+          Specifies the ordering method to be used for assigning a common
+          ordering to the leaves of network1 and network2. If this option is
+          not used, ordering is done using a default method. Currently, only
+          the default method is available.
+
+   -1 <partition method>
+          Specifies the partitioning method to be used for network1. Supported
+          methods  are  "total",  "partial", and "inout" (see the command
+          build_partition_mdds for more information). If this option is not
+          specified, then the default method "inout" is used.
+
+   -2 <partition method>
+          Specifies the partitioning method to be used for network2. Supported
+          methods  are  "total",  "partial", and "inout" (see the command
+          build_partition_mdds for more information). If this option is not
+          specified, then default method "inout" is used.
+
+   -i
+          Print Bdd statistics.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/compute_reachCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/compute_reachCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/compute_reachCmd.txt	(revision 14)
@@ -0,0 +1,154 @@
+
+  compute_reach - compute the set of reachable states of the FSM
+     _________________________________________________________________
+
+   compute_reach  [-d  <depthValue>]  [-f]  [-g  <file>]  [-h]  [-i]  [-r
+   <thresholdValue>] [-s <printStep>] [-t <timeOut>] [-v #] [-A #] [-D] [-F]
+
+   Compute the set of reachable states of the FSM associated with the flattened
+   network. The command build_partition_mdds (or init_verify) must have already
+   been invoked on the flattened network, before this command is called. On
+   subsequent  calls  to  compute_reach, the reachable states will not be
+   recomputed, but statistics can be printed using -v. To force recomputation
+   with a different set of options, for example a depth value with -d, use -F
+   option.
+
+   The method used for image computation is displayed by the option -v 1. To
+   change the image computation method, use the command set image_method, and
+   then  start again with the command flatten_hierarchy. The reachability
+   computation makes extensive use of image computation. There are several
+   user-settable options that can be used to affect the performance of image
+   computation. See the documentation for the set command for these options.
+
+   Command options:
+
+   -d <depthValue>
+          Perform  reachability  for  depthValue steps only - this option
+          specifies the number of unit operations (image computations) to be
+          performed in the reachability computation. The depthValue used in
+          successive calls proceeds from the previous state. For example,
+          compute_reach -d 3; compute_reach -d 4; will perform 7 steps of
+          reachability in total, the second call to compute_reach proceeding
+          from the result of the first. While using only -A 0 option (default),
+          this  additionally corresponds to the depth in the state graph,
+          starting from the initial state. For the -A 1 option, the above may
+          not be true. This option is not compatible with -A 2.
+
+   -f
+          Store the set of new states (onion rings) reached at each step of
+          reachability.  If  this flag is specified, then the computation
+          proceeds with the previously set of onion rings, if any exist (not
+          any prior computation without onion rings). This option is likely to
+          use more memory during reachability analysis. This is not compatible
+          with -A 2.
+
+   -g <hints_file>
+          Use guided search. The file hints_file contains a series of hints. A
+          hint is a formula that does not contain any temporal operators, so
+          hints_file has the same syntax as a file of invariants used for
+          check_invariant. The hints are used in the order given to change the
+          transition relation. The transition relation is conjoined with the
+          hint to yield an underapproximation of the transition relation. If
+          the hints are cleverly chosen, this may speed up the computation
+          considerably, because a search with the changed transition relation
+          may be much simpler than one with the original transition relation,
+          and results obtained can be reused, so that we may never have to do
+          an expensive search with the original relation. See also: Ravi and
+          Somenzi, Hints to accelerate symbolic traversal. CHARME'99; Bloem,
+          Ravi, and Somenzi, Efficient Decision Procedures for Model Checking
+          of Linear Time Logic Properties, CAV'99; Bloem, Ravi, and Somenzi,
+          Symbolic Guided Search for CTL Model Checking, DAC'00. Not allowed
+          with -A 2 or -i, and will only work with iwls95 or monolithic image
+          methods. The description of some options for guided search can be
+          found in the help page for print_guided_search_options.
+
+   -h
+          Print the command usage.
+
+   -i
+          This option is useful when it's not possible to build the complete
+          transition relation. Using this option, the transition relation is
+          rebuilt at every itereation using the current reached set of states
+          as  the care set. This option is not compatible with the -A > 0
+          options, the -D option and the -g option.
+
+   -r <thresholdValue>
+          Dynamic reordering (with method sift) is invoked once when the size
+          of the reachable state set reaches the threshold value.
+
+   -s <printStep>
+          At every printStep of the reachability computation, print the total
+          number  of  states  reached  thus  far, and the size of the MDD
+          representing this set.
+
+   -t <timeOut>
+          Time  allowed  to perform reachability (in seconds). Default is
+          infinity.
+
+   -v #
+          Print debug information.
+          0: (default) Nothing is printed out.
+
+          1: Print a summary of reachability analysis and some information
+          about  the  image  computation  method (see print_img_info) and
+          summarizes results of reachability:
+
+          FSM depth: the farthest reachable state
+          reachable states: the number of reachable states
+          MDD size: the size of the MDD representing the reachable states
+          analysis time: number of CPU seconds taken to compute the reachable
+          states
+
+          2: Prints the detailed information about reachability analysis. For
+          each printStep, it prints the MDD size of the reachable state set and
+          the number of states in the set.
+
+   -A #
+          This  option  allows  specification of approximate reachability
+          computation.
+
+          0:  (default) Breadth First Search. No approximate reachability
+          computation.
+
+          1: High Density Reachability Analysis (HD). Computes reachable states
+          in a manner that keeps BDD sizes under control. May be faster than
+          BFS in some cases. For larger circuits, this option should compute
+          more reachable states. For help on controlling options for HD, look
+          up help on the command: print_hd_options [1]print_hd_options. Refer
+          to Ravi and Somenzi, ICCAD95. This option is available only when VIS
+          is linked with the CUDD package.
+
+          2.   Approximate   Reachability   Don't  Cares(ARDC).  Computes
+          over-approximate reachable states. For help on controlling options
+          for  ARDC,  look  up  help  on  the command: print_ardc_options
+          [2]print_ardc_options. Refer Moon's paper, ICCAD98 and 2 papers by
+          Cho et al, December TCAD96: one is for State Space Decomposition and
+          the other is for Approximate FSM Traversal. The options -d, -g and -f
+          are not compatible with this option.
+
+   -D
+          First compute an overapproximation to the reachable states. Minimize
+          transition relation using this approximation, and then compute the
+          set of reachable states exactly. This may accelerate reachability
+          analysis.  Refer  to  the paper by Moon et al, ICCAD98. The BDD
+          minimizing method can be chosen by using "set image_minimize_method "
+          [3]set. This option is incompatible with -i.
+
+   -F
+          Force to recompute reachable states.
+
+   Related "set" options:
+
+   rch_simulate <#>
+          The set option can be used to set this flag rch_simulate to specify
+          the number of random vectors to be simulated. Default value for this
+          number is 0.
+            __________________________________________________________
+
+          Last updated on 20100410 00h02
+
+References
+
+   1. file://localhost/projects/development/hsv/vis/common/doc/html/print_hd_optionsCmd.html
+   2. file://localhost/projects/development/hsv/vis/common/doc/html/print_ardc_optionsCmd.html
+   3. file://localhost/projects/development/hsv/vis/common/doc/html/setCmd.html
Index: vis_dev/vis-2.3/share/help/decompose_childCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/decompose_childCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/decompose_childCmd.txt	(revision 14)
@@ -0,0 +1,54 @@
+
+  decompose_child - Partitions Node components into child nodes.
+     _________________________________________________________________
+
+   decompose_child  -n  <groupname>  [-f  <filename>] [-c] [-v] [-t] [-l]
+   [<components>]
+
+   This command partitions the current Node into several new children nodes
+   according to user-specified groups. The user may specify several groups by
+   name [-n] sequentially on the command line. Within each group a list of
+   components (either variables or child nodes) can be placed. The flags [-c]
+   [-v] toggle whether element names are interpreted as child instances or
+   variables (default is instances [-c]). Element names can be loaded from a
+   file as well using the [-f] flag.
+
+   By specifying a variable to be grouped, any object (e.g., Table, Latch,
+   Child) that PRODUCES that variable is included in the newly created child
+   node for that group.
+
+   Command options:
+
+   -n <groupname>
+          Define new group
+
+   -f <filename>
+          Load names from file
+
+   -c
+          Interpret names that follow as child instances to group
+
+   -v
+   Interpret names that follow as variables
+
+   -l
+   Include all latch output nodes (and therefore latches) in group
+
+   -t
+   Include all combinational tables in group. Examples:
+
+   decompose_child -n c1 -v G1 G2 -n c2 IA IB
+
+   Place variables G1 and G2 into a new child node c1 and child nodes IA and IB
+   into a new child node c2.
+
+   Example:
+
+   decompose_child -n ckt_inst child1 -f myinstances -v var1 -n latch_inst -l
+
+   This groups the subckts child1 and those listed in the file myinstances, as
+   well as the variable var1 into a subckt called 'ckt_inst'. It also groups
+   all the latches into a subckt called 'latch_inst'.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/dynamic_var_orderingCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/dynamic_var_orderingCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/dynamic_var_orderingCmd.txt	(revision 14)
@@ -0,0 +1,126 @@
+
+  dynamic_var_ordering - control the application of dynamic variable ordering
+     _________________________________________________________________
+
+   dynamic_var_ordering [-d] [-e <method>] [-f <method>] [-h]
+
+   Control  the application of dynamic variable ordering to the flattened
+   network. Dynamic ordering is a technique to reorder the MDD variables to
+   reduce the size of the existing MDDs. When no options are specified, the
+   current status of dynamic ordering is displayed. At most one of the options
+   -e, -f, and -d should be specified. The commands flatten_hierarchy and
+   static_order must be invoked before this command.
+
+   Dynamic ordering may be time consuming, but can often reduce the size of the
+   MDDs dramatically. The good points to invoke dynamic ordering explicitly
+   (using  the -f option) are after the commands build_partition_mdds and
+   print_img_info. If dynamic ordering finds a good ordering, then you may wish
+   to save this ordering (using write_order) and reuse it (using static_order
+   -s) in the future. A common sequence used to get a good ordering is the
+   following:
+
+  init_verify
+  print_img_info
+  dynamic_var_ordering -f sift
+  write_order 
+  flatten_hierarchy
+  static_order -s input_and_latch -f 
+  build_partition_mdds
+  print_img_info
+  dynamic_var_ordering -f sift
+  
+
+   For many large examples, there is no single best variable order, or that
+   order is hard to find. For example, the best ordering during partitioning of
+   the network may be different from the best ordering during a model check. In
+   that case you can use automatic reordering, using the -e option. This will
+   trigger reordering whenever the total size of the MDD increases by a certain
+   factor. Often, the init command is replaced by the following sequence:
+  flatten_hierarchy 
+  static_order
+  dynamic_var_ordering -e sift
+  build_partition_mdds
+  
+
+   Command options:
+
+   -d
+          Disable dynamic ordering from triggering automatically.
+
+   -e <method>
+          Enable dynamic ordering to trigger automatically whenever a certain
+          threshold on the overall MDD size is reached. "Method" must be one of
+          the following:
+
+          window: Permutes the variables within windows of three adjacent
+          variables so as to minimize the overall MDD size. This process is
+          repeated until no more reduction in size occurs.
+
+          sift: Moves each variable throughout the order to find an optimal
+          position for that variable (assuming all other variables are fixed).
+          This generally achieves greater size reductions than the window
+          method, but is slower.
+
+          The following methods are only available if VIS has been linked with
+          the Bdd package from the University of Colorado (cuBdd).
+
+          random: Pairs of variables are randomly chosen, and swapped in the
+          order.  The  swap is performed by a series of swaps of adjacent
+          variables. The best order among those obtained by the series of swaps
+          is retained. The number of pairs chosen for swapping equals the
+          number of variables in the diagram.
+
+          random_pivot: Same as random, but the two variables are chosen so
+          that the first is above the variable with the largest number of
+          nodes, and the second is below that variable. In case there are
+          several variables tied for the maximum number of nodes, the one
+          closest to the root is used.
+
+          sift_converge:  The  sift  method  is iterated until no further
+          improvement is obtained.
+
+          symmetry_sift: This method is an implementation of symmetric sifting.
+          It is similar to sifting, with one addition: Variables that become
+          adjacent  during  sifting  are tested for symmetry. If they are
+          symmetric, they are linked in a group. Sifting then continues with a
+          group being moved, instead of a single variable.
+
+          symmetry_sift_converge: The symmetry_sift method is iterated until no
+          further improvement is obtained.
+
+          window{2,3,4}: Permutes the variables within windows of n adjacent
+          variables, where "n" can be either 2, 3 or 4, so as to minimize the
+          overall MDD size.
+
+          window{2,3,4}_converge: The window{2,3,4} method is iterated until no
+          further improvement is obtained.
+
+          group_sift: This method is similar to symmetry_sift, but uses more
+          general criteria to create groups.
+
+          group_sift_converge: The group_sift method is iterated until no
+          further improvement is obtained.
+
+          lazy_sift: This method is similar to group_sift, but the creation of
+          groups takes into account the pairing of present and next state
+          variables.
+
+          annealing: This method is an implementation of simulated annealing
+          for variable ordering. This method is potentially very slow.
+
+          genetic: This method is an implementation of a genetic algorithm for
+          variable ordering. This method is potentially very slow.
+
+   -f <method>
+          Force dynamic ordering to be invoked immediately. The values for
+          method are the same as in option -e.
+
+   -h
+          Print the command usage.
+
+   -v <#>
+          Verbosity level. Default is 0. For values greater than 0, statistics
+          pertaining to reordering will be printed whenever reordering occurs.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/echoCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/echoCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/echoCmd.txt	(revision 14)
@@ -0,0 +1,15 @@
+
+  echo - merely echo the arguments
+     _________________________________________________________________
+
+   echo [-h] <args>
+
+   Echoes the arguments to standard output.
+
+   Command options:
+
+   -h
+          Print the command usage.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/flatten_hierarchyCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/flatten_hierarchyCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/flatten_hierarchyCmd.txt	(revision 14)
@@ -0,0 +1,87 @@
+
+  flatten_hierarchy - create a flattened network
+     _________________________________________________________________
+
+   flatten_hierarchy [-a <file>] [-b] [-h] [-s] [-v #]
+
+   Creates a flattened network from a hierarchical description. The flattened
+   network  encompasses everything from the current node of the hierarchy
+   (reached by the command cd), down to and including the leaves. It creates a
+   view  with  the  hierarchy  removed, but retains the multi-level logic
+   structure. The resulting flattened network is stored with the current node.
+   Every table in the flattened network is checked whether it is completely
+   specified and deterministic. This is the starting point for verification
+   related commands.
+
+   A limited form of abstraction can be done by providing a list of variables
+   to treat as primary inputs. See the information under <file> below.
+
+   The verification part of VIS requires the functions specified by the BLIF-MV
+   tables to be completely specified and deterministic. These conditions are
+   checked  during  the  flattening  process; if a table is found that is
+   incompletely specified or is nondeterministic, then an error message is
+   written and a flattened network is not created. The exception to this rule
+   is tables specifying "pseudo inputs"; these are tables with no inputs, and a
+   single output that can take more than one value. Such tables are generated
+   by vl2mv to model the "$ND" construct in Verilog.
+
+   If  this  command  is invoked a second time from the same point in the
+   hierarchy, the previous network is deleted and a new one is created. This is
+   the  tactic to follow if you want to change some aspect of the current
+   network, such as MDD variable ordering or image_method.
+
+   Command options:
+
+   -a <file>
+          A file containing names of variables, used to specify which variables
+          to abstract. The name of a variable is the full hierarchical path
+          name, starting from just after the current hierarchy node (i.e., if
+          the current node is foo, and you want to refer to variable x in foo,
+          then just use x). A variable should appear at most once in the file.
+          Each variable name should appear at the beginning of a new line, with
+          no white space preceding it. The end of a variable name is marked by
+          white space, and any other text on the rest of the line is ignored.
+          Any line starting with "#" or white space is ignored. A sample file
+          is shown here.
+
+  # variables to abstract to model check liveness property
+  choosing0 
+  p0.pc     
+  
+
+          For each variable x appearing in the file, a new primary input node
+          named x$ABS is created to drive all the nodes that were previously
+          driven by x. Hence, the node x will not have any fanouts; however, x
+          and its transitive fanins will remain in the network.
+
+          Abstracting a net effectively allows it to take any value in its
+          range, at every clock cycle. This mechanism can be used to perform
+          manual abstractions. The variables to abstract should not affect the
+          correctness of the property being checked. This usually simplifies
+          the network, and permits some verification tasks to complete that
+          would not otherwise. Note, however, that by increasing the behavior
+          of the system, false negatives are possible when checking universal
+          properties,  and  false  positives  are  possible when checking
+          existential properties.
+
+          A convenient way of generating the hierarchical variable names is by
+          using the write_order command. Note that abstracting next state
+          variables has no effect.
+
+   -b
+          This option has no effect any longer.
+
+   -h
+          Print the command usage.
+
+   -s
+          Do not perform a sweep.
+
+   -v #
+          Print debug information.
+          0: (default) Nothing is printed out.
+
+          >= 2: Prints the variables read from the input file.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/helpCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/helpCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/helpCmd.txt	(revision 14)
@@ -0,0 +1,21 @@
+
+  help - provide on-line information on commands
+     _________________________________________________________________
+
+   help [-a] [-h] [<command>]
+
+   Given  no arguments, "help" prints a list of all commands known to the
+   command interpreter. If a command name is given, detailed information for
+   that command will be provided.
+
+   Command options:
+
+   -a
+          Provides a list of all internal commands, which by convention begin
+          with an underscore.
+
+   -h
+          Print the command usage.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/historyCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/historyCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/historyCmd.txt	(revision 14)
@@ -0,0 +1,70 @@
+
+  history - list previous commands and their event numbers
+     _________________________________________________________________
+
+   history [-h] [<num>]
+
+   Lists previous commands and their event numbers. This is a UNIX-like history
+   mechanism inside the VIS shell.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   <num>
+          Lists the last <num> events. Lists the last 30 events if <num> is not
+          specified.
+
+   History Substitution:
+
+   The history substitution mechanism is a simpler version of the csh history
+   substitution mechanism. It enables you to reuse words from previously typed
+   commands.
+
+   The default history substitution character is the `%' (`!' is default for
+   shell  escapes, and `#' marks the beginning of a comment). This can be
+   changed using the "set" command. In this description '%' is used as the
+   history_char. The `%' can appear anywhere in a line. A line containing a
+   history substitution is echoed to the screen after the substitution takes
+   place. `%' can be preceded by a `\' in order to escape the substitution, for
+   example, to enter a `%' into an alias or to set the prompt.
+
+   Each valid line typed at the prompt is saved. If the "history" variable is
+   set (see help page for "set"), each line is also echoed to the history file.
+   You can use the "history" command to list the previously typed commands.
+
+   Substitutions:
+
+   At any point in a line these history substitutions are available.
+
+   %:0
+          Initial word of last command.
+
+   %:n
+          n-th argument of last command.
+
+   %$
+          Last argument of last command.
+
+   %*
+          All but initial word of last command.
+
+   %%
+          Last command.
+
+   %stuf
+          Last command beginning with "stuf".
+
+   %n
+          Repeat the n-th command.
+
+   %-n
+          Repeat the n-th previous command.
+
+   ^old^new
+          Replace "old" with "new" in previous command. Trailing spaces are
+          significant during substitution. Initial spaces are not significant.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/incremental_ctl_verificationCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/incremental_ctl_verificationCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/incremental_ctl_verificationCmd.txt	(revision 14)
@@ -0,0 +1,163 @@
+
+  incremental_ctl_verification - Verify a set of CTL formulas by means of an
+  incremental model checking algorithm.
+     _________________________________________________________________
+
+   incremental_ctl_verification  [-D  <number>] [-e] [-h] [-n] \ [-s] [-t
+   <seconds>] [-v <number>] [-V <number>] [-x] <ctlfile>
+
+   Like  model_check,  incremental_ctl_verification verifies a set of CTL
+   formulas. It uses a system of abstraction and incremental refinement that
+   works  for  all  of  (fair)CTL,  using over and underapproximations as
+   appropriate. See [1,2] for details.
+
+   Incremental_ctl_verification (also known as Abs or Trasgo) works especially
+   well on large systems on which mc is too slow or runs out of memory. Unlike
+   amc, it can handle full CTL, not just the universal or existential subsets
+   of it. Also, fairness is supported with this command, although it tends to
+   be inefficient. Support for the mu-calculus is not yet implemented.
+
+   Before using incremental_ctl_verification, a flattened hierarchy should be
+   present.  See  `help  init`.  Using dynamic variable reordering may be
+   beneficial on large systems. See `help dynamic_var_ordering`.
+
+   Fairness constraints can be applied using `read_fairness', as with mc. When
+   using incremental verification with fairness, there is no check for unfair
+   initial states. Please be aware that if there are no fair initial states,
+   all formulas starting with "A" will be trivially true. Mc will tell you
+   whether you have fair initial states.
+
+   A typical use would be
+   incremental_ctl_verification -D2 <ctl_file>
+
+   For every formula, incremental verification will report whether it is valid
+   or invalid, or it returns an inconclusive result. A formula is valid iff it
+   holds for all initial states. An error trace is not provided. For the people
+   who are used to mc: The -r option is not supported, incremental verification
+   always reduces the fsm with respect to individual formulas. The -c option is
+   not supported either. There is no sharing of subformulas between different
+   formulas.
+
+   Command options:
+
+   -D <number>
+          Specify extent to which don't cares are used to simplify the MDDs.
+
+          + 0: No Don't Cares used.
+          + 1: Use reachability information to compute the don't-care set.
+            Reachability is performed by formula. This is different from mc,
+            where reachability is performed only once.
+          + 2:  Use reachability information, and minimize the transition
+            relation  with  respect  to  the  `frontier  set'  (aggresive
+            minimization).
+
+          The equivalent of mc -D3 is not implemented.
+
+   -e
+          Compute the set of fair states (those satisfying the formula EGfair
+          TRUE) before the verification process and use the result as care set.
+          In  certain  cases this will speed up computation when fairness
+          constraints are present. In other cases it will slow it down.
+
+   -h
+          Print the command usage.
+
+   -n
+          Try to prove the negation of every formula. In some cases it may be
+          easier to prove the negation of a formula than the formula itself.
+          For systems with only one initial state, a formula is true iff its
+          negation is false. Note that for systems with multiple initial states
+          a formula and its negation can both be false.
+
+   -s
+          Print a summary of statistics after the verification.
+
+   -t <secs>
+          Time in seconds allowed to spend in the verification. The default is
+          infinity.
+
+   -v <number>
+          Specify verbosity level. Use 0 for no feedback (default), 1 for more
+          and  2  for  maximum  feedback.  This option can not be used in
+          conjunction with -V.
+
+   -V <number>
+          Mask specifying type of information to be printed out while verifying
+          the formulas. This allows for a finer control than -v. -V and -v
+          cannot be used simultaneously. The mask is given as a binary number,
+          by taking the logical or of the following binary values. One does not
+          have to convert these numbers to decimal.
+
+          1 number of primary inputs and flip-flops
+
+          10 labeled operational graph of the formulas
+
+          100 cpu-time for the computation in each vertex
+
+          1000 cubes of the function sat for each vertex
+
+          10000 cubes of the function goalSet for each vertex
+
+          100000 vertex data structure contents after evaluation
+
+          1000000 cubes in the care set for every evaluation
+
+          10000000 size of care set for every evaluation
+
+          100000000 number of states that satisfy every sub-formula
+
+          1000000000 number of overall reachable states
+
+          10000000000 cubes for every iteration of a fixed point
+
+          100000000000 size of the BDD in each iteration in a fix-point
+
+          1000000000000 labeled operational graph in dot format
+
+          10000000000000 number of envelope states
+
+          100000000000000 number of states to be refined
+
+          1000000000000000 size of the refinement operands
+
+          10000000000000000 cubes of the refinement operands
+
+          100000000000000000 Number of latches before and after simplification
+
+          1000000000000000000   report   partial  progress  (i.e.  reach,
+          EG(true),...)
+
+          10000000000000000000 Begin/End refinement process
+
+          100000000000000000000 Size of goal set
+
+          1000000000000000000000 cubes of the goal set
+
+          10000000000000000000000 Contents of vertex after refinement
+
+   -x
+          Perform the verification exactly. No approximation is done.
+
+   <ctlfile>
+          File containing the CTL formulas to be verified.
+
+   Related "set" options:
+
+   ctl_change_bracket <yes/no>
+          Vl2mv automatically converts "[]" to "<>" in node names, therefore
+          CTL parser does the same thing. However, in some cases a user does
+          not want to change node names in CTL parsing. Then, use this set
+          option by giving "no". Default is "yes".
+
+   See also commands : model_check, incremental_ctl_verification
+
+   1.  A.  Pardo  and  G.  Hachtel.  Automatic abstraction techniques for
+   propositional mu-calculus model checking. In 9th Conference on Computer
+   Aided Verification (CAV'97). Springer-Verlag. Pages 12-23, 1997.
+
+   2.  A.  Pardo and G. Hachtel. Incremental CTL model checking using BDD
+   subsetting. In 35th Design Automation Conference (DAC'98). pages 457-462,
+   1998.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/init_verifyCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/init_verifyCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/init_verifyCmd.txt	(revision 14)
@@ -0,0 +1,28 @@
+
+  init_verify - create and initialize a flattened network for verification
+     _________________________________________________________________
+
+   init_verify [-b] [-h]
+
+   This command initializes the system for verification, and is equivalent to
+   the command sequence flatten_hierarchy; static_order; build_partition_mdds.
+   If a command returns an error condition, then the sequence is aborted. After
+   init_verify has successfully executed, various commands can be invoked, like
+   model_check, compute_reach, simulate, print_network_stats, and seq_verify.
+
+   Please note that init_verify does not enable dynamic variable reordering.
+   Sometimes, though, this is needed to complete building the partitions, and
+   one has to initialize the verification by hand. Similarly, it may be wise to
+   turn on dynamic variable reordering after init, so that further commands
+   complete more easily. See the help page for dynamic_var_ordering.
+
+   Command options:
+
+   -b
+          This option has no effect any longer.
+
+   -h
+          Print the command usage.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/iterative_model_checkCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/iterative_model_checkCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/iterative_model_checkCmd.txt	(revision 14)
@@ -0,0 +1,94 @@
+
+  iterative_model_check - Perform CTL model checking on an abstracted system
+  with automatic refinement algorithm.
+     _________________________________________________________________
+
+   iterative_model_check [-h] [-x] [-t <seconds>] [-v <number>]\ [-D <number>]
+   [-r <number>] [-i <number>] \ [-p <number>] [-g <number>] <ctlfile>
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   -x
+          Perform the verification exactly. No approximation is done.
+
+   -t <secs>
+          Time in seconds allowed for verification. The default is no limit.
+
+   -v <number>
+          Specify verbosity level. Use 0 for no feedback (default), 1 for more,
+          and 2 for maximum feedback.
+
+   -D <number>
+          Specify extent to which don't cares are used to simplify the MDDs.
+
+          + 0: No don't cares used. This is the default.
+          + 1: Use reachability information to compute the don't-care set.
+          + 2:  Use reachability information, and minimize the transition
+            relation  with  respect  to  the  `frontier  set'  (aggresive
+            minimization).
+          + 3: Use approximate reachability information.
+
+   -r <number>
+          Specify refinement method.
+
+          + 0:  Static  scheduling  by name sorting. Fast, easy, but less
+            accurate.
+          + 1: Static scheduling by latch affinity. Slow, but more accurate.
+            This is the default.
+
+   -i <number>
+          The number of state variables to be added for exact computation at
+          each iteration. The default is 4.
+
+   -l <number>
+          Type of lower-bound approximation method.
+
+          + 0: Take a subset of each transition sub-relation by BDD subsetting.
+          + 1: Take a subset by universal quantification. This is the default.
+
+   -p <number>
+          Type  of partition method. If 'build_partition_mdds' is already
+          invoked,  this  option  is ignored. Notice that some next state
+          functions might not be available after iterative_model_checking
+          command is performed because of this option.
+
+          + 0: Build all next state functions. Same as 'build_partition_mdds'.
+            This is the default.
+          + 1: Build the next state functions related to the formulas. Build
+            all next state functions that are necessary to prove all formulas.
+          + 2: Build the next state functions incrementally. None of next state
+            functions are removed.
+
+   -g <number>
+          Type of operational graph.
+
+          + 0: Negative Operational Graph. Good to prove a formula true.
+          + 1: Positive Operational Graph. Good to prove a formula false.
+          + 2: Mixed Operational Graph. Good to prove any formula, but it may
+            be slower. This is the default.
+
+   <ctlfile>
+          File containing the CTL formulas to be verified.
+
+   Related "set" options:
+
+   ctl_change_bracket <yes/no>
+          Vl2mv automatically converts "[]" to "<>" in node names, therefore
+          CTL parser does the same thing. However, in some cases a user does
+          not want to change node names in CTL parsing. Then, use this set
+          option by giving "no". Default is "yes".
+
+   See also commands : model_check, incremental_ctl_verification
+
+   1.  Jae-Young  Jang,  In-Ho  Moon,  and  Gary  D.  Hachtel.  Iterative
+   Abstraction-based CTL Model Checking. Design, Automation and Test in Europe
+   (DATE), 2000
+
+   2. Jae-Young Jang. Iterative Abstraction-based CTL Model Checking. Ph. D.
+   Thesis. University of Colorado, 1999.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/lang_emptyCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/lang_emptyCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/lang_emptyCmd.txt	(revision 14)
@@ -0,0 +1,150 @@
+
+  lang_empty - perform language emptiness check on a flattened network
+     _________________________________________________________________
+
+   lang_empty  [-b]  [-d  <dbg_level>] [-f <dbg_file>] [-h] [-i] [-s] [-t
+   <time_out_period>] [-v <verbosity_level>] [-A <le_method>] [-D <dc_level>]
+   [-S <schedule>] [-L <lockstep_mode>]
+
+   Performs language emptiness check on a flattened network. The language is
+   not empty when there is a fair path starting at an initial state. Before
+   calling this command, the user should have initialized the design by calling
+   the command [1]init_verify.
+
+   A  fairness  constraint can be read in by calling the [2]read_fairness
+   command; if none is specified, all paths are taken to be fair.
+
+   The system is reduced automatically with respect to the set of fairness
+   constraints.  If  the  language  is not empty, a proof of this fact is
+   generated. A proof is a fair path starting at an initial state. This is
+   represented by a finite sequence of states starting at an initial state (the
+   stem) leading to a fair cycle, i.e., a cycle on which there lies a state
+   from each fairness condition.
+
+   Command options:
+
+   -b
+          Use backward analysis when performing debugging; the default is to
+          use forward analysis. This should be tried when the debugger spends a
+          large amount of time when creating a path to a fair cycle.
+
+   -d <dbg_level>
+          Specify whether to demonstrate a proof of the language non-emptiness
+
+          dbg_level must be one of the following:
+
+          0 : No debugging performed. This is the default.
+
+          1 : Generate a path to a fair cycle.
+
+   -f <dbg_file>
+          Write the debugger output to dbg_file.
+
+   -h
+          Print the command usage.
+
+   -m
+          Pipe debugger output through the UNIX utility more.
+
+   -i
+          Print  input  values  causing transitions between states during
+          debugging. Both primary and pseudo inputs are printed.
+
+   -s
+          Print debug output in the format accepted by the [3]simulate command.
+
+   -t <timeOutPeriod>
+          Specify the time out period (in seconds) after which the command
+          aborts. By default this option is set to infinity.
+
+   -v <verbosity_level>
+          Specify verbosity level. This sets the amount of feedback on CPU
+          usage and code status.
+
+          verbosity_level must be one of the following:
+
+          0 : No feedback provided. This is the default.
+
+          1 : Feedback on code location.
+
+          2 : Feedback on code location and CPU usage.
+
+   -A <le_method>
+          Specify whether the compositional SCC analysis algorithm, Divide and
+          Compose (DnC), is enabled for language emptiness checking. The DnC
+          algorithm first enumerates fair SCCs in an over-approximated abstract
+          model,  and then successively refines them in the more concrete
+          models. Since non-fair SCCs can be ignored in the more concrete
+          models, a potentially large part of the state space are pruned away
+          early on when the computations are cheap.
+
+          le_method must be one of the following:
+
+          0 : no use of Divide and Compose (Default).
+
+          1 : use Divide and Compose.
+
+   -D <dc_level>
+          Specify extent to which don't cares are used to simplify MDDs. Don't
+          cares are minterms on which the value taken by functions does not
+          affect the computation; potentially, these minterms can be used to
+          simplify MDDs and reduce time taken to perform MDD computations.
+
+          dc_level must be one of the following:
+
+          0 : No don't cares are used.
+
+          1 : Use unreachable states as don't cares. This is the default.
+
+   -S <schedule>
+          Specify schedule for GSH algorithm, which generalizes the Emerson-Lei
+          algorithm and is used to compute greatest fixpoints. The choice of
+          schedule  affects the sequence in which EX and EU operators are
+          applied. It makes a difference only when fairness constraints are
+          specified.
+          <schedule> must be one of the following:
+
+          EL : EU and EX operators strictly alternate. This is the default.
+
+          EL1 : EX is applied once for every application of all EUs.
+
+          EL2 : EX is applied repeatedly after each application of all EUs.
+
+          budget : a hybrid of EL and EL2.
+
+          random : enabled operators are applied in (pseudo-)random order.
+
+          off : GSH is disabled, and the old algorithm is used instead. The old
+          algorithm  uses  the  EL  , but the termination checks are less
+          sophisticated than in GSH.
+
+   -F
+          Use forward analysis in the computation of the greatest fixpoint.
+          This option is incompatible with -d 1 or higher and can only be used
+          with -D 1.
+
+   -L <lockstep_mode>
+          Use the lockstep algorithm, which is based on fair SCC enumeration.
+          <lockstep_mode> must be one of the following:
+
+          off : Lockstep is disabled. This is the default. Language emptiness
+          is checked by computing a hull of the fair SCCs.
+
+          on : Lockstep is enabled.
+
+          all : Lockstep is enabled; all fair SCCs are enumerated instead of
+          terminating as soon as one is found. This can be used to study the
+          SCCs of a graph, but it is slower than the default option.
+
+          n : (n is a positive integer). Lockstep is enabled and up to n fair
+          SCCs are enumerated. This is less expensive than all , but still less
+          efficient than on , even when n = 1 .
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
+
+References
+
+   1. file://localhost/projects/development/hsv/vis/common/doc/html/init_verifyCmd.html
+   2. file://localhost/projects/development/hsv/vis/common/doc/html/read_fairnessCmd.html
+   3. file://localhost/projects/development/hsv/vis/common/doc/html/simulateCmd.html
Index: vis_dev/vis-2.3/share/help/lsCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/lsCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/lsCmd.txt	(revision 14)
@@ -0,0 +1,18 @@
+
+  ls - list all the child nodes at the current node
+     _________________________________________________________________
+
+   ls [-h] [-R]
+
+   Lists all the child nodes at the current node.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   -R
+          Call ls recursively all the way down to leaves.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/ltl2snfCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/ltl2snfCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/ltl2snfCmd.txt	(revision 14)
@@ -0,0 +1,19 @@
+
+  ltl2snf - Trnalate LTL formula into Separated Normal Form.
+     _________________________________________________________________
+
+   ltl2snf [-h] <file_name>
+
+   Command options:
+
+   -f <ltl_file>
+          The input file containing LTL formulae.
+
+   -n
+          Negate the formulae.
+
+   -h
+          Print the command usage.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/ltl_model_checkCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/ltl_model_checkCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/ltl_model_checkCmd.txt	(revision 14)
@@ -0,0 +1,215 @@
+
+  ltl_model_check - perform LTL model checking on a flattened network
+     _________________________________________________________________
+
+   ltl_model_check  [-a  <ltl2aut_algorithm>]  [-b]  [-d <dbg_level>] [-f
+   <dbg_file>] [-h] [-i] [-m] [-s] [-t <time_out_period>][-v <verbosity_level>]
+   [-A <le_method>] [-D <dc_level>] [-L <lockstep_mode>] [-S <schedule>] [-F]
+   [-X] [-Y] [-M] <ltl_file>
+
+   Performs LTL model checking on a flattened network. Before calling this
+   command, the user should have initialized the design by calling the command
+   [1]init_verify. Regardless of the options, no 'false positives' or 'false
+   negatives' will occur: the result is correct for the given circuit.
+
+   Properties to be verified should be provided as LTL formulae in the file
+   ltl_file. Note that the support of any wire referred to in a formula should
+   consist only of latches. For the precise syntax of LTL formulas, see the
+   [2]VIS CTL and LTL syntax manual.
+
+   A  formula passes iff it is true for all initial states of the system.
+   Therefore, in the presence of multiple initial states, if a formula fails,
+   the negation of the formula may also fail.
+
+   If  a  formula does not pass, a (potentially partial) proof of failure
+   (referred to as a debug trace) is demonstrated. Fair paths are represented
+   by a finite sequence of states (the stem) leading to a fair cycle, i.e. a
+   cycle  on which there is a state from each fairness condition. Whether
+   demostrate the proof or not can be specified (see option -d).
+
+   Command options:
+
+   -a <ltl2aut_algorithm>
+          Specify  the  algorithm used in LTL formula -> Buechi automaton
+          translation.
+
+          ltl2aut_algorithm must be one of the following:
+
+          0: GPVW.
+
+          1: GPVW+.
+
+          2: LTL2AUT.
+
+          3: WRING (default).
+
+   -b
+          Use boolean minimization during the LTL to Automaton translation.
+
+   -d <dbg_level>
+          Specify whether to demonstrate a counter-example when the system
+          fails a formula being checked.
+
+          dbg_level must be one of the following:
+
+          0: No debugging performed. dbg_level=0 is the default.
+
+          1: Generate a counter-example (a path to a fair cycle).
+
+   -f <dbg_file>
+          Write the debugger output to dbg_file.
+
+   -h
+          Print the command usage.
+
+   -i
+          Print  input  values  causing transitions between states during
+          debugging. Both primary and pseudo inputs are printed.
+
+   -m
+          Pipe debugger output through the UNIX utility more.
+
+   -t <timeOutPeriod>
+          Specify the time out period (in seconds) after which the command
+          aborts. By default this option is set to infinity.
+
+   -s
+          Print debug output in the format accepted by the [3]simulate command.
+
+   -v <verbosity_level>
+          Specify verbosity level. This sets the amount of feedback on CPU
+          usage and code status.
+          verbosity_level must be one of the following:
+
+          0: No feedback provided. This is the default.
+
+          1: Feedback on code location.
+
+          2: Feedback on code location and CPU usage.
+
+   -A <le_method>
+          Specify whether the compositional SCC analysis algorithm, Divide and
+          Compose (DnC), is enabled for language emptiness checking. The DnC
+          algorithm first enumerates fair SCCs in an over-approximated abstract
+          model,  and then successively refines them in the more concrete
+          models. Since non-fair SCCs can be ignored in the more concrete
+          models, a potentially large part of the state space are pruned away
+          early on when the computations are cheap.
+
+          le_method must be one of the following:
+
+          0 : no use of Divide and Compose (Default).
+
+          1 : use Divide and Compose.
+
+   -D <dc_level>
+          Specify extent to which don't cares are used to simplify MDDs in
+          model checking. Don't cares are minterms on which the value taken by
+          functions  does  not affect the computation; potentially, these
+          minterms can be used to simplify MDDs and reduce the time taken to
+          perform model checking.
+          dc_level must be one of the following:
+
+          0 : No don't cares are used.
+
+          1 : Use unreachable states as don't cares. This is the default.
+
+          2 : Use unreachable states as don't cares and in the EU computation,
+          use 'frontiers' for image computation.
+
+          3  : First compute an overapproximation of the reachable states
+          (ARDC), and use that as the cares set. Use `frontiers' for image
+          computation. For help on controlling options for ARDC, look up help
+          on the command: [4]print_ardc_options. Refer to Moon, Jang, Somenzi,
+          Pixley, Yuan, "Approximate Reachability Don't Cares for {CTL} Model
+          Checking",  ICCAD98,  and to two papers by Cho et al, IEEE TCAD
+          December 1996: one is for State Space Decomposition and the other is
+          for Approximate FSM Traversal.
+
+   -S <schedule>
+          Specify schedule for GSH algorithm, which generalizes the Emerson-Lei
+          algorithm and is used to compute greatest fixpoints. The choice of
+          schedule  affects the sequence in which EX and EU operators are
+          applied. It makes a difference only when fairness constraints are
+          specified.
+          <schedule> must be one of the following:
+
+          EL : EU and EX operators strictly alternate. This is the default.
+
+          EL1 : EX is applied once for every application of all EUs.
+
+          EL2 : EX is applied repeatedly after each application of all EUs.
+
+          budget : a hybrid of EL and EL2
+
+          random : enabled operators are applied in (pseudo-)random order.
+
+          off : GSH is disabled, and the old algorithm is used instead. The old
+          algorithm  uses  the  EL  , but the termination checks are less
+          sophisticated than in GSH.
+
+   -F
+          Use forward analysis in the computation of the greatest fixpoint.
+          This option is incompatible with -d 1 or higher and can only be used
+          with -D 1.
+
+   -L <lockstep_mode>
+          Use the lockstep algorithm, which is based on fair SCC enumeration.
+          <lockstep_mode> must be one of the following:
+
+          off : Lockstep is disabled. This is the default. Language emptiness
+          is checked by computing a hull of the fair SCCs.
+
+          on : Lockstep is enabled.
+
+          all : Lockstep is enabled; all fair SCCs are enumerated instead of
+          terminating as soon as one is found. This can be used to study the
+          SCCs of a graph, but it is slower than the default option.
+
+          n : (n is a positive integer). Lockstep is enabled and up to n fair
+          SCCs are enumerated. This is less expensive than all , but still less
+          efficient than on , even when n = 1 .
+
+   -X
+          Disable strength reduction (use different decision procedures for
+          strong, weak, and terminal automaton). Strength reduction is the
+          default.  Refer  to  Bloem,  Ravi, Somenzi, "Efficient Decision
+          Procedures for LTL Model Checking," CAV99.
+
+   -Y
+          Disable incremental construction of the partition for (MxA). Instead,
+          build a new partition from the scratch. Incremental construction of
+          the partition is the default.
+
+   -Z
+          Add arcs into the Buechi automaton by direct simulation relation, to
+          heuristically reduce the length of shortest counter-example in model
+          checking. Refer to Awedh and Somenze, "Proving More Properties with
+          Bounded Model Checking," CAV04.
+
+   -M
+          Maximize (adding arcs to) Buechi automaton using Direct Simulation.
+
+   <ltl_file>
+          File containing LTL formulas to be model checked.
+
+   Related "set" options:
+
+   ltl_change_bracket <yes/no>
+          Vl2mv automatically converts "[]" to "<>" in node names, therefore
+          CTL* parser does the same thing. However, in some cases a user does
+          not want to change node names in CTL* parsing. Then, use this set
+          option by giving "no". Default is "yes".
+
+          See   also  commands  :  model_check,  approximate_model_check,
+          incremental_ctl_verification
+            __________________________________________________________
+
+          Last updated on 20100410 00h02
+
+References
+
+   1. file://localhost/projects/development/hsv/vis/common/doc/html/init_verifyCmd.html
+   2. file://localhost/projects/development/hsv/vis/common/doc/ctl/ctl/ctl.html
+   3. file://localhost/projects/development/hsv/vis/common/doc/html/simulateCmd.html
+   4. file://localhost/projects/development/hsv/vis/common/doc/html/print_ardc_optionsCmd.html
Index: vis_dev/vis-2.3/share/help/ltl_to_autCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/ltl_to_autCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/ltl_to_autCmd.txt	(revision 14)
@@ -0,0 +1,85 @@
+
+  ltl_to_aut - translate LTL formulae into Buechi automata
+     _________________________________________________________________
+
+   ltl_to_aut  [-f  <ltl_file>]  [-m  <algorithm>] [-o <output_file>] [-t
+   <output_format>] [-w] [-b] [-p] [-d] [-r] [-i] [-M] [-v <verbosity>] [-h]
+
+   Translate  the given LTL formulae into Buechi automata, and output the
+   automaton into a file.
+
+   The   translation   algorithms  are  the  same  as  the  one  used  in
+   [1]ltl_model_check . However, more flexible combination of the options can
+   be used with this command.
+
+   The automaton can be displayed on the screen and written into a file. The
+   format of the output can be dot, blifmv, verilog and smv.
+
+   Command options:
+
+   -f <ltl_file>
+          The input file containing LTL formulae.
+
+   -m <algorithm>
+          Specify  the  algorithm used in LTL formula -> Buechi automaton
+          translation algorithm.
+
+          algorithm must be one of the following:
+
+          0: GPVW.
+
+          1: GPVW+.
+
+          2: LTL2AUT.
+
+          3: WRING (default).
+
+   -o <output_file>
+          Write the automata into this file.
+
+   -t <output_format>
+          Specify the output format of the automata.
+
+          output_format must be one of the following:
+
+          0: dot.
+
+          1: blif_mv.
+
+          2: verilog.
+
+          3: all of the formats above (default).
+
+   -w
+          Rewriting the formula before translation.
+
+   -b
+          Boolean minimization during the translation.
+
+   -p
+          Pruning the fair states in the Buechi automaton.
+
+   -d
+          Direct-simulation minimization of the Buechi automaton.
+
+   -r
+          Reverse-simulation minimization of the Buechi automaton.
+
+   -i
+          Minimization based ont the I/O structural information.
+
+   -M
+          Maximize (adding arcs to) Buechi automaton using Direct Simulation.
+
+   -v <verbosity_level>
+          Specify verbosity level. It must be one of the following: 0,1,2,3.
+
+   -h
+          Print the command usage.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
+
+References
+
+   1. file://localhost/projects/development/hsv/vis/common/doc/html/ltl_model_checkCmd.html
Index: vis_dev/vis-2.3/share/help/model_checkCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/model_checkCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/model_checkCmd.txt	(revision 14)
@@ -0,0 +1,319 @@
+
+  model_check - perform fair CTL model checking on a flattened network
+     _________________________________________________________________
+
+   model_check [-b] [-c] [-d <dbg_level>] [-f <dbg_file>] [-g <hints_file>]
+   [-h]  [-i]  [-m] [-r] [-t <time_out_period>][-v <verbosity_level>] [-D
+   <dc_level>] [-F] [-S <schedule>] [-V] [-B] [-I] [-C] [-w <node_file>] [-W]
+   [-G] <ctl_file>
+
+   Performs fair CTL model checking on a flattened network. Before calling this
+   command, the user should have initialized the design by calling the command
+   [1]init_verify. Regardless of the options, no 'false positives' or 'false
+   negatives' will occur: the result is correct for the given circuit.
+
+   Properties to be verified should be provided as CTL formulas in the file
+   ctl_file. Note that the support of any wire referred to in a formula should
+   consist only of latches. For the precise syntax of CTL formulas, see the
+   [2]VIS CTL and LTL syntax manual.
+
+   Properties  of  the form AG f, where f is a formula not involving path
+   quantifiers are referred to as invariants; for such properties it may be
+   substantially faster to use the [3]check_invariant command.
+
+   A fairness constraint can be specified by invoking the [4]read_fairness
+   command; if none is specified, all paths are taken to be fair. If some
+   initial states do not lie on a fair path, the model checker prints a message
+   to this effect.
+
+   A  formula passes iff it is true for all initial states of the system.
+   Therefore, in the presence of multiple initial states, if a formula fails,
+   the negation of the formula may also fail.
+
+   If  a  formula does not pass, a (potentially partial) proof of failure
+   (referred to as a debug trace) is demonstrated. Fair paths are represented
+   by a finite sequence of states (the stem) leading to a fair cycle, i.e. a
+   cycle on which there is a state from each fairness condition. The level of
+   detail of the proof can be specified (see option -d).
+
+   Both  backward (future tense CTL formulas) and forward (past tense CTL
+   formulas) model checking can be performed. Forward model checking is based
+   on Iwashita's ICCAD96 paper. Future tense CTL formulas are automatically
+   converted to past tense ones as much as possible in forward model checking.
+
+   Command options:
+
+   -b
+          Use backward analysis when performing debugging; the default is to
+          use forward analysis. This should be tried when the debugger spends a
+          large amount of time when creating a path to a fair cycle. This
+          option is not compatible with forward model checking option (-F).
+
+   -c
+          Use the formula tree so that there is no sharing of sub-formulae
+          among the formulae in the input file. This option is useful in the
+          following scenario - formulae A, B and C are being checked in order
+          and  there  is sub-formula sharing between A and C. If the BDDs
+          corresponding to the shared sub-formula is huge then computation for
+          B might not be able to finish without using this option.
+
+   -d <dbg_level>
+          Specify the amount of debugging performed when the system fails a
+          formula being checked. Note that it may not always be possible to
+          give a simple counter-example to show that a formula is false, since
+          this may require enumerating all paths from a state. In such a case
+          the model checker will print a message to this effect. This option is
+          incompatible with -F.
+
+          dbg_level must be one of the following:
+
+          0: No debugging performed. dbg_level=0 is the default.
+
+          1: Debugging with minimal output: generate counter-examples for
+          universal formulas (formulas of the form AX|AF|AU|AG) and witnesses
+          for existential formulas (formulas of the form EX|EF|EU|EG). States
+          on a path are not further analyzed.
+
+          2:  Same as dbg_level=1, but more verbose. (The subformulas are
+          printed, too.)
+
+          3: Maximal automatic debugging: as for level 1, except that states
+          occurring on paths will be recursively analyzed.
+
+          4: Manual debugging: at each state, the user is queried if more
+          feedback is desired.
+
+   -f <dbg_file>
+          Write the debugger output to dbg_file. This option is incompatible
+          with  -F. Notes: when you use -d4 (interactive mode), -f is not
+          recommended, since you can't see the output of vis on stdout.
+
+   -g <hints_file>
+          Use guided search. The file hints_file contains a series of hints. A
+          hint is a formula that does not contain any temporal operators, so
+          hints_file has the same syntax as a file of invariants used for
+          check_invariant. The hints are used in the order given to change the
+          transition relation. In the case of least fixpoints (EF, EU), the
+          transition relation is conjoined with the hint, whereas for greatest
+          fixpoints the transition relation is disjoined with the negation of
+          the hint. If the hints are cleverly chosen, this may speed up the
+          computation  considerably,  because  a  search with the changed
+          transition relation may be much simpler than one with the original
+          transition relation, and results obtained can be reused, so that we
+          may never have to do a complicated search with the original relation.
+          Note: hints in terms of primary inputs are not useful for greatest
+          fixpoints. See also: Ravi and Somenzi, Hints to accelerate symbolic
+          traversal. CHARME'99; Bloem, Ravi, and Somenzi, Efficient Decision
+          Procedures  for Model Checking of Linear Time Logic Properties,
+          CAV'99; Bloem, Ravi, and Somenzi, Symbolic Guided Search for CTL
+          Model Checking, DAC'00.
+
+          For formulae that contain both least and greatest fixpoints, the
+          behavior depends on the flag guided_search_hint_type. If it is set to
+          local (default) then every subformula is evaluated to completion,
+          using all hints in order, before the next subformula is started. For
+          pure   ACTL   or   pure   ECTL   formulae,   we  can  also  set
+          guided_search_hint_type to global, in which case the entire formula
+          is evaluated for one hint before moving on to the next hint, using
+          underapproximations. The description of the options for guided search
+          can be found in the help page for print_guided_search_options.
+
+          model_check will call reachability without any guided search, even if
+          -g is used. If you want to perform reachability with guided search,
+          call rch directly.
+
+          Incompatible with -F.
+
+   -h
+          Print the command usage.
+
+   -i
+          Print  input  values  causing transitions between states during
+          debugging. Both primary and pseudo inputs are printed. This option is
+          incompatible with -F.
+
+   -m
+          Pipe debugger output through the UNIX utility more. This option is
+          incompatible with -F.
+
+   -r
+          Reduce the FSM derived from the flattened network with respect to
+          each formula being checked. By default, the FSM is reduced with
+          respect to the conjunction of the formulae in the input file. If this
+          option is used and don't cares are being used for simplification,
+          then  subformula sharing is disabled (result might be incorrect
+          otherwise).
+
+          The truth of a formula may be independent of parts of the network
+          (such as when wires have been abstracted; see [5]flatten_hierarchy).
+          These parts are effectively removed when this option is invoked; this
+          may result in more efficient model checking.
+
+   -t <timeOutPeriod>
+          Specify the time out period (in seconds) after which the command
+          aborts. By default this option is set to infinity.
+
+   -v <verbosity_level>
+          Specify verbosity level. This sets the amount of feedback on CPU
+          usage and code status.
+          verbosity_level must be one of the following:
+
+          0: No feedback provided. This is the default.
+
+          1: Feedback on code location.
+
+          2: Feedback on code location and CPU usage.
+
+   -B
+          Check for vacuously passing formulae using the algorithm of Beer et
+          al. (CAV97). The algorithm applies to a subset of ACTL (w-ACTL) and
+          replaces the smallest important subformula of a passing property with
+          either  FALSE or TRUE depending on its negation parity. It then
+          applies model checking to the resulting witness formula. If the
+          witness formula also passes, then the original formula is deemed to
+          pass vacuously. If the witness formula fails, a counterexample to it
+          provides an interesting witness to the original passing formula. See
+          the CAV97 paper for the definitions of w-ACTL, important subformula,
+          and interesting witness. In short, one of the operands of a binary
+          operator in a w-ACTL formula must be a propositional formula. See
+          also the -V option.
+
+   -C
+          Compute coverage of all observable signals in a set of CTL formulae
+          using  the algorithm of Hoskote, Kam, Ho, Zhao (DAC'99). If the
+          verbosity level (-v option) is equal to 0, only the coverage stats
+          are printed. If verbosity level is greater than zero, then detailed
+          information of the computation at each step of the algorithm is also
+          provided. Debug information is provided in the form of states not
+          covered for each observable signal if the dbg_level (-d option) is
+          greater  than 0. The number of states printed is set by the vis
+          environment variable 'nr_uncoveredstates'. By default the number of
+          states printed is 1. The value of nr_uncoveredstates can be set using
+          the set command. See also the -I option.
+
+   -D <dc_level>
+          Specify extent to which don't cares are used to simplify MDDs in
+          model checking. Don't cares are minterms on which the values taken by
+          functions do not affect the computation; potentially, these minterms
+          can be used to simplify MDDs and reduce the time taken to perform
+          model checking. The -g flag for guided search does not affect the way
+          in which the don't-care conditions are computed.
+          dc_level must be one of the following:
+
+          0 : No don't cares are used.
+
+          1 : Use unreachable states as don't cares. This is the default.
+
+          2 : Use unreachable states as don't cares and in the EU computation,
+          use 'frontiers' for image computation.
+
+          3  : First compute an overapproximation of the reachable states
+          (ARDC), and use that as the cares set. Use `frontiers' for image
+          computation. For help on controlling options for ARDC, look up help
+          on the command: [6]print_ardc_options. Refer to Moon, Jang, Somenzi,
+          Pixley, Yuan, "Approximate Reachability Don't Cares for {CTL} Model
+          Checking",  ICCAD98,  and to two papers by Cho et al, IEEE TCAD
+          December 1996: one is for State Space Decomposition and the other is
+          for Approximate FSM Traversal.
+
+   -F
+          Use forward model checking based on Iwashita's method in ICCAD96.
+          Future tense CTL formulas are automatically converted to past tense
+          ones as much as possible. Converted forward formulas are printed when
+          verbosity is greater than 0. Debug options (-b, -d, -f, -i, and -m)
+          are  ignored  with this option. We have seen that forward model
+          checking was much faster than backward in many cases, also forward
+          was much slower than backward in many cases.
+
+   -I
+          Compute coverage of all observable signals in a set of CTL formulae
+          using  an  improved  algorithm of Jayakumar, Purandare, Somenzi
+          (DAC'03). If the verbosity level (-v option) is equal to 0, only the
+          coverage stats are printed. If verbosity level is greater than zero,
+          then detailed information of the computation at each step of the
+          algorithm is also provided. Debug information is provided in the form
+          of states not covered for each observable signal if the dbg_level (-d
+          option) is greater than 0. The number of states printed is set by the
+          vis environment variable 'nr_uncoveredstates'. By default the number
+          of states printed is 1. The value of nr_uncoveredstates can be set
+          using the set command. Compared to the -C option, this one produces
+          more accurate results and deals with a larger subset of CTL.
+
+   -S <schedule>
+          Specify schedule for GSH algorithm, which generalizes the Emerson-Lei
+          algorithm and is used to compute greatest fixpoints. The choice of
+          schedule  affects the sequence in which EX and EU operators are
+          applied. It makes a difference only when fairness constraints are
+          specified.
+          <schedule> must be one of the following:
+
+          EL : EU and EX operators strictly alternate. This is the default.
+
+          EL1 : EX is applied once for every application of all EUs.
+
+          EL2 : EX is applied repeatedly after each application of all EUs.
+
+          budget : a hybrid of EL and EL2.
+
+          random : enabled operators are applied in (pseudo-)random order.
+
+          off : GSH is disabled, and the old algorithm is used instead. The old
+          algorithm uses the EL schedule, but the termination checks are less
+          sophisticated than in GSH.
+
+   -V
+          Check for vacuously passing formulae with the algorithm of Purandare
+          and Somenzi (CAV2002). The algorithm applies to all of CTL, and to
+          both  passing and failing properties. It says whether a passing
+          formula may be strengthened and still pass, and whether a failing
+          formula may be weakened and still fail. It considers all leaves of a
+          formula that are under one negation parity (e.g., not descendants of
+          a XOR or EQ node) for replacement by either TRUE or FALSE. See also
+          the -B option.
+
+   -w <node_file> This option invoked the algorithm to generate an error trace
+          divided into fated and free segements. Fate represents the
+          inevitability and free is asserted when there is no inevitability.
+          This can be formulated as a two-player concurrent reachability game.
+          The two players are the environment and the system. The node_file is
+          given to specify the variables the are controlled by the system.
+
+   -W
+   This option represents the case that all input variables are controlled by
+          system.
+
+   -G
+   We proposed two algorithm to generate segemented counter example. They are
+          general and restrcited algorithm. Bu default we use restricted
+          algorithm. We can invoke general algorithm with -G option. For more
+          information, please check the STTT'04 paper of Jin et al., "Fate and
+          Free Will in Error Traces"
+
+   <ctl_file>
+          File containing CTL formulas to be model checked.
+
+   Related "set" options:
+
+   ctl_change_bracket <yes/no>
+          Vl2mv automatically converts "[]" to "<>" in node names, therefore
+          CTL parser does the same thing. However, in some cases a user does
+          not want to change node names in CTL parsing. Then, use this set
+          option by giving "no". Default is "yes".
+
+   guided_search_hint_type
+          Switches between local and global hints (see the -g option, or the
+          help page for set).
+
+   See also commands : approximate_model_check, incremental_ctl_verification
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
+
+References
+
+   1. file://localhost/projects/development/hsv/vis/common/doc/html/init_verifyCmd.html
+   2. file://localhost/projects/development/hsv/vis/common/doc/ctl/ctl/ctl.html
+   3. file://localhost/projects/development/hsv/vis/common/doc/html/check_invariantCmd.html
+   4. file://localhost/projects/development/hsv/vis/common/doc/html/read_fairnessCmd.html
+   5. file://localhost/projects/development/hsv/vis/common/doc/html/flatten_hierarchyCmd.html
+   6. file://localhost/projects/development/hsv/vis/common/doc/html/print_ardc_optionsCmd.html
Index: vis_dev/vis-2.3/share/help/network_sweepCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/network_sweepCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/network_sweepCmd.txt	(revision 14)
@@ -0,0 +1,19 @@
+
+  network_sweep - sweeps the network to ensure that deterministic constants are
+  removed
+     _________________________________________________________________
+
+   network_sweep [-h][-v]
+
+   This function performs a sweep on the given Ntk_Network_t. It propagates all
+   the deterministic constant nodes, and removes all buffer nodes. It modifies
+   the network. Command options:
+
+   -h
+          Print the command usage.
+
+   -v
+          Print debug information.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/print_aig_statsCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/print_aig_statsCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/print_aig_statsCmd.txt	(revision 14)
@@ -0,0 +1,26 @@
+
+  print_aig_stats - print statistics about the AND/INVERTER graph.
+     _________________________________________________________________
+
+   print_aig_stats [-h] [-n]
+
+   Print the following statistics about the AND/INVERTER graph:
+
+     Maximum number of nodes: the maximum number of nodes in the AND/ INVERTER
+          graph.
+
+     Current number of nodes: the number of nodes in the AND/INVERTER graph
+          that are used.
+
+   Note that build_partition_maigs must be called before this command.
+
+   Command options:
+
+   -n
+          Print the name of the nodes.
+
+   -h
+          Print the command usage.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/print_ardc_optionsCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/print_ardc_optionsCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/print_ardc_optionsCmd.txt	(revision 14)
@@ -0,0 +1,233 @@
+
+  print_ardc_options - print information about the ARDC options currently in
+  use
+     _________________________________________________________________
+
+   print_ardc_options [-h] [-H]
+
+   Prints information about the current ARDC options.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   -H
+          Print the ARDC set command usage.
+
+   Set parameters: The ARDC options are specified with the set command.
+
+   ardc_traversal_method <method>
+          Specify a method for approximate FSM traversal.
+
+          method must be one of the following:
+
+          0 : MBM (machine by machine).
+
+          1 : RFBF(reached frame by frame).
+
+          2 : TFBF(to frame by frame).
+
+          3 : TMBM(combination of MBM and TFBF).
+
+          4 : LMBM(least fixpoint MBM, default).
+
+          5 : TLMBM(combination of LMBM and TFBF).
+
+   ardc_group_size <size>
+          Specify the number of latches per group for ARDCS.
+
+          size must be a positive integer (default = 8).
+
+   ardc_affinity_factor <affinity>
+          Specify affinity factor to make a group for ARDCs. The available
+          factor is from 0.0(use only correlation) to 1.0(use only dependency).
+
+          affinity must be a positive real (default = 0.5).
+
+   ardc_max_iteration <iteration>
+          Specify the maximum iteration count during approximate FSM traversal.
+          Default is 0 which means infinite.
+
+          iteration must be a positive integer or zero.
+
+   ardc_constrain_target <target>
+          Specify where image constraining will be applied to.
+
+          target must be one of the following:
+
+          0 : constrain transition relation (default).
+
+          1 : constrain initial states.
+
+          2 : constrain both.
+
+   ardc_constrain_method <method>
+          Specify an image constraining method to compute ARDCs.
+
+          method must be one of the following:
+
+          0 : restrict (default).
+
+          1 : constrain
+
+          2 : compact (currently supported by only CUDD)
+
+          3 : squeeze (currently supported by only CUDD)
+
+   ardc_constrain_reorder <method>
+          Specify whether to enable variable reorderings during consecutive
+          image constraining operations.
+
+          method must be one of the following:
+
+          yes  :  allow  variable  reorderings  during  consecutive image
+          constraining operations (default)
+
+          no  : don't allow variable reorderings during consecutive image
+          constraining operations
+
+   ardc_abstract_pseudo_input <method>
+          Specify when to abstract pseudo primary input variables out from
+          transition relation.
+
+          method must be one of the following:
+
+          0 : do not abstract pseudo input variables
+
+          1 : abstract pseudo inputs before image computation (default)
+
+          2 : abstract pseudo inputs at every end of image computation
+
+          3 : abstract pseudo inputs at the end of approximate traversal
+
+   ardc_decompose_flag <method>
+          Specify whether to use decomposed approximate reachable states or
+          single conjuncted reachable states.
+
+          method must be one of the following:
+
+          yes : keep decomposed reachable stateses (default)
+
+          no : make a conjunction of reachable states of all submachines
+
+   ardc_projected_initial_flag <method>
+          Specify which initial states is going to be used.
+
+          method must be one of the following:
+
+          yes : use projected initial states for submachine (default)
+
+          no : use original initial states for submachine
+
+   ardc_image_method <method>
+          Specify  image_mathod  during  computing  reachable  states  of
+          submachines.
+
+          method must be one of the following:
+
+          monolithic : use monolithic image computation
+
+          iwls95 : use iwls95 image computation (default)
+
+          mlp : use mlp image computation
+
+          tfm : use tfm image computation
+
+          hybrid : use hybrid image computation
+
+   ardc_use_high_density <method>
+          Specify whether to use high density in computing reachable states of
+          submachines.
+
+          method must be one of the following:
+
+          yes : use High Density for reachable states of submachines
+
+          no : use BFS for reachable states of submachines (default)
+
+   ardc_reorder_ptr <method>
+          Specify whether to reorder partitioned transition relation after
+          constraining fanin submachines.
+
+          method must be one of the following:
+
+          yes : whenever partitioned transition relation changes, reorders
+          partitioned transition relation
+
+          no : no reordering of partitioned transition relation (default)
+
+   ardc_fanin_constrain_mode <method>
+          Specify which method will be used in constraining fanin submachines.
+
+          method must be one of the following:
+
+          0  : constrain w.r.t. the reachable states of fanin submachines
+          (default)
+
+          1 : constrain w.r.t. the reachable states of both fanin submachines
+          and itself
+
+   ardc_create_pseudo_var_mode <method>
+          Specify which method will be used to create pseudo input variables of
+          submachines.
+
+          method must be one of the following:
+
+          0 : makes pseudo input variables with exact support (default)
+
+          1 : makes pseudo input variables from all state variables of the
+          other submachines
+
+          2 : makes pseudo input variables from all state variables of fanin
+          submachines
+
+   ardc_lmbm_initial_mode <method>
+          Specify  which  method  will  be used as initial states in LMBM
+          computation.
+
+          method must be one of the following:
+
+          0 : use given initial states all the time
+
+          1 : use current reached states as initial states (default)
+
+          2 : use current frontier as initial states
+
+   set ardc_mbm_reuse_tr <method>
+          Specify whether to reuse already constrained transition relation for
+          next iteratrion in MBM.
+
+          method must be one of the following:
+
+          yes : use constrained transition relation for next iteration
+
+          no : use original transition relation for next iteration (default)
+
+   ardc_read_group <filename>
+          Specify a filename containing grouping information
+
+          filename containing grouping information
+
+   ardc_write_group <filename>
+          Specify a filename to write grouping information
+
+          filename to write grouping information
+
+   ardc_verbosity <verbosity>
+          Specify the level of printing information during computing ARDCs.
+
+          verbosity must be 0 - 3 (default = 0).
+
+   The default settings correspond to the fast variants of LMBM and MBM. MBM
+   never  produces  a  more accurate approximation than LMBM for the same
+   state-space decomposition. However, the corresponding statement does not
+   hold for the fast versions. (That is, FastMBM will occasionally outperform
+   FastLMBM.) To get the slower, but more accurate versions of LMBM and MBM use
+   the following settings:
+     * set ardc_constrain_method 1
+     * set ardc_constrain_reorder no
+     * set ardc_abstract_pseudo_input 0
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/print_bdd_statsCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/print_bdd_statsCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/print_bdd_statsCmd.txt	(revision 14)
@@ -0,0 +1,21 @@
+
+  print_bdd_stats - print the BDD statistics for the flattened network
+     _________________________________________________________________
+
+   print_bdd_stats [-h]
+
+   Print the BDD statistics for the flattened network. The MDDs representing
+   the functions of the network are themselves represented by BDDs via an
+   encoding of the multi-valued variables into binary valued variables. The
+   statistics given by this command depend on the underlying BDD package with
+   which VIS was linked. To get more information about the statistics, consult
+   the documentation for the given BDD package. The commands flatten_hierarchy
+   and static_order must be invoked before this command.
+
+   Command options:
+
+   -h
+          Print the command usage.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/print_fairnessCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/print_fairnessCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/print_fairnessCmd.txt	(revision 14)
@@ -0,0 +1,17 @@
+
+  print_fairness - print the fairness constraint of the flattened network
+     _________________________________________________________________
+
+   print_fairness [-h]
+
+   Print the fairness constraint (i.e the set of Buchi conditions) associated
+   with the FSM of the flattened network. By default, the flattened network has
+   the single constraint TRUE, indicating that all paths are fair.
+
+   Command options:
+
+   -h
+          Print the command usage.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/print_guided_search_optionsCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/print_guided_search_optionsCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/print_guided_search_optionsCmd.txt	(revision 14)
@@ -0,0 +1,61 @@
+
+  print_guided_search_options - print information about guided_search_options
+  in use
+     _________________________________________________________________
+
+   print_guided_search_options [-h]
+
+   Prints information about current Guided Search options. Guided search is an
+   alternate method to compute fixpoints by modifying the fixpoint computation
+   with restrictions. It is applicable to the compute_reach, check_invariant
+   and model_check commands (refer to their help pages on the use of guided
+   search).  See  also for details: Ravi and Somenzi, Hints to accelerate
+   symbolic traversal. CHARME'99; Bloem, Ravi, and Somenzi, Efficient Decision
+   Procedures for Model Checking of Linear Time Logic Properties, CAV'99;
+   Bloem, Ravi, and Somenzi, Symbolic Guided Search for CTL Model Checking,
+   DAC'00. Not allowed with -A 2 or -i, and will only work with iwls95 or
+   monolithic image methods. The description of some options can be found in
+   the help page for set.
+
+   Command options:
+
+   guided_search_hint_type
+          Choose from local (default) or global. If this flag is set to local,
+          then every subformula is evaluated to completion, using all hints in
+          order, before the next subformula is started. For pure ACTL or pure
+          ECTL formulae, we can also set guided_search_hint_type to global, in
+          which case the entire formula is evaluated for one hint before moving
+          on to the next hint, using underapproximations.
+
+   guided_search_underapprox_minimize_method
+          Choose from "constrain" and "and" (default). Sets the method with
+          which the transition relation is minimized when underapproximations
+          are used. The option constrain is incompatible with hints that use
+          signals other than inputs.
+
+   guided_search_overapprox_minimize_method
+          Choose from "squeeze" and "ornot" (default). Sets the method with
+          which the transition relation is minimized when underapproximations
+          are used. The option squeeze is incompatible with hints that use
+          signals other than inputs. Ornot implies that the transition relation
+          will be disjoined with the negation of the hint: T' = T + ~h, whereas
+          squeeze will find a small BDD between T and T'.
+
+   guided_search_sequence
+          For compute_reach and check_invariant only. Set this flag to a list
+          of comma-separated integers i1,i2,...,in, with n at most the number
+          of  hints  that you specify . The k'th hint will be used for ik
+          iterations (images). A value of 0 causes the hint to be applied to
+          convergence. Not setting this option is like setting it to 0,0,...,0.
+          If length of the specified sequence is less than the number of hints,
+          the sequence is padded with zeroes.
+
+   Guided search also uses the High Density traversal options that are germane
+   to dead-ends. The relevant flags are hd_dead_end, hd_dead_end_approx_method,
+   hd_frontier_approx_threshold,hd_approx_quality,hd_approx_bias_quality.Use
+   help on the print_hd_options command for explanation of these flags. If
+   guided search is used with HD using the -A 1 options in compute_reach and
+   check_invariant, the HD options are used by both HD and guided search.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/print_hd_optionsCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/print_hd_optionsCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/print_hd_optionsCmd.txt	(revision 14)
@@ -0,0 +1,168 @@
+
+  print_hd_options - print information about the HD options currently in use
+     _________________________________________________________________
+
+   print_hd_options [-h]
+
+   Prints  information  about the current HD options. The HD method is an
+   alternate  method to compute a least fixpoint and is provided with the
+   compute_reach and check_invariant commands. The method is described in Ravi
+   and Somenzi, ICCAD95. The command can be used only when compiled with the
+   CUDD package.
+
+   Command options:
+
+   -h
+   Print the command usage.
+
+   Set parameters: The HD options are specified with the set command.
+
+   hd_frontier_approx_method <method>
+          This option specifes the method to approximate the frontier set.
+
+          Methods:
+
+          remap_ua : (Default) The BDD approximation method of DAC98 Ravi,
+          Shiple, McMillan, Somenzi.
+
+          biased_rua : Approximation method similar to remap_ua, but uses a
+          bias function. The bias function is set appropriate to the context.
+
+          under_approx : The BDD approximation method of Shiple's thesis.
+
+          heavy_branch : The BDD approximation method of ICCAD95 Ravi, Somenzi.
+
+          short_paths : The BDD approximation method of ICCAD95 Ravi, Somenzi.
+
+          compress : An approximation method that runs short_paths first and
+          then remap_ua.
+
+   hd_frontier_approx_threshold <number>
+          This option specifes the size of the frontier to be used for image
+          computation. The threshold for the various methods is approximate
+          (not strictly adhered to). For the remap_ua and biased_rua method,
+          this threshold is a lower bound and the default is 3500. For the
+          short_paths and heavy_branch methods, this threshold is an upper
+          bound. Therefore, a default of 2000 is set to obtain a meaningful
+          result. Any value lower than 2000 is corrected to this default. This
+          value is also relevant for dead-end computations. In a dead-end, the
+          threshold for each image computation (of a disjunct of Reached) is
+          five times the frontier approximation threshold. When the frontier
+          approximation threshold is 0, the threshold for each dead-end image
+          computation is 5000.
+
+   hd_approx_quality <double>
+          This option specifies the quality factor for the under_approx and
+          remap_ua methods. Default value is 1.0. The range is any double value
+          greater than 0. Smaller quality factors produce smaller results.
+          Meaningful values are between 1 and 2.
+
+   hd_approx_bias_quality <double>
+          This option specifies the quality factor for the biased_rua method.
+          Default value is 0.5. The range is any double value greater than 0.
+          Smaller quality factors produce smaller results. Meaningful values
+          are between 0 and 1.
+
+   hd_dead_end <method>
+          This option specifies the method used for dead-end computation. A
+          "dead-end"  is  characterized  by an empty frontier. A dead-end
+          computation involves generating new states from the reached set.
+
+          Methods:
+
+          brute_force : Computes the image of the entire reached set. May be
+          fatal if the reached set is very large.
+
+          conjuncts : (Default) Computes the image of reached by decomposing
+          into parts.
+
+          hybrid : Computes the image of a subset of reached. If no new states,
+          then the reaminder is decomposed in parts.
+
+   hd_dead_end_approx_method <method>
+          This option allows the specification of the approximation method to
+          use to compute the subset of Reached at the dead-end. The threshold
+          used is the same as hd_frontier_approx_threshold.
+
+          For methods, refer hd_frontier_approx_method methods. Default is
+          remap_ua.
+
+   hd_no_scrap_states
+          This allows the option of not adding the "scrap" states. Scrap states
+          are residues from the approximation of the frontier set. Default is
+          to add the scrap states.
+
+   hd_new_only
+          This allows the option of adding considering only new states of each
+          iteration for image computation. The default is to take a set in the
+          interval of the new states and the reached set.
+
+   hd_only_partial_image
+          This allows the option of HD with partial image computation only (no
+          approximation of the frontier set). Default is to allow both partial
+          images and approximation of the frontier set.
+
+   Partial Image options:
+
+   hd_partial_image_method <method>
+          This option allows the image computation to approximate the image
+          with the specified method.
+
+          Methods:
+
+          approx : (Default) Computes a partial image by under-approximating
+          the intermediate products of image computation.
+
+          clipping  : Computes a partial image by "clipping" the depth of
+          recursion of the and-abstract computations during image computation.
+
+   hd_partial_image_threshold <number>
+          This options allows the specification of a threshold (in terms of bdd
+          node  size  of  the  intermediate  product)  that  will trigger
+          approximation of the intermediate product. Default is 200000. This
+          option has to be used in conjunction with hd_partial_image_size. If
+          the value of hd_partial_image_size is larger than this option, then
+          the approximation of the intermediate size will be as large as the
+          hd_partial_image_size number.
+
+   hd_partial_image_size <number>
+          This options allows the specification of a size (in terms of bdd node
+          size of the intermediate product) that is the target size of the
+          approximated  intermediate  product. Default is 100000. For the
+          short_paths and heavy_branch methods, the size of the approximation
+          is corrected to 10000 if the size specified is lower. This is because
+          the short_paths and heavy_branch methods consider this size as an
+          upper bound on the approximation. This option has to be used in
+          conjunction  with  hd_partial_image_threshold.  If the value of
+          hd_partial_image_threshold is much larger than this option, then the
+          desired  size  will not be obtained as approximation may not be
+          triggered.
+
+   hd_partial_image_approx <method>
+          This options allows the specification of the method to be used to
+          approximate the intermediate product.
+
+          For methods, refer hd_frontier_approx_method methods. Default is
+          remap_ua.
+
+   hd_partial_image_approx_quality <double>
+          This option specifies the quality factor for the under_approx and
+          remap_ua methods for partial image computation. Default value is 1.0.
+          Range of values is any double greater than 0. Smaller quality factors
+          produce smaller results. Meaningful values are between 1 and 2.
+
+   hd_partial_image_approx_bias_quality <double>
+          This option specifies the quality factor for the biased_rua method
+          for partial image computation. Default value is 0.5. Range of values
+          is any double greater than 0. Smaller quality factors produce smaller
+          results. Meaningful values are between 0 and 1.
+
+   hd_partial_image_clipping_depth <double>
+          This  option allows the specification of the depth at which the
+          recursion can be clipped when _hd_partial_image_method_ is clipping.
+          Range  of values is between 0 and 1. The clipping depth is then
+          calculated as the specified fraction of the number of variables.
+          Default is 0.4.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/print_hierarchy_statsCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/print_hierarchy_statsCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/print_hierarchy_statsCmd.txt	(revision 14)
@@ -0,0 +1,19 @@
+
+  print_hierarchy_stats - print the statistics of the current node
+     _________________________________________________________________
+
+   print_hierarchy_stats [-h] [-R]
+
+   Prints the statistics of the current node. Note that it is not necessary to
+   invoke flatten_hierarchy first to create a network.
+
+   Command options:
+
+   -h
+          Print the command usage
+
+   -R
+          Print statistics for nodes recursively all the way down to leaves.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/print_hybrid_optionsCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/print_hybrid_optionsCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/print_hybrid_optionsCmd.txt	(revision 14)
@@ -0,0 +1,283 @@
+
+  print_hybrid_options - print information about the hybrid image computation
+  options currently in use
+     _________________________________________________________________
+
+   print_hybrid_options [-h] [-H]
+
+   Prints information about the current hybrid image computation options.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   -H
+          Print the hybrid image computation set command usage.
+
+   Set parameters: The hybrid image computation options are specified with the
+   set command.
+
+   hybrid_mode <mode>
+          Specify a mode how to start hybrid computation.
+
+          mode must be one of the following:
+
+          0 : start with only transition function and build transition relation
+          on demand
+
+          1 : start with both transition function and relation (default)
+
+          2 : start with only transition relation. Only this mode can deal with
+          nondeterminism.
+
+   hybrid_tr_split_method <method>
+          Specify a method to choose a splitting variable in hybrid mode = 2.
+
+          method must be one of the following:
+
+          0 : use support (default)
+
+          1 : use estimate BDD size
+
+   hybrid_build_partial_tr <method>
+          Specify whether to build full or partial transition relation in
+          hybrid mode = 2. This option is used to use less memory. When we use
+          partial  transition relation, for the variables excluded in the
+          transition relation, we build each bit transition relation on demand.
+          When nondeterminism exists in the circuit, this can not be used.
+          method must be one of the following:
+
+          yes : build partial transition relation
+
+          no : build full transition relation (default)
+
+   hybrid_partial_num_vars <number>
+          Specify how many variables are going to be excluded in building
+          partial transition relation. The default is 8.
+
+   hybrid_partial_method <method>
+          Specify a method to choose variables to be excluded in building
+          partial transition relation.
+
+          method must be one of the following:
+
+          0 : use BDD size (default)
+
+          1 : use support
+
+   hybrid_delayed_split <method>
+          Specify a method whether to split transition relation immediately or
+          just all at once before AndExist.
+
+          method must be one of the following:
+
+          yes : apply splitting to transition relation at once
+
+          no : do not apply (default)
+
+   hybrid_split_min_depth <number>
+          Specify the minimum depth to apply dynamic hybrid method. If a depth
+          is smaller than this minimum depth, just split. The default is 1.
+
+   hybrid_split_max_depth <number>
+          Specify the maximum depth to apply dynamic hybrid method. If a depth
+          is bigger than this maximum depth, just conjoin. The default is 5.
+
+   hybrid_pre_split_min_depth <number>
+          Specify the minimum depth to apply dynamic hybrid method in preimage
+          computation. If a depth is smaller than this minimum depth, just
+          split. The default is 0.
+
+   hybrid_pre_split_max_depth <number>
+          Specify the maximum depth to apply dynamic hybrid method in preimage
+          computation. If a depth is bigger than this maximum depth, just
+          conjoin. The default is 4.
+
+   hybrid_lambda_threshold <number>
+          Specify a threshold in floating between 0.0 and 1.0 to determine to
+          split or to conjoin after computing variable lifetime lambda for
+          image computation. If lambda is equal or smaller than this threshold,
+          we conjoin. Otherwise we split. The default is 0.6
+
+   hybrid_pre_lambda_threshold <number>
+          Specify a threshold in floating between 0.0 and 1.0 to determine to
+          split or to conjoin after computing variable lifetime lambda for
+          preimage  computation.  If lambda is equal or smaller than this
+          threshold, we conjoin. Otherwise we split. The default is 0.65
+
+   hybrid_conjoin_vector_size <number>
+          If the number of components in transition function vector is equal or
+          smaller than this threshold, we just conjoin. This check is performed
+          before computing lambda. The default is 10.
+
+   hybrid_conjoin_relation_size <number>
+          If the number of clusters in transition relation is equal or smaller
+          than this threshold, we just conjoin. This check is performed before
+          computing lambda. The default is 2.
+
+   hybrid_conjoin_relation_bdd_size <number>
+          If the shared BDD size of transition relation is equal or smaller
+          than this threshold, we conjoin. This check is performed before
+          computing lambda. The default is 200.
+
+   hybrid_improve_lambda <number>
+          When variable lifetime lambda is bigger than lambda threshold, if the
+          difference between previous and current lambda is equal or smaller
+          than this threshold, then we conjoin. The default is 0.1.
+
+   hybrid_improve_vector_size <number>
+          When variable lifetime lambda is bigger than lambda threshold, if the
+          difference between the previous and current number of components in
+          transition function vector is equal or smaller than this threshold,
+          then we conjoin. The default is 3.
+
+   hybrid_improve_vector_bdd_size <number>
+          When variable lifetime lambda is bigger than lambda threshold, if the
+          difference  between the previous and current shared BDD size of
+          transition function vector is equal or smaller than this threshold,
+          then we conjoin. The default is 30.0.
+
+   hybrid_decide_mode <method>
+          Specify a method to decide whether to split or to conjoin.
+
+          method must be one of the following:
+
+          0 : use only lambda
+
+          1 : use lambda and also special checks to conjoin
+
+          2 : use lambda and also improvement
+
+          3 : use all (default)
+
+   hybrid_reorder_with_from <method>
+          Specify a method to reorder transition relation to conjoin in image
+          computation, whether to include from set in the computation.
+
+          method must be one of the following:
+
+          yes : reorder relation array with from to conjoin (default)
+
+          no : reorder relation array without from to conjoin
+
+   hybrid_pre_reorder_with_from <method>
+          Specify  a  method to reorder transition relation to conjoin in
+          preimage computation, whether to include from set in the computation.
+
+          method must be one of the following:
+
+          yes : reorder relation array with from to conjoin
+
+          no : reorder relation array without from to conjoin (default)
+
+   hybrid_lambda_mode <method>
+          Specify a method to decide which variable lifetime to be used for
+          image computation.
+
+          method must be one of the following:
+
+          0 : total lifetime with ps/pi variables (default)
+
+          1 : active lifetime with ps/pi variables
+
+          2 : total lifetime with ps/ns/pi variables
+
+   hybrid_pre_lambda_mode <method>
+          Specify a method to decide which variable lifetime to be used for
+          preimage computation.
+
+          method must be one of the following:
+
+          0 : total lifetime with ns/pi variables
+
+          1 : active lifetime with ps/pi variables
+
+          2 : total lifetime with ps/ns/pi variables (default)
+
+          3 : total lifetime with ps/pi variables
+
+   hybrid_lambda_with_from <method>
+          Specify a method to compute variable lifetime lambda, whether to
+          include from set in the computation.
+
+          method must be one of the following:
+
+          yes : include from set in lambda computation (default)
+
+          no : do not include
+
+   hybrid_lambda_with_tr <method>
+          Specify a method to compute variable lifetime lambda, whether to use
+          transition relation or transition function vector, when both exist.
+
+          method must be one of the following:
+
+          yes : use transition relation (default)
+
+          no : use transition function vector
+
+   hybrid_lambda_with_clustering <method>
+          Specify a method whether to include clustering to compute variable
+          lifetime lambda.
+
+          method must be one of the following:
+
+          yes : compute lambda after clustering
+
+          no : do not cluster (default)
+
+   hybrid_synchronize_tr <method>
+          Specify a method to keep transition relation. This option is only for
+          when hybrid mode is 1.
+
+          method must be one of the following:
+
+          yes : rebuild transition relation from function vector whenever the
+          function vector changes
+
+          no : do not rebuild (default)
+
+   hybrid_img_keep_pi <method>
+          Specify a method to build forward transition relation.
+
+          method must be one of the following:
+
+          yes  :  keep  all primary input variables in forward transition
+          relation.
+
+          no : quantify out local primary input variables from the transition
+          relation. (default)
+
+   hybrid_pre_keep_pi <method>
+          Specify a method to build backward transition relation.
+
+          method must be one of the following:
+
+          yes  :  keep all primary input variables in backward transition
+          relation and preimages.
+
+          no : quantify out local primary input variables from the transition
+          relation. (default)
+
+   hybrid_pre_canonical <method>
+          Specify a method whether to canonicalize the function vector for
+          preimage computation.
+
+          method must be one of the following:
+
+          yes : canonicalize the function vector
+
+          no : do not canonicalize (default)
+
+   hybrid_tr_method lt;methodgt;
+          Specify an image method for AndExist operation in hybrid method.
+
+          method must be one of the following:
+
+          iwls95 (default)
+
+          mlp
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/print_img_infoCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/print_img_infoCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/print_img_infoCmd.txt	(revision 14)
@@ -0,0 +1,27 @@
+
+  print_img_info - print information about the image method currently in use
+     _________________________________________________________________
+
+   print_img_info [-b] [-f] [-h]
+
+   Prints information about the image computation method currently being used
+   by the FSM. This includes the particular values of parameters used by the
+   method for initialization. If the image information does not exist, then
+   this command forces the information to be computed. If none of the flags (-b
+   or -f) is set, forward transition relation is computed.
+
+   Command options:
+
+   -b
+          Compute the transition relation for backward image computation (if
+          needed).
+
+   -f
+          Compute the transition relation for forward image computation (if
+          needed).
+
+   -h
+          Print the command usage.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/print_ioCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/print_ioCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/print_ioCmd.txt	(revision 14)
@@ -0,0 +1,15 @@
+
+  print_io - print the names of inputs/outputs in the current node
+     _________________________________________________________________
+
+   print_io [-h]
+
+   Prints the names of inputs/outputs in the current node.
+
+   Command options:
+
+   -h
+          Print the command usage.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/print_latchesCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/print_latchesCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/print_latchesCmd.txt	(revision 14)
@@ -0,0 +1,15 @@
+
+  print_latches - print the names of latches in the current node
+     _________________________________________________________________
+
+   print_latches [-h]
+
+   Prints the names of latches in the current node.
+
+   Command options:
+
+   -h
+          Print the command usage.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/print_mlp_optionsCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/print_mlp_optionsCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/print_mlp_optionsCmd.txt	(revision 14)
@@ -0,0 +1,72 @@
+
+  print_mlp_options - print information about the MLP image computation options
+  currently in use
+     _________________________________________________________________
+
+   print_mlp_options [-h] [-H]
+
+   Prints information about the current MLP image computation options.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   -H
+          Print the MLP image computation set command usage.
+
+   Set parameters: The MLP image computation options are specified with the set
+   command.
+
+   mlp_cluster <method>
+          Specify a method for clustering.
+
+          method must be one of the following:
+
+          0 : linear clustering
+
+          1 : affinity based tree clustering (default)
+
+   mlp_reorder <method>
+          Specify  a  method  for  reordering  after clustering for image
+          computation.
+
+          method must be one of the following:
+
+          0 : no reordering after clustering (default)
+
+          1 : reorder using MLP after clustering (inside)
+
+          2 : reorder using MLP after clustering (outside)
+
+          3 : reorder using IWLS95 after clustering
+
+   mlp_pre_reorder <method>
+          Specify  a  method for reordering after clustering for preimage
+          computation.
+
+          method must be one of the following:
+
+          0 : no reordering after clustering (default)
+
+          1 : reorder using MLP after clustering (inside)
+
+          2 : reorder using MLP after clustering (outside)
+
+          3 : reorder using IWLS95 after clustering
+
+   mlp_postprocess <method>
+          Specify when to do postprocessing.
+
+          method must be one of the following:
+
+          0 : no postprocessing (default)
+
+          1 : do postprocesing after ordering
+
+          2 : do postprocesing after clustering or reordering
+
+          3 : do both 1 and 2
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/print_modelsCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/print_modelsCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/print_modelsCmd.txt	(revision 14)
@@ -0,0 +1,16 @@
+
+  print_models - list all the models and their statistics
+     _________________________________________________________________
+
+   print_models [-h]
+
+   Lists all the models and prints information about the number of variables,
+   tables, latches etc. in them.
+
+   Command options:
+
+   -h
+          Print the command usage.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/print_networkCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/print_networkCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/print_networkCmd.txt	(revision 14)
@@ -0,0 +1,39 @@
+
+  print_network - print information about the flattened network
+     _________________________________________________________________
+
+   print_network [-f] [-h] [-t]
+
+   Prints the name of the flattened network, and information about each node.
+   For each node, prints the following:
+
+     name: the name of the node
+
+     mdd: MDD id (-1 is uninitialized)
+
+     type: one of combinational, primary-input, pseudo-input, latch, or shadow
+
+     derived attributes: list of derived attributes of the node
+
+   See the ntk documentation for more information on types and attributes. The
+   following is an example describing information associated with a node.
+  small.latch_in: mdd=2, combinational; data-input comb-output
+  
+
+   The flattened name of the node is "small.latch_in", its MDD id is 2, it is
+   of  type  combinational, and it is both a data input to a latch, and a
+   combinational output.
+
+   Command options:
+
+   -f
+          Print the fanins and fanouts of each node.
+
+   -h
+          Print the command usage.
+
+   -t
+          Print table statistics for those nodes having tables.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/print_network_dotCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/print_network_dotCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/print_network_dotCmd.txt	(revision 14)
@@ -0,0 +1,27 @@
+
+  print_network_dot - print a dot description of the flattened network
+     _________________________________________________________________
+
+   print_network_dot [-h] <file_name>
+
+   Write a file in the format taken by the tool dot depicting the topology of
+   the network. Dot is a tool that given a description of a graph in a certain
+   format it produces a postscript print of the graph. For more information
+   about dot look in [1]http://www.research.att.com/orgs/ssr/book/reuse. Once a
+   dot file is produced with this command, the shell command dot -Tps >.ps will
+   produce the postscript file depicting the network.
+
+   If no argument is specified on the command line, the description is written
+   to the standard output.
+
+   Command options:
+
+   -h
+          Print the command usage.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
+
+References
+
+   1. http://www.research.att.com/orgs/ssr/book/reuse
Index: vis_dev/vis-2.3/share/help/print_network_statsCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/print_network_statsCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/print_network_statsCmd.txt	(revision 14)
@@ -0,0 +1,41 @@
+
+  print_network_stats - print statistics about the flattened network
+     _________________________________________________________________
+
+   print_network_stats [-h]
+
+   Prints the following statistics about the flattened network:
+
+     name: the name of the flattened network
+
+     combinational:  the  number of nodes which have a table defining the
+          function of the node (excludes pseudo inputs)
+
+     primary inputs: the number of primary input nodes of the flattened network
+
+     primary outputs: the number of primary output nodes of the flattened
+          network
+
+     latches: the number of (multi-valued) latches
+
+     pseudo inputs: the number of pseudo input nodes of the flattened network
+
+     constants: the number of combinational nodes that implement a multi-valued
+          constant
+
+     edges: the number of fanouts in the network (e.g. if the output of a node
+          is used in two places, this contributes two to the sum)
+
+   Note that flatten_hierarchy must be called before this command.
+
+   Example output:
+  small  combinational=2  pi=2  po=0  latches=1  pseudo=0  const=1  edges=4
+  
+
+   Command options:
+
+   -h
+          Print the command usage.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/print_partitionCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/print_partitionCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/print_partitionCmd.txt	(revision 14)
@@ -0,0 +1,28 @@
+
+  print_partition - print the "dot" format describing the partition graph
+     _________________________________________________________________
+
+   print_partition [-h] <file>
+
+   Write a file in the format taken by the tool dot. Dot is a tool that, given
+   a description of a graph in a certain format, produces a postscript print of
+   the    graph.    For    more    information    about   dot   look   in
+   [1]http://www.research.att.com/sw/tools/graphviz.
+
+   If no argument is specified on the command line, the output is written to
+   the standard output.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   <file>
+          Name of file where the partition is to be written in "dot" format.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
+
+References
+
+   1. http://www.research.att.com/sw/tools/graphviz
Index: vis_dev/vis-2.3/share/help/print_partition_aig_dotCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/print_partition_aig_dotCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/print_partition_aig_dotCmd.txt	(revision 14)
@@ -0,0 +1,29 @@
+
+  print_partition_aig_dot - Print a dot description of the AND/INVERTER graph
+  that was built for the flattened network
+     _________________________________________________________________
+
+   print_partition_aig_dot [-h] <file_name>
+
+   Write a file in the format taken by the tool dot depicting the topology of
+   the AND/INVERTER graph. Dot is a tool that given a description of a graph in
+   a certain format it produces a postscript print of the graph. For more
+   information about dot look in
+   [1]http://www.research.att.com/orgs/ssr/book/reuse. Once a dot file is
+   produced with this command, the shell command dot -Tps >.ps will produce the
+   postscript file depicting the network.
+
+   If no argument is specified on the command line, the description is written
+   to the standard output.
+
+   Command options:
+
+   -h
+          Print the command usage.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
+
+References
+
+   1. http://www.research.att.com/orgs/ssr/book/reuse
Index: vis_dev/vis-2.3/share/help/print_partition_statsCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/print_partition_statsCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/print_partition_statsCmd.txt	(revision 14)
@@ -0,0 +1,30 @@
+
+  print_partition_stats - print statistics about the partition graph
+     _________________________________________________________________
+
+   print_partition_stats [-h] [-n]
+
+   Print statistics about the partition currently attached to the network, such
+   as:
+
+     Method used to build the partition.
+
+     Number of sink vertices.
+
+     Number of source vertices.
+
+     Total number of vertices.
+
+     Number of shared MDD nodes used to represent the functions.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   -n
+          Print the name of the network nodes represented by vertices in the
+          partition.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/print_tfm_optionsCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/print_tfm_optionsCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/print_tfm_optionsCmd.txt	(revision 14)
@@ -0,0 +1,318 @@
+
+  print_tfm_options - print information about the transition function based
+  image computation options currently in use
+     _________________________________________________________________
+
+   print_tfm_options [-h] [-H]
+
+   Prints  information  about the current transition function based image
+   computation options.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   -H
+          Print the transition function based image computation set command
+          usage.
+
+   Set parameters: The transition function based image computation options are
+   specified with the set command.
+
+   tfm_split_method <method>
+          Specify a splitting method.
+
+          method must be one of the following:
+
+          0 : input splitting (default)
+
+          1 : output splitting
+
+          2 : mixed (input split + output split)
+
+   tfm_input_split <method>
+          Specify an input splitting method.
+
+          method must be one of the following:
+
+          0 : support before splitting (default)
+
+          1 : support after splitting
+
+          2 : estimate BDD size after splitting
+
+          3 : top variable
+
+   tfm_pi_split_flag <method>
+          Specify whether to allow primary input variables to be chosen as a
+          splitting variable.
+
+          method must be one of the following:
+
+          yes : choose either state or input variable as splitting variable
+          (default)
+
+          no : choose only state variable as splitting variable
+
+   tfm_range_comp <method>
+          Specify a method whether to convert image to range computataion.
+
+          method must be one of the following:
+
+          0 : do not convert to range computation
+
+          1 : convert image to range computation (default)
+
+          2 : use a threshold (tfm_range_threshold, default for hybrid)
+
+   tfm_range_threshold <number>
+          This option is valid only when the tfm_range_comp is set to 2. This
+          threshold  is  used  to  determine  whether to convert to range
+          computation by comparing the shared BDD size of function vector after
+          constraining w.r.t. from set to its original size. If the size is
+          less than the origianl size * , then we convert to range computation.
+          The default value is 10.
+
+   tfm_range_try_threshold <number>
+          This option is valid only when the tfm_range_comp is set to 2. This
+          option is used to disable checking the condition if it fails to
+          convert consecutively times. The default value is 2.
+
+   tfm_range_check_reorder <method>
+          Specify  whether  to  force  to  call variable reordering after
+          constraining function vector w.r.t. from set and before checking the
+          condition.
+
+          method must be one of the following:
+
+          yes : force to reorder before checking tfm_range_threshold
+
+          no : do not reorder (default)
+
+   tfm_tie_break_mode <method>
+          Specify  a tie breaking method when we have a tie in choosing a
+          splitting variable in input and output splitting method.
+
+          method must be one of the following:
+
+          0 : the closest variable to top (default)
+
+          1 : the smallest BDD size after splitting
+
+   tfm_output_split <method>
+          Specify an output splitting method.
+
+          method must be one of the following:
+
+          0 : smallest BDD size (default)
+
+          1 : largest BDD size
+
+          2 : top variable
+
+   tfm_turn_depth <number>
+          This option is valid only when mixed or hybrid method is chosen. This
+          is used to determine when to switch to the other method at which
+          depth  of recursion. The default is 5 for tfm and -1 for hybrid
+          method.
+
+   tfm_find_decomp_var <method>
+          Specify a method whether to try to find a decomposable variable
+          (meaning articulation point) first if any.
+
+          method must be one of the following:
+
+          yes : try to find a decomposable variable (articulation point)
+
+          no : do not try (default)
+
+   tfm_sort_vector_flag <method>
+          Specify a method whether to sort function vectors to increase cache
+          performance.
+
+          method must be one of the following:
+
+          yes : sort function vectors (default for tfm)
+
+          no : do not sort (default for hybrid)
+
+   tfm_print_stats <method>
+          Specify a method whether to print statistics for cache and recursions
+          at the end of job.
+
+          method must be one of the following:
+
+          yes : print statistics
+
+          no : do not print (default)
+
+   tfm_print_bdd_size <method>
+          Specify a method whether to print the BDD size of all intermediate
+          product.
+
+          method must be one of the following:
+
+          yes : print BDD size
+
+          no : do not print (default)
+
+   tfm_split_cube_func <method>
+          Specify a method whether to try to find a cube in function vector in
+          input splitting, then perform output splitting once w.r.t. the cube.
+
+          method must be one of the following:
+
+          yes : try cube splitting
+
+          no : do not try (default)
+
+   tfm_find_essential <method>
+          Specify a method whether to try to find essential variables in from
+          set. If a variable occurs in all cubes of a BDD, the variable is
+          called essential. If exists, minimize both function vector and the
+          from set with the essential cube.
+
+          method must be one of the following:
+
+          0 : do not try (default)
+
+          1 : try to find essential variables
+
+          2 : on and off dynamically
+
+   tfm_print_essential <method>
+          Specify  a  method whether to print information about essential
+          variables.
+
+          method must be one of the following:
+
+          0 : do not print (default)
+
+          1 : print only at end
+
+          2 : print at every image computation
+
+   tfm_use_cache <method>
+          Specify whether to use an image cache.
+
+          method must be one of the following:
+
+          0 : do not use cache (default for hybrid)
+
+          1 : use cache (default)
+
+          2 : store all intermediate results
+
+   tfm_global_cache <method>
+          Specify a method whether to use one global image cache, or one image
+          cache per each machine.
+
+          method must be one of the following:
+
+          yes : use only one global cache (default)
+
+          no : use one cache per machine
+
+   tfm_max_chain_length <number>
+          This option is used to set the maximum number of items in a slot for
+          conflict. The default is 2.
+
+   tfm_init_cache_size <number>
+          This option is used to set the initial cache size. The number is
+          recommended to be a prime number. Currently, we do not resize the
+          cache size, but for the future extension, we named initial. The
+          default is 1001.
+
+   tfm_auto_flush_cache <method>
+          Specify a method to flush image cache.
+
+          method must be one of the following:
+
+          0 : flush cache only when requested
+
+          1 : flush cache at the end of image computation (default)
+
+          2 : flush cache before reordering
+
+   tfm_compose_intermediate_vars <method>
+          Specify a method whether to compose all intermediate variables.
+
+          method must be one of the following:
+
+          yes : compose all
+
+          no : do not compose (default)
+
+   tfm_pre_split_method <method>
+          Specify a splitting method for preimage computation.
+
+          method must be one of the following:
+
+          0 : input splitting (domain cofactoring, default)
+
+          1 : output splitting (constraint cofactoring)
+
+          2 : mixed (input split + output split)
+
+          3 : substitution
+
+   tfm_pre_input_split <method>
+          Specify an input splitting method for preimage computation.
+
+          method must be one of the following:
+
+          0 : support before splitting (default)
+
+          1 : support after splitting
+
+          2 : estimate BDD size after splitting
+
+          3 : top variable
+
+   tfm_pre_output_split <method>
+          Specify an output splitting method for preimage computation.
+
+          method must be one of the following:
+
+          0 : smallest BDD size (default)
+
+          1 : largest BDD size
+
+          2 : top variable
+
+   tfm_pre_dc_leaf_method <method>
+          Specify a method to switch to another method to complete preimage
+          computation in domain cofactoring method when no more splitting
+          variable exist.
+
+          method must be one of the following:
+
+          0 : substitution (default)
+
+          1 : constraint cofactoring
+
+          2 : hybrid
+
+   tfm_pre_minimize <method>
+          Specify a method whether to minimize transition function vector w.r.t
+          a chosen function in constraint cofactoring method. This option is
+          recommended to use when image cache is disabled, because even though
+          this option can minimize the BDD size of function vector, this may
+          degrade cache performance.
+
+          method must be one of the following:
+
+          yes : minimize function vector w.r.t. a chosen function in constraint
+          cofactoring
+
+          no : do not minimize (default)
+
+   tfm_verbosity <verbosity>
+          Specify the level of printing information related with transition
+          function method.
+
+          verbosity must be 0 - 2 (default = 0).
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/pwdCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/pwdCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/pwdCmd.txt	(revision 14)
@@ -0,0 +1,15 @@
+
+  pwd - print out the full path of the current node from the root node
+     _________________________________________________________________
+
+   pwd [-h]
+
+   Prints out the full path of the current node from the root node.
+
+   Command options:
+
+   -h
+          Print the command usage.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/quitCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/quitCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/quitCmd.txt	(revision 14)
@@ -0,0 +1,19 @@
+
+  quit - exit VIS
+     _________________________________________________________________
+
+   quit [-h] [-s]
+
+   Stops the program. Does not save the current network before exiting.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   -s
+          Free all the memory before quitting. This is slower, and is used for
+          finding memory leaks.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/read_blifCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/read_blifCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/read_blifCmd.txt	(revision 14)
@@ -0,0 +1,44 @@
+
+  read_blif - read a blif file
+     _________________________________________________________________
+
+   read_blif [-c] [-e <encoding_file_name>] [-h] [-v] <file_name>
+
+   Reads a file in blif format into VIS. All the synthesis-specific constructs
+   of blif are ignored. Internally the blif file is automatically translated
+   into an equivalent blif-mv file, which is then read in with read_blif_mv.
+   Note that, currently this command cannot read blif files which describe
+   mapped circuits. To get around this problem, please use SIS synthesis tool
+   to generate an ordinary blif file. Command options:
+
+   -c
+          Semi-canonicalize all the tables in each model. See the documentation
+          of [1]read_blif_mv for details.
+
+   -e <encoding_file_name>
+          If  set,  the  program  reads in a blif file using the encoding
+          information specified in the encoding_file_name. Only the current
+          hnode is altered in the process, and hence the read is incremental.
+          Typically the encoding file is written out by a write_blif operation.
+          Note that this option cannot be used if no file has been read in.
+          Internally, the encoding file is used in combination with the blif
+          file  to create a blif-mv file which is compatible with the I/O
+          interface of the current node.
+
+   -h
+          Print the command usage.
+
+   -v
+          If set, the program prints out all the unused variables in the blif
+          file.
+
+   <file_name>
+          Name of a blif file to be read in. This can be the output written by
+          SIS. in the blif file.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
+
+References
+
+   1. file://localhost/projects/development/hsv/vis/common/doc/html/read_blif_mvCmd.html
Index: vis_dev/vis-2.3/share/help/read_blif_mvCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/read_blif_mvCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/read_blif_mvCmd.txt	(revision 14)
@@ -0,0 +1,50 @@
+
+  read_blif_mv - read a blif-mv file
+     _________________________________________________________________
+
+   read_blif_mv [-c] [-h] [-r] [-v] <file_name>
+
+   Reads a blif-mv file into VIS. The existing hierarchy for the blif-mv file
+   previously read in is overwritten upon a successful read. If an error is
+   detected while reading a file, the previous hierarchy is preserved.
+
+   Command options:
+
+   -c
+          Semi-canonicalize all the tables in each model. The canonicalization
+          process, assigns a linear order to the table rows and columns, based
+          on  the  value of their entries. For a table with binary valued
+          entries,  this value is exactly the number of 1's in the row or
+          column. Once this linear order is assigned, the rows and columns of
+          the table are swapped so as to order rows and columns with higher
+          value at the beginning of the corresponding row or column order. It
+          is called semi-canonicalization because two tables representing the
+          same logic function need not have the same canonical form.
+
+   -h
+          Print the command usage.
+
+   -r
+          If set, the program replaces the subhierarchy rooted at the current
+          node with a new hierarchy specified by a blif-mv file. The file to be
+          read in has to be compatible with the i/o interface of the current
+          hnode (the same i/o names with the same domains). Otherwise, the
+          current hierarchy is kept intact. If -r is not specified, the entire
+          hierarchy is replaced, not just the subhierarchy at the current node.
+
+   -v
+          If  set, the program prints out all the unused variables in the
+          blif-mv  file.  Otherwise,  only a warning is printed that some
+          variables are not used.
+
+   <file_name>
+          blif-mv file to be read in.
+
+   For more information on blif-mv, refer to the [1]blif-mv manual.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
+
+References
+
+   1. http://www-cad.eecs.berkeley.edu/Respep/Research/vis/doc/blifmv/blifmv/blifmv.html
Index: vis_dev/vis-2.3/share/help/read_fairnessCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/read_fairnessCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/read_fairnessCmd.txt	(revision 14)
@@ -0,0 +1,51 @@
+
+  read_fairness - read a fairness constraint
+     _________________________________________________________________
+
+   read_fairness [-h] <file>
+
+   Read a fairness constraint, and associate this constraint with the FSM of
+   the flattened network. An existing constraint associated with the FSM is
+   lost. Subsequent verification procedures are performed relative to the new
+   constraint. Note that, by default, the flattened network has the constraint
+   TRUE, indicating that all paths are fair. The command build_partition_mdds
+   (or init_verify) must have already been invoked on the flattened network,
+   before this command is called.
+
+   Currently, only Buchi constraints are supported. A Buchi fairness constraint
+   is given by a list of individual Buchi conditions, B1, B2, ..., Bk, where Bi
+   is a set of FSM states. A state is fair if there exists an infinite path
+   from that state that intersects each Bi infinitely often.
+
+   The conditions are specified by a file containing at least one CTL formula
+   (see the [1]VIS CTL and LTL syntax manual). In particular, Bi is defined by
+   a CTL formula, which represents the set of states that makes the formula
+   true (in the absence of any fairness constraint). References to signal names
+   in the network should be made using the full hierarchical names. Note that
+   the support of any wire referred to in a formula should consist only of
+   latches. Each CTL formula is terminated by a semicolon.
+
+   Example: In the three conditions below, B1 contains those states that have a
+   next state where cntr.out is RED, B2 contains those where timer.active is 1,
+   and  B3  contains those states for which every path from the state has
+   tlc.request=1 until tlc.acknowledge=1.
+
+  EX(cntr.out=RED);
+  (timer.active=1);
+  A(tlc.request=1 U tlc.acknowledge=1);
+
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   <file>
+          File containing the set of Buchi conditions.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
+
+References
+
+   1. file://localhost/projects/development/hsv/vis/common/doc/ctl/ctl/ctl.html
Index: vis_dev/vis-2.3/share/help/read_orderCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/read_orderCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/read_orderCmd.txt	(revision 14)
@@ -0,0 +1,40 @@
+
+  read_order - Read and reorder variable order from a file.
+     _________________________________________________________________
+
+   read_order [-h] [-v] [<file>]
+
+   This command reads variable order from a file and reorder variable order
+   according to the order. This command can be used any time after static_order
+   command. However, the users should notice that there is a possibility to get
+   BDD blowups during this command.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   -g <group>
+          Specify whether to group present and next state variables or not.
+
+          0: Do not group.
+
+          1: Do group (default).
+
+   -v
+          Print debug information.
+
+   <file>
+          A file containing names of network nodes, used to specify a variable
+          ordering. The name of a node is the full hierarchical path name,
+          starting from the current hierarchical node. A node should appear at
+          most once in the file. Each node name should appear at the beginning
+          of a new line, with no white space preceeding it. The end of a node
+          name is marked by white space, and any other text on the rest of the
+          line  is  ignored. Any line starting with "#" or white space is
+          ignored. See write_order for a sample file. Note that the variable
+          ordering  cannot  be specified at the bit-level; it can only be
+          specified at the multi-valued variable level.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/read_verilogCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/read_verilogCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/read_verilogCmd.txt	(revision 14)
@@ -0,0 +1,31 @@
+
+  read_verilog - read a verilog file
+     _________________________________________________________________
+
+   read_verilog [-c] [-h] [-u] [-F] <file_name>
+
+   Reads a verilog file into VIS. Internally the file is transformed into an
+   equivalent blif-mv file, which is then read into VIS. The existing hierarchy
+   for the blif-mv file previously read in is overwritten upon a successful
+   read. If an error is detected while reading a file, the previous hierarchy
+   is preserved.
+
+   Command options:
+
+   -c
+          Use explicit clocking.
+
+   -h
+          Print the command usage.
+
+   -u
+          Turn off loop unroling.
+
+   -F
+          Ignore all timing.
+
+   <file_name>
+          Verilog file to be read in.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/regression_testCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/regression_testCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/regression_testCmd.txt	(revision 14)
@@ -0,0 +1,345 @@
+
+  regression_test - perform regression test with the information given in
+  arguments file
+     _________________________________________________________________
+
+   regression_test [-s <script_file_name>]
+
+   Invokes two set of execution of vis to compare the performance and to check
+   sanity of each execution. Then make a set of tables summarizing results,
+   such as CPU sec, memoty usage and fail/pass of model_check, etc.. This
+   command will read a description of the regression test to be performed from
+   the argument file, which is configuartion file. Besides the configuration
+   file, one needs to prepare two template files and a design list. We now
+   describe these in turn. As running example we shall use a regression test
+   that compares check_invariant with and without guided search.
+
+   The configuration file for our example is shown below, delimited by lines of
+   dashes (which are not part of the file). The order in which the lines appear
+   in the file is immaterial. A line beginning with '#' is a comment, and is
+   ignored by regression_test.
+   ----------------------------------------------------------------------
+   DesignDirectory : /projects/development/hsv/vis/Regression
+   DesignList : ./DesignListInv
+   ReferenceVis : /usr/local/vis/i686-o/vis-cu
+   ReferenceVisNickName : BFS
+   ReferenceOutputDir : ./result_inv_bfs
+   RefCommandTemplate : ./TemplateRefInv
+   bRefRun : FALSE
+   NewVis : /usr/local/vis/i686-o/vis-cu
+   NewVisNickName : GS
+   NewOutputDir : ./result_inv_gs
+   bNewRun : FALSE
+   NewCommandTemplate : ./TemplateNewInv
+   bCompareCounterExample : TRUE
+   bDefaultInitCommand : FALSE
+   ResultForPerformance : ./BFSvsGS.tex
+   CompareItem : cpu : elapse:
+   CompareItem : mem : Memory in use:
+   CompareItem : bdd : Peak number of live nodes:
+   ----------------------------------------------------------------------
+
+   Each line defines a parameter of the regression test.
+
+   * DesignDirectory gives the path to the directory where the input files are
+   stored.  In  this  case,  we  are  using  the central repository under
+   ~hsv/vis/Regression. It's typically a good idea to store the results of
+   regression tests in a separate place from the input files. In our examples,
+   the results are stored in the current directory.
+
+    * DesignList gives the name of the file containing the list of test cases
+   to  run.  Each  line  consists of several white space-separated fields
+   describing the files making up the test case. The first field is a path to
+   the files relative to DesignDirectory. The second field is the test case
+   name. The remaining fields are file names. More on this later, when we talk
+   about the design list file in detail.
+
+    * ReferenceVis and NewVis give paths to the two versions of vis to be
+   compared in the regression test. They can be the same, as in this case in
+   which both are the "nightly build."
+
+    * ReferenceVisNickName and NewVisNickName are two identifiers that are used
+   in the LaTeX tables to refer to the two versions that are compared. Short
+   mnemonics are preferable. Avoid using underscores, because they currently
+   cause trouble with LaTeX.
+
+    * ReferenceOutputDir and NewOutputDir give the names of the directories in
+   which the results of the runs will be stored. In each of these directories,
+   vis_reg will create a directory for each test case. The names of these
+   directories are the test case names taken from the design list. Therefore,
+   these names must be unique.
+
+    * RefCommandTemplate and NewCommandTemplate are the templates from which
+   vis_reg produces the scripts used to run the test cases. The mechanism used
+   to derive the scripts from the templates and the design list is described in
+   detail when we talk about the template files. The two templates can be the
+   same file.
+
+    * bRefRun and bNewRun are flags that tell vis_reg which of the two sets of
+   experiments should be run (if any). If one set of results has been already
+   computed, the corresponding flag should be set to FALSE. If both flags are
+   FALSE, vis_reg simply regenerates the summary table.
+
+    * bCompareCounterExample is a flag that instructs vis_reg to scan the
+   output  files  for  counterexamples and record their lengths. For each
+   counterexample, stem and cycle length are found. If this flag is set to
+   FALSE, counterexamples are not analyzed and the corresponding table is not
+   produced.
+
+    * bDefaultInitCommand is a flag that, if set to TRUE, instructs vis_reg to
+   generate a default set of commands to initialize each vis run. This option
+   allows one to save some time in preparing the templates, at the expense of
+   some flexibility.
+
+    * ResultForPerformance is the name of the LaTeX file to which vis_reg
+   writes the summary of the experiments. Its format is described in detail
+   later.
+
+    *  CompareItem specifies one item to be monitored in the experiments.
+   Multiple CompareItem lines may appear in the configuration file. Each one
+   consists of two items: an identifier, and a pattern. The identifier is used
+   in the table to denote the item, whereas the pattern is used to extract from
+   the output files the information to be put in the tables.
+
+    In our example, we declare
+
+    CompareItem : mem : Memory in use:
+
+   We instruct regression_test to search for a line beginning with "Memory in
+   use:" in each section of the output file. The token immediately following
+   the occurrence of the pattern is the data item to be put in the table under
+   "mem." so that the resulting LaTeX table contains data on the memmory usage.
+
+    Since  the  output file is divided into sections delimited by strings
+   "CommandBegin" and "CommandEnd." (See below.), each section is searched for
+   the patterns specified by the CompareItem declarations. If the pattern is
+   matched, the item appears in the table for that section.
+
+    To run the regression_test we need configuration file, template file and
+   design list. In case of template file, we need a two template files, since
+   we want to compare two different run of vis. The syntax of the two templates
+   is identical. We describe the template for "new," but all we say applies to
+   "ref" as well. The "new" template for our example is shown below.
+   ----------------------------------------------------------------------
+
+   echo CommandBegin init
+   read_model
+   flt
+   order_vars
+   part
+   time
+   print_bdd_stats
+   echo CommandEnd init
+   echo CommandBegin ci
+   set hd_frontier_approx_threshold 3500
+   ci -t 3600 -g $HintFile $InvFile
+   time
+   print_bdd_stats
+   echo CommandEnd ci
+   echo CommandBegin ci_cex
+   ci -d 1 -i -t 3600 -g $HintFile $InvFile
+   time
+   print_bdd_stats
+   echo CommandEnd ci_cex
+   ----------------------------------------------------------------------
+
+   Before proceeding to its discussion, it is instructive to examine the script
+   that regression_test produces from it for one test case. regression_test
+   relies on vis's shell variables and aliases to customize the script. The
+   script consists of a preamble in which variables and aliases are defined,
+   followed by one or more sections, each corresponding to a major step in the
+   experiment. Statistics will be collected for each step separately. Our
+   example has three sections, whose names are "init," "ci," and "ci_cex." The
+   names of the sections are arbitrary, except that the automatically generated
+   initialization section is always called "init."
+   ----------------------------------------------------------------------
+
+   set vis_stdout ./result_inv_gs/am2901/am2901.out
+   set vis_stderr ./result_inv_gs/am2901/am2901.err
+   set BlifFile /projects/development/hsv/vis/Regression/Am2901/am2901.mv
+   set OrdFile /projects/development/hsv/vis/Regression/Am2901/am2901.ord
+   set InvFile /projects/development/hsv/vis/Regression/Am2901/am2901.inv
+   set HintFile /projects/development/hsv/vis/Regression/Am2901/am2901.hint
+   alias read_model "rlmv $BlifFile"
+   alias set_fairness " "
+   alias order_vars "so -s input_and_latch $OrdFile"
+   echo CommandBegin init
+   read_model
+   flt
+   order_vars
+   part
+   time
+   print_bdd_stats
+   echo CommandEnd init
+   echo CommandBegin ci
+   set hd_frontier_approx_threshold 3500
+   ci -t 3600 -g $HintFile $InvFile
+   time
+   print_bdd_stats
+   echo CommandEnd ci
+   echo CommandBegin ci_cex
+   ci -d 1 -i -t 3600 -g $HintFile $InvFile
+   time
+   print_bdd_stats
+   echo CommandEnd ci_cex
+   quit
+   ----------------------------------------------------------------------
+
+   The variables and the aliases are defined by vis_reg by examining the fields
+   of the test case description in the design file. regression_test uses file
+   extensions to identify file types. (E.g., .ord indicates an order file in
+   "input_and_latch" format.) A full list of extensions is given below.
+
+   regression_test defines variables for all the file types actually available
+   for the experiment, and only for those. It also defines three aliases that
+   provide some flexibility in mixing different experiments in the same batch.
+
+   For instance, "read_model" is defined as either
+
+           read_blif_mv $BlifFile
+
+   or
+
+           read_blif $BlifFile
+
+   depending on whether the design list specifies a .mv file or a .blif file as
+   model file.
+
+   The definition of "order_vars" takes into account whether an order file is
+   available or not. Finally, the definition of "set_fairness" depends on
+   whether a .fair file is available. This allows one to mix model checking
+   experiments for which no fairness condition is specified to experiments that
+   do require fairness conditions.
+
+   When  bDefaultInitCommand is FALSE, the script is simply the preamble,
+   followed by the unchanged template, follows by the "quit" command, which is
+   always automatically added.
+
+   When bDefaultInitCommand is TRUE, regression_test also adds an automatically
+   generated "init" section between the preamble and the template. This default
+   section is equivalent to
+
+   echo CommandBegin init
+   read_model
+   flt
+   order_vars
+   part
+   time
+   print_bdd_stats
+   echo CommandEnd init
+
+   Notice  that  one  has  no  control over dynamic reordering during the
+   initialization phase if bDefaultInitCommand is TRUE.
+
+   The template should refer to the defined aliases and variables to tailor
+   itself to each test case. Notice, however, that one is not forced to use
+   "order_vars." If one wants to always use vis's static ordering algorithm,
+   (s)he can simply use "so" instead of "order_vars." Likewise, one can decide
+   to always ignore fairness constraints by not including "set_fairness."
+
+   On the other hand, it is usually a bad idea to explicitly include commands
+   like
+
+   read_blif_mv
+   read_blif
+   so -s input_and_latch
+   read_fairness
+
+   in the templates, because they limit the range of test cases to which they
+   can be applied.
+
+   As we said, the templates, and hence the scripts, are divided in sections.
+   Each section begins and ends with an "echo" command. These commands write
+   delimiters to the output file, which are used by vis_reg to define the scope
+   of  the  pattern  searches.  It is important that the tag specified in
+   corresponding pairs of CommandBegin and CommandEnd be the same.
+
+   The calls to "print_bdd_stats" are typically used to add to the output files
+   the information requested by the CompareItem declarations. It is a good idea
+   to specify timeouts for potentially expensive steps.
+
+   The design list file has one line for each test case. A master design list
+   is in ~hsv/vis/Regression/DesignList. Specific design lists can be obtained
+   by commenting out or deleting lines from this master list. One can also
+   create an entirely new list according to the following rules.
+
+   Lines starting with '#' are interpreted as comments and are skipped, as in
+   all files read by vis_reg.
+
+   A test case is a named collection of related files that can be used to run
+   one or more experiments. As mentioned before, each line consists of white
+   space-separated fields. The first is a (relative) path, while the second is
+   the  collection  name.  The  remaining fields specify the files in the
+   collection.
+
+   The smallest collection will specify one .mv or one .blif file. This file is
+   called the "model file," and should always appear in the third field of the
+   line. If the model file is the only file specified, one can run reachability
+   analysis, but not much more. Vis_reg understands the file extensions shown
+   in the following table. For each extension, the variable bound to the file
+   name and a short explanation are given.
+
+   .mv $BlifFile model file to be read with rlmv
+   .blif $BlifFile model file to be read with rl
+   .ord $OrdFIle order file to be read with so -s input_and_latch
+   .inv $InvFile invariant file to be read with ci
+   .ctl $CtlFile property file to be read with mc
+   .fair $FairFile fairness file to be read with rf
+   .hint $HintFile hint file to be read with the -g option of mc, ci, and rch
+
+   Only one file of each type can appear in the collection defining one test
+   case. If multiple property files, or different order files are available for
+   one model file, one has to create two test cases for that model. Different
+   models, on the other hand, can share property files, order files, and so on.
+   The master design list provides examples for both these situations.
+
+   It is not possible to specify both a .mv file and a .blif file for one test
+   case. There must be exactly one model file per test case.
+
+   As was mentioned before, it is important that the name of a test case be
+   unique in the entire batch used for a regression test. On the other hand,
+   several test cases may share the same directory, and often do when they have
+   some files in common.
+
+   The result summary created by regression_test is a LaTeX file consisting of
+   several tables. There is one table with performance stats for each section
+   of  the  output file. In addition, there is an optional counterexample
+   comparison table that summarizes PASS/FAIL information for the properties
+   and the length of counterexamples. For each failing property, the length of
+   the stem and the length of the cycle (if applicable) are reported.
+
+   Each  performance table consists of one column for the test case name,
+   followed  by  as many groups of three columns as there are CompareItem
+   declarations applicable to the section that the table summarizes.
+
+   Each group of three columns gives the data for the reference run, the data
+   for the new run, and the improvement. Vis_reg regards smaller as better.
+   Hence, the improvement is positive if the CPU time, memory occupation, and
+   so on, have decreased from the reference run to the new run. The improvement
+   is computed as
+
+   (value(ref) - value(new)) / value(ref) * 100.
+
+   Notice that this formula tends to make "new" look bad. for instance, if new
+   is twice as fast as ref, the improvement is 50%. If ref is twice as fast,
+   however, the "improvement" is -100%.
+
+   The results of each test case are stored in a separate directory, whose name
+   is obtained by concatenating ReferenceOutputDir (or NewOutputDir) with the
+   test case name. Each directory stores three files, whose names are given by
+   the test case name concatenated with .src, .out, and .err.
+
+   * test_case_name.src stores the script used to run vis.
+   * test_case_name.out stores what vis writes to vis_stdout.
+   * test_case_name.err stores what vis writes to vis_stderr.
+
+   One  has  to  be careful, because vis_reg will overwrite these results
+   directories without warning if run twice with the same ReferenceOutputDir or
+   NewOutputDir and bRefRun or bNewRun set to TRUE.
+
+   With '-s' option, you can create c-shell script file to be able to run
+   experiments in shell. We add this option to solve the problem that are
+   happened when your template file contains child-process by system call.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/res_verifyCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/res_verifyCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/res_verifyCmd.txt	(revision 14)
@@ -0,0 +1,234 @@
+
+  res_verify - Verifies a combinational circuit using residue arithmetic.
+     _________________________________________________________________
+
+   res_verify [-b] [-d <n>] [-h] -i <filename> [-m <filename>] [-n <filename>]
+   {-o <filename> | -O} [-s <filename>] [-t <timeOut>]
+
+   This command performs residue verification between two networks. The method
+   used is based on residue arithmetic and the Chinese Remainder theorem; it is
+   described in [1] ftp://vlsi.colorado.edu/pub/fmcad96.ps. Verification is
+   performed  by interpreting the outputs of the circuits as integers and
+   verifying the residues of the outputs with respect to a set of moduli. The
+   choice of moduli is directed by the Chinese Remainder Theorem in order to
+   prove  equivalence  of  the  two circuits. This method works well with
+   multipliers and possibly other arithmetic circuits (due to its dependence on
+   residue arithmetic). For the same reason, it is necessary to specify an
+   output order which determines how the outputs are interpreted as integers.
+   Discretion  should  be  exercised  in  applying this method to general
+   combinational circuits.
+
+   Residue verification is available only if vis is linked with the cu BDD
+   package.  (This is the default.) It reads both blif and blif-mv files.
+   However, it does NOT support multi-valued variables. Residue verification is
+   primarily for combinational verification, but may be applied to sequential
+   circuits with the same state encoding. The latch outputs are then considered
+   to be combinational inputs of the circuits and the latch inputs and reset
+   are considered to be combinational outputs of the circuits.
+
+   There are two ways to perform residue verification in this package. As a
+   first option, two files describing two networks, the specification and the
+   implementation, (in the same format, blif or blif-mv, see option -b) are
+   given in the command line; the procedure tries to verify the equivalence of
+   the combinational outputs as functions of the combinational inputs.
+
+   vis> res_verify -o network.order -i network1.blif -s network2.blif
+
+   In this case both networks are read in, flattened and the verification is
+   performed between the combinational outputs of both networks. The -i option
+   denotes the implementation file and the -s option denotes the specification
+   file. The -o option specifies the order of outputs for the circuits (See
+   Command Options below for detailed explanation).
+
+   A second way to perform the verification is as follows. The specification
+   network is taken from a hierarchy already read into VIS. Then the res_verify
+   command  compares that specification against an implementation network
+   obtained from the file in the command line. Any previous verification,
+   performed with the specification, can be used towards the next verification
+   task only if the same implementation circuit is being verified against and
+   the same number of outputs have been directly verified with sucess in the
+   previous attempt. The typical sequence of commands given to perform such
+   task would be:
+
+   vis> read_blifmv network1.mv
+   vis> flatten_hierarchy
+   vis> res_verify -o network.order -i network2.mv
+
+   If  the hierarchy has been read but no flattened network exists at the
+   current node, the command will return without doing anything. If one of the
+   networks used is the one in the current node in the hierarchy, then the
+   information  regarding the verification process will be stored in that
+   network.
+
+   Note:  It  is  important  to  keep the specification distinct from the
+   implementation because most parameters specified for the res_verify command
+   are with respect to the specification. For example, the output order is
+   specified with respect to the specification. The file that is read in first
+   in the second format, is considered to be the specification.
+
+   There is an option to directly verify some outputs by building the BDDs for
+   the corresponding outputs of the 2 circuits. In that case, if the user wants
+   to use an initial ordering, the only way to do it is the second method and
+   reading in the network, one may specify the initial order using static
+   order.
+
+   The   command  does  not  repeat  residue  verification  if  the  same
+   specification-implementation pair have been verified with success and the
+   same number of directly verified outputs have been verified in the previous
+   attempt.
+
+   Relevant flags to be set using the set command: 
+
+   residue_verbosity 
+          Default is 0, turns on verbosity to the desired level between 0 and
+          5.
+
+   residue_ignore_direct_verified_outputs 
+          Default 0 (FALSE). If 1, then ignores directly verified outputs
+          during residue verification.
+
+   residue_top_var 
+          Default "msb". The 2 possible values are "msb" and lsb"; this puts
+          the most/least significant bit near the top or bottom of the residue
+          decision diagram.
+
+   residue_autodyn_residue_verif 
+          Default 0 (FALSE). If 1, turns on dynamic reordering during residue
+          verification.
+
+   residue_residue_dyn_method 
+          Default "groupsift". Specifies the method for dynamic reordering
+          during residue verification. Other methods supported are "same" (same
+          as before), "none", "random", "randompivot", "sift", "siftconverge",
+          "symmsiftconverge", "symmsift", "window2", "window3", "window4",
+          "window2converge","window3converge","window4converge","groupsift",
+          "groupsiftconverge", "anneal", "genetic", "linear", "linearconverge",
+          "exact".
+
+   residue_autodyn_direct_verif 
+          Default 0 (FALSE). If 1, turns on dynamic reordering during direct
+          verification.
+
+   residue_direct_dyn_method 
+          Default "groupsift". Specifies the method for dynamic reordering
+          during direct verification. Other methods supported are "same" (same
+          as before), "none", "random", "randompivot", "sift", "siftconverge",
+          "symmsiftconverge", "symmsift", "window2", "window3", "window4",
+          "window2converge","window3converge","window4converge","groupsift",
+          "groupsiftconverge", "anneal", "genetic", "linear", "linearconverge",
+          "exact".
+
+   residue_layer_schedule 
+          Default "alap". This is a flag to specify the layering strategy of
+          the networks. The 2 options are "asap" (as soon as possible) and
+          "alap" (as late as possible).
+
+   residue_layer_size 
+          Default largest layer size in network. Specifies the maximum layer
+          size that can be composed in (relevant for vector composition only).
+
+   residue_composition_method 
+          Default "vector". Specifies the composition method to be used in
+          composing the network into the residue ADD. The options are "vector",
+          "onegate", "preimage" and "superG".
+
+   Command Options: 
+
+   -b
+          If this option is specified, the specification and the implementation
+          files read are considered to be in blif-mv format. Default is blif
+          format.
+
+   -d n
+          This option specifies the number of outputs to be directly verified.
+          That is, for n least significant outputs of the circuit, this command
+          performs like comb_verify. The actual outputs are read off the output
+          order array. Since the output order array is specified starting with
+          the MSB, the number of directly verified outputs will be a chunk of
+          the bottom part of the output order array. The option "-d all" sets
+          the  number  of  directly  verified  outputs  to  the number of
+          combinational outputs in the circuit i.e., all outputs are directly
+          verified. The direct verification for small BDD sizes is faster and
+          overall  reduces  the  number  of  primes to be used in residue
+          verification. In general, one output is checked at a time against the
+          corresponding output of the other network and consequently , this
+          method may be fast and use less memory resources.
+          IMPORTANT: It is possible to specify an initial order for the direct
+          verification. This is done by reading in the specification file and
+          using static_order to specify the initial order. The implementation
+          will get the same order as the specification. When specifying the
+          initial order, one must be careful not to specify the -s option in
+          the res_verify command. The -s option reads in the specification file
+          again and the initial order is lost.
+
+   -h
+          Print the command usage.
+
+   -i <filename>
+          Implementation network to perform verification against. The file must
+          be in blif format unless -b is specified, in which case the file is
+          taken to be in blif-mv format. The blif format is the default.
+
+   -m <filename>
+          Optional file name specifying the matching pair of output names
+          between the two networks. If not specified, it is assumed that all
+          outputs have identical names. This option is useful when verifying
+          two circuits whose output names do not match. The file will give
+          pairs of the form name1 name2 to be considered as corresponding
+          outputs in the verification process. In each pair, name1 may belong
+          to the specification and name2 to the implementation or vice-versa.
+          The matching procedure is not capable of dealing with some special
+          situations. For example, when two outputs, one of each network have
+          the same name, they must correspond to the same output. Partial
+          orders may not be specified.
+
+   -n <filename>
+          Optional  file name specifying the matching pair of input names
+          between the two networks. If not specified, it is assumed that all
+          inputs have identical names. This option is useful when verifying two
+          circuits whose input names do not match. The file will give pairs of
+          the form name1 name2 to be considered as corresponding inputs in the
+          verification  process.  In  each  pair, name1 may belong to the
+          specification and name2 to the implementation or vice-versa. The
+          matching  procedure is not capable of dealing with some special
+          situations. For example, when two inputs, one of each network have
+          the same name, they must correspond to the same input. Partial orders
+          may not be specified.
+
+   -o <filename>
+          Required file specifying output order, starting with the MSB. The
+          file must be a list of output names separated by spaces. The list
+          must belong to the specification network and must contain a full
+          order i.e., must contain all the combinational output names. It is
+          advisable to use the -o option as far as possible to specify the
+          order of the outputs.See also -O option.
+
+   -O
+          This option specifies whether the res_verify command should generate
+          a default order for the outputs. If the -o option is not used, this
+          option must be specified. The default order generated is random and
+          is NOT the same as the input files. The set of outputs for the output
+          order may be generated by using the print_network command to write
+          the network into a file and extract the node name from the lines
+          containing the word "comb-output". The set of outputs can then be
+          ordered as required.
+          It is advisable to use the -o option as far as possible to specify
+          the order of the outputs. The -o option overrides the -O option. See
+          also -o option.
+
+   -s <filename>
+          Specification  network.  This  network  will  be  taken  as the
+          specification of the circuit. The result of the computation will be
+          stored in this network. If this network is not provided, the current
+          node of the hierarchy will be taken. The file must contain a blif
+          description of a circuit unless the option -b is specified, in which
+          case the file is considered in blif-mv format. If two networks are
+          specified  in the command line, both of them must have the same
+          format, either blif or blif-mv. The blif format is the default.
+
+   -t <timeOut >
+          Execution time in seconds allowed for verification before aborting.
+          The default is no limit.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/reset_fairnessCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/reset_fairnessCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/reset_fairnessCmd.txt	(revision 14)
@@ -0,0 +1,17 @@
+
+  reset_fairness - reset the fairness constraint
+     _________________________________________________________________
+
+   reset_fairness [-h]
+
+   Remove any existing fairness constraint associated with the FSM of the
+   flattened network, and impose a single constraint, TRUE, indicating that all
+   states are "accepting".
+
+   Command options:
+
+   -h
+          Print the command usage.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/restruct_fsmCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/restruct_fsmCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/restruct_fsmCmd.txt	(revision 14)
@@ -0,0 +1,135 @@
+
+  restruct_fsm - Restructre the STG of a finite state machine to reduce power
+  dissipation.
+     _________________________________________________________________
+
+   restruct_fsm [-D <fileHead>] [-d <divMethod>] [-E] [-F <factMethod>] [-f
+   <probFile>] [-h] [-N] [-o <orderFile>] [-p <string>] [-s <restrMethod>] [-t
+   <seconds>] [-v]
+
+   This command implements an STG restructuring algorithm that exploits the
+   existence  of  equivalent  states  to  decrease power dissipation, not
+   necessarily  by  collapsing the equivalence states, but by redirecting
+   transitions in the state transition graph (STG). This algorithm is based on
+   monolithic transition relation. The complexity of the algorithm in general
+   increases with an increase in the size of the STG. The number of states and
+   edges  in the STG are exponential in the number of state variables and
+   primary inputs. The memory utilization is not necessarily exponential due to
+   symbolic  representation of the STG. For more details see, "A Symbolic
+   Algorithm for Low-Power Sequential Synthesis", ISLPED 97. This command works
+   only if VIS is compiled with CUDD package. The algorithm can handle circuits
+   described in both BLIF and BLIF-MV format. However, multi-valued variables
+   are  not  supported.  Also,  the  final  synthesized  circuit (network
+   implementation of the restructured STG) is available only in BLIF format.
+   The sequential circuit should have a single initial state. A network should
+   have been created for the circuit and its primary inputs and state variables
+   assigned BDD ids prior to the invocation of this command. A network can be
+   created by the command flatten_hierarchy and command static_order assigns
+   BDD ids to the input and state variables. The command proceeds by creating
+   BDDs for the outputs and next state functions. An FSM data structure is then
+   created on which subsequent operations are performed. After the STG is
+   restructured a new circuit is synthesized by symbolic factorization based on
+   Zero-Suppressed Decision Diagrams (ZDDs). The final synthesized circuit is a
+   file in BLIF format with ".ml.blif" as the extension.
+
+   The typical command flow in vis is the following:
+   vis> read_blif foo.blif
+   vis> flatten_hierarchy
+   vis> static_order
+   vis> dynamic_var_ordering -e sift
+   vis> restruct_fsm
+
+   In the above case example, the final synthesized circuit is MODEL.ml.blif if
+   the name of the design in foo.blif is MODEL.
+   Command options: 
+
+   -A
+          Allow realignment (during symbolic factorization) of ZDDs after BDD
+          reordering and vice versa. This option is effective when only one of
+          the BDD or ZDD variable reordering is enabled.
+
+   -D <fileHead>
+          Specify the output file name for synthesized circuit. File extension
+          is not necessary. By default, the model name of the circuit is used.
+          For example, -D foobar, will result in foobar.ml.blif
+
+   -d <divMethod>
+          Choose a divisor. See synthesize_network for more details.
+
+   -E
+          Print the number of equivalence classes in the FSM.
+
+   -F <probFile>
+          File with primary input probabilities, one per line. input_name
+          <probability>
+
+   -f <factMethod>
+          Choose a method for factorization. See synthesize_network for more
+          details.
+
+   -h
+          Print command usage.
+
+   -i <string>
+          Specify the prefix to be used to generate names for internal nodes
+          during synthesis. By default, the prefix is "_n".
+
+   -N
+          Expand  the  reachable  set R to include those states which are
+          equivalent to R but not reachable. The default is not to include such
+          states.
+
+   -o <orderFile>
+          File to output BDD variable ordering after the restructured circuit
+          is synthesized.
+
+   -R <value>
+          Allow  reordering  in  BDD and/or ZDD variables during symbolic
+          factorization stage.
+
+          0 : (default) No reordering neither in BDD nor in ZDD.
+
+          1 : Allows reordering only in BDD, not in ZDD.
+
+          2 : Allows reordering only in ZDD, not in BDD.
+
+          3 : Allows reordering both in BDD and in ZDD.
+
+   -s <heuristic>
+          Heuristic to perform restructuring. Consider a fragment of an STG
+          containing states A,B and C and an edge from A to B. Let B and C be
+          equivalent. Since B and C are equivalent, it is possible to change
+          the transition between A and B to A and C. In the more general case,
+          the choice can be driven by different cost constraints. The following
+          are the heuristics:
+          ham  : Hamming distance based heuristic. An edge is chosen that
+          reduces the Hamming distance (or state bit transitions) between the
+          states.
+          fanin  :  Fanin  oriented  heuristic. A representative from the
+          equivalence class is chosen that reduces the total average state bit
+          switching on the incoming edges.
+          faninout : Fanin-Fanout oriented heuristic. A representative from the
+          equivalence class is chosen that reduces the total average state bit
+          switching on the incoming as well as outgoing edges.
+          cproj : A simple C-Projection. A representative from the equivalence
+          class is chosen which is closest to the initial state. The distance
+          d(x,y) is defined as:
+          sum_{i=0}^{N-1}(|x_i - y_i| cdot 2^{N-i-1}).
+
+   -T
+          Try to share more nodes during symbolic factorization. Existing
+          divisors are checked for potential reuse before extracting divisors
+          from the current boolean function.
+
+   -t <seconds>
+          Time in seconds allowed to complete the command. If the computation
+          time goes above that limit, the process is aborted. The default is no
+          limit.
+
+   -v
+          Turn on verbosity.
+
+   See also command : synthesize_network
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/seq_verifyCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/seq_verifyCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/seq_verifyCmd.txt	(revision 14)
@@ -0,0 +1,79 @@
+
+  seq_verify - verify the sequential equivalence of two flattened networks
+     _________________________________________________________________
+
+   seq_verify [-b] [-f <filename>] [-h] [-p <partition method>] [-t <timeOut>]
+   [-B] [-i] [-r] <filename> [<filename>]
+
+   Please read the documentation for the command comb_verify before reading on.
+   The  concepts  of roots and leaves in this command are the same as for
+   comb_verify, except for an added constraint: the set of leaves has to be the
+   set of all primary inputs. This obviously produces the constraint that both
+   networks have the same number of primary inputs. Moreover, no pseudo inputs
+   should be present in the two networks being compared. The set of roots can
+   be an arbitrary subset of nodes.
+
+   The  command  verifies  whether  any  state,  where  the values of two
+   corresponding roots differ, can be reached from the set of initial states of
+   the product machine. If this happens, a debug trace is provided.
+
+   The sequential verification is done by building the product finite state
+   machine.
+
+   The command has two execution modes, just as for comb_verify. In the first
+   mode, two BLIF-MV files are given as arguments to the command:
+
+  vis> seq_verify foo.mv bar.mv
+  
+
+   In the second mode, a single BLIF-MV file is taken. This is network2. It is
+   assumed that network1 is from a hierarchy that has already been read in. If
+   a network is present at the current node (i.e. flatten_hierarchy has been
+   executed), it is used for verification; otherwise the command does nothing.
+
+  vis> read_blifmv foo.mv
+  vis> flatten_hierarchy
+  vis> seq_verify bar.mv
+  
+
+   Command options:
+
+   -b
+          Specifies that the input files are BLIF files.
+
+   -f <filename>
+          Provides the correspondence between the leaves and roots of network1
+          and network2. leaves has to be the set of primary inputs of the
+          networks. roots can be any subset of nodes. If this option is not
+          used, it is assumed that the correspondence is by name, and that the
+          roots are the combinational outputs.
+
+   -h
+          Print the command usage.
+
+   -p <partition method>
+          Specifies the partitioning method for the product machine. Supported
+          methods  are  "total",  "partial", and "inout" (see the command
+          build_partition_mdds for more information). If this option is not
+          specified, then the default method "inout" is used.
+
+   -t <timeOut>
+          Time in seconds allowed to perform equivalence checking. The default
+          is infinity.
+
+   -B
+          Use backward image computation to traverse the state space of the
+          product machine. By default, forward image computaion is used.
+
+   -i
+          Print BDD statistics. This is the only way to see BDD stastics during
+          this  command.  print_bdd_stats after this command doesn't show
+          information related to this command.
+
+   -r
+          Enable  BDD  reordering during the equivalence check. Note that
+          dynamic_var_ordering has no effect on whether reordering is enabled
+          during the execution of seq_verify.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/setCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/setCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/setCmd.txt	(revision 14)
@@ -0,0 +1,215 @@
+
+  set - set an environment variable
+     _________________________________________________________________
+
+   set [-h] [<name>] [<value>]
+
+   A variable environment is maintained by the command interpreter. The "set"
+   command sets a variable to a particular value, and the "unset" command
+   removes the definition of a variable. If "set" is given no arguments, it
+   prints the current value of all variables.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   <name>
+          Variable name
+
+   <value>
+          Value to be assigned to the variable.
+
+   Interpolation  of variables is allowed when using the set command. The
+   variables  are referred to with the prefix of '$'. So for example, the
+   following can be done to check the value of a set variable:
+   vis> set foo bar
+   vis> echo $foo
+   bar
+   The last line "bar" will the output produced by vis.
+
+   Variables can be extended by using the character ':' to concatenate values.
+   For example :
+   vis> set foo bar
+   vis> set foo $foo:foobar
+   vis> echo $foo
+   bar:foobar
+   The variable foo is extended with the value foobar .
+
+   Whitespace  characters may be present within quotes. However, variable
+   interpolation lays the restriction that the characters ':' and '/' may not
+   be used within quotes. This is to allow for recursive interpolation. So for
+   example, the following is allowed
+   vis> set "foo bar" this
+   vis> echo $"foo bar"
+   this
+   The last line will be the output produced by vis.
+   But  in  the  following, the value of the variable foo/bar will not be
+   interpreted correctly:
+
+   vis> set "foo/bar" this
+   vis> echo $"foo/bar"
+   foo/bar
+   If a variable is not set by the "set" command, then the variable is returned
+   unchanged.
+
+   Different commands use environment information for different purposes. The
+   command interpreter makes use of the following parameters:
+
+   autoexec
+          Defines a command string to be automatically executed after every
+          command processed by the command interpreter. This is useful for
+          things like timing commands, or tracing the progress of optimization.
+
+   open_path
+          "open_path" (in analogy to the shell-variable PATH) is a list of
+          colon-separated strings giving directories to be searched whenever a
+          file is opened for read. Typically the current directory (.) is first
+          in   this   list.   The   standard  system  library  (typically
+          $VIS_LIBRARY_PATH) is always implicitly appended to the current path.
+          This provides a convenient short-hand mechanism for reaching standard
+          library files.
+
+   vis_stderr 
+          Standard error (normally stderr) can be re-directed to a file by
+          setting the variable vis_stderr.
+
+   vis_stdout
+          Standard output (normally stdout) can be re-directed to a file by
+          setting the variable vis_stdout.
+
+   Building MDDs for the network makes use of following setting:
+
+   partition_method
+          This  parameter  is  used to select the method for creating the
+          partition.  The  vertices  of  a  partition  correspond  to the
+          combinational inputs, combinational outputs, and any intermediate
+          nodes used. Each vertex has a multi-valued function (represented by
+          MDDs) expressing the function of the corresponding network node in
+          terms of the partition vertices in its transitive fanin. Hence, the
+          MDDs of the partition represent a partial collapsing of the network.
+          The possible values of partition_method are:
+
+        inout
+                Expresses  the  combinational  outputs  in  terms  of the
+                combinational inputs. This is the default partitioning method.
+
+        total
+                The partition built is isomorphic to the combinational part of
+                the network. The function of each node is expressed in terms of
+                its immediate fanins.
+
+        frontier
+                The partition built contains the combinational part of the
+                network as well as vertices corresponding to some intermediate
+                nodes. These vertices are generated to control the MDD sizes of
+                the combinational outputs. The number of intermediate variables
+                can be controlled by the parameter "partition_threshold". The
+                method "inout" and "total" are special cases of this method
+                (corresponding to a partition_threshold of infinity and 0
+                respectively).
+
+   partition_threshold
+          This parameter is used in conjuction with the selection of "frontier"
+          as partition method. This determines the threshold at which a new MDD
+          variable is created in the partition.
+
+   Image computation makes use of following settings:
+
+   image_method
+          The "image_method" parameter is used to control the image method used
+          in various symbolic analysis techniques. Currently, two image methods
+          are  implemented. Use "set image_method <method>" to choose the
+          appropriate method.
+
+        monolithic
+                This is the most naive approach possible. However, this method
+                is not suitable for circuits with more than 20 latches.
+
+        tfm
+                This is the pure transition function method. This method is
+                supposed not to be used in general fixpoint computations.
+                Approximate  traversal  is an application of this method.
+                Basically this method is made as a part of hybrid method. For
+                more  detailed options, see the help of print_tfm_options
+                command.
+
+        hybrid
+                This is a hybrid method combining transition relation and
+                function  methods. Transition relation method is based on
+                conjunction  of  partitioned transition relation, whereas
+                transition function method is based on splitting on an input or
+                output variable recursively. The hybrid method choose either
+                splitting or conjunction at each recursion dynamically using
+                the dependence matrix. For details, refer to the paper "To
+                split or to Conjoin: The Question in Image Computation" by
+                In-Ho Moon, James Kukula, Kavita Ravi, and Fabio Somenzi,
+                DAC'00.  Also  for more detailed options, see the help of
+                print_hybrid_options command.
+
+        iwls95
+                This technique is based on the early variable quantification
+                and  related  heuristics of Ranjan, et al. "Efficient BDD
+                Algorithms for FSM Synthesis and Verification", IWLS 1995.
+                First,  from  the  given multivalued functions, bit level
+                relations are created. These relations are then clustered based
+                on   the   value   of   threshold   value  controlled  by
+                image_cluster_size parameter. Next the relations are ordered
+                for early variable quantification. This ordering is controlled
+                by the parameters image_W1, image_W2, image_W3, and image_W4.
+
+        mlp
+                This technique is based on minimizing the variable lifetime in
+                the conjunctions of the partitioned transition relation. The
+                method  is called MLP (Minimal Lifetime Permutation). For
+                details, refer to the paper "Border-Block Triangular Form and
+                Conjunction Schedule in Image Computation" by In-Ho Moon, Gary
+                Hachtel, and Fabio Somenzi, FMCAD'00. Also for more detailed
+                options, see the help of print_mlp_options command.
+
+   image_farside_method
+          This parameter is used in conjunction with the selection of iwls95,
+          mlp,  or  linear  as the image_method. When the value is 1, the
+          compositional far side image computation approach is enabled; when
+          the value is 0, this feature is disabled (default).
+
+   image_cluster_size
+          This parameter is used in conjunction with the selection of iwls95 as
+          the image_method. The value of this parameter is used as threshold
+          value for creating clusters. The default value of this parameter is
+          5000 which has been empirically proved to be an optimal value.
+
+   image_W1, image_W2, image_W3, image_W4
+          These parameters are used in conjunction with the selection of iwls95
+          as the image_method. They control the weights associated with various
+          factors in ordering the clusters. The default values are 6, 1, 1, and
+          2 respectively. For a detailed description of these parameters,
+          please refer to the paper in IWLS'95 proceedings.
+
+   image_verbosity
+          Sets the verbosity mode (0 minimum to 4 maximum), for the image
+          method iwls95.
+
+   image_minimize_method <method>
+          Sets a minimization method to minimize the transition relation or an
+          image/preimage computaion with a set of dont-care states.
+
+          Methods: 0 : restrict (default).
+
+          1 : constrain
+
+          2 : compact (currently supported by only CUDD)
+
+          3 : squeeze (currently supported by only CUDD)
+
+   scc_method <method>
+          Sets the symbolic method to enumerate strongly connected components
+          (SCCs). Symbolic SCC enumeration is the core computation in LTL and
+          fair-CTL model checking.
+
+          Methods: lockstep : the O(nlogn) time LockStep algorithm (default).
+
+          Methods: linearstep : the linear time symbolic algorithm (default).
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/set_bdd_parametersCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/set_bdd_parametersCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/set_bdd_parametersCmd.txt	(revision 14)
@@ -0,0 +1,31 @@
+
+  set_bdd_parameters - Creates a table with the value of all the flags
+  currently active in VIS and calls the function bdd_set_parameters with the
+  manager of the current place in the hierarchy and the table.
+     _________________________________________________________________
+
+   set_bdd_parameters [-h][-s]
+
+   The command obtains the bdd manager of the current point in the hierarchy.
+   Given  this  manager  and the set of pairs (variable,value) of the VIS
+   environment, the function sets specific BDD parameters to the given values.
+   This command works in conjunction with print_bdd_stats.
+
+   Print_bdd_stats first prints a report of the parameters and statistics of
+   the current bdd_manager. By using the command "set", the user may modify the
+   value of any of the parameters of the underlying bdd package. The way to do
+   it is by setting a value in the variable BDD.parameter name where parameter
+   name is the name of the parameter exactly as printed by the print_bdd_stats
+   command. In order to "re-program" the underlying bdd package this command
+   must be invoked.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   -s
+          Print the bdd parameter and statistics after the modification.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/simulateCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/simulateCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/simulateCmd.txt	(revision 14)
@@ -0,0 +1,132 @@
+
+  simulate - simulate the flattened network
+     _________________________________________________________________
+
+   simulate [ -I <0/1> ] [ -O <0/1> ] [ -P <0/1> ] [ -S <0/1> ] [ -h ] [ -i
+   <vectors_file> ] [ -n <vectors_number> ] [ -o <output_file> ] [ -p <0|1> ] [
+   -v ]
+
+   Simulates  a  network with a set of input vectors. Before calling this
+   command,  the  user  should  create  a  partition  (using  the command
+   build_partition_mdds). The simulation vectors can be provided by the user
+   (using -i vectors_file), or generated randomly.
+
+   Command options:
+
+   -I <0/1>
+          This option controls the printing the primary input variables. 0
+          implies printing is disabled, enabled otherwise. The default value is
+          1. The output file generated with this flag set to 0 may not be used
+          as input file for simulation (if there are some primary inputs to the
+          system).
+
+   -O <0/1>
+          This option controls the printing the primary output variables. 0
+          implies printing is disabled, enabled otherwise. The default value is
+          1.
+
+   -P <0/1>
+          This option controls the printing the pseudo input variables. 0
+          implies printing is disabled, enabled otherwise. The default value is
+          1. The output file generated with this flag set to 0 may not be used
+          as input file for simulation (if there are some pseudo-inputs to the
+          system).
+
+   -S <0/1>
+          This option controls the printing the state variables. 0 implies
+          printing is disabled, enabled otherwise. The default value is 1.
+
+   -h
+          Print a help message that details all options.
+
+   -i <vectors_file>
+          Give the simulation vector file name. If this option is not used,
+          vectors are generated randomly.
+
+   -n <N>
+          Simulate N vectors. This option should be used if vectors_file is not
+          specified. If a vectors_file is given, and if there are more than N
+          vectors in the file, only the first N vectors are simulated.
+
+   -o <output_file>
+          Give  the  name of a file where the simulation result should be
+          written.  If  this option is not used, the simulation result is
+          directed to standard output.
+
+   -p <0|1|2>
+          This option is available only with random vector generation mode, and
+          affects how values for pseudo-inputs (non-deterministic constants)
+          are generated. 0: pseudo-inputs are treated by user. 1: pseudo-inputs
+          are treated randomly. 2: pseudo-inputs are treated by choosing the
+          first possibility.
+
+   -v
+          Enable verbose mode. Prints CPU time usage.
+
+   The vectors_file has two main parts:
+
+   Declarations:
+
+        Inputs list:
+                Gives an ordering of the primary and pseudo inputs. Every input
+                must be reported in this field.
+
+        Latches list:
+                Gives an ordering of the latches. Every latch must be reported
+                in this field.
+
+        Outputs list:
+                Gives an ordering of the outputs. This list may be incomplete.
+                Simulation is performed only on outputs present in this list.
+
+        Initial state:
+                Value of an initial state. This value is given with respect to
+                the latch ordering.
+
+   Simulation Vectors:
+          One vector per line according to the given order of inputs.
+
+   Final State:
+          Prints the value of state variables after the last simulation vector
+          is applied.
+
+   An example of a simulation vectors file is:
+   # ----> Declarations
+       .inputs X1 X2
+       .latches L1 L2
+       .outputs O
+       .initial green 0
+       .start_vectors
+       # ----> Vectors
+       0 1
+       1 0
+       1 1
+
+   Note the keywords: .inputs, .latches, .outputs, .initial, .start_vectors. A
+   line started by a '#' is a comment line.
+
+   The simulation result is printed either in a file (using -o output_file) or
+   to standard output. It has the same format as vectors_file with additional
+   fields for latches and outputs. Here is the result of simulation on last
+   vectors_file example:
+   .inputs X1 X2
+       .latches L1 L2
+       .outputs O
+       .initial green 0
+       .start_vectors
+       #input; current_state; output
+       0 1 ; green 0 ; 0
+       1 0 ; blue 0 ; 1
+       1 1 ; red 1 ; 1
+       #Final State : green 1
+
+   Note that each input line has been extended by its simulation result with
+   current states and outputs listed in order. The output_file can be read by
+   simulate as vectors_file (latches and outputs values are ignored). When
+   starting simulation a good trick is to run simulate with random vectors
+   generation  mode;  the  resulting can be used as a template to write a
+   vectors_file. For example, executing "simulate -n 1 -o foo.output" will
+   generate a representative file.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/sourceCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/sourceCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/sourceCmd.txt	(revision 14)
@@ -0,0 +1,72 @@
+
+  source - execute commands from a file
+     _________________________________________________________________
+
+   source [-h] [-p] [-s] [-x] <file> [<args>]
+
+   Reads and executes commands from a file.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   -p
+          Print a prompt before reading each command.
+
+   -s
+          Silently ignore an attempt to execute commands from a nonexistent
+          file.
+
+   -x
+          Echo each command before it is executed.
+
+   <file>
+          File name
+
+   Arguments on the command line after the filename are remembered but not
+   evaluated. Commands in the script file can then refer to these arguments
+   using the history substitution mechanism.
+
+   EXAMPLE:
+
+   Contents of test.scr:
+
+  read_blif_mv %:2
+  init_verify
+  simulate -n 10
+  
+
+   Typing  "source test.scr lion.mv" on the command line will execute the
+   sequence
+
+  read_blif_mv lion.mv
+  init_verify
+  simulate -n 10
+  
+
+   (In  this  case  %:0  gets "source", %:1 gets "test.scr", and %:2 gets
+   "lion.mv".)  If  you type "alias st source test.scr" and then type "st
+   lion.blif bozo", you will execute
+
+  read_blif_mv bozo
+  init_verify
+  simulate -n 10
+  
+
+   because "bozo" was the second argument on the last command line typed. In
+   other words, command substitution in a script file depends on how the script
+   file  was  invoked.  Switches  passed to a command are also counted as
+   positional parameters. Therefore, if you type "st -x lion.mv bozo", you will
+   execute
+  read_blif_mv lion.mv
+  init_verify
+  simulate -n 10
+  
+
+   To pass the "-x" switch (or any other switch) to "source" when the script
+   uses positional parameters, you can define an alias. For instance, "alias
+   srcx source -x".
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/spfd_pdloCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/spfd_pdloCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/spfd_pdloCmd.txt	(revision 14)
@@ -0,0 +1,162 @@
+
+  spfd_pdlo - Perform SPFD-based simultaneous placement and logic optimization.
+     _________________________________________________________________
+
+   spfd_pdlo [-D <depth>] [-h] [-n <file>] [-r] [-t <sec>] [-v <n>] [-w <file>]
+   net_file arch_file place_file route_file
+
+   This command performs SPFD-based combined logic and placement optimization
+   of combinational circuits mapped to LUT-based FPGAs to improve circuit area
+   and speed. The flexibilities in the circuit are represented by SPFDs. The
+   following references explain in detail the theory behind SPFDs.
+
+   S. Yamashita, H. Sawada, and A. Nagoya. A new method to express functional
+   permissibilities for LUT based FPGAs and its applications. In International
+   Conference on Computer Aided Design, pages 254-261, 1996.
+
+   Subarnarekha Sinha and Robert K. Brayton. Implementation and use of SPFDs in
+   optimizaing Boolean networks. In International Conference on Computer Aided
+   Design, 1998.
+
+   The  command  implements  a technique that tightly links the logic and
+   placement optimization steps. The algorithm is based on simulated annealing.
+   Two types of moves, directed towards global reduction in the cost function
+   (total wire length), are accepted by the simulated annealing algorithm: (1)
+   wire removal/replacement, and (2) swapping of a pair of blocks in the FPGA.
+   Feedback from placement is valuable in making an informed choice of a target
+   wire during logic optimization moves. The logic optimization steps performed
+   are similar to those of spfd_pilo, except that the placement information is
+   now used instead of the fanout count. More information on this technique can
+   be found in :
+
+   Balakrishna Kumthekar and Fabio Somenzi. Power and delay reduction via
+   simultaneous  logic  and  placement  optimization in FPGAs. In Design,
+   Automation and Test in Europe, 2000.
+
+   The command produces a placement file which is used by VPR for routing.
+
+   This command can be used only if VIS is linked with VPR 4.22 (Versatile
+   Place and Route), the FPGA place and route tool [1]VPR, from the University
+   of Toronto. Please follow the instructions provided in the release notes to
+   use VPR with VIS. You can also contact kumtheka@avanticorp.com if you need
+   more help.
+
+   Before calling this command a network should be created for the design (use
+   flatten_hierarchy) and MDD ids for every node in the network should be
+   created (static_order -o all -n append). Dynamic variable ordering (dvo -e
+   sift) can be enabled to reduce BDD sizes.
+
+   Command options:
+
+   -D <depth>
+          A cluster is computed which includes nodes within the specified
+          'depth'. The default value is 1.
+
+   -n <file>
+          File to output the optimized circuit in VPR's .net format.
+
+   -r
+          Do not reprogram LUTs if no structural changes have been performed
+          with in the cluster, i.e., if no nodes or wires have been removed do
+          not  change  the local implementation of LUTs even if alternate
+          implementations are availabe from SPFD information. The default is to
+          reprogram.
+
+   -t <sec>
+          Time in seconds allowed to complete the command. If the computation
+          time goes above that limit, the process is is aborted. The default is
+          no limit.
+
+   -v <n>
+          Verbosity level.
+
+   -w <file>
+          File to output final optimized circuit.
+
+   The following is needed by VPR:
+
+   net_file
+          The description of the circuit in the .net format. Logic optimization
+          uses the circuit described in .BLIF format whereas VPR needs the same
+          circuit  described in .net format. VPack (which comes with VPR)
+          converts a .BLIF format into a .net format.
+
+   arch_file
+          Architecture description file for FPGAs. More information can be
+          found in VPR's manual.
+
+   place_file
+          File to dump placement information.
+
+   route_file
+          File to dump routing information.
+
+          Relevant flags to be set by the set command:
+
+        spfd_pdlo_logic_move_freq "r1 m1 r2 m2 ..."
+                Perform m1 logic moves whenever the rate of acceptance during
+                simulated annealing is greater than or equal to r1, and so on.
+                r1, r2, r3 ... should be monotonically decreasing, else the
+                results would be unpredictable. 0 <= ri <= 1.0. For example:
+
+                set spfd_pdlo_logic_move_freq "0.8 0 0.5 5 0.2 10"
+
+                In the above logic schedule, zero logic moves per temperature
+                will be performed when the rate of acceptance is above 0.8, 5
+                logic moves between 0.8 and 0.5, 10 moves between 0.5 and 0.2.
+                As no value is specified for acceptance rate close to 0.0, by
+                default, 1 logic move per temperature will be performed. In
+                this example it will be 1 logic move between 0.2 and 0.0. The
+                quotes around the schedule are necessary.
+
+        spfd_repl_rem
+                If no, the logic optimization performs only wire removal. If
+                yes, both wire replacement and removal are performed.
+
+        spfd_pdlo_timing
+                If set, use timing driven method to remove or replace wires on
+                the critical path. If not set, use bounding box of the wires as
+                the cost function.
+
+        spfd_pdlo_timing_nodeorwire
+                Remove/replace all the wires belonging to the most critical
+                net.  If not set, attempt to remove/replace only the most
+                critical wire.
+
+        spfd_pdlo_out_crit_nets_first
+                Output the circuit in VPR's .net format with the nets appearing
+                in the increasing order of their slack. If not set, the initial
+                net order specified in the original circuit's .net file is
+                used. The file is specified with -n option. This variable is
+                valid only if spfd_pdlo_timing is set.
+
+        spfd_pdlo_remap_clb_array
+                During logic optimization, due to the removal of nodes in the
+                network, the current size of FPGA might be bigger than it is
+                necessary. In such cases, if this variable is set, the size of
+                the FPGA is reduced to fit the current logic network.
+
+          Relevant flags that are options to VPR:
+
+          For detailed information on the following options please refer to the
+          manual that accompanies VPR source distribution.
+
+        vpr_nodisp
+        vpr_fix_pins
+        vpr_nx
+        vpr_ny
+        vpr_fast
+        vpr_init_t
+        vpr_alpha_t
+        vpr_exit_t
+        vpr_inner_num
+        vpr_seet
+        vpr_place_cost_exp
+        vpr_place_chan_width
+            __________________________________________________________
+
+          Last updated on 20100410 00h02
+
+References
+
+   1. http://www.eecg.toronto.edu/~vaughn/vpr/vpr.html
Index: vis_dev/vis-2.3/share/help/spfd_piloCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/spfd_piloCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/spfd_piloCmd.txt	(revision 14)
@@ -0,0 +1,117 @@
+
+  spfd_pilo - Perform SPFD-based placement independent logic optimization.
+     _________________________________________________________________
+
+   spfd_pilo  [-a  <[0,1]>] [-D <depth>] [-f <file>] [-h] [-i <freq>] [-p
+   <percent>] [-r] [-S <n>] [-t <sec>] [-v <n>] [-w <file>]
+
+   This command performs SPFD-based wire removal/replacement and reprogramming
+   of combinational circuits mapped to LUT-based FPGAs to reduce the number of
+   wires  and  nodes in the circuit. The flexibilities in the circuit are
+   represented by SPFDs. The following references explain in detail the theory
+   behind SPFDs.
+
+   S. Yamashita, H. Sawada, and A. Nagoya. A new method to express functional
+   permissibilities for LUT based FPGAs and its applications. In International
+   Conference on Computer Aided Design, pages 254-261, 1996.
+
+   Subarnarekha Sinha and Robert K. Brayton. Implementation and use of SPFDs in
+   optimizaing Boolean networks. In International Conference on Computer Aided
+   Design, 1998.
+
+   Instead of computing the flexibilities for every node in the network at
+   once, the algorithm computes the flexibilities for one cluster at a time.
+   Working with clusters allows us to avoid the BDD explosion problem and
+   hence, handle large circuits. The SPFDs are computed for the cluster and the
+   cluster nodes are reprogrammed based on the flexibility derived. Switching
+   activity is used to drive the choice of alternate function to be implemented
+   at the node. In the absence of switching activity information, the function
+   that  can  reduce support of the node can be chosen (not implemented).
+   Currently, an arbitrary choice is made from the flexibilities provided by
+   SPFDs. (-S 0, -S 2, and -S 4)
+
+   Before calling this command a network should be created for the design (use
+   flatten_hierarchy) and MDD ids for every node in the network should be
+   created (static_order -o all -n append, for example). Dynamic variable
+   ordering (dvo -e sift) can be enabled to reduce BDD sizes.
+
+   Command options:
+
+   -a <alpha>
+          A convex combination of switched capacitance (switching activity *
+          fanout count, SWC) and topological depth is used to sort the fanin
+          nodes during SPFD computation. alpha is between 0 and 1.0. The cost
+          function is alpha*SWC + (1.0-alpha)*topDepth. The default value is
+          0.5.
+
+   -D <depth>
+          A cluster is computed which includes nodes within the specified
+          'depth'. The default value is 1.
+
+   -f <file>
+          File with simulation vectors. The file format is as below. The format
+          is simple but strict and hence, few checks are made.
+
+          .i c n d o e p f q g r h s i t j u k a l b m
+          .s
+          0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 1 1 1 1 ;
+          0 1 1 0 0 0 0 1 0 1 1 0 1 1 1 1 0 0 0 0 1 ;
+          0 0 1 0 0 0 0 1 0 1 0 0 0 1 0 1 0 0 0 0 1 ;
+          0 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 0 1 0 0 1 ;
+          The .i statement specifies the primary inputs of the network. The
+          patterns start after .s key word. Each vector is a space separated
+          list of bits and ends in a semi-colon. The length of any vector
+          should  be  equal  to the number of signals specified in the .i
+          statement. A line starting with # is a comment.
+
+   -h
+          Print usage.
+
+   -i <freq>
+          Number of iterations after which to update node switching activity.
+          This  is valid only if patterns are provided in a file using -f
+          option. The default value is every 5 iterations.
+
+   -m <n>
+          Heuristics to optimize a selected node.
+          0: Reduce the selected node's support.
+          1: Reprogram the selected node.
+          2: Reprogram the selected node's fanin nodes. (default)
+          3: Reduce the selected node's fanout wires.
+
+   -p <percent>
+          The percentage of vectors, specified via -f option, used to perform
+          simulation (to update switching activity) during logic optimization.
+          The default value is 10%.
+
+   -r
+          Do not reprogram LUTs if no structural changes have been performed
+          with in the cluster, i.e., if no nodes or wires have been removed do
+          not  change  the local implementation of LUTs even if alternate
+          implementations are availabe from SPFD information. The default is to
+          reprogram.
+
+   -S <n>
+          Method used to sort nodes. The nodes are then optimized in that
+          order.
+          0: Random node is chosen. (default)
+          1: If switching activity is available, node with maximum SWC is
+          chosen.
+          2: Node with maximum fanout is chosen.
+          3: If switching activity is available, node with minimum SWC is
+          chosen.
+          4: Node with minimum fanout is chosen.
+
+   -t <sec>
+          Time in seconds allowed to complete the command. If the computation
+          time goes above that limit, the process is aborted. The default is no
+          limit.
+
+   -v <n>
+          Verbosity level. Default value is 0.
+
+   -w <file>
+          File to output final optimized circuit.
+            __________________________________________________________
+
+          Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/static_orderCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/static_orderCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/static_orderCmd.txt	(revision 14)
@@ -0,0 +1,178 @@
+
+  static_order - order the MDD variables of the flattened network
+     _________________________________________________________________
+
+   static_order [-a] [-h] [-n <method>] [-o <type>] [-r <method>] -s <type> [-t
+   <timeOut>] [-v #] <file>
+
+   Order the MDD variables of the flattened network. MDD variables must be
+   created before MDDs can be built. Networks with combinational cycles cannot
+   be  ordered. If the MDD variables have already been ordered, then this
+   command does nothing. To undo the current ordering, reinvoke the command
+   flatten_hierarchy.
+
+   Command options:
+
+   -a
+          Order each next state variable immediately following the variables in
+          the support of the corresponding next state function. By default,
+          each  next  state variable is placed immeadiately following the
+          corresponding  present  state  variable.  It  has been observed
+          experimentally that ordering the NS variable after the PS variable is
+          almost always better; however, as a last b resort, you might want to
+          try this option.
+
+          Unless the -a flag is set, the PS and NS variables corresponding to
+          latches are grouped together and cannot be separated by dynamic
+          reordering. (This is done even when the ordering is read from a file
+          - adjacent PS/NS vars in the file are grouped).
+
+   -h
+          Print the command usage.
+
+   -n <method>
+          Specify which node ordering method to use. Node ordering is the
+          process of computing a total ordering on all the network nodes. This
+          ordering is then projected onto the set of nodes specified by -o
+          type. In the complexity measures below, n is the number of network
+          nodes, E is the number of network edges, and k is the number of
+          latches. "Method" must be one of the following:
+
+          interleave: (default) Uses Algorithm 2 of Fujii et al., "Interleaving
+          Based  Variable  Ordering  Methods  for OBDDs", ICCAD 1993. The
+          complexity is O(E+nlog(n)).
+
+          append: Uses the algorithm of Malik, et al. "Logic Verification using
+          Binary Decision Diagrams in a Logic Synthesis Environment," ICCAD,
+          1988. Nodes are visited in DFS order, and appended to a global order
+          list in the order they are visited. The fanins of a node are visited
+          in order of decreasing depth. The roots of the DFS are visited in the
+          order determined by the -r method. The complexity is O(E+nlog(n)).
+
+          merge_left:  Uses  an  algorithm  alluded  to  in Fujii et al.,
+          "Interleaving Based Variable Ordering Methods for OBDDs", ICCAD 1993.
+          Nodes are visited in DFS order. At a given node g, its fanins are
+          visited in order of decreasing depth. For each fanin fi, a total
+          order is computed for all the nodes in the transitive fanin (TFI) of
+          fi, including fi itself. This ordering is merged into the combined
+          ordering from fanins of higher priority. After processing all of the
+          fanins,  the  result is a total ordering on all TFI nodes of g.
+          Finally,  g is appended to the end of this ordering, yielding a
+          topological ordering. For example if the ordering for f1 is list1 =
+          (a,b,d,f1) and for f2 is list2=(c,d,e,f2), and f1 has greater depth
+          than f2, then the ordering for g is (c,a,b,d,e,f2,f1,g). The merge is
+          done by inserting into list1 those nodes in list2 not already in
+          list1, in such a way that the inserted nodes remain as close as
+          possible to their left neighbors in list2 ("insert as far left as
+          possible"). The roots of the DFS are merged in the order determined
+          by -r method. The complexity is O(n^2) (currently, there is a bug
+          which causes more memory to be consumed than necessary).
+
+          merge_right: Same as merge_left, except that the merge is done in
+          such a way that the inserted nodes remain as close as possible to
+          their right neighbors in list2 ("insert as far right as possible").
+          For the example above, the ordering for g is (a,b,c,d,f1,e,f2,g). It
+          has  been  observed  experimentally that neither merge_left nor
+          merge_right  is  superior  to  the other; there are cases where
+          verification times out with merge_left but not merge_right, and vice
+          versa.
+
+   -o <type>
+          Specify the network nodes for which MDD variables should be created.
+          Type can be one of the following:
+
+          all: Order all the nodes of the network. This is normally not used.
+
+          input_and_latch: (default) Order the primary inputs, pseudo inputs,
+          latches, and next state variables. This is the minimum set of nodes
+          that need to be ordered to perform operations on FSMs (e.g. model
+          checking, reachability). For purely combinational circuits, just the
+          primary and pseudo inputs are ordered.
+
+   -r <method>
+          Specify which root ordering method to use. The "roots" of a network
+          refer to the roots of the cones of logic driving the combinational
+          outputs (data latch inputs, initial state latch inputs, and primary
+          outputs) of a network. Root ordering is used to determine in which
+          order to visit the roots of the network for the DFS carried out in
+          node ordering (see -n). "Method" must be one of the following:
+
+          depth: (default for 30 or more latches) Roots are ordered based on
+          logic depth (i.e. longest path to a combinational input). Greater
+          depth roots appear earlier in the ordering. All data latch inputs
+          appear before all other combinational outputs. The complexity is
+          O(E+nlog(n)).  It has been observed experimentally that mincomm
+          produces superior orderings to depth. However, the complexity of the
+          mincomm  algorithm is such that it cannot produce orderings for
+          designs  with more than a hundred or so latches. Hence, for big
+          designs, use depth, followed optionally by dynamic_var_ordering.
+
+          mincomm: (default for less than 30 latches) Uses the algorithm of
+          Aziz, et al. "BDD Variable Ordering for Interacting Finite State
+          Machines," DAC, 1994. First, the latches are ordered to decrease a
+          communication  complexity  bound (where backward edges are more
+          expensive than forward edges) on the latch communication graph. This
+          directly gives an ordering for the data latch inputs. The remaining
+          combinational outputs are ordered after the data latch inputs, in
+          decreasing  order  of  their  depth.  The  total  complexity is
+          O(nlog(n)+E+k^3).
+
+   -s <type>
+          Used in conjunction with <file> to specify which nodes are supplied
+          in the ordering file. Type can be one of the following (there is no
+          default):
+
+          all: The ordering file supplies all the nodes of the network. The
+          ordering generated is the supplied order, projected onto the set of
+          nodes specified by -o.
+
+          input_and_latch: The ordering file supplies the primary inputs,
+          pseudo  inputs, latches, and next state variables. The ordering
+          generated  is  exactly  what  is  supplied  (in  the case of -o
+          input_and_latch). -o all is incompatible with -s input_and_latch.
+
+          next_state_node: The ordering file supplies next state variables.
+          During the ordering algorithm, the next state functions are visited
+          in the order in which their corresponding next state variables appear
+          in the file. The order of the next state variables in the ordering
+          generated is not necessarily maintained.
+
+          partial: The ordering file supplies an arbitrary subset of nodes of
+          the network. The ordering algorithm works by finding a total ordering
+          on all the nodes (independent of the ordering supplied), then merging
+          the computed order into the supplied order (maintaining the relative
+          order of the supplied order), and then projecting the resulting
+          ordering onto the set of nodes specified by -o.
+
+   -t <timeOut>
+          Time in seconds allowed to perform static ordering. If the flattened
+          network has more than a couple hundred latches and you are using
+          option -r mincomm, then you might want to set a timeOut to limit the
+          allowed time. The default is no limit.
+
+   -v #
+          Print debug information.
+          0 Nothing is printed out. This is the default.
+
+          >=  1 Prints the nodes read from the input file (satisfying the
+          supplied order type); prints the root order used for exploring the
+          network.
+
+          >= 2 Prints the depth of nodes.
+
+          >= 3 Prints the ordering computed at each node.
+
+   <file>
+          A file containing names of network nodes, used to specify a variable
+          ordering. The name of a node is the full hierarchical path name,
+          starting from the current hierarchical node. A node should appear at
+          most once in the file. Each node name should appear at the beginning
+          of a new line, with no white space preceeding it. The end of a node
+          name is marked by white space, and any other text on the rest of the
+          line  is  ignored. Any line starting with "#" or white space is
+          ignored. See write_order for a sample file. Note that the variable
+          ordering  cannot  be specified at the bit-level; it can only be
+          specified at the multi-valued variable level.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/synthesize_networkCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/synthesize_networkCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/synthesize_networkCmd.txt	(revision 14)
@@ -0,0 +1,124 @@
+
+  synthesize_network - Synthesizes a network using ZDD factorization method.
+     _________________________________________________________________
+
+   synthesize_network [-d <divisor>] [-e] [-f <factoringMethod>] [-h] [-i
+   <prefix>] [-o <fileHead>] [-r <reachMethod>] [-t <timeOut>] [-v] [-A] [-O
+   <outputOrdering>] [-R <reorder>] [-T]
+
+   This command synthesizes a network to have as few literals as possible and
+   outputs a blif file and an equation file. Those files are the results of the
+   synthesis. By default, the names of the files are model_name.ml.blif and
+   model_name.eq  unless users specify the model_name explicitly using -o
+   option. But, when the output blif file is read in sis, it may have slightly
+   different  number of literals. This problem will be fixed in the later
+   version. Currently, this command can be used only with CUDD package. Designs
+   described in BLIF or BLIF-MV format can be synthesized by this command.
+   However, multiple valued variables are not supported. Hence, signals in the
+   designs described in BLIF-MV need to be restricted to binary values. There
+   are 4 divisor functions to find a good divisor of a function. Neither of
+   them consistently generates the best result. And, there are 2 factoring
+   methods: simple factoring and generic factoring. Also, neither of two always
+   does better than the other.
+
+   Command options:
+
+   -d <divisor>
+          Choose a divisor.
+
+          0 : Fast divisor. We find a divisor on a ZDD graph. As soon as any
+          shared  node(variable)  is found, the variable is returned as a
+          divisor.
+
+          1 : (default) Least occuring literal divisor. If a variable occurs
+          the least frequently(but, should be more than one) in cubes, it
+          returns the variable as a divisor.
+
+          2 : Most occuring literal divisor. If a variable occurs the most
+          frequently in cubes, it returns the variable as a divisor.
+
+          3 : Level-0 divisor. It finds a divisor that is a level-0 cokernel.
+
+   -e
+          Dump the synthesized circuit in equation format also. Default is not
+          to.
+
+   -f <factoringMethod>
+          Choose a factoring method.
+
+          0 : (default) Simple factoring. This method uses a simple recursion.
+          First, it finds a proper divisor of a function, then divide the
+          function by the divisor, then it gets a quotient and a remainder.
+          And, it does the same thing recursively for each divisor, quotient,
+          and remainder.
+
+          1 : Generic factoring. This method is quite similar to the simple
+          factoring, but it does more in terms of considering cube-free and
+          common  divisor  and literal factoring. But, it does not always
+          generate better results than the simple factoring does.
+
+   -h
+          Print the command usage.
+
+   -i <prefix>
+          Specify the prefix of internal node names. By default, the prefix is
+          "_n".
+
+   -o <fileHead>
+          Specify the output file name (without extension). By default, the
+          model name in a blif file is used.
+
+   -r <reachMethod>
+          If the network is sequential, then use unreachable states as dont
+          cares in the optimization. By default no reachability analysis is
+          performed. See -A option of command compute_reach for more details.
+          The various options are:
+
+          0 : Do not use dont cares (default).
+
+          1 : Use normal breadth first search method for reachability analysis.
+
+          2 : Use high density traversal method for reachablity analysis.
+
+          3 : Use approximate unreachable states(a subset of actual unreachable
+          states) as dont cares.
+
+   -t <timeOut>
+          Time in seconds allowed to perform synthesize_network. The default is
+          no limit.
+
+   -v
+          Print debug information.
+
+   -A
+          Allow realignment to ZDD/BDD after BDD/ZDD reordering, respectively.
+          This option is effective when only one reordering in BDD or ZDD is
+          enabled.
+
+   -O <outputOrdering>
+          Choose an output ordering method.
+
+          0 : No ordering.
+
+          1 : (default) Use support variable set of output functions.
+
+          2 : Use BDD size of output functions.
+
+   -R <reorder>
+          Allow reordering in BDD and/or ZDD.
+
+          0 or n : (default) No reordering neither in BDD nor in ZDD.
+
+          1 or b : Allows reordering only in BDD, not in ZDD.
+
+          2 or z : Allows reordering only in ZDD, not in BDD.
+
+          3 or a : Allows reordering both in BDD and in ZDD.
+
+   -T
+          Try to share more nodes during symbolic factorization. Existing
+          divisors are checked for potential reuse before extracting divisors
+          from the current boolean function.
+              ____________________________________________________
+
+                Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/test_network_acyclicCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/test_network_acyclicCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/test_network_acyclicCmd.txt	(revision 14)
@@ -0,0 +1,17 @@
+
+  test_network_acyclic - determine whether the network is acyclic
+     _________________________________________________________________
+
+   test_network_acyclic [-h]
+
+   If the flattened network has a combinational cycle, then prints information
+   about one of the cycles. If no cycles are present, then it prints a message
+   to this effect.
+
+   Command options:
+
+   -h
+          Print the command usage.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/timeCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/timeCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/timeCmd.txt	(revision 14)
@@ -0,0 +1,23 @@
+
+  time - provide a simple elapsed time value
+     _________________________________________________________________
+
+   time [-h][-u]
+
+   Prints the processor time used since the last time command, and the total
+   processor time used since VIS was started.
+
+   By default, the time reported is the CPU time spent executing instructions
+   of the calling process and the time this process waited for children that
+   terminated.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   -u
+          Exclude child process time.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/truesimCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/truesimCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/truesimCmd.txt	(revision 14)
@@ -0,0 +1,81 @@
+
+  truesim - Simulate the flattened network
+     _________________________________________________________________
+
+   truesim [ -D <filename> ] [ -d ] [ -f <filename> ] [ -g <filename> ] [ -h ]
+   [ -n <N> ] [ -p <filename> ] [ -r <N> ] [ -t <time> ] [ -v <N> ]
+
+   Simulates  a  network with a set of input vectors. Before calling this
+   command,  the  user  should  create  a  partition  (using  the command
+   build_partition_mdds). The simulation vectors can be provided by the user
+   (using -f vectors_file), or generated randomly.
+
+   Command options:
+
+   -D <filename>
+          File to dump randomly generated vectors. Primary input probability
+          file SHOULD be specified with -p option.
+
+   -d
+          Perform event-driven true delay simulation. The fanout count of the
+          nodes is used as an estimate for the node delay. Primary inputs are
+          assumed to have arrival times of zero.
+
+   -f <filename>
+          File containing simulation vectors. The format is simple but strict
+          and hence, few checks are made. The file format is as below:
+
+          .i c n d o e p f q g r h s i t j u k a l b m
+          .s
+          0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 1 1 1 1 ;
+          0 1 1 0 0 0 0 1 0 1 1 0 1 1 1 1 0 0 0 0 1 ;
+          0 0 1 0 0 0 0 1 0 1 0 0 0 1 0 1 0 0 0 0 1 ;
+          0 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 0 1 0 0 1 ;
+          The .i statement specifies the primary inputs of the network. The
+          patterns start after .s key word. Each vector is a space separated
+          list of bits and ends in a semi-colon. The length of any vector
+          should  be  equal  to the number of signals specified in the .i
+          statement. A line starting with # is a comment.
+
+   -g <filename>
+          File to output random probabilities for primary inputs. Use this
+          option ONLY to produce a vector of signal probabilities for primary
+          inputs. This option does not proceed with simulation.
+
+   -h
+          Print a help message that details all options.
+
+   -n <N>
+          Number of patterns to simulate. The default is 1000. Use this option
+          ONLY with -p option.
+
+   -p <filename>
+          File containing primary input probabilities. The format is as shown
+          below:
+
+          PI_Name1 0.67
+          PI_Name2 0.45
+
+   -r <N>
+          Print  PI/PO names after every N patterns simulated, for better
+          readability of simulation output. This option is effective only when
+          the verbosity flag is on.
+
+   -T <filename>
+          File containing node delay and load values. The file format is as
+          shown below:
+
+          node1 delay1 load1
+          node2 delay2 load2
+          The delay vaues are assumed as specified in a common unit. The same
+          is true for load values too.
+
+   -t <time>
+          Time in seconds allowed to finish the simulation. The default is no
+          limit.
+
+   -v <N>
+          Specify verbosity level, N.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/unaliasCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/unaliasCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/unaliasCmd.txt	(revision 14)
@@ -0,0 +1,18 @@
+
+  unalias - remove the definition of an alias.
+     _________________________________________________________________
+
+   unalias [-h] <alias_names>
+
+   Removes the definition of an alias.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   <alias_names>
+          Aliases to be removed
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/unsetCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/unsetCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/unsetCmd.txt	(revision 14)
@@ -0,0 +1,20 @@
+
+  unset - unset an environment variable
+     _________________________________________________________________
+
+   unset [-h] <variables>
+
+   A variable environment is maintained by the command interpreter. The "set"
+   command sets a variable to a particular value, and the "unset" command
+   removes the definition of a variable.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   <variables>
+          Variables to be unset
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/usageCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/usageCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/usageCmd.txt	(revision 14)
@@ -0,0 +1,16 @@
+
+  usage - provide a dump of process statistics
+     _________________________________________________________________
+
+   usage [-h]
+
+   Prints a formatted dump of processor-specific usage statistics. For Berkeley
+   Unix, this includes all of the information in the getrusage() structure.
+
+   Command options:
+
+   -h
+          Print the command usage.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/whichCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/whichCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/whichCmd.txt	(revision 14)
@@ -0,0 +1,21 @@
+
+  which - look for a file called name
+     _________________________________________________________________
+
+   which [-h] <file_name>
+
+   Looks  for  a  file in a set of directories which includes the current
+   directory as well as those in the VIS path. If it finds it, it reports the
+   path. The path is specified through the "set open_path" command in the
+   .visrc.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   <file_name>
+          File to be searched
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/write_blifCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/write_blifCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/write_blifCmd.txt	(revision 14)
@@ -0,0 +1,225 @@
+
+  write_blif - determinize, encode and write an hnode to a blif file
+     _________________________________________________________________
+
+   write_blif   [-c]   [-l]   [-e  <encoding_file_name>]  [-R]  [-h]  [-v
+   <verbosity_value>] [<file>]
+
+   Encodes, determinizes, and writes all tables in the current hnode to a BLIF
+   file. With the '-l' or '-c' options, or when 'write_blif' is used with no
+   options, only the current hnode is written out as a blif file. The '-R'
+   option writes the entire hierarchy rooted at the current hnode to the blif
+   file, assuming all tables are deterministic and all variables are boolean.
+
+   Encoding the Multi-Valued Variables:
+
+   First, all multi-valued variables in the hnode are binary encoded. Each
+   multi-valued variable requires 'm' binary variables in its encoding, where m
+   =  log2(n).  Here  'n'  is  the  number of values in the domain of the
+   multi-valued variable. If variable X has n binary variables in its encoding,
+   these  are  called X0, X1, ... X. X0 is the least significant encoding
+   variable. The value i of multi-valued variable X is encoded such that X0 +
+   2^1 * X1 + ... + 2^(n-1) * X = i. After encoding, each table in the hnode is
+   written out to the blif file.
+
+   Determinizing Non-Deterministic Tables:
+
+   Non-deterministic tables are determinized by adding more binary variables to
+   a particular variable's encoding. The variable that is chosen is the one
+   that  has  the  smallest  number  of binary variables in its encoding.
+   Determinization is explained by means of an example:
+
+   Consider the BLIF-MV table, where each of a, b, and c can have 4 values.
+   Each multi-valued variable has two binary variables in its encoding. These
+   are called a0, a1, b0, b1, c0 and c1.
+
+   .model foo
+
+   .inputs a b
+
+   .outputs c
+
+   .mv a, b, c 4
+
+   .table a b ->c
+
+   2 1 (1,2)
+
+   (1,2) 1 3
+
+   .end
+
+   The first row of this table represents non-determinism, since for a given
+   assignment of input values (i.e. a=2, b=1), the output can take on two
+   values (1 or 2). To determinize this row, it is split into two rows, each
+   with a unique singleton output value. A new binary variable is added to the
+   encoding of a (or b, since in this case each of them has the same number of
+   binary variables in its encoding). The new variable a2 is given separate
+   values in each of the new rows. The resulting blif table looks like:
+
+   .model foo
+
+   .inputs a0 a1 a2 b0 b1
+
+   .outputs c0 c1
+
+   .names a0 a1 a2 b0 b1 ->c0 c1
+
+   0 1 0 1 0 1 0 (these two rows represent
+
+   0 1 1 1 0 0 1 row 1 of the MV table)
+
+   1 0 - 1 0 1 1 (these two rows represent
+
+   0 1 - 1 0 1 1 row 2 of the MV table)
+
+   .end
+
+   Note that this table is still not deterministic, since rows 1 and 4 have
+   input minterm(s) in common, but the corresponding outputs are different. To
+   resolve this, a new binary variable is added to the encoding for b (since b
+   currently  has  the smallest encoding). For the conflicting rows, this
+   variable b2 is assigned different values, and for all other rows, it is
+   assigned a '-' value. After this change, rows 1 and 4 no longer have common
+   input minterm(s). The intermediate table now looks like:
+
+   .model foo
+
+   .inputs a0 a1 a2 b0 b1 b2
+
+   .outputs c0 c1
+
+   .names a0 a1 a2 b0 b1 b2->c0 c1
+
+   0 1 0 1 0 1 1 0
+
+   0 1 1 1 0 - 0 1
+
+   1 0 - 1 0 - 1 1
+
+   0 1 - 1 0 0 1 1
+
+   .end
+
+   This process is continued until the table is determinized. In this example,
+   the final blif file looks like:
+
+   .model foo
+
+   .inputs a0 a1 a2 a3 b0 b1 b2
+
+   .outputs c0 c1
+
+   .table a0 a1 a2 a3 b0 b1 b2 ->c0 c1
+
+   0 1 0 - 1 0 1 1 0
+
+   0 1 1 1 1 0 - 0 1
+
+   1 0 - - 1 0 - 1 1
+
+   0 1 - 0 1 0 0 1 1
+
+   .end
+
+   Blif allows only single output tables, so in reality the above table is
+   split into two single output tables before being written out to the blif
+   file. The new binary variables that are thus introduced are treated as
+   primary inputs in the blif file.
+
+   We make no claim on the optimality of this process, just that it is simple.
+   It may turn out that the number of new variables is much larger than the
+   optimum one.
+
+   Interfacing Between Binary and Multi-Valued Variables:
+
+   In order for the SIS-optimized version of this file to be read back into
+   VIS, we need to re-create the corresponding multi-valued variables. For this
+   purpose, interface information (model name, input and output declarations
+   for the hnode) is written out to a special encoding file (e.g. foo.enc).
+   Additionally,  binary->multi-valued encoding tables are written to the
+   encoding file for each PO. In the above example, the binary->multi-valued
+   table for variable c looks like
+
+   .table c0 c1 -> c
+
+   0 0 0
+
+   1 0 1
+
+   0 1 2
+
+   1 1 3
+
+   and  this can be seen as a decoder of the binary variables. Similarly,
+   multi-valued->binary encoding tables are written to the encoding file for
+   each PI. The multi-valued->binary table for variable b in the above example
+   is:
+
+   .table b -> b0 b1
+
+   0 0 0
+
+   1 1 0
+
+   2 0 1
+
+   3 1 1
+
+   and this can be seen as an encoder of the multi-valued variables. Similar
+   tables are written to the encoding file for sub-circuit inputs and outputs.
+   Likewise, such tables are written out for latch inputs and outputs. This is
+   needed so that the original multi-valued latches can be reinstated while the
+   blif file is being read back into VIS. These multi-valued latch declarations
+   are written to the encoding file during the write_blif process.
+
+   The combination of this encoding file and the blif file results in a legal
+   BLIF-MV hnode description.
+
+   If  no file is specified, the blif file is written out to the standard
+   output. If the encoding file is not specified, encoding information is
+   written out to .enc.
+
+   Options:
+
+   The '-R' option writes the entire hierarchy rooted at the current hnode to
+   the blif file, first checking that all tables are deterministic and all
+   variables are boolean. Other options ('-c', '-l', or write_blif with no
+   options) only write out the current hnode. Also, when the '-R' option is
+   specified, no encoding file is written since none is needed.
+
+   Command options:
+
+   -c
+          Writes only combinational part to blif file.
+
+   -l
+          Writes out latches, making latch IOs primary outputs in the blif
+          file.
+
+   -e <encoding_file_name>
+          If set, the program writes the encoding information into this file.
+          The default is the model name for the current node extended by .enc.
+
+   -R
+          Recursively writes out the entire hierarchy rooted at the current
+          hnode to the blif file. In this sub-hierarchy, all tables must be
+          deterministic and all variables must be boolean. Either of the -c, -l
+          or -e options cannot be used together with this option.
+
+   -h
+          Prints the command usage.
+
+   -v <verbosity_value>
+          Specifies verbosity level, an integer less than 3.
+
+   <file>
+          name of blif file to be written, default is standard output.
+
+          Note  that if neither the -c or the -l options are chosen, then
+          latches are written out, without making latch IOs primary outputs in
+          the blif file. Currently the files written out using this option
+          cannot be read back into VIS.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/write_blif_mvCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/write_blif_mvCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/write_blif_mvCmd.txt	(revision 14)
@@ -0,0 +1,26 @@
+
+  write_blif_mv - write a blif-mv file
+     _________________________________________________________________
+
+   write_blif_mv [-h] [<file>]
+
+   Writes out the hierarchy below the current node in blif-mv format to the
+   file specified as an argument. If no argument is specified, the output is
+   available at the standard output.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   <file>
+          name of blif-mv file to be written.
+
+   For more information on blif-mv, refer to the [1]blif-mv manual.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
+
+References
+
+   1. http://www-cad.eecs.berkeley.edu/Respep/Research/vis/doc/blifmv/blifmv/blifmv.html
Index: vis_dev/vis-2.3/share/help/write_network_blif_mvCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/write_network_blif_mvCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/write_network_blif_mvCmd.txt	(revision 14)
@@ -0,0 +1,21 @@
+
+  write_network_blif_mv - write a blif-MV description of the flattened network
+     _________________________________________________________________
+
+   write_network_blif_mv [-h] [-p] <file_name>
+
+   Write a file in Blif-MV format describing the network.
+
+   If no argument is specified on the command line, the description is written
+   to the vis standard output.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   -p
+          Promote pseudo inputs to primary inputs.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/write_orderCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/write_orderCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/write_orderCmd.txt	(revision 14)
@@ -0,0 +1,61 @@
+
+  write_order - write the current order of the MDD variables of the flattened
+  network
+     _________________________________________________________________
+
+   write_order [-h] [-o <type>] [<file>]
+
+   Write the current order of the MDD variables of the flattened network. If no
+   file name is specified, the output is written to stdout. A sample output is
+   shown here.
+  # name                 type            mddId vals levs
+  system.choosing0      primary-input       31    2 (61)
+  system.p0.pc          latch               32   11 (62, 63, 64, 65)
+  
+
+   The first column gives the full hierarchical path name of the node, starting
+   from the current hierarchical node. The second column gives the type of the
+   node in the flattened network (see the command print_network). The third
+   column gives the MDD id of the node; this can be thought of as just another
+   name for the node. The fourth column gives the number of values that the
+   multi-valued variable at the output of the node can assume. The last column
+   gives the levels of the BDD variables that encode the multi-valued variable
+   (0 is the topmost level of the BDD).
+
+   The bits of a multi-valued variable need not appear consecutively (due to
+   dynamic variable ordering). Each node appears at most once in the output
+   file. The nodes in the file appear in ascending order of the lowest level
+   bit in the encoding of the node's multi-valued variable (e.g. a node with
+   levels (12, 73) will appear before a node with levels (17, 21, 25)).
+
+   To specify a variable ordering for static_order, a convenient tactic is to
+   write out the current ordering, edit the file to rearrange the ordering (or
+   comment out some nodes, using "#"), and then read the file back in using
+   static_order. Note that everything after the first column is ignored when
+   the file is read in.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   -o <type>
+          Specify  the network nodes to write out. Type can be one of the
+          following:
+
+          all: Write out all the nodes of the network. This option is allowed
+          only if all variables have been ordered.
+
+          input_and_latch: (default) Write out the primary inputs, pseudo
+          inputs, latches, and next state variables.
+
+          next_state_node: Write out the next state variables (node type is
+          "shadow"). This file can be modified and read back in using the
+          static_order -s next_state_node command.
+
+   <file>
+          File to which to write the ordering. By default, the ordering is
+          written to stdout.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
Index: vis_dev/vis-2.3/share/help/write_smvCmd.txt
===================================================================
--- vis_dev/vis-2.3/share/help/write_smvCmd.txt	(revision 14)
+++ vis_dev/vis-2.3/share/help/write_smvCmd.txt	(revision 14)
@@ -0,0 +1,26 @@
+
+  write_smv - write an smv file
+     _________________________________________________________________
+
+   write_smv [-h] [<file>]
+
+   Writes out the hierarchy below the current node in smv format to the file
+   specified  as  an argument. If no argument is specified, the output is
+   available at the standard output.
+
+   Command options:
+
+   -h
+          Print the command usage.
+
+   <file>
+          name of smv file to be written.
+
+   For more information on smv, refer to the [1]smv manual.
+     _________________________________________________________________
+
+   Last updated on 20100410 00h02
+
+References
+
+   1. http://www-2.cs.cmu.edu/~modelcheck/smv.html
Index: vis_dev/vis-2.3/share/ioBlifToMv.nawk
===================================================================
--- vis_dev/vis-2.3/share/ioBlifToMv.nawk	(revision 14)
+++ vis_dev/vis-2.3/share/ioBlifToMv.nawk	(revision 14)
@@ -0,0 +1,195 @@
+#!nawk -f
+
+#**CFile***********************************************************************
+#
+# FileName    [ioBlifToMv.nawk]
+#
+# PackageName [io]
+#
+# Synopsis    [A nawk script to convert a blif file into a blif-mv file.]
+#
+# Description [A nawk script to convert a blif file into a blif-mv file.
+# The blif file should be free of errors. The script ignores synthesis related
+# information.]
+#
+# SeeAlso     []
+#
+# Author      [Rajeev K. Ranjan, Yuji Kukimoto]
+#
+# Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+# All rights reserved.
+#
+# Permission is hereby granted, without written agreement and without license
+# or royalty fees, to use, copy, modify, and distribute this software and its
+# documentation for any purpose, provided that the above copyright notice and
+# the following two paragraphs appear in all copies of this software.
+#
+# IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+# OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+# CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+# FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+# "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+# MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+#
+#*****************************************************************************/
+
+BEGIN {
+	subckt_counter = 0
+	while (my_getline()){
+		main()
+	}
+	if (flag){
+		print ".end"
+	}
+}
+
+function main(){
+	while (1) {
+		if ($1 == ".model"){
+			print
+			while (last_char("\\")==1){
+				getline
+				print
+			}	
+			flag = 1;
+			break
+		}
+		if ($1 == ".end"){
+			print
+			flag = 0;
+			break
+		}
+		if ($1 == ".inputs" || $1 == ".outputs"){
+			print
+			while (last_char("\\")==1){
+				getline
+				print
+			}
+			break
+		}
+	 	if ($1 == ".subckt"){
+			fieldCounter = 0;
+			do{
+				last_char_back_slash = last_char("\\")
+				gsub("\\\\","")
+				for (i=1; i<=NF; i++){
+					fieldArray[fieldCounter] = $i;
+					fieldCounter++;
+				}
+				if (last_char_back_slash) getline
+			} while (last_char_back_slash)
+
+			printf("%s %s %d ", fieldArray[0], fieldArray[1], subckt_counter)
+			subckt_counter++;
+			for (i=2; i<fieldCounter-1; i++){
+				printf("%s ", fieldArray[i])
+			}
+			printf("%s\n", fieldArray[fieldCounter-1]);
+		}
+	 	if ($1 == ".latch"){
+			fieldCounter = 0;
+			do{
+				last_char_back_slash = last_char("\\")
+				gsub("\\\\","")
+				for (i=1; i<=NF; i++){
+					fieldArray[fieldCounter] = $i;
+					fieldCounter++;
+				}
+				if (last_char_back_slash) getline
+			} while (last_char_back_slash)
+
+			print fieldArray[0], " ", fieldArray[1], " ", fieldArray[2]
+			print ".reset ", fieldArray[2]
+			if ((fieldCounter == 4) || (fieldCounter == 6)){
+				resetValue = fieldArray[fieldCounter-1];
+				if (resetValue == "0" || resetValue == "1")
+					print resetValue
+				else
+					print "-"
+			}
+			else {
+				print "0"
+			}
+			break
+		}
+		if ($1 == ".names"){
+			print
+			while (last_char("\\")==1){
+				getline
+				print
+			}	
+			if (my_getline() == 0) break
+			if (row_of_table()){
+				if (last_char("0"))
+					print ".def 1"
+				else
+					print ".def 0"
+				while (1){
+					gsub("1","1 ")
+					gsub("0","0 ")
+					gsub("-","- ")
+					for(i = 1; i< NF; i++)
+						printf("%s ",$i)
+					printf("%s",$NF)
+					printf("\n")
+					if (my_getline() == 0) break
+					if (row_of_table()) 
+						continue
+					else 
+						break
+				}
+				continue
+			}
+			else {
+				print ".def 0"
+				continue
+			}
+		}
+		if ($1 == ".exdc"){ # ignore the rest of the file
+			while (getline){
+			}
+			break
+		}
+		while (last_char("\\")==1)
+				getline
+		break
+	}
+}
+
+function last_char(char,  linelength, lastchar){
+	linelength = length
+	lastchar = substr($0, linelength)
+	if (lastchar == char)
+		return 1
+	else
+		return 0
+}
+
+function first_char(char, firstchar){
+	firstchar = substr($1,1,1)
+	if (firstchar == char)
+		return 1
+	else 
+		return 0
+}
+
+function row_of_table(){
+	if (first_char("1") || first_char("0") || first_char("-"))
+		return 1
+	else 
+		return 0
+}
+
+
+function my_getline(){
+	while (getline){
+		if ((NF == 0) || first_char("#"))
+			continue
+		return 1
+	}
+	return 0
+}
Index: vis_dev/vis-2.3/share/ioBlifToMvForIncremental.nawk
===================================================================
--- vis_dev/vis-2.3/share/ioBlifToMvForIncremental.nawk	(revision 14)
+++ vis_dev/vis-2.3/share/ioBlifToMvForIncremental.nawk	(revision 14)
@@ -0,0 +1,150 @@
+#!nawk -f
+
+#**CFile***********************************************************************
+#
+# FileName    [ioBlifToMv.nawk]
+#
+# PackageName [io]
+#
+# Synopsis    [A nawk script to convert a blif file into a blif-mv file.]
+#
+# Description [A nawk script to convert a blif file into a blif-mv file.
+# The blif file should be free of errors. The script ignores synthesis related
+# information.]
+#
+# SeeAlso     []
+#
+# Author      [Rajeev K. Ranjan, Yuji Kukimoto]
+#
+# Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+# All rights reserved.
+#
+# Permission is hereby granted, without written agreement and without license
+# or royalty fees, to use, copy, modify, and distribute this software and its
+# documentation for any purpose, provided that the above copyright notice and
+# the following two paragraphs appear in all copies of this software.
+#
+# IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+# OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+# CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+# FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+# "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+# MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+#
+#*****************************************************************************/
+
+BEGIN {
+	while (my_getline()){
+		main()
+	}
+	print ".end"
+}
+
+function main(){
+	while (1) {
+		if (match($1,"\\.latch|\\.model|\\.inputs|\\.outputs")){
+			while (last_char("\\") == 1){
+				getline
+			}	
+			break
+		}
+		if ($1 == ".names"){
+			print
+			while (last_char("\\")==1){
+				getline
+				print
+			}	
+			if (my_getline() == 0) break
+			if (row_of_table()){
+				if (last_char("0"))
+					print ".def 1"
+				else
+					print ".def 0"
+				while (1){
+					gsub("1","1 ")
+					gsub("0","0 ")
+					gsub("-","- ")
+					for(i = 1; i< NF; i++)
+						printf("%s ",$i)
+					printf("%s",$NF)
+					printf("\n")
+					if (my_getline() == 0) break
+					if (row_of_table()) 
+						continue
+					else 
+						break
+				}
+				continue
+			}
+			else {
+				print ".def 0"
+				continue
+			}
+		}
+	 	if ($1 == ".subckt"){
+			fieldCounter = 0;
+			do{
+				last_char_back_slash = last_char("\\")
+				gsub("\\\\","")
+				for (i=1; i<=NF; i++){
+					fieldArray[fieldCounter] = $i;
+					fieldCounter++;
+				}
+				if (last_char_back_slash) getline
+			} while (last_char_back_slash)
+
+			printf("%s %s %d ", fieldArray[0], fieldArray[1], subckt_counter)
+			subckt_counter++;
+			for (i=2; i<fieldCounter-1; i++){
+				printf("%s ", fieldArray[i])
+			}
+			printf("%s\n", fieldArray[fieldCounter-1]);
+		}
+       	if ($1 == ".exdc"){ # ignore the rest of the file
+       		while (getline){
+         	}
+           	break
+       	}
+		while (last_char("\\")==1)
+			getline
+		break
+	}
+}
+
+function last_char(char,  linelength, lastchar){
+	linelength = length
+	lastchar = substr($0, linelength)
+	if (lastchar == char)
+		return 1
+	else
+		return 0
+}
+
+function first_char(char, firstchar){
+	firstchar = substr($1,1,1)
+	if (firstchar == char)
+		return 1
+	else 
+		return 0
+}
+
+function row_of_table(){
+	if (first_char("1") || first_char("0") || first_char("-"))
+		return 1
+	else 
+		return 0
+}
+
+
+function my_getline(){
+	while (getline){
+		if ((NF == 0) || first_char("#"))
+			continue
+		return 1
+	}
+	return 0
+}
Index: vis_dev/vis-2.3/share/master.visrc
===================================================================
--- vis_dev/vis-2.3/share/master.visrc	(revision 14)
+++ vis_dev/vis-2.3/share/master.visrc	(revision 14)
@@ -0,0 +1,50 @@
+set open_path .:
+
+alias acyc test_network_acyclic
+alias aig  build_partition_maigs
+alias amc  approximate_model_check
+alias bmc  bounded_model_check
+alias ci   check_invariant
+alias dvo  dynamic_var_ordering
+alias flt  flatten_hierarchy
+alias icv  incremental_ctl_verification
+alias init init_verify
+alias le   lang_empty
+alias ltl  ltl_model_check
+alias mc   model_check
+alias imc  iterative_model_check
+alias part build_partition_mdds
+alias pf   print_fairness
+alias pbs  print_bdd_stats
+alias phs  print_hierarchy_stats
+alias pii  print_img_info
+alias pio  print_io
+alias pl   print_latches
+alias pm   print_models
+alias pn   print_network
+alias pns  print_network_stats
+alias pp   print_partition
+alias pps  print_partition_stats
+alias q    quit
+alias rch  compute_reach -v 1
+alias resv res_verify
+alias rf   read_fairness
+alias rl   read_blif
+alias rlmv read_blif_mv
+alias ro   so -s input_and_latch
+alias rsf  reset_fairness
+alias sift dvo -f sift
+alias sim  simulate
+alias so   static_order
+alias synth synthesize_network
+alias window dvo -f window
+alias wl   write_blif
+alias wlmv write_blif_mv
+alias wo   write_order
+
+#image method iwls95 related settings
+set image_W1 6
+set image_W2 1
+set image_W3 1
+set image_W4 2
+set partition_threshold 5000
Index: vis_dev/vis-2.3/share/memoryaccount
===================================================================
--- vis_dev/vis-2.3/share/memoryaccount	(revision 14)
+++ vis_dev/vis-2.3/share/memoryaccount	(revision 14)
@@ -0,0 +1,274 @@
+#!/usr/local/bin/perl
+#
+# Script to read a file specifying the packages to which every function belongs
+# in VIS and then process the file output of purify and create a table of
+# memory usage per package.
+#
+# Abelardo Pardo <abel@vlsi.colorado.edu>
+#
+# Revision: [$Id: memoryaccount,v 1.8 1997/01/23 03:50:43 hsv Exp $]
+
+require 5.001;
+use Getopt::Long;
+
+$version = "1.8";
+
+# Define option and default variables
+#
+$opt_f = 0;
+$opt_h = 0;
+$opt_p = 0;
+$opt_v = 0;
+$opt_u = 0;
+
+# Read the options
+# 
+$optionResult = GetOptions("f=s","h","m=s","p","u=s","v");
+
+# Read the result of the options
+#
+if ($opt_f) {
+    $file = $opt_f;
+}
+else {
+    $file = "purify.log";
+}
+
+# Print the help message if required
+#
+if ($opt_h || !$optionResult) {
+    goto usage;
+}
+
+if ($opt_u) {
+    if ($opt_u eq "k") {
+	$unit = "Kbytes";
+	$factor = 1000.0;
+	$precission = 2;
+    }
+    if ($opt_u eq "m") {
+	$unit = "Mbytes";
+	$factor = 1000000.0;
+        $precission = 2;
+    }
+    if ($opt_u eq "g") {
+	$unit = "Gbytes";
+	$factor = 1000000000.0;
+	$precission = 2;
+    }
+    if ($opt_u eq "b") {
+	$unit = "bytes";
+	$factor = 1.0;
+	$precission = 0;
+    }
+}
+else {
+    $unit = "bytes";
+    $factor = 1.0;
+    $precission = 0;
+}
+
+# Print the version if required
+#
+if ($opt_v) {
+    print <<ENDOFMESSAGE;
+$0 -- Version: $version -- by Abelardo Pardo <abel\@vlsi.colorado.edu>
+ENDOFMESSAGE
+    exit;
+}
+
+# Initial value of certain variables 
+#
+$detectedmiu = 0;
+$totalchunks = 0;
+$totalmemory = 0;
+
+# Read in the function map files
+#
+
+if ($#ARGV == -1) {
+    push(@ARGV, "./.fmap");
+}
+
+foreach $filename (@ARGV) {
+    if (open(INPUT, $filename)) {
+        while (<INPUT>) {
+            @fields = split(/\s/,$_);
+            $func2pkg{$fields[2]} = $fields[0];
+	    $total{$fields[0]} = 0;
+	}
+	close(INPUT);
+    }
+}
+
+# Open the input file
+#
+open(INPUT, $file) || die "Unable to open file $file\n";
+while (<INPUT>) {
+    chop;
+
+    # Detect the version of purify being executed
+    if (/\s\s\*\sPurify\s([0-9\.]+)\s/) {
+	$purifyVersion = $1;
+	print "Memory Map of $pname at $pdate obtained with Purify $1\n";
+	if ($purifyVersion eq "3.2") {
+	    $totalMemoryExp = "^Memory\\sin\\-use:\\s([0-9]+)\\sbytes";
+	}
+	if ($purifyVersion eq "4.0.1") {
+	    $totalMemoryExp = "^New\\smemory\\sin\\-use:\\s([0-9]+)\\sbytes";
+	}
+    }
+
+    # Detect the first line telling when this was executed
+    if (/^\*\*\*\*\s\sPurify\sinstrumented\s(.+)\s\((.+)\sat\s(.+)\)/) {
+	$pname = $2;
+	$pdate = $3;
+    }
+
+    # Detecting when the data structure has to be flushed
+    if (/^Purify:\sSearching\sfor\sall\smemory\sin\-use\.\.\.$/) {
+	foreach $name (keys %total) {
+	    $total{$name} = 0;
+	}
+	$parsing = 1;
+    }
+
+    if ($parsing) {
+	# Detect the line saying how much memory in use is visible
+	if (/^Memory\sin\-use:\s([0-9]+)\sbytes\s+\(([0-9\.]+)%\s.+\)/) {
+	    $memInUse = $2;
+	}
+	
+	# If we are inside a MIU statement 
+	if ($detectedmiu == 1) {
+	    
+	    # Detect end of MIU statement
+	    if ($_ eq "") {
+		$detectedmiu = 0;
+		if ($notallocatedyet == 1) {
+		    $total{"unclaimed"} += $portioninuse;
+		}
+	    }
+	    else {
+		
+		# Obtain the function name of the allocation
+		if ($notallocatedyet == 1) {
+		    if (/\s+([a-zA-Z0-9_]+)\s+\[(.+)\]/) {
+			$function = $1;
+			if (defined($func2pkg{$function})) {
+			    $pkg = $func2pkg{$function};
+			    $total{$pkg} += $portioninuse;
+			    $notallocatedyet = 0;
+			}
+		    }
+		}
+	    }
+	}
+	
+	if (/^MIU:\s([0-9]+)\sbytes/) {
+	    $detectedmiu = 1;
+	    $portioninuse = $1;
+	    $notallocatedyet = 1;
+	}
+	
+	if (/^\s\s\s\s\sTotal\sAllocated\s+([0-9]+)\s+([0-9]+)/) {
+	    $totalchunks = $1;
+	    $totalmemory = $2;
+	    $parsing = 0;
+	}
+    }
+}
+
+close(INPUT);
+
+if ($memInUse ne "100") {
+    print "Warning: The program is using $memInUse% of its allocated memory\n";
+}
+print "Profile of the memory currently in use:\n";
+foreach $name (sort keys %total) {
+    if ($opt_p || $total{$name} != 0) {
+	$tmemoryunits = $total{$name}/$factor;
+	$percentage = 100.0*$total{$name}/$totalmemory;
+	printf "%9s :  %12.${precission}f %s %5.2f %%\n", 
+	       $name, $tmemoryunits, $unit, $percentage;
+    }
+}
+print "-------------------------------------------------------------------------------\n";
+
+if ($totalchunks == 0) {
+    print "No information found in file $file\n";
+    exit;
+}
+
+$memoryunits = $totalmemory/$factor;
+$memoryperchunk = $totalmemory/$totalchunks;
+printf "Total Memory Allocated = %12.${precission}f %s\n", $memoryunits, $unit;
+print "Memory allocated in $totalchunks portions. ";
+printf "Average %12.2f bytes per portion\n", $memoryperchunk;
+
+exit;
+
+usage:
+    print <<ENDOFMESSAGE;
+
+$0 - Program to analyze and collect statistics about the memory usage of VIS.
+    This is how the filter works. It reads a file mapping function names to
+    package names. The filename to read may be provided in the command
+    line. This map may be created with the script "createfunctionmap". The
+    application first reads in that function map. If a function is mapped in
+    more than one file, the last one read in the one that prevails (for that
+    reason it is recommended to read in first the global map and then the map
+    in the user area). After that, it opens the file "purify.log" (this value
+    may be overwritten with the "-f" option). It parses this file to detect the
+    beginning and end of the purify dump of the memory in use. Among other
+    things, the parsing analyzes every MIU (Memory in use) statement. The MIU
+    statement gives the call stack whenever a memory allocation of a portion
+    that is still in use is performed. The script parses this call stack
+    searching for function names. When a function name that is present in the
+    map previously read is found, that memory is added to a counter for the
+    package to which that function belongs. Since purify prints a finite number
+    of functions in this call stack, it might happen that none of the function
+    names in that stack is in the map. In that case, the memory allocated is
+    accounted to the "unclaimed" category.  If while using this script, the
+    unclaimed category represents a significant portion of the memory in use,
+    there are two things that can be done: Either the length of the call stack
+    is increased by using the "-chain-length" option in purify whose default is
+    6, or more function names are included in the map file, such that the
+    "unclaimed memory" situation does not occur that often.  When the script is
+    done parsing the purify file, it prints a summary of the memory allocated
+    to each and every package present in its map. Purify makes a distinction
+    between the memory in use and the allocated memory. The former is the
+    memory that is still accessible to the program. The latter is the total
+    memory allocated to the program. If the memory being used by the program is
+    not the total memory allocated by the program, the script issues a
+    warning. This situation means that there is a portion of the memory that
+    cannot be accessed and therefore leaked. Please refer to the purify user's
+    guide Chapter 14, "Purify API" for more information about the type of
+    information provided by purify.
+
+Usage:
+  $0 [-f <filename>] [-h] [-p] [-v] [-u <units>] filenames
+
+Options:
+  -f <filename>     File to read the dump from. The default is "purify.log"
+  -h                Print this message
+  -p                Print also the packages that do not use any memory.
+  -v                Print the version
+  -u <units>        Units to print the memory usage in. It may be "b" for bytes
+                    "k" for kilobytes, "m" for megabytes and "g" for gigabytes.
+		    The default is bytes.
+  filenames         Files containing the function map to be read. Default is
+                    ./.fmap 
+
+Bugs:
+  This script has been tested for purify versions 3.2 and 4.0.1. Since the
+  parsing is sensitive to the messages written in the dump file, a new version
+  of purify might have different messages that are not matched in the
+  script. If this situation arises, chances are the results are completely
+  bogus. 
+
+Author: Abelardo Pardo <abel\@vlsi.colorado.edu>
+
+
+ENDOFMESSAGE
+    exit;
Index: vis_dev/vis-2.3/share/script_compute_reach.robust
===================================================================
--- vis_dev/vis-2.3/share/script_compute_reach.robust	(revision 14)
+++ vis_dev/vis-2.3/share/script_compute_reach.robust	(revision 14)
@@ -0,0 +1,26 @@
+# Script file for computing the reachable states of a FSM. 
+# This script invokes the safest commands to finish the reachability of
+# an FSM. This may not be the fastest way to perform
+# reachability. However, the script should work in almost all
+# cases. Hence the subscript "robust".
+
+# Author: Rajeev K. Ranjan
+
+# Usage: 
+# After reading in the design using one of 
+# "read_blif, read_blif_mv, or read_verilog" commands, 
+# on VIS prompt type:  
+# source script_compute_reach.robust 
+#
+# Trouble shooting:
+# i) Invoke the script exactly the way prescribed (no option to "source")
+
+### Script starts here #################################################
+
+  # Source the generic script file
+
+source script_generic.robust
+
+  # Invoke the reachability command.
+
+compute_reach -v 1
Index: vis_dev/vis-2.3/share/script_compute_reach.simple
===================================================================
--- vis_dev/vis-2.3/share/script_compute_reach.simple	(revision 14)
+++ vis_dev/vis-2.3/share/script_compute_reach.simple	(revision 14)
@@ -0,0 +1,25 @@
+# Script file for computing the reachable states of a FSM. 
+
+# Author: Rajeev K. Ranjan
+
+# Usage: 
+# After reading in the design using one of 
+# "read_blif, read_blif_mv, or read_verilog" commands, 
+# on VIS prompt type:  
+# source script_compute_reach.simple 
+#
+# Trouble shooting:
+# i) Invoke the script exactly the way prescribed (no option to "source")
+# ii) The script tries to create a file in the current directory. Make sure
+#     that the directory is writable by you.
+
+### Script starts here #################################################
+
+
+  # First source the generic script file
+
+source script_generic.simple
+
+  # Finally invoke the reachability command.
+
+compute_reach -v 1
Index: vis_dev/vis-2.3/share/script_fair_model_check.robust
===================================================================
--- vis_dev/vis-2.3/share/script_fair_model_check.robust	(revision 14)
+++ vis_dev/vis-2.3/share/script_fair_model_check.robust	(revision 14)
@@ -0,0 +1,28 @@
+# Script file for checking a set of CTL formula under a set of
+# fairness constraints (no debugging).
+
+# Author: Rajeev K. Ranjan
+
+# Usage: 
+# After reading in the design using one of 
+# "read_blif, read_blif_mv, or read_verilog" commands, 
+# on VIS prompt type:  
+# source script_fair_model_check.robust <fairness_file> <ctl_file>
+#
+# Trouble shooting:
+# i) Invoke the script exactly the way prescribed (no option to "source")
+
+### Script starts here #################################################
+
+  # Source the generic script file
+
+source script_generic.robust
+
+  # Read the fairness constraints.
+
+read_fairness %:2
+
+  # Finally invoke the model checking command (no sharing of
+  # sub-formulae, create reduce FSMs for each formula)
+
+model_check -c -r -d 0 %:3
Index: vis_dev/vis-2.3/share/script_fair_model_check.simple
===================================================================
--- vis_dev/vis-2.3/share/script_fair_model_check.simple	(revision 14)
+++ vis_dev/vis-2.3/share/script_fair_model_check.simple	(revision 14)
@@ -0,0 +1,29 @@
+# Script file for checking a set of CTL formula under a set of
+# fairness constraints (no debugging).
+
+# Author: Rajeev K. Ranjan
+
+# Usage: 
+# After reading in the design using one of 
+# "read_blif, read_blif_mv, or read_verilog" commands, 
+# on VIS prompt type:  
+# source script_fair_model_check.simple <fairness_file> <ctl_file>
+
+# Trouble shooting:
+# i) Invoke the script exactly the way prescribed (no option to "source")
+# ii) The script tries to create a file in the current directory. Make sure
+#     that the directory is writable by you.
+
+### Script starts here #################################################
+
+  # Source the generic script file
+
+source script_generic.simple
+
+  # Read the fairness constraints
+
+read_fairness %:2		
+
+  # Finally invoke the model checking command.
+
+model_check -d 0 %:3
Index: vis_dev/vis-2.3/share/script_generic.robust
===================================================================
--- vis_dev/vis-2.3/share/script_generic.robust	(revision 14)
+++ vis_dev/vis-2.3/share/script_generic.robust	(revision 14)
@@ -0,0 +1,65 @@
+# Generic script file for creating the next state relation of a system
+# This script invokes the safest commands to create the next state relation.
+# The script should work in almost all cases. Hence the subscript "robust".
+
+# Author: Rajeev K. Ranjan
+
+# Usage: 
+# After reading in the design using one of 
+# "read_blif, read_blif_mv, or read_verilog" commands, 
+# on VIS prompt type:  
+# source script_generic.robust 
+#
+# Trouble shooting:
+# i) Invoke the script exactly the way prescribed (no option to "source")
+
+### Script starts here #################################################
+
+  # Get rid of the aliases for the commands used in this file
+
+unalias flatten_hierarchy
+unalias static_order
+unalias build_partition_mdds
+unalias print_img_info
+unalias compute_reach
+unalias dynamic_var_ordering
+unalias write_order
+
+  # Perform the complete specification and deterministic checks
+
+flatten_hierarchy
+
+  # Variable ordering, assuming the default has taken care of the best
+  # setting.
+
+static_order
+
+  # Keep the dynamic variable ordering enabled all the time.
+
+dynamic_var_ordering -e sift
+
+  # Build the next state functions. Use the frontier method such that in
+  # case of very large examples, we can create intermediate variables
+  # and have a handle on the BDD size.
+
+
+  # We do not want  next state functions to have more than 5000 nodes.
+
+set partition_threshold 5000
+build_partition_mdds frontier
+
+  # Next create the next state relation, create clusters and
+  # order them.
+
+  # Use the method published in IWLS 95.
+  # And set the appropriate parameters
+
+set image_method iwls95
+
+  # Make clusters of no larger than 5000
+
+set image_cluster_size 5000
+
+  # Finally invoke the reachability command.
+
+print_img_info
Index: vis_dev/vis-2.3/share/script_generic.simple
===================================================================
--- vis_dev/vis-2.3/share/script_generic.simple	(revision 14)
+++ vis_dev/vis-2.3/share/script_generic.simple	(revision 14)
@@ -0,0 +1,81 @@
+# Generic script file for creating the next state relation of a system.
+
+# Author: Rajeev K. Ranjan
+
+# Usage: 
+# After reading in the design using one of 
+# "read_blif, read_blif_mv, or read_verilog" commands, 
+# on VIS prompt type:  
+# source script_generic.simple 
+#
+# Trouble shooting:
+# i) Invoke the script exactly the way prescribed (no option to "source")
+# ii) The script tries to create a file in the current directory. Make sure
+#     that the directory is writable by you.
+
+### Script starts here #################################################
+
+  # Get rid of the aliases for the commands used in this file
+
+unalias flatten_hierarchy
+unalias static_order
+unalias build_partition_mdds
+unalias print_img_info
+unalias compute_reach
+unalias dynamic_var_ordering
+unalias write_order
+
+  # flatten the hierarchy 
+flatten_hierarchy 
+
+  # Variable ordering, assuming the default has taken care of the best
+  # setting.
+
+static_order
+
+  # Build the next state functions. Use the frontier method such that in
+  # case of very large examples, we can create intermediate variables
+  # and have a handle on the BDD size.
+
+  # We do not want  next state functions to have more than 5000 nodes.
+
+set partition_threshold 5000
+build_partition_mdds frontier
+
+  # Next create the next state relation, create clusters and
+  # order them.
+
+  # Use the method published in IWLS 95.
+  # And set the appropriate parameters
+
+set image_method iwls95
+
+  # Make clusters of no larger than 5000
+
+set image_cluster_size 5000
+
+  # This command is a clumsy way to create the next state relations.
+
+print_img_info 
+
+  # Invoke the sifting operation to reduce the BDD size
+
+dynamic_var_ordering -f sift
+
+  # Save the ordering in a file, to be used later (using a unique name).
+
+write_order __vis.order
+
+  # Restart the computation
+
+flatten_hierarchy 
+
+  # Use the variable ordering obtained after reordering.
+
+static_order -s input_and_latch __vis.order
+
+build_partition_mdds frontier
+
+  # This command is a clumsy way to create the next state relations.
+
+print_img_info 
Index: vis_dev/vis-2.3/share/script_lang_empty_check.robust
===================================================================
--- vis_dev/vis-2.3/share/script_lang_empty_check.robust	(revision 14)
+++ vis_dev/vis-2.3/share/script_lang_empty_check.robust	(revision 14)
@@ -0,0 +1,29 @@
+# Script file for checking the language emptiness of a system under a
+# set of fairness constraints.
+
+# Author: Rajeev K. Ranjan
+
+# Usage: 
+# After reading in the design using one of 
+# "read_blif, read_blif_mv, or read_verilog" commands, 
+# on VIS prompt type:  
+# source script_lang_empty_check.robust  <fairness_file>
+#
+# Trouble shooting:
+# i) Invoke the script exactly the way prescribed (no option to "source")
+
+### Script starts here #################################################
+
+  # Source the generic script file
+
+source script_generic.robust
+
+  # Read the fairness constraints
+
+read_fairness %:2		
+
+  # Finally invoke the language emptiness check
+
+lang_empty -d 0 
+
+
Index: vis_dev/vis-2.3/share/script_lang_empty_check.simple
===================================================================
--- vis_dev/vis-2.3/share/script_lang_empty_check.simple	(revision 14)
+++ vis_dev/vis-2.3/share/script_lang_empty_check.simple	(revision 14)
@@ -0,0 +1,29 @@
+# Script file for checking the language emptiness of a system under a
+# set of fairness constraints.
+
+# Author: Rajeev K. Ranjan
+
+# Usage: 
+# After reading in the design using one of 
+# "read_blif, read_blif_mv, or read_verilog" commands, 
+# on VIS prompt type:  
+# source script_lang_empty_check.simple  <fairness_file>
+
+# Trouble shooting:
+# i) Invoke the script exactly the way prescribed (no option to "source")
+# ii) The script tries to create a file in the current directory. Make sure
+#     that the directory is writable by you.
+
+### Script starts here #################################################
+
+  # Source the generic script file
+
+source script_generic.simple 
+
+  # Read the fairness constraints
+
+read_fairness %:2		
+
+  # Finally invoke the language emptiness check
+
+lang_empty -d 0 
Index: vis_dev/vis-2.3/share/script_model_check.robust
===================================================================
--- vis_dev/vis-2.3/share/script_model_check.robust	(revision 14)
+++ vis_dev/vis-2.3/share/script_model_check.robust	(revision 14)
@@ -0,0 +1,24 @@
+# Script file for checking a set of CTL formula (no fairness
+#						 constraints, no debugging)  
+
+# Author: Rajeev K. Ranjan
+
+# Usage: 
+# After reading in the design using one of 
+# "read_blif, read_blif_mv, or read_verilog" commands, 
+# on VIS prompt type:  
+# source script_model_check.robust  <ctl_file>
+#
+# Trouble shooting:
+# i) Invoke the script exactly the way prescribed (no option to "source")
+
+### Script starts here #################################################
+
+  # Source the generic script file
+
+source script_generic.robust
+
+  # Finally invoke the model checking command (no sharing of
+  # sub-formula, create the reduced FSM for each formula) 
+
+model_check -c -r -d 0 %:2
Index: vis_dev/vis-2.3/share/script_model_check.simple
===================================================================
--- vis_dev/vis-2.3/share/script_model_check.simple	(revision 14)
+++ vis_dev/vis-2.3/share/script_model_check.simple	(revision 14)
@@ -0,0 +1,25 @@
+# Script file for checking a set of CTL formula (no fairness
+#						 constraints, no debugging)  
+
+# Author: Rajeev K. Ranjan
+
+# Usage: 
+# After reading in the design using one of 
+# "read_blif, read_blif_mv, or read_verilog" commands, 
+# on VIS prompt type:  
+# source script_model_check.simple  <ctl_file>
+#
+# Trouble shooting:
+# i) Invoke the script exactly the way prescribed (no option to "source")
+# ii) The script tries to create a file in the current directory. Make sure
+#     that the directory is writable by you.
+
+### Script starts here #################################################
+
+  # Source the generic script 
+
+source script_generic.simple 
+
+  # Invoke the model checking command.
+
+model_check -d 0 %:2
Index: vis_dev/vis-2.3/share/sislib.mv
===================================================================
--- vis_dev/vis-2.3/share/sislib.mv	(revision 14)
+++ vis_dev/vis-2.3/share/sislib.mv	(revision 14)
@@ -0,0 +1,311 @@
+.model __sis_not
+.outputs o
+.inputs a
+.table a -> o
+.default 0
+0 1
+.end
+
+.model __sis_buf
+.outputs o
+.inputs a
+.table a -> o
+.default 1
+0 0
+.end
+
+.model __sis_and
+.outputs o
+.inputs a b
+.table a b -> o
+.default 0
+1 1 1
+.end
+
+.model __sis_and3
+.outputs o
+.inputs a b c
+.table a b c -> o
+.default 0
+1 1 1 1
+.end
+
+.model __sis_and4
+.outputs o
+.inputs a b c d
+.table a b c d -> o
+.default 0
+1 1 1 1 1
+.end
+
+.model __sis_and5
+.outputs o
+.inputs a b c d e
+.table a b c d e -> o
+.default 0
+1 1 1 1 1 1
+.end
+
+.model __sis_and6
+.outputs o
+.inputs a b c d e f
+.table a b c d e f -> o
+.default 0
+1 1 1 1 1 1 1
+.end
+
+.model __sis_and7
+.outputs o
+.inputs a b c d e f g
+.table a b c d e f g -> o
+.default 0
+1 1 1 1 1 1 1 1
+.end
+
+.model __sis_and8
+.outputs o
+.inputs a b c d e f g h
+.table a b c d e f g h -> o
+.default 0
+1 1 1 1 1 1 1 1 1
+.end
+
+.model __sis_and9
+.outputs o
+.inputs a b c d e f g h i
+.table a b c d e f g h i -> o
+.default 0
+1 1 1 1 1 1 1 1 1 1
+.end
+
+.model __sis_nand
+.outputs o
+.inputs a b
+.table a b -> o
+.default 1
+1 1 0
+.end
+
+.model __sis_nand3
+.outputs o
+.inputs a b c
+.table a b c -> o
+.default 1
+1 1 1 0
+.end
+
+.model __sis_nand4
+.outputs o
+.inputs a b c d
+.table a b c d -> o
+.default 1
+1 1 1 1 0
+.end
+
+.model __sis_nand5
+.outputs o
+.inputs a b c d e
+.table a b c d e -> o
+.default 1
+1 1 1 1 1 0
+.end
+
+.model __sis_nand6
+.outputs o
+.inputs a b c d e f
+.table a b c d e f -> o
+.default 1
+1 1 1 1 1 1 0
+.end
+
+.model __sis_nand7
+.outputs o
+.inputs a b c d e f g
+.table a b c d e f g -> o
+.default 1
+1 1 1 1 1 1 1 0
+.end
+
+.model __sis_nand8
+.outputs o
+.inputs a b c d e f g h
+.table a b c d e f g h -> o
+.default 1
+1 1 1 1 1 1 1 1 0
+.end
+
+.model __sis_nand9
+.outputs o
+.inputs a b c d e f g h i
+.table a b c d e f g h i -> o
+.default 1
+1 1 1 1 1 1 1 1 1 0
+.end
+
+.model __sis_or
+.outputs o
+.inputs a b
+.table a b -> o
+.default 1
+0 0 0
+.end
+
+.model __sis_or3
+.outputs o
+.inputs a b c
+.table a b c -> o
+.default 1
+0 0 0 0
+.end
+
+.model __sis_or4
+.outputs o
+.inputs a b c d
+.table a b c d -> o
+.default 1
+0 0 0 0 0
+.end
+
+.model __sis_or5
+.outputs o
+.inputs a b c d e
+.table a b c d e -> o
+.default 1
+0 0 0 0 0 0
+.end
+
+.model __sis_or6
+.outputs o
+.inputs a b c d e f
+.table a b c d e f -> o
+.default 1
+0 0 0 0 0 0 0
+.end
+
+.model __sis_or7
+.outputs o
+.inputs a b c d e f g
+.table a b c d e f g -> o
+.default 1
+0 0 0 0 0 0 0 0
+.end
+
+.model __sis_or8
+.outputs o
+.inputs a b c d e f g h
+.table a b c d e f g h -> o
+.default 1
+0 0 0 0 0 0 0 0 0
+.end
+
+.model __sis_or9
+.outputs o
+.inputs a b c d e f g h i
+.table a b c d e f g h i -> o
+.default 1
+0 0 0 0 0 0 0 0 0 0
+.end
+
+.model __sis_nor
+.outputs o
+.inputs a b
+.table a b -> o
+.default 0
+0 0 1
+.end
+
+.model __sis_nor3
+.outputs o
+.inputs a b c
+.table a b c -> o
+.default 0
+0 0 0 1
+.end
+
+.model __sis_nor4
+.outputs o
+.inputs a b c d
+.table a b c d -> o
+.default 0
+0 0 0 0 1
+.end
+
+.model __sis_nor5
+.outputs o
+.inputs a b c d e
+.table a b c d e -> o
+.default 0
+0 0 0 0 0 1
+.end
+
+.model __sis_nor6
+.outputs o
+.inputs a b c d e f
+.table a b c d e f -> o
+.default 0
+0 0 0 0 0 0 1
+.end
+
+.model __sis_nor7
+.outputs o
+.inputs a b c d e f g
+.table a b c d e f g -> o
+.default 0
+0 0 0 0 0 0 0 1
+.end
+
+.model __sis_nor8
+.outputs o
+.inputs a b c d e f g h
+.table a b c d e f g h -> o
+.default 0
+0 0 0 0 0 0 0 0 1
+.end
+
+.model __sis_nor9
+.outputs o
+.inputs a b c d e f g h i
+.table a b c d e f g h i -> o
+.default 0
+0 0 0 0 0 0 0 0 0 1
+.end
+
+.model __sis_xor
+.outputs o
+.inputs a b
+.table a b -> o
+.default 0
+0 1 1
+1 0 1
+.end
+
+.model __sis_xor3
+.outputs o
+.inputs a b c
+.table a b c -> o
+.default 0
+0 0 1 1
+0 1 0 1
+1 0 0 1
+1 1 1 1
+.end
+
+.model __sis_xnor
+.outputs o
+.inputs a b
+.table a b -> o
+.default 1
+0 1 0
+1 0 0
+.end
+
+.model __sis_xnor3
+.outputs o
+.inputs a b c
+.table a b c -> o
+.default 1
+0 0 1 0
+0 1 0 0
+1 0 0 0
+1 1 1 0
+.end
Index: vis_dev/vis-2.3/share/visdbgpp
===================================================================
--- vis_dev/vis-2.3/share/visdbgpp	(revision 14)
+++ vis_dev/vis-2.3/share/visdbgpp	(revision 14)
@@ -0,0 +1,66 @@
+#! /usr/bin/perl
+#
+# Postprocess debug file from vis
+#   Combine bus signals
+#
+# Author: Toshi Isogai
+#
+# $Id: visdbgpp,v 1.1 2001/03/14 20:10:04 hsv Exp $
+
+%sigval = ();
+
+while (<>) {
+  if (m{^([\w\.]+(<\*\d+\*>)?)<\d+>}) {	# a (possibly partial) state
+    # get lines on the same bus
+    $sig = $1;
+    $val = $sigval{$sig};
+    # Quote the signal name when using it as pattern because it may
+    # contain the metacharacter '*'.
+    while (m{^\Q$sig\E<(\d+)>:(\d)}) {
+      $val = ($val & ~(1<<$1)) | ($2 << $1); # replace value on bit
+      $_ = <ARGV>;
+    }
+    printf "$sig:0x%X\n", $val;
+    $sigval{$sig} = $val;
+    redo;
+
+  } elsif (m{<}) {		# a CTL formula
+      # combine (xyz<a+1:a> * xyz<a-1>) into xyz<a+1:a-1>
+      while (m{\(([\w\.]+(<\*\d+\*>)?)<(\d+)(:(\d+))?>=(0x)?([\da-fA-F]+)
+	       \s\*\s
+	       \1<(\d+)>=(\d)\)}xg) {
+	$str = $&;		# entire matched string
+	$sig = $1;		# signal name
+	$msb = $3;		# most significant bit index
+	$lsb = $5;		# optional least significant bit index
+	$val = hex ($7);	# value of left-hand side
+	$newlsb = $8;		# index being added to the vector
+	$bit = $9;		# value of the new bit
+
+	if ($lsb eq '') {
+	  # new start
+	  $lsb = $msb;
+	}
+
+	if ($lsb == $newlsb+1 || $msb == $newlsb-1) {
+	  $val = sprintf("%X",($val << 1) + $bit);
+
+	  s{\Q$str\E}{$sig<$msb:$newlsb>=0x$val};
+
+	} else {
+	  # warning
+	  print (STDERR "Warning: Non concecutive bits at $.. ");
+ 	  if ($msb == $lsb) {
+	    print (STDERR "Bit $msb next to Bit $newlsb\n");
+	  } else {
+	    print (STDERR "MSB $msb LSB $lsb next to Bit $newlsb\n");
+	  }
+	}
+
+      }
+
+  }
+  print;
+  last if eof();
+
+}
Index: vis_dev/vis-2.3/src/abs/abs.h
===================================================================
--- vis_dev/vis-2.3/src/abs/abs.h	(revision 14)
+++ vis_dev/vis-2.3/src/abs/abs.h	(revision 14)
@@ -0,0 +1,70 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [abs.h]
+
+  PackageName [abs]
+
+  Synopsis    [Incremental CTL model checker.]
+
+  Description [This package provides the command "incremental_ctl_verification",
+  an algorithm to verify CTL formulas starting from an initial abstraction and
+  applying refinements to increment the level of accuracy in the verification.
+  The theory behind this work can be found in:
+
+  @InCollection{Pardo97,
+    author =       {Abelardo Pardo and Gary Hachtel},
+    title =        {Automatic Abstraction Techniques for Propositional
+                    $\mu$-calculus Model Checking},
+    booktitle =    {9th Conference on Computer Aided Verification (CAV'97)},
+    publisher =    {Springer-Verlag},
+    year =         1997,
+    editor =       {O. Grumberg},
+    month =        jun,
+    pages =        {12-23},
+    note =         {LNCS-1254}
+    }] 
+
+  Author      [Abelardo Pardo <abel@vlsi.colorado.edu>]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+  Revision    [$Id: abs.h,v 1.5 2002/09/08 22:14:03 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _ABSINC
+#define _ABSINC
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "fsm.h"
+
+typedef struct AbsVerificationInfo Abs_VerificationInfo_t;
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void Abs_Init(void);
+EXTERN void Abs_End(void);
+EXTERN Abs_VerificationInfo_t * Abs_VerificationComputeInfo(Ntk_Network_t *network);
+EXTERN array_t * Abs_FileParseFormulaArray(FILE *fp);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _ABSINC */
+
Index: vis_dev/vis-2.3/src/abs/abs.make
===================================================================
--- vis_dev/vis-2.3/src/abs/abs.make	(revision 14)
+++ vis_dev/vis-2.3/src/abs/abs.make	(revision 14)
@@ -0,0 +1,5 @@
+CSRC += absCatalog.c absCmd.c absEvaluate.c absInternal.c absRefine.c \
+	absTranslate.c absUtil.c 
+HEADERS += abs.h absInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/abs/absCatalog.c
===================================================================
--- vis_dev/vis-2.3/src/abs/absCatalog.c	(revision 14)
+++ vis_dev/vis-2.3/src/abs/absCatalog.c	(revision 14)
@@ -0,0 +1,630 @@
+/**CFile***********************************************************************
+
+  FileName    [absCatalog.c]
+
+  PackageName [abs]
+
+  Synopsis [Functions to handle a catalog of sub-formulas to detect
+  common sub-expressions]
+
+  Author      [Abelardo Pardo <abel@vlsi.colorado.edu>]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "absInt.h" 
+
+static char rcsid[] UNUSED = "$Id: absCatalog.c,v 1.8 2005/04/16 04:22:21 fabio Exp $";
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis [A struct to keep list of subformulas to detect common
+  subexpressions]
+
+  SeeAlso     [AbsVerificationInfo]
+
+******************************************************************************/
+
+struct AbsVertexCatalog {
+  lsList fixedPoints;
+  lsList booleanOps;
+  lsList negations;
+  lsList preImages;
+  lsList identifiers;
+  lsList variables;
+};
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the fixedPoints field from a AbsVertexCatalog_t 
+  structure]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexCatalog]
+
+******************************************************************************/
+#define AbsVertexCatalogReadFixedPoints(\
+  /* AbsVertexCatalog_t * */ cPtr      \
+)                                      \
+    (cPtr->fixedPoints)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the booleanOps field from a AbsVertexCatalog_t 
+  structure]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexCatalog]
+
+******************************************************************************/
+#define AbsVertexCatalogReadBooleanOps(\
+  /* AbsVertexCatalog_t * */ cPtr      \
+)                                      \
+    (cPtr->booleanOps)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the negations field from a AbsVertexCatalog_t 
+  structure]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexCatalog]
+
+******************************************************************************/
+#define AbsVertexCatalogReadNegations(\
+  /* AbsVertexCatalog_t * */ cPtr      \
+)                                      \
+    (cPtr->negations)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the preImages field from a AbsVertexCatalog_t 
+  structure]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexCatalog]
+
+******************************************************************************/
+#define AbsVertexCatalogReadPreImages(\
+  /* AbsVertexCatalog_t * */ cPtr      \
+)                                      \
+    (cPtr->preImages)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the identifiers field from a AbsVertexCatalog_t 
+  structure]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexCatalog]
+
+******************************************************************************/
+#define AbsVertexCatalogReadIdentifiers(\
+  /* AbsVertexCatalog_t * */ cPtr      \
+)                                      \
+    (cPtr->identifiers)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the variables field from a AbsVertexCatalog_t 
+  structure]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexCatalog]
+
+******************************************************************************/
+#define AbsVertexCatalogReadVariables(\
+  /* AbsVertexCatalog_t * */ cPtr     \
+)                                     \
+    (cPtr->variables)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the fixedPoints field from a AbsVertexCatalog_t 
+  structure]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexCatalog]
+
+******************************************************************************/
+#define AbsVertexCatalogSetFixedPoints(\
+  /* AbsVertexCatalog_t * */ cPtr,    \
+  /* lsList */ data                   \
+)                                     \
+    (cPtr->fixedPoints) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the booleanOps field from a AbsVertexCatalog_t 
+  structure]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexCatalog]
+
+******************************************************************************/
+#define AbsVertexCatalogSetBooleanOps(\
+  /* AbsVertexCatalog_t * */ cPtr,    \
+  /* lsList */ data                   \
+)                                     \
+    (cPtr->booleanOps) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the negations field from a AbsVertexCatalog_t 
+  structure]
+
+  SideEffects  [AbsVertexCatalog]
+
+  SeeAlso      []
+
+******************************************************************************/
+#define AbsVertexCatalogSetNegations(\
+  /* AbsVertexCatalog_t * */ cPtr,   \
+  /* lsList */ data                  \
+)                                    \
+    (cPtr->negations) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the preImages field from a AbsVertexCatalog_t 
+  structure]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexCatalog]
+
+******************************************************************************/
+#define AbsVertexCatalogSetPreImages(\
+  /* AbsVertexCatalog_t * */ cPtr,  \
+  /* lsList */ data                 \
+)                                   \
+    (cPtr->preImages) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the identifiers field from a AbsVertexCatalog_t 
+  structure]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexCatalog]
+
+******************************************************************************/
+#define AbsVertexCatalogSetIdentifiers(\
+  /* AbsVertexCatalog_t * */ cPtr,     \
+  /* lsList */ data                    \
+)                                      \
+    (cPtr->identifiers) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the variables field from a AbsVertexCatalog_t 
+  structure]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexCatalog]
+
+******************************************************************************/
+#define AbsVertexCatalogSetVariables(\
+  /* AbsVertexCatalog_t * */ cPtr,   \
+  /* lsList */ data                  \
+)                                    \
+    (cPtr->variables) = (data)
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static AbsVertexInfo_t * LookUpBooleanOp(lsList vertexList, AbsVertex_t type, boolean polarity, AbsVertexInfo_t *leftKid, AbsVertexInfo_t *rightKid);
+static AbsVertexInfo_t * LookUpFixedPoint(lsList vertexList, boolean polarity, AbsVertexInfo_t *leftKid, int localId);
+static AbsVertexInfo_t * LookUpIdentifier(lsList vertexList, boolean polarity, char *name, char *value);
+static AbsVertexInfo_t * LookUpPreImage(lsList vertexList, boolean polarity, AbsVertexInfo_t *leftKid);
+static AbsVertexInfo_t * LookUpVariable(lsList vertexList, boolean polarity, int localId);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Allocate the structure to store the catalog of vertices]
+
+  SideEffects        []
+
+  SeeAlso            [AbsVertexCatalog]
+
+******************************************************************************/
+AbsVertexCatalog_t *
+AbsVertexCatalogInitialize(void)
+{
+  AbsVertexCatalog_t *result;
+
+  result = ALLOC(AbsVertexCatalog_t, 1);
+
+  AbsVertexCatalogSetFixedPoints(result, lsCreate());
+  AbsVertexCatalogSetBooleanOps(result, lsCreate());
+  AbsVertexCatalogSetNegations(result, lsCreate());
+  AbsVertexCatalogSetPreImages(result, lsCreate());
+  AbsVertexCatalogSetIdentifiers(result, lsCreate());
+  AbsVertexCatalogSetVariables(result, lsCreate());
+
+  return result;
+} /* End of AbsVertexCatalogInitialize */
+
+/**Function********************************************************************
+
+  Synopsis [Deallocate the structure storing the catalog vertices]
+
+  SideEffects        []
+
+  SeeAlso            [AbsVertexCatalog]
+
+******************************************************************************/
+void
+AbsVertexCatalogFree(
+  AbsVertexCatalog_t *c)
+{
+  lsDestroy(AbsVertexCatalogReadFixedPoints(c), (void (*)(lsGeneric))0);
+  lsDestroy(AbsVertexCatalogReadBooleanOps(c), (void (*)(lsGeneric))0);
+  lsDestroy(AbsVertexCatalogReadNegations(c), (void (*)(lsGeneric))0);
+  lsDestroy(AbsVertexCatalogReadPreImages(c), (void (*)(lsGeneric))0);
+  lsDestroy(AbsVertexCatalogReadIdentifiers(c), (void (*)(lsGeneric))0);
+  lsDestroy(AbsVertexCatalogReadVariables(c), (void (*)(lsGeneric))0);
+
+  FREE(c);
+
+  return;
+} /* End of AbsVertexCatalogFree */
+
+/**Function********************************************************************
+
+  Synopsis [Find or create the vertex with the given sub-formula in the vertex
+  catalog]
+
+  SideEffects []
+
+  SeeAlso [AbsVertexCatalog]
+
+******************************************************************************/
+AbsVertexInfo_t *
+AbsVertexCatalogFindOrAdd(
+  AbsVertexCatalog_t *catalog,
+  AbsVertex_t type,
+  boolean polarity,
+  AbsVertexInfo_t *leftKid,
+  AbsVertexInfo_t *rightKid,
+  int localId,
+  char *idName,
+  char *idValue
+)
+{
+  if (type == fixedPoint_c) {
+    return LookUpFixedPoint(AbsVertexCatalogReadFixedPoints(catalog),
+			    polarity, leftKid, localId);
+  }
+
+  if (type == and_c || type == xor_c || type == xnor_c) {
+    return LookUpBooleanOp(AbsVertexCatalogReadBooleanOps(catalog),
+			   type, polarity, leftKid, rightKid);
+  }
+
+  if (type == not_c) {
+    return LookUpPreImage(AbsVertexCatalogReadNegations(catalog),
+			  polarity, leftKid);
+  }
+
+  if (type == preImage_c) {
+    return LookUpPreImage(AbsVertexCatalogReadPreImages(catalog),
+			  polarity, leftKid);
+  }
+
+  if (type == identifier_c) {
+    return LookUpIdentifier(AbsVertexCatalogReadIdentifiers(catalog),
+			    polarity, idName, idValue);
+  }
+
+  if (type == variable_c) {
+    return LookUpVariable(AbsVertexCatalogReadVariables(catalog),
+			  polarity, localId);
+  }
+
+  (void) fprintf(vis_stderr, "** abs error: Unknown vertex type in function ");
+  (void) fprintf(vis_stderr, "AbsVertexCatalogFindOrAdd.\n");
+
+  return NIL(AbsVertexInfo_t);
+
+} /* End of AbsVertexCatalogFindOrAdd */
+
+/**Function********************************************************************
+
+  Synopsis           [Delete a vertex from the catalog]
+
+  SideEffects        []
+
+  SeeAlso            [AbsVertexFree]
+
+******************************************************************************/
+void
+AbsCatalogDelete(
+  AbsVertexCatalog_t *catalog,
+  AbsVertexInfo_t *vertex)
+{
+  AbsVertex_t type;
+  AbsVertexInfo_t *result;
+  lsList vertexList;
+  lsGen listGen;
+  lsHandle item;
+  lsGeneric userData;
+
+  vertexList = 0;
+  type = AbsVertexReadType(vertex);
+
+  /* Select the proper list from the catalog */
+  if (type == fixedPoint_c) {
+    vertexList = AbsVertexCatalogReadFixedPoints(catalog);
+  }
+
+  if (type == and_c || type == xor_c || type == xnor_c) {
+    vertexList = AbsVertexCatalogReadBooleanOps(catalog);
+  }
+
+  if (type == not_c) {
+    vertexList = AbsVertexCatalogReadNegations(catalog);
+  }
+
+  if (type == preImage_c) {
+    vertexList = AbsVertexCatalogReadPreImages(catalog);
+  }
+
+  if (type == identifier_c) {
+    vertexList = AbsVertexCatalogReadIdentifiers(catalog);
+  }
+
+  if (type == variable_c) {
+    vertexList = AbsVertexCatalogReadVariables(catalog);
+  }
+  
+  listGen = lsStart(vertexList);
+  while(lsNext(listGen, &result, &item) == LS_OK) {
+    if (result == vertex) {
+      lsRemoveItem(item, &userData);
+      assert(vertex == (AbsVertexInfo_t *)userData);
+      lsFinish(listGen);
+      return;
+    }
+  }
+
+  (void) fprintf(vis_stderr, "** abs error: Removing non-existent vertex from");
+  (void) fprintf(vis_stderr, " catalog\n");
+
+  return;
+} /* End of AbsCatalogDelete */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis           [Find or add a vertex to the list of boolean ops]
+
+  SideEffects        []
+
+  SeeAlso            [AbsVertexCatalogFindOrAdd]
+
+******************************************************************************/
+static AbsVertexInfo_t *
+LookUpBooleanOp(
+  lsList vertexList,
+  AbsVertex_t type,
+  boolean polarity,
+  AbsVertexInfo_t *leftKid,
+  AbsVertexInfo_t *rightKid)
+{
+  lsGen listGen;
+  AbsVertexInfo_t *result;
+
+  /* Start the generator and traverse the list */
+  listGen = lsStart(vertexList);
+  while(lsNext(listGen, &result, NIL(lsHandle)) == LS_OK) {
+    if (AbsVertexReadType(result) == type &&
+	AbsVertexReadLeftKid(result) == leftKid &&
+	AbsVertexReadRightKid(result) == rightKid &&
+	AbsVertexReadPolarity(result) == polarity) {
+      AbsVertexReadRefs(result)++;
+      lsFinish(listGen);
+      return result;
+    }
+  }
+
+  /* Item has not been found */
+  lsFinish(listGen);
+  result = AbsVertexInitialize();
+  lsNewBegin(vertexList, (lsGeneric)result, NIL(lsHandle));
+
+  return result;
+} /* End of LookUpBooleanOp */
+
+/**Function********************************************************************
+
+  Synopsis           [Find or add a vertex to the list of fixedpoints]
+
+  SideEffects        []
+
+  SeeAlso            [AbsVertexCatalogFindOrAdd]
+
+******************************************************************************/
+static AbsVertexInfo_t *
+LookUpFixedPoint(
+  lsList vertexList,
+  boolean polarity,
+  AbsVertexInfo_t *leftKid,
+  int localId)
+{
+  lsGen listGen;
+  AbsVertexInfo_t *result;
+
+  /* Start the generator and traverse the list */
+  listGen = lsStart(vertexList);
+  while(lsNext(listGen, &result, NIL(lsHandle)) == LS_OK) {
+    if (AbsVertexReadLeftKid(result) == leftKid &&
+	AbsVertexReadPolarity(result) == polarity &&
+	AbsVertexReadVarId(AbsVertexReadFpVar(result)) == localId) {
+      AbsVertexReadRefs(result)++;
+      lsFinish(listGen);
+      return result;
+    }
+  }
+
+  /* Item has not been found */
+  lsFinish(listGen);
+  result = AbsVertexInitialize();
+  lsNewBegin(vertexList, (lsGeneric)result, NIL(lsHandle));
+
+  return result;
+} /* End of LookUpFixedPoint */
+
+/**Function********************************************************************
+
+  Synopsis           [Find or add a vertex to the list of identifiers]
+
+  SideEffects        []
+
+  SeeAlso            [AbsVertexCatalogFindOrAdd]
+
+******************************************************************************/
+static AbsVertexInfo_t *
+LookUpIdentifier(
+  lsList vertexList,
+  boolean polarity,
+  char *name,
+  char *value)
+{
+  lsGen listGen;
+  AbsVertexInfo_t *result;
+
+  /* Start the generator and traverse the list */
+  listGen = lsStart(vertexList);
+  while(lsNext(listGen, &result, NIL(lsHandle)) == LS_OK) {
+    if (AbsVertexReadPolarity(result) == polarity &&
+	strcmp(AbsVertexReadName(result), name) == 0 && 
+	strcmp(AbsVertexReadValue(result), value) == 0) {
+      AbsVertexReadRefs(result)++;
+      lsFinish(listGen);
+      return result;
+    }
+  }
+
+  /* Item has not been found */
+  lsFinish(listGen);
+  result = AbsVertexInitialize();
+  lsNewBegin(vertexList, (lsGeneric)result, NIL(lsHandle));
+
+  return result;
+} /* End of LookUpIdentifier */
+
+/**Function********************************************************************
+
+  Synopsis           [Find or add a vertex to the list of preimages]
+
+  SideEffects        []
+
+  SeeAlso            [AbsVertexCatalogFindOrAdd]
+
+******************************************************************************/
+static AbsVertexInfo_t *
+LookUpPreImage(
+  lsList vertexList,
+  boolean polarity,
+  AbsVertexInfo_t *leftKid)
+{
+  lsGen listGen;
+  AbsVertexInfo_t *result;
+
+  /* Start the generator and traverse the list */
+  listGen = lsStart(vertexList);
+  while(lsNext(listGen, &result, NIL(lsHandle)) == LS_OK) {
+    if (AbsVertexReadLeftKid(result) == leftKid &&
+	AbsVertexReadPolarity(result) == polarity) {
+      AbsVertexReadRefs(result)++;
+      lsFinish(listGen);
+      return result;
+    }
+  }
+
+  /* Item has not been found */
+  lsFinish(listGen);
+  result = AbsVertexInitialize();
+  lsNewBegin(vertexList, (lsGeneric)result, NIL(lsHandle));
+
+  return result;
+} /* End of LookUpPreImage */
+
+/**Function********************************************************************
+
+  Synopsis           [Find or add a vertex to the list of variables]
+
+  SideEffects        []
+
+  SeeAlso            [AbsVertexCatalogFindOrAdd]
+
+******************************************************************************/
+static AbsVertexInfo_t *
+LookUpVariable(
+  lsList vertexList,
+  boolean polarity,
+  int localId)
+{
+  lsGen listGen;
+  AbsVertexInfo_t *result;
+
+  /* Start the generator and traverse the list */
+  listGen = lsStart(vertexList);
+  while(lsNext(listGen, &result, NIL(lsHandle)) == LS_OK) {
+    if (AbsVertexReadPolarity(result) == polarity &&
+	AbsVertexReadVarId(result) == localId) {
+      AbsVertexReadRefs(result)++;
+      lsFinish(listGen);
+      return result;
+    }
+  }
+
+  /* Item has not been found */
+  lsFinish(listGen);
+  result = AbsVertexInitialize();
+  lsNewBegin(vertexList, (lsGeneric)result, NIL(lsHandle));
+
+  return result;
+} /* End of LookUpVariable */
+
Index: vis_dev/vis-2.3/src/abs/absCmd.c
===================================================================
--- vis_dev/vis-2.3/src/abs/absCmd.c	(revision 14)
+++ vis_dev/vis-2.3/src/abs/absCmd.c	(revision 14)
@@ -0,0 +1,784 @@
+/**CFile***********************************************************************
+
+  FileName    [absCmd.c]
+
+  PackageName [abs]
+
+  Synopsis    [Encapsulation for the incremental_ctl_verification command.]
+
+  Author      [Abelardo Pardo <abel@vlsi.colorado.edu>]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "absInt.h"
+
+static char rcsid[] UNUSED = "$Id: absCmd.c,v 1.37 2002/09/08 22:13:50 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+static jmp_buf timeOutEnv;
+static int absTimeOut;
+static long alarmLap;
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandAbsCtl(Hrc_Manager_t **hmgr, int argc, char **argv);
+static AbsOptions_t * ParseAbsCtlOptions(int argc, char **argv);
+static void TimeOutHandle(int sigType);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Initialize abs package]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Abs_Init(void)
+{
+  Cmd_CommandAdd("incremental_ctl_verification", CommandAbsCtl, 0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [End abs package]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Abs_End(void)
+{
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis [Encapsulation of the incremental_ctl_verification command.]
+
+  Description [The function starts by parsing the options. After that it checks
+  for the network structure. The ctl formulas are read and check for
+  correctness. Once the formulas have been read, they need to be translated
+  from the CTL representation to the operational graph representation required
+  for the incremental algorithm. The function AbsCtlFormulaArrayTranslate
+  performs this task. After all these points have been cleared, the timeout is
+  programmed and the verification process starts.
+  
+  Once the result has been obtained, the function prints the result as well as
+  some execution statistics, de-allocates all the required data structures and
+  returns.]
+
+  SideEffects        []
+
+  CommandName        [incremental_ctl_verification] 	   
+
+  CommandSynopsis [Verify a set of CTL formulas by means of an incremental
+  model checking algorithm.]
+
+  CommandArguments [\[-D &lt;number&gt;\] \[-e\] \[-h\]  \[-n\] \
+  \[-s\] \[-t &lt;seconds&gt;\] \[-v &lt;number&gt;\] \[-V &lt;number&gt;\] 
+  \[-x\] &lt;ctlfile&gt;]]
+
+  CommandDescription [
+  Like model_check, incremental_ctl_verification verifies a set of CTL
+  formulas.  It uses a system of abstraction and incremental
+  refinement 
+  that works for all of (fair)CTL, using over and underapproximations as
+  appropriate. See \[1,2\] for details.
+  
+  <p> Incremental_ctl_verification (also known as Abs or Trasgo) 
+  works especially well on large systems on which mc is too slow or
+  runs out of memory.  
+  Unlike amc, it can handle full CTL, not just the universal or
+  existential subsets of it. Also, fairness is supported with this
+  command, although it tends to be inefficient.  
+  Support for the mu-calculus is not yet implemented.
+
+  <p>Before using incremental_ctl_verification, a flattened hierarchy
+  should be present. See `help init`. Using dynamic variable reordering
+  may be beneficial on large systems. See `help
+  dynamic_var_ordering`. 
+
+  <p>Fairness constraints can be applied using
+  `read_fairness', as with mc.  When using incremental verification
+  with fairness, there is no check for unfair initial states. Please
+  be aware that if there are no fair initial states, all formulas
+  starting with "A" will be trivially true. Mc will tell you whether
+  you have fair initial states.
+
+  <p>A typical use would be
+  <br>incremental_ctl_verification -D2 &lt;ctl_file&gt;
+
+  <p>For every formula, incremental verification will report whether
+  it is valid or invalid, or it returns an inconclusive result. A formula is
+  valid iff it holds for all initial states. An error trace is not provided.
+
+  For the people who are used to mc: The -r option is not supported,
+  incremental verification always reduces the fsm with respect to
+  individual formulas. The -c option is not supported either. There is
+  no sharing of subformulas between different formulas.
+
+  <p>Command options:<p>
+
+  <dl>
+
+  <dt> -D &lt;number&gt;
+  <dd> Specify extent to which don't cares are used to simplify the
+  MDDs.
+  <ul> 
+  <li>0: No Don't Cares used.
+  <li>1: Use reachability information to compute the don't-care
+     set. Reachability is performed by formula. This is different from
+     mc, where reachability is performed only once.
+  <li>2: Use reachability information, and minimize the transition relation
+     with respect to the `frontier set' (aggresive minimization).
+  </ul>
+  The equivalent of mc -D3 is not implemented.
+
+  <dt> -e
+  <dd>Compute the set of fair states (those satisfying the formula EGfair TRUE)
+  before the verification process and use the result as care set. In certain
+  cases this will speed up computation when fairness constraints are
+  present. In other cases it will slow it down.
+
+  <dt> -h
+  <dd> Print the command usage.
+
+  <dt> -n
+  <dd> Try to prove the negation of every formula. In some cases it
+  may be easier to prove the negation of a formula than the formula
+  itself. For systems with only one initial state, a formula is true
+  iff its negation is false. Note that for systems with multiple
+  initial states a formula and its negation can both be false.
+
+  <dt> -s
+  <dd> Print a summary of statistics after the verification.
+
+  <dt> -t &lt;secs&gt;
+  <dd> Time in seconds allowed to spend in the verification.  The default is
+  infinity.
+
+  <dt> -v &lt;number&gt;
+  <dd>Specify verbosity level. Use 0 for no feedback (default), 1
+  for more and 2 for maximum feedback. This option can not be used in
+  conjunction with -V.
+
+  <dt> -V &lt;number&gt;
+  <dd> Mask specifying type of information to be printed out while
+  verifying the formulas. This allows for a finer control than -v. -V
+  and -v cannot be used simultaneously.
+  The mask is given as a binary number, by taking the
+  logical or of the following binary values. One does not have to
+  convert these numbers to decimal.<p> 
+  
+                        1  number of primary inputs and flip-flops <p>
+                       10  labeled operational graph of the formulas <p>
+                      100  cpu-time for the computation in each vertex <p> 
+                     1000  cubes of the function sat for each vertex <p> 
+                    10000  cubes of the function goalSet for each vertex <p> 
+                   100000  vertex data structure contents after evaluation <p>
+                  1000000  cubes in the care set for every evaluation <p> 
+                 10000000  size of care set for every evaluation <p> 
+                100000000  number of states that satisfy every sub-formula <p> 
+               1000000000  number of overall reachable states <p> 
+              10000000000  cubes for every iteration of a fixed point <p> 
+             100000000000  size of the BDD in each iteration in a fix-point <p> 
+            1000000000000  labeled operational graph in dot format <p> 
+           10000000000000  number of envelope states <p> 
+          100000000000000  number of states to be refined <p> 
+         1000000000000000  size of the refinement operands <p> 
+        10000000000000000  cubes of the refinement operands <p> 
+       100000000000000000  Number of latches before and after simplification <p>
+      1000000000000000000  report partial progress (i.e. reach, EG(true),...)<p>
+     10000000000000000000  Begin/End refinement process <p> 
+    100000000000000000000  Size of goal set <p> 
+   1000000000000000000000  cubes of the goal set <p> 
+  10000000000000000000000  Contents of vertex after refinement <p> 
+
+  <dt> -x
+  <dd> Perform the verification exactly. No approximation is done.
+
+  <dt> &lt;ctlfile&gt; 
+  <dd> File containing the CTL formulas to be verified.
+
+  <dt> Related "set" options: <p>
+  <dt> ctl_change_bracket &lt;yes/no&gt;
+  <dd> Vl2mv automatically converts "\[\]" to "&lt;&gt;" in node names,
+  therefore CTL parser does the same thing. However, in some cases a user
+  does not want to change node names in CTL parsing. Then, use this set
+  option by giving "no". Default is "yes".
+  <p>
+
+  <dt> See also commands : model_check, incremental_ctl_verification <p>
+
+  </dl>
+
+  <p>1. A. Pardo and G. Hachtel. Automatic abstraction techniques for
+  propositional mu-calculus model checking. In <I>9th Conference on
+  Computer Aided Verification (CAV'97)</I>. Springer-Verlag. Pages
+  12-23, 1997.
+  <p>2. A. Pardo and G. Hachtel. Incremental CTL model checking using BDD
+  subsetting.  In <I>35th Design Automation Conference
+  (DAC'98)</I>. pages 457-462, 1998.   
+  ]
+
+******************************************************************************/
+static int
+CommandAbsCtl(
+  Hrc_Manager_t **hmgr,
+  int argc,
+  char **argv)
+{
+  AbsVerificationResult_t formulaResult;
+  Abs_VerificationInfo_t  *absInfo;
+  AbsVertexInfo_t         *formulaPtr;
+  Ctlp_Formula_t          *ctlFormula;
+  AbsOptions_t            *options;
+  Ntk_Network_t           *network;
+  array_t                 *ctlArray;
+  array_t                 *existCtlArray;
+  array_t                 *fairArray;
+  array_t                 *existFairArray;
+  array_t                 *graphArray;
+  array_t                 *resultArray;
+  FILE                    *formulaFile;
+  boolean                 correctSemantics;
+  Fsm_Fsm_t               *fsm;
+  Fsm_Fairness_t          *fairness;
+  long                    cpuTime;
+  int                     status;
+  int                     i;
+  int                     numConjuncts;
+
+  /* Initialize some variables */
+  graphArray = NIL(array_t);
+  resultArray = NIL(array_t);
+  options = NIL(AbsOptions_t);
+  ctlArray = NIL(array_t);
+  existCtlArray = NIL(array_t);
+  fairArray = NIL(array_t);
+  existFairArray = NIL(array_t);
+  absInfo = NIL(Abs_VerificationInfo_t);
+
+  if (bdd_get_package_name() != CUDD) {
+    fprintf(vis_stderr, "** abs error : incremental_ctl_verification ");
+    fprintf(vis_stderr, "is currently supported by only CUDD.\n");
+    status = 1;
+    goto cleanup;
+  }
+
+  error_init();
+
+  /* Parse the options */
+  options = ParseAbsCtlOptions(argc, argv);
+
+  /* Check if there has been any error parsing the options */
+  if (!options) {
+    status = 1;
+    goto cleanup;
+  }
+
+  /* Obtain the network */
+  network = Ntk_HrcManagerReadCurrentNetwork( *hmgr );
+  if ( network == NIL( Ntk_Network_t)) {
+    (void) fprintf(vis_stdout, "%s\n", error_string());
+    error_init();
+    status = 1;
+    goto cleanup;
+  }
+
+  /* Open the file with the ctl formulas */
+  formulaFile = Cmd_FileOpen(AbsOptionsReadFileName(options), "r", 
+			     NIL(char *), 0);
+  if (formulaFile == NIL(FILE)) {
+    status = 1;
+    goto cleanup;
+  }
+
+  /* Parse the formulas and close the file */
+  ctlArray = Ctlp_FileParseFormulaArray(formulaFile);
+  fclose(formulaFile);
+
+  if (ctlArray == NIL(array_t)) {
+    (void) fprintf(vis_stderr, 
+		   "** abs error: Error while parsing CTL formulas\n");
+    status = 1;
+    goto cleanup;
+  }
+
+  /* Read the fairness constraints */
+  fsm = Fsm_HrcManagerReadCurrentFsm(*hmgr);
+  if (fsm != NIL(Fsm_Fsm_t)){
+    fairness = Fsm_FsmReadFairnessConstraint(fsm);
+    if (fairness != NIL(Fsm_Fairness_t)){
+      fairArray = array_alloc(Ctlp_Formula_t *,0);
+      numConjuncts = Fsm_FairnessReadNumConjunctsOfDisjunct(fairness, 0);
+      for (i = 0; i < numConjuncts; i++) {
+        ctlFormula = Fsm_FairnessReadFinallyInfFormula(fairness, 0, i);
+        if ((Ctlp_FormulaReadType(ctlFormula) != Ctlp_TRUE_c) &&
+            (Ctlp_FormulaReadType(ctlFormula) != Ctlp_FALSE_c)){
+	  array_insert_last(Ctlp_Formula_t *, fairArray, 
+			    Ctlp_FormulaDup(ctlFormula));
+        }
+      }
+      if (array_n(fairArray) == 0){
+        array_free(fairArray);
+        fairArray = NIL(array_t);
+      }
+    }
+  }
+
+  /* Verify that the formulas are semantically correct */
+  correctSemantics = TRUE;
+
+  /* Check the semantics of the temporal formulas */
+  arrayForEachItem(Ctlp_Formula_t *, ctlArray, i, ctlFormula) {
+    if (!Mc_FormulaStaticSemanticCheckOnNetwork(ctlFormula, network, FALSE)) {
+      (void) fprintf(vis_stdout, 
+		 "** abs error: Inconsistency detected in formula number %d.\n",
+		     i);
+      (void) fprintf(vis_stdout, "ABS: %s\n", error_string());
+      error_init();
+      correctSemantics = FALSE;
+    }
+  }
+
+  /* Check the fairness constraints */
+  if (fairArray != NIL(array_t)) {
+    arrayForEachItem(Ctlp_Formula_t *, fairArray, i, ctlFormula) {
+      if (!Mc_FormulaStaticSemanticCheckOnNetwork(ctlFormula, network, FALSE)) {
+	(void) fprintf(vis_stdout, 
+		       "** abs error: Inconsistency detected in fairness ");
+	(void) fprintf(vis_stdout, "constraint number %d.\n", i);
+	(void) fprintf(vis_stdout, "ABS: %s\n", error_string());
+	error_init();
+	correctSemantics = FALSE;
+      }
+    }
+  }
+
+  /* If there is any inconsistency, do not execute the command */
+  if (!correctSemantics) {
+    status = 1;
+    goto cleanup;
+  }
+
+  /* Replace XORs and EQs with equivalent subtrees. We insist on having
+   * only monotonic operators. */
+  Ctlp_FormulaArrayMakeMonotonic(ctlArray);
+  Ctlp_FormulaArrayMakeMonotonic(fairArray);
+
+  /* Translate the ctl formulas and fairness constraints to existential form */
+  existCtlArray = Ctlp_FormulaArrayConvertToExistentialFormTree(ctlArray);
+  if (fairArray != NIL(array_t)) {
+    existFairArray = Ctlp_FormulaArrayConvertToExistentialFormTree(fairArray);
+  }
+
+  /* Compute the information related to the system being verified */
+  absInfo = Abs_VerificationComputeInfo(network);
+  if (absInfo == NIL(Abs_VerificationInfo_t)) {
+    (void) fprintf(vis_stdout, "** abs error: Error computing the information required ");
+    (void) fprintf(vis_stdout, "for verification.\n");
+    status = 1;
+    goto cleanup;
+  }
+
+  /* Store the options */
+  AbsVerificationInfoSetOptions(absInfo, options);
+
+  /* Translate the array of CTL formulas to operational graphs */
+  graphArray = AbsCtlFormulaArrayTranslate(absInfo, existCtlArray, 
+					   existFairArray);
+
+  if (graphArray == NIL(array_t)) {
+    (void) fprintf(vis_stderr, 
+		   "** abs error: Error translating CTL formulas.\n");
+    (void) fprintf(vis_stderr, "** abs error: Aborting command.\n");
+    status = 1;
+    goto cleanup;
+  }
+
+  /* Program the timeOut if pertinent */
+  if (AbsOptionsReadTimeOut(options) > 0) {
+    /* Set the static variables */
+    absTimeOut = AbsOptionsReadTimeOut(options);
+    alarmLap = util_cpu_time();
+
+    /* Set the handler */
+    (void) signal(SIGALRM, TimeOutHandle);
+    (void) alarm(AbsOptionsReadTimeOut(options));
+    
+    /* Set the jump for the timeout */
+    if (setjmp(timeOutEnv) > 0) {
+      (void) fprintf(vis_stdout,
+		     "# ABS: Timeout occurred after %7.1f CPU seconds\n",
+		     (util_cpu_time() - alarmLap)/1000.0);
+      (void) fprintf(vis_stdout, "# ABS: data may be corrupted.\n");
+      alarm(0);
+      return 1;
+    }
+  }
+
+  /* Print the graph in DOT format */
+  if (AbsOptionsReadVerbosity(options) & ABS_VB_PRDOT) {
+      AbsVertexPrintDot(vis_stdout, graphArray);
+  }
+
+  /* Set the cpu-time lap */
+  cpuTime = util_cpu_time();
+
+  /* Verify every formula */
+  resultArray = AbsFormulaArrayVerify(absInfo, graphArray);
+
+  /* Print out the execution time*/
+  (void) fprintf(vis_stdout, "ABS: Total Verification Time: %7.1f secs\n",
+		 (util_cpu_time() - cpuTime)/1000.0);
+  
+  /* Print out the results */
+  /* RB changed this to take into account multiple initial states in negtd
+     formulas */
+  arrayForEachItem(AbsVerificationResult_t, resultArray, i, formulaResult) {
+    (void) fprintf(vis_stdout, "# ABS: formula ");
+    switch (formulaResult) {
+    case trueVerification_c:
+      (void) fprintf(vis_stdout, "passed --- ");
+      break;
+    case falseVerification_c:
+      (void) fprintf(vis_stdout, "failed --- ");
+      break;
+    case inconclusiveVerification_c:
+      (void) fprintf(vis_stdout, "undecided --- ");
+    }
+    if (AbsOptionsReadNegateFormula(options))
+      fprintf(vis_stdout, "NOT[ ");
+    Ctlp_FormulaPrint(vis_stdout, 
+		      array_fetch(Ctlp_Formula_t *, ctlArray, i));
+    if (AbsOptionsReadNegateFormula(options))
+      fprintf(vis_stdout, " ]\n");
+    else
+      fprintf(vis_stdout, "\n");
+  }
+  
+  /* Print the stats if selected by command line option */
+  if (AbsOptionsReadPrintStats(options)) {
+    int i;
+    
+    AbsStatsPrintReport(vis_stdout, AbsVerificationInfoReadStats(absInfo));
+    
+    (void) fprintf(vis_stdout, "# ABS: -- Command Line Options --\n");
+    (void) fprintf(vis_stdout, "# ABS: ");
+    for (i=0; i<argc; i++) {
+      (void) fprintf(vis_stdout, "%s ", argv[i]);
+    }
+    (void) fprintf(vis_stdout, "\n");
+  }
+  
+  /* Disconnect the alarm */
+  alarm(0);
+  
+  status = 0;
+  
+  /* Clean up the memory and return */
+  cleanup:
+  if (graphArray != NIL(array_t)) {
+    arrayForEachItem(AbsVertexInfo_t *, graphArray, i, formulaPtr) {
+      AbsVertexFree(AbsVerificationInfoReadCatalog(absInfo), formulaPtr,
+		    NIL(AbsVertexInfo_t));
+    }
+    array_free(graphArray);
+  }
+  if (resultArray != NIL(array_t)) {
+    array_free(resultArray);
+  }
+  if (options != NIL(AbsOptions_t)) {
+    AbsOptionsFree(options);
+  }
+  if (ctlArray != NIL(array_t)) {
+    Ctlp_FormulaArrayFree(ctlArray);
+  }
+  if (existCtlArray != NIL(array_t)) {
+    Ctlp_FormulaArrayFree(existCtlArray);
+  }
+  if (fairArray != NIL(array_t)) {
+    Ctlp_FormulaArrayFree(fairArray);
+  }
+  if (existFairArray != NIL(array_t)) {
+    Ctlp_FormulaArrayFree(existFairArray);
+  }
+  if (absInfo != NIL(Abs_VerificationInfo_t)) {
+    AbsVerificationInfoFree(absInfo);
+  }
+  
+  return status;
+} /* End of CommandAbsCtl */
+
+/**Function********************************************************************
+
+  Synopsis [Parses the options given to the incremental_ctl_verification command
+  and stores them into a structure.]
+
+  SideEffects        []
+
+  SeeAlso            [CommandAbsCtl]
+
+******************************************************************************/
+static AbsOptions_t *
+ParseAbsCtlOptions(
+  int argc,
+  char **argv)
+{
+  AbsOptions_t *result;
+  char *fileName;
+  boolean reachability;
+  boolean envelope;
+  boolean exact;
+  boolean printStats;
+  boolean minimizeIterate;
+  boolean negateFormula;
+  boolean partApprox;
+  boolean DFlag, eFlag, nFlag, pFlag, sFlag, tFlag, vFlag, xFlag;
+  long verbosity;
+  int intVerbosity;
+  int timeOut;
+  int dcValue;
+  int c;
+  unsigned int i;
+
+  /* Default Options */
+  DFlag = eFlag = nFlag = pFlag = sFlag = tFlag = FALSE;
+  vFlag = xFlag = FALSE;
+  reachability = FALSE;
+  envelope = FALSE;
+  exact = FALSE;
+  printStats = FALSE;
+  minimizeIterate = FALSE;
+  negateFormula = FALSE;
+  partApprox = FALSE;
+  verbosity = 0;
+  intVerbosity = 0;
+  timeOut = -1;
+  dcValue = 0;
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "D:ehnpst:v:V:x")) != EOF) {
+    switch(c) {
+      case 'D':
+	dcValue = atoi(util_optarg);
+	if (DFlag || (dcValue < 0) || (dcValue > 2)) {
+	  goto usage;
+	}
+	if (dcValue > 0) {
+	  reachability = TRUE;
+	}
+	if (dcValue > 1) {
+	  minimizeIterate = TRUE;
+	}
+	DFlag = TRUE;
+	break;
+      case 'e':
+	if (eFlag) {
+	  goto usage;
+	}
+	envelope = TRUE;
+	eFlag = TRUE;
+	break;
+      case 'h':
+        goto usage;
+      case 'n':
+	if (nFlag) {
+	  goto usage;
+	}
+	negateFormula = TRUE;
+	nFlag = TRUE;
+	break;
+      case 'p':
+	if (pFlag) {
+	  goto usage;
+	}
+	partApprox = TRUE;
+	pFlag = TRUE;
+        break;
+      case 's':
+	if (sFlag) {
+	  goto usage;
+	}
+	printStats = TRUE;
+	sFlag = TRUE;
+        break;
+      case 't':
+	if (tFlag) {
+	  goto usage;
+	}
+	timeOut = atoi(util_optarg);
+	tFlag = TRUE;
+        break;
+      case 'v':
+	if (vFlag) {
+	  goto usage;
+	}
+	intVerbosity =  atoi(util_optarg);
+        if (intVerbosity == 1){
+	  verbosity = 131849;
+	}else if (intVerbosity == 2){
+	  verbosity = 8388607;
+	}else{
+	  verbosity = 0;
+        }
+        vFlag = TRUE;
+	break;
+      case 'V':
+	if (vFlag) {
+	  goto usage;
+	}
+	for(i=0;i<strlen(util_optarg)-1;i++){
+          if (util_optarg[i] != '0' && util_optarg[i] != '1'){
+	     goto usage;
+	  }
+	}
+	verbosity =  strtol(util_optarg, NIL(char *), 2);
+	vFlag = TRUE;
+        break;
+      case 'x':
+	if (xFlag) {
+	  goto usage;
+	}
+	exact = TRUE;
+	xFlag = TRUE;
+	break;
+      default:
+	goto usage;
+    }
+  }
+
+  /* Check if there is still one parameter left */
+  if (argc - util_optind != 1) {
+    goto usage;
+  }
+
+  /* Obtain the filename from the end of the command line */
+  fileName = util_strsav(argv[util_optind]);
+  
+  /* Store the options  */
+  result = AbsOptionsInitialize();
+  
+  AbsOptionsSetVerbosity(result, verbosity);
+  AbsOptionsSetTimeOut(result, timeOut);
+  AbsOptionsSetReachability(result, reachability);
+  AbsOptionsSetEnvelope(result, envelope);
+  AbsOptionsSetFileName(result, fileName);
+  AbsOptionsSetExact(result, exact);
+  AbsOptionsSetPrintStats(result, printStats);
+  AbsOptionsSetMinimizeIterate(result, minimizeIterate);
+  AbsOptionsSetNegateFormula(result, negateFormula);
+  AbsOptionsSetPartApprox(result, partApprox);
+
+  return result;
+
+ usage:
+  fprintf(vis_stderr,"usage: incremental_ctl_verification [-D <number>] [-e] [-h] [-n] [-s]\n");
+  fprintf(vis_stderr,"[-t <seconds>] [-v <number>] [-V <number>] [-x] <ctlfile>\n");
+  fprintf(vis_stderr,"\n");
+  fprintf(vis_stderr,"Command options:\n");
+  fprintf(vis_stderr,"-D <number>\n");
+  fprintf(vis_stderr,"   Specify extent to which don't cares are used to simplify\n");
+  fprintf(vis_stderr,"   the MDDs.\n");
+  fprintf(vis_stderr,"   0: No Don't Cares used.\n");
+  fprintf(vis_stderr,"   1: Use reachability information to compute the don't-care\n");
+  fprintf(vis_stderr,"     set. Reachability is performed by formula. This is different from\n");
+  fprintf(vis_stderr,"     mc, where reachability is performed only once.\n");
+  fprintf(vis_stderr,"   2: Use reachability information, and minimize the transition relation\n");
+  fprintf(vis_stderr,"     with respect to the `frontier set' (aggresive minimization).\n");
+  fprintf(vis_stderr,"-e\n");
+  fprintf(vis_stderr,"   Compute the set of fair states (those satisfying the formula\n");
+  fprintf(vis_stderr,"   EGfair TRUE) before the verification process and use the result\n");
+  fprintf(vis_stderr,"   as care set.\n");
+  fprintf(vis_stderr,"-h\n");
+  fprintf(vis_stderr,"   Print the command usage.\n");
+  fprintf(vis_stderr,"-n\n");
+  fprintf(vis_stderr,"   Try to prove the negation of every formula\n");
+  fprintf(vis_stderr,"-s\n");
+  fprintf(vis_stderr,"   Print a summary of statistics after the verification.\n");
+  fprintf(vis_stderr,"-t <secs>\n");
+  fprintf(vis_stderr,"   Time in seconds allowed to spend in the verification.\n");
+  fprintf(vis_stderr,"-v <number>\n");
+  fprintf(vis_stderr,"   Specify verbosity level. Use 0 for no feedback (default), 1 for\n");
+  fprintf(vis_stderr,"   more and 2 for maximum feedback. This option can not be used\n");
+  fprintf(vis_stderr,"   in conjunction with -V.\n");
+  fprintf(vis_stderr,"-V <number>\n");
+  fprintf(vis_stderr,"   Mask specifying type of information to be printed out while\n");
+  fprintf(vis_stderr,"   verifying the formulas. See the help page.\n");
+  fprintf(vis_stderr,"-x\n");
+  fprintf(vis_stderr,"   Perform the verification exactly. No approximation is done.\n");
+  fprintf(vis_stderr,"<ctlfile>\n");
+  fprintf(vis_stderr,"   File containing the CTL formulas to be verified.\n");
+  return NIL(AbsOptions_t);
+} /* End of ParseAbsCtlOptions */
+
+/**Function********************************************************************
+
+  Synopsis    [Handle function for timeout.]
+
+  Description [This function is called when the process receives a signal of
+  type alarm. Since alarm is set with elapsed time, this function checks if the
+  CPU time corresponds to the timeout of the command. If not, it reprograms the
+  alarm to fire later and check if the CPU limit has been reached.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+TimeOutHandle(
+  int sigType)
+{
+  long seconds;
+
+  seconds = (util_cpu_time() - alarmLap) / 1000;
+  
+  if (seconds < absTimeOut) {
+    unsigned slack;
+
+    slack = absTimeOut - seconds;
+    (void) signal(SIGALRM, TimeOutHandle);
+    (void) alarm(slack);
+  }
+  else {
+    longjmp(timeOutEnv, 1);
+  }
+} /* End of TimeOutHandle */
Index: vis_dev/vis-2.3/src/abs/absEvaluate.c
===================================================================
--- vis_dev/vis-2.3/src/abs/absEvaluate.c	(revision 14)
+++ vis_dev/vis-2.3/src/abs/absEvaluate.c	(revision 14)
@@ -0,0 +1,997 @@
+/**CFile***********************************************************************
+
+  FileName    [absEvaluate.c]
+
+  PackageName [abs]
+
+  Synopsis [Evaluation procedures for the abstraction based mu-calculus model
+  checker.]
+
+  Author      [Abelardo Pardo <abel@vlsi.colorado.edu>]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "absInt.h"
+
+static char rcsid[] UNUSED = "$Id: absEvaluate.c,v 1.19 2002/09/19 05:25:00 fabio Exp $";
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void EvaluateVariable(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr);
+static void EvaluateIdentifier(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr);
+static void EvaluateNot(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr);
+static void EvaluateAnd(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr);
+static void EvaluateFixedPoint(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr);
+static void EvaluatePreImage(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr);
+static mdd_t * OverApproximatePreImageWithSubFSM(Abs_VerificationInfo_t *absInfo, mdd_t *lowerBound, mdd_t *upperBound, mdd_t *careSet);
+static mdd_t * OverApproximatePreImageWithBddSubsetting(Abs_VerificationInfo_t *absInfo, mdd_t *lowerBound, mdd_t *upperBound, mdd_t *careSet);
+static mdd_t * UnderApproximatePreImageWithBddSubsetting(Abs_VerificationInfo_t *absInfo, mdd_t *lowerBound, mdd_t *upperBound, mdd_t *careSet);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Procedure to evaluate a sub-formula]
+
+  Description [This procedure is simply a switch to call the apropriate
+  evaluation procedures depending on the type of formula]
+
+  SideEffects [EvaluateFixedPoint, EvaluateAnd, EvaluateNot, EvaluatePreImage,
+  EvaluateIdentifier, EvaluateVariable]
+
+******************************************************************************/
+void
+AbsSubFormulaVerify(
+  Abs_VerificationInfo_t *absInfo,
+  AbsVertexInfo_t *vertexPtr)
+{
+  AbsStats_t *stats;
+  mdd_manager *mddManager;
+  mdd_t *oldTmpCareSet = NIL(mdd_t);
+  
+  long verbosity;
+
+  stats = AbsVerificationInfoReadStats(absInfo);
+  mddManager = AbsVerificationInfoReadMddManager(absInfo);
+
+  /* If the current vertex has more than one parent, the temporary care set
+   * must be reset (because it depends on the path that led to this vertex */
+  if (lsLength(vertexPtr->parent) > 1) {
+    oldTmpCareSet = AbsVerificationInfoReadTmpCareSet(absInfo);
+    AbsVerificationInfoSetTmpCareSet(absInfo, mdd_one(mddManager));
+  }
+
+  switch (AbsVertexReadType(vertexPtr)) {
+    case fixedPoint_c:
+      EvaluateFixedPoint(absInfo, vertexPtr);
+      AbsStatsReadEvalFixedPoint(stats)++;
+      break;
+    case and_c: 
+      EvaluateAnd(absInfo, vertexPtr);
+      AbsStatsReadEvalAnd(stats)++;
+      break;
+    case not_c:
+      EvaluateNot(absInfo, vertexPtr);
+      AbsStatsReadEvalNot(stats)++;
+      break;
+    case preImage_c:
+      EvaluatePreImage(absInfo, vertexPtr);
+      AbsStatsReadEvalPreImage(stats)++;
+      break;
+    case identifier_c:
+      EvaluateIdentifier(absInfo, vertexPtr);
+      AbsStatsReadEvalIdentifier(stats)++;
+      break;
+    case variable_c:
+      EvaluateVariable(absInfo, vertexPtr);
+      AbsStatsReadEvalVariable(stats)++;
+      break;
+    default: fail("Encountered unknown type of vertex\n");
+    }
+
+  verbosity = AbsOptionsReadVerbosity(AbsVerificationInfoReadOptions(absInfo));
+
+  /* Print the size of the care set */
+  if (verbosity & ABS_VB_CARESZ) {
+    (void) fprintf(vis_stdout, "ABS: Size of Care Set: ");
+    (void) fprintf(vis_stdout, "%d Nodes.\n", 
+		   mdd_size(AbsVerificationInfoReadCareSet(absInfo)));
+  }
+
+  /* Print the care set */
+  if (verbosity & ABS_VB_CARE) {
+    (void) fprintf(vis_stdout, "ABS: Care Set for Evaluation:\n");
+    AbsBddPrintMinterms(AbsVerificationInfoReadCareSet(absInfo));
+  }
+
+  /* Print the contents of the vertex */
+  if (verbosity & ABS_VB_VTXCNT) {
+    AbsVertexPrint(vertexPtr, NIL(st_table), FALSE, verbosity);
+  }
+
+  if (lsLength(vertexPtr->parent) > 1) {
+    /* Restore the old temporary careset */
+    mdd_free(AbsVerificationInfoReadTmpCareSet(absInfo));
+    AbsVerificationInfoSetTmpCareSet(absInfo, oldTmpCareSet);
+  }
+
+} /* End of AbsSubFormulaVerify */
+
+/**Function********************************************************************
+
+  Synopsis [Traverse the operational graph and mark formulas for evaluation]
+
+  Description [This procedure receives two pointers and marks every formula in
+  between for later evaluation. The marking process is simply setting the field
+  served to 0]
+
+  SideEffects        []
+
+  SeeAlso            [AbsFixedPointIterate]
+
+******************************************************************************/
+void
+AbsFormulaScheduleEvaluation(
+  AbsVertexInfo_t *current,
+  AbsVertexInfo_t *limit)
+{
+  /* We reached the final case */
+  if (current == limit) {
+    return;
+  }
+  else {
+    AbsVertexInfo_t *parentPtr;
+    lsList          parentList;
+    lsGen           gen;
+
+    /* Set the re-evaluation flag for the current vertex */
+    AbsVertexSetServed(current, 0);
+
+    /* Recur over the parents */
+    parentList = AbsVertexReadParent(current);
+    lsForEachItem(parentList, gen, parentPtr) {
+      if (parentPtr != NIL(AbsVertexInfo_t)) {
+	AbsFormulaScheduleEvaluation(parentPtr, limit);
+      }
+    }
+  }
+
+  return;
+} /* End of AbsFormulaScheduleEvaluation */
+
+/**Function********************************************************************
+
+  Synopsis [Function to minimize the size of the BDD representing one iteration
+  of the fix-point]
+
+  Description [This function is simply to encapsulate the call to the minimize
+  procedure and have a simple place where to explore the different choices when
+  it comes to select upper and lower bounds for a function. In the case of
+  fix-point evaluation, there are several bounds that can be used to look for a
+  compact representation, this is the function in which that experimenting
+  should be included]
+
+  SideEffects        []
+
+  SeeAlso            [AbsFixedPointIterate]
+
+******************************************************************************/
+mdd_t *
+AbsComputeOptimalIterate(
+  Abs_VerificationInfo_t *absInfo,
+  AbsVertexInfo_t *vertexPtr,
+  mdd_t *lowerIterate,
+  mdd_t *upperIterate)
+{
+  mdd_t *tmp;
+  mdd_t *result;
+
+  if (AbsOptionsReadMinimizeIterate(AbsVerificationInfoReadOptions(absInfo))
+      && AbsVertexReadUseExtraCareSet(vertexPtr)) {
+
+    /* 
+     * For this computation we have three ingredients and a handfull of
+     * choices. The ingredients are the sets newIterate, iterate and
+     * careSet. The goal is to compute an interval delimited by two boolean
+     * functions and then call the function bdd_between to try to obtain
+     * the best bdd in size inside that interval. To compute the extremes
+     * of the interval there are several choices. For example, the care set
+     * can be used in the lower bound of the interval or in both
+     * bounds. The bigger the interval the more choice the function
+     * bdd_between has to minimize, however, this does not turn into a
+     * better result. 
+     *
+     * Current Choice: [newIterate * iterate', newIterate]
+     */
+    tmp = mdd_and(lowerIterate, upperIterate, 0, 1);
+    result = bdd_between(tmp, upperIterate);
+    
+    /* This line for debugging purposes, should be removed 
+    (void) fprintf(vis_stdout, 
+		   "newIterate : %d, Diff : %d, result %d\n",
+		   mdd_size(upperIterate), mdd_size(tmp),
+		   mdd_size(result)); */
+    
+    mdd_free(tmp);
+  }
+  else {
+    result = mdd_dup(upperIterate);
+  }
+
+  return result;
+} /* End of AbsComputeOptimalIterate */
+
+/**Function********************************************************************
+
+  Synopsis [Function to compute the iteration in a fix-point computation]
+
+  SideEffects        []
+
+  SeeAlso            [AbsSubFormulaVerify]
+
+******************************************************************************/
+boolean
+AbsFixedPointIterate(
+  Abs_VerificationInfo_t *absInfo,
+  AbsVertexInfo_t *vertexPtr,
+  int iterateIndex)
+{
+  AbsVertexInfo_t *subFormula;
+  boolean         keepIterating;
+  boolean         globalApprox;
+  int             stepCount;
+  long            verbosity;
+  mdd_t           *iterate;
+  mdd_t           *newIterate;
+  mdd_t           *careSet;
+    
+  /* Do not allow to iterate from the middle of a fixed point computation */
+  assert(iterateIndex == array_n(AbsVertexReadRings(vertexPtr)) - 1);
+
+  careSet = AbsVerificationInfoReadCareSet(absInfo);
+
+  /* Check if the set of iterates has already converged */
+  if (array_n(AbsVertexReadRings(vertexPtr)) > 1) {
+    mdd_t *ring1 = AbsVertexFetchRing(vertexPtr, iterateIndex);
+    mdd_t *ring2 = AbsVertexFetchRing(vertexPtr, iterateIndex - 1);
+    if (AbsMddLEqualModCareSet(ring1, ring2, careSet)) {
+      return FALSE;
+    }
+    iterate = AbsVertexFetchRing(vertexPtr, iterateIndex - 1);
+  }
+  else {
+    iterate = AbsVertexFetchRing(vertexPtr, iterateIndex);
+  }
+  newIterate = AbsVertexFetchRing(vertexPtr, iterateIndex);
+
+  /* Variable initialization */
+  keepIterating = TRUE;
+  stepCount = iterateIndex;
+  verbosity = AbsOptionsReadVerbosity(AbsVerificationInfoReadOptions(absInfo));
+  subFormula = AbsVertexReadLeftKid(vertexPtr);
+  globalApprox = AbsVertexFetchSubApprox(vertexPtr, iterateIndex);
+  
+  /* Main loop for the fixed point computation */
+  while (keepIterating) {
+    mdd_t *best;
+    
+    /* 
+     * Given newIterate, iterate and CareSet, if the use of extra care set is
+     * enabled, choose the best candidate as the value of the iterate. 
+     */
+    best = AbsComputeOptimalIterate(absInfo, vertexPtr, iterate, newIterate);
+
+    /* Print the iterates */
+    if ((verbosity & ABS_VB_PITER) || (verbosity & ABS_VB_ITSIZ)) {
+      (void) fprintf(vis_stdout, "ABS: New Iterate: ");
+      if (verbosity & ABS_VB_ITSIZ) {
+	(void) fprintf(vis_stdout, "%d -> %d\n", mdd_size(newIterate),
+		       mdd_size(best));
+      }
+      else {
+	(void) fprintf(vis_stdout, "\n");
+      }
+      if (verbosity & ABS_VB_PITER) {
+	AbsBddPrintMinterms(newIterate);
+      }
+    }
+    
+    /* Store the value of the variable */
+    AbsVertexSetSat(AbsVertexReadFpVar(vertexPtr), best);
+    
+    /* Mark the proper sub-formulas for re-evaluation */
+    AbsFormulaScheduleEvaluation(AbsVertexReadFpVar(vertexPtr), vertexPtr);
+    
+    /* Evaluate the sub-formula */
+    AbsSubFormulaVerify(absInfo, subFormula);
+    mdd_free(best);
+    iterate = newIterate;
+    
+    /* 
+     * Compute the new iterate. Due to the fact that don't cares are being
+     * used, it might be possible that the new iterate does not contain the
+     * previous one, in that case the or is taken 
+     */
+    newIterate = mdd_or(iterate, AbsVertexReadSat(subFormula), 1, 1);
+    
+    assert(AbsMddLEqualModCareSet(iterate, newIterate, careSet));
+
+    /* Set the rings and the approximation flags */
+    AbsVertexInsertRing(vertexPtr, newIterate);
+    AbsVertexInsertRingApprox(vertexPtr, FALSE);
+    globalApprox = globalApprox || AbsVertexReadGlobalApprox(subFormula);
+    AbsVertexInsertSubApprox(vertexPtr, globalApprox);
+
+    keepIterating = !AbsMddEqualModCareSet(newIterate, iterate, careSet);
+    
+    stepCount++;
+  } /* End of main while loop */
+
+  return TRUE;
+} /* End of AbsFixedPointIterate */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Function to evaluate a sub-formula representing the variable of a
+  fix-point computation]
+
+  SideEffects        []
+
+  SeeAlso            [AbsSubFormulaVerify]
+
+******************************************************************************/
+static void
+EvaluateVariable(
+  Abs_VerificationInfo_t *absInfo,
+  AbsVertexInfo_t *vertexPtr)
+{
+  /* Increase the number of times the result has been used */
+  AbsVertexReadServed(vertexPtr)++;
+
+  return;
+} /* End of EvaluateVariable */
+
+/**Function********************************************************************
+
+  Synopsis           [Evaluate a vertex storing an Id]
+
+  Description [This vertex represents a subformula with an atomic
+  proposition. No approximation is done on its evaluation. The assumption is
+  that this operation does not cause blow up in the memory requirements. This
+  situation might change though]
+
+  SideEffects        []
+
+  SeeAlso            [AbsSubFormulaVerify]
+
+******************************************************************************/
+static void
+EvaluateIdentifier(
+  Abs_VerificationInfo_t *absInfo,
+  AbsVertexInfo_t *vertexPtr)
+{
+  if (AbsVertexReadServed(vertexPtr) == 0) {
+    Ntk_Node_t     *node;
+    Var_Variable_t *nodeVar;
+    graph_t        *partition;
+    vertex_t       *partitionVertex;
+    Mvf_Function_t *nodeFunction;
+    mdd_t          *result;
+    char           *nodeNameString;
+    char           *nodeValueString;
+    int            nodeValue;
+
+    /* Clean up of previous result */
+    if (AbsVertexReadSat(vertexPtr) != NIL(mdd_t)) {
+      mdd_free(AbsVertexReadSat(vertexPtr));
+      AbsVertexSetSat(vertexPtr, NIL(mdd_t));
+    }
+
+    /* Read the partition */
+    partition = AbsVerificationInfoReadPartition(absInfo);
+    
+    assert(partition != NIL(graph_t));
+    
+    /* Obtain the name and the value being used */
+    nodeNameString = AbsVertexReadName(vertexPtr);
+    nodeValueString = AbsVertexReadValue(vertexPtr);
+    
+    /* Obtain the the node in the network and the variable attached to it */
+    node = Ntk_NetworkFindNodeByName(AbsVerificationInfoReadNetwork(absInfo),
+				     nodeNameString);
+    nodeVar = Ntk_NodeReadVariable(node);
+    
+    /* Obtain the real value of the multi-valued vairable */
+    if (Var_VariableTestIsSymbolic(nodeVar)) {
+      nodeValue = Var_VariableReadIndexFromSymbolicValue(nodeVar,
+							 nodeValueString);
+    }
+    else {
+      nodeValue = atoi(nodeValueString);
+    }
+    
+    /* Read the partition, find the vertex in the partition and its function */
+    partitionVertex = Part_PartitionFindVertexByName(partition, 
+						     nodeNameString);
+    
+    /* If the vertex is not represented in the partition must be built */
+    if (partitionVertex == NIL(vertex_t)) { 
+      Ntk_Node_t *tmpNode;
+      lsGen      tmpGen;
+      array_t    *mvfArray;
+      array_t    *tmpRoots;
+      st_table   *tmpLeaves;
+      
+      /* Initialize the variables */
+      tmpRoots = array_alloc(Ntk_Node_t *, 0);
+      tmpLeaves = st_init_table(st_ptrcmp, st_ptrhash);
+      
+      /* Insert the parameters in the array and table */
+      array_insert_last(Ntk_Node_t *, tmpRoots, node);
+      Ntk_NetworkForEachCombInput(AbsVerificationInfoReadNetwork(absInfo),
+         			  tmpGen, tmpNode) {
+	st_insert(tmpLeaves, (char *) tmpNode, (char *) NTM_UNUSED);
+      }
+      
+      /* Effectively build the mdd for the given vertex */
+      mvfArray =  Ntm_NetworkBuildMvfs(AbsVerificationInfoReadNetwork(absInfo),
+				       tmpRoots, tmpLeaves, NIL(mdd_t));
+      nodeFunction = array_fetch(Mvf_Function_t *, mvfArray, 0);
+      array_free(tmpRoots);
+      st_free_table(tmpLeaves);
+      array_free(mvfArray);
+      
+      /* Store the result in the vertex */
+      result = Mvf_FunctionReadComponent(nodeFunction, nodeValue);
+      AbsVertexSetSat(vertexPtr, mdd_dup(result));
+      Mvf_FunctionFree(nodeFunction);
+    }
+    else {
+      /* Store the result in the vertex */
+      nodeFunction = Part_VertexReadFunction(partitionVertex);
+      result = Mvf_FunctionReadComponent(nodeFunction, nodeValue);
+      AbsVertexSetSat(vertexPtr, mdd_dup(result));
+    }
+    
+    /* Set the approximation flags */
+    AbsVertexSetLocalApprox(vertexPtr, FALSE);
+    AbsVertexSetGlobalApprox(vertexPtr, FALSE);
+  }
+
+  /* Increase the number of times the result has been used */
+  AbsVertexReadServed(vertexPtr)++;
+  
+  return;
+} /* End of EvaluateIdentifier */
+
+/**Function********************************************************************
+
+  Synopsis           [Evaluate a negation vertex]
+
+  SideEffects        []
+
+  SeeAlso            [AbsSubFormulaVerify]
+
+******************************************************************************/
+static void
+EvaluateNot(
+  Abs_VerificationInfo_t *absInfo,
+  AbsVertexInfo_t *vertexPtr)
+{
+  if (AbsVertexReadServed(vertexPtr) == 0) {
+    AbsVertexInfo_t *subFormula;
+    
+    /* Clean up of previous result */
+    if (AbsVertexReadSat(vertexPtr) != NIL(mdd_t)) {
+      mdd_free(AbsVertexReadSat(vertexPtr));
+      AbsVertexSetSat(vertexPtr, NIL(mdd_t));
+    }
+
+    /* Recursively evaluate the sub-formula */
+    subFormula = AbsVertexReadLeftKid(vertexPtr);
+    AbsSubFormulaVerify(absInfo, subFormula);
+
+    /* Negate the result of the sub-formula */
+    AbsVertexSetSat(vertexPtr, mdd_not(AbsVertexReadSat(subFormula)));
+
+    /* Set the approximation flags */
+    AbsVertexSetLocalApprox(vertexPtr, FALSE);
+    AbsVertexSetGlobalApprox(vertexPtr, AbsVertexReadGlobalApprox(subFormula));
+  }
+
+  /* Increase the number of times the result has been used */
+  AbsVertexReadServed(vertexPtr)++;
+
+  return;
+} /* End of EvaluateNot */
+
+/**Function********************************************************************
+
+  Synopsis           [Evaluate a conjunction vertex]
+
+  SideEffects        []
+
+  SeeAlso            [AbsSubFormulaVerify]
+
+******************************************************************************/
+static void
+EvaluateAnd(
+  Abs_VerificationInfo_t *absInfo,
+  AbsVertexInfo_t *vertexPtr)
+{
+  if (AbsVertexReadServed(vertexPtr) == 0) {
+    AbsVertexInfo_t *firstFormula;
+    AbsVertexInfo_t *secondFormula;
+    mdd_t *oldTmpCareSet;
+
+    /* Clean up of previous result */
+    if (AbsVertexReadSat(vertexPtr) != NIL(mdd_t)) {
+      mdd_free(AbsVertexReadSat(vertexPtr));
+      AbsVertexSetSat(vertexPtr, NIL(mdd_t));
+    }
+
+    /* Obtain the subformulas to evaluate */
+    firstFormula = AbsVertexReadLeftKid(vertexPtr);
+    secondFormula = AbsVertexReadRightKid(vertexPtr);
+  
+    /* Recursively evaluate the first sub-formula */
+    AbsSubFormulaVerify(absInfo, firstFormula);
+
+    /* Store the temporary careset and set the new one */
+    oldTmpCareSet = AbsVerificationInfoReadTmpCareSet(absInfo);
+    AbsVerificationInfoSetTmpCareSet(absInfo, 
+				     mdd_and(oldTmpCareSet, 
+					     AbsVertexReadSat(firstFormula), 
+					     1,1));
+
+    /* Recursively evaluate the second sub-formula */
+    AbsSubFormulaVerify(absInfo, secondFormula);
+
+    /* Restore the temporary careset */
+    mdd_free(AbsVerificationInfoReadTmpCareSet(absInfo));
+    AbsVerificationInfoSetTmpCareSet(absInfo, oldTmpCareSet);
+    
+    /* Compute result, so far no approximation is required */
+    AbsVertexSetSat(vertexPtr, mdd_and(AbsVertexReadSat(firstFormula),
+				       AbsVertexReadSat(secondFormula), 
+				       1, 1));
+
+    /* Set the approximation flags */
+    AbsVertexSetLocalApprox(vertexPtr, FALSE);
+    AbsVertexSetGlobalApprox(vertexPtr, 
+			     AbsVertexReadGlobalApprox(firstFormula) || 
+			     AbsVertexReadGlobalApprox(secondFormula));
+  }
+
+  /* Increase the number of times the result has been used */
+  AbsVertexReadServed(vertexPtr)++;
+
+  return;
+} /* End of EvaluateAnd */
+
+/**Function********************************************************************
+
+  Synopsis           [Evaluate a fix-point vertex]
+
+  SideEffects        []
+
+  SeeAlso            [AbsSubFormulaVerify]
+
+******************************************************************************/
+static void
+EvaluateFixedPoint(
+  Abs_VerificationInfo_t *absInfo,
+  AbsVertexInfo_t *vertexPtr)
+{
+  if (AbsVertexReadServed(vertexPtr) == 0) {
+    mdd_manager *mddManager;
+    mdd_t       *oldTmpCareSet;
+    mdd_t       *newTmpCareSet;
+
+    if (AbsVertexReadRings(vertexPtr) != NIL(array_t)) {
+      mdd_t *ringUnit;
+      int i;
+
+      arrayForEachItem(mdd_t *, AbsVertexReadRings(vertexPtr), i, ringUnit) {
+	mdd_free(ringUnit);
+      }
+      array_free(AbsVertexReadRings(vertexPtr));
+      array_free(AbsVertexReadRingApprox(vertexPtr));
+      array_free(AbsVertexReadSubApprox(vertexPtr));
+      mdd_free(AbsVertexReadSat(vertexPtr));
+    }
+
+    /* Re-allocation of the temporary structures */
+    AbsVertexSetRings(vertexPtr, array_alloc(mdd_t *, 0));
+    AbsVertexSetRingApprox(vertexPtr, array_alloc(boolean, 0));
+    AbsVertexSetSubApprox(vertexPtr, array_alloc(boolean, 0));
+    
+    /* Initial values of the fixed point */
+    mddManager = AbsVerificationInfoReadMddManager(absInfo);
+    AbsVertexInsertRing(vertexPtr, mdd_zero(mddManager));
+    AbsVertexInsertRingApprox(vertexPtr, FALSE);
+    AbsVertexInsertSubApprox(vertexPtr, FALSE);
+
+    /* Reset the temporary careset to the mdd one */
+    oldTmpCareSet = AbsVerificationInfoReadTmpCareSet(absInfo);
+    newTmpCareSet = mdd_one(mddManager);
+    AbsVerificationInfoSetTmpCareSet(absInfo, newTmpCareSet);
+
+    /* Effectively iterate the body */
+    AbsFixedPointIterate(absInfo, vertexPtr, 0);
+
+    /* Restore the old temporary careset */
+    mdd_free(newTmpCareSet);
+    AbsVerificationInfoSetTmpCareSet(absInfo, oldTmpCareSet);
+    
+    /* Set the last result as the set sat*/
+    AbsVertexSetSat(vertexPtr, 
+		    mdd_dup(AbsVertexFetchRing(vertexPtr,
+					array_n(AbsVertexReadRings(vertexPtr))
+					       - 1)));
+
+    /* Set the approximation flags */
+    AbsVertexSetLocalApprox(vertexPtr, FALSE);
+    AbsVertexSetGlobalApprox(vertexPtr, 
+			     AbsVertexFetchSubApprox(vertexPtr,
+			       array_n(AbsVertexReadSubApprox(vertexPtr)) - 1));
+  }
+
+  /* Increase the number of times the result has been used */
+  AbsVertexReadServed(vertexPtr)++;
+
+  return;
+}
+
+ /* End of EvaluateFixedPoint */
+
+/**Function********************************************************************
+
+  Synopsis           [Evaluate a pre-image vertex]
+
+  SideEffects        []
+
+  SeeAlso            [AbsSubFormulaVerify]
+
+******************************************************************************/
+static void
+EvaluatePreImage(
+  Abs_VerificationInfo_t *absInfo,
+  AbsVertexInfo_t *vertexPtr)
+{
+  AbsOptions_t *options;
+  AbsStats_t   *stats;
+  long         verbosity;
+
+  /* Variable initialization */
+  options = AbsVerificationInfoReadOptions(absInfo);
+  verbosity = AbsOptionsReadVerbosity(options);
+  stats = AbsVerificationInfoReadStats(absInfo);
+
+  if (AbsVertexReadServed(vertexPtr) == 0) {
+    AbsVertexInfo_t *subFormula;
+    mdd_manager     *mddManager;
+    mdd_t           *result;
+    mdd_t           *careSet;
+    mdd_t           *oldTmpCareSet;
+    mdd_t           *minimizedSet;
+
+    /* Variable initialization */
+    mddManager = AbsVerificationInfoReadMddManager(absInfo);
+    subFormula = AbsVertexReadLeftKid(vertexPtr);
+
+    /* 
+     * Compute the care set as the conjunction of the given one and the
+     * temporary one 
+     */
+    careSet = mdd_and(AbsVerificationInfoReadCareSet(absInfo),
+		      AbsVerificationInfoReadTmpCareSet(absInfo), 1, 1);
+
+    /* Clean up */
+    if (AbsVertexReadSat(vertexPtr) != NIL(mdd_t)) {
+      mdd_free(AbsVertexReadSat(vertexPtr));
+      AbsVertexSetSat(vertexPtr, NIL(mdd_t));
+    }
+    
+    /* Reset the temporary careset to the mdd one */
+    oldTmpCareSet = AbsVerificationInfoReadTmpCareSet(absInfo);
+    AbsVerificationInfoSetTmpCareSet(absInfo, mdd_one(mddManager));
+
+    /* Evaluate the sub-formula */
+    AbsSubFormulaVerify(absInfo, subFormula);
+
+    /* Restore the old temporary careset */
+    mdd_free(AbsVerificationInfoReadTmpCareSet(absInfo));
+    AbsVerificationInfoSetTmpCareSet(absInfo, oldTmpCareSet);
+    
+    /* Check for trivial cases */
+    if (mdd_is_tautology(AbsVertexReadSat(subFormula), 0) ||
+	mdd_is_tautology(AbsVertexReadSat(subFormula), 1)) {
+      AbsVertexSetSat(vertexPtr, mdd_dup(AbsVertexReadSat(subFormula)));
+      AbsVertexSetLocalApprox(vertexPtr, FALSE);
+      AbsVertexSetGlobalApprox(vertexPtr, 
+			       AbsVertexReadGlobalApprox(subFormula));
+      mdd_free(careSet);
+      return;
+    }
+
+    /* if (AbsOptionsReadMinimizeIterate(options)){ */
+    if (FALSE){
+      minimizedSet = bdd_minimize(AbsVertexReadSat(subFormula),
+				  AbsVerificationInfoReadCareSet(absInfo));
+    }
+    else {
+      minimizedSet = mdd_dup(AbsVertexReadSat(subFormula));
+    }
+      
+    /* Look up in the cache if the result has been previously computed */
+    if (AbsVertexReadSolutions(vertexPtr) != NIL(st_table)) {
+      mdd_t   *unit;
+      boolean localFlag;
+      boolean exactness;
+      
+      exactness = AbsOptionsReadExact(options);
+      if (AbsEvalCacheLookup(AbsVertexReadSolutions(vertexPtr),
+			     minimizedSet, careSet, !exactness,
+			     &unit, &localFlag)) {
+
+	/* Set the sat */
+	AbsVertexSetSat(vertexPtr, mdd_dup(unit));
+
+	/* Set the approximation flags */
+	AbsVertexSetLocalApprox(vertexPtr, localFlag & !exactness);
+	AbsVertexSetGlobalApprox(vertexPtr, 
+				 AbsVertexReadGlobalApprox(subFormula) || 
+				 AbsVertexReadLocalApprox(vertexPtr));
+	/* Increase the number of times the result has been used */
+	AbsVertexReadServed(vertexPtr)++;
+	
+	mdd_free(careSet);
+	mdd_free(minimizedSet);
+	return;
+      }
+    }
+    else {
+      /* Initialize the cache */
+      AbsVertexSetSolutions(vertexPtr, st_init_table(st_ptrcmp, st_ptrhash));
+    }
+
+    /* Effectively compute preImage */
+    if (!AbsOptionsReadExact(options)) {
+      if (AbsVertexReadPolarity(vertexPtr)) {
+	if (AbsOptionsReadPartApprox(options)) {
+	  result = OverApproximatePreImageWithSubFSM(absInfo, minimizedSet, 
+						     minimizedSet, careSet);
+	}
+	else {
+	  result = OverApproximatePreImageWithBddSubsetting(absInfo, 
+							    minimizedSet, 
+							    minimizedSet, 
+							    careSet);
+	}
+	AbsVertexSetLocalApprox(vertexPtr, TRUE);
+      }
+      else {
+	result = UnderApproximatePreImageWithBddSubsetting(absInfo, 
+							   minimizedSet, 
+							   minimizedSet,
+							   careSet);
+	AbsVertexSetLocalApprox(vertexPtr, TRUE);
+      }
+      AbsStatsReadApproxPreImage(AbsVerificationInfoReadStats(absInfo))++;
+    }
+    else {
+      Fsm_Fsm_t       *system;
+      Img_ImageInfo_t *imageInfo;
+      long            cpuTime;
+
+      system = AbsVerificationInfoReadFsm(absInfo);
+      imageInfo = Fsm_FsmReadOrCreateImageInfo(system, 1, 0);
+      cpuTime = util_cpu_time();
+      result = Img_ImageInfoComputeBwdWithDomainVars(imageInfo, minimizedSet,
+						     minimizedSet,careSet);
+      AbsStatsReadPreImageCpuTime(stats)+= util_cpu_time() - cpuTime;
+
+      AbsStatsReadExactPreImage(stats)++;
+      AbsVertexSetLocalApprox(vertexPtr, FALSE);
+    }
+    AbsVertexSetSat(vertexPtr, result);
+
+    /* Set the value in the cache */
+    AbsEvalCacheInsert(AbsVertexReadSolutions(vertexPtr),
+		       minimizedSet, AbsVertexReadSat(vertexPtr), careSet,
+		       AbsVertexReadLocalApprox(vertexPtr), FALSE);
+    AbsStatsReadPreImageCacheEntries(stats)++;
+    mdd_free(minimizedSet);
+
+    /* Set the approximation flags */
+    AbsVertexSetGlobalApprox(vertexPtr, 
+			     AbsVertexReadGlobalApprox(subFormula) || 
+			     AbsVertexReadLocalApprox(vertexPtr));
+
+    /* Print the number of states in the on set of Sat */
+    if (verbosity & ABS_VB_TSAT) {
+      Fsm_Fsm_t *globalSystem;
+      array_t *domainVars;
+      mdd_t *intersection;
+      
+      intersection = mdd_and(AbsVertexReadSat(vertexPtr), careSet, 1, 1);
+      
+      globalSystem = AbsVerificationInfoReadFsm(absInfo);
+      domainVars = Fsm_FsmReadPresentStateVars(globalSystem);
+      (void) fprintf(vis_stdout, "ABS: %.0f States satisfy the EX formula.\n",
+		     mdd_count_onset(AbsVerificationInfoReadMddManager(absInfo),
+				     intersection, domainVars));
+      mdd_free(intersection);
+    }
+    mdd_free(careSet);
+  }
+  
+
+  /* Increase the number of times the result has been used */
+  AbsVertexReadServed(vertexPtr)++;
+
+  return;
+} /* End of EvaluatePreImage */
+
+/**Function********************************************************************
+
+  Synopsis           [Compute an over-approximation of the Preimage]
+
+  SideEffects [This overapproximation is computed by just ignoring some FSM
+  components]
+
+  SeeAlso            [AbsSubFormulaVerify]
+
+******************************************************************************/
+static mdd_t *
+OverApproximatePreImageWithSubFSM(
+  Abs_VerificationInfo_t *absInfo,
+  mdd_t *lowerBound,
+  mdd_t *upperBound,
+  mdd_t *careSet)
+{
+  Fsm_Fsm_t       *system;
+  Img_ImageInfo_t *imageInfo;
+  mdd_t           *result;
+  long            cpuTime;
+
+  /* Initialize some variables */
+  system = AbsVerificationInfoReadApproxFsm(absInfo);
+
+  if (system == NIL(Fsm_Fsm_t)) {
+    system = AbsVerificationInfoReadFsm(absInfo);
+  }
+
+  /* Obtain the image info */
+  imageInfo = Fsm_FsmReadOrCreateImageInfo(system, 1, 0);
+
+  cpuTime = util_cpu_time();
+  result = Img_ImageInfoComputeBwdWithDomainVars(imageInfo, lowerBound,
+						 upperBound, careSet);
+  AbsStatsReadAppPreCpuTime(AbsVerificationInfoReadStats(absInfo))+= 
+    util_cpu_time() - cpuTime;
+
+  return result;
+} /* End of OverApproximatePreImageWithSubFSM */
+
+
+/**Function********************************************************************
+
+  Synopsis [A second procedure to compute an over-approximation of the
+  Preimage]
+
+  SideEffects        []
+
+  SeeAlso            [AbsSubFormulaVerify]
+
+******************************************************************************/
+static mdd_t *
+OverApproximatePreImageWithBddSubsetting(
+  Abs_VerificationInfo_t *absInfo,
+  mdd_t *lowerBound,
+  mdd_t *upperBound,
+  mdd_t *careSet)
+{
+  Fsm_Fsm_t       *system;
+  Img_ImageInfo_t *imageInfo;
+  mdd_t           *superSet;
+  mdd_t           *result;
+  long            cpuTime;
+
+  /* Initialize some variables */
+  system = AbsVerificationInfoReadFsm(absInfo);
+
+  /* Compute the subset of the restriction set */
+  superSet = bdd_approx_remap_ua(lowerBound,BDD_OVER_APPROX,
+			  AbsVerificationInfoReadNumStateVars(absInfo), 
+			  0,1);
+  
+  /* Obtain the image info */
+  imageInfo = Fsm_FsmReadOrCreateImageInfo(system, 1, 0);
+
+  cpuTime = util_cpu_time();
+  result = Img_ImageInfoComputeBwdWithDomainVars(imageInfo, superSet,
+						 superSet, careSet);
+  AbsStatsReadAppPreCpuTime(AbsVerificationInfoReadStats(absInfo))+= 
+    util_cpu_time() - cpuTime;
+
+  mdd_free(superSet);
+
+  return result;
+} /* End of OverApproximatePreImageWithBddSubsetting */
+
+/**Function********************************************************************
+
+  Synopsis           [Compute an under-approximation of the preimage]
+
+  SideEffects        []
+
+  SeeAlso            [AbsSubFormulaVerify]
+
+******************************************************************************/
+static mdd_t *
+UnderApproximatePreImageWithBddSubsetting(
+  Abs_VerificationInfo_t *absInfo,
+  mdd_t *lowerBound,
+  mdd_t *upperBound,
+  mdd_t *careSet)
+{
+  Fsm_Fsm_t       *system;
+  Img_ImageInfo_t *imageInfo;
+  mdd_t           *subSet;
+  mdd_t           *result;
+  long            cpuTime;
+
+  /* Initialize some variables */
+  system = AbsVerificationInfoReadFsm(absInfo);
+
+  /* Compute the subset of the restriction set */
+  subSet = bdd_approx_remap_ua(lowerBound, BDD_UNDER_APPROX,
+		      AbsVerificationInfoReadNumStateVars(absInfo),
+		      0,1);
+
+  /* Obtain the image info */
+  imageInfo = Fsm_FsmReadOrCreateImageInfo(system, 1, 0);
+
+  cpuTime = util_cpu_time();
+  result = Img_ImageInfoComputeBwdWithDomainVars(imageInfo, subSet, subSet, 
+						 careSet);
+  AbsStatsReadAppPreCpuTime(AbsVerificationInfoReadStats(absInfo))+= 
+    util_cpu_time() - cpuTime;
+
+  mdd_free(subSet);
+
+  return result;
+} /* End of UnderApproximatePreImageWithBddSubsetting */
Index: vis_dev/vis-2.3/src/abs/absInt.h
===================================================================
--- vis_dev/vis-2.3/src/abs/absInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/abs/absInt.h	(revision 14)
@@ -0,0 +1,2722 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [absInt.h]
+
+  PackageName [abs]
+
+  Synopsis [Internal declarations required for the incremental CTL model
+  checker.]
+
+  Description [The definitions in this file can be divided in three categories:
+  The verbosity constants, the structure definitions and the macros to access
+  to all the fields in the structures.]
+  
+  Author      [Abelardo Pardo <abel@vlsi.colorado.edu>]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+  Revision    [$Id: absInt.h,v 1.16 2002/09/08 22:18:10 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _ABSINT
+#define _ABSINT
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include <unistd.h>
+#include "ntm.h"
+#include "abs.h"
+#include <string.h>
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/* The verbosity system used throughout the entire code is based on a
+   mask. This mask is assumed to have 32 bits, every bit turns on and off the
+   printout of certain info related to the algorithm. The way to use this mask
+   is to go bit by bit and write a 0 to turn off the printing or a 1 to turn it
+   on. Be careful with printing information that is too verbose, such as the
+   cubes for sat or goalSet, or the minterms of a result. The program does not
+   have any mechanism to detect this situation, and if the output is redirected
+   to a file, for a complex example, the size of that file might potentially
+   overflow the biggest of the filesystems. Please refer to the man page of the
+   incremental_ctl_verification command on how to specify the mask. */
+
+#define ABS_VB_PIFF        (1<<0)  /* system's primary inputs and flip-flops */
+#define ABS_VB_GRAPH       (1<<1)  /* labeled operational graph */
+#define ABS_VB_PTIME       (1<<2)  /* cpu-time for each vertex */
+#define ABS_VB_SCUBE       (1<<3)  /* cubes of sat */
+#define ABS_VB_GCUBE       (1<<4)  /* cubes of goalSet */
+#define ABS_VB_VTXCNT      (1<<5)  /* vertex's contents after evaluation */
+#define ABS_VB_CARE        (1<<6)  /* care set for every evaluation */
+#define ABS_VB_CARESZ      (1<<7)  /* care set size for every evaluation */
+#define ABS_VB_TSAT        (1<<8)  /* number of states that satisfy formula */
+#define ABS_VB_PRCH        (1<<9)  /* number of reachable states */
+#define ABS_VB_PITER       (1<<10) /* iterate minterms of a fixed point */
+#define ABS_VB_ITSIZ       (1<<11) /* iterate's size in a fixed point */
+#define ABS_VB_PRDOT       (1<<12) /* formulas in dot format */
+#define ABS_VB_PENV        (1<<13) /* number of envelope states */
+#define ABS_VB_PRINIT      (1<<14) /* number of states to be refined */
+#define ABS_VB_PREFSZ      (1<<15) /* size of the refinement operands */
+#define ABS_VB_PREFCB      (1<<16) /* cubes of the refinement operands */
+#define ABS_VB_SIMPLE      (1<<17) /* how the system has been simplified */
+#define ABS_VB_PPROGR      (1<<18) /* partial progress: reach, EG(true, etc) */
+#define ABS_VB_REFINE      (1<<19) /* Begin/End refinement process */
+#define ABS_VB_GOALSZ      (1<<20) /* Size of goal set */
+#define ABS_VB_GLCUBE      (1<<21) /* cubes of the goal set */
+#define ABS_VB_REFVTX      (1<<22) /* Contents of vertex after refinement */
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef struct AbsVertexInfo AbsVertexInfo_t;
+typedef struct AbsOptions AbsOptions_t;
+typedef struct AbsVertexCatalog AbsVertexCatalog_t;
+typedef struct AbsParseInfo AbsParseInfo_t;
+typedef struct AbsStats AbsStats_t;
+typedef struct AbsEvalCacheEntry AbsEvalCacheEntry_t;
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Enum************************************************************************
+
+  Synopsis    [Type of result obtained from the verification algorithm.]
+
+  Description [The algorithm may provide a conclusive or inconclusive
+  result. The conclusive result itself can be that the formula is TRUE or
+  FALSE.]
+
+  SeeAlso     [AbsFormulaArrayVerify]
+
+******************************************************************************/
+typedef enum {
+  trueVerification_c,
+  falseVerification_c,
+  inconclusiveVerification_c
+} AbsVerificationResult_t;
+
+/**Enum************************************************************************
+
+  Synopsis    [Type of vertices representing a formula]
+
+  Description [A formula is represented by a data structure referred to as the
+  "labeled operational graph". This graph has a structure structure close to
+  the parse tree of the formula. This enumerated type contains the different
+  types of vertices that can be found in that graph.]
+
+  SeeAlso     [AbsCtlFormulaArrayTranslate]
+
+******************************************************************************/
+typedef enum {
+  fixedPoint_c,
+  and_c, 
+  xor_c,
+  xnor_c,
+  not_c,
+  preImage_c,
+  identifier_c,
+  variable_c,
+  false_c
+} AbsVertex_t;
+
+/**Struct**********************************************************************
+
+  Synopsis [Data structure attached to every vertex of labeled operational
+  graph representing a given formula]
+
+  Description [This structure holds all the per vertex information that is
+  relevant to the verification procedure. The structure has a union to store
+  the information that is different depending on the type of vertex. The main
+  highlights of this data structure is that for the case of the vertex of type
+  EX, the field exData contains a table storing the previous solutions computed
+  for that vertex. This can be seen as a cache. The reason for this cache is
+  because since the algorithm works incrementally, it has to perform numerous
+  re-evaluation of formulas, and the most expensive to re-evaluate are the EX
+  vertices, so the storage of the previous results pays off.]
+
+  SeeAlso [AbsCtlFormulaArrayTranslate AbsSubFormulaRefine AbsSubFormulaVerify]
+
+******************************************************************************/
+struct AbsVertexInfo {
+  AbsVertex_t vertexType;     /* Type of vertex */
+  mdd_t *sat;                 /* Set of states that satisfy the sub-formula */  
+  int vertexId;               /* Integer identifying a vertex */
+  int refs;                   /* Number of vertices pointing to this one */
+  int served;                 /* Times the vertex's results have been read */ 
+  int depth;                  /* Depth of the formula it represents */
+  boolean  polarity;          /* Boolean saying the node's polarity */
+  boolean localApprox;        /* Local approximation has been computed */
+  boolean globalApprox;       /* Approximated in a sub-formula */
+  boolean constant;           /* The sub-formula does not have variables */
+  boolean trueRefine;         /* The refinement process is conclusive */
+  AbsVertexInfo_t *leftKid;   /* Left sub-formula */
+  AbsVertexInfo_t *rightKid;  /* Right sub-formula */
+  lsList parent;              /* Pointers to the parent formulas */
+  union {
+    struct {
+      st_table *solutions;    /* Already computed results */
+    } exData;
+    struct {
+      int varId;              /* Variable id */
+      mdd_t *goalSet;         /* States that need to be include/excluded */
+    } varData;
+    struct {
+      AbsVertexInfo_t *fpVar; /* Right sub-formula */
+      array_t *rings;         /* mdd_ts computed in the fixed point */
+      array_t *ringApprox;    /* Approximations made in the rings */
+      array_t *subApprox;     /* Approximation made from the previous 
+				 iteration */
+      boolean useExtraCareSet;/* Use care set ala reachability */
+    } fpData;
+    struct {
+      char *name;             /* name of the id */
+      char *value;            /* value of the id */
+    } idData;
+  } vertexData;
+};
+
+/**Struct**********************************************************************
+
+  Synopsis [Structure to store the information needed in the overall
+  verification process.]
+
+  Description [Some of these fields are owned by the package, that is, they are
+  created inside the Abs code, and some others are just pointers to other data
+  structures not created in abs. The allocation and free procedures take care
+  of that by de-allocating only the structures locally created. The overall
+  algorithm also performs a series of image computations. Because of the high
+  number of re-evaluation of formulas, the overall algorithm keeps a table
+  storing the results of previous image computations. This table is global to
+  the entire algorithm, therefore, any image computation that is performed at
+  any point checks first if the result is already in the "imageCache" table.]
+
+  SeeAlso [AbsCtlFormulaArrayTranslate AbsSubFormulaRefine AbsSubFormulaVerify]
+
+******************************************************************************/
+struct AbsVerificationInfo {
+  Ntk_Network_t   *network;      /* Pointer to network. Not owned */
+  graph_t         *partition;    /* Pointer to the partition. Not owned */
+  mdd_manager     *mddManager;   /* Manager. Not Owned */
+  Fsm_Fsm_t       *fsm;          /* Fsm being considered. Not Owned */
+  int             numStateVars;  /* Number of bdd state variables */
+  Fsm_Fsm_t       *approxFsm;    /* Approximate FSM. Not Owned */
+  st_table        *stateVars;    /* Table with the state variable ids. Owned */
+  st_table        *quantifyVars; /* Variables to Quantify. Owned */
+  mdd_t           *careSet;      /* Global care set */
+  mdd_t           *tmpCareSet;   /* Temporary care set */
+  st_table        *imageCache;   /* To store the image computations */
+  AbsVertexCatalog_t *catalog;   /* Catalog to detect common sub-formulas */
+  AbsStats_t      *stats;        /* Statistics gathered during execution */
+  AbsOptions_t    *options;      /* Command line options */
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [Structure for storing the command line options.]
+
+  SeeAlso     [AbsVerificationInfo]
+
+******************************************************************************/
+struct AbsOptions {
+  long verbosity;       /* Level of verbosity throughout the verification */
+  int timeOut;          /* Time limit in the execution */
+  boolean reachability; /* Do reachability analysis prior to verification */
+  boolean envelope;     /* Compute EG(true) as the first formula */
+  char *fileName;       /* File to read the formulas from */
+  char *fairFileName;   /* File to read the fairness constraints for FCTL */
+  boolean exact;        /* Perform exact verification */
+  boolean printStats;   /* Print the stats after verification */
+  boolean minimizeIterate; /* Minimize the iterates of the fixed points */
+  boolean negateFormula; /* Verify the negation of the formula instead */
+  boolean partApprox;   /* Use partition transition relation approximation */
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [Structure to store statistics about the algorithm.]
+
+  Description [The statistics collected through execution will be stored in
+  this structure which itself is stored inside the AbsVerificationInfo_t
+  structure.]
+
+  SeeAlso     [AbsVerificationInfo_t]
+
+******************************************************************************/
+struct AbsStats {
+  int numReorderings;   /* Number of BDD variable re-orderings performed */
+  int evalFixedPoint;   /* Number of FixedPoint vertex evaluations */
+  int evalAnd;          /* Number of And vertex evaluations*/
+  int evalNot;          /* Number of Not vertex evaluations*/
+  int evalPreImage;     /* Number of PreImage vertex evaluations*/
+  int evalIdentifier;   /* Number of Identifier vertex evaluations*/
+  int evalVariable;     /* Number of Variable vertex evaluations*/
+  int refineFixedPoint; /* Number of FixedPoint vertex refinements */
+  int refineAnd;        /* Number of And vertex refinements */
+  int refineNot;        /* Number of Not vertex refinements */
+  int refinePreImage;   /* Number of PreImage vertex refinements */
+  int refineIdentifier; /* Number of Identifier vertex refinements */
+  int refineVariable;   /* Number of Variable vertex refinements */
+  int exactPreImage;    /* Number of exact pre-image computations */
+  int approxPreImage;   /* Number of approximate pre-image computations */
+  int exactImage;       /* Number of exact image computations */
+  int preImageCacheEntries; /* Size of the pre-image cache */
+  int imageCacheEntries;    /* Size of the image cache */
+  long imageCpuTime;        /* CPU time spent in exact image computation */
+  long preImageCpuTime;     /* CPU time spent in exact pre-image computation */
+  long appPreCpuTime;       /* CPU time spent in approximate pre-image comp. */
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [Cache entry for image and pre-image cache]
+
+  SeeAlso     [AbsSubFormulaRefine]
+
+******************************************************************************/
+struct AbsEvalCacheEntry {
+  mdd_t *key;      /* BDD operand */
+  boolean approx;  /* Is it an approximation? */
+  int complement;  /* Is it complemented? */
+  mdd_t *result;   /* Result BDD */
+  mdd_t *careSet;  /* Care set used for the computation */
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the vertexType field from a AbsVertexInfo_t 
+  structure.]
+
+  SideEffects  []
+
+******************************************************************************/
+#define AbsVertexReadType(      \
+  /* AbsVertexInfo_t * */ sfPtr \
+)                               \
+    ((sfPtr)->vertexType)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the vertexId field from a AbsVertexInfo_t 
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      []
+
+******************************************************************************/
+#define AbsVertexReadId(        \
+  /* AbsVertexInfo_t * */ sfPtr \
+)                               \
+    ((sfPtr)->vertexId)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the sat field from a AbsVertexInfo_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexReadSat(       \
+  /* AbsVertexInfo_t * */ sfPtr \
+)                               \
+    ((sfPtr)->sat)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the references field from a AbsVertexInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexReadRefs(      \
+  /* AbsVertexInfo_t * */ sfPtr \
+)                               \
+    ((sfPtr)->refs)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the served field from a AbsVertexInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexReadServed(    \
+  /* AbsVertexInfo_t * */ sfPtr \
+)                               \
+    ((sfPtr)->served)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the polarity field from a AbsVertexInfo_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexReadPolarity(  \
+  /* AbsVertexInfo_t * */ sfPtr \
+)                               \
+    ((sfPtr)->polarity)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the depth field from a AbsVertexInfo_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexReadDepth(     \
+  /* AbsVertexInfo_t * */ sfPtr \
+)                               \
+    ((sfPtr)->depth)
+
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the localApprox field from a AbsVertexInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexReadLocalApprox( \
+  /* AbsVertexInfo_t * */ sfPtr   \
+)                                 \
+    ((sfPtr)->localApprox)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the globalApprox field from a AbsVertexInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexReadGlobalApprox( \
+  /* AbsVertexInfo_t * */ sfPtr    \
+)                                  \
+    ((sfPtr)->globalApprox)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the constant field from a AbsVertexInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexReadConstant(  \
+  /* AbsVertexInfo_t * */ sfPtr \
+)                               \
+    ((sfPtr)->constant)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the trueRefine field from a AbsVertexInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexReadTrueRefine( \
+  /* AbsVertexInfo_t * */ sfPtr  \
+)                                \
+    ((sfPtr)->trueRefine)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the leftKid field from a AbsVertexInfo_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexReadLeftKid(   \
+  /* AbsVertexInfo_t * */ sfPtr \
+)                               \
+    ((sfPtr)->leftKid)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the rightKid field from a AbsVertexInfo_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexReadRightKid(  \
+  /* AbsVertexInfo_t * */ sfPtr \
+)                               \
+    ((sfPtr)->rightKid)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the parent field from a AbsVertexInfo_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexReadParent(    \
+  /* AbsVertexInfo_t * */ sfPtr \
+)                               \
+    ((sfPtr)->parent)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the solutions field from a AbsVertexInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexReadSolutions( \
+  /* AbsVertexInfo_t * */ sfPtr \
+)                               \
+    ((sfPtr)->vertexData.exData.solutions)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the varId field from a AbsVertexInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexReadVarId(     \
+  /* AbsVertexInfo_t * */ sfPtr \
+)                               \
+    ((sfPtr)->vertexData.varData.varId)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the goalSet field from a AbsVertexInfo_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexReadGoalSet(   \
+  /* AbsVertexInfo_t * */ sfPtr \
+)                               \
+    ((sfPtr)->vertexData.varData.goalSet)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the fpVar field from a AbsVertexInfo_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexReadFpVar(     \
+  /* AbsVertexInfo_t * */ sfPtr \
+)                               \
+    ((sfPtr)->vertexData.fpData.fpVar)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the rings field from a AbsVertexInfo_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexReadRings(     \
+  /* AbsVertexInfo_t * */ sfPtr \
+)                               \
+    ((sfPtr)->vertexData.fpData.rings)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to fetch an element from the rings field from a
+  AbsVertexInfo_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexFetchRing(      \
+  /* AbsVertexInfo_t * */ sfPtr, \
+  /* int */ index                \
+)                                \
+    (array_fetch(mdd_t *, ((sfPtr)->vertexData.fpData.rings), (index)))
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the ringApprox field from a AbsVertexInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexReadRingApprox( \
+  /* AbsVertexInfo_t * */ sfPtr  \
+)                                \
+    ((sfPtr)->vertexData.fpData.ringApprox)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to fetch an element from the ringApprox field from a
+  AbsVertexInfo_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexFetchRingApprox( \
+  /* AbsVertexInfo_t * */ sfPtr,  \
+  /* int */ index                 \
+)                                 \
+    (array_fetch(boolean, ((sfPtr)->vertexData.fpData.ringApprox), (index)))
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the subApprox field from a AbsVertexInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexReadSubApprox( \
+  /* AbsVertexInfo_t * */ sfPtr \
+)                               \
+    ((sfPtr)->vertexData.fpData.subApprox)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to fetch an element from the subApprox field from a
+  AbsVertexInfo_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexFetchSubApprox( \
+  /* AbsVertexInfo_t * */ sfPtr, \
+  /* int */ index                \
+)                                \
+    (array_fetch(boolean, ((sfPtr)->vertexData.fpData.subApprox), (index)))
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the useExtraCareSet field from a AbsVertexInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexReadUseExtraCareSet( \
+  /* AbsVertexInfo_t * */ sfPtr       \
+)                                     \
+    ((sfPtr)->vertexData.fpData.useExtraCareSet)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the name field from a AbsVertexInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexReadName(      \
+  /* AbsVertexInfo_t * */ sfPtr \
+)                               \
+    ((sfPtr)->vertexData.idData.name)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the value field from a AbsVertexInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexReadValue(     \
+  /* AbsVertexInfo_t * */ sfPtr \
+)                               \
+    ((sfPtr)->vertexData.idData.value)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Macro to set the vertexType field from a AbsVertexInfo_t 
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexSetType(        \
+  /* AbsVertexInfo_t * */ sfPtr, \
+  /* AbsVertex_t */ vtype        \
+)                                \
+    ((sfPtr)->vertexType) = (vtype)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Macro to set the vertexId field from a AbsVertexInfo_t 
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexSetId(          \
+  /* AbsVertexInfo_t * */ sfPtr, \
+  /* int */ data                 \
+)                                \
+    ((sfPtr)->vertexId) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the sat field from a AbsVertexInfo_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexSetSat(         \
+  /* AbsVertexInfo_t * */ sfPtr, \
+  /* mdd_t * */ set              \
+)                                \
+    ((sfPtr)->sat) = (set)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the refs field from a AbsVertexInfo_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexSetRefs(        \
+  /* AbsVertexInfo_t * */ sfPtr, \
+  /* boolean */ data             \
+)                                \
+    ((sfPtr)->refs) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the served field from a AbsVertexInfo_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexSetServed(      \
+  /* AbsVertexInfo_t * */ sfPtr, \
+  /* boolean */ data             \
+)                                \
+    ((sfPtr)->served) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the polarity field from a AbsVertexInfo_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexSetPolarity(    \
+  /* AbsVertexInfo_t * */ sfPtr, \
+  /* boolean */ data             \
+)                                \
+    ((sfPtr)->polarity) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the depth field from a AbsVertexInfo_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexSetDepth(       \
+  /* AbsVertexInfo_t * */ sfPtr, \
+  /* int */ data                 \
+)                                \
+    ((sfPtr)->depth) = (data)
+
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the localApprox field from a AbsVertexInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexSetLocalApprox( \
+  /* AbsVertexInfo_t * */ sfPtr, \
+  /* boolean */ data             \
+)                                \
+    ((sfPtr)->localApprox) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the globalApprox field from a AbsVertexInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexSetGlobalApprox( \
+  /* AbsVertexInfo_t * */ sfPtr,  \
+  /* boolean */ data              \
+)                                 \
+    ((sfPtr)->globalApprox) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the constant field from a AbsVertexInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexSetConstant(    \
+  /* AbsVertexInfo_t * */ sfPtr, \
+  /* boolean */ data             \
+)                                \
+    ((sfPtr)->constant) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the trueRefine field from a AbsVertexInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexSetTrueRefine(  \
+  /* AbsVertexInfo_t * */ sfPtr, \
+  /* boolean */ data             \
+)                                \
+    ((sfPtr)->trueRefine) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the leftKid field from a AbsVertexInfo_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexSetLeftKid(            \
+  /* AbsVertexInfo_t * */ sfPtr,        \
+  /* AbsVertexInfo_t * */ subFormulaPtr \
+)                                       \
+    ((sfPtr)->leftKid) = (subFormulaPtr)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the rightKid field from a AbsVertexInfo_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexSetRightKid(           \
+  /* AbsVertexInfo_t * */ sfPtr,        \
+  /* AbsVertexInfo_t * */ subFormulaPtr \
+)                                       \
+    ((sfPtr)->rightKid) = (subFormulaPtr)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the parent field from a AbsVertexInfo_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexSetParent(             \
+  /* AbsVertexInfo_t * */ sfPtr,        \
+  /* AbsVertexInfo_t * */ subFormulaPtr \
+)                                       \
+    lsNewBegin(((sfPtr)->parent), (lsGeneric)subFormulaPtr, NIL(lsHandle))
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the solutions field from a AbsVertexInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexSetSolutions(   \
+  /* AbsVertexInfo_t * */ sfPtr, \
+  /* array_t * */ data           \
+)                                \
+    ((sfPtr)->vertexData.exData.solutions) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the varId field from a AbsVertexInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexSetVarId(       \
+  /* AbsVertexInfo_t * */ sfPtr, \
+  /* array_t * */ data           \
+)                                \
+    ((sfPtr)->vertexData.varData.varId) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the goalSet field from a AbsVertexInfo_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexSetGoalSet(     \
+  /* AbsVertexInfo_t * */ sfPtr, \
+  /* mdd_t * */ set              \
+)                                \
+    ((sfPtr)->vertexData.varData.goalSet) = (set)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the fpVar field from a AbsVertexInfo_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexSetFpVar(       \
+  /* AbsVertexInfo_t * */ sfPtr, \
+  /* int */ data                 \
+)                                \
+    ((sfPtr)->vertexData.fpData.fpVar) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the rings field from a AbsVertexInfo_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexSetRings(       \
+  /* AbsVertexInfo_t * */ sfPtr, \
+  /* array_t * */ data           \
+)                                \
+    ((sfPtr)->vertexData.fpData.rings) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to insert a ring in the rings field from a AbsVertexInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexInsertRing(     \
+  /* AbsVertexInfo_t * */ sfPtr, \
+  /* array_t * */ data           \
+)                                \
+    array_insert_last(mdd_t *, ((sfPtr)->vertexData.fpData.rings), (data))
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the ringApprox field from a AbsVertexInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexSetRingApprox(  \
+  /* AbsVertexInfo_t * */ sfPtr, \
+  /* array_t * */ data           \
+)                                \
+    ((sfPtr)->vertexData.fpData.ringApprox) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to insert an element in the ringApprox field from a
+  AbsVertexInfo_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexInsertRingApprox( \
+  /* AbsVertexInfo_t * */ sfPtr,   \
+  /* array_t * */ data             \
+)                                  \
+    array_insert_last(boolean, ((sfPtr)->vertexData.fpData.ringApprox), (data))
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the subApprox field from a AbsVertexInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexSetSubApprox(   \
+  /* AbsVertexInfo_t * */ sfPtr, \
+  /* array_t * */ data           \
+)                                \
+    ((sfPtr)->vertexData.fpData.subApprox) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to insert an element in the subApprox field from a
+  AbsVertexInfo_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexInsertSubApprox( \
+  /* AbsVertexInfo_t * */ sfPtr,  \
+  /* array_t * */ data            \
+)                                 \
+    array_insert_last(boolean, ((sfPtr)->vertexData.fpData.subApprox), (data))
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the useExtraCareSet field from a AbsVertexInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexSetUseExtraCareSet( \
+  /* AbsVertexInfo_t * */ sfPtr,     \
+  /* int */ data                     \
+)                                    \
+    ((sfPtr)->vertexData.fpData.useExtraCareSet) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the name field from a AbsVertexInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexSetName(        \
+  /* AbsVertexInfo_t * */ sfPtr, \
+  /* int */ data                 \
+)                                \
+    ((sfPtr)->vertexData.idData.name) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the value field from a AbsVertexInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsVertexInfo]
+
+******************************************************************************/
+#define AbsVertexSetValue(       \
+  /* AbsVertexInfo_t * */ sfPtr, \
+  /* int */ data                 \
+)                                \
+    ((sfPtr)->vertexData.idData.value) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the network field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoReadNetwork( \
+  /* Abs_VerificationInfo_t * */ vInfo  \
+)                                       \
+    ((vInfo)->network)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the partition field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoReadPartition( \
+  /* Abs_VerificationInfo_t * */ vInfo    \
+)                                         \
+    ((vInfo)->partition)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the fsm field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoReadFsm(    \
+  /* Abs_VerificationInfo_t * */ vInfo \
+)                                      \
+    ((vInfo)->fsm)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the numStateVars field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoReadNumStateVars(    \
+  /* Abs_VerificationInfo_t * */ vInfo \
+)                                      \
+    ((vInfo)->numStateVars)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the approxFsm field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoReadApproxFsm( \
+  /* Abs_VerificationInfo_t * */ vInfo    \
+)                                         \
+    ((vInfo)->approxFsm)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the stateVars field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoReadStateVars( \
+  /* Abs_VerificationInfo_t * */ vInfo    \
+)                                         \
+    ((vInfo)->stateVars)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the quantifyVars field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoReadQuantifyVars( \
+  /* Abs_VerificationInfo_t * */ vInfo       \
+)                                            \
+    ((vInfo)->quantifyVars)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the careSet field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoReadCareSet( \
+  /* Abs_VerificationInfo_t * */ vInfo  \
+)                                       \
+    ((vInfo)->careSet)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the tmpCareSet field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoReadTmpCareSet( \
+  /* Abs_VerificationInfo_t * */ vInfo     \
+)                                          \
+    ((vInfo)->tmpCareSet)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the imageCache field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoReadImageCache( \
+  /* Abs_VerificationInfo_t * */ vInfo     \
+)                                          \
+    ((vInfo)->imageCache)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the mddManager field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoReadMddManager( \
+  /* Abs_VerificationInfo_t * */ vInfo     \
+)                                          \
+    ((vInfo)->mddManager)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the catalog field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoReadCatalog( \
+  /* Abs_VerificationInfo_t * */ vInfo  \
+)                                       \
+    ((vInfo)->catalog)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the stats field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoReadStats(  \
+  /* Abs_VerificationInfo_t * */ vInfo \
+)                                      \
+    ((vInfo)->stats)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the options field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoReadOptions( \
+  /* Abs_VerificationInfo_t * */ vInfo  \
+)                                       \
+    ((vInfo)->options)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Macro to set the network field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoSetNetwork(  \
+  /* Abs_VerificationInfo_t * */ vInfo, \
+  /* Ntk_Network_t */ data              \
+)                                       \
+    ((vInfo)->network) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Macro to set the partition field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoSetPartition( \
+  /* Abs_VerificationInfo_t * */ vInfo,  \
+  /* graph_t */ data                     \
+)                                        \
+    ((vInfo)->partition) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the fsm field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoSetFsm(      \
+  /* Abs_VerificationInfo_t * */ vInfo, \
+  /* Fsm_Fsm_t */ data                  \
+)                                       \
+    ((vInfo)->fsm) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the numStateVars field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoSetNumStateVars( \
+  /* Abs_VerificationInfo_t * */ vInfo,     \
+  /* Fsm_Fsm_t */ data                      \
+)                                           \
+    ((vInfo)->numStateVars) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the approxFsm field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoSetApproxFsm( \
+  /* Abs_VerificationInfo_t * */ vInfo,  \
+  /* Fsm_Fsm_t */ data                   \
+)                                        \
+    ((vInfo)->approxFsm) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Macro to set the stateVars field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoSetStateVars( \
+  /* Abs_VerificationInfo_t * */ vInfo,  \
+  /* st_table * */ data                  \
+)                                        \
+    ((vInfo)->stateVars) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the quantifyVars field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoSetQuantifyVars( \
+  /* Abs_VerificationInfo_t * */ vInfo,     \
+  /* st_table **/ data                      \
+)                                           \
+    ((vInfo)->quantifyVars) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the careSet field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoSetCareSet( \
+  /* Abs_VerificationInfo_t * */ vInfo,\
+  /* st_table **/ data                 \
+)                                      \
+    ((vInfo)->careSet) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the tmpCareSet field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoSetTmpCareSet( \
+  /* Abs_VerificationInfo_t * */ vInfo,   \
+  /* st_table **/ data                    \
+)                                         \
+    ((vInfo)->tmpCareSet) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the imageCache field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoSetImageCache( \
+  /* Abs_VerificationInfo_t * */ vInfo,   \
+  /* st_table **/ data                    \
+)                                         \
+    ((vInfo)->imageCache) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Macro to set the mddManager field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoSetMddManager( \
+  /* Abs_VerificationInfo_t * */ vInfo,   \
+  /* mdd_manager * */ data                \
+)                                         \
+    ((vInfo)->mddManager) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Macro to set the catalog field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoSetCatalog(  \
+  /* Abs_VerificationInfo_t * */ vInfo, \
+  /* AbsVertexInfo_t * */ data          \
+)                                       \
+    ((vInfo)->catalog) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Macro to set the stats field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoSetStats(    \
+  /* Abs_VerificationInfo_t * */ vInfo, \
+  /* AbsVertexInfo_t * */ data          \
+)                                       \
+    ((vInfo)->stats) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Macro to set the options field from a Abs_VerificationInfo_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [Abs_VerificationInfo_t]
+
+******************************************************************************/
+#define AbsVerificationInfoSetOptions(  \
+  /* Abs_VerificationInfo_t * */ vInfo, \
+  /* AbsOptions_t * */ data             \
+)                                       \
+    ((vInfo)->options) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the verbosity field from a AbsOptions_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsOptions]
+
+******************************************************************************/
+#define AbsOptionsReadVerbosity( \
+  /* AbsOptions_t * */ oInfo     \
+)                                \
+    ((oInfo)->verbosity)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the timeOut field from a AbsOptions_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsOptions]
+
+******************************************************************************/
+#define AbsOptionsReadTimeOut( \
+  /* AbsOptions_t * */ oInfo   \
+)                              \
+    ((oInfo)->timeOut)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the reachability field from a AbsOptions_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsOptions]
+
+******************************************************************************/
+#define AbsOptionsReadReachability( \
+  /* AbsOptions_t * */ oInfo        \
+)                                   \
+    ((oInfo)->reachability)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the envelope field from a AbsOptions_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsOptions]
+
+******************************************************************************/
+#define AbsOptionsReadEnvelope( \
+  /* AbsOptions_t * */ oInfo    \
+)                               \
+    ((oInfo)->envelope)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the fileName field from a AbsOptions_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsOptions]
+
+******************************************************************************/
+#define AbsOptionsReadFileName( \
+  /* AbsOptions_t * */ oInfo    \
+)                               \
+    ((oInfo)->fileName)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the fairFileName field from a AbsOptions_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsOptions]
+
+******************************************************************************/
+#define AbsOptionsReadFairFileName( \
+  /* AbsOptions_t * */ oInfo        \
+)                                   \
+    ((oInfo)->fairFileName)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the exact field from a AbsOptions_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsOptions]
+
+******************************************************************************/
+#define AbsOptionsReadExact( \
+  /* AbsOptions_t * */ oInfo \
+)                            \
+    ((oInfo)->exact)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the printStats field from a AbsOptions_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsOptions]
+
+******************************************************************************/
+#define AbsOptionsReadPrintStats( \
+  /* AbsOptions_t * */ oInfo      \
+)                                 \
+    ((oInfo)->printStats)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the minimizeIterate field from a AbsOptions_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsOptions]
+
+******************************************************************************/
+#define AbsOptionsReadMinimizeIterate( \
+  /* AbsOptions_t * */ oInfo           \
+)                                      \
+    ((oInfo)->minimizeIterate)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the negateFormula field from a AbsOptions_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsOptions]
+
+******************************************************************************/
+#define AbsOptionsReadNegateFormula( \
+  /* AbsOptions_t * */ oInfo         \
+)                                    \
+    ((oInfo)->negateFormula)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the partApprox field from a AbsOptions_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsOptions]
+
+******************************************************************************/
+#define AbsOptionsReadPartApprox( \
+  /* AbsOptions_t * */ oInfo      \
+)                                 \
+    ((oInfo)->partApprox)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the verbosity field from a AbsOptions_t structure.]
+
+  SideEffects []
+
+  SeeAlso      [AbsOptions]
+
+******************************************************************************/
+#define AbsOptionsSetVerbosity( \
+  /* AbsOptions_t * */ oInfo,   \
+  /* int */ data                \
+)                               \
+    ((oInfo)->verbosity) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the timeOut field from a AbsOptions_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsOptions]
+
+******************************************************************************/
+#define AbsOptionsSetTimeOut( \
+  /* AbsOptions_t * */ oInfo, \
+  /* int */ data              \
+)                             \
+    ((oInfo)->timeOut) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the reachability field from a AbsOptions_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsOptions]
+
+******************************************************************************/
+#define AbsOptionsSetReachability( \
+  /* AbsOptions_t * */ oInfo,      \
+  /* int */ data                   \
+)                                  \
+    ((oInfo)->reachability) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the envelope field from a AbsOptions_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsOptions]
+
+******************************************************************************/
+#define AbsOptionsSetEnvelope( \
+  /* AbsOptions_t * */ oInfo,  \
+  /* int */ data               \
+)                              \
+    ((oInfo)->envelope) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the fileName field from a AbsOptions_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsOptions]
+
+******************************************************************************/
+#define AbsOptionsSetFileName( \
+  /* AbsOptions_t * */ oInfo,  \
+  /* int */ data               \
+)                              \
+    ((oInfo)->fileName) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the fairFileName field from a AbsOptions_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsOptions_t]
+
+******************************************************************************/
+#define AbsOptionsSetFairFileName( \
+  /* AbsOptions_t * */ oInfo,      \
+  /* int */ data                   \
+)                                  \
+    ((oInfo)->fairFileName) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the exact field from a AbsOptions_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsOptions_t]
+
+******************************************************************************/
+#define AbsOptionsSetExact(   \
+  /* AbsOptions_t * */ oInfo, \
+  /* int */ data              \
+)                             \
+    ((oInfo)->exact) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the printStats field from a AbsOptions_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsOptions_t]
+
+******************************************************************************/
+#define AbsOptionsSetPrintStats( \
+  /* AbsOptions_t * */ oInfo,    \
+  /* int */ data                 \
+)                                \
+    ((oInfo)->printStats) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the minimizeIterate field from a AbsOptions_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsOptions_t]
+
+******************************************************************************/
+#define AbsOptionsSetMinimizeIterate( \
+  /* AbsOptions_t * */ oInfo,         \
+  /* int */ data                      \
+)                                     \
+    ((oInfo)->minimizeIterate) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the negateFormula field from a AbsOptions_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsOptions_t]
+
+******************************************************************************/
+#define AbsOptionsSetNegateFormula( \
+  /* AbsOptions_t * */ oInfo,       \
+  /* boolean */ data                \
+)                                   \
+    ((oInfo)->negateFormula) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the partApprox field from a AbsOptions_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsOptions_t]
+
+******************************************************************************/
+#define AbsOptionsSetPartApprox( \
+  /* AbsOptions_t * */ oInfo,    \
+  /* boolean */ data             \
+)                                \
+    ((oInfo)->partApprox) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the numReorderings field from a AbsStats_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsReadNumReorderings( \
+  /* AbsStats_t * */ sInfo          \
+)                                   \
+    (sInfo)->numReorderings
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the evalFixedPoint field from a AbsStats_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsReadEvalFixedPoint( \
+  /* AbsStats_t * */ sInfo          \
+)                                   \
+    (sInfo)->evalFixedPoint
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the numReorderings field from a AbsStats_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsSetNumReorderings( \
+  /* AbsStats_t * */ sInfo,        \
+  /* int  */ data                  \
+)                                  \
+    (sInfo)->numReorderings = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the evalFixedPoint field from a AbsStats_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsSetEvalFixedPoint( \
+  /* AbsStats_t * */ sInfo,        \
+  /* int  */ data                  \
+)                                  \
+    (sInfo)->evalFixedPoint = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the evalAnd field from a AbsStats_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsReadEvalAnd( \
+  /* AbsStats_t * */ sInfo   \
+)                            \
+    (sInfo)->evalAnd
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the evalAnd field from a AbsStats_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsSetEvalAnd( \
+  /* AbsStats_t * */ sInfo, \
+  /* int  */ data           \
+)                           \
+    (sInfo)->evalAnd = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the evalNot field from a AbsStats_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsReadEvalNot( \
+  /* AbsStats_t * */ sInfo   \
+)                            \
+    (sInfo)->evalNot
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the evalNot field from a AbsStats_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsSetEvalNot( \
+  /* AbsStats_t * */ sInfo, \
+  /* int  */ data           \
+)                           \
+    (sInfo)->evalNot = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the evalPreImage field from a AbsStats_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsReadEvalPreImage( \
+  /* AbsStats_t * */ sInfo        \
+)                                 \
+    (sInfo)->evalPreImage
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the evalPreImage field from a AbsStats_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsSetEvalPreImage( \
+  /* AbsStats_t * */ sInfo,      \
+  /* int  */ data                \
+)                                \
+    (sInfo)->evalPreImage = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the evalIdentifier field from a AbsStats_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsReadEvalIdentifier( \
+  /* AbsStats_t * */ sInfo          \
+)                                   \
+    (sInfo)->evalIdentifier
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the evalIdentifier field from a AbsStats_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsSetEvalIdentifier( \
+  /* AbsStats_t * */ sInfo,        \
+  /* int  */ data                  \
+)                                  \
+    (sInfo)->evalIdentifier = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the evalVariable field from a AbsStats_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsReadEvalVariable( \
+  /* AbsStats_t * */ sInfo        \
+)                                 \
+    (sInfo)->evalVariable
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the evalVariable field from a AbsStats_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsSetEvalVariable( \
+  /* AbsStats_t * */ sInfo,      \
+  /* int  */ data                \
+)                                \
+    (sInfo)->evalVariable = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the refineFixedPoint field from a AbsStats_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsReadRefineFixedPoint( \
+  /* AbsStats_t * */ sInfo            \
+)                                     \
+    (sInfo)->refineFixedPoint
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the refineFixedPoint field from a AbsStats_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsSetRefineFixedPoint( \
+  /* AbsStats_t * */ sInfo,          \
+  /* int  */ data                    \
+)                                    \
+    (sInfo)->refineFixedPoint = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the refineAnd field from a AbsStats_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsReadRefineAnd( \
+  /* AbsStats_t * */ sInfo     \
+)                              \
+    (sInfo)->refineAnd
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the refineAnd field from a AbsStats_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsSetRefineAnd( \
+  /* AbsStats_t * */ sInfo,   \
+  /* int  */ data             \
+)                             \
+    (sInfo)->refineAnd = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the refineNot field from a AbsStats_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsReadRefineNot( \
+  /* AbsStats_t * */ sInfo     \
+)                              \
+    (sInfo)->refineNot
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the refineNot field from a AbsStats_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsSetRefineNot( \
+  /* AbsStats_t * */ sInfo,   \
+  /* int  */ data             \
+)                             \
+    (sInfo)->refineNot = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the refinePreImage field from a AbsStats_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsReadRefinePreImage( \
+  /* AbsStats_t * */ sInfo          \
+)                                   \
+    (sInfo)->refinePreImage
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the refinePreImage field from a AbsStats_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsSetRefinePreImage( \
+  /* AbsStats_t * */ sInfo,        \
+  /* int  */ data                  \
+)                                  \
+    (sInfo)->refinePreImage = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the refineIdentifier field from a AbsStats_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsReadRefineIdentifier( \
+  /* AbsStats_t * */ sInfo            \
+)                                     \
+    (sInfo)->refineIdentifier
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the refineIdentifier field from a AbsStats_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsSetRefineIdentifier( \
+  /* AbsStats_t * */ sInfo,          \
+  /* int  */ data                    \
+)                                    \
+    (sInfo)->refineIdentifier = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the refineVariable field from a AbsStats_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsReadRefineVariable( \
+  /* AbsStats_t * */ sInfo          \
+)                                   \
+    (sInfo)->refineVariable
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the refineVariable field from a AbsStats_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsSetRefineVariable( \
+  /* AbsStats_t * */ sInfo,        \
+  /* int  */ data                  \
+)                                  \
+    (sInfo)->refineVariable = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the exactPreImage field from a AbsStats_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsReadExactPreImage( \
+  /* AbsStats_t * */ sInfo         \
+)                                  \
+    (sInfo)->exactPreImage
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the exactPreImage field from a AbsStats_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsSetExactPreImage( \
+  /* AbsStats_t * */ sInfo,       \
+  /* int  */ data                 \
+)                                 \
+    (sInfo)->exactPreImage = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the approxPreImage field from a AbsStats_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsReadApproxPreImage( \
+  /* AbsStats_t * */ sInfo          \
+)                                   \
+    (sInfo)->approxPreImage
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the approxPreImage field from a AbsStats_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsSetApproxPreImage( \
+  /* AbsStats_t * */ sInfo,        \
+  /* int  */ data                  \
+)                                  \
+    (sInfo)->approxPreImage = (data)
+
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the exactImage field from a AbsStats_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsReadExactImage( \
+  /* AbsStats_t * */ sInfo      \
+)                               \
+    (sInfo)->exactImage
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the exactImage field from a AbsStats_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsSetExactImage( \
+  /* AbsStats_t * */ sInfo,    \
+  /* int  */ data              \
+)                              \
+    (sInfo)->exactImage = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the preImageCacheEntries field from a AbsStats_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsReadPreImageCacheEntries( \
+  /* AbsStats_t * */ sInfo                \
+)                                         \
+    (sInfo)->preImageCacheEntries
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the preImageCacheEntries field from a AbsStats_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsSetPreImageCacheEntries( \
+  /* AbsStats_t * */ sInfo,              \
+  /* int  */ data                        \
+)                                        \
+    (sInfo)->preImageCacheEntries = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the imageCacheEntries field from a AbsStats_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsReadImageCacheEntries( \
+  /* AbsStats_t * */ sInfo             \
+)                                      \
+    (sInfo)->imageCacheEntries
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the imageCacheEntries field from a AbsStats_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsSetImageCacheEntries( \
+  /* AbsStats_t * */ sInfo,           \
+  /* int  */ data                     \
+)                                     \
+    (sInfo)->imageCacheEntries = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the imageCpuTime field from a AbsStats_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsReadImageCpuTime( \
+  /* AbsStats_t * */ sInfo        \
+)                                 \
+    (sInfo)->imageCpuTime
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the imageCpuTime field from a AbsStats_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsSetImageCpuTime( \
+  /* AbsStats_t * */ sInfo,      \
+  /* int  */ data                \
+)                                \
+    (sInfo)->imageCpuTime = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the preImageCpuTime field from a AbsStats_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsReadPreImageCpuTime( \
+  /* AbsStats_t * */ sInfo        \
+)                                 \
+    (sInfo)->preImageCpuTime
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the preImageCpuTime field from a AbsStats_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsSetPreImageCpuTime( \
+  /* AbsStats_t * */ sInfo,      \
+  /* int  */ data                \
+)                                \
+    (sInfo)->preImageCpuTime = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the appPreCpuTime field from a AbsStats_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsReadAppPreCpuTime( \
+  /* AbsStats_t * */ sInfo        \
+)                                 \
+    (sInfo)->appPreCpuTime
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the appPreCpuTime field from a AbsStats_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsStats_t]
+
+******************************************************************************/
+#define AbsStatsSetAppPreCpuTime( \
+  /* AbsStats_t * */ sInfo,      \
+  /* int  */ data                \
+)                                \
+    (sInfo)->appPreCpuTime = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the key field of the AbsEvalCacheEntry_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsEvalCacheEntry_t]
+
+******************************************************************************/
+#define AbsEvalCacheEntryReadKey(   \
+  /* AbsEvalCacheEntry_t * */ eInfo \
+)                                   \
+    ((eInfo)->key)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the key field of the AbsEvalCacheEntry_t structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsEvalCacheEntry_t]
+
+******************************************************************************/
+#define AbsEvalCacheEntrySetKey(     \
+  /* AbsEvalCacheEntry_t * */ eInfo, \
+  /* mdd_t * */ data                 \
+)                                    \
+    ((eInfo)->key) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the approx field of the AbsEvalCacheEntry_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsEvalCacheEntry_t]
+
+******************************************************************************/
+#define AbsEvalCacheEntryReadApprox( \
+  /* AbsEvalCacheEntry_t * */ eInfo  \
+)                                    \
+    ((eInfo)->approx)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the approx field of the AbsEvalCacheEntry_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsEvalCacheEntry_t]
+
+******************************************************************************/
+#define AbsEvalCacheEntrySetApprox(  \
+  /* AbsEvalCacheEntry_t * */ eInfo, \
+  /* mdd_t * */ data                 \
+)                                    \
+    ((eInfo)->approx) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the complement field of the AbsEvalCacheEntry_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsEvalCacheEntry_t]
+
+******************************************************************************/
+#define AbsEvalCacheEntryReadComplement( \
+  /* AbsEvalCacheEntry_t * */ eInfo      \
+)                                        \
+    ((eInfo)->complement)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the complement field of the AbsEvalCacheEntry_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsEvalCacheEntry_t]
+
+******************************************************************************/
+#define AbsEvalCacheEntrySetComplement( \
+  /* AbsEvalCacheEntry_t * */ eInfo,    \
+  /* mdd_t * */ data                    \
+)                                       \
+    ((eInfo)->complement) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the result field of the AbsEvalCacheEntry_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsEvalCacheEntry_t]
+
+******************************************************************************/
+#define AbsEvalCacheEntryReadResult( \
+  /* AbsEvalCacheEntry_t * */ eInfo  \
+)                                    \
+    ((eInfo)->result)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the careSet field of the AbsEvalCacheEntry_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsEvalCacheEntry_t]
+
+******************************************************************************/
+#define AbsEvalCacheEntryReadCareSet( \
+  /* AbsEvalCacheEntry_t * */ eInfo   \
+)                                     \
+    ((eInfo)->careSet)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the result field of the AbsEvalCacheEntry_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsEvalCacheEntry_t]
+
+******************************************************************************/
+#define AbsEvalCacheEntrySetResult(  \
+  /* AbsEvalCacheEntry_t * */ eInfo, \
+  /* mdd_t * */ data                 \
+)                                    \
+    ((eInfo)->result) = (data)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the careSet field of the AbsEvalCacheEntry_t
+  structure.]
+
+  SideEffects  []
+
+  SeeAlso      [AbsEvalCacheEntry_t]
+
+******************************************************************************/
+#define AbsEvalCacheEntrySetCareSet(  \
+  /* AbsEvalCacheEntry_t * */ eInfo,  \
+  /* mdd_t * */ data                  \
+)                                     \
+    ((eInfo)->careSet) = (data)
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN AbsVertexCatalog_t * AbsVertexCatalogInitialize(void);
+EXTERN void AbsVertexCatalogFree(AbsVertexCatalog_t *c);
+EXTERN AbsVertexInfo_t * AbsVertexCatalogFindOrAdd(AbsVertexCatalog_t *catalog, AbsVertex_t type, boolean polarity, AbsVertexInfo_t *leftKid, AbsVertexInfo_t *rightKid, int localId, char *idName, char *idValue);
+EXTERN void AbsCatalogDelete(AbsVertexCatalog_t *catalog, AbsVertexInfo_t *vertex);
+EXTERN void AbsSubFormulaVerify(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr);
+EXTERN void AbsFormulaScheduleEvaluation(AbsVertexInfo_t *current, AbsVertexInfo_t *limit);
+EXTERN mdd_t * AbsComputeOptimalIterate(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr, mdd_t *lowerIterate, mdd_t *upperIterate);
+EXTERN boolean AbsFixedPointIterate(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr, int iterateIndex);
+EXTERN AbsVertexInfo_t * AbsVertexInitialize(void);
+EXTERN void AbsVertexFree(AbsVertexCatalog_t *catalog, AbsVertexInfo_t *v, AbsVertexInfo_t *fromVertex);
+EXTERN Abs_VerificationInfo_t * AbsVerificationInfoInitialize(void);
+EXTERN void AbsVerificationInfoFree(Abs_VerificationInfo_t *v);
+EXTERN AbsOptions_t * AbsOptionsInitialize(void);
+EXTERN void AbsOptionsFree(AbsOptions_t *unit);
+EXTERN AbsStats_t * AbsStatsInitialize(void);
+EXTERN void AbsStatsFree(AbsStats_t *unit);
+EXTERN AbsEvalCacheEntry_t * AbsCacheEntryInitialize(void);
+EXTERN void AbsCacheEntryFree(AbsEvalCacheEntry_t *unit);
+EXTERN void AbsEvalCacheInsert(st_table *solutions, mdd_t *key, mdd_t *result, mdd_t *careSet, boolean approx, boolean replace);
+EXTERN boolean AbsEvalCacheLookup(st_table *solutions, mdd_t *key, mdd_t *careSet, boolean approx, mdd_t **result, boolean *storedApprox);
+EXTERN void AbsVerificationFlushCache(Abs_VerificationInfo_t *absInfo);
+EXTERN void AbsVertexFlushCache(AbsVertexInfo_t *vertexPtr);
+EXTERN mdd_t * AbsImageReadOrCompute(Abs_VerificationInfo_t *absInfo, Img_ImageInfo_t *imageInfo, mdd_t *set, mdd_t *careSet);
+EXTERN array_t * AbsFormulaArrayVerify(Abs_VerificationInfo_t *absInfo, array_t *formulaArray);
+EXTERN Fsm_Fsm_t * AbsCreateReducedFsm(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr, Fsm_Fsm_t **approxFsm);
+EXTERN boolean AbsMddEqualModCareSet(mdd_t *f, mdd_t *g, mdd_t *careSet);
+EXTERN boolean AbsMddLEqualModCareSet(mdd_t *f, mdd_t *g, mdd_t *careSet);
+EXTERN AbsParseInfo_t * AbsParseInfoInitialize(void);
+EXTERN void AbsParseInfoFree(AbsParseInfo_t *data);
+EXTERN mdd_t * AbsSubFormulaRefine(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr, mdd_t *goalSet);
+EXTERN array_t * AbsCtlFormulaArrayTranslate(Abs_VerificationInfo_t *verInfo, array_t *formulaArray, array_t *fairArray);
+EXTERN void AbsVertexPrintDot(FILE *fp, array_t *vertexArray);
+EXTERN void AbsVertexPrint(AbsVertexInfo_t *vertexPtr, st_table *visitedSF, boolean recur, long verbosity);
+EXTERN void AbsBddPrintMinterms(mdd_t *function);
+EXTERN void AbsFormulaSetConstantBit(AbsVertexInfo_t *vertexPtr);
+EXTERN boolean AbsFormulaSanityCheck(AbsVertexInfo_t *vertexPtr, st_table *rootTable);
+EXTERN boolean AbsIteratesSanityCheck(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr);
+EXTERN void AbsStatsPrintReport(FILE *fp, AbsStats_t *stats);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _ABSINT */
+
Index: vis_dev/vis-2.3/src/abs/absInternal.c
===================================================================
--- vis_dev/vis-2.3/src/abs/absInternal.c	(revision 14)
+++ vis_dev/vis-2.3/src/abs/absInternal.c	(revision 14)
@@ -0,0 +1,1348 @@
+/**CFile***********************************************************************
+
+  FileName    [absInternal.c]
+
+  PackageName [abs]
+
+  Synopsis    [Miscelaneous functions to handle caches, don't care conditions, initialization and deallocation of structures, etc]
+
+  Author      [Abelardo Pardo <abel@vlsi.colorado.edu>]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "absInt.h"
+
+static char rcsid[] UNUSED = "$Id: absInternal.c,v 1.30 2005/04/16 04:22:21 fabio Exp $";
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+static int vertexCounter = 0;
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static mdd_t * ComputeEGtrue(Abs_VerificationInfo_t *absInfo, mdd_t *careStates);
+static void SelectIdentifierVertices(AbsVertexInfo_t *vertexPtr, array_t *result, st_table *visited);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Fill the fields of the data structure storing the information
+  required for the verification process]
+
+  SideEffects        []
+
+******************************************************************************/
+Abs_VerificationInfo_t *
+Abs_VerificationComputeInfo(
+  Ntk_Network_t *network)
+{
+  Abs_VerificationInfo_t *absInfo;
+  Ntk_Node_t            *nodePtr;
+  graph_t               *partition;
+  mdd_manager           *mddManager;
+  st_table              *table;
+  lsGen                 lsgen;
+
+
+  /* Create the data structure to store all the needed info */
+  absInfo = AbsVerificationInfoInitialize();
+
+  /* Fill the data structure in */
+  AbsVerificationInfoSetNetwork(absInfo, network);
+  partition = Part_NetworkReadPartition(network);
+  AbsVerificationInfoSetPartition(absInfo, partition);
+  mddManager = Part_PartitionReadMddManager(partition);
+  AbsVerificationInfoSetMddManager(absInfo, mddManager);
+  
+  /* Compute the state variable pairs */
+  table = st_init_table(st_numcmp, st_numhash);
+  Ntk_NetworkForEachLatch(network, lsgen, nodePtr) {
+    Ntk_Node_t *latchInputPtr;
+    int        mddId, mddId2;
+    
+    mddId = Ntk_NodeReadMddId(nodePtr);
+    latchInputPtr = Ntk_NodeReadShadow(nodePtr);
+    mddId2 = Ntk_NodeReadMddId(latchInputPtr);
+    st_insert(table, (char *)(long)mddId, (char *)(long)mddId2);
+  }
+  AbsVerificationInfoSetStateVars(absInfo, table);
+  
+  /* Compute the quantify variables */
+  table = st_init_table(st_numcmp, st_numhash);
+  Ntk_NetworkForEachInput(network, lsgen, nodePtr) {
+    int mddId;
+    
+    mddId = Ntk_NodeReadMddId(nodePtr);
+    st_insert(table, (char *)(long)mddId, NIL(char));
+  }
+  AbsVerificationInfoSetQuantifyVars(absInfo, table);
+  
+  /* Initalize the catalog to detect common expressions */
+  AbsVerificationInfoSetCatalog(absInfo, AbsVertexCatalogInitialize());
+  
+  return absInfo;
+} /* End of Abs_VerificationComputeInfo */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Create a new structure of type VertexInfo and initialize
+  all its fields.]
+
+  SideEffects        []
+
+  SeeAlso            [AbsVertexInfo_t]
+
+******************************************************************************/
+AbsVertexInfo_t *
+AbsVertexInitialize(void)
+{
+  AbsVertexInfo_t *result;
+
+  result = ALLOC(AbsVertexInfo_t, 1);
+
+  AbsVertexSetType(result, false_c);
+  AbsVertexSetId(result, vertexCounter++);
+  AbsVertexSetSat(result, NIL(mdd_t));
+  AbsVertexSetRefs(result, 1);
+  AbsVertexSetServed(result, 0);
+  AbsVertexSetPolarity(result, FALSE);
+  AbsVertexSetDepth(result, -1);
+  AbsVertexSetLocalApprox(result, FALSE);
+  AbsVertexSetGlobalApprox(result, FALSE);
+  AbsVertexSetConstant(result, FALSE);
+  AbsVertexSetTrueRefine(result, FALSE);
+  AbsVertexSetLeftKid(result, NIL(AbsVertexInfo_t));
+  AbsVertexSetRightKid(result, NIL(AbsVertexInfo_t));
+  result->parent = lsCreate();
+ 
+  /* Not all of these need to be initialized, but to be sure... */
+  AbsVertexSetSolutions(result, NIL(st_table));
+  AbsVertexSetVarId(result, 0);
+  AbsVertexSetFpVar(result, NIL(AbsVertexInfo_t));
+  AbsVertexSetVarId(result, 0);
+  AbsVertexSetGoalSet(result, NIL(mdd_t));
+  AbsVertexSetRings(result, NIL(array_t));
+  AbsVertexSetRingApprox(result, NIL(array_t));
+  AbsVertexSetSubApprox(result, NIL(array_t));
+  AbsVertexSetUseExtraCareSet(result, FALSE);
+  AbsVertexSetName(result, NIL(char));
+  AbsVertexSetValue(result, NIL(char));
+
+  return result;
+} /* End of AbsVertexInitialize */
+
+/**Function********************************************************************
+
+  Synopsis           [Free a structure of type AbsVertexInfo.]
+
+  Description        [optional]
+
+  SideEffects        []
+
+  SeeAlso            [AbsVertexInfo_t]
+
+******************************************************************************/
+void
+AbsVertexFree(
+  AbsVertexCatalog_t *catalog,
+  AbsVertexInfo_t *v,
+  AbsVertexInfo_t *fromVertex)
+{
+  /* Decrement the number of references */
+  AbsVertexReadRefs(v)--;
+
+  /* Remove the pointer from its parent to itself */
+  if (fromVertex != NIL(AbsVertexInfo_t)) {
+    AbsVertexInfo_t *result;
+    lsGen listGen;
+    lsHandle item, toDelete;
+    lsGeneric userData;
+
+    listGen = lsStart(AbsVertexReadParent(v));
+    toDelete = (lsHandle) 0;
+    while(toDelete == (lsHandle) 0 &&
+	  lsNext(listGen, &result, &item) == LS_OK) {
+      if (result == fromVertex) {
+	toDelete = item;
+      }
+    }
+    lsFinish(listGen);
+
+    if (toDelete != (lsHandle)0) {
+      lsRemoveItem(toDelete, &userData);
+    }
+  }
+
+  /* If it is not the last reference we are done */
+  if (AbsVertexReadRefs(v) != 0) {
+    return;
+  }
+
+  /* Vertices that need recursion over the leftKid */
+  if (AbsVertexReadType(v) == fixedPoint_c ||
+      AbsVertexReadType(v) == and_c ||
+      AbsVertexReadType(v) == xor_c ||
+      AbsVertexReadType(v) == xnor_c ||
+      AbsVertexReadType(v) == not_c ||
+      AbsVertexReadType(v) == preImage_c) {
+    AbsVertexFree(catalog, AbsVertexReadLeftKid(v), v);
+  }
+  
+  /* Vertices that need recursion over the rightKid */
+  if (AbsVertexReadType(v) == and_c ||
+      AbsVertexReadType(v) == xor_c ||
+      AbsVertexReadType(v) == xnor_c) {
+    AbsVertexFree(catalog, AbsVertexReadRightKid(v), v);
+  }
+
+  /* Remove the vertex from the catalog */
+  AbsCatalogDelete(catalog, v);
+
+  /* The variable vertex does not reference the sat set */
+  if (AbsVertexReadType(v) != variable_c && 
+      AbsVertexReadSat(v) != NIL(mdd_t)) {
+    mdd_free(AbsVertexReadSat(v));
+  }
+
+  if (AbsVertexReadType(v) == variable_c && 
+      AbsVertexReadGoalSet(v) != NIL(mdd_t)) {
+    mdd_free(AbsVertexReadGoalSet(v));
+  }
+  
+  lsDestroy(AbsVertexReadParent(v), (void (*)(lsGeneric))0);
+
+  /* Free the union fields depending on the type of vertex */
+  if (AbsVertexReadType(v) == preImage_c) {
+    if (AbsVertexReadSolutions(v) != NIL(st_table)) {
+      AbsEvalCacheEntry_t *value;
+      bdd_node            *key;
+      st_generator        *stgen;
+
+      st_foreach_item(AbsVertexReadSolutions(v), stgen, &key, &value) {
+	AbsCacheEntryFree(value);
+      }
+      st_free_table(AbsVertexReadSolutions(v));
+    }
+  }
+  else if (AbsVertexReadType(v) == fixedPoint_c) {
+    if (AbsVertexReadRings(v) != NIL(array_t)) {
+      mdd_t *unit;
+      int i;
+
+      arrayForEachItem(mdd_t *, AbsVertexReadRings(v), i, unit) {
+	mdd_free(unit);
+      }
+      array_free(AbsVertexReadRings(v));
+    }
+    if (AbsVertexReadRingApprox(v) != NIL(array_t)) {
+      array_free(AbsVertexReadRingApprox(v));
+    }
+    if (AbsVertexReadSubApprox(v) != NIL(array_t)) {
+      array_free(AbsVertexReadSubApprox(v));
+    }
+  }
+  else if (AbsVertexReadType(v) == identifier_c) {
+    FREE(AbsVertexReadName(v));
+    FREE(AbsVertexReadValue(v));
+  }
+
+  /* Deallocate the memory for the structure itself */
+  FREE(v);
+} /* End of AbsVertexFree */
+
+/**Function********************************************************************
+
+  Synopsis [Allocates the data structure to store information about
+  the general verification process.]
+
+  SideEffects        []
+
+  SeeAlso            [AbsVerificationInfo AbsVertexInfo]
+
+******************************************************************************/
+Abs_VerificationInfo_t *
+AbsVerificationInfoInitialize(void)
+{
+  Abs_VerificationInfo_t *result;
+
+  result = ALLOC(Abs_VerificationInfo_t, 1);
+
+  AbsVerificationInfoSetNetwork(result, NIL(Ntk_Network_t));
+  AbsVerificationInfoSetPartition(result, NIL(graph_t));
+  AbsVerificationInfoSetFsm(result, NIL(Fsm_Fsm_t));
+  AbsVerificationInfoSetNumStateVars(result, 0);
+  AbsVerificationInfoSetApproxFsm(result, NIL(Fsm_Fsm_t));
+  AbsVerificationInfoSetStateVars(result, NIL(st_table));
+  AbsVerificationInfoSetQuantifyVars(result, NIL(st_table));
+  AbsVerificationInfoSetCareSet(result, NIL(mdd_t));
+  AbsVerificationInfoSetTmpCareSet(result, NIL(mdd_t));
+  AbsVerificationInfoSetImageCache(result, NIL(st_table));
+  AbsVerificationInfoSetMddManager(result, NIL(mdd_manager));
+  AbsVerificationInfoSetCatalog(result, NIL(AbsVertexCatalog_t));
+  AbsVerificationInfoSetStats(result, AbsStatsInitialize());
+  AbsVerificationInfoSetOptions(result, NIL(AbsOptions_t));
+  
+  return result;
+} /* End of AbsVerificationInfoInitialize */
+
+/**Function********************************************************************
+
+  Synopsis           [Free the structure storing the verification info.]
+
+  Description [Some of the fields in this structure are owned by this
+  package and some others are simply pointers to a data structure that
+  is owned by some other package. Refer to the definition of
+  Abs_VerificationInfo_t to know which fields are onwed and which are
+  not.]
+
+  SideEffects        []
+
+  SeeAlso            [AbsVerificationInfo AbsVertexInfo]
+
+******************************************************************************/
+void
+AbsVerificationInfoFree(
+  Abs_VerificationInfo_t *v)
+{
+  if (AbsVerificationInfoReadStateVars(v) != NIL(st_table)) {
+    st_free_table(AbsVerificationInfoReadStateVars(v));
+  }
+
+  if (AbsVerificationInfoReadQuantifyVars(v) != NIL(st_table)) {
+    st_free_table(AbsVerificationInfoReadQuantifyVars(v));
+  }
+
+  if (AbsVerificationInfoReadImageCache(v) != NIL(st_table)) {
+    AbsEvalCacheEntry_t *value;
+    bdd_node            *key;
+    st_generator        *stgen;
+
+    st_foreach_item(AbsVerificationInfoReadImageCache(v), stgen,
+		    &key, &value) {
+      AbsCacheEntryFree(value);
+    }
+    st_free_table(AbsVerificationInfoReadImageCache(v));
+  }
+
+  if (AbsVerificationInfoReadCareSet(v) != NIL(mdd_t)) {
+    mdd_free(AbsVerificationInfoReadCareSet(v));
+  }
+
+  if (AbsVerificationInfoReadTmpCareSet(v) != NIL(mdd_t)) {
+    mdd_free(AbsVerificationInfoReadTmpCareSet(v));
+  }
+
+  if (AbsVerificationInfoReadCatalog(v) != NIL(AbsVertexCatalog_t)) {
+    AbsVertexCatalogFree(AbsVerificationInfoReadCatalog(v));
+  }
+
+  AbsStatsFree(AbsVerificationInfoReadStats(v));
+
+  FREE(v);
+
+  /* 
+   * The options field is not freed since it is assumed that it has been
+   * allocated outside the AbsVerificationInitialize procedure
+   */
+
+  return;
+} /* End of AbsVerificationInfoFree */
+
+/**Function********************************************************************
+
+  Synopsis [Allocate the structure to store the value of the options.]
+
+  SideEffects        []
+
+  SeeAlso            [AbsOptions]
+
+******************************************************************************/
+AbsOptions_t *
+AbsOptionsInitialize(void)
+{
+  AbsOptions_t *result;
+
+  result = ALLOC(AbsOptions_t, 1);
+
+  AbsOptionsSetVerbosity(result, 0);
+  AbsOptionsSetTimeOut(result, 0);
+  AbsOptionsSetFileName(result, NIL(char));
+  AbsOptionsSetReachability(result, FALSE);
+  AbsOptionsSetFairFileName(result, NIL(char));
+  AbsOptionsSetExact(result, FALSE);
+  AbsOptionsSetPrintStats(result, FALSE);
+  AbsOptionsSetMinimizeIterate(result, FALSE);
+  AbsOptionsSetNegateFormula(result, FALSE);
+  AbsOptionsSetPartApprox(result, FALSE);
+
+  return result;
+} /* End of AbsOptionsInitialize */
+
+/**Function********************************************************************
+
+  Synopsis [Deallocate the structure storing the value of the options.]
+
+  SideEffects        []
+
+  SeeAlso            [AbsOptions]
+
+******************************************************************************/
+void
+AbsOptionsFree(AbsOptions_t *unit)
+{
+  if (AbsOptionsReadFileName(unit) != NIL(char)) {
+    FREE(AbsOptionsReadFileName(unit));
+  }
+  
+  if (AbsOptionsReadFairFileName(unit) != NIL(char)) {
+    FREE(AbsOptionsReadFairFileName(unit));
+  }
+
+  FREE(unit);
+  
+  return;
+} /* End of AbsOptionsInitialize */
+
+
+/**Function********************************************************************
+
+  Synopsis [Allocate the data structure storing the different statistics
+  measurements collected by the algorithms]
+
+  SideEffects        []
+
+  SeeAlso            [AbsStats]
+
+******************************************************************************/
+AbsStats_t *
+AbsStatsInitialize(void)
+{
+  AbsStats_t *result;
+
+  result = ALLOC(AbsStats_t, 1);
+  
+  AbsStatsSetNumReorderings(result, 0);
+  AbsStatsSetEvalFixedPoint(result, 0);
+  AbsStatsSetEvalAnd(result, 0);
+  AbsStatsSetEvalNot(result, 0);
+  AbsStatsSetEvalPreImage(result, 0);
+  AbsStatsSetEvalIdentifier(result, 0);
+  AbsStatsSetEvalVariable(result, 0);
+  AbsStatsSetRefineFixedPoint(result, 0);
+  AbsStatsSetRefineAnd(result, 0);
+  AbsStatsSetRefineNot(result, 0);
+  AbsStatsSetRefinePreImage(result, 0);
+  AbsStatsSetRefineIdentifier(result, 0);
+  AbsStatsSetRefineVariable(result, 0);
+  AbsStatsSetExactPreImage(result, 0);
+  AbsStatsSetApproxPreImage(result, 0);
+  AbsStatsSetExactImage(result, 0);
+  AbsStatsSetPreImageCacheEntries(result, 0);
+  AbsStatsSetImageCacheEntries(result, 0);
+  AbsStatsSetImageCpuTime(result, 0);
+  AbsStatsSetPreImageCpuTime(result, 0);
+  AbsStatsSetAppPreCpuTime(result, 0);
+
+  return result;
+
+} /* End of AbsStatsInitialize */
+
+/**Function********************************************************************
+
+  Synopsis           [Function to free the AbsStats structure]
+
+  SideEffects        []
+
+  SeeAlso            [AbsStats]
+
+******************************************************************************/
+void
+AbsStatsFree(
+  AbsStats_t *unit)
+{
+  FREE(unit);
+} /* End of AbsStatsFree */
+
+/**Function********************************************************************
+
+  Synopsis [Initalize the entry of the cache for previously computed results]
+
+  SideEffects        []
+
+  SeeAlso            [AbsEvalCacheEntry]
+
+******************************************************************************/
+AbsEvalCacheEntry_t *
+AbsCacheEntryInitialize(void)
+{
+  AbsEvalCacheEntry_t *result;
+
+  result = ALLOC(AbsEvalCacheEntry_t, 1);
+
+  AbsEvalCacheEntrySetKey(result, NIL(mdd_t));
+  AbsEvalCacheEntrySetApprox(result, FALSE);
+  AbsEvalCacheEntrySetComplement(result, 0);
+  AbsEvalCacheEntrySetResult(result, NIL(mdd_t));
+  AbsEvalCacheEntrySetCareSet(result, NIL(mdd_t));
+
+  return result;
+} /* End of AbsCacheEntryInitialize */
+
+/**Function********************************************************************
+
+  Synopsis           [Function to de-allocate the AbsEvalCacheEntry]
+
+  SideEffects        []
+
+  SeeAlso            [AbsEvalCacheEntry]
+
+******************************************************************************/
+void
+AbsCacheEntryFree(
+  AbsEvalCacheEntry_t *unit)
+{
+  mdd_free(AbsEvalCacheEntryReadKey(unit));
+  mdd_free(AbsEvalCacheEntryReadResult(unit));
+  mdd_free(AbsEvalCacheEntryReadCareSet(unit));
+
+  FREE(unit);
+} /* End of AbsCacheEntryFree */
+
+/**Function********************************************************************
+
+  Synopsis           [Insert an item in the evaluation cache]
+
+  SideEffects        []
+
+  SeeAlso            [AbsEvalCacheEntry]
+
+******************************************************************************/
+void
+AbsEvalCacheInsert(
+  st_table *solutions,
+  mdd_t *key,
+  mdd_t *result,
+  mdd_t *careSet,
+  boolean approx,
+  boolean replace)
+{
+  AbsEvalCacheEntry_t *entry;
+  int                 complement;
+  bdd_node            *f;
+
+  entry = NIL(AbsEvalCacheEntry_t);
+  f = bdd_get_node(key, &complement);
+
+  /* If the replacement is required, delete the element from the table */
+  if (replace) {
+    st_delete(solutions, &f, &entry);
+
+    mdd_free(AbsEvalCacheEntryReadKey(entry));
+    mdd_free(AbsEvalCacheEntryReadResult(entry));
+    mdd_free(AbsEvalCacheEntryReadCareSet(entry));
+  }
+
+  assert(!st_is_member(solutions, (char *)f));
+
+  if (entry == NIL(AbsEvalCacheEntry_t)) {
+    entry = AbsCacheEntryInitialize();
+  }
+
+  AbsEvalCacheEntrySetKey(entry, mdd_dup(key));
+  AbsEvalCacheEntrySetApprox(entry, approx);
+  AbsEvalCacheEntrySetComplement(entry, complement);
+  AbsEvalCacheEntrySetResult(entry, mdd_dup(result));
+  AbsEvalCacheEntrySetCareSet(entry, mdd_dup(careSet));
+  
+  /* Insert the new entry in the cache */
+  st_insert(solutions, (char *)f, (char *)entry);
+
+  return;
+} /* End of AbsEvalCacheInsert */
+
+/**Function********************************************************************
+
+  Synopsis           [Lookup a previous evaluation in the cache]
+
+  SideEffects        []
+
+  SeeAlso            [AbsEvalCacheEntry]
+
+******************************************************************************/
+boolean
+AbsEvalCacheLookup(
+  st_table *solutions,
+  mdd_t *key,
+  mdd_t *careSet,
+  boolean approx,
+  mdd_t **result,
+  boolean *storedApprox)
+{
+  AbsEvalCacheEntry_t *entry;
+  bdd_node            *f;
+  int                 complement;
+  
+  f = bdd_get_node(key, &complement);
+
+  if (st_lookup(solutions, f, &entry)) {
+    if (complement == AbsEvalCacheEntryReadComplement(entry) &&
+	(approx || !AbsEvalCacheEntryReadApprox(entry)) &&
+	mdd_lequal(careSet, AbsEvalCacheEntryReadCareSet(entry), 1, 1)) {
+      *result = AbsEvalCacheEntryReadResult(entry);
+      if (storedApprox != 0) {
+	*storedApprox = AbsEvalCacheEntryReadApprox(entry);
+      }
+      return TRUE;
+    }
+    else {
+      st_delete(solutions, &f, &entry);
+      AbsCacheEntryFree(entry);
+    }
+  }
+
+  return FALSE;
+} /* End of AbsEvalCacheLookup */
+
+/**Function********************************************************************
+
+  Synopsis           [Delete all the entries in the evaluation cache]
+
+  SideEffects        []
+
+  SeeAlso            [AbsEvalCacheEntry]
+
+******************************************************************************/
+void
+AbsVerificationFlushCache(
+  Abs_VerificationInfo_t *absInfo)
+{
+  AbsEvalCacheEntry_t *value;
+  st_table            *table;
+  bdd_node            *key;
+  st_generator        *stgen;
+
+  table = AbsVerificationInfoReadImageCache(absInfo);
+
+  if (table == NIL(st_table)) {
+    return;
+  }
+
+  st_foreach_item(table, stgen, &key, &value) {
+    AbsCacheEntryFree(value);
+  }
+
+  st_free_table(table);
+  AbsVerificationInfoSetImageCache(absInfo, NIL(st_table));
+
+  return;
+} /* End of AbsVerificationFlushCache */
+
+/**Function********************************************************************
+
+  Synopsis [Delete all the entries stored in the local evaluation cache that a
+  given vertex has attached to it]
+
+  SideEffects        []
+
+  SeeAlso            [AbsVertexInfo]
+
+******************************************************************************/
+void
+AbsVertexFlushCache(
+  AbsVertexInfo_t *vertexPtr)
+{
+  if (AbsVertexReadType(vertexPtr) == preImage_c) {
+    if (AbsVertexReadSolutions(vertexPtr) != NIL(st_table)) {
+      AbsEvalCacheEntry_t *value;
+      bdd_node            *key;
+      st_generator        *stgen;
+      
+      st_foreach_item(AbsVertexReadSolutions(vertexPtr), stgen, &key,
+		      &value) {
+	AbsCacheEntryFree(value);
+      }
+      st_free_table(AbsVertexReadSolutions(vertexPtr));
+      AbsVertexSetSolutions(vertexPtr, NIL(st_table));
+    }
+  }
+
+  if (AbsVertexReadLeftKid(vertexPtr) != NIL(AbsVertexInfo_t)) {
+    AbsVertexFlushCache(AbsVertexReadLeftKid(vertexPtr));
+  }
+
+  if (AbsVertexReadRightKid(vertexPtr) != NIL(AbsVertexInfo_t)) {
+    AbsVertexFlushCache(AbsVertexReadRightKid(vertexPtr));
+  }
+
+  return;
+} /* End of AbsVertexFlushCache */
+
+/**Function********************************************************************
+
+  Synopsis [Read an image computation from the cache, and if it is not present,
+  invoke the image algorithm and store its result]
+
+  SideEffects        []
+
+  SeeAlso            [AbsEvalCacheEntry]
+
+******************************************************************************/
+mdd_t *
+AbsImageReadOrCompute(
+  Abs_VerificationInfo_t *absInfo,
+  Img_ImageInfo_t *imageInfo,
+  mdd_t *set,
+  mdd_t *careSet
+)
+{
+  AbsEvalCacheEntry_t *entry;
+  st_table            *table;
+  bdd_node            *f;
+  mdd_t               *result;
+  long                cpuTime;
+  int                 complement;
+
+  entry = NIL(AbsEvalCacheEntry_t);
+  table = AbsVerificationInfoReadImageCache(absInfo);
+  f = bdd_get_node(set, &complement);
+
+  /* See if the table has been created */
+  if (table == NIL(st_table)) {
+    table = st_init_table(st_ptrcmp, st_ptrhash);
+    AbsVerificationInfoSetImageCache(absInfo, table);
+  }
+  else {
+    /* Look up for the operation */
+    if (st_lookup(table, f, &entry)) {
+      if (complement == AbsEvalCacheEntryReadComplement(entry) &&
+	  mdd_lequal(careSet, AbsEvalCacheEntryReadCareSet(entry), 1, 1)) {
+	result = mdd_dup(AbsEvalCacheEntryReadResult(entry));
+	return result;
+      }
+      else {
+	st_delete(table, &f, &entry);
+
+	mdd_free(AbsEvalCacheEntryReadKey(entry));
+	mdd_free(AbsEvalCacheEntryReadResult(entry));
+	mdd_free(AbsEvalCacheEntryReadCareSet(entry));
+      }
+    }
+  }
+
+  /* The result has not been found. Compute it and insert it in the cache */
+  cpuTime = util_cpu_time();
+  result = Img_ImageInfoComputeFwdWithDomainVars(imageInfo, set, set, careSet);
+  AbsStatsReadImageCpuTime(AbsVerificationInfoReadStats(absInfo))+= 
+    util_cpu_time() - cpuTime;
+  AbsStatsReadExactImage(AbsVerificationInfoReadStats(absInfo))++;
+
+  if (entry == NIL(AbsEvalCacheEntry_t)) {
+    entry = AbsCacheEntryInitialize();
+  }
+
+  AbsEvalCacheEntrySetKey(entry, mdd_dup(set));
+  AbsEvalCacheEntrySetComplement(entry, complement);
+  AbsEvalCacheEntrySetResult(entry, mdd_dup(result));
+  AbsEvalCacheEntrySetCareSet(entry, mdd_dup(careSet));
+  
+  /* Insert the new entry in the cache */
+  st_insert(table, (char *)f, (char *)entry);
+
+  AbsStatsReadImageCacheEntries(AbsVerificationInfoReadStats(absInfo))++;
+
+  return result;
+} /* End of AbsImageReadOrCompute */
+
+/**Function********************************************************************
+
+  Synopsis [Procedure to fire the evaluation process for a collection of
+  formulas given in an array]
+
+  Description [This is the main procedure of the package. The command
+  abs_model_check invokes this function. This procedure invokes the procedure
+  AbsSubFormulaVerify]
+  
+  SideEffects []
+
+******************************************************************************/
+array_t *
+AbsFormulaArrayVerify(
+  Abs_VerificationInfo_t *absInfo,
+  array_t *formulaArray)
+{
+  AbsOptions_t    *options;
+  AbsVertexInfo_t *formulaPtr;
+  Fsm_Fsm_t       *fsm;
+  array_t         *result;
+  mdd_manager     *mddManager;
+  int             fIndex;
+  int             numReorderings;
+
+  /* Initialize some variables */
+  options = AbsVerificationInfoReadOptions(absInfo);
+  mddManager = AbsVerificationInfoReadMddManager(absInfo);
+  numReorderings = bdd_read_reorderings(mddManager);
+  
+  /* Print the configuration of the system */
+  if (AbsOptionsReadVerbosity(options) & ABS_VB_PIFF) {
+    (void) fprintf(vis_stdout, "ABS: System with (PI,FF) = (%d,%d)\n", 
+		   st_count(AbsVerificationInfoReadQuantifyVars(absInfo)), 
+		   st_count(AbsVerificationInfoReadStateVars(absInfo)));
+  }
+
+  /* Create the array of results */
+  result = array_alloc(AbsVerificationResult_t, array_n(formulaArray));
+
+  /* Obtain the fsm representing the complete circuit */
+  fsm = Fsm_FsmCreateFromNetworkWithPartition(
+          AbsVerificationInfoReadNetwork(absInfo), NIL(graph_t));
+
+  /* Traverse the array of formulas and verify all of them */
+  arrayForEachItem(AbsVertexInfo_t *, formulaArray, fIndex, formulaPtr) {
+    Fsm_Fsm_t *localSystem;
+    Fsm_Fsm_t *approxSystem;
+    array_t   *stateVarIds;
+    mdd_t     *initialStates;
+    mdd_t     *careStates;
+    long      cpuTime;
+    int       numBddVars;
+    int       mddId;
+    int       i;
+
+    /* Variable Initialization */
+    approxSystem = NIL(Fsm_Fsm_t);
+
+    /* Set the cpu-time lap */
+    cpuTime = util_cpu_time();
+
+    /* Print the labeled operational graph */
+    if (AbsOptionsReadVerbosity(options) & ABS_VB_GRAPH) {
+      (void) fprintf(vis_stdout, "ABS: === Labeled Operational Graph ===\n");
+      AbsVertexPrint(formulaPtr, NIL(st_table), TRUE,
+		     AbsOptionsReadVerbosity(options));
+      (void) fprintf(vis_stdout, "ABS: === End of Graph ===\n");
+    }
+    
+    /* Simplify the system with respect to the given formula */
+    localSystem = AbsCreateReducedFsm(absInfo, formulaPtr, &approxSystem);
+    if (localSystem == NIL(Fsm_Fsm_t)) {
+      localSystem = fsm;
+    }
+    if (approxSystem == NIL(Fsm_Fsm_t)) {
+      approxSystem = fsm;
+    }
+
+    AbsVerificationInfoSetFsm(absInfo, localSystem);
+
+    /* Compute the number of bdd variables needed to encode the state space */
+    stateVarIds = Fsm_FsmReadPresentStateVars(localSystem);
+    numBddVars = 0;
+    arrayForEachItem(int, stateVarIds, i, mddId) {
+      array_t *mvarList = mdd_ret_mvar_list(mddManager);
+      mvar_type mddVar  = array_fetch(mvar_type, mvarList, mddId);
+      numBddVars += mddVar.encode_length;
+    }
+    AbsVerificationInfoSetNumStateVars(absInfo, numBddVars);
+
+    AbsVerificationInfoSetApproxFsm(absInfo, approxSystem);
+
+    if (AbsOptionsReadVerbosity(options) & ABS_VB_SIMPLE) {
+      (void) fprintf(vis_stdout, 
+		     "ABS: System Simplified from %d to %d latches\n",
+		     array_n(Fsm_FsmReadPresentStateVars(fsm)),
+		     array_n(Fsm_FsmReadPresentStateVars(localSystem)));
+      (void) fprintf(vis_stdout, 
+		     "ABS: System Approximated by %d of %d latches\n",
+		     array_n(Fsm_FsmReadPresentStateVars(approxSystem)),
+		     array_n(Fsm_FsmReadPresentStateVars(localSystem)));
+    }
+		   
+    /* Compute reachability if requested */
+    if (AbsOptionsReadReachability(options)) {
+      mdd_t *reachableStates;
+      long  cpuTime;
+      
+      cpuTime = util_cpu_time();
+      
+      reachableStates = Fsm_FsmComputeReachableStates(localSystem, 0, 1, 0, 0, 
+		        0, 0, 0,Fsm_Rch_Default_c, 0, 0, NIL(array_t), FALSE,
+			NIL(array_t));
+      if (AbsOptionsReadVerbosity(options) & ABS_VB_PPROGR) {
+	(void) fprintf(vis_stdout, "ABS: %7.1f secs spent in reachability \n",
+		       (util_cpu_time() - cpuTime)/1000.0);
+      }
+
+      /* Print the number of reachable states */
+      if (AbsOptionsReadVerbosity(options) & ABS_VB_PRCH) {
+	array_t *sVars;
+	
+	sVars = Fsm_FsmReadPresentStateVars(localSystem);
+	(void) fprintf(vis_stdout, "ABS: System with %.0f reachable states.\n",
+		       mdd_count_onset(mddManager, reachableStates, sVars));
+      }
+      
+      careStates = reachableStates;
+    } /* End of reachability analysis */
+    else {
+      careStates = mdd_one(mddManager);
+    }
+
+    /* Compute the initial states */
+    initialStates = Fsm_FsmComputeInitialStates(localSystem);
+    if (initialStates == NIL(mdd_t)) {
+      (void) fprintf(vis_stdout, "** abs error: Unable to compute initial states.\n");
+      (void) fprintf(vis_stdout, "ABS: %s\n", error_string());
+      
+      AbsVerificationInfoFree(absInfo);
+      array_free(result);
+      /* Deallocate the FSM if the system was reduced */
+      if (localSystem != fsm) {
+	Fsm_FsmFree(localSystem);
+      }
+      return NIL(array_t);
+    }
+
+    /* Set the don't care information */
+    if (AbsVerificationInfoReadCareSet(absInfo) != NIL(mdd_t)) {
+      mdd_free(AbsVerificationInfoReadCareSet(absInfo));
+    }
+    AbsVerificationInfoSetCareSet(absInfo, careStates);
+    if (AbsVerificationInfoReadTmpCareSet(absInfo) != NIL(mdd_t)) {
+      mdd_free(AbsVerificationInfoReadTmpCareSet(absInfo));
+    }
+    AbsVerificationInfoSetTmpCareSet(absInfo, mdd_one(mddManager));
+
+    /* Compute the formula EG(true) if required */
+    if (AbsOptionsReadEnvelope(options)) {
+      mdd_t *newCareStates;
+      mdd_t *tmp1;
+
+      newCareStates = ComputeEGtrue(absInfo, careStates);
+      tmp1 = mdd_and(newCareStates, careStates, 1, 1);
+      mdd_free(careStates);
+      mdd_free(newCareStates);
+      careStates = tmp1;
+      AbsVerificationInfoSetCareSet(absInfo, careStates);
+    }
+
+    /* Print verbosity message */
+    if (AbsOptionsReadVerbosity(options) & ABS_VB_VTXCNT) {
+      (void) fprintf(vis_stdout, "ABS: === Initial Verification ===\n");
+    }
+    
+    /* Create the initial evaluation of the formula */
+    AbsSubFormulaVerify(absInfo, formulaPtr);
+    
+    assert(!AbsVertexReadTrueRefine(formulaPtr));
+
+    /* Print verbosity message */
+    if (AbsOptionsReadVerbosity(options) & ABS_VB_VTXCNT) {
+      (void) fprintf(vis_stdout, "ABS: === End of Initial Verification ===\n");
+    }
+    
+    /* Print cpu-time information */
+    if (AbsOptionsReadVerbosity(options) & ABS_VB_PPROGR) {
+      (void) fprintf(vis_stdout, "ABS: Initial verification: %7.1f secs.\n",
+		     (util_cpu_time() - cpuTime)/1000.0);
+    }
+
+    /* Check if the initial states satisfy the formula */
+    if (mdd_lequal(initialStates, AbsVertexReadSat(formulaPtr), 1, 1)) {
+	array_insert(int, result, fIndex, trueVerification_c);
+    }
+    else {
+      if (AbsVertexReadGlobalApprox(formulaPtr)) {
+	mdd_t *goalSet;
+	mdd_t *refinement;
+
+	/* 
+	 * Compute the set of states remaining in the goal. We are assuming
+	 * that the parity of the top vertex is negative 
+	 */
+	assert(!AbsVertexReadPolarity(formulaPtr));
+
+	/* Compute the initial goal set */
+	goalSet = mdd_and(initialStates, AbsVertexReadSat(formulaPtr), 1, 0);
+
+	/* Notify that the refinement process is beginning */
+	if (AbsOptionsReadVerbosity(options) &ABS_VB_PPROGR) {
+	  (void) fprintf(vis_stdout, 
+			 "ABS: Verification has been approximated. ");
+	  (void) fprintf(vis_stdout, "Beginning approximation refinement\n");
+	}
+
+	/* Print the number of states to refine */
+	if (AbsOptionsReadVerbosity(options) & ABS_VB_PRINIT) {
+	  array_t *sVars;
+
+	  sVars = Fsm_FsmReadPresentStateVars(fsm);
+	  (void) fprintf(vis_stdout, 
+			 "ABS: %.0f states out of %.0f to be refined\n",
+			 mdd_count_onset(mddManager, goalSet, sVars),
+			 mdd_count_onset(mddManager, initialStates, sVars));
+	}
+
+	/* Effectively perform the refinement */
+	refinement = AbsSubFormulaRefine(absInfo, formulaPtr, goalSet); 
+
+	/* Insert the outcome of the refinement in the solution */
+	if (mdd_is_tautology(refinement, 0)) {
+	  array_insert(int, result, fIndex, trueVerification_c);
+	}
+	else {
+	  if (!AbsVertexReadTrueRefine(formulaPtr)) {
+	    array_insert(int, result, fIndex, inconclusiveVerification_c);
+	  }
+	  else {
+	    array_insert(int, result, fIndex, falseVerification_c);
+	  }
+	}
+	mdd_free(goalSet);
+	mdd_free(refinement);
+      }
+      else {
+	array_insert(int, result, fIndex, falseVerification_c);
+      }
+    }
+    mdd_free(initialStates);
+    
+    /* Print cpu-time information */
+    if (AbsOptionsReadVerbosity(options) & ABS_VB_PPROGR) {
+      (void) fprintf(vis_stdout, "ABS: Formula #%d verified in %7.1f secs.\n",
+		     fIndex + 1, (util_cpu_time() - cpuTime)/1000.0);
+    }
+
+    /* Print the number of states in the on set of Sat */
+    if (AbsOptionsReadVerbosity(options) & ABS_VB_TSAT) {
+      array_t *sVars;
+      
+      sVars = Fsm_FsmReadPresentStateVars(localSystem);
+      (void) fprintf(vis_stdout, "ABS: %.0f States in sat of the formula.\n",
+		     mdd_count_onset(mddManager, AbsVertexReadSat(formulaPtr), 
+				     sVars));
+    }
+
+    /* Clean up */
+    AbsVertexFlushCache(formulaPtr);
+    AbsVerificationFlushCache(absInfo);
+    if (approxSystem != fsm) {
+      Fsm_FsmFree(approxSystem);
+    }
+    if (localSystem != fsm) {
+      Fsm_FsmFree(localSystem);
+    }
+  } /* End of the loop over the array of formulas to be verified */
+
+  /* Set the number of reorderings in the stats */
+  AbsStatsSetNumReorderings(AbsVerificationInfoReadStats(absInfo),
+			    bdd_read_reorderings(mddManager) - numReorderings);
+
+  /* Clean up */
+  Fsm_FsmFree(fsm);
+
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Given a FSM and operational graph, simplify the FSM based on
+  topological analysis of the FSM]
+
+  SideEffects        []
+
+******************************************************************************/
+Fsm_Fsm_t *
+AbsCreateReducedFsm(
+  Abs_VerificationInfo_t *absInfo,
+  AbsVertexInfo_t *vertexPtr,
+  Fsm_Fsm_t **approxFsm)
+{
+  AbsVertexInfo_t *vPtr;
+  Ntk_Network_t   *network;
+  Ntk_Node_t      *nodePtr;
+  Fsm_Fsm_t       *result;
+  lsGen           gen;
+  array_t         *vertexArray;
+  array_t         *nodeArray;
+  array_t         *supportArray;
+  array_t         *inputs;
+  array_t         *latches;
+  st_table        *visited;
+  int             i;
+
+  if (vertexPtr == NIL(AbsVertexInfo_t)) {
+    return NIL(Fsm_Fsm_t);
+  }
+
+  network = AbsVerificationInfoReadNetwork(absInfo);
+
+  /* Select the vertices of type "identifier" */
+  visited = st_init_table(st_ptrcmp, st_ptrhash);
+  vertexArray = array_alloc(AbsVertexInfo_t *, 0);
+  SelectIdentifierVertices(vertexPtr, vertexArray, visited);
+  st_free_table(visited);
+
+  if (array_n(vertexArray) == 0) {
+    array_free(vertexArray);
+    return NIL(Fsm_Fsm_t);
+  }
+
+  /* Create the array of network nodes corresponding to the identifiers */
+  visited = st_init_table(st_ptrcmp, st_ptrhash);
+  nodeArray = array_alloc(Ntk_Node_t *, 0);
+  arrayForEachItem(AbsVertexInfo_t *, vertexArray, i, vPtr) {
+    nodePtr = Ntk_NetworkFindNodeByName(network, AbsVertexReadName(vPtr));
+
+    assert(nodePtr != NIL(Ntk_Node_t));
+
+    if (!st_is_member(visited, (char *)nodePtr)) {
+      array_insert_last(Ntk_Node_t *, nodeArray, nodePtr);
+      st_insert(visited, (char *)nodePtr, NIL(char));
+    }
+  }
+  array_free(vertexArray);
+
+  /* Create the input and array latches to compute the approxFsm */
+  inputs = array_alloc(Ntk_Node_t *, 0);
+  Ntk_NetworkForEachInput(network, gen, nodePtr) {
+    array_insert_last(Ntk_Node_t *, inputs, nodePtr);
+  }
+  latches = array_alloc(Ntk_Node_t *, 0);
+  Ntk_NetworkForEachLatch(network, gen, nodePtr) {
+    if (st_is_member(visited, (char *)nodePtr)) {
+      array_insert_last(Ntk_Node_t *, latches, nodePtr);
+    }
+    else {
+      array_insert_last(Ntk_Node_t *, inputs, nodePtr);
+    }
+  }
+  st_free_table(visited);
+
+  /* Obtain the approximated system */
+  *approxFsm = Fsm_FsmCreateReducedFsm(network, NIL(graph_t), latches, inputs, 
+				       NIL(array_t));
+  array_free(inputs);
+  array_free(latches);
+
+  /* Obtain the transitive fanin of the nodes */
+  supportArray = Ntk_NodeComputeCombinationalSupport(network, nodeArray, FALSE);
+  array_free(nodeArray);
+
+  /* If the transitive fanin of the nodes is empty, return */
+  if (array_n(supportArray) == 0) {
+    array_free(supportArray);
+    return NIL(Fsm_Fsm_t);
+  }
+
+  /* Divide the nodes between inputs and latches and create the final FSM */
+  inputs = array_alloc(Ntk_Node_t *, 0);
+  latches = array_alloc(Ntk_Node_t *, 0);
+  arrayForEachItem(Ntk_Node_t *, supportArray, i, nodePtr) {
+    if (Ntk_NodeTestIsInput(nodePtr)) {
+      array_insert_last(Ntk_Node_t *, inputs, nodePtr);
+    }
+    else {
+      assert(Ntk_NodeTestIsLatch(nodePtr));
+      array_insert_last(Ntk_Node_t *, latches, nodePtr);
+    }
+  }
+  array_free(supportArray);
+
+  /* If the collection of inputs and latches is the whole FSM, return */
+  if (array_n(inputs) == Ntk_NetworkReadNumInputs(network) &&
+      array_n(latches) == Ntk_NetworkReadNumLatches(network)) {
+    array_free(inputs);
+    array_free(latches);
+    return NIL(Fsm_Fsm_t);
+  }
+
+  result = Fsm_FsmCreateReducedFsm(network, NIL(graph_t), latches, inputs, 
+				   NIL(array_t));
+
+  /* Clean up */
+  array_free(inputs);
+  array_free(latches);
+
+  return result;
+} /* End of AbsCreateReducedFsm */
+
+/**Function********************************************************************
+
+  Synopsis [Check if two functions are identical modulo the don't care function
+  provided]
+
+  SideEffects        []
+
+******************************************************************************/
+boolean
+AbsMddEqualModCareSet(
+  mdd_t *f,
+  mdd_t *g,
+  mdd_t *careSet)
+{
+  boolean result = mdd_equal_mod_care_set(f, g, careSet);
+  return result;
+} /* End of AbsMddEqualModCareSet */
+
+/**Function********************************************************************
+
+  Synopsis [Check if function f is contained in function g but taking into
+  account the provided care set]
+
+  SideEffects        []
+
+******************************************************************************/
+boolean
+AbsMddLEqualModCareSet(
+  mdd_t *f,
+  mdd_t *g,
+  mdd_t *careSet)
+{
+  boolean result = mdd_lequal_mod_care_set(f, g, 1, 1, careSet);
+  return result;
+} /* End of AbsMddLEqualModCareSet */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis           [Compute the verification of the formula EG(true)]
+
+  Description [This is provided as an option. The computation of this formula
+  might reduce the state space to be explored. Specifically, it gets rid of
+  states that do not have any successor as well as any other states leading to
+  them. The benefit of this computation is unclear, specially because some
+  tools that read verilog and produce blif-mv might produce a self loop in
+  every state for which no transition is specified. If that is so, there will
+  never be a state without a successor.]
+
+  SideEffects        []
+
+******************************************************************************/
+static mdd_t *
+ComputeEGtrue(
+  Abs_VerificationInfo_t *absInfo,
+  mdd_t *careStates)
+{
+  AbsOptions_t    *options;
+  AbsVertexInfo_t *vertex;
+  Ctlp_Formula_t  *egFormula;
+  Ctlp_Formula_t  *trueFormula;
+  mdd_manager     *mddManager;
+  array_t         *inputTranslation;
+  array_t         *outputTranslation;
+  mdd_t           *envelope;
+  long            cpuTime;
+  
+  cpuTime = util_cpu_time();
+  options = AbsVerificationInfoReadOptions(absInfo);
+  mddManager = AbsVerificationInfoReadMddManager(absInfo);
+  
+  /* Compute the EG(true) fixed point */
+  trueFormula = Ctlp_FormulaCreate(Ctlp_TRUE_c, NIL(void), NIL(void));
+  egFormula = Ctlp_FormulaCreate(Ctlp_EG_c, trueFormula, NIL(void));
+  
+  /* Translate into the graph representation */
+  inputTranslation = array_alloc(Ctlp_Formula_t *, 1);
+  array_insert(Ctlp_Formula_t *, inputTranslation, 0, egFormula);
+  outputTranslation = AbsCtlFormulaArrayTranslate(absInfo, inputTranslation, 
+						  NIL(array_t));
+  vertex = array_fetch(AbsVertexInfo_t *, outputTranslation, 0);
+  array_free(inputTranslation);
+  array_free(outputTranslation);
+  
+  /* Evaluate the formula */
+  AbsSubFormulaVerify(absInfo, vertex);
+  
+  envelope = mdd_dup(AbsVertexReadSat(vertex));
+  
+  /* Clean up */
+  Ctlp_FormulaFree(egFormula);
+  AbsVertexFree(AbsVerificationInfoReadCatalog(absInfo), vertex, 
+		NIL(AbsVertexInfo_t));
+  
+  /* Print the number of envelope states */
+  if (AbsOptionsReadVerbosity(options) & ABS_VB_PENV) {
+    array_t *sVars;
+    mdd_t *states;
+  
+    sVars = Fsm_FsmReadPresentStateVars(AbsVerificationInfoReadFsm(absInfo));
+    states = mdd_and(envelope, careStates, 1, 1);
+    (void) fprintf(vis_stdout, "ABS: Envelope with %.0f care states.\n",
+		   mdd_count_onset(mddManager, states, sVars));
+    mdd_free(states);
+  }
+  
+  if (AbsOptionsReadVerbosity(options) & ABS_VB_PENV) {
+    (void) fprintf(vis_stdout, "ABS: %7.1f secs computing EG(TRUE)\n",
+		   (util_cpu_time() - cpuTime)/1000.0);
+  }
+
+  return envelope;
+} /* End of ComputeEGtrue */
+
+/**Function********************************************************************
+
+  Synopsis [Given a graph, select the set of vertices that represent
+  identifiers]
+
+  SideEffects        []
+
+******************************************************************************/
+static void
+SelectIdentifierVertices(
+  AbsVertexInfo_t *vertexPtr,
+  array_t *result,
+  st_table *visited)
+{
+  assert(result != NIL(array_t));
+
+  if (vertexPtr == NIL(AbsVertexInfo_t)) {
+    return;
+  }
+
+  if (st_is_member(visited, (char *)vertexPtr)) {
+    return;
+  }
+
+  if (AbsVertexReadType(vertexPtr) == identifier_c) {
+    array_insert_last(AbsVertexInfo_t *, result, vertexPtr);
+    st_insert(visited, (char *)vertexPtr, NIL(char));
+    return;
+  }
+  else {
+    SelectIdentifierVertices(AbsVertexReadLeftKid(vertexPtr), result, visited);
+    SelectIdentifierVertices(AbsVertexReadRightKid(vertexPtr), result, visited);
+  }
+
+  st_insert(visited, (char *)vertexPtr, NIL(char));
+
+  return;
+} /* End of SelectIdentifierVertices */
Index: vis_dev/vis-2.3/src/abs/absRefine.c
===================================================================
--- vis_dev/vis-2.3/src/abs/absRefine.c	(revision 14)
+++ vis_dev/vis-2.3/src/abs/absRefine.c	(revision 14)
@@ -0,0 +1,1022 @@
+/**CFile***********************************************************************
+
+  FileName    [absRefine.c]
+
+  PackageName [abs]
+
+  Synopsis [Abstraction Refinement procedures for the mu-calculus model
+  checker.]
+
+  Author      [Abelardo Pardo <abel@vlsi.colorado.edu>]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "absInt.h"
+
+static char rcsid[] UNUSED = "$Id: absRefine.c,v 1.24 2002/09/19 05:25:01 fabio Exp $";
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static mdd_t * RefineVariable(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr, mdd_t *goalSet);
+static mdd_t * RefineIdentifier(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr, mdd_t *goalSet);
+static mdd_t * RefineNot(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr, mdd_t *goalSet);
+static mdd_t * RefineAnd(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr, mdd_t *goalSet);
+static mdd_t * RefineFixedPoint(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr, mdd_t *goalSet);
+static mdd_t * RefineFixedPointIterate(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr, mdd_t *goalSet, int iterateNumber);
+static mdd_t * RefinePreImage(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr, mdd_t *goalSet);
+static boolean RestoreContainment(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr);
+static int PruneIterateVector(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr);
+static mdd_t * SuccessTest(mdd_t *sat, mdd_t *goalSet, boolean polarity);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis           [Refine a given sub-formula]
+
+  Description [This function just checks for some trivial cases and then calls
+  the appropriate refinement function depending on the type of the formula]
+
+  SideEffects        []
+
+  SeeAlso [RefineAnd, RefineFixedPoint, RefineNot, RefinePreImage,
+  RefineIdentifier, RefineVariable]
+
+******************************************************************************/
+mdd_t *
+AbsSubFormulaRefine(
+  Abs_VerificationInfo_t *absInfo,
+  AbsVertexInfo_t *vertexPtr,
+  mdd_t *goalSet)
+{
+  AbsStats_t *stats;
+  mdd_manager *mddManager;
+  mdd_t *oldTmpCareSet = NIL(mdd_t);
+  mdd_t      *realGoalSet;
+  mdd_t      *result;
+  long       verbosity;
+
+  verbosity = AbsOptionsReadVerbosity(AbsVerificationInfoReadOptions(absInfo));
+  stats = AbsVerificationInfoReadStats(absInfo);
+  mddManager = AbsVerificationInfoReadMddManager(absInfo);
+
+  if (verbosity & ABS_VB_REFINE) {
+    (void) fprintf(vis_stdout, "ABS: Beginning Refinement of Vertex(%3d)\n",
+		   AbsVertexReadId(vertexPtr));
+  }
+
+  /* If the goal set is empty, do not refine */
+  if (mdd_is_tautology(goalSet, 0)) {
+
+    if (verbosity & ABS_VB_GOALSZ) {
+      (void) fprintf(vis_stdout, 
+		     "ABS: Empty Goal in Refinement of Vertex(%3d)\n",
+		     AbsVertexReadId(vertexPtr));
+    }
+
+    /* Set the refine flag */
+    AbsVertexSetTrueRefine(vertexPtr, TRUE);
+
+    return mdd_dup(goalSet);
+  }
+
+  realGoalSet = SuccessTest(AbsVertexReadSat(vertexPtr), goalSet, 
+			    AbsVertexReadPolarity(vertexPtr));
+
+  /* If the vertex is refined already do not try to refine it */
+  if (mdd_is_tautology(realGoalSet, 0) || 
+      !AbsVertexReadGlobalApprox(vertexPtr)) {
+
+    if (verbosity & ABS_VB_GOALSZ) {
+      (void) fprintf(vis_stdout, 
+		     "ABS: Quick (%d,%d) Refinement of Vertex(%3d)\n",
+		     mdd_is_tautology(realGoalSet, 0)? 1: 0,
+		     AbsVertexReadGlobalApprox(vertexPtr)? 0: 1,
+		     AbsVertexReadId(vertexPtr));
+    }
+
+    AbsVertexSetTrueRefine(vertexPtr, TRUE);
+    return realGoalSet;
+  }
+
+  if (verbosity & ABS_VB_GOALSZ) {
+    (void) fprintf(vis_stdout, "ABS: Received Goal Set-> ");
+    (void) fprintf(vis_stdout, "%d Nodes\n",
+		   mdd_size(realGoalSet));
+    if (verbosity & ABS_VB_GLCUBE) {
+      AbsBddPrintMinterms(realGoalSet);
+    }
+  }
+
+  mdd_free(realGoalSet);
+
+  /* If the current vertex has more than one parent, the temporary care set
+   * must be reset (because it depends on the path that led to this vertex) */
+  if (lsLength(vertexPtr->parent) > 1) {
+    oldTmpCareSet = AbsVerificationInfoReadTmpCareSet(absInfo);
+    AbsVerificationInfoSetTmpCareSet(absInfo, mdd_one(mddManager));
+  }
+
+  switch (AbsVertexReadType(vertexPtr)) {
+    case fixedPoint_c:
+      result = RefineFixedPoint(absInfo, vertexPtr, goalSet);
+      AbsStatsReadRefineFixedPoint(stats)++;
+      break;
+    case and_c: 
+      result = RefineAnd(absInfo, vertexPtr, goalSet);
+      AbsStatsReadRefineAnd(stats)++;
+      break;
+    case not_c:
+      result = RefineNot(absInfo, vertexPtr, goalSet);
+      AbsStatsReadRefineNot(stats)++;
+      break;
+    case preImage_c:
+      result = RefinePreImage(absInfo, vertexPtr, goalSet);
+      AbsStatsReadRefinePreImage(stats)++;
+      break;
+    case identifier_c:
+      result = RefineIdentifier(absInfo, vertexPtr, goalSet);
+      AbsStatsReadRefineIdentifier(stats)++;
+      break;
+    case variable_c:
+      result = RefineVariable(absInfo, vertexPtr, goalSet);
+      AbsStatsReadRefineVariable(stats)++;
+      break;
+    default: fail("Encountered unknown type of vertex\n");
+    }
+
+  if (verbosity & ABS_VB_REFINE) {
+    (void) fprintf(vis_stdout, 
+		   "ABS: Done Refining Vertex(%3d).\n",
+		   AbsVertexReadId(vertexPtr));
+  }
+
+  if (verbosity & ABS_VB_GOALSZ) {
+    (void) fprintf(vis_stdout, "ABS: Returned Goal Set-> ");
+    (void) fprintf(vis_stdout, "%d Nodes\n",
+		   mdd_size(result));
+    if (verbosity & ABS_VB_GLCUBE) {
+      AbsBddPrintMinterms(result);
+    }
+  }
+
+  if (verbosity  & ABS_VB_REFVTX) {
+    AbsVertexPrint(vertexPtr, NIL(st_table), FALSE, verbosity);
+  }
+
+  if (lsLength(vertexPtr->parent) > 1) {
+    /* Restore the old temporary careset */
+    mdd_free(AbsVerificationInfoReadTmpCareSet(absInfo));
+    AbsVerificationInfoSetTmpCareSet(absInfo, oldTmpCareSet);
+  }
+
+  return result;
+} /* End of AbsSubFormulaRefine */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis           [Function to refine the sat set of a variable vertex.]
+
+  Description [The variable vertex reads the value of sat from the environment,
+  therefore no approximation is done here. The function just reads if the
+  goalSet is included in the current sat. This function returns
+  trueVerification_c if the vertex has been successfully refined,
+  falseVerification_c if the vertex has been refined until the exact
+  computation has been performed but the refinement failed, and
+  inconclusiveVerification_c if the vertex has been refined to the extent of
+  the computational limits and still failed.]
+
+  SideEffects        []
+
+  SeeAlso            [AbsSubFormulaRefine]
+
+******************************************************************************/
+static mdd_t *
+RefineVariable(
+  Abs_VerificationInfo_t *absInfo,
+  AbsVertexInfo_t *vertexPtr,
+  mdd_t *goalSet)
+{
+  /* Set the current goalSet. If the pointer is non-empty, that means that the
+     variable belongs to a different pointer from the one being considered,
+     therefore, only the first goal set is of interest to us.*/
+  if (AbsVertexReadGoalSet(vertexPtr) == NIL(mdd_t)) {
+    AbsVertexSetGoalSet(vertexPtr, mdd_dup(goalSet));
+  }
+
+  /* Set the validity of the refinement */
+  AbsVertexSetTrueRefine(vertexPtr, !AbsVertexReadGlobalApprox(vertexPtr));
+
+  return mdd_dup(goalSet);
+} /* End of RefineVariable */
+
+/**Function********************************************************************
+
+  Synopsis           [Function to refine an atomic formula]
+
+  SideEffects        []
+
+  SeeAlso            [AbsSubFormulaRefine]
+
+******************************************************************************/
+static mdd_t *
+RefineIdentifier(
+  Abs_VerificationInfo_t *absInfo,
+  AbsVertexInfo_t *vertexPtr,
+  mdd_t *goalSet)
+{
+  /* Set the refinement flags */
+  AbsVertexSetTrueRefine(vertexPtr, TRUE);
+
+  /*
+   * If the polarity of this vertex is negative, we need to add states to
+   * the satisfying set.  Since we already have the exact set, the states not
+   * in it are the returned goal.  If the polarity is positive, we need to
+   * remove states.  The states of the incoming goal that are in the
+   * satisfying set are the returned goal.
+   */
+  if (AbsVertexReadPolarity(vertexPtr)) {
+    return mdd_and(goalSet, AbsVertexReadSat(vertexPtr), 1, 1);
+  } else {
+    return mdd_and(goalSet, AbsVertexReadSat(vertexPtr), 1, 0);
+  }
+} /* End of RefineIdentifier */
+
+/**Function********************************************************************
+
+  Synopsis           [Formula to refine a negation formula]
+
+  SideEffects        []
+
+  SeeAlso            [AbsSubFormulaRefine]
+
+******************************************************************************/
+static mdd_t *
+RefineNot(
+  Abs_VerificationInfo_t *absInfo,
+  AbsVertexInfo_t *vertexPtr,
+  mdd_t *goalSet)
+{
+  AbsVertexInfo_t *subFormula;
+  mdd_t *result;
+
+  /* The not vertex has a trivial propagation equation */
+  subFormula = AbsVertexReadLeftKid(vertexPtr);
+
+  /* Go ahead and re-evaluate */
+  mdd_free(AbsVertexReadSat(vertexPtr));
+
+  /* Refine recursively */
+  result = AbsSubFormulaRefine(absInfo, subFormula, goalSet);
+
+  /* Set the set sat */
+  AbsVertexSetSat(vertexPtr, mdd_not(AbsVertexReadSat(subFormula)));
+  
+  /* Set the approximation flags */
+  AbsVertexSetLocalApprox(vertexPtr, FALSE);
+  AbsVertexSetGlobalApprox(vertexPtr, AbsVertexReadGlobalApprox(subFormula));
+
+  /* Set the trueRefine flag */
+  AbsVertexSetTrueRefine(vertexPtr, AbsVertexReadTrueRefine(subFormula));
+
+  assert(mdd_lequal(result, goalSet, 1, 1));
+
+  return result;
+} /* End of RefineNot */
+
+/**Function********************************************************************
+
+  Synopsis           [Function to refine a conjunction formula]
+
+  SideEffects        []
+
+  SeeAlso            [AbsSubFormulaRefine]
+
+******************************************************************************/
+static mdd_t *
+RefineAnd(
+  Abs_VerificationInfo_t *absInfo,
+  AbsVertexInfo_t *vertexPtr,
+  mdd_t *goalSet)
+{
+  AbsVertexInfo_t *firstFormula;
+  AbsVertexInfo_t *secondFormula;
+  mdd_t           *kidFirstResult;
+  mdd_t           *conjunction;
+  mdd_t           *result;
+  mdd_t           *oldTmpCareSet;
+
+  /* Delete the old sat */
+  mdd_free(AbsVertexReadSat(vertexPtr));
+
+  /* Obtain the Sub-formulas  */
+  firstFormula = AbsVertexReadLeftKid(vertexPtr);
+  secondFormula = AbsVertexReadRightKid(vertexPtr);
+
+  kidFirstResult = AbsSubFormulaRefine(absInfo, firstFormula, goalSet);
+  
+  /* Store the temporary careset and set the new one */
+  oldTmpCareSet = AbsVerificationInfoReadTmpCareSet(absInfo);
+  AbsVerificationInfoSetTmpCareSet(absInfo, 
+				   mdd_and(oldTmpCareSet, 
+					   AbsVertexReadSat(firstFormula), 
+					   1,1));
+  
+  if (AbsVertexReadPolarity(vertexPtr)) {
+    /* 
+     * Positive polarity: The goal set is given to one sub-formula first for
+     * refinement, and the left-overs are given to the second sub-formula.
+     */
+    result = AbsSubFormulaRefine(absInfo, secondFormula, kidFirstResult);
+    mdd_free(kidFirstResult);
+  }
+  else { /* Vertex with negative polarity */
+    mdd_t *kidSecondResult;
+    mdd_t *reducedGoalSet;
+
+    reducedGoalSet = mdd_and(goalSet, AbsVertexReadSat(firstFormula), 1, 1);
+    kidSecondResult = AbsSubFormulaRefine(absInfo, secondFormula,
+					  reducedGoalSet);
+    result = mdd_or(kidFirstResult, kidSecondResult, 1, 1);
+
+    mdd_free(reducedGoalSet);
+    mdd_free(kidFirstResult);
+    mdd_free(kidSecondResult);
+  }
+
+  /* Restore the temporary careset */
+  mdd_free(AbsVerificationInfoReadTmpCareSet(absInfo));
+  AbsVerificationInfoSetTmpCareSet(absInfo, oldTmpCareSet);
+  
+  /* Re-evaluate the vertex just in case there has been some refinement */
+  conjunction = mdd_and(AbsVertexReadSat(firstFormula),
+			AbsVertexReadSat(secondFormula), 1, 1);
+  
+  /* Store the new Sat value */
+  AbsVertexSetSat(vertexPtr, conjunction);
+  
+  /* Set the approximation flags */
+  AbsVertexSetLocalApprox(vertexPtr, FALSE);
+  AbsVertexSetGlobalApprox(vertexPtr,
+			   AbsVertexReadGlobalApprox(firstFormula) || 
+			   AbsVertexReadGlobalApprox(secondFormula));
+
+  /* Set the refinement flags */
+  AbsVertexSetTrueRefine(vertexPtr, AbsVertexReadTrueRefine(firstFormula) &&
+			 AbsVertexReadTrueRefine(secondFormula));
+
+  assert(mdd_lequal(result, goalSet, 1, 1));
+
+  return result;
+} /* End of RefineAnd */
+
+/**Function********************************************************************
+
+  Synopsis           [Function to refine the fix-point sub-formulas]
+
+  Description [The function calls several additional procedures to perform the
+  refinement]
+
+  SideEffects        []
+
+  SeeAlso [AbsSubFormulaRefine, AbsFixedPointIterate, RefineFixedPointIterate,
+  PruneIterateVector, RestoreContainment]
+
+******************************************************************************/
+static mdd_t *
+RefineFixedPoint(
+  Abs_VerificationInfo_t *absInfo,
+  AbsVertexInfo_t *vertexPtr,
+  mdd_t *goalSet)
+{
+  boolean newIterates;
+  mdd_t   *currentGoalSet;
+  mdd_t   *result;
+  mdd_t   *oldTmpCareSet;
+  mdd_t   *newTmpCareSet;
+  mdd_t   *oneMdd;
+  int     numIterates;
+
+  /* Variable initialization */
+  numIterates = array_n(AbsVertexReadRings(vertexPtr)) - 1;
+  newIterates = TRUE;
+
+  /* Delete the previous result */
+  if (AbsVertexReadSat(vertexPtr) != NIL(mdd_t)) {
+    mdd_free(AbsVertexReadSat(vertexPtr));
+  }
+
+  /* Set the new care set */
+  oldTmpCareSet = AbsVerificationInfoReadTmpCareSet(absInfo);
+  newTmpCareSet = mdd_one(AbsVerificationInfoReadMddManager(absInfo));
+  AbsVerificationInfoSetTmpCareSet(absInfo, newTmpCareSet);
+
+  oneMdd = mdd_one(AbsVerificationInfoReadMddManager(absInfo));
+  currentGoalSet = mdd_dup(oneMdd);
+  /* While the fixed point has not been approximated exactly */
+  while (newIterates && AbsVertexReadGlobalApprox(vertexPtr)
+	 && !mdd_is_tautology(currentGoalSet, 0)) {
+    mdd_t *newGoalSet;
+    boolean pruneIterates;
+
+    newGoalSet = RefineFixedPointIterate(absInfo, vertexPtr, currentGoalSet,
+					 numIterates);
+
+    /* Release unnecessary functions */
+    mdd_free(newGoalSet);
+    mdd_free(currentGoalSet);
+
+    /* Restore the inclusion property in the fixed point iterates */
+    pruneIterates = RestoreContainment(absInfo, vertexPtr);
+
+    /* Remove redundant iterates */
+    if (pruneIterates) {
+      numIterates = PruneIterateVector(absInfo, vertexPtr);
+    }
+
+    /* Sanity check of the refinement process */
+    assert(AbsIteratesSanityCheck(absInfo, vertexPtr));
+
+    /* Check if further iteration is required */
+    newIterates = AbsFixedPointIterate(absInfo, vertexPtr, numIterates);
+    numIterates = array_n(AbsVertexReadRings(vertexPtr)) - 1;
+
+    currentGoalSet = SuccessTest(AbsVertexFetchRing(vertexPtr, numIterates),
+				 oneMdd, AbsVertexReadPolarity(vertexPtr));
+  } /* End of while loop */
+
+  mdd_free(oneMdd);
+
+  /* Restore the old temporary careset */
+  mdd_free(newTmpCareSet);
+  AbsVerificationInfoSetTmpCareSet(absInfo, oldTmpCareSet);
+
+  AbsVertexSetSat(vertexPtr, 
+		  mdd_dup(AbsVertexFetchRing(vertexPtr, numIterates)));
+
+  AbsVertexSetLocalApprox(vertexPtr, FALSE);
+  AbsVertexSetGlobalApprox(vertexPtr, 
+			   AbsVertexFetchSubApprox(vertexPtr, numIterates));
+
+  result = mdd_and(currentGoalSet, goalSet, 1, 1);
+  mdd_free(currentGoalSet);
+  return result;
+} /* End of RefineFixedPoint */
+
+/**Function********************************************************************
+
+  Synopsis           [Apply the refinement procedure to one of the iterations
+  of the fix-point]
+
+  SideEffects        []
+
+  SeeAlso            [AbsSubFormulaRefine]
+
+******************************************************************************/
+static mdd_t *
+RefineFixedPointIterate(
+  Abs_VerificationInfo_t *absInfo,
+  AbsVertexInfo_t *vertexPtr,
+  mdd_t *goalSet,
+  int iterateNumber)
+{
+  AbsVertexInfo_t *varFormula;
+  AbsVertexInfo_t *subFormula;
+  boolean         trueRefine;
+  mdd_t           *careSet;
+  mdd_t           *variableValue;
+  mdd_t           *result;
+  mdd_t           *previousGoal;
+  mdd_t           *refinedGoal;
+  mdd_t           *newIterate;
+  mdd_t           *oldIterate;
+  mdd_t           *subFormulaSat;
+  int             saveExact;
+
+  assert(iterateNumber != 0);
+
+  /* Variable initialization */
+  varFormula = AbsVertexReadFpVar(vertexPtr);
+  subFormula = AbsVertexReadLeftKid(vertexPtr);
+  careSet = AbsVerificationInfoReadCareSet(absInfo);
+  oldIterate = AbsVertexFetchRing(vertexPtr, iterateNumber);
+
+  /* Propagate the goalSet for refinement */
+  variableValue = AbsVertexFetchRing(vertexPtr, iterateNumber - 1);
+
+  AbsVertexSetSat(varFormula, variableValue);
+
+  AbsVertexSetGlobalApprox(varFormula,
+			   AbsVertexFetchSubApprox(vertexPtr,
+						   iterateNumber - 1));
+
+  /* Schedule the formula for Re-evaluation */
+  AbsFormulaScheduleEvaluation(varFormula, vertexPtr);
+
+  /* Evaluate the sub-formula again */
+  AbsSubFormulaVerify(absInfo, subFormula);
+
+  /* Set the goal to empty to detect if the refinement reaches it */
+  if (AbsVertexReadGoalSet(varFormula) != NIL(mdd_t)) {
+    mdd_free(AbsVertexReadGoalSet(varFormula));
+    AbsVertexSetGoalSet(varFormula, NIL(mdd_t));
+  }
+
+  /* Refine the sub-formula for this iterate */
+  result = AbsSubFormulaRefine(absInfo, subFormula, goalSet);
+
+  /* Read the trueRefine from the subFormula */
+  trueRefine = AbsVertexReadTrueRefine(subFormula);
+
+  /* If The refinement does not need a recursive step, return. The return may
+   * be for three different reasons:
+   *   a) The local refinement that was just done, succeeded completely.
+   *   b) The goalset in varFormula is NIL, which means, the refinement
+          process failed somewhere earlier in the process, and therefore, the
+	  false result was computed without the refinement of the variable.
+       c) trueRefine is TRUE. Which means, that even though the approximate
+          flag in the vertex is TRUE, meaning that there has been an
+	  approximation, the refinement is still solid
+   */
+  if (mdd_is_tautology(result, 0) || trueRefine || 
+      AbsVertexReadGoalSet(varFormula) == NIL(mdd_t)) {
+
+    subFormulaSat = AbsVertexReadSat(subFormula);
+    if (AbsVertexReadPolarity(vertexPtr)) {
+      if (AbsMddLEqualModCareSet(subFormulaSat, oldIterate, careSet)) {
+	newIterate = mdd_dup(subFormulaSat);
+      }
+      else {
+	newIterate = mdd_and(subFormulaSat, oldIterate, 1, 1);
+      }
+    }
+    else {
+      if (AbsMddLEqualModCareSet(oldIterate, subFormulaSat, careSet)) {
+	newIterate = mdd_dup(subFormulaSat);
+      }
+      else {
+	newIterate = mdd_or(subFormulaSat, oldIterate, 1, 1);
+      }
+    }
+
+    mdd_free(oldIterate);
+    array_insert(mdd_t *, AbsVertexReadRings(vertexPtr), iterateNumber,
+		 newIterate);
+
+    /* Set the new approx flag */
+    array_insert(boolean, AbsVertexReadSubApprox(vertexPtr), iterateNumber,
+		 AbsVertexReadGlobalApprox(subFormula));
+
+    AbsVertexSetTrueRefine(vertexPtr, trueRefine);
+
+    return result;
+  }
+
+  /* Recursive call to refine the previous iterate */
+  previousGoal = mdd_dup(AbsVertexReadGoalSet(varFormula));
+  refinedGoal = RefineFixedPointIterate(absInfo, vertexPtr, previousGoal,
+					iterateNumber - 1);
+
+  trueRefine = AbsVertexReadTrueRefine(vertexPtr);
+
+  /* 
+   * Due to the refinement of the previous iterate, convergence might have
+   * been reached
+   */
+  if (iterateNumber > 1) {
+    mdd_t *ring1 = AbsVertexFetchRing(vertexPtr, iterateNumber - 1);
+    mdd_t *ring2 = AbsVertexFetchRing(vertexPtr, iterateNumber - 2);
+    if (AbsMddLEqualModCareSet(ring1, ring2, careSet)) {
+      mdd_free(previousGoal);
+      mdd_free(refinedGoal);
+      mdd_free(oldIterate);
+      mdd_free(result);
+
+      array_insert(mdd_t *, AbsVertexReadRings(vertexPtr), iterateNumber,
+		   mdd_dup(AbsVertexFetchRing(vertexPtr, iterateNumber - 1)));
+
+      AbsVertexSetTrueRefine(vertexPtr, trueRefine);
+
+      /* Set the new approx flag */
+      array_insert(boolean, AbsVertexReadSubApprox(vertexPtr), iterateNumber, 
+		   AbsVertexReadGlobalApprox(subFormula));
+
+      return SuccessTest(AbsVertexFetchRing(vertexPtr, iterateNumber),
+			 goalSet, AbsVertexReadPolarity(vertexPtr));
+    }
+  }
+
+  mdd_free(previousGoal);
+  mdd_free(refinedGoal);
+
+  /* Evaluate the sub-formula exactly */
+  variableValue = AbsVertexFetchRing(vertexPtr, iterateNumber - 1);
+
+  AbsVertexSetSat(varFormula, variableValue);
+  mdd_free(result);
+
+  AbsVertexSetGlobalApprox(varFormula, 
+			   AbsVertexFetchSubApprox(vertexPtr, 
+						   iterateNumber - 1));
+
+  /* Schedule the formula for Re-evaluation */
+  AbsFormulaScheduleEvaluation(varFormula, vertexPtr);
+
+  /* Evaluate the sub-formula this time exactly */
+  saveExact = AbsOptionsReadExact(AbsVerificationInfoReadOptions(absInfo));
+  AbsOptionsSetExact(AbsVerificationInfoReadOptions(absInfo), TRUE);
+  AbsSubFormulaVerify(absInfo, subFormula);
+  AbsOptionsSetExact(AbsVerificationInfoReadOptions(absInfo), saveExact);
+
+  /* Enforce monotonicity of the approximants */
+  subFormulaSat = AbsVertexReadSat(subFormula);
+  if (AbsVertexReadPolarity(vertexPtr)) {
+    if (AbsMddLEqualModCareSet(subFormulaSat, oldIterate, careSet)) {
+      newIterate = mdd_dup(subFormulaSat);
+    }
+    else {
+      newIterate = mdd_and(subFormulaSat, oldIterate, 1, 1);
+    }
+  }
+  else {
+    if (AbsMddLEqualModCareSet(oldIterate, subFormulaSat, careSet)) {
+      newIterate = mdd_dup(subFormulaSat);
+    }
+    else {
+      newIterate = mdd_or(subFormulaSat, oldIterate, 1, 1);
+    }
+  }
+
+  /* Set the new approx flag */
+  array_insert(boolean, AbsVertexReadSubApprox(vertexPtr), iterateNumber, 
+	       AbsVertexReadGlobalApprox(subFormula));
+
+  /* Recompute the goal set and the iterate */
+  result = SuccessTest(newIterate, goalSet,
+		       AbsVertexReadPolarity(vertexPtr));
+
+  /* Some basic sanity check */
+  assert(AbsVertexReadPolarity(vertexPtr)?
+	 AbsMddLEqualModCareSet(newIterate, oldIterate, careSet):
+	 AbsMddLEqualModCareSet(oldIterate, newIterate, careSet));
+
+  /* Store the new iterate */
+  mdd_free(oldIterate);
+  array_insert(mdd_t *, AbsVertexReadRings(vertexPtr), iterateNumber, 
+	       newIterate);
+
+  /* Set the new approx flag */
+  array_insert(boolean, AbsVertexReadSubApprox(vertexPtr), iterateNumber, 
+	       AbsVertexReadGlobalApprox(subFormula));
+
+  AbsVertexSetTrueRefine(vertexPtr, trueRefine);
+
+  return result;
+} /* End of RefineFixedPointIterate */
+
+/**Function********************************************************************
+
+  Synopsis           [Function to refine the pre-image sub-formula]
+
+  SideEffects        []
+
+  SeeAlso            [AbsSubFormulaRefine]
+
+******************************************************************************/
+static mdd_t *
+RefinePreImage(
+  Abs_VerificationInfo_t *absInfo,
+  AbsVertexInfo_t *vertexPtr,
+  mdd_t *goalSet)
+{
+  AbsStats_t      *stats;
+  AbsVertexInfo_t *subFormula;
+  Img_ImageInfo_t *imageInfo;
+  Fsm_Fsm_t       *system;
+  mdd_t           *careSet;
+  mdd_t           *result;
+  mdd_t           *subResult;
+  mdd_t           *newGoalSet;
+  mdd_t           *oldTmpCareSet;
+  mdd_t           *preImage;
+
+  /* Variable initialization */
+  system = AbsVerificationInfoReadFsm(absInfo);
+  subFormula = AbsVertexReadLeftKid(vertexPtr);
+  subResult = AbsVertexReadSat(subFormula);
+  stats = AbsVerificationInfoReadStats(absInfo);
+  imageInfo = Fsm_FsmReadOrCreateImageInfo(system, 1, 1);
+  careSet = mdd_and(AbsVerificationInfoReadCareSet(absInfo),
+		    AbsVerificationInfoReadTmpCareSet(absInfo), 1, 1);
+
+  /* Propagate the goal set */
+  newGoalSet = AbsImageReadOrCompute(absInfo, imageInfo, goalSet, subResult);
+
+  /* Store the new care set */
+  oldTmpCareSet = AbsVerificationInfoReadTmpCareSet(absInfo);
+  AbsVerificationInfoSetTmpCareSet(absInfo, 
+			mdd_one(AbsVerificationInfoReadMddManager(absInfo)));
+
+  /* Refine recursively */
+  result = AbsSubFormulaRefine(absInfo, subFormula, newGoalSet);
+
+  /* Restore the old temporary careset */
+  mdd_free(AbsVerificationInfoReadTmpCareSet(absInfo));
+  AbsVerificationInfoSetTmpCareSet(absInfo, oldTmpCareSet);
+
+  if (!mdd_equal(result, newGoalSet) || 
+      !AbsVertexReadGlobalApprox(subFormula)) {
+    mdd_free(AbsVertexReadSat(vertexPtr));
+    
+    if (AbsVertexReadSolutions(vertexPtr) == NIL(st_table)) {
+      /* Initialize the cache */
+      AbsVertexSetSolutions(vertexPtr, st_init_table(st_ptrcmp, st_ptrhash));
+    }
+    
+    preImage = NIL(mdd_t);
+    if (AbsEvalCacheLookup(AbsVertexReadSolutions(vertexPtr),
+			   AbsVertexReadSat(subFormula), careSet, FALSE,
+			   &preImage, 0)) {
+      
+      /* Set the sat */
+      AbsVertexSetSat(vertexPtr, mdd_dup(preImage));
+    }
+    else {
+      long cpuTime;
+      
+      subResult = AbsVertexReadSat(subFormula);
+      
+      cpuTime = util_cpu_time();
+      AbsVertexSetSat(vertexPtr, 
+		      Img_ImageInfoComputeBwdWithDomainVars(imageInfo, 
+							    subResult,
+							    subResult,
+							    careSet));
+      AbsStatsReadPreImageCpuTime(stats)+= util_cpu_time() - cpuTime;
+      
+      AbsStatsReadExactPreImage(stats)++;
+      
+      /* Insert the result in the cache */
+      AbsEvalCacheInsert(AbsVertexReadSolutions(vertexPtr),
+			 AbsVertexReadSat(subFormula),
+			 AbsVertexReadSat(vertexPtr), careSet,
+			 FALSE, FALSE);
+      
+    }
+    /* Set the new approximation flags */
+    AbsVertexSetLocalApprox(vertexPtr, FALSE);
+    AbsVertexSetGlobalApprox(vertexPtr, 
+			     AbsVertexReadGlobalApprox(subFormula));
+  } /* If !mdd_equal || !GlobalApprox(subFormula) */
+  mdd_free(careSet);
+  mdd_free(newGoalSet);
+  mdd_free(result);
+
+  result = SuccessTest(AbsVertexReadSat(vertexPtr), goalSet,
+		       AbsVertexReadPolarity(vertexPtr));
+
+  AbsVertexSetTrueRefine(vertexPtr, 
+			 AbsVertexReadTrueRefine(subFormula));
+
+  return result;
+} /* End of RefinePreImage */
+
+/**Function********************************************************************
+
+  Synopsis [Function to restore the containment relation between the iterations
+  of a fix-point]
+
+  Description [After the refinement procedure has gone through the iterations
+  of the fix-point, it is possible that the containment relation is no longer
+  satisfied. This function looks at the polarity of the formula inside the
+  fix-point and restores the containment relation to the iterations. This
+  process can be seen as the propagation of certain refinements in the middle
+  of the chain of iterations to the rest of the chain]
+
+  SideEffects        []
+
+  SeeAlso            [AbsSubFormulaRefine]
+
+******************************************************************************/
+static boolean
+RestoreContainment(
+  Abs_VerificationInfo_t *absInfo,
+  AbsVertexInfo_t *vertexPtr)
+{
+  mdd_t *iterateMdd;
+  mdd_t *iterateMddPrevious;
+  mdd_t *product;
+  boolean convergence;
+  int numIterates;
+  int index;
+
+  convergence = FALSE;
+  numIterates = array_n(AbsVertexReadRings(vertexPtr)) - 1;
+
+  if (AbsVertexReadPolarity(vertexPtr)) {
+    iterateMddPrevious = AbsVertexFetchRing(vertexPtr, numIterates);
+    
+    for(index = numIterates - 1; index >= 0; index--) {
+      iterateMdd = iterateMddPrevious;
+      iterateMddPrevious = AbsVertexFetchRing(vertexPtr, index);
+      
+      if (!AbsMddLEqualModCareSet(iterateMddPrevious, iterateMdd,
+				  AbsVerificationInfoReadCareSet(absInfo))) {
+	product = mdd_and(iterateMddPrevious, iterateMdd, 1, 1);
+	
+	/* Add here don't care minimization */
+	
+	mdd_free(iterateMddPrevious);
+	array_insert(mdd_t *, AbsVertexReadRings(vertexPtr), index, product);
+	iterateMddPrevious = product;
+      }
+
+      if (index != numIterates - 1 &&
+	  AbsMddLEqualModCareSet(iterateMdd, iterateMddPrevious,
+				 AbsVerificationInfoReadCareSet(absInfo))) {
+	convergence = TRUE;
+      }
+    }
+  }
+  else {
+    iterateMdd = AbsVertexFetchRing(vertexPtr, 0);
+
+    for(index = 1; index <= numIterates; index++) {
+      iterateMddPrevious = iterateMdd;
+      iterateMdd = AbsVertexFetchRing(vertexPtr, index);
+
+      if (!AbsMddLEqualModCareSet(iterateMddPrevious, iterateMdd,
+				  AbsVerificationInfoReadCareSet(absInfo))) {
+	product = mdd_or(iterateMddPrevious, iterateMdd, 1, 1);
+	
+	/* Add here don't care minimization */
+
+	mdd_free(iterateMdd);
+	array_insert(mdd_t *, AbsVertexReadRings(vertexPtr), index, product);
+	iterateMdd = product;
+      }
+      
+      if (index != numIterates &&
+	  AbsMddLEqualModCareSet(iterateMdd, iterateMddPrevious,
+				 AbsVerificationInfoReadCareSet(absInfo))) {
+	convergence = TRUE;
+      }
+    }
+  }
+
+  return convergence;
+} /* End of RestoreContainment */
+
+/**Function********************************************************************
+
+  Synopsis [Detect early convergence in the iterations of a fix-point]
+
+  Description [After the refinement process has modified the iterations of the
+  fix-point and the containment relation has been restored, it could happen
+  that two iterations in the middle of the chain are identical. This is an
+  early termination condition and the sequence of iterations needs to be
+  pruned]
+
+  SideEffects        []
+
+  SeeAlso            [AbsSubFormulaRefine]
+
+******************************************************************************/
+static int
+PruneIterateVector(
+  Abs_VerificationInfo_t *absInfo,
+  AbsVertexInfo_t *vertexPtr)
+{
+  array_t *newRings;
+  array_t *newRingApprox;
+  array_t *newSubApprox;
+  mdd_t   *current;
+  mdd_t   *previous;
+  mdd_t   *careSet;
+  int     numIterates;
+  int     index;
+
+  /* Read the care Set */
+  careSet = AbsVerificationInfoReadCareSet(absInfo);
+  
+  /* Read the number of iterates initially in the vertex */
+  numIterates = array_n(AbsVertexReadRings(vertexPtr)) - 1;
+  assert(numIterates > 0);
+  
+  /* If there are only two iterates, no pruning is needed */
+  if (numIterates < 2) {
+    return numIterates;
+  }
+
+  /* Allocate the new arrays to store the new iterates */
+  newRings = array_alloc(mdd_t *, 0);
+  newRingApprox = array_alloc(boolean, 0);
+  newSubApprox = array_alloc(boolean, 0);
+
+  /* Initial values for the loop */
+  index = 1;
+  previous = AbsVertexFetchRing(vertexPtr, index - 1);
+  current = AbsVertexFetchRing(vertexPtr, index);
+  array_insert_last(mdd_t *, newRings, mdd_dup(previous));
+  array_insert_last(boolean, newRingApprox,
+		    AbsVertexFetchRingApprox(vertexPtr, index - 1));
+  array_insert_last(boolean, newSubApprox,
+		    AbsVertexFetchSubApprox(vertexPtr, index - 1));
+
+  /* Traverse the set of iterates */
+  while (index < numIterates && 
+	 !AbsMddLEqualModCareSet(current, previous, careSet)) {
+    array_insert_last(mdd_t *, newRings, mdd_dup(current));
+    array_insert_last(boolean, newRingApprox,
+		      AbsVertexFetchRingApprox(vertexPtr, index));
+    array_insert_last(boolean, newSubApprox,
+		      AbsVertexFetchSubApprox(vertexPtr, index));
+    index++;
+    previous = current;
+    current = AbsVertexFetchRing(vertexPtr, index);
+  }
+
+  /* Insert the last two elements of the array */
+  array_insert_last(mdd_t *, newRings, mdd_dup(current));
+  array_insert_last(boolean, newRingApprox, 
+		    AbsVertexFetchRingApprox(vertexPtr, index));
+  array_insert_last(boolean, newSubApprox,
+		    AbsVertexFetchSubApprox(vertexPtr, index));
+
+  /* Free the arrays stored in the vertex and store the new ones */
+  arrayForEachItem(mdd_t *, AbsVertexReadRings(vertexPtr), index, current) {
+    mdd_free(current);
+  }
+  array_free(AbsVertexReadRings(vertexPtr));
+  array_free(AbsVertexReadRingApprox(vertexPtr));
+  array_free(AbsVertexReadSubApprox(vertexPtr));
+  
+  /* Store the new results */
+  AbsVertexSetRings(vertexPtr, newRings);
+  AbsVertexSetRingApprox(vertexPtr, newRingApprox);
+  AbsVertexSetSubApprox(vertexPtr, newSubApprox);
+  
+  assert(array_n(newRings) == array_n(newRingApprox));
+  assert(array_n(newRings) == array_n(newSubApprox));
+
+  return array_n(newRings) - 1;
+} /* End of PruneIterateVector */
+
+/**Function********************************************************************
+
+  Synopsis [Test if the function SAT is contained/excluded from the goal set
+  depending on the polarity]
+
+  SideEffects        []
+
+  SeeAlso            [AbsSubFormulaRefine]
+
+******************************************************************************/
+static mdd_t *
+SuccessTest(
+  mdd_t *sat,
+  mdd_t *goalSet,
+  boolean polarity)
+{
+  mdd_t *result;
+
+  if (polarity) {
+    result = mdd_and(goalSet, sat, 1, 1);
+  }
+  else {
+    result = mdd_and(goalSet, sat, 1, 0);
+  }
+
+  return result;
+} /* End of SuccessTest */
Index: vis_dev/vis-2.3/src/abs/absTranslate.c
===================================================================
--- vis_dev/vis-2.3/src/abs/absTranslate.c	(revision 14)
+++ vis_dev/vis-2.3/src/abs/absTranslate.c	(revision 14)
@@ -0,0 +1,1645 @@
+/**CFile***********************************************************************
+
+  FileName    [absTranslate.c]
+
+  PackageName [abs]
+
+  Synopsis    [Functions to translate CTL formulas to mu-calculus graphs.]
+
+  Author      [Abelardo Pardo <abel@vlsi.colorado.edu>]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "absInt.h" 
+
+static char rcsid[] UNUSED = "$Id: absTranslate.c,v 1.14 2002/09/04 14:58:18 fabio Exp $";
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static AbsVertexInfo_t * TranslateCtlSubFormula(AbsVertexCatalog_t *catalog, Ctlp_Formula_t *formula, array_t *fairArray, AbsVertexInfo_t *fairPositive, AbsVertexInfo_t *fairNegative, int polarity, int *uniqueIds);
+static AbsVertexInfo_t * ComputeFairPredicate(AbsVertexCatalog_t *catalog, AbsVertexInfo_t *atomicPredicate, array_t *fairArray, int polarity, int *uniqueIds);
+static AbsVertexInfo_t * TranslateCtlID(AbsVertexCatalog_t *catalog, Ctlp_Formula_t *formula, int polarity);
+static AbsVertexInfo_t * TranslateCtlEU(AbsVertexCatalog_t *catalog, Ctlp_Formula_t *formula, array_t *fairArray, AbsVertexInfo_t *fairPositive, AbsVertexInfo_t *fairNegative, int polarity, int *uniqueIds);
+static AbsVertexInfo_t * TranslateCtlEG(AbsVertexCatalog_t *catalog, Ctlp_Formula_t *formula, int polarity, int *uniqueIds);
+static AbsVertexInfo_t * TranslateCtlEGFair(AbsVertexCatalog_t *catalog, Ctlp_Formula_t *formula, array_t *fairArray, AbsVertexInfo_t *fairPositive, AbsVertexInfo_t *fairNegative, int polarity, int *uniqueIds);
+static AbsVertexInfo_t * TranslateCtlEX(AbsVertexCatalog_t *catalog, Ctlp_Formula_t *formula, array_t *fairArray, AbsVertexInfo_t *fairPositive, AbsVertexInfo_t *fairNegative, int polarity, int *uniqueIds);
+static AbsVertexInfo_t * TranslateCtlNOT(AbsVertexCatalog_t *catalog, Ctlp_Formula_t *formula, array_t *fairArray, AbsVertexInfo_t *fairPositive, AbsVertexInfo_t *fairNegative, int polarity, int *uniqueIds);
+static AbsVertexInfo_t * TranslateCtlTHEN(AbsVertexCatalog_t *catalog, Ctlp_Formula_t *formula, array_t *fairArray, AbsVertexInfo_t *fairPositive, AbsVertexInfo_t *fairNegative, int polarity, int *uniqueIds);
+static AbsVertexInfo_t * TranslateCtlAND(AbsVertexCatalog_t *catalog, Ctlp_Formula_t *formula, array_t *fairArray, AbsVertexInfo_t *fairPositive, AbsVertexInfo_t *fairNegative, int polarity, int *uniqueIds);
+static AbsVertexInfo_t * TranslateCtlOR(AbsVertexCatalog_t *catalog, Ctlp_Formula_t *formula, array_t *fairArray, AbsVertexInfo_t *fairPositive, AbsVertexInfo_t *fairNegative, int polarity, int *uniqueIds);
+static AbsVertexInfo_t * CreateConjunctionChain(AbsVertexCatalog_t *catalog, array_t *conjunctions, int polarity);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Translate an array of CTL formulas to an array of labeled
+  operational graphs. The graphs may share vertices among them.]
+
+  SideEffects        []
+
+  SeeAlso            [TranslateCtlSubFormula]
+
+******************************************************************************/
+array_t *
+AbsCtlFormulaArrayTranslate(
+  Abs_VerificationInfo_t *verInfo,
+  array_t *formulaArray,
+  array_t *fairArray)
+{
+  AbsVertexCatalog_t *catalog;
+  Ctlp_Formula_t  *formulaPtr;
+  AbsVertexInfo_t *fairPositive;
+  AbsVertexInfo_t *fairNegative;
+  array_t         *result;
+  boolean         initialPolarity;
+  int             uniqueIds;
+  int             i;
+
+  if (formulaArray == NIL(array_t)) {
+    return NIL(array_t);
+  }
+
+  /* Initialize certain variables */
+  catalog = AbsVerificationInfoReadCatalog(verInfo);
+  uniqueIds = 0;
+
+  if (fairArray != NIL(array_t)) {
+    fairPositive = ComputeFairPredicate(catalog, NIL(AbsVertexInfo_t),
+					fairArray, TRUE, &uniqueIds);
+
+    fairNegative = ComputeFairPredicate(catalog, NIL(AbsVertexInfo_t), 
+					fairArray, FALSE, &uniqueIds);
+  }
+  else {
+    fairPositive = NIL(AbsVertexInfo_t);
+    fairNegative = NIL(AbsVertexInfo_t);
+  }
+
+  if (AbsOptionsReadNegateFormula(AbsVerificationInfoReadOptions(verInfo))) {
+    initialPolarity = TRUE;
+  }
+  else {
+    initialPolarity = FALSE;
+  }
+
+  /* Create the result */
+  result = array_alloc(AbsVertexInfo_t *, array_n(formulaArray));
+
+  arrayForEachItem(Ctlp_Formula_t *, formulaArray, i, formulaPtr) {
+    AbsVertexInfo_t *resultPtr;
+
+    /* Translate the formula */
+    resultPtr = TranslateCtlSubFormula(AbsVerificationInfoReadCatalog(verInfo),
+				       formulaPtr,      /* Formula */
+				       fairArray,       /* Fairness 
+							   constraints */
+				       fairPositive,    /* Predicate fair 
+							   with positive 
+							   polarity */
+				       fairNegative,    /* Predicate fair
+							   with negative
+							   polarity */
+				       initialPolarity, /* Initial polarity */
+				       &uniqueIds);     /* Unique id counter */
+
+    /* Negate the formula if needed */
+    if (AbsOptionsReadNegateFormula(AbsVerificationInfoReadOptions(verInfo))) {
+      AbsVertexInfo_t *newResult;
+
+      /* If the formula's top vertex is a negation, eliminate the redundancy */
+      if (AbsVertexReadType(resultPtr) == not_c) {
+	
+	newResult = AbsVertexReadLeftKid(resultPtr);
+	AbsVertexReadRefs(newResult)++;
+	AbsVertexFree(catalog, resultPtr, NIL(AbsVertexInfo_t));
+	
+	resultPtr =  newResult;
+      }
+      else {
+	/* Create the not vertex */
+	newResult = AbsVertexCatalogFindOrAdd(catalog, not_c, FALSE, 
+					      resultPtr,
+					      NIL(AbsVertexInfo_t), 0, 
+					      NIL(char), 
+					      NIL(char));
+	if (AbsVertexReadType(newResult) == false_c) {
+	  AbsVertexSetPolarity(newResult, FALSE);
+	  AbsVertexSetDepth(newResult, AbsVertexReadDepth(resultPtr) + 1);
+	  AbsVertexSetType(newResult, not_c);
+	  AbsVertexSetLeftKid(newResult, resultPtr);
+	  AbsVertexSetParent(resultPtr, newResult);
+	}
+	else {
+	  AbsVertexFree(catalog, resultPtr, NIL(AbsVertexInfo_t));
+	}
+	resultPtr = newResult;
+      }
+    } /* If the formula needs to be negated */
+
+    /* Set the constant bit */
+    AbsFormulaSetConstantBit(resultPtr);
+
+    array_insert(AbsVertexInfo_t *, result, i, resultPtr);
+  }
+
+  /* Clean up */
+  if (fairPositive != NIL(AbsVertexInfo_t)) {
+    AbsVertexFree(catalog, fairPositive, NIL(AbsVertexInfo_t));
+  }
+  if (fairNegative != NIL(AbsVertexInfo_t)) {
+    AbsVertexFree(catalog, fairNegative, NIL(AbsVertexInfo_t));
+  }
+
+#ifndef NDEBUG
+  {
+    AbsVertexInfo_t *operationGraph;
+    st_table *rootTable = st_init_table(st_ptrcmp, st_ptrhash);
+    arrayForEachItem(AbsVertexInfo_t *, result, i, operationGraph) {
+      st_insert(rootTable, (char *) operationGraph, NIL(char));
+    }
+    arrayForEachItem(AbsVertexInfo_t *, result, i, operationGraph) {
+      assert(AbsFormulaSanityCheck(operationGraph, rootTable));
+    }
+    st_free_table(rootTable);
+  }
+#endif
+
+  return result;
+} /* End of AbsCtlFormulaArrayTranslate */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Recursive formula to translate a formula to its operational graph]
+
+  Description [This function is just a case to call the specific translation
+  routines for the different types of sub-formulas]
+
+  SideEffects        []
+
+  SeeAlso [TranslateCtlId, TranslateCtlEG, TranslateCtlEGFair, TranslateCtlEU,
+  TranslateCtlEX, TranslateCtlNOT, TranslateCtlTHEN, TranslateCtlAND,
+  TranslateCtlOR]
+
+******************************************************************************/
+static AbsVertexInfo_t *
+TranslateCtlSubFormula(
+  AbsVertexCatalog_t *catalog,
+  Ctlp_Formula_t *formula,
+  array_t *fairArray,
+  AbsVertexInfo_t *fairPositive,
+  AbsVertexInfo_t *fairNegative,
+  int polarity,
+  int *uniqueIds)
+{
+  AbsVertexInfo_t *result;
+
+  result = NIL(AbsVertexInfo_t);
+
+  switch (Ctlp_FormulaReadType(formula)) {
+    case Ctlp_TRUE_c:
+    case Ctlp_FALSE_c: {
+      (void) fprintf(vis_stderr, "** abs error: Error in TranslateCtlSubFormula. ");
+      (void) fprintf(vis_stderr, "TRUE/FALSE constant found.\n");
+      result = NIL(AbsVertexInfo_t);
+      break;
+    }
+    case Ctlp_ID_c: {
+      result = TranslateCtlID(catalog, formula, polarity);
+      break;
+    }
+    case Ctlp_EG_c: {
+      if (fairArray == NIL(array_t)) {
+	result = TranslateCtlEG(catalog, formula, polarity, uniqueIds);
+      }
+      else {
+	result = TranslateCtlEGFair(catalog, formula, fairArray, fairPositive, 
+				    fairNegative, polarity, uniqueIds);
+      }
+      break;
+    }
+    case Ctlp_EU_c: {
+      result = TranslateCtlEU(catalog, formula, fairArray, fairPositive, 
+			      fairNegative, polarity, uniqueIds);
+      break;
+    }
+    case Ctlp_EX_c: {
+      result = TranslateCtlEX(catalog, formula, fairArray, fairPositive, 
+			      fairNegative, polarity, uniqueIds);
+      break;
+    }
+    case Ctlp_NOT_c: {
+      result = TranslateCtlNOT(catalog, formula, fairArray, fairPositive, 
+			       fairNegative, polarity, uniqueIds);
+      break;
+    }
+    case Ctlp_THEN_c:  {
+      result = TranslateCtlTHEN(catalog, formula, fairArray, fairPositive, 
+				fairNegative, polarity, uniqueIds);
+      break;
+    }
+    case Ctlp_EQ_c:
+    case Ctlp_XOR_c: {
+      /* Non-monotonic operators should have been replaced before
+       * reaching this point.
+       */
+      fail("Encountered unexpected type of CTL formula\n");
+      break;
+    }
+    case Ctlp_AND_c: {
+      result = TranslateCtlAND(catalog, formula, fairArray, fairPositive, 
+			       fairNegative, polarity, uniqueIds);
+      break;
+    }
+    case Ctlp_OR_c: {
+      result = TranslateCtlOR(catalog, formula, fairArray, fairPositive, 
+			      fairNegative, polarity, uniqueIds);
+      break;
+    }
+    default: fail("Encountered unknown type of CTL formula\n");
+  }
+
+  return result;
+} /* End of TranslateCtlSubFormula */
+
+/**Function********************************************************************
+
+  Synopsis [Computes the operational graph representation of the predicate
+  "fair"]
+
+  Description [Given a set of formulas f_1,...,f_n compute the predicate fair
+  which is computed as follows: fair(p) = nu(x).(p * Product(i=1,n)(EX[E[p U (x
+  * f_i)]])). The final graph will have in its top vertex the polarity given as
+  a parameter to the routine.]
+
+  SideEffects        []
+
+  SeeAlso            [AbsCtlFormulaArrayTranslate]
+
+******************************************************************************/
+static AbsVertexInfo_t *
+ComputeFairPredicate(
+  AbsVertexCatalog_t *catalog,
+  AbsVertexInfo_t *atomicPredicate,
+  array_t *fairArray,
+  int polarity,
+  int *uniqueIds)
+{
+  Ctlp_Formula_t *ctlPtr;
+  AbsVertexInfo_t *mainVarVertex;
+  AbsVertexInfo_t *mainVarNotVertex;
+  AbsVertexInfo_t *vertexPtr;
+  AbsVertexInfo_t *aux1;
+  AbsVertexInfo_t *aux2;
+  AbsVertexInfo_t *aux3;
+  array_t *conjunctions;
+  array_t *constraintArray;
+  int     mainVarId;
+  int     i;
+  
+  /* Obtain the representation of the fairness predicates */
+  constraintArray = array_alloc(AbsVertexInfo_t *, array_n(fairArray));
+  arrayForEachItem(Ctlp_Formula_t *, fairArray, i, ctlPtr) {
+    array_insert(AbsVertexInfo_t *, constraintArray, i, 
+		 TranslateCtlSubFormula(catalog, ctlPtr, NIL(array_t), 
+					NIL(AbsVertexInfo_t), 
+					NIL(AbsVertexInfo_t), polarity,  
+					uniqueIds));
+  }
+
+  /* Create the vertex representing the variable of the greatest fixed point */
+  mainVarId = (*uniqueIds)++;
+
+  aux1 = AbsVertexCatalogFindOrAdd(catalog, variable_c, !polarity, 
+				   NIL(AbsVertexInfo_t), 
+				   NIL(AbsVertexInfo_t),
+				   mainVarId, NIL(char), NIL(char));
+  if (AbsVertexReadType(aux1) == false_c) {
+    AbsVertexSetPolarity(aux1, !polarity);
+    AbsVertexSetDepth(aux1, 1);
+    AbsVertexSetType(aux1, variable_c);
+    AbsVertexSetVarId(aux1, mainVarId);
+  }
+  mainVarVertex = aux1;
+
+  mainVarNotVertex = AbsVertexCatalogFindOrAdd(catalog, not_c, polarity, aux1,
+					       NIL(AbsVertexInfo_t), 0, 
+					       NIL(char), NIL(char));
+  if (AbsVertexReadType(mainVarNotVertex) == false_c) {
+    AbsVertexSetPolarity(mainVarNotVertex, polarity);
+    AbsVertexSetDepth(mainVarNotVertex, 2);
+    AbsVertexSetType(mainVarNotVertex, not_c);
+    AbsVertexSetLeftKid(mainVarNotVertex, aux1);
+    AbsVertexSetParent(mainVarVertex, mainVarNotVertex);
+  }
+  else {
+    AbsVertexFree(catalog, aux1, NIL(AbsVertexInfo_t));
+  }
+
+  /* Create the predicates EX[E[f U z * f_i]] */
+  conjunctions = array_alloc(AbsVertexInfo_t *, array_n(fairArray));
+  arrayForEachItem(AbsVertexInfo_t *, constraintArray, i, vertexPtr) {
+    AbsVertexInfo_t *varVertex;
+    int variableId;
+
+    /* Create the conjunction between z and f_i */
+    AbsVertexReadRefs(mainVarNotVertex)++;
+    aux1 = AbsVertexCatalogFindOrAdd(catalog, and_c, polarity, vertexPtr, 
+				     mainVarNotVertex, 0, NIL(char), 
+				     NIL(char));
+    if (AbsVertexReadType(aux1) == false_c) {
+      AbsVertexSetPolarity(aux1, polarity);
+      if (AbsVertexReadDepth(vertexPtr) > 2) {
+	AbsVertexSetDepth(aux1, AbsVertexReadDepth(vertexPtr) + 1);
+      }
+      else {
+	AbsVertexSetDepth(aux1, 3);
+      }
+      AbsVertexSetType(aux1, and_c);
+      AbsVertexSetLeftKid(aux1, vertexPtr);
+      AbsVertexSetRightKid(aux1, mainVarNotVertex);
+      AbsVertexSetParent(vertexPtr, aux1);
+      AbsVertexSetParent(mainVarNotVertex, aux1);
+    }
+    else {
+      /* Cache hit */
+      AbsVertexFree(catalog, vertexPtr, NIL(AbsVertexInfo_t));
+      AbsVertexFree(catalog, mainVarNotVertex, NIL(AbsVertexInfo_t));
+    }
+
+    /* Create the vertex negating the previous conjunction */
+    aux2 = AbsVertexCatalogFindOrAdd(catalog, not_c, !polarity, aux1, 
+				     NIL(AbsVertexInfo_t), 0, NIL(char), 
+				     NIL(char));
+    if (AbsVertexReadType(aux2) == false_c) {
+      AbsVertexSetPolarity(aux2, !polarity);
+      AbsVertexSetDepth(aux2, AbsVertexReadDepth(aux1) + 1);
+      AbsVertexSetType(aux2, not_c);
+      AbsVertexSetLeftKid(aux2, aux1);
+      AbsVertexSetParent(aux1, aux2);
+    }
+    else {
+      /* Cache hit */
+      AbsVertexFree(catalog, aux1, NIL(AbsVertexInfo_t));
+    }
+
+    /* Create the variable of the fixed point in the EU sub-formula*/
+    variableId = (*uniqueIds)++;
+    aux1 = AbsVertexCatalogFindOrAdd(catalog, variable_c, polarity,
+				     NIL(AbsVertexInfo_t), 
+				     NIL(AbsVertexInfo_t), variableId, 
+				     NIL(char), NIL(char));
+    if (AbsVertexReadType(aux1) == false_c) {
+      AbsVertexSetPolarity(aux1, polarity);
+      AbsVertexSetDepth(aux1, 1);
+      AbsVertexSetType(aux1, variable_c);
+      AbsVertexSetVarId(aux1, variableId);
+    }
+    varVertex = aux1;
+
+    /* Create the vertex storing the preimage sub-formula */
+    aux3 = AbsVertexCatalogFindOrAdd(catalog, preImage_c, polarity,
+				     aux1, NIL(AbsVertexInfo_t),
+				     0, NIL(char), NIL(char));
+    if (AbsVertexReadType(aux3) == false_c) {
+      AbsVertexSetPolarity(aux3, polarity);
+      AbsVertexSetDepth(aux3, 2);
+      AbsVertexSetType(aux3, preImage_c);
+      AbsVertexSetLeftKid(aux3, aux1);
+      AbsVertexSetParent(aux1, aux3);
+    }
+    else {
+      /* Cache hit */
+      AbsVertexFree(catalog, aux1, NIL(AbsVertexInfo_t));
+    }
+  
+    if (atomicPredicate != NIL(AbsVertexInfo_t)) {
+      AbsVertexReadRefs(atomicPredicate)++;
+      /* Create the vertex representing the and */
+      aux1 = AbsVertexCatalogFindOrAdd(catalog, and_c, polarity,
+				       atomicPredicate, aux3, 0, NIL(char), 
+				       NIL(char));
+      if (AbsVertexReadType(aux1) == false_c) {
+	AbsVertexSetPolarity(aux1, polarity);
+	if (AbsVertexReadDepth(atomicPredicate) > 2) {
+	  AbsVertexSetDepth(aux1, AbsVertexReadDepth(atomicPredicate) + 1);
+	}
+	else {
+	  AbsVertexSetDepth(aux1, 3);
+	}
+	AbsVertexSetType(aux1, and_c);
+	AbsVertexSetLeftKid(aux1, atomicPredicate);
+	AbsVertexSetRightKid(aux1, aux3);
+	AbsVertexSetParent(atomicPredicate, aux1);
+	AbsVertexSetParent(aux3, aux1);
+      }
+      else {
+	/* Cache hit */
+	AbsVertexFree(catalog, aux3, NIL(AbsVertexInfo_t));
+	AbsVertexFree(catalog, atomicPredicate, NIL(AbsVertexInfo_t));
+      }
+    }
+    else {
+      aux1 = aux3;
+    }
+
+    /* Create the not vertex on top of the conjunction */
+    aux3 = AbsVertexCatalogFindOrAdd(catalog, not_c, !polarity, aux1, 
+				     NIL(AbsVertexInfo_t), 0, NIL(char), 
+				     NIL(char));
+    if (AbsVertexReadType(aux3) == false_c) {
+      AbsVertexSetPolarity(aux3, !polarity);
+      AbsVertexSetDepth(aux3, AbsVertexReadDepth(aux1) + 1);
+      AbsVertexSetType(aux3, not_c);
+      AbsVertexSetLeftKid(aux3, aux1);
+      AbsVertexSetParent(aux1, aux3);
+    }
+    else {
+      /* Cache hit */
+      AbsVertexFree(catalog, aux1, NIL(AbsVertexInfo_t));
+    }
+    
+    /* Vertex taking the conjunction */
+    aux1 = AbsVertexCatalogFindOrAdd(catalog, and_c, !polarity, aux2, aux3,
+				     0, NIL(char), NIL(char));
+    if (AbsVertexReadType(aux1) == false_c) {
+      AbsVertexSetPolarity(aux1, !polarity);
+      if (AbsVertexReadDepth(aux2) > AbsVertexReadDepth(aux3)) {
+	AbsVertexSetDepth(aux1, AbsVertexReadDepth(aux2) + 1);
+      }
+      else {
+	AbsVertexSetDepth(aux1, AbsVertexReadDepth(aux3) + 1);
+      }
+      AbsVertexSetType(aux1, and_c);
+      AbsVertexSetLeftKid(aux1, aux2);
+      AbsVertexSetRightKid(aux1, aux3);
+      AbsVertexSetParent(aux3, aux1);
+      AbsVertexSetParent(aux2, aux1);
+    }
+    else {
+      AbsVertexFree(catalog, aux3, NIL(AbsVertexInfo_t));
+      AbsVertexFree(catalog, aux2, NIL(AbsVertexInfo_t));
+    }
+    
+    /* negation of the conjunction */
+    aux2 = AbsVertexCatalogFindOrAdd(catalog, not_c, polarity, aux1,
+				     NIL(AbsVertexInfo_t), 0, NIL(char), 
+				     NIL(char));
+    if (AbsVertexReadType(aux2) == false_c) {
+      AbsVertexSetPolarity(aux2, polarity);
+      AbsVertexSetDepth(aux2, AbsVertexReadDepth(aux1) + 1);
+      AbsVertexSetType(aux2, not_c);
+      AbsVertexSetLeftKid(aux2, aux1);
+      AbsVertexSetParent(aux1, aux2);
+    }
+    else {
+      AbsVertexFree(catalog, aux1, NIL(AbsVertexInfo_t));
+    }
+  
+    /* Create the lfp vertex for the EU operator */
+    aux1 = AbsVertexCatalogFindOrAdd(catalog, fixedPoint_c, polarity, aux2,
+				     NIL(AbsVertexInfo_t), 0, NIL(char),
+				     NIL(char));
+    if (AbsVertexReadType(aux1) == false_c) {
+      AbsVertexSetPolarity(aux1, polarity);
+      AbsVertexSetDepth(aux1, AbsVertexReadDepth(aux2) + 1);
+      AbsVertexSetType(aux1, fixedPoint_c);
+      AbsVertexSetLeftKid(aux1, aux2);
+      AbsVertexSetFpVar(aux1, varVertex);
+      AbsVertexSetUseExtraCareSet(aux1, TRUE);
+      AbsVertexSetParent(aux2, aux1);
+    }
+    else {
+      AbsVertexFree(catalog, aux2, NIL(AbsVertexInfo_t));
+    }
+    
+    /* Create the final EX vertex on top of the EU */
+    aux2 = AbsVertexCatalogFindOrAdd(catalog, preImage_c, polarity,
+				     aux1, NIL(AbsVertexInfo_t), 0, NIL(char),
+				     NIL(char));
+    if (AbsVertexReadType(aux2) == false_c) {
+      AbsVertexSetPolarity(aux2, polarity);
+      AbsVertexSetDepth(aux2, AbsVertexReadDepth(aux1) + 1);
+      AbsVertexSetType(aux2, preImage_c);
+      AbsVertexSetLeftKid(aux2, aux1);
+      AbsVertexSetParent(aux1, aux2);
+    }
+    else {
+      AbsVertexFree(catalog, aux1, NIL(AbsVertexInfo_t));
+    }
+
+    array_insert(AbsVertexInfo_t *, conjunctions, i, aux2);
+  } /* End of the loop iterating over the fairness constraints */
+  AbsVertexReadRefs(mainVarNotVertex)--;
+
+  /* Create the chain of ands for the conjunctions */
+  aux1 = CreateConjunctionChain(catalog, conjunctions, polarity);
+
+  /* Create the and with the atomic predicate if required */
+  if (atomicPredicate != NIL(AbsVertexInfo_t)) {
+    aux2 = AbsVertexCatalogFindOrAdd(catalog, and_c, polarity, atomicPredicate, 
+				     aux1, 0, NIL(char), NIL(char));
+    if (AbsVertexReadType(aux2) == false_c) {
+      AbsVertexSetPolarity(aux2, polarity);
+      if (AbsVertexReadDepth(aux1) > AbsVertexReadDepth(atomicPredicate)) {
+	AbsVertexSetDepth(aux2, AbsVertexReadDepth(aux1) + 1);
+      }
+      else {
+	AbsVertexSetDepth(aux2, AbsVertexReadDepth(atomicPredicate) + 1);
+      }
+      AbsVertexSetType(aux2, and_c);
+      AbsVertexSetLeftKid(aux2, atomicPredicate);
+      AbsVertexSetRightKid(aux2, aux1);
+      AbsVertexSetParent(atomicPredicate, aux2);
+      AbsVertexSetParent(aux1, aux2);
+    }
+    else {
+      AbsVertexFree(catalog, aux1, NIL(AbsVertexInfo_t));
+      AbsVertexFree(catalog, atomicPredicate, NIL(AbsVertexInfo_t));
+    }
+  }
+  else {
+    aux2 = aux1;
+  }
+
+  /* Create the not vertex on top of the conjunction */
+  aux1 = AbsVertexCatalogFindOrAdd(catalog, not_c, !polarity, aux2, 
+				   NIL(AbsVertexInfo_t), 0, NIL(char), 
+				   NIL(char));
+  if (AbsVertexReadType(aux1) == false_c) {
+    AbsVertexSetPolarity(aux1, !polarity);
+    AbsVertexSetDepth(aux1, AbsVertexReadDepth(aux2) + 1);
+    AbsVertexSetType(aux1, not_c);
+    AbsVertexSetLeftKid(aux1, aux2);
+    AbsVertexSetParent(aux2, aux1);
+  }
+  else {
+    AbsVertexFree(catalog, aux2, NIL(AbsVertexInfo_t));
+  }
+  
+  /* Create the top most fixed point vertex */
+  aux2 = AbsVertexCatalogFindOrAdd(catalog, fixedPoint_c, !polarity, aux1,
+				   NIL(AbsVertexInfo_t), mainVarId,
+				   NIL(char), NIL(char));
+  if (AbsVertexReadType(aux2) == false_c) {
+    AbsVertexSetPolarity(aux2, !polarity);
+    AbsVertexSetDepth(aux2, AbsVertexReadDepth(aux1) + 1);
+    AbsVertexSetType(aux2, fixedPoint_c);
+    AbsVertexSetVarId(aux2, mainVarId);
+    AbsVertexSetLeftKid(aux2, aux1);
+    AbsVertexSetFpVar(aux2, mainVarVertex);
+    AbsVertexSetUseExtraCareSet(aux2, FALSE);
+    AbsVertexSetParent(aux1, aux2);
+  }
+  else {
+    AbsVertexSetUseExtraCareSet(aux2, FALSE);
+    AbsVertexFree(catalog, aux1, NIL(AbsVertexInfo_t));
+  }
+  
+  /* Create the top most vertex */
+  aux1 = AbsVertexCatalogFindOrAdd(catalog, not_c, polarity, aux2, 
+				   NIL(AbsVertexInfo_t), 0, NIL(char), 
+				   NIL(char));
+  if (AbsVertexReadType(aux1) == false_c) {
+    AbsVertexSetPolarity(aux1, polarity);
+    AbsVertexSetDepth(aux1, AbsVertexReadDepth(aux2) + 1);
+    AbsVertexSetType(aux1, not_c);
+    AbsVertexSetLeftKid(aux1, aux2);
+    AbsVertexSetParent(aux2, aux1);
+  }
+  else {
+    AbsVertexFree(catalog, aux2, NIL(AbsVertexInfo_t));
+  }
+  
+  /* Clean up */
+  array_free(constraintArray);
+  arrayForEachItem(AbsVertexInfo_t *, conjunctions, i, vertexPtr) {
+    AbsVertexFree(catalog, vertexPtr, NIL(AbsVertexInfo_t));
+  }
+  array_free(conjunctions);
+
+  return aux1;
+} /* End of ComputeFairPredicate */
+
+/**Function********************************************************************
+
+  Synopsis [Computes the operational grarph representation of an atomic
+  predicate]
+
+  SideEffects        []
+
+  SeeAlso            [TranslateCtlSubFormula]
+
+******************************************************************************/
+static AbsVertexInfo_t *
+TranslateCtlID(
+  AbsVertexCatalog_t *catalog,
+  Ctlp_Formula_t *formula,	       
+  int polarity)
+{
+  AbsVertexInfo_t *result;
+
+  result = AbsVertexCatalogFindOrAdd(catalog,
+				     identifier_c,
+				     polarity,
+				     NIL(AbsVertexInfo_t),
+				     NIL(AbsVertexInfo_t),
+				     0,
+				     Ctlp_FormulaReadVariableName(formula),
+				     Ctlp_FormulaReadValueName(formula));
+  if (AbsVertexReadType(result) == false_c) {
+    AbsVertexSetPolarity(result, polarity);
+    AbsVertexSetDepth(result, 1);
+    AbsVertexSetType(result, identifier_c);
+    AbsVertexSetName(result, 
+		     util_strsav(Ctlp_FormulaReadVariableName(formula)));
+    AbsVertexSetValue(result,
+		      util_strsav(Ctlp_FormulaReadValueName(formula)));
+  }
+  
+  return result;
+} /* End of TranslateCtlID */
+
+/**Function********************************************************************
+
+  Synopsis [Computes the operational graph representation of a formula of the
+  form E(pUq)]
+
+  SideEffects        []
+
+  SeeAlso            [TranslateCtlSubFormula]
+
+******************************************************************************/
+static AbsVertexInfo_t *
+TranslateCtlEU(
+  AbsVertexCatalog_t *catalog,
+  Ctlp_Formula_t *formula,
+  array_t *fairArray,
+  AbsVertexInfo_t *fairPositive,
+  AbsVertexInfo_t *fairNegative,
+  int polarity,
+  int *uniqueIds)
+{
+  AbsVertexInfo_t *result;
+  AbsVertexInfo_t *leftResult;
+  AbsVertexInfo_t *rightResult;
+  AbsVertexInfo_t *aux1;
+  AbsVertexInfo_t *aux2;
+  AbsVertexInfo_t *aux3;
+  AbsVertexInfo_t *varVertex;
+  int variableId;
+  
+  /* Allocate a unique id for the fixed point */
+  variableId = (*uniqueIds)++;
+  
+  /* Create the vertex storing the fixed point variable */
+  aux1 = AbsVertexCatalogFindOrAdd(catalog, variable_c, polarity,
+				   NIL(AbsVertexInfo_t), 
+				   NIL(AbsVertexInfo_t), variableId, 
+				   NIL(char), NIL(char));
+  if (AbsVertexReadType(aux1) == false_c) {
+    AbsVertexSetPolarity(aux1, polarity);
+    AbsVertexSetDepth(aux1, 1);
+    AbsVertexSetType(aux1, variable_c);
+    AbsVertexSetVarId(aux1, variableId);
+  }
+  varVertex = aux1;
+  
+  /* Create the vertex storing the preimage sub-formula */
+  aux2 = AbsVertexCatalogFindOrAdd(catalog, preImage_c, polarity,
+				   aux1, NIL(AbsVertexInfo_t),
+				   0, NIL(char), NIL(char));
+  if (AbsVertexReadType(aux2) == false_c) {
+    AbsVertexSetPolarity(aux2, polarity);
+    AbsVertexSetDepth(aux2, 2);
+    AbsVertexSetType(aux2, preImage_c);
+    AbsVertexSetLeftKid(aux2, aux1);
+    AbsVertexSetParent(aux1, aux2);
+  }
+  else {
+    /* Cache hit */
+    AbsVertexFree(catalog, aux1, NIL(AbsVertexInfo_t));
+  }
+  
+  if (Ctlp_FormulaReadType(Ctlp_FormulaReadLeftChild(formula)) != Ctlp_TRUE_c) {
+    /* Compute the value of the sub-formula */
+    leftResult = TranslateCtlSubFormula(catalog,
+					Ctlp_FormulaReadLeftChild(formula),
+					fairArray, fairPositive, fairNegative,
+					polarity, uniqueIds);
+    
+    /* Create the vertex representing the and */
+    aux1 = AbsVertexCatalogFindOrAdd(catalog, and_c, polarity, leftResult, aux2,
+				     0, NIL(char), 
+				     NIL(char));
+    if (AbsVertexReadType(aux1) == false_c) {
+      AbsVertexSetPolarity(aux1, polarity);
+      if (AbsVertexReadDepth(leftResult) > 2) {
+	AbsVertexSetDepth(aux1, AbsVertexReadDepth(leftResult) + 1);
+      }
+      else {
+	AbsVertexSetDepth(aux1, 3);
+      }
+      AbsVertexSetType(aux1, and_c);
+      AbsVertexSetLeftKid(aux1, leftResult);
+      AbsVertexSetRightKid(aux1, aux2);
+      AbsVertexSetParent(leftResult, aux1);
+      AbsVertexSetParent(aux2, aux1);
+    }
+    else {
+      /* Cache hit */
+      AbsVertexFree(catalog, aux2, NIL(AbsVertexInfo_t));
+      AbsVertexFree(catalog, leftResult, NIL(AbsVertexInfo_t));
+    }
+  } /* if type is TRUE */
+  else {
+    aux1 = aux2;
+  }
+  
+  /* Create the not vertex on top of the conjunction */
+  aux2 = AbsVertexCatalogFindOrAdd(catalog, not_c, !polarity, aux1, 
+				   NIL(AbsVertexInfo_t), 0, NIL(char), 
+				   NIL(char));
+  if (AbsVertexReadType(aux2) == false_c) {
+    AbsVertexSetPolarity(aux2, !polarity);
+    AbsVertexSetDepth(aux2, AbsVertexReadDepth(aux1) + 1);
+    AbsVertexSetType(aux2, not_c);
+    AbsVertexSetLeftKid(aux2, aux1);
+    AbsVertexSetParent(aux1, aux2);
+  }
+  else {
+    /* Cache hit */
+    AbsVertexFree(catalog, aux1, NIL(AbsVertexInfo_t));
+  }
+  
+  /* Evaluate the right operand of the EU */
+  rightResult= TranslateCtlSubFormula(catalog,
+				      Ctlp_FormulaReadRightChild(formula),
+				      fairArray, fairPositive, fairNegative,
+				      polarity, uniqueIds);
+  
+  /* check if there are fairness constraints */
+  if (fairPositive != NIL(AbsVertexInfo_t)) {
+    AbsVertexInfo_t *fairness;
+    AbsVertexInfo_t *conjunction;
+
+    /* The negative polarity version of the fairness must be present as well */
+    assert(fairNegative != NIL(AbsVertexInfo_t));
+
+    /* Select the apropriate representation of the fairness constraint */
+    if (polarity) {
+      fairness = fairPositive;
+    }
+    else {
+      fairness = fairNegative;
+    }
+    AbsVertexReadRefs(fairness)++;
+
+    conjunction = AbsVertexCatalogFindOrAdd(catalog, and_c, polarity,
+					    rightResult, fairness, 0, NIL(char),
+					    NIL(char));
+
+    if (AbsVertexReadType(conjunction) == false_c) {
+      int leftDepth;
+      int rightDepth;
+
+      leftDepth = AbsVertexReadDepth(rightResult);
+      rightDepth = AbsVertexReadDepth(fairness);
+
+      AbsVertexSetPolarity(conjunction, polarity);
+      if (leftDepth > rightDepth) {
+	AbsVertexSetDepth(conjunction, leftDepth + 1);
+      }
+      else {
+	AbsVertexSetDepth(conjunction, rightDepth + 1);
+      }
+      AbsVertexSetType(conjunction, and_c);
+      AbsVertexSetLeftKid(conjunction, rightResult);
+      AbsVertexSetRightKid(conjunction, fairness);
+      AbsVertexSetParent(rightResult, conjunction);
+      AbsVertexSetParent(fairness, conjunction);
+    }
+    else {
+      AbsVertexFree(catalog, rightResult, NIL(AbsVertexInfo_t));
+      AbsVertexFree(catalog, fairness, NIL(AbsVertexInfo_t));
+    }
+    rightResult = conjunction;
+  }
+
+  /* If the sub-formula's top vertex is a negation, eliminate the redundancy */
+  if (AbsVertexReadType(rightResult) == not_c) {
+    AbsVertexInfo_t *newResult;
+
+
+    newResult = AbsVertexReadLeftKid(rightResult);
+    AbsVertexReadRefs(newResult)++;
+    AbsVertexFree(catalog, rightResult, NIL(AbsVertexInfo_t));
+    aux1 = newResult;
+  }
+  else {
+    /* Vertex negating second operand */
+    aux1 = AbsVertexCatalogFindOrAdd(catalog, not_c, !polarity, rightResult, 
+				     NIL(AbsVertexInfo_t), 0, NIL(char), 
+				     NIL(char));
+    if (AbsVertexReadType(aux1) == false_c) {
+      AbsVertexSetPolarity(aux1, !polarity);
+      AbsVertexSetDepth(aux1, AbsVertexReadDepth(rightResult) + 1);
+      AbsVertexSetType(aux1, not_c);
+      AbsVertexSetLeftKid(aux1, rightResult);
+      AbsVertexSetParent(rightResult, aux1);
+    }
+    else {
+      AbsVertexFree(catalog, rightResult, NIL(AbsVertexInfo_t));
+    }
+  }
+  
+  /* Vertex taking the conjunction */
+  aux3 = AbsVertexCatalogFindOrAdd(catalog, and_c, !polarity, aux1, aux2,
+				   0, NIL(char), NIL(char));
+  if (AbsVertexReadType(aux3) == false_c) {
+    AbsVertexSetPolarity(aux3, !polarity);
+    if (AbsVertexReadDepth(aux1) > AbsVertexReadDepth(aux2)) {
+      AbsVertexSetDepth(aux3, AbsVertexReadDepth(aux1) + 1);
+    }
+    else {
+      AbsVertexSetDepth(aux3, AbsVertexReadDepth(aux2) + 1);
+    }
+    AbsVertexSetType(aux3, and_c);
+    AbsVertexSetLeftKid(aux3, aux1);
+    AbsVertexSetRightKid(aux3, aux2);
+    AbsVertexSetParent(aux1, aux3);
+    AbsVertexSetParent(aux2, aux3);
+  }
+  else {
+    AbsVertexFree(catalog, aux1, NIL(AbsVertexInfo_t));
+    AbsVertexFree(catalog, aux2, NIL(AbsVertexInfo_t));
+  }
+  
+  /* negation of the conjunction */
+  aux1 = AbsVertexCatalogFindOrAdd(catalog, not_c, polarity, aux3,
+				   NIL(AbsVertexInfo_t), 0, NIL(char), 
+				   NIL(char));
+  if (AbsVertexReadType(aux1) == false_c) {
+    AbsVertexSetPolarity(aux1, polarity);
+    AbsVertexSetDepth(aux1, AbsVertexReadDepth(aux3) + 1);
+    AbsVertexSetType(aux1, not_c);
+    AbsVertexSetLeftKid(aux1, aux3);
+    AbsVertexSetParent(aux3, aux1);
+  }
+  else {
+    AbsVertexFree(catalog, aux3, NIL(AbsVertexInfo_t));
+  }
+  
+  /* Top vertex fixed point operator */
+  result = AbsVertexCatalogFindOrAdd(catalog, fixedPoint_c, polarity, aux1,
+				     NIL(AbsVertexInfo_t), 0, NIL(char), 
+				     NIL(char));
+  if (AbsVertexReadType(result) == false_c) {
+    AbsVertexSetPolarity(result, polarity);
+    AbsVertexSetDepth(result, AbsVertexReadDepth(aux1) + 1);
+    AbsVertexSetType(result, fixedPoint_c);
+    AbsVertexSetLeftKid(result, aux1);
+    AbsVertexSetFpVar(result, varVertex);
+    AbsVertexSetUseExtraCareSet(result, TRUE);
+    AbsVertexSetParent(aux1, result);
+  }
+  else {
+    AbsVertexFree(catalog, aux1, NIL(AbsVertexInfo_t));
+  }
+  
+  return result;
+} /* End of TranslateCtlEU */
+
+/**Function********************************************************************
+
+  Synopsis [Computes the operational graph representation of a formula of the
+  form EG(p)]
+
+  SideEffects        []
+
+  SeeAlso            [TranslateCtlSubFormula]
+
+******************************************************************************/
+static AbsVertexInfo_t *
+TranslateCtlEG(
+  AbsVertexCatalog_t *catalog,
+  Ctlp_Formula_t *formula,
+  int polarity,
+  int *uniqueIds)
+{
+  AbsVertexInfo_t *result;
+  AbsVertexInfo_t *varVertex;
+  AbsVertexInfo_t *aux1;
+  AbsVertexInfo_t *aux2;
+  AbsVertexInfo_t *childResult;
+  int variableId;
+  
+  /* Allocate a unique id for the fixed point */
+  variableId = (*uniqueIds)++;
+  
+  /* Create the vertex storing the fixed point variable */
+  aux1 = AbsVertexCatalogFindOrAdd(catalog, variable_c, !polarity,
+				   NIL(AbsVertexInfo_t), 
+				   NIL(AbsVertexInfo_t),
+				   variableId, NIL(char), NIL(char));
+  if (AbsVertexReadType(aux1) == false_c) {
+    AbsVertexSetPolarity(aux1, !polarity);
+    AbsVertexSetDepth(aux1, 1);
+    AbsVertexSetType(aux1, variable_c);
+    AbsVertexSetVarId(aux1, variableId);
+  }
+  varVertex = aux1;
+  
+  /* Create the vertex to negate the variable of the fixed point */
+  aux2 = AbsVertexCatalogFindOrAdd(catalog, not_c, polarity, aux1, 
+				   NIL(AbsVertexInfo_t), 0, NIL(char), 
+				   NIL(char));
+  if (AbsVertexReadType(aux2) == false_c) {
+    AbsVertexSetPolarity(aux2, polarity);
+    AbsVertexSetDepth(aux2, 2);
+    AbsVertexSetType(aux2, not_c);
+    AbsVertexSetLeftKid(aux2, aux1);
+    AbsVertexSetParent(aux1, aux2);
+  }
+  else {
+    AbsVertexFree(catalog, aux1, NIL(AbsVertexInfo_t));
+  }
+
+  /* Create the vertex storing the preimage sub-formula */
+  aux1 = AbsVertexCatalogFindOrAdd(catalog, preImage_c, polarity,
+				   aux1, NIL(AbsVertexInfo_t),
+				   0, NIL(char), NIL(char));
+  if (AbsVertexReadType(aux1) == false_c) {
+    AbsVertexSetPolarity(aux1, polarity);
+    AbsVertexSetDepth(aux1, 3);
+    AbsVertexSetType(aux1, preImage_c);
+    AbsVertexSetLeftKid(aux1, aux2);
+    AbsVertexSetParent(aux2, aux1);
+  }
+  else {
+    AbsVertexFree(catalog, aux1, NIL(AbsVertexInfo_t));
+  }
+  
+  if (Ctlp_FormulaReadType(Ctlp_FormulaReadLeftChild(formula)) != Ctlp_TRUE_c) {
+    /* Create the vertex representing the sub-formula of EG */
+    childResult = TranslateCtlSubFormula(catalog, 
+					 Ctlp_FormulaReadLeftChild(formula),
+					 NIL(array_t), NIL(AbsVertexInfo_t), 
+					 NIL(AbsVertexInfo_t), polarity, 
+					 uniqueIds);
+    
+    /* Create the vertex representing the and */
+    aux2 = AbsVertexCatalogFindOrAdd(catalog, and_c, polarity, childResult, 
+				     aux1, 0, NIL(char), 
+				     NIL(char));
+    if (AbsVertexReadType(aux2) == false_c) {
+      AbsVertexSetPolarity(aux2, polarity);
+      if (AbsVertexReadDepth(childResult) > 2) {
+	AbsVertexSetDepth(aux2, AbsVertexReadDepth(childResult) + 1);
+      }
+      else {
+	AbsVertexSetDepth(aux2, 4);
+      }
+      AbsVertexSetType(aux2, and_c);
+      AbsVertexSetLeftKid(aux2, childResult);
+      AbsVertexSetRightKid(aux2, aux1);
+      AbsVertexSetParent(childResult, aux2);
+      AbsVertexSetParent(aux1, aux2);
+    }
+    else {
+      AbsVertexFree(catalog, aux1, NIL(AbsVertexInfo_t));
+      AbsVertexFree(catalog, childResult, NIL(AbsVertexInfo_t));
+    }
+  }
+  else {
+    aux2 = aux1;
+  }
+  
+  /* Create the not vertex on top of the conjunction */
+  aux1 = AbsVertexCatalogFindOrAdd(catalog, not_c, !polarity, aux2, 
+				   NIL(AbsVertexInfo_t), 0, NIL(char), 
+				   NIL(char));
+  if (AbsVertexReadType(aux1) == false_c) {
+    AbsVertexSetPolarity(aux1, !polarity);
+    AbsVertexSetDepth(aux1, AbsVertexReadDepth(aux2) + 1);
+    AbsVertexSetType(aux1, not_c);
+    AbsVertexSetLeftKid(aux1, aux2);
+    AbsVertexSetParent(aux2, aux1);
+  }
+  else {
+    AbsVertexFree(catalog, aux2, NIL(AbsVertexInfo_t));
+  }
+  
+  /* Create the fixedpoint_c vertex */
+  aux2 = AbsVertexCatalogFindOrAdd(catalog, fixedPoint_c, !polarity, aux1,
+				   NIL(AbsVertexInfo_t), variableId,
+				   NIL(char), NIL(char));
+  if (AbsVertexReadType(aux2) == false_c) {
+    AbsVertexSetPolarity(aux2, !polarity);
+    AbsVertexSetDepth(aux2, AbsVertexReadDepth(aux1) + 1);
+    AbsVertexSetType(aux2, fixedPoint_c);
+    AbsVertexSetVarId(aux2, variableId);
+    AbsVertexSetLeftKid(aux2, aux1);
+    AbsVertexSetFpVar(aux2, varVertex);
+    AbsVertexSetUseExtraCareSet(aux2, FALSE);
+    AbsVertexSetParent(aux1, aux2);
+  }
+  else {
+    AbsVertexSetUseExtraCareSet(aux2, FALSE);
+    AbsVertexFree(catalog, aux1, NIL(AbsVertexInfo_t));
+  }
+  
+  /* Create the top most not vertex  */
+  result = AbsVertexCatalogFindOrAdd(catalog, not_c, polarity, aux2, 
+				     NIL(AbsVertexInfo_t), 0, NIL(char), 
+				     NIL(char));
+  if (AbsVertexReadType(result) == false_c) {
+    AbsVertexSetPolarity(result, polarity);
+    AbsVertexSetDepth(result, AbsVertexReadDepth(aux2) + 1);
+    AbsVertexSetType(result, not_c);
+    AbsVertexSetLeftKid(result, aux2);
+    AbsVertexSetParent(aux2, result);
+  }
+  else {
+    AbsVertexFree(catalog, aux2, NIL(AbsVertexInfo_t));
+  }
+  
+  return result;
+} /* End of TranslateCtlEG */
+
+/**Function********************************************************************
+
+  Synopsis [Computes the operational graph representation of a predicate of the
+  form EGfair(f)]
+
+  SideEffects        []
+
+  SeeAlso            [TranslateCtlSubFormula]
+
+******************************************************************************/
+static AbsVertexInfo_t *
+TranslateCtlEGFair(
+  AbsVertexCatalog_t *catalog,
+  Ctlp_Formula_t *formula,
+  array_t *fairArray,
+  AbsVertexInfo_t *fairPositive,
+  AbsVertexInfo_t *fairNegative,
+  int polarity,
+  int *uniqueIds)
+{
+  AbsVertexInfo_t *result;
+  AbsVertexInfo_t *childResult;
+
+  if (Ctlp_FormulaReadType(Ctlp_FormulaReadLeftChild(formula)) == Ctlp_TRUE_c) {
+    if (polarity) {
+      result = fairPositive;
+      AbsVertexReadRefs(fairPositive)++;
+    }
+    else {
+      result = fairNegative;
+      AbsVertexReadRefs(fairNegative)++;
+    }
+  }
+  else {
+    childResult = TranslateCtlSubFormula(catalog,
+					 Ctlp_FormulaReadLeftChild(formula),
+					 fairArray, fairPositive, fairNegative,
+					 polarity, uniqueIds);
+
+    result = ComputeFairPredicate(catalog, childResult, fairArray, polarity,
+				  uniqueIds);
+  }
+
+  return result;
+} /* End of TranslateCtlEGFair */
+
+/**Function********************************************************************
+
+  Synopsis [Computes the operational graph representation of the predicate
+  EX(p)]
+
+  SideEffects        []
+
+  SeeAlso            [TranslateCtlSubFormula]
+
+******************************************************************************/
+static AbsVertexInfo_t *
+TranslateCtlEX(
+  AbsVertexCatalog_t *catalog,
+  Ctlp_Formula_t *formula,
+  array_t *fairArray,
+  AbsVertexInfo_t *fairPositive,
+  AbsVertexInfo_t *fairNegative,
+  int polarity,
+  int *uniqueIds)
+{
+  AbsVertexInfo_t *result;
+  AbsVertexInfo_t *childResult;
+  
+  /* Translate the sub-formula regardless */
+  childResult = TranslateCtlSubFormula(catalog,
+				       Ctlp_FormulaReadLeftChild(formula),
+				       fairArray, fairPositive, fairNegative,
+				       polarity, uniqueIds);
+  
+  /* check if there are fairness constraints */
+  if (fairPositive != NIL(AbsVertexInfo_t)) {
+    AbsVertexInfo_t *fairness;
+    AbsVertexInfo_t *conjunction;
+
+    /* The negative polarity version of the fairness must be present as well */
+    assert(fairNegative != NIL(AbsVertexInfo_t));
+
+    /* Select the apropriate representation of the fairness constraint */
+    if (polarity) {
+      fairness = fairPositive;
+    }
+    else {
+      fairness = fairNegative;
+    }
+    AbsVertexReadRefs(fairness)++;
+
+    conjunction = AbsVertexCatalogFindOrAdd(catalog, and_c, polarity,
+					    childResult, fairness, 0, NIL(char),
+					    NIL(char));
+
+    if (AbsVertexReadType(conjunction) == false_c) {
+      int leftDepth;
+      int rightDepth;
+
+      leftDepth = AbsVertexReadDepth(childResult);
+      rightDepth = AbsVertexReadDepth(fairness);
+
+      AbsVertexSetPolarity(conjunction, polarity);
+      if (leftDepth > rightDepth) {
+	AbsVertexSetDepth(conjunction, leftDepth + 1);
+      }
+      else {
+	AbsVertexSetDepth(conjunction, rightDepth + 1);
+      }
+      AbsVertexSetType(conjunction, and_c);
+      AbsVertexSetLeftKid(conjunction, childResult);
+      AbsVertexSetRightKid(conjunction, fairness);
+      AbsVertexSetParent(childResult, conjunction);
+      AbsVertexSetParent(fairness, conjunction);
+    }
+    else {
+      AbsVertexFree(catalog, childResult, NIL(AbsVertexInfo_t));
+      AbsVertexFree(catalog, fairness, NIL(AbsVertexInfo_t));
+    }
+    childResult = conjunction;
+  }
+
+  /* Create the preImage vertex */
+  result = AbsVertexCatalogFindOrAdd(catalog, preImage_c, polarity, 
+				     childResult, NIL(AbsVertexInfo_t), 0, 
+				     NIL(char), NIL(char));
+  if (AbsVertexReadType(result) == false_c) {
+    AbsVertexSetPolarity(result, polarity);
+    AbsVertexSetDepth(result, AbsVertexReadDepth(childResult) + 1);
+    AbsVertexSetType(result, preImage_c);
+    AbsVertexSetLeftKid(result, childResult);
+    AbsVertexSetParent(childResult, result);
+  }
+  else {
+    AbsVertexFree(catalog, childResult, NIL(AbsVertexInfo_t));
+  }
+							   
+  return result;
+} /* End of TranslateCtlEX */
+
+/**Function********************************************************************
+
+  Synopsis [Computes the operational graph representation of the predicate
+  NOT(p)]
+
+  SideEffects        []
+
+  SeeAlso            [TranslateCtlSubFormula]
+
+******************************************************************************/
+static AbsVertexInfo_t *
+TranslateCtlNOT(
+  AbsVertexCatalog_t *catalog,
+  Ctlp_Formula_t *formula,
+  array_t *fairArray,
+  AbsVertexInfo_t *fairPositive,
+  AbsVertexInfo_t *fairNegative,
+  int polarity,
+  int *uniqueIds)
+{
+  AbsVertexInfo_t *result;
+  AbsVertexInfo_t *childResult;
+  
+  childResult = TranslateCtlSubFormula(catalog,
+				       Ctlp_FormulaReadLeftChild(formula),
+				       fairArray, fairPositive, fairNegative,
+				       !polarity, uniqueIds);
+  
+  /* If the sub-formula's top vertex is a negation, eliminate the redundancy */
+  if (AbsVertexReadType(childResult) == not_c) {
+    AbsVertexInfo_t *newResult;
+
+    newResult = AbsVertexReadLeftKid(childResult);
+    AbsVertexReadRefs(newResult)++;
+    AbsVertexFree(catalog, childResult, NIL(AbsVertexInfo_t));
+    
+    return newResult;
+  }
+
+  /* Create the not vertex */
+  result = AbsVertexCatalogFindOrAdd(catalog, not_c, polarity, childResult,
+				     NIL(AbsVertexInfo_t), 0, NIL(char), 
+				     NIL(char));
+  if (AbsVertexReadType(result) == false_c) {
+    AbsVertexSetPolarity(result, polarity);
+    AbsVertexSetDepth(result, AbsVertexReadDepth(childResult) + 1);
+    AbsVertexSetType(result, not_c);
+    AbsVertexSetLeftKid(result, childResult);
+    AbsVertexSetParent(childResult, result);
+  }
+  else {
+    AbsVertexFree(catalog, childResult, NIL(AbsVertexInfo_t));
+  }
+  
+  return result;
+} /* End of TranslateCtlNOT */
+
+/**Function********************************************************************
+
+  Synopsis [Computes the operational graph representation of the predicate
+  of the form p -> q]
+
+  SideEffects        []
+
+  SeeAlso            [TranslateCtlSubFormula]
+
+******************************************************************************/
+static AbsVertexInfo_t *
+TranslateCtlTHEN(
+  AbsVertexCatalog_t *catalog,
+  Ctlp_Formula_t *formula,
+  array_t *fairArray,
+  AbsVertexInfo_t *fairPositive,
+  AbsVertexInfo_t *fairNegative,
+  int polarity,
+  int *uniqueIds)
+{
+  AbsVertexInfo_t *result;
+  AbsVertexInfo_t *leftResult, *rightResult;
+  AbsVertexInfo_t *aux1;
+  AbsVertexInfo_t *aux2;
+  
+  leftResult = TranslateCtlSubFormula(catalog,
+				      Ctlp_FormulaReadLeftChild(formula),
+				      fairArray, fairPositive, fairNegative,
+				      !polarity, uniqueIds);
+  rightResult= TranslateCtlSubFormula(catalog,
+				      Ctlp_FormulaReadRightChild(formula),
+				      fairArray, fairPositive, fairNegative,
+				      polarity, uniqueIds);
+  
+  /* If the sub-formula's top vertex is a negation, eliminate the redundancy */
+  if (AbsVertexReadType(rightResult) == not_c) {
+    AbsVertexInfo_t *newResult;
+
+    newResult = AbsVertexReadLeftKid(rightResult);
+    AbsVertexReadRefs(newResult)++;
+    AbsVertexFree(catalog, rightResult, NIL(AbsVertexInfo_t));
+    aux1 = newResult;
+  }
+  else {
+    /* Vertex negating first operand */
+    aux1 = AbsVertexCatalogFindOrAdd(catalog, not_c, !polarity, rightResult, 
+				     NIL(AbsVertexInfo_t), 0, NIL(char), 
+				     NIL(char));
+    if (AbsVertexReadType(aux1) == false_c) {
+      AbsVertexSetPolarity(aux1, !polarity);
+      AbsVertexSetDepth(aux1, AbsVertexReadDepth(rightResult) + 1);
+      AbsVertexSetType(aux1, not_c);
+      AbsVertexSetLeftKid(aux1, rightResult);
+      AbsVertexSetParent(rightResult, aux1);
+    }
+    else {
+      AbsVertexFree(catalog, rightResult, NIL(AbsVertexInfo_t));
+    }
+  }
+  
+  /* Result node holding the and of both operands */
+  aux2 = AbsVertexCatalogFindOrAdd(catalog, and_c, !polarity, leftResult, 
+				   aux1, 0, NIL(char), NIL(char));
+  if (AbsVertexReadType(aux2) == false_c) {
+    AbsVertexSetPolarity(aux2, !polarity);
+    if (AbsVertexReadDepth(leftResult) > AbsVertexReadDepth(aux1)) {
+      AbsVertexSetDepth(aux2, AbsVertexReadDepth(leftResult) + 1);
+    }
+    else {
+      AbsVertexSetDepth(aux2, AbsVertexReadDepth(aux1) + 1);
+    }
+    AbsVertexSetType(aux2, and_c);
+    AbsVertexSetLeftKid(aux2, leftResult);
+    AbsVertexSetRightKid(aux2, aux1);
+    AbsVertexSetParent(aux1, aux2);
+    AbsVertexSetParent(leftResult, aux2);
+  }
+  else {
+    AbsVertexFree(catalog, leftResult, NIL(AbsVertexInfo_t));
+    AbsVertexFree(catalog, aux1, NIL(AbsVertexInfo_t));
+  }
+  
+  /* Top vertex negation of the conjunction */
+  result = AbsVertexCatalogFindOrAdd(catalog, not_c, polarity, aux2,
+				     NIL(AbsVertexInfo_t), 0, NIL(char), 
+				     NIL(char));
+  if (AbsVertexReadType(result) == false_c) {
+    AbsVertexSetPolarity(result, polarity);
+    AbsVertexSetDepth(result, AbsVertexReadDepth(aux2) + 1);
+    AbsVertexSetType(result, not_c);
+    AbsVertexSetLeftKid(result, aux2);
+    AbsVertexSetParent(aux2, result);
+  }
+  else {
+    AbsVertexFree(catalog, aux2, NIL(AbsVertexInfo_t));
+  }
+  
+  return result;
+} /* End of TranslateCtlTHEN */
+
+/**Function********************************************************************
+
+  Synopsis [Computes the operational graph representation of the predicate of
+  the form p AND q]
+
+  SideEffects        []
+
+  SeeAlso            [TranslateCtlSubFormula]
+
+******************************************************************************/
+static AbsVertexInfo_t *
+TranslateCtlAND(
+  AbsVertexCatalog_t *catalog,
+  Ctlp_Formula_t *formula,
+  array_t *fairArray,
+  AbsVertexInfo_t *fairPositive,
+  AbsVertexInfo_t *fairNegative,
+  int polarity,
+  int *uniqueIds)
+{
+  AbsVertexInfo_t *result;
+  AbsVertexInfo_t *leftResult, *rightResult;
+  int leftDepth;
+  int rightDepth;
+  
+  leftResult = TranslateCtlSubFormula(catalog,
+				      Ctlp_FormulaReadLeftChild(formula),
+				      fairArray, fairPositive, fairNegative,
+				      polarity, uniqueIds);
+  rightResult= TranslateCtlSubFormula(catalog,
+				      Ctlp_FormulaReadRightChild(formula),
+				      fairArray, fairPositive, fairNegative,
+				      polarity, uniqueIds);
+  
+  /* Read the depths */
+  leftDepth = AbsVertexReadDepth(leftResult);
+  rightDepth = AbsVertexReadDepth(rightResult);
+  
+  result = AbsVertexCatalogFindOrAdd(catalog, and_c, polarity, leftResult, 
+				     rightResult, 0, NIL(char), NIL(char));
+  if (AbsVertexReadType(result) == false_c) {
+    AbsVertexSetPolarity(result, polarity);
+    if (leftDepth > rightDepth) {
+      AbsVertexSetDepth(result, leftDepth + 1);
+    }
+    else {
+      AbsVertexSetDepth(result, rightDepth + 1);
+    }
+    AbsVertexSetType(result, and_c);
+    AbsVertexSetLeftKid(result, leftResult);
+    AbsVertexSetRightKid(result, rightResult);
+    AbsVertexSetParent(leftResult, result);
+    AbsVertexSetParent(rightResult, result);
+  }
+  else {
+    AbsVertexFree(catalog, leftResult, NIL(AbsVertexInfo_t));
+    AbsVertexFree(catalog, rightResult, NIL(AbsVertexInfo_t));
+  }
+  
+  return result;
+} /* End of TranslateCtlAND */
+
+/**Function********************************************************************
+
+  Synopsis [Computes the operational graph representation of the predicate of
+   the for p OR q]
+
+  SideEffects        []
+
+  SeeAlso            [TranslateCtlSubFormula]
+
+******************************************************************************/
+static AbsVertexInfo_t *
+TranslateCtlOR(
+  AbsVertexCatalog_t *catalog,
+  Ctlp_Formula_t *formula,
+  array_t *fairArray,
+  AbsVertexInfo_t *fairPositive,
+  AbsVertexInfo_t *fairNegative,
+  int polarity,
+  int *uniqueIds)
+{
+  AbsVertexInfo_t *result;
+  AbsVertexInfo_t *leftResult, *rightResult;
+  AbsVertexInfo_t *aux1;
+  AbsVertexInfo_t *aux2;
+  AbsVertexInfo_t *aux3;
+  
+  leftResult = TranslateCtlSubFormula(catalog,
+				      Ctlp_FormulaReadLeftChild(formula),
+				      fairArray, fairPositive, fairNegative,
+				      polarity, uniqueIds);
+  rightResult= TranslateCtlSubFormula(catalog,
+				      Ctlp_FormulaReadRightChild(formula),
+				      fairArray, fairPositive, fairNegative,
+				      polarity, uniqueIds);
+  
+  /* If the sub-formula's top vertex is a negation, eliminate the redundancy */
+  if (AbsVertexReadType(leftResult) == not_c) {
+    AbsVertexInfo_t *newResult;
+
+    newResult = AbsVertexReadLeftKid(leftResult);
+    AbsVertexReadRefs(newResult)++;
+    AbsVertexFree(catalog, leftResult, NIL(AbsVertexInfo_t));
+    aux1 = newResult;
+  }
+  else {
+    /* Vertex negating first operand */
+    aux1 = AbsVertexCatalogFindOrAdd(catalog, not_c, !polarity, leftResult, 
+				     NIL(AbsVertexInfo_t), 0, NIL(char), 
+				     NIL(char));
+    if (AbsVertexReadType(aux1) == false_c) {
+      AbsVertexSetPolarity(aux1, !polarity);
+      AbsVertexSetDepth(aux1, AbsVertexReadDepth(leftResult) + 1);
+      AbsVertexSetType(aux1, not_c);
+      AbsVertexSetLeftKid(aux1, leftResult);
+      AbsVertexSetParent(leftResult, aux1);
+    }
+    else {
+      AbsVertexFree(catalog, leftResult, NIL(AbsVertexInfo_t));
+    }
+  }
+  
+  if (AbsVertexReadType(rightResult) == not_c) {
+    AbsVertexInfo_t *newResult;
+
+    newResult = AbsVertexReadLeftKid(rightResult);
+    AbsVertexReadRefs(newResult)++;
+    AbsVertexFree(catalog, rightResult, NIL(AbsVertexInfo_t));
+    aux2 = newResult;
+  }
+  else {
+    /* Vertex negating second operand */
+    aux2 = AbsVertexCatalogFindOrAdd(catalog, not_c, !polarity, rightResult, 
+				     NIL(AbsVertexInfo_t), 0, NIL(char), 
+				     NIL(char));
+    if (AbsVertexReadType(aux2) == false_c) {
+      AbsVertexSetPolarity(aux2, !polarity);
+      AbsVertexSetDepth(aux2, AbsVertexReadDepth(rightResult) + 1);
+      AbsVertexSetType(aux2, not_c);
+      AbsVertexSetLeftKid(aux2, rightResult);
+      AbsVertexSetParent(rightResult, aux2);
+    }
+    else {
+      AbsVertexFree(catalog, rightResult, NIL(AbsVertexInfo_t));
+    }
+  }
+  
+  /* Vertex taking the conjunction */
+  aux3 = AbsVertexCatalogFindOrAdd(catalog, and_c, !polarity, aux1, aux2,
+				   0, NIL(char), NIL(char));
+  if (AbsVertexReadType(aux3) == false_c) {
+    AbsVertexSetPolarity(aux3, !polarity);
+    if (AbsVertexReadDepth(aux1) > AbsVertexReadDepth(aux2)) {
+      AbsVertexSetDepth(aux3, AbsVertexReadDepth(aux1) + 1);
+    }
+    else {
+      AbsVertexSetDepth(aux3, AbsVertexReadDepth(aux2) + 1);
+    }
+    AbsVertexSetType(aux3, and_c);
+    AbsVertexSetLeftKid(aux3, aux1);
+    AbsVertexSetRightKid(aux3, aux2);
+    AbsVertexSetParent(aux1, aux3);
+    AbsVertexSetParent(aux2, aux3);
+  }
+  else {
+    AbsVertexFree(catalog, aux1, NIL(AbsVertexInfo_t));
+    AbsVertexFree(catalog, aux2, NIL(AbsVertexInfo_t));
+  }
+  
+  /* Top vertex negation of the conjunction */
+  result = AbsVertexCatalogFindOrAdd(catalog, not_c, polarity, aux3,
+				     NIL(AbsVertexInfo_t), 0, NIL(char), 
+				     NIL(char));
+  if (AbsVertexReadType(result) == false_c) {
+    AbsVertexSetPolarity(result, polarity);
+    AbsVertexSetDepth(result, AbsVertexReadDepth(aux3) + 1);
+    AbsVertexSetType(result, not_c);
+    AbsVertexSetLeftKid(result, aux3);
+    AbsVertexSetParent(aux3, result);
+  }
+  else {
+    AbsVertexFree(catalog, aux3, NIL(AbsVertexInfo_t));
+  }
+  
+  return result;
+} /* End of TranslateCtlOR */
+
+/**Function********************************************************************
+
+  Synopsis [Given an array containing vertices, creates the conjunction of all
+  of them.]
+
+  SideEffects        []
+
+  SeeAlso            [ComputeFairPredicate]
+
+******************************************************************************/
+static AbsVertexInfo_t *
+CreateConjunctionChain(
+  AbsVertexCatalog_t *catalog,
+  array_t *conjunctions,
+  int polarity)
+{
+  AbsVertexInfo_t *aux1;
+  AbsVertexInfo_t *aux2;
+  AbsVertexInfo_t *aux3;
+  int i;
+
+  assert(conjunctions != NIL(array_t));
+
+  aux1 = array_fetch(AbsVertexInfo_t *, conjunctions, 0);
+  AbsVertexReadRefs(aux1)++;
+
+  if (array_n(conjunctions) == 1) {
+    return aux1;
+  }
+
+  for (i=1; i<array_n(conjunctions); i++) {
+    aux2 = array_fetch(AbsVertexInfo_t *, conjunctions, i);
+    AbsVertexReadRefs(aux2)++;
+    
+    aux3 = AbsVertexCatalogFindOrAdd(catalog, and_c, polarity, aux1, aux2, 0,
+				     NIL(char), NIL(char));
+
+    if (AbsVertexReadType(aux3) == false_c) {
+      AbsVertexSetPolarity(aux3, polarity);
+      if (AbsVertexReadDepth(aux1) < AbsVertexReadDepth(aux2)) {
+	AbsVertexSetDepth(aux3, AbsVertexReadDepth(aux2) + 1);
+      }
+      else {
+	AbsVertexSetDepth(aux3, AbsVertexReadDepth(aux1) + 1);
+      }
+      AbsVertexSetType(aux3, and_c);
+      AbsVertexSetLeftKid(aux3, aux1);
+      AbsVertexSetRightKid(aux3, aux2);
+      AbsVertexSetParent(aux1, aux3);
+      AbsVertexSetParent(aux2, aux3);
+    }
+    else {
+      AbsVertexFree(catalog, aux1, NIL(AbsVertexInfo_t));
+      AbsVertexFree(catalog, aux2, NIL(AbsVertexInfo_t));
+    }
+
+    aux1 = aux3;
+  }
+
+  return aux1;
+} /* End of CreateConjunctionChain */
Index: vis_dev/vis-2.3/src/abs/absUtil.c
===================================================================
--- vis_dev/vis-2.3/src/abs/absUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/abs/absUtil.c	(revision 14)
@@ -0,0 +1,829 @@
+/**CFile***********************************************************************
+
+  FileName    [absUtil.c]
+
+  PackageName [abs]
+
+  Synopsis [Some miscelaneous functions for non-critical tasks such as printing
+  information, sanity checks, etc]
+
+  Author      [Abelardo Pardo <abel@vlsi.colorado.edu>]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include <time.h>
+#include "absInt.h" 
+
+static char rcsid[] UNUSED = "$Id: absUtil.c,v 1.17 2005/04/16 04:22:21 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void VertexPrintDotRecur(FILE *fp, AbsVertexInfo_t *vertex, st_table *visited);
+static char * VertexTypeToString(AbsVertexInfo_t *vertex);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Print recursively the sub-graph from a given vertex in DOT format.]
+
+  Description [The function receives a pointer to a vertex and a file
+  descriptor. It prints the sub-graph starting with the given vertex in DOT
+  format. The DOT format can be found in the graph visualization package in <a
+  href="http://www.research.att.com/orgs/ssr/book/reuse">
+  http://www.research.att.com/orgs/ssr/book/reuse</a>.]
+
+  SideEffects        []
+
+  SeeAlso            [AbsVertexInfo]
+
+******************************************************************************/
+void
+AbsVertexPrintDot(
+  FILE *fp,
+  array_t *vertexArray)
+{
+  AbsVertexInfo_t *vertexPtr;
+  st_table        *visited;
+  struct tm       *nowStructPtr;
+  char            *nowTxt;
+  time_t          now;
+  int i;
+
+  /* Initialize some variables */
+  now = time(0);
+  nowStructPtr = localtime(&now);
+  nowTxt = asctime(nowStructPtr);
+  visited = st_init_table(st_ptrcmp, st_ptrhash);
+
+  /*
+   * Write out the header for the output file.
+   */
+  (void) fprintf(fp, "# %s\n", Vm_VisReadVersion());
+  (void) fprintf(fp, "# generated: %s", nowTxt);
+  (void) fprintf(fp, "#\n");
+
+  (void) fprintf(fp, "digraph \"Formula\" {\n  rotate=90;\n");
+  (void) fprintf(fp, "  margin=0.5;\n  label=\"Formula\";\n");
+  (void) fprintf(fp, "  size=\"10,7.5\";\n  ratio=\"fill\";\n");
+
+  arrayForEachItem(AbsVertexInfo_t *, vertexArray, i, vertexPtr) {
+    VertexPrintDotRecur(fp, vertexPtr, visited);
+  }
+
+  (void) fprintf(fp, "}\n");
+  st_free_table(visited);
+
+  return;
+} /* End of AbsVertexPrintDot */
+
+
+/**Function********************************************************************
+
+  Synopsis [Function to print the information stored in a vertex.]
+
+  Description [The function receives a pointer to a vertex, a table with
+  vertices already visited and a variable to enable recursion. If the vertex is
+  already in the table, it is not printed. Otherwise, its contents is printed,
+  and if recur is true, the sub-formulas are recursively printed.]
+
+  SideEffects        []
+
+  SeeAlso            [AbsVertexInfo]
+
+******************************************************************************/
+void
+AbsVertexPrint(
+  AbsVertexInfo_t *vertexPtr,
+  st_table *visitedSF,
+  boolean recur,
+  long verbosity)
+{
+  st_table *newVisitedSF;
+
+  newVisitedSF = NIL(st_table);
+  if (recur && visitedSF == NIL(st_table)) {
+    newVisitedSF = st_init_table(st_ptrcmp, st_ptrhash);
+    (void) fprintf(vis_stdout, "ABS:----------------------------------");
+    (void) fprintf(vis_stdout, "-------------------\n");
+  }
+  else {
+    newVisitedSF = visitedSF;
+  }
+
+  if (newVisitedSF != NIL(st_table)) {
+    if (st_is_member(newVisitedSF, (char *)vertexPtr)) {
+      return;
+    }
+    st_insert(newVisitedSF, (char *)vertexPtr, NIL(char));
+  }
+
+  /* Print the type of vertex */
+  (void) fprintf(vis_stdout, "ABS: Vertex(%3d)-(",
+		 AbsVertexReadId(vertexPtr));
+  switch(AbsVertexReadType(vertexPtr)) {
+    case identifier_c:
+      (void) fprintf(vis_stdout, "Identifier ");
+      break;
+    case false_c:
+      (void) fprintf(vis_stdout, "   FALSE   ");
+      break;
+    case variable_c:
+      (void) fprintf(vis_stdout, " Variable  ");
+      break;
+    case fixedPoint_c:
+      (void) fprintf(vis_stdout, "Fixed Point");
+      break;
+    case preImage_c:
+      (void) fprintf(vis_stdout, " PreImage  ");
+      break;
+    case not_c:
+      (void) fprintf(vis_stdout, "    Not    ");
+      break;
+    case and_c: 
+      (void) fprintf(vis_stdout, "    and    ");
+      break;
+    case xor_c:
+      (void) fprintf(vis_stdout, "    xor    ");
+      break;
+    case xnor_c:
+      (void) fprintf(vis_stdout, "    xnor   ");
+      break;
+    default: fail("Encountered unknown type of Vertex\n");
+  }
+  (void) fprintf(vis_stdout, ") (%p)-> ", (void *) vertexPtr);
+
+  /* Print pointer to kids  */
+  if (AbsVertexReadLeftKid(vertexPtr) != NIL(AbsVertexInfo_t)) {
+    (void) fprintf(vis_stdout, "(%p)/",
+		   (void *) AbsVertexReadLeftKid(vertexPtr));
+  }
+  else {
+    (void) fprintf(vis_stdout, "(---NIL---)/");
+  }
+  if (AbsVertexReadRightKid(vertexPtr) != NIL(AbsVertexInfo_t)) {
+    (void) fprintf(vis_stdout, "(%p)\n",
+		   (void *) AbsVertexReadRightKid(vertexPtr));
+  }
+  else {
+    (void) fprintf(vis_stdout, "(---NIL---)\n");
+  }
+
+  /* Print Sat */
+  if (AbsVertexReadType(vertexPtr) != variable_c) {
+    (void) fprintf(vis_stdout, "ABS: Sat  -> ");
+    if (AbsVertexReadSat(vertexPtr) != NIL(mdd_t)) {
+      (void) fprintf(vis_stdout, "%d Nodes\n", 
+		     mdd_size(AbsVertexReadSat(vertexPtr)));
+      if (verbosity & ABS_VB_SCUBE) {
+	AbsBddPrintMinterms(AbsVertexReadSat(vertexPtr));
+      }
+    }
+    else {
+      (void) fprintf(vis_stdout, "NIL\n");
+    }
+  }
+
+  /* Print refs, served, polarity, depth, localApprox and globalApprox */
+  (void) fprintf(vis_stdout, 
+		 "ABS: Rfs Svd Plrty Dpth LclApp GlblApp Cnt Ref\n");
+  (void) fprintf(vis_stdout, "ABS: %3d %3d %3d %6d %4d %6d %5d %3d\n",
+		 AbsVertexReadRefs(vertexPtr), AbsVertexReadServed(vertexPtr),
+		 AbsVertexReadPolarity(vertexPtr), 
+		 AbsVertexReadDepth(vertexPtr),
+		 AbsVertexReadLocalApprox(vertexPtr),
+		 AbsVertexReadGlobalApprox(vertexPtr),
+		 AbsVertexReadConstant(vertexPtr),
+		 AbsVertexReadTrueRefine(vertexPtr));
+
+  /* Print the parents */
+  (void) fprintf(vis_stdout, "ABS: Parents-> ");
+  if (lsLength(AbsVertexReadParent(vertexPtr)) != 0) {
+    AbsVertexInfo_t *parent;
+    lsList parentList;
+    lsGen listGen;
+
+    parentList = AbsVertexReadParent(vertexPtr);
+    lsForEachItem(parentList, listGen, parent) {
+      if (parent == NIL(AbsVertexInfo_t)) {
+	(void) fprintf(vis_stdout, "(---NIL---) ");
+      }
+      else {
+	(void) fprintf(vis_stdout, "%p ", (void *) parent);
+      }
+    }
+    (void) fprintf(vis_stdout, "\n");
+  }
+  else {
+    (void) fprintf(vis_stdout, "---NIL--\n");
+  }
+
+  /* Print Sub-systems*/
+  if (AbsVertexReadType(vertexPtr) == preImage_c) {
+    (void) fprintf(vis_stdout, "ABS: Solutions-> ");
+    if (AbsVertexReadSolutions(vertexPtr) != NIL(st_table)) {
+      AbsEvalCacheEntry_t *entry;
+      st_generator        *stgen;
+      array_t             *units;
+      bdd_node            *key;
+
+      units = array_alloc(mdd_t *, 0);
+      st_foreach_item(AbsVertexReadSolutions(vertexPtr), stgen, &key, &entry) {
+	array_insert_last(mdd_t *, units, 
+			  AbsEvalCacheEntryReadResult(entry));
+      }
+      (void) fprintf(vis_stdout, "%d elements with size %ld Nodes.\n",
+		     array_n(units), mdd_size_multiple(units));
+      array_free(units);
+    }
+    else {
+      (void) fprintf(vis_stdout, "---NIL--\n");
+    }
+  }
+
+  /* Print the localId */
+  if (AbsVertexReadType(vertexPtr) == variable_c) {
+    (void) fprintf(vis_stdout, "ABS: Variable Id-> %d\n",
+		   AbsVertexReadVarId(vertexPtr));
+  }
+
+  if (AbsVertexReadType(vertexPtr) == fixedPoint_c) {
+    /* Print the variable vertex  */
+    (void) fprintf(vis_stdout, "ABS: Variable Vertex-> %p\n", 
+		   (void *) AbsVertexReadFpVar(vertexPtr));
+    
+    /* Print the rings */
+    (void) fprintf(vis_stdout, "ABS: Rings->");
+    if (AbsVertexReadRings(vertexPtr) != NIL(array_t)) {
+      (void) fprintf(vis_stdout, "%d elements with size %ld Nodes.\n",
+		     array_n(AbsVertexReadRings(vertexPtr)),
+		     mdd_size_multiple(AbsVertexReadRings(vertexPtr)));
+    }
+    else {
+      (void) fprintf(vis_stdout, " NIL\n");
+    }
+    /* Print the approximation flags */
+    (void) fprintf(vis_stdout, "ABS: ApproxRings-> ");
+    if (AbsVertexReadRingApprox(vertexPtr) != NIL(array_t)) {
+      int unit;
+      int i;
+      
+      arrayForEachItem(int, AbsVertexReadRingApprox(vertexPtr), i, unit) {
+	(void) fprintf(vis_stdout, "%d,", unit);
+      }
+      (void) fprintf(vis_stdout, "\n");
+    }
+    else {
+      (void) fprintf(vis_stdout, " NIL\n");
+    }
+    
+    /* Print the sub-approximation flags */
+    (void) fprintf(vis_stdout, "ABS: SubApproxRings-> ");
+    if (AbsVertexReadSubApprox(vertexPtr) != NIL(array_t)) {
+      int unit;
+      int i;
+      
+      arrayForEachItem(int, AbsVertexReadSubApprox(vertexPtr), i, unit) {
+	(void) fprintf(vis_stdout, "%d,", unit);
+      }
+      (void) fprintf(vis_stdout, "\n");
+    }
+    else {
+      (void) fprintf(vis_stdout, " NIL\n");
+    }
+  }
+
+  /* Print name and value of the identifier */
+  if (AbsVertexReadType(vertexPtr) == identifier_c) {
+    (void) fprintf(vis_stdout, "ABS: Name/Value-> %s/%s\n",
+		   AbsVertexReadName(vertexPtr), AbsVertexReadValue(vertexPtr));
+  }
+
+  (void) fprintf(vis_stdout, "ABS:----------------------------------");
+  (void) fprintf(vis_stdout, "-------------------\n");
+
+  /* Print the sub-formulas recursively if enabled */
+  if (recur) {
+    if (AbsVertexReadLeftKid(vertexPtr) != NIL(AbsVertexInfo_t)) {
+      AbsVertexPrint(AbsVertexReadLeftKid(vertexPtr), newVisitedSF, recur,
+		     verbosity);
+    }
+    
+    if (AbsVertexReadRightKid(vertexPtr) != NIL(AbsVertexInfo_t)) {
+      AbsVertexPrint(AbsVertexReadRightKid(vertexPtr), newVisitedSF, recur,
+		     verbosity);
+    }
+  }
+
+  /* Clean up */
+  if (visitedSF != newVisitedSF) {
+    st_free_table(newVisitedSF);
+  }
+
+  return;
+} /* End of AbsVertexPrint */
+
+/**Function********************************************************************
+
+  Synopsis           [Function to print the cubes of a BDD.]
+
+  SideEffects        []
+
+******************************************************************************/
+void
+AbsBddPrintMinterms(
+  mdd_t *function)
+{
+  bdd_gen *gen;
+  array_t *cube;
+  int i;
+  int literal;
+
+  if (mdd_is_tautology(function, 1)) {
+    (void) fprintf(vis_stdout, "Tautology\n");
+    return;
+  }
+
+  if (mdd_is_tautology(function, 0)) {
+    (void) fprintf(vis_stdout, "EmptyBdd\n");
+    return;
+  }
+
+  /* Allocate the generator and start the iteration */
+  gen = bdd_first_cube(function, &cube);
+
+  do {
+    arrayForEachItem(int, cube, i, literal) {
+      if (literal == 2) {
+	(void) fprintf(vis_stdout, "-");
+      }
+      else {
+	(void) fprintf(vis_stdout, "%1d", literal);
+      }
+    }
+    (void) fprintf(vis_stdout, "\n");
+  } while (bdd_next_cube(gen, &cube));
+
+  /* Clean Up */
+  bdd_gen_free(gen);
+} /* End of AbsBddPrintMinterms */
+
+/**Function********************************************************************
+
+  Synopsis [Function to detect portions of a formula that need to be evaluated
+  only once]
+
+  Description [This procedure detects portions of a formula that need to be
+  evaluated only once. This amounts basically to detect if there is any vertex
+  representing a variable in a fix-point. If not, after the formula has been
+  evaluated it is declared constant and no further evaluation is required.]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+void
+AbsFormulaSetConstantBit(
+  AbsVertexInfo_t *vertexPtr)
+{
+  boolean leftCntBit;
+  boolean rightCntBit;
+
+  if (AbsVertexReadType(vertexPtr) == identifier_c) {
+    AbsVertexSetConstant(vertexPtr, TRUE);
+    return;
+  }
+
+  if (AbsVertexReadType(vertexPtr) == variable_c) {
+    AbsVertexSetConstant(vertexPtr, FALSE);
+    return;
+  }
+
+  leftCntBit = TRUE;
+  rightCntBit = TRUE;
+
+  /* Recursive call in the left kid */
+  if (AbsVertexReadLeftKid(vertexPtr) != NIL(AbsVertexInfo_t)) {
+    AbsFormulaSetConstantBit(AbsVertexReadLeftKid(vertexPtr));
+    leftCntBit = AbsVertexReadConstant(AbsVertexReadLeftKid(vertexPtr));
+  }
+
+  /* Recursive call in the right kid */
+  if (AbsVertexReadRightKid(vertexPtr) != NIL(AbsVertexInfo_t)) {
+    AbsFormulaSetConstantBit(AbsVertexReadRightKid(vertexPtr));
+    rightCntBit = AbsVertexReadConstant(AbsVertexReadRightKid(vertexPtr));
+  }
+
+  AbsVertexSetConstant(vertexPtr, leftCntBit && rightCntBit);
+
+  return;
+} /* End of AbsFormulaSetConstantBit */
+
+/**Function********************************************************************
+
+  Synopsis [Standard tests to check if the graph represenging a formula is
+  correctly built]
+
+  SideEffects        []
+
+  SeeAlso            [AbsVertexInfo]
+
+******************************************************************************/
+boolean
+AbsFormulaSanityCheck(
+  AbsVertexInfo_t *vertexPtr,
+  st_table *rootTable)
+{
+  AbsVertexInfo_t *aux;
+  boolean result;
+  lsGen listGen;
+  int leftDepth;
+  int rightDepth;
+
+  result = TRUE;
+
+  /* Check the type */
+  if (AbsVertexReadType(vertexPtr) == false_c) {
+    result = FALSE;
+    (void) fprintf(vis_stdout, "** abs error: Illegal formula type.\n");
+  }
+
+  /* Check the refs and the served fields */
+  if (AbsVertexReadRefs(vertexPtr) < 0 || AbsVertexReadServed(vertexPtr) < 0 ||
+      AbsVertexReadRefs(vertexPtr) < AbsVertexReadServed(vertexPtr)) {
+    result = FALSE;
+    (void) fprintf(vis_stdout, "** abs error: Illegal value on reference count.\n");
+  }
+
+  /* Check the depth */
+  leftDepth = AbsVertexReadDepth(vertexPtr) - 1;
+  rightDepth = AbsVertexReadDepth(vertexPtr) - 1;
+  if (AbsVertexReadLeftKid(vertexPtr) != NIL(AbsVertexInfo_t)) {
+    leftDepth = AbsVertexReadDepth(AbsVertexReadLeftKid(vertexPtr));
+  }
+  if (AbsVertexReadRightKid(vertexPtr) != NIL(AbsVertexInfo_t)) {
+    rightDepth = AbsVertexReadDepth(AbsVertexReadRightKid(vertexPtr));
+  }
+  if (leftDepth + 1 != AbsVertexReadDepth(vertexPtr) &&
+      rightDepth + 1 != AbsVertexReadDepth(vertexPtr)) {
+    result = FALSE;
+    (void) fprintf(vis_stdout, "** abs error: Illegal depth value.\n");
+  }
+
+  /* Check if the parent pointers are correctly set */
+  lsForEachItem(AbsVertexReadParent(vertexPtr), listGen, aux) {
+    if (AbsVertexReadLeftKid(aux) != vertexPtr && 
+	AbsVertexReadRightKid(aux) != vertexPtr) {
+      lsFinish(listGen);
+      result = FALSE;
+      (void) fprintf(vis_stdout, "** abs error: Illegal parent pointer.\n");
+    }
+  }
+  
+  /* Check if number of parents and ref agree */
+  if ((lsLength(AbsVertexReadParent(vertexPtr)) +
+       st_is_member(rootTable, (char *) vertexPtr)) !=
+      AbsVertexReadRefs(vertexPtr)) {
+    result = FALSE;
+    (void) fprintf(vis_stdout, "** abs error: Illegal number of parents.\n");
+  }
+
+  /* Check if the constant flag is properly set */
+  if (AbsVertexReadConstant(vertexPtr)) {
+    if (AbsVertexReadType(vertexPtr) == variable_c) {
+      result = FALSE;
+      (void) fprintf(vis_stdout, "** abs error: Illegal constant flag.\n");
+    }
+    else {
+      AbsVertexInfo_t *leftKid;
+      AbsVertexInfo_t *rightKid;
+
+      leftKid = AbsVertexReadLeftKid(vertexPtr);
+      rightKid = AbsVertexReadRightKid(vertexPtr);
+
+      if (leftKid != NIL(AbsVertexInfo_t)  && !AbsVertexReadConstant(leftKid)) {
+	result = FALSE;
+      (void) fprintf(vis_stdout, "** abs error: Illegal constant flag.\n");
+      }
+      if (rightKid != NIL(AbsVertexInfo_t) && 
+	  !AbsVertexReadConstant(rightKid)) {
+	result = FALSE;
+	(void) fprintf(vis_stdout, "** abs error: Illegal constant flag.\n");
+      }
+    }
+  }
+
+  /* Check the polarity labeling */
+  if (AbsVertexReadType(vertexPtr) == not_c) {
+    if (AbsVertexReadPolarity(vertexPtr) == 
+	AbsVertexReadPolarity(AbsVertexReadLeftKid(vertexPtr))) {
+      result = FALSE;
+      (void) fprintf(vis_stdout, "** abs error: Illegal polarity labeling.\n");
+    }
+  }
+  else {
+    if (AbsVertexReadLeftKid(vertexPtr) != NIL(AbsVertexInfo_t) &&
+	AbsVertexReadPolarity(vertexPtr) !=
+	AbsVertexReadPolarity(AbsVertexReadLeftKid(vertexPtr))) {
+      result = FALSE;
+      (void) fprintf(vis_stdout, "** abs error: Illegal polarity labeling.\n");
+    }
+    if (AbsVertexReadRightKid(vertexPtr) != NIL(AbsVertexInfo_t) &&
+	AbsVertexReadPolarity(vertexPtr) !=
+	AbsVertexReadPolarity(AbsVertexReadRightKid(vertexPtr))) {
+      result = FALSE;
+      (void) fprintf(vis_stdout, "** abs error: Illegal polarity labeling.\n");
+    }
+  }
+  
+  if (!result) {
+    return result;
+  }
+
+  /* Recur over the sub-formulas */
+  if (AbsVertexReadLeftKid(vertexPtr) != NIL(AbsVertexInfo_t)) {
+    result = AbsFormulaSanityCheck(AbsVertexReadLeftKid(vertexPtr), rootTable);
+  }
+  
+  if (!result) {
+    return result;
+  }
+
+  if (AbsVertexReadRightKid(vertexPtr) != NIL(AbsVertexInfo_t) && 
+      AbsVertexReadType(vertexPtr) != fixedPoint_c) {
+    result = AbsFormulaSanityCheck(AbsVertexReadRightKid(vertexPtr), rootTable);
+  }
+  
+  return result;
+} /* End of AbsFormulaSanityCheck */
+
+/**Function********************************************************************
+
+  Synopsis           [Sanity check for the set of iterates in a fixed point]
+
+  Description [This function verifies the property that in the sequence of
+  iterates of a fixed point s_1,...,s_n, if i<j then s_i\subseteq s_j. If the
+  condition is not satisfied it returns a FALSE. Its use is recommended inside
+  an assert clause, that way, whenever the property is not satisfied, the
+  program aborts]
+
+  SideEffects        []
+
+******************************************************************************/
+boolean
+AbsIteratesSanityCheck(
+  Abs_VerificationInfo_t *absInfo,
+  AbsVertexInfo_t *vertexPtr)
+{
+  array_t *rings;
+  mdd_t *element;
+  mdd_t *previous;
+  mdd_t *careSet;
+  boolean result;
+  int index;
+
+  /* Variable initialization */
+  careSet = AbsVerificationInfoReadCareSet(absInfo);
+  result = TRUE;
+  rings = AbsVertexReadRings(vertexPtr);
+  element = NIL(mdd_t);
+  previous = NIL(mdd_t);
+
+  arrayForEachItem(mdd_t *, rings, index, element) {
+    if (previous != NIL(mdd_t)) {
+      result = result && AbsMddLEqualModCareSet(previous, element, careSet);
+      if (AbsMddEqualModCareSet(previous, element, careSet) &&
+          index != array_n(rings) - 1) {
+	result = FALSE;
+      }
+    }
+    previous = element;
+  }
+
+  return result;
+} /* End of AbsIteratesSanityCheck */
+
+/**Function********************************************************************
+
+  Synopsis           [Print the statistics report]
+
+  SideEffects        []
+
+******************************************************************************/
+void
+AbsStatsPrintReport(
+  FILE *fp,
+  AbsStats_t *stats)
+{
+  (void) fprintf(fp, "ABS: ------- Statistics Begin Report -------\n");
+  (void) fprintf(fp, "ABS: FixedPoint Evaluated %6d times\n",
+		 AbsStatsReadEvalFixedPoint(stats));
+  (void) fprintf(fp, "ABS:            Refined   %6d times\n",
+		 AbsStatsReadRefineFixedPoint(stats));
+  (void) fprintf(fp, "ABS: And        Evaluated %6d times\n",
+		 AbsStatsReadEvalAnd(stats));
+  (void) fprintf(fp, "ABS:            Refined   %6d times\n",
+		 AbsStatsReadRefineAnd(stats));
+  (void) fprintf(fp, "ABS: Not        Evaluated %6d times\n",
+		 AbsStatsReadEvalNot(stats));
+  (void) fprintf(fp, "ABS:            Refined   %6d times\n",
+		 AbsStatsReadRefineNot(stats));
+  (void) fprintf(fp, "ABS: PreImage   Evaluated %6d times\n",
+		 AbsStatsReadEvalPreImage(stats));
+  (void) fprintf(fp, "ABS:            Refined   %6d times\n",
+		 AbsStatsReadRefinePreImage(stats));
+  (void) fprintf(fp, "ABS: Identifier Evaluated %6d times\n",
+		 AbsStatsReadEvalIdentifier(stats));
+  (void) fprintf(fp, "ABS:            Refined   %6d times\n",
+		 AbsStatsReadRefineIdentifier(stats));
+  (void) fprintf(fp, "ABS: Variable   Evaluated %6d times\n",
+		 AbsStatsReadEvalVariable(stats));
+  (void) fprintf(fp, "ABS:            Refined   %6d times\n",
+		 AbsStatsReadRefineVariable(stats));
+  (void) fprintf(fp, "ABS: ---------------------------------------\n");
+  (void) fprintf(fp, "ABS: Preimage Exact       %6d times\n",
+		 AbsStatsReadExactPreImage(stats));
+  (void) fprintf(fp, "ABS:          Approx.     %6d times\n",
+		 AbsStatsReadApproxPreImage(stats));
+  (void) fprintf(fp, "ABS: Image    Exact       %6d times\n",
+		 AbsStatsReadExactImage(stats));
+  (void) fprintf(fp, "ABS: ---------------------------------------\n");
+  (void) fprintf(fp, "ABS: PreImg CacheEntries  %6d entries\n",
+		 AbsStatsReadPreImageCacheEntries(stats));
+  (void) fprintf(fp, "ABS: Img    CacheEntries  %6d entries\n",
+		 AbsStatsReadImageCacheEntries(stats));
+  (void) fprintf(fp, "ABS: ---------------------------------------\n");
+  (void) fprintf(fp, "ABS: PreImg Cpu Time     %7.1f seconds\n",
+		 AbsStatsReadPreImageCpuTime(stats)/1000.0);
+  (void) fprintf(fp, "ABS: AppPre Cpu Time     %7.1f seconds\n",
+		 AbsStatsReadAppPreCpuTime(stats)/1000.0);
+  (void) fprintf(fp, "ABS: Image  Cpu Time     %7.1f seconds\n",
+		 AbsStatsReadImageCpuTime(stats)/1000.0);
+  (void) fprintf(fp, "ABS: ---------------------------------------\n");
+  (void) fprintf(fp, "ABS: Reordering Invoked   %6d times\n",
+		 AbsStatsReadNumReorderings(stats));
+  (void) fprintf(fp, "ABS: ---------------------------------------\n");
+  util_print_cpu_stats(vis_stdout);
+  (void) fprintf(fp, "ABS: -------  Statistics End Report  -------\n");
+
+  return;
+} /* End of AbsStatsPrintReport */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis           [Prints the vertex content in DOT format.]
+
+  SideEffects        []
+
+  SeeAlso            [AbsVertexPrintDot]
+
+******************************************************************************/
+static void
+VertexPrintDotRecur(
+  FILE *fp,
+  AbsVertexInfo_t *vertex,
+  st_table *visited)
+{
+  AbsVertexInfo_t *leftKid;
+  AbsVertexInfo_t *rightKid;
+
+  /* Check the cache */
+  if (st_is_member(visited, (char *)vertex)) {
+    return;
+  }
+
+  /* Recur in the left kid if needed */
+  leftKid = AbsVertexReadLeftKid(vertex);
+  if (leftKid != NIL(AbsVertexInfo_t)) {
+    VertexPrintDotRecur(fp, AbsVertexReadLeftKid(vertex), visited);
+    
+    if (AbsVertexReadType(leftKid) != identifier_c) {
+      (void) fprintf(fp, "  \"%s(%d)%c\" -> \"%s(%d)%c\";\n", 
+		     VertexTypeToString(vertex),
+		     AbsVertexReadId(vertex),
+		     AbsVertexReadPolarity(vertex)?'+':'-', 
+		     VertexTypeToString(leftKid),
+		     AbsVertexReadId(leftKid),
+		     AbsVertexReadPolarity(leftKid)?'+':'-');
+    }
+    else {
+      (void) fprintf(fp, "  \"%s(%d)%c\" -> \"%s=%s(%d)%c\"\n",
+		     VertexTypeToString(vertex),
+		     AbsVertexReadId(vertex),
+		     AbsVertexReadPolarity(vertex)?'+':'-',
+		     AbsVertexReadName(leftKid),
+		     AbsVertexReadValue(leftKid),
+		     AbsVertexReadId(leftKid),
+		     AbsVertexReadPolarity(leftKid)?'+':'-');
+    }
+  }
+    
+  /* Recur in the right kid if needed */
+  rightKid = AbsVertexReadRightKid(vertex);
+  if (rightKid != NIL(AbsVertexInfo_t)) {
+    VertexPrintDotRecur(fp, AbsVertexReadRightKid(vertex), visited);
+
+    if (AbsVertexReadType(rightKid) != identifier_c) {
+      (void) fprintf(fp, "  \"%s(%d)%c\" -> \"%s(%d)%c\";\n", 
+		     VertexTypeToString(vertex),
+		     AbsVertexReadId(vertex),
+		     AbsVertexReadPolarity(vertex)?'+':'-', 
+		     VertexTypeToString(rightKid),
+		     AbsVertexReadId(rightKid),
+		     AbsVertexReadPolarity(rightKid)?'+':'-');
+    }
+    else {
+      (void) fprintf(fp, "  \"%s(%d)%c\" -> \"%s=%s(%d)%c\"\n",
+		     VertexTypeToString(vertex),
+		     AbsVertexReadId(vertex),
+		     AbsVertexReadPolarity(vertex)?'+':'-',
+		     AbsVertexReadName(rightKid),
+		     AbsVertexReadValue(rightKid),
+		     AbsVertexReadId(rightKid),
+		     AbsVertexReadPolarity(rightKid)?'+':'-');
+    }
+  }
+
+  st_insert(visited, (char *)vertex, NIL(char));
+  
+  return;
+} /* End of VertexPrintDotRecur */
+
+/**Function********************************************************************
+
+  Synopsis           [Returns the string representing a vertex type.]
+
+  SideEffects        []
+
+******************************************************************************/
+static char *
+VertexTypeToString(
+  AbsVertexInfo_t *vertex)
+{
+  char *typeStr;
+
+  switch (AbsVertexReadType(vertex)) {
+    case fixedPoint_c:
+      typeStr = "LFP";
+      break;
+    case and_c:
+      typeStr = "AND";
+      break;
+    case xor_c:
+      typeStr = "XOR";
+      break;
+    case xnor_c:
+      typeStr = "XNOR";
+      break;
+    case not_c:
+      typeStr = "NOT";
+      break;
+    case preImage_c:
+      typeStr = "Pre";
+      break;
+    case identifier_c:
+      typeStr = "Id";
+      break;
+    case variable_c:
+      typeStr = "VAR";
+      break;
+    case false_c:
+      typeStr = "FALSE";
+      break;
+    default:
+      fail("Unknown vertex type.");
+      break;
+  }
+
+  return typeStr;
+} /* End of VertexTypeToString */
+
Index: vis_dev/vis-2.3/src/amc/amc.h
===================================================================
--- vis_dev/vis-2.3/src/amc/amc.h	(revision 14)
+++ vis_dev/vis-2.3/src/amc/amc.h	(revision 14)
@@ -0,0 +1,176 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [amc.h]
+
+  PackageName [amc]
+
+  Synopsis    [Model Check using over(under)-approximation of the transition
+  relation.]
+
+  Description [The package implements the approximate_model_check command.
+  The command is designed as a wrapper around the model_check command. 
+  The command contains dual algorithms.  Predefined abstraction of the 
+  transition relation is performed in a controlled way to ensure that the result 
+  is reliable. By default, the command makes its effort to prove whether 
+  the given ACTL formula is positive. User must set an environment variable 
+  "amc_prove_false" when he/she wishes to prove whether the given ACTL formula 
+  is negative.  When the formula is proven FALSE, then the error trace is 
+  returned as in the model_check command. 
+  Currently, one predefined approximation method, namely a "block-tearing"
+  method, is implemented. The package manipulate the internal data structure
+  of FSM to obtain over(under)-approximation of a given system. The algorithm
+  begin with coarse approximation in which the degree of initial approximation
+  is set by the user. Initial degree of approximation can be set by using 
+  "amc_sizeof_group" environment. When the initial attempt using the coarse
+  approximation fails, the algorithm automatically combine subsystems(take 
+  synchronous product) to obtain refined approximations. The procedure is
+  repeated until the approximation is good enough so that the result is 
+  reliable. 
+  ]
+
+
+  Author      [Woohyuk Lee]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+  Revision    [$Id: amc.h,v 1.17 2002/09/08 23:15:15 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _AMC
+#define _AMC
+
+#include "part.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Enum************************************************************************
+
+  Synopsis    [Methods for Approximation.]
+
+  Description [Currently, only Amc_Block_c is used. Amc_Block_c method
+  implements the abstraction method called "block tearing". The blocks of 
+  subsystem is created by grouping the subset of vertices of the partition.
+  Based on the initial grouping into blocks of subsystems, over(under)-
+  approximation of the transition relation is created. The approximations of
+  the transition relation is used to conservatively verify either true
+  positive or true negative of a given ACTL formula.]
+
+******************************************************************************/
+typedef enum {
+  Amc_Variable_c,
+  Amc_Block_c,
+  Amc_Default_c
+} Amc_MethodType;
+
+/**Enum************************************************************************
+
+  Synopsis    [Verbosity Levels.]
+
+******************************************************************************/
+typedef enum {
+  Amc_VerbosityNone_c,
+  Amc_VerbositySpit_c,
+  Amc_VerbosityVomit_c
+} Amc_VerbosityLevel;
+
+/**Enum************************************************************************
+
+  Synopsis    [Quantification Mode.]
+
+******************************************************************************/
+typedef enum {
+  Amc_PresentVars_c,
+  Amc_NextVars_c,
+  Amc_InputVars_c,
+  Amc_User_c
+} Amc_QuantificationMode;
+
+/**Enum************************************************************************
+
+  Synopsis    [Verification Results.]
+
+******************************************************************************/
+typedef enum {
+  Amc_Verified_Unknown_c,
+  Amc_Verified_True_c,
+  Amc_Verified_False_c
+} Amc_Verified_Answer;
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef struct AmcSubsystemInfo Amc_SubsystemInfo_t;
+typedef struct AmcInfoStruct Amc_Info_t;
+
+#include "mc.h"
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void Amc_AmcEvaluateFormula(Ntk_Network_t *network, Ctlp_Formula_t *formula, int verbosity);
+EXTERN Amc_Info_t * Amc_AmcInfoInitialize(Ntk_Network_t *network, Ctlp_Formula_t *formula, Amc_MethodType methodType, int verbosity);
+EXTERN mdd_t * Amc_AmcExistentialQuantifySubsystem(Amc_SubsystemInfo_t *subSystem, array_t *quantifyVars, Amc_QuantificationMode quantificationMode);
+EXTERN array_t * Amc_AmcExistentialQuantifySubsystemArray(array_t *subSystemArray, Amc_SubsystemInfo_t *currentSystem, array_t *quantifyVars, Amc_QuantificationMode quantificationMode);
+EXTERN Fsm_Fsm_t * Amc_AmcSubsystemReadFsm(Amc_SubsystemInfo_t *system);
+EXTERN void Amc_AmcSubsystemSetFsm(Amc_SubsystemInfo_t *system, Fsm_Fsm_t *info);
+EXTERN array_t * Amc_AmcSubsystemReadRelationArray(Amc_SubsystemInfo_t *system);
+EXTERN void Amc_AmcSubsystemSetRelationArray(Amc_SubsystemInfo_t *system, array_t *info);
+EXTERN mdd_t * Amc_AmcSubsystemReadNextStateVarSmoothen(Amc_SubsystemInfo_t *system);
+EXTERN void Amc_AmcSubsystemSetNextStateVarSmoothen(Amc_SubsystemInfo_t *system, mdd_t *info);
+EXTERN mdd_t * Amc_AmcSubsystemReadSatisfy(Amc_SubsystemInfo_t *system);
+EXTERN void Amc_AmcSubsystemSetSatisfy(Amc_SubsystemInfo_t *system, mdd_t *data);
+EXTERN st_table * Amc_AmcSubsystemReadVertexTable(Amc_SubsystemInfo_t *system);
+EXTERN void Amc_AmcSubsystemSetVertexTable(Amc_SubsystemInfo_t *system, st_table *data);
+EXTERN st_table * Amc_AmcSubsystemReadFanInTable(Amc_SubsystemInfo_t *system);
+EXTERN void Amc_AmcSubsystemSetFanInTable(Amc_SubsystemInfo_t *system, st_table *data);
+EXTERN st_table * Amc_AmcSubsystemReadFanOutTable(Amc_SubsystemInfo_t *system);
+EXTERN void Amc_AmcSubsystemSetFanOutTable(Amc_SubsystemInfo_t *system, st_table *data);
+EXTERN char * Amc_AmcSubsystemReadMethodSpecificData(Amc_SubsystemInfo_t *system);
+EXTERN void Amc_AmcSubsystemSetMethodSpecificData(Amc_SubsystemInfo_t *system, char *data);
+EXTERN mdd_t * Amc_AmcReadInitialStates(Amc_Info_t *system);
+EXTERN void Amc_AmcSetInitialStates(Amc_Info_t *system, mdd_t *data);
+EXTERN Amc_SubsystemInfo_t * Amc_AmcReadOptimalSystem(Amc_Info_t *system);
+EXTERN void Amc_AmcSetOptimalSystem(Amc_Info_t *system, Amc_SubsystemInfo_t *data);
+EXTERN void * Amc_AmcReadMethodData(Amc_Info_t *system);
+EXTERN void Amc_AmcSetMethodData(Amc_Info_t *system, void *data);
+EXTERN Amc_SubsystemInfo_t * Amc_AmcSubsystemAllocate(void);
+EXTERN Amc_SubsystemInfo_t * Amc_AmcSubsystemCreate(Fsm_Fsm_t *fsm, mdd_t *satisfyStates, st_table *vertexTable, st_table *fanInTable, st_table *fanOutTable);
+EXTERN Amc_SubsystemInfo_t * Amc_AmcSubsystemDuplicate(Ntk_Network_t *network, Amc_SubsystemInfo_t *subSystem);
+EXTERN void Amc_AmcSubsystemFree(Amc_SubsystemInfo_t *subSystem);
+EXTERN void Amc_AmcSubsystemFreeAlsoPartition(Amc_SubsystemInfo_t *subSystem);
+EXTERN Amc_SubsystemInfo_t * Amc_CombineSubsystems(Ntk_Network_t *network, Amc_SubsystemInfo_t *subSystem1, Amc_SubsystemInfo_t *subSystem2);
+EXTERN Img_ImageInfo_t * Amc_AmcReadOrCreateImageInfo(Fsm_Fsm_t *fsm);
+EXTERN mdd_t * Amc_AmcEvaluateCTLFormula(Amc_SubsystemInfo_t *subSystem, array_t *subSystemArray, Ctlp_Formula_t *ctlFormula, mdd_t *fairStates, Fsm_Fairness_t *fairCondition, mdd_t *modelCareStates, boolean lowerBound, array_t *quantifyVars, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel);
+EXTERN mdd_t * Amc_AmcEvaluateEXFormula(Fsm_Fsm_t *modelFsm, array_t *subSystemArray, Amc_SubsystemInfo_t *subSystem, mdd_t *targetMdd, mdd_t *fairStates, mdd_t *careStates, boolean lowerBound, array_t *quantifyVars, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel);
+EXTERN mdd_t * Amc_AmcEvaluateEUFormula(Fsm_Fsm_t *modelFsm, array_t *subSystemArray, Amc_SubsystemInfo_t *subSystem, mdd_t *invariantMdd, mdd_t *targetMdd, mdd_t *fairStates, mdd_t *careStates, array_t *onionRings, boolean lowerBound, array_t *quantifyVars, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel);
+EXTERN mdd_t * Amc_AmcEvaluateEGFormula(Fsm_Fsm_t *modelFsm, array_t *subSystemArray, Amc_SubsystemInfo_t *subSystem, mdd_t *invariantMdd, mdd_t *fairStates, Fsm_Fairness_t *modelFairness, mdd_t *careStates, array_t *onionRingsArrayForDbg, boolean lowerBound, array_t *quantifyVars, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel);
+EXTERN void Amc_Init(void);
+EXTERN void Amc_End(void);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _AMC */
Index: vis_dev/vis-2.3/src/amc/amc.make
===================================================================
--- vis_dev/vis-2.3/src/amc/amc.make	(revision 14)
+++ vis_dev/vis-2.3/src/amc/amc.make	(revision 14)
@@ -0,0 +1,4 @@
+CSRC += amcBlock.c amcCmd.c amcAmc.c
+HEADERS += amc.h amcInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/amc/amcAmc.c
===================================================================
--- vis_dev/vis-2.3/src/amc/amcAmc.c	(revision 14)
+++ vis_dev/vis-2.3/src/amc/amcAmc.c	(revision 14)
@@ -0,0 +1,2488 @@
+/**CFile***********************************************************************
+
+  FileName    [amcAmc.c]
+
+  PackageName [amc]
+
+  Synopsis    [Approximate Model Checker.]
+
+  Author      [Woohyuk Lee <woohyuk@duke.colorado.edu>]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "amcInt.h" 
+#include "mcInt.h" 
+
+static char rcsid[] UNUSED = "$Id: amcAmc.c,v 1.57 2005/04/16 04:22:41 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+static int stringCompare(const void *s1, const void *s2);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Evaluate formula with approximations.]
+
+  Description [Starting from an initial coarse approximation, find an 
+  approximation that produces reliable result. The degree of approximation
+  is determined by the number of vertices contained in a subsystem. The initial
+  number of vertices in a subsystem is set by "amc_sizeof_group" environment.
+  The algorithm searches a virtual lattice of approximations in which the
+  level of the lattice is defined as the degree of approximations. Once the
+  approximations in a certain level fails to prove the formula, the algorithm
+  automatically refines the approximation by combining(taking the synchronous
+  product) of subsystems. It repeats the process until the approximation is
+  refined enough to produce a reliable result. The procedure may also be
+  viewed as finding a pseudo-optimal path starting from the coarse 
+  approximations(in level 1 of the lattice of approximations) to the
+  approximations that produce reliable result. One can draw a virtual contour
+  separating the approximations that produce faulty results and the reliable
+  results. We call this virtual placement of the approximations and the
+  contour separting the two regions, a lattice of approximations.
+  The algorithms are dual. Each algorithm makes its effort to prove whether the
+  formula is positive or negative respectively. When proving true positive of
+  given ACTL formula we use over-approximation  of the transition relation,
+  and to prove true negative, we use under-approximation of the transition
+  relation.]
+
+
+  SideEffects []
+
+  SeeAlso []
+  
+******************************************************************************/
+void
+Amc_AmcEvaluateFormula(
+  Ntk_Network_t		*network,
+  Ctlp_Formula_t	*formula,
+  int			verbosity)
+{
+  Amc_Info_t		*amcInfo;
+  int			levelOfLattice;
+  char			*flagValue;
+
+  long initialTime = 0;
+  long finalTime;
+
+
+  /* 
+   * If the partition was not created, get out.  We are assuming we were able to 
+   * construct BDD for each combinational outputs.
+   */
+
+  graph_t	*partition = Part_NetworkReadPartition(network);
+  if (partition == NIL(graph_t)) {
+    error_append("** amc error: Network has no partition. Cannot apply approximate model checking.");
+    return;
+  }
+
+
+  /*
+   * Initialize data structures.
+   */
+  amcInfo = Amc_AmcInfoInitialize(network, formula, Amc_Default_c, verbosity);
+
+
+
+  /* 
+   * Check every possible environment variables that user may have set.
+   * And give user some assurance by reporting the flag values.
+   * Explanation of possible environment variables are discussed in the
+   * man page of the package.
+   */
+  amcInfo->isMBM = 0;
+
+  flagValue = Cmd_FlagReadByName("amc_prove_false");
+  if (flagValue == NIL(char)){
+    amcInfo->lowerBound = 0;
+    fprintf(vis_stdout, "\n#AMC: Proving whether the formula is true.\n");
+  }
+  else {
+    amcInfo->lowerBound = 1;
+    fprintf(vis_stdout, "\n#AMC: Proving whether the formula is false.\n");
+  }
+
+  if(verbosity) {
+    flagValue = Cmd_FlagReadByName("amc_grouping_method");
+    if (flagValue == NIL(char)){
+      amcInfo->groupingMethod = 0;
+      fprintf(vis_stdout, "\n#AMC: No grouping method has been set."); 
+    }
+    else {
+      amcInfo->groupingMethod = 1;
+      fprintf(vis_stdout, "\n#AMC: Using latch dependency method for grouping latches into subsystems.");
+    }
+  }
+
+
+
+  /*
+   * The lattice of approximation algorithm.
+   */
+
+  levelOfLattice = array_n(amcInfo->subSystemArray);
+  amcInfo->currentLevel = 1;
+
+  while(levelOfLattice >= amcInfo->currentLevel) {
+    if(verbosity) {
+      (void)fprintf(vis_stdout, "\n\n##AMC: Entering level %d(%d) of the lattice of approximations\n", 
+                                   amcInfo->currentLevel, levelOfLattice);
+      fflush(vis_stdout);
+    }
+
+
+    initialTime = util_cpu_time();
+
+    if( (!(*amcInfo->amcBoundProc)(amcInfo, formula, verbosity)) && !(amcInfo->isVerified) ) {
+
+      /* Automatically switches to lattice of lowerbound approximations */
+      if(verbosity)
+        (void)fprintf(vis_stdout, "Abandoning upper bound approximations.\n");
+
+      /* Free all */
+      (*amcInfo->amcFreeProc)(amcInfo);
+
+      amcInfo = Amc_AmcInfoInitialize(network, formula, Amc_Default_c, verbosity);
+      amcInfo->lowerBound = TRUE;
+      amcInfo->currentLevel = 0;
+
+    }
+    else if(amcInfo->isVerified) {
+      finalTime = util_cpu_time();
+      if(verbosity == Amc_VerbosityVomit_c) {
+        (void) fprintf(vis_stdout, "\n%-20s%10ld\n", "analysis time =", 
+                                    (finalTime - initialTime) / 1000);
+      }
+
+      if(amcInfo->amcAnswer == Amc_Verified_True_c) {
+        (void) fprintf(vis_stdout, "\n# AMC: Verified formula TRUE at level %d of %d : ",
+		       amcInfo->currentLevel, levelOfLattice);
+      }else if(amcInfo->amcAnswer == Amc_Verified_False_c) {
+        (void) fprintf(vis_stdout, "\n# AMC: Verified formula FALSE at level %d of %d : ",
+		       amcInfo->currentLevel, levelOfLattice);
+      }else{
+	fprintf(vis_stdout, "\n# AMC: formula unknown --- ");
+        Ctlp_FormulaPrint( vis_stdout, Ctlp_FormulaReadOriginalFormula( formula ) );
+	(void) fprintf(vis_stdout, "\n# AMC: Verified formula UNKNOWN at level %d of %d : ",
+		       amcInfo->currentLevel, levelOfLattice);
+      }
+      (void) fprintf(vis_stdout, "\n# AMC: ");
+      Ctlp_FormulaPrint( vis_stdout, Ctlp_FormulaReadOriginalFormula( formula ) );
+      AmcPrintOptimalSystem(vis_stdout, amcInfo);
+      (*amcInfo->amcFreeProc)(amcInfo);
+      return;
+    } /* end of else if(amcInfo->isVerified) */
+    
+    amcInfo->currentLevel++;
+  } /* end of while(levelOfLattice >= amcInfo->currentLevel) */
+  
+  finalTime = util_cpu_time();
+  if(verbosity == Amc_VerbosityVomit_c) {
+    (void) fprintf(vis_stdout, "\n%-20s%10ld\n", "analysis time =",
+		   (finalTime - initialTime) / 1000);
+  }
+  
+  /*
+  ** Now, spec was not verified becase there was an error in computation.
+  */ 
+  (void) fprintf(vis_stdout, "\n# AMC: The spec was not able to be verified.\n# AMC: ");
+  Ctlp_FormulaPrint( vis_stdout, Ctlp_FormulaReadOriginalFormula( formula ) );
+  (*amcInfo->amcFreeProc)(amcInfo);
+  
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes an amcInfo structure for the given method.]
+
+  Description [Regardless of the method type, the initialization procedure
+  starts from constructing set of subsystems. A subsystem contains a subset
+  of vertices of the partition. Based on the subset of vertices, subFSM is
+  created. The subsystems are stored as an array. After the creation of
+  the subsystem array, the function initializes remaining field of 
+  (Amc_Info_t *) amcInfo.
+  The function returns initialized (Amc_Info_t *) amcInfo.]
+
+  SideEffects        []
+
+  SeeAlso     []
+
+******************************************************************************/
+Amc_Info_t *
+Amc_AmcInfoInitialize(
+  Ntk_Network_t		*network,
+  Ctlp_Formula_t	*formula,
+  Amc_MethodType	methodType,
+  int			verbosity)
+{
+  Amc_Info_t		*amcInfo;
+  char			*userSpecifiedMethod;
+
+  amcInfo = ALLOC(Amc_Info_t, 1);
+  amcInfo->network = network;
+
+  /*
+   * AmcCreateSubsystems creates fsm for each subsystem and returns subSystemArray.
+   */
+  amcInfo->subSystemArray = AmcCreateSubsystemArray(network, formula);
+
+#ifdef AMC_DEBUG
+AmcCheckSupportAndOutputFunctions(amcInfo->subSystemArray);
+#endif
+
+  /*
+   * Initialize optimalSystem, isVerified; 
+   */
+  amcInfo->optimalSystem = NIL(Amc_SubsystemInfo_t);
+  amcInfo->isVerified = 0;
+  amcInfo->amcAnswer = Amc_Verified_Unknown_c;
+
+  /*
+   * If methodType is default, use user-specified method.
+   */
+  if (methodType == Amc_Default_c) {
+    userSpecifiedMethod = Cmd_FlagReadByName("amc_method");
+    if (userSpecifiedMethod == NIL(char)) {
+      methodType = Amc_Block_c;
+    }
+    else {
+      if (strcmp(userSpecifiedMethod, "block") == 0) {
+        methodType = Amc_Block_c;
+      }
+      else if (strcmp(userSpecifiedMethod, "variable") == 0) {
+        methodType = Amc_Variable_c;
+      }
+      else {
+        (void) fprintf(vis_stderr, "** amc error: Unrecognized amc_method %s: using Block method.\n",
+                       userSpecifiedMethod);
+        methodType = Amc_Block_c;
+      }
+    }
+  }
+  
+  amcInfo->methodType = methodType;
+
+
+  /* 
+   * Every subsystem shares identical initial states. 
+   * We do not abstract the state space. Only the transition relation is over or
+   * under approximated.
+   */
+  {
+    mdd_t		*sampleInitialStates;
+    Amc_SubsystemInfo_t *sampleSystem;
+
+    /* 
+     * Fsm routines always returns duplicate copy. 
+     */
+
+    sampleSystem = array_fetch(Amc_SubsystemInfo_t *, amcInfo->subSystemArray, 0);
+    sampleInitialStates = Fsm_FsmComputeInitialStates(sampleSystem->fsm); 
+    amcInfo->initialStates = sampleInitialStates;  
+  }
+
+
+  /* 
+   * Fill in the rest of amcInfo according to methodType.
+   */
+  switch(methodType) {
+    case Amc_Block_c:
+      amcInfo->methodData = NIL(void);
+      amcInfo->amcBoundProc = AmcBlockTearingProc;
+      amcInfo->amcFreeProc  = AmcFreeBlock;
+      break;
+/*
+ ;;The variable tearing method has not been implemented yet;;
+    case Amc_Variable_c:
+      amcInfo->methodData = AmcInfoInitializeVariable(amcInfo);
+      amcInfo->amcUpperBoundProc = AmcUpperBoundProcVariable;
+      amcInfo->amcLowerBoundProc = AmcLowerBoundProcVariable;
+      amcInfo->amcFreeProc = AmcFreeVariable;
+      break;
+*/
+    default:
+      fail("Invalid methodtype when initalizing amc method"); 
+  }
+
+  amcInfo->currentLevel = 0;
+
+  return(amcInfo);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Apply existential quantification over a subsystem.]
+
+  Description [Given a subsystem, the routine existentially quantify 
+  the MDD variables from the transition relation of the subsystem.   
+  The return value is the resulting MDD. There are four quantification 
+  modes;   
+  <dl>
+  <dt> Amc_PresentVars_c
+  <dd> Existentially quantify present state variables. <p>
+
+  <dt> Amc_NextVars_c
+  <dd> Existentially quantify next state variables. <p>
+  
+  <dt> Amc_InputVars_c
+  <dd> Existentially quantify input variables. <p>
+
+  <dt> Amc_User_c
+  <dd> Existentially quantify variables provide by the user. In this
+       mode user has to provide the array of MDD IDs to the function. If
+       the user does not provide the array of MDD IDs, the function just
+       returns the transition relation of the subsystem. <p>
+  </dl>]
+
+  SideEffects []
+
+  SeeAlso     [Amc_SubsystemInfo, AmcInitializeQuantifyVars]
+
+******************************************************************************/
+mdd_t *
+Amc_AmcExistentialQuantifySubsystem(
+  Amc_SubsystemInfo_t	*subSystem,
+  array_t		*quantifyVars,
+Amc_QuantificationMode	quantificationMode)
+{
+  Fsm_Fsm_t	*subSystemFsm	= AmcSubsystemReadFsm(subSystem);	
+  Ntk_Network_t *network	= Fsm_FsmReadNetwork(subSystemFsm);
+  mdd_manager	*mddManager	= Ntk_NetworkReadMddManager(network);
+  graph_t	*partition	= Part_NetworkReadPartition(network);
+
+  mdd_t		*result;
+
+  array_t	*transitionRelationArray = Amc_AmcSubsystemReadRelationArray(subSystem);
+
+  if( transitionRelationArray == NIL(array_t) ) { 
+    /* Build the transition relation of this subsystem. */
+    st_table	*vertexTable	= AmcSubsystemReadVertexTable(subSystem);
+    st_generator		*stGen;
+    char			*latchName;
+
+    transitionRelationArray	= array_alloc(mdd_t *, 0);   
+    st_foreach_item(vertexTable, stGen, &latchName, NIL(char *)) {
+
+      Ntk_Node_t	*latch		= Ntk_NetworkFindNodeByName(network, latchName);
+      int		functionMddId	= Ntk_NodeReadMddId(Ntk_NodeReadShadow(latch));
+
+      char	*nameLatchDataInput	= Ntk_NodeReadName(Ntk_LatchReadDataInput(latch));
+      vertex_t	*ptrVertex	= Part_PartitionFindVertexByName(partition, nameLatchDataInput);
+
+      Mvf_Function_t	*nextStateFunction;
+      mdd_t         	*transitionRelation;
+      nextStateFunction		= Part_VertexReadFunction(ptrVertex);
+      transitionRelation	= Mvf_FunctionBuildRelationWithVariable(nextStateFunction,
+                                                                functionMddId);
+#ifdef AMC_DEBUG
+    {
+      int y, mddId; array_t *supportOfRelation;
+      fprintf(vis_stdout, "\nThe transition relation of the output function of the node : %s", latchName);
+      supportOfRelation = mdd_get_support(mddManager, transitionRelation);
+      arrayForEachItem(int, supportOfRelation, y, mddId) {
+        Ntk_Node_t *supportNode = Ntk_NetworkFindNodeByMddId(network, mddId);
+        fprintf(vis_stdout, "\n\tThe node in the support : %s", 
+                                       Ntk_NodeReadName(supportNode));
+      }
+    }
+#endif 
+
+      if( nextStateFunction == NIL(Mvf_Function_t) ) {
+         error_append("** amc error: Build partition before running approximate model checker.");
+         return NIL(mdd_t);
+      }
+
+      array_insert_last(mdd_t *, transitionRelationArray, transitionRelation);
+    } /* end of st_foreach_item */
+
+    /* Cache the transition relation of the subsystem. */
+    Amc_AmcSubsystemSetRelationArray(subSystem, transitionRelationArray);
+
+  } /* end of transition relation construction. */
+
+
+  /*
+   * Notice : The present and next state variable of a subsystem is identical
+   * to that of the original system. The subsystem carries the subset of the
+   * output functions of the original system.
+   */
+  if( quantificationMode == Amc_User_c ) {
+    /* result = Img_MultiwayLinearAndSmooth(mddManager, transitionRelationArray, quantifyVars,
+					 NIL(array_t)); */
+    if( AmcSubsystemReadNextStateVarSmoothen(subSystem) == NIL(mdd_t) ) {
+      result = Fsm_MddMultiwayAndSmooth(mddManager, transitionRelationArray, quantifyVars);
+      AmcSubsystemSetNextStateVarSmoothen(subSystem, result);
+    }
+    else {
+      result = AmcSubsystemReadNextStateVarSmoothen(subSystem);
+    }
+  }
+  else if( quantificationMode == Amc_PresentVars_c ) {
+    array_t	*presentVars	= Fsm_FsmReadPresentStateVars(subSystemFsm);
+    result = Fsm_MddMultiwayAndSmooth(mddManager, transitionRelationArray, presentVars);
+  }
+  else if( quantificationMode == Amc_NextVars_c ) {
+    array_t	*nextVars	= Fsm_FsmReadNextStateVars(subSystemFsm);
+    result = Fsm_MddMultiwayAndSmooth(mddManager, transitionRelationArray, nextVars);
+  }
+  else if( quantificationMode == Amc_InputVars_c ) {
+    array_t	*inputVars	= Fsm_FsmReadInputVars(subSystemFsm);
+    result = Fsm_MddMultiwayAndSmooth(mddManager, transitionRelationArray, inputVars);
+  }
+  else {
+    error_append("** amc error: Invalid quantification mode.");
+    return NIL(mdd_t);
+  }
+
+
+  return(result);
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Apply existential quantification to the array of subsystems.]
+
+  Description [Given an array of subsystems, the routine existentially 
+  quantifies the MDD variables from the transition relations of the subsystems.
+  The existential quantification is applied to the subsystems that hasn't
+  yet been taken into the optimal system. The optimal system is the group 
+  of subsystems that has been synchronously combined. 
+  There are four quantification modes;
+  <dl>
+  <dt> Amc_PresentVars_c
+  <dd> Existentially quantify present state variables. <p>
+
+  <dt> Amc_NextVars_c
+  <dd> Existentially quantify next state variables. <p>
+  
+  <dt> Amc_InputVars_c
+  <dd> Existentially quantify input variables. <p>
+
+  <dt> Amc_User_c
+  <dd> Existentially quantify variables provide by the user. In this
+       mode user has to provide the array of MDD IDs to the function. If
+       the user does not provide the array of MDD IDs, the function just
+       returns the transition relation of the subsystem. <p>
+  </dl>
+  The return value is the array of quantified result of the MDD 
+  representation of the transition relation.  ]
+  
+  SideEffects []
+
+  SeeAlso     [Amc_SubsystemInfo, Amc_AmcExistentialQuantifySubsystem]
+
+******************************************************************************/
+array_t *
+Amc_AmcExistentialQuantifySubsystemArray(
+  array_t			*subSystemArray,
+  Amc_SubsystemInfo_t		*currentSystem,
+  array_t			*quantifyVars,
+  Amc_QuantificationMode	quantificationMode)
+{
+  int i;
+  Amc_SubsystemInfo_t	*subSystem; 
+  mdd_t              	*quantifiedSystemMdd;
+  array_t		*quantifiedSystemMddArray = array_alloc(mdd_t *, 0);
+
+  if( (quantificationMode == Amc_User_c) && (quantifyVars == NIL(array_t)) ) {
+    error_append("** amc error: Subsystem has no output functions.");
+    return NIL(array_t);
+  }
+
+  arrayForEachItem(Amc_SubsystemInfo_t *, subSystemArray, i, subSystem) {
+    if( (!subSystem->takenIntoOptimal) && (i != currentSystem->takenIntoOptimal) ) {
+
+      quantifiedSystemMdd =
+	Amc_AmcExistentialQuantifySubsystem(subSystem, quantifyVars, 
+					    quantificationMode);
+      array_insert_last(mdd_t *, quantifiedSystemMddArray, quantifiedSystemMdd);
+    }
+  }
+
+  return(quantifiedSystemMddArray);
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [Read the fsm field of a Amc_SubsystemInfo]
+
+  SideEffects        []
+
+  SeeAlso            [Amc_SubsystemInfo]
+
+******************************************************************************/
+Fsm_Fsm_t *
+Amc_AmcSubsystemReadFsm(
+  Amc_SubsystemInfo_t *system)
+{
+  return AmcSubsystemReadFsm(system);
+} /* End of Amc_AmcSubsystemReadFsm */
+
+/**Function********************************************************************
+
+  Synopsis           [Set the fsm field of a Amc_SubsystemInfo]
+
+  SideEffects        []
+
+  SeeAlso            [Amc_SubsystemInfo_t]
+
+******************************************************************************/
+void
+Amc_AmcSubsystemSetFsm(
+  Amc_SubsystemInfo_t *system,
+  Fsm_Fsm_t *info)
+{
+  AmcSubsystemSetFsm(system, info);
+} /* End of Amc_AmcSubsystemReadFsm */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Read the transition relation field of the 
+  Amc_SubsystemInfo]
+
+  SideEffects        []
+
+  SeeAlso            [Amc_SubsystemInfo]
+
+******************************************************************************/
+array_t *
+Amc_AmcSubsystemReadRelationArray(
+  Amc_SubsystemInfo_t *system)
+{
+  return AmcSubsystemReadRelationArray(system);
+} /* End of Amc_AmcSubsystemReadTransitionRelation */
+
+/**Function********************************************************************
+
+  Synopsis           [Set the transition relation field of the 
+  Amc_SubsystemInfo]
+
+  SideEffects        []
+
+  SeeAlso            [Amc_SubsystemInfo_t]
+
+******************************************************************************/
+void
+Amc_AmcSubsystemSetRelationArray(
+  Amc_SubsystemInfo_t	*system,
+  array_t		*info)
+{
+  AmcSubsystemSetRelationArray(system, info);
+} /* End of Amc_AmcSubsystemSetTransitionRelation */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Read the nextStateVarSmoothen field of the 
+  Amc_SubsystemInfo]
+
+  Description 	     [nextStateVarSmoothen field contains the MDD of the 
+  transition relation with the next state variable existentially quantified.]
+
+  SideEffects        []
+
+  SeeAlso            [Amc_SubsystemInfo]
+
+******************************************************************************/
+mdd_t *
+Amc_AmcSubsystemReadNextStateVarSmoothen(
+  Amc_SubsystemInfo_t *system)
+{
+  return AmcSubsystemReadNextStateVarSmoothen(system);
+} /* End of Amc_AmcSubsystemReadNextStateVarSmooth */
+
+/**Function********************************************************************
+
+  Synopsis           [Set the nextStateVarSmoothen field of the 
+  Amc_SubsystemInfo]
+
+  SideEffects        []
+
+  SeeAlso            [Amc_SubsystemInfo_t]
+
+******************************************************************************/
+void
+Amc_AmcSubsystemSetNextStateVarSmoothen(
+  Amc_SubsystemInfo_t	*system,
+  mdd_t			*info)
+{
+  AmcSubsystemSetNextStateVarSmoothen(system, info);
+} /* End of Amc_AmcSubsystemSetNextStateVarSmooth */
+
+/**Function********************************************************************
+
+  Synopsis 	[Read the satisfyStates field of the Amc_SubsystemInfo_t]
+
+  SideEffects   []
+
+  SeeAlso       [Amc_SubsystemInfo_t]
+
+******************************************************************************/
+mdd_t *
+Amc_AmcSubsystemReadSatisfy(
+  Amc_SubsystemInfo_t *system)
+{
+  return AmcSubsystemReadSatisfy(system);
+} /* End of Amc_AmcSubsystemReadSatisfy */
+
+/**Function********************************************************************
+
+  Synopsis 	[Set the satisfyStates field of Amc_SubsystemInfo_t ]
+
+  Description   [satisfyStates field contains the MDD representation of the
+  super(sub)set of states satisfying given formula. The super(sub)set of states 
+  satisfying given formula is obtained by utilizing the information of 
+  the subsystem.] 
+
+  SideEffects   []
+
+  SeeAlso       [Amc_SubsystemInfo_t]
+
+******************************************************************************/
+void
+Amc_AmcSubsystemSetSatisfy(
+  Amc_SubsystemInfo_t *system,
+  mdd_t *data)
+{
+  AmcSubsystemSetSatisfy(system, data);
+} /* End of Amc_AmcSubsystemSetSatisfy */
+
+/**Function********************************************************************
+
+  Synopsis  	[Read the vertexTable field of the Amc_SubsystemInfo_t]
+
+  Description   [The vertexTable field of the subsystem is the hash table
+  of vertex names. Only the vertices contained in the subsystem is stored
+  in this table.]
+
+  SideEffects   []
+
+  SeeAlso       [Amc_SubsystemInfo_t]
+
+******************************************************************************/
+st_table *
+Amc_AmcSubsystemReadVertexTable(
+  Amc_SubsystemInfo_t *system)
+{
+  return AmcSubsystemReadVertexTable(system);
+} /* End of Amc_AmcSubsystemReadVertexTable */
+
+/**Function********************************************************************
+
+  Synopsis 	[Set the vertexTable field of Amc_SubsystemInfo_t ]
+
+  SideEffects   []
+
+  SeeAlso       [Amc_SubsystemInfo_t]
+
+******************************************************************************/
+void
+Amc_AmcSubsystemSetVertexTable(
+  Amc_SubsystemInfo_t *system,
+  st_table *data)
+{
+  AmcSubsystemSetVertexTable(system, data);
+} /* End of Amc_AmcSubsystemSetVertexTable */
+
+/**Function********************************************************************
+
+  Synopsis   	[Read the fanInTable field of the Amc_SubsystemInfo_t]
+
+  Description   [The fanInTable is the hash table of the subsystem index.
+  The subsystem index is the pointer value uniquely distinguishing subsystems.
+  The table contains the index of the subsystems whose component vertex
+  is one of the transitive fan-ins of the vertex in this subsystem.]
+
+  SideEffects   []
+
+  SeeAlso       [Amc_SubsystemInfo_t]
+
+******************************************************************************/
+st_table *
+Amc_AmcSubsystemReadFanInTable(
+  Amc_SubsystemInfo_t *system)
+{
+  return AmcSubsystemReadFanInTable(system);
+} /* End of Amc_AmcSubsystemReadFanInTable */
+
+/**Function********************************************************************
+
+  Synopsis 	[Set the fanInTable field of Amc_SubsystemInfo_t ]
+
+  SideEffects   []
+
+  SeeAlso       [Amc_SubsystemInfo_t]
+
+******************************************************************************/
+void
+Amc_AmcSubsystemSetFanInTable(
+  Amc_SubsystemInfo_t *system,
+  st_table *data)
+{
+  AmcSubsystemSetFanInTable(system, data);
+} /* End of Amc_AmcSubsystemSetFanInTable */
+
+/**Function********************************************************************
+
+  Synopsis 	[Read the fanOutTable field of the Amc_SubsystemInfo_t]
+
+  Description   [The fanOutTable is the hash table of the subsystem index.
+  The subsystem index is the pointer value uniquely distinguishing subsystems.
+  The table contains the index of the subsystems whose component vertex
+  is one of the transitive fan-outs of the vertex in this subsystem.]
+
+  SideEffects   []
+
+  SeeAlso       [Amc_SubsystemInfo_t]
+
+******************************************************************************/
+st_table *
+Amc_AmcSubsystemReadFanOutTable(
+  Amc_SubsystemInfo_t *system)
+{
+  return AmcSubsystemReadFanOutTable(system);
+} /* End of Amc_AmcSubsystemReadFanOutTable */
+
+/**Function********************************************************************
+
+  Synopsis 	[Set the fanOutTable field of Amc_SubsystemInfo_t ]
+
+  SideEffects   []
+
+  SeeAlso       [Amc_SubsystemInfo_t]
+
+******************************************************************************/
+void
+Amc_AmcSubsystemSetFanOutTable(
+  Amc_SubsystemInfo_t *system,
+  st_table *data)
+{
+  AmcSubsystemSetFanOutTable(system, data);
+} /* End of Amc_AmcSubsystemSetFanOutTable */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Read the MethodSpecific field of Amc_SubsystemInfo_t]
+
+  Description        [The method specific field may hold any value(s) that are
+  specific to the various methods.]
+
+  SideEffects        []
+
+  SeeAlso            [Amc_SubsystemInfo_t]
+
+******************************************************************************/
+char *
+Amc_AmcSubsystemReadMethodSpecificData(
+  Amc_SubsystemInfo_t *system)
+{
+  return AmcSubsystemReadMethodSpecificData(system);
+} /* End of Amc_AmcSubsystemReadMethodSpecificData */
+
+/**Function********************************************************************
+
+  Synopsis           [Set the MethodSpecific field of Amc_SubsystemInfo_t]
+
+  SideEffects        []
+
+  SeeAlso            [Amc_SubsystemInfo_t]
+
+******************************************************************************/
+void 
+Amc_AmcSubsystemSetMethodSpecificData(
+  Amc_SubsystemInfo_t *system,
+  char                *data)
+{
+  AmcSubsystemSetMethodSpecificData(system, data);
+} /* End of Amc_AmcSubsystemSetMethodSpecificData */
+
+
+
+/**Function********************************************************************
+
+  Synopsis 	[Read the initial states from Amc_Info_t]
+
+  SideEffects   []
+
+  SeeAlso       [Amc_Info_t]
+
+******************************************************************************/
+mdd_t *
+Amc_AmcReadInitialStates(
+  Amc_Info_t *system)
+{
+  return AmcReadInitialStates(system);
+} /* End of Amc_AmcReadInitialStates */
+
+/**Function********************************************************************
+
+  Synopsis 	[Sets the initial states from Amc_Info_t]
+
+  SideEffects   []
+
+  SeeAlso       [Amc_Info_t]
+
+******************************************************************************/
+void
+Amc_AmcSetInitialStates(
+  Amc_Info_t	*system,
+  mdd_t		*data)
+{
+  AmcSetInitialStates(system, data);
+} /* End of Amc_AmcSetInitialStates */
+
+/**Function********************************************************************
+
+  Synopsis 	[Read the optimal system from Amc_Info_t]
+
+  SideEffects   []
+
+  SeeAlso       [Amc_Info_t]
+
+******************************************************************************/
+Amc_SubsystemInfo_t *
+Amc_AmcReadOptimalSystem(
+  Amc_Info_t *system)
+{
+  return AmcReadOptimalSystem(system);
+} /* End of Amc_AmcReadOptimalSystem */
+
+/**Function********************************************************************
+
+  Synopsis 	[Sets the optimal system from Amc_Info_t]
+
+  SideEffects   []
+
+  SeeAlso       [Amc_Info_t]
+
+******************************************************************************/
+void
+Amc_AmcSetOptimalSystem(
+  Amc_Info_t *system,
+  Amc_SubsystemInfo_t    *data)
+{
+  AmcSetOptimalSystem(system, data);
+} /* End of Amc_AmcSetOptimalSystem */
+
+/**Function********************************************************************
+
+  Synopsis 	[Read the MethodData from Amc_Info_t]
+
+  SideEffects   []
+
+  SeeAlso       [Amc_Info_t]
+
+******************************************************************************/
+void *
+Amc_AmcReadMethodData(
+  Amc_Info_t *system)
+{
+  return AmcReadMethodData(system);
+} /* End of Amc_AmcReadMethodData */
+
+/**Function********************************************************************
+
+  Synopsis 	[Sets the MethodData from Amc_Info_t]
+
+  SideEffects   []
+
+  SeeAlso       [Amc_Info_t]
+
+******************************************************************************/
+void
+Amc_AmcSetMethodData(
+  Amc_Info_t	*system,
+  void		*data)
+{
+  AmcSetMethodData(system, data);
+} /* End of Amc_AmcSetMethodData */
+
+
+
+/**Function********************************************************************
+
+  Synopsis           [Allocate and initialize a Amc_SubsystemInfo_t]
+
+  SideEffects        []
+
+  SeeAlso            [Amc_AmcSubsystemFree]
+
+******************************************************************************/
+Amc_SubsystemInfo_t *
+Amc_AmcSubsystemAllocate(void)
+{
+  Amc_SubsystemInfo_t *result;
+
+  result = ALLOC(Amc_SubsystemInfo_t, 1);
+
+  return result;
+} /* End of Amc_SubsystemAllocate */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Create a subsystem.]
+
+  Description        [Create and initialize a subsystem.]
+
+  SideEffects        []
+
+  SeeAlso            []
+
+******************************************************************************/
+Amc_SubsystemInfo_t *
+Amc_AmcSubsystemCreate(
+  Fsm_Fsm_t             *fsm,
+  mdd_t                 *satisfyStates,
+  st_table              *vertexTable,
+  st_table		*fanInTable,
+  st_table 		*fanOutTable)
+{
+  Amc_SubsystemInfo_t *result;
+
+  result                    	= ALLOC(Amc_SubsystemInfo_t, 1);
+  result->fsm               	= fsm;
+  result->relationArray		= NIL(array_t);
+  result->nextStateVarSmoothen	= NIL(mdd_t);
+  result->satisfyStates     	= satisfyStates;
+  result->vertexTable       	= vertexTable;
+  result->fanInTable        	= fanInTable;
+  result->fanOutTable       	= fanOutTable;
+  result->takenIntoOptimal  	= 0;  /* Initialize to 0 */
+  result->methodSpecificData 	= NIL(char);
+
+  return result;
+} 
+
+/**Function********************************************************************
+
+  Synopsis           [Duplicate a subsystem.]
+
+  SideEffects        []
+
+  SeeAlso            [Amc_AmcSubsystemAllocate]
+
+******************************************************************************/
+Amc_SubsystemInfo_t *
+Amc_AmcSubsystemDuplicate(
+  Ntk_Network_t       *network, 
+  Amc_SubsystemInfo_t *subSystem)
+{
+  Fsm_Fsm_t	*fsm;
+  mdd_t		*satisfyStates	= NIL(mdd_t);
+  st_table      *vertexTable	= NIL(st_table);
+  st_table	*fanInTable	= NIL(st_table);
+  st_table	*fanOutTable	= NIL(st_table);
+  graph_t       *partition	= Part_NetworkReadPartition(network);
+
+  if(subSystem->satisfyStates != NIL(mdd_t)) {
+    satisfyStates = mdd_dup(subSystem->satisfyStates);
+  }
+  if(subSystem->vertexTable != NIL(st_table)) {
+    vertexTable = st_copy(subSystem->vertexTable);
+  }
+  if(subSystem->fanInTable != NIL(st_table)) {
+    fanInTable = st_copy(subSystem->fanInTable);
+  }
+  if(subSystem->fanOutTable != NIL(st_table)) {
+    fanOutTable = st_copy(subSystem->fanOutTable);
+  }
+
+  fsm = Fsm_FsmCreateSubsystemFromNetwork(network, partition, vertexTable,
+	FALSE, 0);
+
+  return(Amc_AmcSubsystemCreate(fsm, satisfyStates, vertexTable, fanInTable, fanOutTable));
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis           [Free a subsystem.]
+
+  Description        [Frees a subsystem plus associated fields except the 
+  partition. This is to reuse the partition without recreating it.]
+
+  SideEffects        []
+
+  SeeAlso            [Amc_AmcSubsystemAllocate]
+
+******************************************************************************/
+void
+Amc_AmcSubsystemFree(
+  Amc_SubsystemInfo_t *subSystem)
+{
+  st_table 	*vertexTable;
+  st_table	*fanInTable, *fanOutTable;
+
+  /* Do not free partition associated to this fsm */
+  if (AmcSubsystemReadFsm(subSystem) != NIL(Fsm_Fsm_t)) {
+    Fsm_FsmSubsystemFree(AmcSubsystemReadFsm(subSystem));
+  } 
+
+  if (AmcSubsystemReadRelationArray(subSystem) != NIL(array_t)) {
+    array_t *transitionRelationArray = AmcSubsystemReadRelationArray(subSystem);
+    mdd_t   *transitionRelation;
+    int		i;
+    arrayForEachItem(mdd_t *, transitionRelationArray, i, transitionRelation) {
+      mdd_free(transitionRelation); 
+    } 
+    array_free(transitionRelationArray);
+  }
+
+  if (AmcSubsystemReadNextStateVarSmoothen(subSystem) != NIL(mdd_t)) {
+    mdd_free(AmcSubsystemReadNextStateVarSmoothen(subSystem));
+  }
+
+  if (AmcSubsystemReadSatisfy(subSystem) != NIL(mdd_t)) {
+    mdd_free(AmcSubsystemReadSatisfy(subSystem));
+  } 
+
+  /* Do not free vertex!! */
+  vertexTable = AmcSubsystemReadVertexTable(subSystem);
+  if (vertexTable != NIL(st_table)) {
+    st_free_table(vertexTable);
+  }
+
+  fanInTable = AmcSubsystemReadFanInTable(subSystem);
+  if (fanInTable != NIL(st_table)) {
+    st_free_table(fanInTable);
+  }
+
+  fanOutTable = AmcSubsystemReadFanOutTable(subSystem);
+  if (fanOutTable != NIL(st_table)) {
+    st_free_table(fanOutTable);
+  }
+
+
+  FREE(subSystem);
+} 
+
+/**Function********************************************************************
+
+  Synopsis           [Free a subsystem.]
+
+  Description        [Frees a subsystem including the associated partition.]
+
+  SideEffects        []
+
+  SeeAlso            [Amc_AmcSubsystemAllocate]
+
+******************************************************************************/
+void
+Amc_AmcSubsystemFreeAlsoPartition(
+  Amc_SubsystemInfo_t *subSystem)
+{
+  st_table      *vertexTable;
+  st_table      *fanInTable, *fanOutTable;
+
+  /* Do not free partition associated to this fsm */
+  if (AmcSubsystemReadFsm(subSystem) != NIL(Fsm_Fsm_t)) {
+    Fsm_FsmFree(AmcSubsystemReadFsm(subSystem));
+  } 
+
+  if (AmcSubsystemReadRelationArray(subSystem) != NIL(array_t)) {
+    array_t *transitionRelationArray = AmcSubsystemReadRelationArray(subSystem);
+    mdd_t   *transitionRelation;
+    int         i;
+    arrayForEachItem(mdd_t *, transitionRelationArray, i, transitionRelation) {
+      mdd_free(transitionRelation); 
+    } 
+    array_free(transitionRelationArray);
+  }
+
+  if (AmcSubsystemReadNextStateVarSmoothen(subSystem) != NIL(mdd_t)) {
+    mdd_free(AmcSubsystemReadNextStateVarSmoothen(subSystem));
+  }
+
+  if (AmcSubsystemReadSatisfy(subSystem) != NIL(mdd_t)) {
+    mdd_free(AmcSubsystemReadSatisfy(subSystem));
+  } 
+
+  /* Do not free vertex!! */
+  vertexTable = AmcSubsystemReadVertexTable(subSystem);
+  if (vertexTable != NIL(st_table)) {
+    st_free_table(vertexTable);
+  }
+
+  fanInTable = AmcSubsystemReadFanInTable(subSystem);
+  if (fanInTable != NIL(st_table)) {
+    st_free_table(fanInTable);
+  }
+
+  fanOutTable = AmcSubsystemReadFanOutTable(subSystem);
+  if (fanOutTable != NIL(st_table)) {
+    st_free_table(fanOutTable);
+  }
+
+
+  FREE(subSystem);
+} 
+
+
+
+
+/**Function********************************************************************
+
+  Synopsis           [Combine two subsystems and return the resulting
+  subsystem.]
+
+  Description        [Take the synchronous product of two subsystems. The routine
+  returns resulting subsystem. If either one of the subsystem is NIL return
+  the other. It is an error to pass two NIL pointers. Either one has to be
+  a subsystem.]
+
+  SideEffects        []
+
+  SeeAlso            []
+
+******************************************************************************/
+Amc_SubsystemInfo_t *
+Amc_CombineSubsystems(
+  Ntk_Network_t		*network,
+  Amc_SubsystemInfo_t	*subSystem1,
+  Amc_SubsystemInfo_t   *subSystem2)
+{
+  Amc_SubsystemInfo_t 	*subSystemInfo;
+  Amc_SubsystemInfo_t   *subSystem;
+  st_table		*vertexTable, *vertexTable1, *vertexTable2;
+  st_table		*fanInTable = NIL(st_table);
+  st_table 		*fanOutTable = NIL(st_table);
+  st_table		*fanInTable1, *fanInTable2;
+  st_table		*fanOutTable1, *fanOutTable2;
+  Ntk_Node_t    	*latch;  
+  graph_t		*partition = Part_NetworkReadPartition(network);
+  Fsm_Fsm_t		*fsm;
+  lsGen         	gen;
+  st_generator          *stGen;
+
+  /* If two subsystem are identical return error */
+  if(subSystem1 == subSystem2) {
+    error_append("** amc error: illegal subsystem combination");
+    return NIL(Amc_SubsystemInfo_t);
+  }
+  /* If two subsystem are NIL return error */
+  if( (subSystem1 == NIL(Amc_SubsystemInfo_t)) && 
+      (subSystem2 == NIL(Amc_SubsystemInfo_t)) ) {
+    error_append("** amc error: illegal subsystem combination");
+    return NIL(Amc_SubsystemInfo_t);
+  }
+
+  /* If either of two subsystem is NIL return copy of the other */
+  if(subSystem1 == NIL(Amc_SubsystemInfo_t)) {
+    return Amc_AmcSubsystemDuplicate(network, subSystem2);
+  }
+  if(subSystem2 == NIL(Amc_SubsystemInfo_t)) {
+    return Amc_AmcSubsystemDuplicate(network, subSystem1);
+  }
+
+  vertexTable  = st_init_table(strcmp, st_strhash); 
+  vertexTable1 = AmcSubsystemReadVertexTable(subSystem1);
+  vertexTable2 = AmcSubsystemReadVertexTable(subSystem2);
+
+  Ntk_NetworkForEachLatch(network, gen, latch) {
+    char *latchName = Ntk_NodeReadName(latch);
+    if( st_lookup(vertexTable1, latchName, (char **)0) || 
+        st_lookup(vertexTable2, latchName, (char **)0) ) {
+
+      st_insert(vertexTable, latchName, (char *)0);
+
+    }
+  } /* end of Ntk_NetworkForEachLatch */
+
+
+  fanInTable1 = AmcSubsystemReadFanInTable(subSystem1);
+  fanInTable2 = AmcSubsystemReadFanInTable(subSystem2);
+  if( (fanInTable1 != NIL(st_table)) && (fanInTable2 != NIL(st_table)) ) { 
+
+    fanInTable  = st_init_table(st_ptrcmp, st_ptrhash); 
+
+    st_foreach_item(fanInTable1, stGen, &subSystem, NIL(char *)) {
+      st_insert(fanInTable, (char *)subSystem, (char *)0);
+    }
+    st_foreach_item(fanInTable2, stGen, &subSystem, NIL(char *)) {
+      st_insert(fanInTable, (char *)subSystem, (char *)0);
+    }
+  }
+
+
+  fanOutTable1 = AmcSubsystemReadFanOutTable(subSystem1);
+  fanOutTable2 = AmcSubsystemReadFanOutTable(subSystem2);
+
+  if( (fanOutTable1 != NIL(st_table)) && (fanOutTable2 != NIL(st_table)) ) { 
+
+    fanOutTable  = st_init_table(st_ptrcmp, st_ptrhash); 
+
+    st_foreach_item(fanInTable1, stGen, &subSystem, NIL(char *)) {
+      st_insert(fanOutTable, subSystem, (char *)0);
+    }
+    st_foreach_item(fanInTable2, stGen, &subSystem, NIL(char *)) {
+      st_insert(fanOutTable, subSystem, (char *)0);
+    }
+  }
+
+
+  fsm = Fsm_FsmCreateSubsystemFromNetwork(network, partition, vertexTable,
+	FALSE, 0);
+
+  subSystemInfo = Amc_AmcSubsystemCreate(fsm, NIL(mdd_t), vertexTable, 
+                                            fanInTable, fanOutTable);
+
+  /* Does not free tables */
+
+  return(subSystemInfo);
+}
+
+#ifdef AMC_DEBUG_
+/**Function********************************************************************
+
+  Synopsis    [Returns the imageInfo struct stored by the FSM; creates if
+  necessary.]
+
+  Description [_Obsolete_]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoInitialize Fsm_FsmReadImageInfo]
+
+******************************************************************************/
+Img_ImageInfo_t *
+Amc_AmcReadOrCreateImageInfo(
+  Fsm_Fsm_t *fsm)
+{
+  Img_ImageInfo_t *imageInfo;
+  if( Fsm_FsmReadImageInfo(fsm) == NIL(Img_ImageInfo_t)) {
+    array_t *dummyInputVars 	= array_alloc(int, 0);
+    imageInfo = Img_ImageInfoInitialize(Fsm_FsmReadPartition(fsm),
+                                        Fsm_FsmReadNextStateFunctions(fsm),
+                                        Fsm_FsmReadPresentStateVars(fsm),
+                                        Fsm_FsmReadNextStateVars(fsm),
+                                        dummyInputVars,
+                                        Fsm_FsmReadNetwork(fsm),
+                                        Img_Default_c, Img_Both_c);
+    Fsm_FsmSetImageInfo(fsm, imageInfo);
+    array_free(dummyInputVars);
+  }
+  return (imageInfo);
+}
+#endif
+
+/**Function********************************************************************
+
+  Synopsis    [Model check formula with approxmiations.]
+
+  Description [The routine evaluates given formula with approximations.]
+  
+  Comment     []
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t * 
+Amc_AmcEvaluateCTLFormula(
+  Amc_SubsystemInfo_t   *subSystem,
+  array_t		*subSystemArray,
+  Ctlp_Formula_t        *ctlFormula, 
+  mdd_t                 *fairStates, 
+  Fsm_Fairness_t        *fairCondition, 
+  mdd_t                 *modelCareStates,
+  boolean               lowerBound,
+  array_t		*quantifyVars,
+  Mc_VerbosityLevel     verbosity,
+  Mc_DcLevel            dcLevel )
+{
+  Fsm_Fsm_t     *modelFsm = Amc_AmcSubsystemReadFsm(subSystem);
+
+  mdd_t  *leftMdd  = NIL(mdd_t);
+  mdd_t  *rightMdd = NIL(mdd_t);
+  mdd_t  *result   = NIL(mdd_t);
+  mdd_t  *tmpResult = NIL(mdd_t);
+
+  mdd_t *ctlFormulaStates = Ctlp_FormulaObtainStates(ctlFormula );
+  mdd_manager *mddMgr = Fsm_FsmReadMddManager(modelFsm);
+  mdd_t *careStates = NIL(mdd_t);
+  
+
+  if (ctlFormulaStates) {
+    return ctlFormulaStates;
+  }
+  
+  { 
+    Ctlp_Formula_t *leftChild = Ctlp_FormulaReadLeftChild(ctlFormula);
+    if (leftChild) {
+      leftMdd = Amc_AmcEvaluateCTLFormula(subSystem, subSystemArray, leftChild, fairStates, fairCondition, 
+                                   modelCareStates, lowerBound, quantifyVars, verbosity, dcLevel); 
+      if (!leftMdd) 
+        return NIL(mdd_t);
+    }
+  }
+
+  {
+    Ctlp_Formula_t *rightChild = Ctlp_FormulaReadRightChild(ctlFormula);
+    if (rightChild) {
+      rightMdd = Amc_AmcEvaluateCTLFormula(subSystem, subSystemArray, rightChild, fairStates, fairCondition, 
+                                    modelCareStates, lowerBound, quantifyVars, verbosity, dcLevel);
+      if (!rightMdd ) 
+        return NIL(mdd_t);
+    }
+  }
+
+  careStates = (modelCareStates != NIL(mdd_t)) ?  mdd_dup(modelCareStates) : mdd_one(mddMgr);
+  switch ( Ctlp_FormulaReadType( ctlFormula ) ) {
+
+    case Ctlp_ID_c : tmpResult = AmcModelCheckAtomicFormula( modelFsm, ctlFormula ); 
+
+       /* #AMC : Obtain lowerbound of the constraint set. */
+      if(0 && lowerBound) { /*Chao: this is not correct! consider !EF(!p) */
+        array_t *quantifyPresentVars     = array_fetch(array_t *, quantifyVars, 0);
+        int	numOfPresentQuantifyVars = array_n(quantifyPresentVars);
+        /* 
+         * Currently VIS does not allow primary input as the variable of 
+         * the atomic propositions. 
+         */
+        if(numOfPresentQuantifyVars > 0) {
+           result = mdd_consensus(mddMgr, tmpResult, quantifyPresentVars);  
+           mdd_free(tmpResult);
+        }
+        else
+           result = tmpResult;
+        }
+      else
+        result = tmpResult;
+
+      break;
+
+    case Ctlp_TRUE_c : result = mdd_one( mddMgr ); break;
+    case Ctlp_FALSE_c : result = mdd_zero( mddMgr ); break;
+
+    case Ctlp_NOT_c : result = mdd_not( leftMdd ); break;
+    case Ctlp_EQ_c : result = mdd_xnor( leftMdd, rightMdd ); break;
+    case Ctlp_XOR_c : result = mdd_xor( leftMdd, rightMdd ); break;
+    case Ctlp_THEN_c : result = mdd_or( leftMdd, rightMdd, 0, 1 ); break;
+    case Ctlp_AND_c: result = mdd_and( leftMdd, rightMdd, 1, 1 ); break;
+    case Ctlp_OR_c: result = mdd_or( leftMdd, rightMdd, 1, 1 ); break;
+
+    case Ctlp_EX_c: 
+      result = Amc_AmcEvaluateEXFormula( modelFsm, subSystemArray, subSystem, leftMdd, fairStates, 
+					careStates, lowerBound, quantifyVars, verbosity, dcLevel );
+      break;
+
+    case Ctlp_EU_c: {
+      array_t *onionRings = array_alloc( mdd_t *, 0 );
+      result = Amc_AmcEvaluateEUFormula( modelFsm, subSystemArray, subSystem, leftMdd, rightMdd, fairStates, 
+                                    careStates, onionRings, lowerBound, quantifyVars, verbosity, dcLevel );
+      Ctlp_FormulaSetDbgInfo( ctlFormula, (void *) onionRings, McFormulaFreeDebugData); 
+      break;
+    }
+
+    case Ctlp_EG_c: {
+      array_t *arrayOfOnionRings = array_alloc( array_t *, 0 );
+      result = Amc_AmcEvaluateEGFormula( modelFsm, subSystemArray, subSystem, leftMdd, 
+					fairStates, fairCondition, careStates, 
+					arrayOfOnionRings, lowerBound, quantifyVars, verbosity, dcLevel );
+      Ctlp_FormulaSetDbgInfo( ctlFormula, (void *) arrayOfOnionRings, McFormulaFreeDebugData); 
+      break;
+    }
+
+    default: fail("Encountered unknown type of CTL formula\n");
+  }
+
+
+  Ctlp_FormulaSetStates( ctlFormula, result );
+
+  mdd_free( careStates );
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    	[Evaluate EX formula with approximations.]
+
+  Description 	[The routine evaluates EX formula with approximations. The 
+  routine is used both to obtain lower- and upper- bound of the exact preimage.
+
+  Chao: Let's use the following symbols to represent the present-state vars,
+  next-state vars, and the input vars:
+    s        -- Present-State Vars
+    t        -- Next-State Vars
+    x        -- Input Vars
+    s_A,t_A  -- PS or NS vars in the abstract model
+    s_R,t_R  -- PS or NS vars in the remaining models
+    T        -- Transition Relation of the concrete model, T = T_A * T_R
+    T_A,T_R  -- TR of the abstract model or the remaining models
+  
+  The upper-bound EX computation is
+    \exist  (s_R) ( \exist (t,x)   (T_A(s,x,t_A)  * C(t))                )
+
+  The lower-bound EX computation is
+    \forall (s_R) ( \exist (t_A,x) ( T_A(s,x,t_A) * (\forall (t_R) C(t)) )
+  ]
+
+  SideEffects 	[]
+
+  SeeAlso       [AmcInitializeQuantifyVars]
+
+******************************************************************************/
+
+mdd_t *
+Amc_AmcEvaluateEXFormula(
+  Fsm_Fsm_t		*modelFsm,
+  array_t		*subSystemArray, 
+  Amc_SubsystemInfo_t   *subSystem,
+  mdd_t			*targetMdd,
+  mdd_t			*fairStates,
+  mdd_t			*careStates,
+  boolean		lowerBound,
+  array_t		*quantifyVars,
+  Mc_VerbosityLevel	verbosity,
+  Mc_DcLevel		dcLevel )
+{
+  /* 
+   * The care set consists of the passed careStates 
+   */
+  mdd_t *toCareSet = mdd_dup( careStates );
+
+  mdd_t *fromLowerBound;
+  mdd_t *fromUpperBound;
+  mdd_t *result = NIL(mdd_t);
+  mdd_t *tmpResult;
+  mdd_manager *mddManager = Fsm_FsmReadMddManager( modelFsm );
+  array_t *quantifyPresentVars = array_fetch(array_t *, quantifyVars, 0);
+  
+  Img_ImageInfo_t * imageInfo;
+
+  assert(quantifyPresentVars != NIL(array_t));
+
+  imageInfo = Fsm_FsmReadOrCreateImageInfo(modelFsm, 1, 1);
+
+  if ( dcLevel == McDcLevelRchFrontier_c ) {
+    /*
+     * The lower bound is the conjunction of the fair states,
+     * the target states, and the care states.
+     */
+    mdd_t *tmpMdd = mdd_and( targetMdd, fairStates, 1, 1 );
+    fromLowerBound = mdd_and( tmpMdd, careStates, 1, 1 );
+    mdd_free( tmpMdd );
+    /* 
+     * The upper bound is the OR of the lower bound with the 
+     * complement of the care states.
+     */
+    fromUpperBound = mdd_or( fromLowerBound, careStates, 1, 0 );
+  }
+  else {
+    /*
+     * The lower bound is the conjunction of the fair states,
+     * and the target states.
+     */
+    fromLowerBound = mdd_and( targetMdd, fairStates, 1, 1 );
+    /*
+     * The upper bound is the same as the lower bound.
+     */
+    fromUpperBound = mdd_dup( fromLowerBound );
+  }
+
+
+  /***************************************************************************
+   * compute C1(s) =
+   *    C(s)                         for upper-bound EX computation
+   *    ( \forall (s_R) C(s) )       for lower-bound EX computation
+   ***************************************************************************/
+  if (lowerBound) {
+      mdd_t *mdd1, *mdd2;
+      mdd1 = fromLowerBound;
+      mdd2 = fromUpperBound;
+      if (array_n(quantifyPresentVars) > 0) {
+	fromLowerBound = mdd_consensus(mddManager, fromLowerBound,
+				       quantifyPresentVars);
+      } else {
+	fromLowerBound = mdd_dup(fromLowerBound);
+      }
+      if (mdd_equal(mdd1, mdd2)) {
+	fromUpperBound = mdd_dup(fromLowerBound);
+      }else {
+	if (array_n(quantifyPresentVars) > 0) {
+	  fromUpperBound = mdd_consensus(mddManager, fromUpperBound,
+					 quantifyPresentVars);
+	} else {
+	  fromUpperBound = mdd_dup(fromUpperBound);
+	}
+      }
+      mdd_free(mdd1);
+      mdd_free(mdd2);
+  }
+
+  /***************************************************************************
+   * Compute \exist (t,x) ( T_A(s,x,t_A) * C1(t) ), where
+   *    C1(t) = C(t)                      for upper-bound EX
+   *    C1(t) = (\forall (t_R) C(t) )     for lower-bound EX
+   ***************************************************************************/
+  tmpResult = Img_ImageInfoComputeBwdWithDomainVars( imageInfo,
+                                                     fromLowerBound,
+                                                     fromUpperBound,
+                                                     toCareSet );
+
+  /***************************************************************************
+   * Compute the final result
+   *    \exist  (s_R)  (tmpResult(s))      for upper-bound EX
+   *    \forall (s_R)  (tmpResult(s))      for lower-bound EX
+   **************************************************************************/
+  if (lowerBound) {
+    if (array_n(quantifyPresentVars) > 0) {
+      result = mdd_consensus(mddManager, tmpResult, quantifyPresentVars);
+    } else {
+      result = mdd_dup(tmpResult);
+    }
+  }else {
+    result = mdd_dup(tmpResult);
+    /*  result = mdd_smooth(mddManager, tmpResult, quantifyPresentVars);*/
+  } 
+  mdd_free(tmpResult);
+  
+  mdd_free( fromLowerBound );
+  mdd_free( fromUpperBound );
+  mdd_free( toCareSet );
+
+  if ( verbosity == McVerbosityMax_c ) {
+    static int refCount = 0;
+    mdd_manager *mddMgr = Fsm_FsmReadMddManager( modelFsm );
+    array_t *psVars	= Fsm_FsmReadPresentStateVars( modelFsm );
+    mdd_t *tmpMdd = careStates ? mdd_and( result, careStates, 1, 1 ) : mdd_dup( result );
+    fprintf(vis_stdout, "--EX called %d (bdd_size - %d)\n", ++refCount, mdd_size( result ) );
+    fprintf(vis_stdout, "--There are %.0f care states satisfying EX formula\n", 
+            mdd_count_onset(  mddMgr, tmpMdd, psVars ) ); 
+    mdd_free(tmpMdd);
+  }
+
+  return result;
+}
+
+#if 0
+/* this is the original (buggy) version */
+mdd_t *
+Amc_AmcEvaluateEXFormula_Old(
+  Fsm_Fsm_t		*modelFsm,
+  array_t		*subSystemArray, 
+  Amc_SubsystemInfo_t   *subSystem,
+  mdd_t			*targetMdd,
+  mdd_t			*fairStates,
+  mdd_t			*careStates,
+  boolean		lowerBound,
+  array_t		*quantifyVars,
+  Mc_VerbosityLevel	verbosity,
+  Mc_DcLevel		dcLevel )
+{
+  /* 
+   * The care set consists of the passed careStates 
+   */
+  mdd_t *toCareSet = mdd_dup( careStates );
+
+  mdd_t *fromLowerBound;
+  mdd_t *fromUpperBound;
+  mdd_t *result = NIL(mdd_t);
+  mdd_t *tmpResult;
+
+  Img_ImageInfo_t * imageInfo;
+
+  imageInfo = Fsm_FsmReadOrCreateImageInfo(modelFsm, 1, 1);
+
+  /*
+   * this condition will never  be true; we didnt find it to be 
+   * especially effective, are avoiding using it for now. later
+   * we may add a McDcLevelMax+1 field which will allow us to use it
+   *
+   */
+  if ( dcLevel > McDcLevelRchFrontier_c ) {
+    /*
+     * The lower bound is the conjunction of the fair states,
+     * the target states, and the care states.
+     */
+    mdd_t *tmpMdd = mdd_and( targetMdd, fairStates, 1, 1 );
+    fromLowerBound = mdd_and( tmpMdd, careStates, 1, 1 );
+    mdd_free( tmpMdd );
+    /* 
+     * The upper bound is the OR of the lower bound with the 
+     * complement of the care states.
+     */
+    fromUpperBound = mdd_or( fromLowerBound, careStates, 1, 0 );
+  }
+  else {
+    /*
+     * The lower bound is the conjunction of the fair states,
+     * and the target states.
+     */
+    fromLowerBound = mdd_and( targetMdd, fairStates, 1, 1 );
+    /*
+     * The upper bound is the same as the lower bound.
+     */
+    fromUpperBound = mdd_dup( fromLowerBound );
+  }
+
+  /* #AMC : */
+#ifdef AMC_DEBUG
+  if(lowerBound) {
+    /* 
+     * Sanity check. The set to compute a preimage from should only contain the present
+     * state variables of the subsystem.
+     */
+    {
+      mdd_manager       *mddManager	= Fsm_FsmReadMddManager( modelFsm );
+      Ntk_Network_t	*network	= Fsm_FsmReadNetwork(modelFsm);
+      array_t		*supportArray	= mdd_get_support(mddManager, fromLowerBound);
+      st_table		*vertexTable	= Amc_AmcSubsystemReadVertexTable(subSystem);
+      int 		i, varId;
+
+      fprintf(vis_stdout, "\n#AMC : Sanity check of the support of the constraint set");
+      arrayForEachItem(int, supportArray, i, varId) {
+        Ntk_Node_t  *node = Ntk_NetworkFindNodeByMddId(network, varId);
+        char *latchName = Ntk_NodeReadName(node); 
+        fprintf(vis_stdout, "\n#  fromLowerBound -- Node : %s", latchName);
+      }
+
+      arrayForEachItem(int, supportArray, i, varId) {
+        char *latchName = Ntk_NodeReadName(Ntk_NetworkFindNodeByMddId(network, varId)); 
+        if( !st_lookup(vertexTable, latchName, (char **)0 )) {
+          fprintf(vis_stdout, "\n** amc error : Whoops!! Something's wrong in lowerbound routine.");
+          fflush(vis_stdout); 
+        }
+      } /* end of arrayForEachItem */
+    }
+  } /* end of if(lowerBound) */
+#endif
+
+  tmpResult = Img_ImageInfoComputeBwdWithDomainVars( imageInfo,
+                                                     fromLowerBound,
+                                                     fromUpperBound,
+                                                     toCareSet );
+#ifdef AMC_DEBUG
+    {
+      Ntk_Network_t	*network	= Fsm_FsmReadNetwork(modelFsm);
+      mdd_manager 	*mddManager	= Fsm_FsmReadMddManager( modelFsm );
+      array_t		*supportArray	= mdd_get_support(mddManager, tmpResult);
+      int 		i, varId;
+
+      fprintf(vis_stdout, "\n#AMC : Sanity check of the support of the preimage");
+      arrayForEachItem(int, supportArray, i, varId) {
+        Ntk_Node_t  *node = Ntk_NetworkFindNodeByMddId(network, varId);
+        char *latchName = Ntk_NodeReadName(node); 
+        fprintf(vis_stdout, "\n## The preimage contains the node : %s", latchName);
+	if( Ntk_NodeTestIsLatch(node) ) 
+          fprintf(vis_stdout, "\n##  The node is a latch");
+	else
+          fprintf(vis_stdout, "\n##  The node is not a latch");
+
+      } /* end of arrayForEachItem */
+    }
+#endif
+
+  /* #AMC : */
+  if(lowerBound) {
+    mdd_manager *mddManager	  = Fsm_FsmReadMddManager( modelFsm );
+    array_t 	*quantifyNextVars = array_fetch(array_t *, quantifyVars, 1);
+    array_t 	*exQuantifiedSystemMddArray; 
+
+    /* 
+     * Existential abstraction of next state variables from subsystems that are
+     * not currently in consideration. Each subsystem has disjoint next state
+     * functions, hence we distribute existential abstraction over subsystems.
+     */
+
+    exQuantifiedSystemMddArray =
+      Amc_AmcExistentialQuantifySubsystemArray(subSystemArray, subSystem,
+					       quantifyNextVars, Amc_User_c);
+
+    /* 
+     * Universal abstraction of present state and input variables from
+     * subsystems that are not currently in consideration. 
+     */
+    {
+      array_t 	*quantifyPresentVars = array_fetch(array_t *, quantifyVars, 0);
+      array_t 	*quantifyInputVars   = array_fetch(array_t *, quantifyVars, 2);
+      array_t	*consensusVarArray   = array_join(quantifyPresentVars,
+						  quantifyInputVars);
+      mdd_t	*interResult	     = mdd_one( mddManager );
+      mdd_t	*subMdd;
+      int	i;
+
+      array_insert_last(mdd_t *, exQuantifiedSystemMddArray, tmpResult);
+      arrayForEachItem(mdd_t *, exQuantifiedSystemMddArray, i, subMdd) {
+        mdd_t *cResult = mdd_consensus(mddManager, subMdd, consensusVarArray); 
+        result = mdd_and(cResult, interResult, 1, 1); 
+        mdd_free(cResult); mdd_free(interResult);
+        interResult = result;
+
+        if( mdd_is_tautology(result, 0) ) break;
+      }
+
+      mdd_free(tmpResult);
+      /* Do not free Mdds. These are cached. */
+      array_free(exQuantifiedSystemMddArray);
+      array_free(consensusVarArray);
+    }
+
+
+  } /* end of if(lowerBound) */
+  else {
+   result = tmpResult;
+  } /* end of #AMC insertion */
+
+  mdd_free( fromLowerBound );
+  mdd_free( fromUpperBound );
+  mdd_free( toCareSet );
+
+  if ( verbosity == McVerbosityMax_c ) {
+    static int refCount = 0;
+    mdd_manager *mddMgr = Fsm_FsmReadMddManager( modelFsm );
+    array_t *psVars	= Fsm_FsmReadPresentStateVars( modelFsm );
+    mdd_t *tmpMdd = careStates ? mdd_and( result, careStates, 1, 1 ) : mdd_dup( result );
+    fprintf(vis_stdout, "--EX called %d (bdd_size - %d)\n", ++refCount, mdd_size( result ) );
+    fprintf(vis_stdout, "--There are %.0f care states satisfying EX formula\n", 
+            mdd_count_onset(  mddMgr, tmpMdd, psVars ) ); 
+    mdd_free(tmpMdd);
+  }
+
+  return result;
+}
+#endif
+
+/**Function********************************************************************
+
+  Synopsis    [Evaluate EU formula with approximations.]
+
+  Description []
+
+  Comment     []
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Amc_AmcEvaluateEUFormula( 
+  Fsm_Fsm_t *modelFsm,
+  array_t   *subSystemArray, 
+  Amc_SubsystemInfo_t   *subSystem,
+  mdd_t *invariantMdd,
+  mdd_t *targetMdd,
+  mdd_t *fairStates,
+  mdd_t *careStates,
+  array_t *onionRings,
+  boolean lowerBound,
+  array_t *quantifyVars,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel )
+{
+  mdd_t *aMdd;
+  mdd_t *bMdd;
+  mdd_t *cMdd;
+  mdd_t *resultMdd = mdd_and( targetMdd, fairStates, 1, 1 );
+  mdd_t *ringMdd   = mdd_dup( resultMdd ); 
+
+  while (TRUE) { 
+
+    if ( onionRings ) {
+      array_insert_last( mdd_t *, onionRings, mdd_dup( resultMdd ) );
+    }
+
+    /*
+     * When trying to use dont cares to the hilt, 
+     * use a bdd between succ iterations -> ringMdd 
+     */
+    aMdd = Amc_AmcEvaluateEXFormula( modelFsm, subSystemArray, subSystem, ringMdd, fairStates, careStates,
+                                    lowerBound, quantifyVars, verbosity, dcLevel );  
+    mdd_free( ringMdd );
+    bMdd = mdd_and( aMdd, invariantMdd, 1, 1 ); 
+    cMdd = mdd_or( resultMdd, bMdd, 1, 1 ); 
+
+    mdd_free( aMdd );
+    mdd_free( bMdd );
+
+    if ( mdd_equal_mod_care_set( cMdd, resultMdd, careStates ) ) {
+      mdd_free( cMdd );
+      break;
+    }
+
+    if ( dcLevel >= McDcLevelRchFrontier_c ) {
+      mdd_t *tmpMdd = mdd_and( resultMdd, cMdd, 0, 1 );
+      ringMdd = bdd_between( tmpMdd, cMdd );
+      if ( verbosity == McVerbosityMax_c ) {
+        fprintf(vis_stdout, "-- EU |A(n+1)-A(n)| = %d\t|A(n+1)| = %d\t|between-dc| = %d\n", 
+                mdd_size( tmpMdd ), mdd_size( resultMdd ), mdd_size( ringMdd ) );
+      }
+      mdd_free( tmpMdd );
+    }
+    else {
+      ringMdd = mdd_dup( cMdd );
+      if ( verbosity == McVerbosityMax_c ) {
+        fprintf(vis_stdout, "-- EU |ringMdd| = %d\n", mdd_size( ringMdd ) );
+      }
+    }
+
+    mdd_free( resultMdd );
+    resultMdd = cMdd;
+
+  }
+
+  if ( ( verbosity == McVerbosityMax_c ) ) {
+    static int refCount=0;
+    mdd_manager *mddMgr = Fsm_FsmReadMddManager( modelFsm );
+    array_t *psVars	= Fsm_FsmReadPresentStateVars( modelFsm );
+    mdd_t *tmpMdd = careStates ? mdd_and( resultMdd, careStates, 1, 1 ) : mdd_dup( resultMdd );
+    fprintf(vis_stdout, "--EU called %d (bdd_size - %d)\n", ++refCount, mdd_size( resultMdd ) );
+    fprintf(vis_stdout, "--There are %.0f care states satisfying EU formula\n", 
+            mdd_count_onset(  mddMgr, tmpMdd, psVars ) );
+    mdd_free(tmpMdd);
+  }
+
+  return resultMdd;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Evaluate EG formula with approximations.]
+
+  Description []
+
+  SideEffects []
+
+******************************************************************************/
+
+mdd_t *
+Amc_AmcEvaluateEGFormula( 
+  Fsm_Fsm_t *modelFsm,
+  array_t   *subSystemArray,
+  Amc_SubsystemInfo_t   *subSystem,
+  mdd_t *invariantMdd,
+  mdd_t *fairStates,
+  Fsm_Fairness_t *modelFairness,
+  mdd_t *careStates,
+  array_t *onionRingsArrayForDbg,
+  boolean lowerBound,
+  array_t *quantifyVars,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel )
+{
+  int i;
+  array_t *onionRings = NIL(array_t);
+  array_t *tmpOnionRingsArrayForDbg = NIL(array_t);
+  mdd_manager *mddManager = Fsm_FsmReadMddManager( modelFsm );
+  mdd_t *mddOne = mdd_one( mddManager );
+  mdd_t *Zmdd;
+
+ 
+  array_t *buchiFairness = array_alloc( mdd_t *, 0 );
+  if (modelFairness) {
+    if ( !Fsm_FairnessTestIsBuchi( modelFairness ) ) {
+      (void) fprintf(vis_stdout, "#** mc error: non Buchi fairness constraints not supported\n");
+      return NIL(mdd_t);
+    }
+    else {
+      int j;
+      int numBuchi = Fsm_FairnessReadNumConjunctsOfDisjunct( modelFairness, 0 );
+      array_t	*careStatesArray = array_alloc(mdd_t *, 0);
+
+      array_insert(mdd_t *, careStatesArray, 0, careStates);
+      for( j = 0 ; j < numBuchi; j++ ) {
+        mdd_t *tmpMdd = Fsm_FairnessObtainFinallyInfMdd(modelFairness,
+							0, j, careStatesArray,
+							dcLevel);
+        array_insert_last( mdd_t *, buchiFairness, tmpMdd );
+      }
+      array_free(careStatesArray);
+    }
+  }
+  else {
+    array_insert_last( mdd_t *, buchiFairness, mdd_one(mddManager) );
+  }
+
+  if ( onionRingsArrayForDbg !=NIL(array_t) ) {
+    tmpOnionRingsArrayForDbg = array_alloc( array_t *, 0 );
+  }
+
+
+  Zmdd = mdd_dup( invariantMdd );
+  while (TRUE) {
+
+    mdd_t *ZprimeMdd = mdd_dup(Zmdd);
+    mdd_t *conjunctsMdd = NIL(mdd_t);
+    mdd_t *AAmdd = mdd_dup(Zmdd);
+
+    for ( i = 0 ; i < array_n( buchiFairness ) ; i++ ) {
+
+      mdd_t *aMdd, *bMdd, *cMdd;
+      mdd_t *FiMdd = array_fetch( mdd_t *, buchiFairness, i );
+
+      if ( tmpOnionRingsArrayForDbg ) {
+        onionRings = array_alloc( mdd_t *, 0 );
+        array_insert_last( array_t *, tmpOnionRingsArrayForDbg, onionRings );
+      }
+
+      /* aMdd = mdd_and( FiMdd, Zmdd, 1, 1); */
+      aMdd = mdd_and( FiMdd, AAmdd, 1, 1);
+
+      bMdd = Amc_AmcEvaluateEUFormula( modelFsm, subSystemArray, subSystem, AAmdd, aMdd, mddOne, careStates, 
+                                      onionRings, lowerBound, quantifyVars, verbosity, dcLevel );
+      mdd_free(aMdd);
+      cMdd = Amc_AmcEvaluateEXFormula( modelFsm, subSystemArray, subSystem, bMdd, mddOne, careStates,
+                                      lowerBound, quantifyVars, verbosity, dcLevel ); 
+      mdd_free(bMdd);
+
+      if ( conjunctsMdd == NIL(mdd_t) ) {
+        conjunctsMdd = mdd_dup( cMdd );
+        mdd_free( AAmdd ); AAmdd = mdd_and( conjunctsMdd, invariantMdd,1 ,1 ); 
+      }
+      else {
+        mdd_t *tmpMdd = mdd_and( cMdd, conjunctsMdd, 1, 1 );
+        mdd_free( conjunctsMdd );
+        conjunctsMdd = tmpMdd;
+        mdd_free( AAmdd ); AAmdd = mdd_and( conjunctsMdd, invariantMdd,1 ,1 );
+      }
+      mdd_free( cMdd );
+    }
+    mdd_free(AAmdd);
+
+    mdd_free(ZprimeMdd);
+    ZprimeMdd = mdd_and( invariantMdd, conjunctsMdd, 1, 1 );
+    mdd_free( conjunctsMdd );
+
+    if ( mdd_equal_mod_care_set( ZprimeMdd, Zmdd, careStates ) ) {
+      mdd_free( ZprimeMdd );
+      break;
+    }
+
+    mdd_free( Zmdd );
+    Zmdd = ZprimeMdd;
+
+    if ( tmpOnionRingsArrayForDbg ) {
+      arrayForEachItem(array_t *, tmpOnionRingsArrayForDbg, i, onionRings ) {
+        mdd_array_free( onionRings );
+      }
+      array_free( tmpOnionRingsArrayForDbg );
+      tmpOnionRingsArrayForDbg = array_alloc( array_t *, 0 );
+    }
+  }
+
+  if ( onionRingsArrayForDbg != NIL(array_t) ) {
+    arrayForEachItem(array_t *, tmpOnionRingsArrayForDbg, i, onionRings ) {
+      array_insert_last( array_t *, onionRingsArrayForDbg, onionRings );
+    }
+    array_free( tmpOnionRingsArrayForDbg );
+  }
+
+  if ( ( verbosity == McVerbositySome_c ) || ( verbosity == McVerbosityMax_c ) ) {
+    { 
+      for ( i = 0 ; i < array_n( onionRingsArrayForDbg ); i++ ) {
+        int j;
+        mdd_t *Fi = array_fetch( mdd_t *,  buchiFairness, i );
+        array_t *onionRings = array_fetch( array_t *, onionRingsArrayForDbg, i );
+        for( j = 0 ; j < array_n( onionRings ) ; j++ ) {
+          mdd_t *ring = array_fetch( mdd_t *, onionRings, j );
+          if ( j == 0 ) {
+            if ( ! mdd_lequal( ring, Fi, 1, 1 ) ) {
+              fprintf( vis_stderr, "Problem w/ dbg - inner most ring not in Fi\n");
+            }
+          }
+          if ( ! mdd_lequal( ring, Zmdd, 1, 1 ) ) {
+            fprintf( vis_stderr, "Problem w/ dbg - onion ring fails invariant\n");
+          }
+        }
+      }
+    }
+
+    { 
+      mdd_t *tmpMdd = careStates ? mdd_and( Zmdd, careStates, 1, 1 ) : mdd_dup( Zmdd );
+      fprintf(vis_stdout, "--There are %.0f states satisfying EG formula\n", 
+              mdd_count_onset(  Fsm_FsmReadMddManager( modelFsm ), tmpMdd,
+                                Fsm_FsmReadPresentStateVars( modelFsm ) ) );
+      mdd_free( tmpMdd );
+    }
+  }
+
+  mdd_array_free( buchiFairness );
+  mdd_free( mddOne );
+
+  return Zmdd;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis           [Create an array of subsystems.] 
+
+  Description        [Based on the array of set of vertices, create an 
+  array of subsystems. Depending on the grouping method, different function
+  call is made to obtain an array of structure typed Part_SubsystemInfo_t. 
+  From this information, the vertex table, fan-in table, and the fan-out 
+  table is obtained to create an array of subFSMs and the subsystems.
+  ]
+
+  SideEffects        []
+
+  SeeAlso            [Part_SubsystemInfo_t]
+
+******************************************************************************/
+array_t	*
+AmcCreateSubsystemArray(
+  Ntk_Network_t         *network,
+  Ctlp_Formula_t        *formula)
+{
+  array_t		*partitionArray, *subSystemArray;
+  Part_Subsystem_t	*partitionSubsystem;
+  Part_SubsystemInfo_t *subsystemInfo; 
+  st_table		*vertexTable;
+  array_t	 	*fanInIndexArray, *fanOutIndexArray;
+  st_table		*fanInSystemTable, *fanOutSystemTable;
+  Amc_SubsystemInfo_t	*subSystem; 
+  graph_t		*partition = Part_NetworkReadPartition(network);
+  int			i, j;
+  int			fanInIndex, fanOutIndex, numOfVertex;
+  Amc_SubsystemInfo_t   *fanInSubsystem, *fanOutSubsystem;
+  char			*flagValue, *numberOfVertexInGroup;
+  array_t               *ctlArray;
+
+  /* Obtain the size of the subsystem */
+  numberOfVertexInGroup = Cmd_FlagReadByName("amc_sizeof_group");
+  if(numberOfVertexInGroup != NIL(char)){
+    numOfVertex = atoi(numberOfVertexInGroup); 
+  }
+  else{
+    /* default value */
+    numOfVertex = 8; 
+  }
+
+  /* 
+   * Obtain subsystem partitioned as submachines. 
+   */
+  flagValue = Cmd_FlagReadByName("amc_grouping_method");
+  if( (flagValue != NIL(char)) && 
+           (strcmp(flagValue, "latch_dependency")) == 0){
+
+    subsystemInfo = Part_PartitionSubsystemInfoInit(network);
+    Part_PartitionSubsystemInfoSetBound(subsystemInfo, numOfVertex);
+    partitionArray = Part_PartCreateSubsystems(subsystemInfo, NIL(array_t),
+    	NIL(array_t));
+    
+    Part_PartitionSubsystemInfoFree(subsystemInfo); 
+
+  }
+  else{
+    /*
+     * Latches which have dependency relation with given formulae
+     * are computed and grouped into sub-systems.
+     */
+    lsGen  gen;
+    Ntk_Node_t *node;
+    char *name;
+    array_t *arrayOfDataInputName;
+    lsList latchInputList = lsCreate();
+
+    if (latchInputList == (lsList)0){
+      return NIL(array_t);
+    }
+
+    ctlArray = array_alloc(Ctlp_Formula_t *, 1);
+    array_insert(Ctlp_Formula_t *, ctlArray, 0, formula);
+
+    if (!Part_PartitionGetLatchInputListFromCTL(network, ctlArray,
+						NIL(array_t),
+						latchInputList)) {
+      array_free(ctlArray);
+      return NIL(array_t);
+    }
+    arrayOfDataInputName = array_alloc(Ntk_Node_t *, lsLength(latchInputList));
+    lsForEachItem(latchInputList, gen, node){
+      name = Ntk_NodeReadName(node);
+      array_insert_last(char *, arrayOfDataInputName, name);
+    }
+    lsDestroy(latchInputList, (void (*)(lsGeneric))0);
+    array_sort(arrayOfDataInputName, stringCompare);
+
+    partitionArray = Part_PartGroupVeriticesBasedOnHierarchy(network,
+                     arrayOfDataInputName);
+    array_free(arrayOfDataInputName);
+    array_free(ctlArray);
+  }
+
+  subSystemArray = array_alloc(Amc_SubsystemInfo_t *, array_n(partitionArray));
+
+
+  /* 
+   * For each partitioned submachines build an FSM. 
+   */
+  arrayForEachItem(Part_Subsystem_t *, partitionArray, i, partitionSubsystem) {
+    Fsm_Fsm_t *fsm;
+
+    vertexTable = Part_PartitionSubsystemReadVertexTable(partitionSubsystem);
+    fanInIndexArray  = Part_PartitionSubsystemReadFanIn(partitionSubsystem);
+    fanOutIndexArray = Part_PartitionSubsystemReadFanOut(partitionSubsystem); 
+
+    FREE(partitionSubsystem);
+
+    fsm = Fsm_FsmCreateSubsystemFromNetwork(network, partition, vertexTable,
+	FALSE, 0);
+
+    subSystem = Amc_AmcSubsystemCreate(fsm, NIL(mdd_t), vertexTable, 
+                                    /*   NIL(st_table), NIL(st_table) ); */
+				       (st_table *)fanInIndexArray, 
+				       (st_table *)fanOutIndexArray); 
+    array_insert_last(Amc_SubsystemInfo_t *, subSystemArray, subSystem);
+  } /* end of arrayForEachItem(partitionArray) */
+
+  array_free(partitionArray);
+
+  /* 
+   * Convert fanInIndexTable to fanInSystemTable
+   * Convert fanOutIndexTable to fanOutSystemTable
+   */
+  arrayForEachItem(Amc_SubsystemInfo_t *, subSystemArray, i, subSystem) {
+
+    fanInIndexArray = (array_t *) AmcSubsystemReadFanInTable(subSystem);
+    fanInSystemTable = st_init_table(st_ptrcmp, st_ptrhash);
+
+    if( fanInIndexArray != NIL(array_t) ) {
+      arrayForEachItem(int, fanInIndexArray, j, fanInIndex) {
+     
+        fanInSubsystem = array_fetch(Amc_SubsystemInfo_t *, subSystemArray,
+				     fanInIndex);
+        st_insert(fanInSystemTable, (char *)fanInSubsystem, NIL(char));
+
+      }
+      array_free(fanInIndexArray);
+    }
+
+    AmcSubsystemSetFanInTable(subSystem, fanInSystemTable);
+
+
+    fanOutIndexArray = (array_t *) AmcSubsystemReadFanOutTable(subSystem);
+    fanOutSystemTable = st_init_table(st_ptrcmp, st_ptrhash);
+
+    if( fanOutIndexArray != NIL(array_t) ) {
+      arrayForEachItem(int, fanOutIndexArray, j, fanOutIndex) {
+     
+        fanOutSubsystem = array_fetch(Amc_SubsystemInfo_t *, subSystemArray,
+				      fanOutIndex);
+        st_insert(fanOutSystemTable, (char *)fanOutSubsystem, NIL(char));
+
+      }
+      array_free(fanOutIndexArray);
+    }
+
+    AmcSubsystemSetFanOutTable(subSystem, fanOutSystemTable);
+
+  }
+
+
+  return subSystemArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [Print subsystem(s) taken into the optimal system.]
+
+  SideEffects        [From the array of subsystems, prints the subsystems
+  that has been added(combined) to form a optimal system.]
+
+  SeeAlso            []
+
+******************************************************************************/
+void
+AmcPrintOptimalSystem(
+  FILE *fp,
+  Amc_Info_t *amcInfo)
+{
+  int i;
+  Amc_SubsystemInfo_t *subSystem;
+
+  fprintf(fp, "\nSubsystems in optimal path : ");
+
+  arrayForEachItem(Amc_SubsystemInfo_t *, amcInfo->subSystemArray, i, subSystem) {
+   
+    if(subSystem->takenIntoOptimal)
+      fprintf(fp, " %d ", i); 
+  
+  }
+
+}
+
+#ifdef AMC_DEBUG
+/**Function********************************************************************
+
+  Synopsis           [Only for the debugging purpose.]
+
+  SideEffects        []
+
+  SeeAlso            []
+
+******************************************************************************/
+void
+AmcCheckSupportAndOutputFunctions(
+  array_t *subSystemArray)
+{
+  int i;
+  Amc_SubsystemInfo_t *subSystem;
+  arrayForEachItem(Amc_SubsystemInfo_t *, subSystemArray, i, subSystem) {
+    Fsm_Fsm_t	*subSystemFsm	= AmcSubsystemReadFsm(subSystem);	
+    Ntk_Network_t *network	= Fsm_FsmReadNetwork(subSystemFsm);
+    mdd_manager	*mddManager	= Ntk_NetworkReadMddManager(network);
+    graph_t	*partition	= Part_NetworkReadPartition(network);
+
+    st_table	*vertexTable	= AmcSubsystemReadVertexTable(subSystem);
+    st_generator		*stGen;
+    char			*latchName;
+
+    st_foreach_item(vertexTable, stGen, &latchName, NIL(char *)) {
+
+      Ntk_Node_t	*latch		= Ntk_NetworkFindNodeByName(network, latchName);
+      int		functionMddId	= Ntk_NodeReadMddId(Ntk_NodeReadShadow(latch));
+
+      char	*nameLatchDataInput	= Ntk_NodeReadName(Ntk_LatchReadDataInput(latch));
+      vertex_t	*ptrVertex	= Part_PartitionFindVertexByName(partition, nameLatchDataInput);
+      Mvf_Function_t	*nextStateFunction;
+      st_table		*supportTable;
+
+      nextStateFunction	= Part_VertexReadFunction(ptrVertex);
+      supportTable 	= AmcCreateFunctionSupportTable(nextStateFunction);
+
+      /* print the name of the latch vars and its mddId in this subsystem*/
+      fprintf(vis_stdout, "\nSubsystem %d : Has latch : %s MddId : %d", 
+                                             i, latchName, Ntk_NodeReadMddId(latch));
+      fprintf(vis_stdout, "\n\tIts corresponding next state var : %s MddId : %d", 
+                                             Ntk_NodeReadName(Ntk_NodeReadShadow(latch)),
+                                             Ntk_NodeReadMddId(Ntk_NodeReadShadow(latch)) );
+
+      /* print the name of the output function and its mddId */
+      {
+        int outputMddId = Ntk_NodeReadMddId(Ntk_LatchReadDataInput(latch));
+        fprintf(vis_stdout, "\n\tIts output function  Output Function : %s  MddId : %d", 
+                                              nameLatchDataInput, outputMddId); 
+      }
+
+      /* print the support of its output function */
+      {
+        st_generator		*stGen2;
+        long			supportId;
+        st_foreach_item(supportTable, stGen2, (char **)&supportId, NIL(char *)) {
+          Ntk_Node_t  *supportNode = Ntk_NetworkFindNodeByMddId(network, (int) supportId);
+          char		*supportName = Ntk_NodeReadName(supportNode);
+          fprintf(vis_stdout, "\n\tOutput function's support : %s MddId : %d",
+                                                supportName, (int) supportId); 
+          fflush(vis_stdout);
+        } 
+      }
+
+
+    } /* end of st_foreach_item */
+
+  } /* end of ArrayForEachItem */
+
+
+  /* Print the name of the present state vars and its mddId */
+  /* Print the name of the next state vars and its mddId */
+  /* Print the input vars */
+  {
+    Amc_SubsystemInfo_t *subSystem = array_fetch(Amc_SubsystemInfo_t *, subSystemArray, 0);
+    Fsm_Fsm_t   *subSystemFsm	   = AmcSubsystemReadFsm(subSystem);
+    Ntk_Network_t *network         = Fsm_FsmReadNetwork(subSystemFsm);
+    lsGen gen; Ntk_Node_t *inputNode;
+    Ntk_NetworkForEachPrimaryInput(network, gen, inputNode) {
+      fprintf(vis_stdout, "\nPrimary Input : %s MddId : %d", 
+                             Ntk_NodeReadName(inputNode), Ntk_NodeReadMddId(inputNode));
+    }
+  }
+
+  /* Print the pseudo input vars */
+  {
+    Amc_SubsystemInfo_t *subSystem = array_fetch(Amc_SubsystemInfo_t *, subSystemArray, 0); 
+    Fsm_Fsm_t   *subSystemFsm	   = AmcSubsystemReadFsm(subSystem);
+    Ntk_Network_t *network         = Fsm_FsmReadNetwork(subSystemFsm);
+    lsGen gen; Ntk_Node_t *inputNode;
+    Ntk_NetworkForEachPseudoInput(network, gen, inputNode) {
+      fprintf(vis_stdout, "\nPseudo Input : %s MddId : %d", 
+                             Ntk_NodeReadName(inputNode), Ntk_NodeReadMddId(inputNode));
+      fflush(vis_stdout);
+    }
+  }
+
+}
+
+/**Function********************************************************************
+
+  Synopsis           [Only for debugging.]
+
+  SideEffects        []
+
+  SeeAlso            [Amc_SubsystemInfo]
+
+******************************************************************************/
+st_table *
+AmcCreateFunctionSupportTable(
+  Mvf_Function_t *mvf)
+{
+  mdd_manager  *mddManager;        /* Manager for the MDDs */
+  array_t      *support;
+  st_table     *mddSupport = st_init_table(st_numcmp, st_numhash);
+  int          numComponents = Mvf_FunctionReadNumComponents(mvf);
+  int          j, k;
+  mdd_t        *unit;
+
+  assert(numComponents!= 0);
+  
+  mddManager = Mvf_FunctionReadMddManager(mvf);
+
+  /*
+   * compute the support of an mdd as the union of supports of every
+   * function component 
+   */
+  for(j = 0; j < numComponents; j++) {
+    unit = Mvf_FunctionReadComponent(mvf, j);
+    support = mdd_get_support(mddManager, unit);
+    
+    /* For every element of its support */
+    for(k = 0; k < array_n(support); k++) {
+      st_insert(mddSupport, (char *)(long)array_fetch(int, support, k), (char *)0);
+    } /* End of for */
+    array_free(support);
+  } /* End of for */
+
+  return mddSupport;
+} /* End of */
+#endif
+
+
+/**Function********************************************************************
+
+  Synopsis    [Find Mdd for states satisfying Atomic Formula.]
+
+  Description [This is a duplicate copy of static function, 
+  ModelCheckAtomicFormula(). ] 
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+AmcModelCheckAtomicFormula( 
+  Fsm_Fsm_t *modelFsm,
+  Ctlp_Formula_t *ctlFormula)
+{
+  mdd_t * resultMdd;
+  mdd_t *tmpMdd;
+  Ntk_Network_t *network = Fsm_FsmReadNetwork( modelFsm );
+  char *nodeNameString = Ctlp_FormulaReadVariableName( ctlFormula );
+  char *nodeValueString = Ctlp_FormulaReadValueName( ctlFormula );
+  Ntk_Node_t *node = Ntk_NetworkFindNodeByName( network, nodeNameString );
+
+  Var_Variable_t *nodeVar;
+  int nodeValue;
+
+  graph_t *modelPartition;
+  vertex_t *partitionVertex;
+  Mvf_Function_t *MVF;
+
+  nodeVar = Ntk_NodeReadVariable( node );
+  if ( Var_VariableTestIsSymbolic( nodeVar ) ){
+    nodeValue = Var_VariableReadIndexFromSymbolicValue( nodeVar, nodeValueString );
+  }
+  else {
+    nodeValue = atoi( nodeValueString );
+  } 
+
+  modelPartition = Part_NetworkReadPartition( network );
+  if ( !( partitionVertex = Part_PartitionFindVertexByName( modelPartition,
+                                                            nodeNameString ) )) { 
+    lsGen tmpGen;
+    Ntk_Node_t *tmpNode;
+    array_t *mvfArray;
+    array_t *tmpRoots = array_alloc( Ntk_Node_t *, 0 );
+    st_table *tmpLeaves = st_init_table( st_ptrcmp, st_ptrhash );
+    array_insert_last( Ntk_Node_t *, tmpRoots, node );
+
+    Ntk_NetworkForEachCombInput( network, tmpGen, tmpNode ) {
+      st_insert( tmpLeaves, (char *) tmpNode, (char *) NTM_UNUSED );
+    }
+
+    mvfArray =  Ntm_NetworkBuildMvfs( network, tmpRoots, tmpLeaves,
+                                      NIL(mdd_t) );
+    MVF = array_fetch( Mvf_Function_t *, mvfArray, 0 );
+    array_free( tmpRoots );
+    st_free_table( tmpLeaves );
+    array_free( mvfArray );
+
+    tmpMdd = Mvf_FunctionReadComponent( MVF, nodeValue );
+    resultMdd = mdd_dup( tmpMdd );
+    Mvf_FunctionFree( MVF );
+    return resultMdd;
+  }
+  else {
+    MVF = Part_VertexReadFunction( partitionVertex );
+    tmpMdd = Mvf_FunctionReadComponent( MVF, nodeValue );
+    resultMdd = mdd_dup( tmpMdd );
+    return resultMdd;
+  }
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis [Compare two strings]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+stringCompare(
+  const void * s1,
+  const void * s2)
+{
+  return(strcmp(*(char **)s1, *(char **)s2));
+}
Index: vis_dev/vis-2.3/src/amc/amcBlock.c
===================================================================
--- vis_dev/vis-2.3/src/amc/amcBlock.c	(revision 14)
+++ vis_dev/vis-2.3/src/amc/amcBlock.c	(revision 14)
@@ -0,0 +1,1338 @@
+/**CFile***********************************************************************
+
+  FileName    [amcBlock.c]
+
+  PackageName [amc]
+
+  Synopsis    [Implementation of the block-tearing abstraction.]
+
+  Author      [Woohyuk Lee]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "amcInt.h"
+#include "mcInt.h"
+
+static char rcsid[] UNUSED = "$Id: amcBlock.c,v 1.35 2005/04/25 20:24:53 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [Block tearing specific information.] 
+
+  Description []
+
+******************************************************************************/
+struct BlockInfoStruct {
+  Amc_SubsystemInfo_t 	*optimalSystem; /* temporary storage for Block method */
+  int			bestSystem;     /* temporary storage for Block method */
+};
+
+struct BlockSubsystemInfoStruct {
+  int           scheduledForRefinement;
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef struct BlockInfoStruct BlockInfo_t;
+typedef struct BlockSubsystemInfoStruct BlockSubsystemInfo_t;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static BlockInfo_t * AmcObtainOptimalSystemUpperBound(Amc_Info_t *amcInfo, Ctlp_Formula_t *formula, BlockInfo_t *BlockInfo, int verbosity);
+static BlockInfo_t * AmcObtainOptimalSystemLowerBound(Amc_Info_t *amcInfo, Ctlp_Formula_t *formula, BlockInfo_t *BlockInfo, int verbosity);
+static void AmcInitializeDependency(array_t *subSystemArray, int isMBM);
+static void AmcInitializeSchedule(Amc_Info_t *amcInfo);
+static int AmcIsEverySubsystemRescheduled(Amc_Info_t *amcInfo);
+static void AmcPrintScheduleInformation(Amc_Info_t *amcInfo);
+#if 0
+static void AmcRescheduleForRefinement(st_table *fanOutSystemTable);
+static mdd_t * AmcRefineWithSatisfyStatesOfFanInSystem(Amc_SubsystemInfo_t *subSystem, mdd_t *careStates);
+#endif
+static array_t * AmcInitializeQuantifyVars(Amc_SubsystemInfo_t *subSystem);
+#if 0
+static void AmcFreeBlockInfo(BlockInfo_t *BlockInfo);
+#endif
+static int AmcBlockSubsystemReadScheduledForRefinement(BlockSubsystemInfo_t *system);
+static void AmcBlockSubsystemSetScheduledForRefinement(BlockSubsystemInfo_t *system, int data);
+#if 0
+static Amc_SubsystemInfo_t * AmcBlockReadOptimalSubsystem(BlockInfo_t *system);
+#endif
+static void AmcBlockSetOptimalSystem(BlockInfo_t *system, Amc_SubsystemInfo_t *data);
+#if 0
+static int AmcBlockReadBestSystem(BlockInfo_t *system);
+#endif
+static void AmcBlockSetBestSystem(BlockInfo_t *system, int data);
+#if 0
+static Amc_SubsystemInfo_t * AmcClearInputVarsFromFSM(Amc_SubsystemInfo_t *subSystem);
+#endif
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+  
+  Synopsis    [A block-tearing procedure.]
+
+  Description [From an array of subsystems, the routine picks a subsystem 
+  that produces best result. When proving true positive, a subsystem that 
+  produces smallest cardinality of the error state is chosen as the best 
+  subsystem. 
+  Error states are defined as;
+  (Initial States) - (Subset of states satisfying given formula). 
+  An over-approximation of the transition relation produces a subset of
+  states satisfying the original ACTL formula. Whenever the subset of states
+  satisfying given formula contains the initial states, we conclude that
+  the system models the specification. 
+  The routine treats initial states as a monotonically 
+  decreasing(cardinality wise) set.  This is because when we identify 
+  the set of subsets of states satisfying given ACTL formula cover 
+  the initial states, we can conclude that the initial states are entirely 
+  contained in the exact set of states satisfying given ACTL formula.
+  Hence, once we identify an error states, the routine updates the 
+  error states as new initial states. 
+
+  When proving true negative of given ACTL formula, the best subsystem 
+  is that produces smallest cardinality of the superset of states satisfying 
+  ACTL formula in consideration. An under-approximation of the transition
+  relation of the original system produces a superset of states satisfying 
+  the ACTL formulas. Whenever we find an initial state(s) that are not
+  contained in the superset of states satisfying given ACTL formula, we
+  conclude that the system does not model the specification. An initial
+  state(s) that is not contained in the superset of states satisfying
+  an ACTL formula is used to produce a debug trace.
+ 
+  When "machine by machine" switch is ON, refinement of either subsets or
+  the supersets of states satisfying given formula is performed. This 
+  process is done until the refinements cannot be made.
+  (Note; "machine by machine" refinement is not yet supported. 2/12/97)
+
+  ]
+
+  SideEffects []
+
+******************************************************************************/
+int
+AmcBlockTearingProc(
+  Amc_Info_t     *amcInfo,
+  Ctlp_Formula_t *formula,
+  int            verbosity)
+{
+  array_t               *subSystemArray = amcInfo->subSystemArray;
+  Amc_SubsystemInfo_t   *subSystem;
+  BlockInfo_t           BlockInfo;
+
+
+  /*
+   * Update fan-in subsystems and fan-out subsystems when machine by machine 
+   * method is ON.
+   * Update initial states in BlockInfo.
+   * Reschedule every subsystem to be evaluated.
+   */
+
+  if( amcInfo->optimalSystem == NIL(Amc_SubsystemInfo_t) ) {
+    AmcInitializeDependency(subSystemArray, amcInfo->isMBM);
+  }
+
+  AmcInitializeSchedule(amcInfo);
+
+  /* BlockInfo is a temporary storage. optimal system is not freed */
+  BlockInfo.optimalSystem = NIL(Amc_SubsystemInfo_t);
+    
+
+  /*
+   * Outer loop until there's no scheduled subsystem.
+   */
+  while(AmcIsEverySubsystemRescheduled(amcInfo)) {
+
+    if(verbosity == Amc_VerbosityNone_c)
+      AmcPrintScheduleInformation(amcInfo);
+
+
+    if( !amcInfo->lowerBound ) {
+        AmcObtainOptimalSystemUpperBound(amcInfo, formula, &BlockInfo, 
+					 verbosity);
+        /* AmcObtainOptimalSystemUpperBoundWithDI(amcInfo, formula, &BlockInfo,
+	                                          verbosity); */
+    }
+    else {
+        AmcObtainOptimalSystemLowerBound(amcInfo, formula, &BlockInfo, 
+					 verbosity);
+        /* AmcObtainOptimalSystemLowerBoundWithMBM(amcInfo, formula, &BlockInfo,
+	                                           verbosity); */
+    }
+
+    if(amcInfo->isVerified) {
+
+        int best = BlockInfo.bestSystem;
+        subSystem = array_fetch(Amc_SubsystemInfo_t *, amcInfo->subSystemArray,
+				best);
+        subSystem->takenIntoOptimal = 1;
+
+      return 1;
+    }
+
+    if(!amcInfo->isMBM)
+      break;
+
+  } /* End of while() */
+
+  if(verbosity == Amc_VerbosityNone_c)
+    AmcPrintScheduleInformation(amcInfo);
+
+
+  /* Update the subsystem that had been included in optimal system */
+  {
+    int best = BlockInfo.bestSystem;
+    subSystem = array_fetch(Amc_SubsystemInfo_t *, amcInfo->subSystemArray, 
+			    best);
+    subSystem->takenIntoOptimal = 1;
+  }
+
+  /* Update amcInfo's optimal system */
+  if(amcInfo->optimalSystem != NIL(Amc_SubsystemInfo_t)) {
+#ifdef AMC_DEBUG
+    {
+      Amc_SubsystemInfo_t *previousOpt = amcInfo->optimalSystem;
+      Amc_SubsystemInfo_t *currentOpt  = BlockInfo.optimalSystem;
+
+      if(!amcInfo->lowerBound) {
+        if(mdd_lequal(previousOpt->satisfyStates, currentOpt->satisfyStates,
+		      1, 1)) {
+          fprintf(vis_stdout, "\n###AMC : We are ok.");
+        }
+        else {
+          fprintf(vis_stdout, "\n** amc error: Somethings wrong.");
+        }
+      }
+      else {
+        if( mdd_lequal(currentOpt->satisfyStates, previousOpt->satisfyStates,
+		       1, 1)) {
+          fprintf(vis_stdout, "\n###AMC : We are ok.");
+        }
+        else {
+          fprintf(vis_stdout, "\n** amc error: Somethings wrong.");
+        }
+      }
+    }
+#endif 
+    Amc_AmcSubsystemFree(amcInfo->optimalSystem);
+  }
+  AmcSetOptimalSystem(amcInfo, BlockInfo.optimalSystem);
+
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees block-tearing specific data structure.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+AmcFreeBlock(
+  Amc_Info_t *amcInfo)
+{
+  Amc_SubsystemInfo_t	*subSystem; 
+  BlockSubsystemInfo_t	*BlockSubsystem;
+  int i ;
+
+  /* what if amc doesn't free partition */
+  arrayForEachItem(Amc_SubsystemInfo_t *, amcInfo->subSystemArray, i, 
+		   subSystem) {
+    BlockSubsystem = (BlockSubsystemInfo_t *)AmcSubsystemReadMethodSpecificData(subSystem);
+    if(BlockSubsystem != NIL(BlockSubsystemInfo_t))
+      FREE(BlockSubsystem);
+
+    Amc_AmcSubsystemFree(subSystem); 
+  }
+  array_free(amcInfo->subSystemArray);
+
+  if(amcInfo->optimalSystem != NIL(Amc_SubsystemInfo_t)) {
+    Amc_AmcSubsystemFree(amcInfo->optimalSystem);
+    amcInfo->optimalSystem = NIL(Amc_SubsystemInfo_t);
+  }
+
+  if( amcInfo->initialStates != NIL(mdd_t)) {
+    mdd_free(amcInfo->initialStates);
+    amcInfo->initialStates = NIL(mdd_t);
+  }
+
+  FREE(amcInfo);
+
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+
+/**Function********************************************************************
+  
+  Synopsis [Obtain best subsystem that has not taken into the optimal system.]
+
+  Description [The routine is used to prove true positive of given ACTL formula.
+  An over-approximation of transition relation is used. Over-approximation of
+  the transition relation is obtained by simply replacing the subsystems not in
+  consideration into tautology. We are adding more behavior into the system
+  by preserving only the subset of subsystems(subFSMs). We call this
+  procedure a block-tearing abstraction. We do not abstract initial states
+  in any sense.
+
+  The best subsystem is chosen from those subsystems that has not yet been
+  taken into the optimal system. A subsystem that produces best result is
+  determined by the smallest error states. An error states are defined as;
+  Error States = 
+  (Initial States) - (Subset of states satisfying given ACTL formula)   
+  For each subsystem, a subset of states satisfying given ACTL formula is
+  computed by using an over-approximation of the transition relation obtained
+  from the subsystem. The routine picks a subsystem whose corresponding
+  error states are cardinality wise minimal.
+ 
+  The optimal system is the collection of subsystems that were chosen as
+  the best subsystem in each iteration. A function call to this routine is 
+  regarded as a single iteration when "machine by machine" refinement is turned
+  OFF. These subsystems are synchronously combined to form a optimal system. 
+
+  Once the best subsystem is chosen(from the set of subsystems that has not
+  been combined into the optimal system), an initial states are updated with
+  an error states. An error states are defined as;
+  (Initial States) - (Subset of states satisfying given ACTL formula)
+
+  A more aggressive update of initial states may also be performed. If we
+  denote a subset of states satisfying given ACTL formula as Sat^L(\phi).
+  New Initial States = (Old Initial States) - \Sigma_{i}(Sat^L_i(\phi)
+  The routine currently does not attempt above aggressive approach. The 
+  routine update initial state as;
+  New Initial States = (Old Initial States) - Sat^L_{Best i}(\phi).
+
+ 
+  ]
+
+  SideEffects []
+
+******************************************************************************/
+static BlockInfo_t *
+AmcObtainOptimalSystemUpperBound(
+Amc_Info_t		*amcInfo,
+Ctlp_Formula_t 		*formula,
+BlockInfo_t		*BlockInfo,
+int			verbosity)
+{
+  array_t		*subSystemArray = amcInfo->subSystemArray;
+  Amc_SubsystemInfo_t	*subSystem, *bestCombinedSystem;
+  mdd_t			*initialStates;
+  mdd_t			*smallestStates, *currentErrorStates, *careStates;
+  int			i, best = 0;
+  graph_t               *partition = Part_NetworkReadPartition(amcInfo->network);
+  mdd_manager           *mddManager = Part_PartitionReadMddManager(partition);
+  mdd_t                 *mddOne = mdd_one(mddManager);
+  array_t               *quantifyVars;
+  Mc_DcLevel		dcLevel;
+  char	*flagValue;
+
+
+  /* 
+   * Initial states must be set before coming into this routine.
+   */
+  initialStates = amcInfo->initialStates;
+  if( initialStates == NIL(mdd_t) ) {
+    (void)fprintf(vis_stderr, "** amc error: \n");
+    return(NIL(BlockInfo_t));
+  }
+ 
+  /* Read in the usage of don't care level */
+  flagValue = Cmd_FlagReadByName("amc_DC_level");
+  if(flagValue != NIL(char)){
+    dcLevel = (Mc_DcLevel) atoi(flagValue); 
+    if( dcLevel > McDcLevelRchFrontier_c ) dcLevel = McDcLevelRchFrontier_c;
+  }
+  else{
+    /* default value set to McDcLevelNone_c. Mc's default is McDcLevelRch_c. */
+    dcLevel = McDcLevelNone_c; 
+  }
+
+  /*
+   * Update the set of states satisfying the formula for each sub-systems.
+   * The process of "combining sub-systems" is equivalent of taking a 
+   * "synchronous product" of multiple sub-subsystems.
+   */
+  smallestStates = NIL(mdd_t);
+  bestCombinedSystem  = NIL(Amc_SubsystemInfo_t);
+
+  arrayForEachItem(Amc_SubsystemInfo_t *, subSystemArray, i, subSystem) {
+
+    mdd_t       		*reachableStates, *fairStates, *satisfyStates;
+    Fsm_Fsm_t   		*combinedFsm;
+    Fsm_Fairness_t      	*fairCond;
+    Amc_SubsystemInfo_t 	*combinedSystem; 
+
+    /* Proceed if the subsystem had not yet been taken into the optimal system. */
+    if(!subSystem->takenIntoOptimal) {
+
+      /* 
+       * Combine subsystems. If optimal subsystem is NIL, duplicate the
+       * subsystem.
+       */  
+      combinedSystem = Amc_CombineSubsystems(amcInfo->network,
+					     amcInfo->optimalSystem,
+					     subSystem);
+      combinedFsm = AmcSubsystemReadFsm(combinedSystem);
+
+      quantifyVars = AmcInitializeQuantifyVars(combinedSystem);
+      
+      /* 
+       * Currently forced not to compute reachable states. This is to reduce
+       * computational overhead of computing it when dealing with complex
+       * examples.
+       */
+      reachableStates = mdd_one(mddManager);
+      fairStates = mdd_one(mddManager);
+      fairCond = Fsm_FsmReadFairnessConstraint(combinedFsm);
+
+
+      /* Obtain new care set from fan-in systems */
+      careStates = mdd_dup(reachableStates);
+
+      Ctlp_FlushStates(formula);
+      satisfyStates = mdd_dup(Amc_AmcEvaluateCTLFormula(combinedSystem,
+							subSystemArray, 
+							formula, fairStates,
+							fairCond,
+							careStates,
+							amcInfo->lowerBound, 
+							quantifyVars,
+							/*NIL(array_t),*/
+							(Mc_VerbosityLevel)
+							verbosity, dcLevel));
+
+      {
+        int x; array_t *quantifyStateVars;
+        arrayForEachItem(array_t *, quantifyVars, x, quantifyStateVars) {
+          array_free(quantifyStateVars); 
+        }
+        array_free(quantifyVars);
+      }
+      /* Free */
+      mdd_free(careStates);
+      mdd_free(reachableStates); mdd_free(fairStates); 
+      
+
+      /* 
+       * Update the set of states satisfying the formula for each subsystems
+       * when newly computed states are tighter than the one already stored.
+       * Notice, "satisfySates" holds the set of states satisfying the formula
+       * computed with the combined_system(optimal_system || current_subsystem). 
+       * 
+       */
+      if( subSystem->satisfyStates != NIL(mdd_t) ) {
+
+        if( !(mdd_equal(subSystem->satisfyStates, satisfyStates )) &&
+            (mdd_lequal(subSystem->satisfyStates, satisfyStates, 1, 1)) ) {
+          /* We got a tighter approximation. */
+          mdd_free(subSystem->satisfyStates);
+          AmcSubsystemSetSatisfy(subSystem, mdd_dup(satisfyStates));
+        }
+         
+      }     
+      else {
+        /* We are in the first level of the lattice */
+        AmcSubsystemSetSatisfy(subSystem, mdd_dup(satisfyStates));
+
+      }
+
+      /* Update the set of states satisfying the formula for the combined_system. */
+      if( AmcSubsystemReadSatisfy(combinedSystem) != NIL(mdd_t) )
+        mdd_free( AmcSubsystemReadSatisfy(combinedSystem) );
+      AmcSubsystemSetSatisfy(combinedSystem, mdd_dup(satisfyStates));
+
+
+      if( verbosity == Amc_VerbosityVomit_c) {
+         mdd_manager *mddMgr = Fsm_FsmReadMddManager(combinedSystem->fsm);
+         array_t     *psVars = Fsm_FsmReadPresentStateVars(combinedSystem->fsm);
+
+         fprintf(vis_stdout, "\n#AMC STATUS: The states satisfying the formula : %10g",
+                        mdd_count_onset(  mddMgr, combinedSystem->satisfyStates, psVars ) );
+         fflush(vis_stdout);
+       }
+
+      /* 
+       * Check whether the formula evaluates to TRUE. 
+       */
+      { 
+        mdd_t *notSatisfyStates = mdd_not(satisfyStates);
+        currentErrorStates = mdd_and(initialStates, notSatisfyStates, 1, 1);
+        mdd_free(notSatisfyStates);
+        mdd_free(satisfyStates);
+      }
+
+      if ( mdd_is_tautology(currentErrorStates, 0) ) { 
+        /* The formula is verified TRUE!! */
+
+        AmcBlockSetBestSystem(BlockInfo, i);
+        amcInfo->isVerified = 1; 
+	amcInfo->amcAnswer = Amc_Verified_True_c;
+	fprintf(vis_stdout, "\n# AMC: formula passed --- ");
+	Ctlp_FormulaPrint(vis_stdout, Ctlp_FormulaReadOriginalFormula(formula));
+
+        if(currentErrorStates != NIL(mdd_t))
+          mdd_free(currentErrorStates); 
+        if(smallestStates != NIL(mdd_t))
+          mdd_free(smallestStates);
+        if( bestCombinedSystem != NIL(Amc_SubsystemInfo_t) )
+          Amc_AmcSubsystemFree(bestCombinedSystem); 
+
+        mdd_free(mddOne); Amc_AmcSubsystemFree(combinedSystem); 
+        Ctlp_FlushStates(formula);
+
+        return BlockInfo;
+      } /* end of if */
+      else if (amcInfo->currentLevel == array_n(amcInfo->subSystemArray)){
+	/* The formula is verified FALSE!! */
+	array_t	*careStatesArray;
+
+        AmcBlockSetBestSystem(BlockInfo, i);
+	amcInfo->isVerified = 1;
+	amcInfo->amcAnswer = Amc_Verified_False_c;
+	fprintf(vis_stdout, "\n# AMC: formula failed --- ");
+	Ctlp_FormulaPrint(vis_stdout, Ctlp_FormulaReadOriginalFormula(formula));
+
+        if(currentErrorStates != NIL(mdd_t)) mdd_free(currentErrorStates);
+        if(smallestStates != NIL(mdd_t))     mdd_free(smallestStates);
+
+        if( bestCombinedSystem != NIL(Amc_SubsystemInfo_t) )
+     	  Amc_AmcSubsystemFree(bestCombinedSystem);
+
+        {
+          /* Temporarily stay here until the damn thing becomes visible. */
+          McOptions_t *mcOptions = ALLOC(McOptions_t, 1);
+          mcOptions->useMore = FALSE;
+          mcOptions->fwdBwd = McFwd_c;
+          mcOptions->reduceFsm = FALSE;
+          mcOptions->printInputs = FALSE;
+          mcOptions->simFormat = FALSE;
+          mcOptions->verbosityLevel = McVerbosityNone_c;
+          mcOptions->dbgLevel = McDbgLevelMin_c;
+          mcOptions->dcLevel   = McDcLevelNone_c;
+          mcOptions->ctlFile = NIL(FILE);
+          mcOptions->debugFile = NIL(FILE);
+
+	  careStatesArray = array_alloc(mdd_t *, 0);
+          array_insert(mdd_t *, careStatesArray, 0, mddOne);
+	  fprintf(vis_stdout, "\n");
+          McFsmDebugFormula((McOptions_t *)mcOptions, formula,
+          		    combinedSystem->fsm, careStatesArray);
+	  array_free(careStatesArray);
+          FREE(mcOptions);
+	}
+        mdd_free(mddOne);
+        Amc_AmcSubsystemFree(combinedSystem);
+        Ctlp_FlushStates(formula);
+
+        return BlockInfo;	
+      }
+
+      /* 
+       * Get the locally optimal subsystem by choosing a subsystem that produces
+       * smallest error states.
+       */
+      if( smallestStates == NIL(mdd_t) ||
+         mdd_count_onset(mddManager, currentErrorStates, Fsm_FsmReadPresentStateVars(subSystem->fsm)) <=
+         mdd_count_onset(mddManager, smallestStates, Fsm_FsmReadPresentStateVars(subSystem->fsm)) ) {
+
+        if( smallestStates != NIL(mdd_t) )
+          mdd_free(smallestStates);
+
+        smallestStates = currentErrorStates;
+
+        if(bestCombinedSystem != NIL(Amc_SubsystemInfo_t)) {
+          Amc_AmcSubsystemFree(bestCombinedSystem);
+          bestCombinedSystem = NIL(Amc_SubsystemInfo_t);
+        }
+        bestCombinedSystem = combinedSystem; 
+        best = i;
+      }
+
+      else { /* Free combined system, current error states */
+        Amc_AmcSubsystemFree(combinedSystem);
+        combinedSystem = NIL(Amc_SubsystemInfo_t);
+        mdd_free(currentErrorStates); 
+      }
+
+    
+    } /* end of if(!takenIntoOptimal) */
+
+  } /* end of arrayForEachItem(subSystemArray) */
+
+
+  /* 
+   * Flush the formula that was kept in last iteration.
+   * Update Block Info.  
+   */
+  Ctlp_FlushStates(formula);
+
+  /* Update the inital states */
+  {
+    mdd_t *initialStates;
+    if((initialStates = AmcReadInitialStates(amcInfo)) != NIL(mdd_t))
+      mdd_free(initialStates);
+    AmcSetInitialStates(amcInfo, smallestStates);
+  }
+
+  if( verbosity == Amc_VerbositySpit_c ) {
+    mdd_manager *mddMgr = Fsm_FsmReadMddManager(bestCombinedSystem->fsm);
+    array_t 	*psVars = Fsm_FsmReadPresentStateVars(bestCombinedSystem->fsm);
+
+    fprintf(vis_stdout, "\n#AMC : The BDD size of the states satisfying the formula : %d", 
+                                  mdd_size(bestCombinedSystem->satisfyStates) );
+    fprintf(vis_stdout, "\n#AMC : The cardinality of the states satisfying the formula : %10g ",
+                          mdd_count_onset(  mddMgr, bestCombinedSystem->satisfyStates, psVars ) );
+    fprintf(vis_stdout, "\n#AMC : The BDD size of the states new initial states : %d",
+                                  mdd_size(smallestStates) );
+    fprintf(vis_stdout, "\n#AMC : The cardinality of the new initial states : %10g ",
+                          mdd_count_onset(  mddMgr, smallestStates, psVars ) );
+  }
+
+
+  /* 
+   * Update the optimal system BlockInfo->optimalSystem. BlockInfo is a temporary 
+   * storage that survive through single level of the lattice.
+   */
+  if(BlockInfo->optimalSystem != NIL(Amc_SubsystemInfo_t)) {
+    Amc_AmcSubsystemFree(BlockInfo->optimalSystem);
+    AmcBlockSetOptimalSystem(BlockInfo, NIL(Amc_SubsystemInfo_t));
+  }
+  AmcSetOptimalSystem(BlockInfo, bestCombinedSystem);
+
+  /* Set the best system. */
+  AmcBlockSetBestSystem(BlockInfo, best);
+
+  mdd_free(mddOne);
+  
+  return BlockInfo;
+
+}
+
+
+/**Function********************************************************************
+  
+  Synopsis [Obtain best subsystem that has not taken into the optimal system.]
+
+  Description [The routine is to choose a subsystem that produces a best result
+  when proving true negative of the formula. An under-approximation of the
+  transition is used to obtain a superset of states satisfying given formula.
+  The best subsystem is a subsystem that produces a smallest cardinality
+  of a superset of states satisfying given ACTL formula.]
+
+  SideEffects []
+
+******************************************************************************/
+static BlockInfo_t *
+AmcObtainOptimalSystemLowerBound(
+Amc_Info_t		*amcInfo,
+Ctlp_Formula_t 		*formula,
+BlockInfo_t		*BlockInfo,
+int			verbosity)
+{
+  array_t		*subSystemArray = amcInfo->subSystemArray;
+  Amc_SubsystemInfo_t	*subSystem, *bestCombinedSystem;
+  mdd_t			*initialStates;
+  mdd_t			*smallestStates, *currentErrorStates, *careStates;
+  int			i, best = 0;
+  graph_t               *partition = Part_NetworkReadPartition(amcInfo->network);
+  mdd_manager           *mddManager = Part_PartitionReadMddManager(partition);
+  mdd_t                 *mddOne = mdd_one(mddManager);
+  array_t		*quantifyVars;
+  Mc_DcLevel		dcLevel;
+  char			*flagValue;
+  
+  /* 
+   * Initial states must be set before coming into this routine.
+   */
+  initialStates = amcInfo->initialStates;
+  if( initialStates == NIL(mdd_t) ) {
+    (void)fprintf(vis_stderr, "** amc error: \n");
+    return(NIL(BlockInfo_t));
+  }
+
+  /* Read in the usage of don't care level. Do not want to pass parameters. */
+  flagValue = Cmd_FlagReadByName("amc_DC_level");
+  if(flagValue != NIL(char)){
+    dcLevel = (Mc_DcLevel) atoi(flagValue);
+    if( dcLevel > McDcLevelRchFrontier_c ) dcLevel = McDcLevelRchFrontier_c;
+  }
+  else{
+    /* default value set to McDcLevelNone_c. Mc's default is McDcLevelRch_c. */
+    dcLevel = McDcLevelNone_c;
+  }
+
+  /*
+   * Update the set of states satisfying the formula for each subsystem.
+   * The process of "combining sub-systems" is equivalent of taking a 
+   * "synchronous product" of multiple subsystems.
+   */
+  smallestStates = NIL(mdd_t);
+  bestCombinedSystem  = NIL(Amc_SubsystemInfo_t);
+
+  arrayForEachItem(Amc_SubsystemInfo_t *, subSystemArray, i, subSystem) {
+
+    mdd_t       		*reachableStates, *fairStates, *satisfyStates;
+    Fsm_Fsm_t   		*combinedFsm;
+    Fsm_Fairness_t      	*fairCond;
+    Amc_SubsystemInfo_t 	*combinedSystem; 
+
+    /* Proceed if the subsystem has not yet been taken into the optimal system. */
+    if(!subSystem->takenIntoOptimal) {
+
+      /* 
+       * Combine subsystems. If optimal subsystem is NIL, duplicate the
+       * subsystem.
+       */
+      combinedSystem = Amc_CombineSubsystems(amcInfo->network,
+					     amcInfo->optimalSystem,
+					     subSystem);
+      /* Remove input variables from the FSM */
+      /*      combinedSystem = AmcClearInputVarsFromFSM(combinedSystem);*/
+      combinedFsm = AmcSubsystemReadFsm(combinedSystem);
+
+      /*
+       * Use takenIntoOptimal field for the purpose of excluding current block
+       * when universally quantifying variables from transition relation. 
+       * Obtain lower bound of transition relation by universal quantification.
+       */
+
+      quantifyVars = AmcInitializeQuantifyVars(combinedSystem);
+      combinedSystem->takenIntoOptimal = i;
+
+
+      /*
+       * Currently forced not to compute reachable states. This is to reduce
+       * computational burden of computing it when dealing with complex
+       * examples.
+       */
+      reachableStates = mdd_one(mddManager);
+      fairStates = mdd_one(mddManager);
+      fairCond = Fsm_FsmReadFairnessConstraint(combinedFsm);
+      careStates = mdd_dup(reachableStates);
+
+      Ctlp_FlushStates(formula);
+      satisfyStates = mdd_dup(Amc_AmcEvaluateCTLFormula(combinedSystem,
+							subSystemArray, 
+							formula, fairStates,
+							fairCond, careStates,
+							amcInfo->lowerBound, 
+							quantifyVars,
+							(Mc_VerbosityLevel)
+							verbosity, dcLevel));
+      {
+        int x; array_t *quantifyStateVars;
+        arrayForEachItem(array_t *, quantifyVars, x, quantifyStateVars) {
+          array_free(quantifyStateVars); 
+        }
+        array_free(quantifyVars);
+      }
+      mdd_free(careStates); mdd_free(reachableStates); mdd_free(fairStates); 
+      
+
+      /*
+       */
+      if( subSystem->satisfyStates != NIL(mdd_t) ) {
+        if( !(mdd_equal(satisfyStates, subSystem->satisfyStates )) &&
+             (mdd_lequal(satisfyStates, subSystem->satisfyStates, 1, 1)) ) {
+          /* We got a tighter approximation. */
+          mdd_free(subSystem->satisfyStates);
+          AmcSubsystemSetSatisfy(subSystem, mdd_dup(satisfyStates));
+        }
+      }     /* end of if( subSystem->satisfyStates != NIL(mdd_t) ) */
+      else {
+        /* Update subsystem when we are in level 1 of the lattice */
+        AmcSubsystemSetSatisfy(subSystem, mdd_dup(satisfyStates));
+      }
+
+      if( AmcSubsystemReadSatisfy(combinedSystem) != NIL(mdd_t) )
+        mdd_free( AmcSubsystemReadSatisfy(combinedSystem) );
+      AmcSubsystemSetSatisfy(combinedSystem, mdd_dup(satisfyStates));
+
+
+      /* Test if the formula is verified */
+      {
+        mdd_t *notSatisfyStates = mdd_not(satisfyStates);
+        currentErrorStates 	= mdd_and(initialStates, notSatisfyStates, 1, 1);
+        mdd_free(notSatisfyStates);
+        mdd_free(satisfyStates);
+      }
+
+      if( verbosity == Amc_VerbosityVomit_c) {
+        mdd_manager *mddMgr = Fsm_FsmReadMddManager(combinedSystem->fsm);
+        array_t *psVars     = Fsm_FsmReadPresentStateVars(combinedSystem->fsm);
+
+        fprintf(vis_stdout,
+		"\n#AMC STATUS: The states satisfying the formula : %10g",
+		mdd_count_onset(mddMgr, combinedSystem->satisfyStates, psVars ) );
+        fflush(vis_stdout);
+      }
+
+      if ( !mdd_is_tautology(currentErrorStates, 0) ) {
+	array_t	*careStatesArray;
+
+        /* Verified the formula FALSE!! */
+        AmcBlockSetBestSystem(BlockInfo, i);
+	amcInfo->isVerified = 1;
+	amcInfo->amcAnswer = Amc_Verified_False_c;
+	fprintf(vis_stdout, "\n# AMC: formula failed --- ");
+        Ctlp_FormulaPrint(vis_stdout, Ctlp_FormulaReadOriginalFormula(formula));
+
+
+        if(currentErrorStates != NIL(mdd_t)) mdd_free(currentErrorStates);
+        if(smallestStates != NIL(mdd_t))     mdd_free(smallestStates);
+
+        if( bestCombinedSystem != NIL(Amc_SubsystemInfo_t) )
+     	  Amc_AmcSubsystemFree(bestCombinedSystem);
+
+        {
+          /* Temporarily stay here until the damn thing becomes visible. */
+          McOptions_t *mcOptions = ALLOC(McOptions_t, 1);
+          mcOptions->useMore = FALSE;
+          mcOptions->fwdBwd = McFwd_c;
+          mcOptions->reduceFsm = FALSE;
+          mcOptions->printInputs = FALSE;
+          mcOptions->simFormat = FALSE;
+          mcOptions->verbosityLevel = McVerbosityNone_c;
+          mcOptions->dbgLevel = McDbgLevelMinVerbose_c;
+          mcOptions->dcLevel   = McDcLevelNone_c;
+          mcOptions->ctlFile = NIL(FILE);
+          mcOptions->debugFile = NIL(FILE);
+
+	  careStatesArray = array_alloc(mdd_t *, 0);
+          array_insert(mdd_t *, careStatesArray, 0, mddOne);
+	  fprintf(vis_stdout, "\n");
+          McFsmDebugFormula((McOptions_t *)mcOptions, formula,
+          		    combinedSystem->fsm, careStatesArray);
+	  array_free(careStatesArray);
+          FREE(mcOptions);
+	}
+        mdd_free(mddOne);
+        Amc_AmcSubsystemFree(combinedSystem);
+        Ctlp_FlushStates(formula);
+
+        return BlockInfo;
+
+      }else if (amcInfo->currentLevel == array_n(amcInfo->subSystemArray)){
+	/* The formula is verified true!! */
+        AmcBlockSetBestSystem(BlockInfo, i);
+        amcInfo->isVerified = 1; 
+	amcInfo->amcAnswer = Amc_Verified_True_c;
+	fprintf(vis_stdout, "\n# AMC: formula passed --- ");
+        Ctlp_FormulaPrint(vis_stdout, Ctlp_FormulaReadOriginalFormula(formula));
+
+
+        if(currentErrorStates != NIL(mdd_t))
+          mdd_free(currentErrorStates); 
+        if(smallestStates != NIL(mdd_t))
+          mdd_free(smallestStates);
+        if( bestCombinedSystem != NIL(Amc_SubsystemInfo_t) )
+          Amc_AmcSubsystemFree(bestCombinedSystem); 
+
+        mdd_free(mddOne); Amc_AmcSubsystemFree(combinedSystem); 
+        Ctlp_FlushStates(formula);
+
+        return BlockInfo;
+      }
+
+      mdd_free(currentErrorStates);
+
+
+      /*
+       * Choose a subsystem that produces smallest satisfying states.
+       */
+      if( smallestStates == NIL(mdd_t) ||
+          mdd_count_onset(mddManager, subSystem->satisfyStates, Fsm_FsmReadPresentStateVars(subSystem->fsm)) <= 
+          mdd_count_onset(mddManager, smallestStates, Fsm_FsmReadPresentStateVars(subSystem->fsm)) ) {
+        /*
+         * Found locally optimal subsystem. 
+         * Free smallest-error-state, best combined system so far. 
+         * Update smallest-error-states and best combined system. 
+         */
+        if( smallestStates != NIL(mdd_t) ) mdd_free(smallestStates);
+
+        smallestStates = mdd_dup(subSystem->satisfyStates);
+
+        if(bestCombinedSystem != NIL(Amc_SubsystemInfo_t)) {
+          Amc_AmcSubsystemFree(bestCombinedSystem);
+          bestCombinedSystem = NIL(Amc_SubsystemInfo_t);
+        }
+        bestCombinedSystem = combinedSystem; 
+        best = i;
+      }
+
+      else { /* Free combined system, current error states */
+        Amc_AmcSubsystemFree(combinedSystem); combinedSystem = NIL(Amc_SubsystemInfo_t);
+      }
+
+    } /* end of if(!takenIntoOptimal) */
+
+  } /* end of arrayForEachItem(subSystemArray) */
+
+  mdd_free(smallestStates);
+
+  /* 
+   * Flush formula that was kept in last iteration. Update Block Info.  
+   */
+  Ctlp_FlushStates(formula);
+
+  /*
+   * Update optimal system BlockInfo->optimalSystem. BlockInfo is a temporary 
+   * storage that survive through single level of the lattice.
+   */
+  if(BlockInfo->optimalSystem != NIL(Amc_SubsystemInfo_t)) {
+    Amc_AmcSubsystemFree(BlockInfo->optimalSystem);
+    AmcBlockSetOptimalSystem(BlockInfo, NIL(Amc_SubsystemInfo_t));
+  }
+  AmcSetOptimalSystem(BlockInfo, bestCombinedSystem);
+
+  /* Set best system. */
+  AmcBlockSetBestSystem(BlockInfo, best);
+  mdd_free(mddOne);
+
+  return BlockInfo;
+
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initialize dependencies between subsystems.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+AmcInitializeDependency(
+array_t		*subSystemArray,
+int		isMBM)
+{
+  Amc_SubsystemInfo_t 	*subSystem;  
+  BlockSubsystemInfo_t	*BlockSubsystem;
+  int	i;
+
+  if(!isMBM) {
+    int i;
+    arrayForEachItem(Amc_SubsystemInfo_t *, subSystemArray, i, subSystem) {
+      AmcSubsystemSetMethodSpecificData(subSystem, NIL(BlockSubsystemInfo_t));
+    }
+    return;
+  }
+
+  arrayForEachItem(Amc_SubsystemInfo_t *, subSystemArray, i, subSystem) {
+
+    BlockSubsystem = ALLOC(BlockSubsystemInfo_t, 1);
+
+    AmcSubsystemSetMethodSpecificData(subSystem, BlockSubsystem);
+
+  }
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Initialize scheduling information.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+AmcInitializeSchedule(
+Amc_Info_t *amcInfo)
+{
+  array_t                 *subSystemArray = amcInfo->subSystemArray;
+  Amc_SubsystemInfo_t     *subSystem;  
+  BlockSubsystemInfo_t    *BlockSubsystem;
+  int i;
+
+  /* If MBM flag is not set just return */
+  if(!amcInfo->isMBM)
+    return;
+
+  arrayForEachItem(Amc_SubsystemInfo_t *, subSystemArray, i, subSystem) {
+
+    BlockSubsystem = (BlockSubsystemInfo_t *) AmcSubsystemReadMethodSpecificData(subSystem);
+    if(!subSystem->takenIntoOptimal)
+      AmcBlockSubsystemSetScheduledForRefinement(BlockSubsystem, 1);
+    
+  }
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Test whether there is any subsystems to be reevaluated.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+AmcIsEverySubsystemRescheduled(
+Amc_Info_t *amcInfo)
+{
+  array_t		*subSystemArray = amcInfo->subSystemArray;
+  Amc_SubsystemInfo_t 	*subSystem;  
+  BlockSubsystemInfo_t	*BlockSubsystem;
+  int i;
+
+  /* If MBM flag is not set just return */
+  if( !amcInfo->isMBM )
+    return 1;
+
+  arrayForEachItem(Amc_SubsystemInfo_t *, subSystemArray, i, subSystem) {
+
+    BlockSubsystem = (BlockSubsystemInfo_t *) AmcSubsystemReadMethodSpecificData(subSystem);
+    if( AmcBlockSubsystemReadScheduledForRefinement(BlockSubsystem) )
+      return 1;
+    
+  }
+  return 0;
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Print schedule information.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+AmcPrintScheduleInformation(
+Amc_Info_t *amcInfo)
+{
+  array_t                 *subSystemArray = amcInfo->subSystemArray;
+  Amc_SubsystemInfo_t     *subSystem;  
+  BlockSubsystemInfo_t    *BlockSubsystem;
+  int i;
+
+  /* If MBM flag is not set just return */
+  if(!amcInfo->isMBM)
+    return;
+
+  fprintf(vis_stdout, "\nSchedule information : ");
+
+  arrayForEachItem(Amc_SubsystemInfo_t *, subSystemArray, i, subSystem) {
+
+    BlockSubsystem = (BlockSubsystemInfo_t *) AmcSubsystemReadMethodSpecificData(subSystem);
+    fprintf(vis_stdout, " %d ", AmcBlockSubsystemReadScheduledForRefinement(BlockSubsystem) );
+    
+  }
+
+}
+
+
+#if 0
+/**Function********************************************************************
+
+  Synopsis    [Update scheduling information for reevaluation.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+AmcRescheduleForRefinement(
+st_table	*fanOutSystemTable)
+{
+  Amc_SubsystemInfo_t 	*subSystem;
+  BlockSubsystemInfo_t	*BlockSubsystem;
+  st_generator *stGen;
+
+  st_foreach_item(fanOutSystemTable, stGen, &subSystem, NIL(char *)) {
+
+    /* reschedule only ones that are not taken */
+    if(!subSystem->takenIntoOptimal) {
+      BlockSubsystem = (BlockSubsystemInfo_t *) AmcSubsystemReadMethodSpecificData(subSystem);
+      AmcBlockSubsystemSetScheduledForRefinement(BlockSubsystem, 1);
+    }
+
+  }
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Refine result with transitive fanin subsystems.]
+
+  SideEffects []
+
+******************************************************************************/
+static mdd_t *
+AmcRefineWithSatisfyStatesOfFanInSystem(
+Amc_SubsystemInfo_t	*subSystem,
+mdd_t			*careStates)
+{
+  st_table		*fanInTable = AmcSubsystemReadFanInTable(subSystem);
+  Amc_SubsystemInfo_t	*fanInSystem;
+  st_generator		*stGen;
+
+  mdd_t 		*oldCareStates = careStates;
+  st_foreach_item(fanInTable, stGen, &fanInSystem, NIL(char *)) {
+
+    if(fanInSystem->satisfyStates != NIL(mdd_t)) {
+      mdd_t 	*fanInSatisfyStates = mdd_dup(fanInSystem->satisfyStates);
+      careStates = mdd_and(fanInSatisfyStates, oldCareStates, 1, 1);
+      mdd_free(oldCareStates); mdd_free(fanInSatisfyStates);
+      oldCareStates = careStates;
+    }
+
+  }
+
+  return(careStates);
+} /* end of "machine by machine" refinement of the careset */
+#endif
+
+
+/**Function********************************************************************
+
+  Synopsis [Initialize mdd variables to be quantified. Used in
+  under-approximation of the transition relation.]
+
+  SideEffects []
+
+******************************************************************************/
+static array_t *
+AmcInitializeQuantifyVars(
+Amc_SubsystemInfo_t *subSystem)
+{
+  array_t             *quantifyVars		= array_alloc(array_t *, 0);
+  array_t             *quantifyPresentVars	= array_alloc(int, 0);
+  array_t             *quantifyNextVars		= array_alloc(int, 0);
+  array_t             *quantifyInputVars	= array_alloc(int, 0);
+  Ntk_Network_t       *network = Fsm_FsmReadNetwork(AmcSubsystemReadFsm(subSystem));
+  Ntk_Node_t          *latch;
+  st_table            *vertexTable = AmcSubsystemReadVertexTable(subSystem);
+  lsGen               gen;
+    
+  Ntk_NetworkForEachLatch(network, gen, latch) {
+    char *latchName = Ntk_NodeReadName(latch); 
+#ifdef AMC_DEBUG
+	fprintf(vis_stdout, "\nlatch name: %s", latchName);
+	fprintf(vis_stdout, "\n latch id: %d", Ntk_NodeReadMddId(latch));
+	fprintf(vis_stdout, "\n latch id: %d", Ntk_NodeReadMddId(Ntk_NodeReadShadow(latch)));
+	fflush(vis_stdout);
+#endif
+    if(!st_lookup(vertexTable, latchName, (char **)0)) {
+    
+      /* Next state variables. */
+      array_insert_last(int, quantifyNextVars, Ntk_NodeReadMddId(Ntk_NodeReadShadow(latch)));
+      /* Present state variables. */
+      array_insert_last(int, quantifyPresentVars, Ntk_NodeReadMddId(latch));
+
+    } /* end of if(st_lookup(vertexTable)) */
+  } /* end of Ntk_NetworkForEachLatch */
+
+
+  {
+    st_table	*inputVarTable = st_init_table(st_numcmp, st_numhash);
+    Ntk_Node_t  *primaryInput;
+    /* Build the hash table of input vars of this subsystem. */
+    /* arrayForEachItem(int, inputVarArray, i, inputVar) {
+      st_insert(inputVarTable, (char *)(long)inputVar, (char *)0);
+    } */
+
+    Ntk_NetworkForEachInput(network, gen, primaryInput) {
+      int	mddId = Ntk_NodeReadMddId(primaryInput);
+#ifdef AMC_DEBUG
+      char *inputName = Ntk_NodeReadName(primaryInput); 
+      int	testMddId = Ntk_NodeReadMddId(primaryInput);
+      fprintf(vis_stdout, "\nprimary input name : %s", inputName);
+      fprintf(vis_stdout, "\nprimary input mdd id : %d", testMddId);
+      fflush(vis_stdout);
+#endif
+      /* if(!st_lookup(inputVarTable, (char *)(long)mddId, (char **)0)) { */
+        array_insert_last(int, quantifyInputVars, mddId);
+      /* } */
+    }
+    st_free_table(inputVarTable);
+  }
+
+  array_insert_last(array_t *, quantifyVars, quantifyPresentVars); 
+  array_insert_last(array_t *, quantifyVars, quantifyNextVars); 
+  array_insert_last(array_t *, quantifyVars, quantifyInputVars); 
+ 
+  return quantifyVars;
+
+}
+
+
+#if 0
+/**Function********************************************************************
+
+  Synopsis    [Frees block-tearing specific data structure.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+AmcFreeBlockInfo(
+BlockInfo_t	*BlockInfo)
+{
+
+  if(BlockInfo->optimalSystem != NIL(Amc_SubsystemInfo_t)) {
+    Amc_AmcSubsystemFree(BlockInfo->optimalSystem);
+  }
+
+}
+#endif
+
+
+/**Function********************************************************************
+
+  Synopsis    [Read scheduling information.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+AmcBlockSubsystemReadScheduledForRefinement(
+BlockSubsystemInfo_t        *system)
+{
+  return system->scheduledForRefinement;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Set scheduling information.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+AmcBlockSubsystemSetScheduledForRefinement(
+BlockSubsystemInfo_t        *system,
+int		      data)
+{
+  system->scheduledForRefinement = data;
+}
+
+
+#if 0
+/**Function********************************************************************
+
+  Synopsis    [Read optimal system.]
+
+  SideEffects []
+
+******************************************************************************/
+static Amc_SubsystemInfo_t *
+AmcBlockReadOptimalSubsystem(
+BlockInfo_t        *system)
+{
+  return system->optimalSystem;
+}
+#endif
+
+/**Function********************************************************************
+
+  Synopsis    [Set optimal system.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+AmcBlockSetOptimalSystem(
+BlockInfo_t        	     *system,
+Amc_SubsystemInfo_t  *data)
+{
+  system->optimalSystem = data;
+}
+
+#if 0
+/**Function********************************************************************
+
+  Synopsis    [Read best system.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+AmcBlockReadBestSystem(
+BlockInfo_t        *system)
+{
+  return system->bestSystem;
+}
+#endif
+
+/**Function********************************************************************
+
+  Synopsis    [Set best system.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+AmcBlockSetBestSystem(
+BlockInfo_t                *system,
+int		     data)
+{
+  system->bestSystem = data;
+}
+
+#if 0
+/**Function********************************************************************
+
+  Synopsis    [Clear input variables from the FSM of the subsystem.]
+
+  Description [Preimage computation existentially abstract both range variables
+  and input variables. This function is used to prevent existential
+  abstraction of input variables when computing the preimage.]
+
+  SideEffects []
+
+******************************************************************************/
+static Amc_SubsystemInfo_t *
+AmcClearInputVarsFromFSM(
+Amc_SubsystemInfo_t   *subSystem)
+{
+  Fsm_Fsm_t	*fsm = subSystem->fsm;
+  array_t	*inputVarArray = Fsm_FsmReadInputVars(fsm);
+  array_t	*newInputVarArray = array_alloc(int, 0);
+
+  array_free(inputVarArray);
+  (void) Fsm_FsmSetInputVars(fsm, newInputVarArray);
+
+  return(subSystem);
+}
+#endif
Index: vis_dev/vis-2.3/src/amc/amcCmd.c
===================================================================
--- vis_dev/vis-2.3/src/amc/amcCmd.c	(revision 14)
+++ vis_dev/vis-2.3/src/amc/amcCmd.c	(revision 14)
@@ -0,0 +1,565 @@
+/**CFile***********************************************************************
+
+  FileName    [amcCmd.c]
+
+  PackageName [amc]
+
+  Synopsis    [Command interface for the amc package.]
+
+  Author      [Woohyuk Lee <woohyuk@duke.colorado.edu>]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "amcInt.h"
+
+static char rcsid[] UNUSED = "$Id: amcCmd.c,v 1.44 2005/05/19 02:36:36 awedh Exp $";
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+static jmp_buf timeOutEnv;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandAmc(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static void ApproximateModelCheckUsage(void);
+static void TimeOutHandle(void);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the amc package.]
+
+  SideEffects []
+
+  SeeAlso     [Amc_End]
+
+******************************************************************************/
+void
+Amc_Init(void)
+{
+  Cmd_CommandAdd("approximate_model_check", CommandAmc, 0);
+/*  Cmd_CommandAdd("approximate_compute_reach", CommandApproxReach, 0); */
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Ends the amc package.]
+
+  SideEffects []
+
+  SeeAlso     [Amc_Init]
+
+******************************************************************************/
+void
+Amc_End(void)
+{
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis         [The approximate_model_check command.]
+
+  CommandName      [approximate_model_check]
+
+  CommandSynopsis  [perform ACTL model checking on an abstracted 
+	           and flattened network]
+
+  CommandArguments [\[-h\] \[-v &lt;verbosity_level&gt;\] &lt;ctl_file&gt; ]
+  
+  CommandDescription [Performs ACTL model checking on an abstracted and
+  flattened network.  Predefined abstractions are performed prior to model
+  checking.  Before calling this command, the user should have initialized the
+  design by calling the command <a href="init_verifyCmd.html"> <code>
+  init_verify</code></a>.  <p>
+   
+  The command includes two dual algorithms. The user should set appropriate
+  environment parameters associated with the command to execute proper
+  algorithm.  By default, the command makes its effort to prove whether given
+  ACTL formula is positive. To check whether the ACTL formula is negative, user
+  should set the environment parameter <b>amc_prove_false</b> prior to
+  executing the command.  See <a href="#environment">below</a> for the
+  environment parameters associated with this command.  <p>
+
+  Properties to be verified should be provided as ACTL formulas in the file
+  <code>&lt;ctl_file&gt;</code>. The command only accepts ACTL formulas.
+  Mixed, ECTL expressions are not supported.  
+  ACTL formulas are those in which all quantifiers are universal and 
+  negation is only allowed at the level of atomic propositions.
+  For the precise syntax of CTL formulas, see the <a href="../ctl/ctl/ctl.html"> 
+  VIS CTL and LTL syntax manual</a>.<p>
+
+  The command is designed to tackle the state explosion problem we encounter
+  when dealing with large and complex circuits. Based on the initial size of
+  the group, the command constructs over- or under-approximation of the
+  transition relation of the system. A group (subsystem) is a portion of
+  the original circuit containing a subset of the latches and
+  their next state functions.  The initial size of a group can be set with
+  the <a href="#sizeofgroup">amc_sizeof_group</a> environment variable.
+  These initial approximations may not contain every detail of the exact 
+  system. However they may contain enough information to
+  determine whether the formula is positive or negative.  Starting from an
+  initial coarse approximation, the command makes its effort to prove whether
+  given ACTL formula is positive or negative. When the procedure fails to prove
+  correctness of the formula with initial approximations, it automatically
+  refines the approximations. It repeats the process until the algorithm
+  produces a reliable result or the available resources are exhausted.<p>
+
+  Due to the overhead procedures, for some circuits, the exact <a
+  href="model_checkCmd.html"><code>model_check</code> </a> method may evaluate
+  formulas faster with less resources.  If any formula evaluates to
+  <em>false</em>, a debug trace is reported.<p>
+
+  The command does not use fairness constraints even if they have been read
+  with the <a href="read_fairnessCmd.html"><code>read_fairness</code></a> 
+  command. <p>
+
+   
+   <b>Command options: </b>
+   <p>
+
+   <dl>
+   
+   <dt><code> -h </code>
+   <dd> Print the command usage.
+
+   <p>
+          
+   <dt><code> -v  &lt;verbosity_level&gt; </code>
+   <dd> Specify verbosity level. <code> verbosity_level</code> must be one of 
+   the following:
+   <p>
+
+         <code> 0 </code> : No feedback provided. This is the default. <br>
+         <code> 1 </code> : Some feedback. <br>
+         <code> 2 </code> : Lots of feedback.
+         <p>
+
+   <dt> -t  <code>&lt;timeOutPeriod&gt;</code>
+   <dd> Specify the time out period (in seconds) after which the command
+   aborts. By default this option is set to infinity.
+   <p>
+          
+   <dt> <code> &lt;ctl_file&gt; </code>
+   <dd> File containing ACTL formulas to be model checked.
+   <p>
+
+   </dl>
+
+   <b><A NAME="environment">Environment Parameters:</A></b>
+   <p>
+
+	Environment parameters should be set using the set command
+   	from the VIS shell <br>
+        (e.g. <code>vis\> set amc_prove_false</code>).
+
+   <p>
+
+   <dl>
+
+   <dt> <b><code> amc_prove_false  </code></b>
+   <br>
+        When the parameter is set, the command makes its effort to prove
+        whether given ACTL formula is negative. The command constructs a set of
+        under-approximations of the transition relations of the system. When
+        the formula evaluates to <em>false</em>, a debug trace is reported by
+        default.  <p>
+
+   <dt> <b><code> amc_grouping_method &lt;grouping method&gt; </code></b>
+   <br>
+	Specifies grouping method. Grouping method is a method for grouping 
+        number of latches into single subsystem. Two methods are supported. 
+   <p>
+        <dd> <b>Grouping based on hierarchy<code>(default)</code></b> : The 
+	     method groups latches based on the hierarchy of the system. 
+	     Normally, complex circuits are designed in multiple
+             processes. Furthermore, processes form a hierarchy.  The method
+             uses this information provided by the original design.  When a
+             design described in high level description language is transformed
+             into low level BLIF format, the processes are transformed into
+             subcircuits. The method groups those latches that are within same
+             subcircuit.<p>
+
+        <dd> <b>Grouping based on latch dependencies(latch_dependency)</b>: The 
+             method groups those latches
+             that are closely related. Closely related latches are those who has
+             many (transitive) connections between them.
+   <p>
+
+	When the parameter is not specified, the command by default uses
+	hierarchical grouping method.
+   <p>
+
+   <dt> <b><A NAME="sizeofgroup"><code> amc_sizeof_group &lt;integer value&gt; </code></A></b>
+   <br>
+	Determines the number of latches in each group(subsystem). The default
+	value is 8. The initial size of the subsystem determines the initial
+	degree of approximations of the transition relations. There's no proven
+	rule of setting the value. Some experimental results show that setting
+	the value to about 5-20% of overall number of latches is
+	reasonable(e.g.  if the system contains 100 latches set the value to
+	5-20).  However, the suggested range may not work well with some
+	examples.  <p>
+	
+   <dt> <b><code> amc_DC_level &lt;integer value&gt; </code></b>
+   <br>
+	Specifies don't care levels. Default level is 0. Absence of the
+	parameter sets the amc_DC_level to 0.
+   <br>
+          amc_DC_level must be one of the following:<p>
+     <dl>
+          <dt><code>0</code>: No don't cares are used. This is the default.<br>
+          <dt><code>1</code>: Use unreachable states as don't cares. <br>
+          <dt><code>2</code>: Aggressively use DC's to simplify MDD's in model 
+	  checking. <br>
+     </dl>
+   <p>
+
+	Using don't cares may take more time for some examples since the
+        approximate model checker computes the reachable states for each
+        subsystem. For some large circuits it is undesirable to set don't care
+        level.  <p>
+
+  <dt> Related "set" options: <p>
+  <dt> ctl_change_bracket &lt;yes/no&gt;
+  <dd> Vl2mv automatically converts "\[\]" to "&lt;&gt;" in node names,
+  therefore CTL parser does the same thing. However, in some cases a user
+  does not want to change node names in CTL parsing. Then, use this set
+  option by giving "no". Default is "yes".
+  <p>
+
+  <dt> See also commands : model_check, incremental_ctl_verification <p>
+
+  </dl>
+
+   <b>Examples:</b> <br>
+   Here are some example sequences of the VIS executions using the approximate
+   model checker.<br>
+   <p>
+
+   <code>
+	read_blif_mv abp/abp.mv <br>
+	flatten_hierarchy <br>
+	static_order <br>
+	build_partition_mdds <br>
+	set amc_sizeof_group 4 <br>
+	approximate_model_check abp/abpt.ctl <br>
+	time <br>
+	quit <br>
+  <p>
+
+	read_blif_mv coherence/coherence.mv <br>
+	flatten_hierarchy <br>
+	static_order <br>
+	build_partition_mdds <br>
+	set amc_sizeof_group 8 <br>
+	set amc_prove_false <br>
+	set amc_DC_level 0 <br>
+	approximate_model_check coherence/coherence2.ctl <br>
+	time <br>
+	quit <br>
+  <p>
+
+
+  The algorithm used by approximate_model_check is described in detail in
+  <a href="ftp://vlsi.colorado.edu/pub/iccad96.ps">
+  ftp://vlsi.colorado.edu/pub/iccad96.ps</a>
+  ]
+
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandAmc(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  static int		timeOutPeriod;	  /* CPU seconds allowed */
+  char			*ctlFileName;	  /* Name of file containing formulas */
+  FILE			*ctlFile;	  /* File to read the formulas from */
+  Ntk_Network_t		*network;         /* Pointer to the current network */
+  array_t		*ctlFormulaArray; /* Array of read ctl formulas */
+  array_t		*ctlNormalForm;   /* Array of normal ctl formulas */
+  Ctlp_Formula_t	*currentFormula;  /* Formula being verified */
+  int			c, i;
+  Amc_VerbosityLevel	verbosity;	  /* Verbosity level */
+
+  long initialTime;
+  long finalTime;
+
+
+  /* Initialize Default Values */
+  timeOutPeriod   = 0;
+  ctlFileName     = NIL(char);
+  verbosity 	  = Amc_VerbosityNone_c;
+
+  /*
+   * Parse command line options.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "ht:v:")) != EOF) {
+    switch(c) {
+      case 'h':
+        ApproximateModelCheckUsage();
+	return 1;
+      case 't':
+	timeOutPeriod = atoi(util_optarg);
+	break;
+      case 'v':
+        verbosity = (Amc_VerbosityLevel) atoi(util_optarg);
+        break;
+      default:
+	ApproximateModelCheckUsage();
+	return 1;
+    }
+  }
+
+  /* Make sure the CTL file has been provided */
+  if (argc == util_optind) {
+    ApproximateModelCheckUsage();
+    return 1;
+  }
+  else {
+    ctlFileName = argv[util_optind];
+  }
+
+  /* 
+   * Obtain the network from the hierarchy manager 
+   */
+  network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+  if (network == NIL(Ntk_Network_t)) {
+    return 1;
+  }
+  /*
+   * Check whether the fairness was read.
+   */
+  {
+    Fsm_Fsm_t      *exactFsm = Fsm_NetworkReadOrCreateFsm(network);
+    Fsm_Fairness_t *fairCons =  Fsm_FsmReadFairnessConstraint(exactFsm);
+    int	numOfDisjuncts = Fsm_FairnessReadNumDisjuncts(fairCons);
+    if (numOfDisjuncts > 1) {
+      /* non-Buchi */
+      fprintf(vis_stdout, "** amc warning: Fairness Constraint is not supported.\n");
+    }
+    else {
+      int numOfConj     = Fsm_FairnessReadNumConjunctsOfDisjunct(fairCons, 0);
+      if (numOfConj > 1) {
+        /* Buchi */
+        fprintf(vis_stdout, "** amc warning: Fairness Constraint is not supported.\n");
+      }
+    }
+  } 
+
+  /* 
+   * Read in the array of CTL formulas provided in ctlFileName 
+   */
+  ctlFile = Cmd_FileOpen(ctlFileName, "r", NIL(char *), 0);
+  if (ctlFile == NIL(FILE)) {
+    return 1;
+  }
+  ctlFormulaArray = Ctlp_FileParseFormulaArray(ctlFile);
+  fclose(ctlFile);
+
+  if (ctlFormulaArray == NIL(array_t)) {
+    (void) fprintf(vis_stderr, "** amc error: Error while parsing ctl formulas in file.\n");
+    return 1;
+  } 
+
+  ctlNormalForm = Ctlp_FormulaArrayConvertToExistentialFormTree(ctlFormulaArray);
+
+  /* 
+   * Start the timer. 
+   */
+  if (timeOutPeriod > 0) {
+    (void) signal(SIGALRM, (void (*)(int))TimeOutHandle);
+    (void) alarm(timeOutPeriod);
+
+    /* The second time setjmp is called, it returns here !!*/
+    if (setjmp(timeOutEnv) > 0) {
+      (void) fprintf(vis_stdout, "# AMC: timeout ocurred after %d seconds.\n",
+		     timeOutPeriod);
+      alarm(0);
+
+      /* Note that there is a huge memory leak here. */
+      Ctlp_FormulaArrayFree(ctlFormulaArray);
+      Ctlp_FormulaArrayFree(ctlNormalForm);
+      return 1;
+    } 
+  }
+
+
+  /* 
+   * Loop over every CTL formula in the array 
+   */
+  arrayForEachItem(Ctlp_Formula_t *, ctlNormalForm, i, currentFormula) {
+    boolean validFormula;
+
+    validFormula = FormulaTestIsForallQuantifier(currentFormula); 
+    if (!validFormula) {
+      fprintf(vis_stderr, "Formula ");
+      Ctlp_FormulaPrint(vis_stderr, currentFormula);
+      fprintf(vis_stderr, " is not a valid ACTL formula. Skipping it\n");
+    }
+    else if (!Mc_FormulaStaticSemanticCheckOnNetwork(currentFormula, network,
+						     FALSE)) {
+      (void) fprintf(vis_stdout, "\n** amc error: Error in parsing Atomic Formula:\n%s\n", error_string());
+      error_init();
+      Ctlp_FormulaFree( currentFormula );
+      continue;
+    }
+    else {
+      error_init();
+      initialTime = util_cpu_time();
+      Amc_AmcEvaluateFormula(network, currentFormula, verbosity);
+      finalTime = util_cpu_time();
+      if(verbosity == Amc_VerbosityVomit_c) {
+        (void) fprintf(vis_stdout, "\n%-20s%10ld\n", "analysis time =",
+                       (finalTime - initialTime) / 1000);
+      }
+      fprintf(vis_stdout, "\n");
+    }
+
+  } /* End of arrayForEachItem in ctlFormulaArray */
+
+
+
+  /* Deactivate the alarm */
+  alarm(0);
+
+
+  /* Clean up */
+  Ctlp_FormulaArrayFree(ctlFormulaArray);
+  Ctlp_FormulaArrayFree(ctlNormalForm);
+  error_cleanup();
+
+
+  /* normal exit */
+  return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Prints the usage of the approximate_model_checking command.]
+
+  SideEffects        []
+
+  SeeAlso            [CommandAmc]
+
+******************************************************************************/
+static void
+ApproximateModelCheckUsage(void)
+{
+  (void) fprintf(vis_stderr, "usage: approximate_model_check [-h] ");
+  (void) fprintf(vis_stderr, "[-t secs] [-v] ctlfile\n");
+  (void) fprintf(vis_stderr, "   -h        print the command usage\n");
+  (void) fprintf(vis_stderr, "   -t secs   Seconds allowed for computation\n");
+  (void) fprintf(vis_stderr, "   -v number verbosity level\n");
+  (void) fprintf(vis_stderr, "   ctlfile   File containing the ctl formulas\n");
+
+  return;
+} /* End of ApproximateModelCheckUsage */
+
+
+
+/**Function********************************************************************
+
+  Synopsis           [Tests recursively if a formula is a valid ACTL formula.]
+
+  Description [This function implements the recursive steps needed for the
+  function FormulaTestIsForallQuantifier.]
+
+  SideEffects        []
+
+  SeeAlso            [CommandAmc]
+
+******************************************************************************/
+boolean
+FormulaTestIsForallQuantifier(
+  Ctlp_Formula_t *formula)
+{
+  Ctlp_Formula_t    *newFormula;
+  boolean           converted; 
+  Ctlp_FormulaClass result;
+
+  if (!Ctlp_FormulaTestIsConverted(formula)) {
+    newFormula = Ctlp_FormulaConvertToExistentialForm(formula);
+    converted = TRUE;
+  }
+  else {
+    newFormula = formula;
+    converted = FALSE;
+  }
+
+  result = Ctlp_CheckClassOfExistentialFormula(newFormula);
+
+  if (converted) {
+    Ctlp_FormulaFree(newFormula);
+  } /* End of if */
+
+  return result == Ctlp_ACTL_c || result == Ctlp_QuantifierFree_c;
+
+} /* End of FormulaTestIsForallQuantifier */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Handle the timeout signal.]
+
+  Description [This function is called when the time out occurs. In principle
+  it could do something smarter, but so far it just transfers control to the
+  point in the code where setjmp was called.]
+
+  SideEffects [This function gains control at any point in the middle of the
+  computation, therefore the memory allocated so far leaks.]
+
+******************************************************************************/
+static void
+TimeOutHandle(void)
+{
+  longjmp(timeOutEnv, 1);
+} /* End of TimeOutHandle */
Index: vis_dev/vis-2.3/src/amc/amcInt.h
===================================================================
--- vis_dev/vis-2.3/src/amc/amcInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/amc/amcInt.h	(revision 14)
@@ -0,0 +1,216 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [amcInt.h]
+
+  PackageName [amc]
+
+  Synopsis    [Internal data type definitions and macros to handle the
+  structures of the amc package.]
+
+  Author      [Woohyuk Lee <woohyuk@duke.colorado.edu>]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+  Revision    [$Id: amcInt.h,v 1.23 2002/09/08 02:10:46 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _AMCINT
+#define _AMCINT
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+/* #include <unistd.h> */
+#include "amc.h"
+#include <string.h>
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef int (*AmcCallBackProc)  ARGS((Amc_Info_t *, Ctlp_Formula_t *, int));
+typedef void (*AmcFreeProc) ARGS((Amc_Info_t *));
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+/**Struct**********************************************************************
+
+  Synopsis    [Information regarding a subsystem.]
+
+  Description [Each field represents information associated with a subsystem.]
+
+  SeeAlso     [AmcInfoStruct]
+
+******************************************************************************/
+struct AmcSubsystemInfo{
+  Fsm_Fsm_t	*fsm;		       /* Sub-Fsm of this subsystem */
+  array_t	*relationArray;        /* Array of MDD representation of the 
+					  transition relation */
+  mdd_t		*nextStateVarSmoothen; /* Transition relation of subsystems
+					  with next state variables existentially
+ 					  quantified */
+  mdd_t		*satisfyStates;        /* Sub(Super)-set of states satisfying 
+					  given formula */
+  st_table 	*vertexTable;          /* Vertices in the subsystem */
+  st_table	*fanInTable;           /* */
+  st_table	*fanOutTable;          /* */
+  int		takenIntoOptimal;      /* If 1, the subsystem is part of the system */
+  char		*methodSpecificData;   /* May be used to store method specific data */
+};
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [Information regarding the amc package.]
+
+  Description [This is a higher level of information related to the amc package.]
+
+  SeeAlso     [AmcSubsystemInfo]
+
+******************************************************************************/
+struct AmcInfoStruct{
+  Ntk_Network_t		*network;	 /* Corresponding network */
+  Amc_MethodType	methodType;	 /* Approximation method type */
+  void                  *methodData;     /* Method-dependent data structure */
+
+  array_t		*subSystemArray; /* Array of AmcSubsystemInfo *  */
+  Amc_SubsystemInfo_t 	*optimalSystem;  /* */
+  mdd_t			*initialStates;  /* */
+  AmcCallBackProc	amcBoundProc;    /* Function using upper bound approximation */ 
+  AmcFreeProc		amcFreeProc;	 /* Function to free method-specific data structure */
+  int			isVerified;	 /* isVerified=1  whenever formula is verified */
+  Amc_Verified_Answer   amcAnswer;       /* {Unknown, True, False} */
+  int			isMBM;		 /* isMBM=1 when Machine by Machine method is applied */
+  int			groupingMethod;  /* */
+  boolean		lowerBound;      /* lowerBound=1 when lower bound approximation is used */
+  int                   currentLevel;    /* Current lattice approximation level */  
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#define AmcSubsystemReadFsm(system) \
+  (system)->fsm
+
+#define AmcSubsystemSetFsm(system, data) \
+  (system)->fsm = (data)
+
+
+#define AmcSubsystemReadRelationArray(system) \
+  (system)->relationArray
+
+#define AmcSubsystemSetRelationArray(system, data) \
+  (system)->relationArray = (data)
+
+
+#define AmcSubsystemReadNextStateVarSmoothen(system) \
+  (system)->nextStateVarSmoothen
+
+#define AmcSubsystemSetNextStateVarSmoothen(system, data) \
+  (system)->nextStateVarSmoothen = (data)
+
+
+#define AmcSubsystemReadSatisfy(system) \
+  (system)->satisfyStates
+
+#define AmcSubsystemSetSatisfy(system, data) \
+  (system)->satisfyStates = (data)
+
+
+#define AmcSubsystemReadVertexTable(system) \
+  (system)->vertexTable
+
+#define AmcSubsystemSetVertexTable(system, data) \
+  (system)->vertexTable = (data)
+
+
+#define AmcSubsystemReadFanInTable(system) \
+  (system)->fanInTable
+
+#define AmcSubsystemSetFanInTable(system, data) \
+  (system)->fanInTable = (data)
+
+
+#define AmcSubsystemReadFanOutTable(system) \
+  (system)->fanOutTable
+
+#define AmcSubsystemSetFanOutTable(system, data) \
+  (system)->fanOutTable = (data)
+
+
+#define AmcSubsystemReadMethodSpecificData(system) \
+  (system)->methodSpecificData
+
+#define AmcSubsystemSetMethodSpecificData(system, data) \
+  (system)->methodSpecificData = (char *) (data)
+
+
+#define AmcReadInitialStates(system) \
+  (system)->initialStates
+
+#define AmcSetInitialStates(system, data) \
+  (system)->initialStates = (data)
+
+
+#define AmcReadOptimalSystem(system) \
+  (system)->optimalSystem
+
+#define AmcSetOptimalSystem(system, data) \
+  (system)->optimalSystem = (data)
+
+
+#define AmcReadMethodData(system) \
+  (system)->methodData
+
+#define AmcSetMethodData(system, data) \
+  (system)->methodData = (data)
+
+
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN array_t	* AmcCreateSubsystemArray(Ntk_Network_t *network, Ctlp_Formula_t *formulA);
+EXTERN void AmcPrintOptimalSystem(FILE *fp, Amc_Info_t *amcInfo);
+EXTERN void AmcCheckSupportAndOutputFunctions(array_t *subSystemArray);
+EXTERN st_table * AmcCreateFunctionSupportTable(Mvf_Function_t *mvf);
+EXTERN mdd_t * AmcModelCheckAtomicFormula(Fsm_Fsm_t *modelFsm, Ctlp_Formula_t *ctlFormula);
+EXTERN int AmcBlockTearingProc(Amc_Info_t *amcInfo, Ctlp_Formula_t *formula, int verbosity);
+EXTERN void AmcFreeBlock(Amc_Info_t *amcInfo);
+EXTERN boolean FormulaTestIsForallQuantifier(Ctlp_Formula_t *formula);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _AMCINT */
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/baig/baig.h
===================================================================
--- vis_dev/vis-2.3/src/baig/baig.h	(revision 14)
+++ vis_dev/vis-2.3/src/baig/baig.h	(revision 14)
@@ -0,0 +1,595 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [baig.h]
+
+  PackageName [baig]
+
+  Synopsis    [Binary AND/INVERTER graph]
+
+  Description [External functions and data strucures of the binary AND/INVERTER graph package]
+
+  SeeAlso     [baigInt.h]
+
+  Author      [Mohammad Awedh]
+
+  Copyright [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+  Revision    [$Id: baig.h,v 1.29 2009/04/12 00:14:03 fabio Exp $]
+
+
+******************************************************************************/
+
+#ifndef _BAIG
+#define _BAIG
+
+#include "st.h"
+#include "ntk.h"
+#include "bdd.h"
+#include "mdd.h"
+#include "sat.h"
+#include "ctlsp.h"
+/*Bing:*/
+#include "puresat.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define bAigInvertBit      0x1                        /* This bit is set to indicate inverted edge*/
+
+#define bAigArrayMaxSize   (1 << 27)  /* Maximum size of the node array */
+
+#define ZERO_NODE_INDEX    0                          /* Reserve this index for constant Zero node*/
+#define bAig_Zero          (ZERO_NODE_INDEX)          /* Constatnt Zero node */
+#define bAig_One           (bAig_Not(bAig_Zero))      /* Constatnt One node  */
+
+#define bAig_NULL          2
+/*Bing*/
+#define bAigNodeSize       12 /*8*/                          /* Array is used to implement the bAig graph.
+                                                         Each node occupies bAigNodeSize array elements. */
+#define bAigFirstNodeIndex   bAigNodeSize             /* The first node index. */
+
+#define bAig_HashTableSize 481931
+
+#define  bAigValue     0   /* Index of the decision level. */  
+#define  bAigFlags     1   /* Index of flag for this node.*/
+#define  bAigLeft      2   /* Index of the left child */ 
+#define  bAigRight     3   /* Index of the right child */ 
+#define  bAigNFanout   4   /* Index of number of fanout.*/
+#define  bAigFanout    5   /* Index of fanout pointer for this node.*/
+#define  bAigCanonical 6   /* Index of canonical node for this node.*/
+#define  bAigNext      7   /* Index of dummy for this node.*/
+
+/*Bing:*/
+#define  bAigClass     8
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef char			 nameType_t;
+typedef long                     bAigEdge_t;
+typedef struct bAigManagerStruct bAig_Manager_t;
+typedef struct bAigTimeFrameStruct 	bAigTimeFrame_t;
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [And/Inverter graph manager.]
+
+  Description []
+
+******************************************************************************/
+struct bAigManagerStruct {
+  bAigEdge_t *NodesArray;       /* contains pointers to nodes of type
+				   bAig_Node_t */
+  long        nodesArraySize;    /* contains the current number of nodes */
+  long        maxNodesArraySize; /* Nodes Array maximum size */
+
+  bAigEdge_t *HashTable;        /* Hash table */
+  st_table   *SymbolTable;      /* Symbol table to store variables and their
+				   indices */
+  char       **nameList;        /* This table contains the name of each node.
+				   nodeID is used to access the node's name. */
+  array_t    *mVarList;         /* List of mVarId of each variable */ 
+  array_t    *bVarList;         /* List of bVardId (bAig_t) of the binary value
+				   encoding for multi-valued variables. */
+  int        allocatedFlags;
+  int        *bddIdArray;
+  bdd_t      **bddArray;
+  bdd_t      **relArray;
+  st_table   *id2aig;
+
+  struct bAigTimeFrameStruct *timeframe;
+  struct bAigTimeFrameStruct *timeframeWOI;
+  struct satLiteralDBStruct *literals;
+  char *dummy;
+  
+  /* Bing: for interpolation */
+  bAigEdge_t **  HashTableArray;
+  st_table **    SymbolTableArray;
+  int NumOfTable;
+
+  int class_; /* one is C1, 2 is C2 or for multiCut it is the timeframe */
+  IP_Manager_t * ipm;
+  satArray_t * assertArray;
+  bAigEdge_t  InitState, IPState;
+  /*RTree_t *root;*/
+  int IP,test2LevelMini;
+  satArray_t * assertArray2, *EqArray, *CoiAssertArray;
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [A struct to save unrolled system]
+
+******************************************************************************/
+struct bAigTimeFrameStruct {
+  int nInputs;                 /* the number of inputs */
+  int nOutputs;                /* the number of outputs */
+  int nLatches;                /* the number of latchs */
+  int nInternals;              /* the numebr of internal nodes */
+  int currentTimeframe;        /* the number of unrolled timeframe */
+  bAigEdge_t **inputs;         /* the array to save input of each unrolled timeframe */
+  bAigEdge_t **outputs;        /* the array to save output of each unrolled timeframe */
+  bAigEdge_t **latchInputs;    /* the array to save latch input of each unrolled timeframe */
+  bAigEdge_t **internals;      /* the array to save internal node of each unrolled timeframe */
+  /* we need this array to build property */
+  /* based on internal node, there might be */
+  /* the way to improve this. */
+  bAigEdge_t *oriLatchInputs;  /* the array to save latch input of original system */
+  bAigEdge_t *oribLatchInputs; /* the array to save latch input of original system */
+  bAigEdge_t *oriInputs;       /* the array to save input of original system */
+  bAigEdge_t *oribInputs;      /* the array to save input of original system */
+  st_table *li2index;          /* It maps the latch input aig to index which can identify i'th latch input through latchInputs[i][index] */
+  st_table *o2index;           /* It maps the output aig to index which can identify i'th latch input through outputs[i][index] */
+  st_table *i2index;           /* It maps the input aig to index which can identify i'th latch input through inputs[i][index] */
+  st_table *pi2index;          /* It maps the input aig to index which can identify i'th latch input through inputs[i][index] */
+  array_t *latchArr;
+  array_t *inputArr;
+  array_t *outputArr;
+  array_t *iindexArray;
+  array_t *assertedArray;
+  int nbInputs;                /* the number of input bits */
+  int nbLatches;               /* the number of latche bits */
+  bAigEdge_t **binputs;        /* the array to save input bit of each unrolled timeframe */
+  bAigEdge_t **blatchInputs;   /* the array to save latch input bit of each unrolled timeframe */
+  st_table *bli2index;         /* It maps the latch input bit of aig to index which can identify i'th latch input through blatchInputs[i][index] */
+  st_table *bpi2index;         /* It maps the input bit of aig to index which can identify i'th latch input through binputs[i][index] */
+
+  /*Bing:*/
+  st_table *libli2eq;
+  st_table *idx2name;
+  st_table *MultiLatchTable;   /* stores var corresponding to multiple latches */
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [A struct to save transition relation of AIG ]
+
+******************************************************************************/
+typedef struct bAigTransitionStruct 	bAigTransition_t;
+struct bAigTransitionStruct {
+  Ntk_Network_t     *network;
+  bAig_Manager_t    *manager;
+  satManager_t *allsat;   /** to save the sat manager for allsat process **/
+  satManager_t *lifting;  /** to save the sat manager for lifting process **/
+  int nInputs;            
+  int nLatches;          
+  bAigEdge_t objective;
+  bAigEdge_t *inputs;         
+  bAigEdge_t *cstates;   
+  bAigEdge_t *nstates;
+  bAigEdge_t *initials;
+  bAigEdge_t *n2c;
+  bAigEdge_t *c2n;
+  bAigEdge_t *cobj;
+  int csize;
+  int istates;
+  bAigEdge_t *tstates;   
+  bAigEdge_t *coiStates;  /* to identified the next states variables in froniter set **/ 
+
+  int *vinputs;     /** to save the value of primary inputs **/  
+  int *vtstates;    /** to save the value of tstates variable during lifting **/
+  int objValue;
+  int latestBlockingClause;
+  int iteration;
+  struct satArrayStruct *unassigned;
+  struct satArrayStruct *tVariables;
+  struct satArrayStruct *auxObj;
+  struct satArrayStruct *objArr; /** to save the next state variable used to build objective */
+
+  struct satArrayStruct *reached;
+  struct satArrayStruct *frontier;
+  struct satArrayStruct *originalFrontier;
+  int avgLits;
+  int sum;
+  int period;
+  int interval;
+  int nBlocked;
+
+  int method;
+  int interface;
+  int inclusionInitial;
+  int constrain;
+  int verbose;
+  int reductionUsingUnsat;
+  int disableLifting;
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns the class of a node]
+
+  Description  []
+
+  SideEffects [none]
+
+  SeeAlso      []
+
+******************************************************************************/
+/*Bing:*/
+#define bAig_Class(node) (\
+ manager->NodesArray[bAig_NonInvertedEdge(node)+bAigClass]\
+)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Performs the 'Not' Logical operator]
+
+  Description  [This macro inverts the edge going to a node which corresponds 
+                to NOT operator]
+
+  SideEffects [none]
+
+  SeeAlso      []
+
+******************************************************************************/
+#define bAig_Not(node) (                         \
+        (bAigEdge_t) ((node) ^ (bAigInvertBit))  \
+)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns the non inverted edge.]
+
+  Description  [This macro returns the non inverted edge.  It clears the least 
+  significant bit of the edge if it is set.]
+
+  SideEffects  [none]
+
+  SeeAlso      []
+
+******************************************************************************/
+#define bAig_NonInvertedEdge(edge) ( \
+	(edge) & ~(bAigInvertBit)    \
+)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Returns true if the edge is inverted.]
+
+  Description  []
+
+  SideEffects [none] 
+
+  SeeAlso      []
+
+******************************************************************************/
+#define bAig_IsInverted(edge) (   \
+	(edge) & (bAigInvertBit)  \
+)
+
+/**Macro***********************************************************************
+
+  Synopsis    [Return right child of aig node]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+#define rightChild(node)(\
+(manager->NodesArray[bAig_NonInvertedEdge(node)+bAigRight])\
+)
+
+/**Macro***********************************************************************
+
+  Synopsis    [Return left child of aig node]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+#define leftChild(node)(\
+(manager->NodesArray[bAig_NonInvertedEdge(node)+bAigLeft])\
+)
+
+/**Macro***********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+#define fanout(node)(\
+manager->NodesArray[bAig_NonInvertedEdge(node)+bAigFanout]\
+)
+
+/**Macro***********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+#define nFanout(node)(\
+manager->NodesArray[bAig_NonInvertedEdge(node)+bAigNFanout]\
+)
+
+/**Macro***********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+#define flags(node)(\
+manager->NodesArray[bAig_NonInvertedEdge(node)+bAigFlags]\
+)
+
+/**Macro***********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+#define canonical(node)(\
+manager->NodesArray[bAig_NonInvertedEdge(node)+bAigCanonical]\
+)
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [return next of aig]
+
+  Description [This is used to build hash table for structural hashing]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+#define next(node)(\
+manager->NodesArray[bAig_NonInvertedEdge(node)+bAigNext]\
+)
+
+/**Macro***********************************************************************
+
+  Synopsis    [return value of aig node]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+#define aig_value(node)(\
+(manager->NodesArray[bAig_NonInvertedEdge(node)+bAigValue])\
+)
+
+/**Macro***********************************************************************
+
+  Synopsis    [The node ID]
+
+  Description [Node ID is a unique number for each node and can be found by 
+              dividing the edge going to this node by bAigNodeSize.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+/*#define bAigNodeID(edge)(\
+bAig_NonInvertedEdge(edge)>>3 \
+)*/
+
+/*Bing:*/
+#define bAigNodeID(edge)(\
+bAig_NonInvertedEdge(edge)/bAigNodeSize \
+)
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Hash function for the hash table.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+#define HashTableFunction(left, right) \
+( (bAigEdge_t)\
+((( (bAigEdge_t) (left)) << 3) + \
+(( (bAigEdge_t) (right)) << 3)) % bAig_HashTableSize \
+)
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Traverse fanout of AIG ]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+#define bAigEdgeForEachFanout(                             \
+	manager,     /* bAig_Manager_t */                  \
+	v,           /* bAigEdge_t */                      \
+	cur,         /* bAigEdge_t for fanout */           \
+	ii,                                                \
+	iii,                                               \
+	pfan                                               \
+)                                                          \
+for(ii=0, iii=nFanout(v), pfan=(bAigEdge_t *)fanout(v);    \
+    (ii<iii) && (cur = pfan[ii]);                          \
+    ii++)
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Is AIG node a variable node]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+#define bAigIsVar(manager, v)                              \
+    (leftChild(v) == bAig_NULL)
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Check whether two nodes are same or not]
+
+  Description [Check whether two nodes are same or not, accounting for
+  complementation.  The two nodes may only differ in the LSB.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+#define bAigCompareNode(l, r)                              \
+  (((l) | 1) == ((r) | 1))
+
+
+/**Macro***********************************************************************
+
+  Synopsis    [Swap AIG nodes ]
+
+  Description [Swap two AIG nodes by a sequence of exclusive ORs.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+#define bAigSwap(l, r)                                     \
+  {(l) ^= (r); (r) ^= (l); (l) ^= (r);}
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void bAig_BddSweepMain(Ntk_Network_t *network, array_t *nodeArray);
+EXTERN void bAig_BddSweepSub(bAig_Manager_t *manager, mdd_manager *mgr, bAigEdge_t v, st_table *bdd2vertex, int sizeLimit, int *newBddIdIndex);
+EXTERN void bAig_BuildAigBFSManner(Ntk_Network_t *network, mAig_Manager_t *manager, st_table *leaves, int sweep);
+EXTERN void bAig_BddSweepForceMain(Ntk_Network_t *network, array_t *nodeArray);
+EXTERN void bAig_BddSweepForceSub(bAig_Manager_t *manager, mdd_manager *mgr, bAigEdge_t v, st_table *bdd2vertex, int sizeLimit, int *newBddIdIndex);
+EXTERN void bAig_Init(void);
+EXTERN void bAig_End(void);
+EXTERN bAig_Manager_t * bAig_initAig(int maxSize);
+EXTERN void bAig_quit(bAig_Manager_t *manager);
+EXTERN void bAig_NodePrint(bAig_Manager_t *manager, bAigEdge_t node);
+EXTERN nameType_t * bAig_NodeReadName(bAig_Manager_t *manager, bAigEdge_t node);
+EXTERN void bAig_NodeSetName(bAig_Manager_t *manager, bAigEdge_t node, nameType_t *name);
+EXTERN int bAig_NodeReadIndexOfRightChild(bAig_Manager_t *manager, bAigEdge_t nodeIndex);
+EXTERN bAigEdge_t bAig_NodeReadIndexOfLeftChild(bAig_Manager_t *manager, bAigEdge_t nodeIndex);
+EXTERN bAigEdge_t bAig_GetCanonical(bAig_Manager_t *manager, bAigEdge_t nodeIndex);
+EXTERN int bAig_Merge(bAig_Manager_t *manager, bAigEdge_t nodeIndex1, bAigEdge_t nodeIndex2);
+EXTERN void bAig_PrintNode(bAig_Manager_t *manager, bAigEdge_t i);
+EXTERN bAigEdge_t bAig_And(bAig_Manager_t *manager, bAigEdge_t nodeIndex1, bAigEdge_t nodeIndex2);
+EXTERN bAigEdge_t bAig_And2(bAig_Manager_t *manager, bAigEdge_t nodeIndex1, bAigEdge_t nodeIndex2);
+EXTERN bAigEdge_t bAig_Or(bAig_Manager_t *manager, bAigEdge_t nodeIndex1, bAigEdge_t nodeIndex2);
+EXTERN bAigEdge_t bAig_Xor(bAig_Manager_t *manager, bAigEdge_t nodeIndex1, bAigEdge_t nodeIndex2);
+EXTERN bAigEdge_t bAig_Eq(bAig_Manager_t *manager, bAigEdge_t nodeIndex1, bAigEdge_t nodeIndex2);
+EXTERN bAigEdge_t bAig_Then(bAig_Manager_t *manager, bAigEdge_t nodeIndex1, bAigEdge_t nodeIndex2);
+EXTERN bAigEdge_t bAig_CreateNode(bAig_Manager_t *manager, bAigEdge_t nodeIndex1, bAigEdge_t nodeIndex2);
+EXTERN bAigEdge_t bAig_FindNodeByName(bAig_Manager_t *manager, nameType_t *name);
+EXTERN bAigEdge_t bAig_CreateVarNode(bAig_Manager_t *manager, nameType_t *name);
+EXTERN int bAig_isVarNode(bAig_Manager_t *manager, bAigEdge_t node);
+EXTERN bAigEdge_t bAig_bddTobAig(bAig_Manager_t *bAigManager, bdd_t *fn);
+EXTERN int bAig_PrintDot(FILE *fp, bAig_Manager_t *manager);
+EXTERN bAigEdge_t bAig_And4(bAig_Manager_t *manager, bAigEdge_t l, bAigEdge_t r);
+EXTERN bAigEdge_t bAig_And3(bAig_Manager_t *manager, bAigEdge_t l, bAigEdge_t r);
+EXTERN void bAig_SetMaskTransitiveFanin(bAig_Manager_t *manager, int v, unsigned int mask);
+EXTERN void bAig_ResetMaskTransitiveFanin(bAig_Manager_t *manager, int v, unsigned int mask, unsigned int resetMask);
+EXTERN void bAig_ExpandTimeFrame(Ntk_Network_t *network, mAig_Manager_t *manager, int bound, int withInitialState);
+EXTERN void bAig_FreeTimeFrame(bAigTimeFrame_t *timeframe);
+EXTERN bAigTimeFrame_t * bAig_InitTimeFrame(Ntk_Network_t *network, mAig_Manager_t *manager, int withInitialState);
+EXTERN void bAig_CreateNewNode(mAig_Manager_t *manager, st_table *node2MvfAigTable, Ntk_Node_t *node, bAigEdge_t *bli, bAigEdge_t *li, int *bindex, int *index);
+EXTERN bAigEdge_t bAig_ExpandForEachCone(mAig_Manager_t *manager, bAigEdge_t v, st_table *old2new);
+EXTERN void bAig_CheckConnect(bAig_Manager_t *manager, int from, int to);
+EXTERN int bAig_CheckConnectFanin(bAig_Manager_t *manager, int from, int to);
+EXTERN int bAig_CheckConnectFanout(bAig_Manager_t *manager, int from, int to);
+EXTERN int bAig_GetValueOfNode(bAig_Manager_t *manager, bAigEdge_t v);
+EXTERN void bAig_GetCOIForNode(Ntk_Node_t *node, st_table *table);
+EXTERN void bAig_GetCOIForNodeMain(Ntk_Network_t * network, char *name);
+EXTERN void bAig_CheckLatchStatus(Ntk_Network_t * network, bAig_Manager_t *manager);
+EXTERN void bAig_PrintNodeAigStatus(bAig_Manager_t *manager, Ntk_Node_t *node);
+EXTERN void bAig_PrintNodeAigStatusWithName(Ntk_Network_t * network, bAig_Manager_t *manager, char *name);
+EXTERN bAigEdge_t bAig_CreatebAigForInvariant( Ntk_Network_t *network, bAig_Manager_t *manager, Ctlsp_Formula_t *inv);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _BAIG */
Index: vis_dev/vis-2.3/src/baig/baig.make
===================================================================
--- vis_dev/vis-2.3/src/baig/baig.make	(revision 14)
+++ vis_dev/vis-2.3/src/baig/baig.make	(revision 14)
@@ -0,0 +1,4 @@
+CSRC += baigCmd.c baigNode.c baigBddSweep.c baigTimeframe.c baigAllSat.c
+HEADERS += baig.h baigInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/baig/baigAllSat.c
===================================================================
--- vis_dev/vis-2.3/src/baig/baigAllSat.c	(revision 14)
+++ vis_dev/vis-2.3/src/baig/baigAllSat.c	(revision 14)
@@ -0,0 +1,3070 @@
+/**CFile***********************************************************************
+
+  FileName    [baigAllSat.c]
+
+  PackageName [baig]
+
+  Synopsis    [Routines to check sat-based invariant checking.]
+
+  Author      [HoonSang Jin]
+
+  Copyright [ This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+
+******************************************************************************/
+
+#include "baig.h"
+#include "baigInt.h"
+#include "ntk.h"
+#include "bmc.h"
+#include "sat.h"
+
+static char rcsid[] UNUSED = "$Id: baigAllSat.c,v 1.4 2009/04/11 02:40:01 fabio Exp $";
+static satManager_t *SATcm;
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+static int nodenameCompare( const void * node1, const void * node2);
+static int levelCompare( const void * node1, const void * node2);
+static int indexCompare( const void * node1, const void * node2);
+static int StringCheckIsInteger(char *string, int *value);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Create data structure for transition relation.]
+
+  Description [Create data structure for transition relation.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bAigTransition_t *
+bAigCreateTransitionRelation(
+	Ntk_Network_t *network,
+	mAig_Manager_t *manager)
+{
+bAigTransition_t *t;
+array_t   *bVarList, *mVarList;
+array_t *latcharr;
+Ntk_Node_t *node, *dataInput;
+mAigMvar_t mVar;
+mAigBvar_t bVar;
+st_table *node2MvfAigTable;
+lsGen gen;
+int nLatches, nInputs;
+int i, j, index, index1;
+int mAigId, maxCS;
+bAigEdge_t v;
+bAigEdge_t *cstates, *nstates, *inputs;
+
+  t = ALLOC(bAigTransition_t, 1);
+  memset(t, 0, sizeof(bAigTransition_t));
+  t->network = network;
+  t->manager = manager;
+
+  bVarList = mAigReadBinVarList(manager);
+  mVarList = mAigReadMulVarList(manager);
+
+  latcharr = array_alloc(Ntk_Node_t *, 16);
+  nLatches = 0;
+  Ntk_NetworkForEachLatch(network, gen, node) {
+    mAigId = Ntk_NodeReadMAigId(node);
+    mVar = array_fetch(mAigMvar_t, mVarList, mAigId);
+    nLatches += mVar.encodeLength;
+    array_insert_last(Ntk_Node_t *, latcharr, node);
+  }
+  t->nLatches = nLatches;
+
+  node2MvfAigTable = 
+	(st_table *)Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+
+  array_sort(latcharr, nodenameCompare);
+
+  cstates = ALLOC(bAigEdge_t, nLatches);
+  nstates = ALLOC(bAigEdge_t, nLatches);
+  t->tstates = ALLOC(bAigEdge_t, nLatches);
+  t->initials = ALLOC(bAigEdge_t, nLatches);
+
+  nLatches = 0;
+  maxCS = 0;
+  for(j=0; j<array_n(latcharr); j++) {
+    node = array_fetch(Ntk_Node_t *, latcharr, j);
+    mAigId = Ntk_NodeReadMAigId(node);
+    mVar = array_fetch(mAigMvar_t, mVarList, mAigId);
+    index = nLatches;
+    for(i=0, index1=mVar.bVars; i<mVar.encodeLength; i++) {
+      bVar = array_fetch(mAigBvar_t, bVarList, index1++);
+      v = bVar.node;
+      cstates[index++] = v;
+      if(maxCS < v)
+	maxCS = v;
+    }
+
+    dataInput = Ntk_LatchReadDataInput(node);
+    mAigId = Ntk_NodeReadMAigId(dataInput);
+    mVar = array_fetch(mAigMvar_t, mVarList, mAigId);
+    index = nLatches;
+    for(i=0, index1=mVar.bVars; i<mVar.encodeLength; i++) {
+      bVar = array_fetch(mAigBvar_t, bVarList, index1++);
+      v = bVar.node;
+      v = bAig_GetCanonical(manager, v);
+      nstates[index++] = v;
+    }
+
+    dataInput = Ntk_LatchReadInitialInput(node);
+    mAigId = Ntk_NodeReadMAigId(dataInput);
+    mVar = array_fetch(mAigMvar_t, mVarList, mAigId);
+    index = nLatches;
+    for(i=0, index1=mVar.bVars; i<mVar.encodeLength; i++) {
+      bVar = array_fetch(mAigBvar_t, bVarList, index1++);
+      v = bVar.node;
+      v = bAig_GetCanonical(manager, v);
+      t->initials[index++] = v;
+    }
+    nLatches = index;
+  }
+
+  nInputs = 0;
+  Ntk_NetworkForEachPrimaryInput(network, gen, node) {
+    mAigId = Ntk_NodeReadMAigId(node);
+    mVar = array_fetch(mAigMvar_t, mVarList, mAigId);
+    nInputs += mVar.encodeLength;
+  }
+  Ntk_NetworkForEachPseudoInput(network, gen, node) {
+    mAigId = Ntk_NodeReadMAigId(node);
+    mVar = array_fetch(mAigMvar_t, mVarList, mAigId);
+    nInputs += mVar.encodeLength;
+  }
+  t->nInputs = nInputs;
+
+  inputs = ALLOC(bAigEdge_t, nInputs);
+  nInputs = 0;
+  Ntk_NetworkForEachPrimaryInput(network, gen, node) {
+    mAigId = Ntk_NodeReadMAigId(node);
+    mVar = array_fetch(mAigMvar_t, mVarList, mAigId);
+    for(i=0, index1=mVar.bVars; i<mVar.encodeLength; i++) {
+      bVar = array_fetch(mAigBvar_t, bVarList, index1++);
+      v = bVar.node;
+      inputs[nInputs++] = v;
+    }
+  }
+  Ntk_NetworkForEachPseudoInput(network, gen, node) {
+    mAigId = Ntk_NodeReadMAigId(node);
+    mVar = array_fetch(mAigMvar_t, mVarList, mAigId);
+    for(i=0, index1=mVar.bVars; i<mVar.encodeLength; i++) {
+      bVar = array_fetch(mAigBvar_t, bVarList, index1++);
+      v = bVar.node;
+      inputs[nInputs++] = v;
+    }
+  }
+
+  t->cstates = cstates;
+  t->nstates = nstates;
+  t->inputs = inputs;
+
+  maxCS /= bAigNodeSize;
+  maxCS++;
+  t->csize = maxCS;
+  t->cobj = ALLOC(bAigEdge_t, maxCS);
+  memset(t->cobj, 0, sizeof(bAigEdge_t)*maxCS);
+  t->c2n = ALLOC(bAigEdge_t, maxCS);
+  memset(t->c2n, 0, sizeof(bAigEdge_t)*maxCS);
+  nLatches = t->nLatches;
+  for(i=0; i<nLatches; i++) {
+    v = t->cstates[i];
+    t->c2n[SATnodeID(v)] = t->nstates[i];
+  }
+  memcpy(t->tstates, cstates, sizeof(bAigEdge_t)*t->nLatches);
+
+  t->vinputs = ALLOC(int, t->nInputs);
+  memset(t->vinputs, 0, sizeof(int)*t->nInputs);
+  t->vtstates = ALLOC(int, t->nLatches);
+  memset(t->vtstates, 0, sizeof(int)*t->nLatches);
+  
+  t->avgLits = 0;
+  t->sum = 0;
+  t->interval = 10;
+  t->period = 100;
+  array_free(latcharr);
+
+  return(t);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Create AIG for invariant property.]
+
+  Description [Create AIG for invariant property.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bAigEdge_t
+bAig_CreatebAigForInvariant(
+	Ntk_Network_t *network,
+    	bAig_Manager_t *manager,
+    	Ctlsp_Formula_t *inv)
+{
+bAigEdge_t result, left, right;
+st_table *nodeToMvfAigTable;
+int nodeValue;
+int check;    
+char *nodeNameString;
+char *nodeValueString;
+Ntk_Node_t *node;
+Var_Variable_t *nodeVar;
+MvfAig_Function_t  *tmpMvfAig;
+
+
+  if (inv == NIL(Ctlsp_Formula_t))	return mAig_NULL; 
+  if (inv->type == Ctlsp_TRUE_c) 	return mAig_One; 
+  if (inv->type == Ctlsp_FALSE_c) 	return mAig_Zero;
+
+  assert(Ctlsp_isPropositionalFormula(inv));
+
+  if (inv->type == Ctlsp_ID_c){
+    nodeNameString  = Ctlsp_FormulaReadVariableName(inv);
+    nodeValueString = Ctlsp_FormulaReadValueName(inv);
+    node = Ntk_NetworkFindNodeByName(network, nodeNameString);
+      
+    if (node == NIL(Ntk_Node_t)) {
+      fprintf(vis_stderr, "sat_inv error: Could not find node corresponding to the name\t %s\n", nodeNameString);
+      return mAig_NULL;
+    }
+
+    nodeToMvfAigTable = (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+    if (nodeToMvfAigTable == NIL(st_table)){
+      fprintf(vis_stderr, 
+	      "sat_inv error: please run build_partiton_maigs first");
+      return mAig_NULL;
+    }
+    tmpMvfAig = Bmc_ReadMvfAig(node, nodeToMvfAigTable);
+    if (tmpMvfAig ==  NIL(MvfAig_Function_t)){
+      tmpMvfAig = Bmc_NodeBuildMVF(network, node);
+      array_free(tmpMvfAig);
+      tmpMvfAig = Bmc_ReadMvfAig(node, nodeToMvfAigTable);
+    }
+      
+    nodeVar = Ntk_NodeReadVariable(node);
+    if (Var_VariableTestIsSymbolic(nodeVar)) {
+      nodeValue = Var_VariableReadIndexFromSymbolicValue(nodeVar, nodeValueString);
+      if ( nodeValue == -1 ) {
+        fprintf(vis_stderr, 
+		"Value specified in RHS is not in domain of variable\n");
+        fprintf(vis_stderr,"%s = %s\n", nodeNameString, nodeValueString);
+        return mAig_NULL;
+      }
+    }
+    else { 
+      check = StringCheckIsInteger(nodeValueString, &nodeValue);
+      if( check == 0 ) {
+        fprintf(vis_stderr,"Illegal value in the RHS\n");
+        fprintf(vis_stderr,"%s = %s\n", nodeNameString, nodeValueString);
+        return mAig_NULL;
+      }
+      if( check == 1 ) {
+        fprintf(vis_stderr,"Value in the RHS is out of range of int\n");
+        fprintf(vis_stderr,"%s = %s", nodeNameString, nodeValueString);
+        return mAig_NULL;
+      }
+      if ( !(Var_VariableTestIsValueInRange(nodeVar, nodeValue))) {
+        fprintf(vis_stderr,"Value specified in RHS is not in domain of variable\n");
+        fprintf(vis_stderr,"%s = %s\n", nodeNameString, nodeValueString);
+        return mAig_NULL;
+      }
+    }
+    result = bAig_GetCanonical(manager,
+	      MvfAig_FunctionReadComponent(tmpMvfAig, nodeValue));
+    return result;
+  }
+
+  left = bAig_CreatebAigForInvariant(network, manager, inv->left);
+  if (left == mAig_NULL){
+    return mAig_NULL;
+  }  
+  right = bAig_CreatebAigForInvariant(network, manager, inv->right);
+
+  if (right == mAig_NULL && inv->type ==Ctlsp_NOT_c ){
+    return mAig_Not(left);
+  }  
+  else if(right == mAig_NULL) {
+    return mAig_NULL;
+  }
+
+  switch(inv->type) {
+    case Ctlsp_OR_c:
+      result = mAig_Or(manager, left, right);
+      break;
+    case Ctlsp_AND_c:
+      result = mAig_And(manager, left, right);
+      break;
+    case Ctlsp_THEN_c:
+      result = mAig_Then(manager, left, right); 
+      break;
+    case Ctlsp_EQ_c:
+      result = mAig_Eq(manager, left, right);
+      break;
+    case Ctlsp_XOR_c:
+      result = mAig_Xor(manager, left, right);
+      break;
+    default:
+      fail("Unexpected LTL type");
+  }
+  return result;
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Compute AG.]
+
+  Description [Compute AG.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+bAigCheckInvariantWithAG(
+	bAigTransition_t *t,
+	bAigEdge_t objective)
+{
+int included, returnFlag;
+bAig_Manager_t *manager;
+satManager_t *cm;
+long frontierNodesBegin;
+
+  manager = t->manager;
+  bAigCleanUpDataFromPreviousExecution(t);
+
+  /** This is for applying SAT-based AX operation **/
+  objective = bAig_Not(objective);
+  t->objective = objective;
+  returnFlag = 0;
+
+  while(1) {
+    /** 
+     * This function do nothing in the first iteration, 
+     * since no frontier is provided at first.
+     * Instead of frontier, we have complemented objective at first
+     **/
+
+    if(t->verbose > 1) 
+      fprintf(vis_stdout, "** SAT_INV : %d'th pre-image is being computed\n", t->iteration+1);
+
+    frontierNodesBegin = manager->nodesArraySize;
+    if(t->iteration > 0) {
+      bAigBuildObjectiveFromFrontierSet(t);
+      if(t->frontier->num <= 1) {
+        returnFlag = 1; /** property passed **/
+	break;
+      }
+    }
+    
+    cm = bAigCirCUsInterfaceForAX(t);
+    cm->frontierNodesBegin = frontierNodesBegin;
+
+    t->allsat = cm;
+  
+
+    sat_CleanDatabase(cm);
+
+    bAigMarkConeOfInfluenceForAX(t, cm);
+
+    fflush(vis_stdout);
+
+    bAig_ComputeAX(t);
+
+    if(t->verbose > 1) {
+      sat_ReportStatistics(cm, cm->each);
+    }
+
+    included = bAigInclusionTestOnInitialStates(t);
+    if(included == 0) {
+      returnFlag = 2; /** propoerty failed **/
+    }
+
+    /** reched to convergenece **/
+    if(t->frontier->num <= 1) {
+      returnFlag = 1; /** property passed **/
+    }
+
+
+    bAig_PostProcessForAX(t, cm);
+    t->manager->nodesArraySize = frontierNodesBegin;
+    t->allsat = 0;
+
+    if(t->lifting) {
+      sat_FreeManager(t->lifting);
+      t->lifting = 0;
+    }
+
+    if(t->originalFrontier) {
+      sat_ArrayFree(t->originalFrontier);
+      t->originalFrontier = 0;
+    }
+
+    if(returnFlag) {
+      break;
+    }
+    t->iteration++;
+  } 
+
+  if(t->verbose > 0) {
+    fprintf(vis_stdout, "** SAT_INV : Total %d pre-image is computed\n", t->iteration+1);
+  }
+
+  sat_ArrayFree(t->frontier);
+  t->frontier = 0;
+  sat_ArrayFree(t->reached);
+  t->reached = 0;
+
+  fflush(vis_stdout);
+
+  return(returnFlag);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Reduce the number of blocking clauses based on UNSAT core generation.]
+
+  Description [Reduce the number of blocking clauses based on UNSAT core generation.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAigReduceBlockingClauseWithUnsatCore(bAigTransition_t *t)
+{
+satArray_t *cnfArray;
+satArray_t *coreArray;
+satArray_t *rootArray;
+satOption_t *option;
+satManager_t *cm;
+st_table *mappedTable;
+char filename[1024];
+int flag, i, size;
+bAigEdge_t v, nv, *plit;
+
+  cnfArray = sat_ArrayAlloc(1024);
+  mappedTable = st_init_table(st_numcmp, st_numhash);
+
+  sat_ArrayInsert(cnfArray, 0);
+  cm = t->allsat;
+  /** Collect CNF from frontier of previous run **/
+  for(v = cm->frontierNodesBegin; v<cm->frontierNodesEnd; v+= satNodeSize) {
+    if(!(SATflags(v) & IsCNFMask))	continue;
+    size = SATnumLits(v);
+    plit = (long*)SATfirstLit(v);
+    for(i=0; i<size; i++, plit++) {
+      nv = SATgetNode(*plit);
+      sat_ArrayInsert(cnfArray, nv);
+      nv = SATnormalNode(nv);
+      SATflags(nv) |= VisitedMask;
+    }
+    sat_ArrayInsert(cnfArray, 0);
+  }
+
+  /** Collect transition function(AIG) for CNF translation **/
+  rootArray = sat_ArrayAlloc(t->nLatches);
+  for(i=0; i<t->nLatches; i++) {
+    v = t->nstates[i];
+    v = SATnormalNode(v);
+    if(v>1 && (SATflags(v) & VisitedMask))
+      sat_ArrayInsert(rootArray, v);
+  }
+  for(i=0; i<rootArray->num; i++) {
+    v = rootArray->space[i];
+    SATflags(v) &= ResetVisitedMask;
+  }
+
+  if(cm->maxNodesArraySize > t->manager->maxNodesArraySize) {
+    t->manager->maxNodesArraySize = cm->maxNodesArraySize;
+    t->manager->nameList   = REALLOC(char *, t->manager->nameList  , t->manager->maxNodesArraySize/bAigNodeSize);
+    t->manager->bddIdArray = REALLOC(int ,   t->manager->bddIdArray  , t->manager->maxNodesArraySize/bAigNodeSize);
+    t->manager->bddArray   = REALLOC(bdd_t *, t->manager->bddArray  , t->manager->maxNodesArraySize/bAigNodeSize);
+  }
+  t->manager->maxNodesArraySize = cm->maxNodesArraySize;
+  t->manager->NodesArray = cm->nodesArray;
+  bAig_CreateCNFFromAIG(t->manager, rootArray, cnfArray);
+  sat_ArrayFree(rootArray);
+
+  /** Collect all previous blocking clauses **/
+  for(v = cm->frontierNodesEnd; v<cm->nodesArraySize; v+= satNodeSize) {
+    if(!(SATflags(v) & IsCNFMask))	continue;
+    if(!(SATflags(v) & IsBlockingMask))	continue;
+    size = SATnumLits(v);
+    plit = (long*)SATfirstLit(v);
+    for(i=0; i<size; i++, plit++) {
+      nv = SATgetNode(*plit);
+      sat_ArrayInsert(cnfArray, nv);
+    }
+    sat_ArrayInsert(cnfArray, -v);
+  }
+
+  /** add objecitve into CNF instance **/
+  sat_ArrayInsert(cnfArray, t->objective);
+  sat_ArrayInsert(cnfArray, 0);
+
+  option = sat_InitOption();
+
+  if(t->verbose > 2) {
+    sprintf(filename, "core%d.cnf", t->iteration);
+    sat_WriteCNFFromArray(cnfArray, filename);
+  }
+  coreArray = sat_ArrayAlloc(1024);
+  flag = sat_CNFMainWithArray(option, cnfArray, 1, coreArray, mappedTable);
+
+  if(flag == SAT_SAT)	{
+    sprintf(filename, "core%d.cnf", t->iteration);
+    fprintf(stdout, "ERROR : this instance %s should be UNSAT\n", filename);
+    sat_WriteCNFFromArray(cnfArray, filename);
+  }
+
+  for(i=0; i<coreArray->num; i++) {
+    v = coreArray->space[i];
+    if(st_lookup(mappedTable, (char *)v, &nv)) {
+      /* If a clause is blocking clause then it is in the table **/
+      SATflags(nv) |= InCoreMask;    
+    }
+    /**
+    else {
+      fprintf(stdout, "ERROR : the clause %ld should be in the mapping table\n", v);
+    }
+    **/
+  }
+  for(v=satNodeSize; v<cm->nodesArraySize; v+=satNodeSize) {
+    if(!(SATflags(v) & IsCNFMask))
+      continue;
+    if(!(SATflags(v) & IsBlockingMask))
+      continue;
+    if(!(SATflags(v) & IsFrontierMask))
+      continue;
+    if((SATflags(v) & InCoreMask))
+      continue;
+
+    SATresetInUse(v);
+    if(t->verbose > 4) {
+      fprintf(vis_stdout, "NOTICE : deleted blocking clause\n");
+      sat_PrintNode(cm, v);
+    }
+  }
+
+
+  st_free_table(mappedTable);
+  sat_ArrayFree(cnfArray);
+  sat_ArrayFree(coreArray);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Check if the initial states are included in conjunction of block clauses.]
+
+  Description [Check if the initial states are included in conjunction of block clauses. It is done by checking satisfiability of formula (I \wedge \neg B).
+ If it is unsatisfiable then all the initial states are included in B.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+bAigInclusionTestOnInitialStates(bAigTransition_t *t)
+{
+satArray_t *cnfArray;
+satOption_t *option;
+char filename[1024];
+int flag;
+
+  if(t->inclusionInitial == 0)	return(1);
+
+  cnfArray = bAigCreateCNFInstanceForInclusionTestOnInitialStates(t);
+  option = sat_InitOption();
+
+  if(t->verbose > 2) {
+    sprintf(filename, "init%d.cnf", t->iteration);
+    sat_WriteCNFFromArray(cnfArray, filename);
+  }
+  flag = sat_CNFMainWithArray(option, cnfArray, 0, 0, 0);
+  sat_ArrayFree(cnfArray);
+
+  if(flag == SAT_UNSAT)	return(1);
+  else			return(0);
+
+  return(1);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Create instance for initial states inclusion test]
+
+  Description [Create instance for initial states inclusion test]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+satArray_t *
+bAigCreateCNFInstanceForInclusionTestOnInitialStates(bAigTransition_t *t)
+{
+satArray_t *cnfArray, *frontier;
+satArray_t *andArr, *orArr, *fandArr, *clause;
+satArray_t *rootArray;
+bAigEdge_t v, cv, out, objective;
+bAigEdge_t maxIndex;
+long *space;
+int i, j;
+int nCls;
+
+  maxIndex = 0;
+  for(i=0; i<t->nLatches; i++) {
+    v = t->cstates[i];
+    if(maxIndex < v) 	maxIndex = v;
+  }
+  maxIndex += bAigNodeSize;
+ 
+  cnfArray = sat_ArrayAlloc(2048);
+  andArr = sat_ArrayAlloc(1024);
+  orArr = sat_ArrayAlloc(1024);
+  fandArr = sat_ArrayAlloc(1024);
+  clause = sat_ArrayAlloc(1024);
+ 
+  nCls = 0;
+  frontier = t->frontier; 
+  sat_ArrayInsert(cnfArray, 0);
+  for(i=0, space=frontier->space; i<frontier->num; i++, space++) {
+    if(*space <= 0) { /** 0 or -1 is seperator between clauses **/
+      space++;
+      i++;
+
+      if(i >= frontier->num) {
+	break;
+      }
+
+      fandArr->num = 0;
+      andArr->num = 0;
+      while(*space > 0) {
+	sat_ArrayInsert(fandArr, *space);
+	i++;
+	space++;
+      }
+      i--;
+      space--;
+
+
+      for(j=0; j<fandArr->num; j++) {
+	v = fandArr->space[j];
+	sat_ArrayInsert(andArr, v);
+      }
+
+      out = maxIndex;
+      maxIndex += bAigNodeSize;
+      sat_ArrayInsert(orArr, out);
+
+      for(j=0; j<andArr->num; j++) {
+	v = andArr->space[j];
+	sat_ArrayInsert(cnfArray, SATnot(v));
+	sat_ArrayInsert(cnfArray, SATnot(out));
+	sat_ArrayInsert(cnfArray, -1); /** seperator **/
+	nCls++;
+      }
+
+      for(j=0; j<andArr->num; j++) {
+	v = andArr->space[j];
+	sat_ArrayInsert(cnfArray, v);
+      }
+      sat_ArrayInsert(cnfArray, out);
+      sat_ArrayInsert(cnfArray, -1);
+      nCls++;
+    }
+  }
+
+  objective = maxIndex;
+  maxIndex += bAigNodeSize;
+  for(i=0; i<orArr->num; i++) {
+    v = orArr->space[i];
+    sat_ArrayInsert(cnfArray, SATnot(v));
+    sat_ArrayInsert(cnfArray, objective);
+    sat_ArrayInsert(cnfArray, -1);
+    nCls++;
+  }
+  for(i=0; i<orArr->num; i++) {
+    v = orArr->space[i];
+    sat_ArrayInsert(cnfArray, v);
+  }
+
+  sat_ArrayInsert(cnfArray, SATnot(objective));
+
+  sat_ArrayInsert(cnfArray, -1);
+  nCls++;
+
+  /** assert objective **/
+  sat_ArrayInsert(cnfArray, objective);
+  sat_ArrayInsert(cnfArray, -1);
+  nCls++;
+
+  sat_ArrayFree(andArr);
+  sat_ArrayFree(orArr);
+  sat_ArrayFree(fandArr);
+  sat_ArrayFree(clause);
+
+
+  /** Collect AIG for CNF translation **/
+  rootArray = sat_ArrayAlloc(t->nLatches);
+  for(i=0; i<t->nLatches; i++) {
+    v = t->initials[i];
+    if(v>1)
+      sat_ArrayInsert(rootArray, v);
+  }
+
+  if(t->allsat->maxNodesArraySize > t->manager->maxNodesArraySize) {
+    t->manager->maxNodesArraySize = t->allsat->maxNodesArraySize;
+    t->manager->nameList   = REALLOC(char *, t->manager->nameList  , t->manager->maxNodesArraySize/bAigNodeSize);
+    t->manager->bddIdArray = REALLOC(int ,   t->manager->bddIdArray  , t->manager->maxNodesArraySize/bAigNodeSize);
+    t->manager->bddArray   = REALLOC(bdd_t *, t->manager->bddArray  , t->manager->maxNodesArraySize/bAigNodeSize);
+  }
+  t->manager->maxNodesArraySize = t->allsat->maxNodesArraySize;
+  t->manager->NodesArray = t->allsat->nodesArray;
+  bAig_CreateCNFFromAIG(t->manager, rootArray, cnfArray);
+  sat_ArrayFree(rootArray);
+
+  /** 
+   * connect AIG root and current state variable with equivalence
+   * relation 
+   * **/
+  for(i=0; i<t->nLatches; i++) {
+    v = t->initials[i];
+    cv = t->cstates[i];
+    if(v == 0) {
+      sat_ArrayInsert(cnfArray, SATnot(cv));
+      sat_ArrayInsert(cnfArray, -1);
+    }
+    else if(v == 1) {
+      sat_ArrayInsert(cnfArray, cv);
+      sat_ArrayInsert(cnfArray, -1);
+    }
+    else {
+      sat_ArrayInsert(cnfArray, SATnot(v));
+      sat_ArrayInsert(cnfArray, (cv));
+      sat_ArrayInsert(cnfArray, -1);
+      sat_ArrayInsert(cnfArray, (v));
+      sat_ArrayInsert(cnfArray, SATnot(cv));
+      sat_ArrayInsert(cnfArray, -1);
+    }
+  }
+
+  return(cnfArray);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Create instance for AIG]
+
+  Description [Create instance for AIG]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAig_CreateCNFFromAIG(
+	bAig_Manager_t *manager,
+	satArray_t *rootArray,
+	satArray_t *cnfArray)
+{
+int i;
+bAigEdge_t v, left, right;
+
+  for(i=0; i<rootArray->num; i++) {
+    v = rootArray->space[i];
+    bAig_SetMaskTransitiveFanin(manager, v, VisitedMask);
+  }
+
+  for(v=bAigFirstNodeIndex ; v<manager->nodesArraySize; v+=bAigNodeSize){
+    if(flags(v) & IsCNFMask) 
+      continue;
+    if(flags(v) & VisitedMask) {
+      /** create CNF for this AIG **/
+      left = leftChild(v);
+      if(left == 2)
+	continue;
+      right = rightChild(v);
+
+      sat_ArrayInsert(cnfArray, SATnot(left));
+      sat_ArrayInsert(cnfArray, SATnot(right));
+      sat_ArrayInsert(cnfArray, (v));
+      sat_ArrayInsert(cnfArray, -1);
+      sat_ArrayInsert(cnfArray, (left));
+      sat_ArrayInsert(cnfArray, SATnot(v));
+      sat_ArrayInsert(cnfArray, -1);
+      sat_ArrayInsert(cnfArray, (right));
+      sat_ArrayInsert(cnfArray, SATnot(v));
+      sat_ArrayInsert(cnfArray, -1);
+    }
+  }
+
+  for(i=0; i<rootArray->num; i++) {
+    v = rootArray->space[i];
+    bAig_ResetMaskTransitiveFanin(manager, v, VisitedMask, ResetVisitedMask);
+  }
+  return;
+}
+		      
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compute AX based on SAT.]
+
+  Description [Compute AX based on SAT.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAig_ComputeAX(bAigTransition_t *t)
+{
+satManager_t *cm;
+long btime, etime;
+
+  btime = util_cpu_time();
+
+  cm = t->allsat;
+  sat_PreProcessingForMixed(cm);
+
+  if(cm->status == 0) {
+    if(t->constrain)
+      bAigCreateSatManagerForLifting(t);
+    else 
+      bAigCreateSatManagerForLiftingUnconstrained(t);
+  /**
+    **/
+    bAigSolveAllSatWithLifting(t);
+    if(t->iteration > 0 && t->reductionUsingUnsat)
+      bAigReduceBlockingClauseWithUnsatCore(t);
+  }
+
+  sat_PostProcessing(cm);
+
+  /** Copy to transition so that they can be used for next iteration **/
+  t->reached = cm->reached;
+  t->frontier = cm->frontier;
+  cm->reached = 0;
+  cm->frontier = 0;
+
+  etime = util_cpu_time();
+  cm->each->satTime = (double)(etime - btime) / 1000.0 ;
+  fflush(vis_stdout);
+  return;
+  
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Enumerate solution with lifting.]
+
+  Description [Enumerate solution with lifting.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAigSolveAllSatWithLifting(bAigTransition_t *t)
+{
+satManager_t *cm;
+satLevel_t *d;
+satOption_t *option;
+int level;
+
+  cm = t->allsat;
+
+  d = SATgetDecision(0);
+  cm->implicatedSoFar = d->implied->num;
+  cm->currentTopConflict = 0;
+
+  option = cm->option;
+
+  /**
+  option->decisionHeuristic = 0;
+  option->decisionHeuristic |= DVH_DECISION;
+  **/
+
+  if(cm->status == SAT_UNSAT) {
+    sat_Undo(cm, SATgetDecision(0));
+    return;
+  }
+
+  while(1) {
+    sat_PeriodicFunctions(cm);
+
+    d = sat_MakeDecision(cm);
+
+    if(d == 0)	{
+      bAigBlockingClauseAnalysisBasedOnLifting(t, cm);
+
+      if(cm->currentDecision == -1) {
+        sat_Undo(cm, SATgetDecision(0));
+	cm->status = SAT_UNSAT;
+	return;
+      }
+      d = SATgetDecision(cm->currentDecision);
+    }
+
+    while(1) {
+      sat_ImplicationMain(cm, d);
+
+      if(d->conflict == 0)	
+	break;
+
+      level = sat_ConflictAnalysis(cm, d);
+
+      if(cm->currentDecision == -1) {
+        sat_Undo(cm, SATgetDecision(0));
+	cm->status = SAT_UNSAT;
+	return;
+      }
+
+      d = SATgetDecision(cm->currentDecision);
+    }
+  }
+
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Apply minimization based on lifting and create blocking clause.]
+
+  Description [Apply minimization based on lifting and create blocking clause.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAigBlockingClauseAnalysisBasedOnLifting(bAigTransition_t *t, satManager_t *allsat)
+{
+satManager_t *cm;
+satLevel_t *d;
+satArray_t *clauseArray;
+bAigEdge_t v, obj, blocked, fdaLit;
+int objInverted, inverted;
+int i, satisfied;
+int value, tvalue;
+int mLevel, bLevel;
+
+  cm = allsat;
+  for(i=0; i<t->nInputs; i++) {
+    v = t->inputs[i];
+    t->vinputs[i] = SATvalue(v);
+  }
+
+  SATcm = allsat;
+  qsort(t->tstates, t->nLatches, sizeof(bAigEdge_t), levelCompare);
+
+  for(i=0; i<t->nLatches; i++) {
+    v = t->tstates[i];
+    t->vtstates[i] = SATvalue(v);
+  }
+
+  /** cm is lifting instance from now on **/
+  cm = t->lifting;
+
+  obj = (bAigEdge_t )cm->obj->space[0];
+  objInverted = SATisInverted(obj);
+  obj = SATnormalNode(obj);
+
+  d = sat_AllocLevel(cm);
+  satisfied = 0;
+
+  clauseArray = sat_ArrayAlloc(256);
+  clauseArray->num = 0;
+
+  /** 
+   * Propagate primary input variable first, 
+   * since  they can be freely qunatified
+   **/
+  for(i=0; i<t->nInputs; i++) {
+    if(satisfied)	break;
+    v = t->inputs[i];
+    if(!(SATflags(v) & CoiMask))	continue;
+
+    value = t->vinputs[i];
+    if(value > 1)	continue;
+    tvalue = SATvalue(v);
+    if(tvalue < 2)	continue;
+
+    SATvalue(v) = value;
+    SATmakeImplied(v, d);
+    sat_Enqueue(cm->queue, v);
+    SATflags(v) |= InQueueMask;
+
+    sat_ImplicationMain(cm, d);
+
+    value = SATvalue(obj);
+    if(value < 2)	satisfied = 1;	
+  }
+
+  /** 
+   * Propagate current state variable to apply greedy minization.
+   * Save candidates variable for lifting to clauseArray 
+   **/
+  if(satisfied == 0) {
+    d = sat_AllocLevel(cm);
+    for(i=0; i<t->nLatches; i++) {
+      if(satisfied)	break;
+      v = t->tstates[i];
+      if(!(SATflags(v) & CoiMask))	continue;
+
+      value = t->vtstates[i];
+      if(value > 1)	continue; /** exceptional case **/
+      tvalue = SATvalue(v);
+  
+      /** 
+       * If a current state variable is implied by other state variable
+       * sasignments then it is part of candidate variable
+       **/
+      sat_ArrayInsert(clauseArray, v^(!value));
+  
+      if(tvalue > 1) {
+        SATvalue(v) = value;
+        SATmakeImplied(v, d);
+        sat_Enqueue(cm->queue, v);
+        SATflags(v) |= InQueueMask;
+    
+        sat_ImplicationMain(cm, d);
+        value = SATvalue(obj);
+        if(value < 2)	satisfied = 1;	
+      }
+    }
+  }
+
+  value = SATvalue(obj);
+  if(value > 1) {
+    fprintf(stdout, "ERROR : Can't justify objective %ld\n", t->objective);
+    exit(0);
+  }
+
+  if(clauseArray->num == 0) { 
+    /** the objective is satified with primary input only **/
+    sat_Backtrack(cm, 0);
+    cm->currentDecision--;
+
+    sat_Backtrack(allsat, 0);
+    allsat->currentDecision--;
+    return;
+  }
+
+
+  bAigCollectAntecdentOfObjective(t, cm, t->objective, clauseArray);
+
+  if(clauseArray->num == 0) { 
+    /** the objective is satified with primary input only **/
+    fprintf(stdout, "ERROR : This might be the bug after greedy heuristic\n");
+    sat_Backtrack(cm, 0);
+    cm->currentDecision--;
+
+    return;
+  }
+
+  sat_Backtrack(cm, 0);
+  d = SATgetDecision(cm->currentDecision);
+  sat_Undo(cm, d);
+  cm->currentDecision--;
+
+  /**
+  bAigMinimizationBasedOnLifting(t, t->objective, clauseArray);
+  **/
+  if(t->disableLifting == 0)
+    bAigMinimizationBasedOnLiftingAllAtOnce(t, t->objective, clauseArray);
+
+  if(clauseArray->num == 0) { 
+    /** the objective is satified with primary input only **/
+    /**
+    fprintf(stdout, "ERROR : This might be the bug after lifting\n");
+    **/
+
+    if(cm->currentDecision >= 0) {
+      sat_Backtrack(cm, 0);
+      cm->currentDecision--;
+    }
+
+    sat_Backtrack(allsat, 0);
+    allsat->currentDecision--;
+
+    return;
+  }
+
+  /** operation on all sat instance **/
+  cm = t->allsat;
+
+  mLevel = 0;
+  for(i=0; i<clauseArray->num; i++) {
+    v = clauseArray->space[i];
+    v = SATnormalNode(v);
+    if(mLevel < SATlevel(v))
+      mLevel = SATlevel(v);
+  }
+
+  blocked = sat_AddBlockingClause(cm, clauseArray);
+  SATflags(blocked) |= IsFrontierMask;
+
+  if(t->verbose > 3)
+    sat_PrintNode(cm, blocked);
+
+  sat_Backtrack(cm, mLevel);
+  d = SATgetDecision(cm->currentDecision);
+
+  if(t->verbose > 3) {
+    qsort(clauseArray->space, clauseArray->num, sizeof(long), indexCompare);
+    for(i=0; i<clauseArray->num; i++) {
+      fprintf(stdout, "%ld ", clauseArray->space[i]);
+    }
+    fprintf(stdout, "\n");
+  }
+
+  if(bAigCheckExistenceOfUIP(cm, clauseArray, mLevel, &fdaLit, &bLevel)) {
+    sat_Backtrack(cm, bLevel);
+
+    if(SATlevel(fdaLit) == 0) {
+      sat_Backtrack(cm, 0);
+      cm->currentDecision = -1;
+      sat_ArrayFree(clauseArray);
+      return;
+    }
+
+    d = SATgetDecision(cm->currentDecision);
+    inverted = SATisInverted(fdaLit);
+    fdaLit = SATnormalNode(fdaLit);
+    SATante(fdaLit) = blocked;
+    SATvalue(fdaLit) = inverted;
+    SATmakeImplied(fdaLit, d);
+    
+    if((SATflags(fdaLit) & InQueueMask)  == 0) {
+      sat_Enqueue(cm->queue, fdaLit);
+      SATflags(fdaLit) |= InQueueMask;
+    }
+  }
+  else {
+    d->conflict = blocked;
+    sat_ConflictAnalysisWithBlockingClause(cm, d);
+  }
+
+  sat_ArrayFree(clauseArray);
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Apply minization based on checking antecedent of objective.]
+
+  Description [Apply minization based on checking antecedent of objective.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+bAigCheckExistenceOfUIP(
+	satManager_t *cm, 
+	satArray_t *clauseArray, 
+	int mLevel, 
+	bAigEdge_t *fdaLit, 
+	int *bLevel)
+{
+int i, nLit, level;
+int uipFlag;
+bAigEdge_t v, ante;
+
+  nLit = 0;
+  *bLevel = 0;
+  *fdaLit = 0;
+  uipFlag = 0;
+  for(i=0; i<clauseArray->num; i++) {
+    v = clauseArray->space[i];
+    v = SATnormalNode(v);
+    level = SATlevel(v);
+    if(level == mLevel) {
+      nLit++;
+      if(nLit > 1)
+	break;
+
+      ante = SATante(v);
+      if(ante == 0) {
+	uipFlag = 1;
+	*fdaLit = clauseArray->space[i];
+      }
+    }
+    else if(*bLevel < level)
+      *bLevel = level;
+  }
+
+  if(nLit > 1)
+    uipFlag = 0;
+
+  if(uipFlag)	return(1);
+  else		return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Apply minization based on checking antecedent of objective.]
+
+  Description [Apply minization based on checking antecedent of objective.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAigMinimizationBasedOnLifting(
+	bAigTransition_t *t, 
+	bAigEdge_t obj,
+	satArray_t *orderArray)
+{
+satManager_t *allsat, *cm;
+satLevel_t *d;
+satArray_t *tmpArray;
+satArray_t *notLiftableArray;
+bAigEdge_t v, tv, *plit;
+bAigEdge_t lastNode, lastLit, ante;
+int inverted, inserted;
+int tvalue, value, bLevel;
+int i, j, size;
+
+  cm = t->lifting;
+  allsat = t->allsat;
+  /** 
+   * This is for incremental SAT to identified objective dependent conflict
+   * clauses
+   **/
+  cm->option->includeLevelZeroLiteral = 1;
+  lastLit = cm->literals->last-cm->literals->begin;
+  lastNode = cm->nodesArraySize;
+
+  /** 
+   * Make level 0 implication  
+   * 1. Primary input since they are not the target of lifting
+   * 2. Unit and pure literals..
+   * 3. Complemented objective
+   **/
+  d = sat_AllocLevel(cm);
+  for(i=0; i<t->nInputs; i++) {
+    v = t->inputs[i];
+    if(!(SATflags(v) & CoiMask))	continue;
+    value = t->vinputs[i];
+
+    SATvalue(v) = value;
+    SATmakeImplied(v, d);
+    sat_Enqueue(cm->queue, v);
+    SATflags(v) |= InQueueMask;
+
+  }
+  sat_ImplyArray(cm, d, cm->assertion);
+  sat_ImplyArray(cm, d, cm->unitLits);
+  sat_ImplyArray(cm, d, cm->pureLits);
+  sat_ImplyArray(cm, d, cm->auxObj);
+  sat_ImplyArray(cm, d, cm->nonobjUnitLitArray);
+
+  value = SATisInverted(obj);
+  v = SATnormalNode(obj);
+  SATvalue(v) = value;
+  SATmakeImplied(v, d);
+  if((SATflags(v) & InQueueMask) == 0) {
+    sat_Enqueue(cm->queue, v);
+    SATflags(v) |= InQueueMask;
+  }
+  sat_ImplicationMain(cm, d);
+
+  /** Apply lifting **/
+  for(i=0; i<orderArray->num; i++) {
+    cm->status = 0;
+
+    /** check liftability of i'th variable on order array */
+
+    tv = orderArray->space[i];
+    v = SATnormalNode(tv);
+    value = SATvalue(v);
+    if(value < 2) { /** implied by other decisions */
+      continue;
+    }
+    value = !SATisInverted(tv);
+    SATvalue(v) = value;
+
+    d = sat_AllocLevel(cm);
+
+    SATmakeImplied(v, d);
+    if((SATflags(v) & InQueueMask) == 0) {
+      sat_Enqueue(cm->queue, v);
+      SATflags(v) |= InQueueMask;
+    }
+    sat_ImplicationMain(cm, d);
+  }
+
+  /** check liftability of i'th variable on order array */
+  notLiftableArray = sat_ArrayAlloc(orderArray->num);
+  for(i=orderArray->num-1; i>=0; i--) {
+      /** to identify previous decision **/
+    while(1) {
+      if(i<0) break;
+      tv = orderArray->space[i];
+      v = SATnormalNode(tv);
+      value = SATvalue(v);
+      ante = SATante(v);
+      if(ante) { /** implied by other decisions */
+        tvalue = !SATisInverted(tv);
+	if(tvalue == value)
+          sat_ArrayInsert(notLiftableArray, tv);
+	i--;
+	continue;
+      }
+      else { /** decision variable **/
+	sat_Backtrack(cm, SATlevel(v)-1);
+	break;
+      }
+    }
+    if(i<0)	break;
+
+    bLevel = cm->currentDecision;
+
+    tv = orderArray->space[i];
+    value = SATisInverted(tv); /** assign complemented value **/
+    SATvalue(v) = value;
+
+    d = sat_AllocLevel(cm);
+    SATmakeImplied(v, d);
+    if((SATflags(v) & InQueueMask) == 0) {
+      sat_Enqueue(cm->queue, v);
+      SATflags(v) |= InQueueMask;
+    }
+    sat_ImplicationMain(cm, d);
+
+    if(d->conflict) { /** the variable can be lifted **/
+      sat_Backtrack(cm, bLevel);
+      continue;
+    }
+
+    for(j=0; j<notLiftableArray->num; j++) {
+      v = notLiftableArray->space[j];
+      value = !SATisInverted(v);
+      v = SATnormalNode(v);
+      tvalue = SATvalue(v);
+      if(tvalue < 2 && tvalue != value) {
+	/** the variable can be lifted **/
+        sat_Backtrack(cm, bLevel);
+	d->conflict = v;
+        continue;
+      }
+      SATvalue(v) = value;
+      SATmakeImplied(v, d);
+      if((SATflags(v) & InQueueMask) == 0) {
+        sat_Enqueue(cm->queue, v);
+        SATflags(v) |= InQueueMask;
+      }
+      sat_ImplicationMain(cm, d);
+      if(d->conflict) { /** the variable can be lifted **/
+        break;
+      }
+    }
+
+    if(d->conflict) { /** the variable can be lifted **/
+      sat_Backtrack(cm, bLevel);
+      continue;
+    }
+
+    bAigSolverForLifting(cm, cm->currentDecision); /** Need further decision **/
+    /** There is a case that the implication queue is not empty **/
+    sat_CleanImplicationQueue(cm);
+    if(cm->status == SAT_SAT) {
+      sat_ArrayInsert(notLiftableArray, tv); 
+    }
+    sat_Backtrack(cm, bLevel);
+  }
+
+  memcpy(orderArray->space, notLiftableArray->space, sizeof(long)*notLiftableArray->num);
+  orderArray->num = notLiftableArray->num;
+  sat_ArrayFree(notLiftableArray);
+
+  sat_Backtrack(cm, 0);
+  d = SATgetDecision(cm->currentDecision);
+  sat_Undo(cm, d);
+  cm->currentDecision--;
+  cm->status = 0;
+
+
+  /** Forward clauses from lifting process to allsat process **/
+  /** Need to review this code **/
+  tmpArray = sat_ArrayAlloc(64);
+  for(i=lastNode; i<cm->nodesArraySize; i+=satNodeSize) {
+    size = SATnumLits(i);
+    plit = (long*)SATfirstLit(i);
+    inserted = 0;
+    tmpArray->num = 0;
+    for(j=0; j<size; j++, plit++) {
+      v = SATgetNode(*plit);
+      inverted = SATisInverted(v);
+      v = SATnormalNode(v);
+      value = (allsat->nodesArray[v+satValue]) ;
+      value = value ^ inverted;
+      /** To check if the clause is safe to add allsat instance **/
+      if(value > 0)
+        inserted = 1;
+      sat_ArrayInsert(tmpArray, v^(!inverted));
+    }
+    if(inserted)
+      sat_AddConflictClause(allsat, tmpArray, 0);
+  }
+  sat_ArrayFree(tmpArray);
+
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Apply minization based on checking antecedent of objective.]
+
+  Description [Apply minization based on checking antecedent of objective.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAigMinimizationBasedOnLiftingAllAtOnce(
+	bAigTransition_t *t, 
+	bAigEdge_t obj,
+	satArray_t *orderArray)
+{
+satManager_t *allsat, *cm;
+satLevel_t *d;
+satArray_t *implied;
+satArray_t *notLiftableArray;
+bAigEdge_t v, tv;
+bAigEdge_t lastNode, lastLit;
+long *space;
+int value;
+int i, j, size, num;
+
+  cm = t->lifting;
+  allsat = t->allsat;
+  /** 
+   * This is for incremental SAT to identified objective dependent conflict
+   * clauses
+   **/
+  cm->option->includeLevelZeroLiteral = 1;
+  lastLit = cm->literals->last-cm->literals->begin;
+  lastNode = cm->nodesArraySize;
+
+  /** 
+   * Make level 0 implication  
+   * 1. Primary input since they are not the target of lifting
+   * 2. Unit and pure literals..
+   * 3. Complemented objective
+   **/
+  d = sat_AllocLevel(cm);
+  for(i=0; i<t->nInputs; i++) {
+    v = t->inputs[i];
+    if(!(SATflags(v) & CoiMask))	continue;
+    value = t->vinputs[i];
+
+    SATvalue(v) = value;
+    SATmakeImplied(v, d);
+    sat_Enqueue(cm->queue, v);
+    SATflags(v) |= InQueueMask;
+
+  }
+  sat_ImplyArray(cm, d, cm->assertion);
+  sat_ImplyArray(cm, d, cm->unitLits);
+  sat_ImplyArray(cm, d, cm->pureLits);
+  sat_ImplyArray(cm, d, cm->auxObj);
+  sat_ImplyArray(cm, d, cm->nonobjUnitLitArray);
+
+  value = SATisInverted(obj);
+  v = SATnormalNode(obj);
+  SATvalue(v) = value;
+  SATmakeImplied(v, d);
+  if((SATflags(v) & InQueueMask) == 0) {
+    sat_Enqueue(cm->queue, v);
+    SATflags(v) |= InQueueMask;
+  }
+  sat_ImplicationMain(cm, d);
+
+  /** Apply lifting **/
+  num = d->implied->num;
+  notLiftableArray = sat_ArrayAlloc(orderArray->num);
+  for(i=0; i<orderArray->num; i++) {
+    cm->status = 0;
+    d->conflict = 0;
+
+    /** check liftability of i'th variable on order array */
+
+    tv = orderArray->space[i];
+    v = SATnormalNode(tv);
+    value = SATisInverted(tv);
+    SATvalue(v) = value;
+
+    SATmakeImplied(v, d);
+    if((SATflags(v) & InQueueMask) == 0) {
+      sat_Enqueue(cm->queue, v);
+      SATflags(v) |= InQueueMask;
+    }
+
+    for(j=i+1; j<orderArray->num; j++) {
+      v = orderArray->space[j];
+      value = !SATisInverted(v);
+      v = SATnormalNode(v);
+      SATvalue(v) = value;
+      SATmakeImplied(v, d);
+      if((SATflags(v) & InQueueMask) == 0) {
+        sat_Enqueue(cm->queue, v);
+        SATflags(v) |= InQueueMask;
+      }
+    }
+
+    for(j=0; j<notLiftableArray->num; j++) {
+      v = notLiftableArray->space[j];
+      value = !SATisInverted(v);
+      v = SATnormalNode(v);
+      SATvalue(v) = value;
+      SATmakeImplied(v, d);
+      if((SATflags(v) & InQueueMask) == 0) {
+        sat_Enqueue(cm->queue, v);
+        SATflags(v) |= InQueueMask;
+      }
+    }
+    sat_ImplicationMain(cm, d);
+
+
+    if(d->conflict == 0) {
+      bAigSolverForLifting(cm, 0); /** Need further decision **/
+    /** There is a case that the implication queue is not empty **/
+      sat_CleanImplicationQueue(cm);
+    }
+    else  {
+      cm->status = SAT_UNSAT;
+    }
+
+    if(cm->status == SAT_SAT) {
+      sat_ArrayInsert(notLiftableArray, tv); 
+      sat_Backtrack(cm, 0);
+    }
+
+    d = SATgetDecision(0);
+    implied = d->implied;
+    space = implied->space;
+    size = implied->num;
+    for(j=num; j<size; j++) {
+      v = space[j];
+  
+      SATvalue(v) = 2;
+      SATflags(v) &= ResetNewVisitedObjInQueueMask;
+      SATante(v) = 0;
+      SATante2(v) = 0;
+      SATlevel(v) = -1;
+    }
+    implied->num = num;
+    cm->currentDecision = 0;
+
+  }
+
+  memcpy(orderArray->space, notLiftableArray->space, sizeof(long)*notLiftableArray->num);
+  orderArray->num = notLiftableArray->num;
+  sat_ArrayFree(notLiftableArray);
+
+
+  d = SATgetDecision(0);
+  sat_Undo(cm, d);
+  cm->status = 0;
+  cm->currentDecision = -1;
+
+#if 0
+  /** Forward clauses from lifting process to allsat process **/
+  /** Need to review this code **/
+  tmpArray = sat_ArrayAlloc(64);
+  for(i=lastNode; i<cm->nodesArraySize; i+=satNodeSize) {
+    size = SATnumLits(i);
+    plit = (long*)SATfirstLit(i);
+    inserted = 0;
+    tmpArray->num = 0;
+    for(j=0; j<size; j++, plit++) {
+      tv = SATgetNode(*plit);
+      inverted = SATisInverted(tv);
+      v = SATnormalNode(tv);
+      value = (allsat->nodesArray[v+satValue]) ;
+      value = value ^ inverted;
+      /** To check if the clause is safe to add allsat instance **/
+      if(value > 0)
+        inserted = 1;
+      sat_ArrayInsert(tmpArray, SATnot(tv));
+    }
+    if(inserted)
+      sat_AddConflictClause(allsat, tmpArray, 0);
+  }
+  sat_ArrayFree(tmpArray);
+#endif
+
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [SAT solver for lifting .]
+
+  Description [SAT solver for lifting. ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAigSolverForLifting(satManager_t *cm, int tLevel)
+{
+satLevel_t *d;
+int level;
+
+  d = SATgetDecision(0);
+  cm->implicatedSoFar = d->implied->num;
+
+  while(1) {
+    d = sat_MakeDecision(cm);
+
+    if(d == 0)	{
+      cm->status = SAT_SAT;
+      return;
+    }
+
+    while(1) {
+      sat_ImplicationMain(cm, d);
+
+      if(d->conflict == 0)	
+	break;
+
+      level = sat_ConflictAnalysisForLifting(cm, d);
+
+      if(cm->currentDecision <= -1) {
+	cm->status = SAT_UNSAT;
+	return;
+      }
+
+      d = SATgetDecision(cm->currentDecision);
+    }
+  }
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Apply minization based on checking antecedent of objective.]
+
+  Description [Apply minization based on checking antecedent of objective.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAigCollectAntecdentOfObjective(
+	bAigTransition_t *t, 
+	satManager_t *cm, 
+	bAigEdge_t obj, 
+	satArray_t *clauseArray)
+{
+int i, value;
+bAigEdge_t v;
+
+  bAigCollectAntecdentOfObjectiveAux(cm, obj);
+
+  clauseArray->num = 0;
+  for(i=0; i<t->nLatches; i++) {
+    v = t->tstates[i];
+    if(SATflags(v) & VisitedMask) {
+      value = t->vtstates[i];
+      sat_ArrayInsert(clauseArray, v^(!value));
+    }
+  }
+  /** 
+   * We don't need to reset visited flags, since they will be reset by
+   * backtracking 
+   **/
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Apply minization based on checking antecedent of objective.]
+
+  Description [Apply minization based on checking antecedent of objective.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAigCollectAntecdentOfObjectiveAux(satManager_t *cm, bAigEdge_t v)
+{
+int i, size, completeness;
+int value, inverted;
+bAigEdge_t ante, nv, *plit;
+
+  if(v == 2)	
+    return;
+
+  v = SATnormalNode(v);
+  if(SATflags(v) & VisitedMask)
+    return;
+
+  SATflags(v) |= VisitedMask;
+  ante = SATante(v);
+  if(ante == 0)	
+    return;
+
+  if(SATflags(ante) & IsCNFMask) {
+
+    size = SATnumLits(ante);
+
+    completeness = 1;
+    for(i=0, plit=(bAigEdge_t*)SATfirstLit(ante); i<size; i++, plit++) {
+      nv = SATgetNode(*plit);
+      inverted = SATisInverted(nv);
+      nv = SATnormalNode(nv);
+      value = SATvalue(nv) ^ inverted;
+      if(v == nv) {
+	if(value == 0)	completeness = 0;
+      }
+      else {
+	if(value == 1)	completeness = 0;
+      }
+    }
+    if(completeness == 0) {
+      fprintf(stdout, "ERROR : incomplete implication graph\n");
+    }
+
+    for(i=0, plit=(bAigEdge_t*)SATfirstLit(ante); i<size; i++, plit++) {
+      nv = SATgetNode(*plit);
+      nv = SATnormalNode(nv);
+      if(SATflags(nv) & VisitedMask)
+	continue;
+      bAigCollectAntecdentOfObjectiveAux(cm, nv);
+    }
+  }
+  else {
+    bAigCollectAntecdentOfObjectiveAux(cm, ante);
+    ante = SATante2(v);
+    if(ante)
+      bAigCollectAntecdentOfObjectiveAux(cm, ante);
+  }
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Create SAT manager for lifting.]
+
+  Description [Create SAT manager for lifting.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAigCreateSatManagerForLiftingUnconstrained(bAigTransition_t *t)
+{
+satManager_t *lifting, *allsat, *cm;
+bAigEdge_t *lastLit;
+satOption_t *option;
+satLiteralDB_t *literals;
+long objective;
+
+  allsat = t->allsat;
+  lifting = sat_InitManager(0);
+  t->lifting = lifting;
+
+  /** to add blocking clause to lifting instance, modify lastLit **/
+  cm = allsat;
+  lastLit = 0;
+  
+  /**  To copy circuit structure **/
+  lifting->nodesArraySize = allsat->frontierNodesBegin;
+
+  lifting->initNodesArraySize = lifting->nodesArraySize;
+  lifting->maxNodesArraySize = lifting->nodesArraySize * 2;
+
+  lifting->nodesArray = ALLOC(long, lifting->maxNodesArraySize);
+  memcpy(lifting->nodesArray, allsat->nodesArray, sizeof(long) * lifting->nodesArraySize);
+
+  lifting->HashTable = ALLOC(long, bAig_HashTableSize);
+  memcpy(lifting->HashTable, allsat->HashTable, sizeof(long)*bAig_HashTableSize);
+
+  /** allocate literal pool **/
+  sat_AllocLiteralsDB(lifting);
+  literals = lifting->literals;
+
+  lifting->comment = ALLOC(char, 2);
+  lifting->comment[0] = ' ';
+  lifting->comment[1] = '\0';
+  lifting->stdErr = allsat->stdErr;
+  lifting->stdOut = allsat->stdOut;
+  lifting->status = 0;
+  lifting->orderedVariableArray = 0;
+  lifting->unitLits = sat_ArrayAlloc(16);
+  lifting->pureLits = sat_ArrayAlloc(16);
+  lifting->option = 0;
+  lifting->each = 0;
+  lifting->decisionHead = 0;
+  lifting->variableArray = 0;
+  lifting->queue = 0;
+  lifting->BDDQueue = 0;
+  lifting->unusedAigQueue = 0;
+
+  option = sat_InitOption();
+  lifting->option = option;
+  option->verbose = 0;
+
+  /** this is important because of incrementality **/
+  option->decisionHeuristic = 0;
+  option->decisionHeuristic |= DVH_DECISION;
+
+  lifting->each = sat_InitStatistics();
+
+  if(t->originalFrontier || t->allsat->reached) {
+    objective = bAigBuildComplementedObjectiveWithCNF(
+	  t, lifting, t->originalFrontier, t->allsat->reached);
+    objective = SATnot(objective);
+  }
+  else {
+    lifting->initNumVariables = lifting->nodesArraySize;
+    if(lifting->variableArray == 0) {
+      lifting->variableArray = ALLOC(satVariable_t, lifting->initNumVariables+1);
+      memset(lifting->variableArray, 0, 
+	      sizeof(satVariable_t) * (lifting->initNumVariables+1));
+    }
+    sat_CleanDatabase(lifting);
+
+    if(t->allsat->assertion) t->lifting->assertion = sat_ArrayDuplicate(t->allsat->assertion);
+    if(t->allsat->auxObj)    t->lifting->auxObj = sat_ArrayDuplicate(t->allsat->auxObj);
+    objective = allsat->obj->space[0];
+    sat_MarkTransitiveFaninForNode(lifting, objective, CoiMask);
+  }
+
+
+  sat_PreProcessingForMixedNoCompact(lifting);
+
+  if(lifting->obj)	sat_ArrayFree(lifting->obj);	
+  lifting->obj = sat_ArrayAlloc(1);
+  sat_ArrayInsert(lifting->obj, (objective));
+
+  /* 
+   * reset score of PI 
+   * Since the scores of PI and current state variables are high than 
+   * other variables because of blocking clauses that forwarded from
+   * prevous image step.
+  for(i=0; i<t->nInputs; i++) {
+    v = t->inputs[i];
+    var = lifting->variableArray[SATnodeID(v)];
+    var.scores[0] = 0;
+    var.scores[1] = 0;
+  }
+  for(i=0; i<t->nLatches; i++) {
+    v = t->cstates[i];
+    var = lifting->variableArray[SATnodeID(v)];
+    var.scores[0] = 0;
+    var.scores[1] = 0;
+  }
+   **/
+
+  /** 
+   * To apply greedy minimization, the objective is not asserted 
+   * The complemented objective will be asserted during lifting
+   * process
+   **/
+
+
+  lifting->currentDecision = -1;
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Create SAT manager for lifting.]
+
+  Description [Create SAT manager for lifting.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAigCreateSatManagerForLifting(bAigTransition_t *t)
+{
+satManager_t *lifting, *allsat, *cm;
+bAigEdge_t *lastLit, v;
+satOption_t *option;
+satLiteralDB_t *literals;
+int size, dir;
+int nCls, nLits, index;
+long *space;
+
+  allsat = t->allsat;
+  lifting = sat_InitManager(0);
+  t->lifting = lifting;
+
+  /** to add blocking clause to lifting instance, modify lastLit **/
+  cm = allsat;
+  lastLit = 0;
+  
+  if(t->constrain) {
+    /**
+    if(allsat->nodesArraySize != allsat->frontierNodesEnd){
+      v = allsat->frontierNodesEnd-satNodeSize;
+      lastLit = SATfirstLit(v);
+      lastLit += SATnumLits(v);
+      lastLit++;
+    }
+    lifting->nodesArraySize = allsat->frontierNodesEnd;
+    **/
+    if(allsat->nodesArraySize != allsat->frontierNodesEnd){
+      v = allsat->nodesArraySize-satNodeSize;
+      lastLit = (bAigEdge_t *) SATfirstLit(v);
+      lastLit += SATnumLits(v);
+      lastLit++;
+    }
+    lifting->nodesArraySize = allsat->nodesArraySize;
+  
+  }
+  else {
+/**    
+ *  To copy circuit, frontier, and all blocking clauses
+ *    lifting->nodesArraySize = allsat->nodesArraySize; 
+ **/
+    /**  To copy circuit structure **/
+    lifting->nodesArraySize = allsat->frontierNodesBegin;
+  }
+
+  /** 
+   * We save the frontier SAT first in allsat instance and
+   * blocking clauses geenrated from previous runs.
+   **/
+  lifting->initNodesArraySize = lifting->nodesArraySize;
+  lifting->maxNodesArraySize = lifting->nodesArraySize * 2;
+
+  lifting->nodesArray = ALLOC(long, lifting->maxNodesArraySize);
+  memcpy(lifting->nodesArray, allsat->nodesArray, sizeof(long) * lifting->nodesArraySize);
+
+  lifting->HashTable = ALLOC(long, bAig_HashTableSize);
+  memcpy(lifting->HashTable, allsat->HashTable, sizeof(long)*bAig_HashTableSize);
+
+  literals = ALLOC(satLiteralDB_t, 1);
+  lifting->literals = literals;
+
+  if(lastLit > 0) {
+    size = lastLit - allsat->literals->begin;
+  }
+  else {
+    size = 0;
+  }
+
+  if(size > 1) { /** there are clauses for objective **/
+    literals->begin = ALLOC(long, size*4);
+    literals->end = literals->begin + size*4;
+    memcpy(literals->begin, allsat->literals->begin, sizeof(long)*size);
+    literals->last = literals->begin + size;
+    literals->initialSize = literals->begin+size-1;
+  }
+  else { /** there is no extra logic for objective **/
+    size = 1024 * 1024;
+    literals->begin = ALLOC(long, size);
+    *(literals->begin) = 0;
+    literals->last = literals->begin + 1;
+    literals->end = literals->begin + size;
+    literals->initialSize = literals->last;
+  }
+
+  lifting->initNumVariables = allsat->initNumVariables;
+  lifting->initNumClauses = allsat->initNumClauses;
+  lifting->initNumLiterals = allsat->initNumLiterals;
+  lifting->comment = ALLOC(char, 2);
+  lifting->comment[0] = ' ';
+  lifting->comment[1] = '\0';
+  lifting->stdErr = allsat->stdErr;
+  lifting->stdOut = allsat->stdOut;
+  lifting->status = 0;
+  lifting->orderedVariableArray = 0;
+  lifting->unitLits = sat_ArrayAlloc(16);
+  lifting->pureLits = sat_ArrayAlloc(16);
+  lifting->option = 0;
+  lifting->each = 0;
+  lifting->decisionHead = 0;
+  lifting->variableArray = 0;
+  lifting->queue = 0;
+  lifting->BDDQueue = 0;
+  lifting->unusedAigQueue = 0;
+
+  option = sat_InitOption();
+  lifting->option = option;
+  option->verbose = 0;
+
+  /** this is important because of incrementality **/
+  option->decisionHeuristic = 0;
+  option->decisionHeuristic |= DVH_DECISION;
+
+  lifting->each = sat_InitStatistics();
+
+  sat_CleanDatabase(lifting);
+
+  if(lifting->variableArray == 0) {
+    lifting->variableArray = ALLOC(satVariable_t, lifting->initNumVariables+1);
+    memset(lifting->variableArray, 0, 
+	    sizeof(satVariable_t) * (lifting->initNumVariables+1));
+  }
+
+  cm = lifting;
+  nCls = nLits = 0;
+  for(space = literals->begin; space < literals->last; space++) {
+    if(*space < 0) {
+      v = -(*space);
+      space++;
+      SATfirstLit(v) = (long) space;
+      index = 0;
+      while(1) {
+	if(*space < 0)	break;
+	dir = SATgetDir(*space);
+	nLits++;
+        if(dir == -2){
+	  space++;
+	  index++;
+	  continue;
+	}
+        SATunsetWL(space);
+        sat_AddWL(cm, v, index, dir);
+	space++;
+	index++;
+      }
+      nCls++;
+    }
+  }
+  lifting->initNumClauses = nCls;
+  lifting->initNumLiterals = nLits;
+
+  if(allsat->assertion) lifting->assertion = sat_ArrayDuplicate(allsat->assertion);
+  if(allsat->auxObj) 	lifting->auxObj = sat_ArrayDuplicate(allsat->auxObj);
+
+  bAigMarkConeOfInfluenceForAX(t, lifting);
+
+
+  bAigPreProcessingForLiftingInstance(t, lifting) ;
+
+  /* 
+   * reset score of PI 
+   * Since the scores of PI and current state variables are high than 
+   * other variables because of blocking clauses that forwarded from
+   * prevous image step.
+  for(i=0; i<t->nInputs; i++) {
+    v = t->inputs[i];
+    var = lifting->variableArray[SATnodeID(v)];
+    var.scores[0] = 0;
+    var.scores[1] = 0;
+  }
+  for(i=0; i<t->nLatches; i++) {
+    v = t->cstates[i];
+    var = lifting->variableArray[SATnodeID(v)];
+    var.scores[0] = 0;
+    var.scores[1] = 0;
+  }
+   **/
+
+  /** 
+   * To apply greedy minimization, the objective is not asserted 
+   * The complemented objective will be asserted during lifting
+   * process
+   **/
+
+  if(lifting->obj)	sat_ArrayFree(lifting->obj);	
+  lifting->obj = sat_ArrayDuplicate(allsat->obj);
+
+  lifting->currentDecision = -1;
+
+}
+/**Function********************************************************************
+
+  Synopsis    [ Pre-processing to run CirCUs with AIG and CNF]
+
+  Description [ Pre-processing to run CirCUs with AIG and CNF]
+
+  SideEffects [ One has to run sat_PostProcessing for AllSat enumeration after running CirCUs]
+
+  SeeAlso     [ sat_PostProcessing ]
+
+******************************************************************************/
+void
+bAigPreProcessingForLiftingInstance(bAigTransition_t *t, satManager_t *cm) 
+{
+satLevel_t *d;
+int i;
+long v;
+
+
+  /** create implication queue **/
+  cm->queue = sat_CreateQueue(1024);
+  cm->BDDQueue = sat_CreateQueue(1024);
+  cm->unusedAigQueue = sat_CreateQueue(1024);
+
+  /**
+  create variable array : one can reduce size of variable array using
+  mapping. for fanout free internal node....
+  **/
+
+  if(cm->variableArray == 0) {
+    cm->variableArray = ALLOC(satVariable_t, cm->initNumVariables+1);
+    memset(cm->variableArray, 0, 
+	    sizeof(satVariable_t) * (cm->initNumVariables+1));
+  }
+
+  if(cm->auxArray == 0)
+    cm->auxArray = sat_ArrayAlloc(1024);
+  if(cm->nonobjUnitLitArray == 0)
+    cm->nonobjUnitLitArray = sat_ArrayAlloc(128);
+  if(cm->objUnitLitArray == 0)
+    cm->objUnitLitArray = sat_ArrayAlloc(128);
+
+  /** compact fanout of AIG node 
+  sat_CompactFanout(cm);
+  **/
+
+  cm->initNodesArraySize = cm->nodesArraySize;
+  cm->beginConflict = cm->nodesArraySize;
+
+  if(cm->option->allSatMode) {
+    sat_RestoreFrontierClauses(cm);
+    sat_RestoreBlockingClauses(cm);
+  }
+
+  /** Initial score **/
+  sat_InitScoreForMixed(cm);
+
+  /** create decision stack **/
+  if(cm->decisionHeadSize == 0) {
+    cm->decisionHeadSize = 32;
+    cm->decisionHead = ALLOC(satLevel_t, cm->decisionHeadSize);
+    memset(cm->decisionHead, 0, sizeof(satLevel_t) * cm->decisionHeadSize);
+  }
+  cm->currentDecision = -1;
+
+  /** to avoid purify warning **/
+  SATvalue(2) = 2;
+  SATflags(0) = 0;
+
+  /** incremental SAT.... **/
+  if(cm->option->incTraceObjective) { 
+    sat_RestoreForwardedClauses(cm, 0);
+  }
+  else if(cm->option->incAll) {
+    sat_RestoreForwardedClauses(cm, 1);
+  }
+
+  if(cm->option->incTraceObjective) {
+    sat_MarkObjectiveFlagToArray(cm, cm->obj);
+    sat_MarkObjectiveFlagToArray(cm, cm->objCNF);
+  }
+
+  /** Level 0 decision.... **/
+  d = sat_AllocLevel(cm);
+
+  sat_ApplyForcedAssignmentMain(cm, d);
+
+  if(cm->status == SAT_UNSAT)
+    return;
+
+  /** 
+   * There is a case that circuit consists of single objective node 
+   **/
+  for(i=0; i<cm->pureLits->num; i++) {
+    v = cm->pureLits->space[i];
+    if(v == t->objective) {
+      for(;i<cm->pureLits->num; i++) {
+        cm->pureLits->space[i] = cm->pureLits->space[i+1];
+      }
+      cm->pureLits->num--;
+      break;
+    }
+  }
+
+  sat_ImplyArray(cm, d, cm->assertion);
+  sat_ImplyArray(cm, d, cm->unitLits);
+  sat_ImplyArray(cm, d, cm->pureLits);
+  sat_ImplyArray(cm, d, cm->auxObj);
+  sat_ImplyArray(cm, d, cm->nonobjUnitLitArray);
+  sat_ImplyArray(cm, d, cm->obj);
+
+  sat_ImplicationMain(cm, d);
+  if(d->conflict) {
+    cm->status = SAT_UNSAT;
+  }
+
+  if(cm->status == 0) {
+    if(cm->option->incDistill) {
+      sat_IncrementalUsingDistill(cm);
+    }
+  }
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Post processing after computing AX.]
+
+  Description [Free sat manager...]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAig_PostProcessForAX(bAigTransition_t *t, satManager_t *cm)
+{
+bAig_Manager_t *manager;
+
+  manager = t->manager;
+  if(cm->maxNodesArraySize > manager->maxNodesArraySize) {
+    manager->maxNodesArraySize = cm->maxNodesArraySize;
+    manager->nameList   = REALLOC(char *, manager->nameList  , manager->maxNodesArraySize/bAigNodeSize);
+    manager->bddIdArray = REALLOC(int ,   manager->bddIdArray  , manager->maxNodesArraySize/bAigNodeSize);
+    manager->bddArray   = REALLOC(bdd_t *, manager->bddArray  , manager->maxNodesArraySize/bAigNodeSize);
+  }
+
+  manager->maxNodesArraySize = cm->maxNodesArraySize;
+  manager->NodesArray = cm->nodesArray;
+  manager->literals = cm->literals;
+  cm->literals->last = cm->literals->initialSize;
+
+  cm->nodesArray = 0;
+  cm->literals = 0;
+  cm->HashTable = 0;
+
+  sat_FreeManager(cm);
+
+  /** reset objective for next iteration **/
+  t->objective = 0; 
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Mark cone of influence for AX.]
+
+  Description [Mark cone of influence for objective and intermediate variable that are created for complement frontier.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAigMarkConeOfInfluenceForAX(bAigTransition_t *t, satManager_t *cm)
+{
+satArray_t *arr;
+int i;
+bAigEdge_t v;
+
+  sat_MarkTransitiveFaninForNode(cm, t->objective, CoiMask);
+
+  if(t->tVariables) {
+    arr = t->tVariables;
+    for(i=0; i<arr->num; i++) {
+      v = arr->space[i];
+      SATflags(v) |= CoiMask;
+    }
+  }
+
+  if(t->auxObj) {
+    arr = t->auxObj;
+    for(i=0; i<arr->num; i++) {
+      v = arr->space[i];
+      sat_MarkTransitiveFaninForNode(cm, v, CoiMask);
+    }
+  }
+
+  if(t->objArr) {
+    arr = t->objArr;
+    for(i=0; i<arr->num; i++) {
+      v = arr->space[i];
+      sat_MarkTransitiveFaninForNode(cm, v, CoiMask);
+    }
+  }
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Make interface for CirCUs to compute AX.]
+
+  Description [Make interface for CirCUs to compute AX.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+satManager_t *
+bAigCirCUsInterfaceForAX(bAigTransition_t *t)
+{
+satManager_t *cm;
+bAig_Manager_t *manager;
+satOption_t *option;
+int i;
+bAigEdge_t v;
+
+  manager = t->manager;
+  cm = sat_InitManager(0);
+  memset(cm, 0, sizeof(satManager_t));
+
+  cm->nodesArraySize = manager->nodesArraySize;
+  cm->initNodesArraySize = manager->nodesArraySize;
+  cm->maxNodesArraySize = manager->maxNodesArraySize;
+  cm->nodesArray = manager->NodesArray;
+  cm->HashTable = manager->HashTable;
+  cm->literals = manager->literals;
+  cm->initNumVariables = (manager->nodesArraySize/bAigNodeSize);
+  cm->initNumClauses = 0;
+  cm->initNumLiterals = 0;
+  cm->comment = ALLOC(char, 2);
+  cm->comment[0] = ' ';
+  cm->comment[1] = '\0';
+  cm->stdErr = vis_stderr;
+  cm->stdOut = vis_stdout;
+  cm->status = 0;
+  cm->orderedVariableArray = 0;
+  cm->unitLits = sat_ArrayAlloc(16);
+  cm->pureLits = sat_ArrayAlloc(16);
+  cm->option = 0;
+  cm->each = 0;
+  cm->decisionHead = 0;
+  cm->variableArray = 0;
+  cm->queue = 0;
+  cm->BDDQueue = 0;
+  cm->unusedAigQueue = 0;
+
+  option = sat_InitOption();
+  cm->option = option;
+  option->verbose = 0;
+
+  cm->each = sat_InitStatistics();
+  sat_AllocLiteralsDB(cm);
+
+  cm->obj = sat_ArrayAlloc(1);
+  sat_ArrayInsert(cm->obj, t->objective);
+
+  if(t->auxObj && t->auxObj->num) {
+    cm->auxObj = sat_ArrayAlloc(t->auxObj->num);
+    for(i=0; i<t->auxObj->num; i++) {
+      v = t->auxObj->space[i];
+      sat_ArrayInsert(cm->auxObj, v);
+    }
+  }
+  cm->option->allSatMode = 1;
+
+  /** 
+   * Copy to reachable states and frontier to satManager  
+   * so that they can be used to build current instance. 
+   **/
+  cm->reached = t->reached;
+  cm->frontier = t->frontier;
+  t->reached = 0;
+  t->frontier = 0;
+
+  return(cm);
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Build new objective from frontier set by complementing blocking cluases] 
+
+  Description [Build new objective from frontier set by complementing blocking cluases, the frontier array of bAigTransition_t save the blocking clause as clause form. The structure of frontier array is as follows.
+      clause seperator, literals in clause, clause seperator, ..., clause seperator ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bAigEdge_t
+bAigBuildObjectiveFromFrontierSet(bAigTransition_t *t)
+{
+mAig_Manager_t *manager;
+satArray_t *frontier;
+satArray_t *clause;
+satArray_t *andArr, *orArr;
+satArray_t *fandArr;
+satArray_t *fArr;
+int i, j, nCls, removeFlag;
+int inverted;
+long *space, index;
+bAigEdge_t v, tv, out, objective;
+  
+  manager = t->manager;
+
+  andArr = sat_ArrayAlloc(1024);
+  fandArr = sat_ArrayAlloc(1024);
+  clause = sat_ArrayAlloc(1024);
+
+  if(t->coiStates == 0) 
+    t->coiStates = ALLOC(bAigEdge_t, sizeof(bAigEdge_t) * t->csize);
+  memset(t->coiStates, 0, sizeof(bAigEdge_t)*t->csize);
+
+  if(t->tVariables) t->tVariables->num = 0;
+  else              t->tVariables = sat_ArrayAlloc(1024);
+  fArr = sat_ArrayAlloc(1024);
+  orArr = t->tVariables;
+
+  nCls = 0;
+  frontier = t->frontier; 
+  sat_ArrayInsert(fArr, 0);
+  for(i=0, space=frontier->space; i<frontier->num; i++, space++) {
+    if(*space <= 0) { /** 0 or -1 is seperator between clauses **/
+      space++;
+      i++;
+
+      if(i >= frontier->num) {
+	break;
+      }
+
+      removeFlag = 0;
+      fandArr->num = 0;
+      andArr->num = 0;
+      while(*space > 0) {
+#if 0
+	v = *space;
+	inverted = SATisInverted(v);
+        tv = SATnormalNode(v);
+	index = SATnodeID(tv);
+	if(index > t->csize) {
+	  fprintf(stdout, "ERROR : %ld is not current state variable\n", tv);
+	  exit(0);
+	}
+	v = t->c2n[index];
+	v = v ^ (inverted);
+	if(v == 0) {  /** skip **/
+	}
+	else if(v == 1)  /** trivially satisfied **/
+	  removeFlag = 1;
+	else if(removeFlag == 0) {
+	  sat_ArrayInsert(andArr, v);
+	  t->coiStates[index] = 1;
+	}
+#endif
+
+	sat_ArrayInsert(fandArr, *space);
+	i++;
+	space++;
+      }
+      i--;
+      space--;
+
+
+      removeFlag = 0;
+      for(j=0; j<fandArr->num; j++) {
+	v = fandArr->space[j];
+	inverted = SATisInverted(v);
+        tv = SATnormalNode(v);
+	index = SATnodeID(tv);
+	if(index > t->csize) {
+	  fprintf(stdout, "ERROR : %ld is not current state variable\n", tv);
+	  exit(0);
+	}
+	v = t->c2n[index];
+	v = v ^ (inverted);
+
+	if(t->verbose > 4)
+	  fprintf(stdout, "%ld(%ld) ",fandArr->space[j], v); 
+	if(v == 0) {  /** skip **/
+          andArr->space[j] = 0;
+	}
+	else if(v == 1)  /** trivially satisfied **/
+	  removeFlag = 1;
+	else  {
+	  sat_ArrayInsert(andArr, v);
+	  t->coiStates[index] = 1;
+	}
+      }
+      if(t->verbose > 4)
+        fprintf(stdout, "\n");
+
+      if(removeFlag)
+	continue;
+
+     
+      if(t->verbose > 4) {
+        fprintf(stdout, "%ld-> ", andArr->num);
+        for(j=0; j<andArr->num; j++) {
+	  v = andArr->space[j];
+	  fprintf(stdout, "%ld ", v);
+        }
+        fprintf(stdout, "\n");
+      }
+
+      out = bAig_CreateNode(manager, 2, 2);
+      sat_ArrayInsert(orArr, out);
+
+      for(j=0; j<andArr->num; j++) {
+	v = andArr->space[j];
+	sat_ArrayInsert(fArr, SATnot(v));
+	sat_ArrayInsert(fArr, SATnot(out));
+	sat_ArrayInsert(fArr, -1); /** seperator **/
+	nCls++;
+      }
+
+      for(j=0; j<andArr->num; j++) {
+	v = andArr->space[j];
+	sat_ArrayInsert(fArr, v);
+      }
+      sat_ArrayInsert(fArr, out);
+      sat_ArrayInsert(fArr, -1);
+      nCls++;
+    }
+  }
+
+  objective = bAig_CreateNode(manager, 2, 2);
+  for(i=0; i<orArr->num; i++) {
+    v = orArr->space[i];
+    sat_ArrayInsert(fArr, SATnot(v));
+    sat_ArrayInsert(fArr, objective);
+    sat_ArrayInsert(fArr, -1);
+    nCls++;
+  }
+  for(i=0; i<orArr->num; i++) {
+    v = orArr->space[i];
+    sat_ArrayInsert(fArr, v);
+  }
+
+  sat_ArrayInsert(fArr, SATnot(objective));
+
+  sat_ArrayInsert(fArr, -1);
+  nCls++;
+
+  if(orArr->num == 0) {
+    fArr->num = 0;
+  }
+
+  if(t->verbose > 0) {
+    fprintf(vis_stdout, "** SAT_INV : %ld number of frontier blocking clauses are processed\n", orArr->num);
+    fprintf(vis_stdout, "** SAT_INV : %d number of clauses are added to build objective\n", nCls);
+  }
+
+  sat_ArrayFree(andArr);
+  sat_ArrayFree(fandArr);
+  sat_ArrayFree(clause);
+
+  t->originalFrontier = frontier;
+  t->frontier = fArr;
+  t->objective = objective;
+
+  if(t->objArr == 0) 
+    t->objArr = sat_ArrayAlloc(t->nLatches);
+  t->objArr->num = 0;
+  for(i=0; i<t->csize; i++) {
+    if(t->coiStates[i]) {
+      sat_ArrayInsert(t->objArr, SATnormalNode(t->c2n[i]));
+    }
+  }
+
+
+  return(objective);
+}
+
+bAigEdge_t
+bAigBuildComplementedObjectiveWithCNF(
+	bAigTransition_t *t, 
+	satManager_t *cm,
+	satArray_t *narr,
+	satArray_t *carr)
+{
+satArray_t *clause;
+satArray_t *andArr, *orArr;
+satArray_t *fandArr;
+satArray_t *fArr, *arr;
+satArray_t *frontier;
+int i, j, nCls, removeFlag;
+int inverted;
+long *space, index;
+bAigEdge_t v, tv, out, objective;
+bAigEdge_t obj1, obj2;
+  
+  andArr = sat_ArrayAlloc(1024);
+  fandArr = sat_ArrayAlloc(1024);
+  clause = sat_ArrayAlloc(1024);
+
+  if(t->coiStates == 0) 
+    t->coiStates = ALLOC(bAigEdge_t, sizeof(bAigEdge_t) * t->csize);
+  memset(t->coiStates, 0, sizeof(bAigEdge_t)*t->csize);
+
+  if(t->tVariables) t->tVariables->num = 0;
+  else              t->tVariables = sat_ArrayAlloc(1024);
+  fArr = sat_ArrayAlloc(1024);
+
+  orArr =sat_ArrayAlloc(1024);
+
+  sat_ArrayInsert(fArr, 0);
+  nCls = 0;
+  frontier = narr;
+
+
+  if(frontier) {
+  for(i=0, space=frontier->space; i<frontier->num; i++, space++) {
+    if(*space <= 0) { /** 0 or -1 is seperator between clauses **/
+      space++;
+      i++;
+
+      if(i >= frontier->num) {
+	break;
+      }
+
+      removeFlag = 0;
+      fandArr->num = 0;
+      andArr->num = 0;
+      while(*space > 0) {
+	sat_ArrayInsert(fandArr, *space);
+	i++;
+	space++;
+      }
+      i--;
+      space--;
+
+
+      removeFlag = 0;
+      for(j=0; j<fandArr->num; j++) {
+	v = fandArr->space[j];
+	inverted = SATisInverted(v);
+        tv = SATnormalNode(v);
+	index = SATnodeID(tv);
+	if(index > t->csize) {
+	  fprintf(stdout, "ERROR : %ld is not current state variable\n", tv);
+	  exit(0);
+	}
+	v = t->c2n[index];
+	v = v ^ (inverted);
+
+	if(t->verbose > 4)
+	  fprintf(stdout, "%ld(%ld) ",fandArr->space[j], v); 
+	if(v == 0) {  /** skip **/
+          andArr->space[j] = 0;
+	}
+	else if(v == 1)  /** trivially satisfied **/
+	  removeFlag = 1;
+	else  {
+	  sat_ArrayInsert(andArr, v);
+	  t->coiStates[index] = 1;
+	}
+      }
+      if(t->verbose > 4)
+        fprintf(stdout, "\n");
+
+      if(removeFlag)
+	continue;
+
+     
+      if(t->verbose > 4) {
+        fprintf(stdout, "%ld-> ", andArr->num);
+        for(j=0; j<andArr->num; j++) {
+	  v = andArr->space[j];
+	  fprintf(stdout, "%ld ", v);
+        }
+        fprintf(stdout, "\n");
+      }
+
+      out = sat_CreateNode(cm, 2, 2);
+      sat_ArrayInsert(orArr, out);
+      sat_ArrayInsert(t->tVariables, out);
+
+      for(j=0; j<andArr->num; j++) {
+	v = andArr->space[j];
+	sat_ArrayInsert(fArr, SATnot(v));
+	sat_ArrayInsert(fArr, SATnot(out));
+	sat_ArrayInsert(fArr, -1); /** seperator **/
+	nCls++;
+      }
+
+      for(j=0; j<andArr->num; j++) {
+	v = andArr->space[j];
+	sat_ArrayInsert(fArr, v);
+      }
+      sat_ArrayInsert(fArr, out);
+      sat_ArrayInsert(fArr, -1);
+      nCls++;
+    }
+  }
+  }
+
+  obj1 = sat_CreateNode(cm, 2, 2);
+  for(i=0; i<orArr->num; i++) {
+    v = orArr->space[i];
+    sat_ArrayInsert(fArr, SATnot(v));
+    sat_ArrayInsert(fArr, obj1);
+    sat_ArrayInsert(fArr, -1);
+    nCls++;
+  }
+  for(i=0; i<orArr->num; i++) {
+    v = orArr->space[i];
+    sat_ArrayInsert(fArr, v);
+  }
+
+  sat_ArrayInsert(fArr, SATnot(obj1));
+
+  sat_ArrayInsert(fArr, -1);
+  nCls++;
+
+#if 1
+  frontier = carr;
+  if(frontier) {
+  for(i=0, space=frontier->space; i<frontier->num; i++, space++) {
+    if(*space <= 0) { /** 0 or -1 is seperator between clauses **/
+      space++;
+      i++;
+
+      if(i >= frontier->num) {
+	break;
+      }
+
+      fandArr->num = 0;
+      andArr->num = 0;
+      while(*space > 0) {
+	sat_ArrayInsert(fandArr, *space);
+	i++;
+	space++;
+      }
+      i--;
+      space--;
+
+
+      if(t->verbose > 4) {
+        fprintf(stdout, "%ld-> ", andArr->num);
+        for(j=0; j<andArr->num; j++) {
+	  v = andArr->space[j];
+	  fprintf(stdout, "%ld ", v);
+        }
+        fprintf(stdout, "\n");
+      }
+
+      out = sat_CreateNode(cm, 2, 2);
+      sat_ArrayInsert(orArr, out);
+      sat_ArrayInsert(t->tVariables, out);
+
+      for(j=0; j<andArr->num; j++) {
+	v = andArr->space[j];
+	sat_ArrayInsert(fArr, SATnot(v));
+	sat_ArrayInsert(fArr, SATnot(out));
+	sat_ArrayInsert(fArr, -1); /** seperator **/
+	nCls++;
+      }
+
+      for(j=0; j<andArr->num; j++) {
+	v = andArr->space[j];
+	sat_ArrayInsert(fArr, v);
+      }
+      sat_ArrayInsert(fArr, out);
+      sat_ArrayInsert(fArr, -1);
+      nCls++;
+    }
+  }
+  }
+
+  obj2 = sat_CreateNode(cm, 2, 2);
+  for(i=0; i<orArr->num; i++) {
+    v = orArr->space[i];
+    sat_ArrayInsert(fArr, SATnot(v));
+    sat_ArrayInsert(fArr, obj2);
+    sat_ArrayInsert(fArr, -1);
+    nCls++;
+  }
+  for(i=0; i<orArr->num; i++) {
+    v = orArr->space[i];
+    sat_ArrayInsert(fArr, v);
+  }
+
+  sat_ArrayInsert(fArr, SATnot(obj2));
+
+  sat_ArrayInsert(fArr, -1);
+  nCls++;
+  #endif
+
+  sat_ArrayInsert(t->tVariables, obj1);
+  sat_ArrayInsert(t->tVariables, obj2);
+  objective = sat_CreateNode(cm, 2, 2);
+  sat_ArrayInsert(fArr, SATnot(obj1));
+  sat_ArrayInsert(fArr, SATnot(obj2));
+  sat_ArrayInsert(fArr, objective);
+  sat_ArrayInsert(fArr, -1);
+  sat_ArrayInsert(fArr, (obj1));
+  sat_ArrayInsert(fArr, SATnot(objective));
+  sat_ArrayInsert(fArr, -1);
+  sat_ArrayInsert(fArr, (obj2));
+  sat_ArrayInsert(fArr, SATnot(objective));
+  sat_ArrayInsert(fArr, -1);
+
+  if(orArr->num == 0) {
+    fArr->num = 0;
+  }
+
+  if(t->verbose > 0) {
+    fprintf(vis_stdout, "** SAT_INV : %ld number of frontier blocking clauses are processed\n", orArr->num);
+    fprintf(vis_stdout, "** SAT_INV : %d number of clauses are added to build objective\n", nCls);
+  }
+
+  sat_ArrayFree(andArr);
+  sat_ArrayFree(fandArr);
+  sat_ArrayFree(clause);
+
+  cm->initNumVariables = cm->nodesArraySize;
+  if(cm->variableArray == 0) {
+    cm->variableArray = ALLOC(satVariable_t, cm->initNumVariables+1);
+    memset(cm->variableArray, 0, 
+	    sizeof(satVariable_t) * (cm->initNumVariables+1));
+  }
+  sat_RestoreClauses(cm, fArr);
+  sat_CleanDatabase(cm);
+
+
+  if(t->allsat->assertion) t->lifting->assertion = sat_ArrayDuplicate(t->allsat->assertion);
+  if(t->allsat->auxObj)    t->lifting->auxObj = sat_ArrayDuplicate(t->allsat->auxObj);
+
+  sat_MarkTransitiveFaninForNode(cm, objective, CoiMask);
+
+  for(i=0; i<t->csize; i++) {
+    if(t->coiStates[i]) {
+      sat_MarkTransitiveFaninForNode(cm, SATnormalNode(t->c2n[i]), CoiMask);
+    }
+  }
+
+  if(t->tVariables) {
+    arr = t->tVariables;
+    for(i=0; i<arr->num; i++) {
+      v = arr->space[i];
+      SATflags(v) |= CoiMask;
+    }
+  }
+
+  if(t->auxObj) {
+    arr = t->auxObj;
+    for(i=0; i<arr->num; i++) {
+      v = arr->space[i];
+      sat_MarkTransitiveFaninForNode(cm, v, CoiMask);
+    }
+  }
+  return(objective);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Function to clean data of bAigTransition_t generated from previous execution]
+
+  Description [Function to clean data of bAigTransition_t generated from previous execution]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAigCleanUpDataFromPreviousExecution(bAigTransition_t *t)
+{
+  if(t->frontier) {
+    sat_ArrayFree(t->frontier);
+    t->frontier = 0;
+  }
+  if(t->reached) {
+    sat_ArrayFree(t->reached);
+    t->reached = 0;
+  }
+
+  t->objective = 0;
+  t->iteration = 0;
+  t->nBlocked = 0;
+  t->sum = 0;
+  t->avgLits = 0;
+
+}
+/**Function********************************************************************
+
+  Synopsis    [Function to print information of bAigTransition_t]
+
+  Description [Function to print information of bAigTransition_t]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAigPrintTransitionInfo(bAigTransition_t *t)
+{
+int i;
+
+  fprintf(vis_stdout, "Transition relation information in terms of AIG\n");
+  fprintf(vis_stdout, "objective : %ld\n", t->objective);
+  fprintf(vis_stdout, "number of primary inputs : %d\n", t->nInputs);
+  fprintf(vis_stdout, "number of states variables : %d\n", t->nLatches);
+
+  fprintf(vis_stdout, "primary inputs :");
+  for(i=0; i<t->nInputs; i++) {
+    fprintf(vis_stdout, "%5ld ", t->inputs[i]);
+    if((i+1)%10 == 0 && i > 0) 
+      fprintf(vis_stdout, "\n                ");
+  }
+  fprintf(vis_stdout, "\n");
+
+  fprintf(vis_stdout, "state variables :");
+  for(i=0; i<t->nLatches; i++) {
+    fprintf(vis_stdout, "%5ld(%5ld):%5ld ", 
+	    t->cstates[i], t->initials[i], t->nstates[i]);
+    if((i+1)%3 == 0 && i > 0) 
+      fprintf(vis_stdout, "\n                 ");
+  }
+  fprintf(vis_stdout, "\n");
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Function to arrange node to the alphabetic order ]
+
+  Description [Function to arrange node to the alphabetic order ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+nodenameCompare(
+  const void * node1,
+  const void * node2)
+{
+Ntk_Node_t *v1, *v2;
+char *name1, *name2;
+
+  v1 = *(Ntk_Node_t **)(node1);
+  v2 = *(Ntk_Node_t **)(node2);
+  name1 = Ntk_NodeReadName(v1);
+  name2 = Ntk_NodeReadName(v2);
+  
+  return (strcmp(name1, name2));
+} 
+
+/**Function********************************************************************
+
+  Synopsis    [Function to check if given string is integer]
+
+  Description [Function to check if given string is integer]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+StringCheckIsInteger(
+  char *string,
+  int *value)
+{
+  char *ptr;
+  long l;
+  
+  l = strtol (string, &ptr, 0) ;
+  if(*ptr != '\0')
+    return 0;
+  if ((l > MAXINT) || (l < -1 - MAXINT))
+    return 1 ;
+  *value = (int) l;
+  return 2 ;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Function to check the deicison level of variable ]
+
+  Description [Function to check the deicison level of variable ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+levelCompare(
+  const void * node1,
+  const void * node2)
+{
+  bAigEdge_t v1, v2;
+  int l1, l2;
+
+  v1 = *(bAigEdge_t *)(node1);
+  v2 = *(bAigEdge_t *)(node2);
+  l1 = SATcm->variableArray[SATnodeID(v1)].level;
+  l2 = SATcm->variableArray[SATnodeID(v2)].level;
+  
+  if(l1 == l2)	return(v1 > v2);
+  return (l1 > l2);
+} 
+/**Function********************************************************************
+
+  Synopsis    [Function to check the index ]
+
+  Description [Function to check the index ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+indexCompare(
+  const void * node1,
+  const void * node2)
+{
+  bAigEdge_t v1, v2;
+
+  v1 = *(bAigEdge_t *)(node1);
+  v2 = *(bAigEdge_t *)(node2);
+  
+  return(v1 > v2);
+} 
+
Index: vis_dev/vis-2.3/src/baig/baigBddSweep.c
===================================================================
--- vis_dev/vis-2.3/src/baig/baigBddSweep.c	(revision 14)
+++ vis_dev/vis-2.3/src/baig/baigBddSweep.c	(revision 14)
@@ -0,0 +1,807 @@
+/**CFile***********************************************************************
+
+  FileName    [baigBddSweep.c]
+
+  PackageName [baig]
+
+  Synopsis    [Functions to find functional equivalent node index using bdd sweeping.]
+
+  Author      [HoonSang Jin]
+
+  Copyright [ This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "maig.h"
+#include "ntk.h"
+#include "cmd.h"
+#include "baig.h"
+#include "baigInt.h"
+#include "heap.h"
+#include "ntmaig.h"
+#include "ord.h"
+
+static char rcsid[] UNUSED = "$Id: baigBddSweep.c,v 1.13 2005/05/18 18:11:42 jinh Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int SweepBddCompare(const char *x, const char *y);
+static int SweepBddHash(char *x, int size);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+void bAig_BuildAigBFSManner( Ntk_Network_t *network, mAig_Manager_t *manager, st_table *leaves, int sweep);
+void bAig_BddSweepMain(Ntk_Network_t *network, array_t *nodeArray);
+void bAig_BddSweepForceMain(Ntk_Network_t *network, array_t *nodeArray);
+
+/**Function********************************************************************
+
+  Synopsis    [Compare function for BDD sweeping]
+
+  Description [Compare function for BDD sweeping]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+SweepBddCompare(const char *x, const char *y)
+{
+  return(bdd_ptrcmp((bdd_t *)x, (bdd_t *)y));
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Hashing function for BDD sweeping]
+
+  Description [Hashing function for BDD sweeping]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+SweepBddHash(char *x, int size)
+{
+
+  return(bdd_ptrhash((bdd_t *)x, size));
+}
+
+/**Function********************************************************************
+
+  Synopsis    [BDD sweeping for aig nodes]
+
+  Description [BDD sweeping for aig nodes rooted at latch data inputs and 
+               primary outputs]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAig_BddSweepMain(Ntk_Network_t *network, array_t *nodeArray)
+{
+  array_t *mVarList, *bVarList;
+  bdd_t *bdd, *func;
+  int bddIdIndex;
+  int i, count, sizeLimit, mvfSize;
+  int maxSize, curSize;
+  array_t *tnodeArray;
+  lsGen gen;
+  st_generator *gen1;
+  Ntk_Node_t *node;
+  bAigEdge_t v;
+  MvfAig_Function_t  *mvfAig;
+  mAig_Manager_t *manager;
+  mdd_manager *mgr;
+  st_table *node2MvfAigTable;
+  st_table * bdd2vertex;
+  mAigMvar_t mVar;
+  mAigBvar_t bVar;
+  int index1, mAigId;
+
+
+  manager = Ntk_NetworkReadMAigManager(network);
+
+  mgr = Ntk_NetworkReadMddManager(network);
+  if(mgr == 0) {
+    Ord_NetworkOrderVariables(network, Ord_RootsByDefault_c, 
+	    Ord_NodesByDefault_c, FALSE, Ord_InputAndLatch_c, 
+	    Ord_Unassigned_c, 0, 0);
+    mgr = Ntk_NetworkReadMddManager(network);
+  }
+  node2MvfAigTable = 
+      (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+
+  bdd2vertex = st_init_table(SweepBddCompare, SweepBddHash);
+
+  sizeLimit = 500;
+  maxSize = manager->nodesArraySize;
+
+  tnodeArray = 0;
+  if(nodeArray == 0) {
+    bVarList = mAigReadBinVarList(manager);
+    mVarList = mAigReadMulVarList(manager);
+    tnodeArray = array_alloc(bAigEdge_t, 0);
+    Ntk_NetworkForEachLatch(network, gen, node) { 
+      node = Ntk_LatchReadDataInput(node);
+      st_lookup(node2MvfAigTable, node, &mvfAig);
+      mvfSize = array_n(mvfAig);
+      for(i=0; i<mvfSize; i++){
+        v = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(mvfAig, i));
+	array_insert_last(bAigEdge_t, tnodeArray, v);
+      }
+
+      mAigId = Ntk_NodeReadMAigId(node);
+      mVar = array_fetch(mAigMvar_t, mVarList, mAigId);
+      for(i=0, index1=mVar.bVars; i<mVar.encodeLength; i++) {
+        bVar = array_fetch(mAigBvar_t, bVarList, index1++);
+        v = bVar.node;
+        v = bAig_GetCanonical(manager, v);
+	array_insert_last(bAigEdge_t, tnodeArray, v);
+      }
+    }
+    Ntk_NetworkForEachPrimaryOutput(network, gen, node) { 
+      st_lookup(node2MvfAigTable, node, &mvfAig);
+      mvfSize = array_n(mvfAig);
+      for(i=0; i<mvfSize; i++){
+        v = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(mvfAig, i));
+	array_insert_last(bAigEdge_t, tnodeArray, v);
+      }
+    }
+  }
+
+  count = bAigNodeID(manager->nodesArraySize);
+  for(i=0; i<count; i++) {
+    manager->bddIdArray[i] = -1;
+    manager->bddArray[i] = 0;
+  }
+  manager->bddArray[0] = bdd_zero(mgr);
+
+  bddIdIndex = 0;
+  for(i=bAigNodeSize; i<manager->nodesArraySize; i+=bAigNodeSize) {
+    if(leftChild(i) != 2)	continue;
+    bdd = bdd_get_variable(mgr, bddIdIndex);
+    manager->bddIdArray[bAigNodeID(i)] = bddIdIndex;
+    manager->bddArray[bAigNodeID(i)] = bdd;
+    bddIdIndex++;
+  }
+
+  if(nodeArray) {
+    for(i=0; i<array_n(nodeArray); i++) {
+      v = array_fetch(bAigEdge_t, nodeArray, i);
+      v = bAig_GetCanonical(manager, v);
+      bAig_BddSweepSub(manager, mgr, v, bdd2vertex, sizeLimit, &bddIdIndex);
+    }
+  }
+  else {
+    for(i=0; i<array_n(tnodeArray); i++) {
+      v = array_fetch(bAigEdge_t, tnodeArray, i);
+      v = bAig_GetCanonical(manager, v);
+      bAig_BddSweepSub(manager, mgr, v, bdd2vertex, sizeLimit, &bddIdIndex);
+    }
+    array_free(tnodeArray);
+  }
+  
+  count = bAigNodeID(manager->nodesArraySize);
+  for(i=0; i<count; i++) {
+    if(manager->bddArray[i])	{
+      bdd_free(manager->bddArray[i]);
+      manager->bddArray[i] = 0;
+    }
+  }
+
+  st_foreach_item(bdd2vertex, gen1, &func, &v) {
+    bdd_free(func);
+  }
+  st_free_table(bdd2vertex);
+
+  count = bAigNodeID(manager->nodesArraySize);
+  curSize = 0;
+  for(i=0; i<count; i++) {
+    if(bAigGetPassFlag(manager, i*bAigNodeSize)) {
+      curSize++;
+    }
+  }
+  /*
+  fprintf(vis_stdout, "NOTICE : Before %d after %d used %d\n", 
+	  maxSize/bAigNodeSize, count, (maxSize-curSize)/bAigNodeSize);
+  fflush(vis_stdout);
+  */
+  return;
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Auxiliary function for BDD sweeping]
+
+  Description [Auxiliary function for BDD sweeping]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAig_BddSweepSub(
+	bAig_Manager_t *manager, 
+	mdd_manager *mgr, 
+	bAigEdge_t v, 
+	st_table *bdd2vertex,
+	int sizeLimit,
+	int *newBddIdIndex)
+{
+  bAigEdge_t left, right, oldV, nv;
+  bdd_t *leftBdd, *rightBdd;
+  bdd_t *func, *nfunc, *funcBar, *newBdd;
+  int newId, size;
+
+  if(v == 0 || v == 1)	return;
+  if(manager->bddArray[bAigNodeID(v)]) {
+    return;
+  }
+
+  left = leftChild(v);
+  right = rightChild(v);
+  left = bAig_GetCanonical(manager, left);
+  right = bAig_GetCanonical(manager, right);
+
+  if(left == 2 && right == 2) {
+    return;
+  }
+
+  bAig_BddSweepSub(manager, mgr, left, bdd2vertex, sizeLimit, newBddIdIndex);
+  bAig_BddSweepSub(manager, mgr, right, bdd2vertex, sizeLimit, newBddIdIndex);
+
+  v = bAig_GetCanonical(manager, v);
+  if(manager->bddArray[bAigNodeID(v)]) {
+    return;
+  }
+
+  left = leftChild(v);
+  right = rightChild(v);
+  left = bAig_GetCanonical(manager, left);
+  right = bAig_GetCanonical(manager, right);
+
+  leftBdd = manager->bddArray[bAigNodeID(left)];
+  rightBdd = manager->bddArray[bAigNodeID(right)];
+
+  if(leftBdd == 0) {
+    bAig_BddSweepSub(manager, mgr, left, bdd2vertex, sizeLimit, newBddIdIndex);
+    left = bAig_GetCanonical(manager, left);
+    leftBdd = manager->bddArray[bAigNodeID(left)];
+  }
+
+  if(rightBdd == 0) {
+    bAig_BddSweepSub(manager, mgr, right, bdd2vertex, sizeLimit, newBddIdIndex);
+    right = bAig_GetCanonical(manager, right);
+    rightBdd = manager->bddArray[bAigNodeID(right)];
+  }
+
+  /**
+  bAig_VerifyBddArray(manager, leftBdd, left);
+  bAig_VerifyBddArray(manager, rightBdd, right);
+  **/
+
+  if(leftBdd == 0 || rightBdd == 0) {
+    fprintf(vis_stdout, 
+	    "ERROR : all the nodes should have bdd node at this moment\n");
+  }
+
+  func = bdd_and(leftBdd, rightBdd, 
+	     !bAig_IsInverted(left), !bAig_IsInverted(right));
+
+  if(bAig_IsInverted(v))	{
+    funcBar = bdd_not(func);
+    nfunc = funcBar;
+  }
+  else {
+    nfunc = bdd_dup(func);
+  }
+
+  if(st_lookup(bdd2vertex, nfunc, &oldV)) {
+    bAig_Merge(manager, oldV, v);
+  }
+  else {
+    funcBar = bdd_not(nfunc);
+    if(st_lookup(bdd2vertex, funcBar, &oldV)) {
+      bAig_Merge(manager, bAig_Not(oldV), v);
+    }
+    bdd_free(funcBar);
+  }
+  bdd_free(nfunc);
+
+  v = bAig_NonInvertedEdge(v);
+  nv = bAig_GetCanonical(manager, v);
+  v = nv;
+
+  if(manager->bddArray[bAigNodeID(v)] == 0) {
+    size = bdd_size(func);
+    if(size > sizeLimit) {
+      newId = *newBddIdIndex;
+      (*newBddIdIndex) ++;
+      newBdd = bdd_get_variable(mgr, newId);
+      manager->bddIdArray[bAigNodeID(v)] = newId;
+      bdd_free(func);
+      func = newBdd;
+      manager->bddArray[bAigNodeID(v)] = func;
+      st_insert(bdd2vertex, (char *)bdd_dup(func), (char *)bAig_NonInvertedEdge(v));
+    }
+    else {
+      if(bAig_IsInverted(v)) {
+        funcBar = bdd_not(func);
+        manager->bddArray[bAigNodeID(v)] = funcBar;
+        st_insert(bdd2vertex, (char *)func, (char *)v);
+      }
+      else {
+        manager->bddArray[bAigNodeID(v)] = func;
+        st_insert(bdd2vertex, (char *)bdd_dup(func), (char *)v);
+      }
+    }
+  }
+  else 	bdd_free(func);
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Build aig nodes in breath first manner]
+
+  Description [Build aig nodes in breath first manner]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAig_BuildAigBFSManner(
+	Ntk_Network_t *network, 
+	mAig_Manager_t *manager, 
+	st_table *leaves,
+	int sweep)
+{
+array_t *nodeArray, *result;
+lsGen gen1;
+int iter, maxLevel, level;
+int i, j, k;
+bAigEdge_t v;
+Ntk_Node_t *node, *fanin, *fanout;
+st_table *node2mvfAigTable;
+array_t *curArray, *nextArray, *tmpArray;
+array_t *levelArray, *clevelArray;
+MvfAig_Function_t  *mvfAig;
+int mvfSize;
+st_generator *gen;
+
+  Ntk_NetworkForEachNode(network, gen1, node) {
+    Ntk_NodeSetUndef(node, (void *)0);
+  }
+
+  curArray = array_alloc(Ntk_Node_t *, 0);
+  st_foreach_item(leaves, gen, &node, &fanout) {
+    array_insert_last(Ntk_Node_t *, curArray, node);
+    Ntk_NodeSetUndef(node, (void *)1);
+  }
+
+  levelArray = array_alloc(array_t *, 10);
+  nextArray = array_alloc(Ntk_Node_t *, 0);
+  iter = 0;
+  while(1) {
+    clevelArray = array_alloc(array_t *, 10);
+    array_insert_last(array_t *, levelArray, clevelArray);
+    for(i=0; i<array_n(curArray); i++) {
+      node = array_fetch(Ntk_Node_t *, curArray, i);
+      Ntk_NodeForEachFanout(node, j, fanout) {  
+
+	level = (int)(long)Ntk_NodeReadUndef(fanout);
+	if(level > 0)	continue;
+
+	maxLevel = 0;
+	Ntk_NodeForEachFanin(fanout, k, fanin) {
+	  level = (int)(long)Ntk_NodeReadUndef(fanin);
+	  if(level == 0) {
+	    maxLevel = 0;
+	    break;
+	  }
+	  else if(level > maxLevel) {
+	    maxLevel = level;
+	  }
+	}
+
+	if(maxLevel > 0) {
+          Ntk_NodeSetUndef(fanout, (void *)(long)(maxLevel+1));
+	  array_insert_last(Ntk_Node_t *, nextArray, fanout);
+	  array_insert_last(Ntk_Node_t *, clevelArray, fanout);
+	}
+      }
+    }
+    
+    curArray->num = 0;
+    tmpArray = curArray;
+    curArray = nextArray;
+    nextArray = tmpArray;
+    if(curArray->num == 0)	break;
+
+    iter++;
+  }
+
+  Ntk_NetworkForEachNode(network, gen1, node) {
+    Ntk_NodeSetUndef(node, (void *)0);
+  }
+
+  for(i=0; i<array_n(levelArray); i++) {
+    clevelArray = array_fetch(array_t *, levelArray, i);
+    result = ntmaig_NetworkBuildMvfAigs(network, clevelArray, leaves);
+    MvfAig_FunctionArrayFree(result);
+    node2mvfAigTable = (st_table *) Ntk_NetworkReadApplInfo(
+	    network, MVFAIG_NETWORK_APPL_KEY);
+
+    if(i < 50 && sweep) {
+      nodeArray = array_alloc(bAigEdge_t, 0);
+      for(j=0; j<array_n(clevelArray); j++) {
+        node = array_fetch(Ntk_Node_t *, clevelArray, j);
+        st_lookup(node2mvfAigTable, node, &mvfAig);
+        mvfSize = array_n(mvfAig);
+        for(k=0; k<mvfSize; k++){
+          v = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(mvfAig, k));
+          array_insert_last(bAigEdge_t, nodeArray, v);
+        }
+      }
+
+      bAig_BddSweepForceMain(network, nodeArray);
+  
+      for(j=0; j<array_n(clevelArray); j++) {
+        node = array_fetch(Ntk_Node_t *, clevelArray, j);
+        st_lookup(node2mvfAigTable, node, &mvfAig);
+        mvfSize = array_n(mvfAig);
+        for(k=0; k<mvfSize; k++){
+          v = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(mvfAig, k));
+          array_insert(bAigEdge_t, nodeArray, v, k);
+        }
+      }
+      array_free(nodeArray);
+    }
+
+    array_free(clevelArray);
+  }
+  array_free(levelArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [BDD sweeping ]
+
+  Description [BDD sweeping ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAig_BddSweepForceMain(Ntk_Network_t *network, array_t *nodeArray)
+{
+  array_t *mVarList, *bVarList;
+  bdd_t *bdd, *func;
+  int bddIdIndex;
+  int i, count, sizeLimit, mvfSize;
+  int maxSize, curSize;
+  array_t *tnodeArray;
+  lsGen gen;
+  st_generator *gen1;
+  Ntk_Node_t *node;
+  bAigEdge_t v;
+  MvfAig_Function_t  *mvfAig;
+  mAig_Manager_t *manager;
+  mdd_manager *mgr;
+  st_table *node2MvfAigTable;
+  st_table * bdd2vertex;
+  mAigMvar_t mVar;
+  mAigBvar_t bVar;
+  int index1, mAigId;
+  int newmask, resetNewmask;
+  int usedAig;
+
+
+  manager = Ntk_NetworkReadMAigManager(network);
+
+  mgr = Ntk_NetworkReadMddManager(network);
+  if(mgr == 0) {
+    Ord_NetworkOrderVariables(network, Ord_RootsByDefault_c, 
+	    Ord_NodesByDefault_c, FALSE, Ord_InputAndLatch_c, 
+	    Ord_Unassigned_c, 0, 0);
+    mgr = Ntk_NetworkReadMddManager(network);
+  }
+  node2MvfAigTable = 
+      (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+
+  bdd2vertex = st_init_table(SweepBddCompare, SweepBddHash);
+
+  sizeLimit = 500;
+  maxSize = manager->nodesArraySize;
+
+  tnodeArray = 0;
+  if(nodeArray == 0) {
+    bVarList = mAigReadBinVarList(manager);
+    mVarList = mAigReadMulVarList(manager);
+    tnodeArray = array_alloc(bAigEdge_t, 0);
+    Ntk_NetworkForEachLatch(network, gen, node) { 
+      node = Ntk_LatchReadDataInput(node);
+      st_lookup(node2MvfAigTable, node, &mvfAig);
+      mvfSize = array_n(mvfAig);
+      for(i=0; i<mvfSize; i++){
+        v = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(mvfAig, i));
+	array_insert_last(bAigEdge_t, tnodeArray, v);
+      }
+
+      mAigId = Ntk_NodeReadMAigId(node);
+      mVar = array_fetch(mAigMvar_t, mVarList, mAigId);
+      for(i=0, index1=mVar.bVars; i<mVar.encodeLength; i++) {
+        bVar = array_fetch(mAigBvar_t, bVarList, index1++);
+        v = bVar.node;
+        v = bAig_GetCanonical(manager, v);
+	array_insert_last(bAigEdge_t, tnodeArray, v);
+      }
+    }
+    Ntk_NetworkForEachPrimaryOutput(network, gen, node) { 
+      st_lookup(node2MvfAigTable, node, &mvfAig);
+      mvfSize = array_n(mvfAig);
+      for(i=0; i<mvfSize; i++){
+        v = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(mvfAig, i));
+	array_insert_last(bAigEdge_t, tnodeArray, v);
+      }
+    }
+  }
+
+  count = bAigNodeID(manager->nodesArraySize);
+  for(i=0; i<count; i++) {
+    manager->bddIdArray[i] = -1;
+    manager->bddArray[i] = 0;
+  }
+  manager->bddArray[0] = bdd_zero(mgr);
+
+  bddIdIndex = 0;
+  for(i=bAigNodeSize; i<manager->nodesArraySize; i+=bAigNodeSize) {
+    if(leftChild(i) != 2)	continue;
+    bdd = bdd_get_variable(mgr, bddIdIndex);
+    manager->bddIdArray[bAigNodeID(i)] = bddIdIndex;
+    manager->bddArray[bAigNodeID(i)] = bdd;
+    bddIdIndex++;
+  }
+
+  if(nodeArray) {
+    for(i=0; i<array_n(nodeArray); i++) {
+      v = array_fetch(bAigEdge_t, nodeArray, i);
+      v = bAig_GetCanonical(manager, v);
+      bAig_BddSweepForceSub(manager, mgr, v, bdd2vertex, sizeLimit, &bddIdIndex);
+    }
+  }
+  else {
+    for(i=0; i<array_n(tnodeArray); i++) {
+      v = array_fetch(bAigEdge_t, tnodeArray, i);
+      v = bAig_GetCanonical(manager, v);
+      bAig_BddSweepForceSub(manager, mgr, v, bdd2vertex, sizeLimit, &bddIdIndex);
+    }
+  }
+  
+  count = bAigNodeID(manager->nodesArraySize);
+  for(i=0; i<count; i++) {
+    if(manager->bddArray[i])	{
+      bdd_free(manager->bddArray[i]);
+      manager->bddArray[i] = 0;
+    }
+  }
+
+  st_foreach_item(bdd2vertex, gen1, &func, &v) {
+    bdd_free(func);
+  }
+  st_free_table(bdd2vertex);
+
+  count = bAigNodeID(manager->nodesArraySize);
+  curSize = 0;
+  for(i=0; i<count; i++) {
+    if(bAigGetPassFlag(manager, i*bAigNodeSize)) {
+      curSize++;
+    }
+  }
+
+
+  newmask = 0x00000100;
+  resetNewmask = 0xfffffeff;
+  if(tnodeArray) {
+  for(i=0; i<array_n(tnodeArray); i++) {
+    v = array_fetch(int, tnodeArray, i);
+    bAig_SetMaskTransitiveFanin(manager, v, newmask);
+  }
+
+  usedAig = 0;
+  for(i=bAigNodeSize; i<manager->nodesArraySize; i+=bAigNodeSize) {
+    if(flags(i) & newmask)	usedAig++;
+  }
+
+  for(i=0; i<array_n(tnodeArray); i++) {
+    v = array_fetch(int, tnodeArray, i);
+    bAig_ResetMaskTransitiveFanin(manager, v, newmask, resetNewmask);
+  }
+  array_free(tnodeArray);
+  fprintf(vis_stdout, "NOTICE : Before %d after %d used %d\n", 
+	  maxSize/bAigNodeSize, count, usedAig);
+  fflush(vis_stdout);
+  }
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Auxilary function BDD sweeping ]
+
+  Description [Auxilary function BDD sweeping ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAig_BddSweepForceSub(
+	bAig_Manager_t *manager, 
+	mdd_manager *mgr, 
+	bAigEdge_t v, 
+	st_table *bdd2vertex,
+	int sizeLimit,
+	int *newBddIdIndex)
+{
+  bAigEdge_t left, right, oldV, nv;
+  bdd_t *leftBdd, *rightBdd;
+  bdd_t *func, *nfunc, *funcBar, *newBdd;
+  int newId, size;
+
+  if(v == 0 || v == 1)	return;
+  if(manager->bddArray[bAigNodeID(v)]) {
+    return;
+  }
+
+
+  left = leftChild(v);
+  right = rightChild(v);
+  left = bAig_GetCanonical(manager, left);
+  right = bAig_GetCanonical(manager, right);
+
+  if(left == 2 && right == 2) {
+    return;
+  }
+
+  bAig_BddSweepForceSub(manager, mgr, left, bdd2vertex, sizeLimit, newBddIdIndex);
+  bAig_BddSweepForceSub(manager, mgr, right, bdd2vertex, sizeLimit, newBddIdIndex);
+
+  v = bAig_GetCanonical(manager, v);
+  if(manager->bddArray[bAigNodeID(v)]) {
+    return;
+  }
+
+  left = leftChild(v);
+  right = rightChild(v);
+  left = bAig_GetCanonical(manager, left);
+  right = bAig_GetCanonical(manager, right);
+
+  leftBdd = manager->bddArray[bAigNodeID(left)];
+  rightBdd = manager->bddArray[bAigNodeID(right)];
+
+  if(leftBdd == 0) {
+    bAig_BddSweepForceSub(manager, mgr, left, bdd2vertex, sizeLimit, newBddIdIndex);
+    left = bAig_GetCanonical(manager, left);
+    leftBdd = manager->bddArray[bAigNodeID(left)];
+  }
+
+  if(rightBdd == 0) {
+    bAig_BddSweepForceSub(manager, mgr, right, bdd2vertex, sizeLimit, newBddIdIndex);
+    right = bAig_GetCanonical(manager, right);
+    rightBdd = manager->bddArray[bAigNodeID(right)];
+  }
+
+  /**
+  bAig_VerifyBddArray(manager, leftBdd, left);
+  bAig_VerifyBddArray(manager, rightBdd, right);
+  **/
+
+  if(leftBdd == 0 || rightBdd == 0) {
+    fprintf(vis_stdout, 
+	    "ERROR : all the nodes should have bdd node at this moment\n");
+  }
+
+  func = bdd_and(leftBdd, rightBdd, 
+	     !bAig_IsInverted(left), !bAig_IsInverted(right));
+
+  if(bAig_IsInverted(v))	{
+    funcBar = bdd_not(func);
+    nfunc = funcBar;
+  }
+  else {
+    nfunc = bdd_dup(func);
+  }
+
+  if(st_lookup(bdd2vertex, nfunc, &oldV)) {
+    bAig_Merge(manager, oldV, v);
+  }
+  else {
+    funcBar = bdd_not(nfunc);
+    if(st_lookup(bdd2vertex, funcBar, &oldV)) {
+      bAig_Merge(manager, bAig_Not(oldV), v);
+    }
+    bdd_free(funcBar);
+  }
+  bdd_free(nfunc);
+
+  v = bAig_NonInvertedEdge(v);
+  nv = bAig_GetCanonical(manager, v);
+  v = nv;
+
+  if(manager->bddArray[bAigNodeID(v)] == 0) {
+    size = bdd_size(func);
+    if(size > sizeLimit) {
+      newId = *newBddIdIndex;
+      (*newBddIdIndex) ++;
+      newBdd = bdd_get_variable(mgr, newId);
+      manager->bddIdArray[bAigNodeID(v)] = newId;
+      bdd_free(func);
+      func = newBdd;
+      manager->bddArray[bAigNodeID(v)] = func;
+      st_insert(bdd2vertex, (char *)bdd_dup(func), (char *)bAig_NonInvertedEdge(v));
+    }
+    else {
+      if(bAig_IsInverted(v)) {
+        funcBar = bdd_not(func);
+        manager->bddArray[bAigNodeID(v)] = funcBar;
+        st_insert(bdd2vertex, (char *)func, (char *)v);
+      }
+      else {
+        manager->bddArray[bAigNodeID(v)] = func;
+        st_insert(bdd2vertex, (char *)bdd_dup(func), (char *)v);
+      }
+    }
+  }
+  else 	bdd_free(func);
+
+  return;
+}
Index: vis_dev/vis-2.3/src/baig/baigCmd.c
===================================================================
--- vis_dev/vis-2.3/src/baig/baigCmd.c	(revision 14)
+++ vis_dev/vis-2.3/src/baig/baigCmd.c	(revision 14)
@@ -0,0 +1,728 @@
+/**CFile***********************************************************************
+
+  FileName    [baigCmd.c]
+
+  PackageName [baig]
+
+  Synopsis    [Functions to initialize and shut down the bAig manager.]
+
+  Author      [Mohammad Awedh]
+
+  Copyright [ This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "maig.h"
+#include "ntk.h"
+#include "cmd.h"
+#include "baig.h"
+#include "baigInt.h"
+#include "ctlsp.h"
+
+static char rcsid[] UNUSED = "$Id: baigCmd.c,v 1.32 2009/04/12 00:14:03 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+static jmp_buf timeOutEnv;
+static int bmcTimeOut;		/* timeout value */
+static long alarmLapTime;	/* starting CPU time for timeout */
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandPrintPartitionAig(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandPrintAigStats(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandCheckInvariantSat(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static void TimeOutHandle(void);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Initialize baig package]
+
+  SideEffects [none]
+
+  SeeAlso     [bAig_End]
+
+******************************************************************************/
+void
+bAig_Init(void)
+{
+  Cmd_CommandAdd("print_partition_aig_dot", CommandPrintPartitionAig, 0);
+  Cmd_CommandAdd("print_aig_stats", CommandPrintAigStats, 0);
+  Cmd_CommandAdd("check_invariant_sat", CommandCheckInvariantSat, 0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [End baig package]
+
+  SideEffects []
+
+  SeeAlso     [bAig_Init]
+
+******************************************************************************/
+void
+bAig_End(void)
+{
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a new bAig manager.]
+
+  Description [Creates a new bAig manager, Create a NodeArray of size equal to
+  maxSize * bAigNodeSize. Returns a pointer to the manager if successful; 
+  NULL otherwise.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+bAig_Manager_t *
+bAig_initAig(
+  int maxSize /* maximum number of nodes in the AIG graph */
+)
+{
+  int i;
+
+  bAig_Manager_t *manager = ALLOC(bAig_Manager_t,1);
+  if (manager == NIL( bAig_Manager_t)){
+    return NIL( bAig_Manager_t);
+  }
+  /*Bing:*/
+  memset(manager,0,sizeof(bAig_Manager_t ));
+
+  maxSize = maxSize * bAigNodeSize;  /* each node is a size of bAigNodeSize */
+
+  /* ??? */
+  /*  maxSize = (maxSize/bAigNodeSize)*bAigNodeSize;
+  if (maxSize >  bAigArrayMaxSize ) {
+  }*/
+  manager->NodesArray = ALLOC(bAigEdge_t, maxSize);
+  manager->maxNodesArraySize = maxSize;
+  manager->nodesArraySize = bAigFirstNodeIndex;
+
+  fanout(0) = 0;
+  canonical(0) = 0;
+  flags(0) = 0;
+  aig_value(0) = 2;
+  next(0) = bAig_NULL;
+  /*Bing:*/
+  memset(manager->NodesArray,0,maxSize*sizeof(bAigEdge_t));
+
+  manager->SymbolTable = st_init_table(strcmp,st_strhash);
+  manager->nameList = ALLOC(char *, manager->maxNodesArraySize/bAigNodeSize);
+  manager->bddIdArray = ALLOC(int, manager->maxNodesArraySize/bAigNodeSize);
+  manager->bddArray = ALLOC(bdd_t *, manager->maxNodesArraySize/bAigNodeSize);
+
+  manager->HashTable =  ALLOC(bAigEdge_t, bAig_HashTableSize);
+  for (i=0; i<bAig_HashTableSize; i++)
+    manager->HashTable[i]= bAig_NULL; 
+
+  manager->mVarList = array_alloc(mAigMvar_t, 0);
+  manager->bVarList = array_alloc(mAigBvar_t, 0);
+  manager->timeframe = 0;
+  manager->timeframeWOI = 0;
+  manager->literals = 0;
+    
+  /* Bing: for MultiCut */
+  manager->SymbolTableArray = ALLOC(st_table *,100);
+  manager->HashTableArray = ALLOC(bAigEdge_t *,100);
+  manager->NumOfTable = 100;
+
+  /* Bing: for interpolation */
+  manager->class_ = 1;
+  manager->InitState = bAig_One;
+  manager->assertArray = (satArray_t *)0;
+
+  return(manager);
+
+} /* end of bAig_Init */
+
+
+/**Function********************************************************************
+
+  Synopsis [Quit bAig manager]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAig_quit(
+  bAig_Manager_t *manager)
+{
+  char          *name;
+  st_generator  *stGen;
+  bAigEdge_t    varIndex;
+
+  if (manager->mVarList != NIL(array_t)){
+    array_free(manager->mVarList);
+  }
+  if (manager->bVarList != NIL(array_t)){
+    array_free(manager->bVarList);
+  }
+  FREE(manager->HashTable);
+  st_foreach_item(manager->SymbolTable, stGen, &name, &varIndex) {
+    FREE(name);
+  }
+  st_free_table(manager->SymbolTable);
+  /* i is too small to represent 80000
+  for (i=0; i< manager->maxNodesArraySize/bAigNodeSize ; i++){
+    FREE(manager->nameList[i]);
+  }
+  */
+  FREE(manager->nameList);
+  FREE(manager->NodesArray);
+  bAig_FreeTimeFrame(manager->timeframe);
+  bAig_FreeTimeFrame(manager->timeframeWOI);
+  FREE(manager);
+
+  /* Free SymbolTableArray and HashTableArray? */
+}
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void 
+bAig_NodePrint(
+   bAig_Manager_t *manager,
+   bAigEdge_t node)
+{
+  if (node == bAig_Zero) {
+    printf("0");
+    return;
+  }
+  if (node == bAig_One) {
+    printf("1");
+    return;
+  }
+  if (bAig_IsInverted(node)){
+    printf(" NOT(");
+  }
+  if (bAigIsVar(manager,node)) {
+    printf("Var Node");
+  } else {
+    printf("(");
+    bAig_NodePrint(manager, leftChild(node));
+    printf("AND");
+    bAig_NodePrint(manager, rightChild(node));
+    printf(")");
+  }
+  if (bAig_IsInverted(node)){
+    printf(")");
+  }
+
+} /* bAig_NodePrint */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the print_partition_aig_dot command.]
+  
+  CommandName [print_partition_aig_dot]
+
+  CommandSynopsis [Print a dot description of the AND/INVERTER graph that was
+  built for the flattened network]
+
+  CommandArguments [\[-h\] &lt;file_name&gt;]
+
+  CommandDescription [Write a file in the format taken by the tool <tt>dot</tt>
+  depicting the topology of the AND/INVERTER graph. 
+  Dot is a tool that given a description of a graph in a certain format it 
+  produces a postscript print of the graph. 
+  For more information about <tt>dot</tt> look in <a
+  href="http://www.research.att.com/orgs/ssr/book/reuse">
+  http://www.research.att.com/orgs/ssr/book/reuse</a>. Once a dot file is
+  produced with this command, the shell command <tt>dot -Tps <filename>
+  &gt;<file>.ps</tt> will produce the postscript file depicting the network.<p>
+
+  If no argument is specified on the command line, the description is written
+  to the standard output.<p>
+
+  Command options:<p>
+  <dl><dt> -h
+  <dd> Print the command usage.
+  </dl>]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+CommandPrintPartitionAig(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  FILE *fp;
+  int c, i, mvfSize;
+  Ntk_Network_t *network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+  mAig_Manager_t *manager;
+  MvfAig_Function_t  *mvfAig;
+  bAigEdge_t v;
+  Ntk_Node_t *node, *latch;
+  st_table   *node2MvfAigTable;
+  lsGen gen;
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc,argv,"h")) != EOF){
+    switch(c){
+      case 'h':
+        goto usage;
+      default:
+        goto usage;
+    }
+  }
+  /* Check if the network has been read in */
+  if (network == NIL(Ntk_Network_t)) {
+    return 1;
+  }
+
+  if (argc == 1) {
+    fp = stdout;
+  }
+  else if (argc == 2) {
+    fp = Cmd_FileOpen(*(++argv), "w", NIL(char *), /* silent */ 1);
+    if (fp == NIL(FILE)) {
+      (void) fprintf(vis_stderr, "Cannot write to %s\n", *argv);
+      return 1;
+    }
+  }
+  else {
+    goto usage;
+  }
+
+  manager = Ntk_NetworkReadMAigManager(network);
+
+  if (manager == NIL(mAig_Manager_t)) {
+    return 1;
+  }
+  node2MvfAigTable = 
+	(st_table *)Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+
+  Ntk_NetworkForEachLatch(network, gen, latch) {
+    node = Ntk_LatchReadDataInput(latch);
+    st_lookup(node2MvfAigTable, node, &mvfAig);
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+      bAig_SetMaskTransitiveFanin(manager, v, VisitedMask);
+    }
+  }
+  Ntk_NetworkForEachPrimaryOutput(network, gen, node) {
+    st_lookup(node2MvfAigTable, node, &mvfAig);
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+      bAig_SetMaskTransitiveFanin(manager, v, VisitedMask);
+    }
+  }
+
+  Ntk_NetworkForEachNode(network, gen, node) {
+    st_lookup(node2MvfAigTable, node, &mvfAig);
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+      bAig_SetMaskTransitiveFanin(manager, v, VisitedMask);
+    }
+  }
+
+  bAig_PrintDot(fp, manager);
+  Ntk_NetworkForEachLatch(network, gen, latch) {
+    node = Ntk_LatchReadInitialInput(latch);
+    st_lookup(node2MvfAigTable, node, &mvfAig);
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+      bAig_ResetMaskTransitiveFanin(manager, v, VisitedMask, ResetVisitedMask);
+    }
+  }
+  Ntk_NetworkForEachPrimaryOutput(network, gen, node) {
+    st_lookup(node2MvfAigTable, node, &mvfAig);
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+      bAig_ResetMaskTransitiveFanin(manager, v, VisitedMask, ResetVisitedMask);
+    }
+  }
+  Ntk_NetworkForEachNode(network, gen, node) {
+    st_lookup(node2MvfAigTable, node, &mvfAig);
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+      bAig_ResetMaskTransitiveFanin(manager, v, VisitedMask, ResetVisitedMask);
+    }
+  }
+
+  return 0;
+usage:
+  (void) fprintf(vis_stderr, "usage: print_partition_aig_dot [-h] [file]\n");
+  (void) fprintf(vis_stderr, "    -h\t\tprint the command usage\n");
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the print_aig_stats command.]
+  CommandName [print_aig_stats]
+
+  CommandSynopsis [print statistics about the AND/INVERTER graph.]
+
+  CommandArguments [\[-h\] \[-n\]]
+
+  CommandDescription [Print the following statistics about the AND/INVERTER 
+  graph:
+
+ <dl>
+  <li> <b>Maximum number of nodes:</b> the maximum number of nodes in the AND/
+  INVERTER graph.
+
+  <li> <b>Current number of nodes:</b> the number of nodes in the AND/INVERTER
+  graph that are used.
+
+ </dl>
+
+  Note that <tt>build_partition_maigs</tt> must be called before this command.<p>
+
+  Command options:<p>
+
+  <dl>
+  <dt> -n
+  <dd> Print the name of the nodes.<p>
+  <dt> -h
+  <dd> Print the command usage.<p>
+  </dl>
+  ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+CommandPrintAigStats(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  Ntk_Network_t *network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+  mAig_Manager_t *manager;
+  int i;
+  int printVar = 0;
+  int c;
+
+  /*
+   * Parse command line options.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "hn")) != EOF) {
+    switch(c) {
+      case 'h':
+        goto usage;
+     case 'n':
+       printVar = 1;
+        break;
+      default:
+        goto usage;
+    }
+  }
+  if (network == NIL(Ntk_Network_t)) {
+    return 1;
+  }
+
+  manager = Ntk_NetworkReadMAigManager(network);
+
+  if (manager == NIL(mAig_Manager_t)) {
+    return 1;
+  }
+  (void) fprintf(vis_stdout,"And/Inverter graph Static Report\n");
+  (void) fprintf(vis_stdout,"Maximum number of nodes: %ld\n", manager->maxNodesArraySize/bAigNodeSize);
+  (void) fprintf(vis_stdout,"Current number of nodes: %ld\n\n", manager->nodesArraySize/bAigNodeSize);
+  if (printVar == 1){
+     (void) fprintf(vis_stdout,"Nodes name\n");
+     for(i=1; i< manager->nodesArraySize/bAigNodeSize; i++){
+        if (manager->nameList[i][0] != 'N'){
+           (void) fprintf(vis_stdout,"%s\n", manager->nameList[i]);
+        }
+     }
+  }
+  return 0;
+usage:
+  (void) fprintf(vis_stderr, "usage: print_aig_stats [-h] [-n] \n");
+  (void) fprintf(vis_stderr, "   -h print the command usage\n");
+  (void) fprintf(vis_stderr, "   -n list of variables\n");
+  return 1;		/* error exit */
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the check_invariant_sat command.]
+  CommandName [check_invariant_sat]
+
+  CommandSynopsis [Check invariant property using sat based unmounded model checking]
+
+  CommandArguments [\[-h\] \[-d\] 
+                    \[-t &lt;timeOutPeriod&gt;\] 
+		    \[-m &lt;method&gt;\]
+		    \[-v &lt;verbosity_level&gt;\] 
+		    &lt;inv_file&gt; ]
+
+  CommandDescription [Perform SAT-based unbounded model checking on 
+  And-Inverter-Graph. The command compute fixed point of AG using AX operation.
+  AX is implemented using AllSAT enumeration algorithm.
+
+  Command options:<p>
+
+  <dl>
+  <dt> -d 
+  <dd> Disable inclusion test on initial states.<p>
+
+  <dt> -v  <code>&lt;verbosity_level&gt;</code>
+  <dd> Specify verbosity level. This sets the amount of feedback  on CPU usage and code status.
+
+  <dt> -t  <code>&lt;timeOutPeriod&gt;</code>
+  <dd> Specify the time out period (in seconds) after which the command aborts. By default this option is set to infinity.
+  <p>
+
+  <dt> -m  <code>&lt;method&gt;</code>
+  <dd> Specify the method for AllSAT algorithm.
+  <p>
+
+
+  <dt> -h
+  <dd> Print the command usage.<p>
+  </dl>
+
+  <dt> <code> &lt;inv_file&gt; </code>
+  <dd> File containing Invariant formulae to be checked.
+  ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+CommandCheckInvariantSat(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+char *filename;
+FILE *fin;
+array_t *invarArray;
+Ntk_Network_t     *network;
+bAig_Manager_t    *manager;
+bAigTransition_t *t;
+Ctlsp_Formula_t *formula;
+char c;int i, property;
+int timeOutPeriod;
+int passFlag, method;
+int interface, verbose;
+int inclusion_test;
+int constrain;
+int reductionUsingUnsat;
+int disableLifting;
+
+  timeOutPeriod = -1;
+  method = 1;
+  interface = 0;
+  inclusion_test = 1;
+  verbose = 0;
+  constrain = 1;
+  reductionUsingUnsat = 0;
+  disableLifting = 0;
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "hicdt:m:v:ul")) != EOF) {
+    switch(c) {
+      case 'h':
+	goto usage;
+      case 'i' :
+	interface = 1;
+	break;
+      case 'd' :
+	inclusion_test = 0;
+	break;
+      case 'c' :
+	constrain = 0;
+	break;
+      case 'u' :
+	reductionUsingUnsat = 1;
+	break;
+      case 'l' :
+	disableLifting = 1;
+	break;
+      case 't' :
+	timeOutPeriod = atoi(util_optarg);
+	break;
+      case 'v' :
+	verbose = atoi(util_optarg);
+	break;
+      case 'm' :
+	method = atoi(util_optarg);
+	break;
+    }
+  }
+  if (argc - util_optind == 0) {
+    (void) fprintf(vis_stderr, "** ERROR : file containing property file not provided\n");
+    goto usage;
+  }
+  else if (argc - util_optind > 1) {
+    (void) fprintf(vis_stderr, "** ERROR : too many arguments\n");
+    goto usage;
+  }
+  filename = util_strsav(argv[util_optind]);
+
+  if(!(fin = fopen(filename, "r"))) {
+    fprintf(vis_stdout, "Error : can't open invariant file %s\n", filename);
+    return(1);
+  }
+  invarArray = Ctlsp_FileParseFormulaArray(fin);
+  fclose(fin);
+
+  if (timeOutPeriod > 0) {
+    (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
+    (void) alarm(timeOutPeriod);
+    if (setjmp(timeOutEnv) > 0) {
+      (void) fprintf(vis_stderr,
+		"** ERROR : timeout occurred after %d seconds.\n", timeOutPeriod);
+      alarm(0);
+      return 1;
+    }
+  }
+
+  network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+  manager = Ntk_NetworkReadMAigManager(network);
+
+  t = bAigCreateTransitionRelation(network, manager);
+  t->method = method;
+  t->interface = interface;
+  t->inclusionInitial = inclusion_test;
+  t->verbose = verbose;
+  t->constrain = constrain;
+  t->disableLifting = disableLifting;
+  t->reductionUsingUnsat = reductionUsingUnsat;
+
+  if(t->verbose > 1) 
+    bAigPrintTransitionInfo(t);
+
+
+  fprintf(vis_stdout, "# INV: Summary of invariant pass/fail\n");
+  for(i=0; i<array_n(invarArray); i++) {
+    formula = array_fetch(Ctlsp_Formula_t *, invarArray, i);
+    Ctlsp_FormulaPrint(vis_stdout, formula);
+    fprintf(vis_stdout, "\n");
+
+    property = bAig_CreatebAigForInvariant(network, manager, formula);
+
+    passFlag = bAigCheckInvariantWithAG(t, property);
+
+    if(passFlag == 1) {
+      fprintf(vis_stdout, "# INV: formula passed --- ");
+      Ctlsp_FormulaPrint(vis_stdout, Ctlsp_FormulaReadOriginalFormula(formula));
+      fprintf(vis_stdout, "\n");
+    }
+    else {
+      fprintf(vis_stdout, "# INV: formula failed --- ");
+      Ctlsp_FormulaPrint(vis_stdout, Ctlsp_FormulaReadOriginalFormula(formula));
+      fprintf(vis_stdout, "\n");
+    }
+  }
+
+  return(0);
+
+  usage:
+  (void) fprintf(vis_stderr, "usage: check_invariant_sat [-h] <inv_file>\n");
+  (void) fprintf(vis_stderr, "   -h \tprint the command usage\n");
+  (void) fprintf(vis_stderr, "   -d \tdisable inclusion test on initial states\n");
+  (void) fprintf(vis_stderr, "   -m : 0 disable lifting\n");
+  (void) fprintf(vis_stderr, "        1 enable lifting (default)\n");
+  (void) fprintf(vis_stderr, "   <inv_file> Invariant file to be checked.\n");
+
+  return(1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Handle function for timeout.]
+
+  Description [This function is called when the time out occurs.
+  Since alarm is set with an elapsed time, this function checks if the
+  CPU time corresponds to the timeout of the command.  If not, it
+  reprograms the alarm to fire again later.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+TimeOutHandle(void)
+{
+  int seconds = (int) ((util_cpu_ctime() - alarmLapTime) / 1000);
+
+  if (seconds < bmcTimeOut) {
+    unsigned slack = (unsigned) (bmcTimeOut - seconds);
+    (void) signal(SIGALRM, (void(*)(int)) TimeOutHandle);
+    (void) alarm(slack);
+  } else {
+    longjmp(timeOutEnv, 1);
+  }
+} /* TimeOutHandle */
+
Index: vis_dev/vis-2.3/src/baig/baigInt.h
===================================================================
--- vis_dev/vis-2.3/src/baig/baigInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/baig/baigInt.h	(revision 14)
@@ -0,0 +1,98 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [baigInt.h]
+
+  PackageName [baig]
+
+  Synopsis    []
+
+  Description [Internal data structures of the bAig package.]
+
+  SeeAlso     []
+
+  Author      [Mohammad Awedh]
+
+  Copyright [ This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+  Revision    [$Id: baigInt.h,v 1.21 2005/07/15 21:09:26 jinh Exp $]
+
+******************************************************************************/
+
+#ifndef _bAIGINT
+#define _bAIGINT
+
+#include "util.h"
+#include "array.h"
+#include "baig.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/* Each node occupies 8 location.  The following describes these locations */
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void bAigSetPassFlag(bAig_Manager_t *manager, bAigEdge_t node);
+EXTERN void bAigResetPassFlag(bAig_Manager_t *manager, bAigEdge_t node);
+EXTERN int bAigGetPassFlag(bAig_Manager_t *manager, bAigEdge_t node);
+EXTERN bAigEdge_t bAigCreateAndNode(bAig_Manager_t *manager, bAigEdge_t node1, bAigEdge_t node2);
+EXTERN bAigTransition_t * bAigCreateTransitionRelation( Ntk_Network_t *network, mAig_Manager_t *manager);
+EXTERN int bAigCheckInvariantWithAG( bAigTransition_t *t, bAigEdge_t objective);
+EXTERN void bAigCleanUpDataFromPreviousExecution(bAigTransition_t *t);
+EXTERN bAigEdge_t bAigBuildObjectiveFromFrontierSet(bAigTransition_t *t);
+EXTERN satManager_t * bAigCirCUsInterfaceForAX(bAigTransition_t *t);
+EXTERN void bAigMarkConeOfInfluenceForAX(bAigTransition_t *t, satManager_t *cm);
+EXTERN void bAig_ComputeAX(bAigTransition_t *t);
+EXTERN void bAig_PostProcessForAX(bAigTransition_t *t, satManager_t *cm);
+EXTERN void bAigCreateSatManagerForLifting(bAigTransition_t *t);
+EXTERN void bAigSolveAllSatWithLifting(bAigTransition_t *t);
+EXTERN void bAigBlockingClauseAnalysisBasedOnLifting(bAigTransition_t *t, satManager_t *allsat);
+EXTERN void bAigCollectAntecdentOfObjective( bAigTransition_t *t, satManager_t *cm, bAigEdge_t obj, satArray_t *clauseArray);
+EXTERN void bAigMinimizationBasedOnLifting( bAigTransition_t *t, bAigEdge_t obj, satArray_t *orderArray);
+EXTERN int bAigCheckExistenceOfUIP( satManager_t *cm, satArray_t *clauseArray,int mLevel,  bAigEdge_t *fdaLit, int *bLevel);
+EXTERN void bAigSolverForLifting(satManager_t *cm, int tLevel);
+EXTERN void bAigCollectAntecdentOfObjectiveAux(satManager_t *cm, bAigEdge_t v);
+EXTERN int bAigInclusionTestOnInitialStates(bAigTransition_t *t);
+EXTERN void bAigPrintTransitionInfo(bAigTransition_t *t);
+EXTERN void bAigMinimizationBasedOnLiftingAllAtOnce( bAigTransition_t *t, bAigEdge_t obj, satArray_t *orderArray); 
+EXTERN satArray_t * bAigCreateCNFInstanceForInclusionTestOnInitialStates(bAigTransition_t *t);
+EXTERN void bAig_CreateCNFFromAIG( bAig_Manager_t *manager, satArray_t *rootArray, satArray_t *cnfArray);
+EXTERN void bAigCreateSatManagerForLiftingUnconstrained(bAigTransition_t *t);
+EXTERN bAigEdge_t bAigBuildComplementedObjectiveWithCNF( bAigTransition_t *t, satManager_t *cm, satArray_t *narr, satArray_t *carr);
+EXTERN void bAigPreProcessingForLiftingInstance(bAigTransition_t *t, satManager_t *cm);
+
+
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _bAIGINT */
Index: vis_dev/vis-2.3/src/baig/baigNode.c
===================================================================
--- vis_dev/vis-2.3/src/baig/baigNode.c	(revision 14)
+++ vis_dev/vis-2.3/src/baig/baigNode.c	(revision 14)
@@ -0,0 +1,1811 @@
+/**CFile***********************************************************************
+
+  FileName    [baigNode.c]
+
+  PackageName [baig]
+
+  Synopsis    [Routines to access node data structure of the And/Inverter
+               graph.]
+
+  Author      [Mohammad Awedh, HoonSang Jin]
+
+  Copyright [ This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+
+******************************************************************************/
+
+#include "vm.h"
+#include "baig.h"
+#include "baigInt.h"
+
+static char rcsid[] UNUSED = "$Id: baigNode.c,v 1.33 2009/04/12 00:14:03 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void connectOutput(bAig_Manager_t *manager, bAigEdge_t from, bAigEdge_t to, int inputIndex);
+static bAigEdge_t HashTableLookup(bAig_Manager_t *manager, bAigEdge_t node1, bAigEdge_t node2);
+static int HashTableAdd(bAig_Manager_t *manager, bAigEdge_t nodeIndexParent, bAigEdge_t nodeIndex1, bAigEdge_t nodeIndex2);
+static int HashTableDelete(bAig_Manager_t *manager, bAigEdge_t node);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Read Node's name.]
+
+  Description [Read the name of a node given its index.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+nameType_t *
+bAig_NodeReadName(
+   bAig_Manager_t *manager,
+   bAigEdge_t     node)
+{
+  return manager->nameList[bAigNodeID(node)];
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Set Node's name.]
+
+  Description [Set the name of node in Symbol table and name List]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void 
+bAig_NodeSetName(
+   bAig_Manager_t *manager,
+   bAigEdge_t     node,
+   nameType_t     *name)
+{
+  nameType_t *tmpName = manager->nameList[bAigNodeID(node)];
+  FREE(tmpName);
+  st_insert(manager->SymbolTable, name, (char*) (long) node);
+  manager->nameList[bAigNodeID(node)] = name;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the index of the right node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+bAig_NodeReadIndexOfRightChild(
+   bAig_Manager_t *manager,
+   bAigEdge_t nodeIndex)
+{
+  return rightChild(nodeIndex);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the index of the left node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bAigEdge_t
+bAig_NodeReadIndexOfLeftChild(
+   bAig_Manager_t *manager,
+   bAigEdge_t nodeIndex)
+{
+  return leftChild(nodeIndex);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Get canonical node of given node.]
+
+  Description [This function find node index that is functionally equivalent with given node index.]  
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bAigEdge_t
+bAig_GetCanonical(
+    bAig_Manager_t *manager, 
+    bAigEdge_t nodeIndex)
+{
+bAigEdge_t next;
+
+/*if(nodeIndex == bAig_NULL)	return(nodeIndex);*/
+
+//Bing: 
+ if(nodeIndex == bAig_NULL||
+    nodeIndex == bAig_One ||
+    nodeIndex == bAig_Zero)
+   return(nodeIndex); 
+
+  while(bAigGetPassFlag(manager, nodeIndex)) {
+    next = canonical(nodeIndex);
+    if(bAig_IsInverted(nodeIndex))  next = bAig_Not(next);
+    nodeIndex = next;
+  }
+  return(nodeIndex);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Merge two functionally equivalent node.]
+
+  Description [This function merges the equivalent two nodes. ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+bAig_Merge(
+    bAig_Manager_t *manager,
+    bAigEdge_t nodeIndex1,
+    bAigEdge_t nodeIndex2)
+{
+bAigEdge_t newNodeIndex, nodeIndex, tnodeIndex;
+bAigEdge_t leftIndex, rightIndex;
+bAigEdge_t outIndex, *pfan;
+int id1, id2;
+bAigEdge_t cur;
+bdd_t **bddArray;
+array_t *nodeArray;
+int i, ii, iii;
+long *ManagerNodesArray;
+
+  nodeIndex1 = bAig_GetCanonical(manager, nodeIndex1);
+  nodeIndex2 = bAig_GetCanonical(manager, nodeIndex2);
+
+  if(nodeIndex1 == nodeIndex2)	return(nodeIndex1);
+
+
+  ManagerNodesArray = manager->NodesArray;
+
+
+  newNodeIndex = nodeIndex1;     
+  if (bAig_NonInvertedEdge(nodeIndex1) > bAig_NonInvertedEdge(nodeIndex2)){
+    nodeIndex1 = nodeIndex2;
+    nodeIndex2 = newNodeIndex;
+  }
+
+  if(bAig_IsInverted(nodeIndex2)) {
+    nodeIndex1 = bAig_Not(nodeIndex1);
+    nodeIndex2 = bAig_Not(nodeIndex2);
+  }
+
+  nodeArray = array_alloc(bAigEdge_t, 0);
+  nodeIndex = nodeIndex2;
+  array_insert_last(bAigEdge_t, nodeArray, nodeIndex);
+  while(bAig_NonInvertedEdge(canonical(nodeIndex)) != bAig_NonInvertedEdge(nodeIndex2)){
+    if(bAig_IsInverted(nodeIndex))
+      nodeIndex = bAig_Not(canonical(nodeIndex));
+    else
+      nodeIndex = canonical(nodeIndex);
+    array_insert_last(bAigEdge_t, nodeArray, nodeIndex);
+  }
+
+  bAigSetPassFlag(manager, nodeIndex2);
+  nodeIndex = nodeIndex1;
+  while(bAig_NonInvertedEdge(canonical(nodeIndex)) != bAig_NonInvertedEdge(nodeIndex1)) {
+    if(bAig_IsInverted(nodeIndex))
+      nodeIndex = bAig_Not(canonical(nodeIndex));
+    else
+      nodeIndex = canonical(nodeIndex);
+  }
+
+  for(i=0; i<array_n(nodeArray); i++) {
+    tnodeIndex = array_fetch(bAigEdge_t, nodeArray, i);
+    if(bAig_IsInverted(nodeIndex))
+      canonical(nodeIndex) = bAig_Not(tnodeIndex);
+    else 
+      canonical(nodeIndex) = tnodeIndex;
+
+    if(bAig_IsInverted(nodeIndex))
+      nodeIndex = bAig_Not(canonical(nodeIndex));
+    else
+      nodeIndex = canonical(nodeIndex);
+  }
+
+  if(bAig_IsInverted(nodeIndex))	{
+    canonical(nodeIndex) = bAig_Not(nodeIndex1);
+  }
+  else {
+    canonical(nodeIndex) = nodeIndex1;
+  }
+  array_free(nodeArray);
+
+  nodeArray = array_alloc(bAigEdge_t, 0);
+  bAigEdgeForEachFanout(manager, nodeIndex2, cur, ii, iii, pfan) {
+    cur = cur >> 1;
+    cur = bAig_NonInvertedEdge(cur);
+    array_insert_last(bAigEdge_t, nodeArray, cur);
+  }
+
+  for(i=0; i<array_n(nodeArray); i++) {
+    outIndex = array_fetch(bAigEdge_t, nodeArray, i);
+    leftIndex = leftChild(outIndex);
+    rightIndex = rightChild(outIndex);
+
+    HashTableDelete(manager, outIndex);
+
+    newNodeIndex = bAig_And(manager, leftIndex, rightIndex);
+
+    bAig_Merge(manager, newNodeIndex, outIndex);
+
+  }
+  array_free(nodeArray);
+
+  bddArray = manager->bddArray;
+  id1 = bAigNodeID(nodeIndex1);
+  id2 = bAigNodeID(nodeIndex2);
+  if(bddArray[id1] == 0 && bddArray[id2]){ 
+    if(bAig_IsInverted(nodeIndex2)) {
+      if(bAig_IsInverted(nodeIndex1)) {
+        bddArray[id1] = bdd_dup(bddArray[id2]);
+      }
+      else {
+        bddArray[id1] = bdd_not(bddArray[id2]);
+      }
+    }
+    else {
+      if(bAig_IsInverted(nodeIndex1)) {
+        bddArray[id1] = bdd_not(bddArray[id2]);
+      }
+      else {
+        bddArray[id1] = bdd_dup(bddArray[id2]);
+      }
+    }
+  }
+  return(nodeIndex1);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Print node information.]
+
+  Description [Print node information.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void
+bAig_PrintNode(
+  bAig_Manager_t *manager,
+  bAigEdge_t i)
+{
+  int j, size;
+  long cur, *pfan;
+
+  fprintf(vis_stdout, "nodeIndex : %ld (%ld)\n", i, bAigNodeID(i)); 
+  fprintf(vis_stdout, "child     : %ld%c, %ld%c\n", 
+	  bAig_NonInvertedEdge(leftChild(i)), bAig_IsInverted(leftChild(i)) ? '\'' : ' ', 
+	  bAig_NonInvertedEdge(rightChild(i)), bAig_IsInverted(rightChild(i)) ? '\'' : ' ');
+  fprintf(vis_stdout, "canonical : %s (%ld)\n", 
+	  bAigGetPassFlag(manager, i) ? "pass" : "true", bAig_GetCanonical(manager, i));
+  fprintf(vis_stdout, "refCount  : %ld\n", nFanout(i));
+  fprintf(vis_stdout, "          : ");
+  size = nFanout(i);
+  for(j=0, pfan = (bAigEdge_t *)fanout(i); j<size; j++) {
+    cur = pfan[j];
+    cur = cur >> 1;
+    fprintf(vis_stdout, " %ld", cur);
+  }
+  fprintf(vis_stdout, "\n");
+
+  fprintf(vis_stdout, "next      : %ld\n", next(i));
+  fflush(vis_stdout);
+}
+   
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the Logical AND of two nodes.]
+
+  Description [This function performs the Logical AND of two nodes.  The inputs
+               are the indices of the two nodes.  This function returns the index 
+               of the result node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bAigEdge_t
+bAig_And(
+   bAig_Manager_t *manager,
+   bAigEdge_t nodeIndex1,
+   bAigEdge_t nodeIndex2)
+{
+
+  bAigEdge_t newNodeIndex;
+
+  nodeIndex1 = bAig_GetCanonical(manager, nodeIndex1);
+  nodeIndex2 = bAig_GetCanonical(manager, nodeIndex2);
+
+  newNodeIndex = nodeIndex1;     /* The left node has the smallest index */
+  if (bAig_NonInvertedEdge(nodeIndex1) > bAig_NonInvertedEdge(nodeIndex2)){
+    nodeIndex1 = nodeIndex2;
+    nodeIndex2 = newNodeIndex;
+  }
+
+  if ( nodeIndex2 == bAig_Zero ) {
+    return bAig_Zero;
+  }
+  if ( nodeIndex1 == bAig_Zero ) {
+    return bAig_Zero;
+  }
+  if ( nodeIndex2 == bAig_One ) {
+    return nodeIndex1;
+  }
+  if ( nodeIndex1 == bAig_One ) {
+    return nodeIndex2;
+  }
+  if ( nodeIndex1 == nodeIndex2 ) {
+    return nodeIndex1;
+  }
+  if ( nodeIndex1 == bAig_Not(nodeIndex2) ) {
+    return bAig_Zero;
+  }
+
+  /* Look for the new node in the Hash table */
+  newNodeIndex = HashTableLookup(manager, nodeIndex1, nodeIndex2);
+
+  if (newNodeIndex == bAig_NULL){ 
+    if(bAigIsVar(manager, nodeIndex1) && bAigIsVar(manager, nodeIndex2))
+      newNodeIndex = bAig_And2(manager, nodeIndex1, nodeIndex2);
+    else if(bAigIsVar(manager, nodeIndex1)) 
+      newNodeIndex = bAig_And3(manager, nodeIndex1, nodeIndex2);
+    else if(bAigIsVar(manager, nodeIndex2)) 
+      newNodeIndex = bAig_And3(manager, nodeIndex2, nodeIndex1);
+    else {
+      newNodeIndex = bAig_And4(manager, nodeIndex1, nodeIndex2);
+    }
+  }
+    
+  return newNodeIndex;
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Structural hashing for and2]
+
+  Description [Structural hashing for and2]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bAigEdge_t
+bAig_And2(
+   bAig_Manager_t *manager,
+   bAigEdge_t nodeIndex1,
+   bAigEdge_t nodeIndex2)
+{
+  bAigEdge_t newNodeIndex;
+
+  nodeIndex1 = bAig_GetCanonical(manager, nodeIndex1);
+  nodeIndex2 = bAig_GetCanonical(manager, nodeIndex2);
+
+  newNodeIndex = nodeIndex1;     /* The left node has the smallest index */
+  if (bAig_NonInvertedEdge(nodeIndex1) > bAig_NonInvertedEdge(nodeIndex2)){
+    nodeIndex1 = nodeIndex2;
+    nodeIndex2 = newNodeIndex;
+  }
+  if ( nodeIndex2 == bAig_Zero ) {
+    return bAig_Zero;
+  }
+  if ( nodeIndex1 == bAig_Zero ) {
+    return bAig_Zero;
+  }
+  if ( nodeIndex2 == bAig_One ) {
+    return nodeIndex1;
+  }
+  if ( nodeIndex1 == bAig_One ) {
+    return nodeIndex2;
+  }
+  if ( nodeIndex1 == nodeIndex2 ) {
+    return nodeIndex1;
+  }
+  if ( nodeIndex1 == bAig_Not(nodeIndex2) ) {
+    return bAig_Zero;
+  }
+  newNodeIndex = HashTableLookup(manager, nodeIndex1, nodeIndex2);
+
+  if (newNodeIndex == bAig_NULL){ 
+    newNodeIndex = bAigCreateAndNode(manager, nodeIndex1, nodeIndex2) ;
+
+    HashTableAdd(manager, newNodeIndex, nodeIndex1, nodeIndex2);
+    connectOutput(manager, nodeIndex1, newNodeIndex, 0);
+    connectOutput(manager, nodeIndex2, newNodeIndex, 1);
+
+#if 0
+#ifdef LEARNING_
+    tNodeIndex = HashTableLookup(manager, bAig_Not(nodeIndex1), nodeIndex2);
+    if(tNodeIndex) bAig_Learn(manager, nodeIndex1, nodeIndex2);
+
+    tNodeIndex = HashTableLookup(manager, nodeIndex1, bAig_Not(nodeIndex2));
+    if(tNodeIndex) bAig_Learn(manager, nodeIndex2, nodeIndex1);
+#endif
+#endif
+  }
+  return newNodeIndex;
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the Logical OR of two nodes.]
+
+  Description [This function performs the Logical OR of two nodes.  The inputs
+               are the indices of the two nodes.  This function returns the index 
+               of the result node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bAigEdge_t
+bAig_Or(
+   bAig_Manager_t *manager,
+   bAigEdge_t nodeIndex1,
+   bAigEdge_t nodeIndex2)
+{
+  return ( bAig_Not(bAig_And(manager,  bAig_Not(nodeIndex1),  bAig_Not(nodeIndex2))));
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the Logical XOR of two nodes.]
+
+  Description [This function performs the Logical XOR of two nodes.  The inputs
+               are the indices of the two nodes.  This function returns the index 
+               of the result node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bAigEdge_t
+bAig_Xor(
+   bAig_Manager_t *manager,
+   bAigEdge_t nodeIndex1,
+   bAigEdge_t nodeIndex2)
+{
+ return bAig_Or(manager,
+	    bAig_And(manager, nodeIndex1, bAig_Not(nodeIndex2)),
+	    bAig_And(manager, bAig_Not(nodeIndex1),nodeIndex2)
+	);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the Logical Equal ( <--> XNOR) of two nodes.]
+
+  Description [This function performs the Logical XNOR of two nodes.  The inputs
+               are the indices of the two nodes.  This function returns the index 
+               of the result node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bAigEdge_t
+bAig_Eq(
+   bAig_Manager_t *manager,
+   bAigEdge_t nodeIndex1,
+   bAigEdge_t nodeIndex2)
+{
+ return bAig_Not(
+	    bAig_Xor(manager, nodeIndex1, nodeIndex2)
+	    );
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the Logical Then (--> Implies) of two nodes.]
+
+  Description [This function performs the Logical Implies of two nodes.  The inputs
+               are the indices of the two nodes.  This function returns the index 
+               of the result node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bAigEdge_t
+bAig_Then(
+   bAig_Manager_t *manager,
+   bAigEdge_t nodeIndex1,
+   bAigEdge_t nodeIndex2)
+{
+ return bAig_Or(manager,
+	        bAig_Not(nodeIndex1),
+                nodeIndex2);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [create new node] 
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bAigEdge_t
+bAig_CreateNode(
+   bAig_Manager_t  *manager,
+   bAigEdge_t nodeIndex1,
+   bAigEdge_t nodeIndex2)
+{
+  
+  bAigEdge_t newNode = manager->nodesArraySize;
+
+  if (manager->nodesArraySize >= manager->maxNodesArraySize ){
+    manager->maxNodesArraySize = 2* manager->maxNodesArraySize;
+    manager->NodesArray = REALLOC(bAigEdge_t, manager->NodesArray, manager->maxNodesArraySize);
+    manager->nameList   = REALLOC(char *,     manager->nameList  , manager->maxNodesArraySize/bAigNodeSize);
+    manager->bddIdArray = REALLOC(int ,     manager->bddIdArray  , manager->maxNodesArraySize/bAigNodeSize);
+    manager->bddArray   = REALLOC(bdd_t *,     manager->bddArray  , manager->maxNodesArraySize/bAigNodeSize);
+  }
+  manager->NodesArray[bAig_NonInvertedEdge(newNode)+bAigRight] = nodeIndex2;
+  manager->NodesArray[bAig_NonInvertedEdge(newNode)+bAigLeft]  = nodeIndex1;
+ 
+  next(newNode)     = bAig_NULL;
+  fanout(newNode) = 0;
+  canonical(newNode) = newNode;
+  flags(newNode) = 0;
+  nFanout(newNode) = 0;
+  manager->bddIdArray[bAigNodeID(newNode)] = -1; 
+  manager->bddArray[bAigNodeID(newNode)] = 0; 
+
+  manager->nodesArraySize +=bAigNodeSize;
+  
+  //Bing: for interpolation
+  aig_value(newNode) = 2;
+  manager->nameList[bAigNodeID(newNode)] = 0;
+  manager->NodesArray[newNode+bAigClass] = manager->class_;
+  
+  return(newNode);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Return the bAig node given its name.]
+
+  SideEffects []
+
+******************************************************************************/
+bAigEdge_t
+bAig_FindNodeByName(
+  bAig_Manager_t *manager,
+  nameType_t     *name)
+{
+   
+  bAigEdge_t node;
+
+  if (!st_lookup(manager->SymbolTable, name, &node)){
+    node = bAig_NULL;
+  }
+
+  return bAig_GetCanonical(manager, node);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [create var node ] 
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bAigEdge_t
+bAig_CreateVarNode(
+   bAig_Manager_t  *manager,
+   nameType_t	   *name)
+{
+   
+  bAigEdge_t varIndex;
+
+
+  if (!st_lookup(manager->SymbolTable, name, &varIndex)){
+    varIndex = bAig_CreateNode(manager, bAig_NULL, bAig_NULL);
+    if (varIndex == bAig_NULL){
+      return (varIndex);
+    } 
+    /* Insert the varaible in the Symbol Table */
+    st_insert(manager->SymbolTable, name, (char*) (long) varIndex);
+    manager->nameList[bAigNodeID(varIndex)] = name; 
+    return(varIndex);
+  }
+  else {
+    return (varIndex);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return True if this node is Variable node]
+
+  SideEffects []
+
+******************************************************************************/
+int 
+bAig_isVarNode(
+   bAig_Manager_t *manager,
+   bAigEdge_t      node)
+{
+  if((rightChild(node) == bAig_NULL) && (leftChild(node) == bAig_NULL)) {
+    return 1;
+  }
+  return 0;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis [Build the binary AND/INVERTER graph for a given bdd function]
+
+  SideEffects [Build the binary AND/INVERTER graph for a given bdd function.
+               We assume that the return bdd nodes from the foreach_bdd_node are
+	       in the order from childeren to parent. i.e all the childeren
+	       nodes are returned before the parent node.]
+
+  SideEffects []
+
+  SeeAlso     []
+  
+******************************************************************************/
+bAigEdge_t
+bAig_bddTobAig(
+   bAig_Manager_t *bAigManager,
+   bdd_t          *fn)
+{
+  bdd_gen     *gen;
+  bdd_node    *node, *thenNode, *elseNode, *funcNode;
+  bdd_manager *bddManager = bdd_get_manager(fn);
+  /*
+    Used to read the variable name of a bdd node.
+  */
+  array_t     *mvar_list  = mdd_ret_mvar_list(bddManager);
+  array_t     *bvar_list  = mdd_ret_bvar_list(bddManager);
+  bvar_type   bv;
+  mvar_type   mv;
+  
+  bdd_node    *one        = bdd_read_one(bddManager);  
+  int         is_complemented;
+  int         flag;  
+  bAigEdge_t  var, left, right, result;
+  
+  char      name[100];
+  st_table  *bddTObaigTable;
+  
+  if (fn == NULL){
+    return bAig_NULL;
+  }
+  funcNode = bdd_get_node(fn, &is_complemented);
+  if (bdd_is_constant(funcNode)){
+    return (is_complemented?bAig_Zero:bAig_One);
+  }
+  bddTObaigTable = st_init_table(st_numcmp, st_numhash);
+  st_insert(bddTObaigTable, (char *) (long) bdd_regular(one),  (char *) bAig_One);
+
+  foreach_bdd_node(fn, gen, node){
+    int nodeIndex = bdd_node_read_index(node);
+    int index, rtnNodeIndex;
+
+    if (bdd_is_constant(node)){
+      continue;
+    }
+
+    bv = array_fetch(bvar_type, bvar_list, nodeIndex);
+    /*
+      get the multi-valued varaible.
+     */
+    mv = array_fetch(mvar_type, mvar_list, bv.mvar_id);
+    arrayForEachItem(int, mv.bvars, index, rtnNodeIndex) {
+      if (nodeIndex == rtnNodeIndex){
+	break;
+      }
+    }
+    assert(index < mv.encode_length);
+    /*
+    printf("Name of bdd node %s %d\n", mv.name, index);
+    */
+    sprintf(name, "%s_%d", mv.name, index);
+    /*
+      Create or Retrieve the bAigEdge_t  w.r.t. 'name'
+    */
+    var  = bAig_CreateVarNode(bAigManager, util_strsav(name));
+
+    thenNode  = bdd_bdd_T(node);
+    flag = st_lookup(bddTObaigTable, (char *) (long) bdd_regular(thenNode),
+		     &left);
+    assert(flag);
+      
+    elseNode  = bdd_bdd_E(node);
+    flag = st_lookup(bddTObaigTable, (char *) (long) bdd_regular(elseNode),
+		     &right);
+    assert(flag);
+    /*
+     test if the elseNode is complemented arc?
+    */
+    if (bdd_is_complement(elseNode)){
+      right = bAig_Not(right);
+    }
+    if (right ==  bAig_Zero){        /* result = var*then */
+      result =  bAig_And(bAigManager, var, left);
+    } else if (right ==  bAig_One){        /* result = then + not(var) */
+      result =  bAig_Or(bAigManager, left, bAig_Not(var));
+    } else if (left ==  bAig_One) { /* result = var + else */
+      result =  bAig_Or(bAigManager, var, right);      
+    } else {                        /* result = var * then + not(var)*else */
+      result =  bAig_Or(bAigManager, bAig_And(bAigManager, var, left),
+			bAig_And(bAigManager, bAig_Not(var), right));
+    }
+    st_insert(bddTObaigTable, (char *) (long) bdd_regular(node),
+	      (char *) (long) result);
+  }
+  flag = st_lookup(bddTObaigTable, (char *) (long) bdd_regular(funcNode),
+		   &result);  
+  assert(flag);
+  st_free_table(bddTObaigTable);
+
+  if (is_complemented){
+    return bAig_Not(result);
+  } else {
+    return result;
+  }
+} /* end of bAig_bddtobAig() */
+
+
+/**Function********************************************************************
+
+  Synopsis [Print dot file for AIG nodes]
+
+  SideEffects []
+
+******************************************************************************/
+int
+bAig_PrintDot(
+  FILE *fp,
+  bAig_Manager_t *manager)
+{
+  long i;
+
+  /*
+   * Write out the header for the output file.
+   */
+  (void) fprintf(fp, "digraph \"AndInv\" {\n  rotate=90;\n");
+  (void) fprintf(fp, "  margin=0.5;\n  label=\"AndInv\";\n");
+  (void) fprintf(fp, "  size=\"10,7.5\";\n  ratio=\"fill\";\n");
+ 
+  
+  for (i=bAigFirstNodeIndex ; i< manager->nodesArraySize ; i+=bAigNodeSize){
+    (void) fprintf(fp,"Node%ld  [label=\"%s \"];\n",i,bAig_NodeReadName(manager, i));
+  }
+  for (i=bAigFirstNodeIndex ; i< manager->nodesArraySize ; i+=bAigNodeSize){
+    if (rightChild(i) != bAig_NULL){
+      if (bAig_IsInverted(rightChild(i))){
+        (void) fprintf(fp,"Node%ld -> Node%ld [color = red];\n",bAig_NonInvertedEdge(rightChild(i)), i);
+      }
+      else{
+        (void) fprintf(fp,"Node%ld -> Node%ld;\n",bAig_NonInvertedEdge(rightChild(i)), i);
+      }
+      if (bAig_IsInverted(leftChild(i))){
+        (void) fprintf(fp,"Node%ld -> Node%ld [color = red];\n",bAig_NonInvertedEdge(leftChild(i)), i);
+      }
+      else{
+        (void) fprintf(fp,"Node%ld -> Node%ld;\n",bAig_NonInvertedEdge(leftChild(i)), i);
+      }
+    }/* if */ 
+  }/*for */
+
+  (void) fprintf(fp, "}\n");
+
+  return 1;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Set pass flag for node] 
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void 
+bAigSetPassFlag(
+    bAig_Manager_t  *manager,
+    bAigEdge_t node)
+{
+
+   flags(node) |= CanonicalBitMask;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Reset pass flag for node] 
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void 
+bAigResetPassFlag(
+    bAig_Manager_t  *manager,
+    bAigEdge_t node)
+{
+
+   flags(node) &= ResetCanonicalBitMask;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Get pass flag for node] 
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+bAigGetPassFlag(
+    bAig_Manager_t  *manager,
+    bAigEdge_t node)
+   
+{
+
+  return((flags(node) & CanonicalBitMask) != 0);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Create AND node and assign name to it ] 
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bAigEdge_t
+bAigCreateAndNode(
+   bAig_Manager_t  *manager,
+   bAigEdge_t node1,
+   bAigEdge_t node2)
+{
+   
+  bAigEdge_t varIndex;
+  char       *name = NIL(char);
+  char       *node1Str = util_inttostr(node1);
+  char       *node2Str = util_inttostr(node2);
+
+  name = util_strcat4("Nd", node1Str,"_", node2Str);
+  while (st_lookup(manager->SymbolTable, name, &varIndex)){
+    printf("Find redundant node at %ld %ld\n", node1, node2);
+    name = util_strcat3(name, node1Str, node2Str);
+  }
+  FREE(node1Str);
+  FREE(node2Str);
+  varIndex = bAig_CreateNode(manager, node1, node2);
+  if (varIndex == bAig_NULL){
+    FREE(name);
+    return (varIndex);
+  } 
+  /* Insert the varaible in the Symbol Table */
+  st_insert(manager->SymbolTable, name, (char*) (long) varIndex);
+  manager->nameList[bAigNodeID(varIndex)] = name; 
+
+  return(varIndex);
+
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Connect fanin fanout of two AIG nodes]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+connectOutput(
+   bAig_Manager_t *manager,
+   bAigEdge_t from,
+   bAigEdge_t to,
+   int inputIndex)
+{
+  bAigEdge_t *pfan;
+  int nfan;
+
+  to = bAig_NonInvertedEdge(to);
+  pfan = (bAigEdge_t *)fanout(from);
+  nfan = nFanout(from);
+  if(nfan == 0) pfan = ALLOC(bAigEdge_t, 2);
+  else          pfan = REALLOC(bAigEdge_t, pfan, nfan+2);
+  to += bAig_IsInverted(from);
+  to = to << 1;
+  to += inputIndex;
+  pfan[nfan++] = to;
+  pfan[nfan] = 0;
+  fanout(from) = (long)pfan;
+  nFanout(from) = nfan;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [disconnect fanin fanout of two AIG nodes]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+static void
+unconnectOutput(
+   bAig_Manager_t *manager,
+   bAigEdge_t from,
+   bAigEdge_t to)
+{
+   bAigEdge_t cur, *pfan, *newfan;
+   int i, nfan;
+
+  from = bAig_NonInvertedEdge(from);
+  to = bAig_NonInvertedEdge(to);
+
+  pfan = (bAigEdge_t *)fanout(from);
+  nfan = nFanout(from);
+  newfan = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*(nfan));
+  for(i=0; i<nfan; i++) {
+    cur = pfan[i];
+    cur = cur >> 1;
+    cur = bAig_NonInvertedEdge(cur);
+    if(cur == to) {
+      memcpy(newfan, pfan, sizeof(bAigEdge_t)*i);
+      memcpy(&(newfan[i]), &(pfan[i+1]), sizeof(bAigEdge_t)*(nfan-i-1));
+      newfan[nfan-1] = 0;
+      fanout(from) = (int)newfan;
+      free(pfan);
+      nFanout(from) = nfan-1;
+      break;
+    }
+  }
+}
+******************************************************************************/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Look for the node in the Hash Table.]
+
+  Description [.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static bAigEdge_t
+HashTableLookup(
+  bAig_Manager_t *manager,  
+  bAigEdge_t  node1,
+  bAigEdge_t  node2)
+{
+  bAigEdge_t key = HashTableFunction(node1, node2);
+  bAigEdge_t node;
+  
+  node = manager->HashTable[key];
+  if  (node == bAig_NULL) {
+    return bAig_NULL;
+  }
+  else{
+    while ( (rightChild(bAig_NonInvertedEdge(node)) != node2) ||
+	    (leftChild(bAig_NonInvertedEdge(node))  != node1)) {
+  
+      if (next(bAig_NonInvertedEdge(node)) == bAig_NULL){
+	return(bAig_NULL); 
+      }
+      node = next(bAig_NonInvertedEdge(node)); /* Get the next Node */
+    } /* While loop */ 
+    return(node);
+
+  } /* If Then Else */
+    
+} /* End of HashTableLookup() */
+
+/**Function********************************************************************
+
+  Synopsis    [Add a node in the Hash Table.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+HashTableAdd(
+  bAig_Manager_t   *manager,  
+  bAigEdge_t  nodeIndexParent,
+  bAigEdge_t  nodeIndex1,
+  bAigEdge_t  nodeIndex2)
+{
+  bAigEdge_t key = HashTableFunction(nodeIndex1, nodeIndex2);
+  bAigEdge_t nodeIndex;
+  bAigEdge_t node;
+                                                
+  nodeIndex = manager->HashTable[key];
+  if  (nodeIndex == bAig_NULL) {
+    manager->HashTable[key] = nodeIndexParent;
+    return TRUE;
+  }
+  else{
+    node = nodeIndex;
+    nodeIndex = next(bAig_NonInvertedEdge(nodeIndex));  /* Get the Node */
+    while (nodeIndex != bAig_NULL) {
+      node = nodeIndex;
+      nodeIndex = next(bAig_NonInvertedEdge(nodeIndex));
+    }
+    next(bAig_NonInvertedEdge(node)) = nodeIndexParent;
+    return TRUE;
+  }
+    
+} /* End of HashTableAdd() */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Hash table delete]
+
+  Description [Hash table delete]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+HashTableDelete(
+  bAig_Manager_t   *manager,  
+  bAigEdge_t  node)
+{
+  bAigEdge_t key = HashTableFunction(leftChild(node), rightChild(node));
+  bAigEdge_t nodeIndex;
+                                                
+  nodeIndex = manager->HashTable[key];
+  if (nodeIndex == node) {
+    manager->HashTable[key] = next(node);
+    return TRUE;
+  }
+  else{
+    while(nodeIndex && next(bAig_NonInvertedEdge(nodeIndex)) != node)
+      nodeIndex = next(bAig_NonInvertedEdge(nodeIndex));
+
+    next(bAig_NonInvertedEdge(nodeIndex)) = 
+	next(bAig_NonInvertedEdge(next(bAig_NonInvertedEdge(nodeIndex))));
+    return TRUE;
+  }
+    
+} /* End of HashTableAdd() */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Structural hasing for and4]
+
+  Description [Structural hasing for and4]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+bAigEdge_t
+bAig_And4(
+           bAig_Manager_t *manager,
+           bAigEdge_t l,
+           bAigEdge_t r)
+{
+  int caseIndex, caseSig;
+  bAigEdge_t ll, lr, rl, rr;
+  bAigEdge_t t1, t2;
+
+  ll = leftChild(l);
+  lr = rightChild(l);
+  rl = leftChild(r);
+  rr = rightChild(r);
+
+  if(bAigCompareNode(l, rl) ||
+     bAigCompareNode(l, rr)) {
+    return(bAig_And3(manager, l, r));
+  }
+  else if(bAigCompareNode(r, ll) ||
+     bAigCompareNode(r, lr)) {
+    return(bAig_And3(manager, r, l));
+  }
+
+  if(ll > lr+1) bAigSwap(ll, lr);
+  if(rl > rr+1) bAigSwap(rl, rr);
+
+  caseIndex = 0; /* (a b)(c d) */
+  if(bAigCompareNode(ll, rl)) {
+    if(bAigCompareNode(lr, rr)) {
+      caseIndex = 4; /* (a b) (a b) */
+    }
+    else {
+      caseIndex = 1; /* (a b) (a c) */
+      if(lr > rr+1) {
+        bAigSwap(ll, rl);
+        bAigSwap(lr, rr); 
+        bAigSwap(l, r); 
+      }
+    }
+  }
+  else if(bAigCompareNode(lr, rl)) {
+    caseIndex = 2; /* (b a)(a c) */
+  }
+  else if(bAigCompareNode(lr, rr)) {
+    caseIndex = 3; /* (b a)(c a) */
+    if(ll > rl+1) {
+      bAigSwap(ll, rl);
+      bAigSwap(lr, rr); 
+      bAigSwap(l, r); 
+    }
+  }
+  else if(bAigCompareNode(ll, rr)) {
+    /* (a b)(c a)  */
+    bAigSwap(ll, rl);
+    bAigSwap(lr, rr); 
+    bAigSwap(l, r); 
+    caseIndex = 2; /* (c a )(a b) because of c < b */
+  }
+
+  caseSig = 0;
+  if(bAig_IsInverted(ll)) caseSig += 32;
+  if(bAig_IsInverted(lr)) caseSig += 16;
+  if(bAig_IsInverted(l))  caseSig += 8;
+  if(bAig_IsInverted(rl)) caseSig += 4;
+  if(bAig_IsInverted(rr)) caseSig += 2;
+  if(bAig_IsInverted(r))  caseSig += 1;
+  /**
+  fprintf(vis_stdout, "Index: %d Sig: %2d  (%5d%c %5d%c)%c (%5d%c %5d%c)%c (%5d, %5d)\n", 
+	  caseIndex, caseSig, 
+	  bAig_NonInvertedEdge(ll), bAig_IsInverted(ll) ? '\'' : ' ',
+	  bAig_NonInvertedEdge(lr), bAig_IsInverted(lr) ? '\'' : ' ',
+	  bAig_IsInverted(l) ? '\'' : ' ',
+	  bAig_NonInvertedEdge(rl), bAig_IsInverted(rl) ? '\'' : ' ',
+	  bAig_NonInvertedEdge(rr), bAig_IsInverted(rr) ? '\'' : ' ',
+	  bAig_IsInverted(r) ? '\'' : ' ',
+	  bAig_NonInvertedEdge(l), bAig_NonInvertedEdge(r)
+	   );
+	   **/
+  if(caseIndex == 0) {
+    return(bAig_And2(manager, l, r));
+  }
+  else if(caseIndex == 1) {
+    switch(caseSig) {
+	case 19 :
+	case 17 :
+	case 3 :
+	case 1 :
+	case 55 :
+	case 53 :
+	case 39 :
+	case 37 :
+      t1 = bAig_And(manager, lr, bAig_Not(rr));
+      t2 = bAig_And(manager, ll, t1);
+      return(t2);
+	case 18 :
+	case 16 :
+	case 2 :
+	case 0 :
+	case 54 :
+	case 52 :
+	case 38 :
+	case 36 :
+      t1 = bAig_And(manager, lr, rr);
+      t2 = bAig_And(manager, ll, t1);
+      return(t2);
+	case 26 :
+	case 24 :
+	case 10 :
+	case 8 :
+	case 62 :
+	case 60 :
+	case 46 :
+	case 44 :
+      t1 = bAig_And(manager, bAig_Not(lr), rr);
+      t2 = bAig_And(manager, ll, t1);
+      return(t2);
+	case 61 :
+	case 27 :
+	case 25 :
+	case 11 :
+	case 63 :
+	case 47 :
+	case 9 :
+	case 45 :
+      t1 = bAig_And(manager, bAig_Not(lr), bAig_Not(rr));
+      t2 = bAig_Or(manager, bAig_Not(ll), t1);
+      return(t2);
+	case 23 :
+	case 21 :
+	case 7 :
+	case 5 :
+	case 51 :
+	case 49 :
+	case 35 :
+	case 33 :
+      return(l);
+	case 30 :
+	case 28 :
+	case 14 :
+	case 12 :
+	case 58 :
+	case 56 :
+	case 42 :
+	case 40 :
+      return(r);
+	case 22 :
+	case 20 :
+	case 6 :
+	case 4 :
+	case 50 :
+	case 48 :
+	case 34 :
+	case 32 :
+      return(bAig_Zero);
+	case 31 :
+	case 29 :
+	case 15 :
+	case 13 :
+	case 59 :
+	case 57 :
+	case 43 :
+	case 41 :
+      t1 = bAig_And2(manager, l, r);
+      return(t1);
+    }
+  }
+  else if(caseIndex == 2) {
+    switch(caseSig) {
+	case 35 :
+	case 33 :
+	case 3 :
+	case 1 :
+	case 55 :
+	case 53 :
+	case 23 :
+	case 21 :
+      t1 = bAig_And(manager, lr, bAig_Not(rr));
+      t2 = bAig_And(manager, ll, t1);
+      return(t2);
+	case 34 :
+	case 32 :
+	case 2 :
+	case 0 :
+	case 54 :
+	case 52 :
+	case 22 :
+	case 20 :
+      t1 = bAig_And(manager, lr, rr);
+      t2 = bAig_And(manager, ll, t1);
+      return(t2);
+	case 42 :
+	case 40 :
+	case 10 :
+	case 8 :
+	case 62 :
+	case 60 :
+	case 30 :
+	case 28 :
+      t1 = bAig_And(manager, lr, rr);
+      t2 = bAig_And(manager, bAig_Not(ll), t1);
+      return(t2);
+	case 43 :
+	case 41 :
+	case 11 :
+	case 9 :
+	case 63 :
+	case 61 :
+	case 31 :
+	case 29 :
+      t1 = bAig_And(manager, bAig_Not(ll), bAig_Not(rr));
+      t2 = bAig_Or(manager, bAig_Not(lr), t1);
+      return(t2);
+	case 39 :
+	case 37 :
+	case 7 :
+	case 5 :
+	case 51 :
+	case 49 :
+	case 19 :
+	case 17 :
+      return(l);
+	case 46 :
+	case 44 :
+	case 14 :
+	case 12 :
+	case 58 :
+	case 56 :
+	case 26 :
+	case 24 :
+      return(r);
+	case 38 :
+	case 36 :
+	case 6 :
+	case 4 :
+	case 50 :
+	case 48 :
+	case 18 :
+	case 16 :
+      return(bAig_Zero);
+	case 45 :
+	case 15 :
+	case 13 :
+	case 59 :
+	case 57 :
+	case 47 :
+	case 27 :
+	case 25 :
+      t1 = bAig_And2(manager, l, r);
+      return(t1);
+    }
+  }
+  else if(caseIndex == 3) {
+    switch(caseSig) {
+	case 37 :
+	case 33 :
+	case 5 :
+	case 1 :
+	case 55 :
+	case 51 :
+	case 23 :
+	case 19 :
+      t1 = bAig_And(manager, bAig_Not(rl), lr);
+      t2 = bAig_And(manager, ll, t1);
+      return(t2);
+	case 36 :
+	case 32 :
+	case 4 :
+	case 0 :
+	case 54 :
+	case 50 :
+	case 22 :
+	case 18 :
+      t1 = bAig_And(manager, rl, lr);
+      t2 = bAig_And(manager, ll, t1);
+      return(t2);
+	case 44 :
+	case 40 :
+	case 12 :
+	case 8 :
+	case 62 :
+	case 58 :
+	case 30 :
+	case 26 :
+      t1 = bAig_And(manager, rl, lr);
+      t2 = bAig_And(manager, bAig_Not(ll), t1);
+      return(t2);
+	case 45 :
+	case 41 :
+	case 13 :
+	case 9 :
+	case 63 :
+	case 59 :
+	case 31 :
+	case 27 :
+      t1 = bAig_And(manager, bAig_Not(ll), bAig_Not(rl));
+      t2 = bAig_Or(manager, bAig_Not(lr), t1);
+      return(t2);
+	case 39 :
+	case 35 :
+	case 7 :
+	case 3 :
+	case 53 :
+	case 49 :
+	case 21 :
+	case 17 :
+      return(l);
+	case 46 :
+	case 42 :
+	case 14 :
+	case 10 :
+	case 60 :
+	case 56 :
+	case 28 :
+	case 24 :
+      return(r);
+	case 38 :
+	case 34 :
+	case 6 :
+	case 2 :
+	case 52 :
+	case 48 :
+	case 20 :
+	case 16 :
+      return(bAig_Zero);
+	case 47 :
+	case 43 :
+	case 15 :
+	case 11 :
+	case 61 :
+	case 57 :
+	case 29 :
+	case 25 :
+      t1 = bAig_And2(manager, l, r);
+      return(t1);
+    }
+  }
+  else if(caseIndex == 4) {
+    switch(caseSig) {
+	case 22 :
+	case 20 :
+	case 6 :
+	case 4 :
+	case 50 :
+	case 48 :
+	case 34 :
+	case 32 :
+	case 2 :
+	case 16 :
+	case 52 :
+	case 1 :
+	case 8 :
+	case 19 :
+	case 26 :
+	case 37 :
+	case 44 :
+	case 38 :
+	case 55 :
+	case 62 :
+      return(bAig_Zero);
+	case 0 :
+	case 18 :
+	case 36 :
+	case 54 :
+	case 9 :
+	case 27 :
+	case 45 :
+	case 63 :
+	case 5 :
+	case 23 :
+	case 33 :
+	case 51 :
+	case 3 :
+	case 17 :
+	case 49 :
+	case 7 :
+	case 35 :
+	case 21 :
+	case 39 :
+	case 53 :
+      return(l);
+	case 40 :
+	case 58 :
+	case 12 :
+	case 30 :
+	case 24 :
+	case 10 :
+	case 14 :
+	case 56 :
+	case 28 :
+	case 42 :
+	case 60 :
+	case 46 :
+      return(r);
+	case 11 :
+	case 47 :
+	case 25 :
+	case 61 :
+      return(bAig_Not(ll));
+	case 41 :
+	case 59 :
+	case 13 :
+	case 31 :
+      return(bAig_Not(lr));
+	case 15 :
+      t1 = bAig_And(manager, ll, bAig_Not(lr));
+      t2 = bAig_And(manager, bAig_Not(ll), lr);
+      return(bAig_Not(bAig_And2(manager, bAig_Not(t1), bAig_Not(t2))));
+	case 57 :
+      t1 = bAig_And(manager, rl, bAig_Not(rr));
+      t2 = bAig_And(manager, bAig_Not(rl), rr);
+      return(bAig_Not(bAig_And2(manager, bAig_Not(t1), bAig_Not(t2))));
+	case 29 :
+      t1 = bAig_And(manager, ll, lr);
+      t2 = bAig_And(manager, bAig_Not(ll), bAig_Not(lr));
+      return((bAig_And2(manager, bAig_Not(t1), bAig_Not(t2))));
+	case 43 :
+      t1 = bAig_And(manager, rl, rr);
+      t2 = bAig_And(manager, bAig_Not(rl), bAig_Not(rr));
+      return((bAig_And2(manager, bAig_Not(t1), bAig_Not(t2))));
+    }
+  }
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Structural hasing for and3]
+
+  Description [Structural hasing for and3]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bAigEdge_t
+bAig_And3(
+           bAig_Manager_t *manager,
+           bAigEdge_t l,
+           bAigEdge_t r)
+{
+  int caseIndex, caseSig;
+  bAigEdge_t rl, rr;
+
+  rl = leftChild(r);
+  rr = rightChild(r);
+
+  caseIndex = 0; /* (a)(b c) */
+  if(bAigCompareNode(l, rl)) {
+    caseIndex = 1; /* (a)(a b) */
+  }
+  else if(bAigCompareNode(l, rr)) {
+    caseIndex = 2; /* (a)(b a) */
+  }
+
+  caseSig = 0;
+  if(bAig_IsInverted(l))  caseSig += 8;
+  if(bAig_IsInverted(rl)) caseSig += 4;
+  if(bAig_IsInverted(rr)) caseSig += 2;
+  if(bAig_IsInverted(r))  caseSig += 1;
+  if(caseIndex == 0) {
+    return(bAig_And2(manager, l, r));
+  }
+  else if(caseIndex == 1) {
+    switch(caseSig) {
+	case 2 :
+	case 0 :
+	case 14 :
+	case 12 :
+      return(r);
+	case 10 :
+	case 8 :
+	case 6 :
+	case 4 :
+      return(bAig_Zero);
+	case 3 :
+	case 1 :
+	case 15 :
+	case 13 :
+      return(bAig_And(manager, rl, bAig_Not(rr)));
+	case 11 :
+	case 9 :
+	case 7 :
+	case 5 :
+      return(l);
+    }
+  }
+  else if(caseIndex == 2) {
+    switch(caseSig) {
+	case 4 :
+	case 0 :
+	case 14 :
+	case 10 :
+      return(r);
+	case 12 :
+	case 8 :
+	case 6 :
+	case 2 :
+      return(bAig_Zero);
+	case 5 :
+	case 1 :
+	case 15 :
+	case 11 :
+      return(bAig_And(manager, bAig_Not(rl), rr));
+	case 13 :
+	case 9 :
+	case 7 :
+	case 3 :
+      return(l);
+    }
+  }
+  return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Set mask for transitive fanin nodes]
+
+  Description [Set mask for transitive fanin nodes]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAig_SetMaskTransitiveFanin(
+	bAig_Manager_t *manager,
+	int v,
+	unsigned int mask)
+{
+  if(v == 2)	return;
+
+
+  if(flags(v) & mask)	return;
+
+  flags(v) |= mask;
+
+  bAig_SetMaskTransitiveFanin(manager, leftChild(v), mask);
+  bAig_SetMaskTransitiveFanin(manager, rightChild(v), mask);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Reset mask for transitive fanin nodes]
+
+  Description [Reset mask for transitive fanin nodes]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAig_ResetMaskTransitiveFanin(
+	bAig_Manager_t *manager,
+	int v,
+	unsigned int mask,
+	unsigned int resetMask)
+{
+  if(v == 2)	return;
+
+
+  if(!(flags(v) & mask))	return;
+
+  flags(v) &= resetMask;
+  bAig_ResetMaskTransitiveFanin(manager, leftChild(v), mask, resetMask);
+  bAig_ResetMaskTransitiveFanin(manager, rightChild(v), mask, resetMask);
+}
+
+
+/**Function********************************************************************
+
+   Synopsis [Get value of aig node.]
+
+   Description [The default falue is 2, which is same as UNKNOWN. This value can be assigned from SAT solver.]
+
+   SideEffects []
+   
+   SeeAlso     []
+   
+******************************************************************************/
+
+int
+bAig_GetValueOfNode(bAig_Manager_t *manager, bAigEdge_t v)
+{
+  unsigned int value, lvalue, rvalue;
+  bAigEdge_t left, right;
+
+
+  /*
+  if(!(flags(v) & CoiMask))	return(2);
+  **/
+  if(v == 2)	return(2);
+
+  value = aig_value(v);
+  if(value == 3)	return(2);
+  if(value == 2) {
+    left = bAig_GetCanonical(manager, leftChild(v));
+    lvalue = bAig_GetValueOfNode(manager, left);
+    if(lvalue == 0)	{
+      value = 0;
+    }
+    else {
+      right = bAig_GetCanonical(manager, rightChild(v));
+      rvalue = bAig_GetValueOfNode(manager, right);
+      if(rvalue == 0) {
+	value = 0;
+      }
+      else if(rvalue == 1 && lvalue == 1) {
+	value = 1;
+      }
+      else {
+	value = 2;
+      }
+    }
+  }
+
+  if(value == 2) {
+    aig_value(v) = 3;
+    return(value);
+  }
+  else	{	
+    aig_value(v) = value;
+    return(value ^ bAig_IsInverted(v));
+  }
+}
+
Index: vis_dev/vis-2.3/src/baig/baigTimeframe.c
===================================================================
--- vis_dev/vis-2.3/src/baig/baigTimeframe.c	(revision 14)
+++ vis_dev/vis-2.3/src/baig/baigTimeframe.c	(revision 14)
@@ -0,0 +1,1460 @@
+/**CFile***********************************************************************
+
+  FileName    [baigTimeframe.c]
+
+  PackageName [baig]
+
+  Synopsis    [Functions to manage timeframe expansion.]
+
+  Author      [HoonSang Jin]
+
+  Copyright [ This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "maig.h"
+#include "ntk.h"
+#include "cmd.h"
+#include "baig.h"
+#include "baigInt.h"
+#include "heap.h"
+#include "sat.h"
+#include "bmc.h"
+
+static char rcsid[] UNUSED = "$ $";
+
+/* #define TIMEFRAME_VERIFY_ */
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int nameCompare(const void * node1, const void * node2);
+static int NoOfBitEncode(int n);
+static bAigEdge_t CaseNew(mAig_Manager_t *manager, bAigEdge_t *arr, array_t * encodeList, int index);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Expand timeframe n times]
+
+  Description [Expand timeframe n times. If withInitialState flag is set then 
+               unroll transition function considering initial states, otherwise
+	       the state variables of 0'th timeframe are free variables]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAig_ExpandTimeFrame(
+	Ntk_Network_t *network,
+	mAig_Manager_t *manager,
+	int bound,
+	int withInitialState)
+{
+bAigTimeFrame_t *timeframe;
+int nLatches, nInputs, nOutputs, nInternals;
+int nbLatches, nbInputs;
+int i, j;
+int index, index1, bindex, tindex;
+int mvfSize, lmvfSize;
+int lmAigId;
+array_t *iindexArray;
+MvfAig_Function_t  *mvfAig, *lmvfAig;
+bAigEdge_t *li, *bli;
+bAigEdge_t *pre_li, *ori_li;
+bAigEdge_t v, nv = bAig_NULL;
+Ntk_Node_t *node, *latch;
+st_table   *node2MvfAigTable, *old2new;
+mAigMvar_t lmVar;
+mAigBvar_t lbVar;
+array_t   *bVarList, *mVarList;
+lsGen gen;
+
+
+  if(withInitialState) timeframe = manager->timeframe;
+  else                 timeframe = manager->timeframeWOI;
+
+  if(timeframe == 0) 
+    timeframe = bAig_InitTimeFrame(network, manager, withInitialState);
+
+  node2MvfAigTable = 
+	(st_table *)Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+
+  nbLatches = timeframe->nbLatches;
+  nbInputs = timeframe->nbInputs;
+  nLatches = timeframe->nLatches;
+  nInputs = timeframe->nInputs;
+  nOutputs = timeframe->nOutputs;
+  nInternals = timeframe->nInternals;
+
+  iindexArray = timeframe->iindexArray;
+
+  if(bound > timeframe->currentTimeframe) {
+    timeframe->latchInputs = (bAigEdge_t **)
+	realloc(timeframe->latchInputs, sizeof(bAigEdge_t *)*(bound+2));
+    timeframe->inputs = (bAigEdge_t **)
+      realloc(timeframe->inputs, sizeof(bAigEdge_t *)*(bound+1));
+    timeframe->blatchInputs = (bAigEdge_t **)
+	realloc(timeframe->blatchInputs, sizeof(bAigEdge_t *)*(bound+2));
+    timeframe->binputs = (bAigEdge_t **)
+      realloc(timeframe->binputs, sizeof(bAigEdge_t *)*(bound+1));
+    timeframe->outputs = (bAigEdge_t **)
+      realloc(timeframe->outputs, sizeof(bAigEdge_t *)*(bound+1));
+    timeframe->internals = (bAigEdge_t **)
+      realloc(timeframe->internals, sizeof(bAigEdge_t *)*(bound+1));
+  }
+
+  bVarList = mAigReadBinVarList(manager);
+  mVarList = mAigReadMulVarList(manager);
+
+  for(j=timeframe->currentTimeframe+1; j<=bound; j++) {
+    /** create new primary input node **/
+    timeframe->inputs = (bAigEdge_t **)
+        realloc(timeframe->inputs, sizeof(bAigEdge_t *)*(j+1));
+    timeframe->binputs = (bAigEdge_t **)
+        realloc(timeframe->binputs, sizeof(bAigEdge_t *)*(j+1));
+    bli = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nbInputs);
+    timeframe->binputs[j] = bli;
+    li = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nInputs);
+    timeframe->inputs[j] = li;
+    index = 0;
+    index1 = 0;
+    bindex = 0;
+    Ntk_NetworkForEachPrimaryInput(network, gen, node) {
+      bAig_CreateNewNode(manager, node2MvfAigTable, node, bli, li, &bindex, &index);
+
+      st_lookup(node2MvfAigTable, node, &mvfAig);
+      mvfSize = array_n(mvfAig);
+      for(i=0; i< mvfSize; i++){
+        v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+#ifdef TIMEFRAME_VERIFY_
+	fprintf(vis_stdout, "IN(%d) %s(%d) : %d -> %d\n", j, Ntk_NodeReadName(node), i, v, li[index1]);
+#endif
+	index1++;
+      }
+    }
+    Ntk_NetworkForEachPseudoInput(network, gen, node) {
+      bAig_CreateNewNode(manager, node2MvfAigTable, node, bli, li,  &bindex, &index);
+
+      st_lookup(node2MvfAigTable, node, &mvfAig);
+      mvfSize = array_n(mvfAig);
+      for(i=0; i< mvfSize; i++){
+        v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+#ifdef TIMEFRAME_VERIFY_
+	fprintf(vis_stdout, "PI(%d) %s(%d) : %d -> %d\n", j, Ntk_NodeReadName(node), i, v, li[index1]);
+#endif
+	index1++;
+      }
+    }
+
+    /** map previous time frame into current **/
+    old2new = st_init_table(st_ptrcmp, st_ptrhash);
+    pre_li = timeframe->inputs[j];
+    ori_li = timeframe->oriInputs;
+    for(i=0; i<nInputs; i++)
+      st_insert(old2new, (char *)ori_li[i], (char *)pre_li[i]);
+
+    pre_li = timeframe->latchInputs[j];
+    ori_li = timeframe->oriLatchInputs;
+    for(i=0; i<nLatches; i++)
+      st_insert(old2new, (char *)ori_li[i], (char *)pre_li[i]);
+
+    pre_li = timeframe->binputs[j];
+    ori_li = timeframe->oribInputs;
+    for(i=0; i<nbInputs; i++)
+      st_insert(old2new, (char *)ori_li[i], (char *)pre_li[i]);
+
+    pre_li = timeframe->blatchInputs[j];
+    ori_li = timeframe->oribLatchInputs;
+    for(i=0; i<nbLatches; i++)
+      st_insert(old2new, (char *)ori_li[i], (char *)pre_li[i]);
+
+    /** create new time frame **/
+    li = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nLatches);
+    bli = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nbLatches);
+    timeframe->latchInputs[j+1] = li;
+    timeframe->blatchInputs[j+1] = bli;
+    bindex = index = 0;
+    Ntk_NetworkForEachLatch(network, gen, latch) {
+      node  = Ntk_LatchReadDataInput(latch);
+      mvfAig = lmvfAig = 0;
+      st_lookup(node2MvfAigTable, node, &mvfAig);
+      mvfSize = array_n(mvfAig);
+      st_lookup(node2MvfAigTable, latch, &lmvfAig);
+      lmvfSize = array_n(lmvfAig);
+      if(mvfSize != lmvfSize) {
+	fprintf(vis_stdout, "WARNING : the number of values of signals mismatched\n");
+	fprintf(vis_stdout, "          %s(%d), %s(%d)\n", 
+		Ntk_NodeReadName(node), mvfSize, 
+		Ntk_NodeReadName(latch), lmvfSize);
+        for(i=0; i< mvfSize; i++){
+          v = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(mvfAig, i));
+          nv = bAig_ExpandForEachCone(manager, v, old2new);
+          st_insert(old2new, (char *)v, (char *)nv);
+          li[index++] = nv;
+        }
+        for(i=mvfSize; i< lmvfSize; i++){
+          li[index++] = nv;
+        }
+      }
+      else {
+        for(i=0; i< mvfSize; i++){
+          v = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(mvfAig, i));
+	  /**
+	    fprintf(vis_stdout, "-------------------------------\n");
+            fprintf(vis_stdout, "      Latch input %d %d\n", v, manager->nodesArraySize);
+            fprintf(vis_stdout, "-------------------------------\n");
+            bAig_SatRebuildNodeVerifySub(v, manager->NodesArray);
+	    **/
+
+          nv = bAig_ExpandForEachCone(manager, v, old2new);
+	  flags(nv) |= StateBitMask;
+          st_insert(old2new, (char *)v, (char *)nv);
+#ifdef TIMEFRAME_VERIFY_
+	  fprintf(vis_stdout, "LI(%d) %s(%d) : %d -> %d\n", 
+		  j+1, Ntk_NodeReadName(latch), i, v, nv);
+#endif
+          li[index++] = nv;
+        }
+      }
+
+      lmAigId = Ntk_NodeReadMAigId(node);
+      lmVar = array_fetch(mAigMvar_t, mVarList, lmAigId);
+      for(i=0, tindex=lmVar.bVars; i<lmVar.encodeLength; i++) {
+        lbVar = array_fetch(mAigBvar_t, bVarList, tindex);
+	tindex++;
+        v = bAig_GetCanonical(manager, lbVar.node);
+        nv = bAig_ExpandForEachCone(manager, v, old2new);
+        flags(nv) |= StateBitMask;
+        st_insert(old2new, (char *)v, (char *)nv);
+        bli[bindex++] = nv;
+      }
+    }
+
+    li = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nOutputs);
+    timeframe->outputs[j] = li;
+    index = 0;
+    Ntk_NetworkForEachPrimaryOutput(network, gen, node) {
+      st_lookup(node2MvfAigTable, node, &mvfAig);
+      mvfSize = array_n(mvfAig);
+      for(i=0; i< mvfSize; i++){
+        v = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(mvfAig, i));
+
+	/**
+	  fprintf(vis_stdout, "-------------------------------\n");
+          fprintf(vis_stdout, "      Output %d\n", v);
+          fprintf(vis_stdout, "-------------------------------\n");
+          bAig_SatRebuildNodeVerifySub(v, manager->NodesArray);
+	  **/
+
+        nv = bAig_ExpandForEachCone(manager, v, old2new);
+        st_insert(old2new, (char *)v, (char *)nv);
+#ifdef TIMEFRAME_VERIFY_
+	fprintf(vis_stdout, "PO(%d) %s(%d) : %d -> %d\n", j+1, Ntk_NodeReadName(node), i, v, li[index]);
+#endif
+      st_insert(old2new, (char *)v, (char *)nv);
+        li[index++] = nv;
+      }
+    }
+  
+    li = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nInternals);
+    timeframe->internals[j] = li;
+    for(i=0; i<array_n(iindexArray); i++) {
+      v = array_fetch(bAigEdge_t, iindexArray, i);
+      nv = bAig_ExpandForEachCone(manager, v, old2new);
+      st_insert(old2new, (char *)v, (char *)nv);
+      li[i] = nv;
+    }
+    st_free_table(old2new);
+  }
+
+  timeframe->currentTimeframe = bound;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Compare function for name ordering]
+
+  Description [Compare function for name ordering]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+nameCompare(
+  const void * node1,
+  const void * node2)
+{
+  char *name1, *name2;
+  
+  name1 = Ntk_NodeReadName((Ntk_Node_t *)node1);
+  name2 = Ntk_NodeReadName((Ntk_Node_t *)node2);
+  return(strcmp(*(char**)name1, *(char **)name2));
+
+} 
+
+
+/**Function********************************************************************
+
+  Synopsis    [Make first timeframe]
+
+  Description [Make first timeframe]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bAigTimeFrame_t *
+bAig_InitTimeFrame(
+	Ntk_Network_t *network,
+	mAig_Manager_t *manager,
+	int withInitialState)
+{
+bAigTimeFrame_t *timeframe;
+array_t *latchArr, *inputArr, *outputArr;
+array_t *iindexArray;
+st_table   *li2index, *o2index, *i2index, *pi2index;
+st_table   *bli2index, *bpi2index;
+Ntk_Node_t *node, *latch;
+st_table   *node2MvfAigTable, *old2new;
+lsGen gen;
+int nLatches, nInputs, nOutputs, nInternals;
+int nbLatches, nbInputs;
+int i;
+int index, index1, mvfSize, lmvfSize;
+int bindex, tindex, tindex1;
+MvfAig_Function_t  *mvfAig, *tmpMvfAig, *lmvfAig;
+bAigEdge_t *li, *pre_li, *ori_li;
+bAigEdge_t *bli, *ori_bli;
+bAigEdge_t v=bAig_NULL, nv;
+mAigMvar_t mVar;
+mAigBvar_t bVar;
+array_t   *bVarList, *mVarList;
+int mAigId;
+int lmAigId;
+mAigMvar_t lmVar;
+mAigBvar_t lbVar;
+
+  node2MvfAigTable = 
+	(st_table *)Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+
+  timeframe = ALLOC(bAigTimeFrame_t, 1);
+  memset(timeframe, 0, sizeof(bAigTimeFrame_t));
+  if(withInitialState) manager->timeframe = timeframe;
+  else                 manager->timeframeWOI = timeframe;
+
+  latchArr = array_alloc(Ntk_Node_t *, 0);
+  inputArr = array_alloc(Ntk_Node_t *, 0);
+  outputArr = array_alloc(Ntk_Node_t *, 0);
+  timeframe->latchArr = latchArr;
+  timeframe->inputArr = inputArr;
+  timeframe->outputArr = outputArr;
+
+  li2index = st_init_table(st_ptrcmp, st_ptrhash);
+  o2index = st_init_table(st_ptrcmp, st_ptrhash);
+  i2index = st_init_table(st_ptrcmp, st_ptrhash);
+  pi2index = st_init_table(st_ptrcmp, st_ptrhash);
+
+  bli2index = st_init_table(st_ptrcmp, st_ptrhash);
+  bpi2index = st_init_table(st_ptrcmp, st_ptrhash);
+
+  timeframe->li2index = li2index;
+  timeframe->o2index = o2index;
+  timeframe->pi2index = pi2index;
+  timeframe->i2index = i2index;
+
+  timeframe->bli2index = bli2index;
+  timeframe->bpi2index = bpi2index;
+  /** 
+   * count total number, 
+   * insert into node array 
+   * and make table for bAigEdge_t to index
+   **/
+
+  bVarList = mAigReadBinVarList(manager);
+  mVarList = mAigReadMulVarList(manager);
+
+  nLatches = 0;
+  nbLatches = 0;
+  Ntk_NetworkForEachLatch(network, gen, latch) {
+    array_insert_last(Ntk_Node_t *, latchArr, latch);
+    st_lookup(node2MvfAigTable, latch, &mvfAig);
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+      st_insert(li2index, (char *)v, (char *)(long)nLatches++);
+    }
+
+    mAigId = Ntk_NodeReadMAigId(latch);
+    mVar = array_fetch(mAigMvar_t, mVarList, mAigId);
+    for(i=0, index1=mVar.bVars; i<mVar.encodeLength; i++) {
+      bVar = array_fetch(mAigBvar_t, bVarList, index1);
+      st_insert(bli2index, (char *)bVar.node, (char *)(long)nbLatches++);
+      index1++;
+    }
+  }
+  timeframe->nLatches = nLatches;
+  timeframe->nbLatches = nbLatches;
+
+  nOutputs = 0;
+  Ntk_NetworkForEachPrimaryOutput(network, gen, node) {
+    array_insert_last(Ntk_Node_t *, outputArr, node);
+    st_lookup(node2MvfAigTable, node, &mvfAig);
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+      st_insert(o2index, (char *)(long)v, (char *)(long)nOutputs++);
+    }
+  }
+  timeframe->nOutputs = nOutputs;
+
+  timeframe->iindexArray = iindexArray = array_alloc(bAigEdge_t, 0);
+  nInternals = 0;
+  Ntk_NetworkForEachNode(network, gen, node) {
+    if(Ntk_NodeTestIsShadow(node))	continue;
+    if(Ntk_NodeTestIsCombInput(node))	continue;
+    if(Ntk_NodeTestIsCombOutput(node))continue;
+    if(!st_lookup(node2MvfAigTable, node, &mvfAig)) {
+      tmpMvfAig = Bmc_NodeBuildMVF(network, node);
+      array_free(tmpMvfAig);
+      mvfAig = Bmc_ReadMvfAig(node, node2MvfAigTable);
+    }
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+      if(!st_lookup(i2index, (char *)v, &index1)) {
+	array_insert_last(bAigEdge_t, iindexArray, v);
+	st_insert(i2index, (char *)v, (char *)(long)nInternals++);
+      }
+    }
+#ifdef TIMEFRAME_VERIFY_
+      if(!strcmp(Ntk_NodeReadName(node), "v25") ||
+	 !strcmp(Ntk_NodeReadName(node), "v27")) {
+	  fprintf(stdout, "current error %d %d\n", v, nInternals);
+      }
+#endif
+  }
+  timeframe->nInternals = nInternals;
+
+  nInputs = 0;
+  nbInputs = 0;
+  Ntk_NetworkForEachPrimaryInput(network, gen, node) {
+    array_insert_last(Ntk_Node_t *, inputArr, node);
+    if(!st_lookup(node2MvfAigTable, node, &mvfAig)) {
+      tmpMvfAig = Bmc_NodeBuildMVF(network, node);
+      array_free(tmpMvfAig);
+      mvfAig = Bmc_ReadMvfAig(node, node2MvfAigTable);
+    }
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+	st_insert(pi2index, (char *)(long)v, (char *)(long)nInputs++);
+    }
+
+    mAigId = Ntk_NodeReadMAigId(node);
+    mVar = array_fetch(mAigMvar_t, mVarList, mAigId);
+    for(i=0, index1=mVar.bVars; i<mVar.encodeLength; i++) {
+      bVar = array_fetch(mAigBvar_t, bVarList, index1);
+      st_insert(bpi2index, (char *)bVar.node, (char *)(long)nbInputs++);
+      index1++;
+    }
+  }
+  Ntk_NetworkForEachPseudoInput(network, gen, node)  {
+    array_insert_last(Ntk_Node_t *, inputArr, node);
+    if(!st_lookup(node2MvfAigTable, node, &mvfAig)) {
+      tmpMvfAig = Bmc_NodeBuildMVF(network, node);
+      array_free(tmpMvfAig);
+      mvfAig = Bmc_ReadMvfAig(node, node2MvfAigTable);
+    }
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+	st_insert(pi2index, (char *)(long)v, (char *)(long)nInputs++);
+    }
+
+    mAigId = Ntk_NodeReadMAigId(node);
+    mVar = array_fetch(mAigMvar_t, mVarList, mAigId);
+    for(i=0, index1=mVar.bVars; i<mVar.encodeLength; i++) {
+      bVar = array_fetch(mAigBvar_t, bVarList, index1);
+      st_insert(bpi2index, (char *)bVar.node, (char *)(long)nbInputs++);
+      index1++;
+    }
+  }
+  timeframe->nInputs = nInputs;
+  timeframe->nbInputs = nbInputs;
+
+  array_sort(inputArr, nameCompare);
+  array_sort(latchArr, nameCompare);
+  array_sort(outputArr, nameCompare);
+
+    /** make 0 index bAigEdge_t **/
+  old2new = st_init_table(st_ptrcmp, st_ptrhash);
+  bli = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nbInputs);
+  li = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nInputs);
+  index1 = index = 0;
+  bindex = 0;
+  Ntk_NetworkForEachPrimaryInput(network, gen, node) {
+    bAig_CreateNewNode(manager, node2MvfAigTable, node, bli, li, &bindex, &index);
+
+    st_lookup(node2MvfAigTable, node, &mvfAig);
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+#ifdef TIMEFRAME_VERIFY_
+      fprintf(vis_stdout, "IN(%d) %s(%d) : %d -> %d\n", -1, Ntk_NodeReadName(node), i, v, li[index1]);
+#endif
+      st_insert(old2new, (char *)v, (char *)(li[index1++]));
+    }
+  }
+  Ntk_NetworkForEachPseudoInput(network, gen, node) {
+    bAig_CreateNewNode(manager, node2MvfAigTable, node, bli, li, &bindex, &index);
+
+    st_lookup(node2MvfAigTable, node, &mvfAig);
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+#ifdef TIMEFRAME_VERIFY_
+      fprintf(vis_stdout, "PI(%d) %s(%d) : %d -> %d\n", -1, Ntk_NodeReadName(node), i, v, li[index1]);
+#endif
+      st_insert(old2new, (char *)v, (char *)(li[index1++]));
+    }
+  }
+
+  timeframe->blatchInputs = (bAigEdge_t **)malloc(sizeof(bAigEdge_t *)*(2));
+  bli = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nbLatches);
+  timeframe->blatchInputs[0] = bli;
+
+  timeframe->latchInputs = (bAigEdge_t **)malloc(sizeof(bAigEdge_t *)*(2));
+  li = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nLatches);
+  timeframe->latchInputs[0] = li;
+
+  ori_li = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nLatches);
+  ori_bli = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nbLatches);
+  timeframe->oriLatchInputs = ori_li;
+  timeframe->oribLatchInputs = ori_bli;
+
+  index1 = index = 0;
+  bindex = tindex = tindex1 = 0;
+
+  if(withInitialState == 0) {
+    Ntk_NetworkForEachLatch(network, gen, latch) {
+      bAig_CreateNewNode(manager, node2MvfAigTable, latch, bli, li, &bindex, &index);
+
+      st_lookup(node2MvfAigTable, latch, &mvfAig);
+      mvfSize = array_n(mvfAig);
+      for(i=0; i< mvfSize; i++){
+        v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+        st_insert(old2new, (char *)v, (char *)(li[index1]));
+  #ifdef TIMEFRAME_VERIFY_
+	fprintf(vis_stdout, "LI(%d) %s(%d) : %d -> %d\n", 0, Ntk_NodeReadName(latch), i, v, li[index1]);
+  #endif
+	ori_li[index1++] = v;
+      }
+
+      lmAigId = Ntk_NodeReadMAigId(latch);
+      lmVar = array_fetch(mAigMvar_t, mVarList, lmAigId);
+      for(i=0, tindex1=lmVar.bVars; i<lmVar.encodeLength; i++) {
+        lbVar = array_fetch(mAigBvar_t, bVarList, tindex1);
+	tindex1++;
+        v = bAig_GetCanonical(manager, lbVar.node);
+	ori_bli[tindex++] = v ;
+      }
+    }
+  }
+  else {
+    Ntk_NetworkForEachLatch(network, gen, latch) {
+      node  = Ntk_LatchReadInitialInput(latch);
+      mvfAig = lmvfAig = 0;
+      st_lookup(node2MvfAigTable, node, &mvfAig);
+      mvfSize = array_n(mvfAig);
+      if(!st_lookup(node2MvfAigTable, latch, &lmvfAig)) {
+        tmpMvfAig = Bmc_NodeBuildMVF(network, latch);
+        array_free(tmpMvfAig);
+        lmvfAig = Bmc_ReadMvfAig(latch, node2MvfAigTable);
+      }
+      lmvfSize = array_n(lmvfAig);
+      if(mvfSize != lmvfSize) {
+	  fprintf(vis_stdout, "WARNING : the number of values of signals mismatched\n");
+	  fprintf(vis_stdout, "          %s(%d), %s(%d)\n", 
+		  Ntk_NodeReadName(node), mvfSize, 
+		  Ntk_NodeReadName(latch), lmvfSize);
+        for(i=0; i< mvfSize; i++){
+          v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+          nv = bAig_ExpandForEachCone(manager, v, old2new);
+          st_insert(old2new, (char *)v, (char *)nv);
+	    li[index++] = nv;
+        }
+        for(i=mvfSize; i<lmvfSize; i++) {
+          nv = bAig_ExpandForEachCone(manager, v, old2new);
+          st_insert(old2new, (char *)v, (char *)nv);
+	    li[index++] = nv;
+        }
+      }
+      else {
+        for(i=0; i< mvfSize; i++){
+          v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+          nv = bAig_ExpandForEachCone(manager, v, old2new);
+          st_insert(old2new, (char *)v, (char *)nv);
+	    li[index++] = nv;
+        }
+      }
+      for(i=0; i< lmvfSize; i++){
+        v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(lmvfAig, i));
+  #ifdef TIMEFRAME_VERIFY_
+	  fprintf(vis_stdout, "LI(%d) %s(%d) : %d -> %d\n", 0, Ntk_NodeReadName(latch), i, v, li[index1]);
+  #endif
+	  ori_li[index1++] = v;
+      }
+      lmAigId = Ntk_NodeReadMAigId(latch);
+      lmVar = array_fetch(mAigMvar_t, mVarList, lmAigId);
+      for(i=0, tindex1=lmVar.bVars; i<lmVar.encodeLength; i++) {
+        lbVar = array_fetch(mAigBvar_t, bVarList, tindex1);
+	tindex1++;
+        v = bAig_GetCanonical(manager, lbVar.node);
+	ori_bli[tindex++]  = v;
+      }
+      node  = Ntk_LatchReadInitialInput(latch);
+      lmAigId = Ntk_NodeReadMAigId(node);
+      lmVar = array_fetch(mAigMvar_t, mVarList, lmAigId);
+      for(i=0, tindex1=lmVar.bVars; i<lmVar.encodeLength; i++) {
+        lbVar = array_fetch(mAigBvar_t, bVarList, tindex1);
+	tindex1++;
+        v = bAig_GetCanonical(manager, lbVar.node);
+        if(st_lookup(old2new, (char *)v, &nv))
+	  bli[bindex++]  = nv;
+	else
+	  bli[bindex++]  = v;
+      }
+    }
+  }
+  st_free_table(old2new);
+
+  timeframe->binputs = (bAigEdge_t **)malloc(sizeof(bAigEdge_t *));
+  bli = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nbInputs);
+  timeframe->binputs[0] = bli;
+
+  timeframe->inputs = (bAigEdge_t **)malloc(sizeof(bAigEdge_t *));
+  li = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nInputs);
+  ori_li = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nInputs);
+  ori_bli = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nInputs);
+  timeframe->inputs[0] = li;
+  timeframe->oriInputs = ori_li;
+  timeframe->oribInputs = ori_bli;
+  index1 = index = 0;
+  tindex = bindex = tindex1 = 0;
+  Ntk_NetworkForEachPrimaryInput(network, gen, node) {
+    bAig_CreateNewNode(manager, node2MvfAigTable, node, bli, li, &bindex, &index);
+
+    st_lookup(node2MvfAigTable, node, &mvfAig);
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+#ifdef TIMEFRAME_VERIFY_
+	fprintf(vis_stdout, "IN(%d) %s(%d) : %d -> %d\n", 0, Ntk_NodeReadName(node), i, v, li[index1]);
+#endif
+	ori_li[index1++] = v;
+    }
+    lmAigId = Ntk_NodeReadMAigId(node);
+    lmVar = array_fetch(mAigMvar_t, mVarList, lmAigId);
+    for(i=0, tindex1=lmVar.bVars; i<lmVar.encodeLength; i++) {
+      lbVar = array_fetch(mAigBvar_t, bVarList, tindex1);
+      tindex1++;
+      v = bAig_GetCanonical(manager, lbVar.node);
+      ori_bli[tindex++] = v;
+    }
+  }
+  Ntk_NetworkForEachPseudoInput(network, gen, node) {
+    bAig_CreateNewNode(manager, node2MvfAigTable, node, bli, li, &bindex, &index);
+
+    st_lookup(node2MvfAigTable, node, &mvfAig);
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+#ifdef TIMEFRAME_VERIFY_
+	fprintf(vis_stdout, "PI(%d) %s(%d) : %d -> %d\n", 0, Ntk_NodeReadName(node), i, v, li[index1]);
+#endif
+	ori_li[index1++] = v;
+    }
+    lmAigId = Ntk_NodeReadMAigId(node);
+    lmVar = array_fetch(mAigMvar_t, mVarList, lmAigId);
+    for(i=0, tindex1=lmVar.bVars; i<lmVar.encodeLength; i++) {
+      lbVar = array_fetch(mAigBvar_t, bVarList, tindex1);
+      tindex1++;
+      v = bAig_GetCanonical(manager, lbVar.node);
+      ori_bli[tindex++] = v;
+    }
+  }
+
+    /** map node of previous timeframe into current timeframe **/
+  old2new = st_init_table(st_ptrcmp, st_ptrhash);
+  pre_li = timeframe->inputs[0];
+  ori_li = timeframe->oriInputs;
+  for(i=0; i<nInputs; i++)
+    st_insert(old2new, (char *)ori_li[i], (char *)pre_li[i]);
+  pre_li = timeframe->latchInputs[0];
+  ori_li = timeframe->oriLatchInputs;
+  for(i=0; i<nLatches; i++)
+    st_insert(old2new, (char *)ori_li[i], (char *)pre_li[i]);
+
+  pre_li = timeframe->binputs[0];
+  ori_li = timeframe->oribInputs;
+  for(i=0; i<nbInputs; i++)
+    st_insert(old2new, (char *)ori_li[i], (char *)pre_li[i]);
+  pre_li = timeframe->blatchInputs[0];
+  ori_li = timeframe->oribLatchInputs;
+  for(i=0; i<nbLatches; i++)
+    st_insert(old2new, (char *)ori_li[i], (char *)pre_li[i]);
+
+    /** create timeframe **/
+  li = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nLatches);
+  timeframe->latchInputs[1] = li;
+  bli = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nbLatches);
+  timeframe->blatchInputs[1] = bli;
+  bindex = index = 0;
+  Ntk_NetworkForEachLatch(network, gen, latch) {
+    node  = Ntk_LatchReadDataInput(latch);
+    mvfAig = lmvfAig = 0;
+    st_lookup(node2MvfAigTable, node, &mvfAig);
+    mvfSize = array_n(mvfAig);
+    st_lookup(node2MvfAigTable, latch, &lmvfAig);
+    lmvfSize = array_n(lmvfAig);
+    if(mvfSize != lmvfSize) {
+	fprintf(vis_stdout, "WARNING : the number of values of signals mismatched\n");
+	fprintf(vis_stdout, "          %s(%d), %s(%d)\n", 
+		Ntk_NodeReadName(node), mvfSize, 
+		Ntk_NodeReadName(latch), lmvfSize);
+      for(i=0; i< mvfSize; i++){
+        v = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(mvfAig, i));
+        nv = bAig_ExpandForEachCone(manager, v, old2new);
+        st_insert(old2new, (char *)v, (char *)nv);
+        li[index++] = nv;
+      }
+      for(i=mvfSize; i< lmvfSize; i++){
+        li[index++] = nv;
+      }
+    }
+    else {
+      for(i=0; i< mvfSize; i++){
+        v = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(mvfAig, i));
+        nv = bAig_ExpandForEachCone(manager, v, old2new);
+/*	flags(nv) |= StateBitMask; */
+        st_insert(old2new, (char *)v, (char *)nv);
+#ifdef TIMEFRAME_VERIFY_
+	fprintf(vis_stdout, "LI(%d) %s(%d) : %d -> %d\n", 
+		  1, Ntk_NodeReadName(latch), i, v, nv);
+#endif
+        li[index++] = nv;
+      }
+    }
+    /* State bit mapping **/
+    lmAigId = Ntk_NodeReadMAigId(node);
+    lmVar = array_fetch(mAigMvar_t, mVarList, lmAigId);
+    for(i=0, tindex=lmVar.bVars; i<lmVar.encodeLength; i++) {
+      lbVar = array_fetch(mAigBvar_t, bVarList, tindex);
+      tindex++;
+      v = bAig_GetCanonical(manager, lbVar.node);
+      nv = bAig_ExpandForEachCone(manager, v, old2new);
+      flags(nv) |= StateBitMask;
+      st_insert(old2new, (char *)v, (char *)nv);
+      bli[bindex++] = nv;
+    }
+
+  }
+
+  timeframe->outputs = (bAigEdge_t **)malloc(sizeof(bAigEdge_t *));
+  li = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nOutputs);
+  timeframe->outputs[0] = li;
+  index = 0;
+  Ntk_NetworkForEachPrimaryOutput(network, gen, node) {
+    st_lookup(node2MvfAigTable, node, &mvfAig);
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+      nv = bAig_ExpandForEachCone(manager, v, old2new);
+#ifdef TIMEFRAME_VERIFY_
+	fprintf(vis_stdout, "PO(%d) %s(%d) : %d -> %d\n", 0, Ntk_NodeReadName(node), i, v, li[index]);
+#endif
+      st_insert(old2new, (char *)v, (char *)nv);
+      li[index++] = nv;
+    }
+  }
+
+  index = 0;
+  timeframe->internals = (bAigEdge_t **)malloc(sizeof(bAigEdge_t *));
+  li = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nInternals);
+  timeframe->internals[0] = li;
+  for(i=0; i<array_n(iindexArray); i++) {
+    v = array_fetch(bAigEdge_t, iindexArray, i);
+    nv = bAig_ExpandForEachCone(manager, v, old2new);
+    st_insert(old2new, (char *)v, (char *)nv);
+    li[i] = nv;
+  }
+  st_free_table(old2new);
+
+  timeframe->currentTimeframe = 0;
+
+  return(timeframe);
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Create aig node for free variables]
+
+  Description [Create aig node for free variables, 
+               such as primary input and pseudo input]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAig_CreateNewNode(
+	mAig_Manager_t *manager, 
+	st_table *node2MvfAigTable,
+	Ntk_Node_t *node, 
+	bAigEdge_t *bli,
+	bAigEdge_t *li,
+	int *bindex, 
+	int *index)
+{
+  int i, j, value, noBits;
+  bAigEdge_t *arr, v, tv;
+  MvfAig_Function_t  *mvfAig;
+  array_t *encodeList;
+  bAigEdge_t *ManagerNodesArray;
+  bAigTimeFrame_t *timeframe;
+ 
+  timeframe = manager->timeframe;
+
+  value = Var_VariableReadNumValues(Ntk_NodeReadVariable(node));
+  noBits = NoOfBitEncode(value);
+  arr = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*noBits);
+  mvfAig = 0;
+  st_lookup(node2MvfAigTable, node, &mvfAig);
+  for(i=0; i<noBits; i++) {
+    arr[i] = bAig_CreateNode(manager, bAig_NULL, bAig_NULL);
+    bli[(*bindex)++] = arr[i];
+
+    flags(arr[i]) |= IsSystemMask;
+  }
+
+  for(i=0; i<value; i++) {
+    v = MvfAig_FunctionReadComponent(mvfAig, i);
+    /**
+    if(v == bAig_Zero)		li[(*index)++] = bAig_Zero;
+    else if(v == bAig_One)	li[(*index)++] = bAig_One;
+    else {
+    }
+    **/
+      encodeList = array_alloc(bAigEdge_t, 0);
+      for(j=0; j<value; j++) {
+        if(j == i)array_insert_last(bAigEdge_t, encodeList, mAig_One);
+        else	array_insert_last(bAigEdge_t, encodeList, mAig_Zero);
+      }
+      tv = CaseNew(manager, arr, encodeList, noBits-1);
+      li[(*index)++] = tv;
+
+      ManagerNodesArray = manager->NodesArray;
+
+      array_free(encodeList);
+      if(v == bAig_Zero){
+	flags(tv) |= StaticLearnMask;
+	if(timeframe->assertedArray == 0)
+	  timeframe->assertedArray = array_alloc(bAigEdge_t, 0);
+	array_insert_last(bAigEdge_t, timeframe->assertedArray, bAig_Not(tv));
+      }
+      else if(v == bAig_One){
+	flags(tv) |= StaticLearnMask;
+	if(timeframe->assertedArray == 0)
+	  timeframe->assertedArray = array_alloc(bAigEdge_t, 0);
+	array_insert_last(bAigEdge_t, timeframe->assertedArray, tv);
+      }
+  }
+  free(arr);
+}
+    
+/**Function********************************************************************
+
+  Synopsis    [Compute bits is needed for encode n]
+
+  Description [Compute bits is needed for encode n]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+NoOfBitEncode( int n)
+{
+  int i = 0;
+  int j = 1;
+
+  if (n < 2) return 1; /* Takes care of mv.values <= 1 */
+
+  while (j < n) {
+    j = j * 2;
+    i++;
+  }
+  return i;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Extract bit from multi valued array]
+
+  Description [Extract bit from multi valued array]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static bAigEdge_t 
+CaseNew(mAig_Manager_t *manager,
+  bAigEdge_t      *arr,
+  array_t *       encodeList,
+  int             index) 
+{
+  int encodeLen;
+  int i, count;
+  bAigEdge_t v;
+  bAigEdge_t    andResult1, andResult2, orResult, result;
+  bAigEdge_t    node1, node2;
+  array_t *newEncodeList;
+
+  encodeLen = array_n(encodeList);
+  if (encodeLen == 1)
+    return array_fetch(bAigEdge_t, encodeList, 0);
+  newEncodeList =  array_alloc(bAigEdge_t, 0);
+
+  v = arr[index];
+  count = 0;
+  for (i=0; i< (encodeLen/2); i++){
+    node1 = array_fetch(bAigEdge_t, encodeList, count++);
+    node2 = array_fetch(bAigEdge_t, encodeList, count++);
+  
+     /*  performs ITE operator */
+    andResult1 = bAig_And(manager, v,           node2);
+    andResult2 = bAig_And(manager, bAig_Not(v), node1);
+    orResult   = bAig_Or (manager, andResult1,  andResult2);
+    flags(andResult1) |= IsSystemMask;
+    flags(andResult2) |= IsSystemMask;
+    flags(orResult) |= IsSystemMask;
+    
+    array_insert_last(bAigEdge_t, newEncodeList, orResult);
+  }
+
+  if(encodeLen%2){
+    node1 = array_fetch(bAigEdge_t, encodeList, count);
+    array_insert_last(bAigEdge_t, newEncodeList, node1);
+  }
+
+  result = CaseNew(manager, arr, newEncodeList, index-1);
+  array_free(newEncodeList);
+  return(result);
+}
+
+  
+/**Function********************************************************************
+
+  Synopsis    [Expand timeframe for aig node ]
+
+  Description [Expand timeframe for aig node ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bAigEdge_t 
+bAig_ExpandForEachCone(
+	mAig_Manager_t *manager,
+	bAigEdge_t v,
+	st_table *old2new)
+{
+  bAigEdge_t left, right, nv;
+
+  v = bAig_GetCanonical(manager, v);
+  if(v == bAig_One || v == bAig_Zero)	return(v);
+  if(v == bAig_NULL)	{
+      fprintf(vis_stdout, "current error\n");
+      return(v);
+  }
+
+
+  if(st_lookup(old2new, (char *)v, &nv))
+    return(nv);
+  if(st_lookup(old2new, (char *)bAig_Not(v), &nv))
+    return(bAig_Not(nv));
+
+  left = bAig_ExpandForEachCone(manager, leftChild(v), old2new);
+  right = bAig_ExpandForEachCone(manager, rightChild(v), old2new);
+
+  nv = bAig_And(manager, left, right);
+
+  flags(nv) |= IsSystemMask;
+  
+  if(bAig_IsInverted(v))	nv = bAig_Not(nv);
+  st_insert(old2new, (char *)v, (char *)nv);
+
+  return(nv);
+
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Check connectivity between aig nodes]
+
+  Description [Check connectivity between aig nodes]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAig_CheckConnect(
+	bAig_Manager_t *manager,
+	int from, int to)
+{
+int reached;
+
+  reached = bAig_CheckConnectFanin(manager, from, leftChild(to));
+  if(reached == 0)
+    reached = bAig_CheckConnectFanin(manager, from, rightChild(to));
+
+  if(reached == 0)
+    fprintf(stdout, "Node %d is not (backward) reachable from node %d\n",
+	    from, to);
+
+  reached = bAig_CheckConnectFanout(manager, from, to);
+  if(reached == 0)
+    fprintf(stdout, "Node %d is not (forward) reachable from node %d\n",
+	    to, from);
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Check connectivity of each fanin aig nodes]
+
+  Description [Check connectivity of each fanin aig nodes]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+bAig_CheckConnectFanin(bAig_Manager_t *manager,
+	int from, int to)
+{
+int left, right;
+int reached;
+
+  if(bAig_NonInvertedEdge(from) == bAig_NonInvertedEdge(to))
+    return(1);
+
+  left = leftChild(to);
+  if(left == 2)	
+    return(0);
+
+  right = leftChild(to);
+
+
+  reached = bAig_CheckConnectFanin(manager, from, left);
+  if(reached == 1)
+    return(1);
+  reached = bAig_CheckConnectFanin(manager, from, right);
+  if(reached == 1)
+    return(1);
+
+  return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Check connectivity of each fanout aig nodes]
+
+  Description [Check connectivity of each fanout aig nodes]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+bAig_CheckConnectFanout(bAig_Manager_t *manager,
+	int from, int to)
+{
+long *pfan, cur;
+int size, j;
+int reached;
+
+  size = nFanout(from);
+  for(j=0, pfan = (bAigEdge_t *)fanout(from); j<size; j++) {
+    cur = pfan[j];
+    cur = cur >> 1;
+    reached = bAig_CheckConnectFanout(manager, cur, to);
+    if(reached == 1)
+      return(1);
+  }
+  return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Get cone of influence nodes of given aig node]
+
+  Description [Get cone of influence nodes of given aig node]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAig_GetCOIForNode(Ntk_Node_t *node, st_table *table)
+{
+int i;
+Ntk_Node_t *faninNode;
+
+  if(node == NIL(Ntk_Node_t)){
+    return;
+  }
+  if (Ntk_NodeTestIsLatch(node)){
+    st_insert(table, (char *)node, (char *)node);
+    return;
+  }
+
+  Ntk_NodeForEachFanin(node, i, faninNode) {
+    bAig_GetCOIForNode(faninNode, table);
+  }
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Print cone of influence nodes of given aig node]
+
+  Description [Print cone of influence nodes of given aig node]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAig_GetCOIForNodeMain(Ntk_Network_t * network, char *name)
+{
+int i, found;
+Ntk_Node_t *node, *faninNode;
+lsGen gen;
+st_generator *gen1;
+st_table *table;
+
+  node = Ntk_NetworkFindNodeByName(network, name);
+  if(node == 0) {
+    found = 0;
+    Ntk_NetworkForEachNode(network, gen, node) {
+      if(!strcmp(Ntk_NodeReadName(node), name)) {
+	found = 1;
+	break;
+      }
+    }
+
+    if(found == 0)
+      node = 0;
+  }
+  
+  if(node == NIL(Ntk_Node_t)){
+    return;
+  }
+  if (Ntk_NodeTestIsLatch(node)){
+    fprintf(stdout, "%s\n", Ntk_NodeReadName(node));
+    return;
+  }
+
+  table = st_init_table(st_ptrcmp, st_ptrhash);
+
+  Ntk_NodeForEachFanin(node, i, faninNode) {
+    bAig_GetCOIForNode(faninNode, table);
+  }
+
+  st_foreach_item(table, gen1, &node, &node) {
+    fprintf(stdout, "%s\n", Ntk_NodeReadName(node));
+  }
+
+  st_free_table(table);
+  return;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Check status of latch]
+
+  Description [Check status of latch]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAig_CheckLatchStatus(Ntk_Network_t * network, bAig_Manager_t *manager)
+{
+Ntk_Node_t *node; 
+Ntk_Node_t *data, *init;
+lsGen gen;
+mAigMvar_t lmVar;
+mAigBvar_t lbVar;
+int tindex1, v, i, lmAigId;
+array_t   *mVarList, *bVarList;
+
+  mVarList = mAigReadMulVarList(manager);
+  bVarList = mAigReadBinVarList(manager);
+  Ntk_NetworkForEachNode(network, gen, node) {
+    if(Ntk_NodeTestIsPrimaryInput(node)) {
+      fprintf(stdout, "Primary I %s :", Ntk_NodeReadName(node));
+      lmAigId = Ntk_NodeReadMAigId(node);
+      lmVar = array_fetch(mAigMvar_t, mVarList, lmAigId);
+      for(i=0, tindex1=lmVar.bVars; i<lmVar.encodeLength; i++, tindex1++) {
+        lbVar = array_fetch(mAigBvar_t, bVarList, tindex1);
+        v = bAig_GetCanonical(manager, lbVar.node);
+	fprintf(stdout, "%d ", v);
+      }
+      fprintf(stdout, "\n");
+    }
+  }
+  Ntk_NetworkForEachNode(network, gen, node) {
+    if(Ntk_NodeTestIsPseudoInput(node)) {
+      fprintf(stdout, "Pseudo I %s :", Ntk_NodeReadName(node));
+      lmAigId = Ntk_NodeReadMAigId(node);
+      lmVar = array_fetch(mAigMvar_t, mVarList, lmAigId);
+      for(i=0, tindex1=lmVar.bVars; i<lmVar.encodeLength; i++, tindex1++) {
+        lbVar = array_fetch(mAigBvar_t, bVarList, tindex1);
+        v = bAig_GetCanonical(manager, lbVar.node);
+	fprintf(stdout, "%d ", v);
+      }
+      fprintf(stdout, "\n");
+    }
+  }
+  Ntk_NetworkForEachNode(network, gen, node) {
+    if (Ntk_NodeTestIsLatch(node)){
+      fprintf(stdout, "Latch %s :", Ntk_NodeReadName(node));
+      lmAigId = Ntk_NodeReadMAigId(node);
+      lmVar = array_fetch(mAigMvar_t, mVarList, lmAigId);
+      for(i=0, tindex1=lmVar.bVars; i<lmVar.encodeLength; i++, tindex1++) {
+        lbVar = array_fetch(mAigBvar_t, bVarList, tindex1);
+        v = bAig_GetCanonical(manager, lbVar.node);
+	fprintf(stdout, "%d ", v);
+      }
+      fprintf(stdout, "\n");
+
+      data  = Ntk_LatchReadDataInput(node);
+      fprintf(stdout, "  data input %s :", Ntk_NodeReadName(data));
+      lmAigId = Ntk_NodeReadMAigId(data);
+      lmVar = array_fetch(mAigMvar_t, mVarList, lmAigId);
+      for(i=0, tindex1=lmVar.bVars; i<lmVar.encodeLength; i++, tindex1++) {
+        lbVar = array_fetch(mAigBvar_t, bVarList, tindex1);
+        v = bAig_GetCanonical(manager, lbVar.node);
+	fprintf(stdout, "%d ", v);
+      }
+      fprintf(stdout, "\n");
+
+      init = Ntk_LatchReadInitialInput(node);
+      fprintf(stdout, "  latch init %s :", Ntk_NodeReadName(init));
+      lmAigId = Ntk_NodeReadMAigId(init);
+      lmVar = array_fetch(mAigMvar_t, mVarList, lmAigId);
+      for(i=0, tindex1=lmVar.bVars; i<lmVar.encodeLength; i++, tindex1++) {
+        lbVar = array_fetch(mAigBvar_t, bVarList, tindex1);
+        v = bAig_GetCanonical(manager, lbVar.node);
+	fprintf(stdout, "%d ", v);
+      }
+      fprintf(stdout, "\n");
+    }
+  }
+  Ntk_NetworkForEachNode(network, gen, node) {
+    lmAigId = Ntk_NodeReadMAigId(node);
+    if(lmAigId == 2 || lmAigId == 0) {
+      fprintf(stdout, "node aig id %s\n", Ntk_NodeReadName(node));
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Print status of aig node]
+
+  Description [Print status of aig node]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAig_PrintNodeAigStatus(bAig_Manager_t *manager, Ntk_Node_t *node)
+{
+mAigMvar_t lmVar;
+mAigBvar_t lbVar;
+int tindex1, v, i, lmAigId;
+array_t   *mVarList, *bVarList;
+
+  mVarList = mAigReadMulVarList(manager);
+  bVarList = mAigReadBinVarList(manager);
+  fprintf(stdout, "node %s :", Ntk_NodeReadName(node));
+  lmAigId = Ntk_NodeReadMAigId(node);
+  lmVar = array_fetch(mAigMvar_t, mVarList, lmAigId);
+  for(i=0, tindex1=lmVar.bVars; i<lmVar.encodeLength; i++, tindex1++) {
+    lbVar = array_fetch(mAigBvar_t, bVarList, tindex1);
+    v = bAig_GetCanonical(manager, lbVar.node);
+    fprintf(stdout, "%d ", v);
+  }
+  fprintf(stdout, "\n");
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Check status of aig node]
+
+  Description [Check status of aig node]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAig_PrintNodeAigStatusWithName(Ntk_Network_t * network, bAig_Manager_t *manager, char *name)
+{
+Ntk_Node_t *node;
+
+  node = Ntk_NetworkFindNodeByName(network, name);
+  bAig_PrintNodeAigStatus(manager, node);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Free timeframe ]
+
+  Description [ Free timeframe ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAig_FreeTimeFrame(bAigTimeFrame_t * timeframe)
+{
+int i; 
+long *li;
+
+   if(timeframe == 0)	return;
+
+   if(timeframe->li2index)	st_free_table(timeframe->li2index);
+   if(timeframe->o2index)	st_free_table(timeframe->o2index);
+   if(timeframe->i2index)	st_free_table(timeframe->i2index);
+   if(timeframe->pi2index)	st_free_table(timeframe->pi2index);
+   if(timeframe->latchArr)	array_free(timeframe->latchArr);
+   if(timeframe->inputArr)	array_free(timeframe->inputArr);
+   if(timeframe->outputArr)	array_free(timeframe->outputArr);
+   if(timeframe->iindexArray)	array_free(timeframe->iindexArray);
+   if(timeframe->assertedArray)	array_free(timeframe->assertedArray);
+   if(timeframe->oriLatchInputs)free(timeframe->oriLatchInputs);
+   if(timeframe->oriInputs)     free(timeframe->oriInputs);
+   if(timeframe->oribLatchInputs)free(timeframe->oribLatchInputs);
+   if(timeframe->oribInputs)     free(timeframe->oribInputs);
+
+   if(timeframe->inputs) {
+     for(i=0; i<timeframe->currentTimeframe; i++) {
+	li = timeframe->inputs[i];
+	if(li)	free(li);
+     }
+     free(timeframe->inputs);
+   }
+   if(timeframe->binputs) {
+     for(i=0; i<timeframe->currentTimeframe; i++) {
+	li = timeframe->binputs[i];
+	if(li)	free(li);
+     }
+     free(timeframe->binputs);
+   }
+   if(timeframe->outputs) {
+     for(i=0; i<timeframe->currentTimeframe; i++) {
+	li = timeframe->outputs[i];
+	if(li)	free(li);
+     }
+     free(timeframe->outputs);
+   }
+   if(timeframe->latchInputs) {
+     for(i=0; i<timeframe->currentTimeframe; i++) {
+	li = timeframe->latchInputs[i];
+	if(li)	free(li);
+     }
+     free(timeframe->latchInputs);
+   }
+   if(timeframe->blatchInputs) {
+     for(i=0; i<timeframe->currentTimeframe; i++) {
+	li = timeframe->blatchInputs[i];
+	if(li)	free(li);
+     }
+     free(timeframe->blatchInputs);
+   }
+   if(timeframe->internals) {
+     for(i=0; i<timeframe->currentTimeframe; i++) {
+	li = timeframe->internals[i];
+	if(li)	free(li);
+     }
+     free(timeframe->internals);
+   }
+}
+
Index: vis_dev/vis-2.3/src/bmc/bmc.h
===================================================================
--- vis_dev/vis-2.3/src/bmc/bmc.h	(revision 14)
+++ vis_dev/vis-2.3/src/bmc/bmc.h	(revision 14)
@@ -0,0 +1,66 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [bmc.h]
+
+  PackageName [bmc]
+
+  Synopsis    [bounded model checking (BMC) header file.]
+
+  Description []
+
+  Author      [Mohammad Awedh]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+  Revision    [$Id: bmc.h,v 1.26 2010/04/09 23:50:57 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _BMC
+#define _BMC
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "ntk.h"
+#include "ntmaig.h"
+#include "ctlspInt.h"
+#include "mcInt.h"
+#include "fsm.h"
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define BMC_INITIAL_STATES 1
+#define BMC_NO_INITIAL_STATES 0
+
+#define CirCUs 0
+#define cusp 1
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef struct BmcOption     BmcOption_t;
+typedef struct BmcCnfClauses BmcCnfClauses_t;
+typedef struct BmcCnfStates  BmcCnfStates_t; 
+typedef struct BmcCheckForTermination BmcCheckForTermination_t;
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN boolean Bmc_AbstractCheckAbstractPath(Ntk_Network_t *network, McPath_t *abstractPath, array_t *supportList, Ctlsp_Formula_t *formula);
+EXTERN void Bmc_Init(void);
+EXTERN void Bmc_End(void);
+EXTERN mdd_t * Bmc_ComputeCloseCube(mdd_t *states, mdd_t *target, int *dist, Fsm_Fsm_t *modelFsm);
+EXTERN MvfAig_Function_t * Bmc_NodeBuildMVF(Ntk_Network_t *network, Ntk_Node_t *node);
+EXTERN MvfAig_Function_t * Bmc_ReadMvfAig(Ntk_Node_t * node, st_table * nodeToMvfAigTable);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _BMC */
Index: vis_dev/vis-2.3/src/bmc/bmc.make
===================================================================
--- vis_dev/vis-2.3/src/bmc/bmc.make	(revision 14)
+++ vis_dev/vis-2.3/src/bmc/bmc.make	(revision 14)
@@ -0,0 +1,4 @@
+CSRC += bmcUtil.c bmcCmd.c bmcBmc.c bmcCirCUsUtil.c bmcCirCUs.c bmcAutSat.c bmcAutUtil.c 
+HEADERS += bmc.h bmcInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/bmc/bmcAutSat.c
===================================================================
--- vis_dev/vis-2.3/src/bmc/bmcAutSat.c	(revision 14)
+++ vis_dev/vis-2.3/src/bmc/bmcAutSat.c	(revision 14)
@@ -0,0 +1,677 @@
+/**CFile***********************************************************************
+
+  FileName    [bmcAutSat.c]
+
+  PackageName [bmc]
+ 
+  Synopsis    [Automaton for BMC]
+
+  Author      [Mohammad Awedh]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+******************************************************************************/
+
+#include "bmc.h"
+#include "bmcInt.h"
+
+static char rcsid[] UNUSED = "$Id: bmcAutSat.c,v 1.10 2005/04/16 18:02:25 awedh Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+ Synopsis [Verify the general LTL formula passes by applying the
+   termination criteria that are described in the paper "Proving More
+   Properties with Bounded Model Checking"]
+
+  Description [Check for the termination on the composition of the
+  automaton that describes the negation of the LTL formula and the
+  model.  We apply the termination criteria as described in the paper
+  "Proving More Properties with Bounded Model Checking".]
+
+  Return value:
+        -1 error in running BMC
+	 0 no action
+	 1 (m+n-1) <= options->maxK.  If no counterexample of length up to (m+n-1),
+	                              the property passes
+	 2 (m+n-1) >  options->maxK   The property is undecided if no counterexample
+	                              of length <= options->maxK.
+	 3 Pass by early termination
+  
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+BmcAutLtlCheckForTermination(
+  Ntk_Network_t            *network,
+  array_t                  *constraintArray,
+  BmcCheckForTermination_t *terminationStatus,
+  st_table                 *nodeToMvfAigTable,
+  st_table                 *CoiTable,
+  BmcOption_t              *options)
+{
+  
+  BmcCnfClauses_t *cnfClauses = NIL(BmcCnfClauses_t);
+  FILE            *cnfFile;
+  array_t         *result = NIL(array_t);
+  array_t         *unitClause = array_alloc(int, 0);
+  array_t         *orClause;
+
+  long            startTime, endTime;
+  int             k = terminationStatus->k;
+  int             returnStatus = 0;
+  Ltl_Automaton_t *automaton = terminationStatus->automaton;
+
+  /*
+    If checkLevel == 0 -->  check for beta' only and if UNSAT, m=k and chekLevel =1
+    If checkLevel == 1 -->  check for beta  only and if UNSAT, checkLevel = 2.
+    If checkLevel == 2 -->  check for alpha only and if UNSAT, n=k and checkLevel = 3.
+    If gama is UNSAT up to (m+n-1) and checkLvel = 3, formula passes.
+    checkLevel = 4 if (m+n-1) > maxK;
+   */ 
+  startTime = util_cpu_ctime();
+ 
+  /* ===========================
+     Early termination condition
+     =========================== */
+  if (options->earlyTermination) {
+    if (options->verbosityLevel == BmcVerbosityMax_c) {
+      (void) fprintf(vis_stdout, "\nChecking the early termination at k= %d\n", k);
+    }
+    /*
+      Create clauses database 
+    */
+    cnfClauses = BmcCnfClausesAlloc();
+
+    cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
+    if (cnfFile == NIL(FILE)) {
+      (void)fprintf(vis_stderr,
+		    "** bmc error: Cannot create CNF output file %s\n",
+		    options->satInFile);
+      return -1;
+    }
+    BmcAutCnfGenerateClausesForSimpleCompositePath(network, automaton, 0, k, BMC_INITIAL_STATES,
+						cnfClauses, nodeToMvfAigTable, CoiTable);
+    BmcWriteClauses(NIL(mAig_Manager_t), cnfFile, cnfClauses, options);
+    (void) fclose(cnfFile);
+    BmcCnfClausesFree(cnfClauses);
+	  
+    result = BmcCheckSAT(options);
+    if(options->satSolverError){
+      return -1;
+    }
+    if(result == NIL(array_t)) {
+      (void) fprintf(vis_stdout, "# BMC: by early ermination\n");
+      return 3;
+    }
+  } /* Early termination */
+   if((!automaton->fairSets) &&
+     (terminationStatus->checkLevel == 0)) {
+    /*
+      All the automaton states are fair states. So, beta' and beta are always UNSAT.
+    */
+    terminationStatus->m = 0;
+     (void) fprintf(vis_stdout,"Value of m = %d\n", terminationStatus->m);
+    terminationStatus->checkLevel = 2;
+  }
+  /*
+    beta''(k) 
+  */
+  if(terminationStatus->checkLevel == 0){ 
+    int i;
+    /*
+      Create clauses database 
+    */
+    cnfClauses = BmcCnfClausesAlloc();
+    if (options->verbosityLevel == BmcVerbosityMax_c) {
+      (void) fprintf(vis_stdout, "# BMC: Check Beta'' \n");
+    }
+    cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
+    if (cnfFile == NIL(FILE)) {
+      (void)fprintf(vis_stderr,
+		    "** bmc error: Cannot create CNF output file %s\n",
+		    options->satInFile);
+      return -1;
+    }
+    BmcAutCnfGenerateClausesForSimpleCompositePath(network, automaton, 0, k+1, BMC_NO_INITIAL_STATES,
+						cnfClauses, nodeToMvfAigTable, CoiTable);
+    for(i=1; i<=k+1; i++){
+      if(constraintArray != NIL(array_t)){
+	Ctlsp_Formula_t *formula;
+	int              j;
+	
+	arrayForEachItem(Ctlsp_Formula_t *, constraintArray, j, formula) {
+	  array_insert(int, unitClause, 0,
+		       - BmcGenerateCnfForLtl(network, formula, i, i, -1, cnfClauses)
+		       );
+	  BmcCnfInsertClause(cnfClauses, unitClause);
+	}
+      }
+      array_insert(int, unitClause, 0,
+		   - BmcAutGenerateCnfForBddOffSet(automaton->fairSets, i, i, cnfClauses, NIL(st_table))
+		   );
+      BmcCnfInsertClause(cnfClauses, unitClause);
+    }
+       if(constraintArray != NIL(array_t)){
+      Ctlsp_Formula_t *formula;
+      int              j;
+
+      orClause   = array_alloc(int, 0);
+      
+      arrayForEachItem(Ctlsp_Formula_t *, constraintArray, j, formula) {
+	array_insert_last(int, orClause,
+			  BmcGenerateCnfForLtl(network, formula, k+1, k+1, -1, cnfClauses)
+			  );
+      }
+      array_insert_last(int, orClause, 
+			BmcAutGenerateCnfForBddOffSet(automaton->fairSets, k+1, k+1, cnfClauses, NIL(st_table))
+			);
+      BmcCnfInsertClause(cnfClauses, orClause);
+      array_free(orClause);
+    } else {
+      array_insert(int, unitClause, 0, 
+		   BmcAutGenerateCnfForBddOffSet(automaton->fairSets, 0, 0, cnfClauses, NIL(st_table))
+		   );
+      BmcCnfInsertClause(cnfClauses, unitClause);
+    }
+    BmcWriteClauses(NIL(mAig_Manager_t), cnfFile, cnfClauses, options);
+    (void) fclose(cnfFile);
+    
+    result = BmcCheckSAT(options);
+    
+    if(options->satSolverError){
+      return -1;
+    }
+    if(result == NIL(array_t)) {
+      terminationStatus->m = k;
+      (void)fprintf(vis_stderr,"m = %d\n", terminationStatus->m);
+      terminationStatus->checkLevel = 1;
+    }
+    BmcCnfClausesFree(cnfClauses);
+  } /* Check for Beta' */
+  
+  /*
+    beta'(k) 
+  */
+  if(terminationStatus->checkLevel == 0){
+    int i;
+    /*
+      Create clauses database 
+    */
+    cnfClauses = BmcCnfClausesAlloc();
+    if (options->verbosityLevel == BmcVerbosityMax_c) {
+      (void) fprintf(vis_stdout, "# BMC: Check Beta' \n");
+    }
+    cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
+    if (cnfFile == NIL(FILE)) {
+      (void)fprintf(vis_stderr,
+		    "** bmc error: Cannot create CNF output file %s\n",
+		    options->satInFile);
+      return -1;
+    }
+    BmcAutCnfGenerateClausesForSimpleCompositePath(network, automaton, 0, k+1, BMC_NO_INITIAL_STATES,
+						cnfClauses, nodeToMvfAigTable, CoiTable);
+    for(i=0; i<=k; i++){
+      if(constraintArray != NIL(array_t)){
+	Ctlsp_Formula_t *formula;
+	int              j;
+	
+	arrayForEachItem(Ctlsp_Formula_t *, constraintArray, j, formula) {
+	  array_insert(int, unitClause, 0,
+		       - BmcGenerateCnfForLtl(network, formula, i, i, -1, cnfClauses)
+		       );
+	  BmcCnfInsertClause(cnfClauses, unitClause);
+	}
+      }
+      array_insert(int, unitClause, 0,
+		   - BmcAutGenerateCnfForBddOffSet(automaton->fairSets, i, i, cnfClauses, NIL(st_table))
+		   );
+      BmcCnfInsertClause(cnfClauses, unitClause);
+    }
+    if(constraintArray != NIL(array_t)){
+      Ctlsp_Formula_t *formula;
+      int              j;
+
+      orClause   = array_alloc(int, 0);
+      
+      arrayForEachItem(Ctlsp_Formula_t *, constraintArray, j, formula) {
+	array_insert_last(int, orClause,
+			  BmcGenerateCnfForLtl(network, formula, k+1, k+1, -1, cnfClauses)
+			  );
+      }
+      array_insert_last(int, orClause, 
+			BmcAutGenerateCnfForBddOffSet(automaton->fairSets, k+1, k+1, cnfClauses, NIL(st_table))
+			);
+      BmcCnfInsertClause(cnfClauses, orClause);
+      array_free(orClause);
+    } else {
+      array_insert(int, unitClause, 0, 
+		   BmcAutGenerateCnfForBddOffSet(automaton->fairSets, k+1, k+1, cnfClauses, NIL(st_table))
+		   );
+      BmcCnfInsertClause(cnfClauses, unitClause);
+    }
+    
+    BmcWriteClauses(NIL(mAig_Manager_t), cnfFile, cnfClauses, options);
+    (void) fclose(cnfFile);
+    
+    result = BmcCheckSAT(options);
+    
+    if(options->satSolverError){
+      return -1;
+    }
+    if(result == NIL(array_t)) {
+      terminationStatus->m = k;
+      (void)fprintf(vis_stdout,"Value of m = %d\n", terminationStatus->m);
+      terminationStatus->checkLevel = 1;
+    }
+    BmcCnfClausesFree(cnfClauses);
+  } /* Check for Beta' */
+  
+  /*
+    Check for Beta.
+  */
+  if(terminationStatus->checkLevel == 1){
+    cnfClauses = BmcCnfClausesAlloc();
+    {/* To print a witness */
+      /*  lsGen               lsGen;
+      vertex_t            *vtx;
+      Ltl_AutomatonNode_t *state;
+      int i;
+      
+      foreach_vertex(automaton->G, lsGen, vtx) {
+	state = (Ltl_AutomatonNode_t *) vtx->user_data;
+	state->cnfIndex = ALLOC(int, k+2);
+	for(i=0; i<=k+1; i++){
+	  state->cnfIndex[i] = BmcAutGenerateCnfForBddOffSet(state->Encode, i,
+							     i, cnfClauses, NIL(st_table));
+	}
+	} */
+    }/* To print a witness */
+    if (options->verbosityLevel == BmcVerbosityMax_c) {
+      (void) fprintf(vis_stdout, "# BMC: Check Beta\n");
+    }
+    
+    cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
+    if (cnfFile == NIL(FILE)) {
+      (void)fprintf(vis_stderr,
+		    "** bmc error: Cannot create CNF output file %s\n",
+		    options->satInFile);
+      return -1;
+    }
+    /*
+      Generate a simple path of length k+1.
+    */
+    BmcAutCnfGenerateClausesForSimpleCompositePath(network, automaton, 0, k+1, BMC_NO_INITIAL_STATES,
+						cnfClauses, nodeToMvfAigTable,
+						   CoiTable);
+
+    if(constraintArray != NIL(array_t)){
+      Ctlsp_Formula_t *formula;
+      int              j;
+      
+      arrayForEachItem(Ctlsp_Formula_t *, constraintArray, j, formula) {
+	array_insert(int, unitClause, 0,
+		     - BmcGenerateCnfForLtl(network, formula, k, k, -1, cnfClauses)
+		     );
+	BmcCnfInsertClause(cnfClauses, unitClause);
+      }
+    }
+    
+    array_insert(int, unitClause, 0, 
+		 - BmcAutGenerateCnfForBddOffSet(automaton->fairSets, k, k, cnfClauses, NIL(st_table))
+		 );
+    BmcCnfInsertClause(cnfClauses, unitClause);
+
+   if(constraintArray != NIL(array_t)){
+      Ctlsp_Formula_t *formula;
+      int              j;
+
+      orClause   = array_alloc(int, 0);
+      
+      arrayForEachItem(Ctlsp_Formula_t *, constraintArray, j, formula) {
+	array_insert_last(int, orClause,
+			  BmcGenerateCnfForLtl(network, formula, k+1, k+1, -1, cnfClauses)
+			  );
+      }
+      array_insert_last(int, orClause, 
+			BmcAutGenerateCnfForBddOffSet(automaton->fairSets, k+1, k+1, cnfClauses, NIL(st_table))
+			);
+      BmcCnfInsertClause(cnfClauses, orClause);
+      array_free(orClause);
+    } else { 
+      array_insert(int, unitClause, 0, 
+		   BmcAutGenerateCnfForBddOffSet(automaton->fairSets, k+1, k+1, cnfClauses, NIL(st_table))
+		   );
+      BmcCnfInsertClause(cnfClauses, unitClause);
+    }
+    
+    BmcWriteClauses(NIL(mAig_Manager_t), cnfFile, cnfClauses, options);
+    (void) fclose(cnfFile);
+    
+    result = BmcCheckSAT(options);
+    
+    if(options->satSolverError){
+      return -1;
+    }
+    if(result == NIL(array_t)) {
+      terminationStatus->checkLevel = 2;
+    }
+    BmcCnfClausesFree(cnfClauses);
+  } /* Check Beta*/
+  
+  if(terminationStatus->checkLevel == 2){ /* we check Alpha if Beta is unsatisfiable */
+
+    if (options->verbosityLevel == BmcVerbosityMax_c) {
+      (void) fprintf(vis_stdout, "# BMC: Check Alpha \n");
+    }
+    
+    cnfClauses = BmcCnfClausesAlloc();
+      
+    cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
+    if (cnfFile == NIL(FILE)) {
+      (void)fprintf(vis_stderr,
+		    "** bmc error: Cannot create CNF output file %s\n",
+		    options->satInFile);
+      return -1;
+    }
+    
+    BmcAutCnfGenerateClausesForSimpleCompositePath(network, automaton, 0, k, BMC_INITIAL_STATES,
+						cnfClauses, nodeToMvfAigTable, CoiTable);
+    if(automaton->fairSets){
+
+      if(constraintArray != NIL(array_t)){
+	Ctlsp_Formula_t *formula;
+	int              j;
+	
+	orClause   = array_alloc(int, 0);
+	
+	arrayForEachItem(Ctlsp_Formula_t *, constraintArray, j, formula) {
+	  array_insert_last(int, orClause,
+			    BmcGenerateCnfForLtl(network, formula, k, k, -1, cnfClauses)
+			    );
+	}
+	array_insert_last(int, orClause, 
+			  BmcAutGenerateCnfForBddOffSet(automaton->fairSets, k, k, cnfClauses, NIL(st_table))
+			  );
+	BmcCnfInsertClause(cnfClauses, orClause);
+	array_free(orClause);
+      } else {
+	
+	array_insert(int, unitClause, 0,  
+		     BmcAutGenerateCnfForBddOffSet(automaton->fairSets, k, k, cnfClauses, NIL(st_table))
+		     );
+	BmcCnfInsertClause(cnfClauses, unitClause);
+      }
+    }
+    BmcWriteClauses(NIL(mAig_Manager_t), cnfFile, cnfClauses, options);
+    (void) fclose(cnfFile);
+    
+    result = BmcCheckSAT(options);
+    BmcCnfClausesFree(cnfClauses);
+    if(options->satSolverError){
+      return -1;
+    }
+    if(result == NIL(array_t)) {
+      terminationStatus->n = k;
+      terminationStatus->checkLevel = 3;
+      (void)fprintf(vis_stderr,"m=%d  n=%d\n",terminationStatus->m,terminationStatus->n);
+      if ((terminationStatus->m+terminationStatus->n-1) <= options->maxK){
+	terminationStatus->k = terminationStatus->m+terminationStatus->n-1;
+	if(k==0){
+	  /*
+	    By induction, the property passes.
+	  */
+	  terminationStatus->k = 0;
+	}
+	returnStatus = 1;
+      } else {
+	terminationStatus->checkLevel = 4;
+	returnStatus = 2;
+      }
+    }
+  }/* Chek for Alpha */
+  
+  array_free(unitClause);
+
+  if (options->verbosityLevel != BmcVerbosityNone_c) {
+    endTime = util_cpu_ctime();
+    fprintf(vis_stdout, "-- Check for termination time time = %10g\n",
+	    (double)(endTime - startTime) / 1000.0);
+  }
+
+  return returnStatus;
+ 
+} /* BmcAutLtlCheckForTermination */
+
+
+/**Function********************************************************************
+
+  Synopsis [Generate CNF clauses that describe a path in the automaton.] 
+
+  Description [Generate CNF clauses for a path in the automaton
+  starting from "fromState" and ending at "toState". If "initialState"
+  = BMC_INITIAL_STATES, the the path starts from an initial state.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+BmcAutCnfGenerateClausesForPath(
+  Ltl_Automaton_t *automaton,
+  int             fromState,
+  int             toState,
+  int             initialState,
+  BmcCnfClauses_t *cnfClauses)
+{
+  int          k;
+  array_t      *unitClause = array_alloc(int, 1);
+
+  if(initialState){
+    array_insert(int, unitClause, 0, 
+		 BmcAutGenerateCnfForBddOffSet(automaton->initialStates, 0, 0, cnfClauses, automaton->nsPsTable)
+		 );
+    BmcCnfInsertClause(cnfClauses, unitClause);
+  }
+  for(k=fromState; k<toState; k++){
+    array_insert(int, unitClause, 0,  
+    BmcAutGenerateCnfForBddOffSet(automaton->transitionRelation, k, k+1, cnfClauses, automaton->nsPsTable)
+		      );
+    BmcCnfInsertClause(cnfClauses, unitClause);
+  }
+  array_free(unitClause);
+  
+} /* BmcAutCnfGenerateClausesForPath() */
+
+
+/**Function********************************************************************
+
+  Synopsis [Generate CNF clauses for a simple path in the composite
+  model]
+
+  Description [This function generates CNF clauses for a simple path
+  from state "fromState" to state "toState" in the composition of
+  network and automaton.  A simple path is a path along which every
+  state in the path is distinct.  If Si and Sj in the path then Si !=
+  Sj.
+
+  If the value of "initialState" is BMC_INITIAL_STATES, then the path
+  is an initialized path.  Otherwise "initialState" is
+  BMC_NO_INITIAL_STATES.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+BmcAutCnfGenerateClausesForSimpleCompositePath(
+   Ntk_Network_t   *network,
+   Ltl_Automaton_t *automaton,
+   int             fromState,
+   int             toState,
+   int             initialState,
+   BmcCnfClauses_t *cnfClauses,
+   st_table        *nodeToMvfAigTable,
+   st_table        *CoiTable)
+{
+  int state;
+  
+  /*
+    Generate clauses for a path from fromState to toState in the original model.
+  */
+  BmcCnfGenerateClausesForPath(network, fromState, toState, initialState, cnfClauses, nodeToMvfAigTable, CoiTable);
+  /*
+    Generate clauses for a path from fromState to toState in the Automaton.
+  */
+  BmcAutCnfGenerateClausesForPath(automaton, fromState, toState, initialState, cnfClauses);
+  
+  /*
+    Restrict the above path to be simpe path.
+  */
+  for(state= fromState + 1; state < toState; state++){
+    BmcCnfNoLoopToAnyPreviouseCompositeStates(network, automaton, fromState, state,
+					      cnfClauses, nodeToMvfAigTable, CoiTable);
+  }
+
+  return;
+} /* BmcAutCnfGenerateClausesForSimpleCompositePath */
+
+
+/**Function********************************************************************
+
+  Synopsis [Generate CNF clauses for no loop from last state to any of
+  the previouse states of the path]
+
+  Description [Generate CNF clauses for no loop from last state
+  "toState" to any of the previous states starting from
+  "fromState". It generates the CNF clauses such that the last state
+  of the path is not equal to any previous states.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+BmcCnfNoLoopToAnyPreviouseCompositeStates(
+   Ntk_Network_t   *network,
+   Ltl_Automaton_t *automaton,
+   int             fromState,
+   int             toState,
+   BmcCnfClauses_t *cnfClauses,
+   st_table        *nodeToMvfAigTable,
+   st_table        *CoiTable)
+{
+  mAig_Manager_t     *manager   = Ntk_NetworkReadMAigManager(network);
+  bdd_manager        *bddManager = bdd_get_manager(automaton->transitionRelation);
+  
+  Ntk_Node_t         *latch;
+  MvfAig_Function_t  *latchMvfAig;
+  bAigEdge_t         *latchBAig;
+  array_t            *orClause;
+  int                currentIndex, nextIndex, andIndex1, andIndex2;  
+  int                i, k, mvfSize, bddID;
+    
+  st_generator       *stGen;
+
+  /*
+    Generates CNF clauses to constrain that the toState is not equal
+    to any previouse states starting from fromState.
+    
+    Assume there are two state varaibles a and b. To check if Si !=
+    Sj, we must generate clauses for the formula ( ai != aj + bi !=
+    bj).
+  */
+  for(k=fromState; k < toState; k++){
+    orClause = array_alloc(int,0);
+    st_foreach_item(CoiTable, stGen, &latch, NULL) {
+      
+  
+      latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+      if (latchMvfAig ==  NIL(MvfAig_Function_t)){
+	latchMvfAig = Bmc_NodeBuildMVF(network, latch);
+	array_free(latchMvfAig);
+	latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+      } 
+      mvfSize   = array_n(latchMvfAig);
+      latchBAig = ALLOC(bAigEdge_t, mvfSize);   
+      
+      for(i=0; i< mvfSize; i++){
+	latchBAig[i] = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(latchMvfAig, i));
+      }
+
+      for (i=0; i< mvfSize; i++){
+	currentIndex = BmcGenerateCnfFormulaForAigFunction(manager, latchBAig[i], k       ,cnfClauses);
+	nextIndex = BmcGenerateCnfFormulaForAigFunction(manager, latchBAig[i], toState ,cnfClauses);	 
+	andIndex1 = cnfClauses->cnfGlobalIndex++;
+	BmcCnfGenerateClausesForAND(currentIndex, -nextIndex, andIndex1, cnfClauses);
+	andIndex2 = cnfClauses->cnfGlobalIndex++;
+	BmcCnfGenerateClausesForAND(-currentIndex, nextIndex, andIndex2, cnfClauses);
+
+	array_insert_last(int, orClause, andIndex1);
+	array_insert_last(int, orClause, andIndex2);
+      }
+      FREE(latchBAig);
+    }/* For each latch loop*/
+    st_foreach_item(automaton->psNsTable, stGen, &bddID, NULL) {
+      currentIndex = BmcGetCnfVarIndexForBddNode(bddManager, bdd_regular(bdd_bdd_ith_var(bddManager, bddID)),
+						 k, cnfClauses);
+      nextIndex    = BmcGetCnfVarIndexForBddNode(bddManager, bdd_regular(bdd_bdd_ith_var(bddManager, bddID)),
+						 toState, cnfClauses);
+      						 
+      andIndex1 = cnfClauses->cnfGlobalIndex++;
+      BmcCnfGenerateClausesForAND(currentIndex, -nextIndex, andIndex1, cnfClauses);
+      andIndex2 = cnfClauses->cnfGlobalIndex++;
+      BmcCnfGenerateClausesForAND(-currentIndex, nextIndex, andIndex2, cnfClauses);
+      
+      array_insert_last(int, orClause, andIndex1);
+      array_insert_last(int, orClause, andIndex2);
+    }
+    BmcCnfInsertClause(cnfClauses, orClause);
+    array_free(orClause);
+  } /* foreach k*/
+  return;
+} /* BmcCnfNoLoopToAnyPreviouseCompositeStates */
Index: vis_dev/vis-2.3/src/bmc/bmcAutUtil.c
===================================================================
--- vis_dev/vis-2.3/src/bmc/bmcAutUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/bmc/bmcAutUtil.c	(revision 14)
@@ -0,0 +1,932 @@
+/**CFile***********************************************************************
+
+  FileName    [bmcAutUtil.c]
+
+  PackageName [bmc]
+ 
+  Synopsis    [Utility file for BMC_Automaton]
+
+  Author      [Mohammad Awedh]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+******************************************************************************/
+
+#include "bmc.h"
+#include "bmcInt.h"
+
+static char rcsid[] UNUSED = "$Id: bmcAutUtil.c,v 1.18 2005/05/18 18:11:52 jinh Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static st_table * AutomatonVertexGetImg(graph_t *G, vertex_t *vtx);
+static st_table * AutomatonVertexGetPreImg(graph_t *G, vertex_t *vtx);
+static int stIntersect(st_table *tbl1, st_table *tbl2);
+static int NoOfBitEncode(int n);
+static bdd_t * encodeOfInteger(mdd_manager *manager, array_t *varArray, int val);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Encode the states of the Automaton.] 
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+BmcAutEncodeAutomatonStates(
+  Ntk_Network_t   *network,
+  Ltl_Automaton_t *automaton)
+{
+  mdd_manager	      *manager = Ntk_NetworkReadMddManager(network);
+  lsGen               lsGen, lsGen1;
+  vertex_t            *vtx;
+  Ltl_AutomatonNode_t *node, *node1;
+  Ctlsp_Formula_t     *F;
+  mdd_t               *label;
+  
+  int                 i;
+
+  /*
+    Build the mdd of the labels of each automaton node
+   */
+  foreach_vertex(automaton->G, lsGen, vtx) {
+    node = (Ltl_AutomatonNode_t *) vtx->user_data;
+    if (node->Labels) {
+      label =  mdd_one(manager);
+      for (i=0; i<array_n(automaton->labelTable); i++) {
+	if (LtlSetGetElt(node->Labels, i)) {
+	  F = array_fetch(Ctlsp_Formula_t *, automaton->labelTable, i);
+	  label = mdd_and(label, BmcAutBuildMddForPropositionalFormula(network, automaton, F), 1, 1);
+	}
+      }
+      node->Encode = label;
+    }
+  }
+  /*
+    Encode automaton labels
+   */
+  foreach_vertex(automaton->G, lsGen, vtx) {
+    bdd_t *newVar = NULL;
+    
+    node = (Ltl_AutomatonNode_t *) vtx->user_data;
+    foreach_vertex(automaton->G, lsGen1, vtx) {
+      node1 = (Ltl_AutomatonNode_t *) vtx->user_data;
+      if(node != node1){
+	if(newVar == NULL){
+	  newVar = bdd_create_variable(manager);
+	  node->Encode = bdd_and(node->Encode, newVar, 1, 1);
+	}
+	node1->Encode = bdd_and(node1->Encode, bdd_not(newVar), 1, 1);
+      }
+    }
+  }
+} /* BmcAutEncodeAutomatonStates() */
+
+
+/**Function********************************************************************
+
+  Synopsis [Encode the states of the Automaton.] 
+
+  Description [The labels of each node in the automaton are
+  propositional and are asserted by state variables in the original
+  model. So, we uses these labels as part of the state encoding of the
+  automaton.  If two nodes cannot be uniquely specified, then we use
+  new variables]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+BmcAutEncodeAutomatonStates2(
+  Ntk_Network_t   *network,
+  Ltl_Automaton_t *automaton)
+{
+  mdd_manager	      *manager = Ntk_NetworkReadMddManager(network);
+  lsGen               lsGen, lsGen1;
+  vertex_t            *vtx;
+  Ltl_AutomatonNode_t *node, *node1;
+  Ctlsp_Formula_t     *F;
+  mdd_t               *label;
+  
+  int                 i;
+ 
+  /*
+    Build the mdd for the labels of each automaton node.
+   */
+  foreach_vertex(automaton->G, lsGen, vtx) {
+    node = (Ltl_AutomatonNode_t *) vtx->user_data;
+    if (node->Labels) {
+      label =  mdd_one(manager);
+      for (i=0; i<array_n(automaton->labelTable); i++) {
+	if (LtlSetGetElt(node->Labels, i)) {
+	  F = array_fetch(Ctlsp_Formula_t *, automaton->labelTable, i); 
+	  label = mdd_and(label, BmcAutBuildMddForPropositionalFormula(network, automaton, F), 1, 1);
+	}
+      }
+      node->Encode = label;
+    }
+  }
+  /*
+    Three cases:
+      1- node and node1 are both = 1
+      2- node1 = 1
+      3- neither node nor nod1 equal to 1
+   */
+  foreach_vertex(automaton->G, lsGen, vtx) {
+    bdd_t *newVar = NULL;
+    st_table        *preState, *preState1;
+   
+    node = (Ltl_AutomatonNode_t *) vtx->user_data;
+    preState  = AutomatonVertexGetPreImg(automaton->G, vtx);
+
+    foreach_vertex(automaton->G, lsGen1, vtx) {  
+      node1 = (Ltl_AutomatonNode_t *) vtx->user_data;
+      if(node != node1){
+	if (!mdd_is_tautology(mdd_and(node->Encode, node1->Encode, 1,1),0)){
+	  preState1 = AutomatonVertexGetPreImg(automaton->G, vtx);
+	  if (stIntersect(preState, preState1)){
+	    if(mdd_equal(node->Encode, mdd_one(manager)) && !mdd_equal(node1->Encode, mdd_one(manager))){
+	      node->Encode = bdd_not(node1->Encode);
+	    } else
+	      if(mdd_equal(node1->Encode, mdd_one(manager)) && !mdd_equal(node->Encode, mdd_one(manager))){
+		node1->Encode = bdd_not(node->Encode);
+	      } else {
+		if(newVar == NULL){
+		  newVar = bdd_create_variable(manager);
+		}
+		node1->Encode = bdd_and(node1->Encode, bdd_not(newVar), 1, 1);
+		node->Encode = bdd_and(node->Encode, bdd_not(node1->Encode), 1, 1);
+	      }
+	  } else {
+	    if(newVar == NULL){
+	      newVar = bdd_create_variable(manager);
+	      node->Encode = bdd_and(node->Encode, newVar, 1, 1);
+	    }
+	    node1->Encode = bdd_and(node1->Encode,  bdd_not(newVar), 1, 1);
+	  }
+	}
+      }
+    }
+  }
+
+#if 0  
+  /*
+    Encode the automaton labels
+   */
+  foreach_vertex(automaton->G, lsGen, vtx) {
+    bdd_t               *newVar = NULL;
+    st_table            *nextStates;
+    Ltl_AutomatonNode_t *nextState;
+    st_generator        *stGen;
+    
+    node       = (Ltl_AutomatonNode_t *) vtx->user_data;
+    nextStates = AutomatonVertexGetImg(automaton->G, vtx);
+    
+    st_foreach_item(nextStates, stGen, (char **)&vtx, NIL(char *)) {
+      nextState = (Ltl_AutomatonNode_t *) vtx->user_data;
+
+      if(node != nextState){
+	if (!mdd_is_tautology(mdd_and(node->Encode, nextState->Encode, 1,1),0)){
+	  printf("n%d intersects n%d\n", node->index, nextState->index);
+	  if(newVar == NULL){
+	    newVar = bdd_create_variable(manager);
+	    /*node->Encode = bdd_and(node->Encode, newVar, 1, 1);*/
+	  }
+	  nextState->Encode = bdd_and(nextState->Encode, bdd_not(newVar), 1, 1);
+	  node->Encode = bdd_and(node->Encode, bdd_not(nextState->Encode), 1, 1);
+	}
+      }
+    }
+  }
+#endif
+  
+} /* BmcAutEncodeAutomatonStates2() */
+
+/**Function********************************************************************
+
+  Synopsis [Encode the states of the Automaton.] 
+
+  Description [The labels of each node in the automaton are
+  propositional and are asserted by state variables in the original
+  model. So, we uses these labels as part of the state encoding of the
+  automaton.  If two nodes cannot be uniquely specified, then we use
+  new variables]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+BmcAutEncodeAutomatonStates3(
+  Ntk_Network_t   *network,
+  Ltl_Automaton_t *automaton)
+{
+  mdd_manager	      *manager = Ntk_NetworkReadMddManager(network);
+  lsGen               lsGen;
+  st_generator        *stGen, *stGen1;
+  vertex_t            *vtx, *vtx1;
+  Ltl_AutomatonNode_t *node, *node1;
+  Ctlsp_Formula_t     *F;
+  bdd_t               *label;
+  
+  int                 i;
+  int                 noOfStates=0;
+  int                 noOfBits;
+  array_t             *varArray = array_alloc(bdd_t*,0);
+
+  /*
+    Build the bdd for the labels of each automaton node.
+   */
+  foreach_vertex(automaton->G, lsGen, vtx) {
+    node = (Ltl_AutomatonNode_t *) vtx->user_data;
+    if (node->Labels) {
+      noOfStates++;
+      label =  bdd_one(manager);
+      for (i=0; i<array_n(automaton->labelTable); i++) {
+	if (LtlSetGetElt(node->Labels, i)) {
+	  F = array_fetch(Ctlsp_Formula_t *, automaton->labelTable, i); 
+	  label = bdd_and(label, BmcAutBuildMddForPropositionalFormula(network, automaton, F), 1, 1);
+	}
+      }
+      node->Encode = label;
+    }
+  }
+
+  st_foreach_item(automaton->Init, stGen, &vtx, NULL) {
+    node = (Ltl_AutomatonNode_t *) vtx->user_data;
+    st_foreach_item(automaton->Init, stGen1, &vtx1, NULL) {
+      node1 = (Ltl_AutomatonNode_t *) vtx1->user_data;
+      if(node != node1){
+	if(mdd_equal(node->Encode, mdd_one(manager)) && !mdd_equal(node1->Encode, mdd_one(manager))){
+	      node->Encode = bdd_not(node1->Encode);
+	} else
+	  if(mdd_equal(node1->Encode, mdd_one(manager)) && !mdd_equal(node->Encode, mdd_one(manager))){
+	    node1->Encode = bdd_not(node->Encode);
+	  }
+      }
+    }
+  }
+
+  noOfBits = NoOfBitEncode(noOfStates);
+  for(i=0; i< noOfBits; i++){ 
+    array_insert_last(bdd_t*, varArray, bdd_create_variable(manager));
+  }
+  i=0;
+  foreach_vertex(automaton->G, lsGen, vtx) {
+    node = (Ltl_AutomatonNode_t *) vtx->user_data;
+    if (node->Labels) {
+      node->Encode = bdd_and(node->Encode, encodeOfInteger(manager, varArray, i), 1, 1);
+      i++;
+    }
+  }
+} /* BmcAutEncodeAutomatonStates3() */
+
+
+/**Function********************************************************************
+
+  Synopsis [Build BDD of the transition relation of the Automaton.] 
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+BmcAutBuildTransitionRelation(
+  Ntk_Network_t   *network,
+  Ltl_Automaton_t *automaton)
+{
+  mdd_manager	      *manager = Ntk_NetworkReadMddManager(network);
+  lsGen               lsGen;
+  st_generator        *stGen;
+  vertex_t            *vtx, *vtx1;
+  Ltl_AutomatonNode_t *state, *nextState;
+ 
+  
+  
+  bdd_t               *nextStateBdd, *transitionRelation;
+  bdd_t               *initialState, *fairSet, *fairState;
+  int                 i;
+  bdd_t               *bddVar;
+  st_table            *nextStates;
+  var_set_t           *psSupport, *nsSupport;
+  st_table            *FairSet = 0;
+  array_t             *fairSetArray;
+
+  /*
+    psNsTable  (Bdd Id, bdd_t*)
+   */
+  st_table            *psNsTable = st_init_table(st_numcmp, st_numhash);
+  /*
+    nsPsTable  (BDD Id, BDD Id)
+   */
+  st_table            *nsPsTable = st_init_table(st_numcmp, st_numhash);
+
+  boolean             isComplemented;
+  int                 nodeIndex;
+  
+  /*
+    Initialization
+   */
+  transitionRelation = bdd_zero(manager);
+
+  /*
+    Build the transition relation 
+   */
+  foreach_vertex(automaton->G, lsGen, vtx) {
+    state = (Ltl_AutomatonNode_t *) vtx->user_data;
+    /*
+      support is the set of the bddId of the bdd node in the support of the bdd function. 
+    */
+    psSupport = bdd_get_support(state->Encode);
+    for(i=0; i<psSupport->n_elts; i++) {
+      if (var_set_get_elt(psSupport, i) == 1) {
+	/*
+	  i is the bdd Id of the variable in the support of the function.
+	*/
+	if (!st_lookup(psNsTable, (char *)(long) i, NULL)){
+	  bddVar =  bdd_create_variable(manager);
+	  nodeIndex = bdd_node_read_index(bdd_get_node(bddVar, &isComplemented));
+	  st_insert(psNsTable, (char *) (long) i,         (char *) bddVar);
+	  st_insert(nsPsTable, (char *) (long) nodeIndex, (char *) (long)i);
+	}
+      }
+    }
+    /*
+      Get the next states.
+     */
+    nextStates = AutomatonVertexGetImg(automaton->G, vtx);
+    st_foreach_item(nextStates, stGen, &vtx1, NULL) {
+      nextState = (Ltl_AutomatonNode_t *) vtx1->user_data;
+
+      nextStateBdd = bdd_dup(nextState->Encode);
+      nsSupport = bdd_get_support(nextStateBdd);
+      for(i=0; i<nsSupport->n_elts; i++) {
+	if (var_set_get_elt(nsSupport, i) == 1) {
+	  bdd_t *tmp;
+
+	  if (!st_lookup(psNsTable, (char *)(long)i, &bddVar)){
+	    bddVar =  bdd_create_variable(manager);
+	    nodeIndex = bdd_node_read_index(bdd_get_node(bddVar, &isComplemented));
+	    st_insert(psNsTable, (char *) (long) i,         (char *) bddVar);
+	    st_insert(nsPsTable, (char *) (long) nodeIndex, (char *) (long)i);
+	  }	  
+	  tmp = nextStateBdd;
+	  nextStateBdd = bdd_compose(nextStateBdd, bdd_get_variable(manager, i), bddVar);
+	  bdd_free(tmp);
+	}
+      }
+      transitionRelation = bdd_or(transitionRelation, bdd_and(state->Encode, nextStateBdd,1 ,1) ,1 ,1);
+      
+    } /* for each next states*/
+  } /* for each present state */
+
+  fairSetArray = array_alloc(bdd_t*, 0);
+  fairSet = 0;
+  if (lsLength(automaton->Fair) != 0) {
+    fairSet = bdd_zero(manager);
+    lsForEachItem(automaton->Fair, lsGen, FairSet) {
+      fairState = bdd_zero(manager);
+      st_foreach_item(FairSet, stGen, &vtx, NULL) {
+	state = (Ltl_AutomatonNode_t *) vtx->user_data;
+	fairState = bdd_or(fairState, state->Encode,1,1);
+      }
+      array_insert_last(bdd_t*, fairSetArray, fairState); 
+      fairSet = bdd_or(fairSet, fairState,1,1);
+    }
+  }
+  initialState = bdd_zero(manager);
+  st_foreach_item(automaton->Init, stGen, &vtx, NULL) {
+    state = (Ltl_AutomatonNode_t *) vtx->user_data;
+    initialState = bdd_or(initialState, state->Encode, 1, 1);
+  }
+  automaton->transitionRelation  = transitionRelation;
+  automaton->initialStates       = initialState;
+  automaton->fairSets            = fairSet;
+  automaton->psNsTable           = psNsTable;
+  automaton->nsPsTable           = nsPsTable;
+  automaton->fairSetArray        = fairSetArray;
+  
+} /* BmcAutBuildTransitionRelation() */
+
+
+/**Function********************************************************************
+
+  Synopsis [Build MDD for a propositional formula.] 
+
+  Description [Build MDD for a propositional formula. Returns NIL if the conversion
+  fails. The calling application is responsible for freeing the returned MDD.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+mdd_t *
+BmcAutBuildMddForPropositionalFormula(
+   Ntk_Network_t   *network,
+   Ltl_Automaton_t *automaton,
+   Ctlsp_Formula_t *formula)
+{
+  mdd_manager	  *manager = Ntk_NetworkReadMddManager(network);
+  mdd_t           *left, *right, *result;
+  
+
+  if (formula == NIL(Ctlsp_Formula_t)) {
+    return NIL(mdd_t);
+  }
+  if (formula->type == Ctlsp_TRUE_c){
+    return bdd_one(manager);
+  }
+  if (formula->type == Ctlsp_FALSE_c){
+    return  mdd_zero(manager);
+  }
+  
+  if (!Ctlsp_isPropositionalFormula(formula)) {
+    (void) fprintf(vis_stderr, "bmc error: Only propositional formula can be converted to bdd \n");
+    fprintf(vis_stdout, "\nFormula: ");
+    Ctlsp_FormulaPrint(vis_stdout, formula);
+    fprintf(vis_stdout, "\n");
+    return NIL(mdd_t);
+  }
+  /*
+    Atomic proposition.
+   */
+  if (formula->type == Ctlsp_ID_c){
+    int       is_complemented;
+    bdd_node  *funcNode;
+    
+    result   =  BmcModelCheckAtomicFormula(Fsm_NetworkReadOrCreateFsm(network), formula);
+    funcNode = bdd_get_node(result, &is_complemented);
+    if(is_complemented){
+      funcNode = bdd_not_bdd_node(funcNode);
+    }
+    return result;
+  }
+  /*
+    right can be NIL(mdd_t) for unery operators, but left can't be  NIL(mdd_t)
+   */
+  left  = BmcAutBuildMddForPropositionalFormula(network, automaton, formula->left);
+  if (left == NIL(mdd_t)){
+    return NIL(mdd_t);
+  }  
+  right = BmcAutBuildMddForPropositionalFormula(network, automaton, formula->right);
+  /*assert(right !=  NIL(mdd_t)); */
+  switch(formula->type) {
+    case Ctlsp_NOT_c:
+      result = mdd_not(left);
+      break;
+    case Ctlsp_OR_c:
+      result = mdd_or(left, right, 1, 1);
+      break;
+    case Ctlsp_AND_c:
+      result = mdd_and(left, right, 1, 1);
+      break;
+    case Ctlsp_THEN_c:
+      result = mdd_or(left, right, 0, 1); 
+      break;
+    case Ctlsp_EQ_c:
+      result = mdd_xnor(left, right);
+      break;
+    case Ctlsp_XOR_c:
+      result = mdd_xor(left, right);
+      break;
+  default:
+    /*
+      return NIL(mdd_t) if the type is not supported
+     */
+    fail("Unexpected type");
+  }
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Generate CNF for a given BDD function.]
+
+  Description [Generate CNF for a BDD function.  This function first
+  negates the BDD function, and then generates the CNF corresponding
+  to the OFF-set of the negated function.  If the BDD node is a next
+  state variable, we use the BDD index of the present state variable
+  corresponding to this variable.  We could do this by searching the
+  nsPSTable.  If trans ==1, this function generates a CNF for a
+  transition from current state to next state, otherwise it generates
+  CNF for NO transition.
+
+  The function calling this function must add a unit clause to set the
+  returned value to positive (for function to be true) or negative
+  (for function to be false).
+
+  ]
+  
+  SideEffects []
+
+  SeeAlso     []
+  
+******************************************************************************/
+int 
+BmcAutGenerateCnfForBddOffSet(
+   bdd_t          *function,
+   int             current,
+   int             next,
+   BmcCnfClauses_t *cnfClauses,
+   st_table        *nsPsTable)
+{
+  bdd_manager *bddManager = bdd_get_manager(function);
+  bdd_node    *node, *funcNode;
+  int         is_complemented;
+  bdd_gen     *gen;
+  int         varIndex; 
+  array_t     *tmpClause;
+  array_t     *cube;
+  int         i, value;
+  int         state = current;
+  bdd_t       *bddFunction;
+  bdd_t       *newVar;
+
+  int         total=0, ndc=0;
+  float       per;
+
+  if (function == NULL){
+    return 0;
+  }
+ 
+  funcNode = bdd_get_node(function, &is_complemented);
+ 
+  if (bdd_is_constant(funcNode)){
+    if (is_complemented){
+      /* add an empty clause to indicate FALSE (un-satisfiable)*/
+      BmcAddEmptyClause(cnfClauses);
+    }
+    /*bdd_free(bddFunction);
+      bdd_free(newVar);*/
+    return 0;
+  }
+
+  newVar = bdd_create_variable(bddManager);
+  bddFunction = bdd_xnor(newVar, function);
+  bddFunction = bdd_not(bddFunction);
+
+  foreach_bdd_cube(bddFunction, gen, cube){
+    tmpClause = array_alloc(int,0);
+    arrayForEachItem(int, cube, i, value) {
+      total++;
+      if (value != 2){
+	int j;
+
+	ndc++;
+	/*
+	  If the BDD varaible is a next state varaible, we use the corresponding
+	  current state varaible but with next state index.
+	 */
+	
+	if (nsPsTable && st_lookup_int(nsPsTable, (char *)(long)i, &j)){
+	  node = bdd_bdd_ith_var(bddManager, j);
+	  state = next;
+	} else {
+	  node = bdd_bdd_ith_var(bddManager, i);
+	  state = current;
+	}
+	varIndex  = BmcGetCnfVarIndexForBddNode(bddManager, bdd_regular(node), state, cnfClauses);
+	if (value == 1){
+	  varIndex = -varIndex; 
+	}
+	array_insert_last(int, tmpClause, varIndex);
+      }
+    }
+    BmcCnfInsertClause(cnfClauses, tmpClause);
+    array_free(tmpClause);
+  }/* foreach_bdd_cube() */
+  varIndex  = BmcGetCnfVarIndexForBddNode(bddManager,
+				       bdd_regular(bdd_get_node(newVar, &is_complemented)),
+				       current, cnfClauses);
+  per = ((float) ((float)ndc/(float)total))*100; 
+  return (varIndex);
+} /* BmcAutGenerateCnfForBddOffSet() */
+
+
+/**Function********************************************************************
+
+  Synopsis [Alloc Memory for BmcCheckForTermination_t]
+
+  SideEffects []
+
+  SeeAlso []
+******************************************************************************/
+BmcCheckForTermination_t *
+BmcAutTerminationAlloc(
+  Ntk_Network_t   *network,
+  Ctlsp_Formula_t *ltlFormula,
+  array_t         *constraintArray)
+{
+  BmcCheckForTermination_t  *result = ALLOC(BmcCheckForTermination_t, 1);
+  Ltl_Automaton_t           *automaton;
+  LtlMcOption_t             *ltlOptions = LtlMcOptionAlloc();
+  
+  if (!result){
+    return result;
+  }
+  /*
+    Build the Buechi Automaton for the negation of the LTL formula.
+  */
+  ltlOptions->algorithm    = Ltl2Aut_WRING_c;
+  ltlOptions->rewriting    = TRUE;
+  ltlOptions->prunefair    = TRUE;
+  ltlOptions->iocompatible = TRUE;
+  ltlOptions->directsim    = TRUE;
+  ltlOptions->reversesim   = TRUE;
+  ltlOptions->verbosity    = McVerbosityNone_c;
+  ltlOptions->noStrengthReduction = 1;
+  
+  automaton  = LtlMcFormulaToAutomaton(network, ltlFormula, ltlOptions, 0);
+  assert(automaton != NIL(Ltl_Automaton_t));
+  
+  /*BmcAutEncodeAutomatonStates(network, automaton); */
+  /*mcAutEncodeAutomatonStates2(network, automaton);*/
+  BmcAutEncodeAutomatonStates3(network, automaton);
+  BmcAutBuildTransitionRelation(network, automaton);
+    
+  LtlMcOptionFree(ltlOptions);
+
+  result->k = 0;
+  result->m = -1;
+  result->n = -1;
+  result->checkLevel = 0;
+  result->action = 0;
+  result->automaton = automaton;
+
+  result->externalConstraints  = NIL(Ctlsp_Formula_t);
+  if(constraintArray != NIL(array_t)){
+    Ctlsp_Formula_t *formula1, *formula2;
+    int              j;
+    
+    formula1 = NIL(Ctlsp_Formula_t);
+    arrayForEachItem(Ctlsp_Formula_t *, constraintArray, j, formula2) {
+      formula2 = Ctlsp_FormulaDup(formula2);
+      if(formula1 == NIL(Ctlsp_Formula_t)) {
+	formula1 = formula2;
+      } else {
+	formula1 =  Ctlsp_FormulaCreate(Ctlsp_OR_c, formula1, formula2);
+      }
+    }
+    result->externalConstraints = formula1;
+  }
+  result->internalConstraints = automaton->fairSets;
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Convert LTL to Automaton]
+
+  Description []
+  SideEffects []
+
+  SeeAlso []
+******************************************************************************/
+Ltl_Automaton_t *
+BmcAutLtlToAutomaton(
+  Ntk_Network_t   *network,
+  Ctlsp_Formula_t *ltlFormula)
+{
+  Ltl_Automaton_t  *automaton;
+  LtlMcOption_t    *ltlOptions = LtlMcOptionAlloc();
+  
+  /*
+    Build the Buechi Automaton for the negation of the LTL formula.
+  */
+  ltlOptions->algorithm    = Ltl2Aut_WRING_c;
+  ltlOptions->rewriting    = TRUE;
+  ltlOptions->prunefair    = TRUE;
+  ltlOptions->iocompatible = TRUE;
+  ltlOptions->directsim    = TRUE;
+  ltlOptions->reversesim   = TRUE;
+  ltlOptions->verbosity    = McVerbosityNone_c;
+  ltlOptions->noStrengthReduction = 1;
+  
+  automaton  = LtlMcFormulaToAutomaton(network, ltlFormula, ltlOptions, 0);
+  assert(automaton != NIL(Ltl_Automaton_t));
+ 
+  return automaton;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Free BmcCheckForTermination_t.]
+
+  SideEffects []
+
+  SeeAlso []
+******************************************************************************/
+void
+BmcAutTerminationFree(
+  BmcCheckForTermination_t *result)
+{
+  LtlTableau_t    *tableau;
+  Ltl_Automaton_t *automaton = result->automaton;
+    
+  tableau = automaton->tableau; 
+  Ltl_AutomatonFree((gGeneric) automaton);
+  LtlTableauFree(tableau);
+  if(result->externalConstraints  != NIL(Ctlsp_Formula_t)){
+    Ctlsp_FormulaFree(result->externalConstraints);
+  }
+  
+  FREE(result);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Return the image of the given vertex in the hash table.]
+
+  SideEffects [Result should be freed by the caller.]
+
+******************************************************************************/
+static st_table *
+AutomatonVertexGetImg(
+  graph_t *G,
+  vertex_t *vtx)
+{
+  lsList Img;
+  lsGen lsgen;
+  edge_t *e;
+  vertex_t *s;
+  st_table *uTable;
+
+  Img = g_get_out_edges(vtx);
+
+  uTable = st_init_table(st_ptrcmp, st_ptrhash);
+  lsForEachItem(Img, lsgen, e) {
+    s = g_e_dest(e);
+    st_insert(uTable, (char *) s, (char *) s);
+  }
+
+  return uTable;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return the pre-image of the given vertex in the hash table.]
+
+  SideEffects [Result should be freed by the caller.]
+
+******************************************************************************/
+static st_table *
+AutomatonVertexGetPreImg(
+  graph_t *G,
+  vertex_t *vtx)
+{
+  lsList preImg;
+  lsGen lsgen;
+  edge_t *e;
+  vertex_t *s;
+  st_table *uTable;
+
+  preImg = g_get_in_edges(vtx);
+
+  uTable = st_init_table(st_ptrcmp, st_ptrhash);
+  lsForEachItem(preImg, lsgen,  e) {
+    s = g_e_source(e);
+    st_insert(uTable, (char *) s, (char *) s);
+  }
+  
+  return uTable;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return 1 if tbl1 and tbl2 two intersects.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+stIntersect(
+  st_table *tbl1,
+  st_table *tbl2)
+{
+  st_generator *stgen;
+  vertex_t *vtx;
+
+  st_foreach_item(tbl1, stgen, &vtx, NULL) {
+    if (st_is_member(tbl2,(char *)vtx)) {
+      st_free_gen(stgen);
+      return 1;
+    }
+  }
+  return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns no. of Bit encoding needed for n]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+NoOfBitEncode(
+   int n)
+{
+    int i = 0;
+    int j = 1;
+
+    if (n < 2) return 1; /* Takes care of value <= 1 */
+
+    while (j < n) {
+	j = j * 2;
+	i++;
+    }
+    return i;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns no. of Bit encoding needed for n]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static bdd_t *
+encodeOfInteger(
+  mdd_manager *manager,
+  array_t *varArray,
+  int val)
+{
+  int i;
+  bdd_t *returnValue =  mdd_one(manager);
+  int tmp = val;
+  bdd_t  *var;
+
+  for(i=0; i< array_n(varArray); i++){
+    var = array_fetch(bdd_t*, varArray, i);
+    if(tmp%2 == 0){
+      returnValue = bdd_and(returnValue, var, 1, 0); 
+    } else {
+      returnValue = bdd_and(returnValue, var, 1, 1);
+    }
+    tmp = tmp / 2;
+  }
+  return returnValue;
+}
+
Index: vis_dev/vis-2.3/src/bmc/bmcBmc.c
===================================================================
--- vis_dev/vis-2.3/src/bmc/bmcBmc.c	(revision 14)
+++ vis_dev/vis-2.3/src/bmc/bmcBmc.c	(revision 14)
@@ -0,0 +1,2912 @@
+/**CFile***********************************************************************
+
+  FileName    [bmcBmc.c]
+
+  PackageName [bmc]
+
+  Synopsis    [SAT-based ltl model checker.]
+
+  Author      [Mohammad Awedh]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+  
+******************************************************************************/
+
+#include "bmcInt.h"
+
+static char rcsid[] UNUSED = "$Id: bmcBmc.c,v 1.72 2005/10/14 04:41:11 awedh Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int checkIndex(int index, BmcCnfClauses_t *cnfClauses);
+static int doAnd(int left, int right);
+static int doOr(int left, int right);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+   Synopsis [Apply Bounded Model Checking (BMC) on a propositional formula.]
+
+   Description [If the property dos not hold in any initial state, the
+   property holds.
+
+   Note: Before calling this function, the LTL formula must be negated. 
+   
+   ]
+
+   SideEffects []
+   
+   SeeAlso     []
+   
+******************************************************************************/
+void
+BmcLtlVerifyProp(
+   Ntk_Network_t   *network,
+   Ctlsp_Formula_t *ltlFormula,
+   st_table        *CoiTable,
+   BmcOption_t     *options)
+{
+  mAig_Manager_t    *manager = Ntk_NetworkReadMAigManager(network);
+  st_table          *nodeToMvfAigTable = NIL(st_table);  /* maps each node to its mvfAig */
+  BmcCnfClauses_t   *cnfClauses = NIL(BmcCnfClauses_t);
+  
+
+  FILE              *cnfFile;
+
+  array_t           *result = NIL(array_t);
+  long              startTime, endTime;
+  bAigEdge_t        property;
+  array_t           *unitClause;
+  
+  assert(Ctlsp_isPropositionalFormula(ltlFormula));
+  
+  startTime = util_cpu_ctime();
+  
+  if (options->verbosityLevel != BmcVerbosityNone_c){
+    (void) fprintf(vis_stdout, "LTL formula is propositional\n");
+  }
+  property = BmcCreateMaigOfPropFormula(network, manager, ltlFormula);
+ 
+  if (property == mAig_NULL){
+    return;
+  }
+  if (property == bAig_One){
+    (void) fprintf(vis_stdout,"# BMC: Empty counterexample because the property is always FALSE\n");
+    (void) fprintf(vis_stdout,"# BMC: formula failed\n");
+    if (options->verbosityLevel != BmcVerbosityNone_c){
+      fprintf(vis_stdout, "-- bmc time = %10g\n",
+	      (double)(util_cpu_ctime() - startTime) / 1000.0);
+    }
+    return;
+  } else if (property == bAig_Zero){
+    (void) fprintf(vis_stdout,"# BMC: The property is always TRUE\n");
+    (void) fprintf(vis_stdout,"# BMC: formula passed\n");
+    if (options->verbosityLevel != BmcVerbosityNone_c){
+      fprintf(vis_stdout, "-- bmc time = %10g\n",
+	      (double)(util_cpu_ctime() - startTime) / 1000.0);
+    }
+    return;
+  }
+  cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);    
+  if (cnfFile == NIL(FILE)) {
+    (void) fprintf(vis_stderr,
+		   "** bmc error: Cannot create CNF output file %s\n",
+		   options->satInFile);
+    return;
+  }
+  /* nodeToMvfAigTable Maps each node to its Multi-function And/Inv graph */
+  nodeToMvfAigTable = (st_table *) Ntk_NetworkReadApplInfo(network,
+							   MVFAIG_NETWORK_APPL_KEY);
+  assert(nodeToMvfAigTable != NIL(st_table));
+  /*
+    Create clauses database 
+  */
+  cnfClauses = BmcCnfClausesAlloc();
+  unitClause = array_alloc(int, 1);
+
+  /*
+    Create an initialized path of length 0
+   */
+  BmcCnfGenerateClausesForPath(network, 0, 0, BMC_INITIAL_STATES, cnfClauses, nodeToMvfAigTable, CoiTable);
+   
+  /* Generate CNF for the property */
+  array_insert(int, unitClause, 0,
+	       BmcGenerateCnfFormulaForAigFunction(manager, property, 0, cnfClauses));
+  
+  BmcCnfInsertClause(cnfClauses, unitClause);
+  BmcWriteClauses(manager, cnfFile, cnfClauses, options);
+  (void) fclose(cnfFile);
+
+  result = BmcCheckSAT(options);
+  if (options->satSolverError){
+    (void) fprintf(vis_stdout,"# BMC: Error in calling SAT solver\n");
+  } else {
+    if (result != NIL(array_t)){
+      (void) fprintf(vis_stdout, "# BMC: formula failed\n");
+      if(options->verbosityLevel != BmcVerbosityNone_c){
+      	(void) fprintf(vis_stdout,
+		       "# BMC: Found a counterexample of length = 0 \n");
+      }
+      if (options->dbgLevel == 1) {
+	BmcPrintCounterExample(network, nodeToMvfAigTable, cnfClauses,
+			       result, 0, CoiTable, options, NIL(array_t));
+      }
+      array_free(result);
+    } else {
+      if(options->verbosityLevel != BmcVerbosityNone_c){
+	fprintf(vis_stdout,"# BMC: no counterexample found of length up to 0\n");
+      }
+      (void) fprintf(vis_stdout, "# BMC: formula Passed\n");
+    }
+  }
+  array_free(unitClause);   
+  BmcCnfClausesFree(cnfClauses);
+  
+  if (options->verbosityLevel != BmcVerbosityNone_c){
+    endTime = util_cpu_ctime();
+    fprintf(vis_stdout, "-- bmc time = %10g\n",
+	    (double)(endTime - startTime) / 1000.0);
+  }
+  fflush(vis_stdout);
+  return;
+} /* BmcLtlVerifyProp  */
+
+
+/**Function********************************************************************
+
+  Synopsis [Check if the LTL formula in the form G(p) (invariant),
+  where p is a propositional formula, is an Inductive Invariant]
+
+  Description [Check if the LTL formula in the form G(p), where p is a
+  propositional formula, is an Inductive Invariant
+
+  An LTL formula G(p), where p is a propositional formul, is an
+  inductive invariant if the following two conditions hold:
+  
+     1- p holds in all the intial states.
+     2- If p holds in a state s, then it also holds in all states
+        that are reachable from s.
+
+  G(p) is an inductive invariant if : 
+    SAT( I(0) and !p(0)) return UNSAT and
+    SAT( p(i) and T(i, i+1) and !p(i+1)) returns UNSAT.
+
+  Return value:
+    0 if the property is not an inductive invariant 
+    1 if the property is an inductive invariant
+   -1 error
+   ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+BmcLtlCheckInductiveInvariant(
+  Ntk_Network_t   *network,
+  bAigEdge_t      property,
+  BmcOption_t     *options,
+  st_table        *CoiTable)
+{
+  mAig_Manager_t    *manager = Ntk_NetworkReadMAigManager(network);
+  BmcCnfClauses_t   *cnfClauses = NIL(BmcCnfClauses_t);
+  array_t           *unitClause;
+  int               cnfIndex;
+  array_t           *result = NIL(array_t);
+  FILE              *cnfFile;
+  st_table          *nodeToMvfAigTable = NIL(st_table);  /* maps each node to its mvfAig */
+  int               savedVerbosityLevel = options->verbosityLevel;
+  int               returnValue = 0;  /* the property is not an inductive invariant */
+
+  cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);    
+  if (cnfFile == NIL(FILE)) {
+    (void) fprintf(vis_stderr,
+		   "** bmc error: Cannot create CNF output file %s\n",
+		   options->satInFile);
+    return -1;
+  }
+  /*
+    nodeToMvfAigTable Maps each node to its Multi-function And/Inv graph
+  */
+  nodeToMvfAigTable =
+    (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+  
+  assert(nodeToMvfAigTable != NIL(st_table));
+
+  /*
+    Clause database
+   */
+  cnfClauses = BmcCnfClausesAlloc();
+  /*
+    Check if the property holds in all intial states
+  */
+  /*
+    Generate CNF clauses for initial states
+  */
+  BmcCnfGenerateClausesForPath(network, 0, 0, BMC_INITIAL_STATES,
+			       cnfClauses, nodeToMvfAigTable, CoiTable);
+  /*
+    Generate CNF clauses for the property
+  */
+  cnfIndex = BmcGenerateCnfFormulaForAigFunction(manager, property, 0, cnfClauses);
+  unitClause = array_alloc(int, 1);
+  array_insert(int, unitClause, 0, cnfIndex); /* because property is the negation of
+						the LTL formula*/
+  BmcCnfInsertClause(cnfClauses, unitClause);
+  
+  options->verbosityLevel = BmcVerbosityNone_c;
+  BmcWriteClauses(manager, cnfFile, cnfClauses, options);
+  (void) fclose(cnfFile);
+  result = BmcCheckSAT(options);    
+  options->verbosityLevel = (Bmc_VerbosityLevel) savedVerbosityLevel;
+  BmcCnfClausesFree(cnfClauses);
+  if (options->satSolverError){
+    return -1;
+  }
+  if (result == NIL(array_t)){ /* the property holds at all initial states */
+    cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);    
+    if (cnfFile == NIL(FILE)) {
+      (void) fprintf(vis_stderr,
+		     "** bmc error: Cannot create CNF output file %s\n",
+		     options->satInFile);
+      return -1;
+    }
+    /*
+      Check if the property holds in state i, it also holds in state i+1
+    */
+    cnfClauses = BmcCnfClausesAlloc();  
+    /*
+      Generate CNF clauses for a transition from state i to state i+1.
+    */
+    BmcCnfGenerateClausesForPath(network, 0, 1, BMC_NO_INITIAL_STATES,
+				 cnfClauses, nodeToMvfAigTable, CoiTable);
+    
+    cnfIndex = BmcGenerateCnfFormulaForAigFunction(manager, property, 0, cnfClauses);
+    array_insert(int, unitClause, 0, -cnfIndex); /* because property is the negation of
+						    the LTL formula */
+    BmcCnfInsertClause(cnfClauses, unitClause);
+    
+    cnfIndex = BmcGenerateCnfFormulaForAigFunction(manager, property, 1, cnfClauses);
+    array_insert(int, unitClause, 0, cnfIndex); /* because property is the negation of
+						   the LTL formula */
+    BmcCnfInsertClause(cnfClauses, unitClause);
+    options->verbosityLevel = BmcVerbosityNone_c;
+    BmcWriteClauses(manager, cnfFile, cnfClauses, options);
+    (void) fclose(cnfFile);
+    result = BmcCheckSAT(options);
+    options->verbosityLevel = (Bmc_VerbosityLevel) savedVerbosityLevel;
+    BmcCnfClausesFree(cnfClauses);
+    if (options->satSolverError){
+      returnValue = -1;
+    }
+    if (result != NIL(array_t)){
+      returnValue = 0; /* the property is not an inductive invariant */
+    } else {
+      returnValue = 1;  /* the property is an inductive invariant */
+    }
+  }
+  array_free(unitClause);
+  return returnValue; 
+} /* BmcLtlCheckInductiveInvariant() */
+
+
+/**Function********************************************************************
+
+   Synopsis [Apply Bounded Model Checking (BMC) on an LTL formula of
+   the form G(p), where p is a propositional formula.]
+
+   Description [Given a model M, an LTL formula f = Gp, and a bound k,
+   we first find a counterexample of length k to a state that violates
+   p.  If -r switch of the BMC command is specified, we apply the
+   induction proof to check if the property f passes. The property f
+   passes if there is no simple path in M that leads to a state that
+   violates p, or no simple path in M starting at an initial state.
+
+   Note: Before calling this function, the LTL formula must be negated. 
+   
+   ]
+
+   SideEffects []
+   
+   SeeAlso     []
+   
+******************************************************************************/
+void
+BmcLtlVerifyGp(  
+   Ntk_Network_t   *network,
+   Ctlsp_Formula_t *ltlFormula,
+   st_table        *CoiTable,
+   BmcOption_t     *options)
+{
+  mAig_Manager_t    *manager = Ntk_NetworkReadMAigManager(network);
+  st_table          *nodeToMvfAigTable = NIL(st_table);  /* maps each node to its mvfAig */
+  BmcCnfClauses_t   *cnfClauses = NIL(BmcCnfClauses_t);
+  BmcCnfStates_t    *state;
+
+  FILE              *cnfFile;
+  array_t           *Pclause = array_alloc(int, 0);
+
+  int               k, bound, initK, propK;
+  array_t           *result = NIL(array_t);
+  long              startTime, endTime;
+  bAigEdge_t        property;
+  int               minK = options->minK;
+  int               maxK = options->maxK;
+  int               i, initState = BMC_INITIAL_STATES;
+  array_t           *unitClause;
+  
+  int               bmcError = FALSE;
+  
+  Bmc_PropertyStatus formulaStatus;
+  
+  assert(Ctlsp_LtlFormulaIsFp(ltlFormula));
+  
+  startTime = util_cpu_ctime();
+
+  if (options->verbosityLevel != BmcVerbosityNone_c){
+    (void)fprintf(vis_stdout, "LTL formula is of type G(p)\n");
+  }
+  property = BmcCreateMaigOfPropFormula(network, manager, ltlFormula->right);
+
+  if (property == mAig_NULL){
+    return;
+  }
+  if (property == bAig_One){
+    (void) fprintf(vis_stdout,"# BMC: Empty counterexample because the property is always FALSE\n");
+    (void) fprintf(vis_stdout,"# BMC: formula failed\n");
+    if (options->verbosityLevel != BmcVerbosityNone_c){
+      fprintf(vis_stdout, "-- bmc time = %10g\n",
+	      (double)(util_cpu_ctime() - startTime) / 1000.0);
+    }
+    return;
+  } else if (property == bAig_Zero){
+    (void) fprintf(vis_stdout,"# BMC: The property is always TRUE\n");
+    (void) fprintf(vis_stdout,"# BMC: formula passed\n");
+    if (options->verbosityLevel != BmcVerbosityNone_c){
+      fprintf(vis_stdout, "-- bmc time = %10g\n",
+	      (double)(util_cpu_ctime() - startTime) / 1000.0);
+    }
+    return;
+  }
+
+#if 0
+  if (options->verbosityLevel == BmcVerbosityMax_c){
+    (void) fprintf(vis_stdout, "\nBMC: Check if the property is an inductive invariant\n");
+  }
+  checkInductiveInvariant = BmcLtlCheckInductiveInvariant(network, property, options, CoiTable);
+  
+  if(checkInductiveInvariant == -1){
+    return;
+  }
+  if (checkInductiveInvariant == 1){
+    (void) fprintf(vis_stdout,"# BMC: The property is an inductive invariant\n");
+    (void) fprintf(vis_stdout,"# BMC: formula passed\n");
+    if (options->verbosityLevel != BmcVerbosityNone_c){
+      fprintf(vis_stdout, "-- bmc time = %10g\n",
+	      (double)(util_cpu_ctime() - startTime) / 1000.0);
+    }
+    return;
+  }
+#endif
+  if (options->verbosityLevel != BmcVerbosityNone_c){
+    (void)fprintf(vis_stdout, "Apply BMC on counterexample of length >= %d and <= %d (+%d)\n",
+		  minK, maxK, options->step);
+  }
+  initK  = 0;
+  propK  = 0;
+  formulaStatus = BmcPropertyUndecided_c;
+  
+  /* nodeToMvfAigTable Maps each node to its Multi-function And/Inv graph */
+  nodeToMvfAigTable =
+    (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+  assert(nodeToMvfAigTable != NIL(st_table));
+
+  /*
+    Create clauses database 
+  */
+  cnfClauses = BmcCnfClausesAlloc();
+  /*
+    init = BmcCreateMaigOfInitialStates(network, nodeToMvfAigTable, CoiTable);
+  */
+  for(bound = minK; bound <= maxK; bound += options->step){
+    if (options->verbosityLevel == BmcVerbosityMax_c) {
+      (void) fprintf(vis_stdout,
+		     "\nBMC: Generate counterexample of length %d\n",
+		     bound);
+    }
+    cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);    
+    if (cnfFile == NIL(FILE)) {
+      (void) fprintf(vis_stderr,
+		     "** bmc error: Cannot create CNF output file %s\n",
+		     options->satInFile);
+      bmcError = TRUE;
+      break;
+    }
+    BmcCnfGenerateClausesForPath(network, initK, bound, initState, cnfClauses, nodeToMvfAigTable, CoiTable);
+
+    initState = BMC_NO_INITIAL_STATES;
+   
+    /* Generate CNF for the property */
+    Pclause = array_alloc(int, 0);
+    /*
+    state = BmcCnfClausesFreeze(cnfClauses);
+    */
+    for(k=propK; k <= bound; k++){
+      array_insert_last(
+	int, Pclause, BmcGenerateCnfFormulaForAigFunction(manager, property,
+							  k, cnfClauses));
+    }
+    
+    state = BmcCnfClausesFreeze(cnfClauses);
+    
+    BmcCnfInsertClause(cnfClauses, Pclause);
+    BmcWriteClauses(manager, cnfFile, cnfClauses, options);
+    (void) fclose(cnfFile);
+    BmcCnfClausesRestore(cnfClauses, state);
+    result = BmcCheckSAT(options);
+    if (options->satSolverError){
+      array_free(Pclause);
+      break;
+    }
+    if (result != NIL(array_t)){
+      bound++;
+      array_free(Pclause);
+      /*
+	formula failed\n"
+      */
+      formulaStatus = BmcPropertyFailed_c;
+      break;
+    }
+    unitClause = array_alloc(int, 1);
+    for(i=0; i<array_n(Pclause); i++){
+      array_insert(int, unitClause, 0, -array_fetch(int, Pclause, i));
+      BmcCnfInsertClause(cnfClauses, unitClause);
+    }
+    array_free(unitClause);   
+    array_free(Pclause);
+    FREE(state);
+    initK = bound;
+    propK = bound+1;
+
+    /*
+      Prove if the property passes using the induction proof of SSS0.
+     */
+    if((result == NIL(array_t)) &&
+       (options->inductiveStep !=0) &&
+       (bound % options->inductiveStep == 0)){
+      BmcCnfClauses_t   *cnfClauses;
+      array_t           *result = NIL(array_t);
+      array_t           *unitClause =  array_alloc(int, 1);
+      int               savedVerbosityLevel = options->verbosityLevel;
+      long              startTime = util_cpu_ctime();
+	
+      if (options->verbosityLevel == BmcVerbosityMax_c) {
+	(void) fprintf(vis_stdout, "\nBMC: Check for induction\n");
+      }
+      options->verbosityLevel = BmcVerbosityNone_c;
+
+      if(options->earlyTermination){
+	/*
+	  Early termination condition
+	  
+	  Check if there is no simple path of length 'bound' starts from
+	  initial states
+	  
+	*/
+	cnfClauses = BmcCnfClausesAlloc();
+	
+	cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
+	if (cnfFile == NIL(FILE)) {
+	  (void)fprintf(vis_stderr,
+			"** bmc error: Cannot create CNF output file %s\n",
+			options->satInFile);
+	  bmcError = TRUE;
+	  break;
+	}
+	/*
+	  Generate an initialized simple path path of length bound.
+	*/
+	BmcCnfGenerateClausesForLoopFreePath(network, 0, bound, BMC_INITIAL_STATES,
+					     cnfClauses, nodeToMvfAigTable, CoiTable);
+	BmcWriteClauses(manager, cnfFile, cnfClauses, options);
+	(void) fclose(cnfFile);
+	BmcCnfClausesFree(cnfClauses);
+	
+	result = BmcCheckSAT(options);
+	if(options->satSolverError){
+	  break;
+	}
+	if(result == NIL(array_t)){
+	  if (savedVerbosityLevel == BmcVerbosityMax_c) {
+	    (void) fprintf(vis_stdout,
+			   "# BMC: No simple path starting at an initial state\n");
+	  }
+	  formulaStatus = BmcPropertyPassed_c;
+	} else {
+	  array_free(result);
+	}
+      } /* Early termination */
+      if(formulaStatus != BmcPropertyPassed_c){
+	cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
+	if (cnfFile == NIL(FILE)) {
+	  (void)fprintf(vis_stderr,
+			"** bmc error: Cannot create CNF output file %s\n",
+			options->satInFile);
+	  bmcError = TRUE;
+	  break;
+	}
+	cnfClauses = BmcCnfClausesAlloc();
+	/*
+	  Generate a simple path of length k+1
+	*/
+	BmcCnfGenerateClausesForLoopFreePath(network, 0, bound+1, BMC_NO_INITIAL_STATES,
+					     cnfClauses, nodeToMvfAigTable, CoiTable);
+	/*
+	  All the states to bound satisfy the property.
+	*/
+	unitClause = array_alloc(int, 1);
+	for(k=0; k <= bound; k++){
+	  array_insert(
+	    int, unitClause, 0, -BmcGenerateCnfFormulaForAigFunction(manager, property,
+								     k, cnfClauses));
+	  BmcCnfInsertClause(cnfClauses, unitClause);
+	}
+	/*
+	  The property fails at bound +1
+	*/
+	array_insert(int, unitClause, 0,
+		     BmcGenerateCnfFormulaForAigFunction(manager, property,
+							 bound+1, cnfClauses));
+	BmcCnfInsertClause(cnfClauses, unitClause);
+	array_free(unitClause);
+	
+	BmcWriteClauses(manager, cnfFile, cnfClauses, options);
+	BmcCnfClausesFree(cnfClauses);
+	(void) fclose(cnfFile);
+	result = BmcCheckSAT(options);
+	if (options->satSolverError){
+	  break;
+	}
+	if(result == NIL(array_t)) {
+	  if (savedVerbosityLevel == BmcVerbosityMax_c) {
+	    (void) fprintf(vis_stdout,
+			   "# BMC: No simple path leading to a bad state\n");
+	  }
+	  formulaStatus = BmcPropertyPassed_c;
+	}
+      }
+      options->verbosityLevel = (Bmc_VerbosityLevel) savedVerbosityLevel;
+      if (options->verbosityLevel != BmcVerbosityNone_c){
+	endTime = util_cpu_ctime();
+	fprintf(vis_stdout, "-- check for induction time = %10g\n",
+		(double)(endTime - startTime) / 1000.0);
+      }
+    } /* Check induction */
+    if(formulaStatus != BmcPropertyUndecided_c){
+      break;
+    }
+  } /* for bound loop */
+  if( bmcError == FALSE){
+    if (options->satSolverError){
+      (void) fprintf(vis_stdout,"# BMC: Error in calling SAT solver\n");
+    } else {
+      if(formulaStatus == BmcPropertyUndecided_c){
+	if (options->verbosityLevel != BmcVerbosityNone_c){
+	  (void) fprintf(vis_stdout,
+			 "# BMC: no counterexample found of length up to %d \n",
+			 options->maxK);
+	}
+      }
+      if(formulaStatus == BmcPropertyFailed_c) {
+	(void) fprintf(vis_stdout, "# BMC: formula failed\n");
+         if(options->verbosityLevel != BmcVerbosityNone_c){
+	   (void) fprintf(vis_stdout,
+			  "# BMC: Found a counterexample of length = %d \n", bound-1);
+	 }
+	if (options->dbgLevel == 1) {
+	  BmcPrintCounterExample(network, nodeToMvfAigTable, cnfClauses,
+				 result, bound-1, CoiTable, options, NIL(array_t));
+	}
+      } else if(formulaStatus == BmcPropertyPassed_c) {
+	(void) fprintf(vis_stdout, "# BMC: formula Passed\n");
+      } else if(formulaStatus == BmcPropertyUndecided_c) {
+	(void) fprintf(vis_stdout,"# BMC: formula undecided\n");
+      }
+    }
+  }
+  /* free all used memories */
+  if(cnfClauses != NIL(BmcCnfClauses_t)){
+    BmcCnfClausesFree(cnfClauses);
+  }
+  if(result != NIL(array_t)) {
+    array_free(result);
+  }
+  /*
+  array_free(Pclause);
+  */
+  if (options->verbosityLevel != BmcVerbosityNone_c){
+    endTime = util_cpu_ctime();
+    fprintf(vis_stdout, "-- bmc time = %10g\n",
+	    (double)(endTime - startTime) / 1000.0);
+  }
+  fflush(vis_stdout);
+  return;
+} /* BmcLtlVerifyGp()  */
+
+/**Function********************************************************************
+
+   Synopsis [Apply Bounded Model Checking (BMC) on an LTL formula of
+   the form F(p), where p is propositional.]
+
+   Description [Given a model M, an LTL formula f = Fp, and a bound k,
+   we first find a k-loop counterexample of length k at which all
+   states violate p.  If -r switch of the BMC command is specified, we
+   apply the method in the paper "Proving More Properties with Bounded
+   Model Checking" to check if the property f passes.
+
+   Note: Before calling this function, the LTL formula must be negated. 
+   
+   ]   
+   SideEffects []
+   
+   SeeAlso     []
+
+******************************************************************************/
+void
+BmcLtlVerifyFp(
+   Ntk_Network_t   *network,
+   Ctlsp_Formula_t *ltlFormula,
+   st_table        *CoiTable,
+   BmcOption_t     *options)
+{
+  mAig_Manager_t  *manager   = Ntk_NetworkReadMAigManager(network);
+  st_table        *nodeToMvfAigTable = NIL(st_table);  /* maps each node to its mvfAig */
+  BmcCnfClauses_t *cnfClauses = NIL(BmcCnfClauses_t);
+  
+  
+  FILE       *cnfFile;
+  array_t    *unitClause= array_alloc(int, 1), *outClause;
+  int        outIndex;
+  int        k;
+  array_t    *result  = NIL(array_t);
+  long       startTime, endTime;
+  bAigEdge_t property;
+  int        bound;
+  int        bmcError = FALSE;
+    
+  Bmc_PropertyStatus formulaStatus = BmcPropertyUndecided_c;
+
+  assert(Ctlsp_LtlFormulaIsGp(ltlFormula));
+   
+  startTime = util_cpu_ctime();
+  if (options->verbosityLevel != BmcVerbosityNone_c){
+    (void)fprintf(vis_stdout, "LTL formula is of type F(p)\n");
+  }
+  property = BmcCreateMaigOfPropFormula(network, manager, ltlFormula->right);
+  if (property == mAig_NULL){
+    return;
+  }
+  if (property == bAig_One){
+    (void) fprintf(vis_stdout, "# BMC: formula failed\n");
+    (void) fprintf(vis_stdout, "       Empty counterexample because the property is always FALSE\n");
+    if (options->verbosityLevel != BmcVerbosityNone_c) {
+      endTime = util_cpu_ctime();
+      fprintf(vis_stdout, "-- bmc time = %10g\n",
+	      (double)(endTime - startTime) / 1000.0);
+    }
+    return;
+  } else if (property == bAig_Zero){
+    (void) fprintf(vis_stdout,"# BMC: The property is always TRUE\n");
+    formulaStatus = BmcPropertyPassed_c;
+    (void) fprintf(vis_stdout,"# BMC: formula passed\n");
+    if (options->verbosityLevel != BmcVerbosityNone_c) {
+      endTime = util_cpu_ctime();
+      fprintf(vis_stdout, "-- bmc time = %10g\n",
+	      (double)(endTime - startTime) / 1000.0);
+    }
+    return;
+  }
+  if (options->verbosityLevel != BmcVerbosityNone_c){
+    (void)fprintf(vis_stdout, "Apply BMC on counterexample of length >= %d and <= %d (+%d) \n",
+		  options->minK, options->maxK, options->step);
+  }
+  /*
+    nodeToMvfAigTable Maps each node to its Multi-function AIG graph
+  */
+  nodeToMvfAigTable = (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+  assert(nodeToMvfAigTable != NIL(st_table));
+  outClause = NIL(array_t);
+  bound = options->minK;
+  BmcGetCoiForLtlFormula(network, ltlFormula, CoiTable);
+  
+  while( (result == NIL(array_t)) && (bound <= options->maxK)){
+    if (options->verbosityLevel == BmcVerbosityMax_c) {
+      (void) fprintf(vis_stdout,
+		     "\nBMC: Generate counterexample of length %d\n", bound);
+    }
+    cnfClauses = BmcCnfClausesAlloc();
+    cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);    
+    if (cnfFile == NIL(FILE)) {
+      (void)fprintf(vis_stderr,
+		    "** bmc error: Cannot create CNF output file %s\n",
+		    options->satInFile);
+      bmcError = TRUE;
+      break;
+    }
+    /*
+      Generate clauses for an initialized path of length "bound".
+    */
+    BmcCnfGenerateClausesForPath(network, 0, bound, BMC_INITIAL_STATES,
+				 cnfClauses, nodeToMvfAigTable, CoiTable);
+    /*
+      Generate CNF for the property. Property fails at all states
+     */
+    for(k=0; k <= bound; k++){
+      array_insert(int, unitClause, 0,
+		   BmcGenerateCnfFormulaForAigFunction(manager, property,
+						       k, cnfClauses));
+      BmcCnfInsertClause(cnfClauses, unitClause);
+    }
+
+    /* Generate CNF for a loop-back (loop from the last state to any
+       state) path.
+       (Sk -> S0) + (Sk -> S1) + ..... + (Sk-> Sk-1) + (Sk-> Sk)
+       Each transition consisits of one or more latches.  We
+       AND the transiton relation of these latches.  For multi-valued
+       latches, we OR the equivalence of each value of the latch. To
+       do the AND we use the CNF equivalent of the AND.  a = b*c => (b
+       + !a) * (c + !a)
+    */
+    outClause = array_alloc(int, bound);   
+    for (k=0; k <= bound; k++){
+      /*
+	Create new var for the output of the AND node.
+      */
+      outIndex = cnfClauses->cnfGlobalIndex++;
+      BmcCnfGenerateClausesFromStateToState(network, bound, k, cnfClauses,
+					    nodeToMvfAigTable, CoiTable, outIndex);
+      array_insert(int, outClause, k, outIndex);
+    }  /* for k state loop */
+    BmcCnfInsertClause(cnfClauses, outClause);
+  
+    BmcWriteClauses(manager, cnfFile, cnfClauses, options);
+    (void) fclose(cnfFile);
+    
+    result = BmcCheckSAT(options);
+    if (options->satSolverError){
+      break;
+    }
+    if(result != NIL(array_t)){
+      formulaStatus = BmcPropertyFailed_c;
+      break;
+    }
+    BmcCnfClausesFree(cnfClauses);
+    array_free(outClause);
+    if((result == NIL(array_t)) &&
+       (options->inductiveStep !=0) &&
+       (bound % options->inductiveStep == 0)
+       )    
+      {
+      int     savedVerbosityLevel = options->verbosityLevel;
+      long    startTime = util_cpu_ctime();
+      array_t *result  = NIL(array_t);
+
+      if (options->verbosityLevel == BmcVerbosityMax_c) {
+	(void) fprintf(vis_stdout,
+		       "\nBMC: Check if the property passes\n");
+      }
+      cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
+      if (cnfFile == NIL(FILE)) {
+	(void)fprintf(vis_stderr,
+		      "** bmc error: Cannot create CNF output file %s\n",
+		      options->satInFile);
+	bmcError = TRUE;
+	break;
+      }
+      cnfClauses = BmcCnfClausesAlloc();
+      /*
+	CNF for an initialized simple path.
+       */
+      BmcCnfGenerateClausesForLoopFreePath(network, 0, bound, BMC_INITIAL_STATES,
+					   cnfClauses, nodeToMvfAigTable, CoiTable);
+      /*
+	Generate CNF for the property. Property fails at all states
+      */
+      for(k=0; k <= bound; k++){
+	array_insert(int, unitClause, 0,
+		     BmcGenerateCnfFormulaForAigFunction(manager, property,
+							 k, cnfClauses));
+	BmcCnfInsertClause(cnfClauses, unitClause);
+      }
+      BmcWriteClauses(manager, cnfFile, cnfClauses, options);
+      BmcCnfClausesFree(cnfClauses);
+      (void) fclose(cnfFile);
+      /*
+	Do not print any detail information when checking the clauses
+       */
+      options->verbosityLevel = BmcVerbosityNone_c;
+      result = BmcCheckSAT(options);
+      options->verbosityLevel = (Bmc_VerbosityLevel) savedVerbosityLevel;
+      if (options->satSolverError){
+	break;
+      }
+      if (options->verbosityLevel != BmcVerbosityNone_c){
+	endTime = util_cpu_ctime();
+	fprintf(vis_stdout, "--  checking time = %10g\n",
+		(double)(endTime - startTime) / 1000.0);
+      }
+      if (result == NIL(array_t)){ /* UNSAT */
+	formulaStatus = BmcPropertyPassed_c;
+	break;  /* formula is satisfiable */
+      }
+      array_free(result);
+    } /* Check induction */
+
+    /* free all used memories 
+    BmcCnfClausesFree(cnfClauses); */
+
+    bound += options->step;
+  } /* while result and bound */
+  if (bmcError == FALSE){
+    if(!options->satSolverError){
+      if(formulaStatus == BmcPropertyFailed_c) {
+	(void) fprintf(vis_stdout, "# BMC: formula failed\n");
+	if(options->verbosityLevel != BmcVerbosityNone_c){
+	  (void) fprintf(vis_stdout,
+			 "# BMC: Found a counterexample of length = %d \n", bound);
+	}
+	if (options->dbgLevel == 1) {
+	  BmcPrintCounterExample(network, nodeToMvfAigTable, cnfClauses,
+				 result, bound, CoiTable, options, outClause);
+	}
+	array_free(result);
+	BmcCnfClausesFree(cnfClauses);
+	array_free(outClause);
+      } else if(formulaStatus == BmcPropertyPassed_c) {
+	(void) fprintf(vis_stdout, "# BMC: formula Passed\n");
+      } else if(formulaStatus == BmcPropertyUndecided_c) {
+	(void) fprintf(vis_stdout,"# BMC: formula undecided\n");
+	if (options->verbosityLevel != BmcVerbosityNone_c){
+	  (void) fprintf(vis_stdout,
+		       "# BMC: no counterexample found of length up to %d \n",
+			 options->maxK);
+	}
+      }
+    } else {
+      (void) fprintf(vis_stdout,"# BMC: Error in calling SAT solver\n");
+    }
+  }
+  if (options->verbosityLevel != BmcVerbosityNone_c) {
+    endTime = util_cpu_ctime();
+    fprintf(vis_stdout, "-- bmc time = %10g\n",
+	    (double)(endTime - startTime) / 1000.0);
+  }
+  if(unitClause != NIL(array_t)) {
+    array_free(unitClause);
+  }
+  fflush(vis_stdout);  
+  return;
+} /* BmcLtlVerifyFp() */
+
+/**Function********************************************************************
+
+   Synopsis [Apply Bounded Model Checking (BMC) on an LTL formula of
+   the form FG(p), where p is propositional.]
+
+   Description [Given a model M, an LTL formula f = FGp, and a bound
+   k, we first find a k-loop counterexample of length k at which p
+   false inside the loop.  If -r switch of the BMC command is
+   specified, we apply the method in the paper "Proving More
+   Properties with Bounded Model Checking" to check if the property f
+   passes.
+
+   Note: Before calling this function, the LTL formula must be negated. 
+   
+   ]
+  
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+BmcLtlVerifyFGp(
+   Ntk_Network_t   *network,
+   Ctlsp_Formula_t *ltlFormula,
+   st_table        *CoiTable,
+   BmcOption_t     *options)
+{
+  mAig_Manager_t   *manager = Ntk_NetworkReadMAigManager(network);
+  st_table         *nodeToMvfAigTable = NIL(st_table);  /* node to mvfAig */
+  BmcCnfClauses_t  *cnfClauses = NIL(BmcCnfClauses_t);
+  FILE             *cnfFile;
+  
+  array_t          *orClause, *tmpClause, *loopClause;
+  int              k, l, andIndex, loop;
+  array_t          *result = NIL(array_t);
+  long             startTime, endTime;
+  int              minK = options->minK;
+  int              maxK = options->maxK;
+  Ctlsp_Formula_t  *propFormula;
+  bAigEdge_t       property;
+
+  Bmc_PropertyStatus formulaStatus;
+  int                bmcError = FALSE;
+  
+  int              m=-1, n=-1;
+  int              checkLevel = 0;
+  /*
+    Refer to Theorem 1 in the paper "Proving More Properties with Bounded Model Checking"
+    
+    If checkLevel == 0 -->  check for beta' only. If UNSAT, m=k and chekLevel = 1
+    If checkLevel == 1 -->  check for beta  only. If UNSAT, checkLevel = 2.
+    If checkLevel == 2 -->  check for alpha only. If UNSAT, n=k and checkLevel = 3.
+    If gama is UNSAT up to (m+n-1) and checkLvel = 3, formula passes.
+    checkLevel = 4 if (m+n-1) > maxK; */
+
+  /*
+    Remember the LTL property was negated
+   */
+  assert(Ctlsp_LtlFormulaIsGFp(ltlFormula));
+
+  /* ************** */
+  
+  /* Initialization */
+  
+  /* ************** */
+  loopClause = NIL(array_t);
+  startTime = util_cpu_ctime();
+  /*
+    nodeToMvfAigTable maps each node to its multi-function And/Inv graph
+  */
+  nodeToMvfAigTable =
+    (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+  if (nodeToMvfAigTable == NIL(st_table)){
+    (void) fprintf(vis_stderr,
+		   "** bmc error: you need to build the AIG structure first\n");
+    return;
+  }
+  propFormula = Ctlsp_FormulaReadRightChild(Ctlsp_FormulaReadRightChild(ltlFormula));
+  property    = BmcCreateMaigOfPropFormula(network, manager, propFormula);
+  if (options->verbosityLevel != BmcVerbosityNone_c){
+    (void)fprintf(vis_stdout, "LTL formula is of type FG(p)\n");
+    (void) fprintf(vis_stdout, "Apply BMC on counterexample of length >= %d and <= %d (+%d) \n",
+		  minK, maxK, options->step);
+  }
+  tmpClause  = array_alloc(int, 2);
+  k= minK;
+  formulaStatus = BmcPropertyUndecided_c;
+  while( (result == NIL(array_t)) && (k <= maxK)){
+    /*
+      Search for a k-loop counterexample of length k.
+     */
+    if (options->verbosityLevel == BmcVerbosityMax_c) {
+      (void) fprintf(vis_stdout, "\nGenerate counterexample of length %d\n", k);
+    }
+    /*
+      Create a clause database
+     */
+    cnfClauses = BmcCnfClausesAlloc();
+
+    cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
+    if (cnfFile == NIL(FILE)) {
+      (void)fprintf(vis_stderr,
+		    "** bmc error: Cannot create CNF output file %s\n",
+		    options->satInFile);
+      bmcError = TRUE;
+      break;
+    }
+    
+    /**********************************************
+       \gama(k)
+    ***********************************************/
+    /*
+      Generate an initialized path of length k.
+     */
+    BmcCnfGenerateClausesForPath(network, 0, k, BMC_INITIAL_STATES, cnfClauses, nodeToMvfAigTable, CoiTable);
+    /*
+      k-loop
+     */
+    orClause   = array_alloc(int, 0);
+    loopClause = array_alloc(int, k+1);
+    for(l=0; l<=k; l++){
+      /*
+	Use to check if there is a loop from k to l.
+       */
+      loop = cnfClauses->cnfGlobalIndex++;
+      BmcCnfGenerateClausesFromStateToState(network, k, l, cnfClauses, nodeToMvfAigTable, CoiTable, loop);
+      array_insert(int, loopClause, l, loop);
+      
+      andIndex   = cnfClauses->cnfGlobalIndex++;
+      array_insert(int, tmpClause, 0, loop);
+      array_insert(int, tmpClause, 1, -andIndex);
+      BmcCnfInsertClause(cnfClauses, tmpClause);
+
+      /*
+	         l
+	If [[F p]]  if p true in a state from l to k.
+	         k
+       */
+      array_insert(int, tmpClause, 0,
+		   BmcGenerateCnfForLtl(network, Ctlsp_FormulaCreate(Ctlsp_F_c, propFormula, NIL(Ctlsp_Formula_t)),
+					l, k, -1, cnfClauses));
+      BmcCnfInsertClause(cnfClauses, tmpClause);
+      
+      array_insert_last(int, orClause, andIndex);
+    } /* for l loop */
+    BmcCnfInsertClause(cnfClauses, orClause);
+    array_free(orClause);
+    BmcWriteClauses(manager, cnfFile, cnfClauses, options);
+    (void) fclose(cnfFile);
+      
+    result = BmcCheckSAT(options);
+    if(options->satSolverError){
+      break;
+    }
+    if(result != NIL(array_t)) {
+      formulaStatus = BmcPropertyFailed_c;
+      break;
+    }
+    array_free(loopClause);
+    /* free all used memories */
+    BmcCnfClausesFree(cnfClauses);
+
+    /* ====================================================================
+             Use termination criteria to prove that the property passes.
+       ==================================================================== */
+    if((result == NIL(array_t)) &&
+       (options->inductiveStep !=0) &&
+       (k % options->inductiveStep == 0)
+       )
+      {
+	array_t *unitClause = array_alloc(int, 0);
+	array_t *result = NIL(array_t);
+	int     savedVerbosityLevel = options->verbosityLevel;
+
+	options->verbosityLevel = BmcVerbosityNone_c;
+	/* ===========================
+	   Early termination condition
+	   =========================== */
+	if(options->earlyTermination){
+	  if (savedVerbosityLevel == BmcVerbosityMax_c) {
+	    (void) fprintf(vis_stdout, "\nChecking the early termination at k= %d\n", k);
+	  }
+	  cnfClauses = BmcCnfClausesAlloc();
+
+	  cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
+	  if (cnfFile == NIL(FILE)) {
+	    (void)fprintf(vis_stderr,
+			  "** abmc error: Cannot create CNF output file %s\n",
+			  options->satInFile);
+	    bmcError = TRUE;
+	    break;
+	  }
+	  /*
+	    Generate an initialized simple path path of length k.
+	  */
+	  BmcCnfGenerateClausesForLoopFreePath(network, 0, k, BMC_INITIAL_STATES,
+					       cnfClauses, nodeToMvfAigTable, CoiTable);
+	  BmcWriteClauses(manager, cnfFile, cnfClauses, options);
+	  (void) fclose(cnfFile);
+	  BmcCnfClausesFree(cnfClauses);
+	  
+	  result = BmcCheckSAT(options);
+	  if(options->satSolverError){
+	    break;
+	  }
+	  if(result == NIL(array_t)) {
+	    formulaStatus = BmcPropertyPassed_c;
+	    if (savedVerbosityLevel == BmcVerbosityMax_c) {
+	      (void) fprintf(vis_stdout, "# BMC: By early termination\n");
+	    }
+	    break;
+	  }
+	} /* Early termination */
+
+	/*
+	  Check \beta''(k)
+	*/
+	if(checkLevel == 0){
+	  int i;
+	  
+	  cnfClauses = BmcCnfClausesAlloc();
+	  if (savedVerbosityLevel == BmcVerbosityMax_c) {
+	    (void) fprintf(vis_stdout, "# BMC: Check beta'' \n");
+	  }
+	  cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
+	  if (cnfFile == NIL(FILE)) {
+	    (void)fprintf(vis_stderr,
+			  "** bmc error: Cannot create CNF output file %s\n",
+			  options->satInFile);
+	    bmcError = TRUE;
+	    break;
+	  }
+	  /*
+	    Generate a simple path of length k+1.
+	  */
+	  BmcCnfGenerateClausesForLoopFreePath(network, 0, k+1, BMC_NO_INITIAL_STATES,
+					       cnfClauses, nodeToMvfAigTable, CoiTable);
+	  for(i=1; i<=k+1; i++){
+	    array_insert(int, unitClause, 0,
+			 -BmcGenerateCnfFormulaForAigFunction(manager, property,
+							      i, cnfClauses));
+	    BmcCnfInsertClause(cnfClauses, unitClause);
+	  }
+	  array_insert(int, unitClause, 0,
+		       BmcGenerateCnfFormulaForAigFunction(manager, property,
+							   0, cnfClauses));
+	  BmcCnfInsertClause(cnfClauses, unitClause);
+	  
+	  BmcWriteClauses(manager, cnfFile, cnfClauses, options);
+	  (void) fclose(cnfFile);
+	  
+	  result = BmcCheckSAT(options);
+	  BmcCnfClausesFree(cnfClauses);
+	  if(options->satSolverError){
+	    break;
+	  }
+	  if(result == NIL(array_t)) {
+	    m = k;
+	    printf("Beta'': Value of m = %d\n", m);
+	    checkLevel = 1;
+	  }
+	} /* Check for beta'' */
+	
+	/*
+	  Check \beta'(k) 
+	*/
+	if(checkLevel == 0){
+	  int i;
+	  
+	  cnfClauses = BmcCnfClausesAlloc();
+	  if (savedVerbosityLevel == BmcVerbosityMax_c) {
+	    (void) fprintf(vis_stdout, "# BMC: Check beta' \n");
+	  }
+	  cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
+	  if (cnfFile == NIL(FILE)) {
+	    (void)fprintf(vis_stderr,
+			  "** bmc error: Cannot create CNF output file %s\n",
+			  options->satInFile);
+	    bmcError = TRUE;
+	    break;
+	  }
+	  /*
+	    Generate a simple path of length k+1.
+	  */
+	  BmcCnfGenerateClausesForLoopFreePath(network, 0, k+1, BMC_NO_INITIAL_STATES,
+					       cnfClauses, nodeToMvfAigTable, CoiTable);
+	  for(i=0; i<=k; i++){
+	    array_insert(int, unitClause, 0,
+			 -BmcGenerateCnfFormulaForAigFunction(manager, property,
+							      i, cnfClauses));
+	    BmcCnfInsertClause(cnfClauses, unitClause);
+	  }
+	  array_insert(int, unitClause, 0,
+		       BmcGenerateCnfFormulaForAigFunction(manager, property,
+							   k+1, cnfClauses));
+	  BmcCnfInsertClause(cnfClauses, unitClause);
+	  
+	  BmcWriteClauses(manager, cnfFile, cnfClauses, options);
+	  (void) fclose(cnfFile);
+	  
+	  result = BmcCheckSAT(options);
+	  BmcCnfClausesFree(cnfClauses);
+	  if(options->satSolverError){
+	    break;
+	  }
+	  if(result == NIL(array_t)) {
+	    m = k;
+	    printf("Beta': Value of m = %d\n", m);
+	    checkLevel = 1;
+	  }
+	} /* Check for beta' */
+	/*
+	  Check for beta
+	*/
+	if(checkLevel == 1){
+	  cnfClauses = BmcCnfClausesAlloc();
+	  if (savedVerbosityLevel == BmcVerbosityMax_c) {
+	    (void) fprintf(vis_stdout, "# BMC: Check beta\n");
+	  }	  
+	  cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
+	  if (cnfFile == NIL(FILE)) {
+	    (void)fprintf(vis_stderr,
+			  "** bmc error: Cannot create CNF output file %s\n",
+			  options->satInFile);
+	    bmcError = TRUE;
+	    break;
+	  }
+	  /*
+	    Generate a simple path of length k+1.
+	  */
+	  BmcCnfGenerateClausesForLoopFreePath(network, 0, k+1, BMC_NO_INITIAL_STATES,
+					       cnfClauses, nodeToMvfAigTable, CoiTable);
+	  array_insert(int, unitClause, 0,
+		       -BmcGenerateCnfFormulaForAigFunction(manager, property,
+							    k, cnfClauses));
+	  BmcCnfInsertClause(cnfClauses, unitClause);
+	  array_insert(int, unitClause, 0,
+		       BmcGenerateCnfFormulaForAigFunction(manager, property,
+							   k+1, cnfClauses));
+	  BmcCnfInsertClause(cnfClauses, unitClause);
+	  
+	  BmcWriteClauses(manager, cnfFile, cnfClauses, options);
+	  (void) fclose(cnfFile);
+	  
+	  result = BmcCheckSAT(options);
+	  BmcCnfClausesFree(cnfClauses);
+	  if(options->satSolverError){
+	    break;
+	  }
+	  if(result == NIL(array_t)) {
+	    checkLevel = 2;
+	  }
+	} /* Check beta */
+      
+	if(checkLevel == 2){ /* we check \alpha if \beta UNSAT */
+	  if (savedVerbosityLevel == BmcVerbosityMax_c) {
+	    (void) fprintf(vis_stdout, "# BMC: Check alpha \n");
+	  }	  
+	  /*
+	    \alpha(k)
+	  */
+	  cnfClauses = BmcCnfClausesAlloc();
+	 
+	  cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
+	  if (cnfFile == NIL(FILE)) {
+	    (void)fprintf(vis_stderr,
+			  "** bmc error: Cannot create CNF output file %s\n",
+			  options->satInFile);
+	    bmcError = TRUE;
+	    break;
+	  }
+	  /*
+	    Generate an initialized path of length k.
+	  */
+	  BmcCnfGenerateClausesForLoopFreePath(network, 0, k, BMC_INITIAL_STATES,
+					       cnfClauses, nodeToMvfAigTable, CoiTable);
+	  
+	  array_insert(int, unitClause, 0,
+		       BmcGenerateCnfFormulaForAigFunction(manager, property,
+							   k, cnfClauses));
+	  BmcCnfInsertClause(cnfClauses, unitClause);
+	  
+	  
+	  BmcWriteClauses(manager, cnfFile, cnfClauses, options);
+	  (void) fclose(cnfFile);
+	  
+	  result = BmcCheckSAT(options);
+	  BmcCnfClausesFree(cnfClauses);
+	  if(options->satSolverError){
+	    break;
+	  }
+	  if(result == NIL(array_t)) {
+	    n = k;
+	    checkLevel = 3;
+	    printf("m=%d  n=%d\n",m,n);
+	    if ((m+n-1) <= maxK){
+	      maxK = m+n-1;
+	    } else {
+	      checkLevel = 4;
+	    }
+	  }
+	}/* Check alpha */
+	array_free(unitClause);
+	options->verbosityLevel = (Bmc_VerbosityLevel) savedVerbosityLevel;
+      } /* Prove the property passes*/
+    k += options->step;
+  } /* while result and k*/
+  if (bmcError == FALSE){
+    if(options->satSolverError){
+      (void) fprintf(vis_stdout,"# BMC: Error in calling SAT solver\n");
+    } else {
+      if(checkLevel == 3){
+	(void) fprintf(vis_stdout, "# BMC: (m+n-1) Complete the theorem\n");
+	formulaStatus = BmcPropertyPassed_c;
+      }
+      if(formulaStatus == BmcPropertyFailed_c) {
+	(void) fprintf(vis_stdout, "# BMC: formula failed\n");
+	if(options->verbosityLevel != BmcVerbosityNone_c){
+	  (void) fprintf(vis_stdout,
+			 "# BMC: Found a counterexample of length = %d \n", k);
+	}
+	if (options->dbgLevel == 1) {
+	  BmcPrintCounterExample(network, nodeToMvfAigTable, cnfClauses,
+				 result, k, CoiTable, options, loopClause);
+	  BmcCnfClausesFree(cnfClauses);
+	  array_free(loopClause);
+	}
+      } else if(formulaStatus == BmcPropertyPassed_c) {
+	(void) fprintf(vis_stdout, "# BMC: formula Passed\n");
+      } else if(formulaStatus == BmcPropertyUndecided_c) {
+	(void) fprintf(vis_stdout,"# BMC: formula undecided\n");
+	if (options->verbosityLevel != BmcVerbosityNone_c){
+	  (void) fprintf(vis_stdout,
+			 "# BMC: no counterexample found of length up to %d \n",
+			 maxK);
+	}
+      }
+    }
+  }
+  /*
+    free all used memories
+  */
+  array_free(tmpClause);
+ 
+  if(result != NIL(array_t)){
+    array_free(result);
+  }
+  if (options->verbosityLevel != BmcVerbosityNone_c) {
+    endTime = util_cpu_ctime();
+    fprintf(vis_stdout, "-- abmc time = %10g\n",
+	    (double)(endTime - startTime) / 1000.0);
+  }
+  fflush(vis_stdout);
+  return;
+} /* BmcLtlVerifyGFp() */
+
+/**Function********************************************************************
+
+   Synopsis [Apply Bounded Model Checking (BMC) on an LTL formula of
+   depth = 1]
+
+   Description [The depth of the LTL formula f is the maximum level of
+   nesting of temporal operators in f.  If the depth of the LTL
+   formula = 1, the translation of the formula in case of loop is
+   independent of the loop.
+
+   Note: Before calling this function, the LTL formula must be negated. 
+   
+   ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+BmcLtlVerifyUnitDepth(
+   Ntk_Network_t   *network,
+   Ctlsp_Formula_t *ltlFormula,
+   st_table        *CoiTable,
+   BmcOption_t     *options)
+{
+  mAig_Manager_t    *manager = Ntk_NetworkReadMAigManager(network);
+  st_table          *nodeToMvfAigTable = NIL(st_table);  /* node to mvfAig */
+  BmcCnfClauses_t   *cnfClauses = NIL(BmcCnfClauses_t);
+  FILE              *cnfFile;
+
+  array_t           *orClause =NIL(array_t);
+  array_t           *loopClause, *tmpclause;
+  int               l, loopIndex, andIndex, loop;
+  int               noLoopIndex;
+  array_t           *result = NIL(array_t);
+  
+  int               leftValue  = 0;
+  int               rightValue = 0;
+  long              startTime, endTime;
+  int               k;
+  int               minK = options->minK;
+  int               maxK = options->maxK;
+                    /* Store the index of a loop from k to all sate from 0 to k */
+  
+  Bmc_PropertyStatus       formulaStatus;
+  BmcCheckForTermination_t *terminationStatus = 0;
+  int                      bmcStatus=0; /* Holds the status of running BMC
+					   = -1 if there is an error */
+  
+  assert(Ctlsp_LtlFormulaDepth(ltlFormula) == 1);
+  
+  /* ************** */
+  /* Initialization */
+  /* ************** */
+  
+  startTime = util_cpu_ctime();
+  /*
+    nodeToMvfAigTable maps each node to its multi-function AIG graph
+  */
+  nodeToMvfAigTable =
+    (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+  assert(nodeToMvfAigTable != NIL(st_table));
+
+  loopClause = NIL(array_t);
+  
+  if (options->verbosityLevel != BmcVerbosityNone_c){
+    (void) fprintf(vis_stdout, "Unit depth LTL formula\n");
+    (void) fprintf(vis_stdout, "Apply BMC on counterexample of length >= %d and <= %d (+%d) \n",
+		  minK, maxK, options->step);
+  }
+   if(options->inductiveStep !=0){
+     /*
+       Use the termination criteria to prove the property passes.    
+     */
+     terminationStatus = BmcAutTerminationAlloc(network,
+						Ctlsp_LtllFormulaNegate(ltlFormula),
+						NIL(array_t));
+     assert(terminationStatus);
+   }
+  k = minK;
+  formulaStatus = BmcPropertyUndecided_c;
+  while( (result == NIL(array_t)) && (k <= maxK)){
+    if (options->verbosityLevel == BmcVerbosityMax_c) {
+      (void) fprintf(vis_stdout, "\nGenerate counterexample of length %d\n", k);
+    }
+    /*
+      Create clause database
+     */
+    cnfClauses = BmcCnfClausesAlloc();
+
+    cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
+    if (cnfFile == NIL(FILE)) {
+      (void)fprintf(vis_stderr,
+		    "** bmc error: Cannot create CNF output file %s\n",
+		    options->satInFile);
+      bmcStatus = -1;
+      break;
+    }
+    /*
+      Generate clauses represent an initialized path of length k
+     */
+    BmcCnfGenerateClausesForPath(network, 0, k, BMC_INITIAL_STATES,
+				 cnfClauses, nodeToMvfAigTable, CoiTable);
+    /*
+      Generate clauses represent paths which satisfy the LTL formula if
+      there is no loop.
+    */
+    noLoopIndex = BmcGenerateCnfForLtl(network, ltlFormula, 0, k, -1, cnfClauses);
+    leftValue   = checkIndex(noLoopIndex, cnfClauses);
+    if (leftValue != 1) { /* no loop  part of the basic encoding is not TRUE */
+      orClause = array_alloc(int, 0);   
+      /*
+        No need to check for !Lk in the basic encoding 
+      */
+      if (leftValue == -1){ /* no loop part of the basic encoding is not FALSE */
+	array_insert_last(int, orClause, noLoopIndex);
+      }
+      /*
+	Generate clauses represent paths which satisfy the LTL formula if
+	there is a loop.
+      */
+      loopIndex = BmcGenerateCnfForLtl(network, ltlFormula, 0, k, 0, cnfClauses);
+      rightValue = checkIndex(loopIndex, cnfClauses);
+      if (rightValue == 0){ /* loop  part of the basic encoding is FALSE */
+	break;
+      }
+      /*
+	rightValue can be 1 or -1
+	leftValue can be 0 or -1
+       */
+      if (noLoopIndex == loopIndex){ /* do not check for the existence of a loop*/
+	break;
+      }
+      /*
+	Clauses for loop-back path.
+       */
+      loopClause = array_alloc(int, k+2);
+      for(l=0; l<=k; l++){
+	  loop = cnfClauses->cnfGlobalIndex++;
+	  BmcCnfGenerateClausesFromStateToState(network, k, l, cnfClauses,
+						nodeToMvfAigTable, CoiTable, loop);
+	  array_insert(int, loopClause, l, loop);
+      } /* for l loop */
+      loop = cnfClauses->cnfGlobalIndex++;
+      array_insert(int, loopClause, k+1, -loop);
+      BmcCnfInsertClause(cnfClauses, loopClause);
+      if(rightValue == -1){
+	andIndex   = cnfClauses->cnfGlobalIndex++;
+	tmpclause  = array_alloc(int, 2);
+	
+	array_insert(int, tmpclause, 0, loop);
+	array_insert(int, tmpclause, 1, -andIndex);
+	BmcCnfInsertClause(cnfClauses, tmpclause);
+	
+	array_insert(int, tmpclause, 0, loopIndex);
+	array_insert(int, tmpclause, 1, -andIndex);
+	BmcCnfInsertClause(cnfClauses, tmpclause);
+	
+	array_free(tmpclause);
+	array_insert_last(int, orClause, andIndex);
+      } else {
+	array_insert_last(int, orClause, loop);
+      }
+    }
+    /* if((leftValue == 1) || (rightValue == 1)){ */
+    if(leftValue == 1){
+      assert(k==1);
+      /*
+	formula failed
+      */
+      formulaStatus = BmcPropertyFailed_c;
+      if (options->verbosityLevel != BmcVerbosityNone_c){
+	(void) fprintf(vis_stdout,"# BMC: Empty counterexample because the property is always FALSE\n");
+      }
+      break;
+    } else if((leftValue == 0) && (rightValue == 0)){
+      if (options->verbosityLevel != BmcVerbosityNone_c){
+	(void) fprintf(vis_stdout,"# BMC: the formula is trivially true");
+	(void) fprintf(vis_stdout," for counterexamples of length %d\n", k);
+      }
+    } else {
+      BmcCnfInsertClause(cnfClauses, orClause);
+      array_free(orClause);
+      BmcWriteClauses(manager, cnfFile, cnfClauses, options);
+      (void) fclose(cnfFile);
+      
+      result = BmcCheckSAT(options);
+      if(options->satSolverError){
+	break;
+      }
+      if(result != NIL(array_t)) {
+	/*
+	  formula failed
+	*/
+	formulaStatus = BmcPropertyFailed_c;
+      } else {
+	/* free some used memories */
+	BmcCnfClausesFree(cnfClauses);
+	array_free(loopClause);
+	/*
+	  Use the termination check
+	*/
+
+	if(terminationStatus && (formulaStatus == BmcPropertyUndecided_c) && (bmcStatus != 1)){
+	  if((options->inductiveStep !=0) &&
+	     (k % options->inductiveStep == 0)
+	     )
+	    {
+	      /*
+		Check for termination for the current value of k.
+	      */
+	      terminationStatus->k = k;
+	      bmcStatus = BmcAutLtlCheckForTermination(network,
+						       NIL(array_t), terminationStatus,
+						       nodeToMvfAigTable, CoiTable, options);
+	      if(bmcStatus == 1){
+		maxK = options->maxK;
+	      }
+	      if(bmcStatus == 3){
+		formulaStatus = BmcPropertyPassed_c;
+		break;
+	      }
+	      if(bmcStatus == -1){
+		break;
+	      }
+	    }
+	} /* terminationStatus */
+      }
+    }
+    k += options->step;
+  } /* while result and k*/
+
+ /*
+    If no error.
+   */
+  if(bmcStatus != -1){
+    if(bmcStatus == 1){
+      (void) fprintf(vis_stdout,
+		     "# BMC: no counterexample found of length up to %d \n", options->maxK);
+      (void) fprintf(vis_stdout, "# BMC: By termination criterion (m+n-1)\n");
+      formulaStatus = BmcPropertyPassed_c;
+    }
+    if(options->satSolverError){
+      (void) fprintf(vis_stdout,"# BMC: Error in calling SAT solver\n");
+    } else {
+      if(formulaStatus == BmcPropertyFailed_c) {
+	(void) fprintf(vis_stdout, "# BMC: formula failed\n");
+	if(options->verbosityLevel != BmcVerbosityNone_c){
+	  (void) fprintf(vis_stdout,
+			 "# BMC: Found a counterexample of length = %d \n", k);
+	}
+	if ((options->dbgLevel == 1) && (result != NIL(array_t))) {
+	  BmcPrintCounterExample(network, nodeToMvfAigTable, cnfClauses,
+				 result, k, CoiTable, options, loopClause);
+	}
+	/* free some used memories */
+	BmcCnfClausesFree(cnfClauses);
+	array_free(loopClause);
+	array_free(result);
+      } else if(formulaStatus == BmcPropertyPassed_c) {
+	(void) fprintf(vis_stdout, "# BMC: formula Passed\n");
+	(void) fprintf(vis_stdout, "#      Termination depth = %d\n", maxK);
+      } else if(formulaStatus == BmcPropertyUndecided_c) {
+	(void) fprintf(vis_stdout,"# BMC: formula undecided\n");
+	if (options->verbosityLevel != BmcVerbosityNone_c){
+	  (void) fprintf(vis_stdout,
+			 "# BMC: no counterexample found of length up to %d \n",
+			 maxK);
+	}
+      }
+    }
+  }
+  if (options->verbosityLevel != BmcVerbosityNone_c) {
+    endTime = util_cpu_ctime();
+    fprintf(vis_stdout, "-- bmc time = %10g\n",
+	    (double)(endTime - startTime) / 1000.0);
+  }
+  if(terminationStatus){
+    BmcAutTerminationFree(terminationStatus);
+  }
+  fflush(vis_stdout);
+  return;
+} /* Bmc_VerifyUnitDepth() */
+
+/**Function********************************************************************
+
+  Synopsis    [Use BMC to verify a general LTL formulae]
+
+  Description [Implements the Bounded Model Checking technique as in the paper
+  "Symbolic Model Checking without BDDs".  We also have implemented some of the
+  improvements in the BMC encoding described in the paper "Improving the
+  Encoding of LTL Model Checking into SAT" ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+BmcLtlVerifyGeneralLtl(
+   Ntk_Network_t   *network,
+   Ctlsp_Formula_t *ltlFormula,
+   st_table        *CoiTable,
+   array_t         *constraintArray,
+   BmcOption_t     *options)
+{
+  mAig_Manager_t    *manager = Ntk_NetworkReadMAigManager(network);
+  st_table          *nodeToMvfAigTable = NIL(st_table);  /* node to mvfAig */
+  BmcCnfClauses_t   *cnfClauses = NIL(BmcCnfClauses_t);
+  FILE              *cnfFile;
+
+  array_t           *orClause = NIL(array_t);
+  array_t           *loopClause, *tmpclause;
+  int               l, loopIndex, andIndex, loop;
+  int               noLoopIndex;
+  array_t           *result = NIL(array_t);
+  array_t           *fairnessArray = NIL(array_t);
+  int               leftValue  = 0;
+  int               rightValue = 0;
+  long              startTime, endTime;
+  int               k;
+  int               minK = options->minK;
+  int               maxK = options->maxK;
+  boolean           boundedFormula;
+  int               depth;
+                    /* Store the index of loop from k to all sate from 0 to k */
+  
+  array_t           *ltlConstraintArray;	/* constraints converted to LTL */
+  int               f;
+  boolean           fairness  = (constraintArray != NIL(array_t));
+
+  BmcCheckForTermination_t *terminationStatus = 0;
+  Bmc_PropertyStatus       formulaStatus;
+  int                      bmcStatus=0; /* Holds the status of running BMC
+					   = -1 if there is an error */
+  
+  /* ************** */
+  /* Initialization */
+  /* ************** */
+  startTime = util_cpu_ctime();
+  /*
+    nodeToMvfAigTable maps each node to its multi-function And/Inv graph
+  */
+  nodeToMvfAigTable =
+    (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+  assert(nodeToMvfAigTable != NIL(st_table));
+
+  loopClause = NIL(array_t);
+  noLoopIndex = 0;
+  ltlConstraintArray = NIL(array_t);
+  if(fairness){
+    Ctlsp_Formula_t *formula;
+    int              i;
+    /*
+      All formulae in constraintArray are propositional, propositional
+      constraint.
+    */
+    ltlConstraintArray = array_alloc(Ctlsp_Formula_t *, 0);
+    arrayForEachItem(Ctlsp_Formula_t *, constraintArray, i, formula) {
+      /*
+	To help making propositional constraint easy to encode.
+      */
+      formula =  Ctlsp_FormulaCreate(Ctlsp_F_c, formula, NIL(Ctlsp_Formula_t));
+      array_insert(Ctlsp_Formula_t *, ltlConstraintArray, i, formula);
+      BmcGetCoiForLtlFormula(network, formula, CoiTable);
+    }
+  }
+  /*
+    For bounded formulae use a tighter upper bound if possible.
+  */
+  boundedFormula = Ctlsp_LtlFormulaTestIsBounded(ltlFormula, &depth);
+  if (boundedFormula && depth < maxK && depth >= minK) {
+    maxK = depth;
+  } else {
+    if(options->inductiveStep !=0){
+      /*
+	Use the termination criteria to prove the property passes.    
+      */
+      terminationStatus = BmcAutTerminationAlloc(network,
+						 Ctlsp_LtllFormulaNegate(ltlFormula),
+						 constraintArray);
+      assert(terminationStatus);
+    }
+  }
+  if (options->verbosityLevel != BmcVerbosityNone_c){
+    (void) fprintf(vis_stdout, "General LTL BMC\n");
+    if (boundedFormula){
+      (void) fprintf(vis_stdout, "Bounded formula of depth %d\n", depth);
+    }
+    (void) fprintf(vis_stdout, "Apply BMC on counterexample of length >= %d and <= %d (+%d) \n",
+		  minK, maxK, options->step);
+  }
+  k= minK;
+  formulaStatus = BmcPropertyUndecided_c;
+  while( (result == NIL(array_t)) && (k <= maxK)){
+    if (options->verbosityLevel == BmcVerbosityMax_c) {
+      (void) fprintf(vis_stdout, "\nGenerate counterexample of length %d\n", k);
+    }
+
+    cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
+    if (cnfFile == NIL(FILE)) {
+      (void)fprintf(vis_stderr,
+		    "** bmc error: Cannot create CNF output file %s\n",
+		    options->satInFile);
+      bmcStatus = -1;
+      break;
+    }
+    /*
+      Create a clause database
+     */
+    cnfClauses = BmcCnfClausesAlloc();
+    /*
+      Gnerate clauses for an initialized path of length k
+     */
+    BmcCnfGenerateClausesForPath(network, 0, k, BMC_INITIAL_STATES,
+				 cnfClauses, nodeToMvfAigTable, CoiTable);
+
+    if(!fairness){ /* No fairness constraint */
+      noLoopIndex = BmcGenerateCnfForLtl(network, ltlFormula, 0, k, -1, cnfClauses);
+      leftValue   = checkIndex(noLoopIndex, cnfClauses);
+    } else {
+      leftValue = 0; /* the path must have a loop*/
+    }
+    if (leftValue != 1) {
+      orClause = array_alloc(int, 0);   
+      /*
+        No need to check for !Lk in the basic encoding 
+      */
+      if (leftValue == -1){
+	array_insert_last(int, orClause, noLoopIndex);
+      }
+      loopClause = array_alloc(int, k+1);
+     
+      for(l=0; l<=k; l++){
+	loopIndex = BmcGenerateCnfForLtl(network, ltlFormula, 0, k, l, cnfClauses);
+	rightValue = checkIndex(loopIndex, cnfClauses);
+	if (rightValue == 0){
+	  break;
+	}
+	if(fairness){
+	  Ctlsp_Formula_t *formula;
+	  int             i;
+
+	  fairnessArray = array_alloc(int, 0);
+	  arrayForEachItem(Ctlsp_Formula_t *, ltlConstraintArray, i, formula) {
+	    array_insert_last(int, fairnessArray,
+			      BmcGenerateCnfForLtl(network, formula, l, k, -1, cnfClauses));
+	  }
+	}
+	if (rightValue !=0){
+	  loop = cnfClauses->cnfGlobalIndex++;
+	  BmcCnfGenerateClausesFromStateToState(network, k, l, cnfClauses,
+						nodeToMvfAigTable, CoiTable, loop);
+	  array_insert(int, loopClause, l, loop);
+	  if(rightValue == -1){
+	    
+	    andIndex   = cnfClauses->cnfGlobalIndex++;
+	    tmpclause  = array_alloc(int, 2);
+	    array_insert(int, tmpclause, 0, loop);
+	    array_insert(int, tmpclause, 1, -andIndex);
+	    BmcCnfInsertClause(cnfClauses, tmpclause);
+
+	    array_insert(int, tmpclause, 0, loopIndex);
+	    array_insert(int, tmpclause, 1, -andIndex);
+	    BmcCnfInsertClause(cnfClauses, tmpclause);
+	    
+	    if(fairness){
+	      for(f=0; f < array_n(fairnessArray); f++){
+		array_insert(int, tmpclause, 0, array_fetch(int, fairnessArray, f)); 
+		array_insert(int, tmpclause, 1, -andIndex);
+		BmcCnfInsertClause(cnfClauses, tmpclause);
+	      }
+	    }
+	    array_free(tmpclause);
+	    array_insert_last(int, orClause, andIndex);
+	  } else {
+	    array_insert_last(int, orClause, loop);
+	  }
+	}
+	if(fairness){
+	  array_free(fairnessArray);
+	}
+      } /* for l loop */
+    }
+    if((leftValue == 1) || (rightValue == 1)){
+      assert(k==1);
+      if (options->verbosityLevel != BmcVerbosityNone_c){
+	formulaStatus = BmcPropertyFailed_c;
+	(void) fprintf(vis_stdout,"# BMC: Empty counterexample because the property is always FALSE\n");
+      }
+      break;
+    } else if((leftValue == 0) && (rightValue == 0)){
+      if (options->verbosityLevel != BmcVerbosityNone_c){
+	(void) fprintf(vis_stdout,"# BMC: the formula is trivially true");
+	(void) fprintf(vis_stdout," for counterexamples of length %d\n", k);
+      }
+    } else {
+      /*
+      BmcCnfInsertClause(cnfClauses, loopClause);
+      */
+      BmcCnfInsertClause(cnfClauses, orClause);
+      /*
+      array_free(loopClause);
+      */
+      array_free(orClause);
+      BmcWriteClauses(manager, cnfFile, cnfClauses, options);
+      (void) fclose(cnfFile);
+      
+      result = BmcCheckSAT(options);
+      if(options->satSolverError){
+	break;
+      }
+      if(result != NIL(array_t)) {
+	/*
+	  formula failed\n"
+	 */
+	formulaStatus = BmcPropertyFailed_c;
+	break;
+      }
+      array_free(loopClause);
+    }
+    /* free all used memories */
+    BmcCnfClausesFree(cnfClauses);
+    cnfClauses = NIL(BmcCnfClauses_t);
+    
+    /*
+      Use the termination check if the the LTL formula is not bounded
+     */
+    if(terminationStatus && (formulaStatus == BmcPropertyUndecided_c) && (bmcStatus != 1)){
+      if((options->inductiveStep !=0) &&
+	 (k % options->inductiveStep == 0)
+	 )
+	{
+	  /*
+	    Check for termination for the current value of k.
+	   */
+	  terminationStatus->k = k;
+	  bmcStatus = BmcAutLtlCheckForTermination(network,
+						   constraintArray, terminationStatus,
+						   nodeToMvfAigTable, CoiTable, options);
+	  if(bmcStatus == 1){
+	    maxK = terminationStatus->k;
+	  }
+	  if(bmcStatus == 3){
+	    formulaStatus = BmcPropertyPassed_c;
+	    break;
+	  }
+	  if(bmcStatus == -1){
+	    break;
+	  }
+	}
+    } /* terminationStatus */
+    k += options->step;
+  } /* while result and k*/
+
+  /*
+    If no error.
+   */
+  if(bmcStatus != -1){
+    /*
+    if(result == NIL(array_t)){
+    */
+    if(formulaStatus == BmcPropertyUndecided_c){
+      if(bmcStatus == 1){
+	(void) fprintf(vis_stdout,
+		       "# BMC: no counterexample found of length up to %d \n", maxK);
+	(void) fprintf(vis_stdout, "# BMC: By termination criterion (m+n-1)\n");
+	formulaStatus = BmcPropertyPassed_c;
+      }
+      if (boundedFormula && depth <= options->maxK){
+	(void) fprintf(vis_stdout,
+		       "# BMC: no counterexample found of length up to %d \n", depth);
+	formulaStatus = BmcPropertyPassed_c;
+      }
+    }
+    if(options->satSolverError){
+      (void) fprintf(vis_stdout,"# BMC: Error in calling SAT solver\n");
+    } else {
+      if(formulaStatus == BmcPropertyFailed_c) {
+	(void) fprintf(vis_stdout, "# BMC: formula failed\n");
+	if(options->verbosityLevel != BmcVerbosityNone_c){
+	  (void) fprintf(vis_stdout,
+			 "# BMC: Found a counterexample of length = %d \n", k);
+	}
+	if ((options->dbgLevel == 1) && (result != NIL(array_t))) {
+	  BmcPrintCounterExample(network, nodeToMvfAigTable, cnfClauses,
+				 result, k, CoiTable, options, loopClause);
+	}
+	/*BmcCnfClausesFree(cnfClauses);*/
+	array_free(loopClause);
+      } else if(formulaStatus == BmcPropertyPassed_c) {
+	(void) fprintf(vis_stdout, "# BMC: formula Passed\n");
+	(void) fprintf(vis_stdout, "#      Termination depth = %d\n", maxK);
+      } else if(formulaStatus == BmcPropertyUndecided_c) {
+	(void) fprintf(vis_stdout,"# BMC: formula undecided\n");
+	if (options->verbosityLevel != BmcVerbosityNone_c){
+	  (void) fprintf(vis_stdout,
+			 "# BMC: no counterexample found of length up to %d \n",
+			 maxK);
+	}
+      }
+    }
+  }
+  if (options->verbosityLevel != BmcVerbosityNone_c) {
+    endTime = util_cpu_ctime();
+    fprintf(vis_stdout, "-- bmc time = %10g\n",
+	    (double)(endTime - startTime) / 1000.0);
+  }
+  /*
+    free all used memories
+  */
+  if(terminationStatus){
+    BmcAutTerminationFree(terminationStatus);
+  }
+  if(result != NIL(array_t)){
+    array_free(result);
+  }
+  if(cnfClauses != NIL(BmcCnfClauses_t)){
+    BmcCnfClausesFree(cnfClauses);
+  }
+  if(fairness){
+    /*Ctlsp_FormulaArrayFree(ltlConstraintArray);*/
+  }
+  fflush(vis_stdout);
+  return;
+} /* BmcLtlVerifyGeneralLtl() */
+
+/**Function********************************************************************
+
+  Synopsis    [Generate CNF for an LTL formula]
+
+  Description [Generate array of clauses for a trnasition from state i to
+              state k. If l is non-zero, it will also generate the clauses
+	      from state l to state i.
+	      
+              if the clause array is empty {}, the propety is always TRUE
+	      if the the clause array has one empty clause {{}}, the property
+	      is always FALSE.
+	      return the clause index number.
+  ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+BmcGenerateCnfForLtl(
+   Ntk_Network_t   *network,
+   Ctlsp_Formula_t *ltlFormula,
+   int             i /* from state i */,
+   int             k /* to state k   */,
+   int             l /* loop         */,
+   BmcCnfClauses_t *cnfClauses)
+{
+  int left, right, cnfIndex;
+  int andIndex, orIndex;
+  int j, n;
+  int leftValue, rightValue, andValue, orValue;
+  
+  mAig_Manager_t  *manager = Ntk_NetworkReadMAigManager(network);
+  array_t         *clause, *tmpclause, *orClause, *rightClause, *leftClause;
+  BmcCnfStates_t  *state;
+  
+  assert(ltlFormula != NIL(Ctlsp_Formula_t));
+  right = 0;
+  rightValue = 0;
+  
+  if(Ctlsp_isPropositionalFormula(ltlFormula)){
+    bAigEdge_t property = BmcCreateMaigOfPropFormula(network, manager, ltlFormula);
+       
+    if (property == bAig_Zero){ /* FALSE */
+      /* add an empty clause to indicate FALSE property */
+      BmcAddEmptyClause(cnfClauses);
+      return 0;
+    }
+    if (property == bAig_One){ /* TRUE */
+      /* Don't generate any clause to indicate TRUE property.*/
+      return 0;
+    }
+    /* Generate the clause of the propositional formula */
+    /* The state of the input variables is the same as the state of the state variables. */
+    cnfIndex = BmcGenerateCnfFormulaForAigFunction(manager, property, i, cnfClauses);    
+    return cnfIndex;
+  }
+  /*
+   * Formula is NOT propositional formula 
+   */
+  switch(ltlFormula->type) {
+    case Ctlsp_NOT_c:
+      /* reach here if formula-left is always not propositional*/
+      /* NOT must only appears infront of a propositional formula.*/
+      if (!Ctlsp_isPropositionalFormula(ltlFormula->left)){
+	fprintf(vis_stderr,"BMC error: the LTL formula is not in NNF\n");
+	return 0;
+      }
+      /*
+      return -1*BmcGenerateCnfForLtlNoLoop(network, ltlFormula->left, i, k,
+					   cnfIndexTable, clauseArray);
+      */
+      break;
+    case Ctlsp_AND_c:
+      /*
+	  c = a * b  -->  (!a + !b + c) * (a + !c) * (b + !c).
+	  Because a and b must be one, so we need only the last two clauses.
+       */
+      
+      state = BmcCnfClausesFreeze(cnfClauses);
+      rightValue = 1;
+      
+      left      = BmcGenerateCnfForLtl(network, ltlFormula->left,  i, k, l, cnfClauses);
+      leftValue = checkIndex(left, cnfClauses);
+
+      if (leftValue !=0){
+	right      = BmcGenerateCnfForLtl(network, ltlFormula->right, i, k, l, cnfClauses);
+	rightValue = checkIndex(right, cnfClauses);
+      }
+      if ((leftValue == 0) || (rightValue == 0)){
+	/* restore the information */
+	BmcCnfClausesRestore(cnfClauses, state);
+	/* add an empty clause*/
+	BmcAddEmptyClause(cnfClauses);
+	FREE(state);
+	return 0;  /* FALSE */
+      }
+      if ((leftValue == 1) && (rightValue == 1)){
+	/* restore the information */
+	BmcCnfClausesRestore(cnfClauses, state);
+	FREE(state);
+	return 0; /* TRUE */
+      }
+      BmcCnfClausesUnFreeze(cnfClauses, state);
+      FREE(state);
+      /*
+      tmpclause  = array_alloc(int, 3);
+      array_insert(int, tmpclause, 0, -left);
+      array_insert(int, tmpclause, 1, -right);
+      array_insert(int, tmpclause, 2,  cnfIndex);
+      array_insert_last(array_t *, clauseArray, tmpclause);
+      */
+      if (leftValue == 1){
+	return right;
+      }
+      if (rightValue == 1){
+	return left;
+      }
+      cnfIndex = cnfClauses->cnfGlobalIndex++;      
+      tmpclause  = array_alloc(int, 2);
+      
+      array_insert(int, tmpclause, 0, left);
+      array_insert(int, tmpclause, 1, -cnfIndex);
+      BmcCnfInsertClause(cnfClauses, tmpclause);
+      
+      array_insert(int, tmpclause, 0, right);
+      array_insert(int, tmpclause, 1, -cnfIndex);
+      BmcCnfInsertClause(cnfClauses, tmpclause);
+      array_free(tmpclause);
+
+      return cnfIndex;
+    case Ctlsp_OR_c:
+      /*
+	  c = a + b  -->  (a + b + !c) * (!a + c) * (!b + c).
+	  Because a and b must be one, so we need only the first clause.
+       */
+      state = BmcCnfClausesFreeze(cnfClauses);
+            
+      left      = BmcGenerateCnfForLtl(network, ltlFormula->left,  i, k, l, cnfClauses);
+      leftValue = checkIndex(left, cnfClauses);
+
+      if (leftValue !=1){
+	right      = BmcGenerateCnfForLtl(network, ltlFormula->right, i, k, l, cnfClauses);
+	rightValue = checkIndex(right, cnfClauses);
+      }
+      if ((leftValue == 1) || (rightValue == 1)){
+	/* restore the information */
+	BmcCnfClausesRestore(cnfClauses, state);
+	FREE(state);
+	return 0;  /* TRUE */
+      } 
+      if ((leftValue == 0) && (rightValue == 0)){
+	/* restore the information */
+	BmcCnfClausesRestore(cnfClauses, state);
+	/* add an empty clause*/
+	BmcAddEmptyClause(cnfClauses);
+	FREE(state);
+	return 0;  /* FALSE */
+      }
+      BmcCnfClausesUnFreeze(cnfClauses, state);
+      FREE(state);
+      /* Either leftValue or rightValue = 0 and the other != 1
+         At least one clause will be added
+       */
+      if (leftValue == 0){
+	return right;
+      }
+      if (rightValue == 0){
+	return left;
+      }      
+      cnfIndex = cnfClauses->cnfGlobalIndex++;
+
+      tmpclause  = array_alloc(int, 0);
+      array_insert_last(int, tmpclause, -cnfIndex);
+      
+      array_insert_last(int, tmpclause, left);
+	/*
+	tmpclause  = array_alloc(int, 2);
+	array_insert(int, tmpclause, 0, -left);
+	array_insert(int, tmpclause, 1, cnfIndex);
+	array_insert_last(array_t *, clauseArray, tmpclause);
+	*/
+      array_insert_last(int, tmpclause, right);
+	/*
+	tmpclause  = array_alloc(int, 2);
+	array_insert(int, tmpclause, 0, -right);
+	array_insert(int, tmpclause, 1, cnfIndex);
+	array_insert_last(array_t *, clauseArray, tmpclause);
+	*/
+      BmcCnfInsertClause(cnfClauses, tmpclause);
+      array_free(tmpclause);
+      
+      return cnfIndex;
+    case Ctlsp_F_c:
+      if (l >= 0){ /* loop */
+	i = (l < i)? l: i;
+      }
+      cnfIndex = cnfClauses->cnfGlobalIndex++;
+      clause   = array_alloc(int, 0);
+      for (j=i; j<= k; j++){
+	left      = BmcGenerateCnfForLtl(network, ltlFormula->left, j, k, l, cnfClauses);
+	leftValue = checkIndex(left, cnfClauses);
+        if (leftValue != -1){
+	  array_free(clause);
+	  return 0;
+	}
+	array_insert_last(int, clause, left);
+	  /*
+	  tmpclause  = array_alloc(int, 2);
+	  array_insert(int, tmpclause, 1, cnfIndex);
+	  array_insert(int, tmpclause, 0, -left);
+	  array_insert_last(array_t *, clauseArray, tmpclause);
+	  */
+      }
+      array_insert_last(int, clause, -cnfIndex);
+      BmcCnfInsertClause(cnfClauses, clause);
+      array_free(clause);
+ 
+      return cnfIndex;
+    case Ctlsp_G_c:
+      if (l < 0){ /* FALSE */
+	/* add an empty clause */
+	BmcAddEmptyClause(cnfClauses);
+	return 0;
+      } else {
+       i = (l < i)? l: i;
+       andIndex = cnfClauses->cnfGlobalIndex++;
+       for (j=i; j<= k; j++){
+	 left      = BmcGenerateCnfForLtl(network, ltlFormula->left, j, k, l, cnfClauses);
+	 leftValue = checkIndex(left, cnfClauses);
+         if (leftValue != -1){
+	   return 0;
+	 }
+	 tmpclause  = array_alloc(int, 2);
+	 array_insert(int, tmpclause, 0, left);
+	 array_insert(int, tmpclause, 1, -andIndex);
+	 BmcCnfInsertClause(cnfClauses, tmpclause);
+	 array_free(tmpclause);
+       }/* for j loop*/
+      } /* else */
+      return andIndex;
+    case Ctlsp_X_c:
+      /* X left */
+      if((l >= 0) && (i == k) ){
+	i = l;
+      } else if (i < k){
+	i = i + 1;
+      } else { /* FALSE */
+	/* add an empty clause */
+	BmcAddEmptyClause(cnfClauses);
+	return 0;
+      }
+      return BmcGenerateCnfForLtl(network, ltlFormula->left, i, k, l, cnfClauses);
+    case Ctlsp_U_c: /* (left U right) */
+      state = BmcCnfClausesFreeze(cnfClauses);
+      
+      leftValue  = 1; /* left is TRUE*/
+      rightValue = 1; /* right is TRUE*/
+      orIndex    = cnfClauses->cnfGlobalIndex++;
+      orClause   = array_alloc(int, 0);
+      array_insert_last(int, orClause, -orIndex);
+
+      orValue = 0;
+      for (j=i; j<= k; j++){
+	right = BmcGenerateCnfForLtl(network, ltlFormula->right, j, k, l, cnfClauses);
+	rightValue = checkIndex(right, cnfClauses);
+	andIndex   = cnfClauses->cnfGlobalIndex++;
+	if (rightValue == -1){
+	  rightClause  = array_alloc(int, 2);
+	  array_insert(int, rightClause, 0, right);
+	  array_insert(int, rightClause, 1, -andIndex);
+	  BmcCnfInsertClause(cnfClauses, rightClause);
+	  array_free(rightClause);
+	}
+	andValue = rightValue;
+	for (n=i; (n <= j-1) && (andValue != 0); n++){
+	  left = BmcGenerateCnfForLtl(network, ltlFormula->left, n, k, l, cnfClauses);
+	  leftValue = checkIndex(left, cnfClauses);
+	  andValue  = doAnd(andValue, leftValue);
+	  if (leftValue == -1){
+	    leftClause  = array_alloc(int, 2);
+	    array_insert(int, leftClause, 0, left);
+	    array_insert(int, leftClause, 1, -andIndex);
+	    BmcCnfInsertClause(cnfClauses, leftClause);
+	    array_free(leftClause);
+	  }
+	} /* for n loop */
+	orValue = doOr(orValue, andValue);
+        if (orValue == 1){ /* TRUE */
+	  break;
+	}
+	if (andValue != 0){
+	  array_insert_last(int, orClause, andIndex);
+	}
+      } /* for j loop*/
+      if ( (l >=0) && (orValue !=1)){ /* loop */
+	for (j=l; j<= i-1; j++){
+	  right = BmcGenerateCnfForLtl(network, ltlFormula->right, j, k, l, cnfClauses);
+	  rightValue = checkIndex(right, cnfClauses);
+	  andIndex   = cnfClauses->cnfGlobalIndex++;
+	  if (rightValue == -1){
+	    rightClause  = array_alloc(int, 2);
+	    array_insert(int, rightClause, 0, right);
+	    array_insert(int, rightClause, 1, -andIndex);
+	    BmcCnfInsertClause(cnfClauses, rightClause);
+	    array_free(rightClause);
+	  }
+	  andValue = rightValue;  
+	  for (n=i; (n<= k) && (andValue != 0); n++){
+	    left = BmcGenerateCnfForLtl(network, ltlFormula->left, n, k, l, cnfClauses);
+	    leftValue = checkIndex(left, cnfClauses);
+	    andValue  = doAnd(andValue, leftValue);
+	    if (leftValue == -1){
+	      leftClause  = array_alloc(int, 2);
+	      array_insert(int, leftClause, 0, left);
+	      array_insert(int, leftClause, 1, -andIndex);
+	      BmcCnfInsertClause(cnfClauses, leftClause);
+	      array_free(leftClause);
+	    }
+	  } /* for n loop */
+	  for (n=l; (n<= j-1)  && (andValue != 0); n++){
+	    left = BmcGenerateCnfForLtl(network, ltlFormula->left, n, k, l, cnfClauses);
+	    leftValue = checkIndex(left, cnfClauses);
+	    andValue  = doAnd(andValue, leftValue);
+	    if (leftValue == -1){
+	      leftClause  = array_alloc(int, 2);
+	      array_insert(int, leftClause, 0, left);
+	      array_insert(int, leftClause, 1, -andIndex);
+	      BmcCnfInsertClause(cnfClauses, leftClause);
+	      array_free(leftClause);
+	    }
+	  } /* for n loop */
+	  orValue = doOr(orValue, andValue);
+	  if (orValue == 1){ /* TRUE */
+	    break;
+	  }
+	  if (andValue != 0){
+	    array_insert_last(int, orClause, andIndex);
+	  }
+	}/* j loop*/
+      } /* if (l>=0) */
+      if ((orValue == 1) || (orValue == 0)){
+	/*restore the infomration back*/
+	BmcCnfClausesRestore(cnfClauses, state);
+	FREE(state);
+	array_free(orClause);
+	if (orValue == 0){
+	  /* add an empty clause*/
+	  BmcAddEmptyClause(cnfClauses);
+	}
+	return 0;
+      } else {
+	BmcCnfClausesUnFreeze(cnfClauses, state);
+	FREE(state);
+	BmcCnfInsertClause(cnfClauses, orClause);
+	array_free(orClause);
+	return orIndex;
+      }
+    case Ctlsp_R_c:
+      /* (left R right) */
+      state = BmcCnfClausesFreeze(cnfClauses);
+      
+      orIndex  = cnfClauses->cnfGlobalIndex++;
+      orClause = array_alloc(int, 0);
+      array_insert_last(int, orClause, -orIndex);
+      
+      orValue = 0;
+      if (l >= 0){ /* loop */
+	andIndex = cnfClauses->cnfGlobalIndex++;
+	andValue = 1;
+	for (j=(i<l?i:l); (j<= k) && (andValue != 0); j++){
+	  right = BmcGenerateCnfForLtl(network, ltlFormula->right, j, k, l, cnfClauses);
+	  rightValue = checkIndex(right, cnfClauses);
+	  andValue  = doAnd(andValue, rightValue);
+	  if (rightValue == -1){
+	    rightClause  = array_alloc(int, 2);
+	    array_insert(int, rightClause, 0, right);
+	    array_insert(int, rightClause, 1, -andIndex);
+	    BmcCnfInsertClause(cnfClauses, rightClause);
+	    array_free(rightClause);
+	  }
+	} /* for j loop*/
+	if (andValue == -1){
+	  array_insert_last(int, orClause, andIndex);
+	}
+	orValue = doOr(orValue, andValue);
+      } /* loop */
+      if(orValue != 1){
+	for (j=i; j<= k; j++){
+	  left = BmcGenerateCnfForLtl(network, ltlFormula->left,
+				      j, k, l, cnfClauses);
+	  leftValue = checkIndex(left, cnfClauses);
+	  andIndex = cnfClauses->cnfGlobalIndex++;
+	  if (leftValue == -1){
+	    leftClause  = array_alloc(int, 2);
+	    array_insert(int, leftClause, 0, left);
+	    array_insert(int, leftClause, 1, -andIndex);
+	    BmcCnfInsertClause(cnfClauses, leftClause);
+	    array_free(leftClause);
+	  }
+	  andValue = leftValue;
+	  for (n=i; (n<= j) && (andValue != 0); n++){
+	    right = BmcGenerateCnfForLtl(network, ltlFormula->right,
+					 n, k, l, cnfClauses);
+	    rightValue = checkIndex(right, cnfClauses);
+	    andValue   = doAnd(andValue, rightValue);
+	    if (rightValue == -1){
+	      rightClause  = array_alloc(int, 2);
+	      array_insert(int, rightClause, 0, right);
+	      array_insert(int, rightClause, 1, -andIndex);
+	      BmcCnfInsertClause(cnfClauses, rightClause);
+	      array_free(rightClause);
+	    }
+	  } /* for n loop */
+	  orValue = doOr(orValue, andValue);
+	  if (orValue == 1){ /* TRUE */
+	    break;
+	  }
+	  if (andValue != 0){
+	    array_insert_last(int, orClause, andIndex);
+	  }
+	}/* for j loop*/
+	if ((l >= 0)  && (orValue !=1)) { /* loop */
+	  for (j=l; j<= i-1; j++){
+	    left = BmcGenerateCnfForLtl(network, ltlFormula->left,
+					j, k, l, cnfClauses);
+	    leftValue = checkIndex(left, cnfClauses);
+	    andIndex = cnfClauses->cnfGlobalIndex++;
+	    if (leftValue == -1){
+	      leftClause  = array_alloc(int, 2);
+	      array_insert(int, leftClause, 0, left);
+	      array_insert(int, leftClause, 1, -andIndex);
+	      BmcCnfInsertClause(cnfClauses, leftClause);
+	      array_free(leftClause);
+	    }
+	    andValue = leftValue;
+	    for (n=i; (n<= k)  && (andValue != 0); n++){
+	      right = BmcGenerateCnfForLtl(network, ltlFormula->right,
+					   n, k, l, cnfClauses);
+	      rightValue = checkIndex(right, cnfClauses);
+	      andValue = doAnd(andValue, rightValue);
+	      if (rightValue == -1){
+		rightClause  = array_alloc(int, 2);
+		array_insert(int, rightClause, 0, right);
+		array_insert(int, rightClause, 1, -andIndex);
+		BmcCnfInsertClause(cnfClauses, rightClause);
+		array_free(rightClause);
+	      }
+	    } /* for n loop */
+	    for (n=l; (n<= j) && (andValue != 0); n++){
+	      right = BmcGenerateCnfForLtl(network, ltlFormula->right,
+					   n, k, l, cnfClauses);
+	      rightValue = checkIndex(right, cnfClauses);
+	      andValue = doAnd(andValue, rightValue);
+	      if (rightValue == -1){
+		rightClause  = array_alloc(int, 2);
+		array_insert(int, rightClause, 0, right);
+		array_insert(int, rightClause, 1, -andIndex);
+		BmcCnfInsertClause(cnfClauses, rightClause);
+		array_free(rightClause);
+	      }
+	    } /* for n loop */
+	    orValue = doOr(orValue, andValue);
+	    if (orValue == 1){ /* TRUE */
+	      break;
+	    }
+	    if (andValue != 0){
+	      array_insert_last(int, orClause, andIndex);
+	    }
+	  } /* for j loop*/
+	} /* if (l>=0) */
+      }/* orValue !=1*/
+      if ((orValue == 1) || (orValue == 0)){
+	/*restore the infomration back*/
+	BmcCnfClausesRestore(cnfClauses, state);
+	FREE(state);
+	array_free(orClause);
+	if (orValue == 0){
+	  /* add an empty clause*/
+	  BmcAddEmptyClause(cnfClauses);
+	}
+	return 0;
+      } else {
+	BmcCnfClausesUnFreeze(cnfClauses, state);
+	FREE(state);
+	BmcCnfInsertClause(cnfClauses, orClause);
+	array_free(orClause);
+	return orIndex;
+      }
+    default:
+      fail("Unexpected LTL formula type");
+      break;
+  }
+  return -1; /* we should never get here */
+}
+/*  BmcLTLFormulaNoLoopTranslation() */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Apply bmc on an abbreviation-free LTL formula that expresses
+  safety propery]
+
+  Description [If an LTL formula expresses a safety property, we generate CNF
+                                        0
+  caluse for the part with no loop: [[f]]
+                                        k
+  ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+BmcLtlCheckSafety(
+   Ntk_Network_t   *network,
+   Ctlsp_Formula_t *ltlFormula,
+   BmcOption_t     *options,
+   st_table        *CoiTable)
+{
+  mAig_Manager_t    *manager = Ntk_NetworkReadMAigManager(network);
+  st_table          *nodeToMvfAigTable = NIL(st_table);  /* node to mvfAig */
+  BmcCnfClauses_t   *cnfClauses = NIL(BmcCnfClauses_t);
+  FILE              *cnfFile;
+  int               noLoopIndex;
+  array_t           *result = NIL(array_t);
+  int               leftValue  = 0;
+  long              startTime, endTime;
+  int               k;
+  int               minK = options->minK;
+  int               maxK = options->maxK;
+  boolean           boundedFormula;
+  int               depth;
+  array_t           *unitClause =  array_alloc(int, 1);
+  
+  array_t           *orClause =  array_alloc(int, 2);
+
+  /* ************** */
+  /* Initialization */
+  /* ************** */
+  startTime = util_cpu_ctime();
+  /* nodeToMvfAigTable maps each node to its multi-function And/Inv graph */
+  nodeToMvfAigTable =
+    (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+  assert(nodeToMvfAigTable != NIL(st_table));
+
+  /* For bounded formulae use a tighter upper bound if possible. */
+  boundedFormula = Ctlsp_LtlFormulaTestIsBounded(ltlFormula, &depth);
+  if (boundedFormula && depth < maxK && depth >= minK) {
+    maxK = depth;
+  }
+  if (options->verbosityLevel != BmcVerbosityNone_c){
+    (void) fprintf(vis_stdout, "saftey LTL BMC\n");
+    if (boundedFormula){
+      (void) fprintf(vis_stdout, "Bounded formula of depth %d\n", depth);
+    }
+    (void) fprintf(vis_stdout, "Apply BMC on counterexample of length >= %d and <= %d (+%d) \n",
+		  minK, maxK, options->step);
+  }
+  k= minK;
+  while( (result == NIL(array_t)) && (k <= maxK)){
+    if (options->verbosityLevel == BmcVerbosityMax_c) {
+      (void) fprintf(vis_stdout, "\nGenerate counterexample of length %d\n", k);
+    }
+    cnfClauses = BmcCnfClausesAlloc();
+    cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
+    if (cnfFile == NIL(FILE)) {
+      (void)fprintf(vis_stderr,
+		    "** bmc error: Cannot create CNF output file %s\n",
+		    options->satInFile);
+      return;
+    }
+    BmcCnfGenerateClausesForPath(network, 0, k, BMC_INITIAL_STATES,
+				 cnfClauses, nodeToMvfAigTable, CoiTable);
+    noLoopIndex = BmcGenerateCnfForLtl(network, ltlFormula, 0, k, -1, cnfClauses);
+    leftValue   = checkIndex(noLoopIndex, cnfClauses);
+
+    if(leftValue == 1){
+      assert(k==1);
+      if (options->verbosityLevel != BmcVerbosityNone_c){
+	(void) fprintf(vis_stdout,"# BMC: formula failed\n");
+	(void) fprintf(vis_stdout,"# BMC: Empty counterexample because the property is always FALSE\n");
+      }
+      break;
+    } else if(leftValue == 0){
+      if (options->verbosityLevel != BmcVerbosityNone_c){
+	(void) fprintf(vis_stdout,"# BMC: the formula is trivially true");
+	(void) fprintf(vis_stdout," for counterexamples of length %d\n", k);
+      }
+      /*
+      break;
+      */
+    } else {
+      array_insert(int, unitClause, 0, noLoopIndex);
+      
+      BmcCnfInsertClause(cnfClauses, unitClause);
+      
+      BmcWriteClauses(manager, cnfFile, cnfClauses, options);
+      (void) fclose(cnfFile);
+      result = BmcCheckSAT(options);
+      if (options->satSolverError){
+	break;
+      }
+      if(result != NIL(array_t)) {
+	(void) fprintf(vis_stdout, "# BMC: formula failed\n");
+	if(options->verbosityLevel != BmcVerbosityNone_c){
+	  (void) fprintf(vis_stdout,
+			 "# BMC: Found a counterexample of length = %d \n", k);
+	}
+	if (options->dbgLevel == 1) {
+	  BmcPrintCounterExample(network, nodeToMvfAigTable, cnfClauses,
+				 result, k, CoiTable, options, NIL(array_t));
+	}
+	break;
+      }
+    }
+    /* free all used memories */
+    BmcCnfClausesFree(cnfClauses);
+#if 0
+
+    /*
+      Check induction
+     */
+    {
+      BmcCnfClauses_t   *noLoopCnfClauses = BmcCnfClausesAlloc();
+      array_t           *noLoopResult = NIL(array_t);
+      array_t           *unitClause =  array_alloc(int, 1);
+      int               i;
+
+      printf("Check Induction \n");
+
+      cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
+      if (cnfFile == NIL(FILE)) {
+	(void)fprintf(vis_stderr,
+		      "** bmc error: Cannot create CNF output file %s\n",
+		      options->satInFile);
+	return;
+      }
+      /*
+	Generate a loop free path
+      */
+      BmcCnfGenerateClausesForLoopFreePath(network, 0, k+1, BMC_NO_INITIAL_STATES,
+					   noLoopCnfClauses, nodeToMvfAigTable, CoiTable);
+      /*
+	The property true at states from 0 to k
+       */
+      unitClause = array_alloc(int, 1);
+      for(i=0; i<=k; i++){
+	array_insert(int, unitClause, 0, 
+		     -BmcGenerateCnfForLtl(network, ltlFormula, i, k, -1, noLoopCnfClauses));
+	BmcCnfInsertClause(noLoopCnfClauses, unitClause);
+      }
+      
+      /*
+	The property fails at k +1
+       */
+      array_insert(int, unitClause, 0, 
+		   BmcGenerateCnfForLtl(network, ltlFormula, 0, k+1, -1, noLoopCnfClauses));
+      BmcCnfInsertClause(noLoopCnfClauses, unitClause);
+      array_free(unitClause);
+   
+      BmcWriteClauses(manager, cnfFile, noLoopCnfClauses, options);
+      (void) fclose(cnfFile);
+      noLoopResult = BmcCheckSAT(options);
+      if(noLoopResult == NIL(array_t)) {
+	(void) fprintf(vis_stdout, "# BMC: formula passed\n");
+	(void) fprintf(vis_stdout,
+		       "# BMC: No more loop free path \n");
+	
+	break;
+      }
+      /*
+	BmcPrintCounterExample(network, nodeToMvfAigTable, noLoopCnfClauses,
+	noLoopResult, bound+1, CoiTable, options, NIL(array_t));
+      */
+      BmcCnfClausesFree(noLoopCnfClauses);
+    } /* Check induction */
+ 
+#endif
+    k += options->step;
+
+#if 0
+    
+    /* Check if reach the depth of the model */
+    cnfClauses = BmcCnfClausesAlloc();
+    cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
+    if (cnfFile == NIL(FILE)) {
+      (void)fprintf(vis_stderr,
+		    "** bmc error: Cannot create CNF output file %s\n",
+		    options->satInFile);
+      return;
+    }
+    /*
+      Generate a loop free path
+     */
+    {
+      BmcCnfGenerateClausesForPath(network, 0, k, BMC_INITIAL_STATES,
+				   cnfClauses, nodeToMvfAigTable, CoiTable);
+      /*
+	initIndex   = BmcCnfGenerateClausesFromStateToState(network, -1, 0, cnfClauses, nodeToMvfAigTable, CoiTable, -1);
+	noLoopIndex = BmcGenerateCnfForLtl(network, ltlFormula, 0, k, -1, cnfClauses);
+	
+	array_insert(int, orClause, 0, initIndex);
+	array_insert(int, orClause, 1, -noLoopIndex);
+	
+	BmcCnfInsertClause(cnfClauses, orClause);
+      */
+      BmcWriteClauses(manager, cnfFile, cnfClauses, options);
+      (void) fclose(cnfFile);
+      result = BmcCheckSAT(options);
+      if(result == NIL(array_t)) {
+	(void) fprintf(vis_stdout, "# BMC: formula passed\n");
+	(void) fprintf(vis_stdout,
+		       "# BMC: No more loop free path \n");
+	
+	return;
+      }
+      /*
+	BmcPrintCounterExample(network, nodeToMvfAigTable, cnfClauses,
+	result, k, CoiTable, options, NIL(array_t));
+      */
+      result = NIL(array_t);
+    }
+    BmcCnfClausesFree(cnfClauses);
+
+
+    /* Check if reach the depth of the model */
+    cnfClauses = BmcCnfClausesAlloc();
+    cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
+    if (cnfFile == NIL(FILE)) {
+      (void)fprintf(vis_stderr,
+		    "** bmc error: Cannot create CNF output file %s\n",
+		    options->satInFile);
+      return;
+    }
+    /*
+      Generate a loop free path
+     */
+    {
+      BmcCnfGenerateClausesForPath(network, 0, k, BMC_NO_INITIAL_STATES,
+				   cnfClauses, nodeToMvfAigTable, CoiTable);
+      /*
+	initIndex   = BmcCnfGenerateClausesFromStateToState(network, -1, 0, cnfClauses, nodeToMvfAigTable, CoiTable, -1);
+      */
+      noLoopIndex = BmcGenerateCnfForLtl(network, ltlFormula, 0, k, -1, cnfClauses);
+      array_insert(int, unitClause, 0, noLoopIndex);
+      
+      BmcCnfInsertClause(cnfClauses, unitClause);
+      /*
+	array_insert(int, orClause, 0, initIndex);
+	array_insert(int, orClause, 1, -noLoopIndex);
+	
+	BmcCnfInsertClause(cnfClauses, orClause);
+      */
+      BmcWriteClauses(manager, cnfFile, cnfClauses, options);
+      (void) fclose(cnfFile);
+      result = BmcCheckSAT(options);
+      if(result == NIL(array_t)) {
+	(void) fprintf(vis_stdout, "# BMC: (Bad state) formula passed\n");
+	(void) fprintf(vis_stdout,
+		       "# BMC: No more loop free path \n");
+	
+	return;
+      }
+      /*
+	BmcPrintCounterExample(network, nodeToMvfAigTable, cnfClauses,
+	result, k, CoiTable, options, NIL(array_t));
+      */
+      result = NIL(array_t);
+    }
+    BmcCnfClausesFree(cnfClauses);
+#endif
+    
+    
+  } /* while result and k*/
+  if (options->satSolverError == FALSE){
+    if ((result == NIL(array_t)) && (k > maxK)){
+      if (boundedFormula && depth <= options->maxK){
+	(void) fprintf(vis_stdout,"# BMC: formula passed\n");
+      } else {
+	(void) fprintf(vis_stdout,"# BMC: formula undecided\n");
+      }
+      if (options->verbosityLevel != BmcVerbosityNone_c){
+	(void) fprintf(vis_stdout,
+		       "# BMC: no counterexample found of length up to %d \n",
+		       maxK);
+      }
+    }
+  }
+  /* free all used memories */
+  if (k == 0){
+     BmcCnfClausesFree(cnfClauses);
+  }
+  if(result != NIL(array_t)){
+    array_free(result);
+  }
+  if (options->verbosityLevel != BmcVerbosityNone_c) {
+    endTime = util_cpu_ctime();
+    fprintf(vis_stdout, "-- bmc time = %10g\n",
+	    (double)(endTime - startTime) / 1000.0);
+  }
+  array_free(unitClause);
+  array_free(orClause);
+  fflush(vis_stdout);
+  return;
+} /* BmcLtlCheckSafety() */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Check if the index of the varaible in CNF is TURE, FALSE, or
+               none]
+
+  Description []
+
+  SideEffects []
+
+******************************************************************************/
+static int
+checkIndex(
+  int             index,
+  BmcCnfClauses_t *cnfClauses)
+{
+  int     rtnValue = -1; /* it is not TRUE or FALSE*/
+
+  if (index == 0){ /* TRUE or FALSE*/
+    if (cnfClauses->emptyClause){   /* last added clause was empty = FALSE*/
+      rtnValue = 0; /* FALSE */
+    } else {
+      /*
+	if (cnfClauses->noOfClauses == 0)
+	rtnValue = 1;
+	}
+      */
+      rtnValue = 1; /* TRUE */
+    }
+  }
+  return rtnValue;
+}
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description [
+                0  1  -1
+	       ----------	
+	     0  0  0   0
+	     1  0  1  -1
+	    -1  0  -1 -1 
+
+  ]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+doAnd(
+  int left,
+  int right)
+{
+  if ((left == -1) && (right == -1)){
+    return -1;
+  }
+  return (left * right);
+  
+} /* doAnd */
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description [
+                 0   1  -1
+		----------- 
+	     0   0   1  -1
+	     1   1   1  -1
+	    -1  -1  -1  -1 
+
+  ]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+doOr(
+  int left,
+  int right)
+{
+  if ((left == -1) || (right == -1)){
+    return -1;
+  }
+  if ((left == 1) || (right == 1)){
+    return 1;
+  }
+  return 0;
+  
+} /* doOr */
Index: vis_dev/vis-2.3/src/bmc/bmcCirCUs.c
===================================================================
--- vis_dev/vis-2.3/src/bmc/bmcCirCUs.c	(revision 14)
+++ vis_dev/vis-2.3/src/bmc/bmcCirCUs.c	(revision 14)
@@ -0,0 +1,3785 @@
+/**CFile***********************************************************************
+
+  FileName    [bmcCirCUs.c]
+
+  PackageName [bmc]
+
+  Synopsis    [BMC ltl model checker using CirCUs.]
+
+  Author      [HoonSang Jin, Mohammad Awedh]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+  
+******************************************************************************/
+
+#include "bmcInt.h"
+#include "sat.h"
+#include "baig.h"
+
+static char rcsid[] UNUSED = "$Id: bmcCirCUs.c,v 1.56 2010/04/09 23:50:57 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int printSatValue(bAig_Manager_t *manager, st_table *nodeToMvfAigTable, st_table *li2index, bAigEdge_t **baigArr, array_t *nodeArr, int bound, int *prevValue);
+static int printSatValueAiger(bAig_Manager_t *manager, st_table *nodeToMvfAigTable, st_table *li2index, bAigEdge_t **baigArr, array_t *nodeArr, int bound, int *prevValue);
+static int StringCheckIsInteger(char *string, int *value);
+static int verifyIfConstant(bAigEdge_t property);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+   Synopsis [Apply Bounded Model Checking (BMC) technique on a propositional
+   formula.]
+
+   Description [If the property dos not hold in any initial state, the
+   property holds.
+
+   Note: Before calling this function, the LTL formula must be negated. 
+   
+   ]
+
+   SideEffects []
+   
+   SeeAlso     []
+   
+******************************************************************************/
+void
+BmcCirCUsLtlVerifyProp(
+    Ntk_Network_t   *network,
+    Ctlsp_Formula_t *ltl,
+    st_table        *coiTable,
+    BmcOption_t     *options)
+{
+  mAig_Manager_t    *manager = Ntk_NetworkReadMAigManager(network);
+  st_table          *nodeToMvfAigTable = NIL(st_table);
+  long              startTime, endTime;
+  bAigEdge_t        property;
+  int               satFlag;
+  satInterface_t    *interface;
+  array_t           *objArray;
+
+  assert(Ctlsp_isPropositionalFormula(ltl));
+
+  startTime = util_cpu_ctime();
+  if (options->verbosityLevel >= BmcVerbosityNone_c){
+    fprintf(vis_stdout, "LTL formula is propositional\n");
+  }
+  property = BmcCirCUsCreatebAigOfPropFormulaOriginal(network, manager, ltl);
+  if (property == mAig_NULL){
+    return;
+  }
+  if (verifyIfConstant(property)){
+    if (options->verbosityLevel != BmcVerbosityNone_c){
+      fprintf(vis_stdout, "-- bmc time = %10g\n",
+	      (double)(util_cpu_ctime() - startTime) / 1000.0);
+    }
+    return;
+  }
+ 
+  nodeToMvfAigTable = (st_table *) Ntk_NetworkReadApplInfo(network,
+							   MVFAIG_NETWORK_APPL_KEY);
+  assert(nodeToMvfAigTable != NIL(st_table));
+  
+  interface = 0;
+  objArray  = array_alloc(bAigEdge_t, 0);
+  bAig_ExpandTimeFrame(network, manager, 1, BMC_INITIAL_STATES);
+  property = BmcCirCUsCreatebAigOfPropFormula(network, manager,
+					      0, ltl, BMC_INITIAL_STATES);
+  array_insert(bAigEdge_t, objArray, 0, property);
+  options->cnfPrefix = 0;
+  interface = BmcCirCUsInterfaceWithObjArr(manager, network,
+					   objArray, NIL(array_t),
+					   options, interface);
+  satFlag = interface->status;
+  sat_FreeInterface(interface);
+
+  if(satFlag == SAT_SAT) {
+    fprintf(vis_stdout, "# BMC: formula failed\n");
+    if(options->dbgLevel == 1){
+      fprintf(vis_stdout, "# BMC: found a counterexample of length 0\n");
+      BmcCirCUsPrintCounterExample(network, nodeToMvfAigTable, coiTable, 0, 0,
+				   options, BMC_INITIAL_STATES);
+    }
+    if(options->dbgLevel == 2){
+      fprintf(vis_stdout, "# BMC: found a counterexample of length 0\n");
+      fprintf(vis_stdout, "# The counterexample for Structural Sat problem is incomplete.\n");
+      BmcCirCUsPrintCounterExampleAiger(network, nodeToMvfAigTable, coiTable, 0, 0,
+                                   options, BMC_INITIAL_STATES);
+    }
+
+  }
+  else if(satFlag != SAT_SAT) {
+    if(options->verbosityLevel != BmcVerbosityNone_c){
+      fprintf(vis_stdout,"# BMC: no counterexample found of length 0\n");
+    }
+    fprintf(vis_stdout,"# BMC: formula passed\n");
+    (void) fprintf(vis_stdout, "#      Termination depth = 0\n");
+  }
+  if (options->verbosityLevel != BmcVerbosityNone_c){
+    endTime = util_cpu_ctime();
+    fprintf(vis_stdout, "-- bmc time = %10g\n", (double)(endTime - startTime) / 1000.0);
+  }
+  array_free(objArray);
+  fflush(vis_stdout);
+  return;
+} /* BmcCirCUsLtlVerifyProp() */
+
+
+/**Function********************************************************************
+
+  Synopsis [Check if the LTL formula in the form G(p) (invariant), p is a
+            propositional formula, is an Inductive Invariant using SAT]
+
+  Description [Check if the LTL formula in the form G(p), p is a
+               propositional formula, is an Inductive Invariant
+
+  An LTL formula G(p), where p is a propositional formula, is an
+  inductive invariant if the following two conditions hold:
+  
+     1- p holds in all intial states.
+     2- If p holds in a state s, then it also holds in all states
+        that are reachable from s.
+
+  G(p) is an inductive invariant if : 
+    SAT( I(0) and !p(0)) return UNSAT and
+    SAT( p(i) and T(i, i+1) and !p(i+1)) returns UNSAT.
+
+  Return value:
+    0 if the property is not an inductive invariant 
+    1 if the property is an inductive invariant
+   ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+BmcCirCUsLtlCheckInductiveInvariant(
+  Ntk_Network_t   *network,
+  Ctlsp_Formula_t *ltl,
+  BmcOption_t     *options,
+  st_table        *CoiTable)
+{
+  mAig_Manager_t  *manager = Ntk_NetworkReadMAigManager(network);
+  bAigEdge_t      property, result;
+  int             satFlag;
+  satInterface_t  *interface;
+  array_t         *objArray   = array_alloc(bAigEdge_t, 1);
+  int             returnValue = 0;  /* the property is not an inductive
+                                       invariant */
+  /*
+    Check if the property holds in all initial states.
+   */
+  interface = 0;
+  bAig_ExpandTimeFrame(network, manager, 1, BMC_INITIAL_STATES);
+  property = BmcCirCUsCreatebAigOfPropFormula(network, manager, 0, ltl->right, BMC_INITIAL_STATES);
+
+  array_insert(bAigEdge_t, objArray, 0, property);
+  options->cnfPrefix = 0;
+  interface = BmcCirCUsInterfaceWithObjArr(manager, network, objArray,
+				 NIL(array_t), options, interface);
+  satFlag = interface->status;
+  sat_FreeInterface(interface);
+
+  if(satFlag == SAT_UNSAT) {
+    /*
+      Check the induction step.
+    */
+    interface = 0;
+    bAig_ExpandTimeFrame(network, manager, 2, BMC_NO_INITIAL_STATES);
+    property = BmcCirCUsCreatebAigOfPropFormula(network, manager, 0, ltl->right, BMC_NO_INITIAL_STATES);
+    /*
+      The property is true at state 0.  Remember that the passing property is
+      the negation of the original property.
+    */
+    result = bAig_Not(property);
+    property = BmcCirCUsCreatebAigOfPropFormula(network, manager, 1, ltl->right, BMC_NO_INITIAL_STATES);
+    /*
+      The property is false at state 1
+    */
+    result = bAig_And(manager, result, property);
+    array_insert(bAigEdge_t, objArray, 0, result);
+    options->cnfPrefix = 1;
+    interface = BmcCirCUsInterfaceWithObjArr(manager, network, objArray,
+				   NIL(array_t), options, interface);
+    satFlag = interface->status;
+    sat_FreeInterface(interface);
+    if(satFlag == SAT_UNSAT) {
+      returnValue = 1; /* the property is an inductive invariant */
+     
+    }
+  }
+  array_free(objArray);
+  return returnValue; 
+} /* BmcCirCUsLtlCheckInductiveInvariant */
+
+
+/**Function********************************************************************
+
+   Synopsis [Apply Bounded Model Checking (BMC) on an LTL formula of
+   the form G(p), where p is a propositional formula.]
+
+   Description [Given a model M, an LTL formula f = Gp, and a bound k,
+   we first find a counterexample of length k to a state that violates
+   p.  If -r switch of the BMC command is specified, we apply the
+   induction proof to check if the property f passes. The property f
+   passes if there is no simple path in M that leads to a state that
+   violates p, or no simple path in M starting at an initial state.
+
+   Note: Before calling this function, the LTL formula must be negated. 
+
+   Using sat as SAT solver.
+   
+   ]
+
+   SideEffects []
+   
+   SeeAlso     []
+   
+******************************************************************************/
+void
+BmcCirCUsLtlVerifyGp(
+    Ntk_Network_t   *network,
+    Ctlsp_Formula_t *ltl,
+    st_table        *coiTable,
+    BmcOption_t     *options)
+{
+  mAig_Manager_t    *manager = Ntk_NetworkReadMAigManager(network);
+  st_table          *nodeToMvfAigTable = NIL(st_table);
+  long              startTime, endTime;
+  bAigEdge_t        property, result, simplePath;
+  int               j, satFlag, k;
+  int               checkInductiveInvariant;
+  array_t           *objArray;
+  array_t           *auxObjArray;
+  satInterface_t    *ceInterface, *etInterface, *tInterface;
+  st_table          *coiIndexTable;
+  Bmc_PropertyStatus formulaStatus;
+
+  assert(Ctlsp_LtlFormulaIsFp(ltl));
+  
+  startTime = util_cpu_ctime();
+
+  if (options->verbosityLevel != BmcVerbosityNone_c){
+    fprintf(vis_stdout, "LTL formula is of type G(p)\n");
+  }
+  property = BmcCirCUsCreatebAigOfPropFormulaOriginal(network, manager, ltl->right);
+  
+  if (property == mAig_NULL){
+    return;
+  }
+  if (verifyIfConstant(property)){
+    if (options->verbosityLevel != BmcVerbosityNone_c){
+      fprintf(vis_stdout, "-- bmc time = %10g\n",
+	      (double)(util_cpu_ctime() - startTime) / 1000.0);
+    }
+    return;
+  }
+
+  if (options->verbosityLevel >= BmcVerbosityMax_c){
+    (void) fprintf(vis_stdout, "\nBMC: Check if the property is an inductive invariant\n");
+  }
+  checkInductiveInvariant = BmcCirCUsLtlCheckInductiveInvariant(network, ltl, options, coiTable);
+  if (checkInductiveInvariant == 1){
+    (void) fprintf(vis_stdout,"# BMC: The property is an inductive invariant\n");
+    (void) fprintf(vis_stdout,"# BMC: formula passed\n");
+    (void) fprintf(vis_stdout, "#      Termination depth = 0\n");
+    if (options->verbosityLevel != BmcVerbosityNone_c){
+      fprintf(vis_stdout, "-- bmc time = %10g\n",
+	      (double)(util_cpu_ctime() - startTime) / 1000.0);
+    }
+    return;
+  }
+  
+  nodeToMvfAigTable = (st_table *) Ntk_NetworkReadApplInfo(network,
+							   MVFAIG_NETWORK_APPL_KEY);
+  assert(nodeToMvfAigTable != NIL(st_table));
+
+  ceInterface = 0;
+  etInterface = 0;
+  tInterface  = 0;
+  if (options->verbosityLevel != BmcVerbosityNone_c){
+    (void)fprintf(vis_stdout, "Apply BMC on counterexample of length >= %d and <= %d (+%d)\n",
+		  options->minK, options->maxK, options->step);
+  }
+  /*
+    Hold objects 
+  */
+  objArray = array_alloc(bAigEdge_t, 2);
+  /*
+    Unused entry is set to bAig_One
+   */
+  array_insert(bAigEdge_t, objArray, 1, bAig_One);
+  /*
+    Hold auxiliary objects (constraints on the path)
+  */
+  auxObjArray = array_alloc(bAigEdge_t, 0);
+  
+  bAig_ExpandTimeFrame(network, manager, 1, BMC_NO_INITIAL_STATES); 
+  coiIndexTable = BmcCirCUsGetCoiIndexTable(network, coiTable);
+  
+  formulaStatus = BmcPropertyUndecided_c;
+  for(k = options->minK; k <= options->maxK; k += options->step){
+    if (options->verbosityLevel == BmcVerbosityMax_c){
+      fprintf(vis_stdout, "\nBMC: Generate counterexample of length %d\n", k);
+    }
+    /*
+      Expand counterexample length to k.  In BMC, counterexample of length k means
+      k+1 time frames.
+     */
+    bAig_ExpandTimeFrame(network, manager, k+1, BMC_INITIAL_STATES);
+    /*
+      The property true at any states from (k-step+1) to k 
+     */
+    result = bAig_Zero;
+    for(j=k-options->step+1; j<=k; j++) {
+      /*
+	For k = options->minK, j goes outside the lower boundary of
+	counterexample search.
+      */
+      if(j < options->minK) continue;
+      
+      property = BmcCirCUsCreatebAigOfPropFormula(network, manager, j, ltl->right, BMC_INITIAL_STATES);
+      result   = bAig_Or(manager, result, property);
+    }
+    array_insert(bAigEdge_t, objArray, 0, result);
+    options->cnfPrefix = k;
+    ceInterface = BmcCirCUsInterfaceWithObjArr(manager, network, objArray,
+					   auxObjArray, options,
+					   ceInterface);
+    satFlag = ceInterface->status;
+    if(satFlag == SAT_SAT){
+      formulaStatus = BmcPropertyFailed_c;
+      break;
+    }
+    /*
+      Given that the property does not hold at all previous states.
+     */
+    array_insert_last(bAigEdge_t, auxObjArray, bAig_Not(result));
+
+    /*
+      Prove if the property passes using the induction proof of SSS0.
+    */
+    if((options->inductiveStep !=0) &&
+       (k % options->inductiveStep == 0)){
+      array_t *auxArray;
+      int i;
+      
+      if (options->verbosityLevel == BmcVerbosityMax_c) {
+	(void) fprintf(vis_stdout, "\nBMC: Check for termination\n");
+      }      
+      /*
+	Expand counterexample length to k+1.  In BMC, counterexample of length k+1 means
+	k+2 time frames.
+      */
+      bAig_ExpandTimeFrame(network, manager, k+2, BMC_NO_INITIAL_STATES);
+      simplePath = BmcCirCUsSimlePathConstraint(network, 0, k+1, nodeToMvfAigTable,
+						coiIndexTable, BMC_NO_INITIAL_STATES);
+      property = BmcCirCUsCreatebAigOfPropFormula(network, manager, k+1, ltl->right,
+						  BMC_NO_INITIAL_STATES);
+      array_insert(bAigEdge_t, objArray, 0, simplePath);
+      array_insert(bAigEdge_t, objArray, 1, property);
+      auxArray = array_alloc(bAigEdge_t, 0);
+      for(i=0; i<=k; i++){
+	array_insert_last(bAigEdge_t, auxArray,
+			  bAig_Not(
+			    BmcCirCUsCreatebAigOfPropFormula(network, manager, i, ltl->right,
+							     BMC_NO_INITIAL_STATES)
+			    ));
+      }
+      options->cnfPrefix = k+1;
+      tInterface = BmcCirCUsInterfaceWithObjArr(manager, network,
+				      objArray, auxArray,
+				      options, tInterface);
+      array_free(auxArray); 
+      array_insert(bAigEdge_t, objArray, 1, bAig_One);
+      if(tInterface->status == SAT_UNSAT){
+	if (options->verbosityLevel == BmcVerbosityMax_c) {
+	  (void) fprintf(vis_stdout,
+			 "# BMC: No simple path leading to a bad state\n");
+	}
+	formulaStatus = BmcPropertyPassed_c;
+	break;
+      }
+      
+      if(options->earlyTermination){
+	/*
+	  Early termination condition
+	  
+	  Check if there is no simple path starts from initial states
+	  
+	*/
+        simplePath = BmcCirCUsSimlePathConstraint(network, 0, k+1, nodeToMvfAigTable,
+						  coiIndexTable,
+						  BMC_INITIAL_STATES);
+	array_insert(bAigEdge_t, objArray, 0, simplePath);
+	etInterface = BmcCirCUsInterfaceWithObjArr(manager, network,
+					       objArray, NIL(array_t),
+					       options, etInterface);
+	options->cnfPrefix = k+1;
+	if(etInterface->status == SAT_UNSAT){
+	  if (options->verbosityLevel == BmcVerbosityMax_c) {
+	    (void) fprintf(vis_stdout,
+			   "# BMC: No simple path starting at an initial state\n");
+	  }
+	  formulaStatus = BmcPropertyPassed_c;
+	  break;
+	}
+      }
+      
+    } /* check for termination*/
+  } /* loop over k*/
+  array_free(objArray);
+  array_free(auxObjArray);
+  sat_FreeInterface(ceInterface);
+  if(etInterface !=0){
+    sat_FreeInterface(etInterface);
+  }
+  if(tInterface !=0){
+    sat_FreeInterface(tInterface);
+  }
+  st_free_table(coiIndexTable);
+
+  if(formulaStatus == BmcPropertyUndecided_c){
+    if (options->verbosityLevel != BmcVerbosityNone_c){
+      (void) fprintf(vis_stdout,
+		     "# BMC: no counterexample found of length up to %d\n",
+		     options->maxK);
+    }
+  }
+  if(formulaStatus == BmcPropertyFailed_c) {
+    (void) fprintf(vis_stdout, "# BMC: formula failed\n");
+    if(options->verbosityLevel != BmcVerbosityNone_c){
+      (void) fprintf(vis_stdout,
+		     "# BMC: Found a counterexample of length = %d \n", k);
+    }
+    if(options->dbgLevel == 1){
+      BmcCirCUsPrintCounterExample(network, nodeToMvfAigTable, coiTable, k, 0,
+				   options, BMC_INITIAL_STATES);
+    }
+    if(options->dbgLevel == 2){
+      BmcCirCUsPrintCounterExampleAiger(network, nodeToMvfAigTable, coiTable, k, 0,
+                                   options, BMC_INITIAL_STATES);
+    }
+  } else if(formulaStatus == BmcPropertyPassed_c) {
+    (void) fprintf(vis_stdout, "# BMC: formula Passed\n");
+    (void) fprintf(vis_stdout, "#      Termination depth = %d\n", k);
+  } else if(formulaStatus == BmcPropertyUndecided_c) {
+    (void) fprintf(vis_stdout,"# BMC: formula undecided\n");
+  }
+  
+  if (options->verbosityLevel != BmcVerbosityNone_c){
+    endTime = util_cpu_ctime();
+    fprintf(vis_stdout, "-- bmc time = %10g\n", (double)(endTime - startTime) / 1000.0);
+  }
+  fflush(vis_stdout);
+
+  return;
+} /* BmcCirCUsLtlVerifyGp() */
+
+/**Function********************************************************************
+
+   Synopsis [Apply Bounded Model Checking (BMC) on an LTL formula of
+   the form F(p), where p is propositional.]
+
+   Description [Given a model M, an LTL formula f = Fp, and a bound k,
+   we first find a k-loop counterexample of length k at which all
+   states violate p.  If -r switch of the BMC command is specified, we
+   apply the method in the paper "Proving More Properties with Bounded
+   Model Checking" to check if the property f passes.
+
+   Note: Before calling this function, the LTL formula must be negated. 
+
+   Using sat as SAT solver.
+   
+   ]   
+   SideEffects []
+   
+   SeeAlso     []
+
+******************************************************************************/
+
+void
+BmcCirCUsLtlVerifyFp(
+    Ntk_Network_t   *network,
+    Ctlsp_Formula_t *ltl,
+    st_table        *coiTable,
+    BmcOption_t     *options)
+{
+  mAig_Manager_t    *manager = Ntk_NetworkReadMAigManager(network);
+  st_table          *nodeToMvfAigTable = NIL(st_table);
+  long              startTime, endTime;
+  bAigEdge_t        property, pathProperty, simplePath, tloop, loop;
+  int               bound, k, satFlag;
+  array_t           *loop_array = NIL(array_t);
+  array_t           *objArray;
+  array_t           *auxObjArray;
+  st_table          *coiIndexTable;
+  satInterface_t    *ceInterface;
+  satInterface_t    *tInterface;
+  Bmc_PropertyStatus formulaStatus;
+
+  startTime = util_cpu_ctime();
+  if(options->verbosityLevel != BmcVerbosityNone_c){
+    fprintf(vis_stdout,"LTL formula is of type F(p)\n");
+  }
+  property = BmcCirCUsCreatebAigOfPropFormulaOriginal(network, manager,
+						      ltl->right);
+  if (verifyIfConstant(property)){
+    if (options->verbosityLevel != BmcVerbosityNone_c){
+      fprintf(vis_stdout, "-- bmc time = %10g\n",
+	      (double)(util_cpu_ctime() - startTime) / 1000.0);
+    }
+    return;
+  }
+
+  nodeToMvfAigTable = 
+	  (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+  assert(nodeToMvfAigTable != NIL(st_table));
+  
+  bAig_ExpandTimeFrame(network, manager, 0, BMC_INITIAL_STATES);
+  coiIndexTable = BmcCirCUsGetCoiIndexTable(network, coiTable);
+
+ /*
+    Hold objects 
+  */
+  objArray = array_alloc(bAigEdge_t, 2);
+  /*
+    Unused entry is set to bAig_One
+   */
+  array_insert(bAigEdge_t, objArray, 1, bAig_One);
+  /*
+    Hold auxiliary objects (constraints on the path)
+  */
+  auxObjArray = array_alloc(bAigEdge_t, 0);
+  
+  ceInterface = 0;
+  tInterface  = 0;
+  formulaStatus = BmcPropertyUndecided_c;
+  if(options->verbosityLevel != BmcVerbosityNone_c){
+    fprintf(vis_stdout,"Apply BMC on counterexample of length >= %d and <= %d (+%d)\n",
+	               options->minK, options->maxK, options->step);
+
+  }
+  bound = options->minK;
+  while(bound<=options->maxK) {
+    if(options->verbosityLevel == BmcVerbosityMax_c)
+      fprintf(vis_stdout, "\nBMC: Generate counterexample of length %d\n", bound);
+    /*
+      Expand counterexample length to bound.  In BMC, counterexample of length bound means
+      bound+1 time frames.
+    */
+    bAig_ExpandTimeFrame(network, manager, bound+1, BMC_INITIAL_STATES );
+    /** 
+     * How can we manage cone of influence with this part ?
+     **/
+    loop_array = array_alloc(bAigEdge_t *, 0);
+    tloop = bAig_Zero;
+    /*
+      Loop from state 'bound' to any previous states.
+     */
+    for(k=0; k<=bound; k++) {
+      loop = BmcCirCUsConnectFromStateToState(network, bound, k, nodeToMvfAigTable,
+					      coiIndexTable, BMC_INITIAL_STATES);
+      array_insert(bAigEdge_t, loop_array, k, loop);
+      tloop = bAig_Or(manager, tloop, loop);
+    }
+    array_insert(bAigEdge_t, objArray, 0, tloop);
+    /*
+      tloop equals true for k-loop path 
+     */
+    /*
+      Property false at all states
+     */
+    pathProperty = bAig_One;
+    for(k=bound; k>=0; k--) {
+      property = BmcCirCUsCreatebAigOfPropFormula(network, manager, k, ltl->right, BMC_INITIAL_STATES);
+      pathProperty = bAig_And(manager, pathProperty, property);
+    }
+    array_insert(bAigEdge_t, objArray, 1, pathProperty);
+    
+    options->cnfPrefix = bound;
+    ceInterface = BmcCirCUsInterfaceWithObjArr(manager, network,
+					       objArray, auxObjArray,
+					       options, ceInterface);
+    satFlag = ceInterface->status;
+    if(satFlag == SAT_SAT){
+      formulaStatus = BmcPropertyFailed_c;
+      break;
+    }
+
+    array_insert_last(bAigEdge_t, auxObjArray, bAig_Not(tloop));
+
+    if((options->inductiveStep !=0) &&
+       (bound % options->inductiveStep == 0)){
+
+      if (options->verbosityLevel == BmcVerbosityMax_c) {
+	(void) fprintf(vis_stdout,
+		       "\nBMC: Check for termination\n");
+      }
+      simplePath = BmcCirCUsSimlePathConstraint(network, 0, bound, nodeToMvfAigTable,
+						coiIndexTable,
+						BMC_INITIAL_STATES);
+      array_insert(bAigEdge_t, objArray, 0, simplePath);
+      array_insert(bAigEdge_t, objArray, 1, pathProperty);
+      tInterface = BmcCirCUsInterfaceWithObjArr(manager, network,
+						objArray, auxObjArray,
+						options, tInterface);
+      if(tInterface->status == SAT_UNSAT){
+	formulaStatus = BmcPropertyPassed_c;
+	break;
+      }
+    }
+    bound += options->step;
+  }
+  array_free(objArray);
+  array_free(auxObjArray);
+  st_free_table(coiIndexTable);
+  sat_FreeInterface(ceInterface);
+  sat_FreeInterface(tInterface);
+
+  if(formulaStatus == BmcPropertyUndecided_c){
+    if (options->verbosityLevel != BmcVerbosityNone_c){
+      (void) fprintf(vis_stdout,
+		     "# BMC: no counterexample found of length up to %d\n",
+		     options->maxK);
+    }
+  }
+  if(formulaStatus == BmcPropertyFailed_c) {
+    (void) fprintf(vis_stdout, "# BMC: formula failed\n");
+    if(options->verbosityLevel != BmcVerbosityNone_c){
+      (void) fprintf(vis_stdout,
+		     "# BMC: Found a counterexample of length = %d \n", bound);
+    }
+    if(options->dbgLevel == 1){
+     BmcCirCUsPrintCounterExample(network, nodeToMvfAigTable, coiTable, bound, loop_array,
+				   options, BMC_INITIAL_STATES);
+    }
+    if(options->dbgLevel == 2){
+     BmcCirCUsPrintCounterExampleAiger(network, nodeToMvfAigTable, coiTable, bound, loop_array,
+                                   options, BMC_INITIAL_STATES);
+    }
+
+  } else if(formulaStatus == BmcPropertyPassed_c) {
+    (void) fprintf(vis_stdout, "# BMC: formula Passed\n");
+    (void) fprintf(vis_stdout, "#      Termination depth = %d\n", bound);
+  } else if(formulaStatus == BmcPropertyUndecided_c) {
+    (void) fprintf(vis_stdout,"# BMC: formula undecided\n");
+  }
+  if (options->verbosityLevel != BmcVerbosityNone_c) {
+    endTime = util_cpu_ctime();
+    fprintf(vis_stdout, "-- bmc time = %10g\n", (double)(endTime - startTime) / 1000.0);
+  }
+  fflush(vis_stdout);  
+  array_free(loop_array);
+
+} /* BmcCirCUsLtlVerifyFp() */
+
+/**Function********************************************************************
+
+   Synopsis [Build AIG graph of BMC encoding for a path]
+
+   Description [Build AIG graph of BMC encoding for a path. If loop = -1,
+   then the BMC encoding is for no loop path.  Otherwise, it is for
+   (to, loop)-loop path]
+
+   SideEffects []
+   
+   SeeAlso     []
+   
+******************************************************************************/
+bAigEdge_t
+BmcCirCUsGenerateLogicForLtl(
+    Ntk_Network_t   *network,
+    Ctlsp_Formula_t *ltl,
+    int from,
+    int to,
+    int loop)
+{
+  bAigEdge_t property, temp;
+  bAigEdge_t left, right, result;
+  int j, k;
+  mAig_Manager_t  *manager = Ntk_NetworkReadMAigManager(network);
+
+  if(Ctlsp_isPropositionalFormula(ltl)){
+    property = BmcCirCUsCreatebAigOfPropFormula(network, manager, from, ltl, BMC_INITIAL_STATES);
+    return(property);
+  }
+
+  switch(ltl->type) {
+    case Ctlsp_NOT_c:
+      if (!Ctlsp_isPropositionalFormula(ltl->left)){
+	fprintf(vis_stderr,"BMC error: the LTL formula is not in NNF\n");
+	return 0;
+      }
+    case Ctlsp_AND_c:
+      left = BmcCirCUsGenerateLogicForLtl(network, ltl->left, from, to, loop);
+      if(left == bAig_Zero) 	return(bAig_Zero);
+      right = BmcCirCUsGenerateLogicForLtl(network, ltl->right, from, to, loop);
+      return(bAig_And(manager, left, right));
+    case Ctlsp_OR_c:
+      left = BmcCirCUsGenerateLogicForLtl(network, ltl->left, from, to, loop);
+      if(left == bAig_One) 	return(bAig_One);
+      right = BmcCirCUsGenerateLogicForLtl(network, ltl->right, from, to, loop);
+      return(bAig_Or(manager, left, right));
+    case Ctlsp_F_c:
+      if(loop >= 0)	from = (loop<from) ? loop : from;
+      result = bAig_Zero;
+      for(j=from; j<=to; j++)  {
+	left = BmcCirCUsGenerateLogicForLtl(network, ltl->left, j, to, loop);
+	if(left == bAig_One)	return(left);
+	result = bAig_Or(manager, left, result);
+      }
+      return(result);
+    case Ctlsp_G_c:
+      if(loop < 0)	return(bAig_Zero);
+      from = (loop < from) ? loop : from;
+      result = bAig_One;
+      for(j=from; j<=to; j++) {
+	left = BmcCirCUsGenerateLogicForLtl(network, ltl->left, j, to, loop);
+	result = bAig_And(manager, result, left);
+	if(result == bAig_Zero)	break;
+      }
+      return(result);
+    case Ctlsp_X_c:
+      if(loop>=0 && from == to)	from = loop;
+      else if(from < to)	from = from + 1;
+      else			return(bAig_Zero);
+      left = BmcCirCUsGenerateLogicForLtl(network, ltl->left, from, to, loop);
+      return(left);
+    case Ctlsp_U_c:
+      result = bAig_Zero;
+      for(j=from; j<=to; j++) {
+	right = BmcCirCUsGenerateLogicForLtl(network, ltl->right, j, to, loop);
+	temp = right;
+	for(k=from; (k<=j-1); k++) {
+	  left = BmcCirCUsGenerateLogicForLtl(network, ltl->left, k, to, loop);
+	  temp = bAig_And(manager, temp, left);
+	  if(temp == bAig_Zero)	break;
+	}
+	result = bAig_Or(manager, result, temp);
+	if(result == bAig_One) break;
+      }
+      if(loop>=0 && result != bAig_One) {
+	for(j=loop; j<=from-1; j++) {
+          right = BmcCirCUsGenerateLogicForLtl(network, ltl->right, j, to, loop);
+	  temp = right;
+	  for(k=from; k<=to; k++) {
+    	    left = BmcCirCUsGenerateLogicForLtl(network, ltl->left, k, to, loop);
+	    temp = bAig_And(manager, temp, left);
+	    if(temp == bAig_Zero)	break;
+	  }
+	  for(k=loop; k<=j-1; k++) {
+    	    left = BmcCirCUsGenerateLogicForLtl(network, ltl->left, k, to, loop);
+	    temp = bAig_And(manager, temp, left);
+	    if(temp == bAig_Zero)	break;
+	  }
+	  result = bAig_Or(manager, result, temp);
+	  if(result == bAig_One) break;
+	}
+      }
+      return(result);
+    case Ctlsp_R_c:
+      result = bAig_Zero;
+      if(loop >= 0) {
+	temp = bAig_One;
+        for(j=(from<loop ? from : loop); j<=to; j++) {
+	  right = BmcCirCUsGenerateLogicForLtl(network, ltl->right, j, to, loop);
+	  temp = bAig_And(manager, temp, right);
+	  if(temp == bAig_Zero)	break;
+	}
+	result = bAig_Or(manager, result, temp);
+      }
+      if(result != bAig_One) {
+	for(j=from; j<=to; j++) {
+	  left = BmcCirCUsGenerateLogicForLtl(network, ltl->left, j, to, loop);
+	  temp = left;
+	  for(k=from; k<=j; k++) {
+            right = BmcCirCUsGenerateLogicForLtl(network, ltl->right, k, to, loop);
+	    temp = bAig_And(manager, temp, right);
+	    if(temp == bAig_Zero)	break;
+	  }
+	  result = bAig_Or(manager, temp, result);
+	  if(result == bAig_One) break;
+	}
+	if(loop >= 0 && result != bAig_One) {
+	  for(j=loop; j<=from-1; j++) {
+	    left = BmcCirCUsGenerateLogicForLtl(network, ltl->left, j, to, loop);
+
+	    temp = left;
+	    for(k=from; k<=to; k++) {
+	      right = BmcCirCUsGenerateLogicForLtl(network, ltl->right, k, to, loop);
+	      temp = bAig_And(manager, temp, right);
+	      if(temp == bAig_Zero)	break;
+	    }
+
+	    for(k=loop; k<=j; k++) {
+	      right = BmcCirCUsGenerateLogicForLtl(network, ltl->right, k, to, loop);
+	      temp = bAig_And(manager, temp, right);
+	      if(temp == bAig_Zero)	break;
+	    }
+
+	    result = bAig_Or(manager, result, temp);
+	    if(result == bAig_One) break;
+	  }
+	}
+      }
+      return(result);
+    default:
+      fail("Unexpected LTL formula type");
+      break;
+  }
+  assert(0);
+  return(-1);
+
+}
+
+/**Function********************************************************************
+   
+   Synopsis [Build AIG graph for BMC encoding using Separated Normal Form
+   (SNF)]
+   
+   Description []
+   
+   SideEffects []
+   
+   SeeAlso     []
+   
+******************************************************************************/
+bAigEdge_t
+BmcCirCUsGenerateLogicForLtlSNF(
+  Ntk_Network_t   *network,
+  array_t         *formulaArray,
+  int             fromState,
+  int             toState,
+  int             loop)
+{
+  mAig_Manager_t  *manager = Ntk_NetworkReadMAigManager(network);
+  Ctlsp_Formula_t *formula;
+  bAigEdge_t      property = bAig_One;
+  bAigEdge_t      left, right, result;
+  int             i, k;
+  Ctlsp_Formula_t *leftChild, *rightChild;
+
+  for (i = 0; i < array_n(formulaArray); i++) { 
+    formula    = array_fetch(Ctlsp_Formula_t *, formulaArray, i);  
+    leftChild  = Ctlsp_FormulaReadLeftChild(formula);
+    rightChild = Ctlsp_FormulaReadRightChild(formula);
+
+    if(!strcmp(Ctlsp_FormulaReadVariableName(leftChild), " SNFstart")){
+      result = BmcCirCUsGenerateLogicForLtl(network, rightChild,
+					    0, toState, loop);
+    } else 
+      if(!strcmp(Ctlsp_FormulaReadVariableName(leftChild), " SNFbound")){
+	result =  BmcCirCUsGenerateLogicForLtl(network, rightChild,
+					       toState, toState, loop);
+      } else {
+	result = bAig_One;
+	for(k=fromState; k<= toState; k++){
+	  left  = BmcCirCUsGenerateLogicForLtl(network, leftChild,
+					       k, toState, loop);
+	  right = BmcCirCUsGenerateLogicForLtl(network, rightChild,
+					       k, toState, loop);
+	  result = bAig_And(manager, result,
+			    bAig_Then(manager, left, right));
+	}
+      }
+    property = bAig_And(manager, property, result);
+  }
+  return property;
+} /* BmcCirCUsGenerateLogicForLtlSNF */
+
+
+/**Function********************************************************************
+
+   Synopsis [Build AIG graph of BMC encoding for LTL formulae based on fixpoint
+   characteristics of LTL formulae.]
+
+   Description [We use BMC encoding based on FMCAD'04 paper: Simple Bounded LTL
+   Model Checking.
+
+   This function can only be applied to abbreviation-free LTL formulae. The
+   formula must be in Negation Normal Form.  For LTL formula of the form Fp,
+   where p is propositional, this function build AIG for auxiliary
+   translation.]
+
+   SideEffects []
+   
+   SeeAlso     []
+   
+******************************************************************************/
+bAigEdge_t
+BmcCirCUsGenerateLogicForLtlFixPoint(
+  Ntk_Network_t   *network,
+  Ctlsp_Formula_t *ltl,
+  int             from,
+  int             to,
+  array_t         *loopArray)
+{
+  bAigEdge_t result;
+  st_table   *ltl2AigTable;
+
+  assert(ltl != NIL(Ctlsp_Formula_t));
+  
+  ltl2AigTable = st_init_table(strcmp, st_strhash);
+  result = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl,
+				  from, to, 0, loopArray, ltl2AigTable);
+  st_free_table(ltl2AigTable);
+
+  return result;
+} /* BmcCirCUsGenerateLogicForLtlFixPoint */
+
+/**Function********************************************************************
+
+   Synopsis [The recursive function of BmcCirCUsGenerateLogicForLtlFixPoint]
+
+   Description []
+
+   SideEffects []
+   
+   SeeAlso     []
+   
+******************************************************************************/
+bAigEdge_t
+BmcCirCUsGenerateLogicForLtlFixPointRecursive(
+  Ntk_Network_t   *network,
+  Ctlsp_Formula_t *ltl,
+  int             from,
+  int             to,
+  int             translation, /* 0 auxilary translation. 1 final translation */
+  array_t         *loopArray,
+  st_table        *ltl2AigTable)
+{
+  mAig_Manager_t  *manager = Ntk_NetworkReadMAigManager(network);
+  bAigEdge_t      property, temp;
+  bAigEdge_t      left, right, result;
+
+  int      j;
+
+  char     *nameKey;
+  char     tmpName[100];
+
+  /*
+    Check if AIG was built for this LTL formula at a given time
+   */
+  sprintf(tmpName, "%ld_%d%d", (long)ltl, from, translation);
+  nameKey = util_strsav(tmpName);
+  if(st_lookup(ltl2AigTable, nameKey, &result)){
+    FREE(nameKey);
+    return result;
+  }
+  FREE(nameKey);
+  
+  if(Ctlsp_isPropositionalFormula(ltl)){
+    property = BmcCirCUsCreatebAigOfPropFormula(network, manager,
+						from, ltl, BMC_INITIAL_STATES);
+    sprintf(tmpName, "%ld_%d%d", (long)ltl, from, 1);
+    nameKey = util_strsav(tmpName);
+    st_insert(ltl2AigTable, nameKey, (char*) (long) property);
+    return(property);
+  }
+  switch(ltl->type) {
+  case Ctlsp_NOT_c:
+    if (!Ctlsp_isPropositionalFormula(ltl->left)){
+      fprintf(vis_stderr,"BMC error: the LTL formula is not in NNF\n");
+
+      return 0;
+    }
+  case Ctlsp_AND_c:
+    left = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl->left, from, to,
+							 translation, loopArray, ltl2AigTable);
+    if(left == bAig_Zero){
+      return(bAig_Zero);
+    }
+    right = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl->right, from, to,
+							  translation, loopArray, ltl2AigTable);
+    return(bAig_And(manager, left, right));
+  case Ctlsp_OR_c:
+    left = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl->left, from, to,
+							 translation, loopArray, ltl2AigTable);
+    if(left == bAig_One){
+      return(bAig_One);
+    }
+    right = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl->right, from, to,
+							  translation, loopArray, ltl2AigTable);
+    return(bAig_Or(manager, left, right));
+  case Ctlsp_X_c:
+    if(from < to){
+      result = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl->left, from+1, to,
+							     1, loopArray, ltl2AigTable);
+    } else {
+      result =  bAig_Zero;
+      for(j=1; j<=to; j++) {
+	left  = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl->left,  j, to,
+							      1, loopArray, ltl2AigTable);
+	temp = bAig_And(manager, array_fetch(bAigEdge_t, loopArray, j), left);
+	result = bAig_Or(manager, result, temp);
+      }
+    }
+    sprintf(tmpName, "%ld_%d%d", (long) ltl, from, 1);
+    nameKey = util_strsav(tmpName);
+    st_insert(ltl2AigTable, nameKey, (char*) (long) result);
+    return result;
+  case Ctlsp_U_c:
+    sprintf(tmpName, "%ld_%d%d", (long) ltl, to, 0); /* 0 for auxiliary translation*/
+    nameKey = util_strsav(tmpName);
+    right = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl->right, to, to, 1, loopArray, ltl2AigTable);
+    st_insert(ltl2AigTable, nameKey, (char*) (long) right);
+    /*
+      Compute the auxiliary translation.
+    */
+    for(j=to-1; j>=from; j--) {
+      result = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl, j+1, to, 0, loopArray, ltl2AigTable);
+      
+      right = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl->right, j, to, 1, loopArray, ltl2AigTable);
+      left  = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl->left,  j, to, 1, loopArray, ltl2AigTable);
+      
+      result  = bAig_And(manager,left, result);
+      result  = bAig_Or(manager,right, result);
+      
+      sprintf(tmpName, "%ld_%d%d", (long)ltl, j, 0); /* 0 for auxiliary translation*/
+      nameKey = util_strsav(tmpName);
+      st_insert(ltl2AigTable, nameKey, (char*) (long) result);
+    }
+    /*
+      Compute the final translation at k.
+    */
+    result =  bAig_Zero;
+    for(j=1; j<=to; j++) {
+      temp = bAig_And(manager, array_fetch(bAigEdge_t, loopArray, j),
+		      BmcCirCUsGenerateLogicForLtlFixPointRecursive(
+			network, ltl, j, to, 0, loopArray, ltl2AigTable));
+      result = bAig_Or(manager, result, temp);
+    }
+    right = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl->right, to, to, 1, loopArray, ltl2AigTable);
+    left  = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl->left,
+							  to, to, 1, loopArray,
+							  ltl2AigTable);
+    
+    result  = bAig_And(manager,left, result);
+    result  = bAig_Or(manager,right, result);
+    
+    sprintf(tmpName, "%ld_%d%d", (long)ltl, to, 1); /* 1 for final translation*/
+    nameKey = util_strsav(tmpName);
+    st_insert(ltl2AigTable, nameKey, (char*) (long) result);
+    /*
+      Compute the final translation.
+    */
+    for(j=to-1; j>=from; j--) {
+      result = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl, j+1, to, 1, loopArray, ltl2AigTable);
+
+      right = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl->right, j, to, 1, loopArray, ltl2AigTable);
+      left  = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl->left,  j, to, 1, loopArray, ltl2AigTable);
+    
+      result  = bAig_And(manager,left, result);
+      result  = bAig_Or(manager,right, result);
+
+      sprintf(tmpName, "%ld_%d%d", (long)ltl, j, 1);
+      nameKey = util_strsav(tmpName);
+      st_insert(ltl2AigTable, nameKey, (char*) (long) result);
+    }
+    return(result);
+  case Ctlsp_R_c:
+    sprintf(tmpName, "%ld_%d%d", (long)ltl, to, 0); /* 0 for auxiliary translation*/
+    right = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl->right, to, to, 1, loopArray, ltl2AigTable);
+    nameKey = util_strsav(tmpName);
+    st_insert(ltl2AigTable, nameKey, (char*) (long) right);
+    /*
+      Compute the auxiliary translation.
+    */
+    for(j=to-1; j>=from; j--) {
+      result = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl, j+1, to, 0, loopArray, ltl2AigTable);
+      
+      right = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl->right, j, to, 1, loopArray, ltl2AigTable);
+      left  = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl->left,  j, to, 1, loopArray, ltl2AigTable);
+      
+      result  = bAig_Or(manager,left, result);
+      result  = bAig_And(manager,right, result);
+      
+      sprintf(tmpName, "%ld_%d%d", (long) ltl, j, 0); /* 0 for auxiliary translation*/
+      nameKey = util_strsav(tmpName);
+      st_insert(ltl2AigTable, nameKey, (char*) (long) result);
+    }
+    /*
+      Compute the final translation at k.
+    */
+    result =  bAig_Zero;
+    for(j=1; j<=to; j++) {
+      temp = bAig_And(manager, array_fetch(bAigEdge_t, loopArray, j),
+		      BmcCirCUsGenerateLogicForLtlFixPointRecursive(
+			network, ltl, j, to, 0, loopArray, ltl2AigTable));
+      result = bAig_Or(manager, result, temp);
+    }
+    right = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl->right,
+							  to, to, 1, loopArray,
+							  ltl2AigTable);
+    left  = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl->left,
+							  to, to, 1, loopArray,
+							  ltl2AigTable);    
+    result  = bAig_Or(manager,left, result);
+    result  = bAig_And(manager,right, result);
+    
+    sprintf(tmpName, "%ld_%d%d", (long) ltl, to+1, 1); /* 1 for final translation*/
+    nameKey = util_strsav(tmpName);
+    st_insert(ltl2AigTable, nameKey, (char*) (long) result);
+    /*
+      Compute the final translation.
+    */
+    for(j=to-1; j>=from; j--) {
+      result = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl, j+1, to, 1, loopArray, ltl2AigTable);
+
+      right = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl->right, j, to, 1, loopArray, ltl2AigTable);
+      left  = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl->left,  j, to, 1, loopArray, ltl2AigTable);
+    
+      result  = bAig_Or(manager,left, result);
+      result  = bAig_And(manager,right, result);
+
+      sprintf(tmpName, "%ld_%d%d", (long)ltl, j, 1);
+      nameKey = util_strsav(tmpName);
+      st_insert(ltl2AigTable, nameKey, (char*) (long) result);
+    }
+    return(result);
+  case Ctlsp_F_c:
+    /*
+      Compute only the auxiliary translation.
+    */
+    sprintf(tmpName, "%ld_%d%d", (long)ltl, to, 0); /* 0 for auxiliary translation*/
+    nameKey = util_strsav(tmpName);
+    left = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl->left,
+							 to, to, 1, loopArray,
+							 ltl2AigTable);
+    st_insert(ltl2AigTable, nameKey, (char*) (long) left);
+
+    for(j=to-1; j>=from; j--) {
+      result = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl,
+							     j+1, to, 0,
+							     loopArray,
+							     ltl2AigTable);
+      left = BmcCirCUsGenerateLogicForLtlFixPointRecursive(network, ltl->left,
+							   j, to, 1, loopArray,
+							   ltl2AigTable);
+      result  = bAig_Or(manager,left, result);
+      
+      sprintf(tmpName, "%ld_%d%d", (long)ltl, j, 0); /* 0 for auxiliary translation*/
+      nameKey = util_strsav(tmpName);
+      st_insert(ltl2AigTable, nameKey, (char*) (long) result);
+    }
+    result =  bAig_Zero;
+    for(j=1; j<=to; j++) {
+      temp = bAig_And(manager, array_fetch(bAigEdge_t, loopArray, j),
+		      BmcCirCUsGenerateLogicForLtlFixPointRecursive(
+			network, ltl, j, to, 0, loopArray, ltl2AigTable));
+      result = bAig_Or(manager, result, temp);
+    }
+    return(result);
+  default:
+    fail("Unexpected LTL formula type");
+    break;
+  }
+  assert(0);
+  return(-1);
+}
+
+/**Function********************************************************************
+
+   Synopsis [Apply Bounded Model Checking (BMC) on an LTL formula of
+   the form FG(p), where p is propositional.]
+
+   Description [Given a model M, an LTL formula f = FGp, and a bound k, we
+   first find a k-loop counterexample of length k at which p false inside the
+   loop.  If -r switch of the BMC command is specified, we apply the method in
+   the paper "Proving More Properties with Bounded Model Checking" to check if
+   the property passes.
+
+   Note: Before calling this function, the LTL formula must be negated. 
+   
+   ]
+  
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+BmcCirCUsLtlVerifyFGp(
+   Ntk_Network_t   *network,
+   Ctlsp_Formula_t *ltlFormula,
+   st_table        *coiTable,
+   BmcOption_t     *options)
+{
+  mAig_Manager_t   *manager = Ntk_NetworkReadMAigManager(network);
+  st_table         *nodeToMvfAigTable = NIL(st_table);  /* node to mvfAig */
+
+  int              j, k, l, satFlag;
+
+  long             startTime, endTime;
+  int              minK = options->minK;
+  int              maxK = options->maxK;
+  Ctlsp_Formula_t  *propFormula;
+  bAigEdge_t       property, loop, pathProperty, tloop;
+  array_t          *loop_array = NIL(array_t);
+  array_t          *previousResultArray;
+  st_table         *coiIndexTable;
+  satInterface_t   *ceInterface;
+  
+  Bmc_PropertyStatus formulaStatus;
+
+  int              m=-1, n=-1;
+  int              checkLevel = 0;
+  /*
+    Refer to Theorem 1 in the paper "Proving More Properties with Bounded Model Checking"
+    
+    If checkLevel == 0 -->  check for beta' only. If UNSAT, m=k and chekLevel = 1
+    If checkLevel == 1 -->  check for beta  only. If UNSAT, checkLevel = 2.
+    If checkLevel == 2 -->  check for alpha only. If UNSAT, n=k and checkLevel = 3.
+    If gama is UNSAT up to (m+n-1) and checkLvel = 3, formula passes.
+    checkLevel = 4 if (m+n-1) > maxK; */
+
+  /*
+    Remember the LTL property was negated
+  */
+  assert(Ctlsp_LtlFormulaIsGFp(ltlFormula));
+
+  /* ************** */
+  /* Initialization */
+  /* ************** */
+  
+  startTime = util_cpu_ctime();
+  if(options->verbosityLevel >= BmcVerbosityMax_c){
+    fprintf(vis_stdout,"LTL formula is of type FG(p)\n");
+  }
+  propFormula = Ctlsp_FormulaReadRightChild(Ctlsp_FormulaReadRightChild(ltlFormula));
+  property = BmcCirCUsCreatebAigOfPropFormulaOriginal(network, manager,
+						      propFormula);
+  if (verifyIfConstant(property)){
+    if (options->verbosityLevel != BmcVerbosityNone_c){
+      fprintf(vis_stdout, "-- bmc time = %10g\n",
+	      (double)(util_cpu_ctime() - startTime) / 1000.0);
+    }
+    return;
+  }
+ 
+  /*
+    nodeToMvfAigTable maps each node to its multi-function And/Inv graph
+  */
+  nodeToMvfAigTable =
+    (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+  assert(nodeToMvfAigTable != NIL(st_table));
+  
+  bAig_ExpandTimeFrame(network, manager, 0, BMC_INITIAL_STATES);
+  coiIndexTable = BmcCirCUsGetCoiIndexTable(network, coiTable);
+  
+  previousResultArray = array_alloc(bAigEdge_t, 0);
+  ceInterface = 0;
+  if(options->verbosityLevel != BmcVerbosityNone_c){
+    fprintf(vis_stdout,"Apply BMC on counterexample of length >= %d and <= %d (+%d)\n",
+	    options->minK, options->maxK, options->step);
+    
+  }
+  k= minK;
+  formulaStatus = BmcPropertyUndecided_c;
+  while(k <= maxK){
+    if (options->verbosityLevel >= BmcVerbosityMax_c) {
+      (void) fprintf(vis_stdout, "\nGenerate counterexample of length %d\n", k);
+    }
+   /*
+     Expand counterexample length to bound.  In BMC, counterexample of length bound means
+     k+1 time frames.
+   */
+    bAig_ExpandTimeFrame(network, manager, k+1, BMC_INITIAL_STATES );
+
+    /*
+      k-loop
+    */
+    loop_array = array_alloc(bAigEdge_t *, 0);
+    tloop = bAig_Zero;
+    /*
+      Loop from last state to any previous states.
+    */
+    for(l=0; l<=k; l++) {
+      loop = BmcCirCUsConnectFromStateToState(network, k, l, nodeToMvfAigTable,
+					      coiIndexTable, BMC_INITIAL_STATES);
+      array_insert(bAigEdge_t, loop_array, l, loop);
+      pathProperty = bAig_Zero;
+      for(j=l; j<=k; j++){
+	property = BmcCirCUsCreatebAigOfPropFormula(network, manager, j, propFormula, BMC_INITIAL_STATES);
+	pathProperty = bAig_Or(manager, pathProperty, property);
+      }
+      
+      tloop = bAig_Or(manager, tloop, bAig_And(manager, pathProperty, loop));
+    }
+    options->cnfPrefix = k;
+    ceInterface = BmcCirCUsInterface(manager, network, tloop,
+				     previousResultArray, options,
+				     ceInterface);
+    satFlag = ceInterface->status;
+    if(satFlag == SAT_SAT){
+      formulaStatus = BmcPropertyFailed_c;
+      break;
+    }
+    array_free(loop_array);
+
+    /* ==================
+       Prove termination
+       ================== */
+    if((checkLevel < 3) &&
+       (options->inductiveStep !=0) &&
+       (k % options->inductiveStep == 0))
+      {
+	satInterface_t *tInterface=0, *etInterface=0;
+	bAigEdge_t     simplePath, property;
+	int            i;
+	
+	/* ===========================
+	   Early termination condition
+	   ===========================
+	*/
+	if (options->earlyTermination) {
+	  if (options->verbosityLevel >= BmcVerbosityMax_c) {
+	    (void) fprintf(vis_stdout, "\nChecking for early termination at k= %d\n", k);
+	  }
+	  bAig_ExpandTimeFrame(network, manager, k+1, BMC_INITIAL_STATES);
+	  simplePath = BmcCirCUsSimlePathConstraint(network, 0, k, nodeToMvfAigTable,
+						    coiIndexTable, BMC_INITIAL_STATES);
+	  options->cnfPrefix = k;
+	  etInterface = BmcCirCUsInterface(manager, network,
+					   simplePath,
+					   previousResultArray,
+					   options, etInterface);
+	  if(etInterface->status == SAT_UNSAT){
+	    formulaStatus = BmcPropertyPassed_c;
+	    if (options->verbosityLevel >= BmcVerbosityMax_c) {
+	      (void) fprintf(vis_stdout, "# BMC: by early termination\n");
+	    }
+	    break;
+	  }
+	} /* Early termination */
+	/*
+	  Check for \beta''(k)
+	*/
+	if(checkLevel == 0){
+	  if (options->verbosityLevel == BmcVerbosityMax_c) {
+	    (void) fprintf(vis_stdout, "# BMC: Check Beta''\n");
+	  }
+	  
+	  bAig_ExpandTimeFrame(network, manager, k+2, BMC_NO_INITIAL_STATES);
+	  simplePath = BmcCirCUsSimlePathConstraint(network, 0, k+1, nodeToMvfAigTable,
+						 coiIndexTable, BMC_NO_INITIAL_STATES);
+	  property = bAig_One;
+	  for(i=1; i<=k+1; i++){
+	    property = bAig_And(manager, property,
+				bAig_Not(BmcCirCUsCreatebAigOfPropFormula(
+				  network, manager, i,
+				  propFormula, BMC_NO_INITIAL_STATES)));
+	  }
+	  property = bAig_And(manager, property,
+			      BmcCirCUsCreatebAigOfPropFormula(
+				network, manager, 0,
+				propFormula, BMC_NO_INITIAL_STATES));
+	  options->cnfPrefix = k+1;
+	  tInterface = 0;
+	  tInterface = BmcCirCUsInterface(manager, network,
+					  bAig_And(manager, property, simplePath),
+					  previousResultArray, options, tInterface);
+	  if(tInterface->status == SAT_UNSAT){
+	    m = k;
+	    if (options->verbosityLevel >= BmcVerbosityMax_c) {
+	      (void)fprintf(vis_stderr,"m = %d\n", m);
+	    }
+	    checkLevel = 1;
+	  }
+	} /* Check for Beta'' */
+	/*
+	  Check for \beta'(k)
+	*/
+	if(checkLevel == 0){
+	  if (options->verbosityLevel == BmcVerbosityMax_c) {
+	    (void) fprintf(vis_stdout, "# BMC: Check Beta'\n");
+	  }
+	  bAig_ExpandTimeFrame(network, manager, k+2, BMC_NO_INITIAL_STATES);
+	  simplePath = BmcCirCUsSimlePathConstraint(network, 0, k+1, nodeToMvfAigTable,
+						 coiIndexTable, BMC_NO_INITIAL_STATES);
+	  property = bAig_One;
+	  for(i=0; i<=k; i++){
+	    property = bAig_And(manager, property,
+				bAig_Not(BmcCirCUsCreatebAigOfPropFormula(
+				  network, manager, i,
+				  propFormula, BMC_NO_INITIAL_STATES)));
+	  }
+	  property = bAig_And(manager, property,
+			      BmcCirCUsCreatebAigOfPropFormula(
+				network, manager, k+1,
+				propFormula, BMC_NO_INITIAL_STATES));
+	  options->cnfPrefix = k+1;
+	  tInterface = 0;
+	  tInterface = BmcCirCUsInterface(manager, network,
+					  bAig_And(manager, property, simplePath),
+					  previousResultArray, options, tInterface);
+	  if(tInterface->status == SAT_UNSAT){
+	    m = k;
+	    if (options->verbosityLevel >= BmcVerbosityMax_c) {
+	      (void)fprintf(vis_stderr,"m = %d\n", m);
+	    }
+	    checkLevel = 1;
+	  } 
+	} /* Check for Beta' */
+	/*
+	  Check for Beta
+	*/
+	if(checkLevel == 1){
+	  if (options->verbosityLevel == BmcVerbosityMax_c) {
+	    (void) fprintf(vis_stdout, "# BMC: Check Beta\n");
+	  }
+	  bAig_ExpandTimeFrame(network, manager, k+2, BMC_NO_INITIAL_STATES);
+	  simplePath = BmcCirCUsSimlePathConstraint(network, 0, k+1, nodeToMvfAigTable,
+						 coiIndexTable, BMC_NO_INITIAL_STATES);
+	  property = bAig_And(manager,
+			      bAig_Not(BmcCirCUsCreatebAigOfPropFormula(
+				network, manager, k,
+				propFormula, BMC_NO_INITIAL_STATES)),
+			      BmcCirCUsCreatebAigOfPropFormula(
+				network, manager, k+1,
+				propFormula, BMC_NO_INITIAL_STATES));
+	  options->cnfPrefix = k+1;
+	  tInterface = BmcCirCUsInterface(manager, network,
+					  bAig_And(manager, property, simplePath),
+					  previousResultArray, options, tInterface);
+	  if(tInterface->status == SAT_UNSAT){
+	    checkLevel = 2;
+	  }
+	} /* Check Beta*/
+  
+	if(checkLevel == 2){ /* we check Alpha if Beta is unsatisfiable */
+	  if (options->verbosityLevel == BmcVerbosityMax_c) {
+	    (void) fprintf(vis_stdout, "# BMC: Check Alpha \n");
+	  }
+	  bAig_ExpandTimeFrame(network, manager, k+1, BMC_INITIAL_STATES);
+	  simplePath = BmcCirCUsSimlePathConstraint(network, 0, k, nodeToMvfAigTable,
+						  coiIndexTable, BMC_INITIAL_STATES);
+	  property = BmcCirCUsCreatebAigOfPropFormula(
+				  network, manager, k,
+				  propFormula, BMC_INITIAL_STATES);
+	  options->cnfPrefix = k;
+	  tInterface = 0;
+	  tInterface = BmcCirCUsInterface(manager, network,
+					  bAig_And(manager, property, simplePath),
+					  previousResultArray, options, tInterface);
+	  if(tInterface->status == SAT_UNSAT){
+	    n = k;
+	    checkLevel = 3;
+	    if (options->verbosityLevel == BmcVerbosityMax_c) {
+	      (void)fprintf(vis_stdout,"Value of m=%d  n=%d\n", m, n);
+	    }
+	    if (m+n-1 <= maxK){
+	      maxK = m+n-1;
+	      checkLevel = 3;
+	    } else {
+	      checkLevel = 4;
+	    }
+	  }
+	}/* Chek for Alpha */
+	
+	if (options->verbosityLevel != BmcVerbosityNone_c) {
+	  endTime = util_cpu_ctime();
+	  fprintf(vis_stdout, "-- Check for termination time = %10g\n",
+		  (double)(endTime - startTime) / 1000.0);
+	}
+  
+      } /* Check for termination */
+    k += options->step;
+  } /* while result and k*/
+ 
+  if(formulaStatus == BmcPropertyFailed_c) {
+    (void) fprintf(vis_stdout, "# BMC: formula failed\n");
+    if(options->verbosityLevel != BmcVerbosityNone_c){
+      (void) fprintf(vis_stdout,
+		       "# BMC: Found a counterexample of length = %d \n", k);
+    }
+    if(options->dbgLevel == 1){
+      BmcCirCUsPrintCounterExample(network, nodeToMvfAigTable, coiTable, k, loop_array,
+				   options, BMC_INITIAL_STATES);
+    }
+    if(options->dbgLevel == 2){
+      BmcCirCUsPrintCounterExampleAiger(network, nodeToMvfAigTable, coiTable, k, loop_array,
+                                   options, BMC_INITIAL_STATES);
+    }
+
+    array_free(loop_array);
+  }
+  if(checkLevel == 3){
+    (void) fprintf(vis_stdout, "# BMC: no counterexample of length <= (m+n-1) %d is found \n", m+n-1);
+    formulaStatus = BmcPropertyPassed_c;
+  }
+  if(formulaStatus == BmcPropertyPassed_c) {
+    (void) fprintf(vis_stdout, "# BMC: formula Passed\n");
+    (void) fprintf(vis_stdout, "#      Termination depth = %d\n", k);
+  } else if(formulaStatus == BmcPropertyUndecided_c) {
+    (void) fprintf(vis_stdout,"# BMC: formula undecided\n");
+    if (options->verbosityLevel != BmcVerbosityNone_c){
+      (void) fprintf(vis_stdout,
+		     "# BMC: no counterexample found of length up to %d\n",
+		     maxK);
+    }
+  }
+  if (options->verbosityLevel != BmcVerbosityNone_c) {
+    endTime = util_cpu_ctime();
+    fprintf(vis_stdout, "-- bmc time = %10g\n",
+	    (double)(endTime - startTime) / 1000.0);
+  }
+  
+  array_free(previousResultArray);
+  
+  fflush(vis_stdout);
+  return;
+} /* BmcCirCUsLtlVerifyGFp() */
+
+/**Function********************************************************************
+
+  Synopsis    [Use BMC technique to verify a general LTL formulae]
+
+  Description [Implements the Bounded Model Checking technique as in the paper
+  "Symbolic Model Checking without BDDs".  We also have implemented some of the
+  improvements in the BMC encoding as were described in the paper "Improving
+  the Encoding of LTL Model Checking into SAT". If snf=1, we use Separated
+  Normal Form technique to encode LTL properties, otherwise we use the original
+  encoding. ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void
+BmcCirCUsLtlVerifyGeneralLtl(
+    Ntk_Network_t   *network,
+    Ctlsp_Formula_t *ltl,
+    st_table	    *coiTable,
+    array_t         *constraintArray,
+    BmcOption_t     *options,
+    int             snf)
+{
+  mAig_Manager_t    *manager = Ntk_NetworkReadMAigManager(network);
+  st_table          *nodeToMvfAigTable = NIL(st_table);
+  long              startTime, endTime;
+  boolean           fairness  = (options->fairFile != NIL(FILE));
+  int               minK = options->minK;
+  int               maxK = options->maxK;
+  boolean           boundedFormula;
+  array_t           *ltlConstraintArray = NIL(array_t);
+  array_t           *fairnessArray = NIL(array_t);
+  int               depth, l, bound, f, satFlag, i;
+  bAigEdge_t        noLoop, loop, ploop; 
+  bAigEdge_t        result=bAig_NULL, temp, fair;
+  array_t           *loop_arr = NIL(array_t);
+  array_t           *objArray;
+  array_t           *auxObjArray;
+  st_table          *coiIndexTable;
+  Ctlsp_Formula_t   *formula;
+  satInterface_t    *interface;
+  array_t           *formulaArray = NIL(array_t);
+  int               nextAction = 0;
+  /*
+    Use when proving termination
+   */
+  BmcCheckForTermination_t *terminationStatus = 0;
+  Bmc_PropertyStatus       formulaStatus;
+
+  nodeToMvfAigTable = 
+	  (st_table *) Ntk_NetworkReadApplInfo(network,
+					       MVFAIG_NETWORK_APPL_KEY);
+  assert(nodeToMvfAigTable != NIL(st_table));
+
+  if(fairness) {
+    Ctlsp_Formula_t *formula; /* a generic LTL formula */
+    int              i;       /* iteration variable */
+
+    ltlConstraintArray = array_alloc(Ctlsp_Formula_t *, 0);
+    
+    arrayForEachItem(Ctlsp_Formula_t *, constraintArray, i, formula) {
+      fprintf(vis_stdout, "Formula: ddd");
+      Ctlsp_FormulaPrint(vis_stdout, formula);
+      fprintf(vis_stdout, "\n");
+      BmcGetCoiForLtlFormula(network, formula, coiTable);
+      formula =  Ctlsp_FormulaCreate(Ctlsp_F_c, formula, NIL(Ctlsp_Formula_t));
+      array_insert_last(Ctlsp_Formula_t *, ltlConstraintArray, formula);
+    }
+  }
+  /*
+    For bounded formulae use a tighter upper bound if possible.
+  */
+  boundedFormula = Ctlsp_LtlFormulaTestIsBounded(ltl, &depth);
+  if (boundedFormula && depth < maxK && depth >= minK) {
+    maxK = depth;
+  } else {
+    if(options->inductiveStep !=0){
+      /*
+	Use the termination criteria to prove the property passes.    
+      */
+      terminationStatus = BmcAutTerminationAlloc(network,
+						 Ctlsp_LtllFormulaNegate(ltl),
+						 constraintArray);
+      assert(terminationStatus);
+    }
+  }
+  if (options->verbosityLevel != BmcVerbosityNone_c){
+    (void) fprintf(vis_stdout, "General LTL BMC\n");
+    if (boundedFormula){
+      (void) fprintf(vis_stdout, "Bounded formula of depth %d\n", depth);
+    }
+    (void) fprintf(vis_stdout, "Apply BMC on counterexample of length >= %d and <= %d (+%d) \n",
+		  minK, maxK, options->step);
+  }
+  bAig_ExpandTimeFrame(network, manager, 1, 1);
+  coiIndexTable = BmcCirCUsGetCoiIndexTable(network, coiTable);
+  interface    = 0;
+  /*
+    Hold objects 
+  */
+  objArray = array_alloc(bAigEdge_t, 1);
+  /*
+    Hold auxiliary objects (constraints on the path)
+  */
+  auxObjArray = array_alloc(bAigEdge_t, 0);
+
+  formulaStatus = BmcPropertyUndecided_c;
+  bound = minK;
+  if(snf){
+    formulaArray = Ctlsp_LtlTranslateIntoSNF(ltl);
+  }
+  startTime = util_cpu_ctime();
+  while(bound<=maxK) {
+    if(options->verbosityLevel == BmcVerbosityMax_c){
+      fprintf(vis_stdout, "\nGenerate counterexample of length %d\n", bound);
+    }
+
+    loop_arr = 0;
+    bAig_ExpandTimeFrame(network, manager, bound+1, BMC_INITIAL_STATES);
+
+    if(fairness){
+      /*
+	In case of fairness constraints, we only include a loop part of BMC
+	encoding
+      */
+      noLoop = bAig_Zero;
+    } else {
+      if(snf){
+	noLoop = BmcCirCUsGenerateLogicForLtlSNF(network, formulaArray, 0, bound, -1);
+      } else {
+	noLoop = BmcCirCUsGenerateLogicForLtl(network, ltl, 0, bound, -1);
+      }
+    }
+    result = noLoop;
+    if(noLoop != bAig_One) {
+      loop_arr = array_alloc(bAigEdge_t, 0);
+      for(l=0; l<=bound; l++) {
+	if(snf){
+	  loop = BmcCirCUsGenerateLogicForLtlSNF(network, formulaArray, 0,
+						 bound, l);
+	} else { 
+	  loop = BmcCirCUsGenerateLogicForLtl(network, ltl, 0, bound, l);
+	}
+	if(loop == bAig_Zero)	continue;
+
+	if(fairness) {
+	  fairnessArray = array_alloc(bAigEdge_t, 0);
+	  arrayForEachItem(Ctlsp_Formula_t *, ltlConstraintArray, i, formula) {
+	    fair = BmcCirCUsGenerateLogicForLtl(network, formula, l, bound, -1);
+	    array_insert_last(bAigEdge_t, fairnessArray, fair);
+	  }
+	}
+
+	if(loop != bAig_Zero) {
+          ploop = BmcCirCUsConnectFromStateToState(network, bound, l, nodeToMvfAigTable, coiIndexTable, 1);
+	  array_insert(bAigEdge_t, loop_arr, l, ploop);
+	  temp = bAig_And(manager, loop, ploop);
+	  if(fairness) {
+	    for(f=0; f < array_n(fairnessArray); f++){
+	      fair = array_fetch(bAigEdge_t, fairnessArray, f);
+	      temp = bAig_And(manager, temp, fair); 
+	    }
+	  }
+	  result = bAig_Or(manager, result, temp);
+	}
+	if(fairness){
+	  array_free(fairnessArray);
+	}
+      }
+    }
+    /*
+    loop = result;
+    
+    if((noLoop == bAig_Zero) && (loop == bAig_Zero)){
+    */
+    /*
+      result = noLoop | loop(0) | loop(1) ... | loop(bound)
+     */
+    
+    if(result == bAig_Zero){
+      if (options->verbosityLevel != BmcVerbosityNone_c){
+	fprintf(vis_stdout,"# BMC: the formula is trivially true");
+	fprintf(vis_stdout," for counterexamples of length %d\n", bound);
+      }
+    } else {
+      array_insert(bAigEdge_t, objArray, 0, result);
+      options->cnfPrefix = bound;
+      interface = BmcCirCUsInterfaceWithObjArr(manager, network,
+					       objArray, auxObjArray,
+					       options, interface);
+      satFlag = interface->status;
+      if(satFlag == SAT_SAT) {
+	formulaStatus = BmcPropertyFailed_c;
+        break;
+      }
+      array_insert_last(bAigEdge_t, auxObjArray, bAig_Not(result));
+    }
+    /*
+      Use the termination check if the the LTL formula is not bounded
+    */
+    if(!boundedFormula &&
+       (formulaStatus == BmcPropertyUndecided_c) &&
+       (nextAction != 1)){
+      if((options->inductiveStep !=0) &&
+	 (bound % options->inductiveStep == 0))
+	{
+	  /*
+	    Check for termination for the current value of k.
+	  */
+	  terminationStatus->k = bound;
+	  BmcCirCUsAutLtlCheckForTermination(network, manager,
+					     nodeToMvfAigTable,
+					     terminationStatus,
+					     coiIndexTable, options);
+	  nextAction = terminationStatus->action;
+	  if(nextAction == 1){
+	    maxK = terminationStatus->k;
+	  } else
+	    if(nextAction == 3){
+	      formulaStatus = BmcPropertyPassed_c;
+	      break;
+	    }
+	}
+    } /* terminationStatus */
+    
+    if(loop_arr) {
+      array_free(loop_arr);
+    }
+    bound += options->step;
+  }
+  array_free(objArray);
+  array_free(auxObjArray);
+  st_free_table(coiIndexTable);
+  sat_FreeInterface(interface);
+
+  if(formulaStatus == BmcPropertyUndecided_c){
+    if(nextAction == 1){
+      /*
+	No counterexample of length up to maxK is found. By termination
+	criterion, formula passes
+      */
+      formulaStatus = BmcPropertyPassed_c;
+    } else 
+      if (boundedFormula && depth <= options->maxK){
+	/*
+	  No counterexample of length up to the bounded depth of the LTL formula is
+	  found. Formula passes
+	*/
+	formulaStatus = BmcPropertyPassed_c;
+      }
+  }
+  
+  if(options->satSolverError){
+    (void) fprintf(vis_stdout,"# BMC: Error in calling SAT solver\n");
+  } else {
+    if(formulaStatus == BmcPropertyFailed_c) {
+      (void) fprintf(vis_stdout, "# BMC: formula failed\n");
+      if(options->verbosityLevel != BmcVerbosityNone_c){
+	(void) fprintf(vis_stdout,
+		       "# BMC: Found a counterexample of length = %d \n", bound);
+      }
+      if (options->dbgLevel == 1) {
+	BmcCirCUsPrintCounterExample(network, nodeToMvfAigTable, coiTable, bound, loop_arr,
+				     options, BMC_INITIAL_STATES);
+      }
+      if (options->dbgLevel == 2) {
+        BmcCirCUsPrintCounterExampleAiger(network, nodeToMvfAigTable, coiTable, bound, loop_arr,
+                                     options, BMC_INITIAL_STATES);
+      }
+    } else if(formulaStatus == BmcPropertyPassed_c) {
+      (void) fprintf(vis_stdout, "# BMC: formula Passed\n");
+      (void) fprintf(vis_stdout, "#      Termination depth = %d\n", maxK);
+    } else if(formulaStatus == BmcPropertyUndecided_c) {
+      (void) fprintf(vis_stdout,"# BMC: formula undecided\n");
+      if (options->verbosityLevel != BmcVerbosityNone_c){
+	(void) fprintf(vis_stdout,
+		       "# BMC: no counterexample found of length up to %d\n",
+		       maxK);
+      }
+    }
+  }
+ 
+  /*
+    free all used memories
+  */
+  if(terminationStatus){
+    BmcAutTerminationFree(terminationStatus);
+  }
+  if(fairness){
+    array_free(ltlConstraintArray);
+  }
+  if(snf){
+    Ctlsp_FormulaArrayFree(formulaArray);
+  }
+  if (options->verbosityLevel != BmcVerbosityNone_c) {
+    endTime = util_cpu_ctime();
+    fprintf(vis_stdout, "-- bmc time = %10g\n", (double)(endTime - startTime) / 1000.0);
+  }
+
+  fflush(vis_stdout);
+}
+
+/**Function********************************************************************
+
+   Synopsis [Verify LTL property using BMC]
+
+   Description [We use the encoding of "Simple Bounded LTL Model
+   Checking", FMCAD04]
+
+   SideEffects []
+   
+   SeeAlso     [BmcCirCUsConnectFromStateToState]
+   
+******************************************************************************/
+void
+BmcCirCUsLtlVerifyGeneralLtlFixPoint(
+    Ntk_Network_t   *network,
+    Ctlsp_Formula_t *ltl,
+    st_table	    *coiTable,
+    array_t         *constraintArray,
+    BmcOption_t     *options)
+{
+  mAig_Manager_t    *manager = Ntk_NetworkReadMAigManager(network);
+  st_table          *nodeToMvfAigTable = NIL(st_table);
+  long              startTime, endTime;
+  bAigEdge_t        property, fair;
+  boolean           fairness  = (options->fairFile != NIL(FILE));
+  int               minK = options->minK;
+  int               maxK = options->maxK;
+  boolean           boundedFormula;
+  array_t           *ltlConstraintArray = NIL(array_t);
+  array_t           *objArray;
+  array_t           *auxObjArray;
+  st_table          *coiIndexTable;
+  Ctlsp_Formula_t   *formula;
+  satInterface_t    *interface;
+  int               nextAction = 0;
+  
+  BmcCheckForTermination_t *terminationStatus = 0;
+  Bmc_PropertyStatus       formulaStatus;
+ 
+  array_t    *loopArray = NIL(array_t), *smallerExists;
+  bAigEdge_t tmp, loop, atMostOnce, loopConstraints;
+  int        i, k, depth, satFlag;
+  
+  startTime = util_cpu_ctime();
+
+  nodeToMvfAigTable = 
+	  (st_table *) Ntk_NetworkReadApplInfo(network,
+					       MVFAIG_NETWORK_APPL_KEY);
+  assert(nodeToMvfAigTable != NIL(st_table));
+
+  if(fairness) {    
+    ltlConstraintArray = array_alloc(Ctlsp_Formula_t *, 0);
+
+    arrayForEachItem(Ctlsp_Formula_t *, constraintArray, i, formula) {
+      BmcGetCoiForLtlFormula(network, formula, coiTable);
+      formula =  Ctlsp_FormulaCreate(Ctlsp_F_c, formula, NIL(Ctlsp_Formula_t));
+      array_insert(Ctlsp_Formula_t *, ltlConstraintArray, i, formula);
+    }
+  }
+
+  /*
+    For bounded formulae use a tighter upper bound if possible.
+  */
+  boundedFormula = Ctlsp_LtlFormulaTestIsBounded(ltl, &depth);
+  if (boundedFormula && depth < maxK && depth >= minK) {
+    maxK = depth;
+  } else {
+    if(options->inductiveStep !=0){
+      /*
+	Use the termination criteria to prove the property passes.    
+      */
+      terminationStatus = BmcAutTerminationAlloc(network,
+						 Ctlsp_LtllFormulaNegate(ltl),
+						 constraintArray);
+      assert(terminationStatus);
+    }
+  }
+  
+  if (options->verbosityLevel != BmcVerbosityNone_c){
+    (void) fprintf(vis_stdout, "General LTL BMC\n");
+    (void) fprintf(vis_stdout, "Apply BMC on counterexample of length >= %d and <= %d (+%d) \n",
+		  minK, maxK, options->step);
+  }
+
+  bAig_ExpandTimeFrame(network, manager, 1, BMC_INITIAL_STATES);
+  /*
+    We need the above line inorder to run the next one.
+   */
+  coiIndexTable = BmcCirCUsGetCoiIndexTable(network, coiTable);
+  interface = 0;
+
+  /*
+    Hold objects 
+  */
+  objArray = array_alloc(bAigEdge_t, 3);
+  /*
+    Hold auxiliary objects (constraints on the path)
+  */
+  auxObjArray = array_alloc(bAigEdge_t, 0);
+
+  formulaStatus = BmcPropertyUndecided_c;
+  k = minK;
+  while(k<=maxK) {
+    if(options->verbosityLevel == BmcVerbosityMax_c){
+      fprintf(vis_stdout, "\nGenerate counterexample of length %d\n", k);
+    }
+    bAig_ExpandTimeFrame(network, manager, k+1, BMC_INITIAL_STATES);
+
+    loopArray = array_alloc(bAigEdge_t, k+1);
+    array_insert(bAigEdge_t, loopArray, 0, bAig_Zero);
+    smallerExists   = array_alloc(bAigEdge_t, k+1);
+    array_insert(bAigEdge_t, smallerExists, 0, bAig_Zero);
+
+    loop = bAig_One;
+    for(i=1; i<= k; i++){
+      tmp = bAig_CreateNode(manager, bAig_NULL, bAig_NULL);
+      array_insert(bAigEdge_t, loopArray, i, tmp);
+      tmp = bAig_Then(manager, tmp,
+		      BmcCirCUsConnectFromStateToState(network, k-1, i-1, nodeToMvfAigTable,
+						       coiIndexTable, BMC_INITIAL_STATES));
+      loop = bAig_And(manager, loop, tmp); 
+    }
+    array_insert(bAigEdge_t, smallerExists, 1, bAig_Zero);
+    for(i=1; i<= k; i++){
+      bAigEdge_t left, right;
+
+      left = array_fetch(bAigEdge_t, smallerExists, i);
+      right = array_fetch(bAigEdge_t, loopArray, i);
+      
+      array_insert(bAigEdge_t, smallerExists, i+1,
+		   bAig_Or(manager, left, right));
+    }
+    atMostOnce =  bAig_One;
+    for(i=1; i<= k; i++){
+      bAigEdge_t left, right;
+
+      left = array_fetch(bAigEdge_t, smallerExists, i);
+      right = array_fetch(bAigEdge_t, loopArray, i);
+      
+      tmp = bAig_Then(manager, left, bAig_Not(right));
+      atMostOnce = bAig_And(manager, atMostOnce, tmp);
+    }
+
+    loopConstraints = bAig_And(manager, loop, atMostOnce);
+
+    property = BmcCirCUsGenerateLogicForLtlFixPoint(network, ltl, 0, k, loopArray);
+
+    if(fairness) {
+      fair = bAig_One;
+      arrayForEachItem(Ctlsp_Formula_t *, ltlConstraintArray, i, formula) {
+	fair = bAig_And(manager, fair,
+			BmcCirCUsGenerateLogicForLtlFixPoint(network, formula,
+							     0, k, loopArray));
+      }
+      array_insert(bAigEdge_t, objArray, 2, fair);
+    } else {
+      array_insert(bAigEdge_t, objArray, 2,  bAig_One);
+    }
+
+    array_insert(bAigEdge_t, objArray, 0, loopConstraints);
+    array_insert(bAigEdge_t, objArray, 1, property);
+    options->cnfPrefix = k;
+    interface = BmcCirCUsInterfaceWithObjArr(manager, network,
+					     objArray, objArray,
+					     options, interface);
+    array_free(smallerExists);
+    
+    satFlag = interface->status;
+    if(satFlag == SAT_SAT) {
+      formulaStatus = BmcPropertyFailed_c;
+      break;
+    }
+    array_free(loopArray);
+    /*
+      Use the termination check if the the LTL formula is not bounded
+    */
+    if(!boundedFormula &&
+       (formulaStatus == BmcPropertyUndecided_c) &&
+       (nextAction != 1)){
+      if((options->inductiveStep !=0) &&
+	 (k % options->inductiveStep == 0))
+	{
+	  /*
+	    Check for termination for the current value of k.
+	  */
+	  terminationStatus->k = k;
+	  BmcCirCUsAutLtlCheckForTermination(network, manager,
+					     nodeToMvfAigTable,
+					     terminationStatus,
+					     coiIndexTable, options);
+	  nextAction = terminationStatus->action;
+	  if(nextAction == 1){
+	    maxK = terminationStatus->k;
+	  } else 
+	    if(nextAction == 3){
+	      formulaStatus = BmcPropertyPassed_c;
+	      maxK = k;
+	      break;
+	    }
+
+	}
+    } /* terminationStatus */
+      
+    k += options->step;
+  }
+  array_free(objArray);
+  array_free(auxObjArray);
+  st_free_table(coiIndexTable);
+  sat_FreeInterface(interface);
+
+  if(formulaStatus == BmcPropertyUndecided_c){
+    /*
+      If no counterexample of length up to a certain bound, then the property
+      passes.
+    */
+    if(nextAction == 1){
+      formulaStatus = BmcPropertyPassed_c;
+    } else 
+      if (boundedFormula && depth <= options->maxK){
+	formulaStatus = BmcPropertyPassed_c;
+      }
+  }
+  if(options->satSolverError){
+    (void) fprintf(vis_stdout,"# BMC: Error in calling SAT solver\n");
+  } else {
+    if(formulaStatus == BmcPropertyFailed_c) {
+      (void) fprintf(vis_stdout, "# BMC: formula failed\n");
+      if(options->verbosityLevel != BmcVerbosityNone_c){
+	(void) fprintf(vis_stdout,
+		       "# BMC: Found a counterexample of length = %d \n", k);
+      }
+      if (options->dbgLevel == 1) {
+	int loop = k;
+	/*
+	  Adjust loopArray to print a proper counterexample.  The encoding
+	  scheme does not differentiate between loop and no-loop path.  If the
+	  path has a loop, then the path length is k-1.
+	*/
+	for(i=1; i< k; i++){
+	  bAigEdge_t   v      = array_fetch(bAigEdge_t, loopArray, i+1);
+	  unsigned int lvalue = aig_value(v); 
+	  
+	  if(lvalue == 1) {
+	    loop = k-1;
+	  }
+	  array_insert(bAigEdge_t, loopArray, i, v);
+	}
+        if (options->dbgLevel == 1) {
+	  BmcCirCUsPrintCounterExample(network, nodeToMvfAigTable,
+				     coiTable, loop, loopArray,
+				     options, BMC_INITIAL_STATES);
+        }
+        if (options->dbgLevel == 1) {
+          BmcCirCUsPrintCounterExampleAiger(network, nodeToMvfAigTable,
+                                     coiTable, loop, loopArray,
+                                     options, BMC_INITIAL_STATES);
+        }
+	array_free(loopArray);
+      }
+    } else if(formulaStatus == BmcPropertyPassed_c) {
+      (void) fprintf(vis_stdout, "# BMC: formula Passed\n");
+      (void) fprintf(vis_stdout, "#      Termination depth = %d\n", maxK);
+    } else if(formulaStatus == BmcPropertyUndecided_c) {
+      (void) fprintf(vis_stdout,"# BMC: formula undecided\n");
+      if (options->verbosityLevel != BmcVerbosityNone_c){
+	(void) fprintf(vis_stdout,
+		       "# BMC: no counterexample found of length up to %d\n",
+		       maxK);
+      }
+    }
+  }
+  
+  /*
+    free all used memories
+  */
+  if(terminationStatus){
+    BmcAutTerminationFree(terminationStatus);
+  }
+  if(fairness){
+     array_free(ltlConstraintArray);
+  }
+ 
+  if (options->verbosityLevel != BmcVerbosityNone_c) {
+    endTime = util_cpu_ctime();
+    fprintf(vis_stdout, "-- bmc time = %10g\n", (double)(endTime - startTime) / 1000.0);
+  }
+
+  fflush(vis_stdout);
+}
+
+
+/**Function********************************************************************
+
+   Synopsis [Apply BMC on a safety properties]
+
+   Description []
+
+   SideEffects []
+   
+   SeeAlso     []
+   
+******************************************************************************/
+
+void
+BmcCirCUsLtlCheckSafety(
+    Ntk_Network_t   *network,
+    Ctlsp_Formula_t *ltl,
+    BmcOption_t     *options,
+    st_table        *coiTable)
+{
+  mAig_Manager_t    *manager = Ntk_NetworkReadMAigManager(network);
+  st_table          *nodeToMvfAigTable = NIL(st_table);
+  long              startTime, endTime;
+  bAigEdge_t        noLoop;
+  int               depth, satFlag, bound;
+  int               minK = options->minK;
+  int               maxK = options->maxK;
+  int               boundedFormula;
+  array_t           *previousResultArray;
+  satInterface_t    *interface;
+  array_t           *objArray;
+  BmcCheckForTermination_t *terminationStatus = 0;
+  Bmc_PropertyStatus       formulaStatus;
+  st_table          *coiIndexTable;
+
+  assert(Ctlsp_LtlFormulaTestIsSyntacticallyCoSafe(ltl));
+  
+  startTime = util_cpu_ctime();
+
+  nodeToMvfAigTable = 
+    (st_table *) Ntk_NetworkReadApplInfo(network,
+					 MVFAIG_NETWORK_APPL_KEY);
+  assert(nodeToMvfAigTable != NIL(st_table));
+  
+  /*
+    For bounded formulae use a tighter upper bound if possible.
+  */
+  boundedFormula = Ctlsp_LtlFormulaTestIsBounded(ltl, &depth);
+  if (boundedFormula && depth < maxK && depth >= minK) {
+    maxK = depth;
+  } else {
+    if(options->inductiveStep !=0){
+      /*
+	Use the termination criteria to prove the property passes.    
+      */
+      terminationStatus = BmcAutTerminationAlloc(network,
+						 Ctlsp_LtllFormulaNegate(ltl),
+						 NIL(array_t));
+      assert(Ltl_AutomatonGetStrength(terminationStatus->automaton) == 0); /* Terminal Automaton*/
+      assert(terminationStatus);
+    }
+  }
+  if (options->verbosityLevel != BmcVerbosityNone_c){
+    (void) fprintf(vis_stdout, "saftey LTL BMC\n");
+    if (boundedFormula){
+      (void) fprintf(vis_stdout, "Bounded formula of depth %d\n", depth);
+    }
+    (void) fprintf(vis_stdout, "Apply BMC on counterexample of length >= %d and <= %d (+%d) \n",
+		  minK, maxK, options->step);
+  }
+  satFlag   = SAT_UNSAT;
+  bAig_ExpandTimeFrame(network, manager, 0, BMC_INITIAL_STATES);
+  coiIndexTable = BmcCirCUsGetCoiIndexTable(network, coiTable);
+  interface = 0;
+  formulaStatus = BmcPropertyUndecided_c;
+  /*
+    Hold objects 
+  */
+  objArray = array_alloc(bAigEdge_t, 1);
+
+  previousResultArray = array_alloc(bAigEdge_t, 0);
+  bound=minK;
+  while(bound<=maxK) {
+    
+    if(options->verbosityLevel == BmcVerbosityMax_c)
+      fprintf(vis_stdout, "\nGenerate counterexample of length %d\n", bound);
+    fflush(vis_stdout);
+
+    bAig_ExpandTimeFrame(network, manager, bound+1, BMC_INITIAL_STATES);
+
+    /*
+      A counterexample to a safety property is finite path at which the
+      safety property does not hold.
+     */
+    noLoop = BmcCirCUsGenerateLogicForLtl(network, ltl, 0, bound, -1);
+    array_insert(bAigEdge_t, objArray, 0, noLoop);
+    
+    options->cnfPrefix = bound;
+    interface = BmcCirCUsInterfaceWithObjArr(manager, network,
+					     objArray,
+					     previousResultArray,
+					     options,
+					     interface);
+    satFlag = interface->status;
+    if(satFlag == SAT_SAT) {
+      formulaStatus = BmcPropertyFailed_c;
+      break;
+    }
+    array_insert_last(bAigEdge_t, previousResultArray, bAig_Not(noLoop));
+
+    /*
+      Use the termination check if the the LTL formula is not bounded
+    */
+    if(!boundedFormula &&
+       (options->inductiveStep !=0) &&
+       (bound % options->inductiveStep == 0))
+      {
+	terminationStatus->k = bound;
+	BmcCirCUsAutLtlCheckTerminalAutomaton(network, manager,
+					      nodeToMvfAigTable,
+					      terminationStatus,
+					      coiIndexTable, options);
+	if(terminationStatus->action == 1){
+	  formulaStatus = BmcPropertyPassed_c;
+	  maxK = bound;
+	  break;
+	}
+      }
+    bound += options->step;
+  }
+  array_free(objArray);
+  array_free(previousResultArray);
+  sat_FreeInterface(interface);
+
+  if ((formulaStatus != BmcPropertyFailed_c) && boundedFormula && depth <= options->maxK){
+    /*
+      No counterexample of length up to the bounded depth of the LTL formula is
+      found. Formula passes
+    */
+    formulaStatus = BmcPropertyPassed_c;
+  }
+  
+  if(options->satSolverError){
+    (void) fprintf(vis_stdout,"# BMC: Error in calling SAT solver\n");
+  } else {
+    if(formulaStatus == BmcPropertyFailed_c) {
+      (void) fprintf(vis_stdout, "# BMC: formula failed\n");
+      if(options->verbosityLevel != BmcVerbosityNone_c){
+	(void) fprintf(vis_stdout,
+		       "# BMC: Found a counterexample of length = %d \n", bound);
+      }
+      if (options->dbgLevel == 1) {
+	BmcCirCUsPrintCounterExample(network, nodeToMvfAigTable, coiTable, bound, NIL(array_t),
+				     options, BMC_INITIAL_STATES);
+      }
+      if (options->dbgLevel == 2) {
+        BmcCirCUsPrintCounterExampleAiger(network, nodeToMvfAigTable, coiTable, bound, NIL(array_t),
+                                     options, BMC_INITIAL_STATES);
+      }
+    } else if(formulaStatus == BmcPropertyPassed_c) {
+      (void) fprintf(vis_stdout, "# BMC: formula Passed\n");
+      (void) fprintf(vis_stdout, "#      Termination depth = %d\n", maxK);
+    } else if(formulaStatus == BmcPropertyUndecided_c) {
+      (void) fprintf(vis_stdout,"# BMC: formula undecided\n");
+      if (options->verbosityLevel != BmcVerbosityNone_c){
+	(void) fprintf(vis_stdout,
+		       "# BMC: no counterexample found of length up to %d \n",
+		       maxK);
+      }
+    }
+  }
+
+  if (options->verbosityLevel != BmcVerbosityNone_c) {
+    endTime = util_cpu_ctime();
+    fprintf(vis_stdout, "-- bmc time = %10g\n", (double)(endTime - startTime) / 1000.0);
+  }
+  fflush(vis_stdout);  
+  return;
+
+}
+
+
+/**Function********************************************************************
+
+   Synopsis [Build AIG for a transition from state "from" to state "to"]
+
+   Description [The state next to "from" equal to "to".  (from+1) == to]
+
+   SideEffects []
+   
+   SeeAlso     []
+   
+******************************************************************************/
+
+bAigEdge_t
+BmcCirCUsConnectFromStateToState(
+    Ntk_Network_t   *network,
+    int from,
+    int to,
+    st_table *nodeToMvfAigTable,
+    st_table *coiIndexTable,
+    int withInitialState)
+{
+  bAigEdge_t *fli, *tli;
+  bAigEdge_t loop, tv;
+  int l, index, nLatches;
+  bAigTimeFrame_t *timeframe;
+  mAig_Manager_t    *manager = Ntk_NetworkReadMAigManager(network);
+
+  if(withInitialState)	timeframe = manager->timeframe;
+  else                  timeframe = manager->timeframeWOI;
+
+  fli = timeframe->latchInputs[from+1];
+  tli = timeframe->latchInputs[to]; 
+  loop = bAig_One;
+  nLatches = timeframe->nLatches;
+  for(l=0; l<nLatches; l++) {
+    if(!st_lookup_int(coiIndexTable, (char *)(long)l, &index))	continue;
+    tv = bAig_Eq(manager, fli[l], tli[l]);
+    loop = bAig_And(manager, tv, loop);
+    if(loop == bAig_Zero)	break;
+  }
+  return(loop);
+}
+
+
+/**Function********************************************************************
+
+   Synopsis [Create AIG graph for simple path constraint]
+
+   Description [Create AIG graph that constrains a path starting from
+   'fromState' and ending at 'toState' to be a simple path.  A simple
+   path is a path such that every state in the path is distinct. i.e
+   for all states in the path Si != Sj for fromState <= i < j <=
+   toState.]
+
+   SideEffects []
+   
+   SeeAlso     []
+   
+******************************************************************************/
+bAigEdge_t
+BmcCirCUsSimlePathConstraint(
+  Ntk_Network_t *network,
+  int           fromState,
+  int           toState,
+  st_table      *nodeToMvfAigTable,
+  st_table      *coiIndexTable,
+  int withInitialState)
+{
+  int             i, j; 
+  bAigEdge_t      loop, nLoop;
+  mAig_Manager_t  *manager = Ntk_NetworkReadMAigManager(network);
+
+  nLoop = bAig_One;
+  for(i=fromState+1; i<=toState; i++) {
+    for(j=fromState; j<i; j++) {
+      /*
+	We want state Si == Sj, but the following function returns
+	S(i+1) == Sj.  So we call the function with i-1.
+      */
+      loop = BmcCirCUsConnectFromStateToState(
+	     network, i-1, j, nodeToMvfAigTable, coiIndexTable, withInitialState);
+      nLoop = bAig_And(manager, nLoop, bAig_Not(loop));
+    }
+  }
+  return(nLoop);
+} /* BmcCirCUsSimplePathConstraint */
+
+
+/**Function********************************************************************
+
+   Synopsis [Build an AIG graph for a simple path]
+
+   Description []
+
+   SideEffects []
+   
+   SeeAlso     []
+   
+******************************************************************************/
+
+bAigEdge_t
+BmcCirCUsGenerateSimplePath(
+	Ntk_Network_t   *network,
+	int from,
+	int to,
+	st_table *nodeToMvfAigTable,
+        st_table *coiIndexTable,
+	int withInitialState)
+{
+int i, j; 
+bAigEdge_t loop, nloop;
+mAig_Manager_t    *manager;
+    
+  manager = Ntk_NetworkReadMAigManager(network);
+
+  bAig_ExpandTimeFrame(network, manager, to, withInitialState);
+
+  nloop = bAig_One;
+  for(i=from+1; i<=to; i++) {
+    for(j=from; j<i; j++) {
+      loop = BmcCirCUsConnectFromStateToState(
+	     network, i-1, j, nodeToMvfAigTable, coiIndexTable, withInitialState);
+      nloop = bAig_And(manager, nloop, bAig_Not(loop));
+    }
+  }
+  return(nloop);
+}
+
+
+/**Function********************************************************************
+
+   Synopsis []
+
+   Description []
+
+   SideEffects []
+   
+   SeeAlso     []
+   
+******************************************************************************/
+
+void
+BmcCirCUsPrintCounterExample(
+  Ntk_Network_t   *network,
+  st_table        *nodeToMvfAigTable,
+  st_table        *coiTable,
+  int             length,
+  array_t         *loop_arr,
+  BmcOption_t     *options,
+  int withInitialState)
+{
+  int *prevLatchValues, *prevInputValues;
+  mAig_Manager_t    *manager = Ntk_NetworkReadMAigManager(network);
+  int loop, k;
+  unsigned int lvalue;
+  bAigEdge_t v;
+  array_t *latchArr;
+  lsGen gen;
+  Ntk_Node_t *node;
+  int tmp;
+  bAigTimeFrame_t *timeframe;
+  FILE *dbgOut = NULL;
+
+  latchArr = array_alloc(Ntk_Node_t *, 0);
+  Ntk_NetworkForEachLatch(network, gen, node){
+    if (st_lookup_int(coiTable, (char *) node, &tmp)){
+      array_insert_last(Ntk_Node_t *, latchArr, node);
+    }
+  }
+
+  if(options->dbgOut)
+  {
+    dbgOut = vis_stdout;
+    vis_stdout = options->dbgOut;
+  }
+
+  /** check index such as, k, length, loop */
+
+  if(withInitialState)	timeframe = manager->timeframe;
+  else                  timeframe = manager->timeframeWOI;
+
+  prevLatchValues = ALLOC(int, timeframe->nLatches);
+  prevInputValues = ALLOC(int, timeframe->nInputs);
+
+  loop = -1;
+  if(loop_arr != 0) {
+    for(k=array_n(loop_arr)-1; k>=0; k--) {
+      v = array_fetch(bAigEdge_t, loop_arr, k);
+      lvalue = aig_value(v);
+      if(lvalue == 1) {
+	loop = k;
+	break;
+      }
+    }
+  }
+  for(k=0; k<=length; k++) {
+    if(k == 0) fprintf(vis_stdout, "\n--State %d:\n", k);
+    else       fprintf(vis_stdout, "\n--Goes to state %d:\n", k);
+  
+    printSatValue(manager, nodeToMvfAigTable, 
+		    timeframe->li2index, 
+		    timeframe->latchInputs, latchArr,
+		    k, prevLatchValues);
+
+    if(options->printInputs == TRUE && k!=0) {
+      fprintf(vis_stdout, "--On input:\n");
+      printSatValue(manager, nodeToMvfAigTable, 
+	            timeframe->pi2index,
+		    timeframe->inputs, timeframe->inputArr,
+		    k-1, prevInputValues);
+    }
+  }
+
+  if(loop >=0) {
+    fprintf(vis_stdout, "\n--Goes back to state %d:\n", loop);
+
+    printSatValue(manager, nodeToMvfAigTable, 
+	            timeframe->li2index,
+		    timeframe->latchInputs, latchArr,
+		    loop, prevLatchValues);
+
+    if(options->printInputs == TRUE && k!=0) {
+      fprintf(vis_stdout, "--On input:\n");
+      printSatValue(manager, nodeToMvfAigTable, 
+	            timeframe->pi2index,
+		    timeframe->inputs, timeframe->inputArr,
+		    length, prevInputValues);
+    }
+  }
+
+  array_free(latchArr);
+  if(options->dbgOut)
+  {
+    vis_stdout = dbgOut;
+  }
+  return;
+}
+
+
+
+/**Function********************************************************************
+
+   Synopsis [Prints the counter-example in Aiger format.]
+
+   Description [The Aiger format is as follows, 
+                currentState, input, output, nextState 
+                the names of the variables aren't printed rather their values
+		are only printed, -i option is set by default.]
+
+   SideEffects []
+   
+   SeeAlso     []
+   
+******************************************************************************/
+
+void
+BmcCirCUsPrintCounterExampleAiger(
+  Ntk_Network_t   *network,
+  st_table        *nodeToMvfAigTable,
+  st_table        *coiTable,
+  int             length,
+  array_t         *loop_arr,
+  BmcOption_t     *options,
+  int withInitialState)
+{
+  int *prevLatchValues, *prevInputValues;
+  mAig_Manager_t    *manager = Ntk_NetworkReadMAigManager(network);
+  int loop, k;
+  unsigned int lvalue;
+  bAigEdge_t v;
+  array_t *latchArr;
+  lsGen gen;
+  Ntk_Node_t *node;
+  int tmp;
+  bAigTimeFrame_t *timeframe;
+  FILE *dbgOut = NULL;
+
+  latchArr = array_alloc(Ntk_Node_t *, 0);
+  Ntk_NetworkForEachLatch(network, gen, node){
+    if (st_lookup_int(coiTable, (char *) node, &tmp)){
+      array_insert_last(Ntk_Node_t *, latchArr, node);
+    }
+  }
+
+  /* writing into a file is not being done in a standard way, need to confirm
+     the writing of trace into a file with the vis standard */
+
+  if(options->dbgOut)
+  {
+    dbgOut = vis_stdout;
+    vis_stdout = options->dbgOut;
+  }
+
+  /** check index such as, k, length, loop */
+
+  if(withInitialState)	timeframe = manager->timeframe;
+  else                  timeframe = manager->timeframeWOI;
+
+  prevLatchValues = ALLOC(int, timeframe->nLatches);
+  prevInputValues = ALLOC(int, timeframe->nInputs);
+
+  loop = -1;
+  if(loop_arr != 0) {
+    for(k=array_n(loop_arr)-1; k>=0; k--) {
+      v = array_fetch(bAigEdge_t, loop_arr, k);
+      lvalue = aig_value(v);
+      if(lvalue == 1) {
+	loop = k;
+	break;
+      }
+    }
+  }
+  
+  /* we need to get rid of the file generation for next vis release and look
+     into ntk package so that the original order can be maintained */
+
+  FILE *order = Cmd_FileOpen("inputOrder.txt", "w", NIL(char *), 0) ;
+  for(k=0; k<array_n(timeframe->inputArr); k++)
+  {
+    node = array_fetch(Ntk_Node_t *, timeframe->inputArr, k);
+    fprintf(order, "%s\n", Ntk_NodeReadName(node));
+  }
+  fclose(order);
+    
+  for(k=0; k<=length; k++) {
+    /*if(k == 0) fprintf(vis_stdout, "\n--State %d:\n", k);
+    else       fprintf(vis_stdout, "\n--Goes to state %d:\n", k);*/
+
+    /*if((loop>=0)||(k<length))
+    { */
+      printSatValueAiger(manager, nodeToMvfAigTable, 
+		    timeframe->li2index, 
+		    timeframe->latchInputs, latchArr,
+		    k, prevLatchValues);
+      fprintf(vis_stdout, " ");
+
+    if((loop<0)||(k<length))
+    { 
+      if(k!=length+1) {
+        printSatValueAiger(manager, nodeToMvfAigTable, 
+	            timeframe->pi2index,
+		    timeframe->inputs, timeframe->inputArr,
+		    k, prevInputValues);
+        fprintf(vis_stdout, " ");
+      }
+
+      if(k!=length+1) {
+        printSatValueAiger(manager, nodeToMvfAigTable, 
+	            timeframe->o2index,
+		    timeframe->outputs, timeframe->outputArr,
+		    k, prevInputValues);
+        fprintf(vis_stdout, " ");
+      }
+
+      if(k!=length+1) {
+        printSatValueAiger(manager, nodeToMvfAigTable,
+                    timeframe->li2index,
+                    timeframe->latchInputs, latchArr,
+                    k+1, prevLatchValues);
+        fprintf(vis_stdout, " ");
+      }
+      if((loop < 0)||(k!=length))
+      {
+        fprintf(vis_stdout, "\n");
+      }
+    }
+  }
+
+  if(loop >=0) {
+    /*fprintf(vis_stdout, "\n--Goes back to state %d:\n", loop);*/
+
+    if(k!=0) {
+      printSatValueAiger(manager, nodeToMvfAigTable,
+                    timeframe->pi2index,
+                    timeframe->inputs, timeframe->inputArr,
+                    length, prevInputValues);
+      fprintf(vis_stdout, " ");
+    }
+
+    printSatValueAiger(manager, nodeToMvfAigTable,
+                    timeframe->o2index,
+                    timeframe->outputs, timeframe->outputArr,
+                    k, prevInputValues);
+    fprintf(vis_stdout, " ");
+
+    printSatValueAiger(manager, nodeToMvfAigTable, 
+	            timeframe->li2index,
+		    timeframe->latchInputs, latchArr,
+		    loop, prevLatchValues);
+    
+    fprintf(vis_stdout, "\n");
+  }
+
+  array_free(latchArr);
+  if(options->dbgOut)
+  {
+    vis_stdout = dbgOut;
+  }
+  return;
+} /* BmcCirCUsPrintCounterExampleAiger */
+
+/**Function********************************************************************
+
+   Synopsis []
+
+   Description []
+
+   SideEffects []
+   
+   SeeAlso     []
+   
+******************************************************************************/
+
+
+static int
+printSatValue(
+    bAig_Manager_t *manager,
+    st_table        *nodeToMvfAigTable,
+    st_table *li2index,
+    bAigEdge_t **baigArr,
+    array_t *nodeArr, 
+    int bound,
+    int *prevValue)
+{
+  Ntk_Node_t * node;
+  int value, lvalue;
+  char *symbolicValue;
+  bAigEdge_t *li, v, tv;
+  int i, j, timeframe, index;
+  int changed=0;
+  MvfAig_Function_t  *mvfAig;
+
+  timeframe = bound;
+  li = baigArr[timeframe];
+  for(i=0; i<array_n(nodeArr); i++) {
+    if(timeframe == 0)	prevValue[i] = -1;
+    node = array_fetch(Ntk_Node_t *, nodeArr, i);
+    mvfAig = Bmc_ReadMvfAig(node, nodeToMvfAigTable);
+
+    if(mvfAig == 0)	continue;
+
+    value = -1;
+    for (j=0; j< array_n(mvfAig); j++) {
+      v = MvfAig_FunctionReadComponent(mvfAig, j);
+      index = -1;
+      if(!st_lookup_int(li2index, (char *)v, &index)) {
+	fprintf(vis_stdout, "printSatValueERROR \n");
+      }
+      v = li[index];
+      if(v == bAig_One)	{
+	value = j;
+	break;
+      }
+
+      if(v != bAig_Zero) {
+	tv = bAig_GetCanonical(manager, v);
+	lvalue = bAig_GetValueOfNode(manager, tv);
+	if(lvalue == 1){	
+	  value = j;
+	  break;
+	}
+      }
+    }
+    if(value >=0) {
+      if (value != prevValue[i]){
+	Var_Variable_t *nodeVar = Ntk_NodeReadVariable(node);
+	prevValue[i] = value;
+	changed = 1;
+	if (Var_VariableTestIsSymbolic(nodeVar)) {
+	  symbolicValue = Var_VariableReadSymbolicValueFromIndex(nodeVar, value);
+	  fprintf(vis_stdout,"%s:%s\n",  Ntk_NodeReadName(node), symbolicValue);
+	} 
+	else {
+	  fprintf(vis_stdout,"%s:%d\n",  Ntk_NodeReadName(node), value);
+	}
+      }
+    }
+  } /* for j loop */
+  if (changed == 0){
+    fprintf(vis_stdout, "<Unchanged>\n");
+  }
+  return 0;
+}
+
+/**Function********************************************************************
+
+   Synopsis [Prints the counter-example in the Aiger Format.]
+
+   Description []
+
+   SideEffects []
+   
+   SeeAlso     [BmcCirCUsPrintCounterExampleAiger]
+   
+******************************************************************************/
+
+static int
+printSatValueAiger(
+    bAig_Manager_t *manager,
+    st_table        *nodeToMvfAigTable,
+    st_table *li2index,
+    bAigEdge_t **baigArr,
+    array_t *nodeArr, 
+    int bound,
+    int *prevValue)
+{
+  Ntk_Node_t * node;
+  int value, lvalue;
+  char *symbolicValue;
+  bAigEdge_t *li, v, tv;
+  int i, j, timeframe, index;
+  MvfAig_Function_t  *mvfAig;
+
+  timeframe = bound;
+  li = baigArr[timeframe];
+  for(i=0; i<array_n(nodeArr); i++) {
+    if(timeframe == 0)	prevValue[i] = -1;
+    node = array_fetch(Ntk_Node_t *, nodeArr, i);
+    mvfAig = Bmc_ReadMvfAig(node, nodeToMvfAigTable);
+
+    if(mvfAig == 0)	continue;
+
+    value = -1;
+    for (j=0; j< array_n(mvfAig); j++) {
+      v = MvfAig_FunctionReadComponent(mvfAig, j);
+      index = -1;
+      if(!st_lookup_int(li2index, (char *)v, &index)) {
+	fprintf(vis_stdout, "printSatValueERROR \n");
+      }
+      v = li[index];
+      if(v == bAig_One)	{
+	value = j;
+	break;
+      }
+
+      if(v != bAig_Zero) {
+	tv = bAig_GetCanonical(manager, v);
+	lvalue = bAig_GetValueOfNode(manager, tv);
+	if(lvalue == 1){	
+	  value = j;
+	  break;
+	}
+      }
+    }
+    if(value >=0) {
+      Var_Variable_t *nodeVar = Ntk_NodeReadVariable(node);
+      prevValue[i] = value;
+      if (Var_VariableTestIsSymbolic(nodeVar)) {
+        symbolicValue = Var_VariableReadSymbolicValueFromIndex(nodeVar, value);
+        fprintf(vis_stdout,"%s", symbolicValue);
+      } 
+      else {
+        fprintf(vis_stdout,"%d", value);
+      }
+    }
+    else
+    {
+      fprintf(vis_stdout,"x");
+    }
+  } /* for j loop */
+  return 0;
+} /* printSatValueAiger */
+
+/**Function********************************************************************
+
+  Synopsis [Builds AND/INVERTER graph (aig) for a propsitional formula
+  at time frame bound]
+
+  Description [Builds AND/INVERTER graph for a propsitional formula at
+  time frame bound.  Returns bAig ID of the function that is quivalent
+  to the propositional fomula]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bAigEdge_t 
+BmcCirCUsCreatebAigOfPropFormula(
+    Ntk_Network_t *network,
+    bAig_Manager_t *manager,
+    int bound,
+    Ctlsp_Formula_t *ltl,
+    int withInitialState)
+{
+  int index;
+  bAigEdge_t result, left, right, *li;
+  bAigTimeFrame_t *timeframe;
+
+  if (ltl == NIL(Ctlsp_Formula_t))	return mAig_NULL; 
+  if (ltl->type == Ctlsp_TRUE_c) 	return mAig_One; 
+  if (ltl->type == Ctlsp_FALSE_c) 	return mAig_Zero; 
+
+  assert(Ctlsp_isPropositionalFormula(ltl));
+  
+  if(withInitialState) timeframe = manager->timeframe;
+  else 	               timeframe = manager->timeframeWOI;
+
+  if (ltl->type == Ctlsp_ID_c){
+      char *nodeNameString  = Ctlsp_FormulaReadVariableName(ltl);
+      char *nodeValueString = Ctlsp_FormulaReadValueName(ltl);
+      Ntk_Node_t *node      = Ntk_NetworkFindNodeByName(network, nodeNameString);
+
+      Var_Variable_t *nodeVar;
+      int             nodeValue;
+
+      MvfAig_Function_t  *tmpMvfAig;
+      st_table           *nodeToMvfAigTable; /* maps each node to its mvfAig */
+      
+      if (node == NIL(Ntk_Node_t)) {
+	char   *nameKey;
+	char   tmpName[100];
+	
+	sprintf(tmpName, "%s_%d", nodeNameString, bound);
+	nameKey = util_strsav(tmpName);
+
+	result  = bAig_FindNodeByName(manager, nameKey);
+	if(result == bAig_NULL){
+	   result = bAig_CreateVarNode(manager, nameKey); 
+	} else {
+	  
+	  FREE(nameKey);
+	}
+
+	
+	return result;
+      }
+
+      nodeToMvfAigTable = (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+      assert(nodeToMvfAigTable != NIL(st_table));
+
+      tmpMvfAig = Bmc_ReadMvfAig(node, nodeToMvfAigTable);
+      if (tmpMvfAig ==  NIL(MvfAig_Function_t)){
+          tmpMvfAig = Bmc_NodeBuildMVF(network, node);
+	  array_free(tmpMvfAig);
+	  tmpMvfAig = Bmc_ReadMvfAig(node, nodeToMvfAigTable);
+      }
+      
+      nodeVar = Ntk_NodeReadVariable(node);
+      if (Var_VariableTestIsSymbolic(nodeVar)) {
+        nodeValue = Var_VariableReadIndexFromSymbolicValue(nodeVar, nodeValueString);
+        if ( nodeValue == -1 ) {
+          (void) fprintf(vis_stderr, "Value specified in RHS is not in domain of variable\n");
+          (void) fprintf(vis_stderr,"%s = %s\n", nodeNameString, nodeValueString);
+          return mAig_NULL;
+        }
+      }
+      else { 
+        int check;    
+         check = StringCheckIsInteger(nodeValueString, &nodeValue);
+         if( check == 0 ) {
+          (void) fprintf(vis_stderr,"Illegal value in the RHS\n");
+          (void) fprintf(vis_stderr,"%s = %s\n", nodeNameString, nodeValueString);
+          return mAig_NULL;
+	 }
+         if( check == 1 ) {
+          (void) fprintf(vis_stderr,"Value in the RHS is out of range of int\n");
+          (void) fprintf(vis_stderr,"%s = %s", nodeNameString, nodeValueString);
+          return mAig_NULL;
+	 }
+         if ( !(Var_VariableTestIsValueInRange(nodeVar, nodeValue))) {
+          (void) fprintf(vis_stderr,"Value specified in RHS is not in domain of variable\n");
+          (void) fprintf(vis_stderr,"%s = %s\n", nodeNameString, nodeValueString);
+          return mAig_NULL;
+
+         }
+      }
+      result = MvfAig_FunctionReadComponent(tmpMvfAig, nodeValue);
+      result = bAig_GetCanonical(manager, result);
+      if(st_lookup_int(timeframe->li2index, (char *)result, &index)) {
+        li = timeframe->latchInputs[bound];
+	result = bAig_GetCanonical(manager, li[index]);
+      }
+      else if(st_lookup_int(timeframe->o2index, (char *)result, &index)) {
+        li = timeframe->outputs[bound];
+	result = bAig_GetCanonical(manager, li[index]);
+      }
+      else if(st_lookup_int(timeframe->i2index, (char *)result, &index)) {
+        li = timeframe->internals[bound];
+	result = bAig_GetCanonical(manager, li[index]);
+      }
+      return result;
+  }
+
+  left = BmcCirCUsCreatebAigOfPropFormula(network, manager, bound, ltl->left, withInitialState);
+  if (left == mAig_NULL){
+    return mAig_NULL;
+  }  
+  right = BmcCirCUsCreatebAigOfPropFormula(network, manager, bound, ltl->right, withInitialState);
+  if (right == mAig_NULL && ltl->type ==Ctlsp_NOT_c ){
+    return mAig_Not(left);
+  }  
+  else if(right == mAig_NULL) {
+    return mAig_NULL;
+  }
+
+  switch(ltl->type) {
+/**
+    case Ctlsp_NOT_c:
+      result = mAig_Not(left);
+      break;
+      **/
+    case Ctlsp_OR_c:
+      result = mAig_Or(manager, left, right);
+      break;
+    case Ctlsp_AND_c:
+      result = mAig_And(manager, left, right);
+      break;
+    case Ctlsp_THEN_c:
+      result = mAig_Then(manager, left, right); 
+      break;
+    case Ctlsp_EQ_c:
+      result = mAig_Eq(manager, left, right);
+      break;
+    case Ctlsp_XOR_c:
+      result = mAig_Xor(manager, left, right);
+      break;
+    default:
+      fail("Unexpected type");
+  }
+  return result;
+} /* BmcCirCUsCreatebAigOfPropFormula */
+
+/**Function********************************************************************
+
+  Synopsis [Builds AND/INVERTER graph (aig) for a propsitional formula]
+
+  Description [Builds AND/INVERTER graph for a propsitional formula.
+  Returns bAig ID of the function that is quivalent to the propositional
+  fomula]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+bAigEdge_t 
+BmcCirCUsCreatebAigOfPropFormulaOriginal(
+    Ntk_Network_t *network,
+    bAig_Manager_t *manager,
+    Ctlsp_Formula_t *ltl
+    )
+{
+  bAigEdge_t result, left, right;
+
+  if (ltl == NIL(Ctlsp_Formula_t))	return mAig_NULL; 
+  if (ltl->type == Ctlsp_TRUE_c) 	return mAig_One; 
+  if (ltl->type == Ctlsp_FALSE_c) 	return mAig_Zero; 
+
+  assert(Ctlsp_isPropositionalFormula(ltl));
+    
+  if (ltl->type == Ctlsp_ID_c){
+      char *nodeNameString  = Ctlsp_FormulaReadVariableName(ltl);
+      char *nodeValueString = Ctlsp_FormulaReadValueName(ltl);
+      Ntk_Node_t *node      = Ntk_NetworkFindNodeByName(network, nodeNameString);
+
+      Var_Variable_t *nodeVar;
+      int             nodeValue;
+
+      MvfAig_Function_t  *tmpMvfAig;
+      st_table           *nodeToMvfAigTable; /* maps each node to its mvfAig */
+      
+      if (node == NIL(Ntk_Node_t)) {
+          (void) fprintf(vis_stderr, "bmc error: Could not find node corresponding to the name\t %s\n", nodeNameString);
+          return mAig_NULL;
+      }
+
+      nodeToMvfAigTable = (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+      if (nodeToMvfAigTable == NIL(st_table)){
+         (void) fprintf(vis_stderr, "bmc error: please run build_partiton_maigs first");
+         return mAig_NULL;
+      }
+      tmpMvfAig = Bmc_ReadMvfAig(node, nodeToMvfAigTable);
+      if (tmpMvfAig ==  NIL(MvfAig_Function_t)){
+          tmpMvfAig = Bmc_NodeBuildMVF(network, node);
+	  array_free(tmpMvfAig);
+	  tmpMvfAig = Bmc_ReadMvfAig(node, nodeToMvfAigTable);
+      }
+      
+      nodeVar = Ntk_NodeReadVariable(node);
+      if (Var_VariableTestIsSymbolic(nodeVar)) {
+        nodeValue = Var_VariableReadIndexFromSymbolicValue(nodeVar, nodeValueString);
+        if ( nodeValue == -1 ) {
+          (void) fprintf(vis_stderr, "Value specified in RHS is not in domain of variable\n");
+          (void) fprintf(vis_stderr,"%s = %s\n", nodeNameString, nodeValueString);
+          return mAig_NULL;
+        }
+      }
+      else { 
+        int check;    
+         check = StringCheckIsInteger(nodeValueString, &nodeValue);
+         if( check == 0 ) {
+          (void) fprintf(vis_stderr,"Illegal value in the RHS\n");
+          (void) fprintf(vis_stderr,"%s = %s\n", nodeNameString, nodeValueString);
+          return mAig_NULL;
+	 }
+         if( check == 1 ) {
+          (void) fprintf(vis_stderr,"Value in the RHS is out of range of int\n");
+          (void) fprintf(vis_stderr,"%s = %s", nodeNameString, nodeValueString);
+          return mAig_NULL;
+	 }
+         if ( !(Var_VariableTestIsValueInRange(nodeVar, nodeValue))) {
+          (void) fprintf(vis_stderr,"Value specified in RHS is not in domain of variable\n");
+          (void) fprintf(vis_stderr,"%s = %s\n", nodeNameString, nodeValueString);
+          return mAig_NULL;
+
+         }
+      }
+      result = bAig_GetCanonical(manager,
+	      MvfAig_FunctionReadComponent(tmpMvfAig, nodeValue));
+      return result;
+  }
+
+  left = BmcCirCUsCreatebAigOfPropFormulaOriginal(network, manager, ltl->left);
+  if (left == mAig_NULL){
+    return mAig_NULL;
+  }  
+  right = BmcCirCUsCreatebAigOfPropFormulaOriginal(network, manager, ltl->right);
+  if (right == mAig_NULL && ltl->type ==Ctlsp_NOT_c ){
+    return mAig_Not(left);
+  }  
+  else if(right == mAig_NULL) {
+    return mAig_NULL;
+  }
+
+  switch(ltl->type) {
+/**
+    case Ctlsp_NOT_c:
+      result = mAig_Not(left);
+      break;
+      **/
+    case Ctlsp_OR_c:
+      result = mAig_Or(manager, left, right);
+      break;
+    case Ctlsp_AND_c:
+      result = mAig_And(manager, left, right);
+      break;
+    case Ctlsp_THEN_c:
+      result = mAig_Then(manager, left, right); 
+      break;
+    case Ctlsp_EQ_c:
+      result = mAig_Eq(manager, left, right);
+      break;
+    case Ctlsp_XOR_c:
+      result = mAig_Xor(manager, left, right);
+      break;
+    default:
+      fail("Unexpected LTL type");
+  }
+  return result;
+} /* BmcCirCUsCreatebAigOfPropFormulaOriginal */
+
+/**Function********************************************************************
+
+   Synopsis [ Check the given string is integer]
+
+   Description [ Check the given string is integer]
+
+   SideEffects []
+   
+   SeeAlso     []
+   
+******************************************************************************/
+
+static int
+StringCheckIsInteger(
+  char *string,
+  int *value)
+{
+  char *ptr;
+  long l;
+  
+  l = strtol (string, &ptr, 0) ;
+  if(*ptr != '\0')
+    return 0;
+  if ((l > MAXINT) || (l < -1 - MAXINT))
+    return 1 ;
+  *value = (int) l;
+  return 2 ;
+}
+
+
+/**Function********************************************************************
+
+   Synopsis [ CirCUs interface for bounded model checking.]
+
+   Description [ CirCUs interface for bounded model checking. ]
+
+   SideEffects []
+   
+   SeeAlso     []
+   
+******************************************************************************/
+
+satInterface_t *
+BmcCirCUsInterface(
+    bAig_Manager_t *manager,
+    Ntk_Network_t  *network,
+    bAigEdge_t     object,
+    array_t        *auxObjectArray,
+    BmcOption_t    *bmcOption,
+    satInterface_t *interface)
+{
+satManager_t   *cm;
+satOption_t    *option;
+satLevel_t *d;
+int i, size;
+bAigEdge_t tv;
+
+/* allocate sat manager */
+  cm = sat_InitManager(interface);
+  cm->nodesArraySize = manager->nodesArraySize;
+  cm->initNodesArraySize = manager->nodesArraySize;
+  cm->maxNodesArraySize = manager->maxNodesArraySize;
+  cm->nodesArray = manager->NodesArray;
+  cm->HashTable = manager->HashTable;
+  cm->literals = manager->literals;
+  cm->initNumVariables = (manager->nodesArraySize/bAigNodeSize);
+  cm->initNumClauses = 0;
+  cm->initNumLiterals = 0;
+  cm->comment = ALLOC(char, 2);
+  cm->comment[0] = ' ';
+  cm->comment[1] = '\0';
+  cm->stdErr = vis_stderr;
+  cm->stdOut = vis_stdout;
+  cm->status = 0;
+  cm->orderedVariableArray = 0;
+  cm->unitLits = sat_ArrayAlloc(16);
+  cm->pureLits = sat_ArrayAlloc(16);
+  cm->option = 0;
+  cm->each = 0;
+  cm->decisionHead = 0;
+  cm->variableArray = 0;
+  cm->queue = 0;
+  cm->BDDQueue = 0;
+  cm->unusedAigQueue = 0;
+  if(interface)
+    cm->nonobjUnitLitArray = interface->nonobjUnitLitArray;
+
+  if(auxObjectArray) {
+    cm->auxObj = sat_ArrayAlloc(auxObjectArray->num+1);
+    size = auxObjectArray->num;
+    for(i=0; i<size; i++) {
+      tv = array_fetch(bAigEdge_t, auxObjectArray, i);
+      if(tv == 1)	continue;
+      else if(tv == 0) {
+        cm->status = SAT_UNSAT;
+        break;
+      }
+      sat_ArrayInsert(cm->auxObj, tv);
+    }
+  }
+  if(object == 0)      cm->status = SAT_UNSAT;
+  else if(object == 1) cm->status = SAT_SAT;
+
+  if(cm->status == 0) {
+    cm->obj = sat_ArrayAlloc(1);
+    sat_ArrayInsert(cm->obj, object);
+
+    /* initialize option */
+    option = sat_InitOption();
+    option->cnfPrefix = bmcOption->cnfPrefix;
+    /*option->verbose = bmcOption->verbosityLevel; */
+    option->verbose = 0;
+    option->timeoutLimit = bmcOption->timeOutPeriod;
+
+    sat_SetIncrementalOption(option, bmcOption->incremental);
+
+    cm->option = option;
+    cm->each = sat_InitStatistics();
+
+    BmcRestoreAssertion(manager, cm);
+    /* value reset.. */
+    sat_CleanDatabase(cm);
+    /* set cone of influence */
+    sat_SetConeOfInfluence(cm);
+    sat_AllocLiteralsDB(cm);
+
+    if(bmcOption->cnfFileName != NIL(char)) {
+      sat_WriteCNF(cm, bmcOption->cnfFileName);
+    }
+    if(bmcOption->clauses == 0){ /* CirCUs circuit*/
+      if (bmcOption->verbosityLevel == BmcVerbosityMax_c) {      
+	fprintf(vis_stdout,
+		"Number of Variables = %d Number of Clauses = %d\n",
+		sat_GetNumberOfInitialVariables(cm),  sat_GetNumberOfInitialClauses(cm));
+      }
+      if (bmcOption->verbosityLevel >= BmcVerbosityMax_c) {
+	(void)fprintf(vis_stdout,"Calling SAT solver (CirCUs) ...");
+	(void) fflush(vis_stdout);
+      }
+      sat_Main(cm);
+      if (bmcOption->verbosityLevel >= BmcVerbosityMax_c) {
+	(void) fprintf(vis_stdout," done ");
+	(void) fprintf(vis_stdout, "(%g s)\n", cm->each->satTime);
+      }
+      
+    } else if(bmcOption->clauses == 1) { /* CirCUs CNF */
+      satArray_t *result;
+      char       *fileName = NIL(char);
+   
+      sat_WriteCNF(cm, bmcOption->satInFile);
+      if(bmcOption->satSolver == cusp){
+	fileName = BmcCirCUsCallCusp(bmcOption);
+      }
+      if(bmcOption->satSolver == CirCUs){
+	fileName = BmcCirCUsCallCirCUs(bmcOption);
+      }
+      if(fileName != NIL(char)){
+	result = sat_ReadForcedAssignment(fileName);
+	d =  sat_AllocLevel(cm);
+        sat_PutAssignmentValueMain(cm, d, result);
+	sat_ArrayFree(result);
+      }
+    }   
+  }
+  sat_CombineStatistics(cm);
+
+  if(interface == 0)
+    interface = ALLOC(satInterface_t, 1);
+
+  interface->total = cm->total;
+  interface->nonobjUnitLitArray = cm->nonobjUnitLitArray;
+  interface->objUnitLitArray = 0;
+  interface->savedConflictClauses = cm->savedConflictClauses;
+  interface->trieArray = cm->trieArray;
+  interface->status = cm->status;
+  cm->total = 0;
+  cm->nonobjUnitLitArray = 0;
+  cm->savedConflictClauses = 0;
+
+  if(cm->maxNodesArraySize > manager->maxNodesArraySize) {
+    manager->maxNodesArraySize = cm->maxNodesArraySize;
+    manager->nameList   = REALLOC(char *, manager->nameList  , manager->maxNodesArraySize/bAigNodeSize);
+    manager->bddIdArray = REALLOC(int ,   manager->bddIdArray  , manager->maxNodesArraySize/bAigNodeSize);
+    manager->bddArray   = REALLOC(bdd_t *, manager->bddArray  , manager->maxNodesArraySize/bAigNodeSize);
+  }
+  manager->NodesArray = cm->nodesArray;
+  manager->literals = cm->literals;
+
+  /* For the case that the input contains CNF clauese; */
+  if(cm->literals)
+    cm->literals->last = cm->literals->initialSize;
+  cm->nodesArray = 0;
+  cm->HashTable = 0;
+  cm->timeframe = 0;
+  cm->timeframeWOI = 0;
+  cm->literals = 0;
+
+  sat_FreeManager(cm);
+
+  return(interface);
+}
+
+/**Function********************************************************************
+
+   Synopsis [ CirCUs interface for bounded model checking.]
+
+   Description [ CirCUs interface for bounded model checking. ]
+
+   SideEffects []
+   
+   SeeAlso     []
+   
+******************************************************************************/
+
+satInterface_t *
+BmcCirCUsInterfaceWithObjArr(
+    bAig_Manager_t *manager,
+    Ntk_Network_t *network,
+    array_t *objectArray,
+    array_t *auxObjectArray,
+    BmcOption_t *bmcOption,
+    satInterface_t *interface)
+{
+satManager_t *cm;
+satOption_t *option;
+int i, size;
+bAigEdge_t tv;
+
+/* allocate sat manager */
+  cm = sat_InitManager(interface);
+  cm->nodesArraySize = manager->nodesArraySize;
+  cm->initNodesArraySize = manager->nodesArraySize;
+  cm->maxNodesArraySize = manager->maxNodesArraySize;
+  cm->nodesArray = manager->NodesArray;
+  cm->HashTable = manager->HashTable;
+  cm->literals = manager->literals;
+  cm->initNumVariables = (manager->nodesArraySize/bAigNodeSize);
+  cm->initNumClauses = 0;
+  cm->initNumLiterals = 0;
+  cm->comment = ALLOC(char, 2);
+  cm->comment[0] = ' ';
+  cm->comment[1] = '\0';
+  cm->stdErr = vis_stderr;
+  cm->stdOut = vis_stdout;
+  cm->status = 0;
+  cm->orderedVariableArray = 0;
+  cm->unitLits = sat_ArrayAlloc(16);
+  cm->pureLits = sat_ArrayAlloc(16);
+  cm->option = 0;
+  cm->each = 0;
+  cm->decisionHead = 0;
+  cm->variableArray = 0;
+  cm->queue = 0;
+  cm->BDDQueue = 0;
+  cm->unusedAigQueue = 0;
+  if(interface)
+    cm->nonobjUnitLitArray = interface->nonobjUnitLitArray;
+
+  if(auxObjectArray) {
+    cm->auxObj = sat_ArrayAlloc(auxObjectArray->num+1);
+    size = auxObjectArray->num;
+    for(i=0; i<size; i++) {
+      tv = array_fetch(bAigEdge_t, auxObjectArray, i);
+      if(tv == 1)	continue;
+      else if(tv == 0) {
+        cm->status = SAT_UNSAT;
+        break;
+      }
+      sat_ArrayInsert(cm->auxObj, tv);
+    }
+  }
+  if(objectArray) {
+    cm->obj = sat_ArrayAlloc(objectArray->num+1);
+    size = objectArray->num;
+    for(i=0; i<size; i++) {
+      tv = array_fetch(bAigEdge_t, objectArray, i);
+      if(tv == 1)	continue;
+      else if(tv == 0) {
+        cm->status = SAT_UNSAT;
+        break;
+      }
+      sat_ArrayInsert(cm->obj, tv);
+    }
+  }
+
+  if(cm->status == 0) {
+    /* initialize option */
+    option = sat_InitOption();
+    option->cnfPrefix = bmcOption->cnfPrefix;
+    /*option->verbose = bmcOption->verbosityLevel; */
+    option->verbose = 0;
+    option->timeoutLimit = bmcOption->timeOutPeriod;
+
+    sat_SetIncrementalOption(option, bmcOption->incremental);
+
+    cm->option = option;
+    cm->each = sat_InitStatistics();
+
+    BmcRestoreAssertion(manager, cm);
+    /* value reset.. */
+    sat_CleanDatabase(cm);
+    /* set cone of influence */
+    sat_SetConeOfInfluence(cm);
+    sat_AllocLiteralsDB(cm);
+
+    if(bmcOption->cnfFileName != NIL(char)) {
+      sat_WriteCNF(cm, bmcOption->cnfFileName);
+    }
+    if(bmcOption->clauses == 0){ /* CirCUs circuit*/
+      if (bmcOption->verbosityLevel == BmcVerbosityMax_c) {      
+	fprintf(vis_stdout,
+		"Number of Variables = %d Number of Clauses = %d\n",
+		sat_GetNumberOfInitialVariables(cm),  sat_GetNumberOfInitialClauses(cm));
+      }
+      if (bmcOption->verbosityLevel >= BmcVerbosityMax_c) {
+	(void)fprintf(vis_stdout,"Calling SAT solver (CirCUs) ...");
+	(void) fflush(vis_stdout);
+      }
+      sat_Main(cm);
+      if (bmcOption->verbosityLevel >= BmcVerbosityMax_c) {
+	(void) fprintf(vis_stdout," done ");
+	(void) fprintf(vis_stdout, "(%g s)\n", cm->each->satTime);
+      }
+    }else if(bmcOption->clauses == 1) { /* CirCUs CNF */
+      satArray_t *result;
+      char       *fileName = NIL(char);
+   
+      sat_WriteCNF(cm, bmcOption->satInFile);
+      if(bmcOption->satSolver == cusp){
+	fileName = BmcCirCUsCallCusp(bmcOption);
+      } else{ 
+	if(bmcOption->satSolver == CirCUs){
+	  fileName = BmcCirCUsCallCirCUs(bmcOption);
+	}
+      }
+      if(fileName != NIL(char)){
+	satLevel_t *d;
+	
+	cm->status = SAT_SAT;
+	result = sat_ReadForcedAssignment(fileName);
+	d =  sat_AllocLevel(cm);
+        sat_PutAssignmentValueMain(cm, d, result);
+	sat_ArrayFree(result);
+      } else {
+	cm->status = SAT_UNSAT;
+      }
+    }
+    /*sat_ReportStatistics(cm, cm->each);*/
+  }
+  sat_CombineStatistics(cm);
+
+  if(interface == 0){
+    interface = ALLOC(satInterface_t, 1);
+  }
+  interface->total = cm->total;
+  interface->nonobjUnitLitArray = cm->nonobjUnitLitArray;
+  interface->objUnitLitArray = 0;
+  interface->savedConflictClauses = cm->savedConflictClauses;
+  interface->trieArray = cm->trieArray;
+  interface->status = cm->status;
+  cm->total = 0;
+  cm->nonobjUnitLitArray = 0;
+  cm->savedConflictClauses = 0;
+
+  if(cm->maxNodesArraySize > manager->maxNodesArraySize) {
+    manager->maxNodesArraySize = cm->maxNodesArraySize;
+    manager->nameList   = REALLOC(char *, manager->nameList  , manager->maxNodesArraySize/bAigNodeSize);
+    manager->bddIdArray = REALLOC(int ,   manager->bddIdArray  , manager->maxNodesArraySize/bAigNodeSize);
+    manager->bddArray   = REALLOC(bdd_t *, manager->bddArray  , manager->maxNodesArraySize/bAigNodeSize);
+  }
+  manager->NodesArray = cm->nodesArray;
+  manager->literals = cm->literals;
+
+  /*
+    For the case that the input contains CNF clauses;
+  */
+  if(cm->literals)
+    cm->literals->last = cm->literals->initialSize;
+  cm->nodesArray = 0;
+  cm->HashTable = 0;
+  cm->timeframe = 0;
+  cm->timeframeWOI = 0;
+  cm->literals = 0;
+
+  sat_FreeManager(cm);
+
+  return(interface);
+}
+
+
+/**Function********************************************************************
+
+   Synopsis [ Create Manager for debug purpose.]
+
+   Description [ Create Manager for debug purpose.]
+
+   SideEffects []
+   
+   SeeAlso     []
+   
+******************************************************************************/
+satManager_t *
+BmcCirCUsCreateManager(
+  Ntk_Network_t *network)
+{
+  satManager_t *cm;
+  bAig_Manager_t *manager;
+  satOption_t *option;
+
+  manager = Ntk_NetworkReadMAigManager(network);
+  /* allocate sat manager*/
+  cm = sat_InitManager(0);
+  cm->nodesArraySize = manager->nodesArraySize;
+  cm->initNodesArraySize = manager->nodesArraySize;
+  cm->maxNodesArraySize = manager->maxNodesArraySize;
+  cm->nodesArray = manager->NodesArray;
+  cm->HashTable = manager->HashTable;
+  cm->literals = manager->literals;
+  cm->initNumVariables = (manager->nodesArraySize/bAigNodeSize);
+  cm->initNumClauses = 0;
+  cm->initNumLiterals = 0;
+  cm->comment = ALLOC(char, 2);
+  cm->comment[0] = ' ';
+  cm->comment[1] = '\0';
+  cm->stdErr = vis_stderr;
+  cm->stdOut = vis_stdout;
+  cm->status = 0;
+  cm->orderedVariableArray = 0;
+  cm->unitLits = sat_ArrayAlloc(16);
+  cm->pureLits = sat_ArrayAlloc(16);
+  cm->option = 0;
+  cm->each = 0;
+  cm->decisionHead = 0;
+  cm->variableArray = 0;
+  cm->queue = 0;
+  cm->BDDQueue = 0;
+  cm->unusedAigQueue = 0;
+
+  if(cm->status == 0) {
+    /* initialize option*/
+    option = sat_InitOption();
+    /*option->verbose = bmcOption->verbosityLevel;*/
+    option->verbose = 0;
+
+    cm->option = option;
+    cm->each = sat_InitStatistics();
+
+    BmcRestoreAssertion(manager, cm);
+    /* value reset..*/
+    sat_CleanDatabase(cm);
+    /* set cone of influence*/
+    sat_SetConeOfInfluence(cm);
+    sat_AllocLiteralsDB(cm);
+
+    /*sat_ReportStatistics(cm, cm->each);*/
+  }
+  sat_CombineStatistics(cm);
+
+  /*
+    For the case that the input contains CNF clauese;
+  */
+  if(cm->literals)
+    cm->literals->last = cm->literals->initialSize;
+
+  return(cm);
+}
+/**Function********************************************************************
+
+   Synopsis [Return a list of AIG in the initialized timeframe corrsponding to
+   the input of all lateches in COI table]
+
+   Description []
+
+   SideEffects []
+   
+   SeeAlso     []
+   
+******************************************************************************/
+
+st_table *
+BmcCirCUsGetCoiIndexTable(
+	Ntk_Network_t *network,
+	st_table *coiTable)
+{
+  mAig_Manager_t  *manager = Ntk_NetworkReadMAigManager(network);
+  Ntk_Node_t   *node;
+  st_generator *gen;
+  int          tmp;
+  st_table     *node2MvfAigTable = 
+    (st_table *)Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+  int mvfSize, index, i;
+  bAigEdge_t         v;
+  MvfAig_Function_t  *mvfAig;
+  st_table           *li2index, *coiIndexTable;
+  
+  assert(manager->timeframe != 0);
+  /*
+    Mohammad Says:
+    This may solve the problem of calling expandTimeframe before calling this
+    function. Check with HoonSang.
+    
+    if(timeframe == 0) 
+    timeframe = bAig_InitTimeFrame(network, manager, 1);
+  */
+  
+  /*
+    li2index stores AIG id for inputs of all latches
+   */
+  li2index = manager->timeframe->li2index;
+  coiIndexTable = st_init_table(st_numcmp, st_numhash);
+
+  st_foreach_item_int(coiTable, gen, &node, &tmp) {
+    if(!Ntk_NodeTestIsLatch(node))	continue;
+    st_lookup(node2MvfAigTable, node, &mvfAig);
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+      if(st_lookup_int(li2index, (char *)v, &index)) 
+        st_insert(coiIndexTable, (char *)(long)index, (char *)(long)index);
+    }
+  }
+  return(coiIndexTable);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Restore aseerted node for SAT solving]
+
+  Description [ Restore aseerted node for SAT solving]
+
+  SideEffects []
+
+  SeeAlso     [bAig_ExpandTimeFrame]
+
+******************************************************************************/
+void
+BmcRestoreAssertion(bAig_Manager_t *manager, satManager_t *cm)
+{
+int size, i, v;
+array_t *asserted;
+
+  if(manager->timeframe && manager->timeframe->assertedArray) {
+    asserted = manager->timeframe->assertedArray;
+    size = asserted->num;
+    cm->assertion = sat_ArrayAlloc(size);
+    for(i=0; i<size; i++) {
+      v = array_fetch(int, asserted, i);
+      sat_ArrayInsert(cm->assertion, v);
+    }
+  }
+  else {
+    cm->assertion = 0;
+  }
+}
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+   Synopsis [Check if the property is TRUE or FALSE]
+
+   Description []
+
+   SideEffects []
+   
+   SeeAlso     []
+   
+******************************************************************************/
+static int
+verifyIfConstant(
+  bAigEdge_t   property)
+{
+
+  if (property == bAig_One){
+    fprintf(vis_stdout,"# BMC: Empty counterexample because the property is always FALSE\n");
+    fprintf(vis_stdout,"# BMC: formula failed\n");
+    return 1;
+  } else if (property == bAig_Zero){
+    fprintf(vis_stdout,"# BMC: The property is always TRUE\n");
+    fprintf(vis_stdout,"# BMC: formula passed\n");
+    return 1;
+  }
+  return 0;
+}
Index: vis_dev/vis-2.3/src/bmc/bmcCirCUsUtil.c
===================================================================
--- vis_dev/vis-2.3/src/bmc/bmcCirCUsUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/bmc/bmcCirCUsUtil.c	(revision 14)
@@ -0,0 +1,1095 @@
+/**CFile***********************************************************************
+
+  FileName    [bmcCirCUsUtil.c]
+
+  PackageName [bmc]
+
+  Synopsis    [Utilities for bmcCirCUs]
+
+  Author      [Mohammad Awedh]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "bmcInt.h"
+#include "sat.h"
+
+static char rcsid[] UNUSED = "$Id: bmcCirCUsUtil.c,v 1.22 2010/04/10 04:07:06 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define MAX_LENGTH 320 /* Max. length of a string while reading a file */
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static char * getBddName(bdd_manager *bddManager, bdd_node *node);
+static bAigEdge_t getAigAtTimeFrame(bAig_Manager_t *manager, bAigEdge_t node, int i, int withInitialState);
+static bAigEdge_t getAigOfBddAtState(Ntk_Network_t *network, bdd_node *node, int state, int withInitialState);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+ Synopsis [Check for termination for safety properties.]
+
+  Description [Check for termination for safety properties.]
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+BmcCirCUsAutLtlCheckTerminalAutomaton(
+  Ntk_Network_t            *network,
+  bAig_Manager_t           *aigManager,
+  st_table                 *nodeToMvfAigTable,
+  BmcCheckForTermination_t *terminationStatus,
+  st_table                 *coiIndexTable,
+  BmcOption_t              *options)
+{
+  long            startTime, endTime;
+  int             k = terminationStatus->k;
+  int             returnStatus = 0;
+  Ltl_Automaton_t *automaton = terminationStatus->automaton;
+  satInterface_t  *tInterface, *etInterface;
+  bAigEdge_t      autPath, property;
+  array_t         *objArray;
+  array_t         *previousResultArray;
+
+  startTime = util_cpu_ctime();
+
+  if (options->verbosityLevel == BmcVerbosityMax_c) {
+    (void) fprintf(vis_stdout, "\nBMC: Check for termination\n");
+  }
+  etInterface = 0;
+  tInterface  = 0;
+    /*
+    Hold objects
+  */
+  objArray = array_alloc(bAigEdge_t, 2);
+  previousResultArray    = array_alloc(bAigEdge_t, 0);
+  returnStatus = 0;
+
+  autPath = BmcCirCUsCreateAigForSimpleCompositePath(network, aigManager, automaton,
+						     0, k+1, nodeToMvfAigTable,
+						     coiIndexTable,
+						     BMC_NO_INITIAL_STATES);
+
+  property = bAig_Not(
+    BmcCirCUsBdd2Aig(network, automaton->fairSets, k, -1,
+		     automaton, aigManager,  BMC_NO_INITIAL_STATES));
+
+  property = bAig_And(aigManager, property,
+		      BmcCirCUsBdd2Aig(network, automaton->fairSets, k+1, -1,
+				       automaton, aigManager,  BMC_NO_INITIAL_STATES));
+  options->cnfPrefix = k+1;
+  array_insert(bAigEdge_t, objArray, 0, property);
+  array_insert(bAigEdge_t, objArray, 1, autPath);
+  tInterface = BmcCirCUsInterfaceWithObjArr(aigManager, network, objArray,
+					    previousResultArray, options, tInterface);
+  if(tInterface->status == SAT_UNSAT){
+     returnStatus = 1;
+  }
+
+  /* ===========================
+     Early termination condition
+     ===========================
+  */
+  if ((options->earlyTermination)&&(returnStatus ==0)) {
+    if (options->verbosityLevel == BmcVerbosityMax_c) {
+      (void) fprintf(vis_stdout, "\nChecking the early termination at k= %d\n", k);
+    }
+
+    autPath = BmcCirCUsCreateAigForSimpleCompositePath(network, aigManager, automaton,
+						       0, k+1, nodeToMvfAigTable,
+						       coiIndexTable,
+						       BMC_INITIAL_STATES);
+    array_insert(bAigEdge_t, objArray, 0, autPath);
+    array_insert(bAigEdge_t, objArray, 1, bAig_One);
+    options->cnfPrefix = k+1;
+    etInterface = BmcCirCUsInterfaceWithObjArr(aigManager, network, objArray,
+					       previousResultArray, options, etInterface);
+
+    if(etInterface->status == SAT_UNSAT){
+      (void) fprintf(vis_stdout, "# BMC: by early termination\n");
+      returnStatus = 1;
+    }
+  } /* Early termination */
+
+  if (options->verbosityLevel != BmcVerbosityNone_c) {
+    endTime = util_cpu_ctime();
+    fprintf(vis_stdout, "-- Check for termination time time = %10g\n",
+	    (double)(endTime - startTime) / 1000.0);
+  }
+  array_free(objArray);
+  array_free(previousResultArray);
+
+  terminationStatus->action = returnStatus;
+
+} /* BmcCirCUsAutLtlCheckTerminalAutomaton */
+
+
+
+/**Function********************************************************************
+
+  Synopsis [Build AIG for a given function in BDD at a given time period]
+
+  Description [Build AIG for a BDD at a time period. If next != -1, then the
+  passed BDD represents a transition relation.]
+
+  SideEffects []
+
+  SeeAlso     [BmcAutEncodeAutomatonStates BmcAutBuildTransitionRelation]
+
+******************************************************************************/
+bAigEdge_t
+BmcCirCUsBdd2Aig(
+  Ntk_Network_t   *network,
+  bdd_t           *function,
+  int             current,
+  int             next,
+  Ltl_Automaton_t *automaton,
+  bAig_Manager_t  *aigManager,
+  int             withInitialState)
+{
+  bdd_manager *bddManager;
+  bdd_node    *node;
+  bdd_gen     *gen;
+
+  array_t     *cube;
+  int         i, value;
+  int         state = current;
+  bAigEdge_t  aigFunction, andFunction, aigNode;
+
+  if (function == NULL){
+    return bAig_NULL;
+  }
+  /*
+    If BDD represents a constant value
+   */
+  if(bdd_is_tautology(function, 0)){
+    return bAig_Zero;
+  }
+  if(bdd_is_tautology(function, 1)){
+    return bAig_One;
+  }
+
+  bddManager = bdd_get_manager(function);
+  aigFunction = bAig_Zero;
+  foreach_bdd_cube(function, gen, cube){
+    andFunction = bAig_One;
+    arrayForEachItem(int, cube, i, value){
+      if (value != 2){
+	int j;
+	/*
+	  If the BDD varaible is a next state varaible, we use the corresponding
+	  current state varaible but with next state index.
+	*/
+	if (next != -1 && st_lookup_int(automaton->nsPsTable, (char *)(long)i, &j)){
+	  node = bdd_bdd_ith_var(bddManager, j);
+	  state = next;
+	} else {
+	  node = bdd_bdd_ith_var(bddManager, i);
+	  state = current;
+	}
+	aigNode = getAigOfBddAtState(network, node, state, withInitialState);
+	if (value == 0){
+	  aigNode = bAig_Not(aigNode);
+	}
+	andFunction = bAig_And(aigManager, andFunction, aigNode);
+      }
+    }
+    aigFunction = bAig_Or(aigManager, aigFunction, andFunction);
+  }/* foreach_bdd_cube */
+
+  return aigFunction;
+} /* BmcCirCUsBdd2Aig */
+
+
+/**Function********************************************************************
+
+  Synopsis [Build AIG for a path in the automaton.]
+
+  Description [Build AIG for a path in the automaton starting from "fromState"
+  and ending at "toState". If "initialState" = BMC_INITIAL_STATES, then the
+  path starts from an initial state.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bAigEdge_t
+BmcCirCUsAutCreateAigForPath(
+  Ntk_Network_t   *network,
+  bAig_Manager_t  *aigManager,
+  Ltl_Automaton_t *automaton,
+  int             fromState,
+  int             toState,
+  int             initialState)
+{
+  int        k;
+  bAigEdge_t result, aigFunction = bAig_One;
+
+  if(initialState){
+    result = BmcCirCUsBdd2Aig(network, automaton->initialStates, 0, -1,
+			      automaton, aigManager, initialState);
+    aigFunction = result;
+  }
+  for(k=fromState; k<toState; k++){
+   result = BmcCirCUsBdd2Aig(network, automaton->transitionRelation, k, k+1,
+			      automaton, aigManager, initialState);
+    aigFunction = bAig_And(aigManager , aigFunction, result);
+  }
+  return aigFunction;
+
+} /* BmcCirCUsAutCreateAigForPath */
+
+/**Function********************************************************************
+
+  Synopsis [Build AIG for a simple path in the automaton.]
+
+  Description [Build AIG a simple path in the automaton starting from
+  "fromState" and ending at "toState". If "initialState" =
+  BMC_INITIAL_STATES, the the path starts from an initial state.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bAigEdge_t
+BmcCirCUsAutCreateAigForSimplePath(
+  Ntk_Network_t   *network,
+  bAig_Manager_t  *aigManager,
+  Ltl_Automaton_t *automaton,
+  int             fromState,
+  int             toState,
+  int             initialState)
+{
+  int        i, j, bddID;
+  bAigEdge_t result, aigFunction, next, current;
+  mdd_manager	     *bddManager = Ntk_NetworkReadMddManager(network);
+  st_generator       *stGen;
+
+  bdd_node           *node;
+
+
+
+  aigFunction = BmcCirCUsAutCreateAigForPath(network, aigManager, automaton,
+					     fromState, toState, initialState);
+  /*
+    The path is simple path
+  */
+  for(i = fromState + 1; i <= toState; i++){
+    for(j=fromState; j < i; j++){
+      result = bAig_Zero;
+      st_foreach_item(automaton->psNsTable, stGen,&bddID, NULL) {
+	node = bdd_bdd_ith_var(bddManager, bddID);
+
+	current = getAigOfBddAtState(network, node, i, initialState);
+	next    = getAigOfBddAtState(network, node, j, initialState);
+
+	result = bAig_Or(aigManager, result,
+			 bAig_Not(bAig_Eq(aigManager, current, next)));
+      }
+      aigFunction = bAig_And(aigManager, aigFunction, result);
+    }
+  }
+
+  return aigFunction;
+
+} /* BmcCirCUsAutCreateAigForSimplePath */
+
+/**Function********************************************************************
+
+  Synopsis [Build AIG for a simple path in the composite model]
+
+  Description [Build AIG a simple path in the composite mode starting from
+  "fromState" and ending at "toState". If "initialState" = BMC_INITIAL_STATES,
+  the the path starts from an initial state.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bAigEdge_t
+BmcCirCUsCreateAigForSimpleCompositePath(
+  Ntk_Network_t   *network,
+  bAig_Manager_t  *aigManager,
+  Ltl_Automaton_t *automaton,
+  int             fromState,
+  int             toState,
+  st_table        *nodeToMvfAigTable,
+  st_table        *coiIndexTable,
+  int             initialState)
+{
+  int        i, j, bddID;
+  bAigEdge_t         result, aigFunction, next, current;
+  mdd_manager	     *bddManager = Ntk_NetworkReadMddManager(network);
+  st_generator       *stGen;
+
+  bdd_node           *node;
+
+
+
+  /*
+    Build a path in the original model
+   */
+  bAig_ExpandTimeFrame(network, aigManager, toState+1, initialState);
+  /*
+    Build a path in the automaton
+   */
+  aigFunction = BmcCirCUsAutCreateAigForPath(network, aigManager, automaton,
+					     fromState, toState, initialState);
+  /*
+    Constrains the two paths to be simple paths
+  */
+  for(i = fromState + 1; i <= toState; i++){
+    for(j=fromState; j < i; j++){
+      result = bAig_Zero;
+
+      /*
+	Unique states in the automaton
+       */
+      st_foreach_item(automaton->psNsTable, stGen, &bddID, NULL) {
+	node = bdd_bdd_ith_var(bddManager, bddID);
+
+	current = BmcCirCUsBdd2Aig(network, bdd_construct_bdd_t(bddManager, node), i, -1,
+				   automaton, aigManager,
+				   initialState);
+	next    = BmcCirCUsBdd2Aig(network, bdd_construct_bdd_t(bddManager,node), j, -1,
+				   automaton, aigManager,
+				   initialState);
+	/*
+	  next    = BmcCirCUsBdd2Aig(network, bdd_construct_bdd_t(bddManager,node), i, j,
+				   automaton, aigManager,
+				   initialState);
+
+	  result = bAig_Or(aigManager, result,
+				   bAig_Not(next));
+	*/
+	result = bAig_Or(aigManager, result,
+			 bAig_Not(bAig_Eq(aigManager, current, next)));
+      }
+      /*
+	Unique states in the original model
+      */
+      result = bAig_Or(aigManager, result,
+		       bAig_Not(BmcCirCUsConnectFromStateToState(network, i-1, j,
+								 nodeToMvfAigTable,
+								 coiIndexTable,
+								 initialState)));
+      aigFunction = bAig_And(aigManager, aigFunction, result);
+    }
+  }
+
+  return aigFunction;
+
+} /* BmcCirCUsCreateAigForSimpleCompositePath */
+
+
+
+/**Function********************************************************************
+
+ Synopsis [Verify the general LTL formula passes by applying the
+   termination criteria that are described in the paper "Proving More
+   Properties with Bounded Model Checking"]
+
+  Description [Check for the termination on the composition of the
+  automaton that describes the negation of the LTL formula and the
+  model.  We apply the termination criteria as described in the paper
+  "Proving More Properties with Bounded Model Checking".]
+
+  Return value:
+	 0 no action
+	 1 (m+n-1) <= options->maxK.  If no counterexample of length up to (m+n-1),
+				      the property passes
+	 2 (m+n-1) >  options->maxK   The property is undecided if no counterexample
+				      of length <= options->maxK.
+	 3 Pass by early termination
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+BmcCirCUsAutLtlCheckForTermination(
+  Ntk_Network_t            *network,
+  bAig_Manager_t           *aigManager,
+  st_table                 *nodeToMvfAigTable,
+  BmcCheckForTermination_t *terminationStatus,
+  st_table                 *coiIndexTable,
+  BmcOption_t              *options)
+{
+  long            startTime, endTime;
+  int             k = terminationStatus->k;
+  int             returnStatus = 0;
+  Ltl_Automaton_t *automaton = terminationStatus->automaton;
+  Ctlsp_Formula_t *externalConstraints = terminationStatus->externalConstraints;
+  satInterface_t  *tInterface, *etInterface;
+  bAigEdge_t      autPath, property, tmp;
+  array_t         *objArray;
+  array_t         *previousResultArray;
+  array_t         *previousResultArrayWOI;
+
+  /*
+    If checkLevel == 0 -->  check for beta' and beta'' only and if either UNSAT, m=k and chekLevel =1
+    If checkLevel == 1 -->  check for beta  only and if UNSAT, checkLevel = 2.
+    If checkLevel == 2 -->  check for alpha only and if UNSAT, n=k and checkLevel = 3.
+    If gama is UNSAT up to (m+n-1) and checkLvel = 3, formula passes.
+    checkLevel = 4 if (m+n-1) > maxK;
+   */
+  startTime = util_cpu_ctime();
+
+  etInterface = 0;
+  tInterface  = 0;
+    /*
+    Hold objects
+  */
+  objArray = array_alloc(bAigEdge_t, 2);
+
+  previousResultArray    = array_alloc(bAigEdge_t, 0);
+  previousResultArrayWOI = array_alloc(bAigEdge_t, 0);
+
+  /* ===========================
+     Early termination condition
+     ===========================
+  */
+  if (options->earlyTermination) {
+    if (options->verbosityLevel == BmcVerbosityMax_c) {
+      (void) fprintf(vis_stdout, "\nChecking the early termination at k= %d\n", k);
+    }
+
+    autPath = BmcCirCUsCreateAigForSimpleCompositePath(network, aigManager, automaton,
+						       0, k, nodeToMvfAigTable,
+						       coiIndexTable,
+						       BMC_INITIAL_STATES);
+    array_insert(bAigEdge_t, objArray, 0, autPath);
+    array_insert(bAigEdge_t, objArray, 1, bAig_One);
+    options->cnfPrefix = k;
+    etInterface = BmcCirCUsInterfaceWithObjArr(aigManager, network, objArray,
+				     previousResultArray, options, etInterface);
+
+    if(etInterface->status == SAT_UNSAT){
+      (void) fprintf(vis_stdout, "# BMC: by early termination\n");
+      terminationStatus->action = 3;
+      return;
+    }
+  } /* Early termination */
+  if((!automaton->fairSets) &&
+     (terminationStatus->checkLevel == 0)) {
+    /*
+      All the automaton states are fair states. So, beta' and beta are always UNSAT.
+    */
+    terminationStatus->m = 0;
+    printf("Value of m = %d\n", terminationStatus->m);
+    terminationStatus->checkLevel = 2;
+  }
+
+   /*
+    Check \beta''(k)
+  */
+  if(terminationStatus->checkLevel == 0){
+    int i;
+
+    if (options->verbosityLevel == BmcVerbosityMax_c) {
+      (void) fprintf(vis_stdout, "# BMC: Check Beta''\n");
+    }
+    autPath = BmcCirCUsCreateAigForSimpleCompositePath(network, aigManager, automaton,
+						       0, k+1, nodeToMvfAigTable,
+						       coiIndexTable, BMC_NO_INITIAL_STATES);
+    property = bAig_One;
+    for(i=1; i<=k+1; i++){
+      tmp = BmcCirCUsBdd2Aig(network, automaton->fairSets, i, -1,
+			     automaton, aigManager,
+			     BMC_NO_INITIAL_STATES);
+
+      if(externalConstraints){
+	tmp = bAig_Or(aigManager, tmp,
+		      BmcCirCUsCreatebAigOfPropFormula(network, aigManager, i,
+						       externalConstraints,
+						       BMC_NO_INITIAL_STATES));
+      }
+      property = bAig_And(aigManager, property, bAig_Not(tmp));
+    }
+
+    tmp = BmcCirCUsBdd2Aig(network, automaton->fairSets, 0, -1,
+			   automaton, aigManager,  BMC_NO_INITIAL_STATES);
+    if(externalConstraints){
+      tmp = bAig_Or(aigManager, tmp,
+		    BmcCirCUsCreatebAigOfPropFormula(network, aigManager, 0,
+						     externalConstraints,
+						     BMC_NO_INITIAL_STATES));
+    }
+    property = bAig_And(aigManager, property, tmp);
+
+    options->cnfPrefix = k+1;
+    array_insert(bAigEdge_t, objArray, 0, property);
+    array_insert(bAigEdge_t, objArray, 1, autPath);
+    tInterface = BmcCirCUsInterfaceWithObjArr(aigManager, network, objArray,
+				    previousResultArray, options, tInterface);
+    if(tInterface->status == SAT_UNSAT){
+      terminationStatus->m = k;
+      (void)fprintf(vis_stderr,"m = %d\n", terminationStatus->m);
+      terminationStatus->checkLevel = 1;
+    }
+  } /* Check for Beta'' */
+
+  /*
+    Check \beta'(k)
+  */
+  if(terminationStatus->checkLevel == 0){
+    int i;
+
+    if (options->verbosityLevel == BmcVerbosityMax_c) {
+      (void) fprintf(vis_stdout, "# BMC: Check Beta'\n");
+    }
+    autPath = BmcCirCUsCreateAigForSimpleCompositePath(network, aigManager, automaton,
+						       0, k+1, nodeToMvfAigTable,
+						       coiIndexTable, BMC_NO_INITIAL_STATES);
+    property = bAig_One;
+    for(i=0; i<=k; i++){
+      tmp = BmcCirCUsBdd2Aig(network, automaton->fairSets, i, -1,
+			     automaton, aigManager,
+			     BMC_NO_INITIAL_STATES);
+      if(externalConstraints){
+	tmp = bAig_Or(aigManager, tmp,
+		      BmcCirCUsCreatebAigOfPropFormula(network, aigManager, i,
+						       externalConstraints,
+						       BMC_NO_INITIAL_STATES));
+      }
+      property = bAig_And(aigManager, property, bAig_Not(tmp));
+    }
+    tmp = BmcCirCUsBdd2Aig(network, automaton->fairSets, k+1, -1,
+			   automaton, aigManager,
+			   BMC_NO_INITIAL_STATES);
+    if(externalConstraints){
+      tmp = bAig_Or(aigManager, tmp,
+		    BmcCirCUsCreatebAigOfPropFormula(network, aigManager, k+1,
+						     externalConstraints,
+						     BMC_NO_INITIAL_STATES));
+    }
+    property = bAig_And(aigManager, property, tmp);
+
+    options->cnfPrefix = k+1;
+    array_insert(bAigEdge_t, objArray, 0, property);
+    array_insert(bAigEdge_t, objArray, 1, autPath);
+    tInterface = BmcCirCUsInterfaceWithObjArr(aigManager, network, objArray,
+				    previousResultArray, options, tInterface);
+    if(tInterface->status == SAT_UNSAT){
+      terminationStatus->m = k;
+      (void)fprintf(vis_stderr,"m = %d\n", terminationStatus->m);
+      terminationStatus->checkLevel = 1;
+    }
+  } /* Check for Beta' */
+
+  /*
+    Check for Beta.
+  */
+  if(terminationStatus->checkLevel == 1){
+
+    if (options->verbosityLevel == BmcVerbosityMax_c) {
+      (void) fprintf(vis_stdout, "# BMC: Check Beta\n");
+    }
+    autPath = BmcCirCUsCreateAigForSimpleCompositePath(network, aigManager, automaton,
+						       0, k+1, nodeToMvfAigTable,
+						       coiIndexTable, BMC_NO_INITIAL_STATES);
+    property = bAig_One;
+
+    tmp = BmcCirCUsBdd2Aig(network, automaton->fairSets, k, -1,
+			   automaton, aigManager,  BMC_NO_INITIAL_STATES);
+
+    if(externalConstraints){
+      tmp = bAig_Or(aigManager, tmp,
+		    BmcCirCUsCreatebAigOfPropFormula(network, aigManager, k,
+						     externalConstraints,
+						     BMC_NO_INITIAL_STATES));
+    }
+    property = bAig_And(aigManager, property, bAig_Not(tmp));
+
+    tmp = BmcCirCUsBdd2Aig(network, automaton->fairSets, k+1, -1,
+			   automaton, aigManager,  BMC_NO_INITIAL_STATES);
+    if(externalConstraints){
+      tmp = bAig_Or(aigManager, tmp,
+		    BmcCirCUsCreatebAigOfPropFormula(network, aigManager, k+1,
+						     externalConstraints,
+						     BMC_NO_INITIAL_STATES));
+    }
+    property = bAig_And(aigManager, property, tmp);
+
+    options->cnfPrefix = k+1;
+    array_insert(bAigEdge_t, objArray, 0, property);
+    array_insert(bAigEdge_t, objArray, 1, autPath);
+    tInterface = BmcCirCUsInterfaceWithObjArr(aigManager, network, objArray,
+				    previousResultArray, options, tInterface);
+    if(tInterface->status == SAT_UNSAT){
+      terminationStatus->checkLevel = 2;
+    }
+  } /* Check Beta*/
+
+  if(terminationStatus->checkLevel == 2){ /* we check Alpha if Beta is unsatisfiable */
+
+    if (options->verbosityLevel == BmcVerbosityMax_c) {
+      (void) fprintf(vis_stdout, "# BMC: Check Alpha \n");
+    }
+    autPath = BmcCirCUsCreateAigForSimpleCompositePath(network, aigManager, automaton,
+						       0, k, nodeToMvfAigTable,
+						       coiIndexTable,
+						       BMC_INITIAL_STATES);
+    array_insert(bAigEdge_t, objArray, 1, bAig_One);
+    property = bAig_Zero;
+    if(automaton->fairSets){
+      property =  BmcCirCUsBdd2Aig(network, automaton->fairSets, k, -1,
+				   automaton, aigManager,  BMC_INITIAL_STATES);
+      array_insert(bAigEdge_t, objArray, 1, property);
+    }
+    if(externalConstraints){
+      property = bAig_Or(aigManager, property,
+			 BmcCirCUsCreatebAigOfPropFormula(network, aigManager, k,
+							  externalConstraints,
+							  BMC_INITIAL_STATES));
+      array_insert(bAigEdge_t, objArray, 1, property);
+    }
+    options->cnfPrefix = k;
+    array_insert(bAigEdge_t, objArray, 0, autPath);
+    tInterface = 0;
+    tInterface = BmcCirCUsInterfaceWithObjArr(aigManager, network,
+					      objArray, previousResultArray,
+					      options, tInterface);
+    if(tInterface->status == SAT_UNSAT){
+      terminationStatus->n = k;
+      terminationStatus->checkLevel = 3;
+      (void)fprintf(vis_stdout,"Value of m=%d  n=%d\n",terminationStatus->m,terminationStatus->n);
+      if ((terminationStatus->m+terminationStatus->n-1) <= options->maxK){
+	terminationStatus->k = terminationStatus->m+terminationStatus->n-1;
+	if(k==0){
+	  /*
+	    By induction, the property passes.
+	   */
+	  terminationStatus->k = 0;
+	}
+	returnStatus = 1;
+      } else {
+	terminationStatus->checkLevel = 4;
+	returnStatus = 2;
+      }
+    }
+  }/* Chek for Alpha */
+
+  if (options->verbosityLevel != BmcVerbosityNone_c) {
+    endTime = util_cpu_ctime();
+    fprintf(vis_stdout, "-- Check for termination time time = %10g\n",
+	    (double)(endTime - startTime) / 1000.0);
+  }
+
+  terminationStatus->action = returnStatus;
+
+} /* BmcAutLtlCheckForTermination */
+
+
+/**Function********************************************************************
+
+  Synopsis [Call CirCUs SAT solver on a CNF file]
+
+  Description [Call CirCUs SAT solver on a CNF file. We use CirCUs as
+  CNF SAT solver.  The function returns a file name that contains the
+  assignment if the set of clauses are satisfiable.
+  ]
+
+  SideEffects []
+
+******************************************************************************/
+char *
+BmcCirCUsCallCirCUs(
+  BmcOption_t *options)
+{
+  satOption_t  *satOption;
+  satManager_t *cm;
+  int          maxSize;
+  char         *fileName = NIL(char);
+
+  satOption          = sat_InitOption();
+  satOption->verbose = options->verbosityLevel-1;
+
+  cm = sat_InitManager(0);
+  cm->comment = ALLOC(char, 2);
+  cm->comment[0] = ' ';
+  cm->comment[1] = '\0';
+  cm->stdOut = stdout;
+  cm->stdErr = stderr;
+
+  cm->option = satOption;
+  cm->each = sat_InitStatistics();
+
+  cm->unitLits = sat_ArrayAlloc(16);
+  cm->pureLits = sat_ArrayAlloc(16);
+
+  maxSize = 10000 << 8;
+  cm->nodesArray = ALLOC(bAigEdge_t, maxSize);
+  cm->maxNodesArraySize = maxSize;
+  cm->nodesArraySize = satNodeSize;
+
+  sat_AllocLiteralsDB(cm);
+
+  sat_ReadCNF(cm, options->satInFile);
+
+  if (options->verbosityLevel == BmcVerbosityMax_c) {
+    (void)fprintf(vis_stdout,"Calling SAT solver (CirCUs) ...");
+    (void) fflush(vis_stdout);
+  }
+  sat_Main(cm);
+  if (options->verbosityLevel == BmcVerbosityMax_c) {
+    (void) fprintf(vis_stdout," done ");
+    (void) fprintf(vis_stdout, "(%g s)\n", cm->each->satTime);
+  }
+  if(cm->status == SAT_UNSAT) {
+    if (options->verbosityLevel != BmcVerbosityNone_c){
+      (void) fprintf(vis_stdout, "# SAT: Counterexample not found\n");
+
+    }
+    fflush(cm->stdOut);
+  } else if(cm->status == SAT_SAT) {
+    if (options->verbosityLevel != BmcVerbosityNone_c){
+      (void) fprintf(vis_stdout, "# SAT: Counterexample found\n");
+    }
+    if (options->verbosityLevel > BmcVerbosityMax_c){
+      sat_ReportStatistics(cm, cm->each);
+    }
+
+    if(!(cm->stdOut = fopen(options->satOutFile, "w"))) {
+      fprintf(stdout, "ERROR : Can't open file %s\n", options->satOutFile);
+      cm->stdOut = stdout;
+      cm->stdErr = stderr;
+    }
+    sat_PrintSatisfyingAssignment(cm);
+    fileName = options->satOutFile;
+  }
+  sat_FreeManager(cm);
+
+  return fileName;
+} /* BmcCallCirCUs */
+
+/**Function********************************************************************
+
+  Synopsis [Check the satisfiability of CNF formula written in file]
+
+  Description [Run external solver on a CNF file. The function returns
+  a file name that contains the assignment if the set of clauses are
+  satisfiable.]
+
+  SideEffects []
+
+******************************************************************************/
+char *
+BmcCirCUsCallCusp(BmcOption_t *options)
+{
+  FILE        *fp;
+  static char parseBuffer[1024];
+  int         satStatus;
+  char        line[MAX_LENGTH];
+  int         num = 0;
+  array_t     *result = NIL(array_t);
+  char        *tmpStr, *tmpStr1, *tmpStr2;
+  long        solverStart;
+  int         satTimeOutPeriod = 0;
+  char        *fileName = NIL(char);
+
+  /*
+    Prepare to call external CNF SAT solver
+   */
+  strcpy(parseBuffer,"cusp -distill -velim -cnf ");
+  options->satSolverError = FALSE;  /* assume no error */
+  if (options->timeOutPeriod > 0) {
+    /* Compute the residual CPU time and subtract a little time to
+       give vis a chance to clean up before its own time out expires.
+    */
+    satTimeOutPeriod = options->timeOutPeriod - 1 -
+      (util_cpu_ctime() - options->startTime) / 1000;
+    if (satTimeOutPeriod <= 0){ /* no time left to run SAT solver */
+      options->satSolverError=TRUE;
+      return NIL(char);
+    }
+    tmpStr2 = util_inttostr(satTimeOutPeriod);
+    tmpStr1 = util_strcat3(options->satInFile," -t ", tmpStr2);
+    tmpStr = util_strcat3(tmpStr1, " >", options->satOutFile);
+    FREE(tmpStr1);
+    FREE(tmpStr2);
+  } else {
+    tmpStr = util_strcat3(options->satInFile, " >", options->satOutFile);
+  }
+  strcat(parseBuffer, tmpStr);
+  FREE(tmpStr);
+
+  if (options->verbosityLevel == BmcVerbosityMax_c) {
+    (void)fprintf(vis_stdout,"Calling SAT solver (cusp) ...");
+    (void) fflush(vis_stdout);
+    solverStart = util_cpu_ctime();
+  } else { /* to remove uninitialized variables warning */
+    solverStart = 0;
+  }
+  /* Call Sat Solver */
+  satStatus = system(parseBuffer);
+  if (satStatus != 0){
+    (void) fprintf(vis_stderr, "Can't run external sat solver.  It may not be in your path.  Status = %d\n", satStatus);
+    options->satSolverError = TRUE;
+    return NIL(char);
+  }
+
+  if (options->verbosityLevel == BmcVerbosityMax_c) {
+    (void) fprintf(vis_stdout," done ");
+    (void) fprintf(vis_stdout, "(%g s)\n",
+		   (double) (util_cpu_ctime() - solverStart)/1000.0);
+  }
+  fp = Cmd_FileOpen(options->satOutFile, "r", NIL(char *), 0);
+  if (fp == NIL(FILE)) {
+    (void) fprintf(vis_stderr, "** bmc error: Cannot open the file %s\n",
+		   options->satOutFile);
+    options->satSolverError = TRUE;
+    return NIL(char);
+  }
+  /* Skip the lines until the result */
+  while(1) {
+    if (fgets(line, MAX_LENGTH - 1, fp) == NULL) break;
+    if(strstr(line,"UNSATISFIABLE") ||
+       strstr(line,"SATISFIABLE") ||
+       strstr(line,"MEMOUT") ||
+       strstr(line,"TIMEOUT"))
+      break;
+  }
+
+  if(strstr(line,"UNSATISFIABLE") != NIL(char)) {
+    if (options->verbosityLevel != BmcVerbosityNone_c){
+      (void) fprintf(vis_stdout, "# SAT: Counterexample not found\n");
+
+    }
+  } else if(strstr(line,"SATISFIABLE") != NIL(char)) {
+    if (options->verbosityLevel != BmcVerbosityNone_c){
+      (void) fprintf(vis_stdout, "# SAT: Counterexample found\n");
+    }
+    /* Skip the initial v of the result line */
+    result = array_alloc(int, 0);
+    while (fgets(line, MAX_LENGTH - 1, fp) != NULL) {
+      char *word;
+      if (line[0] != 'v') {
+	(void) fprintf(vis_stderr,
+		       "** bmc error: Cannot find assignment in file %s\n",
+		       options->satOutFile);
+	options->satSolverError = TRUE;
+	return NIL(char);
+      }
+      word = strtok(&(line[1])," \n");
+      while (word != NIL(char)) {
+	num = atoi(word);
+	if (num == 0) break;
+	array_insert_last(int, result, num);
+	word = strtok(NIL(char)," \n");
+      }
+      if (num == 0) break;
+    }
+    (void) fclose(fp);
+    fp = Cmd_FileOpen(options->satOutFile, "w", NIL(char *), 0);
+    for(num=0; num < array_n(result); num++){
+      fprintf(fp,"%d ", array_fetch(int, result, num));
+      if(((num+1) %10) == 0){
+	fprintf(fp,"\n");
+      }
+    }
+    array_free(result);
+    (void) fclose(fp);
+    fileName = options->satOutFile;
+  } else if(strstr(line,"MEMOUT") != NIL(char)) {
+    (void) fprintf(vis_stdout,"# SAT: SAT Solver Memory out\n");
+    options->satSolverError = TRUE;
+  } else if(strstr(line,"TIMEOUT") != NIL(char)) {
+    (void) fprintf(vis_stdout,
+		   "# SAT: SAT Solver Time out occurred after %d seconds.\n",
+		   satTimeOutPeriod);
+    options->satSolverError = TRUE;
+  } else {
+    (void) fprintf(vis_stdout, "# SAT: SAT Solver failed, try again\n");
+    options->satSolverError = TRUE;
+  }
+  (void) fflush(vis_stdout);
+
+  return fileName;
+} /* BmcCirCUsCallCusp */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [retun the name of bdd node]
+
+  Description [return the name of bdd node. If the bdd is for a
+  multi-valued variable, then its name will be the name of the
+  multi-valued variable concatenated with its index. It is the user
+  responsibility to free the returned name]
+
+  SideEffects []
+
+******************************************************************************/
+static char *
+getBddName(
+  bdd_manager *bddManager,
+  bdd_node *node)
+{
+  array_t   *mvar_list  = mdd_ret_mvar_list(bddManager);
+  array_t   *bvar_list  = mdd_ret_bvar_list(bddManager);
+  char      name[100];
+  bvar_type bv;
+  mvar_type mv;
+  int       nodeIndex = bdd_node_read_index(node);
+  int       index, rtnNodeIndex;
+
+  /*
+    If the node is for a multi-valued varaible.
+  */
+  if (nodeIndex < array_n(bvar_list)){
+    bv = array_fetch(bvar_type, bvar_list, nodeIndex);
+    /*
+      get the multi-valued varaible.
+    */
+    mv = array_fetch(mvar_type, mvar_list, bv.mvar_id);
+    arrayForEachItem(int, mv.bvars, index, rtnNodeIndex) {
+      if (nodeIndex == rtnNodeIndex){
+	break;
+      }
+    }
+    assert(index < mv.encode_length);
+    sprintf(name, "%s_%d", mv.name, index);
+  } else {
+    sprintf(name, "Bdd_%d", nodeIndex);
+  }
+  return util_strsav(name);
+}
+
+/**Function********************************************************************
+
+  Synopsis []
+
+  Description []
+
+  SideEffects []
+
+******************************************************************************/
+static bAigEdge_t
+getAigAtTimeFrame(
+  bAig_Manager_t *manager,
+  bAigEdge_t node,
+  int        i,
+  int withInitialState)
+{
+  bAigTimeFrame_t *timeframe;
+  bAigEdge_t     result, *li;
+  int            index;
+
+  result = bAig_NULL;
+
+  if(withInitialState) timeframe = manager->timeframe;
+  else	               timeframe = manager->timeframeWOI;
+
+  if(st_lookup_int(timeframe->li2index, (char *)node, &index)) {
+    li = timeframe->latchInputs[i];
+    result = bAig_GetCanonical(manager, li[index]);
+  }
+  else if(st_lookup_int(timeframe->o2index, (char *)node, &index)) {
+    li = timeframe->outputs[i];
+    result = bAig_GetCanonical(manager, li[index]);
+  }
+  else if(st_lookup_int(timeframe->i2index, (char *)node, &index)) {
+    li = timeframe->internals[i];
+    result = bAig_GetCanonical(manager, li[index]);
+  }
+  else if(st_lookup_int(timeframe->bli2index, (char *)node, &index)) {
+    li = timeframe->blatchInputs[i];
+    result = bAig_GetCanonical(manager, li[index]);
+  }
+  else if(st_lookup_int(timeframe->bpi2index, (char *)node, &index)) {
+    li = timeframe->binputs[i];
+    result = bAig_GetCanonical(manager, li[index]);
+  }
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Get the AIG node corresponding to a BDD node at a given state]
+
+  Description [We use BDD name to get the corresponding AIG node.  If no AIG node
+  exists, we create one]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static bAigEdge_t
+getAigOfBddAtState(
+  Ntk_Network_t   *network,
+  bdd_node        *node,
+  int             state,
+  int             withInitialState)
+{
+  mdd_manager	   *bddManager = Ntk_NetworkReadMddManager(network);
+  mAig_Manager_t   *aigManager = Ntk_NetworkReadMAigManager(network);
+
+  char        *nodeName, *nameKey;
+  char        tmpName[100];
+  bAigEdge_t  aigNode, rtnAig;
+
+  nodeName = getBddName(bddManager, bdd_regular(node));
+  aigNode  = bAig_FindNodeByName(aigManager, nodeName);
+  if(aigNode == bAig_NULL){
+    sprintf(tmpName, "%s_%d_%d", nodeName, withInitialState, state);
+    nameKey = util_strsav(tmpName);
+    aigNode  = bAig_FindNodeByName(aigManager, nameKey);
+    if(aigNode == bAig_NULL){
+      aigNode = bAig_CreateVarNode(aigManager, nameKey);
+    } else {
+      FREE(nameKey);
+    }
+    rtnAig = aigNode;
+  } else {
+    aigNode = bAig_GetCanonical(aigManager, aigNode);
+    rtnAig  = getAigAtTimeFrame(aigManager, aigNode, state, withInitialState);
+    if(rtnAig == bAig_NULL){
+      rtnAig = bAig_CreateNode(aigManager, bAig_NULL, bAig_NULL);
+    }
+  }
+  return bAig_GetCanonical(aigManager, rtnAig);
+} /* getAigOfBddAtState */
Index: vis_dev/vis-2.3/src/bmc/bmcCmd.c
===================================================================
--- vis_dev/vis-2.3/src/bmc/bmcCmd.c	(revision 14)
+++ vis_dev/vis-2.3/src/bmc/bmcCmd.c	(revision 14)
@@ -0,0 +1,1268 @@
+/**CFile***********************************************************************
+
+  FileName    [bmcCmd.c]
+
+  PackageName [bmc]
+
+  Synopsis    [Command interface for bounded model checking (bmc)]
+
+  Author      [Mohammad Awedh]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+******************************************************************************/
+
+#include "bmcInt.h"
+
+static char rcsid[] UNUSED = "$Id: bmcCmd.c,v 1.83 2010/04/09 23:50:57 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+static jmp_buf timeOutEnv;
+static int bmcTimeOut;		/* timeout value */
+static long alarmLapTime;	/* starting CPU time for timeout */
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static BmcOption_t * ParseBmcOptions(int argc, char **argv);
+static int CommandBmc(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static void TimeOutHandle(void);
+static void DispatchBmcCommand(Ntk_Network_t *network, Ctlsp_Formula_t *ltlFormula, array_t *constraintArray, BmcOption_t *options);
+static int CommandCnfSat(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the BMC package.]
+
+  SideEffects []
+
+  SeeAlso     [Bmc_End]
+
+******************************************************************************/
+void
+Bmc_Init(void)
+{
+  Cmd_CommandAdd("bounded_model_check", CommandBmc, /* doesn't change network */  0);
+  
+  Cmd_CommandAdd("cnf_sat", CommandCnfSat, /* doesn't change network */  0); 
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Ends BMC package.]
+
+  SideEffects []
+
+  SeeAlso     [Bmc_Init]
+
+******************************************************************************/
+void
+Bmc_End(void)
+{
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Parse the user input for command "bmc".]
+
+  Description []
+
+  SideEffects []
+
+******************************************************************************/
+static BmcOption_t *
+ParseBmcOptions(
+  int argc,
+  char **argv)
+{
+  BmcOption_t  *options = BmcOptionAlloc();
+  char *ltlFileName     = NIL(char);
+  unsigned int i;
+  int          c;
+  
+  if (!options){
+    return NIL(BmcOption_t);
+  }
+  
+  options->dbgOut = 0;
+  /*
+   * Parse command line options.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "E:C:S:F:O::I:hiv:m:k:s:o:t:d:r:e")) != EOF) {
+    switch(c) {
+    case 'F':
+      options->fairFile = Cmd_FileOpen(util_optarg, "r", NIL(char *), 0);
+      if (options->fairFile == NIL(FILE)) {
+	(void) fprintf(vis_stdout,
+		       "** bmc error: Cannot open the file %s\n",
+		       util_optarg);
+	BmcOptionFree(options);
+	return NIL(BmcOption_t);
+      }
+      break;
+    case 'O':
+      options->dbgOut = Cmd_FileOpen(util_optarg, "w", NIL(char *), 0);
+      if(options->dbgOut == NIL(FILE)) {
+        (void) fprintf(vis_stdout, "**bmc error: Cannot open %s for debug information.\n", util_optarg);
+         BmcOptionFree(options);
+         return NIL(BmcOption_t);
+      } 
+      break;
+    case 'm':
+      for (i = 0; i < strlen(util_optarg); i++) {
+	if (!isdigit((int)util_optarg[i])) {
+	  goto usage;
+	}
+      }
+      options->minK = atoi(util_optarg);
+      break;
+    case 'k':
+      for (i = 0; i < strlen(util_optarg); i++) {
+	if (!isdigit((int)util_optarg[i])) {
+	  goto usage;
+	}
+      }
+      options->maxK = atoi(util_optarg);
+      break;
+    case 's':
+      for (i = 0; i < strlen(util_optarg); i++) {
+	if (!isdigit((int)util_optarg[i])) {
+	  goto usage;
+	}
+      }
+      options->step = atoi(util_optarg);
+      break;
+    case 'r':
+      for (i = 0; i < strlen(util_optarg); i++) {
+	if (!isdigit((int)util_optarg[i])) {
+	  goto usage;
+	}
+      }
+      options->inductiveStep = atoi(util_optarg);
+      break;
+    case 'e':
+      options->earlyTermination = TRUE;
+      break;	
+    case 'd':
+      for (i = 0; i < strlen(util_optarg); i++) {
+	if (!isdigit((int)util_optarg[i])) {
+	  goto usage;
+	}
+      }
+      options->dbgLevel = atoi(util_optarg);
+      break;	
+    case 't' :
+      options->timeOutPeriod = atoi(util_optarg);
+	break;
+    case 'i':
+      options->printInputs = TRUE;
+      break;	
+    case 'h':
+      goto usage;
+    case 'v':
+      for (i = 0; i < strlen(util_optarg); i++) {
+	if (!isdigit((int)util_optarg[i])) {
+	  goto usage;
+	}
+      }
+      options->verbosityLevel = (Bmc_VerbosityLevel) atoi(util_optarg);
+      break;
+    case 'o':
+      options->cnfFileName = util_strsav(util_optarg);
+      break;	
+    case 'I' :
+      options->incremental = atoi(util_optarg);
+      break;
+    case 'E':
+      for (i = 0; i < strlen(util_optarg); i++) {
+	if (!isdigit((int)util_optarg[i])) {
+	  goto usage;
+	}
+      }
+      options->encoding = atoi(util_optarg);
+      if((options->encoding < 0) || (options->encoding > 2)){
+	goto usage;
+      }
+      break;
+    case 'S':
+      for (i = 0; i < strlen(util_optarg); i++) {
+	if (!isdigit((int)util_optarg[i])) {
+	  goto usage;
+	}
+      }
+      options->satSolver = atoi(util_optarg);
+      if((options->satSolver < 0) || (options->satSolver > 1)){
+	goto usage;
+      }
+      break;
+    case 'C':
+      for (i = 0; i < strlen(util_optarg); i++) {
+	if (!isdigit((int)util_optarg[i])) {
+	  goto usage;
+	}
+      }
+      options->clauses = atoi(util_optarg);
+      if((options->clauses < 0) || (options->clauses > 2)){
+	goto usage;
+      }
+      break;
+    default:
+      goto usage;
+    }
+  }
+  if (options->minK > options->maxK){
+    (void) fprintf(vis_stderr, "** bmc error: value for -m option must not be greater than vlaue for -k option\n");    
+    goto usage;
+  }
+  /*
+   * Open the ltl file.
+   */
+  if (argc - util_optind == 0) {
+    (void) fprintf(vis_stderr, "** bmc error: file containing ltl formulae not provided\n");
+    goto usage;
+  }
+  else if (argc - util_optind > 1) {
+    (void) fprintf(vis_stderr, "** bmc error: too many arguments\n");
+    goto usage;
+  }
+  ltlFileName = util_strsav(argv[util_optind]);
+  
+  /* Read LTL Formulae */
+  if (!ltlFileName) 
+      goto usage;
+
+  options->ltlFile = Cmd_FileOpen(ltlFileName, "r", NIL(char *), 0);
+  if (options->ltlFile == NIL(FILE)) {
+    (void) fprintf(vis_stdout,"** bmc error: Cannot open the file %s\n", ltlFileName);
+    FREE(ltlFileName);
+    BmcOptionFree(options);
+    return NIL(BmcOption_t);
+  }
+  FREE(ltlFileName);
+  /* create SAT Solver input file */
+  if (options->cnfFileName == NIL(char)) {
+    options->satInFile = BmcCreateTmpFile(); 
+    if (options->satInFile == NIL(char)){
+      BmcOptionFree(options);
+      return NIL(BmcOption_t);
+    }
+  } else {
+    options->satInFile = options->cnfFileName;
+  }
+  /* create SAT Solver output file */
+  options->satOutFile = BmcCreateTmpFile();
+  if (options->satOutFile == NIL(char)){
+    BmcOptionFree(options);
+    return NIL(BmcOption_t);
+  }
+  return options;
+  
+ usage:
+  (void) fprintf(vis_stderr, "usage: bmc [-h][-m minimum_length][-k maximum_length][-s step][-r inductive_step][-e][-F <fairness_file>][-d debug_level][-E <encoding>][-C <clauses>][-S <sat_solver>][-O <debug_file>][-I <level>][-v verbosity_level][-t period][-o <cnf_file>] <ltl_file>\n");
+  (void) fprintf(vis_stderr, "   -h \tprint the command usage\n");
+  (void) fprintf(vis_stderr, "   -m \tminimum length of counterexample to be checked (default is 0)\n");  
+  (void) fprintf(vis_stderr, "   -k \tmaximum length of counterexample to be checked (default is 1)\n");
+  (void) fprintf(vis_stderr, "   -s \tincrementing value of counterexample length (default is 1)\n");
+  (void) fprintf(vis_stderr, "   -r \tUse check for termination at each inductive_step to check if the property passes (default is 0).\n");
+  (void) fprintf(vis_stderr, "   -e \tUse early termination to check if the property passes. Valid only with -r \n"); 
+  (void) fprintf(vis_stderr, "   -F <fairness_file>\n");
+  (void) fprintf(vis_stderr, "   -d <debug_level>\n");
+  (void) fprintf(vis_stderr, "       debug_level = 0 => No debugging performed (Default)\n");
+  (void) fprintf(vis_stderr, "       debug_level = 1 => Debugging with minimal output: generate counter-example if the LTL formula fails.\n");
+  (void) fprintf(vis_stderr, "       debug_level = 2 => Debugging with full output in Aiger format: generate counter-example if the LTL formula fails.\n");
+  (void) fprintf(vis_stderr, "   -O <debug_file>\n");
+  (void) fprintf(vis_stderr, "   -i \tPrint input values in debug traces.\n");
+  (void) fprintf(vis_stderr, "   -v <verbosity_level>\n");
+  (void) fprintf(vis_stderr, "       verbosity_level = 0 => no feedback (Default)\n");
+  (void) fprintf(vis_stderr, "       verbosity_level = 1 => code status\n");
+  (void) fprintf(vis_stderr, "       verbosity_level = 2 => code status and CPU usage profile\n");
+  (void) fprintf(vis_stderr, "   -t <period> time out period\n");
+  (void) fprintf(vis_stderr, "   -E <encoding>\n");
+  (void) fprintf(vis_stderr, "       encoding = 0 => Original BMC encoding (Default)\n");
+  (void) fprintf(vis_stderr, "       encoding = 1 => SNF encoding\n");
+  (void) fprintf(vis_stderr, "       encoding = 2 => Fixpoint encoding\n");
+  /*
+  (void) fprintf(vis_stderr, "       encoding = 3 => FNF encoding\n");
+  */
+  (void) fprintf(vis_stderr, "   -S <sat_solver>\n");
+  (void) fprintf(vis_stderr, "       sat_solver = 0 => CirCUs (Default)\n");
+  (void) fprintf(vis_stderr, "       sat_solver = 1 => cusp\n");
+  (void) fprintf(vis_stderr, "   -C <clauses>\n");
+  (void) fprintf(vis_stderr, "       clauses = 0 => Apply CirCUs on circuit (Default)\n");
+  (void) fprintf(vis_stderr, "       clauses = 1 => Apply SAT solver on CNF (new)\n");
+  (void) fprintf(vis_stderr, "       clauses = 2 => Apply SAT solver on CNF (old)\n");
+  (void) fprintf(vis_stderr, "   -I <level>\n");
+  (void) fprintf(vis_stderr, "       level = 1 => Trace Objective\n");
+  (void) fprintf(vis_stderr, "       level = 2 => Distill\n");
+  (void) fprintf(vis_stderr, "       level = 3 => Trace Objective + Distill\n");
+  (void) fprintf(vis_stderr, "   -o <cnf_file> contains CNF of the counterexample\n");
+  (void) fprintf(vis_stderr, "   <ltl_file> The input file containing LTL formulae to be checked.\n");
+
+  BmcOptionFree(options);
+  return NIL(BmcOption_t);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Alloc Memory for BmcOption_t.]
+
+  SideEffects []
+
+  SeeAlso []
+******************************************************************************/
+BmcOption_t *
+BmcOptionAlloc(void)
+{
+  BmcOption_t *result = ALLOC(BmcOption_t, 1);
+  
+  if (!result){
+    return result;
+  }
+  result->ltlFile = NIL(FILE);
+  result->fairFile = NIL(FILE);
+  result->cnfFileName = NIL(char);
+  result->minK = 0;
+  result->maxK = 1;
+  result->step = 1;
+  result->timeOutPeriod  = 0;
+  result->startTime = 0;
+  result->verbosityLevel = BmcVerbosityNone_c;
+  result->dbgLevel       = 0;
+  result->inductiveStep  = 0;
+  result->printInputs    = FALSE;
+  result->satSolverError = FALSE;
+  result->satInFile  = NIL(char);
+  result->satOutFile = NIL(char);
+  result->incremental = 0;
+  result->earlyTermination = 0;
+  result->satSolver = CirCUs;  /* default is 0 */
+  result->clauses   = 0;  /* default is 0 */
+  result->encoding  = 0;  /* default is 0 */
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Free BmcOption_t, and close files.]
+
+  SideEffects []
+
+  SeeAlso []
+******************************************************************************/
+void
+BmcOptionFree(
+  BmcOption_t *result)
+{
+  if (result->ltlFile != NIL(FILE)){
+    fclose(result->ltlFile);
+  }
+  if (result->cnfFileName != NIL(char)){
+    FREE(result->cnfFileName);
+  } else if (result->satInFile != NIL(char)) {
+    unlink(result->satInFile);
+    FREE(result->satInFile);
+  }
+  if (result->fairFile != NIL(FILE)){
+    fclose(result->fairFile);
+  }
+  if (result->satOutFile != NIL(char)) {
+    unlink(result->satOutFile);
+    FREE(result->satOutFile);
+  }
+  FREE(result);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Create a temporary file]
+
+  Description []
+
+  SideEffects []
+
+******************************************************************************/
+char *
+BmcCreateTmpFile(void)
+{
+#if HAVE_MKSTEMP && HAVE_CLOSE  
+  char   cnfFileName[] = "/tmp/vis.XXXXXX";
+  int    fd;
+#else
+  char   *cnfFileName;
+  char   buffer[512];
+#endif
+
+#if HAVE_MKSTEMP && HAVE_CLOSE    
+  fd = mkstemp(cnfFileName);
+  if (fd == -1){
+#else
+  cnfFileName = util_strsav(tmpnam(buffer));
+  if (cnfFileName == NIL(char)){
+#endif       
+    (void)fprintf(vis_stderr,"** bmc error: Can not create temporary file. ");
+    (void)fprintf(vis_stderr,"Clean up /tmp and try again.\n");
+    return NIL(char);
+  }
+#if HAVE_MKSTEMP && HAVE_CLOSE
+  close(fd);
+#endif   
+  return util_strsav(cnfFileName);
+} /* createTmpFile() */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the bounded_model_check command]
+
+  CommandName [bounded_model_check]
+
+  CommandSynopsis [Performs a SAT-based LTL model checking on a flattened network]
+
+  CommandArguments [\[-h\] \[-v &lt;verbosity_level&gt;\]
+                    \[-m &lt;minimum_length&gt;\] \[-k &lt;maximum_length&gt;\] \[-s &lt;step_value&gt;\]
+		    \[-r &lt;termination_check_step&gt;\] \[-e\]
+		    \[-F &lt;fairness_file&gt;\]
+		    \[-S &lt;sat_solver&gt;\] \[-E &lt;encoding&gt;\]
+		    \[-C &lt;clause_type&gt;\] \[-I &lt;inc_level&gt;\]
+		    \[-d &lt;dbg_level&gt;\] \[-t &lt;timeOutPeriod&gt;\]
+		    \[-o &lt;cnf_file&gt;\] \[-i\]
+		    \[-O &lt;debug_file&gt;\] &lt;ltl_file&gt; ]
+		    
+  CommandDescription [Performs a SAT-based LTL bounded model checking (BMC) on
+  a flattened network. This command looks for a counterexample of length <code>
+  k </code> ( minimum_length &le; <code> k </code> &le; maximum_length). If
+  <code> -r </code> is specified, this command performs check for termination
+  after each <code> termination_check_step </code>.  If no counterexample is
+  found, this command increases <code> k </code> by step_value (specifies by
+  the <code> -s </code> option) until a counterexample is found, the search
+  becomes intractable (timed out), or <code> k </code> reaches a bound
+  (determine by the check for termination), and then we conclude that the LTL
+  property passes.
+
+  This command implements the basic encoding of Bounded Model Checking (BMC) as
+  descibed in the paper "Symbolic Model Checking without BDDs".  However, the
+  <code> -E </code> option can be used to select other encoding scheme.  We
+  also applied some of the improvements in the BMC encoding described in the
+  paper "Improving the Encoding of LTL Model Checking into SAT".
+  
+  To prove that an LTL property passes, we implement the termination methods
+  that are descirebed in the papers "Checking Safety Properties Using Induction
+  and a SAT-Solver" and "Proving More Properties with Bounded Model Checking".
+  
+  Before calling this command, the user should have initialized the design by
+  calling the command <A HREF="flatten_hierarchyCmd.html"> <code>
+  flatten_hierarchy</code></A>. If the user uses the -r option and the LTL
+  property is a general LTL property, the command <A
+  HREF="build_partition_maigsCmd.html"> <code> build_partition_maigs</code></A>
+  must be called.  The aig graph must be built by calling the command <A
+  HREF="build_partition_mddsCmd.html"> <code>build_partition_mdds</code></A>
+  <p>
+  
+  Command options:
+  <p>
+  <dl>
+  <dt> -h
+  <dd> Print the command usage.
+  
+  <p>
+  <dt>-m <code>&lt;minimum_length&gt;</code>
+  <dd>Minimum length of counterexample to be checked (default is 0). 
+
+  <dt>-k <code>&lt;maximum_length&gt;</code>
+  <dd>Maximum length of counterexample to be checked (default is 1).
+
+  <dt>-s <code>&lt;step_value&gt;</code>
+  <dd>Incrementing value of counterexample length (default is 1).
+
+  <dt>-r <code>&lt;termination_check_step&gt;</code>
+  <dd>Check for termination for each termination_check_step (default is 0). 0 means don't check for termination.
+
+  <dt>-e
+  <dd> Activate early termination check.  Check if there is no simple path starts from an initial state.
+       Valid only for general LTL and safety properties. Must be used with -r option.
+  
+  <dt>-S <code>&lt;sat_solver&gt;</code>
+  <dd> Specify SAT solver
+  <br><code>sat_solver</code>  must be one of the following:<p>
+  <code>0</code>: CirCUs (Default) <p>
+  <code>1</code>: zChaff <p>
+
+  <dt>-E <code>&lt;encoding&gt;</code>
+  <dd> Specify encoding scheme
+  <br><code>encoding</code>  must be one of the following:<p>
+  <code>0</code>: The original BMC encoding (Default) <p>
+  <code>1</code>: SNF encoding <p>
+  <code>2</code>: Fixpoint encoding <p>
+
+  <dt>-C <code>&lt;clause_type&gt;</code>
+  <dd> Specify clause type
+  <br><code>encoding</code>  must be one of the following:<p>
+  <code>0</code>: Apply CirCUs SAT solver on circuit (Default) <p>
+  <code>1</code>: Apply SAT solver on CNF generated form circuit<p>
+  <code>2</code>: Apply SAT solver on CNF <p>
+
+  <dt>-I <code>&lt;inc_level&gt;</code>
+  <dd> Specify increment sat solver type
+  <br><code>encoding</code>  must be one of the following:<p>
+  <code>1</code>: Trace Objective (Default) <p>
+  <code>2</code>: Distill <p>
+  <code>3</code>: Trace Objective + Distill <p>
+
+  <dt>-F <code>&lt;fairness_file&gt;</code>
+  <dd> Read fairness constraints from <code>&lt;fairness_file&gt;</code>.  Each
+  formula in the file is a condition that must hold infinitely often on a fair
+  path.
+  
+  <dt>-o <code>&lt;cnf_file&gt;</code>
+  Save CNF formula in <code>&lt;cnf_file&gt;</code>
+
+  <dt>-O <code>&lt;debug_file&gt;</code>
+  Save counterexample to <code>&lt;debug_file&gt;</code>
+  
+  <dt> -t  <code>&lt;timeOutPeriod&gt;</code>
+  <dd> Specify the time out period (in seconds) after which the command aborts. By default this option is set to infinity.
+  <p>
+  <dt> -v  <code>&lt;verbosity_level&gt;</code>
+  <dd> Specify verbosity level. This sets the amount of feedback  on CPU usage and code status.
+
+  <br><code>verbosity_level</code>  must be one of the following:<p>
+  
+  <code>0</code>: No feedback provided. This is the default.<p>
+
+  <code>1</code>: Feedback on code location.<p>
+
+  <code>2</code>: Feedback on code location and CPU usage.<p>
+
+  <dt> -d <code> &lt;dbg_level&gt; </code> <dd> Specify the amount of
+  debugging performed when the BMC models check the LTL formula. 
+  <p> <dd> <code> dbg_level</code> must be one
+  of the following:
+
+  <p><code>0</code>: No debugging performed.
+  <code>dbg_level</code>=<code>0</code> is the default.
+
+  <p><code>1</code>: Debugging with minimal output: generate counter-example
+  if the LTL formula fails and the counterexample length.
+
+  <p>
+  <dt> -i
+  <dd> Print input values causing transitions between states during debugging.
+  <p>
+  
+  <dt> <code> &lt;ltl_file&gt; </code>
+  <dd> File containing LTL formulae to be checked.
+  
+  </dl>
+  ]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkAddApplInfo]
+
+******************************************************************************/
+static int
+CommandBmc(
+  Hrc_Manager_t ** hmgr,
+  int              argc,
+  char          ** argv)
+{
+  Ntk_Network_t     *network;
+  BmcOption_t       *options;
+  int               i;
+  array_t           *formulaArray;
+  array_t           *LTLformulaArray;
+  bAig_Manager_t    *manager;
+  array_t           *constraintArray = NIL(array_t);
+
+  /*
+   * Parse command line options.
+   */
+  if ((options = ParseBmcOptions(argc, argv)) == NIL(BmcOption_t)) {
+      return 1;
+  }
+  /*
+   * Read the network
+   */
+  network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+  if (network == NIL(Ntk_Network_t)) {
+    (void) fprintf(vis_stdout, "** bmc error: No network\n");
+    BmcOptionFree(options);
+    return 1;
+  }
+  manager = Ntk_NetworkReadMAigManager(network);
+  if (manager == NIL(mAig_Manager_t)) {
+    (void) fprintf(vis_stdout, "** bmc error: run build_partition_maigs command first\n");
+    BmcOptionFree(options);
+    return 1;
+  }
+  /*
+    We need the bdd when building the transition relation of the automaton
+  */
+  if(options->inductiveStep !=0){
+    Fsm_Fsm_t *designFsm = NIL(Fsm_Fsm_t);
+ 
+    designFsm = Fsm_HrcManagerReadCurrentFsm(*hmgr);
+    if (designFsm == NIL(Fsm_Fsm_t)) {
+      return 1;
+    }
+  }
+  /* time out */
+  if (options->timeOutPeriod > 0) {
+    /* Set the static variables used by the signal handler. */
+    bmcTimeOut = options->timeOutPeriod;
+    alarmLapTime = options->startTime = util_cpu_ctime();
+    (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
+    (void) alarm(options->timeOutPeriod);
+    if (setjmp(timeOutEnv) > 0) {
+      (void) fprintf(vis_stdout,
+		     "\n# BMC: timeout occurred after %d seconds.\n",
+		     options->timeOutPeriod);
+      (void) fprintf(vis_stdout, "# BMC: data may be corrupted.\n");
+      BmcOptionFree(options);
+      alarm(0);
+      return 1;
+    }
+  }
+  formulaArray  = Ctlsp_FileParseFormulaArray(options->ltlFile);
+  if (formulaArray == NIL(array_t)) {
+    (void) fprintf(vis_stderr,
+		   "** bmc error: error in parsing CTL* Fromula from file\n");
+    BmcOptionFree(options);
+    return 1;
+  }
+  if (array_n(formulaArray) == 0) {
+    (void) fprintf(vis_stderr, "** bmc error: No formula in file\n");
+    BmcOptionFree(options);
+    Ctlsp_FormulaArrayFree(formulaArray);
+    return 1;
+  }
+  LTLformulaArray = Ctlsp_FormulaArrayConvertToLTL(formulaArray);
+  Ctlsp_FormulaArrayFree(formulaArray);
+  if (LTLformulaArray ==  NIL(array_t)){
+    (void) fprintf(vis_stdout, "** bmc error: Invalid LTL formula\n");
+    BmcOptionFree(options);
+    return 1;
+  }
+  if (options->fairFile != NIL(FILE)) {
+    constraintArray = BmcReadFairnessConstraints(options->fairFile);
+    if(constraintArray == NIL(array_t)){
+      Ctlsp_FormulaArrayFree(LTLformulaArray);
+      BmcOptionFree(options);
+      return 1;
+    }
+    if(!Ctlsp_LtlFormulaArrayIsPropositional(constraintArray)){
+      Ctlsp_FormulaArrayAddLtlFairnessConstraints(LTLformulaArray,
+						  constraintArray);
+      Ctlsp_FormulaArrayFree(constraintArray);
+      constraintArray = NIL(array_t);
+    }
+  }
+  /*
+    Call a proper BMC function based on LTL formula.
+  */
+  for (i = 0; i < array_n(LTLformulaArray); i++) { 
+    Ctlsp_Formula_t *ltlFormula     = array_fetch(Ctlsp_Formula_t *,
+						  LTLformulaArray, i);
+    
+    DispatchBmcCommand(network, ltlFormula, constraintArray, options);
+  }
+  /*
+    Free used memeory
+  */
+  if (constraintArray != NIL(array_t)){
+    Ctlsp_FormulaArrayFree(constraintArray);
+  }
+  Ctlsp_FormulaArrayFree(LTLformulaArray);
+  BmcOptionFree(options);
+  fflush(vis_stdout);
+  fflush(vis_stderr);
+  alarm(0);
+  return 0;
+
+}/* CommandBmc() */
+
+/**Function********************************************************************
+
+  Synopsis    [Handle function for timeout.]
+
+  Description [This function is called when the time out occurs.
+  Since alarm is set with an elapsed time, this function checks if the
+  CPU time corresponds to the timeout of the command.  If not, it
+  reprograms the alarm to fire again later.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+TimeOutHandle(void)
+{
+  int seconds = (int) ((util_cpu_ctime() - alarmLapTime) / 1000);
+
+  if (seconds < bmcTimeOut) {
+    unsigned slack = (unsigned) (bmcTimeOut - seconds);
+    (void) signal(SIGALRM, (void(*)(int)) TimeOutHandle);
+    (void) alarm(slack);
+  } else {
+    longjmp(timeOutEnv, 1);
+  }
+} /* TimeOutHandle */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Dispatch BMC]
+
+  Description [Call a proper BMC routine.
+
+  The -E for BMC encoding scheme
+      -C clause generation 
+      -S SAT solver   0  CirCUs
+                      1 zChaff
+
+  ]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+DispatchBmcCommand(
+  Ntk_Network_t   *network,
+  Ctlsp_Formula_t *ltlFormula,
+  array_t         *constraintArray,
+  BmcOption_t     *options)
+{
+  Ctlsp_Formula_t *negLtlFormula = Ctlsp_LtllFormulaNegate(ltlFormula);
+  st_table        *CoiTable      = st_init_table(st_ptrcmp, st_ptrhash);
+
+  assert(ltlFormula != NIL(Ctlsp_Formula_t));
+  assert(network != NIL(Ntk_Network_t));
+ 
+  /*
+    print out the given LTL formula
+  */
+  fprintf(vis_stdout, "Formula: ");
+  Ctlsp_FormulaPrint(vis_stdout, ltlFormula);
+  fprintf(vis_stdout, "\n");
+  if (options->verbosityLevel >= BmcVerbosityMax_c){
+    fprintf(vis_stdout, "Negated formula: ");
+    Ctlsp_FormulaPrint(vis_stdout, negLtlFormula);
+    fprintf(vis_stdout, "\n");
+  }
+  /*
+    Compute the cone of influence of the LTL formula
+  */
+  BmcGetCoiForLtlFormula(network, negLtlFormula, CoiTable);
+
+  if(options->clauses == 2){
+    /*
+      Generate clauses for each time frame.  This is the old way of generating
+      clauses in BMC.
+    */
+    if (constraintArray != NIL(array_t)){
+      BmcLtlVerifyGeneralLtl(network, negLtlFormula, CoiTable,
+			     constraintArray, options);
+    } else /*
+	     If the LTL formula is propositional.
+	   */
+      if(Ctlsp_isPropositionalFormula(negLtlFormula)){
+	BmcLtlVerifyProp(network, negLtlFormula, CoiTable, options);
+      } else /*
+	       If the LTL formula is of type G(p) (its negation is
+	       of type F(q)), where p and q are propositional.
+	     */
+	if(Ctlsp_LtlFormulaIsFp(negLtlFormula)){
+	  BmcLtlVerifyGp(network, negLtlFormula, CoiTable, options);
+	} else /*
+		 If the LTL formula is of type F(p) (its negation is
+		 of type G(q)), where p and q are propositional.
+	       */
+	  if (Ctlsp_LtlFormulaIsGp(negLtlFormula)){
+	    BmcLtlVerifyFp(network, negLtlFormula, CoiTable, options);
+	  } else /*
+		   If the depth of the LTL formula (the maximum level
+		   of nesting temporal operators) = 1
+		 */
+	    /*
+	    if (Ctlsp_LtlFormulaDepth(negLtlFormula) == 1){
+	      BmcLtlVerifyUnitDepth(network, negLtlFormula, CoiTable, options);
+	    } else
+	    */
+	      /* 
+		 If the LTL formula is of type FG(p) (its negation is
+		 of type GF(q)), where p and q are propositional.
+	      */
+	      if(Ctlsp_LtlFormulaIsGFp(negLtlFormula)){
+		BmcLtlVerifyFGp(network, negLtlFormula, CoiTable, options);
+	      } else
+		/*
+		  All other LTL formulae
+		*/
+		BmcLtlVerifyGeneralLtl(network, negLtlFormula, CoiTable,
+				       NIL(array_t), options);
+  } else {
+    /*
+     Build AIG for each time frame.
+     */
+    if (constraintArray != NIL(array_t)){
+      if(options->encoding == 0){
+       BmcCirCUsLtlVerifyGeneralLtl(network, negLtlFormula,
+				    CoiTable,
+				   constraintArray, options, 0);
+      } else 
+	if(options->encoding == 1){
+	  BmcCirCUsLtlVerifyGeneralLtl(network, negLtlFormula,
+					  CoiTable,
+					  constraintArray, options, 1);
+	} else 
+	  if(options->encoding == 2){
+	    BmcCirCUsLtlVerifyGeneralLtlFixPoint(network, negLtlFormula,
+						 CoiTable,
+						 constraintArray, options);
+	  }
+    } else
+      /*
+	If the LTL formula is propositional.
+      */
+      if(Ctlsp_isPropositionalFormula(negLtlFormula)){
+	BmcCirCUsLtlVerifyProp(network, negLtlFormula, CoiTable, options);
+      } else
+	/*
+	  If the LTL formula is of type G(p) (its negation is
+	  of type F(q)), where p and q are propositional.
+	*/
+	if(Ctlsp_LtlFormulaIsFp(negLtlFormula)){
+	  BmcCirCUsLtlVerifyGp(network, negLtlFormula, CoiTable, options);
+	} else
+	  /*
+	    If the LTL formula is of type F(p) (its negation is
+	    of type G(q)), where p and q are propositional.
+	  */
+	  if (Ctlsp_LtlFormulaIsGp(negLtlFormula)){
+	    BmcCirCUsLtlVerifyFp(network, negLtlFormula, CoiTable, options);
+	  } else
+	    /*
+	      If the depth of the LTL formula (the maximum level
+	      of nesting temporal operators) = 1
+	      
+	      if (Ctlsp_LtlFormulaDepth(negLtlFormula) == 1){
+	      BmcLtlVerifyUnitDepth(network, negLtlFormula, CoiTable, options);
+	      } else
+	       
+	      If the LTL formula is of type FG(p) (its negation is
+	      of type GF(q)), where p and q are propositional.
+	    */
+	    if(Ctlsp_LtlFormulaIsGFp(negLtlFormula)){
+	      BmcCirCUsLtlVerifyFGp(network, negLtlFormula, CoiTable, options);
+	    } else
+	      if(Ctlsp_LtlFormulaTestIsSyntacticallyCoSafe(negLtlFormula) ||
+	      	 (Ltl_AutomatonGetStrength(BmcAutLtlToAutomaton(network,ltlFormula)) == 0))
+		{
+		  BmcCirCUsLtlCheckSafety(network, negLtlFormula, options, CoiTable);
+		}
+	      else {
+		/*
+		  All other LTL formulae
+		*/
+		if(options->encoding == 0){
+		  BmcCirCUsLtlVerifyGeneralLtl(network, negLtlFormula,
+					       CoiTable,
+					       NIL(array_t), options, 0);
+		} else 
+		  if(options->encoding == 1){
+		    BmcCirCUsLtlVerifyGeneralLtl(network, negLtlFormula,
+						    CoiTable,
+						    NIL(array_t), options, 1);
+		  } else 
+		    if(options->encoding == 2){
+		      BmcCirCUsLtlVerifyGeneralLtlFixPoint(network, negLtlFormula,
+						 CoiTable,
+							   NIL(array_t), options);
+		    }
+	      } 
+  }
+  
+  st_free_table(CoiTable);
+  Ctlsp_FormulaFree(negLtlFormula);
+} /* DispatchBmcCommand() */
+
+
+/**Function********************************************************************
+
+  Synopsis    [cnf_sat]
+
+  Description []
+  
+  CommandName [cnf_sat]
+
+  CommandSynopsis [Perform SAT solving with CNF input]
+
+  CommandArguments [\[-h\] \[-a &lt;assgined_filename&gt;\]
+                    \[-f &lt;output_filename&gt;\] 
+		    \[-t &lt;timeout&gt;\] 
+		    \[-v &lt;verbose&gt;\] 
+		    \[-b\] &lt;cnf_filename&gt; ]
+		    
+
+  CommandDescription [Perform SAT solving with CirCUs after reading CNF file
+  <p>
+  <dt> -b
+
+  <dd> If the given CNF has small number of variables and clause then
+  the BDD is built from the CNF clauses. If the monolithic BDD is built
+  then we can conclude SAT or UNSAT, otherwise the normal SAT algorithm
+  is invoked.
+
+  <p>
+  <p>
+  <dt> -t  <code>&lt;timeOutPeriod&gt;</code>
+
+  <dd> Specify the time out period (in seconds) after which the command
+  aborts. By default this option is set to infinity.
+
+  <p>
+
+  <p>
+  <dt> -f  <code>&lt;output_filename&gt;</code>
+  <dd> Specify the output filename to save the satisfying assignments and 
+  the statistics of SAT solving.
+  <p>
+
+  ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+static int
+CommandCnfSat(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  satOption_t *option;
+  char *filename, c;
+  char *forcedAssignFilename;
+  int timeOutPeriod, i;
+
+  option = sat_InitOption();
+  timeOutPeriod = -1;
+  forcedAssignFilename = 0;
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "a:bf:ht:v:c:")) != EOF) {
+    switch(c) {
+      case 'h':
+	goto usage;
+      case 'b' :
+        option->BDDMonolithic = 1;
+	break;
+      case 'f' :
+	option->outFilename = strdup(util_optarg);
+	break;
+      case 'a' :
+	forcedAssignFilename = strdup(util_optarg);
+	break;
+      case 't' :
+	timeOutPeriod = atoi(util_optarg);
+	break;
+      case 'v':
+	for (i = 0; i < (int)(strlen(util_optarg)); i++) {
+	  if (!isdigit((int)util_optarg[i])) {
+	    goto usage;
+	  }
+	}
+	option->verbose = (Bmc_VerbosityLevel) atoi(util_optarg);
+	break;
+
+	//Bing: for unsat core
+      case 'c':
+	option->coreGeneration = 1;
+	option->unsatCoreFileName = strdup(util_optarg);
+	option->minimizeConflictClause = 0;
+	option->clauseDeletionHeuristic = 0;
+	break;
+      default:
+	goto usage;
+    }
+  }
+
+  if (argc - util_optind == 0) {
+    (void) fprintf(vis_stderr, "** ERROR : file containing cnf file not provided\n");
+    goto usage;
+  }
+  else if (argc - util_optind > 1) {
+    (void) fprintf(vis_stderr, "** ERROR : too many arguments\n");
+    goto usage;
+  }
+  filename = util_strsav(argv[util_optind]);
+
+  if(forcedAssignFilename)
+    option->forcedAssignArr = sat_ReadForcedAssignment(forcedAssignFilename);
+
+  if (timeOutPeriod > 0) {
+    bmcTimeOut = timeOutPeriod;
+    alarmLapTime = util_cpu_ctime();
+    (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
+    (void) alarm(timeOutPeriod);
+    if (setjmp(timeOutEnv) > 0) {
+      (void) fprintf(vis_stderr,
+		"** ERROR : timeout occurred after %d seconds.\n", timeOutPeriod);
+      alarm(0);
+      return 1;
+    }
+  }
+
+  sat_CNFMain(option, filename);
+
+  return 0;
+
+  usage:
+  (void) fprintf(vis_stderr, "usage: cnf_sat [-h] [-v verboseLevel] [-t timeout] <cnf_file>\n");
+  (void) fprintf(vis_stderr, "   -h \tprint the command usage\n");
+  (void) fprintf(vis_stderr, "   -a <filename> \tto make forced assignment\n");
+  (void) fprintf(vis_stderr, "   -f <filename> \twrite log to the file\n");
+  (void) fprintf(vis_stderr, "   -b \tuse BDD based method\n");
+  (void) fprintf(vis_stderr, "   -v <verbosity_level>\n");
+  (void) fprintf(vis_stderr, "   -t <period> time out period\n");
+  (void) fprintf(vis_stderr, "   -c <filename> UNSAT core generation\n");
+  (void) fprintf(vis_stderr, "   <cnf_file> CNF file to be checked.\n");
+  return 1;
+}
+
+
+#if 0
+/**Function********************************************************************
+
+  Synopsis    [Implements the bdd_sat command.]
+
+  Description [This command integrates BDD-based methods with SAT-based method
+  to model safety property of the form AG(p). Where p is either a propositional
+  formula or a path formula consists of only the temporal operator X.]
+  
+  CommandName [bdd_sat_bounded_model_check]
+
+  CommandSynopsis [performs an LTL bounded model checking on a flattened network]
+
+  CommandArguments [\[-h\] \[-v &lt;verbosity_level&gt;\]  \[-d &lt;dbg_level&gt;\] \[-i\] 
+                    -m &lt;minimum_length&gt; -k &lt;maximum_length&gt; -s &lt;step_value&gt;
+		    -o &lt;cnf_file&gt; &lt;ltl_file&gt; ]
+
+		    -F &lt;fairness_file&gt; -o &lt;cnf_file&gt; &lt;ltl_file&gt; ]
+
+  CommandDescription [Performs an LTL bounded model checking on a flattened
+  network. This command looks for a counterexample of length &ge; minimum_length
+  and &le; maximum_length. It increments the length by step_value. 
+  
+  Before calling this command, the user should have initialized the design
+  by calling the command <A HREF="flatten_hierarchyCmd.html"> <code>
+  flatten_hierarchy</code></A>, and
+  then calling the command <A HREF="build_partition_maigsCmd.html"> <code>
+  build_partition_maigs</code></A>.<p>
+  The value of maximum length must be >= minimum length.<p>
+
+  Command options:
+  <p>
+
+  <dl>
+
+  <dt> -h
+  <dd> Print the command usage.
+  <p>
+
+  <dt>-m <code>&lt;minimum_length&gt;</code>
+  <dd>Minimum length of counterexample to be checked (default is 0). 
+
+  <dt>-k <code>&lt;maximum_length&gt;</code>
+  <dd>Maximum length of counterexample to be checked (default is 1).
+
+  <dt>-s <code>&lt;step_value&gt;</code>
+  <dd>Incrementing value of counterexample length (default is 1).
+
+  <dt>-r <code>&lt;inductive_Step&gt;</code>
+  <dd>Use inductive proof at each step_value to check if the property passes (default is 0). 0 means
+  don't use the inductive proof. BMC will check using the indcution if the property passes if the current
+  length of the counterexample is a multiple of inductive_Step.
+  
+  <dt>-F <code>&lt;fairness_file&gt;</code>
+  <dd> Read fairness constraints from <code>&lt;fairness_file&gt;</code>.  Each
+  formula in the file is a condition that must hold infinitely often on a fair
+  path.
+
+  <dt>-o <code>&lt;cnf_file&gt;</code>
+  Save the CNF formula in <code>&lt;cnf_file&gt;</code>
+  
+  <dt> -t  <code>&lt;timeOutPeriod&gt;</code>
+  <dd> Specify the time out period (in seconds) after which the command aborts. By default this option is set to infinity.
+  <p>
+  <dt> -v  <code>&lt;verbosity_level&gt;</code>
+  <dd> Specify verbosity level. This sets the amount of feedback  on CPU usage and code status.
+
+  <br><code>verbosity_level</code>  must be one of the following:<p>
+  
+  <code>0</code>: No feedback provided. This is the default.<p>
+
+  <code>1</code>: Feedback on code location.<p>
+
+  <code>2</code>: Feedback on code location and CPU usage.<p>
+
+  <dt> -d <code> &lt;dbg_level&gt; </code> <dd> Specify the amount of
+  debugging performed when the BMC models check the LTL formula. 
+  <p> <dd> <code> dbg_level</code> must be one
+  of the following:
+
+  <p><code>0</code>: No debugging performed.
+  <code>dbg_level</code>=<code>0</code> is the default.
+
+  <p><code>1</code>: Debugging with minimal output: generate counter-example
+  if the LTL formula fails and the counterexample length.
+
+  <p>
+  
+  <dt> -h
+  <dd> Print the command usage.
+  <p>
+
+  <dt> -i
+  <dd> Print input values causing transitions between states during debugging.
+  <p>
+
+  <dt> -o <code>&lt;cnf_file&gt</code>;
+  <dd> File containing CNF of the counterexample if exist. If specifies, the
+  user can exam this file looking for information about the generated path.
+  This file will be the input to the SAT solver.  The contents of this file
+  is in dimacs format.
+  
+  <dt> <code> &lt;ltl_file&gt; </code>
+  <dd> File containing LTL formulas to be model checked.
+  
+  </dl>
+  ]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkAddApplInfo]
+
+******************************************************************************/ 
+int
+CommandBddSat(
+  Hrc_Manager_t ** hmgr,
+  int              argc,
+  char          ** argv)
+{
+  Ntk_Network_t     *network;
+  BmcOption_t       *options;
+  array_t           *formulaArray;
+  bAig_Manager_t    *mAigManager;
+  Fsm_Fsm_t         *fsm;
+  mdd_manager       *mddManager;
+  int               startTime;
+
+
+  /*
+   * Parse command line options.
+   */
+  if ((options = ParseBmcOptions(argc, argv)) == NIL(BmcOption_t)) {
+      return 1;
+  }
+  /* Read the network */
+  network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+  if (network == NIL(Ntk_Network_t)) {
+    (void) fprintf(vis_stdout, "** bdd_sat error: No network\n");
+    BmcOptionFree(options);
+    return 1;
+  }
+  /* read fsm */
+  fsm = Fsm_NetworkReadOrCreateFsm(network);
+  if (fsm == NIL(Fsm_Fsm_t)) {
+    (void) fprintf(vis_stdout, "** bdd_sat error: Can't read or create fsm\n");
+    BmcOptionFree(options);
+    return 1;
+  }
+  mddManager = Fsm_FsmReadMddManager(fsm); /* mdd manager */
+  
+  mAigManager = Ntk_NetworkReadMAigManager(network);
+  if (mAigManager == NIL(mAig_Manager_t)) {
+    (void) fprintf(vis_stdout, "** bdd_sat error: run build_partition_maigs command first\n");
+    BmcOptionFree(options);
+    return 1;
+  }
+  formulaArray = Ctlsp_FileParseFormulaArray(options->ltlFile);
+  if (formulaArray == NIL(array_t)) {
+    (void) fprintf(vis_stderr,
+		   "** bdd_sat error: Error in parsing CTL* Fromula from file\n");
+    BmcOptionFree(options);
+    return 1;
+  }
+  if (array_n(formulaArray) == 0) {
+    (void) fprintf(vis_stderr, "** bdd_sat error: No formula in file\n");
+    BmcOptionFree(options);
+    array_free(formulaArray);
+    return 1;
+  }
+  /* time out */
+  if (options->timeOutPeriod > 0) {
+    /* Set the static variables used by the signal handler. */
+    bmcTimeOut = options->timeOutPeriod;
+    alarmLapTime = options->startTime = util_cpu_ctime();
+    (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
+    (void) alarm(options->timeOutPeriod);
+    if (setjmp(timeOutEnv) > 0) {
+      (void) fprintf(vis_stdout,
+		     "\n# bdd_sat: timeout occurred after %d seconds.\n",
+		     options->timeOutPeriod);
+      (void) fprintf(vis_stdout, "# bdd_sat: data may be corrupted.\n");
+      BmcOptionFree(options);
+      alarm(0);
+      return 1;
+    }
+  }
+  /* bdd and sat to model check the LTL property.*/
+  BmcBddSat(network, formulaArray, options);
+
+  Ctlsp_FormulaArrayFree(formulaArray);
+  fflush(vis_stdout);
+  fflush(vis_stderr);
+  BmcOptionFree(options);
+  alarm(0);
+  return 0; /* normal exit */
+}/* CommandBddSat() */
+#endif
Index: vis_dev/vis-2.3/src/bmc/bmcInt.h
===================================================================
--- vis_dev/vis-2.3/src/bmc/bmcInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/bmc/bmcInt.h	(revision 14)
@@ -0,0 +1,274 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [bmcInt.h]
+
+  PackageName [bmc]
+
+  Synopsis    [Internal header declarations.]
+
+  Author      [Mohammad Awedh]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+  Revision    [$Id: bmcInt.h,v 1.52 2010/04/09 23:50:57 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _BMCINT
+#define _BMCINT
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+
+#include "cmd.h"
+#include "bmc.h"
+#include "baig.h"
+#include "ltl.h"
+#include "ltlInt.h"
+#include "sat.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef enum {
+  BmcVerbosityNone_c,
+  BmcVerbositySome_c,
+  BmcVerbosityMax_c
+} Bmc_VerbosityLevel;
+
+/*
+  Specify the status of a property
+ */
+
+typedef enum {
+  BmcPropertyUndecided_c,
+  BmcPropertyPassed_c,
+  BmcPropertyFailed_c
+} Bmc_PropertyStatus;
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [A struct for keeping the command line options for bmc command.]
+
+******************************************************************************/
+struct BmcOption {
+  FILE               *ltlFile;  /* contains the LTL formulae */
+  FILE               *fairFile; /* contains the fairness constraints */
+  char               *cnfFileName; /* File contains CNF clauses if -o option
+				      is used */
+  Bmc_VerbosityLevel verbosityLevel;
+  int                minK;
+  int                maxK;
+  int                step;
+  int                timeOutPeriod;
+  long               startTime; /* initial CPU time */
+  int                rewriting;
+  int                dbgLevel;
+  FILE * 	     dbgOut;
+  int                inductiveStep;
+  boolean            printInputs;
+  /* The folowing two pointers are used to point to the two tmp files that will
+     be created in /tmp/ before calling the SAT solver. */
+  char               *satInFile; 
+  char               *satOutFile;
+  boolean            satSolverError;  /* equal to TRUE if an error occurs in calling SAT solver */
+  int 		     incremental;
+  int                cnfPrefix;
+  int                earlyTermination; /* Use early termination check */
+  int                satSolver;   /*
+				    0 CirCUs
+				    1 cusp
+				  */
+  int                clauses;   /* representation of clauses
+				   0 CirCUs circuit
+				   1 CirCUs CNF
+				   2 CNF
+				*/
+  int                encoding;   /* encoding of LTL formula
+				   0 Original encoding
+				   1 Fixpoint
+				   2 SNF
+				   3 SNF-Fixpoint
+				*/
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [A struct to store CNF clauses]
+
+******************************************************************************/
+struct BmcCnfClauses {
+  array_t   *clauseArray;    /* array to store CNF clauses. Each clause is
+			        terminated by the value 0.                        */
+  st_table  *cnfIndexTable;  /* store the index of the key (name, state) in
+			        the clauseArray. It uses to return the index of
+			        of already generated clauses.                     */
+  array_t   *freezedKeys;    /* When CNF is freezed, any new added key to
+				cnfIndexTable will also be added to this
+				array. When CNF restored, these keys in this
+				array will be deleted from cnfIndexTable          */
+  int       nextIndex;      /* holds the index of the next entry in clauseArray.  */
+  int       noOfClauses;    /* total number of clauses */
+  int       cnfGlobalIndex; /* the index of next variable.                        */
+  boolean   emptyClause;    /* equal TRUE if the last added clause was an empty
+			       clause.                                           */
+  boolean   freezed;        /* TRUE if CNF is freezed */
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [A struct to store CNF state. When CNF is freezed, a new state
+               is created. This structure keeps the value of the varaible in
+	       the current state.]
+
+******************************************************************************/
+struct BmcCnfStates {
+  int       nextIndex;      
+  int       noOfClauses;   
+  int       cnfGlobalIndex;
+  int       freezedKeySize;
+  boolean   emptyClause;
+  boolean   freezed;
+};
+
+/**Struct**********************************************************************
+
+  Synopsis [A struct to store the check for termination status. For more
+  information, please refer to \cite{Awedh04}]
+
+******************************************************************************/
+struct BmcCheckForTermination {
+  int       k;   /* The length of the path to be checked*/
+  int       m;   /* The vlaues of m and n in the termination criterion*/
+  int       n;
+  int       checkLevel; /* Which predicate to be checked. */
+  Ltl_Automaton_t *automaton;
+  int       action; /* Next action */
+  bdd_t           *internalConstraints; /* The OR of internal constraints*/
+  Ctlsp_Formula_t *externalConstraints;  /* The OR of external constraints*/
+};
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN int BmcAutLtlCheckForTermination(Ntk_Network_t *network, array_t *constraintArray, BmcCheckForTermination_t *terminationStatus, st_table *nodeToMvfAigTable, st_table *CoiTable, BmcOption_t *options);
+EXTERN void BmcAutCnfGenerateClausesForPath(Ltl_Automaton_t *automaton, int fromState, int toState, int initialState, BmcCnfClauses_t *cnfClauses);
+EXTERN void BmcAutCnfGenerateClausesForSimpleCompositePath(Ntk_Network_t *network, Ltl_Automaton_t *automaton, int fromState, int toState, int initialState, BmcCnfClauses_t *cnfClauses, st_table *nodeToMvfAigTable, st_table *CoiTable);
+EXTERN void BmcCnfNoLoopToAnyPreviouseCompositeStates(Ntk_Network_t *network, Ltl_Automaton_t *automaton, int fromState, int toState, BmcCnfClauses_t *cnfClauses, st_table *nodeToMvfAigTable, st_table *CoiTable);
+EXTERN void BmcAutEncodeAutomatonStates(Ntk_Network_t *network, Ltl_Automaton_t *automaton);
+EXTERN void BmcAutEncodeAutomatonStates2(Ntk_Network_t *network, Ltl_Automaton_t *automaton);
+EXTERN void BmcAutEncodeAutomatonStates3(Ntk_Network_t *network, Ltl_Automaton_t *automaton);
+EXTERN void BmcAutBuildTransitionRelation(Ntk_Network_t *network, Ltl_Automaton_t *automaton);
+EXTERN mdd_t * BmcAutBuildMddForPropositionalFormula(Ntk_Network_t *network, Ltl_Automaton_t *automaton, Ctlsp_Formula_t *formula);
+EXTERN int BmcAutGenerateCnfForBddOffSet(bdd_t *function, int current, int next, BmcCnfClauses_t *cnfClauses, st_table *nsPsTable);
+EXTERN BmcCheckForTermination_t * BmcAutTerminationAlloc(Ntk_Network_t *network, Ctlsp_Formula_t *ltlFormula, array_t *constraintArray);
+EXTERN Ltl_Automaton_t * BmcAutLtlToAutomaton(Ntk_Network_t *network, Ctlsp_Formula_t *ltlFormula);
+EXTERN void BmcAutTerminationFree(BmcCheckForTermination_t *result);
+EXTERN int BmcBddSat(Ntk_Network_t *network, array_t *formulaArray, BmcOption_t *options);
+EXTERN Bmc_PropertyStatus BmcBddSatCheckLtlFormula(Ntk_Network_t *network, mdd_t *initialStates, mdd_t *targetStates, BmcOption_t *options, st_table *CoiTable);
+EXTERN void BmcLtlVerifyProp(Ntk_Network_t *network, Ctlsp_Formula_t *ltlFormula, st_table *CoiTable, BmcOption_t *options);
+EXTERN int BmcLtlCheckInductiveInvariant(Ntk_Network_t *network, bAigEdge_t property, BmcOption_t *options, st_table *CoiTable);
+EXTERN void BmcLtlVerifyGp(Ntk_Network_t *network, Ctlsp_Formula_t *ltlFormula, st_table *CoiTable, BmcOption_t *options);
+EXTERN void BmcLtlVerifyFp(Ntk_Network_t *network, Ctlsp_Formula_t *ltlFormula, st_table *CoiTable, BmcOption_t *options);
+EXTERN void BmcLtlVerifyFGp(Ntk_Network_t *network, Ctlsp_Formula_t *ltlFormula, st_table *CoiTable, BmcOption_t *options);
+EXTERN void BmcLtlVerifyUnitDepth(Ntk_Network_t *network, Ctlsp_Formula_t *ltlFormula, st_table *CoiTable, BmcOption_t *options);
+EXTERN void BmcLtlVerifyGeneralLtl(Ntk_Network_t *network, Ctlsp_Formula_t *ltlFormula, st_table *CoiTable, array_t *constraintArray, BmcOption_t *options);
+EXTERN int BmcGenerateCnfForLtl(Ntk_Network_t *network, Ctlsp_Formula_t *ltlFormula, int i, int k, int l, BmcCnfClauses_t *cnfClauses);
+EXTERN void BmcLtlCheckSafety(Ntk_Network_t *network, Ctlsp_Formula_t *ltlFormula, BmcOption_t *options, st_table *CoiTable);
+EXTERN void BmcCirCUsLtlVerifyProp(Ntk_Network_t *network, Ctlsp_Formula_t *ltl, st_table *coiTable, BmcOption_t *options);
+EXTERN int BmcCirCUsLtlCheckInductiveInvariant(Ntk_Network_t *network, Ctlsp_Formula_t *ltl, BmcOption_t *options, st_table *CoiTable);
+EXTERN void BmcCirCUsLtlVerifyGp(Ntk_Network_t *network, Ctlsp_Formula_t *ltl, st_table *coiTable, BmcOption_t *options);
+EXTERN void BmcCirCUsLtlVerifyFp(Ntk_Network_t *network, Ctlsp_Formula_t *ltl, st_table *coiTable, BmcOption_t *options);
+EXTERN bAigEdge_t BmcCirCUsGenerateLogicForLtl(Ntk_Network_t *network, Ctlsp_Formula_t *ltl, int from, int to, int loop);
+EXTERN bAigEdge_t BmcCirCUsGenerateLogicForLtlSNF(Ntk_Network_t *network, array_t *formulaArray, int fromState, int toState, int loop);
+EXTERN bAigEdge_t BmcCirCUsGenerateLogicForLtlFixPoint(Ntk_Network_t *network, Ctlsp_Formula_t *ltl, int from, int to, array_t *loopArray);
+EXTERN bAigEdge_t BmcCirCUsGenerateLogicForLtlFixPointRecursive(Ntk_Network_t *network, Ctlsp_Formula_t *ltl, int from, int to, int translation, array_t *loopArray, st_table *ltl2AigTable);
+EXTERN void BmcCirCUsLtlVerifyFGp(Ntk_Network_t *network, Ctlsp_Formula_t *ltlFormula, st_table *coiTable, BmcOption_t *options);
+EXTERN void BmcCirCUsLtlVerifyGeneralLtl(Ntk_Network_t *network, Ctlsp_Formula_t *ltl, st_table *coiTable, array_t *constraintArray, BmcOption_t *options, int snf);
+EXTERN void BmcCirCUsLtlVerifyGeneralLtlFixPoint(Ntk_Network_t *network, Ctlsp_Formula_t *ltl, st_table *coiTable, array_t *constraintArray, BmcOption_t *options);
+EXTERN void BmcCirCUsLtlCheckSafety(Ntk_Network_t *network, Ctlsp_Formula_t *ltl, BmcOption_t *options, st_table *coiTable);
+EXTERN bAigEdge_t BmcCirCUsConnectFromStateToState(Ntk_Network_t *network, int from, int to, st_table *nodeToMvfAigTable, st_table *coiIndexTable, int withInitialState);
+EXTERN bAigEdge_t BmcCirCUsSimlePathConstraint(Ntk_Network_t *network, int fromState, int toState, st_table *nodeToMvfAigTable, st_table *coiIndexTable, int withInitialState);
+EXTERN bAigEdge_t BmcCirCUsGenerateSimplePath(Ntk_Network_t *network, int from, int to, st_table *nodeToMvfAigTable, st_table *coiIndexTable, int withInitialState);
+EXTERN void BmcCirCUsPrintCounterExample(Ntk_Network_t *network, st_table *nodeToMvfAigTable, st_table *coiTable, int length, array_t *loop_arr, BmcOption_t *options, int withInitialState);
+EXTERN void BmcCirCUsPrintCounterExampleAiger(Ntk_Network_t *network, st_table *nodeToMvfAigTable, st_table *coiTable, int length, array_t *loop_arr, BmcOption_t *options, int withInitialState);
+EXTERN bAigEdge_t BmcCirCUsCreatebAigOfPropFormula(Ntk_Network_t *network, bAig_Manager_t *manager, int bound, Ctlsp_Formula_t *ltl, int withInitialState);
+EXTERN bAigEdge_t BmcCirCUsCreatebAigOfPropFormulaOriginal(Ntk_Network_t *network, bAig_Manager_t *manager, Ctlsp_Formula_t *ltl);
+EXTERN satInterface_t * BmcCirCUsInterface(bAig_Manager_t *manager, Ntk_Network_t *network, bAigEdge_t object, array_t *auxObjectArray, BmcOption_t *bmcOption, satInterface_t *interface);
+EXTERN satInterface_t * BmcCirCUsInterfaceWithObjArr(bAig_Manager_t *manager, Ntk_Network_t *network, array_t *objectArray, array_t *auxObjectArray, BmcOption_t *bmcOption, satInterface_t *interface);
+EXTERN satManager_t * BmcCirCUsCreateManager(Ntk_Network_t *network);
+EXTERN st_table * BmcCirCUsGetCoiIndexTable(Ntk_Network_t *network, st_table *coiTable);
+EXTERN void BmcCirCUsAutLtlCheckTerminalAutomaton(Ntk_Network_t *network, bAig_Manager_t *aigManager, st_table *nodeToMvfAigTable, BmcCheckForTermination_t *terminationStatus, st_table *coiIndexTable, BmcOption_t *options);
+EXTERN bAigEdge_t BmcCirCUsBdd2Aig(Ntk_Network_t *network, bdd_t *function, int current, int next, Ltl_Automaton_t *automaton, bAig_Manager_t *aigManager, int withInitialState);
+EXTERN bAigEdge_t BmcCirCUsAutCreateAigForPath(Ntk_Network_t *network, bAig_Manager_t *aigManager, Ltl_Automaton_t *automaton, int fromState, int toState, int initialState);
+EXTERN bAigEdge_t BmcCirCUsAutCreateAigForSimplePath(Ntk_Network_t *network, bAig_Manager_t *aigManager, Ltl_Automaton_t *automaton, int fromState, int toState, int initialState);
+EXTERN bAigEdge_t BmcCirCUsCreateAigForSimpleCompositePath(Ntk_Network_t *network, bAig_Manager_t *aigManager, Ltl_Automaton_t *automaton, int fromState, int toState, st_table *nodeToMvfAigTable, st_table *coiIndexTable, int initialState);
+EXTERN void BmcCirCUsAutLtlCheckForTermination(Ntk_Network_t *network, bAig_Manager_t *aigManager, st_table *nodeToMvfAigTable, BmcCheckForTermination_t *terminationStatus, st_table *coiIndexTable, BmcOption_t *options);
+EXTERN char * BmcCirCUsCallCirCUs(BmcOption_t *options);
+EXTERN char * BmcCirCUsCallCusp(BmcOption_t *options);
+EXTERN BmcOption_t * BmcOptionAlloc(void);
+EXTERN void BmcOptionFree(BmcOption_t *result);
+EXTERN char * BmcCreateTmpFile(void);
+EXTERN int CommandBddSat(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+EXTERN mdd_t * BmcFsmEvaluateX(Fsm_Fsm_t *modelFsm, mdd_t *targetMdd);
+EXTERN mdd_t * BmcComputeCloseCube(mdd_t *aSet, mdd_t *target, int *dist, array_t *Support, mdd_manager *mddMgr);
+EXTERN mAigEdge_t BmcCreateMaigOfInitialStates(Ntk_Network_t *network, st_table *nodeToMvfAigTable, st_table *CoiTable);
+EXTERN mAigEdge_t BmcCreateMaigOfPropFormula(Ntk_Network_t *network, mAig_Manager_t *manager, Ctlsp_Formula_t *formula);
+EXTERN mdd_t * BmcCreateMddOfSafetyProperty(Fsm_Fsm_t *fsm, Ctlsp_Formula_t *formula);
+EXTERN int BmcGenerateCnfFormulaForAigFunction(bAig_Manager_t *manager, bAigEdge_t node, int k, BmcCnfClauses_t *cnfClauses);
+EXTERN int BmcGenerateCnfFormulaForBdd(bdd_t *bddFunction, int k, BmcCnfClauses_t *cnfClauses);
+EXTERN int BmcGenerateCnfFormulaForBddOffSet(bdd_t *bddFunction, int k, BmcCnfClauses_t *cnfClauses);
+EXTERN int BmcGenerateCnfForAigFunction(bAig_Manager_t *manager, Ntk_Network_t *network, bAigEdge_t node, int k, BmcCnfClauses_t *cnfClauses);
+EXTERN void BmcGenerateClausesFromStateTostate(bAig_Manager_t *manager, bAigEdge_t *fromAigArray, bAigEdge_t *toAigArray, int mvfSize, int fromState, int toState, BmcCnfClauses_t *cnfClauses, int outIndex);
+EXTERN void BmcWriteClauses(mAig_Manager_t *maigManager, FILE *cnfFile, BmcCnfClauses_t *cnfClauses, BmcOption_t *options);
+EXTERN array_t * BmcCheckSAT(BmcOption_t *options);
+EXTERN array_t * BmcCallCirCUs(BmcOption_t *options);
+EXTERN array_t * BmcCallCusp(BmcOption_t *options);
+EXTERN void BmcPrintCounterExample(Ntk_Network_t *network, st_table *nodeToMvfAigTable, BmcCnfClauses_t *cnfClauses, array_t *result, int length, st_table *CoiTable, BmcOption_t *options, array_t *loopClause);
+EXTERN void BmcPrintCounterExampleAiger(Ntk_Network_t *network, st_table *nodeToMvfAigTable, BmcCnfClauses_t *cnfClauses, array_t *result, int length, st_table *CoiTable, BmcOption_t *options, array_t *loopClause);
+EXTERN void BmcAutPrintCounterExample(Ntk_Network_t *network, Ltl_Automaton_t *automaton, st_table *nodeToMvfAigTable, BmcCnfClauses_t *cnfClauses, array_t *result, int length, st_table *CoiTable, BmcOption_t *options, array_t *loopClause);
+EXTERN void BmcCnfGenerateClausesForPath(Ntk_Network_t *network, int from, int to, int initialState, BmcCnfClauses_t *cnfClauses, st_table *nodeToMvfAigTable, st_table *CoiTable);
+EXTERN void BmcCnfGenerateClausesForLoopFreePath(Ntk_Network_t *network, int fromState, int toState, int initialState, BmcCnfClauses_t *cnfClauses, st_table *nodeToMvfAigTable, st_table *CoiTable);
+EXTERN void BmcCnfGenerateClausesForNoLoopToAnyPreviouseStates(Ntk_Network_t *network, int fromState, int toState, BmcCnfClauses_t *cnfClauses, st_table *nodeToMvfAigTable, st_table *CoiTable);
+EXTERN void BmcCnfGenerateClausesForLoopToAnyPreviouseStates(Ntk_Network_t *network, int fromState, int toState, BmcCnfClauses_t *cnfClauses, st_table *nodeToMvfAigTable, st_table *CoiTable);
+EXTERN void BmcCnfGenerateClausesFromStateToState(Ntk_Network_t *network, int from, int to, BmcCnfClauses_t *cnfClauses, st_table *nodeToMvfAigTable, st_table *CoiTable, int loop);
+EXTERN void BmcCnfGenerateClausesForAND(int a, int b, int c, BmcCnfClauses_t *cnfClauses);
+EXTERN void BmcCnfGenerateClausesForOR(int a, int b, int c, BmcCnfClauses_t *cnfClauses);
+EXTERN BmcCnfClauses_t * BmcCnfClausesAlloc(void);
+EXTERN void BmcCnfClausesFree(BmcCnfClauses_t *cnfClauses);
+EXTERN BmcCnfStates_t * BmcCnfClausesFreeze(BmcCnfClauses_t * cnfClauses);
+EXTERN void BmcCnfClausesUnFreeze(BmcCnfClauses_t *cnfClauses, BmcCnfStates_t *state);
+EXTERN void BmcCnfClausesRestore(BmcCnfClauses_t *cnfClauses, BmcCnfStates_t *state);
+EXTERN void BmcCnfInsertClause(BmcCnfClauses_t *cnfClauses, array_t *clause);
+EXTERN void BmcAddEmptyClause(BmcCnfClauses_t *cnfClauses);
+EXTERN int BmcCnfReadOrInsertNode(BmcCnfClauses_t *cnfClauses, nameType_t *nodeName, int state, int *nodeIndex);
+EXTERN void BmcGetCoiForLtlFormula(Ntk_Network_t *network, Ctlsp_Formula_t *formula, st_table *ltlCoiTable);
+EXTERN void BmcGetCoiForLtlFormulaRecursive(Ntk_Network_t *network, Ctlsp_Formula_t *formula, st_table *ltlCoiTable, st_table *visited);
+EXTERN void BmcGetCoiForNtkNode(Ntk_Node_t *node, st_table *CoiTable, st_table *visited);
+EXTERN mdd_t * BmcModelCheckAtomicFormula(Fsm_Fsm_t *modelFsm, Ctlsp_Formula_t *ctlFormula);
+EXTERN array_t * BmcReadFairnessConstraints(FILE *fp);
+EXTERN int BmcGetCnfVarIndexForBddNode(bdd_manager *bddManager, bdd_node *node, int state, BmcCnfClauses_t *cnfClauses);
+EXTERN void BmcRestoreAssertion(bAig_Manager_t *manager, satManager_t *cm);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _BMCINT */
Index: vis_dev/vis-2.3/src/bmc/bmcUtil.c
===================================================================
--- vis_dev/vis-2.3/src/bmc/bmcUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/bmc/bmcUtil.c	(revision 14)
@@ -0,0 +1,3242 @@
+/**CFile***********************************************************************
+
+  FileName    [bmcUtil.c]
+
+  PackageName [bmc]
+
+  Synopsis    [Utilities for BMC package]
+
+  Author      [Mohammad Awedh]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+  
+******************************************************************************/
+
+#include "bmcInt.h"
+#include "sat.h"
+#include "baig.h"
+
+static char rcsid[] UNUSED = "$Id: bmcUtil.c,v 1.82 2010/04/10 04:07:06 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define MAX_LENGTH 320 /* Max. length of a string while reading a file     */
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int StringCheckIsInteger(char *string, int *value);
+static int nameCompare(const void * name1, const void * name2);
+static void printValue(mAig_Manager_t *manager, Ntk_Network_t *network, st_table *nodeToMvfAigTable, BmcCnfClauses_t *cnfClauses, array_t *varNames, st_table *resultTable, int state, int *prevValue);
+static void printValueAiger(mAig_Manager_t *manager, Ntk_Network_t *network, st_table *nodeToMvfAigTable, BmcCnfClauses_t *cnfClauses, array_t *varNames, st_table *resultTable, int state, int *prevValue);
+static void printValueAigerInputs(mAig_Manager_t *manager, Ntk_Network_t *network, st_table *nodeToMvfAigTable, BmcCnfClauses_t *cnfClauses, array_t *varNames, st_table *resultTable, int state, int *prevValue);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Compute cube that is close to target states.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Bmc_ComputeCloseCube( 
+  mdd_t *states,
+  mdd_t *target,
+  int   *dist,
+  Fsm_Fsm_t *modelFsm)
+{
+  array_t *PSVars = Fsm_FsmReadPresentStateVars( modelFsm );
+  mdd_manager *mddMgr = Ntk_NetworkReadMddManager( Fsm_FsmReadNetwork( modelFsm ) ); 
+  mdd_t *result = BmcComputeCloseCube( states, target, dist, PSVars, mddMgr );
+
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Build multi-valued function for a given node.]
+
+  SideEffects [The mvf of this node is a function of combinational input
+  nodes.]
+
+******************************************************************************/
+MvfAig_Function_t *
+Bmc_NodeBuildMVF(
+  Ntk_Network_t *network,
+  Ntk_Node_t    *node)
+{
+  MvfAig_Function_t * MvfAig; 
+  lsGen tmpGen;
+  Ntk_Node_t *tmpNode;
+  array_t    *mvfArray;
+  array_t    *tmpRoots = array_alloc(Ntk_Node_t *, 0);
+  st_table   *tmpLeaves = st_init_table(st_ptrcmp, st_ptrhash);
+  array_insert_last(Ntk_Node_t *, tmpRoots, node);
+
+  Ntk_NetworkForEachCombInput(network, tmpGen, tmpNode) {
+    st_insert(tmpLeaves, (char *) tmpNode, (char *) ntmaig_UNUSED);
+  }
+
+  mvfArray = ntmaig_NetworkBuildMvfAigs(network, tmpRoots, tmpLeaves);
+  MvfAig   = array_fetch(MvfAig_Function_t *, mvfArray, 0);
+  array_free(tmpRoots);
+  st_free_table(tmpLeaves);
+  array_free(mvfArray);
+  return MvfAig;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns MvfAig corresponding to a node; returns NIL if node not in
+  table.]
+
+  SideEffects [None]
+
+******************************************************************************/
+MvfAig_Function_t *
+Bmc_ReadMvfAig(
+  Ntk_Node_t * node,
+  st_table   * nodeToMvfAigTable)
+{
+  MvfAig_Function_t *result;
+  if (st_lookup(nodeToMvfAigTable, node, &result)){
+     return result;
+  }
+  return NIL(MvfAig_Function_t);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Evaluate states satisfying X target]
+
+  Description [Evaluate states satisfying X target.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+BmcFsmEvaluateX(
+  Fsm_Fsm_t *modelFsm,
+  mdd_t     *targetMdd)
+{
+  mdd_t *fromLowerBound;
+  mdd_t *fromUpperBound;
+  mdd_t *result;
+  Img_ImageInfo_t * imageInfo;
+  mdd_t           *careStates;
+  array_t         *careStatesArray = array_alloc(array_t *, 0);  
+
+  imageInfo = Fsm_FsmReadOrCreateImageInfo(modelFsm, 1, 0);
+
+  /*
+   * The lower bound is the conjunction of the fair states,
+   * and the target states.
+   */
+  fromLowerBound = mdd_dup(targetMdd);
+  /*
+   * The upper bound is the same as the lower bound.
+   */
+  fromUpperBound = mdd_dup(fromLowerBound);
+  /*
+    careSet is the set of all unreachabel states.
+  */
+  careStates = mdd_one(Fsm_FsmReadMddManager(modelFsm));
+  array_insert(mdd_t *, careStatesArray, 0, careStates);
+  
+  result = Img_ImageInfoComputePreImageWithDomainVars(imageInfo,
+		fromLowerBound, fromUpperBound, careStatesArray);
+  mdd_free(fromLowerBound);
+  mdd_free(fromUpperBound);
+  
+  return result;
+
+} /* BmcFsmEvaluateX */
+
+
+/**Function********************************************************************
+
+  Synopsis [Compute cube that is close to target states. Support
+  is an array of mddids representing the total support; that is, all
+  the variables on which aSet may depend. It dos the function only
+  if CUDD is the BDD package.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+BmcComputeCloseCube(
+  mdd_t *aSet,
+  mdd_t *target,
+  int   *dist,
+  array_t *Support,
+  mdd_manager *mddMgr)
+{
+  if (bdd_get_package_name() == CUDD && target != NIL(mdd_t)) {
+    mdd_t *range;             /* range of Support             */
+    mdd_t *legalSet;          /* aSet without the don't cares */
+    mdd_t *closeCube;
+
+    
+    /* Check that support of set is contained in Support. 
+    assert(SetCheckSupport(aSet, Support, mddMgr)); */ 
+    assert(!mdd_is_tautology(aSet, 0));
+    range      = mdd_range_mdd(mddMgr, Support);
+    legalSet   = bdd_and(aSet, range, 1, 1);
+    mdd_free(range);
+    closeCube = mdd_closest_cube(legalSet, target, dist);
+
+    mdd_free(legalSet);
+    
+    return closeCube;
+  } else {
+    return aSet;
+    /*return BMC_ComputeAMinterm(aSet, Support, mddMgr);*/
+  }/* if CUDD */
+
+} /* BmcComputeCloseCube */
+
+
+/**Function********************************************************************
+
+  Synopsis [Build AND/INV graph for intial states]
+
+  Description [Build AND/INV graph for intial states. Returns bAig Id
+  of the bAig Function that represents the intial states.
+
+  The initial states are computed as follows. For each latch i, the relation
+  (x_i = g_i(u)) is built, where x_i is the present state variable of latch i,
+  and g_i(u) is the multi-valued initialization function of latch i, in terms
+  of the input variables u.  These relations are then conjuncted.
+  ]
+
+  SideEffects []
+
+  SeeAlso     []
+  
+******************************************************************************/
+mAigEdge_t
+BmcCreateMaigOfInitialStates(
+  Ntk_Network_t   *network,
+  st_table        *nodeToMvfAigTable,
+  st_table        *CoiTable)
+{
+  mAig_Manager_t  *manager = Ntk_NetworkReadMAigManager(network);
+  st_generator    *stGen;
+  
+  Ntk_Node_t         *latch, *latchInit;
+  MvfAig_Function_t  *initMvfAig, *latchMvfAig;
+ 
+  bAigEdge_t         resultAnd = bAig_One;
+  bAigEdge_t         resultOr;
+  int                i;
+
+  st_foreach_item(CoiTable, stGen, &latch, NULL) {
+    
+    
+    latchInit  = Ntk_LatchReadInitialInput(latch);
+    
+    /* Get the multi-valued function for each node*/
+    initMvfAig = Bmc_ReadMvfAig(latchInit, nodeToMvfAigTable);
+    if (initMvfAig ==  NIL(MvfAig_Function_t)){
+      (void) fprintf(vis_stdout, "No multi-valued function for this node %s \n", Ntk_NodeReadName(latchInit));
+      return bAig_NULL;
+   }
+   latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+   if (latchMvfAig ==  NIL(MvfAig_Function_t)){
+     latchMvfAig = Bmc_NodeBuildMVF(network, latch);
+     array_free(latchMvfAig);
+     latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+   }
+   resultOr  = bAig_Zero;
+   for(i=0; i<array_n(initMvfAig); i++){
+     resultOr = mAig_Or(manager, resultOr,
+			bAig_Eq(manager,
+				bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(initMvfAig,  i)),
+				bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(latchMvfAig, i))
+				)
+			);
+     if(resultOr == bAig_One){
+       break;
+     }
+   }
+   resultAnd = mAig_And(manager, resultAnd, resultOr);
+   if(resultAnd == bAig_Zero){
+     break;
+   }
+  }/* for each latch*/
+
+  return resultAnd;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Builds AND/INVERTER graph (aig) for a propsitional formula]
+
+  Description [Builds AND/INVERTER graph for a propsitional formula.
+  Returns bAig ID of the function that is quivalent to the propositional
+  fomula]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+mAigEdge_t
+BmcCreateMaigOfPropFormula(
+  Ntk_Network_t   *network,
+  mAig_Manager_t  *manager,
+  Ctlsp_Formula_t *formula)
+{
+  mAigEdge_t left, right, result;
+
+  if (formula == NIL(Ctlsp_Formula_t)) {
+    return mAig_NULL;
+  }
+  if (formula->type == Ctlsp_TRUE_c){
+    return mAig_One;
+  }
+  if (formula->type == Ctlsp_FALSE_c){
+    return mAig_Zero;
+  }
+  
+  assert(Ctlsp_isPropositionalFormula(formula));
+  
+  if (formula->type == Ctlsp_ID_c){
+      char *nodeNameString  = Ctlsp_FormulaReadVariableName(formula);
+      char *nodeValueString = Ctlsp_FormulaReadValueName(formula);
+      Ntk_Node_t *node      = Ntk_NetworkFindNodeByName(network, nodeNameString);
+
+      Var_Variable_t *nodeVar;
+      int             nodeValue;
+
+      MvfAig_Function_t  *tmpMvfAig;
+      st_table           *nodeToMvfAigTable; /* maps each node to its mvfAig */
+      
+      if (node == NIL(Ntk_Node_t)) {
+          (void) fprintf(vis_stderr, "bmc error: Could not find node corresponding to the name\t %s\n", nodeNameString);
+          return mAig_NULL;
+      }
+      nodeToMvfAigTable = (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+      if (nodeToMvfAigTable == NIL(st_table)){
+         (void) fprintf(vis_stderr, "bmc error: please run build_partiton_maigs first");
+         return mAig_NULL;
+      }
+      tmpMvfAig = Bmc_ReadMvfAig(node, nodeToMvfAigTable);
+      if (tmpMvfAig ==  NIL(MvfAig_Function_t)){
+          tmpMvfAig = Bmc_NodeBuildMVF(network, node);
+	  array_free(tmpMvfAig);
+	  tmpMvfAig = Bmc_ReadMvfAig(node, nodeToMvfAigTable);
+      }
+      nodeVar = Ntk_NodeReadVariable(node);
+      if (Var_VariableTestIsSymbolic(nodeVar)) {
+        nodeValue = Var_VariableReadIndexFromSymbolicValue(nodeVar, nodeValueString);
+        if ( nodeValue == -1 ) {
+          (void) fprintf(vis_stderr, "Value specified in RHS is not in domain of variable\n");
+          (void) fprintf(vis_stderr,"%s = %s\n", nodeNameString, nodeValueString);
+          return mAig_NULL;
+        }
+      }
+      else { 
+        int check;    
+         check = StringCheckIsInteger(nodeValueString, &nodeValue);
+         if( check == 0 ) {
+          (void) fprintf(vis_stderr,"Illegal value in the RHS\n");
+          (void) fprintf(vis_stderr,"%s = %s\n", nodeNameString, nodeValueString);
+          return mAig_NULL;
+	 }
+         if( check == 1 ) {
+          (void) fprintf(vis_stderr,"Value in the RHS is out of range of int\n");
+          (void) fprintf(vis_stderr,"%s = %s", nodeNameString, nodeValueString);
+          return mAig_NULL;
+	 }
+         if ( !(Var_VariableTestIsValueInRange(nodeVar, nodeValue))) {
+          (void) fprintf(vis_stderr,"Value specified in RHS is not in domain of variable\n");
+          (void) fprintf(vis_stderr,"%s = %s\n", nodeNameString, nodeValueString);
+          return mAig_NULL;
+
+         }
+      }
+      result = MvfAig_FunctionReadComponent(tmpMvfAig, nodeValue);
+      return bAig_GetCanonical(manager, result);
+  }
+  /*
+    right can be mAig_NULL for unery operators, but left can't be mAig_Null
+   */
+  left  = BmcCreateMaigOfPropFormula(network, manager, formula->left);
+  if (left == mAig_NULL){
+    return mAig_NULL;
+  }  
+  right = BmcCreateMaigOfPropFormula(network, manager, formula->right);
+
+  switch(formula->type) {
+    case Ctlsp_NOT_c:
+      result = mAig_Not(left);
+      break;
+    case Ctlsp_OR_c:
+      result = mAig_Or(manager, left, right);
+      break;
+    case Ctlsp_AND_c:
+      result = mAig_And(manager, left, right);
+      break;
+    case Ctlsp_THEN_c:
+      result = mAig_Then(manager, left, right); 
+      break;
+    case Ctlsp_EQ_c:
+      result = mAig_Eq(manager, left, right);
+      break;
+    case Ctlsp_XOR_c:
+      result = mAig_Xor(manager, left, right);
+      break;
+    default:
+      fail("Unexpected LTL type");
+  }
+  return result;
+} /* BmcCreateMaigOfPropFormula */
+
+/**Function********************************************************************
+
+  Synopsis [Build MDD for safety property in form of AG(p).  Where p is either a
+  propositional formula or a path formula contains only the temporal property X.]
+
+  Description [Build MDD for a safety formula. Returns NIL if the conversion
+  fails. The calling application is responsible for freeing the returned MDD.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_FormulaReadClass]
+
+******************************************************************************/
+mdd_t *
+BmcCreateMddOfSafetyProperty(
+  Fsm_Fsm_t       *fsm,
+  Ctlsp_Formula_t *formula)
+{
+ 
+  mdd_manager	*manager = Ntk_NetworkReadMddManager(Fsm_FsmReadNetwork(fsm));
+  mdd_t         *left, *right, *result;
+
+  if (formula == NIL(Ctlsp_Formula_t)) {
+    return NIL(mdd_t);
+  }
+  if (formula->type == Ctlsp_TRUE_c){
+    return bdd_one(manager);
+  }
+  if (formula->type == Ctlsp_FALSE_c){
+    return  mdd_zero(manager);
+  }
+  
+#if 0
+  if (!Ctlsp_isPropositionalFormula(formula)) {
+    (void) fprintf(vis_stderr, "bmc error: Only propositional formula can be converted to bdd \n");
+    fprintf(vis_stdout, "\nFormula: ");
+    Ctlsp_FormulaPrint(vis_stdout, formula);
+    fprintf(vis_stdout, "\n");
+    return NIL(mdd_t);
+  }
+#endif
+  /*
+    Atomic proposition.
+   */
+  if (formula->type == Ctlsp_ID_c){
+    return BmcModelCheckAtomicFormula(fsm, formula);
+  }
+  /*
+    right can be NIL(mdd_t) for unery operators, but left can't be  NIL(mdd_t)
+   */
+  left  = BmcCreateMddOfSafetyProperty(fsm, formula->left);
+  if (left == NIL(mdd_t)){
+    return NIL(mdd_t);
+  }  
+  right = BmcCreateMddOfSafetyProperty(fsm, formula->right);
+  assert(right !=  NIL(mdd_t)); 
+  switch(formula->type) {
+    case Ctlsp_NOT_c:
+      result = mdd_not(left);
+      break;
+    case Ctlsp_OR_c:
+      result = mdd_or(left, right, 1, 1);
+      break;
+    case Ctlsp_AND_c:
+      result = mdd_and(left, right, 1, 1);
+      break;
+    case Ctlsp_THEN_c:
+      result = mdd_or(left, right, 0, 1); 
+      break;
+    case Ctlsp_EQ_c:
+      result = mdd_xnor(left, right);
+      break;
+    case Ctlsp_XOR_c:
+      result = mdd_xor(left, right);
+      break;
+  case Ctlsp_X_c:
+      result = BmcFsmEvaluateX(fsm, left);
+      break;
+  default:
+    /*
+      return NIL(mdd_t) if the type is not supported
+     */
+     return NIL(mdd_t);
+     /*
+      fail("Unexpected type");
+     */
+  }
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generate the CNF formula of a given function represented by
+               AND/INVERTER graph]
+
+  Description [Generate an array of clausese for a function represented in
+  AND/INVERETER graph structure. 
+  
+  the CNF formula of node to the output file specifies by cnfFile.
+               It stores CNF index for each node in the cnfIndexTable. The generated CNF
+               is in dimacs format.
+	       It is an error to call this function on a constand zero/one node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+BmcGenerateCnfFormulaForAigFunction(
+   bAig_Manager_t *manager,
+   bAigEdge_t      node,
+   int             k,
+   BmcCnfClauses_t *cnfClauses)
+{
+  int        leftIndex, rightIndex, nodeIndex;
+  array_t    *clause;
+
+  assert( (node != bAig_One) && (node != bAig_Zero));
+  
+  if(bAig_IsInverted(node)){
+    /*
+      The generated clauses are in dimacs formate that uses negative number to indicate complement
+     */
+    return -1*BmcGenerateCnfFormulaForAigFunction(manager, bAig_NonInvertedEdge(node), k, cnfClauses);
+  }
+  if (BmcCnfReadOrInsertNode(cnfClauses, bAig_NodeReadName(manager, node), k, &nodeIndex)){
+    return nodeIndex;
+  }
+  if (bAig_isVarNode(manager, node)){
+    return nodeIndex;
+  }
+  leftIndex  = BmcGenerateCnfFormulaForAigFunction(manager,
+						   bAig_GetCanonical(manager, leftChild(node)),
+						   k, cnfClauses);
+  rightIndex = BmcGenerateCnfFormulaForAigFunction(manager,
+						   bAig_GetCanonical(manager, rightChild(node)),
+						   k, cnfClauses);
+  clause  = array_alloc(int, 3);
+  array_insert(int, clause, 0, -leftIndex );
+  array_insert(int, clause, 1, -rightIndex);
+  array_insert(int, clause, 2,  nodeIndex );
+  BmcCnfInsertClause(cnfClauses, clause);
+  array_free(clause);
+  
+  clause  = array_alloc(int, 2);
+  array_insert(int, clause, 0,  leftIndex);
+  array_insert(int, clause, 1, -nodeIndex);
+  BmcCnfInsertClause(cnfClauses, clause);
+  array_free(clause);
+  
+  clause  = array_alloc(int, 2);
+  array_insert(int, clause, 0,  rightIndex);
+  array_insert(int, clause, 1, -nodeIndex);
+  BmcCnfInsertClause(cnfClauses, clause);  
+  array_free(clause);
+  
+  return(nodeIndex);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Generate CNF for bdd function]
+
+  Description [
+    The function of each node f = var*thenChild + -var*elseChild
+    var is the variable at this node.
+    For each node there are four cases:
+      - both childeren are constant -> do nothing.
+      - the then child is constant 1 -> generate clauses for f = var + elseChild.
+      - the else child is constant 0 -> generate clauses for f = var * thenChild.
+      - the else child is constant 1 -> generate clauses for f = -var + thenChild.
+      - else -> generate clauses for f = var*thenChild + -var*elseChild.
+  ------------------------------------------------
+    function        |        clauses
+  ------------------------------------------------  
+    c = a*b         | (-a + -b + c)*(a + -c)*(b + -c)
+    c = a+b         | (a + b + -c)*(-a + c)*(-b + c)
+    f = c*a + -c*b  | (-a + -c + f)*(a + -c + -f)*
+                    | (-b +  c + f)*(b +  c + -f)
+
+  return the cnf index of the bdd function
+  ]
+  
+  SideEffects []
+
+  SeeAlso     []
+  
+******************************************************************************/
+int 
+BmcGenerateCnfFormulaForBdd(
+   bdd_t          *bddFunction,
+   int             k,
+   BmcCnfClauses_t *cnfClauses)
+{
+  bdd_manager *bddManager = bdd_get_manager(bddFunction);
+  bdd_node    *node, *thenNode, *elseNode, *funcNode;
+  int         is_complemented;
+  int         nodeIndex=0, thenIndex, elseIndex;
+  bdd_gen     *gen;
+  int         varIndex, flag; 
+  array_t     *tmpClause;
+  
+  st_table    *bddToCnfIndexTable;
+  
+  bdd_t       *currentBddNode;
+  int         cut = 5;
+  
+  if (bddFunction == NULL){
+    return 0;
+  }
+  funcNode = bdd_get_node(bddFunction, &is_complemented);
+  if (bdd_is_constant(funcNode)){
+    if (is_complemented){
+      /* add an empty clause to indicate FALSE (un-satisfiable)*/
+      BmcAddEmptyClause(cnfClauses);
+    }
+    return 0;
+  }
+  if(bdd_size(bddFunction) <= cut){
+    return BmcGenerateCnfFormulaForBddOffSet(bddFunction, k, cnfClauses);
+  }
+  
+  bddToCnfIndexTable = st_init_table(st_numcmp, st_numhash);
+  foreach_bdd_node(bddFunction, gen, node){
+    if (bdd_is_constant(node)){ /* do nothing */
+      continue;
+    }
+
+    /*
+      bdd_size() returns 1 if bdd is constant one.
+    */
+    /*
+      Use offset method to generate CNF if the size of the node <= cut (include the constant 1 node).
+    */
+    /*#if 0*/    
+    if(bdd_size(currentBddNode = bdd_construct_bdd_t(bddManager, bdd_regular(node))) <= cut){
+      if (bdd_size(currentBddNode) == cut){
+	nodeIndex = BmcGenerateCnfFormulaForBddOffSet(currentBddNode, k, cnfClauses);
+	st_insert(bddToCnfIndexTable, (char *) (long) bdd_regular(node),  (char *) (long)nodeIndex);
+	continue;
+      }
+      continue;
+    }
+    /*#endif*/    
+    varIndex  = BmcGetCnfVarIndexForBddNode(bddManager, bdd_regular(node), k, cnfClauses);
+    nodeIndex = varIndex;
+    
+    thenNode = bdd_bdd_T(node);
+    elseNode = bdd_bdd_E(node);
+
+    if (!((bdd_is_constant(thenNode)) && (bdd_is_constant(elseNode)))){
+      nodeIndex = cnfClauses->cnfGlobalIndex++;   /* index of the function of this node */
+      
+      if (bdd_is_constant(thenNode)){ /* the thenNode can be only constant one*/
+	flag = st_lookup_int(bddToCnfIndexTable, bdd_regular(elseNode), &elseIndex);
+        assert(flag);
+	/*
+	  test if the elseNode is complemented arc?
+	*/
+	if (bdd_is_complement(elseNode)){
+	  elseIndex = -1*elseIndex;
+	}  
+	BmcCnfGenerateClausesForOR(elseIndex, varIndex, nodeIndex, cnfClauses);
+      } else if (bdd_is_constant(elseNode)){ /* one or zero */
+	flag = st_lookup_int(bddToCnfIndexTable, bdd_regular(thenNode), &thenIndex);
+        assert(flag);
+	/*
+	  test if the elseNode is complemented arc?
+	*/
+	if (bdd_is_complement(elseNode)){  /* Constant zero */
+	 BmcCnfGenerateClausesForAND(thenIndex, varIndex, nodeIndex, cnfClauses);
+	} else { /* Constant one */
+	 BmcCnfGenerateClausesForOR(thenIndex, -varIndex, nodeIndex, cnfClauses);
+	}
+      } else {
+	flag = st_lookup_int(bddToCnfIndexTable, bdd_regular(thenNode), &thenIndex);
+	if(flag == 0){
+	  thenIndex = BmcGenerateCnfFormulaForBddOffSet(bdd_construct_bdd_t(bddManager, bdd_regular(thenNode)), k, cnfClauses);
+	  st_insert(bddToCnfIndexTable, (char *) (long) bdd_regular(thenNode),  (char *) (long)thenIndex);
+	}
+        /*assert(flag);*/
+	
+	flag = st_lookup_int(bddToCnfIndexTable, bdd_regular(elseNode), &elseIndex);
+	if(flag == 0){
+	  elseIndex = BmcGenerateCnfFormulaForBddOffSet( bdd_construct_bdd_t(bddManager, bdd_regular(elseNode)), k, cnfClauses);
+	  st_insert(bddToCnfIndexTable, (char *) (long) bdd_regular(elseNode),  (char *)(long) elseIndex);
+	}
+        /*assert(flag);*/
+	/*
+	  test if the elseNode is complemented arc?
+	*/
+	if (bdd_is_complement(elseNode)){
+	  elseIndex = -1*elseIndex;
+	}      
+	tmpClause = array_alloc(int, 3);
+
+	assert(abs(thenIndex) <= cnfClauses->cnfGlobalIndex);
+	assert(abs(varIndex) <= cnfClauses->cnfGlobalIndex);
+	assert(abs(nodeIndex) <= cnfClauses->cnfGlobalIndex);
+	  
+	array_insert(int, tmpClause, 0, -thenIndex);
+	array_insert(int, tmpClause, 1, -varIndex);
+	array_insert(int, tmpClause, 2, nodeIndex);
+	BmcCnfInsertClause(cnfClauses, tmpClause);
+	
+	array_insert(int, tmpClause, 0, thenIndex);
+	array_insert(int, tmpClause, 1, -varIndex);
+	array_insert(int, tmpClause, 2, -nodeIndex);
+	BmcCnfInsertClause(cnfClauses, tmpClause);
+	
+	array_insert(int, tmpClause, 0, -elseIndex);
+	array_insert(int, tmpClause, 1, varIndex);
+	array_insert(int, tmpClause, 2, nodeIndex);
+	BmcCnfInsertClause(cnfClauses, tmpClause);
+	
+	array_insert(int, tmpClause, 0, elseIndex);
+	array_insert(int, tmpClause, 1, varIndex);
+	array_insert(int, tmpClause, 2, -nodeIndex);
+	BmcCnfInsertClause(cnfClauses, tmpClause);  
+	
+	array_free(tmpClause);
+      }
+    }
+    st_insert(bddToCnfIndexTable, (char *) (long) bdd_regular(node),  (char *) (long) nodeIndex);
+  } /* foreach_bdd_node() */
+  st_free_table(bddToCnfIndexTable);
+  return (is_complemented? -nodeIndex: nodeIndex);
+} /* BmcGenerateCnfFormulaForBdd() */
+
+
+
+/**Function********************************************************************
+
+  Synopsis [Generate CNF for bdd function based on the off set of the
+  bdd function]
+
+  Description [Express the negation of bdd function in disjunctive
+  normal form(DNF), and generate a clause for each disjunct in the
+  DNF.]
+  
+  SideEffects []
+
+  SeeAlso     []
+  
+******************************************************************************/
+int 
+BmcGenerateCnfFormulaForBddOffSet(
+   bdd_t          *bddFunction,
+   int             k,
+   BmcCnfClauses_t *cnfClauses)
+{
+  bdd_manager *bddManager = bdd_get_manager(bddFunction);
+  bdd_node    *node, *funcNode;
+  int         is_complemented;
+  bdd_gen     *gen;
+  int         varIndex; 
+  array_t     *tmpClause;
+  array_t     *cube;
+  int         i, value;
+  bdd_t       *newVar;
+  
+  if (bddFunction == NULL){
+    return 0;
+  }
+  /*
+    Because the top node of bddFunction represents a variable in
+    bddFunction, newVar is used to represent the function of
+    bddFunction.  Setting the cnfIndex of newVar to 1(0) is like
+    setting the function of bddFunction to 1(0).
+  */
+  newVar = bdd_create_variable(bddManager);
+  bddFunction = bdd_xnor(newVar, bddFunction);
+  funcNode = bdd_get_node(bddFunction, &is_complemented);
+  if (bdd_is_constant(funcNode)){
+    if (is_complemented){
+      /* add an empty clause to indicate FALSE (un-satisfiable)*/
+      BmcAddEmptyClause(cnfClauses);
+    }
+    return 0;
+  }
+  bddFunction = bdd_not(bddFunction);
+
+  foreach_bdd_cube(bddFunction, gen, cube){
+    tmpClause = array_alloc(int,0);
+    arrayForEachItem(int, cube, i, value) {
+      if (value != 2){
+	node = bdd_bdd_ith_var(bddManager, i);
+	varIndex  = BmcGetCnfVarIndexForBddNode(bddManager, bdd_regular(node), k, cnfClauses);
+	if (value == 1){
+	  varIndex = -varIndex; 
+	}
+	array_insert_last(int, tmpClause, varIndex);
+      }
+    }
+    BmcCnfInsertClause(cnfClauses, tmpClause);
+    array_free(tmpClause);
+  }/* foreach_bdd_cube() */
+  varIndex  = BmcGetCnfVarIndexForBddNode(bddManager,
+				       bdd_regular(bdd_get_node(newVar, &is_complemented)),
+				       k, cnfClauses);
+  return (varIndex);
+} /* BmcGenerateCnfFormulaForBddOffSet() */
+
+#if 0
+/**Function********************************************************************
+
+  Synopsis    [Generate the CNF formula of a given function represented by
+               AND/INVERTER graph]
+
+  Description [Generate an array of clausese for a function represented in
+  AND/INVERETER graph structure. 
+  
+  the CNF formula of node to the output file specifies by cnfFile.
+               It stores CNF index for each node in the cnfIndexTable. The generated CNF
+               is in dimacs format.
+	       It is an error to call this function on a constand zero/one node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+BmcGenerateCnfForAigFunction(
+   bAig_Manager_t  *manager,
+   Ntk_Network_t   *network,
+   bAigEdge_t      node,
+   int             k,
+   BmcCnfClauses_t *cnfClauses)
+{
+  int        leftIndex, rightIndex, nodeIndex;
+  array_t    *clause;
+
+  if(bAig_IsInverted(node)){
+    /*
+      The generated clauses are in dimacs formate that uses negative number to indicate complement
+     */
+    return -1*BmcGenerateCnfFormulaForAigFunction(manager, bAig_NonInvertedEdge(node), k, cnfClauses);
+  }
+  {
+    char *name   = bAig_NodeReadName(manager, node);
+    char *found  = strchr(name, '=');
+    
+    if (found != NIL(char)){
+      int value = atoi(found+1);
+      int length = found-name;
+      char toName[length+1];
+      Ntk_Node_t *node;
+      
+      toName[length] = '\0';
+      strncpy(toName, name, length);
+      node = Ntk_NetworkFindNodeByName(network, toName);
+      if ((node != NIL( Ntk_Node_t)) && Ntk_NodeTestIsLatch(node)){
+	MvfAig_Function_t  *tmpMvfAig;
+	st_table *nodeToMvfAigTable = (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+	bAigEdge_t mAigNode;
+
+	if (nodeToMvfAigTable == NIL(st_table)){
+	  (void) fprintf(vis_stderr, "bmc error: please run build_partiton_maigs first");
+	  return mAig_NULL;
+	}
+	if (k==0){
+	  node = Ntk_LatchReadInitialInput(node);
+	} else {
+	  node = Ntk_LatchReadDataInput(node);
+	  k--;
+	}
+	tmpMvfAig = Bmc_ReadMvfAig(node, nodeToMvfAigTable);
+	if (tmpMvfAig ==  NIL(MvfAig_Function_t)){
+          tmpMvfAig = Bmc_NodeBuildMVF(network, node);
+	  array_free(tmpMvfAig);
+	  tmpMvfAig = Bmc_ReadMvfAig(node, nodeToMvfAigTable);
+	}
+	mAigNode = MvfAig_FunctionReadComponent(tmpMvfAig, value);
+	BmcGenerateCnfForAigFunction(manager, network, mAigNode, k, cnfClauses);
+      }
+    }
+  }
+  if (BmcCnfReadOrInsertNode(cnfClauses, bAig_NodeReadName(manager, node), k, &nodeIndex)){
+    return nodeIndex;
+  }
+  if (bAig_isVarNode(manager, node)){
+    return nodeIndex;
+  }
+  leftIndex  = BmcGenerateCnfForAigFunction(manager, network, leftChild(node),  k, cnfClauses);
+  rightIndex = BmcGenerateCnfForAigFunction(manager, network, rightChild(node), k, cnfClauses);
+ 
+  clause  = array_alloc(int, 3);
+  array_insert(int, clause, 0, -leftIndex );
+  array_insert(int, clause, 1, -rightIndex);
+  array_insert(int, clause, 2,  nodeIndex );
+  BmcCnfInsertClause(cnfClauses, clause);
+  array_free(clause);
+  
+  clause  = array_alloc(int, 2);
+  array_insert(int, clause, 0,  leftIndex);
+  array_insert(int, clause, 1, -nodeIndex);
+  BmcCnfInsertClause(cnfClauses, clause);
+  array_free(clause);
+  
+  clause  = array_alloc(int, 2);
+  array_insert(int, clause, 0,  rightIndex);
+  array_insert(int, clause, 1, -nodeIndex);
+  BmcCnfInsertClause(cnfClauses, clause);  
+  array_free(clause);
+
+  return(nodeIndex);
+
+}
+#endif
+/**Function********************************************************************
+
+  Synopsis [
+               c = a <-> b = (a=0)*(b=0) + (a=1)*(b=1) ....
+           For a given term (a=i)*(b=i), if either is Zero,  don't generate
+	                                 clauses for this term.
+	                                 if both are One, don't generate clauses
+					 for c.
+  ]
+
+  SideEffects []
+
+******************************************************************************/
+void
+BmcGenerateClausesFromStateTostate(
+   bAig_Manager_t  *manager,
+   bAigEdge_t      *fromAigArray,
+   bAigEdge_t      *toAigArray,
+   int             mvfSize, 
+   int             fromState,
+   int             toState,
+   BmcCnfClauses_t *cnfClauses,
+   int             outIndex) 
+{
+  array_t    *clause, *tmpclause;
+  int        toIndex, fromIndex, cnfIndex;
+  int        i;
+
+  /* used to turn off the warning messages: might be left uninitialized.
+     We are sure that these two variables will not be used uninitialized.
+  */
+  toIndex =0;
+  fromIndex = 0;
+  
+  for(i=0; i< mvfSize; i++){
+    if ((fromAigArray[i] == bAig_One) && (toAigArray[i] == bAig_One)){
+      return;   /* the clause is always true */
+    }
+  }
+  clause  = array_alloc(int, 0);
+  for(i=0; i< mvfSize; i++){
+    if ((fromAigArray[i] != bAig_Zero) && (toAigArray[i] != bAig_Zero)){
+      if (toAigArray[i] != bAig_One){ 
+         /* to State */
+
+         toIndex = BmcGenerateCnfFormulaForAigFunction(manager,toAigArray[i],
+						       toState,cnfClauses);
+      }
+      if (fromAigArray[i] != bAig_One){ 
+         /* from State */
+         fromIndex = BmcGenerateCnfFormulaForAigFunction(manager,
+							 fromAigArray[i],
+							 fromState,
+							 cnfClauses);
+      }
+     /*
+      Create new var for the output of this node. We don't create variable for this node, we only
+      use its index number.
+     */
+     cnfIndex = cnfClauses->cnfGlobalIndex++;  /* index of the output of the OR of T(from, to) */
+     
+     assert(abs(cnfIndex) <= cnfClauses->cnfGlobalIndex);
+     assert(abs(fromIndex) <= cnfClauses->cnfGlobalIndex);
+     assert(abs(toIndex) <= cnfClauses->cnfGlobalIndex);
+     
+     if (toAigArray[i] == bAig_One){       
+       tmpclause  = array_alloc(int, 2);
+       array_insert(int, tmpclause, 0, -fromIndex);
+       array_insert(int, tmpclause, 1, cnfIndex);
+       BmcCnfInsertClause(cnfClauses, tmpclause);
+       array_free(tmpclause); 
+
+       tmpclause  = array_alloc(int, 2);
+       array_insert(int, tmpclause, 0, fromIndex);
+       array_insert(int, tmpclause, 1, -cnfIndex);
+       BmcCnfInsertClause(cnfClauses, tmpclause);
+       array_free(tmpclause);       
+
+     } else if (fromAigArray[i] == bAig_One){
+       tmpclause  = array_alloc(int, 2);
+       array_insert(int, tmpclause, 0, -toIndex);
+       array_insert(int, tmpclause, 1, cnfIndex);
+       BmcCnfInsertClause(cnfClauses, tmpclause);
+       array_free(tmpclause);
+
+       tmpclause  = array_alloc(int, 2);
+       array_insert(int, tmpclause, 0, toIndex);
+       array_insert(int, tmpclause, 1, -cnfIndex);
+       BmcCnfInsertClause(cnfClauses, tmpclause);
+       array_free(tmpclause);
+       
+     } else {
+       tmpclause  = array_alloc(int, 3);
+       array_insert(int, tmpclause, 0, -toIndex);
+       array_insert(int, tmpclause, 1, -fromIndex);
+       array_insert(int, tmpclause, 2,  cnfIndex);
+       BmcCnfInsertClause(cnfClauses, tmpclause);
+       array_free(tmpclause);
+
+       tmpclause  = array_alloc(int, 2);
+       array_insert(int, tmpclause, 0, toIndex);
+       array_insert(int, tmpclause, 1, -cnfIndex);
+       BmcCnfInsertClause(cnfClauses, tmpclause);
+       array_free(tmpclause);
+
+       tmpclause  = array_alloc(int, 2);
+       array_insert(int, tmpclause, 0, fromIndex);
+       array_insert(int, tmpclause, 1, -cnfIndex);
+       BmcCnfInsertClause(cnfClauses, tmpclause);
+       array_free(tmpclause);
+     }
+     array_insert_last(int, clause, cnfIndex);
+    } /* if */
+  } /* for i loop */
+  if (outIndex != 0 ){
+    array_insert_last(int, clause, -outIndex);
+  }
+  BmcCnfInsertClause(cnfClauses, clause);
+  array_free(clause);
+  
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Write the set of clauses in diamacs format to the output file.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+BmcWriteClauses(
+   mAig_Manager_t  *maigManager,
+   FILE            *cnfFile,
+   BmcCnfClauses_t *cnfClauses,
+   BmcOption_t     *options)
+{
+  st_generator *stGen;
+  char         *name;
+  int          cnfIndex, i, k;
+
+  if (options->verbosityLevel == BmcVerbosityMax_c) {      
+    fprintf(vis_stdout,
+	    "Number of Variables = %d Number of Clauses = %d\n",
+	    cnfClauses->cnfGlobalIndex-1,  cnfClauses->noOfClauses);
+  }
+  st_foreach_item_int(cnfClauses->cnfIndexTable, stGen, &name, &cnfIndex) {
+    fprintf(cnfFile, "c %s %d\n",name, cnfIndex);
+  }
+  (void) fprintf(cnfFile, "p cnf %d %d\n", cnfClauses->cnfGlobalIndex-1,
+		 cnfClauses->noOfClauses);
+  if (cnfClauses->clauseArray != NIL(array_t)) {
+    for (i = 0; i < cnfClauses->nextIndex; i++) {
+      k = array_fetch(int, cnfClauses->clauseArray, i);
+      (void) fprintf(cnfFile, "%d%c", k, (k == 0) ? '\n' : ' ');
+    }
+  }
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Check the satisfiability of CNF formula written in file]
+
+  Description [Run SAT solver on input file]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+BmcCheckSAT(BmcOption_t *options)
+{
+  array_t     *result = NIL(array_t);
+  
+
+  if(options->satSolver == cusp){
+    result = BmcCallCusp(options);
+  }
+  if(options->satSolver == CirCUs){
+    result = BmcCallCirCUs(options);
+  }
+  /* Adjust alarm if timeout in effect.  This is necessary because the
+   * alarm may have gone off while the SAT solver is running.  Since
+   * the CPU time of a child process is charged to the parent only when
+   * the child terminates, the SIGALRM handler assumes that more time
+   * is left than it is in reality.  We could do this adjustment right
+   * after calling the SAT solver, but we prefer to give ourselves the
+   * extra time to report the result even if this means using more time
+   * than we are allotted.
+   */
+  if (options->timeOutPeriod > 0) {
+    int residualTime = options->timeOutPeriod -
+      (util_cpu_ctime() - options->startTime) / 1000;
+    /* Make sure we do not cancel the alarm if no time is left. */
+    if (residualTime <= 0) {
+      residualTime = 1;
+    }
+    (void) alarm(residualTime);
+  }
+
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Check the satisfiability of CNF formula written in file]
+
+  Description [Run CirCUs on input file]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+BmcCallCirCUs(
+  BmcOption_t *options)
+{
+  satOption_t  *satOption;
+  array_t      *result = NIL(array_t);
+  satManager_t *cm;
+  int          maxSize;
+
+  satOption = sat_InitOption();
+  satOption->verbose = options->verbosityLevel;
+    satOption->verbose = 0;
+  
+  cm = sat_InitManager(0);
+  cm->comment = ALLOC(char, 2);
+  cm->comment[0] = ' ';
+  cm->comment[1] = '\0';
+  cm->stdOut = stdout;
+  cm->stdErr = stderr;
+
+  cm->option = satOption;
+  cm->each = sat_InitStatistics();
+
+  cm->unitLits = sat_ArrayAlloc(16);
+  cm->pureLits = sat_ArrayAlloc(16);
+
+  maxSize = 10000 << (bAigNodeSize-4);
+  cm->nodesArray = ALLOC(bAigEdge_t, maxSize);
+  cm->maxNodesArraySize = maxSize;
+  cm->nodesArraySize = bAigNodeSize;
+
+  sat_AllocLiteralsDB(cm);
+
+  sat_ReadCNF(cm, options->satInFile);
+
+  if (options->verbosityLevel == BmcVerbosityMax_c) {
+    (void)fprintf(vis_stdout,"Calling SAT solver (CirCUs) ...");
+    (void) fflush(vis_stdout);
+  }
+  sat_Main(cm);
+  if (options->verbosityLevel == BmcVerbosityMax_c) {
+    (void) fprintf(vis_stdout," done ");
+    (void) fprintf(vis_stdout, "(%g s)\n", cm->each->satTime);
+  }
+  if(cm->status == SAT_UNSAT) {
+    if (options->verbosityLevel != BmcVerbosityNone_c){
+      (void) fprintf(vis_stdout, "# SAT: Counterexample not found\n");
+      
+    }
+    fflush(cm->stdOut);
+  } else if(cm->status == SAT_SAT) {
+    if (options->verbosityLevel != BmcVerbosityNone_c){
+      (void) fprintf(vis_stdout, "# SAT: Counterexample found\n");
+    }
+    if (options->verbosityLevel == BmcVerbosityMax_c){
+      sat_ReportStatistics(cm, cm->each);
+    }
+    fflush(cm->stdOut);
+    result = array_alloc(int, 0);
+    {
+      int i, size, value;
+      
+      size = cm->initNumVariables * bAigNodeSize;
+      for(i=bAigNodeSize; i<=size; i+=bAigNodeSize) {
+	value = SATvalue(i);
+	if(value == 1) {
+	  array_insert_last(int, result, SATnodeID(i));
+	}
+	else if(value == 0) {
+	  array_insert_last(int, result, -(SATnodeID(i)));
+	}
+      }
+    }
+  }
+  //Bing: To avoid SEVERE memory leakage
+  FREE(cm->nodesArray);
+  
+  sat_FreeManager(cm);
+
+  return result;
+} /* BmcCallCirCUs */
+
+/**Function********************************************************************
+
+  Synopsis [Check the satisfiability of CNF formula written in file]
+
+  Description [Run external solver on input file]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+BmcCallCusp(BmcOption_t *options)
+{
+  FILE        *fp;
+  static char parseBuffer[1024];
+  int         satStatus;
+  char        line[MAX_LENGTH];
+  int         num = 0;
+  array_t     *result = NIL(array_t);
+  char        *tmpStr, *tmpStr1, *tmpStr2;
+  long        solverStart;
+  int         satTimeOutPeriod = 0;
+
+  strcpy(parseBuffer,"cusp -distill -velim -cnf ");
+  options->satSolverError = FALSE;  /* assume no error*/
+  if (options->timeOutPeriod > 0) {
+    /* Compute the residual CPU time and subtract a little time to
+       give vis a chance to clean up before its own time out expires.
+    */
+    satTimeOutPeriod = options->timeOutPeriod - 1 -
+      (util_cpu_ctime() - options->startTime) / 1000;
+    if (satTimeOutPeriod <= 0){ /* no time left to run SAT solver*/
+      options->satSolverError=TRUE;
+      return NIL(array_t);
+    }
+    tmpStr2 = util_inttostr(satTimeOutPeriod);
+    tmpStr1 = util_strcat3(options->satInFile," -t ", tmpStr2);
+    tmpStr = util_strcat3(tmpStr1, " >", options->satOutFile);
+    FREE(tmpStr1);
+    FREE(tmpStr2);
+  } else {
+    tmpStr = util_strcat3(options->satInFile, " >", options->satOutFile);
+  }
+  strcat(parseBuffer, tmpStr);
+  FREE(tmpStr);
+  
+  if (options->verbosityLevel == BmcVerbosityMax_c) {
+    (void)fprintf(vis_stdout,"Calling SAT solver (cusp) ...");
+    (void) fflush(vis_stdout);
+    solverStart = util_cpu_ctime();
+  } else { /* to remove uninitialized variables warning */
+    solverStart = 0;
+  }
+  /* Call Sat Solver*/
+  satStatus = system(parseBuffer);
+  if (satStatus != 0){
+    (void) fprintf(vis_stderr, "Can't run cusp. It may not be in your path. Status = %d\n", satStatus);
+    options->satSolverError = TRUE;
+    return NIL(array_t);
+  }
+  
+  if (options->verbosityLevel == BmcVerbosityMax_c) {
+    (void) fprintf(vis_stdout," done ");
+    (void) fprintf(vis_stdout, "(%g s)\n",
+		   (double) (util_cpu_ctime() - solverStart)/1000.0);
+  }
+  fp = Cmd_FileOpen(options->satOutFile, "r", NIL(char *), 0);
+  if (fp == NIL(FILE)) {
+    (void) fprintf(vis_stderr, "** bmc error: Cannot open the file %s\n",
+		   options->satOutFile);
+    options->satSolverError = TRUE;
+    return NIL(array_t);
+  }
+  /* Skip the lines until the result */
+  while(1) {
+    if (fgets(line, MAX_LENGTH - 1, fp) == NULL) break;
+    if(strstr(line,"UNSATISFIABLE") ||
+       strstr(line,"SATISFIABLE") ||
+       strstr(line,"MEMOUT") ||
+       strstr(line,"TIMEOUT"))
+      break;
+  }
+
+  if(strstr(line,"UNSATISFIABLE") != NIL(char)) {
+    if (options->verbosityLevel != BmcVerbosityNone_c){
+      (void) fprintf(vis_stdout, "# SAT: Counterexample not found\n");
+      
+    }
+  } else if(strstr(line,"SATISFIABLE") != NIL(char)) {
+    if (options->verbosityLevel != BmcVerbosityNone_c){
+      (void) fprintf(vis_stdout, "# SAT: Counterexample found\n");
+    }
+    /* Skip the initial v of the result line */
+    result = array_alloc(int, 0);
+    while (fgets(line, MAX_LENGTH - 1, fp) != NULL) {
+      char *word;
+      if (line[0] != 'v') {
+	(void) fprintf(vis_stderr,
+		       "** bmc error: Cannot find assignment in file %s\n",
+		       options->satOutFile);
+	options->satSolverError = TRUE;
+	return NIL(array_t);
+      }
+      word = strtok(&(line[1])," \n");
+      while (word != NIL(char)) {
+	num = atoi(word);
+	if (num == 0) break;
+	array_insert_last(int, result, num);
+	word = strtok(NIL(char)," \n");
+      }
+      if (num == 0) break;
+    }
+  } else if(strstr(line,"MEMOUT") != NIL(char)) {
+    (void) fprintf(vis_stdout,"# SAT: SAT Solver Memory out\n");
+    options->satSolverError = TRUE;
+  } else if(strstr(line,"TIMEOUT") != NIL(char)) {
+    (void) fprintf(vis_stdout,
+		   "# SAT: SAT Solver Time out occurred after %d seconds.\n",
+		   satTimeOutPeriod);
+    options->satSolverError = TRUE;
+  } else {
+    (void) fprintf(vis_stdout, "# SAT: SAT Solver failed, try again\n");
+    options->satSolverError = TRUE;
+  }
+  (void) fflush(vis_stdout);
+  (void) fclose(fp);
+
+  return result;
+} /* BmcCallCusp */
+
+
+/**Function********************************************************************
+
+  Synopsis [Print CounterExample.]
+
+  SideEffects [Print a counterexample that was returned from the SAT
+  solver in term of an array of integer "result". The counterexample
+  starts from state 0 and of lenght eqaual to "length". If loopClause
+  is not empty, this function print a loopback from the last state to
+  a state in loopClause that exist in "result".]
+
+******************************************************************************/
+void
+BmcPrintCounterExample(
+  Ntk_Network_t   *network,
+  st_table        *nodeToMvfAigTable,
+  BmcCnfClauses_t *cnfClauses,
+  array_t         *result,
+  int             length,
+  st_table        *CoiTable,
+  BmcOption_t     *options,
+  array_t         *loopClause)
+{
+  mAig_Manager_t    *manager = Ntk_NetworkReadMAigManager(network);
+  lsGen             gen;
+  st_generator      *stGen;
+  Ntk_Node_t        *node;
+  int               k;
+  array_t           *latches = array_alloc(int, 0);
+  int               *prevValueLatches;
+  array_t           *inputs  = array_alloc(int, 0);
+  int               *prevValueInputs;
+  int               tmp;
+  int               loop;
+  st_table	    *resultTable = st_init_table(st_numcmp, st_numhash);
+
+  /*
+    Initialize resultTable from the result to speed up the search in the result array.
+   */
+  for(k=0; k< array_n(result); k++){
+    st_insert(resultTable, (char *) (long) array_fetch(int, result, k),  (char *) 0);
+  }
+  /* sort latches by name */
+  st_foreach_item(CoiTable, stGen, &node, NULL) {
+      array_insert_last(char*, latches, Ntk_NodeReadName(node));
+  }
+  array_sort(latches, nameCompare);
+  /*
+    Use to store the last value of each latch. If the current value of a latch
+    differs from its corresponding value in this array, we will print the new values.
+   */
+  prevValueLatches = ALLOC(int, array_n(latches));
+  prevValueInputs = 0;
+  if(options->printInputs == TRUE){
+    /* sort inputs by name */
+    Ntk_NetworkForEachInput(network, gen, node){
+      array_insert_last(char*, inputs, Ntk_NodeReadName(node));
+    }
+    array_sort(inputs, nameCompare);
+    prevValueInputs = ALLOC(int, array_n(inputs));
+  }
+  loop = -1; /* no loop back */
+  if(loopClause != NIL(array_t)){
+    for(k=0; k < array_n(loopClause); k++){
+      /*  if (searchArray(result, array_fetch(int, loopClause, k)) > -1){ */
+      if (st_lookup_int(resultTable, (char *)(long)array_fetch(int, loopClause, k), &tmp)){
+	loop = k;
+	break;
+      }
+    }
+  }
+  /*
+  Ntk_NetworkForEachPrimaryOutput(network, gen, node){
+    array_insert_last(char*, outputs, Ntk_NodeReadName(node));
+  }
+  array_sort(outputs, nameCompare);
+  */
+  for (k=0; k<= length; k++){
+    if (k == 0){
+      (void) fprintf(vis_stdout, "\n--State %d:\n", k);
+    } else {
+      (void) fprintf(vis_stdout, "\n--Goes to state %d:\n", k);
+    }
+    /*
+      Print the current values of the latches if they are different form their
+      previous values.
+     */
+    printValue(manager, network, nodeToMvfAigTable, cnfClauses,
+	       latches, resultTable,  k, prevValueLatches);  
+#if 0
+    (void) fprintf(vis_stdout, "--Primary output:\n");
+    printValue(manager, network, nodeToMvfAigTable, cnfClauses, outputs, result, k);
+#endif
+    if((options->printInputs == TRUE) && (k !=0)) {
+      (void) fprintf(vis_stdout, "--On input:\n");
+      printValue(manager, network, nodeToMvfAigTable, cnfClauses,
+		 inputs, resultTable,   k-1, prevValueInputs);   
+    }
+  } /* for k loop */
+  if(loop != -1){
+    (void) fprintf(vis_stdout, "\n--Goes back to state %d:\n", loop);
+    printValue(manager, network, nodeToMvfAigTable, cnfClauses,
+	       latches, resultTable,  loop, prevValueLatches);
+    if((options->printInputs == TRUE)) {
+      (void) fprintf(vis_stdout, "--On input:\n");
+      printValue(manager, network, nodeToMvfAigTable, cnfClauses,
+		 inputs, resultTable, length, prevValueInputs);   
+    }
+  }
+  array_free(latches);
+  FREE(prevValueLatches);
+  if(options->printInputs == TRUE){
+    array_free(inputs);
+    FREE(prevValueInputs);
+  }
+  st_free_table(resultTable);
+  return;
+} /* BmcPrintCounterExample() */
+
+/**Function********************************************************************
+
+  Synopsis [Print CounterExample in Aiger format.]
+
+  SideEffects [Print a counterexample that was returned from the SAT
+  solver in term of an array of integer "result". The counterexample
+  starts from state 0 and of lenght eqaual to "length". If loopClause
+  is not empty, this function print a loopback from the last state to
+  a state in loopClause that exist in "result".]
+
+******************************************************************************/
+void
+BmcPrintCounterExampleAiger(
+  Ntk_Network_t   *network,
+  st_table        *nodeToMvfAigTable,
+  BmcCnfClauses_t *cnfClauses,
+  array_t         *result,
+  int             length,
+  st_table        *CoiTable,
+  BmcOption_t     *options,
+  array_t         *loopClause)
+{
+  mAig_Manager_t    *manager = Ntk_NetworkReadMAigManager(network);
+  lsGen             gen;
+  st_generator      *stGen;
+  Ntk_Node_t        *node;
+  int               k;
+  array_t           *latches = array_alloc(int, 0);
+  int               *prevValueLatches;
+  array_t           *inputs  = array_alloc(int, 0);
+  array_t	    *outputs = array_alloc(int, 0);
+  int               *prevValueInputs;
+  int               *prevValueOutputs;
+  int               tmp;
+  int               loop;
+  st_table	    *resultTable = st_init_table(st_numcmp, st_numhash);
+  char		    *nodeName;
+
+  /*
+    Initialize resultTable from the result to speed up the search in the result array.
+   */
+  for(k=0; k< array_n(result); k++){
+    st_insert(resultTable, (char *) (long) array_fetch(int, result, k),  (char *) 0);
+  }
+  /* sort latches by name */
+  st_foreach_item(CoiTable, stGen, &node, NULL) {
+      array_insert_last(char*, latches, Ntk_NodeReadName(node));
+  }
+  /*
+    Use to store the last value of each latch. If the current value of a latch
+    differs from its corresponding value in this array, we will print the new values.
+   */
+
+  /* the file generation needs to be removed for final vis release */
+
+  FILE *order = Cmd_FileOpen("inputOrder.txt", "w", NIL(char *), 0);
+  for (k=0; k< array_n(latches); k++)
+  {
+    nodeName = array_fetch(char *, latches, k);
+    if((nodeName[0] == '$') && (nodeName[1] == '_'))
+    {
+      fprintf(order, "%s\n", &nodeName[2]);
+    }
+  }
+  fclose(order);
+
+  prevValueLatches = ALLOC(int, array_n(latches));
+  Ntk_NetworkForEachInput(network, gen, node){
+    array_insert_last(char*, inputs, Ntk_NodeReadName(node));
+  }
+
+  prevValueInputs = ALLOC(int, array_n(inputs));
+  loop = -1; /* no loop back */
+  if(loopClause != NIL(array_t)){
+    for(k=0; k < array_n(loopClause); k++){
+      /*  if (searchArray(result, array_fetch(int, loopClause, k)) > -1){ */
+      if (st_lookup_int(resultTable, (char *)(long)array_fetch(int, loopClause, k), &tmp)){
+	loop = k;
+	break;
+      }
+    }
+  }
+ 
+  Ntk_NetworkForEachPrimaryOutput(network, gen, node){
+    array_insert_last(char*, outputs, Ntk_NodeReadName(node));
+  }
+  prevValueOutputs = ALLOC(int, array_n(outputs));
+
+  for (k=0; k< length; k++){
+    /* This will print latches whose name doesn't start with $_. The latches whose
+       name starts with $_ are latches added to the model by the aigtoblif translator.
+     */
+    printValueAiger(manager, network, nodeToMvfAigTable, cnfClauses,
+	       latches, resultTable,  k, prevValueLatches); 
+    fprintf(vis_stdout, " ");
+#if 0
+    (void) fprintf(vis_stdout, "--Primary output:\n");
+    printValue(manager, network, nodeToMvfAigTable, cnfClauses, outputs, result, k);
+#endif
+
+    if((loop<0)||(k<length))
+    {
+
+      /* we augment the original .mv model with latches in front of inputs and hence
+         instead of inputs we print out the value of latches, this would have to be
+         restored in the final release */
+
+      printValueAigerInputs(manager, network, nodeToMvfAigTable, cnfClauses,
+		 latches, resultTable,   k, prevValueInputs);   
+      fprintf(vis_stdout, " ");
+
+      /* the sat-solver doesn't propagate the values to output so we generate the output
+         1 knowing when ouptut would be 1, we will have to remove this for vis release */
+
+      if((k+1)==length)
+      {
+        fprintf(vis_stdout, "1 ");
+      }
+      else
+      {
+        fprintf(vis_stdout, "0 ");
+      }
+
+      printValueAiger(manager, network, nodeToMvfAigTable, cnfClauses,
+               latches, resultTable,  k+1, prevValueLatches); 
+    }
+    if((loop < 0)||(k!=length))
+    {
+      fprintf(vis_stdout, "\n");
+    }
+
+  } /* for k loop */
+  if(loop != -1){
+    (void) fprintf(vis_stdout, "\n--Goes back to state %d:\n", loop);
+    printValueAiger(manager, network, nodeToMvfAigTable, cnfClauses,
+	       latches, resultTable,  loop, prevValueLatches);
+    (void) fprintf(vis_stdout, "--On input:\n");
+    printValueAiger(manager, network, nodeToMvfAigTable, cnfClauses,
+		 inputs, resultTable, length, prevValueInputs);   
+  }
+  array_free(latches);
+  FREE(prevValueLatches);
+  if(options->printInputs == TRUE){
+    array_free(inputs);
+    FREE(prevValueInputs);
+  }
+  st_free_table(resultTable);
+  return;
+} /* BmcPrintCounterExampleAiger() */
+
+
+/**Function********************************************************************
+
+  Synopsis [Print CounterExample.]
+
+  SideEffects [Print a counterexample that was returned from the SAT
+  solver in term of an array of integer "result". The counterexample
+  starts from state 0 and of lenght eqaual to "length". If loopClause
+  is not empty, this function print a loopback from the last state to
+  a state in loopClause that exist in "result".]
+
+******************************************************************************/
+void
+BmcAutPrintCounterExample(
+  Ntk_Network_t   *network,
+  Ltl_Automaton_t *automaton,
+  st_table        *nodeToMvfAigTable,
+  BmcCnfClauses_t *cnfClauses,
+  array_t         *result,
+  int             length,
+  st_table        *CoiTable,
+  BmcOption_t     *options,
+  array_t         *loopClause)
+{
+  mAig_Manager_t    *manager = Ntk_NetworkReadMAigManager(network);
+  lsGen             gen;
+  st_generator      *stGen;
+  Ntk_Node_t        *node;
+  int               k;
+  array_t           *latches = array_alloc(int, 0);
+  int               *prevValueLatches;
+  array_t           *inputs  = array_alloc(int, 0);
+  int               *prevValueInputs;
+  int               tmp;
+  int               loop;
+  st_table	    *resultTable = st_init_table(st_numcmp, st_numhash);
+
+  /*
+    Initialize resultTable from the result to speed up the search in the result array.
+   */
+  for(k=0; k< array_n(result); k++){
+    st_insert(resultTable, (char *) (long) array_fetch(int, result, k),  (char *) 0);
+  }
+  /* sort latches by name */
+  st_foreach_item(CoiTable, stGen, &node, NULL) {
+      array_insert_last(char*, latches, Ntk_NodeReadName(node));
+  }
+  array_sort(latches, nameCompare);
+  /*
+    Use to store the last value of each latch. If the current value of a latch
+    differs from its corresponding value in this array, we will print the new values.
+   */
+  prevValueLatches = ALLOC(int, array_n(latches));
+  prevValueInputs = 0;
+  if(options->printInputs == TRUE){
+    /* sort inputs by name */
+    Ntk_NetworkForEachInput(network, gen, node){
+      array_insert_last(char*, inputs, Ntk_NodeReadName(node));
+    }
+    array_sort(inputs, nameCompare);
+    prevValueInputs = ALLOC(int, array_n(inputs));
+  }
+  loop = -1; /* no loop back */
+  if(loopClause != NIL(array_t)){
+    for(k=0; k < array_n(loopClause); k++){
+      /*  if (searchArray(result, array_fetch(int, loopClause, k)) > -1){ */
+      if (st_lookup_int(resultTable, (char *)(long)array_fetch(int, loopClause, k), &tmp)){
+	loop = k;
+	break;
+      }
+    }
+  }
+  /*
+  Ntk_NetworkForEachPrimaryOutput(network, gen, node){
+    array_insert_last(char*, outputs, Ntk_NodeReadName(node));
+  }
+  array_sort(outputs, nameCompare);
+  */
+  for (k=0; k<= length; k++){
+    if (k == 0){
+      (void) fprintf(vis_stdout, "\n--State %d:\n", k);
+    } else {
+      (void) fprintf(vis_stdout, "\n--Goes to state %d:\n", k);
+    }
+    /*
+      Print the current values of the latches if they are different form their
+      previous values.
+     */
+    printValue(manager, network, nodeToMvfAigTable, cnfClauses,
+	       latches, resultTable,  k, prevValueLatches);
+
+    {
+      lsGen               lsGen;
+      vertex_t            *vtx;
+      Ltl_AutomatonNode_t *state;
+      int                 stateIndex;
+      bdd_node            *node;
+      int                 is_complemented;
+      
+       
+      foreach_vertex(automaton->G, lsGen, vtx) {
+	state = (Ltl_AutomatonNode_t *) vtx->user_data;
+	
+	node = bdd_get_node(state->Encode, &is_complemented);
+	
+	stateIndex  = state->cnfIndex[k];
+
+
+
+	
+	if (st_lookup_int(resultTable, (char *)(long)stateIndex, &tmp)){
+	  (void) fprintf(vis_stdout,"n%d \n", state->index);
+	}
+      }
+    }
+#if 0
+    (void) fprintf(vis_stdout, "--Primary output:\n");
+    printValue(manager, network, nodeToMvfAigTable, cnfClauses, outputs, result, k);
+#endif
+    if((options->printInputs == TRUE) && (k !=0)) {
+      (void) fprintf(vis_stdout, "--On input:\n");
+      printValue(manager, network, nodeToMvfAigTable, cnfClauses,
+		 inputs, resultTable,   k-1, prevValueInputs);   
+    }
+  } /* for k loop */
+  if(loop != -1){
+    (void) fprintf(vis_stdout, "\n--Goes back to state %d:\n", loop);
+    printValue(manager, network, nodeToMvfAigTable, cnfClauses,
+	       latches, resultTable,  loop, prevValueLatches);
+    if((options->printInputs == TRUE)) {
+      (void) fprintf(vis_stdout, "--On input:\n");
+      printValue(manager, network, nodeToMvfAigTable, cnfClauses,
+		 inputs, resultTable, length, prevValueInputs);   
+    }
+  }
+  array_free(latches);
+  FREE(prevValueLatches);
+  if(options->printInputs == TRUE){
+    array_free(inputs);
+    FREE(prevValueInputs);
+  }
+  st_free_table(resultTable);
+  return;
+} /* BmcPrintCounterExample() */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generate CNF formula for a path from state 'from' to state 'to']
+
+  Description [Unfold the transition relation 'k' states (k = to-from +1), and
+  generate clauses for each state.
+  
+           For a multi-valued latch of 4 vlaues. Two binary variables are used 
+           to rpresent X, x1 and x0. For this latch, there exist three multi-valued 
+           functions.
+           One for the binary reoresentation of the variable. For example the
+           second entry of the mvf = 1, iff ~x1 and x0. 
+           The second mfv is for the data input of the latch. If the And/Inv graph 
+           attached to an entry of this mvf equal to 1, X equal to the binary 
+           representation corresponding to this entry. For example, if the And/
+           INV graph attached to the first entry =1, then X = ~x1 & ~x0. 
+           To generate the CNF to the transition relation, first generate CNF to
+           next state varaible using mvf of the latch.  Then, generate CNF for 
+           latch data input using current state variavles. Finaly, generate CNF
+           for the AND of these two MVF.  This for every entry of the MVF. Then 
+           OR the results.
+           The third MVF is for the initial value of the latch.  It is treat the
+           same as the latch data input except if the initial value is constant. 
+   
+  The initialState value may be either BMC_INITIAL_STATES to generate the clause for the intial states.
+  BMC_NO_INITIAL_STATES otherwise.
+  ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+BmcCnfGenerateClausesForPath(
+   Ntk_Network_t   *network,
+   int             from,
+   int             to,
+   int             initialState,
+   BmcCnfClauses_t *cnfClauses,
+   st_table        *nodeToMvfAigTable,
+   st_table        *CoiTable)
+{
+  mAig_Manager_t  *manager   = Ntk_NetworkReadMAigManager(network);
+  st_generator    *stGen;
+  
+  Ntk_Node_t         *latch, *latchData, *latchInit;
+  MvfAig_Function_t  *initMvfAig, *dataMvfAig, *latchMvfAig;
+  bAigEdge_t         *initBAig, *latchBAig, *dataBAig;
+  
+  int        i, k, mvfSize;
+
+  st_foreach_item(CoiTable, stGen, &latch, NULL) {
+    
+ 
+   latchInit  = Ntk_LatchReadInitialInput(latch);
+   latchData  = Ntk_LatchReadDataInput(latch);
+
+   /* Get the multi-valued function for each node*/
+   initMvfAig = Bmc_ReadMvfAig(latchInit, nodeToMvfAigTable);
+   if (initMvfAig ==  NIL(MvfAig_Function_t)){
+     (void) fprintf(vis_stdout, "No multi-valued function for this node %s \n", Ntk_NodeReadName(latchInit));
+     return;
+   } 
+   dataMvfAig = Bmc_ReadMvfAig(latchData, nodeToMvfAigTable);
+   if (dataMvfAig ==  NIL(MvfAig_Function_t)){
+     (void) fprintf(vis_stdout, "No multi-valued function for this node %s \n", Ntk_NodeReadName(latchData));
+     return;
+   }
+   latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+   if (latchMvfAig ==  NIL(MvfAig_Function_t)){
+     latchMvfAig = Bmc_NodeBuildMVF(network, latch);
+     array_free(latchMvfAig);
+     latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+   }
+      
+   mvfSize   = array_n(initMvfAig);
+   initBAig  = ALLOC(bAigEdge_t, mvfSize);
+   dataBAig  = ALLOC(bAigEdge_t, mvfSize);
+   latchBAig = ALLOC(bAigEdge_t, mvfSize);   
+
+   for(i=0; i< mvfSize; i++){
+     dataBAig[i]  = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(dataMvfAig,  i));
+     latchBAig[i] = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(latchMvfAig, i));
+     initBAig[i]  = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(initMvfAig,  i));
+   }
+   /*
+   if (from == 0){
+   */
+   if (initialState == BMC_INITIAL_STATES){
+   /* Generate the CNF for the initial state of the latch */
+     BmcGenerateClausesFromStateTostate(manager, initBAig, latchBAig, mvfSize, -1, 0, cnfClauses, 0);
+   }
+   /* Generate the CNF for the transition functions */   
+   for (k=from; k < to; k++){
+     BmcGenerateClausesFromStateTostate(manager, dataBAig, latchBAig, mvfSize, k, k+1, cnfClauses, 0);
+   } /* for k state loop */
+
+   FREE(initBAig);
+   FREE(dataBAig);
+   FREE(latchBAig);
+  }/* For each latch loop*/
+  
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Generate CNF formula for a loop-free path]
+
+  Description [This function generates CNF formula for a loop-free path from
+  state fromState to state toState. A loop free path is a path from a state S0
+  to state Sn such that every state in the path is distinct. i.e for all states
+  in the path Si != Sj for 0<= i < j <= n.
+	   
+  The initialState value may be either BMC_INITIAL_STATES to generate the clause
+  for the intial states. BMC_NO_INITIAL_STATES otherwise.
+  ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+BmcCnfGenerateClausesForLoopFreePath(
+   Ntk_Network_t   *network,
+   int             fromState,
+   int             toState,
+   int             initialState,
+   BmcCnfClauses_t *cnfClauses,
+   st_table        *nodeToMvfAigTable,
+   st_table        *CoiTable)
+{
+  int state;
+  
+  /*
+    Generate clauses for a path from fromState to toState.
+  */
+  BmcCnfGenerateClausesForPath(network, fromState, toState, initialState, cnfClauses, nodeToMvfAigTable, CoiTable);
+  
+  /*
+    Restrict the above path to be loop-free path.
+  */
+  /*
+    for(state=0; state< toState; state++){
+  */
+  /*
+    Don't include the last state because we know it is not equal any of the previous states.
+    The property fails at this state, and true at all other states.
+   */
+  /*
+  for(state=1; state < toState; state++){
+  */
+  for(state= fromState + 1; state <= toState; state++){
+    BmcCnfGenerateClausesForNoLoopToAnyPreviouseStates(network, fromState, state, cnfClauses, nodeToMvfAigTable, CoiTable);
+  }
+
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Generate Clauses for no loop from last state to any of the
+  previouse states]
+
+  Description [Generate Clauses for no loop from last state (toState) to
+  any of the previous states starting from fromState. It generates the CNF
+  clauses such that the last state of the path is not equal to any of the
+  path previous states. 
+  ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+BmcCnfGenerateClausesForNoLoopToAnyPreviouseStates(
+   Ntk_Network_t   *network,
+   int             fromState,
+   int             toState,
+   BmcCnfClauses_t *cnfClauses,
+   st_table        *nodeToMvfAigTable,
+   st_table        *CoiTable)
+{
+  mAig_Manager_t  *manager   = Ntk_NetworkReadMAigManager(network);
+  st_generator    *stGen;
+  
+  Ntk_Node_t         *latch;
+  MvfAig_Function_t  *latchMvfAig;
+  bAigEdge_t         *latchBAig;
+  array_t            *orClause;
+  int                lastIndex, prevIndex, andIndex1, andIndex2;  
+  int                i, k, mvfSize;
+
+  /*
+    Generates the clauses to check if the toState is not equal to any previouse states starting
+    from fromState.
+    
+    Assume there are two state varaibles a and b. To check if Si != Sj, we must generate clauses
+    for the formula ( ai != aj + bi != bj). 
+  */
+  for(k=fromState; k < toState; k++){
+    orClause = array_alloc(int,0);
+    st_foreach_item(CoiTable, stGen, &latch, NULL) {
+      
+  
+      latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+      if (latchMvfAig ==  NIL(MvfAig_Function_t)){
+	latchMvfAig = Bmc_NodeBuildMVF(network, latch);
+	array_free(latchMvfAig);
+	latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+      } 
+      mvfSize   = array_n(latchMvfAig);
+      latchBAig = ALLOC(bAigEdge_t, mvfSize);   
+      
+      for(i=0; i< mvfSize; i++){
+	latchBAig[i] = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(latchMvfAig, i));
+      }
+
+      for (i=0; i< mvfSize; i++){
+	prevIndex = BmcGenerateCnfFormulaForAigFunction(manager, latchBAig[i], k       ,cnfClauses);
+	lastIndex = BmcGenerateCnfFormulaForAigFunction(manager, latchBAig[i], toState ,cnfClauses);	 
+	andIndex1 = cnfClauses->cnfGlobalIndex++;
+	BmcCnfGenerateClausesForAND(prevIndex, -lastIndex, andIndex1, cnfClauses);
+	andIndex2 = cnfClauses->cnfGlobalIndex++;
+	BmcCnfGenerateClausesForAND(-prevIndex, lastIndex, andIndex2, cnfClauses);
+
+	array_insert_last(int, orClause, andIndex1);
+	array_insert_last(int, orClause, andIndex2);
+      }
+      FREE(latchBAig);
+    }/* For each latch loop*/
+    BmcCnfInsertClause(cnfClauses, orClause);
+    array_free(orClause);
+  } /* foreach k*/
+  return;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generate Clauses for last state equal to any of the
+  previouse states]
+
+  Description [ Change it!
+  Generate Clauses for no loop from last state (toState) to
+  any of the previous states starting from fromState. It generates the CNF
+  clauses such that the last state of the path is not equal to any of the
+  path previous states. 
+  ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+BmcCnfGenerateClausesForLoopToAnyPreviouseStates(
+   Ntk_Network_t   *network,
+   int             fromState,
+   int             toState,
+   BmcCnfClauses_t *cnfClauses,
+   st_table        *nodeToMvfAigTable,
+   st_table        *CoiTable)
+{
+  mAig_Manager_t  *manager   = Ntk_NetworkReadMAigManager(network);
+  st_generator    *stGen;
+  
+  Ntk_Node_t         *latch;
+  MvfAig_Function_t  *latchMvfAig;
+  bAigEdge_t         *latchBAig;
+  array_t            *orClause;
+  int                lastIndex, prevIndex, andIndex1, andIndex2;  
+  int                i, k, mvfSize;
+
+  /*
+    Generates the clauses to check if the toState is not equal to any previouse states starting
+    from fromState.
+    
+    Assume there are two state varaibles a and b. To check if Si != Sj, we must generate clauses
+    for the formula ( ai != aj + bi != bj). 
+  */
+  for(k=fromState; k < toState; k++){
+    orClause = array_alloc(int,0);
+    st_foreach_item(CoiTable, stGen, &latch, NULL) {
+      
+  
+      latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+      if (latchMvfAig ==  NIL(MvfAig_Function_t)){
+	latchMvfAig = Bmc_NodeBuildMVF(network, latch);
+	array_free(latchMvfAig);
+	latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+      } 
+      mvfSize   = array_n(latchMvfAig);
+      latchBAig = ALLOC(bAigEdge_t, mvfSize);   
+      
+      for(i=0; i< mvfSize; i++){
+	latchBAig[i] = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(latchMvfAig, i));
+      }
+
+      for (i=0; i< mvfSize; i++){
+	prevIndex = BmcGenerateCnfFormulaForAigFunction(manager, latchBAig[i], k       ,cnfClauses);
+	lastIndex = BmcGenerateCnfFormulaForAigFunction(manager, latchBAig[i], toState ,cnfClauses);	 
+	andIndex1 = cnfClauses->cnfGlobalIndex++;
+	BmcCnfGenerateClausesForAND(prevIndex, lastIndex, andIndex1, cnfClauses);
+	andIndex2 = cnfClauses->cnfGlobalIndex++;
+	BmcCnfGenerateClausesForAND(-prevIndex, -lastIndex, andIndex2, cnfClauses);
+
+	array_insert_last(int, orClause, andIndex1);
+	array_insert_last(int, orClause, andIndex2);
+      }
+      FREE(latchBAig);
+    }/* For each latch loop*/
+    BmcCnfInsertClause(cnfClauses, orClause);
+    array_free(orClause);
+  } /* foreach k*/
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Generate CNF formula for a path from state 'from' to state 'to']
+
+  Description [Unfold the transition relation 'k' states (k = to-from +1), and
+  generate clauses for each state.
+           For a multi-valued latch of 4 vlaues. Two binary variables are used 
+           to rpresent X, x1 and x0. For this latch, there exist three multi-valued 
+           functions.
+           One for the binary reoresentation of the variable. For example the
+           second entry of the mvf = 1, iff ~x1 and x0. 
+           The second mfv is for the data input of the latch. If the And/Inv graph 
+           attached to an entry of this mvf equal to 1, X equal to the binary 
+           representation corresponding to this entry. For example, if the And/
+           INV graph attached to the first entry =1, then X = ~x1 & ~x0. 
+           To generate the CNF to the transition relation, first generate CNF to
+           next state varaible using mvf of the latch.  Then, generate CNF for 
+           latch data input using current state variavles. Finaly, generate CNF
+           for the AND of these two MVF.  This for every entry of the MVF. Then 
+           OR the results.
+           The third MVF is for the initial value of the latch.  It is treat the
+           same as the latch data input except if the initial value is constant.         
+           ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+BmcCnfGenerateClausesFromStateToState(
+   Ntk_Network_t   *network,
+   int             from,
+   int             to,
+   BmcCnfClauses_t *cnfClauses,
+   st_table        *nodeToMvfAigTable,
+   st_table        *CoiTable,
+   int             loop)
+{
+  mAig_Manager_t  *manager   = Ntk_NetworkReadMAigManager(network);
+  st_generator    *stGen;
+  Ntk_Node_t         *latch, *latchData;
+  MvfAig_Function_t  *dataMvfAig, *latchMvfAig;
+  bAigEdge_t         *latchBAig, *dataBAig;
+  int        i, mvfSize;
+
+  st_foreach_item(CoiTable, stGen, &latch, NULL) {
+    latchData  = Ntk_LatchReadDataInput(latch);
+    
+    dataMvfAig = Bmc_ReadMvfAig(latchData, nodeToMvfAigTable);
+    if (dataMvfAig ==  NIL(MvfAig_Function_t)){
+      (void) fprintf(vis_stdout,
+		     "No multi-valued function for this node %s \n",
+		     Ntk_NodeReadName(latchData));
+      return;
+    }
+    latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+    if (latchMvfAig ==  NIL(MvfAig_Function_t)){
+      latchMvfAig = Bmc_NodeBuildMVF(network, latch);
+    }
+    mvfSize   = array_n(dataMvfAig);
+    dataBAig  = ALLOC(bAigEdge_t, mvfSize);
+    latchBAig = ALLOC(bAigEdge_t, mvfSize);
+    for(i=0; i< mvfSize; i++){
+      dataBAig[i]  = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(dataMvfAig,  i));
+      latchBAig[i] = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(latchMvfAig, i));
+    }
+    BmcGenerateClausesFromStateTostate(manager, dataBAig, latchBAig, mvfSize,
+				       from, to, cnfClauses, loop);
+    FREE(dataBAig);
+    FREE(latchBAig);
+  } /* For each latch loop*/  
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Generate CNF clauses for the AND gate]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void 
+BmcCnfGenerateClausesForAND(
+   int             a,
+   int             b,
+   int             c,
+   BmcCnfClauses_t *cnfClauses)
+{
+  array_t     *tmpClause;
+    
+  tmpClause = array_alloc(int, 3);
+  array_insert(int, tmpClause, 0, -a);
+  array_insert(int, tmpClause, 1, -b);
+  array_insert(int, tmpClause, 2, c);
+  BmcCnfInsertClause(cnfClauses, tmpClause);
+  array_free(tmpClause);
+  
+  tmpClause = array_alloc(int, 2);
+  
+  array_insert(int, tmpClause, 0, a);
+  array_insert(int, tmpClause, 1, -c);
+  BmcCnfInsertClause(cnfClauses, tmpClause);
+  
+  array_insert(int, tmpClause, 0, b);
+  BmcCnfInsertClause(cnfClauses, tmpClause);
+       
+  array_free(tmpClause);
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Generate CNF clauses for the OR gate]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void 
+BmcCnfGenerateClausesForOR(
+   int             a,
+   int             b,
+   int             c,
+   BmcCnfClauses_t *cnfClauses)
+{
+  array_t     *tmpClause;
+    
+  tmpClause = array_alloc(int, 3);
+  array_insert(int, tmpClause, 0, a);
+  array_insert(int, tmpClause, 1, b);
+  array_insert(int, tmpClause, 2, -c);
+  BmcCnfInsertClause(cnfClauses, tmpClause);
+  array_free(tmpClause);
+  
+  tmpClause = array_alloc(int, 2);
+  array_insert(int, tmpClause, 0, -a);
+  array_insert(int, tmpClause, 1, c);
+  BmcCnfInsertClause(cnfClauses, tmpClause);
+  
+  array_insert(int, tmpClause, 0, -b);
+  BmcCnfInsertClause(cnfClauses, tmpClause);
+       
+  array_free(tmpClause);
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Alloc Memory for BmcCnfClauses_t]
+
+  SideEffects []
+
+  SeeAlso []
+******************************************************************************/
+BmcCnfClauses_t *
+BmcCnfClausesAlloc(void)
+{
+  BmcCnfClauses_t *result = ALLOC(BmcCnfClauses_t, 1);
+  
+  if (!result){
+    return result;
+  }
+  result->clauseArray    = array_alloc(int, 0);
+  result->cnfIndexTable  = st_init_table(strcmp, st_strhash);
+  result->freezedKeys    = array_alloc(nameType_t *, 0);
+  
+  result->nextIndex      = 0;
+  result->noOfClauses    = 0;
+  result->cnfGlobalIndex = 1;  
+  result->emptyClause    = FALSE;
+  result->freezed        = FALSE;
+
+  return result;
+} /*BmcCnfClausesAlloc()*/
+
+/**Function********************************************************************
+
+  Synopsis [Free Memory for BmcCnfClauses_t]
+
+  SideEffects []
+
+  SeeAlso []
+******************************************************************************/
+void 
+BmcCnfClausesFree(
+  BmcCnfClauses_t *cnfClauses)
+{
+  st_generator *stGen;
+  char         *name;
+  int          cnfIndex;
+
+  array_free(cnfClauses->clauseArray);
+  array_free(cnfClauses->freezedKeys);
+
+  if (cnfClauses->cnfIndexTable != NIL(st_table)){
+    st_foreach_item_int(cnfClauses->cnfIndexTable, stGen, (char **) &name, &cnfIndex) {
+      FREE(name);
+    }
+    st_free_table(cnfClauses->cnfIndexTable);
+  }
+  FREE(cnfClauses);
+  cnfClauses = NIL(BmcCnfClauses_t);
+} /* BmcCnfClausesFree() */
+
+/**Function********************************************************************
+
+  Synopsis [Freeze the current state of CNF]
+
+  Description [The current state of CNF is stored in the structure BmcCnfStates_t.
+  This information may use later to store CNF to this state by calling
+  BmcCnfClausesRestore().]
+
+  SideEffects []
+
+  SeeAlso [BmcCnfClausesRestore() BmcCnfClausesUnFreeze() ]
+******************************************************************************/
+BmcCnfStates_t *
+BmcCnfClausesFreeze(
+  BmcCnfClauses_t * cnfClauses)
+{
+  BmcCnfStates_t *state = ALLOC(BmcCnfStates_t, 1);
+
+  state->nextIndex      = cnfClauses->nextIndex;
+  state->noOfClauses    = cnfClauses->noOfClauses;
+  state->cnfGlobalIndex = cnfClauses->cnfGlobalIndex;
+
+  /* This variable is used when deleting any new entries in cnfClauses->freezedKeys
+   that will be added after CNF is freezed.*/
+  state->freezedKeySize = array_n(cnfClauses->freezedKeys);
+  
+  state->emptyClause    = cnfClauses->emptyClause;
+  state->freezed        = cnfClauses->freezed;
+  cnfClauses->freezed   = TRUE;
+  return state;
+} /* mcCnfClausesFreeze() */
+
+/**Function********************************************************************
+
+  Synopsis [Unfreeze CNF]
+
+  Description [Keeps the current state of CNF]
+
+  SideEffects []
+
+  SeeAlso []
+******************************************************************************/
+void 
+BmcCnfClausesUnFreeze(
+  BmcCnfClauses_t *cnfClauses,
+  BmcCnfStates_t  *state)
+{
+  int i;
+
+  cnfClauses->freezed = FALSE;
+  if (array_n(cnfClauses->freezedKeys) != 0){
+    int freezedKeySize = array_n(cnfClauses->freezedKeys);
+    
+    for (i=0; i< (freezedKeySize-state->freezedKeySize); i++){
+      (cnfClauses->freezedKeys)->num--;
+    }
+  }
+} /* BmcCnfClausesUnFreeze() */
+
+/**Function********************************************************************
+
+  Synopsis [Restore the CNF to its previouse state]
+
+  Description [Restore the CNF to its previouse state that CNF was when
+  BmcCnfClausesFreeze() was last called]
+
+  SideEffects []
+  
+  SeeAlso []
+******************************************************************************/
+void 
+BmcCnfClausesRestore(
+  BmcCnfClauses_t *cnfClauses,
+  BmcCnfStates_t  *state)
+{
+  int        i, index;
+  nameType_t *key;
+
+  cnfClauses->nextIndex      = state->nextIndex;
+  cnfClauses->noOfClauses    = state->noOfClauses;
+  cnfClauses->cnfGlobalIndex = state->cnfGlobalIndex;
+  cnfClauses->emptyClause    = state->emptyClause;
+  cnfClauses->freezed        = state->freezed;
+  
+  if (array_n(cnfClauses->freezedKeys) != 0){
+    int freezedKeySize = array_n(cnfClauses->freezedKeys);
+		       
+    for (i=0; i< (freezedKeySize-state->freezedKeySize); i++){
+      key = array_fetch_last(nameType_t *, cnfClauses->freezedKeys);
+      if (st_delete_int(cnfClauses->cnfIndexTable, &key, &index)){
+	FREE(key);
+      } 
+      (cnfClauses->freezedKeys)->num--;
+    }
+  }
+} /* BmcCnfClausesRestore() */
+
+/**Function********************************************************************
+
+  Synopsis [Add clause to the clauseArray]
+
+  Description [Add a clause to the clause array.  clause is of type array_t.
+  The user must free clause.]
+
+  SideEffects []
+  
+  SeeAlso []
+******************************************************************************/
+void 
+BmcCnfInsertClause(
+  BmcCnfClauses_t *cnfClauses,
+  array_t         *clause)
+{
+  int  i, lit;
+
+  if (clause != NIL(array_t)){
+    if (array_n(clause) == 0){ /* empty clause */
+      cnfClauses->emptyClause = TRUE;
+      return;
+    }
+    for (i=0; i< array_n(clause); i++){
+      lit = array_fetch(int, clause, i);
+      array_insert(int, cnfClauses->clauseArray, cnfClauses->nextIndex++, lit);
+    }
+    array_insert(int, cnfClauses->clauseArray, cnfClauses->nextIndex++, 0); /*End Of clause*/
+    cnfClauses->noOfClauses++;
+    cnfClauses->emptyClause = FALSE;
+  }
+  return;
+}/* BmcCnfInsertClause() */
+
+/**Function********************************************************************
+
+  Synopsis [Add an empty clause]
+
+  SideEffects []
+
+  SeeAlso []
+******************************************************************************/
+void
+BmcAddEmptyClause(
+  BmcCnfClauses_t *cnfClauses)
+{
+  cnfClauses->emptyClause = TRUE;
+}/* BmcAddEmptyClause() */
+
+/**Function********************************************************************
+
+  Synopsis [Return the cnfIndex of the node]
+
+  Description [If CNF was generated for this node, return its cnfIndex, otherwise
+  insert the name of this node in the cnfIndexTable, and return its cnfIndex. The
+  key to the cnfIndexTable is (nodeName_state).] 
+
+  SideEffects []
+******************************************************************************/
+int
+BmcCnfReadOrInsertNode(
+   BmcCnfClauses_t *cnfClauses,
+   nameType_t      *nodeName,
+   int             state,
+   int             *nodeIndex)
+{
+  nameType_t *varName;
+  int        index;
+  char       *stateStr = util_inttostr(state);
+
+  varName  = util_strcat3(nodeName, "_", stateStr);
+  FREE(stateStr);
+  if (!st_lookup_int(cnfClauses->cnfIndexTable, varName, &index)) {
+    index = cnfClauses->cnfGlobalIndex++;
+    st_insert(cnfClauses->cnfIndexTable, varName, (char*) (long) index);
+    if(cnfClauses->freezed == TRUE){
+      array_insert_last(nameType_t *, cnfClauses->freezedKeys, varName);
+    }
+    *nodeIndex = index;
+    return 0; /* Inserted */
+  }
+  else { /* The node has been visited */
+    *nodeIndex = index;
+    FREE(varName);
+    return 1;     
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Find the Cone of Influnce (COI) for an LTL formula]
+
+  Description [Return a list of state variables (latches) that are in the COI of the
+  LTL formula.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+BmcGetCoiForLtlFormula(
+  Ntk_Network_t   *network,
+  Ctlsp_Formula_t *formula,
+  st_table        *ltlCoiTable)
+{
+  st_table *visited = st_init_table(st_ptrcmp, st_ptrhash);
+  
+  BmcGetCoiForLtlFormulaRecursive(network, formula, ltlCoiTable, visited);
+  st_free_table(visited);
+  return;
+} /* BmcGetCoiForLtlFormula() */
+
+/**Function********************************************************************
+
+  Synopsis    [Recursive function to find the COI of a network node.]
+
+  Description []
+
+  SideEffects []
+
+******************************************************************************/
+void
+BmcGetCoiForLtlFormulaRecursive(
+  Ntk_Network_t   *network,
+  Ctlsp_Formula_t *formula,
+  st_table        *ltlCoiTable,
+  st_table        *visited)
+{
+  if (formula == NIL(Ctlsp_Formula_t)) {
+    return;
+  }
+  /* leaf node */
+  if (formula->type == Ctlsp_ID_c){
+    char       *name = Ctlsp_FormulaReadVariableName(formula);
+    Ntk_Node_t *node = Ntk_NetworkFindNodeByName(network, name);
+    int        tmp;
+
+    if (st_lookup_int(visited, (char *) node, &tmp)){
+      /* Node already visited */
+      return;
+    }
+    BmcGetCoiForNtkNode(node, ltlCoiTable, visited);
+    return;
+  }
+  BmcGetCoiForLtlFormulaRecursive(network, formula->left,  ltlCoiTable, visited);
+  BmcGetCoiForLtlFormulaRecursive(network, formula->right, ltlCoiTable, visited);
+
+  return;
+} /* BmcGetCoiForLtlFormulaRecursive() */
+
+/**Function********************************************************************
+
+  Synopsis    [Genrate COI for a non-latch network node]
+
+  Description [For each fanins of the given node, if its latch, add it
+  to the CoiTable and return. If it is not latch, call this function to
+  look for any latches in the fanins of this node.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+BmcGetCoiForNtkNode(
+  Ntk_Node_t  *node,
+  st_table    *CoiTable,
+  st_table    *visited)
+{
+  int        i, j;
+  Ntk_Node_t *faninNode;
+
+  if(node == NIL(Ntk_Node_t)){
+    return;
+  }
+  if (st_lookup_int(visited, (char *) node, &j)){
+    /* Node already visited */
+    return;
+  }
+  st_insert(visited, (char *) node, (char *) 0);
+  if (Ntk_NodeTestIsLatch(node)){
+    st_insert(CoiTable, (char *) node, (char *) 0);
+  }
+  Ntk_NodeForEachFanin(node, i, faninNode) {
+    BmcGetCoiForNtkNode(faninNode, CoiTable, visited);
+  }
+  return;
+} /* BmcGetCoiForNtkNode() */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Find Mdd for states satisfying Atomic Formula.]
+
+  Description [An atomic formula defines a set of states in the following
+  way: it states a designated ``net'' (specified by the full path name)
+  takes a certain value. The net should be purely a function of latches;
+  as a result an evaluation of the net yields a set of states.]
+
+  SideEffects []
+
+******************************************************************************/
+
+mdd_t *
+BmcModelCheckAtomicFormula(
+  Fsm_Fsm_t *modelFsm,
+  Ctlsp_Formula_t *ctlFormula)
+{
+  mdd_t * resultMdd;
+  mdd_t *tmpMdd;
+  Ntk_Network_t *network = Fsm_FsmReadNetwork(modelFsm);
+  char *nodeNameString = Ctlsp_FormulaReadVariableName(ctlFormula);
+  char *nodeValueString = Ctlsp_FormulaReadValueName(ctlFormula);
+  Ntk_Node_t *node = Ntk_NetworkFindNodeByName(network, nodeNameString);
+
+  Var_Variable_t *nodeVar;
+  int nodeValue;
+
+  graph_t *modelPartition;
+  vertex_t *partitionVertex;
+  Mvf_Function_t *MVF;
+
+  nodeVar = Ntk_NodeReadVariable(node);
+  if (Var_VariableTestIsSymbolic(nodeVar)) {
+    nodeValue = Var_VariableReadIndexFromSymbolicValue(nodeVar, nodeValueString);
+  }
+  else {
+    nodeValue = atoi(nodeValueString);
+  }
+
+  modelPartition = Part_NetworkReadPartition(network);
+  if (!(partitionVertex = Part_PartitionFindVertexByName(modelPartition,
+							 nodeNameString))) {
+    lsGen tmpGen;
+    Ntk_Node_t *tmpNode;
+    array_t *mvfArray;
+    array_t *tmpRoots = array_alloc(Ntk_Node_t *, 0);
+    st_table *tmpLeaves = st_init_table(st_ptrcmp, st_ptrhash);
+    array_insert_last(Ntk_Node_t *, tmpRoots, node);
+
+    Ntk_NetworkForEachCombInput(network, tmpGen, tmpNode) {
+      st_insert(tmpLeaves, (char *) tmpNode, (char *) NTM_UNUSED);
+    }
+
+    mvfArray =  Ntm_NetworkBuildMvfs(network, tmpRoots, tmpLeaves,
+				      NIL(mdd_t));
+    MVF = array_fetch(Mvf_Function_t *, mvfArray, 0);
+    array_free(tmpRoots);
+    st_free_table(tmpLeaves);
+    array_free(mvfArray);
+
+    tmpMdd = Mvf_FunctionReadComponent(MVF, nodeValue);
+    resultMdd = mdd_dup(tmpMdd);
+    Mvf_FunctionFree(MVF);
+  }
+  else {
+    MVF = Part_VertexReadFunction(partitionVertex);
+    tmpMdd = Mvf_FunctionReadComponent(MVF, nodeValue);
+    resultMdd = mdd_dup(tmpMdd);
+  }
+  if (Part_PartitionReadMethod(modelPartition) == Part_Frontier_c &&
+      Ntk_NodeTestIsCombOutput(node)) {
+    array_t	*psVars = Fsm_FsmReadPresentStateVars(modelFsm);
+    mdd_manager	*mgr = Ntk_NetworkReadMddManager(Fsm_FsmReadNetwork(modelFsm));
+    array_t	*supportList;
+    st_table	*supportTable = st_init_table(st_numcmp, st_numhash);
+    int		i, j;
+    int		existIntermediateVars;
+    int		mddId;
+    Mvf_Function_t	*mvf;
+    vertex_t	*vertex;
+    array_t	*varBddRelationArray, *varArray;
+    mdd_t	*iv, *ivMdd, *relation;
+
+    for (i = 0; i < array_n(psVars); i++) {
+      mddId = array_fetch(int, psVars, i);
+      st_insert(supportTable, (char *)(long)mddId, NULL);
+    }
+
+    existIntermediateVars = 1;
+    while (existIntermediateVars) {
+      existIntermediateVars = 0;
+      supportList = mdd_get_support(mgr, resultMdd);
+      for (i = 0; i < array_n(supportList); i++) {
+	mddId = array_fetch(int, supportList, i);
+	if (!st_lookup(supportTable, (char *)(long)mddId, NULL)) {
+	  vertex = Part_PartitionFindVertexByMddId(modelPartition, mddId);
+	  mvf = Part_VertexReadFunction(vertex);
+	  varBddRelationArray = mdd_fn_array_to_bdd_rel_array(mgr, mddId, mvf);
+	  varArray = mdd_id_to_bdd_array(mgr, mddId);
+	  assert(array_n(varBddRelationArray) == array_n(varArray));
+	  for (j = 0; j < array_n(varBddRelationArray); j++) {
+	    iv = array_fetch(mdd_t *, varArray, j);
+	    relation = array_fetch(mdd_t *, varBddRelationArray, j);
+	    ivMdd = bdd_cofactor(relation, iv);
+	    mdd_free(relation);
+	    tmpMdd = resultMdd;
+	    resultMdd = bdd_compose(resultMdd, iv, ivMdd);
+	    mdd_free(tmpMdd);
+	    mdd_free(iv);
+	    mdd_free(ivMdd);
+	  }
+	  array_free(varBddRelationArray);
+	  array_free(varArray);
+	  existIntermediateVars = 1;
+	}
+      }
+      array_free(supportList);
+    }
+    st_free_table(supportTable);
+  }
+  return resultMdd;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Read fairness constraints from file and check for errors.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+array_t *
+BmcReadFairnessConstraints(
+  FILE *fp /* pointer to the fairness constraint file */)
+{
+  array_t *constraintArray;	/* raw fairness constraints */
+  array_t *ltlConstraintArray;	/* constraints converted to LTL */
+
+  if (fp == NIL(FILE) ) {
+    /* Nothing to be done. */
+    return NIL(array_t);
+  }
+
+  /* Read constraints from file and check for errors. */
+  constraintArray = Ctlsp_FileParseFormulaArray(fp);
+  if (constraintArray == NIL(array_t)) {
+    (void) fprintf(vis_stderr,
+		   "** ctlsp error: error reading fairness constraints.\n");
+    return NIL(array_t);
+  }
+  if (array_n(constraintArray) == 0) {
+    (void) fprintf(vis_stderr, "** ctlsp error: fairness file is empty.\n");
+    return NIL(array_t);
+  }
+  /*
+   * Check that each constraint is an LTL formula.
+   */
+  ltlConstraintArray = Ctlsp_FormulaArrayConvertToLTL(constraintArray);
+  Ctlsp_FormulaArrayFree(constraintArray);
+  if (ltlConstraintArray == NIL(array_t)) {
+    (void) fprintf(vis_stderr,
+		   "** ctlsp error: fairness constraints are not LTL formulae.\n");
+    return NIL(array_t);
+  }
+
+  return ltlConstraintArray;
+
+} /* BmcReadFairnessConstraints */
+
+
+/**Function********************************************************************
+
+  Synopsis [return the cnf index for a bdd node]
+
+  SideEffects []
+
+******************************************************************************/
+int
+BmcGetCnfVarIndexForBddNode(
+  bdd_manager *bddManager,
+  bdd_node *node,
+  int      state,
+  BmcCnfClauses_t *cnfClauses)
+{
+  array_t     *mvar_list  = mdd_ret_mvar_list(bddManager);
+  array_t     *bvar_list  = mdd_ret_bvar_list(bddManager);  
+  
+  char      name[100];
+  char      *nodeName;
+  bvar_type bv;
+  mvar_type mv;
+  int nodeIndex = bdd_node_read_index(node);
+  int index, rtnNodeIndex, rtnCode;
+
+
+  /*
+    If the node is for a multi-valued varaible.
+  */
+  if (nodeIndex < array_n(bvar_list)){
+    bv = array_fetch(bvar_type, bvar_list, nodeIndex);
+    /*
+      get the multi-valued varaible.
+    */
+    mv = array_fetch(mvar_type, mvar_list, bv.mvar_id);
+    arrayForEachItem(int, mv.bvars, index, rtnNodeIndex) {
+      if (nodeIndex == rtnNodeIndex){
+	break;
+      }
+    }
+    assert(index < mv.encode_length);
+    /*
+      printf("Name of bdd node %s %d\n", mv.name, index);
+    */
+    sprintf(name, "%s_%d", mv.name, index);
+  } else {
+    sprintf(name, "Bdd_%d", nodeIndex);
+  }
+  nodeName = util_strsav(name);
+  rtnCode = BmcCnfReadOrInsertNode(cnfClauses, nodeName, state, &nodeIndex);
+  if(rtnCode == 1) {
+    FREE(nodeName);
+  }
+  return nodeIndex;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Test that the given string is an integer. Returns 0 if string is
+  not an integer, 1 if the integer is too big for int, and 2 if integer fits
+  in int.]
+
+  SideEffects [Sets the pointer value if the string is an integer small enough
+  for int.]
+
+******************************************************************************/
+static int
+StringCheckIsInteger(
+  char *string,
+  int *value)
+{
+  char *ptr;
+  long l;
+  
+  l = strtol (string, &ptr, 0) ;
+  if(*ptr != '\0')
+    return 0;
+  if ((l > MAXINT) || (l < -1 - MAXINT))
+    return 1 ;
+  *value = (int) l;
+  return 2 ;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Compare procedure for name comparison.]
+
+  Description [Compare procedure for name comparison.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+nameCompare(
+  const void * name1,
+  const void * name2)
+{
+    return(strcmp(*(char**)name1, *(char **)name2));
+
+} /* end of signatureCompare */
+
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Print the valuse of variables in the variable list "varNames".]
+
+  Description [For each variable in the variable list, this functions prints its
+  value in the resultTable if it is different for its value in prevValue. If this
+  variable is a symbolic variable, this function prints its symbolic value.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+printValue(
+  mAig_Manager_t  *manager,
+  Ntk_Network_t   *network,
+  st_table        *nodeToMvfAigTable,
+  BmcCnfClauses_t *cnfClauses,
+  array_t         *varNames,
+  st_table        *resultTable,
+  int             state,
+  int             *prevValue)
+{
+  Ntk_Node_t        *node;
+  int               i, j;
+  bAigEdge_t        bAigId;
+  nameType_t        *varName, *nodeName;
+  int               value, index;
+  MvfAig_Function_t *MvfAig;
+  int               changed = 0;
+  int               tmp;
+
+  for (j=0; j< array_n(varNames); j++) {
+    if (state == 0){
+      prevValue[j] = -1;
+    }
+    nodeName = array_fetch(char *, varNames, j);
+    /*
+      Fetch the node corresponding to this node name.
+    */
+    node = Ntk_NetworkFindNodeByName(network, nodeName);
+    /*
+      Get the multi-valued function for each node
+    */
+    MvfAig = Bmc_ReadMvfAig(node, nodeToMvfAigTable);
+    /*
+      In case of the multi-valued function is not build for this node, do nothing.
+      We may notify the user.
+     */
+    if (MvfAig ==  NIL(MvfAig_Function_t)){
+      continue;
+    }
+    /*
+      No CNF index for this variable at time "state in the "
+     */
+    value = -1;
+    for (i=0; i< array_n(MvfAig); i++) {
+      bAigId = MvfAig_FunctionReadComponent(MvfAig, i);
+      /*
+	constant value
+       */
+      if (bAigId == bAig_One){
+	/*
+	  This variable equal the constant i.
+	 */
+	value = i;
+	break;
+      }
+      if (bAigId != bAig_Zero){
+	char        *tmpStr;
+	
+	nodeName = bAig_NodeReadName(manager, bAigId);
+	/*
+	  Build the variable name at state "state".
+	 */
+	tmpStr = util_inttostr(state);
+	varName  = util_strcat3(nodeName, "_", tmpStr);
+	if (st_lookup_int(cnfClauses->cnfIndexTable, varName, &index)) {
+	  if (bAig_IsInverted(bAigId)){
+	    index = -index;
+	  }
+	  /*if (searchArray(result, index) > -1){*/
+	  if (st_lookup_int(resultTable, (char *)(long)index, &tmp)){
+	    value = i;
+	    break;
+	  }
+	} /* if st_lookup_int()  */
+	FREE(tmpStr);
+	FREE(varName);
+      } /* if (bAigId != bAig_Zero) */
+    }
+    if (value >= 0){
+      if (value != prevValue[j]){
+        Var_Variable_t *nodeVar = Ntk_NodeReadVariable(node);
+
+        prevValue[j] = value;
+        changed = 1;
+        if (Var_VariableTestIsSymbolic(nodeVar)) {
+          char *symbolicValue = Var_VariableReadSymbolicValueFromIndex(nodeVar, value);
+
+          (void) fprintf(vis_stdout,"%s:%s\n",  Ntk_NodeReadName(node), symbolicValue);
+        }
+        else {
+          (void) fprintf(vis_stdout,"%s:%d\n",  Ntk_NodeReadName(node), value);
+        }
+      }
+    } else {
+      /*
+        This variable does not have value in the current time frame. It means its value
+        is not important at this time frame.
+       */
+      (void) fprintf(vis_stdout,"%s:X\n",  Ntk_NodeReadName(node));
+    }
+  } /* for j loop */
+  if (changed == 0){
+    fprintf( vis_stdout, "<Unchanged>\n");
+  }
+
+}/* end of printValue() */
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Print the valuse of variables in the variable list "varNames".]
+
+  Description [For each variable in the variable list, this functions prints the 
+	       values of names, which do not start with $_ as these are true
+	       latches of the model. Since this is in aiger format, hence all
+	       the values are printed even if they didn't change from the 
+	       previous values.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+printValueAiger(
+  mAig_Manager_t  *manager,
+  Ntk_Network_t   *network,
+  st_table        *nodeToMvfAigTable,
+  BmcCnfClauses_t *cnfClauses,
+  array_t         *varNames,
+  st_table        *resultTable,
+  int             state,
+  int             *prevValue)
+{
+  Ntk_Node_t        *node;
+  int               i, j;
+  bAigEdge_t        bAigId;
+  nameType_t        *varName, *nodeName;
+  int               value, index;
+  MvfAig_Function_t *MvfAig;
+  int               tmp;
+  char * 	    NodeName;
+
+  for (j=0; j< array_n(varNames); j++) {
+    if (state == 0){
+      prevValue[j] = -1;
+    }
+    nodeName = array_fetch(char *, varNames, j);
+    /*
+      Fetch the node corresponding to this node name.
+    */
+    node = Ntk_NetworkFindNodeByName(network, nodeName);
+    /*
+      Get the multi-valued function for each node
+    */
+    MvfAig = Bmc_ReadMvfAig(node, nodeToMvfAigTable);
+    /*
+      In case of the multi-valued function is not build for this node, do nothing.
+      We may notify the user.
+     */
+    if (MvfAig ==  NIL(MvfAig_Function_t)){
+      continue;
+    }
+    /*
+      No CNF index for this variable at time "state in the "
+     */
+    value = -1;
+    for (i=0; i< array_n(MvfAig); i++) {
+      bAigId = MvfAig_FunctionReadComponent(MvfAig, i);
+      /*
+	constant value
+       */
+      if (bAigId == bAig_One){
+	/*
+	  This variable equal the constant i.
+	 */
+	value = i;
+	break;
+      }
+      if (bAigId != bAig_Zero){
+	char        *tmpStr;
+	
+	nodeName = bAig_NodeReadName(manager, bAigId);
+	/*
+	  Build the variable name at state "state".
+	 */
+	tmpStr = util_inttostr(state);
+	varName  = util_strcat3(nodeName, "_", tmpStr);
+	if (st_lookup_int(cnfClauses->cnfIndexTable, varName, &index)) {
+	  if (bAig_IsInverted(bAigId)){
+	    index = -index;
+	  }
+	  /*if (searchArray(result, index) > -1){*/
+	  if (st_lookup_int(resultTable, (char *)(long)index, &tmp)){
+	    value = i;
+	    break;
+	  }
+	} /* if st_lookup_int()  */
+	FREE(tmpStr);
+	FREE(varName);
+      } /* if (bAigId != bAig_Zero) */
+    }
+    NodeName = Ntk_NodeReadName(node); 
+    if(!((NodeName[0] == '$') && (NodeName[1] == '_')))
+    {
+      if (value >= 0){
+        Var_Variable_t *nodeVar = Ntk_NodeReadVariable(node);
+	
+        prevValue[j] = value;
+        if (Var_VariableTestIsSymbolic(nodeVar)) {
+  	  char *symbolicValue = Var_VariableReadSymbolicValueFromIndex(nodeVar, value);
+	  
+	  (void) fprintf(vis_stdout,"%s",   symbolicValue);
+        } 
+        else {
+          (void) fprintf(vis_stdout,"%d",  value);
+        }
+      } else {
+      /*
+	This variable does not have value in the current time frame. It means its value
+	is not important at this time frame.
+       */
+        (void) fprintf(vis_stdout,"x" );
+      }
+    } /* these nodes are latches in front of inputs so they will be printed out as inputs */
+  } /* for j loop */
+}/* end of printValueAiger() */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Print the valuse of variables in the variable list "varNames".]
+
+  Description [For each variable in the variable list, this functions checks if
+               the name starts with $_, which means that those latches are 
+	       actually storing the value of inputs. This modification to the
+	       model is externally done and not done by VIS so this method is
+	       only specific to certain type of model, the output of aigtoblif
+	       translator.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+printValueAigerInputs(
+  mAig_Manager_t  *manager,
+  Ntk_Network_t   *network,
+  st_table        *nodeToMvfAigTable,
+  BmcCnfClauses_t *cnfClauses,
+  array_t         *varNames,
+  st_table        *resultTable,
+  int             state,
+  int             *prevValue)
+{
+  Ntk_Node_t        *node;
+  int               i, j;
+  bAigEdge_t        bAigId;
+  nameType_t        *varName, *nodeName;
+  int               value, index;
+  MvfAig_Function_t *MvfAig;
+  int               tmp;
+  char * 	    NodeName;
+
+  for (j=0; j< array_n(varNames); j++) {
+    if (state == 0){
+      prevValue[j] = -1;
+    }
+    nodeName = array_fetch(char *, varNames, j);
+    /*
+      Fetch the node corresponding to this node name.
+    */
+    node = Ntk_NetworkFindNodeByName(network, nodeName);
+    /*
+      Get the multi-valued function for each node
+    */
+    MvfAig = Bmc_ReadMvfAig(node, nodeToMvfAigTable);
+    /*
+      In case of the multi-valued function is not build for this node, do nothing.
+      We may notify the user.
+     */
+    if (MvfAig ==  NIL(MvfAig_Function_t)){
+      continue;
+    }
+    /*
+      No CNF index for this variable at time "state in the "
+     */
+    value = -1;
+    for (i=0; i< array_n(MvfAig); i++) {
+      bAigId = MvfAig_FunctionReadComponent(MvfAig, i);
+      /*
+	constant value
+       */
+      if (bAigId == bAig_One){
+	/*
+	  This variable equal the constant i.
+	 */
+	value = i;
+	break;
+      }
+      if (bAigId != bAig_Zero){
+	char        *tmpStr;
+	
+	nodeName = bAig_NodeReadName(manager, bAigId);
+	/*
+	  Build the variable name at state "state".
+	 */
+	tmpStr = util_inttostr(state);
+	varName  = util_strcat3(nodeName, "_", tmpStr);
+	if (st_lookup_int(cnfClauses->cnfIndexTable, varName, &index)) {
+	  if (bAig_IsInverted(bAigId)){
+	    index = -index;
+	  }
+	  /*if (searchArray(result, index) > -1){*/
+	  if (st_lookup_int(resultTable, (char *)(long)index, &tmp)){
+	    value = i;
+	    break;
+	  }
+	} /* if st_lookup_int()  */
+	FREE(tmpStr);
+	FREE(varName);
+      } /* if (bAigId != bAig_Zero) */
+    }
+    NodeName = Ntk_NodeReadName(node); 
+    if((NodeName[0] == '$') && (NodeName[1] == '_'))
+    {
+      if (value >= 0){
+        Var_Variable_t *nodeVar = Ntk_NodeReadVariable(node);
+	
+        prevValue[j] = value;
+        if (Var_VariableTestIsSymbolic(nodeVar)) {
+  	  char *symbolicValue = Var_VariableReadSymbolicValueFromIndex(nodeVar, value);
+	  
+	  (void) fprintf(vis_stdout,"%s",   symbolicValue);
+        } 
+        else {
+          (void) fprintf(vis_stdout,"%d",  value);
+        }
+      } else {
+      /*
+	This variable does not have value in the current time frame. It means its value
+	is not important at this time frame.
+       */
+        (void) fprintf(vis_stdout,"x" );
+      }
+    } /* these nodes are latches in front of inputs so they will be printed out as inputs */
+  } /* for j loop */
+}/* end of printValueAigerInputs() */
+
+
+
Index: vis_dev/vis-2.3/src/cmd/cmd.h
===================================================================
--- vis_dev/vis-2.3/src/cmd/cmd.h	(revision 14)
+++ vis_dev/vis-2.3/src/cmd/cmd.h	(revision 14)
@@ -0,0 +1,85 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [cmd.h]
+
+  PackageName [cmd]
+
+  Synopsis    [Implements command line interface, and miscellaneous commands.]
+
+  Author      [Originated from SIS]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: cmd.h,v 1.11 2002/09/08 22:06:21 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _CMD
+#define _CMD
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include <setjmp.h>
+#include <signal.h>
+
+#include "hrc.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef int (*PFI)(Hrc_Manager_t **, int, char **);
+
+ 
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void Cmd_CommandAdd(char * name, PFI funcFp, int changes);
+EXTERN int Cmd_CommandExecute(Hrc_Manager_t ** hmgr, char * command);
+EXTERN FILE * Cmd_FileOpen(char * fileName, char * mode, char ** realFileName_p, int silent);
+EXTERN char * Cmd_FlagReadByName(char * flag);
+EXTERN void Cmd_FlagUpdateValue(char * key, char * value);
+EXTERN void Cmd_FlagDeleteByName(char * key);
+EXTERN void Cmd_Init(void);
+EXTERN void Cmd_End(void);
+EXTERN int Cmd_StringCheckIsInteger(char *string, int *value);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _CMD */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/cmd/cmd.make
===================================================================
--- vis_dev/vis-2.3/src/cmd/cmd.make	(revision 14)
+++ vis_dev/vis-2.3/src/cmd/cmd.make	(revision 14)
@@ -0,0 +1,4 @@
+CSRC += cmdCmd.c cmdFile.c cmdMisc.c
+HEADERS += cmd.h cmdInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/cmd/cmdCmd.c
===================================================================
--- vis_dev/vis-2.3/src/cmd/cmdCmd.c	(revision 14)
+++ vis_dev/vis-2.3/src/cmd/cmdCmd.c	(revision 14)
@@ -0,0 +1,848 @@
+/**CFile***********************************************************************
+
+  FileName    [cmdCmd.c]
+
+  PackageName [cmd]
+
+  Synopsis    [Command table and command execution.]
+
+  Author      [Originated from SIS]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "cmdInt.h"
+
+static char rcsid[] UNUSED = "$Id: cmdCmd.c,v 1.16 2005/04/16 04:23:02 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+typedef struct CommandDescrStruct {
+  char *name;
+  PFI command_fp;
+  int changes_hmgr;
+} CommandDescr_t;
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+Hrc_Manager_t *cmdBackupHmgr;
+avl_tree *cmdCommandTable;
+
+static char visShellChar = '!';      /* can be reset using the "set shell_char" */
+
+static int autoexec;		/* indicates currently in autoexec */
+static jmp_buf env;
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int com_dispatch(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int apply_alias(Hrc_Manager_t ** hmgr, int * argcp, char *** argvp, int * loop);
+static void variableInterpolation(int *argc, char ***argv);
+static char * variableInterpolationRecur(char *str);
+static char * split_line(char * command, int * argc, char *** argv);
+static int check_shell_escape(char * p, int * status);
+static void sigterm(int sig);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Adds a command to the command table.]
+
+  Description [Adds a command to the command table.  If name already defines
+  an existing command, its definition is replaced.  FuncFp is a function
+  pointer to code of the form: <p>
+
+                int <br>
+		CommandTest(hmgr, argc, argv)<br>
+                  Hrc_Manager_t **hmgr;<br>
+                  int argc;<br>
+                  char **argv;<br>
+                {<br>
+		    return 0;<br>
+		}<p>
+
+  Note the double de-reference on the hmgr which is passed to the command;
+  this allows the command to replace the current hmgr.  argv\[0\] will generally
+  be the command name, and argv\[1\] ... argv\[argc-1\] are the arguments for the
+  command.  util_getopt() can be used to parse the arguments, but
+  util_getopt_reset() must be used before calling util_getopt().  The command
+  function should return 0 for normal operation, 1 for any error.  The changes
+  flag is used to automatically save the hmgr before executing the command (in
+  order to support undo).]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Cmd_CommandAdd(
+  char * name,
+  PFI  funcFp,
+  int  changes)
+{
+  char *key, *value;
+  CommandDescr_t *descr;
+  int status;
+
+  key = name;
+  if (avl_delete(cmdCommandTable, &key, &value)) {
+    /* delete existing definition for this command */
+    (void) fprintf
+      (vis_stderr, "** cmd warning: redefining '%s'\n", name);
+    CmdCommandFree(value);
+  }
+
+  descr = ALLOC(CommandDescr_t, 1);
+  descr->name = util_strsav(name);
+  descr->command_fp = funcFp;
+  descr->changes_hmgr = changes;
+  status = avl_insert(cmdCommandTable, descr->name, (char *) descr);
+  assert(!status);  /* error here in SIS version, TRS, 8/4/95 */
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Executes a command line.]
+
+  Description [Executes a command line.  This is the top-level of the command
+  interpreter, and supports multiple commands (separated by ;), alias
+  substitution, etc.  For many simple operations, Cmd_CommandExecute() is the
+  easiest way to accomplish a given task. For example, to set a variable, use
+  the code: Cmd_CommandExecute(&hmgr, "set color blue").]
+
+  SideEffects []
+
+******************************************************************************/
+int
+Cmd_CommandExecute(
+  Hrc_Manager_t ** hmgr,
+  char * command)
+{
+  int status, argc;
+  int loop;
+  char *commandp, **argv;
+
+  (void) signal(SIGINT, SIG_IGN);
+  commandp = command;
+  do {
+    if (check_shell_escape(commandp, &status)) {
+      break;
+    }
+    
+    commandp = split_line(commandp, &argc, &argv);
+    loop = 0;
+    status = apply_alias(hmgr, &argc, &argv, &loop);
+    if (status == 0) {
+
+      variableInterpolation(&argc, &argv);
+
+      status = com_dispatch(hmgr, argc, argv);
+    }
+    CmdFreeArgv(argc, argv);
+  } while (status == 0 && *commandp != '\0');
+  return status;
+}
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CmdCommandFree(
+  char * value)
+{
+  CommandDescr_t *command = (CommandDescr_t *) value;
+
+  FREE(command->name);		/* same as key */
+  FREE(command);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static int
+com_dispatch(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int status;
+  char *value;
+  CommandDescr_t *descr;
+
+  if (argc == 0) {		/* empty command */
+    return 0;
+  }
+
+  if (! avl_lookup(cmdCommandTable, argv[0], &value)) {
+    (void) fprintf(vis_stderr, "** cmd error: unknown command '%s'\n", argv[0]);
+    return 1;
+  }
+
+  descr = (CommandDescr_t *) value;
+  if (setjmp(env)) {
+#if 0
+    /* FIX (Tom) need hmgr_dup and network_dup to use this functionality */
+    /* return from control-c -- restore the hmgr */
+    if (descr->changes_hmgr) {
+      *hmgr = cmdBackupHmgr;
+      cmdBackupHmgr = NIL(Hrc_Manager_t);
+    }
+#endif
+    return 1;
+  }
+
+  
+#if 0
+  /* FIX (Tom) need hmgr_dup and network_dup to use this functionality */
+  if (descr->changes_hmgr) {
+    if (cmdBackupHmgr != NIL(Hrc_Manager_t)) {
+      Hrc_ManagerFree(cmdBackupHmgr);
+    }
+    cmdBackupHmgr = hmgr_dup(*hmgr);
+  }
+#endif
+  
+  (void) signal(SIGINT, sigterm);
+  status = (*descr->command_fp)(hmgr, argc, argv);
+
+  /* automatic execution of arbitrary command after each command */
+  /* usually this is a passive command ... */
+  if (status == 0 && ! autoexec) {
+    if (avl_lookup(cmdFlagTable, "autoexec", &value)) {
+      autoexec = 1;
+      status = Cmd_CommandExecute(hmgr, value);
+      autoexec = 0;
+    }
+  }
+
+  (void) signal(SIGINT, SIG_IGN);
+  return status;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [Applies alias.  If perform a history substitution in expanding
+  an alias, remove all the orginal trailing arguments.  For example:<p>
+
+    > alias t rl \!:1<br>
+    > t lion.blif  would otherwise expand to   rl lion.blif lion.blif <br>]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static int
+apply_alias(
+  Hrc_Manager_t ** hmgr,
+  int * argcp,
+  char *** argvp,
+  int * loop)
+{
+  int i, argc, stopit, added, offset, did_subst, subst, status, newc, j;
+  char *arg, **argv, **newv;
+  CmdAliasDescr_t *alias;
+
+  argc = *argcp;
+  argv = *argvp;
+  stopit = 0;
+  for(; *loop < 20; (*loop)++) {
+    if (argc == 0) {
+      return 0;
+    }
+    if (stopit != 0 || avl_lookup(cmdAliasTable, argv[0], &alias) == 0) {
+      return 0;
+    }
+    if (strcmp(argv[0], alias->argv[0]) == 0) {
+      stopit = 1;
+    }
+    FREE(argv[0]);
+    added = alias->argc - 1;
+
+    /* shift all the arguments to the right */
+    if (added != 0) {
+      argv = REALLOC(char *, argv, argc + added);
+      for (i = argc - 1; i >= 1; i--) {
+        argv[i + added] = argv[i];
+      }
+      for (i = 1; i <= added; i++) {
+        argv[i] = NIL(char);
+      }
+      argc += added;
+    }
+    subst = 0;
+    for (i = 0, offset = 0; i < alias->argc; i++, offset++) {
+      arg = CmdHistorySubstitution(alias->argv[i], &did_subst);
+      if (arg == NIL(char)) {
+        *argcp = argc;
+        *argvp = argv;
+        return(1);
+      }
+      if (did_subst != 0) {
+        subst = 1;
+      }
+      status = 0;
+      do {
+        arg = split_line(arg, &newc, &newv);
+        /*
+         * If there's a complete `;' terminated command in `arg',
+         * when split_line() returns arg[0] != '\0'.
+         */
+        if (arg[0] == '\0') {   /* just a bunch of words */
+          break;
+        }
+        status = apply_alias(hmgr, &newc, &newv, loop);
+        if (status == 0) {
+          status = com_dispatch(hmgr, newc, newv);
+        }
+        CmdFreeArgv(newc, newv);
+      } while (status == 0);
+      if (status != 0) {
+        *argcp = argc;
+        *argvp = argv;
+        return(1);
+      }
+      added = newc - 1;
+      if (added != 0) {
+        argv = REALLOC(char *, argv, argc + added);
+        for (j = argc - 1; j > offset; j--) {
+          argv[j + added] = argv[j];
+        }
+        argc += added;
+      }
+      for (j = 0; j <= added; j++) {
+        argv[j + offset] = newv[j];
+      }
+      FREE(newv);
+      offset += added;
+    }
+    if (subst == 1) {
+      for (i = offset; i < argc; i++) {
+        FREE(argv[i]);
+      }
+      argc = offset;
+    }
+    *argcp = argc;
+    *argvp = argv;
+  }
+
+  (void) fprintf(vis_stderr, "** cmd error: alias loop\n");
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allows interpolation of variables]
+
+  Description [Allows interpolation of variables. Here it is implemented by
+  allowing variables to be referred to with the prefix of '$'. The variables
+  are set using the "set" command. So for example, the following can be done <p>
+
+  <code>
+  vis> set foo bar <br>
+  vis> echo $foo <br>
+  bar <br>
+  </code>
+  
+  The last line "bar" will the output produced by vis.
+
+  The following can also be done: <p>
+  
+  <code>
+  vis> set foo $foo:foobar <br>
+  vis> echo $foobar <br>
+  bar:foobar <br>
+  </code>
+  The last line will be the output produced by vis. <p>
+
+  These variables can
+  be used in recursive definitions. The following termination characters are
+  recognized for the variables \\n, \\0, ' ', \\t,  :,  ;,  #,  /.
+
+  Although the set command allows the usage of the some of the
+  above termination characters between quotes, 
+  the variable interpolation procedure has the restriction
+  that the two characters ':' and '/' may not be used with quotes.
+  A variable with spaces in it may be used only if it is enclosed
+  within quotes. ]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+
+static void
+variableInterpolation(int *ori_argc, char ***ori_argv)
+{
+  int i;          /* to iterate through the arguments */
+  char *newStr;   /* string returned by the expanded value */
+  char dollar;    /* character to store reference to the variable, now '$' */
+  int argc;
+  char **argv;
+  int index;
+  int null_string_flag;
+
+  argc = *ori_argc;
+  argv = *ori_argv;
+
+  dollar = '$';
+  null_string_flag = 0;
+
+  /* step through all argvs */
+  for (i = 0; i < argc; i++) {
+    if (strchr((char *)argv[i], (int)dollar) != NULL) {
+      /* expanded string returned by the procedure */
+      newStr = variableInterpolationRecur(argv[i]);
+      if(!strcmp(newStr, " ")) {
+        FREE(argv[i]);
+        /* replace old value with new */
+        argv[i] = 0;
+	null_string_flag = 1;
+      }
+      else {
+        FREE(argv[i]);
+        /* replace old value with new */
+        argv[i] = newStr;
+      }
+    }
+  } /* end of iterating through all arguments */
+
+  if(null_string_flag) {
+    *ori_argv = ALLOC(char *, argc);
+    index = 0;
+    for (i = 0; i < argc; i++) {
+      if(argv[i] == 0) {
+        (*ori_argc)--;
+        continue;
+      }
+      (*ori_argv)[index++] = argv[i];
+    }
+    FREE(argv);
+  }
+
+  return;
+}/* end of variable interpolation */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Recursive procedure that expands the interpolation variables]
+
+  Description [Recursive procedure that expands the interpolation variables.
+  This procedure is designed to handle multiple occurrences of variables
+  in a string and recursive definitions. If the expanded variable has another
+  variable, then the procedure is called recursively. The existence of a
+  variable is identified by the $ sign in the string. But since this may be
+  an environment variable too, the variable is untouched if not found in
+  this table. A sophisticated check can be made to see if this variable
+  exists in the environment, but it is NOT done here. Therefore, detection
+  of bogus values cannot be done. The procedure steps through the string
+  to see if any variables are present. If a termination character (one of
+  :, /) is found after the '$', then the variable
+  is identified and looked up in the flag table. If the returned string again
+  has a dollar, then the procedure is called recursively. If not, the returned
+  value replaces the variable and the stepping through continues. If the
+  variable is not found, then it might be an environment variable.So the
+  procedure leaves the variable there. ]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+
+static char *
+variableInterpolationRecur(char *str)
+{
+  int i;               /* iterators */
+  int findEndDollar;   /* flag to denote that a $ has been found. So
+			* search till end of variable
+			*/
+  int endDollarIndex;  /* index in the current string of the end of the
+			* variable
+			*/
+  int dollarIndex;     /* index in the current string of the dollar sign */  
+  int singleQuote;     /* flag that symbolizes that a quote is started */ 
+  int doubleQuote;     /* flag that symbolizes that a quote is started */
+  char *value;         /* value of the variable that is returned by the table */
+  char *subStr;        /* string to store the variable */
+  int curStrIndex;     /* index to step through the current string */
+  int subLen;          /* length of the variable */
+  int index;           /* variable use to step through the various strings */
+  char *curStr;        /* current string which may change as substitutions
+			* take place
+			*/
+  char *newCurStr;     /* new string pieced together with the expanded value */
+  char c;              /* current character in the string */
+
+  int freeNewValue;    /* new value of string returned by recursion needs
+			* to be freed.
+			*/
+  char dollar;         /* character that stores the dollar sign */
+  int lastPos;         /* position of the last character of the variable
+			* in the string.
+			*/
+  int envVar;           /* flag to say that the variable is not found in
+			 * the table, hence may be an environment variable
+			 */
+
+  dollar = '$';
+  curStrIndex = 0;
+  subLen = 0;
+  findEndDollar = 0;
+  singleQuote = 0;
+  doubleQuote = 0;
+  dollarIndex = -1;
+  endDollarIndex = -1;
+  /* make a local copy since the string may change */
+  curStr = ALLOC(char, strlen(str)+1);
+  curStr = strncpy(curStr, str, strlen(str)+1);
+  /* search through the end of string including te \0 character to detect
+   * end of variable, if required.
+   */
+  while (curStrIndex <= (int) strlen(curStr)) {
+    /* current character */
+    c = curStr[curStrIndex];
+    /* redundant here since split_line already strips out the quotes */
+    if ((c == '\"') || (c == '\'')) {
+      /* also termination charactrers for $ */
+      /* set flags for quote found */
+      singleQuote = !singleQuote;
+      doubleQuote = !doubleQuote;
+      /* also a variable termination */
+      if (findEndDollar) {
+	findEndDollar = 0;
+	endDollarIndex = curStrIndex;
+      }
+    }
+    /* detect a $ if not within quotes */
+    if ((c == '$') && (!singleQuote) && (!doubleQuote)) {
+      if (findEndDollar == 1) {
+	error_append("Cannot have nested $ signs, not found termination\n");
+	break;
+      }
+      /* note the beginning of the dollar position */
+      dollarIndex = curStrIndex;
+      /* start quest for end of dollar */
+      findEndDollar = 1;
+      endDollarIndex = -1;
+    }
+    /* termination characters are \0, :, / when not within quotes.
+     * Although, some of these may never be encountered
+     * since this is called after split_line and apply_alias
+     * Termination characters except '\0' are ignored within quotes
+     */
+    if ((findEndDollar) &&
+	((c == '\0') ||
+	 ((!singleQuote) && (!doubleQuote) &&
+	  ((c == ':') || (c == '/'))))) {
+      /*     if (((c == '\n') || (c == '\t') || (isspace(c)) ||
+	(c == ':') || (c == ';') || (c == '\0') ||
+	(c == '#') || (c == '/')) && (findEndDollar)) { */
+	findEndDollar = 0;
+	endDollarIndex = curStrIndex;
+    } /* end of find termination characters */
+
+    /* found the interpolation variable and its end*/
+    if (!findEndDollar && (endDollarIndex != -1)) {
+      /* found an interpolation variable */
+      subLen = 0;
+      freeNewValue = 0;
+      envVar = 0;
+      subStr = NULL;
+      if (endDollarIndex > (dollarIndex +1)) {
+	/* if not empty string */
+	subStr = ALLOC(char, endDollarIndex - dollarIndex);
+	/* copy the variable into another string */
+	for ( i = 0; i <  endDollarIndex - dollarIndex - 1; i++) {
+	  subStr[i] = curStr[dollarIndex+1+i];
+	}
+	subStr[i] = '\0';
+	/* quiet if of the form var$:iable or var$foo:iable and
+	 * $foo not in flag table
+	 */
+	if (avl_lookup(cmdFlagTable, subStr, (char **)&value) != 0) {
+	  /* found the variable in the alias table */
+	  if (strchr((char *)value, (int)dollar) != NULL) {
+	    /* if more $s in the value */
+	    value = variableInterpolationRecur(value);
+	    subLen = strlen(value);
+	    /* to be freed later since variableInterpolationRecur
+	     * returns a new string to be freed later.
+	     */
+	    freeNewValue = 1;
+
+	  }  else {
+	  /* if no dollars in the value, substitute the return value
+	   * in the string
+	   */
+	    subLen = strlen(value);
+	  }
+	} else { 
+	  /* if the variable is not found, it might be an
+	   * environment variable and so keep it. This might be
+	   * a hazard for bogus variables but that is upto the user.
+	   */
+	  value = subStr;
+	  /* for environment variable keep the $ sign */
+	  subLen = strlen(value) +1;
+	  envVar = 1;
+	}
+
+      } /* end of interpolation variable not trivial */
+      /* prefix + strlen(substituted value) + suffix */
+      newCurStr = ALLOC(char, dollarIndex + 
+			      subLen +
+			      strlen(curStr) - endDollarIndex + 1);
+			
+      
+      
+      /* copy prefix */
+      newCurStr = strncpy(newCurStr, curStr, dollarIndex);
+      i = dollarIndex;
+      if (subLen) {
+	/* copy substituted value */
+	if (envVar) {
+	  /* if it is an environment variable, keep the $ sign */
+	  newCurStr[i++] = '$';
+	}
+	index = 0;
+	while (value[index] != '\0') {
+	  newCurStr[i++] = value[index++];
+	}
+	if (freeNewValue) {
+	  FREE(value);
+	}
+      }
+      /* freed here cos value might be subStr in one case */
+      if (subStr != NULL) {
+	FREE(subStr);
+      }
+      /* copy suffix */
+      index = endDollarIndex;
+      /* figure out where to start the next search */
+      lastPos = i;
+      while (curStr[index] != '\0') {
+	newCurStr[i++] = curStr[index++];
+      }
+      newCurStr[i] = '\0';
+      FREE(curStr);
+      curStr = newCurStr;
+      /* reset counter for further search. Due to recursive calling of this
+       * function eventually, the value that is substituted will not have a $
+       */
+      curStrIndex = lastPos;
+      dollarIndex = -1;
+      endDollarIndex = -1;
+      /* end of found a variable */   
+    } else { /* if a variable is not found, keep going */
+      curStrIndex++;
+    }
+  } /* end of stepping through the string */
+  return(curStr);
+} /* end of variableInterpolationRecur */
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static char *
+split_line(
+  char * command,
+  int * argc,
+  char *** argv)
+{
+  register char *p, *start, c;
+  register int i, j;
+  register char *new_arg;
+  array_t *argv_array;
+  int single_quote, double_quote;
+
+  argv_array = array_alloc(char *, 5);
+
+  p = command;
+  for(;;) {
+    /* skip leading white space */
+    while (isspace((int)(*p))) {
+      p++;
+    }
+
+    /* skip until end of this token */
+    single_quote = double_quote = 0;
+    for(start = p; (c = *p) != '\0'; p++) {
+      if (c == ';' || c == '#' || isspace((int)c)) {
+        if (! single_quote && ! double_quote) {
+          break;
+        }
+      }
+      if (c == '\'') {
+        single_quote = ! single_quote;
+      }
+      if (c == '"') {
+        double_quote = ! double_quote;
+      }
+    }
+    if (single_quote || double_quote) {
+      (void) fprintf(vis_stderr, "** cmd warning: ignoring unbalanced quote ...\n");
+    }
+    if (start == p) break;
+
+    new_arg = ALLOC(char, p - start + 1);
+    j = 0;
+    for(i = 0; i < p - start; i++) {
+      c = start[i];
+      if ((c != '\'') && (c != '\"')) {
+        new_arg[j++] = isspace((int)c) ? ' ' : start[i];
+      }
+    }
+    new_arg[j] = '\0';
+    array_insert_last(char *, argv_array, new_arg);
+  }
+
+  *argc = array_n(argv_array);
+  *argv = array_data(char *, argv_array);
+  array_free(argv_array);
+  if (*p == ';') {
+    p++;
+  }
+  else if (*p == '#') {
+    for(; *p != 0; p++) ;		/* skip to end of line */
+  }
+  return p;
+}    
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static int
+check_shell_escape(
+  char * p,
+  int * status)
+{
+    char *value;
+    while (isspace((int)(*p))) {
+	p++;
+    }
+    if ((value = Cmd_FlagReadByName("shell_char")) != NIL(char)){
+	visShellChar = *value;
+    }
+    if (*p == visShellChar) {
+	*status = system(p+1);
+	return 1;
+    }
+    return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Signal handler.]
+
+  SideEffects []
+
+  SeeAlso     [com_dispatch]
+
+******************************************************************************/
+static void
+sigterm(int sig)
+{
+    (void) signal(SIGINT, SIG_IGN);	/* ignore further ctl-c */
+    (void)fprintf(vis_stderr, "\n");
+    (void)fprintf(vis_stderr,
+		  "** cmd warning : data may be corrupted due to CTRL-c.\n");
+    (void)fprintf(vis_stderr,
+		  "                 It may cause abnormal termination.\n");
+    longjmp(env, 1);
+}
Index: vis_dev/vis-2.3/src/cmd/cmdFile.c
===================================================================
--- vis_dev/vis-2.3/src/cmd/cmdFile.c	(revision 14)
+++ vis_dev/vis-2.3/src/cmd/cmdFile.c	(revision 14)
@@ -0,0 +1,946 @@
+/**CFile***********************************************************************
+
+  FileName    [cmdFile.c]
+
+  PackageName [cmd]
+
+  Synopsis    [File open, and file completion.]
+
+  Author      [Originated from SIS]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "cmdInt.h"
+
+#if HAVE_READLINE_READLINE_H
+#include <readline/readline.h>
+#else
+EXTERN char *readline(char *);
+#endif
+#if HAVE_READLINE_HISTORY_H
+#include <readline/history.h>
+#else
+EXTERN void add_history(char *);
+#endif
+
+static char rcsid[] UNUSED = "$Id: cmdFile.c,v 1.24 2009/04/11 18:25:50 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+#ifdef ESC
+#undef ESC
+#endif
+#define ESC	'\033'
+#define BEEP	'\007'
+#define HIST	'%'
+#define SUBST	'^'
+
+#define STDIN	0
+#define STDOUT	1
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+static char visHistChar = HIST;       /* can be changed by "set hist_char" */
+static char *seperator = " \t\n;";
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+#if HAVE_IOCTL_WITH_TIOCGETC
+static int cmp(const void * s1, const void * s2);
+static int match(char * newmatch, char * lastmatch, char * actual);
+#endif
+static int getnum(char ** linep);
+static char * getarg(char * line, int num);
+static char * bad_event(int n);
+static char * do_subst(char * dest, char * new_);
+static void print_prompt(char * prompt);
+#if HAVE_LIBREADLINE
+static char * removeWhiteSpaces(char *string);
+#endif
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Opens the file with the given mode.]
+
+  Description [Opens the file with the given mode (see fopen()).  Tilde
+  expansion (~user/ or ~/) is performed on the fileName, and "-" is allowed as
+  a synonym for stdin (or stdout, depending on the mode).  If the file cannot
+  be opened, a message is reported using perror(); the silent flag, if true,
+  suppresses this error action.  In either case, A NULL file pointer is
+  returned if any error occurs.  The fileName (after tilde expansion) is
+  returned in the pointer realFileName, if realFileName is non-empty.  This
+  is a pointer which should be free'd when you are done with it.]
+
+  SideEffects []
+
+******************************************************************************/
+FILE *
+Cmd_FileOpen(
+  char * fileName,
+  char * mode,
+  char ** realFileName_p,
+  int  silent)
+{
+  char *realFileName, *path, *user_path;
+  char *lib_name;
+  FILE *fp;
+
+  if (strcmp(fileName, "-") == 0) {
+    if (strcmp(mode, "w") == 0) {
+      realFileName = util_strsav("stdout");
+      fp = stdout;
+    }
+    else {
+      realFileName = util_strsav("stdin");
+      fp = stdin;
+    }
+  }
+  else {
+    realFileName = NIL(char);
+    if (strcmp(mode, "r") == 0) {
+      user_path = Cmd_FlagReadByName("open_path");
+      if (user_path != NIL(char)) {
+	lib_name = Vm_VisObtainLibrary();
+	path = ALLOC(char, strlen(user_path)+strlen(lib_name)+10);
+	(void) sprintf(path, "%s:%s", user_path, lib_name);
+
+	/*
+	 * If the fileName begins with ./, ../, ~/, or /, AND the file doesn't
+	 * actually exist, then VIS will look in the open path (which includes
+	 * the sis library) for the file.  This could lead to unexpected behavior:
+	 * the user is looking for ./msu.genlib, and since that isn't there, the
+	 * users gets sis_lib/msu.genlib, and no error is reported.  The following
+	 * pseudo code fixes this:
+	 *
+	 * if (the beginning of file_name is : ./ || ../ || ~/ || /) {
+	 * realFileName = util_file_search(fileName, NIL(char), "r");
+	 * } else
+	 */
+	realFileName = util_file_search(fileName, path, "r");
+	FREE(path);
+	FREE(lib_name);
+      }
+    }
+    if (realFileName == NIL(char)) {
+      realFileName = util_tilde_expand(fileName);
+    }
+    if (strcmp(mode, "r") == 0 && !util_check_file(realFileName, mode)) {
+      FREE(realFileName);
+      return NIL(FILE);
+    }
+    if ((fp = fopen(realFileName, mode)) == NIL(FILE)) {
+      if (! silent) {
+	perror(realFileName);
+      }
+    }
+  }
+  if (realFileName_p != 0) {
+    *realFileName_p = realFileName;
+  }
+  else {
+    FREE(realFileName);
+  }
+  return fp;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal and static functions                               */
+/*---------------------------------------------------------------------------*/
+
+#if HAVE_IOCTL_WITH_TIOCGETC
+
+/*
+ * Words are seperated by any of the characters in `seperator'.  The seperator
+ * is used to distinguish words from each other in file completion and history
+ * substitution. The recommeded seperator string is " \t\n;".
+ */
+
+static int cmp(const void * s1, const void * s2);
+static int match(char * newmatch, char * lastmatch, char * actual);
+static int getnum(char ** linep);
+
+/**Function********************************************************************
+
+  Synopsis [Duplicates the function of fgets, but also provides file
+  completion in the same style as csh]
+
+  Description [ Input is read from `stream' and returned in `buf'.  Up to
+  `size' bytes will be placed into `buf'.  If `stream' is not stdin, is
+  equivalent to calling fgets(buf, size, stream).
+
+  `prompt' is the prompt you want to appear at the beginning of the line.  The
+  caller does not have to print the prompt string before calling this routine.
+  The prompt has to be reprinted if the user hits ^D.
+
+  The file completion routines are derived from the source code for csh, which
+  is copyrighted by the Regents of the University of California.]
+
+  SideEffects []
+
+******************************************************************************/
+char *
+CmdFgetsFilec(
+  char * buf,
+  int  size,
+  FILE * stream,
+  char * prompt)
+{
+  int n_read, i, len, maxlen, col, sno, modname;
+  struct tchars tchars, oldtchars;
+  DIR *dir;
+  struct dirent *dp;
+#if HAVE_LIBREADLINE
+  char *dupline;
+  char *cleanLine;
+#endif
+
+#if HAVE_TERM_INTERRUPTS
+  int omask;
+  struct sgttyb tty, oldtty;	/* To mask interuupts */
+  int pending = LPENDIN;
+#endif
+
+  char *last_word, *file, *path, *name, *line;
+  char last_char, found[MAXNAMLEN];
+  array_t *names = NIL(array_t);  /* initialize so that lint doesn't complain */
+
+  sno = fileno(stream);
+  if (sno != STDIN || !isatty(sno)){
+    if (prompt != NIL(char)){
+      (void) print_prompt(prompt);
+      (void) fflush(stdout);
+    }
+    return (fgets(buf, size, stream));
+  }
+  else if (Cmd_FlagReadByName("filec") == NIL(char)) {
+#if HAVE_LIBREADLINE
+    /* Effectively read one line of input printing the prompt */
+    dupline = (char *)readline(prompt);
+    cleanLine = removeWhiteSpaces(dupline);
+
+    /* Check if an EOF has been read */
+    if (cleanLine != NIL(char)) {
+      /* If the line is non empty, add it to the history */
+      if (*cleanLine) {
+	add_history(cleanLine);
+      }
+
+      /* Copy the contents of cleanLine to buf, to simulate fgets */
+      strncpy(buf, cleanLine, size);
+      if (strlen(cleanLine) >= size) {
+	buf[size-1] = '\0';
+      }
+      line = buf;
+    }
+    else {
+      line = NIL(char);
+    }
+    FREE(dupline);
+#else
+    /* Get rid of the trailing newline */
+    if (prompt != NIL(char)){
+      (void) print_prompt(prompt);
+      (void) fflush(stdout);
+    }
+    line = fgets(buf, size, stream);
+    if (line != NIL(char)) {
+      len = strlen(line);
+      if (len > 0 && line[len-1] == '\n') {
+	line[len-1] = '\0';
+      }
+    }
+#endif
+    return line;
+  } else {
+    if (prompt != NIL(char)){
+      (void) print_prompt(prompt);
+      (void) fflush(stdout);
+    }
+  }
+
+  /* Allow hitting ESCAPE to break a read() */
+
+  (void) ioctl(sno, TIOCGETC, (char *) &tchars);
+  oldtchars = tchars;
+  tchars.t_brkc = ESC;
+  (void) ioctl(sno, TIOCSETC, (char *) &tchars);
+
+  while ((n_read = read(sno, buf, size)) > 0) {
+    buf[n_read] = '\0';
+    last_word = &buf[n_read - 1];
+    last_char = *last_word;
+    if (last_char == '\n' || n_read == size) {
+      (void) ioctl(sno, TIOCSETC, (char *) &oldtchars);
+      *last_word = '\0';
+      return(buf);
+    }
+    if (last_char == ESC) {
+      *last_word-- = '\0';
+      (void) fprintf(stdout, "\b\b  \b\b");
+    }
+    else {
+      names = array_alloc(char *, 10);
+      (void) fputc('\n', stdout);
+    }
+    for (; last_word >= buf; --last_word) {
+      if (strchr(seperator, *last_word) != NIL(char)) {
+	break;
+      }
+    }
+    last_word++;
+    file = strrchr(buf, '/');
+    if (file == NIL(char)) {
+      file = last_word;
+      modname = 0;
+      path = ".";
+    }
+    else {
+      *file++ = '\0';
+      modname = 1;
+      path = (*last_word == '~') ? util_tilde_expand(last_word) :
+	  last_word;
+    }
+    len = strlen(file);
+    dir = opendir(path);
+    if (dir == NIL(DIR) || len > MAXNAMLEN) {
+      (void) fputc(BEEP, stdout);
+    }
+    else {
+      *found = '\0';
+      maxlen = 0;
+      while ((dp = readdir(dir)) != NIL(struct dirent)) {
+	if (strncmp(file, dp->d_name, len) == 0) {
+	  if (last_char == ESC) {
+	    if (match(dp->d_name, found, file) == 0) {
+	      break;
+	    }
+	  }
+	  else if (len != 0 || *(dp->d_name) != '.') {
+	    if (maxlen < NAMLEN(dp)) {
+	      maxlen = NAMLEN(dp);
+	    }
+	    array_insert_last(char *, names, util_strsav(dp->d_name));
+	  }
+	}
+      }
+      (void) closedir(dir);
+	if (last_char == ESC) {
+	  if (*found == '\0' || strcmp(found, file) == 0) {
+	    (void) fputc(BEEP, stdout);
+	  }
+	  else {
+	    (void) strcpy(file, found);
+	    (void) fprintf(stdout, "%s", &buf[n_read - 1]);
+	  }
+	}
+	else {
+	  maxlen += 2;
+	  col = maxlen;
+	  array_sort(names, cmp);
+	  for (i = 0; i < array_n(names); i++) {
+	    name = array_fetch(char *, names, i);
+	    (void) fprintf(stdout, "%-*s", maxlen, name);
+	    FREE(name);
+	    col += maxlen;
+	    if (col >= 80) {
+	      col = maxlen;
+	      (void) fputc('\n', stdout);
+	    }
+	  }
+	  array_free(names);
+	  if (col != maxlen) {
+	    (void) fputc('\n', stdout);
+	  }
+	}
+      }
+      (void) fflush(stdout);
+      if (modname != 0) {
+	if (path != last_word) {
+	  FREE(path);
+	}
+	*--file = '/';
+      }
+
+#if HAVE_TERM_INTERRUPTS
+      /* mask interrupts temporarily */
+      omask = sigblock(sigmask(SIGINT));
+      (void) ioctl(STDOUT, TIOCGETP, (char *)&tty);
+      oldtty = tty;
+      tty.sg_flags &= ~(ECHO|CRMOD);
+      (void) ioctl(STDOUT, TIOCSETN, (char *)&tty);
+#endif
+
+      /* reprint prompt */
+      (void) write(STDOUT, "\r", 1);
+      print_prompt(prompt);
+
+      /* shove chars from buf back into the input queue */
+      for (i = 0; buf[i]; i++) {
+	(void) ioctl(STDOUT, TIOCSTI, &buf[i]);
+      }
+#if HAVE_TERM_INTERRUPTS
+      /* restore interrupts */
+      (void) ioctl(STDOUT, TIOCSETN, (char *)&oldtty);
+      (void) sigsetmask(omask);
+      (void) ioctl(STDOUT, TIOCLBIS, (char *) &pending);
+#endif
+    }
+    /* restore read() behavior */
+    (void) ioctl(sno, TIOCSETC, (char *) &oldtchars);
+    return(NIL(char));
+}
+
+#else
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+char *
+CmdFgetsFilec(
+  char * buf,
+  int  size,
+  FILE * stream,
+  char * prompt)
+{
+#if HAVE_LIBREADLINE
+  char *dupline;
+  char *cleanLine;
+#endif
+  char *line;
+  int sno;
+#if !HAVE_LIBREADLINE
+  int len;
+#endif
+
+  sno = fileno(stream);
+  if (sno != STDIN || !isatty(sno)){
+    if (prompt != NIL(char)){
+      (void) print_prompt(prompt);
+      (void) fflush(stdout);
+    }
+    return (fgets(buf, size, stream));
+  } else {
+#if HAVE_LIBREADLINE
+    /* Effectively read one line of input printing the prompt */
+    dupline = (char *)readline(prompt);
+    cleanLine = removeWhiteSpaces(dupline);
+
+    /* Check if an EOF has been read */
+    if (cleanLine != NIL(char)) {
+      /* If the line is non empty, add it to the history */
+      if (*cleanLine) {
+	add_history(cleanLine);
+      }
+
+      /* Copy the contents of cleanLine to buf, to simulate fgets */
+      strncpy(buf, cleanLine, size);
+      if ((int) strlen(cleanLine) >= size) {
+	buf[size-1] = '\0';
+      }
+      line = buf;
+    }
+    else {
+      line = NIL(char);
+    }
+    FREE(dupline);
+#else
+    /* Get rid of the trailing newline */
+    if (prompt != NIL(char)){
+      (void) print_prompt(prompt);
+      (void) fflush(stdout);
+    }
+    line = fgets(buf, size, stream);
+    if (line != NIL(char)) {
+      len = strlen(line);
+      if (len > 0 && line[len-1] == '\n') {
+	line[len-1] = '\0';
+      }
+    }
+#endif
+    return line;
+  }
+
+}
+
+#endif /* HAVE_IOCTL_WITH_TIOCGETC */
+
+
+#if HAVE_IOCTL_WITH_TIOCGETC
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static int
+cmp(
+  const void * s1,
+  const void * s2)
+{
+    return(strcmp(*(char **)s1, *(char **)s2));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static int
+match(
+  char * newmatch,
+  char * lastmatch,
+  char * actual)
+{
+  int i = 0;
+
+  if (*actual == '\0' && *newmatch == '.') {
+    return(1);
+  }
+  if (*lastmatch == '\0') {
+    (void) strcpy(lastmatch, newmatch);
+    return(1);
+  }
+  while (*newmatch++ == *lastmatch) {
+    lastmatch++;
+    i++;
+  }
+  *lastmatch = '\0';
+  return(i);
+}
+/* #endif */ /* defined(hpux) */
+
+#endif
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Simple history substitution routine.]
+
+  Description [Simple history substitution routine. Not, repeat NOT, the
+  complete csh history substitution mechanism.
+
+  In the following ^ is the SUBST character and ! is the HIST character.
+  Deals with:
+	!!			last command
+	!stuff			last command that began with "stuff"
+	!*			all but 0'th argument of last command
+	!$			last argument of last command
+	!:n			n'th argument of last command
+	!n			repeat the n'th command
+	!-n			repeat n'th previous command
+	^old^new		replace "old" w/ "new" in previous command
+
+
+  Trailing spaces are significant. Removes all initial spaces.
+
+  Returns `line' if no changes were made.  Returns pointer to a static buffer
+  if any changes were made.  Sets `changed' to 1 if a history substitution
+  took place, o/w set to 0.  Returns NULL if error occurred.]
+
+  SideEffects []
+
+******************************************************************************/
+char *
+CmdHistorySubstitution(
+  char * line,
+  int * changed)
+{
+  static char buf[1024], c;
+  char *value;
+  char *last, *old, *new_, *start, *b, *l;
+  int n, len, i, num, internal_change;
+
+  *changed = 0;
+  internal_change = 0;
+  while (isspace((int)(*line))) {
+    line++;
+  }
+  if (*line == '\0') {
+    return(line);
+  }
+  n = array_n(vm_commandHistoryArray);
+  last = (n > 0) ?
+    array_fetch(char *, vm_commandHistoryArray, n - 1) : (char *) "";
+
+  b = buf;
+  if (*line == SUBST) {
+    old = line + 1;
+    new_ = strchr(old, SUBST);
+    if (new_ == NIL(char)) {
+      goto bad_modify;
+    }
+    *new_++ = '\0';		      /* makes change in contents of line */
+    start = strstr(last, old);
+    if (start == NIL(char)) {
+      *--new_ = SUBST;
+      bad_modify:
+      (void) fprintf(vis_stderr, "** cmd error: Modifier failed\n");
+      return(NIL(char));
+    }
+    while (last != start) {
+      *b++ = *last++;
+    }
+    b = do_subst(b, new_);
+    last += strlen(old);
+    while ((*b++ = *last++)) {
+    }
+    *changed = 1;
+    return(buf);
+  }
+
+  if ((value = Cmd_FlagReadByName("history_char")) != NIL(char)){
+    visHistChar = *value;
+  }
+
+  for (l = line; (*b = *l); l++) {
+    if (*l == visHistChar) {
+      /*
+       * If a \ immediately preceeds a HIST char, pass just HIST char
+       * Otherwise pass both \ and the character.
+       */
+      if (l > line && l[-1] == '\\') {
+	b[-1] = visHistChar;
+	internal_change = 1;
+	continue;
+      }
+      if (n == 0) {
+	return(bad_event(0));
+      }
+      l++;
+      /* Cannot use a switch since the history char is a variable !!! */
+      if (*l == visHistChar){
+	/* replace !! in line with last */
+	b = do_subst(b, last);
+      }
+      else if (*l == '$'){
+	/* replace !$ in line with last arg of last */
+	b = do_subst(b, getarg(last, -1));
+      }
+      else if (*l == '*'){
+	b = do_subst(b, getarg(last, -2));
+      }
+      else if (*l == ':'){
+	/* replace !:n in line with n'th arg of last */
+	l++;
+	num = getnum(&l);
+	new_ = getarg(last, num);
+	if (new_ == NIL(char)) {
+	  (void) fprintf(vis_stderr, "** cmd error: Bad %c arg selector\n", visHistChar);
+	  return(NIL(char));
+	}
+	b = do_subst(b, new_);
+      }
+      else if (*l == '-'){
+	/* replace !-n in line with n'th prev cmd */
+	l++;
+	num = getnum(&l);
+	if (num > n || num == 0) {
+	  return(bad_event(n - num + 1));
+	}
+	b = do_subst(b, array_fetch(char *, vm_commandHistoryArray, n - num));
+      }
+      else {
+	/* replace !n in line with n'th command */
+	if (isdigit((int)(*l))) {
+	  num = getnum(&l);
+	  if (num > n || num == 0) {
+	    return(bad_event(num));
+	  }
+	  b = do_subst(b, array_fetch(char *, vm_commandHistoryArray, num - 1));
+	}
+	else {	/* replace !boo w/ last cmd beginning w/ boo */
+	  start = l;
+	  while (*l && strchr(seperator, *l) == NIL(char)) {
+	    l++;
+	  }
+	  c = *l;
+	  *l = '\0';
+	  len = strlen(start);
+	  for (i = n - 1; i >= 0; i--) {
+	    old = array_fetch(char *, vm_commandHistoryArray, i);
+	    if (strncmp(old, start, len) == 0) {
+	      b = do_subst(b, old);
+	      break;
+	    }
+	  }
+	  if (i < 0) {
+	    (void) fprintf(vis_stderr, "** cmd error: Event not found: %s\n", start);
+	    *l = c;
+	    return(NIL(char));
+	  }
+	  *l-- = c;
+
+	}
+      }
+      *changed = 1;
+    }
+    else {
+      b++;
+    }
+  }
+  if (*changed != 0 || internal_change != 0) {
+    return(buf);
+  }
+  return(line);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static int
+getnum(
+  char ** linep)
+{
+  int num = 0;
+  char *line = *linep;
+
+  for (; isdigit((int)(*line)); line++) {
+    num *= 10;
+    num += *line - '0';
+  }
+  *linep = line - 1;
+  return(num);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static char *
+getarg(
+  char * line,
+  int  num)
+{
+  static char buf[128];
+  char *b, *c;
+  int i;
+
+  if (num == -1) {
+    i = 123456;
+  }
+  else if (num == -2) {
+    i = 1;
+  }
+  else {
+    i = num;
+  }
+
+  c = line;
+  do {
+    b = line = c;
+    while (*line && strchr(seperator, *line) == NIL(char)) {
+      line++;
+    }
+    c = line;
+    while (*c && strchr(seperator, *c) != NIL(char)) {
+      c++;
+    }
+    if (*c == '\0') {
+      break;
+    }
+  } while (--i >= 0);
+
+  if (i > 0) {
+    if (num == -1) {
+      return(b);
+    }
+    return(NIL(char));
+  }
+  if (num < 0) {
+    return(b);
+  }
+  c = buf;
+  do {
+    *c++ = *b++;
+  } while (b < line && c < &buf[127]);
+  *c = '\0';
+  return(buf);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static char *
+bad_event(
+  int  n)
+{
+  (void) fprintf(vis_stderr, "** cmd error: Event %d not found\n", n);
+  return(NIL(char));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static char *
+do_subst(
+  char * dest,
+  char * new_)
+{
+  while ((*dest = *new_++)) {
+    dest++;
+  }
+  return(dest);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+print_prompt(
+  char * prompt)
+{
+  char buf[256];
+
+  if (prompt == NIL(char)) return;
+
+  while (*prompt != '\0') {
+    if (*prompt == visHistChar) {
+      (void) sprintf(buf, "%d", array_n(vm_commandHistoryArray) + 1);
+      if (write(STDOUT, buf, (int) strlen(buf)) == -1) exit(-1);
+    }
+    else {
+      if (write(STDOUT, prompt, 1) == -1) exit(-1);
+    }
+    prompt++;
+  }
+}
+
+#ifdef HAVE_LIBREADLINE
+/**Function********************************************************************
+
+  Synopsis [Removes tabs and spaces from the beginning and end of string.]
+
+  SideEffects        []
+
+******************************************************************************/
+static char *
+removeWhiteSpaces(
+  char *string)
+{
+  char *left;
+  char *right;
+
+  if (string == NIL(char)) {
+    return NIL(char);
+  }
+
+  /* Traverse the beginning of the string */
+  for (left = string; *left == ' ' || *left == '\t'; left++);
+
+  /* If we reached the end of the string */
+  if (*left == 0) {
+    return left;
+  }
+
+  /* Traverse the end of the string */
+  right = left + strlen(left) - 1;
+  while (right > left && (*right == ' ' || *right == '\t')) {
+    right--;
+  }
+  /* Set the new end of string */
+  *++right = '\0';
+
+  return left;
+} /* End of removeWhiteSpaces */
+#endif
Index: vis_dev/vis-2.3/src/cmd/cmdInt.h
===================================================================
--- vis_dev/vis-2.3/src/cmd/cmdInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/cmd/cmdInt.h	(revision 14)
@@ -0,0 +1,145 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [cmdInt.h]
+
+  PackageName [cmd]
+
+  Synopsis    [Internal declarations for command package.]
+
+  Author      [Originated from SIS]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: cmdInt.h,v 1.6 1998/09/18 17:08:00 rbloem Exp $]
+
+******************************************************************************/
+
+#ifndef _CMDINT
+#define _CMDINT
+
+#include "ntk.h"
+#include "cmd.h"
+
+#if STDC_HEADERS
+#  include <string.h>
+#  include <stdlib.h>
+#else
+extern void free();
+extern char *strncpy();
+extern char *strstr();
+extern char *strrchr();
+#endif
+
+/*
+ * This is for Solaris -- it needs to be convinced that we're actually
+ * using BSD-style calls in sys/ioctl.h, otherwise it doesn't find
+ * "ECHO" "CRMOD" and "TIOCSTI" when compiling cmdFile.c
+ */
+#define BSD_COMP
+
+#if IOCTL_WITH_TERMIOS
+#  include <sys/ioctl.h>
+#  include <sys/termios.h>
+#else
+#  if HAVE_SYS_IOCTL_H
+#    include <sys/ioctl.h>
+#  else
+#    if HAVE_SYS_TERMIOS_H
+#      include <sys/termios.h>
+#    endif
+#  endif
+#endif
+
+/* Linux and its wacky header files... */
+#if HAVE_BSD_SGTTY_H
+#  include <bsd/sgtty.h>
+#endif
+
+/* RB: include this header file on irix machines to get def of ttchars */
+#if NEED_TTOLD
+#  include <sys/ttold.h>
+#endif
+
+#if HAVE_SYS_SIGNAL_h
+#  include <sys/signal.h>
+#endif
+#if HAVE_SIGNAL_H
+#  include <signal.h>
+#endif
+
+/*
+ * No unix system seems to be able to agree on how to access directories,
+ * which cmdFile.c needs to do.  This solution, suggested by the autoconf
+ * distribution, seems to handle most of the nonsense.
+ */
+
+#if HAVE_DIRENT_H
+#  include <dirent.h>
+#  define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+#  define dirent direct
+#  define NAMLEN(dirent) (dirent)->d_namlen
+#  if HAVE_SYS_NDIR_H
+#    include <sys/ndir.h>
+#  endif
+#  if HAVE_SYS_DIR_H
+#    include <sys/dir.h>
+#  endif
+#  if HAVE_NDIR_H
+#    include <ndir.h>
+#  endif
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+typedef struct CmdAliasDescrStruct {
+  char *name;
+  int argc;
+  char **argv;
+} CmdAliasDescr_t;
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+extern avl_tree *cmdCommandTable;
+extern avl_tree *cmdFlagTable;
+extern avl_tree *cmdAliasTable;
+extern Hrc_Manager_t *cmdBackupHmgr;
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void CmdCommandFree(char * value);
+EXTERN char * CmdFgetsFilec(char * buf, int size, FILE * stream, char * prompt);
+EXTERN char * CmdFgetsFilec(char * buf, int size, FILE * stream, char * prompt);
+EXTERN char * CmdHistorySubstitution(char * line, int * changed);
+EXTERN void CmdFreeArgv(int argc, char ** argv);
+EXTERN void CmdAliasFree(char * value);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _CMDINT */
Index: vis_dev/vis-2.3/src/cmd/cmdMisc.c
===================================================================
--- vis_dev/vis-2.3/src/cmd/cmdMisc.c	(revision 14)
+++ vis_dev/vis-2.3/src/cmd/cmdMisc.c	(revision 14)
@@ -0,0 +1,2076 @@
+/**CFile***********************************************************************
+
+  FileName    [cmdMisc.c]
+
+  PackageName [cmd]
+
+  Synopsis    [Variable table; miscellaneous commands related to the general
+  system.]
+
+  Author      [SIS]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "cmdInt.h"
+#include <errno.h>
+
+static char rcsid[] UNUSED = "$Id: cmdMisc.c,v 1.59 2009/04/11 18:25:50 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+/* The maximum length of an input line */
+#define MAX_STR		32768
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+avl_tree *cmdAliasTable;
+avl_tree *cmdFlagTable;
+
+static boolean fileCreated;
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandTime(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandEcho(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandSetBddParameters(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandMemoryProfile(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandQuit(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandUsage(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandWhich(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandHistory(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandAlias(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandUnalias(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandSetVariable(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandUnsetVariable(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandHelp(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandSource(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static void print_alias(char * value);
+static char * command_alias_help(char * command);
+static void FlushBuffers(int sigtype);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Looks up value of flag in table of named values.]
+
+  Description [The command parser maintains a table of named values.  These
+  are manipulated using the 'set' and 'unset' commands.  The value of the
+  named flag is returned, or NIL(char) is returned if the flag has not been
+  set.]
+
+  SideEffects []
+
+******************************************************************************/
+char *
+Cmd_FlagReadByName(
+  char * flag)
+{
+  char *value;
+
+  if (avl_lookup(cmdFlagTable, flag, &value)) {
+    return value;
+  }
+  else {
+    return NIL(char);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Updates a set value by calling instead of set command.]
+
+  Description [Updates a set value by calling instead of set command.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Cmd_FlagUpdateValue(
+  char * key, char * value)
+{
+  char *oldValue, *newValue;
+
+  if (!key)
+    return;
+  if (value)
+    newValue = util_strsav(value);
+  else
+    newValue = util_strsav("");
+
+  if (avl_delete(cmdFlagTable, &key, &oldValue))
+    FREE(oldValue);
+
+  (void) avl_insert(cmdFlagTable, key, newValue);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Deletes a set value by calling instead of unset command.]
+
+  Description [Deletes a set value by calling instead of unset command.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Cmd_FlagDeleteByName(
+  char * key)
+{
+  char *value;
+
+  if (!key)
+    return;
+
+  if (avl_delete(cmdFlagTable, &key, &value)) {
+    FREE(key);
+    FREE(value);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the command package.]
+
+  SideEffects [Commands are added to the command table.]
+
+  SeeAlso     [Cmd_End]
+
+******************************************************************************/
+void
+Cmd_Init(void)
+{
+  char *path;
+  char *lib_name;
+
+
+  cmdCommandTable = avl_init_table((int(*)(const void *, const void *))strcmp);
+  cmdFlagTable = avl_init_table((int(*)(const void *, const void *))strcmp);
+  cmdAliasTable = avl_init_table((int(*)(const void *, const void *))strcmp);
+
+  Cmd_CommandAdd("alias", CommandAlias, 0);
+  Cmd_CommandAdd("echo", CommandEcho, 0);
+  Cmd_CommandAdd("help", CommandHelp, 0);
+  Cmd_CommandAdd("quit", CommandQuit, 0);
+  Cmd_CommandAdd("source", CommandSource, 0);
+/*  Cmd_CommandAdd("undo", CommandUndo, 0); */
+  Cmd_CommandAdd("set", CommandSetVariable, 0);
+  Cmd_CommandAdd("unalias", CommandUnalias, 0);
+  Cmd_CommandAdd("unset", CommandUnsetVariable, 0);
+  Cmd_CommandAdd("time", CommandTime, 0);
+  Cmd_CommandAdd("usage", CommandUsage, 0);
+  Cmd_CommandAdd("history", CommandHistory, 0);
+  Cmd_CommandAdd("which", CommandWhich, 0);
+  Cmd_CommandAdd("set_bdd_parameters" , CommandSetBddParameters, 0);
+  Cmd_CommandAdd("_memory_profile", CommandMemoryProfile, 0);
+  fileCreated = FALSE;
+
+  /* Program the signal of type USR1 to flush vis_stdout and vis_stderr */
+#ifdef SIGUSR1
+  (void) signal(SIGUSR1, FlushBuffers);
+#endif
+
+  /* set the default open_path */
+  lib_name = Vm_VisObtainLibrary();
+  path = ALLOC(char, strlen(lib_name) + 20);
+  sprintf(path, "set open_path .:%s", lib_name);
+  Cmd_CommandExecute(NULL, path);
+  FREE(lib_name);
+  FREE(path);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Ends the command package.]
+
+  Description [Ends the command package. Tables are freed, and the global
+  error string is freed.]
+
+  SideEffects []
+
+  SeeAlso     [Cmd_Init]
+
+******************************************************************************/
+void
+Cmd_End(void)
+{
+  avl_free_table(cmdFlagTable, (void (*)(char *))free, (void (*)(char *))free);
+  avl_free_table(cmdCommandTable, (void (*)(char *)) 0, CmdCommandFree);
+  avl_free_table(cmdAliasTable, (void (*)(char *)) 0, CmdAliasFree);
+  if (cmdBackupHmgr != NIL(Hrc_Manager_t)) {
+    Hrc_ManagerFree(cmdBackupHmgr);
+  }
+  error_cleanup();
+
+  if (fileCreated == TRUE) {
+    (void) fprintf(vis_stdout, "Purify has created a temporary file. The file");
+    (void) fprintf(vis_stdout, " must be deleted.\n");
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Test that the given string is an integer. Returns 0 if string is
+  not an integer, 1 if the integer is too big for int, and 2 if integer fits
+  in int.]
+
+  SideEffects [Sets the pointer value if the string is an integer small enough
+  for int.]
+
+******************************************************************************/
+int
+Cmd_StringCheckIsInteger(
+  char *string,
+  int *value)
+{
+  char *ptr;
+  long l;
+
+  errno = 0 ;
+  l = strtol (string, &ptr, 0) ;
+  if(*ptr != '\0')
+    return 0;
+  if (errno != 0)
+    return 1;
+  if ((l > MAXINT) || (l < -1 - MAXINT))
+    return 1 ;
+  *value = (int) l;
+  return 2 ;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CmdFreeArgv(int  argc,  char ** argv)
+{
+  int i;
+
+  for(i = 0; i < argc; i++) {
+    FREE(argv[i]);
+  }
+  FREE(argv);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+void
+CmdAliasFree(
+  char * value)
+{
+  CmdAliasDescr_t *alias = (CmdAliasDescr_t *) value;
+
+  CmdFreeArgv(alias->argc, alias->argv);
+  FREE(alias->name);		/* same as key */
+  FREE(alias);
+}
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis          [Implements the time command.]
+
+  CommandName       [time]
+  CommandSynopsis   [provide a simple elapsed time value]
+  CommandArguments [\[-h\]\[-u\]]
+  CommandDescription [Prints the processor time used since the last time
+  command, and the total processor time used since VIS was started. <p>
+  By default, the time reported is the CPU time spent executing instructions
+  of the calling process and the time this process waited for children that
+  terminated.<p>
+  Command options:<p>
+  <dl><dt> -h
+  <dd> Print the command usage.
+  </dl>
+  <dl><dt> -u
+  <dd> Exclude child process time.
+  </dl>]
+
+  SideEffects        []
+
+******************************************************************************/
+static int
+CommandTime(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  static long last_time_u = 0;
+  static long last_time_c = 0;
+  long time;
+  int c;
+  boolean excludeChildren = FALSE;
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc,argv,"hu")) != EOF){
+    switch(c){
+    case 'h':
+      goto usage;
+    case 'u':
+      excludeChildren = TRUE;
+      break;
+    default:
+      goto usage;
+    }
+  }
+
+  if (argc != util_optind) {
+    goto usage;
+  }
+
+  if (excludeChildren) {
+    time = util_cpu_time();
+    (void) fprintf(vis_stdout,
+		   "elapse: %2.1f seconds, total: %2.1f seconds\n",
+		   (time - last_time_u) / 1000.0, time / 1000.0);
+    last_time_u = time;
+  } else {
+    time = util_cpu_ctime();
+    (void) fprintf(vis_stdout,
+		   "elapse: %2.1f seconds, total: %2.1f seconds\n",
+		   (time - last_time_c) / 1000.0, time / 1000.0);
+    last_time_c = time;
+  }
+  return 0;
+
+usage:
+  (void) fprintf(vis_stderr, "usage: time [-h][-u]\n");
+  (void) fprintf(vis_stderr, "   -h \t\tprint the command usage\n");
+  (void) fprintf(vis_stderr, "   -u \t\texclude child process time\n");
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [Implements the echo command.]
+
+  CommandName        [echo]
+  CommandSynopsis    [merely echo the arguments]
+  CommandArguments   [\[-h\] &lt;args&gt;]
+  CommandDescription [Echoes the arguments to standard output.<p>
+  Command options:<p>
+  <dl><dt> -h
+  <dd> Print the command usage.
+  </dl>]
+
+  SideEffects        []
+
+******************************************************************************/
+static int
+CommandEcho(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int i;
+  int c;
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "h")) != EOF) {
+    switch(c) {
+      case 'h':
+	goto usage;
+      default:
+	goto usage;
+    }
+  }
+
+  for(i = 1; i < argc; i++) {
+    (void) fprintf(vis_stdout, "%s ", argv[i]);
+  }
+  (void) fprintf(vis_stdout, "\n");
+  return 0;
+
+  usage:
+  (void) fprintf(vis_stderr, "usage: echo [-h] string \n");
+  (void) fprintf(vis_stderr, "   -h \t\tprint the command usage\n");
+  return (1);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the set_bdd_parameters command.]
+
+  SideEffects []
+
+  CommandName [set_bdd_parameters]
+
+  CommandSynopsis [Creates a table with the value of all the flags currently
+  active in VIS and calls the function bdd_set_parameters with the manager of
+  the current place in the hierarchy and the table.]
+
+  CommandArguments [\[-h\]\[-s\]]
+
+  CommandDescription [The command obtains the bdd manager of the current point
+  in the hierarchy. Given this manager and the set of pairs (variable,value) of
+  the VIS environment, the function sets specific BDD parameters to the given
+  values. This command works in conjunction with print_bdd_stats.<p>
+
+  Print_bdd_stats first prints a report of the parameters and statistics of the
+  current bdd_manager. By using the command "set", the user may modify the
+  value of any of the parameters of the underlying bdd package. The way to do
+  it is by setting a value in the variable <tt>BDD.parameter name</tt> where
+  <tt>parameter name<\tt> is the name of the parameter exactly as printed by
+  the print_bdd_stats command. In order to "re-program" the underlying bdd
+  package this command must be invoked.<p>
+
+  Command options:<p>
+
+  <dl>
+
+  <dt> -h
+  <dd> Print the command usage.
+
+  <dt> -s
+  <dd> Print the bdd parameter and statistics after the modification.
+
+  </dl>
+  ]
+
+******************************************************************************/
+static int
+CommandSetBddParameters(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  Ntk_Network_t *network;
+  boolean  showAfter;
+  int      c;
+
+  showAfter = FALSE;
+  network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+
+  /*
+   * Parse the command line.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "hs")) != EOF) {
+    switch (c) {
+      case 'h':
+	goto usage;
+      case 's':
+	showAfter = TRUE;
+	break;
+      default:
+	goto usage;
+    }
+  }
+
+  /* flatten_hierarchy and static_order must have been invoked already. */
+  if (network == NIL(Ntk_Network_t)) {
+    return 1;
+  }
+  if (!Ntk_NetworkReadMddManager(network)) {
+    (void) fprintf(vis_stderr, "The MDD variables have not been ordered. ");
+    (void) fprintf(vis_stderr, "Use static_order.\n");
+    return 1;
+  }
+
+  /* Create the table of variable->value */
+  bdd_set_parameters(Ntk_NetworkReadMddManager(network), cmdFlagTable,
+		     vis_stdout);
+
+  if (showAfter) {
+    bdd_print_stats(Ntk_NetworkReadMddManager(network), vis_stdout);
+  }
+
+  return 0;  /* Everything okay */
+
+usage:
+  (void) fprintf(vis_stderr, "usage: set_bdd_parameters [-h] [-s]\n");
+  (void) fprintf(vis_stderr, "   -h  print the command usage\n");
+  (void) fprintf(vis_stderr, "   -s  print also the bdd statistics\n");
+
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the _memory_profile command.]
+
+  CommandName [_memory_profile]
+
+  CommandSynopsis [It shows the amount of memory used by every pacakge.]
+
+  CommandArguments [\[-f &lt;filename&gt;\] \[-h\] \[-p\] \[-u &lt;units&gt;\]]
+
+  CommandDescription [This command intregrates the output from purify with a
+  function map generated by a perlscript plus another perlscript to generate a
+  memory profile of vis.<p>
+
+  This command relies on the output of purify to a file to call the script
+  "memoryaccount" and produce a summary of how much memory has been allocated
+  by each package. Although this command may appear simple it requires the
+  interaction of two scripts and three files, so special care should be taken
+  when attempting to modify it.<p>
+
+  Here is the way it works. The code in this command is conditionally compiled
+  depending on the definition of the symbol <tt>PURIFY</tt>. If the symbol is
+  not defined, the program prints a message notifying that the command is not
+  operative in this executable. If <tt>PURIFY</tt> has been defined, there are
+  certain things that are assumed. The executable has been linked with
+  purify. The output of purify is being redirected to a file with name
+  <tt>purify.log</tt>. The perl script <tt>memoryaccount</tt> is in
+  <tt>$VIS/common/share</tt> and it is executable. There exists a file mapping
+  function names to packages in the same place whose name is <tt>.fmap</tt>.<p>
+
+  The command then calls <tt>purify_all_inuse()</tt> to force purify to dump to
+  the file <tt>purify.log</tt> the information about the memory that is
+  currently visible to the program. This memory is not the total memory
+  allocated by the program since there may be leaked memory that is no longer
+  accessible. A temporary file is created and the script <tt>memoryaccount</tt>
+  is called to analyze the file <tt>purify.log</tt> and write in the temporary
+  file the memory profile obtained from it. Once the script is done, the
+  temporary file is dumped to <tt>vis_stdout</tt> and deleted.<p>
+
+  Since most of the computation in this command is done by the pearlscript
+  <tt>memoryaccount</tt>, for more information please refer to the message
+  printed when the script is invoked with the option <tt>-h</tt>.
+
+  Command options:<p>
+
+  <dl>
+  <dt> -f &lt;filename&gt;
+  <dd> File to read the dump from. The default is purify.log. This option
+  should be used if and only if the option <tt>-log-file</tt> has been used at
+  the linking stage when building the executable.
+  <dt> -h
+  <dd> Print the command usage.
+  <dt> -p
+  <dd> Print also the packages that did not allocated any visible memory
+  <dt> -u &lt;units&gt;
+  <dd> Units to print the memory usage in. It may be "b" for
+  bytes, "k" for kilobytes, "m" for megabytes and "g" for gigabytes. The default
+  is bytes.
+  </dl>
+  ]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandMemoryProfile(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+
+  int   c;
+  char  options[128];
+#ifdef PURIFY
+  char  tmpFileName[128];
+  FILE  *fp;
+  char  command[256];
+  char  *visDirectoryName;
+  int   systemStatus;
+#endif
+
+  /*
+   * Parse command line options.
+   */
+  options[0] = 0;
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "f:hpu:")) != EOF) {
+    switch(c) {
+      case 'f':
+	strcat(options, " -f ");
+	strcat(options, util_optarg);
+	break;
+      case 'h':
+	goto usage;
+      case 'p':
+	strcat(options, " -p ");
+	break;
+      case 'u':
+	strcat(options, " -u ");
+	strcat(options, util_optarg);
+	break;
+      default:
+	goto usage;
+    }
+  }
+
+
+#ifdef PURIFY
+  /* Flag to remember that a file has been created by purify */
+  fileCreated = TRUE;
+
+  /* Obtain the name of a temporary file */
+  tmpnam(tmpFileName);
+
+  /* Kick purify to dump the data in the file */
+  purify_all_inuse();
+
+  /* Obtain the path to the perl script */
+  visDirectoryName = Vm_VisObtainLibrary();
+
+  /* Prepare the string to be sent to a shell */
+  (void)sprintf(command, "%s/memoryaccount %s %s/.fmap ./.fmap >%s",
+		visDirectoryName, options, visDirectoryName,
+		tmpFileName);
+
+  /* Effectively execute the perlscript */
+  systemStatus = system(command);
+  if (systemStatus != 0) {
+    return 1;
+  }
+
+  fp = Cmd_FileOpen(tmpFileName, "r", NIL(char *), 1);
+
+  /* Check if the open has been successful */
+  if (fp == NIL(FILE)) {
+    (void) fprintf(vis_stderr, "** cmd error: File %s was not found\n", tmpFileName);
+    return 1;
+  }
+
+  /* Dump the contents of the result file in vis_stdout */
+  while(fgets(command, 128, fp) != NIL(char)) {
+    (void) fprintf(vis_stdout, "%s", command);
+  }
+  fclose(fp);
+
+  /* Remove the temporary file */
+#if HAVE_UNLINK
+  unlink(tmpFileName);
+#endif
+#else
+  (void) fprintf(vis_stderr, "** cmd error: Command not available: Vis has not been ");
+  (void) fprintf(vis_stderr, "compiled with purify.\n");
+#endif
+
+  return 0;		/* normal exit */
+
+  usage:
+  (void) fprintf(vis_stderr, "usage: _memory_profile [-f <filename>] [-h] ");
+  (void) fprintf(vis_stderr, "[-p] [-u <units>] <filenames>\n");
+  (void) fprintf(vis_stderr, "   -f <file>\tFile to read the purify dump");
+  (void) fprintf(vis_stderr, " from. The default is purify.log\n");
+  (void) fprintf(vis_stderr, "   -h\t\tprint the command usage\n");
+  (void) fprintf(vis_stderr, "   -p\t\tPrint also the packages that do not ");
+  (void) fprintf(vis_stderr, " allocate any memory\n");
+  (void) fprintf(vis_stderr, "   -u <units>\tUnits to print the memory usage");
+  (void) fprintf(vis_stderr, " in. It may be b for bytes\n");
+  (void) fprintf(vis_stderr, "     \t\tk for kilobytes, m for megabytes and ");
+  (void) fprintf(vis_stderr, "g for gigabutes.\n");
+  return 1;		/* error exit */
+}
+
+
+/**Function********************************************************************
+
+  Synopsis          [Implements the quit command.]
+
+  Description [A return value of -1 indicates a quick quit, -2 return frees
+  the memory.]
+
+  CommandName       [quit]
+  CommandSynopsis   [exit VIS]
+  CommandArguments  [\[-h\] \[-s\]]
+  CommandDescription [Stops the program.  Does not save the current network
+  before exiting.<p>
+  Command options:<p>
+  <dl><dt> -h
+  <dd> Print the command usage.
+  </dl>
+  <dl><dt> -s
+  <dd> Free all the memory before quitting.
+  This is slower, and is used for finding memory leaks.
+  </dl>
+  ]
+
+  SideEffects        []
+
+******************************************************************************/
+static int
+CommandQuit(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int c;
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc,argv,"hs")) != EOF){
+    switch(c){
+      case 'h':
+	goto usage;
+      case 's':
+	return -2;
+      default:
+	goto usage;
+    }
+  }
+
+  if ( argc != util_optind){
+    goto usage;
+  }
+  return -1;
+
+  usage:
+    (void)fprintf(vis_stderr, "usage: quit [-h] [-s]\n");
+    (void)fprintf(vis_stderr, "   -h  print the command usage\n");
+    (void)fprintf(vis_stderr, "   -s  frees all the memory before quitting\n");
+    return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis          [Implements the usage command.]
+
+  CommandName       [usage]
+  CommandSynopsis   [provide a dump of process statistics]
+  CommandArguments  [\[-h\]]
+  CommandDescription [Prints a formatted dump of processor-specific usage
+  statistics. For Berkeley Unix, this includes all of the information in the
+  getrusage() structure.<p>
+  Command options:<p>
+  <dl><dt> -h
+  <dd> Print the command usage.
+  </dl> ]
+
+  SideEffects        []
+
+******************************************************************************/
+static int
+CommandUsage(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int c;
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc,argv,"h")) != EOF){
+    switch(c){
+      case 'h':
+	goto usage;
+      default:
+	goto usage;
+    }
+  }
+
+  if (argc != util_optind){
+    goto usage;
+  }
+  util_print_cpu_stats(vis_stdout);
+  return 0;
+
+  usage:
+    (void) fprintf(vis_stderr, "usage: usage [-h]\n");
+    (void) fprintf(vis_stderr, "   -h \t\tprint the command usage\n");
+    return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis          [Implements the which command.]
+
+  CommandName       [which]
+  CommandSynopsis   [look for a file called name]
+  CommandArguments  [\[-h\] &lt;file_name&gt;]
+  CommandDescription [Looks for a file in a set of directories
+  which includes the current directory as well as those in the VIS path.
+  If it finds it, it reports the path.
+  The path is specified through the "set open_path" command in the .visrc.<p>
+  Command options:<p>
+  <dl><dt> -h
+  <dd> Print the command usage.
+  </dl>
+  <dl><dt> &lt;file_name&gt;
+  <dd> File to be searched
+  </dl>]
+
+  SideEffects       []
+
+  SeeAlso           [set]
+
+******************************************************************************/
+static int
+CommandWhich(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  FILE *fp;
+  char *filename;
+  int c;
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc,argv,"h")) != EOF){
+    switch(c){
+      case 'h':
+	goto usage;
+      default:
+	goto usage;
+    }
+  }
+
+  if (argc-1 != util_optind){
+    goto usage;
+  }
+
+  fp = Cmd_FileOpen(argv[1], "r", &filename, 0);
+  if (fp != 0) {
+    (void) fprintf(vis_stdout, "%s\n", filename);
+    (void) fclose(fp);
+  }
+  FREE(filename);
+  return 0;
+
+  usage:
+    (void)fprintf(vis_stderr,"usage: which [-h] file_name\n");
+    (void) fprintf(vis_stderr, "   -h \t\tprint the command usage\n");
+    return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis          [Implements the history command.]
+
+  CommandName       [history]
+
+  CommandSynopsis   [list previous commands and their event numbers]
+
+  CommandArguments  [\[-h\] \[&lt;num&gt;\]]
+
+  CommandDescription [Lists previous commands and their event numbers.
+  This is a UNIX-like history mechanism inside the VIS shell.<p>
+  Command options:<p>
+  <dl><dt> -h
+  <dd> Print the command usage.
+  </dl>
+  <dl><dt> &lt;num&gt;
+  <dd> Lists the last &lt;num&gt; events.  Lists the last
+  30 events if &lt;num&gt; is not specified.
+  </dl><p>
+
+  History Substitution:<p>
+
+  The history substitution mechanism is a simpler version of the csh history
+  substitution mechanism.  It enables you to reuse words from previously typed
+  commands.<p>
+
+  The default history substitution character is the `%' (`!' is default for
+  shell escapes, and `#' marks the beginning of a comment). This can be changed
+  using the "set" command. In this description '%' is used as the history_char.
+  The `%' can appear anywhere in a line.  A line containing a history
+  substitution is echoed to the screen after the substitution takes place.
+  `%' can be preceded by a `\\' in order to escape the substitution,
+  for example, to enter a `%' into an alias or to set the prompt.<br><p>
+
+  Each valid line typed at the prompt is saved.  If the "history" variable
+  is set (see help page for "set"), each line is also echoed to the history
+  file.  You can use the "history" command to list the previously typed
+  commands. <p>
+
+  Substitutions: <p>
+
+  At any point in a line these history substitutions are
+  available.<p>
+	<dl><dt>%:0   <dd>  Initial word of last command.</dl>
+	<dl><dt>%:n   <dd>   n-th argument of last command.</dl>
+	<dl><dt>%$    <dd>   Last argument of last command.</dl>
+	<dl><dt>%*    <dd>   All but initial word of last command.</dl>
+
+	<dl><dt>%%    <dd>   Last command.</dl>
+	<dl><dt>%stuf <dd>   Last command beginning with "stuf".</dl>
+	<dl><dt>%n    <dd>   Repeat the n-th command.</dl>
+	<dl><dt>%-n   <dd>   Repeat the n-th previous command.</dl>
+	<dl><dt>^old^new  <dd>       Replace "old" with "new" in previous command.
+	Trailing spaces are significant during substitution.
+	Initial spaces are not significant.</dl>  ]
+
+  SideEffects        []
+
+  SeeAlso            [set]
+
+******************************************************************************/
+static int
+CommandHistory(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int i, num, lineno;
+  int size;
+  int c;
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "h")) != EOF) {
+    switch(c) {
+      case 'h':
+	goto usage;
+      default:
+	goto usage;
+    }
+  }
+
+  if (argc > 3) {
+    goto usage;
+  }
+  num = 30;
+  lineno = 1;
+  for (i = 1; i < argc; i++) {
+    if (argv[i][0] == '-') {
+      if (argv[i][1] == 'h') {
+	lineno = 0;
+      }
+      else {
+	goto usage;
+      }
+    }
+    else {
+      num = atoi(argv[i]);
+      if (num <= 0) {
+	goto usage;
+      }
+    }
+  }
+  size = array_n(vm_commandHistoryArray);
+  num = (num < size) ? num : size;
+  for (i = size - num; i < size; i++) {
+    if (lineno != 0) {
+      (void) fprintf(vis_stdout, "%d\t", i + 1);
+    }
+    (void) fprintf(vis_stdout, "%s\n", array_fetch(char *, vm_commandHistoryArray, i));
+  }
+  return(0);
+
+usage:
+  (void) fprintf(vis_stderr, "usage: history [-h] [num]\n");
+  (void) fprintf(vis_stderr, "   -h \t\tprint the command usage\n");
+  (void) fprintf(vis_stderr, "   num \t\tprint the last num commands\n");
+  return(1);
+}
+
+
+
+
+/**Function********************************************************************
+
+  Synopsis          [Implements the alias command.]
+
+  CommandName       [alias]
+
+  CommandSynopsis   [provide an alias for a command]
+
+  CommandArguments  [\[-h\] \[&lt;name&gt; \[&lt;string&gt;\]\]]
+
+  CommandDescription [The "alias" command, if given no arguments, will print
+  the definition of all current aliases.  <p>
+
+  Given a single argument, it will print the definition of that alias (if any).
+
+  Given two arguments, the keyword "name" becomes an alias for
+  the command string "string", replacing any other alias with the
+  same name.<p>
+
+  Command options:
+  <dl><dt> -h
+  <dd> Print the command usage.
+  </dl>
+  <dl><dt> &lt;name&gt;
+  <dd> Alias
+  </dl>
+  <dl><dt> &lt;string&gt;
+  <dd> Command string
+  </dl>
+
+  It is possible to create aliases that take arguments by using the history
+  substitution mechanism.  To protect the history substitution character `%'
+  from immediate expansion, it must be preceded by a `\\' when entering the
+  alias. <p>
+
+  For example:<p>
+  <pre>
+   vis> alias read read_\\%:1 \\%:2.\\%:1
+   vis> read blif lion
+  </pre>
+  will create an alias `read', execute "read_blif lion.blif".  <p>
+
+  And...<p>
+  <pre>
+  vis> alias echo2 "echo Hi ; echo \\%* !"
+  vis> echo2 happy birthday
+  </pre>
+  will print:<p>
+  <pre>
+  Hi
+  happy birthday !
+  </pre>
+
+  CAVEAT: Currently there is no check to see if there is a circular
+  dependency in the alias definition. e.g.<p>
+
+  <pre>
+  vis> alias foo "print_network_stats; print_network; foo"
+  </pre>
+
+  creates an alias which refers to itself. Executing the command "foo" will
+  result an infinite loop during which the commands "print_network_stats"
+  and "print_network" will be executed.<p>
+
+   ]
+
+  SideEffects        []
+
+  SeeAlso            [unalias]
+
+******************************************************************************/
+static int
+CommandAlias(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int i;
+  char *key, *value;
+  CmdAliasDescr_t *alias;
+  avl_generator *gen;
+  int status;
+  int c;
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "h")) != EOF) {
+    switch(c) {
+      case 'h':
+	goto usage;
+      default:
+	goto usage;
+    }
+  }
+
+
+  if (argc == 1) {
+    avl_foreach_item(cmdAliasTable, gen, AVL_FORWARD, &key, &value) {
+      print_alias(value);
+    }
+    return 0;
+
+  }
+  else if (argc == 2) {
+    if (avl_lookup(cmdAliasTable, argv[1], &value)) {
+      print_alias(value);
+    }
+    return 0;
+  }
+
+  /* delete any existing alias */
+  key = argv[1];
+  if (avl_delete(cmdAliasTable, &key, &value)) {
+    CmdAliasFree(value);
+  }
+
+  alias = ALLOC(CmdAliasDescr_t, 1);
+  alias->name = util_strsav(argv[1]);
+  alias->argc = argc - 2;
+  alias->argv = ALLOC(char *, alias->argc);
+  for(i = 2; i < argc; i++) {
+    alias->argv[i-2] = util_strsav(argv[i]);
+  }
+  status = avl_insert(cmdAliasTable, alias->name, (char *) alias);
+  assert(!status);  /* error here in SIS version, TRS, 8/4/95 */
+  return 0;
+
+  usage:
+    (void) fprintf(vis_stderr, "usage: alias [-h] [command [string]]\n");
+    (void) fprintf(vis_stderr, "   -h \t\tprint the command usage\n");
+    return (1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [Implements the unalias command.]
+
+  CommandName        [unalias]
+  CommandSynopsis    [remove the definition of an alias.]
+  CommandArguments   [\[-h\] &lt;alias_names&gt;]
+  CommandDescription [Removes the definition of an alias.<p>
+  Command options:<p>
+  <dl><dt> -h
+  <dd> Print the command usage.
+  </dl>
+  <dl><dt> &lt;alias_names&gt;
+  <dd> Aliases to be removed
+  </dl>]
+
+  SideEffects        []
+
+  SeeAlso            [alias]
+
+******************************************************************************/
+static int
+CommandUnalias(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int i;
+  char *key, *value;
+  int c;
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "h")) != EOF) {
+    switch(c) {
+      case 'h':
+	goto usage;
+      default:
+	goto usage;
+    }
+  }
+
+  if (argc < 2) {
+    goto usage;
+  }
+
+  for(i = 1; i < argc; i++) {
+    key = argv[i];
+    if (avl_delete(cmdAliasTable, &key, &value)) {
+      CmdAliasFree(value);
+    }
+  }
+  return 0;
+
+  usage:
+    (void) fprintf(vis_stderr, "usage: unalias [-h] alias_names\n");
+    (void) fprintf(vis_stderr, "   -h \t\tprint the command usage\n");
+    return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis          [Implements the set command.]
+
+  CommandName       [set]
+
+  CommandSynopsis   [set an environment variable]
+
+  CommandArguments  [\[-h\] \[&lt;name&gt;\] \[&lt;value&gt;\]]
+
+  CommandDescription [ A variable environment is maintained by the command
+  interpreter.
+  The "set" command sets a variable to a particular value, and the
+  "unset" command removes the definition of a variable.
+  If "set" is given no arguments, it prints the current value of all variables.<p>
+
+  Command options:<p>
+  <dl> <dt> -h
+  <dd> Print the command usage.
+  </dl>
+  <dl> <dt> &lt;name&gt;
+  <dd> Variable name
+  </dl>
+  <dl> <dt> &lt;value&gt;
+  <dd> Value to be assigned to the variable.
+  </dl>
+
+ <p>
+  Interpolation of variables is allowed when using the set command. The
+  variables are  referred to with the prefix of '$'. So for example, the following
+  can be done to check the value of a set variable:<br>
+  <code>
+  vis> set foo bar <br>
+  vis> echo $foo <br>
+  bar <br>
+  </code>
+
+  The last line "bar" will the output produced by vis.<p>
+
+  Variables can be extended by using the character ':' to concatenate
+  values. For example : <br>
+  <code>
+  vis> set foo bar <br>
+  vis> set foo $foo:foobar <br>
+  vis> echo $foo <br>
+  bar:foobar <br>
+  </code>
+  The variable <code> foo </code> is extended with the value <code>
+  foobar </code>. <p>
+
+  Whitespace characters may be present within quotes. However, variable
+  interpolation lays the restriction that the characters ':' and '/' may
+  not be used within quotes. This is to allow for recursive interpolation.
+  So for example, the following is allowed<br>
+    <code>
+  vis> set "foo bar" this <br>
+  vis> echo $"foo bar"<br>
+  this <br>
+  </code>
+  The last line will be the output produced by vis. <br>
+  But in the following, the  value of the variable <code> foo/bar </code>
+  will not be interpreted correctly:<p>
+  <code>
+  vis> set "foo/bar" this <br>
+  vis> echo $"foo/bar" <br>
+  foo/bar <br>
+  </code>
+  If a variable is not set by the "set" command, then the variable is returned
+  unchanged.
+  <p>
+
+  Different commands use environment information for different purposes.
+  The command interpreter makes use of the following parameters:<p>
+
+ <dl>
+ <dt><b>autoexec</b>
+ <dd>     Defines a command string to be automatically executed after every
+	   command processed by the command interpreter.
+	   This is useful for things like timing commands, or tracing the
+	   progress of optimization.
+</dl>
+
+
+ <dl><dt><b>open_path</b>
+ <dd>      "open_path" (in analogy to the shell-variable PATH) is a list of
+	   colon-separated strings giving directories to be searched whenever
+	   a file is opened for read.  Typically the current directory (.) is
+	   first in this list.  The standard system library (typically
+	   $VIS_LIBRARY_PATH) is always implicitly appended to the current path.
+	   This provides a convenient short-hand mechanism for reaching
+	   standard library files.
+ </dl>
+ <dl><dt> <b>vis_stderr </b>
+ <dd>   Standard error (normally stderr) can be re-directed to a file
+	   by setting the variable vis_stderr.
+ </dl>
+
+ <dl><dt>  <b>vis_stdout</b>
+ <dd>           Standard output (normally stdout) can be re-directed to a file
+	   by setting the variable vis_stdout.
+ </dl>
+
+ Building MDDs for the network makes use of following setting:
+ <dl><dt> <b>partition_method</b>
+ <dd> This parameter is used to select the method for creating the
+ partition.  The vertices of a partition correspond to the
+  combinational inputs, combinational outputs, and any intermediate nodes used.  Each vertex has a multi-valued
+  function (represented by MDDs) expressing the function of the corresponding
+  network node in terms of the partition vertices in its transitive fanin.
+  Hence, the MDDs of the partition represent a partial collapsing of the
+  network. The possible values of partition_method are:
+  <dl>
+  <dt> <b>inout</b>
+  <dd>Expresses the combinational outputs in terms of the
+  combinational inputs. This is the default partitioning method.
+
+  <dt> <b>total</b>
+  <dd> The partition built is isomorphic to the combinational
+  part of the network.  The function of each node is expressed in terms of its
+  immediate fanins.
+
+  <dt> <b>frontier</b>
+  <dd> The partition built contains the combinational part of the
+  network as well as vertices corresponding to some intermediate
+  nodes. These vertices are generated to control the MDD sizes of the
+  combinational outputs. The number of intermediate variables can be
+  controlled by the parameter "partition_threshold". The method
+  "inout" and "total" are special cases of this method (corresponding
+  to a partition_threshold of infinity and 0 respectively).
+
+  </dl>
+  </dl>
+ <dl><dt> <b>partition_threshold</b>
+ <dd> This parameter is used in
+ conjuction with the selection of "frontier" as partition method. This
+ determines the threshold at which a new MDD variable is created in
+ the partition.
+ </dl>
+
+ Image computation makes use of following settings:
+
+ <dl>
+   <dt><b>image_method</b>
+   <dd> The "image_method" parameter is used to control the image method used
+   in various symbolic analysis techniques. Currently, two image methods are
+   implemented. Use "set image_method &lt;method&gt;" to choose the appropriate
+   method.
+
+   <dl>
+     <dt><b>monolithic</b>
+     <dd> This is the most naive approach possible. However, this method is not
+     suitable for circuits with more than 20 latches.
+
+     <dt><b>tfm</b>
+     <dd> This is the pure transition function method. This method is supposed
+     not to be used in general fixpoint computations. Approximate traversal is
+     an application of this method. Basically this method is made as a part of
+     hybrid method. For more detailed options, see the help of
+     print_tfm_options command.
+
+     <dt><b>hybrid</b>
+     <dd> This is a hybrid method combining transition relation and function
+     methods. Transition relation method is based on conjunction of partitioned
+     transition relation, whereas transition function method is based on
+     splitting on an input or output variable recursively.  The hybrid method
+     choose either splitting or conjunction at each recursion dynamically using
+     the dependence matrix. For details, refer to the paper "To split or to
+     Conjoin: The Question in Image Computation" by In-Ho Moon, James Kukula,
+     Kavita Ravi, and Fabio Somenzi, DAC'00. Also for more detailed options,
+     see the help of print_hybrid_options command.
+
+     <dt><b>iwls95</b>
+	  <dd> This technique is based on the early variable quantification and
+     related heuristics of Ranjan, et al.  "Efficient BDD Algorithms for FSM
+     Synthesis and Verification", IWLS 1995. First, from the given multivalued
+     functions, bit level relations are created. These relations are then
+     clustered based on the value of threshold value controlled by
+     <b>image_cluster_size</b> parameter. Next the relations are ordered for
+     early variable quantification. This ordering is controlled by the
+     parameters <b>image_W1, image_W2, image_W3,</b> and <b>image_W4</b>.
+
+     <dt><b>mlp</b>
+     <dd> This technique is based on minimizing the variable lifetime
+     in the conjunctions of the partitioned transition relation. The
+     method is called MLP (Minimal Lifetime Permutation). For details,
+     refer to the paper "Border-Block Triangular Form and Conjunction Schedule
+     in Image Computation" by In-Ho Moon, Gary Hachtel, and Fabio Somenzi,
+     FMCAD'00. Also for more detailed options, see the help of
+     print_mlp_options command.
+   </dl>
+
+
+   <dt><b>image_farside_method</b>
+   <dd> This parameter is used in conjunction with the selection of
+   <b>iwls95</b>, <b>mlp</b>, or <b>linear</b> as the
+   <b>image_method</b>. When the value is 1, the compositional far
+   side image computation approach is enabled; when the value is 0,
+   this feature is disabled (default).
+
+   <dt><b>image_cluster_size</b>
+   <dd> This parameter is used in conjunction with the selection of
+   <b>iwls95</b> as the <b>image_method</b>. The value of this parameter is
+   used as threshold value for creating clusters. The default value of this
+   parameter is 5000 which has been empirically proved to be an optimal value.
+
+   <dt><b>image_W1, image_W2, image_W3, image_W4</b>
+   <dd> These parameters are used in conjunction with the selection of
+   <b>iwls95</b> as the <b>image_method</b>. They control the weights
+   associated with various factors in ordering the clusters. The default values
+   are 6, 1, 1, and 2 respectively. For a detailed description of these
+   parameters, please refer to the paper in IWLS'95 proceedings.
+
+   <dt><b>image_verbosity</b>
+   <dd> Sets the verbosity mode (0 minimum to 4 maximum), for the image method
+   <b>iwls95</b>.<p>
+
+  <dt>image_minimize_method  &lt;method&gt;
+  <dd> Sets a minimization method to minimize the transition relation or an
+  image/preimage computaion with a set of dont-care states.  <p>
+  Methods:
+  <code> 0 </code>: restrict (default). <p>
+  <code> 1 </code>: constrain <p>
+  <code> 2 </code>: compact (currently supported by only CUDD) <p>
+  <code> 3 </code>: squeeze (currently supported by only CUDD) <p>
+
+  <dt>scc_method &lt;method&gt;
+  <dd> Sets the symbolic method to enumerate strongly connected components
+  (SCCs). Symbolic SCC enumeration is the core computation in LTL and
+  fair-CTL model checking.
+  <p> Methods: <code> lockstep </code>: the O(nlogn) time LockStep
+  algorithm (default).
+  <p> Methods: <code> linearstep </code>: the linear time symbolic
+  algorithm (default).
+
+  </dl> ]
+
+  SideEffects        []
+
+  SeeAlso            [unset]
+
+******************************************************************************/
+static int
+CommandSetVariable(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  char *flag_value, *key, *value;
+  avl_generator *gen;
+  int c;
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "h")) != EOF) {
+    switch(c) {
+      case 'h':
+	goto usage;
+      default:
+	goto usage;
+    }
+  }
+  if (argc == 0 || argc > 3) {
+    goto usage ;
+  }
+  else if (argc == 1) {
+    avl_foreach_item(cmdFlagTable, gen, AVL_FORWARD, &key, &value) {
+      (void) fprintf(vis_stdout, "%s\t%s\n", key, value);
+    }
+    return 0;
+  }
+  else {
+    key = argv[1];
+    if (avl_delete(cmdFlagTable, &key, &value)) {
+      FREE(key);
+      FREE(value);
+    }
+
+    flag_value = argc == 2 ? util_strsav("") : util_strsav(argv[2]);
+
+    (void) avl_insert(cmdFlagTable, util_strsav(argv[1]), flag_value);
+
+    if (strcmp(argv[1], "vis_stdout") == 0) {
+      if (vis_stdout != stdout) {
+	(void) fclose(vis_stdout);
+      }
+      if (strcmp(flag_value, "") == 0) {
+	flag_value = "-";
+      }
+      vis_stdout = Cmd_FileOpen(flag_value, "w", NIL(char *), 0);
+      if (vis_stdout == NULL) {
+	vis_stdout = stdout;
+      }
+#if HAVE_SETVBUF
+      setvbuf(vis_stdout, (char *)NULL, _IOLBF, 0);
+#endif
+    }
+    if (strcmp(argv[1], "vis_stderr") == 0) {
+      if (vis_stderr != stderr) {
+	(void) fclose(vis_stderr);
+      }
+      if (strcmp(flag_value, "") == 0) {
+	flag_value = "-";
+      }
+      vis_stderr = Cmd_FileOpen(flag_value, "w", NIL(char *), 0);
+      if (vis_stderr == NULL) {
+	vis_stderr = stderr;
+      }
+#if HAVE_SETVBUF
+      setvbuf(vis_stderr, (char *)NULL, _IOLBF, 0);
+#endif
+    }
+    if (strcmp(argv[1], "history") == 0) {
+      if (vis_historyFile != NIL(FILE)) {
+	(void) fclose(vis_historyFile);
+      }
+      if (strcmp(flag_value, "") == 0) {
+	vis_historyFile = NIL(FILE);
+      }
+      else {
+	vis_historyFile = Cmd_FileOpen(flag_value, "w", NIL(char *), 0);
+	if (vis_historyFile == NULL) {
+	  vis_historyFile = NIL(FILE);
+	}
+      }
+    }
+    return 0;
+  }
+
+  usage:
+      (void) printf("usage: set [-h] [name] [value]\n");
+      (void) fprintf(vis_stderr, "   -h \t\tprint the command usage\n");
+      return 1;
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis          [Implements the unset command.]
+
+  CommandName       [unset]
+
+  CommandSynopsis   [unset an environment variable]
+
+  CommandArguments  [\[-h\] &lt;variables&gt;]
+
+  CommandDescription [ A variable environment is maintained by the command
+  interpreter.
+  The "set" command sets a variable to a particular value, and the
+  "unset" command removes the definition of a variable. <p>
+  Command options:<p>
+  </dl>
+  <dl><dt> -h
+  <dd> Print the command usage.
+  </dl>
+  <dl><dt> &lt;variables&gt;
+  <dd> Variables to be unset
+  </dl>
+  ]
+
+  SideEffects        []
+
+  SeeAlso            [set]
+
+******************************************************************************/
+static int
+CommandUnsetVariable(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int i;
+  char *key, *value;
+  int c;
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "h")) != EOF) {
+    switch(c) {
+      case 'h':
+	goto usage;
+      default:
+	goto usage;
+    }
+  }
+
+  if (argc < 2) {
+    goto usage;
+  }
+
+  for(i = 1; i < argc; i++) {
+    key = argv[i];
+    if (avl_delete(cmdFlagTable, &key, &value)) {
+      FREE(key);
+      FREE(value);
+    }
+  }
+  return 0;
+
+
+  usage:
+    (void) fprintf(vis_stderr, "usage: unset [-h] variables \n");
+    (void) fprintf(vis_stderr, "   -h \t\tprint the command usage\n");
+    return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [Implements the help command.]
+
+  CommandName        [help]
+
+  CommandSynopsis    [provide on-line information on commands]
+
+  CommandArguments   [\[-a\] \[-h\] \[&lt;command&gt;\]]
+
+  CommandDescription [Given no arguments, "help" prints a list of all commands
+  known to the command interpreter.
+  If a command name is given, detailed information for that command will be
+  provided.<p>
+
+  Command options:<p>
+  <dl><dt> -a
+  <dd> Provides a list of all internal commands, which by convention begin with an underscore.
+  </dl>
+  <dl><dt> -h
+  <dd> Print the command usage.
+  </dl>]
+
+  SideEffects        []
+
+******************************************************************************/
+static int
+CommandHelp(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int c, i, all;
+  char *key;
+  avl_generator *gen;
+  char buffer[1024];
+  char *command;
+  char *lib_name;
+#if HAVE_GETENV
+  char *pager;
+#endif
+
+
+  util_getopt_reset();
+  all = 0;
+  while ((c = util_getopt(argc, argv, "ah")) != EOF) {
+    switch(c) {
+      case 'a':
+	all = 1;
+	break;
+      case 'h':
+	goto usage;
+      default:
+	goto usage;
+    }
+  }
+
+  if (argc - util_optind == 0) {
+    fprintf(vis_stderr,"List of commands:\n");
+    i = 0;
+    avl_foreach_item(cmdCommandTable, gen, AVL_FORWARD, &key, NIL(char *)) {
+      if ((key[0] == '_') == all) {
+	(void) fprintf(vis_stdout, "%-26s", key);
+	if ((++i%3) == 0) {
+	  (void) fprintf(vis_stdout, "\n");
+	}
+      }
+    }
+    if ((i%3) != 0) {
+      (void) fprintf(vis_stdout, "\n");
+    }
+  }
+  else if (argc - util_optind == 1) {
+    command = command_alias_help(argv[util_optind]);
+    lib_name = Vm_VisObtainLibrary();
+#if HAVE_GETENV
+    pager = getenv("PAGER");
+    if (pager != NULL) {
+      (void) sprintf(buffer, "%s %s/help/%sCmd.txt", pager, lib_name, command);
+    } else {
+      (void) sprintf(buffer, "more %s/help/%sCmd.txt", lib_name, command);
+    }
+#else
+    (void) sprintf(buffer, "more %s/help/%sCmd.txt", lib_name, command);
+#endif
+    (void) system(buffer);
+    FREE(lib_name);
+  }
+  else {
+    goto usage;
+  }
+
+  return 0;
+
+usage:
+  (void) fprintf(vis_stderr, "usage: help [-a] [-h] [command]\n");
+  (void) fprintf(vis_stderr, "   -a \t\tprint help for all commands\n");
+  (void) fprintf(vis_stderr, "   -h \t\tprint the command usage\n");
+
+  return 1;
+}
+
+#if 0
+Change "/*!*Function" to "/**Function" when reactivate command
+/*!*Function********************************************************************
+
+  Synopsis          [Implements the undo command.]
+
+  CommandName       [undo]
+
+  CommandSynopsis   [undo the result of the last command which changed the network]
+
+  CommandDescription [ A simple 1-level undo is supported.
+  It reverts the network to its state before the last command which
+  changed the network.  Note that interrupting a command (with ^C)
+  which changes the network uses up the one level of undo.<p> ]
+
+  SideEffects        []
+
+******************************************************************************/
+static int
+CommandUndo(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  if (argc != 1) {
+    (void) fprintf(vis_stderr, "usage: undo\n");
+    return 1;
+  }
+
+  (void) fprintf(vis_stderr, "** cmd error: undo: not yet implemented\n");
+  return 1;
+
+#if 0
+
+  /*
+   * FIX (Tom): can't enable "undo" until network_dup and hmgr_dup exist.
+   */
+  if (cmdBackupHmgr == NIL(Hrc_Manager_t)) {
+    (void) fprintf(vis_stderr, "undo: no hmgr currently saved\n");
+    return 1;
+  }
+  else {
+
+    /* Swap the current and backup. */
+    Hrc_Manager_t *temp = *hmgr;
+    *hmgr = cmdBackupHmgr;
+    cmdBackupHmgr = temp;
+    return 0;
+  }
+#endif
+}
+#endif
+
+
+
+/**Function********************************************************************
+
+  Synopsis          [Implements the source command.]
+
+  CommandName       [source]
+
+  CommandSynopsis   [execute commands from a file]
+
+  CommandArguments  [\[-h\] \[-p\] \[-s\] \[-x\] &lt;file&gt; \[&lt;args&gt;\]]
+
+  CommandDescription [Reads and executes commands from a file.<p>
+  Command options:<p>
+  <dl><dt> -h
+  <dd> Print the command usage.
+  </dl>
+  <dl><dt> -p
+  <dd> Print a prompt before reading each command.
+  </dl>
+  <dl><dt> -s
+  <dd> Silently
+  ignore an attempt to execute commands from a nonexistent file.
+  </dl>
+  <dl><dt> -x
+  <dd> Echo each command before it is executed.
+  </dl>
+  <dl><dt> &lt;file&gt;
+  <dd> File name
+  </dl>
+
+  Arguments on the command line after the filename are remembered but not
+  evaluated.  Commands in the script file can then refer to these arguments
+  using the history substitution mechanism.<p>
+
+  EXAMPLE:<p>
+
+  Contents of test.scr:<p>
+
+  <pre>
+  read_blif_mv %:2
+  init_verify
+  simulate -n 10
+  </pre>
+
+  Typing "source test.scr lion.mv" on the command line will execute the
+  sequence<p>
+
+  <pre>
+  read_blif_mv lion.mv
+  init_verify
+  simulate -n 10
+  </pre>
+
+  (In this case <code>%:0</code> gets "source", <code>%:1</code> gets
+  "test.scr", and <code>%:2</code> gets "lion.mv".)
+  If you type "alias st source test.scr" and then type "st lion.blif bozo",
+  you will execute<p>
+
+  <pre>
+  read_blif_mv bozo
+  init_verify
+  simulate -n 10
+  </pre>
+
+  because "bozo" was the second argument on the last command line typed.  In
+  other words, command substitution in a script file depends on how the script
+  file was invoked. Switches passed to a command are also counted as
+  positional parameters. Therefore, if you type "st -x lion.mv bozo",
+  you will execute
+
+  <pre>
+  read_blif_mv lion.mv
+  init_verify
+  simulate -n 10
+  </pre>
+
+  To pass the "-x" switch (or any other switch) to "source" when the
+  script uses positional parameters, you can define an alias. For
+  instance, "alias srcx source -x".<p>
+
+
+  ]
+
+  SideEffects        [required]
+
+  SeeAlso            [history]
+
+******************************************************************************/
+static int
+CommandSource(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int c, echo, prompt, silent, interactive, quit_count, lp_count;
+  int status = 0; /* initialize so that lint doesn't complain */
+  int lp_file_index, did_subst;
+  char *prompt_string, *real_filename, line[MAX_STR], *command;
+  FILE *fp;
+
+  interactive = silent = prompt = echo = 0;
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "hipsx")) != EOF) {
+    switch(c) {
+	case 'h':
+	  goto usage ;
+	case 'i':               /* a hack to distinguish EOF from stdin */
+	  interactive = 1;
+	  break;
+	case 'p':
+	  prompt = 1;
+	  break;
+	case 's':
+	  silent = 1;
+	  break;
+	case 'x':
+	  echo = 1;
+	  break;
+      default:
+	  goto usage;
+    }
+  }
+
+  /* added to avoid core-dumping when no script file is specified */
+  if (argc == util_optind){
+    goto usage;
+  }
+
+  lp_file_index = util_optind;
+  lp_count = 0;
+
+  /*
+   * FIX (Tom, 5/7/95):  I'm not sure what the purpose of this outer do loop
+   * is. In particular, lp_file_index is never modified in the loop, so it
+   * looks it would just read the same file over again.  Also, SIS had
+   * lp_count initialized to -1, and hence, any file sourced by SIS (if -l or
+   * -t options on "source" were used in SIS) would actually be executed
+   * twice.
+   */
+  do {
+    lp_count ++; /* increment the loop counter */
+
+    fp = Cmd_FileOpen(argv[lp_file_index], "r", &real_filename, silent);
+    if (fp == NULL) {
+      FREE(real_filename);
+      return ! silent;	/* error return if not silent */
+    }
+
+    quit_count = 0;
+    do {
+      if (prompt) {
+	prompt_string = Cmd_FlagReadByName("prompt");
+	if (prompt_string == NIL(char)) {
+	  prompt_string = "vis> ";
+	}
+
+      }
+      else {
+	prompt_string = NIL(char);
+      }
+
+      /* clear errors -- e.g., EOF reached from stdin */
+      clearerr(fp);
+
+      /* read another command line */
+      if (CmdFgetsFilec(line, MAX_STR, fp, prompt_string) == NULL) {
+	if (interactive) {
+	  if (quit_count++ < 5) {
+	    (void) fprintf(vis_stderr, "\nUse \"quit\" to leave VIS.\n");
+	    continue;
+	  }
+	  status = -1;		/* fake a 'quit' */
+	}
+	else {
+	  status = 0;		/* successful end of 'source' ; loop? */
+	}
+	break;
+      }
+      quit_count = 0;
+
+      if (echo) {
+	(void) fprintf(vis_stdout, "%s", line);
+      }
+      command = CmdHistorySubstitution(line, &did_subst);
+      if (command == NIL(char)) {
+	status = 1;
+	break;
+      }
+      if (did_subst) {
+	if (interactive) {
+	  (void) fprintf(stdout, "%s\n", command);
+	}
+      }
+      if (command != line) {
+	(void) strcpy(line, command);
+      }
+      if (interactive && *line != '\0') {
+	array_insert_last(char *, vm_commandHistoryArray, util_strsav(line));
+	if (vis_historyFile != NIL(FILE)) {
+	  (void) fprintf(vis_historyFile, "%s\n", line);
+	  (void) fflush(vis_historyFile);
+	}
+      }
+
+      status = Cmd_CommandExecute(hmgr, line);
+    } while (status == 0);
+
+    if (fp != stdin) {
+      if (status > 0) {
+	(void) fprintf(vis_stderr, "** cmd error: aborting 'source %s'\n", real_filename);
+      }
+      (void) fclose(fp);
+    }
+    FREE(real_filename);
+
+  } while ((status == 0) && (lp_count <= 0));
+
+  return status;
+
+usage:
+  (void) fprintf(vis_stderr, "source [-h] [-p] [-s] [-x] file_name\n");
+  (void) fprintf(vis_stderr, "\t-h print the command usage\n");
+  (void) fprintf(vis_stderr, "\t-p supply prompt before reading each line\n");
+  (void) fprintf(vis_stderr, "\t-s silently ignore nonexistent file\n");
+  (void) fprintf(vis_stderr, "\t-x echo each line as it is executed\n");
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+print_alias(
+  char * value)
+{
+  int i;
+  CmdAliasDescr_t *alias;
+
+  alias = (CmdAliasDescr_t *) value;
+  (void) fprintf(vis_stdout, "%s\t", alias->name);
+  for(i = 0; i < alias->argc; i++) {
+    (void) fprintf(vis_stdout, " %s", alias->argv[i]);
+  }
+  (void) fprintf(vis_stdout, "\n");
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static char *
+command_alias_help(
+  char * command)
+{
+  char *value;
+  CmdAliasDescr_t *alias;
+
+  if (!avl_lookup(cmdAliasTable, command, &value)) {
+    return command;
+  }
+  alias = (CmdAliasDescr_t *) value;
+  return alias->argv[0];
+}
+
+/**Function********************************************************************
+
+  Synopsis           [Function to flush vis_stdout and vis_stderr.]
+
+  Description [This function is the signal handler for the SIGUSR1
+  signal. Whenever that signal is received, this function is executed and the
+  output channels of VIS are flushed.]
+
+  SideEffects        []
+
+  SeeAlso            [Cmd_Init]
+
+******************************************************************************/
+static void
+FlushBuffers(
+  int sigtype)
+{
+  fflush(vis_stdout);
+  fflush(vis_stderr);
+
+  /* Reprogram again the handler */
+#ifdef SIGUSR1
+  (void) signal(SIGUSR1, FlushBuffers);
+#endif
+} /* End of FlushBuffers */
Index: vis_dev/vis-2.3/src/ctlp/ctlp.h
===================================================================
--- vis_dev/vis-2.3/src/ctlp/ctlp.h	(revision 14)
+++ vis_dev/vis-2.3/src/ctlp/ctlp.h	(revision 14)
@@ -0,0 +1,240 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [ctlp.h]
+
+  PackageName [ctlp]
+
+  Synopsis    [Routines for parsing, writing and accessing CTL formulas.]
+
+  Description [This package implements a parser for CTL (Computation Tree
+  Logic) formulas.  CTL is a language used to describe properties of systems.
+  For the syntax of CTL formulas, refer to <A HREF="../ctl_ltl/ctl_ltl/ctl_ltl.html">
+  the VIS CTL and LTL syntax manual</A>.]
+
+  SeeAlso     [mc]
+
+  Author      [Gary York, Ramin Hojati, Tom Shiple, Adnan Aziz, Yuji Kukimoto,
+               Jae-Young Jang, In-Ho Moon]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: ctlp.h,v 1.29 2005/05/08 14:51:46 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _CTLP
+#define _CTLP
+
+#include "vm.h"
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Enum************************************************************************
+
+  Synopsis    [Types of operators allowed in CTL formulas.]
+
+  Description [The types of nodes in a CTL formula parse tree. ID, TRUE, and
+  FALSE are leaves, and all others are internal nodes.]
+
+  SeeAlso     [Ctlp_FormulaReadType]
+
+******************************************************************************/
+typedef enum {
+  Ctlp_EX_c,     /* there exists a next state */
+  Ctlp_EG_c,     /* there exists a path globally */
+  Ctlp_EF_c,     /* there exists a path finally */
+  Ctlp_EU_c,     /* there exists a path, until (not symmetric in args) */ 
+  Ctlp_AX_c,     /* for all next states */
+  Ctlp_AG_c,     /* for all paths globally */
+  Ctlp_AF_c,     /* for all paths finally */
+  Ctlp_AU_c,     /* for all paths, until (not symmetric in args) */
+  Ctlp_OR_c,     /* Boolean disjunction */
+  Ctlp_AND_c,    /* Boolean conjunction */
+  Ctlp_NOT_c,    /* Boolean negation*/
+  Ctlp_THEN_c,   /* Boolean implies (not symmetric) */
+  Ctlp_XOR_c,    /* Boolean not equal */
+  Ctlp_EQ_c,     /* Boolean equal */
+  Ctlp_ID_c,     /* an atomic proposition */
+  Ctlp_TRUE_c,   /* tautology (used only for translation to exist. form) */
+  Ctlp_FALSE_c,  /* empty (used only for translation to exist. form) */
+  Ctlp_FwdU_c,   /* forward until */
+  Ctlp_FwdG_c,   /* forward global */
+  Ctlp_EY_c,	 /* there exists a previous state */
+  Ctlp_EH_c,	 /* there exists a path globally in the past */
+  Ctlp_Init_c,	 /* initial states */
+  Ctlp_Cmp_c	 /* compare two leaves in forward CTL */
+} Ctlp_FormulaType;
+
+  
+/**Enum************************************************************************
+
+  Synopsis    [Classification of CTL formulae according to quantification.]
+
+  Description [A CTL formula is quantifier-free if it contains no
+  quantifiers.  A CTL formula is classifed in ECTL if it contains quantifiers
+  and every existential quantifier is under an even number of negations, while
+  every universal quantifier is under an odd number of negations.  For an ACTL
+  formula, the negation parity is exchanged.  All remaining formulae are
+  mixed.]
+
+  SeeAlso     []
+
+******************************************************************************/
+typedef enum {
+  Ctlp_ECTL_c,
+  Ctlp_ACTL_c,
+  Ctlp_Mixed_c,
+  Ctlp_QuantifierFree_c
+} Ctlp_FormulaClass;
+
+
+/**Enum************************************************************************
+
+  Synopsis    [Classification of ACTL formulae according to Beer et al..]
+
+  Description [w-ACTL is the subset of ACTL to which the vacuity detection
+  algorithm of Beer et al. (CAV 97) is applicable.  An ACTL formula is in
+  w-ACTL if at least one child of every binary operator is propositional.
+  A simple formula is a propositional, while a state formula is a
+  non-propositional w-ACTL.]
+
+  SeeAlso     []
+
+******************************************************************************/
+typedef enum {
+    Ctlp_WACTLsimple_c,
+    Ctlp_WACTLstate_c,
+    Ctlp_NONWACTL_c
+} Ctlp_FormulaACTLSubClass;
+
+
+/**Enum************************************************************************
+
+  Synopsis    [Types of approximations that are possible]
+
+  Description [We can have overapproximations, underapproximations, exact
+  approximations, or incomparable sets.  Question: is ctlp the right place for
+  this?  It is used in ctlp, mc, rch. (RB)]
+
+  SeeAlso     []
+
+******************************************************************************/
+typedef enum {
+  Ctlp_Incomparable_c,
+  Ctlp_Underapprox_c,
+  Ctlp_Overapprox_c,
+  Ctlp_Exact_c
+} Ctlp_Approx_t;
+
+
+/**Enum************************************************************************
+
+  Synopsis    [Negation parity of a node.]
+
+  Description [It can be even, odd, or both.  The fourth value is for
+  uninitialized.  For a formula with no sharing, XOR and EQ nodes cause
+  their descendants to have both parities.]
+
+  SeeAlso     []
+
+******************************************************************************/
+typedef enum {
+  Ctlp_NoParity_c,
+  Ctlp_Even_c,
+  Ctlp_Odd_c,
+  Ctlp_EvenOdd_c
+} Ctlp_Parity_t;
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef struct CtlpFormulaStruct Ctlp_Formula_t;
+typedef void   (*Ctlp_DbgInfoFreeFn) (Ctlp_Formula_t *);
+typedef array_t Ctlp_FormulaArray_t; /* array of Ctlp_Formula_t * */
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void Ctlp_Init(void);
+EXTERN void Ctlp_End(void);
+EXTERN array_t * Ctlp_FileParseFormulaArray(FILE * fp);
+EXTERN char * Ctlp_FormulaConvertToString(Ctlp_Formula_t * formula);
+EXTERN void Ctlp_FormulaPrint(FILE * fp, Ctlp_Formula_t * formula);
+EXTERN Ctlp_FormulaType Ctlp_FormulaReadType(Ctlp_Formula_t * formula);
+EXTERN int Ctlp_FormulaReadCompareValue(Ctlp_Formula_t * formula);
+EXTERN char * Ctlp_FormulaReadVariableName(Ctlp_Formula_t * formula);
+EXTERN char * Ctlp_FormulaReadValueName(Ctlp_Formula_t * formula);
+EXTERN Ctlp_Formula_t * Ctlp_FormulaReadLeftChild(Ctlp_Formula_t * formula);
+EXTERN Ctlp_Formula_t * Ctlp_FormulaReadRightChild(Ctlp_Formula_t * formula);
+EXTERN mdd_t * Ctlp_FormulaObtainStates(Ctlp_Formula_t * formula);
+EXTERN mdd_t * Ctlp_FormulaObtainLatestApprox(Ctlp_Formula_t *formula);
+EXTERN mdd_t * Ctlp_FormulaObtainApproxStates(Ctlp_Formula_t *formula, Ctlp_Approx_t approx);
+EXTERN void Ctlp_FormulaSetStates(Ctlp_Formula_t * formula, mdd_t * states);
+EXTERN void Ctlp_FormulaSetApproxStates(Ctlp_Formula_t * formula, mdd_t * states, Ctlp_Approx_t approx);
+EXTERN void Ctlp_FormulaSetDbgInfo(Ctlp_Formula_t * formula, void *data, Ctlp_DbgInfoFreeFn freeFn);
+EXTERN void * Ctlp_FormulaReadDebugData(Ctlp_Formula_t * formula);
+EXTERN boolean Ctlp_FormulaTestIsConverted(Ctlp_Formula_t * formula);
+EXTERN boolean Ctlp_FormulaTestIsQuantifierFree(Ctlp_Formula_t *formula);
+EXTERN Ctlp_Formula_t * Ctlp_FormulaReadOriginalFormula(Ctlp_Formula_t * formula);
+EXTERN void Ctlp_FormulaFree(Ctlp_Formula_t *formula);
+EXTERN void Ctlp_FlushStates(Ctlp_Formula_t * formula);
+EXTERN Ctlp_Formula_t * Ctlp_FormulaDup(Ctlp_Formula_t * formula);
+EXTERN Ctlp_Formula_t * Ctlp_FormulaConverttoComplement(Ctlp_Formula_t * formula);
+EXTERN Ctlp_Formula_t * Ctlp_FormulaConvertAFtoAU(Ctlp_Formula_t * formula);
+EXTERN Ctlp_Formula_t * Ctlp_FormulaConvertEFtoOR(Ctlp_Formula_t * formula);
+EXTERN Ctlp_Formula_t * Ctlp_FormulaConvertEUtoOR(Ctlp_Formula_t * formula);
+EXTERN Ctlp_Formula_t * Ctlp_FormulaConvertXORtoOR(Ctlp_Formula_t * formula);
+EXTERN Ctlp_Formula_t * Ctlp_FormulaConvertEQtoOR(Ctlp_Formula_t * formula);
+EXTERN Ctlp_Formula_t * Ctlp_FormulaPushNegation(Ctlp_Formula_t * formula);
+EXTERN void Ctlp_FormulaArrayFree(array_t * formulaArray);
+EXTERN Ctlp_Formula_t * Ctlp_FormulaConvertToExistentialForm(Ctlp_Formula_t * formula);
+EXTERN Ctlp_Formula_t * Ctlp_FormulaConvertToSimpleExistentialForm(Ctlp_Formula_t * formula);
+EXTERN array_t * Ctlp_FormulaArrayConvertToExistentialFormTree(array_t * formulaArray);
+EXTERN array_t * Ctlp_FormulaArrayConvertToSimpleExistentialFormTree(array_t * formulaArray);
+EXTERN array_t * Ctlp_FormulaArrayConvertToDAG(array_t *formulaArray);
+EXTERN array_t * Ctlp_FormulaDAGConvertToExistentialFormDAG(array_t *formulaDAG);
+EXTERN Ctlp_Formula_t * Ctlp_FormulaCreate(Ctlp_FormulaType type, void * left, void * right);
+EXTERN Ctlp_Formula_t * Ctlp_FormulaCreateOr(char *name, char *valueStr);
+EXTERN Ctlp_Formula_t * Ctlp_FormulaCreateVectorAnd(char *nameVector, char *value);
+EXTERN Ctlp_Formula_t * Ctlp_FormulaCreateVectorOr(char *nameVector, char *valueStr);
+EXTERN Ctlp_Formula_t * Ctlp_FormulaCreateEquiv(char *left, char *right);
+EXTERN Ctlp_Formula_t * Ctlp_FormulaCreateVectorEquiv(char *left, char *right);
+EXTERN Ctlp_Formula_t * Ctlp_FormulaCreateAXMult(char *string, Ctlp_Formula_t *formula);
+EXTERN Ctlp_Formula_t * Ctlp_FormulaCreateEXMult(char *string, Ctlp_Formula_t *formula);
+EXTERN array_t * Ctlp_FormulaArrayConvertToForward(array_t *formulaArray, int singleInitial, boolean doNotShareFlag);
+EXTERN char * Ctlp_FormulaGetTypeString(Ctlp_Formula_t *formula);
+EXTERN Ctlp_FormulaClass Ctlp_CheckClassOfExistentialFormula(Ctlp_Formula_t *formula);
+EXTERN Ctlp_FormulaClass Ctlp_CheckClassOfExistentialFormulaArray(array_t *formulaArray);
+EXTERN boolean Ctlp_FormulaIdentical(Ctlp_Formula_t *formula1, Ctlp_Formula_t *formula2);
+EXTERN void Ctlp_FormulaMakeMonotonic(Ctlp_Formula_t *formula);
+EXTERN void Ctlp_FormulaArrayMakeMonotonic(array_t *formulaArray);
+EXTERN void Ctlp_FormulaNegations(Ctlp_Formula_t *formula, Ctlp_Parity_t parity);
+EXTERN Ctlp_FormulaACTLSubClass Ctlp_CheckIfWACTL(Ctlp_Formula_t *formula);
+EXTERN Ctlp_Formula_t * Ctlp_FormulaCreateWitnessFormula(Ctlp_Formula_t *formula);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _CTLP */
Index: vis_dev/vis-2.3/src/ctlp/ctlp.l
===================================================================
--- vis_dev/vis-2.3/src/ctlp/ctlp.l	(revision 14)
+++ vis_dev/vis-2.3/src/ctlp/ctlp.l	(revision 14)
@@ -0,0 +1,165 @@
+%{
+/**CFile***********************************************************************
+
+  FileName    [ctlp.l]
+
+  PackageName [ctlp]
+
+  Synopsis    [Lexical analyzer for CTL formula parser. See ctlp.h for syntax.]
+
+  Author      [Gary York, Ramin Hojati, Tom Shiple, Yuji Kukimoto,
+               Jae-Young Jang]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: ctlp.l,v 1.8 2010/04/09 23:30:23 fabio Exp $]
+
+******************************************************************************/
+
+#include "ctlpRead.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes global variables for parsing file.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+CtlpFileSetup(
+  FILE * fp)
+{
+  CtlpYyin             = fp;
+  CtlpYylineno         = 1;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Prints error message and sets global error flag.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+CtlpYyerror(
+  char * errmsg)
+{
+  (void) fprintf(vis_stderr, "%s in line %d with token \"%s\"\n", errmsg, CtlpYylineno, yytext); 
+  CtlpGlobalError = 1;
+}
+
+%}
+
+/*---------------------------------------------------------------------------*/
+/*      Lexical analyzer rules                                               */
+/*---------------------------------------------------------------------------*/
+
+%option noyywrap
+%option yylineno
+
+/* substitution strings */
+/* alnum is the same set in alnumsymbol in io.l except [ and ] being
+removed here for the until operator */
+/* - , =, and ; are intentionally removed
+   - is used for -> and <->
+   = is used for foo = bar 
+   ; is used for delimitters */
+/* ( and ) are intentionally removed since they are used as parentheses */
+/* +, *, and ^ have to be used surrounded by spaces
+since they are symbols. ! can be attached immediately w/o spaces though
+since it is not a symbol */
+alnum		[A-Za-z0-9\^\?\|\/\+\*\$\<\>~@\_#\$%\:\"\'\.]
+/*alnum		[A-Za-z0-9\^\?\|\/\[\]\+\*\$\<\>~@\_#\$%\:\"\'\.]*/
+%%
+
+[ \t\n\r]	;
+
+"#".*   ;   
+
+A	{ return(TOK_FORALL); }
+AX	{ return(TOK_FORALL_NEXT); }
+AF	{ return(TOK_FORALL_EVENTUALLY); }
+AG	{ return(TOK_FORALL_GLOBALLY); }
+
+E	{ return(TOK_EXISTS); }
+EX	{ return(TOK_EXISTS_NEXT); }
+EF	{ return(TOK_EXISTS_EVENTUALLY); }
+EG	{ return(TOK_EXISTS_GLOBALLY); }
+
+AX:[0-9]+  { return(TOK_FORALL_NEXT_MULT); }
+EX:[0-9]+  { return(TOK_EXISTS_NEXT_MULT); }
+
+U	{ return(TOK_UNTIL); }
+
+TRUE    { return(TOK_TRUE); }
+
+FALSE   { return(TOK_FALSE); }
+
+\\DEFINE |
+\\Define |
+\\define  { return(TOK_DEFINE); }
+
+\+	{ return(TOK_OR); }
+\|\|	{ return(TOK_OR); }
+\*	{ return(TOK_AND); }
+\&\&	{ return(TOK_AND); }
+!	{ return(TOK_NOT); }
+"^"	{ return(TOK_XOR); }
+"->"	{ return(TOK_THEN); }
+"<->"	{ return(TOK_EQ); }
+=       { return(TOK_ASSIGN); }
+==      { return(TOK_EQIV); }
+\,      { return(TOK_COMMA); }
+\\      { return(TOK_MACRO); }
+
+{alnum}+                                   { return(TOK_ID); }
+{alnum}+\[[ ]*[0-9]+[ ]*\]                 { return(TOK_ID2); }
+{alnum}+\[[ ]*[0-9]+[ ]*\:[ ]*[0-9]+[ ]*\] { return(TOK_ID_VECTOR); }
+
+.       { return CtlpYytext[0]; }
+%%
Index: vis_dev/vis-2.3/src/ctlp/ctlp.make
===================================================================
--- vis_dev/vis-2.3/src/ctlp/ctlp.make	(revision 14)
+++ vis_dev/vis-2.3/src/ctlp/ctlp.make	(revision 14)
@@ -0,0 +1,17 @@
+CSRC += ctlpCmd.c ctlpUtil.c
+HEADERS += ctlp.h ctlpInt.h
+LEXSRC += ctlp.l
+YACCSRC += ctlp.y
+GENERATEDCSRC += ctlpRead.c
+
+$(objectdir)/ctlpRead.c $(objectdir)/ctlpRead.h: ctlp.y ctlp.h ctlpInt.h ctlpLex.c
+	$(YACC) -pCtlpYy -t -d -o $(objectdir)/ctlpRead.c $<
+	-@chmod 0664 $(objectdir)/ctlpRead.c
+
+ctlpLex.c: ctlp.l
+	$(LEX) -PCtlpYy -o$(objectdir)/ctlpLex.c $< 
+	-@chmod 0664 $(objectdir)/ctlpLex.c
+
+$(objectdir)/ctlpRead.o: $(objectdir)/ctlpRead.c
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/ctlp/ctlp.y
===================================================================
--- vis_dev/vis-2.3/src/ctlp/ctlp.y	(revision 14)
+++ vis_dev/vis-2.3/src/ctlp/ctlp.y	(revision 14)
@@ -0,0 +1,323 @@
+%{
+/**CFile*****************************************************************
+
+  FileName    [ctlp.y]
+
+  PackageName [ctlp]
+
+  Synopsis    [Yacc for CTL formula parser.]
+
+  SeeAlso     [ctlp.h]
+
+  Author      [Gary York, Ramin Hojati, Tom Shiple, Yuji Kukimoto
+	       Jae-Young Jang, In-Ho Moon]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ctlpInt.h"
+
+/*
+ * The following is a workaround for a bug in bison, which generates code
+ * that uses alloca().  Their lengthy sequence of #ifdefs for defining
+ * alloca() does the wrong thing for HPUX (it should do what is defined below)
+ */
+#ifdef __hpux
+#  include <alloca.h>
+#endif
+
+static char rcsid[] UNUSED = "$Id: ctlp.y,v 1.20 2010/04/09 23:30:23 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#include "ctlpLex.c"
+
+%}
+
+/*---------------------------------------------------------------------------*/
+/*      Grammar declarations                                                 */
+/*---------------------------------------------------------------------------*/
+
+%union {
+  Ctlp_Formula_t *sf;	/* state formula */
+  char *str;
+}
+
+%type <sf> error stateformula formula
+%type <str> name name_vector name_union name_or macro ax_mult ex_mult
+
+/* %token YYERROR_VERBOSE */
+
+%token TOK_DEFINE
+%token TOK_MACRO
+%token TOK_ID
+%token TOK_ID2
+%token TOK_ID_VECTOR
+%token TOK_ID_UNION
+%token TOK_COMMA
+%token TOK_EQIV
+%token TOK_FORALL
+%token TOK_EXISTS
+%token TOK_UNTIL
+%token TOK_FORALL_NEXT
+%token TOK_FORALL_EVENTUALLY
+%token TOK_FORALL_GLOBALLY
+%token TOK_EXISTS_NEXT
+%token TOK_EXISTS_EVENTUALLY
+%token TOK_EXISTS_GLOBALLY
+%token TOK_FORALL_NEXT_MULT
+%token TOK_EXISTS_NEXT_MULT
+%token TOK_THEN
+%token TOK_EQ
+%token TOK_XOR
+%token TOK_AND
+%token TOK_OR
+%token TOK_NOT
+%token TOK_ASSIGN
+%token TOK_TRUE
+%token TOK_FALSE
+
+/* precedence is specified here from lowest to highest */
+%nonassoc TOK_UNTIL
+%left TOK_THEN
+%left TOK_EQ
+%left TOK_XOR
+%left TOK_OR
+%left TOK_AND
+%nonassoc TOK_FORALL_NEXT TOK_FORALL_EVENTUALLY TOK_FORALL_GLOBALLY TOK_EXISTS_NEXT TOK_EXISTS_EVENTUALLY TOK_EXISTS_GLOBALLY
+%nonassoc TOK_NOT
+
+%%
+
+/*---------------------------------------------------------------------------*/
+/*      Grammar rules                                                        */
+/*---------------------------------------------------------------------------*/
+formulas     : /* nothing */
+	     | formulas formula
+	     ;
+
+formula : stateformula ';'
+	       { CtlpFormulaAddToGlobalArray($1);
+		       $$ = $1;
+	   /*
+	    * The formula is echoed by the lexical analyzer to stdout.
+	    * Here we are just printing the line number after it.
+	    */
+	   CtlpGlobalFormula = NIL(Ctlp_Formula_t);
+	 }
+       | TOK_DEFINE name stateformula
+	 { if (!CtlpFormulaAddToTable($2, $3, CtlpMacroTable)){
+	     CtlpYyerror("** ctl error : MACRO ERROR");
+			 (void) fprintf(vis_stderr, "Macro \"%s\" is already in table.\n\n",$2);
+	     Ctlp_FormulaFree(CtlpGlobalFormula);
+	     $$ = NULL;
+	   }else{
+	     $$ = $3;
+	   }
+	   CtlpGlobalFormula = NIL(Ctlp_Formula_t);
+	 }
+	     | error ';'
+	       { $$ = NULL;
+	   /*
+	    * Error was detected reading the formula. Garbage collect
+	    * and print error message.
+	    */
+		       Ctlp_FormulaFree(CtlpGlobalFormula);
+		       (void) fprintf(vis_stderr, "** ctl error : Invalid CTL formula, line %d\n\n", CtlpYylineno);
+	   CtlpGlobalFormula = NIL(Ctlp_Formula_t);
+	 }
+	     ;
+
+stateformula : '(' stateformula ')'
+       { $$ = $2;
+	 CtlpGlobalFormula= $$;}
+     | TOK_EXISTS '(' stateformula TOK_UNTIL stateformula ')'
+       { $$ = Ctlp_FormulaCreate(Ctlp_EU_c, $3, $5);
+	 CtlpGlobalFormula= $$; }
+     | TOK_EXISTS_NEXT stateformula
+       { $$ = Ctlp_FormulaCreate(Ctlp_EX_c, $2, NIL(Ctlp_Formula_t));
+	 CtlpGlobalFormula= $$;}
+     | ex_mult '(' stateformula ')'
+       { $$ = Ctlp_FormulaCreateEXMult($1, $3);
+	 if ($$ == NIL(Ctlp_Formula_t)){
+	    CtlpYyerror("** ctl error : MULTIPLE EX ERROR");
+	    (void) fprintf(vis_stderr,"Error during parsing line %d.\n\n", CtlpYylineno);
+	    Ctlp_FormulaFree(CtlpGlobalFormula);
+	 }
+	 FREE($1);
+	 CtlpGlobalFormula= $$;
+       }
+     | TOK_EXISTS_EVENTUALLY stateformula
+       { $$ = Ctlp_FormulaCreate(Ctlp_EF_c, $2, NIL(Ctlp_Formula_t));
+	 CtlpGlobalFormula= $$; }
+     | TOK_EXISTS_GLOBALLY stateformula
+       { $$ = Ctlp_FormulaCreate(Ctlp_EG_c, $2, NIL(Ctlp_Formula_t));
+	 CtlpGlobalFormula= $$;}
+     | TOK_FORALL '(' stateformula TOK_UNTIL stateformula ')'
+       { $$ = Ctlp_FormulaCreate(Ctlp_AU_c, $3, $5);
+	 CtlpGlobalFormula= $$; }
+     | TOK_FORALL_NEXT stateformula
+       { $$ = Ctlp_FormulaCreate(Ctlp_AX_c, $2, NIL(Ctlp_Formula_t));
+	 CtlpGlobalFormula= $$; }
+     | ax_mult '(' stateformula ')'
+       { $$ = Ctlp_FormulaCreateAXMult($1, $3);
+	 if ($$ == NIL(Ctlp_Formula_t)){
+	    CtlpYyerror("** ctl error : MULTIPLE AX ERROR");
+	    (void) fprintf(vis_stderr,"Error during parsing line %d.\n\n", CtlpYylineno);
+	    Ctlp_FormulaFree(CtlpGlobalFormula);
+	 }
+	 FREE($1);
+	 CtlpGlobalFormula= $$;
+       }
+     | TOK_FORALL_EVENTUALLY stateformula
+       { $$ = Ctlp_FormulaCreate(Ctlp_AF_c, $2, NIL(Ctlp_Formula_t));
+	 CtlpGlobalFormula= $$; }
+     | TOK_FORALL_GLOBALLY stateformula
+       { $$ = Ctlp_FormulaCreate(Ctlp_AG_c, $2, NIL(Ctlp_Formula_t));
+	 CtlpGlobalFormula= $$; }
+     | stateformula TOK_AND stateformula
+       { $$ = Ctlp_FormulaCreate(Ctlp_AND_c, $1, $3);
+	 CtlpGlobalFormula= $$; }
+     | stateformula TOK_OR stateformula
+       { $$ = Ctlp_FormulaCreate(Ctlp_OR_c, $1, $3);
+	 CtlpGlobalFormula= $$; }
+     | TOK_NOT stateformula
+       { $$ = Ctlp_FormulaCreate(Ctlp_NOT_c, $2, NIL(Ctlp_Formula_t));
+	 CtlpGlobalFormula= $$; }
+     | stateformula TOK_THEN stateformula
+       { $$ = Ctlp_FormulaCreate(Ctlp_THEN_c, $1, $3);
+	 CtlpGlobalFormula= $$; }
+     | stateformula TOK_EQ stateformula
+       { $$ = Ctlp_FormulaCreate(Ctlp_EQ_c, $1, $3);
+	 CtlpGlobalFormula= $$; }
+     | stateformula TOK_XOR stateformula
+       { $$ = Ctlp_FormulaCreate(Ctlp_XOR_c, $1, $3);
+	 CtlpGlobalFormula= $$; }
+     | name TOK_ASSIGN name
+       { $$ = Ctlp_FormulaCreate(Ctlp_ID_c, $1, $3);
+	 CtlpGlobalFormula= $$; }
+     | name TOK_ASSIGN name_union
+       { $$ = Ctlp_FormulaCreateOr($1, $3);
+	 FREE($1);
+	 FREE($3);
+	 CtlpGlobalFormula= $$; }
+     | name_vector TOK_ASSIGN name
+       { $$ = Ctlp_FormulaCreateVectorAnd($1, $3);
+	 if ($$ == NIL(Ctlp_Formula_t)){
+	    CtlpYyerror("** ctl error : Matching ERROR");
+	    (void) fprintf(vis_stderr,"LHS token is not matched to RHS token, line %d.\n\n", CtlpYylineno);
+	    Ctlp_FormulaFree(CtlpGlobalFormula);
+	 }
+	 FREE($1);
+	 FREE($3);
+	 CtlpGlobalFormula= $$;
+       }
+     | name_vector TOK_ASSIGN name_union
+       { $$ = Ctlp_FormulaCreateVectorOr($1, $3);
+	 if ($$ == NIL(Ctlp_Formula_t)){
+	    CtlpYyerror("** ctl error : Matching ERROR");
+	    (void) fprintf(vis_stderr,"LHS token is not matched to RHS token, line %d\n\n", CtlpYylineno);
+	    Ctlp_FormulaFree(CtlpGlobalFormula);
+	 }
+	 FREE($1);
+	 FREE($3);
+	 CtlpGlobalFormula= $$; }
+     | name TOK_EQIV name
+       { $$ = Ctlp_FormulaCreateEquiv($1, $3);
+	 if ($$ == NIL(Ctlp_Formula_t)){
+	    CtlpYyerror("** ctl error : Matching ERROR");
+	    (void) fprintf(vis_stderr,"LHS token is not matched to RHS token, line %d.\n\n", CtlpYylineno);
+	    Ctlp_FormulaFree(CtlpGlobalFormula);
+	 }
+	 FREE($1);
+	 FREE($3);
+	 CtlpGlobalFormula= $$;
+       }
+     | name_vector TOK_EQIV name_vector
+       { $$ = Ctlp_FormulaCreateVectorEquiv($1, $3);
+	 FREE($1);
+	 FREE($3);
+	 CtlpGlobalFormula= $$; }
+     | name TOK_ASSIGN TOK_FORALL
+       { $$ = Ctlp_FormulaCreate(Ctlp_ID_c, $1, util_strsav("A"));
+	 CtlpGlobalFormula= $$; }
+     | name TOK_ASSIGN TOK_EXISTS
+       { $$ = Ctlp_FormulaCreate(Ctlp_ID_c, $1, util_strsav("E"));
+	 CtlpGlobalFormula= $$; }
+     | name TOK_ASSIGN TOK_UNTIL
+       { $$ = Ctlp_FormulaCreate(Ctlp_ID_c, $1, util_strsav("U"));
+	 CtlpGlobalFormula= $$; }
+     | TOK_FORALL TOK_ASSIGN name
+       { $$ = Ctlp_FormulaCreate(Ctlp_ID_c, util_strsav("A"), $3);
+	 CtlpGlobalFormula= $$; }
+     | TOK_EXISTS TOK_ASSIGN name
+       { $$ = Ctlp_FormulaCreate(Ctlp_ID_c, util_strsav("E"), $3);
+	 CtlpGlobalFormula= $$; }
+     | TOK_UNTIL TOK_ASSIGN name
+       { $$ = Ctlp_FormulaCreate(Ctlp_ID_c, util_strsav("U"), $3);
+	 CtlpGlobalFormula= $$; }
+     | TOK_TRUE
+       { $$ = Ctlp_FormulaCreate(Ctlp_TRUE_c, NIL(Ctlp_Formula_t), NIL(Ctlp_Formula_t));
+	 CtlpGlobalFormula= $$; }
+     | TOK_FALSE
+       { $$ = Ctlp_FormulaCreate(Ctlp_FALSE_c, NIL(Ctlp_Formula_t), NIL(Ctlp_Formula_t));
+	 CtlpGlobalFormula= $$; }
+     | macro
+       { $$ = CtlpFormulaFindInTable($1, CtlpMacroTable);
+	 if ($$ == NIL(Ctlp_Formula_t)){
+	    CtlpYyerror("** ctl error : Macro Error");
+	    (void) fprintf(vis_stderr,"Macro \"%s\" is not defined.\n\n",$1);
+	 }
+	 FREE($1);
+	 CtlpGlobalFormula= $$;
+       };
+
+name:  TOK_ID
+       { $$ = util_strsav(CtlpYytext); }
+     | TOK_ID2
+       { (void) CtlpChangeBracket(CtlpYytext);
+	 $$ = util_strsav(CtlpYytext); };
+
+name_vector: TOK_ID_VECTOR
+       { $$ = util_strsav(CtlpYytext); };
+
+name_union: '{' name_or '}'
+       { $$ = $2; };
+
+name_or: name
+       { $$ = $1; }
+      |  name_or TOK_COMMA name
+       { $$ = util_strcat3($1,",",$3);
+	 FREE($1);
+	 FREE($3);
+       }
+      ;
+
+macro: TOK_MACRO name
+       { $$ = $2; } ;
+
+ax_mult: TOK_FORALL_NEXT_MULT
+       { $$ = util_strsav(CtlpYytext); } ;
+ex_mult: TOK_EXISTS_NEXT_MULT
+       { $$ = util_strsav(CtlpYytext); } ;
+%%
Index: vis_dev/vis-2.3/src/ctlp/ctlpCmd.c
===================================================================
--- vis_dev/vis-2.3/src/ctlp/ctlpCmd.c	(revision 14)
+++ vis_dev/vis-2.3/src/ctlp/ctlpCmd.c	(revision 14)
@@ -0,0 +1,336 @@
+/**CFile***********************************************************************
+
+  FileName    [ctlpCmd.c]
+
+  PackageName [ctlp]
+
+  Synopsis    [Command to read in a file containing CTL formulas.]
+
+  Author      [Tom Shiple, In-Ho Moon]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ctlpInt.h"
+
+static char rcsid[] UNUSED = "$Id: ctlpCmd.c,v 1.14 2005/05/19 02:35:25 awedh Exp $";
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandCtlpTest(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int FormulaArrayCountSubformulae(array_t *formulaArray);
+static void FormulaVisitUnvisitedSubformulae(Ctlp_Formula_t *formula, int *ptr);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Initializes the CTL parser package.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlp_End]
+
+******************************************************************************/
+void
+Ctlp_Init(void)
+{
+  Cmd_CommandAdd("_ctlp_test",   CommandCtlpTest,   0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Ends the CTL parser package.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlp_Init]
+
+******************************************************************************/
+void
+Ctlp_End(void)
+{
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the field states in every subformula of formula to
+  NULL.] 
+
+  Description [The function sets the field states in every subformula
+  of formula to NULL.]
+  
+  SideEffects []
+
+******************************************************************************/
+void
+CtlpFormulaSetStatesToNULL(
+  Ctlp_Formula_t *formula)
+{
+  if(formula!=NIL(Ctlp_Formula_t)) {
+    formula->states = NIL(mdd_t);
+    if(formula->type != Ctlp_ID_c) {
+      CtlpFormulaSetStatesToNULL(formula->left);
+      CtlpFormulaSetStatesToNULL(formula->right);
+    }
+  }
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the _ctlp_test command.]
+
+  Description [Implements the _ctlp_test command.  This command is only meant to
+  test the CTL command parser.]
+  
+  CommandName [_ctlp_test]
+
+  CommandSynopsis [test the CTL parser]
+
+  CommandArguments [\[-h\] &lt;file_name&gt;]
+  
+  CommandDescription [Test the CTL parser.  If the entire file of CTL
+  formulas is successfully parsed, then each formula is printed to
+  stdout, followed by the equivalent existential normal form formula.
+  The formulas read are not stored.  For the input file containing:
+  <pre> AG(foo=bar); </pre> the following is produced: <pre> original
+  formula: AG(foo=bar) => equivalent existential formula: !(E(TRUE U
+  !(foo=bar))) </pre> For the syntax of CTL formulas, refer to <A
+  HREF="../ctl/ctl/ctl.html"> the VIS CTL and LTL syntax manual</A>.
+
+  Command options:<p>  
+
+  <dl><dt> -h
+  <dd> Print the command usage.
+  </dl>
+  ]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandCtlpTest(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int     c;
+  int      i;
+  FILE    *fp;
+  array_t *formulaArray;
+  array_t *convertedArray;
+  array_t *existentialConvertedArray;
+  array_t *forwardExistentialArray = NIL(array_t);
+  int     forwardTraversal = 0;
+  
+  /*
+   * Parse command line options.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "Fh")) != EOF) {
+    switch(c) {
+      case 'F':
+        forwardTraversal = 1;
+        break;
+      case 'h':
+        goto usage;
+      default:
+        goto usage;
+    }
+  }
+
+  /*
+   * Open the ctl file.
+   */
+  if (argc - util_optind == 0) {
+    (void) fprintf(vis_stderr, "** ctl error: ctl file not provided\n");
+    goto usage;
+  }
+  else if (argc - util_optind > 1) {
+    (void) fprintf(vis_stderr, "** ctl error: too many arguments\n");
+    goto usage;
+  }
+
+  fp = Cmd_FileOpen(argv[util_optind], "r", NIL(char *), 0);
+  if (fp == NIL(FILE)) {
+    (void)fprintf(vis_stderr, "** ctl error: Cannot open the file %s\n", argv[util_optind]);
+    return 1;
+  }
+
+  /*
+   * Parse the formulas in the file.
+   */
+  formulaArray = Ctlp_FileParseFormulaArray(fp);
+  (void) fclose(fp);
+
+  if (formulaArray == NIL(array_t)) {
+    fflush(vis_stdout);
+    fflush(vis_stderr);
+    return 1;
+  }
+
+  if (forwardTraversal)
+    forwardExistentialArray =
+      Ctlp_FormulaArrayConvertToForward(formulaArray, 1, FALSE);
+
+  convertedArray = Ctlp_FormulaArrayConvertToDAG(formulaArray);
+  array_free(formulaArray);
+  existentialConvertedArray =
+      Ctlp_FormulaDAGConvertToExistentialFormDAG(convertedArray);
+  
+  /*
+   * Print each original formula and its corresponding converted formula.
+   */
+  for (i = 0; i < array_n(convertedArray); i++) {
+    Ctlp_Formula_t *formula;
+
+    formula = array_fetch(Ctlp_Formula_t *, convertedArray, i);
+    (void) fprintf(vis_stdout, "original formula: ");
+    Ctlp_FormulaPrint(vis_stdout, formula);
+    (void) fprintf(vis_stdout, "\n");
+
+    formula = array_fetch(Ctlp_Formula_t *, existentialConvertedArray, i);
+    (void) fprintf(vis_stdout, "=> equivalent existential formula: ");
+    Ctlp_FormulaPrint(vis_stdout, formula);
+    (void) fprintf(vis_stdout, "\n");
+
+    if (forwardTraversal) {
+      formula = array_fetch(Ctlp_Formula_t *, forwardExistentialArray, i);
+      (void) fprintf(vis_stdout, "=> equivalent forward existential formula: ");
+      Ctlp_FormulaPrint(vis_stdout, formula);
+      (void) fprintf(vis_stdout, "\n");
+    }
+  }
+
+  (void)fprintf(vis_stdout, "No. of subformulae (including formulae) = %d\n",
+                FormulaArrayCountSubformulae(existentialConvertedArray));
+  if (forwardTraversal) {
+    (void)fprintf(vis_stdout,
+                  "No. of forward subformulae (including formulae) = %d\n",
+                  FormulaArrayCountSubformulae(forwardExistentialArray));
+  }
+
+
+  Ctlp_FormulaArrayFree(convertedArray);
+  Ctlp_FormulaArrayFree(existentialConvertedArray);
+  if (forwardTraversal)
+    Ctlp_FormulaArrayFree(forwardExistentialArray);
+  
+  fflush(vis_stdout);
+  fflush(vis_stderr);
+
+  return 0;		/* normal exit */
+
+usage:
+  (void) fprintf(vis_stderr, "usage: _ctlp_test file [-h]\n");
+  (void) fprintf(vis_stderr, "   -h  print the command usage\n");
+  return 1;		/* error exit */
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of subformulae in formulaArray.]
+
+  Description [The function counts the number of subformulae in formulaArray
+  (including the formulae themselves) by traversing the DAG. It uses the field
+  states in Ctlp_Formula_t to mark the visited states.]
+  
+  SideEffects [The field states is set to 1.]
+
+******************************************************************************/
+static int
+FormulaArrayCountSubformulae(
+  array_t *formulaArray)
+{
+  int num, i;
+  Ctlp_Formula_t *formula;
+  int count = 0;
+  
+  num = array_n(formulaArray);
+  for(i=0; i<num; i++){
+    formula = array_fetch(Ctlp_Formula_t *, formulaArray, i);
+    FormulaVisitUnvisitedSubformulae(formula, &count);
+  }
+  /* Set the field states to NULL */
+  for(i=0; i<num; i++){
+    formula = array_fetch(Ctlp_Formula_t *, formulaArray, i);
+    CtlpFormulaSetStatesToNULL(formula);
+  }
+  return count;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Visits each unvisited subformula of formula.]
+
+  Description [The formula visits each unvisited subformula of formula and
+  increments *ptr by 1 each time. It also marks each of those as visited.]
+  
+  SideEffects []
+
+******************************************************************************/
+static void
+FormulaVisitUnvisitedSubformulae(
+  Ctlp_Formula_t *formula,
+  int *ptr)
+{
+  if(formula!=NIL(Ctlp_Formula_t)) {
+    if(formula->states == NIL(mdd_t)) {
+      (*ptr)++;
+      formula->states = (mdd_t *) 1;
+      if(formula->type != Ctlp_ID_c) {
+        FormulaVisitUnvisitedSubformulae(formula->left, ptr);
+        FormulaVisitUnvisitedSubformulae(formula->right, ptr);
+      }
+    }
+  }
+}
+
+
+  
+  
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/ctlp/ctlpInt.h
===================================================================
--- vis_dev/vis-2.3/src/ctlp/ctlpInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/ctlp/ctlpInt.h	(revision 14)
@@ -0,0 +1,180 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [ctlpInt.h]
+
+  PackageName [ctlp]
+
+  Synopsis    [Declarations for internal use.]
+
+  Author      [Gary York, Ramin Hojati, Tom Shiple, Adnan Aziz, Yuji Kukimoto,
+               Jae-Young Jang, In-Ho Moon]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: ctlpInt.h,v 1.26 2005/05/13 05:51:05 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _CTLPINT
+#define _CTLPINT
+
+#define MAX_LENGTH_OF_VAR_NAME 512 
+
+#include <string.h>
+#include "ctlp.h"
+#include "hrc.h"
+#include "cmd.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [Tree representing a CTL formula.]
+
+  Description [Data structure for a CTL formula.  A formula is a tree
+  or a one-rooted DAG.  An internal vertex has one or two children,
+  depending on the operator type: if the operator takes just one
+  argument, then the left child holds the subformula, and the right
+  child is NULL; if the operator takes two arguments, then both
+  children are non-NULL.
+  
+  <p>A leaf is either a pair of a variable name in the network and a
+  value, TRUE or FALSE.  The left and right fields are used in leaf
+  vertices only in the first case above. (The left child holds a
+  variable name while the right child holds a value. Note that these
+  two fields are used differently in internal vertices and leaves.)
+
+  <p>DbgInfo is an uninterpreted pointer used by the CTL debugger to store
+  information needed to debug a formula.
+
+  <p>States holds the exact satisfying set of a formula in some fsm (the fsm is
+  not stored along with the set).  The Underapprox and overapprox fields are
+  approximations of the states field. Either states is NIL (no exact result is
+  known), or both underapprox and overapprox are NIL (the exact result is
+  known, or nothing is known at all).
+
+  Note that the convertedFlag being NIL does not imply that originalFormula is
+  NIL: a conversion could have been done that was trivial for the particular
+  node.]
+
+******************************************************************************/
+struct CtlpFormulaStruct {
+  Ctlp_FormulaType type;
+  Ctlp_Formula_t *left;   /* left child in formula */
+  Ctlp_Formula_t *right;  /* right child, or null if not used */
+  int refCount;           /* number of formulas referring to this
+			     formula as a left or right child */
+  mdd_t	*states;          /* set of states satifying formula */
+  mdd_t *underapprox;     /* Underapproximation of states (for hints) */
+  mdd_t *overapprox;      /* overapprox for hints */
+  array_t *Bottomstates;
+  array_t *Topstates;
+  array_t *leaves;
+  array_t *matchfound_top;    /*array of booleans*/
+  array_t *matchelement_top;  /* array of match numbers*/
+  array_t *matchfound_bot;    /*array of booleans*/
+  array_t *matchelement_bot;  /* array of match numbers*/
+  Ctlp_Parity_t negation_parity; /* negation parity */
+  int share;
+  struct {
+    void *data;           /* used  to store information used by debugger */
+    Ctlp_DbgInfoFreeFn freeFn;         /* free function for data */
+    boolean convertedFlag;  /* was converted to existential form
+                                           by non-trivial transformation */
+    Ctlp_Formula_t *originalFormula; /* pointer to formula from which this
+                                           was converted */
+  } dbgInfo;
+  /*
+  ** The following fields are added for forward model checking.
+  */
+  short top; /* 0 : , 1 : forward */
+  short compareValue; /* 0 : = false, 1 : != false */
+  Ctlp_Approx_t latest;	  /* which of the three results is most recent */
+  array_t *BotOnionRings;
+  array_t *TopOnionRings;
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**Variable********************************************************************
+
+  Synopsis    [Global flag for parsing CTL file.]
+
+  Description [This flag is set to 0 before parsing a CTL file commences.  If
+  an error is found while parsing the file, this flag is set to 1.  After the
+  parser returns, if this flag is set, then the global CTL formula array is
+  freed.]
+
+******************************************************************************/
+extern int CtlpGlobalError;
+
+/**Variable********************************************************************
+
+  Synopsis    [Global pointer to the CTL formulas being created.]
+
+  Description [This pointer is always set to the current formula
+  so that the parser can free a partially constructed CTL formula
+  when an error is detected. Every time the parser starts reasing
+  a new formula, this variable is set to NIL(Ctlp_Fromula_t).]
+
+******************************************************************************/
+extern Ctlp_Formula_t *CtlpGlobalFormula;
+
+/**Variable********************************************************************
+
+  Synopsis    [Global pointer to the macro table of formulae]
+
+  Description [This pointer is always set to the macro table so that 
+  the parser can substitute macro string with defined formula]
+
+******************************************************************************/
+extern st_table *CtlpMacroTable;
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void CtlpFormulaSetStatesToNULL(Ctlp_Formula_t *formula);
+EXTERN void CtlpFormulaIncrementRefCount(Ctlp_Formula_t *formula);
+EXTERN void CtlpFormulaDecrementRefCount(Ctlp_Formula_t *formula);
+EXTERN void CtlpFormulaAddToGlobalArray(Ctlp_Formula_t * formula);
+EXTERN void CtlpFormulaFree(Ctlp_Formula_t * formula);
+EXTERN int CtlpStringChangeValueStrToBinString(char *value, char *binValueStr, int interval);
+EXTERN void CtlpChangeBracket(char *inStr);
+EXTERN char * CtlpGetVectorInfoFromStr(char *str, int *start, int *end, int *interval, int *inc);
+EXTERN int CtlpFormulaAddToTable(char *name, Ctlp_Formula_t *formula, st_table *macroTable);
+EXTERN Ctlp_Formula_t * CtlpFormulaFindInTable(char *name, st_table *macroTable);
+EXTERN Ctlp_FormulaClass CtlpResolveClass(Ctlp_FormulaClass class1, Ctlp_FormulaClass class2);
+EXTERN Ctlp_FormulaClass CtlpNegateFormulaClass(Ctlp_FormulaClass class_);
+
+/**AutomaticEnd***************************************************************/
+
+EXTERN void CtlpFileSetup(FILE *fp);  /* lives in a .l file, so not
+                                                automatically generated */
+EXTERN int CtlpYyparse(void);
+#endif /* _CTLPINT */
Index: vis_dev/vis-2.3/src/ctlp/ctlpUtil.c
===================================================================
--- vis_dev/vis-2.3/src/ctlp/ctlpUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/ctlp/ctlpUtil.c	(revision 14)
@@ -0,0 +1,4844 @@
+/**CFile***********************************************************************
+
+  FileName    [ctlpUtil.c]
+
+  PackageName [ctlp]
+
+  Synopsis    [Routines for manipulating CTL formulas.]
+
+  Description [This file contains routines for accessing the fields of the CTL
+  formula data structure, for printing CTL formulas, for reading CTL formulas
+  from a file, and for converting formulas to the existential form.]
+
+  Remarks [There are two types of conversion routines.  One set, for
+  mc and amc, converts a formula to existential normal form, i.e. the
+  AX, AU and AG operators are converted.  The other set, used in imc,
+  converts to simple existential form, a form consisting only of
+  E-operators and the boolean operators AND and NOT.
+
+  Simple existential form is incompatible with the mc debug routines,
+  because these depend on the specific form of the converted formula
+  to decide what the original formula was.
+
+  In the long run, the existential form should probably go, and the
+  debug routines should be adapted.  The only drawback of simple
+  existential form is that the XOR gets expanded into three nontrivial
+  operations, so maybe XOR (or IFF) should be retained. (RB.)]
+
+
+  Author      [Gary York, Ramin Hojati, Tom Shiple, Adnan Aziz, Yuji Kukimoto,
+	       Jae-Young Jang, In-Ho Moon]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ctlpInt.h"
+#include "errno.h"
+
+static char rcsid[] UNUSED = "$Id: ctlpUtil.c,v 1.71 2009/04/11 18:25:53 fabio Exp $";
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**Variable********************************************************************
+
+  Synopsis    [Array of CTL formulas (Ctlp_Formula_t) read from a file.]
+
+  SeeAlso     [Ctlp_FormulaArrayFree]
+
+******************************************************************************/
+static array_t *globalFormulaArray;
+static int	changeBracket = 1;
+
+/* see ctlpInt.h for documentation */
+int CtlpGlobalError;
+Ctlp_Formula_t *CtlpGlobalFormula;
+st_table *CtlpMacroTable;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static Ctlp_Formula_t * FormulaCreateWithType(Ctlp_FormulaType type);
+static int FormulaCompare(const char *key1, const char *key2);
+static int FormulaHash(char *key, int modulus);
+static Ctlp_Formula_t * FormulaHashIntoUniqueTable(Ctlp_Formula_t *formula, st_table *uniqueTable);
+static Ctlp_Formula_t * FormulaConvertToExistentialDAG(Ctlp_Formula_t *formula);
+static void FormulaConvertToForward(Ctlp_Formula_t *formula, int compareValue);
+static void FormulaInsertForwardCompareNodes(Ctlp_Formula_t *formula, Ctlp_Formula_t *parent, int compareValue);
+static int FormulaGetCompareValue(Ctlp_Formula_t *formula);
+static int FormulaIsConvertible(Ctlp_Formula_t *formula);
+static Ctlp_Formula_t * ReplaceSimpleFormula(Ctlp_Formula_t *formula);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Parses a file containing a set of CTL formulas.]
+
+  Description [Parses a file containing a set of semicolon-ending CTL
+  formulas, and returns an array of Ctlp_Formula_t representing those
+  formulas.  If an error is detected while parsing the file, the routine frees
+  any allocated memory and returns NULL.]
+
+  SideEffects [Manipulates the global variables globalFormulaArray,
+  CtlpGlobalError and CtlpGlobalFormula.]
+
+  SeeAlso     [Ctlp_FormulaArrayFree Ctlp_FormulaPrint]
+
+******************************************************************************/
+array_t *
+Ctlp_FileParseFormulaArray(
+  FILE * fp)
+{
+  st_generator *stGen;
+  char *name;
+  Ctlp_Formula_t *formula;
+  char *flagValue;
+  /*
+   * Initialize the global variables.
+   */
+  globalFormulaArray = array_alloc(Ctlp_Formula_t *, 0);
+  CtlpGlobalError = 0;
+  CtlpGlobalFormula = NIL(Ctlp_Formula_t);
+  CtlpMacroTable = st_init_table(strcmp,st_strhash);
+  CtlpFileSetup(fp);
+  /*
+   * Check if changing "[] -> <>" is disabled.
+   */
+  flagValue = Cmd_FlagReadByName("ctl_change_bracket");
+  if (flagValue != NIL(char)) {
+    if (strcmp(flagValue, "yes") == 0)
+      changeBracket = 1;
+    else if (strcmp(flagValue, "no") == 0)
+      changeBracket = 0;
+    else {
+      fprintf(vis_stderr,
+	"** ctl error : invalid value %s for ctl_change_bracket[yes/no]. ***\n",
+	flagValue);
+    }
+  }
+
+  (void)CtlpYyparse();
+  st_foreach_item(CtlpMacroTable,stGen,&name,&formula){
+     FREE(name);
+     CtlpFormulaFree(formula);
+  }
+  st_free_table(CtlpMacroTable);
+
+  /*
+   * Clean up if there was an error, otherwise return the array.
+   */
+  if (CtlpGlobalError){
+    Ctlp_FormulaArrayFree(globalFormulaArray);
+    return NIL(array_t);
+  }
+  else {
+    return globalFormulaArray;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns formula as a character string.]
+
+  Description [Returns formula as a character string. All subformulas are
+  delimited by parenthesis. The syntax used is the same as used by the CTL
+  parser.  Does nothing if passed a NULL formula.]
+
+  SideEffects []
+
+******************************************************************************/
+char *
+Ctlp_FormulaConvertToString(
+  Ctlp_Formula_t * formula)
+{
+  char *s1        = NIL(char);
+  char *s2        = NIL(char);
+  char *tmpString = NIL(char);
+  char *result;
+
+
+  if (formula == NIL(Ctlp_Formula_t)) {
+    return NIL(char);
+  }
+
+  /* The formula is a leaf. */
+  if (formula->type == Ctlp_ID_c){
+    return util_strcat3((char *)(formula->left), "=",(char *)(formula->right));
+  }
+
+  /* If the formula is a non-leaf, the function is called recursively */
+  s1 = Ctlp_FormulaConvertToString(formula->left);
+  s2 = Ctlp_FormulaConvertToString(formula->right);
+
+  switch(formula->type) {
+    /*
+     * The cases are listed in rough order of their expected frequency.
+     */
+    case Ctlp_OR_c:
+      tmpString = util_strcat3(s1, " + ",s2);
+      result    = util_strcat3("(", tmpString, ")");
+      break;
+    case Ctlp_AND_c:
+      tmpString = util_strcat3(s1, " * ", s2);
+      result    = util_strcat3("(", tmpString, ")");
+      break;
+    case Ctlp_THEN_c:
+      tmpString = util_strcat3(s1, " -> ", s2);
+      result    = util_strcat3("(", tmpString, ")");
+      break;
+    case Ctlp_XOR_c:
+      tmpString = util_strcat3(s1, " ^ ", s2);
+      result    = util_strcat3("(", tmpString, ")");
+      break;
+    case Ctlp_EQ_c:
+      tmpString = util_strcat3(s1, " <-> ", s2);
+      result    = util_strcat3("(", tmpString, ")");
+      break;
+    case Ctlp_NOT_c:
+      tmpString = util_strcat3("(", s1, ")");
+      result    = util_strcat3("!", tmpString, "");
+      break;
+    case Ctlp_EX_c:
+      result = util_strcat3("EX(", s1, ")");
+      FREE(s1);
+      break;
+    case Ctlp_EG_c:
+      result = util_strcat3("EG(", s1, ")");
+      break;
+    case Ctlp_EF_c:
+      result = util_strcat3("EF(", s1, ")");
+      break;
+    case Ctlp_EU_c:
+      tmpString = util_strcat3("E(", s1, " U ");
+      result    = util_strcat3(tmpString, s2, ")");
+      break;
+    case Ctlp_AX_c:
+      result = util_strcat3("AX(", s1, ")");
+      break;
+    case Ctlp_AG_c:
+      result = util_strcat3("AG(", s1, ")");
+      break;
+    case Ctlp_AF_c:
+      result = util_strcat3("AF(", s1, ")");
+      break;
+    case Ctlp_AU_c:
+      tmpString = util_strcat3("A(", s1, " U ");
+      result    = util_strcat3(tmpString, s2, ")");
+      break;
+    case Ctlp_TRUE_c:
+      result = util_strsav("TRUE");
+      break;
+    case Ctlp_FALSE_c:
+      result = util_strsav("FALSE");
+      break;
+    case Ctlp_Init_c:
+      result = util_strsav("Init");
+      break;
+    case Ctlp_Cmp_c:
+      if (formula->compareValue == 0)
+	tmpString = util_strcat3("[", s1, "] = ");
+      else
+	tmpString = util_strcat3("[", s1, "] != ");
+      result    = util_strcat3(tmpString, s2, "");
+      break;
+    case Ctlp_FwdU_c:
+      tmpString = util_strcat3("FwdU(", s1, ",");
+      result    = util_strcat3(tmpString, s2, ")");
+      break;
+    case Ctlp_FwdG_c:
+      tmpString = util_strcat3("FwdG(", s1, ",");
+      result    = util_strcat3(tmpString, s2, ")");
+      break;
+    case Ctlp_EY_c:
+      result = util_strcat3("EY(", s1, ")");
+      break;
+    default:
+      fail("Unexpected type");
+  }
+
+  if (s1 != NIL(char)) {
+    FREE(s1);
+  }
+
+  if (s2 != NIL(char)) {
+    FREE(s2);
+  }
+
+  if (tmpString != NIL(char)) {
+    FREE(tmpString);
+  }
+
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints a formula to a file.]
+
+  Description [Prints a formula to a file. All subformulas are delimited by
+  parenthesis. The syntax used is the same as used by the CTL parser.  Does
+  nothing if passed a NULL formula.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Ctlp_FormulaPrint(
+  FILE * fp,
+  Ctlp_Formula_t * formula)
+{
+  char *tmpString;
+  if (formula == NIL(Ctlp_Formula_t)) {
+    return;
+  }
+  tmpString = Ctlp_FormulaConvertToString(formula);
+  (void) fprintf(fp, "%s", tmpString);
+  FREE(tmpString);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the type of a formula.]
+
+  Description [Gets the type of a formula. See ctlp.h for all the types. It is
+  an error to call this function on a NULL formula.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlp_FormulaType
+Ctlp_FormulaReadType(
+  Ctlp_Formula_t * formula)
+{
+  assert( formula != NIL(Ctlp_Formula_t) );
+  return (formula->type);
+}
+
+#if 0
+boolean
+Ctlp_FormulaReadEvenNegations(
+  Ctlp_Formula_t * formula)
+{
+  assert(formula != NIL(Ctlp_Formula_t));
+  return (formula->even_negations);
+}
+#endif
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the compare value of a formula.]
+
+  Description [Gets the compare value of a formula.  It is an error to call
+  this function on a NULL formula.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Ctlp_FormulaReadCompareValue(
+  Ctlp_Formula_t * formula)
+{
+  int value;
+
+  assert( formula != NIL(Ctlp_Formula_t));
+  value = formula->compareValue;
+  return (value);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the variable name of a leaf formula.]
+
+  Description [Reads the variable name of a leaf formula.
+  It is an error to call this function on a non-leaf formula.]
+
+  SideEffects []
+
+******************************************************************************/
+char *
+Ctlp_FormulaReadVariableName(
+  Ctlp_Formula_t * formula)
+{
+  if (formula->type != Ctlp_ID_c){
+    fail("Ctlp_FormulaReadVariableName() was called on a non-leaf formula.");
+  }
+  return ((char *)(formula->left));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the value name of a leaf formula.]
+
+  Description [Reads the value name of a leaf formula.
+  It is an error to call this function on a non-leaf formula.]
+
+  SideEffects []
+
+******************************************************************************/
+char *
+Ctlp_FormulaReadValueName(
+  Ctlp_Formula_t * formula)
+{
+  if (formula->type != Ctlp_ID_c){
+    fail("Ctlp_FormulaReadValueName() was called on a non-leaf formula.");
+  }
+  return ((char *)(formula->right));
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the left child of a formula.]
+
+  Description [Gets the left child of a formula.  User must not free this
+  formula. If a formula is a leaf formula, NIL(Ctlp_Formula_t) is returned.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlp_FormulaReadRightChild]
+
+******************************************************************************/
+Ctlp_Formula_t *
+Ctlp_FormulaReadLeftChild(
+  Ctlp_Formula_t * formula)
+{
+  if (formula->type != Ctlp_ID_c){
+    return (formula->left);
+  }
+  return NIL(Ctlp_Formula_t);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the right child of a formula.]
+
+  Description [Gets the right child of a formula.  User must not free this
+  formula. If a formula is a leaf formula, NIL(Ctlp_Formula_t) is returned.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlp_FormulaReadLeftChild]
+
+******************************************************************************/
+Ctlp_Formula_t *
+Ctlp_FormulaReadRightChild(
+  Ctlp_Formula_t * formula)
+{
+  if (formula->type != Ctlp_ID_c){
+    return (formula->right);
+  }
+  return NIL(Ctlp_Formula_t);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Gets a copy of the set of states for which this formula is
+  true.]
+
+  Description [Gets a copy of the MDD representing the set of states for which
+  this formula is true.  It is the user's responsibility to free this MDD. If
+  the set of states has not yet been computed, then a NULL mdd_t is
+  returned. It is an error to call this function on a NULL formula.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlp_FormulaSetStates]
+
+******************************************************************************/
+mdd_t *
+Ctlp_FormulaObtainStates(
+  Ctlp_Formula_t * formula)
+{
+  assert(formula != NIL(Ctlp_Formula_t));
+  if (formula->states == NIL(mdd_t) ||
+      formula->latest == Ctlp_Incomparable_c) {
+    return NIL(mdd_t);
+  }
+  else {
+    return mdd_dup(formula->states);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Stores the set of states with the formula.]
+
+  Description [Stores the MDD with the formula (a copy is not made,
+  and hence, the caller should not later free this MDD). This MDD is
+  intended to represent the set of states for which the formula is
+  true. It is an error to call this function on a NULL formula.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlp_FormulaObtainStates]
+
+******************************************************************************/
+void
+Ctlp_FormulaSetStates(
+  Ctlp_Formula_t * formula,
+  mdd_t * states)
+{
+  assert(formula != NIL(Ctlp_Formula_t));
+  /* RB: added the next two lines.  Given the Description, this was a
+     bug */
+  if(formula->states != NIL(mdd_t))
+    mdd_free(formula->states);
+  formula->states = states;
+  formula->latest = Ctlp_Exact_c;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Gets (a copy of) the latest approximation of the satisfying set]
+
+  Description [Gets the satisfying set or an approximation of it.  The most
+  recently computed approximation is returned.  If the
+  exact set is available, it will return that, because it is never superseded.
+  If neither exact nor approximate satisfying set is available, or
+  approx is Ctlp_Incomparable_c, it fails.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlp_FormulaSetApproxStates]
+
+******************************************************************************/
+mdd_t *
+Ctlp_FormulaObtainLatestApprox(
+  Ctlp_Formula_t *formula)
+{
+  if (formula->latest == Ctlp_Exact_c)
+    return mdd_dup(formula->states);
+
+  if (formula->latest == Ctlp_Overapprox_c)
+    return mdd_dup(formula->overapprox);
+
+  if (formula->latest == Ctlp_Underapprox_c)
+    return mdd_dup(formula->underapprox);
+
+  if (formula->latest == Ctlp_Incomparable_c)
+    return mdd_dup(formula->states);
+
+  assert(0);  /* we should never get here */
+  return NIL(mdd_t);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Gets (a copy of) an approximation of the satisfying set]
+
+  Description [Gets the required approximation of the satisfying set.  If the
+  exact set is available, it will return that.  If neither is available, or
+  approx is Ctlp_Incomparable_c, it will return NULL.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlp_FormulaSetApproxStates]
+
+******************************************************************************/
+mdd_t *
+Ctlp_FormulaObtainApproxStates(
+  Ctlp_Formula_t *formula,
+  Ctlp_Approx_t approx)
+{
+  if(approx == Ctlp_Incomparable_c)
+    return NIL(mdd_t);
+
+  if (formula->states != NIL(mdd_t))
+    return mdd_dup(formula->states);
+
+  if(approx == Ctlp_Exact_c)
+    return NIL(mdd_t);
+
+  if(approx == Ctlp_Overapprox_c){
+    if(formula->overapprox == NIL(mdd_t))
+      return NIL(mdd_t);
+    else
+      return mdd_dup(formula->overapprox);
+  }
+
+  if(approx == Ctlp_Underapprox_c){
+    if(formula->underapprox == NIL(mdd_t))
+      return NIL(mdd_t);
+    else
+      return mdd_dup(formula->underapprox);
+  }
+
+  assert(0);  /* we should never get here */
+  return NIL(mdd_t);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Stores (an approximation of) the set of states with the
+  formula.]
+
+  Description [Sets the set of states or an under or overapproximation
+  thereof, depending on the approx flag.  If there is already an under
+  or overapproximation, it is overwritten.  If the exact set is given,
+  the approx fields are cleared.  Setting an incomparable
+  approximation results in no action being taken.  An approximation
+  does not replace the exact set.  A copy of the mdd is not made, so
+  the caller should not free it.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlp_FormulaObtainApproxStates Ctlp_FormulaObtainLatestApprox]
+
+******************************************************************************/
+void
+Ctlp_FormulaSetApproxStates(
+  Ctlp_Formula_t * formula,
+  mdd_t * states,
+  Ctlp_Approx_t approx)
+{
+  if (formula->latest == Ctlp_Exact_c) {
+    mdd_free(states);
+    return;
+  }
+
+  formula->latest = approx;
+
+  if (approx == Ctlp_Exact_c) {
+    if (formula->states != NIL(mdd_t))
+      mdd_free(formula->states);
+    formula->states = states;
+
+    if (formula->underapprox != NIL(mdd_t)) {
+      mdd_free(formula->underapprox);
+      formula->underapprox = NIL(mdd_t);
+    }
+
+    if (formula->overapprox != NIL(mdd_t)) {
+      mdd_free(formula->overapprox);
+      formula->overapprox = NIL(mdd_t);
+    }
+
+    return;
+  }
+
+  if (approx == Ctlp_Underapprox_c) {
+    /* you could perform a union instead, but typical use will
+       have monotonically increasing underapproximations */
+    if(formula->underapprox != NIL(mdd_t))
+      mdd_free(formula->underapprox);
+    formula->underapprox = states;
+  }
+
+  if (approx == Ctlp_Overapprox_c) {
+    /* you could perform an intersection instead */
+    if (formula->overapprox != NIL(mdd_t))
+      mdd_free(formula->overapprox);
+    formula->overapprox = states;
+  }
+
+  /* This case is possible; for instance when both children of an implication
+   * with (All, S) condition are underapproximated.  We may lose some states
+   * from the left if they are not in S.  These cause an overapproximation.
+   * We may also lose some states from the right.  These cause an
+   * underapproximation.  When the two effects are combined, we get something
+   * incomparable, yet sufficient to produce the exact result, because it is
+   * accurate over S. */
+  if (approx == Ctlp_Incomparable_c) {
+    if (formula->states != NIL(mdd_t))
+      mdd_free(formula->states);
+    formula->states = states;
+  }
+
+  return;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the debug information of a formula.]
+
+  Description [Sets the debug information of a CTL formula.  The data is
+  uninterpreted.  FreeFn is a pointer to a function that takes a formula as
+  input and returns void.  FreeFn should free all the memory associated with
+  the debug data; it is called when this formula is freed.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlp_FormulaReadDebugData]
+
+******************************************************************************/
+void
+Ctlp_FormulaSetDbgInfo(
+  Ctlp_Formula_t * formula,
+  void *data,
+  Ctlp_DbgInfoFreeFn freeFn)
+{
+  if (formula->dbgInfo.data != NIL(void)){
+    assert(formula->dbgInfo.freeFn != NULL);
+
+    (*formula->dbgInfo.freeFn)(formula);
+  }
+
+  formula->dbgInfo.data   = data;
+  formula->dbgInfo.freeFn = freeFn;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the debug data associated with a formula.]
+
+  Description [Returns the debug data associated with a formula.  These data
+  are uninterpreted by the ctlp package.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlp_FormulaSetDbgInfo]
+
+******************************************************************************/
+void *
+Ctlp_FormulaReadDebugData(
+  Ctlp_Formula_t * formula)
+{
+  return formula->dbgInfo.data;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns TRUE if formula was converted, else FALSE.]
+  from AX/AG/AU/AF]
+
+  Description [Returns TRUE if formula was converted from a formula of type
+  AG, AX, AU, AF, or EF via a call to
+  Ctlp_FormulaConvertToExistentialFormTree or
+  Ctlp_FormulaConvertToExistentialFormDAG. Otherwise, returns FALSE.]
+
+  SideEffects []
+
+******************************************************************************/
+boolean
+Ctlp_FormulaTestIsConverted(
+  Ctlp_Formula_t * formula)
+{
+  return formula->dbgInfo.convertedFlag;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns TRUE if formula contains no path quantifiers.]
+
+  Description [Test if a CTL formula has any path quantifiers in it;
+  if so return false, else true.  For a CTL formula, being quantifier-free
+  and being propositional are equivalent.]
+
+  SideEffects []
+
+******************************************************************************/
+boolean
+Ctlp_FormulaTestIsQuantifierFree(
+  Ctlp_Formula_t *formula)
+{
+  boolean lCheck;
+  boolean rCheck;
+  Ctlp_Formula_t *leftChild;
+  Ctlp_Formula_t *rightChild;
+  Ctlp_FormulaType type;
+
+  if ( formula == NIL( Ctlp_Formula_t ) ) {
+    return TRUE;
+  }
+
+  type = Ctlp_FormulaReadType( formula );
+
+  if ( ( type == Ctlp_ID_c ) ||
+       ( type == Ctlp_TRUE_c ) ||
+       ( type == Ctlp_FALSE_c ) ) {
+    return TRUE;
+  }
+
+  if ( ( type !=  Ctlp_OR_c )   &&
+       ( type !=  Ctlp_AND_c )  &&
+       ( type !=  Ctlp_NOT_c )  &&
+       ( type !=  Ctlp_THEN_c ) &&
+       ( type !=  Ctlp_XOR_c )  &&
+       ( type !=  Ctlp_EQ_c ) ) {
+    return FALSE;
+  }
+
+  leftChild = Ctlp_FormulaReadLeftChild( formula );
+  lCheck = Ctlp_FormulaTestIsQuantifierFree( leftChild );
+
+  if (lCheck == FALSE)
+    return FALSE;
+
+  rightChild = Ctlp_FormulaReadRightChild( formula );
+  rCheck = Ctlp_FormulaTestIsQuantifierFree( rightChild );
+
+  return rCheck;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Annotates the each node in parse tree with its negation
+  parity.]
+
+  Description [This function must be called at the top level with
+  parity = Ctlp_Even_c.  It will then annotate each node with its parity.
+  A node in a formula with sharing may have both parities and a descendant
+  of a XOR or EQ node will have both.  Only backward CTL formulae are
+  considered.]
+
+  SideEffects [changes the negation_parity fields of all nodes in the formula]
+
+******************************************************************************/
+void
+Ctlp_FormulaNegations(
+  Ctlp_Formula_t * formula,
+  Ctlp_Parity_t parity)
+{
+
+  Ctlp_FormulaType formulaType;
+  Ctlp_Formula_t *leftChild;
+  Ctlp_Formula_t *rightChild;
+  Ctlp_Parity_t newparity;
+
+  assert(formula != NIL(Ctlp_Formula_t));
+  if (formula->negation_parity == parity)
+    return; /* already done */
+  if (formula->negation_parity != Ctlp_NoParity_c)
+    parity = Ctlp_EvenOdd_c; /* reconverging paths with different parity */
+  formula->negation_parity = parity;
+
+  formulaType = Ctlp_FormulaReadType(formula);
+  leftChild = Ctlp_FormulaReadLeftChild(formula);
+  rightChild = Ctlp_FormulaReadRightChild(formula);
+
+  switch (formulaType) {
+  case Ctlp_AX_c:
+  case Ctlp_AG_c:
+  case Ctlp_AF_c:
+  case Ctlp_EX_c:
+  case Ctlp_EG_c:
+  case Ctlp_EF_c:
+    Ctlp_FormulaNegations(leftChild,parity);
+    break;
+  case Ctlp_AU_c:
+  case Ctlp_EU_c:
+  case Ctlp_OR_c:
+  case Ctlp_AND_c:
+    Ctlp_FormulaNegations(leftChild,parity);
+    Ctlp_FormulaNegations(rightChild,parity);
+    break;
+  case Ctlp_NOT_c:
+    if (parity == Ctlp_Even_c)
+      newparity = Ctlp_Odd_c;
+    else if (parity == Ctlp_Odd_c)
+      newparity = Ctlp_Even_c;
+    else newparity = Ctlp_EvenOdd_c;
+    Ctlp_FormulaNegations(leftChild,newparity);
+    break;
+  case Ctlp_THEN_c:
+    if (parity == Ctlp_Even_c)
+      newparity = Ctlp_Odd_c;
+    else if (parity == Ctlp_Odd_c)
+      newparity = Ctlp_Even_c;
+    else newparity = Ctlp_EvenOdd_c;
+    Ctlp_FormulaNegations(leftChild,newparity);
+    Ctlp_FormulaNegations(rightChild,parity);
+    break;
+  case Ctlp_XOR_c:
+  case Ctlp_EQ_c:
+    Ctlp_FormulaNegations(leftChild,Ctlp_EvenOdd_c);
+    Ctlp_FormulaNegations(rightChild,Ctlp_EvenOdd_c);
+    break;
+  default:
+      break;
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether an ACTL formula is W-ACTL.]
+
+  Description [Test if the binary operators in an ACTL formula have at
+  least one propositional formula as one of the operands.  If not return
+  Ctlp_NONWACTL_c, else return either Ctlp_WACTLsimple_c for propositional
+  formulae or Ctlp_WACTLstate_c for formulae containing temporal operators.
+  A W-ACTL formula must contain no exitential operators and no forward
+  operators.  XOR and EQ are allowed only in propositional subformulae.]
+
+  SideEffects [none]
+
+******************************************************************************/
+Ctlp_FormulaACTLSubClass
+Ctlp_CheckIfWACTL(
+  Ctlp_Formula_t *formula)
+{
+  Ctlp_FormulaType formulaType;
+  Ctlp_Formula_t *rightFormula, *leftFormula;
+  Ctlp_FormulaACTLSubClass resultLeft, resultRight;
+
+  assert(formula != NIL(Ctlp_Formula_t));
+  if(formula == NIL(Ctlp_Formula_t))
+    return Ctlp_WACTLsimple_c;
+
+  formulaType = Ctlp_FormulaReadType(formula);
+  leftFormula = Ctlp_FormulaReadLeftChild(formula);
+  rightFormula = Ctlp_FormulaReadRightChild(formula);
+
+  /* Depending on the formula type, create result or recur. */
+  switch (formulaType) {
+  case Ctlp_AX_c:
+  case Ctlp_AG_c:
+  case Ctlp_AF_c:
+    resultLeft = Ctlp_CheckIfWACTL(leftFormula);
+    if (resultLeft == Ctlp_NONWACTL_c)
+      return Ctlp_NONWACTL_c;
+    else
+      return Ctlp_WACTLstate_c;
+    break;
+  case Ctlp_AU_c:
+    resultLeft = Ctlp_CheckIfWACTL(leftFormula);
+    if (resultLeft == Ctlp_NONWACTL_c)
+      return Ctlp_NONWACTL_c;
+    resultRight = Ctlp_CheckIfWACTL(rightFormula);
+    if (resultRight == Ctlp_NONWACTL_c)
+      return Ctlp_NONWACTL_c;
+    if (resultLeft == Ctlp_WACTLsimple_c || resultRight == Ctlp_WACTLsimple_c)
+      return Ctlp_WACTLstate_c;
+    else
+      return Ctlp_NONWACTL_c;
+    break;
+  case Ctlp_OR_c:
+  case Ctlp_AND_c:
+  case Ctlp_THEN_c:
+    resultLeft = Ctlp_CheckIfWACTL(leftFormula);
+    if (resultLeft == Ctlp_NONWACTL_c) {
+      return Ctlp_NONWACTL_c;
+    } else {
+      resultRight = Ctlp_CheckIfWACTL(rightFormula);
+      if (resultRight == Ctlp_WACTLsimple_c) {
+	return resultLeft;
+      } else if (resultLeft == Ctlp_WACTLsimple_c) {
+	return resultRight;
+      } else {
+	return Ctlp_NONWACTL_c;
+      }
+    }
+    break;
+  case Ctlp_NOT_c:
+    resultLeft = Ctlp_CheckIfWACTL(leftFormula);
+    return resultLeft;
+    break;
+  case Ctlp_XOR_c:
+  case Ctlp_EQ_c:
+    resultLeft = Ctlp_CheckIfWACTL(leftFormula);
+    if (resultLeft != Ctlp_WACTLsimple_c) {
+      return Ctlp_NONWACTL_c;
+    } else {
+      resultRight = Ctlp_CheckIfWACTL(rightFormula);
+      if (resultRight == Ctlp_WACTLsimple_c)
+	return Ctlp_WACTLsimple_c;
+      else
+	return Ctlp_NONWACTL_c;
+    }
+    break;
+  case Ctlp_ID_c:
+  case Ctlp_TRUE_c:
+  case Ctlp_FALSE_c:
+    return Ctlp_WACTLsimple_c;
+    break;
+  default:
+    fprintf(vis_stderr, "#Ctlp Result : The formula should be in Universal operators!\n");
+    return Ctlp_NONWACTL_c;
+    break;
+  }
+} /* End of Ctlp_CheckTypeOfExistentialFormula */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns original formula corresponding to converted formula.]
+
+  SideEffects []
+
+******************************************************************************/
+Ctlp_Formula_t *
+Ctlp_FormulaReadOriginalFormula(
+  Ctlp_Formula_t * formula)
+{
+  return formula->dbgInfo.originalFormula;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a formula if no other formula refers to it as a
+  sub-formula.]
+
+  Description [The function decrements the refCount of the formula. As a
+  consequence, if the refCount becomes 0, the formula is freed.]
+
+  SideEffects []
+
+  SeeAlso     [CtlpFormulaFree, CtlpDecrementRefCount]
+
+******************************************************************************/
+void
+Ctlp_FormulaFree(
+  Ctlp_Formula_t *formula)
+{
+  CtlpFormulaDecrementRefCount(formula);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Recursively frees states, underapprox and overapprox fields of
+  Ctlp_Formula_t, and the debug data]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     [Ctlp_FormulaFree]
+
+******************************************************************************/
+void
+Ctlp_FlushStates(
+  Ctlp_Formula_t * formula)
+{
+  if (formula != NIL(Ctlp_Formula_t)) {
+
+    if (formula->type != Ctlp_ID_c){
+      if (formula->left  != NIL(Ctlp_Formula_t)) {
+	Ctlp_FlushStates(formula->left);
+      }
+      if (formula->right != NIL(Ctlp_Formula_t)) {
+	Ctlp_FlushStates(formula->right);
+      }
+    }
+
+    if (formula->states != NIL(mdd_t)){
+      mdd_free(formula->states);
+      formula->states = NIL(mdd_t);
+    }
+    if (formula->underapprox != NIL(mdd_t)){
+      mdd_free(formula->underapprox);
+      formula->underapprox = NIL(mdd_t);
+    }
+    if (formula->overapprox != NIL(mdd_t)){
+      mdd_free(formula->overapprox);
+      formula->overapprox = NIL(mdd_t);
+    }
+
+    if (formula->dbgInfo.data != NIL(void)){
+      (*formula->dbgInfo.freeFn)(formula);
+      formula->dbgInfo.data = NIL(void);
+    }
+
+  }
+
+}
+
+/**Function********************************************************************
+
+
+  Synopsis    [Duplicates a CTL formula.]
+
+  Description [Recursively duplicate a formula. Does nothing if the formula
+  is NIL. Does not copy mdd for states, underapprox, overapprox, dbgInfo, and
+  in general all the information that is used to annotate the formula.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlp_Formula_t *
+Ctlp_FormulaDup(
+  Ctlp_Formula_t * formula)
+{
+  Ctlp_Formula_t *result = NIL(Ctlp_Formula_t);
+
+  if ( formula == NIL(Ctlp_Formula_t)) {
+	return NIL(Ctlp_Formula_t);
+  }
+
+  result = ALLOC(Ctlp_Formula_t, 1);
+
+  result->type                    = formula->type;
+  result->states                  = NIL(mdd_t);
+  result->underapprox             = NIL(mdd_t);
+  result->overapprox              = NIL(mdd_t);
+  result->latest                  = Ctlp_Incomparable_c;
+  result->Bottomstates            = NIL(array_t);
+  result->Topstates               = NIL(array_t);
+  result->negation_parity         = Ctlp_NoParity_c;
+  result->leaves                  = formula->leaves == NIL(array_t) ?
+    NIL(array_t) : array_dup(formula->leaves);
+  result->matchfound_top          = NIL(array_t);
+  result->matchelement_top        = NIL(array_t);
+  result->matchfound_bot          = NIL(array_t);
+  result->matchelement_bot        = NIL(array_t);
+  result->refCount                = 1;
+  result->dbgInfo.data            = NIL(void);
+  result->dbgInfo.freeFn          = (Ctlp_DbgInfoFreeFn) NULL;
+  result->dbgInfo.convertedFlag   = FALSE;
+  result->dbgInfo.originalFormula = NIL(Ctlp_Formula_t);
+  result->top                     = 0;
+  result->compareValue            = 0;
+
+  if ( formula->type != Ctlp_ID_c )  {
+    result->left                    = Ctlp_FormulaDup( formula->left );
+    result->right                   = Ctlp_FormulaDup( formula->right );
+  }
+  else {
+    result->left  = (Ctlp_Formula_t *) util_strsav((char *)formula->left );
+    result->right = (Ctlp_Formula_t *) util_strsav((char *)formula->right );
+  }
+  result->share		  = 1;
+  result->BotOnionRings   = NIL(array_t);
+  result->TopOnionRings   = NIL(array_t);
+  return result;
+}
+
+/**Function********************************************************************
+
+
+  Synopsis    [Complements a CTL formula.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlp_Formula_t *
+Ctlp_FormulaConverttoComplement(
+  Ctlp_Formula_t * formula)
+{
+  Ctlp_Formula_t *result;
+
+  if (formula == NIL(Ctlp_Formula_t)) {
+	return NIL(Ctlp_Formula_t);
+  }
+  result = Ctlp_FormulaCreate(Ctlp_NOT_c,formula,NIL(Ctlp_Formula_t));
+  CtlpFormulaIncrementRefCount(formula);
+#if 0
+  result = FormulaCreateWithType(Ctlp_NOT_c);
+  result->left = FormulaCreateWithType(formula->type);
+  result->left->left = formula->left;
+  result->left->right = formula->right;
+  switch (formula->type) {
+  case Ctlp_ID_c:
+  case Ctlp_TRUE_c:
+  case Ctlp_FALSE_c:
+  case Ctlp_Init_c:
+    break;
+  default:
+    CtlpFormulaIncrementRefCount(formula->left);
+    CtlpFormulaIncrementRefCount(formula->right);
+    break;
+  }
+#endif
+  return result;
+} /* Ctlp_FormulaConverttoComplement */
+
+
+/**Function********************************************************************
+
+
+  Synopsis    [Converts AFp to A (TRUE) U p.]
+
+  Description []
+
+  SideEffects [Should be called only for AF formula]
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlp_Formula_t *
+Ctlp_FormulaConvertAFtoAU(
+  Ctlp_Formula_t * formula)
+{
+  Ctlp_Formula_t *result;
+  /* AFf --> (A true U f)  */
+  assert(formula->type == Ctlp_AF_c);
+  result = FormulaCreateWithType(Ctlp_AU_c);
+  result->left  = FormulaCreateWithType(Ctlp_TRUE_c);
+  result->right = formula->left;
+  CtlpFormulaIncrementRefCount(formula->left);
+  return result;
+}
+
+
+/**Function********************************************************************
+
+
+  Synopsis    [Converts EFp to p + EX(EFp).]
+
+  Description []
+
+  SideEffects [Should be called only for EF formula]
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlp_Formula_t *
+Ctlp_FormulaConvertEFtoOR(
+  Ctlp_Formula_t * formula)
+{
+  Ctlp_Formula_t *result;
+  /* EFf --> f + EX(EF(f))  */
+  assert(formula->type == Ctlp_EF_c);
+  result = FormulaCreateWithType(Ctlp_OR_c);
+  result->left = formula->left;
+  result->right = FormulaCreateWithType(Ctlp_EX_c);
+  result->right->left = formula;
+  CtlpFormulaIncrementRefCount(formula->left);
+  CtlpFormulaIncrementRefCount(formula);
+  return result;
+}
+
+
+/**Function********************************************************************
+
+
+  Synopsis    [Converts EpUq to q + p*EX(EpUq).]
+
+  Description []
+
+  SideEffects [Should be called only for EU formula]
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlp_Formula_t *
+Ctlp_FormulaConvertEUtoOR(
+  Ctlp_Formula_t * formula)
+{
+  Ctlp_Formula_t *result;
+  assert(formula->type == Ctlp_EU_c);
+  /* E(f1)U(f2) --> f2 + f1*EX( E(f1)U(f2) )  */
+  result = FormulaCreateWithType(Ctlp_OR_c);
+  result->left = formula->right;
+  result->right = FormulaCreateWithType(Ctlp_AND_c);
+  result->right->left = formula->left;
+  result->right->right = FormulaCreateWithType(Ctlp_EX_c);
+  result->right->right->left = formula;
+  CtlpFormulaIncrementRefCount(formula->left);
+  CtlpFormulaIncrementRefCount(formula->right);
+  CtlpFormulaIncrementRefCount(formula);
+  return result;
+}
+
+
+/**Function********************************************************************
+
+
+  Synopsis    [Convert p^q to !p*q + p*!q.]
+
+  Description []
+
+  SideEffects [Should be called only for XOR formula]
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlp_Formula_t *
+Ctlp_FormulaConvertXORtoOR(
+  Ctlp_Formula_t * formula)
+{
+  Ctlp_Formula_t *result;
+  assert(formula->type == Ctlp_XOR_c);
+  result = FormulaCreateWithType(Ctlp_OR_c);
+  result->left = FormulaCreateWithType(Ctlp_AND_c);
+  result->right = FormulaCreateWithType(Ctlp_AND_c);
+  result->left->left = Ctlp_FormulaConverttoComplement(formula->left);
+  result->left->right = formula->right;
+  result->right->left = formula->left;
+  result->right->right = Ctlp_FormulaConverttoComplement(formula->right);
+  CtlpFormulaIncrementRefCount(formula->left);
+  CtlpFormulaIncrementRefCount(formula->right);
+  return result;
+}
+
+
+/**Function********************************************************************
+
+
+  Synopsis    [Converts p<->q to p*q + !p*!q.]
+
+  Description []
+
+  SideEffects [Should be called only for EQ formula]
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlp_Formula_t *
+Ctlp_FormulaConvertEQtoOR(
+  Ctlp_Formula_t * formula)
+{
+  Ctlp_Formula_t *result;
+  assert(formula->type == Ctlp_EQ_c);
+  result = FormulaCreateWithType(Ctlp_OR_c);
+  result->left = FormulaCreateWithType(Ctlp_AND_c);
+  result->right = FormulaCreateWithType(Ctlp_AND_c);
+  result->left->left = formula->left;
+  result->left->right = formula->right;
+  result->right->left = Ctlp_FormulaConverttoComplement(formula->left);
+  result->right->right = Ctlp_FormulaConverttoComplement(formula->right);
+  CtlpFormulaIncrementRefCount(formula->left);
+  CtlpFormulaIncrementRefCount(formula->right);
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns formula with a negation pushed down]
+
+  Description [Returns formula with a negation pushed down. It is assumed that
+	       the formula being passsed to it is not a proposition]
+
+  SideEffects []
+
+******************************************************************************/
+Ctlp_Formula_t *
+Ctlp_FormulaPushNegation(
+  Ctlp_Formula_t * formula)
+{
+  Ctlp_Formula_t *result;
+  if (formula == NIL(Ctlp_Formula_t)) {
+    return NIL(Ctlp_Formula_t);
+  }
+
+  switch(formula->type) {
+    /*
+     * The cases are listed in rough order of their expected frequency.
+     */
+  case Ctlp_OR_c: /*!(f1 v f2) = !f1 * !f2*/
+    result = FormulaCreateWithType(Ctlp_AND_c);
+    result->left  = Ctlp_FormulaConverttoComplement(formula->left);
+    result->right = Ctlp_FormulaConverttoComplement(formula->right);
+    break;
+  case Ctlp_AND_c: /*!(f1 * f2) = !f1 v !f2*/
+    result = FormulaCreateWithType(Ctlp_OR_c);
+    result->left  = Ctlp_FormulaConverttoComplement(formula->left);
+    result->right = Ctlp_FormulaConverttoComplement(formula->right);
+    break;
+  case Ctlp_THEN_c: /*!(f1 -> f2) = !(!f1 v f2) = f1 * !f2 */
+    result = FormulaCreateWithType(Ctlp_AND_c);
+    result->left  = formula->left;
+    CtlpFormulaIncrementRefCount(formula->left);
+    result->right = Ctlp_FormulaConverttoComplement(formula->right);
+    break;
+  case Ctlp_XOR_c: /*!(f1 ^ f2) = f1 <-> f2*/
+    result = FormulaCreateWithType(Ctlp_EQ_c);
+    result->left  = formula->left;
+    result->right = formula->right;
+    CtlpFormulaIncrementRefCount(formula->left);
+    CtlpFormulaIncrementRefCount(formula->right);
+    break;
+  case Ctlp_EQ_c: /*!(f1 <-> f2) = f1 ^ f2*/
+    result = FormulaCreateWithType(Ctlp_XOR_c);
+    result->left  = formula->left;
+    result->right = formula->right;
+    CtlpFormulaIncrementRefCount(formula->left);
+    CtlpFormulaIncrementRefCount(formula->right);
+    break;
+  case Ctlp_NOT_c:/* !(!f1) = f1*/
+    result = formula->left;
+    CtlpFormulaIncrementRefCount(formula->left);
+    break;
+  case Ctlp_EX_c:/* !(EX(f1)) = AX(!f1)*/
+    result = FormulaCreateWithType(Ctlp_AX_c);
+    result->left  = Ctlp_FormulaConverttoComplement(formula->left);
+    break;
+  case Ctlp_EG_c: /*!(EG(f1)) = AF(!f1)*/
+    result = FormulaCreateWithType(Ctlp_AF_c);
+    result->left  = Ctlp_FormulaConverttoComplement(formula->left);
+    break;
+  case Ctlp_EF_c: /*!(EF(f1)) = AG(!f1)*/
+    result = FormulaCreateWithType(Ctlp_AG_c);
+    result->left  = Ctlp_FormulaConverttoComplement(formula->left);
+    break;
+  case Ctlp_EU_c: /* !(EpUq) = A(!q)U(!(p+q) + AG(!q))*/
+    result = FormulaCreateWithType(Ctlp_AU_c);
+    result->left  = Ctlp_FormulaConverttoComplement(formula->right);
+    result->right = FormulaCreateWithType(Ctlp_OR_c);
+    result->right->left = FormulaCreateWithType(Ctlp_NOT_c);
+    result->right->left->left = FormulaCreateWithType(Ctlp_OR_c);
+    result->right->left->left->left = formula->left;
+    result->right->left->left->right = formula->right;
+    result->right->right = FormulaCreateWithType(Ctlp_AG_c);
+    result->right->right->left = Ctlp_FormulaConverttoComplement(formula->right);
+    CtlpFormulaIncrementRefCount(formula->left);
+    CtlpFormulaIncrementRefCount(formula->right);
+    break;
+  case Ctlp_AX_c:/* !AX(f1) = EX(!f1)*/
+    result = FormulaCreateWithType(Ctlp_EX_c);
+    result->left  = Ctlp_FormulaConverttoComplement(formula->left);
+    break;
+  case Ctlp_AG_c:/* !AG(f1) = EF(!f1) */
+    result = FormulaCreateWithType(Ctlp_EF_c);
+    result->left  = Ctlp_FormulaConverttoComplement(formula->left);
+    break;
+  case Ctlp_AF_c: /* !AF(f1) = EG(!f1)*/
+    result = FormulaCreateWithType(Ctlp_EG_c);
+    result->left  = Ctlp_FormulaConverttoComplement(formula->left);
+    break;
+  case Ctlp_AU_c: /* !(ApUq) = (E(!q)U(!(p+q)))+(EG!q)*/
+    result = FormulaCreateWithType(Ctlp_OR_c);
+    result->left = FormulaCreateWithType(Ctlp_EU_c);
+    result->left->left  = Ctlp_FormulaConverttoComplement(formula->right);
+    result->left->right = FormulaCreateWithType(Ctlp_NOT_c);
+    result->left->right->left= FormulaCreateWithType(Ctlp_OR_c);
+    result->left->right->left->left = formula->left;
+    result->left->right->left->right = formula->right;
+    result->right = FormulaCreateWithType(Ctlp_EG_c);
+    result->right->left = Ctlp_FormulaConverttoComplement(formula->right);
+    CtlpFormulaIncrementRefCount(formula->left);
+    CtlpFormulaIncrementRefCount(formula->right);
+    break;
+  case Ctlp_TRUE_c:/* !TRUE = FALSE*/
+    result = FormulaCreateWithType(Ctlp_FALSE_c);
+    break;
+  case Ctlp_FALSE_c:/*!FALSE = TRUE*/
+    result = FormulaCreateWithType(Ctlp_TRUE_c);
+    break;
+  case Ctlp_Init_c: /* ???*/
+  case Ctlp_Cmp_c: /* ???*/
+    /* if (formula->compareValue == 0)
+	tmpString = util_strcat3("[", s1, "] = ");
+      else
+	tmpString = util_strcat3("[", s1, "] != ");
+      result    = util_strcat3(tmpString, s2, "");
+      break;*/
+  case Ctlp_FwdU_c: /* ???*/
+  case Ctlp_FwdG_c:  /* ??? */
+  case Ctlp_EY_c: /* ??? */
+    result = formula;
+    break;
+  default:
+      fail("Unexpected type");
+  }
+
+  return result;
+}
+/*****************************************************************************/
+
+/**Function********************************************************************
+
+  Synopsis    [Frees an array of CTL formulas.]
+
+  Description [Calls CtlpFormulaDecrementRefCount on each formula in
+  formulaArray, and then frees the array itself. It is okay to call this
+  function with an empty array, but it is an error to call it with a NULL
+  array.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlp_FormulaFree]
+
+******************************************************************************/
+void
+Ctlp_FormulaArrayFree(
+  array_t * formulaArray /* of Ctlp_Formula_t */)
+{
+  int i;
+  int numFormulas = array_n(formulaArray);
+
+  assert(formulaArray != NIL(array_t));
+  for (i = 0; i < numFormulas; i++) {
+    Ctlp_Formula_t *formula = array_fetch(Ctlp_Formula_t *, formulaArray, i);
+
+    CtlpFormulaDecrementRefCount(formula);
+  }
+
+  array_free(formulaArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts a CTL formula to existential form.]
+
+  Description [Converts a CTL formula to existential form.  That is, all
+  universal path quantifiers are replaced with the appropriate combination of
+  existential quantifiers and Boolean negation.  Also converts "finally"
+  operators to "until" operators.<p>
+
+  <p>Returns a new formula that shares absolutely nothing with the original
+  formula (not even the strings). Also, the new formula does not have any MDDs
+  associated with it.  The "originalFormula" field of each new subformula is
+  set to point to the formula passed as an argument.  In addition, if (and only
+  if) the original formula is of type AG, AX, AU, AF, or EF, the "converted
+  flag" is set. Returns NULL if called with a NULL formula.
+
+  <p>Note: the debugger takes advantage of the exact way that the conversion is
+  done.  Hence, you cannot play around much with the syntax of the converted
+  formula.
+
+  <p>A list of conversion rules shouls be included here (RB).
+
+  <br> AG phi turns into !EU(true,! phi'), where the top ! has converted set
+  and points to the AG, and phi' points to phi.
+
+  <br> AU?
+
+  <br> AX?
+
+  <br> Any others?
+  ]
+
+  SideEffects []
+
+
+  SeeAlso [Ctlp_FormulaArrayConvertToExistentialForm,
+  Ctlp_ConvertToSimpleExistentialForm]
+
+******************************************************************************/
+Ctlp_Formula_t *
+Ctlp_FormulaConvertToExistentialForm(
+  Ctlp_Formula_t * formula)
+{
+  Ctlp_Formula_t *new_;
+  char *variableNameCopy, *valueNameCopy;
+
+  if (formula == NIL(Ctlp_Formula_t)) {
+    return NIL(Ctlp_Formula_t);
+  }
+
+  /*
+   * Recursively convert each subformula.
+   */
+
+  switch(formula->type) {
+    case Ctlp_EF_c:
+      /* EFf --> (E true U f)  */
+      new_ = FormulaCreateWithType(Ctlp_EU_c);
+      new_->left  = FormulaCreateWithType(Ctlp_TRUE_c);
+      new_->right = Ctlp_FormulaConvertToExistentialForm(formula->left);
+      new_->dbgInfo.convertedFlag = TRUE;
+      break;
+
+    case Ctlp_AX_c:
+      /* AXf --> !(EX(!f)) */
+      new_ = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left = FormulaCreateWithType(Ctlp_EX_c);
+      new_->left->left = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left->left->left = Ctlp_FormulaConvertToExistentialForm(formula->left);
+      new_->dbgInfo.convertedFlag = TRUE;
+      break;
+
+    case Ctlp_AG_c:
+      /* AGf --> ![(E true U !f)] */
+      new_ = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left = FormulaCreateWithType(Ctlp_EU_c);
+      new_->left->left = FormulaCreateWithType(Ctlp_TRUE_c);
+      new_->left->right = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left->right->left = Ctlp_FormulaConvertToExistentialForm(formula->left);
+      new_->dbgInfo.convertedFlag = TRUE;
+      break;
+
+    case Ctlp_AF_c:
+      /* AFf --> ![EG(!f)] */
+      new_ = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left = FormulaCreateWithType(Ctlp_EG_c);
+      new_->left->left = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left->left->left = Ctlp_FormulaConvertToExistentialForm(formula->left);
+      new_->dbgInfo.convertedFlag = TRUE;
+      break;
+
+    case Ctlp_AU_c:
+      /* A[fUg] --> !((E[!g U (!f*!g)]) + (EG!g)) */
+
+      new_ = FormulaCreateWithType(Ctlp_NOT_c); /* top */
+      new_->left = FormulaCreateWithType(Ctlp_OR_c); /* ((E[!g U (!f*!g)]) + (EG!g)) */
+
+      new_->left->right = FormulaCreateWithType(Ctlp_EG_c); /* EG !g */
+      new_->left->right->left = FormulaCreateWithType(Ctlp_NOT_c); /* !g */
+      new_->left->right->left->left = Ctlp_FormulaConvertToExistentialForm(formula->right); /* g */
+
+      new_->left->left = FormulaCreateWithType(Ctlp_EU_c); /* E[!g U (!f*!g)] */
+      new_->left->left->left = FormulaCreateWithType(Ctlp_NOT_c); /* !g */
+      new_->left->left->left->left = Ctlp_FormulaConvertToExistentialForm(formula->right); /* g */
+      new_->left->left->right = FormulaCreateWithType(Ctlp_AND_c); /* !f*!g */
+      new_->left->left->right->left = FormulaCreateWithType(Ctlp_NOT_c); /* !f */
+      new_->left->left->right->left->left = Ctlp_FormulaConvertToExistentialForm(formula->left); /* f */
+      new_->left->left->right->right = FormulaCreateWithType(Ctlp_NOT_c); /* !g */
+      new_->left->left->right->right->left = Ctlp_FormulaConvertToExistentialForm(formula->right); /* g */
+      new_->dbgInfo.convertedFlag = TRUE;
+      break;
+
+    case Ctlp_ID_c:
+      /* Make a copy of the name, and create a new formula. */
+      variableNameCopy = util_strsav((char *)(formula->left));
+      valueNameCopy = util_strsav((char *)(formula->right));
+      new_ = Ctlp_FormulaCreate(Ctlp_ID_c, variableNameCopy, valueNameCopy);
+      break;
+
+    case Ctlp_THEN_c:
+    case Ctlp_EX_c:
+    case Ctlp_EG_c:
+    case Ctlp_EU_c:
+    case Ctlp_OR_c:
+    case Ctlp_AND_c:
+    case Ctlp_NOT_c:
+    case Ctlp_XOR_c:
+    case Ctlp_EQ_c:
+    case Ctlp_TRUE_c:
+    case Ctlp_FALSE_c:
+      /* These are already in the correct form.  Just convert subformulas. */
+      new_ = FormulaCreateWithType(formula->type);
+      new_->left = Ctlp_FormulaConvertToExistentialForm(formula->left);
+      new_->right = Ctlp_FormulaConvertToExistentialForm(formula->right);
+      break;
+
+    default:
+      fail("Unexpected type");
+  }
+
+  new_->dbgInfo.originalFormula = formula;
+  return new_;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Converts a CTL formula to simple existential form.]
+
+  Description [Converts a CTL formula to simple existential form.
+  That is, all universal path quantifiers are replaced with the
+  appropriate combination of existential quantifiers and Boolean
+  negation. Only `NOT' and `AND' Boolean operators are allowed.  Also
+  converts "finally" operators to "until" operators.
+
+  The converted bit is set in the converted formula only when temporal
+  operators are converted, not when boolean operators are converted.
+
+  A  new formula is created that needs to be freed seperately.]
+
+  SideEffects []
+
+  Remarks     [Ctl formulas in simple existential form are incompatible
+  with the mc debug routines.  The reason is that the debug routines
+  count on a very specific form of the converted formula to conclude
+  what the original formula was.]
+
+  SeeAlso     [Ctlp_FormulaArrayConvertToExistentialForm]
+
+******************************************************************************/
+Ctlp_Formula_t *
+Ctlp_FormulaConvertToSimpleExistentialForm(
+  Ctlp_Formula_t * formula)
+{
+  Ctlp_Formula_t *new_;
+  char *variableNameCopy, *valueNameCopy;
+
+  if (formula == NIL(Ctlp_Formula_t)) {
+    return NIL(Ctlp_Formula_t);
+  }
+
+  /*
+   * Recursively convert each subformula.
+   */
+
+  switch(formula->type) {
+    case Ctlp_EF_c:
+      /* EFf --> (E true U f)  */
+      new_ = FormulaCreateWithType(Ctlp_EU_c);
+      new_->left  = FormulaCreateWithType(Ctlp_TRUE_c);
+      new_->right = Ctlp_FormulaConvertToSimpleExistentialForm(formula->left);
+      new_->dbgInfo.convertedFlag = TRUE;
+      break;
+
+    case Ctlp_AX_c:
+      /* AXf --> !(EX(!f)) */
+      new_ = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left = FormulaCreateWithType(Ctlp_EX_c);
+      new_->left->left = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left->left->left =
+	Ctlp_FormulaConvertToSimpleExistentialForm(formula->left);
+      new_->dbgInfo.convertedFlag = TRUE;
+      break;
+
+    case Ctlp_AG_c:
+      /* AGf --> ![(E true U !f)] */
+      new_ = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left = FormulaCreateWithType(Ctlp_EU_c);
+      new_->left->left = FormulaCreateWithType(Ctlp_TRUE_c);
+      new_->left->right = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left->right->left =
+	Ctlp_FormulaConvertToSimpleExistentialForm(formula->left);
+      new_->dbgInfo.convertedFlag = TRUE;
+      break;
+
+    case Ctlp_AF_c:
+      /* AFf --> ![EG(!f)] */
+      new_ = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left = FormulaCreateWithType(Ctlp_EG_c);
+      new_->left->left = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left->left->left = Ctlp_FormulaConvertToSimpleExistentialForm(formula->left);
+      new_->dbgInfo.convertedFlag = TRUE;
+      break;
+
+    case Ctlp_AU_c:
+      /* A[fUg] --> !(E[!g U (!f*!g)]) * !(EG!g)) */
+
+      new_ = FormulaCreateWithType(Ctlp_AND_c); /* top */
+      new_->left = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->right = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left->left = FormulaCreateWithType(Ctlp_EG_c); /* EG !g */
+      new_->left->left->left = FormulaCreateWithType(Ctlp_NOT_c); /* !g */
+      new_->left->left->left->left =
+	Ctlp_FormulaConvertToSimpleExistentialForm(formula->right); /* g */
+
+      new_->right->left = FormulaCreateWithType(Ctlp_EU_c); /* E[!g U (!f*!g)] */
+      new_->right->left->left = FormulaCreateWithType(Ctlp_NOT_c); /* !g */
+      new_->right->left->left->left =
+	Ctlp_FormulaConvertToSimpleExistentialForm(formula->right); /* g */
+      new_->right->left->right = FormulaCreateWithType(Ctlp_AND_c); /* !f*!g */
+      new_->right->left->right->left = FormulaCreateWithType(Ctlp_NOT_c); /* !f */
+      new_->right->left->right->left->left =
+	Ctlp_FormulaConvertToSimpleExistentialForm(formula->left); /* f */
+      new_->right->left->right->right = FormulaCreateWithType(Ctlp_NOT_c); /* !g */
+      new_->right->left->right->right->left =
+	Ctlp_FormulaConvertToSimpleExistentialForm(formula->right); /* g */
+      new_->dbgInfo.convertedFlag = TRUE;
+      break;
+
+    case Ctlp_ID_c:
+      /* Make a copy of the name, and create a new formula. */
+      variableNameCopy = util_strsav((char *)(formula->left));
+      valueNameCopy = util_strsav((char *)(formula->right));
+      new_ = Ctlp_FormulaCreate(Ctlp_ID_c, variableNameCopy, valueNameCopy);
+      break;
+
+      /* RB: I think THEN (and also OR, and maybe some others) should also have converted set. */
+    case Ctlp_THEN_c:
+      /* p->q --> !(p * !q) */
+      new_ = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left = FormulaCreateWithType(Ctlp_AND_c);
+      new_->left->left =
+	Ctlp_FormulaConvertToSimpleExistentialForm(formula->left);
+      new_->left->right = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left->right->left =
+	Ctlp_FormulaConvertToSimpleExistentialForm(formula->right);
+      break;
+
+    case Ctlp_EX_c:
+    case Ctlp_EG_c:
+    case Ctlp_EU_c:
+    case Ctlp_AND_c:
+    case Ctlp_NOT_c:
+    case Ctlp_TRUE_c:
+    case Ctlp_FALSE_c:
+      /* These are already in the correct form.  Just convert subformulas. */
+      new_ = FormulaCreateWithType(formula->type);
+      new_->left = Ctlp_FormulaConvertToSimpleExistentialForm(formula->left);
+      new_->right = Ctlp_FormulaConvertToSimpleExistentialForm(formula->right);
+      break;
+
+    case Ctlp_OR_c:
+      /* p + q --> !(!p * !q) */
+      new_ = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left = FormulaCreateWithType(Ctlp_AND_c);
+      new_->left->left = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left->right = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left->left->left =
+	Ctlp_FormulaConvertToSimpleExistentialForm(formula->left);
+      new_->left->right->left =
+	Ctlp_FormulaConvertToSimpleExistentialForm(formula->right);
+      break;
+    case Ctlp_XOR_c:
+      /* p ^ q --> !(p * q) * !(!p * !q) */
+      new_ = FormulaCreateWithType(Ctlp_AND_c);
+      new_->left = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left->left = FormulaCreateWithType(Ctlp_AND_c);
+      new_->left->left->left =
+	Ctlp_FormulaConvertToSimpleExistentialForm(formula->left);
+      new_->left->left->right =
+	Ctlp_FormulaConvertToSimpleExistentialForm(formula->right);
+      new_->right = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->right->left = FormulaCreateWithType(Ctlp_AND_c);
+      new_->right->left->left =  FormulaCreateWithType(Ctlp_NOT_c);
+      new_->right->left->left->left =
+	Ctlp_FormulaConvertToSimpleExistentialForm(formula->left);
+      new_->right->left->right = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->right->left->right->left =
+	Ctlp_FormulaConvertToSimpleExistentialForm(formula->right);
+      break;
+
+    case Ctlp_EQ_c:
+      /* p <-> q --> !(p * !q) * !(!p * q) */
+      new_ = FormulaCreateWithType(Ctlp_AND_c);
+      new_->left = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left->left = FormulaCreateWithType(Ctlp_AND_c);
+      new_->left->left->left =
+	Ctlp_FormulaConvertToSimpleExistentialForm(formula->left);
+      new_->left->left->right = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left->left->right->left =
+	Ctlp_FormulaConvertToSimpleExistentialForm(formula->right);
+      new_->right = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->right->left = FormulaCreateWithType(Ctlp_AND_c);
+      new_->right->left->left =  FormulaCreateWithType(Ctlp_NOT_c);
+      new_->right->left->left->left =
+	Ctlp_FormulaConvertToSimpleExistentialForm(formula->left);
+      new_->right->left->right =
+	Ctlp_FormulaConvertToSimpleExistentialForm(formula->right);
+      break;
+
+    default:
+      fail("Unexpected type");
+  }
+
+  new_->dbgInfo.originalFormula = formula;
+  return new_;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Converts an array of CTL formulas to existential form.]
+
+  Description [Calls Ctlp_FormulaConvertToExistentialForm on each formula. It
+  is okay to call this function with an empty array (in which case an empty
+  array is returned), but it is an error to call it with a NULL array.
+
+  All formulas in the array are copied, and hence Ctlp_FormulaArrayFree() needs
+  to be called on the result at the end.]
+
+  SideEffects []
+
+  SeeAlso [Ctlp_FormulaConvertToExistentialForm]
+
+******************************************************************************/
+array_t *
+Ctlp_FormulaArrayConvertToExistentialFormTree(
+  array_t * formulaArray /* of Ctlp_Formula_t  */)
+{
+  int i;
+  int numFormulas = array_n(formulaArray);
+  array_t *convertedArray = array_alloc(Ctlp_Formula_t *, numFormulas);
+
+  assert(formulaArray != NIL(array_t));
+
+  for (i = 0; i < numFormulas; i++) {
+    Ctlp_Formula_t *formula          = array_fetch(Ctlp_Formula_t *, formulaArray, i);
+    Ctlp_Formula_t *convertedFormula = Ctlp_FormulaConvertToExistentialForm(formula);
+
+    array_insert(Ctlp_Formula_t *, convertedArray, i, convertedFormula);
+  }
+
+  return convertedArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Converts an array of CTL formulas to simple existential form.]
+
+  Description [Calls Ctlp_FormulaConvertToSimpleExistentialForm on
+  each formula.  It is okay to call this function with an empty array
+  (in which case an empty array is returned), but it is an error to
+  call it with a NULL array.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlp_FormulaConvertToExistentialForm]
+
+******************************************************************************/
+array_t *
+Ctlp_FormulaArrayConvertToSimpleExistentialFormTree(
+  array_t * formulaArray /* of Ctlp_Formula_t  */)
+{
+  int i;
+  int numFormulas;
+  array_t *convertedArray;
+
+  assert( formulaArray != NIL(array_t));
+
+  numFormulas = array_n(formulaArray);
+  convertedArray = array_alloc(Ctlp_Formula_t *, numFormulas);
+
+  for (i = 0; i < numFormulas; i++) {
+    Ctlp_Formula_t *formula;
+    Ctlp_Formula_t *convertedFormula;
+
+    formula = array_fetch(Ctlp_Formula_t *, formulaArray, i);
+    convertedFormula = Ctlp_FormulaConvertToSimpleExistentialForm(formula);
+
+    array_insert(Ctlp_Formula_t *, convertedArray, i, convertedFormula);
+  }
+
+  return convertedArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Converts an array of CTL formulae to a multi-rooted DAG.]
+
+  Description [The function hashes each subformula of a formula
+  (including the formula itself) into a uniqueTable.  It returns an
+  array containing the roots of the multi-rooted DAG thus created by
+  the sharing of the subformulae.  It is okay to call this function
+  with an empty array (in which case an empty array is returned), but
+  it is an error to call it with a NULL array.]
+
+  SideEffects [A formula in formulaArray might be freed if it had been
+  encountered as a subformula of some other formula. Other formulae in
+  formulaArray might be present in the returned array. Therefore, the
+  formulae in formulaArray should not be freed. Only formulaArray
+  itself should be freed.
+
+
+
+  RB:  What does that mean?
+
+  I understand this as follows.  Copies of the formulae are not made,
+  but rather pointers to the argument subformulae are kept.  Hence, not only
+  should the formulae in the result not be freed, but also you cannot free the
+  argument before you are done with the result.  Furthermore, by invocation of
+  this function, the argument gets altered.  It is still valid, but pointers
+  may have changed.  Is this correct?
+
+
+  RB rewrite: A formula in formulaArray is freed if it is encountered as a
+  subformula of some other formula. Other formulae in formulaArray might be
+  present in the returned array. Therefore, the formulae in formulaArray should
+  not be freed. Only formulaArray itself should be freed.]
+
+  SeeAlso     []
+
+******************************************************************************/
+array_t *
+Ctlp_FormulaArrayConvertToDAG(
+  array_t *formulaArray)
+{
+  int i;
+  Ctlp_Formula_t *formula, *uniqueFormula;
+  st_table *uniqueTable = st_init_table(FormulaCompare, FormulaHash);
+  int numFormulae = array_n(formulaArray);
+  array_t *rootsOfFormulaDAG = array_alloc(Ctlp_Formula_t *, numFormulae);
+
+  assert(formulaArray != NIL(array_t));
+
+  for(i=0; i < numFormulae; i++) {
+    formula = array_fetch(Ctlp_Formula_t *, formulaArray, i);
+    uniqueFormula = FormulaHashIntoUniqueTable(formula, uniqueTable);
+    if(uniqueFormula != formula) {
+      CtlpFormulaDecrementRefCount(formula);
+      CtlpFormulaIncrementRefCount(uniqueFormula);
+      array_insert(Ctlp_Formula_t *, rootsOfFormulaDAG, i, uniqueFormula);
+    }
+    else
+      array_insert(Ctlp_Formula_t *, rootsOfFormulaDAG, i, formula);
+  }
+  st_free_table(uniqueTable);
+  return rootsOfFormulaDAG;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Converts a DAG of CTL formulae to a DAG of existential CTL
+  formulae.]
+
+  Description [The function converts a DAG of CTL formulae to a DAG of
+  existential CTL formulae. The function recursively converts each
+  subformula of each of the formulae in the DAG and remembers the
+  converted formula in the field states. It is okay to call this
+  function with an empty array (in which case an empty array is
+  returned), but it is an error to call it with a NULL array.
+
+  The states fileds in the formula need to be NULL.]
+
+  SideEffects []
+
+  SeeAlso     [FormulaConvertToExistentialDAG]
+
+******************************************************************************/
+array_t *
+Ctlp_FormulaDAGConvertToExistentialFormDAG(
+  array_t *formulaDAG)
+{
+  int i;
+  Ctlp_Formula_t *formula;
+  int numFormulae = array_n(formulaDAG);
+  array_t *existentialFormulaDAG = array_alloc(Ctlp_Formula_t *, numFormulae);
+
+  assert( formulaDAG != NIL(array_t));
+
+  for(i=0; i<numFormulae; i++) {
+    formula = array_fetch(Ctlp_Formula_t *, formulaDAG, i);
+    array_insert(Ctlp_Formula_t *, existentialFormulaDAG, i,
+		 FormulaConvertToExistentialDAG(formula));
+  }
+  for(i=0; i<numFormulae; i++) {
+    formula = array_fetch(Ctlp_Formula_t *, formulaDAG, i);
+    CtlpFormulaSetStatesToNULL(formula);
+  }
+  return existentialFormulaDAG;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a CTL formula with the specified fields.]
+
+  Description [Allocates a Ctlp_Formula_t, and sets the 2 fields given as
+  arguments.  If the type is Ctlp_ID_c, then the left and right fields
+  should contain a pointer to a variable name and a pointer to a value
+  respectively. Otherwise, the two fields point to subformulas. refCount is
+  set to 1. The states field is set to NULL, the converted flag is set to
+  FALSE, and the originalFormula field is set to NULL.]
+
+  Comment     []
+
+  SideEffects []
+
+  SeeAlso     [CtlpFormulaDecrementRefCount]
+
+******************************************************************************/
+Ctlp_Formula_t *
+Ctlp_FormulaCreate(
+  Ctlp_FormulaType  type,
+  void * left,
+  void * right)
+{
+  Ctlp_Formula_t *formula = ALLOC(Ctlp_Formula_t, 1);
+
+  formula->type                    = type;
+  formula->left                    = (Ctlp_Formula_t *)left;
+  formula->right                   = (Ctlp_Formula_t *)right;
+  formula->refCount                = 1;
+  formula->states                  = NIL(mdd_t);
+  formula->underapprox             = NIL(mdd_t);
+  formula->overapprox              = NIL(mdd_t);
+  formula->Topstates		   = NIL(array_t);
+  formula->Bottomstates		   = NIL(array_t);
+  formula->leaves		   = NIL(array_t);
+  formula->matchfound_top          = NIL(array_t);
+  formula->matchelement_top        = NIL(array_t);
+  formula->matchfound_bot          = NIL(array_t);
+  formula->matchelement_bot        = NIL(array_t);
+  formula->negation_parity         = Ctlp_NoParity_c;
+  formula->share                   = 1;
+  formula->dbgInfo.data            = NIL(void);
+  formula->dbgInfo.freeFn          = (Ctlp_DbgInfoFreeFn) NULL;
+  formula->dbgInfo.convertedFlag   = FALSE;
+  formula->dbgInfo.originalFormula = NIL(Ctlp_Formula_t);
+  formula->top                     = 0;
+  formula->compareValue            = 0;
+  formula->latest                  = Ctlp_Incomparable_c;
+  formula->BotOnionRings           = NIL(array_t);
+  formula->TopOnionRings           = NIL(array_t);
+
+  return formula;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a CTL formula with disjunction of atomic propositions]
+
+  Description [This function returns Ctlp_Formula_t for name = {v1,v2,...}.
+  In case of failure, a NULL pointer is returned.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlp_Formula_t *
+Ctlp_FormulaCreateOr(
+  char *name,
+  char *valueStr)
+{
+  Ctlp_Formula_t *formula, *tempFormula;
+  char *preStr;
+
+  preStr = strtok(valueStr,",");
+  formula = Ctlp_FormulaCreate(Ctlp_ID_c, util_strsav(name),
+			       util_strsav(preStr));
+  if (formula == NIL(Ctlp_Formula_t)) {
+     return NIL(Ctlp_Formula_t);
+  }
+  while ((preStr = strtok(NIL(char),",")) != NIL(char)) {
+    tempFormula = Ctlp_FormulaCreate(Ctlp_ID_c, util_strsav(name),
+				     util_strsav(preStr));
+    if (tempFormula == NIL(Ctlp_Formula_t)) {
+      Ctlp_FormulaFree(formula);
+      return NIL(Ctlp_Formula_t);
+    }
+    formula = Ctlp_FormulaCreate(Ctlp_OR_c,formula,tempFormula);
+  }
+  return formula;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a CTL formula with conjunction of atomic propositions]
+
+  Description [This function returns Ctlp_Formula_t for nameVector = value,
+  nameVector is a form of var[i:j] or var<j:j> and value is any integer n or
+  binary string starting with 'b', for instance, b0011. If n is not
+  fitted in var[i:j] or size of binary string is not matched with
+  var[i:j], NULL pointer is returned]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlp_Formula_t *
+Ctlp_FormulaCreateVectorAnd(
+  char *nameVector,
+  char *value)
+{
+  Ctlp_Formula_t *formula, *tempFormula;
+  int startValue, endValue, inc, i,j, interval,startInd;
+  char *binValueStr, *varName, *name;
+  char *bitValue;
+
+  varName = CtlpGetVectorInfoFromStr(nameVector,&startValue,&endValue,&interval,&inc);
+  binValueStr = ALLOC(char,interval+1);
+  if (!CtlpStringChangeValueStrToBinString(value,binValueStr,interval) ){
+    FREE(varName);
+    FREE(binValueStr);
+    return NIL(Ctlp_Formula_t);
+  }
+
+  name = ALLOC(char,MAX_LENGTH_OF_VAR_NAME);
+  (void) sprintf(name,"%s[%d]",varName,startValue);
+  (void) CtlpChangeBracket(name);
+
+  bitValue = ALLOC(char,2);
+  bitValue[0] = binValueStr[0];
+  bitValue[1] = '\0';
+
+  formula = Ctlp_FormulaCreate(Ctlp_ID_c, util_strsav(name),
+			       util_strsav(bitValue));
+  j = 0;
+  startInd = startValue;
+  for(i=startValue;i!=endValue;i=i+inc){
+    startInd += inc;
+    j++;
+    (void) sprintf(name,"%s[%d]",varName,startInd);
+    (void) CtlpChangeBracket(name);
+    bitValue[0] = binValueStr[j];
+    tempFormula = Ctlp_FormulaCreate(Ctlp_ID_c, util_strsav(name),
+				     util_strsav(bitValue));
+    formula = Ctlp_FormulaCreate(Ctlp_AND_c,formula,tempFormula);
+  }
+  FREE(varName);
+  FREE(name);
+  FREE(binValueStr);
+  FREE(bitValue);
+  return formula;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a CTL formula with OR of Vector AND]
+
+  Description [This function returns Ctlp_Formula_t for nameVector = valueStr,
+  nameVector is a form of var[i:j] or var<j:j>, valueStr is "k,l,...,q",
+  and k,l,...,q is either integer or binary string.  Binary string starting
+  with 'b', for instance, b0011. If n is not fitted in var[i:j] or size of
+  binary string is not matched with var[i:j], NULL pointer is returned]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlp_Formula_t *
+Ctlp_FormulaCreateVectorOr(
+  char *nameVector,
+  char *valueStr)
+{
+  Ctlp_Formula_t *formula,*tempFormula;
+  char *preStr;
+
+  preStr = strtok(valueStr,",");
+  formula = Ctlp_FormulaCreateVectorAnd(nameVector,preStr);
+  if ( formula == NIL(Ctlp_Formula_t)){
+    return NIL(Ctlp_Formula_t);
+  }
+  while( (preStr = strtok(NIL(char),",")) != NIL(char) ){
+    tempFormula = Ctlp_FormulaCreateVectorAnd(nameVector,preStr);
+    if ( tempFormula == NIL(Ctlp_Formula_t)){
+      Ctlp_FormulaFree(formula);
+      return NIL(Ctlp_Formula_t);
+    }
+    formula = Ctlp_FormulaCreate(Ctlp_OR_c,formula,tempFormula);
+  }
+  return formula;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a CTL formula for equivalent property]
+
+  Description [This function assumes that each child is defined in binary
+  domain. Enumerate type is not supported]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlp_Formula_t *
+Ctlp_FormulaCreateEquiv(
+   char *left,
+   char *right)
+{
+   Ctlp_Formula_t *formula,*formula1,*formula2;
+
+   char *one;
+   char *zero;
+
+   one = "1";
+   zero = "0";
+
+   formula1 = Ctlp_FormulaCreate(Ctlp_ID_c, util_strsav(left),
+				 util_strsav(one));
+   formula2 = Ctlp_FormulaCreate(Ctlp_ID_c, util_strsav(right),
+				 util_strsav(zero));
+   formula = Ctlp_FormulaCreate(Ctlp_XOR_c,formula1,formula2);
+   return formula;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a CTL formula for equivalent of vector]
+
+  Description [This function returns a formula, which is the AND of a bitwise
+  equivalence]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlp_Formula_t *
+Ctlp_FormulaCreateVectorEquiv(
+  char *left,
+  char *right)
+{
+  Ctlp_Formula_t *formula,*tempFormula;
+  char *leftName,*rightName;
+  char *leftVar, *rightVar;
+  int  leftStart,leftEnd,rightStart,rightEnd,leftInterval,rightInterval;
+  int  leftInc,rightInc,leftInd,rightInd,i;
+
+  leftName  = CtlpGetVectorInfoFromStr(left,&leftStart,&leftEnd,&leftInterval,&leftInc);
+  rightName = CtlpGetVectorInfoFromStr(right,&rightStart,&rightEnd,&rightInterval,&rightInc);
+  if (leftInterval != rightInterval){
+     return NIL(Ctlp_Formula_t);
+  }
+  leftVar = ALLOC(char,MAX_LENGTH_OF_VAR_NAME);
+  (void) sprintf(leftVar,"%s[%d]",leftName,leftStart);
+  (void) CtlpChangeBracket(leftVar);
+  rightVar = ALLOC(char,MAX_LENGTH_OF_VAR_NAME);
+  (void) sprintf(rightVar,"%s[%d]",rightName,rightStart);
+  (void) CtlpChangeBracket(rightVar);
+
+  formula = Ctlp_FormulaCreateEquiv(leftVar,rightVar);
+  leftInd  = leftStart;
+  rightInd = rightStart;
+  for(i=leftStart;i!=leftEnd;i+=leftInc){
+     leftInd  += leftInc;
+     rightInd += rightInc;
+     (void) sprintf(leftVar,"%s[%d]",leftName,leftInd);
+     (void) CtlpChangeBracket(leftVar);
+     (void) sprintf(rightVar,"%s[%d]",rightName,rightInd);
+     (void) CtlpChangeBracket(rightVar);
+     tempFormula = Ctlp_FormulaCreateEquiv(leftVar,rightVar);
+     formula = Ctlp_FormulaCreate(Ctlp_AND_c,formula,tempFormula);
+  }
+  FREE(leftName);
+  FREE(rightName);
+  FREE(leftVar);
+  FREE(rightVar);
+  return formula;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a CTL formula for multiple AX]
+
+  Description [This function returns a formula, which is the multiple
+  times of AX. The given string includes the number of depth]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlp_Formula_t *
+Ctlp_FormulaCreateAXMult(
+  char *string,
+  Ctlp_Formula_t *formula)
+{
+  int i,num;
+  char *str, *ptr;
+  Ctlp_Formula_t *result;
+  str = strchr(string,':');
+  if ( str == NULL) return(NIL(Ctlp_Formula_t));
+  str++;
+
+  num = strtol(str,&ptr,0);
+
+  if (num<=0){
+    return (NIL(Ctlp_Formula_t));
+  }
+  result = Ctlp_FormulaCreate(Ctlp_AX_c,formula,NIL(Ctlp_Formula_t));
+  for(i=1;i<num;i++){
+    result = Ctlp_FormulaCreate(Ctlp_AX_c,result,NIL(Ctlp_Formula_t));
+  }
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a CTL formula for multiple EX]
+
+  Description [This function returns a formula, which is the multiple
+  times of EX. The given string includes the number of depth]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlp_Formula_t *
+Ctlp_FormulaCreateEXMult(
+  char *string,
+  Ctlp_Formula_t *formula)
+{
+  int i, num;
+  char *str, *ptr;
+  Ctlp_Formula_t *result;
+  str = strchr(string,':');
+  if ( str == NULL) return(NIL(Ctlp_Formula_t));
+  str++;
+
+  num = strtol(str,&ptr,0);
+
+  if (num<=0){
+    return (NIL(Ctlp_Formula_t));
+  }
+  result = Ctlp_FormulaCreate(Ctlp_EX_c,formula,NIL(Ctlp_Formula_t));
+  for(i=1;i<num;i++){
+    result = Ctlp_FormulaCreate(Ctlp_EX_c,result,NIL(Ctlp_Formula_t));
+  }
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Converts an array of CTL formulae to forward form.]
+
+  Description [Converts an array of CTL formulae to forward.  Creates a
+  maximally shared representation if noshare is false, a representation without
+  any sharing otherwise. ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+array_t *
+Ctlp_FormulaArrayConvertToForward(array_t *formulaArray, int singleInitial,
+				  boolean doNotShareFlag)
+{
+  int i;
+  Ctlp_Formula_t *formula, *existentialFormula, *forwardFormula;
+  int numFormulae = array_n(formulaArray);
+  array_t *forwardFormulaArray = array_alloc(Ctlp_Formula_t *, numFormulae);
+  array_t *forwardDagArray;
+  int compareValue;
+
+  for(i=0; i < numFormulae; i++) {
+    formula = array_fetch(Ctlp_Formula_t *, formulaArray, i);
+    existentialFormula = Ctlp_FormulaConvertToExistentialForm(formula);
+    assert(existentialFormula != NIL(Ctlp_Formula_t));
+    formula = NIL(Ctlp_Formula_t);
+   /*
+    ** compareValue = 0 : check with FALSE
+    ** compareValue = 1 : check with not-FALSE
+    */
+    if (singleInitial)
+      compareValue = FormulaGetCompareValue(existentialFormula);
+    else
+      compareValue = 0;
+    forwardFormula = FormulaCreateWithType(Ctlp_AND_c);
+    forwardFormula->left = FormulaCreateWithType(Ctlp_Init_c);
+    if (compareValue == 0) {
+      forwardFormula->right = FormulaCreateWithType(Ctlp_NOT_c);
+      forwardFormula->right->left = existentialFormula;
+    } else
+      forwardFormula->right = existentialFormula;
+    forwardFormula->right->states = (mdd_t *)forwardFormula;
+    /* if formula was converted before, keep that reference */
+    if(existentialFormula->dbgInfo.originalFormula != NIL(Ctlp_Formula_t))
+      forwardFormula->dbgInfo.originalFormula =
+	existentialFormula->dbgInfo.originalFormula;
+    else
+      forwardFormula->dbgInfo.originalFormula = existentialFormula;
+
+    forwardFormula->top = 1;
+    forwardFormula->compareValue = compareValue;
+    FormulaConvertToForward(forwardFormula->right, compareValue);
+    CtlpFormulaSetStatesToNULL(forwardFormula);
+    FormulaInsertForwardCompareNodes(forwardFormula, NULL, compareValue);
+    array_insert(Ctlp_Formula_t *, forwardFormulaArray, i, forwardFormula);
+  }
+
+  if (doNotShareFlag)
+    return(forwardFormulaArray);
+
+  forwardDagArray = Ctlp_FormulaArrayConvertToDAG(forwardFormulaArray);
+  array_free(forwardFormulaArray);
+  return forwardDagArray;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a string for each formula type.]
+
+  Description [Returns a string for each formula type.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+char *
+Ctlp_FormulaGetTypeString(Ctlp_Formula_t *formula)
+{
+  char *result;
+
+  switch(formula->type) {
+    /*
+     * The cases are listed in rough order of their expected frequency.
+     */
+    case Ctlp_ID_c:
+      result = util_strsav("ID");
+      break;
+    case Ctlp_OR_c:
+      result = util_strsav("OR");
+      break;
+    case Ctlp_AND_c:
+      result = util_strsav("AND");
+      break;
+    case Ctlp_THEN_c:
+      result = util_strsav("THEN");
+      break;
+    case Ctlp_XOR_c:
+      result = util_strsav("XOR");
+      break;
+    case Ctlp_EQ_c:
+      result = util_strsav("EQ");
+      break;
+    case Ctlp_NOT_c:
+      result = util_strsav("NOT");
+      break;
+    case Ctlp_EX_c:
+      result = util_strsav("EX");
+      break;
+    case Ctlp_EG_c:
+      result = util_strsav("EG");
+      break;
+    case Ctlp_EF_c:
+      result = util_strsav("EF");
+      break;
+    case Ctlp_EU_c:
+      result = util_strsav("EU");
+      break;
+    case Ctlp_AX_c:
+      result = util_strsav("AX");
+      break;
+    case Ctlp_AG_c:
+      result = util_strsav("AG");
+      break;
+    case Ctlp_AF_c:
+      result = util_strsav("AF");
+      break;
+    case Ctlp_AU_c:
+      result = util_strsav("AU");
+      break;
+    case Ctlp_TRUE_c:
+      result = util_strsav("TRUE");
+      break;
+    case Ctlp_FALSE_c:
+      result = util_strsav("FALSE");
+      break;
+    case Ctlp_Init_c:
+      result = util_strsav("Init");
+      break;
+    case Ctlp_Cmp_c:
+      result = util_strsav("Cmp");
+      break;
+    case Ctlp_FwdU_c:
+      result = util_strsav("FwdU");
+      break;
+    case Ctlp_FwdG_c:
+      result = util_strsav("FwdG");
+      break;
+    case Ctlp_EY_c:
+      result = util_strsav("EY");
+      break;
+    case Ctlp_EH_c:
+      result = util_strsav("EH");
+      break;
+    default:
+      fail("Unexpected type");
+  }
+  return(result);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [Tests if a formula is quantifier-free, ACTL, ECTL or
+  mixed.]
+
+  Description [Tests if a formula is Quantifier free, ACTL, ECTL or mixed.  We
+  assume that the formula is in existential normal form, and hence only
+  contains existential temporal operators.
+
+  <p>The formula is ECTL if every temporal operator appears under an even
+  number of negations, and it is ACTL if every temporal operator appears under
+  an odd number of negations.  It is quantifier-free if it is both ECTL and
+  ACTL (i.e., no temporal operators occur), and it is mixed if it is neither
+  ECTL nor ACTL.]
+
+  SideEffects        []
+
+  SeeAlso            []
+
+******************************************************************************/
+Ctlp_FormulaClass
+Ctlp_CheckClassOfExistentialFormula(
+  Ctlp_Formula_t *formula)
+{
+  Ctlp_FormulaType formulaType;
+  Ctlp_Formula_t *rightFormula, *leftFormula;
+  Ctlp_FormulaClass resultLeft, resultRight, tempResult, currentClass;
+
+  assert(formula != NIL(Ctlp_Formula_t));
+  if(formula == NIL(Ctlp_Formula_t))
+    return Ctlp_QuantifierFree_c;
+
+  formulaType = Ctlp_FormulaReadType(formula);
+  leftFormula = Ctlp_FormulaReadLeftChild(formula);
+  rightFormula = Ctlp_FormulaReadRightChild(formula);
+
+  /* Depending on the formula type, create result or recur */
+  switch (formulaType) {
+  case Ctlp_EX_c:
+  case Ctlp_EG_c:
+  case Ctlp_EF_c:
+  case Ctlp_EU_c:
+  case Ctlp_FwdU_c:
+  case Ctlp_FwdG_c:
+  case Ctlp_EY_c:
+  case Ctlp_EH_c:
+    resultLeft = Ctlp_CheckClassOfExistentialFormula(leftFormula);
+    if (formulaType == Ctlp_EU_c || formulaType == Ctlp_FwdU_c ||
+	formulaType == Ctlp_FwdG_c )
+      resultRight = Ctlp_CheckClassOfExistentialFormula(rightFormula);
+    else
+      resultRight = Ctlp_QuantifierFree_c;
+
+    tempResult = CtlpResolveClass(resultLeft, resultRight);
+    currentClass = Ctlp_ECTL_c;
+    return CtlpResolveClass(currentClass, tempResult);
+  case Ctlp_AX_c:
+  case Ctlp_AG_c:
+  case Ctlp_AF_c:
+  case Ctlp_AU_c:
+    /* The formula is supposed to be only existential */
+    fprintf(vis_stdout,
+	    "** Ctlp Error: unexpected (universal) operator type\n");
+    assert(0);
+    return Ctlp_Mixed_c;
+  case Ctlp_OR_c:
+  case Ctlp_AND_c:
+    resultLeft = Ctlp_CheckClassOfExistentialFormula(leftFormula);
+    resultRight = Ctlp_CheckClassOfExistentialFormula(rightFormula);
+    return CtlpResolveClass(resultLeft, resultRight);
+  case Ctlp_NOT_c:
+    tempResult = Ctlp_CheckClassOfExistentialFormula(leftFormula);
+    return CtlpNegateFormulaClass(tempResult);
+   case Ctlp_THEN_c:
+    resultLeft = Ctlp_CheckClassOfExistentialFormula(leftFormula);
+    resultRight = Ctlp_CheckClassOfExistentialFormula(rightFormula);
+    tempResult = CtlpNegateFormulaClass(resultLeft);
+    return CtlpResolveClass(tempResult, resultRight);
+  case Ctlp_XOR_c:
+  case Ctlp_EQ_c:
+    resultLeft =  Ctlp_CheckClassOfExistentialFormula(leftFormula);
+    resultRight = Ctlp_CheckClassOfExistentialFormula(rightFormula);
+    tempResult = CtlpResolveClass(resultLeft, resultRight);
+    if( tempResult == Ctlp_QuantifierFree_c)
+      return Ctlp_QuantifierFree_c;
+    else
+      return Ctlp_Mixed_c;
+  case Ctlp_ID_c:
+  case Ctlp_TRUE_c:
+  case Ctlp_FALSE_c:
+  case Ctlp_Init_c:
+     return Ctlp_QuantifierFree_c;
+  case Ctlp_Cmp_c:
+    return Ctlp_Mixed_c;
+  default:
+    fprintf(vis_stderr, "**Ctlp Error: Unexpected operator detected.\n");
+    assert(0);
+    return Ctlp_Mixed_c;
+  }
+} /* End of Ctlp_CheckTypeOfExistentialFormula */
+
+/**Function********************************************************************
+
+  Synopsis [Tests if an array of simple existential formulae has only
+  ACTL, only ECTL or mixture of formula.]
+
+  Description        [Returns Ctlp_ECTL_c if the array contains only
+  ECTL formulae, Ctlp_ACTL_c if it contains only ACTL formulae,
+  Ctlp_QuantifierFree_c if there are no quantifiers in any formulae,
+  and Ctlp_Mixed otherwise.]
+
+  SideEffects        []
+
+  SeeAlso            [Ctlp_CheckClassOfExistentialFormula]
+
+******************************************************************************/
+Ctlp_FormulaClass
+Ctlp_CheckClassOfExistentialFormulaArray(
+  array_t *formulaArray)
+{
+  Ctlp_FormulaClass result;
+  Ctlp_Formula_t *formula;
+  int formulanr;
+
+  result = Ctlp_QuantifierFree_c;
+  arrayForEachItem(Ctlp_Formula_t *, formulaArray, formulanr, formula){
+    Ctlp_FormulaClass  formulaType;
+    formulaType = Ctlp_CheckClassOfExistentialFormula(formula);
+    result = CtlpResolveClass(result, formulaType);
+    if(result == Ctlp_Mixed_c)
+      return result;
+  }
+  return result;
+} /* End of Ctlp_CheckTypeOfExistentialFormulaArray */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compare two formulas for equality]
+
+  Description [Checks if two formulas are syntactically the same.  Equivalent
+  constructions such as TRUE and TRUE+FALSE are not recognized, but copies are
+  handled correctly, and strings are compared using strcmp.]
+
+  SideEffects []
+
+  SeeAlso     [FormulaCompare]
+
+******************************************************************************/
+boolean
+Ctlp_FormulaIdentical(
+  Ctlp_Formula_t *formula1,
+  Ctlp_Formula_t *formula2)
+{
+  return(FormulaCompare((char *)formula1, (char *)formula2) == 0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Replaces non-monotonic operators in a formula.]
+
+  Description [This function takes a parse tree for a CTL formula and
+  transforms it into another tree that has only monotonic operators.
+  The non-monotonic operators are <code>XOR</code> and <code>EQ</code>.
+  They are replaced by eqivalent trees.  Specificallt, <code>XOR(a,b)</code>
+  is replaced by <code>OR(AND(a,NOT(b)),AND(NOT(a),b))</code> and
+  <code>f <-> g</code> is replaced by <code>AND(f->g,g->f)</code>.<p>
+
+  It is important that the original formula be a tree.  The idea is that this
+  function should be called right after reading the formulae from file.  Since
+  the information attached to the parse tree by the model checking procedures
+  is not preserved, it is also important that no such information exists.
+  These conditions are checked by an assertion.<p>
+
+  This function does not deal with the forward CTL operators.  Reduction to
+  monotonic operators should be performed before conversion to forward CTL.]
+
+  SideEffects [The argument is modified.  The new formulae will apprear
+  when they are printed out.]
+
+  SeeAlso     [Ctlp_FormulaArrayMakeMonotonic]
+
+******************************************************************************/
+void
+Ctlp_FormulaMakeMonotonic(
+  Ctlp_Formula_t *formula)
+{
+  Ctlp_Formula_t *left, *right;
+  Ctlp_FormulaType type;
+
+  if (formula == NIL(Ctlp_Formula_t)) {
+    return;
+  }
+
+  /* Make sure (recursively) that this (sub)-formula is still in its pristine
+   * state.  Specifically, that the parse graph is a tree.
+   */
+  assert(formula->refCount == 1 &&
+	 formula->states == NIL(mdd_t) &&
+	 formula->underapprox == NIL(mdd_t) &&
+	 formula->overapprox == NIL(mdd_t) &&
+	 formula->latest == Ctlp_Incomparable_c &&
+	 formula->dbgInfo.data == NIL(void) &&
+	 formula->dbgInfo.freeFn == (Ctlp_DbgInfoFreeFn) NULL &&
+	 formula->dbgInfo.convertedFlag == FALSE &&
+	 formula->dbgInfo.originalFormula == NIL(Ctlp_Formula_t) &&
+	 formula->top == 0 &&
+	 formula->compareValue == 0
+	 );
+
+  type = Ctlp_FormulaReadType(formula);
+
+  /* Leaves remain unchanged. */
+  if (type == Ctlp_ID_c || type == Ctlp_TRUE_c || type == Ctlp_FALSE_c) {
+    return;
+  }
+
+  /* First recursively fix the children. */
+  left  = Ctlp_FormulaReadLeftChild(formula);
+  Ctlp_FormulaMakeMonotonic(left);
+  right = Ctlp_FormulaReadRightChild(formula);
+  Ctlp_FormulaMakeMonotonic(right);
+
+  /* Fix this node if it is not monotonic. */
+  switch (type) {
+  case Ctlp_EX_c:
+  case Ctlp_EG_c:
+  case Ctlp_EF_c:
+  case Ctlp_EU_c:
+  case Ctlp_AX_c:
+  case Ctlp_AG_c:
+  case Ctlp_AF_c:
+  case Ctlp_AU_c:
+  case Ctlp_OR_c:
+  case Ctlp_AND_c:
+  case Ctlp_NOT_c:
+  case Ctlp_THEN_c:
+  case Ctlp_EY_c:
+  case Ctlp_EH_c:
+    /* Nothing to be done */
+    break;
+  case Ctlp_EQ_c: {
+    Ctlp_Formula_t *dupLeft, *dupRight;
+    Ctlp_Formula_t *thenLeft, *thenRight;
+    dupLeft   = Ctlp_FormulaDup(left);
+    dupRight  = Ctlp_FormulaDup(right);
+    thenLeft  = Ctlp_FormulaCreate(Ctlp_THEN_c, left, right);
+    thenRight = Ctlp_FormulaCreate(Ctlp_THEN_c, dupRight, dupLeft);
+    /* Fix the node in place. */
+    formula->type  = Ctlp_AND_c;
+    formula->left  = thenLeft;
+    formula->right = thenRight;
+    break;
+  }
+  case Ctlp_XOR_c: {
+    Ctlp_Formula_t *dupLeft, *dupRight;
+    Ctlp_Formula_t *negLeft, *negRight;
+    Ctlp_Formula_t *andLeft, *andRight;
+    dupLeft  = Ctlp_FormulaDup(left);
+    dupRight = Ctlp_FormulaDup(right);
+    negLeft  = Ctlp_FormulaCreate(Ctlp_NOT_c, dupLeft, NIL(Ctlp_Formula_t));
+    negRight = Ctlp_FormulaCreate(Ctlp_NOT_c, dupRight, NIL(Ctlp_Formula_t));
+    andLeft  = Ctlp_FormulaCreate(Ctlp_AND_c, left, negRight);
+    andRight = Ctlp_FormulaCreate(Ctlp_AND_c, negLeft, right);
+    /* Fix the node in place. */
+    formula->type  = Ctlp_OR_c;
+    formula->left  = andLeft;
+    formula->right = andRight;
+    break;
+  }
+  default:
+    /* Forward CTL operators (that are not supported) and leaves (that are
+     * dealt with above) would fall here.
+     */
+    fail("unexpected CTL formula type\n");
+  }
+
+  return;
+
+} /* Ctlp_FormulaMakeMonotonic */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Replaces non-monotonic operators in an array of formulae.]
+
+  Description [Apply Ctlp_FormulaMakeMonotonic to each formula in the array.]
+
+  SideEffects [The formulae in the array are modified.]
+
+  SeeAlso     [Ctlp_FormulaMakeMonotonic]
+
+******************************************************************************/
+void
+Ctlp_FormulaArrayMakeMonotonic(
+  array_t *formulaArray /* of Ctlp_Formula_t */)
+{
+  int i;
+  Ctlp_Formula_t *formula;
+
+  if (formulaArray == NIL(array_t)) return;
+  arrayForEachItem(Ctlp_Formula_t *, formulaArray, i, formula) {
+    Ctlp_FormulaMakeMonotonic(formula);
+  }
+
+} /* Ctlp_FormulaArrayMakeMonotonic */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Increments the reference count of a formula.]
+
+  Description [The function increments the reference count of a formula. If
+  the formula is NULL, the function does nothing.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+CtlpFormulaIncrementRefCount(
+  Ctlp_Formula_t *formula)
+{
+  if(formula!=NIL(Ctlp_Formula_t)) {
+    ++(formula->refCount);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Decrements the reference count of a formula.]
+
+  Description [The function decrements the reference count of formula and if
+  the reference count reaches 0, the formula is freed. If the formula is NULL,
+  the function does nothing. It is an error to decrement the reference count
+  below 0.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+CtlpFormulaDecrementRefCount(
+  Ctlp_Formula_t *formula)
+{
+  if(formula!=NIL(Ctlp_Formula_t)) {
+    assert(formula->refCount>0);
+    if(--(formula->refCount) == 0)
+      CtlpFormulaFree(formula);
+  }
+}
+/**Function********************************************************************
+
+  Synopsis    [Adds formula to the end of globalFormulaArray.]
+
+  SideEffects [Manipulates the global variable globalFormulaArray.]
+
+  SeeAlso     [CtlpYyparse]
+
+******************************************************************************/
+void
+CtlpFormulaAddToGlobalArray(
+  Ctlp_Formula_t * formula)
+{
+  array_insert_last(Ctlp_Formula_t *, globalFormulaArray, formula);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a CTL formula.]
+
+  Description [The function frees all memory associated with the formula,
+  including all MDDs and all character strings (however, does not free
+  dbgInfo.originalFormula). It also decrements the reference counts of its two
+  chidren. The function does nothing if formula is NULL.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlp_FormulaArrayFree]
+
+******************************************************************************/
+void
+CtlpFormulaFree(
+  Ctlp_Formula_t * formula)
+{
+  if (formula != NIL(Ctlp_Formula_t)) {
+
+    /*
+     * Free any fields that are not NULL.
+     */
+
+    if (formula->type == Ctlp_ID_c) {
+      FREE(formula->left);
+      FREE(formula->right);
+    }
+    else {
+      if (formula->left  != NIL(Ctlp_Formula_t)) {
+	CtlpFormulaDecrementRefCount(formula->left);
+      }
+      if (formula->right != NIL(Ctlp_Formula_t)) {
+	CtlpFormulaDecrementRefCount(formula->right);
+      }
+    }
+    if (formula->states != NIL(mdd_t))
+      mdd_free(formula->states);
+    if (formula->underapprox != NIL(mdd_t))
+      mdd_free(formula->underapprox);
+    if (formula->overapprox != NIL(mdd_t))
+      mdd_free(formula->overapprox);
+    if (formula->Bottomstates != NIL(array_t))
+      mdd_array_free(formula->Bottomstates);
+    if (formula->Topstates != NIL(array_t))
+      mdd_array_free(formula->Topstates);
+    if (formula->matchfound_top != NIL(array_t))
+      array_free(formula->matchfound_top);
+    if (formula->matchelement_top != NIL(array_t))
+      array_free(formula->matchelement_top);
+    if (formula->matchfound_bot != NIL(array_t))
+      array_free(formula->matchfound_bot);
+    if (formula->matchelement_bot != NIL(array_t))
+      array_free(formula->matchelement_bot);
+    if (formula->leaves != NIL(array_t))
+      array_free(formula->leaves);
+    if (formula->dbgInfo.data != NIL(void)) {
+      (*formula->dbgInfo.freeFn)(formula);
+    }
+    FREE(formula);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Create a binary string of given value with size of interval ]
+
+  Description [The value is a binary string starting with 'b',
+  a hexadecimal string starting with 'x', or an
+  integer string. If Value is not fitted in the interval, 0 is return.
+  Otherwise 1 is returned. Result string is saved at given pointer.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+CtlpStringChangeValueStrToBinString(
+  char *value,
+  char *binValueStr,
+  int  interval)
+{
+  int i;
+  long int num, mask;
+  double maxNum;
+  char *ptr;
+
+  mask = 1;
+  maxNum = pow(2.0,(double)interval);
+  errno = 0;
+
+  if(value[0] == 'b'){
+    if ((int)strlen(value)-1 == interval){
+			for(i=1;i<=interval;i++){
+	if (value[i] == '0' || value[i] == '1'){
+	  binValueStr[i-1] =  value[i];
+	}else{
+	  return 0;
+	}
+      }
+      binValueStr[interval] = '\0';
+    }else{
+      return 0;
+    }
+  }else if (value[0] == 'x'){
+    for(i=1; i < (int)strlen(value); i++){
+      if (!isxdigit((int)value[i])){
+	return 0;
+      }
+    }
+    num = strtol(++value,&ptr,16);
+    if (errno) return 0;
+    if ( num >= maxNum) return 0;
+    for(i=0;i<interval;i++){
+      if(num & (mask<<i)) binValueStr[interval-i-1] = '1';
+      else binValueStr[interval-i-1] = '0';
+    }
+    binValueStr[interval] = '\0';
+  }else{
+    for(i=0;i<(int)strlen(value);i++){
+      if (!isdigit((int)value[i])){
+	return 0;
+      }
+    }
+    num = strtol(value,&ptr,0);
+    if (errno) return 0;
+    if ( num >= maxNum) return 0;
+    mask = 1;
+    for(i=0;i<interval;i++){
+      if(num & (mask<<i)) binValueStr[interval-i-1] = '1';
+      else binValueStr[interval-i-1] = '0';
+    }
+    binValueStr[interval] = '\0';
+  }
+
+  return(1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Change [] to <>]
+
+  Description []
+
+  SideEffects [The input string contains ...[num] and this function changes it
+  to ...<num>.]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+CtlpChangeBracket(
+  char *inStr)
+{
+  int i, j;
+  char *str;
+
+  j = 0;
+  for (i=0;i<(int)strlen(inStr)+1;i++){
+    if (inStr[i] != ' '){
+      inStr[i-j] = inStr[i];
+    }else{
+      j++;
+    }
+  }
+
+  if (changeBracket == 0)
+    return;
+
+  str = strchr(inStr,'[');
+  if (str == NULL) return;
+
+  *str = '<';
+  str = strchr(inStr,']');
+  *str = '>';
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Parse a given vector string.]
+
+  Description [Parse given vector string of the form of var<i:j> and
+  string var is returned. Other information such as i, j, interval between
+  i and j, and increment or decrement from i to j are saved.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+char *
+CtlpGetVectorInfoFromStr(
+   char *str,
+   int  *start,
+   int  *end,
+   int  *interval,
+   int  *inc)
+{
+  char *str1, *str2, *str3;
+  char *startStr, *endStr;
+  char *name, *ptr;
+
+  str1 = strchr(str,'[');
+  str2 = strchr(str,':');
+  str3 = strchr(str,']');
+  startStr = ALLOC(char, str2-str1);
+  endStr = ALLOC(char, str3-str2);
+  name = ALLOC(char, str1-str+1);
+
+  (void) strncpy(name, str, str1-str);
+  (void) strncpy(startStr, str1+1, str2-str1-1);
+  (void) strncpy(endStr, str2+1, str3-str2-1);
+
+  startStr[str2-str1-1] = '\0';
+  endStr[str3-str2-1] = '\0';
+  name[str1-str] = '\0';
+  *start = strtol(startStr,&ptr,0);
+  *end = strtol(endStr,&ptr,0);
+  if(*start > *end){
+      *inc = -1;
+      *interval = *start - *end + 1;
+  } else {
+      *inc = 1;
+      *interval = *end - *start + 1;
+  }
+  FREE(startStr);
+  FREE(endStr);
+  return name;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Insert macro formula into symbol table.]
+
+  Description [If the name is already in table return 0, otherwise insert the
+  formula into the table and return 1]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+CtlpFormulaAddToTable(
+   char *name,
+   Ctlp_Formula_t *formula,
+   st_table *macroTable)
+{
+   if(macroTable == NIL(st_table)){
+      macroTable = st_init_table(strcmp, st_strhash);
+   }
+   if(st_is_member(macroTable, name)){
+      return 0;
+   }
+   st_insert(macroTable, name, (char *)formula);
+   return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Get macro formula from symbol table]
+
+  Description [If macro string is not found in table, NULL pointer is returned]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlp_Formula_t *
+CtlpFormulaFindInTable(
+   char *name,
+   st_table *macroTable)
+{
+   Ctlp_Formula_t *formula;
+   if (st_lookup(macroTable, name, &formula)){
+      return (Ctlp_FormulaDup(formula));
+   }else{
+      return NIL(Ctlp_Formula_t);
+   }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the greatest lower bound of two classes]
+
+  Description [Returns the class of a formula that is the combination of a
+  formula of class1 and class2.  Does this by computing the glb, where mixed <
+  ECTL < quantifierFree, and mixed < ACTL < quantifierfree.]
+
+  SideEffects []
+
+  SeeAlso [Ctlp_CheckClassOfExistentialFormula]
+
+******************************************************************************/
+Ctlp_FormulaClass
+CtlpResolveClass(
+  Ctlp_FormulaClass class1,
+  Ctlp_FormulaClass class2)
+{
+  if ((class1 == Ctlp_Mixed_c) || (class2 == Ctlp_Mixed_c))
+    return Ctlp_Mixed_c;
+  if (class1 == Ctlp_QuantifierFree_c)
+    return class2;
+  if (class2 == Ctlp_QuantifierFree_c)
+    return class1;
+  if (class1 == class2)
+    return class1;
+
+  return Ctlp_Mixed_c;
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the class of a formula that is the negation of a formula
+  of class "class".]
+
+  Description [The negation of a mixed (quantifier free, ECTL, ACTL) formula is
+  mixed (quantifier free, ACTL, ECTL).]
+
+  SideEffects []
+
+  SeeAlso [Ctlp_CheckClassOfExistentialFormula]
+
+******************************************************************************/
+Ctlp_FormulaClass
+CtlpNegateFormulaClass(
+  Ctlp_FormulaClass class_
+)
+{
+  switch(class_){
+  case Ctlp_Mixed_c:
+    return Ctlp_Mixed_c;
+  case Ctlp_QuantifierFree_c:
+    return Ctlp_QuantifierFree_c;
+  case Ctlp_ECTL_c:
+    return Ctlp_ACTL_c;
+  case Ctlp_ACTL_c:
+    return Ctlp_ECTL_c;
+  default:
+    fprintf(vis_stderr, "**Ctlp Error: Unknown formula class\n");
+    assert(0);
+    return Ctlp_Mixed_c;
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Replaces the smallest important sub-fomula in a w-ACTL
+  formula by bottom.]
+
+  Description [Creates a witness formula for a given w-ACTL formula by
+  replacing the smallest inpurtant subformula with bottom.  This function is
+  used in the approach to vacuity detection of Beer et al. (CAV97).  Formulae
+  in w-ACTL are guaranteed to have a unique smallest important subformula,
+  which is defined as follow.  If the formula is simple, its operands are not
+  important.  (An exception is made for implications.  See
+  ReplaceSimpleFormula.)  Otherwise, the non-simple operand is the important
+  operand.  For (A p U q) or (E p U q), where p and q are both simple, p is the
+  important operand.  For unary formulae, the only child is the important
+  operand.  This function works also for ACTL formulae that are not in w-ACTL,
+  and for which smallest important subformulae are not unique.
+  The function picks up a smallest important subformula.]
+
+  SideEffects [none]
+
+  SeeAlso     [ReplaceSimpleFormula]
+
+******************************************************************************/
+Ctlp_Formula_t *
+Ctlp_FormulaCreateWitnessFormula(
+  Ctlp_Formula_t *formula)
+{
+  Ctlp_FormulaType formulaType;
+  Ctlp_Formula_t *rightFormula, *leftFormula;
+  Ctlp_Formula_t *newLeftFormula, *newRightFormula;
+
+  assert(formula != NIL(Ctlp_Formula_t));
+
+  if(formula == NIL(Ctlp_Formula_t))
+    return NIL(Ctlp_Formula_t);
+
+  formulaType = Ctlp_FormulaReadType(formula);
+  leftFormula = Ctlp_FormulaReadLeftChild(formula);
+  rightFormula = Ctlp_FormulaReadRightChild(formula);
+
+  if (Ctlp_FormulaTestIsQuantifierFree(formula)) {
+    return ReplaceSimpleFormula(formula);
+  }
+
+  switch (formulaType) {
+  case Ctlp_AX_c:
+  case Ctlp_EX_c:
+  case Ctlp_AG_c:
+  case Ctlp_EG_c:
+  case Ctlp_AF_c:
+  case Ctlp_EF_c:
+  case Ctlp_NOT_c:
+    newLeftFormula = Ctlp_FormulaCreateWitnessFormula(leftFormula);
+    newRightFormula = NIL(Ctlp_Formula_t);
+    break;
+  case Ctlp_AU_c:
+  case Ctlp_EU_c:
+    /* If both or neither operands are simple, we choose the left one
+       as important.  Deal with special case of converted AG p (E true U p). */
+    if ((formulaType == Ctlp_EU_c &&
+	 Ctlp_FormulaReadType(leftFormula) == Ctlp_TRUE_c) ||
+	(Ctlp_FormulaTestIsQuantifierFree(leftFormula) &&
+	 !Ctlp_FormulaTestIsQuantifierFree(rightFormula))) {
+      newLeftFormula = Ctlp_FormulaDup(leftFormula);
+      newRightFormula = Ctlp_FormulaCreateWitnessFormula(rightFormula);
+    } else {
+      newLeftFormula = Ctlp_FormulaCreateWitnessFormula(leftFormula);
+      newRightFormula = Ctlp_FormulaDup(rightFormula);
+    }
+    break;
+  case Ctlp_OR_c:
+  case Ctlp_AND_c:
+  case Ctlp_THEN_c:
+    /* Here we know one is not simple */
+    if (Ctlp_FormulaTestIsQuantifierFree(leftFormula)) {
+      newLeftFormula = Ctlp_FormulaDup(leftFormula);
+      newRightFormula = Ctlp_FormulaCreateWitnessFormula(rightFormula);
+    } else {
+      newLeftFormula = Ctlp_FormulaCreateWitnessFormula(leftFormula);
+      newRightFormula = Ctlp_FormulaDup(rightFormula);
+    }
+    break;
+  case Ctlp_XOR_c:
+  case Ctlp_EQ_c:
+    newLeftFormula = Ctlp_FormulaDup(leftFormula);
+    newRightFormula = Ctlp_FormulaDup(rightFormula);
+    break;
+  default:
+    newLeftFormula = NIL(Ctlp_Formula_t);
+    newRightFormula = NIL(Ctlp_Formula_t);
+    fprintf(vis_stderr, "**Ctlp Error: Unexpected operator detected.\n");
+    assert(0);
+    break;
+  }
+  return Ctlp_FormulaCreate(formulaType,newLeftFormula,newRightFormula);
+
+} /* Ctlp_FormulaCreateWitnessFormula */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a CTL formula with just the type set.]
+
+  Description [Calls Ctlp_FormulaCreate with type, and all other fields NULL.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlp_FormulaCreate]
+
+******************************************************************************/
+static Ctlp_Formula_t *
+FormulaCreateWithType(
+  Ctlp_FormulaType  type)
+{
+  return (Ctlp_FormulaCreate(type, NIL(Ctlp_Formula_t), NIL(Ctlp_Formula_t)));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [The comparison function for the formula unique table.]
+
+  Description [The function takes as parameters two CTL formulae. It compares
+  the formula type, the left child and the right child, and returns 0 if they
+  match. Otherwise, it returns -1.]
+
+  SideEffects []
+
+  SeeAlso     [FormulaHash]
+
+******************************************************************************/
+static int
+FormulaCompare(
+  const char *key1,
+  const char *key2)
+{
+  Ctlp_Formula_t *formula1 = (Ctlp_Formula_t *) key1;
+  Ctlp_Formula_t *formula2 = (Ctlp_Formula_t *) key2;
+
+  assert(key1 != NIL(char));
+  assert(key2 != NIL(char));
+
+
+  if(formula1->type != formula2->type) {
+    return -1;
+  }
+  if(formula1->type == Ctlp_ID_c) {
+    if(strcmp((char *) (formula1->left), (char *) (formula2->left)) ||
+       strcmp((char *) (formula1->right), (char *) (formula2->right))) {
+      return -1;
+    } else
+      return 0;
+  } else {
+    if(formula1->left != formula2->left)
+      return -1;
+    if(formula1->right != formula2->right)
+      return -1;
+    if (formula1->type == Ctlp_Cmp_c &&
+	formula1->compareValue != formula2->compareValue) {
+      return -1;
+    }
+    return 0;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [The hash function for the formula unique table.]
+
+  Description [The function takes as parameter a CTL formula. If the formula
+  type is Ctlp_ID_c, st_strhash is used with a concatenation of left and
+  right children as the key string. Otherwise, something very similar to
+  st_ptrhash is done.]
+
+  SideEffects []
+
+  SeeAlso     [FormulaCompare]
+
+******************************************************************************/
+static int
+FormulaHash(
+  char *key,
+  int modulus)
+{
+  char *hashString;
+  int hashValue;
+  Ctlp_Formula_t *formula = (Ctlp_Formula_t *) key;
+
+  if(formula->type==Ctlp_ID_c) {
+    hashString = util_strcat3((char *) (formula->left), (char *)
+			      (formula->right), "");
+    hashValue = st_strhash(hashString, modulus);
+    FREE(hashString);
+    return hashValue;
+  }
+  return (int) ((((unsigned long) formula->left >>2) +
+		 ((unsigned long) formula->right >>2)) % modulus);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Hashes the formula into the unique table.]
+
+  Description [The function takes a formula and hashes it and all its
+  subformulae into a unique table. It returns the unique formula identical to
+  the formula being hashed. The formula returned will have maximum sharing
+  with the formulae that are already present in uniqueTable. It returns
+  NIL(Ctlp_Formula_t) if the formula is NIL(Ctlp_Formula_t).]
+
+  SideEffects [If a copy of some subformula of formula is present in
+  uniqueTable then the copy is substituted for it and the reference count of
+  the subform
+  ula is decremented.]
+
+  SeeAlso     [FormulaCompare]
+
+******************************************************************************/
+static Ctlp_Formula_t *
+FormulaHashIntoUniqueTable(
+  Ctlp_Formula_t *formula,
+  st_table *uniqueTable)
+{
+  Ctlp_Formula_t *uniqueFormula, *uniqueLeft, *uniqueRight;
+
+  if(formula == NIL(Ctlp_Formula_t))
+    return NIL(Ctlp_Formula_t);
+  if(st_lookup(uniqueTable, formula, &uniqueFormula)) {
+    return uniqueFormula;
+  }
+  else {
+    if(formula->type == Ctlp_ID_c) {
+      st_insert(uniqueTable, formula, formula);
+      return formula;
+    }
+    else {
+      uniqueLeft = FormulaHashIntoUniqueTable(formula->left, uniqueTable);
+      if(uniqueLeft != NIL(Ctlp_Formula_t))
+	if(uniqueLeft != formula->left) {
+	  CtlpFormulaDecrementRefCount(formula->left);
+	  formula->left = uniqueLeft;
+	  CtlpFormulaIncrementRefCount(formula->left);
+	}
+      uniqueRight = FormulaHashIntoUniqueTable(formula->right, uniqueTable);
+      if(uniqueRight != NIL(Ctlp_Formula_t))
+	if(uniqueRight != formula->right) {
+	  CtlpFormulaDecrementRefCount(formula->right);
+	  formula->right = uniqueRight;
+	  CtlpFormulaIncrementRefCount(formula->right);
+	}
+      if(st_lookup(uniqueTable, formula, &uniqueFormula)) {
+	return uniqueFormula;
+      }
+      else {
+	st_insert(uniqueTable, formula, formula);
+	return formula;
+      }
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Converts the formula tree to a DAG.]
+
+  Description [The function recursively builds an existential DAG for the
+  formula. If a particular sub-formula has been encountered before, the
+  converted existential sub-formula is pointed to by the field states and it
+  is returned without creating a new formula.]
+
+  SideEffects [We abuse states to store which converted formula an original
+  formula points to.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static Ctlp_Formula_t *
+FormulaConvertToExistentialDAG(
+  Ctlp_Formula_t *formula)
+{
+
+  Ctlp_Formula_t *new_;
+  char *variableNameCopy, *valueNameCopy;
+
+  if(formula==NIL(Ctlp_Formula_t))
+    return NIL(Ctlp_Formula_t);
+
+  if(formula->states!=NIL(mdd_t)) {
+    Ctlp_Formula_t *temp = (Ctlp_Formula_t *) (formula->states);
+
+    ++(temp->refCount);
+    return temp;
+  }
+
+  /*
+   * Recursively convert each subformula.
+   */
+
+  switch(formula->type) {
+    case Ctlp_EF_c:
+      /* EFf --> (E true U f)  */
+      new_ = FormulaCreateWithType(Ctlp_EU_c);
+      new_->left  = FormulaCreateWithType(Ctlp_TRUE_c);
+      new_->right = FormulaConvertToExistentialDAG(formula->left);
+      new_->dbgInfo.convertedFlag = TRUE;
+      break;
+
+    case Ctlp_AX_c:
+      /* AXf --> !(EX(!f)) */
+      new_ = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left = FormulaCreateWithType(Ctlp_EX_c);
+      new_->left->left = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left->left->left = FormulaConvertToExistentialDAG(formula->left);
+      new_->dbgInfo.convertedFlag = TRUE;
+      break;
+
+    case Ctlp_AG_c:
+      /* AGf --> ![(E true U !f)] */
+      new_ = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left = FormulaCreateWithType(Ctlp_EU_c);
+      new_->left->left = FormulaCreateWithType(Ctlp_TRUE_c);
+      new_->left->right = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left->right->left = FormulaConvertToExistentialDAG(formula->left);
+      new_->dbgInfo.convertedFlag = TRUE;
+      break;
+
+    case Ctlp_AF_c:
+      /* AFf --> ![EG(!f)] */
+      new_ = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left = FormulaCreateWithType(Ctlp_EG_c);
+      new_->left->left = FormulaCreateWithType(Ctlp_NOT_c);
+      new_->left->left->left = FormulaConvertToExistentialDAG(formula->left);
+      new_->dbgInfo.convertedFlag = TRUE;
+      break;
+
+    case Ctlp_AU_c:
+      /* A[fUg] --> !((E[!g U (!f*!g)]) + (EG!g)) */
+
+      new_ = FormulaCreateWithType(Ctlp_NOT_c); /* top */
+      new_->left = FormulaCreateWithType(Ctlp_OR_c); /* ((E[!g U (!f*!g)]) + (EG!g)) */
+
+      new_->left->right = FormulaCreateWithType(Ctlp_EG_c); /* EG !g */
+      new_->left->right->left = FormulaCreateWithType(Ctlp_NOT_c); /* !g */
+      new_->left->right->left->left = FormulaConvertToExistentialDAG(formula->right); /* g */
+
+      new_->left->left = FormulaCreateWithType(Ctlp_EU_c); /* E[!g U (!f*!g)] */
+      new_->left->left->left = FormulaCreateWithType(Ctlp_NOT_c); /* !g */
+      new_->left->left->left->left = FormulaConvertToExistentialDAG(formula->right); /* g */
+      new_->left->left->right = FormulaCreateWithType(Ctlp_AND_c); /* !f*!g */
+      new_->left->left->right->left = FormulaCreateWithType(Ctlp_NOT_c); /* !f */
+      new_->left->left->right->left->left = FormulaConvertToExistentialDAG(formula->left); /* f */
+      new_->left->left->right->right = FormulaCreateWithType(Ctlp_NOT_c); /* !g */
+      new_->left->left->right->right->left = FormulaConvertToExistentialDAG(formula->right); /* g */
+      new_->dbgInfo.convertedFlag = TRUE;
+      break;
+
+    case Ctlp_ID_c:
+      /* Make a copy of the name, and create a new formula. */
+      variableNameCopy = util_strsav((char *)(formula->left));
+      valueNameCopy = util_strsav((char *)(formula->right));
+      new_ = Ctlp_FormulaCreate(Ctlp_ID_c, variableNameCopy, valueNameCopy);
+      break;
+
+    case Ctlp_THEN_c:
+    case Ctlp_EX_c:
+    case Ctlp_EG_c:
+    case Ctlp_EU_c:
+    case Ctlp_OR_c:
+    case Ctlp_AND_c:
+    case Ctlp_NOT_c:
+    case Ctlp_XOR_c:
+    case Ctlp_EQ_c:
+    case Ctlp_TRUE_c:
+    case Ctlp_FALSE_c:
+      /* These are already in the correct form.  Just convert subformulas. */
+      new_ = FormulaCreateWithType(formula->type);
+      new_->left = FormulaConvertToExistentialDAG(formula->left);
+      new_->right = FormulaConvertToExistentialDAG(formula->right);
+      break;
+
+    default:
+      fail("Unexpected type");
+  }
+
+  formula->states = (mdd_t *) new_; /*using states as pointer to the converted
+				     formula */
+  new_->dbgInfo.originalFormula = formula;
+  return new_;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts an existential formula to forward form.]
+
+  Description [Converts an existential formula to forward form. To
+  convert current formula, it always refer to its parent node and left
+  child of parent node. Current formula is right child of parent node.
+  Parent node should be always Ctlp_AND_c and left child of parent node
+  is already converted.  States is used to store a parent pointer
+  throughout the procedure.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+FormulaConvertToForward(Ctlp_Formula_t *formula, int compareValue)
+{
+  Ctlp_Formula_t *parent, *save;
+  Ctlp_Formula_t *p, *q, *r, *f, *g;
+  int		 p_qf, q_qf;
+  int		 same_order;
+
+  if (formula == NIL(Ctlp_Formula_t))
+    return;
+
+  parent = (Ctlp_Formula_t *)formula->states;
+  r = parent->left; /* already converted */
+
+  /*
+   * Recursively convert each subformula.
+   */
+
+  switch(formula->type) {
+    case Ctlp_EX_c:
+      /*
+      ** p ^ EXf -> Img(p) ^ f , Img(p) = EY(p)
+      **
+      **   *           *
+      **  / \         / \
+      ** p  EX  =>  EY   f
+      **    |       |
+      **    f       p
+      */
+
+      formula->type = Ctlp_EY_c;
+      save = formula->left;
+      formula->left = parent->left;
+      parent->left = formula;
+      parent->right = save;
+
+      parent->top = 1;
+      parent->compareValue = compareValue;
+      parent->right->states = (mdd_t *)parent;
+
+      FormulaConvertToForward(parent->right, compareValue);
+      break;
+
+    case Ctlp_EF_c:
+      /*
+      ** EFf --> (E true U f)
+      ** p ^ (E true U f) --> FwdU(p, true) ^ f
+      **
+      **   *             *
+      **  / \          /   \
+      ** p  EF  =>  FwdU    f
+      **    |        / \
+      **    f       p  true
+      */
+
+      formula->type = Ctlp_FwdU_c;
+      save = formula->left;
+      formula->right = FormulaCreateWithType(Ctlp_TRUE_c);
+      formula->left = parent->left;
+      parent->left = formula;
+      parent->right = save;
+
+      parent->top = 1;
+      parent->compareValue = compareValue;
+      parent->right->states = (mdd_t *)parent;
+
+
+      FormulaConvertToForward(parent->right, compareValue);
+      break;
+
+    case Ctlp_EU_c:
+      /*
+      ** p ^ (E q U f) --> FwdU(p, q) ^ f
+      **
+      **   *             *
+      **  / \          /   \
+      ** p  EU  =>   FwdU   f
+      **    /\        / \
+      **   q  f      p   q
+      */
+
+      formula->type = Ctlp_FwdU_c;
+      save = formula->right;
+      formula->right = formula->left;
+      formula->left = parent->left;
+      parent->left = formula;
+      parent->right = save;
+
+      parent->top = 1;
+      parent->compareValue = compareValue;
+      parent->right->states = (mdd_t *)parent;
+
+      FormulaConvertToForward(parent->right, compareValue);
+      break;
+
+    case Ctlp_EG_c:
+      /*
+      ** p ^ EGq --> FwdG(p, q)
+      **
+      **   *        FwdG
+      **  / \        / \
+      ** p  EG  =>  p   q
+      **    /
+      **   q
+      */
+
+      parent->type = Ctlp_FwdG_c;
+      parent->right = formula->left;
+
+      formula->left = NIL(Ctlp_Formula_t);
+      formula->states = NIL(mdd_t);
+      Ctlp_FormulaFree(formula);
+
+      parent->top = 1;
+      parent->compareValue = compareValue;
+      break;
+
+    case Ctlp_NOT_c:
+      if (formula->left->type == Ctlp_NOT_c) {
+	/*
+	**   *             *
+	**  / \      =>   / \
+	** r  NOT        r   f
+	**     /
+	**   NOT
+	**   /
+	**  f
+	*/
+
+	parent->right = formula->left->left;
+	formula->left->left = NIL(Ctlp_Formula_t);
+	formula->left->states = NIL(mdd_t);
+	Ctlp_FormulaFree(formula->left);
+	formula->left = NIL(Ctlp_Formula_t);
+	formula->states = NIL(mdd_t);
+	Ctlp_FormulaFree(formula);
+
+	parent->top = 1;
+	parent->compareValue = compareValue;
+	parent->right->states = (mdd_t *)parent;
+
+	FormulaConvertToForward(parent->right, compareValue);
+      } else if (formula->left->type == Ctlp_THEN_c) {
+	/*
+	**   *
+	**  / \
+	** r  NOT
+	**    /
+	**  THEN
+	**   / \
+	**  p   q
+	*/
+
+	p = formula->left->left;
+	q = formula->left->right;
+	p_qf = Ctlp_FormulaTestIsQuantifierFree(p);
+	q_qf = Ctlp_FormulaTestIsQuantifierFree(q);
+
+	if (p_qf && q_qf)
+	  break;
+	else if (p_qf ||
+		 (p_qf == 0 && q_qf == 0 && !FormulaIsConvertible(q))) {
+	  /*
+	  ** !(p -> q) = p * !q
+	  **
+	  **   *     =>     *     =>      *
+	  **  / \          / \          /   \
+	  ** r  NOT       r   *        *    NOT
+	  **    /            / \      / \   /
+	  **  THEN          p  NOT   r   p q
+	  **   / \              /
+	  **  p   q            q
+	  */
+
+	  parent->left = formula->left;
+	  parent->left->type = Ctlp_AND_c;
+	  parent->left->left = r;
+	  parent->left->right = p;
+	  parent->right = formula;
+	  parent->right->left = q;
+
+	  parent->top = 1;
+	  parent->compareValue = compareValue;
+	  parent->right->states = (mdd_t *)parent;
+
+	  FormulaConvertToForward(parent->right, compareValue);
+	} else {
+	  /*
+	  ** !(p -> q) = p * !q
+	  **
+	  **   *     =>     *     =>      *
+	  **  / \          / \          /   \
+	  ** r  NOT       r   *        *     p
+	  **    /            / \      / \
+	  **  THEN          p  NOT   r  NOT
+	  **   / \              /       /
+	  **  p   q            q       q
+	  */
+
+	  parent->left = formula->left;
+	  parent->left->type = Ctlp_AND_c;
+	  parent->left->left = r;
+	  parent->left->right = formula;
+	  parent->left->right->left = q;
+	  parent->left->right->right = NIL(Ctlp_Formula_t);
+	  parent->right = p;
+
+	  parent->top = 1;
+	  parent->compareValue = compareValue;
+	  p->states = (mdd_t *)parent;
+
+	  FormulaConvertToForward(p, compareValue);
+	}
+      } else if (formula->left->type == Ctlp_OR_c) {
+	/*
+	** !(p + q) = !p * !q
+	**
+	**   *     =>     *     =>        *
+	**  / \          / \            /   \
+	** r  NOT       r   *          *    NOT
+	**    /            / \        / \    /
+	**    OR         NOT NOT     r  NOT g=q(p)
+	**   / \          /   /         /
+	**  p   q        p   q         f=p(q)
+	*/
+
+	p = formula->left->left;
+	q = formula->left->right;
+	p_qf = Ctlp_FormulaTestIsQuantifierFree(p);
+	q_qf = Ctlp_FormulaTestIsQuantifierFree(q);
+
+	if (p_qf && q_qf)
+	  break;
+	else if (p_qf) {
+	  f = p;
+	  g = q;
+	} else if (q_qf) {
+	  f = q;
+	  g = p;
+	} else  {
+	  if (!FormulaIsConvertible(q)) {
+	    f = p;
+	    g = q;
+	  } else {
+	    f = q;
+	    g = p;
+	  }
+	}
+
+	parent->left = formula->left;
+	parent->left->type = Ctlp_AND_c;
+	parent->left->left = r;
+	parent->left->right = formula;
+	parent->left->right->left = f;
+	parent->left->right->right = NIL(Ctlp_Formula_t);
+	parent->right = FormulaCreateWithType(Ctlp_NOT_c);
+	parent->right->left = g;
+
+	parent->top = 1;
+	parent->compareValue = compareValue;
+	parent->right->states = (mdd_t *)parent;
+
+	FormulaConvertToForward(parent->right, compareValue);
+      } else if (formula->left->type == Ctlp_AND_c) {
+	/*
+	** !(p * q) = !p + !q
+	**
+	**   *          *(+)           *(+)
+	**  / \         / \           /    \
+	** r  NOT  =>  r  OR    =>   *      *
+	**    /           / \       / \    / \
+	**   AND        NOT NOT    r  NOT r  NOT
+	**   / \        /   /         /      /
+	**  p   q      p   q         p      q
+	*/
+
+	p = formula->left->left;
+	q = formula->left->right;
+
+	if (Ctlp_FormulaTestIsQuantifierFree(p) &&
+	    Ctlp_FormulaTestIsQuantifierFree(q)) {
+	  break;
+	}
+
+	if (compareValue)
+	  parent->type = Ctlp_OR_c;
+	parent->left = formula->left;
+	parent->left->left = r;
+	parent->left->right = formula;
+	parent->left->right->left = p;
+
+	parent->right = FormulaCreateWithType(Ctlp_AND_c);
+	parent->right->left = Ctlp_FormulaDup(r);
+	parent->right->right = FormulaCreateWithType(Ctlp_NOT_c);
+	parent->right->right->left = q;
+
+	parent->top = 0;
+	parent->left->top = 1;
+	parent->right->top = 1;
+	parent->left->compareValue = compareValue;
+	parent->right->compareValue = compareValue;
+	parent->left->right->states = (mdd_t *)parent->left;
+	parent->right->right->states = (mdd_t *)parent->right;
+
+	FormulaConvertToForward(parent->left->right, compareValue);
+	FormulaConvertToForward(parent->right->right, compareValue);
+      } else if (formula->left->type == Ctlp_XOR_c) {
+	/*
+	** !(p ^ q) = p * q + !p * !q
+	**
+	**   *              *(+)                   *(+)
+	**  / \            /     \               /      \
+	** |   |   =>     *       *      =>    *          *
+	** |   |         / \     / \          / \      /     \
+	** r  NOT       r   *   r   *        *   g    *      NOT
+	**    /            / \     / \      / \      / \     /
+	**   XOR          p   q  NOT NOT   r   f    r  NOT  g=q(p)
+	**   / \                 /   /                 /
+	**  p   q               p   q                 f=p(q)
+	*/
+
+	p = formula->left->left;
+	q = formula->left->right;
+	p_qf = Ctlp_FormulaTestIsQuantifierFree(p);
+	q_qf = Ctlp_FormulaTestIsQuantifierFree(q);
+
+	same_order = 1;
+	if (p_qf && q_qf)
+	  break;
+	else if (p_qf) {
+	  f = p;
+	  g = q;
+	} else if (q_qf) {
+	  f = q;
+	  g = p;
+	} else {
+	  if (FormulaIsConvertible(p) && !FormulaIsConvertible(q)) {
+	    /*
+	    ** !(p ^ q) = q * p + !p * !q
+	    **
+	    **   *              *(+)                   *(+)
+	    **  / \            /     \               /      \
+	    ** |   |   =>     *       *      =>    *          *
+	    ** |   |         / \     / \          / \      /     \
+	    ** r  NOT       r   *   r   *        *   p    *      NOT
+	    **    /            / \     / \      / \      / \     /
+	    **   XOR          p   q  NOT NOT   r   q    r  NOT  q
+	    **   / \                 /   /                 /
+	    **  p   q               p   q                 p
+	    */
+
+	    f = q;
+	    g = p;
+	    same_order = 0;
+	  } else if (!FormulaIsConvertible(p) && FormulaIsConvertible(q)) {
+	    /*
+	    ** !(p ^ q) = p * q + !q * !p
+	    **
+	    **   *              *(+)                   *(+)
+	    **  / \            /     \               /      \
+	    ** |   |   =>     *       *      =>    *          *
+	    ** |   |         / \     / \          / \      /     \
+	    ** r  NOT       r   *   r   *        *   q    *      NOT
+	    **    /            / \     / \      / \      / \     /
+	    **   XOR          p   q  NOT NOT   r   p    r  NOT  p
+	    **   / \                 /   /                 /
+	    **  p   q               p   q                 q
+	    */
+
+	    f = p;
+	    g = q;
+	    same_order = 0;
+	  } else {
+	    f = p;
+	    g = q;
+	  }
+	}
+
+	if (compareValue)
+	  parent->type = Ctlp_OR_c;
+	parent->left = formula;
+	parent->left->type = Ctlp_AND_c;
+	parent->left->left->type = Ctlp_AND_c;
+	parent->left->left->left = r;
+	parent->left->left->right = f;
+	parent->left->right = g;
+
+	parent->right = FormulaCreateWithType(Ctlp_AND_c);
+	parent->right->left = FormulaCreateWithType(Ctlp_AND_c);
+	parent->right->left->left = Ctlp_FormulaDup(r);
+	parent->right->left->right = FormulaCreateWithType(Ctlp_NOT_c);
+	if (same_order)
+	  parent->right->left->right->left = Ctlp_FormulaDup(f);
+	else
+	  parent->right->left->right->left = Ctlp_FormulaDup(g);
+	parent->right->right = FormulaCreateWithType(Ctlp_NOT_c);
+	if (same_order)
+	  parent->right->right->left = Ctlp_FormulaDup(g);
+	else
+	  parent->right->right->left = Ctlp_FormulaDup(f);
+
+	parent->top = 0;
+	parent->left->top = 1;
+	parent->right->top = 1;
+	parent->left->compareValue = compareValue;
+	parent->right->compareValue = compareValue;
+	parent->left->right->states = (mdd_t *)parent->left;
+	parent->right->right->states = (mdd_t *)parent->right;
+
+	FormulaConvertToForward(parent->left->right, compareValue);
+	FormulaConvertToForward(parent->right->right, compareValue);
+      } else if (formula->left->type == Ctlp_EQ_c) {
+	/*
+	** !(EQ(p, q) = XOR(p, q)
+	**
+	**   *              *(+)                   *(+)
+	**  / \            /     \                /     \
+	** |   |   =>     *       *      =>     *         *
+	** |   |         / \     / \          /   \     /   \
+	** r  NOT       r   *   r   *        *     g   *    NOT
+	**    /            / \     / \      / \       / \   /
+	**   EQ           p  NOT NOT  q    r  NOT    r   f g=q(p)
+	**   / \             /   /            /
+	**  p   q           q   p            f=p(q)
+	*/
+
+	p = formula->left->left;
+	q = formula->left->right;
+	p_qf = Ctlp_FormulaTestIsQuantifierFree(p);
+	q_qf = Ctlp_FormulaTestIsQuantifierFree(q);
+
+	if (p_qf && q_qf)
+	  break;
+	else if (p_qf) {
+	  f = p;
+	  g = q;
+	} else if (q_qf) {
+	  f = q;
+	  g = p;
+	} else {
+	  if (FormulaIsConvertible(p) && FormulaIsConvertible(q)) {
+	    /*
+	    ** !(EQ(p, q) = XOR(p, q)
+	    **
+	    **   *              *(+)                   *(+)
+	    **  / \            /     \                /     \
+	    ** |   |   =>     *       *      =>     *         *
+	    ** |   |         / \     / \          /   \     /   \
+	    ** r  NOT       r   *   r   *        *     p   *     q
+	    **    /            / \     / \      / \       / \
+	    **   EQ           p  NOT NOT  q    r  NOT    r  NOT
+	    **   / \             /   /            /         /
+	    **  p   q           q   p            q         p
+	    */
+
+	    if (compareValue)
+	      parent->type = Ctlp_OR_c;
+	    parent->left = parent->right;
+	    parent->left->type = Ctlp_AND_c;
+	    parent->left->left->type = Ctlp_AND_c;
+	    parent->left->left->left = r;
+	    parent->left->left->right = FormulaCreateWithType(Ctlp_NOT_c);
+	    parent->left->left->right->left = q;
+	    parent->left->right = p;
+
+	    parent->right = FormulaCreateWithType(Ctlp_AND_c);
+	    parent->right->left = FormulaCreateWithType(Ctlp_AND_c);
+	    parent->right->left->left = Ctlp_FormulaDup(r);
+	    parent->right->left->right = FormulaCreateWithType(Ctlp_NOT_c);
+	    parent->right->left->right->left = Ctlp_FormulaDup(p);
+	    parent->right->right = Ctlp_FormulaDup(q);
+
+	    parent->top = 0;
+	    parent->left->top = 1;
+	    parent->right->top = 1;
+	    parent->left->compareValue = compareValue;
+	    parent->right->compareValue = compareValue;
+	    parent->left->right->states = (mdd_t *)parent->left;
+	    parent->right->right->states = (mdd_t *)parent->right;
+
+	    FormulaConvertToForward(parent->left->right, compareValue);
+	    FormulaConvertToForward(parent->right->right, compareValue);
+	    break;
+	  } else if (!FormulaIsConvertible(p) && !FormulaIsConvertible(q)) {
+	    /*
+	    ** !(EQ(p, q) = XOR(p, q)
+	    **
+	    **   *              *(+)                   *(+)
+	    **  / \            /     \                /     \
+	    ** |   |   =>     *       *      =>     *         *
+	    ** |   |         / \     / \          /   \     /   \
+	    ** r  NOT       r   *   r   *        *    NOT  *    NOT
+	    **    /            / \     / \      / \   /   / \   /
+	    **   EQ           p  NOT NOT  q    r   p q   r   q p
+	    **   / \             /   /
+	    **  p   q           q   p
+	    */
+
+	    if (compareValue)
+	      parent->type = Ctlp_OR_c;
+	    parent->left = parent->right;
+	    parent->left->type = Ctlp_AND_c;
+	    parent->left->left->type = Ctlp_AND_c;
+	    parent->left->left->left = r;
+	    parent->left->left->right = p;
+	    parent->left->right = FormulaCreateWithType(Ctlp_NOT_c);
+	    parent->left->right->left = q;
+
+	    parent->right = FormulaCreateWithType(Ctlp_AND_c);
+	    parent->right->left = FormulaCreateWithType(Ctlp_AND_c);
+	    parent->right->left->left = Ctlp_FormulaDup(r);
+	    parent->right->left->right = Ctlp_FormulaDup(q);
+	    parent->right->right = FormulaCreateWithType(Ctlp_NOT_c);
+	    parent->right->right->left = Ctlp_FormulaDup(p);
+
+	    parent->top = 0;
+	    parent->left->top = 1;
+	    parent->right->top = 1;
+	    parent->left->compareValue = compareValue;
+	    parent->right->compareValue = compareValue;
+	    parent->left->right->states = (mdd_t *)parent->left;
+	    parent->right->right->states = (mdd_t *)parent->right;
+
+	    FormulaConvertToForward(parent->left->right, compareValue);
+	    FormulaConvertToForward(parent->right->right, compareValue);
+	    break;
+	  } else {
+	    f = p;
+	    g = q;
+	  }
+	}
+
+	if (compareValue)
+	  parent->type = Ctlp_OR_c;
+	parent->left = parent->right;
+	parent->left->type = Ctlp_AND_c;
+	parent->left->left->type = Ctlp_AND_c;
+	parent->left->left->left = r;
+	parent->left->left->right = FormulaCreateWithType(Ctlp_NOT_c);
+	parent->left->left->right->left = f;
+	parent->left->right = g;
+
+	parent->right = FormulaCreateWithType(Ctlp_AND_c);
+	parent->right->left = FormulaCreateWithType(Ctlp_AND_c);
+	parent->right->left->left = Ctlp_FormulaDup(r);
+	parent->right->left->right = Ctlp_FormulaDup(f);
+	parent->right->right = FormulaCreateWithType(Ctlp_NOT_c);
+	parent->right->right->left = Ctlp_FormulaDup(g);
+
+	parent->top = 0;
+	parent->left->top = 1;
+	parent->right->top = 1;
+	parent->left->compareValue = compareValue;
+	parent->right->compareValue = compareValue;
+	parent->left->right->states = (mdd_t *)parent->left;
+	parent->right->right->states = (mdd_t *)parent->right;
+
+	FormulaConvertToForward(parent->left->right, compareValue);
+	FormulaConvertToForward(parent->right->right, compareValue);
+      }
+      break;
+
+    case Ctlp_THEN_c:
+      /*
+      ** (p -> q) = !p + q
+      **
+      **   *              *(+)
+      **  / \            /    \
+      ** r THEN  =>     *      *
+      **    / \        / \    / \
+      **   p   q      r  NOT r   q
+      **                 /
+      **                p
+      */
+
+      p = formula->left;
+      q = formula->right;
+
+      if (Ctlp_FormulaTestIsQuantifierFree(p) &&
+	  Ctlp_FormulaTestIsQuantifierFree(q)) {
+	break;
+      }
+
+      if (compareValue)
+	parent->type = Ctlp_OR_c;
+      parent->left = formula;
+      parent->left->type = Ctlp_AND_c;
+      parent->left->left = r;
+      parent->left->right = FormulaCreateWithType(Ctlp_NOT_c);
+      parent->left->right->left = p;
+
+      parent->right = FormulaCreateWithType(Ctlp_AND_c);
+      parent->right->left = Ctlp_FormulaDup(r);
+      parent->right->right = q;
+
+      parent->top = 0;
+      parent->left->top = 1;
+      parent->right->top = 1;
+      parent->left->compareValue = compareValue;
+      parent->right->compareValue = compareValue;
+      parent->left->right->states = (mdd_t *)parent->left;
+      parent->right->right->states = (mdd_t *)parent->right;
+
+      FormulaConvertToForward(parent->left->right, compareValue);
+      FormulaConvertToForward(parent->right->right, compareValue);
+      break;
+
+    case Ctlp_OR_c:
+      /*
+      **   *              *(+)
+      **  / \            /    \
+      ** r  OR   =>     *      *
+      **    / \        / \    / \
+      **   p   q      r   p  r   q
+      */
+
+      p = formula->left;
+      q = formula->right;
+
+      if (Ctlp_FormulaTestIsQuantifierFree(p) &&
+	  Ctlp_FormulaTestIsQuantifierFree(q)) {
+	break;
+      }
+
+      if (compareValue)
+	parent->type = Ctlp_OR_c;
+      parent->left = formula;
+      parent->left->type = Ctlp_AND_c;
+      parent->left->left = r;
+      parent->left->right = p;
+
+      parent->right = FormulaCreateWithType(Ctlp_AND_c);
+      parent->right->left = Ctlp_FormulaDup(r);
+      parent->right->right = q;
+
+      parent->top = 0;
+      parent->left->top = 1;
+      parent->right->top = 1;
+      parent->left->compareValue = compareValue;
+      parent->right->compareValue = compareValue;
+      parent->left->right->states = (mdd_t *)parent->left;
+      parent->right->right->states = (mdd_t *)parent->right;
+
+      FormulaConvertToForward(parent->left->right, compareValue);
+      FormulaConvertToForward(parent->right->right, compareValue);
+      break;
+
+    case Ctlp_AND_c:
+      /*
+      **   *     =>     *
+      **  / \          / \
+      ** r  AND      AND  g=q(p)
+      **    / \      / \
+      **   p   q    r   f=p(q)
+      */
+
+      p = formula->left;
+      q = formula->right;
+      p_qf = Ctlp_FormulaTestIsQuantifierFree(p);
+      q_qf = Ctlp_FormulaTestIsQuantifierFree(q);
+
+      if (p_qf && q_qf)
+	break;
+      else if (q_qf) {
+	f = q;
+	g = p;
+      } else {
+	f = p;
+	g = q;
+      }
+
+      parent->left = parent->right;
+      parent->left->left = r;
+      parent->left->right = f;
+      parent->right = g;
+
+      parent->top = 1;
+      parent->compareValue = compareValue;
+      g->states = (mdd_t *)parent;
+
+      FormulaConvertToForward(g, compareValue);
+      break;
+
+    case Ctlp_XOR_c:
+      /*
+      **   *             *(+)                  *(+)
+      **  / \           /    \                /     \
+      ** |   |   =>    *      *     =>      *         *
+      ** |   |        / \    / \          /   \      / \
+      ** r  XOR      r   *  r   *        *    NOT   *   g=q(p)
+      **    / \         / \    / \      / \   /    / \
+      **   p   q       q  NOT NOT p    r   f g    r  NOT
+      **                  /   /                      /
+      **                 p   q                      f=p(q)
+      */
+
+      p = formula->left;
+      q = formula->right;
+      p_qf = Ctlp_FormulaTestIsQuantifierFree(p);
+      q_qf = Ctlp_FormulaTestIsQuantifierFree(q);
+
+      if (p_qf && q_qf)
+	break;
+      else if (p_qf) {
+	f = p;
+	g = q;
+      } else if (q_qf) {
+	f = q;
+	g = p;
+      } else {
+	if (FormulaIsConvertible(p) && FormulaIsConvertible(q)) {
+	  /*
+	  **   *             *(+)                  *(+)
+	  **  / \           /    \                /     \
+	  ** |   |   =>    *      *     =>      *         *
+	  ** |   |        / \    / \          /   \      / \
+	  ** r  XOR      r   *  r   *        *     q    *   p
+	  **    / \         / \    / \      / \        / \
+	  **   p   q       q  NOT NOT p    r  NOT     r  NOT
+	  **                  /   /           /          /
+	  **                 p   q           p          q
+	  */
+
+	  if (compareValue)
+	    parent->type = Ctlp_OR_c;
+	  parent->left = parent->right;
+	  parent->left->type = Ctlp_AND_c;
+	  parent->left->left->type = Ctlp_AND_c;
+	  parent->left->left->left = r;
+	  parent->left->left->right = FormulaCreateWithType(Ctlp_NOT_c);
+	  parent->left->left->right->left = p;
+	  parent->left->right = q;
+
+	  parent->right = FormulaCreateWithType(Ctlp_AND_c);
+	  parent->right->left = FormulaCreateWithType(Ctlp_AND_c);
+	  parent->right->left->left = Ctlp_FormulaDup(r);
+	  parent->right->left->right = FormulaCreateWithType(Ctlp_NOT_c);
+	  parent->right->left->right->left = Ctlp_FormulaDup(q);
+	  parent->right->right = Ctlp_FormulaDup(p);
+
+	  parent->top = 0;
+	  parent->left->top = 1;
+	  parent->right->top = 1;
+	  parent->left->compareValue = compareValue;
+	  parent->right->compareValue = compareValue;
+	  parent->left->right->states = (mdd_t *)parent->left;
+	  parent->right->right->states = (mdd_t *)parent->right;
+
+	  FormulaConvertToForward(parent->left->right, compareValue);
+	  FormulaConvertToForward(parent->right->right, compareValue);
+	  break;
+	} else if (!FormulaIsConvertible(p) && !FormulaIsConvertible(q)) {
+	  /*
+	  **   *             *(+)                   *(+)
+	  **  / \           /    \                /      \
+	  ** |   |   =>    *      *     =>      *          *
+	  ** |   |        / \    / \          /   \      /   \
+	  ** r  XOR      r   *  r   *        *    NOT   *    NOT
+	  **    / \         / \    / \      / \   /    / \   /
+	  **   p   q       q  NOT NOT p    r   p q    r   q p
+	  **                  /   /
+	  **                 p   q
+	  */
+
+	  if (compareValue)
+	    parent->type = Ctlp_OR_c;
+	  parent->left = parent->right;
+	  parent->left->type = Ctlp_AND_c;
+	  parent->left->left->type = Ctlp_AND_c;
+	  parent->left->left->left = r;
+	  parent->left->left->right = p;
+	  parent->left->right = FormulaCreateWithType(Ctlp_NOT_c);
+	  parent->left->right->left = q;
+
+	  parent->right = FormulaCreateWithType(Ctlp_AND_c);
+	  parent->right->left = FormulaCreateWithType(Ctlp_AND_c);
+	  parent->right->left->left = Ctlp_FormulaDup(r);
+	  parent->right->left->right = Ctlp_FormulaDup(q);
+	  parent->right->right = FormulaCreateWithType(Ctlp_NOT_c);
+	  parent->right->right->left = Ctlp_FormulaDup(p);
+
+	  parent->top = 0;
+	  parent->left->top = 1;
+	  parent->right->top = 1;
+	  parent->left->compareValue = compareValue;
+	  parent->right->compareValue = compareValue;
+	  parent->left->right->states = (mdd_t *)parent->left;
+	  parent->right->right->states = (mdd_t *)parent->right;
+
+	  FormulaConvertToForward(parent->left->right, compareValue);
+	  FormulaConvertToForward(parent->right->right, compareValue);
+	  break;
+	} else {
+	  f = p;
+	  g = q;
+	}
+      }
+
+      if (compareValue)
+	parent->type = Ctlp_OR_c;
+      parent->left = parent->right;
+      parent->left->type = Ctlp_AND_c;
+      parent->left->left = FormulaCreateWithType(Ctlp_AND_c);
+      parent->left->left->left = r;
+      parent->left->left->right = f;
+      parent->left->right = FormulaCreateWithType(Ctlp_NOT_c);
+      parent->left->right->left = g;
+
+      parent->right = FormulaCreateWithType(Ctlp_AND_c);
+      parent->right->left = FormulaCreateWithType(Ctlp_AND_c);
+      parent->right->left->left = Ctlp_FormulaDup(r);
+      parent->right->left->right = FormulaCreateWithType(Ctlp_NOT_c);
+      parent->right->left->right->left = Ctlp_FormulaDup(f);
+      parent->right->right = Ctlp_FormulaDup(g);
+
+      parent->top = 0;
+      parent->left->top = 1;
+      parent->right->top = 1;
+      parent->left->compareValue = compareValue;
+      parent->right->compareValue = compareValue;
+      parent->left->right->states = (mdd_t *)parent->left;
+      parent->right->right->states = (mdd_t *)parent->right;
+
+      FormulaConvertToForward(parent->left->right, compareValue);
+      FormulaConvertToForward(parent->right->right, compareValue);
+      break;
+
+    case Ctlp_EQ_c:
+      /*
+      **   *              *(+)                   *(+)
+      **  / \            /     \               /      \
+      ** |   |   =>     *       *      =>    *          *
+      ** |   |         / \     / \          / \      /     \
+      ** r  EQ        r   *   r   *        *   g    *      NOT
+      **    /\           / \     / \      / \      / \     /
+      **   p  q         p   q  NOT NOT   r   f    r  NOT  g=q(p)
+      **                       /   /                 /
+      **                      p   q                 f=p(q)
+      */
+
+      p = formula->left;
+      q = formula->right;
+      p_qf = Ctlp_FormulaTestIsQuantifierFree(p);
+      q_qf = Ctlp_FormulaTestIsQuantifierFree(q);
+
+      same_order = 1;
+      if (p_qf && q_qf)
+	break;
+      else if (p_qf) {
+	f = p;
+	g = q;
+      } else if (q_qf) {
+	f = q;
+	g = p;
+      } else {
+	if (FormulaIsConvertible(p) && !FormulaIsConvertible(q)) {
+	  /*
+	  **   *              *(+)                   *(+)
+	  **  / \            /     \               /      \
+	  ** |   |   =>     *       *      =>    *          *
+	  ** |   |         / \     / \          / \      /     \
+	  ** r  EQ        r   *   r   *        *   p    *      NOT
+	  **    /\           / \     / \      / \      / \     /
+	  **   p  q         p   q  NOT NOT   r   q    r  NOT  q
+	  **                       /   /                 /
+	  **                      p   q                 p
+	  */
+
+	  f = q;
+	  g = p;
+	  same_order = 0;
+	} else if (!FormulaIsConvertible(p) && FormulaIsConvertible(q)) {
+	  /*
+	  **   *              *(+)                   *(+)
+	  **  / \            /     \               /      \
+	  ** |   |   =>     *       *      =>    *          *
+	  ** |   |         / \     / \          / \      /     \
+	  ** r  EQ        r   *   r   *        *   q    *      NOT
+	  **    /\           / \     / \      / \      / \     /
+	  **   p  q         p   q  NOT NOT   r   p    r  NOT  p
+	  **                       /   /                 /
+	  **                      p   q                 q
+	  */
+
+	  f = p;
+	  g = q;
+	  same_order = 0;
+	} else {
+	  f = p;
+	  g = q;
+	}
+      }
+
+      if (compareValue)
+	parent->type = Ctlp_OR_c;
+      parent->left = parent->right;
+      parent->left->type = Ctlp_AND_c;
+      parent->left->left = FormulaCreateWithType(Ctlp_AND_c);
+      parent->left->left->left = r;
+      parent->left->left->right = f;
+      parent->left->right = g;
+
+      parent->right = FormulaCreateWithType(Ctlp_AND_c);
+      parent->right->left = FormulaCreateWithType(Ctlp_AND_c);
+      parent->right->left->left = Ctlp_FormulaDup(r);
+      parent->right->left->right = FormulaCreateWithType(Ctlp_NOT_c);
+      if (same_order)
+	parent->right->left->right->left = Ctlp_FormulaDup(f);
+      else
+	parent->right->left->right->left = Ctlp_FormulaDup(g);
+      parent->right->right = FormulaCreateWithType(Ctlp_NOT_c);
+      if (same_order)
+	parent->right->right->left = Ctlp_FormulaDup(g);
+      else
+	parent->right->right->left = Ctlp_FormulaDup(f);
+
+      parent->top = 0;
+      parent->left->top = 1;
+      parent->right->top = 1;
+      parent->left->compareValue = compareValue;
+      parent->right->compareValue = compareValue;
+      parent->left->right->states = (mdd_t *)parent->left;
+      parent->right->right->states = (mdd_t *)parent->right;
+
+      FormulaConvertToForward(parent->left->right, compareValue);
+      FormulaConvertToForward(parent->right->right, compareValue);
+      break;
+
+    case Ctlp_AX_c:
+    case Ctlp_AG_c:
+    case Ctlp_AF_c:
+    case Ctlp_AU_c:
+      fprintf(vis_stderr,
+	"** ctl error : invalid node type in converting to forward formula.\n"
+	      );
+      assert(0);
+      break;
+
+    case Ctlp_ID_c:
+    case Ctlp_TRUE_c:
+    case Ctlp_FALSE_c:
+      break;
+
+    default:
+      fail("Unexpected type");
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts compare nodes into forward formula.]
+
+  Description [Inserts compare nodes into forward formula.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+FormulaInsertForwardCompareNodes(Ctlp_Formula_t *formula,
+				 Ctlp_Formula_t *parent,
+				 int compareValue)
+{
+  Ctlp_Formula_t *new_;
+
+  if (formula->top) {
+    if (!parent) {
+      new_ = FormulaCreateWithType(Ctlp_Cmp_c);
+      memcpy((void *)new_, (void *)formula, sizeof(Ctlp_Formula_t));
+      formula->type = Ctlp_Cmp_c;
+      formula->left = new_;
+      formula->right = FormulaCreateWithType(Ctlp_FALSE_c);
+      formula->compareValue = compareValue;
+    } else {
+      new_ = FormulaCreateWithType(Ctlp_Cmp_c);
+      new_->left = formula;
+      new_->right = FormulaCreateWithType(Ctlp_FALSE_c);
+      new_->compareValue = compareValue;
+      if (parent->left == formula)
+	parent->left = new_;
+      else
+	parent->right = new_;
+    }
+    return;
+  }
+  FormulaInsertForwardCompareNodes(formula->left, formula, compareValue);
+  FormulaInsertForwardCompareNodes(formula->right, formula, compareValue);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Determines which conversion formula is better.]
+
+  Description [Determines which conversion formula is better between
+  init ^ f != FALSE and init ^ !f == FALSE.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+FormulaGetCompareValue(Ctlp_Formula_t *formula)
+{
+  int	compareValue;
+
+  if (FormulaIsConvertible(formula))
+    compareValue = 1; /* check whether the result is not FALSE */
+  else
+    compareValue = 0; /* check whether the result is FALSE. */
+
+  return(compareValue);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a formula can be converted to forward further.]
+
+  Description [Checks whether a formula can be converted to forward further.
+  It returns 1 if it is convertible, and returns 0 if it is not convertible,
+  and returns 2 if it is partially convertible.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+FormulaIsConvertible(Ctlp_Formula_t *formula)
+{
+  int	convertible;
+  int	value1, value2;
+
+  if (Ctlp_FormulaTestIsQuantifierFree(formula))
+    convertible = 1;
+  else if (formula->type == Ctlp_ID_c)
+    convertible = 1;
+  else if (formula->type == Ctlp_EX_c ||
+	   formula->type == Ctlp_EU_c ||
+	   formula->type == Ctlp_EF_c ||
+	   formula->type == Ctlp_EG_c) {
+    convertible = 1;
+  } else if (formula->type == Ctlp_NOT_c) {
+    if (formula->left->type == Ctlp_NOT_c) {
+      if (formula->left->left->type == Ctlp_EX_c ||
+	  formula->left->left->type == Ctlp_EU_c ||
+	  formula->left->left->type == Ctlp_EF_c ||
+	  formula->left->left->type == Ctlp_EG_c) {
+	convertible = 1;
+      } else {
+	convertible = FormulaIsConvertible(formula->left->left);
+      }
+    } else {
+      if (formula->left->type == Ctlp_EX_c ||
+	  formula->left->type == Ctlp_EU_c ||
+	  formula->left->type == Ctlp_EF_c ||
+	  formula->left->type == Ctlp_EG_c) {
+	convertible = 0;
+      } else {
+	value1 = FormulaIsConvertible(formula->left);
+	value2 = FormulaIsConvertible(formula->right);
+	switch (formula->type) {
+	case Ctlp_AND_c:
+	case Ctlp_OR_c:
+	  convertible = (value1 & 0x1) * (value2 & 0x1);
+	  break;
+	case Ctlp_THEN_c:
+	  convertible = value1 * (value2 & 0x1);
+	  break;
+	default :
+	  convertible = 2;
+	  break;
+	}
+      }
+    }
+  } else {
+    value1 = FormulaIsConvertible(formula->left);
+    value2 = FormulaIsConvertible(formula->right);
+    switch (formula->type) {
+    case Ctlp_AND_c:
+    case Ctlp_OR_c:
+      convertible = value1 * value2;
+      break;
+    case Ctlp_THEN_c:
+      convertible = (value1 & 0x1) * value2;
+      break;
+    default :
+      convertible = 2;
+      break;
+    }
+  }
+
+  return(convertible);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Replaces a simple formula with bottom.]
+
+  Description [This function is used in generating the witness formula from a
+  w-ACTL formula in Beer's approach to vacuity detection.  Replaces a simple
+  (propositional) subformula with bottom, which is FALSE for even negation
+  parity and TRUE for odd negation parity.  An exception is made when the top
+  node of the subformula is an implication.  In that case, the top node and the
+  antecedent (left child) are retained in the replacement, while the
+  consequent (right child) is replaced by bottom.]
+
+  SideEffects [none]
+
+  SeeAlso     [Ctlp_FormulaCreateWitnessFormula]
+
+******************************************************************************/
+static Ctlp_Formula_t *
+ReplaceSimpleFormula(
+  Ctlp_Formula_t * formula)
+{
+  Ctlp_Formula_t *newFormula;
+
+  assert(formula->negation_parity == Ctlp_Even_c ||
+	 formula->negation_parity == Ctlp_Odd_c);
+
+  if (Ctlp_FormulaReadType(formula) == Ctlp_THEN_c) {
+    Ctlp_Formula_t *leftFormula, *rightFormula;
+    Ctlp_Formula_t *newLeftFormula, *newRightFormula;
+
+    leftFormula = Ctlp_FormulaReadLeftChild(formula);
+    rightFormula = Ctlp_FormulaReadRightChild(formula);
+    newLeftFormula = Ctlp_FormulaDup(leftFormula);
+    newRightFormula = ReplaceSimpleFormula(rightFormula);
+    return Ctlp_FormulaCreate(Ctlp_THEN_c,newLeftFormula,newRightFormula);
+  }
+
+  fprintf(vis_stderr, "Replacing formula ");
+  Ctlp_FormulaPrint(vis_stderr, formula);
+  if (formula->negation_parity == Ctlp_Even_c){
+    fprintf(vis_stderr, " by FALSE\n");
+    newFormula = FormulaCreateWithType(Ctlp_FALSE_c);
+  } else{
+    fprintf(vis_stderr, " by TRUE\n");
+    newFormula = FormulaCreateWithType(Ctlp_TRUE_c);
+  }
+  newFormula->negation_parity = formula->negation_parity;
+  return(newFormula);
+}
Index: vis_dev/vis-2.3/src/ctlsp/ctlsp.h
===================================================================
--- vis_dev/vis-2.3/src/ctlsp/ctlsp.h	(revision 14)
+++ vis_dev/vis-2.3/src/ctlsp/ctlsp.h	(revision 14)
@@ -0,0 +1,255 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [ctlsp.h]
+
+  PackageName [ctlsp]
+
+  Synopsis    [Routines for parsing, writing and accessing CTL* formulas.]
+
+  Description [This package implements a parser for CTL* formulas.  CTL* is
+  a language used to describe properties of systems.]
+
+  SeeAlso     []
+
+  Author      [Mohammad Awedh]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+  Revision    [$Id: ctlsp.h,v 1.28 2009/04/11 01:32:36 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _CTLSP
+#define _CTLSP
+
+#include "vm.h"
+#include "ctlp.h"
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Enum************************************************************************
+
+  Synopsis    [Types of operators allowed in CTL* formulas.]
+
+  Description [The types of nodes in a CTL* formula parse tree. ID, TRUE, and
+  FALSE are leaves, and all others are internal nodes.]
+
+  SeeAlso     [Ctlsp_FormulaReadType]
+
+******************************************************************************/
+typedef enum {
+  Ctlsp_E_c,      /* there exists */
+  Ctlsp_A_c,      /* for all paths*/
+  Ctlsp_X_c,      /* Next */
+  Ctlsp_G_c,      /* globally */
+  Ctlsp_F_c,      /* finally */
+  Ctlsp_U_c,      /* until (not symmetric in args) */
+  Ctlsp_R_c,      /* release (not symmetric in args) */
+  Ctlsp_W_c,      /* weak until (not symmetric in args) */
+  Ctlsp_OR_c,     /* Boolean disjunction */
+  Ctlsp_AND_c,    /* Boolean conjunction */
+  Ctlsp_NOT_c,    /* Boolean negation*/
+  Ctlsp_THEN_c,   /* Boolean implies (not symmetric) */
+  Ctlsp_XOR_c,    /* Boolean XOR */
+  Ctlsp_EQ_c,     /* Boolean equal */
+  Ctlsp_ID_c,     /* an atomic proposition */
+  Ctlsp_TRUE_c,   /* tautology (used only for translation to exist. form) */
+  Ctlsp_FALSE_c,  /* empty (used only for translation to exist. form) */
+  Ctlsp_Fwd_c,    /* forward */
+  Ctlsp_Y_c,	 /* previous state */
+  Ctlsp_H_c,	 /* past */
+  Ctlsp_Init_c,	 /* initial states */
+  Ctlsp_Cmp_c	 /* compare two leaves in forward CTL* */
+} Ctlsp_FormulaType;
+
+
+/**Enum************************************************************************
+
+  Synopsis    [Types of operators allowed in CTL formulas.]
+
+  Description [The types of nodes in a CTL formula parse tree. ID, TRUE, and
+  FALSE are leaves, and all others are internal nodes.]
+
+  SeeAlso     [Ctlsp_FormulaReadType]
+
+******************************************************************************/
+typedef enum {
+  Ctlsp_ECTL_c,
+  Ctlsp_ACTL_c,
+  Ctlsp_Mixed_c,
+  Ctlsp_QuantifierFree_c,
+  Ctlsp_LTL_c,
+  Ctlsp_stateFormuls_c,
+  Ctlsp_invalid_c
+} Ctlsp_FormulaClass;
+
+
+/**Enum************************************************************************
+
+  Synopsis    [Types of approximations that are possible]
+
+  Description [We can have overapproximations, underapproximations, exact
+  approximations, or incomparable sets.  Question: is ctlsp the right place for
+  this?  It is used in ctlsp, mc, rch. (RB)]
+
+  SeeAlso     []
+
+******************************************************************************/
+typedef enum {
+  Ctlsp_Incomparable_c,
+  Ctlsp_Underapprox_c,
+  Ctlsp_Overapprox_c,
+  Ctlsp_Exact_c
+} Ctlsp_Approx_t;
+
+/**Enum************************************************************************
+
+  Synopsis    [ Class of CTL* formulas.]
+
+  Description [The classes of nodes in CTL* formula.]
+
+  Note: [We explicity assign values to the enumerated values becuase we
+	 are going to use the numerical values in determining the class of
+	 a CTL* formula. These values are used in table1, table2, and
+	 table3 macros.]
+
+  SeeAlso [ctlspInt.h]
+
+******************************************************************************/
+typedef enum {
+  Ctlsp_propformula_c  = 0,
+  Ctlsp_LTLformula_c   = 1,
+  Ctlsp_stateformula_c = 2,
+  Ctlsp_pathformula_c  = 3
+} Ctlsp_ClassOfFormula;
+
+
+/**Enum************************************************************************
+
+  Synopsis    [ Class of CTL formulas.]
+
+  Description [The classes of CTL formula. This help to find out whether a
+	      formula is CTL or not.  During the parsing of a CTL* formula
+	      the parser determines whether the subformula is a CTL formula,
+	      (Ctlsp_CTL_c) can be CTL formula (Ctlsp_PathCTL_c), or not
+	      CTL formula (Ctlsp_NotCTL_c).]
+
+  SeeAlso     [ctlsp.y]
+
+******************************************************************************/
+typedef enum {
+  Ctlsp_NotCTL_c,
+  Ctlsp_PathCTL_c,
+  Ctlsp_CTL_c
+} Ctlsp_ClassOfCTLFormula;
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef struct CtlspFormulaStruct Ctlsp_Formula_t;
+typedef void   (*Ctlsp_DbgInfoFreeFn) (Ctlsp_Formula_t *);
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void Ctlsp_Init(void);
+EXTERN void Ctlsp_End(void);
+EXTERN array_t * Ctlsp_FileParseFormulaArray(FILE * fp);
+EXTERN array_t * Ctlsp_FileParseCTLFormulaArray(FILE * fp);
+EXTERN char * Ctlsp_FormulaConvertToString(Ctlsp_Formula_t * formula);
+EXTERN void Ctlsp_FormulaPrint(FILE * fp, Ctlsp_Formula_t * formula);
+EXTERN Ctlsp_FormulaType Ctlsp_FormulaReadType(Ctlsp_Formula_t * formula);
+EXTERN int Ctlsp_FormulaReadCompareValue(Ctlsp_Formula_t * formula);
+EXTERN char * Ctlsp_FormulaReadVariableName(Ctlsp_Formula_t * formula);
+EXTERN char * Ctlsp_FormulaReadValueName(Ctlsp_Formula_t * formula);
+EXTERN Ctlsp_Formula_t * Ctlsp_FormulaReadLeftChild(Ctlsp_Formula_t * formula);
+EXTERN Ctlsp_Formula_t * Ctlsp_FormulaReadRightChild(Ctlsp_Formula_t * formula);
+EXTERN mdd_t * Ctlsp_FormulaObtainStates(Ctlsp_Formula_t * formula);
+EXTERN mdd_t * Ctlsp_FormulaObtainApproxStates(Ctlsp_Formula_t *formula, Ctlsp_Approx_t approx);
+EXTERN void Ctlsp_FormulaSetStates(Ctlsp_Formula_t * formula, mdd_t * states);
+EXTERN void Ctlsp_FormulaSetApproxStates(Ctlsp_Formula_t * formula, mdd_t * states, Ctlsp_Approx_t approx);
+EXTERN void Ctlsp_FormulaSetDbgInfo(Ctlsp_Formula_t * formula, void *data, Ctlsp_DbgInfoFreeFn freeFn);
+EXTERN void * Ctlsp_FormulaReadDebugData(Ctlsp_Formula_t * formula);
+EXTERN boolean Ctlsp_FormulaTestIsConverted(Ctlsp_Formula_t * formula);
+EXTERN boolean Ctlsp_FormulaTestIsQuantifierFree(Ctlsp_Formula_t *formula);
+EXTERN Ctlsp_Formula_t * Ctlsp_FormulaReadOriginalFormula(Ctlsp_Formula_t * formula);
+EXTERN int Ctlsp_FormulaReadABIndex(Ctlsp_Formula_t * formula);
+EXTERN void Ctlsp_FormulaSetABIndex(Ctlsp_Formula_t * formula, int ab_idx);
+EXTERN int Ctlsp_FormulaReadLabelIndex(Ctlsp_Formula_t * formula);
+EXTERN void Ctlsp_FormulaSetLabelIndex(Ctlsp_Formula_t * formula, int label_idx);
+EXTERN char Ctlsp_FormulaReadRhs(Ctlsp_Formula_t * formula);
+EXTERN void Ctlsp_FormulaSetRhs(Ctlsp_Formula_t * formula);
+EXTERN void Ctlsp_FormulaResetRhs(Ctlsp_Formula_t * formula);
+EXTERN char Ctlsp_FormulaReadMarked(Ctlsp_Formula_t * formula);
+EXTERN void Ctlsp_FormulaSetMarked(Ctlsp_Formula_t * formula);
+EXTERN void Ctlsp_FormulaResetMarked(Ctlsp_Formula_t * formula);
+EXTERN void Ctlsp_FormulaFree(Ctlsp_Formula_t *formula);
+EXTERN void Ctlsp_FlushStates(Ctlsp_Formula_t * formula);
+EXTERN Ctlsp_Formula_t * Ctlsp_FormulaDup(Ctlsp_Formula_t * formula);
+EXTERN void Ctlsp_FormulaArrayFree(array_t * formulaArray);
+EXTERN array_t * Ctlsp_FormulaArrayConvertToDAG(array_t *formulaArray);
+EXTERN Ctlsp_Formula_t * Ctlsp_FormulaCreate(Ctlsp_FormulaType type, void * left_, void * right_);
+EXTERN Ctlsp_Formula_t * Ctlsp_FormulaCreateOr(char *name, char *valueStr);
+EXTERN Ctlsp_Formula_t * Ctlsp_FormulaCreateVectorAnd(char *nameVector, char *value);
+EXTERN Ctlsp_Formula_t * Ctlsp_FormulaCreateVectorOr(char *nameVector, char *valueStr);
+EXTERN Ctlsp_Formula_t * Ctlsp_FormulaCreateEquiv(char *left, char *right);
+EXTERN Ctlsp_Formula_t * Ctlsp_FormulaCreateVectorEquiv(char *left, char *right);
+EXTERN Ctlsp_Formula_t * Ctlsp_FormulaCreateXMult(char *string, Ctlsp_Formula_t *formula);
+EXTERN Ctlsp_Formula_t * Ctlsp_FormulaCreateEXMult(char *string, Ctlsp_Formula_t *formula);
+EXTERN Ctlsp_Formula_t * Ctlsp_FormulaCreateAXMult(char *string, Ctlsp_Formula_t *formula);
+EXTERN char * Ctlsp_FormulaGetTypeString(Ctlsp_Formula_t *formula);
+EXTERN Ctlsp_FormulaClass Ctlsp_CheckClassOfExistentialFormula(Ctlsp_Formula_t *formula);
+EXTERN Ctlsp_FormulaClass Ctlsp_CheckClassOfExistentialFormulaArray(array_t *formulaArray);
+EXTERN Ctlsp_ClassOfFormula Ctlsp_FormulaReadClass(Ctlsp_Formula_t *formula);
+EXTERN void Ctlsp_FormulaSetClass(Ctlsp_Formula_t *formula, Ctlsp_ClassOfFormula newClass);
+EXTERN Ctlsp_ClassOfCTLFormula Ctlsp_FormulaReadClassOfCTL(Ctlsp_Formula_t *formula);
+EXTERN void Ctlsp_FormulaSetClassOfCTL(Ctlsp_Formula_t *formula, Ctlsp_ClassOfCTLFormula newCTLclass);
+EXTERN array_t * Ctlsp_FormulaArrayConvertToLTL(array_t *formulaArray);
+EXTERN array_t * Ctlsp_FormulaArrayConvertToCTL(array_t *formulaArray);
+EXTERN Ctlp_Formula_t * Ctlsp_FormulaConvertToCTL(Ctlsp_Formula_t *formula);
+EXTERN Ctlp_Formula_t * Ctlsp_PropositionalFormulaToCTL(Ctlsp_Formula_t *formula);
+EXTERN int Ctlsp_isPropositionalFormula(Ctlsp_Formula_t *formula);
+EXTERN int Ctlsp_isCtlFormula(Ctlsp_Formula_t *formula);
+EXTERN int Ctlsp_isLtlFormula(Ctlsp_Formula_t *formula);
+EXTERN Ctlsp_Formula_t * Ctlsp_LtllFormulaNegate(Ctlsp_Formula_t *ltlFormula);
+EXTERN void Ctlsp_LtlSetClass(Ctlsp_Formula_t *formula);
+EXTERN int Ctlsp_LtlFormulaIsGFp(Ctlsp_Formula_t *formula);
+EXTERN boolean Ctlsp_LtlFormulaIsGp(Ctlsp_Formula_t *formula);
+EXTERN boolean Ctlsp_LtlFormulaIsFp(Ctlsp_Formula_t *formula);
+EXTERN boolean Ctlsp_LtlFormulaIsSafety(Ctlsp_Formula_t *formula);
+EXTERN void Ctlsp_FormulaArrayAddLtlFairnessConstraints(array_t *formulaArray, array_t *constraintArray);
+EXTERN Ctlsp_Formula_t * Ctlsp_CtlFormulaToCtlsp(Ctlp_Formula_t *F);
+EXTERN Ctlsp_Formula_t * Ctlsp_LtlFormulaExpandAbbreviation(Ctlsp_Formula_t *formula);
+EXTERN Ctlsp_Formula_t * Ctlsp_LtlFormulaNegationNormalForm(Ctlsp_Formula_t *formula);
+EXTERN Ctlsp_Formula_t * Ctlsp_LtlFormulaHashIntoUniqueTable(Ctlsp_Formula_t *F, st_table *uniqueTable);
+EXTERN void Ctlsp_LtlFormulaClearMarks(Ctlsp_Formula_t *F);
+EXTERN int Ctlsp_LtlFormulaCountNumber(Ctlsp_Formula_t *F);
+EXTERN st_table * Ctlsp_LtlFormulaCreateUniqueTable(void);
+EXTERN int Ctlsp_LtlFormulaIsElementary2(Ctlsp_Formula_t *F);
+EXTERN int Ctlsp_LtlFormulaIsElementary(Ctlsp_Formula_t *F);
+EXTERN boolean Ctlsp_LtlFormulaTestIsBounded(Ctlsp_Formula_t *formula, int *depth);
+EXTERN int Ctlsp_LtlFormulaDepth(Ctlsp_Formula_t *formula);
+EXTERN boolean Ctlsp_LtlFormulaTestIsSyntacticallyCoSafe(Ctlsp_Formula_t *formula);
+EXTERN int Ctlsp_LtlFormulaArrayIsPropositional(array_t * formulaArray);
+EXTERN int Ctlsp_LtlFormulaIsPropositional(Ctlsp_Formula_t *F);
+EXTERN int Ctlsp_LtlFormulaIsAtomicPropositional(Ctlsp_Formula_t *F);
+EXTERN int Ctlsp_LtlFormulaIsFG(Ctlsp_Formula_t *F);
+EXTERN int Ctlsp_LtlFormulaIsGF(Ctlsp_Formula_t *F);
+EXTERN int Ctlsp_LtlFormulaIsFGorGF(Ctlsp_Formula_t *F);
+EXTERN int Ctlsp_LtlFormulaSimplyImply(Ctlsp_Formula_t *from, Ctlsp_Formula_t *to);
+EXTERN array_t * Ctlsp_LtlTranslateIntoSNF(Ctlsp_Formula_t *formula);
+EXTERN void  Ctlsp_LtlTranslateIntoSNFRecursive(Ctlsp_Formula_t *propNode, Ctlsp_Formula_t *formula, array_t *formulaArray, int *index);
+EXTERN Ctlsp_Formula_t * Ctlsp_LtlFormulaSimpleRewriting(Ctlsp_Formula_t *formula);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _CTLSP */
Index: vis_dev/vis-2.3/src/ctlsp/ctlsp.l
===================================================================
--- vis_dev/vis-2.3/src/ctlsp/ctlsp.l	(revision 14)
+++ vis_dev/vis-2.3/src/ctlsp/ctlsp.l	(revision 14)
@@ -0,0 +1,166 @@
+%{
+/**CFile***********************************************************************
+
+  FileName    [ctlsp.l]
+
+  PackageName [ctlsp]
+
+  Synopsis    [Lexical analyzer for CTL* formula parser.]
+
+  Author      [Mohammad Awedh]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+  Revision    [$Id: ctlsp.l,v 1.4 2010/04/09 23:31:37 fabio Exp $]
+
+******************************************************************************/
+
+#include "ctlspRead.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes global variables for parsing file.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+CtlspFileSetup(
+  FILE * fp)
+{
+  CtlspYyin             = fp;
+  CtlspYylineno         = 1;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Prints error message and sets global error flag.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+CtlspYyerror(
+  char * errmsg)
+{
+  (void) fprintf(vis_stderr, "%s in line %d with token \"%s\"\n", errmsg, CtlspYylineno, yytext); 
+  CtlspGlobalError = 1;
+}
+
+%}
+
+/*---------------------------------------------------------------------------*/
+/*      Lexical analyzer rules                                               */
+/*---------------------------------------------------------------------------*/
+
+%option noyywrap
+%option yylineno
+
+/* substitution strings */
+/* alnum is the same set in alnumsymbol in io.l except [ and ] being removed here for the until and release operators */
+/* - , =, and ; are intentionally removed because: 
+   - is used for -> and <->
+   = is used for foo = bar 
+   ; is used for delimitters */
+/* ( and ) are intentionally removed since they are used as parentheses */
+/* +, *, and ^ have to be used surrounded by spaces since they are symbols. 
+   ! can be attached immediately w/o spaces since it is not a symbol */
+
+alnum	[A-Za-z0-9\^\?\|\/\+\*\$\<\>~@\_#\$%\:\"\'\.]
+
+%%
+
+[ \t\n\r]	;
+
+"#".*   ;   
+
+A	{ return(TOK_FORALL); }
+E	{ return(TOK_EXISTS); }
+
+AX	{ return(TOK_FORALL_NEXT); }
+EX	{ return(TOK_EXISTS_NEXT); }
+AF	{ return(TOK_FORALL_EVENTUALLY); }
+EF	{ return(TOK_EXISTS_EVENTUALLY); }
+AG	{ return(TOK_FORALL_GLOBALLY); }
+EG	{ return(TOK_EXISTS_GLOBALLY); }
+
+
+X	{ return(TOK_NEXT); }
+F	{ return(TOK_EVENTUALLY); }
+G	{ return(TOK_GLOBALLY); }
+
+X:[0-9]+  { return(TOK_NEXT_MULT); }
+
+AX:[0-9]+  { return(TOK_FORALL_NEXT_MULT); }
+EX:[0-9]+  { return(TOK_EXISTS_NEXT_MULT); }
+
+U	{ return(TOK_UNTIL); }
+R	{ return(TOK_RELEASE); }
+W	{ return(TOK_WEAK_UNTIL); }
+
+
+TRUE    { return(TOK_TRUE); }
+
+FALSE   { return(TOK_FALSE); }
+
+\\DEFINE |
+\\Define |
+\\define  { return(TOK_DEFINE); }
+
+\+	{ return(TOK_OR); }
+\|\|	{ return(TOK_OR); }
+\*	{ return(TOK_AND); }
+\&\&	{ return(TOK_AND); }
+!	{ return(TOK_NOT); }
+"^"	{ return(TOK_XOR); }
+"->"	{ return(TOK_THEN); }
+"<->"	{ return(TOK_EQ); }
+=       { return(TOK_ASSIGN); }
+==      { return(TOK_EQIV); }
+\,      { return(TOK_COMMA); }
+\\      { return(TOK_MACRO); }
+
+{alnum}+                                   { return(TOK_ID); }
+{alnum}+\[[ ]*[0-9]+[ ]*\]                 { return(TOK_ID2); }
+{alnum}+\[[ ]*[0-9]+[ ]*\:[ ]*[0-9]+[ ]*\] { return(TOK_ID_VECTOR); }
+
+.       { return CtlspYytext[0]; }
+%%
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/ctlsp/ctlsp.make
===================================================================
--- vis_dev/vis-2.3/src/ctlsp/ctlsp.make	(revision 14)
+++ vis_dev/vis-2.3/src/ctlsp/ctlsp.make	(revision 14)
@@ -0,0 +1,17 @@
+CSRC += ctlspCmd.c ctlspUtil.c
+HEADERS += ctlsp.h ctlspInt.h
+LEXSRC += ctlsp.l
+YACCSRC += ctlsp.y
+GENERATEDCSRC += ctlspRead.c
+
+$(objectdir)/ctlspRead.c $(objectdir)/ctlspRead.h: ctlsp.y ctlsp.h ctlspInt.h ctlspLex.c
+	$(YACC) -pCtlspYy -t -d -o $(objectdir)/ctlspRead.c $<
+	-@chmod 0664 $(objectdir)/ctlspRead.c
+
+$(objectdir)/ctlspLex.c: ctlsp.l
+	$(LEX) -PCtlspYy -o$(objectdir)/ctlspLex.c $< 
+	-@chmod 0664 $(objectdir)/ctlspLex.c
+
+$(objectdir)/ctlspRead.o: $(objectdir)/ctlspRead.c
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/ctlsp/ctlsp.y
===================================================================
--- vis_dev/vis-2.3/src/ctlsp/ctlsp.y	(revision 14)
+++ vis_dev/vis-2.3/src/ctlsp/ctlsp.y	(revision 14)
@@ -0,0 +1,617 @@
+%{
+/**CFile*****************************************************************
+
+  FileName    [ctlsp.y]
+
+  PackageName [ctlsp]
+
+  Synopsis    [Yacc for CTL* formula parser.]
+
+  SeeAlso     [ctlsp.h]
+
+  Author      [Mohammad Awedh]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "ctlspInt.h"
+
+/*
+ * The following is a workaround for a bug in bison, which generates code
+ * that uses alloca().  Their lengthy sequence of #ifdefs for defining
+ * alloca() does the wrong thing for HPUX (it should do what is defined below)
+ */
+#ifdef __hpux
+#  include <alloca.h>
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#include "ctlspLex.c"
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+%}
+
+/*---------------------------------------------------------------------------*/
+/*      Grammar declarations                                                 */
+/*---------------------------------------------------------------------------*/
+
+%union {
+  Ctlsp_Formula_t *sf;	/* state formula */
+  char *str;
+}
+
+%type <sf> error formula propformula CTLsFormula
+%type <str> name name_vector name_union name_or macro x_mult ax_mult ex_mult
+
+/* %token YYERROR_VERBOSE */
+
+%token TOK_DEFINE
+%token TOK_MACRO
+%token TOK_ID
+%token TOK_ID2
+%token TOK_ID_VECTOR
+%token TOK_ID_UNION
+%token TOK_COMMA
+%token TOK_EQIV
+%token TOK_FORALL
+%token TOK_EXISTS
+%token TOK_UNTIL
+%token TOK_RELEASE
+%token TOK_WEAK_UNTIL
+%token TOK_NEXT
+%token TOK_EVENTUALLY
+%token TOK_GLOBALLY
+%token TOK_FORALL_NEXT
+%token TOK_FORALL_EVENTUALLY
+%token TOK_FORALL_GLOBALLY
+%token TOK_EXISTS_NEXT
+%token TOK_EXISTS_EVENTUALLY
+%token TOK_EXISTS_GLOBALLY
+%token TOK_NEXT_MULT
+%token TOK_FORALL_NEXT_MULT
+%token TOK_EXISTS_NEXT_MULT
+%token TOK_THEN
+%token TOK_EQ
+%token TOK_XOR
+%token TOK_AND
+%token TOK_OR
+%token TOK_NOT
+%token TOK_ASSIGN
+%token TOK_TRUE
+%token TOK_FALSE
+
+/* precedence is specified here from lowest to highest */
+
+%nonassoc TOK_UNTIL TOK_RELEASE TOK_WEAK_UNTIL
+%left TOK_THEN
+%left TOK_EQ
+%left TOK_XOR
+%left TOK_OR
+%left TOK_AND
+%nonassoc TOK_NEXT TOK_EVENTUALLY TOK_GLOBALLY
+%nonassoc  TOK_FORALL TOK_EXISTS TOK_FORALL_EVENTUALLY TOK_FORALL_GLOBALLY TOK_EXISTS_NEXT TOK_EXISTS_EVENTUALLY TOK_EXISTS_GLOBALLY
+%nonassoc TOK_NOT
+
+%%
+
+/*---------------------------------------------------------------------------*/
+/*      Grammar rules                                                        */
+/*---------------------------------------------------------------------------*/
+formulas     : /* nothing */
+	     | formulas formula
+	     ;
+
+formula : CTLsFormula ';'
+	{
+	  if  (Ctlsp_FormulaReadClass($1) == Ctlsp_pathformula_c )
+	    {
+	     Ctlsp_FormulaFree(CtlspGlobalFormula);
+	     (void) fprintf(vis_stderr, "** CTL * error : Invalid CTL* formula (it is path formula) , line %d\n\n", CtlspYylineno);
+	     CtlspGlobalFormula = NIL(Ctlsp_Formula_t);
+	    }
+	  else
+	    {
+	     CtlspFormulaAddToGlobalArray($1);
+	     $$ = $1;
+	     /*
+	      * The formula is echoed by the lexical analyzer to stdout.
+	      * Here we are just printing the line number after it.
+	      */
+	      CtlspGlobalFormula = NIL(Ctlsp_Formula_t);
+	    }
+	 }
+	| TOK_DEFINE name CTLsFormula
+	  { if (!CtlspFormulaAddToTable($2, $3, CtlspMacroTable)){
+	     CtlspYyerror("** CTL* error : MACRO ERROR");
+	     (void) fprintf(vis_stderr, "Macro \"%s\" is already in table.\n\n",$2);
+	     Ctlsp_FormulaFree(CtlspGlobalFormula);
+	     $$ = NULL;
+	   }else{
+	     $$ = $3;
+	  }
+	   CtlspGlobalFormula = NIL(Ctlsp_Formula_t);
+	 }
+	| error ';'
+	  { $$ = NULL;
+	   /*
+	    * Error was detected reading the formula. Garbage collect
+	    * and print error message.
+	    */
+	    Ctlsp_FormulaFree(CtlspGlobalFormula);
+	    (void) fprintf(vis_stderr, "** ctl* error : Invalid CTL* formula, line %d\n\n", CtlspYylineno);
+	    CtlspGlobalFormula = NIL(Ctlsp_Formula_t);
+	 }
+	 ;
+
+CTLsFormula : propformula
+	     {
+		Ctlsp_FormulaSetClass($1, Ctlsp_propformula_c);
+		Ctlsp_FormulaSetClassOfCTL($1, Ctlsp_CTL_c);
+		$$ = $1;
+		CtlspGlobalFormula= $$;
+	      }
+	     | '(' CTLsFormula ')'
+	      {
+		/*Ctlsp_FormulaSetClass($2,  Ctlsp_FormulaReadClass($2));
+		  do nothing, and the formula keeps its old class
+		*/
+		$$ = $2;
+		CtlspGlobalFormula= $$;
+	      }
+	     | TOK_NOT CTLsFormula
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_NOT_c, $2, NIL(Ctlsp_Formula_t));
+		 Ctlsp_FormulaSetClass($$, Ctlsp_FormulaReadClass($2));
+		 Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_FormulaReadClassOfCTL($2));
+		 CtlspGlobalFormula= $$;
+	       }
+	     |  CTLsFormula TOK_AND CTLsFormula
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_AND_c, $1, $3);
+		 Ctlsp_FormulaSetClass($$, table1(Ctlsp_FormulaReadClass($1),Ctlsp_FormulaReadClass($3)) );
+		 if ((Ctlsp_FormulaReadClassOfCTL($1) ==  Ctlsp_CTL_c) && (Ctlsp_FormulaReadClassOfCTL($3) == Ctlsp_CTL_c))
+		   {
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_CTL_c);
+		   }
+		 else
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_NotCTL_c);
+
+		 CtlspGlobalFormula= $$;
+	       }
+	     | CTLsFormula TOK_OR CTLsFormula
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_OR_c, $1, $3);
+		 Ctlsp_FormulaSetClass($$, table1(Ctlsp_FormulaReadClass($1),Ctlsp_FormulaReadClass($3)) );
+
+		 if ((Ctlsp_FormulaReadClassOfCTL($1) ==  Ctlsp_CTL_c) && (Ctlsp_FormulaReadClassOfCTL($3) == Ctlsp_CTL_c))
+		   {
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_CTL_c);
+		   }
+		 else
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_NotCTL_c);
+
+		 CtlspGlobalFormula= $$;
+	       }
+	     | CTLsFormula TOK_THEN CTLsFormula
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_THEN_c, $1, $3);
+		 Ctlsp_FormulaSetClass($$, table1(Ctlsp_FormulaReadClass($1),Ctlsp_FormulaReadClass($3)) );
+
+		 if ((Ctlsp_FormulaReadClassOfCTL($1) ==  Ctlsp_CTL_c) && (Ctlsp_FormulaReadClassOfCTL($3) == Ctlsp_CTL_c))
+		   {
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_CTL_c);
+		   }
+		 else
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_NotCTL_c);
+
+		 CtlspGlobalFormula= $$;
+	       }
+	     | CTLsFormula TOK_EQ CTLsFormula
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_EQ_c, $1, $3);
+		 Ctlsp_FormulaSetClass($$, table1(Ctlsp_FormulaReadClass($1),Ctlsp_FormulaReadClass($3)) );
+
+		 if ((Ctlsp_FormulaReadClassOfCTL($1) ==  Ctlsp_CTL_c) && (Ctlsp_FormulaReadClassOfCTL($3) == Ctlsp_CTL_c))
+		   {
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_CTL_c);
+		   }
+		 else
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_NotCTL_c);
+
+		 CtlspGlobalFormula= $$;
+	       }
+	     | CTLsFormula TOK_XOR CTLsFormula
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_XOR_c, $1, $3);
+		 Ctlsp_FormulaSetClass($$, table1(Ctlsp_FormulaReadClass($1),Ctlsp_FormulaReadClass($3)) );
+		 if ((Ctlsp_FormulaReadClassOfCTL($1) ==  Ctlsp_CTL_c) && (Ctlsp_FormulaReadClassOfCTL($3) == Ctlsp_CTL_c))
+		   {
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_CTL_c);
+		   }
+		 else
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_NotCTL_c);
+		 CtlspGlobalFormula= $$;
+	       }
+
+	     | TOK_NEXT CTLsFormula
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_X_c, $2, NIL(Ctlsp_Formula_t));
+		 Ctlsp_FormulaSetClass($$, table2(Ctlsp_FormulaReadClass($2)));
+		 if (Ctlsp_FormulaReadClassOfCTL($2) ==  Ctlsp_CTL_c)
+		   {
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_PathCTL_c);
+		   }
+		 else
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_NotCTL_c);
+		 CtlspGlobalFormula= $$;
+	       }
+	     | TOK_EVENTUALLY CTLsFormula
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_F_c, $2, NIL(Ctlsp_Formula_t));
+		 Ctlsp_FormulaSetClass($$, table2(Ctlsp_FormulaReadClass($2)));
+		 if (Ctlsp_FormulaReadClassOfCTL($2) ==  Ctlsp_CTL_c)
+		   {
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_PathCTL_c);
+		   }
+		 else
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_NotCTL_c);
+		 CtlspGlobalFormula= $$;
+	       }
+	     | TOK_GLOBALLY CTLsFormula
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_G_c, $2, NIL(Ctlsp_Formula_t));
+		 Ctlsp_FormulaSetClass($$, table2(Ctlsp_FormulaReadClass($2)) );
+		 if (Ctlsp_FormulaReadClassOfCTL($2) ==  Ctlsp_CTL_c)
+		   {
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_PathCTL_c);
+		   }
+		 else
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_NotCTL_c);
+		 CtlspGlobalFormula= $$;
+	       }
+	     | CTLsFormula TOK_UNTIL CTLsFormula
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_U_c, $1, $3);
+		 Ctlsp_FormulaSetClass($$, table3(Ctlsp_FormulaReadClass($1),Ctlsp_FormulaReadClass($3)) );
+		 if ((Ctlsp_FormulaReadClassOfCTL($1) ==  Ctlsp_CTL_c) && (Ctlsp_FormulaReadClassOfCTL($3) == Ctlsp_CTL_c))
+		   {
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_PathCTL_c);
+		   }
+		 else
+		   {
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_NotCTL_c);
+		   }
+		 CtlspGlobalFormula= $$;
+	       }
+	     | CTLsFormula TOK_RELEASE CTLsFormula
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_R_c, $1, $3);
+		 Ctlsp_FormulaSetClass($$, table3(Ctlsp_FormulaReadClass($1),Ctlsp_FormulaReadClass($3)) );
+		 if ((Ctlsp_FormulaReadClassOfCTL($1) ==  Ctlsp_CTL_c) && (Ctlsp_FormulaReadClassOfCTL($3) == Ctlsp_CTL_c))
+		   {
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_PathCTL_c);
+		   }
+		 else
+		   {
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_NotCTL_c);
+		   }
+		 CtlspGlobalFormula= $$;
+	       }
+	     | CTLsFormula TOK_WEAK_UNTIL CTLsFormula
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_W_c, $1, $3);
+		 Ctlsp_FormulaSetClass($$, table3(Ctlsp_FormulaReadClass($1),Ctlsp_FormulaReadClass($3)) );
+		 if ((Ctlsp_FormulaReadClassOfCTL($1) ==  Ctlsp_CTL_c) && (Ctlsp_FormulaReadClassOfCTL($3) == Ctlsp_CTL_c))
+		   {
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_PathCTL_c);
+		   }
+		 else
+		   {
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_NotCTL_c);
+		   }
+		 CtlspGlobalFormula= $$;
+	       }
+	     | TOK_EXISTS CTLsFormula
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_E_c, $2, NIL(Ctlsp_Formula_t));
+		 Ctlsp_FormulaSetClass($$, Ctlsp_stateformula_c);
+		 if (Ctlsp_FormulaReadClassOfCTL($2) ==  Ctlsp_PathCTL_c)
+		   {
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_CTL_c);
+		   }
+		 else
+		   {
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_NotCTL_c);
+		   }
+		 CtlspGlobalFormula= $$;
+	       }
+	     |  TOK_EXISTS_NEXT CTLsFormula
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_X_c, $2, NIL(Ctlsp_Formula_t));
+		 Ctlsp_FormulaSetClass($$, table2(Ctlsp_FormulaReadClass($2)));
+		 $$ = Ctlsp_FormulaCreate(Ctlsp_E_c, $$, NIL(Ctlsp_Formula_t));
+		 Ctlsp_FormulaSetClass($$, Ctlsp_stateformula_c);
+		 if (Ctlsp_FormulaReadClassOfCTL($2) ==  Ctlsp_CTL_c)
+		 {
+		   Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_CTL_c);
+		 }
+		 else
+		 {
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_NotCTL_c);
+		 }
+		 CtlspGlobalFormula= $$;
+	       }
+	      | ex_mult '(' CTLsFormula ')'
+		 { $$ = Ctlsp_FormulaCreateEXMult($1, $3);
+		   if ($$ == NIL(Ctlsp_Formula_t)){
+		   CtlspYyerror("** ctl* error : MULTIPLE EX ERROR");
+		   (void) fprintf(vis_stderr,"Error during parsing line %d.\n\n", CtlspYylineno);
+		   Ctlsp_FormulaFree(CtlspGlobalFormula);
+		   }
+		   FREE($1);
+		   CtlspGlobalFormula= $$;
+	       }
+	     | TOK_EXISTS_EVENTUALLY CTLsFormula
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_F_c, $2, NIL(Ctlsp_Formula_t));
+		 Ctlsp_FormulaSetClass($$, table2(Ctlsp_FormulaReadClass($2)));
+		 $$ = Ctlsp_FormulaCreate(Ctlsp_E_c, $$, NIL(Ctlsp_Formula_t));
+		 Ctlsp_FormulaSetClass($$, Ctlsp_stateformula_c);
+		 if (Ctlsp_FormulaReadClassOfCTL($2) ==  Ctlsp_CTL_c)
+		   {
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_CTL_c);
+		   }
+		 else
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_NotCTL_c);
+		 CtlspGlobalFormula= $$;
+	       }
+	     | TOK_EXISTS_GLOBALLY CTLsFormula
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_G_c, $2, NIL(Ctlsp_Formula_t));
+		 Ctlsp_FormulaSetClass($$, table2(Ctlsp_FormulaReadClass($2)));
+		 $$ = Ctlsp_FormulaCreate(Ctlsp_E_c, $$, NIL(Ctlsp_Formula_t));
+		 Ctlsp_FormulaSetClass($$, Ctlsp_stateformula_c);
+		 if (Ctlsp_FormulaReadClassOfCTL($2) ==  Ctlsp_CTL_c)
+		   {
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_CTL_c);
+		   }
+		 else
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_NotCTL_c);
+		 CtlspGlobalFormula= $$;
+	       }
+	     | TOK_FORALL CTLsFormula
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_A_c, $2, NIL(Ctlsp_Formula_t));
+		 Ctlsp_FormulaSetClass($$, Ctlsp_stateformula_c);
+		 if (Ctlsp_FormulaReadClassOfCTL($2) ==  Ctlsp_PathCTL_c)
+		   {
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_CTL_c);
+		   }
+		 else
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_NotCTL_c);
+		 CtlspGlobalFormula= $$;
+	       }
+	     | TOK_FORALL_GLOBALLY CTLsFormula
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_G_c, $2, NIL(Ctlsp_Formula_t));
+		 Ctlsp_FormulaSetClass($$, table2(Ctlsp_FormulaReadClass($2)));
+		 $$ = Ctlsp_FormulaCreate(Ctlsp_A_c, $$, NIL(Ctlsp_Formula_t));
+		 Ctlsp_FormulaSetClass($$, Ctlsp_stateformula_c);
+		 if (Ctlsp_FormulaReadClassOfCTL($2) ==  Ctlsp_CTL_c)
+		   {
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_CTL_c);
+		   }
+		 else
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_NotCTL_c);
+		 CtlspGlobalFormula= $$;
+	       }
+	     | TOK_FORALL_NEXT CTLsFormula
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_X_c, $2, NIL(Ctlsp_Formula_t));
+		 Ctlsp_FormulaSetClass($$, table2(Ctlsp_FormulaReadClass($2)));
+		 $$ = Ctlsp_FormulaCreate(Ctlsp_A_c, $$, NIL(Ctlsp_Formula_t));
+		 Ctlsp_FormulaSetClass($$, Ctlsp_stateformula_c);
+		 if (Ctlsp_FormulaReadClassOfCTL($2) ==  Ctlsp_CTL_c)
+		   {
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_CTL_c);
+		   }
+		 else
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_NotCTL_c);
+		 CtlspGlobalFormula= $$;
+	       }
+	      | ax_mult '(' CTLsFormula ')'
+		 { $$ = Ctlsp_FormulaCreateAXMult($1, $3);
+		   if ($$ == NIL(Ctlsp_Formula_t)){
+		   CtlspYyerror("** ctl* error : MULTIPLE AX ERROR");
+		   (void) fprintf(vis_stderr,"Error during parsing line %d.\n\n", CtlspYylineno);
+		   Ctlsp_FormulaFree(CtlspGlobalFormula);
+		   }
+		   FREE($1);
+		   CtlspGlobalFormula= $$;
+	       }
+	     | TOK_FORALL_EVENTUALLY CTLsFormula
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_F_c, $2, NIL(Ctlsp_Formula_t));
+		 Ctlsp_FormulaSetClass($$, table2(Ctlsp_FormulaReadClass($2)));
+		 $$ = Ctlsp_FormulaCreate(Ctlsp_A_c, $$, NIL(Ctlsp_Formula_t));
+		 Ctlsp_FormulaSetClass($$, Ctlsp_stateformula_c);
+		 if (Ctlsp_FormulaReadClassOfCTL($2) ==  Ctlsp_CTL_c)
+		   {
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_CTL_c);
+		   }
+		 else
+		     Ctlsp_FormulaSetClassOfCTL($$, Ctlsp_NotCTL_c);
+		 CtlspGlobalFormula= $$;
+	       }
+	      | x_mult '(' CTLsFormula ')'
+		 { $$ = Ctlsp_FormulaCreateXMult($1, $3);
+		   if ($$ == NIL(Ctlsp_Formula_t)){
+		   CtlspYyerror("** ctl* error : MULTIPLE X ERROR");
+		   (void) fprintf(vis_stderr,"Error during parsing line %d.\n\n", CtlspYylineno);
+		   Ctlsp_FormulaFree(CtlspGlobalFormula);
+		   }
+		   FREE($1);
+		   CtlspGlobalFormula= $$;
+	       }
+	 ;
+
+propformula: '(' propformula ')'
+	       { $$ = $2;
+		 CtlspGlobalFormula= $$;
+	       }
+	     | name TOK_ASSIGN name
+	     { $$ = Ctlsp_FormulaCreate(Ctlsp_ID_c, $1, $3);
+	       CtlspGlobalFormula= $$;
+	     }
+	     | name TOK_ASSIGN name_union
+	     { $$ = Ctlsp_FormulaCreateOr($1, $3);
+	       FREE($1);
+	       FREE($3);
+	       CtlspGlobalFormula= $$;
+	     }
+	     | name_vector TOK_ASSIGN name
+	       { $$ = Ctlsp_FormulaCreateVectorAnd($1, $3);
+		 if ($$ == NIL(Ctlsp_Formula_t))
+		 {
+		  CtlspYyerror("** ctl error : Matching ERROR");
+		  (void) fprintf(vis_stderr,"LHS token is not matched to RHS token, line %d.\n\n", CtlspYylineno);
+		  Ctlsp_FormulaFree(CtlspGlobalFormula);
+		 }
+		 FREE($1);
+		 FREE($3);
+		 CtlspGlobalFormula= $$;
+	       }
+	     | name_vector TOK_ASSIGN name_union
+	       { $$ = Ctlsp_FormulaCreateVectorOr($1, $3);
+		if ($$ == NIL(Ctlsp_Formula_t)){
+		   CtlspYyerror("** ctl error : Matching ERROR");
+		   (void) fprintf(vis_stderr,"LHS token is not matched to RHS token, line %d\n\n", CtlspYylineno);
+		   Ctlsp_FormulaFree(CtlspGlobalFormula);
+		}
+		FREE($1);
+		FREE($3);
+		CtlspGlobalFormula= $$;
+	       }
+	     | name TOK_EQIV name
+	       { $$ = Ctlsp_FormulaCreateEquiv($1, $3);
+		 if ($$ == NIL(Ctlsp_Formula_t)){
+		   CtlspYyerror("** ctl error : Matching ERROR");
+		   (void) fprintf(vis_stderr,"LHS token is not matched to RHS token, line %d.\n\n", CtlspYylineno);
+		   Ctlsp_FormulaFree(CtlspGlobalFormula);
+		 }
+		 FREE($1);
+		 FREE($3);
+		 CtlspGlobalFormula= $$;
+	       }
+	     | name_vector TOK_EQIV name_vector
+	       { $$ = Ctlsp_FormulaCreateVectorEquiv($1, $3);
+		 FREE($1);
+		 FREE($3);
+		 CtlspGlobalFormula= $$;
+	       }
+	     | name TOK_ASSIGN TOK_FORALL
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_ID_c, $1, util_strsav("A"));
+		 CtlspGlobalFormula= $$;
+	       }
+	     | name TOK_ASSIGN TOK_EXISTS
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_ID_c, $1, util_strsav("E"));
+		 CtlspGlobalFormula= $$;
+	       }
+	     | name TOK_ASSIGN TOK_EVENTUALLY
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_ID_c, $1, util_strsav("F"));
+		 CtlspGlobalFormula= $$;
+	       }
+	     | name TOK_ASSIGN TOK_GLOBALLY
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_ID_c, $1, util_strsav("G"));
+		 CtlspGlobalFormula= $$;
+	       }
+	     | name TOK_ASSIGN TOK_NEXT
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_ID_c, $1, util_strsav("X"));
+		 CtlspGlobalFormula= $$;
+	       }
+	     | name TOK_ASSIGN TOK_UNTIL
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_ID_c, $1, util_strsav("U"));
+		 CtlspGlobalFormula= $$;
+	       }
+	     | name TOK_ASSIGN TOK_WEAK_UNTIL
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_ID_c, $1, util_strsav("W"));
+		 CtlspGlobalFormula= $$;
+	       }
+	     | name TOK_ASSIGN TOK_RELEASE
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_ID_c, $1, util_strsav("R"));
+		 CtlspGlobalFormula= $$;
+	       }
+	     | TOK_FORALL TOK_ASSIGN name
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_ID_c, util_strsav("A"), $3);
+		 CtlspGlobalFormula= $$;
+	       }
+	     | TOK_EXISTS TOK_ASSIGN name
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_ID_c, util_strsav("E"), $3);
+		 CtlspGlobalFormula= $$;
+	       }
+	     | TOK_EVENTUALLY TOK_ASSIGN name
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_ID_c, util_strsav("F"), $3);
+		 CtlspGlobalFormula= $$;
+	       }
+	     | TOK_GLOBALLY TOK_ASSIGN name
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_ID_c, util_strsav("G"), $3);
+		 CtlspGlobalFormula= $$;
+	       }
+	     | TOK_NEXT TOK_ASSIGN name
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_ID_c, util_strsav("X"), $3);
+		 CtlspGlobalFormula= $$;
+	       }
+	     | TOK_UNTIL TOK_ASSIGN name
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_ID_c, util_strsav("U"), $3);
+		 CtlspGlobalFormula= $$;
+	       }
+	     | TOK_WEAK_UNTIL TOK_ASSIGN name
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_ID_c, util_strsav("W"), $3);
+		 CtlspGlobalFormula= $$;
+	       }
+	     | TOK_RELEASE TOK_ASSIGN name
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_ID_c, util_strsav("R"), $3);
+		 CtlspGlobalFormula= $$;
+	       }
+	     | TOK_TRUE
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_TRUE_c, NIL(Ctlsp_Formula_t), NIL(Ctlsp_Formula_t));
+		 CtlspGlobalFormula= $$;
+	       }
+	     | TOK_FALSE
+	       { $$ = Ctlsp_FormulaCreate(Ctlsp_FALSE_c, NIL(Ctlsp_Formula_t), NIL(Ctlsp_Formula_t));
+		 CtlspGlobalFormula= $$;
+	       }
+	     | macro
+	       { $$ = CtlspFormulaFindInTable($1, CtlspMacroTable);
+		 if ($$ == NIL(Ctlsp_Formula_t)){
+		    CtlspYyerror("** ctl* error : Macro Error");
+		    (void) fprintf(vis_stderr,"Macro \"%s\" is not defined.\n\n",$1);
+		    FREE($1);
+		    CtlspGlobalFormula= $$;
+		    YYERROR;
+		 }
+		 FREE($1);
+		 CtlspGlobalFormula= $$;
+
+	       };
+
+name:  TOK_ID
+       { $$ = util_strsav(CtlspYytext); }
+     | TOK_ID2
+       { (void) CtlspChangeBracket(CtlspYytext);
+	 $$ = util_strsav(CtlspYytext); };
+name_vector: TOK_ID_VECTOR
+       { $$ = util_strsav(CtlspYytext); };
+
+name_union: '{' name_or '}'
+       { $$ = $2; };
+name_or: name
+       { $$ = $1; }
+      |  name_or TOK_COMMA name
+       { $$ = util_strcat3($1,",",$3);
+	 FREE($1);
+	 FREE($3);
+       }
+      ;
+
+macro: TOK_MACRO name
+       { $$ = $2; } ;
+
+x_mult: TOK_NEXT_MULT
+       { $$ = util_strsav(CtlspYytext); } ;
+
+ax_mult: TOK_FORALL_NEXT_MULT
+       { $$ = util_strsav(CtlspYytext); } ;
+
+ex_mult: TOK_EXISTS_NEXT_MULT
+       { $$ = util_strsav(CtlspYytext); } ;
+%%
Index: vis_dev/vis-2.3/src/ctlsp/ctlspCmd.c
===================================================================
--- vis_dev/vis-2.3/src/ctlsp/ctlspCmd.c	(revision 14)
+++ vis_dev/vis-2.3/src/ctlsp/ctlspCmd.c	(revision 14)
@@ -0,0 +1,474 @@
+/**CFile***********************************************************************
+
+  FileName    [ctlspCmd.c]
+
+  PackageName [ctlsp]
+
+  Synopsis    [Command to read in a file containing CTL* formulas.]
+
+  Author      [Mohammad Awedh]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "ctlspInt.h"
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandCtlspTest(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandLtlToSNF(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int FormulaArrayCountSubformulae(array_t *formulaArray);
+static void FormulaVisitUnvisitedSubformulae(Ctlsp_Formula_t *formula, int *ptr);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Initializes the CTL* parser package.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_End]
+
+******************************************************************************/
+void
+Ctlsp_Init(void)
+{
+  Cmd_CommandAdd("_ctlsp_test",   CommandCtlspTest,   0);
+  Cmd_CommandAdd("ltl2snf", CommandLtlToSNF, 0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Ends the CTL* parser package.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_Init]
+
+******************************************************************************/
+void
+Ctlsp_End(void)
+{
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Sets the field states in every subformula of CTL* formula
+  to NULL.]
+
+  Description [The function sets the field states in every subformula
+  of CTL* formula to NULL.]
+  
+  SideEffects []
+
+******************************************************************************/
+void
+CtlspFormulaSetStatesToNULL(
+  Ctlsp_Formula_t *formula)
+{
+  if(formula!=NIL(Ctlsp_Formula_t)) {
+    formula->states = NIL(mdd_t);
+    if(formula->type != Ctlsp_ID_c) {
+      CtlspFormulaSetStatesToNULL(formula->left);
+      CtlspFormulaSetStatesToNULL(formula->right);
+    }
+  }
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the _ctlsp_test command.]
+
+  Description [Implements the _ctlsp_test command.  This command is only meant to
+  test the CTL* command parser.]
+  
+  CommandName [_ctlsp_test]
+
+  CommandSynopsis [test the CTL* parser]
+
+  CommandArguments [\[-h\] &lt;file_name&gt;]
+  
+  CommandDescription [Test the CTL* parser.  If the entire file of CTL*
+  formulas is successfully parsed, then each formula is printed to
+  stdout, followed by the equivalent existential normal form formula.
+
+  The formulas read are not stored.  For the input file containing:
+  <pre> AG(foo=bar); </pre> the following is produced: <pre> original
+  formula: AG(foo=bar) => equivalent existential formula: !(E(TRUE U
+  !(foo=bar))) </pre> For the syntax of CTL formulas, refer to <A
+  HREF="../ctl/ctl/ctl.html"> the VIS CTL and LTL syntax manual</A>.
+
+  Command options:<p>  
+
+  <dl><dt> -h
+  <dd> Print the command usage.
+  </dl>
+  ]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandCtlspTest(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int     c;
+  int      i;
+  FILE    *fp;
+  array_t *formulaArray;
+  array_t *CtlformulaArray;
+  array_t *LTLformulaArray;
+
+  array_t *convertedArray;  /* in DAG format */
+
+  /*
+   * Parse command line options.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "h")) != EOF) {
+    switch(c) {
+      case 'h':
+        goto usage;
+      default:
+        goto usage;
+    }
+  }
+
+  /*
+   * Open the ctl file.
+   */
+  if (argc - util_optind == 0) {
+    (void) fprintf(vis_stderr, "** CTL* error: ctl* file not provided\n");
+    goto usage;
+  }
+  else if (argc - util_optind > 1) {
+    (void) fprintf(vis_stderr, "** CTL* error: too many arguments\n");
+    goto usage;
+  }
+
+  fp = Cmd_FileOpen(argv[util_optind], "r", NIL(char *), 0);
+  if (fp == NIL(FILE)) {
+    (void)fprintf(vis_stderr, "** CTL* error: Cannot open the file %s\n", argv[util_optind]);
+    return 1;
+  }
+
+  /*
+   * Parse the CTL* formulas in the file.
+   */
+  formulaArray = Ctlsp_FileParseFormulaArray(fp);
+  (void) fclose(fp);
+
+  if (formulaArray == NIL(array_t)) {
+    fflush(vis_stdout);
+    fflush(vis_stderr);
+    return 1;
+  }
+
+
+  convertedArray = Ctlsp_FormulaArrayConvertToDAG(formulaArray);
+  /*  array_free(formulaArray); */
+
+  /*
+   * Print each original formula and its corresponding converted formula.
+   */
+  for (i = 0; i < array_n(convertedArray); i++) {
+    Ctlsp_Formula_t *formula;
+
+    formula = array_fetch(Ctlsp_Formula_t *, convertedArray, i);
+    (void) fprintf(vis_stdout, "original formula: ");
+    Ctlsp_FormulaPrint(vis_stdout, formula);
+    
+    (void) fprintf(vis_stdout, " [CTL* ");
+
+    if (Ctlsp_isCtlFormula(formula)){
+       (void) fprintf(vis_stdout, ",CTL ");
+    }
+
+    if (Ctlsp_isLtlFormula(formula)){
+       (void) fprintf(vis_stdout, ",LTL ");
+    }
+   
+    (void) fprintf(vis_stdout, "]\n");
+
+  }
+ 
+  (void)fprintf(vis_stdout, "No. of subformulae (including formulae) = %d\n",
+                FormulaArrayCountSubformulae(convertedArray));
+
+  /* Converts array of CTL* formula to CTL */
+  CtlformulaArray = Ctlsp_FormulaArrayConvertToCTL(formulaArray);
+  if (CtlformulaArray !=  NIL(array_t)){
+    for (i = 0; i < array_n(CtlformulaArray); i++) { 
+      Ctlp_Formula_t *newFormula;
+
+      newFormula = array_fetch(Ctlp_Formula_t *, CtlformulaArray, i);
+      (void) fprintf(vis_stdout, "CTL formula: ");
+      Ctlp_FormulaPrint(vis_stdout, newFormula);
+      (void) fprintf(vis_stdout, "\n");
+      
+    }
+  array_free(CtlformulaArray);
+  }
+
+  LTLformulaArray = Ctlsp_FormulaArrayConvertToLTL(formulaArray);
+  if (LTLformulaArray !=  NIL(array_t)){
+    for (i = 0; i < array_n(LTLformulaArray); i++) { 
+      Ctlsp_Formula_t *newFormula;
+
+      newFormula = array_fetch(Ctlsp_Formula_t *, LTLformulaArray, i);
+      (void) fprintf(vis_stdout, "LTL formula: ");
+      Ctlsp_FormulaPrint(vis_stdout, newFormula);
+      (void) fprintf(vis_stdout, "\n");
+      
+    }
+  array_free(LTLformulaArray);
+  } else {
+   (void) fprintf(vis_stdout, "No LTL \n");
+  }
+
+  array_free(formulaArray);
+  Ctlsp_FormulaArrayFree(convertedArray);
+
+  fflush(vis_stdout);
+  fflush(vis_stderr);
+
+  return 0;		/* normal exit */
+
+usage:
+  (void) fprintf(vis_stderr, "usage: _ctlsp_test file [-h]\n");
+  (void) fprintf(vis_stderr, "   -h  print the command usage\n");
+  return 1;		/* error exit */
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the ltl2snf command.]
+
+  Description [Implements the ltl2snf command.]
+  
+  CommandName [ltl2snf]
+
+  CommandSynopsis [Trnalate LTL formula into Separated Normal Form.]
+
+  CommandArguments [\[-h\] &lt;file_name&gt;]
+  
+  CommandDescription [
+
+  Command options:
+  <p>  
+  <dl>
+  
+  <dt> -f <code> &lt;ltl_file&gt; </code>
+  <dd> The input file containing LTL formulae.
+
+  <dt> -n
+  <dd> Negate the formulae.
+
+  <dt> -h
+  <dd> Print the command usage.
+  
+  </dl>
+  ]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandLtlToSNF(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int     c, i;
+  FILE    *fp;
+  array_t *formulaArray;
+  array_t *LTLformulaArray;
+  char    *ltlFileName = (char *)0;
+  int     negateFormula = 0;
+
+  /*
+   * Parse command line options.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "hf:n")) != EOF) {
+    switch(c) {
+      case 'h':
+        goto usage;
+    case 'f':
+      ltlFileName = util_strsav(util_optarg);
+      break;
+    case 'n':
+      negateFormula = 1;
+      break;
+    default:
+      goto usage;
+    }
+  }
+  if (!ltlFileName){
+    (void) fprintf(vis_stderr, "** ltl2snf error: ltl file not provided\n");
+    goto usage;
+  }
+  fp = Cmd_FileOpen(ltlFileName, "r", NIL(char *), 0);
+  FREE(ltlFileName);
+  if (fp == NIL(FILE)) {
+    (void) fprintf(vis_stdout,  "** ltl2snf error: error in opening file %s\n", ltlFileName);
+    return 1;
+  }
+  /*
+   * Parse the CTL* formulas in the file.
+   */
+  formulaArray = Ctlsp_FileParseFormulaArray(fp);
+  (void) fclose(fp);
+
+  if (formulaArray == NIL(array_t)) {
+    fflush(vis_stdout);
+    fflush(vis_stderr);
+    return 1;
+  }
+
+  LTLformulaArray = Ctlsp_FormulaArrayConvertToLTL(formulaArray);
+  if (LTLformulaArray !=  NIL(array_t)){
+    for (i = 0; i < array_n(LTLformulaArray); i++) { 
+      Ctlsp_Formula_t *newFormula;
+
+      newFormula = array_fetch(Ctlsp_Formula_t *, LTLformulaArray, i);
+      (void) fprintf(vis_stdout, "LTL formula: ");
+      Ctlsp_FormulaPrint(vis_stdout, newFormula);
+      (void) fprintf(vis_stdout, "\n");
+
+      if(negateFormula){
+	newFormula = Ctlsp_LtllFormulaNegate(newFormula);
+	
+	(void) fprintf(vis_stdout, "Negated LTL formula: ");
+	Ctlsp_FormulaPrint(vis_stdout, newFormula);
+	(void) fprintf(vis_stdout, "\n");
+      }
+      
+      printf("SNF \n");
+      Ctlsp_LtlTranslateIntoSNF(newFormula);
+    }
+  array_free(LTLformulaArray);
+  } else {
+    (void) fprintf(vis_stdout, "No LTL \n");
+  }
+
+  array_free(formulaArray);
+
+  fflush(vis_stdout);
+  fflush(vis_stderr);
+
+  return 0;		/* normal exit */
+
+usage:
+  (void) fprintf(vis_stderr, "usage: ltl2snf  <-f ltl_file> [-h]\n");
+  (void) fprintf(vis_stderr, "   -f <ltl_file>\n");
+  (void) fprintf(vis_stderr, "   -n  negate formula\n");
+  (void) fprintf(vis_stderr, "   -h  print the command usage\n");
+  return 1;		/* error exit */
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of subformulae in formulaArray.]
+
+  Description [The function counts the number of subformulae in formulaArray
+  (including the formulae themselves) by traversing the DAG. It uses the field
+  states in Ctlsp_Formula_t to mark the visited states.]
+  
+  SideEffects [The field states is set to 1.]
+
+******************************************************************************/
+static int
+FormulaArrayCountSubformulae(
+  array_t *formulaArray)
+{
+  int num, i;
+  Ctlsp_Formula_t *formula;
+  int count = 0;
+  
+  num = array_n(formulaArray);
+  for(i=0; i<num; i++){
+    formula = array_fetch(Ctlsp_Formula_t *, formulaArray, i);
+    FormulaVisitUnvisitedSubformulae(formula, &count);
+  }
+  /* Set the field states to NULL */
+  for(i=0; i<num; i++){
+    formula = array_fetch(Ctlsp_Formula_t *, formulaArray, i);
+    CtlspFormulaSetStatesToNULL(formula);
+  }
+  return count;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Visits each unvisited subformula of formula.]
+
+  Description [The formula visits each unvisited subformula of formula and
+  increments *ptr by 1 each time. It also marks each of those as visited.]
+  
+  SideEffects []
+
+******************************************************************************/
+static void
+FormulaVisitUnvisitedSubformulae(
+  Ctlsp_Formula_t *formula,
+  int *ptr)
+{
+  if(formula!=NIL(Ctlsp_Formula_t)) {
+    if(formula->states == NIL(mdd_t)) {
+      (*ptr)++;
+      formula->states = (mdd_t *) 1;
+      if(formula->type != Ctlsp_ID_c) {
+        FormulaVisitUnvisitedSubformulae(formula->left, ptr);
+        FormulaVisitUnvisitedSubformulae(formula->right, ptr);
+      }
+    }
+  }
+}
+
+
+  
+  
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/ctlsp/ctlspInt.h
===================================================================
--- vis_dev/vis-2.3/src/ctlsp/ctlspInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/ctlsp/ctlspInt.h	(revision 14)
@@ -0,0 +1,277 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [ctlspInt.h]
+
+  PackageName [ctlsp]
+
+  Synopsis    [Declarations for internal use.]
+
+  Author      [Mohammad Awedh]
+
+  Copyright   [Copyright (c) 2000-2001 The Regents of the Univ. of Colorado
+  at Boulder. All rights reserved. 
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF COLORADO BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF COLORADO SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: ctlspInt.h,v 1.8 2004/09/15 20:06:29 awedh Exp $]
+
+******************************************************************************/
+
+#ifndef _CTLSPINT
+#define _CTLSPINT
+
+#define MAX_LENGTH_OF_VAR_NAME 512 
+
+#include <string.h>
+#include "ctlsp.h"
+#include "hrc.h"
+#include "cmd.h"
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [Tree representing a CTL formula.]
+
+  Description [Data structure for a CTL formula.  A formula is a tree
+  or a one-rooted DAG.  An internal vertex has one or two children,
+  depending on the operator type: if the operator takes just one
+  argument, then the left child holds the subformula, and the right
+  child is NULL; if the operator takes two arguments, then both
+  children are non-NULL.
+  
+  <p>A leaf is either a pair of a variable name in the network and a
+  value, TRUE or FALSE.  The left and right fields are used in leaf
+  vertices only in the first case above. (The left child holds a
+  variable name while the right child holds a value. Note that these
+  two fields are used differently in internal vertices and leaves.)
+
+  DbgInfo is an uninterpreted pointer used by the CTL debugger
+  to store information needed to debug a formula.
+
+  States holds the exact satisfying set of a formula in some fsm (that
+  is not stored along with the set).  Under- and overapprox are
+  approximations of states, and either states is NIL, or both
+  underapprox and overapprox are.  ]
+
+******************************************************************************/
+struct CtlspFormulaStruct {
+  Ctlsp_FormulaType type;
+  Ctlsp_Formula_t *left;   /* left child in formula */
+  Ctlsp_Formula_t *right;  /* right child, or null if not used */
+  int refCount;           /* number of formulas referring to this
+			     formula as a left or right child */
+  mdd_t	*states;          /* set of states satifying formula */
+  mdd_t *underapprox;     /* Underapproximation of states (for hints) */
+  mdd_t *overapprox;      /* overapprox for hints */
+  
+  struct {
+    void *data;           /* used  to store information used by debugger */
+    Ctlsp_DbgInfoFreeFn freeFn;         /* free function for data */
+    boolean convertedFlag;  /* was converted to existential form
+                                           by non-trivial transformation */
+    Ctlsp_Formula_t *originalFormula; /* pointer to formula from which this
+                                           was converted */
+  } dbgInfo;
+  /*
+  ** The following fields are added for forward model checking.
+  */
+  short top; /* 0 : , 1 : forward */
+  short compareValue; /* 0 : = false, 1 : != false */
+  /*
+  ** The following field is added to specify the Class of the Node
+   */
+  Ctlsp_ClassOfFormula class_;
+  /*
+  ** The following field is added to specify weather the sub-formula is CTL or not. 
+   */
+  Ctlsp_ClassOfCTLFormula CTLclass;
+
+    /* The following fields are for LTL->AUT */
+    int  ab_idx;
+    int  label_idx;
+    char rhs;
+    char marked;
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**Variable********************************************************************
+
+  Synopsis    [Global flag for parsing CTL file.]
+
+  Description [This flag is set to 0 before parsing a CTL file commences.  If
+  an error is found while parsing the file, this flag is set to 1.  After the
+  parser returns, if this flag is set, then the global CTL formula array is
+  freed.]
+
+******************************************************************************/
+extern int CtlspGlobalError;
+
+/**Variable********************************************************************
+
+  Synopsis    [Global pointer to the CTL formulas being created.]
+
+  Description [This pointer is always set to the current formula
+  so that the parser can free a partially constructed CTL formula
+  when an error is detected. Every time the parser starts reasing
+  a new formula, this variable is set to NIL(Ctlsp_Fromula_t).]
+
+******************************************************************************/
+extern Ctlsp_Formula_t *CtlspGlobalFormula;
+
+/**Variable********************************************************************
+
+  Synopsis    [Global pointer to the macro table of formulae]
+
+  Description [This pointer is always set to the macro table so that 
+  the parser can substitute macro string with defined formula]
+
+******************************************************************************/
+extern st_table *CtlspMacroTable;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**Macro***********************************************************************
+
+  Synopsis     [Determine the class of a binary operator CTL* node given the 
+               class of its children (x, y)]
+
+  Description  [This macro determine the class of a binary operator CTL* node
+               given the class of its children (x, y).
+
+                       prop  LTL  state  path
+               -------------------------------
+               prop  | prop  LTL  state  path
+               LTL   |       LTL  path   path
+               state |            state  path
+               path  |                   path
+
+
+               ]
+
+  SideEffects  []
+
+  SeeAlso      []
+
+******************************************************************************/
+#define table1(\
+  x,\
+  y\
+)\
+  ((Ctlsp_ClassOfFormula)  ((x) | (y)) ) 
+
+/**Macro***********************************************************************
+
+  Synopsis     [Determine the class of a uniry operator CTL* node given the 
+               class of its childn (x)]
+
+  Description  [This macro determine the class of a uniry operator CTL* node
+               given the class of its child (x).
+
+               prop  LTL  state  path
+               ----------------------
+               LTL   LTL  path   path
+
+               ]
+
+  SideEffects  []
+
+  SeeAlso      []
+
+******************************************************************************/
+#define table2(     \
+  x                 \
+)                   \
+  ((Ctlsp_ClassOfFormula)  ((x) |  Ctlsp_LTLformula_c) )
+
+/**Macro***********************************************************************
+
+  Synopsis     [Determine the class of a binary Temporal operator CTL* node 
+               given the class of its children (x, y)]
+
+  Description  [This macro determine the class of a Binary Temporal  operator CTL* node
+               given the class of its children (x, y).
+
+                       prop  LTL  state  path
+               -------------------------------
+               prop  | LTL   LTL  path  path
+               LTL   |       LTL  path  path
+               state |            path  path
+               path  |                  path
+
+
+               ]
+
+  SideEffects  []
+
+  SeeAlso      []
+
+******************************************************************************/
+#define table3(\
+  x,\
+  y\
+)\
+  ((Ctlsp_ClassOfFormula)  ((x) | (y) |  Ctlsp_LTLformula_c) )
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void CtlspFormulaSetStatesToNULL(Ctlsp_Formula_t *formula);
+EXTERN Ctlsp_Formula_t * CtlspLtlFormulaSimpleRewriting_Aux(Ctlsp_Formula_t *F, st_table *Utable);
+EXTERN void CtlspFormulaIncrementRefCount(Ctlsp_Formula_t *formula);
+EXTERN void CtlspFormulaDecrementRefCount(Ctlsp_Formula_t *formula);
+EXTERN void CtlspFormulaAddToGlobalArray(Ctlsp_Formula_t * formula);
+EXTERN void CtlspFormulaFree(Ctlsp_Formula_t * formula);
+EXTERN int CtlspStringChangeValueStrToBinString(char *value, char *binValueStr, int interval);
+EXTERN void CtlspChangeBracket(char *inStr);
+EXTERN char * CtlspGetVectorInfoFromStr(char *str, int *start, int *end, int *interval, int *inc);
+EXTERN int CtlspFormulaAddToTable(char *name, Ctlsp_Formula_t *formula, st_table *macroTable);
+EXTERN Ctlsp_Formula_t * CtlspFormulaFindInTable(char *name, st_table *macroTable);
+EXTERN Ctlsp_FormulaClass CtlspCheckClassOfExistentialFormulaRecur(Ctlsp_Formula_t *formula, boolean parity);
+EXTERN Ctlsp_FormulaClass CtlspResolveClass(Ctlsp_FormulaClass class1, Ctlsp_FormulaClass class2);
+EXTERN Ctlp_Formula_t * CtlspFormulaConvertToCTL(Ctlsp_Formula_t *formula);
+EXTERN Ctlsp_Formula_t * CtlspFunctionOr(Ctlsp_Formula_t *left, Ctlsp_Formula_t *right);
+EXTERN Ctlsp_Formula_t * CtlspFunctionAnd(Ctlsp_Formula_t *left, Ctlsp_Formula_t *right);
+EXTERN Ctlsp_Formula_t * CtlspFunctionThen(Ctlsp_Formula_t *left, Ctlsp_Formula_t *right);
+
+/**AutomaticEnd***************************************************************/
+
+EXTERN void CtlspFileSetup(FILE *fp);  /* lives in a .l file, so not
+                                                automatically generated */
+EXTERN int CtlspYyparse(void);
+#endif /* _CTLSPINT */
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/ctlsp/ctlspUtil.c
===================================================================
--- vis_dev/vis-2.3/src/ctlsp/ctlspUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/ctlsp/ctlspUtil.c	(revision 14)
@@ -0,0 +1,5447 @@
+/**CFile***********************************************************************
+
+  FileName    [ctlspUtil.c]
+
+  PackageName [ctlsp]
+
+  Synopsis    [Routines for manipulating CTL* formulas.]
+
+  Description [This file contains routines for accessing the fields of the CTL*
+  formula data structure, for printing CTL* formulas, for reading CTL* formulas
+  from a file, and for converting formulas to the existential form.]
+
+  Author      [Mohammad Awedh, Chao Wang]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "ctlspInt.h"
+#include "errno.h"
+#include "ntk.h"
+
+static char rcsid[] UNUSED = "$Id: ctlspUtil.c,v 1.64 2009/04/11 18:25:55 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**Variable********************************************************************
+
+  Synopsis    [Array of CTL* formulas (Ctlsp_Formula_t) read from a file.]
+
+  SeeAlso     [Ctlsp_FormulaArrayFree]
+
+******************************************************************************/
+static array_t *globalFormulaArray;
+static int	changeBracket = 1;
+
+/* see ctlspInt.h for documentation */
+int CtlspGlobalError;
+Ctlsp_Formula_t *CtlspGlobalFormula;
+st_table *CtlspMacroTable;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static Ctlsp_Formula_t * FormulaCreateWithType(Ctlsp_FormulaType type);
+static int FormulaCompare(const char *key1, const char *key2);
+static int FormulaHash(char *key, int modulus);
+static Ctlsp_Formula_t * FormulaHashIntoUniqueTable(Ctlsp_Formula_t *formula, st_table *uniqueTable);
+static Ctlsp_Formula_t * createSNFnode(Ctlsp_Formula_t *formula, array_t *formulaArray, int *index);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Parses a file containing a set of CTL* formulas.]
+
+  Description [Parses a file containing a set of semicolon-ending CTL*
+  formulas, and returns an array of Ctlsp_Formula_t representing those
+  formulas.  If an error is detected while parsing the file, the routine frees
+  any allocated memory and returns NULL.]
+
+  SideEffects [Manipulates the global variables globalFormulaArray,
+  CtlspGlobalError and CtlspGlobalFormula.]
+
+  SeeAlso     [Ctlsp_FormulaArrayFree Ctlsp_FormulaPrint]
+
+******************************************************************************/
+array_t *
+Ctlsp_FileParseFormulaArray(
+  FILE * fp)
+{
+  st_generator *stGen;
+  char *name;
+  Ctlsp_Formula_t *formula;
+  char *flagValue;
+  /*
+   * Initialize the global variables.
+   */
+  globalFormulaArray = array_alloc(Ctlsp_Formula_t *, 0);
+  CtlspGlobalError = 0;
+  CtlspGlobalFormula = NIL(Ctlsp_Formula_t);
+  CtlspMacroTable = st_init_table(strcmp,st_strhash);
+  CtlspFileSetup(fp);
+  /*
+   * Check if changing "[] -> <>" is disabled.
+   */
+  flagValue = Cmd_FlagReadByName("ctl_change_bracket");
+  if (flagValue != NIL(char)) {
+    if (strcmp(flagValue, "yes") == 0)
+      changeBracket = 1;
+    else if (strcmp(flagValue, "no") == 0)
+      changeBracket = 0;
+    else {
+      fprintf(vis_stderr,
+	"** ctl error : invalid value %s for ctl_change_bracket[yes/no]. ***\n",
+	flagValue);
+    }
+  }
+
+  (void)CtlspYyparse();
+  st_foreach_item(CtlspMacroTable,stGen,&name, &formula){
+     FREE(name);
+     CtlspFormulaFree(formula);
+  }
+  st_free_table(CtlspMacroTable);
+
+  /*
+   * Clean up if there was an error, otherwise return the array.
+   */
+  if (CtlspGlobalError){
+    Ctlsp_FormulaArrayFree(globalFormulaArray);
+    return NIL(array_t);
+  }
+  else {
+    return globalFormulaArray;
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Parses a file containing a set of CTL formulas.]
+
+  Description [Parses a file containing a set of semicolon-terminated CTL
+  formulae, and returns an array of Ctlp_Formula_t representing those
+  formulae.  If an error is detected while parsing the file, the routine frees
+  any allocated memory and returns NULL.]
+
+  SideEffects [Manipulates the global variables globalFormulaArray,
+  CtlspGlobalError and CtlspGlobalFormula.]
+
+  SeeAlso     [Ctlsp_FileParseFormulaArray]
+
+******************************************************************************/
+array_t *
+Ctlsp_FileParseCTLFormulaArray(
+  FILE *fp)
+{
+  array_t *ctlsArray = Ctlsp_FileParseFormulaArray(fp);
+  array_t *ctlArray;
+
+  if (ctlsArray == NIL(array_t)) return NIL(array_t);
+  ctlArray = Ctlsp_FormulaArrayConvertToCTL(ctlsArray);
+  Ctlsp_FormulaArrayFree(ctlsArray);
+  return ctlArray;
+  
+} /* Ctlsp_FileParseCTLFormulaArray */
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a character string represents the CTL* formula]
+
+  Description [Returns formula as a character string. All subformulas are
+  delimited by parenthesis. Does nothing if passed a NULL formula.]
+
+  SideEffects []
+
+******************************************************************************/
+char *
+Ctlsp_FormulaConvertToString(
+  Ctlsp_Formula_t * formula)
+{
+  char *s1        = NIL(char);
+  char *s2        = NIL(char);
+  char *tmpString = NIL(char);
+  char *result;
+
+
+  if (formula == NIL(Ctlsp_Formula_t)) {
+    return NIL(char);
+  }
+
+  /* leaf node */
+  if (formula->type == Ctlsp_ID_c){
+  result = util_strcat3((char *)(formula->left), "=",(char *)(formula->right));
+  /*
+  tmpString = util_strcat3("[", util_inttostr(formula->CTLclass),"]");
+  return util_strcat3(result, " ",tmpString);
+  */
+  return result;
+  }
+
+  /* If the formula is a non-leaf, the function is called recursively */
+  s1 = Ctlsp_FormulaConvertToString(formula->left);
+  s2 = Ctlsp_FormulaConvertToString(formula->right);
+
+  switch(formula->type) {
+    /*
+     * The cases are listed in rough order of their expected frequency.
+     */
+    case Ctlsp_OR_c:
+      tmpString = util_strcat3(s1, " + ",s2);
+      result    = util_strcat3("(", tmpString, ")");
+      break;
+    case Ctlsp_AND_c:
+      tmpString = util_strcat3(s1, " * ", s2);
+      result    = util_strcat3("(", tmpString, ")");
+      break;
+    case Ctlsp_THEN_c:
+      tmpString = util_strcat3(s1, " -> ", s2);
+      result    = util_strcat3("(", tmpString, ")");
+      break;
+    case Ctlsp_XOR_c:
+      tmpString = util_strcat3(s1, " ^ ", s2);
+      result    = util_strcat3("(", tmpString, ")");
+      break;
+    case Ctlsp_EQ_c:
+      tmpString = util_strcat3(s1, " <-> ", s2);
+      result    = util_strcat3("(", tmpString, ")");
+      break;
+    case Ctlsp_NOT_c:
+      tmpString = util_strcat3("(", s1, ")");
+      result    = util_strcat3("!", tmpString, "");
+      break;
+    case Ctlsp_E_c:
+      result = util_strcat3("E(", s1, ")");
+      FREE(s1);
+      break;
+    case Ctlsp_G_c:
+      result = util_strcat3("G(", s1, ")");
+      break;
+    case Ctlsp_F_c:
+      result = util_strcat3("F(", s1, ")");
+      break;
+    case Ctlsp_U_c:
+      tmpString = util_strcat3("(", s1, " U ");
+      result    = util_strcat3(tmpString, s2, ")");
+      break;
+    case Ctlsp_R_c:
+      tmpString = util_strcat3("(", s1, " R ");
+      result    = util_strcat3(tmpString, s2, ")");
+      break;
+    case Ctlsp_W_c:
+      tmpString = util_strcat3("(", s1, " W ");
+      result    = util_strcat3(tmpString, s2, ")");
+      break;
+    case Ctlsp_X_c:
+      result = util_strcat3("X(", s1, ")");
+      break;
+    case Ctlsp_A_c:
+      result = util_strcat3("A(", s1, ")");
+      break;;
+    case Ctlsp_TRUE_c:
+      result = util_strsav("TRUE");
+      break;
+    case Ctlsp_FALSE_c:
+      result = util_strsav("FALSE");
+      break;
+    case Ctlsp_Init_c:
+      result = util_strsav("Init");
+      break;
+    case Ctlsp_Cmp_c:
+      if (formula->compareValue == 0)
+	tmpString = util_strcat3("[", s1, "] = ");
+      else
+	tmpString = util_strcat3("[", s1, "] != ");
+      result    = util_strcat3(tmpString, s2, "");
+      break;
+    case Ctlsp_Fwd_c:
+      tmpString = util_strcat3("FwdG(", s1, ",");
+      result    = util_strcat3(tmpString, s2, ")");
+      break;
+      /*   case Ctlsp_EY_c:
+      result = util_strcat3("EY(", s1, ")");
+      break;*/
+    default:
+      fail("Unexpected type");
+
+  }
+  if (s1 != NIL(char)) {
+    FREE(s1);
+  }
+  if (s2 != NIL(char)) {
+    FREE(s2);
+  }
+  if (tmpString != NIL(char)) {
+    FREE(tmpString);
+  }
+
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints a formula to a file.]
+
+  Description [Prints a formula to a file. All subformulas are delimited by
+  parenthesis. The syntax used is the same as used by the CTL* parser.  Does
+  nothing if passed a NULL formula.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Ctlsp_FormulaPrint(
+  FILE * fp,
+  Ctlsp_Formula_t * formula)
+{
+  char *tmpString;
+  if (formula == NIL(Ctlsp_Formula_t)) {
+    return;
+  }
+  tmpString = Ctlsp_FormulaConvertToString(formula);
+  (void) fprintf(fp, "%s", tmpString);
+  FREE(tmpString);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the type of a formula.]
+
+  Description [Gets the type of a formula. See ctlsp.h for all the types. It is
+  an error to call this function on a NULL formula.]
+
+  SideEffects []
+
+  SeeAlso     [ctlsp.h]
+
+******************************************************************************/
+Ctlsp_FormulaType
+Ctlsp_FormulaReadType(
+  Ctlsp_Formula_t * formula)
+{
+  return (formula->type);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the compare value of a formula.]
+
+  Description [Gets the compare value of a formula. See ctlsp.h for all the
+  types. It is an error to call this function on a NULL formula.]
+
+  SideEffects []
+
+  SeeAlso     [ctlsp.h]
+
+******************************************************************************/
+int
+Ctlsp_FormulaReadCompareValue(
+  Ctlsp_Formula_t * formula)
+{
+  int value;
+  value = formula->compareValue;
+  return (value);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the variable name of a leaf formula.]
+
+  Description [Reads the variable name of a leaf formula.
+  It is an error to call this function on a non-leaf formula.]
+
+  SideEffects []
+
+******************************************************************************/
+char *
+Ctlsp_FormulaReadVariableName(
+  Ctlsp_Formula_t * formula)
+{
+  if (formula->type != Ctlsp_ID_c){
+    fail("Ctlsp_FormulaReadVariableName() was called on a non-leaf formula.");
+  }
+  return ((char *)(formula->left));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the value name of a leaf formula.]
+
+  Description [Reads the value name of a leaf formula.
+  It is an error to call this function on a non-leaf formula.]
+
+  SideEffects []
+
+******************************************************************************/
+char *
+Ctlsp_FormulaReadValueName(
+  Ctlsp_Formula_t * formula)
+{
+  if (formula->type != Ctlsp_ID_c){
+    fail("Ctlsp_FormulaReadValueName() was called on a non-leaf formula.");
+  }
+  return ((char *)(formula->right));
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the left child of a formula.]
+
+  Description [Gets the left child of a formula.  User must not free this
+  formula. If a formula is a leaf formula, NIL(Ctlsp_Formula_t) is returned.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_FormulaReadRightChild]
+
+******************************************************************************/
+Ctlsp_Formula_t *
+Ctlsp_FormulaReadLeftChild(
+  Ctlsp_Formula_t * formula)
+{
+  if (formula->type != Ctlsp_ID_c){
+    return (formula->left);
+  }
+  return NIL(Ctlsp_Formula_t);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the right child of a formula.]
+
+  Description [Gets the right child of a formula.  User must not free this
+  formula. If a formula is a leaf formula, NIL(Ctlsp_Formula_t) is returned.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_FormulaReadLeftChild]
+
+******************************************************************************/
+Ctlsp_Formula_t *
+Ctlsp_FormulaReadRightChild(
+  Ctlsp_Formula_t * formula)
+{
+  if (formula->type != Ctlsp_ID_c){
+    return (formula->right);
+  }
+  return NIL(Ctlsp_Formula_t);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Gets a copy of the set of states for which this formula is
+  true.]
+
+  Description [Gets a copy of the MDD representing the set of states for which
+  this formula is true.  It is the user's responsibility to free this MDD. If
+  the set of states has not yet been computed, then a NULL mdd_t is
+  returned. It is an error to call this function on a NULL formula.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_FormulaSetStates]
+
+******************************************************************************/
+mdd_t *
+Ctlsp_FormulaObtainStates(
+  Ctlsp_Formula_t * formula)
+{
+  if (formula->states == NIL(mdd_t)) {
+    return NIL(mdd_t);
+  }
+  else {
+    return mdd_dup(formula->states);
+  }
+}
+/**Function********************************************************************
+
+  Synopsis [Gets (a copy of) an approximation of the satisfying set]
+
+  Description [Gets the required approximation of the satisfying set.  If the
+  exact set is available, it will return that.  If neither is available, or
+  approx is Ctlsp_Incomparable_c, it will return NULL.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_FormulaSetStates]
+
+******************************************************************************/
+mdd_t *
+Ctlsp_FormulaObtainApproxStates(
+  Ctlsp_Formula_t *formula,
+  Ctlsp_Approx_t approx)
+{
+  if(approx == Ctlsp_Incomparable_c)
+    return NIL(mdd_t);
+
+  if (formula->states != NIL(mdd_t))
+    return mdd_dup(formula->states);
+
+  if(approx == Ctlsp_Exact_c)
+    return NIL(mdd_t);
+
+  if(approx == Ctlsp_Overapprox_c){
+    if(formula->overapprox == NIL(mdd_t))
+      return NIL(mdd_t);
+    else
+      return mdd_dup(formula->overapprox);
+  }
+
+  if(approx == Ctlsp_Underapprox_c){
+    if(formula->underapprox == NIL(mdd_t))
+      return NIL(mdd_t);
+    else
+      return mdd_dup(formula->underapprox);
+  }
+
+  assert(0);  /* we should never get here */
+  return NIL(mdd_t);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Stores the set of states with the formula.]
+
+  Description [Stores the MDD with the formula (a copy is not made,
+  and hence, the caller should not later free this MDD). This MDD is
+  intended to represent the set of states for which the formula is
+  true. It is an error to call this function on a NULL formula.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_FormulaObtainStates]
+
+******************************************************************************/
+void
+Ctlsp_FormulaSetStates(
+  Ctlsp_Formula_t * formula,
+  mdd_t * states)
+{
+  /* RB: added the next two lines.  Given the Description, this was a
+     bug */
+    if(formula->states != NIL(mdd_t))
+      mdd_free(formula->states);
+    formula->states = states;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Stores (an approximation of) the set of states with the
+  formula.]
+
+  Description [Sets the set of states or an under or overapproximation thereof,
+  depending on the approx flag.  If there is already an under or
+  overapproximation, it is overwritten.  If the exact set is given, the approx
+  fields are cleared.  Setting an incomparable approximation results in no
+  action being taken.  A copy of the bdd is not made, so the caller should not
+  free it.  ]
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_FormulaObtainStates]
+
+******************************************************************************/
+void
+Ctlsp_FormulaSetApproxStates(
+  Ctlsp_Formula_t * formula,
+  mdd_t * states,
+  Ctlsp_Approx_t approx)
+{
+  if(approx == Ctlsp_Incomparable_c){
+    mdd_free(states);
+    return;
+  }
+
+  if(approx == Ctlsp_Exact_c){
+    if(formula->states != NIL(mdd_t))
+      mdd_free(formula->states);
+    formula->states = states;
+
+    if(formula->underapprox != NIL(mdd_t)){
+      mdd_free(formula->underapprox);
+      formula->underapprox = NIL(mdd_t);
+    }
+
+    if(formula->overapprox != NIL(mdd_t)){
+      mdd_free(formula->overapprox);
+      formula->overapprox = NIL(mdd_t);
+    }
+  }
+
+  if( approx == Ctlsp_Underapprox_c){
+    /* you could perform a union instead, but typical use will
+       have monotonically increasing underapproximations */
+    if(formula->underapprox != NIL(mdd_t))
+      mdd_free(formula->underapprox);
+    formula->underapprox = states;
+  }
+
+  if( approx == Ctlsp_Overapprox_c){
+    /* you could perform an intersaection instead */
+    if(formula->overapprox != NIL(mdd_t))
+      mdd_free(formula->overapprox);
+    formula->overapprox = states;
+  }
+
+  return;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the debug information of a formula.]
+
+  Description [Sets the debug information of a CTL formula.  The data is
+  uninterpreted.  FreeFn is a pointer to a function that takes a formula as
+  input and returns void.  FreeFn should free all the memory associated with
+  the debug data; it is called when this formula is freed.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_FormulaReadDebugData]
+
+******************************************************************************/
+void
+Ctlsp_FormulaSetDbgInfo(
+  Ctlsp_Formula_t * formula,
+  void *data,
+  Ctlsp_DbgInfoFreeFn freeFn)
+{
+  formula->dbgInfo.data   = data;
+  formula->dbgInfo.freeFn = freeFn;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the debug data associated with a formula.]
+
+  Description [Returns the debug data associated with a formula.  This data is
+  uninterpreted by the ctlsp package.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_FormulaSetDbgInfo]
+
+******************************************************************************/
+void *
+Ctlsp_FormulaReadDebugData(
+  Ctlsp_Formula_t * formula)
+{
+  return formula->dbgInfo.data;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns TRUE if formula was converted, else FALSE.]
+  from AX/AG/AU/AF]
+
+  Description [Returns TRUE if formula was converted from a formula of type
+  AG, AX, AU, AF, or EF via a call to
+  Ctlsp_FormulaConvertToExistentialFormTree or
+  Ctlsp_FormulaConvertToExistentialFormDAG. Otherwise, returns FALSE.]
+
+  SideEffects []
+
+******************************************************************************/
+boolean
+Ctlsp_FormulaTestIsConverted(
+  Ctlsp_Formula_t * formula)
+{
+  return formula->dbgInfo.convertedFlag;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns TRUE if formula contains no path quantifiers.]
+
+  Description [Test if a CTL* formula has any path quantifiers in it;
+  if so return false, else true.  For a CTL* formula, being quantifier-free
+  and being propositional are not equivalent.]
+
+  SideEffects []
+
+******************************************************************************/
+boolean
+Ctlsp_FormulaTestIsQuantifierFree(
+  Ctlsp_Formula_t *formula)
+{
+  boolean lCheck;
+  boolean rCheck;
+  Ctlsp_Formula_t *leftChild;
+  Ctlsp_Formula_t *rightChild;
+  Ctlsp_FormulaType type;
+
+  if ( formula == NIL( Ctlsp_Formula_t ) ) {
+    return TRUE;
+  }
+
+  type = Ctlsp_FormulaReadType( formula );
+
+  if ( ( type == Ctlsp_ID_c ) ||
+       ( type == Ctlsp_TRUE_c ) ||
+       ( type == Ctlsp_FALSE_c ) ) {
+    return TRUE;
+  }
+
+  if ( ( type == Ctlsp_E_c ) || ( type == Ctlsp_A_c ) ) {
+    return FALSE;
+  }
+
+  leftChild = Ctlsp_FormulaReadLeftChild( formula );
+  lCheck = Ctlsp_FormulaTestIsQuantifierFree( leftChild );
+
+  if (lCheck == FALSE)
+    return FALSE;
+
+  rightChild = Ctlsp_FormulaReadRightChild( formula );
+  rCheck = Ctlsp_FormulaTestIsQuantifierFree( rightChild );
+
+  return rCheck;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns original formula corresponding to converted formula.]
+
+  SideEffects []
+
+******************************************************************************/
+Ctlsp_Formula_t *
+Ctlsp_FormulaReadOriginalFormula(
+  Ctlsp_Formula_t * formula)
+{
+  return formula->dbgInfo.originalFormula;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the Alpha-Beta Index. used for LTL->AUT]
+
+  SideEffects []
+
+******************************************************************************/
+int
+Ctlsp_FormulaReadABIndex(
+  Ctlsp_Formula_t * formula)
+{
+  return formula->ab_idx;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Set the Alpha-Beta Index. used for LTL->AUT]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Ctlsp_FormulaSetABIndex(
+  Ctlsp_Formula_t * formula,
+  int ab_idx)
+{
+  formula->ab_idx = ab_idx;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the Label Index. used for LTL->AUT]
+
+  SideEffects []
+
+******************************************************************************/
+int
+Ctlsp_FormulaReadLabelIndex(
+  Ctlsp_Formula_t * formula)
+{
+  return formula->label_idx;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Set the Label Index. used for LTL->AUT]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Ctlsp_FormulaSetLabelIndex(
+  Ctlsp_Formula_t * formula,
+  int label_idx)
+{
+  formula->label_idx = label_idx;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the RHS. used for LTL->AUT]
+
+  SideEffects []
+
+******************************************************************************/
+char
+Ctlsp_FormulaReadRhs(
+  Ctlsp_Formula_t * formula)
+{
+  return formula->rhs;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Set the RHS. used for LTL->AUT]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Ctlsp_FormulaSetRhs(
+  Ctlsp_Formula_t * formula)
+{
+  formula->rhs = 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Reset the RHS. used for LTL->AUT]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Ctlsp_FormulaResetRhs(
+  Ctlsp_Formula_t * formula)
+{
+  formula->rhs = 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the marked. used for LTL->AUT]
+
+  SideEffects []
+
+******************************************************************************/
+char
+Ctlsp_FormulaReadMarked(
+  Ctlsp_Formula_t * formula)
+{
+  return formula->marked;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Set the Alpha-Beta Index. used for LTL->AUT]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Ctlsp_FormulaSetMarked(
+  Ctlsp_Formula_t * formula)
+{
+  formula->marked = 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Reset the Alpha-Beta Index. used for LTL->AUT]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Ctlsp_FormulaResetMarked(
+  Ctlsp_Formula_t * formula)
+{
+  formula->marked = 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a formula if no other formula refers to it as a
+  sub-formula.]
+
+  Description [The function decrements the refCount of the formula. As a
+  consequence, if the refCount becomes 0, the formula is freed.]
+
+  SideEffects []
+
+  SeeAlso     [CtlspFormulaFree, CtlspDecrementRefCount]
+
+******************************************************************************/
+void
+Ctlsp_FormulaFree(
+  Ctlsp_Formula_t *formula)
+{
+  CtlspFormulaDecrementRefCount(formula);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Recursively frees states, underapprox and overapprox fields of
+  Ctlsp_Formula_t, and the debug data]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_FormulaFree]
+
+******************************************************************************/
+void
+Ctlsp_FlushStates(
+  Ctlsp_Formula_t * formula)
+{
+  if (formula != NIL(Ctlsp_Formula_t)) {
+
+    if (formula->type != Ctlsp_ID_c){
+      if (formula->left  != NIL(Ctlsp_Formula_t)) {
+	Ctlsp_FlushStates(formula->left);
+      }
+      if (formula->right != NIL(Ctlsp_Formula_t)) {
+	Ctlsp_FlushStates(formula->right);
+      }
+    }
+
+    if (formula->states != NIL(mdd_t)){
+      mdd_free(formula->states);
+      formula->states = NIL(mdd_t);
+    }
+    if (formula->underapprox != NIL(mdd_t)){
+      mdd_free(formula->underapprox);
+      formula->underapprox = NIL(mdd_t);
+    }
+    if (formula->overapprox != NIL(mdd_t)){
+      mdd_free(formula->overapprox);
+      formula->overapprox = NIL(mdd_t);
+    }
+
+    if (formula->dbgInfo.data != NIL(void)){
+      (*formula->dbgInfo.freeFn)(formula);
+      formula->dbgInfo.data = NIL(void);
+    }
+
+  }
+
+}
+
+/**Function********************************************************************
+
+
+  Synopsis    [Duplicates a CTL* formula.]
+
+  Description [Recursively duplicate a formula. Does nothing if the formula
+  is NIL. Does not copy mdd for states, underapprox, overapprox, dbgInfo.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlsp_Formula_t *
+Ctlsp_FormulaDup(
+  Ctlsp_Formula_t * formula)
+{
+  Ctlsp_Formula_t *result = NIL(Ctlsp_Formula_t);
+
+  if ( formula == NIL(Ctlsp_Formula_t)) {
+	return NIL(Ctlsp_Formula_t);
+  }
+
+  result = ALLOC(Ctlsp_Formula_t, 1);
+
+  result->type                    = formula->type;
+  result->class_                  = formula->class_;
+  result->CTLclass                = formula->CTLclass;
+  result->states                  = NIL(mdd_t);
+  result->underapprox             = NIL(mdd_t);
+  result->overapprox              = NIL(mdd_t);
+  result->refCount                = 1;
+  result->dbgInfo.data            = NIL(void);
+  result->dbgInfo.freeFn          = (Ctlsp_DbgInfoFreeFn) NULL;
+  result->dbgInfo.convertedFlag   = FALSE;
+  result->dbgInfo.originalFormula = NIL(Ctlsp_Formula_t);
+
+  if ( formula->type != Ctlsp_ID_c )  {
+    result->left  = Ctlsp_FormulaDup(formula->left);
+    result->right = Ctlsp_FormulaDup(formula->right);
+  }
+  else {
+    result->left  = (Ctlsp_Formula_t *) util_strsav((char *)formula->left );
+    result->right = (Ctlsp_Formula_t *) util_strsav((char *)formula->right );
+  }
+
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees an array of CTL* formulas.]
+
+  Description [Calls CtlspFormulaDecrementRefCount on each formula in
+  formulaArray, and then frees the array itself. It is okay to call this
+  function with an empty array, but it is an error to call it with a NULL
+  array.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_FormulaFree]
+
+******************************************************************************/
+void
+Ctlsp_FormulaArrayFree(
+  array_t * formulaArray /* of Ctlsp_Formula_t  */)
+{
+  int i;
+  int numFormulas = array_n(formulaArray);
+
+  for (i = 0; i < numFormulas; i++) {
+    Ctlsp_Formula_t *formula = array_fetch(Ctlsp_Formula_t *, formulaArray, i);
+
+    CtlspFormulaDecrementRefCount(formula);
+  }
+
+  array_free(formulaArray);
+}
+/**Function********************************************************************
+
+  Synopsis    [Converts an array of CTL formulae to a multi-rooted DAG.]
+
+  Description [The function hashes each subformula of a formula
+  (including the formula itself) into a uniqueTable.  It returns an
+  array containing the roots of the multi-rooted DAG thus created by
+  the sharing of the subformulae.  It is okay to call this function
+  with an empty array (in which case an empty array is returned), but
+  it is an error to call it with a NULL array.]
+
+  SideEffects [A formula in formulaArray might be freed if it had been
+  encountered as a subformula of some other formula. Other formulae in
+  formulaArray might be present in the returned array. Therefore, the
+  formulae in formulaArray should not be freed. Only formulaArray
+  itself should be freed.
+
+
+
+  RB:  What does that mean?
+
+  I understand this as follows.  Copies of the formulae are not made,
+  but rather pointers to the argument subformulae are kept.  Hence, not only
+  should the formulae in the result not be freed, but also you cannot free the
+  argument before you are done with the result.  Furthermore, by invocation of
+  this function, the argument gets altered.  It is still valid, but pointers
+  may have changed.  Is this correct?
+
+
+  RB rewrite: A formula in formulaArray is freed if it is encountered as a
+  subformula of some other formula. Other formulae in formulaArray might be
+  present in the returned array. Therefore, the formulae in formulaArray should
+  not be freed. Only formulaArray itself should be freed.]
+
+  SeeAlso     []
+
+******************************************************************************/
+array_t *
+Ctlsp_FormulaArrayConvertToDAG(
+  array_t *formulaArray)
+{
+  int i;
+  Ctlsp_Formula_t *formula, *uniqueFormula;
+  st_table *uniqueTable = st_init_table(FormulaCompare, FormulaHash);
+  int numFormulae = array_n(formulaArray);
+  array_t *rootsOfFormulaDAG = array_alloc(Ctlsp_Formula_t *, numFormulae);
+
+  for(i=0; i < numFormulae; i++) {
+    formula = array_fetch(Ctlsp_Formula_t *, formulaArray, i);
+    uniqueFormula = FormulaHashIntoUniqueTable(formula, uniqueTable);
+    if(uniqueFormula != formula) {
+      CtlspFormulaDecrementRefCount(formula);
+      CtlspFormulaIncrementRefCount(uniqueFormula);
+      array_insert(Ctlsp_Formula_t *, rootsOfFormulaDAG, i, uniqueFormula);
+    }
+    else
+      array_insert(Ctlsp_Formula_t *, rootsOfFormulaDAG, i, formula);
+  }
+  st_free_table(uniqueTable);
+  return rootsOfFormulaDAG;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a CTL formula with the specified fields.]
+
+  Description [Allocates a Ctlsp_Formula_t, and sets the 2 fields given as
+  arguments.  If the type is Ctlsp_ID_c, then the left and right fields
+  should contain a pointer to a variable name and a pointer to a value
+  respectively. Otherwise, the two fields point to subformulas. refCount is
+  set to 1. The states field is set to NULL, the converted flag is set to
+  FALSE, and the originalFormula field is set to NULL.]
+
+  Comment     []
+
+  SideEffects []
+
+  SeeAlso     [CtlspFormulaDecrementRefCount]
+
+******************************************************************************/
+Ctlsp_Formula_t *
+Ctlsp_FormulaCreate(
+  Ctlsp_FormulaType  type,
+  void * left_,
+  void * right_)
+{
+  Ctlsp_Formula_t *formula = ALLOC(Ctlsp_Formula_t, 1);
+  Ctlsp_Formula_t *left    = (Ctlsp_Formula_t *) left_;
+  Ctlsp_Formula_t *right   = (Ctlsp_Formula_t *) right_;
+
+  formula->type                    = type;
+  formula->left                    = left;
+  formula->right                   = right;
+  formula->states                  = NIL(mdd_t);
+  formula->underapprox             = NIL(mdd_t);
+  formula->overapprox              = NIL(mdd_t);
+  formula->refCount                = 1;
+  formula->dbgInfo.data            = NIL(void);
+  formula->dbgInfo.freeFn          = (Ctlsp_DbgInfoFreeFn) NULL;
+  formula->dbgInfo.convertedFlag   = FALSE;
+  formula->dbgInfo.originalFormula = NIL(Ctlsp_Formula_t);
+  formula->top                     = 0;
+  formula->compareValue            = 0;
+  formula->class_                  = Ctlsp_propformula_c;
+  formula->CTLclass                = Ctlsp_CTL_c;
+  formula->rhs                     = 0;
+
+  if (left == NIL(Ctlsp_Formula_t)){
+    return formula;
+  }
+
+  switch(formula->type) {
+    case Ctlsp_OR_c:
+    case Ctlsp_AND_c:
+    case Ctlsp_THEN_c:
+    case Ctlsp_XOR_c:
+    case Ctlsp_EQ_c:
+      Ctlsp_FormulaSetClass(formula, table1(Ctlsp_FormulaReadClass(left),Ctlsp_FormulaReadClass(right)));
+      if ((Ctlsp_FormulaReadClassOfCTL(left)  ==  Ctlsp_CTL_c) &&
+	  (Ctlsp_FormulaReadClassOfCTL(right) == Ctlsp_CTL_c)){
+	Ctlsp_FormulaSetClassOfCTL(formula, Ctlsp_CTL_c);
+      } else {
+	Ctlsp_FormulaSetClassOfCTL(formula, Ctlsp_NotCTL_c);
+      }
+      break;
+    case Ctlsp_NOT_c:
+      Ctlsp_FormulaSetClass(formula, Ctlsp_FormulaReadClass(left));
+      Ctlsp_FormulaSetClassOfCTL(formula, Ctlsp_FormulaReadClassOfCTL(left));
+      break;
+    case Ctlsp_E_c:
+    case Ctlsp_A_c:
+      Ctlsp_FormulaSetClass(formula, Ctlsp_stateformula_c);
+      if (Ctlsp_FormulaReadClassOfCTL(left) ==  Ctlsp_PathCTL_c) {
+	Ctlsp_FormulaSetClassOfCTL(formula, Ctlsp_CTL_c);
+      } else {
+	Ctlsp_FormulaSetClassOfCTL(formula, Ctlsp_NotCTL_c);
+      }
+      break;
+    case Ctlsp_G_c:
+    case Ctlsp_F_c:
+      Ctlsp_FormulaSetClass(formula, table2(Ctlsp_FormulaReadClass(left)));
+      if (Ctlsp_FormulaReadClassOfCTL(left) ==  Ctlsp_CTL_c){
+	Ctlsp_FormulaSetClassOfCTL(formula, Ctlsp_PathCTL_c);
+      } else {
+	Ctlsp_FormulaSetClassOfCTL(formula, Ctlsp_NotCTL_c);
+      }
+      break;
+    case Ctlsp_U_c:
+    case Ctlsp_R_c:
+    case Ctlsp_W_c:
+      Ctlsp_FormulaSetClass(formula, table3(Ctlsp_FormulaReadClass(left),Ctlsp_FormulaReadClass(right)));
+      if ((Ctlsp_FormulaReadClassOfCTL(left) ==  Ctlsp_CTL_c) &&
+	  (Ctlsp_FormulaReadClassOfCTL(right) == Ctlsp_CTL_c)) {
+	Ctlsp_FormulaSetClassOfCTL(formula, Ctlsp_PathCTL_c);
+      } else {
+	Ctlsp_FormulaSetClassOfCTL(formula, Ctlsp_NotCTL_c);
+      }
+      break;
+    case Ctlsp_X_c:
+      Ctlsp_FormulaSetClass(formula, table2(Ctlsp_FormulaReadClass(left)));
+      if (Ctlsp_FormulaReadClassOfCTL(left) ==  Ctlsp_CTL_c){
+
+	Ctlsp_FormulaSetClassOfCTL(formula, Ctlsp_PathCTL_c);
+      }  else {
+	Ctlsp_FormulaSetClassOfCTL(formula, Ctlsp_NotCTL_c);
+      }
+      break;
+    default:
+      break;
+  }
+  return formula;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a CTL* formula with disjunction of atomic propositions]
+
+  Description [This function returns Ctlsp_Formula_t for name = {v1,v2,...}.
+  In case of failure, a NULL pointer is returned.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlsp_Formula_t *
+Ctlsp_FormulaCreateOr(
+  char *name,
+  char *valueStr)
+{
+  Ctlsp_Formula_t *formula, *tempFormula;
+  char *preStr;
+
+  preStr = strtok(valueStr,",");
+  formula = Ctlsp_FormulaCreate(Ctlsp_ID_c, util_strsav(name),
+			       util_strsav(preStr));
+  if (formula == NIL(Ctlsp_Formula_t)) {
+     return NIL(Ctlsp_Formula_t);
+  }
+  while ((preStr = strtok(NIL(char),",")) != NIL(char)) {
+    tempFormula = Ctlsp_FormulaCreate(Ctlsp_ID_c, util_strsav(name),
+				     util_strsav(preStr));
+    if (tempFormula == NIL(Ctlsp_Formula_t)) {
+      Ctlsp_FormulaFree(formula);
+      return NIL(Ctlsp_Formula_t);
+    }
+    formula = Ctlsp_FormulaCreate(Ctlsp_OR_c,formula,tempFormula);
+  }
+  return formula;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a CTL* formula with conjunction of atomic propositions]
+
+  Description [This function returns Ctlsp_Formula_t for nameVector =
+  value, nameVector is a form of var[i:j] or var<j:j> and value is any
+  integer n or binary string starting with 'b' or 'x', for instance,
+  b0011 or x100. If n does not fit in var[i:j] or the size of the binary
+  string is not matched with var[i:j], NULL pointer is returned]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlsp_Formula_t *
+Ctlsp_FormulaCreateVectorAnd(
+  char *nameVector,
+  char *value)
+{
+  Ctlsp_Formula_t *formula, *tempFormula;
+  int startValue, endValue, inc, i,j, interval,startInd;
+  char *binValueStr, *varName, *name;
+  char *bitValue;
+
+  varName = CtlspGetVectorInfoFromStr(nameVector,&startValue,&endValue,&interval,&inc);
+  binValueStr = ALLOC(char,interval+1);
+  if (!CtlspStringChangeValueStrToBinString(value,binValueStr,interval) ){
+     FREE(varName);
+     FREE(binValueStr);
+     return NIL(Ctlsp_Formula_t);
+  }
+
+  name = ALLOC(char,MAX_LENGTH_OF_VAR_NAME);
+  (void) sprintf(name,"%s[%d]",varName,startValue);
+  (void) CtlspChangeBracket(name);
+
+  bitValue = ALLOC(char,2);
+  bitValue[0] = binValueStr[0];
+  bitValue[1] = '\0';
+
+  formula = Ctlsp_FormulaCreate(Ctlsp_ID_c, util_strsav(name),
+			       util_strsav(bitValue));
+  j = 0;
+  startInd = startValue;
+  for(i=startValue;i!=endValue;i=i+inc){
+     startInd += inc;
+     j++;
+     (void) sprintf(name,"%s[%d]",varName,startInd);
+     (void) CtlspChangeBracket(name);
+     bitValue[0] = binValueStr[j];
+     tempFormula = Ctlsp_FormulaCreate(Ctlsp_ID_c, util_strsav(name),
+				      util_strsav(bitValue));
+     formula = Ctlsp_FormulaCreate(Ctlsp_AND_c,formula,tempFormula);
+  }
+  FREE(varName);
+  FREE(name);
+  FREE(binValueStr);
+  FREE(bitValue);
+  return formula;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a CTL formula with OR of Vector AND]
+
+  Description [This function returns Ctlsp_Formula_t for nameVector = valueStr,
+  nameVector is a form of var[i:j] or var<j:j>, valueStr is "k,l,...,q",
+  and k,l,...,q is either integer or binary string.  Binary string starting
+  with 'b', for instance, b0011. If n is not fitted in var[i:j] or size of
+  binary string is not matched with var[i:j], NULL pointer is returned]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlsp_Formula_t *
+Ctlsp_FormulaCreateVectorOr(
+  char *nameVector,
+  char *valueStr)
+{
+  Ctlsp_Formula_t *formula,*tempFormula;
+  char *preStr;
+
+  preStr = strtok(valueStr,",");
+  formula = Ctlsp_FormulaCreateVectorAnd(nameVector,preStr);
+  if ( formula == NIL(Ctlsp_Formula_t)){
+     Ctlsp_FormulaFree(formula);
+     return NIL(Ctlsp_Formula_t);
+  }
+  while( (preStr = strtok(NIL(char),",")) != NIL(char) ){
+     tempFormula = Ctlsp_FormulaCreateVectorAnd(nameVector,preStr);
+     if ( tempFormula == NIL(Ctlsp_Formula_t)){
+	Ctlsp_FormulaFree(formula);
+	return NIL(Ctlsp_Formula_t);
+     }
+     formula = Ctlsp_FormulaCreate(Ctlsp_OR_c,formula,tempFormula);
+  }
+  return formula;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a CTL formula for equivalent property]
+
+  Description [This function assumes that each child is defined in binary
+  domain. Enumerate type is not supported]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlsp_Formula_t *
+Ctlsp_FormulaCreateEquiv(
+  char *left,
+  char *right)
+{
+  Ctlsp_Formula_t *formula,*formula1,*formula2;
+
+  char *one;
+  char *zero;
+
+  one = "1";
+  zero = "0";
+
+  formula1 = Ctlsp_FormulaCreate(Ctlsp_ID_c, util_strsav(left),
+				 util_strsav(one));
+  formula2 = Ctlsp_FormulaCreate(Ctlsp_ID_c, util_strsav(right),
+				 util_strsav(zero));
+  formula = Ctlsp_FormulaCreate(Ctlsp_XOR_c,formula1,formula2);
+  return formula;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a CTL formula for equivalent of vector]
+
+  Description [This function returns a formula, which is the AND of a bitwise
+  equivalence]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlsp_Formula_t *
+Ctlsp_FormulaCreateVectorEquiv(
+  char *left,
+  char *right)
+{
+  Ctlsp_Formula_t *formula,*tempFormula;
+  char *leftName,*rightName;
+  char *leftVar, *rightVar;
+  int  leftStart,leftEnd,rightStart,rightEnd,leftInterval,rightInterval;
+  int  leftInc,rightInc,leftInd,rightInd,i;
+
+  leftName  = CtlspGetVectorInfoFromStr(left,&leftStart,&leftEnd,&leftInterval,&leftInc);
+  rightName = CtlspGetVectorInfoFromStr(right,&rightStart,&rightEnd,&rightInterval,&rightInc);
+  if (leftInterval != rightInterval){
+     return NIL(Ctlsp_Formula_t);
+  }
+  leftVar = ALLOC(char,MAX_LENGTH_OF_VAR_NAME);
+  (void) sprintf(leftVar,"%s[%d]",leftName,leftStart);
+  (void) CtlspChangeBracket(leftVar);
+  rightVar = ALLOC(char,MAX_LENGTH_OF_VAR_NAME);
+  (void) sprintf(rightVar,"%s[%d]",rightName,rightStart);
+  (void) CtlspChangeBracket(rightVar);
+
+  formula = Ctlsp_FormulaCreateEquiv(leftVar,rightVar);
+  leftInd  = leftStart;
+  rightInd = rightStart;
+  for(i=leftStart;i!=leftEnd;i+=leftInc){
+     leftInd  += leftInc;
+     rightInd += rightInc;
+     (void) sprintf(leftVar,"%s[%d]",leftName,leftInd);
+     (void) CtlspChangeBracket(leftVar);
+     (void) sprintf(rightVar,"%s[%d]",rightName,rightInd);
+     (void) CtlspChangeBracket(rightVar);
+     tempFormula = Ctlsp_FormulaCreateEquiv(leftVar,rightVar);
+     formula = Ctlsp_FormulaCreate(Ctlsp_AND_c,formula,tempFormula);
+  }
+  FREE(leftName);
+  FREE(rightName);
+  FREE(leftVar);
+  FREE(rightVar);
+  return formula;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a CTL formula for multiple X]
+
+  Description [This function returns a formula, which is the multiple
+  times of AX. The given string includes the number of depth]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlsp_Formula_t *
+Ctlsp_FormulaCreateXMult(
+  char *string,
+  Ctlsp_Formula_t *formula)
+{
+  int i,num;
+  char *str, *ptr;
+  Ctlsp_Formula_t *result = NIL(Ctlsp_Formula_t);
+  str = strchr(string,':');
+  if ( str == NULL) return(NIL(Ctlsp_Formula_t));
+  str++;
+
+  num = strtol(str,&ptr,0);
+
+  for(i=0;i<num;i++){
+    result = Ctlsp_FormulaCreate(Ctlsp_X_c, formula, NIL(Ctlsp_Formula_t));
+    Ctlsp_FormulaSetClass(result, table2(Ctlsp_FormulaReadClass(formula)));
+    if (Ctlsp_FormulaReadClassOfCTL(formula) ==  Ctlsp_CTL_c){
+      Ctlsp_FormulaSetClassOfCTL(result, Ctlsp_PathCTL_c);
+     }
+    else{
+      Ctlsp_FormulaSetClassOfCTL(result, Ctlsp_NotCTL_c);
+     }
+    formula = result;
+    }
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a CTL* formula for multiple EX]
+
+  Description [This function returns a formula, which is the multiple
+  times of EX. The given string includes the number of depth]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlsp_Formula_t *
+Ctlsp_FormulaCreateEXMult(
+  char *string,
+  Ctlsp_Formula_t *formula)
+{
+  int i,num;
+  char *str, *ptr;
+  Ctlsp_Formula_t *result = NIL(Ctlsp_Formula_t);
+
+  str = strchr(string,':');
+  if ( str == NULL) return(NIL(Ctlsp_Formula_t));
+  str++;
+
+  num = strtol(str,&ptr,0);
+
+  for(i=0;i<num;i++){
+    result = Ctlsp_FormulaCreate(Ctlsp_X_c, formula, NIL(Ctlsp_Formula_t));
+    Ctlsp_FormulaSetClass(result, table2(Ctlsp_FormulaReadClass(formula)));
+    result = Ctlsp_FormulaCreate(Ctlsp_E_c, result, NIL(Ctlsp_Formula_t));
+    Ctlsp_FormulaSetClass(result, Ctlsp_stateformula_c);
+    if (Ctlsp_FormulaReadClassOfCTL(formula) ==  Ctlsp_CTL_c)
+    {
+      Ctlsp_FormulaSetClassOfCTL(result, Ctlsp_CTL_c);
+    }
+    else
+    {
+      Ctlsp_FormulaSetClassOfCTL(result, Ctlsp_NotCTL_c);
+    }
+    formula = result;
+  }
+
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a CTL* formula for multiple AX]
+
+  Description [This function returns a formula, which is the multiple
+  times of AX. The given string includes the number of depth]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlsp_Formula_t *
+Ctlsp_FormulaCreateAXMult(
+  char *string,
+  Ctlsp_Formula_t *formula)
+{
+  int i,num;
+  char *str, *ptr;
+  Ctlsp_Formula_t *result = NIL(Ctlsp_Formula_t);
+
+  str = strchr(string,':');
+  if ( str == NULL) return(NIL(Ctlsp_Formula_t));
+  str++;
+
+  num = strtol(str,&ptr,0);
+
+  for(i=0;i<num;i++){
+    result = Ctlsp_FormulaCreate(Ctlsp_X_c, formula, NIL(Ctlsp_Formula_t));
+    Ctlsp_FormulaSetClass(result, table2(Ctlsp_FormulaReadClass(formula)));
+    result = Ctlsp_FormulaCreate(Ctlsp_A_c, result, NIL(Ctlsp_Formula_t));
+    Ctlsp_FormulaSetClass(result, Ctlsp_stateformula_c);
+    if (Ctlsp_FormulaReadClassOfCTL(formula) ==  Ctlsp_CTL_c)
+    {
+      Ctlsp_FormulaSetClassOfCTL(result, Ctlsp_CTL_c);
+    }
+    else
+    {
+      Ctlsp_FormulaSetClassOfCTL(result, Ctlsp_NotCTL_c);
+    }
+    formula = result;
+  }
+
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a string for each formula type.]
+
+  Description [Returns a string for each formula type.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+char *
+Ctlsp_FormulaGetTypeString(Ctlsp_Formula_t *formula)
+{
+  char *result;
+
+  switch(formula->type) {
+    /*
+     * The cases are listed in rough order of their expected frequency.
+     */
+    case Ctlsp_ID_c:
+      result = util_strsav("ID");
+      break;
+    case Ctlsp_OR_c:
+      result = util_strsav("OR");
+      break;
+    case Ctlsp_AND_c:
+      result = util_strsav("AND");
+      break;
+    case Ctlsp_THEN_c:
+      result = util_strsav("THEN");
+      break;
+    case Ctlsp_XOR_c:
+      result = util_strsav("XOR");
+      break;
+    case Ctlsp_EQ_c:
+      result = util_strsav("EQ");
+      break;
+    case Ctlsp_NOT_c:
+      result = util_strsav("NOT");
+      break;
+    case Ctlsp_E_c:
+      result = util_strsav("E");
+      break;
+    case Ctlsp_G_c:
+      result = util_strsav("G");
+      break;
+    case Ctlsp_F_c:
+      result = util_strsav("F");
+      break;
+    case Ctlsp_U_c:
+      result = util_strsav("U");
+      break;
+    case Ctlsp_R_c:
+      result = util_strsav("R");
+      break;
+    case Ctlsp_W_c:
+      result = util_strsav("W");
+      break;
+    case Ctlsp_X_c:
+      result = util_strsav("X");
+      break;
+    case Ctlsp_A_c:
+      result = util_strsav("A");
+      break;
+    case Ctlsp_TRUE_c:
+      result = util_strsav("TRUE");
+      break;
+    case Ctlsp_FALSE_c:
+      result = util_strsav("FALSE");
+      break;
+    case Ctlsp_Init_c:
+      result = util_strsav("Init");
+      break;
+    case Ctlsp_Cmp_c:
+      result = util_strsav("Cmp");
+      break;
+    case Ctlsp_Fwd_c:
+      result = util_strsav("Fwd");
+      break;
+      /*    case Ctlsp_EY_c:
+      result = util_strsav("EY");
+      break;*/
+      /*  case Ctlsp_EH_c:
+      result = util_strsav("EH");
+      break;
+      break;*/
+    default:
+      fail("Unexpected type");
+  }
+  return(result);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [Tests if a formula is a ACTL, ECTL or mixed formula.]
+
+  Description        [Tests if a formula is a ACTL, ECTL or mixed formula. '0'
+  for ECTL, '1' for ACTL and '2' for a mixed formula. If a formula doesn't have
+  any path quantifier, '3' is returned.]
+
+  SideEffects        []
+
+  SeeAlso            []
+
+******************************************************************************/
+Ctlsp_FormulaClass
+Ctlsp_CheckClassOfExistentialFormula(
+  Ctlsp_Formula_t *formula)
+{
+  Ctlsp_FormulaClass result;
+
+  result = CtlspCheckClassOfExistentialFormulaRecur(formula, FALSE);
+
+  return result;
+} /* End of Ctlsp_CheckTypeOfExistentialFormula */
+
+/**Function********************************************************************
+
+  Synopsis [Tests if an array of simple existential formulae has only
+  ACTL, only ECTL or mixture of formula.]
+
+  Description        [Returns Ctlsp_ECTL_c if the array contains only
+  ECTL formulae, Ctlsp_ACTL_c if it contains only ACTL formulae,
+  Ctlsp_QuantifierFree_c if there are no quantifiers in any formulae,
+  and Ctlsp_Mixed otherwise.]
+
+  SideEffects        []
+
+  SeeAlso            [Ctlsp_CheckClassOfExistentialFormula]
+
+******************************************************************************/
+Ctlsp_FormulaClass
+Ctlsp_CheckClassOfExistentialFormulaArray(
+  array_t *formulaArray)
+{
+  Ctlsp_FormulaClass result;
+  Ctlsp_Formula_t *formula;
+  int formulanr;
+
+  result = Ctlsp_QuantifierFree_c;
+  arrayForEachItem(Ctlsp_Formula_t *, formulaArray, formulanr, formula){
+    Ctlsp_FormulaClass  formulaType;
+    formulaType = Ctlsp_CheckClassOfExistentialFormula(formula);
+    result = CtlspResolveClass(result, formulaType);
+    if(result == Ctlsp_Mixed_c)
+      return result;
+  }
+  return result;
+} /* End of Ctlsp_CheckTypeOfExistentialFormulaArray */
+
+/**Function********************************************************************
+
+  Synopsis    [Get the class of a formula]
+
+  Description [Get the current class of a CTL* sub-formula]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlsp_ClassOfFormula
+Ctlsp_FormulaReadClass(Ctlsp_Formula_t *formula)
+{
+  return formula->class_;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Set the class of a formula]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Ctlsp_FormulaSetClass(Ctlsp_Formula_t *formula, Ctlsp_ClassOfFormula newClass)
+{
+  if (formula == NIL(Ctlsp_Formula_t)){
+    return;
+  }
+  formula->class_ = newClass;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Get the type of a CTL formula]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+Ctlsp_ClassOfCTLFormula
+Ctlsp_FormulaReadClassOfCTL(Ctlsp_Formula_t *formula)
+{
+  return formula->CTLclass;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Set the class of CTL]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Ctlsp_FormulaSetClassOfCTL(
+  Ctlsp_Formula_t *formula,
+  Ctlsp_ClassOfCTLFormula newCTLclass)
+{
+  if (formula == NIL(Ctlsp_Formula_t)){
+    return;
+  }
+  formula->CTLclass = newCTLclass;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns an array of LTL formulae.]
+
+  Description [Returns an array of LTL formulae given the array of CTL*
+	       formulae.
+	       If any of the CTL* formula is not LTL formula, retuns NIL.
+	       The return LTL formulae share absolutely nothing with the
+	       original CTL* formulae (not even a string).]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+array_t *
+Ctlsp_FormulaArrayConvertToLTL(
+   array_t *formulaArray)
+{
+  array_t *ltlFormulaArray;
+  int i;
+
+  ltlFormulaArray = array_alloc(Ctlsp_Formula_t *, 0);
+
+  /* Check if all CTL* formulas are LTL formulas */
+  for (i = 0; i < array_n(formulaArray); i++) {
+    Ctlsp_Formula_t *formula, *ltlFormula;
+
+    formula = array_fetch(Ctlsp_Formula_t *, formulaArray, i);
+
+    if (!Ctlsp_isLtlFormula(formula)){
+     Ctlsp_FormulaArrayFree(ltlFormulaArray);
+     return NIL(array_t);
+    }
+    ltlFormula = Ctlsp_FormulaDup(formula);
+    array_insert_last(Ctlsp_Formula_t *, ltlFormulaArray, ltlFormula);
+
+   } /* For Loop */
+  return ltlFormulaArray;
+} /*  Ctlsp_FormulaArrayConvertToLTL() */
+
+/**Function********************************************************************
+
+  Synopsis [Returns an array of CTL formulas from the parsed array of
+  CTL* formulas]
+
+  Description [This function takes an array of CTL* formulae and returns
+	       an array of CTL formulae if applicable.  Function
+	       returns NIL if any CTL * formula can't be converted to
+	       CTL formula.  The returned CTL formulae share absolutely
+	       nothing with the original CTL* formulae (not even a
+	       string).]
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_FormulaConvertToCTL]
+
+******************************************************************************/
+array_t *
+Ctlsp_FormulaArrayConvertToCTL(
+  array_t *formulaArray)
+{
+  array_t *CtlFormulaArray;
+  int i;
+
+  CtlFormulaArray = array_alloc(Ctlp_Formula_t *, 0);
+
+  /* Convert each formula in the array to CTL */
+  for (i = 0; i < array_n(formulaArray); i++) {
+    Ctlsp_Formula_t *formula;
+    Ctlp_Formula_t *newFormula;
+
+    formula = array_fetch(Ctlsp_Formula_t *, formulaArray, i);
+    newFormula = Ctlsp_FormulaConvertToCTL(formula);
+
+    if (newFormula !=  NIL(Ctlp_Formula_t)){
+       array_insert_last(Ctlp_Formula_t *, CtlFormulaArray, newFormula);
+    }
+    else{
+       (void) fprintf(vis_stderr, "** ctl* error : Can't Convert CTL* No. %d to CTL formula\n\n", i);
+       Ctlp_FormulaArrayFree(CtlFormulaArray);
+       return NIL(array_t);
+    }
+   } /* For Loop */
+  return CtlFormulaArray;
+} /*  Ctlsp_FormulaArrayConvertToCTL() */
+
+/**Function********************************************************************
+
+  Synopsis    [Convert an CTL* formula to CTL formula]
+
+  Description [This function takes a formula in CTL* and returns a CTL formula
+  if applicable.  CTL* consists of two formula classes: state formulas and
+  path formulas. CTL formula is a state formula.  CTL* formula can be
+  converted to CTL formula if the CTL* formula is state formula.
+  Note: This function must be called for each formula in a given array.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_FormulaArrayConvertToCTL]
+
+******************************************************************************/
+Ctlp_Formula_t *
+Ctlsp_FormulaConvertToCTL(
+  Ctlsp_Formula_t *formula)
+{
+  if (Ctlsp_FormulaReadClassOfCTL(formula) ==  Ctlsp_CTL_c) {/* CTL* can be converted to CTL */
+    return CtlspFormulaConvertToCTL(formula);
+  }
+  else{
+    return NIL(Ctlp_Formula_t);
+  }
+} /*  Ctlsp_FormulaConvertToCTL() */
+
+/**Function********************************************************************
+  Synopsis    [Convert a propositional CTL* formula to CTL formula]
+
+  Description [A wrapper to CtlspFormulaConvertToCTL]
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_FormulaArrayConvertToCTL]
+
+******************************************************************************/
+Ctlp_Formula_t *
+Ctlsp_PropositionalFormulaToCTL(
+  Ctlsp_Formula_t *formula)
+{
+    return CtlspFormulaConvertToCTL(formula);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Return true if CTL* formula is a propositional formula.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_FormulaReadClass()]
+
+******************************************************************************/
+int
+Ctlsp_isPropositionalFormula(
+  Ctlsp_Formula_t *formula)
+{
+  return (Ctlsp_FormulaReadClass(formula) == Ctlsp_propformula_c);
+} /* Ctlsp_isPropositionalFormula() */
+
+/**Function********************************************************************
+
+  Synopsis    [Return true if CTL* formula is an CTL formula.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_FormulaReadClassOfCTL()]
+
+******************************************************************************/
+int
+Ctlsp_isCtlFormula(
+  Ctlsp_Formula_t *formula)
+{
+  return (Ctlsp_FormulaReadClassOfCTL(formula) ==  Ctlsp_CTL_c);
+} /* Ctlsp_isCtlFormula() */
+
+/**Function********************************************************************
+
+  Synopsis    [Return true if CTL* formula is an LTL formula.]
+
+  Description [a formula is LTL formul if its one of the following:
+	       - Its class is Ctlsp_LTLformula_c
+	       - it is in the form A(Ctlsp_LTLformula_c).
+	       - Its class is Ctlsp_propformula_c.
+	       - it is in the form A(Ctlsp_propformula_c)
+	      ]
+  SideEffects []
+
+  SeeAlso     [Ctlsp_FormulaReadClass()]
+
+******************************************************************************/
+int
+Ctlsp_isLtlFormula(
+  Ctlsp_Formula_t *formula)
+{
+  if (Ctlsp_FormulaReadClass(formula) == Ctlsp_LTLformula_c){
+    return 1;
+  }
+  if (Ctlsp_FormulaReadClass(formula) == Ctlsp_propformula_c){
+    return 1;
+  }
+  if (formula->type ==  Ctlsp_A_c) {
+    if ((Ctlsp_FormulaReadClass(formula->left) == Ctlsp_LTLformula_c) ||
+	(Ctlsp_FormulaReadClass(formula->left) == Ctlsp_propformula_c)) {
+      return 1;
+      }
+    else {
+      return 0;
+    }
+  }
+  return 0;
+} /* Ctlsp_isLtlFormula() */
+
+/**Function********************************************************************
+
+  Synopsis    [Negate an LTL formula]
+
+  Description [This function returns an abbreviation-free LTL formula
+	       of the negation of the input LTL formula. The returned
+	       formula share absolutely nothing with the input LTL
+	       formula.]
+
+  Comment     []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlsp_Formula_t *
+Ctlsp_LtllFormulaNegate(
+  Ctlsp_Formula_t *ltlFormula)
+{
+  Ctlsp_Formula_t *negLtlFormula, *tmpLtlFormula;
+
+  negLtlFormula = Ctlsp_FormulaCreate(Ctlsp_NOT_c, ltlFormula, NIL(Ctlsp_Formula_t));
+  tmpLtlFormula = Ctlsp_LtlFormulaExpandAbbreviation(negLtlFormula);
+  FREE(negLtlFormula);
+  negLtlFormula = Ctlsp_LtlFormulaNegationNormalForm(tmpLtlFormula);
+  if(negLtlFormula != tmpLtlFormula) {
+    Ctlsp_FormulaFree(tmpLtlFormula);
+  }
+  tmpLtlFormula = Ctlsp_LtlFormulaSimpleRewriting(negLtlFormula);
+  Ctlsp_FormulaFree(negLtlFormula);
+  Ctlsp_LtlSetClass(tmpLtlFormula);
+
+  return tmpLtlFormula;
+} /* Ctlsp_LtllFormulaNegate() */
+
+/**Function********************************************************************
+
+  Synopsis    [Set the class of the LTL formula]
+
+  Description [This function recursively sets the class of LTL subformula. For
+  leave nodes, by default the class sets to Ctlsp_propformula_c when the node
+  is created.]
+
+  Comment     [The class filed of an LTL subformula will not be set if the
+  programmer uses FormulaCreateWithType() and then later he adds its children.
+  The correct way of creating a new node knowing its childeren is by using
+  Ctlsp_FormulaCreate()]
+
+  SideEffects []
+
+  SeeAlso     [ctlspInt.h Ctlsp_FormulaCreate]
+
+******************************************************************************/
+void
+Ctlsp_LtlSetClass(
+  Ctlsp_Formula_t *formula)
+{
+  Ctlsp_Formula_t *left, *right;
+
+  if (formula == NIL(Ctlsp_Formula_t)){
+    return;
+  }
+  if (formula->type == Ctlsp_ID_c){
+    return;
+  }
+  if (formula->type == Ctlsp_TRUE_c){
+    return;
+  }
+  if (formula->type == Ctlsp_FALSE_c){
+    return;
+  }
+  left  = formula->left;
+  right = formula->right;
+
+  Ctlsp_LtlSetClass(left);
+  Ctlsp_LtlSetClass(right);
+
+  switch(formula->type) {
+    case Ctlsp_OR_c:
+    case Ctlsp_AND_c:
+    case Ctlsp_THEN_c:
+    case Ctlsp_XOR_c:
+    case Ctlsp_EQ_c:
+      Ctlsp_FormulaSetClass(formula, table1(Ctlsp_FormulaReadClass(left),Ctlsp_FormulaReadClass(right)));
+      break;
+    case Ctlsp_NOT_c:
+      Ctlsp_FormulaSetClass(formula, Ctlsp_FormulaReadClass(left));
+      break;
+    case Ctlsp_E_c:
+    case Ctlsp_A_c:
+      Ctlsp_FormulaSetClass(formula, Ctlsp_stateformula_c);
+      break;
+    case Ctlsp_G_c:
+    case Ctlsp_F_c:
+      Ctlsp_FormulaSetClass(formula, table2(Ctlsp_FormulaReadClass(left)));
+      break;
+    case Ctlsp_U_c:
+    case Ctlsp_R_c:
+    case Ctlsp_W_c:
+      Ctlsp_FormulaSetClass(formula, table3(Ctlsp_FormulaReadClass(left),Ctlsp_FormulaReadClass(right)));
+      break;
+    case Ctlsp_X_c:
+      Ctlsp_FormulaSetClass(formula, table2(Ctlsp_FormulaReadClass(left)));
+      break;
+    default:
+      break;
+  }
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return TRUE iff formula is a "GF(propositional formula)".]
+
+  Description [GFp = FALSE R (TRUE U p) in abbreviation-free LTL formulae.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Ctlsp_LtlFormulaIsGFp(
+  Ctlsp_Formula_t *formula)
+{
+ Ctlsp_Formula_t *rightChild;
+ Ctlsp_Formula_t *leftChild;
+
+ assert(formula != NIL(Ctlsp_Formula_t));
+
+ if (Ctlsp_FormulaReadType(formula) == Ctlsp_R_c) {
+   rightChild = Ctlsp_FormulaReadRightChild(formula);
+   leftChild  = Ctlsp_FormulaReadLeftChild(formula);
+
+   if ((Ctlsp_FormulaReadType(leftChild) == Ctlsp_FALSE_c) &&
+       (Ctlsp_FormulaReadType(rightChild) == Ctlsp_U_c)){
+     if ((Ctlsp_FormulaReadType(Ctlsp_FormulaReadLeftChild(rightChild)) == Ctlsp_TRUE_c) &&
+	 (Ctlsp_isPropositionalFormula(Ctlsp_FormulaReadRightChild(rightChild)))) {
+       return TRUE;
+     }
+   }
+ }
+
+ return FALSE;
+}/* Ctlsp_LtlFormulaIsGFp() */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Return TRUE iff formula is a "G(propositional formula)".]
+
+  Description [G(p) = FALSE R p in abbreviation-free LTL formulae.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_isPropositionalFormula]
+
+******************************************************************************/
+boolean
+Ctlsp_LtlFormulaIsGp(
+  Ctlsp_Formula_t *formula)
+{
+  assert(formula != NIL(Ctlsp_Formula_t));
+
+  if ((Ctlsp_FormulaReadType(formula)== Ctlsp_G_c) &&
+       Ctlsp_isPropositionalFormula(Ctlsp_FormulaReadLeftChild(formula))){
+    return TRUE;
+  }
+  if (Ctlsp_FormulaReadType(formula) == Ctlsp_R_c) {
+    if ((Ctlsp_FormulaReadType(Ctlsp_FormulaReadLeftChild(formula)) == Ctlsp_FALSE_c) &&
+	(Ctlsp_isPropositionalFormula(Ctlsp_FormulaReadRightChild(formula)))) {
+      return TRUE;
+    }
+  }
+  return FALSE;
+} /* Ctlsp_LtlFormulaIsGp */
+
+/**Function********************************************************************
+
+  Synopsis    [Return TRUE iff formula is a "F(propositional formula)".]
+
+  Description [F(p) = TRUE U p in abbreviation-free LTL formulae.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_isPropositionalFormula]
+
+******************************************************************************/
+boolean
+Ctlsp_LtlFormulaIsFp(
+  Ctlsp_Formula_t *formula)
+{
+  assert(formula != NIL(Ctlsp_Formula_t));
+
+  if ((Ctlsp_FormulaReadType(formula)== Ctlsp_F_c) &&
+      Ctlsp_isPropositionalFormula(Ctlsp_FormulaReadLeftChild(formula))){
+    return TRUE;
+  }
+  if (Ctlsp_FormulaReadType(formula) == Ctlsp_U_c) {
+    if ((Ctlsp_FormulaReadType(Ctlsp_FormulaReadLeftChild(formula)) == Ctlsp_TRUE_c) &&
+	Ctlsp_isPropositionalFormula(Ctlsp_FormulaReadRightChild(formula))) {
+      return TRUE;
+    }
+  }
+  return FALSE;
+} /* Ctlsp_LtlFormulaIsFp */
+
+#if 0
+/**Function********************************************************************
+
+  Synopsis    [Return TRUE iff formula is a safety property.]
+
+  Description [ The characterization of LTL formula as a safety formula is
+  taken from the paper by A. Prasad Sistla: Safety, Liveness and Fairness in
+  Temporal Logic.
+  Theorm 3.1 page 8: (For positive LTL formula: formula in Negation Normal Form).
+    - Every propositional formula is a safety formula.
+    - If f, g are safety formula, then so are
+      - f AND g.
+      - f OR  g.
+      - X(f).
+      - f W g. (unless temporal operator).
+      - G(f).
+
+  This function can only be applied to abbreviation-free LTL formulae. The
+  formula must be in Negation Normal Form.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+Ctlsp_LtlFormulaIsSafety(
+  Ctlsp_Formula_t *formula)
+{
+  assert(formula != NIL(Ctlsp_Formula_t));
+
+  if (Ctlsp_isPropositionalFormula(formula)){
+    return TRUE;
+  }
+  if (Ctlsp_LtlFormulaIsW(formula)){
+    return Ctlsp_LtlFormulaIsSafety(Ctlsp_FormulaReadLeftChild(formula)) &&
+      Ctlsp_LtlFormulaIsSafety(Ctlsp_FormulaReadRightChild(formula));
+  }
+  swtich (Ctlsp_FormulaReadType(formula)){
+  case Ctlsp_AND_c:
+  case Ctlsp_OR_c:
+    return Ctlsp_LtlFormulaIsSafety(Ctlsp_FormulaReadLeftChild(formula)) &&
+	   Ctlsp_LtlFormulaIsSafety(Ctlsp_FormulaReadRightChild(formula));
+  case Ctlsp_X_c:
+    return Ctlsp_LtlFormulaIsSafety(Ctlsp_FormulaReadLeftChild(formula));
+  case Ctlsp_NOT_c:
+  case Ctlsp_U_c:
+  case Ctlsp_R_c:
+    return FALSE;
+  default:
+    fail("unexpected node type in abbreviation-free formula\n");
+    return FALSE; /* not reached */
+  }
+
+  /*    == Ctlsp_F_c) &&
+      Ctlsp_isPropositionalFormula(Ctlsp_FormulaReadLeftChild(formula))){
+    return TRUE;
+    } */
+  if (Ctlsp_FormulaReadType(formula) == Ctlsp_U_c) {
+    if (Ctlsp_FormulaReadType(Ctlsp_FormulaReadLeftChild(formula) == Ctlsp_TRUE_c) &&
+	Ctlsp_isPropositionalFormula(Ctlsp_FormulaReadRightChild(formula))) {
+      return TRUE;
+    }
+  }
+  return FALSE;
+} /* Ctlsp_LtlFormulaIsSafety */
+#endif
+
+
+/**Function********************************************************************
+
+  Synopsis    [Add fairness constraints to an array of LTL formulae.]
+
+  Description [This function modifies an array of LTL formulae by adding to
+  each of them a fairness constraint.  This fairness constraint is the
+  conjunction of all fairness constraints in constraintArray.  For consistency
+  with what done throughout VIS, each line in the file is interpreted as a
+  condition that must hold infinitely often.  The function assumes that the
+  incoming array only contains LTL formulae.  The returned formulae are not
+  normalized and not converted to DAGs.]
+
+  SideEffects [formulaArray is modified]
+
+  SeeAlso []
+
+******************************************************************************/
+void
+Ctlsp_FormulaArrayAddLtlFairnessConstraints(
+  array_t *formulaArray     /* array of LTL formulae */,
+  array_t *constraintArray /* array of fairness constraints */)
+{
+  Ctlsp_Formula_t *formula;	/* a generic LTL formula */
+  Ctlsp_Formula_t *fairness;	/* a generic fairness constraint */
+  int i;			/* iteration variable */
+
+  assert(formulaArray != NIL(array_t));
+  assert(constraintArray != NIL(array_t));
+  /*
+   * Create the overall fairness constraints.  If the given constraints
+   * are C_1, C_2, ..., C_k, build the formula /\_i GF C_i.
+   */
+  fairness = NIL(Ctlsp_Formula_t);
+  arrayForEachItem(Ctlsp_Formula_t *, constraintArray, i, formula) {
+    Ctlsp_Formula_t *finally;
+    Ctlsp_Formula_t *globally;
+    finally =  Ctlsp_FormulaCreate(Ctlsp_F_c, formula, NIL(Ctlsp_Formula_t));
+    globally = Ctlsp_FormulaCreate(Ctlsp_G_c, finally, NIL(Ctlsp_Formula_t));
+    if (i == 0) {
+      fairness = globally;
+    } else {
+      fairness = Ctlsp_FormulaCreate(Ctlsp_AND_c, fairness, globally);
+    }
+  }
+  /* Empty fairness constraint files are forbidden. */
+  assert(fairness != NIL(Ctlsp_Formula_t));
+
+  /*
+   * Add fairness to each given formula: Replace f_i by (fairness -> f_i).
+   */
+  arrayForEachItem(Ctlsp_Formula_t *, formulaArray, i, formula) {
+    Ctlsp_Formula_t *modified;
+    modified = Ctlsp_FormulaCreate(Ctlsp_THEN_c,
+				   Ctlsp_FormulaDup(fairness), formula);
+    array_insert(Ctlsp_Formula_t *, formulaArray, i, modified);
+  }
+  Ctlsp_FormulaFree(fairness);
+
+} /* Ctlsp_FormulaArrayAddLtlFairnessConstraints */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Translate a CTL formula into a CTL* formula.]
+
+  Description [Translate a CTL formula into a CTL* formula.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlsp_Formula_t *
+Ctlsp_CtlFormulaToCtlsp(Ctlp_Formula_t *F)
+{
+    Ctlsp_Formula_t *Fsp;
+    Ctlp_FormulaType Ftype;
+    Ctlsp_FormulaType Fsptype;
+
+    if (F == NIL(Ctlp_Formula_t))
+	return NIL(Ctlsp_Formula_t);
+
+    Ftype = Ctlp_FormulaReadType(F);
+    Fsptype = (Ctlsp_FormulaType) Ftype;
+
+    if (Ftype == Ctlp_TRUE_c) {
+	Fsp = Ctlsp_FormulaCreate(Ctlsp_TRUE_c, NIL(Ctlsp_Formula_t),
+				  NIL(Ctlsp_Formula_t));
+    }else if (Ftype == Ctlp_FALSE_c) {
+	Fsp = Ctlsp_FormulaCreate(Ctlsp_FALSE_c, NIL(Ctlsp_Formula_t),
+				  NIL(Ctlsp_Formula_t));
+    }else if (Ftype == Ctlp_ID_c) {
+	char *nameString = Ctlp_FormulaReadVariableName(F);
+	char *valueString = Ctlp_FormulaReadValueName(F);
+	Fsp = Ctlsp_FormulaCreate(Ctlsp_ID_c,
+				  util_strsav(nameString),
+				  util_strsav(valueString));
+    }else {
+	Ctlp_Formula_t *Fleft = Ctlp_FormulaReadLeftChild(F);
+	Ctlp_Formula_t *Fright = Ctlp_FormulaReadRightChild(F);
+	Ctlsp_Formula_t *Fspleft, *Fspright;
+	Fspleft = Ctlsp_CtlFormulaToCtlsp(Fleft);
+	Fspright = Ctlsp_CtlFormulaToCtlsp(Fright);
+	switch(Ftype) {
+	case Ctlp_NOT_c:
+	    Fsptype = Ctlsp_NOT_c;
+	    break;
+	case Ctlp_AND_c:
+	    Fsptype = Ctlsp_AND_c;
+	    break;
+	case Ctlp_OR_c:
+	    Fsptype = Ctlsp_OR_c;
+	    break;
+	case Ctlp_THEN_c:
+	    Fsptype = Ctlsp_THEN_c;
+	    break;
+	case Ctlp_EQ_c:
+	    Fsptype = Ctlsp_EQ_c;
+	    break;
+	case Ctlp_XOR_c:
+	    Fsptype = Ctlsp_XOR_c;
+	    break;
+	default:
+	    assert(0);
+	}
+	if (Fspleft)
+	    CtlspFormulaIncrementRefCount(Fspleft);
+	if (Fspright)
+	    CtlspFormulaIncrementRefCount(Fspright);
+	Fsp = Ctlsp_FormulaCreate(Fsptype, Fspleft, Fspright);
+    }
+
+    return Fsp;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Return a LTL formula with the abbreviations expanded.]
+
+  Description [The input must be a legal LTL formula. The result shares
+  nothing with the input, not even a string; The result itself  does not share
+  sub-formulae. The translation rule is:
+    Ctlsp_THEN_c        a->b  :   !a + b
+    Ctlsp_EQ_c          a<->b :   a*b +!a*!b
+    Ctlsp_XOR_c         a^b   :   a*!b + !a*b
+    Ctlsp_F_c           Fa    :   true U a
+    Ctlsp_G_c           Ga    :   false R a
+    Ctlsp_A_c           Aa    :   a
+    ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlsp_Formula_t *
+Ctlsp_LtlFormulaExpandAbbreviation(
+  Ctlsp_Formula_t *formula)
+{
+  Ctlsp_Formula_t *new_;
+
+  if (formula == NIL(Ctlsp_Formula_t))
+    return formula;
+
+  switch (formula->type) {
+  case Ctlsp_THEN_c:
+    /* a -> b  :: !a + b */
+    new_ = FormulaCreateWithType(Ctlsp_OR_c);
+    new_->left = FormulaCreateWithType(Ctlsp_NOT_c);
+    new_->left->left = Ctlsp_LtlFormulaExpandAbbreviation(formula->left);
+    new_->right = Ctlsp_LtlFormulaExpandAbbreviation(formula->right);
+    break;
+  case Ctlsp_EQ_c:
+    /* a <-> b  :: a*b + !a*!b */
+    new_ = FormulaCreateWithType(Ctlsp_OR_c);
+    new_->left = FormulaCreateWithType(Ctlsp_AND_c);
+    new_->right= FormulaCreateWithType(Ctlsp_AND_c);
+    new_->left->left = Ctlsp_LtlFormulaExpandAbbreviation(formula->left);
+    new_->left->right= Ctlsp_LtlFormulaExpandAbbreviation(formula->right);
+    new_->right->left = FormulaCreateWithType(Ctlsp_NOT_c);
+    new_->right->left->left = Ctlsp_LtlFormulaExpandAbbreviation(formula->left);
+    new_->right->right= FormulaCreateWithType(Ctlsp_NOT_c);
+    new_->right->right->left = Ctlsp_LtlFormulaExpandAbbreviation(formula->right);
+    break;
+  case Ctlsp_XOR_c:
+    /* a ^ b  :: a*!b + !a*b */
+    new_ = FormulaCreateWithType(Ctlsp_OR_c);
+    new_->left = FormulaCreateWithType(Ctlsp_AND_c);
+    new_->left->left = Ctlsp_LtlFormulaExpandAbbreviation(formula->left);
+    new_->left->right= FormulaCreateWithType(Ctlsp_NOT_c);
+    new_->left->right->left = Ctlsp_LtlFormulaExpandAbbreviation(formula->right);
+    new_->right = FormulaCreateWithType(Ctlsp_AND_c);
+    new_->right->left= FormulaCreateWithType(Ctlsp_NOT_c);
+    new_->right->left->left = Ctlsp_LtlFormulaExpandAbbreviation(formula->left);
+    new_->right->right = Ctlsp_LtlFormulaExpandAbbreviation(formula->right);
+    break;
+  case Ctlsp_F_c:
+    /* F a  :: true U a */
+    new_ = FormulaCreateWithType(Ctlsp_U_c);
+    new_->left = FormulaCreateWithType(Ctlsp_TRUE_c);
+    new_->right= Ctlsp_LtlFormulaExpandAbbreviation(formula->left);
+    break;
+  case Ctlsp_G_c:
+    /* G a  :: false R a */
+    new_ = FormulaCreateWithType(Ctlsp_R_c);
+    new_->left = FormulaCreateWithType(Ctlsp_FALSE_c);
+    new_->right= Ctlsp_LtlFormulaExpandAbbreviation(formula->left);
+    break;
+  case Ctlsp_W_c:
+    /* a W b :: b R (a+b) */
+    new_ = FormulaCreateWithType(Ctlsp_R_c);
+    new_->left = Ctlsp_LtlFormulaExpandAbbreviation(formula->right);
+    new_->right = FormulaCreateWithType(Ctlsp_OR_c);
+    new_->right->left = Ctlsp_LtlFormulaExpandAbbreviation(formula->right);
+    new_->right->right = Ctlsp_LtlFormulaExpandAbbreviation(formula->left);
+    break;
+  case Ctlsp_ID_c:
+    /* Make a copy of the name, and create a new formula. */
+    new_ = FormulaCreateWithType(Ctlsp_ID_c);
+    new_->left = (Ctlsp_Formula_t *) util_strsav((char *)(formula->left));
+    new_->right= (Ctlsp_Formula_t *) util_strsav((char *)(formula->right));
+    break;
+  case Ctlsp_A_c:
+    /* Ignore A */
+    new_ = Ctlsp_LtlFormulaExpandAbbreviation(formula->left);
+    break;
+  default:
+    /* These are already in the correct form.  Just convert subformulas. */
+    new_ = FormulaCreateWithType(formula->type);
+    new_->left = Ctlsp_LtlFormulaExpandAbbreviation(formula->left);
+    new_->right= Ctlsp_LtlFormulaExpandAbbreviation(formula->right);
+  }
+
+  return new_;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return the Negation Normal Form (NNF) of a LTL formula.]
+
+  Description [The negation is pushed to the bottom (only ahead fo atomic
+  formulae). The result shares nothing with the input, not even a string;
+  subformulae in the result are not shared either.
+
+  Assume the formula is abbreviation-free, and there are only the following
+  types of formulae before translation:
+    TRUE/ FALSE/ ID/ AND/ OR/ U/ R/ X/ !  .]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlsp_Formula_t *
+Ctlsp_LtlFormulaNegationNormalForm(
+  Ctlsp_Formula_t *formula)
+{
+  Ctlsp_Formula_t *new_, *left, *right;
+#if 0
+  Ctlsp_Formula_t  *negRight, *negLeft;
+#endif
+  Ctlsp_FormulaType dual;
+
+  if (formula == NIL(Ctlsp_Formula_t))
+    return formula;
+
+  if (formula->type == Ctlsp_TRUE_c || formula->type == Ctlsp_FALSE_c) {
+    new_ = FormulaCreateWithType(formula->type);
+    return new_;
+  }
+
+  if (formula->type == Ctlsp_ID_c) {
+    new_ = FormulaCreateWithType(formula->type);
+    new_->left =(Ctlsp_Formula_t *)util_strsav((char *)(formula->left));
+    new_->right=(Ctlsp_Formula_t *)util_strsav((char *)(formula->right));
+    return new_;
+  }
+
+  if (formula->type != Ctlsp_NOT_c) {
+    new_ = FormulaCreateWithType(formula->type);
+    new_->left = Ctlsp_LtlFormulaNegationNormalForm(formula->left);
+    new_->right= Ctlsp_LtlFormulaNegationNormalForm(formula->right);
+    return new_;
+  }
+
+  /* In the following, formula->type == Ctlsp_NOT_c */
+  if (formula->left->type == Ctlsp_NOT_c)
+    return Ctlsp_LtlFormulaNegationNormalForm(formula->left->left);
+
+  if (formula->left->type == Ctlsp_ID_c) {
+    new_ = FormulaCreateWithType(formula->type);
+    new_->left = Ctlsp_LtlFormulaNegationNormalForm(formula->left);
+    return new_;
+  }
+#if 0
+  if (formula->left->type == Ctlsp_THEN_c ) {
+    left  = Ctlsp_LtlFormulaNegationNormalForm(formula->left->left);
+    right = Ctlsp_FormulaCreate(Ctlsp_NOT_c, formula->left->right, NIL(Ctlsp_Formula_t));
+    right = Ctlsp_LtlFormulaNegationNormalForm(right);
+    new_   = Ctlsp_FormulaCreate(Ctlsp_AND_c, left, right);
+    return new_;
+  }
+  if (formula->left->type == Ctlsp_EQ_c ) {
+    left  = Ctlsp_LtlFormulaNegationNormalForm(formula->left->left);
+    right = Ctlsp_LtlFormulaNegationNormalForm(formula->left->right);
+    negRight = Ctlsp_FormulaCreate(Ctlsp_NOT_c, right, NIL(Ctlsp_Formula_t));
+    negLeft  = Ctlsp_FormulaCreate(Ctlsp_NOT_c, left, NIL(Ctlsp_Formula_t));
+    left     = right= Ctlsp_FormulaCreate(Ctlsp_AND_c, left, negRight);
+    right    = right= Ctlsp_FormulaCreate(Ctlsp_AND_c, negLeft, right);
+    new_      = Ctlsp_FormulaCreate(Ctlsp_OR_c, left, right);
+    return Ctlsp_LtlFormulaNegationNormalForm(new_);
+  }
+#endif
+  /* for TRUE/ FALSE/ AND/ OR/ U/ R/ X/ F/ G */
+  switch (formula->left->type) {
+  case Ctlsp_TRUE_c:
+    dual = Ctlsp_FALSE_c;
+    break;
+  case Ctlsp_FALSE_c:
+    dual = Ctlsp_TRUE_c;
+    break;
+  case Ctlsp_AND_c:
+    dual = Ctlsp_OR_c;
+    break;
+  case Ctlsp_OR_c:
+    dual = Ctlsp_AND_c;
+    break;
+  case Ctlsp_U_c:
+    dual = Ctlsp_R_c;
+    break;
+  case Ctlsp_R_c:
+    dual = Ctlsp_U_c;
+    break;
+  case Ctlsp_X_c:
+    dual = Ctlsp_X_c;
+    break;
+  case Ctlsp_F_c:
+    dual = Ctlsp_G_c;
+    break;
+  case Ctlsp_G_c:
+    dual = Ctlsp_F_c;
+    break;
+  default:
+    fail("Unexpected type");
+  }
+
+  /* alloc temporary formulae (! left) and (! right) */
+  left = Ctlsp_FormulaCreate(Ctlsp_NOT_c, formula->left->left, NIL(Ctlsp_Formula_t));
+  right= Ctlsp_FormulaCreate(Ctlsp_NOT_c, formula->left->right, NIL(Ctlsp_Formula_t));
+
+  /* create the new formula */
+  new_ = FormulaCreateWithType(dual);
+  if ((dual == Ctlsp_X_c) ||
+      (dual == Ctlsp_F_c) ||
+      (dual == Ctlsp_G_c) ){
+    new_->left = Ctlsp_LtlFormulaNegationNormalForm(left);
+  }else if (dual != Ctlsp_TRUE_c && dual != Ctlsp_FALSE_c) {
+    new_->left = Ctlsp_LtlFormulaNegationNormalForm(left);
+    new_->right= Ctlsp_LtlFormulaNegationNormalForm(right);
+  }
+  FREE(left);
+  FREE(right);
+
+  return new_;
+}
+
+/**Function********************************************************************
+
+Synopsis    [Hash the LTL formula and its sub-formulae into uniquetable.]
+
+Description [It is possible that 'F' is freed, in which case a new 'F' is
+returned.]
+
+SideEffects []
+
+SeeAlso     []
+
+******************************************************************************/
+
+Ctlsp_Formula_t *
+Ctlsp_LtlFormulaHashIntoUniqueTable(
+  Ctlsp_Formula_t *F,
+  st_table *uniqueTable)
+{
+  Ctlsp_Formula_t *uniqueFormula;
+
+  uniqueFormula = FormulaHashIntoUniqueTable(F, uniqueTable);
+
+  /* If there is a copy 'uniqueFormula' in the uniqueTable, free F and
+     increment the refCount of 'uniqueFormula' */
+  if(uniqueFormula != F) {
+    CtlspFormulaDecrementRefCount(F);
+    CtlspFormulaIncrementRefCount(uniqueFormula);
+  }
+
+  return uniqueFormula;
+}
+
+/**Function********************************************************************
+
+Synopsis    [Clear the '.marked' field of the LTL formula.]
+
+Description [Recursively clear the .marked field for all its sub-formulae.]
+
+SideEffects []
+
+SeeAlso     []
+
+******************************************************************************/
+void
+Ctlsp_LtlFormulaClearMarks(
+  Ctlsp_Formula_t *F)
+{
+  if(F) {
+    F->marked = 0;
+    if (F->type != Ctlsp_ID_c) {
+      Ctlsp_LtlFormulaClearMarks(F->left);
+      Ctlsp_LtlFormulaClearMarks(F->right);
+    }
+  }
+}
+
+/**Function********************************************************************
+
+Synopsis    [Clear the '.marked' field of the LTL formula.]
+
+Description [Recursively clear the .marked field for all its sub-formulae.]
+
+SideEffects []
+
+SeeAlso     []
+
+******************************************************************************/
+int
+Ctlsp_LtlFormulaCountNumber(
+  Ctlsp_Formula_t *F)
+{
+  int result = 1;
+
+  if (!F)
+    return 0;
+
+  if (F->marked)
+    return 0;
+
+  F->marked = 1;
+  if (F->type == Ctlsp_TRUE_c ||
+      F->type == Ctlsp_FALSE_c ||
+      F->type == Ctlsp_ID_c)
+    return 1;
+
+  result += Ctlsp_LtlFormulaCountNumber(F->left);
+  result += Ctlsp_LtlFormulaCountNumber(F->right);
+
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Alloc a unqiue table for formulae.]
+
+  Description [Use FormulaHash and formulaCompare.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+st_table *
+Ctlsp_LtlFormulaCreateUniqueTable( void )
+{
+  return st_init_table(FormulaCompare, FormulaHash);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return True iff formula is an "elementary formula".]
+
+  Description [Return True iff formula is an elementary formula. This is the
+  original definition used in "Wring": it's a TRUE/FALSE/literal/X-formula.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Ctlsp_LtlFormulaIsElementary2(
+  Ctlsp_Formula_t *F)
+{
+  assert(F != 0);
+
+  return (F->type == Ctlsp_X_c || Ctlsp_LtlFormulaIsAtomicPropositional(F) );
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return True iff formula is an "elementary formula".]
+
+  Description [Return True iff the formula is an elementary formula. The
+  definition of 'elementary formula' is slightly different from the one in
+  "Wring":  it's a TRUE/FALSE/Atomic Propositions/X-formula.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Ctlsp_LtlFormulaIsElementary(
+  Ctlsp_Formula_t *F)
+{
+  assert(F != NIL(Ctlsp_Formula_t));
+
+  return (F->type == Ctlsp_X_c || Ctlsp_LtlFormulaIsPropositional(F) );
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return TRUE iff abbreviation-free LTL formula is bounded.]
+
+  Description [A bounded LTL formula is one that contains only atomic
+  propositions, Boolean connectives, and the next-time (X) operator.
+  The depth of a bounded formula is the maximum number of Xs along a
+  path of its parse tree.  This function can only be applied to
+  abbreviation-free LTL formulae.]
+
+  SideEffects [The depth is returned as a side effect.  (Only if the function
+  returns TRUE.)]
+
+  SeeAlso     [Ctlsp_LtlFormulaExpandAbbreviation,
+	       Ctlsp_LtlFormulaTestIsSyntacticallyCoSafe]
+
+******************************************************************************/
+boolean
+Ctlsp_LtlFormulaTestIsBounded(
+  Ctlsp_Formula_t *formula,
+  int *depth)
+{
+  Ctlsp_Formula_t *leftChild;
+  Ctlsp_Formula_t *rightChild;
+  int leftDepth, rightDepth;
+
+  assert(formula != NIL(Ctlsp_Formula_t));
+
+  switch (Ctlsp_FormulaReadType(formula)) {
+  case Ctlsp_TRUE_c:
+  case Ctlsp_FALSE_c:
+  case Ctlsp_ID_c:
+    *depth = 0;
+    return TRUE;
+  case Ctlsp_AND_c:
+  case Ctlsp_OR_c:
+    leftChild = Ctlsp_FormulaReadLeftChild(formula);
+    if (Ctlsp_LtlFormulaTestIsBounded(leftChild, &leftDepth)) {
+      rightChild = Ctlsp_FormulaReadRightChild(formula);
+      if (Ctlsp_LtlFormulaTestIsBounded(rightChild, &rightDepth)) {
+	*depth = leftDepth > rightDepth ? leftDepth : rightDepth;
+	return TRUE;
+      } else {
+	return FALSE;
+      }
+    } else {
+      return FALSE;
+    }
+  case Ctlsp_NOT_c:
+  case Ctlsp_X_c:
+    leftChild = Ctlsp_FormulaReadLeftChild(formula);
+    if (Ctlsp_LtlFormulaTestIsBounded(leftChild, &leftDepth)) {
+      if (Ctlsp_FormulaReadType(formula) == Ctlsp_X_c) leftDepth++;
+      *depth = leftDepth;
+      return TRUE;
+    } else {
+      return FALSE;
+    }
+  case Ctlsp_U_c:
+  case Ctlsp_R_c:
+    return FALSE;
+  default:
+    fail("unexpected node type in abbreviation-free formula\n");
+    return FALSE; /* not reached */
+  }
+} /* Ctlsp_LtlFormulaTestIsBounded */
+
+/**Function********************************************************************
+
+  Synopsis    [Return the depth of abbreviation-free LTL formula.]
+
+  Description [The depth of the LTL formula f is the maximum level of
+  nesting of temporal operators in f.  This function can only be applied
+  to abbreviation-free LTL formulae.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_LtlFormulaExpandAbbreviation]
+
+******************************************************************************/
+int
+Ctlsp_LtlFormulaDepth(
+  Ctlsp_Formula_t *formula)
+{
+  int leftDepth, rightDepth;
+
+  assert(formula != NIL(Ctlsp_Formula_t));
+
+  switch (Ctlsp_FormulaReadType(formula)) {
+  case Ctlsp_TRUE_c:
+  case Ctlsp_FALSE_c:
+  case Ctlsp_ID_c:
+    return 0;
+  case Ctlsp_AND_c:
+  case Ctlsp_OR_c:
+    leftDepth  = Ctlsp_LtlFormulaDepth(Ctlsp_FormulaReadLeftChild(formula));
+    rightDepth = Ctlsp_LtlFormulaDepth(Ctlsp_FormulaReadRightChild(formula));
+    return leftDepth > rightDepth ? leftDepth : rightDepth;
+  case Ctlsp_NOT_c:
+    return Ctlsp_LtlFormulaDepth(Ctlsp_FormulaReadLeftChild(formula));
+  case Ctlsp_X_c:
+    return 1+Ctlsp_LtlFormulaDepth(Ctlsp_FormulaReadLeftChild(formula));
+  case Ctlsp_U_c:
+  case Ctlsp_R_c:
+    leftDepth  = Ctlsp_LtlFormulaDepth(Ctlsp_FormulaReadLeftChild(formula));
+    rightDepth = Ctlsp_LtlFormulaDepth(Ctlsp_FormulaReadRightChild(formula));
+    return 1+(leftDepth > rightDepth ? leftDepth : rightDepth);
+  default:
+    fail("unexpected node type in abbreviation-free formula\n");
+    return 0; /* not reached */
+  }
+} /* Ctlsp_LtlFormulaDepth */
+
+/**Function********************************************************************
+
+  Synopsis    [Return TRUE iff LTL formula in negation normal form is
+  syntactically co-safe.]
+
+  Description [A syntactically co-safe LTL formula is a formula in
+  negation normal form that contains no release (R) operators.  This
+  function can only be applied to abbreviation-free LTL formulae in
+  negation normal form.  We test co-safety because this function is
+  meant to be called on the negation of the given formula.]
+
+  SideEffects [none]
+
+  SeeAlso     [Ctlsp_LtlFormulaNegationNormalForm,
+	       Ctlsp_LtlFormulaTestIsBounded]
+
+******************************************************************************/
+boolean
+Ctlsp_LtlFormulaTestIsSyntacticallyCoSafe(Ctlsp_Formula_t *formula)
+{
+  Ctlsp_Formula_t *leftChild;
+  Ctlsp_Formula_t *rightChild;
+
+  assert(formula != NIL(Ctlsp_Formula_t));
+
+  /*
+    Check for unless temporal operator. a W b = (a U b) OR (FALSE R a)
+		     its negation = (!a R !b) AND (TRUE U !a)
+   */
+  if(Ctlsp_FormulaReadType(formula) ==  Ctlsp_AND_c){
+    leftChild  = Ctlsp_FormulaReadLeftChild(formula);
+    rightChild = Ctlsp_FormulaReadRightChild(formula);
+    if((Ctlsp_FormulaReadType(leftChild)  == Ctlsp_R_c) &&
+       (Ctlsp_FormulaReadType(rightChild) == Ctlsp_U_c)){
+      if(Ctlsp_FormulaReadLeftChild(leftChild) == Ctlsp_FormulaReadRightChild(rightChild)){
+	if(Ctlsp_FormulaReadType(Ctlsp_FormulaReadLeftChild(rightChild)) == Ctlsp_TRUE_c){
+	  return Ctlsp_LtlFormulaTestIsSyntacticallyCoSafe(
+			    Ctlsp_FormulaReadLeftChild(leftChild)) &&
+		 Ctlsp_LtlFormulaTestIsSyntacticallyCoSafe(
+			    Ctlsp_FormulaReadRightChild(leftChild));
+	}
+      }
+    }
+    /*
+       a W b = (FALSE R a) OR (a U b)
+       its negation = (TRUE U !a) AND (!a R !b)
+   */
+    if((Ctlsp_FormulaReadType(rightChild) == Ctlsp_R_c) &&
+       (Ctlsp_FormulaReadType(leftChild) == Ctlsp_U_c)){
+      if(Ctlsp_FormulaReadLeftChild(rightChild) == Ctlsp_FormulaReadRightChild(leftChild)){
+	if(Ctlsp_FormulaReadType(Ctlsp_FormulaReadLeftChild(leftChild)) == Ctlsp_TRUE_c){
+	  return Ctlsp_LtlFormulaTestIsSyntacticallyCoSafe(
+	    Ctlsp_FormulaReadLeftChild(rightChild)) &&
+	    Ctlsp_LtlFormulaTestIsSyntacticallyCoSafe(
+	      Ctlsp_FormulaReadRightChild(rightChild));
+	}
+      }
+    }
+  }
+  switch (Ctlsp_FormulaReadType(formula)) {
+  case Ctlsp_TRUE_c:
+  case Ctlsp_FALSE_c:
+  case Ctlsp_ID_c:
+    return TRUE;
+  case Ctlsp_AND_c:
+  case Ctlsp_OR_c:
+  case Ctlsp_U_c:
+    leftChild = Ctlsp_FormulaReadLeftChild(formula);
+    if (Ctlsp_LtlFormulaTestIsSyntacticallyCoSafe(leftChild)) {
+      rightChild = Ctlsp_FormulaReadRightChild(formula);
+      return Ctlsp_LtlFormulaTestIsSyntacticallyCoSafe(rightChild);
+    } else {
+      return FALSE;
+    }
+  case Ctlsp_NOT_c:
+    leftChild = Ctlsp_FormulaReadLeftChild(formula);
+    /* The formula is in negation normal form. */
+    assert(Ctlsp_FormulaReadType(leftChild) == Ctlsp_ID_c);
+    return TRUE;
+  case Ctlsp_X_c:
+    leftChild = Ctlsp_FormulaReadLeftChild(formula);
+    return Ctlsp_LtlFormulaTestIsSyntacticallyCoSafe(leftChild);
+  case Ctlsp_R_c:
+    return FALSE;
+  default:
+    fail("unexpected node type in abbreviation-free formula\n");
+    return FALSE; /* not reached */
+  }
+} /* Ctlsp_LtlFormulaTestIsSyntacticallyCoSafe */
+
+/**Function********************************************************************
+
+  Synopsis [Tests if each formula in an array of LTL formulae is
+  propositional]
+
+  Description [This function tests each LTL formula in negation normal
+  form to see if it is a propositional formula.  Return TRUE if all formulae
+  are propositional formulae.]
+
+  SideEffects [none]
+
+  SeeAlso     [Ctlsp_LtlFormulaIsPropositional]
+
+******************************************************************************/
+int
+Ctlsp_LtlFormulaArrayIsPropositional(
+  array_t * formulaArray)
+{
+  int             i;
+  Ctlsp_Formula_t *formula;
+
+  for (i = 0; i < array_n(formulaArray); i++) {
+    formula = array_fetch(Ctlsp_Formula_t *, formulaArray, i);
+    if(!Ctlsp_isPropositionalFormula(formula)){
+      /*if(Ctlsp_LtlFormulaIsPropositional(formula) == 0){*/
+      return 0;
+    }
+  }
+  return 1;
+
+} /* Ctlsp_LtlFormulaArrayIsPropositional */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Return T iff formula is a "propositional formula".]
+
+  Description [This function tests an LTL formula in negation normal
+  form to see if it is a propositional formula.  A propositional
+  formula contains only Boolean connectives, TRUE, FALSE, and
+  literals.  A literal is an atomic proposition or the negation of an
+  atomic popposition.]
+
+  SideEffects [none]
+
+  SeeAlso     [Ctlsp_LtlFormulaIsAtomicPropositional]
+
+******************************************************************************/
+int
+Ctlsp_LtlFormulaIsPropositional(
+  Ctlsp_Formula_t *F)
+{
+  int result;
+
+  assert(F !=  NIL(Ctlsp_Formula_t));
+
+  switch (F->type) {
+  case Ctlsp_TRUE_c:
+  case Ctlsp_FALSE_c:
+  case Ctlsp_ID_c:
+    result = 1;
+    break;
+  case Ctlsp_NOT_c: /* negation only appears ahead of AP */
+    if (F->left->type == Ctlsp_ID_c)
+      result = 1;
+    else
+      result = 0;
+    break;
+  case Ctlsp_AND_c:
+  case Ctlsp_OR_c:
+    result = (Ctlsp_LtlFormulaIsPropositional(F->left) &&
+	      Ctlsp_LtlFormulaIsPropositional(F->right));
+    break;
+  default:
+    result = 0;
+  }
+
+  return result;
+} /* Ctlsp_LtlFormulaIsPropositional() */
+
+/**Function********************************************************************
+
+  Synopsis    [Return T iff formula is an "atomic propositional formula".]
+
+  Description [TRUE/FALSE/literal.  literal: an atomic proposition or the
+  negation of an atomic popposition.]
+
+  SideEffects [none]
+
+  SeeAlso     [Ctlsp_LtlFormulaIsPropositional]
+
+******************************************************************************/
+int
+Ctlsp_LtlFormulaIsAtomicPropositional(
+  Ctlsp_Formula_t *F)
+{
+  int result;
+
+  assert(F != 0);
+
+  switch (F->type) {
+  case Ctlsp_TRUE_c:
+  case Ctlsp_FALSE_c:
+  case Ctlsp_ID_c:
+    result = 1;
+    break;
+  case Ctlsp_NOT_c: /* negation only appears ahead of AP */
+    if (F->left->type == Ctlsp_ID_c)
+      result = 1;
+    else
+      result = 0;
+    break;
+  default:
+    result = 0;
+  }
+
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return T iff formula is a "FG formula".]
+
+  Description [TRUE U (FALSE R p).]
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_LtlFormulaIsGF, Ctlsp_LtlFormulaIsFGorGF]
+
+******************************************************************************/
+int
+Ctlsp_LtlFormulaIsFG(
+  Ctlsp_Formula_t *F)
+{
+  int result = 0;
+
+  if (F->type == Ctlsp_U_c) {
+    if (F->left->type == Ctlsp_TRUE_c && F->right->type == Ctlsp_R_c) {
+      result = (F->right->left->type == Ctlsp_FALSE_c);
+    }
+  }
+
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Return T iff formula is a "GF formula".]
+
+  Description [FALSE R (TRUE U p).]
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_LtlFormulaIsFG, Ctlsp_LtlFormulaIsFGorGF]
+
+******************************************************************************/
+int
+Ctlsp_LtlFormulaIsGF(
+  Ctlsp_Formula_t *F)
+{
+  int result = 0;
+
+  if (F->type == Ctlsp_R_c) {
+      if (F->left->type == Ctlsp_FALSE_c && F->right->type == Ctlsp_U_c) {
+	  result = (F->right->left->type == Ctlsp_TRUE_c);
+      }
+  }
+
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return T iff formula is a "FG or GF formula".]
+
+  Description [TRUE U (FALSE R p).]
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_LtlFormulaIsGF, Ctlsp_LtlFormulaIsFG]
+
+******************************************************************************/
+int
+Ctlsp_LtlFormulaIsFGorGF(
+  Ctlsp_Formula_t *F)
+{
+  return (Ctlsp_LtlFormulaIsFG(F) || Ctlsp_LtlFormulaIsGF(F));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Return T iff (form -> to).]
+
+  Description [Since determine '->' is hard, we only consider easy case which
+  can be determined syntatically.
+
+  Notice that, before calling this function, 'from' and 'to' are hashed into
+  the same UniqueTable (This helps in identifying "from==to").]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Ctlsp_LtlFormulaSimplyImply(
+  Ctlsp_Formula_t *from,
+  Ctlsp_Formula_t *to)
+{
+
+#if 0
+  fprintf(vis_stdout, "\n------------------------\n");
+  Ctlsp_FormulaPrint(vis_stdout, from);
+  fprintf(vis_stdout, "\n   ==>\n");
+  Ctlsp_FormulaPrint(vis_stdout, to);
+  fprintf(vis_stdout, "\n------------------------\n");
+#endif
+
+  /* from -> from   :  1 */
+  if (from == to)
+    return 1;
+
+  /* from -> TRUE   :  1 */
+  if (to->type == Ctlsp_TRUE_c)
+    return 1;
+
+  /* FALSE -> to    :  1 */
+  if (from->type == Ctlsp_FALSE_c)
+    return 1;
+
+
+  if (to->type == Ctlsp_U_c) {
+    /* from -> tL U tR: (from->tR)? */
+    if (Ctlsp_LtlFormulaSimplyImply(from, to->right))
+      return 1;
+
+    /* (fL U fR) -> (tl U tR) : (fL->tL)? && (fR->tR)? */
+    if (from->type == Ctlsp_U_c)
+      return (Ctlsp_LtlFormulaSimplyImply(from->left, to->left) &&
+	      Ctlsp_LtlFormulaSimplyImply(from->right, to->right));
+  }
+
+  if (to->type == Ctlsp_R_c) {
+    /* from -> tL R tR: (from->tL)? && (from->tR)? */
+    if (Ctlsp_LtlFormulaSimplyImply(from, to->left) &&
+	Ctlsp_LtlFormulaSimplyImply(from, to->right))
+      return 1;
+
+    /* (fL R fR) -> (tL R tR) : (fL->tL)? && (fR->tR)? */
+    if (from->type == Ctlsp_R_c)
+      return (Ctlsp_LtlFormulaSimplyImply(from->left, to->left) &&
+	      Ctlsp_LtlFormulaSimplyImply(from->right, to->right));
+  }
+
+  /* (fL U fR) -> to :: (fL->to)? && (fR->to)? */
+  if (from->type == Ctlsp_U_c) {
+    if (Ctlsp_LtlFormulaSimplyImply(from->left, to) &&
+	Ctlsp_LtlFormulaSimplyImply(from->right,to) )
+      return 1;
+  }
+
+  /* (fL R fR) -> to :: (fR->to)? */
+  if (from->type == Ctlsp_R_c) {
+    if (Ctlsp_LtlFormulaSimplyImply(from->right,to))
+      return 1;
+  }
+
+  /*************************************************************************
+   * (1) If we unwinding every propositional formula, sometimes it will
+   * become really hard. This is due to the feature of the CTL* parser.
+   * For example, "state[1024]=0" would be parsed into 1024 subformulae
+   *
+   * (2) Without unwinding, some possible simplification cases can not be
+   * detected. For example, "p + !p", "p * !p" (while p and the left
+   * subformula in !p are syntatically different.
+   ************************************************************************/
+  if (!Ctlsp_LtlFormulaIsPropositional(to)) {
+
+    /* form -> tL*tR  : (from->tL)? && (from->rR)? */
+    if (to->type == Ctlsp_AND_c)
+      return (Ctlsp_LtlFormulaSimplyImply(from, to->left) &&
+	      Ctlsp_LtlFormulaSimplyImply(from, to->right));
+
+    /* from -> tL+tR  : (from->tL)? || (from->rR)? */
+    if (to->type == Ctlsp_OR_c)
+      return (Ctlsp_LtlFormulaSimplyImply(from, to->left) ||
+	      Ctlsp_LtlFormulaSimplyImply(from, to->right) );
+  }
+
+  if (!Ctlsp_LtlFormulaIsPropositional(from)) {
+
+    /* (fL * fR) -> to :: (fL->to)? || (fR->to)? */
+    if (from->type == Ctlsp_AND_c)
+      return (Ctlsp_LtlFormulaSimplyImply(from->left, to) ||
+	      Ctlsp_LtlFormulaSimplyImply(from->right,to) );
+
+
+    /* (fL + fR) -> to :: (fL->to)? && (fR->to)? */
+    if (from->type == Ctlsp_OR_c)
+      return (Ctlsp_LtlFormulaSimplyImply(from->left, to) &&
+	      Ctlsp_LtlFormulaSimplyImply(from->right,to) );
+  }
+
+  return 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Translate LTL formula into Separated Normal Form (SNF)]
+
+  Description [Translate LTL formula into Separated Normal Form (SNF).
+  Each LTL formula is translated into a set of rules in the form (p
+  --> f(q)), where p and q are propositional and f(q) contains at most
+  one temporal operator which is either X or F.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_LtlTranslateIntoSNFRecursive]
+
+******************************************************************************/
+array_t *
+Ctlsp_LtlTranslateIntoSNF(
+  Ctlsp_Formula_t *formula)
+{
+  Ctlsp_Formula_t *leftNode;
+  int             index, i;
+  array_t         *formulaArray = array_alloc(Ctlsp_Formula_t *, 0);
+
+  /*
+    rule#1: an LTL formula must hold at an initial state.
+   */
+
+  leftNode  = Ctlsp_FormulaCreate(Ctlsp_ID_c, (void *)util_strsav(" SNFstart"), (void *)util_strsav("1"));
+  /*
+    rightNode = Ctlsp_FormulaCreate(Ctlsp_ID_c, (void *)util_strsav("SNFx_0"),   (void *)util_strsav("1"));
+    newNode = Ctlsp_FormulaCreate(Ctlsp_THEN_c, leftNode, rightNode);
+  */
+
+  index = 0;
+  Ctlsp_LtlTranslateIntoSNFRecursive(leftNode, formula, formulaArray, &index);
+
+  fprintf(vis_stdout, "The SNF rules are:\n");
+  for (i = 0; i < array_n(formulaArray); i++) {
+    Ctlsp_Formula_t *ltlFormula     = array_fetch(Ctlsp_Formula_t *, formulaArray, i);
+
+    Ctlsp_FormulaPrint(vis_stdout, ltlFormula);
+    fprintf(vis_stdout, "\n");
+  }
+
+  return formulaArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Trnalate LTL formula into Separated Normal Form (SNF)]
+
+  Description [Recursively trnaslate LTL formula into SNF
+
+  Assume the formula is abbreviation-free NNF, and there are only the
+  following types of formulae before translation: TRUE FALSE ID AND OR
+  U R X !  .]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Ctlsp_LtlTranslateIntoSNFRecursive(
+  Ctlsp_Formula_t *propNode,
+  Ctlsp_Formula_t *formula,
+  array_t         *formulaArray,
+  int             *index)
+{
+
+  Ctlsp_Formula_t *leftNode, *rightNode, *newNode, *result;
+
+  if(formula == NIL(Ctlsp_Formula_t)){
+    return;
+  }
+  if(Ctlsp_LtlFormulaIsPropositional(formula)){
+    newNode = CtlspFunctionThen(propNode, formula);
+    CtlspFormulaIncrementRefCount(newNode);
+    array_insert_last(Ctlsp_Formula_t *, formulaArray, newNode);
+    return;
+  }
+  switch (Ctlsp_FormulaReadType(formula)) {
+  case Ctlsp_AND_c:
+    leftNode  = Ctlsp_FormulaReadLeftChild(formula);
+    rightNode = Ctlsp_FormulaReadRightChild(formula);
+
+    Ctlsp_LtlTranslateIntoSNFRecursive(propNode, leftNode, formulaArray, index);
+    Ctlsp_LtlTranslateIntoSNFRecursive(propNode, rightNode, formulaArray, index);
+
+    break;
+  case Ctlsp_OR_c:
+    leftNode  = createSNFnode(Ctlsp_FormulaReadLeftChild(formula), formulaArray, index);
+    rightNode = createSNFnode(Ctlsp_FormulaReadRightChild(formula), formulaArray, index);
+    newNode   = CtlspFunctionOr(leftNode, rightNode);
+    Ctlsp_LtlTranslateIntoSNFRecursive(propNode, newNode, formulaArray, index);
+
+    break;
+  case Ctlsp_THEN_c:
+    leftNode  = createSNFnode(Ctlsp_FormulaReadLeftChild(formula), formulaArray, index);
+    rightNode = createSNFnode(Ctlsp_FormulaReadRightChild(formula), formulaArray, index);
+    newNode   = CtlspFunctionOr(
+      Ctlsp_FormulaCreate(Ctlsp_NOT_c, leftNode, NIL(Ctlsp_Formula_t))
+      , rightNode);
+    Ctlsp_LtlTranslateIntoSNFRecursive(propNode, newNode, formulaArray, index);
+    break;
+  case Ctlsp_NOT_c:
+    if (!Ctlsp_isPropositionalFormula(formula)){
+      fprintf(vis_stderr,"SNF error: the LTL formula is not in NNF\n");
+    }
+    break;
+  case Ctlsp_X_c:
+    /*
+      propNode -> X leftNode
+     */
+    leftNode = createSNFnode(Ctlsp_FormulaReadLeftChild(formula), formulaArray, index);
+
+    newNode = Ctlsp_FormulaCreate(Ctlsp_X_c, leftNode, NIL(Ctlsp_Formula_t));
+    newNode = CtlspFunctionThen(propNode, newNode);
+     CtlspFormulaIncrementRefCount(newNode);
+    array_insert_last(Ctlsp_Formula_t *, formulaArray, newNode);
+
+    break;
+  case Ctlsp_F_c:
+    /*
+      propNode -> F leftNode
+     */
+    leftNode = createSNFnode(Ctlsp_FormulaReadLeftChild(formula), formulaArray, index);
+
+    newNode  = Ctlsp_FormulaCreate(Ctlsp_F_c, leftNode, NIL(Ctlsp_Formula_t));
+    newNode  = CtlspFunctionThen(propNode, newNode);
+     CtlspFormulaIncrementRefCount(newNode);
+    array_insert_last(Ctlsp_Formula_t *, formulaArray, newNode);
+
+    break;
+  case Ctlsp_G_c:
+    /*
+      propNode -> G leftNode
+    */
+    leftNode = createSNFnode(Ctlsp_FormulaReadLeftChild(formula), formulaArray, index);
+
+    newNode  = Ctlsp_FormulaCreate(Ctlsp_ID_c, util_strcat3(" SNFx","_", util_inttostr((*index)++)),
+				   (void *)util_strsav("1"));
+
+    result  = CtlspFunctionAnd(leftNode, newNode);
+    Ctlsp_LtlTranslateIntoSNFRecursive(propNode, result, formulaArray, index);
+    result   = Ctlsp_FormulaCreate(Ctlsp_X_c, result, NIL(Ctlsp_Formula_t));
+    Ctlsp_LtlTranslateIntoSNFRecursive(newNode, result, formulaArray, index);
+
+    break;
+  case Ctlsp_U_c:
+    /*
+      x --> a U b = x --> b + a*y
+		    y --> X(b + a*y)
+		    x --> F(b)
+    */
+    newNode = Ctlsp_FormulaCreate(Ctlsp_ID_c, util_strcat3(" SNFx","_", util_inttostr((*index)++)),
+				  (void *)util_strsav("1"));
+
+    leftNode  = createSNFnode(Ctlsp_FormulaReadLeftChild(formula), formulaArray, index);
+    rightNode = createSNFnode(Ctlsp_FormulaReadRightChild(formula), formulaArray, index);
+
+    result  = CtlspFunctionAnd(leftNode, newNode);
+    result  = CtlspFunctionOr(rightNode, result);
+
+    Ctlsp_LtlTranslateIntoSNFRecursive(propNode, result, formulaArray, index);
+
+    result   = Ctlsp_FormulaCreate(Ctlsp_X_c, result, NIL(Ctlsp_Formula_t));
+    Ctlsp_LtlTranslateIntoSNFRecursive(newNode, result, formulaArray, index);
+
+    result   = Ctlsp_FormulaCreate(Ctlsp_F_c, rightNode, NIL(Ctlsp_Formula_t));
+    Ctlsp_LtlTranslateIntoSNFRecursive(propNode, result, formulaArray, index);
+    break;
+  case Ctlsp_W_c:
+    /*
+      x --> a W b = x --> b + a*y
+		    y --> X(b + a*y)
+    */
+    newNode = Ctlsp_FormulaCreate(Ctlsp_ID_c, util_strcat3(" SNFx","_", util_inttostr((*index)++)),
+				  (void *)util_strsav("1"));
+
+    leftNode  = createSNFnode(Ctlsp_FormulaReadLeftChild(formula), formulaArray, index);
+    rightNode = createSNFnode(Ctlsp_FormulaReadRightChild(formula), formulaArray, index);
+
+    result  = CtlspFunctionAnd(leftNode, newNode);
+    result  = CtlspFunctionOr(rightNode, result);
+
+    Ctlsp_LtlTranslateIntoSNFRecursive(propNode, result, formulaArray, index);
+
+    result   = Ctlsp_FormulaCreate(Ctlsp_X_c, result, NIL(Ctlsp_Formula_t));
+    Ctlsp_LtlTranslateIntoSNFRecursive(newNode, result, formulaArray, index);
+    break;
+  case Ctlsp_R_c:
+    /*
+      x --> left R right = x --> left*right + right*y
+			   y --> X(left*rigt* + right*y)
+     */
+    newNode = Ctlsp_FormulaCreate(Ctlsp_ID_c, util_strcat3(" SNFx","_", util_inttostr((*index)++)),
+				  (void *)util_strsav("1"));
+    leftNode  = createSNFnode(Ctlsp_FormulaReadLeftChild(formula), formulaArray, index);
+    rightNode = createSNFnode(Ctlsp_FormulaReadRightChild(formula), formulaArray, index);
+
+    leftNode  = CtlspFunctionAnd(leftNode, rightNode);
+
+    result = CtlspFunctionAnd(rightNode, newNode);
+    result = CtlspFunctionOr(leftNode, result);
+
+    Ctlsp_LtlTranslateIntoSNFRecursive(propNode, result, formulaArray, index);
+
+    result = Ctlsp_FormulaCreate(Ctlsp_X_c, result, NIL(Ctlsp_Formula_t));
+    Ctlsp_LtlTranslateIntoSNFRecursive(newNode, result, formulaArray, index);
+
+    break;
+  default:
+    fail("unexpected node type in abbreviation-free formula\n");
+    return; /* not reached */
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Perform simple rewriting of a formula.]
+
+  Description [We return a formula which shares nothing with the input formula]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlsp_Formula_t *
+Ctlsp_LtlFormulaSimpleRewriting(
+  Ctlsp_Formula_t *formula)
+{
+  Ctlsp_Formula_t *F, *newF;
+  st_table *Utable = st_init_table(FormulaCompare, FormulaHash);
+  st_generator *stGen;
+  char *key;
+
+  /* copy the input formula (so that they share nothing) */
+  F = Ctlsp_LtlFormulaNegationNormalForm(formula);
+
+  /* hash into the 'Utable' */
+  F = Ctlsp_LtlFormulaHashIntoUniqueTable(F, Utable);
+
+  /* simple rewriting */
+  F = CtlspLtlFormulaSimpleRewriting_Aux(F, Utable);
+
+  /* copy F into 'newF' (they shares nothing) */
+  newF = Ctlsp_LtlFormulaNegationNormalForm(F);
+
+  /* free formulae in st_table */
+  st_foreach_item(Utable, stGen, &key, &F) {
+    if (F->type == Ctlsp_ID_c) {
+      FREE(F->left);
+      FREE(F->right);
+    }
+    FREE(F);
+  }
+  st_free_table(Utable);
+
+  return (newF);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Rewriting the LTL formula recursively.]
+
+  Description [Recursive call, used in Ctlsp_LtlFormulaSimpleRewriting() only.]
+
+  SideEffects [The given formula F might be freed (hence unrecoverable)]
+
+  SeeAlso     [Ctlsp_LtlFormulaSimpleRewriting]
+
+******************************************************************************/
+Ctlsp_Formula_t *
+CtlspLtlFormulaSimpleRewriting_Aux(
+  Ctlsp_Formula_t *F,
+  st_table *Utable)
+{
+  Ctlsp_Formula_t *left, *right;
+  Ctlsp_Formula_t *tmpf1, *tmpf2;
+  Ctlsp_Formula_t *True, *False;
+
+  if (F == NIL(Ctlsp_Formula_t))
+    return F;
+
+  if (F->type == Ctlsp_ID_c || F->type == Ctlsp_TRUE_c ||
+      F->type == Ctlsp_FALSE_c) {
+    F = Ctlsp_LtlFormulaHashIntoUniqueTable(F, Utable);
+    return F;
+  }
+
+#if 0
+  fprintf(vis_stdout, "\nRewriting ...\n");
+  Ctlsp_FormulaPrint(vis_stdout, F);
+  fprintf(vis_stdout, "\n");
+#endif
+
+  /* First of all, rewrite F->left, F->right */
+  left = CtlspLtlFormulaSimpleRewriting_Aux(F->left, Utable);
+#if 0
+  fprintf(vis_stdout, "\n... Rewriting(left)\n");
+  Ctlsp_FormulaPrint(vis_stdout, left);
+  fprintf(vis_stdout, "\n");
+#endif
+
+  right = CtlspLtlFormulaSimpleRewriting_Aux(F->right, Utable);
+#if 0
+  fprintf(vis_stdout, "\n... Rewriting(right)\n");
+  Ctlsp_FormulaPrint(vis_stdout, right);
+  fprintf(vis_stdout, "\n");
+#endif
+
+  /* in case we want to use TRUE/FALSE */
+  True = Ctlsp_LtlFormulaHashIntoUniqueTable(FormulaCreateWithType(Ctlsp_TRUE_c), Utable);
+  False = Ctlsp_LtlFormulaHashIntoUniqueTable(FormulaCreateWithType(Ctlsp_FALSE_c), Utable);
+
+  switch (F->type) {
+  case Ctlsp_AND_c:
+
+    /* r -> l :  l*r == r */
+    if (Ctlsp_LtlFormulaSimplyImply(right, left))
+      return right;
+
+    /* l -> r, l*r == l */
+    if (Ctlsp_LtlFormulaSimplyImply(left, right))
+      return left;
+
+    /* r -> !l, l*r == FALSE*/
+    tmpf1 = FormulaCreateWithType(Ctlsp_NOT_c);
+    tmpf1->left = left;
+    tmpf2 = Ctlsp_LtlFormulaNegationNormalForm(tmpf1);
+    FREE(tmpf1);
+    tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+    if (Ctlsp_LtlFormulaSimplyImply(right, tmpf2))
+      return False;
+
+    /* l -> !r, l*r == FALSE*/
+    tmpf1 = FormulaCreateWithType(Ctlsp_NOT_c);
+    tmpf1->left = right;
+    tmpf2 = Ctlsp_LtlFormulaNegationNormalForm(tmpf1);
+    FREE(tmpf1);
+    tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+    if (Ctlsp_LtlFormulaSimplyImply(left, tmpf2))
+      return False;
+
+    /* (ll R lr) * (ll R rr) == (ll) R (lr*rr) */
+    if (left->type == Ctlsp_R_c && right->type == Ctlsp_R_c) {
+      if (left->left == right->left) {
+	tmpf1 = FormulaCreateWithType(Ctlsp_AND_c);
+	tmpf1->left = left->right;
+	tmpf1->right = right->right;
+	CtlspFormulaIncrementRefCount(left->right);
+	CtlspFormulaIncrementRefCount(right->right);
+	tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+
+	tmpf2 = FormulaCreateWithType(Ctlsp_R_c);
+	tmpf2->left = left->left;
+	tmpf2->right = tmpf1;
+	CtlspFormulaIncrementRefCount(left->left);
+	CtlspFormulaIncrementRefCount(tmpf1);
+	tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+	return tmpf2;
+      }
+    }
+
+    /* (ll U lr) * (rl U lr) == (ll * rl) U (lr) */
+    if (left->type == Ctlsp_U_c && right->type == Ctlsp_U_c) {
+      if (left->right == right->right) {
+	tmpf1 = FormulaCreateWithType(Ctlsp_AND_c);
+	tmpf1->left = left->left;
+	tmpf1->right = right->left;
+	CtlspFormulaIncrementRefCount(left->left);
+	CtlspFormulaIncrementRefCount(right->left);
+	tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+
+	tmpf2 = FormulaCreateWithType(Ctlsp_U_c);
+	tmpf2->left = tmpf1;
+	tmpf2->right = left->right;
+	CtlspFormulaIncrementRefCount(tmpf1);
+	CtlspFormulaIncrementRefCount(left->right);
+	tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+	return tmpf2;
+      }
+    }
+
+    /* (X ll)*(X rl) == X (ll*rl) */
+    if (left->type == Ctlsp_X_c && right->type == Ctlsp_X_c) {
+      tmpf1 = FormulaCreateWithType(Ctlsp_AND_c);
+      tmpf1->left = left->left;
+      tmpf1->right = right->left;
+      CtlspFormulaIncrementRefCount(left->left);
+      CtlspFormulaIncrementRefCount(right->left);
+      tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+
+      tmpf2 = FormulaCreateWithType(Ctlsp_X_c);
+      tmpf2->left = tmpf1;
+      CtlspFormulaIncrementRefCount(tmpf1);
+      tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+      return tmpf2;
+    }
+
+    /* (ll R lr) * (rl U ll)   ==  ( (X lr * rl) U ll) * lr */
+    if (left->type == Ctlsp_R_c && right->type == Ctlsp_U_c) {
+      if (left->left == right->right) {
+	tmpf1 = FormulaCreateWithType(Ctlsp_X_c);
+	tmpf1->left = left->right;
+	CtlspFormulaIncrementRefCount(left->right);
+	tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+
+	if (right->left->type != Ctlsp_TRUE_c) {
+	  tmpf2 = FormulaCreateWithType(Ctlsp_AND_c);
+	  tmpf2->left = tmpf1;
+	  tmpf2->right = right->left;
+	  CtlspFormulaIncrementRefCount(tmpf1);
+	  CtlspFormulaIncrementRefCount(right->left);
+	  tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+	}
+
+	tmpf2 = FormulaCreateWithType(Ctlsp_U_c);
+	tmpf2->left = tmpf1;
+	tmpf2->right = left->left;
+	CtlspFormulaIncrementRefCount(tmpf1);
+	CtlspFormulaIncrementRefCount(left->left);
+	tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+
+	tmpf2 = FormulaCreateWithType(Ctlsp_AND_c);
+	tmpf2->left = tmpf1;
+	tmpf2->right = left->right;
+	CtlspFormulaIncrementRefCount(tmpf1);
+	CtlspFormulaIncrementRefCount(left->right);
+	tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+
+	return tmpf2;
+      }
+    }
+    /* (ll U lr) * (lr R rr)   ==  ( (X rr * ll) U rl) * rr */
+    if (left->type == Ctlsp_U_c && right->type == Ctlsp_R_c) {
+      if (left->right == right->left) {
+	tmpf1 = FormulaCreateWithType(Ctlsp_X_c);
+	tmpf1->left = right->right;
+	CtlspFormulaIncrementRefCount(right->right);
+	tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+
+	if (left->left->type != Ctlsp_TRUE_c) {
+	  tmpf2 = FormulaCreateWithType(Ctlsp_AND_c);
+	  tmpf2->left = tmpf1;
+	  tmpf2->right = left->left;
+	  CtlspFormulaIncrementRefCount(tmpf1);
+	  CtlspFormulaIncrementRefCount(left->left);
+	  tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+	}
+
+	tmpf2 = FormulaCreateWithType(Ctlsp_U_c);
+	tmpf2->left = tmpf1;
+	tmpf2->right = right->left;
+	CtlspFormulaIncrementRefCount(tmpf1);
+	CtlspFormulaIncrementRefCount(right->left);
+	tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+
+	tmpf2 = FormulaCreateWithType(Ctlsp_AND_c);
+	tmpf2->left = tmpf1;
+	tmpf2->right = right->right;
+	CtlspFormulaIncrementRefCount(tmpf1);
+	CtlspFormulaIncrementRefCount(right->right);
+	tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+
+	return tmpf2;
+      }
+    }
+
+    /* (ll R lr) * r, r=>ll  == lr *r */
+    if (left->type == Ctlsp_R_c &&
+	Ctlsp_LtlFormulaSimplyImply(right, left->left)) {
+      tmpf1 = FormulaCreateWithType(Ctlsp_AND_c);
+      tmpf1->left = left->right;
+      tmpf1->right = right;
+      CtlspFormulaIncrementRefCount(left->right);
+      CtlspFormulaIncrementRefCount(right);
+      tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+      return tmpf2;
+    }
+    /* l *(rl R rr), l=>rl  == l * rr */
+    if (right->type == Ctlsp_R_c &&
+	Ctlsp_LtlFormulaSimplyImply(left, right->left)) {
+      tmpf1 = FormulaCreateWithType(Ctlsp_AND_c);
+      tmpf1->left = left;
+      tmpf1->right = right->right;
+      CtlspFormulaIncrementRefCount(left);
+      CtlspFormulaIncrementRefCount(right->right);
+      tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+      return tmpf2;
+    }
+
+    /* (ll U lr) * r, r=>!ll   == lr * r */
+    if (left->type == Ctlsp_U_c) {
+      tmpf1 = FormulaCreateWithType(Ctlsp_NOT_c);
+      tmpf1->left = left->left;
+      tmpf2 = Ctlsp_LtlFormulaNegationNormalForm(tmpf1);
+      FREE(tmpf1);
+      tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+
+      if (Ctlsp_LtlFormulaSimplyImply(right, tmpf1)) {
+	tmpf1 = FormulaCreateWithType(Ctlsp_AND_c);
+	tmpf1->left = left->right;
+	tmpf1->right = right;
+	CtlspFormulaIncrementRefCount(left->right);
+	CtlspFormulaIncrementRefCount(right);
+	tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+	return tmpf2;
+      }
+    }
+    /* l * (rl U rr), l=>!rl   == l * rr */
+    if (right->type == Ctlsp_U_c) {
+      tmpf1 = FormulaCreateWithType(Ctlsp_NOT_c);
+      tmpf1->left = right->left;
+      tmpf2 = Ctlsp_LtlFormulaNegationNormalForm(tmpf1);
+      FREE(tmpf1);
+      tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+
+      if (Ctlsp_LtlFormulaSimplyImply(left, tmpf1)) {
+	tmpf1 = FormulaCreateWithType(Ctlsp_AND_c);
+	tmpf1->left = left;
+	tmpf1->right = right->right;
+	CtlspFormulaIncrementRefCount(left);
+	CtlspFormulaIncrementRefCount(right->right);
+	tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+	return tmpf2;
+      }
+    }
+
+    /* FG lrr * FG rrr = FG (lrr * rrr) */
+    if (Ctlsp_LtlFormulaIsFG(left) && Ctlsp_LtlFormulaIsFG(right)) {
+      tmpf1 = FormulaCreateWithType(Ctlsp_AND_c);
+      tmpf1->left = left->right->right;
+      tmpf1->right = right->right->right;
+      CtlspFormulaIncrementRefCount(left->right->right);
+      CtlspFormulaIncrementRefCount(right->right->right);
+      tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+
+      tmpf2 = FormulaCreateWithType(Ctlsp_R_c);
+      tmpf2->left = False;
+      tmpf2->right = tmpf1;
+      CtlspFormulaIncrementRefCount(False);
+      CtlspFormulaIncrementRefCount(tmpf1);
+      tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+
+      tmpf2 = FormulaCreateWithType(Ctlsp_U_c);
+      tmpf2->left = True;
+      tmpf2->right = tmpf1;
+      CtlspFormulaIncrementRefCount(True);
+      CtlspFormulaIncrementRefCount(tmpf1);
+      tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+      return tmpf2;
+    }
+
+    /* return  (l * r) */
+    tmpf1 = FormulaCreateWithType(Ctlsp_AND_c);
+    tmpf1->left = left;
+    tmpf1->right = right;
+    CtlspFormulaIncrementRefCount(left);
+    CtlspFormulaIncrementRefCount(right);
+    tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+    return tmpf2;
+
+  case Ctlsp_OR_c:
+
+    /* r -> l, l+r == l */
+    if (Ctlsp_LtlFormulaSimplyImply(right, left))
+      return left;
+
+    /* l -> r, l+r == r */
+    if (Ctlsp_LtlFormulaSimplyImply(left, right))
+      return right;
+
+    /* !r -> l, l+r == TRUE*/
+    tmpf1 = FormulaCreateWithType(Ctlsp_NOT_c);
+    tmpf1->left = right;
+    tmpf2 = Ctlsp_LtlFormulaNegationNormalForm(tmpf1);
+    FREE(tmpf1);
+    tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+    if (Ctlsp_LtlFormulaSimplyImply(tmpf2, left))
+      return True;
+
+    /* !l -> r, l+r == TRUE*/
+    tmpf1 = FormulaCreateWithType(Ctlsp_NOT_c);
+    tmpf1->left = left;
+    tmpf2 = Ctlsp_LtlFormulaNegationNormalForm(tmpf1);
+    FREE(tmpf1);
+    tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+    if (Ctlsp_LtlFormulaSimplyImply(tmpf2, right))
+      return True;
+
+    /* (ll U lr) + (ll U rr) == (ll) U (lr+rr) */
+    if (left->type == Ctlsp_U_c && right->type == Ctlsp_U_c) {
+      if (left->left == right->left) {
+	tmpf1 = FormulaCreateWithType(Ctlsp_OR_c);
+	tmpf1->left = left->right;
+	tmpf1->right = right->right;
+	CtlspFormulaIncrementRefCount(left->right);
+	CtlspFormulaIncrementRefCount(right->right);
+	tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+
+	tmpf2 = FormulaCreateWithType(Ctlsp_U_c);
+	tmpf2->left = left->left;
+	tmpf2->right = tmpf1;
+	CtlspFormulaIncrementRefCount(left->left);
+	CtlspFormulaIncrementRefCount(tmpf1);
+	tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+	return tmpf2;
+      }
+    }
+
+    /* (ll R lr) + (rl R lr) == (ll+rl) R (lr) */
+    if (left->type == Ctlsp_R_c && right->type == Ctlsp_R_c) {
+      if (left->right == right->right) {
+	tmpf1 = FormulaCreateWithType(Ctlsp_OR_c);
+	tmpf1->left = left->left;
+	tmpf1->right = right->left;
+	CtlspFormulaIncrementRefCount(left->left);
+	CtlspFormulaIncrementRefCount(right->left);
+	tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+
+	tmpf2 = FormulaCreateWithType(Ctlsp_R_c);
+	tmpf2->left = tmpf1;
+	tmpf2->right = left->right;
+	CtlspFormulaIncrementRefCount(tmpf1);
+	CtlspFormulaIncrementRefCount(left->right);
+	tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+	return tmpf2;
+      }
+    }
+
+    /* (X ll) + (X rl) == X (ll+rl) */
+    if (left->type == Ctlsp_X_c && right->type == Ctlsp_X_c) {
+      tmpf1 = FormulaCreateWithType(Ctlsp_OR_c);
+      tmpf1->left = left->left;
+      tmpf1->right = right->left;
+      CtlspFormulaIncrementRefCount(left->left);
+      CtlspFormulaIncrementRefCount(right->left);
+      tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+
+      tmpf2 = FormulaCreateWithType(Ctlsp_X_c);
+      tmpf2->left = tmpf1;
+      CtlspFormulaIncrementRefCount(tmpf1);
+      tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+      return tmpf2;
+    }
+
+    /* ll U lr  + rl R ll  == ((Xlr + rl) R ll) +lr */
+    if (left->type == Ctlsp_U_c && right->type == Ctlsp_R_c) {
+      if (left->left == right->right) {
+	tmpf1 = FormulaCreateWithType(Ctlsp_X_c);
+	tmpf1->left = left->right;
+	CtlspFormulaIncrementRefCount(left->right);
+	tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+
+	if (right->left->type != Ctlsp_FALSE_c) {
+	  tmpf2 = FormulaCreateWithType(Ctlsp_OR_c);
+	  tmpf2->left = tmpf1;
+	  tmpf2->right = right->left;
+	  CtlspFormulaIncrementRefCount(tmpf1);
+	  CtlspFormulaIncrementRefCount(right->left);
+	  tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+	}
+
+	tmpf2 = FormulaCreateWithType(Ctlsp_R_c);
+	tmpf2->left = tmpf1;
+	tmpf2->right = left->left;
+	CtlspFormulaIncrementRefCount(tmpf1);
+	CtlspFormulaIncrementRefCount(left->left);
+	tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+
+	tmpf2 = FormulaCreateWithType(Ctlsp_OR_c);
+	tmpf2->left = tmpf1;
+	tmpf2->right = left->right;
+	CtlspFormulaIncrementRefCount(tmpf1);
+	CtlspFormulaIncrementRefCount(left->right);
+	tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+
+	return tmpf2;
+      }
+    }
+
+    /* ll R lr  + lr U rr  == ((Xrr + ll) R lr) + rr */
+    if (left->type == Ctlsp_R_c && right->type == Ctlsp_U_c) {
+      if (left->right == right->left) {
+	tmpf1 = FormulaCreateWithType(Ctlsp_X_c);
+	tmpf1->left = right->right;
+	CtlspFormulaIncrementRefCount(right->right);
+	tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+
+	if (left->left->type != Ctlsp_FALSE_c) {
+	  tmpf2 = FormulaCreateWithType(Ctlsp_OR_c);
+	  tmpf2->left = tmpf1;
+	  tmpf2->right = left->left;
+	  CtlspFormulaIncrementRefCount(tmpf1);
+	  CtlspFormulaIncrementRefCount(left->left);
+	  tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+	}
+
+	tmpf2 = FormulaCreateWithType(Ctlsp_R_c);
+	tmpf2->left = tmpf1;
+	tmpf2->right = left->right;
+	CtlspFormulaIncrementRefCount(tmpf1);
+	CtlspFormulaIncrementRefCount(left->right);
+	tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+
+	tmpf2 = FormulaCreateWithType(Ctlsp_OR_c);
+	tmpf2->left = tmpf1;
+	tmpf2->right = right->right;
+	CtlspFormulaIncrementRefCount(tmpf1);
+	CtlspFormulaIncrementRefCount(right->right);
+	tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+
+	return tmpf2;
+      }
+    }
+
+    /* ll U lr + r , ll =>r  ==  lr + r ??? */
+    if (left->type == Ctlsp_U_c) {
+      if (Ctlsp_LtlFormulaSimplyImply(left->left, right)) {
+	tmpf1 = FormulaCreateWithType(Ctlsp_OR_c);
+	tmpf1->left = left->right;
+	tmpf1->right = right;
+	CtlspFormulaIncrementRefCount(left->right);
+	CtlspFormulaIncrementRefCount(right);
+	tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+	return tmpf2;
+      }
+    }
+
+    /* l + rl U rr ,  rl => l   ==  rr + l */
+    if (right->type == Ctlsp_U_c) {
+      if (Ctlsp_LtlFormulaSimplyImply(right->left, left)) {
+	tmpf1 = FormulaCreateWithType(Ctlsp_OR_c);
+	tmpf1->left = left;
+	tmpf1->right = right->right;
+	CtlspFormulaIncrementRefCount(left);
+	CtlspFormulaIncrementRefCount(right->right);
+	tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+	return tmpf2;
+      }
+    }
+
+    /* ll R lr + r ,  !ll => r   ==  lr + r */
+    if (left->type == Ctlsp_R_c) {
+      tmpf1 = FormulaCreateWithType(Ctlsp_NOT_c);
+      tmpf1->left = left->left;
+      tmpf2 = Ctlsp_LtlFormulaNegationNormalForm(tmpf1);
+      FREE(tmpf1);
+      tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+      if (Ctlsp_LtlFormulaSimplyImply(tmpf2, right)) {
+	tmpf1 = FormulaCreateWithType(Ctlsp_OR_c);
+	tmpf1->left = left->right;
+	tmpf1->right = right;
+	CtlspFormulaIncrementRefCount(left->right);
+	CtlspFormulaIncrementRefCount(right);
+	tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+	return tmpf2;
+      }
+    }
+
+    /* l + rl R rr ,  !rl => l   ==  rr + l */
+    if (right->type == Ctlsp_R_c) {
+      tmpf1 = FormulaCreateWithType(Ctlsp_NOT_c);
+      tmpf1->left = right->left;
+      tmpf2 = Ctlsp_LtlFormulaNegationNormalForm(tmpf1);
+      FREE(tmpf1);
+      tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+      if (Ctlsp_LtlFormulaSimplyImply(tmpf2, left)) {
+	tmpf1 = FormulaCreateWithType(Ctlsp_OR_c);
+	tmpf1->left = left;
+	tmpf1->right = right->right;
+	CtlspFormulaIncrementRefCount(left);
+	CtlspFormulaIncrementRefCount(right->right);
+	tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+	return tmpf2;
+      }
+    }
+
+    /* GF lrr + GF rrr = GF (lrr + rrr) */
+    if (Ctlsp_LtlFormulaIsGF(left) && Ctlsp_LtlFormulaIsGF(right)) {
+      tmpf1 = FormulaCreateWithType(Ctlsp_OR_c);
+      tmpf1->left = left->right->right;
+      tmpf1->right = right->right->right;
+      CtlspFormulaIncrementRefCount(left->right->right);
+      CtlspFormulaIncrementRefCount(right->right->right);
+      tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+
+      tmpf2 = FormulaCreateWithType(Ctlsp_U_c);
+      tmpf2->left = True;
+      tmpf2->right = tmpf1;
+      CtlspFormulaIncrementRefCount(True);
+      CtlspFormulaIncrementRefCount(tmpf1);
+      tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+
+      tmpf2 = FormulaCreateWithType(Ctlsp_R_c);
+      tmpf2->left = False;
+      tmpf2->right = tmpf1;
+      CtlspFormulaIncrementRefCount(False);
+      CtlspFormulaIncrementRefCount(tmpf1);
+      tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+      return tmpf2;
+    }
+
+    /* return  (l + r) */
+    tmpf1 = FormulaCreateWithType(Ctlsp_OR_c);
+    tmpf1->left = left;
+    tmpf1->right = right;
+    CtlspFormulaIncrementRefCount(left);
+    CtlspFormulaIncrementRefCount(right);
+    tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+    return tmpf2;
+
+  case Ctlsp_U_c:
+
+    /* l -> r : l U r == r */
+    if (Ctlsp_LtlFormulaSimplyImply(left, right))
+      return right;
+
+    /* l U FALSE = FALSE */
+    if (right->type == Ctlsp_FALSE_c)
+      return False;
+
+    /* (X ll) U (X rl) == X (ll U rl) */
+    if (left->type == Ctlsp_X_c && right->type == Ctlsp_X_c) {
+      tmpf1 = FormulaCreateWithType(Ctlsp_U_c);
+      tmpf1->left = left->left;
+      tmpf1->right = right->left;
+      CtlspFormulaIncrementRefCount(left->left);
+      CtlspFormulaIncrementRefCount(right->left);
+      tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+
+      tmpf2 = FormulaCreateWithType(Ctlsp_X_c);
+      tmpf2->left = tmpf1;
+      CtlspFormulaIncrementRefCount(tmpf1);
+      tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+      return tmpf2;
+    }
+
+    /* TRUE U (X rl) == X( TRUE U rl ) */
+    if (left->type == Ctlsp_TRUE_c && right->type == Ctlsp_X_c) {
+      tmpf1 = FormulaCreateWithType(Ctlsp_U_c);
+      tmpf1->left = True;
+      tmpf1->right = right->left;
+      CtlspFormulaIncrementRefCount(True);
+      CtlspFormulaIncrementRefCount(right->left);
+      tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+
+      tmpf2 = FormulaCreateWithType(Ctlsp_X_c);
+      tmpf2->left = tmpf1;
+      CtlspFormulaIncrementRefCount(tmpf1);
+      tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+      return tmpf2;
+    }
+
+    /* l->rl : l U (rl U rr) == rl U rr */
+    if (right->type == Ctlsp_U_c) {
+      if (Ctlsp_LtlFormulaSimplyImply(left, right->left)) {
+	return right;
+      }
+    }
+
+    /* (TRUE or anything) U (FG rrr) == FG rrr */
+    /* (TRUE or anything) U (GF rrr) == GF rrr */
+    if (/*left->type == Ctlsp_TRUE_c &&*/ Ctlsp_LtlFormulaIsFGorGF(right))
+      return right;
+
+    /* TRUE U (rl * FG rrrr) = F(rl) * FG(rrrr) */
+    /* TRUE U (rl * GF rrrr) = F(rl) * GF(rrrr) */
+    if (left->type == Ctlsp_TRUE_c && right->type == Ctlsp_AND_c) {
+      if (Ctlsp_LtlFormulaIsFGorGF(right->right)) {
+	tmpf1 = FormulaCreateWithType(Ctlsp_U_c);
+	tmpf1->left = True;
+	tmpf1->right = right->left;
+	CtlspFormulaIncrementRefCount(True);
+	CtlspFormulaIncrementRefCount(right->left);
+	tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+
+	tmpf2 = FormulaCreateWithType(Ctlsp_AND_c);
+	tmpf2->left = tmpf1;
+	tmpf2->right = right->right;
+	CtlspFormulaIncrementRefCount(tmpf1);
+	CtlspFormulaIncrementRefCount(right->right);
+	tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+	return tmpf2;
+      }
+    }
+
+    /* TRUE U (FG rlrr * rr) == (FG rlrr) * F(rr) */
+    /* TRUE U (GF rlrr * rr) == (GF rlrr) * F(rr) */
+    if (left->type == Ctlsp_TRUE_c && right->type == Ctlsp_AND_c) {
+      if (Ctlsp_LtlFormulaIsFGorGF(right->left)) {
+	tmpf1 = FormulaCreateWithType(Ctlsp_U_c);
+	tmpf1->left = True;
+	tmpf1->right = right->right;
+	CtlspFormulaIncrementRefCount(True);
+	CtlspFormulaIncrementRefCount(right->right);
+	tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+
+	tmpf2 = FormulaCreateWithType(Ctlsp_AND_c);
+	tmpf2->left = right->left;
+	tmpf2->right = tmpf1;
+	CtlspFormulaIncrementRefCount(right->left);
+	CtlspFormulaIncrementRefCount(tmpf1);
+	tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+	return tmpf2;
+      }
+    }
+
+    /* !r -> l : (l U r) == TRUE U r */
+    tmpf1 = FormulaCreateWithType(Ctlsp_NOT_c);
+    tmpf1->left = right;
+    tmpf2 = Ctlsp_LtlFormulaNegationNormalForm(tmpf1);
+    FREE(tmpf1);
+    tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+    if (Ctlsp_LtlFormulaSimplyImply(tmpf2, left)) {
+      tmpf1 = FormulaCreateWithType(Ctlsp_U_c);
+      tmpf1->left = True;
+      tmpf1->right = right;
+      CtlspFormulaIncrementRefCount(True);
+      CtlspFormulaIncrementRefCount(right);
+      tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+      return tmpf2;
+    }
+
+    /* (ll + lr) U r,  ll => r   == (lr U r) */
+    if (left->type == Ctlsp_OR_c) {
+      if (Ctlsp_LtlFormulaSimplyImply(left->left, right)) {
+	tmpf1 = FormulaCreateWithType(Ctlsp_U_c);
+	tmpf1->left = left->right;
+	tmpf1->right = right;
+	CtlspFormulaIncrementRefCount(left->right);
+	CtlspFormulaIncrementRefCount(right);
+	tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+	return tmpf2;
+      }
+    }
+
+    /* (ll + lr) U r,  lr => r   == (ll U r) */
+    if (left->type == Ctlsp_OR_c) {
+      if (Ctlsp_LtlFormulaSimplyImply(left->right, right)) {
+	tmpf1 = FormulaCreateWithType(Ctlsp_U_c);
+	tmpf1->left = left->left;
+	tmpf1->right = right;
+	CtlspFormulaIncrementRefCount(left->left);
+	CtlspFormulaIncrementRefCount(right);
+	tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+	return tmpf2;
+      }
+    }
+
+
+    /* return  (left U right) */
+    tmpf1 = FormulaCreateWithType(Ctlsp_U_c);
+    tmpf1->left = left;
+    tmpf1->right = right;
+    CtlspFormulaIncrementRefCount(left);
+    CtlspFormulaIncrementRefCount(right);
+    tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+    return tmpf2;
+
+  case Ctlsp_R_c:
+
+    /* r -> l : l R r == r */
+    if (Ctlsp_LtlFormulaSimplyImply(right,left))
+      return right;
+
+    /* l R TRUE == TRUE */
+    if (right->type == Ctlsp_TRUE_c)
+      return True;
+
+    /* (X ll) R (X rl) == X (ll R rl) */
+    if (left->type == Ctlsp_X_c && right->type == Ctlsp_X_c) {
+      tmpf1 = FormulaCreateWithType(Ctlsp_R_c);
+      tmpf1->left = left->left;
+      tmpf1->right = right->left;
+      CtlspFormulaIncrementRefCount(left->left);
+      CtlspFormulaIncrementRefCount(right->left);
+      tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+
+      tmpf2 = FormulaCreateWithType(Ctlsp_X_c);
+      tmpf2->left = tmpf1;
+      CtlspFormulaIncrementRefCount(tmpf1);
+      tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+      return tmpf2;
+    }
+
+    /* FALSE R (X rl) == X( FALSE R rl) */
+    if (left->type == Ctlsp_TRUE_c && right->type == Ctlsp_X_c) {
+      tmpf1 = FormulaCreateWithType(Ctlsp_R_c);
+      tmpf1->left = False;
+      tmpf1->right = right->left;
+      CtlspFormulaIncrementRefCount(False);
+      CtlspFormulaIncrementRefCount(right->left);
+      tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+
+      tmpf2 = FormulaCreateWithType(Ctlsp_X_c);
+      tmpf2->left = tmpf1;
+      CtlspFormulaIncrementRefCount(tmpf1);
+      tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+      return tmpf2;
+    }
+
+    /* rl->l :  l R (rl R rr) == (rl R rr) */
+    if (right->type == Ctlsp_R_c)
+      if (Ctlsp_LtlFormulaSimplyImply(right->left, left))
+	return right;
+
+    /* (FALSE or anything) R (FG rrr) == FG rrr */
+    /* (FALSE or anything) R (GF rrr) == GF rrr */
+    if (/*left->type == Ctlsp_FALSE_c &&*/ Ctlsp_LtlFormulaIsFGorGF(right))
+      return right;
+
+    /* FALSE R (rl + FG rrrr) = G(rl) + FG(rrrr) */
+    /* FALSE R (rl + GF rrrr) = G(rl) + GF(rrrr) */
+    if (left->type == Ctlsp_FALSE_c && right->type == Ctlsp_OR_c) {
+      if (Ctlsp_LtlFormulaIsFGorGF(right->right)) {
+	tmpf1 = FormulaCreateWithType(Ctlsp_R_c);
+	tmpf1->left = False;
+	tmpf1->right = right->left;
+	CtlspFormulaIncrementRefCount(False);
+	CtlspFormulaIncrementRefCount(right->left);
+	tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+
+	tmpf2 = FormulaCreateWithType(Ctlsp_OR_c);
+	tmpf2->left = tmpf1;
+	tmpf2->right = right->right;
+	CtlspFormulaIncrementRefCount(tmpf1);
+	CtlspFormulaIncrementRefCount(right->right);
+	tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+	return tmpf2;
+      }
+    }
+
+    /* FALSE R (FG rlrr + rr) = FG(rlrr) + G(rr) */
+    /* FALSE R (GF rlrr + rr) = GF(rlrr) + G(rr) */
+    if (left->type == Ctlsp_FALSE_c && right->type == Ctlsp_OR_c) {
+      if (Ctlsp_LtlFormulaIsFGorGF(right->left)) {
+	tmpf1 = FormulaCreateWithType(Ctlsp_R_c);
+	tmpf1->left = False;
+	tmpf1->right = right->right;
+	CtlspFormulaIncrementRefCount(False);
+	CtlspFormulaIncrementRefCount(right->right);
+	tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+
+	tmpf2 = FormulaCreateWithType(Ctlsp_OR_c);
+	tmpf2->left = tmpf1;
+	tmpf2->right = right->left;
+	CtlspFormulaIncrementRefCount(tmpf1);
+	CtlspFormulaIncrementRefCount(right->left);
+	tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+	return tmpf2;
+      }
+    }
+
+    /* r -> !l : (l R r) == FALSE R r */
+    tmpf1 = FormulaCreateWithType(Ctlsp_NOT_c);
+    tmpf1->left = left;
+    tmpf2 = Ctlsp_LtlFormulaNegationNormalForm(tmpf1);
+    FREE(tmpf1);
+    tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+    if (Ctlsp_LtlFormulaSimplyImply(right, tmpf2)) {
+      tmpf1 = FormulaCreateWithType(Ctlsp_R_c);
+      tmpf1->left = False;
+      tmpf1->right = right;
+      CtlspFormulaIncrementRefCount(False);
+      CtlspFormulaIncrementRefCount(right);
+      tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+      return tmpf2;
+    }
+
+    /* r=>ll : (ll * lr) R r  ==  lr R r */
+    if (left->type == Ctlsp_AND_c) {
+      if (Ctlsp_LtlFormulaSimplyImply(right, left->left)) {
+	tmpf1 = FormulaCreateWithType(Ctlsp_R_c);
+	tmpf1->left = left->right;
+	tmpf1->right = right;
+	CtlspFormulaIncrementRefCount(left->right);
+	CtlspFormulaIncrementRefCount(right);
+	tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+	return tmpf2;
+      }
+    }
+
+    /* r=>lr : (ll * lr) R r  ==  ll R r */
+    if (left->type == Ctlsp_AND_c) {
+      if (Ctlsp_LtlFormulaSimplyImply(right, left->right)) {
+	tmpf1 = FormulaCreateWithType(Ctlsp_R_c);
+	tmpf1->left = left->left;
+	tmpf1->right = right;
+	CtlspFormulaIncrementRefCount(left->left);
+	CtlspFormulaIncrementRefCount(right);
+	tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+	return tmpf2;
+      }
+    }
+
+
+    /* return  (left R right) */
+    tmpf1 = FormulaCreateWithType(Ctlsp_R_c);
+    tmpf1->left = left;
+    tmpf1->right = right;
+    CtlspFormulaIncrementRefCount(left);
+    CtlspFormulaIncrementRefCount(right);
+    tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+    return tmpf2;
+
+  case Ctlsp_X_c:
+
+    /* X(TRUE) == TRUE */
+    /* X(FALSE) == FALSE */
+    if (left->type == Ctlsp_TRUE_c || left->type == Ctlsp_FALSE_c)
+      return left;
+
+    /* X(FGorGF) == FGorGF */
+    if (Ctlsp_LtlFormulaIsFGorGF(left))
+      return left;
+
+    /* X(ll + FGorGF lrrr) == X(ll) + FGorGF lrrr */
+    /* X(ll * FGorGF lrrr) == X(ll) * FGorGF lrrr */
+    if (left->type == Ctlsp_AND_c || left->type == Ctlsp_OR_c) {
+      if (Ctlsp_LtlFormulaIsFGorGF(left->right)) {
+	tmpf1 = FormulaCreateWithType(Ctlsp_X_c);
+	tmpf1->left = left->left;
+	CtlspFormulaIncrementRefCount(left->left);
+	tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+
+	tmpf2 = FormulaCreateWithType(left->type);
+	tmpf2->left = tmpf1;
+	tmpf2->right = left->right;
+	CtlspFormulaIncrementRefCount(tmpf1);
+	CtlspFormulaIncrementRefCount(left->right);
+	tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+	return tmpf2;
+      }
+    }
+
+    /* X(FGorGF llrr + lr) ==  FGorGF llrr + X(lr) */
+    /* X(FGorGF llrr * lr) ==  FGorGF llrr * X(lr) */
+    if (left->type == Ctlsp_AND_c || left->type == Ctlsp_OR_c) {
+      if (Ctlsp_LtlFormulaIsFGorGF(left->left)) {
+	tmpf1 = FormulaCreateWithType(Ctlsp_X_c);
+	tmpf1->left = left->right;
+	CtlspFormulaIncrementRefCount(left->right);
+	tmpf1 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+
+	tmpf2 = FormulaCreateWithType(left->type);
+	tmpf2->left = left->left;
+	tmpf2->right = tmpf1;
+	CtlspFormulaIncrementRefCount(left->left);
+	CtlspFormulaIncrementRefCount(tmpf1);
+	tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf2, Utable);
+	return tmpf2;
+      }
+    }
+
+    /* return X(left) */
+    tmpf1 = FormulaCreateWithType(Ctlsp_X_c);
+    tmpf1->left = left;
+    CtlspFormulaIncrementRefCount(left);
+    tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+    return tmpf2;
+
+  case Ctlsp_NOT_c:
+
+    /* return !(left) */
+    tmpf1 = FormulaCreateWithType(Ctlsp_NOT_c);
+    tmpf1->left = left;
+    CtlspFormulaIncrementRefCount(left);
+    tmpf2 = Ctlsp_LtlFormulaHashIntoUniqueTable(tmpf1, Utable);
+    return tmpf2;
+
+  default:
+    assert(0);
+  }
+  return NIL(Ctlsp_Formula_t);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Increments the reference count of a formula.]
+
+  Description [The function increments the reference count of a formula. If
+  the formula is NULL, the function does nothing.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+CtlspFormulaIncrementRefCount(
+  Ctlsp_Formula_t *formula)
+{
+  if(formula!=NIL(Ctlsp_Formula_t)) {
+    ++(formula->refCount);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Decrements the reference count of a formula.]
+
+  Description [The function decrements the reference count of formula and if
+  the reference count reaches 0, the formula is freed. If the formula is NULL,
+  the function does nothing. It is an error to decrement the reference count
+  below 0.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+CtlspFormulaDecrementRefCount(
+  Ctlsp_Formula_t *formula)
+{
+  if(formula!=NIL(Ctlsp_Formula_t)) {
+    assert(formula->refCount>0);
+    if(--(formula->refCount) == 0)
+      CtlspFormulaFree(formula);
+  }
+}
+/**Function********************************************************************
+
+  Synopsis    [Adds formula to the end of globalFormulaArray.]
+
+  SideEffects [Manipulates the global variable globalFormulaArray.]
+
+  SeeAlso     [CtlspYyparse]
+
+******************************************************************************/
+void
+CtlspFormulaAddToGlobalArray(
+  Ctlsp_Formula_t * formula)
+{
+  array_insert_last(Ctlsp_Formula_t *, globalFormulaArray, formula);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a CTL* formula.]
+
+  Description [The function frees all memory associated with the formula,
+  including all MDDs and all character strings (however, does not free
+  dbgInfo.originalFormula). It also decrements the reference counts of its two
+  chidren. The function does nothing if formula is NULL.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_FormulaArrayFree]
+
+******************************************************************************/
+void
+CtlspFormulaFree(
+  Ctlsp_Formula_t * formula)
+{
+  if (formula != NIL(Ctlsp_Formula_t)) {
+
+    /*
+     * Free any fields that are not NULL.
+     */
+
+    if (formula->type == Ctlsp_ID_c){
+      FREE(formula->left);
+      FREE(formula->right);
+    }
+    else {
+      if (formula->left  != NIL(Ctlsp_Formula_t)) {
+	CtlspFormulaDecrementRefCount(formula->left);
+      }
+      if (formula->right != NIL(Ctlsp_Formula_t)) {
+	CtlspFormulaDecrementRefCount(formula->right);
+      }
+    }
+
+    if (formula->states != NIL(mdd_t))
+      mdd_free(formula->states);
+    if (formula->underapprox != NIL(mdd_t))
+      mdd_free(formula->underapprox);
+    if (formula->overapprox != NIL(mdd_t))
+      mdd_free(formula->overapprox);
+
+    if (formula->dbgInfo.data != NIL(void)){
+      (*formula->dbgInfo.freeFn)(formula);
+    }
+
+    FREE(formula);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Create a binary string of given value with size of interval.]
+
+  Description [The value is a binary string starting with 'b', a
+  hexadecimal string starting with 'x', or an integer string.  If value
+  does not fit the interval, or the binary string is not of the
+  correct length, 0 is return.  Otherwise 1 is returned.  The result
+  string is saved at given pointer.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+CtlspStringChangeValueStrToBinString(
+  char *value,
+  char *binValueStr,
+  int  interval)
+{
+  int i;
+  long int num, mask;
+  double maxNum;
+  char *ptr;
+
+  mask = 1;
+  maxNum = pow(2.0,(double)interval);
+  errno = 0;
+
+  if(value[0] == 'b'){
+    if ((int)strlen(value)-1 == interval){
+			for(i=1;i<=interval;i++){
+	if (value[i] == '0' || value[i] == '1'){
+	  binValueStr[i-1] =  value[i];
+	}else{
+	  return 0;
+	}
+      }
+      binValueStr[interval] = '\0';
+    }else{
+      return 0;
+    }
+  }else if (value[0] == 'x'){
+    for(i=1; i < (int)strlen(value); i++){
+      if (!isxdigit((int)value[i])){
+	return 0;
+      }
+    }
+    num = strtol(++value,&ptr,16);
+    if (errno) return 0;
+    if (num >= maxNum) return 0;
+    for(i=0;i<interval;i++){
+      if(num & (mask<<i)) binValueStr[interval-i-1] = '1';
+      else binValueStr[interval-i-1] = '0';
+    }
+    binValueStr[interval] = '\0';
+  }else{
+    for(i=0;i<(int)strlen(value);i++){
+      if (!isdigit((int)value[i])){
+	return 0;
+      }
+    }
+    num = strtol(value,&ptr,0);
+    if (errno) return 0;
+    if (num >= maxNum) return 0;
+    mask = 1;
+    for(i=0;i<interval;i++){
+      if(num & (mask<<i)) binValueStr[interval-i-1] = '1';
+      else binValueStr[interval-i-1] = '0';
+    }
+    binValueStr[interval] = '\0';
+  }
+
+  return(1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Change [] to <>]
+
+  Description []
+
+  SideEffects [The input string contains ...[num] and this function changes it
+  to ...<num>.]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+CtlspChangeBracket(
+  char *inStr)
+{
+  int i, j;
+  char *str;
+
+  j = 0;
+  for (i=0;i<(int)strlen(inStr)+1;i++){
+    if (inStr[i] != ' '){
+      inStr[i-j] = inStr[i];
+    }else{
+      j++;
+    }
+  }
+
+  if (changeBracket == 0)
+    return;
+
+  str = strchr(inStr,'[');
+  if (str == NULL) return;
+
+  *str = '<';
+  str = strchr(inStr,']');
+  *str = '>';
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Parse a given vector string.]
+
+  Description [Parse given vector string of the form of var<i:j> and
+  string var is returned. Other information such as i, j, interval between
+  i and j, and increment or decrement from i to j are saved.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+char *
+CtlspGetVectorInfoFromStr(
+  char *str,
+  int  *start,
+  int  *end,
+  int  *interval,
+  int  *inc)
+{
+  char *str1, *str2, *str3;
+  char *startStr, *endStr;
+  char *name, *ptr;
+
+  str1 = strchr(str,'[');
+  str2 = strchr(str,':');
+  str3 = strchr(str,']');
+  startStr = ALLOC(char, str2-str1);
+  endStr = ALLOC(char, str3-str2);
+  name = ALLOC(char, str1-str+1);
+
+  (void) strncpy(name, str, str1-str);
+  (void) strncpy(startStr, str1+1, str2-str1-1);
+  (void) strncpy(endStr, str2+1, str3-str2-1);
+
+  startStr[str2-str1-1] = '\0';
+  endStr[str3-str2-1] = '\0';
+  name[str1-str] = '\0';
+  *start = strtol(startStr,&ptr,0);
+  *end = strtol(endStr,&ptr,0);
+  if(*start > *end){
+      *inc = -1;
+      *interval = *start - *end + 1;
+  } else {
+      *inc = 1;
+      *interval = *end - *start + 1;
+  }
+  FREE(startStr);
+  FREE(endStr);
+  return name;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Insert macro formula into symbol table.]
+
+  Description [If the name is already in table return 0, otherwise insert the
+  formula into the table and return 1]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+CtlspFormulaAddToTable(
+  char *name,
+  Ctlsp_Formula_t *formula,
+  st_table *macroTable)
+{
+  if(macroTable == NIL(st_table)){
+    macroTable = st_init_table(strcmp, st_strhash);
+  }
+  if(st_is_member(macroTable, name)){
+    return 0;
+  }
+  st_insert(macroTable, name, (char *)formula);
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Get macro formula from symbol table]
+
+  Description [If macro string is not found in table, NULL pointer is returned]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlsp_Formula_t *
+CtlspFormulaFindInTable(
+  char *name,
+  st_table *macroTable)
+{
+  Ctlsp_Formula_t *formula;
+  if (st_lookup(macroTable, name, &formula)){
+    return (Ctlsp_FormulaDup(formula));
+  }else{
+    return NIL(Ctlsp_Formula_t);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso [FormulaTestIsForallQuantifier]
+
+******************************************************************************/
+Ctlsp_FormulaClass
+CtlspCheckClassOfExistentialFormulaRecur(
+  Ctlsp_Formula_t *formula,
+  boolean parity)
+{
+  Ctlsp_FormulaClass result;
+
+  Ctlsp_FormulaType formulaType = Ctlsp_FormulaReadType(formula);
+  Ctlsp_Formula_t *rightFormula, *leftFormula;
+  Ctlsp_FormulaClass resultLeft, resultRight, tempResult, currentClass;
+
+  /* Depending on the formula type, create result or recur */
+  switch (formulaType) {
+  case Ctlsp_E_c:
+    leftFormula = Ctlsp_FormulaReadLeftChild(formula);
+    resultLeft = CtlspCheckClassOfExistentialFormulaRecur(leftFormula, parity);
+      resultRight = Ctlsp_QuantifierFree_c;
+    tempResult = CtlspResolveClass(resultLeft, resultRight);
+    if (!parity){
+      currentClass = Ctlsp_ECTL_c;
+    }else{
+      currentClass = Ctlsp_ACTL_c;
+    }
+    result = CtlspResolveClass(currentClass, tempResult);
+    break;
+  case Ctlsp_A_c:
+    /* The formula is supposed to be only existential */
+    error_append("Inconsistency detected in function ");
+    error_append("FormulaTestIsForallQuantifier\n");
+    result = Ctlsp_invalid_c;
+    break;
+  case Ctlsp_OR_c:
+  case Ctlsp_AND_c:
+    rightFormula = Ctlsp_FormulaReadRightChild(formula);
+    leftFormula = Ctlsp_FormulaReadLeftChild(formula);
+    resultLeft = CtlspCheckClassOfExistentialFormulaRecur(leftFormula, parity);
+    resultRight = CtlspCheckClassOfExistentialFormulaRecur(rightFormula, parity);
+    result = CtlspResolveClass(resultLeft, resultRight);
+    break;
+  case Ctlsp_NOT_c:
+    parity = !parity;
+    leftFormula = Ctlsp_FormulaReadLeftChild(formula);
+    result = CtlspCheckClassOfExistentialFormulaRecur(leftFormula, parity);
+    break;
+  case Ctlsp_ID_c:
+  case Ctlsp_TRUE_c:
+  case Ctlsp_FALSE_c:
+     result = Ctlsp_QuantifierFree_c;
+     break;
+  case Ctlsp_Cmp_c:
+    result = Ctlsp_Mixed_c;
+    break;
+  default:
+    error_append("Unexpected operator detected.");
+    result = Ctlsp_invalid_c;
+    break;
+  }
+
+  return result;
+
+} /* End of FormulaTestIsForallQuantifier */
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso []
+
+******************************************************************************/
+Ctlsp_FormulaClass
+CtlspResolveClass(
+  Ctlsp_FormulaClass class1,
+  Ctlsp_FormulaClass class2)
+{
+  Ctlsp_FormulaClass result;
+
+  if ((class1 == Ctlsp_Mixed_c) || (class2 == Ctlsp_Mixed_c)){
+    result = Ctlsp_Mixed_c;
+  }else if (class1 == Ctlsp_QuantifierFree_c){
+    result = class2;
+  }else if (class2 == Ctlsp_QuantifierFree_c){
+    result = class1;
+  }else if (class1 == class2){
+    result = class1;
+  }else{
+    result = Ctlsp_Mixed_c;
+  }
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Performs a recursive step of Ctlsp_FormulaConvertToCTL() ]
+
+  Description []
+
+  SideEffects []
+
+  Remarks []
+
+  SeeAlso []
+
+******************************************************************************/
+Ctlp_Formula_t *
+CtlspFormulaConvertToCTL(
+  Ctlsp_Formula_t *formula)
+{
+  Ctlp_Formula_t *newNode, *leftNode, *rightNode;
+  Ctlsp_Formula_t *childNode;
+  char *variableNameCopy, *valueNameCopy;
+
+  if (formula == NIL(Ctlsp_Formula_t)) {
+    return NIL(Ctlp_Formula_t);
+  }
+  /*
+   * Recursively convert each subformula.
+   */
+  switch(formula->type) {
+  case Ctlsp_E_c:
+    childNode = formula->left;
+    switch(childNode->type) {
+    case Ctlsp_X_c:
+      newNode = Ctlp_FormulaCreate(Ctlp_EX_c,
+				   CtlspFormulaConvertToCTL(childNode->left),
+				   NIL(Ctlsp_Formula_t));
+      break;
+    case Ctlsp_F_c:
+      newNode = Ctlp_FormulaCreate(Ctlp_EF_c,
+				   CtlspFormulaConvertToCTL(childNode->left),
+				   NIL(Ctlsp_Formula_t));
+      break;
+    case Ctlsp_U_c:
+      newNode = Ctlp_FormulaCreate(Ctlp_EU_c,
+				   CtlspFormulaConvertToCTL(childNode->left),
+				   CtlspFormulaConvertToCTL(childNode->right));
+      break;
+    case Ctlsp_R_c:
+      /* E(f R g) => !A( !f U !g) */
+
+      leftNode  =  Ctlp_FormulaCreate(Ctlp_NOT_c,
+		   CtlspFormulaConvertToCTL(childNode->left),
+		   NIL(Ctlsp_Formula_t));
+      rightNode =  Ctlp_FormulaCreate(Ctlp_NOT_c,
+		   CtlspFormulaConvertToCTL(childNode->right),
+		   NIL(Ctlsp_Formula_t));
+
+      newNode = Ctlp_FormulaCreate(Ctlp_AU_c, leftNode, rightNode);
+      newNode = Ctlp_FormulaCreate(Ctlp_NOT_c, newNode, NIL(Ctlsp_Formula_t));
+
+      break;
+    case Ctlsp_W_c:
+      /* E(f W g) => !A(!g U !(f + g)) */
+
+      leftNode  =  Ctlp_FormulaCreate(Ctlp_NOT_c,
+		   CtlspFormulaConvertToCTL(childNode->right),
+		   NIL(Ctlsp_Formula_t));
+      rightNode =  Ctlp_FormulaCreate(Ctlp_OR_c,
+		   CtlspFormulaConvertToCTL(childNode->left),
+		   CtlspFormulaConvertToCTL(childNode->right));
+      rightNode =  Ctlp_FormulaCreate(Ctlp_NOT_c, rightNode,
+		   NIL(Ctlsp_Formula_t));
+
+      newNode = Ctlp_FormulaCreate(Ctlp_AU_c, leftNode, rightNode);
+      newNode = Ctlp_FormulaCreate(Ctlp_NOT_c, newNode, NIL(Ctlsp_Formula_t));
+
+      break;
+    case Ctlsp_G_c:
+      newNode = Ctlp_FormulaCreate(Ctlp_EG_c,
+				   CtlspFormulaConvertToCTL(childNode->left),
+				   NIL(Ctlsp_Formula_t));
+      break;
+    default:
+      fail("Unexpected type");
+    } /* switch: childNode->type */
+    break;
+  case Ctlsp_A_c:
+    childNode = formula->left;
+    switch(childNode->type) {
+    case Ctlsp_X_c:
+      newNode = Ctlp_FormulaCreate(Ctlp_AX_c,
+				   CtlspFormulaConvertToCTL(childNode->left),
+				   NIL(Ctlsp_Formula_t));
+      break;
+    case Ctlsp_F_c:
+      newNode = Ctlp_FormulaCreate(Ctlp_AF_c,
+				   CtlspFormulaConvertToCTL(childNode->left),
+				   NIL(Ctlsp_Formula_t));
+      break;
+    case Ctlsp_U_c:
+      newNode = Ctlp_FormulaCreate(Ctlp_AU_c,
+				   CtlspFormulaConvertToCTL(childNode->left),
+				   CtlspFormulaConvertToCTL(childNode->right));
+      break;
+    case Ctlsp_R_c:
+      /* A(f R g) => !E( !f U !g) */
+
+      leftNode  =  Ctlp_FormulaCreate(Ctlp_NOT_c,
+		   CtlspFormulaConvertToCTL(childNode->left),
+		   NIL(Ctlsp_Formula_t));
+      rightNode =  Ctlp_FormulaCreate(Ctlp_NOT_c,
+		   CtlspFormulaConvertToCTL(childNode->right),
+		   NIL(Ctlsp_Formula_t));
+
+      newNode = Ctlp_FormulaCreate(Ctlp_EU_c, leftNode, rightNode);
+      newNode = Ctlp_FormulaCreate(Ctlp_NOT_c, newNode, NIL(Ctlsp_Formula_t));
+
+      break;
+    case Ctlsp_W_c:
+      /* A(f W g) => !E(!g U !(f + g)) */
+
+      leftNode  =  Ctlp_FormulaCreate(Ctlp_NOT_c,
+		   CtlspFormulaConvertToCTL(childNode->right),
+		   NIL(Ctlsp_Formula_t));
+      rightNode =  Ctlp_FormulaCreate(Ctlp_OR_c,
+		   CtlspFormulaConvertToCTL(childNode->left),
+		   CtlspFormulaConvertToCTL(childNode->right));
+      rightNode =  Ctlp_FormulaCreate(Ctlp_NOT_c, rightNode,
+		   NIL(Ctlsp_Formula_t));
+
+      newNode = Ctlp_FormulaCreate(Ctlp_EU_c, leftNode, rightNode);
+      newNode = Ctlp_FormulaCreate(Ctlp_NOT_c, newNode, NIL(Ctlsp_Formula_t));
+
+      break;
+    case Ctlsp_G_c:
+      newNode = Ctlp_FormulaCreate(Ctlp_AG_c,
+				   CtlspFormulaConvertToCTL(childNode->left),
+				   NIL(Ctlsp_Formula_t));
+      break;
+    default:
+      fail("Unexpected type");
+    } /* switch: childNode->type */
+    break;
+
+  case Ctlsp_ID_c:
+    /* Make a copy of the name, and create a new formula. */
+    variableNameCopy = util_strsav((char *)(formula->left));
+    valueNameCopy = util_strsav((char *)(formula->right));
+    newNode = Ctlp_FormulaCreate(Ctlp_ID_c, variableNameCopy, valueNameCopy);
+    break;
+
+  case Ctlsp_THEN_c:
+    newNode = Ctlp_FormulaCreate(Ctlp_THEN_c,
+				 CtlspFormulaConvertToCTL(formula->left) ,
+				 CtlspFormulaConvertToCTL(formula->right) );
+    break;
+  case Ctlsp_OR_c:
+    newNode = Ctlp_FormulaCreate(Ctlp_OR_c,
+				 CtlspFormulaConvertToCTL(formula->left) ,
+				 CtlspFormulaConvertToCTL(formula->right) );
+    break;
+  case Ctlsp_AND_c:
+    newNode = Ctlp_FormulaCreate(Ctlp_AND_c,
+				 CtlspFormulaConvertToCTL(formula->left) ,
+				 CtlspFormulaConvertToCTL(formula->right) );
+    break;
+  case Ctlsp_NOT_c:
+    newNode = Ctlp_FormulaCreate(Ctlp_NOT_c,
+				 CtlspFormulaConvertToCTL(formula->left) ,
+				 CtlspFormulaConvertToCTL(formula->right) );
+    break;
+  case Ctlsp_XOR_c:
+    newNode = Ctlp_FormulaCreate(Ctlp_XOR_c,
+				 CtlspFormulaConvertToCTL(formula->left) ,
+				 CtlspFormulaConvertToCTL(formula->right) );
+    break;
+  case Ctlsp_EQ_c:
+    newNode = Ctlp_FormulaCreate(Ctlp_EQ_c,
+				 CtlspFormulaConvertToCTL(formula->left) ,
+				 CtlspFormulaConvertToCTL(formula->right) );
+    break;
+  case Ctlsp_TRUE_c:
+    newNode = Ctlp_FormulaCreate(Ctlp_TRUE_c,
+				 CtlspFormulaConvertToCTL(formula->left) ,
+				 CtlspFormulaConvertToCTL(formula->right) );
+    break;
+  case Ctlsp_FALSE_c:
+    newNode = Ctlp_FormulaCreate(Ctlp_FALSE_c,
+				 CtlspFormulaConvertToCTL(formula->left) ,
+				 CtlspFormulaConvertToCTL(formula->right) );
+    break;
+  default:
+    fail("Unexpected type");
+  }
+
+  return newNode;
+} /* CtlspFormulaConvertToCTL() */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs OR function]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlsp_Formula_t *
+CtlspFunctionOr(
+  Ctlsp_Formula_t *left,
+  Ctlsp_Formula_t *right)
+{
+  Ctlsp_Formula_t *result;
+
+  if((Ctlsp_FormulaReadType(left)  == Ctlsp_TRUE_c) ||
+     (Ctlsp_FormulaReadType(right) == Ctlsp_TRUE_c)){
+    result = Ctlsp_FormulaCreate(Ctlsp_TRUE_c, NIL(Ctlsp_Formula_t),
+				 NIL(Ctlsp_Formula_t));;
+  } else
+    if(Ctlsp_FormulaReadType(left) == Ctlsp_FALSE_c){
+      result = right;
+    } else
+      if(Ctlsp_FormulaReadType(right) == Ctlsp_FALSE_c){
+	result = left;
+      } else
+	result = Ctlsp_FormulaCreate(Ctlsp_OR_c, left, right);
+
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Performs And function]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlsp_Formula_t *
+CtlspFunctionAnd(
+  Ctlsp_Formula_t *left,
+  Ctlsp_Formula_t *right)
+{
+  Ctlsp_Formula_t *result;
+
+  if((Ctlsp_FormulaReadType(left)  == Ctlsp_FALSE_c) ||
+     (Ctlsp_FormulaReadType(right) == Ctlsp_FALSE_c)){
+    result = Ctlsp_FormulaCreate(Ctlsp_FALSE_c, NIL(Ctlsp_Formula_t),
+				 NIL(Ctlsp_Formula_t));;
+  } else
+    if(Ctlsp_FormulaReadType(left) == Ctlsp_TRUE_c){
+      result = right;
+    } else
+      if(Ctlsp_FormulaReadType(right) == Ctlsp_TRUE_c){
+	result = left;
+      } else
+	result = Ctlsp_FormulaCreate(Ctlsp_AND_c, left, right);
+
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Performs Then(Imply) function]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ctlsp_Formula_t *
+CtlspFunctionThen(
+  Ctlsp_Formula_t *left,
+  Ctlsp_Formula_t *right)
+{
+  Ctlsp_Formula_t *result;
+
+  if((Ctlsp_FormulaReadType(left)  == Ctlsp_TRUE_c) &&
+     (Ctlsp_FormulaReadType(right) == Ctlsp_FALSE_c)){
+    result = Ctlsp_FormulaCreate(Ctlsp_FALSE_c, NIL(Ctlsp_Formula_t),
+				 NIL(Ctlsp_Formula_t));
+  } else
+    if(Ctlsp_FormulaReadType(left) == Ctlsp_FALSE_c){
+      result = Ctlsp_FormulaCreate(Ctlsp_TRUE_c, NIL(Ctlsp_Formula_t),
+				   NIL(Ctlsp_Formula_t));
+    } else
+      if((Ctlsp_FormulaReadType(left)  == Ctlsp_TRUE_c) &&
+	 (Ctlsp_FormulaReadType(right) == Ctlsp_TRUE_c)){
+	result = Ctlsp_FormulaCreate(Ctlsp_TRUE_c, NIL(Ctlsp_Formula_t),
+				     NIL(Ctlsp_Formula_t));
+      } else
+	result = Ctlsp_FormulaCreate(Ctlsp_THEN_c, left, right);
+
+  return result;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a CTL* formula with just the type set.]
+
+  Description [Calls Ctlsp_FormulaCreate with type, and all other fields NULL.]
+
+  SideEffects []
+
+  SeeAlso     [Ctlsp_FormulaCreate]
+
+******************************************************************************/
+static Ctlsp_Formula_t *
+FormulaCreateWithType(
+  Ctlsp_FormulaType type)
+{
+  return (Ctlsp_FormulaCreate(type, NIL(Ctlsp_Formula_t), NIL(Ctlsp_Formula_t)));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [The comparison function for the formula unique table.]
+
+  Description [The function takes as parameters two CTL* formulae. It compares
+  the formula type, the left child and the right child, and returns 0 if they
+  match. Otherwise, it returns -1.]
+
+  SideEffects []
+
+  SeeAlso     [FormulaHash]
+
+******************************************************************************/
+static int
+FormulaCompare(
+  const char *key1,
+  const char *key2)
+{
+  Ctlsp_Formula_t *formula1 = (Ctlsp_Formula_t *) key1;
+  Ctlsp_Formula_t *formula2 = (Ctlsp_Formula_t *) key2;
+
+  assert(key1 != NIL(char));
+  assert(key2 != NIL(char));
+
+
+  if(formula1->type != formula2->type) {
+    return -1;
+  }
+  if(formula1->type == Ctlsp_ID_c) {
+    if(strcmp((char *) (formula1->left), (char *) (formula2->left)) ||
+       strcmp((char *) (formula1->right), (char *) (formula2->right))) {
+      return -1;
+    } else
+      return 0;
+  } else {
+    if(formula1->left != formula2->left)
+      return -1;
+    if(formula1->right != formula2->right)
+      return -1;
+    if (formula1->type == Ctlsp_Cmp_c &&
+	formula1->compareValue != formula2->compareValue) {
+      return -1;
+    }
+    return 0;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [The hash function for the formula unique table.]
+
+  Description [The function takes as parameter a CTL* formula. If the formula
+  type is Ctlsp_ID_c, st_strhash is used with a concatenation of left and
+  right children as the key string. Otherwise, something very similar to
+  st_ptrhash is done.]
+
+  SideEffects []
+
+  SeeAlso     [FormulaCompare]
+
+******************************************************************************/
+static int
+FormulaHash(
+  char *key,
+  int modulus)
+{
+  char *hashString;
+  int hashValue;
+  Ctlsp_Formula_t *formula = (Ctlsp_Formula_t *) key;
+
+  if(formula->type==Ctlsp_ID_c) {
+    hashString = util_strcat3((char *) (formula->left), (char *)
+			      (formula->right), "");
+    hashValue = st_strhash(hashString, modulus);
+    FREE(hashString);
+    return hashValue;
+  }
+  return (int) ((((unsigned long) formula->left >>2) +
+		 ((unsigned long) formula->right >>2)) % modulus);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Hashes the formula into the unique table.]
+
+  Description [The function takes a formula and hashes it and all its
+  subformulae into a unique table. It returns the unique formula identical to
+  the formula being hashed. The formula returned will have maximum sharing
+  with the formulae that are already present in uniqueTable. It returns
+  NIL(Ctlsp_Formula_t) if the formula is NIL(Ctlsp_Formula_t).]
+
+  SideEffects [If a copy of some subformula of formula is present in
+  uniqueTable then the copy is substituted for it and the reference count of
+  the subformula is decremented.]
+
+  SeeAlso     [FormulaCompare]
+
+******************************************************************************/
+static Ctlsp_Formula_t *
+FormulaHashIntoUniqueTable(
+  Ctlsp_Formula_t *formula,
+  st_table *uniqueTable)
+{
+  Ctlsp_Formula_t *uniqueFormula, *uniqueLeft, *uniqueRight;
+
+  if(formula == NIL(Ctlsp_Formula_t))
+    return NIL(Ctlsp_Formula_t);
+  if(st_lookup(uniqueTable, formula, &uniqueFormula)) {
+    return uniqueFormula;
+  }
+  else {
+    if(formula->type == Ctlsp_ID_c) {
+      st_insert(uniqueTable, (char *) formula, (char *) formula);
+      return formula;
+    }
+    else {
+      uniqueLeft = FormulaHashIntoUniqueTable(formula->left, uniqueTable);
+      if(uniqueLeft != NIL(Ctlsp_Formula_t))
+	if(uniqueLeft != formula->left) {
+	  CtlspFormulaDecrementRefCount(formula->left);
+	  formula->left = uniqueLeft;
+	  CtlspFormulaIncrementRefCount(formula->left);
+	}
+      uniqueRight = FormulaHashIntoUniqueTable(formula->right, uniqueTable);
+      if(uniqueRight != NIL(Ctlsp_Formula_t))
+	if(uniqueRight != formula->right) {
+	  CtlspFormulaDecrementRefCount(formula->right);
+	  formula->right = uniqueRight;
+	  CtlspFormulaIncrementRefCount(formula->right);
+	}
+      if(st_lookup(uniqueTable, formula, &uniqueFormula)) {
+	return uniqueFormula;
+      }
+      else {
+	st_insert(uniqueTable, (char *) formula, (char *) formula);
+	return formula;
+      }
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis [Create SNF propositional variable if the passed formula is
+  not propositional]
+
+  Description [If formula is not propositional, generate SNF for the
+  formula first and returned the renamed variable]
+
+  SideEffects [Add the new generated SNF rule to formulaArray]
+
+  SeeAlso     [Ctlsp_LtlTranslateIntoSNFRecursive]
+
+******************************************************************************/
+static Ctlsp_Formula_t *
+createSNFnode(
+  Ctlsp_Formula_t *formula,
+  array_t         *formulaArray,
+  int             *index)
+{
+  Ctlsp_Formula_t *newNode;
+
+  if(!Ctlsp_LtlFormulaIsPropositional(formula)){
+    newNode  = Ctlsp_FormulaCreate(Ctlsp_ID_c, util_strcat3(" SNFx","_", util_inttostr((*index)++)),
+				   (void *)util_strsav("1"));
+    Ctlsp_LtlTranslateIntoSNFRecursive(newNode, formula, formulaArray, index);
+    return newNode;
+  } else {
+    return Ctlsp_FormulaDup(formula);
+  }
+
+}
Index: vis_dev/vis-2.3/src/eqv/eqv.h
===================================================================
--- vis_dev/vis-2.3/src/eqv/eqv.h	(revision 14)
+++ vis_dev/vis-2.3/src/eqv/eqv.h	(revision 14)
@@ -0,0 +1,153 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [eqv.h]
+
+  PackageName [eqv]
+
+  Synopsis    [Provides commands for doing combinational and sequential
+  verification on two networks.]
+
+  Description [The eqv package provides two commands - comb_verify and
+  seq_verify for doing combinational and sequential verification respectively.
+  Two networks along with options for partitioning and ordering form the input
+  to the commands.<p>
+
+  Combinational verification : Two sets of distinguished nodes, roots and
+  leaves, are specified for each network. The leaves should form a complete
+  support for the roots in both networks. The correspondence between the roots
+  and leaves of the two networks can be specified in an input file. The format
+  of the input file is as follows-<p>
+
+  .roots<p>
+  &lt;name1&gt; &lt;name2&gt;<p>
+  .<p>
+  .<p>
+  .leaves<p>
+  &lt;name1&gt; &lt;name2&gt;
+  .<p>
+  .<p>
+  Here, name1 is a node name in the first network and name2 a node name in the
+  second network.<p>
+
+  If no input file is given, the combinational outputs are assumed to be roots
+  and the combinational inputs are assumed to be leaves. comb_verify checks
+  for each pair of corresponding roots whether the two are equivalent as
+  logical functions of corresponding leaf variables. This is done by
+  constructing BDD's for the roots in terms of the leaf variables. For each
+  pair in which the two roots are not equivalent, a minterm where they are not
+  equal is written out. Note that pseudo inputs are treated no differently
+  from any other inputs.<p> 
+
+  Sequential verification : Two inputs and an option for partitioning form the
+  input for this command. A set of distinguished nodes called roots is
+  specified for each network. The correspondence between the two sets can be
+  specified in an input file as described above. If no input file is given,
+  the primary outputs are assumed to be roots. seq_verify checks for each
+  pair of corresponding roots whether the two roots have different values in a
+  reachable state of the product machine of the networks for any input. For
+  each pair that this happens, an error trace is written out.<p>
+
+  The method used in sequential verification i.e. product machine cannot handle
+  non-determinism. Therefore, the two networks shouldn't have any pseudo
+  inputs.]
+
+  SeeAlso     [ntk.h]
+
+  Author      [Shaz Qadeer]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: eqv.h,v 1.6 2002/09/08 23:28:36 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _EQV
+#define _EQV
+
+#include "fsm.h"
+#include "ord.h"
+#include "io.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef void (*OFT) (Ntk_Network_t *, Ntk_Network_t *, st_table *);
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void Eqv_Init(void);
+EXTERN void Eqv_End(void);
+EXTERN boolean Eqv_NetworkVerifyCombinationalEquivalence(Ntk_Network_t *network1, Ntk_Network_t *network2, st_table *leavesMap, st_table *rootsMap, OFT AssignCommonOrder, Part_PartitionMethod method1, Part_PartitionMethod method2);
+EXTERN boolean Eqv_NetworkVerifySequentialEquivalence(Ntk_Network_t *network1, Ntk_Network_t *network2, st_table *rootsTable, st_table *leavesTable, Part_PartitionMethod partMethod, boolean useBackwardReach, boolean reordering);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _EQV */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/eqv/eqv.make
===================================================================
--- vis_dev/vis-2.3/src/eqv/eqv.make	(revision 14)
+++ vis_dev/vis-2.3/src/eqv/eqv.make	(revision 14)
@@ -0,0 +1,4 @@
+CSRC += eqvCmd.c eqvMisc.c eqvVerify.c
+HEADERS += eqv.h eqvInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/eqv/eqvCmd.c
===================================================================
--- vis_dev/vis-2.3/src/eqv/eqvCmd.c	(revision 14)
+++ vis_dev/vis-2.3/src/eqv/eqvCmd.c	(revision 14)
@@ -0,0 +1,1318 @@
+/**CFile***********************************************************************
+
+  FileName    [eqvCmd.c]
+
+  PackageName [eqv]
+
+  Synopsis    [Implements the eqv commands.]
+
+  Description [This file initializes the eqv package and provides the
+  interface between the command line and the top level routine which does the
+  equivalence checking.]
+
+  Author      [Shaz Qadeer]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "eqvInt.h"
+
+static char rcsid[] UNUSED = "$Id: eqvCmd.c,v 1.20 2009/04/11 18:26:04 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+static jmp_buf timeOutEnv;
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandCombEquivalence(Hrc_Manager_t **hmgr, int argc, char **argv);
+static int CommandSeqEquivalence(Hrc_Manager_t **hmgr, int argc, char **argv);
+static void TimeOutHandle(void);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [This function initializes the eqv package.]
+
+  SideEffects []
+
+  SeeAlso     [Eqv_End()]
+
+******************************************************************************/
+void
+Eqv_Init(void)
+{
+  Cmd_CommandAdd("comb_verify", CommandCombEquivalence, 0);
+  Cmd_CommandAdd("seq_verify", CommandSeqEquivalence, 0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [This function ends the eqv package.]
+
+  SideEffects []
+
+  SeeAlso     [Eqv_Init()]
+
+******************************************************************************/
+void
+Eqv_End(void)
+{
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [This function sits between the command line and the top level
+  function which checks combinational equivalence.]
+
+  Description [The function parses the command line and generates the
+  arguments to the top level routine.]
+
+  SideEffects [If the variables of the network present at the current node of
+  the existing hierarchy have not been ordered, they get ordered.]
+
+  SeeAlso [Eqv_NetworkVerifyCombinationalEquivalence]
+
+  CommandName [comb_verify]
+
+  CommandSynopsis [verify the combinational equivalence of two flattened networks]
+
+  CommandArguments [ \[-b\] \[-f &lt;filename&gt;\] \[-h\] \[-o &lt;ordering
+  method&gt;\] \[-t &lt;timeOut&gt;\] \[-1 &lt;partition method&gt;\] \[-2
+  &lt;partition method&gt;\] \[-i\] &lt;filename1&gt; \[&lt;filename2&gt;\] ]
+
+  CommandDescription [This command verifies the combinational equivalence of
+  two flattened networks.  In particular, any set of functions (the roots),
+  defined over any set of intermediate variables (the leaves), can be checked
+  for equivalence between the two networks.  Roots and leaves are subsets of
+  the nodes of a network, with the restriction that the leaves should form a
+  complete support for the roots. The correspondence between the roots and the
+  leaves in the two networks is specified in a file given by the option -f
+  <filename>. The default option
+  assumes that the roots are the combinational outputs and the leaves are the
+  combinational inputs.<p>
+
+  When there is a pseudo input in the set of leaves, the range of values it
+  can take should be the same as that of the multi-valued variable
+  corresponding to it, for comb_verify to function correctly.
+  This restriction will be removed in future.<p>
+
+  There are two ways to do combinational verification.  In the first mode, two
+  BLIF-MV files are given as arguments to the command, e.g.<p>
+
+  <pre>
+  vis> comb_verify foo.mv bar.mv
+  </pre>
+
+  Verification is done for the flattened networks at the root nodes of the two
+  BLIF-MV hierarchies.  In any error messages printed, "network1" refers to
+  the first file, and "network2" refers to the second. Both of these networks
+  are freed at the end of the command. This mode is totally independent from
+  any existing hierarchy previously read in.
+
+  In the second mode, it is assumed that a hierarchy has already been read
+  in. Then, comb_verify can be called with a single BLIF-MV file, and this
+  will do the comparison between the network present at the current node
+  ("network1") and the network corresponding to the root node of the hierarchy
+  in the BLIF-MV file("network2"). A typical sequence of commands is:<p>
+
+  <pre>
+  vis> read_blifmv foo.mv
+  vis> init_verify
+  vis> comb_verify bar.mv
+  </pre>
+
+  If a hierarchy has been read in but a flattened network does not exist at
+  the current node (flatten_hierarchy has not been invoked), the command does
+  nothing. If a network exists at the
+  current node, but the variables haven't been ordered, then the variables are
+  ordered and a partition created. This partition is freed at the end. A
+  side-effect is that the variables are ordered. If a partition exists, then
+  it is used if the vertices corresponding to the roots specified are present
+  in it, otherwise a new partition is created with the current ordering. The
+  partition created for the new network read in is always freed at the end.<p>
+
+  Command options:<p>
+
+  <dl>
+
+  <dt> -b
+  <dd> Specifies that the files are BLIF files and not BLIF-MV files.
+  <p>
+
+  <dt> -f &lt;filename&gt;
+  <dd> Provides the correspondence between the leaves and roots of
+  network1 and network2. If this option is not used, it is assumed
+  that the correspondence is by name, except that two latch inputs
+  match if either they have the same name or the corresponding latch
+  outputs have the same name.  Leaves are the combinational inputs,
+  and roots are the combinational outputs.  <p>
+
+  <dt> -h
+  <dd> Print the command usage.
+  <p>
+
+  <dt> -t &lt;timeOut&gt;
+  <dd> Time in seconds allowed to perform equivalence checking.  The default
+  is infinity.<p>
+
+  <dt> -o &lt;ordering method&gt;
+  <dd> Specifies the ordering method to be used for assigning a common
+  ordering to the leaves of network1 and network2. If this option is not used,
+  ordering is done using a default method.  Currently, only the default method
+  is available. <p>
+
+  <dt> -1 &lt;partition method&gt;
+
+  <dd> Specifies the partitioning method to be used for network1. Supported
+  methods are "total", "partial", and "inout" (see the command
+  <code>build_partition_mdds</code> for more information). If this option is
+  not specified, then the default method "inout" is used.  <p>
+
+  <dt> -2 &lt;partition method&gt;
+  <dd> Specifies the partitioning method to be used for network2. Supported
+  methods are "total", "partial", and "inout" (see the command
+  <code>build_partition_mdds</code> for more information). If this option is
+  not specified, then default method "inout" is used.  <p>
+
+  <dt> -i
+  <dd> Print Bdd statistics.
+
+  </dl>
+  ]
+
+******************************************************************************/
+
+static int
+CommandCombEquivalence(
+  Hrc_Manager_t **hmgr,
+  int argc,
+  char **argv)
+{
+  static int                   timeOutPeriod;
+  static Hrc_Manager_t        *hmgr1;
+  static Hrc_Manager_t        *hmgr2;
+  static Ntk_Network_t        *network1;
+  static Ntk_Network_t        *network2;
+  int                          c;
+  int                          check;
+  FILE                        *fp;
+  FILE                        *inputFile = NIL(FILE);
+  char                        *fileName1;
+  char                        *fileName2;
+  char                        *name1;
+  char                        *name2;
+  st_generator                *gen;
+  static Part_PartitionMethod  partMethod1;
+  static Part_PartitionMethod  partMethod2;
+  static OFT                   AssignCommonOrder;
+  static st_table             *inputMap;
+  static st_table             *outputMap;
+  st_table                    *rootsTable = NIL(st_table);
+  st_table                    *leavesTable = NIL(st_table);
+  boolean                      fileFlag = FALSE;
+  boolean                      equivalent;
+  boolean                      printBddInfo = FALSE;
+  static boolean               execMode; /* FALSE: verify against current network,
+					    TRUE:  verify the two given networks */
+  boolean isBlif = FALSE;
+
+  /*
+   * These are the default values.  These variables must be declared static
+   * to avoid lint warnings.  Since they are static, we must reinitialize
+   * them outside of the variable declarations.
+   */
+  timeOutPeriod     = 0;
+  hmgr1             = NIL(Hrc_Manager_t);
+  hmgr2             = NIL(Hrc_Manager_t);
+  partMethod1       = Part_Default_c;
+  partMethod2       = Part_Default_c;
+  AssignCommonOrder = DefaultCommonOrder;
+  inputMap          = NIL(st_table);
+  outputMap         = NIL(st_table);
+
+  error_init();
+  util_getopt_reset();
+  while((c = util_getopt(argc, argv, "bf:o:1:2:ht:i")) != EOF) {
+    switch(c) {
+      case 'b':
+	isBlif = TRUE;
+	break;
+      case 'f':
+	if((inputFile = Cmd_FileOpen(util_optarg, "r", NIL(char *), 1)) ==
+	   NIL(FILE)) {
+	  (void) fprintf(vis_stderr, "** eqv error: File %s not found.\n", util_optarg);
+	  goto usage;
+	}
+	fileFlag = 1;
+	break;
+      case 'o':
+	/* The following line causes a seg fault, because
+	   FindOrderingMethod() always returns NULL, and currently
+	   only DefaultCommonOrder is used.
+	AssignCommonOrder = FindOrderingMethod();
+	*/
+	/* The programmer supplies and modifies this function if any new
+	   ordering method is introduced. FindOrderingMethod() should return
+	   the type OFT. */
+	break;
+      case 't':
+	timeOutPeriod = atoi(util_optarg);
+	break;
+      case '1':
+	if(!strcmp(util_optarg, "total")) {
+	  partMethod1 =  Part_Total_c;
+	}
+	else
+	  if(!strcmp(util_optarg, "partial")) {
+	  partMethod1 =  Part_Partial_c;
+	  }
+	else
+	  if(!strcmp(util_optarg, "inout")) {
+	    partMethod1 = Part_InOut_c;
+	  }
+	  else {
+	    (void) fprintf(vis_stderr, "** eqv error: Unknown partition method 1\n");
+	    goto usage;
+	  }
+	break;
+      case '2':
+	if(!strcmp(util_optarg, "total")) {
+	  partMethod2 =  Part_Total_c;
+	}
+	else
+	  if(!strcmp(util_optarg, "partial")) {
+	  partMethod2 =  Part_Partial_c;
+	  }
+	else
+	  if(!strcmp(util_optarg, "inout")) {
+	    partMethod2 = Part_InOut_c;
+	  }
+	  else {
+	    (void) fprintf(vis_stderr, "** eqv error: Unknown partition method 2\n");
+	    goto usage;
+	  }
+	break;
+      case 'i':
+	printBddInfo = TRUE;
+	break;
+      case 'h':
+	goto usage;
+      default :
+	goto usage;
+    }
+  }
+  if(argc == 1) {
+    goto usage;
+  }
+
+  if(argc == util_optind+1) {
+    execMode = FALSE;
+  }
+  else
+    if(argc == util_optind+2) {
+      execMode = TRUE;
+    }
+    else {
+      error_append("** eqv error: Improper number of arguments.\n");
+      (void) fprintf(vis_stderr, "%s", error_string());
+      goto usage;
+    }
+  if(execMode == FALSE) {
+    hmgr1 = *hmgr;
+    if(Hrc_ManagerReadCurrentNode(hmgr1) == NIL(Hrc_Node_t)) {
+      (void) fprintf(vis_stderr, "** eqv error: The hierarchy manager is empty.  Read in design.\n");
+      return 1;
+    }
+    network1 = (Ntk_Network_t *) Hrc_NodeReadApplInfo(
+		    Hrc_ManagerReadCurrentNode(hmgr1), NTK_HRC_NODE_APPL_KEY);
+    if(network1 == NIL(Ntk_Network_t)) {
+      (void) fprintf(vis_stderr, "** eqv error: There is no network. Use flatten_hierarchy.\n");
+      return 1;
+    }
+    if(Ntk_NetworkReadApplInfo(network1, PART_NETWORK_APPL_KEY) == NIL(void)) {
+      (void) fprintf(vis_stderr, "** eqv error: Network has not been partitioned. Use build_partition_mdds.\n");
+      return 1;
+    }
+    fileName2 = argv[util_optind];
+    if(isBlif) {
+      if((hmgr2 = Io_BlifRead(fileName2, FALSE)) == NIL(Hrc_Manager_t)) {
+	(void) fprintf(vis_stderr, "** eqv error: Error in reading file %s\n", fileName2);
+	goto usage;
+      }
+    }
+    else {
+      if((fp = Cmd_FileOpen(fileName2, "r", NIL(char *), 1)) == NIL(FILE)) {
+	(void) fprintf(vis_stderr, "** eqv error: File %s not found\n", fileName2);
+	return 1;
+      }
+      hmgr2 = Io_BlifMvRead(fp, NIL(Hrc_Manager_t), FALSE, FALSE, FALSE);
+      fclose(fp);
+      if(hmgr2 == NIL(Hrc_Manager_t)) {
+	(void) fprintf(vis_stderr, "** eqv error: Error in reading file %s\n", fileName2);
+	return 1;
+      }
+    }
+    network2 = Ntk_HrcNodeConvertToNetwork(Hrc_ManagerReadCurrentNode(hmgr2),
+					   TRUE, (lsList) NULL);
+    if(network2 == NIL(Ntk_Network_t)) {
+      Hrc_ManagerFree(hmgr2);
+      (void) fprintf(vis_stderr, "** eqv error: Error in network2.\n");
+      return 1;
+    }
+
+  }
+  else {
+    fileName1 = argv[util_optind];
+    fileName2 = argv[util_optind+1];
+    if(isBlif) {
+      if((hmgr1 = Io_BlifRead(fileName1, FALSE)) == NIL(Hrc_Manager_t)) {
+	(void) fprintf(vis_stderr, "** eqv error: Error in reading file %s\n", fileName1);
+	return 1;
+      }
+      if((hmgr2 = Io_BlifRead(fileName2, FALSE)) == NIL(Hrc_Manager_t)) {
+	(void) fprintf(vis_stderr, "** eqv error: Error in reading file %s\n", fileName2);
+	if(hmgr1) {
+	  Hrc_ManagerFree(hmgr1);
+	}
+	return 1;
+      }
+    }
+    else {
+      if((fp = Cmd_FileOpen(fileName1, "r", NIL(char *), 1)) == NIL(FILE)) {
+	(void) fprintf(vis_stderr, "** eqv error: File %s not found\n", fileName1);
+	return 1;
+      }
+      hmgr1 = Io_BlifMvRead(fp, NIL(Hrc_Manager_t), FALSE, FALSE, FALSE);
+      fclose(fp);
+      if(hmgr1 == NIL(Hrc_Manager_t)) {
+	(void) fprintf(vis_stderr, "** eqv error: Error in reading file %s\n", fileName1);
+	goto usage;
+      }
+      if((fp = Cmd_FileOpen(fileName2, "r", NIL(char *), 1)) == NIL(FILE)) {
+	(void) fprintf(vis_stderr, "** eqv error: File %s not found\n", fileName2);
+	if(hmgr1) {
+	  Hrc_ManagerFree(hmgr1);
+	}
+	return 1;
+      }
+      hmgr2 = Io_BlifMvRead(fp, NIL(Hrc_Manager_t), FALSE, FALSE, FALSE);
+      fclose(fp);
+      if(hmgr2 == NIL(Hrc_Manager_t)) {
+	(void) fprintf(vis_stderr, "** eqv error: Error in reading file %s\n", fileName2);
+	if(hmgr1) {
+	  Hrc_ManagerFree(hmgr1);
+	}
+	return 1;
+      }
+    }
+    network1 = Ntk_HrcNodeConvertToNetwork(Hrc_ManagerReadCurrentNode(hmgr1),
+					   TRUE, (lsList) NULL);
+    network2 = Ntk_HrcNodeConvertToNetwork(Hrc_ManagerReadCurrentNode(hmgr2),
+					   TRUE, (lsList) NULL);
+
+    if((network1 == NIL(Ntk_Network_t)) || (network2 == NIL(Ntk_Network_t))) {
+      if(network1 == NIL(Ntk_Network_t)) {
+	(void) fprintf(vis_stderr, "** eqv error: Error in network1.\n");
+      }
+      if(network2 == NIL(Ntk_Network_t)) {
+	(void) fprintf(vis_stderr, "** eqv error: Error in network2.\n");
+      }
+      Hrc_ManagerFree(hmgr1);
+      Hrc_ManagerFree(hmgr2);
+      return 1;
+    }
+    if((network1 == NIL(Ntk_Network_t)) || (network2 == NIL(Ntk_Network_t))) {
+      if(network1 == NIL(Ntk_Network_t)) {
+	(void) fprintf(vis_stderr, "** eqv error: Error in network1.\n");
+      }
+      if(network2 == NIL(Ntk_Network_t)) {
+	(void) fprintf(vis_stderr, "** eqv error: Error in network2.\n");
+      }
+      Hrc_ManagerFree(hmgr1);
+      Hrc_ManagerFree(hmgr2);
+      return 1;
+    }
+  }
+
+  if(Ntk_NetworkReadNumCombInputs(network1) !=
+     Ntk_NetworkReadNumCombInputs(network2)) {
+    error_append("** eqv error: Different number of inputs in the two networks.\n");
+    if(!fileFlag) {
+      if(execMode) {
+	Hrc_ManagerFree(hmgr1);
+	Ntk_NetworkFree(network1);
+      }
+      Hrc_ManagerFree(hmgr2);
+      Ntk_NetworkFree(network2);
+      (void) fprintf(vis_stderr, "%s", error_string());
+      return 1;
+    }
+  }
+
+  if(fileFlag) {
+    rootsTable = st_init_table(strcmp, st_strhash);
+    leavesTable = st_init_table(strcmp, st_strhash);
+    check = ReadRootLeafMap(inputFile, rootsTable, leavesTable);
+    fclose(inputFile);
+    switch (check) {
+      case 0 : /* error */
+	st_free_table(rootsTable);
+	st_free_table(leavesTable);
+	(void) fprintf(vis_stderr, "** eqv error: No data in the input file.\n");
+	if(execMode) {
+	  Hrc_ManagerFree(hmgr1);
+	  Ntk_NetworkFree(network1);
+	}
+	Hrc_ManagerFree(hmgr2);
+	Ntk_NetworkFree(network2);
+	return 1;
+    case 1 : /* leaves only */
+	st_free_table(rootsTable);
+	inputMap = MapNamesToNodes(network1, network2, leavesTable);
+	st_foreach_item(leavesTable, gen, &name1, &name2) {
+	  FREE(name1);
+	  FREE(name2);
+	}
+	st_free_table(leavesTable);
+	if(inputMap == NIL(st_table)) {
+	  (void) fprintf(vis_stderr, "%s", error_string());
+	  if(execMode) {
+	    Hrc_ManagerFree(hmgr1);
+	    Ntk_NetworkFree(network1);
+	  }
+	  Hrc_ManagerFree(hmgr2);
+	  Ntk_NetworkFree(network2);
+	  return 1;
+	}
+	if((outputMap = MapCombOutputsByName(network1, network2)) ==
+	   NIL(st_table)) {
+	  st_free_table(inputMap);
+	  if(execMode) {
+	    Hrc_ManagerFree(hmgr1);
+	    Ntk_NetworkFree(network1);
+	  }
+	  Hrc_ManagerFree(hmgr2);
+	  Ntk_NetworkFree(network2);
+	  (void) fprintf(vis_stderr, "%s", error_string());
+	  return 1;
+	}
+	if(!TestRootsAndLeavesAreValid(network1, network2, inputMap,
+				       outputMap)){
+	  st_free_table(inputMap);
+	  st_free_table(outputMap);
+	  if(execMode) {
+	    Hrc_ManagerFree(hmgr1);
+	    Ntk_NetworkFree(network1);
+	  }
+	  Hrc_ManagerFree(hmgr2);
+	  Ntk_NetworkFree(network2);
+	  (void) fprintf(vis_stderr, "%s", error_string());
+	  return 1;
+	}
+	break;
+    case 2 : /* roots only */
+	st_free_table(leavesTable);
+	outputMap = MapNamesToNodes(network1, network2, rootsTable);
+	st_foreach_item(rootsTable, gen, &name1, &name2) {
+	  FREE(name1);
+	  FREE(name2);
+	}
+	st_free_table(rootsTable);
+	if(outputMap ==NIL(st_table)) {
+	  (void) fprintf(vis_stderr, "%s", error_string());
+	  if(execMode) {
+	    Hrc_ManagerFree(hmgr1);
+	    Ntk_NetworkFree(network1);
+	  }
+	  Hrc_ManagerFree(hmgr2);
+	  Ntk_NetworkFree(network2);
+	  return 1;
+	}
+	if((inputMap = MapCombInputsByName(network1, network2)) ==
+	   NIL(st_table)) {
+	  st_free_table(outputMap);
+	  if(execMode) {
+	    Hrc_ManagerFree(hmgr1);
+	    Ntk_NetworkFree(network1);
+	  }
+	  Hrc_ManagerFree(hmgr2);
+	  Ntk_NetworkFree(network2);
+	  (void) fprintf(vis_stderr, "%s", error_string());
+	  return 1;
+	}
+	if(!TestRootsAndLeavesAreValid(network1, network2, inputMap,
+				       outputMap)){
+	  st_free_table(inputMap);
+	  st_free_table(outputMap);
+	  if(execMode) {
+	    Hrc_ManagerFree(hmgr1);
+	    Ntk_NetworkFree(network1);
+	  }
+	  Hrc_ManagerFree(hmgr2);
+	  Ntk_NetworkFree(network2);
+	  return 1;
+	}
+	break;
+    case 3 : /* both leaves and roots */
+	inputMap = MapNamesToNodes(network1, network2, leavesTable);
+	st_foreach_item(leavesTable, gen, &name1, &name2) {
+	  FREE(name1);
+	  FREE(name2);
+	}
+	st_free_table(leavesTable);
+	outputMap = MapNamesToNodes(network1, network2, rootsTable);
+	st_foreach_item(rootsTable, gen, &name1, &name2) {
+	  FREE(name1);
+	  FREE(name2);
+	}
+	st_free_table(rootsTable);
+	if((inputMap == NIL(st_table)) || (outputMap == NIL(st_table))) {
+	  (void) fprintf(vis_stderr, "%s", error_string());
+	  if(inputMap) {
+	    st_free_table(inputMap);
+	  }
+	  if(outputMap) {
+	    st_free_table(outputMap);
+	  }
+	  if(execMode) {
+	    Hrc_ManagerFree(hmgr1);
+	    Ntk_NetworkFree(network1);
+	  }
+	  Hrc_ManagerFree(hmgr2);
+	  Ntk_NetworkFree(network2);
+	  return 1;
+	}
+	if(!TestRootsAndLeavesAreValid(network1, network2, inputMap,
+				       outputMap)){
+	  st_free_table(inputMap);
+	  st_free_table(outputMap);
+	  if(execMode) {
+	    Hrc_ManagerFree(hmgr1);
+	    Ntk_NetworkFree(network1);
+	  }
+	  Hrc_ManagerFree(hmgr2);
+	  Ntk_NetworkFree(network2);
+	  (void) fprintf(vis_stderr, "%s", error_string());
+	  return 1;
+	}
+	break;
+    }
+  }
+  else {
+    inputMap = MapCombInputsByName(network1, network2);
+    outputMap = MapCombOutputsByName(network1, network2);
+    if((inputMap == NIL(st_table)) || (outputMap == NIL(st_table))) {
+      if(inputMap) {
+	st_free_table(inputMap);
+      }
+      if(outputMap) {
+	st_free_table(outputMap);
+      }
+      if(execMode) {
+	Hrc_ManagerFree(hmgr1);
+	Ntk_NetworkFree(network1);
+      }
+      Hrc_ManagerFree(hmgr2);
+      Ntk_NetworkFree(network2);
+      (void) fprintf(vis_stderr, "%s", error_string());
+      return 1;
+    }
+  }
+
+  /* Start the timer before calling the equivalence checker. */
+  if (timeOutPeriod > 0){
+    (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
+    (void) alarm(timeOutPeriod);
+    if (setjmp(timeOutEnv) > 0) {
+      (void) fprintf(vis_stderr, "Timeout occurred after %d seconds.\n", timeOutPeriod);
+      alarm(0);
+      return 1;
+    }
+  }
+
+  equivalent = Eqv_NetworkVerifyCombinationalEquivalence(network1, network2,
+							 inputMap, outputMap,
+							 AssignCommonOrder,
+							 partMethod1,
+							 partMethod2);
+
+  if(equivalent) {
+    (void) fprintf(vis_stdout, "Networks are combinationally equivalent.\n\n");
+  }
+  else {
+    (void) fprintf(vis_stdout, "%s", error_string());
+    (void) fprintf(vis_stdout, "Networks are NOT combinationally equivalent.\n\n");
+  }
+
+  if (printBddInfo) {
+    bdd_print_stats(Ntk_NetworkReadMddManager(network1), vis_stdout);
+  }
+
+  st_free_table(inputMap);
+  st_free_table(outputMap);
+  if(execMode) {
+    Hrc_ManagerFree(hmgr1);
+    Ntk_NetworkFree(network1);
+  }
+  Hrc_ManagerFree(hmgr2);
+  Ntk_NetworkFree(network2);
+
+  alarm(0);
+  return 0; /* normal exit */
+
+  usage:
+  (void) fprintf(vis_stderr, "usage: comb_verify [-b] [-f filename] [-h] [-o ordering method] [-t time]\n");
+  (void) fprintf(vis_stderr, "                   [-1 partMethod1] [-2 partMethod2] [-i] file1 [file2]\n");
+  (void) fprintf(vis_stderr, "   -b        input files are BLIF\n");
+  (void) fprintf(vis_stderr, "   -f file   variable name correspondence file\n");
+  (void) fprintf(vis_stderr, "   -h        print the command usage\n");
+  (void) fprintf(vis_stderr, "   -o method variable ordering method\n");
+  (void) fprintf(vis_stderr, "   -t time   time out period (in seconds)\n");
+  (void) fprintf(vis_stderr, "   -1 method partitioning method for network1\n");
+  (void) fprintf(vis_stderr, "   -2 method partitioning method for network2\n");
+  (void) fprintf(vis_stderr, "   -i        print Bdd statistics\n");
+  return 1;             /* error exit */
+}
+
+/**Function********************************************************************
+
+  Synopsis [This function sits between the command line and the main routine
+  of sequential verification.]
+
+  Description [The function parses the command line.]
+
+  SideEffects []
+
+  SeeAlso [Eqv_NetworkVerifySequentialEquivalence]
+
+  CommandName [seq_verify]
+
+  CommandSynopsis [verify the sequential equivalence of two flattened networks]
+
+  CommandArguments [\[-b\] \[-f &lt;filename&gt;\] \[-h\] \[-p &lt;partition
+  method&gt;\] \[-t &lt;timeOut&gt;\] \[-B\] \[-i\] \[-r\] &lt;filename&gt; \[&lt;filename&gt;\]]
+
+  CommandDescription [Please read the documentation for the command
+  <code>comb_verify</code> before reading on. The concepts of roots and leaves
+  in this command are the same as for <code>comb_verify</code>, except for an
+  added constraint: the set of leaves has to be the set of all primary inputs.
+  This obviously produces the constraint that both networks have the
+  same number of primary inputs. Moreover, no pseudo inputs should be present
+  in the two networks being compared. The set of roots can be an arbitrary
+  subset of nodes.<p>
+
+  The command verifies whether any state, where the values of two
+  corresponding roots differ, can be reached from the set of
+  initial states of the product machine. If this happens, a debug trace is
+  provided.<p>
+
+  The sequential verification is done by building the product finite state
+  machine.<p>
+
+  The command has two execution modes, just as for <code>comb_verify</code>.
+  In the first mode, two BLIF-MV files are given as arguments to the
+  command:<p>
+
+  <pre>
+  vis> seq_verify foo.mv bar.mv
+  </pre>
+
+  In the second mode, a single BLIF-MV file is taken. This is network2. It is
+  assumed that network1 is from a hierarchy that has already been read in. If
+  a network is present at the current node (i.e. flatten_hierarchy has been
+  executed), it is used for verification; otherwise the command does
+  nothing.<p>
+
+  <pre>
+  vis> read_blifmv foo.mv
+  vis> flatten_hierarchy
+  vis> seq_verify bar.mv
+  </pre>
+
+  Command options:<p>
+
+  <dl>
+
+  <dt> -b
+  <dd> Specifies that the input files are BLIF files.
+  <p>
+
+  <dt> -f &lt;filename&gt;
+  <dd> Provides the correspondence between the leaves and roots of network1
+  and network2. leaves has to be the set of primary inputs of the
+  networks. roots can be any subset of nodes. If this option is not used, it
+  is assumed that the correspondence is by name, and that the roots are the
+  combinational outputs.  <p>
+
+  <dt> -h
+  <dd> Print the command usage.
+  <p>
+
+  <dt> -p &lt;partition method&gt;
+  <dd> Specifies the partitioning method for the product machine. Supported
+  methods are "total", "partial", and "inout" (see the command
+  <code>build_partition_mdds</code> for more information). If this option is
+  not specified, then the default method "inout" is used.
+  <p>
+
+  <dt> -t &lt;timeOut&gt;
+  <dd> Time in seconds allowed to perform equivalence checking.  The default
+  is infinity.<p>
+
+  <dt> -B
+  <dd> Use backward image computation to traverse the state space of
+  the product machine.  By default, forward image computaion is used.
+
+  <dt> -i
+  <dd> Print BDD statistics. This is the only way to see BDD stastics during
+  this command. print_bdd_stats after this command doesn't show information
+  related to this command.
+
+  <dt> -r
+  <dd> Enable BDD reordering during the equivalence check.  Note that
+  dynamic_var_ordering has no effect on whether reordering is enabled during
+  the execution of seq_verify.
+  </dl>
+
+  ]
+
+******************************************************************************/
+static int
+CommandSeqEquivalence(
+  Hrc_Manager_t **hmgr,
+  int argc,
+  char **argv)
+{
+  static int            timeOutPeriod;
+  static Hrc_Manager_t *hmgr1;
+  static Hrc_Manager_t *hmgr2;
+  static Ntk_Network_t *network1;
+  static Ntk_Network_t *network2;
+  int                   c;
+  int                   check;
+  FILE                 *fp;
+  static FILE          *inputFile;
+  char                 *fileName1;
+  char                 *fileName2;
+  char                 *name1;
+  char                 *name2;
+  st_generator         *gen;
+  static Part_PartitionMethod partMethod;
+  st_table             *outputMap = NIL(st_table);
+  st_table             *inputMap = NIL(st_table);
+  st_table             *rootsTable = NIL(st_table);
+  st_table             *leavesTable = NIL(st_table);
+  static boolean        fileFlag;
+  static boolean        execMode; /* FALSE: verify against the current network,
+				     TRUE:  verify the two networks */
+  static boolean        equivalent;
+  boolean               isBlif = FALSE;
+  boolean               printBddInfo = FALSE;
+  static boolean        useBackwardReach;
+  boolean               reordering = FALSE;
+
+  /*
+   * These are the default values.  These variables must be declared static
+   * to avoid lint warnings.  Since they are static, we must reinitialize
+   * them outside of the variable declarations.
+   */
+  timeOutPeriod    = 0;
+  hmgr1            = NIL(Hrc_Manager_t);
+  hmgr2            = NIL(Hrc_Manager_t);
+  inputFile        = NIL(FILE);
+  partMethod       = Part_Default_c;
+  fileFlag         = FALSE;
+  equivalent       = FALSE;
+  useBackwardReach = FALSE;
+
+  error_init();
+  util_getopt_reset();
+  while((c = util_getopt(argc, argv, "bBf:p:hFt:ir")) != EOF) {
+    switch(c) {
+    case 'b':
+      isBlif = TRUE;
+      break;
+    case 'f':
+      if((inputFile = Cmd_FileOpen(util_optarg, "r", NIL(char *), 1)) ==
+	 NIL(FILE)) {
+	(void) fprintf(vis_stderr,
+		       "** eqv error: File %s not found.\n", util_optarg);
+	return 1;
+      }
+      fileFlag = 1;
+      break;
+    case 'p':
+      if(!strcmp(util_optarg, "total")) {
+	partMethod =  Part_Total_c;
+      } else {
+	if(!strcmp(util_optarg, "partial")) {
+	  partMethod =  Part_Partial_c;
+	} else {
+	  if(!strcmp(util_optarg, "inout")) {
+	    partMethod = Part_InOut_c;
+	  } else {
+	    (void) fprintf(vis_stderr,
+			   "** eqv error: Unknown partition method\n");
+	    goto usage;
+	  }
+	}
+      }
+      break;
+    case 't':
+      timeOutPeriod = atoi(util_optarg);
+      break;
+    case 'B':
+      useBackwardReach = TRUE;
+      break;
+    case 'h':
+      goto usage;
+    case 'i':
+      printBddInfo = TRUE;
+      break;
+    case 'r':
+      reordering = TRUE;
+      break;
+    default:
+      goto usage;
+    }
+  }
+  if(argc == 1) {
+    goto usage;
+  }
+  if(argc == util_optind+1) {
+    execMode = FALSE;
+  }
+  else
+    if(argc == util_optind+2) {
+      execMode = TRUE;
+    }
+    else {
+      error_append("** eqv error: Improper number of arguments.\n");
+      (void) fprintf(vis_stderr, "%s", error_string());
+      goto usage;
+    }
+  if(execMode == FALSE) {
+    hmgr1 = *hmgr;
+    if(Hrc_ManagerReadCurrentNode(hmgr1) == NIL(Hrc_Node_t)) {
+      (void) fprintf(vis_stderr, "** eqv error: The hierarchy manager is empty.  Read in design.\n");
+      return 1;
+    }
+    network1 = (Ntk_Network_t *) Hrc_NodeReadApplInfo(
+		    Hrc_ManagerReadCurrentNode(hmgr1), NTK_HRC_NODE_APPL_KEY);
+    if(network1 == NIL(Ntk_Network_t)) {
+      (void) fprintf(vis_stderr, "** eqv error: There is no network. Use flatten_hierarchy.\n");
+      return 1;
+    }
+    if(!Ntk_NetworkReadNumLatches(network1)) {
+      (void) fprintf(vis_stderr, "** eqv error: No latches present in the current network. Use comb_verify.\n");
+      return 1;
+    }
+    fileName2 = argv[util_optind];
+    if(isBlif) {
+      if((hmgr2 = Io_BlifRead(fileName2, FALSE)) == NIL(Hrc_Manager_t)) {
+	(void) fprintf(vis_stderr, "** eqv error: Error in reading file %s\n", fileName2);
+	goto usage;
+      }
+    }
+    else {
+      if((fp = Cmd_FileOpen(fileName2, "r", NIL(char *), 1)) == NIL(FILE)) {
+	(void) fprintf(vis_stderr, "** eqv error: File %s not found\n", fileName2);
+	return 1;
+      }
+      hmgr2 = Io_BlifMvRead(fp, NIL(Hrc_Manager_t), FALSE, FALSE, FALSE);
+      fclose(fp);
+      if(hmgr2 == NIL(Hrc_Manager_t)) {
+	(void) fprintf(vis_stderr, "** eqv error: Error in reading file %s\n", fileName2);
+	return 1;
+      }
+    }
+    network2 = Ntk_HrcNodeConvertToNetwork(Hrc_ManagerReadCurrentNode(hmgr2),
+					   TRUE, (lsList) NULL);
+    if(network2 == NIL(Ntk_Network_t)) {
+      Hrc_ManagerFree(hmgr2);
+      (void) fprintf(vis_stderr, "** eqv error: Error in network2.\n");
+      return 1;
+    }
+    if(!Ntk_NetworkReadNumLatches(network2)) {
+      (void) fprintf(vis_stderr, "** eqv error: No latches present in %s. Use comb_verify.\n", fileName2);
+      Hrc_ManagerFree(hmgr2);
+      Ntk_NetworkFree(network2);
+      return 1;
+    }
+  }
+  else {
+    fileName1 = argv[util_optind];
+    fileName2 = argv[util_optind+1];
+    if(isBlif) {
+      if((hmgr1 = Io_BlifRead(fileName1, FALSE)) == NIL(Hrc_Manager_t)) {
+	(void) fprintf(vis_stderr, "** eqv error: Error in reading file %s\n", fileName1);
+	return 1;
+      }
+      if((hmgr2 = Io_BlifRead(fileName2, FALSE)) == NIL(Hrc_Manager_t)) {
+	(void) fprintf(vis_stderr, "** eqv error: Error in reading file %s\n", fileName2);
+	if(hmgr1) {
+	  Hrc_ManagerFree(hmgr1);
+	}
+	return 1;
+      }
+    }
+    else {
+      if((fp = Cmd_FileOpen(fileName1, "r", NIL(char *), 1)) == NIL(FILE)) {
+	(void) fprintf(vis_stderr, "** eqv error: File %s not found\n", fileName1);
+	return 1;
+      }
+      hmgr1 = Io_BlifMvRead(fp, NIL(Hrc_Manager_t), FALSE, FALSE, FALSE);
+      fclose(fp);
+      if(hmgr1 == NIL(Hrc_Manager_t)) {
+	(void) fprintf(vis_stderr, "** eqv error: Error in reading file %s\n", fileName1);
+	goto usage;
+      }
+      if((fp = Cmd_FileOpen(fileName2, "r", NIL(char *), 1)) == NIL(FILE)) {
+	(void) fprintf(vis_stderr, "** eqv error: File %s not found\n", fileName2);
+	if(hmgr1) {
+	  Hrc_ManagerFree(hmgr1);
+	}
+	return 1;
+      }
+      hmgr2 = Io_BlifMvRead(fp, NIL(Hrc_Manager_t), FALSE, FALSE, FALSE);
+      fclose(fp);
+      if(hmgr2 == NIL(Hrc_Manager_t)) {
+	(void) fprintf(vis_stderr, "** eqv error: Error in reading file %s\n", fileName2);
+	if(hmgr1) {
+	  Hrc_ManagerFree(hmgr1);
+	}
+	return 1;
+      }
+    }
+    network1 = Ntk_HrcNodeConvertToNetwork(Hrc_ManagerReadCurrentNode(hmgr1),
+					   TRUE, (lsList) NULL);
+    network2 = Ntk_HrcNodeConvertToNetwork(Hrc_ManagerReadCurrentNode(hmgr2),
+					   TRUE, (lsList) NULL);
+    if((network1 == NIL(Ntk_Network_t)) || (network2 == NIL(Ntk_Network_t))) {
+      if(network1 == NIL(Ntk_Network_t)) {
+	(void) fprintf(vis_stderr, "** eqv error: Error in network1.\n");
+      }
+      if(network2 == NIL(Ntk_Network_t)) {
+	(void) fprintf(vis_stderr, "** eqv error: Error in network2.\n");
+      }
+      Hrc_ManagerFree(hmgr1);
+      Hrc_ManagerFree(hmgr2);
+      return 1;
+    }
+
+    if(!Ntk_NetworkReadNumLatches(network1)) {
+      (void) fprintf(vis_stderr, "** eqv error: No latches present in %s. Use comb_verify.\n", fileName1);
+      Hrc_ManagerFree(hmgr1);
+      Ntk_NetworkFree(network1);
+      Hrc_ManagerFree(hmgr2);
+      Ntk_NetworkFree(network2);
+      return 1;
+    }
+    if(!Ntk_NetworkReadNumLatches(network2)) {
+      (void) fprintf(vis_stderr, "** eqv error: No latches present in %s. Use comb_verify.\n", fileName2);
+      Hrc_ManagerFree(hmgr1);
+      Ntk_NetworkFree(network1);
+      Hrc_ManagerFree(hmgr2);
+      Ntk_NetworkFree(network2);
+      return 1;
+    }
+  }
+  if(Ntk_NetworkReadNumPrimaryInputs(network1) !=
+     Ntk_NetworkReadNumInputs(network1)) {
+    error_append("** eqv error: Pseudo inputs present in network1. Unable to do verification.\n");
+    (void) fprintf(vis_stderr, "%s", error_string());
+    if(execMode) {
+      Hrc_ManagerFree(hmgr1);
+      Ntk_NetworkFree(network1);
+    }
+    Hrc_ManagerFree(hmgr2);
+    Ntk_NetworkFree(network2);
+    return 1;
+  }
+  if(Ntk_NetworkReadNumPrimaryInputs(network2) !=
+     Ntk_NetworkReadNumInputs(network2)) {
+    error_append("** eqv error: Pseudo inputs present in network2. Unable to do verification.\n");
+    (void) fprintf(vis_stderr, "%s", error_string());
+    if(execMode) {
+      Hrc_ManagerFree(hmgr1);
+      Ntk_NetworkFree(network1);
+    }
+    Hrc_ManagerFree(hmgr2);
+    Ntk_NetworkFree(network2);
+    return 1;
+  }
+  if(Ntk_NetworkReadNumPrimaryInputs(network1) !=
+     Ntk_NetworkReadNumPrimaryInputs(network2)) {
+    error_append("** eqv error: Different number of inputs in the two networks.\n");
+    (void) fprintf(vis_stderr, "%s", error_string());
+    if(execMode) {
+      Hrc_ManagerFree(hmgr1);
+      Ntk_NetworkFree(network1);
+    }
+    Hrc_ManagerFree(hmgr2);
+    Ntk_NetworkFree(network2);
+    return 1;
+  }
+
+  /* Start the timer before calling the equivalence checker. */
+  if (timeOutPeriod > 0){
+    (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
+    (void) alarm(timeOutPeriod);
+    if (setjmp(timeOutEnv) > 0) {
+      (void) fprintf(vis_stderr, "Timeout occurred after %d seconds.\n",
+		     timeOutPeriod);
+      alarm(0);
+      return 1;
+    }
+  }
+
+  if(fileFlag) {
+    rootsTable = st_init_table(strcmp, st_strhash);
+    leavesTable = st_init_table(strcmp, st_strhash);
+    check = ReadRootLeafMap(inputFile, rootsTable, leavesTable);
+    fclose(inputFile);
+    if(check == 0) {
+      st_free_table(rootsTable);
+      st_free_table(leavesTable);
+      (void) fprintf(vis_stderr, "** eqv error: No data in the input file\n");
+      alarm(0);
+      return 1;
+    }
+    switch (check) {
+    case 1 :
+      st_free_table(rootsTable);
+      outputMap = MapPrimaryOutputsByName(network1, network2);
+      if((outputMap == NIL(st_table)) || !TestLeavesAreValid(network1,
+							     network2,
+							     leavesTable)) {
+	st_foreach_item(leavesTable, gen, &name1, &name2) {
+	  FREE(name1);
+	  FREE(name2);
+	}
+	st_free_table(leavesTable);
+	if(outputMap) {
+	  st_free_table(outputMap);
+	}
+	(void) fprintf(vis_stderr, "%s", error_string());
+	if(execMode) {
+	  Hrc_ManagerFree(hmgr1);
+	  Ntk_NetworkFree(network1);
+	}
+	Hrc_ManagerFree(hmgr2);
+	Ntk_NetworkFree(network2);
+	(void) fprintf(vis_stderr, "%s", error_string());
+	alarm(0);
+	return 1;
+      }
+      equivalent = Eqv_NetworkVerifySequentialEquivalence(network1,
+							  network2,
+							  NIL(st_table),
+							  leavesTable,
+							  partMethod,
+							  useBackwardReach,
+							  reordering);
+      st_foreach_item(leavesTable, gen, &name1, &name2) {
+	FREE(name1);
+	FREE(name2);
+      }
+      st_free_table(leavesTable);
+      break;
+    case 2 :
+      st_free_table(leavesTable);
+      inputMap = MapPrimaryInputsByName(network1, network2);
+
+      if((inputMap == NIL(st_table)) || !TestRootsAreValid(network1,
+							   network2,
+							   rootsTable)) {
+	st_foreach_item(rootsTable, gen, &name1, &name2) {
+	  FREE(name1);
+	  FREE(name2);
+	}
+	st_free_table(rootsTable);
+	if(inputMap) {
+	  st_free_table(inputMap);
+	}
+	(void) fprintf(vis_stderr, "%s", error_string());
+	if(execMode) {
+	  Hrc_ManagerFree(hmgr1);
+	  Ntk_NetworkFree(network1);
+	}
+	Hrc_ManagerFree(hmgr2);
+	Ntk_NetworkFree(network2);
+	alarm(0);
+	return 1;
+      }
+      equivalent = Eqv_NetworkVerifySequentialEquivalence(network1,
+							  network2,
+							  rootsTable,
+							  NIL(st_table),
+							  partMethod,
+							  useBackwardReach,
+							  reordering);
+      st_foreach_item(rootsTable, gen, &name1, &name2) {
+	FREE(name1);
+	FREE(name2);
+      }
+      st_free_table(rootsTable);
+      break;
+    case 3 :
+      if(TestRootsAreValid(network1, network2, rootsTable) &&
+	 TestLeavesAreValid(network1, network2, leavesTable)) {
+	equivalent = Eqv_NetworkVerifySequentialEquivalence(network1,
+							    network2,
+							    rootsTable,
+							    leavesTable,
+							    partMethod,
+							    useBackwardReach,
+							    reordering);
+	st_foreach_item(rootsTable, gen, &name1, &name2) {
+	  FREE(name1);
+	  FREE(name2);
+	}
+	st_free_table(rootsTable);
+	st_foreach_item(leavesTable, gen, &name1, &name2) {
+	  FREE(name1);
+	  FREE(name2);
+	}
+	st_free_table(leavesTable);
+      }
+      else {
+	if(execMode) {
+	  Hrc_ManagerFree(hmgr1);
+	  Ntk_NetworkFree(network1);
+	}
+	Hrc_ManagerFree(hmgr2);
+	Ntk_NetworkFree(network2);
+	st_foreach_item(rootsTable, gen, &name1, &name2) {
+	  FREE(name1);
+	  FREE(name2);
+	}
+	st_free_table(rootsTable);
+	st_foreach_item(leavesTable, gen, &name1, &name2) {
+	  FREE(name1);
+	  FREE(name2);
+	}
+	st_free_table(leavesTable);
+	(void) fprintf(vis_stderr, "%s", error_string());
+	alarm(0);
+	return 1;
+      }
+    }
+  }
+  else {
+    outputMap = MapPrimaryOutputsByName(network1, network2);
+    inputMap = MapPrimaryInputsByName(network1, network2);
+    if((inputMap == NIL(st_table)) || (outputMap == NIL(st_table))) {
+      if(inputMap) {
+	st_free_table(inputMap);
+      }
+      if(outputMap) {
+	st_free_table(outputMap);
+      }
+      if(execMode) {
+	Hrc_ManagerFree(hmgr1);
+	Ntk_NetworkFree(network1);
+      }
+      Hrc_ManagerFree(hmgr2);
+      Ntk_NetworkFree(network2);
+      (void) fprintf(vis_stderr, "%s", error_string());
+      alarm(0);
+      return 1;    /* all primary outputs do not match */
+    }
+    st_free_table(inputMap);
+    st_free_table(outputMap);
+    equivalent = Eqv_NetworkVerifySequentialEquivalence(network1, network2,
+							NIL(st_table),
+							NIL(st_table),
+							partMethod,
+							useBackwardReach,
+							reordering);
+  }
+  if(equivalent) {
+    (void) fprintf(vis_stdout, "Networks are sequentially equivalent.\n\n");
+  }
+  else {
+    (void) fprintf(vis_stdout,
+		   "Networks are NOT sequentially equivalent.\n\n");
+  }
+
+  if (printBddInfo) {
+    bdd_print_stats(Ntk_NetworkReadMddManager(network2), vis_stdout);
+  }
+
+  if(execMode) {
+    Hrc_ManagerFree(hmgr1);
+    Ntk_NetworkFree(network1);
+  }
+  Hrc_ManagerFree(hmgr2);
+  Ntk_NetworkFree(network2);
+
+  alarm(0);
+  return 0;  /* normal exit */
+
+  usage :
+  (void) fprintf(vis_stderr, "usage: seq_verify [-b] [-f filename] [-h] [-p partition method] [-t time] [-B]\n\t\t  [-i] [-r] file1 [file2]\n");
+  (void) fprintf(vis_stderr, "   -b        input files are BLIF\n");
+  (void) fprintf(vis_stderr, "   -f file   variable name correspondence file\n");
+  (void) fprintf(vis_stderr, "   -h        print the command usage\n");
+  (void) fprintf(vis_stderr, "   -p method partitioning method for product machine\n");
+  (void) fprintf(vis_stderr, "   -t time   time out period (in seconds)\n");
+  (void) fprintf(vis_stderr, "   -B        use backward image computation\n");
+  (void) fprintf(vis_stderr, "   -i        print BDD statistics\n");
+  (void) fprintf(vis_stderr, "   -r        enable BDD variable reordering\n");
+  return 1;    /* error exit */
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Handle function for timeout.]
+
+  Description [This function is called when the time out occurs.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+TimeOutHandle(void)
+{
+  longjmp(timeOutEnv, 1);
+}
Index: vis_dev/vis-2.3/src/eqv/eqvInt.h
===================================================================
--- vis_dev/vis-2.3/src/eqv/eqvInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/eqv/eqvInt.h	(revision 14)
@@ -0,0 +1,108 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [eqvInt.h]
+
+  PackageName [eqv]
+
+  Synopsis    []
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [Shaz Qadeer]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: eqvInt.h,v 1.3 2002/09/08 23:29:32 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _EQVINT
+#define _EQVINT
+
+#include "eqv.h"
+#include <string.h>
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN st_table * MapPrimaryInputsByName(Ntk_Network_t *network1, Ntk_Network_t *network2);
+EXTERN st_table * MapCombInputsByName(Ntk_Network_t *network1, Ntk_Network_t *network2);
+EXTERN st_table * MapPrimaryOutputsByName(Ntk_Network_t *network1, Ntk_Network_t *network2);
+EXTERN st_table * MapCombOutputsByName(Ntk_Network_t *network1, Ntk_Network_t *network2);
+EXTERN OFT FindOrderingMethod(void);
+EXTERN boolean TestRootsAndLeavesAreValid(Ntk_Network_t *network1, Ntk_Network_t *network2, st_table *inputMap, st_table *outputMap);
+EXTERN st_table * MapNamesToNodes(Ntk_Network_t *network1, Ntk_Network_t *network2, st_table *names);
+EXTERN int ReadRootLeafMap(FILE *inputFile, st_table *rootsTable, st_table *leavesTable);
+EXTERN void DefaultCommonOrder(Ntk_Network_t *network1, Ntk_Network_t *network2, st_table *inputMap);
+EXTERN boolean TestLeavesAreValid(Ntk_Network_t *network1, Ntk_Network_t *network2, st_table *leavesTable);
+EXTERN boolean TestRootsAreValid(Ntk_Network_t *network1, Ntk_Network_t *network2, st_table *rootsTable);
+EXTERN boolean TestPartitionIsValid(Ntk_Network_t *network, st_table *roots, st_table *leaves);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _EQVINT */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/eqv/eqvMisc.c
===================================================================
--- vis_dev/vis-2.3/src/eqv/eqvMisc.c	(revision 14)
+++ vis_dev/vis-2.3/src/eqv/eqvMisc.c	(revision 14)
@@ -0,0 +1,1105 @@
+/**CFile***********************************************************************
+
+  FileName    [eqvMisc.c]
+
+  PackageName [eqv]
+
+  Synopsis    [This file provides some miscellaneous functions for the eqv
+               package.]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [Shaz Qadeer]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "eqvInt.h"
+
+static char rcsid[] UNUSED = "$Id: eqvMisc.c,v 1.10 2009/04/11 01:40:06 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static boolean NodesMatchUp(Ntk_Node_t *node1, Ntk_Node_t *node2);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [This function returns a hash table of corresponding primary input
+               nodes in network1 and network2.]
+
+  Description [The hash table returned by the function contains corresponding
+               primary input nodes in network1 and network2. The correspondence
+               is based on the names of the nodes. The following conditions
+               constitute an error:
+               1) the number of primary inputs in the two networks is different.
+               2) there is no primary input in network2 by the same name as
+               one occurring in network1.
+               3) the two primary inputs in network1 and network2 having the
+               same names have different variable types.  
+               If an error occurs, NULL is returned.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+st_table *
+MapPrimaryInputsByName(
+  Ntk_Network_t *network1,
+  Ntk_Network_t *network2)
+{
+  lsGen gen1, gen2;
+  Ntk_Node_t *node1, *node2;
+  Var_Variable_t *var1, *var2;
+  char *name1, *name2;
+  boolean flag = FALSE;
+  boolean equivalent = TRUE;
+  boolean causeOfError = TRUE;
+  st_table *inputMap;
+  int numValues;
+  int i;
+  
+  if(Ntk_NetworkReadNumPrimaryInputs(network1) !=
+           Ntk_NetworkReadNumPrimaryInputs(network2)) {
+    error_append("Different number of primary inputs in the two networks\n");
+    return NIL(st_table);
+  }
+  inputMap = st_init_table(st_ptrcmp, st_ptrhash);
+  Ntk_NetworkForEachPrimaryInput(network1, gen1, node1) {
+    name1 = Ntk_NodeReadName(node1);
+    Ntk_NetworkForEachPrimaryInput(network2, gen2, node2) {
+      name2 = Ntk_NodeReadName(node2);
+      if (strcmp(name1, name2) == 0) {
+	boolean a, b;
+        
+        var1 = Ntk_NodeReadVariable(node1);
+        var2 = Ntk_NodeReadVariable(node2);
+	a = Var_VariableTestIsEnumerative(var1);
+	b = Var_VariableTestIsEnumerative(var2);
+	if((a && !b) || (!a && b)) {
+	  error_append("Input ");
+          error_append(name1);
+          error_append(" and ");
+          error_append(name2);
+          error_append(" have different variable types\n");
+          causeOfError = FALSE;
+        }
+	else {
+          numValues = Var_VariableReadNumValues(var1);
+          if(a && b) {
+            if(numValues == Var_VariableReadNumValues(var2)) {
+              st_insert(inputMap, (char *) node1, (char *) node2);
+              flag = TRUE;
+            }	
+            else {
+              error_append("Input ");
+              error_append(name1);
+              error_append(" and ");
+              error_append(name2);
+              error_append(" have different range of values\n");
+              causeOfError = FALSE;
+            }
+          }
+          else {/* both are symbolic */
+            boolean flag2 = TRUE;
+            for(i=0; i<numValues; i++) {
+              if(strcmp(Var_VariableReadSymbolicValueFromIndex(var1, i),
+                        Var_VariableReadSymbolicValueFromIndex(var2, i)))
+                {
+                  flag2 = FALSE;
+                  error_append("Input ");
+                  error_append(name1);
+                  error_append(" and ");
+                  error_append(name2);
+                  error_append(" have different symbolic values\n");
+                  causeOfError = FALSE;
+                }
+            }
+            if(flag2) {
+              st_insert(inputMap, (char *) node1, (char *) node2);
+              flag = TRUE;
+            }
+          }
+        }
+      }
+    }
+
+    if(!flag) {
+      equivalent = FALSE;    /* name1 did not find a match in network2 */
+      if(causeOfError) {
+        error_append("Input ");
+        error_append(name1);
+        error_append(" does not have a match\n");
+      }
+      else {
+        causeOfError = TRUE;
+      }
+    }
+    else {
+      flag = FALSE;
+    }	
+  }
+  
+  
+  if(!equivalent) {
+    st_free_table(inputMap);
+    return NIL(st_table);
+  }
+  else {
+    return inputMap;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis     [The function returns a hash table of corresponding
+  combinational input nodes in network1 and network2.]
+
+  Description  [The hash table returned by the function contains corresponding
+               combinational input nodes in network1 and network2. The
+               correspondence is based on the names of the nodes. The
+               following conditions constitute an error:
+               1) the number of combinational inputs in the two networks is
+               different.
+               2) there is no combinational input in network2 by the same name as
+               one occurring in network1.
+               3) the two combinational inputs in network1 and network2 having 
+               same names have different variable types.  
+               If an error occurs, NULL is returned.]
+
+  SideEffects  []
+
+  SeeAlso      []
+
+******************************************************************************/
+st_table *
+MapCombInputsByName(
+  Ntk_Network_t *network1,
+  Ntk_Network_t *network2)
+{
+  lsGen gen1, gen2;
+  Ntk_Node_t *node1, *node2;
+  Var_Variable_t *var1, *var2;
+  char *name1, *name2;
+  boolean flag = FALSE;
+  boolean equivalent = TRUE;
+  boolean causeOfError = TRUE;
+  st_table *inputMap;
+  int numValues;
+  int i;
+  
+  if(Ntk_NetworkReadNumCombInputs(network1) !=
+           Ntk_NetworkReadNumCombInputs(network2)) {
+    error_append("Different number of combinational inputs in the two networks\n");
+    return NIL(st_table);
+  }
+  inputMap = st_init_table(st_ptrcmp, st_ptrhash);
+  Ntk_NetworkForEachCombInput(network1, gen1, node1) {
+    name1 = Ntk_NodeReadName(node1);
+    Ntk_NetworkForEachCombInput(network2, gen2, node2) {
+      name2 = Ntk_NodeReadName(node2);
+      if (strcmp(name1, name2) == 0) {
+	boolean a, b;
+        
+        var1 = Ntk_NodeReadVariable(node1);
+        var2 = Ntk_NodeReadVariable(node2);
+	a = Var_VariableTestIsEnumerative(var1);
+	b = Var_VariableTestIsEnumerative(var2);
+	if((a && !b) || (!a && b)) {
+	  error_append("Input ");
+          error_append(name1);
+          error_append(" and ");
+          error_append(name2);
+          error_append(" have different variable types\n");
+          causeOfError = FALSE;
+        }
+	else {
+          numValues = Var_VariableReadNumValues(var1);
+          if(a && b) {
+            if(numValues == Var_VariableReadNumValues(var2)) {
+              st_insert(inputMap, (char *) node1, (char *) node2);
+              flag = TRUE;
+            }	
+            else {
+              error_append("Input ");
+              error_append(name1);
+              error_append(" and ");
+              error_append(name2);
+              error_append(" have different range of values\n");
+              causeOfError = FALSE;
+            }
+          }
+          else {/* both are symbolic */
+            boolean flag2 = TRUE;
+            for(i=0; i<numValues; i++) {
+              if(strcmp(Var_VariableReadSymbolicValueFromIndex(var1, i),
+                        Var_VariableReadSymbolicValueFromIndex(var2, i)))
+                {
+                  flag2 = FALSE;
+                  error_append("Input ");
+                  error_append(name1);
+                  error_append(" and ");
+                  error_append(name2);
+                  error_append(" have different symbolic values\n");
+                  causeOfError = FALSE;
+                }
+            }
+            if(flag2) {
+              st_insert(inputMap, (char *) node1, (char *) node2);
+              flag = TRUE;
+            }
+          }
+        }
+      }
+    }
+
+    if(!flag) {
+      equivalent = FALSE;    /* name1 did not find a match in network2 */
+      if(causeOfError) {
+        error_append("Input ");
+        error_append(name1);
+        error_append(" does not have a match\n");
+      }
+      else {
+        causeOfError = TRUE;
+      }
+    }
+    else {
+      flag = FALSE;
+    }	
+  }
+  
+  
+  if(!equivalent) {
+    st_free_table(inputMap);
+    return NIL(st_table);
+  }
+  else {
+    return inputMap;
+  }
+}
+  
+/**Function********************************************************************
+
+  Synopsis    [This function returns a hash table of corresponding primary
+  output nodes in network1 and network2.]
+
+  Description [The hash table returned by the function contains corresponding
+               primary output nodes in network1 and network2. The correspondence
+               is based on the names of the nodes. The following conditions
+               constitute an error:
+               1) the number of primary outputs in the two networks is different.
+               2) there is no primary output in network2 by the same name as
+               one occurring in network1.
+               3) the two primary outputs in network1 and network2 having the
+               same names have different variable types.  
+               If an error occurs, NULL is returned.]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+st_table *
+MapPrimaryOutputsByName(
+  Ntk_Network_t *network1,
+  Ntk_Network_t *network2)
+{
+  lsGen gen1, gen2;
+  Ntk_Node_t *node1, *node2;
+  Var_Variable_t *var1, *var2;
+  char *name1, *name2;
+  boolean flag = FALSE;
+  boolean equivalent = TRUE;
+  boolean causeOfError = TRUE;
+  st_table *outputMap;
+  int numValues;
+  int i;
+  
+  if(Ntk_NetworkReadNumPrimaryOutputs(network1) !=
+           Ntk_NetworkReadNumPrimaryOutputs(network2)) {
+    error_append("Different number of primary outputs in the two networks\n");
+    return NIL(st_table);
+  }
+  outputMap = st_init_table(st_ptrcmp, st_ptrhash);
+  Ntk_NetworkForEachPrimaryOutput(network1, gen1, node1) {
+    name1 = Ntk_NodeReadName(node1);
+    Ntk_NetworkForEachPrimaryOutput(network2, gen2, node2) {
+      name2 = Ntk_NodeReadName(node2);
+      if (strcmp(name1, name2) == 0) {
+	boolean a, b;
+        
+        var1 = Ntk_NodeReadVariable(node1);
+        var2 = Ntk_NodeReadVariable(node2);
+	a = Var_VariableTestIsEnumerative(var1);
+	b = Var_VariableTestIsEnumerative(var2);
+	if((a && !b) || (!a && b)) {
+	  error_append("Output ");
+          error_append(name1);
+          error_append(" and ");
+          error_append(name2);
+          error_append(" have different variable types\n");
+          causeOfError = FALSE;
+        }
+	else {
+          numValues = Var_VariableReadNumValues(var1);
+          if(a && b) {
+            if(numValues == Var_VariableReadNumValues(var2)) {
+              st_insert(outputMap, (char *) node1, (char *) node2);
+              flag = TRUE;
+            }	
+            else {
+              error_append("Output ");
+              error_append(name1);
+              error_append(" and ");
+              error_append(name2);
+              error_append(" have different range of values\n");
+              causeOfError = FALSE;
+            }
+          }
+          else {/* both are symbolic */
+            boolean flag2 = TRUE;
+            for(i=0; i<numValues; i++) {
+              if(strcmp(Var_VariableReadSymbolicValueFromIndex(var1, i),
+                        Var_VariableReadSymbolicValueFromIndex(var2, i)))
+                {
+                  flag2 = FALSE;
+                  error_append("Output ");
+                  error_append(name1);
+                  error_append(" and ");
+                  error_append(name2);
+                  error_append(" have different symbolic values\n");
+                  causeOfError = FALSE;
+                }
+            }
+            if(flag2) {
+              st_insert(outputMap, (char *) node1, (char *) node2);
+              flag = TRUE;
+            }
+          }
+        }
+        
+      }
+    }
+
+    if(!flag) {
+      equivalent = FALSE;    /* name1 did not find a match in network2 */
+      if(causeOfError) {
+        error_append("Output ");
+        error_append(name1);
+        error_append(" does not have a match\n");
+      }
+      else {
+        causeOfError = TRUE;
+      }
+    }
+    else {
+      flag = FALSE;
+    }	
+  }
+  
+  
+  if(!equivalent) {
+    st_free_table(outputMap);
+    return NIL(st_table);
+  }
+  else {
+    return outputMap;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [This function returns a hash table of corresponding
+  combinational output nodes in network1 and network2.]
+
+  Description [The hash table returned by the function contains corresponding
+               combinational output nodes in network1 and network2. The
+               correspondence is based on the names of the nodes. The
+               following conditions constitute an error:
+               1) the number of combinational outputs in the two networks is
+               different.
+               2) there is no combinational output in network2 by the same
+               name as one occurring in network1.
+               3) the two combinational outputs in network1 and network2 having 
+               same names have different variable types.  
+               If an error occurs, NULL is returned.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+st_table *
+MapCombOutputsByName(
+  Ntk_Network_t *network1,
+  Ntk_Network_t *network2)
+{
+  lsGen gen1, gen2;
+  Ntk_Node_t *node1, *node2;
+  Var_Variable_t *var1, *var2;
+  char *name1, *name2;
+  boolean flag = FALSE;
+  boolean equivalent = TRUE;
+  boolean causeOfError = TRUE;
+  st_table *outputMap;
+  int numValues;
+  int i;
+  
+  if(Ntk_NetworkReadNumCombOutputs(network1) !=
+     Ntk_NetworkReadNumCombOutputs(network2)) {
+    error_append("Different number of combinational outputs in the two networks\n");
+    return NIL(st_table);
+  }
+  outputMap = st_init_table(st_ptrcmp, st_ptrhash);
+  Ntk_NetworkForEachCombOutput(network1, gen1, node1) {
+    name1 = Ntk_NodeReadName(node1);
+    Ntk_NetworkForEachCombOutput(network2, gen2, node2) {
+      name2 = Ntk_NodeReadName(node2);
+      if (NodesMatchUp(node1, node2)) {
+	boolean a, b;
+
+        var1 = Ntk_NodeReadVariable(node1);
+        var2 = Ntk_NodeReadVariable(node2);
+	a = Var_VariableTestIsEnumerative(var1);
+	b = Var_VariableTestIsEnumerative(var2);
+	if((a && !b) || (!a && b)) {
+	  error_append("Output ");
+          error_append(name1);
+          error_append(" and ");
+          error_append(name2);
+          error_append(" have different variable types\n");
+          causeOfError = FALSE;
+        }
+	else {
+          numValues = Var_VariableReadNumValues(var1);
+          if(a && b) {
+            if(numValues == Var_VariableReadNumValues(var2)) {
+              st_insert(outputMap, (char *) node1, (char *) node2);
+              flag = TRUE;
+            }
+            else {
+              error_append("Output ");
+              error_append(name1);
+              error_append(" and ");
+              error_append(name2);
+              error_append(" have different range of values\n");
+              causeOfError = FALSE;
+            }
+          }
+          else {/* both are symbolic */
+            boolean flag2 = TRUE;
+            for(i=0; i<numValues; i++) {
+              if(strcmp(Var_VariableReadSymbolicValueFromIndex(var1, i),
+                        Var_VariableReadSymbolicValueFromIndex(var2, i)))
+                {
+                  flag2 = FALSE;
+                  error_append("Output ");
+                  error_append(name1);
+                  error_append(" and ");
+                  error_append(name2);
+                  error_append(" have different symbolic values\n");
+                  causeOfError = FALSE;
+                }
+            }
+            if(flag2) {
+              st_insert(outputMap, (char *) node1, (char *) node2);
+              flag = TRUE;
+	      break;
+            }
+          }
+        }
+      }
+    }
+
+    if(!flag) {
+      equivalent = FALSE;    /* name1 did not find a match in network2 */
+      if(causeOfError) {
+        error_append("Output ");
+        error_append(name1);
+        error_append(" does not have a match\n");
+      }
+      else {
+        causeOfError = TRUE;
+      }
+    }
+    else {
+      flag = FALSE;
+    }	
+  }
+  
+  
+  if(!equivalent) {
+    st_free_table(outputMap);
+    return NIL(st_table);
+  }
+  else {
+    return outputMap;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [This function returns the ordering method to be used.]
+
+  SideEffects []
+  
+  SeeAlso     []
+
+******************************************************************************/
+OFT
+FindOrderingMethod(void)
+{
+  return (OFT) NULL;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [The function checks whether inputMap and outputMap form valid
+               roots and leaves for network1 and network2.]
+
+  Description [inputMap is a hash table of the corresponding leaves in
+  network1 and network2. outputMap is a hash table of the corresponding roots
+  in network1 and network2. The function checks whether the leaves of each
+  network form a complete support of its roots. If this turns out to be false
+  for any network, FALSE is returned otherwise TRUE is returned.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+TestRootsAndLeavesAreValid(
+  Ntk_Network_t *network1,
+  Ntk_Network_t *network2,
+  st_table *inputMap,
+  st_table *outputMap)
+{
+  
+  st_generator *gen;
+  array_t *roots1, *roots2;
+  st_table *leaves1, *leaves2;
+  Ntk_Node_t *node1, *node2;
+  boolean test = TRUE;
+  
+  roots1 = array_alloc(Ntk_Node_t *, 0);
+  roots2 = array_alloc(Ntk_Node_t *, 0);
+  st_foreach_item(outputMap, gen, &node1, &node2) {
+    array_insert_last(Ntk_Node_t *, roots1, node1);
+    array_insert_last(Ntk_Node_t *, roots2, node2);
+  }
+  leaves1 = st_init_table(st_ptrcmp, st_ptrhash);
+  leaves2 = st_init_table(st_ptrcmp, st_ptrhash);
+  st_foreach_item(inputMap, gen, &node1, &node2) {
+    st_insert(leaves1, node1, NULL);
+    st_insert(leaves2, node2, NULL);
+  }
+  if(!Ntk_NetworkTestLeavesCoverSupportOfRoots(network1, roots1,
+                                             leaves1)) {
+    error_append("Leaves do not form a complete support for roots in network1.\n");
+    test = FALSE;
+  }
+  if(!Ntk_NetworkTestLeavesCoverSupportOfRoots(network2, roots2,
+                                             leaves2)) {
+    error_append("Leaves do not form a complete support for roots in network2.\n");
+    test = FALSE;
+  }
+  array_free(roots1);
+  array_free(roots2);
+  st_free_table(leaves1);
+  st_free_table(leaves2);
+  return test;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [This function takes a hash table of names and generates a
+               hash table of nodes.]
+
+  Description [The input to the function is a hash table of names of nodes.
+               It returns a hash table of nodes corresponding to the names.
+               In the hash table names, key is a name in network1 and value
+               is a name in network2. Similarly, in the table which is
+               returned, key is a node in network1 and value a node in
+               network2. If no node by a certain name is found in a network,
+               NULL is returned.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+st_table *
+MapNamesToNodes(
+  Ntk_Network_t *network1,
+  Ntk_Network_t *network2,
+  st_table *names)
+{
+  st_table *nodes = st_init_table(st_ptrcmp, st_ptrhash);
+  char *name1, *name2;
+  Ntk_Node_t *node1, *node2;
+  boolean error = FALSE;
+  st_generator *gen;
+  
+  
+  st_foreach_item(names, gen, &name1, &name2) {
+    if((node1 = Ntk_NetworkFindNodeByName(network1, name1)) ==
+       NIL(Ntk_Node_t)) {
+      error = TRUE;
+      error_append(name1);
+      error_append(" not present in network1.\n");
+    }
+    
+    if((node2 = Ntk_NetworkFindNodeByName(network2, name2)) ==
+       NIL(Ntk_Node_t)) {
+      error = TRUE;
+      error_append(name2);
+      error_append(" not present in network2.\n");
+    }
+    st_insert(nodes, (char *) node1, (char *) node2);
+  }
+  if(error) {
+    st_free_table(nodes);
+    return NIL(st_table);
+  }
+  else {
+    return nodes;
+  }
+}
+
+    
+/**Function********************************************************************
+
+  Synopsis    [This function reads an input file containing names of roots and
+  leaves, and stores the corresponding names in the two hash tables-
+  rootsTable and leavesTable.]
+  
+  Description [The function returns 0 if there are no roots or leaves in the
+               file. It is an error not to have either roots or leaves in the
+               file. It returns 1 if there are roots but no leaves, 2 if there
+               are leaves but no roots, and 3 if there are both roots and
+               leaves.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+ReadRootLeafMap(
+  FILE *inputFile,
+  st_table *rootsTable,
+  st_table *leavesTable)
+{
+  char *name;
+  char *rootName1, *rootName2;
+  char *leafName1, *leafName2;
+  char c;
+  boolean rootsFlag= 0;
+  boolean leavesFlag = 0;
+  st_generator *gen;
+  
+  while(((c = fgetc(inputFile)) == ' ') || (c == '\t') || (c== '\n' ));
+  ungetc(c, inputFile);
+  name = ALLOC(char, 20);
+  
+  if(fscanf(inputFile, "%s", name) == EOF) {
+    FREE(name);
+    return 0;
+    /* both roots and leaves absent */
+  }
+  if(!strcmp(name, ".roots")) {
+    rootsFlag = 1;
+    while(((c = fgetc(inputFile)) == ' ') || (c == '\t') || (c== '\n' ));
+    ungetc(c, inputFile);
+    while((fscanf(inputFile, "%s", name) != EOF) && strcmp(name, ".leaves")) {
+      rootName1 = ALLOC(char, strlen(name) + 1);
+      strcpy(rootName1, name);
+      while(((c = fgetc(inputFile)) == ' ') || (c == '\t') || (c== '\n' ));
+      ungetc(c, inputFile);
+      if((fscanf(inputFile, "%s", name) == EOF) || (!strcmp(name, ".leaves"))) {
+        FREE(name);
+        FREE(rootName1);
+        st_foreach_item(rootsTable, gen, &rootName1, &rootName2) {
+          FREE(rootName1);
+          FREE(rootName2);
+          return 0;
+        }
+      }
+      rootName2 = ALLOC(char, strlen(name) + 1);
+      strcpy(rootName2, name);
+      st_insert(rootsTable, rootName1, rootName2);
+      while(((c = fgetc(inputFile)) == ' ') || (c == '\t') || (c== '\n' ));
+      ungetc(c, inputFile);
+      name[0] = '\0'; /* this is to insure that whenever the while loop
+                         is terminated, only one of the conditions is false */
+    }
+  }
+  if(!strcmp(name, ".leaves")) {
+    leavesFlag = 1;
+    while(((c = fgetc(inputFile)) == ' ') || (c == '\t') || (c== '\n' ));
+    ungetc(c, inputFile);
+    while(fscanf(inputFile, "%s", name) != EOF) {
+      leafName1 = ALLOC(char, strlen(name) + 1);
+      strcpy(leafName1, name);
+      while(((c = fgetc(inputFile)) == ' ') || (c == '\t') || (c== '\n' ));
+      ungetc(c, inputFile);
+      if(fscanf(inputFile, "%s", name) == EOF) {
+        FREE(name);
+        FREE(leafName1);
+        st_foreach_item(leavesTable, gen, &leafName1, &leafName2) {
+          FREE(leafName1);
+          FREE(leafName2);
+          return 0;
+        }
+      }
+      leafName2 = ALLOC(char, strlen(name) + 1);
+      strcpy(leafName2, name);
+      st_insert(leavesTable, leafName1, leafName2);
+      while(((c = fgetc(inputFile)) == ' ') || (c == '\t') || (c== '\n' ));
+      ungetc(c, inputFile);
+    }
+  }
+  FREE(name);
+  if(rootsFlag == 1) {
+    if(leavesFlag == 1) {
+      return 3; /* both leaves and roots present */
+    }
+    else {
+      return 2; /* roots present but leaves absent */
+    }
+  }
+  else {
+    if(leavesFlag == 1) {
+      return 1; /* roots absent but leaves present */
+    }
+    else {
+      return 0;
+    }
+  }
+}
+  
+/**Function********************************************************************
+
+  Synopsis    [This function generates the default ordering of leaf nodes.]
+
+  Description [The function checks if network1 has a partition registered with
+  it. If there is no partition, The function orders the variables of network1,
+  using the option Ord_All_c i.e. orders all the nodes. If a partition exists,
+  the existing ordering is left undisturbed. It then copies the mddIds
+  of those nodes of network1 which are present in inputMap into
+  the corresponding nodes of network2.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+DefaultCommonOrder(
+  Ntk_Network_t *network1, 
+  Ntk_Network_t *network2,
+  st_table *inputMap)
+{
+  st_generator *gen;
+  Ntk_Node_t *node1, *node2;
+  int id;
+  lsList dummy = (lsList) 0;
+  
+  if(Ntk_NetworkReadApplInfo(network1, PART_NETWORK_APPL_KEY) == NIL(void)) {
+    Ord_NetworkOrderVariables(network1, Ord_RootsByDefault_c,
+                              Ord_NodesByDefault_c, FALSE, Ord_All_c,
+                              Ord_Unassigned_c, dummy, 0);
+  }
+  
+  st_foreach_item(inputMap, gen, &node1, &node2) {
+    id = Ntk_NodeReadMddId(node1);
+    Ntk_NodeSetMddId(node2, id);
+  }
+}
+  
+      
+
+/**Function********************************************************************
+
+  Synopsis    [This function checks whether the leaves present in leavesTable
+  constitute the full set of primary inputs of network1 and network2.]
+
+  Description [leavesTable contains names of corresponding leaves in network1
+  and network2. The function returns TRUE if the leaves present in leavesTable
+  constitute the full set of primary inputs of network1 and network2. The
+  following  conditions result in a return value of FALSE:
+  a) there is no node by a name present in leavesTable.
+  b) the node with a particular name is not a primary input
+  c) the number of leaves is different from the number of primary inputs in
+  either network.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+TestLeavesAreValid(
+  Ntk_Network_t *network1,
+  Ntk_Network_t *network2,
+  st_table *leavesTable)
+
+{
+  st_generator *gen;
+  Ntk_Node_t *node1, *node2;
+  char *name1, *name2;
+  boolean valid = TRUE;
+  int count = 0;
+  
+  st_foreach_item(leavesTable, gen, &name1, &name2) {
+    node1 = Ntk_NetworkFindNodeByName(network1, name1);
+    node2 = Ntk_NetworkFindNodeByName(network2, name2);
+    if(node1 == NIL(Ntk_Node_t)) {
+      error_append(name1);
+      error_append(" not found in network1.\n");
+      valid = FALSE;
+    }
+    else {
+      if(!Ntk_NodeTestIsPrimaryInput(node1)) {
+        error_append(name1);
+        error_append(" is not a primary input node\n");
+        valid = FALSE;
+      }
+    }
+    
+    if(node2 == NIL(Ntk_Node_t)) {
+      error_append(name2);
+      error_append(" not found in network2.\n");
+      valid = FALSE;
+    }
+    else {
+      if(!Ntk_NodeTestIsPrimaryInput(node2)) {
+        error_append(name2);
+        error_append(" is not a primary input node\n");
+        valid = FALSE;
+      }
+    }
+    
+    count ++;
+  }
+  if(valid) {
+    if(!((Ntk_NetworkReadNumPrimaryInputs(network1) == count) && (Ntk_NetworkReadNumPrimaryInputs(network2) == count))) {
+      error_append("All primary inputs not specified in the input file\n");
+      valid = FALSE;
+    }
+  }
+  return valid;
+}
+
+/**Function********************************************************************
+
+  Synopsis       [The function checks whether the names present in rootsTable
+  have nodes corresponding to them present in network1 and network2.]
+
+  Description    [rootsTable contains names of corresponding roots in network1
+  and network2. The function returns TRUE if the roots present in rootsTable
+  have nodes corresponding to them in the network1 and network2. Otherwise,
+  FALSE is returned.]
+
+  SideEffects    []
+
+  SeeAlso        []
+
+******************************************************************************/
+boolean
+TestRootsAreValid(
+  Ntk_Network_t *network1,
+  Ntk_Network_t *network2,
+  st_table *rootsTable)
+
+{
+  st_generator *gen;
+  char *name1, *name2;
+  boolean valid = TRUE;
+  
+  st_foreach_item(rootsTable, gen, &name1, &name2) {
+    if(Ntk_NetworkFindNodeByName(network1, name1) == NIL(Ntk_Node_t)) {
+      valid = FALSE;
+      error_append(name1);
+      error_append(" not present in network1.\n");
+    }
+    
+    if(Ntk_NetworkFindNodeByName(network2, name2) == NIL(Ntk_Node_t)) {
+      valid = FALSE;
+      error_append(name2);
+      error_append(" not present in network2.\n");
+    }
+  }
+  return valid;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [The function checks whether the partition registered
+  with network has vertices corresponding to nodes stored as keys in roots and
+  leaves.]
+
+  Description        [The function returns TRUE if all the nodes stored as
+                      keys in roots and leaves have corresponding vertices in
+                      the partition of network. It returns FALSE otherwise. It
+                      is assumed that network has a partition associated with
+                      it.]
+
+  SideEffects        []
+
+  SeeAlso            []
+
+******************************************************************************/
+boolean
+TestPartitionIsValid(
+  Ntk_Network_t *network,
+  st_table *roots,
+  st_table *leaves)
+{
+  graph_t *partition = Part_NetworkReadPartition(network);
+  st_generator *gen;
+  char *name;
+  Ntk_Node_t *node1, *node2;
+  boolean flag = TRUE;
+  
+  st_foreach_item(roots, gen, &node1, &node2) {
+    name = Ntk_NodeReadName(node1);
+    if(Part_PartitionFindVertexByName(partition, name) == NIL(vertex_t)) {
+      flag = FALSE;
+    }
+  }
+  st_foreach_item(leaves, gen, &node1, &node2) {
+    name = Ntk_NodeReadName(node1);
+    if(Part_PartitionFindVertexByName(partition, name) == NIL(vertex_t)) {
+      flag = FALSE;
+    }
+  }
+  return flag;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Check whether two nodes may be matched by name.]
+
+  Description [Check whether two nodes from different networks may be
+  matched by name in equivalence verification.  If the two nodes have
+  the same names, then they match.  Moreover, if the two nodes are
+  latch inputs and the corresponding latches match by name, they also
+  match.  This last clause makes comb_verify a lot more useful because
+  small changes in Verilog source or in its translation to blif-mv
+  usually leave the latch names unchanged, but alter the names of
+  the next state variables.]
+
+  SideEffects [none]
+
+  SeeAlso     [MapCombOutputsByName]
+
+******************************************************************************/
+static boolean
+NodesMatchUp(
+  Ntk_Node_t *node1 /* node from network1 */,
+  Ntk_Node_t *node2 /* node from network2 */
+  )
+{
+  char *name1, *name2;
+
+  name1 = Ntk_NodeReadName(node1);
+  name2 = Ntk_NodeReadName(node2);
+
+  if (strcmp(name1, name2) == 0)
+    return TRUE;
+
+  /* Try to match through the state variables. */
+  if ((Ntk_NodeTestIsLatchDataInput(node1) &&
+      Ntk_NodeTestIsLatchDataInput(node2)) ||
+      (Ntk_NodeTestIsLatchInitialInput(node1) &&
+       Ntk_NodeTestIsLatchInitialInput(node2))) {
+    Ntk_Node_t *latch1, *latch2;
+    char *nameLatch1, *nameLatch2;
+    array_t *fanout1, *fanout2;
+
+    fanout1 = Ntk_NodeReadFanouts(node1);
+    if (array_n(fanout1) != 1) return FALSE;
+    fanout2 = Ntk_NodeReadFanouts(node2);
+    if (array_n(fanout2) != 1) return FALSE;
+
+    latch1 = array_fetch(Ntk_Node_t *, fanout1, 0);
+    assert(Ntk_NodeTestIsLatch(latch1));
+    latch2 = array_fetch(Ntk_Node_t *, fanout2, 0);
+    assert(Ntk_NodeTestIsLatch(latch2));
+
+    nameLatch1 = Ntk_NodeReadName(latch1);
+    nameLatch2 = Ntk_NodeReadName(latch2);
+
+    return (strcmp(nameLatch1, nameLatch2) == 0);
+  }
+
+  return FALSE;
+
+} /* NodesMatchUp */
Index: vis_dev/vis-2.3/src/eqv/eqvVerify.c
===================================================================
--- vis_dev/vis-2.3/src/eqv/eqvVerify.c	(revision 14)
+++ vis_dev/vis-2.3/src/eqv/eqvVerify.c	(revision 14)
@@ -0,0 +1,637 @@
+/**CFile***********************************************************************
+
+  FileName    [eqvVerify.c]
+
+  PackageName [eqv]
+
+  Synopsis    [This file contains the two routines which do combinational and
+  sequential verification.]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [Shaz Qadeer]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "eqvInt.h"
+
+static char rcsid[] UNUSED = "$Id: eqvVerify.c,v 1.10 2009/04/11 01:40:06 fabio Exp $";
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [This function does combinational verification between network1
+  and network2.]
+
+  Description [roootsMap and leavesMap contain corresponding nodes in network1
+  and network2. It is assumed that the set of leaf nodes forms a complete
+  support of the set of root nodes in both the networks. This function
+  verifies the combinational equivalence of corresponding roots in terms of
+  the leaves. method1 and method2 specify the partition methods to be used for
+  partitioning network1 and network2 respectively. AssignCommonOrder is a
+  pointer to a function which takes two networks, whose mdd managers are
+  identical, and a hash table containing corresponding leaf nodes whose mdd Id
+  should be the same. AssignCommonOrder() orders the two networks ensuring
+  that identical mddIds are assigned to the corresponding leaf nodes in the
+  hash table. This function has to be supplied by the user.
+
+  This function returns TRUE if all the root pairs are combinationally
+  equivalent otherwise it returns FALSE. It is assumed that network1 already
+  has a mdd manager. If a partition is registered with network1, and it has
+  vertices corresponding to the specified roots and leaves it is used
+  otherwise a new partition is created. A new partition is always created for
+  network2.]
+
+  SideEffects []
+
+******************************************************************************/
+boolean
+Eqv_NetworkVerifyCombinationalEquivalence(
+  Ntk_Network_t *network1,
+  Ntk_Network_t *network2,
+  st_table *leavesMap,  /* the mapping between the inputs of the networks;
+			 * hash table from Ntk_Node_t * to Ntk_Node_t * */
+  st_table *rootsMap,   /* the mapping between the outputs of the networks;
+			 * hash table from Ntk_Node_t * to Ntk_Node_t * */
+  OFT AssignCommonOrder,
+  Part_PartitionMethod method1,
+  Part_PartitionMethod method2)
+{
+  mdd_manager *mddMgr;
+  lsList leavesList1, leavesList2;
+  lsList rootsList1, rootsList2;
+  st_table *leaves1, *leaves2;
+  array_t *roots1, *roots2;
+  st_generator *gen;
+  lsGen listGen;
+  graph_t *rootsToLeaves1, *rootsToLeaves2;
+  Ntk_Node_t *node1, *node2;
+  char *name1, *name2, *name;
+  Mvf_Function_t *func1, *func2;
+  int num, i, j;
+  array_t *mvfRoots1, *mvfRoots2;
+  boolean equivalent = TRUE;
+  lsList dummy = (lsList) 0;
+  int mddId1, mddId2;
+  vertex_t *vertex;
+  lsGeneric data;
+  boolean partValid = FALSE;
+  mdd_manager *mgr;
+  int mddId;
+  array_t *mddIdArray;
+  mdd_t *aMinterm, *diff;
+  char *mintermName;
+  mdd_t *comp1, *comp2;
+  int numComponents;
+
+  /* First check whether a partition is registered with network1 */
+  if(Ntk_NetworkReadApplInfo(network1, PART_NETWORK_APPL_KEY) != NIL(void)) {
+    /*
+     * Check whether the registered partition can be used to compute the roots
+     * in terms of the leaves. If it can be used, then i won't create a new
+     * one.
+     */
+    partValid = TestPartitionIsValid(network1, rootsMap, leavesMap);
+    /*
+     * If a partition already exists, an mddManager also exists.
+     * So, don't allocate a new one.
+     */
+    mddMgr = Ntk_NetworkReadMddManager(network1);
+  }
+  else {
+    mddMgr = Ntk_NetworkInitializeMddManager(network1);
+  }
+  assert(mddMgr != NIL(mdd_manager));
+  Ntk_NetworkSetMddManager(network2, mddMgr);
+  (*AssignCommonOrder)(network1, network2, leavesMap);
+
+  /* Create lists of leaves and roots for creating partitions. */
+  leavesList1 = lsCreate();
+  leavesList2 = lsCreate();
+  st_foreach_item(leavesMap, gen, &node1, &node2) {
+    mddId1 = Ntk_NodeReadMddId(node1);
+    mddId2 = Ntk_NodeReadMddId(node2);
+    assert(mddId1 == mddId2);
+    lsNewEnd(leavesList1, (lsGeneric) node1, LS_NH);
+    lsNewEnd(leavesList2, (lsGeneric) node2, LS_NH);
+  }
+
+  rootsList1 = lsCreate();
+  rootsList2 = lsCreate();
+  st_foreach_item(rootsMap, gen, &node1, &node2) {
+    lsNewEnd(rootsList1, (lsGeneric) node1, LS_NH);
+    lsNewEnd(rootsList2, (lsGeneric) node2, LS_NH);
+  }
+
+  if(partValid) {
+    rootsToLeaves1 = Part_NetworkReadPartition(network1);
+  }
+  else {
+    rootsToLeaves1 = Part_NetworkCreatePartition(network1, NIL(Hrc_Node_t),
+						 "dummy", rootsList1,
+						 leavesList1, NIL(mdd_t),
+						 method1, dummy,
+						 FALSE, FALSE, TRUE);
+  }
+
+  /*
+   * Generate arrays of root and leaf vertices in the first partition
+   * to pass as arguments to Part_PartitionCollapse().
+   */
+  roots1 = array_alloc(vertex_t *, 0);
+  lsForEachItem(rootsList1, listGen, data) {
+    name = Ntk_NodeReadName((Ntk_Node_t *) data);
+    vertex = Part_PartitionFindVertexByName(rootsToLeaves1, name);
+    assert(vertex != NIL(vertex_t));
+    array_insert_last(vertex_t *, roots1, vertex);
+  }
+  leaves1 = st_init_table(st_ptrcmp, st_ptrhash);
+  lsForEachItem(leavesList1, listGen, data) {
+    name = Ntk_NodeReadName((Ntk_Node_t *) data);
+    vertex = Part_PartitionFindVertexByName(rootsToLeaves1, name);
+/*    assert(vertex != NIL(vertex_t)); */
+    if(vertex != NIL(vertex_t)) {
+      /*
+       * If a leaf is not actually in the support of the roots then
+       * it will not be present in the partition.
+       */
+      mddId = Part_VertexReadMddId(vertex);
+      st_insert(leaves1, (char *) vertex, (char *) (long) mddId);
+    }
+  }
+
+  lsDestroy(rootsList1, (void (*) (lsGeneric)) 0);
+  lsDestroy(leavesList1, (void (*) (lsGeneric)) 0);
+  rootsToLeaves2 = Part_NetworkCreatePartition(network2, NIL(Hrc_Node_t),
+					       "dummy", rootsList2,
+					       leavesList2, NIL(mdd_t),
+					       method2, dummy, FALSE,
+					       FALSE, TRUE);
+
+  /*
+   * Generate arrays of root and leaf vertices in the second partition
+   * to pass as arguments to Part_PartitionCollapse().
+   */
+  roots2 = array_alloc(vertex_t *, 0);
+  lsForEachItem(rootsList2, listGen, data) {
+    name = Ntk_NodeReadName((Ntk_Node_t *) data);
+    vertex = Part_PartitionFindVertexByName(rootsToLeaves2, name);
+    assert(vertex != NIL(vertex_t));
+    array_insert_last(vertex_t *, roots2, vertex);
+  }
+  leaves2 = st_init_table(st_ptrcmp, st_ptrhash);
+  lsForEachItem(leavesList2, listGen, data) {
+    name = Ntk_NodeReadName((Ntk_Node_t *) data);
+    vertex = Part_PartitionFindVertexByName(rootsToLeaves2, name);
+/*    assert(vertex != NIL(vertex_t)); */
+    if(vertex != NIL(vertex_t)) {
+      /*
+       * If a leaf is not actually in the support of the roots then
+       * it will not be present in the partition.
+       */
+      mddId = Part_VertexReadMddId(vertex);
+      st_insert(leaves2, (char *) vertex, (char *) (long) mddId);
+    }
+  }
+  lsDestroy(rootsList2, (void (*) (lsGeneric)) 0);
+  lsDestroy(leavesList2, (void (*) (lsGeneric)) 0);
+  assert(Part_PartitionReadMddManager(rootsToLeaves1) ==
+	 Part_PartitionReadMddManager(rootsToLeaves2));
+
+  mvfRoots1 = Part_PartitionCollapse(rootsToLeaves1, roots1, leaves1, NIL(mdd_t));
+  mvfRoots2 = Part_PartitionCollapse(rootsToLeaves2, roots2, leaves2, NIL(mdd_t));
+
+  assert(array_n(mvfRoots1) == array_n(mvfRoots2));
+  num = array_n(mvfRoots1);
+  mddIdArray = array_alloc(int, 0);
+  st_foreach_item_int(leaves1, gen, &vertex, &mddId) {
+    array_insert_last(int, mddIdArray, mddId);
+  }
+
+  /*
+   * For each pair of corresponding outputs in the two arrays mvfRoots1 and
+   * mvfRoots2, I will compute the mdd representing all the input combinations
+   * for which they are different. For each pair, I will print one input
+   * combination for which they are different.
+   */
+
+  for(i = 0; i<num; ++i) {
+    func1 = array_fetch(Mvf_Function_t *, mvfRoots1, i);
+    func2 = array_fetch(Mvf_Function_t *, mvfRoots2, i);
+    if(!Mvf_FunctionTestIsEqualToFunction(func1, func2)) {
+      mgr = Mvf_FunctionReadMddManager(func1);
+      assert(mgr == Mvf_FunctionReadMddManager(func2));
+      numComponents = Mvf_FunctionReadNumComponents(func1);
+      for(j=0; j<numComponents; ++j) {
+	comp1 = Mvf_FunctionReadComponent(func1, j);
+	comp2 = Mvf_FunctionReadComponent(func2, j);
+	diff = mdd_xor(comp1, comp2);
+	if(!mdd_is_tautology(diff, 0)) {
+	  aMinterm = Mc_ComputeAMinterm(diff, mddIdArray, mddMgr);
+	  mintermName = Mc_MintermToString(aMinterm, mddIdArray, network1);
+	  vertex = array_fetch(vertex_t *, roots1, i);
+	  name1 = Part_VertexReadName(vertex);
+	  vertex = array_fetch(vertex_t *, roots2, i);
+	  name2 = Part_VertexReadName(vertex);
+	  (void) fprintf(vis_stdout, "%s from network1 and %s from network2 differ on input values\n%s",
+			 name1, name2, mintermName);
+	  FREE(mintermName);
+	  mdd_free(aMinterm);
+	  mdd_free(diff);
+	  break;
+	}
+	mdd_free(diff);
+      }
+      equivalent = FALSE;
+    }
+  }
+  array_free(mddIdArray);
+  if(!partValid) {
+    Part_PartitionFree(rootsToLeaves1);
+  }
+  Part_PartitionFree(rootsToLeaves2);
+  array_free(roots1);
+  array_free(roots2);
+  st_free_table(leaves1);
+  st_free_table(leaves2);
+  arrayForEachItem(Mvf_Function_t *, mvfRoots1, i, func1) {
+    Mvf_FunctionFree(func1);
+  }
+  array_free(mvfRoots1);
+  arrayForEachItem(Mvf_Function_t *, mvfRoots2, i, func2) {
+    Mvf_FunctionFree(func2);
+  }
+  array_free(mvfRoots2);
+  Ntk_NetworkSetMddManager(network2, NIL(mdd_manager));
+  /*
+   * This is needed because Ntk_NetworkFree() will be called on both network1
+   * and network2.
+   */
+  return equivalent;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [This function does sequential verification between network1 and
+  network2.]
+
+  Description [It accepts as input the two networks, and two hash tables of
+  node names - rootsTable and leavesTable. leavesTable gives the names of
+  corresponding primary inputs in the two networks. If leavesTable is NULL,
+  the inputs are simply matched by names. rootsTable gives the names of
+  corresponding nodes in the two networks whose sequential equivalence has to
+  be verified. If rootsTable is NULL, it is assumed that all the
+  primary outputs need to be verified and that they are to be associated by
+  names. The function returns TRUE if the all the corresponding nodes are
+  sequentially equivalent otherwise it returns FALSE. The verification is done
+  by appending network1 to network2, thereby forming the product machine. A
+  set of states in which the corresponding outputs to be verified are
+  different for some input is calculated and it is checked whether any of
+  these states is reachable from an initial state of the product machine.]
+
+  SideEffects [network2 is modified in this function.]
+
+******************************************************************************/
+boolean
+Eqv_NetworkVerifySequentialEquivalence(
+  Ntk_Network_t *network1,
+  Ntk_Network_t *network2,
+  st_table *rootsTable,    /* the mapping between the outputs of the networks;
+			    * hash table from char * to char * */
+  st_table *leavesTable,   /* the mapping between the inputs of the networks;
+			    * hash table from char * to char * */
+  Part_PartitionMethod partMethod,
+  boolean useBackwardReach,
+  boolean reordering)
+{
+  array_t *roots;
+  st_table *leaves;
+  lsList rootsList;
+  lsList rootsPartList = (lsList) 0;
+  st_table *outputMap = NIL(st_table);
+  Ntk_Node_t *node1, *node2, *node;
+  char *name1, *name2, *temp;
+  st_generator *gen;
+  lsGen listGen;
+  graph_t *partition;
+  vertex_t *vertex;
+  mdd_manager *mddMgr;
+  array_t *mvfArray;
+  Mvf_Function_t *mvf1, *mvf2;
+  mdd_t *badStates, *initialStates;
+  mdd_t *mddTemp, *mdd1, *mdd2, *tautology;
+  mdd_t *mddComp1, *mddComp2;
+  int n, i, j, numComponents;
+  int id;
+  array_t *inputIdArray;
+  lsList dummy = (lsList) 0;
+  lsGeneric data;
+  Ntk_Node_t *input;
+  Fsm_Fsm_t *modelFsm;
+  array_t *onionRings;
+  array_t *aPath;
+  boolean inequivalent;
+  boolean rootsFlag = (rootsTable == NIL(st_table)) ? FALSE : TRUE;
+  array_t *careStatesArray = array_alloc(mdd_t *, 0);
+
+  /* If rootsFlag is FALSE, all primary outputs are to be verified */
+  if(rootsFlag == FALSE) {
+    outputMap = MapPrimaryOutputsByName(network1, network2);
+  }
+
+  /*
+   * If leavesFlag is FALSE, the primary inputs in the two networks are
+   * assumed to have same names. In the network returned by
+   * Ntk_NetworkAppendNetwork(), the two corresponding nodes will be merged.
+   * If leavesFlag is TRUE, the name correspondence between the primary inputs
+   * in the two networks is specified in leavesTable.
+   */
+  if(leavesTable == NIL(st_table)) {
+    st_table *emptyTable = st_init_table(strcmp, st_strhash);
+    Ntk_NetworkAppendNetwork(network2, network1, emptyTable);
+    st_free_table(emptyTable);
+  }
+  else {
+    Ntk_NetworkAppendNetwork(network2, network1, leavesTable);
+  }
+
+  /*
+   * network1 has been appended to the erstwhile network2, and the new network
+   * is now called network2.
+   */
+
+  mddMgr = Ntk_NetworkInitializeMddManager(network2);
+
+  Ord_NetworkOrderVariables(network2, Ord_RootsByDefault_c,
+			    Ord_NodesByDefault_c, FALSE, Ord_InputAndLatch_c,
+			    Ord_Unassigned_c, dummy, FALSE);
+
+  if (reordering)
+    Ntk_NetworkSetDynamicVarOrderingMethod(network2, BDD_REORDER_SIFT,
+					   BDD_REORDER_VERBOSITY);
+  /*
+   * Ntk_NetworkAppendNetwork() adds $NTK2 to the names of all the
+   * appended nodes. I want to find the appended nodes in new network2
+   * corresponding to the roots in network1. I will add all these nodes to
+   * rootsList. I will also add all the roots of the erstwhile network2, which
+   * exist in the network2 also. rootsList will finally contain all the nodes
+   * in network2 whose mdds have to be created by Part_Partition Collapse().
+   */
+
+  rootsList = lsCreate();
+  if(rootsFlag == FALSE) {
+    st_foreach_item(outputMap, gen, &node1, &node2) {
+      name1 = Ntk_NodeReadName(node1);
+      temp = util_strcat3(name1, "$NTK2", "");
+      name1 = temp;
+      node1 = Ntk_NetworkFindNodeByName(network2, name1);
+      assert(node1 != NIL(Ntk_Node_t));
+      FREE(name1);
+      lsNewEnd(rootsList, (lsGeneric) node1, LS_NH);
+      lsNewEnd(rootsList, (lsGeneric) node2, LS_NH);
+    }
+  }
+  else {
+    st_foreach_item(rootsTable, gen, &name1, &name2) {
+      /* I am finding the node in the new network2 */
+      temp = util_strcat3(name1, "$NTK2", "");
+      name1 = temp;
+      node1 = Ntk_NetworkFindNodeByName(network2, name1);
+      FREE(name1);
+      lsNewEnd(rootsList, (lsGeneric) node1, LS_NH);
+      node2 = Ntk_NetworkFindNodeByName(network2, name2);
+      lsNewEnd(rootsList, (lsGeneric) node2, LS_NH);
+    }
+  }
+  if(outputMap) {
+    st_free_table(outputMap);
+  }
+  /* rootsPartList is the list of nodes which will passed to
+   * Part_NetworkCreatePartition(). I want all the next state functions i.e.
+   * latch data inputs as well as everything in rootsList to be in
+   * rootsPartList. If rootsFlag is FALSE, rootsPartList is simply passed as
+   * (lsList) 0.
+   */
+  if(rootsFlag) {
+    rootsPartList = lsCreate();
+    Ntk_NetworkForEachCombOutput(network2, listGen, node) {
+      if(Ntk_NodeTestIsLatchDataInput(node) ||
+	 Ntk_NodeTestIsLatchInitialInput(node)){
+	lsNewEnd(rootsPartList, (lsGeneric) node, LS_NH);
+      }
+    }
+    lsForEachItem(rootsList, listGen, node) {
+      if(!Ntk_NodeTestIsLatchDataInput(node) &&
+	 !Ntk_NodeTestIsLatchInitialInput(node)) {
+	lsNewEnd(rootsPartList, (lsGeneric) node, LS_NH);
+      }
+    }
+  }
+  partition = Part_NetworkCreatePartition(network2, NIL(Hrc_Node_t), "dummy",
+					  rootsPartList,
+					  (lsList) 0, NIL(mdd_t), partMethod,
+					  dummy, FALSE, FALSE, TRUE);
+
+  Ntk_NetworkAddApplInfo(network2, PART_NETWORK_APPL_KEY,
+			 (Ntk_ApplInfoFreeFn) Part_PartitionFreeCallback,
+			 (void *) partition);
+  if(rootsPartList) {
+    lsDestroy(rootsPartList, (void (*) (lsGeneric)) 0);
+  }
+  /* Create roots and leaves for Part_PartitionCollapse().
+   */
+  roots = array_alloc(vertex_t *, 0);
+  lsForEachItem(rootsList, listGen, data) {
+    name1 = Ntk_NodeReadName((Ntk_Node_t *) data);
+    vertex = Part_PartitionFindVertexByName(partition, name1);
+    assert(vertex != NIL(vertex_t));
+    array_insert_last(vertex_t *, roots, vertex);
+  }
+  lsDestroy(rootsList, (void (*) (lsGeneric)) 0);
+  leaves = st_init_table(st_ptrcmp, st_ptrhash);
+  Ntk_NetworkForEachCombInput(network2, listGen, node1) {
+    name1 = Ntk_NodeReadName(node1);
+    vertex = Part_PartitionFindVertexByName(partition, name1);
+    if(vertex != NIL(vertex_t)) {
+      /* A combinational input might not be present in the support of any
+	 node in rootsPartList. If so, it will not be present in the partition
+	 also. */
+      st_insert(leaves, (char *) vertex, (char *) (long) 0);
+    }
+  }
+  mvfArray = Part_PartitionCollapse(partition, roots, leaves, NIL(mdd_t));
+  array_free(roots);
+  st_free_table(leaves);
+  n = array_n(mvfArray);
+  assert(n%2 == 0);
+  n = n/2;
+  assert(mddMgr != NULL);
+
+/* In mvfArray, the mvfs of corresponding nodes occur one after the other,
+   * because of the way rootsList was created. badStates will ultimately
+   * contain all the states for which  any pair of corresponding nodes differ
+   * for some input.
+   */
+  badStates = mdd_zero(mddMgr);
+  for(i=0; i<n; i++) {
+    mvf1 = array_fetch(Mvf_Function_t *, mvfArray, 2*i);
+    mvf2 = array_fetch(Mvf_Function_t *, mvfArray, 2*i +1);
+    numComponents = Mvf_FunctionReadNumComponents(mvf1);
+    mdd2 = mdd_zero(mddMgr);
+    /*
+     * Hopefully, mddMgr of the partition is the same as the mddMgr of the
+     * MVFs.
+     */
+    for(j=0; j<numComponents; j++) {
+      mddComp1 = Mvf_FunctionObtainComponent(mvf1, j);
+      mddComp2 = Mvf_FunctionObtainComponent(mvf2, j);
+      mdd1 = mdd_and(mddComp1, mddComp2, 1, 1);
+      mdd_free(mddComp1);
+      mdd_free(mddComp2);
+      mddTemp = mdd_or(mdd2, mdd1, 1, 1);
+      mdd_free(mdd1);
+      mdd_free(mdd2);
+      mdd2 = mddTemp;
+    }
+
+   /*
+    * At this point, mdd2 represents the set of input and present state
+    * combinations in which mvf1 and mvf2 produce the same value. I want the
+    * set for which mvf1 and mvf2 are different.
+    */
+    mddTemp = mdd_or(badStates, mdd2, 1, 0);
+    mdd_free(mdd2);
+    mdd_free(badStates);
+    badStates = mddTemp;
+  }
+  arrayForEachItem(Mvf_Function_t *, mvfArray, i, mvf1) {
+    Mvf_FunctionFree(mvf1);
+  }
+  array_free(mvfArray);
+  /* existentially quantify out the input variables */
+  inputIdArray = array_alloc(int, 0);
+
+  Ntk_NetworkForEachPrimaryInput(network2, listGen, input) {
+    id = Ntk_NodeReadMddId(input);
+    assert(id >= 0);
+    array_insert_last(int, inputIdArray, id);
+  }
+
+  mddTemp = mdd_smooth(mddMgr, badStates, inputIdArray);
+  mdd_free(badStates);
+  badStates = mddTemp;
+  array_free(inputIdArray);
+  modelFsm = Fsm_FsmCreateFromNetworkWithPartition(network2, NIL(graph_t));
+  assert(modelFsm != NIL(Fsm_Fsm_t));
+  Ntk_NetworkAddApplInfo(network2, FSM_NETWORK_APPL_KEY,
+			 (Ntk_ApplInfoFreeFn) Fsm_FsmFreeCallback,
+			 (void *) modelFsm);
+
+  onionRings = array_alloc(mdd_t *, 0);
+  initialStates = Fsm_FsmComputeInitialStates(modelFsm);
+  tautology = mdd_one(mddMgr);
+
+  /* Model checking function */
+  if (useBackwardReach == TRUE) {
+    array_insert(mdd_t *, careStatesArray, 0, tautology);
+    inequivalent = Mc_FsmComputeStatesReachingToSet(modelFsm, badStates,
+			careStatesArray, initialStates,
+			onionRings, McVerbosityNone_c, McDcLevelNone_c);
+    array_free(careStatesArray);
+    mdd_free(badStates);
+    mdd_free(tautology);
+
+    if (inequivalent) {
+      mdd_t *outerOnionRing = array_fetch_last(mdd_t *, onionRings);
+      mdd_t *badInitialStates = mdd_and(initialStates, outerOnionRing, 1, 1);
+      array_t *psVarMddIdArray = Fsm_FsmReadPresentStateVars(modelFsm);
+      mdd_t *aBadInitialState = Mc_ComputeAMinterm(initialStates, psVarMddIdArray, mddMgr);
+      mdd_free(badInitialStates);
+      aPath = Mc_BuildPathToCore(aBadInitialState, onionRings, modelFsm,
+				 McGreaterOrEqualZero_c);
+      (void) Mc_PrintPath(aPath, modelFsm, TRUE); /* TRUE -> print inputs on path */
+      mdd_free(aBadInitialState);
+      mdd_free(initialStates);
+      mdd_array_free(aPath);
+      mdd_array_free(onionRings);
+      return FALSE;
+    }
+    else {
+      mdd_free(initialStates);
+      return TRUE;
+    }
+  }
+  else { /* do forward search */
+    array_insert(mdd_t *, careStatesArray, 0, tautology);
+    inequivalent = Mc_FsmComputeStatesReachableFromSet(modelFsm, initialStates,
+			careStatesArray, badStates, onionRings,
+			McVerbosityNone_c, McDcLevelNone_c);
+    array_free(careStatesArray);
+    mdd_free(tautology);
+    mdd_free(initialStates);
+
+    if (inequivalent) {
+      mdd_t *outerOnionRing = array_fetch_last(mdd_t *, onionRings);
+      mdd_t *reachableBadStates = mdd_and(badStates, outerOnionRing, 1, 1);
+      array_t *psVarMddIdArray = Fsm_FsmReadPresentStateVars(modelFsm);
+      mdd_t *aBadReachableState = Mc_ComputeAMinterm(reachableBadStates, psVarMddIdArray, mddMgr);
+      mdd_free(reachableBadStates);
+      psVarMddIdArray = Fsm_FsmReadPresentStateVars(modelFsm);
+      aPath = Mc_BuildPathFromCore(aBadReachableState, onionRings, modelFsm,
+				 McGreaterOrEqualZero_c);
+      (void) Mc_PrintPath(aPath, modelFsm, TRUE); /* TRUE -> print inputs on path */
+      mdd_free(aBadReachableState);
+      mdd_free(badStates);
+      mdd_array_free(aPath);
+      mdd_array_free(onionRings);
+      return FALSE;
+    }
+    else {
+      mdd_free(badStates);
+      return TRUE;
+    }
+  }
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
Index: vis_dev/vis-2.3/src/fsm/fsm.h
===================================================================
--- vis_dev/vis-2.3/src/fsm/fsm.h	(revision 14)
+++ vis_dev/vis-2.3/src/fsm/fsm.h	(revision 14)
@@ -0,0 +1,336 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [fsm.h]
+
+  PackageName [fsm]
+
+  Synopsis    [Finite state machine abstraction of a network.]
+
+  Description [A finite state machine contains a pointer to a network, so it
+  inherits all the information that is contained in the network, such as node
+  names and MDD ids.  An FSM has a partition associated with it; the output
+  and next state functions are derived from the partition.  This partition
+  does not necessarily have to be the default partition associated with the
+  network.<p>
+
+  The FSM maintains information relating to state reachability
+  (initial states, reachable states, underapprox or not, and the
+  partition of reachable states into "onion rings"), and fairness
+  information (fair states, fairness constraints, and generic
+  debugging information).  Also, the FSM stores the MDD ids of present
+  state, next state, and input variables, in a convenient format.]
+
+  Author [Shaker Sarwary, Tom Shiple, Rajeev Ranjan, Kavita Ravi, In-Ho Moon]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: fsm.h,v 1.76 2005/05/13 08:30:30 hhhan Exp $]
+
+******************************************************************************/
+
+#ifndef _FSM
+#define _FSM
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "img.h"
+#include "ctlp.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+#define FSM_NETWORK_APPL_KEY "Fsm_NetworkApplKey"
+#define Fsm_Rch_Default_c Fsm_Rch_Bfs_c
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef struct FsmFsmStruct Fsm_Fsm_t;
+typedef struct FsmFairnessStruct Fsm_Fairness_t;
+typedef struct FsmArdcOptionsStruct Fsm_ArdcOptions_t;
+typedef struct FsmHdTravOptions FsmHdTravOptions_t;
+typedef array_t Fsm_HintsArray_t;
+
+/**Function********************************************************************
+
+  Synopsis [Specifies type of reachability computation.]
+
+  Description [Specifies type of reachability
+  computation. Fsm_Rch_Bfs_c specifies normal BFS. Fsm_Rch_Hd_c
+  specifies HD computation (Ravi & Somenzi ICCAD95). Fsm_Rch_Oa_c
+  specified Approximate reachability analysis first published by Cho
+  in EDAC'93. Fsm_Rch_PureSat_c is first published by Bing Li in BMC'03 ]
+
+  SideEffects []
+
+  SeeAlso []
+  
+******************************************************************************/
+typedef enum {
+    Fsm_Rch_Bfs_c,
+    Fsm_Rch_Gs_c,
+    Fsm_Rch_Hd_c,
+    Fsm_Rch_Oa_c,
+    Fsm_Rch_Grab_c,
+    Fsm_Rch_PureSat_c
+} Fsm_RchType_t;
+
+/**Function********************************************************************
+
+  Synopsis [Specifies the status of reachable states.]
+
+  Description [Specifies the status of reachable states.]
+
+  SideEffects []
+
+  SeeAlso []
+  
+******************************************************************************/
+typedef enum {
+    Fsm_Rch_Exact_c,
+    Fsm_Rch_Under_c,
+    Fsm_Rch_Over_c
+} Fsm_RchStatus_t;
+
+/**Function********************************************************************
+
+  Synopsis [Specifies type of dead-end computation.]
+
+  Description [Specifies type of dead-end computation. Fsm_Hd_DE_BF_c
+  implies computation of the entire Reached set. Fsm_Hd_DE_Con_c
+  specifies dead-end computation by decomposing Reached in terms of
+  disjunctive factors.  Fsm_Hd_DE_Hyb_c first tries to extract a
+  subset of Reached to compute its image. If no new states are found,
+  it computes the image of Reached by decomposing it into disjunctive
+  parts.]
+
+
+  SideEffects []
+
+  SeeAlso []
+  
+******************************************************************************/
+typedef enum {
+  Fsm_Hd_DE_BF_c,
+  Fsm_Hd_DE_Con_c,
+  Fsm_Hd_DE_Hyb_c
+} Fsm_HdDeadEndType_t;
+
+/**Enum************************************************************************
+
+  Synopsis [Specifies type of approximate FSM traversal.]
+
+  Description [Specifies type of approximate FSM traversal.]
+
+  SideEffects []
+
+  SeeAlso []
+  
+******************************************************************************/
+typedef enum {
+  Fsm_Ardc_Traversal_Mbm_c,
+  Fsm_Ardc_Traversal_Rfbf_c,
+  Fsm_Ardc_Traversal_Tfbf_c,
+  Fsm_Ardc_Traversal_Tmbm_c,
+  Fsm_Ardc_Traversal_Lmbm_c,
+  Fsm_Ardc_Traversal_Tlmbm_c,
+  Fsm_Ardc_Traversal_Simple_c
+} Fsm_Ardc_TraversalType_t;
+
+/**Enum************************************************************************
+
+  Synopsis [Specifies type of what-to-constrain.]
+
+  Description [Specifies type of what-to-constrain.]
+
+  SideEffects []
+
+  SeeAlso []
+  
+******************************************************************************/
+typedef enum {
+  Fsm_Ardc_Constrain_Tr_c, /* Tr : transition relation */
+  Fsm_Ardc_Constrain_Initial_c,
+  Fsm_Ardc_Constrain_Both_c
+} Fsm_Ardc_ConstrainTargetType_t;
+
+/**Enum************************************************************************
+
+  Synopsis [Specifies type of when to abstract pseudo PIs.]
+
+  Description [Specifies type of when to abstract pseudo PIs.]
+
+  SideEffects []
+
+  SeeAlso []
+  
+******************************************************************************/
+typedef enum {
+  Fsm_Ardc_Abst_Ppi_No_c,
+  Fsm_Ardc_Abst_Ppi_Before_Image_c,
+  Fsm_Ardc_Abst_Ppi_After_Image_c,
+  Fsm_Ardc_Abst_Ppi_At_End_c
+} Fsm_Ardc_AbstPpiType_t;
+
+#include "mc.h"
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void Fsm_ArdcMinimizeTransitionRelation(Fsm_Fsm_t *fsm, Img_DirectionType fwdbwd);
+EXTERN mdd_t * Fsm_ArdcComputeImage(Fsm_Fsm_t *fsm, mdd_t *fromLowerBound, mdd_t *fromUpperBound, array_t *toCareSetArray);
+EXTERN array_t * Fsm_FsmComputeOverApproximateReachableStates(Fsm_Fsm_t *fsm, int incrementalFlag, int verbosityLevel, int printStep, int depthValue, int shellFlag, int reorderFlag, int reorderThreshold, int recompute);
+EXTERN array_t * Fsm_ArdcComputeOverApproximateReachableStates(Fsm_Fsm_t *fsm, int incrementalFlag, int verbosityLevel, int printStep, int depthValue, int shellFlag, int reorderFlag, int reorderThreshold, int recompute, Fsm_ArdcOptions_t *options);
+EXTERN array_t * Fsm_ArdcDecomposeStateSpace(Ntk_Network_t *network, array_t *presentStateVars, array_t *nextStateFunctions, Fsm_ArdcOptions_t *options);
+EXTERN Fsm_ArdcOptions_t * Fsm_ArdcAllocOptionsStruct(void);
+EXTERN void Fsm_ArdcGetDefaultOptions(Fsm_ArdcOptions_t *options);
+EXTERN Fsm_Ardc_TraversalType_t Fsm_ArdcOptionsReadTraversalMethod(Fsm_ArdcOptions_t *options);
+EXTERN int Fsm_ArdcOptionsReadGroupSize(Fsm_ArdcOptions_t *options);
+EXTERN float Fsm_ArdcOptionsReadAffinityFactor(Fsm_ArdcOptions_t *options);
+EXTERN Img_MinimizeType Fsm_ArdcOptionsReadConstrainMethod(Fsm_ArdcOptions_t *options);
+EXTERN Fsm_Ardc_ConstrainTargetType_t Fsm_ArdcOptionsReadConstrainTarget(Fsm_ArdcOptions_t *options);
+EXTERN int Fsm_ArdcOptionsReadMaxIteration(Fsm_ArdcOptions_t *options);
+EXTERN Fsm_Ardc_AbstPpiType_t Fsm_ArdcOptionsReadAbstractPseudoInput(Fsm_ArdcOptions_t *options);
+EXTERN boolean Fsm_ArdcOptionsReadDecomposeFlag(Fsm_ArdcOptions_t *options);
+EXTERN boolean Fsm_ArdcOptionsReadProjectedInitialFlag(Fsm_ArdcOptions_t *options);
+EXTERN boolean Fsm_ArdcOptionsReadConstrainReorderFlag(Fsm_ArdcOptions_t *options);
+EXTERN Img_MethodType Fsm_ArdcOptionsReadImageMethod(Fsm_ArdcOptions_t *options);
+EXTERN boolean Fsm_ArdcOptionsReadUseHighDensity(Fsm_ArdcOptions_t *options);
+EXTERN int Fsm_ArdcOptionsReadVerbosity(Fsm_ArdcOptions_t *options);
+EXTERN void Fsm_ArdcOptionsSetTraversalMethod(Fsm_ArdcOptions_t *options, Fsm_Ardc_TraversalType_t traversalMethod);
+EXTERN void Fsm_ArdcOptionsSetGroupSize(Fsm_ArdcOptions_t *options, int groupSize);
+EXTERN void Fsm_ArdcOptionsSetAffinityFactor(Fsm_ArdcOptions_t *options, float affinityFactor);
+EXTERN void Fsm_ArdcOptionsSetConstrainMethod(Fsm_ArdcOptions_t *options, Img_MinimizeType constrainMethod);
+EXTERN void Fsm_ArdcOptionsSetConstrainTarget(Fsm_ArdcOptions_t *options, Fsm_Ardc_ConstrainTargetType_t constrainTarget);
+EXTERN void Fsm_ArdcOptionsSetMaxIteration(Fsm_ArdcOptions_t *options, int maxIteration);
+EXTERN void Fsm_ArdcOptionsSetAbstractPseudoInput(Fsm_ArdcOptions_t *options, Fsm_Ardc_AbstPpiType_t abstractPseudoInput);
+EXTERN void Fsm_ArdcOptionsSetDecomposeFlag(Fsm_ArdcOptions_t *options, boolean decomposeFlag);
+EXTERN void Fsm_ArdcOptionsSetProjectedInitialFlag(Fsm_ArdcOptions_t *options, boolean projectedInitialFlag);
+EXTERN void Fsm_ArdcOptionsSetConstrainReorderFlag(Fsm_ArdcOptions_t *options, int constrainReorderFlag);
+EXTERN void Fsm_ArdcOptionsSetImageMethod(Fsm_ArdcOptions_t *options, Img_MethodType ardcImageMethod);
+EXTERN void Fsm_ArdcOptionsSetUseHighDensity(Fsm_ArdcOptions_t *options, boolean useHighDensity);
+EXTERN void Fsm_ArdcOptionsSetVerbosity(Fsm_ArdcOptions_t *options, int verbosity);
+EXTERN double Fsm_ArdcCountOnsetOfOverApproximateReachableStates(Fsm_Fsm_t *fsm);
+EXTERN int Fsm_ArdcBddSizeOfOverApproximateReachableStates(Fsm_Fsm_t *fsm);
+EXTERN mdd_t * Fsm_ArdcGetMddOfOverApproximateReachableStates(Fsm_Fsm_t *fsm);
+EXTERN void Fsm_ArdcPrintReachabilityResults(Fsm_Fsm_t *fsm, long elapseTime);
+EXTERN int Fsm_ArdcReadVerbosity(void);
+EXTERN void Fsm_Init(void);
+EXTERN void Fsm_End(void);
+EXTERN Fsm_Fairness_t * Fsm_FsmReadFairnessConstraint(Fsm_Fsm_t *fsm);
+EXTERN mdd_t * Fsm_FsmComputeFairStates(Fsm_Fsm_t *fsm, array_t *careSetArray, int verbosity, int dcLevel, Mc_GSHScheduleType schedule, Mc_FwdBwdAnalysis direction, boolean useEarlyTermination);
+EXTERN Ctlp_Formula_t * Fsm_FairnessReadFinallyInfFormula(Fsm_Fairness_t *fairness, int i, int j);
+EXTERN Ctlp_Formula_t * Fsm_FairnessReadGloballyInfFormula(Fsm_Fairness_t *fairness, int i, int j);
+EXTERN mdd_t * Fsm_FairnessObtainFinallyInfMdd(Fsm_Fairness_t *fairness, int i, int j, array_t *careSetArray, Mc_DcLevel dcLevel);
+EXTERN mdd_t * Fsm_FairnessObtainGloballyInfMdd(Fsm_Fairness_t *fairness, int i, int j, array_t *careSetArray, Mc_DcLevel dcLevel);
+EXTERN boolean Fsm_FairnessTestIsStreett(Fsm_Fairness_t *fairness);
+EXTERN boolean Fsm_FairnessTestIsBuchi(Fsm_Fairness_t *fairness);
+EXTERN int Fsm_FairnessReadNumDisjuncts(Fsm_Fairness_t *fairness);
+EXTERN int Fsm_FairnessReadNumConjunctsOfDisjunct(Fsm_Fairness_t *fairness, int i);
+EXTERN array_t * Fsm_FsmReadDebugArray(Fsm_Fsm_t *fsm);
+EXTERN Fsm_Fsm_t * Fsm_FsmCreateFromNetworkWithPartition(Ntk_Network_t *network, graph_t *partition);
+EXTERN Fsm_Fsm_t * Fsm_FsmCreateReducedFsm(Ntk_Network_t *network, graph_t *partition, array_t *latches, array_t *inputs, array_t *fairArray);
+EXTERN Fsm_Fsm_t * Fsm_FsmCreateAbstractFsm(Ntk_Network_t *network, graph_t *partition, array_t *latches, array_t *invisibleLatches, array_t *inputs, array_t *fairArray, boolean independentFlag);
+EXTERN void Fsm_FsmFree(Fsm_Fsm_t * fsm);
+EXTERN void Fsm_FsmSubsystemFree(Fsm_Fsm_t * fsm);
+EXTERN void Fsm_FsmFreeCallback(void * data);
+EXTERN Ntk_Network_t * Fsm_FsmReadNetwork(Fsm_Fsm_t * fsm);
+EXTERN mdd_manager * Fsm_FsmReadMddManager(Fsm_Fsm_t * fsm);
+EXTERN Fsm_Fsm_t * Fsm_NetworkReadOrCreateFsm(Ntk_Network_t * network);
+EXTERN Fsm_Fsm_t * Fsm_NetworkReadFsm(Ntk_Network_t * network);
+EXTERN Img_ImageInfo_t * Fsm_FsmReadImageInfo(Fsm_Fsm_t *fsm);
+EXTERN void Fsm_FsmFreeImageInfo(Fsm_Fsm_t *fsm);
+EXTERN graph_t * Fsm_FsmReadPartition(Fsm_Fsm_t *fsm);
+EXTERN boolean Fsm_FsmTestIsReachabilityDone(Fsm_Fsm_t *fsm);
+EXTERN boolean Fsm_FsmTestIsOverApproximateReachabilityDone(Fsm_Fsm_t *fsm);
+EXTERN mdd_t * Fsm_FsmReadReachableStates(Fsm_Fsm_t *fsm);
+EXTERN mdd_t * Fsm_FsmReadCurrentReachableStates(Fsm_Fsm_t *fsm);
+EXTERN array_t * Fsm_FsmReadOverApproximateReachableStates(Fsm_Fsm_t *fsm);
+EXTERN array_t * Fsm_FsmReadCurrentOverApproximateReachableStates(Fsm_Fsm_t *fsm);
+EXTERN array_t * Fsm_FsmReadReachabilityOnionRings(Fsm_Fsm_t *fsm);
+EXTERN boolean Fsm_FsmReachabilityOnionRingsStates(Fsm_Fsm_t *fsm, mdd_t ** result);
+EXTERN boolean Fsm_FsmTestReachabilityOnionRingsUpToDate(Fsm_Fsm_t *fsm);
+EXTERN Fsm_RchType_t Fsm_FsmReadReachabilityOnionRingsMode(Fsm_Fsm_t *fsm);
+EXTERN Img_ImageInfo_t * Fsm_FsmReadOrCreateImageInfo(Fsm_Fsm_t *fsm, int bwdImgFlag, int fwdImgFlag);
+EXTERN Img_ImageInfo_t * Fsm_FsmReadOrCreateImageInfoFAFW(Fsm_Fsm_t *fsm, int bwdImgFlag, int fwdImgFlag);
+EXTERN Img_ImageInfo_t * Fsm_FsmReadOrCreateImageInfoForComputingRange(Fsm_Fsm_t *fsm, int bwdImgFlag, int fwdImgFlag);
+EXTERN mdd_t * Fsm_FsmComputeInitialStates(Fsm_Fsm_t *fsm);
+EXTERN array_t * Fsm_FsmReadPresentStateVars(Fsm_Fsm_t *fsm);
+EXTERN array_t * Fsm_FsmReadNextStateVars(Fsm_Fsm_t *fsm);
+EXTERN array_t * Fsm_FsmReadNextStateFunctionNames(Fsm_Fsm_t *fsm);
+EXTERN array_t * Fsm_FsmReadInputVars(Fsm_Fsm_t *fsm);
+EXTERN array_t * Fsm_FsmReadPrimaryInputVars(Fsm_Fsm_t *fsm);
+EXTERN array_t * Fsm_FsmReadPseudoInputVars(Fsm_Fsm_t *fsm);
+EXTERN mdd_t * Fsm_FsmReadFairnessStates(Fsm_Fsm_t *fsm);
+EXTERN void Fsm_FsmSetInputVars(Fsm_Fsm_t *fsm, array_t *inputVars);
+EXTERN void Fsm_FsmSetInitialStates(Fsm_Fsm_t *fsm, mdd_t *initStates);
+EXTERN Fsm_Fsm_t * Fsm_HrcManagerReadCurrentFsm(Hrc_Manager_t *hmgr);
+EXTERN Fsm_Fsm_t * Fsm_FsmCreateSubsystemFromNetwork(Ntk_Network_t *network, graph_t *partition, st_table *vertexTable, boolean independentFlag, int createPseudoVarMode);
+EXTERN void Fsm_InstantiateHint(Fsm_Fsm_t *fsm, mdd_t *hint, int fwdFlag, int bwdFlag, Ctlp_Approx_t type, int printStatus);
+EXTERN void Fsm_CleanUpHints(Fsm_Fsm_t *fsm, int fwdFlag, int bwdFlag, int printStatus);
+EXTERN void Fsm_FsmFreeReachableStates(Fsm_Fsm_t *fsm);
+EXTERN void Fsm_FsmFreeOverApproximateReachableStates(Fsm_Fsm_t *fsm);
+EXTERN int Fsm_FsmGetReachableDepth(Fsm_Fsm_t *fsm);
+EXTERN boolean Fsm_FsmCheckSameSubFsmInTotalFsm(Fsm_Fsm_t *fsm, Fsm_Fsm_t *subFsm1, Fsm_Fsm_t *subFsm2);
+EXTERN Fsm_RchStatus_t Fsm_FsmReadReachabilityApproxComputationStatus(Fsm_Fsm_t *fsm);
+EXTERN void Fsm_MinimizeTransitionRelationWithReachabilityInfo(Fsm_Fsm_t *fsm, Img_DirectionType fwdbwd, boolean verbosity);
+EXTERN FsmHdTravOptions_t * Fsm_FsmHdGetTravOptions(int nvars);
+EXTERN void Fsm_FsmHdFreeTravOptions(FsmHdTravOptions_t *options);
+EXTERN int Fsm_FsmHdOptionReadNumVars(FsmHdTravOptions_t *options);
+EXTERN int Fsm_FsmHdOptionReadFrontierApproxThreshold(FsmHdTravOptions_t *options);
+EXTERN boolean Fsm_FsmHdOptionReadOnlyPartialImage(FsmHdTravOptions_t *options);
+EXTERN boolean Fsm_FsmHdOptionReadScrapStates(FsmHdTravOptions_t *options);
+EXTERN double Fsm_FsmHdOptionReadQuality(FsmHdTravOptions_t *options);
+EXTERN bdd_approx_type_t Fsm_FsmHdOptionReadFrontierApproxMethod(FsmHdTravOptions_t *options);
+EXTERN Fsm_HdDeadEndType_t Fsm_FsmHdOptionReadDeadEnd(FsmHdTravOptions_t *options);
+EXTERN boolean Fsm_FsmHdOptionReadNewOnly(FsmHdTravOptions_t *options);
+EXTERN bdd_approx_type_t Fsm_FsmHdOptionReadDeadEndSubsetMethod(FsmHdTravOptions_t *options);
+EXTERN int Fsm_FsmHdOptionSetFrontierApproxThreshold(FsmHdTravOptions_t *options, int threshold);
+EXTERN void Fsm_FsmHdOptionSetOnlyPartialImage(FsmHdTravOptions_t *options, boolean onlyPartial);
+EXTERN void Fsm_FsmHdOptionSetScrapStates(FsmHdTravOptions_t *options, boolean scrapStates);
+EXTERN void Fsm_FsmHdOptionSetQuality(FsmHdTravOptions_t *options, double quality);
+EXTERN void Fsm_FsmHdOptionSetFrontierApproxMethod(FsmHdTravOptions_t *options, bdd_approx_type_t approxMethod);
+EXTERN void Fsm_FsmHdOptionSetDeadEnd(FsmHdTravOptions_t *options, Fsm_HdDeadEndType_t deadEnd);
+EXTERN void Fsm_FsmHdOptionSetNewOnly(FsmHdTravOptions_t *options, boolean newOnly);
+EXTERN void Fsm_FsmHdOptionSetDeadEndSubsetMethod(FsmHdTravOptions_t *options, bdd_approx_type_t approxMethod);
+EXTERN mdd_t * Fsm_FsmComputeReachableStates(Fsm_Fsm_t *fsm, int incrementalFlag, int verbosityLevel, int printStep, int depthValue, int shellFlag, int reorderFlag, int reorderThreshold, Fsm_RchType_t approxFlag, int ardc, int recompute, array_t *invarStates, boolean printWarning, array_t *guideArray);
+EXTERN mdd_t * Fsm_MddMultiwayAndSmooth(mdd_manager *mddManager, array_t *mddArray, array_t *smoothingVars);
+EXTERN void Fsm_FsmReachabilityPrintResults(Fsm_Fsm_t *fsm, long elapseTime, int approxFlag);
+EXTERN void Fsm_FsmFairnessUpdate(Fsm_Fsm_t *fsm, array_t *formulaArray);
+EXTERN mdd_t *Fsm_FsmReadUniQuantifyInputCube(Fsm_Fsm_t *fsm);
+EXTERN mdd_t *Fsm_FsmReadExtQuantifyInputCube(Fsm_Fsm_t *fsm);
+EXTERN Img_ImageInfo_t * Fsm_FsmReadOrCreateImageInfoPrunedFAFW(Fsm_Fsm_t *fsm, mdd_t *Winning, int bwdImgFlag, int fwdImgFlag);
+EXTERN boolean Fsm_FsmReadUseUnquantifiedFlag( Fsm_Fsm_t * fsm);
+EXTERN void Fsm_FsmSetImageInfo( Fsm_Fsm_t *fsm, Img_ImageInfo_t *imageInfo);
+EXTERN void Fsm_FsmSetUseUnquantifiedFlag(Fsm_Fsm_t *fsm, boolean value);
+EXTERN int Fsm_FsmReadFAFWFlag(Fsm_Fsm_t *fsm);
+EXTERN void Fsm_FsmSetFAFWFlag(Fsm_Fsm_t *fsm, boolean FAFWFlag);
+EXTERN void Fsm_FsmSetSystemVariableFAFW(Fsm_Fsm_t *fsm, st_table *bddIdTable);
+EXTERN void Fsm_ImageInfoConjoinWithWinningStrategy( Fsm_Fsm_t *modelFsm, Img_DirectionType directionType, mdd_t *winningStrategy);
+EXTERN void Fsm_ImageInfoRecoverFromWinningStrategy( Fsm_Fsm_t *modelFsm, Img_DirectionType directionType);
+
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _FSM */
Index: vis_dev/vis-2.3/src/fsm/fsm.make
===================================================================
--- vis_dev/vis-2.3/src/fsm/fsm.make	(revision 14)
+++ vis_dev/vis-2.3/src/fsm/fsm.make	(revision 14)
@@ -0,0 +1,4 @@
+CSRC += fsmCmd.c fsmFair.c fsmFsm.c fsmReach.c fsmHD.c fsmArdc.c
+HEADERS += fsm.h fsmInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/fsm/fsmArdc.c
===================================================================
--- vis_dev/vis-2.3/src/fsm/fsmArdc.c	(revision 14)
+++ vis_dev/vis-2.3/src/fsm/fsmArdc.c	(revision 14)
@@ -0,0 +1,4453 @@
+/**CFile***********************************************************************
+
+  FileName    [fsmArdc.c]
+
+  PackageName [fsm]
+
+  Synopsis    [Routines to perform overapproximate reachability on the FSM
+  structure.]
+
+  Description [The basic algorithms are almost same as the one in
+  Hyunwoo Cho's paper in TCAD96, except as noted below. To read the
+  functions in this file, it is strongly recommended to read that
+  paper first and In-Ho Moon's paper in ICCAD98.
+
+  0. Cho's algorithm uses transition function for image computation,
+     whereas we use transition relation.
+  1. constrainTarget
+     In Cho's papers, there are two versions of algorithms: one is constraining
+     transition relation, the other is initial states, so this function
+     includes these two as well as the case of both.
+     0) Fsm_Ardc_Constrain_Tr_c      : constrain transition relation (default).
+     1) Fsm_Ardc_Constrain_Initial_c : constrain initial state.
+     2) Fsm_Ardc_Constrain_Both_c    : constrain both.
+  2. decomposeFlag
+     To do above constraining operation, we can make the constraint
+     either conjoined (as single bdd) or decomposed (as array of bdds) from
+     the reachable states of fanin submachines of the current submachine.
+     To have same interface for these two, array of constraints is used.
+  3. dynamic variable reordering
+     In Cho's algorithm, dynamic variable ordering is not allowed, but
+     it is allowed here. Also, refer to 5. restore-containment.
+  4. abstractPseudoInput
+     To make  convergence faster, we can abstract pseudo primary input
+     variables early, but refer to 5. restore-containment.
+     0) Fsm_Ardc_Abst_Ppi_No_c		 : do not abstract pseudo input
+					   variables.
+     1) Fsm_Ardc_Abst_Ppi_Before_Image_c : abstract before image computation
+					   (default).
+     2) Fsm_Ardc_Abst_Ppi_After_Image_c  : abstract after image computation.
+     3) Fsm_Ardc_Abst_Ppi_At_End_c       : abstract at the end of approximate
+					   traversal.
+  5. restore-constainment
+     Due to 3 (dynamic variable reordering) and 4 (abstractPseudoInput),
+     current reachable states may not be subset of previous reachable
+     states. In this case, we correct current reachable states to the
+     intersection of current and previous reachable states in MBM. However,
+     in FBF, we need to take union of the two.
+  6. projectedInitialFlag
+     When we do reachability analysis of submachines, initial states of
+     a submachine can be one of the followings. In Cho's paper, projected
+     initial states was used.
+     0) FALSE : use original initial states for submachine
+     1) TRUE  : use projected initial states for submachine (default)
+  ]
+
+  Author      [In-Ho Moon]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  COLORADO HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF COLORADO SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF COLORADO HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "fsmInt.h"
+#include "ntm.h"
+
+static char rcsid[] UNUSED = "$Id: fsmArdc.c,v 1.86 2009/04/12 00:44:04 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define ARDC_MAX_LINE_LEN	4096
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void SortSubFsmsForApproximateTraversal(array_t **subFsmArray, array_t **fanInsIndexArray, array_t **fanOutsIndexArray, int verbosityLevel);
+static array_t * ArdcMbmTraversal(Fsm_Fsm_t *fsm, int nvars, array_t *subFsmArray, array_t *fanInsIndexArray, array_t *fanOutsIndexArray, mdd_t ***subReached, int incrementalFlag, int verbosityLevel, int printStep, int depthValue, int shellFlag, int reorderFlag, int reorderThreshold, Fsm_RchType_t approxFlag, Fsm_ArdcOptions_t *options, boolean lfpFlag);
+static array_t * ArdcRfbfTraversal(Fsm_Fsm_t *fsm, int nvars, array_t *subFsmArray, array_t *fanInsIndexArray, int incrementalFlag, int verbosityLevel, int printStep, int depthValue, int shellFlag, int reorderFlag, int reorderThreshold, Fsm_RchType_t approxFlag, Fsm_ArdcOptions_t *options);
+static array_t * ArdcTfbfTraversal(Fsm_Fsm_t *fsm, int nvars, array_t *subFsmArray, array_t *fanInsIndexArray, mdd_t ***subReached, mdd_t ***subTo, int incrementalFlag, int verbosityLevel, int printStep, int depthValue, int shellFlag, int reorderFlag, int reorderThreshold, Fsm_RchType_t approxFlag, Fsm_ArdcOptions_t *options);
+static array_t * ArdcTmbmTraversal(Fsm_Fsm_t *fsm, int nvars, array_t *subFsmArray, array_t *fanInsIndexArray, array_t *fanOutsIndexArray, int incrementalFlag, int verbosityLevel, int printStep, int depthValue, int shellFlag, int reorderFlag, int reorderThreshold, Fsm_RchType_t approxFlag, Fsm_ArdcOptions_t *options, boolean lfpFlag);
+static array_t * ArdcSimpleTraversal(Fsm_Fsm_t *fsm, int nvars, array_t *subFsmArray, int incrementalFlag, int verbosityLevel, int printStep, int depthValue, int shellFlag, int reorderFlag, int reorderThreshold, Fsm_RchType_t approxFlag, Fsm_ArdcOptions_t *options, int setFlag);
+static void ComputeFaninConstrainArray(array_t *faninConstrainArray, mdd_t **constraint, int current, array_t *fans, int decomposeFlag, int faninConstrainMode);
+static void MinimizeTransitionRelationWithFaninConstraint(Img_ImageInfo_t *imageInfo, array_t *faninConstrainArray, Img_MinimizeType constrainMethod, boolean reorderPtrFlag, boolean duplicate);
+static void ComputeConstrainedInitialStates(Fsm_Fsm_t *subFsm, array_t *faninConstrainArray, Img_MinimizeType constrainMethod);
+static void ComputeApproximateReachableStatesArray(mdd_manager *mddManager, array_t *reachedArray, mdd_t **reached, mdd_t ***subReached, int nSubFsms, int decomposeFlag);
+static array_t * ArdcCopyOverApproxReachableStatesFromExact(Fsm_Fsm_t *fsm);
+static void PrintCurrentReachedStates(mdd_manager *mddManager, Fsm_Fsm_t **subFsm, mdd_t **reached, Fsm_Ardc_TraversalType_t method, int nSubFsms, int iteration, int nvars, int ardcVerbosity, boolean supportCheckFlag);
+static void PrintBddWithName(Fsm_Fsm_t *fsm, array_t *mddIdArr, mdd_t *node);
+static void ArdcReadGroup(Ntk_Network_t *network, FILE *groupFile, array_t *latchNameArray, array_t *groupIndexArray);
+static void ArdcWriteOneGroup(Part_Subsystem_t *partitionSubsystem, FILE *groupFile, int i);
+static void ArdcPrintOneGroup(Part_Subsystem_t *partitionSubsystem, int i, int nLatches, array_t *fanIns, array_t *fanOuts);
+static int GetArdcSetIntValue(char *string, int l, int u, int defaultValue);
+static void ArdcEpdCountOnsetOfOverApproximateReachableStates(Fsm_Fsm_t *fsm, EpDouble *epd);
+static mdd_t * QuantifyVariables(mdd_t *state, array_t *smoothArray, mdd_t *smoothCube);
+static void UpdateMbmEventSchedule(Fsm_Fsm_t **subFsm, array_t *fanOutIndices, int *traverse, int lfpFlag);
+static void PrintTfmStatistics(array_t *subFsmArray);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions					     */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Minimize transition relation of a submachine with ARDC.]
+
+  Description [Minimize transition relation of a submachine with
+  ARDC. Direction of traversal is specified by forward(1) or
+  backward(2) or both(3).
+
+  <p>This function is internal to the ardc sub-package.
+  
+  <p>Perhaps you should use Fsm_MinimizeTransitionRelationWithReachabilityInfo.
+  That function will minimize wrt exact RDCs if available.
+   ]
+
+
+  SideEffects []
+
+******************************************************************************/
+void
+Fsm_ArdcMinimizeTransitionRelation(Fsm_Fsm_t *fsm, Img_DirectionType fwdbwd)
+{
+  char			*flagValue;
+  int			value = 0;
+  int			fwd = 0;
+  int			bwd = 0;
+  Img_ImageInfo_t	*imageInfo;
+  int			saveStatus;
+  boolean		reorderPtrFlag = FALSE;
+
+  switch (fwdbwd) {
+  case Img_Forward_c:
+    fwd = 1;
+    break;
+  case Img_Backward_c:
+    bwd = 1;
+    break;
+  case Img_Both_c:
+    fwd = 1;
+    bwd= 1;
+    break;
+  }
+
+  imageInfo = Fsm_FsmReadOrCreateImageInfo(fsm, bwd, fwd);
+
+  saveStatus = 0;
+  flagValue = Cmd_FlagReadByName("ardc_verbosity");
+  if (flagValue != NIL(char)) {
+    sscanf(flagValue, "%d", &value);
+    if (value > 1) {
+      saveStatus = Img_ReadPrintMinimizeStatus(imageInfo);
+      Img_SetPrintMinimizeStatus(imageInfo, 1);
+    }
+  }
+
+  reorderPtrFlag = FsmGetArdcSetBooleanValue("ardc_reorder_ptr",
+						reorderPtrFlag);
+  Img_MinimizeTransitionRelation(
+    imageInfo,
+    Fsm_FsmReadCurrentOverApproximateReachableStates(fsm),
+    Img_DefaultMinimizeMethod_c, fwdbwd, reorderPtrFlag);
+
+  if (value > 1)
+    Img_SetPrintMinimizeStatus(fsm->imageInfo, saveStatus);
+  return;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the image of current reachable states of an FSM.]
+
+  Description [Computes the image of current reachable states of an FSM.
+  It calls Fsm_FsmComputeReachableStates by setting depthValue to 1.]
+
+  SideEffects []
+
+  SeeAlso []
+
+******************************************************************************/
+mdd_t *
+Fsm_ArdcComputeImage(Fsm_Fsm_t *fsm,
+		     mdd_t *fromLowerBound,
+		     mdd_t *fromUpperBound,
+		     array_t *toCareSetArray)
+{
+  Img_ImageInfo_t	*imageInfo = NIL(Img_ImageInfo_t);
+  mdd_t			*image;
+
+  /* Create an imageInfo for image computations, if not already created. */
+  imageInfo = Fsm_FsmReadOrCreateImageInfo(fsm, 0, 1);
+
+  /* Compute the image */
+  image = Img_ImageInfoComputeImageWithDomainVars(imageInfo,
+		fromLowerBound, fromUpperBound, toCareSetArray);
+
+  return(image);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes overapproximate reachable states.]
+
+  Description [Computes overapproximate reachable states. This function is a
+  wrapper around Fsm_ArdcComputeOverApproximateReachableStates.]
+
+  SideEffects []
+
+  SeeAlso [Fsm_ArdcComputeOverApproximateReachableStates]
+
+******************************************************************************/
+array_t *
+Fsm_FsmComputeOverApproximateReachableStates(Fsm_Fsm_t *fsm,
+  int incrementalFlag, int verbosityLevel, int printStep, int depthValue,
+  int shellFlag, int reorderFlag, int reorderThreshold, int recompute)
+{
+  array_t		*apprReachableStates;
+  Fsm_ArdcOptions_t	options;
+
+  Fsm_ArdcGetDefaultOptions(&options);
+
+  if (printStep && options.verbosity < 2)
+    printStep = 0;
+
+  apprReachableStates = Fsm_ArdcComputeOverApproximateReachableStates(fsm,
+    incrementalFlag, verbosityLevel, printStep, depthValue, shellFlag,
+    reorderFlag, reorderThreshold, recompute, &options);
+
+  return(apprReachableStates);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the set of approximate reachable states of an FSM.]
+
+  Description [Computes the set of approximate reachable states of an FSM.
+  If this set has already been computed, then just returns the result of
+  the previous computation. The computations starts by creating
+  partitions (based on either hierarchy or state space
+  decomposition [TCAD96]). The submachines are created for each of these
+  partitions. Then approximate traversal is performed by one of the
+  supported methods (MBM, RFBF, TFBF, TMBM, LMBM, and TLMBM). The approximate
+  reachable set is returned in a conjunctive decomposed form in an array.]
+
+  SideEffects []
+
+  SeeAlso [Fsm_FsmComputeInitialStates Fsm_FsmComputeReachableStates]
+
+******************************************************************************/
+array_t *
+Fsm_ArdcComputeOverApproximateReachableStates(Fsm_Fsm_t *fsm,
+					      int incrementalFlag,
+					      int verbosityLevel,
+					      int printStep,
+					      int depthValue, int shellFlag,
+					      int reorderFlag,
+					      int reorderThreshold,
+					      int recompute,
+					      Fsm_ArdcOptions_t *options)
+{
+  array_t		*reachableStatesArray = NIL(array_t);
+  mdd_t			*reachableStates = NIL(mdd_t);
+  mdd_t			*initialStates;
+  Ntk_Network_t		*network = Fsm_FsmReadNetwork(fsm);
+  Part_Subsystem_t	*partitionSubsystem;
+  array_t		*partitionArray;
+  int			i;
+  graph_t		*partition = Part_NetworkReadPartition(network);
+  st_table		*vertexTable;
+  Fsm_Fsm_t		*subFsm;
+  array_t		*subFsmArray;
+  array_t		*fanIns, *fanOuts;
+  array_t		*fanInsIndexArray, *fanOutsIndexArray;
+  array_t		*fans;
+  array_t		*psVars;
+  mdd_manager		*mddManager = Fsm_FsmReadMddManager(fsm);
+  char			*flagValue;
+  Fsm_RchType_t		approxFlag;
+  int			nvars; /* the number of binary variables of the fsm */
+  FILE			*groupFile = NIL(FILE);
+  Img_MethodType	imageMethod = Img_Default_c;
+  Img_MethodType	saveImageMethod = Img_Default_c;
+  char			*imageMethodString;
+  Fsm_Ardc_AbstPpiType_t saveAbstractPseudoInput;
+
+  if (recompute)
+    FsmResetReachabilityFields(fsm, Fsm_Rch_Oa_c);
+
+  /* If exact is already computed, copy exact to overapproximate. */
+  if (Fsm_FsmReadReachableStates(fsm) != NIL(mdd_t)) {
+    if (Fsm_FsmReadCurrentOverApproximateReachableStates(fsm) != NIL(array_t)) {
+      /* If the overapproximation is already the exact set, return it,
+       * otherwise discard it. */
+      if (FsmReadReachabilityOverApproxComputationStatus(fsm) ==
+	  Fsm_Ardc_Exact_c) {
+	return(Fsm_FsmReadOverApproximateReachableStates(fsm));
+      } else {
+	fprintf(vis_stdout,
+		"** ardc warning : ignoring previous computation.\n");
+	Fsm_FsmFreeOverApproximateReachableStates(fsm);
+      }
+    }
+    if (verbosityLevel > 0 || options->verbosity > 0) {
+      fprintf(vis_stdout,
+	      "** ardc info : exact reached states are already computed.\n");
+    }
+    /* Either we had no overapproximation, or it was not the exact set, and
+     * hence it was discarded.  Copy from exact to overapproximate. */
+    reachableStatesArray = ArdcCopyOverApproxReachableStatesFromExact(fsm);
+    return(reachableStatesArray);
+  }
+
+  /* If already computed, just return the array. */
+  if (Fsm_FsmReadCurrentOverApproximateReachableStates(fsm) != NIL(array_t)) {
+    if (FsmReadReachabilityOverApproxComputationStatus(fsm) >=
+	Fsm_Ardc_Converged_c) {
+      return(Fsm_FsmReadOverApproximateReachableStates(fsm));
+    } else {
+      /* Here, at this time, we just throw away current approximate
+       * reachable states which is not converged yet, then restart.
+       */
+      fprintf(vis_stdout,
+	      "** ardc warning : ignoring previous computation.\n");
+      Fsm_FsmFreeOverApproximateReachableStates(fsm);
+    }
+  }
+
+  /* Perform state space decomposition. */
+  partitionArray = Fsm_ArdcDecomposeStateSpace(network,
+					       fsm->fsmData.presentStateVars,
+					       fsm->fsmData.nextStateFunctions,
+					       options);
+
+  /* If there is only one group, call exact reachability analysis. */
+  if (array_n(partitionArray) == 1) {
+    if (options->verbosity > 0) {
+      fprintf(vis_stdout,
+	      "** ardc info : changing to exact reachability analysis.\n");
+    }
+    arrayForEachItem(Part_Subsystem_t *, partitionArray, i,
+		     partitionSubsystem) {
+      Part_PartitionSubsystemFree(partitionSubsystem);
+    }
+    array_free(partitionArray);
+
+    if (options->useHighDensity)
+      approxFlag = Fsm_Rch_Hd_c;
+    else
+      approxFlag = Fsm_Rch_Bfs_c;
+    reachableStates = Fsm_FsmComputeReachableStates(fsm,
+		0, verbosityLevel, printStep, 0,
+		0, reorderFlag, reorderThreshold,
+		approxFlag, 0, 0, NIL(array_t), (verbosityLevel > 1),
+						    NIL(array_t));
+    mdd_free(reachableStates);
+    reachableStatesArray = ArdcCopyOverApproxReachableStatesFromExact(fsm);
+    return(reachableStatesArray);
+  }
+
+  /* Read the image_method flag, and save its value in imageMethodString. */
+  flagValue = Cmd_FlagReadByName("image_method");
+  if (flagValue != NIL(char)) {
+    if (strcmp(flagValue, "iwls95") == 0 || strcmp(flagValue, "default") == 0)
+      imageMethod = Img_Iwls95_c;
+    else if (strcmp(flagValue, "monolithic") == 0)
+      imageMethod = Img_Monolithic_c;
+    else if (strcmp(flagValue, "tfm") == 0)
+      imageMethod = Img_Tfm_c;
+    else if (strcmp(flagValue, "hybrid") == 0)
+      imageMethod = Img_Hybrid_c;
+    else if (strcmp(flagValue, "mlp") == 0)
+      imageMethod = Img_Mlp_c;
+    else {
+      fprintf(vis_stderr, "** ardc error: invalid image method %s.\n",
+	      flagValue);
+    }
+  }
+  imageMethodString = flagValue;
+  /* Update the image_method flag to the method specified for approximate
+   * reachability. */
+  if (options->ardcImageMethod != Img_Default_c &&
+      options->ardcImageMethod != imageMethod) {
+    saveImageMethod = imageMethod;
+    if (options->ardcImageMethod == Img_Monolithic_c) {
+      Cmd_FlagUpdateValue("image_method", "monolithic");
+      imageMethod = Img_Monolithic_c;
+    } else if (options->ardcImageMethod == Img_Iwls95_c) {
+      Cmd_FlagUpdateValue("image_method", "iwls95");
+      imageMethod = Img_Iwls95_c;
+    } else if (options->ardcImageMethod == Img_Tfm_c) {
+      Cmd_FlagUpdateValue("image_method", "tfm");
+      imageMethod = Img_Tfm_c;
+    } else if (options->ardcImageMethod == Img_Hybrid_c) {
+      Cmd_FlagUpdateValue("image_method", "hybrid");
+      imageMethod = Img_Hybrid_c;
+    } else if (options->ardcImageMethod == Img_Mlp_c) {
+      Cmd_FlagUpdateValue("image_method", "mlp");
+      imageMethod = Img_Mlp_c;
+    }
+  }
+
+  /* Open the file where to save the result of partitioning is so requested. */
+  if (options->writeGroupFile) {
+    groupFile = Cmd_FileOpen(options->writeGroupFile, "w", NIL(char *), 0);
+    if (groupFile == NIL(FILE)) {
+      fprintf(vis_stderr, "** ardc error : can't open file [%s] to write.\n",
+	      options->writeGroupFile);
+    }
+  }
+
+  /* Compute the set of initial states, if not already computed. */
+  initialStates = Fsm_FsmComputeInitialStates(fsm);
+
+  subFsmArray = array_alloc(Fsm_Fsm_t *, 0);
+  fanInsIndexArray = array_alloc(array_t *, 0);
+  fanOutsIndexArray = array_alloc(array_t *, 0);
+
+  /* For each partitioned submachines build an FSM. */
+  arrayForEachItem(Part_Subsystem_t *, partitionArray, i, partitionSubsystem) {
+    vertexTable = Part_PartitionSubsystemReadVertexTable(partitionSubsystem);
+    fanIns = Part_PartitionSubsystemReadFanIn(partitionSubsystem);
+    fanOuts = Part_PartitionSubsystemReadFanOut(partitionSubsystem);
+    subFsm = Fsm_FsmCreateSubsystemFromNetwork(network, partition,
+						vertexTable, TRUE,
+						options->createPseudoVarMode);
+    /* Depending on the options, the initial states of each submachine
+     * are either the states of the entire system or their projection
+     * on the subspace of the submachine. */
+    if (!options->projectedInitialFlag &&
+	options->abstractPseudoInput != Fsm_Ardc_Abst_Ppi_Before_Image_c) {
+      subFsm->reachabilityInfo.initialStates = mdd_dup(initialStates);
+    } else {
+      mdd_t	*dummy;
+
+      dummy = Fsm_FsmComputeInitialStates(subFsm);
+      mdd_free(dummy);
+    }
+    array_insert_last(Fsm_Fsm_t *, subFsmArray, subFsm);
+    array_insert_last(array_t *, fanInsIndexArray, fanIns);
+    array_insert_last(array_t *, fanOutsIndexArray, fanOuts);
+
+    if (options->verbosity > 1) {
+      int	nLatches;
+      nLatches = mdd_get_number_of_bdd_vars(mddManager,
+      					    subFsm->fsmData.presentStateVars);
+      ArdcPrintOneGroup(partitionSubsystem, i, nLatches, fanIns, fanOuts);
+    }
+    if (groupFile)
+      ArdcWriteOneGroup(partitionSubsystem, groupFile, i);
+
+    st_free_table(vertexTable);
+  } /* end of arrayForEachItem(partitionArray) */
+  mdd_free(initialStates);
+
+  if (groupFile)
+    fclose(groupFile);
+
+  /* Sort submachines to find the order in which to traverse them. */
+  SortSubFsmsForApproximateTraversal(&subFsmArray, &fanInsIndexArray,
+				     &fanOutsIndexArray, options->verbosity);
+
+  /* Optimize pseudo-input variables to contain only the variables of fanin
+   * submachines. If createPseudoVarMode is 0, the set of pseudo-input
+   * variables is just the collection of the variables of all other
+   * submachines.
+   * If createPseudoVarMode is 1, the set is the collection of the variables
+   * of only its fanin submachines. If createPseudoVarMode is 2, the set is
+   * the collection of the support variables that appear in other submachines.
+   */
+  if (options->createPseudoVarMode == 0) {
+    arrayForEachItem(Fsm_Fsm_t *, subFsmArray, i, subFsm) {
+      Fsm_Fsm_t	*faninSubfsm;
+      int	j, fanin;
+
+      subFsm->fsmData.primaryInputVars = array_dup(subFsm->fsmData.inputVars);
+      subFsm->fsmData.pseudoInputVars = array_alloc(int, 0);
+      fanIns = array_fetch(array_t *, fanInsIndexArray, i);
+      arrayForEachItem(int, fanIns, j, fanin) {
+	if (fanin == i)
+	  continue;
+	faninSubfsm = array_fetch(Fsm_Fsm_t *, subFsmArray, fanin);
+	array_append(subFsm->fsmData.pseudoInputVars,
+		  faninSubfsm->fsmData.presentStateVars);
+      }
+      subFsm->fsmData.globalPsVars = array_dup(
+	subFsm->fsmData.presentStateVars);
+      array_append(subFsm->fsmData.globalPsVars,
+	subFsm->fsmData.pseudoInputVars);
+      array_append(subFsm->fsmData.inputVars, subFsm->fsmData.pseudoInputVars);
+
+      subFsm->fsmData.pseudoInputBddVars = mdd_id_array_to_bdd_array(mddManager,
+	subFsm->fsmData.pseudoInputVars);
+
+      if (subFsm->fsmData.createVarCubesFlag) {
+	subFsm->fsmData.pseudoInputCube = mdd_id_array_to_bdd_cube(mddManager,
+	  subFsm->fsmData.pseudoInputVars);
+	subFsm->fsmData.primaryInputCube = subFsm->fsmData.inputCube;
+	subFsm->fsmData.inputCube = mdd_id_array_to_bdd_cube(mddManager,
+	  subFsm->fsmData.inputVars);
+	subFsm->fsmData.globalPsCube = mdd_id_array_to_bdd_cube(mddManager,
+	  subFsm->fsmData.globalPsVars);
+      }
+    }
+  }
+
+  if (options->useHighDensity)
+    approxFlag = Fsm_Rch_Hd_c;
+  else
+    approxFlag = Fsm_Rch_Bfs_c;
+
+  /* In case of transition function method, since quantification doesn't
+   * make any sense, we turn it off.  We turn quantification off also for the
+   * hybrid method, because it starts with tfm.
+   */
+  saveAbstractPseudoInput = options->abstractPseudoInput;
+  if (imageMethod == Img_Tfm_c || imageMethod == Img_Hybrid_c)
+    options->abstractPseudoInput = Fsm_Ardc_Abst_Ppi_No_c;
+
+  nvars = mdd_get_number_of_bdd_vars(mddManager, fsm->fsmData.presentStateVars);
+  if (options->traversalMethod == Fsm_Ardc_Traversal_Mbm_c) {
+    reachableStatesArray = ArdcMbmTraversal(fsm, nvars, subFsmArray,
+		fanInsIndexArray, fanOutsIndexArray, NULL,
+		incrementalFlag, verbosityLevel, printStep,
+		depthValue, shellFlag, reorderFlag,
+		reorderThreshold, approxFlag, options, FALSE);
+  } else if (options->traversalMethod == Fsm_Ardc_Traversal_Rfbf_c) {
+    if (approxFlag == Fsm_Rch_Hd_c) {
+      fprintf(vis_stderr,
+	"** ardc error : High Density Traversal is not allowed in FBF.\n");
+    }
+    reachableStatesArray = ArdcRfbfTraversal(fsm, nvars, subFsmArray,
+		fanInsIndexArray,
+		incrementalFlag, verbosityLevel, printStep,
+		depthValue, shellFlag, reorderFlag, reorderThreshold,
+		approxFlag, options);
+  } else if (options->traversalMethod == Fsm_Ardc_Traversal_Tfbf_c) {
+    if (approxFlag == Fsm_Rch_Hd_c) {
+      fprintf(vis_stderr,
+	"** ardc error : High Density Traversal is not allowed in FBF.\n");
+    }
+    reachableStatesArray = ArdcTfbfTraversal(fsm, nvars, subFsmArray,
+		fanInsIndexArray, NULL, NULL,
+		incrementalFlag, verbosityLevel, printStep,
+		depthValue, shellFlag, reorderFlag, reorderThreshold,
+		approxFlag, options);
+  } else if (options->traversalMethod == Fsm_Ardc_Traversal_Tmbm_c) {
+    reachableStatesArray = ArdcTmbmTraversal(fsm, nvars, subFsmArray,
+		fanInsIndexArray, fanOutsIndexArray,
+		incrementalFlag, verbosityLevel, printStep,
+		depthValue, shellFlag, reorderFlag, reorderThreshold,
+		approxFlag, options, FALSE);
+  } else if (options->traversalMethod == Fsm_Ardc_Traversal_Lmbm_c) {
+    reachableStatesArray = ArdcMbmTraversal(fsm, nvars, subFsmArray,
+		fanInsIndexArray, fanOutsIndexArray, NULL,
+		incrementalFlag, verbosityLevel, printStep,
+		depthValue, shellFlag, reorderFlag,
+		reorderThreshold, approxFlag, options, TRUE);
+  } else if (options->traversalMethod == Fsm_Ardc_Traversal_Tlmbm_c) {
+    reachableStatesArray = ArdcTmbmTraversal(fsm, nvars, subFsmArray,
+		fanInsIndexArray, fanOutsIndexArray,
+		incrementalFlag, verbosityLevel, printStep,
+		depthValue, shellFlag, reorderFlag, reorderThreshold,
+		approxFlag, options, TRUE);
+  } else {
+    reachableStatesArray = ArdcSimpleTraversal(fsm, nvars, subFsmArray,
+		incrementalFlag, verbosityLevel, printStep,
+		depthValue, shellFlag, reorderFlag, reorderThreshold,
+		approxFlag, options, TRUE);
+  }
+  options->abstractPseudoInput = saveAbstractPseudoInput;
+
+  if (options->verbosity &&
+      (options->ardcImageMethod == Img_Tfm_c ||
+       options->ardcImageMethod == Img_Hybrid_c)) {
+    PrintTfmStatistics(subFsmArray);
+  }
+
+  fsm->reachabilityInfo.subPsVars = array_alloc(array_t *, 0);
+  if (options->decomposeFlag) {
+    for (i = 0; i < array_n(subFsmArray); i++) {
+      subFsm = array_fetch(Fsm_Fsm_t *, subFsmArray, i);
+      psVars = array_dup(subFsm->fsmData.presentStateVars);
+      array_insert_last(array_t *, fsm->reachabilityInfo.subPsVars, psVars);
+    }
+  } else {
+    psVars = array_dup(fsm->fsmData.presentStateVars);
+    array_insert_last(array_t *, fsm->reachabilityInfo.subPsVars, psVars);
+  }
+
+  arrayForEachItem(array_t *, fanInsIndexArray, i, fans) {
+    array_free(fans);
+  }
+  array_free(fanInsIndexArray);
+  arrayForEachItem(array_t *, fanOutsIndexArray, i, fans) {
+    array_free(fans);
+  }
+  array_free(fanOutsIndexArray);
+  arrayForEachItem(Part_Subsystem_t *, partitionArray, i, partitionSubsystem) {
+    FREE(partitionSubsystem);
+  }
+  array_free(partitionArray);
+
+  arrayForEachItem(Fsm_Fsm_t *, subFsmArray, i, subFsm) {
+    Fsm_FsmSubsystemFree(subFsm);
+  }
+  array_free(subFsmArray);
+
+  /* Restore value of image_method flag. */
+  if (options->ardcImageMethod != Img_Default_c &&
+      options->ardcImageMethod != saveImageMethod) {
+    if (imageMethodString) {
+      if (saveImageMethod == Img_Monolithic_c)
+	Cmd_FlagUpdateValue("image_method", "monolithic");
+      else if (saveImageMethod == Img_Iwls95_c)
+	Cmd_FlagUpdateValue("image_method", "iwls95");
+      else if (saveImageMethod == Img_Tfm_c)
+	Cmd_FlagUpdateValue("image_method", "tfm");
+      else if (saveImageMethod == Img_Hybrid_c)
+	Cmd_FlagUpdateValue("image_method", "hybrid");
+      else if (saveImageMethod == Img_Mlp_c)
+	Cmd_FlagUpdateValue("image_method", "mlp");
+    } else
+      Cmd_FlagDeleteByName("image_method");
+  }
+
+  fsm->reachabilityInfo.apprReachableStates = reachableStatesArray;
+  return(reachableStatesArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs state space decomposition.]
+
+  Description [Performs state space decomposition.]
+
+  SideEffects []
+
+  SeeAlso []
+
+******************************************************************************/
+array_t *
+Fsm_ArdcDecomposeStateSpace(Ntk_Network_t *network, array_t *presentStateVars,
+			array_t *nextStateFunctions, Fsm_ArdcOptions_t *options)
+{
+  array_t		*latchNameArray;
+  array_t		*groupIndexArray;
+  char			*name;
+  Ntk_Node_t		*latch;
+  int			i, mddId;
+  Part_SubsystemInfo_t	*subsystemInfo;
+  array_t		*partitionArray;
+  FILE			*groupFile = NIL(FILE);
+  long			initialTime = 0, finalTime;
+  int			verbosity = 0;
+  float			affinityFactor = 0.5;
+  int			groupSize = 8;
+
+  if (options) {
+    verbosity = options->verbosity;
+    affinityFactor = options->affinityFactor;
+    groupSize = options->groupSize;
+  } else {
+    char	*flagValue;
+
+    flagValue = Cmd_FlagReadByName("ardc_group_size");
+    if (flagValue != NIL(char)) {
+      sscanf(flagValue, "%d", &groupSize);
+      if (groupSize <= 0) {
+	fprintf(vis_stderr,
+		"** ardc error: invalid value %s for ardc_group_size[>0]. **\n",
+		flagValue);
+	groupSize = 8;
+      }
+    }
+    flagValue = Cmd_FlagReadByName("ardc_verbosity");
+    if (flagValue != NIL(char))
+      sscanf(flagValue, "%d", &verbosity);
+    flagValue = Cmd_FlagReadByName("ardc_affinity_factor");
+    if (flagValue != NIL(char)) {
+      sscanf(flagValue, "%f", &affinityFactor);
+      if (affinityFactor < 0.0 || affinityFactor > 1.0) {
+	fprintf(vis_stderr,
+      "** ardc error :invalid value %s for ardc_affinity_factor[0.0-1.0]. **\n",
+		flagValue);
+	affinityFactor = 0.5;
+      }
+    }
+  }
+
+  if (verbosity > 0)
+    initialTime = util_cpu_time();
+
+  if (options && options->readGroupFile) {
+    groupFile = Cmd_FileOpen(options->readGroupFile, "r", NIL(char *), 1);
+    if (groupFile == NIL(FILE)) {
+      fprintf(vis_stderr, "** ardc error : can't open file [%s] to read.\n",
+	      options->readGroupFile);
+    }
+  }
+
+  if (groupFile) {
+    latchNameArray = array_alloc(char *, 0);
+    groupIndexArray = array_alloc(int, 0);
+    ArdcReadGroup(network, groupFile, latchNameArray, groupIndexArray);
+    subsystemInfo = Part_PartitionSubsystemInfoInit(network);
+    partitionArray = Part_PartCreateSubsystems(subsystemInfo,
+			latchNameArray, groupIndexArray);
+    Part_PartitionSubsystemInfoFree(subsystemInfo);
+    arrayForEachItem(char *, latchNameArray, i, name) {
+      FREE(name);
+    }
+    array_free(latchNameArray);
+    array_free(groupIndexArray);
+    fclose(groupFile);
+    groupFile = NIL(FILE);
+  } else if (groupSize > 0) {
+    subsystemInfo = Part_PartitionSubsystemInfoInit(network);
+    /*
+    Part_PartitionSubsystemInfoSetVerbosity(subsystemInfo, verbosity);
+    */
+    Part_PartitionSubsystemInfoSetBound(subsystemInfo, groupSize);
+    Part_PartitionSubsystemInfoSetAffinityFactor(subsystemInfo, affinityFactor);
+    latchNameArray = array_alloc(char *, 0);
+    arrayForEachItem(int, presentStateVars, i, mddId) {
+      latch = Ntk_NetworkFindNodeByMddId(network, mddId);
+      name = Ntk_NodeReadName(latch);
+      array_insert_last(char *, latchNameArray, name);
+    }
+    partitionArray = Part_PartCreateSubsystems(subsystemInfo,
+		       latchNameArray, NIL(array_t));
+    array_free(latchNameArray);
+    Part_PartitionSubsystemInfoFree(subsystemInfo);
+  } else {
+    partitionArray = Part_PartGroupVeriticesBasedOnHierarchy(network,
+      nextStateFunctions);
+  }
+  if (verbosity > 0) {
+    finalTime = util_cpu_time();
+    fprintf(vis_stdout, "grouping(state space decomposition) time = %g\n",
+      (double)(finalTime - initialTime) / 1000.0);
+  }
+
+  return(partitionArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates an ARDC option structure.]
+
+  Description [Allocates an ARDC option structure.]
+
+  SideEffects []
+
+  SeeAlso []
+
+******************************************************************************/
+Fsm_ArdcOptions_t *
+Fsm_ArdcAllocOptionsStruct(void)
+{
+  Fsm_ArdcOptions_t *options;
+
+  options = ALLOC(Fsm_ArdcOptions_t, 1);
+  (void)memset((void *)options, 0, sizeof(Fsm_ArdcOptions_t));
+
+  return(options);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets default values for ARDC computatiion.]
+
+  Description [Gets default values for ARDC computatiion.
+  Options are as follows.
+
+  set ardc_traversal_method <m>
+      m = 0 : MBM (machine by machine, default)
+      m = 1 : RFBF(reached frame by frame)
+      m = 2 : TFBF(to frame by frame)
+      m = 3 : TMBM(TFBF + MBM)
+      m = 4 : LMBM(least fixpoint MBM)
+  set ardc_group_size <n>
+      n (default = 8)
+  set ardc_affinity_factor <f>
+      f = 0.0 - 1.0 (default = 0.5)
+  set ardc_max_iteration <n>
+      n (default = 0(infinity))
+  set ardc_constrain_target <m>
+      m = 0 : constrain transition relation (default)
+      m = 1 : constrain initial states
+      m = 2 : constrain both
+  set ardc_constrain_method <m>
+      m = 0 : restrict (default)
+      m = 1 : constrain
+      m = 2 : compact (currently supported by only CUDD)
+      m = 3 : squeeze (currently supported by only CUDD)
+  set ardc_constrain_reorder <m>
+      m = yes : allow variable reorderings during consecutive
+		image constraining operations (default)
+      m = no  : don't allow variable reorderings during consecutive
+		image constraining operations
+  set ardc_abstract_pseudo_input <m>
+      m = 0 : do not abstract pseudo input variables
+      m = 1 : abstract pseudo inputs before image computation (default)
+      m = 2 : abstract pseudo inputs at every end of image computation
+      m = 3 : abstract pseudo inputs at the end of approximate traversal
+  set ardc_decompose_flag <m>
+      m = yes : keep decomposed reachable stateses (default)
+      m = no  : make a conjunction of reachable states of all submachines
+  set ardc_projected_initial_flag <m>
+      m = yes : use projected initial states for submachine (default)
+      m = no  : use original initial states for submachine
+  set ardc_image_method <m>
+      m = monolithic : use monolithic image computation for submachines
+      m = iwls95     : use iwls95 image computation for submachines (default)
+      m = tfm        : use tfm image computation for submachines
+      m = hybrid     : use hybrid image computation for submachines
+  set ardc_use_high_density <m>
+      m = yes : use High Density for reachable states of submachines
+      m = no  : use BFS for reachable states of submachines (default)
+  set ardc_create_pseudo_var_mode <m>
+      m = 0 : makes pseudo input variables with exact support (default)
+      m = 1 : makes pseudo input variables from all state variables of
+	      the other machines
+      m = 2 : makes pseudo input variables from all state variables of
+	      fanin machines
+  set ardc_reorder_ptr <m>
+      m = yes : whenever partitioned transition relation changes,
+		reorders partitioned transition relation
+      m = no  : no reordering of partitioned transition relation (default)
+  set ardc_fanin_constrain_mode <m>
+      m = 0 : constrains w.r.t. the reachable states of fanin machines (default)
+      m = 1 : constrains w.r.t. the reachable states of both fanin machines
+	      and itself
+  set ardc_lmbm_initial_mode <m>
+      m = 0 : use given initial states all the time
+      m = 1 : use current reached states as initial states (default)
+      m = 2 : use current frontier as initial states
+  set ardc_mbm_reuse_tr <m>
+      m = yes : use constrained transition relation for next iteration
+      m = no  : use original transition relation for next iteration (default)
+  set ardc_read_group <filename>
+      <filename> file containing grouping information
+  set ardc_write_group <filename>
+      <filename> file to write grouping information
+  set ardc_verbosity <n>
+      n = 0 - 3 (default = 0)
+  ]
+
+  SideEffects []
+
+  SeeAlso []
+
+******************************************************************************/
+void
+Fsm_ArdcGetDefaultOptions(Fsm_ArdcOptions_t *options)
+{
+  int			groupSize = 8;
+  float			affinityFactor = 0.5;
+  Fsm_Ardc_TraversalType_t traversalMethod = Fsm_Ardc_Traversal_Lmbm_c;
+  int			maxIteration = 0;
+  Fsm_Ardc_ConstrainTargetType_t constrainTarget = Fsm_Ardc_Constrain_Tr_c;
+  Img_MinimizeType	constrainMethod = Img_Restrict_c;
+  boolean		decomposeFlag = TRUE;
+  Fsm_Ardc_AbstPpiType_t abstractPseudoInput = Fsm_Ardc_Abst_Ppi_Before_Image_c;
+  boolean		projectedInitialFlag = TRUE;
+  boolean		constrainReorderFlag = TRUE;
+  Img_MethodType	ardcImageMethod = Img_Default_c;
+  boolean		useHighDensity = FALSE;
+  int			createPseudoVarMode = 0;
+  int			verbosity = 0;
+  char			*flagValue;
+  int			value;
+  float			affinity;
+  boolean		reorderPtrFlag = FALSE;
+  int			faninConstrainMode = 0;
+  int			lmbmInitialStatesMode = 1;
+  int			mbmReuseTrFlag = 0;
+
+  flagValue = Cmd_FlagReadByName("ardc_traversal_method");
+  if (flagValue != NIL(char)) {
+    sscanf(flagValue, "%d", &value);
+    switch (value) {
+    case 0 :
+      traversalMethod = Fsm_Ardc_Traversal_Mbm_c;
+      break;
+    case 1 :
+      traversalMethod = Fsm_Ardc_Traversal_Rfbf_c;
+      break;
+    case 2 :
+      traversalMethod = Fsm_Ardc_Traversal_Tfbf_c;
+      break;
+    case 3 :
+      traversalMethod = Fsm_Ardc_Traversal_Tmbm_c;
+      break;
+    case 4 :
+      traversalMethod = Fsm_Ardc_Traversal_Lmbm_c;
+      break;
+    case 5 :
+      traversalMethod = Fsm_Ardc_Traversal_Tlmbm_c;
+      break;
+    case 6 : /* hidden option */
+      traversalMethod = Fsm_Ardc_Traversal_Simple_c;
+      break;
+    default :
+      fprintf(vis_stderr, "** ardc error : invalid value %s", flagValue);
+      fprintf(vis_stderr, " for ardc_traversal_method[0-5]. **\n");
+      break;
+    }
+  }
+  options->traversalMethod = traversalMethod;
+
+  flagValue = Cmd_FlagReadByName("ardc_group_size");
+  if (flagValue != NIL(char)) {
+    sscanf(flagValue, "%d", &value);
+    if (value > 0)
+      groupSize = value;
+    else {
+      fprintf(vis_stderr,
+	      "** ardc error : invalid value %s for ardc_group_size[>0]. **\n",
+	      flagValue);
+    }
+  }
+  options->groupSize = groupSize;
+
+  flagValue = Cmd_FlagReadByName("ardc_affinity_factor");
+  if (flagValue != NIL(char)) {
+    sscanf(flagValue, "%f", &affinity);
+    if (affinity >= 0.0 && affinity <= 1.0)
+      affinityFactor = affinity;
+    else {
+      fprintf(vis_stderr,
+     "** ardc error : invalid value %s for ardc_affinity_factor[0.0-1.0]. **\n",
+	      flagValue);
+    }
+  }
+  options->affinityFactor = affinityFactor;
+
+  flagValue = Cmd_FlagReadByName("ardc_constrain_method");
+  if (flagValue != NIL(char)) {
+    sscanf(flagValue, "%d", &value);
+    switch (value) {
+    case 0 :
+      constrainMethod = Img_Restrict_c;
+      break;
+    case 1 :
+      constrainMethod = Img_Constrain_c;
+      break;
+    case 2 :
+      if (bdd_get_package_name() != CUDD) {
+	fprintf(vis_stderr, "** ardc error : Compact in ardc_constrain_method");
+	fprintf(vis_stderr, " is currently supported by only CUDD. **\n");
+	break;
+      }
+      constrainMethod = Img_Compact_c;
+      break;
+    case 3 :
+      if (bdd_get_package_name() != CUDD) {
+	fprintf(vis_stderr, "** ardc error : Squeeze in ardc_constrain_method");
+	fprintf(vis_stderr, " is currently supported by only CUDD. **\n");
+	break;
+      }
+      constrainMethod = Img_Squeeze_c;
+      break;
+    case 4 :
+      constrainMethod = Img_And_c;
+      break;
+    default :
+      fprintf(vis_stderr,
+      "** ardc error : invalid value %s for ardc_constrain_method[0-4]. **\n",
+	      flagValue);
+      break;
+    }
+  }
+  options->constrainMethod = constrainMethod;
+
+  flagValue = Cmd_FlagReadByName("ardc_constran_to");
+  if (flagValue != NIL(char)) {
+    sscanf(flagValue, "%d", &value);
+    switch (value) {
+    case 0 :
+      constrainTarget = Fsm_Ardc_Constrain_Tr_c;
+      break;
+    case 1 :
+      constrainTarget = Fsm_Ardc_Constrain_Initial_c;
+      break;
+    case 2 :
+      constrainTarget = Fsm_Ardc_Constrain_Both_c;
+      break;
+    default :
+      fprintf(vis_stderr,
+	"** ardc error : invalid value %s for ardc_constrain_target[0-2]. **\n",
+	    flagValue);
+      break;
+    }
+  }
+  options->constrainTarget = constrainTarget;
+
+  flagValue = Cmd_FlagReadByName("ardc_max_iteration");
+  if (flagValue != NIL(char)) {
+    sscanf(flagValue, "%d", &value);
+    if (value >= 0)
+      maxIteration = value;
+    else {
+      fprintf(vis_stderr,
+	"** ardc error : invalid value %s for ardc_max_iteration[>=0]. **\n",
+	flagValue);
+    }
+  }
+  options->maxIteration = maxIteration;
+
+  flagValue = Cmd_FlagReadByName("ardc_abstract_pseudo_input");
+  if (flagValue != NIL(char)) {
+    sscanf(flagValue, "%d", &value);
+    switch (value) {
+    case 0 :
+      abstractPseudoInput = Fsm_Ardc_Abst_Ppi_No_c;
+      break;
+    case 1 :
+      abstractPseudoInput = Fsm_Ardc_Abst_Ppi_Before_Image_c;
+      break;
+    case 2 :
+      abstractPseudoInput = Fsm_Ardc_Abst_Ppi_After_Image_c;
+      break;
+    case 3 :
+      abstractPseudoInput = Fsm_Ardc_Abst_Ppi_At_End_c;
+      break;
+    default :
+      fprintf(vis_stderr, "** ardc error : invalid value %s", flagValue);
+      fprintf(vis_stderr, " for ardc_abstract_pseudo_input[0-3]. **\n");
+      break;
+    }
+  }
+  options->abstractPseudoInput = abstractPseudoInput;
+
+  decomposeFlag = FsmGetArdcSetBooleanValue("ardc_decompose_flag",
+						decomposeFlag);
+  options->decomposeFlag = decomposeFlag;
+
+  projectedInitialFlag =
+			FsmGetArdcSetBooleanValue("ardc_projected_initial_flag",
+						projectedInitialFlag);
+  options->projectedInitialFlag = projectedInitialFlag;
+
+  constrainReorderFlag = FsmGetArdcSetBooleanValue("ardc_constrain_reorder",
+						constrainReorderFlag);
+  options->constrainReorderFlag = constrainReorderFlag;
+
+  flagValue = Cmd_FlagReadByName("ardc_image_method");
+  if (flagValue != NIL(char)) {
+    if (strcmp(flagValue, "monolithic") == 0)
+      ardcImageMethod = Img_Monolithic_c;
+    else if (strcmp(flagValue, "iwls95") == 0)
+      ardcImageMethod = Img_Iwls95_c;
+    else if (strcmp(flagValue, "mlp") == 0)
+      ardcImageMethod = Img_Mlp_c;
+    else if (strcmp(flagValue, "tfm") == 0)
+      ardcImageMethod = Img_Tfm_c;
+    else if (strcmp(flagValue, "hybrid") == 0)
+      ardcImageMethod = Img_Hybrid_c;
+    else
+      fprintf(vis_stderr, "** ardc error : invalid value %s\n", flagValue);
+  }
+  options->ardcImageMethod = ardcImageMethod;
+
+  useHighDensity = FsmGetArdcSetBooleanValue("ardc_use_high_density",
+					  useHighDensity);
+  options->useHighDensity = useHighDensity;
+
+  createPseudoVarMode = GetArdcSetIntValue("ardc_create_pseudo_var_mode", 0, 2,
+					   createPseudoVarMode);
+  options->createPseudoVarMode = createPseudoVarMode;
+
+  reorderPtrFlag = FsmGetArdcSetBooleanValue("ardc_reorder_ptr",
+						reorderPtrFlag);
+  options->reorderPtrFlag = reorderPtrFlag;
+
+  faninConstrainMode = GetArdcSetIntValue("ardc_fanin_constrain_mode", 0, 1,
+					   faninConstrainMode);
+  options->faninConstrainMode = faninConstrainMode;
+
+  flagValue = Cmd_FlagReadByName("ardc_read_group");
+  if (flagValue)
+    options->readGroupFile = flagValue;
+  else
+    options->readGroupFile = NIL(char);
+
+  flagValue = Cmd_FlagReadByName("ardc_write_group");
+  if (flagValue)
+    options->writeGroupFile = flagValue;
+  else
+    options->writeGroupFile = NIL(char);
+
+  lmbmInitialStatesMode = GetArdcSetIntValue("ardc_lmbm_initial_mode", 0, 2,
+						lmbmInitialStatesMode);
+  options->lmbmInitialStatesMode = lmbmInitialStatesMode;
+
+  mbmReuseTrFlag = FsmGetArdcSetBooleanValue("ardc_mbm_reuse_tr",
+						mbmReuseTrFlag);
+  options->mbmReuseTrFlag = mbmReuseTrFlag;
+
+  verbosity = GetArdcSetIntValue("ardc_verbosity", 0, 3, verbosity);
+  options->verbosity = verbosity;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads traversal method option.]
+
+  Description [Reads traversal method option.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Fsm_Ardc_TraversalType_t
+Fsm_ArdcOptionsReadTraversalMethod(Fsm_ArdcOptions_t *options)
+{
+  return(options->traversalMethod);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads group size option.]
+
+  Description [Reads group size option.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Fsm_ArdcOptionsReadGroupSize(Fsm_ArdcOptions_t *options)
+{
+  return(options->groupSize);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads affinity factor option.]
+
+  Description [Reads affinity factor option.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+float
+Fsm_ArdcOptionsReadAffinityFactor(Fsm_ArdcOptions_t *options)
+{
+  return(options->affinityFactor);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads constrain method option.]
+
+  Description [Reads constrain method option.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Img_MinimizeType
+Fsm_ArdcOptionsReadConstrainMethod(Fsm_ArdcOptions_t *options)
+{
+  return(options->constrainMethod);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads constrain option.]
+
+  Description [Reads constrain option.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Fsm_Ardc_ConstrainTargetType_t
+Fsm_ArdcOptionsReadConstrainTarget(Fsm_ArdcOptions_t *options)
+{
+  return(options->constrainTarget);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads max iteration option.]
+
+  Description [Reads max iteration option.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Fsm_ArdcOptionsReadMaxIteration(Fsm_ArdcOptions_t *options)
+{
+  return(options->maxIteration);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads abstract pseudo input option.]
+
+  Description [Reads abstract pseudo input option.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Fsm_Ardc_AbstPpiType_t
+Fsm_ArdcOptionsReadAbstractPseudoInput(Fsm_ArdcOptions_t *options)
+{
+  return(options->abstractPseudoInput);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads decomposed constraint option.]
+
+  Description [Reads decomposed constraint option.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+Fsm_ArdcOptionsReadDecomposeFlag(Fsm_ArdcOptions_t *options)
+{
+  return(options->decomposeFlag);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads initial states mode option.]
+
+  Description [Reads initial states mode option.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+Fsm_ArdcOptionsReadProjectedInitialFlag(Fsm_ArdcOptions_t *options)
+{
+  return(options->projectedInitialFlag);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads constrain reorder flag option.]
+
+  Description [Reads constrain reorder flag option.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+Fsm_ArdcOptionsReadConstrainReorderFlag(Fsm_ArdcOptions_t *options)
+{
+  return(options->constrainReorderFlag);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads image method for ARDC computation.]
+
+  Description [Reads image method for ARDC computation.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Img_MethodType
+Fsm_ArdcOptionsReadImageMethod(Fsm_ArdcOptions_t *options)
+{
+  return(options->ardcImageMethod);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads use high density option.]
+
+  Description [Reads use high density option.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+Fsm_ArdcOptionsReadUseHighDensity(Fsm_ArdcOptions_t *options)
+{
+  return(options->useHighDensity);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads verbosity option.]
+
+  Description [Reads verbosity option.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Fsm_ArdcOptionsReadVerbosity(Fsm_ArdcOptions_t *options)
+{
+  return(options->verbosity);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets traversal method option.]
+
+  Description [Sets traversal method option.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Fsm_ArdcOptionsSetTraversalMethod(Fsm_ArdcOptions_t *options,
+				  Fsm_Ardc_TraversalType_t traversalMethod)
+{
+  options->traversalMethod = traversalMethod;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets group size option.]
+
+  Description [Sets group size option.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Fsm_ArdcOptionsSetGroupSize(Fsm_ArdcOptions_t *options, int groupSize)
+{
+  options->groupSize = groupSize;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets affinity factor option.]
+
+  Description [Sets affinity factor option.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Fsm_ArdcOptionsSetAffinityFactor(Fsm_ArdcOptions_t *options,
+				 float affinityFactor)
+{
+  options->affinityFactor = affinityFactor;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets constrain method option.]
+
+  Description [Sets constrain method option.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Fsm_ArdcOptionsSetConstrainMethod(Fsm_ArdcOptions_t *options,
+				  Img_MinimizeType constrainMethod)
+{
+  options->constrainMethod = constrainMethod;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets constrain option.]
+
+  Description [Sets constrain option.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Fsm_ArdcOptionsSetConstrainTarget(Fsm_ArdcOptions_t *options,
+				Fsm_Ardc_ConstrainTargetType_t constrainTarget)
+{
+  options->constrainTarget = constrainTarget;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets max iteration option.]
+
+  Description [Sets max iteration option.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Fsm_ArdcOptionsSetMaxIteration(Fsm_ArdcOptions_t *options, int maxIteration)
+{
+  options->maxIteration = maxIteration;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets abstract pseudo input option.]
+
+  Description [Sets abstract pseudo input option.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Fsm_ArdcOptionsSetAbstractPseudoInput(Fsm_ArdcOptions_t *options,
+			      Fsm_Ardc_AbstPpiType_t abstractPseudoInput)
+{
+  options->abstractPseudoInput = abstractPseudoInput;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets decomposed constraint option.]
+
+  Description [Sets decomposed constraint option.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Fsm_ArdcOptionsSetDecomposeFlag(Fsm_ArdcOptions_t *options,
+				boolean decomposeFlag)
+{
+  options->decomposeFlag = decomposeFlag;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets initial states mode option.]
+
+  Description [Sets initial states mode option.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Fsm_ArdcOptionsSetProjectedInitialFlag(Fsm_ArdcOptions_t *options,
+				       boolean projectedInitialFlag)
+{
+  options->projectedInitialFlag = projectedInitialFlag;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets constrain reorder flag option.]
+
+  Description [Sets constrain reorder flag option.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Fsm_ArdcOptionsSetConstrainReorderFlag(Fsm_ArdcOptions_t *options,
+				       int constrainReorderFlag)
+{
+  options->constrainReorderFlag = constrainReorderFlag;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets image method for ARDC computation.]
+
+  Description [Sets image method for ARDC computation.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Fsm_ArdcOptionsSetImageMethod(Fsm_ArdcOptions_t *options,
+				Img_MethodType ardcImageMethod)
+{
+  options->ardcImageMethod = ardcImageMethod;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets use high density option.]
+
+  Description [Sets use high density option.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Fsm_ArdcOptionsSetUseHighDensity(Fsm_ArdcOptions_t *options,
+				 boolean useHighDensity)
+{
+  options->useHighDensity = useHighDensity;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets verbosity option.]
+
+  Description [Sets verbosity option.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Fsm_ArdcOptionsSetVerbosity(Fsm_ArdcOptions_t *options, int verbosity)
+{
+  options->verbosity = verbosity;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of approximate reachable states of an FSM.]
+
+  Description [Returns the number of approximate reachable states of an FSM.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+double
+Fsm_ArdcCountOnsetOfOverApproximateReachableStates(Fsm_Fsm_t *fsm)
+{
+  mdd_t *reached;
+  array_t *psVars, *reachedArray;
+  mdd_manager *mddManager = Fsm_FsmReadMddManager(fsm);
+  double numReached = 1.0, tmpReached;
+  int i;
+
+  if (!Fsm_FsmReadCurrentOverApproximateReachableStates(fsm))
+    return(0.0);
+
+  reachedArray = Fsm_FsmReadCurrentOverApproximateReachableStates(fsm);
+  arrayForEachItem(mdd_t *, reachedArray, i, reached) {
+    psVars = array_fetch(array_t *, fsm->reachabilityInfo.subPsVars, i);
+    tmpReached = mdd_count_onset(mddManager, reached, psVars);
+    numReached *= tmpReached;
+  }
+
+  return(numReached);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the bdd size of the set of approximate reachable
+  states of an FSM.]
+
+  Description [Returns the bdd size of the set of approximate reachable
+  states of an FSM.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Fsm_ArdcBddSizeOfOverApproximateReachableStates(Fsm_Fsm_t *fsm)
+{
+  mdd_t *reached;
+  array_t *reachedArray;
+  int i, size = 0;
+
+  if (!Fsm_FsmReadCurrentOverApproximateReachableStates(fsm))
+    return(0);
+
+  reachedArray = Fsm_FsmReadCurrentOverApproximateReachableStates(fsm);
+  arrayForEachItem(mdd_t *, reachedArray, i, reached) {
+    size += mdd_size(reached);
+  }
+
+  return(size);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the conjunction of approximate reachable states of
+  an FSM.]
+
+  Description [Returns the conjunction of approximate reachable states of
+  an FSM.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+mdd_t *
+Fsm_ArdcGetMddOfOverApproximateReachableStates(Fsm_Fsm_t *fsm)
+{
+  mdd_t		*reached, *reachedSet, *tmp;
+  mdd_manager	*mddManager = Fsm_FsmReadMddManager(fsm);
+  array_t	*reachedArray;
+  int		i;
+
+  if (!Fsm_FsmReadCurrentOverApproximateReachableStates(fsm))
+    return(NIL(mdd_t));
+
+  reachedSet = mdd_one(mddManager);
+  reachedArray = Fsm_FsmReadCurrentOverApproximateReachableStates(fsm);
+  arrayForEachItem(mdd_t *, reachedArray, i, reached) {
+    tmp = reachedSet;
+    reachedSet = mdd_and(reachedSet, reached, 1, 1);
+    mdd_free(tmp);
+  }
+
+  return(reachedSet);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Prints info about overapproximate reachable states.]
+
+  Description [Prints info about overapproximate reachable states.]
+
+  SideEffects []
+
+  SeeAlso []
+
+******************************************************************************/
+void
+Fsm_ArdcPrintReachabilityResults(Fsm_Fsm_t *fsm, long elapseTime)
+{
+  array_t *psVars = Fsm_FsmReadPresentStateVars(fsm);
+  mdd_manager *mddMgr = Fsm_FsmReadMddManager(fsm);
+  int nvars = mdd_get_number_of_bdd_vars(mddMgr, psVars);
+  char apprStr[24], ardcStr[24];
+
+  if (nvars <= EPD_MAX_BIN) {
+    double mintermAppr, mintermArdc;
+
+    mintermAppr = Fsm_ArdcCountOnsetOfOverApproximateReachableStates(fsm);
+    sprintf(apprStr, "%10g", mintermAppr);
+    mintermArdc = pow((double)2.0, (double)nvars) - mintermAppr;
+    sprintf(ardcStr, "%10g", mintermArdc);
+  } else {
+    EpDouble apprEpd, ardcEpd;
+
+    ArdcEpdCountOnsetOfOverApproximateReachableStates(fsm, &apprEpd);
+    EpdPow2(nvars, &ardcEpd);
+    EpdSubtract2(&ardcEpd, &apprEpd);
+    EpdGetString(&apprEpd, apprStr);
+    EpdGetString(&ardcEpd, ardcStr);
+  }
+
+  (void)fprintf(vis_stdout,"***********************************************\n");
+  (void)fprintf(vis_stdout,"Over-approximate Reachability analysis results:\n");
+  (void)fprintf(vis_stdout, "%-30s%s\n", "reachable states = ", apprStr);
+  (void)fprintf(vis_stdout, "%-30s%s\n", "unreachable states(ARDCs) = ",
+		ardcStr);
+  (void)fprintf(vis_stdout, "%-30s%10d\n", "BDD size = ",
+		Fsm_ArdcBddSizeOfOverApproximateReachableStates(fsm));
+  (void)fprintf(vis_stdout, "%-30s%10g\n", "analysis time = ",
+		(double)elapseTime / 1000.0);
+  switch (FsmReadReachabilityOverApproxComputationStatus(fsm)) {
+  case Fsm_Ardc_NotConverged_c :
+    (void) fprintf(vis_stdout, "%-30s%10s\n", "reachability status = ",
+		   "not converged(invalid)");
+    break;
+  case Fsm_Ardc_Valid_c :
+    (void) fprintf(vis_stdout, "%-30s%10s\n", "reachability status = ",
+		   "not converged(valid)");
+    break;
+  case Fsm_Ardc_Converged_c :
+    (void) fprintf(vis_stdout, "%-30s%10s\n", "reachability status = ",
+		   "converged");
+    break;
+  case Fsm_Ardc_Exact_c :
+    (void) fprintf(vis_stdout, "%-30s%10s\n", "reachability status = ",
+		   "exact");
+    break;
+  default :
+    break;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Reads ARDC verbosity option.]
+
+  Description [Reads ARDC verbosity option.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Fsm_ArdcReadVerbosity(void)
+{
+  char *flagValue;
+  int verbosity = 0;
+
+  flagValue = Cmd_FlagReadByName("ardc_verbosity");
+  if (flagValue != NIL(char))
+    sscanf(flagValue, "%d", &verbosity);
+  return(verbosity);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions					     */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Check if each conjunct is contained in the invariant.]
+
+  Description [Check if each conjunct is contained in the invariant.]
+
+  SideEffects []
+
+  SeeAlso []
+
+******************************************************************************/
+int
+FsmArdcCheckInvariant(Fsm_Fsm_t *fsm, array_t *invarStates)
+{
+  array_t *overApproxArray;
+  mdd_t *conjunct;
+  int i, j;
+  mdd_t *invariant;
+
+  overApproxArray = Fsm_ArdcComputeOverApproximateReachableStates(fsm,
+    0, 0, 0, 0, 0, 0, 0, 0, NIL(Fsm_ArdcOptions_t));
+
+  /* for each invariant check if the over approx holds */
+  arrayForEachItem(mdd_t *, invarStates, i, invariant) {
+    arrayForEachItem(mdd_t *, overApproxArray, j, conjunct) {
+      if (conjunct == NIL(mdd_t))
+	continue;
+      if (!mdd_lequal(conjunct, invariant, 1, 1))
+	return 0;
+    }
+  }
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints ARDC options currently in use.]
+
+  Description [Prints ARDC options currently in use.]
+
+  SideEffects []
+
+  SeeAlso []
+
+******************************************************************************/
+void
+FsmArdcPrintOptions(void)
+{
+  Fsm_ArdcOptions_t	options;
+  char			dummy[31];
+
+  Fsm_ArdcGetDefaultOptions(&options);
+
+  switch (options.traversalMethod) {
+  case Fsm_Ardc_Traversal_Mbm_c :
+    sprintf(dummy, "MBM");
+    break;
+  case Fsm_Ardc_Traversal_Rfbf_c :
+    sprintf(dummy, "RFBF");
+    break;
+  case Fsm_Ardc_Traversal_Tfbf_c :
+    sprintf(dummy, "TFBF");
+    break;
+  case Fsm_Ardc_Traversal_Tmbm_c :
+    sprintf(dummy, "TMBM");
+    break;
+  case Fsm_Ardc_Traversal_Lmbm_c :
+    sprintf(dummy, "LMBM");
+    break;
+  case Fsm_Ardc_Traversal_Tlmbm_c :
+    sprintf(dummy, "TLMBM");
+    break;
+  case Fsm_Ardc_Traversal_Simple_c :
+    sprintf(dummy, "SIMPLE");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "ARDC: ardc_traversal_method = %d (%s)\n",
+	  options.traversalMethod, dummy);
+  fprintf(vis_stdout, "ARDC: ardc_group_size = %d\n", options.groupSize);
+  fprintf(vis_stdout, "ARDC: ardc_affinity_factor = %f\n",
+	  options.affinityFactor);
+  fprintf(vis_stdout, "ARDC: ardc_max_iteration = %d\n", options.maxIteration);
+  switch (options.constrainTarget) {
+  case Fsm_Ardc_Constrain_Tr_c :
+    sprintf(dummy, "transition relation");
+    break;
+  case Fsm_Ardc_Constrain_Initial_c :
+    sprintf(dummy, "initial");
+    break;
+  case Fsm_Ardc_Constrain_Both_c :
+    sprintf(dummy, "both");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "ARDC: ardc_constrain_target = %d (%s)\n",
+	  options.constrainTarget, dummy);
+  switch (options.constrainMethod) {
+  case Img_Restrict_c :
+    sprintf(dummy, "restrict");
+    break;
+  case Img_Constrain_c :
+    sprintf(dummy, "constrain");
+    break;
+  case Img_Compact_c :
+    sprintf(dummy, "compact");
+    break;
+  case Img_Squeeze_c :
+    sprintf(dummy, "squeeze");
+    break;
+  case Img_And_c :
+    sprintf(dummy, "and");
+    break;
+  case Img_DefaultMinimizeMethod_c :
+    sprintf(dummy, "restrict");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "ARDC: ardc_constrain_method = %d (%s)\n",
+	  options.constrainMethod, dummy);
+  if (options.constrainReorderFlag)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "ARDC: ardc_constrain_reorder = %s\n", dummy);
+  if (options.decomposeFlag)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "ARDC: ardc_decompose_flag = %s\n", dummy);
+  switch (options.abstractPseudoInput) {
+  case Fsm_Ardc_Abst_Ppi_No_c :
+    sprintf(dummy, "no");
+    break;
+  case Fsm_Ardc_Abst_Ppi_Before_Image_c :
+    sprintf(dummy, "before image");
+    break;
+  case Fsm_Ardc_Abst_Ppi_After_Image_c :
+    sprintf(dummy, "after image");
+    break;
+  case Fsm_Ardc_Abst_Ppi_At_End_c :
+    sprintf(dummy, "at end");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "ARDC: ardc_abstract_pseudo_input = %d (%s)\n",
+	  options.abstractPseudoInput, dummy);
+  if (options.projectedInitialFlag)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "ARDC: ardc_projected_initial_flag = %s\n", dummy);
+  if (options.ardcImageMethod == Img_Monolithic_c)
+    sprintf(dummy, "monolithic");
+  else if (options.ardcImageMethod == Img_Tfm_c)
+    sprintf(dummy, "tfm");
+  else if (options.ardcImageMethod == Img_Hybrid_c)
+    sprintf(dummy, "hybrid");
+  else if (options.ardcImageMethod == Img_Mlp_c)
+    sprintf(dummy, "mlp");
+  else
+    sprintf(dummy, "iwls95");
+  fprintf(vis_stdout, "ARDC: ardc_image_method = %s\n", dummy);
+  if (options.useHighDensity)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "ARDC: ardc_use_high_density = %s\n", dummy);
+  if (options.reorderPtrFlag)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "ARDC: ardc_reorder_ptr = %s\n", dummy);
+  if (options.faninConstrainMode == 0)
+    sprintf(dummy, "only fanin");
+  else
+    sprintf(dummy, "fanin + itself");
+  fprintf(vis_stdout, "ARDC: ardc_fanin_constrain_mode = %d (%s)\n",
+	  options.faninConstrainMode, dummy);
+  if (options.createPseudoVarMode == 0)
+    sprintf(dummy, "with exact support");
+  else if (options.createPseudoVarMode == 1)
+    sprintf(dummy, "all the other submachines");
+  else
+    sprintf(dummy, "only fanin submachines");
+  fprintf(vis_stdout, "ARDC: ardc_create_pseudo_var_mode = %d (%s)\n",
+	  options.createPseudoVarMode, dummy);
+  if (options.lmbmInitialStatesMode == 0)
+    sprintf(dummy, "given initial");
+  else if (options.lmbmInitialStatesMode == 1)
+    sprintf(dummy, "reached set");
+  else
+    sprintf(dummy, "frontier set");
+  fprintf(vis_stdout, "ARDC: ardc_lmbm_initial_mode = %d (%s)\n",
+	  options.lmbmInitialStatesMode, dummy);
+  if (options.mbmReuseTrFlag)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "ARDC: ardc_mbm_reuse_tr = %s\n", dummy);
+  if (options.readGroupFile)
+    fprintf(vis_stdout, "ARDC: ardc_read_group = %s\n", options.readGroupFile);
+  else
+    fprintf(vis_stdout, "ARDC: ardc_read_group = nil\n");
+  if (options.writeGroupFile) {
+    fprintf(vis_stdout, "ARDC: ardc_write_group = %s\n",
+	    options.writeGroupFile);
+  } else
+    fprintf(vis_stdout, "ARDC: ardc_write_group = nil\n");
+  fprintf(vis_stdout, "ARDC: ardc_verbosity = %d\n", options.verbosity);
+  fprintf(vis_stdout,
+	  "See help page on print_ardc_options for setting these options\n");
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints BDDS of approximate reachable states of an FSM.]
+
+  Description [Prints BDDS of approximate reachable states of an FSM.]
+
+  SideEffects []
+
+  SeeAlso []
+
+******************************************************************************/
+void
+FsmArdcPrintOverApproximateReachableStates(Fsm_Fsm_t *fsm)
+{
+  mdd_t	*appr;
+  array_t	*mddIdArr;
+
+  if (!Fsm_FsmTestIsOverApproximateReachabilityDone(fsm)) {
+  fprintf(vis_stdout, "** ardc warning : no approximate reachable states **\n");
+    return;
+  }
+  appr = Fsm_ArdcGetMddOfOverApproximateReachableStates(fsm);
+  mddIdArr = Fsm_FsmReadPresentStateVars(fsm);
+  PrintBddWithName(fsm, mddIdArr, appr);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Prints BDDS of exact reachable states of an FSM.]
+
+  Description [Prints BDDS of exact reachable states of an FSM.]
+
+  SideEffects []
+
+  SeeAlso []
+
+******************************************************************************/
+void
+FsmArdcPrintExactReachableStates(Fsm_Fsm_t *fsm)
+{
+  mdd_t	*reachableStates;
+  array_t	*mddIdArr;
+
+  if (!Fsm_FsmTestIsReachabilityDone(fsm)) {
+    fprintf(vis_stdout, "** ardc warning : no reachable states **\n");
+    return;
+  }
+  reachableStates = Fsm_FsmReadReachableStates(fsm);
+  mddIdArr = Fsm_FsmReadPresentStateVars(fsm);
+  PrintBddWithName(fsm, mddIdArr, reachableStates);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints BDDs of a node.]
+
+  Description [Prints BDDs of a node.]
+
+  SideEffects []
+
+  SeeAlso []
+
+******************************************************************************/
+void
+FsmArdcPrintBddOfNode(Fsm_Fsm_t *fsm, mdd_t *node)
+{
+  PrintBddWithName(fsm, NIL(array_t), node);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints array of array of integer.]
+
+  Description [Prints array of array of integer.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+FsmArdcPrintArrayOfArrayInt(array_t *arrayOfArray)
+{
+  int		i, j, n;
+  array_t	*array;
+
+  for (i = 0; i < array_n(arrayOfArray); i++) {
+    array = array_fetch(array_t *, arrayOfArray, i);
+    fprintf(vis_stdout, "array[%d] =", i);
+    for (j = 0; j < array_n(array); j++) {
+      n = array_fetch(int, array, j);
+      fprintf(vis_stdout, " %d", n);
+    }
+    fprintf(vis_stdout, "\n");
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a set Boolean value related ARDC computation.]
+
+  Description [Returns a set Boolean value related ARDC computation.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+FsmGetArdcSetBooleanValue(char *string, boolean defaultValue)
+{
+  char		*flagValue;
+  boolean	value = defaultValue;
+
+  flagValue = Cmd_FlagReadByName(string);
+  if (flagValue != NIL(char)) {
+    if (strcmp(flagValue, "yes") == 0)
+      value = TRUE;
+    else if (strcmp(flagValue, "no") == 0)
+      value = FALSE;
+    else {
+      fprintf(vis_stderr,
+	      "** ardc error : invalid value %s for %s[yes/no]. **\n",
+	      flagValue, string);
+    }
+  }
+
+  return(value);
+}
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions					     */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sorts subfsms so that a subfsm with smaller fanins comes first.]
+
+  Description [Sorts subfsms so that a subfsm with smaller fanins comes first.]
+
+  SideEffects []
+
+  SeeAlso []
+
+******************************************************************************/
+static void
+SortSubFsmsForApproximateTraversal(array_t **subFsmArray,
+				   array_t **fanInsIndexArray,
+				   array_t **fanOutsIndexArray,
+				   int verbosityLevel)
+{
+  int		n = array_n(*subFsmArray);
+  array_t	*newSubFsmArray;
+  array_t	*newFanInsIndexArray;
+  array_t	*newFanOutsIndexArray;
+  int		i, j, smallest;
+  Fsm_Fsm_t	*subFsm;
+  array_t	*fanIns, *fanOuts;
+  Fsm_Fsm_t	*smallestSubFsm = NIL(Fsm_Fsm_t);
+  array_t	*smallestFanIns = NIL(array_t);
+  array_t	*smallestFanOuts = NIL(array_t);
+  int		*flag;
+  int		*nFanIns, *nFanOuts;
+  int		fanIn, fanOut;
+  int		*order = NIL(int);
+  int		*target;
+
+  newSubFsmArray = array_alloc(Fsm_Fsm_t *, 0);
+  newFanInsIndexArray = array_alloc(array_t *, 0);
+  newFanOutsIndexArray = array_alloc(array_t *, 0);
+
+  flag = ALLOC(int, n);
+  (void)memset((void *)flag, 0, sizeof(int) * n);
+
+  if (verbosityLevel > 1)
+    order = ALLOC(int, n);
+  target = ALLOC(int, n);
+  nFanIns = ALLOC(int, n);
+  nFanOuts = ALLOC(int, n);
+  for (i = 0; i < n; i++) {
+    fanIns = array_fetch(array_t *, *fanInsIndexArray, i);
+    nFanIns[i] = array_n(fanIns);
+    fanOuts = array_fetch(array_t *, *fanOutsIndexArray, i);
+    nFanOuts[i] = array_n(fanOuts);
+  }
+
+  for (i = 0; i < n; i++) {
+    /*
+    ** finds a submachine which has the smallest number of fanins
+    ** if tie, use number of fanouts
+    */
+    smallest = -1;
+    for (j = 0; j < n; j++) {
+      if (flag[j])
+	continue;
+      subFsm = array_fetch(Fsm_Fsm_t *, *subFsmArray, j);
+      fanIns = array_fetch(array_t *, *fanInsIndexArray, j);
+      fanOuts = array_fetch(array_t *, *fanOutsIndexArray, j);
+      if (smallest == -1 || nFanIns[j] < nFanIns[smallest] ||
+	  (nFanIns[j] == nFanIns[smallest] &&
+	   nFanOuts[j] < nFanOuts[smallest])) {
+	smallest = j;
+	smallestSubFsm = subFsm;
+	smallestFanIns = fanIns;
+	smallestFanOuts = fanOuts;
+      }
+    }
+    target[smallest] = i;
+    if (verbosityLevel > 1)
+      order[i] = smallest;
+    flag[smallest] = 1;
+    array_insert_last(Fsm_Fsm_t *, newSubFsmArray, smallestSubFsm);
+    array_insert_last(array_t *, newFanInsIndexArray, smallestFanIns);
+    array_insert_last(array_t *, newFanOutsIndexArray, smallestFanOuts);
+    /*
+    ** decrease number of fanouts by 1 from each submachine
+    ** which is not chosen yet
+    */
+    for (j = 0; j < array_n(smallestFanIns); j++) {
+      fanIn = array_fetch(int, smallestFanIns, j);
+      if (flag[fanIn])
+	continue;
+      nFanOuts[fanIn]--;
+    }
+    /*
+    ** decrease number of fanins by 1 from each submachine
+    ** which is not chosen yet
+    */
+    for (j = 0; j < array_n(smallestFanOuts); j++) {
+      fanOut = array_fetch(int, smallestFanOuts, j);
+      if (flag[fanOut])
+	continue;
+      nFanIns[fanOut]--;
+    }
+  }
+
+  /* make new fanins & fanouts  index array according to new order */
+  for (i = 0; i < n; i++) {
+    fanIns = array_fetch(array_t *, newFanInsIndexArray, i);
+    for (j = 0; j < array_n(fanIns); j++) {
+      fanIn = array_fetch(int, fanIns, j);
+      array_insert(int, fanIns, j, target[fanIn]);
+    }
+    fanOuts = array_fetch(array_t *, newFanOutsIndexArray, i);
+    for (j = 0; j < array_n(fanOuts); j++) {
+      fanOut = array_fetch(int, fanOuts, j);
+      array_insert(int, fanOuts, j, target[fanOut]);
+    }
+  }
+
+  if (verbosityLevel > 1) {
+    int	k;
+
+    fprintf(vis_stdout, "=== sorted sub-fsm order ===\n");
+    for (i = 0; i < n; i++)
+      fprintf(vis_stdout, " %d", order[i]);
+    fprintf(vis_stdout, "\n");
+
+    for (i = 0; i < n; i++) {
+      fprintf(vis_stdout, "SUB-FSM [%d]\n", i);
+      fanIns = array_fetch(array_t *, newFanInsIndexArray, i);
+      fanOuts = array_fetch(array_t *, newFanOutsIndexArray, i);
+      fprintf(vis_stdout, "== fanins(%d) :", array_n(fanIns));
+      for (j = 0; j < array_n(fanIns); j++) {
+	k = array_fetch(int, fanIns, j);
+	fprintf(vis_stdout, " %d", k);
+      }
+      fprintf(vis_stdout, "\n");
+      fprintf(vis_stdout, "== fanouts(%d) :", array_n(fanOuts));
+      for (j = 0; j < array_n(fanOuts); j++) {
+	k = array_fetch(int, fanOuts, j);
+	fprintf(vis_stdout, " %d", k);
+      }
+      fprintf(vis_stdout, "\n");
+    }
+  }
+
+  FREE(flag);
+  FREE(nFanIns);
+  FREE(nFanOuts);
+  if (verbosityLevel > 1)
+    FREE(order);
+  FREE(target);
+  array_free(*subFsmArray);
+  array_free(*fanInsIndexArray);
+  array_free(*fanOutsIndexArray);
+  *subFsmArray = newSubFsmArray;
+  *fanInsIndexArray = newFanInsIndexArray;
+  *fanOutsIndexArray = newFanOutsIndexArray;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes an upper bound to the reachable states of an FSM
+  by MBM.]
+
+  Description [Computes an upper bound to the reachable states of an
+  FSM by MBM or LMBM. This computation proceeds in an event-driven
+  manner. First it computes the reachable states of all submachines,
+  then only for those submachines such that any of their fanin
+  submachine's reachable states have changed. It recomputes reachable
+  states by constraining the transition relation with respect to the
+  reached states of all fanin submachines. This is iterated until it
+  converges. The basic algorithm for MBM is almost same as the one in Hyunwoo
+  Cho's paper in TCAD96, except as noted below.
+  0. Cho's algorithm uses transition function for image computation,
+     whereas we use either the transition function or the transition relation
+     depending on the image computation method.
+  1. constrainTarget
+     In Cho's papers, there are two versions of algorithms: one is constraining
+     transition relation, the other is initial states, so this function
+     includes these two as well as the case of both.
+     0) Fsm_Ardc_Constrain_Tr_c      : constrain transition relation (default).
+     1) Fsm_Ardc_Constrain_Initial_c : constrain initial state.
+     2) Fsm_Ardc_Constrain_Both_c    : constrain both.
+  2. decomposeFlag
+     To perform the above constraining operation, we can make the constraint
+     either conjoined (as single bdd) or decomposed (as array of bdds) from
+     the reachable states of fanin submachines of the current submachine.
+     To have same interface for these two, array of constraints is used.
+  3. dynamic variable reordering
+     In Cho's algorithm, dynamic variable ordering is not allowed, but
+     it is here. Also, refer to 5. (restore-containment).
+  4. abstractPseudoInput
+     To make faster convergence, we can abstract pseudo primary input
+     variables early, but refer to 5. (restore-containment).
+     0) Fsm_Ardc_Abst_Ppi_No_c		 : do not abstract pseudo-input
+					   variables.
+     1) Fsm_Ardc_Abst_Ppi_Before_Image_c : abstract before image computation
+					   (default).
+     2) Fsm_Ardc_Abst_Ppi_After_Image_c  : abstract after image computation.
+     3) Fsm_Ardc_Abst_Ppi_At_End_c       : abstract at the end of approximate
+					   traversal.
+  5. restore-constainment
+     Due to 3 (dynamic variable reordering) and 4 (abstractPseudoInput),
+     current reachable states may not be a subset of previous reachable
+     states. In this case, we correct current reachable state to the
+     intersection of current and previous reachable states. But, in FBF,
+     we need to take the union of the two.
+  6. projectedInitialFlag
+     When we do reachability analysis of submachines, initial states of
+     a submachine can be one of the following. In Cho's paper, projected
+     initial states was used.
+     0) FALSE : use original initial states for submachine
+     1) TRUE  : use projected initial states for submachine (default)
+  ]
+
+  SideEffects []
+
+  SeeAlso [ArdcRfbfTraversal ArdcTfbfTraversal ArdcTmbmTraversal
+  ArdcSimpleTraversal]
+
+******************************************************************************/
+static array_t *
+ArdcMbmTraversal(
+  Fsm_Fsm_t *fsm,
+  int nvars,
+  array_t *subFsmArray,
+  array_t *fanInsIndexArray,
+  array_t *fanOutsIndexArray,
+  mdd_t ***subReached /* sub-result for TMBM, pointer of bdd array */,
+  /* The following arguments up to approxFlag are passed for exact
+   * reachability. */
+  int incrementalFlag,
+  int verbosityLevel,
+  int printStep,
+  int depthValue,
+  int shellFlag,
+  int reorderFlag,
+  int reorderThreshold,
+  Fsm_RchType_t approxFlag,
+  Fsm_ArdcOptions_t *options,
+  boolean lfpFlag /* If TRUE, performs LMBM */
+  )
+{
+  mdd_manager		*mddManager;
+  int			i, n = array_n(subFsmArray);
+  int			*traverse;
+  mdd_t			**reached, **constraint;
+  mdd_t			**oldReached;
+  mdd_t			**frontier;
+  int			converged = 0;
+  Fsm_Fsm_t		**subFsm;
+  array_t		*fans;
+  mdd_t			*tmp;
+  int			iteration = 0;
+  mdd_t			**initial = NIL(mdd_t *);
+  array_t		*reachedArray = array_alloc(mdd_t *, 0);
+  array_t		*faninConstrainArray;
+  Img_ImageInfo_t	*imageInfo = NIL(Img_ImageInfo_t);
+  int			dynStatus;
+  bdd_reorder_type_t	dynMethod;
+  boolean		restoreContainmentFlag;
+  boolean		reuseTrFlag = FALSE;
+			/* If set, just update the transition relation
+			   without copying the original transition relation */
+  boolean		reused = FALSE;
+  boolean		duplicate;
+  boolean		tmpReorderPtrFlag;
+  int			nConstrainOps = 0;
+  long			tImgComps = 0;
+  long			tConstrainOps = 0;
+  long			tRestoreContainment = 0;
+  long			tAbstractVars = 0;
+  long			tBuildTr = 0;
+  long			initialTime = 0, finalTime;
+  int			maxIteration = options->maxIteration;
+  int			constrainTarget = options->constrainTarget;
+  boolean		decomposeFlag = options->decomposeFlag;
+  int			abstractPseudoInput = options->abstractPseudoInput;
+  Img_MinimizeType	constrainMethod = options->constrainMethod;
+  boolean		projectedInitialFlag = options->projectedInitialFlag;
+  int			ardcVerbosity = options->verbosity;
+  boolean		constrainReorderFlag = options->constrainReorderFlag;
+  boolean		reorderPtrFlag = options->reorderPtrFlag;
+  int			faninConstrainMode = options->faninConstrainMode;
+  int			lmbmInitialStatesMode = options->lmbmInitialStatesMode;
+
+  reuseTrFlag = FsmGetArdcSetBooleanValue("ardc_mbm_reuse_tr", reuseTrFlag);
+  if (reuseTrFlag && lfpFlag) {
+    /* This is to use the i-th constrained transition relation in
+     * the (i+1)-th iteration, instead of the original transition relation.
+     * Therefore, the i-th constraint should be a superset of the (i+1)-th. */
+    fprintf(vis_stderr,
+	    "** ardc error : can't reuse transition relation in LMBM. **\n");
+    reuseTrFlag = FALSE;
+  }
+
+  Img_ResetNumberOfImageComputation(Img_Forward_c);
+
+  reached = ALLOC(mdd_t *, n);
+  constraint = ALLOC(mdd_t *, n);
+  traverse = ALLOC(int, n);	/* array used for scheduling */
+  subFsm = ALLOC(Fsm_Fsm_t *, n);
+  oldReached = ALLOC(mdd_t *, n);
+
+  mddManager = Fsm_FsmReadMddManager(fsm);
+  for (i = 0; i < n; i++) {
+    subFsm[i] = array_fetch(Fsm_Fsm_t *, subFsmArray, i);
+    oldReached[i] = NIL(mdd_t);
+  }
+
+  /* Set up. */
+  if (lfpFlag) {		/* LMBM */
+    initial = ALLOC(mdd_t *, n);
+    for (i = 0; i < n; i++)
+      initial[i] = Fsm_FsmComputeInitialStates(subFsm[i]);
+    if (lmbmInitialStatesMode >= 1)	/* restart from frontier states */
+      frontier = ALLOC(mdd_t *, n);
+    else
+      frontier = NIL(mdd_t *);
+
+    for (i = 0; i < n; i++) {
+      reached[i] = mdd_dup(initial[i]);
+      constraint[i] = mdd_dup(initial[i]);
+      traverse[i] = 1;
+      if (frontier)
+	frontier[i] = NIL(mdd_t);
+    }
+  } else {			/* MBM */
+    for (i = 0; i < n; i++) {
+      reached[i] = mdd_one(mddManager);
+      constraint[i] = mdd_one(mddManager);
+      traverse[i] = 1;
+    }
+
+    if (constrainTarget == Fsm_Ardc_Constrain_Initial_c ||
+	constrainTarget == Fsm_Ardc_Constrain_Both_c) {
+      initial = ALLOC(mdd_t *, n);
+      for (i = 0; i < n; i++)
+	initial[i] = Fsm_FsmComputeInitialStates(subFsm[i]);
+    }
+
+    frontier = NIL(mdd_t *);
+  }
+
+  /* Set the flag for containment restoration according to the options. */
+  if (constrainMethod == Img_Constrain_c &&
+      constrainReorderFlag == FALSE &&
+      abstractPseudoInput == Fsm_Ardc_Abst_Ppi_No_c) {
+    restoreContainmentFlag = FALSE;
+  } else
+    restoreContainmentFlag = TRUE;
+
+  /* Compute fixpoint. */
+  do {
+    converged = 1;
+    for (i = 0; i < n; i++) {
+      if (!traverse[i])
+	continue;
+      if (ardcVerbosity > 1)
+	fprintf(vis_stdout, "--- sub fsm [%d] ---\n", i);
+      if (oldReached[i])
+	mdd_free(oldReached[i]);
+      oldReached[i] = reached[i];
+      /* Build constraint array. */
+      faninConstrainArray = array_alloc(mdd_t *, 0);
+      fans = array_fetch(array_t *, fanInsIndexArray, i);
+      ComputeFaninConstrainArray(faninConstrainArray, constraint,
+				 i, fans, decomposeFlag, faninConstrainMode);
+      /* Build constrained transition relation. */
+      dynStatus = bdd_reordering_status(mddManager, &dynMethod);
+      if (dynStatus != 0 && constrainReorderFlag == 0)
+	bdd_dynamic_reordering_disable(mddManager);
+      if (ardcVerbosity > 0)
+	initialTime = util_cpu_time();
+      imageInfo = Fsm_FsmReadOrCreateImageInfo(subFsm[i], 0, 1); /* forward */
+      if (ardcVerbosity > 0) {
+	finalTime = util_cpu_time();
+	tBuildTr += finalTime - initialTime;
+      }
+      /* Minimize the transition relation of the current submachine w.r.t.
+       * the reached set of its fanin submachines.
+       */
+      if (constrainTarget != Fsm_Ardc_Constrain_Initial_c) {
+	int saveStatus = Img_ReadPrintMinimizeStatus(imageInfo);
+	if (ardcVerbosity > 2)
+	  Img_SetPrintMinimizeStatus(imageInfo, 2);
+	else if (ardcVerbosity > 0)
+	  Img_SetPrintMinimizeStatus(imageInfo, 1);
+	else
+	  Img_SetPrintMinimizeStatus(imageInfo, 0);
+	if (reuseTrFlag) {
+	  if (reused)
+	    duplicate = FALSE;
+	  else
+	    duplicate = TRUE;
+	} else
+	  duplicate = TRUE;
+	if (reorderPtrFlag &&
+	    abstractPseudoInput != Fsm_Ardc_Abst_Ppi_Before_Image_c) {
+	  tmpReorderPtrFlag = 1;
+	} else
+	  tmpReorderPtrFlag = 0;
+	if (ardcVerbosity > 0)
+	  initialTime = util_cpu_time();
+	MinimizeTransitionRelationWithFaninConstraint(imageInfo,
+		faninConstrainArray, constrainMethod, tmpReorderPtrFlag,
+		duplicate);
+	if (ardcVerbosity > 0) {
+	  finalTime = util_cpu_time();
+	  tConstrainOps += finalTime - initialTime;
+	}
+	Img_SetPrintMinimizeStatus(imageInfo, saveStatus);
+      }
+      if (constrainTarget != Fsm_Ardc_Constrain_Tr_c) {
+	ComputeConstrainedInitialStates(subFsm[i], faninConstrainArray,
+					constrainMethod);
+      }
+      nConstrainOps++;
+      mdd_array_free(faninConstrainArray);
+      /* Restore dynamic reordering options if they had been changed. */
+      if (dynStatus != 0 && constrainReorderFlag == 0) {
+	bdd_dynamic_reordering(mddManager, dynMethod,
+			       BDD_REORDER_VERBOSITY_DEFAULT);
+      }
+      /* Quantify pseudo-input variables from the transition relation. */
+      if (abstractPseudoInput == Fsm_Ardc_Abst_Ppi_Before_Image_c) {
+	int saveStatus = Img_ReadPrintMinimizeStatus(imageInfo);
+	if (ardcVerbosity > 2)
+	  Img_SetPrintMinimizeStatus(imageInfo, 2);
+	else if (ardcVerbosity > 0)
+	  Img_SetPrintMinimizeStatus(imageInfo, 1);
+	else
+	  Img_SetPrintMinimizeStatus(imageInfo, 0);
+	if (ardcVerbosity > 0)
+	  initialTime = util_cpu_time();
+	Img_AbstractTransitionRelation(imageInfo,
+	  subFsm[i]->fsmData.pseudoInputBddVars,
+	  subFsm[i]->fsmData.pseudoInputCube, Img_Forward_c);
+	if (reorderPtrFlag)
+	  Img_ReorderPartitionedTransitionRelation(imageInfo, Img_Forward_c);
+	if (ardcVerbosity > 0) {
+	  finalTime = util_cpu_time();
+	  tAbstractVars += finalTime - initialTime;
+	}
+	Img_SetPrintMinimizeStatus(imageInfo, saveStatus);
+      }
+      if (lfpFlag && lmbmInitialStatesMode > 0 && iteration > 0) {
+	/* Update the initial states to either reached or frontier. */
+	FsmSetReachabilityApproxComputationStatus(subFsm[i], Fsm_Rch_Under_c);
+	mdd_free(subFsm[i]->reachabilityInfo.initialStates);
+	if (lmbmInitialStatesMode == 1)
+	  subFsm[i]->reachabilityInfo.initialStates = mdd_dup(reached[i]);
+	else
+	  subFsm[i]->reachabilityInfo.initialStates = mdd_dup(frontier[i]);
+      } else {
+	/* Reset the reachable states for a new reachability. */
+	if (subFsm[i]->reachabilityInfo.reachableStates) {
+	  mdd_free(subFsm[i]->reachabilityInfo.reachableStates);
+	  subFsm[i]->reachabilityInfo.reachableStates = NIL(mdd_t);
+	}
+	subFsm[i]->reachabilityInfo.depth = 0;
+      }
+      /* Traverse this submachine. */
+      if (ardcVerbosity > 0)
+	initialTime = util_cpu_time();
+      reached[i] = Fsm_FsmComputeReachableStates(subFsm[i],
+		incrementalFlag, verbosityLevel, printStep, depthValue,
+		shellFlag, reorderFlag, reorderThreshold,
+		approxFlag, 0, 0, NIL(array_t), FALSE, NIL(array_t));
+      if (Img_ImageInfoObtainMethodType(imageInfo) == Img_Tfm_c ||
+	  Img_ImageInfoObtainMethodType(imageInfo) == Img_Hybrid_c) {
+	Img_TfmFlushCache(imageInfo, FALSE);
+      }
+      if (ardcVerbosity > 0) {
+	finalTime = util_cpu_time();
+	tImgComps += finalTime - initialTime;
+      }
+      /* Compute the frontier for LMBM. */
+      if (lfpFlag && lmbmInitialStatesMode > 0) {
+	if (lmbmInitialStatesMode >= 1) {
+	  if (iteration == 0)
+	    frontier[i] = mdd_dup(reached[i]);
+	  else {
+	    mdd_t	*fromLowerBound;
+
+	    fromLowerBound = mdd_and(reached[i], oldReached[i], 1, 0);
+	    tmp = reached[i];
+	    reached[i] = mdd_or(oldReached[i], tmp, 1, 1);
+	    mdd_free(tmp);
+	    mdd_free(frontier[i]);
+	    if (lmbmInitialStatesMode == 2) {
+	      frontier[i] = bdd_between(fromLowerBound, reached[i]);
+	      mdd_free(fromLowerBound);
+	    } else
+	      frontier[i] = fromLowerBound;
+	  }
+	}
+	if (iteration > 0) {
+	  mdd_free(subFsm[i]->reachabilityInfo.initialStates);
+	  subFsm[i]->reachabilityInfo.initialStates = mdd_dup(initial[i]);
+	}
+      }
+      /* Restore the original transition relation. */
+      if (constrainTarget != Fsm_Ardc_Constrain_Initial_c) {
+	if (!reuseTrFlag)
+	  Img_RestoreTransitionRelation(imageInfo, Img_Forward_c);
+      }
+      /* Quantify the pseudo-input variables from reached. */
+      if (abstractPseudoInput == Fsm_Ardc_Abst_Ppi_After_Image_c) {
+	if (ardcVerbosity > 0)
+	  initialTime = util_cpu_time();
+	if (n > 1) {
+	  tmp = reached[i];
+	  reached[i] = QuantifyVariables(reached[i],
+				subFsm[i]->fsmData.pseudoInputBddVars,
+				subFsm[i]->fsmData.pseudoInputCube);
+	  mdd_free(tmp);
+	}
+	if (ardcVerbosity > 0) {
+	  finalTime = util_cpu_time();
+	  tAbstractVars += finalTime - initialTime;
+	}
+      }
+
+      mdd_free(constraint[i]);
+      constraint[i] = mdd_dup(reached[i]);
+      /* Update traversal schedule and possibly restore containment. */
+      traverse[i] = 0;
+      if (!mdd_equal(oldReached[i], reached[i])) {
+	if (ardcVerbosity > 2) {
+	  double	r1, r2;
+
+	  r1 = mdd_count_onset(mddManager, reached[i],
+			       subFsm[i]->fsmData.presentStateVars);
+	  r2 = mdd_count_onset(mddManager, oldReached[i],
+			       subFsm[i]->fsmData.presentStateVars);
+	  fprintf(vis_stdout, "oldReached = %g, reached = %g\n", r2, r1);
+	}
+
+	/* Restore-containment operation. */
+	if (restoreContainmentFlag) {
+	  if (ardcVerbosity > 0)
+	    initialTime = util_cpu_time();
+	  if (lfpFlag) {	/* LMBM */
+	    if (mdd_lequal(oldReached[i], reached[i], 1, 1)) {
+	      /* Containment OK. */
+	      fans = array_fetch(array_t *, fanOutsIndexArray, i);
+	      UpdateMbmEventSchedule(subFsm, fans, traverse, lfpFlag);
+	    } else {
+	      /* Restoration needed. */
+	      if (ardcVerbosity > 1) {
+		fprintf(vis_stdout,
+    "** ardc info: reached is not superset of oldReached in subFsm[%d] **\n",
+			i);
+	      }
+	      mdd_free(reached[i]);
+	      reached[i] = mdd_or(oldReached[i],
+			subFsm[i]->reachabilityInfo.reachableStates, 1, 1);
+	      mdd_free(subFsm[i]->reachabilityInfo.reachableStates);
+	      subFsm[i]->reachabilityInfo.reachableStates = mdd_dup(reached[i]);
+	      mdd_free(constraint[i]);
+	      constraint[i] = mdd_dup(reached[i]);
+	      if (!mdd_equal(oldReached[i], reached[i])) {
+		fans = array_fetch(array_t *, fanOutsIndexArray, i);
+		UpdateMbmEventSchedule(subFsm, fans, traverse, lfpFlag);
+	      }
+	    }
+	  } else {		/* MBM */
+	    if (!mdd_lequal(reached[i], oldReached[i], 1, 1)) {
+	      /* Restoration needed. */
+	      if (ardcVerbosity > 1) {
+		fprintf(vis_stdout,
+    "** ardc info: reached is not subset of oldReached in subFsm[%d] **\n", i);
+	      }
+	      mdd_free(reached[i]);
+	      reached[i] = mdd_and(oldReached[i],
+			subFsm[i]->reachabilityInfo.reachableStates, 1, 1);
+	      mdd_free(subFsm[i]->reachabilityInfo.reachableStates);
+	      subFsm[i]->reachabilityInfo.reachableStates = mdd_dup(reached[i]);
+	      mdd_free(constraint[i]);
+	      constraint[i] = mdd_dup(reached[i]);
+	      if (!mdd_equal(oldReached[i], reached[i])) {
+		fans = array_fetch(array_t *, fanOutsIndexArray, i);
+		UpdateMbmEventSchedule(subFsm, fans, traverse, lfpFlag);
+	      }
+	    } else {
+	      /* Containment OK. */
+	      fans = array_fetch(array_t *, fanOutsIndexArray, i);
+	      UpdateMbmEventSchedule(subFsm, fans, traverse, lfpFlag);
+	    }
+	  }
+	  if (ardcVerbosity > 0) {
+	    finalTime = util_cpu_time();
+	    tRestoreContainment += finalTime - initialTime;
+	  }
+	} else {		/* no containment restoration needed */
+	  fans = array_fetch(array_t *, fanOutsIndexArray, i);
+	  UpdateMbmEventSchedule(subFsm, fans, traverse, lfpFlag);
+	}
+      }
+    }
+    /* Check for convergence. */
+    for (i = 0; i < n; i++) {
+      if (traverse[i]) {
+	converged = 0;
+	break;
+      }
+    }
+    iteration++;
+    if (ardcVerbosity > 0) {
+      boolean	supportCheckFlag = FALSE;
+
+      /* Print the current reached states and check the supports. */
+      if (projectedInitialFlag ||
+	  abstractPseudoInput == Fsm_Ardc_Abst_Ppi_Before_Image_c) {
+	supportCheckFlag = TRUE;
+      }
+      if (lfpFlag) {
+	PrintCurrentReachedStates(mddManager, subFsm, reached,
+				  Fsm_Ardc_Traversal_Lmbm_c,
+				  n, iteration, nvars, ardcVerbosity,
+				  supportCheckFlag);
+      } else {
+	PrintCurrentReachedStates(mddManager, subFsm, reached,
+				  Fsm_Ardc_Traversal_Mbm_c,
+				  n, iteration, nvars, ardcVerbosity,
+				  supportCheckFlag);
+      }
+    }
+
+    if (iteration == maxIteration)
+      break;
+  } while (!converged);
+
+  /* Restore the original transtion relation. */
+  if (reuseTrFlag) {
+    if (constrainTarget != Fsm_Ardc_Constrain_Initial_c)
+      Img_RestoreTransitionRelation(imageInfo, Img_Forward_c);
+  }
+
+  if (ardcVerbosity > 0) {
+    if (lfpFlag)
+      fprintf(vis_stdout, "LMBM : total iterations %d\n", iteration);
+    else
+      fprintf(vis_stdout, "MBM : total iterations %d\n", iteration);
+  }
+
+  /* Reset the initial states to the original. */
+  if (constrainTarget == Fsm_Ardc_Constrain_Initial_c ||
+      constrainTarget == Fsm_Ardc_Constrain_Both_c || lfpFlag) {
+    for (i = 0; i < n; i++) {
+      mdd_free(subFsm[i]->reachabilityInfo.initialStates);
+      subFsm[i]->reachabilityInfo.initialStates = initial[i];
+    }
+    FREE(initial);
+  }
+
+  /* Quantify the pseudo-input variables from reached. */
+  if (abstractPseudoInput == Fsm_Ardc_Abst_Ppi_At_End_c) {
+    if (ardcVerbosity > 0)
+      initialTime = util_cpu_time();
+    for (i = 0; i < n; i++) {
+      tmp = reached[i];
+      reached[i] = QuantifyVariables(reached[i],
+				subFsm[i]->fsmData.pseudoInputBddVars,
+				subFsm[i]->fsmData.pseudoInputCube);
+      mdd_free(tmp);
+    }
+    if (ardcVerbosity > 0) {
+      finalTime = util_cpu_time();
+      tAbstractVars += finalTime - initialTime;
+    }
+  }
+
+  /* Set the status of current overapproximate reached states. */
+  if (converged)
+    FsmSetReachabilityOverApproxComputationStatus(fsm, Fsm_Ardc_Converged_c);
+  else if (lfpFlag)
+    FsmSetReachabilityOverApproxComputationStatus(fsm, Fsm_Ardc_NotConverged_c);
+  else
+    FsmSetReachabilityOverApproxComputationStatus(fsm, Fsm_Ardc_Valid_c);
+
+  ComputeApproximateReachableStatesArray(mddManager, reachedArray,
+					 reached, subReached, n,
+					 decomposeFlag);
+  /* Clean up. */
+  if (decomposeFlag) {
+    for (i = 0; i < n; i++) {
+      mdd_free(oldReached[i]);
+      mdd_free(constraint[i]);
+    }
+  } else {
+    for (i = 0; i < n; i++) {
+      mdd_free(oldReached[i]);
+      if (subReached == NULL)
+	mdd_free(reached[i]);
+      mdd_free(constraint[i]);
+    }
+  }
+
+  if (subReached)
+    *subReached = reached;
+  else
+    FREE(reached);
+  FREE(traverse);
+  FREE(constraint);
+  FREE(subFsm);
+  FREE(oldReached);
+  if (lfpFlag && lmbmInitialStatesMode >= 1) {/*consistent:from >1 to >=1 C.W*/
+    for (i = 0; i < n; i++) {
+      if (frontier[i])
+	mdd_free(frontier[i]);
+    }
+    FREE(frontier);
+  }
+
+  /* Print final stats. */
+  if (ardcVerbosity > 0) {
+    fprintf(vis_stdout, "%d image computations, %d constrain operations\n",
+	Img_GetNumberOfImageComputation(Img_Forward_c), nConstrainOps);
+    fprintf(vis_stdout,
+	"image computation time = %g, constrain operation time = %g\n",
+	(double)tImgComps / 1000.0, (double)tConstrainOps / 1000.0);
+    fprintf(vis_stdout, "restore-containment time = %g\n",
+	(double)tRestoreContainment / 1000.0);
+    fprintf(vis_stdout, "abstract variables time = %g\n",
+	(double)tAbstractVars / 1000.0);
+    fprintf(vis_stdout, "build TR time = %g\n",
+	(double)tBuildTr / 1000.0);
+  }
+
+  return(reachedArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes an upperbound of an FSM by RFBF.]
+
+  Description [Computes an upperbound of an FSM by RFBF. It first
+  sets all constraints to initial states, then does one image
+  computation, then updates constraints with reached states. This is
+  iteratively done until it gets converged. Refer the description of
+  ArdcMbmTraversal(MBM).]
+
+  SideEffects []
+
+  SeeAlso [ArdcMbmTraversal ArdcTfbfTraversal ArdcTmbmTraversal
+  ArdcSimpleTraversal]
+
+******************************************************************************/
+static array_t *
+ArdcRfbfTraversal(Fsm_Fsm_t *fsm, int nvars,
+		  array_t *subFsmArray, array_t *fanInsIndexArray,
+		  int incrementalFlag, int verbosityLevel,
+		  int printStep, int depthValue, int shellFlag,
+		  int reorderFlag, int reorderThreshold,
+		  Fsm_RchType_t approxFlag, Fsm_ArdcOptions_t *options)
+{
+  mdd_manager		*mddManager;
+  int			i, n = array_n(subFsmArray);
+  mdd_t			**reached, **constraint, **newConstraint;
+  mdd_t			**newReached, *to;
+  int			converged = 0;
+  Fsm_Fsm_t		**subFsm;
+  array_t		*fans;
+  mdd_t			*tmp;
+  mdd_t			*initialStates;
+  int			iteration = 0;
+  mdd_t			**initial = NIL(mdd_t *);
+  array_t		*reachedArray = array_alloc(mdd_t *, 0);
+  array_t		*faninConstrainArray;
+  Img_ImageInfo_t	*imageInfo = NIL(Img_ImageInfo_t);
+  int			dynStatus;
+  bdd_reorder_type_t	dynMethod;
+  boolean		restoreContainmentFlag;
+  mdd_t			*toCareSet;
+  array_t		*toCareSetArray = array_alloc(mdd_t *, 0);
+  int			depth = 0;
+  boolean		tmpReorderPtrFlag;
+  long			tImgComps = 0;
+  long			tConstrainOps = 0;
+  long			initialTime = 0, finalTime;
+  int			maxIteration = options->maxIteration;
+  int			constrainTarget = options->constrainTarget;
+  boolean		decomposeFlag = options->decomposeFlag;
+  int			abstractPseudoInput = options->abstractPseudoInput;
+  Img_MinimizeType	constrainMethod = options->constrainMethod;
+  boolean		projectedInitialFlag = options->projectedInitialFlag;
+  int			ardcVerbosity = options->verbosity;
+  boolean		constrainReorderFlag = options->constrainReorderFlag;
+  boolean		reorderPtrFlag = options->reorderPtrFlag;
+  int			faninConstrainMode = options->faninConstrainMode;
+
+  Img_ResetNumberOfImageComputation(Img_Forward_c);
+
+  reached = ALLOC(mdd_t *, n);
+  constraint = ALLOC(mdd_t *, n);
+  newConstraint = ALLOC(mdd_t *, n);
+  subFsm = ALLOC(Fsm_Fsm_t *, n);
+  newReached = ALLOC(mdd_t *, n);
+
+  mddManager = Fsm_FsmReadMddManager(fsm);
+  for (i = 0; i < n; i++) {
+    subFsm[i] = array_fetch(Fsm_Fsm_t *, subFsmArray, i);
+    initialStates = Fsm_FsmComputeInitialStates(subFsm[i]);
+    reached[i] = initialStates;
+    constraint[i] = mdd_dup(initialStates);
+
+    if (printStep && ((depth % printStep) == 0)) {
+      if (ardcVerbosity > 1)
+	fprintf(vis_stdout, "--- sub fsm [%d] ---\n", i);
+      (void)fprintf(vis_stdout,
+		    "BFS step = %d\t|states| = %8g\tBdd size = %8ld\n", depth,
+		    mdd_count_onset(mddManager, reached[i],
+				    subFsm[i]->fsmData.presentStateVars),
+		    (long)mdd_size(reached[i]));
+    }
+  }
+
+  if (constrainTarget == Fsm_Ardc_Constrain_Initial_c ||
+      constrainTarget == Fsm_Ardc_Constrain_Both_c) {
+    initial = ALLOC(mdd_t *, n);
+    for (i = 0; i < n; i++)
+      initial[i] = mdd_dup(reached[i]);
+  }
+
+  if (constrainMethod != Img_Constrain_c ||
+      constrainReorderFlag == TRUE ||
+      abstractPseudoInput != Fsm_Ardc_Abst_Ppi_No_c) {
+    restoreContainmentFlag = TRUE;
+  } else
+    restoreContainmentFlag = FALSE;
+
+  converged = 0;
+  do {
+    depth++;
+    for (i = 0; i < n; i++) {
+      if (ardcVerbosity > 1)
+	fprintf(vis_stdout, "--- sub fsm [%d] ---\n", i);
+      faninConstrainArray = array_alloc(mdd_t *, 0);
+      fans = array_fetch(array_t *, fanInsIndexArray, i);
+      ComputeFaninConstrainArray(faninConstrainArray, constraint,
+				 i, fans, decomposeFlag, faninConstrainMode);
+      dynStatus = bdd_reordering_status(mddManager, &dynMethod);
+      if (dynStatus != 0 && constrainReorderFlag == 0)
+	bdd_dynamic_reordering_disable(mddManager);
+      imageInfo = Fsm_FsmReadOrCreateImageInfo(subFsm[i], 0, 1);
+      if (constrainTarget != Fsm_Ardc_Constrain_Initial_c) {
+	int saveStatus = Img_ReadPrintMinimizeStatus(imageInfo);
+	if (ardcVerbosity > 2)
+	  Img_SetPrintMinimizeStatus(imageInfo, 2);
+	else if (ardcVerbosity > 0)
+	  Img_SetPrintMinimizeStatus(imageInfo, 1);
+	else
+	  Img_SetPrintMinimizeStatus(imageInfo, 0);
+	if (reorderPtrFlag &&
+	    abstractPseudoInput != Fsm_Ardc_Abst_Ppi_Before_Image_c) {
+	  tmpReorderPtrFlag = 1;
+	} else
+	  tmpReorderPtrFlag = 0;
+	if (ardcVerbosity > 0)
+	  initialTime = util_cpu_time();
+	MinimizeTransitionRelationWithFaninConstraint(imageInfo,
+		faninConstrainArray, constrainMethod, tmpReorderPtrFlag,
+		TRUE);
+	if (ardcVerbosity > 0) {
+	  finalTime = util_cpu_time();
+	  tConstrainOps += finalTime - initialTime;
+	}
+	Img_SetPrintMinimizeStatus(imageInfo, saveStatus);
+      }
+      if (constrainTarget != Fsm_Ardc_Constrain_Tr_c) {
+	ComputeConstrainedInitialStates(subFsm[i], faninConstrainArray,
+					constrainMethod);
+      }
+      mdd_array_free(faninConstrainArray);
+      if (dynStatus != 0 && constrainReorderFlag == 0) {
+	bdd_dynamic_reordering(mddManager, dynMethod,
+			       BDD_REORDER_VERBOSITY_DEFAULT);
+      }
+      if (abstractPseudoInput == Fsm_Ardc_Abst_Ppi_Before_Image_c) {
+	int saveStatus = Img_ReadPrintMinimizeStatus(imageInfo);
+	if (ardcVerbosity > 2)
+	  Img_SetPrintMinimizeStatus(imageInfo, 2);
+	else if (ardcVerbosity > 0)
+	  Img_SetPrintMinimizeStatus(imageInfo, 1);
+	else
+	  Img_SetPrintMinimizeStatus(imageInfo, 0);
+	Img_AbstractTransitionRelation(imageInfo,
+	  subFsm[i]->fsmData.pseudoInputBddVars,
+	  subFsm[i]->fsmData.pseudoInputCube, Img_Forward_c);
+	if (reorderPtrFlag)
+	  Img_ReorderPartitionedTransitionRelation(imageInfo, Img_Forward_c);
+	Img_SetPrintMinimizeStatus(imageInfo, saveStatus);
+      }
+      toCareSet = mdd_not(reached[i]);
+      array_insert(mdd_t *, toCareSetArray, 0, toCareSet);
+      if (ardcVerbosity > 0)
+	initialTime = util_cpu_time();
+      to = Fsm_ArdcComputeImage(subFsm[i], reached[i], reached[i],
+				toCareSetArray);
+      if (Img_ImageInfoObtainMethodType(imageInfo) == Img_Tfm_c ||
+	  Img_ImageInfoObtainMethodType(imageInfo) == Img_Hybrid_c) {
+	Img_TfmFlushCache(imageInfo, FALSE);
+      }
+      if (ardcVerbosity > 0) {
+	finalTime = util_cpu_time();
+	tImgComps += finalTime - initialTime;
+      }
+      mdd_free(toCareSet);
+
+      newReached[i] = mdd_or(reached[i], to, 1, 1);
+      mdd_free(to);
+      if (constrainTarget != Fsm_Ardc_Constrain_Initial_c)
+	Img_RestoreTransitionRelation(imageInfo, Img_Forward_c);
+      if (abstractPseudoInput == Fsm_Ardc_Abst_Ppi_After_Image_c) {
+	tmp = newReached[i];
+	newReached[i] = QuantifyVariables(newReached[i],
+					subFsm[i]->fsmData.pseudoInputBddVars,
+					subFsm[i]->fsmData.pseudoInputCube);
+	mdd_free(tmp);
+      }
+
+      /* restore-containment operation */
+      if (restoreContainmentFlag) {
+	if (!mdd_lequal(reached[i], newReached[i], 1, 1)) {
+	  if (ardcVerbosity > 2) {
+	    double	r1, r2;
+
+	    fprintf(vis_stdout,
+   "** ardc warning : newReached is not superset of reached in subFsm[%d] **\n",
+		    i);
+	    r1 = mdd_count_onset(mddManager, reached[i],
+				 subFsm[i]->fsmData.presentStateVars);
+	    r2 = mdd_count_onset(mddManager, newReached[i],
+				 subFsm[i]->fsmData.presentStateVars);
+	    fprintf(vis_stdout, "reached = %g, newReached = %g\n", r1, r2);
+	  }
+	  tmp = newReached[i];
+	  newReached[i] = mdd_or(newReached[i], reached[i], 1, 1);
+	  mdd_free(tmp);
+	}
+      }
+
+      newConstraint[i] = mdd_dup(newReached[i]);
+
+      if (printStep && ((depth % printStep) == 0)) {
+	(void)fprintf(vis_stdout,
+		      "BFS step = %d\t|states| = %8g\tBdd size = %8ld\n",
+		      depth, mdd_count_onset(mddManager, newReached[i],
+				     subFsm[i]->fsmData.presentStateVars),
+		      (long)mdd_size(newReached[i]));
+      }
+    }
+    converged = 1;
+    for (i = 0; i < n; i++) {
+      if (mdd_equal(reached[i], newReached[i]))
+	mdd_free(newReached[i]);
+      else {
+	converged = 0;
+	mdd_free(reached[i]);
+	reached[i] = newReached[i];
+      }
+    }
+    iteration++;
+    if (ardcVerbosity > 0) {
+      boolean	supportCheckFlag = FALSE;
+
+      if (projectedInitialFlag ||
+	  abstractPseudoInput == Fsm_Ardc_Abst_Ppi_Before_Image_c) {
+	supportCheckFlag = TRUE;
+      }
+      PrintCurrentReachedStates(mddManager, subFsm, reached,
+				Fsm_Ardc_Traversal_Rfbf_c,
+				n, iteration, nvars, ardcVerbosity,
+				supportCheckFlag);
+    }
+
+    /* update constraints */
+    for (i = 0; i < n; i++) {
+      mdd_free(constraint[i]);
+      constraint[i] = newConstraint[i];
+      newConstraint[i] = NIL(mdd_t);
+    }
+
+    if (iteration == maxIteration)
+      break;
+  } while (!converged);
+  if (ardcVerbosity > 0) {
+    fprintf(vis_stdout, "RFBF : total iteration %d\n", iteration);
+    fprintf(vis_stdout, "%d image computations, %d constrain operations\n",
+	Img_GetNumberOfImageComputation(Img_Forward_c), n * iteration);
+    fprintf(vis_stdout,
+	"image computation time = %g, constrain operation time = %g\n",
+	(double)tImgComps / 1000.0, (double)tConstrainOps / 1000.0);
+  }
+
+  if (constrainTarget == Fsm_Ardc_Constrain_Initial_c ||
+      constrainTarget == Fsm_Ardc_Constrain_Both_c) {
+    for (i = 0; i < n; i++) {
+      mdd_free(subFsm[i]->reachabilityInfo.initialStates);
+      subFsm[i]->reachabilityInfo.initialStates = initial[i];
+    }
+    FREE(initial);
+  }
+
+  if (abstractPseudoInput == Fsm_Ardc_Abst_Ppi_At_End_c) {
+    for (i = 0; i < n; i++) {
+      tmp = reached[i];
+      reached[i] = QuantifyVariables(reached[i],
+				subFsm[i]->fsmData.pseudoInputBddVars,
+				subFsm[i]->fsmData.pseudoInputCube);
+      mdd_free(tmp);
+    }
+  }
+
+  /* sets the status of current overapproximate reached states */
+  if (converged)
+    FsmSetReachabilityOverApproxComputationStatus(fsm, Fsm_Ardc_Converged_c);
+  else
+    FsmSetReachabilityOverApproxComputationStatus(fsm, Fsm_Ardc_NotConverged_c);
+
+  ComputeApproximateReachableStatesArray(mddManager, reachedArray,
+					 reached, NULL, n, decomposeFlag);
+  if (decomposeFlag) {
+    for (i = 0; i < n; i++) {
+      mdd_free(constraint[i]);
+    }
+  } else {
+    for (i = 0; i < n; i++) {
+      mdd_free(reached[i]);
+      mdd_free(constraint[i]);
+    }
+  }
+
+  FREE(reached);
+  FREE(constraint);
+  FREE(newConstraint);
+  FREE(subFsm);
+  FREE(newReached);
+  array_free(toCareSetArray);
+
+  return(reachedArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes an upperbound of an FSM by TFBF.]
+
+  Description [Computes an upperbound of an FSM by TFBF. It first
+  sets all constraints to initial states, then does one image
+  computation, then updates constraints with the results of image
+  computations. This is iteratively done until it gets converged.
+  Refer the description of ArdcMbmTraversal(MBM).]
+
+  SideEffects []
+
+  SeeAlso [ArdcMbmTraversal ArdcRfbfTraversal ArdcTmbmTraversal
+  ArdcSimpleTraversal]
+
+******************************************************************************/
+static array_t *
+ArdcTfbfTraversal(Fsm_Fsm_t *fsm, int nvars,
+		  array_t *subFsmArray, array_t *fanInsIndexArray,
+		  mdd_t ***subReached, mdd_t ***subTo,
+		  int incrementalFlag, int verbosityLevel,
+		  int printStep, int depthValue, int shellFlag,
+		  int reorderFlag, int reorderThreshold,
+		  Fsm_RchType_t approxFlag, Fsm_ArdcOptions_t *options)
+{
+  mdd_manager		*mddManager = NIL(mdd_manager);
+  int			i, j, n = array_n(subFsmArray);
+  mdd_t			**reached, **constraint, **newConstraint;
+  mdd_t			**to, **old_to;
+  int			converged = 0;
+  Fsm_Fsm_t		**subFsm;
+  array_t		*pi_to;
+  mdd_t			*tmp;
+  array_t		*fans;
+  mdd_t			*initialStates;
+  int			iteration = 0;
+  mdd_t			**initial = NIL(mdd_t *);
+  array_t		*reachedArray = array_alloc(mdd_t *, 0);
+  array_t		*faninConstrainArray;
+  Img_ImageInfo_t	*imageInfo = NIL(Img_ImageInfo_t);
+  int			dynStatus;
+  bdd_reorder_type_t	dynMethod;
+  mdd_t			*toCareSet;
+  array_t		*toCareSetArray = array_alloc(mdd_t *, 0);
+  int			depth = 0;
+  boolean		tmpReorderPtrFlag;
+  long			tImgComps = 0;
+  long			tConstrainOps = 0;
+  long			initialTime = 0, finalTime;
+  int			maxIteration = options->maxIteration;
+  int			constrainTarget = options->constrainTarget;
+  boolean		decomposeFlag = options->decomposeFlag;
+  int			abstractPseudoInput = options->abstractPseudoInput;
+  Img_MinimizeType	constrainMethod = options->constrainMethod;
+  boolean		projectedInitialFlag = options->projectedInitialFlag;
+  int			ardcVerbosity = options->verbosity;
+  boolean		constrainReorderFlag = options->constrainReorderFlag;
+  boolean		reorderPtrFlag = options->reorderPtrFlag;
+  int			faninConstrainMode = options->faninConstrainMode;
+
+  Img_ResetNumberOfImageComputation(Img_Forward_c);
+
+  reached = ALLOC(mdd_t *, n);
+  constraint = ALLOC(mdd_t *, n);
+  newConstraint = ALLOC(mdd_t *, n);
+  subFsm = ALLOC(Fsm_Fsm_t *, n);
+  pi_to = array_alloc(mdd_t *, 0);
+  to = ALLOC(mdd_t *, n);
+  array_insert_last(mdd_t **, pi_to, to);
+
+  mddManager = Fsm_FsmReadMddManager(fsm);
+  for (i = 0; i < n; i++) {
+    subFsm[i] = array_fetch(Fsm_Fsm_t *, subFsmArray, i);
+    initialStates = Fsm_FsmComputeInitialStates(subFsm[i]);
+    reached[i] = initialStates;
+    constraint[i] = mdd_dup(initialStates);
+    to[i] = mdd_zero(mddManager);
+
+    if (printStep && ((depth % printStep) == 0)) {
+      if (ardcVerbosity > 1)
+	fprintf(vis_stdout, "--- sub fsm [%d] ---\n", i);
+      (void)fprintf(vis_stdout,
+		    "BFS step = %d\t|states| = %8g\tBdd size = %8ld\n", depth,
+		    mdd_count_onset(mddManager, reached[i],
+				    subFsm[i]->fsmData.presentStateVars),
+		    (long)mdd_size(reached[i]));
+    }
+  }
+
+  if (constrainTarget == Fsm_Ardc_Constrain_Initial_c ||
+      constrainTarget == Fsm_Ardc_Constrain_Both_c) {
+    initial = ALLOC(mdd_t *, n);
+    for (i = 0; i < n; i++)
+      initial[i] = Fsm_FsmComputeInitialStates(subFsm[i]);
+  }
+
+  converged = 0;
+  do {
+    depth++;
+    to = ALLOC(mdd_t *, n);
+    for (i = 0; i < n; i++) {
+      if (ardcVerbosity > 1)
+	fprintf(vis_stdout, "--- sub fsm [%d] ---\n", i);
+      faninConstrainArray = array_alloc(mdd_t *, 0);
+      fans = array_fetch(array_t *, fanInsIndexArray, i);
+      ComputeFaninConstrainArray(faninConstrainArray, constraint,
+				 i, fans, decomposeFlag, faninConstrainMode);
+      dynStatus = bdd_reordering_status(mddManager, &dynMethod);
+      if (dynStatus != 0 && constrainReorderFlag == 0)
+	bdd_dynamic_reordering_disable(mddManager);
+      imageInfo = Fsm_FsmReadOrCreateImageInfo(subFsm[i], 0, 1);
+      if (constrainTarget != Fsm_Ardc_Constrain_Initial_c) {
+	int saveStatus = Img_ReadPrintMinimizeStatus(imageInfo);
+	if (ardcVerbosity > 2)
+	  Img_SetPrintMinimizeStatus(imageInfo, 2);
+	else if (ardcVerbosity > 0)
+	  Img_SetPrintMinimizeStatus(imageInfo, 1);
+	else
+	  Img_SetPrintMinimizeStatus(imageInfo, 0);
+	if (reorderPtrFlag &&
+	    abstractPseudoInput != Fsm_Ardc_Abst_Ppi_Before_Image_c) {
+	  tmpReorderPtrFlag = 1;
+	} else
+	  tmpReorderPtrFlag = 0;
+	if (ardcVerbosity > 0)
+	  initialTime = util_cpu_time();
+	MinimizeTransitionRelationWithFaninConstraint(imageInfo,
+		faninConstrainArray, constrainMethod, tmpReorderPtrFlag,
+		TRUE);
+	if (ardcVerbosity > 0) {
+	  finalTime = util_cpu_time();
+	  tConstrainOps += finalTime - initialTime;
+	}
+	Img_SetPrintMinimizeStatus(imageInfo, saveStatus);
+      }
+      if (constrainTarget != Fsm_Ardc_Constrain_Tr_c) {
+	ComputeConstrainedInitialStates(subFsm[i], faninConstrainArray,
+					constrainMethod);
+      }
+      mdd_array_free(faninConstrainArray);
+      if (dynStatus != 0 && constrainReorderFlag == 0) {
+	bdd_dynamic_reordering(mddManager, dynMethod,
+			       BDD_REORDER_VERBOSITY_DEFAULT);
+      }
+      if (abstractPseudoInput == Fsm_Ardc_Abst_Ppi_Before_Image_c) {
+	int saveStatus = Img_ReadPrintMinimizeStatus(imageInfo);
+	if (ardcVerbosity > 2)
+	  Img_SetPrintMinimizeStatus(imageInfo, 2);
+	else if (ardcVerbosity > 0)
+	  Img_SetPrintMinimizeStatus(imageInfo, 1);
+	else
+	  Img_SetPrintMinimizeStatus(imageInfo, 0);
+	Img_AbstractTransitionRelation(imageInfo,
+		       subFsm[i]->fsmData.pseudoInputBddVars,
+		       subFsm[i]->fsmData.pseudoInputCube, Img_Forward_c);
+	if (reorderPtrFlag)
+	  Img_ReorderPartitionedTransitionRelation(imageInfo, Img_Forward_c);
+	Img_SetPrintMinimizeStatus(imageInfo, saveStatus);
+      }
+      toCareSet = mdd_not(reached[i]);
+      array_insert(mdd_t *, toCareSetArray, 0, toCareSet);
+      if (ardcVerbosity > 0)
+	initialTime = util_cpu_time();
+      to[i] = Fsm_ArdcComputeImage(subFsm[i], constraint[i],
+				   constraint[i], toCareSetArray);
+      if (Img_ImageInfoObtainMethodType(imageInfo) == Img_Tfm_c ||
+	  Img_ImageInfoObtainMethodType(imageInfo) == Img_Hybrid_c) {
+	Img_TfmFlushCache(imageInfo, FALSE);
+      }
+      if (ardcVerbosity > 0) {
+	finalTime = util_cpu_time();
+	tImgComps += finalTime - initialTime;
+      }
+      mdd_free(toCareSet);
+      if (constrainTarget != Fsm_Ardc_Constrain_Initial_c)
+	Img_RestoreTransitionRelation(imageInfo, Img_Forward_c);
+
+      tmp = reached[i];
+      reached[i] = mdd_or(reached[i], to[i], 1, 1);
+      mdd_free(tmp);
+      if (abstractPseudoInput == Fsm_Ardc_Abst_Ppi_After_Image_c) {
+	tmp = reached[i];
+	reached[i] = QuantifyVariables(reached[i],
+				subFsm[i]->fsmData.pseudoInputBddVars,
+				subFsm[i]->fsmData.pseudoInputCube);
+	mdd_free(tmp);
+      }
+      newConstraint[i] = mdd_dup(to[i]);
+
+      if (printStep && ((depth % printStep) == 0)) {
+	(void)fprintf(vis_stdout,
+		      "BFS step = %d\t|states| = %8g\tBdd size = %8ld\n",
+		      depth, mdd_count_onset(mddManager, reached[i],
+				     subFsm[i]->fsmData.presentStateVars),
+		      (long)mdd_size(reached[i]));
+      }
+    }
+    for (i = 0; i < array_n(pi_to); i++) {
+      old_to = array_fetch(mdd_t **, pi_to, i);
+      for (j = 0; j < n; j++) {
+	if (!mdd_equal(old_to[j], to[j]))
+	  break;
+      }
+      if (j == n)
+	break;
+    }
+    if (i == array_n(pi_to))
+      converged = 0;
+    else {
+      converged = 1;
+      if (ardcVerbosity > 0) {
+	fprintf(vis_stdout,
+		"** ardc info : TFBF converged at iteration %d(=%d).\n",
+		iteration + 1, i);
+      }
+    }
+    iteration++;
+    if (ardcVerbosity > 0) {
+      boolean	supportCheckFlag = FALSE;
+
+      if (projectedInitialFlag ||
+	  abstractPseudoInput == Fsm_Ardc_Abst_Ppi_Before_Image_c) {
+	supportCheckFlag = TRUE;
+      }
+      PrintCurrentReachedStates(mddManager, subFsm, reached,
+				Fsm_Ardc_Traversal_Tfbf_c,
+				n, iteration, nvars, ardcVerbosity,
+				supportCheckFlag);
+    }
+
+    /* update constraints */
+    for (i = 0; i < n; i++) {
+      mdd_free(constraint[i]);
+      constraint[i] = newConstraint[i];
+      newConstraint[i] = NIL(mdd_t);
+    }
+
+    if (converged || iteration == maxIteration) {
+      if (subTo)
+	*subTo = to;
+      else {
+	for (i = 0; i < n; i++)
+	  mdd_free(to[i]);
+	FREE(to);
+      }
+      break;
+    }
+    array_insert_last(mdd_t **, pi_to, to);
+  } while (!converged);
+  if (ardcVerbosity > 0) {
+    fprintf(vis_stdout, "TFBF : total iteration %d\n", iteration);
+    fprintf(vis_stdout, "%d image computations, %d constrain operations\n",
+	Img_GetNumberOfImageComputation(Img_Forward_c), n * iteration);
+    fprintf(vis_stdout,
+	"image computation time = %g, constrain operation time = %g\n",
+	(double)tImgComps / 1000.0, (double)tConstrainOps / 1000.0);
+  }
+
+  if (constrainTarget == Fsm_Ardc_Constrain_Initial_c ||
+      constrainTarget == Fsm_Ardc_Constrain_Both_c) {
+    for (i = 0; i < n; i++) {
+      mdd_free(subFsm[i]->reachabilityInfo.initialStates);
+      subFsm[i]->reachabilityInfo.initialStates = initial[i];
+    }
+    FREE(initial);
+  }
+
+  if (abstractPseudoInput == Fsm_Ardc_Abst_Ppi_At_End_c) {
+    for (i = 0; i < n; i++) {
+      tmp = reached[i];
+      reached[i] = QuantifyVariables(reached[i],
+				subFsm[i]->fsmData.pseudoInputBddVars,
+				subFsm[i]->fsmData.pseudoInputCube);
+      mdd_free(tmp);
+    }
+  }
+
+  /* sets the status of current overapproximate reached states */
+  if (converged)
+    FsmSetReachabilityOverApproxComputationStatus(fsm, Fsm_Ardc_Converged_c);
+  else
+    FsmSetReachabilityOverApproxComputationStatus(fsm, Fsm_Ardc_NotConverged_c);
+
+  ComputeApproximateReachableStatesArray(mddManager, reachedArray,
+					 reached, subReached, n, decomposeFlag);
+  if (decomposeFlag) {
+    for (i = 0; i < n; i++) {
+      mdd_free(constraint[i]);
+    }
+  } else {
+    for (i = 0; i < n; i++) {
+      if (subReached == NULL)
+	mdd_free(reached[i]);
+      mdd_free(constraint[i]);
+    }
+  }
+
+  if (subReached)
+    *subReached = reached;
+  else
+    FREE(reached);
+  FREE(constraint);
+  FREE(newConstraint);
+  FREE(subFsm);
+  for (i = 0; i < array_n(pi_to); i++) {
+    to = array_fetch(mdd_t **, pi_to, i);
+    for (j = 0; j < n; j++)
+      mdd_free(to[j]);
+    FREE(to);
+  }
+  array_free(pi_to);
+  array_free(toCareSetArray);
+
+  return(reachedArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes an upperbound of an FSM by TMBM.]
+
+  Description [Computes an upperbound of an FSM by TMBM. TMBM is a
+  combination of TFBF and MBM. It first calls TFBF with max iteration
+  number(given by ardc_max_iteration set option). Then if the reached
+  states are not converged yet, it calls MBM by using current reached
+  states as initial states.]
+
+  SideEffects []
+
+  SeeAlso [ArdcMbmTraversal ArdcRfbfTraversal ArdcTfbfTraversal
+  ArdcSimpleTraversal]
+
+******************************************************************************/
+static array_t *
+ArdcTmbmTraversal(
+  Fsm_Fsm_t *fsm,
+  int nvars,
+  array_t *subFsmArray,
+  array_t *fanInsIndexArray,
+  array_t *fanOutsIndexArray,
+  int incrementalFlag,
+  int verbosityLevel,
+  int printStep,
+  int depthValue,
+  int shellFlag,
+  int reorderFlag,
+  int reorderThreshold,
+  Fsm_RchType_t approxFlag,
+  Fsm_ArdcOptions_t *options,
+  boolean lfpFlag)
+{
+  mdd_manager	*mddManager;
+  int		i, n = array_n(subFsmArray);
+  mdd_t		**reached, **tfbf_reached;
+  mdd_t		**to, **initial;
+  Fsm_Fsm_t	*subFsm = NIL(Fsm_Fsm_t);
+  mdd_t		*tmp;
+  array_t	*reachedArray;
+  int		saveMaxIteration;
+
+  saveMaxIteration = options->maxIteration;
+  if (options->maxIteration == 0)
+    options->maxIteration = 10; /* default */
+
+  /* Try TFBF for the presecribed number of steps. */
+  reachedArray = ArdcTfbfTraversal(fsm, nvars, subFsmArray, fanInsIndexArray,
+				   &tfbf_reached, &to,
+				   incrementalFlag, verbosityLevel, printStep,
+				   depthValue, shellFlag, reorderFlag,
+				   reorderThreshold, approxFlag, options);
+
+  /* If TFBF converged in the allotted number of iterations, clean up and
+   * return. */
+  if (FsmReadReachabilityOverApproxComputationStatus(fsm) >=
+      Fsm_Ardc_Converged_c) {
+    for (i = 0; i < n; i++) {
+      mdd_free(tfbf_reached[i]);
+      mdd_free(to[i]);
+    }
+    FREE(tfbf_reached);
+    FREE(to);
+    return(reachedArray);
+  }
+
+  mdd_array_free(reachedArray);
+
+  /* Save the initial states of each submachine in "initial"; thenset it
+   * to the "to" states returned by TFBF. */
+  initial = ALLOC(mdd_t *, n);
+  for (i = 0; i < n; i++) {
+    subFsm = array_fetch(Fsm_Fsm_t *, subFsmArray, i);
+    initial[i] = subFsm->reachabilityInfo.initialStates;
+    subFsm->reachabilityInfo.initialStates = mdd_dup(to[i]);
+  }
+
+  /* Apply either MBM or LMBM starting from the "to" states returned by
+   * TFBF. */
+  options->maxIteration = 0;
+  reachedArray = ArdcMbmTraversal(fsm, nvars, subFsmArray,
+			  fanInsIndexArray, fanOutsIndexArray, &reached,
+			  incrementalFlag, verbosityLevel, printStep,
+			  depthValue, shellFlag, reorderFlag, reorderThreshold,
+			  approxFlag, options, lfpFlag);
+  options->maxIteration = saveMaxIteration;
+
+  mdd_array_free(reachedArray);
+
+  /* Combine the reachability results of TFBF and (L)MBM and restore
+   * the initial states of the submachines. */
+  for (i = 0; i < n; i++) {
+    tmp = reached[i];
+    reached[i] = mdd_or(tfbf_reached[i], reached[i], 1, 1);
+    mdd_free(tmp);
+    subFsm = array_fetch(Fsm_Fsm_t *, subFsmArray, i);
+    mdd_free(subFsm->reachabilityInfo.initialStates);
+    subFsm->reachabilityInfo.initialStates = initial[i];
+  }
+
+  /* Build the array of reachable states in either monolithic or decomposed
+   * form depending on the value of decomposeFlag. */
+  reachedArray = array_alloc(mdd_t *, 0);
+  mddManager = Fsm_FsmReadMddManager(subFsm);
+  ComputeApproximateReachableStatesArray(mddManager, reachedArray,
+					 reached, NULL, n,
+					 options->decomposeFlag);
+  if (!options->decomposeFlag) {
+    for (i = 0; i < n; i++)
+      mdd_free(reached[i]);
+  }
+
+  /* Clean up. */
+  for (i = 0; i < n; i++) {
+    mdd_free(tfbf_reached[i]);
+    mdd_free(to[i]);
+  }
+
+  FREE(reached);
+  FREE(tfbf_reached);
+  FREE(to);
+  FREE(initial);
+
+  return(reachedArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes a very rough upperbound in short time.]
+
+  Description [Computes a very rough upperbound in short time. It is very
+  simplified version of MBM, no iteration and no constrain operation.]
+
+  SideEffects []
+
+  SeeAlso [ArdcMbmTraversal ArdcRfbfTraversal ArdcTfbfTraversal
+  ArdcTmbmTraversal]
+
+******************************************************************************/
+static array_t *
+ArdcSimpleTraversal(Fsm_Fsm_t *fsm, int nvars, array_t *subFsmArray,
+		    int incrementalFlag, int verbosityLevel,
+		    int printStep, int depthValue, int shellFlag,
+		    int reorderFlag, int reorderThreshold,
+		    Fsm_RchType_t approxFlag, Fsm_ArdcOptions_t *options,
+		    int setFlag)
+{
+  mdd_manager		*mddManager;
+  int			i, n = array_n(subFsmArray);
+  mdd_t			**reached;
+  Fsm_Fsm_t		**subFsm;
+  mdd_t			*tmp;
+  array_t		*reachedArray = array_alloc(mdd_t *, 0);
+  Img_ImageInfo_t	*imageInfo = NIL(Img_ImageInfo_t);
+  boolean		decomposeFlag = options->decomposeFlag;
+  int			abstractPseudoInput = options->abstractPseudoInput;
+  boolean		projectedInitialFlag = options->projectedInitialFlag;
+  int			ardcVerbosity = options->verbosity;
+
+  reached = ALLOC(mdd_t *, n);
+  subFsm = ALLOC(Fsm_Fsm_t *, n);
+
+  for (i = 0; i < n; i++)
+    subFsm[i] = array_fetch(Fsm_Fsm_t *, subFsmArray, i);
+
+  mddManager = Fsm_FsmReadMddManager(subFsm[0]);
+  for (i = 0; i < n; i++) {
+    if (printStep && ardcVerbosity > 1)
+      fprintf(vis_stdout, "--- sub fsm [%d] ---\n", i);
+    if (abstractPseudoInput == Fsm_Ardc_Abst_Ppi_Before_Image_c) {
+      int saveStatus = Img_ReadPrintMinimizeStatus(imageInfo);
+      if (ardcVerbosity > 2)
+	Img_SetPrintMinimizeStatus(imageInfo, 2);
+      else if (ardcVerbosity > 0)
+	Img_SetPrintMinimizeStatus(imageInfo, 1);
+      else
+	Img_SetPrintMinimizeStatus(imageInfo, 0);
+      imageInfo = Fsm_FsmReadOrCreateImageInfo(subFsm[i], 0, 1);
+      Img_AbstractTransitionRelation(imageInfo,
+				     subFsm[i]->fsmData.pseudoInputBddVars,
+				     subFsm[i]->fsmData.pseudoInputCube,
+				     Img_Forward_c);
+      Img_SetPrintMinimizeStatus(imageInfo, saveStatus);
+    }
+    reached[i] = Fsm_FsmComputeReachableStates(subFsm[i],
+		       incrementalFlag, verbosityLevel, printStep, depthValue,
+		       shellFlag, reorderFlag, reorderThreshold,
+		       approxFlag, 0, 0, NIL(array_t), FALSE, NIL(array_t));
+    if (Img_ImageInfoObtainMethodType(imageInfo) == Img_Tfm_c ||
+	Img_ImageInfoObtainMethodType(imageInfo) == Img_Hybrid_c) {
+      Img_TfmFlushCache(imageInfo, FALSE);
+    }
+    if (abstractPseudoInput == Fsm_Ardc_Abst_Ppi_After_Image_c) {
+      if (n > 1) {
+	tmp = reached[i];
+	reached[i] = QuantifyVariables(reached[i],
+				subFsm[i]->fsmData.pseudoInputBddVars,
+				subFsm[i]->fsmData.pseudoInputCube);
+	mdd_free(tmp);
+      }
+    }
+  }
+
+  if (ardcVerbosity > 0) {
+    boolean	supportCheckFlag = FALSE;
+
+    if (projectedInitialFlag ||
+	abstractPseudoInput == Fsm_Ardc_Abst_Ppi_Before_Image_c) {
+      supportCheckFlag = TRUE;
+    }
+    PrintCurrentReachedStates(mddManager, subFsm, reached,
+				Fsm_Ardc_Traversal_Simple_c,
+				n, 0, nvars, ardcVerbosity,
+				supportCheckFlag);
+  }
+
+  if (abstractPseudoInput == Fsm_Ardc_Abst_Ppi_At_End_c) {
+    for (i = 0; i < n; i++) {
+      tmp = reached[i];
+      reached[i] = QuantifyVariables(reached[i],
+				subFsm[i]->fsmData.pseudoInputBddVars,
+				subFsm[i]->fsmData.pseudoInputCube);
+      mdd_free(tmp);
+    }
+  }
+
+  /* sets the status of current overapproximate reached states */
+  if (setFlag)
+    FsmSetReachabilityOverApproxComputationStatus(fsm, Fsm_Ardc_Converged_c);
+
+  ComputeApproximateReachableStatesArray(mddManager, reachedArray,
+					 reached, NULL, n, decomposeFlag);
+
+  FREE(reached);
+  FREE(subFsm);
+
+  return(reachedArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes fanin constraint with the reached states of
+  fanin submachines.]
+
+  Description [Computes fanin constraint with the reached states of
+  fanin submachines.]
+
+  SideEffects []
+
+  SeeAlso [ArdcMbmTraversal ArdcRfbfTraversal ArdcTfbfTraversal]
+
+******************************************************************************/
+static void
+ComputeFaninConstrainArray(array_t *faninConstrainArray, mdd_t **constraint,
+			   int current, array_t *fans,
+			   int decomposeFlag, int faninConstrainMode)
+{
+  mdd_t	*faninConstrain, *tmp;
+  int	i, fanin;
+
+  if (decomposeFlag) {
+    if (faninConstrainMode == 1) {
+      array_insert_last(mdd_t *, faninConstrainArray,
+			mdd_dup(constraint[current]));
+    }
+    arrayForEachItem(int, fans, i, fanin) {
+      array_insert_last(mdd_t *, faninConstrainArray,
+			  mdd_dup(constraint[fanin]));
+    }
+  } else {
+    if (faninConstrainMode == 1)
+      faninConstrain = mdd_dup(constraint[current]);
+    else
+      faninConstrain = NIL(mdd_t);
+    arrayForEachItem(int, fans, i, fanin) {
+      if (faninConstrain) {
+	tmp = faninConstrain;
+	faninConstrain = mdd_and(faninConstrain, constraint[fanin], 1, 1);
+	mdd_free(tmp);
+      } else
+	faninConstrain = mdd_dup(constraint[fanin]);
+    }
+    array_insert_last(mdd_t *, faninConstrainArray, faninConstrain);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Minimizes transition relation with fanin constraint.]
+
+  Description [Minimizes transition relation with fanin constraint.]
+
+  SideEffects []
+
+  SeeAlso [ArdcMbmTraversal ArdcRfbfTraversal ArdcTfbfTraversal]
+
+******************************************************************************/
+static void
+MinimizeTransitionRelationWithFaninConstraint(Img_ImageInfo_t *imageInfo,
+					      array_t *faninConstrainArray,
+					      Img_MinimizeType constrainMethod,
+					      boolean reorderPtrFlag,
+					      boolean duplicate)
+{
+  if (duplicate) {
+    Img_DupTransitionRelation(imageInfo, Img_Forward_c);
+    Img_ResetTrMinimizedFlag(imageInfo, Img_Forward_c);
+  }
+  Img_MinimizeTransitionRelation(imageInfo, faninConstrainArray,
+				 constrainMethod, Img_Forward_c,
+				 reorderPtrFlag);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes constrained initial states.]
+
+  Description [Computes constrained initial states.]
+
+  SideEffects [This function just update a new constrained initial
+  states, so caller should take care of this.]
+
+  SeeAlso [ArdcMbmTraversal ArdcRfbfTraversal ArdcTfbfTraversal]
+
+******************************************************************************/
+static void
+ComputeConstrainedInitialStates(Fsm_Fsm_t *subFsm,
+				array_t *faninConstrainArray,
+				Img_MinimizeType constrainMethod)
+{
+  int	i;
+  mdd_t	*faninConstrain, *tmp, *constrainedInitial;
+
+  constrainedInitial = subFsm->reachabilityInfo.initialStates;
+  for (i = 0; i < array_n(faninConstrainArray); i++) {
+    faninConstrain = array_fetch(mdd_t *, faninConstrainArray, i);
+    tmp = constrainedInitial;
+    constrainedInitial = Img_MinimizeImage(constrainedInitial,
+					   faninConstrain, constrainMethod,
+					   TRUE);
+    mdd_free(tmp);
+  }
+  subFsm->reachabilityInfo.initialStates = constrainedInitial;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makes an array of approximate reachable states.]
+
+  Description [Makes an array of approximate reachable states.]
+
+  SideEffects []
+
+  SeeAlso [ArdcMbmTraversal ArdcRfbfTraversal ArdcTfbfTraversal]
+
+******************************************************************************/
+static void
+ComputeApproximateReachableStatesArray(mdd_manager *mddManager,
+				       array_t *reachedArray,
+				       mdd_t **reached,
+				       mdd_t ***subReached,
+				       int nSubFsms,
+				       int decomposeFlag)
+{
+  int i;
+
+  if (decomposeFlag) {
+    for (i = 0; i < nSubFsms; i++) {
+      if (subReached)
+	array_insert_last(mdd_t *, reachedArray, mdd_dup(reached[i]));
+      else
+	array_insert_last(mdd_t *, reachedArray, reached[i]);
+    }
+  } else {
+    mdd_t *reachedSet = mdd_one(mddManager);
+    for (i = 0; i < nSubFsms; i++) {
+      mdd_t *tmp = reachedSet;
+      reachedSet = mdd_and(reachedSet, reached[i], 1, 1);
+      mdd_free(tmp);
+    }
+    array_insert_last(mdd_t *, reachedArray, reachedSet);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Copy exact reached states to overapproximate.]
+
+  Description [Copy exact reached states to overapproximate.]
+
+  SideEffects []
+
+  SeeAlso []
+
+******************************************************************************/
+static array_t *
+ArdcCopyOverApproxReachableStatesFromExact(Fsm_Fsm_t *fsm)
+{
+  array_t	*reachableStatesArray;
+
+  if (Fsm_FsmReadReachableStates(fsm) == NIL(mdd_t))
+    return(NIL(array_t));
+
+  reachableStatesArray = array_alloc(mdd_t *, 0);
+  array_insert_last(mdd_t *, reachableStatesArray,
+		    mdd_dup(Fsm_FsmReadReachableStates(fsm)));
+  FsmSetReachabilityOverApproxComputationStatus(fsm, Fsm_Ardc_Exact_c);
+  fsm->reachabilityInfo.apprReachableStates = reachableStatesArray;
+  fsm->reachabilityInfo.subPsVars = array_alloc(array_t *, 0);
+  array_insert_last(array_t *, fsm->reachabilityInfo.subPsVars,
+		    array_dup(fsm->fsmData.presentStateVars));
+  return(reachableStatesArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints current approximate reached states.]
+
+  Description [Prints current approximate reached states.]
+
+  SideEffects []
+
+  SeeAlso []
+
+******************************************************************************/
+static void
+PrintCurrentReachedStates(mdd_manager *mddManager, Fsm_Fsm_t **subFsm,
+			  mdd_t **reached, Fsm_Ardc_TraversalType_t method,
+			  int nSubFsms, int iteration, int nvars,
+			  int ardcVerbosity, boolean supportCheckFlag)
+{
+  int		i;
+  char		string[24];
+  double	tmpReached;
+
+  if (nvars <= EPD_MAX_BIN) {
+    double	numReached = 1.0, tmpReached;
+
+    for (i = 0; i < nSubFsms; i++) {
+      tmpReached = mdd_count_onset(mddManager, reached[i],
+				   subFsm[i]->fsmData.presentStateVars);
+      if (ardcVerbosity > 1) {
+	if (ardcVerbosity > 2 && supportCheckFlag) {
+	  assert(mdd_check_support(mddManager, reached[i],
+				   subFsm[i]->fsmData.presentStateVars));
+	}
+	fprintf(vis_stdout, "# of reached for subFsm[%d] = %g\n",
+		i, tmpReached);
+      }
+      numReached *= tmpReached;
+    }
+    sprintf(string, "%g", numReached);
+  } else {
+    EpDouble	epd;
+
+    EpdConvert((double)1.0, &epd);
+
+    for (i = 0; i < nSubFsms; i++) {
+      tmpReached = mdd_count_onset(mddManager, reached[i],
+				   subFsm[i]->fsmData.presentStateVars);
+      if (ardcVerbosity > 1) {
+	if (ardcVerbosity > 2 && supportCheckFlag) {
+	  assert(mdd_check_support(mddManager, reached[i],
+				   subFsm[i]->fsmData.presentStateVars));
+	}
+	fprintf(vis_stdout, "# of reached for subFsm[%d] = %g\n",
+		i, tmpReached);
+      }
+      EpdMultiply(&epd, tmpReached);
+    }
+    EpdGetString(&epd, string);
+  }
+
+  switch (method) {
+  case Fsm_Ardc_Traversal_Mbm_c :
+    fprintf(vis_stdout, "MBM : iteration %d, # of reached = %s\n",
+	    iteration, string);
+    break;
+  case Fsm_Ardc_Traversal_Rfbf_c :
+    fprintf(vis_stdout, "RFBF : iteration %d, # of reached = %s\n",
+	    iteration, string);
+    break;
+  case Fsm_Ardc_Traversal_Tfbf_c :
+    fprintf(vis_stdout, "TFBF : iteration %d, # of reached = %s\n",
+	    iteration, string);
+    break;
+  case Fsm_Ardc_Traversal_Tmbm_c :
+    fprintf(vis_stdout, "TMBM : iteration %d, # of reached = %s\n",
+	    iteration, string);
+    break;
+  case Fsm_Ardc_Traversal_Lmbm_c :
+    fprintf(vis_stdout, "LMBM : iteration %d, # of reached = %s\n",
+	    iteration, string);
+    break;
+  case Fsm_Ardc_Traversal_Tlmbm_c :
+    fprintf(vis_stdout, "TLMBM : iteration %d, # of reached = %s\n",
+	    iteration, string);
+    break;
+  case Fsm_Ardc_Traversal_Simple_c :
+    fprintf(vis_stdout, "SIMPLE : # of reached = %s\n", string);
+    break;
+  default :
+    break;
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints bdd variable names and levels of mddIdArr, and minterms.]
+
+  Description [Prints bdd variable names and levels of mddIdArr, and minterms.]
+
+  SideEffects []
+
+  SeeAlso []
+
+******************************************************************************/
+static void
+PrintBddWithName(Fsm_Fsm_t *fsm, array_t *mddIdArr, mdd_t *node)
+{
+  int		i, j, size;
+  mdd_manager	*mddManager;
+  array_t	*mvarArray;
+  mvar_type	mv;
+  int		bddId, mddId, varLevel;
+  bdd_t		*varBdd;
+
+  if (!node)
+    return;
+
+  mddManager = Fsm_FsmReadMddManager(fsm);
+  if (!mddIdArr)
+    mddIdArr = mdd_get_support(mddManager, node);
+  mvarArray = mdd_ret_mvar_list(mddManager);
+
+  size = array_n(mddIdArr);
+  for (i = 0; i < size; i++) {
+    mddId = array_fetch(int, mddIdArr, i);
+    mv = array_fetch(mvar_type, mvarArray, mddId);
+    for (j = 0; j < mv.encode_length; j++) {
+      bddId = mdd_ret_bvar_id(&mv, j);
+      varBdd = bdd_get_variable(mddManager, bddId);
+      varLevel = bdd_top_var_level(mddManager, varBdd);
+      if (mv.encode_length == 1)
+	fprintf(vis_stdout, "%s %d\n", mv.name, varLevel);
+      else
+	fprintf(vis_stdout, "%s[%d] %d\n", mv.name, j, varLevel);
+      bdd_free(varBdd);
+    }
+  }
+  bdd_print_minterm(node);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads grouping information.]
+
+  Description [Reads grouping information.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ArdcReadGroup(Ntk_Network_t *network, FILE *groupFile,
+	array_t *latchNameArray, array_t *groupIndexArray)
+{
+  char		line[ARDC_MAX_LINE_LEN];
+  char		*latchName, *name, *group;
+  int		groupIndex = 0;
+
+  while (fgets(line, ARDC_MAX_LINE_LEN, groupFile)) {
+    if (strlen(line) == 0)
+      continue;
+    if (line[0] == '#')
+      continue;
+    if (line[strlen(line) - 1] == '\n')
+      line[strlen(line) - 1] = '\0';
+    group = strtok(line, " ");
+    if (strncmp(group, "GROUP[", 6) == 0)
+      sscanf(group, "GROUP[%d]:", &groupIndex);
+    else {
+      latchName = util_strsav(group);
+      array_insert_last(char *, latchNameArray, latchName);
+      array_insert_last(int, groupIndexArray, groupIndex);
+    }
+    while ((name = strtok(NIL(char), " \t")) != NIL(char)) {
+      latchName = util_strsav(name);
+      array_insert_last(char *, latchNameArray, latchName);
+      array_insert_last(int, groupIndexArray, groupIndex);
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes one grouping information.]
+
+  Description [Writes one grouping information.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ArdcWriteOneGroup(Part_Subsystem_t *partitionSubsystem, FILE *groupFile, int i)
+{
+  st_generator	*stGen;
+  st_table	*vertexNameTable;
+  char		*latchName;
+
+  fprintf(groupFile, "GROUP[%d]:", i);
+  vertexNameTable = Part_PartitionSubsystemReadVertexTable(partitionSubsystem);
+  st_foreach_item(vertexNameTable, stGen, &latchName, NIL(char *)) {
+    fprintf(groupFile, " %s", latchName);
+  }
+  fprintf(groupFile, "\n");
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints one grouping information.]
+
+  Description [Prints one grouping information.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ArdcPrintOneGroup(Part_Subsystem_t *partitionSubsystem, int i, int nLatches,
+		  array_t *fanIns, array_t *fanOuts)
+{
+  int		j, k;
+  st_generator	*stGen;
+  st_table	*vertexNameTable;
+  char		*latchName;
+
+  fprintf(vis_stdout, "SUB-FSM [%d]\n", i);
+  fprintf(vis_stdout, "== latches(%d) :", nLatches);
+  vertexNameTable = Part_PartitionSubsystemReadVertexTable(partitionSubsystem);
+  st_foreach_item(vertexNameTable, stGen, &latchName, NIL(char *)) {
+    fprintf(vis_stdout, " %s", latchName);
+  }
+  fprintf(vis_stdout, "\n");
+  fprintf(vis_stdout, "== fanins(%d) :", array_n(fanIns));
+  for (j = 0; j < array_n(fanIns); j++) {
+    k = array_fetch(int, fanIns, j);
+    fprintf(vis_stdout, " %d", k);
+  }
+  fprintf(vis_stdout, "\n");
+  fprintf(vis_stdout, "== fanouts(%d) :", array_n(fanOuts));
+  for (j = 0; j < array_n(fanOuts); j++) {
+    k = array_fetch(int, fanOuts, j);
+    fprintf(vis_stdout, " %d", k);
+  }
+  fprintf(vis_stdout, "\n");
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a set integer value related ARDC computation.]
+
+  Description [Returns a set integer value related ARDC computation.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+GetArdcSetIntValue(char *string, int l, int u, int defaultValue)
+{
+  char	*flagValue;
+  int	tmp;
+  int	value = defaultValue;
+
+  flagValue = Cmd_FlagReadByName(string);
+  if (flagValue != NIL(char)) {
+    sscanf(flagValue, "%d", &tmp);
+    if (tmp >= l && (tmp <= u || u == 0))
+      value = tmp;
+    else {
+      fprintf(vis_stderr,
+	"** ardc error : invalid value %d for %s[%d-%d]. **\n", tmp, string,
+	      l, u);
+    }
+  }
+
+  return(value);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of approximate reachable states of an FSM.]
+
+  Description [Returns the number of approximate reachable states of an FSM.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ArdcEpdCountOnsetOfOverApproximateReachableStates(Fsm_Fsm_t *fsm, EpDouble *epd)
+{
+  mdd_t *reached;
+  array_t *psVars, *reachedArray;
+  mdd_manager *mddManager = Fsm_FsmReadMddManager(fsm);
+  double tmpReached;
+  int i;
+
+  EpdMakeZero(epd, 0);
+
+  if (!Fsm_FsmReadCurrentOverApproximateReachableStates(fsm))
+    return;
+
+  EpdConvert((double)1.0, epd);
+  reachedArray = Fsm_FsmReadCurrentOverApproximateReachableStates(fsm);
+  arrayForEachItem(mdd_t *, reachedArray, i, reached) {
+    psVars = array_fetch(array_t *, fsm->reachabilityInfo.subPsVars, i);
+    tmpReached = mdd_count_onset(mddManager, reached, psVars);
+    EpdMultiply(epd, tmpReached);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Quantifies out smoothing variables.]
+
+  Description [Quantifies out smoothing variables. If the bdd package is CUDD,
+  it performs with a cube for better efficiency. Otherwise, it uses
+  conventional  mdd id array. smoothArray should be an array of bdd variables.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static mdd_t *
+QuantifyVariables(mdd_t *state, array_t *smoothArray, mdd_t *smoothCube)
+{
+  if (smoothCube)
+    return(bdd_smooth_with_cube(state, smoothCube));
+  else
+    return(bdd_smooth(state, smoothArray));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Updates event scheduling of submachines for traversal.]
+
+  Description [Updates event scheduling of submachines for traversal.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+UpdateMbmEventSchedule(Fsm_Fsm_t **subFsm, array_t *fanOutIndices,
+			int *traverse, int lfpFlag)
+{
+  int	i, fanout;
+
+  arrayForEachItem(int, fanOutIndices, i, fanout) {
+    if (lfpFlag) {
+      if (!subFsm[fanout]->reachabilityInfo.reachableStates ||
+	  !bdd_is_tautology(subFsm[fanout]->reachabilityInfo.reachableStates,
+			    1)) {
+	traverse[fanout] = 1;
+      }
+    } else
+      traverse[fanout] = 1;
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints statistics of transition function method.]
+
+  Description [Prints statistics of transition function method.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+PrintTfmStatistics(array_t *subFsmArray)
+{
+  int			i;
+  Img_ImageInfo_t	*imageInfo;
+  Fsm_Fsm_t		*subFsm;
+  double		tInserts, tLookups, tHits, tEntries;
+  double		inserts, lookups, hits, entries;
+  int			nSlots, tSlots, maxChainLength;
+  float			avgDepth, tAvgDepth, avgDecomp, tAvgDecomp;
+  int			tRecurs, tLeaves, tTurns, tDecomps, minDecomp;
+  int			nRecurs, nLeaves, nTurns;
+  int			nDecomps, topDecomp, maxDecomp, tMaxDecomp;
+  int			maxDepth, tMaxDepth;
+  int			flag, globalCache;
+
+  tInserts = tLookups = tHits = tEntries = 0.0;
+  tSlots = 0;
+  tRecurs = tLeaves = tTurns = tDecomps = 0;
+  tAvgDepth = tAvgDecomp = 0.0;
+  tMaxDecomp = tMaxDepth = 0;
+  minDecomp = 10000000; /* arbitrarily large number */
+
+  globalCache = Img_TfmCheckGlobalCache(0);
+  if (globalCache) {
+    flag = Img_TfmGetCacheStatistics(NIL(Img_ImageInfo_t), 0, &inserts,
+				     &lookups, &hits, &entries, &nSlots,
+				     &maxChainLength);
+    tInserts = inserts;
+    tLookups = lookups;
+    tHits = hits;
+    tEntries = entries;
+    tSlots = nSlots;
+  }
+
+  for (i = 0; i < array_n(subFsmArray); i++) {
+    subFsm = array_fetch(Fsm_Fsm_t *, subFsmArray, i);
+    imageInfo = Fsm_FsmReadOrCreateImageInfo(subFsm, 0, 1);
+
+    if (!globalCache) {
+      flag = Img_TfmGetCacheStatistics(imageInfo, 0, &inserts, &lookups, &hits,
+				       &entries, &nSlots, &maxChainLength);
+      if (flag) {
+	tInserts += inserts;
+	tLookups += lookups;
+	tHits += hits;
+	tEntries += entries;
+	tSlots += nSlots;
+      }
+    }
+
+    flag = Img_TfmGetRecursionStatistics(imageInfo, 0, &nRecurs, &nLeaves,
+				 &nTurns, &avgDepth, &maxDepth, &nDecomps,
+				 &topDecomp, &maxDecomp, &avgDecomp);
+    if (flag) {
+      tAvgDepth = (tAvgDepth * (float)tLeaves + avgDepth * (float)nLeaves) /
+		  (float)(tLeaves + nLeaves);
+      tRecurs += nRecurs;
+      tLeaves += nLeaves;
+      tTurns += nTurns;
+      tAvgDecomp = (tAvgDecomp * (float)tDecomps +
+		    avgDecomp * (float)nDecomps) / (float)(tDecomps + nDecomps);
+      tDecomps += nDecomps;
+      if (topDecomp < minDecomp)
+	minDecomp = topDecomp;
+      if (maxDecomp > tMaxDecomp)
+	tMaxDecomp = maxDecomp;
+      if (maxDepth > tMaxDepth)
+	tMaxDepth = maxDepth;
+    }
+  }
+
+  if (tInserts != 0.0) {
+    if (globalCache) {
+      fprintf(vis_stdout,
+	"** global cache statistics of transition function **\n");
+    } else
+      fprintf(vis_stdout, "** cache statistics of transition function **\n");
+    fprintf(vis_stdout, "# insertions = %g\n", tInserts);
+    fprintf(vis_stdout, "# lookups = %g\n", tLookups);
+    fprintf(vis_stdout, "# hits = %g (%.2f%%)\n", tHits,
+      tHits / tLookups * 100.0);
+    fprintf(vis_stdout, "# misses = %g (%.2f%%)\n", tLookups - tHits,
+      (tLookups - tHits) / tLookups * 100.0);
+    fprintf(vis_stdout, "# entries = %g\n", tEntries);
+    if (tSlots > 0) {
+      fprintf(vis_stdout, "# slots = %d\n", tSlots);
+      fprintf(vis_stdout, "maxChainLength = %d\n", maxChainLength);
+    }
+  }
+
+  if (tRecurs != 0) {
+    fprintf(vis_stdout, "** recursion statistics of transition function **\n");
+    fprintf(vis_stdout, "# recursions = %d\n", tRecurs);
+    fprintf(vis_stdout, "# leaves = %d\n", tLeaves);
+    fprintf(vis_stdout, "# turns = %d\n", tTurns);
+    fprintf(vis_stdout, "# average recursion depth = %g (max = %d)\n",
+	    tAvgDepth, tMaxDepth);
+    fprintf(vis_stdout,
+	    "# decompositions = %d (top = %d, max = %d, average = %g)\n",
+	    tDecomps, minDecomp, tMaxDecomp, tAvgDecomp);
+  }
+}
Index: vis_dev/vis-2.3/src/fsm/fsmCmd.c
===================================================================
--- vis_dev/vis-2.3/src/fsm/fsmCmd.c	(revision 14)
+++ vis_dev/vis-2.3/src/fsm/fsmCmd.c	(revision 14)
@@ -0,0 +1,2720 @@
+/**CFile***********************************************************************
+
+  FileName    [fsmCmd.c]
+
+  PackageName [fsm]
+
+  Synopsis    [Commands for the FSM package.]
+
+  Author      [Shaker Sarwary, Tom Shiple, Rajeev Ranjan, In-Ho Moon, Kavita Ravi]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "fsmInt.h"
+
+static char rcsid[] UNUSED = "$Id: fsmCmd.c,v 1.122 2005/05/19 03:21:37 awedh Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+static jmp_buf timeOutEnv;
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandComputeReach(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandReadFairness(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandResetFairness(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandPrintFairness(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandPrintImageInfo(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandPrintHdOptions(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandPrintArdcOptions(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandPrintTfmOptions(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandPrintHybridOptions(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandPrintMlpOptions(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandPrintGuidedSearchOptions(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static void TimeOutHandle(void);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the FSM package.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_End]
+
+******************************************************************************/
+void
+Fsm_Init(void)
+{
+  Cmd_CommandAdd("compute_reach",   CommandComputeReach,   0);
+  Cmd_CommandAdd("read_fairness",   CommandReadFairness,   0);
+  Cmd_CommandAdd("reset_fairness",  CommandResetFairness,  0);
+  Cmd_CommandAdd("print_fairness",  CommandPrintFairness,  0);
+  Cmd_CommandAdd("print_img_info",  CommandPrintImageInfo, 0);
+  Cmd_CommandAdd("print_hd_options",  CommandPrintHdOptions, 0);
+  Cmd_CommandAdd("print_guided_search_options",  CommandPrintGuidedSearchOptions, 0);
+  Cmd_CommandAdd("print_ardc_options",  CommandPrintArdcOptions, 0);
+  Cmd_CommandAdd("print_tfm_options",  CommandPrintTfmOptions, 0);
+  Cmd_CommandAdd("print_hybrid_options",  CommandPrintHybridOptions, 0);
+  Cmd_CommandAdd("print_mlp_options",  CommandPrintMlpOptions, 0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Ends the FSM package.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_Init]
+
+******************************************************************************/
+void
+Fsm_End(void)
+{
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the compute_reach command.]
+
+  Description [If no network or FSM exists, does nothing. Otherwise, the set
+  of reachablestates is calculated by computing least fixed point of the
+  initial states under the next state functions of the FSM.  The option [-v n]
+  specifies the verbosity level.  If n is greater than 0, summary information
+  is printed.  If n is greater than 1, intermediate information is printed.]
+
+  CommandName [compute_reach]
+
+  CommandSynopsis [compute the set of reachable states of the FSM]
+
+  CommandArguments [\[-d &lt;depthValue&gt;\] \[-f\] \[-g &lt;file&gt;\] \[-h\] \[-i\] \[-r &lt;thresholdValue&gt;\] \[-s &lt;printStep&gt;\] \[-t &lt;timeOut&gt;\] \[-v #\] \[-A #\] \[-D\] \[-F\]]
+
+  CommandDescription [Compute the set of reachable states of the FSM
+  associated with the flattened network.  The command
+  <tt>build_partition_mdds</tt> (or <tt>init_verify</tt>) must have
+  already been invoked on the flattened network, before this command
+  is called.  On subsequent calls to compute_reach, the reachable
+  states will not be recomputed, but statistics can be printed using
+  -v. To force recomputation with a different set of options, for
+  example a depth value with -d, use -F option. <p>
+
+  The method used for image computation is displayed by the option
+  <tt>-v 1</tt>.  To change the image computation method, use the
+  command <tt>set image_method</tt>, and then start again with the
+  command <tt>flatten_hierarchy</tt>.  The reachability computation
+  makes extensive use of image computation. There are several
+  user-settable options that can be used to affect the performance of
+  image computation.  See the documentation for the <tt>set</tt>
+  command for these options.<p>
+  
+  Command options:<p>
+
+  <dl>
+
+  <dt> -d &lt;depthValue&gt;
+  <dd> Perform reachability for depthValue steps only - this option
+  specifies the number of unit operations (image computations) to be
+  performed in the reachability computation. The depthValue used in
+  successive calls proceeds from the previous state. For example,
+  compute_reach -d 3; compute_reach -d 4; will perform 7 steps of
+  reachability in total, the second call to compute_reach proceeding
+  from the result of the first. While using only -A 0 option
+  (default), this additionally corresponds to the depth in the state
+  graph, starting from the initial state.  For the -A 1 option, the
+  above may not be true. This option is not compatible with -A 2. <p>
+
+  <dt> -f
+  <dd> Store the set of new states (onion rings) reached at each step
+  of reachability. If this flag is specified, then the computation
+  proceeds with the previously set of onion rings, if any exist (not
+  any prior computation without onion rings). This option is likely to
+  use more memory during reachability analysis. This is not compatible
+  with -A 2. <p>
+
+  <dt> -g &lt;<code>hints_file</code>&gt; <dd> Use guided search.  The
+  file <code>hints_file</code> contains a series of hints.  A hint is
+  a formula that does not contain any temporal operators, so
+  <code>hints_file</code> has the same syntax as a file of invariants
+  used for check_invariant.  The hints are used in the order given to
+  change the transition relation.  The transition relation is
+  conjoined with the hint to yield an underapproximation of the
+  transition relation.  If the hints are cleverly chosen, this may
+  speed up the computation considerably, because a search with the
+  changed transition relation may be much simpler than one with the
+  original transition relation, and results obtained can be reused, so
+  that we may never have to do an expensive search with the original
+  relation.  See also: Ravi and Somenzi, Hints to accelerate symbolic
+  traversal. CHARME'99; Bloem, Ravi, and Somenzi, Efficient Decision
+  Procedures for Model Checking of Linear Time Logic Properties,
+  CAV'99; Bloem, Ravi, and Somenzi, Symbolic Guided Search for CTL
+  Model Checking, DAC'00. Not allowed with -A 2 or -i, and will only
+  work with iwls95 or monolithic image methods.  The description of
+  some options for guided search can be found in the help page for
+  print_guided_search_options. <p>
+  
+  <dt> -h
+  <dd> Print the command usage.<p>
+
+  <dt> -i <dd> This option is useful when it's not possible to build the
+  complete transition relation. Using this option, the transition relation is
+  rebuilt at every itereation using the current reached set of states as the
+  care set. This option is not compatible with the -A > 0 options, the -D
+  option and the -g option.<p>
+
+  <dt> -r &lt;thresholdValue&gt;
+  <dd> Dynamic reordering (with method sift) is invoked once when the size
+  of the reachable state set reaches the threshold value.<p>
+
+  <dt> -s &lt;printStep&gt;
+  <dd> At every printStep of the reachability computation, print the total
+  number of states reached thus far, and the size of the MDD representing this
+  set.<p>
+
+  <dt> -t &lt;timeOut&gt; 
+  <dd> Time allowed to perform reachability (in seconds).  Default is infinity.<p>
+
+  <dt> -v #
+  <dd> Print debug information.
+  <dd>
+  0: (default) Nothing is printed out.<p>
+
+  1: Print a summary of reachability analysis and some information
+  about the image computation method (see <tt>print_img_info</tt>) and
+  summarizes results of reachability:
+
+  <dd>
+  <dd> <b>FSM depth:</b> the farthest reachable state
+  <dd> <b>reachable states:</b> the number of reachable states
+  <dd> <b>MDD size:</b> the size of the MDD representing the reachable states 
+  <dd> <b>analysis time:</b> number of CPU seconds taken to compute the
+  reachable states<p> 
+
+  2: Prints the detailed information about reachability analysis. For
+  each <tt> printStep</tt>, it prints the MDD size of the reachable
+  state set and the number of states in the set. <p>
+
+  <dt> -A #
+  <dd> This option allows specification of approximate reachability
+  computation. <p>
+
+  0:  (default) Breadth First Search. No approximate reachability
+  computation. <p>
+
+  1: High Density Reachability Analysis (HD). Computes reachable states in a
+  manner that keeps BDD sizes under control. May be faster than BFS in some
+  cases. For larger circuits, this option should compute more reachable
+  states. For help on controlling options for HD, look up help on the command:
+  print_hd_options <A HREF="print_hd_optionsCmd.html">
+  <code>print_hd_options</code></A>.  Refer to Ravi and Somenzi, ICCAD95. This
+  option is available only when VIS is linked with the CUDD package.  <p>
+  
+  2. Approximate Reachability Don't Cares(ARDC). Computes over-approximate
+  reachable states. For help on controlling options for ARDC, look up help on
+  the command: print_ardc_options <A HREF="print_ardc_optionsCmd.html">
+  <code>print_ardc_options</code></A>.  Refer Moon's paper, ICCAD98 and 2
+  papers by Cho et al, December TCAD96: one is for State Space Decomposition
+  and the other is for Approximate FSM Traversal. The options -d, -g and -f are
+  not compatible with this option. <p>
+
+  <dt> -D <dd> First compute an overapproximation to the reachable states.
+  Minimize transition relation using this approximation, and then compute the
+  set of reachable states exactly. This may accelerate reachability
+  analysis. Refer to the paper by Moon et al, ICCAD98. The BDD minimizing
+  method can be chosen by using "set image_minimize_method <method>" <A HREF =
+  "setCmd.html"><code>set</code></A>.  This option is incompatible with -i.
+  <p>
+
+  <dt> -F
+  <dd> Force to recompute reachable states.
+  <p>
+
+  <dt> Related "set" options: <p>
+  <dt> rch_simulate &lt;#&gt;
+  <dd> The set option can be used to set this flag rch_simulate to specify the
+  number of random vectors to be simulated. Default value for this number is 0.
+  <p>
+  
+  ]
+
+  SideEffects [The reachable states, depth, initial states of the FSM are
+  stored.]
+
+******************************************************************************/
+static int
+CommandComputeReach(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int        c;
+  mdd_t      *reachableStates = NIL(mdd_t);
+  mdd_t      *initialStates;
+  long        initialTime;
+  long        finalTime;
+  static int  verbosityLevel;
+  static int  printStep;
+  static int  timeOutPeriod;
+  Fsm_Fsm_t  *fsm = Fsm_HrcManagerReadCurrentFsm(*hmgr);
+  static int reorderFlag;
+  static int reorderThreshold;
+  static int shellFlag;
+  static int depthValue;
+  static int incrementalFlag;
+  static int approxFlag;
+  static int ardc;
+  static int recompute;
+  Fsm_RchType_t rchType;
+  FILE *guideFile = NIL(FILE); /* file of hints for guided search */
+  array_t *guideArray = NIL(array_t);
+  Img_MethodType imgMethod;
+  
+  /*
+   * These are the default values.  These variables must be declared static
+   * to avoid lint warnings.  Since they are static, we must reinitialize
+   * them outside of the variable declarations.
+   */
+  verbosityLevel = 0;
+  printStep      = 0;
+  timeOutPeriod  = 0;
+  shellFlag = 0;
+  depthValue = 0;
+  incrementalFlag = 0;
+  rchType = Fsm_Rch_Default_c;
+  approxFlag = 0;
+  ardc = 0;
+  recompute = 0;
+
+  /*
+   * Parse command line options.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "d:fg:hir:s:t:v:A:DF")) != EOF) {
+    switch(c) {
+      case 'd':
+        depthValue = atoi(util_optarg);
+        break;
+      case 'f':
+        shellFlag = 1;
+        break;
+      case 'g':
+	  guideFile = Cmd_FileOpen(util_optarg, "r", NIL(char *), 0);
+	  if (guideFile == NIL(FILE)) {
+	    fprintf(vis_stdout,
+		    "** rch error: Guide file cannot be read. Check permissions and path\n");
+	    goto usage;
+	  }
+          break;  
+      case 'h':
+        goto usage;
+      case 'i':
+        incrementalFlag = 1;
+        break;
+      case 'r':
+        reorderFlag = 1;
+        reorderThreshold = atoi(util_optarg);
+        break;
+      case 's':
+        printStep = atoi(util_optarg);
+        break;
+      case 't':
+        timeOutPeriod = atoi(util_optarg);
+        break;
+      case 'v':
+        verbosityLevel = atoi(util_optarg);
+        break;
+      case 'A' :
+        approxFlag = atoi(util_optarg);
+	if ((approxFlag > 2) || (approxFlag < 0)) {
+	    goto usage;
+	}
+        break;
+      case 'D':
+        ardc = 1;
+        break;
+      case 'F':
+        recompute = 1;
+        break;
+      default:
+        goto usage;
+    }
+  }
+  if (c == EOF && argc != util_optind)
+    goto usage;
+  
+  imgMethod = Img_UserSpecifiedMethod(); 
+    
+  if ((approxFlag == 1) && (bdd_get_package_name() != CUDD)) {
+    fprintf(vis_stderr, "** rch error: compute_reach with -A 1 option is currently supported only by CUDD.\n");
+    return 1;
+  }
+
+  if (fsm == NIL(Fsm_Fsm_t)) {
+    return 1;
+  }
+
+  if (incrementalFlag && approxFlag) {
+      fprintf(vis_stdout,
+	      "** rch error: Incremental flag and approx flag are incompatible.\n");
+      goto usage;
+  }
+  if (incrementalFlag && ardc) {
+      fprintf(vis_stdout,
+	      "** rch error: The -i and -D flags are incompatible.\n");
+      goto usage;
+  }
+
+  if (depthValue && approxFlag == 2) {
+    fprintf(vis_stdout,
+	    "** rch error: Depth value and over-approx flag are incompatible.\n");
+    goto usage;
+  }
+  
+  if (shellFlag && approxFlag == 2) {
+    fprintf(vis_stdout,
+	    "** rch error: Shell flag and over-approx flag are incompatible.\n");
+    goto usage;
+  }
+  
+  if (guideFile != NIL(FILE)){
+    if(incrementalFlag) {
+      fprintf(vis_stdout, "** rch error: Guided search is not compatible with the -i flag\n");
+      goto usage;
+    }
+    if(approxFlag == 2){
+      fprintf(vis_stdout, "** rch error: Guided search is not compatible with Over-approx flag\n");
+      goto usage;
+    }
+    if(imgMethod != Img_Iwls95_c && imgMethod != Img_Monolithic_c &&
+       imgMethod != Img_Mlp_c){
+      fprintf(vis_stdout, "** rch error: Guided search can only be performed\n");
+      fprintf(vis_stdout, "with IWLS95, MLP, or Monolithic image methods.\n");
+    goto usage;
+    }
+  }/* if guided search requested */
+  
+  /* Start the timeOut timer. */
+  if (timeOutPeriod > 0){
+    (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
+    (void) alarm(timeOutPeriod);
+    if (setjmp(timeOutEnv) > 0) {
+      (void) fprintf(vis_stdout, "** rch info: Timeout occurred after %d seconds.\n",
+                     timeOutPeriod);
+      (void) fprintf(vis_stdout, "** rch warning: The time out may have "
+		     "corrupted the data.\n");
+     alarm(0);
+      return 1;
+    }
+  }
+
+  /* Make sure that the initial states can be computed without a problem. */
+  error_init();
+  initialStates = Fsm_FsmComputeInitialStates(fsm);
+  if (initialStates == NIL(mdd_t)) {
+    (void) fprintf(vis_stderr, "** rch error: Latch initialization function depends on another latch:\n");
+    (void) fprintf(vis_stderr, "%s", error_string());
+    (void) fprintf(vis_stderr, "\n");
+    (void) fprintf(vis_stderr, "** rch error: Initial states cannot be computed.\n");
+    return (1);
+  }
+  else {
+    mdd_free(initialStates);
+  }
+
+  /* translate approx flag */
+  switch(approxFlag) {
+  case 0: rchType = Fsm_Rch_Bfs_c; break;
+  case 1: rchType = Fsm_Rch_Hd_c; break;
+  case 2: rchType = Fsm_Rch_Oa_c; break;
+  default: rchType = Fsm_Rch_Default_c; break;
+  }
+
+  if (guideFile != NIL(FILE)) {
+    guideArray = Mc_ComputeGuideArray(fsm, guideFile);
+    if(guideArray == NIL(array_t))
+      return(1);
+  }
+
+  if (rchType == Fsm_Rch_Oa_c) {
+    array_t	*apprReachableStates;
+
+    initialTime = util_cpu_time();
+    apprReachableStates = Fsm_FsmComputeOverApproximateReachableStates(fsm,
+	incrementalFlag, verbosityLevel, printStep, depthValue, shellFlag,
+	reorderFlag, reorderThreshold, recompute);
+    finalTime = util_cpu_time();
+
+    if (apprReachableStates == NIL(array_t)) {
+      (void)fprintf(vis_stdout,
+	"** rch error: Reachability computation failed, no rechable states\n");
+      return 1;
+    }
+
+    if (verbosityLevel > 0)
+      Fsm_ArdcPrintReachabilityResults(fsm, finalTime-initialTime);
+    alarm(0);
+    return(0);
+  }
+
+  /* Compute the reachable states. */
+  initialTime = util_cpu_time();
+  reachableStates = Fsm_FsmComputeReachableStates(
+    fsm, incrementalFlag, verbosityLevel, printStep, depthValue, shellFlag,
+    reorderFlag, reorderThreshold, rchType, ardc, recompute, NIL(array_t),
+    (verbosityLevel > 0), guideArray);  
+  finalTime = util_cpu_time();
+  mdd_array_free(guideArray);
+
+  if (reachableStates == NIL(mdd_t)) {
+    (void)fprintf(vis_stdout, "** rch error: Reachability computation failed, no rechable states\n");
+    return 1;
+  }
+
+  if (verbosityLevel > 0){
+    if (fsm->imageInfo){ 
+      char *methodType =
+          Img_ImageInfoObtainMethodTypeAsString(fsm->imageInfo); 
+      (void) fprintf(vis_stdout, "** rch info: Computing reachable states using the ");
+      (void) fprintf(vis_stdout, "%s image computation method.\n", methodType);
+      FREE(methodType);
+      (void)Img_ImageInfoPrintMethodParams(fsm->imageInfo,
+                                           vis_stdout);
+      if (Img_ImageInfoObtainMethodType(fsm->imageInfo) == Img_Tfm_c ||
+	  Img_ImageInfoObtainMethodType(fsm->imageInfo) == Img_Hybrid_c) {
+	Img_TfmPrintStatistics(fsm->imageInfo, Img_Forward_c);
+      }
+    }
+    Fsm_FsmReachabilityPrintResults(fsm, finalTime-initialTime, approxFlag);
+
+  }
+  mdd_free(reachableStates);
+
+  alarm(0);
+  return (0);
+
+  usage:
+  (void) fprintf(vis_stderr, "usage: compute_reach [-d depthValue] [-h] [-f] [-i] [-g <hint file>][-r thresholdValue] [-s printStep] [-t timeOut] [-v #][-A #][-D][-F]\n");
+  (void) fprintf(vis_stderr, "   -d depthValue perform reachability up to depthValue steps\n");
+  (void) fprintf(vis_stderr, "   -f \t\t store the onion rings ateach step\n");
+  (void) fprintf(vis_stderr, "   -h \t\t print the command usage\n");
+  (void) fprintf(vis_stderr, "   -g filename\t perform reachability analysis with guided search using the given file. Not allowed with -A 2\n");
+  (void) fprintf(vis_stderr, "   -i \t\t builds the transition relation incrementally (not supported with -A 1,2).\n");
+  (void) fprintf(vis_stderr, "   -r thresholdValue invoke dynamic reordering once when the size of the reached state set reaches this value.\n");
+  (void) fprintf(vis_stderr, "   -s printStep\t print reachability information every printStep steps (0 for no information).\n");
+  (void) fprintf(vis_stderr, "   -t time\t time out period (in seconds)\n");
+  (void) fprintf(vis_stderr, "   -v #\t\t verbosity level\n");
+  (void) fprintf(vis_stderr, "   -A #\t\t 0 (default) - BFS method.\n");
+  (void) fprintf(vis_stderr, "      #\t\t 1 - HD method.\n");
+  (void) fprintf(vis_stderr, "      #\t\t 2 - Over-approximation by approximate traversal.\n");
+  (void) fprintf(vis_stderr, "   -D \t\t Try to minimize transition relation with ARDCs\n");
+  (void) fprintf(vis_stderr, "   -F \t\t force to recompute reachable states\n");
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the read_fairness command.]
+
+  Description [If no network or FSM exists, does nothing. Otherwise, parses
+  the CTL formulas in the input file, and creates a fairness constraint data
+  structure to store them.  Currently, only Buchi constraints are parsed.
+  This command does not do any computation on the fairness constraint.]
+
+  Comment [To support Streett conditions, we need a delimiter in the input
+  file to group finallyInf/globallyInf pairs (a "horizontal" delimiter).  To
+  support canonical fairness constraints, we additionally need a "vertical"
+  delimiter to group different disjuncts.]
+
+  CommandName [read_fairness]
+
+  CommandSynopsis [read a fairness constraint]
+
+  CommandArguments [\[-h\] &lt;file&gt;]
+  
+  CommandDescription [Read a fairness constraint, and associate this
+  constraint with the FSM of the flattened network.  An existing constraint
+  associated with the FSM is lost. Subsequent verification procedures are
+  performed relative to the new constraint. Note that, by default, the
+  flattened network has the constraint TRUE, indicating that all paths are
+  fair. The command <tt>build_partition_mdds</tt> (or <tt>init_verify</tt>)
+  must have already been invoked on the flattened network, before this command
+  is called.<p>
+
+  Currently, only Buchi constraints are supported. A Buchi fairness constraint
+  is given by a list of individual Buchi conditions, B1, B2, ..., Bk, where Bi
+  is a set of FSM states.  A state is fair if there exists an infinite path
+  from that state that intersects each Bi infinitely often.<p>
+
+  The conditions are specified by a file containing at least one CTL formula
+  (see the <A HREF="../ctl/ctl/ctl.html"> VIS CTL and LTL syntax manual</A>).  In
+  particular, Bi is defined by a CTL formula, which represents the set of
+  states that makes the formula true (in the absence of any fairness
+  constraint).  References to signal names in the network should be made using
+  the full hierarchical names.  Note that the support of any wire referred to
+  in a formula should consist only of latches. Each CTL formula is terminated
+  by a semicolon.<p>
+
+  Example: In the three conditions below, B1 contains those states that have a
+  next state where cntr.out is RED, B2 contains those where timer.active is 1,
+  and B3 contains those states for which every path from the state has
+  tlc.request=1 until tlc.acknowledge=1.<p>
+
+  <pre>
+  EX(cntr.out=RED);
+  (timer.active=1);
+  A(tlc.request=1 U tlc.acknowledge=1);
+  </pre>
+
+  Command options:<p>  
+
+  <dl>
+
+  <dt> -h
+  <dd> Print the command usage.<p> 
+
+  <dt> &lt;file&gt;
+  <dd> File containing the set of Buchi conditions.<p> 
+  
+  </dl>
+  ]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandReadFairness(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int       c;
+  FILE      *fp;
+  array_t   *formulaArray;
+  Fsm_Fsm_t *fsm = Fsm_HrcManagerReadCurrentFsm(*hmgr);
+  
+  /*
+   * Parse command line options.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "h")) != EOF) {
+    switch(c) {
+      case 'h':
+        goto usage;
+      default:
+        goto usage;
+    }
+    /* NOT REACHED */
+  }
+
+  if (fsm == NIL(Fsm_Fsm_t)) {
+    (void) fprintf(vis_stderr, "** fair error: Fairness constraint not recorded.\n");
+    return 1;
+  }
+
+  /*
+   * Open the fairness file.
+   */
+  if (argc - util_optind == 0) {
+    (void) fprintf(vis_stderr, "** fair error: fairness file not provided\n");
+    goto usage;
+  }
+  else if (argc - util_optind > 1) {
+    (void) fprintf(vis_stderr, "** fair error: too many arguments\n");
+    goto usage;
+  }
+
+  fp = Cmd_FileOpen(argv[util_optind], "r", NIL(char *), 0);
+  if (fp == NIL(FILE)) {
+    return 1;
+  }
+
+  /*
+   * Parse the formulas in the file.
+   */
+  formulaArray = Ctlp_FileParseFormulaArray(fp);
+  (void) fclose(fp);
+
+  if (formulaArray == NIL(array_t)) {
+    (void) fprintf(vis_stderr, "** fair error: error reading fairness conditions.\n");
+    return 1;
+  }
+  else if (array_n(formulaArray) == 0) {
+    (void) fprintf(vis_stderr, "** fair error: fairness file is empty.\n");
+    (void) fprintf(vis_stderr, "** fair error: Use reset_fairness to reset the fairness constraint.");
+    return 1;
+  }
+  else {
+    int             j;
+    Fsm_Fairness_t *fairness;
+    Ntk_Network_t  *network = Fsm_FsmReadNetwork(fsm);
+
+    /*
+     * First check that each formula is semantically correct wrt the network.
+     */
+    error_init();
+    for (j = 0; j < array_n(formulaArray); j++) {
+      Ctlp_Formula_t *formula;
+      boolean         status; 
+      
+      formula  = array_fetch(Ctlp_Formula_t *, formulaArray, j);
+      status = Mc_FormulaStaticSemanticCheckOnNetwork(formula, network, FALSE);
+      
+      if (status == FALSE) {
+        (void) fprintf(vis_stderr,
+		       "** fair error: error reading fairness constraint "); 
+        Ctlp_FormulaPrint(vis_stderr, formula);
+        (void) fprintf(vis_stderr, ":\n");
+        (void) fprintf(vis_stderr, "%s", error_string());
+        (void) fprintf(vis_stderr, "\n");
+        return 1;
+      }
+    }
+
+
+    /*
+     * Interpret the array of CTL formulas as a set of Buchi conditions.
+     * Hence, create a single disjunct, consisting of k conjuncts, where k is
+     * the number of CTL formulas read in.  The jth conjunct has the jth
+     * formula as its finallyInf component, and NULL as its globallyInf
+     * component.
+     */
+    fairness = FsmFairnessAlloc(fsm);    
+    for (j = 0; j < array_n(formulaArray); j++) {
+      Ctlp_Formula_t *formula = array_fetch(Ctlp_Formula_t *, formulaArray, j);
+
+      FsmFairnessAddConjunct(fairness, formula, NIL(Ctlp_Formula_t), 0, j);
+    }
+    array_free(formulaArray); /* Don't free the formulas themselves. */
+
+    /*
+     * Remove any existing fairnessInfo associated with the FSM, and update
+     * the fairnessInfo.constraint with the new fairness just read.
+     */
+    FsmFsmFairnessInfoUpdate(fsm, NIL(mdd_t), fairness, NIL(array_t));
+
+    return 0;
+  }
+
+  usage:
+  (void) fprintf(vis_stderr, "usage: read_fairness [-h] file\n");
+  (void) fprintf(vis_stderr, "   -h    print the command usage\n");
+  (void) fprintf(vis_stderr, "   file  file containing the list of conditions\n");
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the reset_fairness command.]
+
+  Description [If no network or FSM exists, does nothing. Otherwise, resets
+  the fairnessInfo associated with the FSM to the default case.]
+
+  CommandName [reset_fairness]
+
+  CommandSynopsis [reset the fairness constraint]
+
+  CommandArguments [\[-h\]]
+  
+  CommandDescription [Remove any existing fairness constraint associated with
+  the FSM of the flattened network, and impose a single constraint, TRUE,
+  indicating that all states are "accepting".<p>
+
+  Command options:<p>  
+
+  <dl>
+
+  <dt> -h
+  <dd> Print the command usage.<p>  
+
+  </dl>
+  ]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandResetFairness(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int       c;
+  Fsm_Fsm_t *fsm = Fsm_HrcManagerReadCurrentFsm(*hmgr);
+
+  /*
+   * Parse command line options.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "h")) != EOF) {
+    switch(c) {
+      case 'h':
+        goto usage;
+      default:
+        goto usage;
+    }
+    /* NOT REACHED */
+  }
+
+  if (fsm == NIL(Fsm_Fsm_t)) {
+    return 1;
+  }
+
+  /*
+   * Remove any existing fairnessInfo associated with the FSM, and add back
+   * the default constraint.
+   */
+  FsmFsmFairnessInfoUpdate(fsm, NIL(mdd_t), NIL(Fsm_Fairness_t), NIL(array_t));
+  fsm->fairnessInfo.constraint = FsmFsmCreateDefaultFairnessConstraint(fsm);
+
+  return 0;
+
+
+  usage:
+  (void) fprintf(vis_stderr, "usage: reset_fairness [-h]\n");
+  (void) fprintf(vis_stderr, "   -h  print the command usage\n");
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the print_fairness command.]
+
+  Description [If no network or FSM exists, does nothing. Otherwise, prints
+  the fairness constraint associated with the FSM.  If no fairness
+  constraint exists, then prints a message to that affect.]
+
+  CommandName [print_fairness]
+
+  CommandSynopsis [print the fairness constraint of the flattened network]
+
+  CommandArguments [\[-h\]]
+  
+  CommandDescription [Print the fairness constraint (i.e the set of Buchi
+  conditions) associated with the FSM of the flattened network.  By default,
+  the flattened network has the single constraint TRUE, indicating that all
+  paths are fair.<p>
+
+  Command options:<p>  
+
+  <dl>
+
+  <dt> -h
+  <dd> Print the command usage.<p>  
+
+  </dl>
+  ]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandPrintFairness(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int            c;
+  Fsm_Fairness_t *constraint;
+  int             numDisjuncts;
+  Fsm_Fsm_t      *fsm = Fsm_HrcManagerReadCurrentFsm(*hmgr);
+
+  /*
+   * Parse command line options.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "h")) != EOF) {
+    switch(c) {
+      case 'h':
+        goto usage;
+      default:
+        goto usage;
+    }
+    /* NOT REACHED */
+  }
+
+  if (fsm == NIL(Fsm_Fsm_t)) {
+    return 1;
+  }
+
+  /*
+   * Print the fairness constraint.  It is assumed that there is at least one
+   * disjunct present.  Currently, only Buchi constraints can be printed out.
+   */
+  constraint = Fsm_FsmReadFairnessConstraint(fsm);
+  assert(constraint != NIL(Fsm_Fairness_t));
+  numDisjuncts = Fsm_FairnessReadNumDisjuncts(constraint);
+  assert(numDisjuncts != 0);
+
+  if (numDisjuncts > 1) {
+    (void) fprintf(vis_stdout, "Fairness constraint not Buchi...");
+    (void) fprintf(vis_stdout, "don't know how to print.\n");
+  }
+  else {
+    int i;
+    int numConjuncts = Fsm_FairnessReadNumConjunctsOfDisjunct(constraint, 0);
+
+    (void) fprintf(vis_stdout, "Fairness constraint:\n");
+    for (i = 0; i < numConjuncts; i++) {
+      if (Fsm_FairnessReadGloballyInfFormula(constraint, 0, i) !=
+          NIL(Ctlp_Formula_t)) {
+        (void) fprintf(vis_stdout, "Fairness constraint not Buchi...");
+        (void) fprintf(vis_stdout, "don't know how to print.\n");
+      }
+        
+      Ctlp_FormulaPrint(vis_stdout,
+                        Fsm_FairnessReadFinallyInfFormula(constraint, 0, i));
+      (void) fprintf(vis_stdout, ";\n");
+    }
+  }
+
+  return 0;
+
+  usage:
+  (void) fprintf(vis_stderr, "usage: print_fairness [-h]\n");
+  (void) fprintf(vis_stderr, "   -h  print the command usage\n");
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the print_img_info command.]
+
+  CommandName [print_img_info]
+
+  CommandSynopsis [print information about the image method currently
+  in use]
+
+  CommandArguments [\[-b\] \[-f\] \[-h\] ]
+
+  CommandDescription [Prints information about the image computation method
+  currently being used by the FSM. This includes the particular values of
+  parameters used by the method for initialization.  If the image information
+  does not exist, then this command forces the information to be
+  computed. If none of the flags (-b or -f) is set, forward
+  transition relation is computed. <p>
+
+  Command options: <p>
+
+  <dl>
+
+  <dt> -b
+  <dd> Compute the transition relation for backward image computation
+  (if needed).<p>
+
+  <dt> -f
+  <dd> Compute the transition relation for forward image computation
+  (if needed).<p>
+
+  <dt> -h
+  <dd> Print the command usage.<p>
+  
+  </dl>]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandPrintImageInfo(Hrc_Manager_t ** hmgr, int  argc, char ** argv)
+{
+  int c;
+  Img_ImageInfo_t *imageInfo;
+  Fsm_Fsm_t       *fsm = Fsm_HrcManagerReadCurrentFsm(*hmgr);
+  int bwdImgFlag = 0;
+  int fwdImgFlag = 0;
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "bfh")) != EOF) {
+    switch(c) {
+      case 'b':
+        bwdImgFlag = 1;
+        break;
+      case 'f':
+        fwdImgFlag = 1;
+        break;
+      case 'h':
+        goto usage;
+      default:
+        goto usage;
+    }
+  }
+
+  if (fsm == NIL(Fsm_Fsm_t)) {
+    return 1;
+  }
+
+  if (!(bwdImgFlag || fwdImgFlag)){
+    fwdImgFlag = 1;
+  }
+
+  imageInfo = Fsm_FsmReadOrCreateImageInfo(fsm, bwdImgFlag, fwdImgFlag);
+  Img_ImageInfoPrintMethodParams(imageInfo, vis_stdout);
+  return 0;
+
+usage:
+  (void) fprintf(vis_stderr,"usage: print_image_method [-b] [-f] [-h]\n");
+  (void) fprintf(vis_stderr, "  -b  create the backward transition relation\n");
+  (void) fprintf(vis_stderr, "  -f  create the forward transition relation\n");
+  (void) fprintf(vis_stderr, "  -h  print the command usage\n");
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the print_hd_options command.]
+
+  CommandName [print_hd_options]
+
+  CommandSynopsis [print information about the HD options currently
+  in use]
+
+  CommandArguments [\[-h\] ]
+
+  CommandDescription [Prints information about the current HD options.
+  The HD method is an alternate method to compute a least fixpoint and
+  is provided with the compute_reach and check_invariant commands.
+  The method is described in Ravi and Somenzi, ICCAD95. The command
+  can be used only when compiled with the CUDD package.  <p>
+
+  Command options: <p>
+
+  <dt> -h
+  <dd> Print the command usage.<p>
+  
+  </dl>
+
+  Set parameters: The HD options are specified with the set command.
+
+  <dl>
+  <dt> hd_frontier_approx_method &lt;method&gt;
+  <dd> This option specifes
+  the method to approximate the frontier set. <p>
+
+  Methods: <p>
+  remap_ua : (Default) The BDD approximation method of DAC98 Ravi,
+  Shiple, McMillan, Somenzi. <p>
+  biased_rua : Approximation method similar to remap_ua, but uses
+  a bias function. The bias function is set appropriate to the context. <p>
+  under_approx : The BDD approximation method of Shiple's thesis. <p>
+  heavy_branch : The BDD approximation method of ICCAD95 Ravi,
+  Somenzi. <p>
+  short_paths : The BDD approximation method of ICCAD95 Ravi,
+  Somenzi. <p>
+  compress : An approximation method that runs short_paths first
+  and then remap_ua. <p>
+
+  <dt> hd_frontier_approx_threshold &lt;number&gt;
+  <dd> This option specifes the size of the frontier to be used for
+  image computation. The threshold for the various methods is
+  approximate (not strictly adhered to). For the remap_ua and
+  biased_rua method, this threshold is a lower bound and the default
+  is 3500. For the short_paths and heavy_branch methods, this threshold
+  is an upper bound. Therefore, a default of 2000 is set to obtain a
+  meaningful result. Any value lower than 2000 is corrected to this
+  default. This value is also relevant for dead-end computations. In a
+  dead-end, the threshold for each image computation (of a disjunct of
+  Reached) is five times the frontier approximation threshold. When
+  the frontier approximation threshold is 0, the threshold for each
+  dead-end image computation is 5000. <p>
+
+  <dt> hd_approx_quality &lt;double&gt
+  <dd> This option specifies the quality factor for the under_approx
+  and remap_ua methods. Default value is 1.0. The range is any
+  double value greater than 0. Smaller quality factors produce smaller
+  results. Meaningful values are between 1 and 2.  <p>
+
+  <dt> hd_approx_bias_quality &lt;double&gt
+  <dd> This option specifies the quality factor for the biased_rua
+  method. Default value is 0.5. The range is any
+  double value greater than 0. Smaller quality factors produce smaller
+  results. Meaningful values are between 0 and 1.<p>
+
+  <dt> hd_dead_end &lt;method&gt
+  <dd> This option specifies the method used for dead-end
+  computation. A "dead-end" is characterized by an empty
+  frontier. A dead-end computation involves generating new states from
+  the reached set. <p>
+
+  Methods:<p>
+  brute_force : Computes the image of the entire reached
+  set. May be fatal if the reached set is very large. <p> 
+  conjuncts : (Default) Computes the image of reached by
+  decomposing into parts. <p>
+  hybrid : Computes the image of a subset of reached. If no
+  new states, then the reaminder is decomposed in parts. <p>
+
+  <dt> hd_dead_end_approx_method &lt;method&gt;
+  <dd> This option allows the specification of the approximation
+  method to use to compute the subset of Reached at the dead-end. The
+  threshold used is the same as hd_frontier_approx_threshold.<p>
+
+  For methods, refer hd_frontier_approx_method methods. Default is remap_ua.<p>
+
+  <dt> hd_no_scrap_states
+  <dd> This allows the option of not adding the "scrap" states. Scrap
+  states are residues from the approximation of the frontier set. 
+  Default is to add the scrap states. <p>
+
+  <dt> hd_new_only
+  <dd> This allows the option of adding considering only new states of
+  each iteration for image computation. The default is to take a set in
+  the interval of the new states and the reached set. <p>
+
+  <dt> hd_only_partial_image
+  <dd> This allows the option of HD with partial image computation
+  only (no approximation of the frontier set).  Default is to allow both
+  partial images and approximation of the frontier set. <p>
+
+  <dt> Partial Image options: <p>
+
+  <dt> hd_partial_image_method &lt;method&gt
+  <dd> This option allows the image computation to approximate the
+  image with the specified method. <p>
+  Methods:<p>
+  approx : (Default) Computes a partial image by
+  under-approximating the intermediate products of image computation.
+  <p>
+  clipping : Computes a partial image by "clipping" the
+  depth of recursion of the and-abstract computations during image
+  computation. <p>
+
+  <dt> hd_partial_image_threshold &lt;number&gt
+  <dd> This options allows the specification of a threshold (in terms
+  of bdd node size of the intermediate product) that will trigger
+  approximation of the intermediate product. Default is 200000. This
+  option has to be used in conjunction with hd_partial_image_size. If
+  the value of hd_partial_image_size is larger than this option, then
+  the approximation of the intermediate size will be as large as the
+  hd_partial_image_size number. <p>
+
+  <dt> hd_partial_image_size &lt;number&gt
+  <dd> This options allows the specification of a size (in terms of
+  bdd node size of the intermediate product) that is the target size
+  of the approximated intermediate product. Default is 100000. For the
+  short_paths and heavy_branch methods, the size of the approximation
+  is corrected to 10000 if the size specified is lower. This is
+  because the short_paths and heavy_branch methods consider this size
+  as an upper bound on the approximation. This option has to be used
+  in conjunction with hd_partial_image_threshold. If the value of
+  hd_partial_image_threshold is much larger than this option, then the
+  desired size will not be obtained as approximation may not be 
+  triggered.<p>
+
+  <dt> hd_partial_image_approx &lt;method&gt
+  <dd> This options allows the specification of the method to be used
+  to approximate the intermediate product. <p>
+
+  For methods, refer hd_frontier_approx_method methods. Default is remap_ua.<p>
+
+  <dt> hd_partial_image_approx_quality &lt;double&gt
+  <dd> This option specifies the quality factor for the under_approx
+  and remap_ua methods for partial image computation. Default value is
+  1.0. Range of values is any double greater than 0. Smaller quality
+  factors produce smaller results. Meaningful values are between 1 and
+  2.  <p>
+
+  <dt> hd_partial_image_approx_bias_quality &lt;double&gt
+  <dd> This option specifies the quality factor for the biased_rua
+  method for partial image computation. Default value is
+  0.5. Range of values is any double greater than 0. Smaller quality
+  factors produce smaller results. Meaningful values are between 0 and
+  1. <p>
+
+  <dt> hd_partial_image_clipping_depth &lt;double&gt
+  <dd> This option allows the specification of the depth at which the
+  recursion can be clipped when _hd_partial_image_method_ is
+  clipping. Range of values is between 0 and 1. The clipping depth is
+  then calculated as the specified fraction of the number of
+  variables. Default is 0.4. <p>
+  
+  </dl>
+  ]
+  
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandPrintHdOptions(Hrc_Manager_t ** hmgr, int  argc, char ** argv)
+{
+  int c;
+
+  if (*hmgr == NULL) {
+    fprintf(vis_stderr,"** hrc error: Hierarchy manager is empty\n");
+    return 1;
+  }
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "h")) != EOF) {
+    switch(c) {
+      case 'h':
+        goto usage;
+      default:
+        goto usage;
+    }
+     /* NOT REACHED */
+ }
+
+  /* print hd options */
+  FsmHdPrintOptions();
+  return 0;
+
+usage:
+  (void) fprintf(vis_stderr,"usage: print_hd_options [-h]\n");
+  (void) fprintf(vis_stderr, "  -h  print the command usage\n");
+  return 1;
+} /* end of CommandPrintHdOptions */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the print_ardc_options command.]
+
+  CommandName [print_ardc_options]
+
+  CommandSynopsis [print information about the ARDC options currently
+  in use]
+
+  CommandArguments [\[-h\] \[-H\]]
+
+  CommandDescription [Prints information about the current ARDC options.
+  <p>
+
+  Command options: <p>
+
+  <dl>
+
+  <dt> -h
+  <dd> Print the command usage.<p>
+
+  <dt> -H
+  <dd> Print the ARDC set command usage.<p>
+  
+  </dl>
+
+  Set parameters: The ARDC options are specified with the set command.
+
+  <dl>
+
+  <dt> ardc_traversal_method <code> &lt;method&gt; </code>
+  <dd> Specify a method for approximate FSM traversal.
+  <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: MBM (machine by machine). <p>
+  <code> 1 </code>: RFBF(reached frame by frame). <p>
+  <code> 2 </code>: TFBF(to frame by frame). <p>
+  <code> 3 </code>: TMBM(combination of MBM and TFBF). <p>
+  <code> 4 </code>: LMBM(least fixpoint MBM, default). <p>
+  <code> 5 </code>: TLMBM(combination of LMBM and TFBF). <p>
+
+  <dt> ardc_group_size <code> &lt;size&gt; </code>
+  <dd> Specify the number of latches per group for ARDCS.
+  <p>
+  <dd>
+  <code> size </code> must be a positive integer (default = 8).
+  <p>
+
+  <dt> ardc_affinity_factor <code> &lt;affinity&gt; </code>
+  <dd> Specify affinity factor to make a group for ARDCs.
+       The available factor is from 0.0(use only correlation) to 1.0(use only
+       dependency).
+  <p>
+  <dd>
+  <code> affinity </code> must be a positive real (default = 0.5).
+  <p>
+
+  <dt> ardc_max_iteration <code> &lt;iteration&gt; </code>
+  <dd> Specify the maximum iteration count during approximate FSM traversal.
+  Default is 0 which means infinite.
+  <p>
+  <dd>
+  <code> iteration </code> must be a positive integer or zero.
+  <p>
+
+  <dt> ardc_constrain_target <code> &lt;target&gt; </code>
+  <dd> Specify where image constraining will be applied to.
+  <p>
+  <dd>
+  <code> target </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: constrain transition relation (default). <p>
+  <code> 1 </code>: constrain initial states. <p>
+  <code> 2 </code>: constrain both. <p>
+
+  <dt> ardc_constrain_method <code> &lt;method&gt; </code>
+  <dd> Specify an image constraining method to compute ARDCs.
+  <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: restrict (default). <p>
+  <code> 1 </code>: constrain <p>
+  <code> 2 </code>: compact (currently supported by only CUDD) <p>
+  <code> 3 </code>: squeeze (currently supported by only CUDD) <p>
+
+  <dt> ardc_constrain_reorder <code> &lt;method&gt; </code>
+  <dd> Specify whether to enable variable reorderings during consecutive
+  image constraining operations.
+  <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: allow variable reorderings during consecutive image
+                      constraining operations (default) <p>
+  <code> no  </code>: don't allow variable reorderings during consecutive
+                      image constraining operations <p>
+
+  <dt> ardc_abstract_pseudo_input <code> &lt;method&gt; </code>
+  <dd> Specify when to abstract pseudo primary input variables out
+  from transition relation.
+  <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: do not abstract pseudo input variables <p>
+  <code> 1 </code>: abstract pseudo inputs before image computation (default)<p>
+  <code> 2 </code>: abstract pseudo inputs at every end of image computation <p>
+  <code> 3 </code>: abstract pseudo inputs at the end of approximate traversal<p>
+
+  <dt> ardc_decompose_flag <code> &lt;method&gt; </code>
+  <dd> Specify whether to use decomposed approximate reachable states or
+       single conjuncted reachable states.
+  <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: keep decomposed reachable stateses (default) <p>
+  <code> no  </code>: make a conjunction of reachable states of all submachines <p>
+
+  <dt> ardc_projected_initial_flag <code> &lt;method&gt; </code>
+  <dd> Specify which initial states is going to be used.
+  <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: use projected initial states for submachine (default) <p>
+  <code> no  </code>: use original initial states for submachine <p>
+
+  <dt> ardc_image_method <code> &lt;method&gt; </code>
+  <dd> Specify image_mathod during computing reachable states of submachines.
+  <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> monolithic </code>: use monolithic image computation <p>
+  <code> iwls95     </code>: use iwls95 image computation (default) <p>
+  <code> mlp        </code>: use mlp image computation <p>
+  <code> tfm        </code>: use tfm image computation <p>
+  <code> hybrid     </code>: use hybrid image computation <p>
+
+  <dt> ardc_use_high_density <code> &lt;method&gt; </code>
+  <dd> Specify whether to use high density in computing reachable states
+  of submachines.
+  <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: use High Density for reachable states of submachines <p>
+  <code> no  </code>: use BFS for reachable states of submachines (default) <p>
+
+  <dt> ardc_reorder_ptr <code> &lt;method&gt; </code>
+  <dd> Specify whether to reorder partitioned transition relation after
+  constraining fanin submachines.
+  <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: whenever partitioned transition relation changes,
+  reorders partitioned transition relation <p>
+  <code> no  </code>: no reordering of partitioned transition relation (default) <p>
+
+  <dt> ardc_fanin_constrain_mode <code> &lt;method&gt; </code>
+  <dd> Specify which method will be used in constraining fanin submachines. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: constrain w.r.t. the reachable states of fanin submachines
+  (default) <p>
+  <code> 1 </code>: constrain w.r.t. the reachable states of both fanin
+  submachines and itself <p>
+
+  <dt> ardc_create_pseudo_var_mode <code> &lt;method&gt; </code>
+  <dd> Specify which method will be used to create pseudo input
+  variables of submachines.
+  <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: makes pseudo input variables with exact support
+  (default) <p>
+  <code> 1 </code>: makes pseudo input variables from all state
+  variables of the other submachines <p>
+  <code> 2 </code>: makes pseudo input variables from all state
+  variables of fanin submachines <p>
+
+  <dt> ardc_lmbm_initial_mode <code> &lt;method&gt; </code>
+  <dd> Specify which method will be used as initial states in LMBM
+  computation.
+  <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: use given initial states all the time <p>
+  <code> 1 </code>: use current reached states as initial states (default) <p>
+  <code> 2 </code>: use current frontier as initial states <p>
+
+  <dt> set ardc_mbm_reuse_tr <code> &lt;method&gt; </code>
+  <dd> Specify whether to reuse already constrained transition relation
+  for next iteratrion in MBM. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: use constrained transition relation for next iteration <p>
+  <code> no  </code>: use original transition relation for next iteration
+		      (default) <p>
+
+  <dt> ardc_read_group <code> &lt;filename&gt; </code>
+  <dd> Specify a filename containing grouping information <p>
+  <dd>
+  <code> filename </code> containing grouping information
+  <p>
+
+  <dt> ardc_write_group <code> &lt;filename&gt; </code>
+  <dd> Specify a filename to write grouping information <p>
+  <dd>
+  <code> filename </code> to write grouping information
+  <p>
+
+  <dt> ardc_verbosity <code> &lt;verbosity&gt; </code>
+  <dd> Specify the level of printing information during computing ARDCs.
+  <p>
+  <dd>
+  <code> verbosity </code> must be 0 - 3 (default = 0).
+  <p>
+  
+  </dl>
+
+  The default settings correspond to the fast variants of LMBM and
+  MBM.  MBM never produces a more accurate approximation than LMBM for
+  the same state-space decomposition.  However, the corresponding
+  statement does not hold for the fast versions.  (That is, FastMBM
+  will occasionally outperform FastLMBM.)  To get the slower, but more
+  accurate versions of LMBM and MBM use the following settings:
+
+  <ul>
+  <li> set ardc_constrain_method 1
+  <li> set ardc_constrain_reorder no
+  <li> set ardc_abstract_pseudo_input 0
+  </ul>
+  
+  ]
+  
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandPrintArdcOptions(Hrc_Manager_t ** hmgr, int  argc, char ** argv)
+{
+  int c;
+
+  if (*hmgr == NULL) {
+    fprintf(vis_stderr,"** hrc error: Hierarchy manager is empty\n");
+    return 1;
+  }
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "hH")) != EOF) {
+    switch(c) {
+      case 'h':
+        goto usage;
+      case 'H':
+        goto usage_ardc;
+      default:
+        goto usage;
+    }
+    /* NOT REACHED */
+  }
+
+  /* print ARDC options */
+  FsmArdcPrintOptions();
+  return 0;
+
+usage:
+  (void) fprintf(vis_stderr,"usage: print_ardc_options [-h] [-H]\n");
+  (void) fprintf(vis_stderr, "  -h  print the command usage\n");
+  (void) fprintf(vis_stderr, "  -H  print the ARDC set command usage\n");
+  return 1;
+usage_ardc:
+  (void) fprintf(vis_stderr, "   set ardc_traversal_method <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : MBM (machine by machine)\n");
+  (void) fprintf(vis_stderr, "       m = 1 : RFBF(reached frame by frame)\n");
+  (void) fprintf(vis_stderr, "       m = 2 : TFBF(to frame by frame)\n");
+  (void) fprintf(vis_stderr, "       m = 3 : TMBM(TFBF + MBM)\n");
+  (void) fprintf(vis_stderr, "       m = 4 : LMBM(least fixpoint MBM, default)\n");
+  (void) fprintf(vis_stderr, "       m = 5 : TLMBM(TFBF + LMBM)\n");
+  (void) fprintf(vis_stderr, "   set ardc_group_size <n>\n");
+  (void) fprintf(vis_stderr, "       n (default = 8)\n");
+  (void) fprintf(vis_stderr, "   set ardc_affinity_factor <f>\n");
+  (void) fprintf(vis_stderr, "       f = 0.0 - 1.0 (default = 0.5)\n");
+  (void) fprintf(vis_stderr, "   set ardc_max_iteration <n>\n");
+  (void) fprintf(vis_stderr, "       n (default = 0(infinity))\n");
+  (void) fprintf(vis_stderr, "   set ardc_constrain_target <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : constrain transition relation (default)\n");
+  (void) fprintf(vis_stderr, "       m = 1 : constrain initial states\n");
+  (void) fprintf(vis_stderr, "       m = 2 : constrain both\n");
+  (void) fprintf(vis_stderr, "   set ardc_constrain_method <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : restrict (default)\n");
+  (void) fprintf(vis_stderr, "       m = 1 : constrain\n");
+  (void) fprintf(vis_stderr,
+		 "       m = 2 : compact (currently supported by only CUDD)\n");
+  (void) fprintf(vis_stderr,
+		 "       m = 3 : squeeze (currently supported by only CUDD)\n");
+  (void) fprintf(vis_stderr, "   set ardc_constrain_reorder <m>\n");
+  (void) fprintf(vis_stderr, "       m = yes : allow variable reorderings during consecutive\n");
+  (void) fprintf(vis_stderr, "                 image constraining operations (default)\n");
+  (void) fprintf(vis_stderr, "       m = no  : don't allow variable reorderings during consecutive\n");
+  (void) fprintf(vis_stderr, "                 image constraining operations\n");
+  (void) fprintf(vis_stderr, "   set ardc_abstract_pseudo_input <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : do not abstract pseudo input variables\n");
+  (void) fprintf(vis_stderr, "       m = 1 : abstract pseudo inputs before image computation (default)\n");
+  (void) fprintf(vis_stderr, "       m = 2 : abstract pseudo inputs at every end of image computation\n");
+  (void) fprintf(vis_stderr, "       m = 3 : abstract pseudo inputs at the end of approximate traversal\n");
+  (void) fprintf(vis_stderr, "   set ardc_decompose_flag <m>\n");
+  (void) fprintf(vis_stderr, "       m = yes : keep decomposed reachable stateses (default)\n");
+  (void) fprintf(vis_stderr, "       m = no  : make a conjunction of reachable states of all submachines\n");
+  (void) fprintf(vis_stderr, "   set ardc_projected_initial_flag <m>\n");
+  (void) fprintf(vis_stderr, "       m = yes : use projected initial states for submachine (default)\n");
+  (void) fprintf(vis_stderr, "       m = no  : use original initial states for submachine\n");
+  (void) fprintf(vis_stderr, "   set ardc_image_method <m>\n");
+  (void) fprintf(vis_stderr, "       m = monolithic : use monolithic image computation for submachines\n");
+  (void) fprintf(vis_stderr, "       m = iwls95     : use iwls95 image computation for submachines (default)\n");
+  (void) fprintf(vis_stderr, "       m = mlp        : use mlp image computation for submachines\n");
+  (void) fprintf(vis_stderr, "       m = tfm        : use tfm image computation for submachines\n");
+  (void) fprintf(vis_stderr, "       m = hybrid     : use hybrid image computation for submachines\n");
+  (void) fprintf(vis_stderr, "   set ardc_use_high_density <m>\n");
+  (void) fprintf(vis_stderr, "       m = yes : use High Density for reachable states of submachines\n");
+  (void) fprintf(vis_stderr, "       m = no  : use BFS for reachable states of submachines (default)\n");
+  (void) fprintf(vis_stderr, "   set ardc_create_pseudo_var_mode <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : makes pseudo input variables with exact support (default)\n");
+  (void) fprintf(vis_stderr, "       m = 1 : makes pseudo input variables from all state variables of\n");
+  (void) fprintf(vis_stderr, "               the other machines\n");
+  (void) fprintf(vis_stderr, "       m = 2 : makes pseudo input variables from all state variables of\n");
+  (void) fprintf(vis_stderr, "               fanin machines\n");
+  (void) fprintf(vis_stderr, "   set ardc_reorder_ptr <m>\n");
+  (void) fprintf(vis_stderr, "       m = yes : whenever partitioned transition relation changes,\n");
+  (void) fprintf(vis_stderr, "                 reorders partitioned transition relation\n");
+  (void) fprintf(vis_stderr, "       m = no  : no reordering of partitioned transition relation (default)\n");
+  (void) fprintf(vis_stderr, "   set ardc_fanin_constrain_mode <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : constrains w.r.t. the reachable states of fanin machines\n");
+  (void) fprintf(vis_stderr, "               (default)\n");
+  (void) fprintf(vis_stderr, "       m = 1 : constrains w.r.t. the reachable states of both fanin machines\n");
+  (void) fprintf(vis_stderr, "               and itself\n");
+  (void) fprintf(vis_stderr, "   set ardc_lmbm_initial_mode <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : use given initial states all the time\n");
+  (void) fprintf(vis_stderr, "       m = 1 : use current reached states as initial states (default)\n");
+  (void) fprintf(vis_stderr, "       m = 2 : use current frontier as initial states\n");
+  (void) fprintf(vis_stderr, "   set ardc_mbm_reuse_tr <m>\n");
+  (void) fprintf(vis_stderr, "       m = yes : use constrained transition relation for next iteration\n");
+  (void) fprintf(vis_stderr, "       m = no  : use original transition relation for next iteration (default)\n");
+  (void) fprintf(vis_stderr, "   set ardc_read_group <filename>\n");
+  (void) fprintf(vis_stderr, "       <filename> file containing grouping information\n");
+  (void) fprintf(vis_stderr, "   set ardc_write_group <filename>\n");
+  (void) fprintf(vis_stderr, "       <filename> file to write grouping information\n");
+  (void) fprintf(vis_stderr, "   set ardc_verbosity <n>\n");
+  (void) fprintf(vis_stderr, "       n = 0 - 3 (default = 0)\n");
+  return 1;
+} /* end of CommandPrintArdcOptions */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the print_tfm_options command.]
+
+  CommandName [print_tfm_options]
+
+  CommandSynopsis [print information about the transition function based
+  image computation options currently in use]
+
+  CommandArguments [\[-h\] \[-H\]]
+
+  CommandDescription [Prints information about the current transition function
+  based image computation options.
+  <p>
+
+  Command options: <p>
+
+  <dl>
+
+  <dt> -h
+  <dd> Print the command usage.<p>
+
+  <dt> -H
+  <dd> Print the transition function based image computation set command usage.
+  <p>
+  
+  </dl>
+
+  Set parameters: The transition function based image computation options are
+  specified with the set command.
+
+  <dl>
+
+  <dt> tfm_split_method <code> &lt;method&gt; </code>
+  <dd> Specify a splitting method. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: input splitting (default) <p>
+  <code> 1 </code>: output splitting <p>
+  <code> 2 </code>: mixed (input split + output split) <p>
+
+  <dt> tfm_input_split <code> &lt;method&gt; </code>
+  <dd> Specify an input splitting method. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: support before splitting (default) <p>
+  <code> 1 </code>: support after splitting <p>
+  <code> 2 </code>: estimate BDD size after splitting <p>
+  <code> 3 </code>: top variable <p>
+
+  <dt> tfm_pi_split_flag <code> &lt;method&gt; </code>
+  <dd> Specify whether to allow primary input variables to be chosen
+       as a splitting variable. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: choose either state or input variable as splitting
+		      variable (default) <p>
+  <code> no  </code>: choose only state variable as splitting variable <p>
+
+  <dt> tfm_range_comp <code> &lt;method&gt; </code>
+  <dd> Specify a method whether to convert image to range computataion. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: do not convert to range computation <p>
+  <code> 1 </code>: convert image to range computation (default) <p>
+  <code> 2 </code>: use a threshold (tfm_range_threshold, default for
+  hybrid) <p>
+
+  <dt> tfm_range_threshold &lt;number&gt;
+  <dd> This option is valid only when the tfm_range_comp is set to 2. This
+  threshold is used to determine whether to convert to range computation
+  by comparing the shared BDD size of function vector after constraining
+  w.r.t. from set to its original size. If the size is less than the origianl
+  size * <number>, then we convert to range computation. The default value
+  is 10. <p>
+
+  <dt> tfm_range_try_threshold &lt;number&gt;
+  <dd> This option is valid only when the tfm_range_comp is set to 2. This
+  option is used to disable checking the condition if it fails to convert
+  consecutively <number> times. The default value is 2. <p>
+
+  <dt> tfm_range_check_reorder <code> &lt;method&gt; </code>
+  <dd> Specify whether to force to call variable reordering after constraining
+  function vector w.r.t. from set and before checking the condition. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: force to reorder before checking tfm_range_threshold <p>
+  <code> no  </code>: do not reorder (default) <p>
+
+  <dt> tfm_tie_break_mode <code> &lt;method&gt; </code>
+  <dd> Specify a tie breaking method when we have a tie in choosing
+  a splitting variable in input and output splitting method. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: the closest variable to top (default) <p>
+  <code> 1 </code>: the smallest BDD size after splitting <p>
+
+  <dt> tfm_output_split <code> &lt;method&gt; </code>
+  <dd> Specify an output splitting method. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: smallest BDD size (default) <p>
+  <code> 1 </code>: largest BDD size <p>
+  <code> 2 </code>: top variable <p>
+
+  <dt> tfm_turn_depth &lt;number&gt;
+  <dd> This option is valid only when mixed or hybrid method is chosen.
+  This is used to determine when to switch to the other method at which
+  depth of recursion. The default is 5 for tfm and -1 for hybrid method. <p>
+
+  <dt> tfm_find_decomp_var <code> &lt;method&gt; </code>
+  <dd> Specify a method whether to try to find a decomposable variable
+  (meaning articulation point) first if any. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: try to find a decomposable variable (articulation point)
+  <p>
+  <code> no  </code>: do not try (default) <p>
+
+  <dt> tfm_sort_vector_flag <code> &lt;method&gt; </code>
+  <dd> Specify a method whether to sort function vectors to increase cache
+  performance. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: sort function vectors (default for tfm) <p>
+  <code> no  </code>: do not sort (default for hybrid) <p>
+
+  <dt> tfm_print_stats <code> &lt;method&gt; </code>
+  <dd> Specify a method whether to print statistics for cache and recursions
+  at the end of job.<p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: print statistics <p>
+  <code> no  </code>: do not print (default) <p>
+
+  <dt> tfm_print_bdd_size <code> &lt;method&gt; </code>
+  <dd> Specify a method whether to print the BDD size of all intermediate
+  product. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: print BDD size <p>
+  <code> no  </code>: do not print (default) <p>
+
+  <dt> tfm_split_cube_func <code> &lt;method&gt; </code>
+  <dd> Specify a method whether to try to find a cube in function vector
+  in input splitting, then perform output splitting once w.r.t. the cube. <p>
+  
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: try cube splitting <p>
+  <code> no  </code>: do not try (default) <p>
+
+  <dt> tfm_find_essential <code> &lt;method&gt; </code>
+  <dd> Specify a method whether to try to find essential variables in from set.
+  If a variable occurs in all cubes of a BDD, the variable is called essential.
+  If exists, minimize both function vector and the from set with the essential
+  cube. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: do not try (default) <p>
+  <code> 1 </code>: try to find essential variables <p>
+  <code> 2 </code>: on and off dynamically <p>
+
+  <dt> tfm_print_essential <code> &lt;method&gt; </code>
+  <dd> Specify a method whether to print information about essential variables.
+  <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: do not print (default) <p>
+  <code> 1 </code>: print only at end <p>
+  <code> 2 </code>: print at every image computation <p>
+
+  <dt> tfm_use_cache <code> &lt;method&gt; </code>
+  <dd> Specify whether to use an image cache. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: do not use cache (default for hybrid) <p>
+  <code> 1 </code>: use cache (default) <p>
+  <code> 2 </code>: store all intermediate results <p>
+
+  <dt> tfm_global_cache <code> &lt;method&gt; </code>
+  <dd> Specify a method whether to use one global image cache, or one image
+  cache per each machine. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: use only one global cache (default) <p>
+  <code> no  </code>: use one cache per machine <p>
+
+  <dt> tfm_max_chain_length &lt;number&gt;
+  <dd> This option is used to set the maximum number of items in a slot for
+  conflict. The default is 2. <p>
+
+  <dt> tfm_init_cache_size &lt;number&gt;
+  <dd> This option is used to set the initial cache size. The number is
+  recommended to be a prime number. Currently, we do not resize the cache size,
+  but for the future extension, we named initial. The default is 1001. <p>
+
+  <dt> tfm_auto_flush_cache <code> &lt;method&gt; </code>
+  <dd> Specify a method to flush image cache. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: flush cache only when requested <p>
+  <code> 1 </code>: flush cache at the end of image computation (default) <p>
+  <code> 2 </code>: flush cache before reordering <p>
+
+  <dt> tfm_compose_intermediate_vars <code> &lt;method&gt; </code>
+  <dd> Specify a method whether to compose all intermediate variables.  <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: compose all <p>
+  <code> no  </code>: do not compose (default) <p>
+
+  <dt> tfm_pre_split_method <code> &lt;method&gt; </code>
+  <dd> Specify a splitting method for preimage computation. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: input splitting (domain cofactoring, default) <p>
+  <code> 1 </code>: output splitting (constraint cofactoring) <p>
+  <code> 2 </code>: mixed (input split + output split) <p>
+  <code> 3 </code>: substitution <p>
+
+  <dt> tfm_pre_input_split <code> &lt;method&gt; </code>
+  <dd> Specify an input splitting method for preimage computation. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: support before splitting (default) <p>
+  <code> 1 </code>: support after splitting <p>
+  <code> 2 </code>: estimate BDD size after splitting <p>
+  <code> 3 </code>: top variable <p>
+
+  <dt> tfm_pre_output_split <code> &lt;method&gt; </code>
+  <dd> Specify an output splitting method for preimage computation. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: smallest BDD size (default) <p>
+  <code> 1 </code>: largest BDD size <p>
+  <code> 2 </code>: top variable <p>
+
+  <dt> tfm_pre_dc_leaf_method <code> &lt;method&gt; </code>
+  <dd> Specify a method to switch to another method to complete preimage
+  computation in domain cofactoring method when no more splitting variable
+  exist. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: substitution (default) <p>
+  <code> 1 </code>: constraint cofactoring <p>
+  <code> 2 </code>: hybrid <p>
+
+  <dt> tfm_pre_minimize <code> &lt;method&gt; </code>
+  <dd> Specify a method whether to minimize transition function vector
+  w.r.t a chosen function in constraint cofactoring method. This
+  option is recommended to use when image cache is disabled, because
+  even though this option can minimize the BDD size of function vector,
+  this may degrade cache performance. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: minimize function vector w.r.t. a chosen function
+                in constraint cofactoring <p>
+  <code> no  </code>: do not minimize (default) <p>
+
+  <dt> tfm_verbosity <code> &lt;verbosity&gt; </code>
+  <dd> Specify the level of printing information related with transition
+  function method.
+  <p>
+  <dd>
+  <code> verbosity </code> must be 0 - 2 (default = 0).
+  <p>
+
+  </dl>
+  ]
+  
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandPrintTfmOptions(Hrc_Manager_t ** hmgr, int  argc, char ** argv)
+{
+  int c;
+
+  if (*hmgr == NULL) {
+    fprintf(vis_stderr,"** hrc error: Hierarchy manager is empty\n");
+    return 1;
+  }
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "hH")) != EOF) {
+    switch(c) {
+      case 'h':
+        goto usage;
+      case 'H':
+        goto usage_tfm;
+      default:
+        goto usage;
+    }
+     /* NOT REACHED */
+ }
+
+  /* print transition function based image computation options */
+  Img_PrintTfmOptions();
+  return 0;
+
+usage:
+  (void) fprintf(vis_stderr,"usage: print_tfm_options [-h] [-H]\n");
+  (void) fprintf(vis_stderr, "  -h  print the command usage\n");
+  (void) fprintf(vis_stderr, "  -H  print the transition function based ");
+  (void) fprintf(vis_stderr, "image computation set command usage\n");
+  return 1;
+usage_tfm:
+  (void) fprintf(vis_stderr, "   set tfm_split_method <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : input splitting (default)\n");
+  (void) fprintf(vis_stderr, "       m = 1 : output splitting\n");
+  (void) fprintf(vis_stderr, "       m = 2 : mixed (input split + output split)\n");
+  (void) fprintf(vis_stderr, "   set tfm_input_split <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : support before splitting (default)\n");
+  (void) fprintf(vis_stderr, "       m = 1 : support after splitting\n");
+  (void) fprintf(vis_stderr, "       m = 2 : estimate BDD size after splitting\n");
+  (void) fprintf(vis_stderr, "       m = 3 : top variable\n");
+  (void) fprintf(vis_stderr, "   set tfm_pi_split_flag <m>\n");
+  (void) fprintf(vis_stderr, "       m = yes : choose either state or input variable as splitting variable\n");
+  (void) fprintf(vis_stderr, "                 (default)\n");
+  (void) fprintf(vis_stderr, "       m = no  : choose only state variable as splitting variable\n");
+  (void) fprintf(vis_stderr, "   set tfm_range_comp <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : do not convert to range computation\n");
+  (void) fprintf(vis_stderr, "       m = 1 : convert image to range computation (default)\n");
+  (void) fprintf(vis_stderr, "       m = 2 : use a threshold (tfm_range_threshold, default for hybrid)\n");
+  (void) fprintf(vis_stderr, "   set tfm_range_threshold <n>\n");
+  (void) fprintf(vis_stderr, "       n (default = 10)\n");
+  (void) fprintf(vis_stderr, "   set tfm_range_try_threshold <n>\n");
+  (void) fprintf(vis_stderr, "       n (default = 2)\n");
+  (void) fprintf(vis_stderr, "   set tfm_range_check_reorder <m>\n");
+  (void) fprintf(vis_stderr, "       m = yes : force to reorder before checking tfm_range_threshold\n");
+  (void) fprintf(vis_stderr, "       m = no  : do not reorder (default)\n");
+  (void) fprintf(vis_stderr, "   set tfm_tie_break_mode <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : the closest variable to top (default)\n");
+  (void) fprintf(vis_stderr, "       m = 1 : the smallest BDD size after splitting\n");
+  (void) fprintf(vis_stderr, "   set tfm_output_split <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : smallest BDD size (default)\n");
+  (void) fprintf(vis_stderr, "       m = 1 : largest BDD size\n");
+  (void) fprintf(vis_stderr, "       m = 2 : top variable\n");
+  (void) fprintf(vis_stderr, "   set tfm_turn_depth <n>\n");
+  (void) fprintf(vis_stderr, "       n (default = 5, -1 for hybrid)\n");
+  (void) fprintf(vis_stderr, "   set tfm_find_decomp_var <m>\n");
+  (void) fprintf(vis_stderr, "       m = yes : try to find a decomposable variable (articulation point)\n");
+  (void) fprintf(vis_stderr, "       m = no  : do not try (default)\n");
+  (void) fprintf(vis_stderr, "   set tfm_sort_vector_flag <m>\n");
+  (void) fprintf(vis_stderr, "       m = yes : sort function vectors to utilize cache (default for tfm)\n");
+  (void) fprintf(vis_stderr, "       m = no  : do not sort (default for hybrid)\n");
+  (void) fprintf(vis_stderr, "   set tfm_print_stats <m>\n");
+  (void) fprintf(vis_stderr, "       m = yes : print statistics for cache and recursions\n");
+  (void) fprintf(vis_stderr, "       m = no  : do not print (default)\n");
+  (void) fprintf(vis_stderr, "   set tfm_print_bdd_size <m>\n");
+  (void) fprintf(vis_stderr, "       m = yes : print BDD size of all intermediate product\n");
+  (void) fprintf(vis_stderr, "       m = no  : do not print (default)\n");
+  (void) fprintf(vis_stderr, "   set tfm_split_cube_func <m>\n");
+  (void) fprintf(vis_stderr, "       m = yes : find a cube function element,\n");
+  (void) fprintf(vis_stderr, "                 then apply output splitting in input splitting\n");
+  (void) fprintf(vis_stderr, "       m = no  : do not try (default)\n");
+  (void) fprintf(vis_stderr, "   set tfm_find_essential <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : do not try (default)\n");
+  (void) fprintf(vis_stderr, "       m = 1 : try to find essential variables\n");
+  (void) fprintf(vis_stderr, "       m = 2 : on and off dynamically\n");
+  (void) fprintf(vis_stderr, "   set tfm_print_essential <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : do not print (default)\n");
+  (void) fprintf(vis_stderr, "       m = 1 : print only at end\n");
+  (void) fprintf(vis_stderr, "       m = 2 : print at every image computation\n");
+  (void) fprintf(vis_stderr, "   set tfm_use_cache <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : do not use cache (default for hybrid)\n");
+  (void) fprintf(vis_stderr, "       m = 1 : use cache (default)\n");
+  (void) fprintf(vis_stderr, "       m = 2 : store all intermediate results\n");
+  (void) fprintf(vis_stderr, "   set tfm_global_cache <m>\n");
+  (void) fprintf(vis_stderr, "       m = yes : use only one global cache (default)\n");
+  (void) fprintf(vis_stderr, "       m = no  : use one cache per machine\n");
+  (void) fprintf(vis_stderr, "   set tfm_max_chain_length <n>\n");
+  (void) fprintf(vis_stderr, "       n (default = 2)\n");
+  (void) fprintf(vis_stderr, "   set tfm_init_cache_size <n>\n");
+  (void) fprintf(vis_stderr, "       n (default = 1001)\n");
+  (void) fprintf(vis_stderr, "   set tfm_auto_flush_cache <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : flush cache only when requested\n");
+  (void) fprintf(vis_stderr, "       m = 1 : flush cache at the end of image computation (default)\n");
+  (void) fprintf(vis_stderr, "       m = 2 : flush cache before reordering\n");
+  (void) fprintf(vis_stderr, "   set tfm_compose_intermediate_vars <m>\n");
+  (void) fprintf(vis_stderr, "       m = yes : compose all intermediate vars\n");
+  (void) fprintf(vis_stderr, "       m = no  : do not compose (default)\n");
+  (void) fprintf(vis_stderr, "   set tfm_pre_split_method <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : input splitting (domain cofactoring, default)\n");
+  (void) fprintf(vis_stderr, "       m = 1 : output splitting (constraint cofactoring)\n");
+  (void) fprintf(vis_stderr, "       m = 2 : mixed (input split + output split)\n");
+  (void) fprintf(vis_stderr, "       m = 3 : substitution\n");
+  (void) fprintf(vis_stderr, "   set tfm_pre_input_split <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : support before splitting (default)\n");
+  (void) fprintf(vis_stderr, "       m = 1 : support after splitting\n");
+  (void) fprintf(vis_stderr, "       m = 2 : estimate BDD size after splitting\n");
+  (void) fprintf(vis_stderr, "       m = 3 : top variable\n");
+  (void) fprintf(vis_stderr, "   set tfm_pre_output_split <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : smallest BDD size (default)\n");
+  (void) fprintf(vis_stderr, "       m = 1 : largest BDD size\n");
+  (void) fprintf(vis_stderr, "       m = 2 : top variable\n");
+  (void) fprintf(vis_stderr, "   set tfm_pre_dc_leaf_method <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : substitution (default)\n");
+  (void) fprintf(vis_stderr, "       m = 1 : constraint cofactoring\n");
+  (void) fprintf(vis_stderr, "       m = 2 : hybrid\n");
+  (void) fprintf(vis_stderr, "   set tfm_pre_minimize <m>\n");
+  (void) fprintf(vis_stderr, "       m = yes : minimize function vector w.r.t. a chosen function\n");
+  (void) fprintf(vis_stderr, "                 in constraint cofactoring\n");
+  (void) fprintf(vis_stderr, "       m = no  : do not minimize (default)\n");
+  (void) fprintf(vis_stderr, "   set tfm_verbosity <n>\n");
+  (void) fprintf(vis_stderr, "       n = 0 - 2 (default = 0)\n");
+  return 1;
+} /* end of CommandPrintTfmOptions */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the print_hybrid_options command.]
+
+  CommandName [print_hybrid_options]
+
+  CommandSynopsis [print information about the hybrid image computation options
+  currently in use]
+
+  CommandArguments [\[-h\] \[-H\]]
+
+  CommandDescription [Prints information about the current hybrid image
+  computation options.
+  <p>
+
+  Command options: <p>
+
+  <dl>
+
+  <dt> -h
+  <dd> Print the command usage.<p>
+
+  <dt> -H
+  <dd> Print the hybrid image computation set command usage.<p>
+  
+  </dl>
+
+  Set parameters: The hybrid image computation options are specified with the
+  set command.
+
+  <dl>
+
+  <dt> hybrid_mode <code> <m>&lt;mode<m>&gt; </code>
+  <dd> Specify a mode how to start hybrid computation. <p>
+  <dd>
+  <code> mode </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: start with only transition function and build transition
+  relation on demand <p>
+  <code> 1 </code>: start with both transition function and relation (default)
+  <p>
+  <code> 2 </code>: start with only transition relation. Only this mode
+  can deal with nondeterminism.<p>
+
+  <dt> hybrid_tr_split_method <code> <m>&lt;method<m>&gt; </code>
+  <dd> Specify a method to choose a splitting variable in hybrid mode = 2. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: use support (default) <p>
+  <code> 1 </code>: use estimate BDD size <p>
+
+  <dt> hybrid_build_partial_tr <code> <m>&lt;method<m>&gt; </code>
+  <dd> Specify whether to build full or partial transition relation in
+  hybrid mode = 2.
+  This option is used to use less memory. When we use partial transition
+  relation, for the variables excluded in the transition relation, we build
+  each bit transition relation on demand. When nondeterminism exists in
+  the circuit, this can not be used.
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: build partial transition relation <p>
+  <code> no  </code>: build full transition relation (default) <p>
+
+  <dt> hybrid_partial_num_vars &lt;number&gt;
+  <dd> Specify how many variables are going to be excluded in building
+  partial transition relation. The default is 8. <p>
+
+  <dt> hybrid_partial_method <code> <m>&lt;method<m>&gt; </code>
+  <dd> Specify a method to choose variables to be excluded in building
+  partial transition relation. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: use BDD size (default) <p>
+  <code> 1 </code>: use support <p>
+
+  <dt> hybrid_delayed_split <code> <m>&lt;method<m>&gt; </code>
+  <dd> Specify a method whether to split transition relation immediately or
+  just all at once before AndExist. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: apply splitting to transition relation at once <p>
+  <code> no  </code>: do not apply (default) <p>
+
+  <dt> hybrid_split_min_depth &lt;number&gt;
+  <dd> Specify the minimum depth to apply dynamic hybrid method. If a depth
+  is smaller than this minimum depth, just split. The default is 1. <p>
+
+  <dt> hybrid_split_max_depth &lt;number&gt;
+  <dd> Specify the maximum depth to apply dynamic hybrid method. If a depth
+  is bigger than this maximum depth, just conjoin. The default is 5. <p>
+
+  <dt> hybrid_pre_split_min_depth &lt;number&gt;
+  <dd> Specify the minimum depth to apply dynamic hybrid method in preimage
+  computation. If a depth is smaller than this minimum depth, just split.
+  The default is 0. <p>
+
+  <dt> hybrid_pre_split_max_depth &lt;number&gt;
+  <dd> Specify the maximum depth to apply dynamic hybrid method in preimage
+  computation. If a depth is bigger than this maximum depth, just conjoin.
+  The default is 4. <p>
+
+  <dt> hybrid_lambda_threshold &lt;number&gt;
+  <dd> Specify a threshold in floating between 0.0 and 1.0 to determine
+  to split or to conjoin after computing variable lifetime lambda for
+  image computation.
+  If lambda is equal or smaller than this threshold, we conjoin.
+  Otherwise we split. The default is 0.6 <p>
+
+  <dt> hybrid_pre_lambda_threshold &lt;number&gt;
+  <dd> Specify a threshold in floating between 0.0 and 1.0 to determine
+  to split or to conjoin after computing variable lifetime lambda for
+  preimage computation.
+  If lambda is equal or smaller than this threshold, we conjoin.
+  Otherwise we split. The default is 0.65 <p>
+
+  <dt> hybrid_conjoin_vector_size &lt;number&gt;
+  <dd> If the number of components in transition function vector is equal or
+  smaller than this threshold, we just conjoin. This check is performed before
+  computing lambda. The default is 10. <p>
+
+  <dt> hybrid_conjoin_relation_size &lt;number&gt;
+  <dd> If the number of clusters in transition relation is equal or smaller
+  than this threshold, we just conjoin. This check is performed before
+  computing lambda. The default is 2. <p>
+
+  <dt> hybrid_conjoin_relation_bdd_size &lt;number&gt;
+  <dd> If the shared BDD size of transition relation is equal or smaller than
+  this threshold, we conjoin. This check is performed before computing lambda.
+  The default is 200. <p>
+
+  <dt> hybrid_improve_lambda &lt;number&gt;
+  <dd> When variable lifetime lambda is bigger than lambda threshold,
+  if the difference between previous and current lambda is equal or smaller
+  than this threshold, then we conjoin. The default is 0.1. <p>
+
+  <dt> hybrid_improve_vector_size &lt;number&gt;
+  <dd> When variable lifetime lambda is bigger than lambda threshold,
+  if the difference between the previous and current number of components
+  in transition function vector is equal or smaller than this threshold,
+  then we conjoin. The default is 3. <p>
+
+  <dt> hybrid_improve_vector_bdd_size &lt;number&gt;
+  <dd> When variable lifetime lambda is bigger than lambda threshold,
+  if the difference between the previous and current shared BDD size of
+  transition function vector is equal or smaller than this threshold,
+  then we conjoin. The default is 30.0. <p>
+
+  <dt> hybrid_decide_mode <code> <m>&lt;method<m>&gt; </code>
+  <dd> Specify a method to decide whether to split or to conjoin. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: use only lambda <p>
+  <code> 1 </code>: use lambda and also special checks to conjoin <p>
+  <code> 2 </code>: use lambda and also improvement <p>
+  <code> 3 </code>: use all (default) <p>
+
+  <dt> hybrid_reorder_with_from <code> <m>&lt;method<m>&gt; </code>
+  <dd> Specify a method to reorder transition relation to conjoin in image
+  computation, whether to include from set in the computation. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: reorder relation array with from to conjoin (default) <p>
+  <code> no  </code>: reorder relation array without from to conjoin <p>
+
+  <dt> hybrid_pre_reorder_with_from <code> <m>&lt;method<m>&gt; </code>
+  <dd> Specify a method to reorder transition relation to conjoin in preimage
+  computation, whether to include from set in the computation. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: reorder relation array with from to conjoin <p>
+  <code> no  </code>: reorder relation array without from to conjoin (default)
+  <p>
+
+  <dt> hybrid_lambda_mode <code> <m>&lt;method<m>&gt; </code>
+  <dd> Specify a method to decide which variable lifetime to be used for
+  image computation. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: total lifetime with ps/pi variables (default) <p>
+  <code> 1 </code>: active lifetime with ps/pi variables <p>
+  <code> 2 </code>: total lifetime with ps/ns/pi variables <p>
+
+  <dt> hybrid_pre_lambda_mode <code> <m>&lt;method<m>&gt; </code>
+  <dd> Specify a method to decide which variable lifetime to be used for
+  preimage computation. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: total lifetime with ns/pi variables <p>
+  <code> 1 </code>: active lifetime with ps/pi variables <p>
+  <code> 2 </code>: total lifetime with ps/ns/pi variables (default) <p>
+  <code> 3 </code>: total lifetime with ps/pi variables <p>
+
+  <dt> hybrid_lambda_with_from <code> <m>&lt;method<m>&gt; </code>
+  <dd> Specify a method to compute variable lifetime lambda, whether
+  to include from set in the computation. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: include from set in lambda computation (default) <p>
+  <code> no  </code>: do not include <p>
+
+  <dt> hybrid_lambda_with_tr <code> <m>&lt;method<m>&gt; </code>
+  <dd> Specify a method to compute variable lifetime lambda, whether
+  to use transition relation or transition function vector, when both
+  exist. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: use transition relation (default) <p>
+  <code> no  </code>: use transition function vector <p>
+
+  <dt> hybrid_lambda_with_clustering <code> <m>&lt;method<m>&gt; </code>
+  <dd> Specify a method whether to include clustering to compute variable
+  lifetime lambda. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: compute lambda after clustering <p>
+  <code> no  </code>: do not cluster (default) <p>
+
+  <dt> hybrid_synchronize_tr <code> <m>&lt;method<m>&gt; </code>
+  <dd> Specify a method to keep transition relation. This option is only for
+  when hybrid mode is 1. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: rebuild transition relation from function vector
+  whenever the function vector changes <p>
+  <code> no  </code>: do not rebuild (default) <p>
+
+  <dt> hybrid_img_keep_pi <code> <m>&lt;method<m>&gt; </code>
+  <dd> Specify a method to build forward transition relation. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: keep all primary input variables in forward transition
+  relation. <p>
+  <code> no  </code>: quantify out local primary input variables from the
+  transition relation. (default) <p>
+
+  <dt> hybrid_pre_keep_pi <code> <m>&lt;method<m>&gt; </code>
+  <dd> Specify a method to build backward transition relation. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: keep all primary input variables in backward transition
+  relation and preimages. <p>
+  <code> no  </code>: quantify out local primary input variables from the
+  transition relation. (default) <p>
+
+  <dt> hybrid_pre_canonical <code> <m>&lt;method<m>&gt; </code>
+  <dd> Specify a method whether to canonicalize the function vector for
+  preimage computation. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> yes </code>: canonicalize the function vector <p>
+  <code> no  </code>: do not canonicalize (default) <p>
+
+  <dt> hybrid_tr_method <code> <m>lt;method<m>gt; </code>
+  <dd> Specify an image method for AndExist operation in hybrid method. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> iwls95 (default) <p>
+  <code> mlp <p>
+
+  </dl>
+  ]
+  
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandPrintHybridOptions(Hrc_Manager_t ** hmgr, int  argc, char ** argv)
+{
+  int c;
+
+  if (*hmgr == NULL) {
+    fprintf(vis_stderr,"** hrc error: Hierarchy manager is empty\n");
+    return 1;
+  }
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "hH")) != EOF) {
+    switch(c) {
+      case 'h':
+        goto usage;
+      case 'H':
+        goto usage_hybrid;
+      default:
+        goto usage;
+    }
+  }
+
+  /* print hybrid image computation options */
+  Img_PrintHybridOptions();
+  return 0;
+
+usage:
+  (void) fprintf(vis_stderr,"usage: print_hybrid_options [-h] [-H]\n");
+  (void) fprintf(vis_stderr, "  -h  print the command usage\n");
+  (void) fprintf(vis_stderr,
+		"  -H  print the hybrid image computation set command usage\n");
+  return 1;
+usage_hybrid:
+  (void) fprintf(vis_stderr, "   set hybrid_mode <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : start with only transition function\n");
+  (void) fprintf(vis_stderr, "       m = 1 : start with both transition function and relation at the beginning (default)\n");
+  (void) fprintf(vis_stderr, "       m = 2 : start with only transition relation\n");
+  (void) fprintf(vis_stderr, "   set hybrid_tr_split_method <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : use support (default)\n");
+  (void) fprintf(vis_stderr, "       m = 1 : use estimate BDD size\n");
+  (void) fprintf(vis_stderr, "   set hybrid_build_partial_tr <m>\n");
+  (void) fprintf(vis_stderr, "       m = yes : build partial transition relation\n");
+  (void) fprintf(vis_stderr, "       m = no  : build full transition relation (default)\n");
+  (void) fprintf(vis_stderr, "   set hybrid_partial_num_vars <n>\n");
+  (void) fprintf(vis_stderr, "       n (default = 8)\n");
+  (void) fprintf(vis_stderr, "   set hybrid_partial_method <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : use BDD size (default)\n");
+  (void) fprintf(vis_stderr, "       m = 1 : use support\n");
+  (void) fprintf(vis_stderr, "   set hybrid_delayed_split <m>\n");
+  (void) fprintf(vis_stderr, "       m = yes : apply splitting to transition relation at once\n");
+  (void) fprintf(vis_stderr, "       m = no  : do not apply (default)\n");
+  (void) fprintf(vis_stderr, "   set hybrid_split_min_depth <n>\n");
+  (void) fprintf(vis_stderr, "       n (default = 1)\n");
+  (void) fprintf(vis_stderr, "   set hybrid_split_max_depth <n>\n");
+  (void) fprintf(vis_stderr, "       n (default = 5)\n");
+  (void) fprintf(vis_stderr, "   set hybrid_pre_split_min_depth <n>\n");
+  (void) fprintf(vis_stderr, "       n (default = 0)\n");
+  (void) fprintf(vis_stderr, "   set hybrid_pre_split_max_depth <n>\n");
+  (void) fprintf(vis_stderr, "       n (default = 4)\n");
+  (void) fprintf(vis_stderr, "   set hybrid_lambda_threshold <f>\n");
+  (void) fprintf(vis_stderr, "       f (default = 0.6)\n");
+  (void) fprintf(vis_stderr, "   set hybrid_pre_lambda_threshold <f>\n");
+  (void) fprintf(vis_stderr, "       f (default = 0.65)\n");
+  (void) fprintf(vis_stderr, "   set hybrid_conjoin_vector_size <n>\n");
+  (void) fprintf(vis_stderr, "       n (default = 10)\n");
+  (void) fprintf(vis_stderr, "   set hybrid_conjoin_relation_size <n>\n");
+  (void) fprintf(vis_stderr, "       n (default = 2)\n");
+  (void) fprintf(vis_stderr, "   set hybrid_conjoin_relation_bdd_size <n>\n");
+  (void) fprintf(vis_stderr, "       n (default = 200)\n");
+  (void) fprintf(vis_stderr, "   set hybrid_improve_lambda <f>\n");
+  (void) fprintf(vis_stderr, "       f (default = 0.1)\n");
+  (void) fprintf(vis_stderr, "   set hybrid_improve_vector_size <n>\n");
+  (void) fprintf(vis_stderr, "       n (default = 3)\n");
+  (void) fprintf(vis_stderr, "   set hybrid_improve_vector_bdd_size <f>\n");
+  (void) fprintf(vis_stderr, "       f (default = 30.0)\n");
+  (void) fprintf(vis_stderr, "   set hybrid_decide_mode <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : use only lambda\n");
+  (void) fprintf(vis_stderr, "       m = 1 : use lambda and special checks\n");
+  (void) fprintf(vis_stderr, "       m = 2 : use lambda and improvement\n");
+  (void) fprintf(vis_stderr, "       m = 3 : use all (default)\n");
+  (void) fprintf(vis_stderr, "   set hybrid_reorder_with_from <m>\n");
+  (void) fprintf(vis_stderr, "       m = yes : include from set in reordering relation array (default)\n");
+  (void) fprintf(vis_stderr, "       m = no  : do not include\n");
+  (void) fprintf(vis_stderr, "   set hybrid_pre_reorder_with_from <m>\n");
+  (void) fprintf(vis_stderr, "       m = yes : include from set in reordering relation array\n");
+  (void) fprintf(vis_stderr, "       m = no  : do not include (default)\n");
+  (void) fprintf(vis_stderr, "   set hybrid_lambda_mode <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : total lifetime with ps/pi variables (default)\n");
+  (void) fprintf(vis_stderr, "       m = 1 : active lifetime with ps/pi variables\n");
+  (void) fprintf(vis_stderr, "       m = 2 : total lifetime with ps/ns/pi variables\n");
+  (void) fprintf(vis_stderr, "   set hybrid_pre_lambda_mode <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : total lifetime with ns/pi variables\n");
+  (void) fprintf(vis_stderr, "       m = 1 : active lifetime with ps/pi variables\n");
+  (void) fprintf(vis_stderr, "       m = 2 : total lifetime with ps/ns/pi variables (default)\n");
+  (void) fprintf(vis_stderr, "       m = 3 : total lifetime with ps/pi variables\n");
+  (void) fprintf(vis_stderr, "   set hybrid_lambda_with_from <m>\n");
+  (void) fprintf(vis_stderr, "       m = yes : include from set in lambda computation (default)\n");
+  (void) fprintf(vis_stderr, "       m = no  : do not include\n");
+  (void) fprintf(vis_stderr, "   set hybrid_lambda_with_clustering <m>\n");
+  (void) fprintf(vis_stderr, "       m = yes : compute lambda after clustering\n");
+  (void) fprintf(vis_stderr, "       m = no  : do not cluster (default)\n");
+  (void) fprintf(vis_stderr, "   set hybrid_synchronize_tr <m>\n");
+  (void) fprintf(vis_stderr, "       m = yes : rebuild transition relation whenever function vector changes\n");
+  (void) fprintf(vis_stderr, "       m = no  : do not rebuild (default)\n");
+  (void) fprintf(vis_stderr, "   set hybrid_img_keep_pi <m>\n");
+  (void) fprintf(vis_stderr, "       m = yes : keep all pi variables in forward tr\n");
+  (void) fprintf(vis_stderr, "       m = no  : quantify out local pi variables (default)\n");
+  (void) fprintf(vis_stderr, "   set hybrid_pre_keep_pi <m>\n");
+  (void) fprintf(vis_stderr, "       m = yes : keep all pi variables in backward tr and preimages\n");
+  (void) fprintf(vis_stderr, "       m = no  : quantify out local pi variables (default)\n");
+  (void) fprintf(vis_stderr, "   set hybrid_pre_canonical <m>\n");
+  (void) fprintf(vis_stderr, "       m = yes : canonicalize the function vector for preimage\n");
+  (void) fprintf(vis_stderr, "       m = no  : do not canonicalize (default)\n");
+  (void) fprintf(vis_stderr, "   set hybrid_tr_method <m>\n");
+  (void) fprintf(vis_stderr, "       m = iwls95 (default)\n");
+  (void) fprintf(vis_stderr, "       m = mlp\n");
+  return 1;
+} /* end of CommandPrintHybridOptions */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the print_mlp_options command.]
+
+  CommandName [print_mlp_options]
+
+  CommandSynopsis [print information about the MLP image computation options
+  currently in use]
+
+  CommandArguments [\[-h\] \[-H\]]
+
+  CommandDescription [Prints information about the current MLP image
+  computation options.
+  <p>
+
+  Command options: <p>
+
+  <dl>
+
+  <dt> -h
+  <dd> Print the command usage.<p>
+
+  <dt> -H
+  <dd> Print the MLP image computation set command usage.<p>
+  
+  </dl>
+
+  Set parameters: The MLP image computation options are specified with the
+  set command.
+
+  <dl>
+
+  <dt> mlp_cluster <code> <m>&lt;method<m>&gt; </code>
+  <dd> Specify a method for clustering. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: linear clustering <p>
+  <code> 1 </code>: affinity based tree clustering (default) <p>
+
+  <dt> mlp_reorder <code> <m>&lt;method<m>&gt; </code>
+  <dd> Specify a method for reordering after clustering for image
+  computation. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: no reordering after clustering (default) <p>
+  <code> 1 </code>: reorder using MLP after clustering (inside) <p>
+  <code> 2 </code>: reorder using MLP after clustering (outside) <p>
+  <code> 3 </code>: reorder using IWLS95 after clustering <p>
+
+  <dt> mlp_pre_reorder <code> <m>&lt;method<m>&gt; </code>
+  <dd> Specify a method for reordering after clustering for preimage
+  computation. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: no reordering after clustering (default) <p>
+  <code> 1 </code>: reorder using MLP after clustering (inside) <p>
+  <code> 2 </code>: reorder using MLP after clustering (outside) <p>
+  <code> 3 </code>: reorder using IWLS95 after clustering <p>
+
+  <dt> mlp_postprocess <code> <m>&lt;method<m>&gt; </code>
+  <dd> Specify when to do postprocessing. <p>
+  <dd>
+  <code> method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: no postprocessing (default) <p>
+  <code> 1 </code>: do postprocesing after ordering <p>
+  <code> 2 </code>: do postprocesing after clustering or reordering <p>
+  <code> 3 </code>: do both 1 and 2 <p>
+
+  </dl>
+  ]
+  
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandPrintMlpOptions(Hrc_Manager_t ** hmgr, int  argc, char ** argv)
+{
+  int c;
+
+  if (*hmgr == NULL) {
+    fprintf(vis_stderr,"** hrc error: Hierarchy manager is empty\n");
+    return 1;
+  }
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "hH")) != EOF) {
+    switch(c) {
+      case 'h':
+        goto usage;
+      case 'H':
+        goto usage_mlp;
+      default:
+        goto usage;
+    }
+  }
+
+  /* print hybrid image computation options */
+  Img_PrintMlpOptions();
+  return 0;
+
+usage:
+  (void) fprintf(vis_stderr,"usage: print_mlp_options [-h] [-H]\n");
+  (void) fprintf(vis_stderr, "  -h  print the command usage\n");
+  (void) fprintf(vis_stderr,
+		"  -H  print the MLP image computation set command usage\n");
+  return 1;
+usage_mlp:
+  (void) fprintf(vis_stderr, "   set mlp_cluster <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : linear clustering\n");
+  (void) fprintf(vis_stderr, "       m = 1 : affinity based tree clustering (default)\n");
+  (void) fprintf(vis_stderr, "   set mlp_reorder <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : no reordering after clustering (default)\n");
+  (void) fprintf(vis_stderr, "       m = 1 : reorder using MLP after clustering (inside)\n");
+  (void) fprintf(vis_stderr, "       m = 2 : reorder using MLP after clustering (outside)\n");
+  (void) fprintf(vis_stderr, "       m = 3 : reorder using IWLS95 after clustering\n");
+  (void) fprintf(vis_stderr, "   set mlp_pre_reorder <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : no reordering after clustering (default)\n");
+  (void) fprintf(vis_stderr, "       m = 1 : reorder using MLP after clustering (inside)\n");
+  (void) fprintf(vis_stderr, "       m = 2 : reorder using MLP after clustering (outside)\n");
+  (void) fprintf(vis_stderr, "       m = 3 : reorder using IWLS95 after clustering\n");
+  (void) fprintf(vis_stderr, "   set mlp_postprocess <m>\n");
+  (void) fprintf(vis_stderr, "       m = 0 : no postprocessing (default)\n");
+  (void) fprintf(vis_stderr, "       m = 1 : do postprocessing after ordering\n");
+  (void) fprintf(vis_stderr, "       m = 2 : do postprocessing after clustering or reordering\n");
+  (void) fprintf(vis_stderr, "       m = 3 : do both 1 and 2\n");
+  return 1;
+} /* end of CommandPrintMlpOptions */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the print_guided_search_options command.]
+
+  CommandName [print_guided_search_options]
+
+  CommandSynopsis [print information about guided_search_options in use]
+
+  CommandArguments [\[-h\] ]
+
+  CommandDescription [Prints information about current Guided Search
+  options. Guided search is an alternate method to compute fixpoints
+  by modifying the fixpoint computation with restrictions. It is
+  applicable to the <tt>compute_reach</tt>, <tt>check_invariant</tt>
+  and <tt>model_check</tt> commands (refer to their help pages on the
+  use of guided search). See also for details: Ravi and Somenzi, Hints
+  to accelerate symbolic traversal. CHARME'99; Bloem, Ravi, and
+  Somenzi, Efficient Decision Procedures for Model Checking of Linear
+  Time Logic Properties, CAV'99; Bloem, Ravi, and Somenzi, Symbolic
+  Guided Search for CTL Model Checking, DAC'00. Not allowed with -A 2
+  or -i, and will only work with iwls95 or monolithic image methods.
+  The description of some options can be found in the help page for
+  set. <p>
+
+  Command options: <p>
+
+  <dl>
+  <dt>guided_search_hint_type</dt>
+  
+  <dd>Choose from local (default) or global.  If this flag is set to
+  local, then every subformula is evaluated to completion, using all
+  hints in order, before the next subformula is started. For pure ACTL
+  or pure ECTL formulae, we can also set guided_search_hint_type to
+  global, in which case the entire formula is evaluated for one hint
+  before moving on to the next hint, using underapproximations.</dd>
+
+  <dt>guided_search_underapprox_minimize_method</dt>
+
+  <dd>Choose from "constrain" and "and" (default).  Sets the method with which
+  the transition relation is minimized when underapproximations are used.  The
+  option constrain is incompatible with hints that use signals other than
+  inputs.</dd>
+
+  <dt>guided_search_overapprox_minimize_method</dt>
+
+  <dd>Choose from "squeeze" and "ornot" (default).  Sets the method with which
+  the transition relation is minimized when underapproximations are used.  The
+  option squeeze is incompatible with hints that use signals other than inputs.
+  Ornot implies that the transition relation will be disjoined with the
+  negation of the hint: T' = T + ~h, whereas squeeze will find a small BDD
+  between T and T'.</dd>
+
+  <dt>guided_search_sequence</dt>
+
+  <dd>For compute_reach and check_invariant only.  Set this flag to a list of
+  comma-separated integers <code>i1,i2,...,in</code>, with <code>n</code> at
+  most the number of hints that you specify .  The <code>k</code>'th hint will
+  be used for <code>ik</code> iterations (images).  A value of <code>0</code>
+  causes the hint to be applied to convergence.  Not setting this option is
+  like setting it to <code>0,0,...,0</code>.  If length of the specified
+  sequence is less than the number of hints, the sequence is padded with
+  zeroes.   
+  </dl>
+
+  Guided search also uses the High Density traversal options that are
+  germane to dead-ends. The relevant flags are hd_dead_end,
+  hd_dead_end_approx_method, hd_frontier_approx_threshold,
+  hd_approx_quality, hd_approx_bias_quality. Use help on the
+  print_hd_options command for explanation of these flags. If guided
+  search is used with HD using the -A 1 options in
+  <tt>compute_reach</tt> and <tt>check_invariant</tt>, the HD options
+  are used by both HD and guided search. ]
+
+  
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandPrintGuidedSearchOptions(Hrc_Manager_t ** hmgr, int  argc, char ** argv)
+{
+  int c;
+  if (*hmgr == NULL) {
+    fprintf(vis_stderr,"** hrc error: Hierarchy manager is empty\n");
+    return 1;
+  }
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "h")) != EOF) {
+    switch(c) {
+      case 'h':
+        goto usage;
+      default:
+        goto usage;
+    }
+     /* NOT REACHED */
+  }
+
+  FsmGuidedSearchPrintOptions();
+  return 0;
+ usage:
+  (void) fprintf(vis_stderr,"usage: print_guided_search_options [-h]\n");
+  (void) fprintf(vis_stderr, "  -h  print the command usage\n");
+  return 1;
+
+} /* end of CommandGuidedSearchPrintOptions */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Handle function for timeout.]
+
+  Description [This function is called when the time out occurs.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+TimeOutHandle(void)
+{
+  longjmp(timeOutEnv, 1);
+}
Index: vis_dev/vis-2.3/src/fsm/fsmFair.c
===================================================================
--- vis_dev/vis-2.3/src/fsm/fsmFair.c	(revision 14)
+++ vis_dev/vis-2.3/src/fsm/fsmFair.c	(revision 14)
@@ -0,0 +1,912 @@
+/**CFile***********************************************************************
+
+  FileName    [fsmFair.c]
+
+  PackageName [fsm]
+
+  Synopsis    [Implementation of fairness constraints data structure.]
+
+  Description [Implementation of fairness constraints data structure.  The
+  fairness constraint data structure has been defined to allow canonical
+  fairness constraints.  However, presently, only Buchi constraints can be
+  parsed, and the model checker can handle only Buchi constraints.]
+
+  Author      [Tom Shiple and Adnan Aziz and Gitanjali Swamy]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "fsmInt.h"
+
+static char rcsid[] UNUSED = "$Id: fsmFair.c,v 1.28 2003/01/22 18:44:20 jinh Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [A leaf of the canonical fairness constraint structure.  The name
+  is misleading: this is interpreted as (GF finallyinf + FG globallyInf), a
+  disjunction.]
+
+******************************************************************************/
+typedef struct FairnessConjunctStruct {
+  Ctlp_Formula_t *finallyInf;  /* states to visit infinitely often */
+  Ctlp_Formula_t *globallyInf; /* states to visit almost always */
+} FairnessConjunct_t;
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static FairnessConjunct_t * FairnessReadConjunct(Fsm_Fairness_t *fairness, int i, int j);
+static mdd_t * FsmObtainStatesSatisfyingFormula(Fsm_Fsm_t *fsm, Ctlp_Formula_t *formula, array_t *careSetArray, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the fairness constraint of an FSM.]
+
+  Description [Returns the fairness constraint of an FSM.  This is stored as a
+  "canonical fairness constraint", which is a formula of the form (OR_i (AND_j
+  (F-inf S_ij + G-inf T_ij))). Each of the S_ij and T_ij are CTL formulas,
+  representing a set of states in the FSM. F-inf means "globally finally", or
+  "infinitely often"; G-inf means "finally globally" or "almost always".<p>
+
+  Each (AND_j (F-inf S_ij + G-inf T_ij)) is referred to as a "disjunct", and
+  each (F-inf S_ij + G-inf T_ij) is referred to as a "conjunct".  A Streett
+  constraint has just one disjunct.  A Buchi constraint has just one disjunct,
+  and each conjunct of this disjunct has a NULL G-inf condition.<p>
+
+  By default, an FSM is always initialized with a single fairness constraint
+  TRUE, indicating that all states are "accepting".]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmComputeFairStates Fsm_FairnessReadFinallyInfFormula
+  Fsm_FairnessReadGloballyInfFormula]
+
+******************************************************************************/
+Fsm_Fairness_t *
+Fsm_FsmReadFairnessConstraint(
+  Fsm_Fsm_t *fsm)
+{
+  return (fsm->fairnessInfo.constraint);
+}
+
+mdd_t *
+Fsm_FsmReadFairnessStates(Fsm_Fsm_t *fsm)
+{
+   return(fsm->fairnessInfo.states);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the set of fair states of an FSM.]
+
+  Description [Computes the set of fair states of an FSM.  If there is a
+  fairness constraint associated with the FSM, and the fair states have been
+  previously computed, then a copy of the fair states is returned.  If none of
+  the above is true, then the CTL model checker is called to compute the set of
+  fair states, and a copy of this set is returned.  Also, if the CTL model
+  checker is called, information is stored in the FSM for the purpose of
+  debugging CTL formulas in the presence of a fairness constraint.  The second
+  argument is an optional care set array; when this is used, the set of fair
+  states returned is correct on the conjunction of the elements of the care set
+  array.  If careSetArray is set to NIL(mdd_t), it is defaulted to a
+  one-element array containing mdd_one.
+
+  <p> Note that when an FSM is created, by default, there is a single fairness
+  constraint TRUE, indicating that all states are "accepting".  In this case,
+  this function will just return TRUE, which is correct assuming that there are
+  no dead-end states.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmReadFairnessConstraint]
+
+******************************************************************************/
+mdd_t *
+Fsm_FsmComputeFairStates(
+  Fsm_Fsm_t *fsm,
+  array_t *careSetArray,
+  int verbosity,
+  int dcLevel,
+  Mc_GSHScheduleType schedule,
+  Mc_FwdBwdAnalysis direction,
+  boolean useEarlyTermination)
+{
+  mdd_manager    *mddManager = Fsm_FsmReadMddManager(fsm);
+  Fsm_Fairness_t *constraint = Fsm_FsmReadFairnessConstraint(fsm);
+
+  assert(constraint != NIL(Fsm_Fairness_t));
+
+  if (fsm->fairnessInfo.states != NIL(mdd_t)) {
+    /* Already computed. */
+    return mdd_dup(fsm->fairnessInfo.states);
+  } else {
+    /* Compute from scratch. */
+    mdd_t   *fairStates;
+    array_t *dbgArray = array_alloc(array_t *, 0);
+
+    /* No or trivial fairness constraint */
+    if (FsmFairnessConstraintIsDefault(constraint)) {
+      array_t *onionRings;
+      
+      fairStates = mdd_one(mddManager);
+      
+      onionRings = array_alloc(mdd_t *, 1);
+      array_insert_last(mdd_t *, onionRings, mdd_one(mddManager));
+      array_insert_last(array_t *, dbgArray, onionRings);
+
+      fsm->fairnessInfo.states = mdd_dup(fairStates);
+      fsm->fairnessInfo.dbgArray = dbgArray;
+    } else {
+      mdd_t   *oneMdd = mdd_one(mddManager);
+      array_t *tmpCareSetArray;
+
+      if (careSetArray) {
+	tmpCareSetArray = careSetArray;
+      } else {
+	/* oneMdd is default */
+	tmpCareSetArray = array_alloc(mdd_t *, 0);
+	array_insert_last(mdd_t *, tmpCareSetArray, oneMdd);
+      }
+
+      if (direction == McBwd_c) {
+	mdd_t *initialStates;
+	Mc_EarlyTermination_t *earlyTermination;
+	int fixpoint = 1;
+	
+	if (useEarlyTermination == TRUE) {
+	  initialStates = Fsm_FsmComputeInitialStates(fsm);
+	  earlyTermination = Mc_EarlyTerminationAlloc(McSome_c, initialStates);
+	} else {
+	  initialStates = NIL(mdd_t);
+	  earlyTermination = MC_NO_EARLY_TERMINATION;
+	}
+
+	fairStates =
+	  Mc_FsmEvaluateEGFormula(fsm,
+				  oneMdd, NIL(mdd_t), oneMdd,
+				  constraint, tmpCareSetArray,
+				  earlyTermination, NIL(array_t),
+				  Mc_None_c, &dbgArray,
+				  (Mc_VerbosityLevel) verbosity,
+				  (Mc_DcLevel) dcLevel,
+				  &fixpoint, schedule);
+	if (useEarlyTermination == TRUE) {
+	  Mc_EarlyTerminationFree(earlyTermination);
+	  mdd_free(initialStates);
+	}
+	if (!fixpoint) {
+	  int i;
+	  array_t *mddArray;
+	  arrayForEachItem(array_t *, dbgArray, i, mddArray) {
+	    mdd_array_free(mddArray);
+	  }
+	  array_free(dbgArray);
+	} else {
+	  fsm->fairnessInfo.states = mdd_dup(fairStates);
+	  fsm->fairnessInfo.dbgArray = dbgArray;
+	}
+      } else {
+	fairStates =
+	  Mc_FsmEvaluateEHFormula(fsm,
+				  oneMdd, NIL(mdd_t), oneMdd,
+				  constraint, tmpCareSetArray,
+				  MC_NO_EARLY_TERMINATION, NIL(array_t),
+				  Mc_None_c, NIL(array_t *),
+				  (Mc_VerbosityLevel) verbosity,
+				  (Mc_DcLevel) dcLevel,
+				  NIL(boolean), schedule);
+	array_free(dbgArray);
+      }
+      if (tmpCareSetArray != careSetArray)
+	array_free(tmpCareSetArray);
+      mdd_free(oneMdd);
+    }
+
+    return fairStates;
+  }/* compute from scratch*/
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the finallyInf component of a leaf of a canonical fairness
+  constraint.]
+
+  Description [Reads the finallyInf component of the jth conjunct of the ith
+  disjunct of a canonical fairness constraint (i and j start counting from
+  0). This is CTL formula representing a set of states of an FSM; this formula
+  is not necessarily in existential normal form. If there is no finallyInf
+  component at this location, then a NULL formula is returned.  It is assumed
+  that i and j are within bounds.]
+
+  SideEffects []
+
+  SeeAlso [Fsm_FsmReadFairnessConstraint Fsm_FairnessReadGloballyInfFormula
+  Fsm_FairnessReadFinallyInfMdd]
+
+******************************************************************************/
+Ctlp_Formula_t *
+Fsm_FairnessReadFinallyInfFormula(
+  Fsm_Fairness_t *fairness,
+  int i,
+  int j)
+{
+  FairnessConjunct_t *conjunct = FairnessReadConjunct(fairness, i, j);
+  return (conjunct->finallyInf);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the globallyInf component of a leaf of a canonical fairness
+  constraint.]
+
+  Description [Reads the globallyInf component of the jth conjunct of the ith
+  disjunct of a canonical fairness constraint (i and j start counting from
+  0). This is CTL formula representing a set of states of an FSM; this formula
+  is not necessarily in existential normal form. If there is no globallyInf
+  component at this location, then a NULL formula is returned.  It is assumed
+  that i and j are within bounds.]
+
+  SideEffects []
+
+  SeeAlso [Fsm_FsmReadFairnessConstraint Fsm_FairnessReadFinallyInfFormula
+  Fsm_FairnessReadGloballyInfMdd]
+
+******************************************************************************/
+Ctlp_Formula_t *
+Fsm_FairnessReadGloballyInfFormula(
+  Fsm_Fairness_t *fairness,
+  int i,
+  int j)
+{
+  FairnessConjunct_t *conjunct = FairnessReadConjunct(fairness, i, j);
+  return (conjunct->globallyInf);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Obtains a copy of the MDD of the finallyInf component of a leaf of
+  a canonical fairness constraint.]
+
+  Description [Obtains a copy of the MDD of the finallyInf component of the
+  jth conjunct of the ith disjunct of a canonical fairness constraint (i and j
+  start counting from 0). This MDD represents the set of FSM states which
+  satisfy the finallyInf formula.  This set is guaranteed to be correct on the
+  set of reachable states.  If there is no finallyInf component at this
+  location, then a NULL MDD is returned.  It is assumed that i and j are
+  within bounds.  The first time this function is called with the given data,
+  the CTL model checker is called to compute the set of states (with all
+  states fair, and no fairness constraint); additional calls take constant
+  time. It is the responsibililty of the calling function to free the returned
+  mdd.]
+
+  SideEffects []
+
+  SeeAlso [Fsm_FsmReadFairnessConstraint Fsm_FairnessReadFinallyInfFormula
+  Fsm_FairnessReadGloballyInfMdd]
+
+******************************************************************************/
+mdd_t *
+Fsm_FairnessObtainFinallyInfMdd(
+  Fsm_Fairness_t *fairness,
+  int i,
+  int j,
+  array_t *careSetArray,
+  Mc_DcLevel dcLevel)
+{
+  Ctlp_Formula_t *formula = Fsm_FairnessReadFinallyInfFormula(fairness, i, j);
+  /* hard code verbosity to Mc_VerbosityNone */
+  return(FsmObtainStatesSatisfyingFormula(fairness->fsm, formula, careSetArray,
+					  McVerbosityNone_c, dcLevel));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Obtains a copy of the MDD of the globallyInf component of a leaf of
+  a canonical fairness constraint.]
+
+  Description [Obtains a copy of the MDD of the globallyInf component of the
+  jth conjunct of the ith disjunct of a canonical fairness constraint (i and j
+  start counting from 0). This MDD represents the set of FSM states which
+  satisfy the globallyInf formula.  This set is guaranteed to be correct on
+  the set of reachable states.  If there is no globallyInf component at this
+  location, then a NULL MDD is returned.  It is assumed that i and j are
+  within bounds. The first time this function is called with the given data,
+  the CTL model checker is called to compute the set of states (with all
+  states fair, and no fairness constraint); additional calls take constant
+  time. It is the responsibililty of the calling function to free the returned
+  mdd.]
+
+  SideEffects []
+
+  SeeAlso [Fsm_FsmReadFairnessConstraint Fsm_FairnessReadGloballyInfFormula
+  Fsm_FairnessReadFinallyInfMdd]
+
+******************************************************************************/
+mdd_t *
+Fsm_FairnessObtainGloballyInfMdd(
+  Fsm_Fairness_t *fairness,
+  int i,
+  int j,
+  array_t *careSetArray,
+  Mc_DcLevel dcLevel)
+{
+  Ctlp_Formula_t *formula = Fsm_FairnessReadGloballyInfFormula(fairness, i, j);
+  /* hard code verbosity to Mc_VerbosityNone */
+  return(FsmObtainStatesSatisfyingFormula(fairness->fsm, formula, careSetArray,
+					  McVerbosityNone_c, dcLevel));
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns TRUE if fairness constraint is of type Streett.]
+
+  Description [Returns TRUE if fairness constraint is of type Streett, else
+  FALSE.  A Streett fairness constraint is a canonical fairness constraint,
+  with one disjunct.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmReadFairnessConstraint Fsm_FairnessTestIsBuchi]
+
+******************************************************************************/
+boolean
+Fsm_FairnessTestIsStreett(
+  Fsm_Fairness_t *fairness)
+{
+  return (array_n(fairness->disjunctArray) == 1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns TRUE if fairness constraint is of type Buchi].
+
+  Description [Returns TRUE if fairness constraint is of type Buchi, else
+  FALSE.  A Buchi fairness constraint is a canonical fairness constraint, with
+  one disjunct, where each conjunct has a NULL G-inf condition.  Note that a
+  Buchi constraint is also a Streett constraint.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmReadFairnessConstraint Fsm_FairnessTestIsStreet]
+
+******************************************************************************/
+boolean
+Fsm_FairnessTestIsBuchi(
+  Fsm_Fairness_t *fairness)
+{
+  if (array_n(fairness->disjunctArray) != 1) {
+    return (FALSE);
+  }
+  else {
+    int      j;
+    array_t *disjunct = array_fetch(array_t *, fairness->disjunctArray, 0);
+
+    for (j = 0; j < array_n(disjunct); j++) {
+      FairnessConjunct_t *conjunct = array_fetch(FairnessConjunct_t *,
+						 disjunct, j);
+      if (conjunct->globallyInf != NIL(Ctlp_Formula_t)) {
+        return (FALSE);
+      }
+    }
+    return (TRUE);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of disjuncts of a canonical fairness
+  constraint.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmReadFairnessConstraint
+  Fsm_FairnessReadNumConjunctsOfDisjunct]
+
+******************************************************************************/
+int
+Fsm_FairnessReadNumDisjuncts(
+  Fsm_Fairness_t *fairness)
+{
+  return (array_n(fairness->disjunctArray));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the number of conjuncts of the ith disjunct of a canonical
+  fairness constraint.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmReadFairnessConstraint Fsm_FairnessReadNumDisjuncts]
+
+******************************************************************************/
+int
+Fsm_FairnessReadNumConjunctsOfDisjunct(
+  Fsm_Fairness_t *fairness,
+  int i)
+{
+  array_t *disjunct = array_fetch(array_t *, fairness->disjunctArray, i);
+
+  return (array_n(disjunct));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the fair CTL debugging information of an FSM.]
+
+  Description [Returns the fair CTL debugging information of an FSM.
+  Currently, the fairness constraints are limited to Buchi constraints. The
+  return value is an array of array_t* of mdd_t*.  The returned array is of
+  length k, where k is the number of Buchi constraints.  The ith element of
+  the returned array is an array of MDDs giving the sequence of state sets
+  that can reach the ith Buchi constraint.  In particular, the jth MDD of the
+  ith array is the set of states that can reach the ith Buchi set in j or
+  fewer steps (the 0th MDD is the ith Buchi set itself).]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmReadFairnessConstraint]
+
+******************************************************************************/
+array_t *
+Fsm_FsmReadDebugArray(Fsm_Fsm_t *fsm)
+{
+  return (fsm->fairnessInfo.dbgArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Create and Update the fairness constraint of the FSM.]
+
+  Description [Given the FSM and an array of CTL formula, build the buechi
+  fairness constraints, and update.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmReadFairnessConstraint]
+
+******************************************************************************/
+void
+Fsm_FsmFairnessUpdate(
+  Fsm_Fsm_t *fsm,
+  array_t *formulaArray)
+{
+    Fsm_Fairness_t *fairness = FsmFairnessAlloc(fsm);
+    int j;
+    /*
+     * Interpret the array of CTL formulas as a set of Buchi conditions.
+     * Hence, create a single disjunct, consisting of k conjuncts, where k is
+     * the number of CTL formulas read in.  The jth conjunct has the jth
+     * formula as its finallyInf component, and NULL as its globallyInf
+     * component.
+     */
+    
+    for (j = 0; j < array_n(formulaArray); j++) {
+      Ctlp_Formula_t *formula = array_fetch(Ctlp_Formula_t *, formulaArray, j);
+
+      FsmFairnessAddConjunct(fairness, formula, NIL(Ctlp_Formula_t), 0, j);
+    }
+
+    /*
+     * Remove any existing fairnessInfo associated with the FSM, and update
+     * the fairnessInfo.constraint with the new fairness just read.
+     */
+    FsmFsmFairnessInfoUpdate(fsm, NIL(mdd_t), fairness, NIL(array_t));
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Create a default fairness constraint.]
+
+  Description [Create a default fairness constraint containing a single
+  formula, TRUE, indicating that all states are "accepting".]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmReadFairnessConstraint]
+
+******************************************************************************/
+Fsm_Fairness_t *
+FsmFsmCreateDefaultFairnessConstraint(
+  Fsm_Fsm_t *fsm)
+{
+  Fsm_Fairness_t *fairness    = FsmFairnessAlloc(fsm);
+  Ctlp_Formula_t *trueFormula = Ctlp_FormulaCreate(Ctlp_TRUE_c,
+                                                   NIL(Ctlp_Formula_t),
+                                                   NIL(Ctlp_Formula_t));
+
+  FsmFairnessAddConjunct(fairness, trueFormula, NIL(Ctlp_Formula_t), 0, 0);
+  return fairness;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [See whether the fairness constraint is the default one]
+
+  Description [See if the fairness constraint is the default one, which implies
+  that all states are accepting.]
+
+  SideEffects []
+
+  SeeAlso     [FsmFsmCreateDefaultFairnessConstraint]
+
+******************************************************************************/
+boolean
+FsmFairnessConstraintIsDefault(
+  Fsm_Fairness_t *fairness)
+{
+  array_t            *disjuncts;
+  array_t            *conjuncts;
+  FairnessConjunct_t *leaf;
+  Ctlp_Formula_t     *tautology;
+  boolean            result;
+  
+  /* one disjunct */
+  disjuncts = fairness->disjunctArray;
+  if(array_n(disjuncts) !=  1)
+    return FALSE;
+
+  /* one conjunct */
+  conjuncts = array_fetch(array_t *, disjuncts, 0);
+  if(array_n(conjuncts) != 1)
+    return FALSE;
+
+  /* set to (GF TRUE * FG NULL) */
+  leaf = array_fetch(FairnessConjunct_t *, conjuncts, 0);
+  if(leaf->globallyInf != NIL(Ctlp_Formula_t))
+    return FALSE;
+
+  tautology = Ctlp_FormulaCreate(Ctlp_TRUE_c, NIL(Ctlp_Formula_t),
+				 NIL(Ctlp_Formula_t));
+  result = Ctlp_FormulaIdentical(tautology, leaf->finallyInf);
+  Ctlp_FormulaFree(tautology);
+
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a fairness constraint.]
+
+  Description [Frees all the memory associated with a fairness constraint,
+  including the underlying CTL formulas.]
+
+  SideEffects []
+
+  SeeAlso     [FsmFairnessAlloc]
+
+******************************************************************************/
+void
+FsmFairnessFree(
+  Fsm_Fairness_t *fairness)
+{
+  int i;
+
+  for (i = 0; i < array_n(fairness->disjunctArray); i++) {
+    int j;
+    array_t *disjunct = array_fetch(array_t *, fairness->disjunctArray, i);
+
+    for (j = 0; j < array_n(disjunct); j++) {
+      FairnessConjunct_t *conjunct = array_fetch(FairnessConjunct_t *,
+                                                 disjunct, j);
+      Ctlp_FormulaFree(conjunct->finallyInf);
+      Ctlp_FormulaFree(conjunct->globallyInf);
+      FREE(conjunct);
+    }
+    array_free(disjunct);
+  }
+  array_free(fairness->disjunctArray);
+  FREE(fairness);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates a fairness constraint.]
+
+  Description [Allocates a fairness constraint.  Sets the FSM pointer, and
+  allocates a disjunct array containing 0 elements.]
+
+  SideEffects []
+
+  SeeAlso     [FsmFairnessFree FsmFairnessAddConjunct]
+
+******************************************************************************/
+Fsm_Fairness_t *
+FsmFairnessAlloc(Fsm_Fsm_t *fsm)
+{
+  Fsm_Fairness_t *fairness = ALLOC(Fsm_Fairness_t, 1);
+
+  fairness->fsm           = fsm;
+  fairness->disjunctArray = array_alloc(array_t *, 0);
+
+  return fairness;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adds a conjunct to a fairness constraint.]
+
+  Description [Adds a conjunct to a fairness constraint. i and j must not be
+  negative; otherwise, there is no restriction on their values.  i and j start
+  counting from 0.  Note that it is possible to create a 2-D array with
+  "holes" in it, although this is probably not desirable.  If holes are
+  created, they are zeroed out.]
+
+  SideEffects []
+
+  SeeAlso     [FsmFairnessAlloc]
+
+******************************************************************************/
+void
+FsmFairnessAddConjunct(
+  Fsm_Fairness_t *fairness,
+  Ctlp_Formula_t *finallyInf,
+  Ctlp_Formula_t *globallyInf,
+  int             i,
+  int             j)
+{
+  int k;
+  array_t *disjunct;
+  int numConjuncts;
+  int                 numDisjuncts = array_n(fairness->disjunctArray);
+  FairnessConjunct_t *conjunct     = ALLOC(FairnessConjunct_t, 1);
+
+  assert((i >= 0) && (j >= 0));
+
+  /* Get the array for row i. */
+  if (i >= numDisjuncts) {
+    /*
+     * i is out of range.  Create a new disjunct, add it to the array, and
+     * zero out the intervening entries.
+     */
+    disjunct = array_alloc(FairnessConjunct_t *, 0);
+
+    /* Note that the array is dynamically extended. */
+    array_insert(array_t *, fairness->disjunctArray, i, disjunct);
+
+    /* Zero out the holes just created (if any). */
+    for (k = numDisjuncts; k < i; k++) {
+      array_insert(array_t *, fairness->disjunctArray, k, NIL(array_t));
+    }
+  }
+  else {
+    /*
+     * i is in range.  However, there may not be a non-NIL array at entry i
+     * yet.
+     */
+    disjunct = array_fetch(array_t *, fairness->disjunctArray, i);
+    if (disjunct == NIL(array_t)) {
+      disjunct = array_alloc(FairnessConjunct_t *, 0);
+      array_insert(array_t *, fairness->disjunctArray, i, disjunct);
+    }
+  }
+
+  /*
+   * Fill in the conjunct, and add it to the jth position of the ith row.  If
+   * holes are created, then zero them out.
+   */
+  conjunct->finallyInf  = finallyInf;
+  conjunct->globallyInf = globallyInf;
+
+  array_insert(FairnessConjunct_t *, disjunct, j, conjunct);
+  numConjuncts = array_n(disjunct);
+  for (k = numConjuncts; k < j; k++) {
+    array_insert(FairnessConjunct_t *, disjunct, k, NIL(FairnessConjunct_t));
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Updates the fairnessInfo of an FSM.]
+
+  Description [Updates the fairnessInfo of an FSM with the supplied arguments.
+  If any of the existing fields are currently non-NULL, then first frees
+  them. DbgArray is assumed to be an array of arrays of mdd_t's.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+FsmFsmFairnessInfoUpdate(
+  Fsm_Fsm_t *fsm,
+  mdd_t *states,
+  Fsm_Fairness_t *constraint,
+  array_t *dbgArray)
+{
+  array_t *oldDbgArray = fsm->fairnessInfo.dbgArray;
+
+  if (fsm->fairnessInfo.states != NIL(mdd_t)){
+    mdd_free(fsm->fairnessInfo.states);
+  }
+  fsm->fairnessInfo.states = states;
+
+  if (fsm->fairnessInfo.constraint != NIL(Fsm_Fairness_t)) {
+    FsmFairnessFree(fsm->fairnessInfo.constraint);
+  }
+  fsm->fairnessInfo.constraint = constraint;
+
+  if (oldDbgArray != NIL(array_t)) {
+    int i;
+    for (i = 0; i < array_n(oldDbgArray); i++) {
+      array_t *mddArray = array_fetch(array_t *, oldDbgArray, i);
+      mdd_array_free(mddArray);
+    }
+    array_free(oldDbgArray);
+  }
+  fsm->fairnessInfo.dbgArray = dbgArray;
+}
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Reads a leaf of a canonical fairness constraint.]
+
+  Description [Reads the the jth conjunct of the ith disjunct of a canonical
+  fairness constraint.  It is assumed that i and j are within bounds.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmReadFairnessConstraint Fsm_FairnessReadGloballyInfFormula
+  Fsm_FairnessReadFinallyInfMdd]
+
+******************************************************************************/
+static FairnessConjunct_t *
+FairnessReadConjunct(
+  Fsm_Fairness_t *fairness,
+  int i,
+  int j)
+{
+  array_t            *disjunct;
+  FairnessConjunct_t *conjunct;
+
+  assert((i >= 0) && (i < array_n(fairness->disjunctArray)));
+  disjunct = array_fetch(array_t *, fairness->disjunctArray, i);
+
+  assert((j >= 0) && (j < array_n(disjunct)));
+  conjunct = array_fetch(FairnessConjunct_t *, disjunct, j);
+
+  return conjunct;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Obtains the set of states satisfying a formula.]
+
+  Description [Returns a copy of the set of states satisfying a CTL formula,
+  in the context of an FSM.  If this set has already been computed for this
+  formula, then a copy is returned.  Otherwise, the CTL model checker is
+  called on the existential normal form of the formula, with all states fair,
+  and no fairness constraint.  The result is guaranteed correct on reachable
+  states.  If formula is NULL, then a NULL MDD is returned.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FairnessObtainFinallyInfMdd Fsm_FairnessObtainGloballyInfMdd]
+
+******************************************************************************/
+static mdd_t *
+FsmObtainStatesSatisfyingFormula(
+  Fsm_Fsm_t      *fsm,
+  Ctlp_Formula_t *formula,
+  array_t *careSetArray,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel)
+{
+  if (formula == NIL(Ctlp_Formula_t)) {
+    return (NIL(mdd_t));
+  }
+  else {
+    mdd_t *stateSet = Ctlp_FormulaObtainStates(formula);
+
+    if (stateSet != NIL(mdd_t)) {
+      return stateSet;
+    }
+    else {
+      mdd_t          *result;
+      mdd_manager    *mddManager  = Fsm_FsmReadMddManager(fsm);
+      mdd_t          *oneMdd      = mdd_one(mddManager);
+      Ctlp_Formula_t *convFormula =
+			Ctlp_FormulaConvertToExistentialForm(formula);
+
+      /* Note that Mc_FsmEvaluateFormula returns a copy of the MDD. */
+      result = Mc_FsmEvaluateFormula(fsm, convFormula, oneMdd,
+				     NIL(Fsm_Fairness_t),
+				     careSetArray,
+				     MC_NO_EARLY_TERMINATION,
+				     NIL(Fsm_HintsArray_t),
+				     Mc_None_c, verbosity, dcLevel, 0,
+				     McGSH_EL_c);
+      mdd_free(oneMdd);
+
+      /*
+       * We must make a copy of the MDD for the return value.
+       */
+      Ctlp_FormulaSetStates(formula, result);
+      stateSet = mdd_dup(result);
+
+      Ctlp_FormulaFree(convFormula);
+
+      return stateSet;
+    }
+  }
+}
Index: vis_dev/vis-2.3/src/fsm/fsmFsm.c
===================================================================
--- vis_dev/vis-2.3/src/fsm/fsmFsm.c	(revision 14)
+++ vis_dev/vis-2.3/src/fsm/fsmFsm.c	(revision 14)
@@ -0,0 +1,2720 @@
+/**CFile***********************************************************************
+
+  FileName    [fsmFsm.c]
+
+  PackageName [fsm]
+
+  Synopsis    [Routines to create and manipulate the FSM structure.]
+
+  Author      [Shaker Sarwary, Tom Shiple, Rajeev Ranjan, In-Ho Moon]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "fsmInt.h"
+
+static char rcsid[] UNUSED = "$Id: fsmFsm.c,v 1.88 2007/04/02 17:03:13 hhkim Exp $";
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static Fsm_Fsm_t * FsmStructAlloc(Ntk_Network_t *network, graph_t *partition);
+static void FsmCreateVariableCubes(Fsm_Fsm_t *fsm);
+static int nameCompare(const void * name1, const void * name2);
+static boolean VarIdArrayCompare(mdd_manager *mddMgr, array_t *vars1, array_t *vars2);
+static boolean NSFunctionNamesCompare(mdd_manager *mddMgr, array_t *names1, array_t *names2);
+static array_t * GetMddSupportIdArray(Fsm_Fsm_t *fsm, st_table *mddIdTable, st_table *pseudoMddIdTable);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Creates an FSM from a network.]
+
+  Description [Creates an FSM from a network and a partition. The FSM is
+  initialized to the single fairness constraint TRUE, indicating that all
+  states are "accepting". Reachability information, fair states, and
+  imageInfo, are initialized to NIL, since these items are computed on
+  demand. If the network has no latches, then NULL is returned and a message
+  is written to error_string.<p>
+
+  The partition gives the MVFs defining the next state functions of the
+  network.  If the partition is NULL, then a duplicate of the default
+  partition of the network (found using Part_NetworkReadPartition) is used.
+  If the network has no default partition, then NULL is returned and a message
+  is written to error_string.  Having the partition as a parameter gives the
+  calling application the flexibility of using a different partition from the
+  default, possibly one representing different functions than those given by
+  the network (say for the purpose of computing approximations).  However, it
+  is assumed (though not checked), that the partition has the same
+  combinational input variables and next state function names as the network.
+  Finally, note that the given partition will be freed when the FSM is freed.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmFree]
+
+******************************************************************************/
+Fsm_Fsm_t *
+Fsm_FsmCreateFromNetworkWithPartition(
+  Ntk_Network_t *network,
+  graph_t       *partition)
+{
+  lsGen       gen;
+  Ntk_Node_t *latch;
+  Ntk_Node_t *input;
+  Fsm_Fsm_t  *fsm;
+  int i;
+  
+  fsm = FsmStructAlloc(network, partition);
+  if (fsm == NIL(Fsm_Fsm_t)) return NIL(Fsm_Fsm_t);
+  fsm->fairnessInfo.constraint = FsmFsmCreateDefaultFairnessConstraint(fsm);
+  
+  /* sort by name of latch */
+  Ntk_NetworkForEachLatch(network, gen, latch){
+    array_insert_last(char*, fsm->fsmData.nextStateFunctions,
+                      Ntk_NodeReadName(latch));
+  }
+
+  array_sort(fsm->fsmData.nextStateFunctions, nameCompare);
+
+  for (i = 0; i < array_n(fsm->fsmData.nextStateFunctions); i ++) {
+    char *nodeName;
+    nodeName = array_fetch(char *, fsm->fsmData.nextStateFunctions, i);
+    latch = Ntk_NetworkFindNodeByName(network, nodeName);
+    array_insert(char*, fsm->fsmData.nextStateFunctions, i,
+		 Ntk_NodeReadName(Ntk_LatchReadDataInput(latch)));
+    array_insert_last(int, fsm->fsmData.presentStateVars,
+		      Ntk_NodeReadMddId(latch));
+    array_insert_last(int, fsm->fsmData.nextStateVars,
+		      Ntk_NodeReadMddId(Ntk_NodeReadShadow(latch)));
+  }
+  
+  Ntk_NetworkForEachInput(network, gen, input){
+    array_insert_last(int, fsm->fsmData.inputVars, Ntk_NodeReadMddId(input));
+  }
+  
+  FsmCreateVariableCubes(fsm);
+  return (fsm);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a FSM given the set of latches and the inputs.]
+
+  Description [This function is primarily used to create a "reduced"
+  FSM specific to a particular property during model checking. The
+  given array of latches and inputs are associated with the FSM. If
+  partition is NIL, the default partition from network is
+  obtained. This partition will be used to obtain the next state
+  functions of the latches. The last argument is an arry of fairness
+  constraints which is used to restrict the reduced fsm to fair
+  paths. </p>
+  For a detailed desription of various fields of FSM, please refer to
+  the function Fsm_FsmCreateFromNetworkWithPartition.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmFree Fsm_FsmCreateFromNetworkWithPartition]
+
+******************************************************************************/
+Fsm_Fsm_t *
+Fsm_FsmCreateReducedFsm(
+  Ntk_Network_t *network,
+  graph_t       *partition,
+  array_t       *latches,
+  array_t       *inputs,
+  array_t       *fairArray)
+{
+  Ntk_Node_t *latch;
+  Ntk_Node_t *input;
+  Fsm_Fsm_t  *fsm;
+  Fsm_Fairness_t *fairness;
+  int i,j;
+  
+  if (array_n(latches) == 0){
+    error_append("Number of latches passed = 0. Cannot create sub-FSM.");
+    return (NIL(Fsm_Fsm_t));
+  }
+  
+  fsm = FsmStructAlloc(network, partition);
+  if (fsm == NIL(Fsm_Fsm_t)) return NIL(Fsm_Fsm_t);
+
+  /* initialize fairness constraints */
+  if (fairArray != NIL(array_t)){
+    fairness = FsmFairnessAlloc(fsm);    
+    for (j = 0; j < array_n(fairArray); j++) {
+      Ctlp_Formula_t *formula = array_fetch(Ctlp_Formula_t *, fairArray, j);
+      
+      FsmFairnessAddConjunct(fairness, formula, NIL(Ctlp_Formula_t), 0, j);
+    }
+    fsm->fairnessInfo.constraint = fairness;
+  }
+  else {
+    fsm->fairnessInfo.constraint =
+        FsmFsmCreateDefaultFairnessConstraint(fsm);
+  }
+
+  /* sort latches by name */
+  for(i=0; i<array_n(latches); i++){
+    latch = array_fetch(Ntk_Node_t*, latches, i);
+    array_insert_last(char*, fsm->fsmData.nextStateFunctions,
+                      Ntk_NodeReadName(latch));
+  }
+  array_sort(fsm->fsmData.nextStateFunctions, nameCompare);
+
+  for(i=0; i<array_n(latches); i++){
+    char *nodeName;
+    nodeName = array_fetch(char *, fsm->fsmData.nextStateFunctions, i);
+    latch = Ntk_NetworkFindNodeByName(network, nodeName);  
+    array_insert_last(int, fsm->fsmData.presentStateVars,
+                      Ntk_NodeReadMddId(latch));
+    array_insert_last(int, fsm->fsmData.nextStateVars,
+                      Ntk_NodeReadMddId(Ntk_NodeReadShadow(latch)));
+    array_insert(char*, fsm->fsmData.nextStateFunctions, i, 
+                      Ntk_NodeReadName(Ntk_LatchReadDataInput(latch)));
+  }
+  
+  for(i=0; i<array_n(inputs); i++){
+    input = array_fetch(Ntk_Node_t*, inputs, i);
+    array_insert_last(int, fsm->fsmData.inputVars, Ntk_NodeReadMddId(input));
+  }
+
+  FsmCreateVariableCubes(fsm);
+  return (fsm);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a FSM given the set of latches and the inputs.]
+
+  Description [This function is primarily used to create an "abstract"
+  FSM specific to a particular property during invariant checking with
+  abstraction refinement method Grab. The given array of latches and
+  inputs are associated with the FSM. the array of invisible latches
+  can be treated either as inputs (independentFlag==TRUE), or as
+  latches (independentFlag==FALSE). It is the user's responsibility to
+  make sure that latches, invisibleVars, and inputs are mutually
+  disjoint. 
+
+  When independentFlag==TRUE, the FSM is defined by the pair
+  (fsmData.presentStateVars, fsmData.inputVars); when
+  independentFlag==FALSE, the FSM is defined by the pair
+  (fsmData.globalPsVars, fsmData.primaryInputVars). For more
+  information, please check the function
+  Fsm_FsmReadOrCreateImageInfo(). The two pairs are defined as
+  follows:
+
+                presentStateVars inputVars  globalPsVars primaryInputVars
+  ----------------------------------------------------------------------- 
+  absLatches   |        X                        X
+  invisibleVars|                     X           X
+  inputs       |                     X                          X  
+  -----------------------------------------------------------------------
+
+  If partition is NIL, the default partition from network is
+  obtained. This partition will be used to obtain the next state
+  functions of the latches. The last argument is an arry of fairness
+  constraints which is used to restrict the reduced fsm to fair
+  paths. </p> For a detailed desription of various fields of FSM,
+  please refer to the function Fsm_FsmCreateFromNetworkWithPartition.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmFree Fsm_FsmCreateReducedFsm]
+
+******************************************************************************/
+Fsm_Fsm_t *
+Fsm_FsmCreateAbstractFsm(
+  Ntk_Network_t *network,
+  graph_t       *partition,
+  array_t       *latches,
+  array_t       *invisibleVars,
+  array_t       *inputs,
+  array_t       *fairArray,
+  boolean        independentFlag)
+{
+  Ntk_Node_t *latch;
+  Ntk_Node_t *input;
+  Ntk_Node_t *node;
+  Fsm_Fsm_t  *fsm;
+  Fsm_Fairness_t *fairness;
+  int i,j;
+  
+  if (FALSE && array_n(latches) == 0){
+    error_append("Number of latches passed = 0. Cannot create sub-FSM.");
+    return (NIL(Fsm_Fsm_t));
+  }
+  
+  fsm = FsmStructAlloc(network, partition);
+  if (fsm == NIL(Fsm_Fsm_t)) return NIL(Fsm_Fsm_t);
+
+  /* initialize fairness constraints */
+  if (fairArray != NIL(array_t)){
+    fairness = FsmFairnessAlloc(fsm);    
+    for (j = 0; j < array_n(fairArray); j++) {
+      Ctlp_Formula_t *formula = array_fetch(Ctlp_Formula_t *, fairArray, j);
+      
+      FsmFairnessAddConjunct(fairness, formula, NIL(Ctlp_Formula_t), 0, j);
+    }
+    fsm->fairnessInfo.constraint = fairness;
+  }
+  else {
+    fsm->fairnessInfo.constraint =
+        FsmFsmCreateDefaultFairnessConstraint(fsm);
+  }
+
+  /* when independentFlag==FALSE, use globalPsVars and
+   * primaryInputVars (instead of presentStateVars and inputVars) to
+   * build the transition relation
+   */
+  if (!independentFlag) {
+    fsm->fsmData.globalPsVars = array_alloc(int, 0);
+    fsm->fsmData.primaryInputVars = array_alloc(int, 0);
+  }
+
+
+  /* sort latches by name */
+  for(i=0; i<array_n(latches); i++){
+    latch = array_fetch(Ntk_Node_t*, latches, i);
+    array_insert_last(char*, fsm->fsmData.nextStateFunctions,
+                      Ntk_NodeReadName(latch));
+  }
+  array_sort(fsm->fsmData.nextStateFunctions, nameCompare);
+
+  for(i=0; i<array_n(latches); i++){
+    char *nodeName;
+    nodeName = array_fetch(char *, fsm->fsmData.nextStateFunctions, i);
+    latch = Ntk_NetworkFindNodeByName(network, nodeName);  
+    array_insert_last(int, fsm->fsmData.presentStateVars,
+                      Ntk_NodeReadMddId(latch));
+    array_insert_last(int, fsm->fsmData.nextStateVars,
+                      Ntk_NodeReadMddId(Ntk_NodeReadShadow(latch)));
+    array_insert(char*, fsm->fsmData.nextStateFunctions, i, 
+                      Ntk_NodeReadName(Ntk_LatchReadDataInput(latch)));
+    
+    if (!independentFlag)
+      array_insert_last(int, fsm->fsmData.globalPsVars,
+			Ntk_NodeReadMddId(latch));      
+  }
+
+  for(i=0; i<array_n(inputs); i++){
+    input = array_fetch(Ntk_Node_t*, inputs, i);
+    array_insert_last(int, fsm->fsmData.inputVars, Ntk_NodeReadMddId(input));
+    
+    if (!independentFlag)
+      array_insert_last(int, fsm->fsmData.primaryInputVars, 
+			Ntk_NodeReadMddId(input));
+  }
+
+
+  arrayForEachItem(Ntk_Node_t *, invisibleVars, i, node) {
+    array_insert_last(int, fsm->fsmData.inputVars, Ntk_NodeReadMddId(node));
+
+    if (!independentFlag) {
+      array_insert_last(int, fsm->fsmData.globalPsVars, 
+			Ntk_NodeReadMddId(node));
+    }
+  }
+
+
+  FsmCreateVariableCubes(fsm);
+  return (fsm);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the memory associated with an FSM.]
+
+  Description [Frees the memory associated with an FSM. In particular, frees
+  all the MDDs, and frees the associated partition.  The FSM's corresponding
+  network is not modified in any way.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmCreateFromNetwork]
+
+******************************************************************************/
+void
+Fsm_FsmFree(
+  Fsm_Fsm_t * fsm)
+{
+  Part_PartitionFree(fsm->partition);
+  Fsm_FsmSubsystemFree(fsm);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the memory associated with an FSM.]
+
+  Description [Identical to Fsm_FsmFree() but does not free the partition.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmCreateSubsystemFromNetwork]
+
+******************************************************************************/
+void
+Fsm_FsmSubsystemFree(
+  Fsm_Fsm_t * fsm)
+{
+
+  Fsm_FsmFreeImageInfo(fsm);
+  
+  /* Free reachability info. */
+  if (fsm->reachabilityInfo.initialStates != NIL(mdd_t)){
+    mdd_free(fsm->reachabilityInfo.initialStates);
+  }
+  if (fsm->reachabilityInfo.reachableStates != NIL(mdd_t)){
+    mdd_free(fsm->reachabilityInfo.reachableStates);
+  }
+  if (fsm->reachabilityInfo.apprReachableStates != NIL(array_t))
+    mdd_array_free(fsm->reachabilityInfo.apprReachableStates);
+  if (fsm->reachabilityInfo.subPsVars != NIL(array_t)){
+    int i;
+    array_t *psVars;
+    arrayForEachItem(array_t *, fsm->reachabilityInfo.subPsVars, i, psVars) {
+      array_free(psVars);
+    }
+    array_free(fsm->reachabilityInfo.subPsVars);
+  }
+  if (Fsm_FsmReadReachabilityOnionRings(fsm) != NIL(array_t)){
+    mdd_array_free(Fsm_FsmReadReachabilityOnionRings(fsm));
+  }
+
+  /* Free fairness info. */
+  FsmFsmFairnessInfoUpdate(fsm, NIL(mdd_t), NIL(Fsm_Fairness_t), NIL(array_t));
+
+  array_free(fsm->fsmData.presentStateVars);
+  array_free(fsm->fsmData.nextStateVars);
+  array_free(fsm->fsmData.inputVars);
+  array_free(fsm->fsmData.nextStateFunctions);
+  if (fsm->fsmData.pseudoInputVars)
+    array_free(fsm->fsmData.pseudoInputVars);
+  if (fsm->fsmData.primaryInputVars)
+    array_free(fsm->fsmData.primaryInputVars);
+  if (fsm->fsmData.globalPsVars)
+    array_free(fsm->fsmData.globalPsVars);
+
+  if (fsm->fsmData.presentStateCube)
+    mdd_free(fsm->fsmData.presentStateCube);
+  if (fsm->fsmData.nextStateCube)
+    mdd_free(fsm->fsmData.nextStateCube);
+  if (fsm->fsmData.inputCube)
+    mdd_free(fsm->fsmData.inputCube);
+  if (fsm->fsmData.pseudoInputCube)
+    mdd_free(fsm->fsmData.pseudoInputCube);
+  if (fsm->fsmData.primaryInputCube)
+    mdd_free(fsm->fsmData.primaryInputCube);
+  if (fsm->fsmData.globalPsCube)
+    mdd_free(fsm->fsmData.globalPsCube);
+
+  if (fsm->fsmData.pseudoInputBddVars)
+    mdd_array_free(fsm->fsmData.pseudoInputBddVars);
+  if (fsm->fsmData.presentStateBddVars)
+    mdd_array_free(fsm->fsmData.presentStateBddVars);
+
+  FREE(fsm);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Callback function to free an FSM.]
+
+  Description [Typecasts data to (Fsm_Fsm_t *) and then calls Fsm_FsmFree.
+  This function should only be used as a callback for other applications that
+  don't know the FSM type, for example the network ApplInfoTable.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmFree]
+
+******************************************************************************/
+void
+Fsm_FsmFreeCallback(
+  void * data /* an object of type Fsm_Fsm_t*  type casted to void* */)
+{
+  Fsm_FsmFree((Fsm_Fsm_t *) data);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the corresponding network of an FSM.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmCreateFromNetwork]
+
+******************************************************************************/
+Ntk_Network_t *
+Fsm_FsmReadNetwork(
+  Fsm_Fsm_t * fsm)
+{
+  return (fsm->network);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Read UnquantifiedFlag of an FSM.]
+
+  Description [This is function for FateAndFreeWill counterexample generation.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmCreateFromNetwork]
+
+******************************************************************************/
+boolean
+Fsm_FsmReadUseUnquantifiedFlag(
+  Fsm_Fsm_t * fsm)
+{
+  return (fsm->useUnquantifiedFlag);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the MDD manager of the corresponding network of an FSM.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmCreateFromNetwork]
+
+******************************************************************************/
+mdd_manager *
+Fsm_FsmReadMddManager(
+  Fsm_Fsm_t * fsm)
+{
+  return (Ntk_NetworkReadMddManager(fsm->network));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the FSM of a network; creates FSM if necessary.]
+
+  Description [If there is an FSM associated with network, then returns it.
+  Otherwise, creates an FSM from network (using a duplicate of the partition
+  associated with the network), registers the FSM with the network, and then
+  returns the newly created FSM.  Note that if the network has no latches or
+  the network has no partition, then a NULL FSM is returned.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmCreateFromNetwork Ntk_NetworkReadApplInfo
+  Fsm_NetworkReadFsm]
+
+******************************************************************************/
+Fsm_Fsm_t *
+Fsm_NetworkReadOrCreateFsm(
+  Ntk_Network_t * network)
+{
+  Fsm_Fsm_t *fsm = (Fsm_Fsm_t*) Ntk_NetworkReadApplInfo(network, FSM_NETWORK_APPL_KEY);
+      
+  if (fsm == NIL(Fsm_Fsm_t)) {
+    fsm = Fsm_FsmCreateFromNetworkWithPartition(network, NIL(graph_t));
+    if (fsm != NIL(Fsm_Fsm_t)) {
+      (void) Ntk_NetworkAddApplInfo(network, FSM_NETWORK_APPL_KEY,
+                             (Ntk_ApplInfoFreeFn) Fsm_FsmFreeCallback,
+                             (void *) fsm);
+    }
+  }
+  
+  return fsm;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the FSM of a network.]
+
+  Description [Returns the FSM of a network, which may be NULL.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmCreateFromNetwork Ntk_NetworkReadApplInfo
+  Fsm_NetworkReadOrCreateFsm]
+
+******************************************************************************/
+Fsm_Fsm_t *
+Fsm_NetworkReadFsm(
+  Ntk_Network_t * network)
+{
+  return ((Fsm_Fsm_t*) Ntk_NetworkReadApplInfo(network,
+                                               FSM_NETWORK_APPL_KEY));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the imageInfo struct stored by the FSM.]
+
+  Description [Returns the imageInfo struct stored by the FSM, which may be
+  NULL.]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoInitialize Fsm_FsmReadOrCreateImageInfo]
+
+******************************************************************************/
+Img_ImageInfo_t *
+Fsm_FsmReadImageInfo(
+  Fsm_Fsm_t *fsm)
+{
+  return (fsm->imageInfo);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Set the imageInfo.]
+
+  Description [Set the imageInfo. ] 
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoInitialize Fsm_FsmReadOrCreateImageInfo]
+
+******************************************************************************/
+void
+Fsm_FsmSetImageInfo(
+  Fsm_Fsm_t *fsm, Img_ImageInfo_t *imageInfo)
+{
+  fsm->imageInfo = imageInfo;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the imageInfo struct stored by the FSM.]
+
+  Description [Returns the imageInfo struct stored by the FSM, which may be
+  NULL.]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoInitialize Fsm_FsmReadOrCreateImageInfo]
+
+******************************************************************************/
+void
+Fsm_FsmFreeImageInfo(
+  Fsm_Fsm_t *fsm)
+{
+  if(fsm->imageInfo) {
+    Img_ImageInfoFree(fsm->imageInfo);
+    fsm->imageInfo = NIL(Img_ImageInfo_t);
+  }
+
+  if(fsm->unquantifiedImageInfo) {
+    Img_ImageInfoFree(fsm->unquantifiedImageInfo);
+    fsm->unquantifiedImageInfo = NIL(Img_ImageInfo_t);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the partition associated with the FSM.]
+
+  Description [Returns the partition associated with the FSM.  This is the
+  graph of MVFs defining the combinational output functions of the FSM.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmCreateFromNetwork]
+
+******************************************************************************/
+graph_t *
+Fsm_FsmReadPartition(
+  Fsm_Fsm_t *fsm)
+{
+  return (fsm->partition);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Test if reachability has been performed on the FSM.]
+
+  Description [Return TRUE if reachability has already been performed, else FALSE.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmComputeReachableStates]
+
+******************************************************************************/
+boolean
+Fsm_FsmTestIsReachabilityDone(
+  Fsm_Fsm_t *fsm)
+{
+  
+  if (Fsm_FsmReadReachableStates(fsm) != NIL(mdd_t)) {
+	return TRUE;
+  }
+  return FALSE;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Test if approximate reachability has been performed on the FSM.]
+
+  Description [Return TRUE if approximate reachability has already been
+  performed, else FALSE.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmComputeReachableStates]
+
+******************************************************************************/
+boolean
+Fsm_FsmTestIsOverApproximateReachabilityDone(
+  Fsm_Fsm_t *fsm)
+{
+  
+  if (Fsm_FsmReadOverApproximateReachableStates(fsm) != NIL(array_t)) {
+	return TRUE;
+  }
+  return FALSE;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the reachable states of an FSM.]
+
+  SideEffects [Returns the reachable states of an FSM.]
+
+  SeeAlso     [Fsm_FsmComputeReachableStates]
+
+******************************************************************************/
+mdd_t *
+Fsm_FsmReadReachableStates(
+  Fsm_Fsm_t *fsm)
+{
+  if (fsm->reachabilityInfo.rchStatus == Fsm_Rch_Exact_c)
+    return(fsm->reachabilityInfo.reachableStates);
+  else
+    return(NIL(mdd_t));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the reachable states of an FSM.]
+
+  SideEffects [Returns the reachable states of an FSM. May be an under
+  approximation or an over approximation.]
+
+  SeeAlso     [Fsm_FsmComputeReachableStates]
+
+******************************************************************************/
+mdd_t *
+Fsm_FsmReadCurrentReachableStates(
+  Fsm_Fsm_t *fsm)
+{
+  return(fsm->reachabilityInfo.reachableStates);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the approximate reachable states of an FSM.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_ArdcComputeOverApproximateReachableStates]
+
+******************************************************************************/
+array_t *
+Fsm_FsmReadOverApproximateReachableStates(
+  Fsm_Fsm_t *fsm)
+{
+  if (fsm->reachabilityInfo.overApprox >= 2)
+    return(fsm->reachabilityInfo.apprReachableStates);
+  else
+    return(NIL(array_t));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the current approximate reachable states of an FSM.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_ArdcComputeOverApproximateReachableStates]
+
+******************************************************************************/
+array_t *
+Fsm_FsmReadCurrentOverApproximateReachableStates(
+  Fsm_Fsm_t *fsm)
+{
+  return(fsm->reachabilityInfo.apprReachableStates);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return array of onion rings from reachability computation]
+
+  Description [Return array of onion rings from reachability
+  computation; NIL if reachability has not been performed. DO NOT free
+  this array.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmComputeReachableStates]
+
+******************************************************************************/
+array_t *
+Fsm_FsmReadReachabilityOnionRings(
+  Fsm_Fsm_t *fsm)
+{
+  return fsm->reachabilityInfo.onionRings;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Checks whether the onion rings are consistent with the
+  reachable states.]
+
+  Description [Checks whether the onion rings are consistent with the
+  reachable states. Returns FALSE if no states in onion
+  rings.]
+
+  SideEffects [result is set to the union of the onion rings]
+
+  SeeAlso     [Fsm_FsmbtainBFSShells]
+
+******************************************************************************/
+boolean
+Fsm_FsmReachabilityOnionRingsStates(
+  Fsm_Fsm_t *fsm,
+  mdd_t ** result)
+{
+  int i;
+  mdd_t *tmpMdd;
+  mdd_t *ring;
+  array_t *onionRings;
+
+  onionRings = Fsm_FsmReadReachabilityOnionRings(fsm);
+  if ( onionRings == NIL(array_t) ) {
+    *result = NIL(mdd_t);
+    return 0;
+  }
+
+  *result = bdd_zero(Fsm_FsmReadMddManager(fsm));
+  arrayForEachItem(mdd_t *, onionRings, i, ring) {
+    tmpMdd = mdd_or(*result, ring, 1, 1);
+    mdd_free(*result);
+    *result = tmpMdd;
+  }
+  if (Fsm_FsmReadCurrentReachableStates(fsm)) {
+    if (mdd_lequal(Fsm_FsmReadCurrentReachableStates(fsm), *result, 1,1)) {
+      FsmSetReachabilityOnionRingsUpToDateFlag(fsm, TRUE);
+    }
+  }
+  return (Fsm_FsmTestReachabilityOnionRingsUpToDate(fsm));
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Checks if the onion rings are consistent with the
+  reachable states.]
+
+  Description [Checks if the onion rings are consistent with the
+  reachable states.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmComputeReachableStates]
+
+******************************************************************************/
+boolean
+Fsm_FsmTestReachabilityOnionRingsUpToDate(
+  Fsm_Fsm_t *fsm)
+{
+  return fsm->reachabilityInfo.onionRingsUpToDate;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Checks if the onion rings are due to BFS or not.]
+
+  Description [Checks if the onion rings are due to BFS or not.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmComputeReachableStates]
+
+******************************************************************************/
+Fsm_RchType_t
+Fsm_FsmReadReachabilityOnionRingsMode(
+  Fsm_Fsm_t *fsm)
+{
+  return fsm->reachabilityInfo.onionRingsMode;
+}
+
+  
+/**Function********************************************************************
+
+  Synopsis    [Returns the imageInfo struct stored by the FSM; creates if
+  necessary.]
+
+  Description [Returns the imageInfo struct stored by the FSM.  If one doesn't
+  currently exist in the FSM, then one is initialized and set, before it is
+  returned.  The imageInfo is initialized using the default image method, and
+  is initialized for both forward and backward image computations. It uses the
+  partition with which this FSM was created when the function
+  Fsm_FsmCreateFromNetwork was called.]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoInitialize Fsm_FsmReadImageInfo]
+
+******************************************************************************/
+Img_ImageInfo_t *
+Fsm_FsmReadOrCreateImageInfo(Fsm_Fsm_t *fsm, int bwdImgFlag, int fwdImgFlag)
+{
+  Img_DirectionType	imgFlag = Img_Forward_c;
+  array_t		*presentStateVars, *inputVars;
+  mdd_t			*presentStateCube, *inputCube;
+
+  if (bwdImgFlag && fwdImgFlag)
+    imgFlag = Img_Both_c;
+  else if (bwdImgFlag)
+    imgFlag = Img_Backward_c;
+
+  if (fsm->fsmData.globalPsVars) {
+    presentStateVars = fsm->fsmData.globalPsVars;
+    inputVars = fsm->fsmData.primaryInputVars;
+    presentStateCube = fsm->fsmData.globalPsCube;
+    inputCube = fsm->fsmData.primaryInputCube;
+  } else {
+    presentStateVars = fsm->fsmData.presentStateVars;
+    inputVars = fsm->fsmData.inputVars;
+    presentStateCube = fsm->fsmData.presentStateCube;
+    inputCube = fsm->fsmData.inputCube;
+  }
+
+  fsm->imageInfo = Img_ImageInfoInitialize(fsm->imageInfo,
+                                           fsm->partition,
+                                           fsm->fsmData.nextStateFunctions,
+                                           presentStateVars,
+                                           fsm->fsmData.nextStateVars,
+                                           inputVars,
+                                           presentStateCube,
+                                           fsm->fsmData.nextStateCube,
+                                           inputCube,
+                                           fsm->network,
+                                           Img_Default_c, imgFlag, 0, 0);
+
+  if (fsm->fsmData.globalPsVars) {
+    Img_ImageInfoUpdateVariables(fsm->imageInfo,
+				 fsm->partition,
+				 fsm->fsmData.presentStateVars,
+				 fsm->fsmData.inputVars,
+				 fsm->fsmData.presentStateCube,
+				 fsm->fsmData.inputCube);
+  }
+
+  return(fsm->imageInfo);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the imageInfo struct stored by the FSM; creates if
+  necessary.]
+
+  Description [Returns the imageInfo struct stored by the FSM.  If one doesn't
+  currently exist in the FSM, then one is initialized and set, before it is
+  returned.  The imageInfo is initialized using the default image method, and
+  is initialized for both forward and backward image computations. It uses the
+  partition with which this FSM was created when the function
+  Fsm_FsmCreateFromNetwork was called. In this function we create the ImageInfo 
+  that has no quntified input for Fate and Free will.]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoInitialize Fsm_FsmReadImageInfo]
+
+******************************************************************************/
+Img_ImageInfo_t *
+Fsm_FsmReadOrCreateImageInfoFAFW(Fsm_Fsm_t *fsm, int bwdImgFlag, int fwdImgFlag)
+{
+  Img_DirectionType	imgFlag = Img_Forward_c;
+  array_t		*presentStateVars, *inputVars;
+  mdd_t			*presentStateCube, *inputCube;
+  mdd_manager           *mgr;
+
+  mgr = Fsm_FsmReadMddManager(fsm);
+
+  if (bwdImgFlag && fwdImgFlag)
+    imgFlag = Img_Both_c;
+  else if (bwdImgFlag)
+    imgFlag = Img_Backward_c;
+
+  presentStateVars = fsm->fsmData.presentStateVars;
+  inputVars = array_alloc(int , 0);
+  presentStateCube = fsm->fsmData.presentStateCube;
+  inputCube = mdd_one(mgr);
+
+  fsm->unquantifiedImageInfo = Img_ImageInfoInitialize(
+		                           fsm->unquantifiedImageInfo,
+                                           fsm->partition,
+                                           fsm->fsmData.nextStateFunctions,
+                                           presentStateVars,
+                                           fsm->fsmData.nextStateVars,
+                                           inputVars,
+                                           presentStateCube,
+                                           fsm->fsmData.nextStateCube,
+                                           inputCube,
+                                           fsm->network,
+                                           Img_Default_c, imgFlag, 1, 0);
+
+  if(!Img_IsQuantifyArraySame(fsm->unquantifiedImageInfo, inputVars)) {
+    array_free(inputVars);
+  }
+
+  if(!Img_IsQuantifyCubeSame(fsm->unquantifiedImageInfo, inputCube)) {
+    mdd_free(inputCube);
+  }
+
+  return(fsm->unquantifiedImageInfo);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the imageInfo struct stored by the FSM; creates if
+  necessary.]
+
+  Description [Returns the imageInfo struct stored by the FSM.  If one doesn't
+  currently exist in the FSM, then one is initialized and set, before it is
+  returned.  The imageInfo is initialized using the default image method, and
+  is initialized for both forward and backward image computations. It uses the
+  partition with which this FSM was created when the function
+  Fsm_FsmCreateFromNetwork was called. In this function we create the ImageInfo 
+  that has no quntified input for Fate and Free will.]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoInitialize Fsm_FsmReadImageInfo]
+
+******************************************************************************/
+Img_ImageInfo_t *
+Fsm_FsmReadOrCreateImageInfoPrunedFAFW(Fsm_Fsm_t *fsm, mdd_t *Winning, int bwdImgFlag, int fwdImgFlag)
+{
+  Img_DirectionType	imgFlag = Img_Forward_c;
+  array_t		*presentStateVars, *inputVars;
+  mdd_t			*presentStateCube, *inputCube;
+  mdd_manager           *mgr;
+  Img_ImageInfo_t *imageInfo;
+
+  mgr = Fsm_FsmReadMddManager(fsm);
+
+  if (bwdImgFlag && fwdImgFlag)
+    imgFlag = Img_Both_c;
+  else if (bwdImgFlag)
+    imgFlag = Img_Backward_c;
+
+  presentStateVars = fsm->fsmData.presentStateVars;
+  inputVars = array_alloc(int , 0);
+  presentStateCube = fsm->fsmData.presentStateCube;
+  inputCube = mdd_one(mgr);
+
+  imageInfo = Img_ImageInfoInitialize(
+		                           0,
+                                           fsm->partition,
+                                           fsm->fsmData.nextStateFunctions,
+                                           presentStateVars,
+                                           fsm->fsmData.nextStateVars,
+                                           inputVars,
+                                           presentStateCube,
+                                           fsm->fsmData.nextStateCube,
+                                           inputCube,
+                                           fsm->network,
+                                           Img_Default_c, imgFlag, 0, Winning);
+
+  if(!Img_IsQuantifyArraySame(imageInfo, inputVars)) {
+    array_free(inputVars);
+  }
+
+  if(!Img_IsQuantifyCubeSame(imageInfo, inputCube)) {
+    mdd_free(inputCube);
+  }
+
+  return(imageInfo);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the imageInfo struct stored by the FSM; creates if
+  necessary.]
+
+  Description [Returns the imageInfo struct stored by the FSM.  If one doesn't
+  currently exist in the FSM, then one is initialized and set, before it is
+  returned.  The imageInfo is initialized using the default image method, and
+  is initialized for both forward and backward image computations. It uses the
+  partition with which this FSM was created when the function
+  Fsm_FsmCreateFromNetwork was called. In this function we create the ImageInfo 
+  that has no quntified input for Fate and Free will.]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoInitialize Fsm_FsmReadImageInfo]
+
+******************************************************************************/
+Img_ImageInfo_t *
+Fsm_FsmReadOrCreateImageInfoForComputingRange(Fsm_Fsm_t *fsm, int bwdImgFlag, int fwdImgFlag)
+{
+  Img_DirectionType	imgFlag = Img_Forward_c;
+  array_t		*presentStateVars, *inputVars;
+  mdd_t			*presentStateCube, *inputCube;
+
+  if (bwdImgFlag && fwdImgFlag)
+    imgFlag = Img_Both_c;
+  else if (bwdImgFlag)
+    imgFlag = Img_Backward_c;
+
+  if (fsm->fsmData.globalPsVars) {
+    presentStateVars = fsm->fsmData.globalPsVars;
+    inputVars = fsm->fsmData.primaryInputVars;
+    presentStateCube = fsm->fsmData.globalPsCube;
+    inputCube = fsm->fsmData.primaryInputCube;
+  } else {
+    presentStateVars = fsm->fsmData.presentStateVars;
+    inputVars = fsm->fsmData.inputVars;
+    presentStateCube = fsm->fsmData.presentStateCube;
+    inputCube = fsm->fsmData.inputCube;
+  }
+
+  fsm->imageInfo = Img_ImageInfoInitialize(fsm->imageInfo,
+                                           fsm->partition,
+                                           fsm->fsmData.nextStateFunctions,
+                                           presentStateVars,
+                                           fsm->fsmData.nextStateVars,
+                                           inputVars,
+                                           presentStateCube,
+                                           fsm->fsmData.nextStateCube,
+                                           inputCube,
+                                           fsm->network,
+                                           Img_Linear_Range_c, imgFlag, 0, 0);
+
+  if (fsm->fsmData.globalPsVars) {
+    Img_ImageInfoUpdateVariables(fsm->imageInfo,
+				 fsm->partition,
+				 fsm->fsmData.presentStateVars,
+				 fsm->fsmData.inputVars,
+				 fsm->fsmData.presentStateCube,
+				 fsm->fsmData.inputCube);
+  }
+
+  return(fsm->imageInfo);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Computes the set of initial states of an FSM.]
+
+  Description [Computes the set of initial states of an FSM.  If this set
+  has already been computed, then just returns the result of the previous
+  computation.  The calling application is responsible for freeing the
+  returned MDD in all cases.<p>
+
+  The nodes driving the initial inputs of the latches, called the initial
+  nodes, must not have latches in their support.  If an initial node is found
+  that has a latch in its transitive fanin, then a NULL MDD is returned, and a
+  message is written to the error_string.<p>
+  
+  The initial states are computed as follows. For each latch i, the relation
+  (x_i = g_i(u)) is built, where x_i is the present state variable of latch i,
+  and g_i(u) is the multi-valued initialization function of latch i, in terms
+  of the input variables u.  These relations are then conjuncted, and the
+  input variables are existentially quantified from the result
+  (i.e. init_states(x) = \exists u \[\prod (x_i = g_i(u))\]).]
+
+  SideEffects [The result of the initial state computation is stored with
+  the FSM.]
+
+  SeeAlso [Fsm_FsmComputeReachableStates]
+  
+******************************************************************************/
+mdd_t *
+Fsm_FsmComputeInitialStates(Fsm_Fsm_t *fsm)
+{
+  int            i = 0;
+  lsGen          gen;
+  mdd_t         *initStates;
+  Ntk_Node_t    *node;
+  array_t       *initRelnArray;
+  array_t       *initMvfs;
+  array_t       *initNodes;
+  array_t       *initVertices;
+  array_t       *latchMddIds;
+  st_table      *supportNodes;
+  st_table      *supportVertices;
+  mdd_manager   *mddManager = Fsm_FsmReadMddManager(fsm);
+  graph_t       *partition  = fsm->partition;
+  Ntk_Network_t *network    = fsm->network;
+  int            numLatches;
+  array_t	*psVars;
+  Img_MethodType imageMethod;
+  
+  /* If already computed, just return a copy. */
+  if (fsm->reachabilityInfo.initialStates != NIL(mdd_t)){
+    return (mdd_dup(fsm->reachabilityInfo.initialStates));
+  }
+
+  psVars = fsm->fsmData.presentStateVars;
+  numLatches = array_n(psVars);
+
+  /*
+   * Get the array of initial nodes, both as network nodes and as partition
+   * vertices.
+   */
+  initNodes    = array_alloc(Ntk_Node_t *, numLatches);
+  initVertices = array_alloc(vertex_t *, numLatches);
+  latchMddIds  = array_alloc(int, numLatches);
+  for (i=0; i<numLatches; i++){
+    int latchMddId = array_fetch(int, psVars, i);
+    Ntk_Node_t *latch = Ntk_NetworkFindNodeByMddId(network, latchMddId);
+    Ntk_Node_t *initNode   = Ntk_LatchReadInitialInput(latch);
+    vertex_t   *initVertex = Part_PartitionFindVertexByName(partition,
+				Ntk_NodeReadName(initNode));
+    array_insert(Ntk_Node_t *, initNodes, i, initNode);
+    array_insert(vertex_t *, initVertices, i, initVertex);
+    array_insert(int, latchMddIds, i, Ntk_NodeReadMddId(latch));
+  }
+
+  /*
+   * Get the table of legal support nodes, both as network nodes and
+   * as partition vertices. Inputs (both primary and pseudo) and constants
+   * constitute the legal support nodes.
+   */
+  supportNodes    = st_init_table(st_ptrcmp, st_ptrhash);
+  supportVertices = st_init_table(st_ptrcmp, st_ptrhash);
+  Ntk_NetworkForEachNode(network, gen, node) {
+    vertex_t *vertex = Part_PartitionFindVertexByName(partition,
+                                                      Ntk_NodeReadName(node));
+
+    if (Ntk_NodeTestIsConstant(node) || Ntk_NodeTestIsInput(node)) {
+      st_insert(supportNodes, (char *) node, NIL(char));
+      st_insert(supportVertices, (char *) vertex, NIL(char));
+    }
+  }
+
+  /*
+   * If the initial nodes are not covered by the legal support nodes, then
+   * return NIL.
+   */
+  if (!Ntk_NetworkTestLeavesCoverSupportOfRoots(network, initNodes,
+  						supportNodes)) {
+    array_free(initNodes);
+    array_free(initVertices);
+    array_free(latchMddIds);
+    st_free_table(supportNodes);
+    st_free_table(supportVertices);
+    return NIL(mdd_t);
+  }
+
+  /*
+   * At this point, we are certain that the initialization functions are
+   * well-defined. Get the MVF for each initialization node, in terms of the
+   * support vertices.  Note that the MVF for each initial node is guaranteed to
+   * exist in the partition, since an initial node is a combinational
+   * output.
+   */
+  array_free(initNodes);
+  st_free_table(supportNodes);
+  initMvfs = Part_PartitionCollapse(partition, initVertices,
+                                    supportVertices, NIL(mdd_t)); 
+  array_free(initVertices);
+  st_free_table(supportVertices);
+
+  /* Compute the relation (x_i = g_i(u)) for each latch. */
+  initRelnArray = array_alloc(mdd_t*, numLatches);
+  for (i = 0; i < numLatches; i++) {
+    int latchMddId = array_fetch(int, latchMddIds, i);
+    Mvf_Function_t *initMvf = array_fetch(Mvf_Function_t *, initMvfs, i);
+    mdd_t *initLatchReln = Mvf_FunctionBuildRelationWithVariable(initMvf,
+								latchMddId);
+    array_insert(mdd_t *, initRelnArray, i, initLatchReln);
+  }
+
+  array_free(latchMddIds);
+  Mvf_FunctionArrayFree(initMvfs);
+
+  /* init_states(x) = \exists u \[\prod (x_i = g_i(u))\] */
+  /*initStates = Fsm_MddMultiwayAndSmooth(mddManager, initRelnArray,
+                                        fsm->fsmData.inputVars);
+  */	
+
+  imageMethod = Img_UserSpecifiedMethod();
+  if (imageMethod != Img_Iwls95_c && imageMethod != Img_Mlp_c)
+    imageMethod = Img_Iwls95_c;
+  initStates = Img_MultiwayLinearAndSmooth(mddManager, initRelnArray,
+                                           fsm->fsmData.inputVars, psVars,
+					   imageMethod, Img_Forward_c); 
+
+  mdd_array_free(initRelnArray); 
+
+  fsm->reachabilityInfo.initialStates = initStates;
+  return mdd_dup(initStates);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the array of MDD ids of the present state variables of an
+  FSM.]
+
+  Description [Returns the array of MDD ids of the present state variables of
+  an FSM.  This array should not be modified or freed in any way.]
+
+  SideEffects []
+
+  SeeAlso [Fsm_FsmReadNextStateVars Fsm_FsmReadInputVars
+  Fsm_FsmReadNextStateFunctionNames]
+
+******************************************************************************/
+array_t *
+Fsm_FsmReadPresentStateVars(Fsm_Fsm_t *fsm)
+{
+  return fsm->fsmData.presentStateVars;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Returns the array of MDD ids of the next state variables of an
+  FSM.]
+
+  Description [Returns the array of MDD ids of the next state variables of
+  an FSM.  This array should not be modified or freed in any way.]
+
+  SideEffects []
+
+  SeeAlso [Fsm_FsmReadPresentStateVars Fsm_FsmReadInputVars
+  Fsm_FsmReadNextStateFunctionNames]
+
+******************************************************************************/
+array_t *
+Fsm_FsmReadNextStateVars(Fsm_Fsm_t *fsm)
+{
+  return fsm->fsmData.nextStateVars;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Returns an array of strings containing the names of the nodes
+  driving the data inputs of the latches.]
+
+  Description [Returns the array of strings containing the names of the nodes
+  driving the data inputs of the latches. This array should not be modified or
+  freed in any way.]
+
+  SideEffects []
+
+  SeeAlso [Fsm_FsmReadPresentStateVars Fsm_FsmReadNextStateVars
+  Fsm_FsmReadInputVars]
+
+******************************************************************************/
+array_t *
+Fsm_FsmReadNextStateFunctionNames(Fsm_Fsm_t *fsm)
+{
+  return fsm->fsmData.nextStateFunctions;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Returns the array of MDD ids of the input variables of an
+  FSM.]
+
+  Description [Returns the array of MDD ids of the input variables of an FSM.
+  This includes both primary inputs and pseudo inputs. This array should not
+  be modified or freed in any way.]
+
+  SideEffects []
+
+  SeeAlso [Fsm_FsmReadPresentStateVars Fsm_FsmReadNextStateVars
+  Fsm_FsmReadNextStateFunctionNames]
+
+******************************************************************************/
+array_t *
+Fsm_FsmReadInputVars(Fsm_Fsm_t *fsm)
+{
+  return fsm->fsmData.inputVars;
+}
+
+array_t *
+Fsm_FsmReadPrimaryInputVars(Fsm_Fsm_t *fsm)
+{
+  return fsm->fsmData.primaryInputVars;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the array of MDD ids of the pseudo input variables
+  of a sub FSM.]
+
+  Description [Returns the array of MDD ids of the pseudo input variables
+  of a sub FSM.  This array should not be modified or freed in any way.]
+
+  SideEffects []
+
+  SeeAlso [Fsm_FsmReadNextStateVars Fsm_FsmReadInputVars
+  Fsm_FsmReadNextStateFunctionNames]
+
+******************************************************************************/
+array_t *
+Fsm_FsmReadPseudoInputVars(Fsm_Fsm_t *fsm)
+{
+  return fsm->fsmData.pseudoInputVars;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set input variables into the FSM structure.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Fsm_FsmSetInputVars(Fsm_Fsm_t *fsm, array_t *inputVars)
+{
+  fsm->fsmData.inputVars = inputVars;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set useUnquantifiedFlag into the FSM structure.]
+
+  Description [This is function for FateAndFreeWill counterexample generation.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Fsm_FsmSetUseUnquantifiedFlag(Fsm_Fsm_t *fsm, boolean value)
+{
+  fsm->useUnquantifiedFlag = value;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set the initial states of an FSM.]
+
+  Description []
+
+  SideEffects [Old mdd_t representing the initial states is deleted and
+  replaced by the argument provided.]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Fsm_FsmSetInitialStates(Fsm_Fsm_t *fsm, mdd_t *initStates)
+{
+  mdd_t *init;
+  
+  init = fsm->reachabilityInfo.initialStates;
+  if (init != NIL(mdd_t)) {
+    mdd_free(init);
+  }
+  fsm->reachabilityInfo.initialStates = initStates;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Read FAFWFlag from the FSM structure.]
+
+  Description [This is function for FateAndFreeWill counterexample generation.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Fsm_FsmReadFAFWFlag(Fsm_Fsm_t *fsm) 
+{
+  return((int)(fsm->FAFWFlag));
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set FAFWFlag in the FSM structure.]
+
+  Description [This is function for FateAndFreeWill counterexample generation.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Fsm_FsmSetFAFWFlag(Fsm_Fsm_t *fsm, boolean FAFWFlag) 
+{
+  fsm->FAFWFlag = FAFWFlag;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set input variables that are controlled by system and environment 
+            in the FSM structure.]
+
+  Description [This is function for FateAndFreeWill counterexample generation.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Fsm_FsmSetSystemVariableFAFW(Fsm_Fsm_t *fsm, st_table *bddIdTable)
+{
+  mdd_manager *mgr;
+  array_t *inputVars, *bddIdArray;
+  bdd_t *extCube, *uniCube;
+  bdd_t *newCube, *varBdd;
+  st_generator *gen;
+  int mddId, bddId, tbddId, i, j;
+
+  if(bddIdTable == 0 && fsm->FAFWFlag == 0) {
+    if(fsm->extQuantifyInputCube)
+      bdd_free(fsm->extQuantifyInputCube);
+    if(fsm->uniQuantifyInputCube)
+      bdd_free(fsm->uniQuantifyInputCube);
+    fsm->extQuantifyInputCube = 0;
+    fsm->uniQuantifyInputCube = 0;
+    return;
+  }
+
+  mgr = Fsm_FsmReadMddManager(fsm);
+  inputVars = Fsm_FsmReadInputVars(fsm);
+
+  extCube = mdd_one(mgr);
+  for(i=0; i<array_n(inputVars); i++) {
+    mddId = array_fetch(int, inputVars, i);
+    bddIdArray = mdd_id_to_bdd_id_array(mgr, mddId);
+    for(j=0; j<array_n(bddIdArray); j++) {
+      bddId = array_fetch(int, bddIdArray, j);
+      if(bddIdTable && st_lookup_int(bddIdTable, (char *)(long)bddId, &tbddId)) {
+	continue;
+      }
+      varBdd = bdd_get_variable(mgr, bddId);
+      newCube = bdd_and(extCube, varBdd, 1, 1);
+      bdd_free(extCube); bdd_free(varBdd);
+      extCube = newCube;
+    }
+    array_free(bddIdArray);
+  }
+  uniCube = mdd_one(mgr);
+  if(bddIdTable) {
+    st_foreach_item(bddIdTable, gen, &bddId, &bddId) {
+      varBdd = bdd_get_variable(mgr, bddId);
+      newCube = bdd_and(uniCube, varBdd, 1, 1);
+      bdd_free(uniCube); bdd_free(varBdd);
+      uniCube = newCube;
+    }
+  }
+  fsm->extQuantifyInputCube = extCube;
+  fsm->uniQuantifyInputCube = uniCube;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Read input variables that is controlled by environment
+            in the FSM structure.]
+
+  Description [This is function for FateAndFreeWill counterexample generation.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bdd_t *
+Fsm_FsmReadExtQuantifyInputCube(Fsm_Fsm_t *fsm)
+{
+  return(fsm->extQuantifyInputCube);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Read input variables that is controlled by system
+            in the FSM structure.]
+
+  Description [This is function for FateAndFreeWill counterexample generation.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bdd_t *
+Fsm_FsmReadUniQuantifyInputCube(Fsm_Fsm_t *fsm)
+{
+  return(fsm->uniQuantifyInputCube);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the current FSM of a hierarchy manager.]
+
+  Description [Returns the FSM of the network of the current node of a
+  hierarchy manager. If the 1) hmgr is NULL, 2) current node is NULL, 3)
+  network is NULL, 4) the variables of the network have not been ordered, 5) a
+  partition doesn't exist for the network, or 6) the network does not have any
+  latches, then a message is printed to vis_stderr, and NULL is returned.  If
+  all the above conditions have been satisfied, and the network doesn't
+  already have an FSM, then one is created.]
+
+  SideEffects []
+
+  SeeAlso     [Hrc_ManagerReadCurrentNode Ntk_HrcManagerReadCurrentNetwork
+  Fsm_NetworkReadOrCreateFsm]
+
+******************************************************************************/
+Fsm_Fsm_t *
+Fsm_HrcManagerReadCurrentFsm(Hrc_Manager_t *hmgr)
+{
+  Fsm_Fsm_t     *fsm;
+  Ntk_Network_t *network = Ntk_HrcManagerReadCurrentNetwork(hmgr);
+  
+  if (network == NIL(Ntk_Network_t)) {
+    return NIL(Fsm_Fsm_t);
+  }
+
+  if (Ord_NetworkTestAreVariablesOrdered(network, Ord_InputAndLatch_c) == FALSE) {
+    (void) fprintf(vis_stderr, "** fsm error: The MDD variables have not been ordered.  ");
+    (void) fprintf(vis_stderr, "Use static_order.\n");
+    return NIL(Fsm_Fsm_t);
+  }
+
+  if (Part_NetworkReadPartition(network) == NIL(graph_t)){
+    (void) fprintf(vis_stderr, "** fsm error: Network has not been partitioned.  ");
+    (void) fprintf(vis_stderr, "Use build_partition_mdds.\n");
+    return NIL(Fsm_Fsm_t);
+  }
+
+  error_init();
+  fsm = Fsm_NetworkReadOrCreateFsm(network);
+  if (fsm == NIL(Fsm_Fsm_t)) {
+    (void) fprintf(vis_stderr, "%s", error_string());
+    (void) fprintf(vis_stderr, "\n");
+  }
+  
+  return fsm;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a subFSM from a network.]
+
+  Description [Given a vertex table, the routine creates a subFSM. The routine
+  reads in the vertex table  and stores only corresponding next state functions 
+  into the subFSM. Every present, next state and input variables in the system
+  are stored into the subFSM.
+  ]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmCreateFromNetworkWithPartition, Fsm_FsmFree]
+
+******************************************************************************/
+Fsm_Fsm_t *
+Fsm_FsmCreateSubsystemFromNetwork(
+  Ntk_Network_t *network,
+  graph_t	*partition,
+  st_table	*vertexTable,
+  boolean	independentFlag,
+  int		createPseudoVarMode)
+{
+  lsGen       gen;
+  Ntk_Node_t *latch;
+  Ntk_Node_t *input;
+  Fsm_Fsm_t  *fsm;
+  char *latchName;
+  int i;
+  st_table *pseudoMddIdTable = NIL(st_table);
+
+  fsm = FsmStructAlloc(network, partition);
+  if (fsm == NIL(Fsm_Fsm_t)) return NIL(Fsm_Fsm_t);
+  fsm->fairnessInfo.constraint = FsmFsmCreateDefaultFairnessConstraint(fsm);
+
+  /*
+   * Creates an FSM for the subsystem.
+   */
+  /* sort latches by name. */
+  Ntk_NetworkForEachLatch(network, gen, latch) {
+    latchName = Ntk_NodeReadName(latch); 
+    if(st_lookup(vertexTable, latchName, (char **)0)) {
+      array_insert_last(char*, fsm->fsmData.nextStateFunctions, latchName);
+    } /* end of if(st_lookup(vertexTable)) */
+  }
+
+  if (independentFlag && createPseudoVarMode) {
+    fsm->fsmData.pseudoInputVars = array_alloc(int, 0);
+    fsm->fsmData.primaryInputVars = array_alloc(int, 0);
+    fsm->fsmData.globalPsVars = array_alloc(int, 0);
+    if (createPseudoVarMode == 2)
+      pseudoMddIdTable = st_init_table(st_numcmp, st_numhash);
+  }
+
+  array_sort(fsm->fsmData.nextStateFunctions, nameCompare);
+  
+  arrayForEachItem(char *, fsm->fsmData.nextStateFunctions, i, latchName) {
+    latch = Ntk_NetworkFindNodeByName(network, latchName); 
+    array_insert(char*, fsm->fsmData.nextStateFunctions, i,
+		 Ntk_NodeReadName(Ntk_LatchReadDataInput(latch)));
+    array_insert_last(int, fsm->fsmData.nextStateVars,
+		      Ntk_NodeReadMddId(Ntk_NodeReadShadow(latch)));
+    array_insert_last(int, fsm->fsmData.presentStateVars,
+		      Ntk_NodeReadMddId(latch));
+  } /* end of Ntk_NetworkForEachLatch(network, gen, latch) */
+
+  /* Fill in remaining latch for nextStateVars */
+  if (!independentFlag || createPseudoVarMode) {
+    Ntk_NetworkForEachLatch(network, gen, latch) {
+      char *latchName = Ntk_NodeReadName(latch); 
+      if(!st_lookup(vertexTable, latchName, (char **)0)) {
+	if (independentFlag) {
+	  if (createPseudoVarMode == 1) {
+	    array_insert_last(int, fsm->fsmData.pseudoInputVars,
+				Ntk_NodeReadMddId(latch));
+	    array_insert_last(int, fsm->fsmData.inputVars,
+				Ntk_NodeReadMddId(latch));
+	  } else {
+	    st_insert(pseudoMddIdTable, (char *)(long)Ntk_NodeReadMddId(latch),
+			NIL(char));
+	  }
+	} else {
+	  array_insert_last(int, fsm->fsmData.nextStateVars, 
+			    Ntk_NodeReadMddId(Ntk_NodeReadShadow(latch)));
+	  array_insert_last(int, fsm->fsmData.presentStateVars,
+			    Ntk_NodeReadMddId(latch));
+	}
+      }
+    }
+  }
+
+  /* Input variables are identical for every subsystems */
+  Ntk_NetworkForEachInput(network, gen, input){
+    array_insert_last(int, fsm->fsmData.inputVars, Ntk_NodeReadMddId(input));
+    if (independentFlag && createPseudoVarMode) {
+      array_insert_last(int, fsm->fsmData.primaryInputVars,
+			Ntk_NodeReadMddId(input));
+    }
+  }
+
+  if (independentFlag && createPseudoVarMode) {
+    if (createPseudoVarMode == 2) {
+      int	mddId;
+      array_t	*supportMddIdArray;
+      st_table	*mddIdTable;
+
+      mddIdTable = st_init_table(st_numcmp, st_numhash);
+      arrayForEachItem(int, fsm->fsmData.presentStateVars, i, mddId) {
+	st_insert(mddIdTable, (char *)(long)mddId, NIL(char));
+      }
+      arrayForEachItem(int, fsm->fsmData.inputVars, i, mddId) {
+	st_insert(mddIdTable, (char *)(long)mddId, NIL(char));
+      }
+
+      supportMddIdArray = GetMddSupportIdArray(fsm, mddIdTable,
+						pseudoMddIdTable);
+
+      arrayForEachItem(int, supportMddIdArray, i, mddId) {
+	if (!st_lookup(mddIdTable, (char *)(long)mddId, NIL(char *))) {
+	  array_insert_last(int, fsm->fsmData.pseudoInputVars, mddId);
+	  array_insert_last(int, fsm->fsmData.inputVars, mddId);
+	}
+      }
+      st_free_table(mddIdTable);
+      st_free_table(pseudoMddIdTable);
+      array_free(supportMddIdArray);
+    }
+
+    array_append(fsm->fsmData.globalPsVars, fsm->fsmData.presentStateVars);
+    array_append(fsm->fsmData.globalPsVars, fsm->fsmData.pseudoInputVars);
+  }
+
+  FsmCreateVariableCubes(fsm);
+  fsm->fsmData.presentStateBddVars = mdd_id_array_to_bdd_array(
+    Fsm_FsmReadMddManager(fsm), fsm->fsmData.presentStateVars);
+  return (fsm);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Instantiate a given hint]
+
+  Description [Instantiate a given hint. The fwd and bwd flags
+  indicate whether the fwd transition relation or the backward
+  transition relation is created. A non-zero value will cause the hint
+  to be instantiated in that direction.  The type flag indicates
+  whether the hint should be applied as an overapproximation or an
+  underapproximation.
+
+  After minimization wrt the hint is done, the TR is minimized wrt the
+  conjunction of the care states in careStatesArray (an array of mdd_t *),
+  unless this array is NULL, in which case it is ignored.]
+
+  SideEffects []
+
+  SeeAlso [Fsm_CleanUpHints]
+
+******************************************************************************/
+void
+Fsm_InstantiateHint(
+  Fsm_Fsm_t *fsm,
+  mdd_t *hint,
+  int fwdFlag,
+  int bwdFlag,
+  Ctlp_Approx_t type,
+  int printStatus)
+{
+  boolean underApprox = FALSE;
+  Img_DirectionType imgFlag = Img_Forward_c;
+
+  assert(type != Ctlp_Incomparable_c);
+  
+  if (bwdFlag && fwdFlag)
+    imgFlag = Img_Both_c;
+  else if (bwdFlag)
+    imgFlag = Img_Backward_c;
+
+  switch (type) {
+  case (Ctlp_Underapprox_c): underApprox = TRUE; break;
+  case (Ctlp_Overapprox_c): underApprox = FALSE; break;
+  case (Ctlp_Exact_c):
+    underApprox = TRUE;
+    hint = mdd_one(Fsm_FsmReadMddManager(fsm));
+    break;
+  default: assert(0); break;
+  }
+  /* If we reach this point, underApprox has been explicitly assigned
+   * by the switch. */
+  
+  Img_ImageConstrainAndClusterTransitionRelation(
+    Fsm_FsmReadOrCreateImageInfo(fsm, bwdFlag, fwdFlag),
+    imgFlag,
+    hint,
+    ((underApprox == TRUE) ?
+     Img_GuidedSearchReadUnderApproxMinimizeMethod() :
+     Img_GuidedSearchReadOverApproxMinimizeMethod()),
+    underApprox, /* underapprox */
+    0, /* dont clean up */
+    0, /* no variable reordering */
+    printStatus);
+
+  Fsm_MinimizeTransitionRelationWithReachabilityInfo(fsm, imgFlag,
+						     printStatus); 
+  
+  if (type == Ctlp_Exact_c) mdd_free(hint);
+
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Clean up after hints]
+
+  Description [Clean up after hints.]
+
+  SideEffects []
+
+  SeeAlso [Fsm_InstantiateHint]
+  
+******************************************************************************/
+void
+Fsm_CleanUpHints( Fsm_Fsm_t *fsm, int fwdFlag, int bwdFlag, int printStatus)
+{
+  Img_DirectionType	imgFlag = Img_Forward_c;
+  mdd_t *one = bdd_one(Fsm_FsmReadMddManager(fsm));
+  if (bwdFlag && fwdFlag)
+    imgFlag = Img_Both_c;
+  else if (bwdFlag)
+    imgFlag = Img_Backward_c;
+
+  Img_ImageConstrainAndClusterTransitionRelation(fsm->imageInfo,
+						 imgFlag,
+						 one,
+						 Img_GuidedSearchReadUnderApproxMinimizeMethod(),
+						 1, /* under approx */
+						 1, /* clean up */
+						 0, /* no variable reordering */
+						 printStatus);
+  mdd_free(one);
+  return;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the reachable states of an FSM.]
+
+  Description [Frees the reachable states of an FSM.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmFree, Fsm_FsmFreeOverApproximateReachableStates]
+
+******************************************************************************/
+void
+Fsm_FsmFreeReachableStates(Fsm_Fsm_t *fsm)
+{
+  if (fsm->reachabilityInfo.reachableStates) {
+    mdd_free(fsm->reachabilityInfo.reachableStates);
+    fsm->reachabilityInfo.reachableStates = NIL(mdd_t);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the approximate reachable states of an FSM.]
+
+  Description [Frees the approximate reachable states of an FSM.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmFree, Fsm_FsmFreeReachableStates]
+
+******************************************************************************/
+void
+Fsm_FsmFreeOverApproximateReachableStates(Fsm_Fsm_t *fsm)
+{
+  if (fsm->reachabilityInfo.apprReachableStates) {
+    mdd_array_free(fsm->reachabilityInfo.apprReachableStates);
+    fsm->reachabilityInfo.apprReachableStates = NIL(array_t);
+    fsm->reachabilityInfo.overApprox = Fsm_Ardc_NotConverged_c;
+  }
+  if (fsm->reachabilityInfo.subPsVars) {
+    int i;
+    array_t *psVars;
+
+    for (i = 0; i < array_n(fsm->reachabilityInfo.subPsVars); i++) {
+      psVars = array_fetch(array_t *, fsm->reachabilityInfo.subPsVars, i);
+      array_free(psVars);
+    }
+    array_free(fsm->reachabilityInfo.subPsVars);
+    fsm->reachabilityInfo.subPsVars = NIL(array_t);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the reachable depth of an FSM.]
+
+  Description [Returns the reachable depth of an FSM.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Fsm_FsmGetReachableDepth(Fsm_Fsm_t *fsm)
+{
+    return(fsm->reachabilityInfo.depth);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Checks if the 2 given fsms are the same, given that they
+  are from the same total fsm. ]
+
+  Description [Checks if the 2 given fsms are the same, given that
+  they are from the same total fsm. Compares present, next state,
+  input, real present state and abstract variables. Also compares the
+  next state function NAMES ONLY. Since the 2 fsms are guaranteed to
+  be parts of te same total fsm and they share the same network, the
+  mdds of next state function nodes with the same name are guaranteed
+  to be the same. ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+Fsm_FsmCheckSameSubFsmInTotalFsm(Fsm_Fsm_t *fsm,
+				 Fsm_Fsm_t *subFsm1,
+				 Fsm_Fsm_t *subFsm2)
+{
+  mdd_manager *mddMgr = Fsm_FsmReadMddManager(fsm);
+  boolean result;
+  
+  assert(Fsm_FsmReadNetwork(fsm) == Fsm_FsmReadNetwork(subFsm1));
+  assert(Fsm_FsmReadNetwork(fsm) == Fsm_FsmReadNetwork(subFsm2));
+  assert(Fsm_FsmReadMddManager(subFsm1) == mddMgr);
+  assert(Fsm_FsmReadMddManager(subFsm2) == mddMgr);
+
+  /* compare present state variables */
+  result = VarIdArrayCompare(mddMgr,
+			     Fsm_FsmReadPresentStateVars(subFsm1),
+			     Fsm_FsmReadPresentStateVars(subFsm2));
+  if (!result) return FALSE;
+
+  /* compare next state variables */
+  result = VarIdArrayCompare(mddMgr,
+			     Fsm_FsmReadNextStateVars(subFsm1),
+			     Fsm_FsmReadNextStateVars(subFsm2));
+  if (!result) return FALSE;
+
+  /* compare input variables */
+  result = VarIdArrayCompare(mddMgr,
+			     Fsm_FsmReadInputVars(subFsm1),
+			     Fsm_FsmReadInputVars(subFsm2));
+  if (!result) return FALSE;
+
+  /* compare the pseudo input variables */
+  result = VarIdArrayCompare(mddMgr,
+			     Fsm_FsmReadPseudoInputVars(subFsm1),
+			     Fsm_FsmReadPseudoInputVars(subFsm2));
+  if (!result) return FALSE;
+
+  /* compare next state functions */
+  result = NSFunctionNamesCompare(mddMgr,
+				  Fsm_FsmReadNextStateFunctionNames(subFsm1),
+				  Fsm_FsmReadNextStateFunctionNames(subFsm2));
+  if (!result) return FALSE;
+
+  return TRUE;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns whether reachability analysis was an approximation or 
+  exact.]
+
+  Description [Returns whether reachability analysis was an approximation or
+  exact.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Fsm_RchStatus_t
+Fsm_FsmReadReachabilityApproxComputationStatus(Fsm_Fsm_t *fsm)
+{
+  return fsm->reachabilityInfo.rchStatus;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Minimize the transition relation wrt either ARDCs or exact
+  reachability information]
+
+  Description [Prefers exact rdcs when available, if neither exact nor
+  approximate rdcs are availablem, the TR is not touched.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Fsm_MinimizeTransitionRelationWithReachabilityInfo(
+  Fsm_Fsm_t *fsm,
+  Img_DirectionType fwdbwd,
+  boolean verbosity)
+{
+  Img_ImageInfo_t *imageInfo;
+  array_t *minimizeArray = NIL(array_t);
+  boolean fwd            = FALSE;
+  boolean bwd            = FALSE;
+  int     oldVerbosity;
+  Fsm_RchStatus_t status;
+  boolean  freeArray;
+  mdd_t *exactrdc;
+  
+  switch (fwdbwd) {
+  case Img_Forward_c:
+    fwd = 1;
+    break;
+  case Img_Backward_c:
+    bwd = 1;
+    break;
+  case Img_Both_c:
+    fwd = 1;
+    bwd= 1;
+    break;
+  default:
+    assert(0);
+    break;
+  }
+  
+  imageInfo = Fsm_FsmReadOrCreateImageInfo(fsm, bwd, fwd);
+  oldVerbosity = Img_ReadPrintMinimizeStatus(imageInfo);
+  
+  status = Fsm_FsmReadReachabilityApproxComputationStatus(fsm);
+  exactrdc = Fsm_FsmReadCurrentReachableStates(fsm);
+  
+  if((status == Fsm_Rch_Exact_c || status == Fsm_Rch_Over_c) &&
+     exactrdc != NIL(mdd_t) ){
+    freeArray = TRUE;
+    minimizeArray = array_alloc(mdd_t *, 1);
+    array_insert_last(mdd_t *, minimizeArray, mdd_dup(exactrdc)); 
+  }else{
+    freeArray = FALSE;
+    minimizeArray = Fsm_FsmReadCurrentOverApproximateReachableStates(fsm);
+    if(minimizeArray == NIL(array_t))
+      return;
+  }
+
+  if(verbosity)
+    Img_SetPrintMinimizeStatus(imageInfo, 1);
+
+  /* We never reorder the clusters of the iwls structure.  It is probably
+     better to reorder them, but as this is written, there is no time to
+     evaluate the effect of reordering. */
+    Img_MinimizeTransitionRelation(imageInfo, minimizeArray,
+				 Img_DefaultMinimizeMethod_c, fwdbwd, FALSE);
+  
+  if(verbosity)
+    Img_SetPrintMinimizeStatus(imageInfo, oldVerbosity);
+
+  if(freeArray)
+    mdd_array_free(minimizeArray);
+
+  return;
+}
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Sets array of onion rings from reachability computation]
+
+  Description [Sets array of onion rings from reachability
+  computation.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmReadReachabilityOnionRings]
+
+******************************************************************************/
+void
+FsmSetReachabilityOnionRings(
+  Fsm_Fsm_t *fsm, array_t *onionRings)
+{
+  fsm->reachabilityInfo.onionRings = onionRings;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Sets whether  onion rings are due to BFS.]
+
+  Description [Sets whether onion rings are due to BFS.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmReadReachabilityOnionRingsMode]
+
+******************************************************************************/
+void
+FsmSetReachabilityOnionRingsMode(
+  Fsm_Fsm_t *fsm, Fsm_RchType_t value)
+{
+  fsm->reachabilityInfo.onionRingsMode = value;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Sets whether  onion rings are up to date.]
+
+  Description [Sets whether  onion rings are up to date.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmReachabilityOnionRingsUpToDate]
+
+******************************************************************************/
+void
+FsmSetReachabilityOnionRingsUpToDateFlag(
+  Fsm_Fsm_t *fsm,  boolean value)
+{
+  fsm->reachabilityInfo.onionRingsUpToDate = value;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Sets whether reachability analysis was an approximation.]
+
+  Description [Sets whether reachability analysis was an approximation.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+FsmSetReachabilityApproxComputationStatus(
+  Fsm_Fsm_t *fsm,  Fsm_RchStatus_t value)
+{
+  fsm->reachabilityInfo.rchStatus = value;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the status of overapproxiate reachable computation.]
+
+  Description [Sets the status of overapproxiate reachable computation.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+FsmSetReachabilityOverApproxComputationStatus(
+  Fsm_Fsm_t *fsm,  Fsm_Ardc_StatusType_t status)
+{
+  fsm->reachabilityInfo.overApprox = status;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the status of overapproxiate reachable computation.]
+
+  Description [Reads the status of overapproxiate reachable computation.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Fsm_Ardc_StatusType_t
+FsmReadReachabilityOverApproxComputationStatus(Fsm_Fsm_t *fsm)
+{
+  return(fsm->reachabilityInfo.overApprox);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Sets the mode field to indicate whether computation has
+  always been BFS.]
+
+  Description [Sets the mode field to indicate whether computation has
+  always been BFS.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+FsmSetReachabilityComputationMode(
+  Fsm_Fsm_t *fsm,  Fsm_RchType_t value)
+{
+  fsm->reachabilityInfo.reachabilityMode = value;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Reads the mode field to indicate whether computation has
+  always been BFS.]
+
+  Description [Reads the mode field to indicate whether computation has
+  always been BFS.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Fsm_RchType_t
+FsmReadReachabilityComputationMode(
+  Fsm_Fsm_t *fsm)
+{
+  return fsm->reachabilityInfo.reachabilityMode;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Reset fsm fields]
+
+  Description [Reset fsm fields. Free reachable states, onion rings.
+  Reset the onion ring up-to-date flag, onion rings BFS, depth and
+  under approximation flag.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+FsmResetReachabilityFields(Fsm_Fsm_t *fsm, Fsm_RchType_t approxFlag)
+{
+  int i;
+  mdd_t *reachableStates;
+  /* free reachable states if it is necessary to recompute anyway. */
+  if (approxFlag != Fsm_Rch_Oa_c) {
+    if (Fsm_FsmReadCurrentReachableStates(fsm)) {
+      Fsm_FsmFreeReachableStates(fsm);
+    }
+  } else if (Fsm_FsmReadCurrentOverApproximateReachableStates(fsm)) {
+    Fsm_FsmFreeOverApproximateReachableStates(fsm);
+  }
+	
+  /* free onion rings */
+  if (Fsm_FsmReadReachabilityOnionRings(fsm) != NIL(array_t)) {
+    arrayForEachItem(mdd_t *, Fsm_FsmReadReachabilityOnionRings(fsm), i,
+	reachableStates) {
+      mdd_free(reachableStates);
+    }
+    array_free(Fsm_FsmReadReachabilityOnionRings(fsm));
+    FsmSetReachabilityOnionRings(fsm, NIL(array_t));
+  }
+  fsm->reachabilityInfo.depth = 0;
+  FsmSetReachabilityComputationMode(fsm, Fsm_Rch_Default_c);
+  FsmSetReachabilityApproxComputationStatus(fsm, Fsm_Rch_Under_c);
+  FsmSetReachabilityOnionRingsUpToDateFlag(fsm, FALSE);
+  FsmSetReachabilityOnionRingsMode(fsm, Fsm_Rch_Default_c);
+  return;
+} /* end of FsmResetReachabilityFields */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Allocates HD Info structure.]
+
+  Description [Allocates HD Info structure.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmHdStructFree]
+
+******************************************************************************/
+FsmHdStruct_t *
+FsmHdStructAlloc(int nvars)
+{
+  FsmHdStruct_t *hdInfo = ALLOC(FsmHdStruct_t, 1);
+  if (hdInfo == NIL(FsmHdStruct_t)) return hdInfo;
+  hdInfo->numDeadEnds = 0;
+  hdInfo->firstSubset = TRUE;
+  hdInfo->lastIter = -1;
+  hdInfo->partialImage = FALSE;
+  hdInfo->residueCount = 0;
+  hdInfo->interiorStates = NIL(mdd_t);
+  hdInfo->interiorStateCandidate = NIL(mdd_t);
+  hdInfo->deadEndResidue = NIL(mdd_t);
+  hdInfo->options = Fsm_FsmHdGetTravOptions(nvars);
+  hdInfo->stats = FsmHdStatsStructAlloc();
+  hdInfo->imageOfReachedComputed = FALSE;
+  hdInfo->onlyPartialImage = FALSE;
+  hdInfo->slowGrowth = 0;
+  hdInfo->deadEndWithOriginalTR = FALSE;
+  hdInfo->deadEndComputation = FALSE;
+  return hdInfo;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees HD info struct.]
+
+  Description [Frees HD info struct.]
+
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmHdStructAllocate]
+
+******************************************************************************/
+void
+FsmHdStructFree(FsmHdStruct_t *hdInfo)
+{
+  if (hdInfo->interiorStates != NULL) mdd_free(hdInfo->interiorStates);
+  if (hdInfo->interiorStateCandidate != NULL)
+    mdd_free(hdInfo->interiorStateCandidate);
+  if (hdInfo->deadEndResidue != NULL) mdd_free(hdInfo->deadEndResidue);
+  
+  FsmHdStatsStructFree(hdInfo->stats);
+  Fsm_FsmHdFreeTravOptions(hdInfo->options);
+  FREE(hdInfo);
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Prints all options that are related to guided search.]
+
+  Description [Prints all options that are related to guided search.]
+
+  SideEffects []
+
+  SeeAlso     [CommandGuidedSearchOptions]
+
+******************************************************************************/
+void
+FsmGuidedSearchPrintOptions(void)
+{
+  char *string =  Cmd_FlagReadByName("guided_search_hint_type");
+  if (string == NIL(char)) string = "local";
+  fprintf(vis_stdout, "Flag guided_search_hint_type is set to %s.\n", string);
+  string = Cmd_FlagReadByName("guided_search_underapprox_minimize_method");
+  if (string == NIL(char)) string = "and";
+  fprintf(vis_stdout, "Flag guided_search_underapprox_minimize_method is set to %s.\n", string);
+  string = Cmd_FlagReadByName("guided_search_overapprox_minimize_method");
+  if (string == NIL(char)) string = "ornot";
+  fprintf(vis_stdout, "Flag guided_search_overapprox_minimize_method is set to %s.\n", string);
+  string = Cmd_FlagReadByName("guided_search_sequence");
+  if (string == NIL(char)) string = "all hints to convergence";
+  fprintf(vis_stdout, "Flag guided_search_overapprox_minimize_method is set to %s.\n", string);
+  return;
+}
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Allocates structure]
+
+  Description [Allocates structure]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static Fsm_Fsm_t *
+FsmStructAlloc(Ntk_Network_t *network,
+	    graph_t	*partition)
+{
+  Fsm_Fsm_t *fsm;
+  if (Ntk_NetworkReadNumLatches(network) == 0) {
+    error_append("Network has no latches. Cannot create FSM.");
+    return (NIL(Fsm_Fsm_t));
+  }
+  
+  fsm = ALLOC(Fsm_Fsm_t, 1);
+  if (fsm == NIL(Fsm_Fsm_t)) return NIL(Fsm_Fsm_t);
+  memset(fsm, 0, sizeof(Fsm_Fsm_t));
+
+  fsm->network = network;
+
+  if (partition == NIL(graph_t)) {
+    partition = Part_NetworkReadPartition(network);
+
+    if (partition == NIL(graph_t)) {
+      error_append("Network has no partition. Cannot create FSM.");
+      return (NIL(Fsm_Fsm_t));
+    } else {
+      fsm->partition = Part_PartitionDuplicate(partition);
+    }
+  } else {
+    fsm->partition = partition;
+  }
+  
+  FsmSetReachabilityOnionRings(fsm, NIL(array_t));
+  FsmSetReachabilityOnionRingsUpToDateFlag(fsm, FALSE);
+  FsmSetReachabilityOnionRingsMode(fsm, Fsm_Rch_Default_c);
+  FsmSetReachabilityApproxComputationStatus(fsm, Fsm_Rch_Under_c);
+  FsmSetReachabilityComputationMode(fsm, Fsm_Rch_Default_c);
+  FsmSetReachabilityOverApproxComputationStatus(fsm, Fsm_Ardc_NotConverged_c);
+
+  fsm->fsmData.presentStateVars   = array_alloc(int, 0);
+  fsm->fsmData.nextStateVars      = array_alloc(int, 0);
+  fsm->fsmData.inputVars          = array_alloc(int, 0);
+  fsm->fsmData.nextStateFunctions = array_alloc(char *, 0);
+
+  return (fsm);
+} /* end of FsmStructAlloc */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates structure]
+
+  Description [Allocates structure]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+FsmCreateVariableCubes(Fsm_Fsm_t *fsm)
+{
+  mdd_manager *manager = Fsm_FsmReadMddManager(fsm);
+  char *flagValue;
+  boolean createVariableCubesFlag = TRUE;
+
+  if (bdd_get_package_name() != CUDD)
+    return;
+
+  flagValue = Cmd_FlagReadByName("fsm_create_var_cubes");
+  if (flagValue != NIL(char)) {
+    if (strcmp(flagValue, "yes") == 0)
+      createVariableCubesFlag = TRUE;
+    else if (strcmp(flagValue, "no") == 0)
+      createVariableCubesFlag = FALSE;
+    else {
+      fprintf(vis_stderr,
+	"** ardc error : invalid value %s for create_var_cubes[yes/no]. **\n",
+	flagValue);
+    }
+  }
+
+  if (!createVariableCubesFlag)
+    return;
+
+  fsm->fsmData.createVarCubesFlag = TRUE;
+  fsm->fsmData.presentStateCube =
+	mdd_id_array_to_bdd_cube(manager, fsm->fsmData.presentStateVars);
+  fsm->fsmData.nextStateCube =
+	mdd_id_array_to_bdd_cube(manager, fsm->fsmData.nextStateVars);
+  fsm->fsmData.inputCube =
+	mdd_id_array_to_bdd_cube(manager, fsm->fsmData.inputVars);
+  if (fsm->fsmData.pseudoInputVars) {
+    fsm->fsmData.pseudoInputCube =
+	mdd_id_array_to_bdd_cube(manager, fsm->fsmData.pseudoInputVars);
+  }
+  if (fsm->fsmData.primaryInputVars) {
+    fsm->fsmData.primaryInputCube =
+	mdd_id_array_to_bdd_cube(manager, fsm->fsmData.primaryInputVars);
+  }
+  if (fsm->fsmData.globalPsVars) {
+    fsm->fsmData.globalPsCube =
+	mdd_id_array_to_bdd_cube(manager, fsm->fsmData.globalPsVars);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compare procedure for name comparison.]
+
+  Description [Compare procedure for name comparison.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+nameCompare(
+  const void * name1,
+  const void * name2)
+{
+    return(strcmp(*(char **)name1, *(char **)name2));
+
+} /* end of signatureCompare */
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Checks that 2 arrays of variables ids are the same.]
+
+  Description [ Checks that 2 arrays of variables ids are the same by
+  computing the bdd of the cube.]
+ 
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmCheckSameSubFsmInTotalFsm]
+
+******************************************************************************/
+static boolean
+VarIdArrayCompare(mdd_manager *mddMgr,
+		  array_t *vars1,
+		  array_t *vars2)
+{
+  
+  mdd_t *cube1, *cube2;
+  boolean result = FALSE;
+  cube1 = bdd_compute_cube(mddMgr, vars1);
+  cube2 = bdd_compute_cube(mddMgr, vars2);
+  if ((cube1 == NIL(mdd_t)) || (cube2 == NIL(mdd_t))) {
+    result = (cube1 == cube2) ? TRUE : FALSE;
+  } else {
+    result =  bdd_equal(cube1, cube2) ? TRUE : FALSE;
+  }
+  if (cube1 != NIL(bdd_t)) bdd_free(cube1);
+  if (cube2 != NIL(bdd_t)) bdd_free(cube2);
+  return result;
+} /* end of VarIdArrayCompare */
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Checks that 2 arrays of variables ids are the same.]
+
+  Description [ Checks that 2 arrays of variables ids are the same by
+  computing the bdd of the cube.]
+ 
+  SideEffects []
+
+  SeeAlso     [Fsm_FsmCheckSameSubFsmInTotalFsm]
+
+******************************************************************************/
+static boolean
+NSFunctionNamesCompare(mdd_manager *mddMgr,
+		       array_t *names1,
+		       array_t *names2)
+{
+  int sizeArray = array_n(names1);
+  int i, count;
+  char *name;
+  st_table *nameTable = st_init_table(strcmp, st_strhash);
+
+  if (sizeArray != array_n(names2)) return FALSE;
+  /* check if elements in names2 is in names1 */
+  arrayForEachItem(char *, names1, i, name) {
+    if (st_lookup_int(nameTable, name, &count)) {
+      count++;
+    } else {
+      count = 1;
+    }
+    st_insert(nameTable, name, (char *)(long)count);
+  }
+  
+  arrayForEachItem(char *, names2, i, name) {
+    if (!st_lookup_int(nameTable, name, &count)) {
+      st_free_table(nameTable);
+      return FALSE;
+    } else if (count == 0) { 
+      st_free_table(nameTable);
+      return FALSE;
+    } else {
+      count--;
+      st_insert(nameTable, name, (char *)(long)count);   
+    }
+  }
+  st_free_table(nameTable);
+
+  /* check if elements in names1 is in names2 */
+  nameTable = st_init_table(strcmp, st_strhash);
+  arrayForEachItem(char *, names2, i, name) {
+    if (st_lookup_int(nameTable, name, &count)) {
+      count++;
+    } else {
+      count = 1;
+    }
+    st_insert(nameTable, name, (char *)(long)count);
+  }
+  
+  arrayForEachItem(char *, names1, i, name) {
+    if (!st_lookup_int(nameTable, name, &count)) {
+      st_free_table(nameTable);
+      return FALSE;
+    } else if (count == 0) { 
+      st_free_table(nameTable);
+      return FALSE;
+    } else {
+      count--;
+      st_insert(nameTable, name, (char *)(long)count);   
+    }
+  }
+  st_free_table(nameTable);
+  return TRUE;
+} /* end of NSFunctionNamesCompare */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns an array of mdd Ids of an FSM.]
+
+  Description [Returns an array of mdd Ids of an FSM.]
+ 
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static array_t *
+GetMddSupportIdArray(Fsm_Fsm_t *fsm, st_table *mddIdTable,
+		     st_table *pseudoMddIdTable)
+{
+  mdd_t			*func;
+  char			*nodeName;
+  vertex_t		*vertex;
+  Mvf_Function_t	*mvf;
+  int			i, j, k;
+  long                  mddId;
+  array_t		*varBddFunctionArray;
+  mdd_manager		*mddManager;
+  array_t		*supportMddIdArray, *support;
+  st_table		*supportMddIdTable;
+  st_generator		*stGen;
+
+  supportMddIdTable = st_init_table(st_numcmp, st_numhash);
+  mddManager = Part_PartitionReadMddManager(fsm->partition);
+
+  for (i = 0; i < array_n(fsm->fsmData.nextStateFunctions); i++) {
+    nodeName = array_fetch(char*, fsm->fsmData.nextStateFunctions, i);
+    vertex = Part_PartitionFindVertexByName(fsm->partition, nodeName);
+    mvf = Part_VertexReadFunction(vertex);
+    mddId = (long) array_fetch(int, fsm->fsmData.nextStateVars, i);
+    varBddFunctionArray = mdd_fn_array_to_bdd_fn_array(mddManager,
+						       (int) mddId, mvf);
+
+    for (j = 0; j < array_n(varBddFunctionArray); j++) {
+      func = array_fetch(mdd_t *, varBddFunctionArray, j);
+      support = mdd_get_support(mddManager, func);
+      arrayForEachItem(int, support, k, mddId) {
+	if (!st_lookup(supportMddIdTable, (char *)mddId, NIL(char *))) {
+	  if (st_lookup(mddIdTable, (char *)mddId, NIL(char *)) ||
+	      st_lookup(pseudoMddIdTable, (char *)mddId, NIL(char *))) {
+	    st_insert(supportMddIdTable, (char *)mddId, NIL(char));
+	  } else { /* intermediate variables */
+	    /* NEEDS to get the supports of an intermediate variable */
+	    assert(0);
+	  }
+	}
+      }
+    }
+    array_free(varBddFunctionArray);
+  }
+
+  supportMddIdArray = array_alloc(int, 0);
+  st_foreach_item(supportMddIdTable, stGen, &mddId, NIL(char *)) {
+    array_insert_last(int, supportMddIdArray, (int) mddId);
+  }
+
+  return(supportMddIdArray);
+}
+
+
Index: vis_dev/vis-2.3/src/fsm/fsmHD.c
===================================================================
--- vis_dev/vis-2.3/src/fsm/fsmHD.c	(revision 14)
+++ vis_dev/vis-2.3/src/fsm/fsmHD.c	(revision 14)
@@ -0,0 +1,2101 @@
+/**CFile***********************************************************************
+
+  FileName    [fsmHD.c]
+
+  PackageName [fsm]
+
+  Synopsis [Routines to perform high density reachability on the FSM
+  structure.]
+
+  Description [Routines to perform high density reachability on the
+  FSM structure. The main quantities in HD reachability analysis are:
+  MDDs:
+  0. initial states: initial states of the machine. 
+  1. reachableStates
+  2. fromLowerBound : lower bound of states fed to
+  the next image computation.]
+  3. fromUpperBound: In HD, this is set to the fromLowerBound.
+  4. image: image computed in each iteration.
+  5. interiorStates: set of states that have no new successors.
+  6. deadEndResidue: We refer to residue as those states which have
+  been discarded for image computation in computing an approximation
+  of the frontier set. deadEndResidue is the residue right after a
+  dead-end. It is also the residue of the first approximation
+  performed in the traversal.
+   
+  FLAGS and COUNTS:
+  0. deadEndComputation: Indicates that this is a dead-end.
+  1. residueCount: number of times residues have been returned from a
+  dead-end. After 4 times it is freed.
+  2. fromOrDeadEnd: Indicates which type of approximation is
+  permissible. If from, then the specified method is used, if dead-end
+  remap_ua is always used. Default is remap_ua.
+  3. fronierApproxThreshold: Size of approximation of the frontier set.
+  4. nvars: Number of present state variables.
+  5. failedPartition: decomposition of reached in dead-ends failed.
+  6. reachedSize: size of reachableStates
+  7. greedy: whether dead-end computation is greedy (stop when new states
+  are found. ) or not (compute the image of the entire reached set).
+  8. firstSubset: whether the first approximation has been performed
+  or not. 
+
+  Other structures:
+  0. imageInfo: required for transition relation.
+  1. varArray: present state var array.
+  2. options: HD options.
+  3. stats: holds information about minterms and size of the various
+  mdds involved.
+  
+  
+  These quantities are modified as necessary at each step of the HD
+  manipulation. The same names are used throughout this file.]
+  
+  Author      [Kavita Ravi]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "fsmInt.h"
+#include "bdd.h"
+#include "ntm.h"
+#include "img.h"
+
+static char rcsid[] UNUSED = "$Id: fsmHD.c,v 1.32 2005/05/16 06:23:29 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+/* thresholds for computation */
+#define FSM_HD_DEADEND_RESIDUE_LIMIT 5000/*size beyond which residue is freed*/
+#define FSM_HD_FRONTIER_APPROX_THRESHOLD 3500 /* default frontier approximation
+						 threshold */
+#define FSM_HD_REACHED_THRESHOLD  2000   /* Threshold below which reached is
+					 not decomposed */ 
+#define FSM_HD_DISJ_SIZE 5000            /* default Size of disjunct whose image
+			    may be computed in dead end computation. */
+#define FSM_HD_DEADEND_MAX_SIZE_FACTOR 5 /* Factor such that when multiplied with
+	the approx threshold will allow partitioning of the reached disjunct. */
+#define FSM_HD_FROM 0 /* Constant to indicate to subsetting method whether to use
+		       * specified method or remap_ua */
+#define FSM_HD_DEADEND 1 /* Constant to indicate to subsetting method whether to use
+		       * specified method or remap_ua */
+#define FSM_HD_MIN_SIZE_FROM 700 /* threshold to indicate not to subset if under this size */
+#define FSM_HD_DONT_FREE 0 /* flag to indicate that mdds should not be freed */
+#define FSM_HD_FREE 1 /* flag to indicate that mdds should be freed */
+#define FSM_HD_SP_THRESHOLD 2000 /* Threshold for short_paths method */
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef struct FsmHdSizeStruct FsmHdSizeStruct_t;
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/**Struct**********************************************************************
+  Synopsis [Stats structure to store size and minterm count]
+  
+******************************************************************************/
+struct FsmHdSizeStruct {
+  mdd_t *bdd;
+  int size;
+  long rnd;
+};
+		  
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static mdd_t * ComputeNewSeedsAtDeadEnd(mdd_manager *mddManager, Img_ImageInfo_t *imageInfo, mdd_t *reachableStates, FsmHdStruct_t *hdInfo, int greedy, int verbosity);
+static mdd_t * ComputeImageOfDecomposedParts(mdd_manager *mddManager, Img_ImageInfo_t *imageInfo, mdd_t *reachedSet, mdd_t *reachableStates, FsmHdStruct_t *hdInfo, int frontierApproxThreshold, int nvars, int *failedPartition, int greedy, int verbosity);
+static mdd_t * ProcessDisjunctsRecursive(mdd_manager *mddManager, Img_ImageInfo_t *imageInfo, mdd_t **reachedSet, mdd_t *reachableStates, FsmHdStruct_t *hdInfo, int frontierApproxThreshold, int nvars, int *failedPartition, int reachedSize, int greedy, int verbosity);
+static mdd_t * ComputeSubsetBasedOnMethod(mdd_t *fromBetween, mdd_t *fromLowerBound, FsmHdTravOptions_t *options, int fromOrDeadEnd);
+static mdd_t * AddStates(mdd_t *a, mdd_t *b, int freeA, int freeB);
+static mdd_t * SubtractStates(mdd_t *a, mdd_t *b, int freeA, int freeB);
+static int RandomCompare(const void *ptrX, const void *ptrY);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Returns the options required for approximate traversal.]
+
+  Description [Return the options required for approximate traversal
+  in the options structure. Will return NULL if the number of
+  variables is less than zero. Only chance to set the
+  variables. nvars should be number of BDD state variables in the
+  FSM. Caller frees this structure. This procedure sets default values
+  and overwrites with user-specified values by reading the specific
+  set variables associated with the options.]
+
+  SideEffects []
+
+  SeeAlso [Fsm_FsmHdStatsStructFree]
+  
+******************************************************************************/
+FsmHdTravOptions_t *
+Fsm_FsmHdGetTravOptions(int nvars)
+{
+  char *frontierApproxMethodString, *frontierApproxThresholdString;
+  char *scrapStatesString;
+  char *deadEndString, *qualityString;
+  char *newOnlyString, *partialImageString, *deadEndSubsetMethodString;
+  FsmHdTravOptions_t *options;
+
+  if (nvars < 0) return NIL(FsmHdTravOptions_t);
+  options = ALLOC(FsmHdTravOptions_t, 1);
+  if (options == NIL(FsmHdTravOptions_t)) {
+    return NIL(FsmHdTravOptions_t);
+  }
+
+  options->nvars = nvars;
+  /* set defaults */
+  options->frontierApproxMethod = BDD_APPROX_RUA;
+  options->frontierApproxThreshold = FSM_HD_FRONTIER_APPROX_THRESHOLD;
+  options->quality = 1.0;
+  options->deadEnd = Fsm_Hd_DE_Con_c;
+  options->deadEndSubsetMethod = BDD_APPROX_RUA;
+  options->scrapStates = TRUE;
+  options->newOnly = FALSE;
+  options->onlyPartialImage = FALSE;
+  options->qualityBias = 0.5;
+  
+  /*  method for subsetting reached, from */
+  frontierApproxMethodString = Cmd_FlagReadByName("hd_frontier_approx_method");
+  if (frontierApproxMethodString != NIL(char)) {
+    if (strcmp(frontierApproxMethodString, "heavy_branch") == 0) {
+      options->frontierApproxMethod = BDD_APPROX_HB;
+    } else if (strcmp(frontierApproxMethodString, "short_paths") == 0) {
+      options->frontierApproxMethod = BDD_APPROX_SP;
+    } else if (strcmp(frontierApproxMethodString, "under_approx") == 0) {
+      options->frontierApproxMethod = BDD_APPROX_UA;
+    } else if (strcmp(frontierApproxMethodString, "remap_ua") == 0) {
+      options->frontierApproxMethod = BDD_APPROX_RUA;
+    } else if (strcmp(frontierApproxMethodString, "compress") == 0) {
+      options->frontierApproxMethod = BDD_APPROX_COMP;
+    } else if (strcmp(frontierApproxMethodString, "biased_rua") == 0) {
+      options->frontierApproxMethod = BDD_APPROX_BIASED_RUA;
+    }
+  }
+
+  /* threshold value */
+  frontierApproxThresholdString = Cmd_FlagReadByName("hd_frontier_approx_threshold");
+  if (frontierApproxThresholdString != NIL(char)) {
+    options->frontierApproxThreshold = strtol(frontierApproxThresholdString,
+					   NULL, 10);
+  }
+  /* adjust threshold if too small */
+  if ((options->frontierApproxMethod == BDD_APPROX_HB) ||
+      (options->frontierApproxMethod == BDD_APPROX_SP) ||
+      (options->frontierApproxMethod == BDD_APPROX_COMP)) {
+    if (options->frontierApproxThreshold < FSM_HD_SP_THRESHOLD) {
+      fprintf(vis_stdout, "** hd warning: Threshold too low, Correcting Frontier Approx Threshold to %d\n", FSM_HD_SP_THRESHOLD);
+      options->frontierApproxThreshold =  FSM_HD_SP_THRESHOLD;
+    }
+  } else if (options->frontierApproxThreshold < 0) {
+    fprintf(vis_stdout, "** hd warning: Threshold negative, Correcting Frontier Approx Threshold to 0\n");
+    options->frontierApproxThreshold = FSM_HD_FRONTIER_APPROX_THRESHOLD;
+  }
+
+
+  /* quality option for remap_ua */
+  qualityString = Cmd_FlagReadByName("hd_approx_quality");
+  if (qualityString != NIL(char)) {
+    options->quality = strtod(qualityString, NULL);
+    if (options->quality < 0.0) {
+      options->quality = 1.0;
+    }
+  }
+
+  /* quality option for biased_rua */
+  qualityString = Cmd_FlagReadByName("hd_approx_bias_quality");
+  if (qualityString != NIL(char)) {
+    options->qualityBias = strtod(qualityString, NULL);
+    if (options->qualityBias < 0.0) {
+      options->qualityBias = 0.5;
+    }
+  }
+
+  /* method for dead end computations */
+  deadEndString = Cmd_FlagReadByName("hd_dead_end");
+  if (deadEndString != NIL(char)) {
+    if (strcmp(deadEndString, "brute_force") == 0) {
+      options->deadEnd = Fsm_Hd_DE_BF_c;
+    } else if (strcmp(deadEndString, "conjuncts") == 0) {
+      options->deadEnd = Fsm_Hd_DE_Con_c;
+    } else if (strcmp(deadEndString, "hybrid") == 0) {
+      options->deadEnd = Fsm_Hd_DE_Hyb_c;
+    }
+  }
+  /*  method for subsetting reached, from during deadEnds*/
+  deadEndSubsetMethodString = Cmd_FlagReadByName("hd_dead_end_approx_method");
+  if (deadEndSubsetMethodString != NIL(char)) {
+    if (strcmp(deadEndSubsetMethodString, "heavy_branch") == 0) {
+      options->deadEndSubsetMethod = BDD_APPROX_HB;
+    } else if (strcmp(deadEndSubsetMethodString, "short_paths") == 0) {
+      options->deadEndSubsetMethod = BDD_APPROX_SP;
+    } else if (strcmp(deadEndSubsetMethodString, "under_approx") == 0) {
+      options->deadEndSubsetMethod = BDD_APPROX_UA;
+    } else if (strcmp(deadEndSubsetMethodString, "remap_ua") == 0) {
+      options->deadEndSubsetMethod = BDD_APPROX_RUA;
+    } else if (strcmp(deadEndSubsetMethodString, "compress") == 0) {
+      options->deadEndSubsetMethod = BDD_APPROX_COMP;
+    }
+  }
+  /* option to not add blocking states */
+  scrapStatesString = Cmd_FlagReadByName("hd_no_scrap_states");
+  if (scrapStatesString != NIL(char)) {
+    options->scrapStates = FALSE;
+  }
+
+  /* option to consider only new states instead of fromBetween */
+  newOnlyString = Cmd_FlagReadByName("hd_new_only");
+  if (newOnlyString != NIL(char)) {
+    options->newOnly = TRUE;
+  }
+    
+  /* perform approximate traversal with only partial images */
+  partialImageString = Cmd_FlagReadByName("hd_only_partial_image");
+  if (partialImageString != NIL(char)) {
+    options->onlyPartialImage = TRUE;
+  }
+
+  return (options);
+} /* end of Fsm_FsmHdGetTraversalOptions */
+
+/**Function********************************************************************
+
+  Synopsis    [Free options structure.]
+
+  Description [Free options structure.]
+
+  SideEffects []
+
+  SeeAlso [Fsm_FsmHdGetTraversalOptions]
+  
+******************************************************************************/
+void
+Fsm_FsmHdFreeTravOptions(FsmHdTravOptions_t *options)
+{
+  if (options) FREE(options);
+  return;
+} /* end of Fsm_FsmHdFreeTravOptions */
+
+/**Function**********************************************************************
+
+  Synopsis [Read high density threshold from HD Approximate Traversal
+  option structure]
+  
+  Description [Read high density threshold from HD Approximate
+  Traversal option structure]
+  
+  SideEffects []
+
+  SeeAlso []
+  
+******************************************************************************/
+int
+Fsm_FsmHdOptionReadNumVars(FsmHdTravOptions_t *options)
+{
+  if (options) return(options->nvars);
+  else return 0;
+}
+
+/**Function**********************************************************************
+
+  Synopsis [Read high density threshold from HD Approximate Traversal
+  option structure]
+
+  Description [Read high density threshold from HD Approximate Traversal
+  option structure]
+
+  SideEffects []
+
+  SeeAlso []
+
+******************************************************************************/
+int 
+Fsm_FsmHdOptionReadFrontierApproxThreshold(FsmHdTravOptions_t *options)
+{
+  if (options) return (options->frontierApproxThreshold);
+  else return 0;
+}
+
+/**Function**********************************************************************
+
+  Synopsis [Read only partial image option from HD Approximate
+  Traversal option structure]
+
+  Description [Read only partial image option from HD Approximate
+  Traversal option structure]
+
+  SideEffects []
+
+  SeeAlso []
+  
+******************************************************************************/
+boolean
+Fsm_FsmHdOptionReadOnlyPartialImage(FsmHdTravOptions_t *options)
+{
+  if (options) return (options->onlyPartialImage);
+  else return FALSE;
+}
+
+/**Function**********************************************************************
+
+  Synopsis [Read blocking states option from HD Approximate
+  Traversal option structure]
+
+  Description [Read blocking states option from HD Approximate
+  Traversal option structure]
+
+  SideEffects []
+
+  SeeAlso []
+  
+******************************************************************************/
+boolean
+Fsm_FsmHdOptionReadScrapStates(FsmHdTravOptions_t *options)
+{
+  if (options) return (options->scrapStates);
+  else return TRUE;
+}
+
+/**Function**********************************************************************
+
+  Synopsis [Read quality factor from HD Approximate Traversal option
+  structure]
+
+  Description [Read quality factor from HD Approximate Traversal option
+  structure]
+
+  SideEffects []
+
+  SeeAlso []
+  
+******************************************************************************/
+double
+Fsm_FsmHdOptionReadQuality(FsmHdTravOptions_t *options)
+{
+  if (options) return(options->quality);
+  else return 1.0;
+}
+
+/**Function**********************************************************************
+
+  Synopsis [Read High Density Method from HD Approximate Traversal
+  option structure]
+
+  Description [Read High Density Method from HD Approximate Traversal
+  option structure]
+
+  SideEffects []
+
+  SeeAlso []
+  
+******************************************************************************/
+bdd_approx_type_t
+Fsm_FsmHdOptionReadFrontierApproxMethod(FsmHdTravOptions_t *options)
+{
+  if (options) return(options->frontierApproxMethod);
+  else return BDD_APPROX_RUA;
+}
+
+/**Function**********************************************************************
+
+  Synopsis [Read dead-end from HD Approximate Traversal option
+  structure]
+
+  Description [Read dead-end from HD Approximate Traversal option
+  structure]
+
+  SideEffects []
+
+  SeeAlso []
+  
+******************************************************************************/
+Fsm_HdDeadEndType_t
+Fsm_FsmHdOptionReadDeadEnd(FsmHdTravOptions_t *options)
+{
+  if (options) return(options->deadEnd);
+  else return Fsm_Hd_DE_Con_c;
+}
+
+/**Function**********************************************************************
+
+  Synopsis [Read new only option from HD Approximate Traversal option
+  structure]
+
+  Description [Read new only option from HD Approximate Traversal option
+  structure]
+
+  SideEffects []
+
+  SeeAlso []
+  
+******************************************************************************/
+boolean
+Fsm_FsmHdOptionReadNewOnly(FsmHdTravOptions_t *options)
+{
+  if (options) return(options->newOnly);
+  else return FALSE;
+}
+
+/**Function**********************************************************************
+
+  Synopsis [Read dead-end subset method from HD Approximate Traversal
+  option structure]
+
+  Description [Read dead-end subset method from HD Approximate Traversal
+  option structure]
+
+  SideEffects []
+
+  SeeAlso []
+  
+******************************************************************************/
+bdd_approx_type_t
+Fsm_FsmHdOptionReadDeadEndSubsetMethod(FsmHdTravOptions_t *options)
+{
+  if (options) return(options->deadEndSubsetMethod);
+  else return BDD_APPROX_RUA;
+}
+
+/**Function**********************************************************************
+
+  Synopsis [Set high density threshold from HD Approximate Traversal
+  option structure]
+
+  Description [Set high density threshold from HD Approximate
+  Traversal option structure. Returns 0 if threshold less than number
+  of state variables in the FSM, corrects the value to number of
+  variables. Else 1.]
+
+  SideEffects []
+
+  SeeAlso []
+
+******************************************************************************/
+int 
+Fsm_FsmHdOptionSetFrontierApproxThreshold(FsmHdTravOptions_t *options,
+					  int threshold)
+{
+  if ((options->frontierApproxMethod == BDD_APPROX_HB) ||
+      (options->frontierApproxMethod == BDD_APPROX_SP) ||
+      (options->frontierApproxMethod == BDD_APPROX_COMP)) {
+    if  (threshold < FSM_HD_SP_THRESHOLD) {
+      fprintf(vis_stdout, "** hd warning: Threshold too low, Correcting Frontier Approx Threshold to %d\n", FSM_HD_SP_THRESHOLD);
+      options->frontierApproxThreshold =  FSM_HD_SP_THRESHOLD;
+      return 0;
+    } else {
+      options->frontierApproxThreshold = threshold;
+      return 1;
+    }
+  } else if (threshold < 0) {
+    fprintf(vis_stdout, "** hd warning: Threshold negative, Correcting Frontier Approx Threshold to 0\n");
+    options->frontierApproxThreshold = FSM_HD_FRONTIER_APPROX_THRESHOLD;
+    return 0;
+  } else {
+    options->frontierApproxThreshold = threshold;
+    return 1;
+  }
+}
+
+/**Function**********************************************************************
+
+  Synopsis [Set only partial image option from HD Approximate
+  Traversal option structure]
+
+  Description [Set only partial image option from HD Approximate
+  Traversal option structure]
+
+  SideEffects []
+
+  SeeAlso []
+  
+******************************************************************************/
+void
+Fsm_FsmHdOptionSetOnlyPartialImage(FsmHdTravOptions_t *options,
+				   boolean onlyPartial)
+{
+  if (options) options->onlyPartialImage = onlyPartial;
+  return;
+}
+
+/**Function**********************************************************************
+
+  Synopsis [Set blocking states option from HD Approximate
+  Traversal option structure]
+
+  Description [Set blocking states option from HD Approximate
+  Traversal option structure]
+
+  SideEffects []
+
+  SeeAlso []
+  
+******************************************************************************/
+void
+Fsm_FsmHdOptionSetScrapStates(FsmHdTravOptions_t *options, boolean scrapStates)
+{
+  if (options) options->scrapStates = scrapStates;
+  return;
+}
+
+/**Function**********************************************************************
+
+  Synopsis [Set quality factor from HD Approximate Traversal option
+  structure]
+
+  Description [Set quality factor from HD Approximate Traversal option
+  structure. Range of quality is positive doubles. Default value is
+  1.0. ]
+
+  SideEffects []
+
+  SeeAlso []
+  
+******************************************************************************/
+void
+Fsm_FsmHdOptionSetQuality(FsmHdTravOptions_t *options, double quality)
+{
+  if (quality > 0.0) 
+    if (options) options->quality = quality;
+  return;
+}
+
+/**Function**********************************************************************
+
+  Synopsis [Set High Density Method from HD Approximate Traversal
+  option structure]
+
+  Description [Set High Density Method from HD Approximate Traversal
+  option structure]
+
+  SideEffects []
+
+  SeeAlso []
+  
+******************************************************************************/
+void
+Fsm_FsmHdOptionSetFrontierApproxMethod(FsmHdTravOptions_t *options,
+				       bdd_approx_type_t approxMethod)
+{
+  if (options) options->frontierApproxMethod = approxMethod;
+  if ((options->frontierApproxMethod == BDD_APPROX_HB) ||
+      (options->frontierApproxMethod == BDD_APPROX_SP) ||
+      (options->frontierApproxMethod == BDD_APPROX_COMP)) {
+    if  (options->frontierApproxThreshold < FSM_HD_SP_THRESHOLD) {
+      fprintf(vis_stdout, "** hd warning: Threshold too low, Correcting Frontier Approx Threshold to %d\n", FSM_HD_SP_THRESHOLD);
+      options->frontierApproxThreshold =  FSM_HD_SP_THRESHOLD;
+      return;
+    }
+  } else if (options->frontierApproxThreshold < 0) {
+    fprintf(vis_stdout, "** hd warning: Threshold negative, Correcting Frontier Approx Threshold to 0\n");
+    options->frontierApproxThreshold = FSM_HD_FRONTIER_APPROX_THRESHOLD;
+    return;
+  }
+
+  return;
+}
+
+/**Function**********************************************************************
+
+  Synopsis [Set dead-end from HD Approximate Traversal option
+  structure]
+
+  Description [Set dead-end from HD Approximate Traversal option
+  structure]
+
+  SideEffects []
+
+  SeeAlso []
+  
+******************************************************************************/
+void
+Fsm_FsmHdOptionSetDeadEnd(FsmHdTravOptions_t *options,
+			  Fsm_HdDeadEndType_t deadEnd)
+{
+  if (options) options->deadEnd = deadEnd;
+  return;
+}
+
+/**Function**********************************************************************
+
+  Synopsis [Set new only option from HD Approximate Traversal option
+  structure]
+
+  Description [Set new only option from HD Approximate Traversal option
+  structure]
+
+  SideEffects []
+
+  SeeAlso []
+  
+******************************************************************************/
+void
+Fsm_FsmHdOptionSetNewOnly(FsmHdTravOptions_t *options, boolean newOnly)
+{
+  if (options) options->newOnly = newOnly;
+  return;
+}
+
+/**Function**********************************************************************
+
+  Synopsis [Set dead-end subset method from HD Approximate Traversal
+  option structure]
+
+  Description [Set dead-end subset method from HD Approximate Traversal
+  option structure]
+
+  SideEffects []
+
+  SeeAlso []
+  
+******************************************************************************/
+void
+Fsm_FsmHdOptionSetDeadEndSubsetMethod(FsmHdTravOptions_t *options,
+				      bdd_approx_type_t approxMethod)
+{
+  if (options) options->deadEndSubsetMethod = approxMethod;
+  return;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Allocate stats structure.]
+
+  Description [Allocate stats structure. Caller frees stats structure]
+
+  SideEffects []
+
+  SeeAlso [FsmHdStatsStructFree FsmHdStatsComputeSizeAndMinterms FsmHdStatsReset]
+  
+******************************************************************************/
+FsmHdMintSizeStats_t *
+FsmHdStatsStructAlloc(void)
+{
+  FsmHdMintSizeStats_t *stats;
+
+  stats = ALLOC(FsmHdMintSizeStats_t, 1);
+  if (stats == NULL) return NULL;
+
+  stats->sizeTo = 0;
+  stats->mintermTo = 0.0;
+  stats->sizeFrom = 0;
+  stats->mintermFrom = 0.0;
+  stats->sizeFromSubset = 0;
+  stats->mintermFromSubset = 0.0;
+  stats->sizeReached = 0;
+  stats->mintermReached = 0.0;
+  
+  return stats;
+} /* end of FsmHdStatsStructAlloc */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Free stats structure.]
+
+  Description [Free stats structure.]
+
+  SideEffects []
+
+  SeeAlso [FsmHdStatsStructAlloc FsmHdStatsComputeSizeAndMinterms FsmHdStatsReset]
+  
+******************************************************************************/
+void
+FsmHdStatsStructFree(FsmHdMintSizeStats_t *stats)
+{
+  FREE(stats);
+  return;
+} /* end of FsmHdStatsStructFree */
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compute size and minterms of a bdd]
+
+  Description [Compute size and minterms of a bdd]
+
+  SideEffects []
+
+  SeeAlso [FsmHdStatsStructFree FsmHdStatsStructFree FsmHdStatsReset]
+  
+******************************************************************************/
+void
+FsmHdStatsComputeSizeAndMinterms(mdd_manager *mddManager,
+		       mdd_t *f,
+		       array_t *varArray,
+		       int nvars,
+		       Fsm_Hd_Quant_t field,
+		       FsmHdMintSizeStats_t *stats)
+{
+  int size;
+  double minterms = 0.0;
+  
+  size = mdd_size(f);
+  if (nvars <= 1023)
+    minterms = mdd_count_onset(mddManager, f, varArray);
+  
+  switch (field) {
+  case Fsm_Hd_From: {
+    stats->sizeFrom = size;
+    stats->mintermFrom = minterms; 
+    break;
+  }
+  case Fsm_Hd_To: {
+    stats->sizeTo = size;
+    stats->mintermTo = minterms;
+    break;
+  }
+  case Fsm_Hd_FromSubset: {
+    stats->sizeFromSubset = size;
+    stats->mintermFromSubset = minterms;
+    break;
+  }
+  case Fsm_Hd_Reached: {
+    stats->sizeReached = size;
+    stats->mintermReached = minterms;
+    break;
+  }
+  default: break;
+  }
+  return;
+} /* end of FsmHdStatsComputeSizeAndMinterms */
+
+/**Function********************************************************************
+
+  Synopsis    [Resets stats structure.]
+
+  Description [Resets stats structure.]
+
+  SideEffects [FsmHdStatsStructAlloc FsmHdStatsComputeSizeAndMinterms
+  FsmHdStatsReset]
+
+******************************************************************************/
+void
+FsmHdStatsReset(FsmHdMintSizeStats_t *stats,
+		Fsm_Hd_Quant_t field)
+{
+
+  switch (field) {
+  case Fsm_Hd_To:
+    stats->sizeTo = 0;
+    stats->mintermTo = 0.0;
+    break;
+  case Fsm_Hd_From:
+    stats->sizeFrom = 0;
+    stats->mintermFrom = 0.0;
+    break;
+  case Fsm_Hd_FromSubset:
+    stats->sizeFromSubset = 0;
+    stats->mintermFromSubset = 0.0;
+    break;
+  case Fsm_Hd_Reached:
+    stats->sizeReached = 0;
+    stats->mintermReached = 0.0;
+    break;
+  }
+  return;
+} /* end of FsmHdStatsReset */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Print HD options.]
+
+  Description [Print HD options.]
+
+  SideEffects [ ]
+
+  SeeAlso [FsmHdGetTraversalOptions]
+  
+******************************************************************************/
+void
+FsmHdPrintOptions(void)
+{
+  FsmHdTravOptions_t *options;
+  char *dummy;
+  options = Fsm_FsmHdGetTravOptions( 0);
+  if (options == NIL(FsmHdTravOptions_t)) {
+    fprintf(vis_stderr, "HD: Unalble to get options\n");
+    return;
+  }
+
+  dummy = ALLOC(char, 20);
+  if (dummy == NULL) return;
+  switch (options->frontierApproxMethod) {
+  case BDD_APPROX_HB: sprintf(dummy, "%s", "heavy_branch"); break;
+  case BDD_APPROX_SP: sprintf(dummy, "%s", "short_paths"); break;
+
+  case BDD_APPROX_UA: sprintf(dummy, "%s", "under_approx"); break;
+  case BDD_APPROX_RUA: sprintf(dummy, "%s", "remap_ua"); break;
+  case BDD_APPROX_BIASED_RUA: sprintf(dummy, "%s", "biased_rua"); break;
+
+  case BDD_APPROX_COMP: sprintf(dummy, "%s", "compress"); break;
+  default: sprintf(dummy, "%s", "remap_ua"); break;
+  }
+    
+  fprintf(vis_stdout, "HD: Approx method for frontier subsets = %s\n", dummy);
+  fprintf(vis_stdout, "HD: Threshold for frontier approximation = %d\n", options->frontierApproxThreshold);
+  fprintf(vis_stdout, "HD: Quality option for approx methods = %g\n", options->quality);
+  fprintf(vis_stdout, "HD: Bias quality option for the biased approx method = %g\n", options->qualityBias);
+
+  switch (options->deadEnd) {
+  case Fsm_Hd_DE_BF_c: sprintf(dummy, "%s", "brute_force"); break;
+  case Fsm_Hd_DE_Con_c: sprintf(dummy, "%s", "conjuncts"); break;
+  case Fsm_Hd_DE_Hyb_c: sprintf(dummy, "%s", "hybrid"); break;
+  }
+    
+  fprintf(vis_stdout, "HD: Dead-End method = %s\n", dummy);
+
+  switch (options->deadEndSubsetMethod) {
+  case BDD_APPROX_HB: sprintf(dummy, "%s", "heavy_branch"); break;
+  case BDD_APPROX_SP: sprintf(dummy, "%s", "short_paths"); break;
+
+  case BDD_APPROX_UA: sprintf(dummy, "%s", "under_approx"); break;
+  case BDD_APPROX_RUA: sprintf(dummy, "%s", "remap_ua"); break;
+
+  case BDD_APPROX_COMP: sprintf(dummy, "%s", "compress"); break;
+  default: sprintf(dummy, "%s", "remap_ua"); break;
+  }
+    
+  fprintf(vis_stdout, "HD: Dead-end approx method = %s\n", dummy);
+  FREE(dummy);
+  
+  fprintf(vis_stdout, "HD: Add scrap states option = ");
+  if (options->scrapStates == TRUE) fprintf(vis_stdout, "yes\n");
+  else fprintf(vis_stdout, "no\n");
+
+  fprintf(vis_stdout, "HD: Only new states in frontier option = ");
+  if (options->newOnly == TRUE) fprintf(vis_stdout, "yes\n");
+  else fprintf(vis_stdout, "no\n");
+
+  fprintf(vis_stdout, "HD: Only partial image option = ");
+  if (options->onlyPartialImage == TRUE) fprintf(vis_stdout, "yes\n");
+  else fprintf(vis_stdout, "no\n");
+
+  Fsm_FsmHdFreeTravOptions(options);
+  Img_ImagePrintPartialImageOptions();
+  
+  fprintf(vis_stdout, "See help page on print_hd_options for setting these options\n");
+  return;
+
+} /* end of FsmHdPrintOptions */
+
+/**Function********************************************************************
+
+  Synopsis [Checks if dead-end and computes new states from
+  Reached-InteriorStates.]
+
+  Description [Checks if dead-end and computes new states from
+  Reached-InteriorStates. If a residue exists, the residue states are returned, 
+  else new states are returned.]
+
+  SideEffects [interior states are updated]
+
+  SeeAlso []
+
+******************************************************************************/
+mdd_t *
+FsmHdDeadEnd(mdd_manager *mddManager,
+	     Img_ImageInfo_t *imageInfo,
+	     mdd_t *reachableStates,
+	     FsmHdStruct_t *hdInfo, 
+	     array_t *varArray,
+	     int greedy,
+	     int verbosity)
+{
+  mdd_t *fromLowerBound;
+  
+  /* if residue is around to long, throw it away */
+  if (hdInfo->residueCount >= 4) {
+    if (hdInfo->deadEndResidue != NULL) {
+      mdd_free(hdInfo->deadEndResidue);
+      hdInfo->deadEndResidue = NULL;
+    }
+  }
+      
+  if ((hdInfo->deadEndResidue != NULL) && (greedy)) {
+    /* dont compute new seeds out of dead end
+     * if some states are left over from previous iterations.
+     */
+    fromLowerBound = hdInfo->deadEndResidue;
+    hdInfo->deadEndResidue = NULL;
+    assert(!mdd_is_tautology(fromLowerBound, 0));
+    if (hdInfo->interiorStates != NIL(mdd_t))
+      assert(mdd_lequal(fromLowerBound, hdInfo->interiorStates, 1, 0));
+    if (verbosity >= 2) fprintf(vis_stdout, "Residue had new seeds\n");
+    (hdInfo->residueCount)++;
+  } else {
+    /* compute new seeds by decomposing reachable states */
+    if (hdInfo->deadEndResidue != NULL) {
+      mdd_free(hdInfo->deadEndResidue);
+      hdInfo->deadEndResidue = NULL;
+    }
+    hdInfo->residueCount = 0;
+    fromLowerBound = ComputeNewSeedsAtDeadEnd(mddManager,
+					      imageInfo,
+					      reachableStates,
+					      hdInfo,
+					      greedy,
+					      verbosity);
+
+  }
+	    
+  /* mark that this is a dead end */
+  hdInfo->deadEndComputation = TRUE;
+
+  return (fromLowerBound);
+} /* end of FsmHdDeadEnd */
+
+/**Function********************************************************************
+
+  Synopsis    [Computes a dense subset of the frontier.]
+
+  Description [Computes a dense subset of the frontier. Assumption:
+  fromUpperBound has the old reached states, reachableStates has the
+  new reachable states if the entire set of new states were added,
+  fromLowerBound has the set of new states, interior states have
+  states all of whose successors have been computed, image is the
+  result of the previous image computation (which is not a
+  dead-end). image has to be set to NULL if already freed. Proceed as
+  follows: Swap image and reachable states if image is larger
+  (mintermwise) than reachable states. Then compute non-interior
+  states: the only states we care about. Compute from such that it
+  includes the dead-end residue. If new_only option is not specified,
+  compute the set between the new states + dead-end residue and
+  non-interior states. A subset of this set will be computed
+  subsequently. The point is take to take as many states as possible
+  from a set which will most likely yield new successors. The subset
+  is computed only if the set of new states is large. The subset is
+  kept only if it is dense enough. A flag is set to indicate a subset
+  has been taken. The dead-end residue is computed if a dead-end
+  preceded this. If blocking states are specified, Reached is adjusted
+  to add only the subset. The dead-end residue is freed if too sparse
+  and big. Set fromLowerBound, fromUpperBound, reachableStates, stats
+  for the next iteration.]
+
+  SideEffects [ Set fromLowerBound, fromUpperBound, reachableStates,
+  stats for the next iteration. Set firstSubset and
+  deadEndResidue. Free interiorStates, image.]
+
+  SeeAlso []
+  
+******************************************************************************/
+void
+FsmHdFromComputeDenseSubset(mdd_manager *mddManager,
+			    mdd_t **fromLowerBound,
+			    mdd_t **fromUpperBound,
+			    mdd_t **reachableStates,
+			    mdd_t **image,
+			    mdd_t *initialStates,
+			    FsmHdStruct_t *hdInfo,
+			    int shellFlag,
+			    array_t *onionRings,
+			    int sizeOfOnionRings,
+			    array_t *varArray)
+{
+
+  int thisTimeSubset;
+  mdd_t *fromSubset, *fromBetween;
+  mdd_t *temp, *temp1, *nonInteriorStates;
+  float densityFrom = 0.0, densityFromSubset = 0.0; /* initialize to pacify */
+  int numReorders;
+  double mintResidue;
+  int sizeResidue;
+  int frontierApproxThreshold;
+  int nvars;
+  
+  numReorders = bdd_read_reorderings(mddManager);
+  frontierApproxThreshold = Fsm_FsmHdOptionReadFrontierApproxThreshold(hdInfo->options);
+  nvars =  Fsm_FsmHdOptionReadNumVars(hdInfo->options);
+
+   /* if image is bigger and smaller in size, switch. Add initial states.
+   * Reset dead states since they are no longer valid.
+   */
+
+#if 0 /* taken out for counterexamples  */
+  if ((FsmHdStatsReadMintermReached(hdInfo->stats) <
+       FsmHdStatsReadMintermTo(hdInfo->stats)) &&
+      (FsmHdStatsReadSizeReached(hdInfo->stats) > FsmHdStatsReadSizeTo(hdInfo->stats))) {
+    if (hdInfo->interiorStates != NIL(mdd_t)) mdd_free(hdInfo->interiorStates);
+    hdInfo->interiorStates = bdd_zero(mddManager);
+    bdd_free(*reachableStates);
+    mdd_free(*fromUpperBound);
+    *reachableStates = mdd_or(initialStates, *image, 1, 1);
+    *reachableStates = AddStates(*fromLowerBound, *reachableStates,
+				 FSM_HD_DONT_FREE, FSM_HD_FREE);
+    FsmHdStatsComputeSizeAndMinterms(mddManager, *reachableStates,
+			     varArray, nvars, Fsm_Hd_Reached, hdInfo->stats);
+    *fromUpperBound = mdd_dup(*reachableStates);
+    if (shellFlag && *onionRings) {
+      int onionRingCount;
+      mdd_t *onionRing;
+      fprintf(vis_stdout, "Onion Rings no longer valid. \n");
+      arrayForEachItem(mdd_t *, *onionRings, onionRingCount, onionRing) {
+	mdd_free(onionRing);
+      }
+      *onionRings = NIL(array_t);
+    }
+  }
+#endif  
+
+  /* states which may produce new states as successors */
+  nonInteriorStates = SubtractStates(*reachableStates, hdInfo->interiorStates,
+				     FSM_HD_DONT_FREE, FSM_HD_DONT_FREE);
+
+  /* try and reinject the residue from a dead end into the frontier */
+  if (hdInfo->deadEndResidue != NULL) {
+    temp = mdd_or(*fromLowerBound, hdInfo->deadEndResidue, 1, 1);
+  } else {
+    temp = mdd_dup(*fromLowerBound);
+  }
+  /* calculate the actual "from" going to be used */
+  if ( Fsm_FsmHdOptionReadNewOnly(hdInfo->options) == FALSE) {
+    fromBetween = bdd_squeeze(temp, nonInteriorStates);
+    mdd_free(temp);
+  } else {
+    fromBetween = temp;
+  }
+  mdd_free(nonInteriorStates);
+
+  if (nvars <= 1023) {
+    FsmHdStatsComputeSizeAndMinterms(mddManager, fromBetween,
+				     varArray, nvars,
+				     Fsm_Hd_From, hdInfo->stats);
+  }
+    
+  /* if from is bigger in size than image, use image as from*/
+  if (( Fsm_FsmHdOptionReadNewOnly(hdInfo->options) == FALSE) && (*image != NULL) &&
+      (FsmHdStatsReadSizeTo(hdInfo->stats) < FsmHdStatsReadSizeFrom(hdInfo->stats))) {
+    mdd_free(fromBetween);
+    FsmHdStatsSetSizeFrom(hdInfo->stats, FsmHdStatsReadSizeTo(hdInfo->stats));
+    FsmHdStatsSetMintermFrom(hdInfo->stats, FsmHdStatsReadMintermTo(hdInfo->stats));
+    fromBetween = *image;
+    *image = NULL;
+  }
+
+  /* free image since no longer required */
+  if (*image != NULL) mdd_free(*image);
+
+  assert(FsmHdStatsReadMintermFromSubset(hdInfo->stats) == 0.0);
+  assert(FsmHdStatsReadSizeFromSubset(hdInfo->stats) == 0);
+
+  /* flag to indicate whether a subset is computed this time */
+  thisTimeSubset = 0;
+
+  /* if size of from exceeds threshold, subset */
+  if ((FsmHdStatsReadSizeFrom(hdInfo->stats) >  frontierApproxThreshold) &&
+      (FsmHdStatsReadSizeFrom(hdInfo->stats) > FSM_HD_MIN_SIZE_FROM)) {
+
+    /* get subset based on the different methods */
+    fromSubset = ComputeSubsetBasedOnMethod(fromBetween,
+					    *fromLowerBound, hdInfo->options,
+					    FSM_HD_FROM);
+    if (nvars <= 1023) {
+      /* record stats */
+      FsmHdStatsComputeSizeAndMinterms(mddManager, fromSubset,
+			     varArray, nvars, 
+			   Fsm_Hd_FromSubset, hdInfo->stats);
+      /* compute density */
+      densityFromSubset = FsmHdStatsReadDensityFromSubset(hdInfo->stats);
+      densityFrom = FsmHdStatsReadDensityFrom(hdInfo->stats);
+    }
+		
+    /* check density of subset, discard the subset if not required*/
+    if (((nvars <= 1023) &&
+	 (((densityFrom < densityFromSubset) ||
+	    (FsmHdStatsReadSizeFrom(hdInfo->stats) > 2*frontierApproxThreshold)))) ||
+	((nvars > 1023) &&
+	 ((bdd_apa_compare_ratios(nvars, fromSubset, fromBetween,
+				  FsmHdStatsReadSizeFromSubset(hdInfo->stats),
+				  FsmHdStatsReadSizeFrom(hdInfo->stats)) ||
+	    (FsmHdStatsReadSizeFrom(hdInfo->stats) > 2*frontierApproxThreshold))))) {
+
+      /* subset chosen this time */
+      thisTimeSubset = 1;
+      
+      mdd_free(fromBetween);
+
+      /* discard the old bounds only if not required later */
+      if (hdInfo->deadEndComputation || hdInfo->firstSubset) {
+	/* store the residue since subset has been taken. Use them in
+           subsequent iterations*/
+	hdInfo->deadEndResidue = SubtractStates(*fromLowerBound, fromSubset,
+					 FSM_HD_DONT_FREE, FSM_HD_DONT_FREE);
+	if(mdd_is_tautology(hdInfo->deadEndResidue, 0)) {
+	  mdd_free(hdInfo->deadEndResidue);
+	  hdInfo->deadEndResidue = NULL;
+	} else if (mdd_size(hdInfo->deadEndResidue) > FSM_HD_DEADEND_RESIDUE_LIMIT) {
+	  mdd_free(hdInfo->deadEndResidue);
+	  hdInfo->deadEndResidue = NULL;
+	} else {
+	  hdInfo->firstSubset = 0;
+	}
+		
+      }
+      
+      /* set from lower bound for next image computation */
+      mdd_free(*fromLowerBound);
+      *fromLowerBound = fromSubset;
+		    
+    }  else {
+      /* discard the old bounds; since no subset is discarded */
+      mdd_free(*fromLowerBound);
+      /* Undo subset computation */
+      mdd_free(fromSubset);
+      *fromLowerBound = fromBetween;
+    }
+  } else {
+    /* No subsetting here */
+    mdd_free(*fromLowerBound);
+    *fromLowerBound = fromBetween;
+  }
+
+  /* remove frontier from dead-end residue */
+  if ((hdInfo->deadEndResidue != NULL) && (!hdInfo->deadEndComputation)) {
+    hdInfo->deadEndResidue = SubtractStates(hdInfo->deadEndResidue, *fromLowerBound,
+				     FSM_HD_FREE, FSM_HD_DONT_FREE);
+    if (mdd_is_tautology(hdInfo->deadEndResidue, 0)) {
+      mdd_free(hdInfo->deadEndResidue);
+      hdInfo->deadEndResidue = NULL;
+    } else if (mdd_size(hdInfo->deadEndResidue) > FSM_HD_DISJ_SIZE) {
+      mdd_free(hdInfo->deadEndResidue);
+      hdInfo->deadEndResidue = NULL;
+    }
+  }
+
+  /*
+   * check size of reached if there were any reorderings since
+   * the last time the size was measured
+   */
+  if (bdd_read_reorderings(mddManager)> numReorders) {
+    FsmHdStatsSetSizeReached(hdInfo->stats, mdd_size(*reachableStates));
+  }
+  /* Modify Reachable states if necessary. The conditions are if
+   * blocking states are not to be included in Reached. The exceptions
+   * are if no subset was computed or the size of Reached is less than
+   * 30000 or if this were a DEAD-END computation (very important:
+   * this rule isnt violated). That is ALL states computed out of a
+   * DEAD_END must ALWAYS be added to reached.
+   */
+  if (thisTimeSubset && (Fsm_FsmHdOptionReadScrapStates(hdInfo->options) == FALSE) &&
+      (!hdInfo->deadEndComputation) && 
+      (FsmHdStatsReadSizeReached(hdInfo->stats) > 30000)) {
+    temp = AddStates(*fromUpperBound, *fromLowerBound,
+		     FSM_HD_FREE, FSM_HD_DONT_FREE);
+    temp1 = bdd_squeeze(temp, *reachableStates);
+    mdd_free(*reachableStates);
+    mdd_free(temp);
+    *reachableStates = temp1;
+    FsmHdStatsComputeSizeAndMinterms(mddManager, *reachableStates, varArray,
+			   nvars, Fsm_Hd_Reached, hdInfo->stats);
+    if (shellFlag && onionRings) { /* restrict the onion rings to the modified reachable set */
+      int onionRingCount;
+      for (onionRingCount = sizeOfOnionRings; onionRingCount < array_n(onionRings);
+	   onionRingCount++) {
+	mdd_t *onionRing;
+	onionRing = array_fetch(mdd_t *, onionRings, onionRingCount);
+	temp = mdd_and(onionRing, *reachableStates, 1, 1);
+	mdd_free(onionRing);
+	array_insert(mdd_t *, onionRings, onionRingCount, temp);
+      }
+    }
+
+  } else {
+    mdd_free(*fromUpperBound);
+  }
+
+  /* Throw away dead-end residue when it gets to be a pain.
+   * i.e., when its density is larger than Reached or when the
+   * fraction of minterms retained in it are too small.
+   */
+  if (hdInfo->deadEndResidue != NULL) {
+    mintResidue = mdd_count_onset(mddManager, hdInfo->deadEndResidue, varArray);
+    sizeResidue = mdd_size(hdInfo->deadEndResidue);
+    if ((mintResidue < 	0.001*FsmHdStatsReadMintermReached(hdInfo->stats)) ||
+	(mintResidue/sizeResidue > FsmHdStatsReadDensityReached(hdInfo->stats))) {
+      mdd_free(hdInfo->deadEndResidue);
+      hdInfo->deadEndResidue = NULL;
+    }
+  }
+
+  /* set fromUpperBound for the next iteration */
+  *fromUpperBound = *fromLowerBound;
+  return;
+} /* end of FsmHdFromComputeDenseSubset */
+
+ 
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Compute new seeds at dead-end]
+
+  Description [Compute new seeds at dead-end, depending on the dead
+  end method. Hybrid method calls conjunct method.  Hybrid method
+  tries a subset of (Reached-Interior) states first. The rest is
+  shared between the hybrid and the conjuncts method. They proceed as
+  follows: Decompose Reached and compute the image of small decomposed
+  parts. If this fails to get new seeds (because decomposition failed
+  to decompose reached into small enough parts) then compute a subset
+  of the states whose image has not been computed. Finally give in and
+  compute the image of a potentially large Reached. newSeeds is set to
+  NULL if no new states. ]
+
+
+  SideEffects []
+
+  SeeAlso [FsmHdDeadEnd ComputeImageOfDecomposedParts
+  ComputeSubsetBasedOnMethod]
+  
+******************************************************************************/
+static mdd_t *
+ComputeNewSeedsAtDeadEnd(mdd_manager *mddManager,
+			 Img_ImageInfo_t *imageInfo,
+			 mdd_t *reachableStates,
+			 FsmHdStruct_t *hdInfo, 
+			 int greedy,
+			 int verbosity)
+{
+  mdd_t *toCareSet, *newSeeds = NULL, *possibleSeeds, *temp;
+  mdd_t *reachedSubset, *reachedSet;
+  int failedPartition = 0;
+  int frontierApproxThreshold =  Fsm_FsmHdOptionReadFrontierApproxThreshold(hdInfo->options);
+  int deadEnd =  Fsm_FsmHdOptionReadDeadEnd(hdInfo->options);
+  int nvars =  Fsm_FsmHdOptionReadNumVars(hdInfo->options);
+  
+  /* in brute force method, compute the image of the entire reached */
+  if (deadEnd == Fsm_Hd_DE_BF_c) {
+    toCareSet = mdd_not(reachableStates);
+    possibleSeeds = Img_ImageInfoComputeFwdWithDomainVars(imageInfo,
+							  reachableStates,
+							  reachableStates,
+							  toCareSet);
+    mdd_free(toCareSet);
+    newSeeds = SubtractStates(possibleSeeds, reachableStates,
+			      FSM_HD_FREE, FSM_HD_DONT_FREE);
+    return (newSeeds);
+  }
+
+  /* in HYBRID method, first try with  a subset of the reached set */
+  reachedSet = SubtractStates(reachableStates, hdInfo->interiorStates,
+			    FSM_HD_DONT_FREE, FSM_HD_DONT_FREE);
+  if (deadEnd ==  Fsm_Hd_DE_Hyb_c) {
+    /* compute image of a subset of reached */
+    reachedSubset = ComputeSubsetBasedOnMethod(reachedSet,
+					       NIL(mdd_t),
+					       hdInfo->options,
+					       FSM_HD_DEADEND);
+					       
+    if (bdd_size(reachedSubset) < 2*frontierApproxThreshold) {
+      toCareSet = mdd_not(reachableStates);
+      possibleSeeds = Img_ImageInfoComputeFwdWithDomainVars(imageInfo,
+							    reachedSubset,
+							    reachableStates,
+							    toCareSet);
+      mdd_free(toCareSet);
+      /* compute new states */
+      newSeeds = SubtractStates(possibleSeeds, reachableStates,
+			      FSM_HD_FREE, FSM_HD_DONT_FREE);
+      /* add to interior states */
+      hdInfo->interiorStates = AddStates(hdInfo->interiorStates, reachedSubset,
+				  FSM_HD_FREE, FSM_HD_DONT_FREE);
+      if (verbosity >= 2) {
+	fprintf(vis_stdout, "Interior states added, Size = %d\n",
+		mdd_size(hdInfo->interiorStates));
+      }
+
+      if ((!mdd_is_tautology(newSeeds, 0)) && (greedy))  {
+	mdd_free(reachedSet);
+	mdd_free(reachedSubset);
+	return (newSeeds);
+      } else {
+	/* reset newSeeds value for further computations */
+	if (mdd_is_tautology(newSeeds, 0)) {
+	  mdd_free(newSeeds);
+	  newSeeds = NULL;
+	}
+	/* if new seeds not found or iter_decomp unsuccessful, set
+	 * reachedSet to the other part (which may be a part of the
+	 * reachable states (former) or the reachable states itself
+	 * (latter)).
+	 */
+	reachedSet = SubtractStates(reachedSet, reachedSubset,
+				      FSM_HD_FREE, FSM_HD_FREE);
+      }
+    } else {
+      mdd_free(reachedSubset);
+    }
+  }
+  
+  /* compute the decomposed image of reachedSet */
+  if ((deadEnd == Fsm_Hd_DE_Con_c) ||
+      (deadEnd == Fsm_Hd_DE_Hyb_c)) {
+    /* this flag is set when the image of some decomposed part is
+     * not computed due to its size.
+     */
+    failedPartition = 0;
+    /* save any previously computed new states */
+    temp = newSeeds;
+    /* compute new seeds by recursively decomposing reachedSet */
+    newSeeds = ComputeImageOfDecomposedParts(mddManager,
+					     imageInfo,
+					     reachedSet,
+					     reachableStates,
+					     hdInfo,
+					     frontierApproxThreshold,
+					     nvars,
+					     &failedPartition,
+					     greedy,
+					     verbosity);
+    /* combine new states */
+    newSeeds = AddStates(newSeeds, temp, FSM_HD_FREE, FSM_HD_FREE);
+
+    /* if no remains or partition didnt fail, return new Seeds */
+    /* if greedy and new states found, return */
+    if ((mdd_lequal(reachedSet, hdInfo->interiorStates, 1, 1)) ||
+	((newSeeds != NULL) && (greedy))) {
+      /* assert that the entire image was computed */
+      if (mdd_lequal(reachedSet, hdInfo->interiorStates, 1, 1)) assert(!failedPartition);
+      mdd_free(reachedSet);
+      if (newSeeds == NULL)
+	newSeeds = bdd_zero(mddManager);
+      else
+	assert(!mdd_is_tautology(newSeeds, 0));
+      return(newSeeds);
+    }
+
+    /* continue if either no new states have been found or the
+     * computation is not greedy */
+    /* new set whose image is to be computed  */
+    reachedSet = SubtractStates(reachedSet, hdInfo->interiorStates,
+				FSM_HD_FREE, FSM_HD_DONT_FREE);
+    
+    
+    /* one last shot with a subsetting the remains */
+    /* reachedSubset is the subset of reached remains */
+    reachedSubset = ComputeSubsetBasedOnMethod(reachedSet,
+					       NIL(mdd_t),
+					       hdInfo->options,
+					       FSM_HD_DEADEND);
+	
+    /* compute image of the subset above */
+    toCareSet = mdd_not(reachableStates);
+    possibleSeeds = Img_ImageInfoComputeFwdWithDomainVars(imageInfo,
+							  reachedSubset,
+							  reachableStates,
+							  toCareSet);
+    mdd_free(toCareSet);
+    /* add to interior states */
+    hdInfo->interiorStates = AddStates(hdInfo->interiorStates, reachedSubset,
+				FSM_HD_FREE, FSM_HD_FREE);
+    if (verbosity >= 2) {
+      fprintf(vis_stdout, "Interior states added, Size = %d\n",
+	      mdd_size(hdInfo->interiorStates));
+    }
+    /* combine all new states */
+    temp = newSeeds;
+    newSeeds = SubtractStates(possibleSeeds, reachableStates,
+			      FSM_HD_FREE, FSM_HD_DONT_FREE);
+    newSeeds = AddStates(newSeeds, temp, FSM_HD_FREE, FSM_HD_FREE);
+
+    /* if no new seeds, compute the image of (reachedSet - reachedSubset) */
+    if ((mdd_is_tautology(newSeeds, 0) != 1) && (greedy)) {
+      mdd_free(reachedSet);
+      mdd_free(reachedSubset);
+      return newSeeds;
+    } else {
+      /* reset newSeeds for further computation */
+      if (mdd_is_tautology(newSeeds, 0)) {
+	mdd_free(newSeeds);
+	newSeeds = NULL;
+      }
+      /* set reached = reachedSet - reachedSubset */
+      reachedSet  = SubtractStates(reachedSet, reachedSubset,
+				   FSM_HD_FREE, FSM_HD_FREE);
+    }
+
+    /* save previously computed new states */
+    temp = newSeeds;
+    failedPartition = 0;
+    /* try decomposition again */
+    newSeeds = ComputeImageOfDecomposedParts(mddManager,
+					     imageInfo,
+					     reachedSet,
+					     reachableStates, hdInfo, 
+					     frontierApproxThreshold,
+					     nvars,
+					     &failedPartition,
+					     greedy,
+					     verbosity);
+    /* combine all new states */
+    newSeeds = AddStates(newSeeds, temp, FSM_HD_FREE, FSM_HD_FREE);
+    /* if no remains or partition didnt fail, return new Seeds */
+    /* if greedy and new states found, return */
+    if ((mdd_lequal(reachedSet, hdInfo->interiorStates, 1, 1)) ||
+	((newSeeds != NULL) && (greedy))) {
+      /* assert that the entire image was computed */
+      if (mdd_lequal(reachedSet, hdInfo->interiorStates, 1, 1)) assert(!failedPartition);
+      mdd_free(reachedSet);
+      if (newSeeds == NULL)
+	newSeeds = bdd_zero(mddManager);
+      else
+	assert(!mdd_is_tautology(newSeeds, 0));
+      return(newSeeds);
+    }
+
+    /* continue if either no new states have been found or the
+     * computation is not greedy */
+    /* new set whose image is to be computed  */
+    reachedSet = SubtractStates(reachedSet, hdInfo->interiorStates,
+				FSM_HD_FREE, FSM_HD_DONT_FREE);
+    
+    /* now bite the bullet and compute the image of the whole
+     * remainder.
+     */
+    toCareSet = mdd_not(reachableStates);
+    possibleSeeds = Img_ImageInfoComputeFwdWithDomainVars(imageInfo,
+							  reachedSet,
+							  reachableStates,
+							  toCareSet);
+    mdd_free(toCareSet);
+    /* add to interios states */
+    hdInfo->interiorStates = AddStates(hdInfo->interiorStates, reachedSet,
+				FSM_HD_FREE, FSM_HD_FREE);
+    if (verbosity >= 2) {
+      fprintf(vis_stdout, "Interior states added, Size = %d\n",
+	      mdd_size(hdInfo->interiorStates));
+    }
+    /* combine all new states */
+    temp = newSeeds;
+    newSeeds = SubtractStates(possibleSeeds, reachableStates,
+			      FSM_HD_FREE, FSM_HD_DONT_FREE);
+    newSeeds = AddStates(newSeeds, temp, FSM_HD_FREE, FSM_HD_FREE);
+
+  }
+  return newSeeds;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Compute image of decomposed reached set until new seeds
+  are found.]
+
+  Description [Compute image of decomposed reached set until new seeds
+  are found. This procedure is obliged to return newSeeds = NULL if no
+  new seeds are found. The recursive procedure tries to decompose
+  Reached. The return value is the set of new states. ]
+
+  SideEffects []
+  
+  SeeAlso [ComputeNewSeedsAtDeadEnd ProcessDisjunctsRecursive]
+
+******************************************************************************/
+static mdd_t *
+ComputeImageOfDecomposedParts(mdd_manager *mddManager,
+			      Img_ImageInfo_t *imageInfo,
+			      mdd_t *reachedSet,
+			      mdd_t *reachableStates,
+			      FsmHdStruct_t *hdInfo, 
+			      int frontierApproxThreshold,
+			      int nvars,
+			      int *failedPartition,
+			      int greedy,
+			      int verbosity)
+{
+
+  mdd_t *temp, *newSeeds, *possibleSeeds;
+  mdd_t *toCareSet;
+  int reachedSize, threshold;
+    
+  /* initialize some variables */
+  newSeeds = NULL;
+  reachedSize = mdd_size(reachedSet);
+  threshold = (FSM_HD_REACHED_THRESHOLD > frontierApproxThreshold) ? FSM_HD_REACHED_THRESHOLD : frontierApproxThreshold;
+
+  /* compute the image of reached if it is small */
+  if (reachedSize < threshold) {
+    toCareSet = mdd_not(reachableStates);
+    possibleSeeds = Img_ImageInfoComputeFwdWithDomainVars(imageInfo,
+							  reachedSet,
+							  reachableStates,
+							  toCareSet);
+    mdd_free(toCareSet);
+    newSeeds = SubtractStates(possibleSeeds, reachableStates,
+			      FSM_HD_FREE, FSM_HD_DONT_FREE);
+    if (mdd_is_tautology(newSeeds, 0)) {
+      mdd_free(newSeeds);
+      newSeeds = NULL;
+    }
+    hdInfo->interiorStates = AddStates(hdInfo->interiorStates, reachedSet,
+				FSM_HD_FREE, FSM_HD_DONT_FREE);
+    return (newSeeds);
+  }
+
+  /* create conjuncts of the complement, disjuncts of the
+   * reachable set
+   */
+  temp = mdd_dup(reachedSet);
+  /* set threshold to some non-trivial value */
+  if (frontierApproxThreshold <= 0)
+    frontierApproxThreshold = FSM_HD_REACHED_THRESHOLD/
+      FSM_HD_DEADEND_MAX_SIZE_FACTOR;
+  /* compute the image of decomposed parts. Return when some new seeds are
+   * found.
+   */
+  newSeeds = ProcessDisjunctsRecursive(mddManager,
+				       imageInfo,
+				       &temp,
+				       reachableStates,
+				       hdInfo, 
+				       frontierApproxThreshold,
+				       nvars,
+				       failedPartition,
+				       reachedSize,
+				       greedy,
+				       verbosity);
+					 
+  return (newSeeds);
+    
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the image of decomposed reached greedily]
+
+  Description [Computes the image of decomposed reached
+  greedily. Recursive procedure that decomposes product into two
+  conjuncts at each call. In the greedy procedure, decomposition stops
+  if the computed partitions are below a certain threshold. The image
+  of all partitions under this threshold are computed. Also subsets of
+  the remaining large partitions are considered for image
+  computation. newSeeds is set to NULL if no new states are found.  If
+  any partition cannot be decomposed any further and it is too large,
+  then its image is not computed and the failed partition flag is
+  set. The calling procedure should infer this partition from the
+  interior states and compute its image.]
+
+  SideEffects [Frees reachedSet]
+
+   SeeAlso [ComputeImageOfDecomposedParts]
+  
+******************************************************************************/
+static mdd_t *
+ProcessDisjunctsRecursive(mdd_manager *mddManager,
+			  Img_ImageInfo_t *imageInfo,
+			  mdd_t **reachedSet,
+			  mdd_t *reachableStates,
+			  FsmHdStruct_t *hdInfo, 
+			  int frontierApproxThreshold,
+			  int nvars,
+			  int *failedPartition,
+			  int reachedSize,
+			  int greedy,
+			  int verbosity)
+{
+  mdd_t *toCareSet, *newSeeds, *possibleSeeds;
+  mdd_t *temp, *subset;
+  int  tempSize;
+  int hitConstant;
+  mdd_t **disjArray;
+  char *decompString;
+  int i;
+  int numParts;
+  FsmHdSizeStruct_t sizeStruct;
+  array_t *sizeArray;
+  
+  hitConstant = 0;
+
+  assert((!mdd_is_tautology(*reachedSet, 1)) &&
+	 (!mdd_is_tautology(*reachedSet, 0)));
+  if (verbosity >= 2) {
+    fprintf(vis_stdout, "Orig Size = %d, ",mdd_size(*reachedSet));
+  }
+
+  /* decompose reached set into disjuntive parts */
+  decompString = Cmd_FlagReadByName("hd_decomp");
+  if (decompString == NIL(char)) {
+    numParts = bdd_var_decomp(*reachedSet,
+					(bdd_partition_type_t)BDD_DISJUNCTS,
+					&disjArray);
+  } else if (strcmp(decompString, "var") == 0) {
+    numParts = bdd_var_decomp(*reachedSet,
+					(bdd_partition_type_t)BDD_DISJUNCTS,
+					&disjArray);
+  } else if (strcmp(decompString, "gen") == 0) {
+    numParts = bdd_gen_decomp(*reachedSet,
+					(bdd_partition_type_t)BDD_DISJUNCTS,
+					&disjArray);
+  } else if (strcmp(decompString, "approx") == 0) {
+    numParts = bdd_approx_decomp(*reachedSet,
+					   (bdd_partition_type_t)BDD_DISJUNCTS,
+					   &disjArray);
+  } else if (strcmp(decompString, "iter") == 0) {
+    numParts = bdd_iter_decomp(*reachedSet,
+					 (bdd_partition_type_t)BDD_DISJUNCTS,
+					 &disjArray);
+  } else {
+    numParts = bdd_var_decomp(*reachedSet,
+					(bdd_partition_type_t)BDD_DISJUNCTS,
+					&disjArray);
+  }
+  mdd_free(*reachedSet);
+
+  /* decomposition failed */
+  if (numParts == 0) return NULL;
+
+  /* decomposition failed, stop recurring */
+  if (numParts == 1) hitConstant = 1;
+  
+  /* allocate array with bdds and sizes */
+  sizeArray = array_alloc(FsmHdSizeStruct_t,  0);  
+  if (sizeArray == NIL(array_t)) {
+    for (i = 0; i < numParts; i++) {
+      mdd_free(disjArray[i]);
+    }
+    FREE(disjArray);
+    return NULL;
+  }
+  
+  /* free all constants and partitions that are larger than the
+   * original reached size
+   */
+  for (i = 0; i < numParts; i++) {
+    assert(!mdd_is_tautology(disjArray[i], 1));
+    tempSize = bdd_size(disjArray[i]);
+    if ((tempSize >= reachedSize) ||
+	(tempSize == 1)) {
+      if (tempSize == 1) {
+	hitConstant = 1;
+	assert (mdd_is_tautology(disjArray[i], 0));
+      } else {
+	*failedPartition = 1;
+      }
+      mdd_free(disjArray[i]);
+    } else {
+      sizeStruct.bdd = disjArray[i];
+      sizeStruct.size = tempSize;
+      sizeStruct.rnd = util_random();
+      array_insert_last(FsmHdSizeStruct_t, sizeArray, sizeStruct);
+    }
+  }
+  FREE(disjArray);
+
+  if (array_n(sizeArray) == 0) {
+    array_free(sizeArray);
+    return (NULL);
+  }
+  
+  /* shuffle parts randomly. */
+  if (array_n(sizeArray) > 1) {
+    array_sort(sizeArray, RandomCompare);
+  } 
+
+  if (verbosity >= 2) {
+    arrayForEachItem(FsmHdSizeStruct_t, sizeArray, i, sizeStruct) {
+      fprintf(vis_stdout , "disjSize[%d] = %d ", i, sizeStruct.size);
+    }
+    fprintf(vis_stdout, "\n");
+  }
+  
+  /* now compute image of parts or recur*/
+  newSeeds = NULL;
+  arrayForEachItem(FsmHdSizeStruct_t, sizeArray, i, sizeStruct) {
+    temp = NULL;
+    if ((sizeStruct.size <
+	 frontierApproxThreshold*FSM_HD_DEADEND_MAX_SIZE_FACTOR) ||
+	(sizeStruct.size < FSM_HD_DISJ_SIZE)) {
+      /* if this partition is small enough, compute its image */
+      /* compute image */
+      toCareSet = mdd_not(reachableStates);
+      possibleSeeds = Img_ImageInfoComputeFwdWithDomainVars(imageInfo,
+							    sizeStruct.bdd,
+							    reachableStates,
+							    toCareSet); 
+      mdd_free(toCareSet);
+      /* update interior states */
+      hdInfo->interiorStates = AddStates(hdInfo->interiorStates, sizeStruct.bdd,
+				  FSM_HD_FREE, FSM_HD_FREE);
+      if (verbosity >= 2) {
+	fprintf(vis_stdout, "Interior states added, Size = %d\n",
+		mdd_size(hdInfo->interiorStates));
+      }
+      /* store new states if any were already found */
+      temp = newSeeds;
+      /* compute new states of this image */
+      newSeeds = SubtractStates(possibleSeeds, reachableStates,
+			      FSM_HD_FREE, FSM_HD_DONT_FREE);
+      /* add up states or set newSeeds to NULL if no new states */
+      if (temp != NULL) {
+	assert(!mdd_is_tautology(temp, 0));
+	newSeeds = AddStates(newSeeds, temp, FSM_HD_FREE, FSM_HD_FREE);
+      } else if (mdd_is_tautology(newSeeds, 0) == 1) {
+	mdd_free(newSeeds);
+	newSeeds = NULL;
+      }	
+    } else if ((!hitConstant) && ((newSeeds == NULL) ||
+				  (!greedy) ||
+				  (sizeStruct.size < 3* FSM_HD_DISJ_SIZE))) {
+      /* recur if size is small enough, or non-greedy computation or
+       * no new states have been found yet. But not if a constant is hit. */
+      /* store any new states already computed */
+      temp = newSeeds;
+      newSeeds = ProcessDisjunctsRecursive(mddManager,
+					   imageInfo,
+					   &(sizeStruct.bdd),
+					   reachableStates, hdInfo, 
+					   frontierApproxThreshold,
+					   nvars,
+					   failedPartition,
+					   reachedSize,
+					   greedy,
+					   verbosity);
+      /* if new seeds not NULL, then not zero either */
+      if (newSeeds != NULL) {
+	assert(!mdd_is_tautology(newSeeds, 0));
+	/* add states */
+	if (temp != NULL) {
+	  newSeeds = AddStates(temp, newSeeds, FSM_HD_FREE, FSM_HD_FREE);
+	}
+      } else {
+	newSeeds = temp;
+      }
+    } else {
+      /* if this partition is too large, compute the image of its
+       *  subset if the subset is small enough */
+      /* set failed partition as image is not being computed of this
+       *  whole part */
+      *failedPartition = 1;
+      /* compute subset */
+      subset = bdd_approx_remap_ua(sizeStruct.bdd,
+				   (bdd_approx_dir_t)BDD_UNDER_APPROX,
+				   nvars, 0, 1.0);
+      mdd_free(sizeStruct.bdd);
+      tempSize = bdd_size(subset);
+      /* compute image of subset if small enough */
+      if ((tempSize < frontierApproxThreshold*FSM_HD_DEADEND_MAX_SIZE_FACTOR) ||
+	  (tempSize < FSM_HD_DISJ_SIZE)) {
+	/* compute image */
+	toCareSet = mdd_not(reachableStates);
+	possibleSeeds = Img_ImageInfoComputeFwdWithDomainVars(imageInfo,
+							      subset,
+							      reachableStates,
+							      toCareSet);
+	mdd_free(toCareSet);
+	/* update dead states */
+	hdInfo->interiorStates = AddStates(hdInfo->interiorStates, subset,
+				    FSM_HD_FREE, FSM_HD_FREE);
+	if (verbosity >= 2) {
+	  fprintf(vis_stdout, "Interior states added, Size = %d\n",
+		  mdd_size(hdInfo->interiorStates));
+	}
+	/* store new states if any were already found */
+	temp = newSeeds;
+	/* compute new states of this image */
+	newSeeds = SubtractStates(possibleSeeds, reachableStates,
+				FSM_HD_FREE, FSM_HD_DONT_FREE);
+	/* add up states or set newSeeds to NULL if no new states */
+	if (temp != NULL) {
+	  assert(!mdd_is_tautology(temp, 0));
+	  newSeeds = AddStates(newSeeds, temp, FSM_HD_FREE, FSM_HD_FREE);
+	} else if (mdd_is_tautology(newSeeds, 0) == 1) {
+	  mdd_free(newSeeds);
+	  newSeeds = NULL;
+	}	
+      } else {
+	mdd_free(subset);
+      }
+    }
+  } /* end of array for each */
+
+  array_free(sizeArray);
+		
+  return (newSeeds);
+
+} /* end of ProcessDisjunctsRecursive */
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the subset of the from set]
+
+  Description [Computes the subset of the from set. Makes sure that
+  there are some new states. Returns the subset as computing be the
+  specified approximation method.]
+
+
+  SideEffects []
+
+******************************************************************************/
+static mdd_t *
+ComputeSubsetBasedOnMethod(mdd_t *fromBetween,
+			   mdd_t *fromLowerBound,
+			   FsmHdTravOptions_t *options,
+			   int fromOrDeadEnd)
+{
+  mdd_t *fromSubset;
+  int frontierApproxThreshold =  Fsm_FsmHdOptionReadFrontierApproxThreshold(options);
+  int frontierApproxMethod;
+  double quality =  Fsm_FsmHdOptionReadQuality(options);
+  int nvars =  Fsm_FsmHdOptionReadNumVars(options);
+			     
+  
+  frontierApproxMethod = (fromOrDeadEnd == FSM_HD_FROM) ?
+     Fsm_FsmHdOptionReadFrontierApproxMethod(options) :
+    ((fromOrDeadEnd == FSM_HD_DEADEND) ?
+      Fsm_FsmHdOptionReadDeadEndSubsetMethod(options) :
+      Fsm_FsmHdOptionReadFrontierApproxMethod(options));
+  
+  /* based on approximation method specified, compute subset */
+  switch (frontierApproxMethod) {
+  case BDD_APPROX_HB:
+    frontierApproxThreshold = (frontierApproxThreshold < FSM_HD_SP_THRESHOLD) ? FSM_HD_SP_THRESHOLD: frontierApproxThreshold;
+    fromSubset = bdd_approx_hb(fromBetween,
+			       (bdd_approx_dir_t)BDD_UNDER_APPROX,
+			       nvars, frontierApproxThreshold);
+    if (fromLowerBound != NIL(mdd_t)) {
+      if (!bdd_equal(fromBetween,fromLowerBound))  {
+	if (mdd_lequal(fromSubset, fromLowerBound, 1, 0)) {
+	  mdd_free(fromSubset);
+	  fromSubset = bdd_approx_hb(fromLowerBound,
+				     (bdd_approx_dir_t)BDD_UNDER_APPROX,
+				     nvars, frontierApproxThreshold);
+	}
+      }
+    }
+		    
+    break;
+  case BDD_APPROX_SP:
+    frontierApproxThreshold = (frontierApproxThreshold < FSM_HD_SP_THRESHOLD) ? FSM_HD_SP_THRESHOLD: frontierApproxThreshold;
+    fromSubset = bdd_approx_sp(fromBetween,
+			       (bdd_approx_dir_t)BDD_UNDER_APPROX,
+			       nvars, frontierApproxThreshold,
+			       0);
+    if (fromLowerBound != NIL(mdd_t)) {
+      if (!bdd_equal(fromBetween,fromLowerBound))  {
+	if (mdd_lequal(fromSubset, fromLowerBound, 1, 0)) {
+	  mdd_free(fromSubset);
+	  fromSubset = bdd_approx_sp(fromLowerBound,
+				     (bdd_approx_dir_t)BDD_UNDER_APPROX,
+				     nvars, frontierApproxThreshold,
+				     0);
+	}
+      }
+    }
+		    
+    break;
+  case BDD_APPROX_UA:
+    fromSubset = bdd_approx_ua(fromBetween,
+			       (bdd_approx_dir_t)BDD_UNDER_APPROX,
+			       nvars, frontierApproxThreshold,
+			       0, quality);
+    if (fromLowerBound != NIL(mdd_t)) {
+      if (!bdd_equal(fromBetween,fromLowerBound))  {
+	if (mdd_lequal(fromSubset, fromLowerBound, 1, 0)) {
+	  mdd_free(fromSubset);
+	  fromSubset = bdd_approx_ua(fromLowerBound,
+				     (bdd_approx_dir_t)BDD_UNDER_APPROX,
+				     nvars, frontierApproxThreshold,
+				     0, quality);
+	}
+      }
+    }
+    break;
+  case BDD_APPROX_RUA:
+    fromSubset = bdd_approx_remap_ua(fromBetween,
+				     (bdd_approx_dir_t)BDD_UNDER_APPROX,
+				     nvars, frontierApproxThreshold,
+				     quality );
+    if (fromLowerBound != NIL(mdd_t)) {
+      if (!bdd_equal(fromBetween,fromLowerBound))  {
+	if (mdd_lequal(fromSubset, fromLowerBound, 1, 0)) {
+	  mdd_free(fromSubset);
+	  fromSubset = bdd_approx_remap_ua(fromLowerBound,
+					   (bdd_approx_dir_t)BDD_UNDER_APPROX,
+					   nvars, frontierApproxThreshold,
+					   quality);
+	}
+      }
+    }
+		    
+    break;
+  case BDD_APPROX_BIASED_RUA:
+    if (fromLowerBound == NIL(mdd_t)) {
+      fromLowerBound = fromBetween;
+    }
+    fromSubset = bdd_approx_biased_rua(fromBetween,
+				     (bdd_approx_dir_t)BDD_UNDER_APPROX,
+				       fromLowerBound,
+				       nvars, frontierApproxThreshold,
+				     quality, options->qualityBias );
+    if (fromLowerBound != NIL(mdd_t)) {
+      if (!bdd_equal(fromBetween,fromLowerBound))  {
+	if (mdd_lequal(fromSubset, fromLowerBound, 1, 0)) {
+	  mdd_free(fromSubset);
+	  fromSubset = bdd_approx_remap_ua(fromLowerBound,
+					   (bdd_approx_dir_t)BDD_UNDER_APPROX,
+					   nvars, frontierApproxThreshold,
+					   quality);
+	}
+      }
+    }
+    break;
+  case BDD_APPROX_COMP:
+    frontierApproxThreshold = (frontierApproxThreshold < FSM_HD_SP_THRESHOLD) ? FSM_HD_SP_THRESHOLD: frontierApproxThreshold;
+    fromSubset = bdd_approx_compress(fromBetween,
+				     (bdd_approx_dir_t)BDD_UNDER_APPROX,
+				     nvars, frontierApproxThreshold);
+
+    if (fromLowerBound != NIL(mdd_t)) {
+      if (!bdd_equal(fromBetween,fromLowerBound))  {
+	if (mdd_lequal(fromSubset, fromLowerBound, 1, 0)) {
+	  mdd_free(fromSubset);
+	  fromSubset = bdd_approx_compress(fromLowerBound,
+					   (bdd_approx_dir_t)BDD_UNDER_APPROX,
+					   nvars, frontierApproxThreshold);
+	}
+      }
+    }
+
+    break;
+  default:
+    fromSubset = bdd_approx_remap_ua(fromBetween,
+				     (bdd_approx_dir_t)BDD_UNDER_APPROX,
+				     nvars, frontierApproxThreshold,
+				     quality );
+    if (fromLowerBound != NIL(mdd_t)) {
+      if (!bdd_equal(fromBetween,fromLowerBound))  {
+	if (mdd_lequal(fromSubset, fromLowerBound, 1, 0)) {
+	  mdd_free(fromSubset);
+	  fromSubset = bdd_approx_remap_ua(fromLowerBound,
+					   (bdd_approx_dir_t)BDD_UNDER_APPROX,
+					   nvars, frontierApproxThreshold,
+					   quality);
+	}
+      }
+    }
+    break;
+  }
+
+  return (fromSubset);
+} /* end of ComputeSubsetBasedOnMethod */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Add states.]
+
+  Description [Add States.]
+
+  SideEffects [ Free the original parts]
+
+******************************************************************************/
+static mdd_t *
+AddStates(mdd_t *a, mdd_t *b, int freeA, int freeB)
+{
+  mdd_t *result;
+  if ((a != NULL) && (b != NULL)) {
+    result = mdd_or(a, b, 1, 1);
+  } else if ((a == NULL) && (b == NULL)) {
+    result = a;
+  } else if (a == NULL) {
+    result = mdd_dup(b);
+  } else {
+    result =  mdd_dup(a);
+  }
+  if ((freeA == FSM_HD_FREE) && (a != NULL))  mdd_free(a);
+  if ((freeB == FSM_HD_FREE) && (b != NULL)) mdd_free(b);
+  return result;
+} /* end of AddStates */
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Subtract states b from a.]
+
+  Description [Subtract states b from a.]
+
+  SideEffects [ Free the original parts]
+
+******************************************************************************/
+static mdd_t *
+SubtractStates(mdd_t *a, mdd_t *b, int freeA, int freeB)
+{
+  mdd_t *result;
+  if ((a != NULL) && (b != NULL)) {
+    result = mdd_and(a, b, 1, 0);
+  } else if ((a == NULL) && (b == NULL)) {
+    result = a;
+  } else if (b == NULL) {
+    result =  mdd_dup(a);
+  } else { /* a = NULL , b != NULL */
+    result = NULL;
+  }
+  if ((freeA == FSM_HD_FREE) && (a != NULL))  mdd_free(a);
+  if ((freeB == FSM_HD_FREE) && (b != NULL)) mdd_free(b);
+  return result;
+} /* end of SubtractStates */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Random Comparison fn.]
+
+  Description [Random Comparison fn.]
+
+  SideEffects [ ]
+
+******************************************************************************/
+static int
+RandomCompare(const void *ptrX,
+	      const void *ptrY)
+{
+  FsmHdSizeStruct_t *sizeStruct1 = (FsmHdSizeStruct_t *)ptrX;
+  FsmHdSizeStruct_t *sizeStruct2 = (FsmHdSizeStruct_t *)ptrY;
+
+  if (sizeStruct1->rnd > sizeStruct2->rnd) return 1;
+  else if (sizeStruct1->rnd < sizeStruct2->rnd) return -1;
+  else return 0;
+} /* end of BddSizeCompare */
Index: vis_dev/vis-2.3/src/fsm/fsmInt.h
===================================================================
--- vis_dev/vis-2.3/src/fsm/fsmInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/fsm/fsmInt.h	(revision 14)
@@ -0,0 +1,480 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [fsmInt.h]
+
+  PackageName [fsm]
+
+  Synopsis    [Internal declarations for fsm package.]
+
+  Author [Shaker Sarwary, Tom Shiple, Rajeev Ranjan, Kavita Ravi, In-Ho Moon]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: fsmInt.h,v 1.45 2003/01/22 18:44:20 jinh Exp $]
+
+******************************************************************************/
+
+#ifndef _FSMINT
+#define _FSMINT
+
+#include "fsm.h"
+#include "ord.h"
+#include "part.h"
+#include "mc.h"
+#include <string.h>
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [Canonical fairness constraint.]
+
+  Description [Canonical fairness constraint. This is an array of arrays, where
+  each entry is a pair of CTL formulas, S_ij and T_ij.  Each CTL formula
+  identifies a set of states of the FSM. The interpretation of this 2-D array
+  is: (OR_i (AND_j (F-inf S_ij + G-inf T_ij))). Hence, disjunctArray is an
+  array of array_t * of FairnessConjunct_t *.]
+
+  SeeAlso     [Fsm_FsmReadFairnessConstraint]
+
+******************************************************************************/
+struct FsmFairnessStruct {
+  Fsm_Fsm_t *fsm;         /* fsm to which the fairness constraint is associated */
+  array_t   *disjunctArray; /* canonical fairness constraint */
+};
+
+/**Enum************************************************************************
+
+  Synopsis [Specifies type of status of overapproximate reached states.]
+
+  Description [Specifies type of status of overapproximate reached states.]
+
+  SideEffects []
+
+  SeeAlso []
+  
+******************************************************************************/
+typedef enum {
+  Fsm_Ardc_NotConverged_c,
+  Fsm_Ardc_Valid_c,
+  Fsm_Ardc_Converged_c,
+  Fsm_Ardc_Exact_c
+} Fsm_Ardc_StatusType_t;
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [A finite state machine.]
+
+  Description [A finite state machine.  See fsm.h for an overview of the
+  structure. Non-obvious fields are described here:
+
+  <p>the ith entry of the array reachabilityInfo.onionRings contains the set of
+  states reached in i steps from the initial states. The type of reachability
+  computation may have been approximate. Therefore the distance from the
+  initial state may not exactly be i. Further, these onion rings may not be
+  consistent with the reachable states. But their sum will always be smaller
+  than or equal to the reachableStates field.
+
+  <p>The onionRingsUpToDate field indicates whether the onion rings are
+  consistent with the reachable states.
+
+  <p>The onionRingsBFS field indicates whether onion rings were generated with
+  BFS.
+
+  <p>The depth pertains to the depth of computation with respect to the
+  reachableStates field. In case of approximate computation and reordering, the
+  depth and the exact onion rings may not be reproducible.
+
+  <p>The mode field indicates how the reachable states were generated. If they
+  were ever generated using HD, this is marked.
+
+  <p>FairnessInfo.states is the set of fair states (i.e. those states from
+  which there exists a fair path).  FairnessInfo.dbgArray is an array of
+  array_t* of mdd_t*, where the jth MDD of the ith array gives the set of
+  states that can reach the ith Buchi set in j or fewer steps.
+
+  <p>FsmData.nextStateFunctions is an array of strings, containing the names of
+  the nodes driving the data inputs of latches.
+
+  <p>presentStateVars, nextStateVars, and nextStateFunctions are all in
+  one-to-one correspondence.]
+
+******************************************************************************/
+struct FsmFsmStruct {
+  Ntk_Network_t   *network;   /* corresponding network */
+  graph_t         *partition; /* DAG of MVFs giving the next state fns */
+  Img_ImageInfo_t *imageInfo;
+  Img_ImageInfo_t *unquantifiedImageInfo;
+  bdd_t           *extQuantifyInputCube;
+  bdd_t           *uniQuantifyInputCube;
+  boolean useUnquantifiedFlag;
+  boolean FAFWFlag;
+
+  struct {
+    mdd_t *initialStates;
+    mdd_t *reachableStates; /* reachable states or an under-approximation */
+    int depth;   /* depth upto which the traversal was carried out. */
+    Fsm_RchType_t reachabilityMode;   /* indicates what mode(BFS/HD) was
+					 applied to reachability. */
+    Fsm_RchStatus_t rchStatus;  /* specified whether the reachable states is
+				   exact or an under approximation or
+				   an over aproximation. */
+    Fsm_Ardc_StatusType_t overApprox;  /* status of current overapproximate
+					  reached states. */
+    array_t *apprReachableStates; /* to store overapproximate reachable states*/
+    array_t *subPsVars;	/* to store real present state variables of submachines
+			   in over-approximate  reachability computation */
+    array_t *onionRings;   /* array of mdd_t* */
+    Fsm_RchType_t onionRingsMode; /* indicates whether onion rings were
+				generated with BFS or some approximate method */
+    boolean onionRingsUpToDate;  /* flag which indicates whether the sum of
+				    onion rings is equal to reachable states */
+  } reachabilityInfo;
+
+  struct {
+    mdd_t *states;
+    Fsm_Fairness_t *constraint;
+    array_t *dbgArray;                /* array of array_t* of mdd_t* */
+  } fairnessInfo;
+
+  struct {
+    array_t *presentStateVars;        /* array of MDD id's */
+    array_t *nextStateVars;           /* array of MDD id's */
+    array_t *inputVars;               /* array of MDD id's */
+    array_t *nextStateFunctions;      /* array of char* */
+    /* The following 3 are just for subsystems.
+     * inputVars = primaryInputVars + pseudoInputVars
+     * globalPsVars = presentStateVars + pseudoInputVars
+     */
+    array_t *pseudoInputVars;         /* array of MDD id's */
+    array_t *primaryInputVars;        /* array of MDD id's */
+    array_t *globalPsVars;            /* array of MDD id's */
+    mdd_t   *presentStateCube;
+    mdd_t   *nextStateCube;
+    mdd_t   *inputCube;
+    mdd_t   *pseudoInputCube;
+    mdd_t   *primaryInputCube;
+    mdd_t   *globalPsCube;
+    array_t *presentStateBddVars;     /* array of bdd variables */
+    array_t *pseudoInputBddVars;      /* array of bdd variables */
+    boolean createVarCubesFlag;
+  } fsmData;
+};
+
+/**Struct**********************************************************************
+
+  Synopsis [Specifies options for ARDC computation.]
+
+  Description [Specifies options for ARDC computation.]
+
+  SideEffects []
+  
+  SeeAlso []
+
+******************************************************************************/
+struct FsmArdcOptionsStruct {
+    Fsm_Ardc_TraversalType_t traversalMethod; /* one of MBM, RFBF, TFBF, TMBM,
+    						 LMBM, SIMPLE */
+    int groupSize; /* number of latches per group in state space
+                      decomposition */
+    float affinityFactor; /* controls weight between dependency and
+                             correlation in state space decomposition */
+    Img_MinimizeType constrainMethod;
+		/* which operator is going to be used for image constraining
+		** operation among restrict, constrain, compact, and squeeze */
+    Fsm_Ardc_ConstrainTargetType_t constrainTarget;
+		/* where to apply image constraining between
+                ** transition relation and initial states */
+    int maxIteration; /* maximum iteration number in approximate traversal */
+    Fsm_Ardc_AbstPpiType_t abstractPseudoInput;
+		/* when to abstract pseudo input variables
+                ** from transition relation or reachable states */
+    boolean decomposeFlag;
+		/* whether to use single conjuncted approximate reachable
+		** states or decomposed approximate reachable states */
+    boolean projectedInitialFlag; /* whether to use original initial states or
+                                     projected initial states */
+    boolean constrainReorderFlag; /* if set, allow variable reorderings
+                                     during image constraining operation */
+    Img_MethodType ardcImageMethod;
+    boolean useHighDensity; /* if set, use high density */
+    boolean reorderPtrFlag;
+    int faninConstrainMode;
+    char *readGroupFile;
+    char *writeGroupFile;
+    int lmbmInitialStatesMode;
+    boolean mbmReuseTrFlag;
+    int createPseudoVarMode;
+    int verbosity; /* print more information */
+};
+
+/**Struct**********************************************************************
+  Synopsis [Approximate Traversal option structure.]
+
+  Description [Approximate Traversal option structure. Set by set commands. See help in CommandPrintHdOptions.]
+
+  SideEffects []
+  
+  SeeAlso []
+  
+******************************************************************************/
+struct FsmHdTravOptions {
+  int nvars; /* number of bdd state variables */
+  bdd_approx_type_t frontierApproxMethod; /* type of approximation to use to extract subset of from */
+  int frontierApproxThreshold; /* threshold for approximation */
+  Fsm_HdDeadEndType_t deadEnd; /* kind of dead-end method to use */
+  bdd_approx_type_t deadEndSubsetMethod;  /* which approximation method to use in dead-ends */
+  double quality; /* quality factor for bdd_apprxo_remap_ua method */
+  double qualityBias; /* quality factor for bdd_approx_remap_ua method */
+  boolean scrapStates; /* option to not add scrap states */
+  boolean newOnly; /* option to pick frontier from the new states only */
+  boolean onlyPartialImage; /* option to only use partial image computation */
+};
+
+
+/**Struct**********************************************************************
+  Synopsis [Stats structure to store size and minterm count]
+
+  Description [Stats structure to store size and minterm count]
+
+  SideEffects []
+  
+  SeeAlso []
+   
+******************************************************************************/
+struct FsmHdMintSizeStats {
+  int sizeTo;  /* size of image */
+  double mintermTo; /* minterms of image */
+  int sizeFrom; /* size of from (frontier) */
+  double mintermFrom; /* minterms of from (frontier) */
+  int sizeFromSubset; /* size of subset of frontier */
+  double mintermFromSubset; /* minterms of subset of frontier */
+  int sizeReached; /* size of reached set */
+  double mintermReached; /* minterms of reached set */
+};  
+
+
+/**Struct**********************************************************************
+  Synopsis [Structure to store HD related information.]
+
+  Description [Structure to store HD related information.]
+
+  SideEffects []
+  
+  SeeAlso []
+   
+******************************************************************************/
+struct FsmHdStruct {
+  int numDeadEnds; /* number of dead computations performed. */
+  boolean firstSubset; /* indicates that first subset has been computed*/
+  int lastIter;    /* indicates the last iteration in which a slow growth
+		    * of reached was recorded. */
+  boolean partialImage;/* iff partial image computation was performed */
+  int residueCount;/* number of times the residue has been used in a dead end*/
+  mdd_t *interiorStates; /* states which cannot produce any new states */
+  mdd_t *interiorStateCandidate; /* states which could potentially belong to
+				  * interior states. */
+  mdd_t *deadEndResidue; /*  states which do not lie in dense subset
+			  * of "from" after dead-end computation */
+  struct FsmHdTravOptions *options;	/* options for HD traversal */
+  struct FsmHdMintSizeStats *stats; /* structure storing minterms and sizes of the 
+				* various BDDs of traversal.
+				*/
+  boolean imageOfReachedComputed;  /* iff image of reached set was computed.*/
+  boolean onlyPartialImage;    /* flag indicating that only partial image
+				* should be used during traversal. */
+  int slowGrowth;  /* number of successive iterations of slow growth of
+		    * reached */
+
+  boolean deadEndWithOriginalTR; /* this flag allows computing a dead end at
+					  * the end if all the frontier under the original
+					  * TR is generated at some point. */
+  boolean deadEndComputation;
+};
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef struct FsmHdMintSizeStats FsmHdMintSizeStats_t;
+typedef struct FsmHdStruct FsmHdStruct_t;
+
+/**Struct**********************************************************************
+  Synopsis [Enumerated type to specify various quantities in HD]
+******************************************************************************/
+typedef enum {
+    Fsm_Hd_From,
+    Fsm_Hd_To,
+    Fsm_Hd_FromSubset,
+    Fsm_Hd_Reached
+} Fsm_Hd_Quant_t;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+  Synopsis [Read Minterms of Reached from stats structure]
+
+******************************************************************************/
+#define FsmHdStatsReadMintermReached(stats) (stats->mintermReached)
+
+/**Struct**********************************************************************
+  Synopsis [Read Minterms of To from stats structure]
+
+******************************************************************************/
+#define FsmHdStatsReadMintermTo(stats) (stats->mintermTo)
+
+/**Struct**********************************************************************
+  Synopsis [Read Minterms of From from stats structure]
+
+******************************************************************************/
+#define FsmHdStatsReadMintermFrom(stats) (stats->mintermFrom)
+
+/**Struct**********************************************************************
+  Synopsis [Read Minterms of FromSubset from stats structure]
+
+******************************************************************************/
+#define FsmHdStatsReadMintermFromSubset(stats) (stats->mintermFromSubset)
+
+/**Struct**********************************************************************
+  Synopsis [Read Size of Reached from stats structure]
+
+******************************************************************************/
+#define FsmHdStatsReadSizeReached(stats) (stats->sizeReached)
+
+/**Struct**********************************************************************
+  Synopsis [Read Size of To from stats structure]
+
+******************************************************************************/
+#define FsmHdStatsReadSizeTo(stats) (stats->sizeTo)
+
+/**Struct**********************************************************************
+  Synopsis [Read Size of From from stats structure]
+
+******************************************************************************/
+#define FsmHdStatsReadSizeFrom(stats) (stats->sizeFrom)
+
+/**Struct**********************************************************************
+  Synopsis [Read Size of FromSubset from stats structure]
+
+******************************************************************************/
+#define FsmHdStatsReadSizeFromSubset(stats) (stats->sizeFromSubset)
+
+/**Struct**********************************************************************
+  Synopsis [Read Density of From from stats structure]
+
+******************************************************************************/
+#define FsmHdStatsReadDensityFrom(stats) \
+              (FsmHdStatsReadMintermFrom(stats)/FsmHdStatsReadSizeFrom(stats))
+
+/**Struct**********************************************************************
+  Synopsis [Read Density of FromSubset from stats structure]
+
+******************************************************************************/
+#define FsmHdStatsReadDensityFromSubset(stats) \
+  (FsmHdStatsReadMintermFromSubset(stats)/FsmHdStatsReadSizeFromSubset(stats))
+
+/**Struct**********************************************************************
+  Synopsis [Read Density of Reached from stats structure]
+
+******************************************************************************/
+#define FsmHdStatsReadDensityReached(stats) \
+        (FsmHdStatsReadMintermReached(stats)/FsmHdStatsReadSizeReached(stats))
+
+/**Struct**********************************************************************
+  Synopsis [Set Size of From from stats structure]
+
+******************************************************************************/
+#define FsmHdStatsSetSizeFrom(stats, value) (stats->sizeFrom = value)
+
+/**Struct**********************************************************************
+  Synopsis [Set Minterm of From from stats structure]
+
+******************************************************************************/
+#define FsmHdStatsSetMintermFrom(stats, value) (stats->mintermFrom = value)
+
+/**Struct**********************************************************************
+  Synopsis [Set Size of FromSubset from stats structure]
+
+******************************************************************************/
+#define FsmHdStatsSetSizeFromSubset(stats, value) \
+                                   (stats->sizeFromSubset = value)
+
+/**Struct**********************************************************************
+  Synopsis [Set Minterm of FromSubset from stats structure]
+
+******************************************************************************/
+#define FsmHdStatsSetMintermFromSubset(stats, value) \
+                                      (stats->mintermFromSubset = value)
+
+/**Struct**********************************************************************
+  Synopsis [Set Size of Reached from stats structure]
+
+******************************************************************************/
+#define FsmHdStatsSetSizeReached(stats, value) (stats->sizeReached = value)
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN int FsmArdcCheckInvariant(Fsm_Fsm_t *fsm, array_t *invarStates);
+EXTERN void FsmArdcPrintOptions(void);
+EXTERN void FsmArdcPrintOverApproximateReachableStates(Fsm_Fsm_t *fsm);
+EXTERN void FsmArdcPrintExactReachableStates(Fsm_Fsm_t *fsm);
+EXTERN void FsmArdcPrintBddOfNode(Fsm_Fsm_t *fsm, mdd_t *node);
+EXTERN void FsmArdcPrintArrayOfArrayInt(array_t *arrayOfArray);
+EXTERN boolean FsmGetArdcSetBooleanValue(char *string, boolean defaultValue);
+EXTERN Fsm_Fairness_t * FsmFsmCreateDefaultFairnessConstraint(Fsm_Fsm_t *fsm);
+EXTERN boolean FsmFairnessConstraintIsDefault(Fsm_Fairness_t *fairness);
+EXTERN void FsmFairnessFree(Fsm_Fairness_t *fairness);
+EXTERN Fsm_Fairness_t * FsmFairnessAlloc(Fsm_Fsm_t *fsm);
+EXTERN void FsmFairnessAddConjunct(Fsm_Fairness_t *fairness, Ctlp_Formula_t *finallyInf, Ctlp_Formula_t *globallyInf, int i, int j);
+EXTERN void FsmFsmFairnessInfoUpdate(Fsm_Fsm_t *fsm, mdd_t *states, Fsm_Fairness_t *constraint, array_t *dbgArray);
+EXTERN void FsmSetReachabilityOnionRings(Fsm_Fsm_t *fsm, array_t *onionRings);
+EXTERN void FsmSetReachabilityOnionRingsMode(Fsm_Fsm_t *fsm, Fsm_RchType_t value);
+EXTERN void FsmSetReachabilityOnionRingsUpToDateFlag(Fsm_Fsm_t *fsm, boolean value);
+EXTERN void FsmSetReachabilityApproxComputationStatus(Fsm_Fsm_t *fsm, Fsm_RchStatus_t value);
+EXTERN void FsmSetReachabilityOverApproxComputationStatus(Fsm_Fsm_t *fsm, Fsm_Ardc_StatusType_t status);
+EXTERN Fsm_Ardc_StatusType_t FsmReadReachabilityOverApproxComputationStatus(Fsm_Fsm_t *fsm);
+EXTERN void FsmSetReachabilityComputationMode(Fsm_Fsm_t *fsm, Fsm_RchType_t value);
+EXTERN Fsm_RchType_t FsmReadReachabilityComputationMode(Fsm_Fsm_t *fsm);
+EXTERN void FsmResetReachabilityFields(Fsm_Fsm_t *fsm, Fsm_RchType_t approxFlag);
+EXTERN FsmHdStruct_t * FsmHdStructAlloc(int nvars);
+EXTERN void FsmHdStructFree(FsmHdStruct_t *hdInfo);
+EXTERN void FsmGuidedSearchPrintOptions(void);
+EXTERN FsmHdMintSizeStats_t * FsmHdStatsStructAlloc(void);
+EXTERN void FsmHdStatsStructFree(FsmHdMintSizeStats_t *stats);
+EXTERN void FsmHdStatsComputeSizeAndMinterms(mdd_manager *mddManager, mdd_t *f, array_t *varArray, int nvars, Fsm_Hd_Quant_t field, FsmHdMintSizeStats_t *stats);
+EXTERN void FsmHdStatsReset(FsmHdMintSizeStats_t *stats, Fsm_Hd_Quant_t field);
+EXTERN void FsmHdPrintOptions(void);
+EXTERN mdd_t * FsmHdDeadEnd(mdd_manager *mddManager, Img_ImageInfo_t *imageInfo, mdd_t *reachableStates, FsmHdStruct_t *hdInfo, array_t *varArray, int greedy, int verbosity);
+EXTERN void FsmHdFromComputeDenseSubset(mdd_manager *mddManager, mdd_t **fromLowerBound, mdd_t **fromUpperBound, mdd_t **reachableStates, mdd_t **image, mdd_t *initialStates, FsmHdStruct_t *hdInfo, int shellFlag, array_t *onionRings, int sizeOfOnionRings, array_t *varArray);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _FSMINT */
Index: vis_dev/vis-2.3/src/fsm/fsmReach.c
===================================================================
--- vis_dev/vis-2.3/src/fsm/fsmReach.c	(revision 14)
+++ vis_dev/vis-2.3/src/fsm/fsmReach.c	(revision 14)
@@ -0,0 +1,2134 @@
+/**CFile***********************************************************************
+
+  FileName    [fsmReach.c]
+
+  PackageName [fsm]
+
+  Synopsis    [Routines to perform reachability on the FSM structure.]
+
+  Author      [Rajeev K. Ranjan, In-Ho Moon, Kavita Ravi]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "fsmInt.h"
+#include "bdd.h"
+#include "ntm.h"
+#include "img.h"
+#include "sim.h"
+
+static char rcsid[] UNUSED = "$Id: fsmReach.c,v 1.102 2009/04/11 01:40:54 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+/* HD constants */
+#define FSM_HD_NONGREEDY 0 /* flag to indicate non-greedy computation at
+			      dead-ends */
+#define FSM_HD_GREEDY 1 /* flag to indicate greedy computation at dead-ends */
+#define FSM_HD_LARGE_SIZE 100000 /* size considered large for reached */
+#define FSM_HD_MID_SIZE 50000    /* size considered medium for reached*/
+#define FSM_HD_MINT_GROWTH 0.5   /* factor measuring minterm jump of reached*/
+#define FSM_HD_GROWTH_RATE 0.04 /* Growth rate for reached in measuring slow
+				 * growth. */
+#define FSM_MDD_DONT_FREE 0  /* flag to indicate that bdd should not be freed. */
+#define FSM_MDD_FREE 1       /* flag to indicate that bdd should be freed.*/
+#define FSM_HD_NUM_SLOW_GROWTHS 5 /* number of iterations of allowed
+				   * slow growth of reached. */
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CheckImageValidity(mdd_manager *mddManager, mdd_t *image, array_t *domainVarMddIdArray, array_t *quantifyVarMddIdArray);
+static int ComputeNumberOfBinaryStateVariables(mdd_manager *mddManager, array_t *mddIdArray);
+static mdd_t * AddStates(mdd_t *a, mdd_t *b, int freeA, int freeB);
+static void RandomSimulation(int simNVec, Fsm_Fsm_t *fsm, Fsm_RchType_t approxFlag, mdd_t *initialStates, mdd_t **reachableStates, mdd_t **fromLowerBound, FsmHdStruct_t *hdInfo);
+static void PrintStatsPerIteration(Fsm_RchType_t approxFlag, int nvars, int depth, FsmHdStruct_t *hdInfo, mdd_manager *mddManager, mdd_t *reachableStates, mdd_t *fromLowerBound, array_t *mintermVarArray);
+static void HdInduceFullDeadEndIfNecessary(mdd_manager *mddManager, Img_ImageInfo_t *imageInfo, mdd_t **fromLowerBound, mdd_t **fromUpperBound, mdd_t **reachableStates, mdd_t **image, FsmHdStruct_t *hdInfo, int *depth, int shellFlag, array_t *onionRings, array_t *mintermVarArray, int oldSize, double oldMint, int verbosityLevel);
+static mdd_t * ComputeInitialStates(Fsm_Fsm_t *fsm, int shellFlag, boolean printWarning);
+static int CheckStatesContainedInInvariant(mdd_t *reachableStates, array_t *invarStates);
+static void HdComputeReachabilityParameters(mdd_manager *mddManager, Img_ImageInfo_t *imageInfo, mdd_t **reachableStates, mdd_t **fromUpperBound, mdd_t **fromLowerBound, mdd_t **image, FsmHdStruct_t *hdInfo, mdd_t *initialStates, array_t *mintermVarArray, int *depth, int printStep, int shellFlag, array_t *onionRings, int verbosityLevel);
+static int InitializeIncrementalParameters(Fsm_Fsm_t *fsm, Ntk_Network_t *network, array_t **arrayOfRoots, st_table **tableOfLeaves);
+static mdd_t * IncrementalImageCompute(Ntk_Network_t *network, Fsm_Fsm_t *fsm, mdd_manager *mddManager, mdd_t *fromLowerBound, mdd_t *fromUpperBound, mdd_t *toCareSet, array_t *arrayOfRoots, st_table *tableOfLeaves, array_t *smoothVarArray, array_t *relationArray, int numLatch);
+static void PrintOnionRings(Fsm_Fsm_t *fsm, int printStep, Fsm_RchType_t approxFlag, int nvars);
+static array_t * GenerateGuidedSearchSequenceArray(array_t *guideArray);
+static void ComputeReachabilityParameters(mdd_manager *mddManager, Img_ImageInfo_t *imageInfo, Fsm_RchType_t approxFlag, mdd_t **reachableStates, mdd_t **fromUpperBound, mdd_t **fromLowerBound, mdd_t **image, FsmHdStruct_t *hdInfo, mdd_t *initialStates, array_t *mintermVarArray, int *depth, int printStep, int shellFlag, array_t *onionRings, int verbosityLevel, boolean guidedSearchMode, mdd_t *hint, int *hintDepth, boolean *notConverged);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis [Computes the set of reachable states of an FSM.]
+
+  Description [Computes the set of reachable states of an FSM.  If
+  this set has already been computed, then just returns the result of
+  the previous computation. The recomputation is done anyway if onion
+  rings are required and have not been previously computed. The
+  calling application is responsible for freeing the returned MDD in
+  all cases.  If verbosityLevel is greater than 1, then information is
+  printed after every k steps of reachability, where k is defined by
+  the -s option in the compute_reach command (the default for k is
+  1). If reorderFlag is set, then dynamic reordering is invoked once
+  when the size of the reachable state set reaches the threshold given
+  by reorderThreshold.  This is independent of the
+  dynamic_variable_reordering command. The shell flag indicates that
+  the onion rings of frontier states should be stored. The default
+  does not store the onion rings. The default value for approxFlag is
+  Fsm_Rch_Default_c. See fsm.h for values.
+
+  The procedure offers the following variations of reachability
+  analysis: 1. Exact Reachability analysis by breadth-first search
+  (default). 2. Reachability Analysis (HD) . 3. Reachability Analysis
+  (upper bound by overapproximate FSM traversal). 4 ARDC-accelerated
+  Reachability Analysis.  5. Invariant checking with early termination.
+
+  A lower bound (specified by depthValue) on the reachable states may
+  be obtained by performing a specified number of iterations
+  (depthValue argument). It updates a field in the
+  fsm.reachabilityInfo signalling that the reachable states are an
+  under approximation. The default for the depthValue argument is 0
+  which indicates that reachability analysis computation should
+  proceed to a fixpoint. If a depthValue is specified after the
+  computation of reachable states, the reachable states is returned,
+  else depthValue number of computations are performed. Every non-zero
+  depthValue is interpreted as the number of iterations (image
+  computations) to be performed from the current state (not from the
+  initial state).
+
+  Reachability Analysis (HD) is requested as approxFlag =  Fsm_Rch_Hd_c.
+  HD provides an exact set of reachable states with memory efficiency or
+  a lower bound if reachability analysis does not complete.
+  HD Principles: 1. compute image of small BDDs. 2. compute partial
+  image if necessary 3. When no new states are generated (dead-end),
+  compute new states from image of reached in a decomposed form.  Allow
+  no partial image.  4. When there is a big jump in the size of
+  reached, compute its entire image.  5. store states that will
+  produce no new successors (interior states)
+
+  The algorithm is implemented as follows
+  from = init; reached = init;
+  while (reached != 1 && from != 0) {
+    Allow partial image;
+    image = Image(from);
+    Check if partial image;
+    from = image - reached;
+    if (!partial image) interior_states_candidate = from;
+    if (from == 0 || slow growth of Reached for 5 iterations) {
+      Dead-end computation(greedy): find new states from image of reached;
+    }
+    if (from != 0 and (reached+from) size has a big jump) {
+      Dead-end computation(non-greedy): find the entire image of reached;
+    }
+    if (from != 0) {
+      Compute dense subset of from with at least 1 new state;
+      if subset contains from (i.e., all new states)
+		       interior states += interior states candidate;
+      reached = reached + from/subset;
+    }
+  }
+
+  Legend:  fromLowerBound = from; initialStates = init;
+	   reachableStates = reached
+	   fromUpperBound = reachableStates (BFS)/fromLowerBound(HD)
+	   interiorStates = states with no new successors
+	   interiorStateCandidates = states that may be interior
+		  states depending on whether all of them are added to
+		  reachableStates.
+
+  Currently, this does not support the incrementalFlag = 1 option.
+
+  Reachability Analysis (upper bound by overapproximate FSM traversal)
+  gives an upper bound of exact reachable states by overapproximation.
+  It is requested as approxFlag = Fsm_Rch_Oa_c. To do this, first, it
+  groups latch variables by using SSD(State Space Decomposition in the
+  paper Cho et.al, TCAD96-DEC) algorithm, then computes the reachable
+  states of each submachines until convergence, then the product of
+  reachable states of all submachines is an overapproximate reachable
+  states. In this case, depthValue and shellFlag and incrementalFlag
+  are incompatible with this option.
+
+  ARDC-accelerated Reachability Analysis may allow faster and smaller
+  memory usage reachability analysis. First, it computes
+  overapproximated reachable states (if already computed, just use it).
+  Reachability Analysis is then performed (any value of approxFlag is
+  applicable) with a transition relation minimized with the complement
+  of overapproximate reachable states as don't cares (called
+  ARDC). This option is requested as ardc = 1.
+
+  invarStates is a set of invariant states that can be specified. The
+  reachable states must satisfy all invariants. The default value is
+  NULL. Any invalid invariant must also be set to NULL in the
+  invarStaes array. This option is used by the check_invariant
+  command. When an array of invariant states is provided, reachability
+  analysis is done until an invariant is violated or when reachability
+  finishes, whichever is earlier. If an approximation of the reachable
+  states exists, then each invariant is checked for violation. If none
+  are violated, the set of reachable states is returned. It is the
+  caller's resposibility to remove the violating invariant from the
+  invarStates array to continue checking the remaining
+  invariants. The presence of invarStates takes precedence over a
+  non-zero depthValue.
+
+  In general, the reachable states may not be consistent with the
+  onion rings i.e., sum of onion rings is always contained in the
+  reachable states.  When the shell flag is specified and onion rings
+  exist, the initial states are set to the sum of the onion ring
+  states instead of the default initial states of the fsm or
+  previously computed reachable states.
+
+  Some random simulation of the reachable states can be done prior to
+  reachability analysis. This is turned on using the rch_simulate
+  flag. A number should be specifed in the command : set sim_reach
+  <number>, which specifies the number of vectors to be simulated.
+  The initial states are then set to the simulated set of states. If
+  HD is specified, a subset may be taken.
+
+  The recompute flag asks for an explicit recomputation. This means
+  that even reachable states have been computed, they will be
+  recomputed.
+
+  On consecutive calls, recomputation is avoided as much as
+  possible. The specific cases are when
+  Case a. No shell Flag: Recomputation is avoided when reachability is
+  done, when an underapproximation exists and it violates an
+  invariant,  an overapproximation exists and all invariants pass.
+
+  Case b. With shell flag: Recomputation is avoided when onion rings
+  are up-to-date and reachability is done or when onion rings are
+  up-to-date, an underapproximation exists and an invariant fails.
+
+  Update of fsm.reachabiltiyInfo fields are also based on minimum
+  recomputation. The reachability field is updated only if the current
+  set of reachable states are larger than the previous set.
+
+  printWarning flag turns is used to turn on/off the warning message
+  printed when the previously computed reachable states are used to
+  proceed with computation. The default is TRUE.  ]
+
+  SideEffects [The result of the reachable state computation is stored
+  with the FSM. i.e., depth, reachable set, underapprox flag. ]
+
+  SeeAlso [Fsm_FsmComputeInitialStates
+  Fsm_ArdcComputeOverApproximateReachableStates]
+
+******************************************************************************/
+mdd_t *
+Fsm_FsmComputeReachableStates(
+  Fsm_Fsm_t *fsm,
+  int incrementalFlag,
+  int verbosityLevel,
+  int printStep,
+  int depthValue,
+  int shellFlag,
+  int reorderFlag,
+  int reorderThreshold,
+  Fsm_RchType_t approxFlag,
+  int ardc,
+  int recompute,
+  array_t *invarStates,
+  boolean printWarning,
+  array_t *guideArray)
+{
+  /* BFS variables */
+  Img_ImageInfo_t *imageInfo = NIL(Img_ImageInfo_t); /* image info structure*/
+  Img_ImageInfo_t *oldImageInfo = NIL(Img_ImageInfo_t);
+  mdd_t           *reachableStates;/* reachable states */
+  mdd_t           *unreachableStates;
+  mdd_t           *fromLowerBound; /* new states in each iteration */
+  mdd_t           *fromUpperBound; /* set to reachable states */
+  mdd_t           *image, *newImage;/* image computed at each iteration */
+  mdd_t           *initialStates;  /* initial states */
+  mdd_t           *toCareSet;      /* the complement of the reached set */
+  int              depth = 0;      /* depth upto which the computation is
+				    * performed.
+				    */
+  graph_t         *partition, *oldPartition;
+  mdd_manager     *mddManager = Fsm_FsmReadMddManager(fsm); /* mdd manager */
+  Ntk_Network_t   *network = fsm->network; /* network */
+  bdd_reorder_type_t currentMethod =
+    Ntk_NetworkReadDynamicVarOrderingMethod(network); /* current reordering
+						       * method */
+  int firstTimeFlag = TRUE, firstReorderFlag = FALSE;
+			 /* a flag to indicate the start of the computation */
+  Fsm_RchStatus_t rchStatus = Fsm_Rch_Under_c;
+			 /* under approximation of the reached set computed */
+  int reachableStateSetSize; /* bdd size of the reached set */
+  array_t *mintermVarArray; /* array of present state variables */
+  array_t *onionRings = NIL(array_t);
+			    /* onionringarray for shellFlag computation */
+
+  /* Incremental flag  variables */
+  array_t *arrayOfRoots = NIL(array_t);
+  st_table *tableOfLeaves = NIL(st_table);
+  int numLatch = 0;
+  array_t *relationArray = NIL(array_t), *smoothVarArray = NIL(array_t);
+
+  boolean notConverged = FALSE; /* flag that says that the fixpoint procedure
+				   did not converge. */
+  /* HD variables */
+  FsmHdStruct_t *hdInfo = NULL;
+  int nvars;       /* number of present state variables */
+
+
+  /* Simulation variables */
+  int simNVec = 0;                 /* number of simulation vectors. */
+  char *simString = Cmd_FlagReadByName("rch_simulate");
+
+  /* Guided Search */
+  array_t *hintDepthArray = NIL(array_t);
+  int hintDepth = -1;
+  mdd_t   *hint = NIL(mdd_t); /* iterates over guide array */
+  int      hintnr;            /* idem                      */
+  boolean guidedSearchMode = FALSE;
+  boolean guideArrayAllocated = FALSE;
+
+  boolean invariantFailed = FALSE;
+
+  /* initializations */
+  /* if fsm is a submachine, takes realPsVars to count minterm correctly. */
+  mintermVarArray = Fsm_FsmReadPresentStateVars(fsm);
+
+  /* compute number of present state variables */
+  nvars = ComputeNumberOfBinaryStateVariables(mddManager, mintermVarArray);
+  assert(nvars > 0);
+
+  /* initializations */
+  if (recompute) {
+    if (incrementalFlag &&
+	((approxFlag == Fsm_Rch_Hd_c) || (approxFlag == Fsm_Rch_Oa_c))) {
+      fprintf(vis_stdout,
+	      "** rch error: Incremental flag and HD computation are not compatible\n");
+      return NIL(mdd_t);
+    }
+    FsmResetReachabilityFields(fsm, approxFlag);
+  } else if ((!shellFlag) || Fsm_FsmTestReachabilityOnionRingsUpToDate(fsm)) {
+    /* If already computed and exact , just return a copy. */
+    reachableStates = Fsm_FsmReadReachableStates(fsm);
+    if (reachableStates != NIL(mdd_t)){
+      if (printWarning) {
+	fprintf(vis_stdout, "** rch info: Reachable states have been previously computed.\n");
+	fprintf(vis_stdout, "** rch info: Not recomputing reachable states.\n");
+	fprintf(vis_stdout, "** rch info: Use compute_reach -F to recompute if necessary.\n");
+      }
+      if (!shellFlag) {
+	if (printWarning) {
+	  if (FsmReadReachabilityComputationMode(fsm) == Fsm_Rch_Bfs_c) {
+	    fprintf(vis_stdout, "** rch info: All previous computations done using BFS (-A 0 option).\n");
+	  } else {
+	    fprintf(vis_stdout, "** rch info: Some previous computations done using BFS/DFS mode (-A 1 or -g option).\n");
+	  }
+	}
+	return (mdd_dup(reachableStates));
+      } else if (Fsm_FsmReadReachabilityOnionRings(fsm)) {
+	/* if onion rings exist, since they are up-to-date, return the
+	 * reachable states
+	 */
+	if (printWarning) {
+	  if (Fsm_FsmReadReachabilityOnionRingsMode(fsm) == Fsm_Rch_Bfs_c) {
+	    fprintf(vis_stdout, "** rch info: Onion rings have been computed using BFS (-A 0 option)\n");
+	  } else {
+	    fprintf(vis_stdout, "** rch info: Some onion rings have been computed using BFS/DFS (-A 1 or -g option)\n");
+	  }
+	}
+	if (printStep)
+	  PrintOnionRings(fsm, printStep, approxFlag, nvars);
+	return (mdd_dup(reachableStates));
+      }
+    }
+
+    /* if some computed states exist and they violate an invariant,
+       return the current set of reachable states */
+    reachableStates = Fsm_FsmReadCurrentReachableStates(fsm);
+    if (reachableStates != NIL(mdd_t)) {
+      if (!shellFlag) {
+	/* if an underApprox  exists, check invariant, if any */
+	if (invarStates != NIL(array_t)) {
+	  if (!CheckStatesContainedInInvariant(reachableStates, invarStates)) {
+	    if (printWarning) {
+	      fprintf(vis_stdout, "** rch info: Invariant violation using previously computed states\n");
+	    }
+	    /* return violating reachable states */
+	    return (mdd_dup(reachableStates));
+	  }
+	}
+      } else if (Fsm_FsmReadReachabilityOnionRings(fsm)) {
+	/* an invariant fails. */
+	if (invarStates != NIL(array_t)) {
+	  if (!CheckStatesContainedInInvariant(reachableStates, invarStates)) {
+	    if (printWarning) {
+	      fprintf(vis_stdout, "** rch info: Invariant violation using previously computed states\n");
+	      if (Fsm_FsmReadReachabilityOnionRingsMode(fsm) == Fsm_Rch_Bfs_c) {
+		fprintf(vis_stdout, "** rch info: Previous onion rings computed in BFS (-A 0 option).\n");
+	      } else {
+		fprintf(vis_stdout, "** rch info: Some set of onion rings have been computed using BFS/DFS (-A 1 or -g option)\n");
+	      }
+	      fprintf(vis_stdout, "** rch info: Use compute_reach -F to recompute if necessary.\n");
+	    }
+	    if (printStep) {
+	      PrintOnionRings(fsm, printStep, approxFlag, nvars);
+	    }
+	    return (mdd_dup(reachableStates));
+	  }
+	}
+      }
+    }
+    /* if an over approx exists, check invariant, if any */
+    if ((invarStates != NIL(array_t)) && (!shellFlag) && (!depthValue) &&
+	(Fsm_FsmReadOverApproximateReachableStates(fsm)
+	 != NIL(array_t))) {
+      if (FsmArdcCheckInvariant(fsm, invarStates)) {
+	fprintf(vis_stdout, "** rch info: Over approximation exists, using over approximation for invariant checking.\n");
+	 return(Fsm_ArdcGetMddOfOverApproximateReachableStates(fsm));
+      }
+    }
+
+    if (incrementalFlag &&
+	((approxFlag == Fsm_Rch_Hd_c) || (approxFlag == Fsm_Rch_Oa_c))) {
+      fprintf(vis_stdout,
+	      "** rch error: Incremental flag and HD computation are not compatible\n");
+
+      return NIL(mdd_t);
+    }
+  }
+  /* onion rings make no sense with Over approx */
+  if (shellFlag && (approxFlag == Fsm_Rch_Oa_c)) {
+    fprintf(vis_stdout, "** rch error: Can't generate onion rings with over approx\n");
+    return NIL(mdd_t);
+  }
+
+  /* depth value makes no sense with over approximation */
+  if (depthValue && (approxFlag == Fsm_Rch_Oa_c)) {
+    fprintf(vis_stdout, "** rch error: Can't generate over approx with depth Value\n");
+    return NIL(mdd_t);
+  }
+
+  /* guided search cannot be done with Over approximation */
+  if ((guideArray != NIL(array_t)) && (approxFlag == Fsm_Rch_Oa_c)) {
+    fprintf(vis_stdout, "Guided search is not implemented with Over approximations\n");
+    return NIL(mdd_t);
+  }
+
+  /* initializations */
+  reachableStateSetSize = 0;
+  if ((approxFlag == Fsm_Rch_Hd_c) || (guideArray != NIL(array_t))) {
+    /* this structure is needed for HD and guidedSearch */
+    hdInfo = FsmHdStructAlloc(nvars);
+  }
+
+  simNVec = 0;
+  if (simString != NIL(char)) {
+    simNVec = strtol(simString, NULL, 10);
+    if (simNVec <= 0)  simNVec = 0;
+  }
+  /* initialize onion ring array */
+  if (shellFlag) {
+    if (Fsm_FsmReadReachabilityOnionRings(fsm) == NIL(array_t)) {
+      onionRings = array_alloc(mdd_t *, 0);
+    } else {
+      onionRings = Fsm_FsmReadReachabilityOnionRings(fsm);
+    }
+  }
+
+  /* Computes ARDCs, and  overapproximation by SSD traversal, if required. */
+  if (approxFlag == Fsm_Rch_Oa_c || ardc) {
+    long initialTime = 0;
+    long finalTime;
+
+    assert(!incrementalFlag);
+
+    if (verbosityLevel > 0)
+      initialTime = util_cpu_time();
+
+    (void)Fsm_FsmComputeOverApproximateReachableStates(fsm, incrementalFlag,
+	verbosityLevel, printStep, depthValue, shellFlag, reorderFlag,
+	reorderThreshold, recompute);
+
+    if (approxFlag == Fsm_Rch_Oa_c) {
+      if (hdInfo != NIL(FsmHdStruct_t)) FsmHdStructFree(hdInfo);
+      return(Fsm_ArdcGetMddOfOverApproximateReachableStates(fsm));
+    }
+
+    if (verbosityLevel > 0) {
+      finalTime = util_cpu_time();
+      Fsm_ArdcPrintReachabilityResults(fsm, finalTime-initialTime);
+    }
+  }
+
+  if(Cmd_FlagReadByName("linear_compute_range")) {
+    partition = Part_NetworkCreatePartition(network, 0, "temp", (lsList)0,
+	(lsList)0, NIL(mdd_t), Part_Fine_c, 0, 0, 0, 0);
+    oldPartition = fsm->partition;
+    oldImageInfo = fsm->imageInfo;
+    fsm->imageInfo = 0;
+    imageInfo = Fsm_FsmReadOrCreateImageInfoForComputingRange(fsm, 0, 1);
+    unreachableStates = Img_ImageGetUnreachableStates(imageInfo);
+    fprintf(vis_stdout, "%-20s%10g\n", "reachable states =",
+		     mdd_count_onset(mddManager, unreachableStates,
+				     fsm->fsmData.presentStateVars));
+    fflush(vis_stdout);
+    /* get unreachable states */
+    Img_ImageInfoFree(imageInfo);
+    fsm->imageInfo = oldImageInfo;
+    fsm->partition = oldPartition;
+    Part_PartitionFree(partition);
+    exit(0);
+  }
+  /* Compute the set of initial states. Start with the
+   * underapproximation of Reached states if it exists or sum of
+   * onion rings if shell flag is specified or the initial states of
+   * the fsm.
+   */
+  initialStates = ComputeInitialStates(fsm, shellFlag, printWarning);
+  if (initialStates == NIL(mdd_t)) {
+    fprintf(vis_stdout, "** rch error: No initial states computed.");
+    fprintf(vis_stdout, " No reachability will be performed.\n");
+    if (hdInfo != NIL(FsmHdStruct_t)) FsmHdStructFree(hdInfo);
+    return NIL(mdd_t);
+  }
+
+  if (incrementalFlag){
+    /* Note: if incrementalflag is set, no imageinfo is created! */
+    numLatch = InitializeIncrementalParameters(fsm, network, &arrayOfRoots,
+					       &tableOfLeaves);
+    smoothVarArray = array_join(fsm->fsmData.presentStateVars,
+				fsm->fsmData.inputVars);
+    relationArray = array_alloc(mdd_t *, numLatch+1);
+  } else {
+    /* Create an imageInfo for image computations, if not already created. */
+    imageInfo = Fsm_FsmReadOrCreateImageInfo(fsm, 0, 1);
+    if (ardc) {
+      Fsm_ArdcMinimizeTransitionRelation(fsm, Img_Forward_c);
+    }
+  }
+
+  /* Get approximate traversal options */
+  if ((!incrementalFlag) && (approxFlag == Fsm_Rch_Hd_c)) {
+    /* only partial image allowed. No approximation of frontier set */
+    hdInfo->onlyPartialImage =  Fsm_FsmHdOptionReadOnlyPartialImage(hdInfo->options);
+    /* states which can produce no new successors. */
+    hdInfo->interiorStates = bdd_zero(mddManager);
+  }
+
+  /* pertaining to simulation */
+  if (simNVec > 0) {
+    RandomSimulation(simNVec, fsm, approxFlag, initialStates,
+		     &reachableStates, &fromLowerBound, hdInfo);
+  } else {
+    /* start reached set with initial states */
+    reachableStates = mdd_dup(initialStates);
+    fromLowerBound = mdd_dup(reachableStates);
+  }
+
+  /* initialize variables to print */
+  if ((!incrementalFlag) && (approxFlag == Fsm_Rch_Hd_c)) {
+
+    FsmHdStatsComputeSizeAndMinterms(mddManager, reachableStates,
+			   mintermVarArray, nvars,
+			   Fsm_Hd_Reached, hdInfo->stats);
+    FsmHdStatsComputeSizeAndMinterms(mddManager, fromLowerBound,
+			   mintermVarArray, nvars,
+			   Fsm_Hd_From, hdInfo->stats);
+    FsmHdStatsSetMintermFromSubset(hdInfo->stats, FsmHdStatsReadMintermFrom(hdInfo->stats));
+    FsmHdStatsSetSizeFromSubset(hdInfo->stats, FsmHdStatsReadSizeFrom(hdInfo->stats));
+  }
+
+  if (printStep && ((depth % printStep) == 0) && (approxFlag == Fsm_Rch_Hd_c)){
+    fprintf(vis_stdout, "\nIndex: R = Reached; I = Image, F = Frontier, FA = Approximation of Frontier\n");
+    fprintf(vis_stdout, "       f = Minterms in f; |f| = Bdd nodes in f\n\n");
+  }
+  /* initialize for the first iteration */
+   fromUpperBound = reachableStates;
+
+  /* hint array */
+  if (guideArray == NIL(array_t)) {
+    guideArray = array_alloc(mdd_t *, 0);
+    guideArrayAllocated = TRUE;
+  }
+  /* pad with 1 when no hints are provided */
+  if (array_n(guideArray) == 0) {
+    array_insert_last(mdd_t *, guideArray, bdd_one(mddManager));
+  }
+  /* depth sequence for hints. 1-to-1 correspondence with guidearray */
+  /* -1 implies apply hint to convergence. */
+  hintDepthArray = GenerateGuidedSearchSequenceArray(guideArray);
+
+  assert(array_n(hintDepthArray) == array_n(guideArray));
+
+  if (array_n(guideArray) == 0) hint = mdd_one(mddManager);
+
+  arrayForEachItem(mdd_t *, guideArray, hintnr, hint){
+
+    /* check the depth for which this hint is to be applied. */
+    hintDepth = array_fetch(int, hintDepthArray, hintnr);
+
+    if(hintnr == 0 && mdd_is_tautology(hint, 1) && array_n(guideArray) == 1){
+      assert(hintDepth == -1);
+    }  else {
+      assert(!incrementalFlag);
+      guidedSearchMode  = TRUE;
+      Fsm_InstantiateHint(fsm, hint, 1, 0, Ctlp_Underapprox_c,
+			  verbosityLevel > 1);
+      if (hintnr < (array_n(guideArray)-1))
+	fprintf(vis_stdout, "**GS info: Instantiating  hint number %d\n", hintnr+1);
+      else
+	fprintf(vis_stdout, "**GS info: Restoring original transition relation\n");
+
+      if (approxFlag == Fsm_Rch_Hd_c) {
+	/* clean up all the invalid state information */
+	if (hdInfo->interiorStates != NIL(mdd_t))
+	  mdd_free(hdInfo->interiorStates);
+	hdInfo->interiorStates = NIL(mdd_t); /* for every new hint, this is invalid. */
+	if (hdInfo->interiorStateCandidate != NIL(mdd_t))
+	  mdd_free(hdInfo->interiorStateCandidate);
+	hdInfo->interiorStateCandidate = NIL(mdd_t); /* for every new hint, this is invalid */
+	hdInfo->imageOfReachedComputed = FALSE; /* since it doesn't matter for every new hint */
+	if (hdInfo->deadEndResidue != NIL(mdd_t))
+	  mdd_free(hdInfo->deadEndResidue);
+	hdInfo->deadEndResidue = NIL(mdd_t);
+      }
+      /* generate a frontier by doing a dead-end computation if the
+	 frontier is empty. This is non-greedy for BFS and greedy for
+	 HD. */
+      if (mdd_is_tautology(fromLowerBound, 0)) {
+	ComputeReachabilityParameters(mddManager, imageInfo, approxFlag,
+				      &reachableStates, &fromUpperBound,
+				      &fromLowerBound, &image, hdInfo,
+				      initialStates,
+				      mintermVarArray,
+				      &depth, printStep,
+				      shellFlag, onionRings,
+				      verbosityLevel,
+				      guidedSearchMode, hint, &hintDepth,
+				      &notConverged);
+      }
+    }
+    /* initialize */
+    notConverged = FALSE;
+    if (!incrementalFlag)
+      Img_ImageInfoResetUseOptimizedRelationFlag(imageInfo);
+    /* Main loop of reachability computation. */
+    /* Iterate until fromLowerBound is empty or all states are reached. */
+    while (!mdd_is_tautology(fromLowerBound, 0)) {
+      if(depth > 0 && !incrementalFlag)
+	Img_ImageInfoSetUseOptimizedRelationFlag(imageInfo);
+      /* fromLowerBound is the "onion shell" of states just reached. */
+      if ((shellFlag && (approxFlag != Fsm_Rch_Hd_c) &&
+	  (!firstTimeFlag ||
+	   (Fsm_FsmReadReachabilityOnionRings(fsm) == NIL(array_t)))) ||
+	  (shellFlag && (approxFlag == Fsm_Rch_Hd_c) &&
+	  (Fsm_FsmReadReachabilityOnionRings(fsm) == NIL(array_t)) &&
+	  firstTimeFlag)) {
+	array_insert_last(mdd_t*, onionRings, mdd_dup(fromLowerBound));
+      }
+
+      /* if it is the print step, print out the iteration and the */
+      if (printStep && ((depth % printStep) == 0)) {
+	int step;
+	/* for BFS, preserve earlier format of printing */
+	step = (shellFlag) ? array_n(onionRings) : Fsm_FsmGetReachableDepth(fsm)+depth;
+	PrintStatsPerIteration(approxFlag,
+			       nvars,
+			       step,
+			       hdInfo,
+			       mddManager,
+			       reachableStates,
+			       fromLowerBound,
+			       mintermVarArray);
+      }
+
+      /* Check if invariant contains the new states.  In case of HD
+       * computation, check the containment of the entire reached set.
+       */
+      if (invarStates != NIL(array_t)) {
+	mdd_t *temp;
+	temp = (approxFlag == Fsm_Rch_Hd_c) ? reachableStates : fromLowerBound;
+	if (!CheckStatesContainedInInvariant(temp, invarStates)) {
+	  notConverged = TRUE;
+	  invariantFailed = TRUE; /* flag used for early termination */
+	  break;
+	}
+      }
+
+      if (mdd_is_tautology(reachableStates, 1)) {
+	break;
+      }
+
+      if ((depthValue && (depth == depthValue)) ||
+	  /* limited depth hint is implemented this way */
+	  (hintDepth == 0)) {
+	/* No more steps */
+	notConverged = TRUE;
+	break;
+      }
+
+      if (reorderFlag && !firstReorderFlag &&
+	  (reachableStateSetSize >= reorderThreshold )){
+	firstReorderFlag = TRUE;
+	(void) fprintf(vis_stdout, "Dynamic variable ordering forced ");
+	(void) fprintf(vis_stdout, "with method sift\n");
+	Ntk_NetworkSetDynamicVarOrderingMethod(network,
+					       BDD_REORDER_SIFT,
+					       BDD_REORDER_VERBOSITY_DEFAULT);
+	bdd_reorder(Ntk_NetworkReadMddManager(network));
+	Ntk_NetworkSetDynamicVarOrderingMethod(network, currentMethod,
+					       BDD_REORDER_VERBOSITY_DEFAULT);
+      }
+
+      firstTimeFlag = FALSE;
+      /* careSet for image computation is the set of all states not reached
+       * so far.
+       */
+      toCareSet = mdd_not(reachableStates);
+
+      /*
+       * Image of some set between lower and upper, where we care
+       * about the image only on unreached states.
+       */
+      if (incrementalFlag){
+	image = IncrementalImageCompute(network, fsm, mddManager,
+					fromLowerBound,
+					fromUpperBound, toCareSet,
+					arrayOfRoots, tableOfLeaves,
+					smoothVarArray, relationArray,
+					numLatch);
+      } else{
+	assert(!incrementalFlag);
+
+	if (approxFlag == Fsm_Rch_Hd_c) {
+	  /* allow partial image computation */
+	  Img_ImageAllowPartialImage(imageInfo, TRUE);
+	}
+
+	/* compute the image of this iteration */
+	image = Img_ImageInfoComputeFwdWithDomainVars(imageInfo,
+						      fromLowerBound,
+						      fromUpperBound,
+						      toCareSet);
+
+
+
+	/* record if partial image or not */
+	if (approxFlag == Fsm_Rch_Hd_c) {
+	  /* Check if partial image computation, disallow partial image
+	   * computation.
+	   */
+	  hdInfo->partialImage = Img_ImageWasPartial(imageInfo);
+	  /* record this to prevent dead-end computation. */
+	  hdInfo->imageOfReachedComputed = (!hdInfo->partialImage) &&
+	    mdd_equal(reachableStates, fromLowerBound);
+	  /* potential candidates for interior states (only if not a
+	   * partial image)
+	   */
+	  if (!hdInfo->partialImage) hdInfo->interiorStateCandidate = mdd_dup(fromLowerBound);
+	}
+      }
+
+      /* free the used bdds */
+      mdd_free(toCareSet);
+
+      /* New lower bound is the states just reached. */
+      mdd_free(fromLowerBound);
+      fromLowerBound = mdd_and(image, reachableStates, 1, 0);
+      depth++;
+      hintDepth--;
+
+
+      if ((!incrementalFlag) && (approxFlag == Fsm_Rch_Hd_c)) {
+	FsmHdStatsComputeSizeAndMinterms(mddManager, image,
+					 mintermVarArray, nvars,
+					 Fsm_Hd_To, hdInfo->stats);
+      }
+
+      /* need image only if HD and not dead-end */
+      if (approxFlag != Fsm_Rch_Hd_c) {
+	  mdd_free(image);
+	  image = NULL;
+      } else {
+	if (hdInfo->imageOfReachedComputed ||	hdInfo->onlyPartialImage ||
+	  (hdInfo->slowGrowth >= FSM_HD_NUM_SLOW_GROWTHS) ||
+	  mdd_is_tautology(fromLowerBound, 0)) {
+	  mdd_free(image);
+	  image = NULL;
+	}
+      }
+
+      /* computes reachable states, fromlowerBound and fromupperbound
+       * for BFS.  For HD it computes the above as well as interior
+       * statess, dead-end residue, etc. All the other parameteres are
+       * updated. For guided search, this call does not perform a
+       * non-greedy dead-end computation, even if the frontier is 0. */
+       ComputeReachabilityParameters(mddManager, imageInfo, approxFlag,
+				    &reachableStates,
+				    &fromUpperBound,
+				    &fromLowerBound,
+				    &image,
+				     hdInfo,
+				    initialStates,
+				    mintermVarArray,
+				     &depth,  printStep,
+				     shellFlag, onionRings,
+				    verbosityLevel, FALSE, hint,
+				    &hintDepth,
+				    &notConverged);
+
+
+       if (mdd_is_tautology(fromLowerBound, 0) &&
+	   (approxFlag == Fsm_Rch_Bfs_c) &&
+	   (!guidedSearchMode) && (!depthValue))
+	 depth--;
+
+    } /* end of main while loop (while frontier != 0) */
+
+    /* stop iterating over hint if invariants are violated or all
+       states are reachable or limited depth value has been
+       reached. */
+    if (invariantFailed) break;
+    if (mdd_is_tautology(reachableStates, 1)) {
+      break;
+    }
+    if (depthValue && (depth == depthValue)) {
+      /* No more steps */
+      break;
+    }
+
+  }/* for each hint */
+
+
+  if(!incrementalFlag &&
+     Img_ImageInfoObtainMethodType(imageInfo) == Img_Linear_c &&
+     Img_ImageInfoObtainOptimizeType(imageInfo) == Opt_NS &&
+     Img_IsTransitionRelationOptimized(imageInfo)) {
+    Img_ImageInfoResetUseOptimizedRelationFlag(imageInfo);
+    fprintf(vis_stdout, "%-20s%10g\n", "reachable states =",
+		 mdd_count_onset(mddManager, reachableStates,
+				 fsm->fsmData.presentStateVars));
+    fromLowerBound = mdd_dup(reachableStates);
+    fromUpperBound = reachableStates;
+    while (1) {
+      toCareSet = mdd_dup(reachableStates);
+      image = Img_ImageInfoComputeFwdWithDomainVars(imageInfo,
+						  fromLowerBound,
+						  fromUpperBound,
+						  toCareSet);
+      newImage = bdd_or(image, initialStates, 1, 1);
+      bdd_free(image);
+      image = newImage;
+      if(mdd_equal(fromLowerBound, image)) {
+	mdd_free(toCareSet);
+	mdd_free(fromLowerBound);
+	mdd_free(reachableStates);
+	fromLowerBound = image;
+	reachableStates = mdd_dup(fromLowerBound);
+	fromUpperBound = reachableStates;
+	fprintf(vis_stdout, "%-20s%10g\n", "reachable states =",
+		 mdd_count_onset(mddManager, reachableStates,
+				 fsm->fsmData.presentStateVars));
+	break;
+      }
+      mdd_free(toCareSet);
+      mdd_free(fromLowerBound);
+      mdd_free(reachableStates);
+      fromLowerBound = image;
+      reachableStates = mdd_dup(fromLowerBound);
+      fromUpperBound = reachableStates;
+
+      fprintf(vis_stdout, "%-20s%10g\n", "reachable states =",
+		 mdd_count_onset(mddManager, reachableStates,
+				 fsm->fsmData.presentStateVars));
+    }
+  }
+
+
+  /* clean up for Guided search mainly, only if needed */
+  /* we rely on the fact that the variable hint is set to the last hint from
+   * the previous loop.
+   */
+  if (guidedSearchMode && !mdd_is_tautology(hint, 1))
+    Fsm_CleanUpHints(fsm, 1, 0, printStep);
+  array_free(hintDepthArray);
+
+  /* If (1) all states are reachable, or (2) not limited depth computation
+     and not a converge with a hint, or (3) limited depth and not
+     guided search mode and BFS and frontier = 0, or (4) in guided
+     search, if limited depth and frontier = 0 then one full dead-end
+     should have occured */
+  if(mdd_is_tautology(reachableStates, 1) ||
+     ((notConverged == FALSE) && mdd_is_tautology(hint, 1)) ||
+     (!guidedSearchMode && (notConverged == TRUE) &&
+      mdd_is_tautology(fromLowerBound, 0) && (approxFlag == Fsm_Rch_Bfs_c)) ||
+     (guidedSearchMode && hdInfo->deadEndWithOriginalTR &&
+      mdd_is_tautology(fromLowerBound, 0) && (approxFlag == Fsm_Rch_Bfs_c))) {
+
+    rchStatus = Fsm_Rch_Exact_c;
+    if (mdd_is_tautology(reachableStates, 1) &&
+	!mdd_is_tautology(fromLowerBound, 0) &&
+	printStep && ((depth % printStep) == 0) ) {
+      int step;
+      /* for BFS, preserve earlier format of printing */
+      step = (shellFlag) ?
+	array_n(onionRings) :
+	Fsm_FsmGetReachableDepth(fsm)+depth;
+      PrintStatsPerIteration(approxFlag, nvars, step, hdInfo,
+			     mddManager, reachableStates,
+			     fromLowerBound, mintermVarArray);
+    }
+  }
+
+  /* clean up the hints if allocated here */
+  if (guideArrayAllocated) mdd_array_free(guideArray);
+
+  if (hdInfo != NIL(FsmHdStruct_t)) {
+    FsmHdStructFree(hdInfo);
+  }
+
+  mdd_free(fromLowerBound);
+  mdd_free(initialStates);
+
+  /* Update FSM reahcability fields */
+
+  /* indicate whether the shells are consistent with the reachable states */
+  if (!shellFlag) {
+    /* if any states were added from a previous computation, shells
+       are not up-to-date */
+    if (Fsm_FsmReadCurrentReachableStates(fsm) != NIL(mdd_t)) {
+      if (!mdd_lequal(reachableStates, Fsm_FsmReadCurrentReachableStates(fsm), 1, 1)) {
+	FsmSetReachabilityOnionRingsUpToDateFlag(fsm, FALSE);
+      } /* otherwise the previous iteration was computed with onion
+      rings, in which case it is still up-to-date or the previous
+      iteration was computed without onion rings and it was set to not
+      up-to-date in the previous iteration */
+    } else {
+      assert(Fsm_FsmReadReachabilityOnionRings(fsm) == NIL(array_t));
+      /* not up-to-date because no onion rings */
+      FsmSetReachabilityOnionRingsUpToDateFlag(fsm, FALSE);
+    }
+
+  } else {
+    /* shells are up to date only if current set adds upto previously
+       computed states or more */
+    if (Fsm_FsmReadCurrentReachableStates(fsm)) {
+      if (!mdd_lequal(Fsm_FsmReadCurrentReachableStates(fsm),
+		    reachableStates, 1, 1)) {
+	FsmSetReachabilityOnionRingsUpToDateFlag(fsm, FALSE);
+      } else {
+	FsmSetReachabilityOnionRingsUpToDateFlag(fsm, TRUE);
+      }
+
+    } else FsmSetReachabilityOnionRingsUpToDateFlag(fsm, TRUE);
+
+    /* Onion rings are not BFS, i.e., HD or Guided search. */
+    if ((approxFlag == Fsm_Rch_Hd_c) ||
+	(Fsm_FsmReadReachabilityOnionRingsMode(fsm) == Fsm_Rch_Hd_c) ||
+	guidedSearchMode)
+      FsmSetReachabilityOnionRingsMode(fsm, Fsm_Rch_Hd_c);
+
+    if (array_n(onionRings) == 0) {
+      array_free(onionRings);
+      onionRings = NIL(array_t);
+    }
+    FsmSetReachabilityOnionRings(fsm, onionRings);
+  }
+
+  /* update fsm structure */
+  /* record depth of traversal, depth is consistent with reachable
+     states, hence may not be consistent with the onion rings */
+  /* replace reachable states if only more states have been computed now */
+  if (Fsm_FsmReadCurrentReachableStates(fsm) != NIL(mdd_t)) {
+    if (!mdd_lequal(reachableStates, Fsm_FsmReadCurrentReachableStates(fsm), 1, 1)) {
+      Fsm_FsmFreeReachableStates(fsm);
+      fsm->reachabilityInfo.reachableStates = mdd_dup(reachableStates);
+      if (!shellFlag) fsm->reachabilityInfo.depth = Fsm_FsmGetReachableDepth(fsm) + depth;
+      else if (Fsm_FsmReadReachabilityOnionRings(fsm))
+	fsm->reachabilityInfo.depth = array_n(Fsm_FsmReadReachabilityOnionRings(fsm));
+      /* set computation mode as HD if HD or Guided search, basically to indicate not BFS */
+      if ((approxFlag == Fsm_Rch_Hd_c) ||
+	  (FsmReadReachabilityComputationMode(fsm)  == Fsm_Rch_Hd_c) ||
+	  guidedSearchMode) {
+	FsmSetReachabilityComputationMode(fsm, Fsm_Rch_Hd_c);
+      }
+    }
+  } else {
+    fsm->reachabilityInfo.reachableStates = mdd_dup(reachableStates);
+    if (!shellFlag) fsm->reachabilityInfo.depth = depth;
+    else if (Fsm_FsmReadReachabilityOnionRings(fsm))
+      fsm->reachabilityInfo.depth = array_n(Fsm_FsmReadReachabilityOnionRings(fsm));
+    /* set computation mode as HD if HD or Guided search, basically to indicate not BFS */
+      if ((approxFlag == Fsm_Rch_Hd_c) || guidedSearchMode) {
+	FsmSetReachabilityComputationMode(fsm, Fsm_Rch_Hd_c);
+      } else {
+	FsmSetReachabilityComputationMode(fsm, Fsm_Rch_Bfs_c);
+      }
+
+  }
+  /* indicate whether reachability analysis is completed or not */
+  FsmSetReachabilityApproxComputationStatus(fsm, rchStatus);
+
+  if (incrementalFlag){
+    array_free(relationArray);
+    array_free(arrayOfRoots);
+    st_free_table(tableOfLeaves);
+    array_free(smoothVarArray);
+    /* Need to put in next state function data for the partition */
+  }
+
+  return reachableStates;
+} /* end of Fsm_FsmComputeReachableStates */
+
+
+
+/**Function********************************************************************
+
+  Synopsis [Existentially quantifies variables from an implicit product.]
+
+  Description [Existentially quantifies the smoothing variables from the
+  product of the MDDs in mddArray, and returns the result. SmoothingVars is an
+  array of MDD ids. For now, uses the simplistic approach of conjunction all
+  the MDDs, and then quantifying the smoothing variables.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Fsm_MddMultiwayAndSmooth(mdd_manager *mddManager, array_t *mddArray,
+			 array_t *smoothingVars)
+{
+  int i;
+  mdd_t *resultMdd;
+  mdd_t *product = mdd_one(mddManager);
+
+  for (i = 0; i<array_n(mddArray); i++){
+    mdd_t *mdd         = array_fetch(mdd_t*, mddArray, i);
+    mdd_t *tempProduct = mdd_and(product, mdd, 1, 1);
+    mdd_free(product);
+    product = tempProduct;
+  }
+
+  if (array_n(smoothingVars) == 0) {
+    resultMdd = mdd_dup(product);
+  }
+  else{
+    resultMdd =  mdd_smooth(mddManager, product, smoothingVars);
+  }
+
+  mdd_free(product);
+  return resultMdd;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the results of reachability analysis.]
+
+  Description    [Prints the results of reachability analysis.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Fsm_FsmReachabilityPrintResults(
+  Fsm_Fsm_t *fsm,
+  long elapseTime,
+  int approxFlag)
+{
+  mdd_manager	*mddManager = Fsm_FsmReadMddManager(fsm);
+  mdd_t		*reachableStates = fsm->reachabilityInfo.reachableStates;
+  array_t	*psVarsArray;
+  int		nvars;
+
+  if (!reachableStates)
+    return;
+
+  psVarsArray = Fsm_FsmReadPresentStateVars(fsm);
+  /* compute number of present state variables */
+  nvars = ComputeNumberOfBinaryStateVariables(mddManager, psVarsArray);
+
+  (void) fprintf(vis_stdout,"********************************\n");
+  (void) fprintf(vis_stdout,"Reachability analysis results:\n");
+  if ((FsmReadReachabilityComputationMode(fsm) == Fsm_Rch_Bfs_c) &&
+      (Fsm_FsmReadReachableStates(fsm) != NIL(mdd_t))) {
+    (void) fprintf(vis_stdout, "%-20s%10d\n", "FSM depth =",
+		   fsm->reachabilityInfo.depth);
+  } else {
+    (void) fprintf(vis_stdout, "%-20s%10d\n", "computation depth =",
+		   fsm->reachabilityInfo.depth);
+  }
+  if (nvars <= 1023) {
+    (void) fprintf(vis_stdout, "%-20s%10g\n", "reachable states =",
+		   mdd_count_onset(mddManager, reachableStates,
+				   fsm->fsmData.presentStateVars));
+  } else {
+    /*
+    (void) fprintf(vis_stdout, "%-20s", "reachable states = ");
+    bdd_print_apa_minterm(vis_stdout, reachableStates, nvars, (long)6);
+    */
+    EpDouble	epd;
+    char	strValue[20];
+
+    mdd_epd_count_onset(mddManager, reachableStates,
+			fsm->fsmData.presentStateVars, &epd);
+    EpdGetString(&epd, strValue);
+    (void) fprintf(vis_stdout, "%-20s%10s\n", "reachable states =", strValue);
+  }
+  (void) fprintf(vis_stdout, "%-20s%10d\n", "BDD size =",
+		 mdd_size(reachableStates));
+  (void) fprintf(vis_stdout, "%-20s%10g\n", "analysis time =",
+		 (double)elapseTime/1000.0);
+  if (Fsm_FsmReadReachableStates(fsm) != NIL(mdd_t)) {
+    (void) fprintf(vis_stdout, "%-20s%10s\n", "reachability analysis = ", "complete");
+  } else {
+    (void) fprintf(vis_stdout, "%-20s%10s\n", "reachability analysis = ", "incomplete");
+  }
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Checks the validity of image]
+
+  Description [In a properly formed image, there should not be any
+  domain or quantify variables in its support. This function checks
+  for that fact.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CheckImageValidity(mdd_manager *mddManager, mdd_t *image, array_t
+		   *domainVarMddIdArray, array_t *quantifyVarMddIdArray)
+{
+  int i;
+  array_t *imageSupportArray = mdd_get_support(mddManager, image);
+  st_table *imageSupportTable = st_init_table(st_numcmp, st_numhash);
+  for (i=0; i<array_n(imageSupportArray); i++){
+    int mddId = array_fetch(int, imageSupportArray, i);
+    (void) st_insert(imageSupportTable, (char *) (long) mddId, NIL(char));
+  }
+  for (i=0; i<array_n(domainVarMddIdArray); i++){
+    int domainVarId;
+    domainVarId = array_fetch(int, domainVarMddIdArray, i);
+    assert(st_is_member(imageSupportTable, (char *)(long)domainVarId) == 0);
+  }
+  for (i=0; i<array_n(quantifyVarMddIdArray); i++){
+    int quantifyVarId;
+    quantifyVarId = array_fetch(int, quantifyVarMddIdArray, i);
+    assert(st_is_member(imageSupportTable, (char *)(long)quantifyVarId) == 0);
+  }
+  st_free_table(imageSupportTable);
+  array_free(imageSupportArray);
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of Bdd variables for the given Mdd id array].
+
+  Description [Counts the number of Bdd variables for the given Mdd id array]
+
+
+  SideEffects []
+
+******************************************************************************/
+static int
+ComputeNumberOfBinaryStateVariables(mdd_manager *mddManager,
+			       array_t *mddIdArray)
+{
+  int mddId, i;
+  mvar_type mddVar;
+  int numEncodingBits, count = 0;
+  array_t *mvar_list = mdd_ret_mvar_list(mddManager);
+
+  arrayForEachItem(int, mddIdArray, i, mddId) {
+    mddVar = array_fetch(mvar_type, mvar_list, mddId);
+    numEncodingBits = mddVar.encode_length;
+    count += numEncodingBits;
+  }
+  return count;
+} /* end of ComputeNumberOfBinaryStateVariables */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Add states.]
+
+  Description [Add States.]
+
+  SideEffects [ Free the original parts]
+
+******************************************************************************/
+static mdd_t *
+AddStates(mdd_t *a, mdd_t *b, int freeA, int freeB)
+{
+  mdd_t *result;
+  if ((a != NULL) && (b != NULL)) {
+    result = mdd_or(a, b, 1, 1);
+  } else if ((a == NULL) && (b == NULL)) {
+    result = a;
+  } else if (a == NULL) {
+    result = mdd_dup(b);
+  } else {
+    result =  mdd_dup(a);
+  }
+  if ((freeA == FSM_MDD_FREE) && (a != NULL)) mdd_free(a);
+  if ((freeB == FSM_MDD_FREE) && (b != NULL)) mdd_free(b);
+  return result;
+} /* end of AddStates */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Simulates randomly specified number of states.]
+
+  Description [Simulates randomly specified number of states.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+RandomSimulation(int simNVec,
+		 Fsm_Fsm_t *fsm,
+		 Fsm_RchType_t approxFlag,
+		 mdd_t *initialStates,
+		 mdd_t **reachableStates,
+		 mdd_t **fromLowerBound,
+		 FsmHdStruct_t *hdInfo)
+{
+  Ntk_Network_t   *network = fsm->network;
+
+  /* Compute specified number of simulated states. */
+  *reachableStates = Sim_RandomSimulate(network, simNVec, 0);
+  *reachableStates = AddStates(*reachableStates, initialStates, FSM_MDD_FREE, FSM_MDD_DONT_FREE);
+  *fromLowerBound = mdd_dup(*reachableStates);
+
+  if (approxFlag == Fsm_Rch_Hd_c) {
+    if (mdd_size(*fromLowerBound) >
+	Fsm_FsmHdOptionReadFrontierApproxThreshold(hdInfo->options)) {
+      /* Reset frontier if too large. */
+      mdd_free(*fromLowerBound);
+      *fromLowerBound = bdd_between(initialStates, *reachableStates);
+      if (!mdd_equal(*fromLowerBound, *reachableStates)) {
+	hdInfo->firstSubset = FALSE;
+	hdInfo->deadEndResidue = mdd_and(*reachableStates,
+					 *fromLowerBound, 1, 0);
+      }
+    }
+  }
+  return;
+} /* end of RandomSimulation */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints stats per iteration]
+
+  Description [Prints stats per iteration]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+PrintStatsPerIteration(Fsm_RchType_t approxFlag,
+		       int nvars,
+		       int depth,
+		       FsmHdStruct_t *hdInfo,
+		       mdd_manager *mddManager,
+		       mdd_t *reachableStates,
+		       mdd_t *fromLowerBound,
+		       array_t *mintermVarArray)
+{
+  if (approxFlag != Fsm_Rch_Hd_c) {
+    int reachableStateSetSize = mdd_size(reachableStates);
+    if (nvars <= 1023) {
+      (void)fprintf(vis_stdout, "BFS step = %d\t|states| = %8g\tBdd size = %8ld\n",
+		    depth, mdd_count_onset(mddManager, reachableStates,
+					   mintermVarArray),
+		    (long)reachableStateSetSize);
+      /*			    bdd_print_minterm(reachableStates); */
+    } else {
+      (void)fprintf(vis_stdout, "BFS step = %d\tBdd size = %8d\t|states| = ",
+		    depth, reachableStateSetSize);
+      (void) bdd_print_apa_minterm(vis_stdout, reachableStates, nvars, (long)6);
+    }
+
+  } else { /* HD */
+
+    if (nvars <= 1023) {
+      (void)fprintf(vis_stdout, "Step = %d, R = %8g, |R| = %8d,  I = %8g,  |I| = %8d\n",
+		    depth,  FsmHdStatsReadMintermReached(hdInfo->stats),
+		    FsmHdStatsReadSizeReached(hdInfo->stats), FsmHdStatsReadMintermTo(hdInfo->stats) ,
+		    FsmHdStatsReadSizeTo(hdInfo->stats));
+      (void)fprintf(vis_stdout, "Completed iteration %d at %g seconds\n",
+		    depth, (util_cpu_time()/1000.0));
+
+      (void)fprintf(vis_stdout, "Step = %d, F = %8g, |F| = %8d, FA = %8g, |FA| = %8d\n",
+		    depth+1, FsmHdStatsReadMintermFrom(hdInfo->stats),
+		    FsmHdStatsReadSizeFrom(hdInfo->stats),
+		    FsmHdStatsReadMintermFromSubset(hdInfo->stats),
+		    FsmHdStatsReadSizeFromSubset(hdInfo->stats));
+    } else {
+      int status;
+      (void)fprintf(vis_stdout, "Step = %d, |R| = %8d, R = ",
+		    depth, FsmHdStatsReadSizeReached(hdInfo->stats));
+      status = bdd_print_apa_minterm(vis_stdout, reachableStates, nvars, (long)6);
+      if (!status) {
+	error_append("** rch error: Error in printing arbitrary precision minterm count of Reached");
+      }
+
+      (void)fprintf(vis_stdout, "Completed iteration %d at %g seconds\n",
+		    depth, (util_cpu_time()/1000.0));
+      (void)fprintf(vis_stdout, "Step = %d, |F| = %8d, F = %8g, |FA| = %8d, FA = ",
+		    depth, FsmHdStatsReadSizeFrom(hdInfo->stats), 0.0,
+		    FsmHdStatsReadSizeFromSubset(hdInfo->stats) );
+      status = bdd_print_apa_minterm(vis_stdout, fromLowerBound, nvars, 6);
+      if (!status) {
+	error_append("** rch error: Error in printing arbitrary precision minterm count of From");
+      }
+    }
+  }
+  return;
+} /* end of PrintStatsPerIteration */
+
+/**Function********************************************************************
+
+  Synopsis [Induce full dead-end if there is a big jump in Reached
+  size]
+
+  Description [Induce full dead-end if there is a big jump in Reached
+  size and not enough increase in minterms of Reached. So throw away
+  the new large-sized Reached and compute its entire image. Use the
+  dead-end computation for this and use the non-greedy flag. This is a
+  recovery mechanism to combat fragmentation of the state space.]
+
+  SideEffects [Other quantities are adjusted accordingly. Now the Reached
+  set before the dead-end computation will be added to the interior states.]
+
+******************************************************************************/
+static void
+HdInduceFullDeadEndIfNecessary(mdd_manager *mddManager,
+			       Img_ImageInfo_t *imageInfo,
+			       mdd_t **fromLowerBound,
+			       mdd_t **fromUpperBound,
+			       mdd_t **reachableStates,
+			       mdd_t **image,
+			       FsmHdStruct_t *hdInfo,
+			       int *depth,
+			       int shellFlag,
+			       array_t *onionRings,
+			       array_t *mintermVarArray,
+			       int oldSize,
+			       double oldMint,
+			       int verbosityLevel)
+{
+  int nvars =  Fsm_FsmHdOptionReadNumVars(hdInfo->options);
+  /*
+   * Compute a full (non-greedy) dead-end when a dead-end computation
+   * hasn't occurred, and the jump in minterms is lower than MINT_GROWTH and
+   * either the old reached size is between MID_SIZE and LARGE_SIZE and the
+   * jump is MID_SIZE or the new size is larger than LARGE_SIZE and the jump
+   * is LARGE_SIZE.
+   */
+  if ((hdInfo->deadEndComputation == FALSE) &&
+      ((FsmHdStatsReadMintermReached(hdInfo->stats) - oldMint)/oldMint < FSM_HD_MINT_GROWTH) &&
+      (((FsmHdStatsReadSizeReached(hdInfo->stats)  > FSM_HD_MID_SIZE) &&
+	(FsmHdStatsReadSizeReached(hdInfo->stats) - oldSize > FSM_HD_MID_SIZE) &&
+	(oldSize > FSM_HD_MID_SIZE) && (oldSize < FSM_HD_LARGE_SIZE)) ||
+       ((FsmHdStatsReadSizeReached(hdInfo->stats) > FSM_HD_LARGE_SIZE) &&
+	(FsmHdStatsReadSizeReached(hdInfo->stats) - oldSize > FSM_HD_LARGE_SIZE)))) {
+    if (verbosityLevel >= 2) {
+      fprintf(vis_stdout, "Full Dead End: New Reached = %d, Minterms = %g\n",
+	      FsmHdStatsReadSizeReached(hdInfo->stats), FsmHdStatsReadMintermReached(hdInfo->stats));
+    }
+
+    if (*image != NULL) {
+      mdd_free(*image);
+      *image = NULL;
+    }
+    /* throw away the reached with the jump in size */
+    mdd_free(*reachableStates);
+    if (shellFlag && onionRings) {
+      mdd_free(array_fetch(mdd_t *, onionRings, array_n(onionRings)-1));
+      array_insert(mdd_t *, onionRings, array_n(onionRings)-1, NIL(mdd_t));
+    }
+
+    *reachableStates = *fromUpperBound;
+    /* throw away interior state candidates since we just threw away
+     * the new states
+     */
+    if (hdInfo->interiorStateCandidate != NIL(mdd_t)) {
+      mdd_free(hdInfo->interiorStateCandidate);
+      hdInfo->interiorStateCandidate = NIL(mdd_t);
+    }
+
+    if (verbosityLevel >= 2) {
+      /* record number of dead ends */
+      (hdInfo->numDeadEnds)++;
+      fprintf(vis_stdout, "Dead-End %d at %g seconds - FULL\n",
+	      hdInfo->numDeadEnds, (util_cpu_time()/1000.0));
+    }
+
+    /* perform a full non-greedy dead-end computation */
+    *fromLowerBound = FsmHdDeadEnd(mddManager, imageInfo, *reachableStates,
+				  hdInfo,
+				  mintermVarArray,
+				  FSM_HD_NONGREEDY, verbosityLevel);
+    (*depth)++;
+    /* update reached since a new set of seeds have been found */
+    assert (!mdd_is_tautology(*fromLowerBound, 0));
+    if (shellFlag && onionRings) {
+      mdd_t *temp = mdd_and(*fromLowerBound, *reachableStates, 1, 0);
+      if (!mdd_is_tautology(temp, 0))
+	array_insert(mdd_t *, onionRings, array_n(onionRings)-1, temp);
+      else
+	mdd_free(temp);
+    }
+    *fromUpperBound = *reachableStates;
+    *reachableStates = mdd_or(*fromLowerBound, *fromUpperBound, 1, 1);
+    FsmHdStatsComputeSizeAndMinterms(mddManager, *reachableStates,
+				     mintermVarArray,  nvars,
+				     Fsm_Hd_Reached, hdInfo->stats);
+  } /* end of if jump in Reached */
+} /* end of  HdInduceFullDeadEndIfNecessary */
+
+
+/**Function********************************************************************
+
+  Synopsis [Compute initial states.]
+
+  Description [Compute initial states. Return fsm initial states if no
+  previously computed states are found. If shell flag, compute union
+  of rings. If not shell flag, return previously computed states.]
+
+  SideEffects []
+
+******************************************************************************/
+static mdd_t *
+ComputeInitialStates(Fsm_Fsm_t *fsm, int shellFlag, boolean printWarning)
+{
+  mdd_t *initialStates = NIL(mdd_t);
+  boolean rings = FALSE;
+  array_t *mintermVarArray = Fsm_FsmReadPresentStateVars(fsm);
+
+  if (Fsm_FsmReadCurrentReachableStates(fsm) == NIL(mdd_t)) {
+    initialStates = Fsm_FsmComputeInitialStates(fsm);
+    return (initialStates);
+  } else if (shellFlag) {
+    (void) Fsm_FsmReachabilityOnionRingsStates(fsm, &initialStates);
+    if (initialStates == NIL(mdd_t)) {
+      initialStates = Fsm_FsmComputeInitialStates(fsm);
+      return (initialStates);
+    } else if (mdd_is_tautology(initialStates, 0)) {
+      initialStates = Fsm_FsmComputeInitialStates(fsm);
+      return (initialStates);
+    }
+    /* some states are found in the onion rings */
+    rings = TRUE;
+  } else {
+    /* use previously computed states */
+    initialStates = mdd_dup(Fsm_FsmReadCurrentReachableStates(fsm));
+  }
+  if (printWarning) {
+    fprintf(vis_stdout, "** rch warning: Starting reachability analysis from previously computed states.\n");
+    fprintf(vis_stdout, "** rch warning: Use compute_reach -F to recompute if necessary.\n");
+    fprintf(vis_stdout, "** rch warning: Previously computed states = %g, Size = %d, computation depth = 0-%d\n", mdd_count_onset(Fsm_FsmReadMddManager(fsm), initialStates, mintermVarArray), mdd_size(initialStates), fsm->reachabilityInfo.depth);
+    if (!rings) {
+      if (FsmReadReachabilityComputationMode(fsm) == Fsm_Rch_Bfs_c) {
+	fprintf(vis_stdout, "** rch warning: Previous computation done with BFS (-A 0 option)\n");
+      } else if (FsmReadReachabilityComputationMode(fsm) == Fsm_Rch_Hd_c) {
+	fprintf(vis_stdout, "** rch warning: Some previous computations done using BFS/DFS mode (-A 1 or -g option)\n");
+      }
+    } else {
+      if (Fsm_FsmReadReachabilityOnionRingsMode(fsm) == Fsm_Rch_Bfs_c) {
+	fprintf(vis_stdout, "** rch warning: Previous onion rings computed with BFS (-A 0 option)\n");
+      } else if (Fsm_FsmReadReachabilityOnionRingsMode(fsm) == Fsm_Rch_Hd_c) {
+	fprintf(vis_stdout, "** rch warning: Some set of onion rings have been computed using BFS/DFS (-A 1 or -g option)\n");
+      }
+    }
+  }
+  return (initialStates);
+} /* end of ComputeInitialStates */
+
+
+/**Function********************************************************************
+
+  Synopsis [Checks if the reachable states are contained in each
+  element of an array of invariants.]
+
+  Description [Checks if the reachable states are contained in each
+  element of an array of invariants. Returns 0 as soon as a violation
+  is found.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CheckStatesContainedInInvariant(mdd_t *reachableStates,
+				array_t *invarStates)
+{
+  int i;
+  mdd_t *invariant;
+
+  arrayForEachItem(mdd_t *, invarStates, i, invariant) {
+    if (invariant == NIL(mdd_t)) continue;
+    if (!mdd_lequal(reachableStates, invariant, 1, 1)) {
+      return 0;
+    }
+  }
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Computes the reachable states, fromLowerBound and
+  fromUpperBound for HD Traversal.]
+
+  Description [Computes the reachable states, fromLowerBound and
+  fromUpperBound for HD Traversal. Updates all other arguments such as
+  interiorStates, deadEndResidue . There are 3 major operations in
+  this procedure. 1. Induce (if slow growth in reached) and compute a
+  dead-end if necessary. 2. Compute the image of Reached if there is a
+  big jump in its size. 3. Compute a dense subset of states to be used
+  as a frontier in the next iteration.
+
+  1. A dead-end is the situation where no new states have been
+  produced (fromLowerBound = 0), It is induced if the rate of growth
+  of Reached is slow. If the image of the Entire Reached set has been
+  computed in the previous iteration, then pretend this is a dead-end.
+
+  2. If the jump in Reached is large, compute its entire image to
+  recover from fragmentation.
+
+  3. A dense subset of the frontier set is computed to be used as the
+  frontier set in the next iteration. The update of reached is
+  performed in this step (may not add scrap states if
+  specified.). If a dead-end has just been performed, the new states
+  are always added to Reached. Growth rate monitors are also
+  updated. ]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+HdComputeReachabilityParameters(mdd_manager *mddManager,
+				Img_ImageInfo_t *imageInfo,
+				mdd_t **reachableStates,
+				mdd_t **fromUpperBound,
+				mdd_t **fromLowerBound,
+				mdd_t **image,
+				FsmHdStruct_t *hdInfo,
+				mdd_t *initialStates,
+				array_t *mintermVarArray,
+				int *depth,
+				int printStep,
+				int shellFlag,
+				array_t *onionRings,
+				int verbosityLevel)
+{
+  float growth;
+  boolean scrapStates;
+  int nvars = Fsm_FsmHdOptionReadNumVars(hdInfo->options);
+  int oldSize;
+  double oldMint;
+  int sizeOfOnionRings = 0;
+  if (shellFlag && onionRings) {
+    sizeOfOnionRings = array_n(onionRings);
+  }
+
+  verbosityLevel = (printStep && (((*depth) % printStep) == 0)) ? verbosityLevel : 0;
+
+  /* keep image if small, record size of the image */
+  oldSize = FsmHdStatsReadSizeReached(hdInfo->stats);
+  oldMint = FsmHdStatsReadMintermReached(hdInfo->stats);
+  FsmHdStatsReset(hdInfo->stats, Fsm_Hd_Reached);
+  FsmHdStatsReset(hdInfo->stats, Fsm_Hd_FromSubset);
+  FsmHdStatsReset(hdInfo->stats, Fsm_Hd_From);
+
+  scrapStates =  Fsm_FsmHdOptionReadScrapStates(hdInfo->options);
+  hdInfo->onlyPartialImage =  Fsm_FsmHdOptionReadOnlyPartialImage(hdInfo->options);
+
+  /* Step 1: Check comments at the top of this function */
+  /* Check if this is a dead end */
+  /* if growth rate of reached is really small, induce a dead-end */
+  hdInfo->deadEndComputation = FALSE;
+  if ((hdInfo->imageOfReachedComputed) ||
+      (mdd_is_tautology(*fromLowerBound, 0)) ||
+      (hdInfo->slowGrowth >= 5)) {
+    /*
+     * if image of reached is computed, add to the dead states.
+     * Set dead-end computation flag and add all new states to Reached.
+     */
+
+    /* add to interior states */
+    hdInfo->interiorStates = AddStates(hdInfo->interiorStates,
+				       hdInfo->interiorStateCandidate,
+				       FSM_MDD_FREE, FSM_MDD_FREE);
+    hdInfo->interiorStateCandidate = NIL(mdd_t);
+    if ((verbosityLevel >= 2) && (hdInfo->interiorStates != NIL(mdd_t))) {
+      fprintf(vis_stdout, "Interior states added, Size = %d, Minterms = %g\n",
+	      mdd_size(hdInfo->interiorStates), mdd_count_onset(mddManager,
+					hdInfo->interiorStates, mintermVarArray));
+    }
+
+    hdInfo->deadEndComputation = TRUE;
+    hdInfo->firstSubset = FALSE;
+    hdInfo->slowGrowth = 0;
+    hdInfo->lastIter = *depth;
+
+    if (!hdInfo->imageOfReachedComputed) {
+      /* Either slow growth or real dead-end */
+      if (verbosityLevel >= 2) {
+	if (!mdd_is_tautology(*fromLowerBound, 0))
+	  fprintf(vis_stdout, "Dead-End triggered by slow growth\n");
+	/* record number of dead ends */
+	(hdInfo->numDeadEnds)++;
+	fprintf(vis_stdout, "Dead-End %d at %g seconds\n", hdInfo->numDeadEnds,
+		(util_cpu_time()/1000.0));
+      }
+
+      /* add another onion ring. */
+      if (shellFlag && onionRings && !mdd_is_tautology(*fromLowerBound, 0)) {
+	mdd_t *temp = mdd_and(*fromLowerBound, *reachableStates, 1, 0);
+	if (!mdd_is_tautology(temp, 0))
+	  array_insert_last(mdd_t *, onionRings, temp);
+	else
+	  mdd_free(temp);
+      }
+      *reachableStates = AddStates(*fromLowerBound, *reachableStates,
+				  FSM_MDD_FREE, FSM_MDD_FREE);
+      *fromUpperBound = *reachableStates;
+
+	  /* perform a dead-end computation */
+      *fromLowerBound = FsmHdDeadEnd(mddManager, imageInfo, *reachableStates,
+				    hdInfo,
+				    mintermVarArray,
+				    FSM_HD_GREEDY, verbosityLevel);
+
+      (*depth)++;
+    }
+  } /* end of if dead-end computation */
+
+  /* Step 2: Check comments at the top of this function */
+  if (!mdd_is_tautology(*fromLowerBound, 0)) {
+    /* add another onion ring. */
+    if (shellFlag && onionRings) {
+      mdd_t *temp = mdd_and(*fromLowerBound, *reachableStates, 1, 0);
+      if (!mdd_is_tautology(temp, 0))
+	array_insert_last(mdd_t *, onionRings, temp);
+      else
+	mdd_free(temp);
+    }
+    /* compute reachable states with new states */
+    *fromUpperBound = *reachableStates;
+    *reachableStates = mdd_or(*fromLowerBound, *fromUpperBound, 1, 1);
+    FsmHdStatsComputeSizeAndMinterms(mddManager, *reachableStates,
+				     mintermVarArray, nvars,
+				     Fsm_Hd_Reached, hdInfo->stats);
+
+
+    /*
+	 * induce a full dead-end computation if jump in size of Reached is
+	 * large. But when the image of Reached has been computed or a dead-end
+	 * computation was just done, this is not done because deadEndComputation
+	 * has been set to 1.
+	 */
+    HdInduceFullDeadEndIfNecessary(mddManager, imageInfo, fromLowerBound,
+				   fromUpperBound, reachableStates, image,
+				   hdInfo, depth, shellFlag, onionRings,
+				   mintermVarArray, oldSize,
+				   oldMint, verbosityLevel);
+  } /* end of  if (!mdd_is_tautology(fromLowerBound, 0)) */
+
+  /* Step 3: Check comments at the top of this function */
+  /* Create subset if necessary */
+  if (!mdd_is_tautology(*fromLowerBound, 0)) {
+    if (!hdInfo->onlyPartialImage) {
+      mdd_t *newStates;
+      /*
+       * Now fromUpperBound has the old reached states, reachableStates
+       * has the new set of states.
+       */
+      newStates = mdd_dup(*fromLowerBound);
+      FsmHdFromComputeDenseSubset(mddManager, fromLowerBound,
+				  fromUpperBound, reachableStates,
+				  image, initialStates, hdInfo,
+				  shellFlag, onionRings, sizeOfOnionRings,
+				  mintermVarArray);
+
+      /* if all new states are chosen from the previous iteration and
+       * all these states have been added then add to interior states.
+       * All new states are sometimes not added when
+       * hdInfo->options->scrapStates is 0. Dead-end computations need not be
+       * considered here since the interior states were already added then.
+       */
+      if ((hdInfo->interiorStateCandidate != NIL(mdd_t)) &&
+	  ((mdd_lequal(newStates, *fromLowerBound, 1, 1)) ||
+	   (scrapStates == TRUE))) {
+	hdInfo->interiorStates = AddStates(hdInfo->interiorStates, hdInfo->interiorStateCandidate,
+				   FSM_MDD_FREE, FSM_MDD_FREE);
+	hdInfo->interiorStateCandidate = NIL(mdd_t);
+	if (verbosityLevel >= 2) {
+	  fprintf(vis_stdout,
+		  "Interior states added, Size = %d, Minterms = %g\n",
+		  mdd_size(hdInfo->interiorStates),
+		  mdd_count_onset(mddManager, hdInfo->interiorStates,
+				  mintermVarArray));
+	}
+      }
+      mdd_free(newStates);
+
+      /* end of if fromLowerbound == 0 && subset Flag*/
+    } else  {
+      mdd_free(*fromUpperBound);
+      if (printStep && ((*depth) % printStep == 0)) {
+	FsmHdStatsComputeSizeAndMinterms(mddManager, *fromLowerBound,
+					 mintermVarArray, nvars, Fsm_Hd_From, hdInfo->stats);
+	FsmHdStatsSetMintermFromSubset(hdInfo->stats, 0.0);
+	FsmHdStatsSetSizeFromSubset(hdInfo->stats, 0);
+      }
+      *fromUpperBound = *reachableStates;
+    }
+  } /* end of if fromLowerBound == 0 */
+  if (hdInfo->interiorStateCandidate != NIL(mdd_t)) {
+    mdd_free(hdInfo->interiorStateCandidate);
+    hdInfo->interiorStateCandidate = NIL(mdd_t);
+  }
+
+  /* monitor growth rate of reached, record if slow growth in consecutive
+   * iterations
+   */
+  if (!mdd_is_tautology(*fromLowerBound, 0)) {
+    FsmHdStatsComputeSizeAndMinterms(mddManager, *reachableStates,
+				     mintermVarArray, nvars, Fsm_Hd_Reached, hdInfo->stats);
+    growth = (float)(FsmHdStatsReadMintermReached(hdInfo->stats) - oldMint)/
+      (float)oldMint;
+    if ((growth < FSM_HD_GROWTH_RATE) &&
+	(((hdInfo->slowGrowth) && ((*depth) == (hdInfo->lastIter) + 1)) || (!(hdInfo->slowGrowth)))) {
+      if (verbosityLevel >= 2) {
+	fprintf(vis_stdout, "Growth rate = %f\n", growth);
+      }
+      (hdInfo->slowGrowth)++;
+      hdInfo->lastIter = *depth;
+    } else {
+      /* reset value */
+      hdInfo->slowGrowth = 0;
+    }
+  }
+  return;
+} /* end of HdComputeReachabilityParameters */
+
+/**Function********************************************************************
+
+  Synopsis [Initializes parameters for incremental computation.]
+
+  Description [Initializes parameters for incremental computation.
+  Instantiates arrayOfRoots and tableOfLeafs, and returns the number of latches
+  in the sytstem.  Upon return, arrayOfRoots is an array of Ntk_Node_t *, and
+  tableOfLeaves is an st_table of Ntk_Node_t *.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+InitializeIncrementalParameters(
+  Fsm_Fsm_t *fsm,
+  Ntk_Network_t *network,
+  array_t **arrayOfRoots,
+  st_table **tableOfLeaves)
+{
+  int numLatch;
+  Ntk_Node_t *node;
+  lsGen gen;
+  int i, mddId;  /* iterate over the nextStateVars of the fsm */
+
+  numLatch = Ntk_NetworkReadNumLatches(network);
+
+  /* This changed to fix a bug.  Instead of reading the roots using
+     Ntk_NetworkForEachCombOutput, we now get them from
+     fsm->fsdData.nextStateVars, which means that the order is consistent with
+     the latter field, as required later on in the incremental reachability
+     code
+
+     old code:
+     *arrayOfRoots = array_alloc(Ntk_Node_t *, numLatch);
+     Ntk_NetworkForEachCombOutput(network, gen, node) {
+     if(Ntk_NodeTestIsLatchDataInput(node)){
+     array_insert_last(Ntk_Node_t *, *arrayOfRoots, node);
+    }
+  }
+  */
+
+  assert(numLatch == array_n(fsm->fsmData.nextStateVars));
+  *arrayOfRoots = array_alloc(Ntk_Node_t *, numLatch);
+
+  arrayForEachItem(int, fsm->fsmData.nextStateVars, i, mddId){
+    Ntk_Node_t *shadow;
+    Ntk_Node_t *latch;
+    Ntk_Node_t *dataInput;
+
+    shadow = Ntk_NetworkFindNodeByMddId(network, mddId);
+    assert(Ntk_NodeTestIsShadow(shadow));
+    latch = Ntk_ShadowReadOrigin(shadow);
+    assert(Ntk_NodeTestIsLatch(latch));
+    dataInput = Ntk_LatchReadDataInput(latch);
+    assert(dataInput != NIL(Ntk_Node_t));
+
+    array_insert(Ntk_Node_t *, *arrayOfRoots, i, dataInput);
+  }
+
+  *tableOfLeaves = st_init_table(st_ptrcmp, st_ptrhash);
+  Ntk_NetworkForEachCombInput(network, gen, node) {
+    st_insert(*tableOfLeaves, (char *)node, (char *) (long) (-1) );
+  }
+  return (numLatch);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes image for incremental computation.]
+
+  Description [Computes image for  incremental computation.]
+
+  SideEffects []
+
+******************************************************************************/
+static mdd_t *
+IncrementalImageCompute(Ntk_Network_t *network,
+			Fsm_Fsm_t *fsm,
+			mdd_manager *mddManager,
+			mdd_t *fromLowerBound,
+			mdd_t *fromUpperBound,
+			mdd_t *toCareSet,
+			array_t *arrayOfRoots,
+			st_table *tableOfLeaves,
+			array_t *smoothVarArray,
+			array_t *relationArray,
+			int numLatch)
+{
+  Mvf_Function_t *function;
+  mdd_t *relation, *optimizedRelation, *toCareSetRV, *imageRV;
+  mdd_t  *subOptimizedRelation, *image;
+  int mddId, i;
+  array_t *arrayOfMvf;
+  mdd_t *frontierSet;
+
+  frontierSet = bdd_between(fromLowerBound, fromUpperBound);
+  /* Create the array of transition relations */
+  toCareSetRV = mdd_substitute(mddManager, toCareSet,
+			       fsm->fsmData.presentStateVars,
+			       fsm->fsmData.nextStateVars);
+
+  arrayOfMvf = Ntm_NetworkBuildMvfs(network, arrayOfRoots,
+				    tableOfLeaves, frontierSet);
+  for (i=0; i < numLatch; i++){
+    function = array_fetch(Mvf_Function_t *, arrayOfMvf, i);
+    mddId = array_fetch(int, fsm->fsmData.nextStateVars, i);
+    /* Since both arrayOfMvf and fsmData have been obtained from */
+    /* the same generator */
+    relation = Mvf_FunctionBuildRelationWithVariable(function,
+						     mddId);
+    subOptimizedRelation = bdd_cofactor(relation, toCareSetRV);
+    mdd_free(relation);
+    optimizedRelation = bdd_cofactor(subOptimizedRelation, frontierSet);
+    mdd_free(subOptimizedRelation);
+    array_insert(mdd_t *, relationArray, i, optimizedRelation);
+  }
+  Mvf_FunctionArrayFree(arrayOfMvf);
+  mdd_free(toCareSetRV);
+  array_insert(mdd_t *, relationArray, numLatch, frontierSet);
+  imageRV = Fsm_MddMultiwayAndSmooth(mddManager, relationArray,
+				     smoothVarArray);
+  /*
+  ** The above call can be substituted by more sophisticated
+  ** Img_MultiwayLinearAndSmooth. However, that will have its
+  ** associated overhead, and could offset any advantage. We
+  ** expect that individual transition relation relations should
+  ** be small and monolithic way to handle them would be ok.
+  ** However, a good strategy would be find the quantification
+  ** schedule which does not change with the computation of
+  ** incremental transition relations.
+  */
+  for (i = 0; i <= numLatch; i++){
+    mdd_free(array_fetch(mdd_t*, relationArray, i));
+  }
+  assert(CheckImageValidity(mddManager, imageRV,
+			    fsm->fsmData.presentStateVars,
+			    fsm->fsmData.inputVars));
+  image = mdd_substitute(mddManager, imageRV,
+			 fsm->fsmData.nextStateVars,
+			 fsm->fsmData.presentStateVars);
+  mdd_free(imageRV);
+  assert(CheckImageValidity(mddManager, image,
+			    fsm->fsmData.nextStateVars,
+			    fsm->fsmData.inputVars));
+  return image;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Prints information about onion rings]
+
+  Description [Prints information about onion rings.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+PrintOnionRings(Fsm_Fsm_t *fsm, int printStep,
+		Fsm_RchType_t approxFlag, int nvars)
+{
+  int i;
+  mdd_t *reachableStates;
+  mdd_manager *mddManager = Fsm_FsmReadMddManager(fsm);
+  array_t *mintermVarArray = Fsm_FsmReadPresentStateVars(fsm);
+
+  fprintf(vis_stdout, "** rch warning: Not possible to compute size of reachable states at every iteration\n");
+  if (Fsm_FsmReadReachabilityOnionRings(fsm) != NIL(array_t)) {
+    arrayForEachItem(mdd_t *, Fsm_FsmReadReachabilityOnionRings(fsm),
+		     i, reachableStates) {
+      if (printStep && (i % printStep == 0)) {
+	if (approxFlag != Fsm_Rch_Hd_c) {
+	  if (nvars <= 1023) {
+	    (void)fprintf(vis_stdout, "BFS step = %d\t|onion ring states| = %8g",
+			  i, mdd_count_onset(mddManager, reachableStates,
+					     mintermVarArray));
+	    if (i != array_n(Fsm_FsmReadReachabilityOnionRings(fsm))-1) {
+	      fprintf(vis_stdout, "\n");
+	    } else {
+	      fprintf(vis_stdout, "\tSize = %d\n", mdd_size(reachableStates));
+	    }
+
+	  } else {
+	    (void)fprintf(vis_stdout, "BFS step = %d\t|onion ring states| = ",
+			  i);
+	    (void) bdd_print_apa_minterm(vis_stdout, reachableStates, nvars, (long)6);
+	    if (i != array_n(Fsm_FsmReadReachabilityOnionRings(fsm))-1) {
+	      fprintf(vis_stdout, "Final Size = %d\n", mdd_size(reachableStates));
+	    }
+	  }
+	} else {
+
+	  if (nvars <= 1023) {
+	    (void)fprintf(vis_stdout, "Step = %d\t|onion ring states| = %8g",
+			  i, mdd_count_onset(mddManager, reachableStates,
+					     mintermVarArray));
+	    if (i != array_n(Fsm_FsmReadReachabilityOnionRings(fsm))-1) {
+	      fprintf(vis_stdout, "\n");
+	    } else {
+	      fprintf(vis_stdout, "\tSize = %d\n", mdd_size(reachableStates));
+	    }
+	  } else {
+	    (void)fprintf(vis_stdout, "Step = %d\t|onion ring states| = ",
+			  i);
+	    (void) bdd_print_apa_minterm(vis_stdout, reachableStates, nvars, (long)6);
+	    if (i != array_n(Fsm_FsmReadReachabilityOnionRings(fsm))-1) {
+	      fprintf(vis_stdout, "Final Size = %d\n", mdd_size(reachableStates));
+	    }
+	  }
+	}
+      }
+    }
+  }
+  return;
+}/* printonionrings */
+
+/**Function********************************************************************
+
+  Synopsis [Reads in a sequence of integers separated by commas and
+  stores them in an array.]
+
+  Description [Reads in a sequence of integers separated by commas from the
+  environment variable guided_search_sequence.  It stores them in an array that
+  it returns.  Alpha characters and 0 integers are replaced by
+  -1.  Pads the remaining entries corresponding to the guide array with -1.
+  Every number indicates the number of times the corresponding (in sequence)
+  hint should be used.  The value -1 means `to convergence'.]
+
+
+  SideEffects []
+
+******************************************************************************/
+static array_t *
+GenerateGuidedSearchSequenceArray(array_t *guideArray)
+{
+  char *seqStr = Cmd_FlagReadByName("guided_search_sequence");
+  char *preStr;
+  int intEntry;
+  array_t *depthArray = array_alloc(int, 0);
+  int i;
+
+  /* Skip parsing if we have no guided search sequence  */
+  if (seqStr != NIL(char)  && strcmp(seqStr, "") != 0){
+    preStr = strtok(seqStr, ",");
+
+    while(preStr != NIL(char)){
+      intEntry = strtol(preStr, (char **) NULL, 10);
+      array_insert_last(int, depthArray, (intEntry == 0 ? -1 : intEntry));
+      preStr = strtok(NIL(char), ",");
+    }
+  }
+
+  if(array_n(depthArray) > array_n(guideArray)){
+    fprintf(vis_stdout, "** rch warning: guided_search_sequence has more entries\n");
+    fprintf(vis_stdout,"than there are hints.  Extra entires will be ignored\n");
+  }
+
+  /* pad with -1s */
+  for (i = array_n(depthArray); i < array_n(guideArray); i++) {
+    array_insert_last(int, depthArray, -1);
+  }
+
+  assert(array_n(depthArray) >= array_n(guideArray));
+
+  return depthArray;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the reachable states, frontier and fromUpperBound.]
+
+  Description [Computes the reachable states, frontier and
+  fromUpperBound. For HD it also generates interior states, interior
+  state candidates, dead-end residue, number of dead-ends, residue
+  count, etc. For guided search, this procedure also generates a
+  dead-end if the frontier is 0. Also this procedure keeps track of
+  convergence and whether a dead-end is required at the end.]
+
+  SideEffects [All arguments are updated.]
+
+  SeeAlso [HdComputeReachabilityParameters FsmHdDeadEnd]
+
+******************************************************************************/
+static void
+ComputeReachabilityParameters(mdd_manager *mddManager,
+			      Img_ImageInfo_t *imageInfo,
+			      Fsm_RchType_t approxFlag,
+			      mdd_t **reachableStates,
+			      mdd_t **fromUpperBound,
+			      mdd_t **fromLowerBound,
+			      mdd_t **image,
+			      FsmHdStruct_t *hdInfo,
+			      mdd_t *initialStates,
+			      array_t *mintermVarArray,
+			      int *depth,
+			      int printStep,
+			      int shellFlag,
+			      array_t *onionRings,
+			      int verbosityLevel,
+			      boolean guidedSearchMode,
+			      mdd_t *hint,
+			      int *hintDepth,
+			      boolean *notConverged)
+{
+  if (approxFlag == Fsm_Rch_Bfs_c) {
+    /* New set of reachable states is old set plus new states in image. */
+    *reachableStates = AddStates(*fromLowerBound, *reachableStates,
+				 FSM_MDD_DONT_FREE, FSM_MDD_FREE);
+    *fromUpperBound = *reachableStates;
+
+    /* in guided search, if the mode is to convergence or the
+       limited depth has not been reached, and the frontier is empty,
+       then generate a frontier in BFS mode (that is a full dead-end).  */
+    if (guidedSearchMode &&
+	mdd_is_tautology(*fromLowerBound, 0) /* no frontier */ &&
+	(hdInfo->deadEndWithOriginalTR == FALSE) /* and guided search */ ) {
+      assert(imageInfo != NIL(Img_ImageInfo_t));
+      if (*hintDepth != 0) {
+	/* add another onion ring. */
+	if (shellFlag && onionRings) {
+	  mdd_t *temp = mdd_and(*fromLowerBound, *reachableStates, 1, 0);
+	  if (!mdd_is_tautology(temp, 0))
+	    array_insert_last(mdd_t *, onionRings, temp);
+	  else
+	    mdd_free(temp);
+	}
+	/* do a full dead-end (non-greedy), compute all the frontier states */
+	mdd_free(*fromLowerBound);
+	*fromLowerBound = FsmHdDeadEnd(mddManager, imageInfo, *reachableStates,
+				       hdInfo,
+				       mintermVarArray,
+				       FSM_HD_NONGREEDY, verbosityLevel);
+	mdd_free(hdInfo->interiorStates);
+	hdInfo->interiorStates = NIL(mdd_t);
+	*reachableStates = AddStates(*fromLowerBound, *reachableStates,
+				     FSM_MDD_DONT_FREE, FSM_MDD_FREE);
+	*fromUpperBound = *reachableStates;
+	(*hintDepth)--;
+	(*depth)++;
+	if (mdd_is_tautology(hint, 1)) hdInfo->deadEndWithOriginalTR = TRUE;
+      } else {
+	*notConverged = TRUE;
+	/* set this flag for correct detection of convergence
+	   Corner case: when limited depth and frontier = 0 */
+      }
+    }
+  } else if (approxFlag == Fsm_Rch_Hd_c) {
+    assert(imageInfo != NIL(Img_ImageInfo_t));
+      if (!guidedSearchMode || (*hintDepth != 0)) {
+	/* computes reachable states, fromLowerBound and fromUpperBound.
+	 * Updates all other quantities such as interiorStates,
+	 * deadEndResidue. */
+	HdComputeReachabilityParameters(mddManager, imageInfo,
+					reachableStates,
+					fromUpperBound,
+					fromLowerBound,
+					image,
+					hdInfo,
+					initialStates,
+					mintermVarArray,
+					depth, printStep,
+					shellFlag, onionRings,
+					verbosityLevel);
+	if (guidedSearchMode) (*hintDepth)--;
+
+      } else { /* guidedSearchMode and hint depth is 0 */
+	if (mdd_is_tautology(*fromLowerBound, 0)) {
+	  *notConverged = TRUE;
+	/* set this flag for correct detection of convergence
+	   Corner case: when limited depth and frontier = 0 */
+	}
+	/* add another onion ring. */
+	if (shellFlag && onionRings) {
+	  mdd_t *temp = mdd_and(*fromLowerBound, *reachableStates, 1, 0);
+	  if (!mdd_is_tautology(temp, 0))
+	    array_insert_last(mdd_t *, onionRings, temp);
+	  else
+	    mdd_free(temp);
+	}
+
+      }
+  }
+  return;
+} /* End of ComputeReachabilityParameters */
Index: vis_dev/vis-2.3/src/grab/grab.c
===================================================================
--- vis_dev/vis-2.3/src/grab/grab.c	(revision 14)
+++ vis_dev/vis-2.3/src/grab/grab.c	(revision 14)
@@ -0,0 +1,1165 @@
+/**CFile***********************************************************************
+
+  FileName    [grab.c]
+
+  PackageName [grab]
+
+  Synopsis    [Abstraction refinement for large scale invariant checking.]
+
+  Description [This file contains the functions to check invariant
+  properties by the GRAB abstraction refinement algorithm. GRAB stands
+  for "Generational Refinement of Ariadne's Bundle," in which the
+  automatic refinement is guided by all shortest abstract
+  counter-examples. For more information, please check the ICCAD'03
+  paper of Wang et al., "Improving Ariadne's Bundle by Following
+  Multiple Counter-Examples in Abstraction Refinement." ]
+  
+  Author      [Chao Wang]
+
+  Copyright   [Copyright (c) 2004 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without
+  license or royalty fees, to use, copy, modify, and distribute this
+  software and its documentation for any purpose, provided that the
+  above copyright notice and the following two paragraphs appear in
+  all copies of this software.]
+
+******************************************************************************/
+
+#include "grabInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+static jmp_buf timeOutEnv;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandGrab(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static void TimeOutHandle(void);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the grab package. The added command is for
+  testing purpose only; the same algorithm can be activated by the
+  check_invariant command.]
+
+  SideEffects []
+
+  SeeAlso     [Refine_End]
+
+******************************************************************************/
+void
+Grab_Init(void)
+{
+  /*
+   * Add a command to the global command table.  By using the leading
+   * underscore, the command will be listed under "help -a" but not "help".
+   */
+  Cmd_CommandAdd("_grab_test", CommandGrab,  0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Ends the grab package.]
+
+  SideEffects []
+
+  SeeAlso     [Refine_Init]
+
+******************************************************************************/
+void
+Grab_End(void)
+{
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Check invariant formulae with abstraction refinement method
+  Grab.]
+
+  Description [Check invariant formulae with the GRAB abstraction
+  refinement method. For each formula, an small initial abstract model
+  is constructed, which contains only the state variables mentioned by
+  the formula. The abstract model is then gradually refined by adding
+  more state variables and Boolean network variables (Bnvs), until it
+  is sufficient to decided the property. Bnvs are internal nodes of
+  the circuit---they are selected in order to partition large
+  combinational logic cones into smaller pieces. The selection of
+  refinement variables (both state vars and Bnvs) is based on the
+  analysis of all the shortest counter-examples, which are captured by
+  a data structure called the Synchronous Onion Rings (SORs). For the
+  algorithmic details, please check the ICCAD'03 paper of Wang et al.,
+  "Improving Ariadne's Bundle by Following Multiple Counter-Examples
+  in Abstraction Refinement," and the ICCD'04 paper of Wang et al.,
+  "Fine-Grain Abstraction and Sequential Don't Cares for Large Scale
+  Model Checking."
+
+  The existence of a network partition is not mandatory for calling
+  this function. However, if it does exist, it will be used by this
+  function; otherwise, the network partition will be constructed
+  incrementally as the abstract model grows. If the default bdd
+  manager is not available, this function will create one and assign
+  bdd ids incrementally as the abstract model grows. (For extremely
+  large models, it is favorable to let the procedure assign bdd ids
+  and construct the partition incrementally.)
+
+  The parameter refineAlgorithm specifies the refinement variable
+  selection algorithm---currently, only GRAB is available. When
+  fineGrainFlag is FALSE, only latches are considered as the
+  abstraction "atoms"; When fineGrainFlag is TRUE, both Bnvs and
+  latches are considered "atoms." To disable the greedy minimization
+  of refinement sets, set refineMinFlag to FALSE. The parameter
+  useArdcFlag is not used at this point. By default, all the shortest
+  counter-examples are analyzed (cexType==GRAB_CEX_SOR); when cexType
+  is set to GRAB_CEX_MINTERM or GRAB_CEX_CUBE, only a minterm or cube
+  state path is analyzed---these two options may be helpful if there
+  is too much overhead of computing the entire SORs.]
+
+  SideEffects [Nothing related to the network is changed: if the
+  default partition and mdd manager are available, they will be left
+  intact; if they are not available, the incrementally created new
+  partition and mdd manager will be freed before exit.]
+
+******************************************************************************/  
+void 
+Grab_NetworkCheckInvariants(
+  Ntk_Network_t *network,
+  array_t *InvariantFormulaArray,
+  char *refineAlgorithm,
+  int fineGrainFlag,
+  int refineMinFlag,
+  int useArdcFlag,
+  int cexType,
+  int verbosity,
+  int dbgLevel,
+  int printInputs,
+  FILE *debugFile,
+  int useMore,
+  char *driverName)
+{
+  mdd_manager     *mddManager = NIL(mdd_manager);
+  graph_t         *partition;
+  Ctlp_Formula_t  *invFormula;
+  Ctlsp_Formula_t *invFormula_sp;
+  array_t         *invStatesArray;
+  array_t         *resultArray;
+  st_table        *absLatchTable, *absBnvTable;
+  st_table        *coiLatchTable, *coiBnvTable;
+  Fsm_Fsm_t       *absFsm;
+  array_t         *visibleVarMddIds, *invisibleVarMddIds;
+  int             concreteLatchCount, abstractLatchCount;
+  int             concreteBnvCount, abstractBnvCount;
+  st_table        *nodeToFaninNumberTable;
+  mdd_t           *rchStates, *invStates = NIL(mdd_t); /*=mdd_one(mddManager);*/
+  array_t         *SORs, *save_SORs;
+  boolean         refineDirection, runMinimization, isLastStep;
+  int             staticOrderFlag, partitionFlag;
+  int             cexLength, refineIteration;
+  array_t         *addedVarsAtCurrentLevel = NIL(array_t);
+  array_t         *addedBnvsAtCurrentLevel = NIL(array_t);
+  int             auxValue1, auxValue2, flag, i;
+
+  long            startTime, endTime, totalTime;
+  long            mcStartTime, mcEndTime, mcTime;
+  long            sorEndTime, sorTime;
+  long            conEndTime, conTime;
+  long            dirStartTime, dirEndTime, dirTime;
+  long            refStartTime, refEndTime, refTime;
+  long            miniStartTime, miniEndTime, miniTime;
+
+
+  if ( strcmp(refineAlgorithm, "GRAB") ) {
+    fprintf(vis_stdout, 
+	    "** ci error: Abstraction refinement method %s not available\n", 
+	    refineAlgorithm);
+    return;
+  }
+
+  /* if the mddIds haven't been assigned to the network nodes, 
+   * we assign them incrementally (i.e., staticOrderFlag==1).
+   */
+  mddManager = Ntk_NetworkReadMddManager(network);
+  if (mddManager == NIL(mdd_manager))
+    staticOrderFlag = 1;
+  else
+    staticOrderFlag = 0;
+
+  if (staticOrderFlag) {
+    GrabNtkClearAllMddIds(network);
+    mddManager = Ntk_NetworkInitializeMddManager(network);
+    if (verbosity >= 2)
+      bdd_dynamic_reordering(mddManager, BDD_REORDER_SIFT, 
+			     BDD_REORDER_VERBOSITY);
+    else
+      bdd_dynamic_reordering(mddManager, BDD_REORDER_SIFT, 
+			     BDD_REORDER_NO_VERBOSITY);
+  }
+
+  /* if the partition hasn't been created, we create the partition
+   * incrementally (i.e., partitionFlag==1)
+   */
+  partition = Part_NetworkReadPartition(network);
+  if (partition == NIL(graph_t))
+    partitionFlag = GRAB_PARTITION_BUILD;
+  else
+    partitionFlag = GRAB_PARTITION_NOCHANGE;
+
+  /* used by the refinement algorithm as a tie-breaker */
+  nodeToFaninNumberTable = st_init_table(st_ptrcmp, st_ptrhash);
+
+  /***************************************************************************
+   * check the invariants
+   ***************************************************************************/
+  resultArray = array_alloc(int, array_n(InvariantFormulaArray));
+
+  arrayForEachItem(Ctlp_Formula_t *, InvariantFormulaArray, i, invFormula) {
+    invFormula_sp = Ctlsp_CtlFormulaToCtlsp(invFormula);
+
+    /* this is required for the following code to function correctly */
+    visibleVarMddIds = invisibleVarMddIds = NIL(array_t);
+    invStatesArray = SORs = save_SORs = NIL(array_t);
+
+    mcTime = sorTime = conTime = dirTime = refTime = miniTime = 0;
+    startTime = util_cpu_ctime();  
+
+    /* record the number of latches in the cone-of-influence */
+    coiLatchTable = GrabComputeCOIAbstraction(network, invFormula);
+    concreteLatchCount = st_count(coiLatchTable);
+    /* build the initial abstract model */
+    absLatchTable = GrabComputeInitialAbstraction(network, invFormula);
+    abstractLatchCount = st_count(absLatchTable);
+    if (verbosity >= 3) {
+      GrabPrintNodeHashTable("InitialAbstractLatches", absLatchTable);
+    }
+
+    /* initialize the abs./concrete table for boolean network variables*/
+    coiBnvTable = st_init_table(st_ptrcmp, st_ptrhash);
+    abstractBnvCount = concreteBnvCount = 0;
+    if (fineGrainFlag == 1) {
+      absBnvTable = st_init_table(st_ptrcmp, st_ptrhash);
+    }else {
+      absBnvTable = NIL(st_table);  
+    }
+    /* if the concrete partition is available, retrieve form it the
+     * bnvs; otherwise, we incrementally create bnvs (for the current
+     * absLatches only)---this is designed for performance concerns */
+    if (partitionFlag == GRAB_PARTITION_NOCHANGE) {
+      Part_PartitionReadOrCreateBnvs(network, coiLatchTable, coiBnvTable);
+      concreteBnvCount = st_count(coiBnvTable);
+    }
+    
+    /* Outer Loop---Over Refinements For Different SOR Lengths
+     */
+    refineIteration = 0;
+    isLastStep = 0;
+    while(1) {
+      long  grabStartTime = util_cpu_ctime();
+      
+      /* Build the Abstract Finite State Machine  */
+      absFsm = GrabCreateAbstractFsm(network, coiBnvTable, absLatchTable,
+				     absBnvTable, partitionFlag, TRUE);
+      concreteBnvCount = st_count(coiBnvTable);      
+      invisibleVarMddIds = GrabGetInvisibleVarMddIds(absFsm, absLatchTable,
+						     absBnvTable);
+      visibleVarMddIds = GrabGetVisibleVarMddIds(absFsm, absLatchTable);
+      /* sanity check  */
+      isLastStep = (array_n(invisibleVarMddIds)==0);
+      if (isLastStep) {
+	assert(abstractLatchCount == concreteLatchCount);
+      }
+
+      /* Compute The Invariant States If They Are Not Available  */
+      if (invStatesArray == NIL(array_t)) {
+	mdd_t * tautology = mdd_one(mddManager);
+	array_t *careSetArray = array_alloc(mdd_t *, 0);
+	array_insert(mdd_t *, careSetArray, 0, tautology);
+	invStates = Mc_FsmEvaluateFormula(absFsm, invFormula, tautology,
+					  NIL(Fsm_Fairness_t), careSetArray,
+					  MC_NO_EARLY_TERMINATION,
+					  NIL(Fsm_HintsArray_t), Mc_None_c,
+					  McVerbosityNone_c, McDcLevelNone_c,
+					  0, McGSH_EL_c);
+	mdd_array_free(careSetArray);
+	invStatesArray = array_alloc(mdd_t *, 0);
+	array_insert(mdd_t *, invStatesArray, 0, invStates);
+      }
+
+      /* Conduct Forward Reachability Analysis  */
+      rchStates = GrabFsmComputeReachableStates(absFsm, 
+						 absLatchTable,
+						 absBnvTable,
+						 invStatesArray,
+						 verbosity);
+
+      mcEndTime = util_cpu_ctime();
+      mcTime += (mcEndTime - grabStartTime);
+      if (verbosity >= 1) {
+	fprintf(vis_stdout, 
+ 	"-- grab: absLatch [%d/%d], absBnv [%d/%d], mc  time is %5g s\n",
+		abstractLatchCount, concreteLatchCount, 
+		abstractBnvCount, concreteBnvCount,
+		(double)(mcEndTime-grabStartTime)/1000.0);
+      }
+
+      /* if bad states cannot be reached, the property is true;
+       * if absFsm is concrete, the property is false 
+       */
+      flag = mdd_lequal(rchStates, invStates, 1, 1);
+      mdd_free(rchStates);
+      if (flag || isLastStep) {
+	/* set the debugging info, if necessary */
+	if (!flag)
+	  SORs = mdd_array_duplicate(Fsm_FsmReadReachabilityOnionRings(absFsm));
+	Fsm_FsmSubsystemFree(absFsm);
+	absFsm = NIL(Fsm_Fsm_t);
+	array_free(invisibleVarMddIds);
+	array_free(visibleVarMddIds);
+	break;
+      }
+
+      /* Build The Synchronous Onion Rings (SORs) */
+      Fsm_FsmFreeImageInfo(absFsm);
+      SORs = GrabFsmComputeSynchronousOnionRings(absFsm, absLatchTable, 
+						 absBnvTable, NIL(array_t),
+						 invStates, cexType, 
+						 verbosity);
+      sorEndTime = util_cpu_ctime();
+      sorTime += (sorEndTime - mcEndTime);
+      
+      /* Concretize Multiple Counter-Examples */
+      cexLength = array_n(SORs)-1;
+      flag = !Bmc_AbstractCheckAbstractTraces(network, SORs, coiLatchTable, 
+					      0, dbgLevel, printInputs);
+      conEndTime = util_cpu_ctime();
+      conTime += (conEndTime - sorEndTime);
+      if (!flag) {
+	if (verbosity >= 1) 
+	  fprintf(vis_stdout, 
+  	  "-- grab: find length-%d concrete counter-examples\n", 
+		cexLength);
+	Fsm_FsmSubsystemFree(absFsm);
+	absFsm = NIL(Fsm_Fsm_t);
+	array_free(invisibleVarMddIds);
+	array_free(visibleVarMddIds);
+	break;
+      }else {
+	if (verbosity >= 2) 
+	  fprintf(vis_stdout, 
+          "-- grab: find length-%d spurious counter-examples\n", 
+		  cexLength);
+      }
+
+      /* Innor Loop---Over Refinements For The Same SOR Length
+       */
+      save_SORs = mdd_array_duplicate(SORs);
+      addedVarsAtCurrentLevel = array_alloc(int, 0);
+      addedBnvsAtCurrentLevel = array_alloc(int, 0);
+      refineDirection = 1;
+      runMinimization = 0;
+
+      while (1) {
+	
+	int skip_refinement = 0;
+
+	/* Get the appropriate refinement direction:
+	 *    runMinimization==1  -->  BOOLEAN
+	 *    fineGrainFlag==0   -->  SEQUENTIAL
+	 *    coiBnvTable is empty  -->  SEQUENTIAL
+	 *    refineDirection==0  -->  BOOLEAN
+	 */
+	if ( !runMinimization && refineDirection) {
+	  if ( fineGrainFlag && st_count(coiBnvTable)>0 ) {
+	    dirStartTime = util_cpu_ctime();
+#if 0 
+	    refineDirection = !GrabTestRefinementSetSufficient(network, 
+							       save_SORs,
+							       absLatchTable,
+							       verbosity);
+#endif
+	    runMinimization = (refineDirection==0);
+	    dirEndTime = util_cpu_ctime();
+	    dirTime += (dirEndTime - dirStartTime);
+	  }
+	}
+
+	if (verbosity >= 3 && refineDirection==0)
+	  fprintf(vis_stdout, "refinement is in %s direction\n", 
+		  (refineDirection? "both":"boolean"));
+
+	/* Minimize the refinement set of latches  */
+	if (runMinimization) { 
+	  int n_latches = st_count(absLatchTable);
+	  int break_flag;
+	  if (refineMinFlag && array_n(addedVarsAtCurrentLevel) > 1) {
+	    miniStartTime = util_cpu_ctime();
+	    GrabMinimizeLatchRefinementSet(network, 
+					   &absLatchTable,
+					   &absBnvTable,
+					   addedVarsAtCurrentLevel,
+					   &addedBnvsAtCurrentLevel,
+					   save_SORs,
+					   verbosity);
+	    abstractLatchCount = st_count(absLatchTable);
+	    abstractBnvCount = absBnvTable? st_count(absBnvTable):st_count(coiBnvTable);
+	    array_free(addedVarsAtCurrentLevel);
+	    addedVarsAtCurrentLevel = array_alloc(int, 0);	    
+	    miniEndTime = util_cpu_ctime();
+	    miniTime += (miniEndTime - miniStartTime);
+	  }
+
+	  /* if the refinement set of bnvs is also sufficient, break */
+	  break_flag = 1;
+	  if (fineGrainFlag && st_count(coiBnvTable)>0) {
+	    dirStartTime = util_cpu_ctime();
+	    break_flag = GrabTestRefinementBnvSetSufficient(network,
+							    coiBnvTable,
+							    save_SORs, 
+							    absLatchTable,
+							    absBnvTable,
+							    verbosity);
+	    dirEndTime = util_cpu_ctime();
+	    dirTime += (dirEndTime - dirStartTime);
+	  }
+	  if (break_flag) {
+	    if (verbosity >= 1)
+	      fprintf(vis_stdout, 
+	      "-- grab: remove length-%d spurious counter-examples\n\n",
+		      cexLength);
+	    break;
+	  }
+
+	  /* Otherwise, skip this refinement step, because the
+	   * current absFsm is not well-defined (some latches have
+	   * been droped)
+	   */
+	  SORs = mdd_array_duplicate(save_SORs);
+	  if (n_latches > st_count(absLatchTable))
+	    skip_refinement = 1;
+
+	  refineDirection = 0;
+	  runMinimization = 0;
+	}
+      
+	/* compute the refinement (by Grab)
+	 */
+	if (!skip_refinement) {
+	  array_t *addedVars = array_alloc(int, 0);
+	  array_t *addedBnvs = array_alloc(int, 0);
+	  auxValue1 = st_count(absLatchTable) + 
+	    ((absBnvTable==NIL(st_table))? 0:st_count(absBnvTable));
+
+	  refStartTime = util_cpu_ctime();
+
+	  /* create the abstract fsm   */
+	  Fsm_FsmSubsystemFree(absFsm);
+	  absFsm = GrabCreateAbstractFsm(network, coiBnvTable, absLatchTable,
+					 absBnvTable, 
+					 GRAB_PARTITION_NOCHANGE, 
+					 FALSE);
+	  /* pick refinement variables */
+	  GrabRefineAbstractionByGrab(absFsm, 
+				      SORs,
+				      absLatchTable,
+				      absBnvTable,
+				      addedVars,
+				      addedBnvs,
+				      refineDirection,
+				      nodeToFaninNumberTable,
+				      verbosity);
+	  array_append(addedVarsAtCurrentLevel, addedVars);
+	  array_append(addedBnvsAtCurrentLevel, addedBnvs);
+	  array_free(addedVars);
+	  array_free(addedBnvs);
+	  /* Sanity check! */
+	  auxValue2 = st_count(absLatchTable) + 
+	    ((absBnvTable==NIL(st_table))? 0:st_count(absBnvTable));
+	  assert(auxValue1 < auxValue2);
+
+	  abstractLatchCount = st_count(absLatchTable);
+	  abstractBnvCount = absBnvTable? st_count(absBnvTable):st_count(coiBnvTable);
+	  
+	  refEndTime = util_cpu_ctime();
+	  refTime += (refEndTime - refStartTime);
+	  if (verbosity >= 3) {
+	    fprintf(vis_stdout, 
+	      "-- grab: absLatch [%d/%d], absBnv [%d/%d], ref time is %5g s\n",
+		    abstractLatchCount, concreteLatchCount, 
+		    abstractBnvCount, concreteBnvCount,
+		    (double)(refEndTime - refStartTime)/1000.0);
+	  }
+
+	  refineIteration++;
+	}
+      
+	/* Create The Refined Abstract FSM */
+	Fsm_FsmSubsystemFree(absFsm);
+	array_free(invisibleVarMddIds);
+	array_free(visibleVarMddIds);
+	absFsm = GrabCreateAbstractFsm(network, coiBnvTable, absLatchTable,
+				       absBnvTable, partitionFlag, TRUE);
+	invisibleVarMddIds = GrabGetInvisibleVarMddIds(absFsm, absLatchTable,
+						       absBnvTable);
+	visibleVarMddIds = GrabGetVisibleVarMddIds(absFsm, absLatchTable);
+	concreteBnvCount = st_count(coiBnvTable);	
+	/* sanity check */
+	isLastStep = (array_n(invisibleVarMddIds)==0);
+	if (isLastStep) {
+	  assert(abstractLatchCount == concreteLatchCount);
+	}
+
+	/* Reduce The Current SORs (with forward reachability analysis) */
+	mcStartTime = util_cpu_ctime();
+	rchStates = GrabFsmComputeConstrainedReachableStates(absFsm, 
+							     absLatchTable,
+							     absBnvTable,
+							     SORs, 
+							     verbosity);
+	mdd_array_free(SORs);
+	SORs = NIL(array_t);
+	mcEndTime = util_cpu_ctime();
+	mcTime += (mcEndTime - mcStartTime);
+	if (verbosity >= 2) {
+	  fprintf(vis_stdout, 
+	      "-- grab: absLatch [%d/%d], absBnv [%d/%d], mc  time is %5g s\n",
+		  abstractLatchCount, concreteLatchCount, 
+		  abstractBnvCount, concreteBnvCount,
+		  (double)(mcEndTime-mcStartTime)/1000.0);
+	}
+
+	/* if bad states is no longer reachable, break out  */
+	flag = mdd_lequal(rchStates, invStates, 1, 1);
+	mdd_free(rchStates);
+	if (isLastStep || flag) {
+	  if (!isLastStep && refineDirection == 1) {
+	    runMinimization = 1;
+	    refineDirection = 0;
+	    continue;
+	  }else
+	    break;
+	}
+
+	/* Build the new SORs (with backward reachability analysis)  */
+	Fsm_FsmFreeImageInfo(absFsm);
+	SORs = GrabFsmComputeSynchronousOnionRings(absFsm, 
+						   absLatchTable, 
+						   absBnvTable,
+						   NIL(array_t), 
+						   invStates,
+						   cexType, 
+						   verbosity);
+	sorEndTime = util_cpu_ctime();
+	sorTime += (sorEndTime - mcEndTime);
+
+      } /* End of the Inner Loop */
+
+
+      /* Minimize The Refinement Set of Boolean Network Variables (BNVs)
+       */
+      if (fineGrainFlag==1 && refineMinFlag 
+	  && array_n(addedBnvsAtCurrentLevel)>1) {
+
+	miniStartTime = util_cpu_ctime();
+	GrabMinimizeBnvRefinementSet(network, 
+				     coiBnvTable,
+				     absLatchTable,
+				     &absBnvTable,
+				     addedBnvsAtCurrentLevel,
+				     save_SORs,
+				     verbosity);
+	abstractLatchCount = st_count(absLatchTable);
+	abstractBnvCount = st_count(absBnvTable);
+	miniEndTime = util_cpu_ctime();
+	miniTime += (miniEndTime - miniStartTime);
+      }
+      mdd_array_free(save_SORs);
+
+      /* Clean-ups 
+       */
+      Fsm_FsmSubsystemFree(absFsm);
+      absFsm = NIL(Fsm_Fsm_t);
+      array_free(invisibleVarMddIds);
+      array_free(visibleVarMddIds);
+      array_free(addedVarsAtCurrentLevel);
+      array_free(addedBnvsAtCurrentLevel);
+      addedVarsAtCurrentLevel = NIL(array_t);
+      addedBnvsAtCurrentLevel = NIL(array_t);
+
+    } /* End of the Outer Loop */
+
+    endTime = util_cpu_ctime();
+    totalTime = endTime - startTime;
+
+    /* Print out the debugging information */
+    if (dbgLevel > 0) {
+      FILE        *tmpFile = vis_stdout;
+      extern FILE *vis_stdpipe;
+
+      if (debugFile)
+	vis_stdpipe = debugFile;
+      else if (useMore)
+	vis_stdpipe = popen("more", "w");
+      else
+	vis_stdpipe = vis_stdout;
+      vis_stdout = vis_stdpipe;
+      
+      if (flag) {
+	fprintf(vis_stdout, "# %s: formula passed --- ", driverName);
+	Ctlp_FormulaPrint(vis_stdout, invFormula);
+	fprintf(vis_stdout, "\n");
+      }else {
+        if(dbgLevel != 2)
+        {
+	   fprintf(vis_stdout, "# %s: formula p%d failed --- ", driverName, i+1);
+	   Ctlp_FormulaPrint(vis_stdout, invFormula);
+           fprintf(vis_stdout, "\n# %s: calling debugger\n", driverName);
+        }
+	flag = !Bmc_AbstractCheckAbstractTraces(network, SORs, coiLatchTable,
+						1, dbgLevel, printInputs);
+      }
+
+      if (vis_stdout != tmpFile && vis_stdout != debugFile)
+	(void)pclose(vis_stdpipe);
+      vis_stdout = tmpFile;
+    }
+
+    if (verbosity >= 2 ) {
+      fprintf(vis_stdout, "\n-- grab: total cpu time = %5g\n", 
+	      (double)totalTime/1000.0);
+      if (verbosity >= 3) {
+	fprintf(vis_stdout,   "-- grab:       mc  time = %5.1f\t(%3.1f%%)\n", 
+		(double)mcTime/1000.0, (100.0*mcTime/totalTime));
+	fprintf(vis_stdout,   "-- grab:       sor time = %5.1f\t(%3.1f%%)\n", 
+		(double)sorTime/1000.0, (100.0*sorTime/totalTime));
+	fprintf(vis_stdout,   "-- grab:       con time = %5.1f\t(%3.1f%%)\n", 
+		(double)conTime/1000.0, (100.0*conTime/totalTime));
+	fprintf(vis_stdout,   "-- grab:       ref time = %5.1f\t(%3.1f%%)\n", 
+		(double)refTime/1000.0, (100.0*refTime/totalTime));
+	fprintf(vis_stdout,   "-- grab:       min time = %5.1f\t(%3.1f%%)\n", 
+		(double)miniTime/1000.0,(100.0*miniTime/totalTime));
+	fprintf(vis_stdout,   "-- grab:       dir time = %5.1f\t(%3.1f%%)\n", 
+		(double)dirTime/1000.0, (100.0*dirTime/totalTime));
+      }
+    }
+
+    if (verbosity >= 1) {
+      if (concreteLatchCount > 0) {
+        fprintf(vis_stdout, "-- grab: abs latch percentage = %d %%\n", 
+	      100 * abstractLatchCount/concreteLatchCount );
+      }
+      if (verbosity >= 3) {
+	fprintf(vis_stdout, "-- grab: abs latch = %d\n", abstractLatchCount);
+	fprintf(vis_stdout, "-- grab: coi latch = %d\n", concreteLatchCount);
+      }
+      if (concreteBnvCount > 0) {
+	fprintf(vis_stdout, "-- grab: abs bnv   percentage = %d %%\n", 
+		(100 * abstractBnvCount/concreteBnvCount) );
+	if (verbosity >= 3) {
+	  fprintf(vis_stdout, "-- grab: abs bnv   = %d\n", abstractBnvCount);
+	  fprintf(vis_stdout, "-- grab: coi bnv   = %d\n", concreteBnvCount);
+	}
+	abstractBnvCount += abstractLatchCount;
+	concreteBnvCount += concreteLatchCount;
+	fprintf(vis_stdout, "-- grab: total abs var percentage  = %d %%\n", 
+		(100 * abstractBnvCount/concreteBnvCount) );
+	if (verbosity >= 3) {
+	  fprintf(vis_stdout, "-- grab:       abs var  = %d\n", 
+		  abstractBnvCount);
+	  fprintf(vis_stdout, "-- grab:       coi var  = %d\n", 
+		  concreteBnvCount);
+	}
+      }
+      fprintf(vis_stdout, "-- grab: total refinement iterations = %d\n", 
+	      refineIteration);
+      fprintf(vis_stdout,  "-- grab: total image    computations %d\n",
+	      Img_GetNumberOfImageComputation(Img_Forward_c));
+      fprintf(vis_stdout,  "-- grab: total preimage computations %d\n",
+	      Img_GetNumberOfImageComputation(Img_Backward_c));
+
+      if (verbosity >= 3) {
+	GrabPrintNodeHashTable("AbstractLatchRankings", absLatchTable);
+	if (fineGrainFlag)
+	  GrabPrintNodeHashTable("AbstractBnvRankings", absBnvTable);
+      }
+    }
+
+    /* Clean-up's
+     */
+    st_free_table(coiLatchTable);
+    st_free_table(absLatchTable);
+    st_free_table(coiBnvTable);
+    if (fineGrainFlag) {
+      st_free_table(absBnvTable);
+    }
+    mdd_array_free(invStatesArray);
+    if (!flag)  mdd_array_free(SORs);
+
+    Ctlsp_FormulaFree(invFormula_sp);
+
+    /* Store the verification results in an array (1--passed, 0--failed) */
+    array_insert(int, resultArray, i, flag);
+  }
+
+  /* print whether the set of invariants passed or failed 
+   */
+  fprintf(vis_stdout, "\n# %s: Summary of invariant pass/fail\n", driverName);
+  arrayForEachItem(Ctlp_Formula_t *, InvariantFormulaArray, i, invFormula) {
+    flag = array_fetch(int, resultArray, i);
+    if (flag) {
+      (void) fprintf(vis_stdout, "# %s: formula passed --- ", driverName);
+      Ctlp_FormulaPrint(vis_stdout, (invFormula));
+      fprintf(vis_stdout, "\n");
+    } else {
+      (void) fprintf(vis_stdout, "# %s: formula failed --- ", driverName);
+      Ctlp_FormulaPrint(vis_stdout, (invFormula));
+      fprintf(vis_stdout, "\n");
+    }
+  }
+
+  /* free the current partition and mdd manager if necessary */
+  if (partitionFlag) {
+    Ntk_NetworkFreeApplInfo(network, PART_NETWORK_APPL_KEY);
+  }
+  if (staticOrderFlag) {
+    mdd_quit(mddManager);
+    Ntk_NetworkSetMddManager(network, NIL(mdd_manager));
+    GrabNtkClearAllMddIds(network);
+  }
+  st_free_table(nodeToFaninNumberTable);
+  array_free(resultArray);
+
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the test command for Grab.]
+
+  CommandName [_grab_test]
+
+  CommandSynopsis [Performs invairant checking on a flattened network
+  with the GRAB abstraction refinement algorithm.]
+
+  CommandArguments [ \[-a &lt;refine_algorithm&gt;\] \[-c &lt;cex_type&gt;\]
+  \[-d &lt;dbg_level&gt;\] \[-F\] \[-M\] \[-i\] \[-m\]
+  \[-t &lt;time_out_period&gt;\] \[-v &lt;verbosity_level&gt;\]
+  \[-f &lt;dbg_file&gt;\] \[-h\]  &lt;inv_file&gt;]
+
+  CommandDescription [Performs invairant checking on a flattened
+  network with the GRAB abstraction refinement algorithm.  Before
+  calling this command, the user should have created the flattened
+  netowrk by calling the commands <A
+  HREF="flatten_hierarchyCmd.html"><code> flatten_hierarchy</code></A>
+  and <A
+  HREF="build_partition_maigsCmd.html"><code>build_partition_maigs</code></A>.
+  The default BDD manager and network partition are not mandatory for
+  calling this command, though they will be used if available. (In
+  other words, the user doesn't have to run the commands <A
+  HREF="static_orderCmd.html"><code>static_order</code></A> and <A
+  HREF="build_partition_mddsCmd.html"><code>build_partition_mdds</code></A>
+  before calling this command.)
+
+  Regardless of the options, no 'false positive' or 'false negatives'
+  will occurs: the result is correct for the given model.
+
+  Properties to be verified should be provided as invariant formulae
+  in the file <code>inv_file</code>. Node that the support of any wire
+  referred to in a formula should consist only of latches. For the
+  precise syntax of CTL and LTL formulas, see the <A
+  HREF="../ctl/ctl/ctl.html"> VIS CTL and LTL syntax
+  manual</A>.  <p>
+
+  If a formula does not pass, a proof of failure (referred to as a
+  counter-example) is demonstrated. Whether demostrate the proof or
+  not can be specified (see option <code>-d</code>).  <p>
+
+  Command options:
+  <p>
+
+  <dl>
+
+  <dt> -a <code> &lt;refine_algorithm&gt; </code>
+  <dd> Specify the refinement variable selection algorithm.
+  <p>
+  <dd> <code>refine_algorithm</code> must be one of the following:
+  
+  <p><code>GRAB</code>: the GRAB refinement method (Default).
+  
+  <p>
+
+  <dt> -c <code> &lt;cex_type&gt; </code> <dd> Specify the type of
+  abstract counter-examples used in the analysis.
+  <p>
+  
+  <dd> <code>cex_type</code> must be one of the following:
+  
+  <p><code>0</code>: minterm state counter-example.
+  <p><code>1</code>: cube state counter-example.
+  <p><code>2</code>: synchronous onion rings (Default).
+  <p>
+
+  <dt> -d <code> &lt;dbg_level&gt; </code>
+  <dd> Specify whether to demonstrate a counter-example when the
+  system fails a formula being checked.
+
+  <p> <dd> <code> dbg_level</code> must be one of the following:
+
+  <p><code>0</code>: No debugging performed.
+  <code>dbg_level</code>=<code>0</code> is the default.
+
+  <p><code>1</code>: Generate a counter-example (a path to a fair cycle).
+  <p>
+
+  <dt> -F <code> &lt;finegrain_flag&gt; </code> <dd> Enable or disable
+  the use of fine-grain abstraction.
+  <p>
+  
+  <dd> <code>finegrain_flag</code> must be one of the following:
+  
+  <p><code>0</code>: disable fine-grain abstraction.
+  <p><code>1</code>: enable fine-grain abstraction (Default).
+  <p>
+
+  <dt> -M <code> &lt;refinemin_flag&gt; </code> <dd> Enable or disable
+  the use of greedy refinement minimization.
+  <p>
+  
+  <dd> <code>refinemin_flag</code> must be one of the following:
+  
+  <p><code>0</code>: disable greedy refinement minimization.
+  <p><code>1</code>: enable greedy refinement minimization (Default).
+  <p>
+
+  <dt> -i
+  <dd> Print input values causing transitions between states during debugging.
+  Both primary and pseudo inputs are printed.
+  <p>
+
+  <dt> -m
+  <dd> Pipe debugger output through the UNIX utility  more.
+  <p>
+
+  <dt> -t  <code>&lt;timeOutPeriod&gt;</code>
+  <dd> Specify the time out period (in seconds) after which the command aborts.
+  By default this option is set to infinity.
+  <p>
+
+   <dt> -v  <code>&lt;verbosity_level&gt;</code>
+  <dd> Specify verbosity level. This sets the amount of feedback  on CPU usage 
+  and code status.
+
+  <br><code>verbosity_level</code>  must be one of the following:<p>
+  
+  <code>0</code>: No feedback provided. This is the default.<p>
+
+  <code>1</code>: Feedback on code location.<p>
+
+  <code>2</code>: Feedback on code location and CPU usage.<p>
+
+  <p>
+
+  <dt> -f  <code>&lt;dbg_out&gt;</code>
+  <dd> Specify the name of the file ot which error trace is written.
+  <p>
+
+  <dt> -h
+  <dd> Print the command usage.
+  <p>
+  
+  See also commands : model_check, check_invariant ]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandGrab(
+  Hrc_Manager_t ** hmgr,
+  int              argc,
+  char **          argv)
+{
+  int             c, verbosity;
+  char            InvFileName[256];
+  FILE            *FP, *dbgFile;
+  array_t         *InvariantFormulaArray;
+  Ntk_Network_t   *network;
+  static int      timeOutPeriod = 0;
+  
+  char       refineAlgorithm[256];
+  int        cexType = 0;  
+  int        refineMinFlag;
+  int        fineGrainFlag;
+  int        useArdcFlag = 0;
+  long       startTime, endTime;
+
+  char       *dbgFileName = NIL(char);
+  int        dbgLevel, printInputs, useMore;
+
+  startTime = util_cpu_ctime();
+
+  Img_ResetNumberOfImageComputation(Img_Both_c);
+
+  /* the default setting is Grab+, 
+   * Generational Refinement of Ariadne's Bundle of SORs
+   */
+  strcpy(refineAlgorithm, "GRAB");
+  cexType = GRAB_CEX_SOR;
+  fineGrainFlag = 1;
+  refineMinFlag = 1;
+  verbosity = 0;
+
+  dbgLevel = 0;
+  printInputs = 0;
+  useMore = 0;
+  
+  /*
+   * Parse command line options.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "a:c:d:F:M:imt:v:f:h")) != EOF) {
+    switch(c) {
+      case 'a':
+	strcpy(refineAlgorithm, util_optarg);
+	break;
+      case 'F':
+	fineGrainFlag = atoi(util_optarg);
+	break;
+      case 'M':
+	refineMinFlag = atoi(util_optarg);
+	break;
+      case 'c':
+	cexType = atoi(util_optarg);
+	break;
+      case 'D':
+	useArdcFlag = 1;
+	break;
+      case 't':
+        timeOutPeriod = atoi(util_optarg);
+        break;
+      case 'v':
+        verbosity = atoi(util_optarg);
+        break;
+      case 'd':
+	dbgLevel = atoi(util_optarg);
+	break;
+      case 'i':
+	printInputs = 1;
+	break;
+      case 'm':
+	useMore = 1;
+	break;
+      case 'f':
+	dbgFileName = util_strsav(util_optarg);
+	break;
+      case 'h':
+        goto usage;
+      default:
+        goto usage;
+    }
+  }
+
+  if (strcmp(refineAlgorithm, "GRAB")) {
+    fprintf(vis_stdout, "\nunknown refinement algorithm: %s\n", 
+	    refineAlgorithm);
+    goto usage;
+  }
+
+  /* Make sure the flattened network  is available
+   */
+  network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+  if (network == NIL(Ntk_Network_t)) {
+    fprintf(vis_stdout, "%s\n", error_string());
+    error_init();
+    return 1;
+  }
+
+  /* Make sure the AIG graph is available 
+   */
+  if (Ntk_NetworkReadMAigManager(network) == NIL(mAig_Manager_t)) {
+    fprintf(vis_stderr, 
+	    "** grab error: please run buid_partiton_maigs first\n");
+    return 1;
+  }
+
+  /* Open the InvFile. (It must contain a single invariant property)
+   */
+  if (argc - util_optind == 0) {
+    (void) fprintf(vis_stderr, 
+		"** grab error: file containing inv formula not provided\n");
+    goto usage;
+  }else if (argc - util_optind > 1) {
+    (void) fprintf(vis_stderr, "** grab error: too many arguments\n");
+    goto usage;
+  }
+  strcpy(InvFileName, argv[util_optind]);
+
+  /* Parsing the InvFile
+   */
+  FP = Cmd_FileOpen(InvFileName, "r", NIL(char *), 0);
+  if (FP == NIL(FILE)) {
+    (void) fprintf(vis_stdout,  "** grab error: error in opening file %s\n", 
+		   InvFileName);
+    return 1;
+  }
+  InvariantFormulaArray = Ctlp_FileParseFormulaArray(FP);
+  fclose(FP);
+  if (InvariantFormulaArray == NIL(array_t)) {
+    (void) fprintf(vis_stdout,
+		   "** grab error: error in parsing formulas from file %s\n",
+		   InvFileName);
+    return 1;
+  }
+
+  if (dbgFileName != NIL(char)) 
+    dbgFile = Cmd_FileOpen(dbgFileName, "r", NIL(char *), 0);
+  else
+    dbgFile = NIL(FILE);
+
+
+  /* Set time out processing (if timeOutPeriod is set) 
+   */
+  if (timeOutPeriod > 0) {
+    (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
+    (void) alarm(timeOutPeriod);
+    if (setjmp(timeOutEnv) > 0) {
+      fprintf(vis_stdout, 
+	   "\n# GRAB: abstract-refine - timeout occurred after %d seconds.\n", 
+	      timeOutPeriod);
+      (void) fprintf(vis_stdout, "# GRAB: data may be corrupted.\n");
+      endTime = util_cpu_ctime();
+      fprintf(vis_stdout, "# GRAB: elapsed time is %5.1f.\n",
+	      (double)(endTime - startTime)/1000.0);
+      if (verbosity) {
+	fprintf(vis_stdout, 
+	      "-- total %d image computations and %d preimage computations\n", 
+		Img_GetNumberOfImageComputation(Img_Forward_c), 
+		Img_GetNumberOfImageComputation(Img_Backward_c));
+      }
+      alarm(0);
+      return 1;
+    }
+  }
+
+  /* Check invariants with the abstraction refinement algorithm GRAB 
+   */
+  Grab_NetworkCheckInvariants(network, 
+			      InvariantFormulaArray,
+			      refineAlgorithm,
+			      fineGrainFlag,
+			      refineMinFlag,
+			      useArdcFlag,
+			      cexType,
+			      verbosity,
+			      dbgLevel,
+			      printInputs,
+			      dbgFile,
+			      useMore,
+			      "GRAB"
+			      );
+
+
+  /* Total cost 
+   */
+  if (verbosity >= 2) {
+    endTime = util_cpu_ctime();
+    fprintf(vis_stdout, "# GRAB: elapsed time is %5.1f.\n",
+	    (double)(endTime - startTime)/1000.0);
+    fprintf(vis_stdout, 
+	    "-- total %d image computations and %d preimage computations\n", 
+	    Img_GetNumberOfImageComputation(Img_Forward_c), 
+	    Img_GetNumberOfImageComputation(Img_Backward_c));
+  }
+
+  alarm(0);
+  return 0;		/* normal exit */
+
+
+  usage:
+
+  (void) fprintf(vis_stderr, "usage: _grab_test [-a refine_algorithm] [-c cex_type] [-d dbg_level] [-F finegrain_flag] [-M refmin_flag] [-i] [-m] [-t period] [-v verbosity_level] [-f dbg_out] [-h] <invar_file>\n");
+  (void) fprintf(vis_stderr, "    -a <refine_algorithm>\n");
+  (void) fprintf(vis_stderr, "        refine_algorithm = GRAB => the GRAB refinement method (Default)\n");
+  (void) fprintf(vis_stderr, "    -c <cex_type>\n");
+  (void) fprintf(vis_stderr, "        cex_type = 0 => minterm state counter-example\n");
+  (void) fprintf(vis_stderr, "        cex_type = 1 => cube state counter-example\n");
+  (void) fprintf(vis_stderr, "        cex_type = 2 => synchronous onion rings (Default)\n");
+  (void) fprintf(vis_stderr, "    -d <dbg_level>\n");
+  (void) fprintf(vis_stderr, "        debug_level = 0 => no debugging (Default)\n");
+  (void) fprintf(vis_stderr, "        debug_level = 1 => print path to state failing invariant\n");
+  (void) fprintf(vis_stderr, "    -F <finegrain_flag>\n");
+  (void) fprintf(vis_stderr, "        finegrain_flag = 0 => disable fine-grain abstraction\n");
+  (void) fprintf(vis_stderr, "        finegrain_flag = 1 => enable fine-grain abstraction (Default)\n");
+  (void) fprintf(vis_stderr, "    -M <refinemin_flag>\n");
+  (void) fprintf(vis_stderr, "        refinemin_flag = 0 => disable greedy refinement minimization\n");
+  (void) fprintf(vis_stderr, "        refinemin_flag = 1 => enable greedy refinement minimization (Default)\n");
+  (void) fprintf(vis_stderr, "    -i \tPrint input values in debug traces.\n");
+  (void) fprintf(vis_stderr, "    -m  pipe debugger output through UNIX utility more\n");
+  (void) fprintf(vis_stderr, "    -t <period> Time out period.\n");
+  (void) fprintf(vis_stderr, "    -v <verbosity_level>\n");
+  (void) fprintf(vis_stderr, "        verbosity_level = 0 => no feedback (Default)\n");
+  (void) fprintf(vis_stderr, "        verbosity_level = 1 => code status\n");
+  (void) fprintf(vis_stderr, "        verbosity_level = 2 => code status and CPU usage profile\n");
+  (void) fprintf(vis_stderr, "    -f <dbg_out>\n");
+  (void) fprintf(vis_stderr, "        write error trace to dbg_out\n");
+  (void) fprintf(vis_stderr, "    <invar_file> The input file containing invariants to be checked.\n");
+  (void) fprintf(vis_stderr, "   -h\t\t print the command usage\n");
+
+  return 1;		/* error exit */
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Handle function for timeout.]
+
+  Description [This function is called when the process receives a signal of
+  type alarm. Since alarm is set with elapsed time, this function checks if the
+  CPU time corresponds to the timeout of the command. If not, it reprograms the
+  alarm to fire later and check if the CPU limit has been reached.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+TimeOutHandle(void)
+{
+  longjmp(timeOutEnv, 1);
+} 
Index: vis_dev/vis-2.3/src/grab/grab.h
===================================================================
--- vis_dev/vis-2.3/src/grab/grab.h	(revision 14)
+++ vis_dev/vis-2.3/src/grab/grab.h	(revision 14)
@@ -0,0 +1,70 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [grab.h]
+
+  PackageName [grab]
+
+  Synopsis    [Abstraction refinement for large scale invariant checking.]
+
+  Description [Abstraction refinement for large scale invariant checking.]
+
+  Author      [Chao Wang.]
+
+  Copyright   [Copyright (c) 2004 The Regents of the Univ. of Colorado. All 
+  rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+  ]
+  
+******************************************************************************/
+
+#ifndef _GRAB
+#define _GRAB
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "vm.h"
+#include "ntk.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void Grab_Init(void);
+EXTERN void Grab_End(void);
+EXTERN void Grab_NetworkCheckInvariants(Ntk_Network_t *network, array_t *InvariantFormulaArray, char *refineAlgorithm, int fineGrainFlag, int refineMinFlag, int useArdcFlag, int cexType, int verbosity, int dbgLevel, int printInputs, FILE *debugFile, int useMore, char *driverName);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _GRAB */
Index: vis_dev/vis-2.3/src/grab/grab.make
===================================================================
--- vis_dev/vis-2.3/src/grab/grab.make	(revision 14)
+++ vis_dev/vis-2.3/src/grab/grab.make	(revision 14)
@@ -0,0 +1,4 @@
+CSRC +=  grabUtil.c grabBMC.c grabGrab.c grab.c
+HEADERS += grab.h grabInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/grab/grabBMC.c
===================================================================
--- vis_dev/vis-2.3/src/grab/grabBMC.c	(revision 14)
+++ vis_dev/vis-2.3/src/grab/grabBMC.c	(revision 14)
@@ -0,0 +1,534 @@
+/**CFile***********************************************************************
+
+  FileName    [grabBMC.c]
+
+  PackageName [grab]
+
+  Synopsis    [Check abstract paths on a more concrete model using SAT.]
+
+  Description [Abstract paths are given in an array of MDDs, which
+  capture multiple abstract paths at the same time. MDDs are encoded
+  as AIG graph to allow the check in the more concrete model.]
+    
+  Author      [Chao Wang]
+
+  Copyright   [Copyright (c) 2004 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without
+  license or royalty fees, to use, copy, modify, and distribute this
+  software and its documentation for any purpose, provided that the
+  above copyright notice and the following two paragraphs appear in
+  all copies of this software.]
+
+******************************************************************************/
+
+#include "grabInt.h"
+#include "bmcInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static bAigEdge_t GrabConvertBddToBaig(bAig_Manager_t *bAigManager, bdd_t *fn, st_table *bddidToNames);
+static st_table * GrabBddGetSupportBaigNames(mdd_manager *mddManager, mdd_t *f);
+static char * GrabBddIdToBaigNames(mdd_manager *mddManager, int bddid);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Check if the abstract paths exist in the model.]
+
+  Description [Check if the abstract paths exist in the model. The
+  paths are given as set of onion rings, where each ring is a set of
+  states. The model is defined by the set of latches in absLatches.]
+
+  SideEffects []
+
+******************************************************************************/
+boolean
+Bmc_AbstractCheckAbstractTraces(
+  Ntk_Network_t *network,
+  array_t *synOnionRings,
+  st_table *absLatches,
+  int verbose, 
+  int dbgLevel,
+  int printInputs)
+{
+  int               pathLength = array_n(synOnionRings) -1;
+  mAig_Manager_t    *maigManager = Ntk_NetworkReadMAigManager(network);
+  st_table          *nodeToMvfAigTable = NIL(st_table); 
+  BmcCnfClauses_t   *cnfClauses;
+  FILE              *cnfFile;
+  BmcOption_t       *options;
+  array_t           *result;
+  int               i;
+  boolean           CexExit = FALSE;
+  
+  nodeToMvfAigTable =
+    (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+  if (nodeToMvfAigTable == NIL(st_table)){
+    fprintf(vis_stderr, 
+	    "** bmc error: please run buid_partiton_maigs first\n");
+    return CexExit;
+  }
+
+  options = BmcOptionAlloc();
+  if (verbose) { 
+    options->dbgLevel = dbgLevel;
+    options->printInputs = printInputs;
+  }
+  options->satInFile = BmcCreateTmpFile();
+  if (options->satInFile == NIL(char)){
+    BmcOptionFree(options);
+    return CexExit;
+  }
+
+  /* create SAT Solver output file */
+  options->satOutFile = BmcCreateTmpFile();
+  if (options->satOutFile == NIL(char)){
+    BmcOptionFree(options);
+    fprintf(vis_stderr, "** bmc error: Cannot allocate a temp file name\n");
+    return CexExit;
+  }
+  cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
+  if (cnfFile == NIL(FILE)) {
+    BmcOptionFree(options);
+    fprintf(vis_stderr, "** bmc error: Cannot create CNF output file %s\n",
+	    options->satInFile);
+    return CexExit;
+  }
+
+  /* Unroll the model exactly 'pathLength' time frames
+   */
+  cnfClauses = BmcCnfClausesAlloc();
+  BmcCnfGenerateClausesForPath(network, 0, pathLength, BMC_INITIAL_STATES,
+			       cnfClauses, nodeToMvfAigTable, absLatches);
+
+  /* Generate the constraints from the abstract paths
+   *   (1) build a bAigEdge_t (graph) for each ring
+   *   (2) add all the cnf clauses that describe this graph
+   *   (3) make the output bAigEdge_t equals to 1
+  */
+  {
+    bAigEdge_t  bAigState;
+    mdd_manager *mddManager = Ntk_NetworkReadMddManager(network);
+    array_t     *clause = array_alloc(int, 1);
+    mdd_t       *ring;
+
+    arrayForEachItem(mdd_t *, synOnionRings, i, ring) {
+      st_table *bddidTobAigNames;
+      bddidTobAigNames = GrabBddGetSupportBaigNames(mddManager, ring);
+      bAigState = GrabConvertBddToBaig(maigManager, ring, bddidTobAigNames);
+      {
+	st_generator *stgen;
+	long tmpId;
+	char *tmpStr;
+	st_foreach_item(bddidTobAigNames, stgen, &tmpId, &tmpStr) {
+	  FREE(tmpStr);
+	}
+	st_free_table(bddidTobAigNames);
+      }
+      array_insert(int, clause, 0, BmcGenerateCnfFormulaForAigFunction(
+                                  maigManager, bAigState, i, cnfClauses));
+      BmcCnfInsertClause(cnfClauses, clause);
+    } 
+   
+    array_free(clause);
+  } 
+
+  /* Call the SAT solver 
+   */
+  BmcWriteClauses(maigManager, cnfFile, cnfClauses, options); 
+  fclose(cnfFile);
+  result = BmcCheckSAT(options);
+  if(result != NIL(array_t)){
+    if (verbose >= 1 && dbgLevel ==1) {
+      fprintf(vis_stdout,"Found Counterexample of length = %d\n", pathLength);
+      BmcPrintCounterExample(network, nodeToMvfAigTable, cnfClauses,
+			     result, pathLength+1, absLatches, options, 
+			     NIL(array_t));
+    }
+    if (verbose >=1 && dbgLevel == 2) {
+      BmcPrintCounterExampleAiger(network, nodeToMvfAigTable, cnfClauses,
+                             result, pathLength+1, absLatches, options,
+                             NIL(array_t));
+    }   
+    CexExit = TRUE;
+  }  
+
+  /* free all used memories */
+  BmcCnfClausesFree(cnfClauses);
+  array_free(result);
+  BmcOptionFree(options);
+
+  return CexExit;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Check if the abstract paths exist in the fine-grain model.]
+
+  Description [Check if the abstract paths exist in the fine-grain
+  model. The paths are given as set of onion rings, where each ring is
+  a set of states.  The model is defined by the set of latches
+  (absLatches) and bnvs (absBnvs). The entire set of bnvs of the
+  network are stored in the table coiBnvTable.
+
+  This procedure first build a NEW maig graph (for the fine-grain
+  model), then check if the abstract paths exist in the model.
+
+  Before it returns, the previous maig graph is restored.]
+  
+  SideEffects []
+
+******************************************************************************/
+boolean
+Bmc_AbstractCheckAbstractTracesWithFineGrain(
+  Ntk_Network_t *network,
+  st_table *coiBnvTable,
+  array_t *synOnionRings,
+  st_table *absLatches,
+  st_table *absBnvs)
+{
+  boolean             result;
+  mAigManagerState_t  oldMaigState;  /* to store the previous AIG */
+  mAig_Manager_t      *maigManager;
+  lsGen               lsgen;
+  Ntk_Node_t          *node;
+  int                 mAigId;
+  int                 i;
+  st_generator        *stgen;
+  st_table            *leaves;
+  array_t             *roots, *combInputs;
+
+  /* save the existing maigManager */
+  oldMaigState.manager = Ntk_NetworkReadMAigManager(network);
+  oldMaigState.nodeToMvfAigTable =  
+    (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+  oldMaigState.nodeToMAigIdTable = st_init_table(st_ptrcmp, st_ptrhash);
+  Ntk_NetworkForEachNode(network, lsgen, node) {
+    mAigId = Ntk_NodeReadMAigId(node);
+    st_insert(oldMaigState.nodeToMAigIdTable, node, (char *)(long)mAigId);
+    Ntk_NodeSetMAigId(node, ntmaig_UNUSED);
+  }
+
+  /* create a new maigManager */
+  maigManager = mAig_initAig();
+  Ntk_NetworkSetMAigManager(network, maigManager);
+  Ntk_NetworkSetApplInfo(network, MVFAIG_NETWORK_APPL_KEY,
+	  		 (Ntk_ApplInfoFreeFn) ntmAig_MvfAigTableFreeCallback,
+			 (void *) st_init_table(st_ptrcmp, st_ptrhash));
+
+  /* roots are the visible latches, and the visible bnvs (some bnvs
+   * may not be in the transitive fan-in cone of the visible latches
+   */
+  roots = array_alloc(Ntk_Node_t *, 0);
+  st_foreach_item(absLatches, stgen, &node, NIL(char *)) {
+    array_insert_last(Ntk_Node_t *, roots, Ntk_LatchReadDataInput(node));
+    array_insert_last(Ntk_Node_t *, roots, Ntk_LatchReadInitialInput(node));
+  }
+  st_foreach_item(absBnvs, stgen, &node, NIL(char *)) {
+    array_insert_last(Ntk_Node_t *, roots, node);
+  }
+
+  combInputs = Ntk_NodeComputeTransitiveFaninNodes(network, roots, 
+						   TRUE, /* stopAtLatches */
+						   FALSE /* combInputsOnly*/
+						   );
+
+  /* leaves are the combinational inputs or the invisible bnvs */
+  leaves = st_init_table(st_ptrcmp, st_ptrhash);
+  arrayForEachItem(Ntk_Node_t *, combInputs, i, node) {
+    if ( Ntk_NodeTestIsCombInput(node) ||
+	 ( st_is_member(coiBnvTable, node) &&
+	   !st_is_member(absBnvs, node) ) ) {
+      st_insert(leaves, node, (char *) ntmaig_UNUSED);
+      Ntk_NodeSetMAigId(node, mAig_CreateVar(maigManager,
+					     Ntk_NodeReadName(node),
+		   Var_VariableReadNumValues(Ntk_NodeReadVariable(node))));
+    }
+  }
+  st_foreach_item(absLatches, stgen, &node, NIL(char *)) {
+    if (!st_is_member(leaves, node)) {
+      st_insert(leaves, node, (char *) ntmaig_UNUSED);
+      Ntk_NodeSetMAigId(node, mAig_CreateVar(maigManager,
+					     Ntk_NodeReadName(node),
+		   Var_VariableReadNumValues(Ntk_NodeReadVariable(node))));
+    }
+  }
+  array_free(combInputs);
+
+#if 1
+  /* THIS SEEMS UNNECESSARY---IT'S HERE TO AVOID ERRORS IN CALLING
+   * ntmaig_NetworkBuildMvfAigs()
+   */
+  Ntk_NetworkForEachCombInput(network, lsgen, node) {
+    if (Ntk_NodeReadMAigId(node) == NTK_UNASSIGNED_MAIG_ID) {
+      Ntk_NodeSetMAigId(node, mAig_CreateVar(maigManager,
+					     Ntk_NodeReadName(node),
+		   Var_VariableReadNumValues(Ntk_NodeReadVariable(node))));
+    } 
+  }
+#endif
+
+  /* build the new AIG graph */
+  ntmaig_NetworkBuildMvfAigs(network, roots, leaves);
+
+  array_free(roots);
+  st_free_table(leaves);
+
+
+  /* check the existence of the abstract path on the new AIG graph */
+  result = Bmc_AbstractCheckAbstractTraces(network,
+					   synOnionRings,
+					   absLatches,
+					   0, 0, 0);
+
+  /* restore the previous maigManager */
+  mAig_quit(maigManager);
+  Ntk_NetworkFreeApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+  Ntk_NetworkSetMAigManager(network, oldMaigState.manager);
+  Ntk_NetworkSetApplInfo(network, MVFAIG_NETWORK_APPL_KEY,
+	  		 (Ntk_ApplInfoFreeFn) ntmAig_MvfAigTableFreeCallback,
+			 (void *) oldMaigState.nodeToMvfAigTable);
+  st_foreach_item(oldMaigState.nodeToMAigIdTable, stgen, &node,
+		  &mAigId) {
+    Ntk_NodeSetMAigId(node, mAigId);
+  }
+  st_free_table(oldMaigState.nodeToMAigIdTable);
+
+  return result;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Build the binary Aig for a given bdd]
+
+  SideEffects [Build the binary Aig for a given bdd.  We assume that
+  the return bdd nodes from the foreach_bdd_node are in the order from
+  childeren to parent. i.e all the childeren nodes are returned before
+  the parent node.
+
+  bddidToNames is a hash table from bddid to its bAigEdge_t name.  If
+  provided, this table should contain entiries for all the bddid in
+  the support.]
+
+  SideEffects []
+
+  SeeAlso     []
+  
+******************************************************************************/
+static bAigEdge_t
+GrabConvertBddToBaig(
+   bAig_Manager_t *bAigManager,
+   bdd_t          *fn,
+   st_table       *bddidToNames)
+{
+  bdd_gen     *gen;
+  bdd_node    *node, *thenNode, *elseNode, *funcNode;
+  bdd_manager *bddManager = bdd_get_manager(fn);
+  bdd_node    *one  = bdd_read_one(bddManager);
+  /*bdd_node    *zero = bdd_read_logic_zero(bddManager);*/
+  int         is_complemented;
+  int         flag;
+  bAigEdge_t  var, left, right, result;
+  char        *name;
+  st_table    *bddTObaigTable;
+  
+  bddTObaigTable = st_init_table(st_numcmp, st_numhash);
+
+  if (fn == NULL){
+    return bAig_NULL;
+  }
+  
+  st_insert(bddTObaigTable, (char *) (long) bdd_regular(one),  
+	    (char *) bAig_One);
+
+  funcNode = bdd_get_node(fn, &is_complemented);
+  
+  if (bdd_is_constant(funcNode)){
+    flag = st_lookup(bddTObaigTable, 
+		     (char *) (long) (funcNode),
+		     &result);
+    assert(flag);
+    st_free_table(bddTObaigTable);
+
+    if (is_complemented)
+      return bAig_Not(result);
+    else
+      return result;
+  }
+  
+  foreach_bdd_node(fn, gen, node){
+    /* if the node has been processed, skip it. (the constant ONE
+     * should be the only node falls into this category).
+     */
+    if (st_is_member(bddTObaigTable, (char *) (long) bdd_regular(node)))
+      continue;
+    
+    /*  bdd_node_read_index() return the current level's bddId */
+    if (bddidToNames) {
+      flag = st_lookup(bddidToNames, (char *)(long)bdd_node_read_index(node),
+		       &name);
+      assert(flag);
+      name = util_strsav(name);
+    }else {
+      char tempString[1024];
+      sprintf(tempString, "BDD%d", bdd_node_read_index(node));
+      name = util_strsav(tempString);
+    }
+
+    /*  Create or Retrieve the bAigEdge_t  w.r.t. 'name' */
+    var  = bAig_CreateVarNode(bAigManager, name);
+    FREE(name);
+
+    thenNode  = bdd_bdd_T(node);
+    flag = st_lookup(bddTObaigTable, (char *) (long) bdd_regular(thenNode),
+		     &left);
+    assert(flag);
+      
+    elseNode  = bdd_bdd_E(node);
+    flag = st_lookup(bddTObaigTable, (char *) (long) bdd_regular(elseNode),
+		      &right);
+    assert(flag);
+
+    /* should we test here whether elseNode is complemented arc? */
+    if (bdd_is_complement(elseNode))
+      right = bAig_Not(right);
+
+    result =  bAig_Or(bAigManager, bAig_And(bAigManager, var, left),
+		                   bAig_And(bAigManager, bAig_Not(var), right));
+    st_insert(bddTObaigTable, (char *) (long) bdd_regular(node),
+	      (char *) (long) result);
+  }
+  flag = st_lookup(bddTObaigTable, (char *) (long) bdd_regular(funcNode),
+		    &result);  
+  assert(flag);
+  st_free_table(bddTObaigTable);
+
+  if (is_complemented){
+    return bAig_Not(result);
+  } else {
+    return result;
+  }
+} /* end of bAig_bddtobAig() */
+
+
+/**Function********************************************************************
+
+Synopsis    [Get a (bddId,baigName) table for the supporting variableS.]
+
+SideEffects [Get a (bddId,baigName) table for the supporting
+variableS. The caller should free the returned table as well as the
+(char *) of its value field.]
+
+SeeAlso     []
+  
+******************************************************************************/
+static st_table *
+GrabBddGetSupportBaigNames(
+  mdd_manager *mddManager,
+  mdd_t *f)
+{
+  int        numOfVars = bdd_num_vars(mddManager);
+  st_table  *bddidTObaigNames = st_init_table(st_numcmp, st_numhash);
+  var_set_t *vset;
+  int        i;
+
+  vset = bdd_get_support(f);
+  for (i=0; i<numOfVars; i++) {
+    if (var_set_get_elt(vset, i) == 1) {
+      st_insert(bddidTObaigNames, (char *)(long)i, 
+		GrabBddIdToBaigNames(mddManager, i));
+    }
+  }
+  var_set_free(vset);
+
+  return bddidTObaigNames;
+}
+
+/**Function********************************************************************
+
+Synopsis    [return the baigName  of a bddid]
+
+SideEffects [The caller should free the returned char *.  This
+  function is based on the assumption that MDD and MAIG shares the
+  same naming convention (which is true in VIS).]
+
+SeeAlso     []
+  
+******************************************************************************/
+static char *
+GrabBddIdToBaigNames(
+  mdd_manager *mddManager,
+  int            bddid)
+{
+  array_t *mvar_list = mdd_ret_mvar_list(mddManager);
+  array_t *bvar_list = mdd_ret_bvar_list(mddManager);
+  bvar_type bv;
+  mvar_type mv;
+  int     mddid, index, id;
+  char    *nodeName;
+  char    baigName[1024];
+
+  /* 1. from bddid, get mddid and the index of this bddid in the mddid 
+   */
+  bv = array_fetch(bvar_type, bvar_list, bddid);
+  mddid = bv.mvar_id;
+  mv = array_fetch(mvar_type, mvar_list, mddid);
+  arrayForEachItem(int, mv.bvars, index, id) {
+    if (id == bddid) 
+      break;
+  }
+  assert(index <= mv.encode_length -1);
+  
+  /* 2. assumptions: (1) mv.name = nodeName,  
+   *                 (2) index is the same for MDD and MAIG
+   */
+  nodeName = mv.name;
+  
+  /* 3. the baigEdge_t's name is ("%s_%d",nodeName,index)
+   */
+  sprintf(baigName, "%s_%d", nodeName, index);
+
+  return util_strsav(baigName);
+}
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/grab/grabGrab.c
===================================================================
--- vis_dev/vis-2.3/src/grab/grabGrab.c	(revision 14)
+++ vis_dev/vis-2.3/src/grab/grabGrab.c	(revision 14)
@@ -0,0 +1,644 @@
+/**CFile***********************************************************************
+
+  FileName    [grabGrab.c]
+
+  PackageName [grab]
+
+  Synopsis    [The GRAB algorithm of computing a set of refinement variables.]
+
+  Description [The computation is based on all the shortest abstract
+  counter-examples.] 
+  
+  Author      [Chao Wang]
+
+  Copyright   [Copyright (c) 2004 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without
+  license or royalty fees, to use, copy, modify, and distribute this
+  software and its documentation for any purpose, provided that the
+  above copyright notice and the following two paragraphs appear in
+  all copies of this software.]
+
+******************************************************************************/
+
+#include "grabInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+static st_table *Sel0ScoreTable;
+static st_table *SelScoreTable;
+static st_table *Sel2ScoreTable;
+static st_table *Sel3ScoreTable;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static array_t * GrabFsmComputeExRings(Fsm_Fsm_t *absFsm, st_table *absVarTable, st_table *absBnvTable, array_t *oldRings, int cexType, int verbose);
+static int GrabCompareScores(const void *ptr1, const void *ptr2);
+static void GrabMddAppendSupports(mdd_manager *mddManager, mdd_t *mdd1, st_table *supportsTable);
+static array_t * ComputeDependence(Ntk_Network_t *network, st_table *vertexTable, array_t *leftVars);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Pick a set of refinement variables using Grab.]
+
+  Description [Pick a set of refinement variables using Grab. When
+  refine_direction is 1, refine in both directions (by adding latches
+  and bnvs); when refine_direction is 0, refine only in the boolean
+  direction (by adding bnvs).
+
+  The present state variables of absFsm must include all the invisible
+  variables; its next state variables must include only the visible
+  ones. On such a FSM, the preimage may contain some invisible
+  variables in its support. The set of preimages, ExRings, is the set
+  of augmented preimages (with invisible variables in the support).
+
+  The refinement variable will be put into either addedVars or
+  addedBnvs, depending on which class it bolongs to; at the same time,
+  it will be put into either absVarTable or
+  BnvTable. 
+
+  nodeToFaninNumber is a global variable, whose values are used as
+  tie-breakers.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+GrabRefineAbstractionByGrab(
+  Fsm_Fsm_t *absFsm,
+  array_t   *SORs,
+  st_table  *absVarTable,
+  st_table  *BnvTable,
+  array_t   *addedVars,
+  array_t   *addedBnvs,
+  int       refine_direction,   
+  st_table  *nodeToFaninNumberTable, 
+  int verbose)
+{
+  Ntk_Network_t *network = Fsm_FsmReadNetwork(absFsm);
+  mdd_manager   *mddManager = Ntk_NetworkReadMddManager(network);
+  array_t       *ExRings;
+  array_t       *visibleVarMddIds, *invisibleVarMddIds, *allPSVars;
+  array_t       *tempArray;
+  mdd_t         *mdd1, *mdd2;
+  char          *nodeName;
+  Ntk_Node_t    *node;
+  double        *Scores, *SelScores, *Sel0Scores, *Sel2Scores, *Sel3Scores;
+  double        epd, baseNum;
+  int           i, j, nRow, nCol;
+  long          mddId, value, value0;
+  boolean       isSupport, isLatch;
+  int           max_num_of_added_vars;
+
+  /* compute the preimages (with invisible vars in their support)
+   */
+  ExRings = GrabFsmComputeExRings(absFsm, absVarTable, BnvTable, SORs,
+				  GRAB_CEX_SOR, verbose);
+  assert(ExRings != NIL(array_t));
+
+  visibleVarMddIds = GrabGetVisibleVarMddIds(absFsm,absVarTable);
+  invisibleVarMddIds = GrabGetInvisibleVarMddIds(absFsm,absVarTable,BnvTable);
+  allPSVars = array_dup(visibleVarMddIds);
+  array_append(allPSVars, invisibleVarMddIds);
+  assert(array_n(invisibleVarMddIds) > 0 );
+  
+  /* Compute the normalized number of "winning positions" for each individual
+   * invisibleVar, and store them in 'Scores'!
+   */
+  nRow = array_n(ExRings);
+  nCol = array_n(invisibleVarMddIds);
+  Scores = ALLOC(double, nRow*nCol);
+  memset(Scores, 0, sizeof(double)*nRow*nCol);
+
+
+  /*********************************************************
+   * for each set of abstract states in (mdd1, Ring[j+1] )
+   *********************************************************/
+  arrayForEachItem(mdd_t *, ExRings, j, mdd1) {
+    st_table *localSupportsTable = st_init_table(st_numcmp, st_numhash);
+    GrabMddAppendSupports(mddManager, mdd1, localSupportsTable);
+
+    if (mdd_get_number_of_bdd_vars(mddManager, allPSVars) <= 1023 )
+      baseNum = mdd_count_onset(mddManager, mdd1, allPSVars);
+    else {
+      mdd_t *stateMdd = mdd_smooth(mddManager, mdd1, invisibleVarMddIds);
+      baseNum = mdd_count_onset(mddManager, stateMdd, visibleVarMddIds);
+      mdd_free(stateMdd);
+    }
+    
+    /***********************************************************
+     * compute the impact of refining with each invisible var
+     ***********************************************************/
+    arrayForEachItem(int, invisibleVarMddIds, i, mddId) {
+      /* for debugging purpose. won't affect the algorithm */
+      Scores[j*nCol+i] = -9E-99;
+
+      /* give credit simply for the appearance */
+      isSupport = st_is_member(localSupportsTable, (char *)mddId);
+      if (!isSupport || baseNum==0.0) 	continue;
+      Scores[j*nCol+i] += 0.001;
+
+      node = Ntk_NetworkFindNodeByMddId(network, mddId);
+      isLatch = (Ntk_NodeTestIsLatch(node));
+      if (refine_direction==0 && isLatch)  continue;
+
+      {
+	array_t *universalQVars = array_alloc(int, 0);
+	/* MX */
+	array_insert_last(int, universalQVars, mddId);
+	mdd2 = mdd_consensus(mddManager, mdd1, universalQVars);
+	array_free(universalQVars);
+
+	if (mdd_get_number_of_bdd_vars(mddManager, allPSVars) <= 1023)
+	  epd = mdd_count_onset(mddManager, mdd2, allPSVars);
+	else {
+	  mdd_t *stateMdd = mdd_smooth(mddManager, mdd2, invisibleVarMddIds);
+	  epd = mdd_count_onset(mddManager, stateMdd, visibleVarMddIds);
+	  mdd_free(stateMdd);
+	}
+	mdd_free(mdd2);
+
+	Scores[j*nCol+i] = (baseNum - epd)/baseNum;
+      }
+      
+      if (j == 0)
+	Scores[j*nCol+i] /= 10.0;
+
+    }
+    st_free_table(localSupportsTable);
+  }
+
+  /* For each column, sum up the score over all the rows. The
+   * selection of refinement variables will be based mainly on these
+   * scores.
+   */
+  SelScores = ALLOC(double, nCol);
+  memset(SelScores, 0, sizeof(double)*nCol);
+  for (i=0; i<nRow; i++) {
+    for (j=0; j<nCol; j++) { 
+      SelScores[j] += Scores[i*nCol+j]; 
+    }
+  }
+
+  /* Other selection criteria:
+   * (0) when in the BOOLEAN refinement direction, only add bnvs
+   * (2) how many absLatches depending on the invisible var?
+   * (3) how much will the invisible var cost?
+   */  
+  Sel0Scores  = ALLOC(double, nCol);
+  Sel2Scores  = ALLOC(double, nCol);
+  Sel3Scores  = ALLOC(double, nCol);
+  tempArray = ComputeDependence(network, absVarTable, invisibleVarMddIds);
+  value0 = lsLength(Ntk_NetworkReadNodes(network));
+  for (j=0; j<nCol; j++) {
+    mddId = array_fetch(int, invisibleVarMddIds, j);
+    node = Ntk_NetworkFindNodeByMddId(network, mddId);
+    isLatch = (Ntk_NodeTestIsLatch(node));
+    /* when refinement is in the BOOLEAN direction, only add bnvs 
+     * otherwise, add either latches or bnvs 
+     */
+    if (refine_direction==0 && !isLatch)
+      Sel0Scores[j] = 1.0;
+    else
+      Sel0Scores[j] = 0.0;      
+    /* dependence */
+    value = array_fetch(int, tempArray, j);
+    Sel2Scores[j] = ((double)value)/st_count(absVarTable);
+    /* cost */
+    value = GrabNodeComputeFaninNumberTableItem(network, 
+						nodeToFaninNumberTable,
+						node);
+    Sel3Scores[j] = 1.0 - ((double)value)/value0; 
+  }
+  array_free(tempArray);
+
+  /* Print out the 'Scores' matrix when requested
+   */
+  if (verbose >= 5) {
+    /* the entire score table */
+    fprintf(vis_stdout, "\n Scores[%d][%d] = \n", nRow, nCol);
+    arrayForEachItem(int, invisibleVarMddIds, i, mddId) {
+      node = Ntk_NetworkFindNodeByMddId(network, mddId);
+      fprintf(vis_stdout, "%s ", (Ntk_NodeTestIsLatch(node)?"   L ":"     "));
+    }
+    fprintf(vis_stdout, "\n"); 
+    arrayForEachItem(int, invisibleVarMddIds, i, mddId) {
+      node = Ntk_NetworkFindNodeByMddId(network, mddId);
+      fprintf(vis_stdout, "%5d ", i);
+    }
+    fprintf(vis_stdout, "\n"); 
+    for (i=0; i<nRow; i++) {
+      for (j=0; j<nCol; j++) { 
+	fprintf(vis_stdout, "%+1.2f ", Scores[i*nCol+j]);  
+      } 
+      fprintf(vis_stdout, "\n"); 
+    }
+    /* best score in each row */
+    for (i=0; i<nRow; i++) {
+      int best_local = 0;
+      for (j=0; j<nCol; j++) { 
+	if (Scores[i*nCol+best_local] < Scores[i*nCol+j])
+	  best_local = j;
+      }
+      fprintf(vis_stdout, "best_local: Scores[%d][%d] = %5g\n",
+	      i, best_local, Scores[i*nCol+best_local]);
+    }
+  }
+
+  /* Sorting the invisibleVarMddIds according to the Selection Scores 
+   */
+  Sel0ScoreTable = st_init_table(st_numcmp, st_numhash);
+  SelScoreTable  = st_init_table(st_numcmp, st_numhash);
+  Sel2ScoreTable = st_init_table(st_numcmp, st_numhash);
+  Sel3ScoreTable = st_init_table(st_numcmp, st_numhash);
+  arrayForEachItem(int, invisibleVarMddIds, j, mddId) {
+    st_insert(Sel0ScoreTable, (char *)mddId, (char *)(Sel0Scores+j));
+    st_insert(SelScoreTable,  (char *)mddId, (char *)(SelScores+j));
+    st_insert(Sel2ScoreTable, (char *)mddId, (char *)(Sel2Scores+j));
+    st_insert(Sel3ScoreTable, (char *)mddId, (char *)(Sel3Scores+j));
+  } 
+
+  array_sort(invisibleVarMddIds, GrabCompareScores);
+
+  if (verbose >= 4) {
+    fprintf(vis_stdout, "       \t  Sel0    Sel     Sel2    Sel3\n");
+    arrayForEachItem(int, invisibleVarMddIds, j, mddId) {
+      double *addr;
+      st_lookup(Sel0ScoreTable, (char *)mddId, &addr);
+      i = (int)(addr-Sel0Scores);
+      node = Ntk_NetworkFindNodeByMddId(network, mddId);
+      isLatch = (Ntk_NodeTestIsLatch(node));
+      fprintf(vis_stdout, 
+	      "%s[%d]\t %+1.3f  %+1.3f  %+1.3f  %+1.3f   %s\n",
+	      (isLatch? "L":" "), 
+	      i,
+	      Sel0Scores[i], SelScores[i], Sel2Scores[i], Sel3Scores[i],
+	      Ntk_NodeReadName(node)
+	      );
+      /* only output the top 20 variables */
+      if (j >= 19) break;
+    }
+  }
+
+  st_free_table(Sel0ScoreTable);
+  st_free_table(SelScoreTable);
+  st_free_table(Sel2ScoreTable);
+  st_free_table(Sel3ScoreTable);
+
+  /* Now find the best (largest score) invisible Var   */
+  {
+    int num_absBnvs = BnvTable? st_count(BnvTable):0;
+
+    if ((st_count(absVarTable) + num_absBnvs) < 10)
+      max_num_of_added_vars = 1;
+    else
+      max_num_of_added_vars = 2 + (st_count(absVarTable)+num_absBnvs)/30;
+  }
+
+  arrayForEachItem(int, invisibleVarMddIds, j, mddId) {
+
+    if (j >= max_num_of_added_vars)    break;
+
+    node = Ntk_NetworkFindNodeByMddId(network, mddId);
+    nodeName = Ntk_NodeReadName(node);
+    if (Ntk_NodeTestIsLatch(node)) {
+      assert(!st_is_member(absVarTable, node));
+      st_insert(absVarTable, node, (char *)(long)st_count(absVarTable));
+      array_insert_last(int, addedVars, mddId);
+      CHKPRINT2( (verbose>=3), "         add Latch %s\n", nodeName );
+    }else if (!Ntk_NodeTestIsLatch(node)) {
+      assert(!st_is_member(BnvTable, node));
+      st_insert(BnvTable, node, (char *)0);
+      array_insert_last(int, addedBnvs, mddId);
+      CHKPRINT2( (verbose>=3), "         add BNV %s\n", nodeName );
+    }
+  }
+
+  /* Clean-ups */
+  array_free(invisibleVarMddIds);
+  array_free(visibleVarMddIds);
+  array_free(allPSVars);
+  mdd_array_free(ExRings);
+  FREE(Scores);
+  FREE(Sel0Scores);
+  FREE(SelScores);
+  FREE(Sel2Scores);
+  FREE(Sel3Scores);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Compute the number of fanin nodes]
+
+  Description [Compute the number of fanin nodes. The result is
+  inserted in the hash table.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+GrabNodeComputeFaninNumberTableItem(
+  Ntk_Network_t   *network,
+  st_table        *nodeToFaninNumberTable,
+  Ntk_Node_t      *node)
+{
+  int          count;
+  array_t      *roots, *supports;
+
+  roots = array_alloc(Ntk_Node_t *, 0);
+  if (!st_lookup_int(nodeToFaninNumberTable, node, &count)) {
+    if (Ntk_NodeTestIsLatch(node)) 
+      array_insert(Ntk_Node_t *, roots, 0, Ntk_LatchReadDataInput(node));
+    else
+      array_insert(Ntk_Node_t *, roots, 0, node);
+
+    supports = Ntk_NodeComputeTransitiveFaninNodes(network, roots, TRUE,FALSE);
+
+    count = array_n(supports);
+    array_free(supports);
+    st_insert(nodeToFaninNumberTable, node, (char *)(long)count);
+  }
+  array_free(roots);
+
+  return count;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Compute the extended Synchronous Onion Rings (SORs).]
+
+  Description [Compute the extended Synchronous Onion Rings (SORs) on
+  the absFSm whose present state variables includes the invisible
+  variables. The preimages, therefore, may have invisible variables in
+  their support. The result is used only inside
+  GrabRefineAbstractionByGrab.]
+
+  SideEffects []
+
+******************************************************************************/
+static array_t *
+GrabFsmComputeExRings(
+  Fsm_Fsm_t *absFsm,
+  st_table  *absVarTable,
+  st_table  *absBnvTable,
+  array_t   *oldRings,
+  int       cexType,
+  int       verbose)
+{
+  Img_ImageInfo_t *imageInfo;
+  Ntk_Network_t   *network = Fsm_FsmReadNetwork(absFsm);
+  array_t         *careStatesArray = array_alloc(mdd_t *, 0);
+  array_t         *allPsVars, *invisibleVarMddIds;
+  array_t         *onionRings, *synOnionRings;
+  mdd_t           *mdd1, *mdd2, *mdd3, *mdd4, *initStates;
+  int             i, j, mddId;
+  Ntk_Node_t      *node;
+
+  imageInfo = Fsm_FsmReadOrCreateImageInfo(absFsm, 1, 0);
+
+  /* Compute the initial states based on all the related latches
+   * (i.e. visible latches and invisible ones that are in the
+   * immediate support)
+   */
+  allPsVars = GrabGetVisibleVarMddIds(absFsm, absVarTable);
+  invisibleVarMddIds = GrabGetInvisibleVarMddIds(absFsm, absVarTable, 
+						 absBnvTable);
+  arrayForEachItem(int, invisibleVarMddIds, i, mddId) {
+    node = Ntk_NetworkFindNodeByMddId(network, mddId);
+    if (Ntk_NodeTestIsLatch(node))
+      array_insert_last(int, allPsVars, mddId);
+  }
+  initStates = GrabComputeInitialStates(network, allPsVars);
+  array_free(allPsVars);
+  array_free(invisibleVarMddIds);
+
+  onionRings = oldRings;
+  if (onionRings == NIL(array_t))
+    onionRings = Fsm_FsmReadReachabilityOnionRings(absFsm);
+  assert(onionRings);
+
+  synOnionRings = array_alloc(mdd_t *, array_n(onionRings));
+
+  for (j=array_n(onionRings)-2; j>=0; j--) {
+    mdd1 = array_fetch(mdd_t *, onionRings, j+1);
+    mdd2 = array_fetch(mdd_t *, onionRings, j);
+
+    array_insert(mdd_t *, careStatesArray, 0, mdd2);
+    mdd3 = Img_ImageInfoComputeEXWithDomainVars(imageInfo,
+						mdd1,
+						mdd1,
+						careStatesArray);
+    mdd4 = mdd_and(mdd2, mdd3, 1, 1);
+    mdd_free(mdd3);
+
+    array_insert(mdd_t *, synOnionRings, j+1, mdd4);
+
+    /* when the more accurate initial states is available, use it */
+    if (j == 0) {
+      mdd1 = mdd_and(mdd4, initStates, 1, 1);
+      if (mdd_is_tautology(mdd1, 0)) {
+	mdd_free(mdd1);
+	mdd1 = mdd_dup(mdd4);
+      }
+      array_insert(mdd_t *, synOnionRings, j, mdd1);
+    }
+  }
+  
+  /* clean-up's */
+  mdd_free(initStates);
+  array_free(careStatesArray);
+
+  return synOnionRings;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Compare the scores of the two invisible variables.]
+
+  Description [Compare the scores of the two invisible variables. It
+  is used inside GrabRefineAbstractionByGrab() for sorting the array
+  of invisible variables. 
+
+  Note that the hash tables like Sel0ScoreTable are declareled as
+  static global variables -- they are visible inside this source
+  file.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+GrabCompareScores(
+  const void *ptr1,
+  const void *ptr2)
+{
+  int  item1 = *((int *)ptr1);
+  int  item2 = *((int *)ptr2);
+  double *first0, *first, *first2, *first3;
+  double *second0, *second, *second2, *second3;
+  double value0, value, value2, value3;
+
+  st_lookup(Sel0ScoreTable, (char *)(long)item1,  &first0);
+  st_lookup(SelScoreTable,  (char *)(long)item1,  &first);
+  st_lookup(Sel2ScoreTable, (char *)(long)item1,  &first2);
+  st_lookup(Sel3ScoreTable, (char *)(long)item1,  &first3);
+
+  st_lookup(Sel0ScoreTable, (char *)(long)item2,  &second0);
+  st_lookup(SelScoreTable,  (char *)(long)item2,  &second);
+  st_lookup(Sel2ScoreTable, (char *)(long)item2,  &second2);
+  st_lookup(Sel3ScoreTable, (char *)(long)item2,  &second3);
+  
+  value0 = *second0 - *first0;
+  value  = *second  - *first;
+  value2 = *second2 - *first2;
+  value3 = *second3 - *first3;
+  
+  if (value0 > 0)         return 1;
+  if (value0 < 0)         return -1;
+
+  if (value > 0)          return 1;
+  if (value < 0)          return -1;
+
+  return 0;
+
+  /* Chao: The tie-breakers are not used for this release. We achieved
+   * the best performance on the suite of testing cases at hand
+   * without the tie-breakers. But the code is retained for the
+   * purpose of future experiments.
+   */
+  
+  if (value2 > 0)         return 1;
+  if (value2 < 0)         return -1;
+
+  if (value3 > 0)         return 1;
+  if (value3 < 0)         return -1;
+
+  return 0;
+}
+  
+ 
+/**Function********************************************************************
+
+  Synopsis    [Add the supporting mddIds into the table.]
+
+  Description [Add the supporting mddIds into the table.]
+
+  SideEffects []
+
+******************************************************************************/
+static void 
+GrabMddAppendSupports( 
+  mdd_manager *mddManager, 
+  mdd_t *mdd1, 
+  st_table *supportsTable) 
+{
+  int mddId, k;
+  array_t *supports = mdd_get_support(mddManager, mdd1);
+
+  arrayForEachItem(int, supports, k, mddId) {
+    if (!st_is_member(supportsTable, (char *)(long)mddId)) 
+	st_insert(supportsTable, (char *)(long)mddId, (char *)0);
+  }
+  array_free(supports);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compute the degree of dependence that the abstract model
+  has on the invisible variables.]
+
+  Description [Compute the degree of dependence that the abstract model
+  has on the invisible variables.]
+
+  SideEffects []
+
+******************************************************************************/
+static array_t * 
+ComputeDependence(
+  Ntk_Network_t *network, 
+  st_table *vertexTable, 
+  array_t *leftVars)
+{
+  array_t *roots, *supports;
+  st_table *supportTable;
+  st_generator *stgen;
+  array_t *dependenceArray = array_alloc(int, array_n(leftVars));
+  int i,mddId;
+  Ntk_Node_t *node, *node1;
+  int count;
+
+  /* initialize the scores to 0   */
+  supportTable = st_init_table(st_ptrcmp, st_ptrhash);
+  arrayForEachItem(int, leftVars, i, mddId) {
+    node = Ntk_NetworkFindNodeByMddId(network, mddId);
+    assert(node);
+    st_insert(supportTable, node, (char *)0);
+  }
+
+  /* compute the supports of the absFsm  */
+  roots = array_alloc(Ntk_Node_t *, 0);
+  st_foreach_item(vertexTable, stgen,  &node,  0) {
+    node = Ntk_LatchReadDataInput(node);
+    array_insert(Ntk_Node_t *, roots, 0, node);
+
+    supports = Ntk_NodeComputeTransitiveFaninNodes(network, roots, TRUE, 
+						   FALSE);
+
+    arrayForEachItem(Ntk_Node_t *, supports, i, node1) {
+      if (st_lookup_int(supportTable, node1, &count)) {
+	count++;
+	st_insert(supportTable, node1, (char *)(long)count);
+      }
+    }
+    array_free(supports);
+  }
+  array_free(roots);
+
+  /* put into an array  */
+  arrayForEachItem(int, leftVars, i, mddId) {
+    node = Ntk_NetworkFindNodeByMddId(network, mddId);
+    assert(node);
+    st_lookup_int(supportTable, node, &count);
+    array_insert(int, dependenceArray, i, count);
+  }
+
+  st_free_table(supportTable);
+
+  return dependenceArray;
+}
+
+
+
Index: vis_dev/vis-2.3/src/grab/grabInt.h
===================================================================
--- vis_dev/vis-2.3/src/grab/grabInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/grab/grabInt.h	(revision 14)
@@ -0,0 +1,143 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [grabInt.h]
+
+  PackageName [grab]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Chao Wang.]
+
+  Copyright   [Copyright (c) 2004 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+  ]
+  
+******************************************************************************/
+
+#ifndef _GRABINT
+#define _GRABINT
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "grab.h"
+#include "cmd.h"
+#include "ctlp.h"
+#include "ctlsp.h"
+#include "mc.h"
+#include "img.h"
+#include "ntk.h"
+#include "ntm.h"
+#include "part.h"
+#include "mvf.h"
+#include <string.h>
+#include "bmc.h"
+#include "mdd.h"
+#include "epd.h"
+#include "fsm.h"
+#include "partInt.h"
+#include "fsmInt.h"
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+#define GRAB_PARTITION_NOCHANGE    0
+#define GRAB_PARTITION_BUILD       1
+#define GRAB_PARTITION_UPDATE      2
+
+#define GRAB_CEX_MINTERM             0
+#define GRAB_CEX_CUBE                1
+#define GRAB_CEX_SOR                 2
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+struct mAigManagerStateStruct{
+  mAig_Manager_t   *manager;
+  st_table         *nodeToMvfAigTable;
+  st_table         *nodeToMAigIdTable;
+};
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef struct mAigManagerStateStruct mAigManagerState_t;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#define DBGMSG1(msg)         fprintf(vis_stdout, "\n<<%s>>\n", msg)
+#define DBGMSG2(msg,msg2)         fprintf(vis_stdout, msg, msg2)
+
+#define CHKPRINT(flag, msg)   if(flag) fprintf(vis_stdout, msg) 
+#define CHKPRINT1(flag, msg)   if(flag) fprintf(vis_stdout, msg) 
+#define CHKPRINT2(flag, msg, msg2)   if(flag) fprintf(vis_stdout, msg, msg2) 
+#define CHKPRINT3(flag, msg, msg2, msg3)   if(flag) fprintf(vis_stdout,msg,msg2,msg3) 
+#define CHKPRINT4(flag, msg, msg2, msg3, msg4)   if(flag) fprintf(vis_stdout,msg,msg2,msg3,msg4) 
+#define CHKPRINT5(flag, msg, msg2, msg3, msg4, msg5)   if(flag) fprintf(vis_stdout,msg,msg2,msg3,msg4,msg5)
+
+#if 0
+
+#define DBGMSG(msg)         fprintf(vis_stdout, "\n<<%s>>\n", msg)
+#define CHKCPUTIME(flag, startTime, msg) \
+        if (flag) { \
+            long thisTime = util_cpu_ctime();\
+            fprintf(vis_stdout, "\n-- elapsed time %5g  (%s)\n",\
+                    (double)(thisTime - startTime)/1000.0, msg); \
+            fflush(vis_stdout);\
+        }
+
+#else 
+
+#define DBGMSG(msg)         
+#define CHKCPUTIME(flag,startTime,msg)  
+
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN boolean Bmc_AbstractCheckAbstractTraces(Ntk_Network_t *network, array_t *synOnionRings, st_table *absLatches, int verbose, int dbgLevel, int printInputs);
+EXTERN boolean Bmc_AbstractCheckAbstractTracesWithFineGrain(Ntk_Network_t *network, st_table *coiBnvTable, array_t *synOnionRings, st_table *absLatches, st_table *absBnvs);
+EXTERN void GrabRefineAbstractionByGrab(Fsm_Fsm_t *absFsm, array_t *SORs, st_table *absVarTable, st_table *BnvTable, array_t *addedVars, array_t *addedBnvs, int refine_direction, st_table *nodeToFaninNumberTable, int verbose);
+EXTERN int GrabNodeComputeFaninNumberTableItem(Ntk_Network_t *network, st_table *nodeToFaninNumberTable, Ntk_Node_t *node);
+EXTERN st_table * GrabComputeCOIAbstraction(Ntk_Network_t *network, Ctlp_Formula_t *invFormula);
+EXTERN st_table * GrabComputeInitialAbstraction(Ntk_Network_t *network, Ctlp_Formula_t *invFormula);
+EXTERN void GrabUpdateAbstractPartition(Ntk_Network_t *network, st_table *coiBnvTable, st_table *absVarTable, st_table *absBnvTable, int partitionFlag);
+EXTERN Fsm_Fsm_t * GrabCreateAbstractFsm(Ntk_Network_t *network, st_table *coiBnvTable, st_table *absVarTable, st_table *absBnvTable, int partitionFlag, int independentFlag);
+EXTERN mdd_t * GrabComputeInitialStates(Ntk_Network_t *network, array_t *psVars);
+EXTERN mdd_t * GrabFsmComputeReachableStates(Fsm_Fsm_t *absFsm, st_table *absVarTable, st_table *absBnvTable, array_t *invStatesArray, int verbose);
+EXTERN mdd_t * GrabFsmComputeConstrainedReachableStates(Fsm_Fsm_t *absFsm, st_table *absVarTable, st_table *absBnvTable, array_t *SORs, int verbose);
+EXTERN array_t * GrabFsmComputeSynchronousOnionRings(Fsm_Fsm_t *absFsm, st_table *absVarTable, st_table *absBnvTable, array_t *oldRings, mdd_t *inv_states, int cexType, int verbose);
+EXTERN array_t * GrabGetVisibleVarMddIds(Fsm_Fsm_t *absFsm, st_table *absVarTable);
+EXTERN array_t * GrabGetInvisibleVarMddIds(Fsm_Fsm_t *absFsm, st_table *absVarTable, st_table *absBnvTable);
+EXTERN int GrabTestRefinementSetSufficient(Ntk_Network_t *network, array_t *SORs, st_table *absVarTable, int verbose);
+EXTERN int GrabTestRefinementBnvSetSufficient(Ntk_Network_t *network, st_table *coiBnvTable, array_t *SORs, st_table *absVarTable, st_table *absBnvTable, int verbose);
+EXTERN void GrabMinimizeLatchRefinementSet(Ntk_Network_t *network, st_table **absVarTable, st_table **absBnvTable, array_t *newlyAddedLatches, array_t **newlyAddedBnvs, array_t *SORs, int verbose);
+EXTERN void GrabMinimizeBnvRefinementSet(Ntk_Network_t *network, st_table *coiBnvTable, st_table *absVarTable, st_table **absBnvTable, array_t *newlyAddedBnvs, array_t *SORs, int verbose);
+EXTERN void GrabNtkClearAllMddIds(Ntk_Network_t *network);
+EXTERN void GrabPrintNodeArray(char *caption, array_t *theArray);
+EXTERN void GrabPrintMddIdArray(Ntk_Network_t *network, char *caption, array_t *mddIdArray);
+EXTERN void GrabPrintNodeList(char *caption, lsList theList);
+EXTERN void GrabPrintNodeHashTable(char *caption, st_table *theTable);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _GRABINT */
+
+
Index: vis_dev/vis-2.3/src/grab/grabUtil.c
===================================================================
--- vis_dev/vis-2.3/src/grab/grabUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/grab/grabUtil.c	(revision 14)
@@ -0,0 +1,1249 @@
+/**CFile***********************************************************************
+
+  FileName    [grabUtil.c]
+
+  PackageName [grab]
+
+  Synopsis    [The utility functions for abstraction refinement.]
+
+  Description [This file contains the functions to check invariant
+  properties by the GRAB abstraction refinement algorithm. GRAB stands
+  for "Generational Refinement of Ariadne's Bundle," in which the
+  automatic refinement is guided by all shortest abstract
+  counter-examples. For more information, please check the ICCAD'03
+  paper of Wang et al., "Improving Ariadne's Bundle by Following
+  Multiple Counter-Examples in Abstraction Refinement." ]
+  
+  Author      [Chao Wang]
+
+  Copyright   [Copyright (c) 2004 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without
+  license or royalty fees, to use, copy, modify, and distribute this
+  software and its documentation for any purpose, provided that the
+  above copyright notice and the following two paragraphs appear in
+  all copies of this software.]
+
+******************************************************************************/
+
+#include "grabInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void GetFormulaNodes(Ntk_Network_t *network, Ctlp_Formula_t *F, array_t *formulaNodes);
+static void GetFaninLatches(Ntk_Node_t *node, st_table *visited, st_table *absVarTable);
+static void NodeTableAddCtlFormulaNodes(Ntk_Network_t *network, Ctlp_Formula_t *formula, st_table * nodesTable);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Compute the Cone-Of-Influence abstract model.]
+
+  Description [Compute the Cone-Of-Influence abstraction, which
+  consists of latches in the transitive supprot of the property.]
+
+  SideEffects []
+
+******************************************************************************/
+st_table *
+GrabComputeCOIAbstraction(
+  Ntk_Network_t *network,
+  Ctlp_Formula_t *invFormula)
+{
+  st_table     *formulaNodes;
+  array_t      *formulaCombNodes;
+  Ntk_Node_t   *node;
+  array_t      *nodeArray;
+  int          i;
+  st_generator *stGen;
+  st_table *absVarTable;
+
+  /* find network nodes in the immediate support of the property */
+  formulaNodes = st_init_table(st_ptrcmp, st_ptrhash);
+  NodeTableAddCtlFormulaNodes(network, invFormula, formulaNodes);
+
+  /* find network nodes in the transitive fan-in */
+  nodeArray = array_alloc(Ntk_Node_t *, 0);
+  st_foreach_item(formulaNodes, stGen,  & node, NIL(char *)) {
+    array_insert_last( Ntk_Node_t *, nodeArray, node);
+  }
+  st_free_table(formulaNodes);
+  formulaCombNodes = Ntk_NodeComputeTransitiveFaninNodes(network, nodeArray,
+							 FALSE, TRUE);
+  array_free(nodeArray);
+
+  /* extract all the latches */
+  absVarTable = st_init_table(st_ptrcmp, st_ptrhash);
+  arrayForEachItem(Ntk_Node_t *, formulaCombNodes, i, node) {
+    if (Ntk_NodeTestIsLatch(node) == TRUE) {
+      st_insert(absVarTable, node, (char *)0);
+    }
+  }
+  array_free(formulaCombNodes);
+  
+  return absVarTable;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Compute the initial abstract model.]
+
+  Description [Compute the he initial abstraction, which consists of
+  latches in the immediate supprot of the property.]
+
+  SideEffects []
+
+******************************************************************************/
+st_table *
+GrabComputeInitialAbstraction(
+  Ntk_Network_t *network, 
+  Ctlp_Formula_t *invFormula)
+{
+  array_t    *formulaNodes = array_alloc(Ntk_Node_t *, 0);
+  Ntk_Node_t *node;
+  int        i;
+  st_table   *absVarTable, *visited;
+
+  GetFormulaNodes(network, invFormula, formulaNodes);
+
+  absVarTable = st_init_table(st_ptrcmp, st_ptrhash);
+  visited = st_init_table(st_ptrcmp, st_ptrhash);
+  arrayForEachItem(Ntk_Node_t *, formulaNodes, i, node) {
+    GetFaninLatches(node, visited, absVarTable);
+  }
+
+  st_free_table(visited);
+  array_free(formulaNodes);
+  
+  return absVarTable;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Build or update partition for the current abstract model.]
+
+  Description [Build or update partition for the current abstract
+  model. It is a two-phase process, in which the first phase generated
+  the Bnvs---intermediate variables that should be created; while the
+  second phase actually create the BDDs. 
+
+  When a non-empty hash table 'absBnvTable' is given, BNVs not in this
+  table should be treated as inputs---they should not appear in the
+  partition either.
+
+  When 'absBnvTable' is not provided (e.g. when fine-grain abstraction
+  is disabled), all relevant BNVs should appear in the partition.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+GrabUpdateAbstractPartition(
+  Ntk_Network_t *network,
+  st_table *coiBnvTable,
+  st_table *absVarTable,
+  st_table *absBnvTable,
+  int partitionFlag)
+{
+  graph_t *newPart;
+  st_table *useAbsBnvTable = absBnvTable? absBnvTable:coiBnvTable;
+  
+  if (partitionFlag == GRAB_PARTITION_BUILD) {
+
+    /* free the existing partition */
+    Ntk_NetworkFreeApplInfo(network, PART_NETWORK_APPL_KEY);
+
+    /* insert bnvs whenever necessary. Note that when the current
+     * partition is not available, this function will create new bnvs
+     * and put them into the coiBnvTable. Otherwise, it retrieves
+     * existing bnvs from the current partiton */
+    Part_PartitionReadOrCreateBnvs(network, absVarTable, coiBnvTable);
+
+    /* create the new partition */
+    newPart = g_alloc();
+    newPart->user_data = (gGeneric)PartPartitionInfoCreate("default",
+					Ntk_NetworkReadMddManager(network),
+							   Part_Frontier_c);
+    Part_PartitionWithExistingBnvs(network, newPart, coiBnvTable, 
+				   absVarTable, useAbsBnvTable);
+    Ntk_NetworkAddApplInfo(network, PART_NETWORK_APPL_KEY,
+			   (Ntk_ApplInfoFreeFn) Part_PartitionFreeCallback,
+			   (void *) newPart);
+
+  }else if (partitionFlag == GRAB_PARTITION_UPDATE) {
+    fprintf(vis_stdout, 
+	    "\n ** grab error: GRAB_PARTITION_UPDATE not implemented\n");
+    assert(0);
+  }
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Create the abstract FSM.]
+
+  Description [Create the abstract FSM. Table 'coiBnvTable' contains
+  all the BNVs (i.e. intermediate variables), while Table
+  'absBnvTable' contains all the visible BNVs. BNVs not in absBnvTable
+  should be treated as inputs.
+
+  When absBnvTable is NULL (e.g. fine-grain abstraction is disabled),
+  no BNV is treated as input.
+
+  If independentFlag is TRUE, invisible latches are regarded as
+  inputs; otherwise, they are regarded as latches.]
+
+  SideEffects []
+
+******************************************************************************/
+Fsm_Fsm_t *
+GrabCreateAbstractFsm( 
+  Ntk_Network_t *network,
+  st_table *coiBnvTable,
+  st_table *absVarTable,
+  st_table *absBnvTable,
+  int partitionFlag,
+  int independentFlag)
+{
+  Fsm_Fsm_t    *fsm;
+  array_t *absLatches = array_alloc(Ntk_Node_t *, 0);
+  array_t *invisibleVars = array_alloc(Ntk_Node_t *, 0);
+  array_t *absInputs = array_alloc(Ntk_Node_t *, 0);
+  array_t *rootNodesArray = array_alloc(Ntk_Node_t *, 0);
+  st_table *rawLeafNodesTable = st_init_table(st_ptrcmp, st_ptrhash);
+  lsList topologicalNodeList;
+  lsGen  lsgen;
+  st_generator *stgen;
+  Ntk_Node_t *node;
+
+  GrabUpdateAbstractPartition(network, coiBnvTable, absVarTable, absBnvTable,
+			      partitionFlag);
+
+  /* first, compute the absLatches, invisibleVars, and absInputs:
+   * absLatches includes all the visible latch variables;
+   * invisibleVars includes all the invisible latches variables; 
+   * absInputs includes all the primary and pseudo inputs.
+   */
+  st_foreach_item(absVarTable, stgen, &node, NIL(char *)) {
+    array_insert_last(Ntk_Node_t *, absLatches, node);
+    array_insert_last(Ntk_Node_t *, rootNodesArray, 
+		      Ntk_LatchReadDataInput(node));
+    array_insert_last(Ntk_Node_t *, rootNodesArray, 
+		      Ntk_LatchReadInitialInput(node));
+  }
+    
+  Ntk_NetworkForEachCombInput(network, lsgen, node) {
+    st_insert(rawLeafNodesTable, node, (char *) (long) (-1) );
+  }
+  st_foreach_item(coiBnvTable, stgen, &node, NIL(char *)) {
+    /* unless it blongs to the current Abstract Model */
+    if (absBnvTable && !st_is_member(absBnvTable, node))
+      st_insert(rawLeafNodesTable, node, (char *) (long) (-1) );
+  }
+
+  topologicalNodeList = Ntk_NetworkComputeTopologicalOrder(network,
+							   rootNodesArray,
+							   rawLeafNodesTable);
+  lsForEachItem(topologicalNodeList, lsgen, node){
+    if (st_is_member(rawLeafNodesTable, node) &&
+	!st_is_member(absVarTable, node) ) {
+      /*if (Ntk_NodeTestIsLatch(node) || 
+	coiBnvTable && st_is_member(coiBnvTable, node))*/
+      if (Ntk_NodeTestIsLatch(node) || 
+	  (coiBnvTable && st_is_member(coiBnvTable, node)))
+	array_insert_last(Ntk_Node_t *, invisibleVars, node);
+      else
+	array_insert_last(Ntk_Node_t *, absInputs, node);
+    }
+  }
+  
+  lsDestroy(topologicalNodeList, (void (*)(lsGeneric))0);
+  st_free_table(rawLeafNodesTable);
+  array_free(rootNodesArray);
+
+
+  /* now, create the abstract Fsm according to the value of
+   * independentFlag when independentFlag is TRUE, the present state
+   * varaibles are absLatches; otherwise, they contain both absLatches
+   * and invisibleVars (with such a FSM, preimages may contain
+   * invisible vars in their supports)
+   */
+  fsm = Fsm_FsmCreateAbstractFsm(network, NIL(graph_t), 
+				 absLatches, invisibleVars, absInputs, 
+				 NIL(array_t), independentFlag);
+
+#if 0
+  /* for debugging */
+  if (partitionFlag == GRAB_PARTITION_NOCHANGE) {
+    GrabPrintNodeArray("absLatches", absLatches);
+    GrabPrintNodeArray("invisibleVars", invisibleVars);
+    GrabPrintNodeArray("absInputs", absInputs);
+  }
+#endif
+
+  array_free(invisibleVars);
+  array_free(absInputs);
+  array_free(absLatches);
+
+
+  return fsm;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Computes the set of initial states of set of latches.]
+
+  Description [Computes the set of initial states of a set of latches.
+  The nodes driving the initial inputs of the latches, called the
+  initial nodes, must not have latches in their support.  If an
+  initial node is found that has a latch in its transitive fanin, then
+  a NULL MDD is returned, and a message is written to the
+  error_string.<p>
+  
+  The initial states are computed as follows. For each latch i, the relation
+  (x_i = g_i(u)) is built, where x_i is the present state variable of latch i,
+  and g_i(u) is the multi-valued initialization function of latch i, in terms
+  of the input variables u.  These relations are then conjuncted, and the
+  input variables are existentially quantified from the result
+  (i.e. init_states(x) = \exists u \[\prod (x_i = g_i(u))\]).]
+
+  SideEffects [The result of the initial state computation is stored with
+  the FSM.]
+
+  SeeAlso [Fsm_FsmComputeReachableStates]
+  
+******************************************************************************/
+mdd_t *
+GrabComputeInitialStates(
+  Ntk_Network_t *network,
+  array_t *psVars)
+{
+  int            i = 0;
+  mdd_t         *initStates;
+  Ntk_Node_t    *node;
+  array_t       *initRelnArray;
+  array_t       *initMvfs;
+  array_t       *initNodes;
+  array_t       *initVertices;
+  array_t       *latchMddIds;
+  array_t       *inputVars = array_alloc(int, 0);
+  array_t       *combArray;
+  st_table      *supportNodes;
+  st_table      *supportVertices;
+  mdd_manager   *mddManager = Ntk_NetworkReadMddManager(network);
+  graph_t       *partition  =
+    (graph_t *) Ntk_NetworkReadApplInfo(network, PART_NETWORK_APPL_KEY);
+  int            numLatches;
+  Img_MethodType imageMethod;
+  
+  numLatches = array_n(psVars);
+
+  /* Get the array of initial nodes, both as network nodes and as
+   * partition vertices.
+   */
+  initNodes    = array_alloc(Ntk_Node_t *, numLatches);
+  initVertices = array_alloc(vertex_t *, numLatches);
+  latchMddIds  = array_alloc(int, numLatches);
+  for (i=0; i<numLatches; i++){
+    int latchMddId = array_fetch(int, psVars, i);
+    Ntk_Node_t *latch = Ntk_NetworkFindNodeByMddId(network, latchMddId);
+    Ntk_Node_t *initNode   = Ntk_LatchReadInitialInput(latch);
+    vertex_t   *initVertex = Part_PartitionFindVertexByName(partition,
+				Ntk_NodeReadName(initNode));
+    array_insert(Ntk_Node_t *, initNodes, i, initNode);
+    array_insert(vertex_t *, initVertices, i, initVertex);
+    array_insert(int, latchMddIds, i, Ntk_NodeReadMddId(latch));
+  }
+
+  /* Get the table of legal support nodes, both as network nodes and
+   * as partition vertices. Inputs (both primary and pseudo) and
+   * constants constitute the legal support nodes.
+   */
+  supportNodes    = st_init_table(st_ptrcmp, st_ptrhash);
+  supportVertices = st_init_table(st_ptrcmp, st_ptrhash);
+  combArray = Ntk_NodeComputeTransitiveFaninNodes(network, initNodes, TRUE,
+						  TRUE);
+  arrayForEachItem(Ntk_Node_t *, combArray, i, node) {
+    vertex_t *vertex = Part_PartitionFindVertexByName(partition,
+						      Ntk_NodeReadName(node));
+    if (Ntk_NodeTestIsConstant(node) || Ntk_NodeTestIsInput(node)) {
+      st_insert(supportNodes,  node, NIL(char));
+      st_insert(supportVertices,  vertex, NIL(char));
+    }
+    if (Ntk_NodeTestIsInput(node)) {
+      assert(Ntk_NodeReadMddId(node) != -1);
+      array_insert_last(int, inputVars, Ntk_NodeReadMddId(node));
+    }
+  }
+  array_free(combArray);
+  array_free(initNodes);
+  st_free_table(supportNodes);
+
+  /* Compute the initial states 
+   */
+  initMvfs = Part_PartitionCollapse(partition, initVertices,
+                                    supportVertices, NIL(mdd_t)); 
+  array_free(initVertices);
+  st_free_table(supportVertices);
+
+  /* Compute the relation (x_i = g_i(u)) for each latch. */
+  initRelnArray = array_alloc(mdd_t*, numLatches);
+  for (i = 0; i < numLatches; i++) {
+    int latchMddId = array_fetch(int, latchMddIds, i);
+    Mvf_Function_t *initMvf = array_fetch(Mvf_Function_t *, initMvfs, i);
+    mdd_t *initLatchReln = Mvf_FunctionBuildRelationWithVariable(initMvf,
+								latchMddId);
+    array_insert(mdd_t *, initRelnArray, i, initLatchReln);
+  }
+
+  array_free(latchMddIds);
+  Mvf_FunctionArrayFree(initMvfs);
+
+  imageMethod = Img_UserSpecifiedMethod();
+  if (imageMethod != Img_Iwls95_c && imageMethod != Img_Mlp_c)
+    imageMethod = Img_Iwls95_c;
+
+  initStates = Img_MultiwayLinearAndSmooth(mddManager, initRelnArray,
+                                           inputVars, psVars,
+					   imageMethod, Img_Forward_c); 
+  
+  mdd_array_free(initRelnArray); 
+  
+  array_free(inputVars);
+  
+  return (initStates);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Compute the reachable states of the abstract model.]
+
+  Description [Compute the reachable states of the abstract model.]
+  
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+GrabFsmComputeReachableStates(
+  Fsm_Fsm_t *absFsm,
+  st_table  *absVarTable,
+  st_table  *absBnvTable,
+  array_t   *invStatesArray,
+  int       verbose)
+{
+  mdd_manager     *mddManager = Fsm_FsmReadMddManager(absFsm);
+  Img_ImageInfo_t *imageInfo;
+  array_t         *fwdOnionRings;
+  mdd_t           *initStates, *mdd1,  *mddOne, *rchStates, *frontier;
+  
+  imageInfo = Fsm_FsmReadOrCreateImageInfo(absFsm, 0, 1);
+
+  fwdOnionRings = array_alloc(mdd_t *, 0);
+  mddOne = mdd_one(mddManager);
+  initStates = Fsm_FsmComputeInitialStates(absFsm);
+  array_insert_last(mdd_t *, fwdOnionRings, initStates);
+  rchStates = mdd_dup(initStates);
+
+  frontier = initStates;
+  while(TRUE) {
+    mdd1 = Img_ImageInfoComputeFwdWithDomainVars(imageInfo, frontier,
+						 rchStates, mddOne);
+    frontier = mdd_and(mdd1, rchStates, 1, 0);
+    mdd_free(mdd1);
+
+    mdd1 = rchStates;
+    rchStates = mdd_or(rchStates, frontier, 1, 1);
+    mdd_free(mdd1);
+
+    if (mdd_is_tautology(frontier, 0)) {
+      mdd_free(frontier);
+      break;
+    }
+    array_insert_last(mdd_t *, fwdOnionRings, frontier);
+
+    /* if this happens, the invariant is voilated */
+    if (!mdd_lequal_array(frontier, invStatesArray, 1, 1))
+      break;
+  }
+
+  mdd_free(mddOne);
+
+  FsmSetReachabilityOnionRings(absFsm, fwdOnionRings);
+
+  return rchStates;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Compute the reachable states inside the SORs.]
+
+  Description [Compute the reachable states inside the SORs.]
+  
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+GrabFsmComputeConstrainedReachableStates(
+  Fsm_Fsm_t *absFsm,
+  st_table *absVarTable,
+  st_table *absBnvTable,
+  array_t *SORs,
+  int verbose)
+{
+  mdd_manager     *mddManager = Fsm_FsmReadMddManager(absFsm);
+  Img_ImageInfo_t *imageInfo;
+  array_t         *rchOnionRings;
+  mdd_t           *mdd1, *mdd2, *mdd3, *mdd4;
+  mdd_t           *mddOne, *initStates, *rchStates;
+  int             i;
+
+  assert (SORs != NIL(array_t));
+
+  imageInfo = Fsm_FsmReadOrCreateImageInfo(absFsm, 0, 1);
+
+  rchOnionRings = array_alloc(mdd_t *, 0);
+  mddOne = mdd_one(mddManager);
+
+  /* the new initial states */
+  mdd2 = array_fetch(mdd_t *, SORs, 0);
+  mdd1 = Fsm_FsmComputeInitialStates(absFsm);
+  initStates = mdd_and(mdd1, mdd2, 1, 1);
+  mdd_free(mdd1);
+  array_insert(mdd_t *, rchOnionRings, 0, initStates);
+
+  /* compute the reachable states inside the previous SORs */
+  rchStates = mdd_dup(initStates);
+  for (i=0; i<array_n(SORs)-1; i++) {
+    mdd1 = array_fetch(mdd_t *, rchOnionRings, i);
+    mdd2 = Img_ImageInfoComputeFwdWithDomainVars(imageInfo,
+						 mdd1,
+						 rchStates,
+						 mddOne);
+
+    mdd3 = array_fetch(mdd_t *, SORs, i+1);
+    mdd4 = mdd_and(mdd2, mdd3, 1, 1);
+    mdd_free(mdd2);
+
+    /* if this happens, the last ring is no longer reachable */
+    if (mdd_is_tautology(mdd4, 0)) {
+      mdd_free(mdd4);
+      break;
+    }
+    array_insert(mdd_t *, rchOnionRings, i+1, mdd4);
+
+    mdd1 = rchStates;
+    rchStates = mdd_or(rchStates, mdd4, 1, 1);
+    mdd_free(mdd1);
+  }
+
+  mdd_free(mddOne);
+
+  FsmSetReachabilityOnionRings(absFsm, rchOnionRings);
+
+  return rchStates;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Compute the Synchronous Onion Rings (SORs).]
+
+  Description [Compute the Synchronous Onion Rings (SORs) with
+  backward reachability analysis. The SORs capture all the shortest
+  counter-examples to an invariant property. If the forward
+  reachability onion rings is not provided (as oldRings), it will be
+  retrived from absFsm.
+
+  cexType controls the type of the counter-example envelope:
+      GRAB_CEX_MINTERM, a single-state path,
+      GRAB_CEX_CUBE, a cube-states path,
+      GRAB_CEX_SOR, the SORs.
+  ]
+  
+  SideEffects []
+
+******************************************************************************/
+array_t *
+GrabFsmComputeSynchronousOnionRings(
+  Fsm_Fsm_t *absFsm,
+  st_table  *absVarTable,
+  st_table  *absBnvTable,
+  array_t   *oldRings,
+  mdd_t     *inv_states,
+  int       cexType,
+  int       verbose)
+{
+  mdd_manager     *mddManager = Fsm_FsmReadMddManager(absFsm);
+  Img_ImageInfo_t *imageInfo;
+  array_t         *onionRings, *synOnionRings;
+  array_t         *allPSVars;
+  mdd_t           *mddOne, *ring;
+  mdd_t           *mdd1, *mdd2, *mdd3, *mdd4;
+  int             j;
+
+  imageInfo = Fsm_FsmReadOrCreateImageInfo(absFsm, 1, 0);
+
+  /* get the forward reachability onion rings */
+  onionRings = oldRings;
+  if (onionRings == NIL(array_t))
+    onionRings = Fsm_FsmReadReachabilityOnionRings(absFsm);
+  assert(onionRings);
+
+  synOnionRings = array_alloc(mdd_t *, array_n(onionRings));
+
+  mddOne = mdd_one(mddManager);
+  allPSVars = Fsm_FsmReadPresentStateVars(absFsm);
+
+  /* the last ring */
+  mdd2 = array_fetch_last(mdd_t *, onionRings);
+  mdd1 = mdd_and(mdd2, inv_states, 1, 0);
+  if (cexType == GRAB_CEX_MINTERM)
+    ring = Mc_ComputeAMinterm(mdd1, allPSVars, mddManager);
+  else if (cexType == GRAB_CEX_CUBE) {
+    array_t *bddIds = mdd_get_bdd_support_ids(mddManager, mdd1);
+    int nvars = array_n(bddIds);
+    array_free(bddIds);
+    ring = bdd_approx_remap_ua(mdd1, (bdd_approx_dir_t)BDD_UNDER_APPROX,
+			       nvars, 1024, 1);
+    if (ring == NIL(mdd_t)) 
+      ring = mdd_dup(mdd1);   
+  }else 
+    ring = mdd_dup(mdd1);
+  mdd_free(mdd1);
+  array_insert(mdd_t *, synOnionRings, array_n(onionRings)-1, ring);
+
+  /* the rest rings */
+  for (j=array_n(onionRings)-2; j>=0; j--) {
+    mdd1 = array_fetch(mdd_t *, synOnionRings, j+1);
+    mdd2 = Img_ImageInfoComputeBwdWithDomainVars(imageInfo,
+						 mdd1,
+						 mdd1,
+						 mddOne);
+
+    mdd3 = array_fetch(mdd_t *, onionRings, j);
+    mdd4 = mdd_and(mdd2, mdd3, 1, 1);
+    mdd_free(mdd2);
+
+    if (cexType == GRAB_CEX_MINTERM) 
+      ring = Mc_ComputeAMinterm(mdd4, allPSVars, mddManager);
+    else if (cexType == GRAB_CEX_CUBE) {
+      array_t *bddIds = mdd_get_bdd_support_ids(mddManager, mdd4);
+      int nvars = array_n(bddIds);
+      array_free(bddIds);
+      ring = bdd_approx_remap_ua(mdd4, (bdd_approx_dir_t)BDD_UNDER_APPROX,
+				 nvars, 1024, 1);
+      if (ring == NIL(mdd_t)) 
+	ring = mdd_dup(mdd4);   
+    }else 
+      ring = mdd_dup(mdd4);
+    mdd_free(mdd4);
+    array_insert(mdd_t *, synOnionRings, j, ring);
+  }
+  
+  mdd_free(mddOne);
+
+  return synOnionRings;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Get the visible variable mddIds of the current abstraction.]
+
+  Description [Get the visible variable mddIds of the current
+  abstraction. Note that they are the state variables.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+GrabGetVisibleVarMddIds (
+  Fsm_Fsm_t *absFsm,
+  st_table *absVarTable)
+{
+  array_t       *visibleVarMddIds = array_alloc(int, 0);
+  st_generator  *stgen;
+  Ntk_Node_t    *node;
+  int           mddId;
+
+  st_foreach_item(absVarTable, stgen, &node, NIL(char *)) {
+    mddId = Ntk_NodeReadMddId(node);
+    array_insert_last(int, visibleVarMddIds, mddId);
+  }
+
+  return visibleVarMddIds;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Get the invisible variable mddIds of the current abstraction.]
+
+  Description [Get the invisible variable mddIds of the current
+  abstraction. Note that they include both state variables and boolean
+  network variables.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+GrabGetInvisibleVarMddIds(
+  Fsm_Fsm_t *absFsm,
+  st_table *absVarTable,
+  st_table *absBnvTable)
+{
+  Ntk_Network_t *network = Fsm_FsmReadNetwork(absFsm);
+  array_t       *inputVars = Fsm_FsmReadInputVars(absFsm);
+  array_t       *invisibleVarMddIds = array_alloc(int, 0);
+  Ntk_Node_t    *node;
+  int           i, mddId;
+
+  arrayForEachItem(int, inputVars, i, mddId) {
+    node = Ntk_NetworkFindNodeByMddId(network, mddId);
+    if ( !Ntk_NodeTestIsInput(node) && 
+	 !st_is_member(absVarTable, node) ) {
+      if (absBnvTable != NIL(st_table)) {
+	if (!st_is_member(absBnvTable, node)) {
+	  array_insert_last(int, invisibleVarMddIds, mddId);
+	}
+      }else
+	array_insert_last(int, invisibleVarMddIds, mddId);
+    }
+  }
+
+  return invisibleVarMddIds;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Test whether the refinement set of latches is sufficient.]
+
+  Description [Test whether the refinement set of latches is sufficient.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+GrabTestRefinementSetSufficient(
+  Ntk_Network_t *network,
+  array_t *SORs,
+  st_table *absVarTable,
+  int verbose)
+{
+  int  is_sufficient;
+
+  is_sufficient = !Bmc_AbstractCheckAbstractTraces(network,
+						   SORs,
+						   absVarTable,
+						   0, 0, 0);
+  return is_sufficient;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Test whether the refinement set of BNVs is sufficient.]
+
+  Description [Test whether the refinement set of BNVs is sufficient.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+GrabTestRefinementBnvSetSufficient(
+  Ntk_Network_t   *network,
+  st_table        *coiBnvTable,
+  array_t         *SORs,
+  st_table        *absVarTable,
+  st_table        *absBnvTable,
+  int             verbose)
+{
+  int     is_sufficient;
+  
+  assert(absBnvTable && coiBnvTable);
+
+  is_sufficient = 
+    !Bmc_AbstractCheckAbstractTracesWithFineGrain(network,
+						  coiBnvTable,
+						  SORs,
+						  absVarTable,
+						  absBnvTable);
+  return is_sufficient;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Minimize the refinement set of latch variable.]
+
+  Description [Minimize the refinement set of latch variable. After
+  that, also prune away the boolean network variables that are no
+  longer in the transitive fan-in.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+GrabMinimizeLatchRefinementSet(
+  Ntk_Network_t *network,
+  st_table **absVarTable,
+  st_table **absBnvTable,
+  array_t *newlyAddedLatches,  
+  array_t **newlyAddedBnvs,  
+  array_t *SORs,
+  int verbose)
+{
+  st_table      *newVertexTable, *oldBnvTable, *transFaninTable;
+  array_t       *rootArray, *transFanins, *oldNewlyAddedBnvs;
+  st_generator  *stgen;
+  Ntk_Node_t    *node;
+  int           i, flag, n_size, mddId;
+  
+  n_size = array_n(newlyAddedLatches);
+
+  if (verbose >= 3) 
+    fprintf(vis_stdout,
+	    "-- grab: minimize latch refinement set: previous size is %d\n", 
+	    n_size);
+
+  arrayForEachItem(int, newlyAddedLatches, i, mddId) {
+    node = Ntk_NetworkFindNodeByMddId(network, mddId);
+    /* first, try to drop it */
+    newVertexTable = st_copy(*absVarTable);
+    flag = st_delete(newVertexTable, &node, NIL(char *));
+    assert(flag);
+    /* if the counter-example does not come back, drop it officially */
+    flag = Bmc_AbstractCheckAbstractTraces(network,SORs,
+					   newVertexTable, 0, 0, 0);
+    if (!flag) {
+      st_free_table(*absVarTable);
+      *absVarTable = newVertexTable;
+      n_size--;
+    }else {
+      st_free_table(newVertexTable);
+      if (verbose >= 3)
+	fprintf(vis_stdout,"         add back %s (latch)\n", 
+		Ntk_NodeReadName(node));
+    }
+  }
+
+  if (verbose >= 3)
+    fprintf(vis_stdout,
+	    "-- grab: minimize latch refinement set: current  size is %d\n", 
+	    n_size);
+
+  /* prune away irrelevant BNVs */
+  if (*absBnvTable != NIL(st_table) && st_count(*absBnvTable)>0) {
+
+    rootArray = array_alloc(Ntk_Node_t *, 0);
+    st_foreach_item(*absVarTable, stgen, &node, NIL(char *)) {
+      array_insert_last(Ntk_Node_t *, rootArray, Ntk_LatchReadDataInput(node));
+      array_insert_last(Ntk_Node_t *, rootArray, 
+			Ntk_LatchReadInitialInput(node));
+    }
+    transFanins = Ntk_NodeComputeTransitiveFaninNodes(network, rootArray,
+						      TRUE, /*stopAtLatch*/
+						      FALSE /*combInputsOnly*/
+						      );
+    array_free(rootArray);
+
+    transFaninTable = st_init_table(st_ptrcmp, st_ptrhash);
+    arrayForEachItem(Ntk_Node_t *, transFanins, i, node) {
+      st_insert(transFaninTable, node, NIL(char));
+    }
+    array_free(transFanins);
+    	
+    oldBnvTable = *absBnvTable;
+    oldNewlyAddedBnvs = *newlyAddedBnvs;
+    *absBnvTable = st_init_table(st_ptrcmp, st_ptrhash);
+    *newlyAddedBnvs = array_alloc(int, 0);
+    st_foreach_item(oldBnvTable, stgen, &node, NIL(char *)) {
+      if (st_is_member(transFaninTable, node))
+	st_insert(*absBnvTable, node, NIL(char));
+    }
+    arrayForEachItem(int, oldNewlyAddedBnvs, i, mddId) {
+      node = Ntk_NetworkFindNodeByMddId(network, mddId);
+      if (st_is_member(transFaninTable, node))
+	array_insert_last(int, *newlyAddedBnvs, mddId);
+    }
+    st_free_table(transFaninTable);
+
+    if (verbose >= 5) {
+      st_foreach_item(oldBnvTable, stgen, &node, NIL(char *)) {
+	if (!st_is_member(*absBnvTable, node)) 
+	  fprintf(vis_stdout, "         prune away BNV %s\n", Ntk_NodeReadName(node));
+      }
+    }
+    
+    array_free(oldNewlyAddedBnvs);
+    st_free_table(oldBnvTable);
+  }
+  
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Minimize the refinement set of latch variable.]
+
+  Description [Minimize the refinement set of latch variable. After
+  that, also prune away the boolean network variables that are no
+  longer in the transitive fan-in.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+GrabMinimizeBnvRefinementSet(
+  Ntk_Network_t *network,
+  st_table *coiBnvTable,
+  st_table *absVarTable,
+  st_table **absBnvTable,
+  array_t *newlyAddedBnvs,    
+  array_t *SORs,
+  int verbose)
+{
+  st_table   *newBnvTable;
+  Ntk_Node_t *node;
+  int        i, flag, n_size, mddId;
+  
+  n_size = array_n(newlyAddedBnvs);
+
+  if (verbose >= 3)
+    fprintf(vis_stdout,
+	    "-- grab: minimize bnv refinement set: previous size is %d\n", 
+	    n_size);
+
+  arrayForEachItem(int, newlyAddedBnvs, i, mddId) {
+    node = Ntk_NetworkFindNodeByMddId(network, mddId);
+    /* first, try to drop it */
+    newBnvTable = st_copy(*absBnvTable);
+    flag = st_delete(newBnvTable, &node, NIL(char *));
+    assert(flag);
+    /* if the counter-example does not come back, drop it officially */
+    flag = Bmc_AbstractCheckAbstractTracesWithFineGrain(network,
+							coiBnvTable, 
+							SORs,
+							absVarTable,
+							newBnvTable);
+    if (!flag) {
+      st_free_table(*absBnvTable);
+      *absBnvTable = newBnvTable;
+      n_size--;
+    }else {
+      st_free_table(newBnvTable);
+      if (verbose >= 3)
+	fprintf(vis_stdout,"         add back %s (BNV)\n", 
+		Ntk_NodeReadName(node));
+    }
+  }
+
+  if (verbose >= 3)
+    fprintf(vis_stdout,
+	    "-- grab: minimize bnv refinement set: current  size is %d\n", 
+	    n_size);
+} 
+
+/**Function********************************************************************
+
+  Synopsis    [Clear the fields of mddId for all network nodes.]
+
+  Description [Clear the fields of mddId for all network nodes.]
+
+  SideEffects []
+
+******************************************************************************/
+void 
+GrabNtkClearAllMddIds(
+  Ntk_Network_t *network)
+{
+#ifndef NDEBUG
+  mdd_manager *mddManager = Ntk_NetworkReadMddManager(network);
+#endif
+  Ntk_Node_t *node;
+  lsGen lsgen;
+
+  assert(mddManager == NIL(mdd_manager));
+
+  Ntk_NetworkForEachNode(network, lsgen, node) {
+    Ntk_NodeSetMddId(node, NTK_UNASSIGNED_MDD_ID);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Print an array of network nodes.]
+
+  Description [Print an array of network nodes.]
+  
+  SideEffects []
+
+******************************************************************************/
+void 
+GrabPrintNodeArray(
+  char *caption,
+  array_t *theArray)
+{
+  Ntk_Node_t *node;
+  char string[32];
+  int i;
+
+  fprintf(vis_stdout, "\n%s[%d] =\n", caption, theArray?array_n(theArray):0);
+
+  if (!theArray) return;
+
+  arrayForEachItem(Ntk_Node_t *, theArray, i, node) {
+    if (Ntk_NodeTestIsLatch(node))
+      strcpy(string, "latch");
+    else if (Ntk_NodeTestIsInput(node))
+      strcpy(string, "input");
+    else if (Ntk_NodeTestIsLatchDataInput(node))
+      strcpy(string, "latchDataIn");
+    else if (Ntk_NodeTestIsLatchInitialInput(node))
+      strcpy(string, "latchInitIn");
+    else if (Ntk_NodeTestIsConstant(node))
+      strcpy(string, "const");
+    else 
+      strcpy(string, "BNV");
+
+    fprintf(vis_stdout, "%s\t(%s)\n", Ntk_NodeReadName(node), string);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Print an array of network nodes.]
+
+  Description [Print an array of network nodes.]
+  
+  SideEffects []
+
+******************************************************************************/
+void 
+GrabPrintMddIdArray(
+  Ntk_Network_t *network,
+  char *caption,
+  array_t *mddIdArray)
+{
+  Ntk_Node_t *node;
+  array_t *theArray = array_alloc(Ntk_Node_t *, array_n(mddIdArray));
+  int i, mddId;
+
+  arrayForEachItem(int, mddIdArray, i, mddId) {
+    node = Ntk_NetworkFindNodeByMddId(network, mddId);
+    array_insert(Ntk_Node_t *, theArray, i, node);
+  }
+
+  GrabPrintNodeArray(caption, theArray);
+
+  array_free(theArray);
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Print a list of network nodes.]
+
+  Description [Print a list of network nodes.]
+  
+  SideEffects []
+
+******************************************************************************/
+void 
+GrabPrintNodeList(
+  char *caption,  
+  lsList theList)
+{
+  Ntk_Node_t *node;
+  char string[32];
+  lsGen lsgen;
+
+  fprintf(vis_stdout, "\n%s[%d] =\n", caption, theList?lsLength(theList):0);
+  
+  if (!theList) return;
+
+  lsForEachItem(theList, lsgen, node) {
+    if (Ntk_NodeTestIsLatch(node))
+      strcpy(string, "latch");
+    else if (Ntk_NodeTestIsInput(node))
+      strcpy(string, "input");
+    else if (Ntk_NodeTestIsLatchDataInput(node))
+      strcpy(string, "latchDataIn");
+    else if (Ntk_NodeTestIsLatchInitialInput(node))
+      strcpy(string, "latchInitIn");
+    else if (Ntk_NodeTestIsConstant(node))
+      strcpy(string, "const");
+    else 
+      strcpy(string, "BNV");
+
+    fprintf(vis_stdout, "   %s\t %s\n", string, Ntk_NodeReadName(node));
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Print a hash table of network nodes.]
+
+  Description [Print a hash table of network nodes.]
+  
+  SideEffects []
+
+******************************************************************************/
+void 
+GrabPrintNodeHashTable(
+  char *caption,
+  st_table *theTable)
+{
+  Ntk_Node_t *node;
+  char string[32];
+  long  value;
+  st_generator *stgen;
+
+  fprintf(vis_stdout, "\n%s[%d] =\n", caption, theTable?st_count(theTable):0);
+
+  if (!theTable) return;
+
+  st_foreach_item(theTable, stgen, &node, &value) {
+    if (Ntk_NodeTestIsLatch(node))
+      strcpy(string, "latch");
+    else if (Ntk_NodeTestIsInput(node))
+      strcpy(string, "input");
+    else if (Ntk_NodeTestIsLatchDataInput(node))
+      strcpy(string, "latchDataIn");
+    else if (Ntk_NodeTestIsLatchInitialInput(node))
+      strcpy(string, "latchInitIn");
+    else if (Ntk_NodeTestIsConstant(node))
+      strcpy(string, "const");
+    else 
+      strcpy(string, "BNV");
+
+    if (value != 0)
+      fprintf(vis_stdout, "   %s\t %s\t %ld\n", string, Ntk_NodeReadName(node),
+	      value);
+    else
+      fprintf(vis_stdout, "   %s\t %s \n", string, Ntk_NodeReadName(node));
+  }
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Get network nodes that are mentioned by the formula.]
+
+  Description [Get network nodes that are mentioned by the formula.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+GetFormulaNodes(
+  Ntk_Network_t *network,
+  Ctlp_Formula_t *F,
+  array_t *formulaNodes)
+{
+
+  if (F == NIL(Ctlp_Formula_t))
+    return;
+
+  if (Ctlp_FormulaReadType(F) == Ctlp_ID_c) {
+    char *nodeNameString = Ctlp_FormulaReadVariableName(F);
+    Ntk_Node_t *node = Ntk_NetworkFindNodeByName(network, nodeNameString);
+    assert(node);
+    array_insert_last(Ntk_Node_t *, formulaNodes, node);
+    return;
+  }
+  
+  GetFormulaNodes(network, Ctlp_FormulaReadRightChild(F), formulaNodes);
+  GetFormulaNodes(network, Ctlp_FormulaReadLeftChild(F),  formulaNodes);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Get the fan-in latches of those already in the table.]
+
+  Description [Get the fan-in latches of those already in the table.]
+
+  SideEffects []
+
+******************************************************************************/
+static void 
+GetFaninLatches(
+  Ntk_Node_t *node,
+  st_table *visited,
+  st_table *absVarTable)
+{
+  if (st_is_member(visited, node))
+    return;
+
+  st_insert(visited, node, (char *)0);
+
+  if (Ntk_NodeTestIsLatch(node)) 
+    st_insert(absVarTable, node, (char *)0);
+  else {
+    int i;
+    Ntk_Node_t *fanin;
+    Ntk_NodeForEachFanin(node, i, fanin) {
+      GetFaninLatches(fanin, visited, absVarTable);
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis [Add nodes for wires referred to in formula to nodesTable.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+NodeTableAddCtlFormulaNodes( 
+  Ntk_Network_t *network,
+  Ctlp_Formula_t *formula, 
+  st_table * nodesTable )
+{
+  if (formula == NIL(Ctlp_Formula_t)) 
+    return;
+
+  if ( Ctlp_FormulaReadType( formula ) == Ctlp_ID_c ) {
+    char *nodeNameString = Ctlp_FormulaReadVariableName( formula );
+    Ntk_Node_t *node = Ntk_NetworkFindNodeByName( network, nodeNameString );
+    if( node ) 
+      st_insert( nodesTable, ( char *) node, NIL(char) );
+    return;
+  }
+  
+  NodeTableAddCtlFormulaNodes( network, Ctlp_FormulaReadRightChild( formula ), nodesTable );
+  NodeTableAddCtlFormulaNodes( network, Ctlp_FormulaReadLeftChild( formula ), nodesTable );
+}
+
+
Index: vis_dev/vis-2.3/src/hrc/hrc.h
===================================================================
--- vis_dev/vis-2.3/src/hrc/hrc.h	(revision 14)
+++ vis_dev/vis-2.3/src/hrc/hrc.h	(revision 14)
@@ -0,0 +1,389 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [hrc.h]
+
+  PackageName [hrc]
+
+  Synopsis    [Hierarchical representation of a design.]
+
+  Description [The concept of a hierarchy is directly related to the
+  constructs in a blifmv file. It is built around three important data
+  structures viz. Hrc_Model_t, Hrc_Subckt_t and Hrc_Node_t. These will be
+  referred to as model, subckt and node.<p>
+
+  A model corresponds directly to a model definition in a blifmv file. It can
+  be viewed as a black box with some I/O pins. A model could call another
+  model as a module within itself using names for the I/O pins which are, in
+  general, different from those actually used inside the model that is
+  called. The correspondence between the two sets of names is stored in a
+  subckt. A call to a model will henceforth be referred to as an instantiation
+  of the model.<p>
+               
+  Since a given model could be called by many other models, it is necessary to
+  distinguish between its different instantiations. An instantiation is
+  represented by a node.  A hierarchy is a tree of nodes. The root node of the
+  tree corresponds to the single instantiation of the root model in a blifmv
+  file. An instantiation of a model results in the instantiation of all models
+  recursively called by it. Thus, the instantiation of root model results in a
+  tree structure being formed.<p>
+               
+  There is also a structure called a hierarchy manager which contains a list
+  of all models and pointers to the root node and the current node. The
+  current node represents the current position in the hierarchy. The designer
+  can, if he wishes, make changes in this node only, or modify the whole
+  sub-tree below it.]
+
+  SeeAlso     [hrcInt.h]
+
+  Author      [Yuji Kukimoto, Shaz Qadeer]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: hrc.h,v 1.5 2005/04/16 04:23:47 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _HRC
+#define _HRC
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef struct HrcModelStruct Hrc_Model_t;
+typedef struct HrcManagerStruct Hrc_Manager_t;
+typedef struct HrcNodeStruct Hrc_Node_t;
+typedef struct HrcSubcktStruct Hrc_Subckt_t;
+typedef struct HrcLatchStruct Hrc_Latch_t;
+typedef void (*Hrc_ApplInfoFreeFn) (void *);
+typedef void (*Hrc_ApplInfoChangeFn) (Hrc_Node_t *, Hrc_Node_t *, void **);
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the models in the hierarchy manager.]
+
+  Description  [This macro iterates over the models in the hierarchy manager.
+                It is an error to modify the models while iterating over them.]
+
+  SideEffects  []
+
+  SeeAlso      []
+
+******************************************************************************/
+#define Hrc_ManagerForEachModel(                                    \
+  /* Hrc_Manager_t * */ manager   /* manager to iterate models */,  \
+  /* st_generator * */  gen       /* local variable for iterator */,\
+  /* char * */          modelName /* name of model */,              \
+  /* Hrc_Model_t * */   model     /* model * */                     \
+)                                                                   \
+  st_foreach_item(Hrc_ManagerReadModelTable(manager), gen, &(modelName), &(model))
+    
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the formal inputs of a node.]
+
+  Description  [This macro iterates over the formal inputs of a node. It is an
+                error to modify the formal inputs while iterating over them.]
+
+  SideEffects  [This macro instantiates macros from the array package.  Hence
+                it is advisable not to nest this macro within array macros.]
+
+  SeeAlso      [Hrc_NodeForEachFormalOutput()]
+
+******************************************************************************/
+#define Hrc_NodeForEachFormalInput(                             \
+  /* Hrc_Node_t * */     node /* node to iterate inputs */,     \
+  /* int */              i    /* local variable for iterator */,\
+  /* Var_Variable_t * */ var  /* input variable of node */      \
+)                                                               \
+  arrayForEachItem(Var_Variable_t *, Hrc_NodeReadFormalInputs(node), i, var)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the formal outputs of a node.]
+
+  Description  [This macro iterates over the formal outputs of a node. It is an
+                error to modify the formal outputs while iterating over them.]
+
+  SideEffects  [This macro instantiates macros from the array package.  Hence
+                it is advisable not to nest this macro within array macros.]
+
+  SeeAlso      [Hrc_NodeForEachFormalInput()]
+
+******************************************************************************/
+#define Hrc_NodeForEachFormalOutput(                            \
+  /* Hrc_Node_t * */     node /* node to iterate outputs */,    \
+  /* int */              i    /* local variable for iterator */,\
+  /* Var_Variable_t * */ var  /* output variable of node */     \
+)                                                               \
+  arrayForEachItem(Var_Variable_t *, Hrc_NodeReadFormalOutputs(node), i, var)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the actual inputs of a model.]
+
+  Description  [This macro iterates over the actual inputs of a node. It is an
+                error to modify the actual inputs while iterating over them.]
+
+  SideEffects  [This macro instantiates macros from the array package.  Hence
+                it is advisable not to nest this macro within array macros.]
+
+  SeeAlso      [Hrc_NodeForEachActualOutput()]
+
+******************************************************************************/
+#define Hrc_NodeForEachActualInput(                               \
+  /* Hrc_Node_t * */     node /* node to iterate actual inputs */,\
+  /* int */              i    /* local variable for iterator */,  \
+  /* Var_Variable_t * */ var  /* actual input variable of node */ \
+)                                                                 \
+  arrayForEachItem(Var_Variable_t *, Hrc_NodeReadActualInputs(node), i, var)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the actual outputs of a node.]
+
+  Description  [This macro iterates over the actual outputs of a node. It is an
+                error to modify the actual outputs while iterating over them.]
+
+  SideEffects  [This macro instantiates macros from the array package.  Hence
+                it is advisable not to nest this macro within array macros.]
+
+  SeeAlso      [Hrc_NodeForEachActualInput()]
+
+******************************************************************************/
+#define Hrc_NodeForEachActualOutput(                               \
+  /* Hrc_Node_t * */     node /* node to iterate actual outputs */,\
+  /* int */              i    /* local variable for iterator */,   \
+  /* Var_Variable_t * */ var  /* actual output variable of node */ \
+)                                                                  \
+  arrayForEachItem(Var_Variable_t *, Hrc_NodeReadActualOutputs(node), i, var)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the name tables of a node.]
+
+  Description  [This macro iterates over the name tables of a node. It is an
+                error to modify the name tables while iterating over them.]
+
+  SideEffects  [This macro instantiates macros from the array package.  Hence
+                it is advisable not to nest this macro within array macros.]
+
+  SeeAlso      [Hrc_NodeForEachLatch()]
+
+******************************************************************************/
+#define Hrc_NodeForEachNameTable(                             \
+  /* Hrc_Node_t * */  node  /* node to iterate tables */,     \
+  /* int */           i     /* local variable for iterator */,\
+  /* Tbl_Table_t * */ table /* table of node */               \
+)                                                             \
+  arrayForEachItem(Tbl_Table_t *, Hrc_NodeReadNameTables(node), i, table)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the subckts of a model.]
+
+  Description  [This macro iterates over the sub-circuits of a node. It is an
+                error to modify the sub-circuits while iterating over them.]
+
+  SideEffects  []
+
+  SeeAlso      []
+
+******************************************************************************/
+#define Hrc_ModelForEachSubckt(                                  \
+  /* Hrc_Model_t */    model  /* model to iterate subcircuits */,\
+  /* st_generator * */ gen    /* local variable for iterator */, \
+  /* char * */         name   /* instance name of subcircuit */, \
+  /* Hrc_Subckt_t * */ subckt /* subcircuit */                   \
+)                                                                \
+  st_foreach_item(Hrc_ModelReadSubcktTable(model), gen, &(name), &(subckt))
+    
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the children of a node.]
+
+  Description  [This macro iterates over the children of a node. It is an
+                error to modify the children while iterating over them.]
+
+  SideEffects  []
+
+  SeeAlso      []
+
+******************************************************************************/
+#define Hrc_NodeForEachChild(                                        \
+  /* Hrc_Node_t * */   node      /* node to iterate child nodes */, \
+  /* st_generator * */ gen       /* local variable for iterator */, \
+  /* char * */         childName /* name of child */,               \
+  /* Hrc_Node_t * */   child     /* child */                        \
+)                                                                    \
+  st_foreach_item(Hrc_NodeReadChildTable(node), gen, &(childName), &(child))
+    
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the latches of a node.]
+
+  Description  [This macro iterates over the latches of a node. It is an
+                error to modify the latches while iterating over them.]
+
+  SideEffects  []
+
+  SeeAlso      [Hrc_NodeForEachNameTable()]
+
+******************************************************************************/
+#define Hrc_NodeForEachLatch(                                      \
+  /* Hrc_Node_t * */   node      /* node to iterate latches */,    \
+  /* st_generator * */ gen       /* local variable for iterator */,\
+  /* char * */         latchName /* name of latch */,              \
+  /* Hrc_Latch_t * */  latch     /* latch */                       \
+)                                                                  \
+  st_foreach_item(Hrc_NodeReadLatchTable(node), gen, &(latchName), &(latch))
+    
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the formal variables of a node.]
+
+  Description  [This macro iterates over the formal variables of a node. It
+                is an error to modify the formal variables while iterating
+                over them.]
+
+  SideEffects  []
+
+  SeeAlso      [Hrc_NodeForEachFormalInput(), Hrc_NodeForEachFormalOuput()]
+
+******************************************************************************/
+#define Hrc_NodeForEachVariable(                                   \
+  /* Hrc_Node_t * */     node    /* node to iterate variables */,  \
+  /* st_generator * */   gen     /* local variable for iterator */,\
+  /* char * */           varName /* name of variable */,           \
+  /* Var_Variable_t * */ var     /* variable */                    \
+)                                                                  \
+  st_foreach_item(Hrc_NodeReadVariableTable(node), gen, &(varName), &var)
+    
+#include "tbl.h"
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void Hrc_Init(void);
+EXTERN void Hrc_End(void);
+EXTERN Hrc_Node_t * Hrc_ModelCreateHierarchy(Hrc_Manager_t *hmgr, Hrc_Model_t *model, char *instanceName);
+EXTERN boolean Hrc_NodeAddApplInfo(Hrc_Node_t *node, char * key, Hrc_ApplInfoFreeFn freeFn, Hrc_ApplInfoChangeFn changeFn, void * data);
+EXTERN void * Hrc_NodeReadApplInfo(Hrc_Node_t *node, char * key);
+EXTERN boolean Hrc_NodeFreeApplInfo(Hrc_Node_t *node, char * key);
+EXTERN void Hrc_ModelWriteBlifMv(FILE *fp, Hrc_Model_t *model, boolean isRootModel, char *rootInstanceName);
+EXTERN Hrc_Node_t * Hrc_ManagerReadRootNode(Hrc_Manager_t *manager);
+EXTERN Hrc_Node_t * Hrc_ManagerReadCurrentNode(Hrc_Manager_t *manager);
+EXTERN st_table * Hrc_ManagerReadModelTable(Hrc_Manager_t *manager);
+EXTERN Hrc_Model_t * Hrc_ManagerFindModelByName(Hrc_Manager_t *manager, char *modelName);
+EXTERN Hrc_Node_t * Hrc_ModelReadMasterNode(Hrc_Model_t *model);
+EXTERN char * Hrc_ModelReadName(Hrc_Model_t *model);
+EXTERN st_table * Hrc_ModelReadSubcktTable(Hrc_Model_t *model);
+EXTERN Hrc_Model_t * Hrc_SubcktReadModel(Hrc_Subckt_t *subckt);
+EXTERN char * Hrc_SubcktReadInstanceName(Hrc_Subckt_t *subckt);
+EXTERN array_t * Hrc_SubcktReadActualInputVars(Hrc_Subckt_t *subckt);
+EXTERN array_t * Hrc_SubcktReadActualOutputVars(Hrc_Subckt_t *subckt);
+EXTERN Hrc_Manager_t * Hrc_NodeReadManager(Hrc_Node_t *node);
+EXTERN char * Hrc_NodeReadModelName(Hrc_Node_t *node);
+EXTERN char * Hrc_NodeReadInstanceName(Hrc_Node_t *node);
+EXTERN Hrc_Node_t * Hrc_NodeReadParentNode(Hrc_Node_t *node);
+EXTERN int Hrc_NodeReadNumFormalInputs(Hrc_Node_t *node);
+EXTERN int Hrc_NodeReadNumFormalOutputs(Hrc_Node_t *node);
+EXTERN int Hrc_NodeReadNumVariables(Hrc_Node_t *node);
+EXTERN int Hrc_NodeReadNumTables(Hrc_Node_t *node);
+EXTERN int Hrc_NodeReadNumLatches(Hrc_Node_t *node);
+EXTERN int Hrc_NodeReadNumChildren(Hrc_Node_t *node);
+EXTERN array_t * Hrc_NodeReadFormalInputs(Hrc_Node_t *node);
+EXTERN array_t * Hrc_NodeReadFormalOutputs(Hrc_Node_t *node);
+EXTERN array_t * Hrc_NodeReadActualInputs(Hrc_Node_t *node);
+EXTERN array_t * Hrc_NodeReadActualOutputs(Hrc_Node_t *node);
+EXTERN array_t * Hrc_NodeReadNameTables(Hrc_Node_t *node);
+EXTERN st_table * Hrc_NodeReadChildTable(Hrc_Node_t *node);
+EXTERN st_table * Hrc_NodeReadLatchTable(Hrc_Node_t *node);
+EXTERN st_table * Hrc_NodeReadVariableTable(Hrc_Node_t *node);
+EXTERN void * Hrc_NodeReadUndef(Hrc_Node_t *node);
+EXTERN Hrc_Latch_t * Hrc_NodeFindLatchByName(Hrc_Node_t *node, char *latchName);
+EXTERN Var_Variable_t * Hrc_NodeFindVariableByName(Hrc_Node_t *node, char *varName);
+EXTERN Hrc_Node_t * Hrc_NodeFindChildByName(Hrc_Node_t *node, char *instanceName);
+EXTERN Var_Variable_t * Hrc_LatchReadInput(Hrc_Latch_t *latch);
+EXTERN Var_Variable_t * Hrc_LatchReadOutput(Hrc_Latch_t *latch);
+EXTERN Tbl_Table_t * Hrc_LatchReadResetTable(Hrc_Latch_t *latch);
+EXTERN void * Hrc_LatchReadUndef(Hrc_Latch_t *latch);
+EXTERN void Hrc_ManagerSetRootNode(Hrc_Manager_t *manager, Hrc_Node_t *node);
+EXTERN void Hrc_ManagerSetCurrentNode(Hrc_Manager_t *manager, Hrc_Node_t *currentNode);
+EXTERN boolean Hrc_NodeAddFormalInput(Hrc_Node_t *node, Var_Variable_t *var);
+EXTERN boolean Hrc_NodeAddFormalOutput(Hrc_Node_t *node, Var_Variable_t *var);
+EXTERN void Hrc_NodeAddNameTable(Hrc_Node_t *node, Tbl_Table_t *nameTable);
+EXTERN void Hrc_NodeSetUndef(Hrc_Node_t *node, void *value);
+EXTERN boolean Hrc_LatchSetResetTable(Hrc_Latch_t *latch, Tbl_Table_t *table);
+EXTERN void Hrc_LatchSetUndef(Hrc_Latch_t *latch, void *value);
+EXTERN Hrc_Manager_t * Hrc_ManagerAlloc(void);
+EXTERN Hrc_Model_t * Hrc_ModelAlloc(Hrc_Manager_t *manager, char *modelName);
+EXTERN Hrc_Node_t * Hrc_NodeAlloc(Hrc_Manager_t *manager, char *modelName, char *instanceName, Hrc_Node_t *parentNode);
+EXTERN Hrc_Node_t * Hrc_NodeDup(Hrc_Node_t *node, char *instanceName);
+EXTERN Hrc_Latch_t * Hrc_LatchCreate(Hrc_Model_t *model, Var_Variable_t *latchInput, Var_Variable_t *latchOutput);
+EXTERN void Hrc_ManagerFree(Hrc_Manager_t *manager);
+EXTERN boolean Hrc_ModelDelete(Hrc_Manager_t *manager, char *modelName);
+EXTERN Hrc_Node_t * Hrc_ManagerFindNodeByPathName(Hrc_Manager_t *manager, char *path, boolean pathFlag);
+EXTERN Var_Variable_t * Hrc_VariableFindActualFromFormal(Hrc_Node_t *node, Var_Variable_t *formalVar, Hrc_Node_t *referenceNode);
+EXTERN array_t * Hrc_ManagerObtainComponentModels(Hrc_Manager_t *manager);
+EXTERN char * Hrc_NodeFindHierarchicalName(Hrc_Node_t *node, boolean pathFlag);
+EXTERN boolean Hrc_TreeReplace(Hrc_Node_t *oldNode, Hrc_Node_t *newNode);
+EXTERN boolean Hrc_NodeTestIsInTree(Hrc_Node_t *node1, Hrc_Node_t *node2);
+EXTERN boolean Hrc_NodeTestIsUninterpreted(Hrc_Node_t *node);
+EXTERN boolean Hrc_ModelTestIsUninterpreted(Hrc_Model_t* model);
+EXTERN boolean Hrc_NodeTestRecursivelyIsUninterpreted(Hrc_Node_t* parent);
+EXTERN boolean Hrc_NodeTestIsUninterpretedNodeInHierarchy(Hrc_Manager_t* hmgr);
+EXTERN boolean Hrc_NodeCheckVariableConsistency(Hrc_Node_t *node);
+EXTERN boolean Hrc_ModelAddSubckt(Hrc_Model_t *callerModel, Hrc_Model_t *calleeModel, char *instanceName, array_t *actualInputVars, array_t *actualOutputVars);
+EXTERN void Hrc_ModelAddNameTable(Hrc_Model_t *model, Tbl_Table_t *table);
+EXTERN boolean Hrc_NodeAddChild(Hrc_Node_t *parent, Hrc_Node_t *child, array_t *actualInputs, array_t *actualOutputs);
+EXTERN boolean Hrc_NodeAddLatch(Hrc_Node_t *node, Hrc_Latch_t *latch);
+EXTERN boolean Hrc_NodeAddVariable(Hrc_Node_t *node, Var_Variable_t *var);
+EXTERN boolean Hrc_NodeDeleteVariable(Hrc_Node_t *node, Var_Variable_t *var);
+EXTERN boolean Hrc_NodeDeleteLatch(Hrc_Node_t *node, Hrc_Latch_t *latch);
+EXTERN void Hrc_ModelWriteSmv(FILE *fp, Hrc_Model_t *model, boolean isRootModel, char *rootInstanceName);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _HRC */
Index: vis_dev/vis-2.3/src/hrc/hrc.make
===================================================================
--- vis_dev/vis-2.3/src/hrc/hrc.make	(revision 14)
+++ vis_dev/vis-2.3/src/hrc/hrc.make	(revision 14)
@@ -0,0 +1,4 @@
+CSRC += hrcCmd.c hrcHierarchy.c hrcInOut.c hrcMemUtil.c hrcMisc.c hrcModify.c
+HEADERS += hrc.h hrcInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/hrc/hrcCmd.c
===================================================================
--- vis_dev/vis-2.3/src/hrc/hrcCmd.c	(revision 14)
+++ vis_dev/vis-2.3/src/hrc/hrcCmd.c	(revision 14)
@@ -0,0 +1,812 @@
+/**CFile***********************************************************************
+
+  FileName    [hrcCmd.c]
+
+  PackageName [hrc]
+
+  Synopsis    [Commands for walking around HSIS/VIS hierarchies.]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [Yuji Kukimoto]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "hrcInt.h"
+
+static char rcsid[] UNUSED = "$Id: hrcCmd.c,v 1.6 2002/09/08 21:54:25 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandCd(Hrc_Manager_t **hmgr, int argc, char **argv);
+static int CommandLs(Hrc_Manager_t **hmgr, int argc, char **argv);
+static int CommandPwd(Hrc_Manager_t **hmgr, int argc, char **argv);
+static void NodeListChildren(Hrc_Node_t *hnode, boolean recursiveFlag, int depth);
+static void PrintSpace(int depth);
+static int CommandPrintModels(Hrc_Manager_t **hmgr, int argc, char **argv);
+static int CommandPrintHierarchyStats(Hrc_Manager_t **hmgr, int argc, char **argv);
+static void PrintNodeStats(Hrc_Node_t *node, boolean isHnode);
+static void PrintNodeStatsRecursively(Hrc_Node_t *node);
+static int CommandPrintIo(Hrc_Manager_t **hmgr, int argc, char **argv);
+static int CommandPrintLatches(Hrc_Manager_t **hmgr, int argc, char **argv);
+static int _HrcStringCmp(const void * s1, const void * s2);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the hrc package.]
+
+  SideEffects []
+
+  SeeAlso     [Hrc_End]
+
+******************************************************************************/
+void
+Hrc_Init(void)
+{
+  Cmd_CommandAdd("cd", CommandCd, 0);
+  Cmd_CommandAdd("ls", CommandLs, 0);
+  Cmd_CommandAdd("pwd", CommandPwd, 0);
+  Cmd_CommandAdd("print_models", CommandPrintModels, 0);
+  Cmd_CommandAdd("print_hierarchy_stats", CommandPrintHierarchyStats, 0);
+  Cmd_CommandAdd("print_io", CommandPrintIo, 0);
+  Cmd_CommandAdd("print_latches", CommandPrintLatches, 0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Ends the hrc package.]
+
+  SideEffects []
+
+  SeeAlso     [Hrc_Init]
+
+******************************************************************************/
+void
+Hrc_End(void)
+{
+}
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [The top-level routine for cd.]
+
+  SideEffects []
+  
+  CommandName [cd]
+
+  CommandSynopsis [change the current node]
+
+  CommandArguments [ \[-h\] &lt;child_instance_name&gt; or &lt;..&gt;]
+
+  CommandDescription [Changes the current node in the existing
+  hierarchy. The argument should be either the name of a child node
+  or .. meaning the parent node. Note that cd ../foo is not allowed.<p>
+  Command options:<p>
+
+  <dl>
+
+  <dt> -h
+  <dd> Print the command usage.
+
+  </dl>
+  ]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+CommandCd(
+  Hrc_Manager_t **hmgr,
+  int argc,
+  char **argv)
+{
+  Hrc_Node_t *currentNode, *parent, *child;
+  int c;
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "h")) != EOF) {
+    switch(c){
+      case 'h':
+        goto usage;
+      default:
+        goto usage;
+    }
+  }
+
+  if (argc != 2){
+    goto usage;
+  }
+  
+  currentNode = Hrc_ManagerReadCurrentNode(*hmgr);
+  if (currentNode == NIL(Hrc_Node_t)){
+    (void)fprintf(vis_stdout,"No file has been read in.\n");
+    return 1;
+  }
+  /* go to the parent node */
+  if (strcmp(*(++argv),"..") == 0){
+    if ((parent = Hrc_NodeReadParentNode(currentNode)) == NIL(Hrc_Node_t)){
+      (void)fprintf(vis_stderr,"You are at the root node. Can't cd to a parent.\n");
+      return 1;
+    }
+    Hrc_ManagerSetCurrentNode(*hmgr,parent);
+    return 0;
+  }
+
+  if ((child = Hrc_NodeFindChildByName(currentNode,*argv)) == NIL(Hrc_Node_t)){
+    (void)fprintf(vis_stderr,"No child node whose name is %s exists in the current node.\n",*argv);
+    return 1;
+  }
+  Hrc_ManagerSetCurrentNode(*hmgr,child);
+  return 0;
+
+usage:
+  (void)fprintf(vis_stderr,"usage: cd [-h] child_name or cd ..\n");
+  (void) fprintf(vis_stderr, "   -h \t\tprint the command usage\n");  
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [The top-level routine for ls.]
+
+  SideEffects []
+
+  CommandName [ls]
+
+  CommandSynopsis [list all the child nodes at the current node]
+
+  CommandArguments [\[-h\] \[-R\]]
+
+  CommandDescription [Lists all the child nodes at the current node.<p>
+  Command options:<p>
+  
+  <dl>
+
+  <dt> -h
+  <dd> Print the command usage.<p>
+  
+  <dt> -R
+  <dd> Call ls recursively all the way down to leaves.
+  </dl>]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+CommandLs(
+  Hrc_Manager_t **hmgr,
+  int argc,
+  char **argv)
+{
+  int recursiveFlag = 0;
+  int c;
+  Hrc_Node_t *currentNode;
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "hR")) != EOF) {
+    switch(c){
+      case 'h':
+        goto usage;
+      case 'R':
+        recursiveFlag = 1;
+        break;
+      default:
+        goto usage;
+    }
+  }
+  /* if there are some arguments for ls */
+  if (argc != util_optind){
+    goto usage;
+  }
+
+  currentNode = Hrc_ManagerReadCurrentNode(*hmgr);
+  if (currentNode == NIL(Hrc_Node_t)){
+    (void)fprintf(vis_stdout,"No file has been read in.\n");
+    return 1;
+  }
+  NodeListChildren(currentNode, recursiveFlag, 0);
+  return 0;
+
+usage:
+  (void)fprintf(vis_stderr,"usage: ls [-h] [-R]\n");
+  (void) fprintf(vis_stderr, "   -h \t\tprint the command usage\n");
+  (void) fprintf(vis_stderr, "   -R \t\tprint recursive tree\n");  
+  
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [The top-level routine for pwd.]
+
+  SideEffects []
+
+  CommandName [pwd]
+  
+  CommandSynopsis [print out the full path of the current node 
+  from the root node]
+  
+  CommandArguments [ \[-h\] ]
+  
+  CommandDescription [Prints out the full path of the current node from
+  the root node.<p>
+  Command options:<p>
+
+  <dl>
+
+  <dt> -h
+  <dd> Print the command usage.
+
+  </dl>
+  ]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+CommandPwd(
+  Hrc_Manager_t **hmgr,
+  int argc,
+  char **argv)
+{
+  Hrc_Node_t *currentNode;
+  Hrc_Node_t *rootNode;
+  char *separator, *hierarchicalName;
+  int c;
+  
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "h")) != EOF) {
+    switch(c){
+      case 'h':
+        goto usage;
+      default:
+        goto usage;
+    }
+  }
+  if (argc != 1){
+    goto usage;
+  }
+  
+  currentNode = Hrc_ManagerReadCurrentNode(*hmgr);
+  if (currentNode == NIL(Hrc_Node_t)){
+    (void)fprintf(vis_stdout,"No file has been read in.\n");
+    return 1;
+  }
+  rootNode = Hrc_ManagerReadRootNode(*hmgr);
+  separator = (char *) ((rootNode == currentNode) ? "" : ".");
+  hierarchicalName = Hrc_NodeFindHierarchicalName(currentNode, FALSE);
+  (void)fprintf(vis_stdout,"%s%s%s\n", Hrc_NodeReadInstanceName(rootNode),
+                separator, hierarchicalName);
+  FREE(hierarchicalName);
+  return 0;
+
+usage:
+  (void)fprintf(vis_stderr,"usage: pwd [-h]\n");
+  (void) fprintf(vis_stderr, "   -h \t\tprint the command usage\n");  
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [The core routine for the command ls.]
+
+  Description [The core routine for the command ls. If the second argument
+  is set to 1, it calls the ls routine recursively all the way down to leaves.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+NodeListChildren(
+  Hrc_Node_t *hnode,
+  boolean recursiveFlag,
+  int depth)
+{
+  st_generator *gen;
+  char *childName;
+  Hrc_Node_t *child;
+  int newDepth, i;
+  array_t *tmpArray;
+
+  newDepth = depth + 1;
+  tmpArray = array_alloc(char *,0);
+  Hrc_NodeForEachChild(hnode,gen,childName,child){
+    array_insert_last(char *,tmpArray,childName);
+  }
+  array_sort(tmpArray,_HrcStringCmp);
+  for (i=0; i < array_n(tmpArray); i++){
+    PrintSpace(depth);
+    childName = array_fetch(char *,tmpArray,i);
+    (void)fprintf(vis_stdout,"%s\n",childName);
+    if (recursiveFlag == 1){
+      NodeListChildren(Hrc_NodeFindChildByName(hnode,childName),recursiveFlag,newDepth);
+    } 
+  } 
+  array_free(tmpArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints out spaces.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+PrintSpace(int depth)
+{
+  int i;
+  for (i=0; i < depth; i++){
+    (void)fprintf(vis_stdout," ");
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [This function the statistics of a model.]
+
+  SideEffects []
+
+  CommandName [print_models]
+  
+  CommandSynopsis [list all the models and their statistics]
+  
+  CommandArguments [ \[-h\] ]
+  
+  CommandDescription [Lists all the models and prints information about
+  the number of variables, tables, latches etc. in them.<p>
+  Command options:<p>
+
+  <dl>
+
+  <dt> -h
+  <dd> Print the command usage.
+
+  </dl>
+  ]
+  
+  SeeAlso     []
+
+******************************************************************************/
+static int 
+CommandPrintModels(
+  Hrc_Manager_t **hmgr,
+  int argc,
+  char **argv)
+{
+  st_generator *gen;
+  char *name;
+  Hrc_Model_t *model;
+  Hrc_Node_t *node;
+  int c;
+  
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "h")) != EOF) {
+    switch(c){
+      case 'h':
+        goto usage;
+      default:
+        goto usage;
+    }
+  }
+  if(argc != 1) {
+    goto usage;
+  }
+
+  node = Hrc_ManagerReadCurrentNode(*hmgr);
+  if (node == NIL(Hrc_Node_t)){
+    (void)fprintf(vis_stderr,"No file has been read in.\n");
+    return 1;
+  }
+
+  Hrc_ManagerForEachModel(*hmgr, gen, name, model) {
+    PrintNodeStats(Hrc_ModelReadMasterNode(model), FALSE);
+    (void) fprintf(vis_stdout, "subckts = %d\n",
+                   st_count(Hrc_ModelReadSubcktTable(model)));
+  }
+  return 0;
+  
+usage:
+  (void) fprintf(vis_stderr, "usage: print_models [-h]\n");
+  (void) fprintf(vis_stderr, "   -h \t\tprint the command usage\n");  
+  return 1;        
+}
+
+/**Function********************************************************************
+
+  Synopsis    [This function prints the statistics of the hierarchy.]
+   
+  SideEffects []
+
+  CommandName [print_hierarchy_stats]
+  
+  CommandSynopsis [print the statistics of the current node]
+  
+  CommandArguments [ \[-h\] \[-R\] ]
+  
+  CommandDescription [Prints the statistics of the current node. Note that
+  it is not necessary to invoke flatten_hierarchy first to create a network.<p>
+  Command options:<p>
+  <dl>
+
+  <dt> -h
+  <dd> Print the command usage <p>
+  
+  <dt> -R
+  <dd> Print statistics for nodes recursively all the way down to leaves.
+
+  </dl>
+  ]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+CommandPrintHierarchyStats(
+  Hrc_Manager_t **hmgr,
+  int argc,
+  char **argv)
+{
+  int c;
+  int recursiveFlag = 0;
+  Hrc_Node_t *node;
+  
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "hR")) != EOF) {
+    switch(c){
+      case 'h':
+        goto usage;
+      case 'R':
+        recursiveFlag = 1;
+        break;
+      default:
+        goto usage;
+    }
+  }
+  /* if there are some arguments left */
+  if (argc != util_optind){
+    goto usage;
+  }
+
+  node = Hrc_ManagerReadCurrentNode(*hmgr);
+  if (node == NIL(Hrc_Node_t)){
+    (void)fprintf(vis_stderr,"No file has been read in.\n");
+    return 1;
+  }
+  
+  if(recursiveFlag) {
+    PrintNodeStatsRecursively(node);
+  }
+  else {
+    PrintNodeStats(node, TRUE);
+  }
+  return 0;
+usage:
+  (void) fprintf(vis_stderr,"usage: print_hierarchy_stats [-h][-R]\n");
+  (void) fprintf(vis_stderr, "   -h \t\tprint the command usage\n");
+  (void) fprintf(vis_stderr, "   -R \t\tprint recursive tree\n");  
+  return 1;  
+}
+
+/**Function********************************************************************
+
+  Synopsis    [This function prints the statistics of a node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+PrintNodeStats(
+  Hrc_Node_t *node,
+  boolean isHnode)
+{
+  (void) fprintf(vis_stdout, "Model name = %s", Hrc_NodeReadModelName(node));
+  if(isHnode) {
+    (void) fprintf(vis_stdout, ", Instance name = %s\n",
+                   Hrc_NodeReadInstanceName(node));
+  }
+  else {
+    (void) fprintf(vis_stdout, "\n");
+  }
+  (void) fprintf(vis_stdout, "inputs = %d,", Hrc_NodeReadNumFormalInputs(node));
+  (void) fprintf(vis_stdout, " outputs = %d,", Hrc_NodeReadNumFormalOutputs(node));
+  (void) fprintf(vis_stdout, " variables = %d,", Hrc_NodeReadNumVariables(node));
+  (void) fprintf(vis_stdout, " tables = %d,", Hrc_NodeReadNumTables(node));
+  (void) fprintf(vis_stdout, " latches = %d", Hrc_NodeReadNumLatches(node));
+  if(isHnode) {
+    (void) fprintf(vis_stdout, ", children = %d\n", Hrc_NodeReadNumChildren(node));
+  }
+  else {
+    (void) fprintf(vis_stdout, "\n");
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [This function prints the statistics of each node in the
+               subtree rooted at node. ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+PrintNodeStatsRecursively(
+  Hrc_Node_t *node)
+{
+  Hrc_Node_t *childNode;
+  st_generator *gen;
+  char *name;
+  
+  PrintNodeStats(node, TRUE);
+  Hrc_NodeForEachChild(node, gen, name, childNode) {
+    PrintNodeStatsRecursively(childNode);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [This function prints the names of inputs/outputs in
+  the current node.]
+   
+  SideEffects []
+
+  CommandName [print_io]
+  
+  CommandSynopsis [print the names of inputs/outputs in the current node]
+  
+  CommandArguments [ \[-h\] ]
+  
+  CommandDescription [Prints the names of inputs/outputs in the current node.<p>
+  Command options:<p>
+  <dl>
+  <dt> -h
+  <dd> Print the command usage.
+  </dl>
+  ]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+CommandPrintIo(
+  Hrc_Manager_t **hmgr,
+  int argc,
+  char **argv)
+{
+  int c, i;
+  Hrc_Node_t *node;
+  Var_Variable_t *var;
+  array_t *tmpArray;
+  
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "h")) != EOF) {
+    switch(c){
+      case 'h':
+        goto usage;
+      default:
+        goto usage;
+    }
+  }
+  /* if there are some arguments left */
+  if (argc != util_optind){
+    goto usage;
+  }
+  node = Hrc_ManagerReadCurrentNode(*hmgr);
+  if (node == NIL(Hrc_Node_t)){
+    (void)fprintf(vis_stderr,"No file has been read in.\n");
+    return 1;
+  }
+  
+  if (Hrc_NodeReadNumFormalInputs(node) == 0){
+    fprintf(vis_stdout,"No inputs\n");
+  }
+  else {
+    tmpArray = array_alloc(char *,0);
+    Hrc_NodeForEachFormalInput(node,i,var){
+      array_insert_last(char *,tmpArray,Var_VariableReadName(var));
+    }
+    array_sort(tmpArray,_HrcStringCmp);
+    fprintf(vis_stdout,"inputs:");
+    for (i=0; i < array_n(tmpArray); i++){
+      fprintf(vis_stdout," %s",array_fetch(char *,tmpArray,i));
+    }
+    fprintf(vis_stdout,"\n");
+    array_free(tmpArray);
+  }
+
+  if (Hrc_NodeReadNumFormalOutputs(node) == 0){
+    fprintf(vis_stdout,"No outputs\n");
+  }
+  else {
+    tmpArray = array_alloc(char *,0);
+    Hrc_NodeForEachFormalOutput(node,i,var){
+      array_insert_last(char *,tmpArray,Var_VariableReadName(var));
+    }
+    array_sort(tmpArray,_HrcStringCmp);
+    fprintf(vis_stdout,"outputs:");
+    for (i=0; i < array_n(tmpArray); i++){
+      fprintf(vis_stdout," %s",array_fetch(char *,tmpArray,i));
+    }
+    fprintf(vis_stdout,"\n");
+    array_free(tmpArray);
+  }
+  return 0;
+
+usage:
+  (void) fprintf(vis_stderr,"usage: print_io [-h]\n");
+  (void) fprintf(vis_stderr, "   -h \t\tprint the command usage\n");
+  return 1;  
+}
+
+/**Function********************************************************************
+
+  Synopsis    [This function prints the names of latches in
+  the current node.]
+   
+  SideEffects []
+
+  CommandName [print_latches]
+  
+  CommandSynopsis [print the names of latches in the current node]
+  
+  CommandArguments [ \[-h\] ]
+  
+  CommandDescription [Prints the names of latches in the current node.<p>
+  Command options:<p>
+  <dl>
+  <dt> -h
+  <dd> Print the command usage.
+  </dl>
+  ]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+CommandPrintLatches(
+  Hrc_Manager_t **hmgr,
+  int argc,
+  char **argv)
+{
+  int c, i;
+  Hrc_Node_t *node;
+  st_generator *gen;
+  char *latchName;
+  Hrc_Latch_t *latch;
+  array_t *tmpArray;
+  
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "h")) != EOF) {
+    switch(c){
+      case 'h':
+        goto usage;
+      default:
+        goto usage;
+    }
+  }
+  /* if there are some arguments left */
+  if (argc != util_optind){
+    goto usage;
+  }
+  node = Hrc_ManagerReadCurrentNode(*hmgr);
+  if (node == NIL(Hrc_Node_t)){
+    (void)fprintf(vis_stderr,"No file has been read in.\n");
+    return 1;
+  }
+  
+  if (Hrc_NodeReadNumLatches(node) == 0){
+    fprintf(vis_stdout,"No latches\n");
+  }
+  else {
+    tmpArray = array_alloc(char *,0);
+    Hrc_NodeForEachLatch(node,gen,latchName,latch){
+      array_insert_last(char *,tmpArray,latchName);
+    }
+    array_sort(tmpArray,_HrcStringCmp);
+    for (i=0; i < array_n(tmpArray); i++){
+      fprintf(vis_stdout,"%s ",array_fetch(char *,tmpArray,i));
+    }
+    fprintf(vis_stdout,"\n");
+    array_free(tmpArray);
+  }
+  return 0;
+
+usage:
+  (void) fprintf(vis_stderr,"usage: print_latches [-h]\n");
+  (void) fprintf(vis_stderr, "   -h \t\tprint the command usage\n");
+  return 1;  
+}
+
+/**Function********************************************************************
+
+  Synopsis    [This function is used for string comparison in array_sort.]
+
+  Description [This function is used for string comparison in array_sort.]
+   
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+_HrcStringCmp(
+  const void * s1,
+  const void * s2)
+{
+  return(strcmp(*(char **)s1, *(char **)s2));
+}
+
Index: vis_dev/vis-2.3/src/hrc/hrcHierarchy.c
===================================================================
--- vis_dev/vis-2.3/src/hrc/hrcHierarchy.c	(revision 14)
+++ vis_dev/vis-2.3/src/hrc/hrcHierarchy.c	(revision 14)
@@ -0,0 +1,228 @@
+/**CFile***********************************************************************
+
+  FileName    [hrcHierarchy.c]
+
+  PackageName [hrc]
+
+  Synopsis    [Creates a hierarchy from model definitions.]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [Yuji Kukimoto]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "hrcInt.h"
+
+static char rcsid[] UNUSED = "$Id: hrcHierarchy.c,v 1.4 2005/04/16 04:23:47 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static Hrc_Node_t * _HrcCreateHierarchyAux(Hrc_Manager_t *hmgr, Hrc_Model_t *model, char *instanceName, st_table *pathTable);
+static int _HrcConnectParentChild(Hrc_Node_t *parent, Hrc_Node_t *child, Hrc_Subckt_t *subckt);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a hierarchy from model definitinos.]
+
+  Description [Creates a hierarchy from model definitinos. The second
+  argument is a pointer to the root model. The last argument is the name
+  of the root node. A hash table pathTable is used to check to see if
+  there is no cyclic model definition.]
+
+  SideEffects []
+
+  SeeAlso     [_HrcCreateHierarchyAux]
+
+******************************************************************************/
+
+Hrc_Node_t *
+Hrc_ModelCreateHierarchy(
+  Hrc_Manager_t *hmgr,
+  Hrc_Model_t *model,
+  char *instanceName)
+{
+  st_table *pathTable = st_init_table(st_ptrcmp,st_ptrhash);
+  Hrc_Node_t *rootNode = _HrcCreateHierarchyAux(hmgr,model,instanceName,pathTable);
+  st_free_table(pathTable);
+  return rootNode;
+}
+    
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Recursively creates a hierarchy from model definitinos.]
+
+  Description []
+
+  SideEffects [pathTable is updated to keep track of the models used
+  from the root to the current node.]
+
+  SeeAlso     [Hrc_CreateHierarchy]
+
+******************************************************************************/
+
+static Hrc_Node_t *
+_HrcCreateHierarchyAux(
+  Hrc_Manager_t *hmgr,
+  Hrc_Model_t *model,
+  char *instanceName,
+  st_table *pathTable)
+{
+  Hrc_Node_t *rootNode, *childNode;
+  Hrc_Model_t *modelToBeInstantiated;
+  Hrc_Subckt_t *subckt;
+  st_generator *gen;
+
+  if (st_is_member(pathTable,(char *)model) == 1){
+    error_append("Model ");
+    error_append(Hrc_ModelReadName(model));
+    error_append(" is defined by using itself.\n");
+    return NIL(Hrc_Node_t);
+  }
+  rootNode = Hrc_NodeDup(Hrc_ModelReadMasterNode(model),instanceName);
+  (void)st_insert(pathTable,model,NULL);
+
+  Hrc_ModelForEachSubckt(model,gen,instanceName,subckt){
+    modelToBeInstantiated = Hrc_SubcktReadModel(subckt);
+    childNode = _HrcCreateHierarchyAux(hmgr,modelToBeInstantiated,Hrc_SubcktReadInstanceName(subckt),pathTable);
+    if (childNode == NIL(Hrc_Node_t)){
+      return NIL(Hrc_Node_t);
+    }
+    if (_HrcConnectParentChild(rootNode,childNode,subckt) == 0){
+      return NIL(Hrc_Node_t);
+    }
+  }
+  (void)st_delete(pathTable,&model,NULL);
+  return rootNode;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Connects a parent node and a child node using Hrc_Subckt_t
+  information.]
+
+  Description []
+
+  SideEffects [The parent node and the child node are connected together
+  in the hierarchy.]
+
+  SeeAlso     [Hrc_NodeAddChild]
+
+******************************************************************************/
+static int
+_HrcConnectParentChild(
+  Hrc_Node_t *parent, 
+  Hrc_Node_t *child,
+  Hrc_Subckt_t *subckt)
+{
+  array_t *actualInputVars, *actualOutputVars;
+  array_t *realActualInputVars, *realActualOutputVars;
+  int i;
+  Var_Variable_t *var, *realVar;
+
+  /* actual inputs and outputs in the master hnode corresponsing to the parent */
+  actualInputVars = Hrc_SubcktReadActualInputVars(subckt);
+  actualOutputVars = Hrc_SubcktReadActualOutputVars(subckt);
+
+  /* collect all the actual inputs in the parent */
+  realActualInputVars = array_alloc(Var_Variable_t *,0);
+  for (i=0; i < array_n(actualInputVars); i++){
+    var = array_fetch(Var_Variable_t *,actualInputVars,i);
+    realVar = Hrc_NodeFindVariableByName(parent,Var_VariableReadName(var)); 
+    array_insert_last(Var_Variable_t *,realActualInputVars,realVar);
+  }
+  /* collect all the actual outputs in the parent */
+  realActualOutputVars = array_alloc(Var_Variable_t *,0);
+  for (i=0; i < array_n(actualOutputVars); i++){
+    var = array_fetch(Var_Variable_t *,actualOutputVars,i);
+    realVar = Hrc_NodeFindVariableByName(parent,Var_VariableReadName(var)); 
+    array_insert_last(Var_Variable_t *,realActualOutputVars,realVar);
+  }
+  /* connects the parent and the child using an hrc function */
+  if (Hrc_NodeAddChild(parent,child,realActualInputVars,realActualOutputVars) == 0){
+     return 0;
+  }
+  return 1;
+}
+  
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/hrc/hrcInOut.c
===================================================================
--- vis_dev/vis-2.3/src/hrc/hrcInOut.c	(revision 14)
+++ vis_dev/vis-2.3/src/hrc/hrcInOut.c	(revision 14)
@@ -0,0 +1,1408 @@
+/**CFile***********************************************************************
+
+  FileName    [hrcInOut.c]
+
+  PackageName [hrc]
+
+  Synopsis    [This file provides the functions for accessing the fields
+               of the data structures of the hrc package.]
+
+  SeeAlso     []
+
+  Author      [Shaz Qadeer]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "hrcInt.h"
+#include "io.h"
+
+static char rcsid[] UNUSED = "$Id: hrcInOut.c,v 1.6 2005/04/28 14:16:09 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Associates application specific data with a node.]
+
+  Description [Adds the key/data pair to the node's applInfoTable. Key may
+  be an arbitrary string; to avoid possible conflicts with other applications,
+  key should be prefixed with the application's package name, for example
+  "Pkg_HrcNodeApplKey".  A copy is made of the string key before it is
+  inserted into applInfoTable. The contents of data are arbitrary; the
+  hierarchy package does not interpret the data. The freeFn is called on data
+  when a node is freed, or when Hrc_NodeFreeApplInfo() is called with the same
+  value of key. The freeFn takes (void *) as its only argument, and returns
+  void. The changeFn is called when a subtree in the hierarchy rooted at
+  oldNode is replaced by another tree rooted at newNode. It takes three
+  arguments - oldNode, newNode and &(applInfo->data), and returns void. Note
+  the order of the three arguments. <p>
+
+  If this function is called with a value of key that already exists in the
+  applInfoTable then the data for the previous entry is freed using the
+  freeFn, its fields are overwritten by the new ones passed as arguments to
+  the function and TRUE is returned. Otherwise, FALSE is returned. 
+
+  <p>
+  WARNING:  This function does not make a copy of data before inserting it
+  into the table.  By calling this function, the application is surrendering
+  responsibility to the hierarchy to free the data.  Once this function is
+  called on data, the data should be freed only by calling
+  Hrc_NodeFreeApplInfo(), Hrc_ManagerFree() or Hrc_TreeReplace().  In other
+  words, it is an error for the application to explicitly free the data
+  without using one of these functions. </p>]
+
+  SideEffects []
+
+  SeeAlso     [Hrc_NodeFreeApplInfo() Hrc_NodeReadApplInfo()]
+
+******************************************************************************/
+boolean
+Hrc_NodeAddApplInfo(
+  Hrc_Node_t *node,
+  char * key,
+  Hrc_ApplInfoFreeFn  freeFn,
+  Hrc_ApplInfoChangeFn changeFn,
+  void * data)
+{
+  ApplInfo_t *applInfo;
+  boolean status;
+  
+  if (st_lookup(node->applInfoTable, key, &applInfo)) {
+    (*applInfo->freeFn)(applInfo->data);
+    status = TRUE;
+  }
+  else {
+    char       *keyCopy  = util_strsav(key);
+
+    applInfo = ALLOC(ApplInfo_t, 1);
+    st_insert(node->applInfoTable, keyCopy, applInfo);
+    status = FALSE;
+  }
+  applInfo->freeFn = freeFn;
+  applInfo->changeFn = changeFn;
+  applInfo->data   = data;
+  return status;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns data corresponding to key if it exists, else returns NULL.]
+
+  Description [If data corresponding to key is associated with the node, then
+  returns a pointer to data (as void *).  Otherwise, returns NULL.]
+
+  SideEffects []
+
+  SeeAlso     [Hrc_NodeAddApplInfo() Hrc_NodeFreeApplInfo()]
+
+******************************************************************************/
+void *
+Hrc_NodeReadApplInfo(
+  Hrc_Node_t *node,
+  char * key)
+{
+  int         status;
+  ApplInfo_t *applInfo;
+  
+  status = st_lookup(node->applInfoTable, key, &applInfo);
+  if (status == 1) {
+    return (applInfo->data);
+  }
+  else {
+    return (NIL(void));
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees application-specific data from a node.]
+
+  Description [If data corresponding to key exists in the node, then frees
+  the data using the associated free function, removes the key/data pair from
+  the network's applInfoTable, and returns TRUE.  If key does not exist, then
+  the function does nothing and returns FALSE.
+  <p>
+  WARNING: This function should be called only if a corresponding call to
+  Hrc_NodeAddApplInfo() has already been made.</p>]
+
+  SideEffects []
+
+  SeeAlso     [Hrc_NodeAddApplInfo() Hrc_NodeReadApplInfo()]
+
+******************************************************************************/
+boolean
+Hrc_NodeFreeApplInfo(
+  Hrc_Node_t *node,
+  char * key)
+{
+  int         status;
+  ApplInfo_t *applInfo;
+  
+  status = st_lookup(node->applInfoTable, key, &applInfo);
+
+  if (status == 1) {
+    st_delete(node->applInfoTable, &key, &applInfo);
+    (*applInfo->freeFn)(applInfo->data);
+    FREE(key);  /* frees the string contained in the table */
+    FREE(applInfo);
+  }
+
+  return ((status) ? TRUE : FALSE);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Writes out a model definition.]
+
+  Description [Writes out a model definition. The second argument is a pointer
+  to a model to be written out. If isRootModel is TRUE, the function prints
+  out .root to specify that the model is a root model. The last argument
+  specifies the instance name of the root model and is used only if isRootModel
+  is set to TRUE.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Hrc_ModelWriteBlifMv(
+  FILE *fp,
+  Hrc_Model_t *model,
+  boolean isRootModel,
+  char *rootInstanceName)
+{
+  Hrc_Node_t *hnode, *subcktHnode;
+  Hrc_Model_t *subcktModel;
+  int i, is_enum, range;
+  Var_Variable_t *var, *actualVar;
+  Hrc_Latch_t *latch;
+  Hrc_Subckt_t *subckt;
+  Tbl_Table_t *table;
+  char *varName, *latchName, *instanceName;
+  st_generator *gen;
+  array_t *subcktActualInputVars, *subcktActualOutputVars;
+
+  (void)fprintf(fp,".model %s\n",Hrc_ModelReadName(model));
+  if (isRootModel){
+    (void)fprintf(fp,".root %s\n",rootInstanceName);
+  }
+  hnode = Hrc_ModelReadMasterNode(model);
+
+  /* .inputs */
+  if (Hrc_NodeReadNumFormalInputs(hnode) != 0){
+    (void)fprintf(fp,".inputs ");
+    Hrc_NodeForEachFormalInput(hnode,i,var){
+      (void)fprintf(fp,"%s ",Var_VariableReadName(var));
+    }
+    (void)fprintf(fp,"\n");
+  }
+
+  /* .outputs */
+  if (Hrc_NodeReadNumFormalOutputs(hnode) != 0){
+    (void)fprintf(fp,".outputs ");
+    Hrc_NodeForEachFormalOutput(hnode,i,var){
+      (void)fprintf(fp,"%s ",Var_VariableReadName(var));
+    }
+    (void)fprintf(fp,"\n");
+  }
+
+  /* .mv */
+  Hrc_NodeForEachVariable(hnode,gen,varName,var){
+    is_enum = Var_VariableTestIsEnumerative(var);
+    range = Var_VariableReadNumValues(var);
+    
+    if (is_enum == 1){
+      if (range == 2){
+        /* Boolean enumerative variables need no .mv declaration. */
+        continue;
+      }
+      else {
+        (void)fprintf(fp,".mv %s %d\n",Var_VariableReadName(var),range);
+      }
+    }
+    else {
+      /* variable var is symbolic */
+      (void)fprintf(fp,".mv %s %d ",Var_VariableReadName(var),range);
+      for (i=0; i < range; i++){
+        (void)fprintf(fp,"%s ",Var_VariableReadSymbolicValueFromIndex(var,i));
+      }
+      (void)fprintf(fp,"\n");
+    }
+  }
+
+  /* .latches */
+  Hrc_NodeForEachLatch(hnode,gen,latchName,latch){
+    (void)fprintf(fp,".latch %s %s\n",
+       Var_VariableReadName(Hrc_LatchReadInput(latch)),
+       Var_VariableReadName(Hrc_LatchReadOutput(latch)));
+    Tbl_TableWriteBlifMvToFile(Hrc_LatchReadResetTable(latch),1,fp);
+  }
+
+  /* .subckt */
+  Hrc_ModelForEachSubckt(model,gen,instanceName,subckt){
+    subcktModel = Hrc_SubcktReadModel(subckt);
+    subcktHnode = Hrc_ModelReadMasterNode(subcktModel);
+    subcktActualInputVars = Hrc_SubcktReadActualInputVars(subckt);
+    subcktActualOutputVars = Hrc_SubcktReadActualOutputVars(subckt);
+
+    (void)fprintf(fp,".subckt %s %s ",
+       Hrc_ModelReadName(subcktModel), Hrc_SubcktReadInstanceName(subckt));
+    Hrc_NodeForEachFormalInput(subcktHnode,i,var){
+      actualVar = array_fetch(Var_Variable_t *,subcktActualInputVars,i);
+      (void)fprintf(fp,"%s = %s ",Var_VariableReadName(var),Var_VariableReadName(actualVar)); 
+    }   
+    Hrc_NodeForEachFormalOutput(subcktHnode,i,var){
+      actualVar = array_fetch(Var_Variable_t *,subcktActualOutputVars,i);
+      (void)fprintf(fp,"%s = %s ",Var_VariableReadName(var),Var_VariableReadName(actualVar)); 
+    }   
+    (void)fprintf(fp,"\n");
+  }
+
+  /* .names */
+  Hrc_NodeForEachNameTable(hnode,i,table){
+    Tbl_TableWriteBlifMvToFile(table,0,fp);
+  }
+
+  (void)fprintf(fp,".end\n");
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes out a model definition in NuSMV format.]
+
+  Description [Writes out a model definition. The second argument is a
+  pointer to a model to be written out. If isRootModel is TRUE, the
+  function prints out .root to specify that the model is a root
+  model. The last argument specifies the instance name of the root
+  model and is used only if isRootModel is set to TRUE.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Hrc_ModelWriteSmv(
+  FILE *fp,
+  Hrc_Model_t *model,
+  boolean isRootModel,
+  char *rootInstanceName)
+{
+  Hrc_Node_t *hnode, *subcktHnode;
+  Hrc_Model_t *subcktModel;
+  int i, is_enum, range;
+  Var_Variable_t *var, *actualVar;
+  Hrc_Latch_t *latch;
+  Hrc_Subckt_t *subckt;
+  Tbl_Table_t *table;
+  char *varName, *latchName, *instanceName;
+  st_generator *gen;
+  array_t *subcktActualInputVars, *subcktActualOutputVars;
+
+  hnode = Hrc_ModelReadMasterNode(model);
+  
+  if (isRootModel){
+    (void)fprintf(fp,"\n\nMODULE main --(");
+    if (Hrc_NodeReadNumFormalInputs(hnode) != 0){
+      fprintf(stderr, 
+	      "Warning: ignored %d input parameter(s) in the main module (root model)\n", 
+	      Hrc_NodeReadNumFormalInputs(hnode));
+    }
+    if (Hrc_NodeReadNumFormalOutputs(hnode) != 0){
+      fprintf(stderr, 
+	      "Warning: ignored %d output parameter(s) in the main module (root model)\n", 
+	      Hrc_NodeReadNumFormalOutputs(hnode));
+    }
+  } else {
+    (void)fprintf(fp,"\n\nMODULE %s (",Hrc_ModelReadName(model));
+  }
+
+  /* Input parameters */
+  if (Hrc_NodeReadNumFormalInputs(hnode) != 0){
+    Hrc_NodeForEachFormalInput(hnode,i,var){
+      Io_SmvPrintVar(fp, var);
+      if(i < Hrc_NodeReadNumFormalInputs(hnode)-1 ||
+	 Hrc_NodeReadNumFormalOutputs(hnode) > 0) {
+	(void)fprintf(fp,", ");
+      }
+    }
+  }
+  /* Output parameters */
+  if (Hrc_NodeReadNumFormalOutputs(hnode) != 0){
+    Hrc_NodeForEachFormalOutput(hnode,i,var){
+      Io_SmvPrintVar(fp, var);
+      if(i < Hrc_NodeReadNumFormalOutputs(hnode)-1) {
+	(void)fprintf(fp,", ");
+      }
+    }
+  }
+  (void)fprintf(fp,")\n");
+
+  /* Variables */
+  Hrc_NodeForEachVariable(hnode,gen,varName,var){
+    if (!isRootModel && (Var_VariableTestIsPI(var) || Var_VariableTestIsPO(var))) {
+      fprintf(fp,"-- PI or PO: ");
+    }
+
+    is_enum = Var_VariableTestIsEnumerative(var);
+    range = Var_VariableReadNumValues(var);
+    
+    (void)fprintf(fp,"VAR ");
+    Io_SmvPrintVar(fp, var);
+    if (is_enum == 1){
+      if (range == 2){
+	(void)fprintf(fp," : boolean;\n");
+      }
+      else {
+	(void)fprintf(fp," : 0..%d;\n",range-1);
+      }
+    }
+    else {
+      /* variable var is symbolic */
+      (void)fprintf(fp," : {");
+      for (i=0; i < range; i++){
+	(void)fprintf(fp,"%s",Var_VariableReadSymbolicValueFromIndex(var,i));
+	if(i < range-1)
+	  (void)fprintf(fp, ", ");
+      }
+      (void)fprintf(fp,"};\n");
+    }
+  }
+
+  /* Subcircuits */
+  Hrc_ModelForEachSubckt(model,gen,instanceName,subckt){
+    subcktModel = Hrc_SubcktReadModel(subckt);
+    subcktHnode = Hrc_ModelReadMasterNode(subcktModel);
+    subcktActualInputVars = Hrc_SubcktReadActualInputVars(subckt);
+    subcktActualOutputVars = Hrc_SubcktReadActualOutputVars(subckt);
+
+    /* Note: mv uses named parameters; we do not check that there are
+       enough parameters or that they occur in the correct order. This
+       doesn't seem to matter at the moment. */
+    (void)fprintf(fp,"VAR %s : %s(",
+       Hrc_SubcktReadInstanceName(subckt), Hrc_ModelReadName(subcktModel));
+    Hrc_NodeForEachFormalInput(subcktHnode,i,var){
+      actualVar = array_fetch(Var_Variable_t *,subcktActualInputVars,i);
+      Io_SmvPrintVar(fp, actualVar);
+      if(i < Hrc_NodeReadNumFormalInputs(subcktHnode)-1 ||
+	 Hrc_NodeReadNumFormalOutputs(subcktHnode) > 0) {
+	(void)fprintf(fp,", ");
+      }
+    }   
+    Hrc_NodeForEachFormalOutput(subcktHnode,i,var){
+      actualVar = array_fetch(Var_Variable_t *,subcktActualOutputVars,i);
+      Io_SmvPrintVar(fp, actualVar);
+      if(i < Hrc_NodeReadNumFormalOutputs(subcktHnode)-1) {
+	(void)fprintf(fp,", ");
+      }
+    }   
+    (void)fprintf(fp,");\n");
+  }
+
+  /* .latches */
+  (void)fprintf(fp,"\nASSIGN\n");
+  Hrc_NodeForEachLatch(hnode,gen,latchName,latch){
+    (void)fprintf(fp,"next(");
+    Io_SmvPrintVar(fp, Hrc_LatchReadOutput(latch));
+    (void)fprintf(fp,") := ");
+    Io_SmvPrintVar(fp, Hrc_LatchReadInput(latch));
+    (void)fprintf(fp,";\ninit(");
+    Io_SmvPrintVar(fp, Hrc_LatchReadOutput(latch));
+    (void)fprintf(fp,") := ");
+    Tbl_TableWriteSmvToFile(Hrc_LatchReadResetTable(latch),1,fp);
+    (void)fprintf(fp,"\n");
+  }
+
+  /* .names */
+  Hrc_NodeForEachNameTable(hnode,i,table){
+    Tbl_TableWriteSmvToFile(table,0,fp);
+  }
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns pointer to root node in the hierarchy.]
+
+  Description [The function simply accesses the rootNode field of the
+               hierarchy manager.]
+
+  SideEffects []
+
+  SeeAlso     [Hrc_ManagerReadCurrentNode()]
+
+******************************************************************************/
+Hrc_Node_t *
+Hrc_ManagerReadRootNode(
+  Hrc_Manager_t *manager)
+{
+  return manager->rootNode;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns pointer to the current node.]
+
+  Description [The function simply accesses the currentNode field of the
+               hierarchy manager.]
+
+  SideEffects []
+
+  SeeAlso     [Hrc_ManagerReadRootNode()]
+
+******************************************************************************/
+Hrc_Node_t *
+Hrc_ManagerReadCurrentNode(
+  Hrc_Manager_t *manager)
+{
+  return manager->currentNode;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the hash table of all the models.]
+
+  Description [A pointer to the table containing all the models currently
+               registered with the manager is returned. This table should
+               not be modified in any way.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+st_table *
+Hrc_ManagerReadModelTable(
+  Hrc_Manager_t *manager)
+{
+  return manager->modelTable;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns pointer to model corresponding to the given name.]
+
+  Description [The function looks up the name in the hash table of models.
+               If the name is found, the corresponding model is returned
+               otherwise NULL is returned.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Hrc_Model_t *
+Hrc_ManagerFindModelByName(
+  Hrc_Manager_t *manager,
+  char *modelName)
+{
+  Hrc_Model_t *model;
+    
+  if(st_lookup(manager->modelTable, modelName, &model)) {
+    return model;
+  }
+  else {
+    return NIL(Hrc_Model_t);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns pointer to the master node of a model.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Hrc_Node_t *
+Hrc_ModelReadMasterNode(
+  Hrc_Model_t *model)
+{
+  return model->masterNode;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the model name.]
+
+  Description [A pointer to model name is returned. Note that this string
+               should not be freed by the user.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+char *
+Hrc_ModelReadName(
+  Hrc_Model_t *model)
+{
+  return model->modelName;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the hash table of sub-circuits of the model.]
+
+  Description [A pointer to the table containing all the sub-circuits of a 
+               model is returned. Note that this table should not be modified
+               in any way.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+st_table *
+Hrc_ModelReadSubcktTable(
+  Hrc_Model_t *model)
+{
+  return model->subcktTable;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns pointer to model of the sub-circuit.]
+
+  Description [A pointer to the model whose instantiation created this
+               sub-circuit is returned.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Hrc_Model_t *
+Hrc_SubcktReadModel(
+  Hrc_Subckt_t *subckt)
+{
+  return subckt->model;
+}
+    
+/**Function********************************************************************
+
+  Synopsis    [Returns pointer to instance name of a sub-circuit.]
+
+  Description [A pointer to instance name of a sub-circuit is returned. Note
+               that this string should not be freed by the user.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+char *
+Hrc_SubcktReadInstanceName(
+  Hrc_Subckt_t *subckt)
+{
+  return subckt->instanceName;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns pointer to the array of actual input variables used for
+               instantiating the model.]
+
+  Description [A pointer to the array of actual input variables is returned.
+               Note that the array should not be modified in any way.]
+
+  SideEffects []
+
+  SeeAlso     [Hrc_SubcktReadActualOutputVars()]
+
+******************************************************************************/
+array_t *
+Hrc_SubcktReadActualInputVars(
+  Hrc_Subckt_t *subckt)
+{
+  return subckt->actualInputVars;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns pointer to the array of actual output variables used for
+               instantiating the model.]
+
+  Description [A pointer to the array of actual output variables is returned.
+               Note that the array should not be modified in any way.]
+
+  SideEffects []
+
+  SeeAlso     [Hrc_SubcktReadActualInputVars()]
+
+******************************************************************************/
+array_t *
+Hrc_SubcktReadActualOutputVars(
+  Hrc_Subckt_t *subckt)
+{    
+  return subckt->actualOutputVars;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the manager of a node.]
+
+  Description [The function returns a pointer to the manager of a node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Hrc_Manager_t *
+Hrc_NodeReadManager(
+  Hrc_Node_t *node)
+{
+  return node->manager;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the model name of a node.]
+
+  Description [A pointer to the name of the model whose instantiation
+               created this node is returned. Note that the string should not
+               be freed by the user.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+char *
+Hrc_NodeReadModelName(
+  Hrc_Node_t *node)
+{
+  return node->modelName;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the instance name of a node.]
+
+  Description [A pointer to the name used when instantiating a node is
+               returned. Note that the string should not be freed by
+               the user.]   
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+char *
+Hrc_NodeReadInstanceName(
+  Hrc_Node_t *node)
+{
+  return node->instanceName;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns pointer to the parent node of a node.]
+
+  Description [A pointer to the parent node of a node is returned.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Hrc_Node_t *
+Hrc_NodeReadParentNode(
+  Hrc_Node_t *node)
+{
+  return node->parentNode;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of formal inputs of a node.]
+
+  Description [The number of formal inputs of a node is returned.]
+
+  SideEffects []
+
+  SeeAlso     [Hrc_NodeReadNumFormalOutputs()]
+
+******************************************************************************/
+int
+Hrc_NodeReadNumFormalInputs(
+  Hrc_Node_t *node)
+{
+  return array_n(node->formalInputs);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of formal outputs of a node.]
+
+  Description [The number of formal outputs of a node is returned.]
+
+  SideEffects []
+
+  SeeAlso     [Hrc_NodeReadNumFormalInputs()]
+
+******************************************************************************/
+int
+Hrc_NodeReadNumFormalOutputs(
+  Hrc_Node_t *node)
+{
+  return array_n(node->formalOutputs);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [This function returns the number of formal variables in a node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Hrc_NodeReadNumVariables(
+  Hrc_Node_t *node)
+{
+  return st_count(node->varTable);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [This function returns the number of tables in the node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Hrc_NodeReadNumTables(
+  Hrc_Node_t *node)
+{
+  return array_n(node->nameTables);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [This function returns the number of latches in a node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Hrc_NodeReadNumLatches(
+  Hrc_Node_t *node)
+{
+  return st_count(node->latchTable);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [This function returns the number of children of a node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Hrc_NodeReadNumChildren(
+  Hrc_Node_t *node)
+{
+  return st_count(node->childTable);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the array of formal inputs of a node.]
+
+  Description [Note that this function has been exported only to provide
+               the exported macro to iterate over the formal inputs of a node.
+               It is not supposed to be used for any other purpose.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+array_t *
+Hrc_NodeReadFormalInputs(
+  Hrc_Node_t *node)
+{
+  return node->formalInputs;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the array of formal outputs of a node.]
+
+  Description [Note that this function has been exported only to provide
+               the exported macro to iterate over the formal outputs of a
+               node. It is not supposed to be used for any other purpose.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+array_t *
+Hrc_NodeReadFormalOutputs(
+  Hrc_Node_t *node)
+{
+  return node->formalOutputs;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the array of actual inputs of a node.]
+
+  Description [Note that this function has been exported only to provide
+               the exported macro to iterate over the actual inputs of a node.
+               It is not supposed to be used for any other purpose.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+array_t *
+Hrc_NodeReadActualInputs(
+  Hrc_Node_t *node)
+{
+  return node->actualInputs;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the array of actual outputs of a node.]
+
+  Description [Note that this function has been exported only to provide
+               the exported macro to iterate over the actual outputs of a
+               node. It is not supposed to be used for any other purpose.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+array_t *
+Hrc_NodeReadActualOutputs(
+  Hrc_Node_t *node)
+{
+  return node->actualOutputs;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the array of name tables of a node.]
+
+  Description [Note that this function has been exported only to provide
+               the exported macro to iterate over the name tables in a
+               node. It is not supposed to be used for any other purpose.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+array_t *
+Hrc_NodeReadNameTables(
+  Hrc_Node_t *node)
+{
+  return node->nameTables;
+}
+    
+/**Function********************************************************************
+
+  Synopsis    [Returns the hash table of children of a node.]
+
+  Description [Note that this function has been exported only to provide
+               the exported macro to iterate over the children of a node.
+               It is not supposed to be used for any other purpose.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+st_table *
+Hrc_NodeReadChildTable(
+  Hrc_Node_t *node)
+{
+  return node->childTable;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the hash table of latches of a node.]
+
+  Description [Note that this function has been exported only to provide
+               the exported macro to iterate over the latches in a node.
+               It is not supposed to be used for any other purpose.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+st_table *
+Hrc_NodeReadLatchTable(
+  Hrc_Node_t *node)
+{
+  return node->latchTable;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the hash table of variables of a node.]
+
+  Description [Note that this function has been exported only to provide
+               the exported macro to iterate over the variables in a node.
+               It is not supposed to be used for any other purpose.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+st_table *
+Hrc_NodeReadVariableTable(
+  Hrc_Node_t *node)
+{
+  return node->varTable;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns pointer to the undef field of a node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void *
+Hrc_NodeReadUndef(
+  Hrc_Node_t *node)
+{
+  return node->undef;
+}
+/**Function********************************************************************
+
+  Synopsis    [Returns pointer to a latch corresponding to a name.]
+
+  Description [The name is looked up in the hash table of latches. If it is
+               found, a pointer to the corresponding latch is returned
+               otherwise NULL is returned.]
+
+  SideEffects []
+
+  SeeAlso     [Hrc_NodeFindVariableByName(), Hrc_NodeFindChildByName()]
+
+******************************************************************************/
+Hrc_Latch_t *
+Hrc_NodeFindLatchByName(
+  Hrc_Node_t *node,
+  char *latchName)
+{
+  Hrc_Latch_t *latch;
+    
+  if(st_lookup(node->latchTable, latchName, &latch)) {
+    return latch;
+  }
+  else {
+    return NIL(Hrc_Latch_t);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns pointer to a variable corresponding to a name.]
+
+  Description [The name is looked up in the hash table of variables. If it is
+               found, a pointer to the corresponding variable is returned
+               otherwise NULL is returned.]
+
+  SideEffects []
+
+  SeeAlso     [Hrc_NodeFindLatchByName(), Hrc_NodeFindChildByName()]
+
+******************************************************************************/
+Var_Variable_t *
+Hrc_NodeFindVariableByName(
+  Hrc_Node_t *node,
+  char *varName)
+{
+  Var_Variable_t *var;
+  
+  if(st_lookup(node->varTable, varName, &var)) {
+    return var;
+  }
+  else {
+    return NIL(Var_Variable_t);
+  }    
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns pointer to child node corresponding to an instance
+               name.]
+
+  Description [The name is looked up in the hash table of children. If it is
+               found, a pointer to the corresponding child is returned
+               otherwise NULL is returned.]
+
+  SideEffects []
+
+  SeeAlso     [Hrc_NodeFindLatchByName(), Hrc_NodeFindVariableByName()]
+
+******************************************************************************/
+Hrc_Node_t *
+Hrc_NodeFindChildByName(
+    Hrc_Node_t *node,
+    char *instanceName)
+{
+  Hrc_Node_t *childNode;
+
+  if(st_lookup(node->childTable, instanceName, &childNode)) {
+    return childNode;
+  }
+  else {
+    return NIL(Hrc_Node_t);
+  }    
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns pointer to input variable of a latch.]
+
+  SideEffects []
+
+  SeeAlso     [Hrc_LatchReadOutput()]
+
+******************************************************************************/
+Var_Variable_t *
+Hrc_LatchReadInput(
+  Hrc_Latch_t *latch)
+{
+  return latch->latchInput;
+}
+    
+/**Function********************************************************************
+
+  Synopsis    [Returns pointer to output variable of a latch.]
+
+  SideEffects []
+
+  SeeAlso     [Hrc_LatchReadInput()]
+
+******************************************************************************/
+Var_Variable_t *
+Hrc_LatchReadOutput(
+  Hrc_Latch_t *latch)
+{
+  return latch->latchOutput;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns pointer to the reset table of a latch.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Tbl_Table_t *
+Hrc_LatchReadResetTable(
+    Hrc_Latch_t *latch)
+{
+  return latch->resetTable;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns pointer to the undef field in a latch.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void *
+Hrc_LatchReadUndef(
+  Hrc_Latch_t *latch)
+{
+  return latch->undef;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the rootNode field of a manager.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Hrc_ManagerSetRootNode(
+  Hrc_Manager_t *manager,
+  Hrc_Node_t *node)
+{
+  manager->rootNode = node;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the currentNode field of a manager.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Hrc_ManagerSetCurrentNode(
+  Hrc_Manager_t *manager,
+  Hrc_Node_t *currentNode)
+{
+  manager->currentNode = currentNode;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Adds a formal input variable to a node.]
+
+  Description [The formal input variable is added to the array of formal
+               inputs and to the hash table of variables and TRUE is returned.
+               If the variable is a primary input already, nothing is done
+               and FALSE is returned.]
+
+  SideEffects []
+
+  SeeAlso     [Hrc_NodeAddFormalOutput()]
+
+******************************************************************************/
+boolean
+Hrc_NodeAddFormalInput(
+  Hrc_Node_t *node,
+  Var_Variable_t *var)
+{
+  char *name = Var_VariableReadName(var);
+
+  if(!Var_VariableTestIsPI(var)) {
+    array_insert_last(Var_Variable_t *, node->formalInputs, var);
+    st_insert(node->varTable, name, (char *) var);
+    (void)Var_VariableSetPI(var);
+    return TRUE;
+  }
+  else {
+    return FALSE;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Adds a formal output variable to a node.]
+
+  Description [The formal output variable is added to the array of formal
+               outputs and to the hash table of variables and TRUE is
+               returned. If the variable is a primary output already,
+               nothing is done and FALSE is returned.]
+
+  SideEffects []
+
+  SeeAlso     [Hrc_NodeAddFormalInput()]
+
+******************************************************************************/
+boolean
+Hrc_NodeAddFormalOutput(
+  Hrc_Node_t *node,
+  Var_Variable_t *var)
+{
+  char *name = Var_VariableReadName(var);
+
+  if(!Var_VariableTestIsPO(var)) {
+    array_insert_last(Var_Variable_t *, node->formalOutputs, var);
+    st_insert(node->varTable, name, (char *) var);
+    (void)Var_VariableSetPO(var);
+    return TRUE;
+  }
+  else {
+    return FALSE;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Adds a name table to a node.]
+
+  SideEffects []
+
+  SeeAlso     [Hrc_NodeAddFormalInput(), Hrc_NodeAddFormalOutput()]
+
+******************************************************************************/
+void
+Hrc_NodeAddNameTable(
+  Hrc_Node_t *node,
+  Tbl_Table_t *nameTable)
+{
+  array_insert_last(Tbl_Table_t *, node->nameTables, nameTable);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the undef field of a node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Hrc_NodeSetUndef(
+  Hrc_Node_t *node,
+  void *value)
+{
+  node->undef = value;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the reset table of a latch.]
+
+  Description [If the resetTable field of the latch is NULL, it is set to
+               table and TRUE is returned otherwise FALSE is returned. ]
+
+  SideEffects []
+
+  SeeAlso     []
+  
+******************************************************************************/
+
+boolean
+Hrc_LatchSetResetTable(
+  Hrc_Latch_t *latch,
+  Tbl_Table_t *table)
+{
+  if (latch->resetTable != NIL(Tbl_Table_t)){
+    return FALSE;
+  }
+  latch->resetTable = table;
+  return TRUE;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Set the undef field of a latch.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Hrc_LatchSetUndef(
+  Hrc_Latch_t *latch,
+  void *value)
+{
+  latch->undef = value;
+}
+    
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/hrc/hrcInt.h
===================================================================
--- vis_dev/vis-2.3/src/hrc/hrcInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/hrc/hrcInt.h	(revision 14)
@@ -0,0 +1,242 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [hrcInt.h]
+
+  PackageName [hrc]
+
+  Synopsis    [The internal declarations needed for the hierarchy]
+
+  Description [This file contains the definitions of important structures
+               needed for defining the hierarchy.]
+
+  SeeAlso     [hrc.h]
+
+  Author      [Yuji Kukimoto, Shaz Qadeer]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: hrcInt.h,v 1.2 2001/03/12 22:28:29 jinh Exp $]
+
+******************************************************************************/
+
+#ifndef _HRCINT
+#define _HRCINT
+ 
+#include "hrc.h"
+#include "cmd.h"
+#include <string.h>
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**Enum************************************************************************
+
+  Synopsis    [Types of components present in a circuit.]
+
+******************************************************************************/
+typedef enum {
+  HrcLatch_c,             /* component is a latch */
+  HrcSubckt_c,            /* component is a subckt */
+  HrcUndef_c              /* component is an arbitrary gate */
+} HrcCktComponentType;
+
+/**Struct**********************************************************************
+
+  Synopsis    [Structure to store uninterpreted application info.]
+
+  SeeAlso     [Hrc_NodeAddApplInfo()]
+
+******************************************************************************/
+typedef struct ApplInfoStruct {
+  Hrc_ApplInfoFreeFn  freeFn;  /* application function to free data */
+  Hrc_ApplInfoChangeFn changeFn; /* application function to change data */
+  void               *data;    /* application data */
+} ApplInfo_t;
+
+/**Struct**********************************************************************
+
+  Synopsis    [Definition of a hierarchy manager]
+
+  Description [rootNode is a pointer to the root node of the hierarchy tree.
+               It corresponds to the instantiation of the root model in a
+               blifmv file. currentNode points to the current position in
+               the hierarchy. This pointer is initialized to root node. Its
+               value changes whenever the cd command for changing the
+               hierarchical level is used. modelTable contains all the
+               defined models.]
+
+  SeeAlso     []
+
+******************************************************************************/
+struct HrcManagerStruct {
+  Hrc_Node_t *rootNode;   /* pointer to root Hrc_Node_t */
+  Hrc_Node_t *currentNode;/* pointer to current Hrc_Node_t */
+  st_table *modelTable;   /* hash table from model name(char *)
+                           * to model (Hrc_Model_t *) */
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [Definition of a model]
+
+  Description [hrcNode is a pointer to a the master node of the model. The
+               master node contains information about all the elements in
+               the model. subcktTable contains all information about the
+               various instantiations of other models from within the model.]
+
+  SeeAlso     [HrcNodeStruct, HrcSubcktStruct]
+
+******************************************************************************/
+struct HrcModelStruct {
+  char *modelName;           /* unique model name */
+  Hrc_Node_t *masterNode;       /* pointer to the master hrcNode of a model */
+  st_table *subcktTable;     /* hash table from instance name (char *) of
+                              * model being called to subckt (Hrc_Subckt_t *)*/
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [Definition of a sub-circuit]
+
+  Description [A subckt is created whenever a model instantiates another. The
+               two arrays actualInputVars and actualOutputVars map contain
+               the variables used to refer to the I/O pins of the instantiated
+               model.]
+
+  SeeAlso     [HrcModelStruct]
+
+******************************************************************************/
+struct HrcSubcktStruct {
+  Hrc_Model_t *model;       /* the subckt resulted from an instantiation of
+                             * this model */
+  char *instanceName;       /* name by which the instantiation took place */
+  array_t *actualInputVars; /* array of actual input variable pointers 
+                             * Var_Variable_t *'s */
+  array_t *actualOutputVars;/* array of actual output variable pointers
+                             * Var_Variable_t *'s */
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [Definition of a node in the hierarchy tree]
+
+  Description [This structure forms the basic unit of the hierarchy tree.
+               Note that the elements of arrays formalInputs and actualInputs,
+               and formalOutputs and actualOutputs are in one to one
+               correspondence.]
+
+  SeeAlso     [HrcModelStruct]
+
+******************************************************************************/
+struct HrcNodeStruct {
+  Hrc_Manager_t *manager;    /* manager to which this node belongs */
+  char *modelName;           /* corresponding model name */
+  char *instanceName;        /* instance name */
+  Hrc_Node_t *parentNode;    /* pointer to the unique parent node */
+  array_t *formalInputs;     /* formal input symbolic variables 
+                              * (Var_Variable_t *) */
+  array_t *formalOutputs;    /* formal output symbolic variables 
+                              * (Var_Variable_t *) */
+  array_t *actualInputs;     /* actual connections (Var_Variable_t *) with 
+                              * the inputs of parent node */
+  array_t *actualOutputs;    /* actual connections (Var_Variable_t *) with 
+                              * the outputs of parent node */  
+  array_t *nameTables;       /* array of Tbl_Table_t *'s corresponding
+                              * to .names in the blifmv file */
+  st_table *childTable;      /* hash table from child instance name (char *) 
+                              * to child (Hrc_Node_t *) */
+  st_table *latchTable;      /* hash table from name of output of latch
+                              * (char *)  to latch (Hrc_Latch_t *) */
+  st_table *varTable;        /* hash table from symbolic variable name
+                              * (char *) to (Var_Variable_t *) */
+  st_table *applInfoTable;   /* hash table for application specific
+                                information from (char *) to (ApplInfo_t *) */ 
+  void *undef;               /* for programmer's use */
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [Definition of a latch]
+
+  Description []
+
+  SeeAlso     []
+
+******************************************************************************/
+struct HrcLatchStruct {
+  Var_Variable_t *latchInput;  /* input of the latch (next state) */
+  Var_Variable_t *latchOutput; /* output of the latch (present state) */
+  Tbl_Table_t *resetTable;     /* pointer to reset table for this latch */
+  void *undef;                 /* for programmer's use */
+};
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void HrcNodeFreeRecursively(Hrc_Node_t *node);
+EXTERN void HrcNodeFreeInternalMemory(Hrc_Node_t *node);
+EXTERN Hrc_Node_t * HrcNodeDeleteChild(Hrc_Node_t *node, char *childName);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _HRCINT */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/hrc/hrcMemUtil.c
===================================================================
--- vis_dev/vis-2.3/src/hrc/hrcMemUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/hrc/hrcMemUtil.c	(revision 14)
@@ -0,0 +1,606 @@
+/**CFile***********************************************************************
+
+  FileName    [hrcMemUtil.c]
+
+  PackageName [hrc]
+
+  Synopsis    [This file deals with the memory utilities for the hrc package.]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [Shaz Qadeer]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "hrcInt.h"
+
+static char rcsid[] UNUSED = "$Id: hrcMemUtil.c,v 1.3 2005/04/16 04:23:47 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void ModelFree(Hrc_Model_t *model);
+static void SubcktFree(Hrc_Subckt_t *subckt);
+static void LatchFree(Hrc_Latch_t *latch);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Allocates a hierarchy manager.]
+
+  Description [The function allocates memory for a hierarchy manager. It
+               initializes the model table of the manager and sets rootNode
+               and currentNode to NULL.]
+
+  SideEffects []
+
+  SeeAlso     []
+******************************************************************************/
+Hrc_Manager_t *
+Hrc_ManagerAlloc(
+  void)
+{
+  Hrc_Manager_t *manager = ALLOC(Hrc_Manager_t, 1);
+  
+  manager->rootNode = NIL(Hrc_Node_t);
+  manager->currentNode = NIL(Hrc_Node_t);
+  manager->modelTable = st_init_table(strcmp, st_strhash);
+  return manager;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates a model with a given name.]
+
+  Description [The function checks if a model by the name modelName already
+               exists. If it does NULL is returned otherwise memory for a
+               new model is allocated. A copy of modelName is made and stored
+               in the model. Therefore, the string modelName should be freed
+               by the user. The subcircuit table and the master node of the
+               model are initialized. The model is registered with the
+               manager.]
+
+  SideEffects []
+
+  SeeAlso     []
+******************************************************************************/
+Hrc_Model_t *
+Hrc_ModelAlloc(
+  Hrc_Manager_t *manager,
+  char *modelName)
+{
+  Hrc_Model_t *model;
+  
+  if(!st_is_member(manager->modelTable,modelName)){
+    model = ALLOC(Hrc_Model_t, 1);
+    model->modelName = util_strsav(modelName);
+    st_insert(manager->modelTable, model->modelName, (char *) model);
+    model->subcktTable = st_init_table(strcmp, st_strhash);
+    model->masterNode = Hrc_NodeAlloc(manager, model->modelName,
+                                      NIL(char), NIL(Hrc_Node_t));
+    return model;
+  }
+  else {
+    return NIL(Hrc_Model_t);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates a node for a particular instantiation of a model.]
+
+  Description [The function allocates memory for a node and initializes all
+               the arrays and hash tables inside the node. Note that the user
+               must free the strings modelName and instanceName because
+               copies of these strings are made and stored. The undef field
+               is set to NULL.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Hrc_Node_t *
+Hrc_NodeAlloc(
+  Hrc_Manager_t *manager,
+  char *modelName,
+  char *instanceName,
+  Hrc_Node_t *parentNode)
+{
+  Hrc_Node_t *node = ALLOC(Hrc_Node_t, 1);
+  /* The manager field is needed only for allocating the parent node. For
+     allocating any other node in the hierarchy, the manager can be obtained
+     from the parent node. */
+  node->manager = manager;
+  node->modelName = util_strsav(modelName);
+  node->instanceName = util_strsav(instanceName);
+  node->parentNode = parentNode;
+  node->formalInputs = array_alloc(Var_Variable_t *, 0);
+  node->formalOutputs = array_alloc(Var_Variable_t *, 0);
+  /* The arrays actualInputs and actualOutputs do not need to be allocated
+     because 1) they are never needed for the master node of a model, and
+     2) they are written over whenever a new node is added to the hierarchy
+     by using Hrc_NodeAddChild() */
+  node->actualInputs = NIL(array_t);
+  node->actualOutputs = NIL(array_t);
+  node->nameTables = array_alloc(Tbl_Table_t *, 0);
+  node->childTable = st_init_table(strcmp, st_strhash);
+  node->latchTable = st_init_table(strcmp, st_strhash);
+  node->varTable = st_init_table(strcmp, st_strhash);
+  node->applInfoTable = st_init_table(strcmp, st_strhash);
+  node->undef = NIL(void);
+  return node;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Duplicates a node with a new instance name.]
+
+  Description [The function duplicates a node. The manager, parentNode,
+               and undef fields are simply copied into the duplicated
+               node. All the other fields viz. hash tables and arrays are
+               allocated anew. All the variables and tables are duplicated.
+               Note that actualInputs and actualOutputs are not copied. They
+               are initialized to NULL. The latches are also duplicated (the
+               reset table is duplicated and the undef field is copied). The
+               applInfoTable is duplicated along with its keys. The
+               user should free instanceName because it is copied.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Hrc_Node_t *
+Hrc_NodeDup(
+  Hrc_Node_t *node,
+  char *instanceName)
+{
+  Hrc_Node_t *dupNode = ALLOC(Hrc_Node_t, 1);
+  st_generator *gen;
+  int i, index;
+  Var_Variable_t *var, *dupVar;
+  Tbl_Table_t *table, *dupTable;
+  Hrc_Latch_t *latch, *dupLatch;
+  st_table *varToDupVar;
+  char *name, *dupName;
+  char *key, *dupKey;
+  ApplInfo_t *applInfo;
+  
+  dupNode->manager = node->manager;
+  dupNode->modelName = util_strsav(node->modelName);
+  dupNode->instanceName = util_strsav(instanceName);
+  dupNode->parentNode = node->parentNode;
+  dupNode->formalInputs = array_alloc(Var_Variable_t *, 0);
+  dupNode->formalOutputs = array_alloc(Var_Variable_t *, 0);
+  dupNode->actualInputs = NIL(array_t);
+  dupNode->actualOutputs = NIL(array_t);
+  /*
+  dupNode->actualInputs = array_alloc(Var_Variable_t *, 0);
+  Hrc_NodeForEachActualInput(node, i, var) {
+    dupVar = Var_VariableDup(var, dupNode);
+    array_insert_last(Var_Variable_t *, dupNode->actualInputs, dupVar);
+  }
+  dupNode->actualOutputs = array_alloc(Var_Variable_t *, 0);
+  Hrc_NodeForEachActualOutput(node, i, var) {
+    dupVar = Var_VariableDup(var, dupNode);
+    array_insert_last(Var_Variable_t *, dupNode->actualOutputs, dupVar);
+  }
+  */
+  dupNode->varTable = st_init_table(strcmp, st_strhash);
+  varToDupVar = st_init_table(st_ptrcmp, st_ptrhash);
+  Hrc_NodeForEachVariable(node, gen, name, var) {
+    dupVar = Var_VariableDup(var, dupNode);
+    dupName = Var_VariableReadName(dupVar);
+    st_insert(dupNode->varTable, dupName, dupVar);
+    st_insert(varToDupVar, var, dupVar);
+  }
+  Hrc_NodeForEachFormalInput(node, i, var) {
+    st_lookup(varToDupVar, var, &dupVar);
+    array_insert_last(Var_Variable_t *, dupNode->formalInputs, dupVar);
+  }
+  Hrc_NodeForEachFormalOutput(node, i, var) {
+    st_lookup(varToDupVar, var, &dupVar);
+    array_insert_last(Var_Variable_t *, dupNode->formalOutputs, dupVar);
+  }
+  dupNode->nameTables = array_alloc(Tbl_Table_t *, 0);
+  Hrc_NodeForEachNameTable(node, i, table) {
+    dupTable = Tbl_TableSoftDup(table);
+    /*dupTable = Tbl_TableHardDup(table);*/
+    Tbl_TableForEachInputVar(dupTable, index, var) {
+      st_lookup(varToDupVar, var, &dupVar);
+      Tbl_TableSubstituteVar(dupTable, var, dupVar);
+    }
+    Tbl_TableForEachOutputVar(dupTable, index, var) {
+      st_lookup(varToDupVar, var, &dupVar);
+      Tbl_TableSubstituteVar(dupTable, var, dupVar);
+    }
+    array_insert_last(Tbl_Table_t *, dupNode->nameTables, dupTable);
+  }
+  dupNode->latchTable = st_init_table(strcmp, st_strhash);
+  Hrc_NodeForEachLatch(node, gen, name, latch) {
+    dupLatch = ALLOC(Hrc_Latch_t, 1);
+    st_lookup(varToDupVar, latch->latchInput, &(dupLatch->latchInput));
+    st_lookup(varToDupVar, latch->latchOutput, &(dupLatch->latchOutput));
+    dupLatch->resetTable = Tbl_TableSoftDup(latch->resetTable);
+    /*dupLatch->resetTable = Tbl_TableHardDup(latch->resetTable);*/
+    Tbl_TableForEachInputVar(dupLatch->resetTable, index, var) {
+      st_lookup(varToDupVar, var, &dupVar);
+      Tbl_TableSubstituteVar(dupLatch->resetTable, var, dupVar);
+    }
+    Tbl_TableForEachOutputVar(dupLatch->resetTable, index, var) {
+      st_lookup(varToDupVar, var, &dupVar);
+      Tbl_TableSubstituteVar(dupLatch->resetTable, var, dupVar);
+    }
+    dupLatch->undef = latch->undef;
+    st_insert(dupNode->latchTable, Var_VariableReadName(dupLatch->latchOutput), dupLatch);
+  }
+  dupNode->childTable = st_copy(node->childTable);
+  dupNode->applInfoTable = st_init_table(strcmp, st_strhash);
+  st_foreach_item(node->applInfoTable, gen, &key, &applInfo) {
+    dupKey = util_strsav(key);
+    st_insert(dupNode->applInfoTable, dupKey, applInfo);
+  }
+  dupNode->undef = node->undef;
+  st_free_table(varToDupVar);
+  return dupNode;
+}
+
+    
+/**Function********************************************************************
+
+  Synopsis    [Creates a latch and registers it with a model.]
+
+  Description [The function looks up the latch in the hash table of latches
+               in the master node of model. If a latch with the same output
+               variable name is not present in the table memory for a new
+               latch is allocated. The resetTable and undef fields of the
+               latch are initialized to NULL and the latch is returned.
+               Otherwise, NULL is returned.]
+
+  SideEffects []
+
+  SeeAlso     []
+******************************************************************************/
+Hrc_Latch_t *
+Hrc_LatchCreate(
+  Hrc_Model_t *model,
+  Var_Variable_t *latchInput,
+  Var_Variable_t *latchOutput)
+{
+  Hrc_Latch_t *latch;
+  char *outputName = Var_VariableReadName(latchOutput);
+  
+  if(!st_is_member(model->masterNode->latchTable, outputName)) {
+    latch = ALLOC(Hrc_Latch_t, 1);
+    latch->latchInput = latchInput;
+    latch->latchOutput = latchOutput;
+    latch->resetTable = NIL(Tbl_Table_t);
+    latch->undef = NIL(void);
+    st_insert(model->masterNode->latchTable, outputName, (char *) latch);
+    return latch;
+  }
+  else {
+    return NIL(Hrc_Latch_t);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a hierarchy manager.]
+
+  Description [The function frees every node in the hierarchy recursively
+               starting from the root node if it is not NULL. All models in
+               the model table are freed and model table itself is freed.]
+
+  SideEffects []
+
+  SeeAlso     []
+******************************************************************************/
+void
+Hrc_ManagerFree(
+  Hrc_Manager_t *manager)
+{
+  st_generator *gen;
+  char *name;
+  Hrc_Model_t *model;
+  
+  if(manager->rootNode != NIL(Hrc_Node_t)) {
+    HrcNodeFreeRecursively(manager->rootNode);
+  }
+  Hrc_ManagerForEachModel(manager, gen, name, model){
+    ModelFree(model);
+  }
+  st_free_table(manager->modelTable);
+  FREE(manager);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Deletes a model from the manager.]
+
+  Description [The function looks up the entry for model in the hash table
+               of models in the manager. If the entry is not found, FALSE is
+               returned otherwise it is removed, model is freed, and TRUE is
+               returned. Note that the corresponding master node is freed too.]
+
+  SideEffects []
+
+  SeeAlso     [ModelFree()]
+******************************************************************************/
+boolean
+Hrc_ModelDelete(
+  Hrc_Manager_t *manager,
+  char *modelName)
+{
+  Hrc_Model_t *model;
+  
+  if(st_delete(manager->modelTable, &(modelName), &model)) {
+    ModelFree(model);
+    return TRUE;
+  }
+  else {
+    return FALSE;
+  }
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Frees a tree hanging from a node.]
+
+  Description [The subtree hanging down from node is freed recursively node
+               by node. In each node, all tables, latches and formal variables
+               are freed and the freeFn is called for all the entries in
+               applInfoTable.
+               The function also frees the memory allocated to the internal
+               fields of all the nodes it frees.]
+
+  SideEffects [The rootNode and currentNode fields in the hierarchy manager
+               are set to NULL if either of these are freed.]
+
+  SeeAlso     [HrcNodeFreeInternalMemory(), Hrc_TreeReplace()]
+
+******************************************************************************/
+void
+HrcNodeFreeRecursively(
+  Hrc_Node_t *node)
+{
+  st_generator *gen;
+  char *name;
+  Hrc_Node_t *childNode;
+  
+  if(node == node->manager->rootNode) {
+    node->manager->rootNode = NIL(Hrc_Node_t);
+  }
+  if(node == node->manager->currentNode) {
+    node->manager->currentNode = NIL(Hrc_Node_t);
+  }
+  HrcNodeFreeInternalMemory(node);
+  Hrc_NodeForEachChild(node, gen, name, childNode) {
+    HrcNodeFreeRecursively(childNode);
+  }
+  st_free_table(node->childTable);
+  FREE(node);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the memory allocated to the internal fields of a node.] 
+  
+  Description [The function frees  all tables, latches and formal variables
+               in the node. The keys in applInfoTable and the applInfoTable
+               itself are also freed.]
+
+  SideEffects []
+
+  SeeAlso     [HrcNodeFreeRecursively()]
+
+******************************************************************************/
+void
+HrcNodeFreeInternalMemory(
+  Hrc_Node_t *node)
+{
+  char *name;
+  st_generator *gen;
+  int i;
+  Tbl_Table_t *table;
+  Hrc_Latch_t *latch;
+  Var_Variable_t *var;
+  ApplInfo_t *applInfo;
+  char *key;
+  
+  FREE(node->modelName);
+  FREE(node->instanceName);
+  array_free(node->formalInputs);
+  array_free(node->formalOutputs);
+  /* In a master node of a model, actualInputs and actualOutputs are NULL.
+     That is why the following two checks are needed. */
+  if(node->actualInputs != NIL(array_t)) {
+    array_free(node->actualInputs);
+  }
+  if(node->actualOutputs != NIL(array_t)) {
+    array_free(node->actualOutputs);
+  }
+  Hrc_NodeForEachNameTable(node, i, table) {
+    Tbl_TableFree(table);
+  }
+  array_free(node->nameTables);
+  Hrc_NodeForEachLatch(node, gen, name, latch) {
+    LatchFree(latch);
+  }
+  st_free_table(node->latchTable);
+  Hrc_NodeForEachVariable(node, gen, name, var) {
+    Var_VariableFree(var);
+  }
+  st_free_table(node->varTable);
+  if(node->applInfoTable) {
+    st_foreach_item(node->applInfoTable, gen, &key, &applInfo) {
+      FREE(key);
+      (*applInfo->freeFn)(applInfo->data);
+      FREE(applInfo);
+    }
+    st_free_table(node->applInfoTable);
+  }
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Frees the memory allocated to a model and its master node.]
+
+  Description [The function frees model. It also frees the master node 
+               and all the sub-circuits of the model.] 
+               
+
+  SideEffects []
+
+  SeeAlso     [Hrc_ModelDelete(), Hrc_ManagerFree()]
+
+******************************************************************************/
+static void
+ModelFree(
+  Hrc_Model_t *model)
+{
+  st_generator *gen;
+  char *name;
+  Hrc_Subckt_t *subckt;
+  
+  FREE(model->modelName);
+  HrcNodeFreeInternalMemory(model->masterNode);
+  st_free_table(model->masterNode->childTable);
+  FREE(model->masterNode);
+  st_foreach_item(model->subcktTable, gen, &name, &subckt) {
+    SubcktFree(subckt);
+  }
+  st_free_table(model->subcktTable);
+  FREE(model);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a sub-circuit.]
+
+  Description [This function frees a sub-circuit. Note that all the variables
+              inside a sub-circuit are freed.]
+
+  SideEffects []
+
+  SeeAlso     [ModelFree()]
+
+******************************************************************************/
+static void
+SubcktFree(
+  Hrc_Subckt_t *subckt)
+{
+  FREE(subckt->instanceName);
+  array_free(subckt->actualInputVars);
+  array_free(subckt->actualOutputVars);
+  FREE(subckt);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a latch.]
+
+  Description [The function frees the latch. If resetTable is not NULL, it
+               is freed. Note that the input and output variables of latch
+               are not freed.]
+
+  SideEffects []
+
+  SeeAlso     [HrcNodeFreeInternalMemory()]
+******************************************************************************/
+static void
+LatchFree(
+  Hrc_Latch_t *latch)
+{
+  if(latch->resetTable != NIL(Tbl_Table_t)){    
+    Tbl_TableFree(latch->resetTable);
+  }
+  FREE(latch);
+}        
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/hrc/hrcMisc.c
===================================================================
--- vis_dev/vis-2.3/src/hrc/hrcMisc.c	(revision 14)
+++ vis_dev/vis-2.3/src/hrc/hrcMisc.c	(revision 14)
@@ -0,0 +1,904 @@
+/**CFile***********************************************************************
+
+  FileName    [hrcMisc.c]
+
+  PackageName [hrc]
+
+  Synopsis    [This file provides some miscellaneous functions.]
+
+  SeeAlso     []
+
+  Author      [Shaz Qadeer]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "hrcInt.h"
+
+static char rcsid[] UNUSED = "$Id: hrcMisc.c,v 1.4 2005/04/27 00:10:58 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void NodeObtainComponentModels(Hrc_Node_t *node, st_table *models);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Returns pointer to the node corresponding to a path name.]
+
+  Description [The function returns a pointer to the node corresponding to
+               a path name. If pathFlag is TRUE it is assumed that the name
+               begins from the current node otherwise the name is assumed to 
+               begin from the root node. If the pathname is correct, the
+               corresponding node is returned otherwise NULL is returned.
+               Note that the pathname should start with instance name of the
+               child of the current node or the root node as the case may be.
+               The individual instance names are separated by ".".]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Hrc_Node_t *
+Hrc_ManagerFindNodeByPathName(
+  Hrc_Manager_t *manager,  
+  char *path,
+  boolean pathFlag)
+{
+  int position, count;
+  int i = 0;
+  Hrc_Node_t *presentNode;
+  char *name;
+  
+  /* Check whether the pathname begins from the root node or the current node
+     and initialize presentNode accordingly. */
+  if(pathFlag == FALSE) {  
+    /* Hierarchy will be traversed beginning from root node. */
+    presentNode = manager->rootNode;
+  }
+  else {
+    /* Hierarchy will be traversed beginning from current node. */
+    presentNode = manager->currentNode;
+  }
+
+  position = i;
+/* The name of a particular node in the pathname begins at position.
+   position is updated every time presentNode is updated to a child from
+   the parent. */
+  
+  count = 0;
+  while(path[i] != '\0') {
+    if(path[i] == '.') {
+      name = ALLOC(char, count+1);
+      strncpy(name, path+position, count);
+      name[count] = '\0';
+      if((presentNode = Hrc_NodeFindChildByName(presentNode, name)) ==
+         NIL(Hrc_Node_t)) {
+        FREE(name);
+        return NIL(Hrc_Node_t);
+      }
+      position += count + 1;
+      count = 0;
+      FREE(name);
+    }
+    else {
+      count++;
+    }
+    i++;
+  }
+  name = ALLOC(char, count+1);
+  strncpy(name, path+position, count);
+  name[count] = '\0';
+  if((presentNode = Hrc_NodeFindChildByName(presentNode, name)) ==
+     NIL(Hrc_Node_t)) {
+    FREE(name);
+    return NIL(Hrc_Node_t);
+  }
+  FREE(name);
+  return presentNode;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns pointer to the actual variable corresponding to
+               a formal variable of a node.]
+
+  Description [The function tracks a formal variable up in the hierarchy
+               until that variable becomes an internal variable of a node.
+               While traversing the hierarchy upwards it does not go beyond
+               the specified reference node. If node is identical to reference
+               node, formalVar is returned. If any error occurs a NULL
+               pointer is returned]
+               
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Var_Variable_t *
+Hrc_VariableFindActualFromFormal(
+  Hrc_Node_t *node,
+  Var_Variable_t *formalVar,
+  Hrc_Node_t *referenceNode)
+{
+  int position = -1;
+  int i;
+  Var_Variable_t *var;
+  Hrc_Node_t *presentNode;
+  Var_Variable_t *presentVar;
+  char *varName;
+  
+  if(node == referenceNode) {
+    return formalVar;
+  }
+  else {
+    presentNode = node;
+    presentVar = formalVar;
+  }
+  
+  /* A variable at position i in formalInputs corresponds to a varible at
+     position i in actualInputs. The variables in actualInputs in a node
+     are actually formal variables (could be I/O or internal) of the parent
+     of the node. Given a formal variable and a node, search for the
+     variable in formalInputs and formalOutputs. If it is not present in
+     either then check if it is an internal variable of the node. If it is
+     present, get the corresponding variable from actualInputs or
+     actualOutputs as the case may be. Update presentVar to this variable
+     and presentNode to the parent of the node. Repeat the process until
+     presentVar is an internal variable of presentNode or presentNode
+     becomes the same as referenceNode. */
+
+  while(presentNode != referenceNode) {
+    Hrc_NodeForEachFormalInput(presentNode, i, var) {
+      if(var == presentVar) {
+        position = i;
+      }
+    }
+    if(position != -1) {
+      presentVar = array_fetch(Var_Variable_t *,
+                               presentNode->actualInputs, position);
+    }
+    else {
+      Hrc_NodeForEachFormalOutput(presentNode, i, var) {
+        if(var == presentVar) {
+          position = i;
+        }
+      }
+      if(position != -1) {
+        presentVar = array_fetch(Var_Variable_t *,
+                                 presentNode->actualOutputs, position);
+      }
+      else {
+        varName = Var_VariableReadName(presentVar);
+        if(st_is_member(presentNode->varTable, varName)) {
+          return presentVar;
+        }
+        else {
+          return NIL(Var_Variable_t);
+        }
+      }
+    }
+    presentNode = presentNode->parentNode;
+/* The following check is just to make sure that the function does not try
+   to access the parent of the root node. */
+    if(presentNode == NIL(Hrc_Node_t )) {
+      return NIL(Var_Variable_t);
+    }
+    position = -1;
+  }
+  return presentVar;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns an array of models being used in the hierarchy
+               below the current node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+array_t *
+Hrc_ManagerObtainComponentModels(
+  Hrc_Manager_t *manager)
+{
+  st_generator *gen;
+  char *modelName;
+  char *dummy;
+  Hrc_Model_t *model;
+  st_table *modelTable = st_init_table(strcmp, st_strhash);
+  array_t *modelArray = array_alloc(Hrc_Model_t *, 0);
+  
+  NodeObtainComponentModels(manager->currentNode, modelTable);
+  st_foreach_item(modelTable, gen, &modelName, &dummy) {
+    st_lookup(manager->modelTable, modelName, &model);
+    array_insert_last(Hrc_Model_t *, modelArray, model);
+  }
+  st_free_table(modelTable);
+  return modelArray;
+}
+
+/**Function********************************************************************
+  
+  Synopsis    [Returns the hierarchical name of a node.]
+  
+  Description [A pointer to a string containing the hierarchical name
+               is returned. The user is responsible for freeing this string.
+               If pathFlag is set to TRUE the name is found relative to the
+               current node otherwise the name is found relative to the
+               root node. The path name of root node relative to the root node
+               and the current node relative to the current node is "".
+               If there is any error NULL is returned. Note
+               that for each level of hierarchy that is traversed there is an
+               instance name and these are separated by ".".]
+
+  SideEffects []
+
+  SeeAlso     [Hrc_ManagerFindNodeByPathName()]
+
+******************************************************************************/
+char *
+Hrc_NodeFindHierarchicalName(
+  Hrc_Node_t *node,
+  boolean pathFlag)
+{
+  Hrc_Manager_t *manager = Hrc_NodeReadManager(node);
+  Hrc_Node_t *currentNode, *rootNode, *tempNode;
+  char *name;
+  char *parentName;
+  char *temp;
+
+  rootNode = Hrc_ManagerReadRootNode(manager);
+  currentNode = Hrc_ManagerReadCurrentNode(manager);
+  
+  if(pathFlag == FALSE) {
+    if(node == rootNode) {
+      name = util_strsav("");
+    }
+    else {
+      tempNode = node;
+      name = util_strsav(Hrc_NodeReadInstanceName(tempNode));
+      while((tempNode = Hrc_NodeReadParentNode(tempNode)) != rootNode) {
+        parentName = util_strsav(Hrc_NodeReadInstanceName(tempNode));
+        temp = util_strcat3(parentName, ".", name);
+        FREE(parentName);
+        FREE(name);
+        name = temp;      
+      }
+    }
+  }
+  else {
+    if(node == currentNode) {
+    name = util_strsav("");
+    }
+    else {
+      tempNode = node;
+      name = util_strsav(Hrc_NodeReadInstanceName(tempNode));
+      if(tempNode == rootNode) {
+        /* return NULL. In this case, the function is being asked to find the
+           pathname of root node relative to the current node, when the
+           current node is not the root node */
+        FREE(name);
+        return NIL(char);
+      }
+      while((tempNode = Hrc_NodeReadParentNode(tempNode)) != currentNode) {
+        if(tempNode == rootNode) {
+          FREE(name);
+          return NIL(char);
+        }
+        parentName = util_strsav(Hrc_NodeReadInstanceName(tempNode));
+        temp = util_strcat3(parentName, ".", name);
+        FREE(parentName);
+        FREE(name);
+        name = temp;      
+      }
+    }
+  }
+  return name;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns pointer to a hash table from global path name of a
+               formal variable to actual variable]
+
+  Description [The hash table returned is from the global path name of a
+               formal variable to the global path name of its corresponding
+               actual variable. While traversing up the hierarchy, the
+               function will not go beyond rootNode.]
+
+  SideEffects [None]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+/*st_table *
+Hrc_TableCreateFormalToActual(
+  Hrc_Node_t *rootNode)
+{
+}*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Replaces a sub-tree in the hierarchy with a another tree.]
+             
+  Description [The function replaces a sub-tree in the hierarchy whose root
+               is oldNode by another tree whose root node is specified by
+               newNode. It is illegal for newNode to be NULL. If oldNode is
+               NULL, the tree hanging from newNode is freed recursively and
+               TRUE is returned. Otherwise, it is checked whether newNode is
+               a part of the existing hierarchy. If it is, FALSE is returned
+               and nothing is done. If it is not, oldNode is replaced
+               by newNode in the hierarchy and TRUE is returned. To effect the
+               replacement, the applInfoTable of newNode is freed and a copy
+               of applInfoTable of oldNode is stored in its place.
+               Then changeFn is called for each entry in the table.
+               The hierarchy is traversed towards the root node
+               starting from the parent of oldNode. At each step, a new model
+               is created and registered with the hierarchy manager. The new
+               model names are obtained by appending a '~' to the name of the
+               model which was modified. Finally, oldNode is freed
+               recursively.]
+
+  SideEffects [The hierarchy tree is modified and new models are added.]
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+Hrc_TreeReplace(
+  Hrc_Node_t *oldNode,
+  Hrc_Node_t *newNode)
+{
+  Hrc_Node_t *tempNode, *presentNode;
+  char *newName, *instanceName;
+  char *newInstanceName;
+  int i, num, index;
+  Hrc_Model_t *prevOldModel, *prevNewModel;
+  Hrc_Model_t *oldModel, *newModel;
+  Hrc_Model_t *calleeModel;
+  Hrc_Subckt_t *subckt;
+  st_table *varToDupVar;
+  Tbl_Table_t *table, *dupTable;
+  Var_Variable_t *var, *dupVar;
+  char *name, *dupName;
+  st_generator *gen;
+  Hrc_Latch_t *latch, *dupLatch;
+  array_t *newActualInputVars, *newActualOutputVars;
+  char *key;
+  ApplInfo_t *applInfo;
+  
+  /* It is illegal to pass NULL as newNode. */
+  assert(newNode != NIL(Hrc_Node_t));
+  
+  if(oldNode == NIL(Hrc_Node_t)) {
+    HrcNodeFreeRecursively(newNode);
+    return TRUE;
+  }
+  
+  if(Hrc_NodeTestIsInTree(newNode, oldNode->manager->rootNode)) {
+    return FALSE;
+  }
+
+  /* free applInfo strutures all the way to the root since
+     flattened networks get invalidated with this tree-replace. */
+  presentNode = oldNode;
+  while(presentNode != NIL(Hrc_Node_t)) {
+    st_foreach_item(presentNode->applInfoTable, gen, &key, &applInfo) {
+      (*applInfo->freeFn)(applInfo->data);
+      FREE(key);
+      FREE(applInfo);
+    }
+    st_free_table(presentNode->applInfoTable);
+    presentNode->applInfoTable = st_init_table(strcmp, st_strhash);
+    presentNode = Hrc_NodeReadParentNode(presentNode);
+  }
+
+  /* If oldNode is the root node of the hierarchy, simply set the root node
+     and current node of the hierarchy to newNode. */
+
+  if(oldNode->parentNode == NIL(Hrc_Node_t)) {
+    Hrc_ManagerSetRootNode(oldNode->manager, newNode);
+    Hrc_ManagerSetCurrentNode(oldNode->manager, newNode);
+  }
+  else {
+    /* First, remove the connection between oldNode and its parent and
+       establish connection between newNode and oldNode's parent. */
+    tempNode = HrcNodeDeleteChild(oldNode->parentNode, oldNode->instanceName);
+    assert(oldNode == tempNode);
+    FREE(newNode->instanceName);
+    newNode->instanceName = util_strsav(oldNode->instanceName);
+    newNode->parentNode = oldNode->parentNode;
+    st_insert(newNode->parentNode->childTable, newNode->instanceName,
+              (char *) newNode);
+    newNode->actualInputs = array_dup(oldNode->actualInputs);
+    newNode->actualOutputs = array_dup(oldNode->actualOutputs);
+
+    /* Starting from the parent of oldNode (now the parent of newNode), go
+       up the hierarchy and at each node generate a new model by modifying
+       the model corresponding to the node appropriately. The new model name
+       is obtained from the old one by appending a '~' to it. The model names
+       in the nodes traversed have to be modified.
+       
+       The three variables newInstanceName, prevOldModel and prevNewModel
+       keep information needed to generate new models by modifying already
+       existing ones. */
+    newInstanceName = newNode->instanceName;
+    presentNode = newNode->parentNode;
+    st_lookup(presentNode->manager->modelTable, oldNode->modelName,
+              &prevOldModel);
+    st_lookup(presentNode->manager->modelTable, newNode->modelName,
+              &prevNewModel);
+    while(presentNode != NIL(Hrc_Node_t)) {
+      oldModel = Hrc_ManagerFindModelByName(presentNode->manager,
+                                            presentNode->modelName);
+      newName = ALLOC(char, strlen(presentNode->modelName) + 2);
+      strcpy(newName, presentNode->modelName);
+      strcat(newName, "~");
+      FREE(presentNode->modelName);
+      presentNode->modelName = newName;
+
+      /* Allocate a new model and fill up its fields by copying and
+         modifying appropriately the fields from the old model */
+      newModel = Hrc_ModelAlloc(presentNode->manager, presentNode->modelName);
+
+      /* Fill in the entries of the master node of newModel. I couldn't
+         use Hrc_NodeDup() to duplicate the master node of the oldModel here
+         because that function does some other things too. All the variables
+         of the masterNode of oldModel are duplicated. Note that masterNode
+         and the nodes in the hierarchy corresponding to the model do not
+         share variables. */
+
+      varToDupVar = st_init_table(st_ptrcmp, st_ptrhash);
+      Hrc_NodeForEachVariable(oldModel->masterNode, gen, name, var) {
+        dupVar = Var_VariableDup(var, newModel->masterNode);
+        dupName = Var_VariableReadName(dupVar);
+        st_insert(newModel->masterNode->varTable, dupName, dupVar);
+        st_insert(varToDupVar, var, dupVar);
+      }
+      Hrc_NodeForEachFormalInput(oldModel->masterNode, i, var) {
+        st_lookup(varToDupVar, var, &dupVar);
+        array_insert_last(Var_Variable_t *,
+                          newModel->masterNode->formalInputs, dupVar);
+      }
+      Hrc_NodeForEachFormalOutput(oldModel->masterNode, i, var) {
+        st_lookup(varToDupVar, var, &dupVar);
+        array_insert_last(Var_Variable_t *,
+                          newModel->masterNode->formalOutputs, dupVar);
+      }
+      Hrc_NodeForEachNameTable(oldModel->masterNode, i, table) {
+        dupTable = Tbl_TableSoftDup(table);
+        Tbl_TableForEachInputVar(dupTable, index, var) {
+          st_lookup(varToDupVar, var, &dupVar);
+          Tbl_TableSubstituteVar(dupTable, var, dupVar);
+        }
+        Tbl_TableForEachOutputVar(dupTable, index, var) {
+          st_lookup(varToDupVar, var, &dupVar);
+          Tbl_TableSubstituteVar(dupTable, var, dupVar);
+        }
+        array_insert_last(Tbl_Table_t *, newModel->masterNode->nameTables,
+                          dupTable);
+      }
+      Hrc_NodeForEachLatch(oldModel->masterNode, gen, name, latch) {
+        dupLatch = ALLOC(Hrc_Latch_t, 1);
+        st_lookup(varToDupVar, latch->latchInput, &(dupLatch->latchInput));
+        st_lookup(varToDupVar, latch->latchOutput, &(dupLatch->latchOutput));
+        dupLatch->resetTable = Tbl_TableSoftDup(latch->resetTable);
+        Tbl_TableForEachInputVar(dupLatch->resetTable, index, var) {
+          st_lookup(varToDupVar, var, &dupVar);
+          Tbl_TableSubstituteVar(dupLatch->resetTable, var, dupVar);
+        }
+        Tbl_TableForEachOutputVar(dupLatch->resetTable, index, var) {
+          st_lookup(varToDupVar, var, &dupVar);
+          Tbl_TableSubstituteVar(dupLatch->resetTable, var, dupVar);
+        }
+        dupLatch->undef = latch->undef;
+        st_insert(newModel->masterNode->latchTable, Var_VariableReadName(dupLatch->latchOutput), dupLatch);
+      }
+
+      /* For each subckt entry in oldModel, add a corresponding entry to
+         newModel except for the entry corresponding to the modified child
+         of presentNode. This particular subckt is recognized by its
+         instanceName. */
+      Hrc_ModelForEachSubckt(oldModel, gen, name, subckt) {
+        if(!strcmp(subckt->instanceName, newInstanceName)) {
+          calleeModel = prevNewModel;
+        }
+        else {
+          calleeModel = subckt->model;
+        }
+        instanceName = subckt->instanceName;
+        newActualInputVars = array_alloc(Var_Variable_t *, 0);
+        num = array_n(subckt->actualInputVars);
+        for(i =0; i < num; ++i) {
+          var = array_fetch(Var_Variable_t *, subckt->actualInputVars, i);
+          st_lookup(varToDupVar, var, &dupVar);
+          array_insert_last(Var_Variable_t *, newActualInputVars, dupVar);
+        }
+        newActualOutputVars = array_alloc(Var_Variable_t *, 0);
+        num = array_n(subckt->actualOutputVars);
+        for(i =0; i < num; ++i) {
+          var = array_fetch(Var_Variable_t *, subckt->actualOutputVars, i);
+          st_lookup(varToDupVar, var, &dupVar);
+          array_insert_last(Var_Variable_t *, newActualOutputVars, dupVar);
+        }
+        Hrc_ModelAddSubckt(newModel, calleeModel, instanceName,
+                           newActualInputVars, newActualOutputVars);
+      }
+      
+      st_free_table(varToDupVar);
+      
+      newInstanceName = presentNode->instanceName;
+      /* Right now, I am not modifying the instance names. */
+      prevOldModel = oldModel;
+      prevNewModel = newModel;
+      presentNode = presentNode->parentNode;
+    }
+  }
+  HrcNodeFreeRecursively(oldNode);
+  return TRUE;
+}
+/**Function********************************************************************
+
+  Synopsis    [Checks whether node1 is part of the tree whose root is node2.]
+
+  Description [The function returns TRUE if node1 is part of the sub-tree
+               whose root is node2. Otherwise, it returns FALSE.]
+
+  SideEffects []
+
+  SeeAlso     [Hrc_TreeReplace()]
+
+******************************************************************************/
+boolean
+Hrc_NodeTestIsInTree(
+  Hrc_Node_t *node1,      
+  Hrc_Node_t *node2)      
+{
+/* node1 is the node whose membership is to be tested */
+/* node2 is the root of the tree which is to be searched */
+  st_generator *gen;
+  char *name;
+  Hrc_Node_t *childNode;
+  
+  if(node1 == node2) {
+    return TRUE;
+  }
+  else {
+    Hrc_NodeForEachChild(node2, gen, name, childNode) {
+      if(Hrc_NodeTestIsInTree(node1, childNode)) {
+        return TRUE;
+      }
+    }
+    return FALSE;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Test whether a hnode is uninterpreted]
+
+  Description [ An uninterpreted node does not have tables, latches or
+                children. This type of  node is defined in BLIF-MV
+                as follows:
+				   
+	        syntax/example:
+								  
+		.subckt f1 t1 a <= x c => z b <= y
+									   
+	        this represents an instance of the uninterpreted function
+                z = f1( x, y ). 
+
+                
+	        a <= b  denotes formal variable a and actual variable b.  Where
+			a is a subckt input.
+
+                        
+		a => b  denotes formal variable a and actual variable b.  Where
+			a is a subckt output.
+
+	        All subckts, with the same model name, should have identical
+		formal parameters.
+                
+	       Note:  previous .subckt syntax is still be supported. There is
+		      no model definition for uninterpreted subckt.
+				]
+
+  SideEffects []
+
+  SeeAlso     [Hrc_ModelTestIsUninterpreted]
+
+******************************************************************************/
+boolean
+Hrc_NodeTestIsUninterpreted(
+  Hrc_Node_t *node )
+
+{
+  if( st_count( Hrc_NodeReadLatchTable( node ) ) ||
+      array_n(  Hrc_NodeReadNameTables( node ) ) ||
+      st_count( Hrc_NodeReadChildTable( node ) ) ) return FALSE;
+
+  return TRUE;
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks if  a model is uninterpreted.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     [Hrc_NodeTestIsUninterpreted]
+
+******************************************************************************/
+boolean
+Hrc_ModelTestIsUninterpreted(
+	Hrc_Model_t* model )
+
+{
+  Hrc_Node_t* node;
+
+  node = Hrc_ModelReadMasterNode( model );
+
+  if( st_count( Hrc_NodeReadLatchTable( node ) ) ||
+      array_n(  Hrc_NodeReadNameTables( node ) ) ||
+      st_count( Hrc_ModelReadSubcktTable( model ) ) ) return FALSE;
+  
+  return TRUE;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Checks for the existence of an uninterpreted node in the 
+                hierarchy below the parent.]
+
+  Description [ Determines if there is a child hnode below the parent 
+		is uninterpreted.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+Hrc_NodeTestRecursivelyIsUninterpreted(
+	Hrc_Node_t* parent )
+{
+  st_generator* gen;
+  char*         childName;
+  Hrc_Node_t*   child;
+  
+  if( Hrc_NodeTestIsUninterpreted( parent )) return TRUE;
+  
+  Hrc_NodeForEachChild( parent, gen, childName, child) {
+
+    if( Hrc_NodeTestRecursivelyIsUninterpreted( child ) ) return TRUE;
+
+  }
+
+  return FALSE;
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Checks for an uninterpreted node in hierarchy.]
+
+  Description [ Determines if there is a node in the hierarchy that is
+                uninterpreted.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+*****************************************************************************/
+boolean
+Hrc_NodeTestIsUninterpretedNodeInHierarchy(
+  Hrc_Manager_t* hmgr )
+
+{
+
+  return Hrc_NodeTestRecursivelyIsUninterpreted( Hrc_ManagerReadRootNode( hmgr ) );
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if all the variables of a given node are consistent.
+  Otherwise 0 is returned.]
+
+  Description [Checks if all the variables in a given node are consistent
+  in terms of labeling of six attributes (PI,PO,PS,NS,SI,SO) and the 
+  numFanoutTables field. Returns 1 if consistent. Otherwise 0 is returned.
+  The function can be used for a sanity check after restructuring the hrc
+  data structure.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+Hrc_NodeCheckVariableConsistency(
+  Hrc_Node_t *node)
+{
+  boolean success = TRUE;
+  int i, j;
+  st_generator *gen;
+  Var_Variable_t *var;
+  Hrc_Latch_t *latch;
+  char *latchName, *varName;
+  st_table *varToNumFanoutTables;
+  Tbl_Table_t *table;
+  long num;
+
+  Hrc_NodeForEachFormalInput(node,i,var){
+    if (Var_VariableTestIsPI(var) == 0){
+      fprintf(vis_stderr, "Input variable %s is not labeled as PI.\n",
+        Var_VariableReadName(var));
+      success = FALSE;
+    }
+  }
+  Hrc_NodeForEachFormalOutput(node,i,var){
+    if (Var_VariableTestIsPO(var) == 0){
+      fprintf(vis_stderr, "Output variable %s is not labeled as PO.\n",
+        Var_VariableReadName(var));
+      success = FALSE;
+    }
+  }
+  /* if the node is not the root node, check consistency of actual variables */
+  if (Hrc_NodeReadParentNode(node) != NIL(Hrc_Node_t)){
+    Hrc_NodeForEachActualInput(node,i,var){
+      if (Var_VariableTestIsSI(var) == 0){
+        fprintf(vis_stderr, "Subcircuit input variable %s is not labeled as SI.\n",
+          Var_VariableReadName(var));
+        success = FALSE;
+      }
+    }
+    Hrc_NodeForEachActualOutput(node,i,var){
+      if (Var_VariableTestIsSO(var) == 0){
+        fprintf(vis_stderr, "Subcircuit output variable %s is not labeled as SO.\n",
+          Var_VariableReadName(var));
+        success = FALSE;
+      }
+    }
+  }
+
+  Hrc_NodeForEachLatch(node,gen,latchName,latch){
+    var = Hrc_LatchReadOutput(latch);
+    if (Var_VariableTestIsPS(var) == 0){
+      fprintf(vis_stderr, "Latch output variable %s is not labeled as PS.\n",
+        Var_VariableReadName(var));
+      success = FALSE;
+    }
+    var = Hrc_LatchReadInput(latch);
+    if (Var_VariableTestIsNS(var) == 0){
+      fprintf(vis_stderr, "Latch input variable %s is not labeled as NS.\n",
+        Var_VariableReadName(var));
+      success = FALSE;
+    }
+  }
+
+  varToNumFanoutTables = st_init_table(st_ptrcmp,st_ptrhash);
+  Hrc_NodeForEachVariable(node,gen,varName,var){
+    if (Var_VariableTestTypeConsistency(var) == 0){
+      success = FALSE;
+    }
+    (void)st_insert(varToNumFanoutTables, (char *)var, (char *)((long)0));
+  }
+
+  Hrc_NodeForEachNameTable(node,i,table){
+    Tbl_TableForEachInputVar(table,j,var){
+      (void)st_lookup(varToNumFanoutTables,var,&num);
+      st_insert(varToNumFanoutTables,var,(char *) ++num);
+    }  
+  }
+
+  Hrc_NodeForEachVariable(node,gen,varName,var){
+    (void)st_lookup(varToNumFanoutTables,var,&num);
+    if (num != (long)Var_VariableReadNumFanoutTables(var)){
+      fprintf(vis_stderr,"numFanoutTables field of variable %s is inconsistent.  (True value = %d, Registered value = %d)\n", 
+        Var_VariableReadName(var), (int)num, Var_VariableReadNumFanoutTables(var));
+      success = FALSE;
+    }
+  }
+
+  st_free_table(varToNumFanoutTables);
+  return success;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [A recursive function which inserts the names of all models
+               used in the construction of a node into the hash table models.]
+
+  SideEffects []
+
+  SeeAlso     [Hrc_ManagerObtainComponentModels()]
+
+******************************************************************************/
+
+static void
+NodeObtainComponentModels(
+    Hrc_Node_t *node,
+    st_table *models)
+{
+    char *name;
+    Hrc_Node_t *child;
+    st_generator *gen;
+    
+    st_insert(models, node->modelName, (char *) 0);
+    Hrc_NodeForEachChild(node, gen, name, child){
+        NodeObtainComponentModels(child, models);
+    }
+}
Index: vis_dev/vis-2.3/src/hrc/hrcModify.c
===================================================================
--- vis_dev/vis-2.3/src/hrc/hrcModify.c	(revision 14)
+++ vis_dev/vis-2.3/src/hrc/hrcModify.c	(revision 14)
@@ -0,0 +1,399 @@
+/**CFile***********************************************************************
+
+  FileName    [hrcModify.c]
+
+  PackageName [hrc]
+
+  Synopsis    [This files provides the basic functions concerned with
+               modifying the hierarchy. This ]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [Shaz Qadeer]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "hrcInt.h"
+
+static char rcsid[] UNUSED = "$Id: hrcModify.c,v 1.4 2005/04/16 04:23:47 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adds a subckt to a model.]
+
+  Description [If a subckt with the same instanceName is already present, the
+               function returns FALSE. Otherwise, a new sub-circuit is
+               allocated and initialized and TRUE is returned. Note that
+               it is the user's responsibility to free the string
+               instanceName. actualInputVars and actualOutputVars are
+               pointer-copied.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+Hrc_ModelAddSubckt(
+  Hrc_Model_t *callerModel,
+  Hrc_Model_t *calleeModel,
+  char *instanceName,
+  array_t *actualInputVars,
+  array_t *actualOutputVars)
+{
+  Hrc_Subckt_t *subckt; 
+  
+  if(!st_is_member(callerModel->subcktTable, instanceName)) {
+    subckt = ALLOC(Hrc_Subckt_t, 1);     
+    subckt->model = calleeModel;
+    subckt->instanceName = util_strsav(instanceName);
+    subckt->actualInputVars = actualInputVars;
+    subckt->actualOutputVars = actualOutputVars;
+    st_insert(callerModel->subcktTable, subckt->instanceName, (char *) subckt);
+    return TRUE;
+  }
+  else {
+    return FALSE;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Adds a name table to a model.]
+
+  Description [The function adds a name table to the master node of a model.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Hrc_ModelAddNameTable(
+  Hrc_Model_t *model,
+  Tbl_Table_t *table)
+{
+  array_insert_last(Tbl_Table_t *, model->masterNode->nameTables, table);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Adds a child node to a node.]
+
+  Description [The function checks if a child with the same instance name
+               is already present in parent. If it is present, FALSE is
+               returned. Otherwise, the child is added and TRUE is returned.
+               Note that before using this function, child should have
+               created using Hrc_NodeAlloc().]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+Hrc_NodeAddChild(
+  Hrc_Node_t *parent,
+  Hrc_Node_t *child,
+  array_t *actualInputs,
+  array_t *actualOutputs)
+{
+  if(!st_is_member(parent->childTable, child->instanceName)) {
+    st_insert(parent->childTable, child->instanceName, (char *) child);
+    child->parentNode = parent;
+    child->actualInputs = actualInputs;
+    child->actualOutputs = actualOutputs;
+    return TRUE;
+  }
+  else {
+    return FALSE;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Adds a latch to a node.]
+
+  Description [The function adds a latch to a node if the latch is not 
+               present already and returns TRUE. Otherwise, it returns FALSE.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+Hrc_NodeAddLatch(
+  Hrc_Node_t *node,
+  Hrc_Latch_t *latch)
+{
+  char *latchOutputName = Var_VariableReadName(latch->latchOutput);
+  
+  if(!st_is_member(node->latchTable, latchOutputName)) {
+    st_insert(node->latchTable, latchOutputName, (char *) latch);
+    return TRUE;
+  }
+  else {
+    return FALSE;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Adds a variable to a node.]
+  
+  Description [The function adds a variable to a node if the variable is not 
+               present already and returns TRUE. Otherwise, it returns FALSE.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+Hrc_NodeAddVariable(
+  Hrc_Node_t *node,
+  Var_Variable_t *var)
+{
+  char *varName = Var_VariableReadName(var);
+  
+  if(!st_is_member(node->varTable, varName)) {
+    st_insert(node->varTable, varName, (char *) var);
+    return TRUE;
+  }
+  else {
+    return FALSE;
+  }
+}
+
+/**Function********************************************************************
+  
+  Synopsis    [Deletes a variable from a node.]
+
+  Description [If the variable is present in node it is deleted and TRUE is
+               returned. Otherwise, nothing is done and FALSE is returned.
+               Note that this function should only be used for deleting an
+               internal variable of a node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+Hrc_NodeDeleteVariable(
+  Hrc_Node_t *node,
+  Var_Variable_t *var)
+{
+  char *varName = Var_VariableReadName(var);
+  
+  return st_delete(node->varTable, &varName, &var);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Deletes a latch from a node.]
+
+  Description [If the latch is present in node it is deleted and TRUE is
+               returned. Otherwise, nothing is done and FALSE is returned.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+Hrc_NodeDeleteLatch(
+  Hrc_Node_t *node,
+  Hrc_Latch_t *latch)
+{
+  char *latchOutputName = Var_VariableReadName(latch->latchOutput);
+  
+  return st_delete(node->latchTable, &latchOutputName, &latch);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Deletes a child from a node.]
+
+  Description [If a child of the name childName exists in node, it is deleted
+               from the childTable of node and a pointer to this child is
+               returned. Otherwise, NULL is returned.]
+
+  SideEffects []
+
+  SeeAlso     [Hrc_TreeReplace()]
+
+******************************************************************************/
+Hrc_Node_t *
+HrcNodeDeleteChild(
+  Hrc_Node_t *node,
+  char *childName)
+{
+  Hrc_Node_t *childNode;
+  
+  if(st_delete(node->childTable, &childName, &childNode)) {
+    return childNode;
+  }
+  else {
+    return NIL(Hrc_Node_t);
+  }
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/imc/imc.h
===================================================================
--- vis_dev/vis-2.3/src/imc/imc.h	(revision 14)
+++ vis_dev/vis-2.3/src/imc/imc.h	(revision 14)
@@ -0,0 +1,197 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [imc.h]
+
+  PackageName [imc]
+
+  Synopsis    [Model Check using over(under)-approximation with automatic
+  iterative refinement.]
+
+  Description []
+
+
+  Author      [Jae-Young Jang]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+  Revision    [$Id:]
+
+******************************************************************************/
+
+#ifndef _IMC
+#define _IMC
+
+#include "part.h"
+#include "mc.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Enum************************************************************************
+
+  Synopsis    [Verbosity Levels.]
+
+******************************************************************************/
+typedef enum {
+  Imc_VerbosityNone_c,
+  Imc_VerbosityMin_c,
+  Imc_VerbosityMax_c
+} Imc_VerbosityLevel;
+
+/**Enum************************************************************************
+
+  Synopsis    [Refinement method.]
+
+******************************************************************************/
+typedef enum {
+  Imc_RefineSort_c,
+  Imc_RefineLatchRelation_c
+} Imc_RefineMethod;
+
+/**Enum************************************************************************
+
+  Synopsis    [Extent to which don't cares are used in Imc functions.]
+
+******************************************************************************/
+
+typedef enum {
+  Imc_DcLevelNone_c,
+  Imc_DcLevelRch_c,
+  Imc_DcLevelMax_c,
+  Imc_DcLevelArdc_c
+} Imc_DcLevel;
+
+/**Enum************************************************************************
+
+  Synopsis    [Type of a verification result.]
+
+******************************************************************************/
+typedef enum {
+  Imc_VerificationTrue_c,
+  Imc_VerificationFalse_c,
+  Imc_VerificationInconclusive_c,
+  Imc_VerificationRefine_c,
+  Imc_VerificationError_c
+} Imc_VerificationResult;
+
+/**Enum************************************************************************
+
+  Synopsis    [Type of an operational graph.]
+
+******************************************************************************/
+typedef enum {
+  Imc_GraphNDOG_c,
+  Imc_GraphPDOG_c,
+  Imc_GraphMOG_c
+} Imc_GraphType;
+
+/**Enum************************************************************************
+
+  Synopsis    [Type of a polarity in a graph.]
+
+******************************************************************************/
+typedef enum {
+  Imc_PolarityNeg_c,
+  Imc_PolarityPos_c,
+  Imc_PolarityBoth_c
+} Imc_Polarity;
+
+/**Enum************************************************************************
+
+  Synopsis    [Upper bound approximation computation method.]
+
+******************************************************************************/
+typedef enum {
+  Imc_UpperExistentialQuantification_c
+} Imc_UpperMethod;
+
+/**Enum************************************************************************
+
+  Synopsis    [Lower bound approximation computation method.]
+
+******************************************************************************/
+typedef enum {
+  Imc_LowerSubsetTR_c,
+  Imc_LowerUniversalQuantification_c
+} Imc_LowerMethod;
+
+/**Enum************************************************************************
+
+  Synopsis    [Partition Method.]
+
+******************************************************************************/
+typedef enum {
+  Imc_PartAll_c,
+  Imc_PartDepend_c,
+  Imc_PartInc_c
+} Imc_PartMethod;
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef struct ImcInfoStruct Imc_Info_t;
+typedef struct ImcUpperSystemInfo Imc_UpperSystemInfo_t;
+typedef struct ImcLowerSystemInfo Imc_LowerSystemInfo_t;
+typedef struct ImcSystemInfo Imc_SystemInfo_t;
+typedef struct ImcNodeInfo Imc_NodeInfo_t;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void Imc_Init(void);
+EXTERN void Imc_End(void);
+EXTERN Imc_VerificationResult Imc_ImcEvaluateFormulaLinearRefine(Ntk_Network_t *network, Ctlp_Formula_t *orgFormula, Ctlp_Formula_t *formula, Ctlp_FormulaClass formulaClass, int incrementalSize, Imc_VerbosityLevel verbosity, Imc_RefineMethod refine, mdd_t *careStates, Fsm_Fsm_t *exactFsm, Imc_DcLevel dcLevel, Imc_GraphType graphType, Imc_LowerMethod lowerMethod, Imc_UpperMethod upperMethod, boolean computeExact, boolean needLower, boolean needUpper, Imc_PartMethod partMethod, Hrc_Node_t *currentNode, char *modelName);
+EXTERN Imc_VerificationResult Imc_ImcVerifyFormula(Imc_Info_t *imcInfo, Ctlp_Formula_t *formula);
+EXTERN Imc_VerificationResult Imc_SatCheck(Imc_Info_t *imcInfo, Ctlp_Formula_t *formula);
+EXTERN Imc_Info_t * Imc_ImcInfoInitialize(Ntk_Network_t *network, Ctlp_Formula_t *formula, Ctlp_FormulaClass formulaClass, Imc_VerbosityLevel verbosity, Imc_RefineMethod refine, mdd_t *careStates, Imc_DcLevel dcLevel, int incrementalSize, Imc_GraphType graphType, Fsm_Fsm_t *exactFsm, Imc_LowerMethod lowerMethod, Imc_UpperMethod upperMethod, boolean computeExact, boolean needLower, boolean needUpper, Imc_PartMethod partMethod, Hrc_Node_t *currentNode, char *modelName);
+EXTERN void Imc_ImcInfoFree(Imc_Info_t *imcInfo);
+EXTERN void Imc_SystemInfoInitialize(Imc_Info_t *imcInfo, st_table *globalLatchNameTable, st_table *initialLatchNameTable);
+EXTERN void Imc_SystemInfoFree(Imc_SystemInfo_t *systemInfo);
+EXTERN void Imc_ImcSystemInfoUpdate(Imc_Info_t *imcInfo, st_table *newLatchNameTable);
+EXTERN void Imc_UpperSystemInfoInitialize(Imc_Info_t *imcInfo, st_table *latchNameTable);
+EXTERN void Imc_UpperSystemMinimize(Imc_Info_t *imcInfo, mdd_t *careStates);
+EXTERN void Imc_UpperSystemInfoFree(Imc_UpperSystemInfo_t *upperSystem);
+EXTERN void Imc_LowerSystemInfoInitialize(Imc_Info_t *imcInfo, st_table *latchNameTable);
+EXTERN void Imc_LowerSystemMinimize(Imc_Info_t *imcInfo, mdd_t *careStates);
+EXTERN void Imc_LowerSystemInfoFree(Imc_LowerSystemInfo_t *lowerSystem);
+EXTERN Imc_NodeInfo_t * Imc_NodeInfoInitialize(Imc_Polarity polarity);
+EXTERN void Imc_NodeInfoReset(Imc_Info_t *imcInfo);
+EXTERN void Imc_NodeInfoFree(Imc_NodeInfo_t *nodeInfo);
+EXTERN void Imc_ImcPrintSystemSize(Imc_Info_t *imcInfo);
+EXTERN void Imc_ImcPrintApproxSystemSize(Imc_Info_t *imcInfo);
+EXTERN mdd_t * Imc_GetUpperSat(Imc_Info_t *imcInfo, Ctlp_Formula_t *formula);
+EXTERN mdd_t * Imc_GetLowerSat(Imc_Info_t *imcInfo, Ctlp_Formula_t *formula);
+EXTERN int Imc_ImcEvaluateCTLFormula(Imc_Info_t *imcInfo, Ctlp_Formula_t *ctlFormula, Imc_Polarity polarity);
+EXTERN int Imc_ImcEvaluateEXApprox(Imc_Info_t *imcInfo, Ctlp_Formula_t *formula, boolean isUpper, boolean isRecomputation);
+EXTERN int Imc_ImcEvaluateEUApprox(Imc_Info_t *imcInfo, Ctlp_Formula_t *formula, boolean isUpper, boolean isRecomputation);
+EXTERN int Imc_ImcEvaluateEGApprox(Imc_Info_t *imcInfo, Ctlp_Formula_t *formula, boolean isUpper, boolean isRecomputation);
+EXTERN mdd_t * Imc_ComputeUpperPreimage(Imc_Info_t *imcInfo, mdd_t *rangeCareStates, mdd_t *targetStates, boolean *isExact);
+EXTERN mdd_t * Imc_ComputeApproxPreimageByQuantification(Imc_Info_t *imcInfo, mdd_t *rangeCareStates, mdd_t *targetStates, boolean *isExact, boolean computeLower);
+EXTERN mdd_t * Imc_ComputeLowerPreimage(Imc_Info_t *imcInfo, mdd_t *rangeCareStates, mdd_t *targetStates, boolean *isExact);
+EXTERN mdd_t * Imc_ComputeLowerPreimageBySubsetTR(Imc_Info_t *imcInfo, mdd_t *rangeCareStates, mdd_t *targetStates, boolean *isExact);
+EXTERN mdd_t * Imc_ProductAbstract(mdd_manager *mddMgr, array_t *relationArray, array_t *smoothVarsMddIdArray, mdd_t *toStates);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _IMC */
Index: vis_dev/vis-2.3/src/imc/imc.make
===================================================================
--- vis_dev/vis-2.3/src/imc/imc.make	(revision 14)
+++ vis_dev/vis-2.3/src/imc/imc.make	(revision 14)
@@ -0,0 +1,4 @@
+CSRC += imcCmd.c imcImc.c
+HEADERS += imc.h imcInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/imc/imcCmd.c
===================================================================
--- vis_dev/vis-2.3/src/imc/imcCmd.c	(revision 14)
+++ vis_dev/vis-2.3/src/imc/imcCmd.c	(revision 14)
@@ -0,0 +1,719 @@
+/**CFile***********************************************************************
+
+  FileName    [imcCmd.c]
+
+  PackageName [imc]
+
+  Synopsis    [Command interface for the imc package.]
+
+  Author      [Jae-Young Jang <jjang@vlsi.colorado.edu>]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "imcInt.h"
+#include "fsm.h"
+
+static char rcsid[] UNUSED = "$Id: imcCmd.c,v 1.24 2002/09/10 04:07:38 fabio Exp $";
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+static jmp_buf timeOutEnv;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandImc(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static void IterativeModelCheckUsage(void);
+static void TimeOutHandle(void);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the imc package.]
+
+  SideEffects []
+
+  SeeAlso     [Imc_End]
+
+******************************************************************************/
+void
+Imc_Init(void)
+{
+  Cmd_CommandAdd("iterative_model_check", CommandImc, 0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Ends the imc package.]
+
+  SideEffects []
+
+  SeeAlso     [Imc_Init]
+
+******************************************************************************/
+void
+Imc_End(void)
+{
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis         [The iterative_model_check command.]
+
+  Description      [The function starts by parsing the options. After that it 
+  checks for the network structure. The CTL formulas are read and checked for
+  correctness. Once the formulas have been read, they need to be translated
+  from the CTL representation to the operational graph representation required
+  for the iterative algorithm. The next state functions of the variables are
+  computed according to partition option when 'build_partition_mdds' has not
+  been invoked. Then iterative model checking is applied to each formula. The 
+  value specified by -i option is used as incremental size (let's say N). 
+  At first, the state transion functions of N state variables shown in the 
+  formula are computed exactly. All the others are approximated. If a
+  conclusive answer cannot be computed, the system is refined by converting
+  N approximate next state functions to be exact and try to verify again. 
+  This procedure continues until a correct answer is found. See \[1,2\] for
+  details.]
+
+  CommandName      [iterative_model_check]
+
+  CommandSynopsis  [Perform CTL model checking on an abstracted system with
+  automatic refinement algorithm.]
+
+  CommandArguments [\[-h\] \[-x\] \[-t &lt;seconds&gt;\] \[-v &lt;number&gt;\]\
+  \[-D &lt;number&gt;\] \[-r &lt;number&gt;\] \[-i &lt;number&gt;\] \
+  \[-p &lt;number&gt;\] \[-g &lt;number&gt;\] &lt;ctlfile&gt;]]
+
+  CommandDescription [  
+  <p>Command options:<p>
+
+  <dl>
+
+  <dt> -h
+  <dd> Print the command usage.
+
+  <dt> -x
+  <dd> Perform the verification exactly. No approximation is done.
+
+  <dt> -t &lt;secs&gt;
+  <dd> Time in seconds allowed for verification.  The default is no limit.
+
+  <dt> -v &lt;number&gt;
+  <dd>Specify verbosity level. Use 0 for no feedback (default), 1
+  for more, and 2 for maximum feedback.
+
+  <dt> -D &lt;number&gt;
+  <dd> Specify extent to which don't cares are used to simplify the MDDs.
+  <ul> 
+  <li>0: No don't cares used.  This is the default.
+  <li>1: Use reachability information to compute the don't-care set.
+  <li>2: Use reachability information, and minimize the transition relation
+     with respect to the `frontier set' (aggresive minimization).
+  <li>3: Use approximate reachability information.
+  </ul>
+
+  <dt> -r &lt;number&gt;
+  <dd> Specify refinement method.
+  <ul>
+  <li>0: Static scheduling by name sorting. Fast, easy, but less accurate.
+  <li>1: Static scheduling by latch affinity. Slow, but more accurate.  This
+         is the default.
+  </ul>
+
+  <dt> -i &lt;number&gt;
+  <dd> The number of state variables to be added for exact computation at
+   each iteration.  The default is 4.
+
+  <dt> -l &lt;number&gt;
+  <dd> Type of lower-bound approximation method.
+  <ul>
+  <li>0: Take a subset of each transition sub-relation by BDD subsetting.
+  <li>1: Take a subset by universal quantification.  This is the default.
+  </ul>
+
+  <dt> -p &lt;number&gt;
+  <dd> Type of partition method. If 'build_partition_mdds' is already invoked,
+  this option is ignored. Notice that some next state functions might not be
+  available after iterative_model_checking command is performed because of
+  this option.
+  <ul>
+  <li>0: Build all next state functions. Same as 'build_partition_mdds'.
+         This is the default.
+  <li>1: Build the next state functions related to the formulas. Build all
+         next state functions that are necessary to prove all formulas.
+  <li>2: Build the next state functions incrementally. None of next state 
+         functions are removed.
+  </ul>
+
+  <dt> -g &lt;number&gt;
+  <dd> Type of operational graph.
+  <ul>
+  <li>0: Negative Operational Graph. Good to prove a formula true.
+  <li>1: Positive Operational Graph. Good to prove a formula false.
+  <li>2: Mixed Operational Graph. Good to prove any formula, but it may
+         be slower.  This is the default.
+  </ul>
+
+  <dt> &lt;ctlfile&gt; 
+  <dd> File containing the CTL formulas to be verified.
+
+  <dt> Related "set" options: <p>
+  <dt> ctl_change_bracket &lt;yes/no&gt;
+  <dd> Vl2mv automatically converts "\[\]" to "&lt;&gt;" in node names,
+  therefore CTL parser does the same thing. However, in some cases a user
+  does not want to change node names in CTL parsing. Then, use this set
+  option by giving "no".  Default is "yes".
+  <p>
+
+  <dt> See also commands : model_check, incremental_ctl_verification <p>
+
+  </dl>
+
+  <p>1. Jae-Young Jang, In-Ho Moon, and Gary D. Hachtel. Iterative 
+  Abstraction-based CTL Model Checking. Design, Automation and Test in Europe
+  (DATE), 2000
+  <p>2. Jae-Young Jang. Iterative Abstraction-based CTL Model Checking. 
+  Ph. D. Thesis. University of Colorado, 1999.  
+  ]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandImc(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  static int	      timeOutPeriod;	  /* CPU seconds allowed */
+  char		      *ctlFileName;	  /* Name of file containing formulas */
+  FILE		      *ctlFile;	          /* File to read the formulas from */
+  Ntk_Network_t	      *network;           /* Pointer to the current network */
+  array_t	      *ctlFormulaArray;   /* Array of read ctl formulas */
+  array_t	      *ctlNormalForm;     /* Array of normal ctl formulas */
+  Ctlp_Formula_t      *formula;           /* Formula being verified */
+  Ctlp_Formula_t      *orgFormula; 
+  Ctlp_Formula_t      *currentFormula; 
+  char                *modelName;
+  Hrc_Node_t          *currentNode;
+  int 		      c, i;
+  array_t             *dagFormula;
+  Imc_RefineMethod    refine;             /* Refine Method */
+  mdd_t		      *careStates;	  /* Care States */
+  Imc_DcLevel         dcLevel;            /* Don't Care Level */
+  Imc_VerbosityLevel  verbosity; 	  /* Verbosity level */
+  Fsm_Fsm_t           *reducedFsm;
+  Fsm_Fsm_t           *exactFsm;
+  int  		      incrementalSize;
+  int                 option;
+  Fsm_ArdcOptions_t   *ardcOptions;
+  Imc_GraphType       graphType;
+  Imc_LowerMethod     lowerMethod;
+  Imc_UpperMethod     upperMethod;
+  boolean             needLower, needUpper;
+  boolean             computeExact;
+  Imc_PartMethod      partMethod;
+  graph_t             *partition;
+
+  long globalTimeStart;
+  long globalTimeEnd;
+  long initialTime;
+  long finalTime;
+
+
+  /* Initialize Default Values */
+  timeOutPeriod    = 0;
+  ctlFileName      = NIL(char);
+  verbosity 	   = Imc_VerbosityNone_c;
+  dcLevel          = Imc_DcLevelNone_c;
+  incrementalSize  = 4;
+  lowerMethod      = Imc_LowerUniversalQuantification_c;
+  upperMethod      = Imc_UpperExistentialQuantification_c;
+  computeExact     = FALSE;
+  partMethod       = Imc_PartAll_c;
+  refine           = Imc_RefineLatchRelation_c;
+  graphType        = Imc_GraphMOG_c;
+
+  /*
+   * Parse command line options.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "hxt:r:i:l:p:v:D:g:")) != EOF) {
+    switch(c) {
+      case 'h':
+        IterativeModelCheckUsage();
+	return 1;
+      case 'x':
+        computeExact = TRUE;
+        break;
+      case 't':
+      	timeOutPeriod = atoi(util_optarg);
+        if (timeOutPeriod < 0){
+          fprintf(vis_stdout,"** imc warning : Timeout Option -t %s is not defined.\n",
+                  util_optarg);
+          IterativeModelCheckUsage();
+          return 1;
+        }
+	      break;
+      case 'r':
+        option = atoi(util_optarg);
+        if (option == 0) refine = Imc_RefineSort_c;
+        else if (option == 1) refine = Imc_RefineLatchRelation_c;
+        else{
+	  fprintf(vis_stdout,"** imc warning : Refine option -r %d is not defined.\n",
+                  option);
+          IterativeModelCheckUsage();
+          return 1;
+        }
+        break;
+      case 'i':
+        incrementalSize = atoi(util_optarg);
+        if (incrementalSize<1){
+          fprintf(vis_stdout,"** imc warning : Incremental size option -i %d",
+                  incrementalSize);
+          fprintf(vis_stdout," is not defined.\n");
+          IterativeModelCheckUsage();
+          return 1;
+        }
+        break;
+      case 'l':
+        option = atoi(util_optarg);
+        if (option==0){
+          lowerMethod = Imc_LowerSubsetTR_c;
+        }else if (option==1){
+          lowerMethod = Imc_LowerUniversalQuantification_c;
+        }else{
+          fprintf(vis_stdout,"** imc warning : Lower bound option option -l %d",
+                  option);
+          fprintf(vis_stdout," is not defined.\n");
+          IterativeModelCheckUsage();
+          return 1;
+        }
+        break;
+      case 'p':
+        option = atoi(util_optarg);
+        if (option==0){
+          partMethod = Imc_PartAll_c;
+        }else if (option==1){
+          partMethod = Imc_PartDepend_c;
+        }else if (option==2){
+          partMethod = Imc_PartInc_c;
+        }else{
+          fprintf(vis_stdout,"** imc warning : Partition option -p %d",
+                  option);
+          fprintf(vis_stdout," is not defined.\n");
+          IterativeModelCheckUsage();
+          return 1;
+        }
+        break;
+      case 'v':
+        option = atoi(util_optarg);
+        if (option == 0) verbosity = Imc_VerbosityNone_c;
+        else if (option == 1) verbosity = Imc_VerbosityMin_c;
+	      else if (option == 2) verbosity = Imc_VerbosityMax_c;
+        else{
+	        fprintf(vis_stdout,"** imc warning : Verbosity option -v %d",
+			option);
+		fprintf(vis_stdout, " is not defined.\n");
+          IterativeModelCheckUsage();
+          return 1;
+	      }
+        break;
+      case 'D':
+      	option = atoi(util_optarg);
+	      if (option == 0) dcLevel = Imc_DcLevelNone_c;
+        else if (option == 1) dcLevel = Imc_DcLevelRch_c;
+	      else if (option == 2) dcLevel = Imc_DcLevelMax_c;
+	      else if (option == 3) dcLevel = Imc_DcLevelArdc_c;
+        else{
+	        fprintf(vis_stdout,"** imc warning : Don't care option -D %d",
+			option);
+		fprintf(vis_stdout, " is not defined.\n");
+          IterativeModelCheckUsage();
+          return 1;
+	      }
+        break;
+      case 'g':
+        option = atoi(util_optarg);
+        if (option == 0) graphType = Imc_GraphNDOG_c;
+        else if (option == 1) graphType = Imc_GraphPDOG_c;
+        else if (option == 2) graphType = Imc_GraphMOG_c;
+        else{
+	        fprintf(vis_stdout,"** imc warning : Graph type option -g %d",
+			option);
+		fprintf(vis_stdout," is not defined.\n");
+          IterativeModelCheckUsage();
+          return 1;
+	      }
+        break;    
+      default:
+	      IterativeModelCheckUsage();
+	      return 1;
+    }
+  }
+
+  /* Make sure the CTL file has been provided */
+  if (argc == util_optind) {
+    IterativeModelCheckUsage();
+    return 1;
+  }
+  else {
+    ctlFileName = argv[util_optind];
+  }
+
+  /* 
+   * Obtain the network from the hierarchy manager 
+   */
+  network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+  if (network == NIL(Ntk_Network_t)) {
+    return 1;
+  }
+
+  /* 
+   * Read in the array of CTL formulas provided in ctlFileName 
+   */
+  ctlFile = Cmd_FileOpen(ctlFileName, "r", NIL(char *), 0);
+  if (ctlFile == NIL(FILE)) {
+    return 1;
+  }
+  ctlFormulaArray = Ctlp_FileParseFormulaArray(ctlFile);
+  fclose(ctlFile);
+
+  if (ctlFormulaArray == NIL(array_t)) {
+    fprintf(vis_stderr, "** imc error: Error while parsing ctl formulas in file.\n");
+    return 1;
+  } 
+
+  /* 
+   * Start the timer. 
+   */
+  if (timeOutPeriod > 0) {
+    (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
+    (void) alarm(timeOutPeriod);
+
+    /* The second time setjmp is called, it returns here !!*/
+    if (setjmp(timeOutEnv) > 0) {
+      (void) fprintf(vis_stdout, "IMC: Timeout occurred after %d seconds.\n",
+		     timeOutPeriod);
+      alarm(0);
+
+      /* Note that there is a huge memory leak here. */
+      Ctlp_FormulaArrayFree(ctlFormulaArray);
+      return 1;
+    } 
+  }
+
+  currentNode = Hrc_ManagerReadCurrentNode(*hmgr);
+  modelName = Hrc_NodeReadModelName(currentNode);
+  partition = Part_NetworkReadPartition(network);
+
+  exactFsm = NIL(Fsm_Fsm_t);
+  reducedFsm = NIL(Fsm_Fsm_t);
+  careStates = NIL(mdd_t);
+
+  if ((computeExact)&&(partMethod == Imc_PartInc_c)){
+    partMethod = Imc_PartDepend_c;
+  }
+
+  if ((dcLevel != Imc_DcLevelNone_c) && (partMethod == Imc_PartInc_c)){
+    partMethod = Imc_PartDepend_c;
+  }
+
+  if (partition == NIL(graph_t) && (partMethod != Imc_PartInc_c)){
+    if (partMethod == Imc_PartAll_c){
+
+      partition = Part_NetworkCreatePartition(network, currentNode, modelName,
+                                          (lsList)0, (lsList)0, NIL(mdd_t),
+                                          Part_InOut_c, (lsList)0, FALSE,
+                                          verbosity, 0);
+      Ntk_NetworkAddApplInfo(network, PART_NETWORK_APPL_KEY,
+                          (Ntk_ApplInfoFreeFn) Part_PartitionFreeCallback,
+                          (void *) partition);
+
+    }else if (partMethod == Imc_PartDepend_c){
+      partition = Part_PartCreatePartitionWithCTL(hmgr, Part_InOut_c, verbosity, 
+                                      0, FALSE, ctlFormulaArray, NIL(array_t));
+      /* Register the partition in the network if any */
+      Ntk_NetworkAddApplInfo(network, PART_NETWORK_APPL_KEY,
+                          (Ntk_ApplInfoFreeFn) Part_PartitionFreeCallback,
+                          (void *) partition);
+    }
+  }
+ 
+  if (partition != NIL(graph_t)){ 
+    exactFsm = Fsm_NetworkReadOrCreateFsm(network); 
+    reducedFsm = Mc_ConstructReducedFsm(network, ctlFormulaArray);
+    if (reducedFsm==NIL(Fsm_Fsm_t)){
+      reducedFsm = exactFsm;
+    }
+
+    /*
+     * Check whether the fairness was read. Fairnedd is ignored.
+     */
+    {
+      Fsm_Fairness_t *fairCons =  Fsm_FsmReadFairnessConstraint(exactFsm);
+      int numOfConj     = Fsm_FairnessReadNumConjunctsOfDisjunct(fairCons, 0);
+      if (numOfConj > 1) {
+        /* Buchi */
+        fprintf(vis_stdout, "** imc warning : Fairness Constraint is not supported.");
+        fprintf(vis_stdout, " Fairness Constraint is ignored.\n");
+      }else if (numOfConj == 1){
+        /* check if fairness is simply default fairness formula, which is TRUE */
+        Ctlp_Formula_t *formula = Fsm_FairnessReadFinallyInfFormula(fairCons, 0, 0);
+        if (Ctlp_FormulaReadType(formula) != Ctlp_TRUE_c){
+    	  fprintf(vis_stdout, "** imc warning : Fairness Constraint is not supported.");
+          fprintf(vis_stdout, " Fairness Constraint is ignored.\n");
+        }
+      }
+    }
+  } 
+
+  globalTimeStart = util_cpu_time();
+
+  if (partition != NIL(graph_t)){
+
+    if (dcLevel == Imc_DcLevelArdc_c){
+      if (verbosity != Imc_VerbosityNone_c){
+        fprintf(vis_stdout, "IMC: Computing approximate reachable states.\n");
+      }
+      ardcOptions = Fsm_ArdcAllocOptionsStruct();
+      Fsm_ArdcGetDefaultOptions(ardcOptions); 
+      initialTime = util_cpu_time();
+      (void) Fsm_ArdcComputeOverApproximateReachableStates(
+	reducedFsm, 0, verbosity, 0, 0, 0, 0, 0, 0, ardcOptions);
+      finalTime = util_cpu_time();
+      if (verbosity != Imc_VerbosityNone_c) {
+        Fsm_ArdcPrintReachabilityResults(reducedFsm, finalTime - initialTime);
+      }
+      /* CW::user is responsible to free Fsm_ArdcGetMdd...
+      careStates
+        = mdd_dup(Fsm_ArdcGetMddOfOverApproximateReachableStates(reducedFsm));
+      */
+      careStates
+        = Fsm_ArdcGetMddOfOverApproximateReachableStates(reducedFsm);
+      
+    }else if (dcLevel >= Imc_DcLevelRch_c){
+      if (verbosity != Imc_VerbosityNone_c){
+         fprintf(vis_stdout, "IMC: Computing exact reachable states.\n");
+      }
+      initialTime = util_cpu_time();
+      careStates = Fsm_FsmComputeReachableStates(reducedFsm,
+  		       			 0, 1, 0, 0, 0, 0, 0,
+  		       			 Fsm_Rch_Default_c, 0, 0,
+  		       			 NIL(array_t), FALSE, NIL(array_t));
+      finalTime = util_cpu_time();
+      if (verbosity != Imc_VerbosityNone_c) {
+        Fsm_FsmReachabilityPrintResults(reducedFsm, finalTime - initialTime,
+				      Fsm_Rch_Default_c);
+      }
+    }else{
+      careStates = NIL(mdd_t);
+    }
+  
+    if (reducedFsm != NIL(Fsm_Fsm_t) && 
+	Fsm_FsmReadImageInfo(reducedFsm) != NIL(Img_ImageInfo_t)) {
+      Fsm_FsmFreeImageInfo(reducedFsm);
+    }
+  }
+
+  ctlNormalForm = Ctlp_FormulaArrayConvertToSimpleExistentialFormTree(
+                  ctlFormulaArray);
+
+  /* 
+   * Loop over every CTL formula in the array 
+   */
+  arrayForEachItem(Ctlp_Formula_t *, ctlNormalForm, i, currentFormula) {
+    Ctlp_FormulaClass formulaClass;    
+    array_t * singleFormulaArray = array_alloc(Ctlp_Formula_t *, 1);
+
+    array_insert(Ctlp_Formula_t *, singleFormulaArray, 0, currentFormula);
+    dagFormula = Ctlp_FormulaArrayConvertToDAG(singleFormulaArray);
+    array_free(singleFormulaArray);
+    formula = array_fetch(Ctlp_Formula_t *, dagFormula, 0);
+    array_free(dagFormula);
+
+    formulaClass = Ctlp_CheckClassOfExistentialFormula(formula);
+
+    /*
+     * Type of approximation needed for verification
+     *
+     *       pDOG  nDOG  MOG
+     * ---------------------
+     * ACTL    L     U    B
+     * ECTL    U     L    B
+     * Mixed   B     B    B
+     */
+
+    if ((formulaClass == Ctlp_Mixed_c) || (graphType == Imc_GraphMOG_c)){
+      needLower = TRUE;
+      needUpper = TRUE;
+
+    }else if (((formulaClass == Ctlp_ACTL_c) && (graphType == Imc_GraphPDOG_c)) ||
+        ((formulaClass == Ctlp_ECTL_c) && (graphType == Imc_GraphNDOG_c))){
+      needLower = TRUE;
+      needUpper = FALSE;      
+
+    }else{
+      needLower = FALSE;
+      needUpper = TRUE;
+    }            
+
+    if (!Mc_FormulaStaticSemanticCheckOnNetwork(formula,network,FALSE)){
+      (void) fprintf(vis_stdout, "\n** imc error: Error in parsing formula:\n%s\n", 
+                     error_string());
+      error_init();
+      continue;
+    }
+
+    error_init();
+    initialTime = util_cpu_time();
+   
+    orgFormula = array_fetch(Ctlp_Formula_t *, ctlFormulaArray, i);
+
+    Imc_ImcEvaluateFormulaLinearRefine(network, orgFormula, formula, 
+      formulaClass, incrementalSize, verbosity, refine, careStates, reducedFsm,
+      dcLevel, graphType, lowerMethod, upperMethod, computeExact, needLower, 
+      needUpper, partMethod, currentNode, modelName);
+
+    finalTime = util_cpu_time();
+    if(verbosity != Imc_VerbosityNone_c) {
+      (void) fprintf(vis_stdout, "%-20s%10ld\n\n",
+		     "IMC: Verification time for this formula =",
+		     (finalTime - initialTime) / 1000);
+    }
+    fprintf(vis_stdout, "\n");
+    
+  } /* End of arrayForEachItem in ctlFormulaArray */
+
+  if (careStates)
+    mdd_free(careStates); /* FIXED */
+
+  globalTimeEnd = util_cpu_time();
+
+  if (verbosity != Imc_VerbosityNone_c) {
+     (void) fprintf(vis_stdout, "%-20s%10ld\n\n",
+	 	    "IMC: Total verification time =",
+		    (globalTimeEnd - globalTimeStart) / 1000);
+  } 
+  
+  /* Deactivate the alarm */
+  alarm(0);
+
+  if ((reducedFsm != NIL(Fsm_Fsm_t)) && (exactFsm != reducedFsm)){
+    Fsm_FsmFree(reducedFsm);
+  }
+
+  Ctlp_FormulaArrayFree(ctlFormulaArray);
+  Ctlp_FormulaArrayFree(ctlNormalForm);
+  error_cleanup();
+
+  /* normal exit */
+  return 0;
+}
+
+/**Function********************************************************************
+
+   Synopsis     [Prints the usage of the iterative_model_checking command.]
+   
+   SideEffects  []
+   
+   SeeAlso      [CommandImc]
+
+******************************************************************************/
+static void
+IterativeModelCheckUsage(void)
+{
+  fprintf(vis_stderr, "usage: iterative_model_check [-h] [-x]");
+  fprintf(vis_stderr, "[-t <secs>] [-v <number>] [-D <number>] [-r <number>]");
+  fprintf(vis_stderr, "[-i <number] [-l <number] [-p <number] [-g <number] ctlfile\n");
+  fprintf(vis_stderr, "   -h        print the command usage\n");
+  fprintf(vis_stderr, "   -x        Exact verification\n");
+  fprintf(vis_stderr, "   -t secs   Seconds allowed for computation\n");
+  fprintf(vis_stderr, "   -v number verbosity level (0:none, 1:mid, 2:max)\n");
+  fprintf(vis_stderr, "   -D number Don't care level. DC's are used to\n");
+  fprintf(vis_stderr, "             reduce transition relation\n");
+  fprintf(vis_stderr, "        0    No don't care (default)\n");
+  fprintf(vis_stderr, "        1    Exact reachable states\n");
+  fprintf(vis_stderr, "        2    Aggressively use DC's\n");
+  fprintf(vis_stderr, "        3    Approximate reachable states\n");
+  fprintf(vis_stderr, "   -r number Refinement method\n");
+  fprintf(vis_stderr, "        0    Static scheduling by name sorting\n");
+  fprintf(vis_stderr, "        1    Static scheduling by latch affinity (defualt)\n");
+  fprintf(vis_stderr, "   -i number Incremental size (default = 4)\n");
+  fprintf(vis_stderr, "   -l number Type of lower-bound approximation method\n");
+  fprintf(vis_stderr, "        0    Take a subset of each transition sub-relation\n");
+  fprintf(vis_stderr, "        1    Take a subset by universal quantification (default)\n");
+  fprintf(vis_stderr, "   -p number Type of partition method\n");
+  fprintf(vis_stderr, "        0    Build all next state functions (default)\n");
+  fprintf(vis_stderr, "        1    Build the next state functions related to formulas\n");
+  fprintf(vis_stderr, "        2    Build the next state functions incrementally\n");
+  fprintf(vis_stderr, "   -g number Type of operational graph\n");
+  fprintf(vis_stderr, "        0    Negative Operational Graph\n");
+  fprintf(vis_stderr, "        1    Positive Operational Graph\n");
+  fprintf(vis_stderr, "        2    Mixed Operational Graph (default)\n");  
+  fprintf(vis_stderr, "   ctlfile   File containing the ctl formulas\n");
+
+  return;
+} /* End of IterativeModelCheckUsage */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Handle the timeout signal.]
+
+  Description [This function is called when the time out occurs. In principle
+  it could do something smarter, but so far it just transfers control to the
+  point in the code where setjmp was called.]
+
+  SideEffects [This function gains control at any point in the middle of the
+  computation, therefore the memory allocated so far leaks.]
+
+******************************************************************************/
+static void
+TimeOutHandle(void)
+{
+  longjmp(timeOutEnv, 1);
+} /* End of TimeOutHandle */
Index: vis_dev/vis-2.3/src/imc/imcImc.c
===================================================================
--- vis_dev/vis-2.3/src/imc/imcImc.c	(revision 14)
+++ vis_dev/vis-2.3/src/imc/imcImc.c	(revision 14)
@@ -0,0 +1,3297 @@
+/**CFile***********************************************************************
+
+  FileName    [imcImc.c]
+
+  PackageName [imc]
+
+  Synopsis    [Incremental Model Checker.]
+
+  Author      [Jae-Young Jang <jjang@vlsi.colorado.edu>]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "imcInt.h" 
+#include "part.h"
+#include "img.h"
+#include "ntm.h"
+
+static char rcsid[] UNUSED = "$Id: imcImc.c,v 1.21 2005/04/27 00:13:01 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int stringCompare(const void * s1, const void * s2);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Verify a formula with incremental refinement.]
+
+  Description [Verify a formula with incremental refinement.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Imc_VerificationResult
+Imc_ImcEvaluateFormulaLinearRefine(
+  Ntk_Network_t         *network,
+  Ctlp_Formula_t        *orgFormula,
+  Ctlp_Formula_t        *formula,
+  Ctlp_FormulaClass     formulaClass,
+  int                   incrementalSize,
+  Imc_VerbosityLevel    verbosity,
+  Imc_RefineMethod	refine,
+  mdd_t			*careStates,
+  Fsm_Fsm_t 		*exactFsm,
+  Imc_DcLevel           dcLevel,
+  Imc_GraphType         graphType,
+  Imc_LowerMethod       lowerMethod,
+  Imc_UpperMethod       upperMethod,
+  boolean               computeExact,
+  boolean               needLower,
+  boolean               needUpper,
+  Imc_PartMethod        partMethod,
+  Hrc_Node_t            *currentNode,
+  char                  *modelName)
+{
+  Imc_Info_t            *imcInfo;
+  st_table              *latchNameTable;
+  int                   numberOfLatches, numberOfIncludedLatches;
+  int			iterationCount;
+  Imc_VerificationResult verification = Imc_VerificationError_c;
+
+  /*
+   * Initialize data structures.
+   */
+  imcInfo = Imc_ImcInfoInitialize(network, formula, formulaClass, verbosity,
+                                  refine, careStates, dcLevel, incrementalSize,
+                                  graphType, exactFsm, lowerMethod, upperMethod,
+                                  computeExact, needLower, needUpper,
+				  partMethod, currentNode, modelName);
+
+  if (imcInfo == NIL(Imc_Info_t))return(Imc_VerificationError_c); /* FIXED */
+
+  numberOfLatches = array_n(imcInfo->systemInfo->latchNameArray);
+ 
+  iterationCount = 1;
+
+  numberOfIncludedLatches = array_n(imcInfo->systemInfo->includedLatchIndex);
+
+  if (verbosity != Imc_VerbosityNone_c) {
+    fprintf(vis_stdout, "IMC : Reduced system has ");
+    Imc_ImcPrintSystemSize(imcInfo);
+  }
+  if(verbosity != Imc_VerbosityNone_c) {
+    fprintf(vis_stdout, "IMC : Approximate system has ");
+    Imc_ImcPrintApproxSystemSize(imcInfo);
+  }
+
+  assert(numberOfLatches >= numberOfIncludedLatches);
+  while(numberOfLatches >= numberOfIncludedLatches) {
+ 
+    /*
+     * verification is one of {Imc_VerificationTrue_c, Imc_VerificationFalse_c,
+     * Imc_VerificationInconclusive_c}.
+     */
+    verification = Imc_ImcVerifyFormula(imcInfo, formula);
+
+    if (verification == Imc_VerificationError_c) {
+
+      (void)fprintf(vis_stdout, "# IMC: formula inconclusive.\n");
+
+      /* Free all */
+      Imc_ImcInfoFree(imcInfo);
+      return verification;
+
+    }else if (verification != Imc_VerificationInconclusive_c){ 
+
+      if ((verification == Imc_VerificationTrue_c)) {
+        (void) fprintf(vis_stdout, "# IMC: formula passed.\n");
+      }else{
+        (void) fprintf(vis_stdout, "# IMC: formula failed.\n");
+      }
+      fprintf(vis_stdout, "IMC : ");
+      Ctlp_FormulaPrint( vis_stdout, orgFormula );
+      fprintf(vis_stdout, "\n");
+      fprintf(vis_stdout, "IMC : ");
+      Ctlp_FormulaPrint( vis_stdout, formula);
+      fprintf(vis_stdout, "\n");
+
+      Imc_ImcInfoFree(imcInfo);
+      return verification;
+    }else{
+      if (numberOfLatches == numberOfIncludedLatches){
+        if (imcInfo->graphType == Imc_GraphPDOG_c){
+          (void) fprintf(vis_stdout, "# IMC: formula passed.\n");
+        }else if (imcInfo->graphType == Imc_GraphNDOG_c){
+          (void) fprintf(vis_stdout, "# IMC: formula failed.\n");
+        }
+        fprintf(vis_stdout, "IMC : ");
+        Ctlp_FormulaPrint( vis_stdout,orgFormula);
+        fprintf(vis_stdout, "\n");
+        fprintf(vis_stdout, "IMC : ");
+        Ctlp_FormulaPrint( vis_stdout, formula); 
+        fprintf(vis_stdout, "\n");
+
+        Imc_ImcInfoFree(imcInfo);
+        return verification;
+      }
+    }       
+
+    latchNameTable = array_fetch(st_table *, 
+                     imcInfo->staticRefineSchedule, iterationCount);
+    
+    Imc_ImcSystemInfoUpdate(imcInfo, latchNameTable);
+
+    /*
+     * Refine the approximate system.
+     */ 
+    if (imcInfo->needUpper){
+      Imc_UpperSystemInfoFree(imcInfo->upperSystemInfo);
+      Imc_UpperSystemInfoInitialize(imcInfo, latchNameTable);
+    }
+
+    if (imcInfo->needLower){
+      Imc_LowerSystemInfoFree(imcInfo->lowerSystemInfo);
+      Imc_LowerSystemInfoInitialize(imcInfo, latchNameTable);
+    }
+
+    Imc_NodeInfoReset(imcInfo);
+
+    numberOfIncludedLatches = 
+        array_n(imcInfo->systemInfo->includedLatchIndex);
+
+    iterationCount++;
+
+    if(verbosity != Imc_VerbosityNone_c) {
+      fprintf(vis_stdout, "IMC : Approximate system has ");
+      Imc_ImcPrintApproxSystemSize(imcInfo);
+    }
+
+  } /* end of while(numberOfLatches >= numberOfIncludedLatches) */
+
+  return(verification); /* FIXED */
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Verify a formula.]
+
+  Description [Verify a formula.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Imc_VerificationResult
+Imc_ImcVerifyFormula(
+  Imc_Info_t *imcInfo,
+  Ctlp_Formula_t *formula)
+{
+  Imc_VerificationResult result;
+
+  if (!Imc_ImcEvaluateCTLFormula(imcInfo, formula, Imc_PolarityPos_c)){
+    return Imc_VerificationError_c;
+  }
+
+  result = Imc_SatCheck(imcInfo, formula);
+
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Check if a formula is true or false.]
+
+  Description [Check if a formula is true or false. If all initial states are
+  contained in a lowerbound satisfying states, a formula is true. If any of
+  initial states is not contained by a upperbound satisfying states, a formula
+  is false. Otherwise, inconclusive.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Imc_VerificationResult
+Imc_SatCheck(
+  Imc_Info_t *imcInfo,
+  Ctlp_Formula_t *formula)
+{
+  mdd_t *initialStates = imcInfo->initialStates;
+  Imc_NodeInfo_t *nodeInfo;
+
+  if (!st_lookup(imcInfo->nodeInfoTable, formula, &nodeInfo)){
+    return Imc_VerificationError_c; /* FIXED */
+  }
+  
+  if (nodeInfo->lowerSat != NIL(mdd_t)){
+    if (mdd_lequal(initialStates, nodeInfo->lowerSat, 1, 1)){
+      return Imc_VerificationTrue_c;
+    }
+  }
+  if (nodeInfo->upperSat != NIL(mdd_t)){
+    if (!mdd_lequal_mod_care_set(initialStates, nodeInfo->upperSat, 1, 1,
+				 imcInfo->modelCareStates)){ /* FIXED */
+      return Imc_VerificationFalse_c;
+    }
+  }
+  return Imc_VerificationInconclusive_c;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes an imcInfo structure for the given method.]
+
+  Description [Regardless of the method type, the initialization procedure
+  starts from constructing set of subsystems. A subsystem contains a subset
+  of vertices of the partition. Based on the subset of vertices, subFSM is
+  created. The subsystems are stored as an array. After the creation of
+  the subsystem array, the function initializes remaining field of 
+  (Imc_Info_t *) imcInfo.
+  The function returns initialized (Imc_Info_t *) imcInfo.]
+
+  SideEffects        []
+
+  SeeAlso     []
+
+******************************************************************************/
+Imc_Info_t *
+Imc_ImcInfoInitialize(
+  Ntk_Network_t	     *network,
+  Ctlp_Formula_t     *formula,
+  Ctlp_FormulaClass  formulaClass,
+  Imc_VerbosityLevel verbosity,
+  Imc_RefineMethod   refine,
+  mdd_t		     *careStates,
+  Imc_DcLevel        dcLevel,
+  int                incrementalSize,
+  Imc_GraphType      graphType,
+  Fsm_Fsm_t          *exactFsm,
+  Imc_LowerMethod    lowerMethod,
+  Imc_UpperMethod    upperMethod,
+  boolean            computeExact,
+  boolean            needLower,
+  boolean            needUpper,
+  Imc_PartMethod     partMethod,
+  Hrc_Node_t         *currentNode, 
+  char               *modelName)
+{
+  int                 i;
+  char                *flagValue;  
+  Imc_Info_t          *imcInfo;
+  mdd_t		      *initialStates;
+  array_t             *scheduleArray;
+  st_table            *latchNameTable;
+  st_table            *newLatchNameTable;
+  st_table            *globalLatchNameTable;
+  array_t             *psMddIdArray;
+  array_t             *nsMddIdArray;
+  array_t             *inputMddIdArray;
+  array_t             *supportMddIdArray;
+  array_t             *preQMddIdArray;
+  array_t             *imgQMddIdArray;
+  Part_CMethod        correlationMethod;
+  Ntk_Node_t          *latch, *input;
+  lsGen               gen;
+  array_t             *latchNameArray;
+
+  imcInfo = ALLOC(Imc_Info_t, 1);
+
+  /*
+   * Initialize 
+   */
+  imcInfo->network         = network;
+  imcInfo->globalFsm       = exactFsm;
+  imcInfo->formulaClass    = formulaClass;
+  imcInfo->incrementalSize = incrementalSize;
+  imcInfo->dcLevel         = dcLevel;
+  imcInfo->refine          = refine;
+  imcInfo->verbosity       = verbosity;
+  imcInfo->upperSystemInfo = NIL(Imc_UpperSystemInfo_t);
+  imcInfo->lowerSystemInfo = NIL(Imc_LowerSystemInfo_t);
+  imcInfo->initialStates   = NIL(mdd_t); 
+  imcInfo->nodeInfoTable   = NIL(st_table);
+  imcInfo->graphType       = graphType;
+  imcInfo->nodeInfoTable   = st_init_table(st_ptrcmp , st_ptrhash);
+  imcInfo->mddMgr          = Ntk_NetworkReadMddManager(network);
+  imcInfo->lowerMethod     = lowerMethod;
+  imcInfo->upperMethod     = upperMethod;
+  imcInfo->currentNode     = currentNode;
+  imcInfo->modelName       = modelName;
+
+  if (exactFsm == NIL(Fsm_Fsm_t)){
+    imcInfo->useLocalFsm = TRUE;
+  }else{
+    imcInfo->useLocalFsm = FALSE;
+  }
+
+  /*
+   * Initialize image and preimage computation info.
+   */
+  if (exactFsm != NIL(Fsm_Fsm_t)){
+    psMddIdArray = array_dup(Fsm_FsmReadPresentStateVars(exactFsm));
+    nsMddIdArray = array_dup(Fsm_FsmReadNextStateVars(exactFsm));
+    inputMddIdArray = array_dup(Fsm_FsmReadInputVars(exactFsm));
+  }else{
+    latchNameArray = array_alloc(char *, 0);
+    psMddIdArray = array_alloc(int, 0);
+    nsMddIdArray = array_alloc(int, 0);
+    inputMddIdArray = array_alloc(int, 0);
+    /* sort by name of latch */
+    Ntk_NetworkForEachLatch(network, gen, latch){
+      array_insert_last(char*, latchNameArray,
+                        Ntk_NodeReadName(latch));
+    }
+
+    array_sort(latchNameArray, stringCompare);
+
+    for (i = 0; i < array_n(latchNameArray); i++) {
+      char *nodeName;
+      nodeName = array_fetch(char *, latchNameArray, i);
+      latch = Ntk_NetworkFindNodeByName(network, nodeName);
+      array_insert_last(int, psMddIdArray,
+                      Ntk_NodeReadMddId(latch));
+      array_insert_last(int, nsMddIdArray,
+                      Ntk_NodeReadMddId(Ntk_NodeReadShadow(latch)));
+    }
+ 
+    array_free(latchNameArray);
+  
+    Ntk_NetworkForEachInput(network, gen, input){
+      array_insert_last(int, inputMddIdArray, Ntk_NodeReadMddId(input));
+    }
+  }
+
+  imgQMddIdArray = array_dup(psMddIdArray);
+  array_append(imgQMddIdArray,inputMddIdArray); 
+
+  supportMddIdArray = array_dup(imgQMddIdArray);
+  array_append(supportMddIdArray,nsMddIdArray);
+
+  preQMddIdArray = array_dup(nsMddIdArray);
+  array_append(preQMddIdArray,inputMddIdArray); 
+
+  array_free(psMddIdArray);
+  array_free(nsMddIdArray);
+  array_free(inputMddIdArray);
+  
+  imcInfo->supportMddIdArray = supportMddIdArray;
+  imcInfo->imgQMddIdArray = imgQMddIdArray;
+  imcInfo->preQMddIdArray = preQMddIdArray;
+  imcInfo->needLower = needLower;
+  imcInfo->needUpper = needUpper;
+  imcInfo->partMethod = partMethod;
+
+  if (careStates == NIL(mdd_t)){
+    imcInfo->modelCareStates = mdd_one(imcInfo->mddMgr);
+  }else{
+    imcInfo->modelCareStates = mdd_dup(careStates);
+  }
+
+  /*
+   * If refine oprion is Imc_RefineLatchRelation_c,
+   * correlation method should be defined.
+   */
+  flagValue = Cmd_FlagReadByName("part_group_correlation_method");
+  if(flagValue == NIL(char)){
+    correlationMethod = Part_CorrelationWithBDD; 
+  }else if (strcmp(flagValue, "support") == 0){
+    correlationMethod = Part_CorrelationWithSupport; 
+  }else if (strcmp(flagValue, "mdd") == 0){
+    correlationMethod = Part_CorrelationWithBDD;
+  }else{
+    correlationMethod = Part_CorrelationWithSupport;
+  }
+
+  if ((refine == Imc_RefineLatchRelation_c) &&
+      (correlationMethod == Part_CorrelationWithBDD) &&
+      (partMethod == Imc_PartInc_c)){
+    correlationMethod = Part_CorrelationWithSupport;
+  }
+  imcInfo->correlationMethod = correlationMethod;
+
+  if (computeExact){
+    scheduleArray = ImcCreateScheduleArray(network, formula, TRUE, 
+                      Imc_RefineLatchRelation_c, verbosity, incrementalSize,
+                      correlationMethod);
+    imcInfo->staticRefineSchedule = NIL(array_t);
+    latchNameTable = array_fetch(st_table *, scheduleArray, 0);
+    st_free_table(latchNameTable);
+    latchNameTable = array_fetch(st_table *, scheduleArray, 1);
+    newLatchNameTable = st_copy(latchNameTable);
+    array_insert(st_table *, scheduleArray, 0, newLatchNameTable);
+
+  }else if (refine == Imc_RefineLatchRelation_c){
+    scheduleArray = ImcCreateScheduleArray(network, formula, FALSE, refine, 
+                    verbosity, incrementalSize, correlationMethod);
+    imcInfo->staticRefineSchedule = scheduleArray;
+
+  }else if (refine == Imc_RefineSort_c){
+    scheduleArray = ImcCreateScheduleArray(network, formula, TRUE, refine, 
+                    verbosity, incrementalSize, correlationMethod);
+    imcInfo->staticRefineSchedule = scheduleArray;
+
+  }else{
+    fprintf(vis_stdout, "** imc error: Unkown refinement method.\n");
+    Imc_ImcInfoFree(imcInfo);
+    return NIL(Imc_Info_t);
+  }
+
+  if (scheduleArray == NIL(array_t)){
+    fprintf(vis_stdout, "** imc error: Can't get an initial system.\n");
+    Imc_ImcInfoFree(imcInfo);
+    return NIL(Imc_Info_t);
+  }
+    
+  globalLatchNameTable = array_fetch(st_table *, scheduleArray, array_n(scheduleArray)-1);
+  latchNameTable = array_fetch(st_table *, scheduleArray, 0);  
+
+  /*
+   * Initialize a total system info.
+   */
+  Imc_SystemInfoInitialize(imcInfo, globalLatchNameTable, latchNameTable);  
+
+  /*
+   * Initialize an initial approximate system info.
+   */
+  if (needUpper){
+    Imc_UpperSystemInfoInitialize(imcInfo,latchNameTable);
+  }
+  if (needLower){
+    Imc_LowerSystemInfoInitialize(imcInfo,latchNameTable);
+  }
+
+  initialStates = Fsm_FsmComputeInitialStates(imcInfo->globalFsm);  
+  if (initialStates == NIL(mdd_t)){
+    fprintf(vis_stdout,"** imc error : System has no initial state.\n");
+    Imc_ImcInfoFree(imcInfo);
+    return NIL(Imc_Info_t);
+  }
+  imcInfo->initialStates = initialStates;  
+
+  if (computeExact){
+    arrayForEachItem(st_table *, scheduleArray, i, latchNameTable){
+      st_free_table(latchNameTable);
+    }
+    array_free(scheduleArray);
+  }
+
+  return(imcInfo);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Free an imcInfo structure for the given method.]
+
+  Description [Free an imcInfo structure for the given method.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Imc_ImcInfoFree(
+  Imc_Info_t *imcInfo)
+{
+  int i;
+  st_table *latchNameTable;
+
+  Imc_UpperSystemInfoFree(imcInfo->upperSystemInfo);
+  Imc_LowerSystemInfoFree(imcInfo->lowerSystemInfo);
+  ImcNodeInfoTableFree(imcInfo->nodeInfoTable);
+  if (imcInfo->initialStates != NIL(mdd_t)) mdd_free(imcInfo->initialStates); 
+
+  if (imcInfo->modelCareStates!=NIL(mdd_t)) mdd_free(imcInfo->modelCareStates);
+  if (imcInfo->staticRefineSchedule != NIL(array_t)){
+    arrayForEachItem(st_table *,imcInfo->staticRefineSchedule, i, latchNameTable){
+      st_free_table(latchNameTable);
+    }
+    array_free(imcInfo->staticRefineSchedule);
+  }
+  if (imcInfo->supportMddIdArray != NIL(array_t)) 
+    array_free(imcInfo->supportMddIdArray);
+  if (imcInfo->imgQMddIdArray != NIL(array_t)) 
+    array_free(imcInfo->imgQMddIdArray);
+  if (imcInfo->preQMddIdArray != NIL(array_t)) 
+    array_free(imcInfo->preQMddIdArray);
+
+  if ((imcInfo->useLocalFsm) && (imcInfo->globalFsm != NIL(Fsm_Fsm_t))){
+    Fsm_FsmSubsystemFree(imcInfo->globalFsm);
+  }
+
+  Imc_SystemInfoFree(imcInfo->systemInfo);
+
+  FREE(imcInfo);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initilalize a system info.]
+
+  Description [Initilalize a system info.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Imc_SystemInfoInitialize(
+  Imc_Info_t *imcInfo,
+  st_table *globalLatchNameTable,
+  st_table *initialLatchNameTable)
+{
+  int i, psMddId, nsMddId, latchSize;
+  char *name, *dataInputName;
+  Ntk_Node_t *node, *latchInput;  
+  Ntk_Network_t *network = imcInfo->network;
+  graph_t *partition = Part_NetworkReadPartition(network);
+  vertex_t *vertex;
+  Mvf_Function_t *mvf;
+  mdd_t *singleTR, *subTR, *tempMdd;
+  st_generator *stGen;
+  lsList latchInputList;
+  lsGen gen;
+  st_table *partNameTable;
+  Imc_SystemInfo_t *systemInfo;
+  array_t *bddIdArray;
+  array_t *latchNameArray = 
+           array_alloc(char *, st_count(globalLatchNameTable));
+  st_table *latchNameTable = st_init_table(strcmp, st_strhash );
+  st_table *latchInputTable = st_init_table(st_ptrcmp, st_ptrhash );
+  st_table *nsMddIdToIndex = st_init_table(st_numcmp, st_numhash);
+  st_table *psMddIdToIndex = st_init_table(st_numcmp, st_numhash);
+  array_t *latchNodeArray = 
+           array_alloc(Ntk_Node_t *, st_count(globalLatchNameTable));
+  array_t *nsMddIdArray = array_alloc(int,st_count(globalLatchNameTable));
+  array_t *psMddIdArray = array_alloc(int,st_count(globalLatchNameTable));
+  array_t *TRArray = array_alloc(mdd_t *,st_count(globalLatchNameTable));
+  array_t *lowerTRArray = array_alloc(mdd_t *,st_count(globalLatchNameTable));
+  array_t *mvfArray = array_alloc(mdd_t *,st_count(globalLatchNameTable));
+  array_t *latchSizeArray = array_alloc(int,st_count(globalLatchNameTable));
+  array_t *includedLatchIndex = array_alloc(int, 0);
+  array_t *includedNsMddId = array_alloc(int, 0);
+  array_t *excludedLatchIndex = array_alloc(int, 0);
+  array_t *excludedNsMddId = array_alloc(int, 0);
+  array_t *excludedPsMddId = array_alloc(int, 0);
+  array_t *includedPsMddId = array_alloc(int, 0);
+  st_table *excludedPsMddIdTable = st_init_table(st_numcmp, st_numhash);
+
+  systemInfo = ALLOC(Imc_SystemInfo_t, 1);
+
+  st_foreach_item(globalLatchNameTable, stGen, &name, NIL(char *)){
+    array_insert_last(char *, latchNameArray, name);
+  }
+
+  array_sort(latchNameArray, stringCompare);
+
+  if (partition == NIL(graph_t)){
+    if ((imcInfo->partMethod == Imc_PartInc_c) &&
+        !((imcInfo->needLower) && 
+         (imcInfo->lowerMethod != Imc_LowerUniversalQuantification_c))){
+      partNameTable = initialLatchNameTable;
+    }else{
+      partNameTable = globalLatchNameTable;
+    }
+    st_foreach_item(partNameTable, stGen, &name, NIL(char *)){
+      node = Ntk_NetworkFindNodeByName(network, name);
+      latchInput = Ntk_LatchReadDataInput(node);
+      st_insert(latchInputTable, (char *)latchInput, (char *)(long)(-1));
+    }
+    latchInputList = lsCreate();
+    st_foreach_item(latchInputTable, stGen, &node, NULL){
+      lsNewEnd(latchInputList, (lsGeneric)node, LS_NH);
+    }
+    st_free_table(latchInputTable);
+    Ntk_NetworkForEachCombOutput(network, gen, node){
+      if (Ntk_NodeTestIsLatchInitialInput(node)){
+        lsNewEnd(latchInputList, (lsGeneric)node, LS_NH);
+      }
+    }
+
+    partition = Part_NetworkCreatePartition(network, imcInfo->currentNode, 
+                  imcInfo->modelName, latchInputList, (lsList)0, NIL(mdd_t),
+                  Part_InOut_c, (lsList)0, FALSE, 0, 0);
+    lsDestroy(latchInputList, (void (*)(lsGeneric))0); 
+    
+    Ntk_NetworkAddApplInfo(network, PART_NETWORK_APPL_KEY,
+                  (Ntk_ApplInfoFreeFn) Part_PartitionFreeCallback,
+                  (void *) partition);
+
+    imcInfo->globalFsm = Fsm_FsmCreateSubsystemFromNetwork(network,partition,
+                                                    partNameTable, FALSE, 0);
+
+    imcInfo->useLocalFsm = TRUE;
+  }else{
+    st_foreach_item(initialLatchNameTable, stGen, &name, NIL(char *)){
+      node = Ntk_NetworkFindNodeByName(network, name);
+      latchInput = Ntk_LatchReadDataInput(node);
+      st_insert(latchInputTable, (char *)latchInput, (char *)(long)(-1));
+    }
+    latchInputList = lsCreate();
+    st_foreach_item(latchInputTable, stGen, &node, NIL(char *)){
+      lsNewEnd(latchInputList, (lsGeneric)node, LS_NH);
+    }
+    st_free_table(latchInputTable);
+    Ntk_NetworkForEachCombOutput(network, gen, node){
+      if (Ntk_NodeTestIsLatchInitialInput(node)){
+        lsNewEnd(latchInputList, (lsGeneric)node, LS_NH);
+      }
+    }
+    (void) Part_PartitionChangeRoots(network, partition,
+				     latchInputList, 0);
+    lsDestroy(latchInputList, (void (*)(lsGeneric))0);
+  }
+
+  for (i=0;i<array_n(latchNameArray);i++){
+    name = array_fetch(char *, latchNameArray, i);
+    node = Ntk_NetworkFindNodeByName(network, name);
+    psMddId = Ntk_NodeReadMddId(node);
+    nsMddId = Ntk_NodeReadMddId(Ntk_NodeReadShadow(node));
+
+    dataInputName = Ntk_NodeReadName(Ntk_LatchReadDataInput(node));
+
+    if (st_is_member(initialLatchNameTable, name)) { 
+      vertex = Part_PartitionFindVertexByName(partition, dataInputName);
+      mvf = Part_VertexReadFunction(vertex);      
+      singleTR = Mvf_FunctionBuildRelationWithVariable(mvf, nsMddId);
+      array_insert(mdd_t *, TRArray, i, 
+                   bdd_minimize(singleTR, imcInfo->modelCareStates));
+      array_insert(mdd_t *, lowerTRArray, i, NIL(mdd_t));
+      array_insert(Mvf_Function_t *, mvfArray, i, NIL(Mvf_Function_t));
+      mdd_free(singleTR);
+    }else{
+      array_insert(Mvf_Function_t *, mvfArray, i, NIL(Mvf_Function_t));
+      array_insert(mdd_t *, lowerTRArray, i, NIL(mdd_t));
+      array_insert(mdd_t *, TRArray, i, NIL(mdd_t));
+    }
+    
+
+    if (!st_is_member(initialLatchNameTable, name)){
+      if (imcInfo->needLower && 
+         imcInfo->lowerMethod != Imc_LowerUniversalQuantification_c){
+        singleTR = array_fetch(mdd_t *, TRArray, i);
+	if (singleTR == NIL(mdd_t)){
+          vertex = Part_PartitionFindVertexByName(partition, dataInputName);
+	  mvf = Part_VertexReadFunction(vertex);                  
+	  singleTR = Mvf_FunctionBuildRelationWithVariable(mvf, nsMddId);
+	  tempMdd = mdd_and(singleTR, imcInfo->modelCareStates, 1, 1);
+	  mdd_free(singleTR);
+	}else{
+          tempMdd = mdd_and(singleTR, imcInfo->modelCareStates, 1, 1);
+	}           
+	subTR = bdd_approx_remap_ua(tempMdd,(bdd_approx_dir_t)BDD_UNDER_APPROX,
+				    array_n(imcInfo->supportMddIdArray), 0, 1.0);
+	mdd_free(tempMdd);
+	tempMdd = bdd_minimize(subTR, imcInfo->modelCareStates);
+	mdd_free(subTR);
+	subTR = tempMdd;
+	array_insert(mdd_t *, lowerTRArray, i, subTR);
+	array_insert(Mvf_Function_t *, mvfArray, i, NIL(Mvf_Function_t));
+      }   
+    }
+
+    if (st_is_member(initialLatchNameTable, name)){
+      array_insert_last(int, includedLatchIndex, i);
+      array_insert_last(int, includedNsMddId, nsMddId);
+      array_insert_last(int, includedPsMddId, psMddId);
+    }else{
+      array_insert_last(int, excludedLatchIndex, i);
+      array_insert_last(int, excludedNsMddId, nsMddId);
+      array_insert_last(int, excludedPsMddId, psMddId);
+      st_insert(excludedPsMddIdTable, (char *)(long)psMddId, 
+                      (char *)0);
+    }      
+    bddIdArray = mdd_id_to_bdd_id_array(imcInfo->mddMgr, nsMddId);
+    latchSize = array_n(bddIdArray);
+    array_free(bddIdArray);
+    st_insert(latchNameTable, name, (char *)(long)i);
+    st_insert(nsMddIdToIndex,(char *)(long)nsMddId, (char *)(long)i); 
+    st_insert(psMddIdToIndex,(char *)(long)psMddId, (char *)(long)i);
+    array_insert(Ntk_Node_t *, latchNodeArray, i, node);
+    array_insert(int, latchSizeArray, i, latchSize);
+ 
+    array_insert(int, nsMddIdArray, i, nsMddId);
+    array_insert(int, psMddIdArray, i, psMddId);
+  }
+  
+  systemInfo->latchNameTable = latchNameTable;
+  systemInfo->latchNameArray = latchNameArray;
+  systemInfo->latchNodeArray = latchNodeArray;  
+  systemInfo->nsMddIdArray = nsMddIdArray;
+  systemInfo->psMddIdArray = psMddIdArray;
+  systemInfo->inputMddIdArray = 
+    array_dup(Fsm_FsmReadInputVars(imcInfo->globalFsm));
+  systemInfo->TRArray = TRArray;
+  systemInfo->lowerTRArray = lowerTRArray;
+  systemInfo->mvfArray = mvfArray;
+  systemInfo->latchSizeArray = latchSizeArray;
+  systemInfo->nsMddIdToIndex = nsMddIdToIndex;
+  systemInfo->psMddIdToIndex = psMddIdToIndex;
+  systemInfo->excludedLatchIndex  = excludedLatchIndex;
+  systemInfo->includedLatchIndex  = includedLatchIndex; 
+  systemInfo->excludedNsMddId  = excludedNsMddId;
+  systemInfo->includedNsMddId  = includedNsMddId; 
+  systemInfo->excludedPsMddId  = excludedPsMddId; 
+  systemInfo->includedPsMddId  = includedPsMddId; 
+  systemInfo->excludedPsMddIdTable  = excludedPsMddIdTable;
+
+  imcInfo->systemInfo = systemInfo;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Free a system info.]
+
+  Description [Free a system info.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Imc_SystemInfoFree(
+  Imc_SystemInfo_t *systemInfo)
+{
+  int i;
+  mdd_t *singleTR;
+
+  if (systemInfo->latchNameTable != NIL(st_table))
+    st_free_table(systemInfo->latchNameTable);
+  if (systemInfo->latchNameArray != NIL(array_t))
+    array_free(systemInfo->latchNameArray);
+  if (systemInfo->latchNodeArray != NIL(array_t))
+    array_free(systemInfo->latchNodeArray);
+  if (systemInfo->nsMddIdArray != NIL(array_t))
+    array_free(systemInfo->nsMddIdArray);
+  if (systemInfo->psMddIdArray != NIL(array_t))
+    array_free(systemInfo->psMddIdArray);
+  if (systemInfo->inputMddIdArray != NIL(array_t))
+    array_free(systemInfo->inputMddIdArray);
+  if (systemInfo->TRArray != NIL(array_t)){
+    for(i=0;i<array_n(systemInfo->TRArray);i++){
+      singleTR = array_fetch(mdd_t *, systemInfo->TRArray, i);
+      if (singleTR != NIL(mdd_t)){
+        mdd_free(singleTR);
+      }
+    }
+    array_free(systemInfo->TRArray);   
+  }
+
+  if (systemInfo->lowerTRArray != NIL(array_t)){
+    for(i=0;i<array_n(systemInfo->lowerTRArray);i++){
+      singleTR = array_fetch(mdd_t *, systemInfo->lowerTRArray, i);
+      if (singleTR != NIL(mdd_t)){
+        mdd_free(singleTR);
+      }
+    }
+    array_free(systemInfo->lowerTRArray);
+  }
+
+  if (systemInfo->mvfArray != NIL(array_t))
+    array_free(systemInfo->mvfArray);
+  if (systemInfo->latchSizeArray != NIL(array_t))
+    array_free(systemInfo->latchSizeArray);
+  if (systemInfo->nsMddIdToIndex != NIL(st_table))
+    st_free_table(systemInfo->nsMddIdToIndex);
+  if (systemInfo->psMddIdToIndex != NIL(st_table))
+    st_free_table(systemInfo->psMddIdToIndex);
+  if (systemInfo->excludedLatchIndex != NIL(array_t))
+    array_free(systemInfo->excludedLatchIndex);
+  if (systemInfo->includedLatchIndex != NIL(array_t))
+    array_free(systemInfo->includedLatchIndex);
+  if (systemInfo->excludedNsMddId != NIL(array_t))
+    array_free(systemInfo->excludedNsMddId);
+  if (systemInfo->includedNsMddId != NIL(array_t))
+    array_free(systemInfo->includedNsMddId);
+  if (systemInfo->excludedPsMddId != NIL(array_t))
+     array_free(systemInfo->excludedPsMddId);
+  if (systemInfo->includedPsMddId != NIL(array_t))
+     array_free(systemInfo->includedPsMddId);
+  if (systemInfo->excludedPsMddIdTable != NIL(st_table))
+    st_free_table(systemInfo->excludedPsMddIdTable);
+
+  FREE(systemInfo);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Update a system info.]
+
+  Description [Update a system info. All variables in newLatchNameTable are now
+  computed exactly.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Imc_ImcSystemInfoUpdate(
+  Imc_Info_t *imcInfo,
+  st_table *newLatchNameTable)
+{
+  int i, nsMddId, psMddId, index;
+  char *name, *dataInputName;
+  mdd_t *singleTR;
+  st_generator *stGen;
+  Ntk_Node_t *node, *latchInput;
+  Mvf_Function_t *mvf;
+  vertex_t *vertex;
+  lsList latchInputList;
+  lsGen gen;
+  graph_t *partition = Part_NetworkReadPartition(imcInfo->network);
+  st_table *latchInputTable;
+  Imc_SystemInfo_t *systemInfo = imcInfo->systemInfo;
+
+  if ((imcInfo->partMethod == Imc_PartInc_c) &&
+      !(imcInfo->needLower && 
+        imcInfo->lowerMethod != Imc_LowerUniversalQuantification_c)){
+    latchInputTable = st_init_table(st_ptrcmp, st_ptrhash );
+    st_foreach_item(newLatchNameTable, stGen, &name, NIL(char *)){
+      node = Ntk_NetworkFindNodeByName(imcInfo->network, name);
+      latchInput = Ntk_LatchReadDataInput(node);
+      st_insert(latchInputTable, (char *)latchInput, (char *)(long)(-1));
+    }
+    latchInputList = lsCreate();
+    st_foreach_item(latchInputTable, stGen, &node, NULL){
+      lsNewEnd(latchInputList, (lsGeneric)node, LS_NH);
+    }
+    st_free_table(latchInputTable);
+    Ntk_NetworkForEachCombOutput(imcInfo->network, gen, node){
+      if (Ntk_NodeTestIsLatchInitialInput(node)){
+        lsNewEnd(latchInputList, (lsGeneric)node, LS_NH);
+      }
+    }
+    (void) Part_PartitionChangeRoots(imcInfo->network, partition,
+				     latchInputList, 0);
+    lsDestroy(latchInputList, (void (*)(lsGeneric))0); 
+  }
+
+  if (systemInfo->excludedLatchIndex != NIL(array_t)){
+    array_free(systemInfo->excludedLatchIndex);
+    systemInfo->excludedLatchIndex = array_alloc(int, 0);
+  }
+  if (systemInfo->includedLatchIndex != NIL(array_t)){
+    array_free(systemInfo->includedLatchIndex);
+    systemInfo->includedLatchIndex = array_alloc(int, 0);
+  }
+  if (systemInfo->excludedNsMddId != NIL(array_t)){
+    array_free(systemInfo->excludedNsMddId);
+    systemInfo->excludedNsMddId = array_alloc(int, 0);
+  }
+  if (systemInfo->includedNsMddId != NIL(array_t)){
+    array_free(systemInfo->includedNsMddId);
+    systemInfo->includedNsMddId = array_alloc(int, 0);
+  }
+  if (systemInfo->excludedPsMddId != NIL(array_t)){
+     array_free(systemInfo->excludedPsMddId);
+     systemInfo->excludedPsMddId = array_alloc(int, 0);
+  }
+  if (systemInfo->includedPsMddId != NIL(array_t)){
+     array_free(systemInfo->includedPsMddId);
+     systemInfo->includedPsMddId = array_alloc(int, 0);
+  }
+  if (systemInfo->excludedPsMddIdTable != NIL(st_table)){
+    st_free_table(systemInfo->excludedPsMddIdTable);
+    systemInfo->excludedPsMddIdTable = st_init_table(st_numcmp, st_numhash);
+  }
+  
+  for(i=0;i<array_n(imcInfo->systemInfo->latchNameArray);i++){
+    name = array_fetch(char *,imcInfo->systemInfo->latchNameArray,i);
+    node = Ntk_NetworkFindNodeByName(imcInfo->network, name);
+    psMddId = Ntk_NodeReadMddId(node);
+    nsMddId = Ntk_NodeReadMddId(Ntk_NodeReadShadow(node));
+
+    if (st_is_member(newLatchNameTable, name)){
+      array_insert_last(int, systemInfo->includedLatchIndex, i);
+      array_insert_last(int, systemInfo->includedNsMddId, nsMddId);
+      array_insert_last(int, systemInfo->includedPsMddId, psMddId);
+    }else{
+      array_insert_last(int, systemInfo->excludedLatchIndex, i);
+      array_insert_last(int, systemInfo->excludedNsMddId, nsMddId);
+      array_insert_last(int, systemInfo->excludedPsMddId, psMddId);
+      st_insert(systemInfo->excludedPsMddIdTable, (char *)(long)psMddId, 
+                      (char *)0);
+    }      
+  }
+     
+  st_foreach_item(newLatchNameTable, stGen, &name, NIL(char *)){
+    st_lookup_int(imcInfo->systemInfo->latchNameTable,name, &index);
+    nsMddId = array_fetch(int, imcInfo->systemInfo->nsMddIdArray, index);
+    psMddId = array_fetch(int, imcInfo->systemInfo->psMddIdArray, index);
+
+    mvf = array_fetch(Mvf_Function_t *, imcInfo->systemInfo->mvfArray, index);
+
+    if (mvf == NIL(Mvf_Function_t)){
+      node = Ntk_NetworkFindNodeByName(imcInfo->network, name); 
+      latchInput = Ntk_LatchReadDataInput(node);
+      dataInputName = Ntk_NodeReadName(Ntk_LatchReadDataInput(node));  
+      vertex = Part_PartitionFindVertexByName(partition, dataInputName);
+      mvf = Part_VertexReadFunction(vertex);
+    }
+
+    singleTR = array_fetch(mdd_t *, imcInfo->systemInfo->TRArray, index);
+
+    if (singleTR == NIL(mdd_t)){ 
+      singleTR = Mvf_FunctionBuildRelationWithVariable(mvf, nsMddId);
+      array_insert(mdd_t *, imcInfo->systemInfo->TRArray, index, 
+                   bdd_minimize(singleTR, imcInfo->modelCareStates));
+
+      array_insert(Mvf_Function_t *, imcInfo->systemInfo->mvfArray, index, 
+                   NIL(Mvf_Function_t));
+      mdd_free(singleTR);
+    }
+
+    singleTR = array_fetch(mdd_t *, imcInfo->systemInfo->lowerTRArray, index);
+    if (singleTR != NIL(mdd_t)){ 
+      mdd_free(singleTR);
+      array_insert(mdd_t *,imcInfo->systemInfo->lowerTRArray,index,NIL(mdd_t));
+    }        
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Initilalize an upper-bound approximate system info.]
+
+  Description [Initilalize an upper-bound approximate system info.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Imc_UpperSystemInfoInitialize(
+  Imc_Info_t *imcInfo,
+  st_table   *latchNameTable)
+{
+  int                   i, index;
+  int                   count;
+  char                  *name;
+  Imc_UpperSystemInfo_t *upperSystem;
+  st_table              *globalLatchNameTable;
+  array_t               *globalLatchNameArray;
+  array_t               *relationArray;
+  mdd_t                 *singleTR;
+
+  upperSystem = ALLOC(Imc_UpperSystemInfo_t, 1);
+  upperSystem->systemInfo = imcInfo->systemInfo;
+
+  globalLatchNameTable = imcInfo->systemInfo->latchNameTable;
+  globalLatchNameArray = imcInfo->systemInfo->latchNameArray;
+
+  relationArray = array_alloc(mdd_t *, st_count(latchNameTable));
+
+  count = 0;
+
+  for (i=0;i<array_n(globalLatchNameArray);i++){
+    name = array_fetch(char *, globalLatchNameArray, i);  
+    if (st_is_member(latchNameTable, name)){
+      st_lookup_int(globalLatchNameTable, name, (int *)&index);
+      singleTR = array_fetch(mdd_t *, imcInfo->systemInfo->TRArray, index);
+      array_insert(mdd_t *, relationArray, count++, singleTR);
+    }
+  }
+
+  Img_ClusterRelationArray(imcInfo->mddMgr, Img_Iwls95_c, Img_Backward_c,
+			   relationArray,
+			   imcInfo->systemInfo->psMddIdArray,
+			   imcInfo->systemInfo->nsMddIdArray,
+			   imcInfo->systemInfo->inputMddIdArray,
+			   &upperSystem->bwdRealationArray,
+			   &upperSystem->bwdSmoothVarsArray,
+			   NIL(array_t *), 0); /* FIXED */
+  upperSystem->fwdRealationArray = NIL(array_t);
+  upperSystem->fwdSmoothVarsArray = NIL(array_t);
+  upperSystem->bwdMinimizedRealationArray = NIL(array_t);
+
+  upperSystem->careStates = mdd_dup(imcInfo->modelCareStates);
+
+  array_free(relationArray);
+ 
+  imcInfo->upperSystemInfo = upperSystem;
+
+  if ((imcInfo->verbosity == Imc_VerbosityMin_c) ||
+      (imcInfo->verbosity == Imc_VerbosityMax_c)){
+    fprintf(vis_stdout, "IMC: |BWD Upper T| = %10ld BDD nodes (%-4d components)\n",
+      bdd_size_multiple(upperSystem->bwdRealationArray),
+      array_n(upperSystem->bwdRealationArray));
+  }
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Minimize the size of a upper-bound transition relation.]
+
+  Description [Minimize the size of a upper-bound transition relation with
+  respect to a given care states.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Imc_UpperSystemMinimize(
+  Imc_Info_t *imcInfo,
+  mdd_t *careStates)
+{
+  int i;
+  mdd_t *singleTR;
+  mdd_t *tempMdd;
+  Imc_UpperSystemInfo_t *upperSystem = imcInfo->upperSystemInfo;
+
+  if (mdd_equal(careStates,upperSystem->careStates)) return;
+
+  if (upperSystem->bwdMinimizedRealationArray == NIL(array_t)){
+    upperSystem->bwdMinimizedRealationArray = 
+      array_alloc(mdd_t *, array_n(upperSystem->bwdRealationArray));
+    for (i=0;i<array_n(upperSystem->bwdRealationArray);i++){
+      array_insert(mdd_t *, upperSystem->bwdMinimizedRealationArray, i, NIL(mdd_t));
+    }
+  }
+
+  for (i=0;i<array_n(upperSystem->bwdRealationArray);i++){ 
+    singleTR = array_fetch(mdd_t *, upperSystem->bwdMinimizedRealationArray, i);
+    if (singleTR != NIL(mdd_t)){
+      mdd_free(singleTR);
+    }
+    singleTR = array_fetch(mdd_t *, upperSystem->bwdRealationArray, i);
+    tempMdd = bdd_minimize(singleTR, careStates);
+    array_insert(mdd_t *, upperSystem->bwdMinimizedRealationArray, i, tempMdd);
+  }
+ 
+  if (upperSystem->careStates != NIL(mdd_t)){
+    mdd_free(upperSystem->careStates);
+  }
+  upperSystem->careStates = mdd_dup(careStates);
+
+  if ((imcInfo->verbosity == Imc_VerbosityMin_c) ||
+      (imcInfo->verbosity == Imc_VerbosityMax_c)){
+    fprintf(vis_stdout, "IMC: |Minimized BWD Upper T| = %10ld BDD nodes (%-4d components)\n",
+      bdd_size_multiple(upperSystem->bwdMinimizedRealationArray),
+      array_n(upperSystem->bwdMinimizedRealationArray));
+  }
+
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Free a upper-bound approximate system info.]
+
+  Description [Free a upper-bound approximate system info.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Imc_UpperSystemInfoFree(
+  Imc_UpperSystemInfo_t *upperSystem)
+{
+  int i;
+  array_t *tempArray;
+
+  if (upperSystem == NIL(Imc_UpperSystemInfo_t)) return;   
+
+  if (upperSystem->careStates != NIL(mdd_t)){
+    mdd_free(upperSystem->careStates);
+  }
+
+  if (upperSystem->fwdRealationArray != NIL(array_t)){
+    mdd_array_free(upperSystem->fwdRealationArray);
+    upperSystem->fwdRealationArray = NIL(array_t);
+  }
+  if (upperSystem->fwdSmoothVarsArray != NIL(array_t)){
+    array_free(upperSystem->fwdSmoothVarsArray);
+    upperSystem->fwdSmoothVarsArray = NIL(array_t);
+  }
+  if (upperSystem->bwdRealationArray != NIL(array_t)){
+    mdd_array_free(upperSystem->bwdRealationArray);
+    upperSystem->bwdRealationArray = NIL(array_t);
+  }
+  if (upperSystem->bwdMinimizedRealationArray != NIL(array_t)){
+    mdd_array_free(upperSystem->bwdMinimizedRealationArray);
+    upperSystem->bwdMinimizedRealationArray = NIL(array_t);
+  }
+  if (upperSystem->bwdSmoothVarsArray != NIL(array_t)){
+    for (i=0; i<array_n(upperSystem->bwdSmoothVarsArray);i++){
+      tempArray = array_fetch(array_t *, upperSystem->bwdSmoothVarsArray, i);
+      mdd_array_free(tempArray);
+    }
+    array_free(upperSystem->bwdSmoothVarsArray);
+    upperSystem->bwdSmoothVarsArray = NIL(array_t);
+  }
+
+  FREE(upperSystem);
+  return;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initilalize a lower-bound approximate system info.]
+
+  Description [Initilalize a lower-bound approximate system info.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Imc_LowerSystemInfoInitialize(
+  Imc_Info_t *imcInfo,
+  st_table   *latchNameTable)
+{
+  int                   i, index;
+  char                  *name;
+  st_generator          *stGen;
+  mdd_t                 *singleTR;
+  Imc_LowerSystemInfo_t *lowerSystem;
+  array_t               *tempArray;
+  array_t               *relationArray;
+  st_table              *globalLatchNameTable;
+  array_t               *latchNameArray;
+
+  lowerSystem = ALLOC(Imc_LowerSystemInfo_t, 1);
+
+  if ((imcInfo->lowerMethod == Imc_LowerUniversalQuantification_c) &&
+      (imcInfo->upperSystemInfo != NIL(Imc_UpperSystemInfo_t))){
+    lowerSystem->bwdRealationArray = mdd_array_duplicate(
+      imcInfo->upperSystemInfo->bwdRealationArray);
+    lowerSystem->bwdSmoothVarsArray = array_alloc(array_t *,
+      array_n(imcInfo->upperSystemInfo->bwdSmoothVarsArray));
+    for (i=0;i<array_n(imcInfo->upperSystemInfo->bwdSmoothVarsArray);i++){
+      tempArray =  array_fetch(array_t *,
+        imcInfo->upperSystemInfo->bwdSmoothVarsArray, i);
+      array_insert(array_t *, lowerSystem->bwdSmoothVarsArray, i,
+        mdd_array_duplicate(tempArray));
+    }
+    lowerSystem->careStates = mdd_dup(imcInfo->modelCareStates);
+    lowerSystem->bwdMinimizedRealationArray = NIL(array_t);
+    imcInfo->lowerSystemInfo = lowerSystem;
+    return;
+  }
+
+  globalLatchNameTable = imcInfo->systemInfo->latchNameTable;
+
+  latchNameArray = array_alloc(char *, 0);
+  st_foreach_item(globalLatchNameTable, stGen, &name, NIL(char *)){
+    array_insert_last(char *, latchNameArray, name);
+  }
+
+  array_sort(latchNameArray, stringCompare);
+
+  relationArray = array_alloc(mdd_t *, 0);
+
+  for (i=0;i<array_n(latchNameArray);i++){
+    name = array_fetch(char *, latchNameArray, i);
+    st_lookup_int(globalLatchNameTable, name, (int *)&index);
+    if (st_lookup(latchNameTable, name, NIL(char *))){
+      singleTR = array_fetch(mdd_t *, imcInfo->systemInfo->TRArray, index);
+    }else{
+      singleTR = array_fetch(mdd_t *, imcInfo->systemInfo->lowerTRArray, index);
+    }
+    if (singleTR != NIL(mdd_t)){
+      array_insert_last(mdd_t *, relationArray, singleTR);
+    }
+  }
+
+  array_free(latchNameArray);
+
+  Img_ClusterRelationArray(imcInfo->mddMgr, Img_Iwls95_c, Img_Backward_c,
+			   relationArray,
+			   imcInfo->systemInfo->psMddIdArray,
+			   imcInfo->systemInfo->nsMddIdArray,
+			   imcInfo->systemInfo->inputMddIdArray,
+			   &lowerSystem->bwdRealationArray,
+			   &lowerSystem->bwdSmoothVarsArray,
+			   NIL(array_t *), 0); /* FIXED */
+  lowerSystem->bwdMinimizedRealationArray = NIL(array_t);
+
+  lowerSystem->careStates = mdd_dup(imcInfo->modelCareStates);;
+
+  imcInfo->lowerSystemInfo = lowerSystem;
+
+  if ((imcInfo->verbosity == Imc_VerbosityMin_c) ||
+      (imcInfo->verbosity == Imc_VerbosityMax_c)){
+    fprintf(vis_stdout, "IMC: |BWD Lower T| = %10ld BDD nodes (%-4d components)\n",
+      bdd_size_multiple(lowerSystem->bwdRealationArray),
+      array_n(lowerSystem->bwdRealationArray));
+  }
+
+  array_free(relationArray); /* Should be freed here, I guess, Chao Wang */
+  
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Minimize the size of a lower-bound transition relation.]
+
+  Description [Minimize the size of a lower-bound transition relation with
+  respect to a given care states.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Imc_LowerSystemMinimize(
+  Imc_Info_t *imcInfo,
+  mdd_t *careStates)
+{
+  int i;
+  mdd_t *singleTR;
+  mdd_t *tempMdd;
+
+  Imc_LowerSystemInfo_t *lowerSystem = imcInfo->lowerSystemInfo;
+
+  if (mdd_equal(careStates,lowerSystem->careStates)) return;
+
+  if (lowerSystem->bwdMinimizedRealationArray == NIL(array_t)){
+    lowerSystem->bwdMinimizedRealationArray = 
+      array_alloc(mdd_t *, array_n(lowerSystem->bwdRealationArray));
+    for (i=0;i<array_n(lowerSystem->bwdRealationArray);i++){
+      array_insert(mdd_t *, lowerSystem->bwdMinimizedRealationArray, i, NIL(mdd_t));
+    }
+  } 
+
+  for (i=0;i<array_n(lowerSystem->bwdRealationArray);i++){
+    singleTR = array_fetch(mdd_t *, lowerSystem->bwdMinimizedRealationArray, i);
+    if (singleTR != NIL(mdd_t)){
+      mdd_free(singleTR);
+    }
+    singleTR = array_fetch(mdd_t *, lowerSystem->bwdRealationArray, i);
+    tempMdd = bdd_minimize(singleTR, careStates);
+    array_insert(mdd_t *, lowerSystem->bwdMinimizedRealationArray, i, tempMdd);
+  }
+
+  if (lowerSystem->careStates != NIL(mdd_t)){
+    mdd_free(lowerSystem->careStates);
+  }
+
+  lowerSystem->careStates = mdd_dup(careStates);
+  if ((imcInfo->verbosity == Imc_VerbosityMin_c) ||
+      (imcInfo->verbosity == Imc_VerbosityMax_c)){
+    fprintf(vis_stdout, "IMC: |Minimized BWD Lower T| = %10ld BDD nodes (%-4d components)\n",
+      bdd_size_multiple(lowerSystem->bwdMinimizedRealationArray),
+      array_n(lowerSystem->bwdMinimizedRealationArray));
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Free a lower-bound approximate system info.]
+
+  Description [Free a lower-bound approximate system info.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Imc_LowerSystemInfoFree(
+  Imc_LowerSystemInfo_t *lowerSystem)
+{
+  int i;
+  array_t *tempArray;
+
+  if (lowerSystem == NIL(Imc_LowerSystemInfo_t)) return;   
+
+  if (lowerSystem->careStates != NIL(mdd_t)){
+    mdd_free(lowerSystem->careStates);
+  }
+
+  if (lowerSystem->bwdRealationArray != NIL(array_t)){
+    mdd_array_free(lowerSystem->bwdRealationArray);
+    lowerSystem->bwdRealationArray = NIL(array_t);
+  }
+  if (lowerSystem->bwdMinimizedRealationArray != NIL(array_t)){
+    mdd_array_free(lowerSystem->bwdMinimizedRealationArray);
+    lowerSystem->bwdMinimizedRealationArray = NIL(array_t);
+  }
+  if (lowerSystem->bwdSmoothVarsArray != NIL(array_t)){
+    for (i=0; i<array_n(lowerSystem->bwdSmoothVarsArray);i++){
+      tempArray = array_fetch(array_t *, lowerSystem->bwdSmoothVarsArray, i);
+      mdd_array_free(tempArray);
+    }
+    array_free(lowerSystem->bwdSmoothVarsArray);
+    lowerSystem->bwdSmoothVarsArray = NIL(array_t); /* FIXED */
+  }
+
+  FREE(lowerSystem);
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Initilalize node info.]
+
+  Description [Initilalize node info.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Imc_NodeInfo_t *
+Imc_NodeInfoInitialize(
+  Imc_Polarity polarity)
+{
+  Imc_NodeInfo_t *nodeInfo; 
+
+  nodeInfo = ALLOC(Imc_NodeInfo_t, 1);
+
+  nodeInfo->isExact = FALSE;
+  nodeInfo->polarity = polarity;
+  nodeInfo->upperSat = NIL(mdd_t);
+  nodeInfo->lowerSat = NIL(mdd_t);
+  nodeInfo->propagatedGoalSet = NIL(mdd_t);
+  nodeInfo->propagatedGoalSetTrue = NIL(mdd_t);
+  nodeInfo->goalSet = NIL(mdd_t);
+  nodeInfo->goalSetTrue = NIL(mdd_t);
+  nodeInfo->answer = Imc_VerificationInconclusive_c;
+  nodeInfo->upperDone = FALSE;
+  nodeInfo->lowerDone = FALSE;
+  nodeInfo->pseudoEdges = NIL(mdd_t);
+  return nodeInfo;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reset node info.]
+
+  Description [Reset node info.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Imc_NodeInfoReset(
+  Imc_Info_t *imcInfo)
+{
+  Ctlp_Formula_t *formula;
+  st_table *nodeInfoTable = imcInfo->nodeInfoTable;
+  st_generator *stGen;
+  Imc_NodeInfo_t *nodeInfo;
+
+  st_foreach_item(nodeInfoTable, stGen, &formula, &nodeInfo){
+    if (!nodeInfo->isExact){
+      nodeInfo->lowerDone = FALSE;
+      nodeInfo->upperDone = FALSE;
+    }
+    if (nodeInfo->propagatedGoalSet != NIL(mdd_t)){
+      mdd_free(nodeInfo->propagatedGoalSet);
+      nodeInfo->propagatedGoalSet = NIL(mdd_t);
+    }
+    if (nodeInfo->propagatedGoalSetTrue != NIL(mdd_t)){
+      mdd_free(nodeInfo->propagatedGoalSetTrue);
+      nodeInfo->propagatedGoalSetTrue = NIL(mdd_t);
+    }
+    if (nodeInfo->goalSet != NIL(mdd_t)){
+      mdd_free(nodeInfo->goalSet);
+      nodeInfo->goalSet = NIL(mdd_t);
+    }
+    if (nodeInfo->goalSetTrue != NIL(mdd_t)){
+      mdd_free(nodeInfo->goalSetTrue);
+      nodeInfo->goalSetTrue = NIL(mdd_t);
+    }
+    if (nodeInfo->pseudoEdges != NIL(mdd_t)){
+      mdd_free(nodeInfo->pseudoEdges);
+      nodeInfo->pseudoEdges = NIL(mdd_t);
+    }   
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Free node info.]
+
+  Description [Free node info.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Imc_NodeInfoFree(
+  Imc_NodeInfo_t *nodeInfo)
+{
+  if (nodeInfo->upperSat != NIL(mdd_t)){
+    mdd_free(nodeInfo->upperSat);
+  }
+  if (nodeInfo->lowerSat != NIL(mdd_t)){
+    mdd_free(nodeInfo->lowerSat);
+  }
+  if (nodeInfo->goalSet != NIL(mdd_t)){
+    mdd_free(nodeInfo->goalSet);
+  }
+  if (nodeInfo->goalSetTrue != NIL(mdd_t)){  
+    mdd_free(nodeInfo->goalSetTrue);
+  }
+  if (nodeInfo->propagatedGoalSet != NIL(mdd_t)){
+    mdd_free(nodeInfo->propagatedGoalSet);
+  }
+  if (nodeInfo->propagatedGoalSetTrue != NIL(mdd_t)){  
+    mdd_free(nodeInfo->propagatedGoalSetTrue);
+  }
+  if (nodeInfo->pseudoEdges != NIL(mdd_t)){  
+    mdd_free(nodeInfo->pseudoEdges);
+  }
+  FREE(nodeInfo);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Print global system size.]
+
+  Description [Print global system size by multi-value and boolean value latch.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Imc_ImcPrintSystemSize(
+  Imc_Info_t *imcInfo)
+{
+  array_t *includedBooleanVars;
+  array_t *psMddIdArray = imcInfo->systemInfo->psMddIdArray;
+
+  includedBooleanVars = mdd_id_array_to_bdd_id_array(imcInfo->mddMgr,
+                        psMddIdArray);
+
+  fprintf(vis_stdout, "%d(%d) ",
+	  array_n(psMddIdArray), array_n(includedBooleanVars));
+  fprintf(vis_stdout, "multi-value(boolean) latches.\n");
+
+  array_free(includedBooleanVars);  
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Print upper-system size.]
+
+  Description [Print upper-system size by multi-value and boolean value latch.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Imc_ImcPrintApproxSystemSize(
+  Imc_Info_t *imcInfo)
+{
+  int i, index, psMddId;
+  array_t *includedBooleanVars;
+  array_t *includedPsMddIdArray;
+  array_t *psMddIdArray = imcInfo->systemInfo->psMddIdArray;
+  array_t *includedLatchIndex = imcInfo->systemInfo->includedLatchIndex;
+  
+  includedPsMddIdArray = array_alloc(int,array_n(includedLatchIndex));
+
+  for(i=0;i<array_n(includedLatchIndex);i++){
+    index = array_fetch(int,includedLatchIndex, i); 
+    psMddId = array_fetch(int, psMddIdArray, index); 
+    array_insert(int, includedPsMddIdArray, i, psMddId);
+  }
+ 
+  includedBooleanVars = mdd_id_array_to_bdd_id_array(imcInfo->mddMgr,
+                        includedPsMddIdArray);
+
+  fprintf(vis_stdout, "%d(%d) ",
+	  array_n(includedPsMddIdArray), array_n(includedBooleanVars));
+  fprintf(vis_stdout, "multi-value(boolean) latches.\n");
+
+  array_free(includedPsMddIdArray);
+  array_free(includedBooleanVars);  
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Get a upperbound satisfying states of a given formula.]
+
+  Description [Get a upperbound satisfying states of a given formula if is is
+  already computed.]
+  
+  Comment     []
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Imc_GetUpperSat(
+  Imc_Info_t *imcInfo,
+  Ctlp_Formula_t *formula)
+{
+  Imc_NodeInfo_t *nodeInfo;
+
+  if (!st_lookup(imcInfo->nodeInfoTable, formula, &nodeInfo)){
+    return NIL(mdd_t); 
+  }
+
+  return nodeInfo->upperSat;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Get a lowerbound satisfying states of a given formula.]
+
+  Description [Get a lowerbound satisfying states of a given formula if is is
+  already computed.]
+  
+  Comment     []
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Imc_GetLowerSat(
+  Imc_Info_t *imcInfo,
+  Ctlp_Formula_t *formula)
+{
+  Imc_NodeInfo_t *nodeInfo;
+
+  if (!st_lookup(imcInfo->nodeInfoTable, formula, &nodeInfo)){
+    return NIL(mdd_t); 
+  }
+
+  return nodeInfo->lowerSat;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Model check formula with approxmiations.]
+
+  Description [The routine evaluates given formula with approximations.
+  If polarity is set, upper approximation is computed. Otherwise, lower
+  approximation is computed.]
+  
+  Comment     []
+
+  SideEffects []
+
+******************************************************************************/
+int 
+Imc_ImcEvaluateCTLFormula(
+  Imc_Info_t            *imcInfo,
+  Ctlp_Formula_t        *ctlFormula, 
+  Imc_Polarity          polarity)
+{
+  Imc_Polarity newPolarity, approxPolarity;
+  Ctlp_Formula_t *leftChild, *rightChild;
+  Imc_NodeInfo_t *nodeInfo;
+  Imc_GraphType graphType = imcInfo->graphType;
+
+  if (Ctlp_FormulaReadType( ctlFormula ) == Ctlp_NOT_c){
+    newPolarity = (polarity == Imc_PolarityNeg_c) ? Imc_PolarityPos_c: 
+                  (polarity == Imc_PolarityPos_c) ? Imc_PolarityNeg_c:
+                  polarity;
+  }else{
+    newPolarity = polarity;
+  }
+
+  if (graphType == Imc_GraphNDOG_c){
+    /* In-Ho : Why change the polarity ? */
+    approxPolarity = (polarity == Imc_PolarityNeg_c) ? Imc_PolarityPos_c:
+                     Imc_PolarityNeg_c;
+  }else{
+    approxPolarity = polarity;
+  } 
+
+  if (!st_lookup(imcInfo->nodeInfoTable, ctlFormula, &nodeInfo)){
+    nodeInfo = Imc_NodeInfoInitialize(polarity);
+    st_insert(imcInfo->nodeInfoTable, ctlFormula, nodeInfo);
+  }else if ((nodeInfo->isExact) ||
+            ((approxPolarity == Imc_PolarityNeg_c) && (nodeInfo->lowerDone)) ||
+            ((approxPolarity == Imc_PolarityPos_c) && (nodeInfo->upperDone))){
+    if (imcInfo->verbosity == Imc_VerbosityMax_c){
+      if ((Ctlp_FormulaReadType( ctlFormula ) == Ctlp_ID_c ) ||
+          (Ctlp_FormulaReadType( ctlFormula ) == Ctlp_TRUE_c ) ||
+          (Ctlp_FormulaReadType( ctlFormula ) == Ctlp_FALSE_c )){ 
+        fprintf(vis_stdout, "IMC : node simple already computed.\n");
+      }else if ((Ctlp_FormulaReadType( ctlFormula ) == Ctlp_AND_c ) ||
+                (Ctlp_FormulaReadType( ctlFormula ) == Ctlp_NOT_c )){ 
+        fprintf(vis_stdout, "IMC : node boolean already computed.\n");
+      }else{
+	/* In-Ho : Why only ECTL? */
+        fprintf(vis_stdout, "IMC : node ECTL already computed.\n");
+      }
+    }
+    return 1;
+  }
+  
+  leftChild = Ctlp_FormulaReadLeftChild(ctlFormula);
+  if (leftChild) {
+    if (!Imc_ImcEvaluateCTLFormula(imcInfo,leftChild,newPolarity)){
+       return 0;
+    } 
+  }
+  rightChild = Ctlp_FormulaReadRightChild(ctlFormula);
+  if (rightChild) {
+    if (!Imc_ImcEvaluateCTLFormula(imcInfo,rightChild,newPolarity)){ 
+       return 0;
+    } 
+  }
+
+  switch ( Ctlp_FormulaReadType( ctlFormula ) ) {
+
+    case Ctlp_ID_c : 
+      if (!ImcModelCheckAtomicFormula(imcInfo,ctlFormula)) return 0; 
+      break;
+    case Ctlp_TRUE_c : 
+      if (!ImcModelCheckTrueFalseFormula(imcInfo,ctlFormula, TRUE)) return 0; 
+      break;
+    case Ctlp_FALSE_c : 
+      if (!ImcModelCheckTrueFalseFormula(imcInfo,ctlFormula, FALSE)) return 0;
+      break;
+    case Ctlp_NOT_c :
+      if ((approxPolarity == Imc_PolarityPos_c) || (graphType == Imc_GraphMOG_c)){
+	      if (!ImcModelCheckNotFormula(imcInfo,ctlFormula, TRUE)) return 0;
+      }
+      if ((approxPolarity == Imc_PolarityNeg_c) || (graphType == Imc_GraphMOG_c)){
+	      if(!ImcModelCheckNotFormula(imcInfo,ctlFormula, FALSE)) return 0;
+      } 
+      break;
+    case Ctlp_AND_c :
+      if ((approxPolarity == Imc_PolarityPos_c) || (graphType == Imc_GraphMOG_c)){       
+        if (!ImcModelCheckAndFormula(imcInfo,ctlFormula,TRUE))return 0;
+      }
+      if ((approxPolarity == Imc_PolarityNeg_c) || (graphType == Imc_GraphMOG_c)){
+        if (!ImcModelCheckAndFormula(imcInfo,ctlFormula,FALSE)) return 0;
+      }   
+      break;
+    case Ctlp_EX_c :
+      if ((approxPolarity == Imc_PolarityPos_c) || (graphType == Imc_GraphMOG_c)){
+	if (!Imc_ImcEvaluateEXApprox(imcInfo,ctlFormula, TRUE, FALSE)) return 0;
+      }
+      if ((approxPolarity == Imc_PolarityNeg_c) || (graphType == Imc_GraphMOG_c)){
+        if (!Imc_ImcEvaluateEXApprox(imcInfo,ctlFormula, FALSE, FALSE)) return 0;
+      }
+      break;
+
+    case Ctlp_EU_c :
+      if ((approxPolarity == Imc_PolarityPos_c) || (graphType == Imc_GraphMOG_c)){ 
+        if (!Imc_ImcEvaluateEUApprox(imcInfo,ctlFormula,TRUE, FALSE)) return 0;
+      }
+      if ((approxPolarity == Imc_PolarityNeg_c) || (graphType == Imc_GraphMOG_c)){
+      	if (!Imc_ImcEvaluateEUApprox(imcInfo,ctlFormula, FALSE, FALSE)) return 0;
+      }
+      break;
+
+    case Ctlp_EG_c :
+      if ((approxPolarity == Imc_PolarityPos_c) || (graphType == Imc_GraphMOG_c)){
+        if (!Imc_ImcEvaluateEGApprox(imcInfo,ctlFormula,TRUE, FALSE)) return 0;
+      }
+      if ((approxPolarity == Imc_PolarityNeg_c) || (graphType == Imc_GraphMOG_c)){
+      	if (!Imc_ImcEvaluateEGApprox(imcInfo,ctlFormula, FALSE, FALSE)) return 0;
+      } 
+      break;
+
+    default: fail("Encountered unknown type of CTL formula\n");
+  }
+
+  if (nodeInfo->upperDone && nodeInfo->lowerDone){
+    if (!nodeInfo->isExact && mdd_equal_mod_care_set(nodeInfo->upperSat, 
+         nodeInfo->lowerSat, imcInfo->modelCareStates)){ /* FIXED */
+      nodeInfo->isExact = TRUE;
+    }
+  }
+
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    	[Evaluate EX formula with approximations.]
+
+  Description 	[Evaluate EX formula with approximations. If isUpper is set,
+  a superset of exact satisfying states of EG formula is computed. Otherwise,
+  a subset is computed.]
+
+  SideEffects 	[]
+
+  SeeAlso       []
+
+******************************************************************************/
+int
+Imc_ImcEvaluateEXApprox(
+  Imc_Info_t *imcInfo,
+  Ctlp_Formula_t *formula,
+  boolean isUpper,
+  boolean isRecomputation)
+{
+  mdd_t *targetStates;
+  Ctlp_Formula_t *leftChild;
+  mdd_t *result = NIL(mdd_t);
+  mdd_t *tempResult;
+  mdd_t *localCareStates;
+  mdd_t *globalCareStates;
+  boolean useLocalCare = FALSE;
+  Imc_NodeInfo_t *nodeInfo, *lNodeInfo;
+  boolean isExact;
+  
+  globalCareStates = imcInfo->modelCareStates;
+
+  if (!st_lookup(imcInfo->nodeInfoTable, formula, &nodeInfo)){
+    fprintf(vis_stdout, "** imc error : EX nodeinfo is not initilize.\n");
+    return 0;
+  }
+
+  leftChild = Ctlp_FormulaReadLeftChild(formula);
+  if (!st_lookup(imcInfo->nodeInfoTable, leftChild, &lNodeInfo)){
+    fprintf(vis_stdout, "** imc error : EX left nodeinfo is not initilize.\n");
+    return 0;
+  }
+
+  if ( imcInfo->verbosity == Imc_VerbosityMax_c ){      
+     if (isUpper){
+      fprintf(vis_stdout, "IMC :  SAT(EX)+ computation start.\n");
+    }else{
+      fprintf(vis_stdout, "IMC :  SAT(EX)- computation start.\n");
+    }
+  }
+
+  /*
+   * If exact sat is already computed from other side of approximation,
+   * use it.
+   */
+  if (nodeInfo->isExact){
+    if ( imcInfo->verbosity == Imc_VerbosityMax_c ){      
+      if (isUpper){
+        fprintf(vis_stdout, "IMC :  SAT(EX)+ computation end.\n");
+      }else{
+        fprintf(vis_stdout, "IMC :  SAT(EX)- computation end.\n");
+      }
+    }
+    return 1;
+  }
+
+
+  /*
+   * If this is not for recomputation, do general satisfying states computation.
+   * Otherwise, compute the subset of the propagated goalset where the formula
+   * satisfies.
+   * Test if tighter satisfying don't care states(ASDC) can be used to reduce
+   * transition sub-relations.
+   */
+  if (nodeInfo->upperSat != NIL(mdd_t)){
+    localCareStates = mdd_and(nodeInfo->upperSat,globalCareStates, 1, 1); 
+  }else{
+    localCareStates = mdd_dup(globalCareStates);
+  }
+
+  if ((mdd_lequal(localCareStates,globalCareStates, 1, 1)) &&
+      (!mdd_equal(localCareStates,globalCareStates))){
+    useLocalCare = TRUE;
+  }
+
+  if (!isRecomputation){
+    if (isUpper){
+      targetStates = lNodeInfo->upperSat;
+    }else{
+      targetStates = lNodeInfo->lowerSat;
+    }
+  }else{
+    targetStates = lNodeInfo->propagatedGoalSetTrue;
+  }
+
+  if (targetStates == NIL(mdd_t)) return 0;
+
+  if ((isUpper)|| (isRecomputation)) 
+    Imc_UpperSystemMinimize(imcInfo, localCareStates);
+  else
+    Imc_LowerSystemMinimize(imcInfo, localCareStates);  
+
+  if ((isUpper) || (isRecomputation)){
+    tempResult = Imc_ComputeUpperPreimage(imcInfo, localCareStates, targetStates, 
+                                          &isExact);
+  }else{
+    tempResult = Imc_ComputeLowerPreimage(imcInfo, localCareStates, targetStates, 
+                                          &isExact);
+  }
+
+  if (tempResult == NIL(mdd_t)) return 0;
+
+  if ((imcInfo->verbosity == Imc_VerbosityMax_c) ||
+      (imcInfo->verbosity == Imc_VerbosityMin_c)) {
+    mdd_t *tmpMdd = mdd_and(tempResult, localCareStates, 1, 1 );
+    double minterm = mdd_count_onset(imcInfo->mddMgr, tmpMdd, 
+              imcInfo->systemInfo->psMddIdArray);
+    if (isUpper){
+      fprintf(vis_stdout, "IMC : |SAT(EX)+| = %.0f (%10g)\n", minterm, minterm);
+    }else{
+      fprintf(vis_stdout, "IMC : |SAT(EX)-| = %.0f (%10g)\n", minterm, minterm);
+    }
+    mdd_free(tmpMdd);
+  }
+
+  if (useLocalCare){
+     result = mdd_and(tempResult, localCareStates, 1, 1); 
+     mdd_free(tempResult);
+     tempResult = bdd_minimize(result, globalCareStates);
+     mdd_free(result);
+     result = tempResult;
+  }else{
+     result = tempResult;
+  }
+
+  mdd_free(localCareStates);
+
+  if (isRecomputation){
+    tempResult = mdd_and(nodeInfo->goalSet, result, 1, 1);
+    mdd_free(result);
+    nodeInfo->propagatedGoalSetTrue = 
+      mdd_or(nodeInfo->goalSetTrue, tempResult, 1, 1);
+    mdd_free(tempResult);
+    return 1;
+  }
+
+  if (isUpper){
+    if (nodeInfo->upperSat != NIL(mdd_t)){
+      mdd_free(nodeInfo->upperSat);
+    }
+    nodeInfo->upperSat = result;
+    nodeInfo->upperDone = TRUE;
+  }else{
+    if (nodeInfo->lowerSat != NIL(mdd_t)){
+      tempResult = mdd_or(nodeInfo->lowerSat, result, 1, 1);
+      mdd_free(nodeInfo->lowerSat);
+      mdd_free(result);
+      result = tempResult;
+    }
+    nodeInfo->lowerSat = result;
+    nodeInfo->lowerDone = TRUE;
+  }
+
+  if ( imcInfo->verbosity == Imc_VerbosityMax_c ){      
+    if (isUpper){
+      fprintf(vis_stdout, "IMC :  SAT(EX)+ computation end.\n");
+    }else{
+      fprintf(vis_stdout, "IMC :  SAT(EX)- computation end.\n");
+    }
+  }
+
+  if (lNodeInfo->isExact && isExact){
+    nodeInfo->isExact = TRUE;
+    if ( imcInfo->verbosity == Imc_VerbosityMax_c ){
+      if (isUpper){
+        fprintf(vis_stdout, "IMC :  SAT(EX)+ computation is exact.\n");
+      }else{
+        fprintf(vis_stdout, "IMC :  SAT(EX)- computation is exact.\n");
+      }
+    }      
+    if (isUpper){
+      if (nodeInfo->lowerSat != NIL(mdd_t)) mdd_free(nodeInfo->lowerSat);
+      nodeInfo->lowerSat = mdd_dup(nodeInfo->upperSat);
+      nodeInfo->lowerDone = TRUE;
+    }else{
+      if (nodeInfo->upperSat != NIL(mdd_t)) mdd_free(nodeInfo->upperSat);
+      nodeInfo->upperSat = mdd_dup(nodeInfo->lowerSat);
+      nodeInfo->upperDone = TRUE;
+    } 
+  }else{
+    nodeInfo->isExact = FALSE;
+  }  
+
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Evaluate EU formula with approximations.]
+
+  Description [Evaluate EU formula with approximations. If isUpper is set,
+  a superset of exact satisfying states of EG formula is computed. Otherwise,
+  a subset is computed.]
+
+  Comment     []
+
+  SideEffects []
+
+******************************************************************************/
+int
+Imc_ImcEvaluateEUApprox(
+  Imc_Info_t *imcInfo,
+  Ctlp_Formula_t *formula,
+  boolean isUpper,
+  boolean isRecomputation)
+{
+  mdd_t *localCareStates;
+  mdd_t *targetStates, *invariantStates;
+  mdd_t *aMdd, *bMdd, *cMdd;
+  mdd_t *result;
+  mdd_t *tmpMdd1, *tmpMdd2;
+  mdd_t * globalCareStates;
+  double size1, size2;
+  Ctlp_Formula_t *lFormula, *rFormula;
+  Imc_NodeInfo_t *nodeInfo, *lNodeInfo, *rNodeInfo;
+  boolean isExact, globalIsExact;
+
+  globalIsExact = TRUE;
+  globalCareStates = imcInfo->modelCareStates;
+  lFormula = Ctlp_FormulaReadLeftChild(formula);
+  rFormula = Ctlp_FormulaReadRightChild(formula);
+
+  if (!st_lookup(imcInfo->nodeInfoTable, formula, &nodeInfo)){
+    fprintf(vis_stdout, "** imc error : EU nodeinfo is not initilize.\n");
+    return 0;
+  }
+  if (!st_lookup(imcInfo->nodeInfoTable, lFormula, &lNodeInfo)){
+    fprintf(vis_stdout, "** imc error : EU left nodeinfo is not initilize.\n");
+    return 0;
+  }
+  if (!st_lookup(imcInfo->nodeInfoTable, rFormula, &rNodeInfo)){
+    fprintf(vis_stdout, "** imc error : EU right nodeinfo is not initilize.\n");
+    return 0;
+  }
+
+  if ( imcInfo->verbosity == Imc_VerbosityMax_c ){      
+    if (isUpper){
+      fprintf(vis_stdout, "IMC :  SAT(EU)+ computation start.\n");
+    }else{
+      fprintf(vis_stdout, "IMC :  SAT(EU)- computation start.\n");
+    }
+  }
+
+  /*
+   * If exact sat is already computed from other side of approximation,
+   * use it.
+   */
+  if (nodeInfo->isExact){
+    if ( imcInfo->verbosity == Imc_VerbosityMax_c ){      
+      if (isUpper){
+        fprintf(vis_stdout, "IMC :  SAT(EU)+ computation end.\n");
+      }else{
+        fprintf(vis_stdout, "IMC :  SAT(EU)- computation end.\n");
+      }
+    }
+    return 1;
+  }
+
+
+  /*
+   * Test if tighter satisfying don't care states(ASDC) can be used to reduce
+   * transition sub-relations.
+   */
+  
+  if (nodeInfo->upperSat != NIL(mdd_t)){
+    localCareStates = mdd_and(nodeInfo->upperSat,globalCareStates, 1, 1); 
+  }else{
+    localCareStates = mdd_dup(globalCareStates);
+  }
+
+  if ((mdd_lequal(localCareStates,globalCareStates, 1, 1)) &&
+      (!mdd_equal(localCareStates,globalCareStates))){
+  }
+
+  if (!isRecomputation){
+    if (isUpper){
+      if (nodeInfo->lowerSat != NIL(mdd_t)){
+        targetStates = mdd_or(rNodeInfo->upperSat, nodeInfo->lowerSat, 1, 1);
+      }else{
+        targetStates = mdd_dup(rNodeInfo->upperSat);
+      }
+      invariantStates = lNodeInfo->upperSat;
+    }else{
+      targetStates = mdd_dup(rNodeInfo->lowerSat);
+      invariantStates = lNodeInfo->lowerSat;
+    }
+  }else{
+    targetStates = mdd_dup(rNodeInfo->propagatedGoalSetTrue);
+    invariantStates = lNodeInfo->propagatedGoalSetTrue;    
+  }
+
+  result = targetStates;
+
+  if ((isUpper) || (isRecomputation))
+    Imc_UpperSystemMinimize(imcInfo, localCareStates);
+  else
+    Imc_LowerSystemMinimize(imcInfo, localCareStates);
+
+  while (TRUE) { 
+
+    if (isUpper){
+      aMdd = Imc_ComputeUpperPreimage(imcInfo, localCareStates, 
+                                      result, &isExact);      
+    }else{
+      aMdd = Imc_ComputeLowerPreimage(imcInfo, localCareStates, 
+                                      result, &isExact);
+    }
+    if (aMdd == NIL(mdd_t)) return 0;
+
+    globalIsExact = (globalIsExact && isExact);
+
+    bMdd = mdd_and( aMdd, invariantStates, 1, 1 );
+    mdd_free( aMdd );
+    aMdd = mdd_and(bMdd, localCareStates, 1, 1);
+    mdd_free(bMdd);
+    bMdd = bdd_minimize(aMdd, globalCareStates);
+    mdd_free(aMdd);
+    cMdd = mdd_or(result, bMdd, 1, 1);
+    mdd_free( bMdd );
+    
+    tmpMdd1 = mdd_and( result, globalCareStates, 1, 1 );
+    tmpMdd2 = mdd_and( cMdd, globalCareStates, 1, 1 );
+    if (mdd_equal(tmpMdd1, tmpMdd2)){
+      mdd_free(cMdd);
+      break;
+    }else if (mdd_equal(tmpMdd2, localCareStates)){ 
+      mdd_free(result);
+      result = cMdd;     
+      break;
+    }else if (( imcInfo->verbosity == Imc_VerbosityMax_c ) ||
+              (imcInfo->verbosity == Imc_VerbosityMin_c)) { 
+      size1 = mdd_count_onset(imcInfo->mddMgr, tmpMdd1,
+		               imcInfo->systemInfo->psMddIdArray);
+      size2 = mdd_count_onset(imcInfo->mddMgr, tmpMdd2,
+		               imcInfo->systemInfo->psMddIdArray);
+      if (isUpper){
+        fprintf(vis_stdout, "IMC : |SAT(EU)+| = %.0f (%10g)-> %.0f (%10g)\n", 
+                size1, size1, size2, size2);
+      }else{
+        fprintf(vis_stdout, "IMC : |SAT(EU)-| = %.0f (%10g)-> %.0f (%10g)\n", 
+                size1, size1, size2, size2);
+      }
+    }      
+    mdd_free(tmpMdd1);
+    mdd_free(tmpMdd2);
+
+    mdd_free( result );
+    result = bdd_minimize(cMdd, globalCareStates);
+    mdd_free(cMdd);
+  }
+
+  if ((imcInfo->verbosity == Imc_VerbosityMax_c) ||
+      (imcInfo->verbosity == Imc_VerbosityMin_c)) {
+    size1 = mdd_count_onset(imcInfo->mddMgr, tmpMdd1,
+		             imcInfo->systemInfo->psMddIdArray);
+    size2 = mdd_count_onset(imcInfo->mddMgr, tmpMdd2,
+	               imcInfo->systemInfo->psMddIdArray);    
+    if (isUpper){
+      fprintf(vis_stdout, "IMC : |SAT(EU)+| = %.0f (%10g)-> %.0f (%10g)\n", 
+              size1, size1, size2, size2);
+    }else{
+      fprintf(vis_stdout, "IMC : |SAT(EU)-| = %.0f (%10g)-> %.0f (%10g)\n", 
+              size1, size1, size2, size2);
+    }
+  }
+
+  mdd_free(tmpMdd1);
+  mdd_free(tmpMdd2);
+
+  mdd_free(localCareStates);
+
+  if (isRecomputation){
+    tmpMdd1 = mdd_and(nodeInfo->goalSet, result, 1, 1);
+    mdd_free(result);
+    nodeInfo->propagatedGoalSetTrue = mdd_or(nodeInfo->goalSetTrue, tmpMdd1, 1, 1);
+    mdd_free(tmpMdd1);
+    return 1;
+  }
+
+  if (isUpper){
+    if (nodeInfo->upperSat != NIL(mdd_t)){
+      mdd_free(nodeInfo->upperSat);
+    }
+    nodeInfo->upperSat = result;
+    nodeInfo->upperDone = TRUE;
+  }else{
+    if (nodeInfo->lowerSat != NIL(mdd_t)){
+      tmpMdd1 = mdd_or(nodeInfo->lowerSat, result, 1, 1);
+      mdd_free(nodeInfo->lowerSat);
+      mdd_free(result);
+      result = tmpMdd1;
+    }
+    nodeInfo->lowerSat = result;
+    nodeInfo->lowerDone = TRUE;
+  } 
+
+  if ( imcInfo->verbosity == Imc_VerbosityMax_c ){      
+    if (isUpper){
+      fprintf(vis_stdout, "IMC :  SAT(EU)+ computation end.\n");
+    }else{
+      fprintf(vis_stdout, "IMC :  SAT(EU)- computation end.\n");
+    }
+  }
+
+  if (lNodeInfo->isExact && rNodeInfo->isExact && globalIsExact){
+    nodeInfo->isExact = TRUE;
+    if ( imcInfo->verbosity == Imc_VerbosityMax_c ){
+      if (isUpper){
+        fprintf(vis_stdout, "IMC :  SAT(EU)+ computation is exact.\n");
+      }else{
+        fprintf(vis_stdout, "IMC :  SAT(EU)- computation is exact.\n");
+      }
+    }   
+    if (isUpper){
+      if (nodeInfo->lowerSat != NIL(mdd_t)) mdd_free(nodeInfo->lowerSat);
+      nodeInfo->lowerSat = mdd_dup(nodeInfo->upperSat);
+      nodeInfo->lowerDone = TRUE;
+    }else{
+      if (nodeInfo->upperSat != NIL(mdd_t)) mdd_free(nodeInfo->upperSat);
+      nodeInfo->upperSat = mdd_dup(nodeInfo->lowerSat);
+      nodeInfo->upperDone = TRUE;
+    } 
+  }else{
+    nodeInfo->isExact = FALSE;
+  } 
+
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Evaluate EG formula with approximations.]
+
+  Description [Evaluate EG formula with approximations. If isUpper is set,
+  a superset of exact satisfying states of EG formula is computed. Otherwise,
+  a subset is computed.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+Imc_ImcEvaluateEGApprox( 
+  Imc_Info_t *imcInfo,
+  Ctlp_Formula_t *formula,
+  boolean isUpper,
+  boolean isRecomputation)
+{
+  mdd_t *Zmdd;
+  mdd_t *bMdd;
+  mdd_t *ZprimeMdd;
+  mdd_t *tmpMdd1, *tmpMdd2;
+  mdd_t *result;
+  mdd_t *localCareStates;
+  mdd_t *globalCareStates;
+  mdd_t *invariantStates;
+  double size1, size2;
+  Ctlp_Formula_t *lFormula;
+  Imc_NodeInfo_t *nodeInfo, *lNodeInfo;
+  boolean isExact, globalIsExact;
+  
+
+  lFormula = Ctlp_FormulaReadLeftChild(formula);
+
+  if (!st_lookup(imcInfo->nodeInfoTable, formula, &nodeInfo)){
+    fprintf(vis_stdout, "** imc error : EG nodeinfo is not initilize.\n");
+    return 0;
+  }
+  if (!st_lookup(imcInfo->nodeInfoTable, lFormula, &lNodeInfo)){
+    fprintf(vis_stdout, "** imc error : EG left nodeinfo is not initilize.\n");
+    return 0;
+  }
+
+  if ( imcInfo->verbosity == Imc_VerbosityMax_c ){      
+    if (isUpper){
+      fprintf(vis_stdout, "IMC :  SAT(EG)+ computation start.\n");
+    }else{
+      fprintf(vis_stdout, "IMC :  SAT(EG)- computation start.\n");
+    }
+  }
+
+  /*
+   * If exact sat is already computed from other side of approximation,
+   * use it.
+   */
+  if (nodeInfo->isExact){
+    if ( imcInfo->verbosity == Imc_VerbosityMax_c ){      
+      if (isUpper){
+        fprintf(vis_stdout, "IMC :  SAT(EG)+ computation end.\n");
+      }else{
+        fprintf(vis_stdout, "IMC :  SAT(EG)- computation end.\n");
+      }
+    }
+    return 1;
+  }
+
+  globalCareStates = imcInfo->modelCareStates;
+
+  /*
+   * Test if tighter satisfying don't care states(ASDC) can be used to reduce
+   * transition sub-relations.
+   */
+  if (nodeInfo->upperSat != NIL(mdd_t)){ 
+    localCareStates = mdd_and(nodeInfo->upperSat,globalCareStates, 1, 1); 
+  }else{
+    localCareStates = mdd_dup(globalCareStates);
+  }
+
+  if ((mdd_lequal(localCareStates,globalCareStates, 1, 1)) &&
+      (!mdd_equal(localCareStates,globalCareStates))){
+  }
+
+  if (!isRecomputation){
+    if (isUpper){
+      if (nodeInfo->upperSat != NIL(mdd_t)){
+        invariantStates = mdd_and(lNodeInfo->upperSat, nodeInfo->upperSat,1,1);
+      }else{
+        invariantStates = mdd_dup(lNodeInfo->upperSat);
+      } 
+    }else{
+      if (nodeInfo->upperSat != NIL(mdd_t)){
+        invariantStates = mdd_and(lNodeInfo->lowerSat, nodeInfo->upperSat,1,1);
+      }else{
+        invariantStates = mdd_dup(lNodeInfo->lowerSat);
+      }
+    }
+  }else{
+    invariantStates = mdd_dup(lNodeInfo->propagatedGoalSetTrue);
+  }
+
+  Zmdd = mdd_dup(invariantStates);
+  ZprimeMdd = NIL(mdd_t);
+
+  globalIsExact = TRUE;
+
+  if ((isUpper) || (isRecomputation))
+    Imc_UpperSystemMinimize(imcInfo, localCareStates);
+  else
+    Imc_LowerSystemMinimize(imcInfo, localCareStates);
+
+  while (TRUE) {
+
+    if (isUpper){
+      bMdd = Imc_ComputeUpperPreimage(imcInfo, localCareStates, 
+                                      Zmdd, &isExact);
+    }else{
+      bMdd = Imc_ComputeLowerPreimage(imcInfo, localCareStates, 
+                                      Zmdd, &isExact);
+    }
+    if (bMdd == NIL(mdd_t)){
+      mdd_free(invariantStates);
+      mdd_free(Zmdd);
+      if (ZprimeMdd !=NIL(mdd_t)) mdd_free(ZprimeMdd);
+      return 0;
+    }
+
+    ZprimeMdd = mdd_and(Zmdd, bMdd, 1, 1);
+    globalIsExact = (globalIsExact && isExact);
+
+    mdd_free(bMdd);
+    
+    tmpMdd1 = mdd_and( Zmdd, globalCareStates, 1, 1 );
+    tmpMdd2 = mdd_and( ZprimeMdd, localCareStates, 1, 1 );
+
+    mdd_free(Zmdd);
+    mdd_free(ZprimeMdd);
+
+    if ((mdd_equal(tmpMdd1, tmpMdd2)) ||
+	(mdd_is_tautology(tmpMdd2, 0))){
+      break;
+    }else if (( imcInfo->verbosity == Imc_VerbosityMax_c ) ||
+              (imcInfo->verbosity == Imc_VerbosityMin_c)) {      
+      size1 = mdd_count_onset(imcInfo->mddMgr, tmpMdd1,
+		               imcInfo->systemInfo->psMddIdArray);
+      size2 = mdd_count_onset(imcInfo->mddMgr, tmpMdd2,
+		               imcInfo->systemInfo->psMddIdArray);
+      if (isUpper){
+        fprintf(vis_stdout, "IMC : |SAT(EG)+| = %.0f (%10g)-> %.0f (%10g)\n", 
+                size1, size1, size2, size2);
+      }else{
+        fprintf(vis_stdout, "IMC : |SAT(EG)-| = %.0f (%10g)-> %.0f (%10g)\n", 
+                size1, size1, size2, size2);
+      }
+    }
+
+    mdd_free(tmpMdd1);
+    Zmdd = bdd_minimize(tmpMdd2, globalCareStates);
+    mdd_free(tmpMdd2);
+  }
+	
+  if (( imcInfo->verbosity == Imc_VerbosityMax_c ) ||
+      (imcInfo->verbosity == Imc_VerbosityMin_c)) {
+    size1 = mdd_count_onset(imcInfo->mddMgr, tmpMdd1,
+		             imcInfo->systemInfo->psMddIdArray);
+    size2 = mdd_count_onset(imcInfo->mddMgr, tmpMdd2,
+		             imcInfo->systemInfo->psMddIdArray);
+    if (isUpper){
+      fprintf(vis_stdout, "IMC : |SAT(EG)+| = %.0f (%10g)-> %.0f (%10g)\n", 
+              size1, size1, size2, size2);
+    }else{
+      fprintf(vis_stdout, "IMC : |SAT(EG)-| = %.0f (%10g)-> %.0f (%10g)\n", 
+              size1, size1, size2, size2);
+    }
+  }
+
+  mdd_free(tmpMdd1);
+  mdd_free(localCareStates);
+
+  result = bdd_minimize(tmpMdd2, globalCareStates);
+  mdd_free(tmpMdd2);
+
+  if (isRecomputation){
+    tmpMdd1 = mdd_and(nodeInfo->goalSet, result, 1, 1);
+    mdd_free(result);
+    nodeInfo->propagatedGoalSetTrue = mdd_or(nodeInfo->goalSetTrue,tmpMdd1,1,1);
+    mdd_free(tmpMdd1);
+    return 1;
+  }
+
+  mdd_free(invariantStates);
+
+  if (isUpper){
+    if (nodeInfo->upperSat != NIL(mdd_t)){
+      mdd_free(nodeInfo->upperSat);
+    }
+    nodeInfo->upperSat = result;
+    nodeInfo->upperDone = TRUE;
+  }else{
+    if (nodeInfo->lowerSat != NIL(mdd_t)){
+      tmpMdd1 = mdd_or(nodeInfo->lowerSat, result, 1, 1);
+      mdd_free(nodeInfo->lowerSat);
+      mdd_free(result);
+      result = bdd_minimize(tmpMdd1, globalCareStates);
+      mdd_free(tmpMdd1);
+    }
+    nodeInfo->lowerSat = result;
+    nodeInfo->lowerDone = TRUE;
+  } 
+
+  if ( imcInfo->verbosity == Imc_VerbosityMax_c ){      
+    if (isUpper){
+      fprintf(vis_stdout, "IMC :  SAT(EG)+ computation end.\n");
+    }else{
+      fprintf(vis_stdout, "IMC :  SAT(EG)- computation end.\n");
+    }
+  }
+
+  if (lNodeInfo->isExact && globalIsExact){
+    nodeInfo->isExact = TRUE;
+    if ( imcInfo->verbosity == Imc_VerbosityMax_c ){
+      if (isUpper){
+        fprintf(vis_stdout, "IMC :  SAT(EG)+ computation is exact.\n");
+      }else{
+        fprintf(vis_stdout, "IMC :  SAT(EG)- computation is exact.\n");
+      }
+    }    
+    if (isUpper){
+      if (nodeInfo->lowerSat != NIL(mdd_t)) mdd_free(nodeInfo->lowerSat);
+      nodeInfo->lowerSat = mdd_dup(nodeInfo->upperSat);
+      nodeInfo->lowerDone = TRUE;
+    }else{
+      if (nodeInfo->upperSat != NIL(mdd_t)) mdd_free(nodeInfo->upperSat);
+      nodeInfo->upperSat = mdd_dup(nodeInfo->lowerSat);
+      nodeInfo->upperDone = TRUE;
+    } 
+  }else{
+    nodeInfo->isExact = FALSE;
+  } 
+
+  return 1;
+}
+
+/**Function*******************************************************************
+
+  Synopsis [Compte a supperset of exact pre image.]
+
+  Description [Compte a supperset of exact pre image. If result is exact pre
+  image, isExact is set.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Imc_ComputeUpperPreimage(
+  Imc_Info_t *imcInfo,
+  mdd_t *rangeCareStates,
+  mdd_t *targetStates,
+  boolean *isExact)
+{
+  if (imcInfo->upperMethod == Imc_UpperExistentialQuantification_c){
+    return Imc_ComputeApproxPreimageByQuantification(imcInfo, rangeCareStates,
+             targetStates, isExact, FALSE);
+  }
+
+  return NIL(mdd_t);
+}
+
+
+/**Function*******************************************************************
+
+  Synopsis [Compte a superset or a subset of exact pre image.]
+
+  Description [Compte a superset or a subset of exact pre image accrding to
+  computeLower parameter. If result is exact pre image, isExact is set.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Imc_ComputeApproxPreimageByQuantification(
+  Imc_Info_t *imcInfo, 
+  mdd_t *rangeCareStates, 
+  mdd_t *targetStates,
+  boolean *isExact,
+  boolean computeLower)
+{
+  int i;
+  int psMddId;
+  double orgSize, newSize;
+  mdd_t *result;
+  mdd_t *nextTarget;
+  mdd_t *reducedTarget;
+  mdd_t *tempMdd;
+  mdd_t *reducedTargetInCare;
+  mdd_t *targetInCare;
+  array_t *supportArray;
+
+  *isExact = TRUE;
+  if (mdd_is_tautology(targetStates, 0)){
+    return mdd_zero(imcInfo->mddMgr);
+  }
+
+  supportArray = mdd_get_support(imcInfo->mddMgr, targetStates);
+
+  for(i=0;i<array_n(supportArray);i++){
+    psMddId = array_fetch(int, supportArray, i);
+    if (st_is_member(imcInfo->systemInfo->excludedPsMddIdTable, 
+		     (char *)(long)psMddId)){
+      *isExact = FALSE;
+      break;
+    }
+  }
+  array_free(supportArray);
+ 
+  if (array_n(imcInfo->systemInfo->excludedPsMddId) >0){
+    if (!computeLower){
+      reducedTarget = mdd_smooth(imcInfo->mddMgr, targetStates, 
+                               imcInfo->systemInfo->excludedPsMddId);
+    }else{
+      reducedTarget = mdd_consensus(imcInfo->mddMgr, targetStates, 
+                               imcInfo->systemInfo->excludedPsMddId);
+    }
+    if ((mdd_is_tautology(reducedTarget,1)) || (mdd_is_tautology(reducedTarget,0))){
+      return reducedTarget;
+    }
+  }else{
+    reducedTarget = mdd_dup(targetStates);
+  }
+
+  if (imcInfo->verbosity == Imc_VerbosityMax_c){
+    targetInCare = mdd_and(targetStates, imcInfo->modelCareStates, 1, 1);
+    reducedTargetInCare = mdd_and(reducedTarget, imcInfo->modelCareStates, 1, 1);
+    orgSize = mdd_count_onset(imcInfo->mddMgr, targetInCare,
+	  	        imcInfo->systemInfo->psMddIdArray);
+    newSize = mdd_count_onset(imcInfo->mddMgr, reducedTargetInCare,
+		          imcInfo->systemInfo->psMddIdArray);
+    if (!computeLower){
+      fprintf(vis_stdout, "IMC : Upper Approximation    |S| = %.0f (%10g)-> %.0f (%10g)\n",
+              orgSize, orgSize, newSize, newSize);
+    }else{
+      fprintf(vis_stdout, "IMC : Lower Approximation    |S| = %.0f (%10g)-> %.0f (%10g)\n",
+              orgSize, orgSize, newSize, newSize);
+    }
+    mdd_free(targetInCare);
+    mdd_free(reducedTargetInCare);
+  }
+
+  nextTarget = mdd_substitute(imcInfo->mddMgr, reducedTarget,
+			      imcInfo->systemInfo->psMddIdArray,
+			      imcInfo->systemInfo->nsMddIdArray);
+
+  mdd_free(reducedTarget);
+
+  if (!computeLower){
+    if (imcInfo->upperSystemInfo->bwdMinimizedRealationArray == NIL(array_t)){
+      result = Imc_ProductAbstract(imcInfo->mddMgr, 
+                                   imcInfo->upperSystemInfo->bwdRealationArray,
+                                   imcInfo->upperSystemInfo->bwdSmoothVarsArray,
+                                   nextTarget);
+    }else{
+      result = Imc_ProductAbstract(imcInfo->mddMgr, 
+                                   imcInfo->upperSystemInfo->bwdMinimizedRealationArray,
+                                   imcInfo->upperSystemInfo->bwdSmoothVarsArray,
+                                   nextTarget);
+    }
+  }else{
+    if (imcInfo->lowerSystemInfo->bwdMinimizedRealationArray == NIL(array_t)){
+      result = Imc_ProductAbstract(imcInfo->mddMgr, 
+                                   imcInfo->lowerSystemInfo->bwdRealationArray,
+                                   imcInfo->lowerSystemInfo->bwdSmoothVarsArray,
+                                   nextTarget);
+    }else{
+      result = Imc_ProductAbstract(imcInfo->mddMgr, 
+                                   imcInfo->lowerSystemInfo->bwdMinimizedRealationArray,
+                                   imcInfo->lowerSystemInfo->bwdSmoothVarsArray,
+                                   nextTarget);
+    }
+  }
+
+  mdd_free(nextTarget);
+
+  if (imcInfo->verbosity == Imc_VerbosityMax_c){
+    double exactSize, approxSize;
+    tempMdd = mdd_and(result, rangeCareStates, 1, 1);  
+    approxSize = mdd_count_onset(imcInfo->mddMgr, result,
+	            imcInfo->systemInfo->psMddIdArray);
+    exactSize = mdd_count_onset(imcInfo->mddMgr, tempMdd,
+	              imcInfo->systemInfo->psMddIdArray);
+    mdd_free(tempMdd);
+    if (!computeLower){
+      fprintf(vis_stdout, "IMC : Upper Preimage      |S+DC| = %.0f (%10g)\n",
+              approxSize, approxSize);
+      fprintf(vis_stdout, "IMC : Upper Preimage         |S| = %.0f (%10g)\n",
+              exactSize, exactSize);
+    }else{
+      fprintf(vis_stdout, "IMC : Lower Preimage      |S+DC| = %.0f (%10g)\n",
+              approxSize, approxSize);
+      fprintf(vis_stdout, "IMC : Lower Preimage         |S| = %.0f (%10g)\n",
+              exactSize, exactSize);
+    } 
+  }
+
+  /* 
+   * If preimage is zero, don't need compute again
+   */
+  if (mdd_is_tautology(result,0)){
+    *isExact = TRUE;
+  }
+
+  return result;
+}
+
+/**Function*******************************************************************
+
+  Synopsis [Compte a subset of exact pre image.]
+
+  Description [Compte a subset of exact pre image. If result is exact pre
+  image, isExact is set.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Imc_ComputeLowerPreimage(
+  Imc_Info_t *imcInfo,
+  mdd_t *rangeCareStates,
+  mdd_t *targetStates,
+  boolean *isExact)
+{
+  if (imcInfo->lowerMethod == Imc_LowerSubsetTR_c){
+    return Imc_ComputeLowerPreimageBySubsetTR(imcInfo, rangeCareStates,
+                                                targetStates, isExact);
+  }else if (imcInfo->lowerMethod == Imc_LowerUniversalQuantification_c){
+    return Imc_ComputeApproxPreimageByQuantification(imcInfo, rangeCareStates,
+             targetStates, isExact, TRUE);
+  }
+
+  return NIL(mdd_t);
+}
+
+
+/**Function*******************************************************************
+
+  Synopsis [Compte a subset of exact pre image by subsetting some transition 
+  sub-relations.]
+
+  Description [Compte a subset of exact pre image by subsetting some transition 
+  sub-relations. If result is exact pre image, isExact is set.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Imc_ComputeLowerPreimageBySubsetTR(
+  Imc_Info_t *imcInfo,
+  mdd_t *rangeCareStates,
+  mdd_t *targetStates,
+  boolean *isExact)
+{
+  mdd_t *tempMdd, *result;
+  mdd_t *toStates;
+
+  *isExact = TRUE;
+
+  if (mdd_is_tautology(targetStates,0)){
+    return mdd_zero(imcInfo->mddMgr);
+  }
+
+  if (mdd_is_tautology(targetStates, 1)){
+    return mdd_one(imcInfo->mddMgr);
+  }
+
+  /*
+   * T_i is T_i for all included latches.
+   */
+
+  /*arrayOfMdd = array_alloc(mdd_t *, 0); never used, I guess. Chao Wang*/
+
+  toStates = mdd_substitute(imcInfo->mddMgr, targetStates,
+			    imcInfo->systemInfo->psMddIdArray,
+			    imcInfo->systemInfo->nsMddIdArray);
+
+  /* Not works with partitioned transition relation 
+  supportArray = mdd_get_support(imcInfo->mddMgr, targetStates);
+
+  for(i=0;i<array_n(supportArray);i++){
+    psMddId = array_fetch(int, supportArray,i);
+
+    if (st_is_member(imcInfo->systemInfo->excludedPsMddIdTable, 
+        (char *)(long)psMddId)){
+      *isExact = FALSE;
+    }
+  }
+  array_free(supportArray);
+  */
+  if (st_count(imcInfo->systemInfo->excludedPsMddIdTable)>0){
+    *isExact = FALSE;
+  }
+
+  if (imcInfo->lowerSystemInfo->bwdMinimizedRealationArray == NIL(array_t)){
+    result = Imc_ProductAbstract(imcInfo->mddMgr,
+                                 imcInfo->lowerSystemInfo->bwdRealationArray,
+                                 imcInfo->lowerSystemInfo->bwdSmoothVarsArray,
+                                 toStates);
+  }else{
+    result = Imc_ProductAbstract(imcInfo->mddMgr,
+                                 imcInfo->lowerSystemInfo->bwdMinimizedRealationArray,
+                                 imcInfo->lowerSystemInfo->bwdSmoothVarsArray,
+                                 toStates);
+  }
+
+  mdd_free(toStates);
+
+  if (imcInfo->verbosity == Imc_VerbosityMax_c){
+    double exactSize, approxSize;
+    tempMdd = mdd_and(result, rangeCareStates, 1, 1);  
+    approxSize = mdd_count_onset(imcInfo->mddMgr, result,
+	            imcInfo->systemInfo->psMddIdArray);
+    exactSize = mdd_count_onset(imcInfo->mddMgr, tempMdd,
+	              imcInfo->systemInfo->psMddIdArray);
+    mdd_free(tempMdd);
+    fprintf(vis_stdout, "IMC : Lower Preimage      |S+DC| = %.0f (%10g)\n",
+            approxSize, approxSize);
+    fprintf(vis_stdout, "IMC : Lower Preimage         |S| = %.0f (%10g)\n",
+            exactSize, exactSize);
+  }
+
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [Compute a product of relation array. All variables in
+  smoothVarsMddIdArray are quntified during product.] 
+
+  Description        [Compute a product of relation array. All variables in
+  smoothVarsMddIdArray are quntified during product.]
+
+  SideEffects        []
+
+  SeeAlso            []
+
+******************************************************************************/
+mdd_t *
+Imc_ProductAbstract(
+  mdd_manager *mddMgr,
+  array_t *relationArray,
+  array_t *smoothVarsMddIdArray,
+  mdd_t *toStates)
+{
+  int i;
+  mdd_t *product, *tempProd;
+  mdd_t *singleTR;
+  array_t *smoothVars;
+
+  product = mdd_dup(toStates);
+
+  for(i=0;i<array_n(relationArray);i++){
+    singleTR = array_fetch(mdd_t *, relationArray, i);
+    smoothVars = array_fetch(array_t*, smoothVarsMddIdArray, i);
+    if (array_n(smoothVars) == 0){
+      tempProd = mdd_and(product, singleTR, 1, 1);
+    }else{
+      tempProd = bdd_and_smooth(product, singleTR, smoothVars);
+    }
+    mdd_free(product);
+    product = tempProd;
+  }
+  if (i < array_n(smoothVarsMddIdArray)) {
+    smoothVars = array_fetch(array_t*, smoothVarsMddIdArray, i);
+    tempProd = bdd_smooth(product, smoothVars);
+    mdd_free(product);
+    product = tempProd;
+  }
+
+  return product;  
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis           [Create an refinement schedule array.] 
+
+  Description        [If dynamicIncrease is true, the first element of return
+  array includes varibales appered in formula. The size of the first element
+  should be less than or equal to incrementalSize. The second element includes
+  all variables in formula's cone of influence. When dynamicIncrease is false,
+  all vaiables in formula's cone of influence (let's say n variables) are
+  partitioned into ceil(n/incrementalSize) elements. Then one more element
+  which includes all n variables are added to return array.]
+
+  SideEffects        []
+
+  SeeAlso            [Part_SubsystemInfo_t]
+
+******************************************************************************/
+array_t	*
+ImcCreateScheduleArray(
+  Ntk_Network_t         *network,
+  Ctlp_Formula_t        *formula,
+  boolean               dynamicIncrease,
+  Imc_RefineMethod	refine,
+  int                   verbosity,
+  int                   incrementalSize,
+  Part_CMethod          correlationMethod)
+{
+  array_t		*partitionArray;
+  Part_Subsystem_t	*partitionSubsystem;
+  Part_SubsystemInfo_t  *subsystemInfo; 
+  st_table	        *latchNameTable;
+  st_table	        *latchNameTableSum, *latchNameTableSumCopy;
+  int		        i;
+  char		        *flagValue;
+  st_generator          *stGen;
+  char                  *name;
+  array_t               *ctlArray;
+  double		affinityFactor;
+  array_t               *scheduleArray;
+  boolean               dynamicAndDependency;
+  array_t               *tempArray, *tempArray2;
+  int                   count;
+
+  /* affinity factor to decompose state space */
+  flagValue = Cmd_FlagReadByName("part_group_affinity_factor");
+  if(flagValue != NIL(char)){
+    affinityFactor = atof(flagValue); 
+  }
+  else{
+    /* default value */
+    affinityFactor = 0.5; 
+  }
+
+  if (refine == Imc_RefineSort_c) dynamicAndDependency = TRUE;
+  else dynamicAndDependency = FALSE;
+
+  /* 
+   * Obtain submachines as array. 
+   * The first sub-system includes variables in CTL formulas and other
+   * latches are groupted in the same way as Part_PartCreateSubsystems()
+   */
+  ctlArray = array_alloc(Ctlp_Formula_t *, 1);
+  subsystemInfo = Part_PartitionSubsystemInfoInit(network);
+  Part_PartitionSubsystemInfoSetBound(subsystemInfo, incrementalSize);
+  Part_PartitionSubsystemInfoSetVerbosity(subsystemInfo, verbosity);
+  Part_PartitionSubsystemInfoSetCorrelationMethod(subsystemInfo,
+    correlationMethod); 
+  Part_PartitionSubsystemInfoSetAffinityFactor(subsystemInfo, affinityFactor);
+  array_insert(Ctlp_Formula_t *, ctlArray, 0, formula);
+
+  partitionArray = Part_PartCreateSubsystemsWithCTL(subsystemInfo,
+                   ctlArray, NIL(array_t), dynamicIncrease,dynamicAndDependency);
+  Part_PartitionSubsystemInfoFree(subsystemInfo);
+  array_free(ctlArray);
+  scheduleArray = array_alloc(st_table *, 0);
+
+
+  /* 
+   * For each partitioned submachines build an FSM. 
+   */
+  latchNameTableSum = st_init_table(strcmp, st_strhash);
+  if (!dynamicAndDependency){
+    for (i=0;i<array_n(partitionArray);i++){
+      partitionSubsystem = array_fetch(Part_Subsystem_t *, partitionArray, i);
+      if (partitionSubsystem != NIL(Part_Subsystem_t)) {
+        latchNameTable = Part_PartitionSubsystemReadVertexTable(partitionSubsystem);
+        st_foreach_item(latchNameTable, stGen, &name, NIL(char *)) {
+          if (!st_lookup(latchNameTableSum, name, NIL(char *))){ 
+            st_insert(latchNameTableSum, name, NIL(char));
+          }
+        }
+        Part_PartitionSubsystemFree(partitionSubsystem);
+      } 
+      latchNameTableSumCopy = st_copy(latchNameTableSum);
+      array_insert_last(st_table *, scheduleArray, latchNameTableSumCopy);
+    }
+  }else{
+    partitionSubsystem = array_fetch(Part_Subsystem_t *, partitionArray, 0);
+    latchNameTable = Part_PartitionSubsystemReadVertexTable(partitionSubsystem);
+    st_foreach_item(latchNameTable, stGen, &name, NIL(char *)) {
+      st_insert(latchNameTableSum, name, NIL(char));
+    }
+    latchNameTableSumCopy = st_copy(latchNameTableSum);
+    array_insert_last(st_table *, scheduleArray, latchNameTableSumCopy);
+    Part_PartitionSubsystemFree(partitionSubsystem);
+
+    partitionSubsystem = array_fetch(Part_Subsystem_t *, partitionArray, 1);
+    tempArray = array_alloc(char *, 0);    
+    if (partitionSubsystem != NIL(Part_Subsystem_t)){
+      latchNameTable = Part_PartitionSubsystemReadVertexTable(partitionSubsystem);
+      st_foreach_item(latchNameTable, stGen, &name, NIL(char *)) {
+        array_insert_last(char *, tempArray, name);
+      }
+      array_sort(tempArray, stringCompare);
+      Part_PartitionSubsystemFree(partitionSubsystem);
+    }
+    
+    partitionSubsystem = array_fetch(Part_Subsystem_t *, partitionArray, 2);
+    tempArray2 = array_alloc(char *, 0);
+    if (partitionSubsystem != NIL(Part_Subsystem_t)) {
+      latchNameTable = Part_PartitionSubsystemReadVertexTable(partitionSubsystem);
+      st_foreach_item(latchNameTable, stGen, &name, NIL(char *)) {
+        array_insert_last(char *, tempArray2, name);
+      }
+      array_sort(tempArray2, stringCompare);
+      Part_PartitionSubsystemFree(partitionSubsystem);
+    }
+
+    array_append(tempArray, tempArray2);
+    array_free(tempArray2);
+
+    count = 0;
+    arrayForEachItem(char *, tempArray, i, name){   
+      if (!st_lookup(latchNameTableSum, name, NIL(char *))){ 
+        st_insert(latchNameTableSum, (char *)name, (char *)0);
+        count++;
+      }
+      if ((count == incrementalSize) && (i < array_n(tempArray)-1)){
+        latchNameTableSumCopy = st_copy(latchNameTableSum);
+        array_insert_last(st_table *, scheduleArray, latchNameTableSumCopy);
+        count = 0;
+      }
+    }
+    array_free(tempArray);
+    latchNameTableSumCopy = st_copy(latchNameTableSum);
+    array_insert_last(st_table *, scheduleArray, latchNameTableSumCopy);
+  }
+
+  array_free(partitionArray);
+  st_free_table(latchNameTableSum);
+
+  return scheduleArray;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Find Mdd for states satisfying Atomic Formula.]
+
+  Description [This is a duplicate copy of static function, 
+  ModelCheckAtomicFormula(). ] 
+
+  SideEffects []
+
+******************************************************************************/
+int
+ImcModelCheckAtomicFormula(
+  Imc_Info_t *imcInfo, 
+  Ctlp_Formula_t *formula)
+{
+  mdd_t * resultMdd;
+  mdd_t *tmpMdd;
+  Fsm_Fsm_t *modelFsm = imcInfo->globalFsm;
+  Ntk_Network_t *network = Fsm_FsmReadNetwork( modelFsm );
+  char *nodeNameString = Ctlp_FormulaReadVariableName( formula );
+  char *nodeValueString = Ctlp_FormulaReadValueName( formula );
+  Ntk_Node_t *node = Ntk_NetworkFindNodeByName( network, nodeNameString );
+  Var_Variable_t *nodeVar;
+  int nodeValue;
+  graph_t *modelPartition;
+  vertex_t *partitionVertex;
+  Mvf_Function_t *MVF;
+  Imc_NodeInfo_t *nodeInfo;
+
+  if (!st_lookup(imcInfo->nodeInfoTable, formula, &nodeInfo)){
+    fprintf(vis_stdout, "** imc error : Atomic nodeinfo is not initilize.\n");
+    return 0;
+  }
+
+  nodeVar = Ntk_NodeReadVariable( node );
+  if ( Var_VariableTestIsSymbolic( nodeVar ) ){
+    nodeValue = Var_VariableReadIndexFromSymbolicValue( nodeVar, nodeValueString );
+  }
+  else {
+    nodeValue = atoi( nodeValueString );
+  } 
+
+  modelPartition = Part_NetworkReadPartition( network );
+  if ( !( partitionVertex = Part_PartitionFindVertexByName( modelPartition,
+                                                            nodeNameString ) )) { 
+    lsGen tmpGen;
+    Ntk_Node_t *tmpNode;
+    array_t *mvfArray;
+    array_t *tmpRoots = array_alloc( Ntk_Node_t *, 0 );
+    st_table *tmpLeaves = st_init_table( st_ptrcmp, st_ptrhash );
+    array_insert_last( Ntk_Node_t *, tmpRoots, node );
+
+    Ntk_NetworkForEachCombInput( network, tmpGen, tmpNode ) {
+      st_insert( tmpLeaves, (char *) tmpNode, (char *) NTM_UNUSED );
+    }
+
+    mvfArray =  Ntm_NetworkBuildMvfs( network, tmpRoots, tmpLeaves,
+                                      NIL(mdd_t) );
+    MVF = array_fetch( Mvf_Function_t *, mvfArray, 0 );
+    array_free( tmpRoots );
+    st_free_table( tmpLeaves );
+    array_free( mvfArray );
+
+    tmpMdd = Mvf_FunctionReadComponent( MVF, nodeValue );
+    resultMdd = mdd_dup( tmpMdd );
+    Mvf_FunctionFree( MVF );
+  }
+  else {
+    MVF = Part_VertexReadFunction( partitionVertex );
+    tmpMdd = Mvf_FunctionReadComponent( MVF, nodeValue );
+    resultMdd = mdd_dup( tmpMdd );
+  }
+
+  tmpMdd = bdd_minimize(resultMdd, imcInfo->modelCareStates);
+  mdd_free(resultMdd);
+  resultMdd = tmpMdd;
+
+  nodeInfo->upperSat = resultMdd;
+  nodeInfo->lowerSat = mdd_dup(resultMdd);
+  nodeInfo->upperDone = TRUE;
+  nodeInfo->lowerDone = TRUE;
+  nodeInfo->isExact = TRUE;
+  return 1;  
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Compute TRUE or FALSE expression.]
+
+  Description [Compute TRUE or FALSE expression.] 
+
+  SideEffects []
+
+******************************************************************************/
+int
+ImcModelCheckTrueFalseFormula(
+  Imc_Info_t *imcInfo, 
+  Ctlp_Formula_t *formula,
+  boolean isTrue)
+{
+  mdd_t *resultMdd;
+  Imc_NodeInfo_t *nodeInfo;
+
+  if (!st_lookup(imcInfo->nodeInfoTable, formula, &nodeInfo)){
+    fprintf(vis_stdout, "** imc error : TRUE or FALSE nodeinfo is not initilize.\n");
+    return 0;
+  }
+
+  /*
+   * Already computed, then return. 
+   */
+  if (nodeInfo->isExact) return 1;
+
+  if (isTrue)
+    resultMdd = mdd_one(imcInfo->mddMgr);
+  else
+    resultMdd = mdd_zero(imcInfo->mddMgr);
+
+  nodeInfo->upperSat = resultMdd;
+  nodeInfo->lowerSat = mdd_dup(resultMdd);  
+  nodeInfo->upperDone = TRUE;
+  nodeInfo->lowerDone = TRUE;
+  nodeInfo->isExact = TRUE;
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Compute NOT expression.]
+
+  Description [Compute NOT expression.] 
+
+  SideEffects []
+
+******************************************************************************/
+int
+ImcModelCheckNotFormula(
+  Imc_Info_t *imcInfo, 
+  Ctlp_Formula_t *formula,
+  boolean isUpper
+  )
+{
+  mdd_t *upperSAT, *lowerSAT;
+  Ctlp_Formula_t *leftChild;
+  Imc_NodeInfo_t *nodeInfo, *leftNodeInfo;
+
+  if (!st_lookup(imcInfo->nodeInfoTable, formula, &nodeInfo)){
+    return 0;
+  }
+
+
+  leftChild = Ctlp_FormulaReadLeftChild(formula);
+  if (!st_lookup(imcInfo->nodeInfoTable, leftChild, &leftNodeInfo)){
+    fprintf(vis_stdout, "** imc error : NOT nodeinfo is not initilize.\n");
+    return 0;
+  }
+
+
+  if (isUpper){
+    if  (leftNodeInfo->lowerSat == NIL(mdd_t)){
+      return 0;
+    }else{
+      if (nodeInfo->upperSat != NIL(mdd_t)) mdd_free(nodeInfo->upperSat);
+      upperSAT = mdd_not(leftNodeInfo->lowerSat);
+      nodeInfo->upperSat = upperSAT;
+      nodeInfo->upperDone = TRUE;
+    }
+  }else{
+    if  (leftNodeInfo->upperSat == NIL(mdd_t)){
+      return 0;
+    }else{
+      if (nodeInfo->lowerSat != NIL(mdd_t)) mdd_free(nodeInfo->lowerSat);
+      lowerSAT = mdd_not(leftNodeInfo->upperSat);
+      nodeInfo->lowerSat = lowerSAT;
+      nodeInfo->lowerDone = TRUE;
+    }
+  }
+
+  if (leftNodeInfo->isExact){
+    nodeInfo->isExact = TRUE;
+    if (isUpper){
+      if (nodeInfo->lowerSat != NIL(mdd_t)) mdd_free(nodeInfo->lowerSat);
+      nodeInfo->lowerSat = mdd_dup(nodeInfo->upperSat);
+      nodeInfo->lowerDone = TRUE;
+    }else{
+      if (nodeInfo->upperSat != NIL(mdd_t)) mdd_free(nodeInfo->upperSat);
+      nodeInfo->upperSat = mdd_dup(nodeInfo->lowerSat);
+      nodeInfo->upperDone = TRUE;
+    }
+  }
+
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Compute AND expression.]
+
+  Description [Compute AND expression.] 
+
+  SideEffects []
+
+******************************************************************************/
+int
+ImcModelCheckAndFormula(
+  Imc_Info_t *imcInfo, 
+  Ctlp_Formula_t *formula,
+  boolean isUpper)
+{
+  mdd_t *tmpMdd;
+  mdd_t *upperSat, *lowerSat;
+  Ctlp_Formula_t *leftChild, *rightChild;
+  Imc_NodeInfo_t *nodeInfo, *leftNodeInfo, *rightNodeInfo;
+
+  if (!st_lookup(imcInfo->nodeInfoTable, formula, &nodeInfo)){
+    return 0;
+  }
+
+  /*
+   * Already computed, then return. 
+   */
+  if (nodeInfo->isExact) return 1;
+
+  leftChild = Ctlp_FormulaReadLeftChild(formula);
+  rightChild = Ctlp_FormulaReadRightChild(formula);
+  if (!st_lookup(imcInfo->nodeInfoTable, leftChild, &leftNodeInfo)){
+    fprintf(vis_stdout, "** imc error : AND left nodeinfo is not initilize.\n");
+    return 0;
+  }
+  if (!st_lookup(imcInfo->nodeInfoTable, rightChild, &rightNodeInfo)){
+    fprintf(vis_stdout, "** imc error : AND right nodeinfo is not initilize.\n");
+    return 0;
+  } 
+
+  /*
+   * Already computed, then return. 
+   */
+  if (isUpper){
+    if ((leftNodeInfo->upperSat == NIL(mdd_t))||
+        (rightNodeInfo->upperSat == NIL(mdd_t))){
+      fprintf(vis_stdout, "** imc error : AND child nodeinfo->upperSat is not computed.\n");
+      return 0;
+    }else{
+      tmpMdd = mdd_and(leftNodeInfo->upperSat,rightNodeInfo->upperSat, 1, 1);
+      upperSat = bdd_minimize(tmpMdd, imcInfo->modelCareStates);
+      mdd_free(tmpMdd);
+      if (nodeInfo->upperSat != NIL(mdd_t)) mdd_free(nodeInfo->upperSat);
+      nodeInfo->upperSat = upperSat;
+      nodeInfo->upperDone = TRUE;
+    }
+  }else{
+    if ((leftNodeInfo->lowerSat == NIL(mdd_t))||
+        (rightNodeInfo->lowerSat == NIL(mdd_t))){
+      fprintf(vis_stdout, "** imc error : AND child nodeinfo->lowerSat is not computed.\n");
+      return 0;
+    }else{
+      tmpMdd = mdd_and(leftNodeInfo->lowerSat,rightNodeInfo->lowerSat, 1, 1);
+      
+      lowerSat = bdd_minimize(tmpMdd, imcInfo->modelCareStates);
+      mdd_free(tmpMdd);
+      if (nodeInfo->lowerSat != NIL(mdd_t)) mdd_free(nodeInfo->lowerSat);
+      nodeInfo->lowerSat = lowerSat;
+      nodeInfo->lowerDone = TRUE;
+    }
+  }
+
+  if ((leftNodeInfo->isExact) && (rightNodeInfo->isExact)){
+    nodeInfo->isExact = TRUE;
+    if (isUpper){
+      if (nodeInfo->lowerSat != NIL(mdd_t)) mdd_free(nodeInfo->lowerSat);
+      nodeInfo->lowerSat = mdd_dup(nodeInfo->upperSat);
+      nodeInfo->lowerDone = TRUE;
+    }else{
+      if (nodeInfo->upperSat != NIL(mdd_t)) mdd_free(nodeInfo->upperSat);
+      nodeInfo->upperSat = mdd_dup(nodeInfo->lowerSat);
+      nodeInfo->upperDone = TRUE;
+    }
+  }
+
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Print latch names in an upper approximate system.]
+
+  Description [Print latch names in an upper approximate system.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImcPrintLatchInApproxSystem(
+  Imc_Info_t *imcInfo)
+{
+  int i, index;
+  char *name;
+  array_t *includedLatchIndex = imcInfo->systemInfo->includedLatchIndex;
+
+  fprintf(vis_stdout, "Latches in approximate system\n");
+  fprintf(vis_stdout, "-----------------------------\n");
+
+  for(i=0;i<array_n(includedLatchIndex);i++){
+    index = array_fetch(int,includedLatchIndex,i);
+    name = array_fetch(char *, imcInfo->systemInfo->latchNameArray, index);
+    fprintf(vis_stdout, "%s\n", name);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Free node info table.]
+
+  Description [Free node info table.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImcNodeInfoTableFree(
+  st_table *nodeInfoTable)
+{
+  Ctlp_Formula_t *formula;
+  Imc_NodeInfo_t *nodeInfo;
+  st_generator *stGen;
+
+  st_foreach_item(nodeInfoTable, stGen, &formula, &nodeInfo){
+    Imc_NodeInfoFree(nodeInfo);
+  }
+
+  st_free_table(nodeInfoTable);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Compare two strings]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+stringCompare(
+  const void * s1,
+  const void * s2)
+{
+  return(strcmp(*(char **)s1, *(char **)s2));
+}
+
Index: vis_dev/vis-2.3/src/imc/imcInt.h
===================================================================
--- vis_dev/vis-2.3/src/imc/imcInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/imc/imcInt.h	(revision 14)
@@ -0,0 +1,229 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [imcInt.h]
+
+  PackageName [imc]
+
+  Synopsis    [Internal data type definitions and macros to handle the
+  structures of the imc package.]
+
+  Author      [Jae-Young Jang <jjang@vlsi.colorado.edu>]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+  Revision    [$Id:]
+
+******************************************************************************/
+
+#ifndef _IMCINT
+#define _IMCINT
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+
+#include "imc.h"
+#include "fsm.h"
+#include <string.h>
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [Information for a total system.]
+
+  Description [Information for a total system.]
+
+  SeeAlso     [ImcInfoStruct]
+
+******************************************************************************/
+struct ImcSystemInfo{
+  st_table 	*latchNameTable;      /* Names of latches in a system */
+  array_t       *latchNameArray;
+  array_t       *latchNodeArray;
+  array_t       *nsMddIdArray;
+  array_t       *psMddIdArray;
+  array_t       *inputMddIdArray;
+  array_t       *TRArray;
+  array_t       *lowerTRArray;
+  array_t       *mvfArray;
+  array_t       *latchSizeArray;
+  st_table      *nsMddIdToIndex;
+  st_table      *psMddIdToIndex;
+  array_t       *includedPsMddId; 
+  array_t       *includedNsMddId;
+  array_t       *includedLatchIndex;
+  array_t       *excludedPsMddId;
+  array_t       *excludedNsMddId;
+  array_t       *excludedLatchIndex;
+  st_table      *excludedPsMddIdTable;
+};
+
+  
+/**Struct**********************************************************************
+
+  Synopsis    [Information for an upper-bound approximate system.]
+
+  Description [Information for an upper-bound approximate system.]
+
+  SeeAlso     [ImcInfoStruct]
+
+******************************************************************************/
+struct ImcUpperSystemInfo{
+  Imc_SystemInfo_t *systemInfo;
+  mdd_t *careStates;
+  array_t *fwdRealationArray;
+  array_t *fwdSmoothVarsArray;
+  array_t *bwdRealationArray;
+  array_t *bwdMinimizedRealationArray;
+  array_t *bwdSmoothVarsArray;
+
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [Information for an upper-bound approximate system.]
+
+  Description [Information for an upper-bound approximate system.]
+
+  SeeAlso     [ImcInfoStruct]
+
+******************************************************************************/
+struct ImcLowerSystemInfo{
+  Imc_SystemInfo_t *systemInfo;
+  mdd_t *careStates;
+  array_t *bwdRealationArray;
+  array_t *bwdMinimizedRealationArray;
+  array_t *bwdSmoothVarsArray;
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [Information for nodes in opeerational graph.]
+
+  Description [Information for nodes in opeerational graph.]
+
+  SeeAlso     [ImcInfoStruct]
+
+******************************************************************************/
+struct ImcNodeInfo{
+  boolean                polarity;
+  boolean                isExact;
+  mdd_t                  *upperSat;   /* upper satisfying set */
+  mdd_t                  *lowerSat;   /* lower satisfying set */
+  boolean                upperDone;
+  boolean                lowerDone;
+  mdd_t                  *propagatedGoalSet;
+  mdd_t                  *propagatedGoalSetTrue;
+  mdd_t                  *goalSet;
+  mdd_t                  *goalSetTrue;
+  mdd_t                  *pseudoEdges;
+  Imc_VerificationResult answer;  
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [Information regarding the imc package.]
+
+  Description [This is a higher level of information related to the imc 
+  verification.]
+
+  SeeAlso     [ImcSubsystemInfo]
+
+******************************************************************************/
+struct ImcInfoStruct{
+  /* General Info */
+  Ntk_Network_t	         *network;         /* Corresponding network */
+  Fsm_Fsm_t              *globalFsm;       /* Global FSM */
+  boolean                useLocalFsm;
+  Imc_DcLevel            dcLevel;          /* Don't care level */
+  mdd_t		         *initialStates;   /* Initial states */
+  Ctlp_FormulaClass      formulaClass;     /* ECTL, ACTL, MIXED, QuantifierFree */
+  mdd_t		         *modelCareStates; /* Global care states */
+  Imc_VerbosityLevel     verbosity;        /* Verbosity */
+  Imc_RefineMethod       refine;           /* Refinement method */
+  Imc_VerificationResult result;           /* Verification Result */
+  mdd_manager            *mddMgr;          /* MDD Manager */
+  Imc_PartMethod         partMethod;
+  char                   *modelName;
+  Hrc_Node_t             *currentNode;
+
+  /* Image, Preimage computation Info */
+  array_t                *supportMddIdArray; /* don't free */
+  array_t                *preQMddIdArray;    /* don't free */
+  array_t                *imgQMddIdArray;    /* don't free */
+
+  /* Operational graph Info */
+  Imc_GraphType          graphType;        /* pDOG, nDOG, MOG */
+  st_table               *nodeInfoTable;   /* node info table */
+  boolean                needLower;
+  boolean                needUpper;
+
+  /* Incremental Verification dependent info */
+  Imc_SystemInfo_t       *systemInfo;      /* System info of total system */
+  int                    incrementalSize;  /* Number of transition sub-relations
+                                              to be refined at each refinement */  
+
+  /* approximation and Dynamic Refinement dependent Info */
+  Imc_LowerMethod        lowerMethod;      /* Lower-bound approximation method */
+  Imc_UpperMethod        upperMethod;      /* Upper-bound approximation method */
+  Imc_UpperSystemInfo_t  *upperSystemInfo; /* Upper-bound approximate system */
+  Imc_LowerSystemInfo_t  *lowerSystemInfo; /* Lower-bound approximate system */
+  mdd_t                  *edges;           /* for edge traversal refinement */
+
+  /* approximation and Static Refinement dependent Info */
+  Part_CMethod           correlationMethod;
+  array_t                *staticRefineSchedule; /* Static refinement schedule */
+};
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN array_t	* ImcCreateScheduleArray(Ntk_Network_t *network, Ctlp_Formula_t *formula, boolean dynamicIncrease, Imc_RefineMethod refine, int verbosity, int incrementalSize, Part_CMethod correlationMethod);
+EXTERN int ImcModelCheckAtomicFormula(Imc_Info_t *imcInfo, Ctlp_Formula_t *formula);
+EXTERN int ImcModelCheckTrueFalseFormula(Imc_Info_t *imcInfo, Ctlp_Formula_t *formula, boolean isTrue);
+EXTERN int ImcModelCheckNotFormula(Imc_Info_t *imcInfo, Ctlp_Formula_t *formula, boolean isUpper);
+EXTERN int ImcModelCheckAndFormula(Imc_Info_t *imcInfo, Ctlp_Formula_t *formula, boolean isUpper);
+EXTERN void ImcPrintLatchInApproxSystem(Imc_Info_t *imcInfo);
+EXTERN void ImcNodeInfoTableFree(st_table *nodeInfoTable);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _IMCINT */
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/img/img.h
===================================================================
--- vis_dev/vis-2.3/src/img/img.h	(revision 14)
+++ vis_dev/vis-2.3/src/img/img.h	(revision 14)
@@ -0,0 +1,298 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [img.h]
+
+  PackageName [img]
+
+  Synopsis    [Methods for performing image computations.]
+
+  Description [The image package is used to compute the image (forward or
+  backward) of a set under a vector of functions.  The functions are given by
+  a graph of multi-valued functions (MVFs). This graph is built using the
+  partition package. Each vertex in this graph has an MVF and an MDD id.  The
+  fanins of a vertex v give those vertices upon which the MVF at v depends.
+  The vector of functions to use for an image computation, the "roots", is
+  specified by an array of (names of) vertices of the graph.  The domain
+  variables are the variables over which "from" sets are defined for forward
+  images, and "to" sets are defined for backward images.  The range variables
+  are the variables over which "to" sets are defined for forward images, and
+  "from" sets are defined for backward images.  The quantify variables are
+  additional variables over which the functions are defined; this set is
+  disjoint from domain variables.  These variables are existentially
+  quantified from the results of backward image computation. <p>
+  
+  Computing images is fundamental to many symbolic analysis techniques, and
+  methods for computing images efficiently is an area of ongoing research.
+  For this reason, the image package has been designed with lots of
+  flexibility to easily allow new methods to be integrated (to add a new
+  method, see the instructions in imgInt.h).  Applications that use the image
+  package can switch among different image methods simply by specifying the
+  method type in the image initialization routine.  By using the returned
+  structure (Img_ImageInfo_t) from the initialization routine, all subsequent
+  (forward or backward) image computations will be done using the specified
+  method.<p>
+  
+  VIS users can control which image method is used by appropriately setting
+  the "image_method" flag.  Also, VIS users can set flags to control
+  parameters for different image computation methods.  Because the user has
+  the ability to change the values of these flags, Img_ImageInfo_t structs
+  should be freed and re-initialized whenever the VIS user changes the value
+  of these flags.<p>
+  
+  Following are descriptions of the methods implemented. In the descriptions,
+  x=x_1,...x_n is the set of domain variables, u=u_1,...,u_k is the set of
+  quantify variables, y=y_1,...,y_m is the set of range variables, and
+  f=f_1(x,u),...,f_m(x,u) is the set of functions under which we wish to
+  compute images.<p>
+  
+  <b>Monolithic:</b> This is the most naive approach possible.  A single
+  relation T(x,y) is constructed during the initialization phase, using the
+  computation (exists u (prod_i(y_i = f_i(x,u)))). To compute the forward
+  image, where fromUpperBound=U(x), fromLowerBound=L(x), and toCareSet=C(y),
+  we first compute a set A(x) between U(x) and L(x).  Then, T(x,y) is
+  simplified with respect to A(x) and C(y) to get T*.  Finally, x is
+  quantified from T* to produce the final answer.  Backward images are
+  computed analogously.  The monolithic method does not recognize any
+  user-settable flags for image computation.<p>
+
+  <b>IWLS95:</b> This technique is based on the early quantification heuristic.
+  The initialization process consists of following steps:   
+  <UL>
+  <LI> Create the relation of the roots at the bit level
+  in terms of the quantify and domain variables.
+  <LI> Order the bit level relations.
+  <LI> Group the relations of bits together, making a cluster
+  whenever the BDD size reaches a threshold.
+  <LI> For each cluster, quantify out the quantify variables which
+  are local to that particular cluster.
+  <LI> Order the clusters using the algorithm given in
+  "Efficient BDD Algorithms for FSM Synthesis and
+  Verification", by R. K. Ranjan et. al. in the proceedings of
+  IWLS'95{1}. 
+  <LI> The orders of the clusters for forward and backward image are
+  calculated and stored. Also stored is the schedule of
+  variables for early quantification. 
+  </UL>
+  For forward and backward image computation the corresponding
+  routines are called with appropriate ordering of clusters and
+  early quantification schedule. <p>]
+
+  Author      [Rajeev Ranjan, Tom Shiple, Abelardo Pardo, In-Ho Moon]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: img.h,v 1.50 2005/05/15 01:03:36 jinh Exp $]
+
+******************************************************************************/
+
+#ifndef _IMG
+#define _IMG
+
+#include "vm.h"
+#include "ntk.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/* This is a threshold for finding dependent variables. */
+#define	IMG_MAX_DEP_SIZE	20
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef struct ImgImageInfoStruct Img_ImageInfo_t;
+
+/**Enum************************************************************************
+
+  Synopsis    [Methods for image computation.  See the description in img.h.]
+
+******************************************************************************/
+typedef enum {
+  Img_Monolithic_c,
+  Img_Iwls95_c,
+  Img_Mlp_c,
+  Img_Tfm_c, /* transition function method */
+  Img_Hybrid_c, /* hybrid image comutation */
+  Img_Linear_c,
+  Img_Linear_Range_c,
+  Img_Default_c
+} Img_MethodType;
+
+
+/**Enum************************************************************************
+
+  Synopsis    [Type to indicate the direction of image computation.]
+
+  Description [Type to indicate the direction of image computation.  When an
+  imageInfo structure is initialized, the application must specify what
+  "directions" of image computation will be performed: forward, backward, or
+  both.]
+
+******************************************************************************/
+typedef enum {
+  Img_Forward_c,
+  Img_Backward_c,
+  Img_Both_c
+} Img_DirectionType;
+
+
+/**Enum************************************************************************
+
+  Synopsis    [Type to indicate image minimization method.]
+
+  Description [Type to indicate image minimization method.]
+
+******************************************************************************/
+typedef enum {
+  Img_Restrict_c, /* default */
+  Img_Constrain_c,
+  Img_Compact_c,
+  Img_Squeeze_c,
+  Img_And_c,
+  Img_OrNot_c,
+  Img_DefaultMinimizeMethod_c /* refer to img_minimize_method */
+} Img_MinimizeType;
+
+/**Enum************************************************************************
+
+  Synopsis    [Image substitute direction]
+
+******************************************************************************/
+typedef enum {
+  Img_D2R_c,	/* domain to range */
+  Img_R2D_c	/* range to domain */
+} Img_SubstituteDir;
+
+/**Enum************************************************************************
+
+  Synopsis    [State variables optimization direction]
+
+******************************************************************************/
+typedef enum {
+  Opt_None,
+  Opt_CS,
+  Opt_NS,
+  Opt_Both
+} Img_OptimizeType;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN int Img_ImageBuildFwdLFPRelation(Ntk_Network_t *network, Img_ImageInfo_t *imageInfo, mdd_t *constraint, int whichTime, int *maxTime, int *numBlocks);
+EXTERN void Img_PrintHybridOptions(void);
+EXTERN mdd_t* Img_MultiwayLinearAndSmooth(mdd_manager *mddManager, array_t *relationArray, array_t *smoothVarMddIdArray, array_t *introducedVarMddIdArray, Img_MethodType method, Img_DirectionType direction);
+EXTERN void Img_PrintPartitionedTransitionRelation(mdd_manager *mddManager, Img_ImageInfo_t *imageInfo, Img_DirectionType directionType);
+EXTERN void Img_ReorderPartitionedTransitionRelation(Img_ImageInfo_t *imageInfo, Img_DirectionType directionType);
+EXTERN void Img_UpdateQuantificationSchedule(Img_ImageInfo_t *imageInfo, Img_DirectionType directionType);
+EXTERN void Img_ClusterRelationArray(mdd_manager *mddManager, Img_MethodType method, Img_DirectionType direction, array_t *relationArray, array_t *domainVarMddIdArray, array_t *rangeVarMddIdArray, array_t *quantifyVarMddIdArray, array_t **clusteredRelationArray, array_t **arraySmoothVarBddArray, array_t **smoothVarCubeArray, boolean freeRelationArray);
+EXTERN void Img_PrintMlpOptions(void);
+EXTERN int Img_TfmGetRecursionStatistics(Img_ImageInfo_t *imageInfo, int preFlag, int *nRecurs, int *nLeaves, int *nTurns, float *averageDepth, int *maxDepth, int *nDecomps, int *topDecomp, int *maxDecomp, float *averageDecomp);
+EXTERN void Img_TfmPrintStatistics(Img_ImageInfo_t *imageInfo, Img_DirectionType dir);
+EXTERN void Img_TfmPrintRecursionStatistics(Img_ImageInfo_t *imageInfo, int preFlag);
+EXTERN void Img_PrintTfmOptions(void);
+EXTERN int Img_TfmGetCacheStatistics(Img_ImageInfo_t *imageInfo, int preFlag, double *inserts, double *lookups, double *hits, double *entries, int *nSlots, int *maxChainLength);
+EXTERN int Img_TfmCheckGlobalCache(int preFlag);
+EXTERN void Img_TfmPrintCacheStatistics(Img_ImageInfo_t *imageInfo, int preFlag);
+EXTERN void Img_TfmFlushCache(Img_ImageInfo_t *imageInfo, int preFlag);
+EXTERN void Img_Init(void);
+EXTERN void Img_End(void);
+EXTERN Img_MethodType Img_UserSpecifiedMethod(void);
+EXTERN Img_ImageInfo_t * Img_ImageInfoInitialize(Img_ImageInfo_t *imageInfo, graph_t * mddNetwork, array_t * roots, array_t * domainVars, array_t * rangeVars, array_t * quantifyVars, mdd_t * domainCube, mdd_t * rangeCube, mdd_t * quantifyCube, Ntk_Network_t * network, Img_MethodType methodType, Img_DirectionType directionType, int FAFWFlag, mdd_t *winning);
+EXTERN void Img_ImageInfoUpdateVariables(Img_ImageInfo_t *imageInfo, graph_t * mddNetwork, array_t * domainVars, array_t * quantifyVars, mdd_t * domainCube, mdd_t * quantifyCube);
+EXTERN void Img_ImageAllowPartialImage(Img_ImageInfo_t *info, boolean value);
+EXTERN void Img_ImagePrintPartialImageOptions(void);
+EXTERN boolean Img_ImageWasPartial(Img_ImageInfo_t *info);
+EXTERN mdd_t * Img_ImageInfoComputeImageWithDomainVars(Img_ImageInfo_t * imageInfo, mdd_t * fromLowerBound, mdd_t * fromUpperBound, array_t * toCareSetArray);
+EXTERN mdd_t * Img_ImageInfoComputeFwdWithDomainVars(Img_ImageInfo_t * imageInfo, mdd_t * fromLowerBound, mdd_t * fromUpperBound, mdd_t * toCareSet);
+EXTERN mdd_t * Img_ImageInfoComputeFwd(Img_ImageInfo_t * imageInfo, mdd_t * fromLowerBound, mdd_t * fromUpperBound, array_t * toCareSetArray);
+EXTERN mdd_t * Img_ImageInfoComputePreImageWithDomainVars(Img_ImageInfo_t * imageInfo, mdd_t * fromLowerBound, mdd_t * fromUpperBound, array_t * toCareSetArray);
+EXTERN mdd_t * Img_ImageInfoComputeEXWithDomainVars(Img_ImageInfo_t * imageInfo, mdd_t * fromLowerBound, mdd_t * fromUpperBound, array_t * toCareSetArray);
+EXTERN mdd_t * Img_ImageInfoComputeBwdWithDomainVars(Img_ImageInfo_t * imageInfo, mdd_t * fromLowerBound, mdd_t * fromUpperBound, mdd_t * toCareSet);
+EXTERN mdd_t * Img_ImageInfoComputeBwd(Img_ImageInfo_t * imageInfo, mdd_t * fromLowerBound, mdd_t * fromUpperBound, array_t * toCareSetArray);
+EXTERN void Img_ImageInfoFree(Img_ImageInfo_t * imageInfo);
+EXTERN char * Img_ImageInfoObtainMethodTypeAsString(Img_ImageInfo_t * imageInfo);
+EXTERN Img_MethodType Img_ImageInfoObtainMethodType(Img_ImageInfo_t * imageInfo);
+EXTERN void Img_ImageInfoPrintMethodParams(Img_ImageInfo_t *imageInfo, FILE *fp);
+EXTERN void Img_ResetTrMinimizedFlag(Img_ImageInfo_t *imageInfo, Img_DirectionType directionType);
+EXTERN Img_MinimizeType Img_ReadMinimizeMethod(void);
+EXTERN void Img_MinimizeTransitionRelation(Img_ImageInfo_t *imageInfo, array_t *constrainArray, Img_MinimizeType minimizeMethod, Img_DirectionType directionType, boolean reorderIwls95Clusters);
+EXTERN mdd_t * Img_MinimizeImage(mdd_t *image, mdd_t *constraint, Img_MinimizeType method, boolean underapprox);
+EXTERN mdd_t * Img_AddDontCareToImage(mdd_t *image, mdd_t *constraint, Img_MinimizeType method);
+EXTERN mdd_t * Img_MinimizeImageArray(mdd_t *image, array_t *constraintArray, Img_MinimizeType method, boolean underapprox);
+EXTERN void Img_SetPrintMinimizeStatus(Img_ImageInfo_t *imageInfo, int status);
+EXTERN int Img_ReadPrintMinimizeStatus(Img_ImageInfo_t *imageInfo);
+EXTERN void Img_AbstractTransitionRelation(Img_ImageInfo_t *imageInfo, array_t *abstractVars, mdd_t *abstractCube, Img_DirectionType directionType);
+EXTERN void Img_DupTransitionRelation(Img_ImageInfo_t *imageInfo, Img_DirectionType directionType);
+EXTERN void Img_RestoreTransitionRelation(Img_ImageInfo_t *imageInfo, Img_DirectionType directionType);
+EXTERN int Img_ApproximateTransitionRelation(Img_ImageInfo_t *imageInfo, bdd_approx_dir_t approxDir, bdd_approx_type_t approxMethod, int approxThreshold, double approxQuality, double approxQualityBias, Img_DirectionType directionType, mdd_t *bias);
+EXTERN mdd_t * Img_ApproximateImage(mdd_manager *mgr, mdd_t *image, bdd_approx_dir_t approxDir, bdd_approx_type_t approxMethod, int approxThreshold, double approxQuality, double approxQualityBias, mdd_t *bias);
+EXTERN int Img_IsPartitionedTransitionRelation(Img_ImageInfo_t *imageInfo);
+EXTERN void Img_ResetNumberOfImageComputation(Img_DirectionType imgDir);
+EXTERN int Img_GetNumberOfImageComputation(Img_DirectionType imgDir);
+EXTERN array_t * Img_GetPartitionedTransitionRelation(Img_ImageInfo_t *imageInfo, Img_DirectionType directionType);
+EXTERN void Img_ReplaceIthPartitionedTransitionRelation(Img_ImageInfo_t *imageInfo, int i, mdd_t *relation, Img_DirectionType directionType);
+EXTERN void Img_ReplacePartitionedTransitionRelation(Img_ImageInfo_t *imageInfo, array_t *relationArray, Img_DirectionType directionType);
+EXTERN mdd_t * Img_ComposeIntermediateNodes(graph_t *partition, mdd_t *node, array_t *psVars, array_t *nsVars, array_t *inputVars);
+EXTERN void Img_ImageConstrainAndClusterTransitionRelation(Img_ImageInfo_t *imageInfo, Img_DirectionType direction, mdd_t *constrain, Img_MinimizeType minimizeMethod, boolean underApprox, boolean cleanUp, boolean forceReorder, int printStatus);
+EXTERN Img_MinimizeType Img_GuidedSearchReadUnderApproxMinimizeMethod(void);
+EXTERN Img_MinimizeType Img_GuidedSearchReadOverApproxMinimizeMethod(void);
+EXTERN mdd_t * Img_Substitute(Img_ImageInfo_t *imageInfo, mdd_t *f, Img_SubstituteDir dir);
+EXTERN mdd_t * Img_ImageGetUnreachableStates(Img_ImageInfo_t * imageInfo);
+EXTERN void Img_ImageInfoSetUseOptimizedRelationFlag(Img_ImageInfo_t * imageInfo);
+EXTERN void Img_ImageInfoResetUseOptimizedRelationFlag(Img_ImageInfo_t * imageInfo);
+EXTERN void Img_ImageInfoResetLinearComputeRange(Img_ImageInfo_t * imageInfo);
+EXTERN void Img_ImageInfoSetLinearComputeRange(Img_ImageInfo_t * imageInfo);
+EXTERN int Img_IsTransitionRelationOptimized(Img_ImageInfo_t * imageInfo);
+EXTERN void Img_ForwardImageInfoConjoinWithWinningStrategy( Img_ImageInfo_t * imageInfo, mdd_t *winningStrategy);
+EXTERN void Img_ForwardImageInfoRecoverFromWinningStrategy( Img_ImageInfo_t * imageInfo);
+EXTERN Img_OptimizeType Img_ImageInfoObtainOptimizeType(Img_ImageInfo_t * imageInfo);
+EXTERN int Img_IsQuantifyCubeSame( Img_ImageInfo_t *imageInfo, mdd_t *quantifyCube);
+EXTERN int Img_IsQuantifyArraySame( Img_ImageInfo_t *imageInfo, array_t *quantifyArray);
+EXTERN void Img_ImageInfoFreeFAFW(Img_ImageInfo_t * imageInfo);
+
+
+
+
+/**
+EXTERN void ImgLinearClusterRelationArray(mdd_manager *mgr, ImgFunctionData_t *functionData, array_t *relationArray, Img_DirectionType direction, array_t **clusteredRelationArrayPtr, array_t **arraySmoothVarBddArrayPtr, array_t **optClusteredRelationArrayPtr, array_t **optArraySmoothVarBddArrayPtr, ImgTrmOption_t *option);
+**/
+
+
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _IMG */
Index: vis_dev/vis-2.3/src/img/img.make
===================================================================
--- vis_dev/vis-2.3/src/img/img.make	(revision 14)
+++ vis_dev/vis-2.3/src/img/img.make	(revision 14)
@@ -0,0 +1,5 @@
+CSRC += imgLinear.c imgHybrid.c imgIwls95.c imgMlp.c imgMonolithic.c imgTfm.c \
+	imgTfmBwd.c imgTfmCache.c imgTfmFwd.c imgTfmUtil.c imgUtil.c
+HEADERS += img.h imgInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/img/imgHybrid.c
===================================================================
--- vis_dev/vis-2.3/src/img/imgHybrid.c	(revision 14)
+++ vis_dev/vis-2.3/src/img/imgHybrid.c	(revision 14)
@@ -0,0 +1,1605 @@
+/**CFile***********************************************************************
+
+  FileName    [imgHybrid.c]
+
+  PackageName [img]
+
+  Synopsis    [Routines for hybrid image computation.]
+
+  Description [The hybrid image computation method combines transition function
+  and relation methods, in other words, combines splitting and conjunction
+  methods.]
+
+  SeeAlso     []
+
+  Author      [In-Ho Moon]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF COLORADO BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  COLORADO HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF COLORADO SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF COLORADO HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+#include "imgInt.h"
+
+static char rcsid[] UNUSED = "$Id: imgHybrid.c,v 1.27 2008/11/27 02:19:53 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static float ComputeSupportLambda(ImgTfmInfo_t *info, array_t *relationArray, mdd_t *cofactorCube, mdd_t *abstractCube, mdd_t *from, array_t *vector, int newRelationFlag, int preFlag, float *improvedLambda);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the options for hybrid image computation.]
+
+  Description [Prints the options for hybrid image computation.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Img_PrintHybridOptions(void)
+{
+  ImgTfmOption_t	*options;
+  char			dummy[80];
+
+  options = ImgTfmGetOptions(Img_Hybrid_c);
+
+  switch (options->hybridMode) {
+  case 0 :
+    sprintf(dummy, "with only transition function");
+    break;
+  case 1 :
+    sprintf(dummy, "with both transition function and relation");
+    break;
+  case 2 :
+    sprintf(dummy, "with only transition relation");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "HYB: hybrid_mode = %d (%s)\n",
+	  options->hybridMode, dummy);
+
+  switch (options->trSplitMethod) {
+  case 0 :
+    sprintf(dummy, "support");
+    break;
+  case 1 :
+    sprintf(dummy, "estimate BDD size");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "HYB: hybrid_tr_split_method = %d (%s)\n",
+	  options->trSplitMethod, dummy);
+
+  if (options->buildPartialTR)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "HYB: hybrid_build_partial_tr = %s\n", dummy);
+
+  fprintf(vis_stdout, "HYB: hybrid_partial_num_vars = %d\n",
+	  options->nPartialVars);
+
+  switch (options->partialMethod) {
+  case 0 :
+    sprintf(dummy, "BDD size");
+    break;
+  case 1 :
+    sprintf(dummy, "support");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "HYB: hybrid_partial_method = %d (%s)\n",
+	  options->partialMethod, dummy);
+
+  if (options->delayedSplit)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "HYB: hybrid_delayed_split = %s\n", dummy);
+
+  fprintf(vis_stdout, "HYB: hybrid_split_min_depth = %d\n",
+	  options->splitMinDepth);
+  fprintf(vis_stdout, "HYB: hybrid_split_max_depth = %d\n",
+	  options->splitMaxDepth);
+  fprintf(vis_stdout, "HYB: hybrid_pre_split_min_depth = %d\n",
+	  options->preSplitMinDepth);
+  fprintf(vis_stdout, "HYB: hybrid_pre_split_max_depth = %d\n",
+	  options->preSplitMaxDepth);
+
+  fprintf(vis_stdout, "HYB: hybrid_lambda_threshold = %.2f\n",
+	  options->lambdaThreshold);
+  fprintf(vis_stdout, "HYB: hybrid_pre_lambda_threshold = %.2f\n",
+	  options->preLambdaThreshold);
+  fprintf(vis_stdout, "HYB: hybrid_conjoin_vector_size = %d\n",
+	  options->conjoinVectorSize);
+  fprintf(vis_stdout, "HYB: hybrid_conjoin_relation_size = %d\n",
+	  options->conjoinRelationSize);
+  fprintf(vis_stdout, "HYB: hybrid_conjoin_relation_bdd_size = %d\n",
+	  options->conjoinRelationBddSize);
+  fprintf(vis_stdout, "HYB: hybrid_improve_lambda = %.2f\n",
+	  options->improveLambda);
+  fprintf(vis_stdout, "HYB: hybrid_improve_vector_size = %d\n",
+	  options->improveVectorSize);
+  fprintf(vis_stdout, "HYB: hybrid_improve_vector_bdd_size = %.2f\n",
+	  options->improveVectorBddSize);
+
+  switch (options->decideMode) {
+  case 0 :
+    sprintf(dummy, "use only lambda");
+    break;
+  case 1 :
+    sprintf(dummy, "lambda + special check");
+    break;
+  case 2 :
+    sprintf(dummy, "lambda + improvement");
+    break;
+  case 3 :
+    sprintf(dummy, "use all");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "HYB: hybrid_decide_mode = %d (%s)\n",
+	  options->decideMode, dummy);
+
+  if (options->reorderWithFrom)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "HYB: hybrid_reorder_with_from = %s\n", dummy);
+
+  if (options->preReorderWithFrom)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "HYB: hybrid_pre_reorder_with_from = %s\n", dummy);
+
+  switch (options->lambdaMode) {
+  case 0 :
+    sprintf(dummy, "total lifetime with ps/pi variables");
+    break;
+  case 1 :
+    sprintf(dummy, "active lifetime with ps/pi variables");
+    break;
+  case 2 :
+    sprintf(dummy, "total lifetime with ps/ns/pi variables");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "HYB: hybrid_lambda_mode = %d (%s)\n",
+	  options->lambdaMode, dummy);
+
+  switch (options->preLambdaMode) {
+  case 0 :
+    sprintf(dummy, "total lifetime with ns/pi variables");
+    break;
+  case 1 :
+    sprintf(dummy, "active lifetime with ps/pi variables");
+    break;
+  case 2 :
+    sprintf(dummy, "total lifetime with ps/ns/pi variables");
+    break;
+  case 3 :
+    sprintf(dummy, "total lifetime with ps/pi variables");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "HYB: hybrid_pre_lambda_mode = %d (%s)\n",
+	  options->preLambdaMode, dummy);
+
+  if (options->lambdaWithFrom)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "HYB: hybrid_lambda_with_from = %s\n", dummy);
+
+  if (options->lambdaWithTr)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "HYB: hybrid_lambda_with_tr = %s\n", dummy);
+
+  if (options->lambdaWithClustering)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "HYB: hybrid_lambda_with_clustering = %s\n", dummy);
+
+  if (options->synchronizeTr)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "HYB: hybrid_synchronize_tr = %s\n", dummy);
+
+  if (options->imgKeepPiInTr)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "HYB: hybrid_img_keep_pi = %s\n", dummy);
+
+  if (options->preKeepPiInTr)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "HYB: hybrid_pre_keep_pi = %s\n", dummy);
+
+  if (options->preCanonical)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "HYB: hybrid_pre_canonical = %s\n", dummy);
+
+  switch (options->trMethod) {
+  case Img_Iwls95_c :
+    sprintf(dummy, "IWLS95");
+    break;
+  case Img_Mlp_c :
+    sprintf(dummy, "MLP");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "HYB: hybrid_tr_method = %s\n", dummy);
+
+  FREE(options);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Decides whether to split or to conjoin.]
+
+  Description [Decides whether to split or to conjoin.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+ImgDecideSplitOrConjoin(ImgTfmInfo_t *info, array_t *vector, mdd_t *from,
+			int preFlag, array_t *relationArray,
+			mdd_t *cofactorCube, mdd_t *abstractCube,
+			int useBothFlag, int depth)
+{
+  int	conjoin = 0;
+  float	lambda, improvedLambda;
+  int	vectorBddSize, vectorSize;
+  int	improved;
+  int	minDepth;
+  int	checkSpecialCases;
+  int	checkImprovement;
+  int	relationSize = 0;
+
+  if (!preFlag) {
+    if (vector && array_n(vector) <= 2)
+      return(0); /* terminal case */
+  }
+
+  if (info->option->decideMode == 1 || info->option->decideMode == 3)
+    checkSpecialCases = 1;
+  else
+    checkSpecialCases = 0;
+  if (info->option->decideMode == 2 || info->option->decideMode == 3)
+    checkImprovement = 1;
+  else
+    checkImprovement = 0;
+
+  if (checkSpecialCases) {
+    if (vector && array_n(vector) <= info->option->conjoinVectorSize) {
+      if (preFlag)
+	info->nConjoinsB++;
+      else
+	info->nConjoins++;
+      if (info->option->printLambda) {
+	fprintf(vis_stdout, "%d: conjoin - small vector size (%d)\n",
+		depth, array_n(vector));
+      }
+      return(1);
+    }
+  }
+
+  if (preFlag)
+    minDepth = info->option->preSplitMinDepth;
+  else
+    minDepth = info->option->splitMinDepth;
+
+  if (useBothFlag && relationArray && vector) {
+    lambda = ComputeSupportLambda(info, relationArray, cofactorCube,
+				  abstractCube, from, vector,
+				  0, preFlag, &improvedLambda);
+  } else if (relationArray) {
+    if (checkSpecialCases) {
+      if (array_n(relationArray) <= info->option->conjoinRelationSize ||
+	  (relationSize = (int)bdd_size_multiple(relationArray)) <=
+		info->option->conjoinRelationBddSize) {
+	if (preFlag)
+	  info->nConjoinsB++;
+	else
+	  info->nConjoins++;
+	if (info->option->printLambda) {
+	  fprintf(vis_stdout, "%d: conjoin - small relation array (%d, %ld)\n",
+		  depth, array_n(relationArray),
+		  bdd_size_multiple(relationArray));
+	}
+	return(1);
+      }
+    }
+
+    lambda = ComputeSupportLambda(info, relationArray, cofactorCube,
+				  abstractCube, from, NIL(array_t),
+				  0, preFlag, &improvedLambda);
+  } else {
+    int		i;
+    ImgComponent_t	*comp;
+
+    relationArray = array_alloc(mdd_t *, 0);
+    for (i = 0; i < array_n(vector); i++) {
+      comp = array_fetch(ImgComponent_t *, vector, i);
+      array_insert_last(mdd_t *, relationArray, comp->func);
+    }
+
+    lambda = ComputeSupportLambda(info, relationArray, NIL(mdd_t),
+				  NIL(mdd_t), from, NIL(array_t),
+				  1, preFlag, &improvedLambda);
+
+    array_free(relationArray);
+  }
+
+  if ((preFlag == 0 && lambda <= info->option->lambdaThreshold) ||
+      (preFlag == 1 && lambda <= info->option->preLambdaThreshold)) {
+    if (preFlag)
+      info->nConjoinsB++;
+    else
+      info->nConjoins++;
+    if (info->option->printLambda) {
+      fprintf(vis_stdout, "%d: conjoin - small lambda (%.2f)\n",
+	      depth, lambda);
+    }
+    conjoin = 1;
+  } else {
+    if (checkImprovement) {
+      if (vector) {
+	vectorBddSize = ImgVectorBddSize(vector);
+	vectorSize = array_n(vector);
+	if (depth == minDepth ||
+	    improvedLambda >= info->option->improveLambda ||
+	    ((float)vectorBddSize * 100.0 / (float)info->prevVectorBddSize) <=
+		info->option->improveVectorBddSize ||
+	    (info->prevVectorSize - vectorSize) >=
+		info->option->improveVectorSize) {
+	  improved = 1;
+	} else
+	  improved = 0;
+	info->prevVectorBddSize = vectorBddSize;
+	info->prevVectorSize = vectorSize;
+      } else {
+	if (relationSize)
+	  vectorBddSize = relationSize;
+	else
+	  vectorBddSize = (int)bdd_size_multiple(relationArray);
+	if (depth == minDepth ||
+	    improvedLambda >= info->option->improveLambda ||
+	    ((float)vectorBddSize * 100.0 / (float)info->prevVectorBddSize) <=
+		info->option->improveVectorBddSize) {
+	  improved = 1;
+	} else
+	  improved = 0;
+	info->prevVectorBddSize = vectorBddSize;
+      }
+      if (improved) {
+	if (preFlag)
+	  info->nSplitsB++;
+	else
+	  info->nSplits++;
+	if (info->option->printLambda) {
+	  fprintf(vis_stdout, "%d: split - big lambda (%.2f) - improved\n",
+		  depth, lambda);
+	}
+	conjoin = 0;
+      } else {
+	if (preFlag)
+	  info->nConjoinsB++;
+	else
+	  info->nConjoins++;
+	if (info->option->printLambda) {
+	  fprintf(vis_stdout, "%d: conjon - big lambda (%.2f) - not improved\n",
+		  depth, lambda);
+	}
+	conjoin = 1;
+      }
+    } else {
+      if (preFlag)
+	info->nSplitsB++;
+      else
+	info->nSplits++;
+      if (info->option->printLambda) {
+	fprintf(vis_stdout, "%d: split - big lambda (%.2f)\n",
+	      depth, lambda);
+      }
+      conjoin = 0;
+    }
+  }
+
+  return(conjoin); /* 0 : split, 1 : conjoin */
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes an image by transition relation.]
+
+  Description [Computes an image by transition relation.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+ImgImageByHybrid(ImgTfmInfo_t *info, array_t *vector, mdd_t *from)
+{
+  int			i, j, nVars;
+  array_t		*relationArray;
+  mdd_t			*result, *domain, *relation, *var, *nextVar;
+  ImgComponent_t	*comp;
+  char			*support;
+  array_t		*smoothVarsBddArray, *introducedVarsBddArray;
+  array_t		*domainVarsBddArray;
+  int			bddId;
+
+  if (from && bdd_is_tautology(from, 0))
+    return(mdd_zero(info->manager));
+
+  nVars = info->nVars;
+  support = ALLOC(char, sizeof(char) * nVars);
+  memset(support, 0, sizeof(char) * nVars);
+
+  relationArray = array_alloc(mdd_t *, 0);
+  introducedVarsBddArray = array_alloc(mdd_t *, 0);
+
+  for (i = 0; i < array_n(vector); i++) {
+    comp = array_fetch(ImgComponent_t *, vector, i);
+    if (comp->intermediate) {
+      relation = mdd_xnor(comp->var, comp->func);
+      bddId = (int)bdd_top_var_id(comp->var);
+      support[bddId] = 1;
+    } else {
+      nextVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+      relation = mdd_xnor(nextVar, comp->func);
+      array_insert_last(mdd_t *, introducedVarsBddArray, nextVar);
+    }
+    array_insert_last(mdd_t *, relationArray, relation);
+ 
+    for (j = 0; j < nVars; j++)
+      support[j] = support[j] | comp->support[j];
+  }
+
+  if (from && (!bdd_is_tautology(from, 1))) {
+    if (info->option->reorderWithFrom)
+      array_insert_last(mdd_t *, relationArray, mdd_dup(from));
+
+    comp = ImgComponentAlloc(info);
+    comp->func = from;
+    ImgComponentGetSupport(comp);
+    for (i = 0; i < nVars; i++)
+      support[i] = support[i] | comp->support[i];
+    comp->func = NIL(mdd_t);
+    ImgComponentFree(comp);
+  }
+
+  smoothVarsBddArray = array_alloc(mdd_t *, 0);
+  if (!info->option->reorderWithFrom)
+    domainVarsBddArray = array_alloc(mdd_t *, 0);
+  else
+    domainVarsBddArray = NIL(array_t);
+  for (i = 0; i < nVars; i++) {
+    if (support[i]) {
+      var = bdd_var_with_index(info->manager, i);
+      if ((!from) || info->option->reorderWithFrom)
+	array_insert_last(mdd_t *, smoothVarsBddArray, var);
+      else {
+	if (st_lookup(info->quantifyVarsTable, (char *)(long)i, NIL(char *)) ||
+	    (info->intermediateVarsTable &&
+	     st_lookup(info->intermediateVarsTable, (char *)(long)i,
+			NIL(char *)))) {
+	  array_insert_last(mdd_t *, smoothVarsBddArray, var);
+	} else {
+	  array_insert_last(mdd_t *, domainVarsBddArray, var);
+	}
+      }
+    }
+  }
+  FREE(support);
+
+  if ((!from) || info->option->reorderWithFrom) {
+    result = ImgMultiwayLinearAndSmooth(info->manager,
+					relationArray,
+					smoothVarsBddArray,
+					introducedVarsBddArray,
+					info->option->trMethod,
+					Img_Forward_c,
+					info->trmOption);
+  } else {
+    result = ImgMultiwayLinearAndSmoothWithFrom(info->manager,
+						relationArray, from,
+						smoothVarsBddArray,
+						domainVarsBddArray,
+						introducedVarsBddArray,
+						info->option->trMethod,
+						Img_Forward_c,
+						info->trmOption);
+    mdd_array_free(domainVarsBddArray);
+  }
+  mdd_array_free(relationArray);
+  mdd_array_free(smoothVarsBddArray);
+  mdd_array_free(introducedVarsBddArray);
+  domain = ImgSubstitute(result, info->functionData, Img_R2D_c);
+  mdd_free(result);
+  return(domain);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes an image by transition relation.]
+
+  Description [Computes an image by transition relation.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+ImgImageByHybridWithStaticSplit(ImgTfmInfo_t *info, array_t *vector,
+				mdd_t *from, array_t *relationArray,
+				mdd_t *cofactorCube, mdd_t *abstractCube)
+{
+  int			i, j;
+  array_t		*mergedRelationArray;
+  mdd_t			*result, *domain, *relation, *var, *nextVar;
+  ImgComponent_t	*comp, *supportComp;
+  int			nVars;
+  char			*support;
+  array_t		*smoothVarsBddArray, *introducedVarsBddArray;
+  array_t		*domainVarsBddArray;
+
+  if (from && bdd_is_tautology(from, 0))
+    return(mdd_zero(info->manager));
+
+  if (cofactorCube && abstractCube) {
+    if (!bdd_is_tautology(cofactorCube, 1) &&
+	!bdd_is_tautology(abstractCube, 1)) {
+      mergedRelationArray = ImgGetCofactoredAbstractedRelationArray(
+					info->manager, relationArray,
+					cofactorCube, abstractCube);
+    } else if (!bdd_is_tautology(cofactorCube, 1)) {
+      mergedRelationArray = ImgGetCofactoredRelationArray(relationArray,
+							  cofactorCube);
+    } else if (!bdd_is_tautology(abstractCube, 1)) {
+      mergedRelationArray = ImgGetAbstractedRelationArray(info->manager,
+							  relationArray,
+							  abstractCube);
+    } else
+      mergedRelationArray = mdd_array_duplicate(relationArray);
+  } else
+    mergedRelationArray = mdd_array_duplicate(relationArray);
+
+  nVars = info->nVars;
+  support = ALLOC(char, sizeof(char) * nVars);
+  memset(support, 0, sizeof(char) * nVars);
+
+  supportComp = ImgComponentAlloc(info);
+  for (i = 0; i < array_n(mergedRelationArray); i++) {
+    supportComp->func = array_fetch(mdd_t *, mergedRelationArray, i);;
+    ImgSupportClear(info, supportComp->support);
+    ImgComponentGetSupport(supportComp);
+    for (j = 0; j < nVars; j++)
+      support[j] = support[j] | supportComp->support[j];
+  }
+
+  if (vector && array_n(vector) > 0) {
+    for (i = 0; i < array_n(vector); i++) {
+      comp = array_fetch(ImgComponent_t *, vector, i);
+      if (comp->intermediate) {
+	relation = mdd_xnor(comp->var, comp->func);
+	support[(int)bdd_top_var_id(comp->var)] = 1;
+      } else {
+	nextVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+	relation = mdd_xnor(nextVar, comp->func);
+	support[(int)bdd_top_var_id(nextVar)] = 1;
+	mdd_free(nextVar);
+      }
+      array_insert_last(mdd_t *, mergedRelationArray, relation);
+
+      for (j = 0; j < nVars; j++)
+	support[j] = support[j] | comp->support[j];
+    }
+  }
+
+  if (from) {
+    if ((!bdd_is_tautology(from, 1)) && info->option->reorderWithFrom)
+      array_insert_last(mdd_t *, mergedRelationArray, mdd_dup(from));
+
+    supportComp->func = from;
+    ImgSupportClear(info, supportComp->support);
+    ImgComponentGetSupport(supportComp);
+    for (i = 0; i < nVars; i++)
+      support[i] = support[i] | supportComp->support[i];
+  }
+  supportComp->func = NIL(mdd_t);
+  ImgComponentFree(supportComp);
+
+  smoothVarsBddArray = array_alloc(mdd_t *, 0);
+  introducedVarsBddArray = array_alloc(mdd_t *, 0);
+  if (!info->option->reorderWithFrom)
+    domainVarsBddArray = array_alloc(mdd_t *, 0);
+  else
+    domainVarsBddArray = NIL(array_t);
+  for (i = 0; i < nVars; i++) {
+    if (support[i]) {
+      var = bdd_var_with_index(info->manager, i);
+      if (st_lookup(info->rangeVarsTable, (char *)(long)i, NIL(char *)))
+	array_insert_last(mdd_t *, introducedVarsBddArray, var);
+      else if ((!from) || info->option->reorderWithFrom)
+	array_insert_last(mdd_t *, smoothVarsBddArray, var);
+      else {
+	if (st_lookup(info->quantifyVarsTable, (char *)(long)i, NIL(char *)) ||
+	    (info->intermediateVarsTable &&
+	     st_lookup(info->intermediateVarsTable, (char *)(long)i,
+			NIL(char *)))) {
+	  array_insert_last(mdd_t *, smoothVarsBddArray, var);
+	} else {
+	  array_insert_last(mdd_t *, domainVarsBddArray, var);
+	}
+      }
+    }
+  }
+  FREE(support);
+
+  if ((!from) || info->option->reorderWithFrom) {
+    result = ImgMultiwayLinearAndSmooth(info->manager,
+					mergedRelationArray,
+					smoothVarsBddArray,
+					introducedVarsBddArray,
+					info->option->trMethod,
+					Img_Forward_c,
+					info->trmOption);
+  } else {
+    result = ImgMultiwayLinearAndSmoothWithFrom(info->manager,
+						mergedRelationArray, from,
+						smoothVarsBddArray,
+						domainVarsBddArray,
+						introducedVarsBddArray,
+						info->option->trMethod,
+						Img_Forward_c,
+						info->trmOption);
+    mdd_array_free(domainVarsBddArray);
+  }
+  mdd_array_free(mergedRelationArray);
+  mdd_array_free(smoothVarsBddArray);
+  mdd_array_free(introducedVarsBddArray);
+
+  domain = ImgSubstitute(result, info->functionData, Img_R2D_c);
+  mdd_free(result);
+  return(domain);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes a preimage by transition relation.]
+
+  Description [Computes a preimage by transition relation.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+ImgPreImageByHybrid(ImgTfmInfo_t *info, array_t *vector, mdd_t *from)
+{
+  int			i, j, nVars;
+  array_t		*relationArray;
+  mdd_t			*result, *relation, *var, *nextVar;
+  ImgComponent_t	*comp;
+  char			*support;
+  array_t		*smoothVarsBddArray, *introducedVarsBddArray;
+  array_t		*rangeVarsBddArray;
+  mdd_t			*fromRange;
+
+  if (bdd_is_tautology(from, 1))
+    return(mdd_one(info->manager));
+  else if (bdd_is_tautology(from, 0))
+    return(mdd_zero(info->manager));
+
+  nVars = info->nVars;
+  support = ALLOC(char, sizeof(char) * nVars);
+  memset(support, 0, sizeof(char) * nVars);
+
+  relationArray = array_alloc(mdd_t *, 0);
+
+  for (i = 0; i < array_n(vector); i++) {
+    comp = array_fetch(ImgComponent_t *, vector, i);
+    if (comp->intermediate) {
+      relation = mdd_xnor(comp->var, comp->func);
+      support[(int)bdd_top_var_id(comp->var)] = 1;
+    } else {
+      nextVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+      relation = mdd_xnor(nextVar, comp->func);
+      support[(int)bdd_top_var_id(nextVar)] = 1;
+      mdd_free(nextVar);
+    }
+    array_insert_last(mdd_t *, relationArray, relation);
+ 
+    for (j = 0; j < nVars; j++)
+      support[j] = support[j] | comp->support[j];
+  }
+
+  fromRange = ImgSubstitute(from, info->functionData, Img_D2R_c);
+  comp = ImgComponentAlloc(info);
+  comp->func = fromRange;
+  ImgComponentGetSupport(comp);
+  for (i = 0; i < nVars; i++)
+    support[i] = support[i] | comp->support[i];
+  comp->func = NIL(mdd_t);
+  ImgComponentFree(comp);
+
+  smoothVarsBddArray = array_alloc(mdd_t *, 0);
+  introducedVarsBddArray = array_alloc(mdd_t *, 0);
+  if (!info->option->preReorderWithFrom)
+    rangeVarsBddArray = array_alloc(mdd_t *, 0);
+  else
+    rangeVarsBddArray = NIL(array_t);
+  for (i = 0; i < nVars; i++) {
+    if (support[i]) {
+      var = bdd_var_with_index(info->manager, i);
+      if (info->intermediateVarsTable &&
+	  st_lookup(info->intermediateVarsTable, (char *)(long)i,
+		    NIL(char *))) {
+	array_insert_last(mdd_t *, smoothVarsBddArray, var);
+      } else if (st_lookup(info->rangeVarsTable, (char *)(long)i,
+			   NIL(char *))) {
+	if (info->option->preReorderWithFrom)
+	  array_insert_last(mdd_t *, smoothVarsBddArray, var);
+	else
+	  array_insert_last(mdd_t *, rangeVarsBddArray, var);
+      } else {
+	if (info->preKeepPiInTr)
+	  array_insert_last(mdd_t *, introducedVarsBddArray, var);
+	else {
+	  if (st_lookup(info->quantifyVarsTable, (char *)(long)i,
+			NIL(char *))) {
+	    array_insert_last(mdd_t *, smoothVarsBddArray, var);
+	  } else
+	    array_insert_last(mdd_t *, introducedVarsBddArray, var);
+	}
+      }
+    }
+  }
+  FREE(support);
+
+  if (info->option->preReorderWithFrom) {
+    array_insert_last(mdd_t *, relationArray, fromRange);
+    result = ImgMultiwayLinearAndSmooth(info->manager,
+					relationArray,
+					smoothVarsBddArray,
+					introducedVarsBddArray,
+					info->option->trMethod,
+					Img_Backward_c,
+					info->trmOption);
+  } else {
+    result = ImgMultiwayLinearAndSmoothWithFrom(info->manager,
+						relationArray, fromRange,
+						smoothVarsBddArray,
+						rangeVarsBddArray,
+						introducedVarsBddArray,
+						info->option->trMethod,
+						Img_Backward_c,
+						info->trmOption);
+    mdd_free(fromRange);
+    mdd_array_free(rangeVarsBddArray);
+  }
+  mdd_array_free(relationArray);
+  mdd_array_free(smoothVarsBddArray);
+  mdd_array_free(introducedVarsBddArray);
+  return(result);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes a preimage by transition relation.]
+
+  Description [Computes a preimage by transition relation.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+ImgPreImageByHybridWithStaticSplit(ImgTfmInfo_t *info, array_t *vector,
+				   mdd_t *from, array_t *relationArray,
+				   mdd_t *cofactorCube, mdd_t *abstractCube)
+{
+  int			i, j;
+  array_t		*mergedRelationArray;
+  mdd_t			*result, *relation, *var, *nextVar, *fromRange;
+  ImgComponent_t	*comp, *supportComp;
+  int			nVars;
+  char			*support;
+  array_t		*smoothVarsBddArray, *introducedVarsBddArray;
+  array_t		*rangeVarsBddArray;
+
+  if (bdd_is_tautology(from, 1))
+    return(mdd_one(info->manager));
+  if (bdd_is_tautology(from, 0))
+    return(mdd_zero(info->manager));
+
+  if (cofactorCube && abstractCube) {
+    if (!bdd_is_tautology(cofactorCube, 1) &&
+	!bdd_is_tautology(abstractCube, 1)) {
+      mergedRelationArray = ImgGetCofactoredAbstractedRelationArray(
+					info->manager, relationArray,
+					cofactorCube, abstractCube);
+    } else if (!bdd_is_tautology(cofactorCube, 1)) {
+      mergedRelationArray = ImgGetCofactoredRelationArray(relationArray,
+							  cofactorCube);
+    } else if (!bdd_is_tautology(abstractCube, 1)) {
+      mergedRelationArray = ImgGetAbstractedRelationArray(info->manager,
+							  relationArray,
+							  abstractCube);
+    } else
+      mergedRelationArray = mdd_array_duplicate(relationArray);
+  } else
+    mergedRelationArray = mdd_array_duplicate(relationArray);
+
+  nVars = info->nVars;
+  support = ALLOC(char, sizeof(char) * nVars);
+  memset(support, 0, sizeof(char) * nVars);
+
+  supportComp = ImgComponentAlloc(info);
+  for (i = 0; i < array_n(mergedRelationArray); i++) {
+    supportComp->func = array_fetch(mdd_t *, mergedRelationArray, i);;
+    ImgSupportClear(info, supportComp->support);
+    ImgComponentGetSupport(supportComp);
+    for (j = 0; j < nVars; j++)
+      support[j] = support[j] | supportComp->support[j];
+  }
+
+  if (vector && array_n(vector) > 0) {
+    for (i = 0; i < array_n(vector); i++) {
+      comp = array_fetch(ImgComponent_t *, vector, i);
+      if (comp->intermediate) {
+	relation = mdd_xnor(comp->var, comp->func);
+	support[(int)bdd_top_var_id(comp->var)] = 1;
+      } else {
+	nextVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+	relation = mdd_xnor(nextVar, comp->func);
+	support[(int)bdd_top_var_id(nextVar)] = 1;
+	mdd_free(nextVar);
+      }
+      array_insert_last(mdd_t *, mergedRelationArray, relation);
+
+      for (j = 0; j < nVars; j++)
+	support[j] = support[j] | comp->support[j];
+    }
+  }
+
+  fromRange = ImgSubstitute(from, info->functionData, Img_D2R_c);
+  supportComp->func = fromRange;
+  ImgSupportClear(info, supportComp->support);
+  ImgComponentGetSupport(supportComp);
+  for (i = 0; i < nVars; i++)
+    support[i] = support[i] | supportComp->support[i];
+  supportComp->func = NIL(mdd_t);
+  ImgComponentFree(supportComp);
+
+  smoothVarsBddArray = array_alloc(mdd_t *, 0);
+  introducedVarsBddArray = array_alloc(mdd_t *, 0);
+  if (!info->option->preReorderWithFrom)
+    rangeVarsBddArray = array_alloc(mdd_t *, 0);
+  else
+    rangeVarsBddArray = NIL(array_t);
+  for (i = 0; i < nVars; i++) {
+    if (support[i]) {
+      var = bdd_var_with_index(info->manager, i);
+      if (info->intermediateVarsTable &&
+	  st_lookup(info->intermediateVarsTable, (char *)(long)i,
+		    NIL(char *))) {
+	array_insert_last(mdd_t *, smoothVarsBddArray, var);
+      } else if (st_lookup(info->rangeVarsTable, (char *)(long)i,
+			   NIL(char *))) {
+	if (info->option->preReorderWithFrom)
+	  array_insert_last(mdd_t *, smoothVarsBddArray, var);
+	else
+	  array_insert_last(mdd_t *, rangeVarsBddArray, var);
+      } else {
+	if (info->preKeepPiInTr)
+	  array_insert_last(mdd_t *, introducedVarsBddArray, var);
+	else {
+	  if (st_lookup(info->quantifyVarsTable, (char *)(long)i,
+			NIL(char *))) {
+	    array_insert_last(mdd_t *, smoothVarsBddArray, var);
+	  } else
+	    array_insert_last(mdd_t *, introducedVarsBddArray, var);
+	}
+      }
+    }
+  }
+  FREE(support);
+
+  if (info->option->preReorderWithFrom) {
+    array_insert_last(mdd_t *, mergedRelationArray, fromRange);
+    result = ImgMultiwayLinearAndSmooth(info->manager,
+					mergedRelationArray,
+					smoothVarsBddArray,
+					introducedVarsBddArray,
+					info->option->trMethod,
+					Img_Backward_c,
+					info->trmOption);
+  } else {
+    result = ImgMultiwayLinearAndSmoothWithFrom(info->manager,
+						mergedRelationArray, fromRange,
+						smoothVarsBddArray,
+						rangeVarsBddArray,
+						introducedVarsBddArray,
+						info->option->trMethod,
+						Img_Backward_c,
+						info->trmOption);
+    mdd_free(fromRange);
+    mdd_array_free(rangeVarsBddArray);
+  }
+  mdd_array_free(mergedRelationArray);
+  mdd_array_free(smoothVarsBddArray);
+  mdd_array_free(introducedVarsBddArray);
+
+  return(result);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a vector is equivalent to a relation array.]
+
+  Description [Checks whether a vector is equivalent to a relation array.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+ImgCheckEquivalence(ImgTfmInfo_t *info, array_t *vector, array_t *relationArray,
+		    mdd_t *cofactorCube, mdd_t *abstractCube, int preFlag)
+{
+  int			i, equal;
+  mdd_t			*product1, *product2;
+  mdd_t			*var, *tmp, *relation;
+  ImgComponent_t	*comp;
+  array_t		*newRelationArray, *tmpRelationArray;
+  array_t		*domainVarBddArray, *quantifyVarBddArray;
+
+  tmpRelationArray = array_alloc(mdd_t *, 0);
+  for (i = 0; i < array_n(vector); i++) {
+    comp = array_fetch(ImgComponent_t *, vector, i);
+    if (comp->intermediate)
+      relation = mdd_xnor(comp->var, comp->func);
+    else {
+      var = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+      relation = mdd_xnor(var, comp->func);
+      mdd_free(var);
+    }
+    array_insert_last(mdd_t *, tmpRelationArray, relation);
+  }
+
+  if (preFlag) {
+    if (info->preKeepPiInTr) {
+      quantifyVarBddArray = array_alloc(mdd_t *, 0);
+      domainVarBddArray = array_join(info->domainVarBddArray,
+				     info->quantifyVarBddArray);
+    } else {
+      quantifyVarBddArray = info->quantifyVarBddArray;
+      domainVarBddArray = info->domainVarBddArray;
+    }
+    newRelationArray = ImgClusterRelationArray(info->manager,
+	info->functionData, info->option->trMethod, Img_Backward_c,
+	info->trmOption, tmpRelationArray, domainVarBddArray,
+	quantifyVarBddArray, info->rangeVarBddArray,
+	NIL(array_t *), NIL(array_t *), 0);
+    if (info->preKeepPiInTr) {
+      array_free(quantifyVarBddArray);
+      array_free(domainVarBddArray);
+    }
+  } else {
+    newRelationArray = ImgClusterRelationArray(info->manager,
+	info->functionData, info->option->trMethod, Img_Forward_c,
+	info->trmOption, tmpRelationArray, info->domainVarBddArray,
+	info->quantifyVarBddArray, info->rangeVarBddArray,
+	NIL(array_t *), NIL(array_t *), 0);
+  }
+  mdd_array_free(tmpRelationArray);
+
+  product1 = mdd_one(info->manager);
+  for (i = 0; i < array_n(newRelationArray); i++) {
+    relation = array_fetch(mdd_t *, newRelationArray, i);
+    tmp = product1;
+    product1 = mdd_and(tmp, relation, 1, 1);
+    mdd_free(tmp);
+  }
+  mdd_array_free(newRelationArray);
+
+  if (cofactorCube && abstractCube) {
+    newRelationArray = ImgGetCofactoredAbstractedRelationArray(info->manager,
+				relationArray, cofactorCube, abstractCube);
+  } else
+    newRelationArray = relationArray;
+
+  product2 = mdd_one(info->manager);
+  for (i = 0; i < array_n(newRelationArray); i++) {
+    relation = array_fetch(mdd_t *, newRelationArray, i);
+    tmp = product2;
+    product2 = mdd_and(tmp, relation, 1, 1);
+    mdd_free(tmp);
+  }
+
+  if (newRelationArray != relationArray)
+    mdd_array_free(newRelationArray);
+
+  if (mdd_equal(product1, product2))
+    equal = 1;
+  else
+    equal = 0;
+
+  mdd_free(product1);
+  mdd_free(product2);
+
+  return(equal);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a vector corresponds to its relation array.]
+
+  Description [Checks whether a vector corresponds to its relation array.
+  This function is used only for debugging with image_cluster_size = 1.
+  Checks each function vector whether its relation exists in the transition
+  relation.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+ImgCheckMatching(ImgTfmInfo_t *info, array_t *vector, array_t *relationArray)
+{
+  int			i, equal = 1;
+  mdd_t			*var, *relation;
+  ImgComponent_t	*comp;
+  st_table		*relationTable;
+  int			*ptr;
+
+  relationTable = st_init_table(st_ptrcmp, st_ptrhash);
+
+  for (i = 0; i < array_n(relationArray); i++) {
+    relation = array_fetch(mdd_t *, relationArray, i);
+    ptr = (int *)bdd_pointer(relation);
+    st_insert(relationTable, (char *)ptr, NULL);
+  }
+
+  for (i = 0; i < array_n(vector); i++) {
+    comp = array_fetch(ImgComponent_t *, vector, i);
+    if (comp->intermediate)
+      relation = mdd_xnor(comp->var, comp->func);
+    else {
+      var = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+      relation = mdd_xnor(var, comp->func);
+      mdd_free(var);
+    }
+    ptr = (int *)bdd_pointer(relation);
+    if (!st_lookup(relationTable, (char *)ptr, NULL)) {
+      if (comp->intermediate) {
+	fprintf(vis_stderr,
+		"Error : relation of varId[%d - intermediate] not found\n",
+		(int)bdd_top_var_id(comp->var));
+      } else {
+	fprintf(vis_stderr, "Error : relation of varId[%d] not found\n",
+		(int)bdd_top_var_id(comp->var));
+      }
+      equal = 0;
+    }
+    mdd_free(relation);
+  }
+
+  st_free_table(relationTable);
+  return(equal);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes variable lifetime lambda.]
+
+  Description [Computes variable lifetime lambda. newRelationFlag is 1 when
+  relationArray is made from the function vector directly, in other words,
+  relationArray is an array of next state functions in this case.]
+
+  SideEffects []
+
+******************************************************************************/
+static float
+ComputeSupportLambda(ImgTfmInfo_t *info, array_t *relationArray,
+			mdd_t *cofactorCube, mdd_t *abstractCube,
+			mdd_t *from, array_t *vector, int newRelationFlag,
+			int preFlag, float *improvedLambda)
+{
+  array_t		*newRelationArray, *clusteredRelationArray;
+  ImgComponent_t	*comp;
+  int			i, j, nVars, nSupports;
+  mdd_t			*newFrom, *var;
+  char			*support;
+  array_t		*smoothVarsBddArray, *introducedVarsBddArray;
+  array_t		*domainVarsBddArray;
+  array_t		*smoothSchedule, *smoothVars;
+  float			lambda;
+  int			size, total, lifetime;
+  Img_DirectionType	direction;
+  int			lambdaWithFrom, prevArea;
+  array_t		*orderedRelationArray;
+  int			nIntroducedVars;
+  int			*highest, *lowest;
+  mdd_t			*relation;
+  int			asIs;
+
+  if (cofactorCube && abstractCube) {
+    newRelationArray = ImgGetCofactoredAbstractedRelationArray(info->manager,
+			      relationArray, cofactorCube, abstractCube);
+    if (from && info->option->lambdaWithFrom) {
+      if (preFlag)
+	newFrom = ImgSubstitute(from, info->functionData, Img_D2R_c);
+      else
+	newFrom = mdd_dup(from);
+      array_insert_last(mdd_t *, newRelationArray, newFrom);
+      lambdaWithFrom = 1;
+    } else {
+      lambdaWithFrom = 0;
+      newFrom = NIL(mdd_t);
+    }
+  } else {
+    if (from && info->option->lambdaWithFrom) {
+      if (newRelationFlag) {
+	newRelationArray = relationArray;
+	if (preFlag)
+	  newFrom = ImgSubstitute(from, info->functionData, Img_D2R_c);
+	else
+	  newFrom = from;
+      } else {
+	/* We don't want to modify the original relation array */
+	newRelationArray = mdd_array_duplicate(relationArray);
+	if (preFlag)
+	  newFrom = ImgSubstitute(from, info->functionData, Img_D2R_c);
+	else
+	  newFrom = mdd_dup(from);
+      }
+      array_insert_last(mdd_t *, newRelationArray, newFrom);
+      lambdaWithFrom = 1;
+    } else {
+      newRelationArray = relationArray;
+      newFrom = NIL(mdd_t);
+      lambdaWithFrom = 0;
+    }
+  }
+
+  if (vector) {
+    for (i = 0; i < array_n(vector); i++) {
+      comp = array_fetch(ImgComponent_t *, vector, i);
+      array_insert_last(mdd_t *, newRelationArray, mdd_dup(comp->func));
+    }
+  }
+
+  nVars = info->nVars;
+  support = ALLOC(char, sizeof(char) * nVars);
+  memset(support, 0, sizeof(char) * nVars);
+
+  comp = ImgComponentAlloc(info);
+  for (i = 0; i < array_n(newRelationArray); i++) {
+    comp->func = array_fetch(mdd_t *, newRelationArray, i);;
+    ImgSupportClear(info, comp->support);
+    ImgComponentGetSupport(comp);
+    for (j = 0; j < nVars; j++)
+      support[j] = support[j] | comp->support[j];
+  }
+  comp->func = NIL(mdd_t);
+  ImgComponentFree(comp);
+
+  nSupports = 0;
+  smoothVarsBddArray = array_alloc(mdd_t *, 0);
+  domainVarsBddArray = array_alloc(mdd_t *, 0);
+  introducedVarsBddArray = array_alloc(mdd_t *, 0);
+  for (i = 0; i < nVars; i++) {
+    if (support[i]) {
+      var = bdd_var_with_index(info->manager, i);
+      if (preFlag) {
+	if (st_lookup(info->rangeVarsTable, (char *)(long)i, NIL(char *))) {
+	  if (lambdaWithFrom)
+	    array_insert_last(mdd_t *, smoothVarsBddArray, var);
+	  else
+	    array_insert_last(mdd_t *, domainVarsBddArray, var);
+	  if (info->option->preLambdaMode == 0 ||
+	      info->option->preLambdaMode == 2)
+	    nSupports++;
+	} else {
+	  if (info->preKeepPiInTr) {
+	    if (st_lookup(info->quantifyVarsTable, (char *)(long)i,
+			NIL(char *))) {
+	      array_insert_last(mdd_t *, introducedVarsBddArray, var);
+	      nSupports++;
+	    } else if (info->intermediateVarsTable &&
+			st_lookup(info->intermediateVarsTable, (char *)(long)i,
+				NIL(char *))) {
+	      array_insert_last(mdd_t *, smoothVarsBddArray, var);
+	      nSupports++;
+	    } else { /* ps variables */
+	      array_insert_last(mdd_t *, introducedVarsBddArray, var);
+	      if (info->option->preLambdaMode != 0)
+		nSupports++;
+	    }
+	  } else {
+	    if (st_lookup(info->quantifyVarsTable, (char *)(long)i,
+			  NIL(char *)) ||
+		(info->intermediateVarsTable &&
+		 st_lookup(info->intermediateVarsTable, (char *)(long)i,
+			   NIL(char *)))) {
+	      array_insert_last(mdd_t *, smoothVarsBddArray, var);
+	      nSupports++;
+	    } else { /* ps variables */
+	      array_insert_last(mdd_t *, introducedVarsBddArray, var);
+	      if (info->option->preLambdaMode != 0)
+		nSupports++;
+	    }
+	  }
+	}
+      } else { /* image computation */
+	if (st_lookup(info->rangeVarsTable, (char *)(long)i, NIL(char *))) {
+	  array_insert_last(mdd_t *, introducedVarsBddArray, var);
+	  if (info->option->lambdaMode == 2)
+	    nSupports++;
+	} else {
+	  if (lambdaWithFrom)
+	    array_insert_last(mdd_t *, smoothVarsBddArray, var);
+	  else {
+	    if (st_lookup(info->quantifyVarsTable, (char *)(long)i,
+			  NIL(char *)) ||
+		(info->intermediateVarsTable &&
+		 st_lookup(info->intermediateVarsTable, (char *)(long)i,
+			   NIL(char *)))) {
+	      array_insert_last(mdd_t *, smoothVarsBddArray, var);
+	    } else
+	      array_insert_last(mdd_t *, domainVarsBddArray, var);
+	  }
+	  nSupports++;
+	}
+      }
+    }
+  }
+
+  if (preFlag)
+    direction = Img_Backward_c;
+  else
+    direction = Img_Forward_c;
+
+  if (info->option->lambdaFromMlp) {
+    FREE(support);
+    if (info->option->lambdaWithClustering) {
+      ImgMlpClusterRelationArray(info->manager, info->functionData,
+			newRelationArray, domainVarsBddArray,
+			smoothVarsBddArray, introducedVarsBddArray,
+			direction, &clusteredRelationArray, NIL(array_t *),
+			info->trmOption);
+      if (newRelationArray != relationArray)
+	mdd_array_free(newRelationArray);
+      newRelationArray = clusteredRelationArray;
+    }
+    prevArea = info->prevTotal;
+    asIs = newRelationFlag ? 0 : 1; /* 0 when relationArray is an array of
+				       functions, i.e. without next state
+				       variables */
+    lambda = ImgMlpComputeLambda(info->manager, newRelationArray,
+			domainVarsBddArray, smoothVarsBddArray,
+			introducedVarsBddArray, direction,
+			info->option->lambdaMode, asIs, &prevArea,
+			improvedLambda, info->trmOption);
+    info->prevTotal = prevArea;
+  } else {
+    smoothSchedule = ImgGetQuantificationSchedule(info->manager,
+			info->functionData, info->option->trMethod,
+			direction, info->trmOption, newRelationArray,
+			smoothVarsBddArray, domainVarsBddArray,
+			introducedVarsBddArray,
+			info->option->lambdaWithClustering,
+			&orderedRelationArray);
+
+    if (direction == Img_Forward_c) {
+      size = array_n(smoothSchedule);
+      lifetime = 0;
+      if (info->option->lambdaMode == 0) { /* total lifetime (lambda) */
+	for (i = 1; i < size; i++) {
+	  smoothVars = array_fetch(array_t *, smoothSchedule, i);
+	  lifetime += array_n(smoothVars) * i;
+	}
+	total = nSupports * (size - 1);
+      } else if (info->option->lambdaMode == 1) { /* active lifetime (lambda) */
+	lowest = ALLOC(int, sizeof(int) * nVars);
+	for (i = 0; i < nVars; i++)
+	  lowest[i] = nVars;
+	highest = ALLOC(int, sizeof(int) * nVars);
+	memset(highest, 0, sizeof(int) * nVars);
+
+	comp = ImgComponentAlloc(info);
+	for (i = 0; i < size - 1; i++) {
+	  relation = array_fetch(mdd_t *, orderedRelationArray, i);
+	  comp->func = relation;
+	  ImgSupportClear(info, comp->support);
+	  ImgComponentGetSupport(comp);
+	  for (j = 0; j < nVars; j++) {
+	    if (!comp->support[j])
+	      continue;
+	    if (st_lookup(info->rangeVarsTable, (char *)(long)j, NIL(char *)))
+	      continue;
+	    if (i < lowest[j])
+	      lowest[j] = i;
+	    if (i > highest[j])
+	      highest[j] = i;
+	  }
+	}
+	comp->func = NIL(mdd_t);
+	ImgComponentFree(comp);
+
+	for (i = 0; i < nVars; i++) {
+	  if (lowest[i] == nVars)
+	    continue;
+	  if (st_lookup(info->rangeVarsTable, (char *)(long)i, NIL(char *)))
+	    continue;
+	  lifetime += highest[i] - lowest[i] + 1;
+	}
+
+	if (newRelationFlag)
+	  lifetime += array_n(newRelationArray);
+	total = nSupports * (size - 1);
+
+	FREE(lowest);
+	FREE(highest);
+      } else { /* total lifetime (lambda) with introduced variables */
+	for (i = 1; i < size; i++) {
+	  smoothVars = array_fetch(array_t *, smoothSchedule, i);
+	  lifetime += array_n(smoothVars) * i;
+	}
+
+	if (newRelationFlag) {
+	  nIntroducedVars = array_n(newRelationArray);
+	  lifetime += nIntroducedVars * (nIntroducedVars + 1) / 2;
+	} else {
+	  comp = ImgComponentAlloc(info);
+	  for (i = 0; i < size - 1; i++) {
+	    relation = array_fetch(mdd_t *, orderedRelationArray, i);
+	    comp->func = relation;
+	    ImgSupportClear(info, comp->support);
+	    ImgComponentGetSupport(comp);
+	    nIntroducedVars = 0;
+	    for (j = 0; j < nVars; j++) {
+	      if (!comp->support[j])
+		continue;
+	      if (st_lookup(info->rangeVarsTable, (char *)(long)j, NIL(char *)))
+		nIntroducedVars++;
+	    }
+	    lifetime += (size - i - 1) * nIntroducedVars;
+	  }
+	  comp->func = NIL(mdd_t);
+	  ImgComponentFree(comp);
+	}
+	total = nSupports * (size - 1);
+      }
+      mdd_array_array_free(smoothSchedule);
+    } else if (info->option->preLambdaMode == 0) { /* total lifetime (lambda) */
+      /* direction == Img_Backward_c */
+      size = array_n(smoothSchedule);
+      lifetime = 0;
+      for (i = 1; i < size; i++) {
+	smoothVars = array_fetch(array_t *, smoothSchedule, i);
+	lifetime += array_n(smoothVars) * i;
+      }
+      total = nSupports * (size - 1);
+      mdd_array_array_free(smoothSchedule);
+    } else { /* direction == Img_Backward_c */
+      size = array_n(smoothSchedule);
+      mdd_array_array_free(smoothSchedule);
+      lifetime = 0;
+
+      lowest = ALLOC(int, sizeof(int) * nVars);
+      for (i = 0; i < nVars; i++)
+	lowest[i] = nVars;
+      highest = ALLOC(int, sizeof(int) * nVars);
+      memset(highest, 0, sizeof(int) * nVars);
+
+      comp = ImgComponentAlloc(info);
+      for (i = 0; i < size - 1; i++) {
+	relation = array_fetch(mdd_t *, orderedRelationArray, i);
+	comp->func = relation;
+	ImgSupportClear(info, comp->support);
+	ImgComponentGetSupport(comp);
+	for (j = 0; j < nVars; j++) {
+	  if (!comp->support[j])
+	    continue;
+	  if (i < lowest[j])
+	    lowest[j] = i;
+	  if (i > highest[j])
+	    highest[j] = i;
+	}
+      }
+      comp->func = NIL(mdd_t);
+      ImgComponentFree(comp);
+
+      if (info->option->preLambdaMode == 1) { /* active lifetime (lambda) */
+	for (i = 0; i < nVars; i++) {
+	  if (lowest[i] == nVars)
+	    continue;
+	  if (st_lookup(info->rangeVarsTable, (char *)(long)i, NIL(char *)) ||
+		st_lookup(info->quantifyVarsTable, (char *)(long)i,
+			       NIL(char *)) ||
+		(info->intermediateVarsTable &&
+		 st_lookup(info->intermediateVarsTable, (char *)(long)i,
+			       NIL(char *)))) {
+	    lifetime += highest[i] - lowest[i] + 1;
+	  }
+	}
+	if (newRelationFlag)
+	  lifetime += array_n(newRelationArray);
+	total = nSupports * (size - 1);
+      } else if (info->option->preLambdaMode == 2) {
+	/* total lifetime (lambda) with introduced variables */
+	for (i = 0; i < nVars; i++) {
+	  if (lowest[i] == nVars)
+	    continue;
+	  if (st_lookup(info->rangeVarsTable, (char *)(long)i, NIL(char *)) ||
+	      st_lookup(info->quantifyVarsTable, (char *)(long)i,
+			NIL(char *)) ||
+	      (info->intermediateVarsTable &&
+	       st_lookup(info->intermediateVarsTable, (char *)(long)i,
+			NIL(char *)))) {
+	    lifetime += highest[i] + 1;
+	  } else {
+	    lifetime += size - lowest[i] - 1;
+	  }
+	}
+	if (newRelationFlag) {
+	  nIntroducedVars = array_n(newRelationArray);
+	  lifetime += nIntroducedVars * (nIntroducedVars + 1) / 2;
+	}
+	total = nSupports * (size - 1);
+      } else { /* total lifetime (lambda) with ps/pi variables */
+	for (i = 0; i < nVars; i++) {
+	  if (lowest[i] == nVars)
+	    continue;
+	  if (st_lookup(info->rangeVarsTable, (char *)(long)i, NIL(char *)))
+	    continue;
+	  if (st_lookup(info->quantifyVarsTable, (char *)(long)i,
+			NIL(char *)) ||
+	      (info->intermediateVarsTable &&
+	       st_lookup(info->intermediateVarsTable, (char *)(long)i,
+			NIL(char *)))) {
+	    lifetime += highest[i] + 1;
+	  } else {
+	    lifetime += size - lowest[i] - 1;
+	  }
+	}
+	if (newRelationFlag) {
+	  nIntroducedVars = array_n(newRelationArray);
+	  lifetime += nIntroducedVars * (nIntroducedVars + 1) / 2;
+	}
+	total = nSupports * (size - 1);
+      }
+
+      FREE(lowest);
+      FREE(highest);
+    }
+
+    FREE(support);
+    mdd_array_free(orderedRelationArray);
+
+    if (total == 0.0) {
+      lambda = 0.0;
+      *improvedLambda = 0.0;
+    } else {
+      lambda = (float)lifetime / (float)total;
+      if (info->prevTotal) {
+	*improvedLambda = info->prevLambda -
+			  (float)lifetime / (float)info->prevTotal;
+      } else
+	*improvedLambda = 0.0;
+    }
+    info->prevTotal = total;
+  }
+
+  mdd_array_free(smoothVarsBddArray);
+  mdd_array_free(domainVarsBddArray);
+  mdd_array_free(introducedVarsBddArray);
+  if (newRelationArray != relationArray)
+    mdd_array_free(newRelationArray);
+  if (newRelationFlag && from && info->option->lambdaWithFrom &&
+	newFrom != from) {
+    mdd_free(newFrom);
+  }
+
+  if (info->option->verbosity >= 2) {
+    if (preFlag)
+      fprintf(vis_stdout, "** tfm info: lambda for preimage = %.2f\n", lambda);
+    else
+      fprintf(vis_stdout, "** tfm info: lambda for image = %.2f\n", lambda);
+  }
+
+  info->prevLambda = lambda;
+  return(lambda);
+}
Index: vis_dev/vis-2.3/src/img/imgInt.h
===================================================================
--- vis_dev/vis-2.3/src/img/imgInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/img/imgInt.h	(revision 14)
@@ -0,0 +1,1089 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [imgInt.h]
+
+  PackageName [img]
+
+  Synopsis    [Internal declarations for img package.]
+
+  Description [To add a new method, called "foo", follow these steps. 1)
+  describe the foo method in the Description field at the top of img.h. 2) Add
+  Img_Foo_c to the Img_MethodType enumerated type. 3) Create a file, imgFoo.c,
+  and define the following functions: ImgImageInfoInitializeFoo,
+  ImgImageInfoComputeFwdFoo, ImgImageInfoComputeBwdFoo,
+  ImgImageInfoFreeFoo. 4) In the function Img_ImageInfoInitialize, add the
+  case "foo" for the "image_method" flag, and add the case Img_Foo_c to the
+  switch for initialization.]
+  
+  SeeAlso     [fsm]
+
+  Author      [Rajeev Ranjan, Tom Shiple, Abelardo Pardo, In-Ho Moon]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: imgInt.h,v 1.76 2005/05/18 18:11:57 jinh Exp $]
+
+******************************************************************************/
+
+#ifndef _IMGINT
+#define _IMGINT
+
+#include "img.h"
+#include "mvf.h"
+#include "cmd.h"
+#include "part.h"
+#include "heap.h"
+#include <string.h>
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define IMGDEFAULT_METHOD Img_Iwls95_c; /* Default image method */
+#define IMG_PI_CLIP_DEPTH 0.4 /* partial image default clipping depth
+				 fraction for and-abstract */
+#define IMG_PI_CLIP_DEPTH_FINAL 0.8 /* partial image default clipping depth
+				       fraction for and-abstract if the
+				    original clipping depth fails */
+#define IMG_PI_SP_THRESHOLD 10000
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef struct ImgFunctionDataStruct ImgFunctionData_t;
+typedef mdd_t * (*ImgImageComputeProc) ARGS((ImgFunctionData_t *,
+					     Img_ImageInfo_t *,
+					     mdd_t *, mdd_t *, array_t *));
+typedef void    (*ImgImageFreeProc)    ARGS((void *));
+typedef void    (*ImgImagePrintMethodParamsProc) ARGS((void *, FILE*));
+
+typedef struct DomainCacheValueStruct ImgDomainCacheValue_t;
+typedef struct ImgPartialImageOptionStruct ImgPartialImageOption_t;
+typedef struct ImgTrmOptionStruct ImgTrmOption_t;
+typedef struct ImgTfmInfo_s ImgTfmInfo_t;
+typedef struct ImgTfmOption_s ImgTfmOption_t;
+typedef struct ImgComponent_s ImgComponent_t;
+typedef struct ImgCacheTable_s ImgCacheTable_t;
+typedef struct ImgCacheEntry_s ImgCacheEntry_t;
+typedef struct ImgCacheStKey_s ImgCacheStKey_t;
+typedef struct VarLifeStruct VarLife_t;
+typedef struct RelationStruct Relation_t;
+typedef struct ClusterStruct Cluster_t;
+typedef struct ConjunctStruct Conjunct_t;
+
+
+
+/**Enum************************************************************************
+
+  Synopsis    [Partial image methods]
+
+******************************************************************************/
+typedef enum {
+  Img_PIApprox_c,
+  Img_PIClipping_c
+} Img_PartialImageMethod;
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [Functions and variables to compute images.]
+
+  Description [This data structure provides all the information about the
+  functions that are to be used to do image computations.  For a thorough
+  explanation of the fields of this structure, see the description of the
+  function Img_ImageInfoInitialize.  None of the data structures stored in
+  this structure belong to the image package, therefore only a pointer to them
+  is kept. A cube here is the product of bdd variables and
+  createVarCubeFlag is the flag whether to create cubes and this is used
+  for just efficiency.]
+
+  SeeAlso     [Img_ImageInfoInitialize]
+
+******************************************************************************/
+struct ImgFunctionDataStruct {
+  graph_t *mddNetwork;  /* graph representing the functions and dependencies */
+  array_t *roots;       /* of char *; functions on which image is computed */
+  array_t *domainVars;  /* array of mddIds of domain variables */
+  array_t *rangeVars;   /* array of mddIds of range variables */
+  array_t *quantifyVars;/* array of mddIds of variables to be quantified */
+  mdd_t   *domainCube;  /* cube of domain bdd variables */
+  mdd_t   *rangeCube;   /* cube of range bdd variables */
+  mdd_t   *quantifyCube; /* cube of input bdd variables */
+  array_t *domainBddVars;  /* array of bdd_t of domain bdd variables */
+  array_t *rangeBddVars;   /* array of bdd_t of range bdd variables */
+  array_t *quantifyBddVars; /* array of bdd_t of primary input bdd variables */
+  int     *permutD2R; /* permutation for substitution from domain to range */
+  int     *permutR2D; /* permutation for substitution from range to domain */
+  boolean createVarCubesFlag;
+  boolean FAFWFlag;
+  mdd_t   *Winning;
+  Ntk_Network_t *network;
+};
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [Information for method-specific image computation.]
+
+  Description [Information for method-specific image computation.  Along with
+  user-specified state subsets, this structure contains all the information
+  that an image computation method needs to perform the forward or backward
+  image of a function vector.  In particular, the methodData is used to allow
+  the image computation to carry information from one image computation to the
+  next (for example, when image computations are done from within a fixed
+  point loop).]
+
+******************************************************************************/
+struct ImgImageInfoStruct {
+  Img_MethodType       methodType;    /* method initialized to */    
+  Img_DirectionType    directionType; /* types of computation Fwd/Bwd allowed */
+  ImgFunctionData_t    functionData;       /* information about the functions */
+  void                *methodData;         /* method-dependent data structure */
+  ImgImageComputeProc  imageComputeFwdProc;/* function to compute Fwd Image */
+  ImgImageComputeProc  imageComputeBwdProc;/* function to compute Bwd Image */
+  ImgImageComputeProc  imageComputeFwdWithDomainVarsProc;
+			/* function to compute Fwd Image on Domain Vars*/
+  ImgImageComputeProc  imageComputeBwdWithDomainVarsProc;
+			/* function to compute Bwd Image on Domain Vars*/
+  ImgImageFreeProc     imageFreeProc;      /* function to free the
+                                              method-dependent data structure */
+  ImgImagePrintMethodParamsProc   imagePrintMethodParamsProc;
+  boolean fwdTrMinimizedFlag;	/* set when TR is minimized with DC */
+  boolean bwdTrMinimizedFlag;	/* set when TR is minimized with DC */
+  int printMinimizeStatus;	/* print status during minimizing
+				 * 0 : not print
+				 * 1 : print all info
+				 * 2 : print final info */
+  int verbosity;
+  int useOptimizedRelationFlag;
+  int linearComputeRange;
+  Img_OptimizeType linearOptimize;
+  void *savedRelation; /* copy of method-dependent data structure */
+};
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [This structure contains the required options for partial 
+               image computation.]
+
+  Description [This structure contains the required options for
+  partial image computation. partialImageMethod can take the values
+  PI_APPROX or PI_CLIPPING. partialImageThreshold is the threshold
+  that triggers approximation. partialImageSize is the size that the
+  approximation is required to reduce to. partialImageApproxMethod
+  specified the approximation method to apply: BDD_APPROX_HB,
+  BDD_APPROX_SP, BDD_APPROX_UA, BDD_APPROX_RUA, BDD_APPROX_BIASED_RUA
+  BDD_APPROX_COMP. clippingDepthFrac is the only parameter required
+  for PI_CLIPPING. nvars is the number of domain vars + range vars +
+  quantify vars. The bias function is used in
+  BDD_APPROX_BIASED_RUA. The qualityBias is also used for
+  BDD_APPROX_BIASED_RUA. ]
+
+******************************************************************************/
+struct ImgPartialImageOptionStruct {
+  int nvars; /* domain vars + range vars + quantify vars */
+  Img_PartialImageMethod partialImageMethod;
+  int partialImageThreshold; /* pertains to PI_APPROX */
+  int partialImageSize; /* pertains to PI_APPROX */
+  bdd_approx_type_t partialImageApproxMethod; /* pertains to PI_APPROX */
+  double quality; /* pertains to PI_APPROX */
+  mdd_t *bias; /* bias function for BDD_APPROX_BIASED_RUA: pertains to PI_APPROX */
+  double qualityBias; /* quality for bias in BDD_APPROX_BIASED_RUA:
+			 pertains to PI_APPROX */
+  double clippingDepthFrac; /* pertains to PI_CLIPPING */
+};
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [This structure contains the required options for filling in
+               the data structure.]
+
+  Description ["clusterSize" is the threshold value used to
+               create clusters. "W1", "W2" etc are the weights used in the
+               heuristic algorithms to order the cluster processing for early
+               quantification. VerbosityLevel  controls the amount of
+               information printed during image computation.]
+
+******************************************************************************/
+struct ImgTrmOptionStruct {
+  int clusterSize;
+  int verbosity;
+  int W1;
+  int W2; /* Weights attached to various parameters. */
+  int W3; /* For details please refer to {1} */
+  int W4;
+  int printDepMatrix; /* Print dependence matrix after building transition
+			 relation (default = 0)
+		      */
+  /* The following options are to read and write cluster file */
+  int readReorderCluster; /* Reorder clusters after reading (default = 0) */
+  char *readCluster; /* cluster file name to read */
+  char *writeCluster; /* cluster file name to write */
+  char *writeDepMatrix; /* file name to write dependence matrix*/
+  /* The following options starting with mlp is for MLP method */
+  int mlpMethod; /* 0 : Find singletons with iterative looping (default)
+		    1 : Find singletons with sorted list by index
+		    2 : Find singletons with sorted list by the number of 1's
+			in active region
+		 */
+  int mlpCluster; /* 0 : sequential conjunctions
+		     1 : affinity based tree clustering (default)
+		  */
+  int mlpClusterDynamic; /* Update affinity dynamically (default = 1) */
+  float mlpAffinityThreshold; /* Find best candidate when its affinity is
+				 at least equal or larger than this threshold
+				 (default = 0.0)
+			      */
+  int mlpClusterQuantifyVars; /* 0 : Find best candidate in clustering with the
+				     highest affinity, and in case of tie,
+				     use smaller number of quantify variables.
+				     (default)
+				 1 : Find best candidate in clustering with the
+				     smallest number of quantify variables, and
+				     in case of tie, use bigger affinity
+				 2 : In addition 1, update the number of quanity
+				     variables dynamically.
+			      */
+  int mlpClusterSortedList; /* Use sorted list for clustering (default = 1) */
+  int mlpInitialCluster; /* Try SSD based initial clustering (default = 0) */
+  int mlpCsFirst; /* Find column singletons first (default = 0) */
+  int mlpSkipRs; /* Skip finding row singletons (default = 0) */
+  int mlpSkipCs; /* Skip finding column singletons (default = 1) */
+  int mlpRowBased; /* Move rows instead of columns after singletons
+		      (default = 0)
+		   */
+  int mlpReorder; /* for image computation
+		     0 : no reordering after clustering (default)
+		     1 : reorder using MLP after clustering (inside)
+		     2 : reorder using MLP after clustering (outside)
+		     3 : reorder using IWLS95 after clustering
+		  */
+  int mlpPreReorder; /* for preimage
+			0 : no reordering after clustering (default)
+			1 : reorder using MLP after clustering (inside)
+			2 : reorder using MLP after clustering (outside)
+			3 : reorder using IWLS95 after clustering
+		     */
+  int mlpPostProcess; /* 0 : no postprocessing (default)
+			 1 : do postprocessing after ordering
+			 2 : do postprocessing after clustering or reordering
+			 3 : both 1 and 2
+		      */
+  int mlpDecomposeScc; /* Decompose dependence matrix with SCCs (default = 1) */
+  int mlpClusterScc; /* Cluster only inside each SCC (default = 1) */
+  int mlpSortScc; /* 0 : no sorting SCCs
+		     1 : sort SCCs by increasing size (default)
+		     2 : sort SCCs by decreasing size
+		  */
+  int mlpSortSccMode; /* 0 : with area of SCCs
+			 1 : with the number of variable
+			 2 : with ratio (nCols/nRows, default)
+		      */
+  int mlpClusterMerge; /* Try to merge with a cluster which is already done
+			  (default = 0)
+			*/
+  int mlpMultiway; /* Quanity out all smooth variables during MLP clustering
+		      (default = 0)
+		   */
+  int mlpLambdaMode; /* 0 : Use the number of final support variables (default)
+			1 : Use the number of initial support variables
+		     */
+  int mlpSortedRows; /* Use a sorted row list for finding best columns
+		        (default = 1)
+		     */
+  int mlpSortedCols; /* Use a sorted row list for finding best columns
+		        (default = 1)
+		     */
+  int mlpPreSwapStateVars; /* Swap present and next state vars for MLP
+			      in preimage computation. (default = 0)
+			   */
+  int mlpPrintMatrix; /* Print dependence matrix during MLP (default = 0) */
+  char *mlpWriteOrder; /* file name to write a variable order from MLP */
+  int mlpVerbosity; /* Verbosity for MLP (default = 0) */
+  int mlpDebug; /* Debug for MLP (default = 0) */
+  int linearFineGrainFlag;
+  int linearGroupStateVariable;
+  int linearOrderVariable;
+  int linearIncludeCS;
+  int linearIncludeNS;
+  int linearQuantifyCS;
+  int linearComputeRange;
+  Img_OptimizeType linearOptimize;
+};
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [This structure stores the information needed for transition
+  function method based on splitting and hybrid method combining splitting
+  and conjunction.]
+
+  Description [The hybrid method also refers to this structure. Some fields
+  are common for image and preimage computations and some are only for
+  image or preimage computation.]
+
+******************************************************************************/
+struct ImgTfmInfo_s {
+  mdd_manager		*manager;
+  Img_MethodType	method;
+  array_t		*vector; /* array of ImgComponent_t */
+  array_t		*toCareSetArray; /* array of bdd_t */
+  int			nComponents;
+  int			nVars; /* number of all variables in bdd manager */
+  int			nRealVars; /* number of pi, ps, and ns */
+  ImgTfmOption_t	*option;
+  ImgCacheTable_t	*imgCache; /* image cache */
+  ImgCacheTable_t	*preCache; /* preimage cache */
+  ImgCacheTable_t	*cache; /* points either imgCache or preCache */
+  int			useConstraint;	/* only for image computation */
+  int			nRecursion; /* number of recursions(splits) */
+  int			nRecursionB; /* for preimage */
+  int			nLeaves; /* number of leaves during splitting */
+  int			nLeavesB; /* for preimage */
+  int			nTurns; /* number of cases that switch from
+				   splitting to conjunction */
+  int			nTurnsB; /* for preimage */
+  float			averageDepth;
+  float			averageDepthB; /* for preimage */
+  int			maxDepth;
+  int			maxDepthB; /* for preimage */
+  int			nDecomps;
+  int			topDecomp;
+  int			maxDecomp;
+  float			averageDecomp;
+  int			nFoundEssentials;
+  float			averageFoundEssential;
+  float			averageFoundEssentialDepth;
+  int			topFoundEssentialDepth;
+  int			*foundEssentials;
+  int			foundEssentialDepth;
+  int			lastFoundEssentialDepth;
+  int			nEmptySubImage;
+  int			nSplits;
+  int			nSplitsB; /* for preimage */
+  int			nConjoins;
+  int			nConjoinsB; /* for preimage */
+  int			nCubeSplits;
+  ImgFunctionData_t	*functionData;
+  st_table		*quantifyVarsTable;
+  st_table		*rangeVarsTable;
+  st_table		*intermediateVarsTable;
+  array_t		*intermediateBddVars;
+  array_t		*newQuantifyBddVars;
+  int			buildTR;
+  boolean		buildPartialTR;
+  array_t		*fwdClusteredRelationArray; /* array of bdd_t */
+  array_t		*bwdClusteredRelationArray; /* array of bdd_t */
+  array_t		*fwdArraySmoothVarBddArray; /* array of array_t */
+  array_t		*bwdArraySmoothVarBddArray; /* array of array_t */
+  array_t		*fwdSmoothVarCubeArray; /* array of bdd_t */
+  array_t		*bwdSmoothVarCubeArray; /* array of bdd_t */
+  array_t		*domainVarBddArray; /* array of bdd_t */
+  array_t		*quantifyVarBddArray; /* array of bdd_t */
+  array_t		*rangeVarBddArray; /* array of bdd_t */
+  ImgTrmOption_t	*trmOption;
+  array_t		*partialBddVars; /* array of bdd_t */
+  char			*partialVarFlag;
+  array_t		*fullVector; /* array of ImgComponent_t */
+  int			eliminateDepend;
+			/* 0 : do not perform this
+			   1 : eliminates dependent variables from
+				constraint and modifies function vector by
+				composition at every image computation.
+			   2 : once the number of eliminated variables
+				becomes zero, do not perform.
+			*/
+  int			nFoundDependVars;
+  float			averageFoundDependVars;
+  int			nPrevEliminatedFwd;
+  int			imageVerbosity;
+  array_t		*fwdSavedRelation; /* array of bdd_t */
+  array_t		*bwdSavedRelation; /* array of bdd_t */
+  array_t		*savedArraySmoothVarBddArray; /* array of array_t */
+  array_t		*savedSmoothVarCubeArray; /* array of bdd_t */
+  int			nImageComps;
+  int			nRangeComps;
+  int			maxIntermediateSize;
+  long			prevVectorBddSize;
+  int			prevVectorSize;
+  float			prevLambda;
+  int			prevTotal;
+  int			nIntermediateVars;
+  int			nonDeterministic;
+  boolean		imgKeepPiInTr; /* keep local primary input variables
+					  in building forward transition
+					  relation */
+  boolean		preKeepPiInTr; /* keep local primary input variables
+					  in building backward transition
+					  relation */
+  boolean		updatedFlag; /* tells whether the function vector or
+					the transition relation changed
+					from the originals during recursions */
+  mdd_t			*debugCareSet;
+};
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [This structure contains all options for trnasition function
+  method and also for hybrid method.]
+
+  Description [Most fields are commonly used for both image and preimage
+  computations, unless there are two separated fields. For some field,
+  there are two default values: one for transition function method and
+  the other is for hybrid method.]
+
+******************************************************************************/
+struct ImgTfmOption_s {
+  int verbosity;
+  int splitMethod;	/* 0 : input splitting (default for tfm)
+			   1 : output splitting
+			   2 : mixed (input split + output split)
+			   3 : hybrid (input split + transition relation)
+			*/
+  int inputSplit;	/* 0 : support before splitting (default)
+			   1 : support after splitting
+			   2 : estimate bdd size after splitting
+			   3 : top variable
+			*/
+  boolean piSplitFlag;	/* If set, primary input variables can be chosen
+			   as a splitting variable, otherwise only
+			   state variables are chosen (default = TRUE)
+			*/
+  int rangeComp;	/* 0 : do not convert to range computation
+			   1 : convert image computation into
+  			       range computation (default)
+			   2 : use a threshold (rangeThreshold,
+				default for hybrid)
+			*/
+  int rangeThreshold;	/* When rangeComp = 2, if the size of resulting BDDs
+			   of applying constrain is larger than the size of
+			   original vector times this threshold, then perform
+			   image computation. (default = 10)
+			*/
+  int rangeTryThreshold; /* The number of consecutive fails allowed in
+			    converting image to range computation,
+			    then force to keep image computation (default = 2)
+			 */
+  boolean rangeCheckReorder; /* If set, force to reorder before checking whether
+				to convert image to range computation
+				(default = FALSE)
+			     */
+  int tieBreakMode;	/* 0 : the closest variable to top (default)
+			   1 : the smallest BDD size after splitting
+			*/
+  int outputSplit;	/* 0 : smallest BDD size (default)
+			   1 : largest BDD size
+			   2 : top variable
+			*/
+  int turnDepth;	/* recursion depth when to change to the other method.
+			   -1 means dynamic decision for hybrid method.
+			   (default = 5, -1 for hybrid)
+			*/
+  boolean findDecompVar; /* If it is set, before we find a best splitting
+			    variable, we try to find a variable which can
+			    decompose function vector after splitting.
+			    (default = FALSE)
+			 */
+  boolean sortVectorFlag; /* If set, sort vector for better caching
+			     (default = TRUE for tfm, FALSE for hybrid)
+			  */
+  boolean printStatistics; /* If set, print statistics for cache and
+				recursions (default = FALSE)
+			   */
+  boolean printBddSize;	/* If set, print BDD size of all intermediate
+			   products (default = FALSE)
+			*/
+  boolean splitCubeFunc; /* If set, find a cube function element,
+			    then apply output splitting in input splitting
+			    (default = FALSE)
+			 */
+  int findEssential;	/* If set, find essential variabels from constraint
+			   and minimize function vector and relation.
+			   0 : off (default)
+			   1 : on
+			   2 : on and off dynamically
+			*/
+  int printEssential;	/* 0 : don't print (default)
+  			   1 : print only at end
+			   2 : print at every image computation
+			*/
+  int maxEssentialDepth;/* (default = 5, but not an option) */
+
+  /* The followings are used for image cache */
+  int useCache;		/* 0 : no cache (default for hybrid)
+			   1 : cache (default for tfm)
+			   2 : st cache (stores all intermediate results)
+			*/
+  boolean globalCache;	/* If set, keeps only one global cache,
+			   otherwise one cache per each submachine.
+			   (default = TRUE)
+			*/
+  int maxChainLength;	/* default = 2 */
+  int initCacheSize;	/* default = 1001 */
+  int autoFlushCache;	/* 0 : frees only when requested
+  			   1 : frees all cache contents at the end of one
+				whole image computation (default)
+			   2 : frees all cache contents before reordering
+			*/
+  boolean composeIntermediateVars;
+			/* If set, compose all intermediate variables
+			   (default = TRUE)
+			*/
+
+  /* The following options are just for pre-image computation */
+  int preSplitMethod;	/* 0 : input splitting (default)
+			   1 : output splitting
+			   2 : mixed
+			   3 : substitution
+			   4 : hybrid (input split + transition relation)
+			*/
+  int preInputSplit;	/* 0 : support before splitting (default)
+			   1 : support after splitting
+			   2 : estimate bdd size after splitting
+			   3 : top variable
+			*/
+  int preOutputSplit;	/* 0 : smallest BDD size (default)
+			   1 : largest BDD size
+			   2 : top variable
+			*/
+  int preDcLeafMethod;	/* 0 : substitution (default)
+			   1 : constraint cofactoring
+			   2 : hybrid
+			*/
+  boolean preMinimize;	/* If set, everytime we split function vector
+			   in output split method for pre-image,
+			   we try to minimize all functions in the vector
+			   with respect to the chosen function.
+			   (default = FALSE)
+			*/
+
+  /* The following options are used for hybrid method */
+  int hybridMode;	/* 0 : start with only transition function and
+				build transition relation on demand
+  			   1 : start with both transition function and
+				relation (default)
+			   2 : start with only transition relation
+			*/
+  int trSplitMethod;	/* This is just for hybridMode = 2.
+			   0 : use support (default)
+  			   1 : use estimate cofactored BDD size
+			*/
+  boolean buildPartialTR; /* If set, build partial transition relations of
+			    the variables that are not supposed to be
+			    chosen as a splitting variable (default = FALSE).
+			    This is just for hybridMode = 2.
+			  */
+  int nPartialVars;	/* default = 8 */
+  int partialMethod;	/* 0 : use BDD size (default)
+  			   1 : use support
+			*/
+  boolean delayedSplit;	/* If set, just keep cofactor variables and abstract
+			   variables as cubes until depth becomes threshold
+			   (default = FALSE)
+			   This is just for hybridMethod = 1.
+			*/
+  int splitMinDepth;	/* minimum depth for checking whether split or not
+			   (default = 1)
+			*/
+  int splitMaxDepth;	/* maximum depth for checking whether split or not
+			   (default = 5)
+			*/
+  int preSplitMinDepth;	/* minimum depth for preimage (default = 1) */
+  int preSplitMaxDepth;	/* maximum depth for preimage (default = 5) */
+  float lambdaThreshold; /* (default = 0.6) */
+  float preLambdaThreshold; /* (default = 0.6) */
+  float improveLambda; /* (default = 0.1) */
+  int improveVectorSize; /* (default = 3) */
+  float improveVectorBddSize; /* (default = 30.0) */
+  int conjoinVectorSize; /* (default = 10 ) */
+  int conjoinRelationSize; /* (default = 1) */
+  int conjoinRelationBddSize; /* (default = 200) */
+  int decideMode; /* 0 : use only lambda threshold
+		     1 : use also checking special condition to conjoin
+		     2 : use also checking improvement
+		     3 : use both (default)
+		 */
+  boolean reorderWithFrom; /* reorder relation array with from to conjoin
+			      (default = TRUE)
+			   */
+  boolean preReorderWithFrom; /* reorder relation array with from to conjoin
+				 (default = FALSE)
+			      */
+  int lambdaMode; /* 0 : total lifetime (lambda, default)
+		     1 : active lifetime (alpha)
+		     2 : total lifetime with introduced variables
+			 (this is just for analysis)
+		  */
+  int preLambdaMode; /* 0 : total lifetime (lambda, default)
+			1 : active lifetime (alpha)
+			2 : total lifetime with introduced variables
+			    (this is just for analysis)
+		     */
+  boolean lambdaFromMlp; /* compute lambda from MLP directly, otherwise from
+			    quantification schedule (default = FALSE)
+			 */
+  boolean lambdaWithFrom; /* compute lambda with from (default = TRUE) */
+  boolean lambdaWithTr; /* compute lambda with transition relation
+			   when both function and relation exist
+			   (default = TRUE)
+			*/
+  boolean lambdaWithClustering; /* compute lambda with clustering
+				   (default = FALSE)
+				*/
+  boolean synchronizeTr; /* when hybrid mode is 1, wnenever function vector
+			    changes, rebuild transition relation from the
+			    changed function vector
+			    (default = FALSE)
+			 */
+  boolean imgKeepPiInTr; /* If set, we keep all primary input variables in
+			    transition relation, otherwise, we quantify out
+			    local primary input variables from the
+			    transition relation. This affects only to
+			    forward transition relation.
+			    (default = FALSE)
+			 */
+  boolean preKeepPiInTr; /* If set, we keep all primary input variables in
+			    transition relation, otherwise, we quantify out
+			    local primary input variables from the
+			    transition relation. This affects only to
+			    backward transition relation. Unlike imgKeepPiInTr,
+			    we keep all primary inputs, we also keep the
+			    primary input variables in preimages. If image
+			    cache is used, this is automatically set to TRUE.
+			    (default = FALSE)
+			 */
+  Img_MethodType trMethod; /* transition relation method
+			      (default = Img_Iwls95_c)
+			   */
+  boolean preCanonical;
+
+  /* The following options are just for debugging and development */
+  boolean debug;
+  boolean checkEquivalence;
+  boolean printLambda;
+  int writeSupportMatrix; /* 0 : none
+			     1 : with only function vector
+			     2 : with transition relation
+			     3 : with function vector and relation
+			  */
+  boolean writeSupportMatrixWithYvars;
+  boolean writeSupportMatrixAndStop;
+  boolean writeSupportMatrixReverseRow;
+  boolean writeSupportMatrixReverseCol;
+  int supportFileCount;
+};
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [This structure stores all information of each next state
+  function or a function of intermediate variable.]
+
+  Description [If the field intermediate is 1, it is an intermediate
+  variable, otherwise it is a next state function. This structure is used
+  for tfm and hybrid methods.]
+
+******************************************************************************/
+struct ImgComponent_s {
+  mdd_t		*var;
+  mdd_t		*func;
+  char		*support;
+  short		id;
+  unsigned int	intermediate: 8;
+  unsigned int	flag: 8;
+};
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [This structure stores one intermediate result of image or
+  preimage.]
+
+  Description [The field constraint can be null when the result is of a
+  range computation. This structure is used for tfm and hybrid methods.]
+
+******************************************************************************/
+struct ImgCacheEntry_s {
+  array_t			*vector;
+  bdd_t				*constraint;
+  bdd_t				*result;
+  struct ImgCacheEntry_s	*next;
+};
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [This structure stores all information of an image cache table.]
+
+  Description [We keep image and preimage cache separately for higher hit
+  ratio. This structure is used for tfm and hybrid methods.]
+
+******************************************************************************/
+struct ImgCacheTable_s {
+  unsigned int		nSlots;
+  boolean		preImgFlag;
+  double		lookups;
+  double		hits;
+  double		inserts;
+  double		entries;
+  int 			maxChainLength;
+  ImgCacheEntry_t	**slot;
+  st_table		*stTable;
+  int			(*compareFunc)(array_t *, array_t *);
+  int			useConstraint;	/* copy of ImgTfmInfo_t */
+};
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [This structure is an entry for keeping all intermediate results
+  using st_table.]
+
+  Description [This structure is used as a key for st_table. This structure
+  is used for tfm and hybrid methods.]
+
+******************************************************************************/
+struct ImgCacheStKey_s {
+  array_t	*vector;
+  bdd_t		*constraint;
+};
+
+/**Struct**********************************************************************
+ 
+  Synopsis    [ ]
+
+  Description [ ]
+
+******************************************************************************/
+struct VarLifeStruct {
+    double index;
+    int from;
+    int to;
+    int effFrom;
+    int effTo;
+    int id;
+    int stateVar;
+    int *relArr;
+    int nSize;
+    int flag;
+    int dummy;
+    int dummy1;
+};
+
+/**Struct**********************************************************************
+ 
+  Synopsis    [ ]
+
+  Description [ ]
+
+******************************************************************************/
+struct RelationStruct {
+    mdd_manager *mgr;
+    struct ConjunctStruct  **conjunctArray;
+    int nSize;
+    struct ConjunctStruct  ***connectedComponent;
+    int nConnectedComponent;
+    int *rangeVars;
+    int nRange;
+    int *domainVars;
+    int nDomain;
+    int *quantifyVars;
+    int nQuantify;
+    int *domain2range;
+    int *range2domain;
+    int *varType;
+    bdd_t **constantCase;
+    int nVar;
+    int *varArrayMap;
+    struct VarLifeStruct **varArray;
+    int nVarArray;
+    int nEffRange;
+    int nEffDomain;
+    int nEffQuantify;
+    int nInitRange;
+    int nInitDomain;
+    int nInitQuantify;
+
+    int bddLimit;
+
+    struct ConjunctStruct  **singletonArray;
+    int nSingletonArray;
+    struct ConjunctStruct  **pseudoSingletonArray;
+    int nPseudoSingletonArray;
+    struct ConjunctStruct  **nextStateArray;
+    int nNextStateArray;
+    struct ConjunctStruct  **allQuantifiedArray;
+    int nAllQuantifiedArray;
+    struct ConjunctStruct  **containedArray;
+    int nContainedArray;
+    int nTotalCluster;
+    struct ClusterStruct **clusterArray;
+    int nClusterArray;
+    Heap_t *clusterHeap;
+    int bModified;
+    int bRefineVarArray;
+    int includeCS;
+    int includeNS;
+    int quantifyCS;
+    int computeRange;
+
+    int verbosity;
+    int dummy;
+};
+
+/**Struct**********************************************************************
+ 
+  Synopsis    [ ]
+
+  Description [ ]
+
+******************************************************************************/
+struct ClusterStruct {
+    int from;
+    int to;
+    int nVar;
+    int nDead;
+    int nAffinity;
+    int flag;
+};
+
+/**Struct**********************************************************************
+ 
+  Synopsis    [ ]
+
+  Description [ ]
+
+******************************************************************************/
+struct ConjunctStruct {
+    int index;
+    int nRange;
+    int nDomain;
+    int nQuantify;
+    int nLive;
+    int from;
+    int to;
+    bdd_t *relation;
+    int *supList;
+    int nSize;
+    int bModified;
+    int bClustered;
+    struct ConjunctStruct **clusterArray;
+    int nCluster;
+    int bSingleton;
+    long dummy;
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#define	IMG_TF_MAX_INT		2000000000
+#define	IMG_TF_MAX_PRINT_DEPTH	100
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN bdd_t * ImgMlpMultiwayAndSmooth(mdd_manager *mddManager, ImgFunctionData_t *functionData, array_t *relationArray, array_t *domainVarBddArray, array_t *quantifyVarBddArray, array_t *rangeVarBddArray, Img_DirectionType direction, ImgTrmOption_t *option);
+EXTERN void ImgMlpClusterRelationArray(mdd_manager *mddManager, ImgFunctionData_t *functionData, array_t *relationArray, array_t *domainVarBddArray, array_t *quantifyVarBddArray, array_t *rangeVarBddArray, Img_DirectionType direction, array_t **clusteredRelationArrayPtr, array_t **arraySmoothVarBddArrayPtr, ImgTrmOption_t *option);
+EXTERN void ImgMlpOrderRelationArray(mdd_manager *mddManager, array_t *relationArray, array_t *domainVarBddArray, array_t *quantifyVarBddArray, array_t *rangeVarBddArray, Img_DirectionType direction, array_t **orderedRelationArrayPtr, array_t **arraySmoothVarBddArrayPtr, ImgTrmOption_t *option);
+EXTERN float ImgMlpComputeLambda(mdd_manager *mddManager, array_t *relationArray, array_t *domainVarBddArray, array_t *quantifyVarBddArray, array_t *rangeVarBddArray, Img_DirectionType direction, int mode, int asIs, int *prevArea, float *improvedLambda, ImgTrmOption_t *option);
+EXTERN void ImgMlpGetQuantificationSchedule(mdd_manager *mddManager, array_t *relationArray, array_t *domainVarBddArray, array_t *quantifyVarBddArray, array_t *rangeVarBddArray, array_t **clusteredRelationArrayPtr, array_t **arraySmoothVarBddArrayPtr, Img_DirectionType direction, ImgTrmOption_t *option);
+EXTERN void ImgMlpPrintDependenceMatrix(mdd_manager *mddManager, array_t *relationArray, array_t *domainVarBddArray, array_t *quantifyVarBddArray, array_t *rangeVarBddArray, Img_DirectionType direction, int printFlag, FILE *fout, ImgTrmOption_t *option);
+EXTERN void ImgMlpWriteClusterFile(FILE *fout, mdd_manager *mddManager, array_t *relationArray, array_t *psVarBddArray, array_t *nsVarBddArray);
+EXTERN void ImgMlpReadClusterFile(FILE *fin, mdd_manager *mddManager, ImgFunctionData_t *functionData, array_t *relationArray, array_t *psVarBddArray, array_t *nsVarBddArray, array_t *quantifyVarBddArray, Img_DirectionType direction, array_t **clusteredRelationArrayPtr, array_t **arraySmoothVarBddArrayPtr, ImgTrmOption_t *option);
+EXTERN void * ImgImageInfoInitializeApprox(ImgFunctionData_t *functionData, Img_DirectionType directionType);
+EXTERN mdd_t * ImgImageInfoComputeFwdApprox(ImgFunctionData_t *functionData, void *methodData, mdd_t *fromLowerBound, mdd_t *fromUpperBound, mdd_t *toCareSet);
+EXTERN mdd_t * ImgImageInfoComputeFwdWithDomainVarsApprox(ImgFunctionData_t *functionData, void *methodData, mdd_t *fromLowerBound, mdd_t *fromUpperBound, mdd_t *toCareSet);
+EXTERN mdd_t * ImgImageInfoComputeBwdWithDomainVarsApprox(ImgFunctionData_t *functionData, void *methodData, mdd_t *fromLowerBound, mdd_t *fromUpperBound, mdd_t *toCareSet);
+EXTERN mdd_t * ImgImageInfoComputeBwdApprox(ImgFunctionData_t *functionData, void *methodData, mdd_t *fromLowerBound, mdd_t *fromUpperBound, mdd_t *toCareSet);
+EXTERN void ImgImageInfoPrintMethodParamsApprox(void *methodData, FILE *fp);
+EXTERN void ImgImageInfoFreeApprox(void *methodData);
+EXTERN mdd_t * ImgImageInfoComputeFwdFwdGrad(ImgFunctionData_t *functionData, void *methodData, mdd_t *fromLowerBound, mdd_t *fromUpperBound, mdd_t *toCareSet);
+EXTERN mdd_t * ImgImageInfoComputeFwdWithDomainVarsFwdGrad(ImgFunctionData_t *functionData, void *methodData, mdd_t *fromLowerBound, mdd_t *fromUpperBound, mdd_t *toCareSet);
+EXTERN void ImgImageInfoFreeFwdGradual(void *methodData);
+EXTERN void * ImgImageInfoInitializeGradual(void *methodData, ImgFunctionData_t * functionData, Img_DirectionType directionType);
+EXTERN void ImgImageInfoPrintMethodParamsFwdGrad(void *methodData, FILE *fp);
+EXTERN int ImgDecideSplitOrConjoin(ImgTfmInfo_t *info, array_t *vector, mdd_t *from, int preFlag, array_t *relationArray, mdd_t *cofactorCube, mdd_t *abstractCube, int useBothFlag, int depth);
+EXTERN mdd_t * ImgImageByHybrid(ImgTfmInfo_t *info, array_t *vector, mdd_t *from);
+EXTERN mdd_t * ImgImageByHybridWithStaticSplit(ImgTfmInfo_t *info, array_t *vector, mdd_t *from, array_t *relationArray, mdd_t *cofactorCube, mdd_t *abstractCube);
+EXTERN mdd_t * ImgPreImageByHybrid(ImgTfmInfo_t *info, array_t *vector, mdd_t *from);
+EXTERN mdd_t * ImgPreImageByHybridWithStaticSplit(ImgTfmInfo_t *info, array_t *vector, mdd_t *from, array_t *relationArray, mdd_t *cofactorCube, mdd_t *abstractCube);
+EXTERN int ImgCheckEquivalence(ImgTfmInfo_t *info, array_t *vector, array_t *relationArray, mdd_t *cofactorCube, mdd_t *abstractCube, int preFlag);
+EXTERN int ImgCheckMatching(ImgTfmInfo_t *info, array_t *vector, array_t *relationArray);
+EXTERN mdd_t* ImgMultiwayLinearAndSmooth(mdd_manager *mddManager, array_t *relationArray, array_t *smoothVarBddArray, array_t *introducedVarBddArray, Img_MethodType method, Img_DirectionType direction, ImgTrmOption_t *option);
+EXTERN mdd_t* ImgMultiwayLinearAndSmoothWithFrom(mdd_manager *mddManager, array_t *relationArray, mdd_t *from, array_t *smoothVarBddArray, array_t *domainVarBddArray, array_t *introducedVarBddArray, Img_MethodType method, Img_DirectionType direction, ImgTrmOption_t *option);
+EXTERN mdd_t* ImgBddLinearAndSmooth(mdd_manager *mddManager, mdd_t *from, array_t *relationArray, array_t *arraySmoothVarBddArray, array_t *smoothVarCubeArray, int verbosity);
+EXTERN array_t * ImgClusterRelationArray(mdd_manager *mddManager, ImgFunctionData_t *functionData, Img_MethodType method, Img_DirectionType direction, ImgTrmOption_t *option, array_t *relationArray, array_t *domainVarBddArray, array_t *quantifyVarBddArray, array_t *rangeVarBddArray, array_t **arraySmoothVarBddArray, array_t **smoothVarCubeArray, boolean freeRelationArray);
+EXTERN array_t * ImgGetQuantificationSchedule(mdd_manager *mddManager, ImgFunctionData_t *functionData, Img_MethodType method, Img_DirectionType direction, ImgTrmOption_t *option, array_t *relationArray, array_t *smoothVarBddArray, array_t *domainVarBddArray, array_t *introducedVarBddArray, boolean withClustering, array_t **orderedRelationArrayPtr);
+EXTERN ImgTrmOption_t * ImgGetTrmOptions(void);
+EXTERN void ImgFreeTrmOptions(ImgTrmOption_t *option);
+EXTERN void * ImgImageInfoInitializeIwls95(void *methodData, ImgFunctionData_t *functionData, Img_DirectionType directionType, Img_MethodType method);
+EXTERN mdd_t * ImgImageInfoComputeFwdIwls95(ImgFunctionData_t *functionData, Img_ImageInfo_t *imageInfo, mdd_t *fromLowerBound, mdd_t *fromUpperBound, array_t *toCareSetArray);
+EXTERN mdd_t * ImgImageInfoComputeFwdWithDomainVarsIwls95(ImgFunctionData_t *functionData, Img_ImageInfo_t *imageInfo, mdd_t *fromLowerBound, mdd_t *fromUpperBound, array_t *toCareSetArray);
+EXTERN mdd_t * ImgImageInfoComputeBwdIwls95(ImgFunctionData_t *functionData, Img_ImageInfo_t *imageInfo, mdd_t *fromLowerBound, mdd_t *fromUpperBound, array_t *toCareSetArray);
+EXTERN mdd_t * ImgImageInfoComputeBwdWithDomainVarsIwls95(ImgFunctionData_t *functionData, Img_ImageInfo_t *imageInfo, mdd_t *fromLowerBound, mdd_t *fromUpperBound, array_t *toCareSetArray);
+EXTERN void ImgImageInfoFreeIwls95(void *methodData);
+EXTERN void ImgImageInfoPrintMethodParamsIwls95(void *methodData, FILE *fp);
+EXTERN st_table * ImgBddGetSupportIdTable(bdd_t *function);
+EXTERN boolean ImgImageWasPartialIwls95(void *methodData);
+EXTERN void ImgImageAllowPartialImageIwls95(void *methodData, boolean value);
+EXTERN void ImgRestoreTransitionRelationIwls95(Img_ImageInfo_t *imageInfo, Img_DirectionType directionType);
+EXTERN void ImgDuplicateTransitionRelationIwls95(Img_ImageInfo_t *imageInfo, Img_DirectionType directionType);
+EXTERN void ImgMinimizeTransitionRelationIwls95(void *methodData, ImgFunctionData_t *functionData, array_t *constrainArray, Img_MinimizeType minimizeMethod, Img_DirectionType directionType, boolean reorderClusters, int printStatus);
+EXTERN void ImgAbstractTransitionRelationIwls95(Img_ImageInfo_t *imageInfo, array_t *abstractVars, mdd_t *abstractCube, Img_DirectionType directionType, int printStatus);
+EXTERN int ImgApproximateTransitionRelationIwls95(mdd_manager *mgr, void *methodData, bdd_approx_dir_t approxDir, bdd_approx_type_t approxMethod, int approxThreshold, double approxQuality, double approxQualityBias, Img_DirectionType directionType, mdd_t *bias);
+EXTERN array_t * ImgGetTransitionRelationIwls95(void *methodData, Img_DirectionType directionType);
+EXTERN void ImgUpdateTransitionRelationIwls95(void *methodData, array_t *relationArray, Img_DirectionType directionType);
+EXTERN void ImgReplaceIthPartitionedTransitionRelationIwls95(void *methodData, int i, mdd_t *relation, Img_DirectionType directionType);
+EXTERN void ImgImageFreeClusteredTransitionRelationIwls95(void *methodData, Img_DirectionType directionType);
+EXTERN void ImgImageConstrainAndClusterTransitionRelationIwls95OrMlp(Img_ImageInfo_t *imageInfo, Img_DirectionType direction, mdd_t *constrain, Img_MinimizeType minimizeMethod, boolean underApprox, boolean cleanUp, boolean forceReorder, int printStatus);
+EXTERN void ImgPrintIntegerArray(array_t *idArray);
+EXTERN void ImgPrintPartition(graph_t *partition);
+EXTERN void ImgPrintPartitionedTransitionRelation(mdd_manager *mddManager, array_t *relationArray, array_t *arraySmoothVarBddArray);
+EXTERN mdd_t * ImgTrmEliminateDependVars(ImgFunctionData_t *functionData, array_t *relationArray, mdd_t *states, mdd_t **dependRelations, int *nDependVars);
+EXTERN void * ImgImageInfoInitializeMono(void *methodData, ImgFunctionData_t * functionData, Img_DirectionType directionType);
+EXTERN mdd_t * ImgImageInfoComputeFwdMono(ImgFunctionData_t * functionData, Img_ImageInfo_t * imageInfo, mdd_t *fromLowerBound, mdd_t *fromUpperBound, array_t * toCareSetArray);
+EXTERN mdd_t * ImgImageInfoComputeFwdWithDomainVarsMono(ImgFunctionData_t *functionData, Img_ImageInfo_t *imageInfo, mdd_t *fromLowerBound, mdd_t *fromUpperBound, array_t *toCareSetArray);
+EXTERN mdd_t * ImgImageInfoComputeBwdMono(ImgFunctionData_t * functionData, Img_ImageInfo_t *imageInfo, mdd_t *fromLowerBound, mdd_t *fromUpperBound, array_t *toCareSetArray);
+EXTERN mdd_t * ImgImageInfoComputeBwdWithDomainVarsMono(ImgFunctionData_t * functionData, Img_ImageInfo_t *imageInfo, mdd_t *fromLowerBound, mdd_t *fromUpperBound, array_t *toCareSetArray);
+EXTERN void ImgImageInfoFreeMono(void * methodData);
+EXTERN void ImgImageInfoPrintMethodParamsMono(void *methodData, FILE *fp);
+EXTERN void ImgRestoreTransitionRelationMono(Img_ImageInfo_t *imageInfo, Img_DirectionType directionType);
+EXTERN void ImgDuplicateTransitionRelationMono(Img_ImageInfo_t *imageInfo);
+EXTERN void ImgMinimizeTransitionRelationMono(Img_ImageInfo_t *imageInfo, array_t *constrainArray, Img_MinimizeType minimizeMethod, int printStatus);
+EXTERN void ImgAddDontCareToTransitionRelationMono(Img_ImageInfo_t *imageInfo, array_t *constrainArray, Img_MinimizeType minimizeMethod, int printStatus);
+EXTERN void ImgAbstractTransitionRelationMono(Img_ImageInfo_t *imageInfo, array_t *abstractVars, mdd_t *abstractCube, int printStatus);
+EXTERN int ImgApproximateTransitionRelationMono(mdd_manager *mgr, Img_ImageInfo_t *imageInfo, bdd_approx_dir_t approxDir, bdd_approx_type_t approxMethod, int approxThreshold, double approxQuality, double approxQualityBias, mdd_t *bias);
+EXTERN void ImgImageConstrainAndClusterTransitionRelationMono(Img_ImageInfo_t *imageInfo, mdd_t *constrain, Img_MinimizeType minimizeMethod, boolean underApprox, boolean cleanUp, boolean forceReorder, int printStatus);
+EXTERN void * ImgImageInfoInitializeTfm(void *methodData, ImgFunctionData_t * functionData, Img_DirectionType directionType, Img_MethodType method);
+EXTERN mdd_t * ImgImageInfoComputeFwdTfm(ImgFunctionData_t *functionData, Img_ImageInfo_t *imageInfo, mdd_t *fromLowerBound, mdd_t *fromUpperBound, array_t *toCareSetArray);
+EXTERN mdd_t * ImgImageInfoComputeFwdWithDomainVarsTfm(ImgFunctionData_t *functionData, Img_ImageInfo_t *imageInfo, mdd_t *fromLowerBound, mdd_t *fromUpperBound, array_t *toCareSetArray);
+EXTERN mdd_t * ImgImageInfoComputeBwdTfm(ImgFunctionData_t *functionData, Img_ImageInfo_t *imageInfo, mdd_t *fromLowerBound, mdd_t *fromUpperBound, array_t *toCareSetArray);
+EXTERN mdd_t * ImgImageInfoComputeBwdWithDomainVarsTfm(ImgFunctionData_t *functionData, Img_ImageInfo_t *imageInfo, mdd_t *fromLowerBound, mdd_t *fromUpperBound, array_t *toCareSetArray);
+EXTERN void ImgImageInfoFreeTfm(void *methodData);
+EXTERN void ImgImageInfoPrintMethodParamsTfm(void *methodData, FILE *fp);
+EXTERN void ImgRestoreTransitionFunction(Img_ImageInfo_t *imageInfo, Img_DirectionType directionType);
+EXTERN void ImgDuplicateTransitionFunction(Img_ImageInfo_t *imageInfo, Img_DirectionType directionType);
+EXTERN void ImgMinimizeTransitionFunction(void *methodData, array_t *constrainArray, Img_MinimizeType minimizeMethod, Img_DirectionType directionType, int printStatus);
+EXTERN void ImgAddDontCareToTransitionFunction(void *methodData, array_t *constrainArray, Img_MinimizeType minimizeMethod, Img_DirectionType directionType, int printStatus);
+EXTERN void ImgAbstractTransitionFunction(Img_ImageInfo_t *imageInfo, array_t *abstractVars, mdd_t *abstractCube, Img_DirectionType directionType, int printStatus);
+EXTERN int ImgApproximateTransitionFunction(mdd_manager *mgr, void *methodData, bdd_approx_dir_t approxDir, bdd_approx_type_t approxMethod, int approxThreshold, double approxQuality, double approxQualityBias, Img_DirectionType directionType, mdd_t *bias);
+EXTERN array_t * ImgGetTransitionFunction(void *methodData, Img_DirectionType directionType);
+EXTERN void ImgUpdateTransitionFunction(void *methodData, array_t *vector, Img_DirectionType directionType);
+EXTERN void ImgReplaceIthTransitionFunction(void *methodData, int i, mdd_t *function, Img_DirectionType directionType);
+EXTERN ImgTfmOption_t * ImgTfmGetOptions(Img_MethodType method);
+EXTERN void ImgImageFreeClusteredTransitionRelationTfm(void *methodData, Img_DirectionType directionType);
+EXTERN void ImgImageConstrainAndClusterTransitionRelationTfm(Img_ImageInfo_t *imageInfo, Img_DirectionType direction, mdd_t *constrain, Img_MinimizeType minimizeMethod, boolean underApprox, boolean cleanUp, boolean forceReorder, int printStatus);
+EXTERN int ImgIsPartitionedTransitionRelationTfm(Img_ImageInfo_t *imageInfo);
+EXTERN bdd_t * ImgTfmPreImage(ImgTfmInfo_t *info, bdd_t *image);
+EXTERN void ImgCacheInitTable(ImgTfmInfo_t *info, int num_slot, int globalCache, boolean preImgFlag);
+EXTERN void ImgCacheDestroyTable(ImgCacheTable_t *table, int globalCache);
+EXTERN bdd_t * ImgCacheLookupTable(ImgTfmInfo_t *info, ImgCacheTable_t *table, array_t *delta, bdd_t *constraint);
+EXTERN void ImgCacheInsertTable(ImgCacheTable_t *table, array_t *delta, bdd_t *constraint, bdd_t *result);
+EXTERN void ImgFlushCache(ImgCacheTable_t *table);
+EXTERN void ImgPrintCacheStatistics(ImgCacheTable_t *cache);
+EXTERN mdd_t * ImgTfmImage(ImgTfmInfo_t *info, mdd_t *from);
+EXTERN mdd_t * ImgChooseTrSplitVar(ImgTfmInfo_t *info, array_t *vector, array_t *relationArray, int trSplitMethod, int piSplitFlag);
+EXTERN void ImgVectorConstrain(ImgTfmInfo_t *info, array_t *vector, mdd_t *constraint, array_t *relationArray, array_t **newVector, mdd_t **cube, array_t **newRelationArray, mdd_t **cofactorCube, mdd_t **abstractCube, boolean singleVarFlag);
+EXTERN mdd_t * ImgVectorMinimize(ImgTfmInfo_t *info, array_t *vector, mdd_t *constraint, mdd_t *from, array_t *relationArray, array_t **newVector, mdd_t **cube, array_t **newRelationArray, mdd_t **cofactorCube, mdd_t **abstractCube);
+EXTERN void ImgVectorFree(array_t *vector);
+EXTERN int ImgVectorFunctionSize(array_t *vector);
+EXTERN long ImgVectorBddSize(array_t *vector);
+EXTERN array_t * ImgVectorCopy(ImgTfmInfo_t *info, array_t *vector);
+EXTERN ImgComponent_t * ImgComponentAlloc(ImgTfmInfo_t *info);
+EXTERN ImgComponent_t * ImgComponentCopy(ImgTfmInfo_t *info, ImgComponent_t *comp);
+EXTERN void ImgComponentFree(ImgComponent_t *comp);
+EXTERN void ImgComponentGetSupport(ImgComponent_t *comp);
+EXTERN void ImgSupportCopy(ImgTfmInfo_t *info, char *dsupport, char *ssupport);
+EXTERN void ImgSupportClear(ImgTfmInfo_t *info, char *support);
+EXTERN void ImgSupportPrint(ImgTfmInfo_t *info, char *support);
+EXTERN int ImgSupportCount(ImgTfmInfo_t *info, char *support);
+EXTERN array_t * ImgGetConstrainedRelationArray(ImgTfmInfo_t *info, array_t *relationArray, mdd_t *constraint);
+EXTERN array_t * ImgGetCofactoredRelationArray(array_t *relationArray, mdd_t *func);
+EXTERN void ImgCofactorRelationArray(array_t *relationArray, mdd_t *func);
+EXTERN array_t * ImgGetAbstractedRelationArray(mdd_manager *manager, array_t *relationArray, mdd_t *cube);
+EXTERN void ImgAbstractRelationArray(mdd_manager *manager, array_t *relationArray, mdd_t *cube);
+EXTERN array_t * ImgGetCofactoredAbstractedRelationArray(mdd_manager *manager, array_t *relationArray, mdd_t *cofactorCube, mdd_t *abstractCube);
+EXTERN array_t * ImgGetAbstractedCofactoredRelationArray(mdd_manager *manager, array_t *relationArray, mdd_t *cofactorCube, mdd_t *abstractCube);
+EXTERN array_t * ImgGetConstrainedVector(ImgTfmInfo_t *info, array_t *vector, mdd_t *constraint);
+EXTERN array_t * ImgGetCofactoredVector(ImgTfmInfo_t *info, array_t *vector, mdd_t *func);
+EXTERN void ImgCofactorVector(ImgTfmInfo_t *info, array_t *vector, mdd_t *func);
+EXTERN mdd_t * ImgTfmEliminateDependVars(ImgTfmInfo_t *info, array_t *vector, array_t *relationArray, mdd_t *states, array_t **newVector, mdd_t **dependRelations);
+EXTERN int ImgExistConstIntermediateVar(array_t *vector);
+EXTERN mdd_t * ImgGetComposedFunction(array_t *vector);
+EXTERN ImgComponent_t * ImgGetLatchComponent(array_t *vector);
+EXTERN array_t * ImgComposeConstIntermediateVars(ImgTfmInfo_t *info, array_t *vector, mdd_t *constIntermediate, mdd_t **cofactorCube, mdd_t **abstractCube, mdd_t **and_, mdd_t **from);
+EXTERN int ImgCountBddSupports(mdd_t *func);
+EXTERN void ImgCheckConstConstrain(mdd_t *f1, mdd_t *f2, int *f21p, int *f21n);
+EXTERN int ImgConstConstrain(mdd_t *func, mdd_t *constraint);
+EXTERN void ImgPrintVectorDependency(ImgTfmInfo_t *info, array_t *vector, int verbosity);
+EXTERN float ImgPercentVectorDependency(ImgTfmInfo_t *info, array_t *vector, int length, int *nLongs);
+EXTERN void ImgWriteSupportMatrix(ImgTfmInfo_t *info, array_t *vector, array_t *relationArray, char *string);
+EXTERN array_t * ImgMinimizeImageArrayWithCareSetArray(array_t *imageArray, array_t *careSetArray, Img_MinimizeType minimizeMethod, boolean underapprox, boolean printInfo, Img_DirectionType dir);
+EXTERN void ImgMinimizeImageArrayWithCareSetArrayInSitu(array_t *imageArray, array_t *careSetArray, Img_MinimizeType minimizeMethod, boolean underapprox, boolean printInfo, Img_DirectionType dir);
+EXTERN mdd_t * ImgSubstitute(mdd_t *f, ImgFunctionData_t *functionData, Img_SubstituteDir dir);
+EXTERN array_t * ImgSubstituteArray(array_t *f_array, ImgFunctionData_t *functionData, Img_SubstituteDir dir);
+EXTERN void ImgPrintPartialImageOptions(void);
+EXTERN ImgPartialImageOption_t * ImgGetPartialImageOptions(void);
+EXTERN int ImgArrayBddArrayCheckValidity(array_t *arrayBddArray);
+EXTERN int ImgBddArrayCheckValidity(array_t *bddArray);
+EXTERN int ImgBddCheckValidity(bdd_t *bdd);
+EXTERN void ImgPrintVarIdTable(st_table *table);
+EXTERN int ImgCheckToCareSetArrayChanged(array_t *toCareSetArray1, array_t *toCareSetArray2);
+
+EXTERN Relation_t * ImgLinearRelationInit(mdd_manager *mgr, array_t *relationArray, array_t *domainBddVars, array_t *rangeBddVars, array_t *qunatifyBddVars, ImgTrmOption_t *option);
+EXTERN void ImgLinearRelationQuit(Relation_t *head);
+EXTERN void ImgLinearRefineRelation(Relation_t *head);
+
+EXTERN array_t * ImgLinearExtractRelationArrayT(Relation_t *head);
+EXTERN bdd_t ** ImgLinearExtractRelationArray(Relation_t *head);
+EXTERN array_t * ImgLinearMakeSmoothVarBdd(Relation_t *head, bdd_t **smoothCubeArr);
+EXTERN int * ImgLinearGetSupportBddId(mdd_manager *mgr, bdd_t *f, int *nSize);
+EXTERN void ImgLinearOptimizeInternalVariables(Relation_t *head);
+EXTERN int ImgLinearClusteringIteratively(Relation_t *head, double affinityLimit, int andExistLimit, int varLimit, int includeZeroGain, int useFailureHistory, Img_OptimizeType optDir, int (*compare_func)(const void *, const void *));
+EXTERN void ImgLinearClusteringByConstraints(Relation_t *head, int includeZeroGain, int varLimit, int clusterLimit, int gainLimit, double affinityLimit, int andExistLimit, int bddLimit, int useFailureHistory, int (*compare_func)(const void *, const void *));
+
+
+EXTERN void ImgLinearClusterRelationArray(mdd_manager *mgr, ImgFunctionData_t *functionData, array_t *relationArray, Img_DirectionType direction, array_t **clusteredRelationArrayPtr, array_t **arraySmoothVarBddArrayPtr, array_t **optClusteredRelationArrayPtr, array_t **optArraySmoothVarBddArrayPtr, ImgTrmOption_t *option);
+
+EXTERN int ImgLinearOptimizeAll(Relation_t *head, Img_OptimizeType optDir, int constantNSOpt);
+
+EXTERN void ImgResetMethodDataLinearComputeRange(void *methodData);
+EXTERN void ImgSetMethodDataLinearComputeRange(void *methodData);
+
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _INT */
Index: vis_dev/vis-2.3/src/img/imgIwls95.c
===================================================================
--- vis_dev/vis-2.3/src/img/imgIwls95.c	(revision 14)
+++ vis_dev/vis-2.3/src/img/imgIwls95.c	(revision 14)
@@ -0,0 +1,6476 @@
+/**CFile***********************************************************************
+
+  FileName    [imgIwls95.c]
+
+  PackageName [img]
+
+  Synopsis    [Routines for image computation using component transition
+               relation approach described in the proceedings of IWLS'95,
+               (henceforth referred to Iwls95 technique).]
+
+  Description [<p>The initialization process performs following steps:
+  <UL>
+  <LI> Create the relation of the roots at the bit level
+  in terms of the quantify and domain variables.
+  <LI> Order the bit level relations.
+  <LI> Group the relations of bits together, making a cluster
+  whenever the BDD size reaches a threshold.
+  <LI> For each cluster, quantify out the quantify variables which
+  are local to that particular cluster.
+  <LI> Order the clusters using the algorithm given in
+  "Efficient BDD Algorithms for FSM Synthesis and
+  Verification", by R. K. Ranjan et. al. in the proceedings of
+  IWLS'95{1}.
+  <LI> The orders of the clusters for forward and backward image are
+  calculated and stored. Also stored is the schedule of
+  variables for early quantification.
+  </UL>
+  For forward and backward image computation the corresponding
+  routines are called with appropriate ordering of clusters and
+  early quantification schedule. <p>
+  Note that, a cubic implementation of the above algorithm is
+  straightforward. However, to obtain quadratic complexity requires
+  significant amount of book-keeping. This is the reason for the complexity
+  of the code in this file.]
+
+  SeeAlso     []
+
+  Author      [Rajeev K. Ranjan, In-Ho Moon, Kavita Ravi]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+#include "imgInt.h"
+#include "fsm.h"
+
+static char rcsid[] UNUSED = "$Id: imgIwls95.c,v 1.127 2005/05/18 18:11:57 jinh Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+#define domainVar_c 0
+#define rangeVar_c 1
+#define quantifyVar_c 2
+#define IMG_IWLS95_DEBUG
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef struct Iwls95InfoStruct Iwls95Info_t;
+typedef struct CtrInfoStruct CtrInfo_t;
+typedef struct VarInfoStruct VarInfo_t;
+typedef struct CtrItemStruct CtrItem_t;
+typedef struct VarItemStruct VarItem_t;
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+/**Struct**********************************************************************
+
+  Synopsis    [This structure stores the information needed for iterative image
+  computation by IWLS'95 method.]
+
+  Description [A step of image computation is computed by taking the product of
+  "From" set with the BDD's of fwdClusteredRelationArray in order.
+  "fwdArraySmoothVarBddArray[i]" is an array of Bdd variables, which represents
+  the set of variables which can be quantified out once
+  fwdClusteredRelationArray[i] is multiplied in the product. Similar analysis
+  holds good for bwdClusteredRelationArray.
+
+  <p>The "option" struct contains option values for computing the above
+  mentioned arrays and also controls the verbosity.
+
+  <p>The bit relation array contains the transition relation in a bit relation
+  form.
+
+  <p>The quantifyVarMddIdArray contains functionData->quantifyVars and any
+  intermediate variables that need to be quantified.
+
+  <p> The *SmoothVarCubeArrays hold the same information as the
+  *ArraySmoothVarBddArrays, but in the form of an array of cubes, one cube for
+  each entry of *ArraySmoothVarBddArrays, because the quantification functions
+  expect a cube. 
+
+  <p>AllowPartialImage is an option for high-density analysis, if it is true,
+  image is allowed to return a subset instead of the correct result.  If it
+  does so, it will set wasPartialImage.  The PIOptions field keeps the options
+  for partial image computation. (See the definition of the type)
+
+  <p> The bwdClusteredCofactoredRelationArray is the
+  clusteredCofactoredRelationArray minimized wrt careSetArray.  Minimization
+  only takes place when the careSetArray that is passed is changed.  They can
+  both be NIL, which means that they need to be recomputed.
+  
+  <p> RB What are savedArray*, method, eliminateDepend, nFoundDependVars,
+  averageFOundDependVars, nPrev*, and lazySiftFlag????]
+
+******************************************************************************/
+
+struct Iwls95InfoStruct {
+  array_t *bitRelationArray; 
+
+  array_t *quantifyVarMddIdArray;
+
+  array_t *fwdOptClusteredRelationArray;
+  array_t *fwdClusteredRelationArray;
+  array_t *fwdOriClusteredRelationArray;
+  array_t *bwdClusteredRelationArray;
+  array_t *bwdOriClusteredRelationArray;
+  array_t *bwdClusteredCofactoredRelationArray;
+  array_t *careSetArray;
+
+  array_t *fwdOptArraySmoothVarBddArray;
+  array_t *fwdArraySmoothVarBddArray;
+  array_t *bwdArraySmoothVarBddArray;
+  array_t *fwdOptSmoothVarCubeArray;
+  array_t *fwdSmoothVarCubeArray;
+  array_t *bwdSmoothVarCubeArray;
+
+  boolean allowPartialImage;
+  boolean wasPartialImage;
+  ImgPartialImageOption_t *PIoption;
+
+  array_t *savedArraySmoothVarBddArray;
+  array_t *savedSmoothVarCubeArray;
+
+  Img_MethodType method;
+  ImgTrmOption_t *option;
+
+  int eliminateDepend;
+	/* 0 : do not perform this
+	   1 : eliminates dependent variables from
+		constraint and modifies function vector by
+		composition at every image computation.
+	   2 : once the number of eliminated variables
+		becomes zero, do not perform.
+	*/
+  int nFoundDependVars;
+  float averageFoundDependVars;
+
+  int nPrevEliminatedFwd;
+  int linearComputeRange;
+
+  boolean lazySiftFlag;
+};
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [This structure contains the information about a particular
+               cluster.]
+
+  Description [Corresponding to each cluster one ctrInfoStruct is created, The
+               various fields of this structure contain the information for
+               ordering the clusters for image computation
+               purposes. "varItemList" is the linked list of "varItemStruct"
+               corresponding to all the support variables of the cluster.]
+
+******************************************************************************/
+struct CtrInfoStruct {
+  int ctrId; /* Unique id of the cluster */
+  int numLocalSmoothVars; /*
+			   * Number of smooth variables in the support of the
+			   * cluster which can be quantified out if the cluster
+			   * is multiplied in the current product.
+			   */
+  int numSmoothVars; /* Number of smooth variables in the support */
+  int numIntroducedVars; /*
+			  * Number of range variables introduced if the cluster
+			  * is multiplied in the current product.
+			  */
+  int maxSmoothVarIndex; /* Max. index of a smooth variable in the support */
+  int rankMaxSmoothVarIndex; /* Rank of maximum index amongst all ctr's */
+  lsList varItemList; /* List of varItemStruct of the support variables */
+  lsHandle ctrInfoListHandle; /*
+			       * Handle to the list of info struct of ctr's
+			       * which are yet to be ordered.
+			       */
+};
+
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [This structure contains information about a particular variable
+               (domain, range or quantify).]
+
+  Description [Corresponding to each variable a structure is created. Like the
+               varItemList field of ctrInfoStruct, ctrItemList contains the
+               list of ctrInfoStruct corresponding to various clusters which
+               depend on this variable.]
+
+******************************************************************************/
+
+struct VarInfoStruct {
+  int bddId;  /* BDD id of the variable */
+  int numCtr; /* Number of components which depend on this variable. */
+  int varType; /* Domain, range or quantify variable ?*/
+  lsList ctrItemList; /* List of ctrItemStruct corresponding to the clusters
+			 that depend on it */
+};
+
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [This structure is the wrapper around a particular variable which
+               is in the support of a particular cluster.]
+
+  Description [Every cluster has a linked list of varItemStruct's. Each of
+               these structs is a wrapper around varInfo. The "ctrItemStruct"
+               corresponding to the cluster itself is present in ctrItemList,
+               the linked list of varInfo. "ctrItemHandle" is the handle to
+               the ctrItemStruct in "ctrItemList" of varInfo.]
+
+******************************************************************************/
+struct VarItemStruct {
+  VarInfo_t *varInfo; /* The pointer to the corresponding variable info
+		       * structure */
+  lsHandle ctrItemHandle; /*
+			   * The list handle to the ctrItemStruct
+			   * corresponding to the ctrInfo (the one which
+			   * contains this varItem in the varItemList) in the
+			   * ctrItemList field of the varInfo.
+			   */
+};
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [This structure is the wrapper around a particular ctr which
+               depend on a particular variable.]
+
+  Description [Every variable has a linked list of ctrItemStruct's. Each of
+               these structs is a wrapper around ctrInfo. The "varItemStruct"
+               corresponding to the variable itself is present in varItemList,
+               the linked list of ctrInfo. "varItemHandle" is the handle to
+               the varItemStruct in "varItemList" of ctrInfo.]
+
+******************************************************************************/
+struct CtrItemStruct {
+  CtrInfo_t *ctrInfo;     /* Pointer to the corresponding cluster
+			   * info structure. */
+  lsHandle varItemHandle; /*
+			   * The list handle to the varItemStruct
+			   * corresponding to the varInfo (the one which
+			   * contains this ctrItem in the ctrItemList) in the
+			   * varItemList field of the ctrInfo.
+			   */
+};
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+static	double	*signatures;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void ResetClusteredCofactoredRelationArray(mdd_manager *mddManager, Iwls95Info_t *info);
+static void FreeClusteredCofactoredRelationArray(Iwls95Info_t *info);
+static ImgTrmOption_t * TrmGetOptions(void);
+static void CreateBitRelationArray(Iwls95Info_t *info, ImgFunctionData_t *functionData);
+static void FreeBitRelationArray(Iwls95Info_t *info);
+static void OrderClusterOrder(mdd_manager *mddManager, array_t *relationArray, array_t *fromVarBddArray, array_t *toVarBddArray, array_t *quantifyVarBddArray, array_t **orderedClusteredRelationArrayPtr, array_t **smoothVarBddArrayPtr, ImgTrmOption_t *option, boolean freeRelationArray);
+static array_t * CreateClusters(bdd_manager *bddManager, array_t *relationArray, ImgTrmOption_t *option);
+static void OrderRelationArray(mdd_manager *mddManager, array_t *relationArray, array_t *domainVarBddArray, array_t *quantifyVarBddArray, array_t *rangeVarBddArray, ImgTrmOption_t *option, array_t **orderedRelationArrayPtr, array_t **arraySmoothVarBddArrayPtr);
+static array_t * RelationArraySmoothLocalVars(array_t *relationArray, array_t *ctrInfoArray, array_t *varInfoArray, st_table *bddIdToBddTable);
+static void OrderRelationArrayAux(array_t *relationArray, lsList remainingCtrInfoList, array_t *ctrInfoArray, array_t *varInfoArray, int *sortedMaxIndexVector, int numSmoothVarsRemaining, int numIntroducedVarsRemaining, st_table *bddIdToBddTable, ImgTrmOption_t *option, array_t *domainAndQuantifyVarBddArray, array_t **orderedRelationArrayPtr, array_t **arraySmoothVarBddArrayPtr, array_t *arrayDomainQuantifyVarsWithZeroNumCtr);
+static array_t * UpdateInfoArrays(CtrInfo_t *ctrInfo, st_table *bddIdToBddTable, int *numSmoothVarsRemainingPtr, int *numIntroducedVarsRemainingPtr);
+static float CalculateBenefit(CtrInfo_t *ctrInfo, int maxNumLocalSmoothVars, int maxNumSmoothVars, int maxIndex, int maxNumIntroducedVars, ImgTrmOption_t *option);
+static void PrintOption(Img_MethodType method, ImgTrmOption_t *option, FILE *fp);
+static Iwls95Info_t * Iwls95InfoStructAlloc(Img_MethodType method);
+static CtrInfo_t * CtrInfoStructAlloc(void);
+static void CtrInfoStructFree(CtrInfo_t *ctrInfo);
+static VarInfo_t * VarInfoStructAlloc(void);
+static void VarInfoStructFree(VarInfo_t *varInfo);
+static void CtrItemStructFree(CtrItem_t *ctrItem);
+static void VarItemStructFree(VarItem_t *varItem);
+static int CtrInfoMaxIndexCompare(const void * p1, const void * p2);
+static void PrintCtrInfoStruct(CtrInfo_t *ctrInfo);
+static void PrintVarInfoStruct(VarInfo_t *varInfo);
+static int CheckQuantificationSchedule(array_t *relationArray, array_t *arraySmoothVarBddArray);
+static int CheckCtrInfoArray(array_t *ctrInfoArray, int numDomainVars, int numQuantifyVars, int numRangeVars);
+static int CheckCtrInfo(CtrInfo_t *ctrInfo, int numDomainVars, int numQuantifyVars, int numRangeVars);
+static int CheckVarInfoArray(array_t *varInfoArray, int numRelation);
+static array_t * BddArrayDup(array_t *bddArray);
+static array_t * BddArrayArrayDup(array_t *bddArray);
+static mdd_t * BddLinearAndSmooth(mdd_manager *mddManager, bdd_t *fromSet, array_t *relationArray, array_t *arraySmoothVarBddArray, array_t *smoothVarCubeArray, int verbosity, ImgPartialImageOption_t *PIoption, boolean *partial, boolean lazySiftFlag);
+static void HashIdToBddTable(st_table *table, array_t *idArray, array_t *bddArray);
+static void PrintSmoothIntroducedCount(array_t *clusterArray, array_t **arraySmoothVarBddArrayPtr, array_t *psBddIdArray, array_t *nsBddIdArray);
+static void PrintBddIdFromBddArray(array_t *bddArray);
+static void PrintBddIdTable(st_table *idTable);
+static void PartitionTraverseRecursively(mdd_manager *mddManager, vertex_t *vertex, int mddId, st_table *vertexTable, array_t *relationArray, st_table *domainQuantifyVarMddIdTable, array_t *quantifyVarMddIdArray);
+static void PrintPartitionRecursively(vertex_t *vertex, st_table *vertexTable, int indent);
+static bdd_t * RecomputeImageIfNecessary(ImgFunctionData_t *functionData, mdd_manager *mddManager, bdd_t *domainSubset, array_t *relationArray, array_t *arraySmoothVarBddArray, array_t *smoothVarCubeArray, int verbosity, ImgPartialImageOption_t *PIoption, array_t *toCareSetArray, boolean *partial, boolean lazySiftFlag);
+static bdd_t * ComputeSubsetOfIntermediateProduct(bdd_t *product, ImgPartialImageOption_t *PIoption);
+static bdd_t * ComputeClippedAndAbstract(bdd_t *product, bdd_t *relation, array_t *smoothVarBddArray, int nvars, int clippingDepth, boolean *partial, int verbosity);
+static array_t * CopyArrayBddArray(array_t *arrayBddArray);
+static void PrintPartitionedTransitionRelation(mdd_manager *mddManager, Iwls95Info_t *info, Img_DirectionType directionType);
+static void ReorderPartitionedTransitionRelation(Iwls95Info_t *info, ImgFunctionData_t *functionData, Img_DirectionType directionType);
+static void UpdateQuantificationSchedule(Iwls95Info_t *info, ImgFunctionData_t *functionData, Img_DirectionType directionType);
+static array_t * MakeSmoothVarCubeArray(mdd_manager *mddManager, array_t *arraySmoothVarBddArray);
+static mdd_t * TrmEliminateDependVars(Img_ImageInfo_t *imageInfo, array_t *relationArray, mdd_t *states, mdd_t **dependRelations);
+static int TrmSignatureCompare(int *ptrX, int *ptrY);
+static void SetupLazySifting(mdd_manager *mddManager, array_t *bddRelationArray, array_t *domainVarBddArray, array_t *quantifyVarBddArray, array_t *rangeVarBddArray, int verbosity);
+static int MddSizeCompare(const void *ptr1, const void *ptr2);
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the result after existentially quantifying a
+  set of variables after taking the product of the array of relations.]
+
+  Description ["relationArray" is an array of mdd's which need to be
+  multiplied and the variables in the "smoothVarMddIdArray" need to
+  be quantified out from the product. "introducedVarMddIdArray" is the
+  array of mddIds of the variables (other than the variables to be
+  quantified out) in the support of the relations. This array is used
+  to compute the product order such that the number of new variables
+  introduced in the product is minimized. However passing an empty
+  array or an array of mddIds of partial support will not result in any
+  error (some optimality will be lost though). The computation consists of 2
+  phases. In phase 1, an ordering of the relations and a schedule of
+  quantifying variables is found (based on IWLS95) heuristic. In phase
+  2, the relations are multiplied in order and the quantifying
+  variables are quantified according to the schedule.]
+
+  SideEffects [None]
+
+******************************************************************************/
+mdd_t*
+Img_MultiwayLinearAndSmooth(mdd_manager *mddManager, array_t *relationArray,
+			    array_t *smoothVarMddIdArray,
+			    array_t *introducedVarMddIdArray,
+			    Img_MethodType method,
+			    Img_DirectionType direction)
+{
+  mdd_t *product;
+  array_t *smoothVarBddArray = mdd_id_array_to_bdd_array(mddManager,
+						      smoothVarMddIdArray);
+  array_t *introducedVarBddArray = mdd_id_array_to_bdd_array(mddManager,
+						   introducedVarMddIdArray);
+
+  product = ImgMultiwayLinearAndSmooth(mddManager, relationArray,
+			smoothVarBddArray, introducedVarBddArray,
+			method, direction, NIL(ImgTrmOption_t));
+
+  mdd_array_free(introducedVarBddArray);
+  mdd_array_free(smoothVarBddArray);
+  return product;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints info of the partitioned transition relation.]
+
+  Description [Prints info of the partitioned transition relation.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Img_PrintPartitionedTransitionRelation(mdd_manager *mddManager,
+					Img_ImageInfo_t *imageInfo,
+					Img_DirectionType directionType)
+{
+  Iwls95Info_t *info = (Iwls95Info_t *) imageInfo->methodData;
+
+  if (imageInfo->methodType != Img_Iwls95_c &&
+      imageInfo->methodType != Img_Mlp_c &&
+      imageInfo->methodType != Img_Linear_c)
+    return;
+
+  PrintPartitionedTransitionRelation(mddManager, info, directionType);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorder partitioned transition relation.]
+
+  Description [Reorder partitioned transition relation.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Img_ReorderPartitionedTransitionRelation(Img_ImageInfo_t *imageInfo,
+					 Img_DirectionType directionType)
+{
+  if (imageInfo->methodType != Img_Iwls95_c &&
+      imageInfo->methodType != Img_Mlp_c &&
+      imageInfo->methodType != Img_Linear_c)
+    return;
+
+  ReorderPartitionedTransitionRelation((Iwls95Info_t *)imageInfo->methodData,
+					&(imageInfo->functionData),
+					directionType);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Updates quantification schedule.]
+
+  Description [Updates quantification schedule.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Img_UpdateQuantificationSchedule(Img_ImageInfo_t *imageInfo,
+				 Img_DirectionType directionType)
+{
+  if (imageInfo->methodType != Img_Iwls95_c)
+    return;
+
+  UpdateQuantificationSchedule((Iwls95Info_t *)imageInfo->methodData,
+				&(imageInfo->functionData), directionType);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Clusters relation array and returns quantification schedule.]
+
+  Description [Clusters relation array and returns quantification schedule.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Img_ClusterRelationArray(mdd_manager *mddManager,
+			Img_MethodType method,
+			Img_DirectionType direction,
+			array_t *relationArray,
+			array_t *domainVarMddIdArray,
+			array_t *rangeVarMddIdArray,
+			array_t *quantifyVarMddIdArray,
+			array_t **clusteredRelationArray,
+			array_t **arraySmoothVarBddArray,
+			array_t **smoothVarCubeArray,
+			boolean freeRelationArray)
+{
+  array_t *domainVarBddArray;
+  array_t *quantifyVarBddArray;
+  array_t *rangeVarBddArray;
+  ImgTrmOption_t *option;
+
+  option = TrmGetOptions();
+  domainVarBddArray = mdd_id_array_to_bdd_array(mddManager,
+						domainVarMddIdArray);
+  rangeVarBddArray = mdd_id_array_to_bdd_array(mddManager,
+						rangeVarMddIdArray);
+  quantifyVarBddArray = mdd_id_array_to_bdd_array(mddManager,
+						  quantifyVarMddIdArray);
+
+  *clusteredRelationArray = ImgClusterRelationArray(mddManager,
+						    NIL(ImgFunctionData_t),
+						    method,
+						    direction,
+						    option,
+						    relationArray,
+						    domainVarBddArray,
+						    quantifyVarBddArray,
+						    rangeVarBddArray,
+						    arraySmoothVarBddArray,
+						    smoothVarCubeArray,
+						    freeRelationArray);
+  
+  ImgFreeTrmOptions(option);
+  mdd_array_free(domainVarBddArray);
+  mdd_array_free(rangeVarBddArray);
+  mdd_array_free(quantifyVarBddArray);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the result after existentially quantifying a
+  set of variables after taking the product of the array of relations.]
+
+  Description ["relationArray" is an array of mdd's which need to be
+  multiplied and the variables in the "smoothVarBddArray" need to
+  be quantified out from the product. "introducedVarBddArray" is the
+  array of the bdd variables (other than the variables to be
+  quantified out) in the support of the relations. This array is used
+  to compute the product order such that the number of new variables
+  introduced in the product is minimized. However passing an empty
+  array or an array of mddIds of partial support will not result in any
+  error (some optimality will be lost though). The computation consists of 2
+  phases. In phase 1, an ordering of the relations and a schedule of
+  quantifying variables is found (based on IWLS95) heuristic. In phase
+  2, the relations are multiplied in order and the quantifying
+  variables are quantified according to the schedule.]
+
+  SideEffects [None]
+
+******************************************************************************/
+mdd_t*
+ImgMultiwayLinearAndSmooth(mdd_manager *mddManager,
+			   array_t *relationArray,
+			   array_t *smoothVarBddArray,
+			   array_t *introducedVarBddArray,
+			   Img_MethodType method,
+			   Img_DirectionType direction,
+			   ImgTrmOption_t *option)
+{
+  mdd_t *product;
+  array_t *domainVarBddArray = array_alloc(bdd_t*, 0);
+
+  product = ImgMultiwayLinearAndSmoothWithFrom(mddManager, relationArray,
+						NIL(mdd_t),
+						smoothVarBddArray,
+						domainVarBddArray,
+						introducedVarBddArray,
+						method, direction, option);
+
+  array_free(domainVarBddArray);
+  return product;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the result after existentially quantifying a
+  set of variables after taking the product of the array of relations.]
+
+  Description ["relationArray" is an array of mdd's which need to be
+  multiplied and the variables in the "smoothVarBddArray" need to
+  be quantified out from the product. "introducedVarBddArray" is the
+  array of the bdd variables (other than the variables to be
+  quantified out) in the support of the relations. This array is used
+  to compute the product order such that the number of new variables
+  introduced in the product is minimized. However passing an empty
+  array or an array of mddIds of partial support will not result in any
+  error (some optimality will be lost though). The computation consists of 2
+  phases. In phase 1, an ordering of the relations and a schedule of
+  quantifying variables is found (based on IWLS95) heuristic. In phase
+  2, the relations are multiplied in order and the quantifying
+  variables are quantified according to the schedule. If "from" is not nil,
+  we first order "relationArray" and make quantification schedule, then
+  we multiply with "from". In this case, "domainVarBddArray" should contain
+  the state variables to be quantified out. If "from" is nil, then
+  "domainVarBddArray" should be an empty array.]
+
+  SideEffects [None]
+
+******************************************************************************/
+mdd_t*
+ImgMultiwayLinearAndSmoothWithFrom(mdd_manager *mddManager,
+				   array_t *relationArray,
+				   mdd_t *from,
+				   array_t *smoothVarBddArray,
+				   array_t *domainVarBddArray,
+				   array_t *introducedVarBddArray,
+				   Img_MethodType method,
+				   Img_DirectionType direction,
+				   ImgTrmOption_t *option)
+{
+  mdd_t *product;
+  boolean partial = FALSE;
+  array_t *orderedRelationArray = NIL(array_t);
+  array_t *arraySmoothVarBddArray = NIL(array_t);
+  int freeOptionFlag;
+  int lazySiftFlag = bdd_is_lazy_sift(mddManager);
+
+  if (!option) {
+    option = TrmGetOptions();
+    freeOptionFlag = 1;
+  } else
+    freeOptionFlag = 0;
+
+  if (method == Img_Iwls95_c) {
+    OrderRelationArray(mddManager, relationArray, domainVarBddArray,
+			smoothVarBddArray, introducedVarBddArray, option,
+			&orderedRelationArray, &arraySmoothVarBddArray);
+  } else if (method == Img_Mlp_c) {
+    if (direction == Img_Forward_c) {
+      /*
+      * domainVarBddArray : PS
+      * introducedVarBddArray : NS
+      */
+      if (option->mlpMultiway && from == NIL(mdd_t)) {
+	product = ImgMlpMultiwayAndSmooth(mddManager, NIL(ImgFunctionData_t),
+					  relationArray, domainVarBddArray,
+					  smoothVarBddArray,
+					  introducedVarBddArray, direction,
+					  option);
+	array_free(domainVarBddArray);
+	if (freeOptionFlag)
+	  ImgFreeTrmOptions(option);
+	return product;
+      } else {
+	ImgMlpOrderRelationArray(mddManager, relationArray, domainVarBddArray,
+				 smoothVarBddArray, introducedVarBddArray,
+				 direction, &orderedRelationArray,
+				 &arraySmoothVarBddArray, option);
+      }
+    } else { /* direction == Img_Backward_c */
+      /*
+      * domainVarBddArray : NS
+      * introducedVarBddArray : PS
+      */
+      if (option->mlpPreSwapStateVars) {
+	if (option->mlpMultiway && from == NIL(mdd_t)) {
+	  product = ImgMlpMultiwayAndSmooth(mddManager, NIL(ImgFunctionData_t),
+					    relationArray,
+					    domainVarBddArray,
+					    smoothVarBddArray,
+					    introducedVarBddArray,
+					    Img_Forward_c, option);
+	  array_free(domainVarBddArray);
+	  if (freeOptionFlag)
+	    ImgFreeTrmOptions(option);
+	  return product;
+	} else {
+	  ImgMlpOrderRelationArray(mddManager, relationArray,
+				   domainVarBddArray, smoothVarBddArray,
+				   introducedVarBddArray,
+				   Img_Forward_c, &orderedRelationArray,
+				   &arraySmoothVarBddArray, option);
+	}
+      } else {
+	if (option->mlpMultiway && from == NIL(mdd_t)) {
+	  product = ImgMlpMultiwayAndSmooth(mddManager, NIL(ImgFunctionData_t),
+					    relationArray, domainVarBddArray,
+					    smoothVarBddArray,
+					    introducedVarBddArray,
+					    Img_Backward_c, option);
+	  array_free(domainVarBddArray);
+	  if (freeOptionFlag)
+	    ImgFreeTrmOptions(option);
+	  return product;
+	} else {
+	  ImgMlpOrderRelationArray(mddManager, relationArray,
+				   domainVarBddArray, smoothVarBddArray,
+				   introducedVarBddArray,
+				   Img_Backward_c, &orderedRelationArray,
+				   &arraySmoothVarBddArray, option);
+	}
+      }
+    }
+  } else
+    assert(0);
+
+  product = BddLinearAndSmooth(mddManager, from,
+			       orderedRelationArray,
+			       arraySmoothVarBddArray,
+			       NIL(array_t),
+			       option->verbosity,
+			       NULL, &partial, lazySiftFlag);
+
+  if (freeOptionFlag) 
+    ImgFreeTrmOptions(option);
+  mdd_array_free(orderedRelationArray);
+  mdd_array_array_free(arraySmoothVarBddArray);
+  return product;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns a BDD after taking the product of fromSet with the
+  BDDs in the relationArray and quantifying out the variables using
+  the schedule given in the arraySmoothVarBddArray.]
+
+  Description [The product is taken from the left, i.e., fromSet is
+  multiplied with relationArray[0]. The array of variables given by
+  arraySmoothVarBddArray[i] are quantified when the relationArray[i]
+  is multiplied in the product.]
+
+  SideEffects [None]
+
+******************************************************************************/
+mdd_t*
+ImgBddLinearAndSmooth(mdd_manager *mddManager,
+			mdd_t *from,
+			array_t *relationArray,
+			array_t *arraySmoothVarBddArray,
+			array_t *smoothVarCubeArray,
+			int verbosity)
+{
+  mdd_t *product;
+  boolean partial = FALSE;
+  int lazySiftFlag = bdd_is_lazy_sift(mddManager);
+
+  product = BddLinearAndSmooth(mddManager, from,
+			       relationArray,
+			       arraySmoothVarBddArray,
+			       smoothVarCubeArray,
+			       verbosity,
+			       NULL, &partial, lazySiftFlag);
+
+  return product;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Clusters relation array and makes quantification schedule.]
+
+  Description [Orders and clusters relation array and makes quantification
+  schedule. (Order/Cluster/Order.)]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+ImgClusterRelationArray(mdd_manager *mddManager,
+			ImgFunctionData_t *functionData,
+			Img_MethodType method,
+			Img_DirectionType direction,
+			ImgTrmOption_t *option,
+			array_t *relationArray,
+			array_t *domainVarBddArray,
+			array_t *quantifyVarBddArray,
+			array_t *rangeVarBddArray,
+			array_t **arraySmoothVarBddArray,
+			array_t **smoothVarCubeArray,
+			boolean freeRelationArray)
+{
+  array_t	*orderedRelationArray;
+  array_t	*clusteredRelationArray;
+  int		freeOptionFlag;
+  long		initialTime, finalTime;
+
+  if (!option) {
+    option = TrmGetOptions();
+    freeOptionFlag = 1;
+  } else
+    freeOptionFlag = 0;
+
+  if (option->verbosity >= 2)
+    initialTime = util_cpu_time();
+  else /* to remove uninitialized variables warning */
+    initialTime = 0;
+
+  if (method == Img_Iwls95_c) {
+    assert(direction != Img_Both_c);
+    if (direction == Img_Forward_c) {
+      OrderClusterOrder(mddManager, relationArray, domainVarBddArray,
+			rangeVarBddArray, quantifyVarBddArray,
+			&orderedRelationArray, arraySmoothVarBddArray,
+			option, freeRelationArray);
+    } else {
+      assert(direction == Img_Backward_c);
+      OrderClusterOrder(mddManager, relationArray, rangeVarBddArray,
+			domainVarBddArray, quantifyVarBddArray,
+			&orderedRelationArray, arraySmoothVarBddArray,
+			option, freeRelationArray);
+
+    }
+    if (freeOptionFlag)
+      ImgFreeTrmOptions(option);
+
+    if (smoothVarCubeArray) {
+      if (functionData->createVarCubesFlag) {
+	*smoothVarCubeArray = MakeSmoothVarCubeArray(mddManager,
+						   *arraySmoothVarBddArray);
+      } else
+	*smoothVarCubeArray = NIL(array_t);
+    }
+    if (option->verbosity >= 2) {
+      finalTime = util_cpu_time();
+      fprintf(vis_stdout, "time for clustering with IWLS95 = %10g\n",
+	      (double)(finalTime - initialTime) / 1000.0);
+    }
+    return(orderedRelationArray);
+  } else if (method == Img_Mlp_c) {
+    if ((direction == Img_Forward_c && option->mlpReorder == 2) ||
+	(direction == Img_Backward_c && option->mlpPreReorder == 2)) {
+      if (direction == Img_Forward_c)
+	option->mlpReorder = 0;
+      else
+	option->mlpPreReorder = 0;
+      ImgMlpClusterRelationArray(mddManager, functionData, relationArray,
+		domainVarBddArray, quantifyVarBddArray, rangeVarBddArray,
+		direction, &clusteredRelationArray, NIL(array_t *), option);
+      if (direction == Img_Forward_c)
+	option->mlpReorder = 2;
+      else
+	option->mlpPreReorder = 2;
+      ImgMlpOrderRelationArray(mddManager, clusteredRelationArray,
+		domainVarBddArray, quantifyVarBddArray, rangeVarBddArray,
+		direction, &orderedRelationArray, arraySmoothVarBddArray,
+		option);
+      mdd_array_free(clusteredRelationArray);
+    } else if ((direction == Img_Forward_c && option->mlpReorder == 3) ||
+	       (direction == Img_Backward_c && option->mlpPreReorder == 3)) {
+      if (direction == Img_Forward_c)
+	option->mlpReorder = 0;
+      else
+	option->mlpPreReorder = 0;
+      ImgMlpClusterRelationArray(mddManager, functionData, relationArray,
+		domainVarBddArray, quantifyVarBddArray, rangeVarBddArray,
+		direction, &clusteredRelationArray, NIL(array_t *), option);
+      if (direction == Img_Forward_c)
+	option->mlpReorder = 3;
+      else
+	option->mlpPreReorder = 3;
+      OrderRelationArray(mddManager, clusteredRelationArray,
+		domainVarBddArray, quantifyVarBddArray,
+		rangeVarBddArray, option,
+		&orderedRelationArray, arraySmoothVarBddArray);
+      mdd_array_free(clusteredRelationArray);
+    } else {
+      ImgMlpClusterRelationArray(mddManager, functionData, relationArray,
+		domainVarBddArray, quantifyVarBddArray, rangeVarBddArray,
+		direction, &orderedRelationArray, arraySmoothVarBddArray,
+		option);
+    }
+    if (freeOptionFlag)
+      ImgFreeTrmOptions(option);
+    if (smoothVarCubeArray) {
+      if (functionData->createVarCubesFlag) {
+	*smoothVarCubeArray = MakeSmoothVarCubeArray(mddManager,
+						   *arraySmoothVarBddArray);
+      } else
+	*smoothVarCubeArray = NIL(array_t);
+    }
+    if (option->verbosity >= 2) {
+      finalTime = util_cpu_time();
+      fprintf(vis_stdout, "time for clustering with MLP = %10g\n",
+		(double)(finalTime - initialTime) / 1000.0);
+    }
+    return(orderedRelationArray);
+  } else
+    assert(0);
+  return NIL(array_t); /* we should never get here */
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns quantification schedule for a given relation array.]
+
+  Description [Returns quantification schedule for a given relation array.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+ImgGetQuantificationSchedule(mdd_manager *mddManager,
+				ImgFunctionData_t *functionData,
+				Img_MethodType method,
+				Img_DirectionType direction,
+				ImgTrmOption_t *option,
+				array_t *relationArray,
+				array_t *smoothVarBddArray,
+				array_t *domainVarBddArray,
+				array_t *introducedVarBddArray,
+				boolean withClustering,
+				array_t **orderedRelationArrayPtr)
+{
+  array_t *orderedRelationArray = NIL(array_t);
+  array_t *clusteredRelationArray;
+  array_t *arraySmoothVarBddArray = NIL(array_t);
+  int freeOptionFlag;
+
+  if (!option) {
+    option = TrmGetOptions();
+    freeOptionFlag = 1;
+  } else
+    freeOptionFlag = 0;
+
+  if (method == Img_Iwls95_c) {
+    if (withClustering) {
+      OrderRelationArray(mddManager, relationArray, domainVarBddArray,
+			smoothVarBddArray, introducedVarBddArray, option,
+			&orderedRelationArray, NIL(array_t *));
+
+      clusteredRelationArray = CreateClusters(mddManager, orderedRelationArray,
+						option);
+      mdd_array_free(orderedRelationArray);
+
+      OrderRelationArray(mddManager, clusteredRelationArray, domainVarBddArray,
+			smoothVarBddArray, introducedVarBddArray, option,
+			&orderedRelationArray, &arraySmoothVarBddArray);
+      mdd_array_free(clusteredRelationArray);
+    } else {
+      OrderRelationArray(mddManager, relationArray, domainVarBddArray,
+			smoothVarBddArray, introducedVarBddArray, option,
+			&orderedRelationArray, &arraySmoothVarBddArray);
+    }
+  } else if (method == Img_Mlp_c) {
+    if (withClustering) {
+      ImgMlpClusterRelationArray(mddManager, functionData, relationArray,
+		domainVarBddArray, smoothVarBddArray, introducedVarBddArray,
+		direction, &orderedRelationArray, &arraySmoothVarBddArray,
+		option);
+    } else {
+      ImgMlpOrderRelationArray(mddManager, relationArray, domainVarBddArray,
+			smoothVarBddArray, introducedVarBddArray, direction,
+			&orderedRelationArray, &arraySmoothVarBddArray,
+			option);
+    }
+  } else
+    assert(0);
+
+  if (freeOptionFlag)
+    ImgFreeTrmOptions(option);
+  if (orderedRelationArrayPtr)
+    *orderedRelationArrayPtr = orderedRelationArray;
+  else
+    mdd_array_free(orderedRelationArray);
+  return(arraySmoothVarBddArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates an option structure for transition relation method.]
+
+  Description [Allocates an option structure for transition relation method.]
+
+  SideEffects []
+
+******************************************************************************/
+ImgTrmOption_t *
+ImgGetTrmOptions(void)
+{
+  ImgTrmOption_t	*option;
+
+  option = TrmGetOptions();
+  return(option);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the option structure for transition relation method.]
+
+  Description [Frees the option structure for transition relation method.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgFreeTrmOptions(ImgTrmOption_t *option)
+{
+  if (option->readCluster)
+    FREE(option->readCluster);
+  if (option->writeCluster)
+    FREE(option->writeCluster);
+  if (option->writeDepMatrix)
+    FREE(option->writeDepMatrix);
+  FREE(option);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Turn off option to apply linear based image computation by comsidering range of state variables]
+
+  Description [ Turn off option to apply linear based image computation by comsidering range of state variables.]
+
+  SideEffects []
+
+  SeeAlso [ImgImageInfoFreeIwls95]
+******************************************************************************/
+
+void 
+ImgResetMethodDataLinearComputeRange(void *methodData)
+{
+  Iwls95Info_t *info = (Iwls95Info_t *) methodData;
+  info->linearComputeRange = 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Turn on option to apply linear based image computation by comsidering range of state variables]
+
+  Description [ Turn on option to apply linear based image computation by comsidering range of state variables.]
+
+  SideEffects []
+
+  SeeAlso []
+******************************************************************************/
+void 
+ImgSetMethodDataLinearComputeRange(void *methodData)
+{
+  Iwls95Info_t *info = (Iwls95Info_t *) methodData;
+  info->linearComputeRange = 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Get unreachable states]
+
+  Description [Return unreachable states]
+
+  SideEffects []
+
+  SeeAlso []
+******************************************************************************/
+mdd_t *
+Img_ImageGetUnreachableStates(Img_ImageInfo_t * imageInfo)
+{
+  array_t *relationArray;
+  mdd_t *states;
+  Iwls95Info_t *info = (Iwls95Info_t *) imageInfo->methodData;
+
+  relationArray = info->fwdOptClusteredRelationArray;
+  states = array_fetch(mdd_t *, relationArray, 0);
+  states = ImgSubstitute(states, &(imageInfo->functionData), Img_R2D_c);
+  return(states);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes an image data structure for image
+  computation using the Iwls95 technique.]
+
+  Description [This process consists of following steps.
+  1. The transition functions are built.
+  2. An array of bit level relations are built using the function
+  mdd_fn_array_to_bdd_rel_array.
+  3. The relations are clustered using the threshold value.
+  4. The clustered relations are ordered.]
+
+  SideEffects []
+
+  SeeAlso [ImgImageInfoFreeIwls95]
+******************************************************************************/
+
+
+void *
+ImgImageInfoInitializeIwls95(void *methodData,
+			     ImgFunctionData_t *functionData,
+                             Img_DirectionType directionType,
+			     Img_MethodType method)
+{
+  array_t *fwdClusteredRelationArray;
+  array_t *bwdClusteredRelationArray;
+  Iwls95Info_t *info = (Iwls95Info_t *) methodData;
+  Ntk_Network_t *network;
+  Ntk_Node_t *node;
+  char *flagValue;
+  int i, mddId ;
+
+  if (info &&
+      (((info->fwdClusteredRelationArray) &&
+	(info->bwdClusteredRelationArray)) ||
+       ((directionType == Img_Forward_c) &&
+	(info->fwdClusteredRelationArray)) ||
+       ((directionType == Img_Backward_c) &&
+	(info->bwdClusteredRelationArray)))) {
+    /* Nothing needs to be done. Return */
+    return (void *) info;
+  }
+  else{
+    array_t *rangeVarBddArray, *domainVarBddArray, *quantifyVarBddArray;
+    array_t *newQuantifyVarMddIdArray;
+    array_t *clusteredRelationArray;
+    FILE *fin, *fout;
+    array_t *bddRelationArray, *quantifyVarMddIdArray;
+    mdd_manager *mddManager = Part_PartitionReadMddManager(functionData->mddNetwork);
+
+    if (info == NIL(Iwls95Info_t)) {
+      info = Iwls95InfoStructAlloc(method);
+    }
+    CreateBitRelationArray(info, functionData);
+
+    /** if FAFWFlag then remove PI from quantifyVarMddIdArray **/
+    bddRelationArray = info->bitRelationArray;
+    quantifyVarMddIdArray = info->quantifyVarMddIdArray;
+    if(functionData->FAFWFlag) {
+      network = functionData->network;
+      newQuantifyVarMddIdArray = array_alloc(int, 0);
+      for(i=0; i<array_n(quantifyVarMddIdArray); i++) {
+	mddId = array_fetch(int, quantifyVarMddIdArray, i);
+	node = Ntk_NetworkFindNodeByMddId(network, mddId);
+	if(!Ntk_NodeTestIsInput(node)) {
+	  array_insert_last(int, newQuantifyVarMddIdArray, mddId);
+	}
+      }
+      array_free(quantifyVarMddIdArray);
+      quantifyVarMddIdArray = newQuantifyVarMddIdArray;
+      info->quantifyVarMddIdArray = newQuantifyVarMddIdArray;
+    }
+
+    info->bitRelationArray = NIL(array_t);
+    info->quantifyVarMddIdArray = NIL(array_t);
+
+    rangeVarBddArray = functionData->rangeBddVars;
+    domainVarBddArray = functionData->domainBddVars;
+    quantifyVarBddArray = mdd_id_array_to_bdd_array(mddManager,
+						    quantifyVarMddIdArray);
+
+    array_free(quantifyVarMddIdArray);
+
+    if (((directionType == Img_Forward_c) ||
+	 (directionType == Img_Both_c)) &&
+	(info->fwdClusteredRelationArray == NIL(array_t))) {
+      if (info->option->readCluster) {
+	if (info->option->readReorderCluster) {
+	  fin = fopen(info->option->readCluster, "r");
+	  ImgMlpReadClusterFile(fin, mddManager,
+			  functionData, bddRelationArray,
+			  domainVarBddArray, rangeVarBddArray,
+			  quantifyVarBddArray, Img_Forward_c,
+			  &clusteredRelationArray, NIL(array_t *),
+			  info->option);
+	  fclose(fin);
+	  if (method == Img_Iwls95_c) {
+	    OrderRelationArray(mddManager, clusteredRelationArray,
+			  domainVarBddArray, quantifyVarBddArray,
+			  rangeVarBddArray, info->option,
+			  &info->fwdClusteredRelationArray,
+			  &info->fwdArraySmoothVarBddArray);
+	  } else if (method == Img_Mlp_c) {
+	    ImgMlpOrderRelationArray(mddManager, clusteredRelationArray,
+			  domainVarBddArray, quantifyVarBddArray,
+			  rangeVarBddArray, Img_Forward_c,
+			  &info->fwdClusteredRelationArray,
+			  &info->fwdArraySmoothVarBddArray,
+			  info->option);
+	  } else
+	    assert(0);
+	  mdd_array_free(clusteredRelationArray);
+	} else {
+	  fin = fopen(info->option->readCluster, "r");
+	  ImgMlpReadClusterFile(fin, mddManager,
+			  functionData, bddRelationArray,
+			  domainVarBddArray, rangeVarBddArray,
+			  quantifyVarBddArray, Img_Forward_c,
+			  &info->fwdClusteredRelationArray,
+			  &info->fwdArraySmoothVarBddArray,
+			  info->option);
+	  fclose(fin);
+	}
+      } else if (method == Img_Iwls95_c) {
+	/*
+	 * Since clusters are formed by multiplying the latches starting
+	 * from one end we need to order the latches using some heuristics
+	 * first. Right now, we order the latches using the same heuristic
+	 * as the one used for ordering the clusters for early quantifiction.
+	 * However, since we are not interested in the quantification
+	 * schedule at this stage, we will pass a NIL(array_t*) as the last
+	 * argument.
+	 */
+        OrderClusterOrder(mddManager, bddRelationArray, domainVarBddArray,
+			  rangeVarBddArray, quantifyVarBddArray,
+			  &info->fwdClusteredRelationArray,
+			  &info->fwdArraySmoothVarBddArray,
+			  info->option, 0);
+      } else if (method == Img_Mlp_c) {
+	if (info->option->mlpReorder == 2) {
+	  info->option->mlpReorder = 0;
+	  ImgMlpClusterRelationArray(mddManager, functionData,
+			bddRelationArray, domainVarBddArray,
+			quantifyVarBddArray, rangeVarBddArray,
+			Img_Forward_c, &clusteredRelationArray,
+			NIL(array_t *), info->option);
+	  info->option->mlpReorder = 2;
+	  ImgMlpOrderRelationArray(mddManager, clusteredRelationArray,
+			domainVarBddArray, quantifyVarBddArray,
+			rangeVarBddArray, Img_Forward_c,
+			&info->fwdClusteredRelationArray,
+			&info->fwdArraySmoothVarBddArray, info->option);
+	  mdd_array_free(clusteredRelationArray);
+	} else if (info->option->mlpReorder == 3) {
+	  info->option->mlpReorder = 0;
+	  ImgMlpClusterRelationArray(mddManager, functionData,
+			bddRelationArray, domainVarBddArray,
+			quantifyVarBddArray, rangeVarBddArray,
+			Img_Forward_c, &clusteredRelationArray,
+			NIL(array_t *), info->option);
+	  info->option->mlpReorder = 3;
+	  OrderRelationArray(mddManager, clusteredRelationArray,
+			domainVarBddArray, quantifyVarBddArray,
+			rangeVarBddArray, info->option,
+			&info->fwdClusteredRelationArray,
+			&info->fwdArraySmoothVarBddArray);
+	  mdd_array_free(clusteredRelationArray);
+	} else {
+	  ImgMlpClusterRelationArray(mddManager, functionData,
+			bddRelationArray, domainVarBddArray,
+			quantifyVarBddArray, rangeVarBddArray,
+			Img_Forward_c, &info->fwdClusteredRelationArray,
+			&info->fwdArraySmoothVarBddArray, info->option);
+	}
+      } else if (method == Img_Linear_c || method == Img_Linear_Range_c) {
+	  if(method == Img_Linear_Range_c) {
+	    info->option->linearComputeRange = 1;
+	    method = Img_Linear_c;
+	  }
+	  ImgLinearClusterRelationArray(mddManager, functionData,
+			bddRelationArray, 
+			Img_Forward_c, 
+			&info->fwdClusteredRelationArray,
+			&info->fwdArraySmoothVarBddArray, 
+			&info->fwdOptClusteredRelationArray,
+			&info->fwdOptArraySmoothVarBddArray, 
+			info->option);
+      } else
+	assert(0);
+
+      if (info->option->verbosity > 2) 
+	PrintPartitionedTransitionRelation(mddManager, info, Img_Forward_c);
+      if(method == Img_Linear_c)
+        ImgPrintPartitionedTransitionRelation(mddManager,
+		info->fwdOptClusteredRelationArray , 
+		info->fwdOptArraySmoothVarBddArray);
+
+      if (info->option->printDepMatrix || info->option->writeDepMatrix) {
+	if (info->option->writeDepMatrix) {
+	  fout = fopen(info->option->writeDepMatrix, "w");
+	  if (!fout) {
+	    fprintf(vis_stderr, "** img error: can't open file [%s]\n",
+	  	    info->option->writeDepMatrix);
+	  }
+	} else
+	  fout = NIL(FILE);
+	ImgMlpPrintDependenceMatrix(mddManager,
+		info->fwdClusteredRelationArray,
+		domainVarBddArray, quantifyVarBddArray, rangeVarBddArray,
+		Img_Forward_c, info->option->printDepMatrix, fout,
+		info->option);
+	if (fout)
+	  fclose(fout);
+      }
+      if (info->option->writeCluster) {
+	fout = fopen(info->option->writeCluster, "w");
+	ImgMlpWriteClusterFile(fout, mddManager, 
+		info->fwdClusteredRelationArray,
+		domainVarBddArray, rangeVarBddArray);
+	fclose(fout);
+      }
+
+      if (functionData->createVarCubesFlag && info->fwdArraySmoothVarBddArray) 
+	info->fwdSmoothVarCubeArray = MakeSmoothVarCubeArray(mddManager,
+					info->fwdArraySmoothVarBddArray);
+      else
+	info->fwdSmoothVarCubeArray = NIL(array_t);
+
+      if (functionData->createVarCubesFlag && info->fwdOptArraySmoothVarBddArray) 
+	info->fwdOptSmoothVarCubeArray = MakeSmoothVarCubeArray(mddManager,
+					info->fwdOptArraySmoothVarBddArray);
+      else
+	info->fwdOptSmoothVarCubeArray = NIL(array_t);
+
+#ifndef NDEBUG
+      if(info->fwdClusteredRelationArray)
+        assert(CheckQuantificationSchedule(info->fwdClusteredRelationArray,
+					 info->fwdArraySmoothVarBddArray));
+      if(info->fwdOptClusteredRelationArray)
+        assert(CheckQuantificationSchedule(info->fwdOptClusteredRelationArray,
+					 info->fwdOptArraySmoothVarBddArray));
+#endif
+    }
+
+    if (((directionType == Img_Backward_c) ||
+	 (directionType == Img_Both_c)) &&
+	(info->bwdClusteredRelationArray == NIL(array_t))) {
+      if (info->option->readCluster) {
+	if (info->option->readReorderCluster) {
+	  fin = fopen(info->option->readCluster, "r");
+	  ImgMlpReadClusterFile(fin, mddManager,
+			  functionData, bddRelationArray,
+			  domainVarBddArray, rangeVarBddArray,
+			  quantifyVarBddArray, Img_Backward_c,
+			  &clusteredRelationArray, NIL(array_t *),
+			  info->option);
+	  fclose(fin);
+	  if (method == Img_Iwls95_c) {
+	    OrderRelationArray(mddManager, clusteredRelationArray,
+			  rangeVarBddArray, quantifyVarBddArray,
+			  domainVarBddArray, info->option,
+			  &info->bwdClusteredRelationArray,
+			  &info->bwdArraySmoothVarBddArray);
+	  } else if (method == Img_Mlp_c) {
+	    ImgMlpOrderRelationArray(mddManager, clusteredRelationArray,
+			  domainVarBddArray, quantifyVarBddArray,
+			  rangeVarBddArray, Img_Backward_c,
+			  &info->bwdClusteredRelationArray,
+			  &info->bwdArraySmoothVarBddArray,
+			  info->option);
+	  } else
+	    assert(0);
+	  mdd_array_free(clusteredRelationArray);
+	} else {
+	  fin = fopen(info->option->readCluster, "r");
+	  ImgMlpReadClusterFile(fin, mddManager,
+			  functionData, bddRelationArray,
+			  domainVarBddArray, rangeVarBddArray,
+			  quantifyVarBddArray, Img_Backward_c,
+			  &info->bwdClusteredRelationArray,
+			  &info->bwdArraySmoothVarBddArray,
+			  info->option);
+	  fclose(fin);
+	}
+      } else if (method == Img_Iwls95_c) {
+	/*
+	 * Since clusters are formed by multiplying the latches starting
+	 * from one end we need to order the latches using some heuristics
+	 * first. Right now, we order the latches using the same heuristic
+	 * as the one used for ordering the clusters for early quantifiction.
+	 * However, since we are not interested in the quantification
+	 * schedule at this stage, we will pass a NIL(array_t*) as the last
+	 * argument.
+	 */
+        OrderClusterOrder(mddManager, bddRelationArray, rangeVarBddArray,
+			  domainVarBddArray, quantifyVarBddArray,
+			  &info->bwdClusteredRelationArray,
+			  &info->bwdArraySmoothVarBddArray,
+			  info->option, 0);
+      } else if (method == Img_Mlp_c) {
+	if (info->option->mlpPreReorder == 2) {
+	  info->option->mlpPreReorder = 0;
+	  ImgMlpClusterRelationArray(mddManager, functionData,
+			bddRelationArray, domainVarBddArray,
+			quantifyVarBddArray, rangeVarBddArray,
+			Img_Backward_c, &clusteredRelationArray,
+			NIL(array_t *), info->option);
+	  info->option->mlpPreReorder = 2;
+	  ImgMlpOrderRelationArray(mddManager, clusteredRelationArray,
+			domainVarBddArray, quantifyVarBddArray,
+			rangeVarBddArray, Img_Backward_c,
+			&info->bwdClusteredRelationArray,
+			&info->bwdArraySmoothVarBddArray, info->option);
+	  mdd_array_free(clusteredRelationArray);
+	} else if (info->option->mlpPreReorder == 3) {
+	  info->option->mlpPreReorder = 0;
+	  ImgMlpClusterRelationArray(mddManager, functionData,
+			bddRelationArray, domainVarBddArray,
+			quantifyVarBddArray, rangeVarBddArray,
+			Img_Backward_c, &clusteredRelationArray,
+			NIL(array_t *), info->option);
+	  info->option->mlpPreReorder = 3;
+	  OrderRelationArray(mddManager, clusteredRelationArray,
+			domainVarBddArray, quantifyVarBddArray,
+			rangeVarBddArray, info->option,
+			&info->bwdClusteredRelationArray,
+			&info->bwdArraySmoothVarBddArray);
+	  mdd_array_free(clusteredRelationArray);
+	} else {
+	  ImgMlpClusterRelationArray(mddManager, functionData,
+			bddRelationArray, domainVarBddArray,
+			quantifyVarBddArray, rangeVarBddArray,
+			Img_Backward_c, &info->bwdClusteredRelationArray,
+			&info->bwdArraySmoothVarBddArray, info->option);
+	}
+      } else
+	assert(0);
+      
+      info->careSetArray = NIL(array_t);
+      info->bwdClusteredCofactoredRelationArray = NIL(array_t);
+      
+      if (info->option->verbosity > 2) 
+	PrintPartitionedTransitionRelation(mddManager, info, Img_Backward_c);
+
+      if (info->option->printDepMatrix || info->option->writeDepMatrix) {
+	if (info->option->writeDepMatrix) {
+	  fout = fopen(info->option->writeDepMatrix, "w");
+	  if (!fout) {
+	    fprintf(vis_stderr, "** img error: can't open file [%s]\n",
+	  	    info->option->writeDepMatrix);
+	  }
+	} else
+	  fout = NIL(FILE);
+	ImgMlpPrintDependenceMatrix(mddManager,
+		info->bwdClusteredRelationArray,
+		domainVarBddArray, quantifyVarBddArray, rangeVarBddArray,
+		Img_Backward_c, info->option->printDepMatrix, fout,
+		info->option);
+      
+	if (fout)
+	  fclose(fout);
+      }
+      if (info->option->writeCluster) {
+	fout = fopen(info->option->writeCluster, "w");
+	ImgMlpWriteClusterFile(fout, mddManager, 
+		info->bwdClusteredRelationArray,
+		domainVarBddArray, rangeVarBddArray);
+	fclose(fout);
+      }
+
+      if (functionData->createVarCubesFlag)
+        info->bwdSmoothVarCubeArray = MakeSmoothVarCubeArray(mddManager,
+					info->bwdArraySmoothVarBddArray);
+      else
+	info->bwdSmoothVarCubeArray = NIL(array_t);
+
+#ifndef NDEBUG
+      assert(CheckQuantificationSchedule(info->bwdClusteredRelationArray,
+					 info->bwdArraySmoothVarBddArray));
+#endif
+    }
+
+    
+    info->lazySiftFlag = bdd_is_lazy_sift(mddManager);
+    if (info->lazySiftFlag) {
+      SetupLazySifting(mddManager, bddRelationArray, domainVarBddArray,
+		       quantifyVarBddArray, rangeVarBddArray,
+		       info->option->verbosity);
+    }
+    
+    /* Free the bddRelationArray */
+    mdd_array_free(bddRelationArray);
+    
+    if ((info->option)->verbosity > 0) {
+      fwdClusteredRelationArray = info->fwdClusteredRelationArray;
+      bwdClusteredRelationArray = info->bwdClusteredRelationArray;
+      if (method == Img_Iwls95_c)
+	fprintf(vis_stdout,"Computing Image Using IWLS95 technique.\n");
+      else if (method == Img_Mlp_c)
+	fprintf(vis_stdout,"Computing Image Using MLP technique.\n");
+      else if (method == Img_Linear_c) {
+	fprintf(vis_stdout,"Computing Image Using LINEAR technique.\n");
+        fwdClusteredRelationArray = info->fwdOptClusteredRelationArray;
+        /*bwdClusteredRelationArray = info->bwdOptClusteredRelationArray;*/
+      }
+      else
+	assert(0);
+      fprintf(vis_stdout,"Total # of domain binary variables = %3d\n",
+	      array_n(domainVarBddArray));
+      fprintf(vis_stdout,"Total # of range binary variables = %3d\n",
+	      array_n(rangeVarBddArray));
+      fprintf(vis_stdout,"Total # of quantify binary variables = %3d\n",
+	      array_n(quantifyVarBddArray));
+      if ((directionType == Img_Forward_c) || (directionType ==
+					       Img_Both_c)) {
+	fprintf(vis_stdout, "Shared size of transition relation for forward image computation is %10ld BDD nodes (%-4d components)\n",
+		bdd_size_multiple(fwdClusteredRelationArray),
+		array_n(fwdClusteredRelationArray));
+      }
+      if ((directionType == Img_Backward_c) || (directionType == Img_Both_c)) {
+	fprintf(vis_stdout, "Shared size of transition relation for backward image computation is %10ld BDD nodes (%-4d components)\n",
+		bdd_size_multiple(bwdClusteredRelationArray),
+		array_n(bwdClusteredRelationArray));
+      }
+    }
+    
+    /* Update nvars field in partial image options structure with
+       total number of variables. */
+    if (info->PIoption != NULL) {
+      (info->PIoption)->nvars = array_n(domainVarBddArray) +
+	array_n(quantifyVarBddArray) +
+	array_n(rangeVarBddArray);
+    }
+    /* Free the Bdd arrays */
+    mdd_array_free(quantifyVarBddArray);
+    
+    flagValue = Cmd_FlagReadByName("image_eliminate_depend_vars");
+    if (flagValue == NIL(char))
+      info->eliminateDepend = 0; /* the default value */
+    else
+      info->eliminateDepend = atoi(flagValue);
+    if (info->eliminateDepend && bdd_get_package_name() != CUDD) {
+      fprintf(vis_stderr,
+"** trm error : image_eliminate_depend_vars is available for only CUDD.\n");
+      info->eliminateDepend = 0;
+    }
+    info->nPrevEliminatedFwd = -1;
+    
+    return (void *)info;
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the forward image of a set of states.]
+
+  Description [Computes the forward image of a set of states. If
+  partial image requested and the first image computed doesn't
+  intersect toCareSet, then recompute image. ASSUME that toCareSet is
+  in terms of functionData->domainVars.]
+
+  SideEffects [ IMPORTANT NOTE: image may be in terms of domain
+  variables even when the reverse is expected IF partial images are
+  allowed. The clean way would be to convert toCareset in terms of
+  functionData->rangeVars but it may end up being quite inefficient.]
+
+  SeeAlso     [ImgImageInfoComputeFwdWithDomainVarsIwls95]
+
+******************************************************************************/
+mdd_t *
+ImgImageInfoComputeFwdIwls95(ImgFunctionData_t *functionData,
+                             Img_ImageInfo_t *imageInfo,
+                             mdd_t *fromLowerBound,
+                             mdd_t *fromUpperBound,
+                             array_t *toCareSetArray)
+{
+  mdd_t *image, *domainSubset, *newFrom;
+  mdd_manager *mddManager;
+  boolean partial;
+  Iwls95Info_t *info = (Iwls95Info_t *)imageInfo->methodData;
+  int eliminateDepend;
+  Img_OptimizeType optDir;
+  array_t *fwdOriClusteredRelationArray;
+  array_t *fwdOriArraySmoothVarBddArray;
+  array_t *fwdOriSmoothVarCubeArray;
+  array_t *fwdClusteredRelationArray;
+  Relation_t *head;
+  int bOptimize;
+  boolean farSideImageIsEnabled;
+  char    *userSpecifiedMethod;
+
+  mddManager = Part_PartitionReadMddManager(functionData->mddNetwork);
+
+  if(imageInfo->methodType == Img_Linear_c) {
+    if(info->fwdClusteredRelationArray == 0 || 
+       imageInfo->useOptimizedRelationFlag) {
+      fwdOriClusteredRelationArray = info->fwdOptClusteredRelationArray;
+      fwdOriArraySmoothVarBddArray = info->fwdOptArraySmoothVarBddArray;
+      fwdOriSmoothVarCubeArray = info->fwdOptSmoothVarCubeArray;
+    }
+    else {
+      fwdOriClusteredRelationArray = info->fwdClusteredRelationArray;
+      fwdOriArraySmoothVarBddArray = info->fwdArraySmoothVarBddArray;
+      fwdOriSmoothVarCubeArray = info->fwdSmoothVarCubeArray;
+    }
+  }
+  else {
+    fwdOriClusteredRelationArray = info->fwdClusteredRelationArray;
+    fwdOriArraySmoothVarBddArray = info->fwdArraySmoothVarBddArray;
+    fwdOriSmoothVarCubeArray = info->fwdSmoothVarCubeArray;
+  }
+
+  if (fwdOriClusteredRelationArray == NIL(array_t)) {
+    fprintf(vis_stderr, "** img error: The data structure has not been ");
+    fprintf(vis_stderr, "initialized for forward image computation\n");
+    return NIL(mdd_t);
+  }
+
+  if (info->eliminateDepend == 1 ||
+      (info->eliminateDepend == 2 && info->nPrevEliminatedFwd > 0)) {
+    eliminateDepend = 1;
+  } else
+    eliminateDepend = 0;
+
+  domainSubset = bdd_between(fromLowerBound, fromUpperBound);
+
+  if (eliminateDepend) {
+    fwdClusteredRelationArray = mdd_array_duplicate(fwdOriClusteredRelationArray);
+    newFrom = TrmEliminateDependVars(imageInfo, fwdClusteredRelationArray,
+				     domainSubset, NIL(mdd_t *));
+    mdd_free(domainSubset);
+    domainSubset = newFrom;
+  } else
+    fwdClusteredRelationArray = fwdOriClusteredRelationArray;
+
+  /* Record if partial images are allowed. */
+  partial = info->allowPartialImage;
+  info->wasPartialImage = FALSE;
+
+  /* bias field is used to bias the intermediate results towards care states */
+  if ((info->PIoption)->partialImageApproxMethod == BDD_APPROX_BIASED_RUA) {
+    /* assume that this array has only one mdd */
+    mdd_t *toCareSet = array_fetch(mdd_t *, toCareSetArray, 0);
+    (info->PIoption)->bias = mdd_dup(toCareSet);
+  }
+
+  /* when the "compositional far side image approach" is selected, and
+   * there are more than one transition relation clusters,
+   * over-approximate images (w.r.t individual TR clusters) will be
+   * used to minimize the transition relation.
+   */
+  farSideImageIsEnabled = FALSE;
+  userSpecifiedMethod = Cmd_FlagReadByName("image_farside_method");
+  if (userSpecifiedMethod != NIL(char)) {
+    if (!strcmp(userSpecifiedMethod, "1")) 
+      farSideImageIsEnabled = TRUE;
+  }
+
+  if (!farSideImageIsEnabled || array_n(fwdClusteredRelationArray) < 2) {
+
+    image = BddLinearAndSmooth(mddManager, domainSubset,
+			       fwdClusteredRelationArray,
+			       fwdOriArraySmoothVarBddArray,
+			       fwdOriSmoothVarCubeArray,
+			       (info->option)->verbosity,
+			       info->PIoption, &partial, info->lazySiftFlag);
+
+  }else {
+
+    array_t  *fwdFarArraySmoothVarBddArray = fwdOriArraySmoothVarBddArray;
+    array_t  *fwdFarSmoothVarCubeArray      = fwdOriSmoothVarCubeArray;
+    array_t  *fwdFarClusteredRelationArray = mdd_array_duplicate(fwdClusteredRelationArray);
+    array_t  *upperBoundImages = array_alloc(mdd_t *, 0);
+    st_table *domainSupportVarTable, *trClusterSupportVarTable;
+    mdd_t    *trCluster, *newDomainset, *newTRcluster, *upperBoundImage;
+    mdd_t    *holdMdd, *tmpMdd;
+    array_t  *tempArray;
+    int      beforeSize, afterSize, middleSize;
+    int      size1, size2, size3;
+    boolean  flag1, flag2;
+    int      i,j, k;
+    long     bddId;
+
+    /* compute a series of over-approximate images based on individual
+     * TR clusters
+     */
+    domainSupportVarTable = st_init_table(st_ptrcmp, st_ptrhash);
+    tempArray = mdd_get_bdd_support_ids(mddManager, domainSubset);
+    arrayForEachItem(int, tempArray, j, bddId) {
+      st_insert(domainSupportVarTable, (char *)bddId, (char *)0);
+    }
+    array_free(tempArray);
+
+    beforeSize = afterSize = middleSize =0;
+    arrayForEachItem(mdd_t *, fwdFarClusteredRelationArray, i, trCluster) {
+      array_t *preQuantifiedVarsInDomainset = array_alloc(mdd_t *, 0);
+      array_t *preQuantifiedVarsInTRcluster = array_alloc(mdd_t *, 0);
+      array_t *quantifiedVarsInProduct = array_alloc(mdd_t *, 0);
+
+      /* some variables can be quantified before taking the conjunction */
+      trClusterSupportVarTable = st_init_table(st_ptrcmp, st_ptrhash);
+      tempArray = mdd_get_bdd_support_ids(mddManager, trCluster);
+      arrayForEachItem(int, tempArray, j, bddId) {
+	st_insert(trClusterSupportVarTable, (char *)bddId, (char *)0);
+      }
+      array_free(tempArray);
+      arrayForEachItem(array_t *, fwdFarArraySmoothVarBddArray, j, tempArray) {
+	arrayForEachItem(mdd_t *, tempArray, k, holdMdd) {
+	  bddId = (int)bdd_top_var_id(holdMdd);
+	  flag1 = st_is_member(domainSupportVarTable, (char *)bddId);
+	  flag2 = st_is_member(trClusterSupportVarTable, (char *)bddId);
+	  if (flag1 && flag2)
+	    array_insert_last(mdd_t *, quantifiedVarsInProduct, holdMdd);
+	  else if (flag1)
+	    array_insert_last(mdd_t *, preQuantifiedVarsInDomainset, holdMdd);
+	  else if (flag2)
+	    array_insert_last(mdd_t *, preQuantifiedVarsInTRcluster, holdMdd);
+	  else 
+	    ;
+	}
+      }
+      st_free_table(trClusterSupportVarTable);
+
+      if (array_n(preQuantifiedVarsInDomainset) == 0)
+	newDomainset = bdd_dup(domainSubset);
+      else
+	newDomainset = bdd_smooth(domainSubset, preQuantifiedVarsInDomainset);
+      array_free(preQuantifiedVarsInDomainset);
+
+      if (array_n(preQuantifiedVarsInTRcluster) == 0)
+	newTRcluster = bdd_dup(trCluster);
+      else
+	newTRcluster = bdd_smooth(trCluster, preQuantifiedVarsInTRcluster);
+      array_free(preQuantifiedVarsInTRcluster);
+
+      /* compute the over-approximated image */
+      if (array_n(quantifiedVarsInProduct) == 0)
+	upperBoundImage = bdd_and(newTRcluster, newDomainset, 1, 1);
+      else
+	upperBoundImage = bdd_and_smooth(newTRcluster, newDomainset, quantifiedVarsInProduct);
+      array_free(quantifiedVarsInProduct);
+      mdd_free(newTRcluster);
+      mdd_free(newDomainset);
+      
+      /* minimize the TR cluster with the new upper bound image */
+      newTRcluster = Img_MinimizeImage(trCluster, upperBoundImage, 
+				       Img_DefaultMinimizeMethod_c, TRUE);
+
+      size1 = mdd_size(trCluster);
+      beforeSize += size1;
+      size2 = mdd_size(upperBoundImage);
+      middleSize += size2;
+      size3 = mdd_size(newTRcluster);
+      afterSize += size3;
+      if (info->option->verbosity >= 3) {
+	fprintf(vis_stdout, "farSideImg: minimize TR cluster[%d]  %d |%d => %d\n", i, 
+		size1, size2, size3);
+      }
+      
+      if (mdd_equal(newTRcluster, trCluster)) {
+	mdd_free(newTRcluster);
+	mdd_free(upperBoundImage);
+      }else {
+	mdd_free(trCluster);
+	array_insert(mdd_t *, fwdFarClusteredRelationArray, i, newTRcluster);
+	array_insert_last(mdd_t *, upperBoundImages, upperBoundImage);
+      }
+    }
+    st_free_table(domainSupportVarTable);
+
+    if (info->option->verbosity >= 2) {
+      fprintf(vis_stdout, "farSideImg: minimize TR total  %d |%d => %d\n",
+	      beforeSize, middleSize, afterSize);
+    }
+    
+    /* compute the image with the simplified transition relation */
+    image = BddLinearAndSmooth(mddManager, domainSubset,
+			       fwdFarClusteredRelationArray,
+			       fwdFarArraySmoothVarBddArray,
+			       fwdFarSmoothVarCubeArray,
+			       (info->option)->verbosity,
+			       info->PIoption, &partial, info->lazySiftFlag);
+    mdd_array_free(fwdFarClusteredRelationArray);
+
+    /* for performance concerns, the following operations are carried
+     *  out in the domain space
+     */
+    arrayForEachItem(mdd_t *, upperBoundImages, i, holdMdd) { 
+      tmpMdd = ImgSubstitute(holdMdd, functionData, Img_R2D_c); 
+      mdd_free(holdMdd); 
+      array_insert(mdd_t *, upperBoundImages, i, tmpMdd); 
+    } 
+    holdMdd = image; 
+    image = ImgSubstitute(image, functionData,Img_R2D_c); 
+    mdd_free(holdMdd); 
+    
+    /* remove the "bad states" introduced by the TR cluster minimization */
+    beforeSize = mdd_size(image);
+    array_sort(upperBoundImages, MddSizeCompare);    
+    arrayForEachItem(mdd_t *, upperBoundImages, i, tmpMdd) {
+      size1 = mdd_size(image);
+      size2 = mdd_size(tmpMdd);
+      holdMdd = image;
+      image = mdd_and(image, tmpMdd, 1, 1);
+      mdd_free(tmpMdd);
+      mdd_free(holdMdd);
+      size3 = mdd_size(image);
+
+      if (info->option->verbosity >= 3) {
+	fprintf(vis_stdout, "farSideImg: clip image  %d | %d => %d\n",
+		size1, size2, size3);
+      }
+    }
+    array_free(upperBoundImages);
+    
+    if (info->option->verbosity >= 2) {
+      afterSize = mdd_size(image);
+      fprintf(vis_stdout, "farSideImg: clip image total  %d => %d \n",
+	      beforeSize, afterSize);
+    }
+
+  }
+
+
+  /* check that no partial image was computed if not allowed */
+  assert(!((!info->allowPartialImage) && partial));
+
+  /* if partial image computed, and if no new states, recompute
+   * image with relaxed parameters.
+   */
+  if (partial) {
+    if (bdd_leq_array(image, toCareSetArray, 1, 0)) {
+      mdd_free(image);
+      partial = info->allowPartialImage;
+      image = RecomputeImageIfNecessary(functionData,
+					mddManager,
+					domainSubset,
+					fwdClusteredRelationArray,
+					fwdOriArraySmoothVarBddArray,
+					fwdOriSmoothVarCubeArray,
+					(info->option)->verbosity,
+					info->PIoption,
+					toCareSetArray,
+					&partial, info->lazySiftFlag);
+    }
+  }
+
+  if(imageInfo->methodType == Img_Linear_c) {
+    if(imageInfo->useOptimizedRelationFlag) {
+      if(info->option->linearOptimize == Opt_NS ||
+         info->option->linearOptimize == Opt_Both)
+        optDir = Opt_Both;
+      else
+        optDir = Opt_CS;
+  
+      head = ImgLinearRelationInit(mddManager, fwdOriClusteredRelationArray, 
+	    functionData->domainBddVars, functionData->rangeBddVars, 
+	    functionData->quantifyBddVars, info->option);
+      bOptimize = ImgLinearOptimizeAll(head, optDir, 0);
+      if(bOptimize) {
+	ImgLinearRefineRelation(head);
+	if(info->fwdClusteredRelationArray == 0 && optDir == Opt_Both) {
+	  info->fwdClusteredRelationArray = fwdOriClusteredRelationArray;
+          info->fwdArraySmoothVarBddArray = 
+	           BddArrayArrayDup(fwdOriArraySmoothVarBddArray);
+	  info->fwdSmoothVarCubeArray = MakeSmoothVarCubeArray(mddManager,
+					info->fwdArraySmoothVarBddArray);
+	}
+	else {
+          mdd_array_free(fwdOriClusteredRelationArray);
+	}
+        fwdOriClusteredRelationArray = ImgLinearExtractRelationArrayT(head);
+        info->fwdOptClusteredRelationArray = fwdOriClusteredRelationArray;
+      }
+      ImgLinearRelationQuit(head);
+    }
+  }
+
+  /* free the bias function created. */
+  if ((info->PIoption)->partialImageApproxMethod == BDD_APPROX_BIASED_RUA) {
+    mdd_free((info->PIoption)->bias);
+    (info->PIoption)->bias = NIL(mdd_t);
+  }
+  /* indicate whether this image computation was partial or exact. */
+  info->wasPartialImage = partial;
+  info->allowPartialImage = FALSE;
+
+  if (eliminateDepend)
+    mdd_array_free(fwdClusteredRelationArray);
+  mdd_free(domainSubset);
+
+  return image;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the forward image of a set of states in terms
+  of domain variables.]
+
+  Description [First the forward image computation function is called
+  which returns an image on range vars. Later, variable substitution
+  is used to obtain image on domain vars.]
+
+  SideEffects []
+
+  SeeAlso     [ImgImageInfoComputeFwdIwls95]
+
+******************************************************************************/
+mdd_t *
+ImgImageInfoComputeFwdWithDomainVarsIwls95(ImgFunctionData_t *functionData,
+                                           Img_ImageInfo_t *imageInfo,
+                                           mdd_t *fromLowerBound,
+                                           mdd_t *fromUpperBound,
+                                           array_t *toCareSetArray)
+{
+  int i;
+  array_t *toCareSetArrayRV = NIL(array_t);
+  mdd_t *toCareSet, *toCareSetRV;
+  mdd_t *imageRV, *imageDV;
+  int useToCareSetFlag;
+  Iwls95Info_t *info = (Iwls95Info_t *)imageInfo->methodData;
+
+  if (toCareSetArray && info->allowPartialImage)
+    useToCareSetFlag = 1;
+  else
+    useToCareSetFlag = 0;
+
+  if (useToCareSetFlag) {
+    toCareSetArrayRV = array_alloc(mdd_t *, 0);
+    arrayForEachItem(bdd_t *, toCareSetArray, i, toCareSet) {
+      toCareSetRV = ImgSubstitute(toCareSet, functionData, Img_D2R_c);
+      array_insert(bdd_t *, toCareSetArrayRV, i, toCareSetRV);
+    }
+  }
+
+  imageRV = ImgImageInfoComputeFwdIwls95(functionData,
+					 imageInfo,
+					 fromLowerBound,
+					 fromUpperBound,
+					 toCareSetArrayRV);
+
+  imageDV = ImgSubstitute(imageRV, functionData, Img_R2D_c);
+  mdd_free(imageRV);
+  if (useToCareSetFlag)
+    mdd_array_free(toCareSetArrayRV);
+  return imageDV;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the backward image of domainSubset.]
+
+  Description [First bdd_cofactor is used to compute the simplified set of
+  states to compute the image of. Next, this simplified set is multiplied with
+  the relation arrays given in the bwdClusteredRelationArray in order and the
+  variables are quantified according to the schedule in
+  bwdArraySmoothVarBddArray.]
+
+  SideEffects []
+
+  SeeAlso     [ImgImageInfoComputeBwdWithDomainVarsIwls95]
+
+******************************************************************************/
+mdd_t *
+ImgImageInfoComputeBwdIwls95(ImgFunctionData_t *functionData,
+                             Img_ImageInfo_t *imageInfo,
+                             mdd_t *fromLowerBound,
+                             mdd_t *fromUpperBound,
+                             array_t *toCareSetArray)
+{
+  mdd_t *image, *domainSubset, *simplifiedImage;
+  mdd_manager *mddManager;
+  Iwls95Info_t *info = (Iwls95Info_t *)imageInfo->methodData;
+  boolean partial;
+  
+  if (info->bwdClusteredRelationArray == NIL(array_t)) {
+    fprintf(vis_stderr, "** img error: The data structure has not been ");
+    fprintf(vis_stderr, "initialized for backward image computation\n");
+    return NIL(mdd_t);
+  }
+  mddManager = Part_PartitionReadMddManager(functionData->mddNetwork);
+  domainSubset = bdd_between(fromLowerBound, fromUpperBound);
+
+  assert(mddManager != NIL(mdd_manager));
+
+  /* Check if we can use the stored simplified relations */
+  if (info->careSetArray == NIL(array_t) ||
+      !mdd_array_equal(info->careSetArray, toCareSetArray)){
+    FreeClusteredCofactoredRelationArray(info);
+    info->careSetArray = mdd_array_duplicate(toCareSetArray);
+    info->bwdClusteredCofactoredRelationArray =
+      ImgMinimizeImageArrayWithCareSetArray(info->bwdClusteredRelationArray,
+					    toCareSetArray,
+					    Img_DefaultMinimizeMethod_c, TRUE,
+					    (info->option->verbosity > 0),
+					    Img_Backward_c);
+  }
+
+  /* if the partial images are allowed, compute the care set (or its superset)
+   * so that partial products can be minimized with respect to it.
+   */
+  partial = info->allowPartialImage;
+  info->wasPartialImage = FALSE;
+
+  /* bias is used to bias the intermediate results towards care states */
+  if ((info->PIoption)->partialImageApproxMethod == BDD_APPROX_BIASED_RUA) {
+    /* assume that this array has only one mdd */
+    mdd_t *toCareSet = array_fetch(mdd_t *, toCareSetArray, 0);
+    (info->PIoption)->bias = mdd_dup(toCareSet);
+  }
+
+
+  image = BddLinearAndSmooth(mddManager, domainSubset,
+			     info->bwdClusteredCofactoredRelationArray,
+			     info->bwdArraySmoothVarBddArray,
+			     info->bwdSmoothVarCubeArray,
+			     (info->option)->verbosity,
+			     info->PIoption, &partial, info->lazySiftFlag);
+
+
+  /* check that no partial image was computed if not allowed */
+  assert(!((!info->allowPartialImage) && partial));
+
+  /* if partial image computed, and if no new states, recompute
+   * image with relaxed parameters.
+   */
+  if (partial && bdd_leq_array(image, toCareSetArray, 1, 0)) {
+    bdd_free(image);
+    partial = info->allowPartialImage;
+    image = RecomputeImageIfNecessary(functionData,
+				      mddManager,
+				      domainSubset,
+				      info->bwdClusteredRelationArray,
+				      info->bwdArraySmoothVarBddArray,
+				      info->bwdSmoothVarCubeArray,
+				      (info->option)->verbosity,
+				      info->PIoption,
+				      toCareSetArray,
+				      &partial, info->lazySiftFlag);
+  }
+
+  /* free the bias function created. */
+  if ((info->PIoption)->partialImageApproxMethod == BDD_APPROX_BIASED_RUA) {
+    mdd_free((info->PIoption)->bias);
+    (info->PIoption)->bias = NIL(mdd_t);
+  }
+  /* indicate whether this image computation was partial or exact. */
+  info->wasPartialImage = partial;
+  info->allowPartialImage = FALSE;
+
+  mdd_free(domainSubset);
+  simplifiedImage = bdd_minimize_array(image, toCareSetArray);
+  bdd_free(image);
+  return simplifiedImage;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the backward image of a set of states.]
+
+  Description [Identical to ImgImageInfoComputeBwdIwls95 except in the
+  fromLowerBound and fromUpperBound, domainVars are substituted by
+  rangeVars.]
+
+  SideEffects []
+
+  SeeAlso     [ImgImageInfoComputeBwdIwls95]
+
+******************************************************************************/
+mdd_t *
+ImgImageInfoComputeBwdWithDomainVarsIwls95(ImgFunctionData_t *functionData,
+					   Img_ImageInfo_t *imageInfo,
+					   mdd_t *fromLowerBound,
+					   mdd_t *fromUpperBound,
+					   array_t *toCareSetArray)
+{
+  mdd_t *fromLowerBoundRV;
+  mdd_t *fromUpperBoundRV;
+  mdd_t *image;
+
+  fromLowerBoundRV = ImgSubstitute(fromLowerBound, functionData, Img_D2R_c);
+  if (mdd_equal(fromLowerBound, fromUpperBound))
+    fromUpperBoundRV = fromLowerBoundRV;
+  else
+    fromUpperBoundRV = ImgSubstitute(fromUpperBound, functionData, Img_D2R_c);
+
+  image =  ImgImageInfoComputeBwdIwls95(functionData,
+					imageInfo,
+					fromLowerBoundRV,
+					fromUpperBoundRV,
+					toCareSetArray);
+
+  mdd_free(fromLowerBoundRV);
+  if (!mdd_equal(fromLowerBound, fromUpperBound))
+    mdd_free(fromUpperBoundRV);
+  return image;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the memory associated with imageInfo.]
+
+  Description [Frees the memory associated with imageInfo.]
+
+  SideEffects []
+
+  SeeAlso [ImgImageInfoInitializeIwls95]
+
+******************************************************************************/
+void
+ImgImageInfoFreeIwls95(void *methodData)
+{
+  Iwls95Info_t *info = (Iwls95Info_t *)methodData;
+
+  if (info == NIL(Iwls95Info_t)) {
+    fprintf(vis_stderr, "** img error: Trying to free the NULL image info\n");
+    return;
+  }
+  if (info->bitRelationArray != NIL(array_t)) {
+    mdd_array_free(info->bitRelationArray);
+  }
+  if (info->quantifyVarMddIdArray != NIL(array_t)) {
+    array_free(info->quantifyVarMddIdArray);
+  }
+  if (info->fwdOptClusteredRelationArray != NIL(array_t)) {
+    mdd_array_free(info->fwdOptClusteredRelationArray);
+    mdd_array_array_free(info->fwdOptArraySmoothVarBddArray);
+  }
+  if (info->fwdOptSmoothVarCubeArray)
+    mdd_array_free(info->fwdOptSmoothVarCubeArray);
+  if (info->fwdClusteredRelationArray != NIL(array_t)) {
+    mdd_array_free(info->fwdClusteredRelationArray);
+    mdd_array_array_free(info->fwdArraySmoothVarBddArray);
+  }
+  if (info->fwdSmoothVarCubeArray)
+    mdd_array_free(info->fwdSmoothVarCubeArray);
+  if (info->bwdClusteredRelationArray != NIL(array_t)) {
+    mdd_array_free(info->bwdClusteredRelationArray);
+    mdd_array_array_free(info->bwdArraySmoothVarBddArray);
+  }
+  if (info->bwdSmoothVarCubeArray)
+    mdd_array_free(info->bwdSmoothVarCubeArray);
+  FreeClusteredCofactoredRelationArray(info);
+  
+  if (info->option != NULL) ImgFreeTrmOptions(info->option);
+  if (info->PIoption != NULL) FREE(info->PIoption);
+
+  if (info->savedArraySmoothVarBddArray != NIL(array_t))
+    mdd_array_array_free(info->savedArraySmoothVarBddArray);
+  if (info->savedSmoothVarCubeArray != NIL(array_t))
+    mdd_array_free(info->savedSmoothVarCubeArray);
+
+  FREE(info);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Prints information about the IWLS95 method.]
+
+  Description [This function is used to obtain the information about
+  the parameters used to initialize the imageInfo. If the file pointer
+  argument is not NULL, the options are printed out. The shared size
+  of the transition relation is printed out on vis_stdout.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgImageInfoPrintMethodParamsIwls95(void *methodData, FILE *fp)
+{
+  Iwls95Info_t *info = (Iwls95Info_t *)methodData;
+  if (fp == NULL) return;
+  PrintOption(info->method, info->option, fp);
+  if (info->fwdClusteredRelationArray != NIL(array_t)) {
+    (void) fprintf(fp, "Shared size of transition relation for forward image computation is %10ld BDD nodes (%-4d components)\n",
+		   bdd_size_multiple(info->fwdClusteredRelationArray),
+		   array_n(info->fwdClusteredRelationArray));
+  }
+  if (info->bwdClusteredRelationArray != NIL(array_t)) {
+    (void) fprintf(fp, "Shared size of transition relation for backward image computation is %10ld BDD nodes (%-4d components)\n",
+		   bdd_size_multiple(info->bwdClusteredRelationArray),
+		   array_n(info->bwdClusteredRelationArray));
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the st_table containing the bdd id of the support
+  variables of the function.]
+
+  Description [Returns the st_table containing the bdd id of the support
+  variables of the function.]
+
+  SideEffects []
+
+******************************************************************************/
+st_table *
+ImgBddGetSupportIdTable(bdd_t *function)
+{
+  st_table *supportTable;
+  var_set_t *supportVarSet;
+  int i;
+
+  supportTable = st_init_table(st_numcmp, st_numhash);
+  supportVarSet = bdd_get_support(function);
+  for(i=0; i<supportVarSet->n_elts; i++) {
+    if (var_set_get_elt(supportVarSet, i) == 1) {
+      st_insert(supportTable, (char *)(long) i, NIL(char));
+    }
+  }
+  var_set_free(supportVarSet);
+  return supportTable;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Checks if the last image/preimage was partial.]
+
+  Description [Checks if the last image/preimage was partial. This
+  flag is valid only for the last image/preimage computation. Reset
+  before every image/preimage computation. ]
+
+  SideEffects [Reset before every image/preimage computation.]
+
+  SeeAlso     [ImgImageAllowPartialImageIwls95]
+
+******************************************************************************/
+boolean
+ImgImageWasPartialIwls95(void *methodData)
+{
+  Iwls95Info_t *info = (Iwls95Info_t *) methodData;
+  return (info->wasPartialImage);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the flag to allow partial images.]
+
+  Description [Sets the flag to allow partial images.  Default is to
+  not allow partial image computations. This flag is reset at the end
+  of every image/preimage computation i.e., has to be specified before
+  every image/preimage computation if partial image is desired. ]
+
+  SideEffects [Flag is reset at the end of every image/preimage
+  computation.]
+
+  SeeAlso     [ImgImageWasPartialIwls95]
+
+******************************************************************************/
+void
+ImgImageAllowPartialImageIwls95(void *methodData, boolean value)
+{
+  Iwls95Info_t *info = (Iwls95Info_t *) methodData;
+  info->allowPartialImage = value;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Restores original transition relation from saved.]
+
+  Description [Restores original transition relation from saved.]
+
+  SideEffects []
+
+  SeeAlso[ImgDuplicateTransitionRelationIwls95]
+******************************************************************************/
+void
+ImgRestoreTransitionRelationIwls95(Img_ImageInfo_t *imageInfo,
+	Img_DirectionType directionType)
+{
+  array_t *relationArray;
+  Iwls95Info_t *iwlsInfo = (Iwls95Info_t *) imageInfo->methodData;
+  ImgFunctionData_t *functionData = &(imageInfo->functionData);
+  mdd_manager *mgr = NIL(mdd_manager);
+  
+  mgr =  Part_PartitionReadMddManager(imageInfo->functionData.mddNetwork);
+  
+  if (directionType == Img_Both_c) {
+    fprintf(vis_stderr,
+	    "** img error : can't restore fwd and bwd at the same time.\n");
+    return;
+  }
+
+  relationArray = ImgGetTransitionRelationIwls95(iwlsInfo, directionType);
+  mdd_array_free(relationArray);
+  ImgUpdateTransitionRelationIwls95(iwlsInfo,
+				    (array_t *)imageInfo->savedRelation,
+				    directionType);
+  imageInfo->savedRelation = NIL(void);
+
+  assert(iwlsInfo->savedArraySmoothVarBddArray);
+  if (directionType == Img_Forward_c) {
+    mdd_array_array_free(iwlsInfo->fwdArraySmoothVarBddArray);
+    iwlsInfo->fwdArraySmoothVarBddArray = iwlsInfo->savedArraySmoothVarBddArray;
+    if (functionData->createVarCubesFlag) {
+      mdd_array_free(iwlsInfo->fwdSmoothVarCubeArray);
+      iwlsInfo->fwdSmoothVarCubeArray = iwlsInfo->savedSmoothVarCubeArray;
+    }
+  } else {
+    mdd_array_array_free(iwlsInfo->bwdArraySmoothVarBddArray);
+    iwlsInfo->bwdArraySmoothVarBddArray = iwlsInfo->savedArraySmoothVarBddArray;
+    if (functionData->createVarCubesFlag) {
+      mdd_array_free(iwlsInfo->bwdSmoothVarCubeArray);
+      iwlsInfo->bwdSmoothVarCubeArray = iwlsInfo->savedSmoothVarCubeArray;
+    }
+  }
+  iwlsInfo->savedArraySmoothVarBddArray = NIL(array_t);
+  iwlsInfo->savedSmoothVarCubeArray = NIL(array_t);
+
+  if(directionType == Img_Backward_c || directionType == Img_Both_c)
+    ResetClusteredCofactoredRelationArray(mgr, iwlsInfo);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Duplicates transition relation.]
+
+  Description [Duplicates transition relation. Assumes that the
+  Transition Relation is an array.]
+
+  SideEffects []
+
+  SeeAlso[ImgRestoreTransitionRelationIwls95]
+******************************************************************************/
+void
+ImgDuplicateTransitionRelationIwls95(Img_ImageInfo_t *imageInfo,
+				     Img_DirectionType directionType)
+{
+  array_t *relationArray, *copiedRelationArray;
+  Iwls95Info_t *iwlsInfo = (Iwls95Info_t *) imageInfo->methodData;
+  ImgFunctionData_t *functionData = &(imageInfo->functionData);
+
+  if (directionType == Img_Both_c) {
+    fprintf(vis_stderr,
+	    "** img error : can't duplicate fwd and bwd at the same time.\n");
+    return;
+  }
+
+  relationArray = ImgGetTransitionRelationIwls95(iwlsInfo, directionType);
+  copiedRelationArray = BddArrayDup(relationArray);
+  assert(!imageInfo->savedRelation);
+  imageInfo->savedRelation = (void *)relationArray;
+  ImgUpdateTransitionRelationIwls95(iwlsInfo,
+				    copiedRelationArray, directionType);
+
+  assert(!iwlsInfo->savedArraySmoothVarBddArray);
+  if (directionType == Img_Forward_c) {
+    iwlsInfo->savedArraySmoothVarBddArray = iwlsInfo->fwdArraySmoothVarBddArray;
+    iwlsInfo->fwdArraySmoothVarBddArray =
+      CopyArrayBddArray(iwlsInfo->savedArraySmoothVarBddArray);
+    if (functionData->createVarCubesFlag) {
+      iwlsInfo->savedSmoothVarCubeArray = iwlsInfo->fwdSmoothVarCubeArray;
+      iwlsInfo->fwdSmoothVarCubeArray =
+	BddArrayDup(iwlsInfo->savedSmoothVarCubeArray);
+    }
+  } else {
+    iwlsInfo->savedArraySmoothVarBddArray = iwlsInfo->bwdArraySmoothVarBddArray;
+    iwlsInfo->bwdArraySmoothVarBddArray =
+      CopyArrayBddArray(iwlsInfo->savedArraySmoothVarBddArray);
+    if (functionData->createVarCubesFlag) {
+      iwlsInfo->savedSmoothVarCubeArray = iwlsInfo->bwdSmoothVarCubeArray;
+      iwlsInfo->bwdSmoothVarCubeArray =
+	BddArrayDup(iwlsInfo->savedSmoothVarCubeArray);
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Minimizes transition relation with given set of constraints.]
+
+  Description [Minimizes transition relation with given set of
+  constraints. This invalidates the bwdclusteredcofactoredrelationarray.
+
+  <p>RB: Can Kavita or In-Ho please explain the difference between these four
+  related functions?? (other three in SeeAlso)
+
+  The constraint should be in terms of present-state and input variables only.
+
+  This function takes care that the quantification schedule is correct
+  afterwards.  If reorderClusters is true, the clusters are reordered after
+  minimization. 
+  ]
+
+  SideEffects []
+
+  SeeAlso [ImgMinimizeTransitionRelationIwls95,
+  ImgApproximateTransitionRelationIwls95, ImgAbstractTransitionRelationIwls95,
+  Img_MinimizeImage] 
+******************************************************************************/
+void
+ImgMinimizeTransitionRelationIwls95(
+  void *methodData,
+  ImgFunctionData_t  *functionData,
+  array_t *constrainArray,
+  Img_MinimizeType minimizeMethod,
+  Img_DirectionType directionType,
+  boolean reorderClusters,
+  int printStatus)
+{
+  Iwls95Info_t *info = (Iwls95Info_t *)methodData;
+
+  if (minimizeMethod == Img_DefaultMinimizeMethod_c)
+    minimizeMethod = Img_ReadMinimizeMethod();  
+  
+  if (directionType == Img_Forward_c || directionType == Img_Both_c) {
+    ImgMinimizeImageArrayWithCareSetArrayInSitu(
+      info->fwdClusteredRelationArray, constrainArray, minimizeMethod, TRUE,
+      (printStatus == 2), Img_Forward_c); 
+
+    if(reorderClusters)
+      ReorderPartitionedTransitionRelation(info, functionData,
+					   Img_Forward_c); 
+    else{
+      /* any minimization method other than restrict may introduce new
+	 variables, which invalidates the quantification schedule */
+      assert(minimizeMethod != Img_DefaultMinimizeMethod_c);
+      if(minimizeMethod != Img_Restrict_c)
+	UpdateQuantificationSchedule(info, functionData, Img_Forward_c);
+    }
+     assert(CheckQuantificationSchedule(info->fwdClusteredRelationArray,
+				     info->fwdArraySmoothVarBddArray));
+  }
+
+  if (directionType == Img_Backward_c || directionType == Img_Both_c) {
+    ImgMinimizeImageArrayWithCareSetArrayInSitu(
+      info->bwdClusteredRelationArray, constrainArray, minimizeMethod, TRUE,
+      (printStatus == 2), Img_Backward_c); 
+
+    if(reorderClusters)
+      ReorderPartitionedTransitionRelation(info, functionData,
+					   Img_Backward_c); 
+    /* Minimization can only introduce PS variables, which need not be
+       quantified out, hence no need to recompute quantification schedule
+       in backward case. */
+    assert(CheckQuantificationSchedule(info->bwdClusteredRelationArray,
+				       info->bwdArraySmoothVarBddArray))
+    }
+
+  if(directionType == Img_Backward_c || directionType == Img_Both_c)
+    FreeClusteredCofactoredRelationArray(info);
+  
+  return;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Abstracts out given variables from transition relation.]
+
+  Description [Abstracts out given variables from transition relation.
+  abstractVars should be an array of bdd variables.  This invalidates the
+  bwdclusteredcofactoredrelationarray. ]
+
+  SideEffects []
+  
+  SeeAlso [ImgMinimizeTransitionRelationIwls95,
+  ImgApproximateTransitionRelationIwls95, ImgAbstractTransitionRelationIwls95]
+
+******************************************************************************/
+void
+ImgAbstractTransitionRelationIwls95(Img_ImageInfo_t *imageInfo,
+	array_t *abstractVars, mdd_t *abstractCube,
+	Img_DirectionType directionType, int printStatus)
+{
+  Iwls95Info_t *info = (Iwls95Info_t *)imageInfo->methodData;
+  int i, fwd_size, bwd_size;
+  bdd_t *relation, *abstractedRelation;
+  
+  if (!abstractVars || array_n(abstractVars) == 0)
+    return;
+
+  fwd_size = bwd_size = 0;
+  if (printStatus) {
+    if (directionType == Img_Forward_c || directionType == Img_Both_c)
+      fwd_size = bdd_size_multiple(info->fwdClusteredRelationArray);
+    if (directionType == Img_Backward_c || directionType == Img_Both_c)
+      bwd_size = bdd_size_multiple(info->bwdClusteredRelationArray);
+  } 
+  if (directionType == Img_Forward_c || directionType == Img_Both_c) {
+    arrayForEachItem(bdd_t*, info->fwdClusteredRelationArray, i, relation) {
+      if (abstractCube)
+	abstractedRelation = bdd_smooth_with_cube(relation, abstractCube);
+      else
+	abstractedRelation = bdd_smooth(relation, abstractVars);
+      if (printStatus == 2) {
+        (void) fprintf(vis_stdout,
+	  "IMG Info: abstracted fwd relation %d => %d in component %d\n",
+			 bdd_size(relation), bdd_size(abstractedRelation), i);
+      }
+      mdd_free(relation);
+      array_insert(bdd_t*, info->fwdClusteredRelationArray, i,
+		   abstractedRelation);
+    }
+  }
+  if (directionType == Img_Backward_c || directionType == Img_Both_c) {
+    arrayForEachItem(bdd_t*, info->bwdClusteredRelationArray, i, relation) {
+      if (abstractCube)
+	abstractedRelation = bdd_smooth_with_cube(relation, abstractCube);
+      else
+	abstractedRelation = bdd_smooth(relation, abstractVars);
+      if (printStatus == 2) {
+        (void) fprintf(vis_stdout,
+	  "IMG Info: abstracted bwd relation %d => %d in component %d\n",
+			 bdd_size(relation), bdd_size(abstractedRelation), i);
+      }
+      mdd_free(relation);
+      array_insert(bdd_t*, info->bwdClusteredRelationArray, i,
+		   abstractedRelation);
+    }
+  }
+  if (printStatus) {
+    if (directionType == Img_Forward_c || directionType == Img_Both_c) {
+      (void) fprintf(vis_stdout,
+     "IMG Info: abstracted fwd relation [%d => %ld] with %d components\n",
+		     fwd_size,
+		     bdd_size_multiple(info->fwdClusteredRelationArray),
+		     array_n(info->fwdClusteredRelationArray));
+    }
+    if (directionType == Img_Backward_c || directionType == Img_Both_c) {
+      (void) fprintf(vis_stdout,
+     "IMG Info: abstracted bwd relation [%d => %ld] with %d components\n",
+		     bwd_size,
+		     bdd_size_multiple(info->bwdClusteredRelationArray),
+		     array_n(info->bwdClusteredRelationArray));
+    }
+  }
+
+  if(directionType == Img_Backward_c || directionType == Img_Both_c) 
+    FreeClusteredCofactoredRelationArray(info);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Approximate transition relation.]
+
+  Description [Approximate transition relation.  This invalidates the
+  bwdclusteredcofactoredrelationarray. ]
+
+  SideEffects [ImgMinimizeTransitionRelationIwls95,
+  ImgApproximateTransitionRelationIwls95, ImgAbstractTransitionRelationIwls95,
+  Img_ApproximateImage] 
+
+******************************************************************************/
+int
+ImgApproximateTransitionRelationIwls95(mdd_manager *mgr, void *methodData,
+		    bdd_approx_dir_t approxDir, bdd_approx_type_t approxMethod,
+		    int approxThreshold, double approxQuality,
+		    double approxQualityBias,
+		    Img_DirectionType directionType, mdd_t *bias)
+{
+  Iwls95Info_t *info = (Iwls95Info_t *)methodData;
+  int i;
+  bdd_t *relation, *approxRelation;
+  int	unchanged = 0;
+  
+  if (directionType == Img_Forward_c || directionType == Img_Both_c) {
+    arrayForEachItem(bdd_t*, info->fwdClusteredRelationArray, i, relation) {
+      approxRelation = Img_ApproximateImage(mgr, relation,
+					    approxDir, approxMethod,
+					    approxThreshold, approxQuality,
+					    approxQualityBias, bias);
+      if (bdd_is_tautology(approxRelation, 1)) {
+	fprintf(vis_stdout,
+		"** img warning : bdd_one from subsetting in fwd[%d].\n", i);
+	mdd_free(approxRelation);
+	unchanged++;
+      } else if (bdd_is_tautology(approxRelation, 0)) {
+	fprintf(vis_stdout,
+		"** img warning : bdd_zero from subsetting in fwd[%d].\n", i);
+	mdd_free(approxRelation);
+	unchanged++;
+      } else if (mdd_equal(approxRelation, relation)) {
+	mdd_free(approxRelation);
+	unchanged++;
+      } else {
+	mdd_free(relation);
+	array_insert(bdd_t*, info->fwdClusteredRelationArray, i,
+		     approxRelation);
+      }
+    }
+  }
+  if (directionType == Img_Backward_c || directionType == Img_Both_c) {
+    arrayForEachItem(bdd_t*, info->bwdClusteredRelationArray, i, relation) {
+      approxRelation = Img_ApproximateImage(mgr, relation,
+					    approxDir, approxMethod,
+					    approxThreshold, approxQuality,
+					    approxQualityBias, bias);
+      if (bdd_is_tautology(approxRelation, 1)) {
+	fprintf(vis_stdout,
+		"** img warning : bdd_one from subsetting in bwd[%d].\n", i);
+	mdd_free(approxRelation);
+	unchanged++;
+      } else if (bdd_is_tautology(approxRelation, 0)) {
+	fprintf(vis_stdout,
+		"** img warning : bdd_zero from subsetting in bwd[%d].\n", i);
+	mdd_free(approxRelation);
+	unchanged++;
+      } else if (mdd_equal(approxRelation, relation)) {
+	mdd_free(approxRelation);
+	unchanged++;
+      } else {
+	mdd_free(relation);
+	array_insert(bdd_t*, info->bwdClusteredRelationArray, i,
+		     approxRelation);
+      }
+    }
+  }
+  
+  if(directionType == Img_Backward_c || directionType == Img_Both_c)
+    FreeClusteredCofactoredRelationArray(info);
+
+  return(unchanged);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns current transition relation.]
+
+  Description [Returns current transition relation.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+ImgGetTransitionRelationIwls95(void *methodData,
+			       Img_DirectionType directionType)
+{
+  Iwls95Info_t *info = (Iwls95Info_t *)methodData;
+
+  if (directionType == Img_Forward_c)
+    return(info->fwdClusteredRelationArray);
+  else if (directionType == Img_Backward_c)
+    return(info->bwdClusteredRelationArray);
+  return(NIL(array_t));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Overwrites transition relation with given.]
+
+  Description [Overwrites transition relation with given.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgUpdateTransitionRelationIwls95(void *methodData, array_t *relationArray,
+				  Img_DirectionType directionType)
+{
+  Iwls95Info_t *info = (Iwls95Info_t *)methodData;
+
+  if (directionType == Img_Forward_c)
+    info->fwdClusteredRelationArray = relationArray;
+  else if (directionType == Img_Backward_c)
+    info->bwdClusteredRelationArray = relationArray;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Replace ith partitioned transition relation.]
+
+  Description [Replace ith partitioned transition relation.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgReplaceIthPartitionedTransitionRelationIwls95(void *methodData,
+	int i, mdd_t *relation, Img_DirectionType directionType)
+{
+  array_t	*relationArray;
+  mdd_t		*old;
+
+  relationArray = ImgGetTransitionRelationIwls95(methodData, directionType);
+  if (!relationArray)
+    return;
+  old = array_fetch(mdd_t *, relationArray, i);
+  mdd_free(old);
+  array_insert(mdd_t *, relationArray, i, relation);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Frees current transition relation and associated
+  quantification schedule for the given direction.]
+
+  Description [Frees current transition relation and associated
+  quantification schedule for the given direction.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgImageFreeClusteredTransitionRelationIwls95(void *methodData,
+			       Img_DirectionType directionType)
+{
+  Iwls95Info_t *info = (Iwls95Info_t *)methodData;
+
+  if (directionType == Img_Forward_c || directionType == Img_Both_c) {
+    if (info->fwdClusteredRelationArray != NIL(array_t)) {
+      mdd_array_free(info->fwdClusteredRelationArray);
+      info->fwdClusteredRelationArray = NIL(array_t);
+    }
+    if (info->fwdArraySmoothVarBddArray != NIL(array_t)) {
+      mdd_array_array_free(info->fwdArraySmoothVarBddArray);
+      info->fwdArraySmoothVarBddArray = NIL(array_t);
+    }
+    if (info->fwdSmoothVarCubeArray != NIL(array_t)) {
+      mdd_array_free(info->fwdSmoothVarCubeArray);
+      info->fwdSmoothVarCubeArray = NIL(array_t);
+    }
+  }
+  if (directionType == Img_Backward_c || directionType == Img_Both_c) {
+    if (info->bwdClusteredRelationArray != NIL(array_t)) {
+      mdd_array_free(info->bwdClusteredRelationArray);
+      info->bwdClusteredRelationArray = NIL(array_t);
+    }
+    if (info->bwdArraySmoothVarBddArray != NIL(array_t)) {
+      mdd_array_array_free(info->bwdArraySmoothVarBddArray);
+      info->bwdArraySmoothVarBddArray = NIL(array_t);
+    }
+    if (info->bwdSmoothVarCubeArray != NIL(array_t)) {
+      mdd_array_free(info->bwdSmoothVarCubeArray);
+      info->bwdSmoothVarCubeArray = NIL(array_t);
+    }
+  }
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis [Constrains/Adds dont-cares to the bit relation and creates
+  a new transition relation.]
+
+  Description [Constrains/adds dont-cares to the bit relation and creates a new
+  transition relation. First, the existing transition relation is freed.  The
+  bit relation is created if it isn't stored already. The bit relation is then
+  copied into the clustered relation field of the given direction.  Then, it is
+  constrained by the given constraint (underapprox) or the complement of the
+  constraint is added (overapprox) to the bit relation.  Then the modified bit
+  relation is clustered.  The underApprox flag indicates whether to create an
+  over or an underapproximation of the transition relation (TRUE for
+  underapproximation, FALSE for overapproximation).  Although the procedure
+  Img_MinimizeImage is used, the minimizeMethod flag for underapproximations
+  should be generated by Img_GuidedSearchReadUnderApproxMinimizeMethod.  The
+  clean up flag indicates freeing of the bit relations.  If the forceReorder
+  flag is set, variable reordering is fired after freeing old relations and
+  before creating new relations.]
+
+  SideEffects [Frees current transition relation and quantification
+  schedule. Frees bit relations if indicated. ]
+
+  SeeAlso [Img_MultiwayLinearAndSmooth ImgImageInfoInitializeMono
+  Img_MinimizeImage]
+  
+******************************************************************************/
+void
+ImgImageConstrainAndClusterTransitionRelationIwls95OrMlp(
+  Img_ImageInfo_t *imageInfo,
+  Img_DirectionType direction,
+  mdd_t *constrain,
+  Img_MinimizeType minimizeMethod,
+  boolean underApprox,
+  boolean cleanUp,
+  boolean forceReorder,
+    int printStatus)
+{
+  ImgFunctionData_t *functionData = &(imageInfo->functionData);
+  Iwls95Info_t *info = (Iwls95Info_t *)imageInfo->methodData;
+  array_t *constrainArray;
+  mdd_manager *mddManager = Part_PartitionReadMddManager(functionData->mddNetwork);
+  array_t *relationArray    = NIL(array_t);
+  array_t *relationArrayFwd = NIL(array_t);
+  array_t *relationArrayBwd = NIL(array_t);
+
+  assert(imageInfo->methodType == Img_Iwls95_c ||
+	 imageInfo->methodType == Img_Mlp_c);
+
+  /* free existing relation */
+  ImgImageFreeClusteredTransitionRelationIwls95(imageInfo->methodData,
+						direction);
+  if (forceReorder) bdd_reorder(mddManager);
+  /* create a bit relation and quantifiable variables (PIs and
+     intermediate variables) if necessary */
+  CreateBitRelationArray(info, functionData);
+
+  /* make a work copy of the bit array */
+  relationArray = BddArrayDup(info->bitRelationArray);
+
+  if (cleanUp) FreeBitRelationArray(info);
+  
+  /* apply the constraint to the bit relation */
+  if (constrain) {
+    constrainArray = array_alloc(mdd_t *, 1);
+    array_insert(mdd_t *, constrainArray, 0, constrain);
+    ImgMinimizeImageArrayWithCareSetArrayInSitu(relationArray,
+						constrainArray,
+						minimizeMethod, underApprox,
+						printStatus, direction);
+    array_free(constrainArray);
+  }
+
+  if (direction == Img_Forward_c) {
+    relationArrayFwd = relationArray;
+  } else if (direction == Img_Backward_c) {
+    relationArrayBwd = relationArray;
+  } else if (direction == Img_Both_c) {
+    relationArrayFwd = relationArray;
+    relationArrayBwd = BddArrayDup(relationArray);
+  } else {
+    assert(0);
+  }
+  relationArray = NIL(array_t);
+  
+  /* return order and recluster the relation */
+  if (direction == Img_Forward_c || direction == Img_Both_c) {
+    Img_ClusterRelationArray(mddManager,
+			     imageInfo->methodType,
+			     direction,
+			     relationArrayFwd,
+			     functionData->domainVars,
+			     functionData->rangeVars,
+			     info->quantifyVarMddIdArray,
+			     &info->fwdClusteredRelationArray,
+			     &info->fwdArraySmoothVarBddArray,
+			     NULL,
+			     1);
+    if (functionData->createVarCubesFlag) {
+      info->fwdSmoothVarCubeArray = MakeSmoothVarCubeArray(mddManager,
+					info->fwdArraySmoothVarBddArray);
+    }
+  }
+  
+  if (direction == Img_Backward_c || direction == Img_Both_c) {
+    Img_ClusterRelationArray(mddManager,
+			     imageInfo->methodType,
+			     direction,
+			     relationArrayBwd,
+			     functionData->domainVars,
+			     functionData->rangeVars,
+			     info->quantifyVarMddIdArray,
+			     &info->bwdClusteredRelationArray,
+			     &info->bwdArraySmoothVarBddArray,
+			     NULL,
+			     1);
+    if (functionData->createVarCubesFlag) {
+      info->bwdSmoothVarCubeArray = MakeSmoothVarCubeArray(mddManager,
+					info->bwdArraySmoothVarBddArray);
+    }
+  }
+
+  if (cleanUp) {
+    array_free(info->quantifyVarMddIdArray);
+    info->quantifyVarMddIdArray = NIL(array_t);
+  }
+
+  /* Print information */
+  if (info->option->verbosity > 0){
+    fprintf(vis_stdout,"Computing Image Using %s technique.\n",
+	    imageInfo->methodType == Img_Mlp_c ? "MLP" : "IWLS95");
+    fprintf(vis_stdout,"Total # of domain binary variables = %3d\n",
+	    array_n(functionData->domainBddVars));
+    fprintf(vis_stdout,"Total # of range binary variables = %3d\n",
+	    array_n(functionData->rangeBddVars));
+    if (info->quantifyVarMddIdArray) {
+      array_t *bddArray;
+
+      bddArray = mdd_id_array_to_bdd_array(mddManager,
+						  info->quantifyVarMddIdArray);
+      fprintf(vis_stdout,"Total # of quantify binary variables = %3d\n",
+	      array_n(bddArray));
+      mdd_array_free(bddArray);
+    } else {
+      fprintf(vis_stdout,"Total # of quantify binary variables = %3d\n",
+	      array_n(functionData->quantifyBddVars));
+    }
+    if (((direction == Img_Forward_c) || (direction == Img_Both_c)) &&
+	(info->fwdClusteredRelationArray != NIL(array_t))) {
+      (void) fprintf(vis_stdout,
+		     "Shared size of transition relation for forward image ");
+      (void) fprintf(vis_stdout,
+		     "computation is %10ld BDD nodes (%-4d components)\n",
+		     bdd_size_multiple(info->fwdClusteredRelationArray),
+		     array_n(info->fwdClusteredRelationArray));
+    }
+    if (((direction == Img_Backward_c) || (direction == Img_Both_c)) &&
+      (info->bwdClusteredRelationArray != NIL(array_t))) {
+      (void) fprintf(vis_stdout,
+		     "Shared size of transition relation for backward image ");
+      (void) fprintf(vis_stdout,
+		     "computation is %10ld BDD nodes (%-4d components)\n",
+		     bdd_size_multiple(info->bwdClusteredRelationArray),
+		     array_n(info->bwdClusteredRelationArray));
+    }
+  }/* if verbosity > 0 */
+
+  if(direction == Img_Backward_c || direction == Img_Both_c)
+    ResetClusteredCofactoredRelationArray(mddManager, info);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints integers from an array.]
+
+  Description [Prints integers from an array.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgPrintIntegerArray(array_t *idArray)
+{
+  int i;
+  fprintf(vis_stdout,
+    "**************** printing bdd ids from the bdd array ***********\n");
+  fprintf(vis_stdout,"%d::\t", array_n(idArray));
+  for (i=0;i<array_n(idArray); i++) {
+    fprintf(vis_stdout," %d ", array_fetch(int, idArray, i));
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the given parition.]
+
+  Description [Prints the given parition.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgPrintPartition(graph_t *partition)
+{
+  vertex_t *vertex;
+  lsList vertexList = g_get_vertices(partition);
+  lsGen gen;
+  st_table *vertexTable = st_init_table(st_ptrcmp, st_ptrhash);
+  fprintf(vis_stdout,"\n");
+  lsForEachItem(vertexList, gen, vertex) {
+    if (lsLength(g_get_out_edges(vertex)) == 0)
+      PrintPartitionRecursively(vertex,vertexTable,0);
+  }
+  st_free_table(vertexTable);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints info of the partitioned transition relation.]
+
+  Description [Prints info of the partitioned transition relation.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgPrintPartitionedTransitionRelation(mdd_manager *mddManager,
+				array_t *relationArray,
+				array_t *arraySmoothVarBddArray)
+{
+  int	i, j, n;
+  mdd_t	*relation;
+  mdd_t *bdd;
+  array_t *smoothVarBddArray;
+  array_t *bvar_list = mdd_ret_bvar_list(mddManager);
+  var_set_t *vset;
+  bvar_type bv;
+
+  n = array_n(relationArray);
+
+  fprintf(vis_stdout, "# of relations = %d\n", n);
+  if (arraySmoothVarBddArray) {
+    smoothVarBddArray = array_fetch(array_t *, arraySmoothVarBddArray, 0);
+    fprintf(vis_stdout, "Early smooth(%d) = ", array_n(smoothVarBddArray));
+    for (j = 0; j < array_n(smoothVarBddArray); j++) {
+      bdd = array_fetch(mdd_t *, smoothVarBddArray, j);
+      mdd_print_support_to_file(vis_stdout, " %s", bdd);
+    }
+    fprintf(vis_stdout, "\n");
+  }
+  for (i = 0; i < n; i++) {
+    relation = array_fetch(mdd_t *, relationArray, i);
+    fprintf(vis_stdout, "T[%d] : bdd_size = %d\n", i, bdd_size(relation));
+    fprintf(vis_stdout, "  support(%d) = ",
+	    mdd_get_number_of_bdd_support(mddManager, relation));
+    vset = bdd_get_support(relation);
+    for (j = 0; j < array_n(bvar_list); j++) {
+      if (var_set_get_elt(vset, j) == 1) {
+	bv = array_fetch(bvar_type, bvar_list, j);
+	mdd_print_support_to_file(vis_stdout, " %s", bv.node);
+      }
+    }
+    var_set_free(vset);
+    fprintf(vis_stdout, "\n");
+    if (arraySmoothVarBddArray) {
+      smoothVarBddArray = array_fetch(array_t *, arraySmoothVarBddArray, i + 1);
+      fprintf(vis_stdout, "  smooth(%d) = ", array_n(smoothVarBddArray));
+      for (j = 0; j < array_n(smoothVarBddArray); j++) {
+	bdd = array_fetch(mdd_t *, smoothVarBddArray, j);
+	mdd_print_support_to_file(vis_stdout, " %s", bdd);
+      }
+      fprintf(vis_stdout, "\n");
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Eliminates dependent variables from transition relation.]
+
+  Description [Eliminates dependent variables from a transition
+  relation.  Returns a simplified copy of the given states if successful;
+  NULL otherwise.]
+
+  SideEffects [relationArray is also modified.]
+
+  SeeAlso     []
+
+******************************************************************************/
+mdd_t *
+ImgTrmEliminateDependVars(ImgFunctionData_t *functionData,
+			  array_t *relationArray,
+			  mdd_t *states, mdd_t **dependRelations,
+			  int *nDependVars)
+{
+  int		i, j;
+  int		howMany = 0;	/* number of latches that can be eliminated */
+  mdd_t		*var, *newStates, *abs, *positive, *phi, *tmp, *relation;
+  int		nSupports;    /* vars in the support of the state set */
+  int		*candidates;	/* vars to be considered for elimination */
+  double	minStates;
+  var_set_t	*supportVarSet;
+  graph_t	*mddNetwork;
+  mdd_manager	*mddManager;
+
+  mddNetwork = functionData->mddNetwork;
+  mddManager = Part_PartitionReadMddManager(mddNetwork);
+
+  if (dependRelations)
+    *dependRelations = mdd_one(mddManager);
+  newStates = mdd_dup(states);
+
+  nSupports = 0;
+  supportVarSet = bdd_get_support(newStates);
+  for (i = 0; i < supportVarSet->n_elts; i++) {
+    if (var_set_get_elt(supportVarSet, i) == 1)
+      nSupports++;
+  }
+  candidates = ALLOC(int, nSupports);
+  if (candidates == NULL) {
+    var_set_free(supportVarSet);
+    return(NULL);
+  }
+  nSupports = 0;
+  for (i = 0; i < supportVarSet->n_elts; i++) {
+    if (var_set_get_elt(supportVarSet, i) == 1) {
+      candidates[nSupports] = i;
+      nSupports++;
+    }
+  }
+  var_set_free(supportVarSet);
+
+  /* The signatures of the variables in a function are the number
+  ** of minterms of the positive cofactors with respect to the
+  ** variables themselves. */
+  signatures = bdd_cof_minterm(newStates);
+  if (signatures == NULL) {
+    FREE(candidates);
+    return(NULL);
+  }
+  /* We now extract a positive quantity which is higher for those
+  ** variables that are closer to being essential. */
+  minStates = signatures[nSupports];
+  for (i = 0; i < nSupports; i++) {
+    double z = signatures[i] / minStates - 1.0;
+    signatures[i] = (z < 0.0) ? -z : z;    /* make positive */
+  }
+  qsort((void *)candidates, nSupports, sizeof(int),
+      (int (*)(const void *, const void *))TrmSignatureCompare);
+  FREE(signatures);
+
+  /* Now process the candidates in the given order. */
+  for (i = 0; i < nSupports; i++) {
+    var = bdd_var_with_index(mddManager, candidates[i]);
+    if (bdd_var_is_dependent(newStates, var)) {
+      abs = bdd_smooth_with_cube(newStates, var);
+      if (abs == NULL)
+	return(NULL);
+      positive = bdd_cofactor(newStates, var);
+      if (positive == NULL)
+	return(NULL);
+      phi = Img_MinimizeImage(positive, abs, Img_DefaultMinimizeMethod_c, 1);
+      if (phi == NULL)
+	return(NULL);
+      mdd_free(positive);
+      if (bdd_size(phi) < IMG_MAX_DEP_SIZE) {
+	howMany++;
+	for (j = 0; j < array_n(relationArray); j++) {
+	  relation = array_fetch(mdd_t *, relationArray, j);
+	  if (dependRelations)
+	    tmp = bdd_smooth_with_cube(relation, var);
+	  else
+	    tmp = bdd_compose(relation, var, phi);
+	  mdd_free(relation);
+	  array_insert(mdd_t *, relationArray, j, tmp);
+	}
+	mdd_free(newStates);
+	newStates = abs;
+	if (dependRelations) {
+	  relation = mdd_xnor(var, phi);
+	  tmp = ImgSubstitute(relation, functionData, Img_R2D_c);
+	  mdd_free(relation);
+	  relation = mdd_and(*dependRelations, tmp, 1, 1);
+	  mdd_free(*dependRelations);
+	  *dependRelations = relation;
+	}
+      } else {
+	mdd_free(abs);
+      }
+      mdd_free(phi);
+    }
+  }
+  FREE(candidates);
+
+  *nDependVars = howMany;
+  return(newStates);
+} /* end of ImgTrmEliminateDependVars */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Reset the clusteredcofactoredrelationarray to the
+  clusteredrelationarray.]
+
+  Description [Copy the clustered array into the clusteredcofactored array, and
+  set the caresetarray to (1).  Assumes either both the caresetarray and the
+  cofactoredarray are NIL, or that they both contain sensible data.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+ResetClusteredCofactoredRelationArray(
+   mdd_manager *mddManager,
+   Iwls95Info_t *info)
+{
+  int i;
+  mdd_t *cluster;
+
+  assert(info->bwdClusteredRelationArray != NIL(array_t));
+  
+  FreeClusteredCofactoredRelationArray(info);
+
+  info->careSetArray = array_alloc(mdd_t *, 1);
+  array_insert_last(mdd_t *, info->careSetArray, mdd_one(mddManager));
+  info->bwdClusteredCofactoredRelationArray = array_alloc(mdd_t *, 0);
+
+  arrayForEachItem(mdd_t *, info->bwdClusteredRelationArray, i, cluster){
+    array_insert_last(mdd_t *, info->bwdClusteredCofactoredRelationArray,
+		      mdd_dup(cluster)); 
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the clusteredcofactoredrelationarray]
+
+
+  Description [Frees the clusteredCofactoredRelationArray, and the
+  careSetArray, and sets them to NIL to signify that they are invalid.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+FreeClusteredCofactoredRelationArray(
+   Iwls95Info_t *info)
+{
+  /* one should only be NIL if the other is, too */
+  assert((info->bwdClusteredCofactoredRelationArray != NIL(array_t)) ==
+	 (info->careSetArray != NIL(array_t)));
+  
+  if(info->bwdClusteredCofactoredRelationArray == NIL(array_t))
+    return;
+  
+  mdd_array_free(info->bwdClusteredCofactoredRelationArray);
+  info->bwdClusteredCofactoredRelationArray = NIL(array_t);
+  mdd_array_free(info->careSetArray);
+  info->careSetArray = NIL(array_t);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the necessary options for computing the image and returns
+               in the option structure.]
+
+  Description [Gets the necessary options for computing the image and returns
+               in the option structure.]
+
+  SideEffects []
+
+******************************************************************************/
+
+static ImgTrmOption_t *
+TrmGetOptions(void)
+{
+  char *flagValue;
+  ImgTrmOption_t *option;
+
+  option = ALLOC(ImgTrmOption_t, 1);
+
+  flagValue = Cmd_FlagReadByName("image_cluster_size");
+  if (flagValue == NIL(char)) {
+    option->clusterSize = 5000; /* the default value */
+  }
+  else {
+    option->clusterSize = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("image_verbosity");
+  if (flagValue == NIL(char)) {
+    option->verbosity = 0; /* the default value */
+  }
+  else {
+    option->verbosity = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("image_W1");
+  if (flagValue == NIL(char)) {
+    option->W1 = 6; /* the default value */
+  }
+  else {
+    option->W1 = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("image_W2");
+  if (flagValue == NIL(char)) {
+    option->W2 = 1; /* the default value */
+  }
+  else {
+    option->W2 = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("image_W3");
+  if (flagValue == NIL(char)) {
+    option->W3 = 1; /* the default value */
+  }
+  else {
+    option->W3 = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("image_W4");
+  if (flagValue == NIL(char)) {
+    option->W4 = 2; /* the default value */
+  }
+  else {
+    option->W4 = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("image_print_depend_matrix");
+  if (flagValue == NIL(char)) {
+    option->printDepMatrix = 0; /* the default value */
+  }
+  else {
+    option->printDepMatrix = atoi(flagValue);
+  }
+
+
+  flagValue = Cmd_FlagReadByName("mlp_method");
+  if (flagValue == NIL(char)) {
+    option->mlpMethod = 0; /* the default value */
+  }
+  else {
+    option->mlpMethod = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_cluster");
+  if (flagValue == NIL(char)) {
+    option->mlpCluster = 1; /* the default value */
+  }
+  else {
+    option->mlpCluster = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_cluster_dynamic");
+  if (flagValue == NIL(char)) {
+    option->mlpClusterDynamic = 1; /* the default value */
+  }
+  else {
+    option->mlpClusterDynamic = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_affinity_threshold");
+  if (flagValue == NIL(char)) {
+    option->mlpAffinityThreshold = 0.0; /* the default value */
+  }
+  else {
+    sscanf(flagValue, "%f", &option->mlpAffinityThreshold);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_cluster_quantify_vars");
+  if (flagValue == NIL(char)) {
+    option->mlpClusterQuantifyVars = 0; /* the default value */
+  }
+  else {
+    option->mlpClusterQuantifyVars = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_cluster_sorted_list");
+  if (flagValue == NIL(char)) {
+    option->mlpClusterSortedList = 1; /* the default value */
+  }
+  else {
+    option->mlpClusterSortedList = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_initial_cluster");
+  if (flagValue == NIL(char)) {
+    option->mlpInitialCluster = 0; /* the default value */
+  }
+  else {
+    option->mlpInitialCluster = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_cs_first");
+  if (flagValue == NIL(char)) {
+    option->mlpCsFirst = 0; /* the default value */
+  }
+  else {
+    option->mlpCsFirst = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_skip_rs");
+  if (flagValue == NIL(char)) {
+    option->mlpSkipRs = 0; /* the default value */
+  }
+  else {
+    option->mlpSkipRs = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_skip_cs");
+  if (flagValue == NIL(char)) {
+    option->mlpSkipCs = 1; /* the default value */
+  }
+  else {
+    option->mlpSkipCs = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_row_based");
+  if (flagValue == NIL(char)) {
+    option->mlpRowBased = 0; /* the default value */
+  }
+  else {
+    option->mlpRowBased = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_reorder");
+  if (flagValue == NIL(char)) {
+    option->mlpReorder = 0; /* the default value */
+  }
+  else {
+    option->mlpReorder = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_pre_reorder");
+  if (flagValue == NIL(char)) {
+    option->mlpPreReorder = 0; /* the default value */
+  }
+  else {
+    option->mlpPreReorder = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_postprocess");
+  if (flagValue == NIL(char)) {
+    option->mlpPostProcess = 0; /* the default value */
+  }
+  else {
+    option->mlpPostProcess = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_decompose_scc");
+  if (flagValue == NIL(char)) {
+    option->mlpDecomposeScc = 1; /* the default value */
+  }
+  else {
+    option->mlpDecomposeScc = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_cluster_scc");
+  if (flagValue == NIL(char)) {
+    option->mlpClusterScc = 1; /* the default value */
+  }
+  else {
+    option->mlpClusterScc = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_sort_scc");
+  if (flagValue == NIL(char)) {
+    option->mlpSortScc = 1; /* the default value */
+  }
+  else {
+    option->mlpSortScc = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_sort_scc_mode");
+  if (flagValue == NIL(char)) {
+    option->mlpSortSccMode = 2; /* the default value */
+  }
+  else {
+    option->mlpSortSccMode = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_cluster_merge");
+  if (flagValue == NIL(char)) {
+    option->mlpClusterMerge = 0; /* the default value */
+  }
+  else {
+    option->mlpClusterMerge = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_multiway");
+  if (flagValue == NIL(char)) {
+    option->mlpMultiway = 0; /* the default value */
+  }
+  else {
+    option->mlpMultiway = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_lambda_mode");
+  if (flagValue == NIL(char)) {
+    option->mlpLambdaMode = 0; /* the default value */
+  }
+  else {
+    option->mlpLambdaMode = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_sorted_rows");
+  if (flagValue == NIL(char)) {
+    option->mlpSortedRows = 1; /* the default value */
+  }
+  else {
+    option->mlpSortedRows = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_sorted_cols");
+  if (flagValue == NIL(char)) {
+    option->mlpSortedCols = 1; /* the default value */
+  }
+  else {
+    option->mlpSortedCols = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_pre_swap_state_vars");
+  if (flagValue == NIL(char)) {
+    option->mlpPreSwapStateVars = 0; /* the default value */
+  }
+  else {
+    option->mlpPreSwapStateVars = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_print_matrix");
+  if (flagValue == NIL(char)) {
+    option->mlpPrintMatrix = 0; /* the default value */
+  }
+  else {
+    option->mlpPrintMatrix = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_write_order");
+  if (flagValue == NIL(char)) {
+    option->mlpWriteOrder = NIL(char); /* the default value */
+  }
+  else {
+    option->mlpWriteOrder = util_strsav(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_verbosity");
+  if (flagValue == NIL(char)) {
+    option->mlpVerbosity = 0; /* the default value */
+  }
+  else {
+    option->mlpVerbosity = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("mlp_debug");
+  if (flagValue == NIL(char)) {
+    option->mlpDebug = 0; /* the default value */
+  }
+  else {
+    option->mlpDebug = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("image_read_reorder_cluster");
+  if (flagValue == NIL(char)) {
+    option->readReorderCluster = 0; /* the default value */
+  }
+  else {
+    option->readReorderCluster = atoi(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("image_read_cluster");
+  if (flagValue == NIL(char)) {
+    option->readCluster = NIL(char); /* the default value */
+  }
+  else {
+    option->readCluster = util_strsav(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("image_write_cluster");
+  if (flagValue == NIL(char)) {
+    option->writeCluster = NIL(char); /* the default value */
+  }
+  else {
+    option->writeCluster = util_strsav(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("image_write_depend_matrix");
+  if (flagValue == NIL(char)) {
+    option->writeDepMatrix = NIL(char); /* the default value */
+  }
+  else {
+    option->writeDepMatrix = util_strsav(flagValue);
+  }
+
+  flagValue = Cmd_FlagReadByName("linear_grain_type");
+  if (flagValue == NIL(char)) {
+    option->linearFineGrainFlag = 0; /* the default value */
+  }
+  else {
+    option->linearFineGrainFlag = 1;
+  }
+
+  flagValue = Cmd_FlagReadByName("linear_optimize");
+  if (flagValue == NIL(char)) {
+    option->linearOptimize = Opt_None; /* the default value */
+  }
+  else {
+    option->linearOptimize = Opt_NS;
+  }
+
+  option->linearOrderVariable = 0;
+  flagValue = Cmd_FlagReadByName("linear_order_variable");
+  if (flagValue == NIL(char)) {
+    option->linearOrderVariable = 0; /* the default value */
+  }
+  else {
+    option->linearOrderVariable = 1;
+  }
+
+  option->linearGroupStateVariable = 0; 
+  flagValue = Cmd_FlagReadByName("linear_group_state_variable");
+  if (flagValue == NIL(char)) {
+    option->linearGroupStateVariable = 0; /* the default value */
+  }
+  else {
+    option->linearGroupStateVariable = 1;
+  }
+  
+  option->linearIncludeCS = 1;
+  option->linearIncludeNS = 1;
+  option->linearQuantifyCS = 0; 
+  option->linearComputeRange = 0;
+  flagValue = Cmd_FlagReadByName("linear_exclude_cs");
+  if (flagValue) option->linearIncludeCS = 0;
+  flagValue = Cmd_FlagReadByName("linear_exclude_ns");
+  if (flagValue) option->linearIncludeNS = 0;
+
+  return option;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Creates the bit relations and the mdd id array for the
+  quantifiable variables and stores it in the ImgIwls95
+  structure. ]
+
+  Description [Creates the bit relations and the mdd id array for the
+  quantifiable variables and stores it in the ImgIwls95
+  structure. This is identical to the initialize procedure. Read the
+  roots (next state mdds), compute the bit relations for each root. If
+  there are some intermediate variables, add them to quantifiable
+  vars. ]
+  
+  SideEffects [bitRelationArray and quantifyVarMddIdArray fields are
+  modified of the Iwls95Info_t struct.]
+  
+  SeeAlso [ImgImageInfoInitializeIwls95]
+  
+******************************************************************************/
+
+static void
+CreateBitRelationArray(Iwls95Info_t *info, ImgFunctionData_t *functionData)
+{
+  array_t *bddRelationArray = NIL(array_t);
+  array_t *domainVarMddIdArray = functionData->domainVars;
+  array_t *rangeVarMddIdArray = functionData->rangeVars;
+  array_t *quantifyVarMddIdArray = NIL(array_t);
+  graph_t *mddNetwork = functionData->mddNetwork;
+  array_t *roots = functionData->roots;
+  int i;
+  int n1, n2, nIntermediateVars = 0;
+  mdd_manager *mddManager = NIL(mdd_manager);
+  st_table *vertexTable   = NIL(st_table);
+  st_table *domainQuantifyVarMddIdTable = NIL(st_table);
+  int mddId;
+  char *nodeName;
+
+  if (info->bitRelationArray != NIL(array_t)) {
+    assert(info->quantifyVarMddIdArray != NIL(array_t));
+    return;
+  }
+  
+  bddRelationArray = array_alloc(mdd_t*, 0);
+  quantifyVarMddIdArray = array_dup(functionData->quantifyVars);
+  mddManager = Part_PartitionReadMddManager(mddNetwork);
+  vertexTable = st_init_table(st_ptrcmp, st_ptrhash);
+  domainQuantifyVarMddIdTable = st_init_table(st_numcmp, st_numhash);
+  
+  arrayForEachItem(int, domainVarMddIdArray, i, mddId) {
+    st_insert(domainQuantifyVarMddIdTable, (char *)(long)mddId, NIL(char));
+  }
+  arrayForEachItem(int, quantifyVarMddIdArray, i, mddId) {
+    st_insert(domainQuantifyVarMddIdTable, (char *)(long)mddId, NIL(char));
+  }
+  
+  arrayForEachItem(char *, roots, i, nodeName) {
+    vertex_t *vertex = Part_PartitionFindVertexByName(mddNetwork, nodeName);
+    Mvf_Function_t *mvf = Part_VertexReadFunction(vertex);
+    int mddId = array_fetch(int, rangeVarMddIdArray, i);
+    
+    /*mdd_t *relation = Mvf_FunctionBuildRelationWithVariable(mvf, mddId);*/
+    array_t *varBddRelationArray = mdd_fn_array_to_bdd_rel_array(mddManager,
+								 mddId, mvf);
+    array_append(bddRelationArray, varBddRelationArray);
+    array_free(varBddRelationArray);
+    /*array_insert_last(mdd_t *, bddRelationArray, relation);*/
+    if (info->option->verbosity)
+      n1 = array_n(bddRelationArray);
+    else /* to remove uninitialized variable warning */
+      n1 = 0;
+    PartitionTraverseRecursively(mddManager, vertex, -1, vertexTable,
+				 bddRelationArray,
+				 domainQuantifyVarMddIdTable,
+				 quantifyVarMddIdArray);
+    if (info->option->verbosity) {
+      n2 = array_n(bddRelationArray);
+      nIntermediateVars += n2 - n1;
+    }
+  }
+  if (info->option->verbosity) {
+    (void)fprintf(vis_stdout, "** img info: %d intermediate variables\n",
+		  nIntermediateVars);
+  }
+  st_free_table(vertexTable);
+  st_free_table(domainQuantifyVarMddIdTable);
+  info->bitRelationArray = bddRelationArray;
+  info->quantifyVarMddIdArray = quantifyVarMddIdArray;
+  return;
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees bit relation array and the quantification variables.]
+
+
+  Description [Frees bit relation array and quantification
+  variables. Important: to set these field to NIL in case of reuse.]
+
+  SideEffects [Also frees the quantifVarMddIdArray field.]
+******************************************************************************/
+static void
+FreeBitRelationArray (Iwls95Info_t *info)
+{
+  mdd_array_free(info->bitRelationArray);
+  info->bitRelationArray = NIL(array_t);
+  return;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis [Takes an array of relations and does order, cluster,
+  order on it according to the IWLS95 method. This forms a
+  heuristically optimized clustered transition relation, plus a
+  quantification schedule that goes with it.]
+
+  Description [Takes an array of relations and does order,
+  cluster, order on it. This forms a heuristically optimized clustered
+  transition relation, plus a quantification schedule that goes with
+  it. Requires the relation array, quantify variables, a
+  "from" variable array (contained in the quantify variables), a "to"
+  variable array and direction of computation (image or
+  preimage). Eventually orderedClusteredRelationArray holds an
+  ordered-clustered-ordered version of the relationArray and
+  smoothVarBddArrayPtr holds the quantification schedule that goes
+  with orderClusteredRelationArray.  If the freeRelationArray flag is
+  set, the relationArray is freed.  This code is identical to
+  ImgInfoInitialize.]
+
+  SideEffects [The existing contents of
+  orderedClusteredRelationArrayPtr or smoothVarBddArrayPtr are lost
+  (not freed). relationArray is freed if the freeRelationArray flag
+  is set.]
+
+  SeeAlso     [ImgImageInfoInitializeIwls95]
+
+******************************************************************************/
+static void
+OrderClusterOrder(mdd_manager *mddManager,			      
+		  array_t     *relationArray, 
+		  array_t     *fromVarBddArray, 
+		  array_t     *toVarBddArray, 
+		  array_t     *quantifyVarBddArray,
+		  array_t    **orderedClusteredRelationArrayPtr,
+		  array_t    **smoothVarBddArrayPtr,
+		  ImgTrmOption_t   *option,
+		  boolean freeRelationArray)
+{
+  array_t *clusteredRelationArray; /*clustered version of orderedRelationArray*/
+
+  /*
+   * Since clusters are formed by multiplying the latches starting
+   * from one end we need to order the latches using some heuristics
+   * first. Right now, we order the latches using the same heuristic
+   * as the one used for ordering the clusters for early quantifiction.
+   * However, since we are not interested in the quantification
+   * schedule at this stage, we will pass a NIL(array_t*) as the last
+   * argument. 
+   */      
+  *orderedClusteredRelationArrayPtr = NIL(array_t);
+  OrderRelationArray(mddManager, relationArray, fromVarBddArray,
+		     quantifyVarBddArray, toVarBddArray, option, 
+		     orderedClusteredRelationArrayPtr, NIL(array_t *));
+
+  /* free relationArray if told to */
+  if (freeRelationArray) mdd_array_free(relationArray);
+  
+  
+  /* Create the clusters */
+  clusteredRelationArray = CreateClusters(mddManager,
+					  *orderedClusteredRelationArrayPtr,
+					  option);
+
+  /* Free the orderedRelationArray */
+  mdd_array_free(*orderedClusteredRelationArrayPtr);
+  
+  /* Order the clusters for image and pre-image computation. */
+  OrderRelationArray(mddManager, clusteredRelationArray, fromVarBddArray, 
+		     quantifyVarBddArray, toVarBddArray, option,
+		     orderedClusteredRelationArrayPtr, smoothVarBddArrayPtr);
+  /* Free the clusteredRelationArray. */
+  mdd_array_free(clusteredRelationArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Forms the clusters of relations based on BDD size heuristic.]
+
+  Description [The clusters are formed by taking the product in order. Once the
+               BDD size of the cluster reaches a threshold, a new cluster is
+               started.]
+
+  SideEffects []
+******************************************************************************/
+
+static array_t *
+CreateClusters(bdd_manager *bddManager, array_t *relationArray,
+               ImgTrmOption_t *option)
+{
+  array_t *clusterArray;
+  int i;
+  bdd_t *cluster, *relation, *tempCluster;
+  int flag;
+  int size;
+
+  clusterArray = array_alloc(bdd_t *, 0);
+
+  for (i=0; i<array_n(relationArray);) {
+    cluster = bdd_one(bddManager);
+    flag = 0;
+    do{
+      relation = array_fetch(bdd_t *,relationArray, i);
+      i++;
+      tempCluster = bdd_and_with_limit(cluster, relation, 1, 1,
+				       option->clusterSize);
+      assert(flag || tempCluster != NIL(mdd_t));
+      if (tempCluster != NIL(mdd_t)) {
+	size = bdd_size(tempCluster);
+	if (size <= option->clusterSize || flag == 0) {
+	  bdd_free(cluster);
+	  cluster = tempCluster;
+	  if (flag == 0 && size >= option->clusterSize)
+	    break;
+	  flag = 1;
+	}
+	else{
+	  bdd_free(tempCluster);
+	  i--;
+	  break;
+	}
+      }
+      else {
+	i--;
+	break;
+      }
+    } while (i < array_n(relationArray));
+    array_insert_last(bdd_t *, clusterArray, cluster);
+  }
+  return clusterArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns an array of ordered relations and an array
+               of BDD cubes (array of BDDs).]
+
+  Description [This function returns an array of ordered relations and an array
+               of BDD cubes (array of BDDs).
+               This consists of following steps:
+               a. Initialize the array of ctrInfoStructs and varInfoStructs.
+               b. Fill in the list of varItemStruct's of ctrInfo's and
+                  ctrItemStruct's of varInfo's.
+               c. Simplify the relations by quantifying out the quantify
+                  variables local to a particular relation.
+               d. Order the relations according to the cost function described
+                  in "CalculateRelationBenefit".]
+  SideEffects []
+
+******************************************************************************/
+static void
+OrderRelationArray(mdd_manager *mddManager,
+                   array_t *relationArray,
+                   array_t *domainVarBddArray,
+                   array_t *quantifyVarBddArray,
+                   array_t *rangeVarBddArray,
+                   ImgTrmOption_t *option,
+                   array_t **orderedRelationArrayPtr,
+                   array_t **arraySmoothVarBddArrayPtr)
+{
+  array_t *quantifyVarBddIdArray, *domainVarBddIdArray, *rangeVarBddIdArray;
+  array_t *domainAndQuantifyVarBddArray;
+  array_t *ctrInfoArray, *varInfoArray, *simplifiedRelationArray;
+  array_t *sortedMaxIndexArray;
+  array_t *arrayDomainQuantifyVarsWithZeroNumCtr = NIL(array_t);
+  int numRelation, numDomainVars, numQuantifyVars, numRangeVars;
+  int numSmoothVars, numVars;
+  int bddId;
+  int i;
+  int *sortedMaxIndexVector;
+  int numSmoothVarsRemaining, numIntroducedVarsRemaining;
+  st_table  *bddIdToVarInfoTable, *bddIdToBddTable;
+  bdd_t *relation, *bdd;
+  CtrInfo_t *ctrInfo;
+  VarInfo_t *varInfo;
+  lsList remainingCtrInfoList;
+
+  numRelation = array_n(relationArray);
+  numDomainVars = array_n(domainVarBddArray);
+  numRangeVars = array_n(rangeVarBddArray);
+  numQuantifyVars = array_n(quantifyVarBddArray);
+  numSmoothVars = numDomainVars + numQuantifyVars;
+  numVars = numSmoothVars + numRangeVars;
+
+  domainVarBddIdArray = bdd_get_varids(domainVarBddArray);
+  rangeVarBddIdArray = bdd_get_varids(rangeVarBddArray);
+  quantifyVarBddIdArray = bdd_get_varids(quantifyVarBddArray);
+  domainAndQuantifyVarBddArray = array_join(domainVarBddArray,
+					    quantifyVarBddArray);
+
+  bddIdToBddTable = st_init_table(st_numcmp, st_numhash);
+  HashIdToBddTable(bddIdToBddTable, domainVarBddIdArray, domainVarBddArray);
+  HashIdToBddTable(bddIdToBddTable, quantifyVarBddIdArray, quantifyVarBddArray);
+  HashIdToBddTable(bddIdToBddTable, rangeVarBddIdArray, rangeVarBddArray);
+
+  bddIdToVarInfoTable = st_init_table(st_numcmp, st_numhash);
+
+  /*
+   * Create the array of ctrInfo's for each component
+   */
+  ctrInfoArray = array_alloc(CtrInfo_t*, 0);
+  varInfoArray = array_alloc(VarInfo_t*, 0);
+
+  /*
+   * Create the array of varInfo for each variable
+   */
+  for (i=0; i<numVars; i++) {
+    varInfo = VarInfoStructAlloc();
+    if (i<numDomainVars) {
+      bddId = array_fetch(int, domainVarBddIdArray, i);
+      varInfo->varType = domainVar_c;
+    }
+    else if (i < (numDomainVars+numQuantifyVars)) {
+      bddId = array_fetch(int, quantifyVarBddIdArray, i-numDomainVars);
+      varInfo->varType = quantifyVar_c;
+    }
+    else{
+      bddId = array_fetch(int, rangeVarBddIdArray,
+			  (i-(numDomainVars+numQuantifyVars)));
+      varInfo->varType = rangeVar_c;
+    }
+    array_insert_last(VarInfo_t*, varInfoArray, varInfo);
+    varInfo->bddId = bddId;
+    st_insert(bddIdToVarInfoTable, (char *)(long) bddId, (char *)varInfo);
+  }
+
+  /*
+   * Fill in the data structure of the ctrInfo and varInfo
+   */
+  for (i=0; i<numRelation; i++) {
+    st_table *supportTable;
+    st_generator *stGen;
+    VarItem_t *varItem;
+    CtrItem_t *ctrItem;
+    lsHandle varItemHandle, ctrItemHandle;
+    long varId;
+
+    ctrInfo = CtrInfoStructAlloc();
+    array_insert_last(CtrInfo_t*, ctrInfoArray, ctrInfo);
+    ctrInfo->ctrId = i;
+    relation = array_fetch(bdd_t*, relationArray, i);
+    supportTable = ImgBddGetSupportIdTable(relation);
+    st_foreach_item(supportTable, stGen, &varId, NULL) {
+      varInfo = NIL(VarInfo_t);
+      if (st_lookup(bddIdToVarInfoTable, (char *) varId, &varInfo) == 0) {
+	/* This variable is of no interest, because it is not present
+	 * in the bddIdToVarInfoTable.
+	 */
+	continue;
+      }
+      varItem = ALLOC(VarItem_t,1);
+      varItem->varInfo = varInfo;
+      (void) lsNewBegin(ctrInfo->varItemList, (lsGeneric)varItem,
+			(lsHandle *)&varItemHandle);
+      ctrItem = ALLOC(CtrItem_t,1);
+      ctrItem->ctrInfo = ctrInfo;
+      (void) lsNewBegin(varInfo->ctrItemList, (lsGeneric)ctrItem,
+			(lsHandle *)&ctrItemHandle);
+      varItem->ctrItemHandle = ctrItemHandle;
+      ctrItem->varItemHandle = varItemHandle;
+      varInfo->numCtr++;
+    }
+    st_free_table(supportTable);
+  } /* Initialization of ctrInfoArray and varInfoArray complete */
+
+  /*
+   * Smooth out the quantify variables which are local to a particular cluster.
+   */
+  simplifiedRelationArray = RelationArraySmoothLocalVars(relationArray,
+							 ctrInfoArray,
+							 varInfoArray,
+							 bddIdToBddTable);
+
+  assert(CheckCtrInfoArray(ctrInfoArray, numDomainVars, numQuantifyVars,
+			   numRangeVars));
+  assert(CheckVarInfoArray(varInfoArray, numRelation));
+
+  /*
+   * In the ordering scheme of clusters, the number of variables yet to be
+   * quantified out and number of variables which are yet to be introduced is
+   * taken into account.  The number of smooth variables which are yet to be
+   * quantified out could have changed. Also some of the range variables may
+   * not be in the support of any of the clusters. This can happen while doing
+   * the ordering for clusters for backward image (when a present state
+   * variable does not appear in the support of any of the next state
+   * functions. Recalculate these numbers.  */
+
+  numSmoothVarsRemaining = numSmoothVars;
+  numIntroducedVarsRemaining = numRangeVars;
+
+  /*
+   * Find out which variables do not appear in the support of any cluster.
+   * Update the numSmoothVarsRemaining and numIntroducedVarsRemaining
+   * accordingly.
+   * Also, these domainVars and quantifyVars can be quantified out as soon as
+   * possible.
+   */
+  if (arraySmoothVarBddArrayPtr != NIL(array_t *))
+    arrayDomainQuantifyVarsWithZeroNumCtr = array_alloc(bdd_t*, 0);
+  for (i=0; i<numVars; i++) {
+    varInfo = array_fetch(VarInfo_t*, varInfoArray, i);
+    if (varInfo->numCtr == 0) {
+      if ((varInfo->varType == domainVar_c) ||
+	  (varInfo->varType == quantifyVar_c)) {
+	numSmoothVarsRemaining--;
+	if (arraySmoothVarBddArrayPtr != NIL(array_t *)) {
+	  st_lookup(bddIdToBddTable, (char *)(long)varInfo->bddId, &bdd);
+	  array_insert_last(bdd_t*, arrayDomainQuantifyVarsWithZeroNumCtr,
+			    bdd_dup(bdd));
+	}
+      }
+      else numIntroducedVarsRemaining--;
+    }
+  }
+
+  /*
+   * The ordering scheme also depends on the value of the maximum index of a
+   * smooth variable which is yet to be quantified. For efficiency reasons, we
+   * maintain a vector indicating the maximum index of the clusters. This
+   * vector is sorted in the decreasing order of index. The rank of a cluster
+   * is stored in its "rankMaxSmoothVarIndex" field.
+   */
+  sortedMaxIndexArray = array_dup(ctrInfoArray);
+  array_sort(sortedMaxIndexArray, CtrInfoMaxIndexCompare);
+  sortedMaxIndexVector = ALLOC(int, numRelation);
+  for (i=0; i<numRelation; i++) {
+    ctrInfo = array_fetch(CtrInfo_t*, sortedMaxIndexArray, i);
+    ctrInfo->rankMaxSmoothVarIndex = i;
+    sortedMaxIndexVector[i] = ctrInfo->maxSmoothVarIndex;
+  }
+  array_free(sortedMaxIndexArray);
+
+  /*
+   * Create a list of clusters which are yet to be ordered. Right now
+   * put all the clusters. Later on the list will contain only those
+   * clusters which have not yet been ordered.
+   */
+  remainingCtrInfoList = lsCreate();
+  for(i=0; i<numRelation; i++) {
+    lsHandle ctrHandle;
+    ctrInfo = array_fetch(CtrInfo_t*, ctrInfoArray, i);
+    lsNewBegin(remainingCtrInfoList, (lsGeneric)ctrInfo, &ctrHandle);
+    ctrInfo->ctrInfoListHandle = ctrHandle;
+  }
+
+  /* Call the auxiliary routine to do the ordering. */
+  OrderRelationArrayAux(simplifiedRelationArray, remainingCtrInfoList,
+			ctrInfoArray, varInfoArray, sortedMaxIndexVector,
+			numSmoothVarsRemaining, numIntroducedVarsRemaining,
+			bddIdToBddTable, option, domainAndQuantifyVarBddArray,
+			orderedRelationArrayPtr, arraySmoothVarBddArrayPtr,
+			arrayDomainQuantifyVarsWithZeroNumCtr);
+
+  lsDestroy(remainingCtrInfoList,0);
+
+  /* Free the info arrays */
+
+  for (i=0; i<numRelation; i++) {
+    ctrInfo = array_fetch(CtrInfo_t*, ctrInfoArray, i);
+    CtrInfoStructFree(ctrInfo);
+  }
+  array_free(ctrInfoArray);
+
+  for (i=0; i<numVars; i++) {
+    varInfo = array_fetch(VarInfo_t*, varInfoArray, i);
+    assert(varInfo->numCtr == 0);
+    VarInfoStructFree(varInfo);
+  }
+  array_free(varInfoArray);
+
+  if (option->verbosity >= 3) {
+    int numRelation = array_n(*orderedRelationArrayPtr);
+
+    if (arraySmoothVarBddArrayPtr != NIL(array_t*)) {
+      PrintSmoothIntroducedCount(*orderedRelationArrayPtr,
+				 arraySmoothVarBddArrayPtr,
+				 domainVarBddIdArray,
+				 rangeVarBddIdArray);
+    }
+    if (option->verbosity >= 4) {
+      for (i= 0; i <numRelation; i++) {
+	st_table *supportTable;
+	(void) fprintf(vis_stdout, "Cluster # %d\n",i);
+	supportTable = ImgBddGetSupportIdTable(
+		       array_fetch(bdd_t*, *orderedRelationArrayPtr, i));
+	PrintBddIdTable(supportTable);
+	if (arraySmoothVarBddArrayPtr != NIL(array_t*)) {
+	  (void) fprintf(vis_stdout, "Exist cube # %d\n",i);
+	  PrintBddIdFromBddArray(array_fetch(array_t*,
+					     *arraySmoothVarBddArrayPtr, i));
+	}
+      }
+    }
+  }
+  FREE(sortedMaxIndexVector);
+  array_free(simplifiedRelationArray);
+
+  /* Free BDD Id arrays */
+  array_free(domainVarBddIdArray);
+  array_free(quantifyVarBddIdArray);
+  array_free(rangeVarBddIdArray);
+  array_free(domainAndQuantifyVarBddArray);
+  /* Free the st_tables */
+  st_free_table(bddIdToBddTable);
+  st_free_table(bddIdToVarInfoTable);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [This function takes an array of relations and quantifies out the
+               quantify variables which are local to a particular relation.]
+
+  Description [This function takes an array of relations and quantifies out the
+               quantify variables which are local to a particular relation.]
+
+  SideEffects [This function fills in the "numSmoothVars",
+               "numLocalSmoothVars", "numIntroducedVars", "maxSmoothVarIndex"
+               fields of ctrInfoStruct corresponding to each relation. It also
+               alters the "numCtr" and "ctrItemList" field of those quantify
+               variables which are quantified out in this function.]
+
+******************************************************************************/
+
+static array_t *
+RelationArraySmoothLocalVars(array_t *relationArray, array_t *ctrInfoArray,
+                             array_t *varInfoArray,
+			     st_table *bddIdToBddTable)
+{
+  array_t *arraySmoothVarBddArray, *smoothVarBddArray;
+  array_t *simplifiedRelationArray;
+  bdd_t *simplifiedRelation, *relation, *varBdd;
+  int maxSmoothVarIndexForAllCtr, i, numRelation;
+
+  numRelation = array_n(relationArray);
+
+  /*
+   * Initialize the array of cubes (of quantified variables which occur in
+   * only one relation), to be smoothed out.
+   */
+  arraySmoothVarBddArray = array_alloc(array_t*, 0);
+  for (i=0; i<numRelation; i++) {
+    smoothVarBddArray = array_alloc(bdd_t*, 0);
+    array_insert_last(array_t*, arraySmoothVarBddArray, smoothVarBddArray);
+  }
+
+  maxSmoothVarIndexForAllCtr = -1;
+  for (i=0; i<numRelation; i++) {
+    VarItem_t *varItem;
+    lsHandle varItemHandle;
+    CtrInfo_t *ctrInfo = array_fetch(CtrInfo_t*, ctrInfoArray, i);
+    int maxSmoothVarIndex = -1;
+    lsGen varItemListGen = lsStart(ctrInfo->varItemList);
+
+    smoothVarBddArray = array_fetch(array_t *, arraySmoothVarBddArray, i);
+    while (lsNext(varItemListGen, &varItem, &varItemHandle) ==
+	   LS_OK) {
+      int  varBddId;
+      VarInfo_t *varInfo = varItem->varInfo;
+      if (varInfo->varType == rangeVar_c) {
+	ctrInfo->numIntroducedVars++;
+      }
+      else if (varInfo->numCtr == 1) {
+	assert(lsLength(varInfo->ctrItemList) == 1);
+	if (varInfo->varType == quantifyVar_c) {
+	  /*
+	   * The variable can be smoothed out.
+	   * Put it in an array of variables to be
+	   * smoothed out from the relation.
+	   */
+	  CtrItem_t *ctrItem;
+	  varBddId = varInfo->bddId;
+	  st_lookup(bddIdToBddTable, (char *)(long)varBddId,&varBdd);
+	  array_insert_last(bdd_t*, smoothVarBddArray, bdd_dup(varBdd));
+	  varInfo->numCtr = 0;
+	  /* Remove the cluster from the ctrItemList of varInfo */
+	  lsRemoveItem(varItem->ctrItemHandle, &ctrItem);
+	  CtrItemStructFree(ctrItem);
+	  /* Remove the variable from the varItemList of ctrInfo.*/
+	  lsRemoveItem(varItemHandle, &varItem);
+	  VarItemStructFree(varItem);
+	  continue;
+	}
+	else {
+	  /* Increase the numLocalSmoothVars count of the corresponding ctr. */
+	  ctrInfo->numLocalSmoothVars++;
+	  ctrInfo->numSmoothVars++;
+	  if (maxSmoothVarIndex < varInfo->bddId) {
+	    maxSmoothVarIndex = varInfo->bddId;
+	  }
+	}
+      }
+      else{ /* varInfo->numCtr > 1 */
+	assert(varInfo->numCtr > 1);
+	ctrInfo->numSmoothVars++;
+	if (maxSmoothVarIndex < varInfo->bddId) {
+	  maxSmoothVarIndex = varInfo->bddId;
+	}
+      }
+    }
+    lsFinish(varItemListGen);
+    if (maxSmoothVarIndex >= 0) {
+      ctrInfo->maxSmoothVarIndex = maxSmoothVarIndex;
+    }
+    else{
+      ctrInfo->maxSmoothVarIndex = 0;
+    }
+    if (maxSmoothVarIndexForAllCtr < maxSmoothVarIndex) {
+      maxSmoothVarIndexForAllCtr = maxSmoothVarIndex;
+    }
+  }
+
+  /*
+   * Initialization Finished. We need to smooth out those quantify
+   * variables which appear in only one ctr.
+   */
+  simplifiedRelationArray = array_alloc(bdd_t*, 0);
+  for (i=0; i<numRelation; i++) {
+    relation = array_fetch(bdd_t*, relationArray, i);
+    smoothVarBddArray = array_fetch(array_t*, arraySmoothVarBddArray, i);
+    if (array_n(smoothVarBddArray) != 0)
+      simplifiedRelation = bdd_smooth(relation, smoothVarBddArray);
+    else
+      simplifiedRelation = bdd_dup(relation);
+    array_insert_last(bdd_t*, simplifiedRelationArray, simplifiedRelation);
+  }
+  mdd_array_array_free(arraySmoothVarBddArray);
+  return simplifiedRelationArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [An auxiliary routine for orderRelationArray to order the
+  clusters.]
+
+  Description [This routine is called by orderRelationArray after the
+  initialization is complete and the cluster relations are simplified wrt to
+  the quantify variable local to the cluster. The algorithm is:
+      While (there exists a cluster to be ordered) {
+         Calculate benefit for each unordered cluster.
+         Choose the cluster with the maximum benefit.
+         Update the cost function parameters.
+      }
+  ]
+
+  SideEffects [ctrInfo and varInfo structures are modified.]
+
+******************************************************************************/
+static void
+OrderRelationArrayAux(array_t *relationArray,
+                      lsList remainingCtrInfoList,
+                      array_t *ctrInfoArray,
+                      array_t *varInfoArray,
+                      int *sortedMaxIndexVector,
+                      int numSmoothVarsRemaining,
+                      int numIntroducedVarsRemaining,
+                      st_table *bddIdToBddTable,
+                      ImgTrmOption_t *option,
+                      array_t *domainAndQuantifyVarBddArray,
+                      array_t **orderedRelationArrayPtr,
+                      array_t **arraySmoothVarBddArrayPtr,
+		      array_t *arrayDomainQuantifyVarsWithZeroNumCtr)
+{
+  int numRelation, ctrCount, currentRankMaxSmoothVarIndex;
+  int maxIndex = 0;
+  array_t *orderedRelationArray, *arraySmoothVarBddArray;
+  array_t *smoothVarBddArray;
+  int *bestCtrIdVector;
+  int maxNumLocalSmoothVars, maxNumSmoothVars, maxNumIntroducedVars;
+  lsGen lsgen;
+
+  ctrCount = 0;
+  currentRankMaxSmoothVarIndex = 0;
+
+  numRelation = array_n(relationArray);
+
+  arraySmoothVarBddArray = NIL(array_t);
+  orderedRelationArray = array_alloc(bdd_t*, 0);
+  *orderedRelationArrayPtr = orderedRelationArray;
+  if (arraySmoothVarBddArrayPtr != NIL(array_t *)) {
+    arraySmoothVarBddArray = array_alloc(array_t*, 0);
+    *arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
+    array_insert_last(array_t*, arraySmoothVarBddArray,
+			arrayDomainQuantifyVarsWithZeroNumCtr);
+  }
+  bestCtrIdVector = ALLOC(int, numRelation);
+
+  while (ctrCount < numRelation) {
+    float bestBenefit, benefit;
+    int bestCtrId;
+    bdd_t *bestRelation;
+    lsGen ctrInfoListGen;
+    CtrInfo_t *ctrInfo, *ctrInfoAux;
+
+    bestBenefit = -1.0e20;	/* a safely small number */
+    bestCtrId = -1;
+    /* Find the maximum index of the remaining clusters */
+    while (currentRankMaxSmoothVarIndex < numRelation &&
+      (maxIndex = sortedMaxIndexVector[currentRankMaxSmoothVarIndex++]) == -1);
+
+    /* Calculate the maximum values of local smooth variables etc. */
+    maxNumLocalSmoothVars = 0;
+    maxNumSmoothVars = 0;
+    maxNumIntroducedVars = 0;
+    lsForEachItem(remainingCtrInfoList, lsgen, ctrInfo) {
+      if (ctrInfo->numLocalSmoothVars > maxNumLocalSmoothVars) {
+	maxNumLocalSmoothVars = ctrInfo->numLocalSmoothVars;
+      }
+      if (ctrInfo->numSmoothVars > maxNumSmoothVars) {
+	maxNumSmoothVars = ctrInfo->numSmoothVars;
+      }
+      if (ctrInfo->numIntroducedVars > maxNumIntroducedVars) {
+	maxNumIntroducedVars = ctrInfo->numIntroducedVars;
+      }
+    }
+
+    if (option->verbosity >= 4) {
+      fprintf(vis_stdout, "maxNumLocalSmoothVars = %3d maxNumSmoothVars = %3d ",
+	      maxNumLocalSmoothVars, maxNumSmoothVars);
+      fprintf(vis_stdout, "maxNumIntroducedVars = %3d\n", maxNumIntroducedVars);
+    }
+    /* Calculate the cost function of each of the cluster */
+    ctrInfoListGen = lsStart(remainingCtrInfoList);
+    while (lsNext(ctrInfoListGen, &ctrInfo, NIL(lsHandle)) ==
+	   LS_OK) {
+      benefit = CalculateBenefit(ctrInfo, maxNumLocalSmoothVars,
+				 maxNumSmoothVars, maxIndex,
+				 maxNumIntroducedVars, option);
+
+      if (option->verbosity >= 4) {
+	fprintf(vis_stdout,
+	  "id = %d: numLocalSmoothVars = %d numSmoothVars = %d benefit = %f\n",
+		ctrInfo->ctrId, ctrInfo->numLocalSmoothVars,
+		ctrInfo->numSmoothVars, benefit);
+      }
+      if (benefit > bestBenefit) {
+	bestBenefit = benefit;
+	bestCtrId = ctrInfo->ctrId;
+      }
+    }
+    lsFinish(ctrInfoListGen);
+    /*
+     * Insert the relation in the ordered array of relations and put in the
+     * appropriate cubes.
+     */
+
+    bestCtrIdVector[ctrCount] = bestCtrId;
+    ctrInfo = array_fetch(CtrInfo_t*, ctrInfoArray, bestCtrId);
+    lsRemoveItem(ctrInfo->ctrInfoListHandle, &ctrInfoAux);
+    assert(ctrInfo == ctrInfoAux);
+    bestRelation = array_fetch(bdd_t*, relationArray, bestCtrId);
+    array_insert_last(bdd_t*, orderedRelationArray, bestRelation);
+    if (option->verbosity >= 4) {
+      fprintf(vis_stdout,
+       "Best id = %d benefit = %f numLocalSmoothVars = %d numSmoothVars = %d\n",
+	      bestCtrId, bestBenefit, ctrInfo->numLocalSmoothVars,
+	      ctrInfo->numSmoothVars);
+    }
+    /*
+     * Update the remaining ctrInfo's and the varInfo's affected by choosing
+     * this cluster. Also get the array of smooth variables which can be
+     * quantified once this cluster is multiplied in the product.
+     */
+    smoothVarBddArray = UpdateInfoArrays(ctrInfo, bddIdToBddTable,
+					 &numSmoothVarsRemaining,
+					 &numIntroducedVarsRemaining);
+    assert(CheckCtrInfo(ctrInfo, numSmoothVarsRemaining, 0,
+			numIntroducedVarsRemaining));
+
+    if (arraySmoothVarBddArrayPtr != NIL(array_t *)) {
+      if (ctrCount == numRelation-1) {
+	/*
+	 * In the last element of arraySmoothVarBddArray, put all the domain
+	 * and quantify variables (in case some of them were not in the support
+	 * of any cluster).
+	 */
+	int		i, j;
+	st_table	*varsTable = st_init_table((ST_PFICPCP)bdd_ptrcmp,
+						   (ST_PFICPI)bdd_ptrhash);
+	array_t		*tmpVarBddArray;
+	mdd_t		*tmpVar;
+
+	arrayForEachItem(array_t *, arraySmoothVarBddArray, i, tmpVarBddArray) {
+	  arrayForEachItem(mdd_t *, tmpVarBddArray, j, tmpVar) {
+	    st_insert(varsTable, (char *)tmpVar, NIL(char));
+	  }
+	}
+	arrayForEachItem(mdd_t *, smoothVarBddArray, i, tmpVar) {
+	  st_insert(varsTable, (char *)tmpVar, NIL(char));
+	}
+	arrayForEachItem(mdd_t *, domainAndQuantifyVarBddArray, i, tmpVar) {
+	  if (st_lookup(varsTable, (char *)tmpVar, NIL(char *)) == 0)
+	    array_insert_last(mdd_t *, smoothVarBddArray, mdd_dup(tmpVar));
+	}
+	st_free_table(varsTable);
+      }
+      array_insert_last(array_t*, arraySmoothVarBddArray, smoothVarBddArray);
+    }
+    else{
+      mdd_array_free(smoothVarBddArray);
+    }
+    sortedMaxIndexVector[ctrInfo->rankMaxSmoothVarIndex] = -1;
+    ctrCount++;
+  }
+  assert(numIntroducedVarsRemaining == 0);
+  assert(numSmoothVarsRemaining == 0);
+  if (option->verbosity >= 3) {
+    int i;
+    (void) fprintf(vis_stdout,"Cluster Sequence = ");
+    for (i=0; i<numRelation; i++) {
+      (void) fprintf(vis_stdout, "%d ", bestCtrIdVector[i]);
+    }
+    (void) fprintf(vis_stdout,"\n");
+  }
+
+  FREE(bestCtrIdVector);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [This function computes the set of variables which can be
+  smoothed out once a particular cluster is chosen to be multiplied in the
+  product.]
+
+  Description [The support variable list (varItemList) of the cluster (ctrInfo)
+  is traversed and depending upon the type of the variable and the number of
+  unordered clustered relations which depend on that variable following actions
+  are taken:
+
+  a. If the variable is of range type:
+     This implies that this variable is appearing for the first time in the
+     product. Since it is already introduced in the product, the cost function
+     of any other unordered relation which depends on this variable will get
+     modified. The numIntroducedVariables field of each of the cluster which
+     depends on this variable is decreased by 1. Also this varItemStruct
+     corresponding to this variable is removed from the varItemList field of
+     the cluster.
+
+  b. If the variable is of domain or quantify type:
+    b1. If number of clusters which depend on this variable is 1 (numCtr == 1):
+           In this case, this variable can be quantified out once the chosen
+           cluster is multiplied in the product. Hence the variable is put in
+           the smoothVarBddArray.
+    b2. If  (numCtr == 2)
+           In this case, there is one more unordered cluster which depends on
+           this variable. But once the current cluster is multiplied in the
+           product, the "numLocalSmoothVars" field of ctrInfo corresponding to
+           the other dependent cluster needs to be increased by 1.
+     b3. If (numCtr > 2)
+           In this case, we just need to decrease the numCtr of the variable by
+           1.
+
+  In any case, for each varInfo in the support variable list (varItemList) of
+  the cluster (ctrInfo) the following invariant is maintained:
+  varInfo->numCtr == lsLength(varInfo->ctrItemList)
+  ]
+
+  SideEffects [The fields of ctrInfo and varInfo are changed as mentioned
+  above.]
+
+******************************************************************************/
+static array_t *
+UpdateInfoArrays(CtrInfo_t *ctrInfo, st_table *bddIdToBddTable,
+                 int *numSmoothVarsRemainingPtr,
+                 int *numIntroducedVarsRemainingPtr)
+{
+  array_t *smoothVarBddArray;
+  lsGen varItemListGen;
+  int numSmoothVarsRemaining = *numSmoothVarsRemainingPtr;
+  int numIntroducedVarsRemaining = *numIntroducedVarsRemainingPtr;
+  VarItem_t *varItem;
+  lsHandle varItemHandle;
+
+  smoothVarBddArray = array_alloc(bdd_t*, 0);
+  varItemListGen = lsStart(ctrInfo->varItemList);
+  while (lsNext(varItemListGen, &varItem, &varItemHandle) ==
+	 LS_OK) {
+    VarInfo_t *varInfo = varItem->varInfo;
+    CtrItem_t *ctrItem;
+    assert(varInfo->numCtr == lsLength(varInfo->ctrItemList));
+    lsRemoveItem(varItem->ctrItemHandle,  &ctrItem);
+    CtrItemStructFree(ctrItem);
+    varInfo->numCtr--;
+    lsRemoveItem(varItemHandle, &varItem);
+    VarItemStructFree(varItem);
+
+    /*
+     * If this variable is to be smoothed (domain or quantify type) and
+     * the numCtr is 1, then it should be added to the smoothVarBddArray,
+     * otherwise, the numCtr should be decreased by 1.
+     * If the variable is of the range type then the number of introduced
+     * vars remaining and the number of introduced vars should be
+     * appropriately modified.
+     */
+    if ((varInfo->varType == domainVar_c) ||
+	(varInfo->varType == quantifyVar_c)) {
+      if (varInfo->numCtr == 0) {
+	bdd_t *varBdd;
+	st_lookup(bddIdToBddTable, (char *)(long)(varInfo->bddId), &varBdd);
+	array_insert_last(bdd_t*, smoothVarBddArray, bdd_dup(varBdd));
+	numSmoothVarsRemaining--;
+	ctrInfo->numLocalSmoothVars--;
+	ctrInfo->numSmoothVars--;
+      }
+      else{
+	if (varInfo->numCtr == 1) {
+	  /*
+	   * We need to update the numLocalSmoothVars of the ctr
+	   * which depends on it.
+	   */
+	  lsFirstItem(varInfo->ctrItemList, &ctrItem, LS_NH);
+	  ctrItem->ctrInfo->numLocalSmoothVars++;
+	}
+	/*
+	 * else varInfo->numCtr > 1 : Nothing to be done because neither it
+	 * can be quantified out, nor it is effecting any cost function.
+	 */
+	ctrInfo->numSmoothVars--;
+      }
+    }
+    else{/* The variable is of range type, so need to appropriately modify the
+	  * numIntroducedVars of those clusters which contain this range
+	  * variable in their support.
+	  */
+      lsHandle ctrItemHandle;
+      lsGen ctrItemListGen = lsStart(varInfo->ctrItemList);
+      ctrInfo->numIntroducedVars--;
+      while (lsNext(ctrItemListGen, &ctrItem, &ctrItemHandle) == LS_OK) {
+	ctrItem->ctrInfo->numIntroducedVars--;
+	lsRemoveItem(ctrItem->varItemHandle,&varItem);
+	lsRemoveItem(ctrItemHandle,&ctrItem);
+	VarItemStructFree(varItem);
+	CtrItemStructFree(ctrItem);
+      }
+      lsFinish(ctrItemListGen);
+      numIntroducedVarsRemaining--;
+      varInfo->numCtr = 0;
+    }
+    assert(varInfo->numCtr == lsLength(varInfo->ctrItemList));
+  }
+  lsFinish(varItemListGen);
+  *numIntroducedVarsRemainingPtr = numIntroducedVarsRemaining;
+  *numSmoothVarsRemainingPtr = numSmoothVarsRemaining;
+  return smoothVarBddArray;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the necessary options for computing the image and returns
+               in the option structure.]
+
+  Description [
+       The strategy
+       Choose the cost function:
+       The objective function attached with each Ti is
+       Ci =  W1 C1i + W2 C2i + W3 C3i - W4C4i
+       where:
+       W1 = weight attached with variable getting smoothed
+       W2 = weight attached with the support count of the Ti
+       W3 = weight attached with the max id of the Ti
+       W4 = weight attached with variable getting introduced
+       C1i = Ui/Vi
+       C2i = Vi/Wi
+       C3i = Mi/Max
+       C4i = Xi/Yi
+       Ui = number of variables getting smoothed
+       Vi = number of ps support variables of Ti
+       Wi = total number of ps variables remaining which have not been
+            smoothed out
+       Mi = value of Max id of Ti
+       Max = value of Max id across all the Ti's remaining to be multiplied
+       Xi = number of ns variables introduced
+       Yi = total number of ns variables which have not been introduced so
+            far.
+       Get the weights from the global option]
+
+  SideEffects []
+
+******************************************************************************/
+static float
+CalculateBenefit(CtrInfo_t *ctrInfo, int maxNumLocalSmoothVars, int
+                 maxNumSmoothVars, int maxIndex, int
+                 maxNumIntroducedVars, ImgTrmOption_t *option)
+{
+  int W1, W2, W3, W4;
+  float benefit;
+
+  W1 = option->W1;
+  W2 = option->W2;
+  W3 = option->W3;
+  W4 = option->W4;
+
+  benefit = 0.0;
+  benefit += (maxNumLocalSmoothVars ?
+	      ((float)W1 * ((float)ctrInfo->numLocalSmoothVars /
+		(float)maxNumLocalSmoothVars)) : 0.0);
+
+  benefit += (maxNumSmoothVars ?
+	      ((float)W2 * ((float)ctrInfo->numSmoothVars /
+		(float)maxNumSmoothVars)) : 0.0);
+
+  benefit += (maxIndex ?
+	      ((float)W3 * ((float)ctrInfo->maxSmoothVarIndex /
+		(float)maxIndex)) : 0.0);
+
+  benefit -= (maxNumIntroducedVars ?
+	      ((float)W4 * ((float)ctrInfo->numIntroducedVars /
+		(float)maxNumIntroducedVars)) : 0.0);
+
+  return benefit;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the option values used in IWLS95 techinique for
+  image computation.]
+
+  Description [Prints the option values used in IWLS95 techinique for
+  image computation.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+PrintOption(Img_MethodType method, ImgTrmOption_t *option, FILE *fp)
+{
+  if (method == Img_Iwls95_c)
+    (void)fprintf(fp, "Printing Information about Image method: IWLS95\n");
+  else if (method == Img_Mlp_c)
+    (void)fprintf(fp, "Printing Information about Image method: MLP\n");
+  else if (method == Img_Linear_c)
+    (void)fprintf(fp, "Printing Information about Image method: LINEAR\n");
+  else
+    assert(0);
+  (void)fprintf(fp,
+		"\tThreshold Value of Bdd Size For Creating Clusters = %d\n",
+		option->clusterSize);
+  (void)fprintf(fp,
+  "\t\t(Use \"set image_cluster_size value\" to set this to desired value)\n");
+  (void)fprintf(fp, "\tVerbosity = %d\n", option->verbosity);
+  (void)fprintf(fp,
+    "\t\t(Use \"set image_verbosity value\" to set this to desired value)\n");
+  if (method == Img_Iwls95_c) {
+    (void)fprintf(fp, "\tW1 =%3d W2 =%2d W3 =%2d W4 =%2d\n",
+		  option->W1, option->W2, option->W3, option->W4);
+    (void)fprintf(fp,
+	"\t\t(Use \"set image_W? value\" to set these to desired values)\n");
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates and initializes the info structure for IWLS95
+  technique.]
+
+  Description [Allocates and initializes the info structure for IWLS95
+  technique.]
+
+  SideEffects []
+
+******************************************************************************/
+static Iwls95Info_t *
+Iwls95InfoStructAlloc(Img_MethodType method)
+{
+  Iwls95Info_t *info;
+  info = ALLOC(Iwls95Info_t, 1);
+  memset(info, 0, sizeof(Iwls95Info_t));
+  info->method = method;
+  info->option = TrmGetOptions();
+  info->PIoption = ImgGetPartialImageOptions();
+  return info;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates and initializes memory for ctrInfoStruct.]
+
+  Description [Allocates and initializes memory for ctrInfoStruct.]
+
+  SideEffects []
+
+******************************************************************************/
+static CtrInfo_t *
+CtrInfoStructAlloc(void)
+{
+  CtrInfo_t *ctrInfo;
+  ctrInfo = ALLOC(CtrInfo_t, 1);
+  ctrInfo->ctrId = -1;
+  ctrInfo->numLocalSmoothVars = 0;
+  ctrInfo->numSmoothVars = 0;
+  ctrInfo->maxSmoothVarIndex = -1;
+  ctrInfo->numIntroducedVars = 0;
+  ctrInfo->varItemList = lsCreate();
+  ctrInfo->ctrInfoListHandle = NULL;
+  return ctrInfo;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the memory associated with ctrInfoStruct.]
+
+  Description [Frees the memory associated with ctrInfoStruct.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+CtrInfoStructFree(CtrInfo_t *ctrInfo)
+{
+  lsDestroy(ctrInfo->varItemList, 0);
+  FREE(ctrInfo);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates and initializes memory for varInfoStruct.]
+
+  Description [Allocates and initializes memory for varInfoStruct.]
+
+  SideEffects []
+
+******************************************************************************/
+static VarInfo_t *
+VarInfoStructAlloc(void)
+{
+  VarInfo_t *varInfo;
+  varInfo = ALLOC(VarInfo_t, 1);
+  varInfo->bddId = -1;
+  varInfo->numCtr = 0;
+  varInfo->varType = -1;
+  varInfo->ctrItemList = lsCreate();
+  return varInfo;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the memory associated with varInfoStruct.]
+
+  Description [Frees the memory associated with varInfoStruct.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+VarInfoStructFree(VarInfo_t *varInfo)
+{
+  lsDestroy(varInfo->ctrItemList,0);
+  FREE(varInfo);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the memory associated with CtrItemStruct]
+
+  Description [Frees the memory associated with CtrItemStruct]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+CtrItemStructFree(CtrItem_t *ctrItem)
+{
+  FREE(ctrItem);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the memory associated with VarItemStruct]
+
+  Description [Frees the memory associated with VarItemStruct]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+VarItemStructFree(VarItem_t *varItem)
+{
+  FREE(varItem);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Compare function used to sort the ctrInfoStruct based on the
+  maxSmoothVarIndex field.]
+
+  Description [This function is used to sort the array of clusters based on the
+  maximum index of the support variable.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CtrInfoMaxIndexCompare(const void * p1, const void * p2)
+{
+  CtrInfo_t **infoCtr1 = (CtrInfo_t **) p1;
+  CtrInfo_t **infoCtr2 = (CtrInfo_t **) p2;
+  return ((*infoCtr1)->maxSmoothVarIndex > (*infoCtr2)->maxSmoothVarIndex);
+}
+
+/* **************************************************************************
+ * Debugging Related Routines.
+ ***************************************************************************/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the CtrInfo_t data structure.]
+
+  Description [Prints the CtrInfo_t data structure.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+PrintCtrInfoStruct(CtrInfo_t *ctrInfo)
+{
+  lsGen lsgen;
+  VarItem_t *varItem;
+
+  (void) fprintf(vis_stdout,"Ctr ID = %d\tNumLocal = %d\tNumSmooth=%d\tNumIntro=%d\tmaxSmooth=%d\trank=%d\n",
+		 ctrInfo->ctrId, ctrInfo->numLocalSmoothVars,
+		 ctrInfo->numSmoothVars, ctrInfo->numIntroducedVars,
+		 ctrInfo->maxSmoothVarIndex, ctrInfo->rankMaxSmoothVarIndex);
+  lsgen = lsStart(ctrInfo->varItemList);
+  while (lsNext(lsgen, &varItem, NIL(lsHandle)) == LS_OK) {
+    (void) fprintf(vis_stdout,"%d\t", varItem->varInfo->bddId);
+  }
+  lsFinish(lsgen);
+  fprintf(vis_stdout,"\n");
+}
+/**Function********************************************************************
+
+  Synopsis    [Prints the VarInfo_t structure.]
+
+  Description [Prints the VarInfo_t structure.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+PrintVarInfoStruct(VarInfo_t *varInfo)
+{
+  lsGen lsgen;
+  CtrItem_t *ctrItem;
+
+  (void) fprintf(vis_stdout,"Var ID = %d\tNumCtr = %d\tVarType=%d\n",
+		 varInfo->bddId, varInfo->numCtr, varInfo->varType);
+  lsgen = lsStart(varInfo->ctrItemList);
+  while (lsNext(lsgen, &ctrItem, NIL(lsHandle)) == LS_OK) {
+    (void) fprintf(vis_stdout,"%d\t", ctrItem->ctrInfo->ctrId);
+  }
+  lsFinish(lsgen);
+  fprintf(vis_stdout,"\n");
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Given an array of BDD's representing the relations and another
+  array of BDD cubes (in the form of array of bdd_t of variable) representing
+  the quantification schedule, this function checks if the schedule is correct.
+  ]
+
+  Description [Assume Ci represents the ith cube in the array and the Ti
+  represents the ith relation. The correctness of the schedule is defined as
+  follows:
+      a. For all Tj: j > i, SUP(Tj) and SUP(Ci) do not intersect, i.e., the
+      variables which are quantified in Ci should not appear in the Tj for j>i.
+      b. For any i, j, SUP(Ci) and SUP(Cj) do not intersect. However this is
+      not true for the last cube (Cn-1). This is because the last cube contains
+      all the smooth variables.
+  ]
+  SideEffects []
+
+******************************************************************************/
+static int
+CheckQuantificationSchedule(array_t *relationArray,
+                            array_t *arraySmoothVarBddArray)
+{
+  int i, j;
+  long varId;
+  st_table *smoothVarTable, *supportTable;
+  bdd_t *relation;
+  array_t *smoothVarBddArray, *smoothVarBddIdArray;
+  st_generator *stgen;
+
+  assert(array_n(relationArray) + 1 == array_n(arraySmoothVarBddArray));
+
+  smoothVarTable = st_init_table(st_numcmp, st_numhash);
+
+  smoothVarBddArray = array_fetch(array_t*, arraySmoothVarBddArray, 0);
+  smoothVarBddIdArray = bdd_get_varids(smoothVarBddArray);
+  for (j=0; j<array_n(smoothVarBddIdArray); j++) {
+    varId = (long) array_fetch(int, smoothVarBddIdArray, j);
+    assert(st_insert(smoothVarTable, (char *) varId, NIL(char))==0);
+  }
+  array_free(smoothVarBddIdArray);
+
+  for (i=0; i<array_n(relationArray); i++) {
+    relation = array_fetch(bdd_t*, relationArray, i);
+    supportTable = ImgBddGetSupportIdTable(relation);
+    /*
+     * Check that none of the variables in the support have already been
+     * quantified.
+     */
+    st_foreach_item(supportTable, stgen, &varId, NULL) {
+      assert(st_is_member(smoothVarTable, (char *) varId) == 0);
+
+    }
+    st_free_table(supportTable);
+    if (i == (array_n(relationArray)-1)) {
+      /* Since last element of arraySmoothVarBddArray has all the
+       * smooth variables, it will not satisfy the condition.
+       */
+      continue;
+    }
+
+    /*
+     * Put each of the variables quantified at this step in the
+     * smoothVarTable. And check that none of these smooth variables
+     * have been introduced before.
+     */
+    smoothVarBddArray = array_fetch(array_t*, arraySmoothVarBddArray, i + 1);
+    smoothVarBddIdArray = bdd_get_varids(smoothVarBddArray);
+    for (j=0; j<array_n(smoothVarBddIdArray); j++) {
+      varId = (long) array_fetch(int, smoothVarBddIdArray, j);
+      assert(st_insert(smoothVarTable, (char *) varId, NIL(char))==0);
+    }
+    array_free(smoothVarBddIdArray);
+  }
+  st_free_table(smoothVarTable);
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Checks the validity of an array of CtrInfoStructs.]
+
+  Description [Checks the validity of an array of CtrInfoStructs.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CheckCtrInfoArray(array_t *ctrInfoArray, int numDomainVars, int
+                  numQuantifyVars, int numRangeVars)
+{
+  int i;
+  for (i=0; i<array_n(ctrInfoArray); i++) {
+    CheckCtrInfo(array_fetch(CtrInfo_t *, ctrInfoArray, i),
+		 numDomainVars, numQuantifyVars, numRangeVars);
+  }
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Checks the validity of a CtrInfoStruct.]
+
+  Description [Checks the validity of a CtrInfoStruct.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CheckCtrInfo(CtrInfo_t *ctrInfo, int numDomainVars,
+	     int numQuantifyVars, int numRangeVars)
+{
+  assert(ctrInfo->numLocalSmoothVars <= (numDomainVars +
+					 numQuantifyVars));
+  assert(ctrInfo->numSmoothVars <= (numDomainVars +
+				    numQuantifyVars));
+  assert(ctrInfo->numIntroducedVars <= numRangeVars);
+  assert(lsLength(ctrInfo->varItemList) ==
+	 (ctrInfo->numSmoothVars+ctrInfo->numIntroducedVars));
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Checks the validity of an array of VarInfoStruct.]
+
+  Description [Checks the validity of an array of VarInfoStruct.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CheckVarInfoArray(array_t *varInfoArray, int numRelation)
+{
+  int i;
+  for (i=0; i<array_n(varInfoArray); i++) {
+    VarInfo_t *varInfo;
+    varInfo = array_fetch(VarInfo_t *, varInfoArray, i);
+    assert(varInfo->numCtr <= numRelation);
+    assert(varInfo->varType >= 0);
+    assert(varInfo->varType <= 2);
+    assert(lsLength(varInfo->ctrItemList) == varInfo->numCtr);
+  }
+  return 1;
+}
+
+/* ****************************************************************
+ * Utility Routines.
+ ****************************************************************/
+
+/**Function********************************************************************
+
+  Synopsis    [Duplicates an array of BDDs.]
+
+  Description [Duplicates an array of BDDs.]
+
+  SideEffects []
+
+******************************************************************************/
+static array_t *
+BddArrayDup(array_t *bddArray)
+{
+  int i;
+  array_t *resultArray;
+  bdd_t *bdd;
+  resultArray = array_alloc(bdd_t*, 0);
+  arrayForEachItem(bdd_t *, bddArray, i, bdd) {
+    array_insert_last(bdd_t*, resultArray, bdd_dup(bdd));
+  }
+  return resultArray;
+}
+
+static array_t *
+BddArrayArrayDup(array_t *bddArray)
+{
+  int i;
+  array_t *resultArray;
+  array_t *arr, *tarr;
+
+  resultArray = array_alloc(bdd_t*, 0);
+  arrayForEachItem(array_t *, bddArray, i, arr) {
+    tarr = BddArrayDup(arr);
+    array_insert_last(array_t*, resultArray, tarr);
+  }
+  return resultArray;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns a BDD after taking the product of fromSet with the
+  BDDs in the relationArray and quantifying out the variables using
+  the schedule given in the arraySmoothVarBddArray.]
+
+  Description [The product is taken from the left, i.e., fromSet is
+  multiplied with relationArray[0]. The array of variables given by
+  arraySmoothVarBddArray[i] are quantified when the relationArray[i]
+  is multiplied in the product. We notice that no simplification is
+  used in the computation. It was found to be the fastest way to
+  compute the image. When partial image is allowed, a partial image is
+  computed based on the method specified. If the method is "approx",
+  approximation is applied to some intermediate product. If the method
+  is "clipping", clipping is introduced during and-abstract. A flag
+  partial is set to indicate to the calling procedure that a partial
+  image was computed as against an exact image. Partial flag comes in
+  indicating whether partial images are allowed, and leave indicating
+  whether the image was partial or not. ]
+
+  SideEffects [partial is set when some approximation is applied]
+
+******************************************************************************/
+static mdd_t *
+BddLinearAndSmooth(mdd_manager *mddManager,
+                   bdd_t *fromSet,
+                   array_t *relationArray,
+                   array_t *arraySmoothVarBddArray,
+                   array_t *smoothVarCubeArray,
+		   int verbosity,
+		   ImgPartialImageOption_t *PIoption,
+		   boolean *partial, boolean lazySiftFlag)
+{
+  int i;
+  int intermediateSize = 0;
+  int maxSize = 0;
+  mdd_t *newProduct;
+  boolean partialImageAllowed;
+  bdd_t *product = fromSet;
+  int clippingDepth = -1;
+  int partialImageThreshold = 0;
+  int partialImageMethod = Img_PIApprox_c;
+  array_t *smoothVarBddArray = NIL(array_t);
+  mdd_t *smoothVarCube = NIL(mdd_t);
+  int nvars = -2;
+
+  assert(CheckQuantificationSchedule(relationArray, arraySmoothVarBddArray));
+
+   /* Copy (*partial) which indicates whether partial image is allowed. */
+  /* (*partial) is set to TRUE later if partial image was performed. */
+  partialImageAllowed = *partial;
+  *partial = FALSE;
+
+  /* partial image options */
+  if (PIoption != NULL) {
+    nvars = PIoption->nvars;
+    clippingDepth = (int) (PIoption->clippingDepthFrac*nvars);
+    partialImageThreshold = PIoption->partialImageThreshold;
+    partialImageMethod = PIoption->partialImageMethod;
+  }
+
+  if (fromSet) {
+    if (smoothVarCubeArray) {
+      smoothVarCube = array_fetch(mdd_t*, smoothVarCubeArray, 0);
+      if (bdd_is_tautology(smoothVarCube, 1))
+	product = bdd_dup(fromSet);
+      else
+	product = bdd_smooth_with_cube(fromSet, smoothVarCube);
+    } else {
+      smoothVarBddArray = array_fetch(array_t*, arraySmoothVarBddArray, 0);
+      if (array_n(smoothVarBddArray) == 0)
+	product = bdd_dup(fromSet);
+      else
+	product = bdd_smooth(fromSet, smoothVarBddArray);
+    }
+  } else
+    product = bdd_one(mddManager);
+
+  for (i=0; i<array_n(relationArray); i++) {
+    bdd_t *relation, *tmpProduct;
+    boolean allowClipping = FALSE;
+
+    /* fetch relation to intersect with the next product. */
+    relation = array_fetch(bdd_t*, relationArray, i);
+    if (smoothVarCubeArray)
+      smoothVarCube = array_fetch(mdd_t*, smoothVarCubeArray, i + 1);
+    else
+      smoothVarBddArray = array_fetch(array_t*, arraySmoothVarBddArray, i + 1);
+
+    /* Clipping allowed only if clipping option is specified, partial
+     * image is allowed, clipping depth is meaningful and sizes are not
+     * under control.
+     */
+    if ((PIoption != NULL)  &&
+	(partialImageAllowed) &&
+	(partialImageMethod == Img_PIClipping_c) &&
+	(nvars >= clippingDepth)) {
+      /* if conjuncts too small, dont clip. */
+      if ((bdd_size(product) > partialImageThreshold) ||
+	  (bdd_size(relation) > partialImageThreshold)) {
+	allowClipping = TRUE;
+      }
+    }
+
+    if (lazySiftFlag) {
+      int j;
+      int nVars = bdd_num_vars(mddManager);
+      var_set_t *sup_ids = bdd_get_support(relation);
+
+      for (j = 0; j < nVars; j++) {
+	if (var_set_get_elt(sup_ids, j) == 1) {
+	  if (bdd_is_ns_var(mddManager, j))
+	    bdd_reset_var_to_be_grouped(mddManager, j);
+	  else if (!bdd_is_ps_var(mddManager, j))
+	    bdd_reset_var_to_be_grouped(mddManager, j);
+	}
+      }
+      var_set_free(sup_ids);
+    }
+
+    /* if clipping not allowed, do regular and-abstract */
+    if (!allowClipping) {
+      if (smoothVarCubeArray) {
+	if (bdd_is_tautology(smoothVarCube, 1))
+	  tmpProduct = bdd_and(product, relation, 1, 1);
+	else {
+	  tmpProduct = bdd_and_smooth_with_cube(product, relation,
+						smoothVarCube);
+	}
+      } else {
+	if (array_n(smoothVarBddArray) == 0)
+	  tmpProduct = bdd_and(product, relation, 1, 1);
+	else
+	  tmpProduct = bdd_and_smooth(product, relation, smoothVarBddArray);
+      }
+    } else {
+      /* the conditions to clip are that partial image is allowed,
+       * partial image method is set to clipping, clipping depth
+       * is meaningful and either the product or the relation is
+       * larger than the partial image threshold.
+       */
+      if (smoothVarCubeArray)
+	smoothVarBddArray = array_fetch(array_t*, arraySmoothVarBddArray, i+1);
+      tmpProduct = ComputeClippedAndAbstract(product, relation,
+					     smoothVarBddArray, nvars,
+					     clippingDepth, partial, verbosity);
+    }
+
+    if (lazySiftFlag) {
+      int k, index;
+      bdd_t *svar;
+
+      if (smoothVarCubeArray)
+	smoothVarBddArray = array_fetch(array_t*, arraySmoothVarBddArray, i+1);
+      for (k = 0; k < array_n(smoothVarBddArray); k++) {
+        svar = array_fetch(bdd_t *, smoothVarBddArray, k);
+	index = bdd_top_var_id(svar);
+        bdd_set_var_to_be_grouped(mddManager, index);
+      }
+    }
+
+    bdd_free(product);
+    product = tmpProduct;
+
+    /* subset if necessary */
+    if ((i != array_n(relationArray)) &&
+	(partialImageAllowed) &&
+	(partialImageMethod == Img_PIApprox_c)) {
+      intermediateSize = bdd_size(product);
+      /* approximate if the intermediate product is too large. */
+      if (intermediateSize > partialImageThreshold) {
+	if (verbosity >= 2) {
+	  (void) fprintf(vis_stdout, "Intermediate Block %d Size = %10d\n", i,
+			 intermediateSize);
+	}
+	newProduct = ComputeSubsetOfIntermediateProduct(product, PIoption);
+	if (verbosity >= 2) {
+	  if (!bdd_equal(newProduct, product)) {
+	    (void)fprintf(vis_stdout,
+			  "Intermediate Block Subset Size = %10d\n",
+			  bdd_size(newProduct));
+	  } else {
+	    (void)fprintf(vis_stdout, "Intermediate Block unchanged\n");
+	  }
+	}
+	/* record if partial image occurred */
+	if (!bdd_equal(newProduct, product)) {
+	  *partial = TRUE;
+	  intermediateSize = bdd_size(product);
+	}
+	bdd_free(product);
+	product = newProduct;
+      }
+    }
+
+    /* keep track of intermediate product size */
+    if (verbosity >= 2) {
+      if ((partialImageMethod  != Img_PIApprox_c) ||
+	  (!partialImageAllowed) ||
+	  ( i == array_n(relationArray))) {
+	intermediateSize = bdd_size(product);
+      }
+      if (maxSize < intermediateSize) {
+	maxSize = intermediateSize;
+      }
+    }
+  }
+  if (lazySiftFlag) {
+    int nVars = bdd_num_vars(mddManager);
+    for (i = 0; i < nVars; i++) {
+      if (bdd_is_ps_var(mddManager, i))
+	bdd_reset_var_to_be_grouped(mddManager, i);
+      else
+	bdd_set_var_to_be_grouped(mddManager, i);
+    }
+  }
+  if (verbosity >= 2) {
+    (void)fprintf(vis_stdout,
+		  "Max. BDD size for intermediate product = %10d\n", maxSize);
+  }/* for all clusters */
+  
+  return product;
+} /* end of BddLinearAndSmooth */
+
+/**Function********************************************************************
+
+  Synopsis    [Hashes bdd id to bdd in the table.]
+
+  Description [The elements of the input array should be in one to one
+  correpondence, i.e., idArray[i] should be the id of the variable
+  bddArray[i]. Each element of idArray is hashed in the table with the value
+  taken from the corresponding element from bddArray.]
+
+  SideEffects []
+
+******************************************************************************/
+
+static void
+HashIdToBddTable(st_table *table, array_t *idArray,
+		 array_t *bddArray)
+{
+  int i;
+  for (i=0; i<array_n(idArray); i++) {
+    int id;
+    bdd_t *bdd;
+    id = array_fetch(int, idArray, i);
+    bdd = array_fetch(bdd_t*, bddArray, i);
+    st_insert(table, (char*)(long)id, (char *)bdd);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints information about the schedule of clusters and
+  the the corresponding smooth cubes.]
+
+  Description [This function is used to print information about the
+  cluster sequence and the sequence of smooth cubes. For each cluster
+  in sequence, it prints the number of variables quantified and the
+  number of variables introduced.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+PrintSmoothIntroducedCount(array_t *clusterArray, array_t
+                           **arraySmoothVarBddArrayPtr,
+                           array_t *psBddIdArray, array_t
+                           *nsBddIdArray)
+{
+  int i,j;
+  st_table *nsBddIdTable, *supportTable, *psBddIdTable;
+  bdd_t *trans;
+  int introducedCount;
+  bdd_t *tmp;
+  st_generator *stgen;
+  long varId;
+  array_t *smoothVarBddArray, *arraySmoothVarBddArray;
+  array_t *smoothVarBddIdArray = NIL(array_t);
+  int psCount, piNdCount;
+
+  if (arraySmoothVarBddArrayPtr == NIL(array_t*))
+    arraySmoothVarBddArray = NIL(array_t);
+  else
+    arraySmoothVarBddArray = *arraySmoothVarBddArrayPtr;
+
+  (void) fprintf(vis_stdout, "**********************************************\n");
+  nsBddIdTable = st_init_table(st_numcmp, st_numhash);
+  for (i=0; i<array_n(nsBddIdArray); i++)
+    st_insert(nsBddIdTable, (char *)(long) array_fetch(int, nsBddIdArray, i),
+	      (char *) NULL);
+  psBddIdTable = st_init_table(st_numcmp, st_numhash);
+  for (i=0; i<array_n(psBddIdArray); i++)
+    st_insert(psBddIdTable, (char *)(long) array_fetch(int, psBddIdArray, i),
+	      (char *) NULL);
+
+  for (i=0; i<=array_n(clusterArray)-1; i++) {
+    trans = array_fetch(bdd_t*, clusterArray, i);
+    supportTable = ImgBddGetSupportIdTable(trans);
+    psCount = 0;
+    piNdCount = 0;
+    if (arraySmoothVarBddArray != NIL(array_t)) {
+      smoothVarBddArray = array_fetch(array_t*, arraySmoothVarBddArray, i);
+      smoothVarBddIdArray = bdd_get_varids(smoothVarBddArray);
+      for (j=0; j<array_n(smoothVarBddIdArray);j++) {
+	if (st_is_member(psBddIdTable, (char *)(long)
+			 array_fetch(int, smoothVarBddIdArray, j)))
+	  psCount++;
+	else
+	  piNdCount++;
+      }
+    }
+    introducedCount = 0;
+    st_foreach_item(nsBddIdTable, stgen, &varId, &tmp) {
+      if (st_is_member(supportTable, (char *)varId)) {
+	introducedCount++;
+	st_delete(nsBddIdTable,&varId, NULL);
+      }
+    }
+    (void)fprintf(vis_stdout,
+    "Tr no = %3d\tSmooth PS # = %3d\tSmooth PI # = %3d\tIntroduced # = %d\n", i,
+		  psCount, piNdCount, introducedCount);
+    st_free_table(supportTable);
+    array_free(smoothVarBddIdArray);
+  }
+  st_free_table(nsBddIdTable);
+  st_free_table(psBddIdTable);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Prints Ids of an array of BDDs.]
+
+  Description [Prints Ids of an array of BDDs.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+PrintBddIdFromBddArray(array_t *bddArray)
+{
+  int i;
+  array_t *idArray = bdd_get_varids(bddArray);
+  fprintf(vis_stdout,
+	  "**************** printing bdd ids from the bdd array ***********\n");
+  fprintf(vis_stdout,"%d::\t", array_n(idArray));
+  for (i=0;i<array_n(idArray); i++) {
+    fprintf(vis_stdout," %d ", (int)array_fetch(int, idArray, i));
+  }
+  fprintf(vis_stdout,"\n******************\n");
+  array_free(idArray);
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the integers from a symbol table.]
+
+  Description [Prints the integers from a symbol table.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+PrintBddIdTable(st_table *idTable)
+{
+  st_generator *stgen;
+  long varId;
+  fprintf(vis_stdout,
+	  "**************** printing bdd ids from the id table  ***********\n");
+  fprintf(vis_stdout,"%d::\t", st_count(idTable));
+  st_foreach_item(idTable, stgen, &varId, NIL(char *)) {
+    fprintf(vis_stdout," %d ", (int) varId);
+  }
+  fprintf(vis_stdout,"\n******************\n");
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Traverses the partition recursively, creating the
+  relations for the intermediate vertices.]
+
+  Description [Traverses the partition recursively, creating the
+  relations for the intermediate vertices.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+PartitionTraverseRecursively(mdd_manager *mddManager, vertex_t *vertex,
+                             int mddId, st_table *vertexTable,
+			     array_t *relationArray,
+			     st_table *domainQuantifyVarMddIdTable,
+                             array_t *quantifyVarMddIdArray)
+{
+  Mvf_Function_t *mvf;
+  lsList faninEdges;
+  lsGen gen;
+  vertex_t *faninVertex;
+  edge_t *faninEdge;
+  array_t *varBddRelationArray;
+
+  if (st_is_member(vertexTable, (char *)vertex)) return;
+  st_insert(vertexTable, (char *)vertex, NIL(char));
+  if (mddId != -1) { /* This is not the next state function node */
+    /* There is an mdd variable associated with this vertex */
+    array_insert_last(int, quantifyVarMddIdArray, mddId);
+    mvf = Part_VertexReadFunction(vertex);
+    /*relation = Mvf_FunctionBuildRelationWithVariable(mvf, mddId);*/
+    varBddRelationArray = mdd_fn_array_to_bdd_rel_array(mddManager, mddId, mvf);
+    array_append(relationArray, varBddRelationArray);
+    array_free(varBddRelationArray);
+    /*array_insert_last(mdd_t *, relationArray, relation);*/
+  }
+  faninEdges = g_get_in_edges(vertex);
+  if (lsLength(faninEdges) == 0) return;
+  lsForEachItem(faninEdges, gen, faninEdge) {
+    faninVertex = g_e_source(faninEdge);
+    mddId = Part_VertexReadMddId(faninVertex);
+    if (st_is_member(domainQuantifyVarMddIdTable, (char *)(long)mddId)) {
+      /* This is either domain var or quantify var */
+      /* continue */
+      continue;
+    }
+    PartitionTraverseRecursively(mddManager, faninVertex, mddId, vertexTable,
+				 relationArray,
+				 domainQuantifyVarMddIdTable,
+				 quantifyVarMddIdArray);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the partition recursively.]
+
+  Description [Prints the partition recursively.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+PrintPartitionRecursively(vertex_t *vertex, st_table *vertexTable, int indent)
+{
+  int i;
+  lsList faninEdges;
+  lsGen gen;
+  vertex_t *faninVertex;
+  edge_t *faninEdge;
+
+  if (st_is_member(vertexTable, (char *)vertex)) return;
+  st_insert(vertexTable, (char *)vertex, NIL(char));
+  for(i=0; i<= indent; i++) fprintf(vis_stdout," ");
+  fprintf(vis_stdout,"%s %d\n", Part_VertexReadName(vertex),
+	  Part_VertexReadMddId(vertex));
+  faninEdges = g_get_in_edges(vertex);
+  if (lsLength(faninEdges) == 0) return;
+  lsForEachItem(faninEdges, gen, faninEdge) {
+    faninVertex = g_e_source(faninEdge);
+    PrintPartitionRecursively(faninVertex, vertexTable,indent+2);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Recompute partial image by relaxing the parameters.]
+
+  Description [Recompute partial image by relaxing the
+  parameters. First the threshold to trigger approximation is
+  increased and then the threshold to approximate is increased. If
+  both fail to produce new states, the exact image is computed (no
+  approximations).Partial flag comes in indicating whether partial
+  images are allowed, and leave indicating whether the image was
+  partial or not. ASSUME that toCareSet is in terms of
+  function->domainVars.]
+
+  SideEffects [partial flag is modified with each image
+  computation. IMPORTANT NOTE: image may be in terms of domain
+  variables even when the reverse is expected.]
+
+******************************************************************************/
+static bdd_t *
+RecomputeImageIfNecessary(ImgFunctionData_t *functionData,
+			  mdd_manager *mddManager,
+			  bdd_t *domainSubset,
+			  array_t *relationArray,
+			  array_t *arraySmoothVarBddArray,
+			  array_t *smoothVarCubeArray,
+			  int verbosity,
+			  ImgPartialImageOption_t *PIoption,
+			  array_t *toCareSetArray,
+			  boolean *partial, boolean lazySiftFlag)
+{
+  int oldPIThreshold = 0, oldPISize;
+  double oldClippingFrac = IMG_PI_CLIP_DEPTH;
+  boolean realRequired = FALSE;
+  mdd_t *image = NIL(mdd_t);
+
+  /* relax values to compute a non-trivial partial image */
+  if (PIoption->partialImageMethod == Img_PIApprox_c) {
+    oldPIThreshold = PIoption->partialImageThreshold;
+    PIoption->partialImageThreshold *= 2;
+    if (!PIoption->partialImageThreshold)
+      PIoption->partialImageThreshold = IMG_PI_SP_THRESHOLD;
+  } else if (PIoption->partialImageMethod == Img_PIClipping_c) {
+    oldClippingFrac = PIoption->clippingDepthFrac;
+    PIoption->clippingDepthFrac =
+	(PIoption->clippingDepthFrac < IMG_PI_CLIP_DEPTH_FINAL) ?
+	IMG_PI_CLIP_DEPTH_FINAL : PIoption->clippingDepthFrac;
+  }
+  if (((PIoption->partialImageMethod == Img_PIClipping_c) &&
+       (oldClippingFrac != PIoption->clippingDepthFrac)) ||
+      (PIoption->partialImageMethod == Img_PIApprox_c)) {
+    if (verbosity >= 2) {
+      fprintf(vis_stdout,
+	"IMG: No new states, computing image again with relaxed thresholds.\n");
+      if (PIoption->partialImageMethod == Img_PIApprox_c) {
+	fprintf(vis_stdout, "IMG: Relaxed hd_partial_image_threshold to %d\n",
+		PIoption->partialImageThreshold);
+      } else if (PIoption->partialImageMethod == Img_PIClipping_c) {
+	fprintf(vis_stdout,
+		"IMG: Relaxed hd_partial_image_clipping_depth to %g\n",
+		PIoption->clippingDepthFrac);
+      }
+    }
+
+    *partial = TRUE;
+    /* if values were relaxed, compute image again. */
+    image = BddLinearAndSmooth(mddManager, domainSubset, relationArray,
+				arraySmoothVarBddArray, smoothVarCubeArray,
+				verbosity, PIoption, partial, lazySiftFlag);
+
+    /* check if new states were produced. */
+    if (*partial) {
+      if (bdd_leq_array(image, toCareSetArray, 1, 0)) {
+      	bdd_free(image);
+	if (PIoption->partialImageMethod == Img_PIApprox_c) {
+	  /* relax approximation values some more. */
+	  oldPISize = PIoption->partialImageSize;
+	  PIoption->partialImageSize *= 2;
+	  if (!PIoption->partialImageSize)
+	    PIoption->partialImageSize = IMG_PI_SP_THRESHOLD;
+
+	  if (verbosity >= 2) {
+	    fprintf(vis_stdout,
+	"IMG: No new states, computing image again with relaxed thresholds.\n");
+	    fprintf(vis_stdout, "IMG: Relaxed hd_partial_image_size to %d\n",
+		    PIoption->partialImageSize);
+	  }
+
+	  *partial = TRUE;
+	  image = BddLinearAndSmooth(mddManager, domainSubset, relationArray,
+				     arraySmoothVarBddArray, smoothVarCubeArray,
+				     verbosity, PIoption, partial,
+				     lazySiftFlag);
+	  PIoption->partialImageSize = oldPISize;
+
+	  /* check if new states were produced. */
+	  if (*partial) {
+	    if (bdd_leq_array(image, toCareSetArray, 1, 0)) {
+	      bdd_free(image);
+	      realRequired = TRUE;
+	    }
+	  }
+	} else if (PIoption->partialImageMethod == Img_PIClipping_c) {
+	  /* compute real image since clipping depth cannot be increased. */
+	  realRequired = TRUE;
+	}
+      }
+    } /* require recomputation */
+  } else { /* clipping depth could not be increased. */
+    /* compute real image since clipping depth cannot be increased. */
+    realRequired = TRUE;
+  }
+
+  /* reset the values to the orginal values. */
+  if (PIoption->partialImageMethod == Img_PIClipping_c) {
+    PIoption->clippingDepthFrac = oldClippingFrac;
+  } else if (PIoption->partialImageMethod == Img_PIApprox_c) {
+    PIoption->partialImageThreshold = oldPIThreshold;
+  }
+  /* if the actual image is required compute it. */
+  if (realRequired) {
+    if (verbosity >= 2) {
+      fprintf(vis_stdout, "IMG: No new states, computing exact image.\n");
+    }
+    *partial = FALSE;
+    image = BddLinearAndSmooth(mddManager, domainSubset, relationArray,
+				arraySmoothVarBddArray, smoothVarCubeArray,
+				verbosity, PIoption, partial, lazySiftFlag);
+    assert(!(*partial));
+  }
+
+  return (image);
+} /* end of RecomputeImageIfNecessary */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Approximate intermediate product according to method.]
+
+  Description [Approximate intermediate product according to method.]
+
+  SideEffects []
+
+******************************************************************************/
+static bdd_t *
+ComputeSubsetOfIntermediateProduct(bdd_t *product,
+				   ImgPartialImageOption_t *PIoption)
+{
+  int partialImageSize = PIoption->partialImageSize;
+  int nvars = PIoption->nvars;
+  bdd_t *newProduct;
+
+  switch (PIoption->partialImageApproxMethod) {
+  case BDD_APPROX_HB:
+    {
+      int tempSize;
+      tempSize = (partialImageSize < IMG_PI_SP_THRESHOLD) ?
+		IMG_PI_SP_THRESHOLD : partialImageSize;
+      newProduct = bdd_approx_hb(product,
+				 (bdd_approx_dir_t)BDD_UNDER_APPROX,
+				 nvars, tempSize);
+      break;
+    }
+  case BDD_APPROX_SP:
+    {
+      int tempSize;
+      tempSize = (partialImageSize < IMG_PI_SP_THRESHOLD) ?
+		IMG_PI_SP_THRESHOLD : partialImageSize;
+      newProduct = bdd_approx_sp(product,
+				 (bdd_approx_dir_t)BDD_UNDER_APPROX,
+				 nvars, tempSize, 0);
+      break;
+    }
+  case BDD_APPROX_UA:
+    newProduct = bdd_approx_ua(product,
+			       (bdd_approx_dir_t)BDD_UNDER_APPROX,
+			       nvars, partialImageSize,
+			       0, PIoption->quality);
+    break;
+  case BDD_APPROX_RUA:
+    newProduct = bdd_approx_remap_ua(product,
+				     (bdd_approx_dir_t)BDD_UNDER_APPROX,
+				     0, partialImageSize,
+				     PIoption->quality);
+    break;
+  case BDD_APPROX_COMP:
+    {
+      newProduct = bdd_approx_compress(product,
+				     (bdd_approx_dir_t)BDD_UNDER_APPROX,
+				     nvars, partialImageSize);
+    }
+    break;
+  case BDD_APPROX_BIASED_RUA:
+    newProduct = bdd_approx_biased_rua(product,
+				       (bdd_approx_dir_t)BDD_UNDER_APPROX,
+				       PIoption->bias,
+				       0, partialImageSize,
+				       PIoption->quality,
+				       PIoption->qualityBias);
+    break;
+  default :
+    newProduct = bdd_approx_remap_ua(product,
+				     (bdd_approx_dir_t)BDD_UNDER_APPROX,
+				     0, partialImageSize,
+				     PIoption->quality);
+    break;
+  }
+  return newProduct;
+} /* end of ComputeSubsetOfIntermediateProduct */
+
+/**Function********************************************************************
+
+  Synopsis    [Clipping and-abstract]
+
+  Description [Compute clipping and-abstract. Try twice. If fail,
+  compute exact and-abstract]
+
+  SideEffects [partial flag is modified.]
+
+******************************************************************************/
+static bdd_t *
+ComputeClippedAndAbstract(bdd_t *product,
+			  bdd_t *relation,
+			  array_t *smoothVarBddArray,
+			  int nvars,
+			  int clippingDepth,
+			  boolean *partial,
+			  int verbosity)
+{
+  bdd_t *tmpProduct;
+
+  /* compute clipped image */
+  tmpProduct = bdd_clipping_and_smooth(product, relation,
+				       smoothVarBddArray, clippingDepth, 0);
+  /* if product is zero, compute clipped image with increased
+   * clipping depth
+   */
+  if (bdd_is_tautology(tmpProduct, 0)) {
+    bdd_free(tmpProduct);
+    tmpProduct = bdd_clipping_and_smooth(product, relation,
+					 smoothVarBddArray,
+					 (int) (nvars*IMG_PI_CLIP_DEPTH_FINAL),
+					 0);
+
+    /* if clipped image is zero, compute unclipped image */
+    if (bdd_is_tautology(tmpProduct, 0)) {
+      if (verbosity >= 2) {
+	fprintf(vis_stdout,
+		"IMG: Clipping failed, computing exact and-abstract\n");
+      }
+      bdd_free(tmpProduct);
+      tmpProduct = bdd_and_smooth(product, relation,
+				  smoothVarBddArray);
+    } else *partial = TRUE;
+
+  } else *partial = TRUE;
+
+  return tmpProduct;
+} /* end of ComputeClippedAndAbstract */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Copy an array of bdd array.]
+
+  Description [Copy an array of bdd array.]
+
+  SideEffects []
+
+******************************************************************************/
+static array_t *
+CopyArrayBddArray(array_t *arrayBddArray)
+{
+  int		i, j;
+  array_t	*newArrayBddArray = array_alloc(array_t *, 0);
+  array_t	*bddArray, *newBddArray;
+  mdd_t		*bdd;
+
+  for (i = 0; i < array_n(arrayBddArray); i++) {
+    bddArray = array_fetch(array_t *, arrayBddArray, i);
+    newBddArray = array_alloc(mdd_t *, 0);
+    for (j = 0; j < array_n(bddArray); j++) {
+      bdd = array_fetch(mdd_t *, bddArray, j);
+      array_insert(mdd_t *, newBddArray, j, bdd_dup(bdd));
+    }
+    array_insert(array_t *, newArrayBddArray, i, newBddArray);
+  }
+
+  return(newArrayBddArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints info of the partitioned transition relation.]
+
+  Description [Prints info of the partitioned transition relation.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+PrintPartitionedTransitionRelation(mdd_manager *mddManager,
+				   Iwls95Info_t *info,
+				   Img_DirectionType directionType)
+{
+  array_t *relationArray;
+  array_t *arraySmoothVarBddArray;
+
+  if (directionType == Img_Forward_c) {
+    relationArray = info->fwdClusteredRelationArray;
+    arraySmoothVarBddArray = info->fwdArraySmoothVarBddArray;
+  } else if (directionType == Img_Backward_c) {
+    relationArray = info->bwdClusteredRelationArray;
+    arraySmoothVarBddArray = info->bwdArraySmoothVarBddArray;
+  } else {
+   return;
+  }
+
+  ImgPrintPartitionedTransitionRelation(mddManager, relationArray,
+					arraySmoothVarBddArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reorder partitioned transition relation.]
+
+  Description [Reorder partitioned transition relation.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+ReorderPartitionedTransitionRelation(Iwls95Info_t *info,
+				     ImgFunctionData_t *functionData,
+				     Img_DirectionType directionType)
+{
+  array_t *domainVarMddIdArray = functionData->domainVars;
+  array_t *rangeVarMddIdArray = functionData->rangeVars;
+  array_t *quantifyVarMddIdArray = array_dup(functionData->quantifyVars);
+  graph_t *mddNetwork = functionData->mddNetwork;
+  mdd_manager *mddManager = Part_PartitionReadMddManager(mddNetwork);
+  array_t *rangeVarBddArray, *domainVarBddArray, *quantifyVarBddArray;
+  array_t *clusteredRelationArray;
+  st_table *varsTable = st_init_table(st_numcmp, st_numhash);
+  int i, j, k, mddId;
+  array_t *smoothVarBddArray, *arraySmoothVarBddArray;
+  mdd_t *mdd;
+  array_t *supportIdArray;
+
+  /* Finds the variables which are neither state variable nor primary input
+   * from previous smooth variable array, and put those variable into
+   * quantify variable array.
+   */
+  for (i =0 ; i<  array_n(domainVarMddIdArray); i++) {
+    mddId = array_fetch(int, domainVarMddIdArray, i);
+    st_insert(varsTable, (char *)(long)mddId, NIL(char));
+  }
+  for (i = 0; i < array_n(rangeVarMddIdArray); i++) {
+    mddId = array_fetch(int, rangeVarMddIdArray, i);
+    st_insert(varsTable, (char *)(long)mddId, NIL(char));
+  }
+    for (i = 0; i < array_n(quantifyVarMddIdArray); i++) {
+    mddId = array_fetch(int, quantifyVarMddIdArray, i);
+    st_insert(varsTable, (char *)(long)mddId, NIL(char));
+  }
+    if (directionType == Img_Forward_c || directionType == Img_Both_c)
+    arraySmoothVarBddArray = info->fwdArraySmoothVarBddArray;
+  else
+    arraySmoothVarBddArray = info->bwdArraySmoothVarBddArray;
+  for (i = 0; i < array_n(arraySmoothVarBddArray); i++) {
+    smoothVarBddArray = array_fetch(array_t *, arraySmoothVarBddArray, i);
+    for (j = 0; j < array_n(smoothVarBddArray); j++) {
+      mdd = array_fetch(mdd_t *, smoothVarBddArray, j);
+      supportIdArray = mdd_get_support(mddManager, mdd);
+      for (k = 0; k < array_n(supportIdArray); k++) {
+	mddId = array_fetch(int, supportIdArray, k);
+	if (!st_lookup(varsTable, (char *)(long)mddId, NIL(char *))) {
+	  array_insert_last(int, quantifyVarMddIdArray, mddId);
+	  st_insert(varsTable, (char *)(long)mddId, NIL(char));
+	}
+      }
+      array_free(supportIdArray);
+    }
+  }
+  st_free_table(varsTable);
+
+  /* Get the Bdds from Mdd Ids */
+  rangeVarBddArray = functionData->rangeBddVars;
+  domainVarBddArray = functionData->domainBddVars;
+  quantifyVarBddArray = mdd_id_array_to_bdd_array(mddManager,
+						  quantifyVarMddIdArray);
+  array_free(quantifyVarMddIdArray);
+
+  if (directionType == Img_Forward_c || directionType == Img_Both_c) {
+    clusteredRelationArray = info->fwdClusteredRelationArray;
+    mdd_array_array_free(info->fwdArraySmoothVarBddArray);
+    info->fwdClusteredRelationArray = NIL(array_t);
+    info->fwdArraySmoothVarBddArray = NIL(array_t);
+    if (info->method == Img_Iwls95_c) {
+      OrderRelationArray(mddManager, clusteredRelationArray,
+			domainVarBddArray, quantifyVarBddArray,
+			rangeVarBddArray, info->option,
+			&info->fwdClusteredRelationArray,
+			&info->fwdArraySmoothVarBddArray);
+    } else if (info->method == Img_Mlp_c) {
+      ImgMlpOrderRelationArray(mddManager, clusteredRelationArray,
+			domainVarBddArray, quantifyVarBddArray,
+			rangeVarBddArray, Img_Forward_c,
+			&info->fwdClusteredRelationArray,
+			&info->fwdArraySmoothVarBddArray,
+			info->option);
+    } else
+      assert(0);
+    mdd_array_free(clusteredRelationArray);
+
+    if (functionData->createVarCubesFlag) {
+      if (info->fwdSmoothVarCubeArray)
+	mdd_array_free(info->fwdSmoothVarCubeArray);
+      info->fwdSmoothVarCubeArray = MakeSmoothVarCubeArray(mddManager,
+					info->fwdArraySmoothVarBddArray);
+    }
+
+    if (info->option->verbosity > 2) {
+      PrintPartitionedTransitionRelation(mddManager, info, Img_Forward_c);
+    }
+  }
+
+  if (directionType == Img_Backward_c || directionType == Img_Both_c) {
+    clusteredRelationArray = info->bwdClusteredRelationArray;
+    mdd_array_array_free(info->bwdArraySmoothVarBddArray);
+    info->bwdClusteredRelationArray = NIL(array_t);
+    info->bwdArraySmoothVarBddArray = NIL(array_t);
+    if (info->method == Img_Iwls95_c) {
+      OrderRelationArray(mddManager, clusteredRelationArray,
+			rangeVarBddArray, quantifyVarBddArray,
+			domainVarBddArray, info->option,
+			&info->bwdClusteredRelationArray,
+			&info->bwdArraySmoothVarBddArray);
+    } else if (info->method == Img_Mlp_c) {
+      ImgMlpOrderRelationArray(mddManager, clusteredRelationArray,
+			domainVarBddArray, quantifyVarBddArray,
+			rangeVarBddArray, Img_Backward_c,
+			&info->bwdClusteredRelationArray,
+			&info->bwdArraySmoothVarBddArray, info->option);
+    } else
+      assert(0);
+    mdd_array_free(clusteredRelationArray);
+
+    if (functionData->createVarCubesFlag) {
+      if (info->bwdSmoothVarCubeArray)
+	mdd_array_free(info->bwdSmoothVarCubeArray);
+      info->bwdSmoothVarCubeArray = MakeSmoothVarCubeArray(mddManager,
+					info->bwdArraySmoothVarBddArray);
+    }
+
+    if (info->option->verbosity > 2) {
+      PrintPartitionedTransitionRelation(mddManager, info, Img_Backward_c);
+    }
+  }
+
+  /* Free the Bdd arrays */
+  mdd_array_free(quantifyVarBddArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Updates quantification schedule.]
+
+  Description [Updates quantification schedule.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+UpdateQuantificationSchedule(Iwls95Info_t *info,
+			     ImgFunctionData_t *functionData,
+			     Img_DirectionType directionType)
+{
+  graph_t *mddNetwork = functionData->mddNetwork;
+  mdd_manager *mddManager = Part_PartitionReadMddManager(mddNetwork);
+  array_t *clusteredRelationArray;
+  st_table *quantifyVarsTable;
+  var_set_t *supportVarSet;
+  int i, j, id, nRelations;
+  int pos;
+  long longid;
+  array_t *smoothVarBddArray, **smoothVarBddArrayPtr;
+  bdd_t *bdd, *relation;
+  st_generator *gen;
+
+  if (directionType == Img_Forward_c || directionType == Img_Both_c) {
+    nRelations = array_n(info->fwdClusteredRelationArray);
+    quantifyVarsTable = st_init_table(st_numcmp, st_numhash);
+    for (i = 0; i <= nRelations; i++) {
+      smoothVarBddArray = array_fetch(array_t *,
+		      info->fwdArraySmoothVarBddArray, i);
+      for (j = 0; j < array_n(smoothVarBddArray); j++) {
+	bdd = array_fetch(mdd_t *, smoothVarBddArray, j);
+	id = (int)bdd_top_var_id(bdd);
+	st_insert(quantifyVarsTable, (char *)(long)id, NIL(char));
+      }
+    }
+
+    clusteredRelationArray = info->fwdClusteredRelationArray;
+    for (i = 0; i < nRelations; i++) {
+      relation = array_fetch(bdd_t *, clusteredRelationArray, i);
+      supportVarSet = bdd_get_support(relation);
+      for (j = 0; j < supportVarSet->n_elts; j++) {
+	if (var_set_get_elt(supportVarSet, j) == 1) {
+	  if (st_is_member(quantifyVarsTable, (char *)(long)j))
+	    st_insert(quantifyVarsTable, (char *)(long)j, (char *)(long)(i+1));
+	}
+      }
+      var_set_free(supportVarSet);
+    }
+
+    mdd_array_array_free(info->fwdArraySmoothVarBddArray);
+    info->fwdArraySmoothVarBddArray = array_alloc(array_t *, nRelations + 1);
+    smoothVarBddArrayPtr = ALLOC(array_t *, sizeof(array_t *) * (nRelations+1));
+    for (i = 0; i <= nRelations; i++) {
+      smoothVarBddArray = array_alloc(bdd_t *, 0);
+      smoothVarBddArrayPtr[i] = smoothVarBddArray;
+      array_insert(array_t *, info->fwdArraySmoothVarBddArray, i,
+		smoothVarBddArray);
+    }
+
+    st_foreach_item_int(quantifyVarsTable, gen, &longid, &pos) {
+      id = (int) longid;
+      smoothVarBddArray = array_fetch(array_t *,
+		      info->fwdArraySmoothVarBddArray, pos);
+      bdd = bdd_var_with_index(mddManager, id);
+      array_insert_last(bdd_t *, smoothVarBddArray, bdd);
+    }
+
+    FREE(smoothVarBddArrayPtr);
+    st_free_table(quantifyVarsTable);
+
+    if (functionData->createVarCubesFlag) {
+      if (info->fwdSmoothVarCubeArray)
+	mdd_array_free(info->fwdSmoothVarCubeArray);
+      info->fwdSmoothVarCubeArray = MakeSmoothVarCubeArray(mddManager,
+					info->fwdArraySmoothVarBddArray);
+    }
+
+    if (info->option->verbosity > 2) {
+      PrintPartitionedTransitionRelation(mddManager, info, Img_Forward_c);
+    }
+  }
+
+  if (directionType == Img_Backward_c || directionType == Img_Both_c) {
+    nRelations = array_n(info->bwdClusteredRelationArray);
+    quantifyVarsTable = st_init_table(st_numcmp, st_numhash);
+    for (i = 0; i <= nRelations; i++) {
+      smoothVarBddArray = array_fetch(array_t *,
+		      info->bwdArraySmoothVarBddArray, i);
+      for (j = 0; j < array_n(smoothVarBddArray); j++) {
+	bdd = array_fetch(mdd_t *, smoothVarBddArray, j);
+	id = (int)bdd_top_var_id(bdd);
+	st_insert(quantifyVarsTable, (char *)(long)id, (char *)(long)0);
+      }
+    }
+
+    clusteredRelationArray = info->bwdClusteredRelationArray;
+    for (i = 0; i < nRelations; i++) {
+      relation = array_fetch(bdd_t *, clusteredRelationArray, i);
+      supportVarSet = bdd_get_support(relation);
+      for (j = 0; j < supportVarSet->n_elts; j++) {
+	if (var_set_get_elt(supportVarSet, j) == 1) {
+	  if (st_is_member(quantifyVarsTable, (char *)(long)j))
+	    st_insert(quantifyVarsTable, (char *)(long)j, (char *)(long)(i+1));
+	}
+      }
+      var_set_free(supportVarSet);
+    }
+
+    mdd_array_array_free(info->bwdArraySmoothVarBddArray);
+    info->bwdArraySmoothVarBddArray = array_alloc(array_t *, nRelations + 1);
+    smoothVarBddArrayPtr = ALLOC(array_t *, sizeof(array_t *) * (nRelations+1));
+    for (i = 0; i <= nRelations; i++) {
+      smoothVarBddArray = array_alloc(bdd_t *, 0);
+      smoothVarBddArrayPtr[i] = smoothVarBddArray;
+      array_insert(array_t *, info->bwdArraySmoothVarBddArray, i,
+		smoothVarBddArray);
+    }
+
+    st_foreach_item_int(quantifyVarsTable, gen, &longid, &pos) {
+      id = (int) longid;
+      smoothVarBddArray = array_fetch(array_t *,
+		      info->bwdArraySmoothVarBddArray, pos);
+      bdd = bdd_var_with_index(mddManager, id);
+      array_insert_last(bdd_t *, smoothVarBddArray, bdd);
+    }
+
+    FREE(smoothVarBddArrayPtr);
+    st_free_table(quantifyVarsTable);
+
+    if (functionData->createVarCubesFlag) {
+      if (info->bwdSmoothVarCubeArray)
+	mdd_array_free(info->bwdSmoothVarCubeArray);
+      info->bwdSmoothVarCubeArray = MakeSmoothVarCubeArray(mddManager,
+					info->bwdArraySmoothVarBddArray);
+    }
+
+    if (info->option->verbosity > 2) {
+      PrintPartitionedTransitionRelation(mddManager, info, Img_Backward_c);
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns array of cubes of smoothing variables.]
+
+  Description [Returns array of cubes of smoothing variables.]
+
+  SideEffects []
+
+******************************************************************************/
+static array_t *
+MakeSmoothVarCubeArray(mdd_manager *mddManager, array_t *arraySmoothVarBddArray)
+{
+  int		i, j;
+  array_t	*smoothVarBddArray;
+  array_t	*cubeArray = array_alloc(mdd_t *, 0);
+  mdd_t		*cube, *var, *tmp;
+
+  arrayForEachItem(array_t *, arraySmoothVarBddArray, i, smoothVarBddArray) {
+    cube = mdd_one(mddManager);
+    arrayForEachItem(mdd_t *, smoothVarBddArray, j, var) {
+      tmp = mdd_and(cube, var, 1, 1);
+      mdd_free(cube);
+      cube = tmp;
+    }
+    array_insert_last(mdd_t *, cubeArray, cube);
+  }
+  return(cubeArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Eliminates dependent variables from transition relation.]
+
+  Description [Eliminates dependent variables from a transition
+  relation.  Returns a simplified copy of the given states if successful;
+  NULL otherwise.]
+
+  SideEffects [relationArray is also modified.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static mdd_t *
+TrmEliminateDependVars(Img_ImageInfo_t *imageInfo, array_t *relationArray,
+			mdd_t *states, mdd_t **dependRelations)
+{
+  int		nDependVars;
+  mdd_t		*newStates;
+  Iwls95Info_t	*info = (Iwls95Info_t *) imageInfo->methodData;
+
+  newStates = ImgTrmEliminateDependVars(&imageInfo->functionData, relationArray,
+					states, dependRelations, &nDependVars);
+  if (nDependVars) {
+    if (imageInfo->verbosity > 0)
+      (void)fprintf(vis_stdout, "Eliminated %d vars.\n", nDependVars);
+    info->averageFoundDependVars = (info->averageFoundDependVars *
+			(float)info->nFoundDependVars + (float)nDependVars) /
+			(float)(info->nFoundDependVars + 1);
+    info->nFoundDependVars++;
+  }
+
+  info->nPrevEliminatedFwd = nDependVars;
+  return(newStates);
+} /* end of TfmEliminateDependVars */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Comparison function used by qsort.]
+
+  Description [Comparison function used by qsort to order the
+  variables according to their signatures.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+TrmSignatureCompare(int *ptrX, int *ptrY)
+{
+  if (signatures[*ptrY] > signatures[*ptrX])
+    return(1);
+  if (signatures[*ptrY] < signatures[*ptrX])
+    return(-1);
+  return(0);
+} /* end of TrmSignatureCompare */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Setups lazy sifting.]
+
+  Description [Setups lazy sifting.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static void
+SetupLazySifting(mdd_manager *mddManager, array_t *bddRelationArray,
+		array_t *domainVarBddArray, array_t *quantifyVarBddArray,
+		array_t *rangeVarBddArray, int verbosity)
+{
+  int i, id, psId, nsId, psLevel, nsLevel;
+  int nVars = bdd_num_vars(mddManager);
+  int nUngroup = 0;
+  int nGroup = 0;
+  int nConst = 0;
+  int *nonLambda = ALLOC(int, nVars);
+  int nLambda = 0;
+  int nDepend1to1 = 0;
+  int nIndepend1to1 = 0;
+  int nPairPsOnce = 0;
+  int pairPsId;
+  int constFlag;
+  int dependFlag;
+  int nDependPs;
+  int nDependPi;
+  bdd_t* relation;
+  var_set_t* supIds;
+  bdd_t *bdd, *psVar, *nsVar;
+
+  bdd_discard_all_var_groups(mddManager);
+  for (i = 0; i < array_n(quantifyVarBddArray); i++) {
+    bdd = array_fetch(bdd_t *, quantifyVarBddArray, i);
+    id = bdd_top_var_id(bdd);
+    bdd_set_pair_index(mddManager, id, id);
+    bdd_set_pi_var(mddManager, id);
+    bdd_reset_var_to_be_grouped(mddManager, id);
+  }
+
+  for (i = 0; i < array_n(rangeVarBddArray); i++) {
+    psVar = array_fetch(bdd_t *, domainVarBddArray, i);
+    nsVar = array_fetch(bdd_t *, rangeVarBddArray, i);
+    psId = bdd_top_var_id(psVar);
+    nsId = bdd_top_var_id(nsVar);
+    bdd_set_pair_index(mddManager, psId, nsId);
+    bdd_set_pair_index(mddManager, nsId, psId);
+    bdd_set_ps_var(mddManager, psId);
+    bdd_set_ns_var(mddManager, nsId);
+    bdd_reset_var_to_be_grouped(mddManager, psId);
+    bdd_set_var_to_be_grouped(mddManager, nsId);
+  }
+
+  if (array_n(domainVarBddArray) > array_n(rangeVarBddArray)) {
+    for (i = array_n(rangeVarBddArray); i < array_n(domainVarBddArray); i++) {
+      bdd = array_fetch(bdd_t *, domainVarBddArray, i);
+      id = bdd_top_var_id(bdd);
+      bdd_set_pair_index(mddManager, id, id);
+      bdd_set_pi_var(mddManager, id);
+      bdd_reset_var_to_be_grouped(mddManager, id);
+    }
+  }
+
+  memset(nonLambda, 0, sizeof(int) * nVars);
+  for (i = 0; i < array_n(bddRelationArray); i++) {
+    nsId = -1;
+    pairPsId = -1;
+    constFlag = 1;
+    dependFlag = 0;
+    nDependPs = 0;
+    nDependPi = 0;
+    relation = array_fetch(bdd_t *, bddRelationArray, i);
+    supIds = bdd_get_support(relation);
+
+    for (id = 0; id < nVars; id++) {
+      if (var_set_get_elt(supIds, id) == 1) {
+	if (bdd_is_ns_var(mddManager, id)) {
+	  pairPsId = bdd_read_pair_index(mddManager, id);
+	  nsId = id;
+	} else if (bdd_is_ps_var(mddManager, id)) {
+	  constFlag = 0;  /* nonconst next sate function */
+	  nonLambda[id]++;
+	  psId = id;
+	  /* At least one next state function depends on psvar id  */
+	  nDependPs++;
+	} else {
+	  constFlag = 0;  /* nonconst next state function */
+	  nDependPi++;
+	}
+      }
+    }
+    if (nsId >= 0) {
+      /* bitwise transition relation depends on some nsvar */
+      for (id = 0; id < nVars; id++) {
+	if (var_set_get_elt(supIds, id) == 1) {
+	  if (pairPsId == id) {
+	    /* dependendent state pair */
+	    nGroup++;
+	    dependFlag = 1;
+	  }
+	}
+      }
+      if (dependFlag != 1) {
+	/* independent state pair */
+	nUngroup++;
+	if (constFlag == 1) {
+	  /* next state function is constant */
+	  psLevel = bdd_get_level_from_id(mddManager, pairPsId);
+	  nsLevel = bdd_get_level_from_id(mddManager, nsId);
+	  if (psLevel == nsLevel - 1) {
+	    bdd = bdd_var_with_index(mddManager, pairPsId);
+	    bdd_new_var_block(bdd, 2);
+	    bdd_free(bdd);
+	    nConst++;
+	  } else if (psLevel == nsLevel + 1) {
+	    bdd = bdd_var_with_index(mddManager, nsId);
+	    bdd_new_var_block(bdd, 2);
+	    bdd_free(bdd);
+	    nConst++;
+	  }
+	} else {
+	  bdd_set_var_to_be_ungrouped(mddManager, pairPsId);
+	  bdd_set_var_to_be_ungrouped(mddManager, nsId);
+	}
+      } else if (nDependPs == 1) {
+	psLevel = bdd_get_level_from_id(mddManager, pairPsId);
+	nsLevel = bdd_get_level_from_id(mddManager, nsId);
+	if (psLevel == nsLevel - 1) {
+	  bdd = bdd_var_with_index(mddManager, pairPsId);
+	  bdd_new_var_block(bdd, 2);
+	  bdd_free(bdd);
+	  nDepend1to1++;
+	} else if (psLevel == nsLevel + 1) {
+	  bdd = bdd_var_with_index(mddManager, nsId);
+	  bdd_new_var_block(bdd, 2);
+	  bdd_free(bdd);
+	  nDepend1to1++;
+	}
+      } else if (nonLambda[pairPsId] == 1) {
+	psLevel = bdd_get_level_from_id(mddManager, pairPsId);
+	nsLevel = bdd_get_level_from_id(mddManager, nsId);
+	if (psLevel == nsLevel - 1) {
+	  bdd = bdd_var_with_index(mddManager, pairPsId);
+	  bdd_new_var_block(bdd, 2);
+	  bdd_free(bdd);
+	  nPairPsOnce++;
+	} else if (psLevel == nsLevel + 1) {
+	  bdd = bdd_var_with_index(mddManager, nsId);
+	  bdd_new_var_block(bdd, 2);
+	  bdd_free(bdd);
+	  nPairPsOnce++;
+	}
+      }
+    } else {
+      /* bitwise transition relation does not depend on any nsvar */
+      nUngroup++;
+    }
+    var_set_free(supIds);
+  }
+  for (i = 0; i < nVars; i++) {
+    if (bdd_is_ps_var(mddManager, i)) {
+      if (nonLambda[i] == 0) {
+	/* no next state function depends on psvar i */
+	psId = i;
+	nsId = bdd_read_pair_index(mddManager, psId);
+	psLevel = bdd_get_level_from_id(mddManager, psId);
+	nsLevel = bdd_get_level_from_id(mddManager, nsId);
+	nLambda++;
+	if (psLevel == nsLevel - 1) {
+	  bdd = bdd_var_with_index(mddManager, psId);
+	  bdd_new_var_block(bdd, 2);
+	  bdd_free(bdd);
+	} else if (psLevel == nsLevel + 1) {
+	  bdd = bdd_var_with_index(mddManager, nsId);
+	  bdd_new_var_block(bdd, 2);
+	  bdd_free(bdd);
+	}
+      }
+    } else if (bdd_is_pi_var(mddManager, i)) {
+      bdd_set_var_to_be_ungrouped(mddManager, i);
+    }
+  }
+  if (verbosity) {
+    fprintf(vis_stdout, "#grp=%d(#depend1to1=%d,#pairpsonce=%d)",
+	    nGroup, nDepend1to1, nPairPsOnce);
+    fprintf(vis_stdout,
+	    " #ungrp=%d(#const=%d,#lambda=%d, independ1to1=%d)\n",
+	    nUngroup, nConst, nLambda, nIndepend1to1);
+  }
+  FREE(nonLambda);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Check whether the given transition relation is optimized.]
+
+  Description [Check whether the given transition relation is optimized.]
+
+  SideEffects [ ]
+
+******************************************************************************/
+int
+Img_IsTransitionRelationOptimized(Img_ImageInfo_t * imageInfo)
+{
+  Iwls95Info_t *info = (Iwls95Info_t *)imageInfo->methodData;
+  if(info->fwdOptClusteredRelationArray &&
+     info->fwdClusteredRelationArray)	return(1);
+  return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Compare the size of two MDDs.]
+
+  Description [Compare the size of two MDDs.]
+
+  SideEffects [ ]
+
+******************************************************************************/
+static int
+MddSizeCompare(const void *ptr1, const void *ptr2)
+{
+  mdd_t *mdd1 = *(mdd_t **)ptr1;
+  mdd_t *mdd2 = *(mdd_t **)ptr2;
+  int size1 = mdd_size(mdd1);
+  int size2 = mdd_size(mdd2);
+
+  if (size1 > size2)
+    return 1;
+  else if (size1 < size2)
+    return -1;
+  else
+    return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Restore original transition relations from restricted transition relations by conjoining  with winning strategy]
+
+  Description [Restore original transition relations from restricted transition relations by conjoining  with winning strategy]
+
+  SideEffects []
+
+  SeeAlso []
+******************************************************************************/
+void
+Img_ForwardImageInfoRecoverFromWinningStrategy(
+        Img_ImageInfo_t * imageInfo
+	)
+{
+  Iwls95Info_t *info;
+  array_t *new_;
+
+  info = (Iwls95Info_t *)imageInfo->methodData;
+
+  if(info->fwdOriClusteredRelationArray) {
+    new_ = info->fwdClusteredRelationArray;
+    info->fwdClusteredRelationArray = info->fwdOriClusteredRelationArray;
+    info->fwdOriClusteredRelationArray = 0;
+    mdd_array_free(new_);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Create restricted transition relations by conjoining  with winning strategy]
+
+  Description [Create restricted transition relations by conjoining  with winning strategy.]
+
+  SideEffects []
+
+  SeeAlso []
+******************************************************************************/
+void
+Img_ForwardImageInfoConjoinWithWinningStrategy(
+        Img_ImageInfo_t * imageInfo,
+	mdd_t *winningStrategy)
+{
+  Iwls95Info_t *info;
+  array_t *old, *new_;
+  int i;
+  mdd_t *tr, *ntr, *winning;
+
+
+  old = 0;
+  winning = 0;
+  new_ = array_alloc(mdd_t *, 0);
+  info = (Iwls95Info_t *)imageInfo->methodData;
+  old = info->fwdClusteredRelationArray;
+  info->fwdClusteredRelationArray = new_;
+  info->fwdOriClusteredRelationArray = old;
+  winning = mdd_dup(winningStrategy);
+/*    winning = ImgSubstitute(winningStrategy, &(imageInfo->functionData), Img_D2R_c);*/
+  for(i=0; i<array_n(old); i++) {
+    tr = array_fetch(mdd_t *, old, i);
+    ntr = mdd_and(tr, winning, 1, 1);
+    array_insert_last(mdd_t *, new_, ntr);
+  }
+  mdd_free(winning);
+}
+
Index: vis_dev/vis-2.3/src/img/imgLinear.c
===================================================================
--- vis_dev/vis-2.3/src/img/imgLinear.c	(revision 14)
+++ vis_dev/vis-2.3/src/img/imgLinear.c	(revision 14)
@@ -0,0 +1,5021 @@
+/**CFile***********************************************************************
+
+  FileName    [imgLinear.c]
+
+  PackageName [img]
+
+  Synopsis    [Routines for image computation using Linear Arrangement
+   published in TACAS02.]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [HoonSang Jin]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF COLORADO BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  COLORADO HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF COLORADO SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF COLORADO HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+#include "imgInt.h"
+#include "fsm.h"
+#include "heap.h"
+
+static char rcsid[] UNUSED = "$Id: imgLinear.c,v 1.18 2010/04/10 00:37:06 fabio Exp $";
+static char linearVarString[] = "TCNI";
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+Cluster_t *__clu;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#define BACKWARD_REDUCTION_RATE 0.5
+#define FORWARD_REDUCTION_RATE 0.5
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void ImgLinearUpdateVariableArrayWithId(Relation_t *head, int cindex, int id);
+static int ImgLinearQuantifyVariablesFromConjunct(Relation_t *head, Conjunct_t *conjunct, array_t *smoothVarBddArray, int *bModified);
+static void ImgLinearConjunctRefine(Relation_t *head, Conjunct_t *conjunct);
+static void ImgLinearVariableArrayQuit(Relation_t *head);
+static void ImgLinearConjunctQuit(Conjunct_t *conjunct);
+static Conjunct_t ** ImgLinearAddConjunctIntoArray(Conjunct_t **array, int *nArray, Conjunct_t *con);
+static void ImgLinearFindSameSupportConjuncts(Relation_t *head, int from, int to);
+static void ImgLinearClusterSameSupportSet(Relation_t *head);
+static void ImgLinearExpandSameSupportSet(Relation_t *head);
+static int ImgLinearIsSameConjunct(Relation_t *head, Conjunct_t *con1, Conjunct_t *con2);
+static bdd_t * ImgLinearClusteringSmooth(Relation_t *head, Cluster_t *clu, int **failureHistory, int andExistLimit, int bddLimit);
+static int ImgLinearClusterUsingHeap(Relation_t *head, double affinityLimit, int andExistLimit, int varLimit, Img_OptimizeType optDir, int rangeFlag, int (*compare_func)(const void *, const void *));
+static void ImgLinearPrintTransitionInfo(Relation_t *head);
+static void ImgLinearComputeLifeTime(Relation_t *head, double *paal, double *patl);
+static void ImgLinearFreeSmoothArray(array_t *smoothVarBddArray);
+static void ImgLinearPrintMatrixFull(Relation_t *head, int matrixIndex);
+static void ImgLinearPrintMatrix(Relation_t *head);
+static void ImgLinearCAPOReadVariableOrder(Relation_t *head, char *baseName, int includeNS);
+static void ImgLinearCAPOInterfaceVariablePl(Relation_t *head, char *baseName, int includeNS);
+static void ImgLinearCAPOInterfaceVariableScl(Relation_t *head, char *baseName);
+static void ImgLinearCAPOInterfaceVariableNet(Relation_t *head, char *baseName, int includeNS);
+static void ImgLinearCAPOInterfaceVariableNodes(Relation_t *head, char *baseName, int includeNS);
+static void ImgLinearVariableOrder(Relation_t *head, char *baseName, int includeNS);
+static void ImgLinearCAPOReadConjunctOrder(Relation_t *head, char *baseName);
+static int ImgLinearCAPORun(char *capoExe, char *baseName, int brief);
+static void ImgLinearCAPOInterfaceAux(Relation_t *head, char *baseName);
+static void ImgLinearCAPOInterfaceConjunctPl(Relation_t *head, char *baseName);
+static void ImgLinearCAPOInterfaceConjunctScl(Relation_t *head, char *baseName);
+static void ImgLinearCAPOInterfaceConjunctNet(Relation_t *head, char *baseName);
+static void ImgLinearCAPOInterfaceConjunctNodes(Relation_t *head, char *baseName);
+static void ImgLinearConjunctionOrder(Relation_t *head, char *baseName, int refineFlag);
+static void ImgLinearConjunctOrderMain(Relation_t *head, int bRefineConjunctOrder);
+static void ImgLinearPrintDebugInfo(Relation_t *head);
+static void ImgLinearPrintVariableProfile(Relation_t *head, char *baseName);
+static void ImgLinearInsertClusterCandidate(Relation_t *head, int from, int to, int nDead, int nVar, double affinityLimit);
+static void ImgLinearInsertPairClusterCandidate(Relation_t *head, int from, double affinityLimit, int varLimit, int rangeFlag);
+static void ImgLinearBuildInitialCandidate(Relation_t *head, double affinityLimit, int varLimit, int rangeFlag, int (*compare_func)(const void *, const void *));
+static bdd_t * ImgLinearClusteringPairSmooth(Relation_t *head, Cluster_t *clu, int **failureHistory, int andExistLimit, int bddLimit);
+static void ImgLinearVariableArrayInit(Relation_t *head);
+static void ImgLinearSetEffectiveNumberOfStateVariable(Relation_t *head, int *rangeId, int *domainId, int *existStateVariable) ;
+static void ImgLinearVariableLifeQuit(VarLife_t *var);
+static void ImgLinearAddNextStateCase(Relation_t *head);
+static void ImgLinearAddSingletonCase(Relation_t *head);
+
+static int ImgLinearCompareDeadAffinityLive(const void *c1, const void *c2);
+static int ImgLinearCompareDeadLiveAffinity(const void *c1, const void *c2);
+static int ImgLinearCompareAffinityDeadLive(const void *c1, const void *c2);
+static int ImgLinearCompareLiveAffinityDead(const void *c1, const void *c2);
+static int ImgLinearHeapCompareDeadAffinityLive(const void *c1, const void *c2);
+static int ImgLinearHeapCompareDeadLiveAffinity(const void *c1, const void *c2);
+static int ImgLinearHeapCompareAffinityDeadLive(const void *c1, const void *c2);
+static int ImgLinearHeapCompareLiveAffinityDead(const void *c1, const void *c2);
+
+static int ImgLinearCompareVarIndex(const void *c1, const void *c2);
+static int ImgLinearCompareVarSize(const void *c1, const void *c2);
+static int ImgLinearCompareVarEffFromSmall(const void *c1, const void *c2);
+static int ImgLinearCompareVarEffFromLarge(const void *c1, const void *c2);
+static int ImgLinearCompareConjunctDummy(const void *c1, const void *c2);
+static int ImgLinearCompareConjunctIndex(const void *c1, const void *c2);
+static int ImgLinearCompareConjunctSize(const void *c1, const void *c2);
+static int ImgLinearCompareConjunctRangeMinusDomain(const void *c1, const void *c2);
+static int ImgLinearCompareVarId(const void *c1, const void *c2);
+static int ImgCheckRangeTestAndOverapproximate(Relation_t *head);
+static void ImgCountOnsetDisjunctiveArray(Relation_t *head);
+static int linearCheckRange(const void *tc);
+
+static void ImgLinearConjunctArrayRefine(Relation_t *head);
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+void ImgLinearConjunctOrderMainCC(Relation_t *head, int refineFlag);
+int ImgLinearClustering(Relation_t *head, Img_OptimizeType optDir);
+int ImgLinearPropagateConstant(Relation_t *head, int nextStateFlag);
+int ImgLinearOptimizeStateVariables(Relation_t *head, Img_OptimizeType optDir);
+void ImgLinearExtractNextStateCase(Relation_t *head);
+void ImgLinearExtractSingletonCase(Relation_t *head);
+/*void ImgLinearClusterRelationArray(mdd_manager *mgr, ImgFunctionData_t *functionData, array_t *relationArray, Img_DirectionType direction, array_t **clusteredRelationArrayPtr, array_t **arraySmoothVarBddArrayPtr, array_t **optClusteredRelationArrayPtr, array_t **optArraySmoothVarBddArrayPtr, ImgTrmOption_t *option);
+*/
+void ImgLinearConnectedComponent(Relation_t *head);
+void ImgLinearBuildConjunctArrayWithQuotientCC(Relation_t *head);
+void ImgLinearFindConnectedComponent(Relation_t *head, Conjunct_t *conjunct, int cc_index);
+void ImgLinearAddConjunctIntoClusterArray(Conjunct_t *base, Conjunct_t *con);
+
+
+/**Function********************************************************************
+
+  Synopsis    [Cluster fine grain transition relation]
+
+  Description [First the linear arrangement of transition relation that minimze max cut is generated and the iterative clustering is applied on it.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+ImgLinearClusterRelationArray(mdd_manager *mgr, 
+                             ImgFunctionData_t *functionData, 
+                             array_t *relationArray, 
+                             Img_DirectionType direction, 
+                             array_t **clusteredRelationArrayPtr, 
+                             array_t **arraySmoothVarBddArrayPtr, 
+                             array_t **optClusteredRelationArrayPtr, 
+                             array_t **optArraySmoothVarBddArrayPtr, 
+                             ImgTrmOption_t *option)
+{
+Img_OptimizeType optDir;
+int bGroupStateVariable;
+int bOrderVariable;
+
+int includeCS;
+int includeNS;
+int quantifyCS;
+array_t *initRelationArray;
+int bOptimize;
+Relation_t *head;
+bdd_t **smoothCubeArr, **optSmoothCubeArr;
+array_t *optRelationArr, *optSmoothVarBddArr;
+array_t *relationArr, *smoothVarBddArr;
+
+  if(option->linearComputeRange) {
+    option->linearIncludeCS = 0;
+    option->linearIncludeNS = 0;
+    option->linearQuantifyCS = 1;
+  }
+  
+  optRelationArr = relationArr = 0;
+  optSmoothVarBddArr = smoothVarBddArr = 0;
+
+  includeCS = option->linearIncludeCS;
+  includeNS = option->linearIncludeNS;
+  quantifyCS = option->linearQuantifyCS;
+  if(option->linearFineGrainFlag)	includeNS = 1;
+  optDir = option->linearOptimize;
+  bOrderVariable = option->linearOrderVariable;
+  bGroupStateVariable = option->linearGroupStateVariable;
+
+  head = ImgLinearRelationInit(mgr, relationArray, 
+	  functionData->domainBddVars, functionData->rangeBddVars, 
+	  functionData->quantifyBddVars, option);
+
+  if(head->verbosity >= 5) ImgLinearPrintDebugInfo(head);
+
+  ImgLinearOptimizeAll(head, Opt_None, 0);
+  ImgLinearRefineRelation(head);
+  initRelationArray = ImgLinearExtractRelationArrayT(head);
+
+  bOptimize = 0;
+
+  ImgLinearPrintMatrix(head);
+
+  if(bOrderVariable)
+    ImgLinearVariableOrder(head, "VarOrder", !bGroupStateVariable);
+
+  if((direction==0) || (direction==2))  {
+    ImgLinearPrintMatrix(head);
+
+    bOptimize |= ImgLinearOptimizeAll(head, optDir, 0);
+    ImgLinearRefineRelation(head);
+    ImgLinearSetEffectiveNumberOfStateVariable(head, 0, 0, 0);
+
+    ImgLinearConjunctOrderMainCC(head, 0);
+
+    ImgLinearPrintMatrix(head);
+
+    bOptimize |= ImgLinearClustering(head, optDir);
+
+    ImgLinearRefineRelation(head);
+    ImgLinearSetEffectiveNumberOfStateVariable(head, 0, 0, 0);
+    ImgLinearPrintTransitionInfo(head);
+
+    ImgLinearPrintMatrix(head);
+
+    ImgLinearPrintMatrixFull(head, 2);
+
+    if(bOptimize) {
+      optRelationArr = ImgLinearExtractRelationArrayT(head);
+      optSmoothCubeArr = ALLOC(bdd_t *, head->nSize+1);
+      optSmoothVarBddArr = ImgLinearMakeSmoothVarBdd(head, optSmoothCubeArr);
+    }
+    else {
+      optRelationArr = ImgLinearExtractRelationArrayT(head);
+      optSmoothCubeArr = ALLOC(bdd_t *, head->nSize+1);
+      optSmoothVarBddArr = ImgLinearMakeSmoothVarBdd(head, optSmoothCubeArr);
+      relationArr = 0;
+      smoothVarBddArr = 0;
+    }
+    ImgLinearPrintDebugInfo(head);
+    ImgLinearRelationQuit(head);
+
+    if(bOptimize) {
+      fprintf(vis_stdout, "Get Schedules without optimization\n");
+      head = ImgLinearRelationInit(mgr, initRelationArray, 
+	  functionData->domainBddVars, functionData->rangeBddVars, 
+	  functionData->quantifyBddVars, option);
+      ImgLinearSetEffectiveNumberOfStateVariable(head, 0, 0, 0);
+      ImgLinearConjunctOrderMainCC(head, 0);
+      if(head->verbosity >= 5)
+        ImgLinearPrintMatrix(head);
+      ImgLinearClustering(head, Opt_None);
+       
+      relationArr = ImgLinearExtractRelationArrayT(head);
+      smoothCubeArr = ALLOC(bdd_t *, head->nSize+1);
+      smoothVarBddArr = ImgLinearMakeSmoothVarBdd(head, smoothCubeArr);
+
+      ImgLinearSetEffectiveNumberOfStateVariable(head, 0, 0, 0);
+      ImgLinearPrintDebugInfo(head);
+      ImgLinearPrintTransitionInfo(head);
+
+      ImgLinearRelationQuit(head);
+    }
+
+    if(optClusteredRelationArrayPtr)
+      *optClusteredRelationArrayPtr = optRelationArr;
+    else
+      mdd_array_free(optRelationArr);
+
+    if(optArraySmoothVarBddArrayPtr)
+      *optArraySmoothVarBddArrayPtr = optSmoothVarBddArr;
+    else if(optSmoothVarBddArr)
+      ImgLinearFreeSmoothArray(optSmoothVarBddArr);
+
+    if(clusteredRelationArrayPtr)
+      *clusteredRelationArrayPtr = relationArr;
+    else
+      mdd_array_free(relationArr);
+
+    if(arraySmoothVarBddArrayPtr)
+      *arraySmoothVarBddArrayPtr = smoothVarBddArr;
+    else if(smoothVarBddArr)
+      ImgLinearFreeSmoothArray(smoothVarBddArr);
+  }
+
+  if((direction==1) || (direction==2)) {
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initialize the data structure for linear arrangement and clustering.]
+
+  Description [Build initial data structure]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Relation_t *
+ImgLinearRelationInit(mdd_manager *mgr,
+	              	array_t *relationArray,
+			array_t *domainBddVars,
+			array_t *rangeBddVars,
+			array_t *quantifyBddVars,
+			ImgTrmOption_t *option)
+{
+Relation_t *head;
+Conjunct_t *conjunct, **conjunctArray;
+bdd_t *varBdd;
+int *domain2range, *range2domain;
+int *varArrayMap, *varType;
+bdd_t **constantCase, *relation;
+int i, j, id, tid, nSize;
+int *supList, listSize;
+char *flagValue;
+int *quantifyVars, nQuantify, *visited;
+
+  head = ALLOC(Relation_t, 1);
+  memset(head, 0, sizeof(Relation_t));
+  head->mgr = mgr;
+  head->nVar = bdd_num_vars(head->mgr);
+  head->bddLimit = option->clusterSize;
+
+  head->verbosity = option->verbosity;
+  flagValue = Cmd_FlagReadByName("linear_verbosity");
+  if(flagValue) {
+    head->verbosity += atoi(flagValue);
+  }
+
+
+  head->includeCS = option->linearIncludeCS;
+  head->includeNS = option->linearIncludeNS;
+  head->quantifyCS = option->linearQuantifyCS;
+  head->computeRange = option->linearComputeRange;
+
+  head->nInitRange = 0;
+  head->nInitDomain = 0;
+  head->nInitQuantify = 0;
+  head->nEffRange = 0;
+  head->nEffDomain = 0;
+  head->nEffQuantify = 0;
+
+  head->clusterArray = 0;
+  head->nClusterArray = 0;
+
+  head->nVarArray = 0;
+  head->varArray = 0;
+
+  head->nSingletonArray = 0;
+  head->singletonArray = 0;
+  head->nNextStateArray = 0;
+  head->nextStateArray = 0;
+
+  domain2range = ALLOC(int, head->nVar);
+  head->domain2range = domain2range;
+  memset(domain2range, -1, sizeof(int)*head->nVar);
+
+  range2domain = ALLOC(int, head->nVar);
+  head->range2domain = range2domain;
+  memset(range2domain, -1, sizeof(int)*head->nVar);
+
+  varType = ALLOC(int, head->nVar);
+  head->varType = varType;
+  memset(varType, 0, sizeof(int)*head->nVar);
+
+  head->nRange = array_n(rangeBddVars);
+  head->nDomain = array_n(domainBddVars);
+
+  head->domainVars = ALLOC(int, head->nDomain);
+  head->rangeVars = ALLOC(int, head->nRange);
+  for(i=0; i<head->nDomain; i++) {
+    varBdd = array_fetch(bdd_t *, domainBddVars, i);
+    id = (int)bdd_top_var_id(varBdd);
+    head->domainVars[i] = id;
+    varType[id] = 1;
+
+    varBdd = array_fetch(bdd_t *, rangeBddVars, i);
+    tid = (int)bdd_top_var_id(varBdd);
+    head->rangeVars[i] = tid;
+    varType[tid] = 2;
+
+    domain2range[id] = tid;
+    range2domain[tid] = id;
+  }
+
+  head->quantifyVars = quantifyVars = ALLOC(int, head->nVar);
+  memset(quantifyVars, 0, sizeof(int)*head->nVar);
+  for(nQuantify=0, i=0; i<array_n(quantifyBddVars); i++) {
+    varBdd = array_fetch(bdd_t *, quantifyBddVars, i);
+    id = (int)bdd_top_var_id(varBdd);
+    quantifyVars[nQuantify++] = id;
+    varType[id] = 3;
+  }
+
+  varArrayMap = ALLOC(int, head->nVar);
+  head->varArrayMap = varArrayMap;
+  memset(varArrayMap, -1, sizeof(int)*head->nVar);
+
+  constantCase = ALLOC(bdd_t *, head->nVar);
+  head->constantCase = constantCase;
+  memset(constantCase, 0, sizeof(bdd_t *)*head->nVar);
+
+
+  nSize = array_n(relationArray);
+  conjunctArray = ALLOC(Conjunct_t *, nSize+1);
+  head->nSize = nSize;
+  head->conjunctArray = conjunctArray;
+
+  visited = ALLOC(int, head->nVar);
+  memset(visited, 0, sizeof(int)*head->nVar);
+  for(i=0; i<nSize; i++) {
+    conjunct = ALLOC(Conjunct_t, 1);
+    memset(conjunct, 0, sizeof(Conjunct_t));
+    conjunct->index = i;
+    relation = array_fetch(bdd_t *, relationArray, i);
+
+    conjunct->relation = mdd_dup(relation);
+
+    supList = ImgLinearGetSupportBddId(head->mgr, relation, &listSize);
+    conjunct->supList = supList;
+    conjunct->nSize = listSize;
+    for(j=0; j<listSize; j++) {
+      id = supList[j];
+      if(varType[id] == 1)	conjunct->nDomain++;
+      else if(varType[id] == 2)	conjunct->nRange++;
+      else if(varType[id] == 3)	conjunct->nQuantify++;
+      else if(visited[id] == 0) {
+	quantifyVars[nQuantify++] = id;
+	visited[id] = 1;
+      }
+    }
+
+    conjunctArray[i] = conjunct;
+  }
+  conjunctArray[i] = 0;
+
+  head->nQuantify= nQuantify;
+  free(visited);
+
+  ImgLinearVariableArrayInit(head);
+  return(head);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Find support varaibles of bdd]
+
+  Description [Find support varaibles of bdd]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int *
+ImgLinearGetSupportBddId(mdd_manager *mgr, bdd_t *f, int *nSize)
+{
+var_set_t *vset;
+array_t *bvar_list;
+int *supList, i, size;
+
+  bvar_list = mdd_ret_bvar_list(mgr);
+  vset = bdd_get_support(f);
+  size = 0;
+  supList = ALLOC(int, size+1);
+  supList[0] = -1;
+  for(i=0; i<array_n(bvar_list); i++) {
+    if(var_set_get_elt(vset, i) == 1) {
+      supList = REALLOC(int, supList, size+2); 
+      supList[size++] = i;
+      supList[size] = -1;
+    }
+  }
+  var_set_free(vset);
+  *nSize = size;
+  if(size == 0)	{
+    free(supList);
+    supList = 0;
+  }
+  return(supList);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Create relation array for image computation from Relation_t data structure]
+
+  Description [Create relation array for image computation from Relation_t data structure]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bdd_t **
+ImgLinearExtractRelationArray(Relation_t *head)
+{
+int i;
+bdd_t **relationArray;
+Conjunct_t *conjunct;
+
+  relationArray = ALLOC(bdd_t *, head->nSize+1);
+  for(i=0; i<head->nSize; i++) {
+    conjunct = head->conjunctArray[i];
+    relationArray[i] = bdd_dup(conjunct->relation);
+  }
+  relationArray[i] = 0;
+  return(relationArray);
+}
+/**Function********************************************************************
+
+  Synopsis    [Create relation array for image computation from Relation_t data structure]
+
+  Description [Create relation array for image computation from Relation_t data structure]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+array_t *
+ImgLinearExtractRelationArrayT(Relation_t *head)
+{
+int i;
+array_t *relationArray;
+Conjunct_t *conjunct;
+
+  relationArray = array_alloc(bdd_t *, head->nSize);
+  for(i=0; i<head->nSize; i++) {
+    conjunct = head->conjunctArray[i];
+    array_insert_last(bdd_t *, relationArray, bdd_dup(conjunct->relation));
+  }
+  return(relationArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Function for optimizing state varaibles]
+
+  Description [If the next or current state variables are eleminated after
+  applying clustering and constant propagation then delete corresponding
+  state variable from transition relation.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+ImgLinearOptimizeAll(Relation_t *head, Img_OptimizeType optDir, int constantNSOpt)
+{
+int bOptimize;
+
+  bOptimize = 0;
+  bOptimize |= ImgLinearPropagateConstant(head, constantNSOpt);
+  bOptimize |= ImgLinearOptimizeStateVariables(head, optDir);
+  ImgLinearOptimizeInternalVariables(head);
+  return(bOptimize);
+}
+/**Function********************************************************************
+
+  Synopsis    [Propagate the constant to simply the transition relation]
+
+  Description [Propagate the constant to simply the transition relation]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+ImgLinearPropagateConstant(Relation_t *head, int nextStateFlag)
+{
+int nSize, i, j;
+int *supList;
+Conjunct_t **conjunctArray;
+Conjunct_t *conjunct;
+mdd_manager *mgr;
+bdd_t **constantCase;
+bdd_t *relation, *simpleRelation;
+int nConstantCase;
+int bOptimize;
+int id, cid, index;
+int *varType;
+int size;
+
+  bOptimize = 0;
+  mgr = head->mgr;
+  constantCase = head->constantCase;
+  varType = head->varType;
+
+  conjunctArray = head->conjunctArray;
+  nSize = head->nSize;
+  nConstantCase = 0;
+  for(index=0, i=0; i<nSize; i++) {
+    conjunct = conjunctArray[i];
+    if(conjunct == 0)	continue;
+    if(conjunct->relation == 0)	continue;
+    
+    if(conjunct->nSize == 1) {
+      id = conjunct->supList[0];
+      if(varType[id] == 2) {
+	if(nextStateFlag) {
+          cid = head->range2domain[id];	
+	  if(constantCase[cid] == 0) {
+	    constantCase[cid] = bdd_dup(conjunct->relation);
+            if(head->verbosity >= 4)
+	      fprintf(vis_stdout, "Detect Constant Case %3d(%c)\n", cid, linearVarString[varType[cid]]);
+	    nConstantCase++;
+	  }
+	}
+	continue;
+      }
+      else {
+	if(constantCase[id] == 0) {
+	  constantCase[id] = bdd_dup(conjunct->relation);
+          if(head->verbosity >= 4)
+	    fprintf(vis_stdout, "Detect Constant Case %3d(%c)\n", id, linearVarString[varType[id]]);
+	  nConstantCase++;
+	}
+        continue;
+      }
+    }
+  }
+
+  if(nConstantCase > 0) {
+    for(i=0; i<head->nSize; i++) {
+      conjunct = conjunctArray[i]; 
+      if(conjunct == 0)	continue;
+      if(conjunct->relation == 0)	continue;
+      relation = conjunct->relation;
+      size = conjunct->nSize;
+      supList = conjunct->supList;
+
+      for(j=0; j<size; j++) {
+	id = supList[j];
+	if(constantCase[id] == 0) 	continue;
+
+	simpleRelation = bdd_cofactor(relation, constantCase[id]); 
+	if(bdd_equal(relation, simpleRelation)) {
+	  bdd_free(simpleRelation);
+	  continue;
+	}
+	if(varType[id] == 1) bOptimize++;
+	bdd_free(conjunct->relation);
+	conjunct->relation = simpleRelation;
+	relation = conjunct->relation;
+	conjunct->bModified = 1;
+	head->bModified = 1;
+	head->bRefineVarArray = 1;
+
+
+        if(head->verbosity >= 2)
+	  fprintf(vis_stdout, "Constant propagation is applied %3d(%c) to %3d'th relation\n", id, linearVarString[varType[id]],  i);
+      }
+      ImgLinearConjunctRefine(head, conjunct);
+    }
+  }
+
+  return(bOptimize);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Remove corresponding current (next) state variables if the next (current state variables are eleminated aftetr clustering]
+
+  Description [Remove corresponding current (next) state variables if the next (current state variables are eleminated aftetr clustering]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+ImgLinearOptimizeStateVariables(Relation_t *head, Img_OptimizeType optDir)
+{
+int *rangeId, *domainId, *existStateVar;
+int *domain2range;
+int *range2domain;
+bdd_t *oneBdd, *varBdd;
+VarLife_t **varArray, *var;
+array_t *smoothVarBddArray;
+Conjunct_t *conjunct;
+int i, id;
+int bOptimize;
+int rangeBound, domainBound;
+int nRangeReduced, nDomainReduced;
+
+  if(optDir == Opt_None)	return(0);
+
+  id = 0;
+  ImgLinearVariableArrayInit(head);
+
+  bOptimize = 0;
+  rangeId = ALLOC(int, head->nRange+1);
+  memset(rangeId, 0, sizeof(int)*(head->nRange+1));
+  domainId = ALLOC(int, head->nDomain+1);
+  memset(domainId, 0, sizeof(int)*(head->nDomain+1));
+  existStateVar = ALLOC(int, head->nVar);
+  memset(existStateVar, 0, sizeof(int)*head->nVar);
+  ImgLinearSetEffectiveNumberOfStateVariable(head, rangeId, domainId, existStateVar);
+
+  rangeBound = (int)((double)head->nInitRange * BACKWARD_REDUCTION_RATE);
+  domainBound = (int)((double)head->nInitDomain * FORWARD_REDUCTION_RATE);
+  if(head->nEffDomain < domainBound) {
+    if(optDir == Opt_Both)	optDir = Opt_NS;
+    else if(optDir == Opt_CS)	optDir = Opt_None;
+  }
+  if(head->nEffRange < rangeBound) {
+    if(optDir == Opt_Both)	optDir = Opt_CS;
+    else if(optDir == Opt_NS)	optDir = Opt_None;
+  }
+  if(optDir == Opt_None)	return(0);
+
+  oneBdd = bdd_one(head->mgr);
+  domain2range = head->domain2range;
+  range2domain = head->range2domain;
+  varArray = head->varArray;
+
+  if(optDir == Opt_Both || optDir == Opt_CS) {
+    smoothVarBddArray = array_alloc(bdd_t *, 0);
+    nDomainReduced = 0;
+    for(i=0; i<head->nEffDomain; i++) {
+      id = domainId[i];
+      if(existStateVar[domain2range[id]]) 	continue;
+
+      var = head->varArrayMap[id] >=0 ? head->varArray[head->varArrayMap[id]] : 0;
+      if(var) {
+	if(head->nEffDomain-nDomainReduced < domainBound)	break;
+        if(var->nSize-head->includeCS == 1) {
+	  varBdd = bdd_get_variable(head->mgr, id);
+	  array_insert_last(bdd_t *, smoothVarBddArray, varBdd);
+	  nDomainReduced++;
+	}	    
+      } 
+    }
+
+    if(array_n(smoothVarBddArray)) {
+      for(i=0; i<head->nSize; i++) {
+	conjunct = head->conjunctArray[i];
+	if(conjunct->nDomain == 0)	continue;
+        if(ImgLinearQuantifyVariablesFromConjunct(
+		      head, conjunct, smoothVarBddArray, &bOptimize)) {
+	  fprintf(vis_stdout, "NOTICE : CS %3d quantified from %d'th relation\n", id, i);
+	}
+      }
+    }
+    mdd_array_free(smoothVarBddArray);
+  }
+
+  if(optDir == Opt_Both || optDir == Opt_NS) {
+    smoothVarBddArray = array_alloc(bdd_t *, 0);
+    nRangeReduced = 0;
+    for(i=0; i<head->nEffRange; i++) {
+      id = rangeId[i];
+      if(existStateVar[range2domain[id]]) 	continue;
+
+      var = head->varArrayMap[id] >=0 ? head->varArray[head->varArrayMap[id]] :
+0;
+      if(var) {
+	if(head->nEffRange-nRangeReduced < rangeBound)	break;
+        if(var->nSize-head->includeNS == 1) {
+	  varBdd = bdd_get_variable(head->mgr, id);
+	  array_insert_last(bdd_t *, smoothVarBddArray, varBdd);
+	  nRangeReduced++;
+	}	    
+      } 
+    }
+
+    if(array_n(smoothVarBddArray)) {
+      for(i=0; i<head->nSize; i++) {
+	conjunct = head->conjunctArray[i];
+	if(conjunct->nRange == 0)	continue;
+        if(ImgLinearQuantifyVariablesFromConjunct(
+		  head, conjunct, smoothVarBddArray, &bOptimize)) {
+	  fprintf(vis_stdout, "NOTICE : NS %3d quantified from %d'th relation\n", id, i);
+	}
+      }
+    }
+    mdd_array_free(smoothVarBddArray);
+  }
+
+  bdd_free(oneBdd);
+  free(rangeId);
+  free(domainId);
+  free(existStateVar);
+
+  ImgLinearVariableArrayInit(head);
+
+  return(bOptimize);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Remove intermediate variables after propagating constant.]
+
+  Description [Remove intermediate variables after propagating constant.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+ImgLinearOptimizeInternalVariables(Relation_t *head)
+{
+bdd_t *oneBdd, *varBdd;
+VarLife_t **varArray, *var;
+Conjunct_t **conjunctArray;
+array_t *smoothVarBddArray;
+int *varType;
+int i, bModified;
+
+  oneBdd = bdd_one(head->mgr);
+  while(1) {
+    bModified = 0;
+    varArray = head->varArray;
+    varType = head->varType;
+    conjunctArray = head->conjunctArray;
+    for(i=0; i<head->nVarArray; i++) {
+      var = head->varArray[i];
+      if(varType[var->id] == 2)
+	continue;
+      if(varType[var->id] == 1 && head->quantifyCS == 0)
+	continue;
+      if(var->from == var->to) {
+	if(conjunctArray[var->from] == 0)	continue;
+        varBdd = bdd_get_variable(head->mgr, var->id);
+        smoothVarBddArray = array_alloc(bdd_t *, 0);
+        array_insert_last(bdd_t *, smoothVarBddArray, varBdd);
+        ImgLinearQuantifyVariablesFromConjunct(
+		head, head->conjunctArray[var->from], smoothVarBddArray, &bModified);
+        mdd_array_free(smoothVarBddArray);
+      }
+    }
+    if(bModified == 0)	break;
+    ImgLinearVariableArrayInit(head);
+  }
+  bdd_free(oneBdd);
+  return;
+}
+
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Refine transition relation.]
+
+  Description [Clean up the Relation_t data structure after applying linear arrangement of transition relation]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+ImgLinearRefineRelation(Relation_t *head)
+{
+  ImgLinearConjunctArrayRefine(head);
+  ImgLinearVariableArrayInit(head);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Order the fine grain transition relation.]
+
+  Description [First find the connected component and apply ordering procedure for each component.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+ImgLinearConjunctOrderMainCC(Relation_t *head, int refineFlag)
+{
+Conjunct_t **connectedArray;
+int i, index;
+char baseName[1024];
+
+  ImgLinearPrintMatrix(head);
+  ImgLinearExtractNextStateCase(head);
+  ImgLinearClusterSameSupportSet(head);
+  ImgLinearRefineRelation(head);
+
+  ImgLinearExtractSingletonCase(head);
+  ImgLinearRefineRelation(head);
+
+  ImgLinearConnectedComponent(head);
+
+  for(i=0; i<head->nConnectedComponent; i++) {
+    connectedArray = head->connectedComponent[i];
+    for(index=0; (long)(connectedArray[index])>0; index++);
+    head->conjunctArray = connectedArray;
+    head->nSize = index;
+    head->bModified = 1;
+    head->bRefineVarArray = 1;
+    qsort(head->conjunctArray, head->nSize, sizeof(Conjunct_t *), 
+	  ImgLinearCompareConjunctSize);
+    ImgLinearVariableArrayInit(head);
+
+    ImgLinearConjunctOrderMain(head, 0);
+    fprintf(stdout, "NOTICE : %d'th connected component\n", i);
+    head->connectedComponent[i] = head->conjunctArray;
+    head->conjunctArray = 0;
+  }
+
+  ImgLinearBuildConjunctArrayWithQuotientCC(head);
+  
+  ImgLinearAddSingletonCase(head);
+  ImgLinearAddNextStateCase(head);
+  ImgLinearExpandSameSupportSet(head);
+  ImgLinearRefineRelation(head);
+
+  ImgLinearRefineRelation(head);
+  ImgLinearPrintMatrix(head);
+
+  sprintf(baseName, "profile");
+  ImgLinearPrintVariableProfile(head, baseName);
+  ImgLinearPrintMatrixFull(head, 2);
+}
+/**Function********************************************************************
+
+  Synopsis    [Order the each connected component]
+
+  Description [The new Relation_t is created for each connected component]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+ImgLinearBuildConjunctArrayWithQuotientCC(Relation_t *head)
+{
+Conjunct_t *conjunct, *tConjunct;
+Conjunct_t **connectedArray;
+Conjunct_t **conjunctArray;
+Conjunct_t **newConjunctArray;
+st_table *table;
+int i, j, k, l;
+int index, id, size;
+int *varType, *supList;
+st_generator *gen;
+char baseName[1024];
+
+  if(head->nConnectedComponent == 1) {
+    size = 0;
+    newConjunctArray = ALLOC(Conjunct_t *, size+1);
+    connectedArray = head->connectedComponent[0];
+    for(j=0; (long)(connectedArray[j])>0; j++) {
+      tConjunct = connectedArray[j];
+      newConjunctArray[size++] = tConjunct;
+      newConjunctArray = REALLOC(Conjunct_t *, newConjunctArray, size+1);
+    }
+    free(head->conjunctArray);
+    head->nSize = size;
+    head->conjunctArray = newConjunctArray;
+    head->bModified = 1;
+    head->bRefineVarArray = 1;
+    ImgLinearRefineRelation(head);
+    return;
+  }
+
+  head->includeCS = 1;
+  head->includeNS = 1;
+  varType = head->varType;
+  conjunctArray = ALLOC(Conjunct_t *, head->nConnectedComponent);
+  for(i=0; i<head->nConnectedComponent; i++) {
+    connectedArray = head->connectedComponent[i];
+
+    table = st_init_table(st_ptrcmp, st_ptrhash);
+    for(j=0; (long)(connectedArray[j])>0; j++) {
+      conjunct = connectedArray[j];
+      size = conjunct->nSize;
+      supList = conjunct->supList;
+      for(k=0; k<size; k++) {
+	id = supList[k];
+	st_insert(table, (char *)(long)id, (char *)(long)id);
+      }
+      for(l=0; l<conjunct->nCluster; l++) {
+	tConjunct = conjunct->clusterArray[l];
+        size = tConjunct->nSize;
+        supList = tConjunct->supList;
+        for(k=0; k<size; k++) {
+	  id = supList[k];
+	  st_insert(table, (char *)(long)id, (char *)(long)id);
+        }
+      }
+    }
+
+    conjunct = ALLOC(Conjunct_t, 1);
+    memset(conjunct, 0, sizeof(Conjunct_t));
+    conjunct->index = i;
+    conjunct->dummy = (long)connectedArray;
+    supList = ALLOC(int, table->num_entries);
+    index = 0;
+    st_foreach_item(table, gen, &id, &id) {
+      if(varType[id] == 1)	conjunct->nDomain++;
+      else if(varType[id] == 2)	conjunct->nRange++;
+      else if(varType[id] == 3)	conjunct->nQuantify++;
+      supList[index++] = id;
+    }
+    conjunct->supList = supList;
+    conjunct->nSize = index;
+
+    conjunctArray[i] = conjunct;
+    conjunct->index = i;
+    conjunct->relation = bdd_zero(head->mgr);
+  }
+
+  head->nSize = head->nConnectedComponent;
+  head->conjunctArray = conjunctArray;
+  head->bRefineVarArray = 1;
+  ImgLinearVariableArrayInit(head);
+
+  sprintf(baseName, "TopCon");
+  ImgLinearCAPOInterfaceConjunctNodes(head, baseName);
+  ImgLinearCAPOInterfaceConjunctNet(head, baseName);
+  ImgLinearCAPOInterfaceConjunctScl(head, baseName);
+  ImgLinearCAPOInterfaceConjunctPl(head, baseName);
+  ImgLinearCAPOInterfaceAux(head, baseName);
+  ImgLinearCAPORun("MetaPlacer", baseName, 0);
+  ImgLinearCAPOReadConjunctOrder(head, baseName);
+
+  size = 0;
+  newConjunctArray = ALLOC(Conjunct_t *, size+1);
+  conjunctArray = head->conjunctArray;
+  for(i=0; i<head->nSize; i++) {
+    conjunct = head->conjunctArray[i];
+    connectedArray = (Conjunct_t **)conjunct->dummy;
+    for(j=0; (long)(connectedArray[j])>0; j++) {
+      tConjunct = connectedArray[j];
+      newConjunctArray[size++] = tConjunct;
+      newConjunctArray = REALLOC(Conjunct_t *, newConjunctArray, size+1);
+    }
+    ImgLinearConjunctQuit(conjunct);
+  }
+  free(conjunctArray);
+  head->conjunctArray = newConjunctArray;
+  head->nSize = size;
+  head->bModified = 1;
+  head->bRefineVarArray = 1;
+  ImgLinearRefineRelation(head);
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Find the connected component from fine grain transition relation]
+
+  Description [Find the connected component from fine grain transition relation]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+ImgLinearConnectedComponent(Relation_t *head)
+{
+Conjunct_t *conjunct;
+Conjunct_t **connectedArray;
+int i, j, index, cc_index;
+int pre_index, pre_cc_index;
+
+  ImgLinearVariableArrayInit(head);
+
+  for(i=0; i<head->nSize; i++) {
+    conjunct = head->conjunctArray[i];
+    conjunct->dummy = 0;
+  }
+
+  cc_index = 0;
+  for(i=0; i<head->nSize; i++) {
+    conjunct = head->conjunctArray[i];
+    if(conjunct->dummy)	continue;
+    cc_index++;
+    ImgLinearFindConnectedComponent(head, conjunct, cc_index);
+  }
+  qsort(head->conjunctArray, head->nSize, sizeof(Conjunct_t *), 
+	             ImgLinearCompareConjunctDummy);
+
+  head->nConnectedComponent = 0;
+  pre_index = 0;
+  pre_cc_index = 1;
+  for(i=0; i<head->nSize; i++) {
+    conjunct = head->conjunctArray[i];
+    if(conjunct->dummy != pre_cc_index) {
+      if((i-pre_index) == 1) { /** singleton case **/
+        head->singletonArray = ImgLinearAddConjunctIntoArray(
+		head->singletonArray, &(head->nSingletonArray), 
+		head->conjunctArray[i-1]);
+      }
+      else { /** connected component case **/
+	if(head->nConnectedComponent)
+	  head->connectedComponent = REALLOC(Conjunct_t **, head->connectedComponent, head->nConnectedComponent+1);
+	else
+	  head->connectedComponent = ALLOC(Conjunct_t **, head->nConnectedComponent+1);
+
+	connectedArray = ALLOC(Conjunct_t *, (i-pre_index+2));
+	head->connectedComponent[head->nConnectedComponent++] = connectedArray;
+	for(index=0, j=pre_index; j<i; j++)
+	  connectedArray[index++] = head->conjunctArray[j];
+	connectedArray[index] = 0;
+      }
+
+      pre_cc_index = conjunct->dummy;
+      pre_index = i;
+    }
+  }
+
+  if((i-pre_index) == 1) { /** singleton case **/
+    head->singletonArray = ImgLinearAddConjunctIntoArray(
+		head->singletonArray, &(head->nSingletonArray), 
+		head->conjunctArray[i-1]);
+  }
+  else { /** connected component case **/
+    if(head->nConnectedComponent)
+      head->connectedComponent = REALLOC(Conjunct_t **,
+head->connectedComponent, head->nConnectedComponent+1);
+
+    else
+      head->connectedComponent = ALLOC(Conjunct_t **,
+head->nConnectedComponent+1);
+
+    connectedArray = ALLOC(Conjunct_t *, (i-pre_index+2));
+    head->connectedComponent[head->nConnectedComponent++] = connectedArray;
+    for(index=0, j=pre_index; j<i; j++)
+      connectedArray[index++] = head->conjunctArray[j];
+    connectedArray[index] = 0;
+  }
+  free(head->conjunctArray);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Find the connected component from fine grain transition relation]
+
+  Description [Find the connected component from fine grain transition relation]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+ImgLinearFindConnectedComponent(Relation_t *head, 
+	                         Conjunct_t *conjunct, 
+				 int cc_index)
+{
+VarLife_t *var;
+int *supList;
+int id, size;
+int index, i, j;
+int *relArr;
+Conjunct_t *tConjunct;
+  
+  if(conjunct->dummy)	return;
+  supList = conjunct->supList;
+  size = conjunct->nSize;
+  conjunct->dummy = cc_index;
+  for(i=0; i<size; i++) {
+    id = supList[i];
+    var = head->varArrayMap[id] >=0 ? head->varArray[head->varArrayMap[id]] : 0;
+   if(!var)	continue;
+    relArr = var->relArr;
+    for(j=0; j<var->nSize; j++) {
+      index = relArr[j];
+      if(index == MAXINT)	continue;
+      if(index == MAXINT-1)	continue;
+      tConjunct = head->conjunctArray[index];
+      if(tConjunct->dummy)	continue;
+      ImgLinearFindConnectedComponent(head, tConjunct, cc_index);
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Extract the relation contains only one next state varaible]
+
+  Description [Extract the relation contains only one next state varaible]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+ImgLinearExtractSingletonCase(Relation_t *head) 
+{
+int i, j, k, id, index;
+VarLife_t **varArray, *var;
+int nSingleton;
+int *supList, *varType;
+Conjunct_t *conjunct, **newSingletonArray;
+int *singletonArray;
+
+  varType = head->varType;
+  varArray = head->varArray;
+  nSingleton = 0;
+  singletonArray = ALLOC(int , nSingleton+1);
+  for(i=0; i<head->nVarArray; i++) {
+    var = varArray[i];
+    if(var->stateVar == 2)	continue;
+    if(var->stateVar == 1) {
+      if(var->nSize - head->includeCS > 1)	continue;
+    }
+    else {
+      if(var->nSize > 1)	continue;
+    }
+
+    for(j=0; j<var->nSize; j++) {
+      if(var->relArr[j] == MAXINT)	continue;
+      if(var->relArr[j] == MAXINT-1)	continue;
+      singletonArray[nSingleton++] = var->relArr[j];
+      singletonArray = REALLOC(int , singletonArray, nSingleton+1);
+    }
+  }
+
+  for(i=0; i<nSingleton; i++) {
+    conjunct = head->conjunctArray[singletonArray[i]];
+    conjunct->bSingleton = 1;
+  }
+
+  for(i=0; i<nSingleton; i++) {
+    conjunct = head->conjunctArray[singletonArray[i]];
+    if(conjunct->nRange == conjunct->nSize-conjunct->nRange &&
+       conjunct->nSize-conjunct->nRange != 1) {
+      conjunct->bSingleton = 0;
+      continue;
+    }
+
+    supList = conjunct->supList;
+    for(j=0; j<conjunct->nSize; j++) {
+      id = supList[j];
+      if(varType[id] == 2)  continue;
+      var = head->varArrayMap[id] >=0 ? head->varArray[head->varArrayMap[id]] : 0;
+      if(!var) 	continue;
+
+      if(var->stateVar == 1) {
+        if(var->nSize - head->includeCS == 1) continue;
+      }
+      else {
+        if(var->nSize == 1)	continue;
+      }
+      for(k=0; k<var->nSize; k++) {
+	index = var->relArr[k];
+	if(index == MAXINT)	continue;
+	if(index == MAXINT-1)	continue;
+	(head->conjunctArray[index])->bSingleton = 0;
+      }
+    }
+  }
+  
+  newSingletonArray = ALLOC(Conjunct_t *, nSingleton);
+  for(index=0, i=0; i<nSingleton; i++) {
+    conjunct = head->conjunctArray[singletonArray[i]];
+    if(conjunct == 0)	continue;
+    if(conjunct->bSingleton) {
+      newSingletonArray[index++] = conjunct;
+      head->conjunctArray[singletonArray[i]] = 0;
+    }
+  }
+  head->nSingletonArray = index;
+  free(singletonArray);
+  qsort(newSingletonArray, head->nSingletonArray, 
+	  sizeof(Conjunct_t *), ImgLinearCompareConjunctRangeMinusDomain);
+  head->singletonArray = newSingletonArray;
+
+  if(head->nSingletonArray)	{
+    head->bModified = 1;
+    head->bRefineVarArray = 1;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Add Conjunct into Cluster Array]
+
+  Description [Add Conjunct into Cluster Array]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+ImgLinearAddConjunctIntoClusterArray(Conjunct_t *base, Conjunct_t *con)
+{
+  if(base->clusterArray == 0) {
+    base->clusterArray = ALLOC(Conjunct_t *, base->nCluster+1);
+    base->clusterArray[base->nCluster++] = con;
+  }
+  else {
+    base->clusterArray = REALLOC(Conjunct_t *, base->clusterArray, base->nCluster+1);
+    base->clusterArray[base->nCluster++] = con;
+  }
+  base->bClustered = 1;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Extract the relation that contains next state varaibles only]
+
+  Description [Extract the relation that contains next state varaibles only]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+ImgLinearExtractNextStateCase(Relation_t *head) 
+{
+int i, index, flag;
+Conjunct_t *conjunct;
+Conjunct_t **nextStateArray;
+
+  index = 0;
+  flag = 1;
+  nextStateArray = ALLOC(Conjunct_t *, index+1);
+  for(index=0, i=head->nSize-1; i>=0; i--) {
+    conjunct = head->conjunctArray[i];
+    if(conjunct == 0)	continue;
+    if(conjunct->nSize == conjunct->nRange && flag == 0) {
+      nextStateArray[index++] = conjunct;
+      nextStateArray = REALLOC(Conjunct_t *, nextStateArray, index+1);
+      head->conjunctArray[i] = 0;
+      head->bModified = 1;
+    }
+    if(conjunct->nSize != conjunct->nRange) flag = 0;
+  }
+  head->nextStateArray = nextStateArray;
+  head->nNextStateArray = index;
+
+  ImgLinearRefineRelation(head);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Free Relation_t data structure]
+
+  Description [Free Relation_t data structure]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+ImgLinearRelationQuit(Relation_t *head)
+{
+int i;
+Conjunct_t *conjunct;
+
+  if(head->varArray)		ImgLinearVariableArrayQuit(head);
+  if(head->rangeVars)		free(head->rangeVars);
+  if(head->domainVars)		free(head->domainVars);
+  if(head->quantifyVars)	free(head->quantifyVars);
+  if(head->varType)		free(head->varType);
+  if(head->varArrayMap)		free(head->varArrayMap);
+
+  if(head->singletonArray)	free(head->singletonArray);
+  if(head->nextStateArray)	free(head->nextStateArray);
+
+  if(head->constantCase) {
+    for(i=0; i<head->nVar; i++)
+      if(head->constantCase[i])	bdd_free(head->constantCase[i]);
+  }
+
+  for(i=0; i<head->nSize; i++) {
+    conjunct = head->conjunctArray[i];
+    ImgLinearConjunctQuit(conjunct);
+  }
+  free(head);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Apply clustering iteratively]
+
+  Description [Apply clustering iteratively]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+ImgLinearClusteringIteratively(Relation_t *head,
+	                        double affinityLimit,
+				int andExistLimit,
+				int varLimit,
+				int includeZeroGain,
+				int useFailureHistory,
+				Img_OptimizeType optDir,
+				int (*compare_func)(const void *, const void *))
+{
+int bddLimit, gainLimit;
+int clusterLimit;
+int bOptimize;
+
+  if(head->nSize < 2)	return(0);
+
+  bOptimize = 0;
+  bddLimit = head->bddLimit;
+  gainLimit = 50;
+
+  while(1) {
+    if(head->nSize < 50)clusterLimit = head->nSize/2;
+    else 		clusterLimit = head->nSize/3+1;
+    if(clusterLimit > 50)	clusterLimit = 50;
+    /**
+    clusterLimit = head->nSize/5;
+    if(clusterLimit < 1)	clusterLimit = 3;
+    **/
+
+    ImgLinearClusteringByConstraints(head, includeZeroGain, varLimit, clusterLimit, 
+	                              gainLimit, affinityLimit, andExistLimit,
+				      bddLimit,  useFailureHistory, compare_func);
+    if(head->bModified) {
+      ImgLinearRefineRelation(head);
+      bOptimize |= ImgLinearOptimizeAll(head, optDir, 0);
+    }
+    else break;
+  }
+  return(bOptimize);
+}
+/**Function********************************************************************
+
+  Synopsis    [Apply clustering with given priority function]
+
+  Description [Apply clustering with given priority function]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+ImgLinearClusteringByConstraints(Relation_t *head, 
+				   int includeZeroGain,
+				   int varLimit,
+				   int clusterLimit,
+				   int gainLimit,
+				   double affinityLimit,
+                                   int andExistLimit,
+				   int bddLimit, 
+				   int useFailureHistory,
+	                           int (*compare_func)(const void *, const void *))
+{
+int size, begin, end;
+int **nDead, **nVar, **nFailure;
+int *dirtyBit;
+int i, j, k, l, index;
+int start, preGain;
+int nClusterArray;
+VarLife_t **varArray, *var;
+Cluster_t **clusterArray, *clu;
+Conjunct_t *conjunct;
+bdd_t *clusteredRelation;
+int fail_flag;
+int from, to, splitable;
+
+  varArray = head->varArray;
+  size = head->nSize;
+
+  nDead = ALLOC(int *, size);
+  nVar = ALLOC(int *, size);
+  nFailure = 0;
+  if(useFailureHistory)
+    nFailure = ALLOC(int *, size);
+  for(i=0; i<size; i++) {
+    nDead[i] = ALLOC(int, size);
+    nVar[i] = ALLOC(int, size);
+    if(useFailureHistory)
+      nFailure[i] = ALLOC(int, size);
+    memset(nDead[i], 0, sizeof(int)*size);
+    memset(nVar[i], 0, sizeof(int)*size);
+    if(useFailureHistory)
+      memset(nFailure[i], 0, sizeof(int)*size);
+  }
+
+  index = 0;
+  for(l=0; l<head->nVarArray; l++) {
+    var = varArray[l];
+    begin = var->from;
+    end = var->to;
+    if(var->stateVar == 1)	begin = -1;
+    else if(var->stateVar == 2)	end = size;
+
+    for(i=0; i<=begin; i++)
+      for(j=end; j<size; j++)
+	nDead[i][j]++;
+
+    for(i=0; i<=var->effTo; i++) {
+      if(i > var->effFrom) {
+	for(k=0; k<var->nSize; k++) {
+	  index = var->relArr[k];
+	  if(index == MAXINT)	continue;
+	  if(index == MAXINT-1)	continue;
+	  if(index >= i)	break;
+	}
+	if(index < i)	start = var->effTo;
+	else		start = index;
+      }
+      else {
+	start = var->effFrom;
+      }
+
+      for(j=start; j<size; j++)
+	nVar[i][j]++;
+    }
+  }
+
+  for(i=0; i<size; i++) {
+    end = (size-1) < i+clusterLimit ? size-1 : i+clusterLimit;
+    if(i==end)	continue;
+    if(nDead[i][end] == 0 && !includeZeroGain)	continue;
+
+    preGain = -1;
+    for(j=end; j>=i; j--) {
+      if(varLimit < nVar[i][j]-nDead[i][j])	continue;
+      if(gainLimit < nDead[i][j])		continue; 
+
+
+      if(preGain != -1) {
+	if(nDead[i][j] < preGain && nDead[i][j] >= 0) {
+	  to = j+1;
+	  for(from=i; from < to; from++) {
+	    if(nDead[from+1][to] != nDead[from][to])	break;
+	  }
+	  if(from != i)	continue;
+
+	  splitable = 0;
+	  for(k=from; k<to; k++) {
+	    if(nDead[from][to] == (nDead[from][k] + nDead[k+1][to])) {
+	      splitable = 1;
+	      break;
+	    }
+	  }
+	  if(!splitable)
+	    ImgLinearInsertClusterCandidate(head, from, to, 
+		             nDead[from][to], nVar[from][to], affinityLimit);
+	}
+      }
+
+      if(nDead[i][j] == 0)	{
+	if(includeZeroGain)
+	  ImgLinearInsertClusterCandidate(head, i, i+1, 
+		             nDead[i][i+1], nVar[i][i+1], affinityLimit);
+	break;
+      }
+
+      preGain = nDead[i][j];
+
+    }
+  }
+  
+  if(head->nClusterArray == 0)	return;
+  qsort(head->clusterArray, head->nClusterArray, sizeof(Cluster_t *),
+compare_func);
+
+  dirtyBit = ALLOC(int, size);
+  memset(dirtyBit, 0, sizeof(int)*size);
+
+  clusterArray = head->clusterArray;
+  nClusterArray = head->nClusterArray;
+  for(i=0; i<nClusterArray; i++) {
+    clu = clusterArray[i];
+    if(useFailureHistory) {
+      if(nFailure[clu->from][clu->to] == 1)	continue;
+    }
+    fail_flag = 0;
+    for(j=clu->from; j<=clu->to; j++) {
+      if(dirtyBit[j] == 1)	{
+	  fail_flag = 1;
+        continue;
+      }
+    }
+    if(fail_flag)	continue;
+
+    clusteredRelation = ImgLinearClusteringSmooth(head, clu, 
+	                   nFailure, andExistLimit, bddLimit);
+
+    conjunct = 0;
+    if(clusteredRelation) {
+      for(j=clu->from; j<=clu->to; j++) {
+	conjunct = head->conjunctArray[j];
+	if(conjunct->relation)	bdd_free(conjunct->relation);
+	conjunct->relation = 0;
+      }
+      conjunct->relation = clusteredRelation;
+      conjunct->bModified = 1;
+      head->bModified = 1;
+      for(j=clu->from; j<=clu->to; j++) dirtyBit[j] = 1;
+
+      if(head->verbosity >= 5)
+        fprintf(stdout, "\tClustering Success : %4d -%4d G(%3d) V(%3d) A(%3d)\n",
+	      clu->from, clu->to, clu->nDead, clu->nVar, clu->nAffinity);
+    }
+    fflush(stdout);
+  }
+
+  for(i=0; i<nClusterArray; i++)
+    free(clusterArray[i]);
+  free(clusterArray);
+  head->clusterArray = 0;
+  head->nClusterArray = 0;
+
+  for(i=0; i<head->nSize; i++) {
+    free(nDead[i]);
+    free(nVar[i]);
+    if(useFailureHistory)
+      free(nFailure[i]);
+  }
+  free(nDead);
+  free(nVar);
+  if(useFailureHistory)
+    free(nFailure);
+
+  return;
+}
+/**Function********************************************************************
+
+  Synopsis    [Add candidates for clustering]
+
+  Description [Add candidates for clustering, each condidate has pair of relation]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearInsertClusterCandidate(Relation_t *head, 
+	                         int from, int to, 
+				 int nDead, int nVar,
+				 double affinityLimit)
+{
+Conjunct_t *conjunct;
+Cluster_t *clu;
+int *varType, *supList;
+int i, j, id, size;
+st_table *table;
+double affinity, tAffinity;
+int preSize, postSize, curSize, overlap;
+
+  varType = head->varType;
+
+  conjunct = head->conjunctArray[from];
+  if(conjunct->relation == 0)	{
+    return;
+  }
+
+  supList = conjunct->supList;
+  size = conjunct->nSize;
+  table = st_init_table(st_numcmp, st_numhash);
+  for(i=0; i<size; i++) {
+    id = supList[i];
+    if(varType[id] == 2)	continue;
+    st_insert(table, (char *)(long)id, (char *)(long)id);
+  }
+
+  tAffinity = 0.0;
+  for(i=from+1; i<=to; i++) {
+    preSize = table->num_entries;
+
+    conjunct = head->conjunctArray[i];
+    if(conjunct->relation == 0)	continue;
+    supList = conjunct->supList;
+    size = conjunct->nSize;
+    curSize = 0;
+    for(j=0; j<size; j++) {
+      id = supList[j];
+
+      if(varType[id] == 2)	continue;
+      curSize++;
+      st_insert(table, (char *)(long)id, (char *)(long)id);
+    }
+
+    postSize = table->num_entries;
+
+    overlap = curSize - (postSize-preSize);
+
+    if(curSize > preSize) 	affinity = (double)overlap/(double)preSize;
+    else			affinity = (double)overlap/(double)curSize;
+
+    /**
+    if(affinity < affinityLimit)	{
+      st_free_table(table);
+      return;
+    }
+    **/
+    tAffinity += affinity;
+  }
+  st_free_table(table);
+
+  tAffinity /= (double)(to-from);
+  clu = ALLOC(Cluster_t, 1);
+  clu->from = from;
+  clu->to = to;
+  clu->nVar = nVar;
+  clu->nDead = nDead;
+  clu->nAffinity = (int)(tAffinity * 100.0);
+
+  head->clusterArray = REALLOC(Cluster_t *, head->clusterArray, head->nClusterArray+1);
+  head->clusterArray[head->nClusterArray++] = clu;
+  if(head->verbosity >= 5) {
+    fprintf(stdout, "Candidate Cluster : %4d-%4d G(%3d) V(%3d) A(%3d)\n",
+	      clu->from, clu->to, clu->nDead, clu->nVar, clu->nAffinity);
+    fflush(stdout);
+  }
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Apply clustering while quantifying the variables that are isolated]
+
+  Description [Apply clustering while quantifying the variables that are isolated]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static bdd_t *
+ImgLinearClusteringSmooth(Relation_t *head, 
+	                   Cluster_t *clu, 
+			   int **failureHistory, 
+			   int andExistLimit,
+			   int bddLimit)
+{
+int *varType, *supList;
+array_t *smoothVarBddArray, *smoothArray;
+Conjunct_t *conjunct;
+bdd_t *relation, *totalRelation;
+bdd_t *varBdd, *tempRelation;
+int i, j, k, tempSize, failFlag;
+int id, tid;
+st_table *deadTable;
+VarLife_t *var;
+
+  varType = head->varType;
+
+  smoothVarBddArray = array_alloc(array_t *, 0);
+  for(i=clu->from; i<=clu->to; i++) {
+    smoothArray = array_alloc(bdd_t *, 0);
+    array_insert_last(array_t *, smoothVarBddArray, smoothArray);
+  }
+
+  deadTable = st_init_table(st_numcmp, st_numhash);
+  for(i=clu->from; i<=clu->to; i++) {
+    conjunct = head->conjunctArray[i];
+    if(conjunct == 0)		continue;
+    if(conjunct->relation == 0)	continue;
+    supList = conjunct->supList;
+    for(j=0; j<conjunct->nSize; j++) {
+      id = supList[j];
+      if(varType[id] == 1 || varType[id] == 2)	continue;
+
+      if(st_lookup(deadTable, (char *)(long)id, &tid)) 	continue;
+
+      var = head->varArray[head->varArrayMap[id]];
+
+      if(clu->from <= var->from && var->to <= clu->to) {
+	st_insert(deadTable, (char *)(long)id, (char *)(long)id);
+	smoothArray = array_fetch(array_t *, smoothVarBddArray,
+var->to-clu->from);
+        varBdd = bdd_get_variable(head->mgr, var->id);
+        array_insert_last(bdd_t *, smoothArray, varBdd);
+      }
+    }
+  }
+  st_free_table(deadTable);
+
+
+  totalRelation = bdd_one(head->mgr);
+  failFlag = 0;
+  for(i=clu->from; i<=clu->to; i++) {
+    conjunct = head->conjunctArray[i];
+    if(conjunct == 0)		continue;
+    if(conjunct->relation == 0)	continue;
+    relation = conjunct->relation;
+    smoothArray = array_fetch(array_t *, smoothVarBddArray, i-clu->from);
+
+    tempRelation = bdd_and_smooth_with_limit(totalRelation, relation, 
+	    				smoothArray, andExistLimit);
+    if(tempRelation) 	tempSize = bdd_size(tempRelation);
+    else 		tempSize = MAXINT;
+
+    if(tempSize > bddLimit) {
+      bdd_free(totalRelation);
+      if(tempRelation)	bdd_free(tempRelation);
+      totalRelation = 0;
+      
+      if(failureHistory) {
+	for(j=0; j<=clu->from; j++) 
+	  for(k=i; k<head->nSize; k++)
+	    failureHistory[j][k] = 1;
+      }
+
+      if(head->verbosity >= 3)
+        fprintf(stdout, "Clustering Failure : %4d-%4d G(%3d) V(%3d) A(%3d) At %3d S(%d)\n",
+	      clu->from, clu->to, clu->nDead, clu->nVar, clu->nAffinity, i, tempSize);
+      break;
+    }
+
+    bdd_free(totalRelation);
+    totalRelation = tempRelation;
+  }
+  ImgLinearFreeSmoothArray(smoothVarBddArray);
+
+  if(failFlag)	return(0);
+  else		return(totalRelation);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Apply clustering with priority queue]
+
+  Description [ Apply clustering with priority queue]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ImgLinearClusterUsingHeap(Relation_t *head,
+	                   double affinityLimit,
+			   int andExistLimit,
+			   int varLimit,
+			   Img_OptimizeType optDir,
+			   int rangeFlag,
+			   int (*compare_func)(const void *, const void *))
+{
+Cluster_t *clu;
+int j;
+Conjunct_t *conjunct;
+bdd_t *clusteredRelation;
+Heap_t *heap;
+int bOptimize;
+long dummy;
+
+  bOptimize = 0;
+  ImgLinearBuildInitialCandidate(head, affinityLimit, varLimit, rangeFlag, compare_func);
+  /** need to consider statevariable optimization **/
+  heap = head->clusterHeap;
+  while(Heap_HeapExtractMin(heap, &clu, &dummy)) {
+    if(clu->flag) {
+      free(clu);
+      continue;
+    }
+    if(clu->to >= head->nSize) {
+      free(clu);
+      continue;
+    }
+
+    clusteredRelation = ImgLinearClusteringPairSmooth(head, clu, 
+	                   0, andExistLimit, head->bddLimit);
+    if(clusteredRelation) {
+      if(head->verbosity >= 5)
+        fprintf(stdout, "\tClustering Success : %4d -%4d G(%3d) V(%3d) A(%3d)\n",
+	      clu->from, clu->to, clu->nDead, clu->nVar, clu->nAffinity);
+      fflush(stdout);
+
+      for(j=clu->from+1; j<=clu->to; j++) {
+	conjunct = head->conjunctArray[j];
+	if(conjunct == 0)	continue;
+	if(conjunct->relation == 0)	continue;
+	bdd_free(conjunct->relation);
+	conjunct->relation = 0;
+      }
+      conjunct = head->conjunctArray[clu->from];
+      if(conjunct->relation)
+        bdd_free(conjunct->relation);
+      conjunct->relation = clusteredRelation;
+      conjunct->bModified = 1;
+      ImgLinearConjunctRefine(head, conjunct);
+      head->bModified = 1;
+      head->bRefineVarArray = 1;
+
+      Heap_HeapApplyForEachElement(heap, linearCheckRange);
+      /**
+      for(i=0; i<heap->nitems; i++) {
+	tclu = (Cluster_t *)(heap->slots[i].item);
+	if(tclu->from <= clu->from && clu->from <= tclu->to)
+	  tclu->flag = 1;
+	if(tclu->from <= clu->to && clu->to <= tclu->to)
+	  tclu->flag = 1;
+      }
+      **/
+
+      ImgLinearInsertPairClusterCandidate(head, clu->from, affinityLimit, varLimit, rangeFlag);
+      ImgLinearInsertPairClusterCandidate(head, clu->from-1, affinityLimit, varLimit, rangeFlag);
+    }
+    if(clu->nDead && clusteredRelation) {
+      ImgLinearVariableArrayInit(head);
+      bOptimize |= ImgLinearOptimizeAll(head, optDir, 0);
+    }
+    free(clu);
+  }
+  Heap_HeapFree(heap);
+  head->clusterHeap = 0;
+
+  if(head->bModified) {
+    if(head->verbosity >= 5)
+      ImgLinearPrintMatrix(head);
+
+    bOptimize |= ImgLinearOptimizeAll(head, optDir, 0);
+    ImgLinearRefineRelation(head);
+
+    if(head->verbosity >= 5)
+      ImgLinearPrintMatrix(head);
+  }
+  return(bOptimize);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [compare function for checking range of cluster]
+
+  Description [compare function for checking range of cluster]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+linearCheckRange(const void *tc)
+{
+Cluster_t *tclu;
+
+  tclu = (Cluster_t *)tc;
+  if(tclu->from <= __clu->from && __clu->from <= tclu->to)
+    tclu->flag = 1;
+  if(tclu->from <= __clu->to && __clu->to <= tclu->to)
+    tclu->flag = 1;
+
+  return(1);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Clustering pair of transition relation]
+
+  Description [Clustering pair of transition relation]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static bdd_t *
+ImgLinearClusteringPairSmooth(Relation_t *head, 
+	                   Cluster_t *clu, 
+			   int **failureHistory, 
+			   int andExistLimit,
+			   int bddLimit)
+{
+int *varType, *supList;
+array_t *smoothArray;
+Conjunct_t *conjunct;
+bdd_t *totalRelation;
+bdd_t *fromRelation, *toRelation;
+bdd_t *varBdd;
+int i, j, k, tempSize;
+int id, tid, effTo;
+st_table *deadTable;
+VarLife_t *var;
+
+  varType = head->varType;
+
+  smoothArray = array_alloc(bdd_t *, 0);
+
+  for(effTo = clu->to+1; effTo<head->nSize; effTo++) {
+    conjunct = head->conjunctArray[effTo];
+    if(conjunct && conjunct->relation)	break;
+  }
+  effTo--;
+
+  deadTable = st_init_table(st_numcmp, st_numhash);
+  for(i=clu->from; i<=clu->to; i++) {
+    conjunct = head->conjunctArray[i];
+    if(conjunct == 0)		continue;
+    if(conjunct->relation == 0)	continue;
+    supList = conjunct->supList;
+    for(j=0; j<conjunct->nSize; j++) {
+      id = supList[j];
+      if(varType[id] == 1 || varType[id] == 2)	continue;
+
+      if(st_lookup(deadTable, (char *)(long)id, &tid)) 	continue;
+
+      var = head->varArray[head->varArrayMap[id]];
+
+      if(clu->from <= var->from && var->to <= effTo) {
+	st_insert(deadTable, (char *)(long)id, (char *)(long)id);
+        varBdd = bdd_get_variable(head->mgr, var->id);
+        array_insert_last(bdd_t *, smoothArray, varBdd);
+      }
+    }
+  }
+  st_free_table(deadTable);
+
+  conjunct = head->conjunctArray[clu->from];
+  fromRelation = conjunct->relation;
+  toRelation = 0;
+  for(i=clu->from+1; i<=clu->to; i++) {
+    conjunct = head->conjunctArray[i];
+    if(conjunct == 0)		continue;
+    if(conjunct->relation == 0)	continue;
+    toRelation = conjunct->relation;
+    break;
+  }
+  if(toRelation == 0) {
+    mdd_array_free(smoothArray);
+    return(0);
+  }
+  if(fromRelation == 0 && toRelation == 0)	return(0);
+  if(fromRelation == 0) {
+    totalRelation = bdd_dup(toRelation);
+  }
+  else if(toRelation == 0) {
+    totalRelation = bdd_dup(fromRelation);
+  }
+  else {
+    totalRelation = bdd_and_smooth_with_limit(fromRelation, toRelation, 
+	    					smoothArray, andExistLimit);
+  }
+  if(totalRelation) 	tempSize = bdd_size(totalRelation);
+  else 			tempSize = MAXINT;
+
+  if(tempSize > bddLimit) {
+    if(totalRelation)	bdd_free(totalRelation);
+    totalRelation = 0;
+    if(failureHistory) {
+      for(j=0; j<=clu->from; j++) 
+	for(k=i; k<head->nSize; k++)
+	  failureHistory[j][k] = 1;
+    }
+    if(head->verbosity >= 3)
+      fprintf(stdout, "Clustering Failure : %4d-%4d G(%3d) V(%3d) A(%3d) At %3d S(%d)\n",
+	      clu->from, clu->to, clu->nDead, clu->nVar, clu->nAffinity, i, tempSize);
+  }
+  mdd_array_free(smoothArray);
+
+  return(totalRelation);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Build data structure for clustering]
+
+  Description [Build data structure for clustering]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+static void 
+ImgLinearBuildInitialCandidate(Relation_t *head, 
+				double affinityLimit,
+				int varLimit, 
+				int rangeFlag,
+	                        int (*compare_func)(const void *, const void *))
+{
+int size, i;
+
+  head->clusterHeap = Heap_HeapInitCompare(head->nSize, compare_func);
+  size = head->nSize;
+  for(i=0; i<size; i++) {
+    ImgLinearInsertPairClusterCandidate(head, i, affinityLimit, varLimit, rangeFlag);
+  }
+  
+  return;
+}
+/**Function********************************************************************
+
+  Synopsis    [Insert initial candidate set]
+
+  Description [Insert initial candidate set]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearInsertPairClusterCandidate(Relation_t *head, 
+	                             int from, 
+				     double affinityLimit,
+				     int varLimit,
+				     int rangeFlag)
+{
+Conjunct_t *conjunct, *fromC, *toC;
+Cluster_t *clu;
+int *varType, *supList;
+st_table *table;
+double affinity;
+int preSize, postSize, curSize, overlap;
+int i, j, id, tid, size, nDead;
+int to, effTo;
+VarLife_t *var;
+
+  if(from < 0)	return;
+  if(from == head->nSize-1)	return;
+ 
+  conjunct = head->conjunctArray[from];
+  if(conjunct == 0 || conjunct->relation == 0) {
+    for(; from>=0; from--) {
+      conjunct = head->conjunctArray[from];
+      if(conjunct == 0)	continue;
+      if(conjunct->relation == 0)	continue;
+      break;
+    }
+  }
+  if(from < 0)	return;
+
+  to = -1;
+  for(i=from+1; i<head->nSize; i++) {
+    conjunct = head->conjunctArray[i];
+    if(!conjunct)	continue;
+    if(conjunct->relation == 0)	continue;
+    to = i;
+    break;
+  }
+  if(to == -1)	return;
+  for(effTo = to+1; effTo<head->nSize; effTo++) {
+    conjunct = head->conjunctArray[effTo];
+    if(conjunct && conjunct->relation)	break;
+  }
+  effTo--;
+
+
+  varType = head->varType;
+
+  fromC = head->conjunctArray[from];
+  toC = head->conjunctArray[to];
+
+  if(rangeFlag && 
+     (fromC->nSize == fromC->nRange || toC->nSize == toC->nRange))
+      return;
+
+  if(fromC->nSize == fromC->nRange && toC->nSize != toC->nRange)
+    return;
+  if(fromC->nSize != fromC->nRange && toC->nSize == toC->nRange)
+    return;
+
+  nDead = 0;
+  supList = fromC->supList;
+  size = fromC->nSize;
+  table = st_init_table(st_numcmp, st_numhash);
+  for(i=0; i<size; i++) {
+    id = supList[i];
+    if(varType[id] == 2)	continue;
+    preSize++;
+    st_insert(table, (char *)(long)id, (char *)(long)id);
+    var = head->varArray[head->varArrayMap[id]];
+    if(from <= var->from && var->to <= effTo)	nDead++;
+  }
+
+  preSize = table->num_entries;
+  supList = toC->supList;
+  size = toC->nSize;
+  curSize = 0;
+  for(j=0; j<size; j++) {
+    id = supList[j];
+    if(varType[id] == 2)	continue;
+    curSize++;
+    if(st_lookup(table, (char *)(long)id, &tid))	continue;
+    st_insert(table, (char *)(long)id, (char *)(long)id);
+    var = head->varArray[head->varArrayMap[id]];
+    if(from <= var->from && var->to <= effTo)	nDead++;
+  }
+
+  postSize = table->num_entries;
+  overlap = curSize - (postSize-preSize);
+  if(overlap == 0)	affinity = 0.0;
+  else {
+    if(curSize > preSize)affinity = (double)overlap/(double)preSize;
+    else		 affinity = (double)overlap/(double)curSize;
+  }
+  st_free_table(table);
+
+  if(affinity < affinityLimit)	return;
+
+  if(affinity == 0.0 && postSize > 10 && 
+	  (fromC->bSingleton || toC->bSingleton))	return;
+  if(postSize-nDead > varLimit)	return;
+
+  clu = ALLOC(Cluster_t, 1);
+  memset(clu, 0, sizeof(Cluster_t));
+  clu->from = from;
+  clu->to = to;
+  clu->nVar = postSize;
+  clu->nDead = nDead;
+  clu->nAffinity = (int)(affinity * 100.0);
+
+  Heap_HeapInsertCompare(head->clusterHeap, (void *)clu, (long)clu);
+  if(head->verbosity >= 5) {
+    fprintf(stdout, "Candidate Cluster : %4d -%4d G(%3d) V(%3d) A(%3d)\n",
+	      clu->from, clu->to, clu->nDead, clu->nVar, clu->nAffinity);
+    fflush(stdout);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Print information of debug information]
+
+  Description [Print information of debug information]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearPrintDebugInfo(Relation_t *head)
+{
+int i, j, id;
+Conjunct_t *conjunct;
+int *supList;
+array_t *smoothVarBddArray;
+array_t *smoothArray;
+bdd_t *varBdd;
+int idPerLine;
+
+  idPerLine = 12;
+
+  fprintf(vis_stdout, "-----------------------------------------------------\n");
+  fprintf(vis_stdout, "     Debug Information for Transition Relations\n");
+  fprintf(vis_stdout, "-----------------------------------------------------\n");
+  fprintf(vis_stdout, "List of Quantify Variables---------------------------\n");
+  for(i=0; i<head->nQuantify; i++) {
+    if(i!=0 && i%idPerLine == 0) fprintf(vis_stdout, "\n");
+    fprintf(vis_stdout, "%3d ", head->quantifyVars[i]);
+  }
+  fprintf(vis_stdout, "\n");
+
+  fprintf(vis_stdout, "List of Domain Variables-----------------------------\n");
+  for(i=0; i<head->nDomain; i++) {
+    if(i!=0 && i%idPerLine == 0) fprintf(vis_stdout, "\n");
+    fprintf(vis_stdout, "%3d ", head->domainVars[i]);
+  }
+  fprintf(vis_stdout, "\n");
+
+  fprintf(vis_stdout, "List of Range Variables------------------------------\n");
+  for(i=0; i<head->nRange; i++) {
+    if(i!=0 && i%idPerLine == 0) fprintf(vis_stdout, "\n");
+    fprintf(vis_stdout, "%3d ", head->rangeVars[i]);
+  }
+  fprintf(vis_stdout, "\n");
+
+  fprintf(vis_stdout, "Varibles in Each Transition Relation-----------------\n");
+  for(i=0; i<head->nSize; i++) {
+    conjunct = head->conjunctArray[i];
+    supList = conjunct->supList;
+    fprintf(vis_stdout, "%3d'th : ", i);
+    for(j=0; j<conjunct->nSize; j++) {
+      if(j!=0 && j%idPerLine == 0) fprintf(vis_stdout, "\n         ");
+      fprintf(vis_stdout, "%3d ", supList[j]);
+    }
+    fprintf(vis_stdout, "\n");
+  }
+
+  smoothVarBddArray = ImgLinearMakeSmoothVarBdd(head, 0);
+  fprintf(vis_stdout, "Quantified Schedule----------------------------------\n");
+  for(i=0; i<=head->nSize; i++) {
+    fprintf(vis_stdout, "%3d'th : ", i);
+    smoothArray = array_fetch(array_t *, smoothVarBddArray, i);
+    for(j=0; j<array_n(smoothArray); j++) {
+      varBdd = array_fetch(bdd_t *, smoothArray, j);
+      id = bdd_top_var_id(varBdd);
+      if(j!=0 && j%idPerLine == 0) fprintf(vis_stdout, "\n         ");
+      fprintf(vis_stdout, "%3d ", id);
+    }
+    fprintf(vis_stdout, "\n");
+  }
+  ImgLinearFreeSmoothArray(smoothVarBddArray);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Main function of linear arrangement]
+
+  Description [ Main function of linear arrangement]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearConjunctOrderMain(Relation_t *head, int bRefineConjunctOrder)
+{
+double aal, atl;
+
+/**
+  head->includeCS = 0;
+  ImgLinearConjunctionOrder(head, "FirstCon", bRefineConjunctOrder);
+  ImgLinearComputeLifeTime(head, &aal, &atl);
+  ImgLinearPrintMatrixFull(head, 0);
+  head->includeCS = 1;
+  tempConjunctArray = ALLOC(Conjunct_t *, head->nSize+1);
+  for(i=0; i<head->nSize; i++) 
+    tempConjunctArray[i] = head->conjunctArray[i];
+  tempAal = aal;
+  tempAtl = atl;
+  fprintf(stdout, "NOTICE : aal %.3f atl %.3f\n", aal, atl);
+  ImgLinearPrintMatrix(head);
+  **/
+
+
+  ImgLinearConjunctionOrder(head, "SecondCon", bRefineConjunctOrder);
+  ImgLinearComputeLifeTime(head, &aal, &atl);
+  ImgLinearPrintMatrixFull(head, 1);
+  fprintf(stdout, "NOTICE : aal %.3f atl %.3f\n", aal, atl);
+  ImgLinearPrintMatrix(head);
+
+  /**
+  if(tempAal < aal) {
+    if( (aal-tempAal) > (tempAtl-atl)*2.0 ) {
+      free(head->conjunctArray);
+      head->conjunctArray = tempConjunctArray;
+      head->bModified = 1;
+      head->bRefineVarArray = 1;
+      ImgLinearRefineRelation(head);
+      fprintf(stdout, "includeCS = 0 is taken\n");
+    }
+    else {
+      fprintf(stdout, "includeCS = 1 is taken\n");
+    }
+  }
+  else {
+    fprintf(stdout, "includeCS = 1 is taken\n");
+  }
+  **/
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Generate linear arrangement with CAPO]
+
+  Description [Generate linear arrangement with CAPO]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearConjunctionOrder(Relation_t *head, char *baseName, int refineFlag)
+{
+Conjunct_t *conjunct;
+int i, j;
+
+
+  if(head->nSize < 2)	return;
+  for(i=0; i<head->nSize; i++) {
+    conjunct = head->conjunctArray[i];
+    conjunct->dummy = 0;
+    for(j=0; j<conjunct->nSize; j++)
+      conjunct->dummy += conjunct->supList[j];
+  }
+  qsort(head->conjunctArray, head->nSize, sizeof(Conjunct_t *), 
+	  ImgLinearCompareConjunctSize);
+  head->bRefineVarArray = 1;
+  ImgLinearRefineRelation(head);
+
+  ImgLinearCAPOInterfaceConjunctNodes(head, baseName);
+  ImgLinearCAPOInterfaceConjunctNet(head, baseName);
+  ImgLinearCAPOInterfaceConjunctScl(head, baseName);
+  ImgLinearCAPOInterfaceConjunctPl(head, baseName);
+  ImgLinearCAPOInterfaceAux(head, baseName);
+  ImgLinearCAPORun("MetaPlacer", baseName, 0);
+  ImgLinearCAPOReadConjunctOrder(head, baseName);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Make interface files for CAPO]
+
+  Description [Make interface files for CAPO]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearCAPOInterfaceConjunctNodes(Relation_t *head, char *baseName)
+{
+char filename[1024];
+FILE *fout;
+int i;
+
+  sprintf(filename, "%s.nodes", baseName);
+  fout = fopen(filename, "w");
+  fprintf(fout, "UCLA nodes 1.0\n");
+  if(head->includeNS) {
+    if(head->includeCS) {
+      fprintf(fout, "NumNodes : %d\n", head->nSize+2);
+      fprintf(fout, "NumTerminals : 2\n");
+    }
+    else {
+      fprintf(fout, "NumNodes : %d\n", head->nSize+1);
+      fprintf(fout, "NumTerminals : 1\n");
+    }
+  }
+  else if(head->includeCS) {
+    fprintf(fout, "NumNodes : %d\n", head->nSize+1);
+    fprintf(fout, "NumTerminals : 1\n");
+  }
+  else {
+    fprintf(fout, "NumNodes : %d\n", head->nSize);
+    fprintf(fout, "NumTerminals : 0\n");
+  }
+  
+  for(i=0; i<head->nSize; i++)
+    fprintf(fout, "C%d 1 1\n", i);
+
+  if(head->includeCS) 
+    fprintf(fout, "C%d 1 1 terminal\n", MAXINT-1);
+
+  if(head->includeNS)
+    fprintf(fout, "C%d 1 1 terminal\n", MAXINT);
+
+  fclose(fout);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Make interface files for CAPO]
+
+  Description [Make interface files for CAPO]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearCAPOInterfaceConjunctNet(Relation_t *head, char *baseName)
+{
+char filename[1024];
+FILE *fout;
+VarLife_t **varArray, *var;
+int i, j, nPin;
+
+  varArray = head->varArray;
+  sprintf(filename, "%s.nets", baseName);
+  fout = fopen(filename, "w");
+  fprintf(fout, "UCLA nets 1.0\n");
+  fprintf(fout, "#NumNets : %d\n", head->nVarArray);
+
+  qsort(head->varArray, head->nVarArray, sizeof(VarLife_t *), ImgLinearCompareVarId);
+  nPin = 0;
+  for(i=0; i<head->nVarArray; i++) {
+    var = varArray[i];
+    if(var->nSize == 1)	nPin += 2;
+    else 		nPin += var->nSize;
+  }
+  fprintf(fout, "NumPins : %d\n", nPin);
+
+  for(i=0; i<head->nVarArray; i++) {
+    var = varArray[i];
+    if(var->nSize == 1)
+      fprintf(fout, "NetDegree : %d S%d\n", var->nSize+1, var->id);
+    else
+      fprintf(fout, "NetDegree : %d S%d\n", var->nSize, var->id);
+
+    for(j=0; j<var->nSize; j++)
+      fprintf(fout, "C%d B\n", var->relArr[j]);
+
+    if(var->nSize == 1) 
+      fprintf(fout, "C%d B\n", var->relArr[0]);
+  }
+  fclose(fout);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Make interface files for CAPO]
+
+  Description [Make interface files for CAPO]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearCAPOInterfaceConjunctScl(Relation_t *head, char *baseName)
+{
+char filename[1024];
+FILE *fout;
+
+  sprintf(filename, "%s.scl", baseName);
+  fout = fopen(filename, "w");
+  fprintf(fout, "UCLA scl 1.0\n");
+  fprintf(fout, "Numrows : 1\n");
+  fprintf(fout, "CoreRow Horizontal\n");
+  fprintf(fout, " Coordinate   : 1\n");
+  fprintf(fout, " Height       : 1\n");
+  fprintf(fout, " Sitewidth    : 1\n");
+  fprintf(fout, " Sitespacing  : 1\n");
+  fprintf(fout, " Siteorient   : N\n");
+  fprintf(fout, " Sitesymmetry : Y\n");
+  fprintf(fout, " SubrowOrigin : 0\n");
+  fprintf(fout, " Numsites     : %d\n", head->nSize*2+2);
+  fprintf(fout, "End\n");
+  fclose(fout);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Make interface files for CAPO]
+
+  Description [Make interface files for CAPO]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearCAPOInterfaceConjunctPl(Relation_t *head, char *baseName)
+{
+char filename[1024];
+FILE *fout;
+int i;
+
+  sprintf(filename, "%s.pl", baseName);
+  fout = fopen(filename, "w");
+
+  fprintf(fout, "UCLA pl 1.0\n");
+  for(i=0; i<head->nSize; i++)
+    fprintf(fout, "C%d %d 1\n", i, (i+2)*2+1);
+
+  if(head->includeCS)
+    fprintf(fout, "C%d 0 1 / N / FIXED\n", MAXINT-1);
+
+  if(head->includeNS)
+    fprintf(fout, "C%d %d 1 / N / FIXED\n", MAXINT, (head->nSize+2)*2+1);
+
+  fclose(fout);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Make interface files for CAPO]
+
+  Description [Make interface files for CAPO]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearCAPOInterfaceAux(Relation_t *head, char *baseName)
+{
+char filename[1024];
+FILE *fout;
+
+  sprintf(filename, "%s.aux", baseName);
+  fout = fopen(filename, "w");
+  fprintf(fout, "RowBasedPlacement : ");
+  fprintf(fout, "%s.nodes %s.nets %s.pl %s.scl\n", 
+  		baseName, baseName, baseName, baseName);
+  fclose(fout);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Run batch job of CAPO]
+
+  Description [Run batch job of CAPO]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ImgLinearCAPORun(char *capoExe, char *baseName, int brief)
+{
+char logFile[1024];
+char capoOption[1024];
+char command[1024];
+char cpCommand[1024];
+FILE *fout;
+int cmdStatus;
+
+  fout = fopen("seeds.in", "w");
+  fprintf(fout, "0\n");
+  fprintf(fout, "460427264\n");
+  fclose(fout);
+
+
+  if(brief) 	
+    sprintf(capoOption, "-replaceSmallBlocks Never -noRowIroning -save -saveXorder");
+  else 		
+    sprintf(capoOption, "-save -saveXorder -clust CutOpt");
+
+  sprintf(logFile, "%s.log", baseName);
+  sprintf(command, "%s -f %s.aux %s > %s", 
+	    capoExe, baseName, capoOption, logFile);
+  cmdStatus = system(command);
+  sprintf(cpCommand, "cp left2right.ord %s.ord", baseName);
+  cmdStatus |= system(cpCommand);
+
+  unlink("seeds.out");
+  unlink("left2right.ord");
+  return (cmdStatus == 0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Read result of CAPO]
+
+  Description [Read result of CAPO]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearCAPOReadConjunctOrder(Relation_t *head, char *baseName)
+{
+char ordFile[1024];
+char line[1024];
+int index, id;
+char *next;
+FILE *fin;
+Conjunct_t *conjunct;
+
+  sprintf(ordFile, "%s.ord", baseName);
+  if(!(fin = fopen(ordFile, "r"))) {
+    fprintf(stdout, "Can't open order file %s\n", ordFile);
+    exit(0);
+  }
+  index = 0;
+  while(fgets(line, 1024, fin)){
+    next = strchr(line, 'C');
+    next++;
+    sscanf(next, "%d", &id);
+    if(id == MAXINT) continue;
+    if(id == MAXINT-1) continue;
+    conjunct = head->conjunctArray[id];
+    conjunct->index = index;
+    index++;
+  }
+  fclose(fin);
+
+  qsort(head->conjunctArray, head->nSize, sizeof(Conjunct_t *), ImgLinearCompareConjunctIndex);
+
+  head->bModified = 1;
+  head->bRefineVarArray = 1;
+  ImgLinearRefineRelation(head);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Make interface for variable ordering]
+
+  Description [Make interface for variable ordering]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearVariableOrder(Relation_t *head, char *baseName, int includeNS)
+{
+  ImgLinearCAPOInterfaceVariableNodes(head, baseName, includeNS);
+  ImgLinearCAPOInterfaceVariableNet(head, baseName, includeNS);
+  ImgLinearCAPOInterfaceVariableScl(head, baseName);
+  ImgLinearCAPOInterfaceVariablePl(head, baseName, includeNS);
+  ImgLinearCAPOInterfaceAux(head, baseName);
+  ImgLinearCAPORun("MetaPlacer", baseName, 0);
+  ImgLinearCAPOReadVariableOrder(head, baseName, includeNS);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Make interface for CAPO]
+
+  Description [Make interface for CAPO]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+ImgLinearCAPOInterfaceVariableNodes(Relation_t *head, char *baseName, int includeNS)
+{
+int i, size;
+VarLife_t **varArray, *var;
+int *varType;
+char filename[1024];
+FILE *fout;
+int numUnused;
+
+  varArray = head->varArray;
+  varType = head->varType;
+  sprintf(filename, "%s.nodes", baseName);
+  fout = fopen(filename, "w");
+
+  fprintf(fout, "UCLA nodes 1.0\n");
+
+  size = 0;
+  if(includeNS)	size = head->nVarArray;
+  else {
+    for(i=0; i<head->nVarArray; i++) {
+      if(varType[varArray[i]->id] == 2)	continue;
+      size++;
+    }
+  }
+
+  numUnused = 0;
+  for(i=0; i<head->nVar; i++) {
+    if(varType[i] != 1)	continue; /* if it is not domain variable **/
+    var = head->varArrayMap[i] >=0 ? head->varArray[head->varArrayMap[i]] : 0;
+    if(var) 	continue;
+    numUnused++;
+  }
+  if(includeNS) {
+    for(i=0; i<head->nVar; i++) {
+      if(varType[i] != 2)	continue; /* if it is not range variable **/
+      var = head->varArrayMap[i] >=0 ? head->varArray[head->varArrayMap[i]] : 0;
+     if(var) 	continue;
+      numUnused++;
+    }
+  }
+  
+  fprintf(fout, "NumNodes : %d\n", size+numUnused);
+  fprintf(fout, "NumTerminals : 0\n");
+  for(i=0; i<head->nVarArray; i++) {
+    var = varArray[i];
+    if(includeNS == 0 && varType[var->id] == 2)	continue;
+    fprintf(fout, "C%d 1 1\n", var->id);
+  }
+
+  for(i=0; i<head->nVar; i++) {
+    if(varType[i] != 1)	continue; /* if it is not domain variable **/
+    var = head->varArrayMap[i] >=0 ? head->varArray[head->varArrayMap[i]] : 0;
+    if(var)	continue;
+    fprintf(fout, "C%d 1 1\n", i);
+  }
+  if(includeNS) {
+    for(i=0; i<head->nVar; i++) {
+      if(varType[i] != 2)	continue; /* if it is not range variable **/
+      var = head->varArrayMap[i] >=0 ? head->varArray[head->varArrayMap[i]] : 0;
+     if(var) 	continue;
+      fprintf(fout, "C%d 1 1\n", i);
+    }
+  }
+  fclose(fout);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Make interface for CAPO]
+
+  Description [Make interface for CAPO]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearCAPOInterfaceVariableNet(Relation_t *head, 
+	                          char *baseName, 
+				  int includeNS)
+{
+int nPin, i, j;
+int id, size;
+Conjunct_t *conjunct;
+bdd_t *relation;
+int *supList, *varType;
+char filename[1024];
+FILE *fout;
+
+  nPin = 0;
+  for(i=0; i<head->nSize; i++) {
+    conjunct = head->conjunctArray[i];
+    relation = conjunct->relation;
+    if(relation == (mdd_t *)(MAXINT-1))	continue;
+    supList = conjunct->supList;
+    if(includeNS) {
+      if(conjunct->nSize == 1)	nPin += 2; 
+      else	  		nPin += conjunct->nSize-conjunct->nRange;
+    }
+    else {
+      if(conjunct->nSize-conjunct->nRange == 1)	nPin += 2;
+      else					nPin += conjunct->nSize-conjunct->nRange;
+    }
+  }
+  nPin += head->nDomain;
+  if(includeNS)
+    nPin += head->nRange;
+
+  varType = head->varType;
+  sprintf(filename, "%s.nets", baseName);
+  fout = fopen(filename, "w");
+  fprintf(fout, "UCLA nets 1.0\n");
+  fprintf(fout, "#NumNets : %d\n", head->nSize);
+  fprintf(fout, "NumPins : %d\n", nPin);
+  for(i=0; i<head->nSize; i++) {
+    conjunct = head->conjunctArray[i];
+    relation = conjunct->relation;
+    if(relation == (mdd_t *)(MAXINT-1))	continue;
+
+    supList = conjunct->supList;
+    if(includeNS)	size = conjunct->nSize;
+    else 		size = conjunct->nSize - conjunct->nRange;
+
+    if(size == 1) 	fprintf(fout, "NetDegree : %d \n", 2);
+    else 		fprintf(fout, "NetDegree : %d \n", size);
+
+    id = 0;
+    if(includeNS) {
+      for(j=0; j<conjunct->nSize; j++) {
+        id = supList[j];
+        fprintf(fout, "C%d B\n", id);
+      }
+    }
+    else {
+      for(j=0; j<conjunct->nSize; j++) {
+        id = supList[j];
+	if(varType[id] == 2) 	continue;
+        fprintf(fout, "C%d B\n", id);
+      }
+    }
+    if(size == 1)
+      fprintf(fout, "C%d B\n", id);
+  }
+  fprintf(fout, "NetDegree : %d \n", head->nDomain);
+  for(i=0; i<head->nVar; i++) {
+    if(varType[i] == 1) 
+      fprintf(fout, "C%d B\n", i);
+  }
+  if(includeNS) {
+    fprintf(fout, "NetDegree : %d \n", head->nRange);
+    for(i=0; i<head->nVar; i++) {
+      if(varType[i] == 2) 
+        fprintf(fout, "C%d B\n", i);
+    }
+  }
+  fclose(fout);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Make interface for CAPO]
+
+  Description [Make interface for CAPO]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearCAPOInterfaceVariableScl(Relation_t *head, char *baseName)
+{
+char filename[1024];
+FILE *fout;
+
+  sprintf(filename, "%s.scl", baseName);
+  fout = fopen(filename, "w");
+  fprintf(fout, "UCLA scl 1.0\n");
+  fprintf(fout, "Numrows : 1\n");
+  fprintf(fout, "CoreRow Horizontal\n");
+  fprintf(fout, " Coordinate   : 1\n");
+  fprintf(fout, " Height       : 1\n");
+  fprintf(fout, " Sitewidth    : 1\n");
+  fprintf(fout, " Sitespacing  : 1\n");
+  fprintf(fout, " Siteorient   : N\n");
+  fprintf(fout, " Sitesymmetry : Y\n");
+  fprintf(fout, " SubrowOrigin : 0\n");
+  fprintf(fout, " Numsites     : %d\n", head->nVarArray*2+2);
+  fprintf(fout, "End\n");
+  fclose(fout);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Make interface for CAPO]
+
+  Description [Make interface for CAPO]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearCAPOInterfaceVariablePl(Relation_t *head, char *baseName, int includeNS)
+{
+char filename[1024];
+FILE *fout;
+VarLife_t *var, **varArray;
+int i, index, *varType;
+
+  varType = head->varType;
+  sprintf(filename, "%s.pl", baseName);
+  fout = fopen(filename, "w");
+  fprintf(fout, "UCLA pl 1.0\n");
+  varArray = head->varArray;
+  for(index=0, i=0; i<head->nVarArray; i++) {
+    var = varArray[i];
+    if(includeNS == 0 && varType[var->id] == 2)	continue;
+    fprintf(fout, "C%d %d 1\n", var->id, (index+1)*2+1);
+    index++;
+  }
+  fclose(fout);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Read result of  CAPO]
+
+  Description [Read result of CAPO]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearCAPOReadVariableOrder(Relation_t *head, char *baseName, int includeNS)
+{
+char ordFile[1024], line[1024];
+FILE *fin;
+char *next;
+int i, id, index, *permutation, *exist;
+
+  sprintf(ordFile, "%s.ord", baseName);
+  if(!(fin = fopen(ordFile, "r"))) {
+    fprintf(stdout, "Can't open order file %s\n", ordFile);
+    exit(0);
+  }
+
+  permutation = ALLOC(int, head->nVar);
+  exist = ALLOC(int, head->nVar);
+  memset(exist, 0, sizeof(int)*head->nVar);
+
+  index = 0;
+  while(fgets(line, 1024, fin)){
+    next = strchr(line, 'C');
+    next++;
+    sscanf(next, "%d", &id);
+    permutation[index++] = id;
+    exist[id] = 1;
+    if(includeNS == 0 && head->varType[id] == 1) {
+      permutation[index++] = head->domain2range[id];
+      exist[head->domain2range[id]] = 1;
+    }
+  }
+  fclose(fin);
+
+  for(i=0; i<head->nVar; i++)
+    if(exist[i] == 0)
+      permutation[index++] = i;
+
+  free(exist);
+
+  bdd_shuffle_heap(head->mgr, permutation);
+
+  free(permutation);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Print profile of variables]
+
+  Description [Print profile of variables]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearPrintVariableProfile(Relation_t *head, char *baseName)
+{
+double aal, atl;
+char filename[1024];
+FILE *fout;
+st_table *cutSet;
+int i, j, nDead, id;
+int *varType;
+int *supList;
+Conjunct_t *conjunct;
+VarLife_t *var;
+st_generator *gen;
+
+  ImgLinearVariableArrayInit(head);
+  varType = head->varType;
+
+  sprintf(filename, "%s.data", baseName);
+  fout = fopen(filename, "w");
+
+  cutSet = st_init_table(st_numcmp, st_numhash);
+  for(i=0; i<head->nVar; i++) {
+    if(varType[i] == 1) 
+      st_insert(cutSet, (char *)(long)i, (char *)(long)i);
+  }
+
+  for(i=0; i<head->nSize; i++) {
+    conjunct = head->conjunctArray[i];
+    supList = conjunct->supList;
+    for(j=0; j<conjunct->nSize; j++)
+      st_insert(cutSet, (char *)(long)supList[j], (char *)(long)supList[j]);
+
+    nDead = 0;
+    st_foreach_item(cutSet, gen, &id, &id) {
+      if(varType[id] == 2) continue;
+
+      var = head->varArrayMap[id] >=0 ? head->varArray[head->varArrayMap[id]] :
+0;
+      if(!var) continue;
+      
+      if(var->to <= i)	{
+	nDead++;
+        st_delete(cutSet, (&id), NULL);
+      }
+    }
+    fprintf(fout, "%d %d %d\n", i, cutSet->num_entries, cutSet->num_entries+nDead);
+  }
+  fclose(fout);
+
+  ImgLinearComputeLifeTime(head, &aal, &atl);
+
+  sprintf(filename, "%s.gnu", baseName);
+  fout = fopen(filename, "w");
+  fprintf(fout, "set terminal postscript \n");
+  fprintf(fout, "set output \"%s.ps\"\n", baseName);
+  fprintf(fout, "set title \"profile of live variable aal %.3f atl %.3f\"\n",
+	  aal, atl);
+  fprintf(fout, "plot \"%s.data\" using 1:2 title \"%s\" with lines, \\\n", baseName, "cut");
+  fprintf(fout, "     \"%s.data\" using 1:3 title \"%s\" with lines\n", baseName, "cut+dead");
+  fclose(fout);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Print matrix]
+
+  Description [Print matrix. Its x axis is varaible and its y axis is relation]
+
+  SideEffects [Print matrix. Its x axis is varaible and its y axis is relation]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+ImgLinearPrintMatrix(Relation_t *head)
+{
+int i, j, id, index;
+int *mapArray;
+VarLife_t **varArray, *var;
+VarLife_t **auxArr, **sortArr;
+int nAuxArr, nSortArr;
+array_t *smoothVarBddArr, *smoothArray;
+bdd_t *varBdd;
+Conjunct_t *conjunct;
+bdd_t *relation;
+int *supList, *varType;
+char *buffer;
+int maxIndex;
+
+  if(head->verbosity < 5)	return;
+
+  ImgLinearVariableArrayInit(head);
+
+  mapArray = ALLOC(int, head->nVar);
+  memset(mapArray, -1, sizeof(int)*head->nVar);
+
+  varArray = head->varArray;
+
+  smoothVarBddArr = ImgLinearMakeSmoothVarBdd(head, 0);
+  for(index=0, i=0; i<array_n(smoothVarBddArr); i++) {
+    smoothArray = array_fetch(array_t *, smoothVarBddArr, i);
+    nAuxArr = 0;
+    auxArr = ALLOC(VarLife_t *, nAuxArr+1);
+    for(j=0; j<array_n(smoothArray); j++) {
+      varBdd = array_fetch(bdd_t *, smoothArray, j);
+      id = (int)bdd_top_var_id(varBdd);
+
+      var = head->varArrayMap[id] >=0 ? head->varArray[head->varArrayMap[id]] :
+0;
+      if(var) {
+	auxArr[nAuxArr++] = var;
+	auxArr = REALLOC(VarLife_t *, auxArr, nAuxArr+1);
+      }
+    }
+    qsort(auxArr, nAuxArr, sizeof(VarLife_t *), ImgLinearCompareVarIndex);
+    for(j=0; j<nAuxArr; j++)
+      mapArray[auxArr[j]->id] = index++;
+    free(auxArr);
+  }
+
+  varArray = head->varArray;
+  nSortArr = 0;
+  sortArr = ALLOC(VarLife_t *, nSortArr+1);
+  for(i=0; i<head->nVarArray; i++) {
+    var = varArray[i];
+    if(var->stateVar == 2)	continue;
+    if(mapArray[var->id] >= 0) {
+      var->index = mapArray[var->id];
+      sortArr[nSortArr++] = var;
+      sortArr = REALLOC(VarLife_t *, sortArr, nSortArr+1);
+    }
+    else {
+      var->index = (double)MAXINT;
+    }
+  }
+  qsort(sortArr, nSortArr, sizeof(VarLife_t *), ImgLinearCompareVarIndex);
+
+  fprintf(stdout, "     ");
+  for(i=0; i<nSortArr; i++) fprintf(stdout, "%d", (i/10)%10);
+  fprintf(stdout, "\n");
+
+  fprintf(stdout, "     ");
+  for(i=0; i<nSortArr; i++) fprintf(stdout, "%d", i%10);
+  fprintf(stdout, "\n");
+
+  buffer = ALLOC(char , nSortArr+1);
+  for(i=0; i<nSortArr; i++) {
+    var = sortArr[i];
+    var->index = (double)i;
+    if(var->stateVar == 1) 	buffer[i] = 'C';
+    else 			buffer[i] = 'T';
+  }
+  buffer[i] = '\0';
+  free(sortArr);
+  fprintf(stdout, "     %s\n", buffer);
+
+  maxIndex = i;
+  for(i=0; i<maxIndex; i++) 	buffer[i] = '.';
+  buffer[i] = '\0';
+
+  varType = head->varType;
+  for(index=0,i=head->nSize-1;i>=0; i--) {
+    conjunct = head->conjunctArray[i];
+    if(conjunct == 0)	continue;
+    if(conjunct->relation == 0)	continue;
+    relation = conjunct->relation;
+    if(relation == (mdd_t *)(MAXINT-1)) continue;
+    if(relation == 0)			continue;
+    supList = conjunct->supList;
+    for(j=0; j<conjunct->nSize; j++) {
+      id = supList[j];
+      if(varType[id] == 2)		continue;
+      var = head->varArrayMap[id] >=0 ? head->varArray[head->varArrayMap[id]] :
+0;
+      if(!var) 	continue;
+      if((int)var->index == MAXINT) 	continue;
+      buffer[(int)var->index] = '1';
+    }
+    index++;
+    fprintf(stdout, "%4d %s %d %d\n", i, buffer, conjunct->nRange, bdd_size(relation));
+    fflush(stdout);
+    for(j=0; j<maxIndex; j++) 	buffer[j] = '.';
+    buffer[j] = '\0';
+  }
+  free(buffer);
+}
+/**Function********************************************************************
+
+  Synopsis    [Print matrix]
+
+  Description [Print matrix]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+ImgLinearPrintMatrixFull(Relation_t *head, int matrixIndex)
+{
+int i, j, id, index;
+int *mapArray;
+VarLife_t **varArray, *var;
+VarLife_t **auxArr, **sortArr;
+int nAuxArr, nSortArr;
+array_t *smoothVarBddArr, *smoothArray;
+FILE *fout;
+int min, max;
+bdd_t *varBdd;
+char filename[1024];
+Conjunct_t *conjunct;
+bdd_t *relation;
+int *supList;
+
+  ImgLinearVariableArrayInit(head);
+
+  mapArray = ALLOC(int, head->nVar);
+  memset(mapArray, -1, sizeof(int)*head->nVar);
+  varArray = head->varArray;
+
+  smoothVarBddArr = ImgLinearMakeSmoothVarBdd(head, 0);
+  for(index=0, i=0; i<array_n(smoothVarBddArr); i++) {
+    smoothArray = array_fetch(array_t *, smoothVarBddArr, i);
+    nAuxArr = 0;
+    auxArr = ALLOC(VarLife_t *, nAuxArr+1);
+    for(j=0; j<array_n(smoothArray); j++) {
+      varBdd = array_fetch(bdd_t *, smoothArray, j);
+      id = (int)bdd_top_var_id(varBdd);
+
+      var = head->varArrayMap[id] >=0 ? varArray[head->varArrayMap[id]] : 0;
+      if(var) {
+	auxArr[nAuxArr++] = var;
+	auxArr = REALLOC(VarLife_t *, auxArr, nAuxArr+1);
+      }
+    }
+    qsort(auxArr, nAuxArr, sizeof(VarLife_t *), ImgLinearCompareVarIndex);
+    for(j=0; j<nAuxArr; j++)
+      mapArray[auxArr[j]->id] = index++;
+    free(auxArr);
+  }
+
+  nSortArr = 0;
+  sortArr = ALLOC(VarLife_t *, nSortArr+1);
+  for(i=0; i<head->nVarArray; i++) {
+    var = varArray[i];
+    if(var->stateVar == 2)	continue;
+    if(mapArray[var->id] >= 0) {
+      var->index = mapArray[var->id];
+      sortArr[nSortArr++] = var;
+      sortArr = REALLOC(VarLife_t *, sortArr, nSortArr+1);
+    }
+    else {
+      var->index = (double)MAXINT;
+    }
+  }
+
+  qsort(sortArr, nSortArr, sizeof(VarLife_t *), ImgLinearCompareVarIndex);
+  free(mapArray);
+
+  sprintf(filename, "fullmatrix%d.data", matrixIndex);
+  fout = fopen(filename, "w");
+  min = 0;
+  max = head->nSize+1;
+  for(i=0; i<nSortArr; i++) {
+    var = sortArr[i];
+    if(var->stateVar == 1)
+      fprintf(fout, "%d %d\n", (int)var->index, min);
+  }
+  free(sortArr);
+
+  for(index=0, i=0; i<head->nSize; i++) {
+    conjunct = head->conjunctArray[i];
+    relation = conjunct->relation;
+    if(relation == (mdd_t *)(MAXINT-1)) continue;
+    if(relation == 0)			continue;
+    supList = conjunct->supList;
+    for(j=0; j<conjunct->nSize; j++) {
+      id = supList[j];
+      var = head->varArrayMap[id] >=0 ? head->varArray[head->varArrayMap[id]] : 0;
+      if(!var)	continue; 
+      if(var->stateVar == 2)
+      if((int)var->index == MAXINT) continue;
+      fprintf(fout, "%d %d\n", (int)var->index, index+1);
+    }
+    index++;
+  }
+  fclose(fout);
+
+  sprintf(filename, "fullmatrix%d.gnu", matrixIndex);
+  fout = fopen(filename, "w");
+  fprintf(fout, "set terminal postscript \n");
+  fprintf(fout, "set output \"fullmatrix%d.ps\"\n", matrixIndex);
+  fprintf(fout, "set title \"profile of live variable\"\n");
+  fprintf(fout, "set yrange [-1:%d]\n", head->nSize+2);
+  fprintf(fout, "plot \"fullmatrix%d.data\" using 1:2 title \"%d\" with point\n",
+		  matrixIndex, matrixIndex);
+  fclose(fout);
+
+  ImgLinearFreeSmoothArray(smoothVarBddArr);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Free smooth variable array]
+
+  Description [Free smooth variable array]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+ImgLinearFreeSmoothArray(array_t *smoothVarBddArray)
+{
+int i;
+array_t *smoothArray;
+
+  for(i=0; i<array_n(smoothVarBddArray); i++) {
+    smoothArray = array_fetch(array_t *, smoothVarBddArray, i);
+    mdd_array_free(smoothArray);
+  }
+  array_free(smoothVarBddArray);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Compute life time of variables]
+
+  Description [Compute life time of variables]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+ImgLinearComputeLifeTime(Relation_t *head, double *paal, double *patl)
+{
+double aal, atl;
+int i;
+VarLife_t **varArray, *var;
+
+  aal = atl = 0.0;
+  varArray = head->varArray;
+  for(i=0; i<head->nVarArray; i++) {
+    var = varArray[i];
+    aal += var->effTo - var->effFrom;
+    if(var->stateVar == 1)	atl += var->to+1;
+    else if(var->stateVar == 2) atl += head->nSize+1 - var->from;
+    else 			atl += var->to - var->from;
+  }
+  atl = atl / (double)(head->nVarArray * head->nSize);
+  aal = aal / (double)(head->nVarArray * head->nSize);
+
+  *paal = aal;
+  *patl = atl;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Print transition relation info]
+
+  Description [Print transition relation info]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearPrintTransitionInfo(Relation_t *head)
+{
+double aal, atl;
+
+  fprintf(stdout, "SUMMARY : domain   variables %d -> %d -> %d\n", 
+	  head->nDomain, head->nInitDomain, head->nEffDomain);
+  fprintf(stdout, "SUMMARY : range    variables %d -> %d -> %d\n", 
+	  head->nRange, head->nInitRange, head->nEffRange);
+  fprintf(stdout, "SUMMARY : quantify variables %d -> %d -> %d\n", 
+	  head->nQuantify, head->nInitQuantify, head->nEffQuantify);
+  fprintf(stdout, "SUMMARY : number of transition relation %d\n", 
+	  head->nSize);
+  ImgLinearComputeLifeTime(head, &aal, &atl);
+  fprintf(stdout, "Active  Life Time : %g\n", aal);
+  fprintf(stdout, "Average Life Time : %g\n", atl);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Make the array of smooth variables]
+
+  Description [Make the array of smooth variables]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+array_t *
+ImgLinearMakeSmoothVarBdd(Relation_t *head, bdd_t **smoothCubeArr)
+{
+array_t *smoothVarBddArray;
+array_t *smoothArray;
+VarLife_t **varArray;
+int i, j, id;
+VarLife_t *var;
+bdd_t *varBdd, *cube, *newCube;
+
+  smoothVarBddArray = array_alloc(array_t *, 0);
+  for(i=0; i<=head->nSize; i++) {
+    smoothArray = array_alloc(bdd_t *, 0);
+    array_insert_last(array_t *, smoothVarBddArray, smoothArray);
+  } 
+
+  varArray = head->varArray;
+  for(i=0; i<head->nVarArray; i++) {
+    var = varArray[i];
+    if(var->stateVar == 2)	continue;
+    smoothArray = array_fetch(array_t *, smoothVarBddArray, var->to+1);
+    varBdd = bdd_get_variable(head->mgr, var->id);
+    array_insert_last(bdd_t *, smoothArray, varBdd);
+  }
+
+  smoothArray = array_fetch(array_t *, smoothVarBddArray, 0);
+  for(i=0; i<head->nDomain; i++) {
+    id = head->domainVars[i];
+    var = head->varArrayMap[id] >=0 ? head->varArray[head->varArrayMap[id]] : 0;
+   if(var)	continue;
+    varBdd = bdd_get_variable(head->mgr, id);
+    array_insert_last(bdd_t *, smoothArray, varBdd);
+  }
+
+  if(smoothCubeArr) {
+    for(i=0; i<=head->nSize; i++) {
+      smoothArray = array_fetch(array_t *, smoothVarBddArray, i);
+      cube = bdd_one(head->mgr);
+      for(j=0; j<array_n(smoothArray); j++) {
+	varBdd = array_fetch(bdd_t *, smoothArray, j);
+	newCube = bdd_and(varBdd, cube, 1, 1);
+	bdd_free(cube);
+	cube = newCube;
+      }
+      smoothCubeArr[i] = cube;
+    }
+  }
+
+  return(smoothVarBddArray);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Priority function for clutering]
+
+  Description [Priority function for clutering]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ImgLinearCompareVarEffFromSmall(const void *c1, const void *c2)
+{
+VarLife_t *con1, *con2;
+
+  con1 = *(VarLife_t **)c1;
+  con2 = *(VarLife_t **)c2;
+  return(con1->effFrom > con2->effFrom);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Priority function for clutering]
+
+  Description [Priority function for clutering]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ImgLinearCompareVarDummyLarge(const void *c1, const void *c2)
+{
+VarLife_t *con1, *con2;
+
+  con1 = *(VarLife_t **)c1;
+  con2 = *(VarLife_t **)c2;
+  return(con1->dummy < con2->dummy);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Priority function for clutering]
+
+  Description [Priority function for clutering]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ImgLinearCompareVarEffFromLarge(const void *c1, const void *c2)
+{
+VarLife_t *con1, *con2;
+
+  con1 = *(VarLife_t **)c1;
+  con2 = *(VarLife_t **)c2;
+  return(con1->effFrom < con2->effFrom);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Priority function for clutering]
+
+  Description [Priority function for clutering]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ImgLinearCompareVarId(const void *c1, const void *c2)
+{
+VarLife_t *con1, *con2;
+
+  con1 = *(VarLife_t **)c1;
+  con2 = *(VarLife_t **)c2;
+  return(con1->id < con2->id);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Priority function for clutering]
+
+  Description [Priority function for clutering]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ImgLinearCompareVarSize(const void *c1, const void *c2)
+{
+VarLife_t *con1, *con2;
+
+  con1 = *(VarLife_t **)c1;
+  con2 = *(VarLife_t **)c2;
+  return(con1->nSize > con2->nSize);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Priority function for clutering]
+
+  Description [Priority function for clutering]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ImgLinearCompareConjunctRangeMinusDomain(const void *c1, const void *c2)
+{
+Conjunct_t *con1, *con2;
+
+  con1 = *(Conjunct_t **)c1;
+  con2 = *(Conjunct_t **)c2;
+  return(con1->nRange-con1->nDomain > con2->nRange-con2->nDomain);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Priority function for clutering]
+
+  Description [Priority function for clutering]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ImgLinearCompareConjunctDummy(const void *c1, const void *c2)
+{
+Conjunct_t *con1, *con2;
+
+  con1 = *(Conjunct_t **)c1;
+  con2 = *(Conjunct_t **)c2;
+  return(con1->dummy > con2->dummy); 
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Priority function for clutering]
+
+  Description [Priority function for clutering]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ImgLinearCompareConjunctIndex(const void *c1, const void *c2)
+{
+Conjunct_t *con1, *con2;
+
+  con1 = *(Conjunct_t **)c1;
+  con2 = *(Conjunct_t **)c2;
+
+  return(con1->index > con2->index); 
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Priority function for clutering]
+
+  Description [Priority function for clutering]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ImgLinearCompareConjunctSize(const void *c1, const void *c2)
+{
+Conjunct_t *con1, *con2;
+
+  con1 = *(Conjunct_t **)c1;
+  con2 = *(Conjunct_t **)c2;
+
+  if(con1->nSize == con2->nSize)
+    return(con1->dummy < con2->dummy);
+  return(con1->nSize < con2->nSize); 
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Priority function for clutering]
+
+  Description [Priority function for clutering]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ImgLinearCompareVarIndex(const void *c1, const void *c2)
+{
+VarLife_t *v1, *v2;
+
+  v1 = *(VarLife_t **)c1;
+  v2 = *(VarLife_t **)c2;
+
+  return(v1->index < v2->index); 
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Priority function for clutering]
+
+  Description [Priority function for clutering]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ImgLinearCompareDeadAffinityLive(const void *c1, const void *c2)
+{
+Cluster_t *clu1, *clu2;
+
+  clu1 = *(Cluster_t **)c1;
+  clu2 = *(Cluster_t **)c2;
+  if(clu1->nDead == clu2->nDead) {
+    if(clu1->nAffinity == clu2->nAffinity) {
+      return(clu1->nVar-clu1->nDead > clu2->nVar-clu2->nDead); 
+    }
+    return(clu1->nAffinity < clu2->nAffinity); 
+  }
+  return(clu1->nDead < clu2->nDead); 
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Priority function for clutering]
+
+  Description [Priority function for clutering]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ImgLinearCompareDeadLiveAffinity(const void *c1, const void *c2)
+{
+Cluster_t *clu1, *clu2;
+
+  clu1 = *(Cluster_t **)c1;
+  clu2 = *(Cluster_t **)c2;
+  if(clu1->nDead == clu2->nDead) {
+    if(clu1->nVar-clu1->nDead == clu2->nVar-clu2->nDead) {
+      return(clu1->nAffinity < clu2->nAffinity); 
+    }
+    return(clu1->nVar-clu1->nDead > clu2->nVar-clu2->nDead); 
+  }
+  return(clu1->nDead < clu2->nDead); 
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Priority function for clutering]
+
+  Description [Priority function for clutering]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ImgLinearCompareAffinityDeadLive(const void *c1, const void *c2)
+{
+Cluster_t *clu1, *clu2;
+
+  clu1 = *(Cluster_t **)c1;
+  clu2 = *(Cluster_t **)c2;
+  if(clu1->nAffinity == clu2->nAffinity) {
+    if(clu1->nDead == clu2->nDead) {
+      return(clu1->nVar-clu1->nDead > clu2->nVar-clu2->nDead); 
+    }
+    return(clu1->nDead < clu2->nDead); 
+  }
+  return(clu1->nAffinity < clu2->nAffinity); 
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Priority function for clutering]
+
+  Description [Priority function for clutering]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ImgLinearCompareLiveAffinityDead(const void *c1, const void *c2)
+{
+Cluster_t *clu1, *clu2;
+
+  clu1 = *(Cluster_t **)c1;
+  clu2 = *(Cluster_t **)c2;
+  if(clu1->nVar-clu1->nDead == clu2->nVar-clu2->nDead) {
+    if(clu1->nAffinity == clu2->nAffinity) {
+      return(clu1->nDead < clu2->nDead);
+    }
+    return(clu1->nAffinity < clu2->nAffinity);
+  }
+  return(clu1->nVar-clu1->nDead > clu2->nVar-clu2->nDead);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Priority function for clutering]
+
+  Description [Priority function for clutering]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ImgLinearHeapCompareDeadAffinityLive(const void *c1, const void *c2)
+{
+Cluster_t *clu1, *clu2;
+
+  clu1 = (Cluster_t *)c1;
+  clu2 = (Cluster_t *)c2;
+  if(clu1->nDead == clu2->nDead) {
+    if(clu1->nAffinity == clu2->nAffinity) {
+      return((clu1->nVar-clu1->nDead) > (clu2->nVar-clu2->nDead)); 
+    }
+    return(clu1->nAffinity < clu2->nAffinity); 
+  }
+  return(clu1->nDead < clu2->nDead); 
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Priority function for clutering]
+
+  Description [Priority function for clutering]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ImgLinearHeapCompareDeadLiveAffinity(const void *c1, const void *c2)
+{
+Cluster_t *clu1, *clu2;
+
+  clu1 = (Cluster_t *)c1;
+  clu2 = (Cluster_t *)c2;
+  if(clu1->nDead == clu2->nDead) {
+    if((clu1->nVar-clu1->nDead) == (clu2->nVar-clu2->nDead)) {
+      return(clu1->nAffinity < clu2->nAffinity); 
+    }
+    return((clu1->nVar-clu1->nDead) > (clu2->nVar-clu2->nDead)); 
+  }
+  return(clu1->nDead < clu2->nDead); 
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Priority function for clutering]
+
+  Description [Priority function for clutering]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ImgLinearHeapCompareAffinityDeadLive(const void *c1, const void *c2)
+{
+Cluster_t *clu1, *clu2;
+
+  clu1 = (Cluster_t *)c1;
+  clu2 = (Cluster_t *)c2;
+  if(clu1->nAffinity == clu2->nAffinity) {
+    if(clu1->nDead == clu2->nDead) {
+      return(clu1->nVar-clu1->nDead > clu2->nVar-clu2->nDead); 
+    }
+    return(clu1->nDead < clu2->nDead); 
+  }
+  return(clu1->nAffinity < clu2->nAffinity); 
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Priority function for clutering]
+
+  Description [Priority function for clutering]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ImgLinearHeapCompareLiveAffinityDead(const void *c1, const void *c2)
+{
+Cluster_t *clu1, *clu2;
+
+  clu1 = (Cluster_t *)c1;
+  clu2 = (Cluster_t *)c2;
+  if(clu1->nVar-clu1->nDead == clu2->nVar-clu2->nDead) {
+    if(clu1->nAffinity == clu2->nAffinity) {
+      return(clu1->nDead < clu2->nDead);
+    }
+    return(clu1->nAffinity < clu2->nAffinity);
+  }
+  return(clu1->nVar-clu1->nDead > clu2->nVar-clu2->nDead);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Initialize variable array]
+
+  Description [Initialize variable array]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearVariableArrayInit(Relation_t *head)
+{
+mdd_manager *mgr;
+Conjunct_t **conjunctArray, *conjunct;
+Conjunct_t *tConjunct;
+bdd_t *relation, *bddOne;
+VarLife_t **varArray;
+int *supList, listSize;
+int *varType, *varArrayMap;
+int i, j, k, id, nVarArray;
+int nSize, newNum;
+
+
+  if(head->bRefineVarArray) {
+    ImgLinearVariableArrayQuit(head);
+  }
+
+  if(head->varArray)	return;
+
+  mgr = head->mgr;
+
+  if(head->nVar != (int)(bdd_num_vars(mgr))) {
+    newNum = bdd_num_vars(head->mgr);
+    head->domain2range = REALLOC(int, head->domain2range, newNum);
+    head->range2domain = REALLOC(int, head->range2domain, newNum);
+    head->varType = REALLOC(int, head->varType, newNum);
+    head->varArrayMap = REALLOC(int, head->varArrayMap, newNum);
+    head->constantCase = REALLOC(bdd_t *, head->constantCase, newNum);
+    head->quantifyVars = REALLOC(int, head->quantifyVars, newNum);
+
+    for(i=head->nVar; i<newNum; i++) {
+      head->domain2range[i] = -1;
+      head->range2domain[i] = -1;
+      head->varType[i] = 0;
+      head->varArrayMap[i] = -1;
+      head->constantCase[i] = 0;
+      head->quantifyVars[i] = 0;
+    }
+    head->nVar = bdd_num_vars(head->mgr);
+  }
+
+  nSize = head->nSize;
+  conjunctArray = head->conjunctArray;
+  varArrayMap = head->varArrayMap;
+
+  id = 0;
+  nVarArray = 0;
+  varArray = ALLOC(VarLife_t *, nVarArray+1);
+  head->varArray = varArray;
+  head->nVarArray = nVarArray;
+  bddOne = bdd_one(head->mgr);
+
+  varType = head->varType;
+  for(i=0; i<nSize; i++) {
+    conjunct = conjunctArray[i];
+    if(conjunct == 0)	continue;
+    relation = conjunct->relation;
+    if(relation == 0)	continue;
+    if(bdd_equal(bddOne, relation))	continue;
+    supList = conjunct->supList;
+    listSize = conjunct->nSize;
+    for(j=0; j<listSize; j++) {
+      id = supList[j]; 
+      ImgLinearUpdateVariableArrayWithId(head, i, id);
+    }
+
+    for(k=0; k<conjunct->nCluster; k++) {
+      tConjunct = conjunct->clusterArray[k];
+      supList = tConjunct->supList;
+      listSize = tConjunct->nSize;
+      for(j=0; j<listSize; j++) {
+        ImgLinearUpdateVariableArrayWithId(head, i, id);
+      }
+    }
+  }
+  bdd_free(bddOne);
+  head->bRefineVarArray = 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Update variable array with id of variable id]
+
+  Description [Update variable array with id of variable id]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearUpdateVariableArrayWithId(Relation_t *head, 
+	                           int cindex, 
+				   int id)
+{
+VarLife_t *var;
+int *varType;
+int *varArrayMap;
+int nVarArray;
+VarLife_t **varArray;
+
+  varType = head->varType;
+  varArrayMap = head->varArrayMap;
+  varArray = head->varArray;
+  nVarArray = head->nVarArray;
+
+  if(varArrayMap[id] == -1) {
+    var = ALLOC(VarLife_t, 1);
+    var->id = id;
+    var->from = cindex;
+    var->to = cindex;
+    var->effFrom = cindex;
+    var->effTo = cindex;
+    var->stateVar = 0;
+    var->relArr = ALLOC(int, 1);
+    var->nSize = 0;
+    var->index = 0.0;
+    varArrayMap[id] = nVarArray;
+    varArray[nVarArray++] = var;
+    varArray = REALLOC(VarLife_t *, varArray, nVarArray+1);
+
+    if(varType[id] == 1) {
+      var->stateVar = 1;
+      if(head->includeCS && !head->quantifyCS) { 
+	var->relArr = REALLOC(int, var->relArr, var->nSize+1);
+	var->relArr[var->nSize++] = MAXINT-1;
+	var->from = -1;
+      }
+    }
+    else if(varType[id] == 2) {
+      var->stateVar = 2;
+      if(head->includeNS) { 
+	var->relArr = REALLOC(int, var->relArr, var->nSize+1);
+	var->relArr[var->nSize++] = MAXINT;
+	var->to = head->nSize;
+      }
+    }
+  }
+  else {
+    var = varArray[varArrayMap[id]];
+  }
+  
+  if(var->to < cindex)		var->to = cindex;
+  if(var->from > cindex)	var->from = cindex;
+
+  if(var->effTo < cindex)	var->effTo = cindex;
+  if(var->effFrom > cindex)	var->effFrom = cindex;
+
+  var->relArr = REALLOC(int, var->relArr, var->nSize+1);
+  var->relArr[var->nSize++] = cindex;
+  head->varArray = varArray;
+  head->nVarArray = nVarArray;
+}
+/**Function********************************************************************
+
+  Synopsis    [Apply quantification with candidate variables]
+
+  Description [Apply quantification with candidate variables]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ImgLinearQuantifyVariablesFromConjunct(Relation_t *head,
+	                               Conjunct_t *conjunct, 
+	                               array_t *smoothVarBddArray,
+				       int *bModified)
+{
+bdd_t *relation, *simpleRelation;
+
+  if(conjunct == 0)	return 1;
+  relation = conjunct->relation;
+  if(relation == 0)	return 1;
+
+  simpleRelation = bdd_smooth(relation, smoothVarBddArray);
+  if(bdd_equal(relation, simpleRelation)) {
+    bdd_free(simpleRelation);
+    return 0;
+  }
+  bdd_free(relation);
+
+  (*bModified)++;
+  conjunct->relation = simpleRelation;
+  conjunct->bModified = 1;
+  head->bModified = 1;
+  head->bRefineVarArray = 1;
+  ImgLinearConjunctRefine(head, conjunct);
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Refine conjunction array to fill the empty slot.]
+
+  Description [Refine conjunction array to fill the empty slot.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearConjunctRefine(Relation_t *head, Conjunct_t *conjunct)
+{
+int i, id, listSize, *supList;
+int *varType;
+
+  if(conjunct->relation == 0)	{
+    if(conjunct->supList)	free(conjunct->supList);
+    conjunct->supList = 0;
+    return;
+  }
+  if(!conjunct->bModified)	return; 
+
+  if(conjunct->supList) {
+    free(conjunct->supList);
+    conjunct->supList = 0;
+  }
+
+  supList = ImgLinearGetSupportBddId(head->mgr, conjunct->relation, &listSize);
+  if(listSize == 0) {
+    conjunct->relation = 0;
+    if(conjunct->supList) {
+      free(conjunct->supList);
+      conjunct->supList = 0;
+    }
+    return;
+  }
+  else {
+    varType = head->varType;
+    conjunct->supList = supList;
+    conjunct->nSize = listSize;
+    conjunct->bModified = 0;
+    conjunct->nDomain = 0;
+    conjunct->nRange = 0;
+    conjunct->nQuantify = 0;
+    conjunct->from = 0;
+    conjunct->to = 0;
+    conjunct->dummy = 0;
+    for(i=0; i<listSize; i++) {
+      id = supList[i];
+      if(varType[id] == 1)	conjunct->nDomain++;
+      else if(varType[id] == 2)	conjunct->nRange++;
+      else if(varType[id] == 3)	conjunct->nQuantify++;
+    }
+    head->bModified = 1;
+  }
+  return;
+}
+/**Function********************************************************************
+
+  Synopsis    [Refine conjunction array to fill the empty slot.]
+
+  Description [Refine conjunction array to fill the empty slot.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearConjunctArrayRefine(Relation_t *head)
+{
+int nSize, i;
+int index;
+Conjunct_t **conjunctArray, **newConjunctArray;
+Conjunct_t *conjunct;
+
+  if(head->bModified == 0)	return;
+
+  conjunctArray = head->conjunctArray;
+  newConjunctArray = ALLOC(Conjunct_t *, head->nSize+1);
+  nSize = head->nSize;
+  for(index=0, i=0; i<nSize; i++) {
+    conjunct = conjunctArray[i];
+    if(conjunct == 0)	{
+      head->bRefineVarArray = 1;
+      continue;
+    }
+    if(conjunct->relation == 0)	{
+      ImgLinearConjunctQuit(conjunct);
+      head->bRefineVarArray = 1;
+      continue;
+    }
+
+    if(conjunct->bModified) {
+      ImgLinearConjunctRefine(head, conjunct);
+      head->bRefineVarArray = 1;
+    }
+
+    if(conjunct == 0)	continue;
+    if(conjunct->relation == 0)	{
+      ImgLinearConjunctQuit(conjunct);
+      continue;
+    }
+
+    newConjunctArray[index] = conjunct;
+    conjunct->index = index++;
+  }
+  newConjunctArray[index] = 0;
+  free(conjunctArray);
+  head->conjunctArray = newConjunctArray;
+  head->nSize = index;
+  head->bModified = 0;
+  return; 
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Get the number of state variables after applying optimization]
+
+  Description [Get the number of state variables after applying optimization]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearSetEffectiveNumberOfStateVariable(Relation_t *head, 
+	                                    int *rangeId, 
+					    int *domainId,
+					    int *existStateVariable) 
+{
+VarLife_t **varArray, *var;
+int *varType;
+int nRange, nDomain, nQuantify;
+int i;
+
+  varArray = head->varArray;
+  varType = head->varType;
+  nRange = nDomain = nQuantify = 0;
+
+  for(i=0; i<head->nVarArray; i++) {
+    var = varArray[i];
+    if(varType[var->id] == 1) 	{
+      if(domainId) domainId[nDomain] = var->id;
+      nDomain++;
+      if(existStateVariable) existStateVariable[var->id] = 1;
+    }
+    else if(varType[var->id] == 2) 	{
+      if(rangeId) rangeId[nRange] = var->id;
+      nRange++;
+      if(existStateVariable) existStateVariable[var->id] = 1;
+    }
+    else if(varType[var->id] == 3) 	{
+      nQuantify++;
+    }
+    else
+      nQuantify++;
+
+  } 
+  if(domainId)	domainId[nDomain] = -1;
+  if(rangeId)	rangeId[nRange] = -1;
+
+  head->nEffRange = nRange;
+  head->nEffDomain = nDomain;
+  head->nEffQuantify = nQuantify;
+
+  if(head->nInitRange == 0 && head->nInitDomain == 0 && head->nInitQuantify == 0) {
+    head->nInitRange = nRange;
+    head->nInitDomain = nDomain;
+    head->nInitQuantify = nQuantify;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Find the case that the relation contains only one next state varaible]
+
+  Description [Find the case that the relation contains only one next state varaible]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearAddSingletonCase(Relation_t *head)
+{
+Conjunct_t **newConjunctArray;
+Conjunct_t **singletonArray;
+Conjunct_t *conjunct;
+int i, j, index;
+int nSingletonArray;
+int putFlag;
+
+  nSingletonArray = head->nSingletonArray;
+  singletonArray = head->singletonArray;
+
+  if(nSingletonArray == 0) 	return;
+  fprintf(stdout, "NOTICE : %d singleton case will be added\n", nSingletonArray);
+
+  qsort(singletonArray, nSingletonArray, sizeof(Conjunct_t *), ImgLinearCompareConjunctRangeMinusDomain);
+
+  index = 0;
+  newConjunctArray = ALLOC(Conjunct_t *, head->nSize + nSingletonArray);
+  putFlag = 0;
+  for(i=0; i<nSingletonArray; i++) {
+    conjunct = singletonArray[i];
+    if(putFlag == 0 && conjunct->nRange > conjunct->nSize-conjunct->nRange) {
+      putFlag = 1;
+      for(j=0; j<head->nSize; j++) 
+	newConjunctArray[index++] = head->conjunctArray[j];
+    }
+    newConjunctArray[index++] = singletonArray[i];
+  }
+  if(putFlag == 0) {
+    for(j=0; j<head->nSize; j++) 
+      newConjunctArray[index++] = head->conjunctArray[j];
+  }
+
+  head->nSize = index;
+  head->bModified = 1;
+  head->bRefineVarArray = 1;
+  free(head->conjunctArray);
+  head->conjunctArray = newConjunctArray;
+  free(singletonArray);
+  head->singletonArray = 0;
+  head->nSingletonArray = 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Find transtion relations that have smae support set]
+
+  Description [Find transtion relations that have smae support set and use this information when finding linear arragement]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearExpandSameSupportSet(Relation_t *head)
+{
+int index, i, j;
+Conjunct_t **newConjunctArray;
+Conjunct_t *conjunct;
+
+  newConjunctArray = ALLOC(Conjunct_t *, head->nSize);
+  for(index=0, i=0; i<head->nSize; i++) {
+    if(index >= head->nSize)
+      newConjunctArray = REALLOC(Conjunct_t *, newConjunctArray, index+1);
+    conjunct = head->conjunctArray[i];
+    newConjunctArray[index++] = conjunct;
+    if(conjunct->nCluster) {
+      for(j=0; j<conjunct->nCluster; j++) {
+        if(index >= head->nSize)
+          newConjunctArray = REALLOC(Conjunct_t *, newConjunctArray, index+1);
+	newConjunctArray[index++] = conjunct->clusterArray[j];
+      }
+      head->bModified = 1;
+      head->bRefineVarArray = 1;
+      conjunct->nCluster = 0;
+      if(conjunct->clusterArray) {
+	free(conjunct->clusterArray);
+	conjunct->clusterArray = 0;
+      }
+    }
+  }
+  free(head->conjunctArray);
+  head->conjunctArray = newConjunctArray;
+  head->nSize = index;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Cluster the relation that has same support set]
+
+  Description [Cluster the relation that has same support set]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearClusterSameSupportSet(Relation_t *head) 
+{
+int i, j, index, id;
+int *supList;
+Conjunct_t *conjunct, *base;
+int *varType;
+Conjunct_t **conjunctArray, **newConjunctArray;
+
+  head->nTotalCluster = 0;
+  varType = head->varType;
+  conjunctArray = head->conjunctArray; 
+
+  for(i=0; i<head->nSize; i++) {
+    conjunct = head->conjunctArray[i];
+    supList = conjunct->supList;
+    conjunct->dummy = 0;
+    for(j=0; j<conjunct->nSize; j++) {
+      id = supList[j];
+      if(varType[id] == 2)	continue;
+      conjunct->dummy += id;
+    }
+    conjunct->dummy *= (conjunct->nSize-conjunct->nRange);
+    conjunct->dummy -= conjunct->nDomain;
+  }
+  qsort(conjunctArray, head->nSize, sizeof(Conjunct_t *), 
+	                ImgLinearCompareConjunctDummy);
+
+  for(i=0; i<head->nSize; i++) {
+    base = head->conjunctArray[i];
+    for(j=i+1; j<head->nSize; j++) {
+      conjunct = head->conjunctArray[j];
+      if(base->dummy != conjunct->dummy) {
+	if(j == i+1)	break;
+        ImgLinearFindSameSupportConjuncts(head, i, j-1);
+	i = j-1;
+	break;
+      }
+    }
+  }
+
+  if(head->bModified)	{
+    conjunctArray = head->conjunctArray;
+    newConjunctArray = ALLOC(Conjunct_t *, head->nSize);
+    for(index=0, i=0; i<head->nSize; i++) {
+      conjunct = conjunctArray[i];
+      if(conjunct == 0)	continue;
+      newConjunctArray[index++] = conjunct;
+    }
+    free(conjunctArray);
+    head->conjunctArray = newConjunctArray;
+    head->nSize = index;
+    head->bModified = 1;
+    head->bRefineVarArray = 1;
+  }
+
+  conjunctArray = head->conjunctArray;
+  qsort(conjunctArray, head->nSize, sizeof(Conjunct_t *), ImgLinearCompareConjunctIndex);
+  if(head->bModified)	{
+    conjunctArray = head->conjunctArray;
+    for(i=0; i<head->nSize; i++) {
+      conjunct = conjunctArray[i];
+      if(conjunct == 0)	continue;
+      conjunct->index = i;
+    }
+  }
+  fprintf(stdout, "NOTICE : %d conjunct clustered\n", head->nTotalCluster);
+  head->nTotalCluster = 0;
+
+}
+/**Function********************************************************************
+
+  Synopsis    [Find the conjuncts that have same support variables.]
+
+  Description [Find the conjuncts that have same support variables.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearFindSameSupportConjuncts(Relation_t *head, int from, int to)
+{
+Conjunct_t *con1, *con2;
+int i, j;
+
+  for(i=from; i<=to; i++) {
+    con1 = head->conjunctArray[i];
+    if(con1 == 0)	continue;
+
+    for(j=from; j<=to; j++) {
+      if(i == j)	continue;
+      con2 = head->conjunctArray[j];
+      if(con2 == 0)	continue;
+      if(ImgLinearIsSameConjunct(head, con1, con2)) {
+        ImgLinearAddConjunctIntoClusterArray(con1, con2);
+	head->conjunctArray[j] = 0;
+
+	head->bModified = 1;
+	head->bRefineVarArray = 1;
+	head->nTotalCluster++;
+      }
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Check if given conjuncts have same support variables]
+
+  Description [Check if given conjuncts have same support variables]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ImgLinearIsSameConjunct(Relation_t *head, Conjunct_t *con1, Conjunct_t *con2)
+{
+int i, j;
+int *sup1, *sup2;
+int id1, id2;
+int *varType;
+
+  if(con1->nDomain != con2->nDomain)	return(0);
+  if(con1->nSize-con1->nRange != con2->nSize-con2->nRange)	return(0);
+  sup1 = con1->supList;
+  sup2 = con2->supList;
+
+  varType = head->varType;
+
+  for(j=0, i=0; i<con1->nSize; i++) {
+    id1 = sup1[i];
+    if(varType[id1] == 2)continue;
+    while(1) {
+      id2 = sup2[j];
+      if(varType[id2] == 2) {
+	j++;
+        continue;
+      }
+      if(id1 != id2)	return(0);
+      j++;
+      break;
+    }
+  }
+  return(1);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Add conjunct into array]
+
+  Description [Add conjunct into array]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static Conjunct_t **
+ImgLinearAddConjunctIntoArray(Conjunct_t **array, int *nArray, Conjunct_t *con)
+{
+  if(array)
+    array = REALLOC(Conjunct_t *, array, (*nArray)+1);
+  else 
+    array = ALLOC(Conjunct_t *, (*nArray)+1);
+  array[(*nArray)++] = con;
+  return(array);
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Free conjunct_t data structure]
+
+  Description [Free conjunct_t data structure]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearConjunctQuit(Conjunct_t *conjunct)
+{
+  if(conjunct->supList)	{
+    free(conjunct->supList);
+    conjunct->supList = 0;
+  }
+  if(conjunct->relation) {
+    bdd_free(conjunct->relation);
+    conjunct->relation = 0;
+  }
+  free(conjunct);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Free variable array]
+
+  Description [Free variable array]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearVariableArrayQuit(Relation_t *head)
+{
+int i;
+VarLife_t **varArray;
+
+
+  varArray = head->varArray;
+  for(i=0; i<head->nVarArray; i++)
+    ImgLinearVariableLifeQuit(varArray[i]);
+
+  free(varArray);
+  head->varArray = 0;
+  head->nVarArray = 0;
+  memset(head->varArrayMap, -1, sizeof(int)*head->nVar);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Free variable life array]
+
+  Description [Free variable  lifearray]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearVariableLifeQuit(VarLife_t *var) 
+{
+   if(var->relArr)	free(var->relArr);
+   free(var);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Main function of clustering]
+
+  Description [Main function of clustering]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+ImgLinearClustering(Relation_t *head, Img_OptimizeType optDir)
+{
+int andExistLimit;
+int useFailureHistory;
+int includeZeroGain;
+double affinityLimit;
+int bOptimize;
+int varLimit;
+
+  bOptimize = 0;
+
+  affinityLimit = 0.99;
+  andExistLimit = 10;
+  varLimit = 200;
+  fprintf(stdout, "Heap DAL affinity %3f, andExist %d\n", 
+	  affinityLimit, andExistLimit);
+  bOptimize |= ImgLinearClusterUsingHeap(head, affinityLimit, andExistLimit,
+                                varLimit, optDir, 0,
+	  			ImgLinearHeapCompareDeadAffinityLive);
+  ImgLinearRefineRelation(head);
+  if(head->verbosity >= 5)
+    ImgLinearPrintMatrix(head);
+  ImgLinearSetEffectiveNumberOfStateVariable(head, 0, 0, 0);
+  ImgLinearPrintTransitionInfo(head);
+
+  includeZeroGain = 0;
+  affinityLimit = 0.3;
+  andExistLimit = 5000;
+  varLimit = 50;
+  useFailureHistory = 0;
+  if(head->computeRange) {
+    varLimit = 50;
+    affinityLimit = 0.8;
+    andExistLimit = 5000;
+    fprintf(stdout, "Heap DAL affinity %3f, andExist %d\n", 
+	    affinityLimit, andExistLimit);
+    bOptimize |= ImgLinearClusterUsingHeap(head, affinityLimit, andExistLimit,
+                                  varLimit, optDir, 0,
+	  			ImgLinearHeapCompareDeadAffinityLive);
+
+    ImgLinearRefineRelation(head);
+    ImgLinearExtractNextStateCase(head);
+    ImgLinearExtractSingletonCase(head);
+    ImgLinearRefineRelation(head);
+    ImgLinearAddSingletonCase(head);
+    ImgLinearRefineRelation(head);
+    ImgLinearAddNextStateCase(head);
+    ImgLinearRefineRelation(head);
+  }
+  else 
+  {
+    fprintf(stdout, "Gain DAL affinity %3f, andExist %d\n", 
+	  affinityLimit, andExistLimit);
+    bOptimize |= ImgLinearClusteringIteratively(head, affinityLimit,
+                                andExistLimit, varLimit, 
+				includeZeroGain, useFailureHistory, optDir,
+				ImgLinearCompareDeadAffinityLive);
+    ImgLinearRefineRelation(head);
+    ImgLinearExtractNextStateCase(head);
+    ImgLinearExtractSingletonCase(head);
+    ImgLinearRefineRelation(head);
+    ImgLinearAddSingletonCase(head);
+    ImgLinearRefineRelation(head);
+    ImgLinearAddNextStateCase(head);
+    ImgLinearRefineRelation(head);
+  }
+
+  includeZeroGain = 1;
+  varLimit = 200;
+  affinityLimit = 0.7;
+  andExistLimit = 5000;
+  fprintf(stdout, "Heap DAL affinity %3f, andExist %d\n", 
+	  affinityLimit, andExistLimit);
+  bOptimize |= ImgLinearClusterUsingHeap(head, affinityLimit, andExistLimit,
+                                varLimit, optDir, 0,
+	  			ImgLinearHeapCompareDeadAffinityLive);
+
+  ImgLinearRefineRelation(head);
+  ImgLinearExtractNextStateCase(head);
+  ImgLinearExtractSingletonCase(head);
+  ImgLinearRefineRelation(head);
+  ImgLinearAddSingletonCase(head);
+  ImgLinearRefineRelation(head);
+  ImgLinearAddNextStateCase(head);
+  ImgLinearRefineRelation(head);
+
+  if(head->verbosity >= 5)
+    ImgLinearPrintMatrix(head);
+  ImgLinearSetEffectiveNumberOfStateVariable(head, 0, 0, 0);
+  ImgLinearPrintTransitionInfo(head);
+
+  includeZeroGain = 1;
+  affinityLimit = 0.4;
+  andExistLimit = 5000;
+  fprintf(stdout, "Heap DAL affinity %3f, andExist %d\n", 
+	  affinityLimit, andExistLimit);
+  bOptimize |= ImgLinearClusterUsingHeap(head, affinityLimit, andExistLimit,
+                                varLimit, optDir, 0,
+	  			ImgLinearHeapCompareDeadAffinityLive);
+  ImgLinearRefineRelation(head);
+  ImgLinearExtractNextStateCase(head);
+  ImgLinearExtractSingletonCase(head);
+  ImgLinearRefineRelation(head);
+  ImgLinearAddSingletonCase(head);
+  ImgLinearRefineRelation(head);
+  ImgLinearAddNextStateCase(head);
+  ImgLinearRefineRelation(head);
+
+  if(head->verbosity >= 5)
+    ImgLinearPrintMatrix(head);
+  ImgLinearSetEffectiveNumberOfStateVariable(head, 0, 0, 0);
+  ImgLinearPrintTransitionInfo(head);
+
+  affinityLimit = 0.0;
+  andExistLimit = 5000;
+  fprintf(stdout, "Heap DLA affinity %3f, andExist %d\n", 
+	  affinityLimit, andExistLimit);
+  bOptimize |= ImgLinearClusterUsingHeap(head, affinityLimit, andExistLimit,
+                                varLimit, optDir, 0,
+	  			ImgLinearHeapCompareDeadLiveAffinity);
+  ImgLinearRefineRelation(head);
+  ImgLinearExtractNextStateCase(head);
+  ImgLinearRefineRelation(head);
+  ImgLinearAddNextStateCase(head);
+  ImgLinearRefineRelation(head);
+  if(head->verbosity >= 5)
+    ImgLinearPrintMatrix(head);
+  ImgLinearSetEffectiveNumberOfStateVariable(head, 0, 0, 0);
+  ImgLinearPrintTransitionInfo(head);
+
+  if(head->computeRange) {
+    includeZeroGain = 0;
+    affinityLimit = 0.0;
+    andExistLimit = andExistLimit;
+    varLimit = MAXINT;
+    head->bddLimit = head->bddLimit * 2;
+    fprintf(stdout, "Heap DLA affinity %3f, andExist %d\n", 
+	  affinityLimit, andExistLimit);
+    while(1) {
+      bOptimize |= ImgLinearClusterUsingHeap(head, affinityLimit, andExistLimit,
+                                varLimit, optDir, 1,
+	  			ImgLinearHeapCompareDeadLiveAffinity);
+      ImgLinearRefineRelation(head);
+
+      if(ImgCheckRangeTestAndOverapproximate(head))	break;
+    }
+
+    ImgCountOnsetDisjunctiveArray(head);
+    ImgLinearSetEffectiveNumberOfStateVariable(head, 0, 0, 0);
+    ImgLinearPrintTransitionInfo(head);
+
+  }
+
+  return(bOptimize);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Count onset of relation array]
+
+  Description [Count onset of relation array]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void 
+ImgCountOnsetDisjunctiveArray(Relation_t *head)
+{
+EpDouble tepd;
+char strValue[1024];
+bdd_t *varBdd;
+mdd_manager *mgr;
+array_t *bddVarArray;
+Conjunct_t *conjunct;
+int count, i, j, id;
+double onSet;
+
+  mgr = head->mgr;
+  count = 0;
+  EpdConvert((double)1.0, &tepd);
+  for(i=0; i<head->nSize; i++) {
+    conjunct = head->conjunctArray[i];
+    bddVarArray = array_alloc(bdd_t *, 0);
+    for(j=0; j<conjunct->nSize; j++) {
+      id = conjunct->supList[j];
+      varBdd = bdd_get_variable(mgr, id);
+      array_insert_last(bdd_t *, bddVarArray, varBdd);
+    }
+    /**
+    bdd_epd_count_onset(conjunct->relation, bddVarArray, &epd);
+    EpdMultiply2(&tepd, &epd);
+    **/
+    onSet = bdd_count_onset(conjunct->relation, bddVarArray);
+    EpdMultiply(&tepd, onSet);
+    count += conjunct->nSize;
+    mdd_array_free(bddVarArray);
+  }
+
+  if(count < head->nRange) {
+    EpdMultiply(&tepd, pow(2, (double)(head->nRange-count)));
+  }
+  EpdGetString(&tepd, strValue);
+  (void) fprintf(vis_stdout, "%-20s%10s\n", "range =", strValue);
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Check range of variables]
+
+  Description [Check range of variables]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ImgCheckRangeTestAndOverapproximate(Relation_t *head)
+{
+Conjunct_t *conjunct;
+VarLife_t **varArray, *var;
+int nVarArray, i, k, count;
+int index;
+int *varType;
+int allRangeFlag;
+bdd_t *relation, *simpleRelation, *varBdd;
+
+
+  allRangeFlag = 1;
+  for(i=0; i<head->nSize; i++) {
+    conjunct = head->conjunctArray[i];
+    if(conjunct->nRange != conjunct->nSize) {
+      allRangeFlag = 0;
+      break;
+    }
+  }
+
+  if(allRangeFlag == 1)	return(1);
+
+  varArray = head->varArray;
+  varType = head->varType;
+  nVarArray = head->nVarArray;
+  /**
+  maxIndex = -1;
+  maxSize = 0;
+  for(i=0; i<nVarArray; i++) {
+    var = varArray[i];
+    if(varType[var->id] == 2)	continue;
+    if(var->nSize > maxSize) {
+      maxIndex = i;
+      maxSize = var->nSize;
+    }
+  }
+
+  if(maxIndex == -1)	return(1);
+  **/
+  count = head->nEffDomain + head->nEffQuantify;
+  if(count == 0)	return(1);
+
+  varArray = ALLOC(VarLife_t *, head->nVarArray);
+  memcpy(varArray, head->varArray, sizeof(VarLife_t *)*head->nVarArray);
+  qsort(varArray, head->nVarArray, sizeof(VarLife_t *), ImgLinearCompareVarSize);
+
+  if(count != 0) {
+    count = (count / 10);
+    if(count == 0) count = 1;
+  }
+  k=0;
+  index = 0;
+  while(1) {
+    if(index >= count)	break;
+    var = varArray[k++];
+    if(var->stateVar == 2)	continue;
+    index++;
+    varBdd = bdd_get_variable(head->mgr, var->id);
+    for(i=0; i<var->nSize; i++) {
+      conjunct = head->conjunctArray[var->relArr[i]];
+      relation = conjunct->relation;
+      simpleRelation = bdd_smooth_with_cube(relation, varBdd);
+      if(bdd_equal(relation, simpleRelation)) {
+        bdd_free(simpleRelation);
+        continue;
+      }
+      bdd_free(relation);
+  
+      conjunct->relation = simpleRelation;
+      conjunct->bModified = 1;
+      head->bModified = 1;
+      head->bRefineVarArray = 1;
+      ImgLinearConjunctRefine(head, conjunct);
+    }
+  }
+  free(varArray);
+
+  ImgLinearRefineRelation(head);
+  ImgLinearConjunctOrderMainCC(head, 0);
+  ImgLinearRefineRelation(head);
+
+  ImgLinearSetEffectiveNumberOfStateVariable(head, 0, 0, 0);
+  ImgLinearPrintTransitionInfo(head);
+  
+  return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Add singleton next state variable case into array]
+
+  Description [Add singleton next state variable case into array]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ImgLinearAddNextStateCase(Relation_t *head)
+{
+Conjunct_t **newConjunctArray;
+int i, j, index;
+
+  index = 0;
+  if(head->nNextStateArray) {
+    newConjunctArray = ALLOC(Conjunct_t *, head->nSize + head->nNextStateArray);
+   for(j=0; j<head->nSize; j++) 
+      newConjunctArray[index++] = head->conjunctArray[j];
+
+    for(i=0; i<head->nNextStateArray; i++) 
+      newConjunctArray[index++] = head->nextStateArray[i];
+
+    head->nSize = index;
+    head->bModified = 1;
+    head->bRefineVarArray = 1;
+    free(head->conjunctArray);
+    head->conjunctArray = newConjunctArray;
+
+    if(head->nextStateArray)	free(head->nextStateArray);
+    head->nextStateArray = 0;
+  }
+}
+
Index: vis_dev/vis-2.3/src/img/imgMlp.c
===================================================================
--- vis_dev/vis-2.3/src/img/imgMlp.c	(revision 14)
+++ vis_dev/vis-2.3/src/img/imgMlp.c	(revision 14)
@@ -0,0 +1,8151 @@
+/**CFile***********************************************************************
+
+  FileName    [imgMlp.c]
+
+  PackageName [img]
+
+  Synopsis    [Routines for image computation using MLP(Minimal Lifetime
+  Permutation) published in FMCAD00.]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [In-Ho Moon]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF COLORADO BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  COLORADO HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF COLORADO SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF COLORADO HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+#include "imgInt.h"
+#include "fsm.h"
+
+static char rcsid[] UNUSED = "$Id: imgMlp.c,v 1.31 2005/04/26 19:08:33 jinh Exp $";
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [This structure contains the information of each row and
+  column.]
+
+  Description []
+
+******************************************************************************/
+typedef struct RcInfo_s {
+  int	pos;	/* level */
+  int	lNum;
+  int	lMin;	/* index */
+  int	lMax;	/* index */
+  int	gNum;
+  int	gMin;	/* index */
+  int	gMax;	/* index */
+  int	prevG;	/* level */
+  int	nextG;	/* level */
+  union {
+    struct {
+      bdd_t	*func;
+      array_t	*nsVarBddArray;
+    } row;
+    struct {
+      bdd_t	*var;
+      int	type;
+    } col;
+  } data;
+} RcInfo_t;
+
+/**Struct**********************************************************************
+
+  Synopsis    [This structure is a list of row and coulmn.]
+
+  Description []
+
+******************************************************************************/
+typedef struct RcList_s {
+  int			index;
+  int			otherIndex;
+  struct RcList_s	*next;
+  struct RcList_s	*prev;
+} RcList_t;
+
+/**Struct**********************************************************************
+
+  Synopsis    [This structure contains the information of row and column
+  list.]
+
+  Description []
+
+******************************************************************************/
+typedef struct RcListInfo_s {
+  int		num;
+  int		maxNum;
+  int		curIndex;
+  st_table	*table;
+  RcList_t	*cur;
+  RcList_t	*head;
+  RcList_t	*tail;
+} RcListInfo_t;
+
+/**Struct**********************************************************************
+
+  Synopsis    [This structure contains the information of each cluster.]
+
+  Description []
+
+******************************************************************************/
+typedef struct ClusterList_s {
+  int			flag;	/* 0 : to be conjuncted
+				   1 : start element
+				   2 : last element
+				   3 : isolated
+				*/
+  int			start;
+  int			end;
+  char			*supports;
+  int			minCol;	/* index */
+  int			maxCol;	/* index */
+  int			nSupports;
+  float			affinity;
+  int			nQuantifyVars;
+  mdd_t			*product;
+  array_t		*nsVarBddArray;
+  struct ClusterList_s	*prev;
+  struct ClusterList_s	*next;
+} ClusterList_t;
+
+/**Struct**********************************************************************
+
+  Synopsis    [This structure is a list of a sorted cluster.]
+
+  Description []
+
+******************************************************************************/
+typedef struct ClusterSortedList_s {
+  ClusterList_t			*list;
+  struct ClusterSortedList_s	*next;
+} ClusterSortedList_t;
+
+/**Struct**********************************************************************
+
+  Synopsis    [This structure contains the information of the list of
+  connected component.]
+
+  Description []
+
+******************************************************************************/
+typedef struct SccList_s {
+  int			startFunc;
+  int			lastFunc;
+  int			startVar;
+  int			lastVar;
+  int			nFuncs;
+  int			nVars;
+  struct SccList_s	*next;
+} SccList_t;
+
+/**Struct**********************************************************************
+
+  Synopsis    [This structure constains latch information from reading a
+  cluster file.]
+
+  Description []
+
+******************************************************************************/
+typedef struct LatchList_s {
+  int		number;
+  int		bddId;
+  mdd_t		*relation;
+  st_table	*table;
+} LatchList_t;
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+static	int	nMoves;
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void SetupMlp(mdd_manager *mddManager, char **xy, int nRows, int nCols, int *rowOrder, int *colOrder, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *varPos, array_t *nsVarBddArray, int *nActiveRows, int *nActiveCols, array_t *nonAppearingVarBddArray, Img_DirectionType direction, ImgTrmOption_t *option);
+static SccList_t * MlpDecomposeScc(mdd_manager *mddManager, char **xy, int nRows, int nActiveRows, int nActiveCols, int *rowOrder, int *colOrder, RcInfo_t *rowInfo, RcInfo_t *colInfo, int clusteredFlag, ImgTrmOption_t *option);
+static int SccSortListIncreasingWithVars(const void *p1, const void *p2);
+static int SccSortListDecreasingWithVars(const void *p1, const void *p2);
+static int SccSortListIncreasingWithArea(const void *p1, const void *p2);
+static int SccSortListDecreasingWithArea(const void *p1, const void *p2);
+static int SccSortListIncreasingWithRatio(const void *p1, const void *p2);
+static int SccSortListDecreasingWithRatio(const void *p1, const void *p2);
+static int SccSortRc(const void *p1, const void *p2);
+static void FreeSccList(SccList_t *sccHeadList);
+static int NumOfSccs(SccList_t *sccHeadList);
+static void BlockLowerTriangle(char **xy, int nRows, int nCols, int nActiveRows, int nActiveCols, SccList_t *sccList, int *rowOrder, int *colOrder, RcInfo_t *rowInfo, RcInfo_t *colInfo, ImgTrmOption_t *option);
+static void MoveBestRows(char **xy, SccList_t *sccList, int nRows, int nCols, int *rowOrder, int *colOrder, RcInfo_t *rowInfo, RcInfo_t *colInfo, int startFunc, int lastFunc, int startVar, int lastVar, ImgTrmOption_t *option);
+static void MoveBestCols(char **xy, SccList_t *sccList, int nRows, int nCols, int nActiveRows, int nActiveCols, int *rowOrder, int *colOrder, RcInfo_t *rowInfo, RcInfo_t *colInfo, int startFunc, int lastFunc, int startVar, int lastVar, ImgTrmOption_t *option);
+static void MlpPostProcess(char **xy, SccList_t *sccList, int nVars, int nRows, int nCols, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder, Img_DirectionType direction, ImgTrmOption_t *option);
+static float ComputeLambdaMlp(char **xy, int nVars, int nRows, int nCols, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder, Img_DirectionType direction, int mode, int asIs, ImgTrmOption_t *option);
+static void FindAndMoveSingletonRows(char **xy, SccList_t *sccList, int nRows, int nCols, int *startFunc, int *lastFunc, int *startVar, int *lastVar, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder, ImgTrmOption_t *option);
+static int MoveSingletonRow(char **xy, SccList_t *sccList, int nRows, int nCols, int x, int *startFunc, int *lastFunc, int *startVar, int *lastVar, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder, RcListInfo_t *candList, ImgTrmOption_t *option);
+static void FindAndMoveSingletonCols(char **xy, SccList_t *sccList, int nRows, int nCols, int *startFunc, int *lastFunc, int *startVar, int *lastVar, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder, ImgTrmOption_t *option);
+static int MoveSingletonCol(char **xy, SccList_t *sccList, int nRows, int nCols, int y, int *startFunc, int *lastFunc, int *startVar, int *lastVar, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder, RcListInfo_t *candList, ImgTrmOption_t *option);
+static void MoveRowToTop(char **xy, int x, int startFunc, int lastFunc, int startVar, int lastVar, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder, RcListInfo_t *candList, int method);
+static void MoveColToLeft(char **xy, int y, int startFunc, int lastFunc, int startVar, int lastVar, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder, RcListInfo_t *candList, int method);
+static void MoveRowToBottom(char **xy, int x, int startFunc, int lastFunc, int startVar, int lastVar, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder, RcListInfo_t *candList, int method);
+static void MoveColToRight(char **xy, int y, int startFunc, int lastFunc, int startVar, int lastVar, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder, RcListInfo_t *candList, int method);
+static void PrintMatrix(char **xy, int nRows, int nCols, int *rowOrder, int *colOrder, RcInfo_t *rowInfo, RcInfo_t *colInfo, int startFunc, int lastFunc, int startVar, int lastVar);
+static void PrintMatrixWithCluster(char **xy, ClusterList_t *headCluster, int nCols, int *rowOrder, int *colOrder, Img_DirectionType direction);
+static void PrintClusterMatrix(ClusterList_t *headCluster, int nCols, int *colOrder, Img_DirectionType direction);
+static void CheckMatrix(char **xy, SccList_t *sccList, int nRows, int nCols, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder, int startFunc, int lastFunc, int startVar, int lastVar, int local);
+static void CheckCluster(ClusterList_t *headCluster, int nCols, RcInfo_t *colInfo, int *colOrder);
+static void WriteMatrix(FILE *fout, char **xy, int nRows, int nCols, int *rowOrder, int *colOrder, RcInfo_t *rowInfo, RcInfo_t *colInfo);
+static void PrintRow(char **xy, int nRows, int nCols, int *rowOrder, int *colOrder, int from, int to);
+static void PrintCol(char **xy, int nRows, int nCols, int *rowOrder, int *colOrder, int from, int to);
+static RcListInfo_t * SortedListAlloc(void);
+static void SortedListFree(RcListInfo_t *candList);
+static void SortedListInsert(RcListInfo_t *candList, int index, int otherIndex, RcInfo_t *otherInfo, int method);
+static void SortedListDelete(RcListInfo_t *candList, int index);
+static void SortedListMove(RcListInfo_t *candList, RcInfo_t *info, int index, int method);
+static void CheckSortedList(RcListInfo_t *candList, RcInfo_t *info, int method);
+static void MlpCluster(mdd_manager *mddManager, char **xy, int nRows, int nCols, int nActiveRows, int nActiveCols, int *nClusterRows, int *nClusterCols, int *rowOrder, int *colOrder, RcInfo_t *rowInfo, RcInfo_t *colInfo, array_t *clusterArray, array_t *arraySmoothVarBddArray, Img_DirectionType direction, int *cRowOrder, array_t *nsVarBddArray, int *sccBorder, int *varPos, ImgTrmOption_t *option);
+static int MlpCountSupport(ClusterList_t *list, int *colOrder, int nActiveCols);
+static float MlpSupportAffinity(ClusterList_t *curList, ClusterList_t *nextList, RcInfo_t *colInfo, int *colOrder, int nActiveCols, int clusterMethod);
+static int RecursiveCluster(mdd_manager *mddManager, ClusterList_t *headCluster, ClusterSortedList_t *clusterSortedList, char **xy, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder, int nActiveRows, int nClusterCols, Img_DirectionType direction, int *varPos, int moveFlag, ImgTrmOption_t *option);
+static int RemoveLocalVarsInCluster(mdd_manager *mddManager, char **xy, ClusterList_t *list, int nActiveRows, int nClusterCols, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder, int moveFlag, ImgTrmOption_t *option);
+static int MlpNumQuantifyVars(ClusterList_t *list, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *colOrder, int nClusterCols);
+static ClusterSortedList_t * ClusterSortedListInsert(ClusterSortedList_t *clusterSortedList, ClusterList_t *list, int useQuantifyVars);
+static int CountClusterList(ClusterList_t *clusterList);
+static int CountClusterSortedList(ClusterSortedList_t *clusterSortedList);
+static array_t * CreateInitialCluster(mdd_manager *mddManager, array_t *relationArray, ImgFunctionData_t *functionData, array_t *nsVarBddArray, ImgTrmOption_t *option);
+static void SortCol(char **xy, int nRows, int nCols, RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder);
+static void UpdateDisapearingPsVars(mdd_manager *mddManager, char **xy, int nActiveRows, int nActiveCols, int *rowOrder, int *colOrder, RcInfo_t *rowInfo, RcInfo_t *colInfo, int row, ImgTrmOption_t *option);
+static void UpdateDisapearingPsVarsInCluster(mdd_manager *mddManager, char **xy, int nActiveRows, int nActiveCols, int *rowOrder, int *colOrder, RcInfo_t *rowInfo, RcInfo_t *colInfo, ClusterList_t *list, int moveFlag, ImgTrmOption_t *option);
+static void UpdateNonappearingNsVars(mdd_manager *mddManager, array_t *nsVarBddArray, int nRows, RcInfo_t *rowInfo, int *rowOrder, array_t *nonAppearingVarBddArray);
+static void WriteOrder(FILE *fout, int nCols, int *colOrder, RcInfo_t *colInfo);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the options for MLP image computation.]
+
+  Description [Prints the options for MLP image computation.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Img_PrintMlpOptions(void)
+{
+  ImgTrmOption_t	*options;
+  char			dummy[80];
+
+  options = ImgGetTrmOptions();
+
+  switch (options->mlpCluster) {
+  case 0 :
+    sprintf(dummy, "linear clustering");
+    break;
+  case 1 :
+    sprintf(dummy, "affinity based tree clustering (default)");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "MLP: mlp_cluster = %d (%s)\n",
+	  options->mlpCluster, dummy);
+
+  switch (options->mlpReorder) {
+  case 0 :
+    sprintf(dummy, "no reordering after clustering (default)");
+    break;
+  case 1 :
+    sprintf(dummy, "reorder using MLP after clustering (inside)");
+    break;
+  case 2 :
+    sprintf(dummy, "reorder using MLP after clustering (outside)");
+    break;
+  case 3 :
+    sprintf(dummy, "reorder using IWLS95 after clustering");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "MLP: mlp_reorder = %d (%s)\n",
+	  options->mlpReorder, dummy);
+
+  switch (options->mlpPreReorder) {
+  case 0 :
+    sprintf(dummy, "no reordering after clustering (default)");
+    break;
+  case 1 :
+    sprintf(dummy, "reorder using MLP after clustering (inside)");
+    break;
+  case 2 :
+    sprintf(dummy, "reorder using MLP after clustering (outside)");
+    break;
+  case 3 :
+    sprintf(dummy, "reorder using IWLS95 after clustering");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "MLP: mlp_pre_reorder = %d (%s)\n",
+	  options->mlpPreReorder, dummy);
+
+  switch (options->mlpPostProcess) {
+  case 0 :
+    sprintf(dummy, "no postprocessing (default)");
+    break;
+  case 1 :
+    sprintf(dummy, "do postprocessing after ordering");
+    break;
+  case 2 :
+    sprintf(dummy, "do postprocessing after clustering or reordering");
+    break;
+  case 3 :
+    sprintf(dummy, "do both 1 and 2");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "MLP: mlp_postprocess = %d (%s)\n",
+	  options->mlpPostProcess, dummy);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs multiway and_smooth using MLP.]
+
+  Description [Performs multiway and_smooth using MLP.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+ImgMlpMultiwayAndSmooth(mdd_manager *mddManager,
+			ImgFunctionData_t *functionData,
+			array_t *relationArray,
+			array_t *domainVarBddArray,
+			array_t *quantifyVarBddArray,
+			array_t *rangeVarBddArray,
+			Img_DirectionType direction,
+			ImgTrmOption_t *option)
+{
+  int		i, clusterSize;
+  array_t	*clusteredRelationArray;
+  mdd_t		*result, *relation, *tmp;
+
+  if (direction == Img_Forward_c) {
+    if (array_n(domainVarBddArray) == 0 && array_n(quantifyVarBddArray) == 0) {
+      if (array_n(relationArray) == 1) {
+	relation = array_fetch(mdd_t *, relationArray, 0);
+	result = bdd_dup(relation);
+      } else {
+	result = array_fetch(mdd_t *, relationArray, 0);
+	for (i = 1; i < array_n(relationArray); i++) {
+	  relation = array_fetch(mdd_t *, relationArray, i);
+	  tmp = result;
+	  result = bdd_and(tmp, relation, 1, 1);
+	  mdd_free(tmp);
+	}
+      }
+      return(result);
+    }
+  }
+
+  clusterSize = option->clusterSize;
+  option->clusterSize = 1000000000;
+  ImgMlpClusterRelationArray(mddManager, functionData, relationArray,
+		domainVarBddArray, quantifyVarBddArray, rangeVarBddArray,
+		direction, &clusteredRelationArray, NIL(array_t *), option);
+  option->clusterSize = clusterSize;
+
+  assert(array_n(clusteredRelationArray) == 1);
+  result = array_fetch(mdd_t *, clusteredRelationArray, 0);
+  array_free(clusteredRelationArray);
+
+  return(result);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Clusters relation array and makes quantification schedule.]
+
+  Description [Orders and clusters relation array and makes quantification
+  schedule. (Order/Cluster.)]
+
+  Description []
+
+  SideEffects [ImgClusterRelationArray]
+
+******************************************************************************/
+void
+ImgMlpClusterRelationArray(mdd_manager *mddManager,
+			ImgFunctionData_t *functionData,
+			array_t *relationArray,
+			array_t *domainVarBddArray,
+			array_t *quantifyVarBddArray,
+			array_t *rangeVarBddArray,
+			Img_DirectionType direction,
+			array_t **clusteredRelationArrayPtr,
+			array_t **arraySmoothVarBddArrayPtr,
+			ImgTrmOption_t *option)
+{
+  int		i, j, x, y, nRows, nCols, nActiveRows, nActiveCols;
+  int		*rowOrder, *colOrder, *cRowOrder;
+  RcInfo_t	*rowInfo, *colInfo;
+  char		**xy;
+  int		nClusterRows, nClusterCols;
+  array_t	*clusterArray;
+  bdd_t		*cluster, *relation, *tempCluster, *var, *nsVar;
+  int		row, col, s, t;
+  array_t	*arraySmoothVarBddArray, *smoothVarBddArray;
+  int		qVarPos;
+  array_t	*nonAppearingVarBddArray;
+  int		*varPos;
+  array_t	*psVarBddArray, *nsVarBddArray;
+  int		index, nVars, nc;
+  long		initialTime, finalTime;
+  array_t	*clusteredRelationArray;
+  SccList_t	*sccHeadList, *sccList;
+  int		*sccBorder;
+  float		lambda1, lambda2, lambda3;
+  FILE		*fout;
+
+  if (option->mlpVerbosity)
+    initialTime = util_cpu_time();
+  else
+    initialTime = 0;
+
+  psVarBddArray = domainVarBddArray;
+  nsVarBddArray = rangeVarBddArray;
+
+  if (option->mlpInitialCluster && functionData) {
+    clusteredRelationArray = CreateInitialCluster(mddManager, relationArray,
+						  functionData, nsVarBddArray,
+						  option);
+  } else
+    clusteredRelationArray = relationArray;
+
+  nRows = array_n(clusteredRelationArray);
+  if (direction == Img_Forward_c)
+    nCols = array_n(domainVarBddArray) + array_n(quantifyVarBddArray);
+  else
+    nCols = array_n(rangeVarBddArray) + array_n(quantifyVarBddArray);
+
+  xy = ALLOC(char *, nRows);
+  for (i = 0; i < nRows; i++) {
+    xy[i] = ALLOC(char, nCols);
+    memset(xy[i], 0, sizeof(char) * nCols);
+  }
+
+  rowOrder = ALLOC(int, nRows);
+  for (i = 0; i < nRows; i++)
+    rowOrder[i] = i;
+  colOrder = ALLOC(int, nCols);
+  for (i = 0; i < nCols; i++)
+    colOrder[i] = i;
+
+  rowInfo = ALLOC(RcInfo_t, nRows);
+  memset(rowInfo, 0, sizeof(RcInfo_t) * nRows);
+  colInfo = ALLOC(RcInfo_t, nCols);
+  memset(colInfo, 0, sizeof(RcInfo_t) * nCols);
+  nVars = bdd_num_vars(mddManager);
+  varPos = ALLOC(int, nVars);
+  memset(varPos, 0, sizeof(int) * nVars);
+
+  for (i = 0; i < nRows; i++) {
+    relation = array_fetch(bdd_t *, clusteredRelationArray, i);
+    rowInfo[i].data.row.func = bdd_dup(relation);
+  }
+
+  nc = 0;
+  for (i = 0; i < array_n(psVarBddArray); i++) {
+    var = array_fetch(bdd_t *, psVarBddArray, i);
+    colInfo[nc].data.col.var = var;
+    colInfo[nc].data.col.type = 1;
+    index = (int)bdd_top_var_id(var);
+    varPos[index] = nc;
+    nc++;
+  }
+  for (i = 0; i < array_n(quantifyVarBddArray); i++) {
+    var = array_fetch(bdd_t *, quantifyVarBddArray, i);
+    colInfo[nc].data.col.var = var;
+    colInfo[nc].data.col.type = 2;
+    index = (int)bdd_top_var_id(var);
+    varPos[index] = nc;
+    nc++;
+  }
+
+  if (arraySmoothVarBddArrayPtr)
+    nonAppearingVarBddArray = array_alloc(bdd_t *, 0);
+  else
+    nonAppearingVarBddArray = NIL(array_t);
+
+  SetupMlp(mddManager, xy, nRows, nCols, rowOrder, colOrder,
+	   rowInfo, colInfo, varPos, nsVarBddArray, &nActiveRows, &nActiveCols,
+	   nonAppearingVarBddArray, direction, option);
+
+  if (nActiveRows == 0) {
+    clusterArray = array_alloc(mdd_t *, 0);
+    cluster = bdd_one(mddManager);
+    for (i = nActiveRows; i < nRows; i++) {
+      row = rowOrder[i];
+      relation = rowInfo[row].data.row.func;
+      tempCluster = bdd_and(cluster, relation, 1, 1);
+      bdd_free(cluster);
+      cluster = tempCluster;
+    }
+    array_insert_last(bdd_t *, clusterArray, cluster);
+    *clusteredRelationArrayPtr = clusterArray;
+
+    if (arraySmoothVarBddArrayPtr) {
+      arraySmoothVarBddArray = array_alloc(array_t *, 0);
+      *arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
+      array_insert_last(array_t *, arraySmoothVarBddArray,
+			nonAppearingVarBddArray);
+      if (direction == Img_Forward_c) {
+	smoothVarBddArray = array_alloc(array_t *, 0);
+	array_insert_last(array_t *, arraySmoothVarBddArray, smoothVarBddArray);
+      } else {
+	smoothVarBddArray = array_alloc(array_t *, 0);
+	for (i = 0; i < nRows; i++) {
+	  row = rowOrder[i];
+	  for (j = 0; j < array_n(rowInfo[row].data.row.nsVarBddArray); j++) {
+	    nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray,
+				j);
+	    array_insert_last(bdd_t *, smoothVarBddArray, bdd_dup(nsVar));
+	  }
+	}
+	array_insert_last(array_t *, arraySmoothVarBddArray,
+			  smoothVarBddArray);
+      }
+    }
+
+    FREE(varPos);
+    for (i = 0; i < nRows; i++) {
+      if (xy[i])
+	FREE(xy[i]);
+    }
+    FREE(xy);
+    FREE(rowOrder);
+    FREE(colOrder);
+    for (i = 0; i < nRows; i++) {
+      bdd_free(rowInfo[i].data.row.func);
+      if (rowInfo[i].data.row.nsVarBddArray)
+	array_free(rowInfo[i].data.row.nsVarBddArray);
+    }
+    FREE(rowInfo);
+    FREE(colInfo);
+    return;
+  }
+  sccHeadList = MlpDecomposeScc(mddManager, xy, nRows, nActiveRows, nActiveCols,
+				rowOrder, colOrder, rowInfo, colInfo,
+				0, option);
+  if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
+    PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
+		rowInfo, colInfo, 0, nActiveRows - 1, 0, nActiveCols - 1);
+  }
+  sccList = sccHeadList;
+  while (sccList) {
+    BlockLowerTriangle(xy, nRows, nCols, nActiveRows, nActiveCols, sccList,
+			rowOrder, colOrder, rowInfo, colInfo, option);
+    sccList = sccList->next;
+  }
+  if (option->mlpVerbosity >= 2) {
+    lambda1 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
+				rowInfo, colInfo, rowOrder, colOrder,
+				direction, 0, 0, option);
+    lambda2 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
+				rowInfo, colInfo, rowOrder, colOrder,
+				direction, 1, 0, option);
+    lambda3 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
+				rowInfo, colInfo, rowOrder, colOrder,
+				direction, 2, 0, option);
+    fprintf(vis_stdout, "Lambda after MLP = %f (%f, %f)\n",
+	    lambda1, lambda2, lambda3);
+  }
+
+  if (option->mlpVerbosity) {
+    finalTime = util_cpu_time();
+    fprintf(vis_stdout, "time for MLP = %10g\n",
+	   (double)(finalTime - initialTime) / 1000.0);
+  }
+  if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
+    PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
+		rowInfo, colInfo, 0, nActiveRows - 1, 0, nActiveCols - 1);
+  }
+
+  if (option->mlpPostProcess == 1 || option->mlpPostProcess == 3) {
+    for (x = 0; x < nActiveRows; x++) {
+      row = rowOrder[x];
+      rowInfo[row].lNum = rowInfo[row].gNum;
+      rowInfo[row].lMin = rowInfo[row].gMin;
+      rowInfo[row].lMax = rowInfo[row].gMax;
+      rowInfo[row].prevG = -1;
+      rowInfo[row].nextG = nActiveCols;
+    }
+    for (y = 0; y < nActiveCols; y++) {
+      col = colOrder[y];
+      colInfo[col].lNum = colInfo[col].gNum;
+      colInfo[col].lMin = colInfo[col].gMin;
+      colInfo[col].lMax = colInfo[col].gMax;
+      colInfo[col].prevG = -1;
+      colInfo[col].nextG = nActiveRows;
+    }
+
+    sccList = sccHeadList;
+    while (sccList) {
+      MlpPostProcess(xy, sccList, nCols, nActiveRows, nActiveCols,
+		   rowInfo, colInfo, rowOrder, colOrder, direction, option);
+      sccList = sccList->next;
+    }
+    if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
+      PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
+		  rowInfo, colInfo, 0, nActiveRows - 1, 0, nActiveCols - 1);
+    }
+  }
+
+  if (option->mlpWriteOrder) {
+    fout = fopen(option->mlpWriteOrder, "w");
+    if (fout) {
+      WriteOrder(fout, nActiveCols, colOrder, colInfo);
+      fclose(fout);
+    } else {
+      fprintf(vis_stderr, "** img error: can't open file [%s]\n",
+	      option->mlpWriteOrder);
+    }
+  }
+
+  clusterArray = array_alloc(bdd_t *, 0);
+  if (arraySmoothVarBddArrayPtr) {
+    arraySmoothVarBddArray = array_alloc(array_t *, 0);
+    array_insert_last(array_t *, arraySmoothVarBddArray,
+			nonAppearingVarBddArray);
+  } else
+    arraySmoothVarBddArray = NIL(array_t);
+
+  if ((direction == Img_Forward_c && option->mlpReorder) ||
+      (direction == Img_Backward_c && option->mlpPreReorder) ||
+      option->mlpPostProcess >= 2) {
+    cRowOrder = ALLOC(int, nActiveRows);
+    for (i = 0; i < nActiveCols; i++) {
+      col = colOrder[i];
+      colInfo[col].lNum = 0;
+      colInfo[col].lMin = nActiveRows;
+      colInfo[col].lMax = -1;
+    }
+  } else
+    cRowOrder = NIL(int);
+
+  if (option->mlpClusterScc) {
+    sccBorder = ALLOC(int, nRows);
+    memset(sccBorder, 0, sizeof(int) * nRows);
+    sccList = sccHeadList;
+    while (sccList) {
+      sccBorder[sccList->startFunc] = 1;
+      sccBorder[sccList->lastFunc] = 2;
+      sccList = sccList->next;
+    }
+  } else
+    sccBorder = NIL(int);
+
+  MlpCluster(mddManager, xy, nRows, nCols, nActiveRows, nActiveCols,
+		&nClusterRows, &nClusterCols,
+		rowOrder, colOrder, rowInfo, colInfo,
+		clusterArray, arraySmoothVarBddArray,
+		direction, cRowOrder, nsVarBddArray, sccBorder, varPos, option);
+
+  if (sccBorder)
+    FREE(sccBorder);
+
+  if ((direction == Img_Forward_c && option->mlpReorder) ||
+      (direction == Img_Backward_c && option->mlpPreReorder) ||
+      option->mlpPostProcess >= 2) {
+    if (option->mlpDecomposeScc && NumOfSccs(sccHeadList) > 1) {
+      FreeSccList(sccHeadList);
+      sccHeadList = MlpDecomposeScc(mddManager, xy, nRows,
+				nClusterRows, nClusterCols,
+				cRowOrder, colOrder, rowInfo, colInfo,
+				1, option);
+    } else {
+      sccHeadList->startFunc = 0;
+      sccHeadList->lastFunc = nClusterRows - 1;
+      sccHeadList->startVar = 0;
+      sccHeadList->lastVar = nClusterCols - 1;
+      sccHeadList->nFuncs = nClusterRows;
+      sccHeadList->nVars = nClusterCols;
+    }
+    if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
+      PrintMatrix(xy, nClusterRows, nClusterCols, cRowOrder, colOrder,
+		  rowInfo, colInfo, 0, nClusterRows - 1, 0, nClusterCols - 1);
+    }
+
+    if ((direction == Img_Forward_c && option->mlpReorder) ||
+	(direction == Img_Backward_c && option->mlpPreReorder)) {
+      sccList = sccHeadList;
+      while (sccList) {
+	BlockLowerTriangle(xy, nRows, nCols, nClusterRows, nClusterCols,
+			   sccList, cRowOrder, colOrder, rowInfo, colInfo,
+			   option);
+	sccList = sccList->next;
+      }
+      if (option->mlpVerbosity >= 2) {
+	lambda1 = ComputeLambdaMlp(xy, nCols, nClusterRows, nClusterCols,
+				   rowInfo, colInfo, rowOrder, colOrder,
+				   direction, 0, 0, option);
+	lambda2 = ComputeLambdaMlp(xy, nCols, nClusterRows, nClusterCols,
+				   rowInfo, colInfo, rowOrder, colOrder,
+				   direction, 1, 0, option);
+	lambda3 = ComputeLambdaMlp(xy, nCols, nClusterRows, nClusterCols,
+				   rowInfo, colInfo, rowOrder, colOrder,
+				   direction, 2, 0, option);
+	fprintf(vis_stdout, "Lambda after MLP-cluster = %f (%f, %f)\n",
+		lambda1, lambda2, lambda3);
+      }
+
+      if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
+	PrintMatrix(xy, nClusterRows, nClusterCols, cRowOrder, colOrder,
+		    rowInfo, colInfo, 0, nClusterRows - 1, 0, nClusterCols - 1);
+      }
+    }
+
+    if (option->mlpPostProcess >= 2) {
+      for (x = 0; x < nClusterRows; x++) {
+	row = rowOrder[x];
+	rowInfo[row].lNum = rowInfo[row].gNum;
+	rowInfo[row].lMin = rowInfo[row].gMin;
+	rowInfo[row].lMax = rowInfo[row].gMax;
+	rowInfo[row].prevG = -1;
+	rowInfo[row].nextG = nClusterCols;
+      }
+      for (y = 0; y < nClusterCols; y++) {
+	col = colOrder[y];
+	colInfo[col].lNum = colInfo[col].gNum;
+	colInfo[col].lMin = colInfo[col].gMin;
+	colInfo[col].lMax = colInfo[col].gMax;
+	colInfo[col].prevG = -1;
+	colInfo[col].nextG = nClusterRows;
+      }
+
+      sccList = sccHeadList;
+      while (sccList) {
+	MlpPostProcess(xy, sccList, nCols, nClusterRows, nClusterCols,
+		     rowInfo, colInfo, cRowOrder, colOrder, direction, option);
+	sccList = sccList->next;
+      }
+      if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
+	PrintMatrix(xy, nClusterRows, nClusterCols, cRowOrder, colOrder,
+		    rowInfo, colInfo, 0, nClusterRows - 1, 0, nClusterCols - 1);
+      }
+    }
+
+    *clusteredRelationArrayPtr = clusterArray;
+
+    if (direction == Img_Forward_c) {
+      for (i = nClusterRows - 1; i >= 0; i--) {
+	row = cRowOrder[i];
+	array_insert_last(bdd_t *, clusterArray, rowInfo[row].data.row.func);
+	rowInfo[row].data.row.func = NIL(bdd_t);
+      }
+
+      if (nRows > nActiveRows) {
+	cluster = bdd_one(mddManager);
+	for (i = nActiveRows; i < nRows; i++) {
+	  row = rowOrder[i];
+	  relation = rowInfo[row].data.row.func;
+	  tempCluster = bdd_and(cluster, relation, 1, 1);
+	  bdd_free(cluster);
+	  cluster = tempCluster;
+	}
+	array_insert_last(bdd_t *, clusterArray, cluster);
+      }
+    } else {
+      if (nRows > nActiveRows) {
+	UpdateNonappearingNsVars(mddManager, nsVarBddArray, nClusterRows,
+				 rowInfo, cRowOrder, nonAppearingVarBddArray);
+
+	cluster = bdd_one(mddManager);
+	for (i = nActiveRows; i < nRows; i++) {
+	  row = rowOrder[i];
+	  relation = rowInfo[row].data.row.func;
+	  tempCluster = bdd_and(cluster, relation, 1, 1);
+	  bdd_free(cluster);
+	  cluster = tempCluster;
+	}
+	array_insert_last(bdd_t *, clusterArray, cluster);
+      }
+
+      for (i = 0; i < nClusterRows; i++) {
+	row = cRowOrder[i];
+	array_insert_last(bdd_t *, clusterArray, rowInfo[row].data.row.func);
+	rowInfo[row].data.row.func = NIL(bdd_t);
+      }
+    }
+
+    if (arraySmoothVarBddArrayPtr) {
+      *arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
+
+      if (direction == Img_Forward_c) {
+	if (nCols > nClusterCols) {
+	  for (i = nClusterCols; i < nCols; i++) {
+	    col = colOrder[i];
+	    array_insert_last(bdd_t *, nonAppearingVarBddArray,
+				bdd_dup(colInfo[col].data.col.var));
+	  }
+	}
+	qVarPos = nClusterCols - 1;
+	if (qVarPos >= 0) {
+	  col = colOrder[qVarPos];
+	  while (colInfo[col].gNum == 0) {
+	    array_insert_last(bdd_t *, nonAppearingVarBddArray,
+				bdd_dup(colInfo[col].data.col.var));
+	    if (qVarPos == 0)
+	      break;
+	    qVarPos--;
+	    col = colOrder[qVarPos];
+	  }
+	}
+	for (i = nClusterRows - 1; i >= 0; i--) {
+	  row = cRowOrder[i];
+	  smoothVarBddArray = array_alloc(array_t *, 0);
+	  col = colOrder[qVarPos];
+	  while (rowInfo[colInfo[col].gMin].pos == i) {
+	    array_insert_last(bdd_t *, smoothVarBddArray,
+				bdd_dup(colInfo[col].data.col.var));
+	    if (qVarPos == 0)
+	      break;
+	    qVarPos--;
+	    col = colOrder[qVarPos];
+	  }
+	  array_insert_last(array_t *, arraySmoothVarBddArray,
+			    smoothVarBddArray);
+	}
+
+	if (nRows > nActiveRows) {
+	  smoothVarBddArray = array_alloc(array_t *, 0);
+	  array_insert_last(array_t *, arraySmoothVarBddArray,
+			    smoothVarBddArray);
+	}
+      } else {
+	if (nRows == nActiveRows) {
+	  UpdateNonappearingNsVars(mddManager, nsVarBddArray, nClusterRows,
+				   rowInfo, cRowOrder, nonAppearingVarBddArray);
+	} else {
+	  smoothVarBddArray = array_alloc(array_t *, 0);
+	  for (i = nActiveRows; i < nRows; i++) {
+	    row = rowOrder[i];
+	    for (j = 0; j < array_n(rowInfo[row].data.row.nsVarBddArray); j++) {
+	      nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray,
+				  j);
+	      array_insert_last(bdd_t *, smoothVarBddArray, bdd_dup(nsVar));
+	    }
+	  }
+	  array_insert_last(array_t *, arraySmoothVarBddArray,
+			    smoothVarBddArray);
+	}
+	for (i = 0; i < nClusterRows; i++) {
+	  row = cRowOrder[i];
+	  smoothVarBddArray = array_alloc(array_t *, 0);
+	  for (j = 0; j < array_n(rowInfo[row].data.row.nsVarBddArray); j++) {
+	    nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray,
+				j);
+	    array_insert_last(bdd_t *, smoothVarBddArray, bdd_dup(nsVar));
+	  }
+
+	  s = colInfo[rowInfo[row].gMin].pos;
+	  t = colInfo[rowInfo[row].gMax].pos;
+	  for (j = s; j <= t; j++) {
+	    col = colOrder[j];
+	    if (colInfo[col].data.col.type == 2) {
+	      if (rowInfo[colInfo[col].gMax].pos == i) {
+		array_insert_last(bdd_t *, smoothVarBddArray,
+				  bdd_dup(colInfo[col].data.col.var));
+	      }
+	    }
+	  }
+	  array_insert_last(array_t *, arraySmoothVarBddArray,
+			    smoothVarBddArray);
+	}
+      }
+    }
+
+    FREE(cRowOrder);
+
+    if (option->mlpVerbosity) {
+      finalTime = util_cpu_time();
+      fprintf(vis_stdout, "time for MLP-clustering-reorder = %10g\n",
+	      (double)(finalTime - initialTime) / 1000.0);
+    }
+  } else {
+    *clusteredRelationArrayPtr = clusterArray;
+    if (arraySmoothVarBddArrayPtr)
+      *arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
+
+    if (option->mlpVerbosity) {
+      finalTime = util_cpu_time();
+      fprintf(vis_stdout, "time for MLP-clustering = %10g\n",
+	      (double)(finalTime - initialTime) / 1000.0);
+    }
+  }
+
+  FreeSccList(sccHeadList);
+
+  FREE(varPos);
+  for (i = 0; i < nRows; i++) {
+    if (xy[i])
+      FREE(xy[i]);
+  }
+  FREE(xy);
+  FREE(rowOrder);
+  FREE(colOrder);
+  for (i = 0; i < nRows; i++) {
+    if (rowInfo[i].data.row.func)
+      bdd_free(rowInfo[i].data.row.func);
+    if (rowInfo[i].data.row.nsVarBddArray)
+      array_free(rowInfo[i].data.row.nsVarBddArray);
+  }
+  FREE(rowInfo);
+  FREE(colInfo);
+  if (option->mlpInitialCluster)
+    mdd_array_free(clusteredRelationArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Orders relation array and makes quantification schedule.]
+
+  Description [Orders relation array and makes quantification schedule.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgMlpOrderRelationArray(mdd_manager *mddManager,
+			array_t *relationArray,
+			array_t *domainVarBddArray,
+			array_t *quantifyVarBddArray,
+			array_t *rangeVarBddArray,
+			Img_DirectionType direction,
+			array_t **orderedRelationArrayPtr,
+			array_t **arraySmoothVarBddArrayPtr,
+			ImgTrmOption_t *option)
+{
+  int		i, j, x, y, nRows, nCols, nActiveRows, nActiveCols;
+  int		*rowOrder, *colOrder;
+  RcInfo_t	*rowInfo, *colInfo;
+  char		**xy;
+  array_t	*orderedArray;
+  bdd_t		*relation, *var, *nsVar;
+  int		row, col, s, t;
+  array_t	*arraySmoothVarBddArray, *smoothVarBddArray;
+  int		qVarPos;
+  array_t	*nonAppearingVarBddArray;
+  int		*varPos;
+  array_t	*psVarBddArray, *nsVarBddArray;
+  int		index, nVars, nc;
+  long		initialTime, finalTime;
+  SccList_t	*sccHeadList, *sccList;
+  float		lambda1, lambda2, lambda3;
+
+  arraySmoothVarBddArray = NIL(array_t);
+  nRows = array_n(relationArray);
+  if (direction == Img_Forward_c)
+    nCols = array_n(domainVarBddArray) + array_n(quantifyVarBddArray);
+  else
+    nCols = array_n(rangeVarBddArray) + array_n(quantifyVarBddArray);
+
+  if (nCols == 0) {
+    if (direction == Img_Forward_c) {
+      orderedArray = mdd_array_duplicate(relationArray);
+      *orderedRelationArrayPtr = orderedArray;
+      if (arraySmoothVarBddArrayPtr) {
+	arraySmoothVarBddArray = array_alloc(array_t *, 0);
+	*arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
+	for (i = 0; i <= nRows; i++) {
+	  smoothVarBddArray = array_alloc(array_t *, 0);
+	  array_insert_last(array_t *, arraySmoothVarBddArray,
+			    smoothVarBddArray);
+	}
+      }
+    } else {
+      orderedArray = array_alloc(mdd_t *, 0);
+      array_insert_last(mdd_t *, orderedArray, mdd_one(mddManager));
+      *orderedRelationArrayPtr = orderedArray;
+      if (arraySmoothVarBddArrayPtr) {
+	arraySmoothVarBddArray = array_alloc(array_t *, 0);
+	*arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
+	for (i = 0; i <= 1; i++) {
+	  smoothVarBddArray = array_alloc(array_t *, 0);
+	  array_insert_last(array_t *, arraySmoothVarBddArray,
+			    smoothVarBddArray);
+	}
+      }
+    }
+    return;
+  }
+
+  if (option->mlpVerbosity)
+    initialTime = util_cpu_time();
+  else
+    initialTime = 0;
+
+  xy = ALLOC(char *, nRows);
+  for (i = 0; i < nRows; i++) {
+    xy[i] = ALLOC(char, nCols);
+    memset(xy[i], 0, sizeof(char) * nCols);
+  }
+
+  rowOrder = ALLOC(int, nRows);
+  for (i = 0; i < nRows; i++)
+    rowOrder[i] = i;
+  colOrder = ALLOC(int, nCols);
+  for (i = 0; i < nCols; i++)
+    colOrder[i] = i;
+
+  rowInfo = ALLOC(RcInfo_t, nRows);
+  memset(rowInfo, 0, sizeof(RcInfo_t) * nRows);
+  colInfo = ALLOC(RcInfo_t, nCols);
+  memset(colInfo, 0, sizeof(RcInfo_t) * nCols);
+  nVars = bdd_num_vars(mddManager);
+  varPos = ALLOC(int, nVars);
+  memset(varPos, 0, sizeof(int) * nVars);
+
+  for (i = 0; i < nRows; i++) {
+    relation = array_fetch(bdd_t *, relationArray, i);
+    rowInfo[i].data.row.func = bdd_dup(relation);
+  }
+
+  psVarBddArray = domainVarBddArray;
+  nsVarBddArray = rangeVarBddArray;
+  nc = 0;
+  for (i = 0; i < array_n(psVarBddArray); i++) {
+    var = array_fetch(bdd_t *, psVarBddArray, i);
+    colInfo[nc].data.col.var = var;
+    colInfo[nc].data.col.type = 1;
+    index = (int)bdd_top_var_id(var);
+    varPos[index] = nc;
+    nc++;
+  }
+  for (i = 0; i < array_n(quantifyVarBddArray); i++) {
+    var = array_fetch(bdd_t *, quantifyVarBddArray, i);
+    colInfo[nc].data.col.var = var;
+    colInfo[nc].data.col.type = 2;
+    index = (int)bdd_top_var_id(var);
+    varPos[index] = nc;
+    nc++;
+  }
+
+  if (arraySmoothVarBddArrayPtr)
+    nonAppearingVarBddArray = array_alloc(bdd_t *, 0);
+  else
+    nonAppearingVarBddArray = NIL(array_t);
+  SetupMlp(mddManager, xy, nRows, nCols, rowOrder, colOrder,
+	   rowInfo, colInfo, varPos, nsVarBddArray, &nActiveRows, &nActiveCols,
+	   nonAppearingVarBddArray, direction, option);
+  if (nActiveRows == 0) {
+    orderedArray = array_alloc(bdd_t *, 0);
+    if (arraySmoothVarBddArrayPtr) {
+      arraySmoothVarBddArray = array_alloc(array_t *, 0);
+      array_insert_last(array_t *, arraySmoothVarBddArray,
+			nonAppearingVarBddArray);
+    }
+    for (i = 0; i < nRows; i++) {
+      row = rowOrder[i];
+      relation = rowInfo[row].data.row.func;
+      array_insert_last(bdd_t *, orderedArray, mdd_dup(relation));
+      if (arraySmoothVarBddArrayPtr) {
+	if (direction == Img_Forward_c) {
+	  smoothVarBddArray = array_alloc(array_t *, 0);
+	  array_insert_last(array_t *, arraySmoothVarBddArray,
+			    smoothVarBddArray);
+	} else {
+	  smoothVarBddArray = rowInfo[row].data.row.nsVarBddArray;
+	  rowInfo[row].data.row.nsVarBddArray = NIL(array_t);
+	  array_insert_last(array_t *, arraySmoothVarBddArray,
+			    smoothVarBddArray);
+	}
+      }
+    }
+    *orderedRelationArrayPtr = orderedArray;
+    if (arraySmoothVarBddArrayPtr)
+      *arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
+
+    FREE(varPos);
+    for (i = 0; i < nRows; i++) {
+      if (xy[i])
+	FREE(xy[i]);
+    }
+    FREE(xy);
+    FREE(rowOrder);
+    FREE(colOrder);
+    for (i = 0; i < nRows; i++) {
+      bdd_free(rowInfo[i].data.row.func);
+      if (rowInfo[i].data.row.nsVarBddArray)
+	array_free(rowInfo[i].data.row.nsVarBddArray);
+    }
+    FREE(rowInfo);
+    FREE(colInfo);
+    return;
+  }
+  sccHeadList = MlpDecomposeScc(mddManager, xy, nRows, nActiveRows, nActiveCols,
+				rowOrder, colOrder, rowInfo, colInfo,
+				0, option);
+  if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
+    PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
+		rowInfo, colInfo, 0, nActiveRows - 1, 0, nActiveCols - 1);
+  }
+  sccList = sccHeadList;
+  while (sccList) {
+    BlockLowerTriangle(xy, nRows, nCols, nActiveRows, nActiveCols, sccList,
+			rowOrder, colOrder, rowInfo, colInfo, option);
+    sccList = sccList->next;
+  }
+  if (option->mlpVerbosity >= 2) {
+    lambda1 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
+				rowInfo, colInfo, rowOrder, colOrder,
+				direction, 0, 0, option);
+    lambda2 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
+				rowInfo, colInfo, rowOrder, colOrder,
+				direction, 1, 0, option);
+    lambda3 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
+				rowInfo, colInfo, rowOrder, colOrder,
+				direction, 2, 0, option);
+    fprintf(vis_stdout, "Lambda after MLP = %f (%f, %f)\n",
+	    lambda1, lambda2, lambda3);
+  }
+
+  if (option->mlpVerbosity) {
+    finalTime = util_cpu_time();
+    fprintf(vis_stdout, "time for MLP = %10g\n",
+	   (double)(finalTime - initialTime) / 1000.0);
+  }
+  if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
+    PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
+		rowInfo, colInfo, 0, nActiveRows - 1, 0, nActiveCols - 1);
+  }
+
+  if (option->mlpPostProcess) {
+    for (x = 0; x < nRows; x++) {
+      row = rowOrder[x];
+      rowInfo[row].lNum = rowInfo[row].gNum;
+      rowInfo[row].lMin = rowInfo[row].gMin;
+      rowInfo[row].lMax = rowInfo[row].gMax;
+      rowInfo[row].prevG = -1;
+      rowInfo[row].nextG = nCols;
+    }
+    for (y = 0; y < nCols; y++) {
+      col = colOrder[y];
+      colInfo[col].lNum = colInfo[col].gNum;
+      colInfo[col].lMin = colInfo[col].gMin;
+      colInfo[col].lMax = colInfo[col].gMax;
+      colInfo[col].prevG = -1;
+      colInfo[col].nextG = nRows;
+    }
+
+    sccList = sccHeadList;
+    while (sccList) {
+      MlpPostProcess(xy, sccList, nCols, nActiveRows, nActiveCols,
+		   rowInfo, colInfo, rowOrder, colOrder, direction, option);
+      sccList = sccList->next;
+    }
+    if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
+      PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
+		  rowInfo, colInfo, 0, nActiveRows - 1, 0, nActiveCols - 1);
+    }
+  }
+
+  orderedArray = array_alloc(bdd_t *, 0);
+  if (arraySmoothVarBddArrayPtr) {
+    arraySmoothVarBddArray = array_alloc(array_t *, 0);
+    array_insert_last(array_t *, arraySmoothVarBddArray,
+			nonAppearingVarBddArray);
+  }
+
+  assert(nActiveCols > 0);
+  if (direction == Img_Forward_c) {
+    if (arraySmoothVarBddArrayPtr) {
+      if (nCols > nActiveCols) {
+	for (i = nActiveCols; i < nCols; i++) {
+	  col = colOrder[i];
+	  array_insert_last(bdd_t *, nonAppearingVarBddArray,
+			    bdd_dup(colInfo[col].data.col.var));
+	}
+      }
+      qVarPos = nActiveCols - 1;
+      if (qVarPos >= 0) {
+	col = colOrder[qVarPos];
+	while (colInfo[col].gNum == 0) {
+	  array_insert_last(bdd_t *, nonAppearingVarBddArray,
+			    bdd_dup(colInfo[col].data.col.var));
+	  if (qVarPos == 0)
+	    break;
+	  qVarPos--;
+	  col = colOrder[qVarPos];
+	}
+      }
+    } else
+      qVarPos = 0; /* to avoid warning */
+    for (i = nActiveRows - 1; i >= 0; i--) {
+      row = rowOrder[i];
+      if (arraySmoothVarBddArrayPtr) {
+	smoothVarBddArray = array_alloc(array_t *, 0);
+	col = colOrder[qVarPos];
+	while (rowInfo[colInfo[col].gMin].pos == i) {
+	  index = (int)bdd_top_var_id(colInfo[col].data.col.var);
+	  array_insert_last(bdd_t *, smoothVarBddArray,
+				bdd_dup(colInfo[col].data.col.var));
+	  if (qVarPos == 0)
+	    break;
+	  qVarPos--;
+	  col = colOrder[qVarPos];
+	}
+	array_insert_last(array_t *, arraySmoothVarBddArray, smoothVarBddArray);
+      }
+      relation = bdd_dup(rowInfo[row].data.row.func);
+      array_insert_last(bdd_t *, orderedArray, relation);
+    }
+
+    if (nRows > nActiveRows) {
+      for (i = nActiveRows; i < nRows; i++) {
+	row = rowOrder[i];
+	relation = rowInfo[row].data.row.func;
+	array_insert_last(bdd_t *, orderedArray, mdd_dup(relation));
+	if (arraySmoothVarBddArrayPtr) {
+	  smoothVarBddArray = array_alloc(array_t *, 0);
+	  array_insert_last(array_t *, arraySmoothVarBddArray,
+			    smoothVarBddArray);
+	}
+      }
+    }
+  } else {
+    if (arraySmoothVarBddArrayPtr) {
+      UpdateNonappearingNsVars(mddManager, nsVarBddArray, nActiveRows,
+				rowInfo, rowOrder, nonAppearingVarBddArray);
+    }
+    if (nRows > nActiveRows) {
+      for (i = nActiveRows; i < nRows; i++) {
+	row = rowOrder[i];
+	relation = rowInfo[row].data.row.func;
+	array_insert_last(bdd_t *, orderedArray, mdd_dup(relation));
+	if (arraySmoothVarBddArrayPtr) {
+	  smoothVarBddArray = rowInfo[row].data.row.nsVarBddArray;
+	  rowInfo[row].data.row.nsVarBddArray = NIL(array_t);
+	  array_insert_last(array_t *, arraySmoothVarBddArray,
+			    smoothVarBddArray);
+	}
+      }
+    }
+    for (i = 0; i < nActiveRows; i++) {
+      row = rowOrder[i];
+      if (arraySmoothVarBddArrayPtr) {
+	smoothVarBddArray = array_alloc(array_t *, 0);
+	for (j = 0; j < array_n(rowInfo[row].data.row.nsVarBddArray); j++) {
+	  nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray, j);
+	  array_insert_last(bdd_t *, smoothVarBddArray, bdd_dup(nsVar));
+	}
+
+	s = colInfo[rowInfo[row].gMin].pos;
+	t = colInfo[rowInfo[row].gMax].pos;
+	for (j = s; j <= t; j++) {
+	  col = colOrder[j];
+	  if (colInfo[col].data.col.type == 2) {
+	    if (rowInfo[colInfo[col].gMax].pos == i) {
+	      array_insert_last(bdd_t *, smoothVarBddArray,
+				bdd_dup(colInfo[col].data.col.var));
+	    }
+	  }
+	}
+	array_insert_last(array_t *, arraySmoothVarBddArray, smoothVarBddArray);
+      }
+      relation = bdd_dup(rowInfo[row].data.row.func);
+      array_insert_last(bdd_t *, orderedArray, relation);
+    }
+  }
+
+  *orderedRelationArrayPtr = orderedArray;
+  if (arraySmoothVarBddArrayPtr)
+    *arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
+
+  FreeSccList(sccHeadList);
+
+  FREE(varPos);
+  for (i = 0; i < nRows; i++) {
+    if (xy[i])
+      FREE(xy[i]);
+  }
+  FREE(xy);
+  FREE(rowOrder);
+  FREE(colOrder);
+  for (i = 0; i < nRows; i++) {
+    bdd_free(rowInfo[i].data.row.func);
+    if (rowInfo[i].data.row.nsVarBddArray)
+      array_free(rowInfo[i].data.row.nsVarBddArray);
+  }
+  FREE(rowInfo);
+  FREE(colInfo);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compute variables lifetime using MLP.]
+
+  Description [Compute variables lifetime using MLP.]
+
+  SideEffects []
+
+******************************************************************************/
+float
+ImgMlpComputeLambda(mdd_manager *mddManager,
+		    array_t *relationArray,
+		    array_t *domainVarBddArray,
+		    array_t *quantifyVarBddArray,
+		    array_t *rangeVarBddArray,
+		    Img_DirectionType direction,
+		    int mode,
+		    int asIs,
+		    int *prevArea,
+		    float *improvedLambda,
+		    ImgTrmOption_t *option)
+{
+  int		i, nRows, nCols, nActiveRows, nActiveCols;
+  int		*rowOrder, *colOrder;
+  RcInfo_t	*rowInfo, *colInfo;
+  char		**xy;
+  bdd_t		*relation, *var;
+  int		*varPos;
+  array_t	*psVarBddArray, *nsVarBddArray;
+  int		index, nVars, nc;
+  SccList_t	*sccHeadList, *sccList;
+  float		lambda;
+  int		area;
+
+  nRows = array_n(relationArray);
+  if (direction == Img_Forward_c)
+    nCols = array_n(domainVarBddArray) + array_n(quantifyVarBddArray);
+  else
+    nCols = array_n(rangeVarBddArray) + array_n(quantifyVarBddArray);
+
+  if (nCols == 0) {
+    if (improvedLambda) {
+      *improvedLambda = 0.0;
+      *prevArea = 0;
+    }
+    return(0.0);
+  }
+
+  xy = ALLOC(char *, nRows);
+  for (i = 0; i < nRows; i++) {
+    xy[i] = ALLOC(char, nCols);
+    memset(xy[i], 0, sizeof(char) * nCols);
+  }
+
+  rowOrder = ALLOC(int, nRows);
+  for (i = 0; i < nRows; i++)
+    rowOrder[i] = i;
+  colOrder = ALLOC(int, nCols);
+  for (i = 0; i < nCols; i++)
+    colOrder[i] = i;
+
+  rowInfo = ALLOC(RcInfo_t, nRows);
+  memset(rowInfo, 0, sizeof(RcInfo_t) * nRows);
+  colInfo = ALLOC(RcInfo_t, nCols);
+  memset(colInfo, 0, sizeof(RcInfo_t) * nCols);
+  nVars = bdd_num_vars(mddManager);
+  varPos = ALLOC(int, nVars);
+  memset(varPos, 0, sizeof(int) * nVars);
+
+  for (i = 0; i < nRows; i++) {
+    relation = array_fetch(bdd_t *, relationArray, i);
+    rowInfo[i].data.row.func = bdd_dup(relation);
+  }
+
+  psVarBddArray = domainVarBddArray;
+  nsVarBddArray = rangeVarBddArray;
+  nc = 0;
+  for (i = 0; i < array_n(psVarBddArray); i++) {
+    var = array_fetch(bdd_t *, psVarBddArray, i);
+    colInfo[nc].data.col.var = var;
+    colInfo[nc].data.col.type = 1;
+    index = (int)bdd_top_var_id(var);
+    varPos[index] = nc;
+    nc++;
+  }
+  for (i = 0; i < array_n(quantifyVarBddArray); i++) {
+    var = array_fetch(bdd_t *, quantifyVarBddArray, i);
+    colInfo[nc].data.col.var = var;
+    colInfo[nc].data.col.type = 2;
+    index = (int)bdd_top_var_id(var);
+    varPos[index] = nc;
+    nc++;
+  }
+
+  SetupMlp(mddManager, xy, nRows, nCols, rowOrder, colOrder,
+	   rowInfo, colInfo, varPos, nsVarBddArray, &nActiveRows, &nActiveCols,
+	   NIL(array_t), direction, option);
+  if (nActiveRows == 0) {
+    FREE(varPos);
+    for (i = 0; i < nRows; i++) {
+      if (xy[i])
+	FREE(xy[i]);
+    }
+    FREE(xy);
+    FREE(rowOrder);
+    FREE(colOrder);
+    for (i = 0; i < nRows; i++) {
+      bdd_free(rowInfo[i].data.row.func);
+      if (rowInfo[i].data.row.nsVarBddArray)
+	array_free(rowInfo[i].data.row.nsVarBddArray);
+    }
+    FREE(rowInfo);
+    FREE(colInfo);
+
+    if (improvedLambda) {
+      *improvedLambda = 0.0;
+      *prevArea = 0;
+    }
+    return(0.0);
+  }
+  sccHeadList = MlpDecomposeScc(mddManager, xy, nRows, nActiveRows, nActiveCols,
+				rowOrder, colOrder, rowInfo, colInfo,
+				0, option);
+  sccList = sccHeadList;
+  while (sccList) {
+    BlockLowerTriangle(xy, nRows, nCols, nActiveRows, nActiveCols, sccList,
+			rowOrder, colOrder, rowInfo, colInfo, option);
+    sccList = sccList->next;
+  }
+
+  lambda = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
+			    rowInfo, colInfo, rowOrder, colOrder,
+			    direction, mode, asIs, option);
+
+  FreeSccList(sccHeadList);
+
+  FREE(varPos);
+  for (i = 0; i < nRows; i++) {
+    if (xy[i])
+      FREE(xy[i]);
+  }
+  FREE(xy);
+  FREE(rowOrder);
+  FREE(colOrder);
+  for (i = 0; i < nRows; i++) {
+    bdd_free(rowInfo[i].data.row.func);
+    if (rowInfo[i].data.row.nsVarBddArray)
+      array_free(rowInfo[i].data.row.nsVarBddArray);
+  }
+  FREE(rowInfo);
+  FREE(colInfo);
+
+  if (option->mlpLambdaMode == 0)
+    area = nActiveRows * nActiveCols;
+  else
+    area = nActiveRows * nCols;
+  if (improvedLambda) {
+    if (*prevArea)
+      *improvedLambda = lambda * (float)area / (*prevArea);
+    else
+      *improvedLambda = 0.0;
+    *prevArea = area;
+  }
+  return(lambda);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makes a quantification schedule using MLP.]
+
+  Description [Makes a quantification schedule using MLP.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgMlpGetQuantificationSchedule(mdd_manager *mddManager,
+			array_t *relationArray,
+			array_t *domainVarBddArray,
+			array_t *quantifyVarBddArray,
+			array_t *rangeVarBddArray,
+			array_t **clusteredRelationArrayPtr,
+			array_t **arraySmoothVarBddArrayPtr,
+			Img_DirectionType direction,
+			ImgTrmOption_t *option)
+{
+  int		i, j, nRows, nCols, nActiveRows, nActiveCols;
+  int		*rowOrder, *colOrder;
+  RcInfo_t	*rowInfo, *colInfo;
+  char		**xy;
+  bdd_t		*relation, *var, *nsVar;
+  int		*varPos;
+  array_t	*psVarBddArray, *nsVarBddArray;
+  int		index, nVars, nc;
+  array_t	*arraySmoothVarBddArray, *smoothVarBddArray;
+  int		qVarPos, row, col, s, t;
+  array_t	*nonAppearingVarBddArray;
+  array_t	*clusteredRelationArray;
+
+  nRows = array_n(relationArray);
+  if (direction == Img_Forward_c)
+    nCols = array_n(domainVarBddArray) + array_n(quantifyVarBddArray);
+  else
+    nCols = array_n(rangeVarBddArray) + array_n(quantifyVarBddArray);
+
+  xy = ALLOC(char *, nRows);
+  for (i = 0; i < nRows; i++) {
+    xy[i] = ALLOC(char, nCols);
+    memset(xy[i], 0, sizeof(char) * nCols);
+  }
+
+  rowOrder = ALLOC(int, nRows);
+  for (i = 0; i < nRows; i++)
+    rowOrder[i] = i;
+  colOrder = ALLOC(int, nCols);
+  for (i = 0; i < nCols; i++)
+    colOrder[i] = i;
+
+  rowInfo = ALLOC(RcInfo_t, nRows);
+  memset(rowInfo, 0, sizeof(RcInfo_t) * nRows);
+  colInfo = ALLOC(RcInfo_t, nCols);
+  memset(colInfo, 0, sizeof(RcInfo_t) * nCols);
+  nVars = bdd_num_vars(mddManager);
+  varPos = ALLOC(int, nVars);
+  memset(varPos, 0, sizeof(int) * nVars);
+
+  psVarBddArray = domainVarBddArray;
+  nsVarBddArray = rangeVarBddArray;
+  if (direction == Img_Forward_c) {
+    for (i = 0; i < nRows; i++) {
+      relation = array_fetch(bdd_t *, relationArray, nRows - 1 - i);
+      rowInfo[i].data.row.func = bdd_dup(relation);
+    }
+  } else {
+    for (i = 0; i < nRows; i++) {
+      relation = array_fetch(bdd_t *, relationArray, i);
+      rowInfo[i].data.row.func = bdd_dup(relation);
+    }
+  }
+  nc = 0;
+  for (i = 0; i < array_n(psVarBddArray); i++) {
+    var = array_fetch(bdd_t *, psVarBddArray, i);
+    colInfo[nc].data.col.var = var;
+    colInfo[nc].data.col.type = 1;
+    index = (int)bdd_top_var_id(var);
+    varPos[index] = nc;
+    nc++;
+  }
+  for (i = 0; i < array_n(quantifyVarBddArray); i++) {
+    var = array_fetch(bdd_t *, quantifyVarBddArray, i);
+    colInfo[nc].data.col.var = var;
+    colInfo[nc].data.col.type = 2;
+    index = (int)bdd_top_var_id(var);
+    varPos[index] = nc;
+    nc++;
+  }
+
+  nonAppearingVarBddArray = array_alloc(bdd_t *, 0);
+  SetupMlp(mddManager, xy, nRows, nCols, rowOrder, colOrder,
+	   rowInfo, colInfo, varPos, nsVarBddArray, &nActiveRows, &nActiveCols,
+	   nonAppearingVarBddArray, direction, option);
+  SortCol(xy, nActiveRows, nActiveCols, rowInfo, colInfo, rowOrder, colOrder);
+
+  clusteredRelationArray = array_alloc(mdd_t *, 0);
+  arraySmoothVarBddArray = array_alloc(array_t *, 0);
+  if (direction == Img_Forward_c) {
+    if (nCols > nActiveCols) {
+      for (i = nActiveCols; i < nCols; i++) {
+	col = colOrder[i];
+	array_insert_last(bdd_t *, nonAppearingVarBddArray,
+			  bdd_dup(colInfo[col].data.col.var));
+      }
+    }
+    qVarPos = nActiveCols - 1;
+    if (qVarPos >= 0) {
+      col = colOrder[qVarPos];
+      while (colInfo[col].gNum == 0) {
+	array_insert_last(bdd_t *, nonAppearingVarBddArray,
+			  bdd_dup(colInfo[col].data.col.var));
+	if (qVarPos == 0)
+	  break;
+	qVarPos--;
+	col = colOrder[qVarPos];
+      }
+    }
+    array_insert_last(array_t *, arraySmoothVarBddArray,
+			nonAppearingVarBddArray);
+    for (i = nActiveRows - 1; i >= 0; i--) {
+      row = rowOrder[i];
+      smoothVarBddArray = array_alloc(array_t *, 0);
+      if (rowInfo[row].gNum > 0) {
+	col = colOrder[qVarPos];
+	while (rowInfo[colInfo[col].gMin].pos == i) {
+	  index = (int)bdd_top_var_id(colInfo[col].data.col.var);
+	  array_insert_last(bdd_t *, smoothVarBddArray,
+				bdd_dup(colInfo[col].data.col.var));
+	  if (qVarPos == 0)
+	    break;
+	  qVarPos--;
+	  col = colOrder[qVarPos];
+	}
+      }
+      array_insert_last(array_t *, arraySmoothVarBddArray, smoothVarBddArray);
+      relation = bdd_dup(rowInfo[row].data.row.func);
+      array_insert_last(bdd_t *, clusteredRelationArray, relation);
+    }
+    if (nRows > nActiveRows) {
+      for (i = nActiveRows; i < nRows; i++) {
+	row = rowOrder[i];
+	smoothVarBddArray = array_alloc(array_t *, 0);
+	array_insert_last(array_t *, arraySmoothVarBddArray, smoothVarBddArray);
+	relation = bdd_dup(rowInfo[row].data.row.func);
+	array_insert_last(bdd_t *, clusteredRelationArray, relation);
+      }
+    }
+  } else {
+    array_insert_last(array_t *, arraySmoothVarBddArray,
+			nonAppearingVarBddArray);
+    if (nRows > nActiveRows) {
+      for (i = nActiveRows; i < nRows; i++) {
+	row = rowOrder[i];
+	smoothVarBddArray = rowInfo[row].data.row.nsVarBddArray;
+	rowInfo[row].data.row.nsVarBddArray = NIL(array_t);
+	array_insert_last(array_t *, arraySmoothVarBddArray, smoothVarBddArray);
+	relation = bdd_dup(rowInfo[row].data.row.func);
+	array_insert_last(bdd_t *, clusteredRelationArray, relation);
+      }
+    }
+    for (i = 0; i < nActiveRows; i++) {
+      row = rowOrder[i];
+      smoothVarBddArray = array_alloc(array_t *, 0);
+      for (j = 0; j < array_n(rowInfo[row].data.row.nsVarBddArray); j++) {
+	nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray, j);
+	array_insert_last(bdd_t *, smoothVarBddArray, bdd_dup(nsVar));
+      }
+      if (rowInfo[row].gNum > 0) {
+	s = colInfo[rowInfo[row].gMin].pos;
+	t = colInfo[rowInfo[row].gMax].pos;
+	for (j = s; j <= t; j++) {
+	  col = colOrder[j];
+	  if (colInfo[col].data.col.type == 2) {
+	    if (rowInfo[colInfo[col].gMax].pos == i) {
+	      array_insert_last(bdd_t *, smoothVarBddArray,
+				bdd_dup(colInfo[col].data.col.var));
+	    }
+	  }
+	}
+      }
+      array_insert_last(array_t *, arraySmoothVarBddArray, smoothVarBddArray);
+      relation = bdd_dup(rowInfo[row].data.row.func);
+      array_insert_last(bdd_t *, clusteredRelationArray, relation);
+    }
+  }
+
+  FREE(varPos);
+  for (i = 0; i < nRows; i++) {
+    if (xy[i])
+      FREE(xy[i]);
+  }
+  FREE(xy);
+  FREE(rowOrder);
+  FREE(colOrder);
+  for (i = 0; i < nRows; i++) {
+    bdd_free(rowInfo[i].data.row.func);
+    if (rowInfo[i].data.row.nsVarBddArray)
+      array_free(rowInfo[i].data.row.nsVarBddArray);
+  }
+  FREE(rowInfo);
+  FREE(colInfo);
+
+  *clusteredRelationArrayPtr = clusteredRelationArray;
+  *arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints dependence matrix.]
+
+  Description [Prints dependence matrix.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgMlpPrintDependenceMatrix(mdd_manager *mddManager,
+			array_t *relationArray,
+			array_t *domainVarBddArray,
+			array_t *quantifyVarBddArray,
+			array_t *rangeVarBddArray,
+			Img_DirectionType direction,
+			int printFlag, FILE *fout,
+			ImgTrmOption_t *option)
+{
+  int		i, nRows, nCols, nActiveRows, nActiveCols;
+  int		*rowOrder, *colOrder;
+  RcInfo_t	*rowInfo, *colInfo;
+  char		**xy;
+  bdd_t		*relation, *var;
+  int		*varPos;
+  array_t	*psVarBddArray, *nsVarBddArray;
+  int		index, nVars, nc;
+  float		lambda1, lambda2, lambda3;
+
+  nRows = array_n(relationArray);
+  if (direction == Img_Forward_c)
+    nCols = array_n(domainVarBddArray) + array_n(quantifyVarBddArray);
+  else
+    nCols = array_n(rangeVarBddArray) + array_n(quantifyVarBddArray);
+
+  xy = ALLOC(char *, nRows);
+  for (i = 0; i < nRows; i++) {
+    xy[i] = ALLOC(char, nCols);
+    memset(xy[i], 0, sizeof(char) * nCols);
+  }
+
+  rowOrder = ALLOC(int, nRows);
+  for (i = 0; i < nRows; i++)
+    rowOrder[i] = i;
+  colOrder = ALLOC(int, nCols);
+  for (i = 0; i < nCols; i++)
+    colOrder[i] = i;
+
+  rowInfo = ALLOC(RcInfo_t, nRows);
+  memset(rowInfo, 0, sizeof(RcInfo_t) * nRows);
+  colInfo = ALLOC(RcInfo_t, nCols);
+  memset(colInfo, 0, sizeof(RcInfo_t) * nCols);
+  nVars = bdd_num_vars(mddManager);
+  varPos = ALLOC(int, nVars);
+  memset(varPos, 0, sizeof(int) * nVars);
+
+  psVarBddArray = domainVarBddArray;
+  nsVarBddArray = rangeVarBddArray;
+  if (direction == Img_Forward_c) {
+    for (i = 0; i < nRows; i++) {
+      relation = array_fetch(bdd_t *, relationArray, nRows - 1 - i);
+      rowInfo[i].data.row.func = bdd_dup(relation);
+    }
+  } else {
+    for (i = 0; i < nRows; i++) {
+      relation = array_fetch(bdd_t *, relationArray, i);
+      rowInfo[i].data.row.func = bdd_dup(relation);
+    }
+  }
+  nc = 0;
+  for (i = 0; i < array_n(psVarBddArray); i++) {
+    var = array_fetch(bdd_t *, psVarBddArray, i);
+    colInfo[nc].data.col.var = var;
+    colInfo[nc].data.col.type = 1;
+    index = (int)bdd_top_var_id(var);
+    varPos[index] = nc;
+    nc++;
+  }
+  for (i = 0; i < array_n(quantifyVarBddArray); i++) {
+    var = array_fetch(bdd_t *, quantifyVarBddArray, i);
+    colInfo[nc].data.col.var = var;
+    colInfo[nc].data.col.type = 2;
+    index = (int)bdd_top_var_id(var);
+    varPos[index] = nc;
+    nc++;
+  }
+
+  SetupMlp(mddManager, xy, nRows, nCols, rowOrder, colOrder,
+	   rowInfo, colInfo, varPos, nsVarBddArray, &nActiveRows, &nActiveCols,
+	   NIL(array_t), direction, option);
+  SortCol(xy, nActiveRows, nActiveCols, rowInfo, colInfo, rowOrder, colOrder);
+
+  if (printFlag) {
+    PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
+		rowInfo, colInfo, 0, nActiveRows - 1, 0, nActiveCols - 1);
+  }
+  if (fout) {
+    WriteMatrix(fout, xy, nActiveRows, nActiveCols, rowOrder, colOrder,
+		rowInfo, colInfo);
+  }
+  lambda1 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
+				rowInfo, colInfo, rowOrder, colOrder,
+				direction, 0, 0, option);
+  lambda2 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
+				rowInfo, colInfo, rowOrder, colOrder,
+				direction, 1, 0, option);
+  lambda3 = ComputeLambdaMlp(xy, nCols, nActiveRows, nActiveCols,
+				rowInfo, colInfo, rowOrder, colOrder,
+				direction, 2, 0, option);
+  fprintf(vis_stdout, "Lambda = %f (%f, %f)\n", lambda1, lambda2, lambda3);
+
+  FREE(varPos);
+  for (i = 0; i < nRows; i++) {
+    if (xy[i])
+      FREE(xy[i]);
+  }
+  FREE(xy);
+  FREE(rowOrder);
+  FREE(colOrder);
+  for (i = 0; i < nRows; i++) {
+    bdd_free(rowInfo[i].data.row.func);
+    if (rowInfo[i].data.row.nsVarBddArray)
+      array_free(rowInfo[i].data.row.nsVarBddArray);
+  }
+  FREE(rowInfo);
+  FREE(colInfo);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes cluster to a file.]
+
+  Description [Writes cluster to a file.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgMlpWriteClusterFile(FILE *fout,
+			mdd_manager *mddManager,
+			array_t *relationArray,
+			array_t *psVarBddArray,
+			array_t *nsVarBddArray)
+{
+  int		i, j, k, nVars;
+  int		bddId, mddId, id, index;
+  mdd_t		*relation;
+  mdd_t		*psVar, *nsVar, **nsVars, **ns2ps;
+  array_t	*supportBddIdArray, *bddIdArray;
+  char		*name;
+  int		count;
+
+  nVars = bdd_num_vars(mddManager);
+  nsVars = ALLOC(bdd_t *, nVars);
+  memset(nsVars, 0, sizeof(bdd_t *) * nVars);
+  ns2ps = ALLOC(bdd_t *, nVars);
+  memset(ns2ps, 0, sizeof(bdd_t *) * nVars);
+
+  for (i = 0; i < array_n(nsVarBddArray); i++) {
+    psVar = array_fetch(bdd_t *, psVarBddArray, i);
+    nsVar = array_fetch(bdd_t *, nsVarBddArray, i);
+    index = (int)bdd_top_var_id(nsVar);
+    nsVars[index] = nsVar;
+    ns2ps[index] = psVar;
+  }
+
+  count = 0;
+  for (i = 0; i < array_n(relationArray); i++) {
+    relation = array_fetch(mdd_t *, relationArray, i);
+    supportBddIdArray = mdd_get_bdd_support_ids(mddManager, relation);
+    psVar = NULL;
+    for (j = 0; j < array_n(supportBddIdArray); j++) {
+      bddId = array_fetch(int, supportBddIdArray, j);
+      psVar = ns2ps[bddId];
+      if (psVar) {
+	break;
+      }
+    }
+    if (psVar) {
+      if (count == 0)
+	fprintf(fout, "CLUSTER[%d] {\n", count);
+      else
+	fprintf(fout, "\nCLUSTER[%d] {\n", count);
+      count++;
+    }
+    for (j = 0; j < array_n(supportBddIdArray); j++) {
+      bddId = array_fetch(int, supportBddIdArray, j);
+      psVar = ns2ps[bddId];
+      if (psVar) {
+	name = mdd_read_var_name(psVar);
+	nsVar = nsVars[bddId];
+	mddId = mdd_read_mdd_id(nsVar);
+	bddIdArray = mdd_id_to_bdd_id_array(mddManager, mddId);
+	for (k = 0; k < array_n(bddIdArray); k++) {
+	  id = array_fetch(int, bddIdArray, k);
+	  if (id == bddId) {
+	    fprintf(fout, "%s %d\n", name, k);
+	    break;
+	  }
+	}
+	array_free(bddIdArray);
+      }
+    }
+    array_free(supportBddIdArray);
+    fprintf(fout, "}\n");
+  }
+
+  FREE(nsVars);
+  FREE(ns2ps);
+}
+
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads cluster file.]
+
+  Description [Reads cluster file.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgMlpReadClusterFile(FILE *fin, mdd_manager *mddManager,
+			ImgFunctionData_t *functionData,
+			array_t *relationArray,
+			array_t *psVarBddArray,
+			array_t *nsVarBddArray,
+			array_t *quantifyVarBddArray,
+			Img_DirectionType direction,
+			array_t **clusteredRelationArrayPtr,
+			array_t **arraySmoothVarBddArrayPtr,
+			ImgTrmOption_t *option)
+{
+  array_t	*clusteredRelationArray, *newRelationArray;
+  array_t	*arraySmoothVarBddArray;
+  int		i, j, k, nVars;
+  long		bddId;
+  int		mddId, id, index;
+  mdd_t		*relation, *cluster, *newCluster;
+  mdd_t		*var, *psVar, *nsVar, **nsVars, **ns2ps;
+  array_t	*supportBddIdArray, *bddIdArray;
+  char		*name;
+  LatchList_t	**latchList;
+  st_table	*intermediateTable, *nameTable, *quantifyVarsTable, *idTable;
+  int		nRelVars, relBddId, relMddId;
+  mdd_t		*relVar;
+  char		*resolved;
+  char		line[512], nameArray[512];
+  st_generator	*stGen1, *stGen2;
+
+  nVars = bdd_num_vars(mddManager);
+  nsVars = ALLOC(bdd_t *, nVars);
+  memset(nsVars, 0, sizeof(bdd_t *) * nVars);
+  ns2ps = ALLOC(bdd_t *, nVars);
+  memset(ns2ps, 0, sizeof(bdd_t *) * nVars);
+  latchList = ALLOC(LatchList_t *, nVars);
+  memset(latchList, 0, sizeof(LatchList_t *) * nVars);
+  resolved = ALLOC(char, nVars);
+  memset(resolved, 0, sizeof(char) * nVars);
+
+  quantifyVarsTable = st_init_table(st_numcmp, st_numhash);
+  for (i = 0; i < array_n(functionData->quantifyBddVars); i++) {
+    var = array_fetch(mdd_t *, functionData->quantifyBddVars, i);
+    index = (int)bdd_top_var_id(var);
+    st_insert(quantifyVarsTable, (char *)(long)index, NIL(char));
+  }
+
+  nameTable = st_init_table(strcmp, st_strhash);
+  for (i = 0; i < array_n(nsVarBddArray); i++) {
+    psVar = array_fetch(bdd_t *, psVarBddArray, i);
+    nsVar = array_fetch(bdd_t *, nsVarBddArray, i);
+    index = (int)bdd_top_var_id(nsVar);
+    nsVars[index] = nsVar;
+    ns2ps[index] = psVar;
+    name = mdd_read_var_name(psVar);
+    mddId = mdd_read_mdd_id(nsVar);
+    st_insert(nameTable, name, (char *)(long)mddId);
+
+    index = (int)bdd_top_var_id(psVar);
+    st_insert(quantifyVarsTable, (char *)(long)index, NIL(char));
+  }
+
+  i = 0;
+  st_foreach_item_int(nameTable, stGen1, &name, &mddId) {
+    printf("[%d] name = %s mdd = %d\n", i, name, mddId);
+    i++;
+  }
+
+  intermediateTable = st_init_table(st_ptrcmp, st_ptrhash);
+  for (i = 0; i < array_n(relationArray); i++) {
+    relation = array_fetch(mdd_t *, relationArray, i);
+    supportBddIdArray = mdd_get_bdd_support_ids(mddManager, relation);
+    nRelVars = 0;
+    psVar = NIL(bdd_t);
+    nsVar = NIL(bdd_t);
+    relVar = NIL(bdd_t);
+    relBddId = -1;
+    relMddId = -1;
+    idTable = st_init_table(st_numcmp, st_numhash);
+    for (j = 0; j < array_n(supportBddIdArray); j++) {
+      bddId = (long) array_fetch(int, supportBddIdArray, j);
+      if (st_lookup(quantifyVarsTable, (char *)bddId, NIL(char *)))
+	continue;
+      psVar = ns2ps[bddId];
+      if (psVar) {
+	if (relVar) {
+	  bdd_free(relVar);
+	  relVar = NIL(bdd_t);
+	}
+	nsVar = nsVars[bddId];
+	relMddId = mdd_read_mdd_id(nsVar);
+	relBddId = (int) bddId;
+	break;
+      } else {
+	if (nRelVars > 0) {
+	  if (relVar)
+	    bdd_free(relVar);
+	}
+	relVar = bdd_var_with_index(mddManager, (int) bddId);
+	relMddId = mdd_read_mdd_id(relVar);
+	relBddId = (int) bddId;
+	name = mdd_read_var_name(relVar);
+	st_insert(nameTable, name, (char *)(long)relMddId);
+	st_insert(idTable, (char *)bddId, NIL(char));
+	if (nRelVars >= 1) {
+	  bdd_free(relVar);
+	  relVar = NIL(bdd_t);
+	}
+	nRelVars++;
+      }
+    }
+    array_free(supportBddIdArray);
+    if (nsVar || relVar) {
+      bddId = (int) relBddId;
+      mddId = relMddId;
+
+      if (relVar)
+	resolved[bddId] = 1;
+
+      bddIdArray = mdd_id_to_bdd_id_array(mddManager, mddId);
+      for (k = 0; k < array_n(bddIdArray); k++) {
+	id = array_fetch(int, bddIdArray, k);
+	if (id == bddId) {
+	  if (latchList[mddId]) {
+	    if (latchList[mddId]->number == 1) {
+	      latchList[mddId]->table = st_init_table(st_numcmp, st_numhash);
+	      st_insert(latchList[mddId]->table,
+			(char *)(long)latchList[mddId]->bddId,
+			(char *)latchList[mddId]->relation);
+	    }
+	    st_insert(latchList[mddId]->table, (char *)bddId,
+		      (char *)relation);
+	  } else {
+	    latchList[mddId] = ALLOC(LatchList_t, 1);
+	    latchList[mddId]->bddId = (int) bddId;
+	    latchList[mddId]->relation = relation;
+	    latchList[mddId]->number = 1;
+	    latchList[mddId]->table = NIL(st_table);
+	  }
+	  break;
+	}
+      }
+      array_free(bddIdArray);
+      st_free_table(idTable);
+    } else {
+      st_insert(intermediateTable, (char *)relation, (char *)idTable);
+    }
+  }
+
+  i = 0;
+  st_foreach_item_int(nameTable, stGen1, &name, &mddId) {
+    printf("[%d] name = %s mdd = %d\n", i, name, mddId);
+    i++;
+  }
+
+  while (intermediateTable->num_entries > 0) {
+    st_foreach_item(intermediateTable, stGen1, &relation, &idTable) {
+      st_foreach_item(idTable, stGen2, &bddId, NIL(char *)) {
+	if (resolved[bddId])
+	  st_delete(idTable, &bddId, NIL(char *));
+      }
+      if (idTable->num_entries == 1) {
+	st_foreach_item(idTable, stGen2, &bddId, NULL);
+	relVar = bdd_var_with_index(mddManager, (int) bddId);
+	mddId = mdd_read_mdd_id(relVar);
+	mdd_free(relVar);
+
+	st_delete(intermediateTable, &relation, NULL);
+
+	bddIdArray = mdd_id_to_bdd_id_array(mddManager, mddId);
+	for (k = 0; k < array_n(bddIdArray); k++) {
+	  id = array_fetch(int, bddIdArray, k);
+	  if (id == bddId) {
+	    if (latchList[mddId]) {
+	      if (latchList[mddId]->number == 1) {
+		latchList[mddId]->table = st_init_table(st_numcmp, st_numhash);
+		st_insert(latchList[mddId]->table,
+			  (char *)(long)latchList[mddId]->bddId,
+			  (char *)latchList[mddId]->relation);
+	      }
+	      st_insert(latchList[mddId]->table, (char *)bddId,
+			(char *)relation);
+	    } else {
+	      latchList[mddId] = ALLOC(LatchList_t, 1);
+	      latchList[mddId]->bddId = (int) bddId;
+	      latchList[mddId]->relation = relation;
+	      latchList[mddId]->number = 1;
+	      latchList[mddId]->table = NIL(st_table);
+	    }
+	    break;
+	  }
+	}
+	array_free(bddIdArray);
+      }
+    }
+  }
+  st_free_table(intermediateTable);
+
+  i = 0;
+  st_foreach_item_int(nameTable, stGen1, &name, &mddId) {
+    printf("[%d] name = %s mdd = %d\n", i, name, mddId);
+    i++;
+  }
+
+  cluster = NIL(mdd_t);
+  clusteredRelationArray = array_alloc(mdd_t *, 0);
+  while (fgets(line, 512, fin)) {
+    if (line[0] == '\n' || line[0] == '#')
+      continue;
+    if (strncmp(line, "CLUSTER", 7) == 0)
+      cluster = mdd_one(mddManager);
+    else if (strncmp(line, "}", 1) == 0)
+      array_insert_last(mdd_t *, clusteredRelationArray, cluster);
+    else {
+      sscanf(line, "%s %d", nameArray, &id);
+      if (st_lookup_int(nameTable, nameArray, &mddId) == 0)
+	assert(0);
+      if (latchList[mddId]) {
+	if (latchList[mddId]->table) {
+	  bddIdArray = mdd_id_to_bdd_id_array(mddManager, mddId);
+	  assert(id < array_n(bddIdArray));
+	  bddId = (long) array_fetch(int, bddIdArray, id);
+	  if (st_lookup(latchList[mddId]->table, (char *)bddId, &relation)) {
+	    latchList[mddId]->number--;
+	    if (latchList[mddId]->number == 0) {
+	      st_free_table(latchList[mddId]->table);
+	      FREE(latchList[mddId]);
+	      latchList[mddId] = NIL(LatchList_t);
+	    }
+	  } else
+	    assert(0);
+	} else {
+	  relation = latchList[mddId]->relation;
+	  FREE(latchList[mddId]);
+	  latchList[mddId] = NIL(LatchList_t);
+	}
+	newCluster = bdd_and(cluster, relation, 1, 1);
+	mdd_free(cluster);
+	cluster = newCluster;
+      } else
+	assert(0);
+    }
+  }
+
+  for (i = 0; i < nVars; i++) {
+    if (latchList[i]) {
+      if (latchList[i]->table) {
+	st_foreach_item(latchList[i]->table, stGen1, &bddId, &relation) {
+	  cluster = bdd_dup(relation);
+	  array_insert_last(mdd_t *, clusteredRelationArray, cluster);
+	}
+	st_free_table(latchList[i]->table);
+      } else {
+	cluster = bdd_dup(latchList[i]->relation);
+	array_insert_last(mdd_t *, clusteredRelationArray, cluster);
+      }
+      FREE(latchList[i]);
+    }
+  }
+
+  FREE(nsVars);
+  FREE(ns2ps);
+  FREE(resolved);
+  FREE(latchList);
+
+  st_free_table(nameTable);
+  st_free_table(quantifyVarsTable);
+
+  if (arraySmoothVarBddArrayPtr) {
+    ImgMlpGetQuantificationSchedule(mddManager,
+		clusteredRelationArray, psVarBddArray, quantifyVarBddArray,
+		nsVarBddArray, &newRelationArray, &arraySmoothVarBddArray,
+		direction, option);
+    mdd_array_free(clusteredRelationArray);
+    clusteredRelationArray = newRelationArray;
+  } else
+    arraySmoothVarBddArray = NIL(array_t);
+
+  *clusteredRelationArrayPtr = clusteredRelationArray;
+  *arraySmoothVarBddArrayPtr = arraySmoothVarBddArray;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Setups MLP.]
+
+  Description [Setups MLP.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+SetupMlp(mdd_manager *mddManager,
+	 char **xy, int nRows, int nCols, int *rowOrder, int *colOrder,
+	 RcInfo_t *rowInfo, RcInfo_t *colInfo, int *varPos,
+	 array_t *nsVarBddArray, int *nActiveRows, int *nActiveCols,
+	 array_t *nonAppearingVarBddArray,
+	 Img_DirectionType direction, ImgTrmOption_t *option)
+{
+  int		i, j, x, y, s, t;
+  int		row, col, otherCol, nr, nc, index;
+  long		initialTime, finalTime;
+  bdd_t		*relation, *nsVar;
+  array_t	*supportArray, *localVarBddArray;
+  int		support;
+  array_t	**arrayLocalVarBddArray;
+  float		lambda1, lambda2, lambda3;
+  bdd_t		**nsVarArray;
+  int		nVars;
+
+  if (option->mlpVerbosity >= 2)
+    initialTime = util_cpu_time();
+  else
+    initialTime = 0;
+
+  nVars = bdd_num_vars(mddManager);
+  nsVarArray = ALLOC(bdd_t *, nVars);
+  memset(nsVarArray, 0, sizeof(bdd_t *) * nVars);
+  for (i = 0; i < array_n(nsVarBddArray); i++) {
+    nsVar = array_fetch(bdd_t *, nsVarBddArray, i);
+    index = (int)bdd_top_var_id(nsVar);
+    nsVarArray[index] = nsVar;
+  }
+
+  for (i = 0; i < nRows; i++) {
+    relation = rowInfo[i].data.row.func;
+    rowInfo[i].data.row.nsVarBddArray = array_alloc(bdd_t *, 0);
+    supportArray = mdd_get_bdd_support_ids(mddManager, relation);
+    for (j = 0; j < array_n(supportArray); j++) {
+      support = array_fetch(int, supportArray, j);
+      nsVar = nsVarArray[support];
+      if (nsVar) {
+	array_insert_last(bdd_t *, rowInfo[i].data.row.nsVarBddArray, nsVar);
+	if (varPos[support])
+	  xy[i][varPos[support]] = 1;
+	else {
+	  index = (int)bdd_top_var_id(colInfo[0].data.col.var);
+	  if (index == support)
+	    xy[i][varPos[support]] = 1;
+	}
+      } else
+	xy[i][varPos[support]] = 1;
+    }
+    array_free(supportArray);
+  }
+  FREE(nsVarArray);
+
+  for (x = 0; x < nRows; x++) {
+    rowInfo[x].gMin = nCols;
+    rowInfo[x].gMax = -1;
+    rowInfo[x].pos = x;
+    rowInfo[x].prevG = -1;
+    rowInfo[x].nextG = nCols;
+  }
+  for (y = 0; y < nCols; y++) {
+    colInfo[y].gMin = nRows;
+    colInfo[y].gMax = -1;
+    colInfo[y].pos = y;
+    colInfo[y].prevG = -1;
+    colInfo[y].nextG = nRows;
+  }
+
+  for (x = 0; x < nRows; x++) {
+    for (y = 0; y < nCols; y++) {
+      if (xy[x][y]) {
+	if (x < colInfo[y].gMin)
+	  colInfo[y].gMin = x;
+	if (x > colInfo[y].gMax)
+	  colInfo[y].gMax = x;
+	if (y < rowInfo[x].gMin)
+	  rowInfo[x].gMin = y;
+	if (y > rowInfo[x].gMax)
+	  rowInfo[x].gMax = y;
+	rowInfo[x].gNum++;
+	colInfo[y].gNum++;
+      }
+    }
+  }
+
+  nc = nCols;
+  arrayLocalVarBddArray = ALLOC(array_t *, nRows);
+  memset(arrayLocalVarBddArray, 0, sizeof(array_t *) * nRows);
+  for (y = 0; y < nc; y++) {
+    col = colOrder[y];
+    if (colInfo[col].data.col.type == 2 && colInfo[col].gNum == 1) {
+      row = colInfo[col].gMin;
+      rowInfo[row].gNum--;
+      if (rowInfo[row].gNum == 1) {
+	if (rowInfo[row].gMin == col) {
+	  rowInfo[row].gMin = rowInfo[row].gMax;
+	  rowInfo[row].lMin = rowInfo[row].lMax;
+	} else {
+	  rowInfo[row].gMax = rowInfo[row].gMin;
+	  rowInfo[row].lMax = rowInfo[row].lMin;
+	}
+      } else if (rowInfo[row].gNum > 1) {
+	if (rowInfo[row].gMin == col) {
+	  s = colInfo[rowInfo[row].gMin].pos;
+	  t = colInfo[rowInfo[row].gMax].pos;
+	  for (j = s + 1; j <= t; j++) {
+	    otherCol = colOrder[j];
+	    if (xy[row][otherCol]) {
+	      rowInfo[row].gMin = otherCol;
+	      rowInfo[row].lMin = otherCol;
+	      break;
+	    }
+	  }
+	} else if (rowInfo[row].gMax == col) {
+	  s = colInfo[rowInfo[row].gMin].pos;
+	  t = colInfo[rowInfo[row].gMax].pos;
+	  for (j = t - 1; j >= s; j--) {
+	    otherCol = colOrder[j];
+	    if (xy[row][otherCol]) {
+	      rowInfo[row].gMax = otherCol;
+	      rowInfo[row].lMax = otherCol;
+	      break;
+	    }
+	  }
+	}
+      }
+
+      for (j = y; j < nc - 1; j++) {
+	colOrder[j] = colOrder[j + 1];
+	colInfo[colOrder[j]].pos = j;
+      }
+      colOrder[nc - 1] = col;
+      colInfo[col].pos = nc - 1;
+
+      nc--;
+      y--;
+
+      if (!arrayLocalVarBddArray[row])
+	arrayLocalVarBddArray[row] = array_alloc(bdd_t *, 0);
+      array_insert_last(bdd_t *, arrayLocalVarBddArray[row],
+			colInfo[col].data.col.var);
+    }
+  }
+
+  if (direction == Img_Backward_c) {
+    long	lindex;
+    st_table	*unusedNsTable;
+    st_generator *gen;
+
+    unusedNsTable = st_init_table(st_numcmp, st_numhash);
+    for (i = 0; i < array_n(nsVarBddArray); i++) {
+      nsVar = array_fetch(bdd_t *, nsVarBddArray, i);
+      lindex = (long) bdd_top_var_id(nsVar);
+      st_insert(unusedNsTable, (char *)lindex, (char *)nsVar);
+    }
+    for (i = 0; i < nRows; i++) {
+      for (j = 0; j < array_n(rowInfo[i].data.row.nsVarBddArray); j++) {
+	nsVar = array_fetch(bdd_t *, rowInfo[i].data.row.nsVarBddArray, j);
+	lindex = (long) bdd_top_var_id(nsVar);
+	st_delete(unusedNsTable, &lindex, NULL);
+      }
+    }
+    st_foreach_item(unusedNsTable, gen, &lindex, &nsVar) {
+      array_insert_last(bdd_t *, nonAppearingVarBddArray, bdd_dup(nsVar));
+    }
+    st_free_table(unusedNsTable);
+  }
+
+  for (i = 0; i < nRows; i++) {
+    localVarBddArray = arrayLocalVarBddArray[i];
+    if (localVarBddArray) {
+      relation = bdd_smooth(rowInfo[i].data.row.func, localVarBddArray);
+      if (nonAppearingVarBddArray && direction == Img_Backward_c &&
+	  bdd_is_tautology(relation, 1)) {
+	  for (j = 0; j < array_n(rowInfo[i].data.row.nsVarBddArray); j++) {
+	    nsVar = array_fetch(bdd_t *, rowInfo[i].data.row.nsVarBddArray, j);
+	    array_insert_last(bdd_t *, nonAppearingVarBddArray, bdd_dup(nsVar));
+	  }
+      }
+      bdd_free(rowInfo[i].data.row.func);
+      rowInfo[i].data.row.func = relation;
+      UpdateDisapearingPsVars(mddManager, xy, nRows, nCols,
+			rowOrder, colOrder, rowInfo, colInfo,
+			i, option);
+      if (localVarBddArray)
+	array_free(localVarBddArray);
+    }
+  }
+  FREE(arrayLocalVarBddArray);
+
+  for (y = 0; y < nc; y++) {
+    col = colOrder[y];
+    if (colInfo[col].gNum == 0) {
+      if (nonAppearingVarBddArray &&
+	  direction == Img_Forward_c && colInfo[col].data.col.type == 1) {
+	array_insert_last(bdd_t *, nonAppearingVarBddArray,
+			  bdd_dup(colInfo[col].data.col.var));
+      }
+      for (j = y; j < nc - 1; j++) {
+	colOrder[j] = colOrder[j + 1];
+	colInfo[colOrder[j]].pos = j;
+      }
+      colOrder[nc - 1] = col;
+      colInfo[col].pos = nc - 1;
+      nc--;
+      y--;
+    }
+  }
+
+  nr = nRows;
+  for (x = 0; x < nr; x++) {
+    row = rowOrder[x];
+    if (rowInfo[row].gNum == 0) {
+      for (i = x; i < nr - 1; i++) {
+	rowOrder[i] = rowOrder[i + 1];
+	rowInfo[rowOrder[i]].pos = i;
+      }
+      rowOrder[nr - 1] = row;
+      rowInfo[row].pos = nr - 1;
+      nr--;
+      x--;
+    }
+  }
+
+  for (x = 0; x < nr; x++) {
+    row = rowOrder[x];
+    rowInfo[row].lMin = rowInfo[row].gMin;
+    rowInfo[row].lMax = rowInfo[row].gMax;
+    rowInfo[row].lNum = rowInfo[row].gNum;
+    if (nc != nCols && rowInfo[row].nextG == nCols)
+      rowInfo[row].nextG = nc;
+  }
+  for (y = 0; y < nc; y++) {
+    col = colOrder[y];
+    colInfo[col].lMin = colInfo[col].gMin;
+    colInfo[col].lMax = colInfo[col].gMax;
+    colInfo[col].lNum = colInfo[col].gNum;
+    if (nr != nRows && colInfo[col].nextG == nRows)
+      colInfo[col].nextG = nr;
+  }
+  if (option->mlpVerbosity >= 2) {
+    finalTime = util_cpu_time();
+    fprintf(vis_stdout, "time for setup = %10g\n",
+	   (double)(finalTime - initialTime) / 1000.0);
+
+    lambda1 = ComputeLambdaMlp(xy, nCols, nr, nc, rowInfo, colInfo,
+				rowOrder, colOrder, direction, 0, 0, option);
+    lambda2 = ComputeLambdaMlp(xy, nCols, nr, nc, rowInfo, colInfo,
+				rowOrder, colOrder, direction, 1, 0, option);
+    lambda3 = ComputeLambdaMlp(xy, nCols, nr, nc, rowInfo, colInfo,
+				rowOrder, colOrder, direction, 2, 0, option);
+    fprintf(vis_stdout, "Initial Lambda = %f (%f, %f)\n",
+	    lambda1, lambda2, lambda3);
+  }
+
+  if (option->mlpDebug) {
+    CheckMatrix(xy, NIL(SccList_t), nr, nc, rowInfo, colInfo,
+		rowOrder, colOrder, 0, nr - 1, 0, nc - 1, 1);
+  }
+
+  *nActiveRows = nr;
+  *nActiveCols = nc;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs connected component decomposition.]
+
+  Description [Performs connected component decomposition.]
+
+  SideEffects []
+
+******************************************************************************/
+static SccList_t *
+MlpDecomposeScc(mdd_manager *mddManager, char **xy, int nRows,
+		int nActiveRows, int nActiveCols, int *rowOrder, int *colOrder,
+		RcInfo_t *rowInfo, RcInfo_t *colInfo,
+		int clusteredFlag, ImgTrmOption_t *option)
+{
+  int		i, j, x, y, size, nVars;
+  int		startRow, startCol;
+  int		nGroups, nChosen;
+  int		row, col, otherRow;
+  int		s1, t1, s2, t2;
+  char		*rowFlag, *colFlag, *stackFlag;
+  int		*stack;
+  SccList_t	*sccHeadList, *sccTailList, *sccList;
+  array_t	*rowScc, *colScc, *sccArray;
+  long		initialTime, finalTime;
+  int		*newRowOrder, *newColOrder;
+  int		nCurRows, nCurCols;
+
+  if (!option->mlpDecomposeScc) {
+    sccList = ALLOC(SccList_t, 1);
+    sccList->nFuncs = nActiveRows;
+    sccList->nVars = nActiveCols;
+    sccList->startFunc = 0;
+    sccList->lastFunc = nActiveRows - 1;
+    sccList->startVar = 0;
+    sccList->lastVar = nActiveCols - 1;
+    sccList->next = NIL(SccList_t);
+    return(sccList);
+  }
+
+  if (option->mlpVerbosity >= 2)
+    initialTime = util_cpu_time();
+  else
+    initialTime = 0;
+
+  sccHeadList = NIL(SccList_t);
+  sccTailList = NIL(SccList_t);
+
+  rowFlag = ALLOC(char, nRows);
+  memset(rowFlag, 0, sizeof(char) * nRows);
+  nVars = bdd_num_vars(mddManager);
+  colFlag = ALLOC(char, nVars);
+  memset(colFlag, 0, sizeof(char) * nVars);
+  stack = ALLOC(int, nActiveRows);
+  stackFlag = ALLOC(char, nRows);
+  memset(stackFlag, 0, sizeof(char) * nRows);
+
+  startRow = 0;
+  startCol = 0;
+  nGroups = 0;
+  nChosen = 0;
+  while (nChosen < nActiveRows) {
+    rowScc = array_alloc(int, 0);
+    colScc = array_alloc(int, 0);
+
+    size = 0;
+    for (i = startRow; i < nActiveRows; i++) {
+      row = rowOrder[i];
+      if (rowFlag[row] == 0) {
+	stack[0] = row;
+	size = 1;
+	stackFlag[row] = 1;
+	break;
+      }
+    }
+
+    while (size) {
+      if (size + array_n(rowScc) == nRows) {
+	FREE(stack);
+	FREE(stackFlag);
+	FREE(rowFlag);
+	FREE(colFlag);
+	array_free(rowScc);
+	array_free(colScc);
+
+	sccList = ALLOC(SccList_t, 1);
+	sccList->nFuncs = nActiveRows;
+	sccList->nVars = nActiveCols;
+	sccList->startFunc = 0;
+	sccList->lastFunc = nActiveRows - 1;
+	sccList->startVar = 0;
+	sccList->lastVar = nActiveCols - 1;
+	sccList->next = NIL(SccList_t);
+	return(sccList);
+      }
+
+      size--;
+      row = stack[size];
+      x = rowInfo[row].pos;
+      rowFlag[row] = nGroups + 1;
+      array_insert_last(int, rowScc, x);
+      nChosen++;
+      s1 = colInfo[rowInfo[row].gMin].pos;
+      t1 = colInfo[rowInfo[row].gMax].pos;
+      for (y = s1; y <= t1; y++) {
+	col = colOrder[y];
+	if (colInfo[col].gNum == nRows) {
+	  FREE(stack);
+	  FREE(stackFlag);
+	  FREE(rowFlag);
+	  FREE(colFlag);
+	  array_free(rowScc);
+	  array_free(colScc);
+
+	  sccList = ALLOC(SccList_t, 1);
+	  sccList->nFuncs = nActiveRows;
+	  sccList->nVars = nActiveCols;
+	  sccList->startFunc = 0;
+	  sccList->lastFunc = nActiveRows - 1;
+	  sccList->startVar = 0;
+	  sccList->lastVar = nActiveCols - 1;
+	  sccList->next = NIL(SccList_t);
+	  return(sccList);
+	}
+	if (!xy[row][col] || colFlag[col])
+	  continue;
+	colFlag[col] = nGroups + 1;
+	array_insert_last(int, colScc, y);
+	s2 = rowInfo[colInfo[col].gMin].pos;
+	t2 = rowInfo[colInfo[col].gMax].pos;
+	for (i = s2; i <= t2; i++) {
+	  otherRow = rowOrder[i];
+	  if (rowFlag[otherRow] || stackFlag[otherRow])
+	    continue;
+	  if (xy[otherRow][col]) {
+	    stack[size] = otherRow;
+	    size++;
+	    stackFlag[otherRow] = 1;
+	  }
+	}
+      }
+    }
+
+    nGroups++;
+    if (nGroups == 1 && nChosen == nActiveRows) {
+      sccList = ALLOC(SccList_t, 1);
+      sccList->nFuncs = nActiveRows;
+      sccList->nVars = nActiveCols;
+      sccList->startFunc = 0;
+      sccList->lastFunc = nActiveRows - 1;
+      sccList->startVar = 0;
+      sccList->lastVar = nActiveCols - 1;
+      sccList->next = NIL(SccList_t);
+
+      sccHeadList = sccList;
+
+      array_free(rowScc);
+      array_free(colScc);
+      break;
+    }
+
+    /* Move the rows and columns that belong to the current group to top-left */
+    array_sort(rowScc, SccSortRc);
+    array_sort(colScc, SccSortRc);
+    for (i = 0; i < array_n(rowScc); i++) {
+      x = array_fetch(int, rowScc, i);
+      if (x == startRow + i)
+	continue;
+      row = rowOrder[x];
+      for (j = x; j > startRow + i; j--) {
+	rowOrder[j] = rowOrder[j - 1];
+	rowInfo[rowOrder[j]].pos = j;
+      }
+      rowOrder[startRow + i] = row;
+      rowInfo[row].pos = startRow + i;
+    }
+    for (i = 0; i < array_n(colScc); i++) {
+      y = array_fetch(int, colScc, i);
+      if (y == startCol + i)
+	continue;
+      col = colOrder[y];
+      for (j = y; j > startCol + i; j--) {
+	colOrder[j] = colOrder[j - 1];
+	colInfo[colOrder[j]].pos = j;
+      }
+      colOrder[startCol + i] = col;
+      colInfo[col].pos = startCol + i;
+    }
+
+    sccList = ALLOC(SccList_t, 1);
+    sccList->nFuncs = array_n(rowScc);
+    sccList->nVars = array_n(colScc);
+    sccList->startFunc = startRow;
+    sccList->lastFunc = startRow + sccList->nFuncs - 1;
+    sccList->startVar = startCol;
+    sccList->lastVar = startCol + sccList->nVars - 1;
+    sccList->next = NIL(SccList_t);
+    startRow += sccList->nFuncs;
+    startCol += sccList->nVars;
+
+    if (sccTailList)
+      sccTailList->next = sccList;
+    else
+      sccHeadList = sccList;
+    sccTailList = sccList;
+
+    array_free(rowScc);
+    array_free(colScc);
+
+    if (option->mlpDebug) {
+      CheckMatrix(xy, NIL(SccList_t), nActiveRows, nActiveCols,
+		  rowInfo, colInfo, rowOrder, colOrder,
+		  0, nActiveRows - 1, 0, nActiveCols - 1, 1);
+    }
+  }
+
+  FREE(stack);
+  FREE(stackFlag);
+  FREE(rowFlag);
+  FREE(colFlag);
+
+  if (option->mlpSortScc && clusteredFlag == 0) {
+    sccArray = array_alloc(SccList_t *, 0);
+    sccList = sccHeadList;
+    while (sccList) {
+      array_insert_last(SccList_t *, sccArray, sccList);
+      sccList = sccList->next;
+    }
+
+    if (option->mlpSortSccMode == 0) {
+      if (option->mlpSortScc == 1)
+	array_sort(sccArray, SccSortListIncreasingWithArea);
+      else
+	array_sort(sccArray, SccSortListDecreasingWithArea);
+    } else if (option->mlpSortSccMode == 1) {
+      if (option->mlpSortScc == 1)
+	array_sort(sccArray, SccSortListIncreasingWithVars);
+      else
+	array_sort(sccArray, SccSortListDecreasingWithVars);
+    } else {
+      if (option->mlpSortScc == 1)
+	array_sort(sccArray, SccSortListIncreasingWithRatio);
+      else
+	array_sort(sccArray, SccSortListDecreasingWithRatio);
+    }
+
+    newRowOrder = ALLOC(int, nActiveRows);
+    newColOrder = ALLOC(int, nActiveCols);
+
+    nCurRows = 0;
+    nCurCols = 0;
+    sccHeadList = NIL(SccList_t);
+    for (i = 0; i < array_n(sccArray); i++) {
+      sccList = array_fetch(SccList_t *, sccArray, i);
+      if (sccHeadList)
+	sccTailList->next = sccList;
+      else
+	sccHeadList = sccList;
+      sccTailList = sccList;
+      sccList->next = NIL(SccList_t);
+
+      for (j = sccList->startFunc; j <= sccList->lastFunc; j++) {
+	row = rowOrder[j];
+	newRowOrder[nCurRows + j - sccList->startFunc] = rowOrder[j];
+	rowInfo[row].pos = nCurRows + j - sccList->startFunc;
+      }
+      sccList->startFunc = nCurRows;
+      sccList->lastFunc = nCurRows + sccList->nFuncs - 1;
+      nCurRows += sccList->nFuncs;
+
+      for (j = sccList->startVar; j <= sccList->lastVar; j++) {
+	col = colOrder[j];
+	newColOrder[nCurCols + j - sccList->startVar] = colOrder[j];
+	colInfo[col].pos = nCurCols + j - sccList->startVar;
+      }
+      sccList->startVar = nCurCols;
+      sccList->lastVar = nCurCols + sccList->nVars - 1;
+      nCurCols += sccList->nVars;
+    }
+
+    memcpy(rowOrder, newRowOrder, sizeof(int) * nActiveRows);
+    memcpy(colOrder, newColOrder, sizeof(int) * nActiveCols);
+
+    if (option->mlpDebug) {
+      CheckMatrix(xy, NIL(SccList_t), nActiveRows, nActiveCols,
+		  rowInfo, colInfo, rowOrder, colOrder,
+		  0, nActiveRows - 1, 0, nActiveCols - 1, 1);
+    }
+
+    FREE(newRowOrder);
+    FREE(newColOrder);
+    array_free(sccArray);
+  }
+
+  if (option->mlpVerbosity >= 2) {
+    finalTime = util_cpu_time();
+    fprintf(vis_stdout, "time for scc decomposition = %10g (#scc=%d)\n",
+	    (double)(finalTime - initialTime) / 1000.0, nGroups);
+  }
+
+  return(sccHeadList);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sorts connected components with the number of variables.]
+
+  Description [Sorts connected components with the number of variables.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+SccSortListIncreasingWithVars(const void *p1, const void *p2)
+{
+  SccList_t **scc1 = (SccList_t **) p1;
+  SccList_t **scc2 = (SccList_t **) p2;
+  if ((*scc1)->nVars > (*scc2)->nVars)
+    return(1);
+  else if ((*scc1)->nVars < (*scc2)->nVars)
+    return(-1);
+  else
+    return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sorts connected components with the number of variables.]
+
+  Description [Sorts connected components with the number of variables.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+SccSortListDecreasingWithVars(const void *p1, const void *p2)
+{
+  SccList_t **scc1 = (SccList_t **) p1;
+  SccList_t **scc2 = (SccList_t **) p2;
+  if ((*scc1)->nVars < (*scc2)->nVars)
+    return(1);
+  else if ((*scc1)->nVars > (*scc2)->nVars)
+    return(-1);
+  else
+    return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sorts connected components with area.]
+
+  Description [Sorts connected components with area.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+SccSortListIncreasingWithArea(const void *p1, const void *p2)
+{
+  SccList_t **scc1 = (SccList_t **) p1;
+  SccList_t **scc2 = (SccList_t **) p2;
+  int	area1, area2;
+
+  area1 = (*scc1)->nFuncs * (*scc1)->nVars;
+  area2 = (*scc2)->nFuncs * (*scc2)->nVars;
+  if (area1 > area2)
+    return(1);
+  else if (area1 < area2)
+    return(-1);
+  else
+    return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sorts connected components with area.]
+
+  Description [Sorts connected components with area.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+SccSortListDecreasingWithArea(const void *p1, const void *p2)
+{
+  SccList_t **scc1 = (SccList_t **) p1;
+  SccList_t **scc2 = (SccList_t **) p2;
+  int	area1, area2;
+
+  area1 = (*scc1)->nFuncs * (*scc1)->nVars;
+  area2 = (*scc2)->nFuncs * (*scc2)->nVars;
+  if (area1 < area2)
+    return(1);
+  else if (area1 > area2)
+    return(-1);
+  else
+    return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sorts connected components with aspect ratio.]
+
+  Description [Sorts connected components with aspect ratio.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+SccSortListIncreasingWithRatio(const void *p1, const void *p2)
+{
+  SccList_t **scc1 = (SccList_t **) p1;
+  SccList_t **scc2 = (SccList_t **) p2;
+  float	ratio1, ratio2;
+
+  ratio1 = (float)((*scc1)->nVars) / (float)((*scc1)->nFuncs);
+  ratio2 = (float)((*scc2)->nVars) / (float)((*scc2)->nFuncs);
+  if (ratio1 > ratio2)
+    return(1);
+  else if (ratio1 < ratio2)
+    return(-1);
+  else
+    return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sorts connected components with aspect ratio.]
+
+  Description [Sorts connected components with aspect ratio.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+SccSortListDecreasingWithRatio(const void *p1, const void *p2)
+{
+  SccList_t **scc1 = (SccList_t **) p1;
+  SccList_t **scc2 = (SccList_t **) p2;
+  float	ratio1, ratio2;
+
+  ratio1 = (float)((*scc1)->nVars) / (float)((*scc1)->nFuncs);
+  ratio2 = (float)((*scc2)->nVars) / (float)((*scc2)->nFuncs);
+  if (ratio1 < ratio2)
+    return(1);
+  else if (ratio1 > ratio2)
+    return(-1);
+  else
+    return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sorts rows or columns using connected component index.]
+
+  Description [Sorts rows or columns using connected component index.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+SccSortRc(const void * p1, const void * p2)
+{
+  int *n1 = (int *) p1;
+  int *n2 = (int *) p2;
+  if (*n1 > *n2)
+    return(1);
+  else if (*n1 < *n2)
+    return(-1);
+  else
+    return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees list of connected components.]
+
+  Description [Frees list of connected components.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+FreeSccList(SccList_t *sccHeadList)
+{
+  SccList_t	*sccList, *sccNextList;
+
+  sccList = sccHeadList;
+  while (sccList) {
+    sccNextList = sccList->next;
+    FREE(sccList);
+    sccList = sccNextList;
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of connected components in the list.]
+
+  Description [Returns the number of connected components in the list.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+NumOfSccs(SccList_t *sccHeadList)
+{
+  SccList_t	*sccList;
+  int		num = 0;
+
+  sccList = sccHeadList;
+  while (sccList) {
+    num++;
+    sccList = sccList->next;
+  }
+  return(num);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makes dependence matrix block lower triangle.]
+
+  Description [Makes dependence matrix block lower triangle by pivoting
+  rows and columns.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+BlockLowerTriangle(char **xy, int nRows, int nCols,
+		   int nActiveRows, int nActiveCols,
+		   SccList_t *sccList, int *rowOrder, int *colOrder,
+		   RcInfo_t *rowInfo, RcInfo_t *colInfo,
+		   ImgTrmOption_t *option)
+{
+  long		initialTime, finalTime;
+  int		startFunc, lastFunc, startVar, lastVar;
+  int		nLeftRows, nLeftCols;
+  int		saveStartFunc, saveLastFunc;
+  int		saveStartVar, saveLastVar;
+
+  if (sccList) {
+    if (sccList->nFuncs == 1 || sccList->nVars == 1)
+      return;
+    startFunc = sccList->startFunc;
+    lastFunc = sccList->lastFunc;
+    startVar = sccList->startVar;
+    lastVar = sccList->lastVar;
+  } else {
+    startFunc = 0;
+    lastFunc = nActiveRows - 1;
+    startVar = 0;
+    lastVar = nActiveCols - 1;
+  }
+
+  if (option->mlpVerbosity >= 2) {
+    saveStartFunc = startFunc;
+    saveLastFunc = lastFunc;
+    saveStartVar = startVar;
+    saveLastVar = lastVar;
+  } else {
+    /* To remove compiler warnings */
+    saveStartFunc = 0;
+    saveLastFunc = 0;
+    saveStartVar = 0;
+    saveLastVar = 0;
+  }
+
+  if (option->mlpDebug) {
+    CheckMatrix(xy, sccList, nActiveRows, nActiveCols, rowInfo, colInfo,
+		rowOrder, colOrder, startFunc, lastFunc, startVar, lastVar, 1);
+  }
+
+  if (option->mlpCsFirst) {
+    /*
+     * Find singleton columns and move each column to the right of the active
+     * window and move its row to the bottom of the active window.
+     */
+    if (option->mlpSkipCs == 0) {
+      if (option->mlpVerbosity >= 2)
+	initialTime = util_cpu_time();
+      else /* to remove uninitialized variables warning */
+	initialTime = 0;
+      FindAndMoveSingletonCols(xy, sccList, nActiveRows, nActiveCols,
+			       &startFunc, &lastFunc, &startVar, &lastVar,
+			       rowInfo, colInfo, rowOrder, colOrder, option);
+      if (option->mlpVerbosity >= 2) {
+	finalTime = util_cpu_time();
+	fprintf(vis_stdout,
+		"time for col singleton = %10g (#row=%d, #col=%d)\n",
+		(double)(finalTime - initialTime) / 1000.0,
+		saveLastFunc - lastFunc, saveLastVar - lastVar);
+      }
+    }
+
+    /*
+     * Find singleton rows and move each row to the top of the active window
+     * and move its column to the left of the active window.
+     */
+    if (option->mlpSkipRs == 0) {
+      if (option->mlpVerbosity >= 2)
+	initialTime = util_cpu_time();
+      else /* to remove uninitialized variables warning */
+	initialTime = 0;
+      FindAndMoveSingletonRows(xy, sccList, nActiveRows, nActiveCols,
+			       &startFunc, &lastFunc, &startVar, &lastVar,
+			       rowInfo, colInfo, rowOrder, colOrder, option);
+      if (option->mlpVerbosity >= 2) {
+	finalTime = util_cpu_time();
+	fprintf(vis_stdout,
+		"time for row singleton = %10g (#row=%d, #col=%d)\n",
+		(double)(finalTime - initialTime) / 1000.0,
+		startFunc - saveStartFunc, startVar - saveStartVar);
+      }
+    }
+  } else {
+    /*
+     * Find singleton rows and move each row to the top of the active window
+     * and move its column to the left of the active window.
+     */
+    if (option->mlpSkipRs == 0) {
+      if (option->mlpVerbosity >= 2)
+	initialTime = util_cpu_time();
+      else /* to remove uninitialized variables warning */
+	initialTime = 0;
+      FindAndMoveSingletonRows(xy, sccList, nActiveRows, nActiveCols,
+			       &startFunc, &lastFunc, &startVar, &lastVar,
+			       rowInfo, colInfo, rowOrder, colOrder, option);
+      if (option->mlpVerbosity >= 2) {
+	finalTime = util_cpu_time();
+	fprintf(vis_stdout,
+		"time for row singleton = %10g (#row=%d, #col=%d)\n",
+		(double)(finalTime - initialTime) / 1000.0,
+		startFunc - saveStartFunc, startVar - saveStartVar);
+      }
+    }
+
+    /*
+     * Find singleton columns and move each column to the right of the active
+     * window and move its row to the bottom of the active window.
+     */
+    if (option->mlpSkipCs == 0) {
+      if (option->mlpVerbosity >= 2)
+	initialTime = util_cpu_time();
+      else /* to remove uninitialized variables warning */
+	initialTime = 0;
+      FindAndMoveSingletonCols(xy, sccList, nActiveRows, nActiveCols,
+			       &startFunc, &lastFunc, &startVar, &lastVar,
+			       rowInfo, colInfo, rowOrder, colOrder, option);
+      if (option->mlpVerbosity >= 2) {
+	finalTime = util_cpu_time();
+	fprintf(vis_stdout,
+		"time for col singleton = %10g (#row=%d, #col=%d)\n",
+		(double)(finalTime - initialTime) / 1000.0,
+		saveLastFunc - lastFunc, saveLastVar - lastVar);
+      }
+    }
+  }
+
+  if (option->mlpVerbosity >= 2) {
+    initialTime = util_cpu_time();
+    nLeftRows = lastFunc - startFunc + 1;
+    nLeftCols = lastVar - startVar + 1;
+  } else {
+    /* To remove compiler warnings */
+    initialTime = 0;
+    nLeftRows = 0;
+    nLeftCols = 0;
+  }
+
+  if (option->mlpRowBased) {
+    MoveBestRows(xy, sccList, nActiveRows, nActiveCols, rowOrder, colOrder,
+		 rowInfo, colInfo,
+		 startFunc, lastFunc, startVar, lastVar, option);
+  } else {
+    MoveBestCols(xy, sccList, nRows, nCols, nActiveRows, nActiveCols,
+		 rowOrder, colOrder, rowInfo, colInfo,
+		 startFunc, lastFunc, startVar, lastVar, option);
+  }
+
+  if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
+    PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
+		rowInfo, colInfo, startFunc, lastFunc, startVar, lastVar);
+  }
+
+  if (option->mlpVerbosity >= 2) {
+    finalTime = util_cpu_time();
+    if (option->mlpRowBased) {
+      fprintf(vis_stdout, "time for best row = %10g (#row=%d, #col=%d)\n",
+		(double)(finalTime - initialTime) / 1000.0,
+		nLeftRows - lastFunc + startFunc - 1,
+		nLeftCols - lastVar + startVar - 1);
+    } else {
+      fprintf(vis_stdout, "time for best col = %10g (#row=%d, #col=%d)\n",
+		(double)(finalTime - initialTime) / 1000.0,
+		nLeftRows - lastFunc + startFunc - 1,
+		nLeftCols - lastVar + startVar - 1);
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds and moves the best row iteratively.]
+
+  Description [Finds and moves the best row iteratively.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+MoveBestRows(char **xy, SccList_t *sccList, int nRows, int nCols,
+		int *rowOrder, int *colOrder,
+		RcInfo_t *rowInfo, RcInfo_t *colInfo,
+		int startFunc, int lastFunc, int startVar, int lastVar,
+		ImgTrmOption_t *option)
+{
+  int		x, y, s1, t1, s2, t2;
+  int		min, bestX;
+  int		row, col, lastCol, moveRow, bestRow;
+  int		regionX, overlap, nOverlaps, nMore;
+
+  regionX = 0;
+  bestX = -1;
+  while (startFunc < lastFunc && startVar < lastVar) {
+    min = nCols;
+    overlap = 0;
+    for (x = startFunc; x <= lastFunc; x++) {
+      row = rowOrder[x];
+      assert(rowInfo[row].lNum);
+      if (overlap) {
+	if (rowInfo[row].lNum < min) {
+	  s1 = colInfo[rowInfo[row].gMin].pos;
+	  if (s1 < regionX)
+	    s1 = regionX;
+	  nOverlaps = 0;
+	  for (y = s1; y < startVar; y++) {
+	    col = colOrder[y];
+	    if (xy[row][col]) {
+	      nOverlaps++;
+	      break;
+	    }
+	  }
+
+	  if (nOverlaps) {
+	    bestX = x;
+	    min = rowInfo[row].lNum;
+	  }
+	}
+      } else {
+	s1 = colInfo[rowInfo[row].gMin].pos;
+	if (s1 < regionX)
+	  s1 = regionX;
+	nOverlaps = 0;
+	for (y = s1; y < startVar; y++) {
+	  col = colOrder[y];
+	  if (xy[row][col]) {
+	    nOverlaps++;
+	    break;
+	  }
+	}
+
+	if (nOverlaps) {
+	  bestX = x;
+	  min = rowInfo[row].lNum;
+	  overlap = 1;
+	} else {
+	  if (rowInfo[row].lNum < min) {
+	    bestX = x;
+	    min = rowInfo[row].lNum;
+	  }
+	}
+      }
+    }
+
+    assert(bestX != -1);
+    if (!overlap)
+      regionX = startFunc;
+
+    row = rowOrder[bestX];
+    while (1) {
+      bestRow = row;
+      s1 = colInfo[rowInfo[row].lMin].pos;
+      t1 = colInfo[rowInfo[row].lMax].pos;
+      min = rowInfo[row].lNum;
+      for (x = startFunc; x <= lastFunc; x++) {
+	moveRow = rowOrder[x];
+	if (moveRow == row)
+	  continue;
+	s2 = colInfo[rowInfo[moveRow].lMin].pos;
+	t2 = colInfo[rowInfo[moveRow].lMax].pos;
+	if (s2 < s1 || t2 > t1)
+	  continue;
+	nMore = 0;
+	nOverlaps = 0;
+	for (y = s2; y <= t2; y++) {
+	  col = colOrder[y];
+	  if (xy[row][col]) {
+	    if (xy[moveRow][col])
+	      nOverlaps++;
+	  } else {
+	    if (xy[moveRow][col]) {
+	      nMore++;
+	      break;
+	    }
+	  }
+	}
+	if (nMore || nOverlaps == 0 || nOverlaps >= min)
+	  continue;
+	min = nOverlaps;
+	bestRow = moveRow;
+      }
+
+      lastCol = -1;
+      s1 = colInfo[rowInfo[bestRow].lMin].pos;
+      t1 = colInfo[rowInfo[bestRow].lMax].pos;
+      for (y = s1; y <= t1; y++) {
+	col = colOrder[y];
+	if (xy[bestRow][col]) {
+	  if (option->mlpVerbosity >= 3) {
+	    fprintf(vis_stdout, "[%d] Moving Col %d(%d) to %d (best row)\n",
+		    nMoves, y, col, startVar);
+	    fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
+		    startFunc, lastFunc, startVar, lastVar);
+	  }
+	  MoveColToLeft(xy, y, startFunc, lastFunc, startVar, lastVar,
+			  rowInfo, colInfo, rowOrder, colOrder,
+			  NIL(RcListInfo_t), option->mlpMethod);
+	  startVar++;
+	  lastCol = col;
+
+	  if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
+	    PrintMatrix(xy, nRows, nCols, rowOrder, colOrder, rowInfo, colInfo,
+			startFunc, lastFunc, startVar, lastVar);
+	  }
+	  if (option->mlpDebug) {
+	    CheckMatrix(xy, sccList, nRows, nCols, rowInfo, colInfo,
+			rowOrder, colOrder,
+			startFunc, lastFunc, startVar, lastVar, 1);
+	  }
+	}
+      }
+
+      if (lastCol != -1) {
+	s2 = rowInfo[colInfo[lastCol].lMin].pos;
+	t2 = rowInfo[colInfo[lastCol].lMax].pos;
+	for (x = s2; x <= t2; x++) {
+	  moveRow = rowOrder[x];
+	  if (xy[moveRow][lastCol] && rowInfo[moveRow].lNum == 0) {
+	    if (option->mlpVerbosity >= 3) {
+	      fprintf(vis_stdout, "[%d] Moving row %d(%d) to %d (best row)\n",
+			nMoves, x, moveRow, startFunc);
+	      fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
+			startFunc, lastFunc, startVar, lastVar);
+	    }
+	    MoveRowToTop(xy, x, startFunc, lastFunc, startVar, lastVar,
+			 rowInfo, colInfo, rowOrder, colOrder,
+			 NIL(RcListInfo_t), option->mlpMethod);
+	    startFunc++;
+	    if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
+	      PrintMatrix(xy, nRows, nCols, rowOrder, colOrder,
+			  rowInfo, colInfo,
+			  startFunc, lastFunc, startVar, lastVar);
+	    }
+	    if (option->mlpDebug) {
+	      CheckMatrix(xy, sccList, nRows, nCols, rowInfo, colInfo,
+			  rowOrder, colOrder,
+			  startFunc, lastFunc, startVar, lastVar, 1);
+	    }
+	  }
+	}
+      }
+
+      if (row == bestRow)
+	break;
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds and moves the best column iteratively.]
+
+  Description [Finds and moves the best column iteratively.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+MoveBestCols(char **xy, SccList_t *sccList, int nRows, int nCols,
+		int nActiveRows, int nActiveCols,
+		int *rowOrder, int *colOrder,
+		RcInfo_t *rowInfo, RcInfo_t *colInfo,
+		int startFunc, int lastFunc, int startVar, int lastVar,
+		ImgTrmOption_t *option)
+{
+  int		x, y, i, s1, t1, s2, t2;
+  char		*rowFlag, *colFlag;
+  int		min, bestY, bestCol;
+  int		row, col, tie, newTies, intersect = 0, maxIntersect, maxLength;
+  int		minX, maxX;
+  RcListInfo_t	*sortedRows, *sortedCols;
+  RcList_t	*cur, *list;
+
+  if (option->mlpSortedRows) {
+    sortedRows = SortedListAlloc();
+    for (x = startFunc; x <= lastFunc; x++) {
+      row = rowOrder[x];
+      SortedListInsert(sortedRows, row, row, rowInfo, 3);
+    }
+
+    if (option->mlpSortedCols)
+      sortedCols = SortedListAlloc();
+    else
+      sortedCols = NIL(RcListInfo_t);
+
+    if (option->mlpDebug)
+      CheckSortedList(sortedRows, rowInfo, 3);
+  } else {
+    sortedRows = NIL(RcListInfo_t);
+    sortedCols = NIL(RcListInfo_t);
+  }
+
+  rowFlag = ALLOC(char, nRows);
+  if (sortedCols)
+    memset(rowFlag, 0, sizeof(char) * nRows);
+  colFlag = ALLOC(char, nCols);
+  while (startFunc != lastFunc && startVar != lastVar) {
+    min = nActiveCols;
+    if (!sortedCols)
+      memset(rowFlag, 0, sizeof(char) * nRows);
+    tie = 0;
+    minX = lastFunc;
+    maxX = startFunc;
+    if (sortedCols) {
+      bestY = nActiveCols;
+      bestCol = nActiveCols;
+      if (sortedCols->num == 0) {
+	if (sortedRows) {
+	  cur = sortedRows->head;
+	  while (cur) {
+	    row = cur->index;
+	    x = rowInfo[row].pos;
+	    if (rowInfo[row].lNum == 0) {
+	      cur = cur->next;
+	      continue;
+	    }
+	    if (rowInfo[row].lNum > min)
+	      break;
+	    rowFlag[row] = 1;
+	    s1 = colInfo[rowInfo[row].lMin].pos;
+	    t1 = colInfo[rowInfo[row].lMax].pos;
+	    for (y = s1; y <= t1; y++) {
+	      col = colOrder[y];
+	      if (!xy[row][col])
+		continue;
+	      if (st_lookup(sortedCols->table, (char *)(long)col, &list)) {
+		list->otherIndex++;
+		SortedListMove(sortedCols, colInfo, col, 4);
+	      } else
+		SortedListInsert(sortedCols, col, 1, colInfo, 4);
+	    }
+	    min = rowInfo[row].lNum;
+	    tie++;
+	    cur = cur->next;
+	  }
+	}
+      } else {
+	if (sortedRows) {
+	  cur = sortedRows->head;
+	  while (cur) {
+	    row = cur->index;
+	    x = rowInfo[row].pos;
+	    if (rowInfo[row].lNum == 0) {
+	      cur = cur->next;
+	      continue;
+	    }
+	    if (rowInfo[row].lNum > min)
+	      break;
+	    min = rowInfo[row].lNum;
+	    tie++;
+	    cur = cur->next;
+	  }
+	}
+      }
+
+      if (option->mlpDebug) {
+	if (sortedRows)
+	  CheckSortedList(sortedRows, rowInfo, 3);
+	CheckSortedList(sortedCols, colInfo, 4);
+      }
+
+      bestCol = sortedCols->head->index;
+      bestY = colInfo[bestCol].pos;
+      assert(bestY >= startVar && bestY <= lastVar);
+      maxLength = colInfo[bestCol].lNum;
+      intersect = sortedCols->head->otherIndex;
+    } else {
+      if (sortedRows) {
+	if (option->mlpDebug)
+	  CheckSortedList(sortedRows, rowInfo, 3);
+
+	cur = sortedRows->head;
+	while (cur) {
+	  row = cur->index;
+	  x = rowInfo[row].pos;
+	  if (rowInfo[row].lNum == 0) {
+	    cur = cur->next;
+	    continue;
+	  }
+	  if (rowInfo[row].lNum < min) {
+	    min = rowInfo[row].lNum;
+	    tie = 1;
+	    memset(rowFlag, 0, sizeof(char) * nRows);
+	    rowFlag[x] = 1;
+	    minX = x;
+	    maxX = x;
+	  } else if (rowInfo[row].lNum == min) {
+	    tie++;
+	    rowFlag[x] = 1;
+	    if (x < minX)
+	      minX = x;
+	    if (x > maxX)
+	      maxX = x;
+	  } else
+	    break;
+	  cur = cur->next;
+	}
+      } else {
+	for (x = startFunc; x <= lastFunc; x++) {
+	  row = rowOrder[x];
+	  if (rowInfo[row].lNum == 0)
+	    continue;
+	  if (rowInfo[row].lNum < min) {
+	    min = rowInfo[row].lNum;
+	    tie = 1;
+	    memset(rowFlag, 0, sizeof(char) * nRows);
+	    rowFlag[x] = 1;
+	    minX = x;
+	    maxX = x;
+	  } else if (rowInfo[row].lNum == min) {
+	    tie++;
+	    rowFlag[x] = 1;
+	    maxX = x;
+	  }
+	}
+      }
+
+      if (tie == 0)
+	break;
+
+      maxLength = 0;
+      maxIntersect = 0;
+      memset(colFlag, 0, sizeof(char) * nCols);
+      bestY = nActiveCols;
+      bestCol = nActiveCols;
+      for (x = minX; x <= maxX; x++) {
+	if (!rowFlag[x])
+	  continue;
+	row = rowOrder[x];
+	s1 = colInfo[rowInfo[row].lMin].pos;
+	t1 = colInfo[rowInfo[row].lMax].pos;
+	for (y = s1; y <= t1; y++) {
+	  col = colOrder[y];
+	  if (xy[row][col]) {
+	    if (colFlag[y])
+	      continue;
+	    colFlag[y] = 1;
+	    intersect = 0;
+	    s2 = rowInfo[colInfo[col].lMin].pos;
+	    t2 = rowInfo[colInfo[col].lMax].pos;
+	    if (s2 < minX)
+	      s2 = minX;
+	    if (t2 > maxX)
+	      t2 = maxX;
+	    for (i = s2; i <= t2; i++) {
+	      if (xy[rowOrder[i]][col]) {
+		if (rowFlag[i])
+		  intersect++;
+	      }
+	    }
+	    if (intersect > maxIntersect ||
+		(intersect == maxIntersect && colInfo[col].lNum > maxLength) ||
+		(intersect == maxIntersect && colInfo[col].lNum == maxLength &&
+		  y < bestY)) {
+	      bestY = y;
+	      bestCol = colOrder[bestY];
+	      maxLength = colInfo[bestCol].lNum;
+	      maxIntersect = intersect;
+	    }
+	  }
+	}
+      }
+    }
+
+    if (option->mlpVerbosity >= 3) {
+      fprintf(vis_stdout,
+"[%d] Moving Col %d(%d) to %d (best col, min=%d, intersect=%d, length=%d)\n",
+	     nMoves, bestY, bestCol, startVar, min, intersect, maxLength);
+      fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
+	     startFunc, lastFunc, startVar, lastVar);
+    }
+    MoveColToLeft(xy, bestY, startFunc, lastFunc, startVar, lastVar,
+		  rowInfo, colInfo, rowOrder, colOrder,
+		  NIL(RcListInfo_t), option->mlpMethod);
+    startVar++;
+    if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
+      PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
+		  rowInfo, colInfo, startFunc, lastFunc, startVar, lastVar);
+    }
+    if (option->mlpDebug) {
+      CheckMatrix(xy, sccList, nActiveRows, nActiveCols, rowInfo, colInfo,
+		  rowOrder, colOrder,
+		  startFunc, lastFunc, startVar, lastVar, 1);
+    }
+
+    if (sortedCols)
+      SortedListDelete(sortedCols, bestCol);
+
+    if (sortedRows) {
+      if (min == 1) {
+	cur = sortedRows->head;
+	while (cur) {
+	  row = cur->index;
+	  if (rowInfo[row].lNum > min)
+	    break;
+	  else if (rowInfo[row].lNum == min) {
+	    cur = cur->next;
+	    continue;
+	  }
+	  x = rowInfo[row].pos;
+	  if (option->mlpVerbosity >= 3) {
+	    fprintf(vis_stdout, "[%d] Moving row %d(%d) to %d (empty row)\n",
+		   nMoves, x, row, startFunc);
+	    fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
+		   startFunc, lastFunc, startVar, lastVar);
+	  }
+	  MoveRowToTop(xy, x, startFunc, lastFunc, startVar, lastVar,
+		       rowInfo, colInfo, rowOrder, colOrder,
+		       NIL(RcListInfo_t), option->mlpMethod);
+	  startFunc++;
+	  if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
+	    PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
+			rowInfo, colInfo,
+			startFunc, lastFunc, startVar, lastVar);
+	  }
+	  if (option->mlpDebug) {
+	    CheckMatrix(xy, sccList, nActiveRows, nActiveCols,
+			rowInfo, colInfo, rowOrder, colOrder,
+			startFunc, lastFunc, startVar, lastVar, 1);
+	  }
+	  cur = cur->next;
+	  SortedListDelete(sortedRows, row);
+	}
+      }
+
+      /* Update sortedRows */
+      /*
+      cur = sortedRows->head;
+      while (cur) {
+	row = cur->index;
+	if (xy[row][bestCol]) {
+	  assert(rowInfo[row].lNum > 0);
+	  SortedListMove(sortedRows, rowInfo, row, 3);
+	}
+	cur = cur->next;
+      }
+      if (option->mlpDebug)
+	CheckSortedList(sortedRows, rowInfo, 3);
+      */
+      s1 = rowInfo[colInfo[bestCol].lMin].pos;
+      t1 = rowInfo[colInfo[bestCol].lMax].pos;
+      cur = sortedRows->head;
+      while (cur) {
+	row = cur->index;
+	x = rowInfo[row].pos;
+	if (x < s1) {
+	  cur = cur->next;
+	  continue;
+	}
+	if (xy[row][bestCol] && rowInfo[row].lNum > 0) {
+	  SortedListMove(sortedRows, rowInfo, row, 3);
+	  if (sortedCols && min == 1) {
+	    if (rowInfo[row].lNum == 1 && rowFlag[row] == 0) {
+	      rowFlag[row] = 1;
+	      s2 = colInfo[rowInfo[row].lMin].pos;
+	      t2 = colInfo[rowInfo[row].lMax].pos;
+	      for (y = s2; y <= t2; y++) {
+		col = colOrder[y];
+		if (!xy[row][col])
+		  continue;
+		if (st_lookup(sortedCols->table, (char *)(long)col, &list)) {
+		  list->otherIndex++;
+		  SortedListMove(sortedCols, colInfo, col, 4);
+		} else
+		  SortedListInsert(sortedCols, col, 1, colInfo, 4);
+	      }
+	    }
+	  }
+	}
+	cur = cur->next;
+      }
+
+      newTies = 0;
+      if (sortedCols && min > 1) {
+	min = nActiveCols;
+	cur = sortedRows->head;
+	while (cur) {
+	  row = cur->index;
+	  x = rowInfo[row].pos;
+	  if (rowInfo[row].lNum == 0) {
+	    cur = cur->next;
+	    continue;
+	  }
+	  if (rowInfo[row].lNum > min)
+	    break;
+	  min = rowInfo[row].lNum;
+	  newTies++;
+	  cur = cur->next;
+	}
+
+	if (newTies != tie) {
+	  SortedListFree(sortedCols);
+	  sortedCols = SortedListAlloc();
+
+	  cur = sortedRows->head;
+	  while (cur) {
+	    row = cur->index;
+	    x = rowInfo[row].pos;
+	    if (rowInfo[row].lNum == 0) {
+	      cur = cur->next;
+	      continue;
+	    }
+	    if (rowInfo[row].lNum > min)
+	      break;
+	    rowFlag[row] = 1;
+	    s1 = colInfo[rowInfo[row].lMin].pos;
+	    t1 = colInfo[rowInfo[row].lMax].pos;
+	    for (y = s1; y <= t1; y++) {
+	      col = colOrder[y];
+	      if (!xy[row][col])
+		continue;
+	      if (st_lookup(sortedCols->table, (char *)(long)col, &list)) {
+		list->otherIndex++;
+		SortedListMove(sortedCols, colInfo, col, 4);
+	      } else
+		SortedListInsert(sortedCols, col, 1, colInfo, 4);
+	    }
+	    cur = cur->next;
+	  }
+	}
+      }
+    } else {
+      if (min == 1) {
+	s1 = rowInfo[colInfo[bestCol].lMin].pos;
+	t1 = rowInfo[colInfo[bestCol].lMax].pos;
+	for (x = s1; x <= t1; x++) {
+	  row = rowOrder[x];
+	  if (xy[row][bestCol] && rowInfo[row].lNum == 0) {
+	    if (option->mlpVerbosity >= 3) {
+	      fprintf(vis_stdout, "[%d] Moving row %d(%d) to %d (empty row)\n",
+		     nMoves, x, row, startFunc);
+	      fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
+		     startFunc, lastFunc, startVar, lastVar);
+	    }
+	    MoveRowToTop(xy, x, startFunc, lastFunc, startVar, lastVar,
+			 rowInfo, colInfo, rowOrder, colOrder,
+			 NIL(RcListInfo_t), option->mlpMethod);
+	    startFunc++;
+	    if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
+	      PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
+			  rowInfo, colInfo,
+			  startFunc, lastFunc, startVar, lastVar);
+	    }
+	    if (option->mlpDebug) {
+	      CheckMatrix(xy, sccList, nActiveRows, nActiveCols,
+			  rowInfo, colInfo, rowOrder, colOrder,
+			  startFunc, lastFunc, startVar, lastVar, 1);
+	    }
+	  }
+	}
+      }
+    }
+  }
+
+  if (sortedRows) {
+    cur = sortedRows->head;
+    while (cur) {
+      row = cur->index;
+      x = rowInfo[row].pos;
+      if (option->mlpVerbosity >= 3) {
+	fprintf(vis_stdout, "[%d] Moving row %d(%d) to %d (bandwidth)\n",
+	       nMoves, x, row, startFunc);
+	fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
+	       startFunc, lastFunc, startVar, lastVar);
+      }
+      MoveRowToTop(xy, x, startFunc, lastFunc, startVar, lastVar,
+		   rowInfo, colInfo, rowOrder, colOrder,
+		   NIL(RcListInfo_t), option->mlpMethod);
+      startFunc++;
+      if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
+	PrintMatrix(xy, nActiveRows, nActiveCols, rowOrder, colOrder,
+		    rowInfo, colInfo,
+		    startFunc, lastFunc, startVar, lastVar);
+      }
+      if (option->mlpDebug) {
+	CheckMatrix(xy, sccList, nActiveRows, nActiveCols, rowInfo, colInfo,
+		    rowOrder, colOrder,
+		    startFunc, lastFunc, startVar, lastVar, 1);
+      }
+      cur = cur->next;
+      SortedListDelete(sortedRows, row);
+    }
+    SortedListFree(sortedRows);
+  }
+
+  if (sortedCols) {
+    cur = sortedCols->head;
+    while (cur) {
+      col = cur->index;
+      cur = cur->next;
+      SortedListDelete(sortedCols, col);
+    }
+    SortedListFree(sortedCols);
+  }
+
+  FREE(rowFlag);
+  FREE(colFlag);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs a postprocessing after MLP.]
+
+  Description [Performs a postprocessing after MLP. Tries to exchange adjacent
+  two rows if the exchange lowers variable lifetime.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+MlpPostProcess(char **xy, SccList_t *sccList, int nVars, int nRows, int nCols,
+		RcInfo_t *rowInfo, RcInfo_t *colInfo,
+		int *rowOrder, int *colOrder,
+		Img_DirectionType direction, ImgTrmOption_t *option)
+{
+  int		x, y, i, j, r, c, row, col, otherRow, otherCol, tmpRow, tmpCol;
+  int		nqv1, nqv2, niv1, niv2, benefit1, benefit2;
+  int		s1, t1, s2, t2, s3, t3, s4, t4;
+  long		initialTime, finalTime;
+  int		nSwaps;
+  float		lambda1, lambda2, lambda3;
+  int		startFunc, lastFunc;
+
+  if (sccList) {
+    startFunc = sccList->startFunc;
+    lastFunc = sccList->lastFunc;
+  } else {
+    startFunc = 0;
+    lastFunc = nRows - 1;
+  }
+
+  if (option->mlpVerbosity)
+    initialTime = util_cpu_time();
+  else
+    initialTime = 0;
+
+  nSwaps = 0;
+  for (x = lastFunc - 1; x >= startFunc; x--) {
+    row = rowOrder[x];
+    if (rowInfo[row].data.row.nsVarBddArray)
+      niv1 = array_n(rowInfo[row].data.row.nsVarBddArray);
+    else
+      niv1 = 0;
+
+    col = rowInfo[row].gMin;
+    if (rowInfo[row].gNum == 1 &&
+	colInfo[col].gNum > 1 && colInfo[col].gMin == x) {
+      t1 = rowInfo[colInfo[col].gMax].pos;
+      for (i = x + 1; i <= t1; i++) {
+	otherRow = rowOrder[i];
+	if (xy[otherRow][col]) {
+	  if (x < i - 1) {
+	    for (j = x; j < i - 1; j++) {
+	      rowOrder[j] = rowOrder[j + 1];
+	      rowInfo[rowOrder[j]].pos = j;
+	    }
+	    rowOrder[i - 1] = row;
+	    rowInfo[row].pos = i - 1;
+
+	    if (rowInfo[otherRow].gNum == 1)
+	      break;
+
+	    s2 = colInfo[rowInfo[otherRow].gMin].pos;
+	    t2 = colInfo[rowInfo[otherRow].gMax].pos;
+	    for (j = t2; j >= s2; j--) {
+	      otherCol = colOrder[j];
+	      if (colInfo[otherCol].gMin == otherRow)
+		t2 = j - 1;
+	      else
+		break;
+	    }
+
+	    s3 = rowInfo[colInfo[col].gMin].pos;
+	    t3 = rowInfo[colInfo[col].gMax].pos;
+	    for (r = s3; r <= t3; r++) {
+	      tmpRow = rowOrder[r];
+	      if (col == rowInfo[tmpRow].gMin) {
+		s4 = colInfo[rowInfo[tmpRow].gMin].pos;
+		t4 = colInfo[rowInfo[tmpRow].gMax].pos;
+		if (t4 > t2)
+		  t4 = t2;
+		for (c = s4 + 1; c <= t4; c++) {
+		  tmpCol = colOrder[c];
+		  if (xy[tmpRow][tmpCol]) {
+		    rowInfo[tmpRow].gMin = tmpCol;
+		    rowInfo[tmpRow].lMin = tmpCol;
+		    break;
+		  }
+		}
+	      }
+
+	      if (xy[tmpRow][col] && t2 >= colInfo[rowInfo[tmpRow].gMax].pos) {
+		rowInfo[tmpRow].gMax = col;
+		rowInfo[tmpRow].lMax = col;
+	      }
+	    }
+
+	    y = colInfo[col].pos;
+	    if (y < t2) {
+	      for (j = y; j < t2; j++) {
+		colOrder[j] = colOrder[j + 1];
+		colInfo[colOrder[j]].pos = j;
+	      }
+	      colOrder[t2] = col;
+	      colInfo[col].pos = t2;
+	    }
+
+	    if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
+	      PrintMatrix(xy, nRows, nCols, rowOrder, colOrder,
+			  rowInfo, colInfo, 0, nRows - 1, 0, nCols - 1);
+	    }
+	    if (option->mlpDebug) {
+	      CheckMatrix(xy, sccList, nRows, nCols, rowInfo, colInfo,
+			  rowOrder, colOrder, 0, nRows - 1, 0, nCols - 1, 1);
+	    }
+
+	    nSwaps++;
+	  }
+	  break;
+	}
+      }
+      continue;
+    }
+
+    for (i = x + 1; i <= lastFunc; i++) {
+      otherRow = rowOrder[i];
+      if (rowInfo[otherRow].data.row.nsVarBddArray)
+	niv2 = array_n(rowInfo[otherRow].data.row.nsVarBddArray);
+      else
+	niv2 = 0;
+
+      nqv1 = 0;
+      s1 = colInfo[rowInfo[row].gMin].pos;
+      t1 = colInfo[rowInfo[row].gMax].pos;
+      for (y = t1; y >= s1; y--) {
+	col = colOrder[y];
+	if (colInfo[col].gMin == row) {
+	  if (!xy[otherRow][col])
+	    nqv1++;
+	} else
+	  break;
+      }
+      benefit1 = nqv1 - niv1;
+
+      nqv2 = 0;
+      s2 = colInfo[rowInfo[otherRow].gMin].pos;
+      t2 = colInfo[rowInfo[otherRow].gMax].pos;
+      for (y = t2; y >= s2; y--) {
+	col = colOrder[y];
+	if (colInfo[col].gMin == otherRow)
+	  nqv2++;
+	else
+	  break;
+      }
+      benefit2 = nqv2 - niv2;
+
+      if (benefit1 > benefit2 ||
+	  (benefit1 == benefit2 &&
+	   (rowInfo[row].gNum > rowInfo[otherRow].gNum ||
+	    (rowInfo[row].gNum == rowInfo[otherRow].gNum &&
+	     bdd_size(rowInfo[row].data.row.func) <
+	     bdd_size(rowInfo[otherRow].data.row.func))))) {
+	nqv1 = 0;
+	for (y = t1; y >= s1; y--) {
+	  if (t1 > t2)
+	    break;
+	  col = colOrder[y];
+	  if (colInfo[col].gMin == row) {
+	    if (!xy[otherRow][col]) {
+	      s3 = rowInfo[colInfo[col].gMin].pos;
+	      t3 = rowInfo[colInfo[col].gMax].pos;
+	      for (r = s3; r <= t3; r++) {
+		tmpRow = rowOrder[r];
+		if (col == rowInfo[tmpRow].gMin) {
+		  s4 = colInfo[rowInfo[tmpRow].gMin].pos;
+		  t4 = colInfo[rowInfo[tmpRow].gMax].pos;
+		  if (t4 > t2 - nqv1)
+		    t4 = t2 - nqv1;
+		  for (c = s4 + 1; c <= t4; c++) {
+		    tmpCol = colOrder[c];
+		    if (xy[tmpRow][tmpCol] && colInfo[tmpCol].gMin != row) {
+		      rowInfo[tmpRow].gMin = tmpCol;
+		      rowInfo[tmpRow].lMin = tmpCol;
+		      break;
+		    }
+		  }
+		}
+
+		if (nqv1 == 0 && xy[tmpRow][col] &&
+		    t2 - nqv1 >= colInfo[rowInfo[tmpRow].gMax].pos) {
+		  rowInfo[tmpRow].gMax = col;
+		  rowInfo[tmpRow].lMax = col;
+		}
+	      }
+
+	      for (j = y; j < t2 - nqv1; j++) {
+		colOrder[j] = colOrder[j + 1];
+		colInfo[colOrder[j]].pos = j;
+	      }
+	      colOrder[t2 - nqv1] = col;
+	      colInfo[col].pos = t2 - nqv1;
+	      nqv1++;
+	    } else {
+	      colInfo[col].gMin = otherRow;
+	      colInfo[col].lMin = otherRow;
+	      if (colInfo[col].gMax == otherRow) {
+		colInfo[col].gMax = row;
+		colInfo[col].lMax = row;
+	      }
+	    }
+	  } else {
+	    if (colInfo[col].gMax == otherRow && xy[row][col]) {
+	      colInfo[col].gMax = row;
+	      colInfo[col].lMax = row;
+	    }
+	  }
+	}
+
+	rowOrder[i - 1] = otherRow;
+	rowInfo[otherRow].pos = i - 1;
+	rowOrder[i] = row;
+	rowInfo[row].pos = i;
+	nSwaps++;
+
+	if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
+	  PrintMatrix(xy, nRows, nCols, rowOrder, colOrder,
+			rowInfo, colInfo, 0, nRows - 1, 0, nCols - 1);
+	}
+	if (option->mlpDebug) {
+	  CheckMatrix(xy, sccList, nRows, nCols, rowInfo, colInfo,
+			rowOrder, colOrder, 0, nRows - 1, 0, nCols - 1, 1);
+	}
+      } else
+	break;
+    }
+  }
+
+  if (option->mlpVerbosity) {
+    if (option->mlpVerbosity >= 2) {
+      lambda1 = ComputeLambdaMlp(xy, nVars, nRows, nCols, rowInfo, colInfo,
+				 rowOrder, colOrder, direction, 0, 0, option);
+      lambda2 = ComputeLambdaMlp(xy, nVars, nRows, nCols, rowInfo, colInfo,
+				 rowOrder, colOrder, direction, 1, 0, option);
+      lambda3 = ComputeLambdaMlp(xy, nVars, nRows, nCols, rowInfo, colInfo,
+				 rowOrder, colOrder, direction, 2, 0, option);
+      fprintf(vis_stdout, "Optimized Lambda = %f (%f, %f)\n",
+	      lambda1, lambda2, lambda3);
+    }
+    finalTime = util_cpu_time();
+    fprintf(vis_stdout, "time for postprocessing = %10g (#swap=%d)\n",
+	   (double)(finalTime - initialTime) / 1000.0, nSwaps);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compute variable lifetime lambda.]
+
+  Description [Compute variable lifetime lambda.]
+
+  SideEffects []
+
+******************************************************************************/
+static float
+ComputeLambdaMlp(char **xy, int nVars, int nRows, int nCols,
+		RcInfo_t *rowInfo, RcInfo_t *colInfo,
+		int *rowOrder, int *colOrder,
+		Img_DirectionType direction,
+		int mode, int asIs, ImgTrmOption_t *option)
+{
+  int		lifetime, area;
+  int		highest, lowest;
+  int		x, y, row, col;
+  int		nIntroducedVars, nYVars;
+  float		lambda;
+
+  lifetime = 0;
+
+  if (direction == Img_Forward_c) {
+    for (y = 0; y < nCols; y++) {
+      col = colOrder[y];
+      lowest = rowInfo[colInfo[col].gMin].pos;
+      if (mode == 1) { /* active lifetime (alpha) */
+	highest = rowInfo[colInfo[col].gMax].pos;
+	lifetime += highest - lowest + 1;
+      } else { /* total lifetime (lambda) */
+	lifetime += nRows - lowest;
+      }
+    }
+  } else {
+    for (y = 0; y < nCols; y++) {
+      col = colOrder[y];
+      lowest = rowInfo[colInfo[col].gMin].pos;
+      if (mode == 1) { /* active lifetime (alpha) */
+	highest = rowInfo[colInfo[col].gMax].pos;
+	lifetime += highest - lowest + 1;
+      } else { /* total lifetime (lambda) */
+	if (colInfo[col].data.col.type == 2) /* primary input variables */
+	  lifetime += lowest + 1;
+	else { /* present state variables */
+	  if (mode == 2)
+	    lifetime += nRows - lowest;
+	}
+      }
+    }
+  }
+
+  /* total lifetime (lambda) with introducedVars */
+  nIntroducedVars = 0;;
+  if (mode == 2 || (mode == 0 && direction == Img_Backward_c)) {
+    if (asIs) { /* contains next state variables */
+      for (x = 0; x < nRows; x++) {
+	row = rowOrder[x];
+	nYVars = array_n(rowInfo[row].data.row.nsVarBddArray);
+	nIntroducedVars += nYVars;
+	lifetime += (x + 1) * nYVars;
+      }
+    } else { /* does not contain next state variables */
+      nIntroducedVars = nRows;
+      lifetime += nIntroducedVars * (nIntroducedVars + 1) / 2;
+    }
+  }
+
+  if (option->mlpLambdaMode == 0)
+    area = nRows * (nCols + nIntroducedVars);
+  else
+    area = nRows * (nVars + nIntroducedVars);
+  lambda = (float)lifetime / (float)area;
+  return(lambda);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds and moves singleton rows.]
+
+  Description [Finds and moves singleton rows.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+FindAndMoveSingletonRows(char **xy, SccList_t *sccList, int nRows, int nCols,
+	int *startFunc, int *lastFunc, int *startVar, int *lastVar,
+	RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder,
+	ImgTrmOption_t *option)
+{
+  int		x, row, col, add, found;
+  RcListInfo_t	*candList;
+
+  if (option->mlpMethod == 0) {
+    while (*startFunc != *lastFunc && *startVar != *lastVar) {
+      found = 0;
+      for (x = *startFunc; x <= *lastFunc; x++) {
+	row = rowOrder[x];
+	if (rowInfo[row].lNum == 1) {
+	  found = 1;
+	  add = MoveSingletonRow(xy, sccList, nRows, nCols, x,
+				startFunc, lastFunc, startVar, lastVar,
+				rowInfo, colInfo, rowOrder, colOrder,
+				NIL(RcListInfo_t), option);
+	  if (*startFunc == *lastFunc || *startVar == *lastVar) {
+	    found = 0;
+	    break;
+	  }
+	  x += add;
+	}
+      }
+      if (!found)
+	break;
+    }
+  } else {
+    if (*startFunc != *lastFunc && *startVar != *lastVar) {
+      candList = SortedListAlloc();
+      for (x = *startFunc; x <= *lastFunc; x++) {
+	row = rowOrder[x];
+	if (rowInfo[row].lNum == 1) {
+	  col = rowInfo[row].lMin;
+	  SortedListInsert(candList, row, col, colInfo, option->mlpMethod);
+	}
+      }
+      if (option->mlpDebug)
+	CheckSortedList(candList, colInfo, option->mlpMethod);
+      while (candList->cur) {
+	candList->curIndex = candList->cur->index;
+	x = rowInfo[candList->curIndex].pos;
+	MoveSingletonRow(xy, sccList, nRows, nCols, x,
+			startFunc, lastFunc, startVar, lastVar,
+			rowInfo, colInfo, rowOrder, colOrder,
+			candList, option);
+	if (option->mlpDebug)
+	  CheckSortedList(candList, colInfo, option->mlpMethod);
+	if (*startFunc == *lastFunc || *startVar == *lastVar) {
+	  break;
+	}
+      }
+      if (option->mlpVerbosity) {
+	fprintf(vis_stdout, "max number of elements in list = %d\n",
+		candList->maxNum);
+      }
+      SortedListFree(candList);
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Moves a singleton row.]
+
+  Description [Moves a singleton row.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+MoveSingletonRow(char **xy, SccList_t *sccList, int nRows, int nCols, int x,
+	int *startFunc, int *lastFunc, int *startVar, int *lastVar,
+	RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder,
+	RcListInfo_t *candList, ImgTrmOption_t *option)
+{
+  int	y, i, add;
+  int	row, col, otherRow;
+  int	startRow, lastRow, startCol, lastCol;
+
+  startRow = *startFunc;
+  startCol = *startVar;
+  lastRow = *lastFunc;
+  lastCol = *lastVar;
+
+  row = rowOrder[x];
+  col = rowInfo[row].lMin;
+  y = colInfo[col].pos;
+
+  if (option->mlpVerbosity >= 3) {
+    fprintf(vis_stdout, "[%d] Moving Col %d(%d) to %d (row singleton)\n",
+	  nMoves, y, col, startCol);
+    fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
+	   startRow, lastRow, startCol, lastCol);
+  }
+  MoveColToLeft(xy, y, startRow, lastRow, startCol, lastCol,
+		rowInfo, colInfo, rowOrder, colOrder, candList,
+		option->mlpMethod);
+  startCol++;
+  if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
+    PrintMatrix(xy, nRows, nCols, rowOrder, colOrder, rowInfo, colInfo,
+		startRow, lastRow, startCol, lastCol);
+  }
+  if (option->mlpDebug) {
+    CheckMatrix(xy, sccList, nRows, nCols, rowInfo, colInfo, rowOrder, colOrder,
+		startRow, lastRow, startCol, lastCol, 1);
+  }
+
+  add = 0;
+  for (i = rowInfo[colInfo[col].lMin].pos;
+       colInfo[col].lNum && i <= rowInfo[colInfo[col].lMax].pos; i++) {
+    otherRow = rowOrder[i];
+    if (!xy[otherRow][col])
+      continue;
+    if (rowInfo[otherRow].lNum == 0) {
+      if (option->mlpVerbosity >= 3) {
+	fprintf(vis_stdout, "[%d] Moving row %d(%d) to %d (row singleton)\n",
+		nMoves, i, otherRow, startRow);
+	fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
+	       startRow, lastRow, startCol, lastCol);
+      }
+      MoveRowToTop(xy, i, startRow, lastRow, startCol, lastCol,
+		   rowInfo, colInfo, rowOrder, colOrder,
+		   NIL(RcListInfo_t), option->mlpMethod);
+      startRow++;
+      if (i > x)
+	add++;
+      if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
+	PrintMatrix(xy, nRows, nCols, rowOrder, colOrder, rowInfo, colInfo,
+		    startRow, lastRow, startCol, lastCol);
+      }
+      if (option->mlpDebug) {
+	CheckMatrix(xy, sccList, nRows, nCols,
+		    rowInfo, colInfo, rowOrder, colOrder,
+		    startRow, lastRow, startCol, lastCol, 1);
+      }
+    }
+  }
+
+  *startFunc = startRow;
+  *startVar = startCol;
+  return(add);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds and moves singleton columns.]
+
+  Description [Finds and moves singleton columns.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+FindAndMoveSingletonCols(char **xy, SccList_t *sccList, int nRows, int nCols,
+	int *startFunc, int *lastFunc, int *startVar, int *lastVar,
+	RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder,
+	ImgTrmOption_t *option)
+{
+  int		y, row, col, add, found;
+  RcListInfo_t	*candList;
+
+  if (option->mlpMethod == 0) {
+    while (*startFunc != *lastFunc && *startVar != *lastVar) {
+      found = 0;
+      for (y = *startVar; y <= *lastVar; y++) {
+	col = colOrder[y];
+	if (colInfo[col].lNum == 1) {
+	  found = 1;
+	  add = MoveSingletonCol(xy, sccList, nRows, nCols, y,
+				startFunc, lastFunc, startVar, lastVar,
+				rowInfo, colInfo, rowOrder, colOrder,
+				NIL(RcListInfo_t), option);
+	  if (*startFunc == *lastFunc || *startVar == *lastVar) {
+	    found = 0;
+	    break;
+	  }
+	  y -= add;
+	}
+      }
+      if (!found)
+	break;
+    }
+  } else {
+    if (*startFunc != *lastFunc && *startVar != *lastVar) {
+      candList = SortedListAlloc();
+      for (y = *startVar; y <= *lastVar; y++) {
+	col = colOrder[y];
+	if (colInfo[col].lNum == 1) {
+	  row = colInfo[col].lMin;
+	  SortedListInsert(candList, col, row, rowInfo, option->mlpMethod);
+	}
+      }
+      if (option->mlpDebug)
+	CheckSortedList(candList, rowInfo, option->mlpMethod);
+      while (candList->cur) {
+	candList->curIndex = candList->cur->index;
+	y = colInfo[candList->curIndex].pos;
+	MoveSingletonCol(xy, sccList, nRows, nCols, y,
+			startFunc, lastFunc, startVar, lastVar,
+			rowInfo, colInfo, rowOrder, colOrder, candList, option);
+	if (option->mlpDebug)
+	  CheckSortedList(candList, rowInfo, option->mlpMethod);
+	if (*startFunc == *lastFunc || *startVar == *lastVar) {
+	  break;
+	}
+      }
+      if (option->mlpVerbosity >= 2) {
+	fprintf(vis_stdout, "max number of elements in list = %d\n",
+		candList->maxNum);
+      }
+      SortedListFree(candList);
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Moves a singleton column.]
+
+  Description [Moves a singleton column.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+MoveSingletonCol(char **xy, SccList_t *sccList, int nRows, int nCols, int y,
+	int *startFunc, int *lastFunc, int *startVar, int *lastVar,
+	RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder,
+	RcListInfo_t *candList, ImgTrmOption_t *option)
+{
+  int	x, j, add;
+  int	row, col, otherCol;
+  int	startRow, lastRow, startCol, lastCol;
+
+  startRow = *startFunc;
+  startCol = *startVar;
+  lastRow = *lastFunc;
+  lastCol = *lastVar;
+
+  col = colOrder[y];
+  row = colInfo[col].lMin;
+  x = rowInfo[row].pos;
+
+  if (option->mlpVerbosity >= 3) {
+    fprintf(vis_stdout, "[%d] Moving Row %d(%d) to %d (col singleton)\n",
+	  nMoves, x, row, lastRow);
+    fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
+	   startRow, lastRow, startCol, lastCol);
+  }
+  MoveRowToBottom(xy, x, startRow, lastRow, startCol, lastCol,
+		  rowInfo, colInfo, rowOrder, colOrder, candList,
+		  option->mlpMethod);
+  lastRow--;
+  if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
+    PrintMatrix(xy, nRows, nCols, rowOrder, colOrder, rowInfo, colInfo,
+		startRow, lastRow, startCol, lastCol);
+  }
+  if (option->mlpDebug) {
+    CheckMatrix(xy, sccList, nRows, nCols, rowInfo, colInfo, rowOrder, colOrder,
+		startRow, lastRow, startCol, lastCol, 1);
+  }
+
+  add = 0;
+  for (j = colInfo[rowInfo[row].lMin].pos;
+       rowInfo[row].lNum && j <= colInfo[rowInfo[row].lMax].pos; j++) {
+    otherCol = colOrder[j];
+    if (!xy[row][otherCol])
+      continue;
+    if (colInfo[otherCol].lNum == 0) {
+      if (option->mlpVerbosity >= 3) {
+	fprintf(vis_stdout, "[%d] Moving Col %d(%d) to %d (col singleton)\n",
+		nMoves, j, otherCol, lastCol);
+	fprintf(vis_stdout, "active window [%d-%d, %d-%d]\n",
+		startRow, lastRow, startCol, lastCol);
+      }
+      MoveColToRight(xy, j, startRow, lastRow, startCol, lastCol,
+		     rowInfo, colInfo, rowOrder, colOrder,
+		     NIL(RcListInfo_t), option->mlpMethod);
+      lastCol--;
+      j--;
+      if (otherCol <= col)
+	add++;
+      if (option->mlpVerbosity >= 4 && option->mlpPrintMatrix) {
+	PrintMatrix(xy, nRows, nCols, rowOrder, colOrder, rowInfo, colInfo,
+		    startRow, lastRow, startCol, lastCol);
+      }
+      if (option->mlpDebug) {
+	CheckMatrix(xy, sccList, nRows, nCols,
+		    rowInfo, colInfo, rowOrder, colOrder,
+		    startRow, lastRow, startCol, lastCol, 1);
+      }
+    }
+  }
+
+  *lastFunc = lastRow;
+  *lastVar = lastCol;
+  return(add);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Moves a row to the top of the active region.]
+
+  Description [Moves a row to the top of the active region.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+MoveRowToTop(char **xy, int x, int startFunc, int lastFunc,
+	     int startVar, int lastVar, RcInfo_t *rowInfo,
+	     RcInfo_t *colInfo, int *rowOrder, int *colOrder,
+	     RcListInfo_t *candList, int method)
+{
+  int	i, j, s, t;
+  int	row, col, tmpRow;
+
+  assert(x >= startFunc && x <= lastFunc);
+
+  row = rowOrder[x];
+  if (x != startFunc) {
+    /* Change row order */
+    for (i = x; i > startFunc; i--) {
+      rowOrder[i] = rowOrder[i - 1];
+      rowInfo[rowOrder[i]].pos = i;
+    }
+    rowOrder[startFunc] = row;
+    rowInfo[row].pos = startFunc;
+  }
+
+  s = colInfo[rowInfo[row].gMin].pos;
+  t = colInfo[rowInfo[row].gMax].pos;
+  for (j = s; j <= t; j++) {
+    col = colOrder[j];
+    if (!xy[row][col])
+      continue;
+    colInfo[col].prevG = startFunc;
+    if (colInfo[col].lNum == 1) {
+      colInfo[col].lMin = row;
+      colInfo[col].lMax = row;
+    } else {
+      if (row == colInfo[col].lMin) {
+	for (i = x + 1; i <= rowInfo[colInfo[col].lMax].pos; i++) {
+	  tmpRow = rowOrder[i];
+	  if (xy[tmpRow][col]) {
+	    colInfo[col].lMin = tmpRow;
+	    break;
+	  }
+	}
+      } else if (row == colInfo[col].lMax) {
+	for (i = x; i >= rowInfo[colInfo[col].lMin].pos; i--) {
+	  tmpRow = rowOrder[i];
+	  if (xy[tmpRow][col]) {
+	    colInfo[col].lMax = tmpRow;
+	    break;
+	  }
+	}
+      }
+    }
+
+    if (colInfo[col].gNum == 1) {
+      colInfo[col].gMin = row;
+      colInfo[col].gMax = row;
+    } else {
+      if (row == colInfo[col].gMin)
+	colInfo[col].gMin = row;
+      else if (row == colInfo[col].gMax) {
+	colInfo[col].gMax = colInfo[col].lMax;
+	if (startFunc <= rowInfo[colInfo[col].gMin].pos)
+	  colInfo[col].gMin = row;
+      } else if (startFunc <= rowInfo[colInfo[col].gMin].pos)
+	colInfo[col].gMin = row;
+    }
+
+    if (rowInfo[row].lNum) {
+      if (j == rowInfo[row].prevG)
+	j = colInfo[rowInfo[row].lMin].pos - 1;
+      else if (j == colInfo[rowInfo[row].lMax].pos)
+	j = rowInfo[row].nextG - 1;
+    }
+  }
+
+  s = colInfo[rowInfo[row].lMin].pos;
+  t = colInfo[rowInfo[row].lMax].pos;
+  for (j = s; j <= t; j++) {
+    col = colOrder[j];
+    if (xy[row][col]) {
+      colInfo[col].lNum--;
+      if (candList) {
+	if (colInfo[col].lNum == 0)
+	  SortedListDelete(candList, col);
+	else if (colInfo[col].lNum == 1)
+	  SortedListInsert(candList, col, row, rowInfo, method);
+      }
+    }
+  }
+
+  nMoves++;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Moves a column to the left of the active region.]
+
+  Description [Moves a column to the left of the active region.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+MoveColToLeft(char **xy, int y, int startFunc, int lastFunc,
+	      int startVar, int lastVar, RcInfo_t *rowInfo,
+	      RcInfo_t *colInfo, int *rowOrder, int *colOrder,
+	      RcListInfo_t *candList, int method)
+{
+  int	i, j, s, t;
+  int	row, col, tmpCol;
+
+  assert(y >= startVar && y <= lastVar);
+
+  col = colOrder[y];
+  if (y != startVar) {
+    /* Change col order */
+    for (j = y; j > startVar; j--) {
+      colOrder[j] = colOrder[j - 1];
+      colInfo[colOrder[j]].pos = j;
+    }
+    colOrder[startVar] = col;
+    colInfo[col].pos = startVar;
+  }
+
+  s = rowInfo[colInfo[col].gMin].pos;
+  t = rowInfo[colInfo[col].gMax].pos;
+  for (i = s; i <= t; i++) {
+    row = rowOrder[i];
+    if (!xy[row][col])
+      continue;
+    rowInfo[row].prevG = startVar;
+    if (rowInfo[row].lNum == 1) {
+      rowInfo[row].lMin = col;
+      rowInfo[row].lMax = col;
+    } else {
+      if (col == rowInfo[row].lMin) {
+	for (j = y + 1; j <= colInfo[rowInfo[row].lMax].pos; j++) {
+	  tmpCol = colOrder[j];
+	  if (xy[row][tmpCol]) {
+	    rowInfo[row].lMin = tmpCol;
+	    break;
+	  }
+	}
+      } else if (col == rowInfo[row].lMax) {
+	for (j = y; j >= colInfo[rowInfo[row].lMin].pos; j--) {
+	  tmpCol = colOrder[j];
+	  if (xy[row][tmpCol]) {
+	    rowInfo[row].lMax = tmpCol;
+	    break;
+	  }
+	}
+      }
+    }
+
+    if (rowInfo[row].gNum == 1) {
+      rowInfo[row].gMin = col;
+      rowInfo[row].gMax = col;
+    } else {
+      if (col == rowInfo[row].gMin)
+	rowInfo[row].gMin = col;
+      else if (col == rowInfo[row].gMax) {
+	rowInfo[row].gMax = rowInfo[row].lMax;
+	if (startVar <= colInfo[rowInfo[row].gMin].pos)
+	  rowInfo[row].gMin = col;
+      } else if (startVar <= colInfo[rowInfo[row].gMin].pos)
+	rowInfo[row].gMin = col;
+    }
+
+    if (colInfo[col].lNum) {
+      if (i == colInfo[col].prevG)
+	i = rowInfo[colInfo[col].lMin].pos - 1;
+      else if (i == rowInfo[colInfo[col].lMax].pos)
+	i = colInfo[col].nextG - 1;
+    }
+  }
+
+  s = rowInfo[colInfo[col].lMin].pos;
+  t = rowInfo[colInfo[col].lMax].pos;
+  for (i = s; i <= t; i++) {
+    row = rowOrder[i];
+    if (xy[row][col]) {
+      rowInfo[row].lNum--;
+      if (candList) {
+	if (rowInfo[row].lNum == 0)
+	  SortedListDelete(candList, row);
+	else if (rowInfo[row].lNum == 1)
+	  SortedListInsert(candList, row, col, colInfo, method);
+      }
+    }
+  }
+
+  nMoves++;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Moves a row to the bottom of the active region.]
+
+  Description [Moves a row to the bottom of the active region.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+MoveRowToBottom(char **xy, int x, int startFunc, int lastFunc,
+		int startVar, int lastVar, RcInfo_t *rowInfo,
+		RcInfo_t *colInfo, int *rowOrder, int *colOrder,
+		RcListInfo_t *candList, int method)
+{
+  int	i, j, s, t;
+  int	row, col, tmpRow;
+
+  assert(x >= startFunc && x <= lastFunc);
+
+  row = rowOrder[x];
+  if (x != lastFunc) {
+    /* Change row order */
+    for (i = x; i < lastFunc; i++) {
+      rowOrder[i] = rowOrder[i + 1];
+      rowInfo[rowOrder[i]].pos = i;
+    }
+    rowOrder[lastFunc] = row;
+    rowInfo[row].pos = lastFunc;
+  }
+
+  s = colInfo[rowInfo[row].gMin].pos;
+  t = colInfo[rowInfo[row].gMax].pos;
+  for (j = s; j <= t; j++) {
+    col = colOrder[j];
+    if (!xy[row][col])
+      continue;
+    colInfo[col].nextG = lastFunc;
+    if (colInfo[col].lNum == 1) {
+      colInfo[col].lMin = row;
+      colInfo[col].lMax = row;
+    } else {
+      if (row == colInfo[col].lMin) {
+	for (i = x; i <= rowInfo[colInfo[col].lMax].pos; i++) {
+	  tmpRow = rowOrder[i];
+	  if (xy[tmpRow][col]) {
+	    colInfo[col].lMin = tmpRow;
+	    break;
+	  }
+	}
+      } else if (row == colInfo[col].lMax) {
+	for (i = x - 1; i >= rowInfo[colInfo[col].lMin].pos; i--) {
+	  tmpRow = rowOrder[i];
+	  if (xy[tmpRow][col]) {
+	    colInfo[col].lMax = tmpRow;
+	    break;
+	  }
+	}
+      }
+    }
+
+    if (colInfo[col].gNum == 1) {
+      colInfo[col].gMin = row;
+      colInfo[col].gMax = row;
+    } else {
+      if (row == colInfo[col].gMax)
+	colInfo[col].gMax = row;
+      else if (row == colInfo[col].gMin) {
+	colInfo[col].gMin = colInfo[col].lMin;
+	if (lastFunc >= rowInfo[colInfo[col].gMax].pos)
+	  colInfo[col].gMax = row;
+      } else if (lastFunc >= rowInfo[colInfo[col].gMax].pos)
+	colInfo[col].gMax = row;
+    }
+
+    if (rowInfo[row].lNum) {
+      if (j == rowInfo[row].prevG)
+	j = colInfo[rowInfo[row].lMin].pos - 1;
+      else if (j == colInfo[rowInfo[row].lMax].pos)
+	j = rowInfo[row].nextG - 1;
+    }
+  }
+
+  s = colInfo[rowInfo[row].lMin].pos;
+  t = colInfo[rowInfo[row].lMax].pos;
+  for (j = s; j <= t; j++) {
+    col = colOrder[j];
+    if (xy[row][col]) {
+      colInfo[col].lNum--;
+      if (candList) {
+	if (colInfo[col].lNum == 0)
+	  SortedListDelete(candList, col);
+	else if (colInfo[col].lNum == 1)
+	  SortedListInsert(candList, col, row, rowInfo, method);
+      }
+    }
+  }
+
+  nMoves++;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Moves a column to the tight of the active region.]
+
+  Description [Moves a column to the tight of the active region.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+MoveColToRight(char **xy, int y, int startFunc, int lastFunc,
+	       int startVar, int lastVar, RcInfo_t *rowInfo,
+	       RcInfo_t *colInfo, int *rowOrder, int *colOrder,
+	       RcListInfo_t *candList, int method)
+{
+  int	i, j, s, t;
+  int	row, col, tmpCol;
+
+  assert(y >= startVar && y <= lastVar);
+
+  col = colOrder[y];
+  if (y != lastVar) {
+    /* Change col order */
+    for (j = y; j < lastVar; j++) {
+      colOrder[j] = colOrder[j + 1];
+      colInfo[colOrder[j]].pos = j;
+    }
+    colOrder[lastVar] = col;
+    colInfo[col].pos = lastVar;
+  }
+
+  s = rowInfo[colInfo[col].gMin].pos;
+  t = rowInfo[colInfo[col].gMax].pos;
+  for (i = s; i <= t; i++) {
+    row = rowOrder[i];
+    if (!xy[row][col])
+      continue;
+    rowInfo[row].nextG = lastVar;
+    if (rowInfo[row].lNum == 1) {
+      rowInfo[row].lMin = col;
+      rowInfo[row].lMax = col;
+    } else {
+      if (col == rowInfo[row].lMin) {
+	for (j = y; j <= colInfo[rowInfo[row].lMax].pos; j++) {
+	  tmpCol = colOrder[j];
+	  if (xy[row][tmpCol]) {
+	    rowInfo[row].lMin = tmpCol;
+	    break;
+	  }
+	}
+      } else if (col == rowInfo[row].lMax) {
+	for (j = y - 1; j >= colInfo[rowInfo[row].lMin].pos; j--) {
+	  tmpCol = colOrder[j];
+	  if (xy[row][tmpCol]) {
+	    rowInfo[row].lMax = tmpCol;
+	    break;
+	  }
+	}
+      }
+    }
+
+    if (rowInfo[row].gNum == 1) {
+      rowInfo[row].gMin = col;
+      rowInfo[row].gMax = col;
+    } else {
+      if (col == rowInfo[row].gMax)
+	rowInfo[row].gMax = col;
+      else if (col == rowInfo[row].gMin) {
+	rowInfo[row].gMin = rowInfo[row].lMin;
+	if (lastVar >= colInfo[rowInfo[row].gMax].pos)
+	  rowInfo[row].gMax = col;
+      } else if (lastVar >= colInfo[rowInfo[row].gMax].pos)
+	rowInfo[row].gMax = col;
+    }
+
+    if (colInfo[col].lNum) {
+      if (i == colInfo[col].prevG)
+	i = rowInfo[colInfo[col].lMin].pos - 1;
+      else if (i == rowInfo[colInfo[col].lMax].pos)
+	i = colInfo[col].nextG - 1;
+    }
+  }
+
+  s = rowInfo[colInfo[col].lMin].pos;
+  t = rowInfo[colInfo[col].lMax].pos;
+  for (i = s; i <= t; i++) {
+    row = rowOrder[i];
+    if (xy[row][col]) {
+      rowInfo[row].lNum--;
+      if (candList) {
+	if (rowInfo[row].lNum == 0)
+	  SortedListDelete(candList, row);
+	else if (rowInfo[row].lNum == 1)
+	  SortedListInsert(candList, row, col, colInfo, method);
+      }
+    }
+  }
+
+  nMoves++;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints a maxtrix.]
+
+  Description [Prints a maxtrix.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+PrintMatrix(char **xy, int nRows, int nCols, int *rowOrder, int *colOrder,
+	    RcInfo_t *rowInfo, RcInfo_t *colInfo,
+	    int startFunc, int lastFunc, int startVar, int lastVar)
+{
+  int	i, j, x, y;
+  int	row, col, index;
+  char	line[2048];
+  bdd_t	*nsVar;
+
+  line[nCols] = '\0';
+  for (x = 0; x < nRows; x++) {
+    if (startFunc != lastFunc && startVar != lastVar &&
+	x == startFunc && x != 0) {
+      for (y = 0; y < nCols; y++) {
+	if (y == startVar || y == lastVar)
+	  line[y] = '%';
+	else
+	  line[y] = '=';
+      }
+      fprintf(vis_stdout, "%s\n", line);
+    }
+    i = rowOrder[x];
+    for (y = 0; y < nCols; y++) {
+      j = colOrder[y];
+      if (xy[i][j])
+	line[y] = '1';
+      else
+	line[y] = '.';
+    }
+    fprintf(vis_stdout, "%s\n", line);
+    if (startFunc != lastFunc && startVar != lastVar &&
+	x == lastFunc && x < nRows - 1) {
+      for (y = 0; y < nCols; y++) {
+	if (y == startVar || y == lastVar)
+	  line[y] = '%';
+	else
+	  line[y] = '=';
+      }
+      fprintf(vis_stdout, "%s\n", line);
+    }
+  }
+  fprintf(vis_stdout, "row order :");
+  for (x = 0; x < nRows; x++) {
+    row = rowOrder[x];
+    fprintf(vis_stdout, " %d(", row);
+    if (rowInfo[row].data.row.nsVarBddArray) {
+      for (i = 0; i < array_n(rowInfo[row].data.row.nsVarBddArray); i++) {
+	nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray, i);
+	index = (int)bdd_top_var_id(nsVar);
+	if (i == 0)
+	  fprintf(vis_stdout, "%d", index);
+	else
+	  fprintf(vis_stdout, ",%d", index);
+      }
+    }
+    fprintf(vis_stdout, ")");
+  }
+  fprintf(vis_stdout, "\n");
+  fprintf(vis_stdout, "col order :");
+  for (y = 0; y < nCols; y++) {
+    col = colOrder[y];
+    index = (int)bdd_top_var_id(colInfo[col].data.col.var);
+    fprintf(vis_stdout, " %d(%d)", col, index);
+  }
+  fprintf(vis_stdout, "\n");
+  fprintf(vis_stdout, "#active rows : %d-%d\n", startFunc, lastFunc);
+  fprintf(vis_stdout, "#active cols : %d-%d\n", startVar, lastVar);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints a matrix with cluster information.]
+
+  Description [Prints a matrix with cluster information.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+PrintMatrixWithCluster(char **xy, ClusterList_t *headCluster, int nCols,
+			int *rowOrder, int *colOrder,
+			Img_DirectionType direction)
+{
+  int		i, j, x, y;
+  char		line[2048];
+  ClusterList_t	*list, *tailCluster;
+
+  line[nCols] = '\0';
+  if (direction == Img_Forward_c) {
+    tailCluster = headCluster;
+    list = headCluster;
+    while (list->next) {
+      tailCluster = list->next;
+      list = tailCluster;
+    }
+    list = tailCluster;
+    while (list) {
+      for (x = list->start; x <= list->end; x++) {
+	i = rowOrder[x];
+	for (y = 0; y < nCols; y++) {
+	  j = colOrder[y];
+	  if (xy[i][j])
+	    line[y] = '1';
+	  else
+	    line[y] = '.';
+	}
+	fprintf(vis_stdout, "%s\n", line);
+      }
+      list = list->prev;
+      if (list) {
+	for (y = 0; y < nCols; y++)
+	  line[y] = '-';
+	fprintf(vis_stdout, "%s\n", line);
+      }
+    }
+  } else {
+    list = headCluster;
+    while (list) {
+      for (x = list->start; x <= list->end; x++) {
+	i = rowOrder[x];
+	for (y = 0; y < nCols; y++) {
+	  j = colOrder[y];
+	  if (xy[i][j])
+	    line[y] = '1';
+	  else
+	    line[y] = '.';
+	}
+	fprintf(vis_stdout, "%s\n", line);
+      }
+      list = list->next;
+      if (list) {
+	for (y = 0; y < nCols; y++)
+	  line[y] = '-';
+	fprintf(vis_stdout, "%s\n", line);
+      }
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints cluster information.]
+
+  Description [Prints cluster information.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+PrintClusterMatrix(ClusterList_t *headCluster, int nCols,
+		   int *colOrder, Img_DirectionType direction)
+{
+  int		j, y;
+  char		line[2048];
+  ClusterList_t	*list, *tailCluster;
+
+  line[nCols] = '\0';
+  if (direction == Img_Forward_c) {
+    tailCluster = headCluster;
+    list = headCluster;
+    while (list->next) {
+      tailCluster = list->next;
+      list = tailCluster;
+    }
+    list = tailCluster;
+    while (list) {
+      for (y = 0; y < nCols; y++) {
+	j = colOrder[y];
+	if (list->supports[j])
+	  line[y] = '1';
+	else
+	  line[y] = '.';
+      }
+      fprintf(vis_stdout, "%s\n", line);
+      list = list->prev;
+      if (list) {
+	for (y = 0; y < nCols; y++)
+	  line[y] = '-';
+	fprintf(vis_stdout, "%s\n", line);
+      }
+    }
+  } else {
+    list = headCluster;
+    while (list) {
+      for (y = 0; y < nCols; y++) {
+	j = colOrder[y];
+	if (list->supports[j])
+	  line[y] = '1';
+	else
+	  line[y] = '.';
+      }
+      fprintf(vis_stdout, "%s\n", line);
+      list = list->next;
+      if (list) {
+	for (y = 0; y < nCols; y++)
+	  line[y] = '-';
+	fprintf(vis_stdout, "%s\n", line);
+      }
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks a matrix for sanity.]
+
+  Description [Checks a matrix for sanity.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+CheckMatrix(char **xy, SccList_t *sccList, int nRows, int nCols,
+	    RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder,
+	    int startFunc, int lastFunc, int startVar, int lastVar, int local)
+{
+  int	i, j, x, y;
+  int	lMin, lMax, gMin, gMax, lNum, gNum, prevG, nextG;
+  int	error = 0;
+
+  for (x = 0; x < nRows; x++) {
+    i = rowOrder[x];
+    if (x != rowInfo[i].pos) {
+      fprintf(vis_stderr, "Error : wrong rowOrder (%d != %d) in Row %d\n",
+	     x, rowInfo[i].pos, x);
+      error = 1;
+    }
+
+    lMin = gMin = nCols;
+    lMax = gMax = -1;
+    lNum = gNum = 0;
+    prevG = -1;
+    nextG = nCols;
+
+    for (y = 0; y < nCols; y++) {
+      j = colOrder[y];
+      if (xy[i][j]) {
+	gNum++;
+	if (y < gMin)
+	  gMin = y;
+	if (y > gMax)
+	  gMax = y;
+	if (local) {
+	  if (x >= startFunc && x <= lastFunc &&
+	      y >= startVar && y <= lastVar) {
+	    if (y < lMin)
+	      lMin = y;
+	    if (y > lMax)
+	      lMax = y;
+	    lNum++;
+	  }
+	  if (!sccList ||
+	      (x >= sccList->startFunc && x <= sccList->lastFunc)) {
+	    if (y < startVar)
+	      prevG = y;
+	    if (y > lastVar && nextG == nCols)
+	      nextG = y;
+	  }
+	}
+      }
+    }
+    if (gNum != rowInfo[i].gNum) {
+      fprintf(vis_stderr, "Error : wrong gNum (%d != %d) in Row %d\n",
+	     gNum, rowInfo[i].gNum, x);
+      error = 1;
+    }
+    if (gNum > 0) {
+      if (gMin != colInfo[rowInfo[i].gMin].pos) {
+	fprintf(vis_stderr, "Error : wrong gMin (%d != %d) in Row %d\n",
+	       gMin, colInfo[rowInfo[i].gMin].pos, x);
+	error = 1;
+      }
+      if (gMax != colInfo[rowInfo[i].gMax].pos) {
+	fprintf(vis_stderr, "Error : wrong gMax (%d != %d) in Row %d\n",
+	       gMax, colInfo[rowInfo[i].gMax].pos, x);
+	error = 1;
+      }
+    }
+    if (local) {
+      if (x >= startFunc && x <= lastFunc &&
+	  lNum != rowInfo[i].lNum) {
+	fprintf(vis_stderr, "Error : wrong lNum (%d != %d) in Row %d\n",
+	       lNum, rowInfo[i].lNum, x);
+	error = 1;
+      }
+      if (x >= startFunc && x <= lastFunc && lMin < nCols &&
+	  lMin != colInfo[rowInfo[i].lMin].pos) {
+	fprintf(vis_stderr, "Error : wrong lMin (%d != %d) in Row %d\n",
+	       lMin, colInfo[rowInfo[i].lMin].pos, x);
+	error = 1;
+      }
+      if (x >= startFunc && x <= lastFunc && lMax > -1 &&
+	  lMax != colInfo[rowInfo[i].lMax].pos) {
+	fprintf(vis_stderr, "Error : wrong lMax (%d != %d) in Row %d\n",
+	       lMax, colInfo[rowInfo[i].lMax].pos, x);
+	error = 1;
+      }
+      if (!sccList || (x >= sccList->startFunc && x <= sccList->lastFunc)) {
+	if (prevG != rowInfo[i].prevG) {
+	  fprintf(vis_stderr, "Error : wrong prevG (%d != %d) in Row %d\n",
+		  prevG, rowInfo[i].prevG, x);
+	  error = 1;
+	}
+	if (nextG != rowInfo[i].nextG) {
+	  fprintf(vis_stderr, "Error : wrong nextG (%d != %d) in Row %d\n",
+		  nextG, rowInfo[i].nextG, x);
+	  error = 1;
+	}
+      }
+    }
+  }
+
+  for (y = 0; y < nCols; y++) {
+    j = colOrder[y];
+    if (y != colInfo[j].pos) {
+      fprintf(vis_stderr, "Error : wrong colOrder (%d != %d) in Col %d\n",
+	     y, colInfo[y].pos, y);
+      error = 1;
+    }
+
+    lMin = gMin = nRows;
+    lMax = gMax = -1;
+    lNum = gNum = 0;
+    prevG = -1;
+    nextG = nRows;
+
+    for (x = 0; x < nRows; x++) {
+      i = rowOrder[x];
+      if (xy[i][j]) {
+	gNum++;
+	if (x < gMin)
+	  gMin = x;
+	if (x > gMax)
+	  gMax = x;
+	if (local) {
+	  if (x >= startFunc && x <= lastFunc &&
+	      y >= startVar && y <= lastVar) {
+	    if (x < lMin)
+	      lMin = x;
+	    if (x > lMax)
+	      lMax = x;
+	    lNum++;
+	  }
+	  if (!sccList ||
+	      (y >= sccList->startVar && y <= sccList->lastVar)) {
+	    if (x < startFunc)
+	      prevG = x;
+	    if (x > lastFunc && nextG == nRows)
+	      nextG = x;
+	  }
+	}
+      }
+    }
+    if (gNum != colInfo[j].gNum) {
+      fprintf(vis_stderr, "Error : wrong gNum (%d != %d) in Col %d\n",
+	     gNum, colInfo[j].gNum, y);
+      error = 1;
+    }
+    if (gNum > 0) {
+      if (gMin != rowInfo[colInfo[j].gMin].pos) {
+	fprintf(vis_stderr, "Error : wrong gMin (%d != %d) in Col %d\n",
+	       gMin, rowInfo[colInfo[j].gMin].pos, y);
+	error = 1;
+      }
+      if (gMax != rowInfo[colInfo[j].gMax].pos) {
+	fprintf(vis_stderr, "Error : wrong gMax (%d != %d) in Col %d\n",
+	       gMax, rowInfo[colInfo[j].gMax].pos, y);
+	error = 1;
+      }
+    }
+    if (local) {
+      if (y >= startVar && y <= lastVar &&
+	  lNum != colInfo[j].lNum) {
+	fprintf(vis_stderr, "Error : wrong lNum (%d != %d) in Col %d\n",
+	       lNum, colInfo[j].lNum, y);
+	error = 1;
+      }
+      if (y >= startVar && y <= lastVar && lMin < nRows &&
+	  lMin != rowInfo[colInfo[j].lMin].pos) {
+	fprintf(vis_stderr, "Error : wrong lMin (%d != %d) in Col %d\n",
+	       lMin, rowInfo[colInfo[j].lMin].pos, y);
+	error = 1;
+      }
+      if (y >= startVar && y <= lastVar && lMax > -1 &&
+	  lMax != rowInfo[colInfo[j].lMax].pos) {
+	fprintf(vis_stderr, "Error : wrong lMax (%d != %d) in Col %d\n",
+	       lMax, rowInfo[colInfo[j].lMax].pos, y);
+	error = 1;
+      }
+      if (!sccList || (y >= sccList->startVar && y <= sccList->lastVar)) {
+	if (prevG != colInfo[j].prevG) {
+	  fprintf(vis_stderr, "Error : wrong prevG (%d != %d) in Col %d\n",
+		  prevG, colInfo[j].prevG, y);
+	  error = 1;
+	}
+	if (nextG != colInfo[j].nextG) {
+	  fprintf(vis_stderr, "Error : wrong nextG (%d != %d) in Col %d\n",
+		  nextG, colInfo[j].nextG, y);
+	  error = 1;
+	}
+      }
+    }
+  }
+
+  assert(!error);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks cluster for sanity.]
+
+  Description [Checks cluster for sanity.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+CheckCluster(ClusterList_t *headCluster, int nCols,
+		RcInfo_t *colInfo, int *colOrder)
+{
+  int	j, y, n;
+  int	gMin, gMax, gNum;
+  int	error = 0;
+  ClusterList_t	*list;
+
+  n = 0;
+  list = headCluster;
+  while (list) {
+    gMin = nCols;
+    gMax = -1;
+    gNum = 0;
+
+    for (y = 0; y < nCols; y++) {
+      j = colOrder[y];
+      if (list->supports[j]) {
+	gNum++;
+	if (y < gMin)
+	  gMin = y;
+	if (y > gMax)
+	  gMax = y;
+      }
+    }
+    if (gNum != list->nSupports) {
+      fprintf(vis_stderr, "Error : wrong nSupports (%d != %d) in Cluster %d\n",
+	     gNum, list->nSupports, n);
+      error = 1;
+    }
+    if (gNum > 0) {
+      if (gMin != colInfo[list->minCol].pos) {
+	fprintf(vis_stderr, "Error : wrong gMin (%d != %d) in Cluster %d\n",
+	       gMin, colInfo[list->minCol].pos, n);
+	error = 1;
+      }
+      if (gMax != colInfo[list->maxCol].pos) {
+	fprintf(vis_stderr, "Error : wrong gMax (%d != %d) in Cluster %d\n",
+	       gMax, colInfo[list->maxCol].pos, n);
+	error = 1;
+      }
+    }
+    n++;
+    list = list->next;
+  }
+
+  assert(!error);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes a matrix to a file.]
+
+  Description [Writes a matrix to a file.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+WriteMatrix(FILE *fout, char **xy, int nRows, int nCols, int *rowOrder,
+	    int *colOrder, RcInfo_t *rowInfo, RcInfo_t *colInfo)
+{
+  int	x, y;
+  int	row, col;
+
+  for (x = 0; x < nRows; x++) {
+    row = rowOrder[x];
+    for (y = 0; y < nCols; y++) {
+      col = colOrder[y];
+      if (xy[row][col])
+	fprintf(fout, "%d %d %d\n", y, x, colInfo[col].data.col.type);
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints a row.]
+
+  Description [Prints a row.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+PrintRow(char **xy, int nRows, int nCols, int *rowOrder, int *colOrder,
+	 int from, int to)
+{
+  int	x, y, row, col;
+
+  for (x = from; x <= to; x++) {
+    row = rowOrder[x];
+    fprintf(vis_stdout, "[%d]%d :", x, row);
+    for (y = 0; y < nCols; y++) {
+      col = colOrder[y];
+      if (xy[row][col])
+	fprintf(vis_stdout, " %d(%d)", y, col);
+    }
+    fprintf(vis_stdout, "\n");
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints a column.]
+
+  Description [Prints a column.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+PrintCol(char **xy, int nRows, int nCols, int *rowOrder, int *colOrder,
+	 int from, int to)
+{
+  int	x, y, row, col;
+
+  for (y = from; y <= to; y++) {
+    col = colOrder[y];
+    fprintf(vis_stdout, "[%d]%d :", y, col);
+    for (x = 0; x < nRows; x++) {
+      row = rowOrder[x];
+      if (xy[row][col])
+	fprintf(vis_stdout, " %d(%d)", x, row);
+    }
+    fprintf(vis_stdout, "\n");
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates a list for sorting.]
+
+  Description [Allocates a list for sorting.]
+
+  SideEffects []
+
+******************************************************************************/
+static RcListInfo_t *
+SortedListAlloc(void)
+{
+  RcListInfo_t	*listInfo;
+
+  listInfo = ALLOC(RcListInfo_t, 1);
+  memset(listInfo, 0, sizeof(RcListInfo_t));
+  listInfo->table = st_init_table(st_numcmp, st_numhash);
+  return(listInfo);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a list used for sorting.]
+
+  Description [Frees a list used for sorting.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+SortedListFree(RcListInfo_t *candList)
+{
+  RcList_t	*candidate, *next;
+
+  candidate = candList->head;
+  while (candidate) {
+    next = candidate->next;
+    FREE(candidate);
+    candidate = next;
+  }
+  st_free_table(candList->table);
+  FREE(candList);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts a list to the sorting list.]
+
+  Description [Inserts a list to the sorting list.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+SortedListInsert(RcListInfo_t *candList, int index,
+		 int otherIndex, RcInfo_t *otherInfo, int method)
+{
+  RcList_t	*candidate, *cur;
+  int		lNum, gNum, diffH, diffT;
+
+  candidate = ALLOC(RcList_t, 1);
+  candidate->index = index;
+  candidate->otherIndex = otherIndex;
+  st_insert(candList->table, (char *)(long)index, (char *)candidate);
+
+  if (candList->num == 0) {
+    candidate->next = NIL(RcList_t);
+    candidate->prev = NIL(RcList_t);
+    candList->cur = candidate;
+    candList->head = candidate;
+    candList->tail = candidate;
+    candList->num = 1;
+    candList->maxNum = 1;
+    return;
+  }
+
+  candList->num++;
+  if (candList->num > candList->maxNum)
+    candList->maxNum = candList->num;
+
+  if (method == 1) {
+    diffH = abs(index - candList->head->index);
+    diffT = abs(index - candList->tail->index);
+
+    if (diffH < diffT) {
+      cur = candList->head;
+      while (cur) {
+	if (index < cur->index) {
+	  candidate->next = cur;
+	  candidate->prev = cur->prev;
+	  if (cur->prev)
+	    cur->prev->next = candidate;
+	  cur->prev = candidate;
+	  if (cur == candList->head)
+	    candList->head = candidate;
+	  break;
+	}
+	cur = cur->next;
+      }
+      if (!cur) {
+	candidate->next = NIL(RcList_t);
+	candidate->prev = candList->tail;
+	candList->tail->next = candidate;
+	candList->tail = candidate;
+      }
+    } else {
+      cur = candList->tail;
+      while (cur) {
+	if (index > cur->index) {
+	  candidate->next = cur->next;
+	  if (cur->next)
+	    cur->next->prev = candidate;
+	  candidate->prev = cur;
+	  cur->next = candidate;
+	  if (cur == candList->tail)
+	    candList->tail = candidate;
+	  break;
+	}
+	cur = cur->prev;
+      }
+      if (!cur) {
+	candidate->next = candList->head;
+	candidate->prev = NIL(RcList_t);
+	candList->head->prev = candidate;
+	candList->head = candidate;
+      }
+    }
+
+    if (candList->cur) {
+      if (candList->cur->index == candList->curIndex)
+	return;
+      else if (candList->cur->index > candList->curIndex) {
+	cur = candList->cur->prev;
+	while (cur) {
+	  if (cur->index <= candList->curIndex)
+	    break;
+	  candList->cur = cur;
+	  cur = cur->prev;
+	}
+      } else {
+	if (candidate->index > candList->curIndex)
+	  candList->cur = candidate;
+	else
+	  candList->cur = candList->head;
+      }
+    } else
+      candList->cur = candList->head;
+  } else if (method == 2) {
+    lNum = otherInfo[otherIndex].lNum;
+    gNum = otherInfo[otherIndex].gNum;
+    diffH = abs(lNum - otherInfo[candList->head->otherIndex].lNum);
+    diffT = abs(lNum - otherInfo[candList->tail->otherIndex].lNum);
+
+    if (diffH < diffT) {
+      cur = candList->head;
+      while (cur) {
+	if (lNum < otherInfo[cur->otherIndex].lNum ||
+	    (lNum == otherInfo[cur->otherIndex].lNum &&
+	     (gNum < otherInfo[cur->otherIndex].gNum ||
+	      (gNum == otherInfo[cur->otherIndex].gNum &&
+		index < cur->index)))) {
+	  candidate->next = cur;
+	  candidate->prev = cur->prev;
+	  if (cur->prev)
+	    cur->prev->next = candidate;
+	  cur->prev = candidate;
+	  if (cur == candList->head)
+	    candList->head = candidate;
+	  break;
+	}
+	cur = cur->next;
+      }
+      if (!cur) {
+	candidate->next = NIL(RcList_t);
+	candidate->prev = candList->tail;
+	candList->tail->next = candidate;
+	candList->tail = candidate;
+      }
+    } else {
+      cur = candList->tail;
+      while (cur) {
+	if (lNum > otherInfo[cur->otherIndex].lNum ||
+	    (lNum == otherInfo[cur->otherIndex].lNum &&
+	     (gNum > otherInfo[cur->otherIndex].gNum ||
+	      (gNum == otherInfo[cur->otherIndex].gNum &&
+		index > cur->index)))) {
+	  candidate->next = cur->next;
+	  if (cur->next)
+	    cur->next->prev = candidate;
+	  candidate->prev = cur;
+	  cur->next = candidate;
+	  if (cur == candList->tail)
+	    candList->tail = candidate;
+	  break;
+	}
+	cur = cur->prev;
+      }
+      if (!cur) {
+	candidate->next = candList->head;
+	candidate->prev = NIL(RcList_t);
+	candList->head->prev = candidate;
+	candList->head = candidate;
+      }
+    }
+  } else if (method == 3) {
+    lNum = otherInfo[otherIndex].lNum;
+    gNum = otherInfo[otherIndex].gNum;
+    diffH = abs(lNum - otherInfo[candList->head->otherIndex].lNum);
+    diffT = abs(lNum - otherInfo[candList->tail->otherIndex].lNum);
+
+    if (diffH < diffT) {
+      cur = candList->head;
+      while (cur) {
+	if (lNum < otherInfo[cur->otherIndex].lNum ||
+	    (lNum == otherInfo[cur->otherIndex].lNum &&
+	     (gNum > otherInfo[cur->otherIndex].gNum ||
+	      (gNum == otherInfo[cur->otherIndex].gNum &&
+		otherInfo[index].pos < otherInfo[cur->index].pos)))) {
+	  candidate->next = cur;
+	  candidate->prev = cur->prev;
+	  if (cur->prev)
+	    cur->prev->next = candidate;
+	  cur->prev = candidate;
+	  if (cur == candList->head)
+	    candList->head = candidate;
+	  break;
+	}
+	cur = cur->next;
+      }
+      if (!cur) {
+	candidate->next = NIL(RcList_t);
+	candidate->prev = candList->tail;
+	candList->tail->next = candidate;
+	candList->tail = candidate;
+      }
+    } else {
+      cur = candList->tail;
+      while (cur) {
+	if (lNum > otherInfo[cur->otherIndex].lNum ||
+	    (lNum == otherInfo[cur->otherIndex].lNum &&
+	     (gNum < otherInfo[cur->otherIndex].gNum ||
+	      (gNum == otherInfo[cur->otherIndex].gNum &&
+		otherInfo[index].pos > otherInfo[cur->index].pos)))) {
+	  candidate->next = cur->next;
+	  if (cur->next)
+	    cur->next->prev = candidate;
+	  candidate->prev = cur;
+	  cur->next = candidate;
+	  if (cur == candList->tail)
+	    candList->tail = candidate;
+	  break;
+	}
+	cur = cur->prev;
+      }
+      if (!cur) {
+	candidate->next = candList->head;
+	candidate->prev = NIL(RcList_t);
+	candList->head->prev = candidate;
+	candList->head = candidate;
+      }
+    }
+  } else if (method == 4) {
+    lNum = otherInfo[index].lNum;
+    cur = candList->tail;
+    while (cur) {
+      if (cur->otherIndex > 1 ||
+	  (cur->otherIndex == 1 && otherInfo[cur->index].lNum > lNum) ||
+	  (cur->otherIndex == 1 && otherInfo[cur->index].lNum == lNum &&
+	   otherInfo[index].pos > otherInfo[cur->index].pos)) {
+	candidate->next = cur->next;
+	if (cur->next)
+	  cur->next->prev = candidate;
+	candidate->prev = cur;
+	cur->next = candidate;
+	if (cur == candList->tail)
+	  candList->tail = candidate;
+	break;
+      }
+      cur = cur->prev;
+    }
+    if (!cur) {
+      candidate->next = candList->head;
+      candidate->prev = NIL(RcList_t);
+      candList->head->prev = candidate;
+      candList->head = candidate;
+    }
+  } else {
+    fprintf(vis_stderr, "** mlp error: invalid sort mode %d\n", method);
+  }
+
+  candList->cur = candList->head;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Deletes a list from the sorting list.]
+
+  Description [Deletes a list from the sorting list.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+SortedListDelete(RcListInfo_t *candList, int index)
+{
+  RcList_t	*candidate;
+  long		lindex = (long) index;
+
+  if (st_lookup(candList->table, (char *)lindex, &candidate)) {
+    if (candidate == candList->head)
+      candList->head = candidate->next;
+    else
+      candidate->prev->next = candidate->next;
+    if (candidate == candList->tail)
+      candList->tail = candidate->prev;
+    else
+      candidate->next->prev = candidate->prev;
+    if (candidate == candList->cur) {
+      if (candidate->next)
+	candList->cur = candidate->next;
+      else
+	candList->cur = candList->head;
+    }
+    st_delete(candList->table, &lindex, NULL);
+    candList->num--;
+    FREE(candidate);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Moves a list in the sorting list.]
+
+  Description [Moves a list in the sorting list.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+SortedListMove(RcListInfo_t *candList, RcInfo_t *info, int index, int method)
+{
+  RcList_t	*cur, *prev, *left, *right;
+
+  if (st_lookup(candList->table, (char *)(long)index, &cur)) {
+    if (method == 1) {
+    } else if (method == 2) {
+    } else if (method == 3) {
+      while (cur != candList->head) {
+	prev = cur->prev;
+	if (info[prev->index].lNum < info[cur->index].lNum ||
+	    (info[prev->index].lNum == info[cur->index].lNum &&
+	     (info[prev->index].gNum > info[cur->index].gNum ||
+	      (info[prev->index].gNum == info[cur->index].gNum &&
+		info[prev->index].pos < info[cur->index].pos)))) {
+	  break;
+	}
+
+	/* swap */
+	if (prev == candList->head)
+	  candList->head = cur;
+	if (cur == candList->tail)
+	  candList->tail = prev;
+	left = prev->prev;
+	right = cur->next;
+	if (left)
+	  left->next = cur;
+	cur->next = prev;
+	prev->next = right;
+	if (right)
+	  right->prev = prev;
+	prev->prev = cur;
+	cur->prev = left;
+      }
+    } else if (method == 4) {
+      while (cur != candList->head) {
+	prev = cur->prev;
+	if (prev->otherIndex > cur->otherIndex ||
+	    (prev->otherIndex == cur->otherIndex &&
+	     (info[prev->index].lNum > info[cur->index].lNum ||
+	      (info[prev->index].lNum == info[cur->index].lNum &&
+		info[prev->index].pos < info[cur->index].pos)))) {
+	  break;
+	}
+
+	/* swap */
+	if (prev == candList->head)
+	  candList->head = cur;
+	if (cur == candList->tail)
+	  candList->tail = prev;
+	left = prev->prev;
+	right = cur->next;
+	if (left)
+	  left->next = cur;
+	cur->next = prev;
+	prev->next = right;
+	if (right)
+	  right->prev = prev;
+	prev->prev = cur;
+	cur->prev = left;
+      }
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks the sorting list for sanity.]
+
+  Description [Checks the sorting list for sanity.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+CheckSortedList(RcListInfo_t *candList, RcInfo_t *info, int method)
+{
+  RcList_t	*cur, *next, *candidate;
+  int		error = 0;
+  int		num = 0;
+
+  cur = candList->head;
+  while (cur) {
+    num++;
+    next = cur->next;
+    if (next) {
+      if (next->prev != cur) {
+	error++;
+	if (next->prev) {
+	  fprintf(vis_stderr, "Error : prev of %d is not %d (!= %d) in list\n",
+		 next->index, cur->index, next->prev->index);
+	} else {
+	  fprintf(vis_stderr, "Error : prev of %d is not %d (!= nil) in list\n",
+		 next->index, cur->index);
+	}
+      }
+      if (method == 1) {
+      } else if (method == 2) {
+      } else if (method == 3) {
+	if (info[cur->index].lNum > info[next->index].lNum) {
+	  error++;
+	  fprintf(vis_stderr,
+		  "Error : cur(%d) lNum(%d) > next(%d) lNum(%d) in row list\n",
+		  cur->index, info[cur->index].lNum,
+		  next->index, info[next->index].lNum);
+	} else if (info[cur->index].lNum == info[next->index].lNum &&
+		   info[cur->index].gNum < info[next->index].gNum) {
+	  error++;
+	  fprintf(vis_stderr,
+		  "Error : cur(%d) gNum(%d) < next(%d) gNum(%d) in row list\n",
+		  cur->index, info[cur->index].gNum,
+		  next->index, info[next->index].gNum);
+	} else if (info[cur->index].lNum == info[next->index].lNum &&
+		   info[cur->index].gNum == info[next->index].gNum &&
+		   info[cur->index].pos > info[next->index].pos) {
+	  error++;
+	  fprintf(vis_stderr,
+		  "Error : cur(%d) pos(%d) > next(%d) pos(%d) in row list\n",
+		  cur->index, info[cur->index].pos,
+		  next->index, info[next->index].pos);
+	}
+      } else if (method == 4) {
+	if (cur->otherIndex < next->otherIndex) {
+	  error++;
+	  fprintf(vis_stderr, 
+	      "Error : cur(%d) length(%d) < next(%d) length(%d) in col list\n",
+		  cur->index, cur->otherIndex, next->index, next->otherIndex);
+	} else if (cur->otherIndex == next->otherIndex &&
+		   info[cur->index].lNum < info[next->index].lNum) {
+	  error++;
+	  fprintf(vis_stderr,
+		  "Error : cur(%d) lNum(%d) < next(%d) lNum(%d) in col list\n",
+		  cur->index, info[cur->index].lNum,
+		  next->index, info[next->index].lNum);
+	} else if (cur->otherIndex == next->otherIndex &&
+		   info[cur->index].lNum == info[next->index].lNum &&
+		   info[cur->index].pos > info[next->index].pos) {
+	  error++;
+	  fprintf(vis_stderr,
+		  "Error : cur(%d) pos(%d) > next(%d) pos(%d) in col list\n",
+		  cur->index, info[cur->index].pos,
+		  next->index, info[next->index].pos);
+	}
+      }
+    } else {
+      if (cur != candList->tail) {
+	error++;
+	if (candList->tail) {
+	  fprintf(vis_stderr, "Error : different tail in list (%d != %d)\n",
+		 cur->index, candList->tail->index);
+	} else {
+	  fprintf(vis_stderr, "Error : different tail in list (%d != nil)\n",
+		cur->index);
+	}
+      }
+    }
+    if (!st_lookup(candList->table, (char *)(long)cur->index, &candidate)) {
+      error++;
+      fprintf(vis_stderr, "Error : index %d not in table\n", cur->index);
+    }
+    cur = next;
+  }
+  if (num != candList->num) {
+    error++;
+    fprintf(vis_stderr,
+	    "Error : different number of elements in list (%d != %d)\n",
+	    num, candList->num);
+  }
+  if (num != st_count(candList->table)) {
+    error++;
+    fprintf(vis_stderr,
+	    "Error : different number of elements in table (%d != %d)\n",
+	    num, st_count(candList->table));
+  }
+  assert(!error);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Clusters on the ordered bits.]
+
+  Description [Clusters on the ordered bits.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+MlpCluster(mdd_manager *mddManager, char **xy, int nRows, int nCols,
+		int nActiveRows, int nActiveCols,
+		int *nClusterRows, int *nClusterCols,
+		int *rowOrder, int *colOrder,
+		RcInfo_t *rowInfo, RcInfo_t *colInfo,
+		array_t *clusterArray, array_t *arraySmoothVarBddArray,
+		Img_DirectionType direction, int *cRowOrder,
+		array_t *nsVarBddArray, int *sccBorder,
+		int *varPos, ImgTrmOption_t *option)
+{
+  int			i, j, row, col;
+  int			ncRows, ncCols;
+  int			index, qVarPos;
+  int			s1, t1, s2;
+  array_t		*smoothVarBddArray;
+  mdd_t			*nsVar, *relation, *cluster, *tempCluster;
+  ClusterList_t		*list, *headCluster, *tailCluster, *nextList, *prevList;
+  ClusterSortedList_t	*clusterSortedList;
+  long			initialTime, finalTime;
+  int			moveFlag = 1;
+  array_t		*nonAppearingVarBddArray;
+  char			*existFlag;
+  array_t		*supportArray, *tmpArray;
+  int			nVars = bdd_num_vars(mddManager);
+  mdd_t			*one;
+
+  if (option->mlpVerbosity)
+    initialTime = util_cpu_time();
+  else
+    initialTime = 0;
+
+  ncCols = nActiveCols;
+  headCluster = NIL(ClusterList_t);
+  tailCluster = NIL(ClusterList_t);
+  clusterSortedList = NIL(ClusterSortedList_t);
+  if (option->mlpCluster == 0) {
+    if (direction == Img_Forward_c) {
+      for (i = nActiveRows - 1; i >= 0;) {
+	row = rowOrder[i];
+
+	list = ALLOC(ClusterList_t, 1);
+	memset(list, 0, sizeof(ClusterList_t));
+	list->flag = 3;
+	list->start = i;
+	list->end = i;
+	list->supports = ALLOC(char, nCols);
+	memcpy(list->supports, xy[row], sizeof(char) * nCols);
+	list->minCol = rowInfo[row].gMin;
+	list->maxCol = rowInfo[row].gMax;
+	list->nSupports = MlpCountSupport(list, colOrder, ncCols);
+	list->product = bdd_dup(rowInfo[row].data.row.func);
+	list->nQuantifyVars = 0;
+	list->affinity = 0.0;
+	if (rowInfo[row].data.row.nsVarBddArray)
+	  list->nsVarBddArray = array_dup(rowInfo[row].data.row.nsVarBddArray);
+	else
+	  list->nsVarBddArray = NIL(array_t);
+
+	if (headCluster)
+	  tailCluster->next = list;
+	else
+	  headCluster = list;
+	list->next = NIL(ClusterList_t);
+	list->prev = tailCluster;
+	tailCluster = list;
+
+	i--;
+
+	if (sccBorder && sccBorder[i + 1] == 1)
+	  continue;
+	if (bdd_size(list->product) >= option->clusterSize)
+	  continue;
+
+	while (i >= 0) {
+	  row = rowOrder[i];
+	  relation = rowInfo[row].data.row.func;
+	  if (bdd_size(list->product) >= option->clusterSize)
+	    break;
+	  cluster = bdd_and(list->product, relation, 1, 1);
+	  if (bdd_size(cluster) <= option->clusterSize) {
+	    mdd_free(list->product);
+	    list->product = cluster;
+	    list->start = i;
+
+	    if (list->nsVarBddArray) {
+	      array_append(list->nsVarBddArray,
+		rowInfo[row].data.row.nsVarBddArray);
+	    }
+
+	    list->nSupports = 0;
+	    list->minCol = nActiveCols;
+	    list->maxCol = -1;
+	    s1 = nActiveCols;
+	    t1 = -1;
+	    supportArray = mdd_get_bdd_support_ids(mddManager, list->product);
+	    for (j = 0; j < array_n(supportArray); j++) {
+	      index = array_fetch(int, supportArray, j);
+	      if (varPos[index] == 0) {
+		if ((int)bdd_top_var_id(colInfo[0].data.col.var) != index)
+      		  continue;
+	      }
+	      index = varPos[index];
+	      list->supports[index] = 1;
+	      list->nSupports++;
+	      s2 = colInfo[index].pos;
+	      if (s2 < s1) {
+		s1 = s2;
+		list->minCol = index;
+	      }
+	      if (s2 > t1) {
+		t1 = s2;
+		list->maxCol = index;
+	      }
+	    }
+	    array_free(supportArray);
+
+	    i--;
+	    if (option->mlpDebug)
+	      CheckCluster(headCluster, ncCols, colInfo, colOrder);
+	  } else {
+	    mdd_free(cluster);
+	    break;
+	  }
+	}
+
+	ncCols = RemoveLocalVarsInCluster(mddManager, xy,
+					    list, nActiveRows, ncCols,
+					    rowInfo, colInfo,
+					    rowOrder, colOrder,
+					    moveFlag, option);
+      }
+    } else {
+      for (i = 0; i < nActiveRows;) {
+	row = rowOrder[i];
+
+	list = ALLOC(ClusterList_t, 1);
+	memset(list, 0, sizeof(ClusterList_t));
+	list->flag = 3;
+	list->start = i;
+	list->end = i;
+	list->supports = ALLOC(char, nCols);
+	memcpy(list->supports, xy[row], sizeof(char) * nCols);
+	list->minCol = rowInfo[row].gMin;
+	list->maxCol = rowInfo[row].gMax;
+	list->nSupports = MlpCountSupport(list, colOrder, ncCols);
+	list->product = bdd_dup(rowInfo[row].data.row.func);
+	list->nQuantifyVars = 0;
+	list->affinity = 0.0;
+	if (rowInfo[row].data.row.nsVarBddArray)
+	  list->nsVarBddArray = array_dup(rowInfo[row].data.row.nsVarBddArray);
+	else
+	  list->nsVarBddArray = NIL(array_t);
+
+	if (headCluster)
+	  tailCluster->next = list;
+	else
+	  headCluster = list;
+	list->next = NIL(ClusterList_t);
+	list->prev = tailCluster;
+	tailCluster = list;
+
+	i++;
+
+	if (sccBorder && sccBorder[i - 1] == 2)
+	  continue;
+	if (bdd_size(list->product) >= option->clusterSize)
+	  continue;
+
+	while (i < nActiveRows) {
+	  row = rowOrder[i];
+	  relation = rowInfo[row].data.row.func;
+	  if (bdd_size(list->product) >= option->clusterSize)
+	    break;
+	  cluster = bdd_and(list->product, relation, 1, 1);
+	  if (bdd_size(cluster) <= option->clusterSize) {
+	    mdd_free(list->product);
+	    list->product = cluster;
+	    list->end = i;
+
+	    if (list->nsVarBddArray) {
+	      array_append(list->nsVarBddArray,
+		rowInfo[row].data.row.nsVarBddArray);
+	    }
+
+	    list->nSupports = 0;
+	    list->minCol = nActiveCols;
+	    list->maxCol = -1;
+	    s1 = nActiveCols;
+	    t1 = -1;
+	    supportArray = mdd_get_bdd_support_ids(mddManager, list->product);
+	    for (j = 0; j < array_n(supportArray); j++) {
+	      index = array_fetch(int, supportArray, j);
+	      if (varPos[index] == 0) {
+		if ((int)bdd_top_var_id(colInfo[0].data.col.var) != index)
+      		  continue;
+	      }
+	      index = varPos[index];
+	      list->supports[index] = 1;
+	      list->nSupports++;
+	      s2 = colInfo[index].pos;
+	      if (s2 < s1) {
+		s1 = s2;
+		list->minCol = index;
+	      }
+	      if (s2 > t1) {
+		t1 = s2;
+		list->maxCol = index;
+	      }
+	    }
+	    array_free(supportArray);
+
+	    i++;
+	    if (option->mlpDebug)
+	      CheckCluster(headCluster, ncCols, colInfo, colOrder);
+	  } else {
+	    mdd_free(cluster);
+	    break;
+	  }
+	}
+
+	ncCols = RemoveLocalVarsInCluster(mddManager, xy,
+					    list, nActiveRows, ncCols,
+					    rowInfo, colInfo,
+					    rowOrder, colOrder,
+					    moveFlag, option);
+      }
+    }
+  } else { /* option->mlpCluster == 1 */
+    if (direction == Img_Forward_c) {
+      for (i = 0; i < nActiveRows; i++) {
+	row = rowOrder[i];
+	list = ALLOC(ClusterList_t, 1);
+	memset(list, 0, sizeof(ClusterList_t));
+
+	if (headCluster && headCluster->flag != 3)
+	  list->flag = 1;
+	else
+	  list->flag = 2;
+	list->start = i;
+	list->end = i;
+	list->supports = ALLOC(char, nCols);
+	memcpy(list->supports, xy[row], sizeof(char) * nCols);
+	list->minCol = rowInfo[row].gMin;
+	list->maxCol = rowInfo[row].gMax;
+	list->nSupports = MlpCountSupport(list, colOrder, ncCols);
+	list->product = bdd_dup(rowInfo[row].data.row.func);
+	list->nQuantifyVars = MlpNumQuantifyVars(list, rowInfo, colInfo,
+						 colOrder, ncCols);
+	if (rowInfo[row].data.row.nsVarBddArray)
+	  list->nsVarBddArray = array_dup(rowInfo[row].data.row.nsVarBddArray);
+	else
+	  list->nsVarBddArray = NIL(array_t);
+
+	if (bdd_size(list->product) >= option->clusterSize) {
+	  if (headCluster) {
+	    ncCols = RecursiveCluster(mddManager, headCluster,
+					clusterSortedList,
+					xy, rowInfo, colInfo,
+					rowOrder, colOrder, nActiveRows, ncCols,
+					direction, varPos, moveFlag, option);
+	    if (option->mlpDebug)
+	      CheckCluster(headCluster, ncCols, colInfo, colOrder);
+	  }
+	  list->flag = 3;
+	  ncCols = RemoveLocalVarsInCluster(mddManager, xy,
+					    list, nActiveRows, ncCols,
+					    rowInfo, colInfo,
+					    rowOrder, colOrder,
+					    moveFlag, option);
+	  if (option->mlpDebug)
+	    CheckCluster(headCluster, ncCols, colInfo, colOrder);
+	  list->affinity = 0.0;
+	  clusterSortedList = NIL(ClusterSortedList_t);
+	} else if (sccBorder && i > 0 && sccBorder[i] == 1) {
+	  ncCols = RecursiveCluster(mddManager, headCluster,
+					clusterSortedList,
+					xy, rowInfo, colInfo,
+					rowOrder, colOrder, nActiveRows, ncCols,
+					direction, varPos, moveFlag, option);
+	  if (option->mlpDebug)
+	    CheckCluster(headCluster, ncCols, colInfo, colOrder);
+	  list->flag = 2;
+	  list->affinity = 0.0;
+	  clusterSortedList = NIL(ClusterSortedList_t);
+	  if (option->mlpClusterSortedList) {
+	    clusterSortedList = ClusterSortedListInsert(clusterSortedList, list,
+						option->mlpClusterQuantifyVars);
+	  }
+	} else {
+	  if (headCluster && headCluster->flag != 3) {
+	    list->affinity = MlpSupportAffinity(list, headCluster, colInfo,
+						colOrder, ncCols,
+						option->mlpCluster);
+	  } else
+	    list->affinity = 0.0;
+	  if (option->mlpClusterSortedList) {
+	    clusterSortedList = ClusterSortedListInsert(clusterSortedList, list,
+						option->mlpClusterQuantifyVars);
+	  }
+	}
+
+	list->next = headCluster;
+	list->prev = NIL(ClusterList_t);
+	if (headCluster) {
+	  if (headCluster->flag == 1)
+	    headCluster->flag = 0;
+	  headCluster->prev = list;
+	}
+	headCluster = list;
+      }
+    } else {
+      for (i = nActiveRows - 1; i >= 0; i--) {
+	row = rowOrder[i];
+	list = ALLOC(ClusterList_t, 1);
+	memset(list, 0, sizeof(ClusterList_t));
+
+	if (headCluster && headCluster->flag != 3)
+	  list->flag = 1;
+	else
+	  list->flag = 2;
+	list->start = i;
+	list->end = i;
+	list->supports = ALLOC(char, nCols);
+	memcpy(list->supports, xy[row], sizeof(char) * nCols);
+	list->minCol = rowInfo[row].gMin;
+	list->maxCol = rowInfo[row].gMax;
+	list->nSupports = MlpCountSupport(list, colOrder, ncCols);
+	list->product = bdd_dup(rowInfo[row].data.row.func);
+	list->nQuantifyVars = MlpNumQuantifyVars(list, rowInfo, colInfo,
+						 colOrder, ncCols);
+	if (rowInfo[row].data.row.nsVarBddArray)
+	  list->nsVarBddArray = array_dup(rowInfo[row].data.row.nsVarBddArray);
+	else
+	  list->nsVarBddArray = NIL(array_t);
+
+	if ( bdd_size(list->product) >= option->clusterSize) {
+	  if (headCluster) {
+	    ncCols = RecursiveCluster(mddManager, headCluster,
+					clusterSortedList,
+					xy, rowInfo, colInfo,
+					rowOrder, colOrder, nActiveRows, ncCols,
+					direction, varPos, moveFlag, option);
+	    if (option->mlpDebug)
+	      CheckCluster(headCluster, ncCols, colInfo, colOrder);
+	  }
+	  list->flag = 3;
+	  ncCols = RemoveLocalVarsInCluster(mddManager, xy,
+					    list, nActiveRows, ncCols,
+					    rowInfo, colInfo,
+					    rowOrder, colOrder,
+					    moveFlag, option);
+	  if (option->mlpDebug)
+	    CheckCluster(headCluster, ncCols, colInfo, colOrder);
+	  list->affinity = 0.0;
+	  clusterSortedList = NIL(ClusterSortedList_t);
+	} else if (sccBorder && i < (nActiveRows - 1) && sccBorder[i] == 2) {
+	  ncCols = RecursiveCluster(mddManager, headCluster,
+					clusterSortedList,
+					xy, rowInfo, colInfo,
+					rowOrder, colOrder, nActiveRows, ncCols,
+					direction, varPos, moveFlag, option);
+	  if (option->mlpDebug)
+	    CheckCluster(headCluster, ncCols, colInfo, colOrder);
+	  list->flag = 2;
+	  list->affinity = 0.0;
+	  clusterSortedList = NIL(ClusterSortedList_t);
+	  if (option->mlpClusterSortedList) {
+	    clusterSortedList = ClusterSortedListInsert(clusterSortedList, list,
+						option->mlpClusterQuantifyVars);
+	  }
+	} else {
+	  if (headCluster && headCluster->flag != 3) {
+	    list->affinity = MlpSupportAffinity(list, headCluster, colInfo,
+						colOrder, ncCols,
+						option->mlpCluster);
+	  } else
+	    list->affinity = 0.0;
+	  if (option->mlpClusterSortedList) {
+	    clusterSortedList = ClusterSortedListInsert(clusterSortedList, list,
+						option->mlpClusterQuantifyVars);
+	  }
+	}
+
+	list->next = headCluster;
+	list->prev = NIL(ClusterList_t);
+	if (headCluster) {
+	  if (headCluster->flag == 1)
+	    headCluster->flag = 0;
+	  headCluster->prev = list;
+	}
+	headCluster = list;
+
+	if (option->mlpClusterSortedList && option->mlpDebug) {
+	  int	n1, n2;
+
+	  n1 = CountClusterList(headCluster);
+	  n2 = CountClusterSortedList(clusterSortedList);
+	  assert(n1 == n2);
+	}
+      }
+    }
+
+    if (headCluster->flag == 1) {
+      ncCols = RecursiveCluster(mddManager, headCluster, clusterSortedList,
+				xy, rowInfo, colInfo,
+				rowOrder, colOrder, nActiveRows, ncCols,
+				direction, varPos, moveFlag, option);
+      if (option->mlpDebug)
+	CheckCluster(headCluster, ncCols, colInfo, colOrder);
+    }
+  }
+
+  list = headCluster;
+  one = bdd_one(mddManager);
+  while (list) {
+    if (bdd_equal(list->product, one)) {
+      assert(list->nSupports == 0);
+
+      prevList = list->prev;
+      nextList = list->next;
+      if ((!prevList) && (!nextList)) /* unity relation */
+	break;
+
+      mdd_free(list->product);
+      if (list->nsVarBddArray)
+	array_free(list->nsVarBddArray);
+      FREE(list->supports);
+
+      if (nextList) {
+	if (list->start < nextList->start)
+	  nextList->start = list->start;
+	if (list->end > nextList->end)
+	  nextList->end = list->end;
+
+	if (list == headCluster)
+	  headCluster = nextList;
+
+	FREE(list);
+      } else {
+	if (list->start < prevList->start)
+	  prevList->start = list->start;
+	if (list->end > prevList->end)
+	  prevList->end = list->end;
+	FREE(list);
+      }
+      if (prevList)
+	prevList->next = nextList;
+      if (nextList)
+	nextList->prev = prevList;
+      list = nextList;
+      continue;
+    }
+    list = list->next;
+  }
+  bdd_free(one);
+
+  if (option->mlpVerbosity >= 3 && option->mlpPrintMatrix) {
+    PrintMatrixWithCluster(xy, headCluster, ncCols, rowOrder, colOrder,
+			   direction);
+    fprintf(vis_stdout, "******** cluster matrix ************\n");
+    PrintClusterMatrix(headCluster, ncCols, colOrder, direction);
+  }
+  if (option->mlpDebug)
+    CheckCluster(headCluster, ncCols, colInfo, colOrder);
+
+  ncRows = 0;
+  nonAppearingVarBddArray = NIL(array_t);
+  if ((direction == Img_Forward_c && option->mlpReorder) ||
+      (direction == Img_Backward_c && option->mlpPreReorder) ||
+      option->mlpPostProcess >= 2) {
+    list = headCluster;
+    while (list) {
+      row = rowOrder[ncRows];
+
+      mdd_free(rowInfo[row].data.row.func);
+      rowInfo[row].data.row.func = list->product;
+      list->product = NIL(mdd_t);
+
+      if (xy[row])
+	FREE(xy[row]);
+      xy[row] = list->supports;
+      list->supports = NIL(char);
+
+      rowInfo[row].gNum = list->nSupports;
+      rowInfo[row].gMin = list->minCol;
+      rowInfo[row].gMax = list->maxCol;
+      rowInfo[row].lNum = list->nSupports;
+      rowInfo[row].lMin = list->minCol;
+      rowInfo[row].lMax = list->maxCol;
+      rowInfo[row].prevG = -1;
+      rowInfo[row].nextG = ncCols;
+
+      if (list->nsVarBddArray) {
+	if (rowInfo[row].data.row.nsVarBddArray)
+	  array_free(rowInfo[row].data.row.nsVarBddArray);
+	rowInfo[row].data.row.nsVarBddArray = list->nsVarBddArray;
+	list->nsVarBddArray = NIL(array_t);
+      }
+
+      nextList = list->next;
+      FREE(list);
+      ncRows++;
+      list = nextList;
+    }
+
+    if (direction == Img_Forward_c) {
+      for (i = 0; i < ncRows; i++) {
+	cRowOrder[i] = rowOrder[ncRows - i - 1];
+	rowInfo[rowOrder[ncRows - i - 1]].pos = i;
+      }
+    } else {
+      for (i = 0; i < ncRows; i++) {
+	cRowOrder[i] = rowOrder[i];
+	rowInfo[rowOrder[i]].pos = i;
+      }
+    }
+
+    for (j = 0; j < ncCols; j++) {
+      col = colOrder[j];
+      colInfo[col].gNum = 0;
+      colInfo[col].gMin = ncRows;
+      colInfo[col].gMax = -1;
+      for (i = 0; i < ncRows; i++) {
+	row = cRowOrder[i];
+	if (xy[row][col]) {
+	  colInfo[col].gNum++;
+	  if (colInfo[col].gMin == ncRows)
+	    colInfo[col].gMin = row;
+	  colInfo[col].gMax = row;
+	}
+      }
+      colInfo[col].lNum = colInfo[col].gNum;
+      colInfo[col].lMin = colInfo[col].gMin;
+      colInfo[col].lMax = colInfo[col].gMax;
+      colInfo[col].prevG = -1;
+      colInfo[col].nextG = ncRows;
+    }
+  } else {
+    if (direction == Img_Forward_c) {
+      if (arraySmoothVarBddArray) {
+	nonAppearingVarBddArray = array_fetch(array_t *,
+					      arraySmoothVarBddArray, 0);
+	if (nCols > ncCols) {
+	  existFlag = ALLOC(char, nVars);
+	  memset(existFlag, 0, sizeof(char) * nVars);
+
+	  for (i = 0; i < array_n(nonAppearingVarBddArray); i++) {
+	    nsVar = array_fetch(bdd_t *, nonAppearingVarBddArray, i);
+	    index = (int)bdd_top_var_id(nsVar);
+	    existFlag[index] = 1;
+	  }
+
+	  for (i = ncCols; i < nCols; i++) {
+	    col = colOrder[i];
+	    index = (int)bdd_top_var_id(colInfo[col].data.col.var);
+	    if (!existFlag[index]) {
+	      array_insert_last(bdd_t *, nonAppearingVarBddArray,
+				bdd_dup(colInfo[col].data.col.var));
+	    }
+	  }
+
+	  FREE(existFlag);
+	}
+	qVarPos = ncCols - 1;
+	if (qVarPos >= 0) {
+	  col = colOrder[qVarPos];
+	  while (colInfo[col].gNum == 0) {
+	    array_insert_last(bdd_t *, nonAppearingVarBddArray,
+				bdd_dup(colInfo[col].data.col.var));
+	    if (qVarPos == 0)
+	      break;
+	    qVarPos--;
+	    col = colOrder[qVarPos];
+	  }
+	}
+      } else
+	qVarPos = 0; /* to avoid warning */
+    } else {
+      if (arraySmoothVarBddArray) {
+	nonAppearingVarBddArray = array_fetch(array_t *,
+						arraySmoothVarBddArray, 0);
+	if (nCols > ncCols) {
+	  for (i = ncCols; i < nCols; i++) {
+	    col = colOrder[i];
+	    if (colInfo[col].data.col.type == 2) {
+	      array_insert_last(bdd_t *, nonAppearingVarBddArray,
+				bdd_dup(colInfo[col].data.col.var));
+	    }
+	  }
+	}
+	qVarPos = ncCols - 1;
+	if (qVarPos >= 0) {
+	  col = colOrder[qVarPos];
+	  while (colInfo[col].gNum == 0) {
+	    if (colInfo[col].data.col.type == 2) {
+	      array_insert_last(bdd_t *, nonAppearingVarBddArray,
+				bdd_dup(colInfo[col].data.col.var));
+	    }
+	    if (qVarPos == 0)
+	      break;
+	    qVarPos--;
+	    col = colOrder[qVarPos];
+	  }
+	}
+
+	existFlag = ALLOC(char, nVars);
+	memset(existFlag, 0, sizeof(char) * nVars);
+
+	for (i = 0; i < array_n(nonAppearingVarBddArray); i++) {
+	  nsVar = array_fetch(bdd_t *, nonAppearingVarBddArray, i);
+	  index = (int)bdd_top_var_id(nsVar);
+	  existFlag[index] = 1;
+	}
+
+	if (nRows > nActiveRows) {
+	  for (i = nActiveRows; i < nRows; i++) {
+	    row = rowOrder[i];
+	    tmpArray = rowInfo[row].data.row.nsVarBddArray;
+	    for (j = 0; j < array_n(tmpArray); j++) {
+	      nsVar = array_fetch(bdd_t *, tmpArray, j);
+	      index = (int)bdd_top_var_id(nsVar);
+	      existFlag[index] = 1;
+	    }
+	  }
+	}
+
+	list = headCluster;
+	while (list) {
+	  supportArray = mdd_get_bdd_support_ids(mddManager, list->product);
+	  for (i = 0; i < array_n(supportArray); i++) {
+	    index = array_fetch(int, supportArray, i);
+	    existFlag[index] = 1;
+	  }
+	  array_free(supportArray);
+	  list = list->next;
+	}
+
+	list = headCluster;
+	while (list) {
+	  for (i = 0; i < array_n(list->nsVarBddArray); i++) {
+	    nsVar = array_fetch(bdd_t *, list->nsVarBddArray, i);
+	    index = (int)bdd_top_var_id(nsVar);
+	    if (!existFlag[index]) {
+	      tmpArray = array_alloc(mdd_t *, 0);
+	      for (j = 0; j < i; j++) {
+		nsVar = array_fetch(bdd_t *, list->nsVarBddArray, j);
+		array_insert_last(mdd_t *, tmpArray, nsVar);
+	      }
+	      for (j = i + 1; j < array_n(list->nsVarBddArray); j++) {
+		nsVar = array_fetch(bdd_t *, list->nsVarBddArray, j);
+		index = (int)bdd_top_var_id(nsVar);
+		if (existFlag[index])
+		  array_insert_last(mdd_t *, tmpArray, nsVar);
+	      }
+	      array_free(list->nsVarBddArray);
+	      list->nsVarBddArray = tmpArray;
+	      break;
+	    }
+	  }
+	  list = list->next;
+	}
+
+	for (i = 0; i < array_n(nsVarBddArray); i++) {
+	  nsVar = array_fetch(bdd_t *, nsVarBddArray, i);
+	  index = (int)bdd_top_var_id(nsVar);
+	  if (!existFlag[index])
+	    array_insert_last(mdd_t *, nonAppearingVarBddArray, bdd_dup(nsVar));
+	}
+
+	FREE(existFlag);
+      } else
+	qVarPos = 0; /* to avoid warning */
+    }
+
+    if (direction == Img_Backward_c && nRows > nActiveRows) {
+      cluster = bdd_one(mddManager);
+      if (arraySmoothVarBddArray)
+	smoothVarBddArray = array_alloc(array_t *, 0);
+      else
+	smoothVarBddArray = NIL(array_t);
+      for (i = nActiveRows; i < nRows; i++) {
+	row = rowOrder[i];
+	relation = rowInfo[row].data.row.func;
+	if (bdd_is_tautology(relation, 1))
+	  continue;
+	if (smoothVarBddArray) {
+	  tmpArray = rowInfo[row].data.row.nsVarBddArray;
+	  for (j = 0; j < array_n(tmpArray); j++) {
+	    nsVar = array_fetch(bdd_t *, tmpArray, j);
+	    array_insert_last(mdd_t *, smoothVarBddArray, bdd_dup(nsVar));
+	  }
+	}
+	tempCluster = bdd_and(cluster, relation, 1, 1);
+	bdd_free(cluster);
+	cluster = tempCluster;
+      }
+      if (bdd_is_tautology(cluster, 1)) {
+	mdd_free(cluster);
+	if (smoothVarBddArray)
+	  mdd_array_free(smoothVarBddArray);
+      } else {
+	array_insert_last(bdd_t *, clusterArray, cluster);
+	if (arraySmoothVarBddArray) {
+	  array_insert_last(array_t *, arraySmoothVarBddArray,
+			    smoothVarBddArray);
+	}
+	ncRows++;
+      }
+    }
+
+    list = headCluster;
+    while (list) {
+      array_insert_last(mdd_t *, clusterArray, list->product);
+      list->product = NIL(mdd_t);
+
+      if (arraySmoothVarBddArray) {
+	if (direction == Img_Forward_c) {
+	  smoothVarBddArray = array_alloc(array_t *, 0);
+	  if (qVarPos >= 0) {
+	    col = colOrder[qVarPos];
+	    while (rowInfo[colInfo[col].gMin].pos >= list->start &&
+		   rowInfo[colInfo[col].gMin].pos <= list->end) {
+	      array_insert_last(bdd_t *, smoothVarBddArray,
+				bdd_dup(colInfo[col].data.col.var));
+	      if (qVarPos == 0)
+		break;
+	      qVarPos--;
+	      col = colOrder[qVarPos];
+	    }
+	  }
+	  array_insert_last(array_t *, arraySmoothVarBddArray,
+			    smoothVarBddArray);
+	} else {
+	  smoothVarBddArray = array_alloc(array_t *, 0);
+	  for (i = 0; i < array_n(list->nsVarBddArray); i++) {
+	    nsVar = array_fetch(bdd_t *, list->nsVarBddArray, i);
+	    array_insert_last(bdd_t *, smoothVarBddArray, bdd_dup(nsVar));
+	  }
+
+	  if (list->nSupports > 0) {
+	    s1 = colInfo[list->minCol].pos;
+	    t1 = colInfo[list->maxCol].pos;
+	    for (i = s1; i <= t1; i++) {
+	      col = colOrder[i];
+	      if (colInfo[col].data.col.type == 2) {
+		if (rowInfo[colInfo[col].gMax].pos >= list->start &&
+		    rowInfo[colInfo[col].gMax].pos <= list->end) {
+		  array_insert_last(bdd_t *, smoothVarBddArray,
+				    bdd_dup(colInfo[col].data.col.var));
+		}
+	      }
+	    }
+	  }
+	  array_insert_last(array_t *, arraySmoothVarBddArray,
+			    smoothVarBddArray);
+	}
+      }
+
+      nextList = list->next;
+      if (list->nsVarBddArray)
+	array_free(list->nsVarBddArray);
+      FREE(list->supports);
+      FREE(list);
+      ncRows++;
+      list = nextList;
+    }
+
+    if (direction == Img_Forward_c && nRows > nActiveRows) {
+      cluster = bdd_one(mddManager);
+      for (i = nActiveRows; i < nRows; i++) {
+	row = rowOrder[i];
+	relation = rowInfo[row].data.row.func;
+	if (bdd_is_tautology(relation, 1))
+	  continue;
+	tempCluster = bdd_and(cluster, relation, 1, 1);
+	bdd_free(cluster);
+	cluster = tempCluster;
+      }
+      if (bdd_is_tautology(cluster, 1))
+	mdd_free(cluster);
+      else {
+	array_insert_last(bdd_t *, clusterArray, cluster);
+	if (arraySmoothVarBddArray) {
+	  smoothVarBddArray = array_alloc(array_t *, 0);
+	  array_insert_last(array_t *, arraySmoothVarBddArray,
+			    smoothVarBddArray);
+	}
+	ncRows++;
+      }
+    }
+  }
+
+  *nClusterRows = ncRows;
+  *nClusterCols = ncCols;
+
+  if (option->mlpVerbosity) {
+    finalTime = util_cpu_time();
+    fprintf(vis_stdout, "time for clustering = %10g\n",
+	   (double)(finalTime - initialTime) / 1000.0);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of supports of the list.]
+
+  Description [Counts the number of supports of the list.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+MlpCountSupport(ClusterList_t *list, int *colOrder, int nActiveCols)
+{
+  int	i, col;
+  int	nSupports = 0;
+
+  for (i = 0; i < nActiveCols; i++) {
+    col = colOrder[i];
+    if (list->supports[col])
+      nSupports++;
+  }
+  return(nSupports);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the affinity of two lists.]
+
+  Description [Computes the affinity of two lists.]
+
+  SideEffects []
+
+******************************************************************************/
+static float
+MlpSupportAffinity(ClusterList_t *curList, ClusterList_t *nextList,
+		RcInfo_t *colInfo, int *colOrder,
+		int nActiveCols, int clusterMethod)
+{
+  ClusterList_t	*minList, *maxList;
+  int		i, col, s, t;
+  int		nOverlaps = 0;
+  float		affinity;
+
+  if (curList->nSupports <= nextList->nSupports) {
+    minList = curList;
+    maxList = nextList;
+  } else {
+    minList = nextList;
+    maxList = curList;
+  }
+
+  s = colInfo[minList->minCol].pos;
+  t = colInfo[minList->maxCol].pos;
+  for (i = s; i <= t; i++) {
+    col = colOrder[i];
+    if (minList->supports[col] && maxList->supports[col])
+      nOverlaps++;
+  }
+
+  if (clusterMethod == 1)
+    affinity = (float)nOverlaps / (float)minList->nSupports;
+  else {
+    affinity = (float)nOverlaps /
+		(float)(minList->nSupports + maxList->nSupports - nOverlaps);
+  }
+  return(affinity);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Clusters recursively with affinity.]
+
+  Description [Clusters recursively with affinity.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+RecursiveCluster(mdd_manager *mddManager, ClusterList_t *headCluster,
+		 ClusterSortedList_t *clusterSortedList,
+		 char **xy, RcInfo_t *rowInfo, RcInfo_t *colInfo,
+		 int *rowOrder, int *colOrder,
+		 int nActiveRows, int nClusterCols,
+		 Img_DirectionType direction, int *varPos,
+		 int moveFlag, ImgTrmOption_t *option)
+{
+  ClusterSortedList_t	*sortedList, *nextSortedList, *prevSortedList;
+  ClusterSortedList_t	*firstSortedList, *secondSortedList, *saveSortedList;
+  ClusterSortedList_t	*tailSortedList1, *tailSortedList2;
+  ClusterList_t		*list, *best;
+  int			i, n1, n2;
+  int			s1, t1, s2;
+  mdd_t			*product;
+  int			merge, index;
+  array_t		*supportArray;
+
+  if (headCluster->flag == 3)
+    return(nClusterCols);
+
+  assert(headCluster);
+  if (option->mlpClusterSortedList && option->mlpDebug) {
+    n1 = CountClusterList(headCluster);
+    n2 = CountClusterSortedList(clusterSortedList);
+    assert(n1 == n2);
+  }
+
+  if (headCluster->flag == 2) {
+    assert(!headCluster->next || headCluster->next->flag == 3);
+    headCluster->flag = 3;
+    nClusterCols = RemoveLocalVarsInCluster(mddManager, xy, headCluster,
+					    nActiveRows, nClusterCols,
+					    rowInfo, colInfo,
+					    rowOrder, colOrder,
+					    moveFlag, option);
+    if (clusterSortedList) {
+      assert(!clusterSortedList->next);
+      FREE(clusterSortedList);
+    }
+    return(nClusterCols);
+  }
+
+  merge = 0;
+  best = NIL(ClusterList_t);
+  if (option->mlpClusterMerge) {
+    /* NEED */
+  }
+
+  if (!best) {
+    if (clusterSortedList)
+      best = clusterSortedList->list;
+    else {
+      best = headCluster;
+      list = headCluster->next;
+      while (list) {
+	if (list->flag == 2)
+	  break;
+	if (option->mlpClusterQuantifyVars) {
+	  if (list->nQuantifyVars < best->nQuantifyVars ||
+	      (list->nQuantifyVars == best->nQuantifyVars &&
+	       list->affinity > best->affinity)) {
+	    best = list;
+	  }
+	} else {
+	  if (list->affinity < option->mlpAffinityThreshold) {
+	    list = list->next;
+	    continue;
+	  }
+	  if (list->affinity > best->affinity ||
+	      (list->affinity == best->affinity &&
+	       list->nQuantifyVars < best->nQuantifyVars)) {
+	    best = list;
+	  }
+	}
+	list = list->next;
+      }
+    }
+  }
+  assert(best->next && best->next->flag != 3);
+
+  list = best->next;
+  product = mdd_and(best->product, list->product, 1, 1);
+
+  if (merge == 0 && bdd_size(product) > option->clusterSize) {
+    mdd_free(product);
+
+    firstSortedList = NIL(ClusterSortedList_t);
+    secondSortedList = NIL(ClusterSortedList_t);
+    if (option->mlpClusterSortedList) {
+      tailSortedList1 = NIL(ClusterSortedList_t);
+      tailSortedList2 = NIL(ClusterSortedList_t);
+      sortedList = clusterSortedList;
+      while (sortedList) {
+	nextSortedList = sortedList->next;
+	if ((best->start > list->start &&
+	     sortedList->list->start >= best->start) ||
+	    (best->start < list->start &&
+	     sortedList->list->start <= best->start)) {
+	  if (tailSortedList1)
+	    tailSortedList1->next = sortedList;
+	  else
+	    firstSortedList = sortedList;
+	  tailSortedList1 = sortedList;
+	} else {
+	  if (tailSortedList2)
+	    tailSortedList2->next = sortedList;
+	  else
+	    secondSortedList = sortedList;
+	  tailSortedList2 = sortedList;
+	}
+	sortedList->next = NIL(ClusterSortedList_t);
+	sortedList = nextSortedList;
+      }
+    }
+
+    if (best == headCluster) {
+      best->flag = 3;
+      if (option->mlpClusterSortedList) {
+	sortedList = firstSortedList;
+	firstSortedList = firstSortedList->next;
+	FREE(sortedList);
+	assert(!firstSortedList);
+      }
+      nClusterCols = RemoveLocalVarsInCluster(mddManager, xy, best,
+						nActiveRows, nClusterCols,
+						rowInfo, colInfo,
+						rowOrder, colOrder,
+						moveFlag, option);
+    } else {
+      best->flag = 2;
+      if (option->mlpClusterSortedList) {
+	sortedList = firstSortedList;
+	prevSortedList = NIL(ClusterSortedList_t);
+	saveSortedList = NIL(ClusterSortedList_t);
+	while (sortedList) {
+	  nextSortedList = sortedList->next;
+	  if (sortedList->list == best) {
+	    if (nextSortedList) {
+	      if (prevSortedList)
+		prevSortedList->next = sortedList->next;
+	      else
+		firstSortedList = sortedList->next;
+	    }
+	    saveSortedList = sortedList;
+	    sortedList->next = NIL(ClusterSortedList_t);
+	    sortedList = nextSortedList;
+	    continue;
+	  }
+	  prevSortedList = sortedList;
+	  sortedList = nextSortedList;
+	}
+	prevSortedList->next = saveSortedList;
+      }
+      nClusterCols = RecursiveCluster(mddManager, headCluster, firstSortedList,
+					xy, rowInfo, colInfo,
+					rowOrder, colOrder,
+					nActiveRows, nClusterCols,
+					direction, varPos, moveFlag, option);
+    }
+    if (option->mlpDebug) {
+      CheckCluster(headCluster, nClusterCols, colInfo, colOrder);
+      CheckMatrix(xy, NIL(SccList_t), nActiveRows, nClusterCols,
+		    rowInfo, colInfo, rowOrder, colOrder,
+		    0, nActiveRows - 1, 0, nClusterCols - 1, 0);
+    }
+
+    if (list->flag == 0) {
+      list->flag = 1;
+      nClusterCols = RecursiveCluster(mddManager, list, secondSortedList,
+					xy, rowInfo, colInfo,
+					rowOrder, colOrder,
+					nActiveRows, nClusterCols,
+					direction, varPos, moveFlag, option);
+    } else {
+      list->flag = 3;
+      sortedList = secondSortedList;
+      secondSortedList = secondSortedList->next;
+      FREE(sortedList);
+      assert(!secondSortedList);
+      nClusterCols = RemoveLocalVarsInCluster(mddManager, xy, list,
+						nActiveRows, nClusterCols,
+						rowInfo, colInfo,
+						rowOrder, colOrder,
+						moveFlag, option);
+    }
+    if (option->mlpDebug) {
+      CheckCluster(headCluster, nClusterCols, colInfo, colOrder);
+      CheckMatrix(xy, NIL(SccList_t), nActiveRows, nClusterCols,
+		    rowInfo, colInfo, rowOrder, colOrder,
+		    0, nActiveRows - 1, 0, nClusterCols - 1, 0);
+    }
+  } else {
+    if (merge == 0 && option->mlpClusterSortedList) {
+      sortedList = clusterSortedList->next;
+      FREE(clusterSortedList);
+      clusterSortedList = sortedList;
+    }
+
+    mdd_free(best->product);
+    best->product = product;
+
+    if (list->flag == 2) {
+      if (best->flag == 1)
+	best->flag = 3;
+      else
+	best->flag = 2;
+    }
+
+    best->nSupports = 0;
+    best->minCol = nClusterCols;
+    best->maxCol = -1;
+    s1 = nClusterCols;
+    t1 = -1;
+    supportArray = mdd_get_bdd_support_ids(mddManager, best->product);
+    for (i = 0; i < array_n(supportArray); i++) {
+      index = array_fetch(int, supportArray, i);
+      if (varPos[index] == 0) {
+	if ((int)bdd_top_var_id(colInfo[0].data.col.var) != index)
+	  continue;
+      }
+      index = varPos[index];
+      best->supports[index] = 1;
+      best->nSupports++;
+      s2 = colInfo[index].pos;
+      if (s2 < s1) {
+	s1 = s2;
+	best->minCol = index;
+      }
+      if (s2 > t1) {
+	t1 = s2;
+	best->maxCol = index;
+      }
+    }
+    array_free(supportArray);
+
+    if (best->nsVarBddArray)
+      array_append(best->nsVarBddArray, list->nsVarBddArray);
+
+    if (list->start < best->start)
+      best->start = list->start;
+    if (list->end > best->end)
+      best->end = list->end;
+
+    if (option->mlpClusterSortedList) {
+      sortedList = clusterSortedList;
+      prevSortedList = NIL(ClusterSortedList_t);
+      if (merge == 0) {
+	while (sortedList) {
+	  nextSortedList = sortedList->next;
+	  if (option->mlpClusterDynamic) {
+	    if (sortedList->list == list || sortedList->list == best->prev) {
+	      if (prevSortedList)
+		prevSortedList->next = sortedList->next;
+	      else
+		clusterSortedList = sortedList->next;
+	      FREE(sortedList);
+	      sortedList = nextSortedList;
+	      continue;
+	    }
+	  } else {
+	    if (sortedList->list == list) {
+	      best->affinity = list->affinity;
+	      sortedList->list = best;
+	      break;
+	    }
+	  }
+	  prevSortedList = sortedList;
+	  sortedList = nextSortedList;
+	}
+      } else {
+	while (sortedList) {
+	  nextSortedList = sortedList->next;
+	  if (option->mlpClusterDynamic) {
+	    if (sortedList->list == best ||
+		sortedList->list == list || sortedList->list == best->prev) {
+	      if (prevSortedList)
+		prevSortedList->next = sortedList->next;
+	      else
+		clusterSortedList = sortedList->next;
+	      FREE(sortedList);
+	      sortedList = nextSortedList;
+	      continue;
+	    }
+	  } else {
+	    if (sortedList->list == best) {
+	      if (prevSortedList)
+		prevSortedList->next = sortedList->next;
+	      else
+		clusterSortedList = sortedList->next;
+	      FREE(sortedList);
+	      sortedList = nextSortedList;
+	      continue;
+	    } else if (sortedList->list == list) {
+	      best->affinity = list->affinity;
+	      sortedList->list = best;
+	      break;
+	    }
+	  }
+	  prevSortedList = sortedList;
+	  sortedList = nextSortedList;
+	}
+      }
+    }
+
+    best->next = list->next;
+    if (list->next)
+      list->next->prev = best;
+
+    mdd_free(list->product);
+    if (list->nsVarBddArray)
+      array_free(list->nsVarBddArray);
+    FREE(list->supports);
+    FREE(list);
+
+    if (merge && best->flag != 3) {
+      nClusterCols = RemoveLocalVarsInCluster(mddManager, xy, best,
+						nActiveRows, nClusterCols,
+						rowInfo, colInfo,
+						rowOrder, colOrder,
+						moveFlag, option);
+    }
+
+    if (best->flag == 3) {
+      nClusterCols = RemoveLocalVarsInCluster(mddManager, xy, best,
+						nActiveRows, nClusterCols,
+						rowInfo, colInfo,
+						rowOrder, colOrder,
+						moveFlag, option);
+    } else {
+      if (option->mlpClusterDynamic) {
+	if (best->flag == 2)
+	  best->affinity = 0.0;
+	else {
+	  best->affinity = MlpSupportAffinity(best, best->next, colInfo,
+						colOrder, nClusterCols,
+						option->mlpCluster);
+	}
+	if (best != headCluster) {
+	  best->prev->affinity = MlpSupportAffinity(best->prev, best, colInfo,
+						    colOrder, nClusterCols,
+						    option->mlpCluster);
+	}
+      }
+      if (option->mlpClusterQuantifyVars == 2) {
+	best->nQuantifyVars = MlpNumQuantifyVars(best, rowInfo, colInfo,
+						 colOrder, nClusterCols);
+      }
+      if (option->mlpClusterSortedList && option->mlpClusterDynamic) {
+	clusterSortedList = ClusterSortedListInsert(clusterSortedList, best,
+						option->mlpClusterQuantifyVars);
+	if (best != headCluster) {
+	  clusterSortedList = ClusterSortedListInsert(clusterSortedList,
+						best->prev,
+						option->mlpClusterQuantifyVars);
+	}
+      }
+    }
+
+    if (headCluster->flag == 1) {
+      if (option->mlpDebug) {
+	CheckCluster(headCluster, nClusterCols, colInfo, colOrder);
+	CheckMatrix(xy, NIL(SccList_t), nActiveRows, nClusterCols,
+		    rowInfo, colInfo, rowOrder, colOrder,
+		    0, nActiveRows - 1, 0, nClusterCols - 1, 0);
+      }
+      nClusterCols = RecursiveCluster(mddManager, headCluster,
+					clusterSortedList,
+					xy, rowInfo, colInfo,
+					rowOrder, colOrder,
+					nActiveRows, nClusterCols,
+					direction, varPos, moveFlag, option);
+    } else {
+      if (!option->mlpClusterDynamic) {
+	assert(!clusterSortedList->next);
+	FREE(clusterSortedList);
+      }
+    }
+  }
+
+  return(nClusterCols);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Removes local variables in a cluster.]
+
+  Description [Removes local variables in a cluster.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+RemoveLocalVarsInCluster(mdd_manager *mddManager, char **xy,
+			 ClusterList_t *list,
+			 int nActiveRows, int nClusterCols,
+			 RcInfo_t *rowInfo, RcInfo_t *colInfo,
+			 int *rowOrder, int *colOrder,
+			 int moveFlag, ImgTrmOption_t *option)
+{
+  int		i, j, k, row, col, otherCol;
+  int		s1, t1, s2, t2, s3, t3;
+  mdd_t		*product;
+  array_t	*localVarBddArray = NIL(array_t);
+
+  s1 = colInfo[list->minCol].pos;
+  t1 = colInfo[list->maxCol].pos;
+  for (i = t1; i >= s1; i--) {
+    col = colOrder[i];
+    if (colInfo[col].data.col.type == 2 &&
+	rowInfo[colInfo[col].gMin].pos >= list->start &&
+	rowInfo[colInfo[col].gMax].pos <= list->end) {
+      if (!localVarBddArray)
+	localVarBddArray = array_alloc(bdd_t *, 0);
+      array_insert_last(bdd_t *, localVarBddArray, colInfo[col].data.col.var);
+
+      list->nSupports--;
+      if (list->nSupports == 0) {
+	list->minCol = -1;
+	list->maxCol = -1;
+      } else if (list->nSupports == 1) {
+	if (list->minCol == col)
+	  list->minCol = list->maxCol;
+	else
+	  list->maxCol = list->minCol;
+      } else if (list->nSupports > 1) {
+	if (list->minCol == col) {
+	  for (j = i + 1; j <= t1; j++) {
+	    otherCol = colOrder[j];
+	    if (list->supports[otherCol]) {
+	      list->minCol = otherCol;
+	      break;
+	    }
+	  }
+	} else if (list->maxCol == col) {
+	  for (j = i - 1; j >= s1; j--) {
+	    otherCol = colOrder[j];
+	    if (list->supports[otherCol]) {
+	      list->maxCol = otherCol;
+	      break;
+	    }
+	  }
+	}
+      }
+
+      s2 = list->start;
+      t2 = list->end;
+      for (j = s2; j <= t2; j++) {
+	row = rowOrder[j];
+	if (xy[row][col]) {
+	  rowInfo[row].gNum--;
+	  if (rowInfo[row].gNum > 0) {
+	    s3 = colInfo[rowInfo[row].gMin].pos;
+	    t3 = colInfo[rowInfo[row].gMax].pos;
+	    if (rowInfo[row].gMin == col) {
+	      for (k = i + 1; k <= t3; k++) {
+		otherCol = colOrder[k];
+		if (xy[row][otherCol]) {
+		  rowInfo[row].gMin = otherCol;
+		  break;
+		}
+	      }
+	    } else if (rowInfo[row].gMax == col) {
+	      for (k = i - 1; k >= s3; k--) {
+		otherCol = colOrder[k];
+		if (xy[row][otherCol]) {
+		  rowInfo[row].gMax = otherCol;
+		  break;
+		}
+	      }
+	    }
+	  }
+	}
+      }
+
+      for (j = i; j < nClusterCols - 1; j++) {
+	colOrder[j] = colOrder[j + 1];
+	colInfo[colOrder[j]].pos = j;
+      }
+      colOrder[nClusterCols - 1] = col;
+      colInfo[col].pos = nClusterCols - 1;
+
+      nClusterCols--;
+
+      if (option->mlpDebug) {
+	CheckCluster(list, nClusterCols, colInfo, colOrder);
+	CheckMatrix(xy, NIL(SccList_t), nActiveRows, nClusterCols,
+		    rowInfo, colInfo, rowOrder, colOrder,
+		    0, nActiveRows - 1, 0, nClusterCols - 1, 0);
+      }
+    }
+  }
+
+  if (localVarBddArray) {
+    product = bdd_smooth(list->product, localVarBddArray);
+    mdd_free(list->product);
+    list->product = product;
+    array_free(localVarBddArray);
+    UpdateDisapearingPsVarsInCluster(mddManager, xy,
+			nActiveRows, nClusterCols,
+			rowOrder, colOrder, rowInfo, colInfo,
+			list, moveFlag, option);
+  }
+
+  return(nClusterCols);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Retuns the number of variables to be quantified in a list.]
+
+  Description [Retuns the number of variables to be quantified in a list.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+MlpNumQuantifyVars(ClusterList_t *list, RcInfo_t *rowInfo, RcInfo_t *colInfo,
+		   int *colOrder, int nClusterCols)
+{
+  int	i, s, t, col;
+  int	nQuantifyVars = 0;
+
+  s = colInfo[list->minCol].pos;
+  t = colInfo[list->maxCol].pos;
+  for (i = t; i >= s; i--) {
+    col = colOrder[i];
+    if (rowInfo[colInfo[col].gMin].pos >= list->start &&
+	rowInfo[colInfo[col].gMin].pos <= list->end) {
+      nQuantifyVars++;
+    } else
+      break;
+  }
+
+  return(nQuantifyVars);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts a cluster in a sorting list.]
+
+  Description [Inserts a cluster in a sorting list.]
+
+  SideEffects []
+
+******************************************************************************/
+static ClusterSortedList_t *
+ClusterSortedListInsert(ClusterSortedList_t *clusterSortedList,
+			ClusterList_t *list, int useQuantifyVars)
+{
+  ClusterSortedList_t	*sortedList, *cur, *prev;
+
+  sortedList = ALLOC(ClusterSortedList_t, 1);
+  sortedList->list = list;
+
+  if (!clusterSortedList) {
+    sortedList->next = NIL(ClusterSortedList_t);
+    return(sortedList);
+  }
+
+  cur = clusterSortedList;
+  prev = NIL(ClusterSortedList_t);
+  while (cur) {
+    if (list->flag == 2) {
+      prev = cur;
+      cur = cur->next;
+      continue;
+    }
+    if (useQuantifyVars) {
+      if (cur->list->flag == 2 ||
+	  list->nQuantifyVars < cur->list->nQuantifyVars ||
+	  (list->nQuantifyVars == cur->list->nQuantifyVars &&
+	   list->affinity >= cur->list->affinity)) {
+	sortedList->next = cur;
+	if (cur == clusterSortedList)
+	  clusterSortedList = sortedList;
+	else
+	  prev->next = sortedList;
+	break;
+      }
+    } else {
+      if (cur->list->flag == 2 ||
+	  list->affinity > cur->list->affinity ||
+	  (list->affinity == cur->list->affinity &&
+	   list->nQuantifyVars <= cur->list->nQuantifyVars)) {
+	sortedList->next = cur;
+	if (cur == clusterSortedList)
+	  clusterSortedList = sortedList;
+	else
+	  prev->next = sortedList;
+	break;
+      }
+    }
+    prev = cur;
+    cur = cur->next;
+  }
+  if (!cur) {
+    prev->next = sortedList;
+    sortedList->next = NIL(ClusterSortedList_t);
+  }
+  return(clusterSortedList);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of lists in a cluster list.]
+
+  Description [Returns the number of lists in a cluster list.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CountClusterList(ClusterList_t *clusterList)
+{
+  ClusterList_t	*list;
+  int		n = 0;
+
+  list = clusterList;
+  while (list) {
+    if (list->flag == 3)
+      break;
+    n++;
+    if (list->flag == 2)
+      break;
+    list = list->next;
+  }
+
+  return(n);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of lists in a sorted cluster list.]
+
+  Description [Returns the number of lists in a sorted cluster list.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CountClusterSortedList(ClusterSortedList_t *clusterSortedList)
+{
+  ClusterSortedList_t	*sortedList;
+  int			n = 0;
+
+  sortedList = clusterSortedList;
+  while (sortedList) {
+    n++;
+    sortedList = sortedList->next;
+  }
+
+  return(n);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates an initial cluster using ARDC decomposition.]
+
+  Description [Creates an initial cluster using ARDC decomposition.]
+
+  SideEffects []
+
+******************************************************************************/
+static array_t *
+CreateInitialCluster(mdd_manager *mddManager, array_t *relationArray,
+		     ImgFunctionData_t *functionData, array_t *nsVarBddArray,
+		     ImgTrmOption_t *option)
+{
+  array_t		*clusteredRelationArray;
+  array_t		*partitionArray;
+  Part_Subsystem_t	*partitionSubsystem;
+  st_table		*vertexTable;
+  int			i, j;
+  int			mddId;
+  long			bddId;
+  Ntk_Node_t		*latch;
+  mdd_t			*cluster, *product, *relation, *var;
+  char			*latchName;
+  st_generator		*stGen;
+  st_table		*id2relation;
+  array_t		*bddIdArray;
+  int			nVars;
+  char			*nsVarFlag;
+  array_t		*domainVars;
+
+  if (array_n(functionData->domainVars) == array_n(functionData->rangeVars))
+    domainVars = functionData->domainVars;
+  else {
+    domainVars = array_alloc(int, 0);
+    for (i = 0; i < array_n(functionData->rangeVars); i++) {
+      mddId = array_fetch(int, functionData->domainVars, i);
+      array_insert_last(int, domainVars, mddId);
+    }
+  }
+  partitionArray = Fsm_ArdcDecomposeStateSpace(functionData->network,
+						domainVars,
+						functionData->roots,
+						NIL(Fsm_ArdcOptions_t));
+  if (domainVars != functionData->domainVars)
+    array_free(domainVars);
+
+  nVars = bdd_num_vars(mddManager);
+  nsVarFlag = ALLOC(char, nVars);
+  memset(nsVarFlag, 0, sizeof(char) * nVars);
+  for (i = 0; i < array_n(nsVarBddArray); i++) {
+    var = array_fetch(mdd_t *, nsVarBddArray, i);
+    bddId = (long) bdd_top_var_id(var);
+    nsVarFlag[bddId] = 1;
+  }
+  clusteredRelationArray = array_alloc(mdd_t *, 0);
+  id2relation = st_init_table(st_numcmp, st_numhash);
+  for (i = 0; i < array_n(relationArray); i++) {
+    relation = array_fetch(mdd_t *, relationArray, i);
+    bddIdArray = mdd_get_bdd_support_ids(mddManager, relation);
+    for (j = 0; j < array_n(bddIdArray); j++) {
+      bddId = (long) array_fetch(int, bddIdArray, j);
+      if (nsVarFlag[bddId]) {
+	st_insert(id2relation, (char *)bddId, (char *)relation);
+	break;
+      }
+    }
+
+    /* the relation of intermediate variable */
+    if (j == array_n(bddIdArray)) {
+      array_insert_last(mdd_t *, clusteredRelationArray, mdd_dup(relation));
+    }
+
+    array_free(bddIdArray);
+  }
+  FREE(nsVarFlag);
+
+  arrayForEachItem(Part_Subsystem_t *, partitionArray, i, partitionSubsystem) {
+    cluster = mdd_one(mddManager);
+    vertexTable = Part_PartitionSubsystemReadVertexTable(partitionSubsystem);
+    st_foreach_item(vertexTable, stGen, &latchName, NIL(char *)) {
+      latch = Ntk_NetworkFindNodeByName(functionData->network, latchName); 
+      mddId = Ntk_NodeReadMddId(Ntk_NodeReadShadow(latch));
+      bddIdArray = mdd_id_to_bdd_id_array(mddManager, mddId);
+      for (j = 0; j < array_n(bddIdArray); j++) {
+	bddId = (long) array_fetch(int, bddIdArray, j);
+	if (st_lookup(id2relation, (char *)bddId, &relation)) {
+	  st_delete(id2relation, &bddId, NULL);
+	  product = mdd_and(cluster, relation, 1, 1);
+	  mdd_free(cluster);
+	  cluster = product;
+	}
+      }
+      array_free(bddIdArray);
+    }
+    Part_PartitionSubsystemFree(partitionSubsystem);
+    array_insert_last(mdd_t *, clusteredRelationArray, cluster);
+  }
+  array_free(partitionArray);
+
+  st_foreach_item(id2relation, stGen, &bddId, &relation) {
+    array_insert_last(mdd_t *, clusteredRelationArray, mdd_dup(relation));
+  }
+  st_free_table(id2relation);
+
+/*
+  if (option->mlpDebug) {
+    mdd_t	*tr1, *tr2, *tmp;
+
+    tr1 = mdd_one(mddManager);
+    for (i = 0; i < array_n(relationArray); i++) {
+      relation = array_fetch(mdd_t *, relationArray, i);
+      tmp = mdd_and(tr1, relation, 1, 1);
+      mdd_free(tr1);
+      tr1 = tmp;
+    }
+
+    tr2 = mdd_one(mddManager);
+    for (i = 0; i < array_n(clusteredRelationArray); i++) {
+      relation = array_fetch(mdd_t *, clusteredRelationArray, i);
+      tmp = mdd_and(tr2, relation, 1, 1);
+      mdd_free(tr2);
+      tr2 = tmp;
+    }
+
+    assert(mdd_equal(tr1, tr2));
+    mdd_free(tr1);
+    mdd_free(tr2);
+  }
+*/
+
+  return(clusteredRelationArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Updates matrix information properly.]
+
+  Description [Updates matrix information properly.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+SortCol(char **xy, int nRows, int nCols,
+	RcInfo_t *rowInfo, RcInfo_t *colInfo, int *rowOrder, int *colOrder)
+{
+  int	x, y, i, j, row, col, lastVar;
+  int	otherRow, otherCol;
+
+  lastVar = nCols - 1;
+
+  for (x = nRows - 1; x >= 0; x--) {
+    row = rowOrder[x];
+    for (y = lastVar; y >= 0; y--) {
+      col = colOrder[y];
+      if (colInfo[col].gMin == row) {
+	if (y == lastVar) {
+	  lastVar--;
+	  continue;
+	}
+	for (j = y; j < lastVar; j++) {
+	  colOrder[j] = colOrder[j + 1];
+	  colInfo[colOrder[j]].pos = j;
+	}
+	colOrder[lastVar] = col;
+	colInfo[col].pos = lastVar;
+	for (i = x; i < nRows; i++) {
+	  otherRow = rowOrder[i];
+	  if (colInfo[rowInfo[otherRow].gMax].pos < lastVar)
+	    rowInfo[otherRow].gMax = col;
+	  if (rowInfo[otherRow].gMin == col) {
+	    for (j = 0; j < nCols; j++) {
+	      otherCol = colOrder[j];
+	      if (xy[otherRow][otherCol]) {
+		rowInfo[otherRow].gMin = otherCol;
+		break;
+	      }
+	    }
+	  }
+	}
+	lastVar--;
+      }
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds disappearing present state variables in a row.]
+
+  Description [Finds disappearing present state variables in a row.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+UpdateDisapearingPsVars(mdd_manager *mddManager, char **xy,
+			int nActiveRows, int nActiveCols,
+			int *rowOrder, int *colOrder,
+			RcInfo_t *rowInfo, RcInfo_t *colInfo,
+			int row, ImgTrmOption_t *option)
+{
+  int		i, id, x, y, s, t, col, tmpRow;
+  mdd_t		*relation;
+  array_t	*supportArray;
+  char		*supportIndex;
+  int		nVars;
+
+  nVars = bdd_num_vars(mddManager);
+  relation = rowInfo[row].data.row.func;
+  supportIndex = ALLOC(char, nVars);
+  memset(supportIndex, 0, sizeof(char) * nVars);
+  supportArray = mdd_get_bdd_support_ids(mddManager, relation);
+  for (i = 0; i < array_n(supportArray); i++) {
+    id = array_fetch(int, supportArray, i);
+    supportIndex[id] = 1;
+  }
+  array_free(supportArray);
+
+  s = colInfo[rowInfo[row].gMin].pos;
+  t = colInfo[rowInfo[row].gMax].pos;
+  x = rowInfo[row].pos;
+  rowInfo[row].gNum = 0;
+  rowInfo[row].gMin = nActiveCols;
+  rowInfo[row].gMax = -1;
+  for (y = s; y <= t; y++) {
+    col = colOrder[y];
+    if (!xy[row][col])
+      continue;
+    id = (int)bdd_top_var_id(colInfo[col].data.col.var);
+    if (supportIndex[id]) {
+      rowInfo[row].gNum++;
+      if (rowInfo[row].gMin == nActiveCols)
+	rowInfo[row].gMin = col;
+      rowInfo[row].gMax = col;
+    } else {
+      xy[row][col] = 0;
+      if (colInfo[col].gNum == 1) {
+	colInfo[col].gNum = 0;
+	colInfo[col].gMin = nActiveRows;
+	colInfo[col].gMax = -1;
+      } else if (colInfo[col].gNum == 2) {
+	colInfo[col].gNum = 1;
+	if (colInfo[col].gMin == row)
+	  colInfo[col].gMin = colInfo[col].gMax;
+	else
+	  colInfo[col].gMax = colInfo[col].gMin;
+      } else {
+	colInfo[col].gNum--;
+	if (row == colInfo[col].gMin) {
+	  for (i = x + 1; i <= rowInfo[colInfo[col].gMax].pos; i++) {
+	    tmpRow = rowOrder[i];
+	    if (xy[tmpRow][col]) {
+	      colInfo[col].gMin = tmpRow;
+	      break;
+	    }
+	  }
+	} else if (row == colInfo[col].gMax) {
+	  for (i = x - 1; i >= rowInfo[colInfo[col].gMin].pos; i--) {
+	    tmpRow = rowOrder[i];
+	    if (xy[tmpRow][col]) {
+	      colInfo[col].gMax = tmpRow;
+	      break;
+	    }
+	  }
+	}
+      }
+    }
+  }
+
+  FREE(supportIndex);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds disappearing present state variables in a cluster.]
+
+  Description [Finds disappearing present state variables in a cluster.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+UpdateDisapearingPsVarsInCluster(mdd_manager *mddManager, char **xy,
+			int nActiveRows, int nActiveCols,
+			int *rowOrder, int *colOrder,
+			RcInfo_t *rowInfo, RcInfo_t *colInfo,
+			ClusterList_t *list, int moveFlag,
+			ImgTrmOption_t *option)
+{
+  int		i, j, k, y, id, row, col, otherRow, otherCol;
+  int		s1, t1, s2, t2, s3, t3, t4;
+  mdd_t		*relation;
+  array_t	*supportArray;
+  char		*supportIndex;
+  int		nVars;
+  ClusterList_t	*otherList;
+
+  if (list->nSupports == 0)
+    return;
+
+  nVars = bdd_num_vars(mddManager);
+  relation = list->product;
+  supportIndex = ALLOC(char, nVars);
+  memset(supportIndex, 0, sizeof(char) * nVars);
+  supportArray = mdd_get_bdd_support_ids(mddManager, relation);
+  for (i = 0; i < array_n(supportArray); i++) {
+    id = array_fetch(int, supportArray, i);
+    supportIndex[id] = 1;
+  }
+  array_free(supportArray);
+
+  s1 = colInfo[list->minCol].pos;
+  t1 = colInfo[list->maxCol].pos;
+  for (y = t1; y >= s1; y--) {
+    col = colOrder[y];
+    if (!list->supports[col])
+      continue;
+    id = (int)bdd_top_var_id(colInfo[col].data.col.var);
+    if (!supportIndex[id]) {
+      list->nSupports--;
+      list->supports[col] = 0;
+      if (list->nSupports == 0) {
+	list->minCol = -1;
+	list->maxCol = -1;
+      } else if (list->nSupports == 1) {
+	if (list->minCol == col)
+	  list->minCol = list->maxCol;
+	else
+	  list->maxCol = list->minCol;
+      } else if (list->nSupports > 1) {
+	if (list->minCol == col) {
+	  for (j = y + 1; j <= t1; j++) {
+	    otherCol = colOrder[j];
+	    if (list->supports[otherCol]) {
+	      list->minCol = otherCol;
+	      break;
+	    }
+	  }
+	} else if (list->maxCol == col) {
+	  for (j = y - 1; j >= s1; j--) {
+	    otherCol = colOrder[j];
+	    if (list->supports[otherCol]) {
+	      list->maxCol = otherCol;
+	      break;
+	    }
+	  }
+	}
+      }
+
+      for (j = list->start; j <= list->end; j++) {
+	row = rowOrder[j];
+	if (xy[row][col]) {
+	  xy[row][col] = 0;
+	  colInfo[col].gNum--;
+	  rowInfo[row].gNum--;
+	  if (rowInfo[row].gNum > 0) {
+	    s2 = colInfo[rowInfo[row].gMin].pos;
+	    t2 = colInfo[rowInfo[row].gMax].pos;
+	    if (rowInfo[row].gMin == col) {
+	      for (k = y + 1; k <= t2; k++) {
+		otherCol = colOrder[k];
+		if (xy[row][otherCol]) {
+		  rowInfo[row].gMin = otherCol;
+		  break;
+		}
+	      }
+	    } else if (rowInfo[row].gMax == col) {
+	      for (k = y - 1; k >= s2; k--) {
+		otherCol = colOrder[k];
+		if (xy[row][otherCol]) {
+		  rowInfo[row].gMax = otherCol;
+		  break;
+		}
+	      }
+	    }
+	  } else {
+	    rowInfo[row].gMin = -1;
+	    rowInfo[row].gMax = nActiveCols;
+	  }
+	}
+      }
+
+      if (colInfo[col].gNum == 0) {
+	colInfo[col].lNum = 0;
+	colInfo[col].gMin = nActiveRows;
+	colInfo[col].lMin = nActiveRows;
+	colInfo[col].gMax = -1;
+	colInfo[col].lMax = -1;
+      } else if (colInfo[col].gNum == 1) {
+	colInfo[col].lNum = 1;
+	if (rowInfo[colInfo[col].gMax].pos > list->end) {
+	  colInfo[col].gMin = colInfo[col].gMax;
+	  colInfo[col].lMin = colInfo[col].gMax;
+	} else {
+	  colInfo[col].gMax = colInfo[col].gMin;
+	  colInfo[col].lMax = colInfo[col].gMin;
+	}
+      } else {
+	colInfo[col].lNum = colInfo[col].gNum;
+	if (rowInfo[colInfo[col].gMin].pos >= list->start &&
+	    rowInfo[colInfo[col].gMin].pos <= list->end) {
+	  for (i = list->end + 1; i <= rowInfo[colInfo[col].gMax].pos; i++) {
+	    otherRow = rowOrder[i];
+	    if (xy[otherRow][col]) {
+	      colInfo[col].gMin = otherRow;
+	      colInfo[col].lMin = otherRow;
+	      break;
+	    }
+	  }
+	} else if (rowInfo[colInfo[col].gMax].pos >= list->start &&
+		   rowInfo[colInfo[col].gMax].pos <= list->end) {
+	  for (i = list->start - 1; i >= rowInfo[colInfo[col].gMin].pos; i--) {
+	    otherRow = rowOrder[i];
+	    if (xy[otherRow][col]) {
+	      colInfo[col].gMax = otherRow;
+	      colInfo[col].lMax = otherRow;
+	      break;
+	    }
+	  }
+	}
+      }
+
+      if (moveFlag) {
+	if (colInfo[col].gNum == 0) {
+	  if (y < nActiveCols - 1) {
+	    for (j = y; j < nActiveCols - 1; j++) {
+	      colOrder[j] = colOrder[j + 1];
+	      colInfo[colOrder[j]].pos = j;
+	    }
+	    colOrder[nActiveCols - 1] = col;
+	    colInfo[col].pos = nActiveCols - 1;
+	  }
+	} else if (rowInfo[colInfo[col].gMin].pos > list->end) {
+	  if (list->prev && list->prev->start > list->start) {
+	    /* Image */
+	    otherList = list->prev;
+	    while (!otherList->supports[col])
+	      otherList = otherList->prev;
+	  } else if (list->next && list->next->start > list->start) {
+	    /* Preimage */
+	    otherList = list->next;
+	    while (!otherList->supports[col])
+	      otherList = otherList->next;
+	  } else
+	    otherList = NIL(ClusterList_t);
+
+	  if (otherList) {
+	    t2 = colInfo[otherList->maxCol].pos;
+	    if (y != t2) {
+	      for (j = y; j < t2; j++) {
+		colOrder[j] = colOrder[j + 1];
+		colInfo[colOrder[j]].pos = j;
+	      }
+	      colOrder[t2] = col;
+	      colInfo[col].pos = t2;
+	      otherList->maxCol = col;
+	      if (otherList->minCol == col) {
+		for (j = y; j < t2; j++) {
+		  otherCol = colOrder[j];
+		  if (otherList->supports[otherCol]) {
+		    otherList->minCol = otherCol;
+		    break;
+		  }
+		}
+	      }
+
+	      s3 = rowInfo[colInfo[col].gMin].pos;
+	      t3 = rowInfo[colInfo[col].gMax].pos;
+	      for (j = s3; j <= t3; j++) {
+		otherRow = rowOrder[j];
+		if (xy[otherRow][col]) {
+		  if (rowInfo[otherRow].gNum > 1) {
+		    t4 = colInfo[rowInfo[otherRow].gMax].pos;
+		    if (t4 <= t2)
+		      rowInfo[otherRow].gMax = col;
+		    if (rowInfo[otherRow].gMin == col) {
+		      for (k = y; k <= t4; k++) {
+			otherCol = colOrder[k];
+			if (xy[otherRow][otherCol]) {
+			  rowInfo[otherRow].gMin = col;
+			  break;
+			}
+		      }
+		    }
+		  }
+		}
+	      }
+	    }
+	  }
+	}
+      }
+
+      if (option->mlpDebug) {
+	CheckCluster(list, nActiveCols, colInfo, colOrder);
+	CheckMatrix(xy, NIL(SccList_t), nActiveRows, nActiveCols,
+		    rowInfo, colInfo, rowOrder, colOrder,
+		    0, nActiveRows - 1, 0, nActiveCols - 1, 0);
+      }
+    }
+  }
+
+  FREE(supportIndex);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds non-appearing next state variables.]
+
+  Description [Finds non-appearing next state variables.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+UpdateNonappearingNsVars(mdd_manager *mddManager, array_t *nsVarBddArray,
+			int nRows, RcInfo_t *rowInfo, int *rowOrder,
+			array_t *nonAppearingVarBddArray)
+{
+  int		i, j, k, row, index, nVars;
+  mdd_t		*nsVar, *relation;
+  char		*existFlag;
+  array_t	*supportArray, *tmpArray;
+
+  nVars = bdd_num_vars(mddManager);
+  existFlag = ALLOC(char, nVars);
+  memset(existFlag, 0, sizeof(char) * nVars);
+
+  for (i = 0; i < nRows; i++) {
+    row = rowOrder[i];
+    relation = rowInfo[row].data.row.func;
+    supportArray = mdd_get_bdd_support_ids(mddManager, relation);
+    for (j = 0; j < array_n(supportArray); j++) {
+      index = array_fetch(int, supportArray, j);
+      existFlag[index] = 1;
+    }
+    array_free(supportArray);
+  }
+
+  for (i = 0; i < nRows; i++) {
+    row = rowOrder[i];
+    for (j = 0; j < array_n(rowInfo[row].data.row.nsVarBddArray); j++) {
+      nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray, j);
+      index = (int)bdd_top_var_id(nsVar);
+      if (!existFlag[index]) {
+	tmpArray = array_alloc(mdd_t *, 0);
+	for (k = 0; k < j; k++) {
+	  nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray, k);
+	  array_insert_last(mdd_t *, tmpArray, nsVar);
+	}
+	for (k = j + 1; k < array_n(rowInfo[row].data.row.nsVarBddArray); k++) {
+	  nsVar = array_fetch(bdd_t *, rowInfo[row].data.row.nsVarBddArray, k);
+	  index = (int)bdd_top_var_id(nsVar);
+	  if (existFlag[index])
+	    array_insert_last(mdd_t *, tmpArray, nsVar);
+	}
+	array_free(rowInfo[row].data.row.nsVarBddArray);
+	rowInfo[row].data.row.nsVarBddArray = tmpArray;
+	break;
+      }
+    }
+  }
+
+  for (i = 0; i < array_n(nsVarBddArray); i++) {
+    nsVar = array_fetch(bdd_t *, nsVarBddArray, i);
+    index = (int)bdd_top_var_id(nsVar);
+    if (!existFlag[index])
+      array_insert_last(mdd_t *, nonAppearingVarBddArray, bdd_dup(nsVar));
+  }
+
+  FREE(existFlag);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes variable order in coulumn of the matrix.]
+
+  Description [Writes variable order in coulumn of the matrix.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+WriteOrder(FILE *fout, int nCols, int *colOrder, RcInfo_t *colInfo)
+{
+  int	i, col;
+  mdd_t	*var;
+  char	*name;
+
+  for (i = 0; i < nCols; i++) {
+    col = colOrder[i];
+    var = colInfo[col].data.col.var;
+    name = mdd_read_var_name(var);
+    fprintf(fout, "%s\n", name);
+  }
+}
Index: vis_dev/vis-2.3/src/img/imgMonolithic.c
===================================================================
--- vis_dev/vis-2.3/src/img/imgMonolithic.c	(revision 14)
+++ vis_dev/vis-2.3/src/img/imgMonolithic.c	(revision 14)
@@ -0,0 +1,653 @@
+/**CFile***********************************************************************
+
+  FileName    [imgMonolithic.c]
+
+  PackageName [img]
+
+  Synopsis    [Routines for image computation using a monolithic transition
+  relation.] 
+
+  Author      [Rajeev K. Ranjan, Tom Shiple, Abelardo Pardo, In-Ho Moon]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "imgInt.h"
+
+static char rcsid[] UNUSED = "$Id: imgMonolithic.c,v 1.23 2002/08/27 08:43:12 fabio Exp $";
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static mdd_t * ImageComputeMonolithic(mdd_t *methodData, mdd_t *fromLowerBound, mdd_t *fromUpperBound, array_t *toCareSetArray, array_t *smoothVars, mdd_t *smoothCube);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+    
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes an image structure for image computation
+  using a monolithic transition relation.]
+
+  Description [This function computes the monolithic transition relation
+  characterizing the behavior of the system from the individual functions.]
+
+  SideEffects []
+
+  SeeAlso     [Img_MultiwayLinearAndSmooth]
+******************************************************************************/
+void *
+ImgImageInfoInitializeMono(void *methodData, ImgFunctionData_t * functionData,
+                           Img_DirectionType directionType)
+{
+  if (!methodData){ /* Need to compute */
+    int          i;
+    mdd_t       *monolithicT;
+    array_t     *rootRelations = array_alloc(mdd_t*, 0);
+    graph_t     *mddNetwork    = functionData->mddNetwork;
+    mdd_manager *mddManager    = Part_PartitionReadMddManager(mddNetwork);
+    array_t     *roots         = functionData->roots;
+    array_t     *leaves        = array_join(functionData->domainVars,
+                                            functionData->quantifyVars);
+    array_t     *rootFunctions = Part_PartitionBuildFunctions(mddNetwork, roots,
+                                                              leaves,
+                                                              NIL(mdd_t)); 
+    
+    array_free(leaves);
+    
+    
+    /*
+     * Take the product of the transition relation of all the root nodes
+     * and smooth out the quantify variables.
+     */
+    
+    /*
+     * Iterate over the function of all the root nodes.
+     */  
+    for (i=0; i<array_n(rootFunctions); i++) {
+      Mvf_Function_t *rootFunction  = array_fetch(Mvf_Function_t*, rootFunctions, i);
+      int             rangeVarMddId = array_fetch(int, functionData->rangeVars, i);
+      mdd_t          *rootRelation =
+          Mvf_FunctionBuildRelationWithVariable(rootFunction,
+                                                rangeVarMddId); 
+      array_insert_last(mdd_t*, rootRelations, rootRelation);
+    }
+    
+    Mvf_FunctionArrayFree(rootFunctions);
+    monolithicT = Img_MultiwayLinearAndSmooth(mddManager, rootRelations,
+                                              functionData->quantifyVars,
+                                              functionData->domainVars,
+					      Img_Iwls95_c, Img_Forward_c);
+    mdd_array_free(rootRelations);
+    return ((void *)monolithicT);
+  }
+  else {
+    return methodData;
+  }
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the forward image of a set of states between
+  fromLowerBound and fromUpperBound.]
+
+  Description [Computes the forward image of a set of states between
+  fromLowerBound and fromUpperBound.  First a set of states between
+  fromLowerBound and fromUpperBound is computed.  Then, the transition
+  relation is simplified by cofactoring it wrt to the set of states found in
+  the first step, and wrt the toCareSet.]
+
+  SideEffects []
+
+  SeeAlso     [ImgImageInfoComputeBwdMono, ImgImageInfoComputeFwdWithDomainVarsMono]
+******************************************************************************/
+mdd_t *
+ImgImageInfoComputeFwdMono(
+  ImgFunctionData_t * functionData,
+  Img_ImageInfo_t * imageInfo,
+  mdd_t *fromLowerBound,
+  mdd_t *fromUpperBound,
+  array_t * toCareSetArray)
+{
+  return  ImageComputeMonolithic((mdd_t *) imageInfo->methodData,
+				 fromLowerBound, fromUpperBound,
+				 toCareSetArray, functionData->domainBddVars,
+                                 functionData->domainCube);  
+}
+
+  
+/**Function********************************************************************
+
+  Synopsis    [Computes the forward image on domain variables of a set
+  of states between fromLowerBound and fromUpperBound.]
+
+  Description [Identical to ImgImageInfoComputeFwdMono except
+  1. toCareSet is in terms of domain vars and hence range vars are
+  substituted first. 2. Before returning the image, range vars are
+  substituted with domain vars.]
+
+  SideEffects []
+
+  SeeAlso     [ImgImageInfoComputeFwdMono]
+******************************************************************************/
+mdd_t *
+ImgImageInfoComputeFwdWithDomainVarsMono(
+  ImgFunctionData_t *functionData,
+  Img_ImageInfo_t *imageInfo,
+  mdd_t *fromLowerBound,
+  mdd_t *fromUpperBound,
+  array_t *toCareSetArray)
+{
+  array_t *toCareSetArrayRV = ImgSubstituteArray(toCareSetArray,
+						 functionData, Img_D2R_c);
+  mdd_t *imageRV = ImgImageInfoComputeFwdMono(functionData,
+					      imageInfo,
+					      fromLowerBound,
+					      fromUpperBound,
+					      toCareSetArrayRV);
+  mdd_t *imageDV = ImgSubstitute(imageRV, functionData, Img_R2D_c);
+
+  mdd_array_free(toCareSetArrayRV);
+  mdd_free(imageRV);
+  return imageDV;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the backward image of a set of states between
+  fromLowerBound and fromUpperBound.]
+
+  Description [Computes the backward image of a set of states between
+  fromLowerBound and fromUpperBound.  First a set of states between
+  fromLowerBound and fromUpperBound is computed.  Then, the transition
+  relation is simplified by cofactoring it wrt to the set of states found in
+  the first step, and wrt the toCareSet.]
+
+  SideEffects []
+  
+  SeeAlso     [ImgImageInfoComputeFwdMono,ImgImageInfoComputeBwdWithDomainVarsMono]
+
+******************************************************************************/
+mdd_t *
+ImgImageInfoComputeBwdMono(
+  ImgFunctionData_t * functionData,
+  Img_ImageInfo_t *imageInfo,
+  mdd_t *fromLowerBound,
+  mdd_t *fromUpperBound,
+  array_t *toCareSetArray)
+{
+  return ImageComputeMonolithic((mdd_t*)imageInfo->methodData, fromLowerBound,
+                                fromUpperBound, toCareSetArray,  
+                                functionData->rangeBddVars,
+                                functionData->rangeCube);  
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the backward image of a set of states between
+  fromLowerBound and fromUpperBound.]
+
+  Description [Identical to ImgImageInfoComputeBwdMono except that
+  fromLowerBound and fromUpperBound and given in terms of domain
+  variables, hence we need to substitute the range variables first.]
+  
+  SideEffects []
+
+  SeeAlso [ImgImageInfoComputeBwdMono]
+
+******************************************************************************/
+mdd_t *
+ImgImageInfoComputeBwdWithDomainVarsMono(
+  ImgFunctionData_t * functionData,
+  Img_ImageInfo_t *imageInfo,
+  mdd_t *fromLowerBound,
+  mdd_t *fromUpperBound,
+  array_t *toCareSetArray)
+{
+  mdd_t *fromLowerBoundRV = ImgSubstitute(fromLowerBound,
+                                          functionData, Img_D2R_c);
+  mdd_t *fromUpperBoundRV = ImgSubstitute(fromUpperBound,
+                                          functionData, Img_D2R_c);
+  mdd_t *image = ImgImageInfoComputeBwdMono(functionData,
+					    imageInfo,
+					    fromLowerBoundRV,
+					    fromUpperBoundRV,
+					    toCareSetArray);
+  mdd_free(fromLowerBoundRV);
+  mdd_free(fromUpperBoundRV);
+  return image;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the method data associated with the monolithic method.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgImageInfoFreeMono(void * methodData)
+{
+  mdd_free((mdd_t *)methodData);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Prints information about the IWLS95 method.]
+
+  Description [This function is used to obtain the information about
+  the parameters used to initialize the imageInfo.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgImageInfoPrintMethodParamsMono(void *methodData, FILE *fp)
+{
+  mdd_t *monolithicRelation = (mdd_t *)methodData;
+  (void) fprintf(fp,"Printing information about image method: Monolithic\n");  
+  (void) fprintf(fp,"\tSize of monolithic relation = %10ld\n",
+                 (long) bdd_size(monolithicRelation));
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Restores original transition relation from saved.]
+
+  Description [Restores original transition relation from saved.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgRestoreTransitionRelationMono(Img_ImageInfo_t *imageInfo,
+	Img_DirectionType directionType)
+{
+  mdd_free((mdd_t *) imageInfo->methodData);
+  imageInfo->methodData = (mdd_t *)imageInfo->savedRelation;
+  imageInfo->savedRelation = NIL(void);
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Duplicates transition relation.]
+
+  Description [Duplicates transition relation. Assumes that the
+  Transition Relation is a MDD.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgDuplicateTransitionRelationMono(Img_ImageInfo_t *imageInfo)
+{
+  imageInfo->savedRelation = (void *)mdd_dup((mdd_t *) imageInfo->methodData);
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Minimizes transition relation with given constraint.]
+
+  Description [Minimizes transition relation with given constraint.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgMinimizeTransitionRelationMono(Img_ImageInfo_t *imageInfo,
+	array_t *constrainArray, Img_MinimizeType minimizeMethod,
+	int printStatus)
+{
+  mdd_t *relation, *simplifiedRelation;
+  int i, size = 0;
+  mdd_t *constrain;
+
+  relation = (mdd_t *)imageInfo->methodData;
+
+  if (printStatus)
+    size = bdd_size(relation);
+
+  for (i = 0; i < array_n(constrainArray); i++) {
+    constrain = array_fetch(mdd_t *, constrainArray, i);
+    simplifiedRelation = Img_MinimizeImage(relation, constrain, minimizeMethod,
+					   TRUE);
+    if (printStatus) {
+      (void) fprintf(vis_stdout, "Info: minimized relation %d | %d => %d\n",
+		     bdd_size(relation), bdd_size(constrain),
+		     bdd_size(simplifiedRelation));
+    }
+    mdd_free(relation);
+    relation = simplifiedRelation;
+  }
+  imageInfo->methodData = (void *)relation;
+
+  if (printStatus) {
+    (void) fprintf(vis_stdout,
+	"IMG Info: minimized relation [%d | %ld => %d]\n",
+		   size, bdd_size_multiple(constrainArray),
+		   bdd_size(relation));
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Add dont care to transition relation.]
+
+  Description [Add dont care to transition relation. The constrain
+  array contains care sets.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgAddDontCareToTransitionRelationMono(Img_ImageInfo_t *imageInfo,
+	array_t *constrainArray, Img_MinimizeType minimizeMethod,
+	int printStatus)
+{
+  mdd_t *relation, *simplifiedRelation;
+  int i, size = 0;
+  mdd_t *constrain;
+
+  relation = (mdd_t *)imageInfo->methodData;
+
+  if (printStatus)
+    size = bdd_size(relation);
+
+  for (i = 0; i < array_n(constrainArray); i++) {
+    constrain = array_fetch(mdd_t *, constrainArray, i);
+    simplifiedRelation = Img_AddDontCareToImage(relation,
+					     constrain, minimizeMethod);
+    if (printStatus) {
+      (void) fprintf(vis_stdout, "Info: minimized relation %d | %d => %d\n",
+		     bdd_size(relation), bdd_size(constrain),
+		     bdd_size(simplifiedRelation));
+    }
+    mdd_free(relation);
+    relation = simplifiedRelation;
+  }
+  imageInfo->methodData = (void *)relation;
+
+  if (printStatus) {
+    (void) fprintf(vis_stdout,
+	"IMG Info: minimized relation [%d | %ld => %d]\n",
+		   size, bdd_size_multiple(constrainArray),
+		   bdd_size(relation));
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Abstracts out given variables from transition relation.]
+
+  Description [Abstracts out given variables from transition relation.
+  abstractVars should be an array of bdd variables.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgAbstractTransitionRelationMono(Img_ImageInfo_t *imageInfo,
+	array_t *abstractVars, mdd_t *abstractCube, int printStatus)
+{
+  mdd_t *relation, *abstractedRelation;
+
+  relation = (mdd_t *)imageInfo->methodData;
+  if (abstractCube)
+    abstractedRelation = bdd_smooth_with_cube(relation, abstractCube);
+  else
+    abstractedRelation = bdd_smooth(relation, abstractVars);
+  if (printStatus) {
+    (void) fprintf(vis_stdout, "Info: abstracted relation %d => %d\n",
+		     bdd_size(relation), bdd_size(abstractedRelation));
+  }
+  mdd_free(relation);
+  imageInfo->methodData = (void *)abstractedRelation;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Approximates transition relation.]
+
+  Description [Approximates transition relation.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+ImgApproximateTransitionRelationMono(mdd_manager *mgr,
+	Img_ImageInfo_t *imageInfo,
+	bdd_approx_dir_t approxDir,
+	bdd_approx_type_t approxMethod,
+	int approxThreshold,
+	double approxQuality,
+	double approxQualityBias,
+	mdd_t *bias)
+{
+  mdd_t *relation, *approxRelation;
+  int	unchanged;
+
+  relation = (mdd_t *)imageInfo->methodData;
+  approxRelation = Img_ApproximateImage(mgr, relation, approxDir, approxMethod,
+					approxThreshold, approxQuality,
+					approxQualityBias, bias);
+  if (bdd_is_tautology(approxRelation, 1)) {
+    fprintf(vis_stdout, "** img warning : bdd_one from subsetting.\n");
+    mdd_free(approxRelation);
+    unchanged = 1;
+  } else if (bdd_is_tautology(approxRelation, 0)) {
+    fprintf(vis_stdout, "** img warning : bdd_zero from subsetting.\n");
+    mdd_free(approxRelation);
+    unchanged = 1;
+  } else if (mdd_equal(approxRelation, relation)) {
+    mdd_free(approxRelation);
+    unchanged = 1;
+  } else {
+    mdd_free(relation);
+    imageInfo->methodData = (void *)approxRelation;
+    unchanged = 0;
+  }
+  return(unchanged);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Constrains/adds dont-cares to the bit relation and creates
+  a new transition relation.]
+
+  Description [Constrains/adds dont-cares to the bit relation and
+  creates a new transition relation. First, the existing transition
+  relation is freed. The bit relation is created and constrained by
+  the given constraint (underapprox) or its complement is add to the
+  bit relation (overapprox) depending on the underApprox flag. Then
+  the modified bit relation is clustered. The code is similar to
+  ImgImageInfoInitializeMono. An over or under approximation of the
+  transition relation may be created. The underApprox flag should be
+  TRUE for an underapproximation and FALSE for an
+  overapproximation. Although Img_MinimizeImage is used the
+  minimizeMethod flag for underapproximations has to be passed by
+  Img_GuidedSearchReadUnderApproxMinimizeMethod. The cleanUp flag is
+  currently useless but is maintained for uniformity with other Image
+  computation methods incase methodData changes in the future to store
+  bitRelations. The flag ]
+
+  SideEffects [Current transition relation and quantification schedule
+  are freed. Bit relations are freed if indicated.]
+
+  SeeAlso [Img_MultiwayLinearAndSmooth ImgImageInfoInitializeMono
+  Img_MinimizeImage Img_AddDontCareToImage ]
+******************************************************************************/
+void 
+ImgImageConstrainAndClusterTransitionRelationMono(Img_ImageInfo_t *imageInfo,
+						  mdd_t *constrain,
+						  Img_MinimizeType minimizeMethod,
+						  boolean underApprox,
+						  boolean cleanUp,
+						  boolean forceReorder,
+						  int printStatus)
+{
+  ImgFunctionData_t *functionData = &(imageInfo->functionData);
+  mdd_t *methodData = (mdd_t *)imageInfo->methodData;
+  int          i;
+  mdd_t       *monolithicT;
+  array_t     *rootRelations = array_alloc(mdd_t*, 0);
+  graph_t     *mddNetwork    = functionData->mddNetwork;
+  mdd_manager *mddManager    = Part_PartitionReadMddManager(mddNetwork);
+  array_t     *roots         = functionData->roots;
+  array_t     *leaves        = array_join(functionData->domainVars,
+					  functionData->quantifyVars);
+  array_t     *rootFunctions;
+  mdd_t       *relation;
+  
+  /*free existing  relation. */
+  if (!methodData) ImgImageInfoFreeMono(methodData);    
+  if (forceReorder) bdd_reorder(mddManager);
+  rootFunctions = Part_PartitionBuildFunctions(mddNetwork, roots,
+					       leaves,
+					       NIL(mdd_t)); 
+  
+  array_free(leaves);
+    
+  /*
+   * Take the product of the transition relation of all the root nodes
+   * and smooth out the quantify variables.
+   */
+  
+  /*
+   * Iterate over the function of all the root nodes.
+   */  
+  for (i=0; i<array_n(rootFunctions); i++) {
+    Mvf_Function_t *rootFunction  = array_fetch(Mvf_Function_t*, rootFunctions, i);
+    int             rangeVarMddId = array_fetch(int, functionData->rangeVars, i);
+    mdd_t          *rootRelation =
+      Mvf_FunctionBuildRelationWithVariable(rootFunction,
+					    rangeVarMddId); 
+    array_insert_last(mdd_t*, rootRelations, rootRelation);
+  }
+  Mvf_FunctionArrayFree(rootFunctions);
+
+  /* Constrain the bit relaitons */
+  if (constrain) {
+    arrayForEachItem(mdd_t *, rootRelations, i, relation) {
+      mdd_t *simplifiedRelation;
+      simplifiedRelation = Img_MinimizeImage(relation, constrain,
+					     minimizeMethod, underApprox);
+      if (printStatus) {
+	(void) fprintf(vis_stdout, "Info: minimized relation %d | %d => %d\n",
+		       bdd_size(relation), bdd_size(constrain),
+		       bdd_size(simplifiedRelation));
+      }
+      mdd_free(relation);
+      array_insert(mdd_t *, rootRelations, i, simplifiedRelation);
+    }
+  }
+
+  /* build the monolithic transition relation. */
+  monolithicT = Img_MultiwayLinearAndSmooth(mddManager, rootRelations,
+					    functionData->quantifyVars,
+					    functionData->domainVars,
+					    Img_Iwls95_c, Img_Forward_c);
+  mdd_array_free(rootRelations);
+  imageInfo->methodData = (void *)monolithicT;
+  if (printStatus) {
+    ImgImageInfoPrintMethodParamsMono(monolithicT, vis_stdout);
+  }
+
+}
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [A generic routine for computing the image.]
+
+  Description [This is a routine for image computation which is called
+  by both forward image and backward image computation. The frontier
+  set (the set of states for which the image is computed) is obtained
+  by finding a small size BDD between lower and upper bounds.
+  The transition relation is simplified by cofactoring
+  it with the domainSubset (frontier set) and with the toCareSet. The
+  order in which this simplification is unimportant from functionality
+  point of view, but the order might effect the BDD size of the
+  optimizedRelation. smoothVars should be an array of bdd variables.]
+
+  SideEffects []
+
+******************************************************************************/
+static mdd_t *
+ImageComputeMonolithic(mdd_t *methodData, mdd_t *fromLowerBound, mdd_t
+		*fromUpperBound, array_t *toCareSetArray,
+		array_t *smoothVars, mdd_t *smoothCube)
+{
+  mdd_t       *domainSubset, *image;
+  mdd_t       *optimizedRelation, *subOptimizedRelation;
+  mdd_t       *monolithicT = (mdd_t *)methodData;
+  
+  assert(monolithicT != NIL(mdd_t));
+  
+  /*
+   * Optimization steps:
+   * Choose the domainSubset optimally.
+   * Reduce the transition relation wrt to care set and domainSubset.
+   */
+  domainSubset = bdd_between(fromLowerBound,fromUpperBound);
+  subOptimizedRelation = bdd_cofactor_array(monolithicT, toCareSetArray);
+  optimizedRelation = bdd_cofactor(subOptimizedRelation, domainSubset);  
+  mdd_free(domainSubset);
+  mdd_free(subOptimizedRelation);
+  /*optimizedRelation = bdd_and(fromLowerBound, monolithicT, 1, 1);*/
+  if (smoothCube)
+    image = bdd_smooth_with_cube(optimizedRelation, smoothCube);
+  else {
+    if (array_n(smoothVars) == 0)
+      image = mdd_dup(optimizedRelation);
+    else
+      image = bdd_smooth(optimizedRelation, smoothVars);
+  }
+
+  mdd_free(optimizedRelation);
+  return image;
+}
+
Index: vis_dev/vis-2.3/src/img/imgTfm.c
===================================================================
--- vis_dev/vis-2.3/src/img/imgTfm.c	(revision 14)
+++ vis_dev/vis-2.3/src/img/imgTfm.c	(revision 14)
@@ -0,0 +1,3750 @@
+/**CFile***********************************************************************
+
+  FileName    [imgTfm.c]
+
+  PackageName [img]
+
+  Synopsis    [Routines for image and preimage computations using transition
+  function method.]
+
+  Description [Transition function method is implemented as a part of the
+  hybrid image computation (refer to "To Split or to Conjoin: The Question
+  in Image Computation", In-Ho Moon et. al. in the proceedings of DAC00.)
+  The hybrid method starts with transition function method based on splitting,
+  then switches to transition relation method based on conjunctions. The
+  decision is based on computing variable lifetimes from dependence matrix
+  dynamically at every recursion.
+  
+  The transition function method itself also can be used as an image_method,
+  however we do not recommend to use this method for general purpose. This
+  method can be used for experimental purpose. However, this method performs
+  quite well for most approximate reachability and some examples on exact
+  reachability.
+
+  There are two image computation methods in transition function method;
+  input splitting (default) and output splitting. Also three preimage
+  computation methods in transition function method are implemented; domain
+  cofactoring (default), sequential substitution, and simultaneous substitution.
+
+  The performance of transition function method is significantly depending on
+  both the choice of splitting variable and the use of image cache. However,
+  the hybrid method does not use image cache by default. Since the recursion
+  depths are bounded (not so deep) in the hybrid method, the cache hit ratio
+  is usually very low.
+
+  The implementation of the transition function method and the hybrid method
+  is very complicate since there are so many options. For details, try
+  print_tfm_options and print_hybrid_options commands in vis, also more
+  detailed descriptions for all options can be read by using help in vis
+  for the two commands.
+  
+  The hybrid method can start with either only function vector or only
+  transition relation, as well as with both function vector and transition
+  relation. In case of starting with only the function vector, when we switch
+  to conjoin, transition relation is built on demand. This method may consume
+  less memory than the others, but it may take more time since it is a big
+  overhead to build transition relation at every conjunction. To reduce this
+  overhead, the hybrid method can start with both function vector and transition
+  relation (default). In the presense of non-determinism, the hybrid mehtod
+  also can start with only transition relation without the function vector.]
+
+  SeeAlso     [imgTfmFwd.c imgTfmBwd.c imgTfmUtil.c imgTfmCache.c]
+
+  Author      [In-Ho Moon]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF COLORADO BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  COLORADO HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF COLORADO SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF COLORADO HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+#include "imgInt.h"
+
+static char rcsid[] UNUSED = "$Id: imgTfm.c,v 1.93 2005/04/23 14:30:54 jinh Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+static	st_table	*HookInfoList; /* adds a hook function to flush image
+					  cache before veriable reordering */
+static	int		nHookInfoList; /* the number of hook functions */
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static ImgTfmInfo_t * TfmInfoStructAlloc(Img_MethodType method);
+static int CompareIndex(const void *e1, const void *e2);
+static int HookInfoFunction(bdd_manager *mgr, char *str, void *method);
+static array_t * ChoosePartialVars(ImgTfmInfo_t *info, array_t *vector, int nPartialVars, int partialMethod);
+static void PrintRecursionStatistics(ImgTfmInfo_t *info, int preFlag);
+static void PrintFoundVariableStatistics(ImgTfmInfo_t *info, int preFlag);
+static void GetRecursionStatistics(ImgTfmInfo_t *info, int preFlag, int *nRecurs, int *nLeaves, int *nTurns, float *averageDepth, int *maxDepth, int *nDecomps, int *topDecomp, int *maxDecomp, float *averageDecomp);
+static int ReadSetIntValue(char *string, int l, int u, int defaultValue);
+static boolean ReadSetBooleanValue(char *string, boolean defaultValue);
+static void FindIntermediateVarsRecursively(ImgTfmInfo_t *info, mdd_manager *mddManager, vertex_t *vertex, int mddId, st_table *vertexTable, array_t *vector, st_table *domainQuantifyVarMddIdTable, array_t *intermediateVarMddIdArray);
+static void GetIntermediateRelationsRecursively(mdd_manager *mddManager, vertex_t *vertex, int mddId, st_table *vertexTable, array_t *relationArray, st_table *domainQuantifyVarMddIdTable, array_t *intermediateVarMddIdArray);
+static int CheckNondeterminism(Ntk_Network_t *network);
+static array_t * TfmCreateBitVector(ImgTfmInfo_t *info, int composeIntermediateVars, int findIntermediateVars);
+static array_t * TfmCreateBitRelationArray(ImgTfmInfo_t *info, int composeIntermediateVars, int findIntermediateVars);
+static void TfmSetupPartialTransitionRelation(ImgTfmInfo_t *info, array_t **partialRelationArray);
+static void TfmBuildRelationArray(ImgTfmInfo_t *info, ImgFunctionData_t *functionData, array_t *bitRelationArray, Img_DirectionType directionType, int writeMatrix);
+static void RebuildTransitionRelation(ImgTfmInfo_t *info, Img_DirectionType directionType);
+static void MinimizeTransitionFunction(array_t *vector, array_t *relationArray, mdd_t *constrain, Img_MinimizeType minimizeMethod, int printStatus);
+static void AddDontCareToTransitionFunction(array_t *vector, array_t *relationArray, mdd_t *constrain, Img_MinimizeType minimizeMethod, int printStatus);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the statistics of recursions of transition function
+  method.]
+
+  Description [Gets the statistics of recursions of transition function
+  method.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Img_TfmGetRecursionStatistics(Img_ImageInfo_t *imageInfo, int preFlag,
+			      int *nRecurs, int *nLeaves, int *nTurns,
+			      float *averageDepth, int *maxDepth, int *nDecomps,
+			      int *topDecomp, int *maxDecomp,
+			      float *averageDecomp)
+{
+  ImgTfmInfo_t	*info;
+
+  if (imageInfo->methodType != Img_Tfm_c &&
+      imageInfo->methodType != Img_Hybrid_c) {
+    return(0);
+  }
+
+  info = (ImgTfmInfo_t *)imageInfo->methodData;
+  if (preFlag) {
+    *nRecurs = info->nRecursionB;
+    *nLeaves = info->nLeavesB;
+    *nTurns = info->nTurnsB;
+    *averageDepth = info->averageDepthB;
+    *maxDepth = info->maxDepthB;
+    *nDecomps = 0;
+    *topDecomp = 0;
+    *maxDecomp = 0;
+    *averageDecomp = 0.0;
+  } else {
+    *nRecurs = info->nRecursion;
+    *nLeaves = info->nLeaves;
+    *nTurns = info->nTurns;
+    *averageDepth = info->averageDepth;
+    *maxDepth = info->maxDepth;
+    *nDecomps = info->nDecomps;
+    *topDecomp = info->topDecomp;
+    *maxDecomp = info->maxDecomp;
+    *averageDecomp = info->averageDecomp;
+  }
+  return(1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the statistics of image cache and recursions in
+  in transition function method.]
+
+  Description [Prints the statistics of image cache and recursions in
+  in transition function method.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Img_TfmPrintStatistics(Img_ImageInfo_t *imageInfo, Img_DirectionType dir)
+{
+  if (dir == Img_Forward_c || dir == Img_Both_c) {
+    Img_TfmPrintCacheStatistics(imageInfo, 0);
+    Img_TfmPrintRecursionStatistics(imageInfo, 0);
+  }
+  if (dir == Img_Backward_c || dir == Img_Both_c) {
+    Img_TfmPrintCacheStatistics(imageInfo, 1);
+    Img_TfmPrintRecursionStatistics(imageInfo, 1);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the statistics of recursions for transition function
+  method.]
+
+  Description [Prints the statistics of recursions for transition function
+  method.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Img_TfmPrintRecursionStatistics(Img_ImageInfo_t *imageInfo, int preFlag)
+{
+  float	avgDepth, avgDecomp;
+  int	nRecurs, nLeaves, nTurns, nDecomps, topDecomp, maxDecomp;
+  int	maxDepth;
+
+  (void) Img_TfmGetRecursionStatistics(imageInfo, preFlag, &nRecurs, &nLeaves,
+				&nTurns, &avgDepth, &maxDepth, &nDecomps,
+				&topDecomp, &maxDecomp, &avgDecomp);
+  if (preFlag)
+    fprintf(vis_stdout, "** recursion statistics of splitting (preImg) **\n");
+  else
+    fprintf(vis_stdout, "** recursion statistics of splitting (img) **\n");
+  fprintf(vis_stdout, "# recursions = %d\n", nRecurs);
+  fprintf(vis_stdout, "# leaves = %d\n", nLeaves);
+  fprintf(vis_stdout, "# turns = %d\n", nTurns);
+  fprintf(vis_stdout, "# average recursion depth = %g (max = %d)\n",
+	  avgDepth, maxDepth);
+  if (!preFlag) {
+    fprintf(vis_stdout,
+	    "# decompositions = %d (top = %d, max = %d, average = %g)\n",
+	    nDecomps, topDecomp, maxDecomp, avgDecomp);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the options for image computation using transition
+  function method.]
+
+  Description [Prints the options for image computation using transition
+  function method.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Img_PrintTfmOptions(void)
+{
+  ImgTfmOption_t	*options;
+  Img_MethodType	method;
+  char			*flagValue, dummy[40];
+
+  flagValue = Cmd_FlagReadByName("image_method");
+  if (flagValue) {
+    if (strcmp(flagValue, "hybrid") == 0)
+      method = Img_Hybrid_c;
+    else
+      method = Img_Tfm_c;
+  } else
+    method = Img_Tfm_c;
+
+  options = ImgTfmGetOptions(method);
+
+  switch (options->splitMethod) {
+  case 0 :
+    sprintf(dummy, "input split");
+    break;
+  case 1 :
+    sprintf(dummy, "output split");
+    break;
+  case 2 :
+    sprintf(dummy, "mixed");
+    break;
+  case 3 :
+    sprintf(dummy, "hybrid");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "TFM: tfm_split_method = %d (%s)\n",
+	  options->splitMethod, dummy);
+
+  switch (options->inputSplit) {
+  case 0 :
+    sprintf(dummy, "support before splitting");
+    break;
+  case 1 :
+    sprintf(dummy, "support after splitting");
+    break;
+  case 2 :
+    sprintf(dummy, "estimate BDD size after splitting");
+    break;
+  case 3 :
+    sprintf(dummy, "top variable");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "TFM: tfm_input_split = %d (%s)\n",
+	  options->inputSplit, dummy);
+
+  if (options->piSplitFlag)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "TFM: tfm_pi_split_flag = %s\n", dummy);
+
+  /* whether to convert image computation to range computation */
+  switch (options->rangeComp) {
+  case 0 :
+    sprintf(dummy, "do not convert");
+    break;
+  case 1 :
+    sprintf(dummy, "convert to range computation");
+    break;
+  case 2 :
+    sprintf(dummy, "convert with threshold");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "TFM: tfm_range_comp = %d (%s)\n",
+	  options->rangeComp, dummy);
+
+  fprintf(vis_stdout, "TFM: tfm_range_threshold = %d\n",
+	  options->rangeThreshold);
+
+  fprintf(vis_stdout, "TFM: tfm_range_try_threshold = %d\n",
+	  options->rangeTryThreshold);
+
+  if (options->rangeCheckReorder)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "TFM: tfm_range_check_reorder = %s\n", dummy);
+
+  switch (options->tieBreakMode) {
+  case 0 :
+    sprintf(dummy, "closest variable to top");
+    break;
+  case 1 :
+    sprintf(dummy, "smallest BDD size after splitting");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "TFM: tfm_tie_break_mode = %d (%s)\n",
+	  options->tieBreakMode, dummy);
+
+  switch (options->outputSplit) {
+  case 0 :
+    sprintf(dummy, "smallest BDD size");
+    break;
+  case 1 :
+    sprintf(dummy, "largest BDD size");
+    break;
+  case 2 :
+    sprintf(dummy, "top variable");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "TFM: tfm_output_split = %d (%s)\n",
+	  options->outputSplit, dummy);
+
+  fprintf(vis_stdout, "TFM: tfm_turn_depth = %d\n",
+	  options->turnDepth);
+
+  if (options->findDecompVar)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "TFM: tfm_find_decomp_var = %s\n", dummy);
+
+  if (options->sortVectorFlag)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "TFM: tfm_sort_vector_flag = %s\n", dummy);
+
+  if (options->printStatistics)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "TFM: tfm_print_stats = %s\n", dummy);
+
+  if (options->printBddSize)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "TFM: tfm_print_bdd_size = %s\n", dummy);
+
+  if (options->splitCubeFunc)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "TFM: tfm_split_cube_func = %s\n", dummy);
+
+  switch (options->findEssential) {
+  case 0 :
+    sprintf(dummy, "off");
+    break;
+  case 1 :
+    sprintf(dummy, "on");
+    break;
+  case 2 :
+    sprintf(dummy, "dynamic");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "TFM: tfm_find_essential = %d (%s)\n",
+	  options->findEssential, dummy);
+
+  switch (options->printEssential) {
+  case 0 :
+    sprintf(dummy, "off");
+    break;
+  case 1 :
+    sprintf(dummy, "at the end");
+    break;
+  case 2 :
+    sprintf(dummy, "at every image computation");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "TFM: tfm_print_essential = %d (%s)\n",
+	  options->printEssential, dummy);
+
+  switch (options->useCache) {
+  case 0 :
+    sprintf(dummy, "off");
+    break;
+  case 1 :
+    sprintf(dummy, "on");
+    break;
+  case 2 :
+    sprintf(dummy, "store all intermediate");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "TFM: tfm_use_cache = %d (%s)\n",
+	  options->useCache, dummy);
+
+  if (options->globalCache)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "TFM: tfm_global_cache = %s\n", dummy);
+
+  fprintf(vis_stdout, "TFM: tfm_max_chain_length = %d\n",
+	  options->maxChainLength);
+
+  fprintf(vis_stdout, "TFM: tfm_init_cache_size = %d\n",
+	  options->initCacheSize);
+
+  switch (options->autoFlushCache) {
+  case 0 :
+    sprintf(dummy, "when requested");
+    break;
+  case 1 :
+    sprintf(dummy, "at the end of image computation");
+    break;
+  case 2 :
+    sprintf(dummy, "before reordering");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "TFM: tfm_auto_flush_cache = %d (%s)\n",
+	  options->autoFlushCache, dummy);
+
+  if (options->composeIntermediateVars)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "TFM: tfm_compose_intermediate_vars = %s\n", dummy);
+
+  switch (options->preSplitMethod) {
+  case 0 :
+    sprintf(dummy, "input split");
+    break;
+  case 1 :
+    sprintf(dummy, "output split");
+    break;
+  case 2 :
+    sprintf(dummy, "mixed");
+    break;
+  case 3 :
+    sprintf(dummy, "substitution");
+    break;
+  case 4 :
+    sprintf(dummy, "hybrid");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "TFM: tfm_pre_split_method = %d (%s)\n",
+	  options->preSplitMethod, dummy);
+
+  switch (options->preInputSplit) {
+  case 0 :
+    sprintf(dummy, "support before splitting");
+    break;
+  case 1 :
+    sprintf(dummy, "support after splitting");
+    break;
+  case 2 :
+    sprintf(dummy, "estimate BDD size after splitting");
+    break;
+  case 3 :
+    sprintf(dummy, "top variable");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "TFM: tfm_pre_input_split = %d (%s)\n",
+	  options->preInputSplit, dummy);
+
+  switch (options->preOutputSplit) {
+  case 0 :
+    sprintf(dummy, "smallest BDD size");
+    break;
+  case 1 :
+    sprintf(dummy, "largest BDD size");
+    break;
+  case 2 :
+    sprintf(dummy, "top variable");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "TFM: tfm_pre_output_split = %d (%s)\n",
+	  options->preOutputSplit, dummy);
+
+  switch (options->preDcLeafMethod) {
+  case 0 :
+    sprintf(dummy, "substitution");
+    break;
+  case 1 :
+    sprintf(dummy, "constraint cofactoring");
+    break;
+  case 2 :
+    sprintf(dummy, "hybrid");
+    break;
+  default :
+    sprintf(dummy, "invalid");
+    break;
+  }
+  fprintf(vis_stdout, "TFM: tfm_pre_dc_leaf_method = %d (%s)\n",
+	  options->preDcLeafMethod, dummy);
+
+  if (options->preMinimize)
+    sprintf(dummy, "yes");
+  else
+    sprintf(dummy, "no");
+  fprintf(vis_stdout, "TFM: tfm_pre_minimize = %s\n", dummy);
+
+  fprintf(vis_stdout, "TFM: tfm_verbosity = %d\n",
+	  options->verbosity);
+
+  FREE(options);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes an image data structure for image
+  computation using transition function method.]
+
+  Description [Initialized an image data structure for image
+  computation using transition function method.]
+
+  SideEffects []
+
+******************************************************************************/
+void *
+ImgImageInfoInitializeTfm(void *methodData, ImgFunctionData_t * functionData,
+			  Img_DirectionType directionType,
+			  Img_MethodType method)
+{
+  int			i;
+  int			latches;
+  int			variables, nVars;
+  array_t		*vector;
+  graph_t		*mddNetwork;
+  mdd_manager		*mddManager;
+  array_t		*rangeVarMddIdArray;
+  ImgTfmInfo_t		*info = (ImgTfmInfo_t *)methodData;
+  int			index;
+  mdd_t			*var;
+  char			*flagValue;
+  char			filename[20];
+  int			composeIntermediateVars, findIntermediateVars;
+  int			nonDeterministic;
+
+  if (info) {
+    if (info->option->useCache) {
+      if (directionType == Img_Forward_c || directionType == Img_Both_c) {
+	if (!info->imgCache)
+	  ImgCacheInitTable(info, info->option->initCacheSize,
+			    info->option->globalCache, FALSE);
+      }
+      if (directionType == Img_Backward_c || directionType == Img_Both_c) {
+	if (!info->preCache)
+	  ImgCacheInitTable(info, info->option->initCacheSize,
+			    info->option->globalCache, TRUE);
+      }
+    }
+    if (info->buildTR &&
+	(((directionType == Img_Forward_c || directionType == Img_Both_c) &&
+	  !info->fwdClusteredRelationArray) ||
+	 ((directionType == Img_Backward_c || directionType == Img_Both_c) &&
+	  !info->bwdClusteredRelationArray))) {
+      TfmBuildRelationArray(info, functionData, NIL(array_t), directionType, 0);
+    }
+    return((void *)info);
+  }
+
+  mddNetwork = functionData->mddNetwork;
+  mddManager = Part_PartitionReadMddManager(mddNetwork);
+  rangeVarMddIdArray = functionData->rangeVars;
+
+  nonDeterministic = CheckNondeterminism(functionData->network);
+  if (nonDeterministic)
+    info = TfmInfoStructAlloc(Img_Hybrid_c);
+  else
+    info = TfmInfoStructAlloc(method);
+  info->nonDeterministic = nonDeterministic;
+  info->functionData = functionData;
+  info->quantifyVarsTable = st_init_table(st_numcmp, st_numhash);
+  for (i = 0; i < array_n(functionData->quantifyBddVars); i++) {
+    var = array_fetch(mdd_t *, functionData->quantifyBddVars, i);
+    index = (int)bdd_top_var_id(var);
+    st_insert(info->quantifyVarsTable, (char *)(long)index, NIL(char));
+  }
+  info->rangeVarsTable = st_init_table(st_numcmp, st_numhash);
+  for (i = 0; i < array_n(functionData->rangeBddVars); i++) {
+    var = array_fetch(mdd_t *, functionData->rangeBddVars, i);
+    index = (int)bdd_top_var_id(var);
+    st_insert(info->rangeVarsTable, (char *)(long)index, NIL(char));
+  }
+
+  latches = 2 * mdd_get_number_of_bdd_vars(mddManager, rangeVarMddIdArray);
+  nVars = latches + mdd_get_number_of_bdd_vars(mddManager,
+						functionData->quantifyVars);
+  variables = bdd_num_vars(mddManager); /* real number of variables */
+  info->nRealVars = nVars;
+  info->nVars = variables;
+
+  if (info->nonDeterministic) {
+    if (method == Img_Tfm_c) {
+      fprintf(vis_stdout,
+	"** tfm warning: The circuit may have nondeterminism.\n");
+      fprintf(vis_stdout, "\tautomatically switched to hybrid mode = 2.\n");
+      info->method = Img_Hybrid_c;
+    } else {
+      if (info->option->hybridMode == 2) {
+	if (info->option->buildPartialTR) {
+	  fprintf(vis_stdout,
+		"** hyb warning: The circuit may have nondeterminism.\n");
+	  fprintf(vis_stdout,
+		"\tdid not use partial transition relation.\n");
+	} else {
+	  fprintf(vis_stdout,
+		"** hyb info: The circuit may have nondeterminism.\n");
+	}
+      } else {
+	fprintf(vis_stdout,
+		"** hyb warning: The circuit may have nondeterminism.\n");
+	fprintf(vis_stdout, "\tautomatically switched to hybrid mode = 2.\n");
+      }
+    }
+  }
+  if (info->nonDeterministic ||
+      (info->option->hybridMode > 0 &&
+       (info->option->splitMethod == 3 || info->option->preSplitMethod == 4))) {
+    if (info->option->hybridMode == 2 || info->nonDeterministic)
+      info->buildTR = 2;
+    else
+      info->buildTR = 1;
+  }
+  if (info->buildTR == 2 &&
+      info->option->buildPartialTR &&
+      info->nonDeterministic == 0 &&
+      info->option->useCache == 0) {
+    info->buildPartialTR = TRUE;
+  }
+
+  info->imgKeepPiInTr = info->option->imgKeepPiInTr;
+  if (info->option->useCache)
+    info->preKeepPiInTr = TRUE;
+  else
+    info->preKeepPiInTr = info->option->preKeepPiInTr;
+
+  if (Part_PartitionReadMethod(mddNetwork) == Part_Frontier_c &&
+      nVars != variables) {
+    if (info->option->composeIntermediateVars) {
+      composeIntermediateVars = 1;
+      findIntermediateVars = 0;
+    } else {
+      composeIntermediateVars = 0;
+      findIntermediateVars = 1;
+    }
+  } else {
+    composeIntermediateVars = 0;
+    findIntermediateVars = 0;
+  }
+
+  if (info->buildTR != 2 || info->buildPartialTR) { /* deterministic */
+    vector = TfmCreateBitVector(info, composeIntermediateVars,
+				findIntermediateVars);
+  } else
+    vector = NIL(array_t);
+
+  info->manager = mddManager;
+  if (info->buildPartialTR)
+    info->fullVector = vector;
+  else
+    info->vector = vector;
+  if (info->buildTR == 2)
+    info->useConstraint = 1;
+  else if (info->option->splitMethod == 1)
+    info->useConstraint = 0;
+  else {
+    if (info->option->rangeComp == 2)
+      info->useConstraint = 2;
+    else if (info->option->rangeComp == 0)
+      info->useConstraint = 1;
+    else
+      info->useConstraint = 0;
+  }
+  if (info->option->useCache) {
+    if (directionType == Img_Forward_c || directionType == Img_Both_c) {
+      ImgCacheInitTable(info, info->option->initCacheSize,
+			info->option->globalCache, FALSE);
+    }
+    if (directionType == Img_Backward_c || directionType == Img_Both_c) {
+      ImgCacheInitTable(info, info->option->initCacheSize,
+			info->option->globalCache, TRUE);
+    }
+    if (info->option->autoFlushCache == 2) {
+      if (nHookInfoList == 0) {
+	HookInfoList = st_init_table(st_ptrcmp, st_ptrhash);
+	bdd_add_hook(info->manager, HookInfoFunction, BDD_PRE_REORDERING_HOOK);
+	st_insert(HookInfoList, (char *)info, NIL(char));
+      } else {
+	if (info->option->globalCache == 0)
+	  st_insert(HookInfoList, (char *)info, NIL(char));
+      }
+      nHookInfoList++;
+    }
+  }
+
+  info->trmOption = ImgGetTrmOptions();
+  info->domainVarBddArray = functionData->domainBddVars;
+  info->quantifyVarBddArray = functionData->quantifyBddVars;
+  info->rangeVarBddArray = functionData->rangeBddVars;
+
+  if (info->vector && info->option->sortVectorFlag && info->option->useCache)
+    array_sort(info->vector, CompareIndex);
+  if (info->buildPartialTR)
+    TfmSetupPartialTransitionRelation(info, NIL(array_t *));
+  if (info->buildTR)
+    TfmBuildRelationArray(info, functionData, NIL(array_t), directionType, 1);
+  if (info->buildTR == 1) {
+    ImgPrintVectorDependency(info, info->vector, info->option->verbosity);
+    if (info->option->writeSupportMatrix == 1) {
+      sprintf(filename, "support%d.mat", info->option->supportFileCount++);
+      ImgWriteSupportMatrix(info, info->vector, NIL(array_t), filename);
+    }
+  }
+  if (info->option->writeSupportMatrixAndStop)
+    exit(0);
+
+  flagValue = Cmd_FlagReadByName("image_eliminate_depend_vars");
+  if (flagValue == NIL(char))
+    info->eliminateDepend = 0; /* the default value */
+  else
+    info->eliminateDepend = atoi(flagValue);
+  if (info->eliminateDepend && bdd_get_package_name() != CUDD) {
+    fprintf(vis_stderr,
+    "** tfm error : image_eliminate_depend_vars is available for only CUDD.\n");
+    info->eliminateDepend = 0;
+  }
+  info->nPrevEliminatedFwd = -1;
+
+  flagValue = Cmd_FlagReadByName("image_verbosity");
+  if (flagValue)
+    info->imageVerbosity = atoi(flagValue);
+
+  if (info->option->printEssential) {
+    info->foundEssentials = ALLOC(int, IMG_TF_MAX_PRINT_DEPTH);
+    memset(info->foundEssentials, 0, sizeof(int) * IMG_TF_MAX_PRINT_DEPTH);
+  }
+  if (info->option->debug)
+    info->debugCareSet = bdd_one(mddManager);
+  else
+    info->debugCareSet = NIL(mdd_t);
+  return((void *)info);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the forward image of a set of states.]
+
+  Description [Computes the forward image of a set of states.]
+
+  SideEffects []
+
+  SeeAlso     [ImgImageInfoComputeFwdWithDomainVarsTfm]
+
+******************************************************************************/
+mdd_t *
+ImgImageInfoComputeFwdTfm(ImgFunctionData_t *functionData,
+			  Img_ImageInfo_t *imageInfo,
+			  mdd_t *fromLowerBound,
+			  mdd_t *fromUpperBound,
+			  array_t *toCareSetArray)
+{
+  ImgTfmInfo_t	*info = (ImgTfmInfo_t *)imageInfo->methodData;
+  mdd_t		*image, *domainSubset;
+
+  if (info->vector == NIL(array_t) &&
+      !(info->buildTR == 2 && info->fwdClusteredRelationArray)) {
+    fprintf(vis_stderr, "** img error: The data structure has not been ");
+    fprintf(vis_stderr, "initialized for image computation\n");
+    return(NIL(mdd_t));
+  }
+
+  info->updatedFlag = FALSE;
+  domainSubset = bdd_between(fromLowerBound, fromUpperBound);
+
+  image = ImgTfmImage(info, domainSubset);
+
+  mdd_free(domainSubset);
+  return(image);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the forward image of a set of states in terms
+  of domain variables.]
+
+  Description [Identical to ImgImageInfoComputeFwdTfm.]
+
+  SideEffects []
+
+  SeeAlso     [ImgImageInfoComputeFwdTfm]
+
+******************************************************************************/
+mdd_t *
+ImgImageInfoComputeFwdWithDomainVarsTfm(ImgFunctionData_t *functionData,
+					Img_ImageInfo_t *imageInfo,
+					mdd_t *fromLowerBound,
+					mdd_t *fromUpperBound,
+					array_t *toCareSetArray)
+{
+  mdd_t *image;
+
+  image = ImgImageInfoComputeFwdTfm(functionData,
+		imageInfo , fromLowerBound, fromUpperBound, toCareSetArray);
+  return(image);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the backward image of domainSubset.]
+
+  Description [Computes the backward image of domainSubset.]
+
+  SideEffects []
+
+  SeeAlso     [ImgImageInfoComputeBwdWithDomainVarsTfm]
+
+******************************************************************************/
+mdd_t *
+ImgImageInfoComputeBwdTfm(ImgFunctionData_t *functionData,
+			  Img_ImageInfo_t *imageInfo,
+			  mdd_t *fromLowerBound,
+			  mdd_t *fromUpperBound,
+			  array_t *toCareSetArray)
+{
+  ImgTfmInfo_t	*info = (ImgTfmInfo_t *)imageInfo->methodData;
+  mdd_t		*image, *domainSubset, *simplifiedImage;
+  array_t	*replace;
+
+  if (info->vector == NIL(array_t) &&
+      !(info->buildTR == 2 && info->bwdClusteredRelationArray)) {
+    fprintf(vis_stderr, "** img error: The data structure has not been ");
+    fprintf(vis_stderr, "initialized for backward image computation\n");
+    return(NIL(mdd_t));
+  }
+
+  info->updatedFlag = FALSE;
+  domainSubset = bdd_between(fromLowerBound, fromUpperBound);
+
+  if (info->toCareSetArray)
+    replace = info->toCareSetArray;
+  else {
+    replace = NIL(array_t);
+    info->toCareSetArray = toCareSetArray;
+  }
+  image = ImgTfmPreImage(info, domainSubset);
+  info->toCareSetArray = replace;
+
+  mdd_free(domainSubset);
+  simplifiedImage = bdd_minimize_array(image, toCareSetArray);
+  bdd_free(image);
+  return(simplifiedImage);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the backward image of a set of states.]
+
+  Description [Identical to ImgImageInfoComputeBwdTfm.]
+
+  SideEffects []
+
+  SeeAlso     [ImgImageInfoComputeBwdTfm]
+
+******************************************************************************/
+mdd_t *
+ImgImageInfoComputeBwdWithDomainVarsTfm(ImgFunctionData_t *functionData,
+					   Img_ImageInfo_t *imageInfo,
+					   mdd_t *fromLowerBound,
+					   mdd_t *fromUpperBound,
+					   array_t *toCareSetArray)
+{
+  mdd_t	*image;
+
+  image = ImgImageInfoComputeBwdTfm(functionData,
+		imageInfo, fromLowerBound, fromUpperBound, toCareSetArray);
+  return(image);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the memory associated with imageInfo.]
+
+  Description [Frees the memory associated with imageInfo.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgImageInfoFreeTfm(void *methodData)
+{
+  ImgTfmInfo_t	*info = (ImgTfmInfo_t *)methodData;
+
+  if (info == NIL(ImgTfmInfo_t)) {
+    fprintf(vis_stderr, "** img error: Trying to free the NULL image info\n");
+    return;
+  }
+  if (info->option->printStatistics) {
+    if (info->nRecursion) {
+      if (info->imgCache)
+	ImgPrintCacheStatistics(info->imgCache);
+      PrintRecursionStatistics(info, 0);
+      PrintFoundVariableStatistics(info, 0);
+    }
+    if (info->nRecursionB) {
+      if (info->preCache)
+	ImgPrintCacheStatistics(info->preCache);
+      PrintRecursionStatistics(info, 1);
+      PrintFoundVariableStatistics(info, 1);
+    }
+  }
+  if (info->vector != NIL(array_t))
+    ImgVectorFree(info->vector);
+  if (info->toCareSetArray != NIL(array_t))
+    mdd_array_free(info->toCareSetArray);
+  if (info->imgCache)
+    ImgCacheDestroyTable(info->imgCache, info->option->globalCache);
+  if (info->preCache)
+    ImgCacheDestroyTable(info->preCache, info->option->globalCache);
+  st_free_table(info->quantifyVarsTable);
+  st_free_table(info->rangeVarsTable);
+  if (info->intermediateVarsTable) {
+    st_free_table(info->intermediateVarsTable);
+    info->intermediateVarsTable = NIL(st_table);
+  }
+  if (info->intermediateBddVars) {
+    mdd_array_free(info->intermediateBddVars);
+    info->intermediateBddVars= NIL(array_t);
+  }
+  if (info->newQuantifyBddVars) {
+    mdd_array_free(info->newQuantifyBddVars);
+    info->newQuantifyBddVars = NIL(array_t);
+  }
+
+  if (info->option->useCache) {
+    if (info->option->autoFlushCache == 2) {
+      nHookInfoList--;
+      st_delete(HookInfoList, &info, NULL);
+      if (nHookInfoList == 0) {
+	st_free_table(HookInfoList);
+	bdd_remove_hook(info->manager, HookInfoFunction,
+			BDD_PRE_REORDERING_HOOK);
+      }
+    }
+  }
+  if (info->option != NULL)
+    FREE(info->option);
+
+  if (info->fwdClusteredRelationArray)
+    mdd_array_free(info->fwdClusteredRelationArray);
+  if (info->bwdClusteredRelationArray)
+    mdd_array_free(info->bwdClusteredRelationArray);
+  if (info->fwdArraySmoothVarBddArray)
+    mdd_array_array_free(info->fwdArraySmoothVarBddArray);
+  if (info->bwdArraySmoothVarBddArray)
+    mdd_array_array_free(info->bwdArraySmoothVarBddArray);
+  if (info->fwdSmoothVarCubeArray)
+    mdd_array_free(info->fwdSmoothVarCubeArray);
+  if (info->bwdSmoothVarCubeArray)
+    mdd_array_free(info->bwdSmoothVarCubeArray);
+  if (info->trmOption)
+    ImgFreeTrmOptions(info->trmOption);
+  if (info->partialBddVars)
+    mdd_array_free(info->partialBddVars);
+  if (info->partialVarFlag)
+    FREE(info->partialVarFlag);
+  if (info->fullVector != NIL(array_t))
+    ImgVectorFree(info->fullVector);
+
+  if (info->foundEssentials)
+    FREE(info->foundEssentials);
+  if (info->debugCareSet)
+    mdd_free(info->debugCareSet);
+
+  if (info->savedArraySmoothVarBddArray != NIL(array_t))
+    mdd_array_array_free(info->savedArraySmoothVarBddArray);
+  if (info->savedSmoothVarCubeArray != NIL(array_t))
+    mdd_array_free(info->savedSmoothVarCubeArray);
+  FREE(info);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints information about the transition function method.]
+
+  Description [This function is used to obtain the information about
+  the parameters used to initialize the imageInfo.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgImageInfoPrintMethodParamsTfm(void *methodData, FILE *fp)
+{
+  ImgTfmInfo_t *info = (ImgTfmInfo_t *)methodData;
+
+  if (fp == NULL)
+    return;
+  if (info->vector)
+    ImgPrintVectorDependency(info, info->vector, 1);
+  if (info->method == Img_Tfm_c) {
+    fprintf(vis_stdout,
+	    "For the options in tfm method, try print_tfm_options.\n");
+    return;
+  }
+  if (info->fwdClusteredRelationArray != NIL(array_t)) {
+    fprintf(fp, "Shared size of transition relation for forward image");
+    fprintf(fp, " computation is %10ld BDD nodes (%-4d components)\n",
+	    bdd_size_multiple(info->fwdClusteredRelationArray),
+	    array_n(info->fwdClusteredRelationArray));
+  }
+  if (info->bwdClusteredRelationArray != NIL(array_t)) {
+    fprintf(fp, "Shared size of transition relation for backward image");
+    fprintf(fp, " computation is %10ld BDD nodes (%-4d components)\n",
+	    bdd_size_multiple(info->bwdClusteredRelationArray),
+	    array_n(info->bwdClusteredRelationArray));
+  }
+  fprintf(vis_stdout, "For the options in hybrid method,");
+  fprintf(vis_stdout, " try print_hybrid_options and print_tfm_options.\n");
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Restores original transition function from saved.]
+
+  Description [Restores original transition function from saved.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgRestoreTransitionFunction(Img_ImageInfo_t *imageInfo,
+	Img_DirectionType directionType)
+{
+  ImgTfmInfo_t	*tfmInfo = (ImgTfmInfo_t *)imageInfo->methodData;
+
+  if (tfmInfo->vector) {
+    ImgVectorFree(tfmInfo->vector);
+    tfmInfo->vector = (array_t *)imageInfo->savedRelation;
+    imageInfo->savedRelation = NIL(void);
+  }
+  if (tfmInfo->fwdClusteredRelationArray) {
+    if (directionType == Img_Forward_c || directionType == Img_Both_c) {
+      mdd_array_free(tfmInfo->fwdClusteredRelationArray);
+      tfmInfo->fwdClusteredRelationArray = tfmInfo->fwdSavedRelation;
+      tfmInfo->fwdSavedRelation = NIL(array_t);
+    }
+  }
+  if (tfmInfo->bwdClusteredRelationArray) {
+    if (directionType == Img_Backward_c || directionType == Img_Both_c) {
+      mdd_array_free(tfmInfo->bwdClusteredRelationArray);
+      tfmInfo->bwdClusteredRelationArray = tfmInfo->bwdSavedRelation;
+      tfmInfo->bwdSavedRelation = NIL(array_t);
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Duplicates transition function.]
+
+  Description [Duplicates transition function.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgDuplicateTransitionFunction(Img_ImageInfo_t *imageInfo,
+				Img_DirectionType directionType)
+{
+  array_t	*copiedVector;
+  array_t	*copiedRelation;
+  ImgTfmInfo_t	*tfmInfo = (ImgTfmInfo_t *)imageInfo->methodData;
+
+  if (tfmInfo->vector) {
+    copiedVector = ImgVectorCopy(tfmInfo, tfmInfo->vector);
+    assert(!imageInfo->savedRelation);
+    imageInfo->savedRelation = (void *)tfmInfo->vector;
+    tfmInfo->vector = copiedVector;
+  }
+  if (tfmInfo->fwdClusteredRelationArray) {
+    if (directionType == Img_Forward_c || directionType == Img_Both_c) {
+      copiedRelation = mdd_array_duplicate(tfmInfo->fwdClusteredRelationArray);
+      tfmInfo->fwdSavedRelation = tfmInfo->fwdClusteredRelationArray;
+      tfmInfo->fwdClusteredRelationArray = copiedRelation;
+    }
+  }
+  if (tfmInfo->bwdClusteredRelationArray) {
+    if (directionType == Img_Backward_c || directionType == Img_Both_c) {
+      copiedRelation = mdd_array_duplicate(tfmInfo->bwdClusteredRelationArray);
+      tfmInfo->bwdSavedRelation = tfmInfo->bwdClusteredRelationArray;
+      tfmInfo->bwdClusteredRelationArray = copiedRelation;
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Minimizes transition function with given set of constraints.]
+
+  Description [Minimizes transition function with given set of constraints.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgMinimizeTransitionFunction(void *methodData,
+		    array_t *constrainArray, Img_MinimizeType minimizeMethod,
+		    Img_DirectionType directionType, int printStatus)
+{
+  ImgTfmInfo_t		*info = (ImgTfmInfo_t *)methodData;
+  int			i, j;
+  bdd_t			*function, *simplifiedFunction;
+  bdd_t			*constrain;
+  bdd_t			*relation, *simplifiedRelation;
+  int			size = 0;
+  long			sizeConstrain;
+  ImgComponent_t	*comp;
+
+  if (printStatus)
+    sizeConstrain = bdd_size_multiple(constrainArray);
+  else
+    sizeConstrain = 0;
+
+  if (info->vector) {
+    if (printStatus)
+      size = ImgVectorBddSize(info->vector);
+
+    arrayForEachItem(ImgComponent_t *, info->vector, i, comp) {
+      function = mdd_dup(comp->func);
+      arrayForEachItem(bdd_t *, constrainArray, j, constrain) {
+	if (bdd_is_tautology(constrain, 1))
+	  continue;
+	simplifiedFunction = Img_MinimizeImage(function, constrain,
+					       minimizeMethod, TRUE);
+	if (printStatus == 2) {
+	  (void) fprintf(vis_stdout,
+	      "IMG Info: minimized function %d | %d => %d in component %d\n",
+			  bdd_size(function), bdd_size(constrain),
+			  bdd_size(simplifiedFunction), i);
+	}
+	mdd_free(function);
+	function = simplifiedFunction;
+      }
+      if (mdd_equal(function, comp->func))
+	mdd_free(function);
+      else {
+	mdd_free(comp->func);
+	comp->func = function;
+	ImgSupportClear(info, comp->support);
+	ImgComponentGetSupport(comp);
+      }
+    }
+
+    if (printStatus) {
+      (void) fprintf(vis_stdout,
+        "IMG Info: minimized function [%d | %ld => %ld] with %d components\n",
+		   size, sizeConstrain,
+		   ImgVectorBddSize(info->vector), array_n(info->vector));
+    }
+  }
+
+  if (info->buildTR == 0)
+    return;
+  else if (info->buildTR == 1 && info->option->synchronizeTr) {
+    if (info->fwdClusteredRelationArray &&
+	(directionType == Img_Forward_c || directionType == Img_Both_c)) {
+      RebuildTransitionRelation(info, Img_Forward_c);
+    }
+    if (info->bwdClusteredRelationArray &&
+	(directionType == Img_Backward_c || directionType == Img_Both_c)) {
+      RebuildTransitionRelation(info, Img_Backward_c);
+    }
+    return;
+  }
+
+  if (info->fwdClusteredRelationArray &&
+      (directionType == Img_Forward_c || directionType == Img_Both_c)) {
+    if (printStatus)
+      size = bdd_size_multiple(info->fwdClusteredRelationArray);
+    arrayForEachItem(bdd_t *, constrainArray, i, constrain) {
+      if (bdd_is_tautology(constrain, 1))
+	continue;
+
+      arrayForEachItem(bdd_t*, info->fwdClusteredRelationArray, j, relation) {
+	simplifiedRelation = Img_MinimizeImage(relation, constrain,
+						 minimizeMethod, TRUE);
+	if (printStatus == 2) {
+	  (void) fprintf(vis_stdout,
+	    "IMG Info: minimized fwd relation %d | %d => %d in component %d\n",
+			 bdd_size(relation), bdd_size(constrain),
+			 bdd_size(simplifiedRelation), j);
+	}
+	mdd_free(relation);
+	array_insert(bdd_t*, info->fwdClusteredRelationArray, j,
+		     simplifiedRelation);
+      }
+    }
+    if (printStatus) {
+      (void) fprintf(vis_stdout,
+     "IMG Info: minimized fwd relation [%d | %ld => %ld] with %d components\n",
+		     size, sizeConstrain,
+		     bdd_size_multiple(info->fwdClusteredRelationArray),
+		     array_n(info->fwdClusteredRelationArray));
+    }
+  }
+  if (info->bwdClusteredRelationArray &&
+      (directionType == Img_Backward_c || directionType == Img_Both_c)) {
+    if (printStatus)
+      size = bdd_size_multiple(info->bwdClusteredRelationArray);
+    arrayForEachItem(bdd_t *, constrainArray, i, constrain) {
+      if (bdd_is_tautology(constrain, 1))
+	continue;
+
+      arrayForEachItem(bdd_t*, info->bwdClusteredRelationArray, j, relation) {
+	simplifiedRelation = Img_MinimizeImage(relation, constrain,
+						 minimizeMethod, TRUE);
+	if (printStatus == 2) {
+	  (void) fprintf(vis_stdout,
+	    "IMG Info: minimized bwd relation %d | %d => %d in component %d\n",
+			 bdd_size(relation), bdd_size(constrain),
+			 bdd_size(simplifiedRelation), j);
+	}
+	mdd_free(relation);
+	array_insert(bdd_t*, info->bwdClusteredRelationArray, j,
+		     simplifiedRelation);
+      }
+    }
+    if (printStatus) {
+      (void) fprintf(vis_stdout,
+     "IMG Info: minimized bwd relation [%d | %ld => %ld] with %d components\n",
+		     size, sizeConstrain,
+		     bdd_size_multiple(info->bwdClusteredRelationArray),
+		     array_n(info->bwdClusteredRelationArray));
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adds a dont care set to the transition function and relation.]
+
+  Description [Adds a dont care set to the transition function and relation.
+  This function is called during guided search.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgAddDontCareToTransitionFunction(void *methodData,
+				   array_t *constrainArray,
+				   Img_MinimizeType minimizeMethod,
+				   Img_DirectionType directionType,
+				   int printStatus)
+{
+  ImgTfmInfo_t		*info = (ImgTfmInfo_t *)methodData;
+  int			i, j;
+  bdd_t			*function, *simplifiedFunction;
+  bdd_t			*constrain;
+  bdd_t			*relation, *simplifiedRelation;
+  int			size = 0;
+  long			sizeConstrain;
+  ImgComponent_t	*comp;
+
+  if (printStatus)
+    sizeConstrain = bdd_size_multiple(constrainArray);
+  else
+    sizeConstrain = 0;
+
+  if (info->vector) {
+    if (printStatus)
+      size = ImgVectorBddSize(info->vector);
+
+    arrayForEachItem(ImgComponent_t *, info->vector, i, comp) {
+      function = mdd_dup(comp->func);
+      arrayForEachItem(bdd_t *, constrainArray, j, constrain) {
+	if (bdd_is_tautology(constrain, 1))
+	  continue;
+	simplifiedFunction = Img_AddDontCareToImage(function, constrain,
+						    minimizeMethod);
+	if (printStatus == 2) {
+	  (void) fprintf(vis_stdout,
+	      "IMG Info: minimized function %d | %d => %d in component %d\n",
+			  bdd_size(function), bdd_size(constrain),
+			  bdd_size(simplifiedFunction), i);
+	}
+	mdd_free(function);
+	function = simplifiedFunction;
+      }
+      if (mdd_equal(function, comp->func))
+	mdd_free(function);
+      else {
+	mdd_free(comp->func);
+	comp->func = function;
+	ImgSupportClear(info, comp->support);
+	ImgComponentGetSupport(comp);
+      }
+    }
+
+    if (printStatus) {
+      (void) fprintf(vis_stdout,
+        "IMG Info: minimized function [%d | %ld => %ld] with %d components\n",
+		   size, sizeConstrain,
+		   ImgVectorBddSize(info->vector), array_n(info->vector));
+    }
+  }
+
+  if (info->buildTR == 0)
+    return;
+  else if (info->buildTR == 1 && info->option->synchronizeTr) {
+    if (info->fwdClusteredRelationArray &&
+	(directionType == Img_Forward_c || directionType == Img_Both_c)) {
+      RebuildTransitionRelation(info, Img_Forward_c);
+    }
+    if (info->bwdClusteredRelationArray &&
+	(directionType == Img_Backward_c || directionType == Img_Both_c)) {
+      RebuildTransitionRelation(info, Img_Backward_c);
+    }
+    return;
+  }
+
+  if (info->fwdClusteredRelationArray &&
+      (directionType == Img_Forward_c || directionType == Img_Both_c)) {
+    if (printStatus)
+      size = bdd_size_multiple(info->fwdClusteredRelationArray);
+    arrayForEachItem(bdd_t *, constrainArray, i, constrain) {
+      if (bdd_is_tautology(constrain, 1))
+	continue;
+
+      arrayForEachItem(bdd_t*, info->fwdClusteredRelationArray, j, relation) {
+	simplifiedRelation = Img_AddDontCareToImage(relation, constrain,
+						    minimizeMethod);
+	if (printStatus == 2) {
+	  (void) fprintf(vis_stdout,
+	    "IMG Info: minimized fwd relation %d | %d => %d in component %d\n",
+			 bdd_size(relation), bdd_size(constrain),
+			 bdd_size(simplifiedRelation), j);
+	}
+	mdd_free(relation);
+	array_insert(bdd_t*, info->fwdClusteredRelationArray, j,
+		     simplifiedRelation);
+      }
+    }
+    if (printStatus) {
+      (void) fprintf(vis_stdout,
+     "IMG Info: minimized fwd relation [%d | %ld => %ld] with %d components\n",
+		     size, sizeConstrain,
+		     bdd_size_multiple(info->fwdClusteredRelationArray),
+		     array_n(info->fwdClusteredRelationArray));
+    }
+  }
+  if (info->bwdClusteredRelationArray &&
+      (directionType == Img_Backward_c || directionType == Img_Both_c)) {
+    if (printStatus)
+      size = bdd_size_multiple(info->bwdClusteredRelationArray);
+    arrayForEachItem(bdd_t *, constrainArray, i, constrain) {
+      if (bdd_is_tautology(constrain, 1))
+	continue;
+
+      arrayForEachItem(bdd_t*, info->bwdClusteredRelationArray, j, relation) {
+	simplifiedRelation = Img_AddDontCareToImage(relation, constrain,
+						    minimizeMethod);
+	if (printStatus == 2) {
+	  (void) fprintf(vis_stdout,
+	    "IMG Info: minimized bwd relation %d | %d => %d in component %d\n",
+			 bdd_size(relation), bdd_size(constrain),
+			 bdd_size(simplifiedRelation), j);
+	}
+	mdd_free(relation);
+	array_insert(bdd_t*, info->bwdClusteredRelationArray, j,
+		     simplifiedRelation);
+      }
+    }
+    if (printStatus) {
+      (void) fprintf(vis_stdout,
+     "IMG Info: minimized bwd relation [%d | %ld => %ld] with %d components\n",
+		     size, sizeConstrain,
+		     bdd_size_multiple(info->bwdClusteredRelationArray),
+		     array_n(info->bwdClusteredRelationArray));
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Abstracts out given variables from transition function.]
+
+  Description [Abstracts out given variables from transition function.
+  abstractVars should be an array of bdd variables.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgAbstractTransitionFunction(Img_ImageInfo_t *imageInfo,
+		array_t *abstractVars, mdd_t *abstractCube,
+		Img_DirectionType directionType, int printStatus)
+{
+  ImgTfmInfo_t		*info = (ImgTfmInfo_t *)imageInfo->methodData;
+  int			i, size = 0;
+  bdd_t			*abstractedFunction;
+  ImgComponent_t	*comp;
+  array_t		*vector;
+  int			flag = 0;
+  int			fwd_size = 0, bwd_size = 0;
+  bdd_t			*relation, *abstractedRelation;
+
+  if (!abstractVars || array_n(abstractVars) == 0)
+    return;
+
+  if (info->vector) {
+    if (printStatus)
+      size = ImgVectorBddSize(info->vector);
+
+    arrayForEachItem(ImgComponent_t *, info->vector, i, comp) {
+      if (bdd_is_tautology(comp->func, 1))
+	continue;
+      if (abstractCube)
+	abstractedFunction = bdd_smooth_with_cube(comp->func, abstractCube);
+      else
+	abstractedFunction = bdd_smooth(comp->func, abstractVars);
+      if (bdd_is_tautology(abstractedFunction, 1)) {
+	comp->flag = 1;
+	flag = 1;
+	continue;
+      }
+      if (mdd_equal(abstractedFunction, comp->func))
+	mdd_free(abstractedFunction);
+      else {
+	if (printStatus == 2) {
+	  (void) fprintf(vis_stdout,
+	      "IMG Info: abstracted function %d => %d in component %d\n",
+			 bdd_size(comp->func), bdd_size(abstractedFunction), i);
+	}
+	mdd_free(comp->func);
+	comp->func = abstractedFunction;
+	ImgSupportClear(info, comp->support);
+	ImgComponentGetSupport(comp);
+      }
+    }
+
+    if (flag) {
+      vector = info->vector;
+      info->vector = array_alloc(ImgComponent_t *, 0);
+      arrayForEachItem(ImgComponent_t *, vector, i, comp) {
+	if (comp->flag) {
+	  ImgComponentFree(comp);
+	  continue;
+	}
+	array_insert_last(ImgComponent_t *, info->vector, comp);
+      }
+      array_free(vector);
+    }
+
+    if (printStatus) {
+      (void) fprintf(vis_stdout,
+       "IMG Info: abstracted function [%d => %ld] with %d components\n",
+		     size, ImgVectorBddSize(info->vector),
+		     array_n(info->vector));
+    }
+  }
+
+  if (info->buildTR == 0)
+    return;
+  else if (info->buildTR == 1 && info->option->synchronizeTr) {
+    if (info->fwdClusteredRelationArray &&
+	(directionType == Img_Forward_c || directionType == Img_Both_c)) {
+      RebuildTransitionRelation(info, Img_Forward_c);
+    }
+    if (info->bwdClusteredRelationArray &&
+	(directionType == Img_Backward_c || directionType == Img_Both_c)) {
+      RebuildTransitionRelation(info, Img_Backward_c);
+    }
+    return;
+  }
+
+  if (printStatus) {
+    if (directionType == Img_Forward_c || directionType == Img_Both_c)
+      fwd_size = bdd_size_multiple(info->fwdClusteredRelationArray);
+    if (directionType == Img_Backward_c || directionType == Img_Both_c)
+      bwd_size = bdd_size_multiple(info->bwdClusteredRelationArray);
+  }
+  if (info->fwdClusteredRelationArray &&
+      (directionType == Img_Forward_c || directionType == Img_Both_c)) {
+    arrayForEachItem(bdd_t*, info->fwdClusteredRelationArray, i, relation) {
+      if (abstractCube)
+	abstractedRelation = bdd_smooth_with_cube(relation, abstractCube);
+      else
+	abstractedRelation = bdd_smooth(relation, abstractVars);
+      if (printStatus == 2) {
+        (void) fprintf(vis_stdout,
+	  "IMG Info: abstracted fwd relation %d => %d in component %d\n",
+			 bdd_size(relation), bdd_size(abstractedRelation), i);
+      }
+      mdd_free(relation);
+      array_insert(bdd_t*, info->fwdClusteredRelationArray, i,
+		   abstractedRelation);
+    }
+  }
+  if (info->bwdClusteredRelationArray &&
+      (directionType == Img_Backward_c || directionType == Img_Both_c)) {
+    arrayForEachItem(bdd_t*, info->bwdClusteredRelationArray, i, relation) {
+      if (abstractCube)
+	abstractedRelation = bdd_smooth_with_cube(relation, abstractCube);
+      else
+	abstractedRelation = bdd_smooth(relation, abstractVars);
+      if (printStatus == 2) {
+        (void) fprintf(vis_stdout,
+	  "IMG Info: abstracted bwd relation %d => %d in component %d\n",
+			 bdd_size(relation), bdd_size(abstractedRelation), i);
+      }
+      mdd_free(relation);
+      array_insert(bdd_t*, info->bwdClusteredRelationArray, i,
+		   abstractedRelation);
+    }
+  }
+  if (printStatus) {
+    if (directionType == Img_Forward_c || directionType == Img_Both_c) {
+      (void) fprintf(vis_stdout,
+     "IMG Info: abstracted fwd relation [%d => %ld] with %d components\n",
+		     fwd_size,
+		     bdd_size_multiple(info->fwdClusteredRelationArray),
+		     array_n(info->fwdClusteredRelationArray));
+    }
+    if (directionType == Img_Backward_c || directionType == Img_Both_c) {
+      (void) fprintf(vis_stdout,
+     "IMG Info: abstracted bwd relation [%d => %ld] with %d components\n",
+		     bwd_size,
+		     bdd_size_multiple(info->bwdClusteredRelationArray),
+		     array_n(info->bwdClusteredRelationArray));
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Approximate transition function.]
+
+  Description [Approximate transition function.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+ImgApproximateTransitionFunction(mdd_manager *mgr,
+		void *methodData, bdd_approx_dir_t approxDir,
+		bdd_approx_type_t approxMethod, int approxThreshold,
+		double approxQuality, double approxQualityBias,
+		Img_DirectionType directionType, mdd_t *bias)
+{
+  ImgTfmInfo_t		*info = (ImgTfmInfo_t *)methodData;
+  int			i;
+  bdd_t			*approxFunction;
+  int			unchanged = 0;
+  ImgComponent_t	*comp;
+  bdd_t			*relation, *approxRelation;
+
+  if (info->vector) {
+    arrayForEachItem(ImgComponent_t *, info->vector, i, comp) {
+      approxFunction = Img_ApproximateImage(mgr, comp->func,
+					    approxDir, approxMethod,
+					    approxThreshold, approxQuality,
+					    approxQualityBias, bias);
+      if (bdd_is_tautology(approxFunction, 1)) {
+	fprintf(vis_stdout,
+		  "** img warning : bdd_one from subsetting in [%d].\n", i);
+	mdd_free(approxFunction);
+	unchanged++;
+      } else if (bdd_is_tautology(approxFunction, 0)) {
+	fprintf(vis_stdout,
+		  "** img warning : bdd_zero from subsetting in [%d].\n", i);
+	mdd_free(approxFunction);
+	unchanged++;
+      } else if (mdd_equal(approxFunction, comp->func)) {
+	mdd_free(approxFunction);
+	unchanged++;
+      } else {
+	mdd_free(comp->func);
+	comp->func = approxFunction;
+	ImgSupportClear(info, comp->support);
+	ImgComponentGetSupport(comp);
+      }
+    }
+  }
+
+  if (info->buildTR == 0)
+    return(unchanged);
+  else if (info->buildTR == 1 && info->option->synchronizeTr) {
+    if (info->fwdClusteredRelationArray &&
+	(directionType == Img_Forward_c || directionType == Img_Both_c)) {
+      RebuildTransitionRelation(info, Img_Forward_c);
+    }
+    if (info->bwdClusteredRelationArray &&
+	(directionType == Img_Backward_c || directionType == Img_Both_c)) {
+      RebuildTransitionRelation(info, Img_Backward_c);
+    }
+    return(unchanged);
+  }
+
+  if (info->fwdClusteredRelationArray &&
+      (directionType == Img_Forward_c || directionType == Img_Both_c)) {
+    arrayForEachItem(bdd_t*, info->fwdClusteredRelationArray, i, relation) {
+      approxRelation = Img_ApproximateImage(mgr, relation,
+					    approxDir, approxMethod,
+					    approxThreshold, approxQuality,
+					    approxQualityBias, bias);
+      if (bdd_is_tautology(approxRelation, 1)) {
+	fprintf(vis_stdout,
+		"** img warning : bdd_one from subsetting in fwd[%d].\n", i);
+	mdd_free(approxRelation);
+	unchanged++;
+      } else if (bdd_is_tautology(approxRelation, 0)) {
+	fprintf(vis_stdout,
+		"** img warning : bdd_zero from subsetting in fwd[%d].\n", i);
+	mdd_free(approxRelation);
+	unchanged++;
+      } else if (mdd_equal(approxRelation, relation)) {
+	mdd_free(approxRelation);
+	unchanged++;
+      } else {
+	mdd_free(relation);
+	array_insert(bdd_t*, info->fwdClusteredRelationArray, i,
+		     approxRelation);
+      }
+    }
+  }
+  if (info->bwdClusteredRelationArray &&
+      (directionType == Img_Backward_c || directionType == Img_Both_c)) {
+    arrayForEachItem(bdd_t*, info->bwdClusteredRelationArray, i, relation) {
+      approxRelation = Img_ApproximateImage(mgr, relation,
+					    approxDir, approxMethod,
+					    approxThreshold, approxQuality,
+					    approxQualityBias, bias);
+      if (bdd_is_tautology(approxRelation, 1)) {
+	fprintf(vis_stdout,
+		"** img warning : bdd_one from subsetting in bwd[%d].\n", i);
+	mdd_free(approxRelation);
+	unchanged++;
+      } else if (bdd_is_tautology(approxRelation, 0)) {
+	fprintf(vis_stdout,
+		"** img warning : bdd_zero from subsetting in bwd[%d].\n", i);
+	mdd_free(approxRelation);
+	unchanged++;
+      } else if (mdd_equal(approxRelation, relation)) {
+	mdd_free(approxRelation);
+	unchanged++;
+      } else {
+	mdd_free(relation);
+	array_insert(bdd_t*, info->bwdClusteredRelationArray, i,
+		     approxRelation);
+      }
+    }
+  }
+  return(unchanged);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns current transition function.]
+
+  Description [Returns current transition function.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+ImgGetTransitionFunction(void *methodData, Img_DirectionType directionType)
+{
+  ImgTfmInfo_t *tfmInfo = (ImgTfmInfo_t *)methodData;
+  if (tfmInfo->vector)
+    return(tfmInfo->vector);
+  if (directionType == Img_Forward_c)
+    return(tfmInfo->fwdClusteredRelationArray);
+  return(tfmInfo->bwdClusteredRelationArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Overwrites transition function with given.]
+
+  Description [Overwrites transition function with given.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgUpdateTransitionFunction(void *methodData, array_t *vector,
+			    Img_DirectionType directionType)
+{
+  ImgTfmInfo_t *tfmInfo = (ImgTfmInfo_t *)methodData;
+  if (tfmInfo->vector)
+    tfmInfo->vector = vector;
+  else if (directionType == Img_Forward_c)
+    tfmInfo->fwdClusteredRelationArray = vector;
+  else
+    tfmInfo->bwdClusteredRelationArray = vector;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Replace ith transition function.]
+
+  Description [Replace ith transition function.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgReplaceIthTransitionFunction(void *methodData, int i, mdd_t *function,
+				Img_DirectionType directionType)
+{
+  ImgTfmInfo_t		*info = (ImgTfmInfo_t *)methodData;
+  array_t		*relationArray;
+  ImgComponent_t	*comp;
+  mdd_t			*old;
+
+  if (info->vector) {
+    comp = array_fetch(ImgComponent_t *, info->vector, i);
+    mdd_free(comp->func);
+    comp->func = function;
+    ImgSupportClear(info, comp->support);
+    ImgComponentGetSupport(comp);
+    return;
+  }
+
+  if (directionType == Img_Forward_c)
+    relationArray = info->fwdClusteredRelationArray;
+  else
+    relationArray = info->bwdClusteredRelationArray;
+
+  old = array_fetch(mdd_t *, relationArray, i);
+  mdd_free(old);
+  array_insert(mdd_t *, relationArray, i, function);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the necessary options for computing the image and returns
+               in the option structure.]
+
+  Description [Gets the necessary options for computing the image and returns
+               in the option structure.]
+
+  SideEffects []
+
+******************************************************************************/
+ImgTfmOption_t *
+ImgTfmGetOptions(Img_MethodType method)
+{
+  char			*flagValue;
+  ImgTfmOption_t	*option;
+
+  option = ALLOC(ImgTfmOption_t, 1);
+  memset(option, 0, sizeof(ImgTfmOption_t));
+
+  option->debug = ReadSetBooleanValue("tfm_debug", FALSE);
+  option->checkEquivalence = ReadSetBooleanValue("tfm_check_equivalence",
+						 FALSE);
+  option->writeSupportMatrix = ReadSetIntValue("tfm_write_support_matrix",
+						0, 2, 0);
+  option->writeSupportMatrixWithYvars =
+    ReadSetBooleanValue("tfm_write_support_matrix_with_y", FALSE);
+  option->writeSupportMatrixAndStop =
+    ReadSetBooleanValue("tfm_write_support_matrix_and_stop", FALSE);
+  option->writeSupportMatrixReverseRow =
+    ReadSetBooleanValue("tfm_write_support_matrix_reverse_row", TRUE);
+  option->writeSupportMatrixReverseCol =
+    ReadSetBooleanValue("tfm_write_support_matrix_reverse_col", TRUE);
+
+  option->verbosity = ReadSetIntValue("tfm_verbosity", 0, 2, 0);
+  if (method == Img_Tfm_c)
+    option->splitMethod = ReadSetIntValue("tfm_split_method", 0, 3, 0);
+  else
+    option->splitMethod = 3; /* the default value */
+  option->inputSplit = ReadSetIntValue("tfm_input_split", 0, 3, 0);
+  option->piSplitFlag = ReadSetBooleanValue("tfm_pi_split_flag", TRUE);
+  if (method == Img_Tfm_c)
+    option->rangeComp = ReadSetIntValue("tfm_range_comp", 0, 2, 1);
+  else
+    option->rangeComp = ReadSetIntValue("tfm_range_comp", 0, 2, 2);
+
+  flagValue = Cmd_FlagReadByName("tfm_range_threshold");
+  if (flagValue == NIL(char))
+    option->rangeThreshold = 10; /* the default value */
+  else
+    option->rangeThreshold = atoi(flagValue);
+
+  flagValue = Cmd_FlagReadByName("tfm_range_try_threshold");
+  if (flagValue == NIL(char))
+    option->rangeTryThreshold = 2; /* the default value */
+  else
+    option->rangeTryThreshold = atoi(flagValue);
+
+  option->rangeCheckReorder =
+    ReadSetBooleanValue("tfm_range_check_reorder", FALSE);
+  option->tieBreakMode = ReadSetIntValue("tfm_tie_break", 0, 1, 0);
+
+  option->outputSplit = ReadSetIntValue("tfm_output_split", 0, 2, 0);
+
+  flagValue = Cmd_FlagReadByName("tfm_turn_depth");
+  if (flagValue == NIL(char)) {
+    if (method == Img_Tfm_c)
+      option->turnDepth = 5; /* the default for tfm */
+    else
+      option->turnDepth = -1; /* the default for hybrid */
+  } else
+    option->turnDepth = atoi(flagValue);
+
+  option->findDecompVar = ReadSetBooleanValue("tfm_find_decomp_var", FALSE);
+  option->globalCache = ReadSetBooleanValue("tfm_global_cache", TRUE);
+
+  flagValue = Cmd_FlagReadByName("tfm_use_cache");
+  if (flagValue == NIL(char)) {
+    if (method == Img_Tfm_c)
+      option->useCache = 1;
+    else
+      option->useCache = 0;
+  } else
+    option->useCache = atoi(flagValue);
+
+  flagValue = Cmd_FlagReadByName("tfm_max_chain_length");
+  if (flagValue == NIL(char))
+    option->maxChainLength = 2; /* the default value */
+  else
+    option->maxChainLength = atoi(flagValue);
+
+  flagValue = Cmd_FlagReadByName("tfm_init_cache_size");
+  if (flagValue == NIL(char))
+    option->initCacheSize = 1001; /* the default value */
+  else
+    option->initCacheSize = atoi(flagValue);
+
+  option->autoFlushCache = ReadSetIntValue("tfm_auto_flush_cache", 0, 2, 1);
+  if (method == Img_Tfm_c)
+    option->sortVectorFlag = ReadSetBooleanValue("tfm_sort_vector", TRUE);
+  else
+    option->sortVectorFlag = ReadSetBooleanValue("tfm_sort_vector", FALSE);
+  option->printStatistics = ReadSetBooleanValue("tfm_print_stats", FALSE);
+  option->printBddSize = ReadSetBooleanValue("tfm_print_bdd_size", FALSE);
+
+  flagValue = Cmd_FlagReadByName("tfm_max_essential_depth");
+  if (flagValue == NIL(char))
+    option->maxEssentialDepth = 5; /* the default value */
+  else
+    option->maxEssentialDepth = atoi(flagValue);
+
+  option->findEssential = ReadSetIntValue("tfm_find_essential", 0, 2, 0);
+  if (option->findEssential && bdd_get_package_name() != CUDD) {
+    fprintf(vis_stderr,
+	    "** tfm error: tfm_find_essential is available for only CUDD.\n");
+    option->findEssential = 0; 
+  }
+  option->printEssential = ReadSetIntValue("tfm_print_essential", 0, 2, 0);
+  option->splitCubeFunc = ReadSetBooleanValue("tfm_split_cube_func", FALSE);
+  option->composeIntermediateVars =
+	ReadSetBooleanValue("tfm_compose_intermediate_vars", FALSE);
+
+  if (method == Img_Tfm_c)
+    option->preSplitMethod = ReadSetIntValue("tfm_pre_split_method", 0, 4, 0);
+  else
+    option->preSplitMethod = 4;
+  option->preInputSplit = ReadSetIntValue("tfm_pre_input_split", 0, 3, 0);
+  option->preOutputSplit = ReadSetIntValue("tfm_pre_output_split", 0, 2, 0);
+  option->preDcLeafMethod = ReadSetIntValue("tfm_pre_dc_leaf_method", 0, 2, 0);
+  option->preMinimize = ReadSetBooleanValue("tfm_pre_minimize", FALSE);
+
+  option->trSplitMethod = ReadSetIntValue("hybrid_tr_split_method", 0, 1, 0);
+
+  option->hybridMode = ReadSetIntValue("hybrid_mode", 0, 2, 1);
+  option->buildPartialTR =
+    ReadSetBooleanValue("hybrid_build_partial_tr", FALSE);
+
+  flagValue = Cmd_FlagReadByName("hybrid_partial_num_vars");
+  if (flagValue == NIL(char))
+    option->nPartialVars = 8; /* the default value */
+  else
+    option->nPartialVars = atoi(flagValue);
+
+  option->partialMethod = ReadSetIntValue("hybrid_partial_method", 0, 1, 0);
+
+  option->delayedSplit = ReadSetBooleanValue("hybrid_delayed_split", FALSE);
+
+  flagValue = Cmd_FlagReadByName("hybrid_split_min_depth");
+  if (flagValue == NIL(char))
+    option->splitMinDepth = 1; /* the default value */
+  else
+    option->splitMinDepth = atoi(flagValue);
+
+  flagValue = Cmd_FlagReadByName("hybrid_split_max_depth");
+  if (flagValue == NIL(char))
+    option->splitMaxDepth = 5; /* the default value */
+  else
+    option->splitMaxDepth = atoi(flagValue);
+
+  flagValue = Cmd_FlagReadByName("hybrid_pre_split_min_depth");
+  if (flagValue == NIL(char))
+    option->preSplitMinDepth = 0; /* the default value */
+  else
+    option->preSplitMinDepth = atoi(flagValue);
+
+  flagValue = Cmd_FlagReadByName("hybrid_pre_split_max_depth");
+  if (flagValue == NIL(char))
+    option->preSplitMaxDepth = 4; /* the default value */
+  else
+    option->preSplitMaxDepth = atoi(flagValue);
+
+  flagValue = Cmd_FlagReadByName("hybrid_lambda_threshold");
+  if (flagValue == NIL(char))
+    option->lambdaThreshold = 0.6; /* the default value */
+  else
+    sscanf(flagValue, "%f", &option->lambdaThreshold);
+
+  flagValue = Cmd_FlagReadByName("hybrid_pre_lambda_threshold");
+  if (flagValue == NIL(char))
+    option->preLambdaThreshold = 0.65; /* the default value */
+  else
+    sscanf(flagValue, "%f", &option->preLambdaThreshold);
+
+  flagValue = Cmd_FlagReadByName("hybrid_conjoin_vector_size");
+  if (flagValue == NIL(char))
+    option->conjoinVectorSize = 10; /* the default value */
+  else
+    option->conjoinVectorSize = atoi(flagValue);
+
+  flagValue = Cmd_FlagReadByName("hybrid_conjoin_relation_size");
+  if (flagValue == NIL(char))
+    option->conjoinRelationSize = 1; /* the default value */
+  else
+    option->conjoinRelationSize = atoi(flagValue);
+
+  flagValue = Cmd_FlagReadByName("hybrid_conjoin_relation_bdd_size");
+  if (flagValue == NIL(char))
+    option->conjoinRelationBddSize = 200; /* the default value */
+  else
+    option->conjoinRelationBddSize = atoi(flagValue);
+
+  flagValue = Cmd_FlagReadByName("hybrid_improve_lambda");
+  if (flagValue == NIL(char))
+    option->improveLambda = 0.1; /* the default value */
+  else
+    sscanf(flagValue, "%f", &option->improveLambda);
+
+  flagValue = Cmd_FlagReadByName("hybrid_improve_vector_size");
+  if (flagValue == NIL(char))
+    option->improveVectorSize = 3; /* the default value */
+  else
+    option->improveVectorSize = atoi(flagValue);
+
+  flagValue = Cmd_FlagReadByName("hybrid_improve_vector_bdd_size");
+  if (flagValue == NIL(char))
+    option->improveVectorBddSize = 30.0; /* the default value */
+  else
+    sscanf(flagValue, "%f", &option->improveVectorBddSize);
+
+  option->decideMode = ReadSetIntValue("hybrid_decide_mode", 0, 3, 3);
+
+  option->reorderWithFrom =
+    ReadSetBooleanValue("hybrid_reorder_with_from", TRUE);
+  option->preReorderWithFrom =
+    ReadSetBooleanValue("hybrid_pre_reorder_with_from", FALSE);
+
+  option->lambdaMode = ReadSetIntValue("hybrid_lambda_mode", 0, 2, 0);
+  option->preLambdaMode = ReadSetIntValue("hybrid_pre_lambda_mode", 0, 3, 2);
+  option->lambdaWithFrom = ReadSetBooleanValue("hybrid_lambda_with_from", TRUE);
+  option->lambdaWithTr = ReadSetBooleanValue("hybrid_lambda_with_tr", TRUE);
+  option->lambdaWithClustering =
+    ReadSetBooleanValue("hybrid_lambda_with_clustering", FALSE);
+
+  option->synchronizeTr = ReadSetBooleanValue("hybrid_synchronize_tr", FALSE);
+  option->imgKeepPiInTr = ReadSetBooleanValue("hybrid_img_keep_pi", FALSE);
+  option->preKeepPiInTr = ReadSetBooleanValue("hybrid_pre_keep_pi", FALSE);
+
+  flagValue = Cmd_FlagReadByName("hybrid_tr_method");
+  if (flagValue == NIL(char))
+    option->trMethod = Img_Iwls95_c; /* the default value */
+  else {
+    if (strcmp(flagValue, "iwls95") == 0)
+      option->trMethod = Img_Iwls95_c;
+    else if (strcmp(flagValue, "mlp") == 0)
+      option->trMethod = Img_Mlp_c;
+    else {
+      fprintf(vis_stderr,
+		"** tfm error : invalid value %s for hybrid_tr_method\n",
+		flagValue);
+      option->trMethod = Img_Iwls95_c;
+    }
+  }
+  option->preCanonical = ReadSetBooleanValue("hybrid_pre_canonical", FALSE);
+
+  option->printLambda = ReadSetBooleanValue("hybrid_print_lambda", FALSE);
+
+  return(option);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Frees current transition function vector and relation for the given
+  direction.]
+
+  Description [Frees current transition function vector and relation for the
+  given direction.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgImageFreeClusteredTransitionRelationTfm(void *methodData,
+					   Img_DirectionType directionType)
+{
+  ImgTfmInfo_t	*info = (ImgTfmInfo_t *)methodData;
+
+  if (info->vector) {
+    ImgVectorFree(info->vector);
+    info->vector = NIL(array_t);
+  }
+  if (info->fullVector) {
+    ImgVectorFree(info->fullVector);
+    info->fullVector = NIL(array_t);
+  }
+  if (info->partialBddVars)
+    mdd_array_free(info->partialBddVars);
+  if (info->partialVarFlag)
+    FREE(info->partialVarFlag);
+  if (info->fwdClusteredRelationArray != NIL(array_t)) {
+    mdd_array_free(info->fwdClusteredRelationArray);
+    info->fwdClusteredRelationArray = NIL(array_t);
+  }
+  if (info->bwdClusteredRelationArray != NIL(array_t)) {
+    mdd_array_free(info->bwdClusteredRelationArray);
+    info->bwdClusteredRelationArray = NIL(array_t);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Constrains the bit function and relation and creates a new
+  transition function vector and relation.]
+
+  Description [Constrains the bit function and relation and creates a new
+  transition function vector and relation. First, the existing transition
+  function vector and relation is
+  freed. The bit relation is created if it isnt stored already. The
+  bit relation is then copied into the Clustered relation of the given
+  direction and constrained by the given constraint. The bit relation
+  is clustered. In the case of the backward relation, the clustered
+  relation is minimized with respect to the care set.]
+
+  SideEffects [Frees current transition relation]
+
+******************************************************************************/
+void
+ImgImageConstrainAndClusterTransitionRelationTfm(Img_ImageInfo_t *imageInfo,
+						Img_DirectionType direction,
+						mdd_t *constrain,
+						Img_MinimizeType minimizeMethod,
+						boolean underApprox,
+						boolean cleanUp,
+						boolean forceReorder,
+						int printStatus)
+{
+  ImgFunctionData_t	*functionData = &(imageInfo->functionData);
+  ImgTfmInfo_t		*info = (ImgTfmInfo_t *)imageInfo->methodData;
+  graph_t		*mddNetwork;
+  mdd_manager		*mddManager = Part_PartitionReadMddManager(
+					functionData->mddNetwork);
+  int			composeIntermediateVars, findIntermediateVars;
+  array_t		*relationArray;
+
+  /* free existing function vector and/or relation */
+  ImgImageFreeClusteredTransitionRelationTfm(imageInfo->methodData, direction);
+  if (forceReorder)
+    bdd_reorder(mddManager);
+
+  mddNetwork = functionData->mddNetwork;
+
+  /* create function vector or bit relation */
+  if (Part_PartitionReadMethod(mddNetwork) == Part_Frontier_c &&
+      info->nVars != info->nRealVars) {
+    if (info->option->composeIntermediateVars) {
+      composeIntermediateVars = 1;
+      findIntermediateVars = 0;
+    } else {
+      composeIntermediateVars = 0;
+      findIntermediateVars = 1;
+    }
+  } else {
+    composeIntermediateVars = 0;
+    findIntermediateVars = 0;
+  }
+
+  if (info->buildTR == 2) { /* non-deterministic */
+    if (info->buildPartialTR) {
+      info->fullVector = TfmCreateBitVector(info, composeIntermediateVars,
+					    findIntermediateVars);
+      TfmSetupPartialTransitionRelation(info, &relationArray);
+    } else {
+      info->vector = NIL(array_t);
+      relationArray = TfmCreateBitRelationArray(info, composeIntermediateVars,
+						findIntermediateVars);
+    }
+  } else {
+    info->vector = TfmCreateBitVector(info, composeIntermediateVars,
+					findIntermediateVars);
+    if (info->buildTR == 0 || info->option->synchronizeTr)
+      relationArray = NIL(array_t);
+    else {
+      relationArray = TfmCreateBitRelationArray(info, composeIntermediateVars,
+						findIntermediateVars);
+    }
+  }
+
+  /* apply the constrain to the bit relation */
+  if (constrain) {
+    if (underApprox) {
+      MinimizeTransitionFunction(info->vector, relationArray,
+				 constrain, minimizeMethod, printStatus);
+    } else {
+      AddDontCareToTransitionFunction(info->vector, relationArray,
+				      constrain, minimizeMethod, printStatus);
+    }
+  }
+
+  if (info->vector && info->option->sortVectorFlag && info->option->useCache)
+    array_sort(info->vector, CompareIndex);
+  if (info->buildTR) {
+    TfmBuildRelationArray(info, functionData, relationArray, direction, 0);
+    if (relationArray)
+      mdd_array_free(relationArray);
+  }
+
+  /* Print information */
+  if (info->option->verbosity > 0){
+    if (info->method == Img_Tfm_c)
+      fprintf(vis_stdout,"Computing Image Using tfm technique.\n");
+    else
+      fprintf(vis_stdout,"Computing Image Using hybrid technique.\n");
+    fprintf(vis_stdout,"Total # of domain binary variables = %3d\n",
+	    array_n(functionData->domainBddVars));
+    fprintf(vis_stdout,"Total # of range binary variables = %3d\n",
+	    array_n(functionData->rangeBddVars));
+    fprintf(vis_stdout,"Total # of quantify binary variables = %3d\n",
+	    array_n(functionData->quantifyBddVars));
+    if (info->vector) {
+      (void) fprintf(vis_stdout,
+		     "Shared size of transition function vector for image ");
+      (void) fprintf(vis_stdout,
+		     "computation is %10ld BDD nodes (%-4d components)\n",
+		     ImgVectorBddSize(info->vector), array_n(info->vector));
+    }
+    if (((direction == Img_Forward_c) || (direction == Img_Both_c)) &&
+	(info->fwdClusteredRelationArray != NIL(array_t))) {
+      (void) fprintf(vis_stdout,
+		     "Shared size of transition relation for forward image ");
+      (void) fprintf(vis_stdout,
+		     "computation is %10ld BDD nodes (%-4d components)\n",
+		     bdd_size_multiple(info->fwdClusteredRelationArray),
+		     array_n(info->fwdClusteredRelationArray));
+    }
+    if (((direction == Img_Backward_c) || (direction == Img_Both_c)) &&
+      (info->bwdClusteredRelationArray != NIL(array_t))) {
+      (void) fprintf(vis_stdout,
+		     "Shared size of transition relation for backward image ");
+      (void) fprintf(vis_stdout,
+		     "computation is %10ld BDD nodes (%-4d components)\n",
+		     bdd_size_multiple(info->bwdClusteredRelationArray),
+		     array_n(info->bwdClusteredRelationArray));
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Check whether transition relation is built in hybrid.]
+
+  Description [Check whether transition relation is built in hybrid.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+ImgIsPartitionedTransitionRelationTfm(Img_ImageInfo_t *imageInfo)
+{
+  ImgTfmInfo_t	*info = (ImgTfmInfo_t *)imageInfo->methodData;
+
+  if (info->buildTR)
+    return(1);
+  else
+    return(0);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates and initializes the info structure for
+  transition function method.]
+
+  Description [Allocates and initializes the info structure for
+  transition function method.]
+
+  SideEffects []
+
+******************************************************************************/
+static ImgTfmInfo_t *
+TfmInfoStructAlloc(Img_MethodType method)
+{
+  ImgTfmInfo_t	*info;
+
+  info = ALLOC(ImgTfmInfo_t, 1);
+  memset(info, 0, sizeof(ImgTfmInfo_t));
+  info->method = method;
+  info->option = ImgTfmGetOptions(method);
+  return(info);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compares two variable indices of components.]
+
+  Description [Compares two variable indices of components.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CompareIndex(const void *e1, const void *e2)
+{
+  ImgComponent_t	*c1, *c2;
+  int			id1, id2;
+
+  c1 = *((ImgComponent_t **)e1);
+  c2 = *((ImgComponent_t **)e2);
+
+  id1 = (int)bdd_top_var_id(c1->var);
+  id2 = (int)bdd_top_var_id(c2->var);
+
+  if (id1 > id2)
+    return(1);
+  else if (id1 < id2)
+    return(-1);
+  else
+    return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Flushes cache entries in a list.]
+
+  Description [Flushes cache entries in a list.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+HookInfoFunction(bdd_manager *mgr, char *str, void *method)
+{
+  ImgTfmInfo_t	*info;
+  st_generator	*stGen;
+
+  if (HookInfoList) {
+    st_foreach_item(HookInfoList, stGen, &info, NULL) {
+      if (info->imgCache)
+	ImgFlushCache(info->imgCache);
+      if (info->preCache)
+	ImgFlushCache(info->preCache);
+    }
+  }
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Chooses variables for static splitting.]
+
+  Description [Chooses variables for static splitting. partialMethod is set
+  by hybrid_partial_method. Refer to print_hybrid_options command.]
+
+  SideEffects []
+
+******************************************************************************/
+static array_t *
+ChoosePartialVars(ImgTfmInfo_t *info, array_t *vector, int nPartialVars,
+		  int partialMethod)
+{
+  int			i, j, nVars;
+  ImgComponent_t	*comp;
+  char			*support;
+  int			*varCost;
+  int			big, small, nChosen, insert, id;
+  mdd_t			*var;
+  int			*partialVars = ALLOC(int, nPartialVars);
+  array_t		*partialBddVars = array_alloc(mdd_t *, 0);
+
+  nVars = info->nVars;
+  varCost = ALLOC(int, nVars);
+  memset(varCost, 0, sizeof(int) * nVars);
+
+  if (partialMethod == 0) {
+    /* chooses the variable whose function has the largest bdd size */
+    for (i = 0; i < array_n(vector); i++) {
+      comp = array_fetch(ImgComponent_t *, vector, i);
+      id = (int)bdd_top_var_id(comp->var);
+      varCost[id] = bdd_size(comp->func);
+    }
+  } else {
+    /* chooses the variable that appears the most frequently */
+    for (i = 0; i < array_n(vector); i++) {
+      comp = array_fetch(ImgComponent_t *, vector, i);
+      support = comp->support;
+      for (j = 0; j < nVars; j++) {
+	if (support[j])
+	  varCost[j]++;
+      }
+    }
+  }
+
+  nChosen = 0;
+  big = small = -1;
+  for (i = 0; i < nVars; i++) {
+    if (varCost[i] == 0)
+      continue;
+    if (st_lookup(info->quantifyVarsTable, (char *)(long)i, NIL(char *)))
+      continue;
+    if (info->intermediateVarsTable &&
+	st_lookup(info->intermediateVarsTable, (char *)(long)i, NIL(char *))) {
+      continue;
+    }
+    if (nChosen == 0) {
+      partialVars[0] = i;
+      nChosen = 1;
+      big = small = varCost[i];
+    } else if (varCost[i] < small) {
+      if (nChosen < nPartialVars) {
+	partialVars[nChosen] = i;
+	nChosen++;
+	small = varCost[i];
+      } else
+	continue;
+    } else if (varCost[i] > big) {
+      if (nChosen < nPartialVars) {
+	for (j = nChosen; j > 0; j--)
+	  partialVars[j] = partialVars[j - 1];
+	partialVars[0] = i;
+	nChosen++;
+	big = varCost[i];
+      } else {
+	for (j = nPartialVars - 1; j > 0; j--)
+	  partialVars[j] = partialVars[j - 1];
+	partialVars[0] = i;
+	big = varCost[i];
+	small = varCost[partialVars[nPartialVars - 1]];
+      }
+    } else {
+      insert = nChosen;
+      for (j = 0; j < nChosen; j++) {
+	if (varCost[i] > varCost[partialVars[j]]) {
+	  insert = j;
+	  break;
+	}
+      }
+      if (nChosen < nPartialVars) {
+	for (j = nChosen; j > insert; j--)
+	  partialVars[j] = partialVars[j - 1];
+	partialVars[insert] = i;
+	nChosen++;
+      } else if (insert < nChosen) {
+	for (j = nPartialVars - 1; j > insert; j--)
+	  partialVars[j] = partialVars[j - 1];
+	partialVars[insert] = i;
+	small = varCost[partialVars[nPartialVars - 1]];
+      }
+    }
+  }
+  FREE(varCost);
+
+  for (i = 0; i < nChosen; i++) {
+    var = bdd_var_with_index(info->manager, partialVars[i]);
+    array_insert_last(mdd_t *, partialBddVars, var);
+  }
+
+  FREE(partialVars);
+  return(partialBddVars);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints statistics of recursions for transition function method.]
+
+  Description [Prints statistics of recursions for transition function method.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+PrintRecursionStatistics(ImgTfmInfo_t *info, int preFlag)
+{
+  float	avgDepth, avgDecomp;
+  int	nRecurs, nLeaves, nTurns, nDecomps, topDecomp, maxDecomp, maxDepth;
+
+  GetRecursionStatistics(info, preFlag, &nRecurs, &nLeaves, &nTurns, &avgDepth,
+		 &maxDepth, &nDecomps, &topDecomp, &maxDecomp, &avgDecomp);
+  if (preFlag)
+    fprintf(vis_stdout, "** recursion statistics of splitting (preImg) **\n");
+  else
+    fprintf(vis_stdout, "** recursion statistics of splitting (img) **\n");
+  fprintf(vis_stdout, "# recursions = %d\n", nRecurs);
+  fprintf(vis_stdout, "# leaves = %d\n", nLeaves);
+  fprintf(vis_stdout, "# turns = %d\n", nTurns);
+  fprintf(vis_stdout, "# average recursion depth = %g (max = %d)\n",
+	  avgDepth, maxDepth);
+  if (!preFlag) {
+    fprintf(vis_stdout,
+	    "# decompositions = %d (top = %d, max = %d, average = %g)\n",
+	    nDecomps, topDecomp, maxDecomp, avgDecomp);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints statistics of finding essential and dependent variables.]
+
+  Description [Prints statistics of finding essential and dependent variables.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+PrintFoundVariableStatistics(ImgTfmInfo_t *info, int preFlag)
+{
+  int	i, maxDepth;
+
+  if (preFlag) {
+    fprintf(vis_stdout, "# split = %d, conjoin = %d\n",
+	    info->nSplitsB, info->nConjoinsB);
+    return;
+  }
+
+  fprintf(vis_stdout,
+    "# found essential vars = %d (top = %d, average = %g, averageDepth = %g)\n",
+	  info->nFoundEssentials, info->topFoundEssentialDepth,
+	  info->averageFoundEssential, info->averageFoundEssentialDepth);
+  if (info->option->printEssential == 1) {
+    maxDepth = info->maxDepth < IMG_TF_MAX_PRINT_DEPTH ?
+		info->maxDepth : IMG_TF_MAX_PRINT_DEPTH;
+    fprintf(vis_stdout, "foundEssential:");
+    for (i = 0; i < maxDepth; i++)
+      fprintf(vis_stdout, " [%d]%d", i, info->foundEssentials[i]);
+    fprintf(vis_stdout, "\n");
+  }
+  if (info->useConstraint == 2)
+    fprintf(vis_stdout, "# range computations = %d\n", info->nRangeComps);
+  fprintf(vis_stdout,
+	  "# found dependent vars = %d (average = %g)\n",
+	  info->nFoundDependVars, info->averageFoundDependVars);
+  fprintf(vis_stdout, "# tautologous subimage = %d\n", info->nEmptySubImage);
+  fprintf(vis_stdout, "# split = %d, conjoin = %d, cubeSplit = %d\n",
+	  info->nSplits, info->nConjoins, info->nCubeSplits);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the statistics of recursions of transition function
+  method.]
+
+  Description [Returns the statistics of recursions of transition function
+  method.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+GetRecursionStatistics(ImgTfmInfo_t *info, int preFlag, int *nRecurs,
+			int *nLeaves, int *nTurns, float *averageDepth,
+			int *maxDepth, int *nDecomps, int *topDecomp,
+			int *maxDecomp, float *averageDecomp)
+{
+  if (preFlag) {
+    *nRecurs = info->nRecursionB;
+    *nLeaves = info->nLeavesB;
+    *nTurns = info->nTurnsB;
+    *averageDepth = info->averageDepthB;
+    *maxDepth = info->maxDepthB;
+    *nDecomps = 0;
+    *topDecomp = 0;
+    *maxDecomp = 0;
+    *averageDecomp = 0.0;
+  } else {
+    *nRecurs = info->nRecursion;
+    *nLeaves = info->nLeaves;
+    *nTurns = info->nTurns;
+    *averageDepth = info->averageDepth;
+    *maxDepth = info->maxDepth;
+    *nDecomps = info->nDecomps;
+    *topDecomp = info->topDecomp;
+    *maxDecomp = info->maxDecomp;
+    *averageDecomp = info->averageDecomp;
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads a set integer value.]
+
+  Description [Reads a set integer value.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ReadSetIntValue(char *string, int l, int u, int defaultValue)
+{
+  char	*flagValue;
+  int	tmp;
+  int	value = defaultValue;
+
+  flagValue = Cmd_FlagReadByName(string);
+  if (flagValue != NIL(char)) {
+    sscanf(flagValue, "%d", &tmp);
+    if (tmp >= l && (tmp <= u || u == 0))
+      value = tmp;
+    else {
+      fprintf(vis_stderr,
+	"** tfm error: invalid value %d for %s[%d-%d]. **\n", tmp, string,
+	      l, u);
+    }
+  }
+
+  return(value);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads a set Boolean value.]
+
+  Description [Reads a set Boolean value.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static boolean
+ReadSetBooleanValue(char *string, boolean defaultValue)
+{
+  char		*flagValue;
+  boolean	value = defaultValue;
+
+  flagValue = Cmd_FlagReadByName(string);
+  if (flagValue != NIL(char)) {
+    if (strcmp(flagValue, "yes") == 0)
+      value = TRUE;
+    else if (strcmp(flagValue, "no") == 0)
+      value = FALSE;
+    else {
+      fprintf(vis_stderr,
+	      "** tfm error: invalid value %s for %s[yes/no]. **\n",
+	      flagValue, string);
+    }
+  }
+
+  return(value);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Traverses the partition recursively, creating the
+  functions for the intermediate vertices.]
+
+  Description [Traverses the partition recursively, creating the
+  functions for the intermediate vertices. This function is originated from
+  PartitionTraverseRecursively in imgIwls95.c]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+FindIntermediateVarsRecursively(ImgTfmInfo_t *info, mdd_manager *mddManager,
+				vertex_t *vertex, int mddId,
+				st_table *vertexTable, array_t *vector,
+				st_table *domainQuantifyVarMddIdTable,
+				array_t *intermediateVarMddIdArray)
+{
+  Mvf_Function_t	*mvf;
+  lsList		faninEdges;
+  lsGen			gen;
+  vertex_t		*faninVertex;
+  edge_t		*faninEdge;
+  array_t		*varBddFunctionArray, *bddArray;
+  int			i;
+  mdd_t			*var, *func;
+  ImgComponent_t	*comp;
+
+  if (st_is_member(vertexTable, (char *)vertex))
+    return;
+  st_insert(vertexTable, (char *)vertex, NIL(char));
+  if (mddId != -1) { /* This is not the next state function node */
+    /* There is an mdd variable associated with this vertex */
+    array_insert_last(int, intermediateVarMddIdArray, mddId);
+    mvf = Part_VertexReadFunction(vertex);
+    varBddFunctionArray = mdd_fn_array_to_bdd_fn_array(mddManager, mddId, mvf);
+    bddArray = mdd_id_to_bdd_array(mddManager, mddId);
+    assert(array_n(varBddFunctionArray) == array_n(bddArray));
+    for (i = 0; i < array_n(bddArray); i++) {
+      var = array_fetch(mdd_t *, bddArray, i);
+      func = array_fetch(mdd_t *, varBddFunctionArray, i);
+      comp = ImgComponentAlloc(info);
+      comp->var = var;
+      comp->func = func;
+      comp->intermediate = 1;
+      ImgComponentGetSupport(comp);
+      array_insert_last(ImgComponent_t *, vector, comp);
+    }
+    array_free(varBddFunctionArray);
+    array_free(bddArray);
+  }
+  faninEdges = g_get_in_edges(vertex);
+  if (lsLength(faninEdges) == 0)
+    return;
+  lsForEachItem(faninEdges, gen, faninEdge) {
+    faninVertex = g_e_source(faninEdge);
+    mddId = Part_VertexReadMddId(faninVertex);
+    if (st_is_member(domainQuantifyVarMddIdTable, (char *)(long)mddId)) {
+      /* This is either domain var or quantify var */
+      continue;
+    }
+    FindIntermediateVarsRecursively(info, mddManager, faninVertex, mddId,
+				    vertexTable, vector,
+				    domainQuantifyVarMddIdTable,
+				    intermediateVarMddIdArray);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Traverses the partition recursively, creating the
+  relations for the intermediate vertices.]
+
+  Description [Traverses the partition recursively, creating the
+  relations for the intermediate vertices. This function is a copy of
+  PartitionTraverseRecursively from imgIwls95.c.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+GetIntermediateRelationsRecursively(mdd_manager *mddManager, vertex_t *vertex,
+				    int mddId, st_table *vertexTable,
+				    array_t *relationArray,
+				    st_table *domainQuantifyVarMddIdTable,
+				    array_t *intermediateVarMddIdArray)
+{
+  Mvf_Function_t	*mvf;
+  lsList		faninEdges;
+  lsGen			gen;
+  vertex_t		*faninVertex;
+  edge_t		*faninEdge;
+  array_t		*varBddRelationArray;
+
+  if (st_is_member(vertexTable, (char *)vertex))
+    return;
+  st_insert(vertexTable, (char *)vertex, NIL(char));
+  if (mddId != -1) { /* This is not the next state function node */
+    /* There is an mdd variable associated with this vertex */
+    array_insert_last(int, intermediateVarMddIdArray, mddId);
+    mvf = Part_VertexReadFunction(vertex);
+    varBddRelationArray = mdd_fn_array_to_bdd_rel_array(mddManager, mddId, mvf);
+    array_append(relationArray, varBddRelationArray);
+    array_free(varBddRelationArray);
+  }
+  faninEdges = g_get_in_edges(vertex);
+  if (lsLength(faninEdges) == 0)
+    return;
+  lsForEachItem(faninEdges, gen, faninEdge) {
+    faninVertex = g_e_source(faninEdge);
+    mddId = Part_VertexReadMddId(faninVertex);
+    if (st_is_member(domainQuantifyVarMddIdTable, (char *)(long)mddId)) {
+      /* This is either domain var or quantify var */
+      continue;
+    }
+    GetIntermediateRelationsRecursively(mddManager, faninVertex, mddId,
+					vertexTable, relationArray,
+					domainQuantifyVarMddIdTable,
+					intermediateVarMddIdArray);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether the network is nondeterministic.]
+
+  Description [Checks whether the network is nondeterministic. However,
+  current implementatin is just checking whether the network has multi-valued
+  variables.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+CheckNondeterminism(Ntk_Network_t *network)
+{
+  Ntk_Node_t		*node;
+  lsGen			gen;
+  Var_Variable_t	*var;
+  int			numValues;
+
+  Ntk_NetworkForEachNode(network, gen, node) {
+    var = Ntk_NodeReadVariable(node);
+    numValues = Var_VariableReadNumValues(var);
+    if (numValues > 2) {
+      lsFinish(gen);
+      return 1;
+    }
+  }
+  return 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Creates function vector.]
+
+  Description [Creates function vector.]
+  
+  SideEffects []
+  
+  SeeAlso [ImgImageInfoInitializeTfm]
+  
+******************************************************************************/
+static array_t *
+TfmCreateBitVector(ImgTfmInfo_t *info,
+		   int composeIntermediateVars, int findIntermediateVars)
+{
+  int			i, j;
+  array_t		*vector;
+  graph_t		*mddNetwork;
+  mdd_manager		*mddManager;
+  array_t		*roots;
+  array_t		*rangeVarMddIdArray;
+  int			index;
+  mdd_t			*var;
+  ImgComponent_t	*comp;
+  st_table		*vertexTable;
+  st_table		*domainQuantifyVarMddIdTable;
+  array_t		*intermediateVarMddIdArray, *intermediateBddVars;
+  int			mddId;
+  ImgFunctionData_t	*functionData = info->functionData;
+
+  mddNetwork = functionData->mddNetwork;
+  mddManager = Part_PartitionReadMddManager(mddNetwork);
+  roots = functionData->roots;
+  rangeVarMddIdArray = functionData->rangeVars;
+
+  if (findIntermediateVars) {
+    vertexTable = st_init_table(st_ptrcmp, st_ptrhash);
+    domainQuantifyVarMddIdTable = st_init_table(st_numcmp, st_numhash);
+    intermediateVarMddIdArray = array_alloc(int, 0);
+    arrayForEachItem(int, functionData->domainVars, i, mddId) {
+      st_insert(domainQuantifyVarMddIdTable, (char *)(long)mddId, NIL(char));
+    }
+    arrayForEachItem(int, functionData->quantifyVars, i, mddId) {
+      st_insert(domainQuantifyVarMddIdTable, (char *)(long)mddId, NIL(char));
+    }
+  } else {
+    vertexTable = NIL(st_table);
+    domainQuantifyVarMddIdTable = NIL(st_table);
+    intermediateVarMddIdArray = NIL(array_t);
+  }
+
+  vector = array_alloc(ImgComponent_t *, 0);
+  /*
+   * Iterate over the function of all the root nodes.
+   */
+  for (i = 0; i < array_n(roots); i++) {
+    mdd_t *func;
+    char *nodeName = array_fetch(char*, roots, i);
+    vertex_t *vertex = Part_PartitionFindVertexByName(mddNetwork, nodeName);
+    Mvf_Function_t *mvf = Part_VertexReadFunction(vertex);
+    int mddId = array_fetch(int, rangeVarMddIdArray, i);
+    array_t *varBddFunctionArray = mdd_fn_array_to_bdd_fn_array(mddManager,
+								mddId, mvf);
+    array_t *bddArray = mdd_id_to_bdd_array(mddManager, mddId);
+
+    assert(array_n(varBddFunctionArray) == array_n(bddArray));
+    if (info->option->debug) {
+      mdd_t *rel1, *rel2;
+      array_t *varBddRelationArray = mdd_fn_array_to_bdd_rel_array(mddManager,
+								   mddId,
+								   mvf);
+      for (j = 0; j < array_n(bddArray); j++) {
+	var = array_fetch(mdd_t *, bddArray, j);
+	func = array_fetch(mdd_t *, varBddFunctionArray, j);
+	rel1 = array_fetch(mdd_t *, varBddRelationArray, j);
+	rel2 = mdd_xnor(var, func);
+	if (!mdd_equal(rel1, rel2)) {
+	  if (mdd_lequal(rel1, rel2, 1, 1))
+	    fprintf(vis_stdout, "** %d(%d): rel < funcRel\n", i, j);
+	  else if (mdd_lequal(rel2, rel1, 1, 1))
+	    fprintf(vis_stdout, "** %d(%d): rel > funcRel\n", i, j);
+	  else
+	    fprintf(vis_stdout, "** %d(%d): rel != funcRel\n", i, j);
+	}
+	mdd_free(rel1);
+	mdd_free(rel2);
+      }
+
+      array_free(varBddRelationArray);
+    }
+    for (j = 0; j < array_n(bddArray); j++) {
+      var = array_fetch(mdd_t *, bddArray, j);
+      func = array_fetch(mdd_t *, varBddFunctionArray, j);
+      if (array_n(bddArray) == 1 && bdd_is_tautology(func, 1)) {
+	array_t *varBddRelationArray = mdd_fn_array_to_bdd_rel_array(mddManager,
+								mddId, mvf);
+	mdd_t *relation = array_fetch(mdd_t *, varBddRelationArray, 0);
+	/* non-deterministic constant */
+	if (bdd_is_tautology(relation, 1)) {
+	  mdd_array_free(varBddRelationArray);
+	  mdd_free(func);
+	  break;
+	}
+	mdd_array_free(varBddRelationArray);
+      }
+      comp = ImgComponentAlloc(info);
+      comp->var = ImgSubstitute(var, functionData, Img_R2D_c);
+      if (composeIntermediateVars) {
+	comp->func = Img_ComposeIntermediateNodes(functionData->mddNetwork,
+		  func, functionData->domainVars, functionData->rangeVars,
+		  functionData->quantifyVars);
+	mdd_free(func);
+      } else
+	comp->func = func;
+      ImgComponentGetSupport(comp);
+      array_insert_last(ImgComponent_t *, vector, comp);
+    }
+    if (findIntermediateVars) {
+      int	n1, n2;
+
+      n1 = array_n(vector);
+      FindIntermediateVarsRecursively(info, mddManager, vertex, -1,
+					vertexTable, vector,
+					domainQuantifyVarMddIdTable,
+					intermediateVarMddIdArray);
+      n2 = array_n(vector);
+      info->nIntermediateVars += n2 - n1;
+    }
+    array_free(varBddFunctionArray);
+    mdd_array_free(bddArray);
+  }
+  if (findIntermediateVars) {
+    int	nonExistFlag;
+
+    /* checks whether intermediate variables are already found */
+    if (info->intermediateVarsTable && info->intermediateBddVars &&
+	info->newQuantifyBddVars) {
+      nonExistFlag = 0;
+    } else {
+      assert(!info->intermediateVarsTable);
+      assert(!info->intermediateBddVars);
+      assert(!info->newQuantifyBddVars);
+      nonExistFlag = 1;
+    }
+
+    if (info->option->verbosity) {
+      (void)fprintf(vis_stdout, "** img info: %d intermediate variables\n",
+	      info->nIntermediateVars);
+    }
+    st_free_table(vertexTable);
+    st_free_table(domainQuantifyVarMddIdTable);
+    if (nonExistFlag) {
+      intermediateBddVars = mdd_id_array_to_bdd_array(mddManager,
+						intermediateVarMddIdArray);
+    } else
+      intermediateBddVars = NIL(array_t);
+    array_free(intermediateVarMddIdArray);
+    if (nonExistFlag) {
+      info->intermediateVarsTable = st_init_table(st_numcmp, st_numhash);
+      for (i = 0; i < array_n(intermediateBddVars); i++) {
+	var = array_fetch(mdd_t *, intermediateBddVars, i);
+	index = (int)bdd_top_var_id(var);
+	st_insert(info->intermediateVarsTable, (char *)(long)index, NIL(char));
+      }
+      info->newQuantifyBddVars = mdd_array_duplicate(
+					functionData->quantifyBddVars);
+      for (i = 0; i < array_n(intermediateBddVars); i++) {
+	var = array_fetch(mdd_t *, intermediateBddVars, i);
+	array_insert_last(mdd_t *, info->newQuantifyBddVars, mdd_dup(var));
+      }
+      info->intermediateBddVars = intermediateBddVars;
+    }
+  }
+
+  return(vector);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Creates the bit relations.]
+
+  Description [Creates the bit relations.]
+  
+  SideEffects []
+  
+  SeeAlso [ImgImageInfoInitializeTfm]
+  
+******************************************************************************/
+static array_t *
+TfmCreateBitRelationArray(ImgTfmInfo_t *info,
+			  int composeIntermediateVars, int findIntermediateVars)
+{
+  array_t		*bddRelationArray = array_alloc(mdd_t*, 0);
+  ImgFunctionData_t	*functionData = info->functionData;
+  array_t		*domainVarMddIdArray = functionData->domainVars;
+  array_t		*rangeVarMddIdArray = functionData->rangeVars;
+  array_t		*quantifyVarMddIdArray = functionData->quantifyVars;
+  graph_t		*mddNetwork = functionData->mddNetwork;
+  array_t		*roots = functionData->roots;
+  int			i, j, n1, n2, mddId, nIntermediateVars = 0;
+  mdd_manager		*mddManager = Part_PartitionReadMddManager(mddNetwork);
+  st_table		*vertexTable = st_init_table(st_ptrcmp, st_ptrhash);
+  st_table		*domainQuantifyVarMddIdTable =
+				st_init_table(st_numcmp, st_numhash);
+  char			*nodeName;
+  mdd_t			*relation, *composedRelation;
+  array_t		*intermediateVarMddIdArray, *intermediateBddVars;
+  int			index;
+  mdd_t			*var;
+
+  if (findIntermediateVars)
+    intermediateVarMddIdArray = array_alloc(int, 0);
+  else
+    intermediateVarMddIdArray = NIL(array_t);
+
+  arrayForEachItem(int, domainVarMddIdArray, i, mddId) {
+    st_insert(domainQuantifyVarMddIdTable, (char *)(long)mddId, NIL(char));
+  }
+  arrayForEachItem(int, quantifyVarMddIdArray, i, mddId) {
+    st_insert(domainQuantifyVarMddIdTable, (char *)(long)mddId, NIL(char));
+  }
+  
+  arrayForEachItem(char *, roots, i, nodeName) {
+    vertex_t *vertex = Part_PartitionFindVertexByName(mddNetwork, nodeName);
+    Mvf_Function_t *mvf = Part_VertexReadFunction(vertex);
+    int mddId = array_fetch(int, rangeVarMddIdArray, i);
+    
+    array_t *varBddRelationArray = mdd_fn_array_to_bdd_rel_array(mddManager,
+								 mddId, mvf);
+    if (composeIntermediateVars) {
+      for (j = 0; j < array_n(varBddRelationArray); j++) {
+	relation = array_fetch(mdd_t *, varBddRelationArray, j);
+	composedRelation = Img_ComposeIntermediateNodes(
+		functionData->mddNetwork, relation, functionData->domainVars,
+		functionData->rangeVars, functionData->quantifyVars);
+	mdd_free(relation);
+	array_insert(mdd_t *, varBddRelationArray, j, composedRelation);
+      }
+
+      array_append(bddRelationArray, varBddRelationArray);
+      array_free(varBddRelationArray);
+    } else {
+      array_append(bddRelationArray, varBddRelationArray);
+      array_free(varBddRelationArray);
+
+      if (findIntermediateVars) {
+	if (info->option->verbosity)
+	  n1 = array_n(bddRelationArray);
+	GetIntermediateRelationsRecursively(mddManager, vertex, -1, vertexTable,
+					    bddRelationArray,
+					    domainQuantifyVarMddIdTable,
+					    intermediateVarMddIdArray);
+	if (info->option->verbosity) {
+	  n2 = array_n(bddRelationArray);
+	  nIntermediateVars += n2 - n1;
+	}
+      }
+    }
+  }
+
+  st_free_table(vertexTable);
+  st_free_table(domainQuantifyVarMddIdTable);
+  if (findIntermediateVars) {
+    int	nonExistFlag;
+
+    /* checks whether intermediate variables are already found */
+    if (info->intermediateVarsTable && info->intermediateBddVars &&
+	info->newQuantifyBddVars) {
+      nonExistFlag = 0;
+    } else {
+      assert(!info->intermediateVarsTable);
+      assert(!info->intermediateBddVars);
+      assert(!info->newQuantifyBddVars);
+      nonExistFlag = 1;
+    }
+
+    if (info->option->verbosity) {
+      (void)fprintf(vis_stdout, "** img info: %d intermediate variables\n",
+	      info->nIntermediateVars);
+    }
+    if (nonExistFlag) {
+      intermediateBddVars = mdd_id_array_to_bdd_array(mddManager,
+						intermediateVarMddIdArray);
+    } else
+      intermediateBddVars = NIL(array_t);
+    array_free(intermediateVarMddIdArray);
+    if (nonExistFlag) {
+      info->intermediateVarsTable = st_init_table(st_numcmp, st_numhash);
+      for (i = 0; i < array_n(intermediateBddVars); i++) {
+	var = array_fetch(mdd_t *, intermediateBddVars, i);
+	index = (int)bdd_top_var_id(var);
+	st_insert(info->intermediateVarsTable, (char *)(long)index, NIL(char));
+      }
+      info->newQuantifyBddVars = mdd_array_duplicate(
+					functionData->quantifyBddVars);
+      for (i = 0; i < array_n(intermediateBddVars); i++) {
+	var = array_fetch(mdd_t *, intermediateBddVars, i);
+	array_insert_last(mdd_t *, info->newQuantifyBddVars, mdd_dup(var));
+      }
+      info->intermediateBddVars = intermediateBddVars;
+    }
+  }
+  return(bddRelationArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Builds partial vector and relation array.]
+
+  Description [Builds partial vector and relation array.]
+  
+  SideEffects []
+  
+  SeeAlso [ImgImageInfoInitializeTfm]
+  
+******************************************************************************/
+static void
+TfmSetupPartialTransitionRelation(ImgTfmInfo_t *info,
+				  array_t **partialRelationArray)
+{
+  int			i, id;
+  mdd_t			*var, *relation;
+  ImgComponent_t	*comp, *newComp;
+  array_t		*partialVector;
+  ImgFunctionData_t	*functionData = info->functionData;
+
+  if (!info->buildPartialTR)
+    return;
+
+  info->partialBddVars = ChoosePartialVars(info, info->fullVector,
+					   info->option->nPartialVars,
+					   info->option->partialMethod);
+  info->partialVarFlag = ALLOC(char, info->nVars);
+  memset(info->partialVarFlag, 0, sizeof(char) * info->nVars);
+  for (i = 0; i < array_n(info->partialBddVars); i++) {
+    var = array_fetch(mdd_t *, info->partialBddVars, i);
+    id = (int)bdd_top_var_id(var);
+    info->partialVarFlag[id] = 1;
+  }
+
+  partialVector = array_alloc(ImgComponent_t *, 0);
+  if (partialRelationArray)
+    *partialRelationArray = array_alloc(mdd_t *, 0);
+
+  for (i = 0; i < array_n(info->fullVector); i++) {
+    comp = array_fetch(ImgComponent_t *, info->fullVector, i);
+    id = (int)bdd_top_var_id(comp->var);
+    if (info->partialVarFlag[id]) {
+      newComp = ImgComponentCopy(info, comp);
+      array_insert_last(ImgComponent_t *, partialVector, newComp);
+
+      if (newComp->intermediate)
+	relation = mdd_xnor(newComp->var, newComp->func);
+      else {
+	var = ImgSubstitute(newComp->var, functionData, Img_D2R_c);
+	relation = mdd_xnor(var, newComp->func);
+	mdd_free(var);
+      }
+      array_insert_last(mdd_t *, *partialRelationArray, relation);
+    }
+  }
+
+  info->vector = partialVector;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Builds relation array from function vector or bit relation.]
+
+  Description [Builds relation array from function vector or bit relation.]
+  
+  SideEffects []
+  
+  SeeAlso [ImgImageInfoInitializeTfm]
+  
+******************************************************************************/
+static void
+TfmBuildRelationArray(ImgTfmInfo_t *info, ImgFunctionData_t *functionData,
+			array_t *bitRelationArray,
+			Img_DirectionType directionType, int writeMatrix)
+{
+  int			i;
+  mdd_t			*var, *relation;
+  array_t		*relationArray;
+  ImgComponent_t	*comp;
+  int			id;
+  array_t		*domainVarBddArray, *quantifyVarBddArray;
+  mdd_t			*one, *res1, *res2;
+  char			filename[20];
+  int			composeIntermediateVars, findIntermediateVars;
+
+  if ((info->buildTR == 1 && info->option->synchronizeTr) ||
+	info->buildPartialTR) {
+    relationArray = array_alloc(mdd_t *, 0);
+    if (info->fullVector) {
+      for (i = 0; i < array_n(info->fullVector); i++) {
+	comp = array_fetch(ImgComponent_t *, info->fullVector, i);
+	id = (int)bdd_top_var_id(comp->var);
+	if (!info->partialVarFlag[id]) {
+	  if (comp->intermediate)
+	    relation = mdd_xnor(comp->var, comp->func);
+	  else {
+	    var = ImgSubstitute(comp->var, functionData, Img_D2R_c);
+	    relation = mdd_xnor(var, comp->func);
+	    mdd_free(var);
+	  }
+	  array_insert_last(mdd_t *, relationArray, relation);
+	}
+      }
+    } else {
+      for (i = 0; i < array_n(info->vector); i++) {
+	comp = array_fetch(ImgComponent_t *, info->vector, i);
+	if (comp->intermediate)
+	  relation = mdd_xnor(comp->var, comp->func);
+	else {
+	  var = ImgSubstitute(comp->var, functionData, Img_D2R_c);
+	  relation = mdd_xnor(var, comp->func);
+	  mdd_free(var);
+	}
+	array_insert_last(mdd_t *, relationArray, relation);
+      }
+    }
+
+    if (directionType == Img_Forward_c || directionType == Img_Both_c) {
+      if (info->imgKeepPiInTr) {
+	if (info->intermediateBddVars)
+	  quantifyVarBddArray = info->intermediateBddVars;
+	else
+	  quantifyVarBddArray = array_alloc(mdd_t *, 0);
+	domainVarBddArray = array_join(info->domainVarBddArray,
+					info->quantifyVarBddArray);
+      } else {
+	if (info->newQuantifyBddVars)
+	  quantifyVarBddArray = info->newQuantifyBddVars;
+	else
+	  quantifyVarBddArray = info->quantifyVarBddArray;
+	domainVarBddArray = info->domainVarBddArray;
+      }
+      info->fwdClusteredRelationArray = ImgClusterRelationArray(
+	info->manager, info->functionData,
+	info->option->trMethod, Img_Forward_c, info->trmOption,
+	relationArray, domainVarBddArray, quantifyVarBddArray,
+	info->rangeVarBddArray, &info->fwdArraySmoothVarBddArray,
+	&info->fwdSmoothVarCubeArray, 0);
+      if (writeMatrix && info->option->writeSupportMatrix == 3) {
+	sprintf(filename, "support%d.mat", info->option->supportFileCount++);
+	ImgWriteSupportMatrix(info, info->vector,
+				info->fwdClusteredRelationArray, filename);
+      } else if (writeMatrix && info->option->writeSupportMatrix == 2) {
+	sprintf(filename, "support%d.mat", info->option->supportFileCount++);
+	ImgWriteSupportMatrix(info, NIL(array_t),
+				info->fwdClusteredRelationArray, filename);
+      }
+      if (info->imgKeepPiInTr) {
+	if (!info->intermediateBddVars)
+	  array_free(quantifyVarBddArray);
+	array_free(domainVarBddArray);
+      }
+      if (info->option->checkEquivalence && (!info->fullVector)) {
+	assert(ImgCheckEquivalence(info, info->vector,
+				   info->fwdClusteredRelationArray,
+				   NIL(mdd_t), NIL(mdd_t), 0));
+      }
+      if (info->option->debug) {
+	one = mdd_one(info->manager);
+	if (info->fullVector) {
+	  res1 = ImgImageByHybrid(info, info->fullVector, one);
+	  res2 = ImgImageByHybridWithStaticSplit(info, info->vector, one,
+					info->fwdClusteredRelationArray,
+					NIL(mdd_t), NIL(mdd_t));
+	} else {
+	  res1 = ImgImageByHybrid(info, info->vector, one);
+	  res2 = ImgImageByHybridWithStaticSplit(info, NIL(array_t), one,
+					info->fwdClusteredRelationArray,
+					NIL(mdd_t), NIL(mdd_t));
+	}
+	assert(mdd_equal(res1, res2));
+	mdd_free(one);
+	mdd_free(res1);
+	mdd_free(res2);
+      }
+    }
+    if (directionType == Img_Backward_c || directionType == Img_Both_c) {
+      if (info->preKeepPiInTr) {
+	if (info->intermediateBddVars)
+	  quantifyVarBddArray = info->intermediateBddVars;
+	else
+	  quantifyVarBddArray = array_alloc(mdd_t *, 0);
+	domainVarBddArray = array_join(info->domainVarBddArray,
+					info->quantifyVarBddArray);
+      } else {
+	if (info->newQuantifyBddVars)
+	  quantifyVarBddArray = info->newQuantifyBddVars;
+	else
+	  quantifyVarBddArray = info->quantifyVarBddArray;
+	domainVarBddArray = info->domainVarBddArray;
+      }
+      info->bwdClusteredRelationArray = ImgClusterRelationArray(
+	info->manager, info->functionData,
+	info->option->trMethod, Img_Backward_c, info->trmOption,
+	relationArray, domainVarBddArray, quantifyVarBddArray,
+	info->rangeVarBddArray, &info->bwdArraySmoothVarBddArray,
+	&info->bwdSmoothVarCubeArray, 0);
+      if (writeMatrix && info->option->writeSupportMatrix == 3) {
+	sprintf(filename, "support%d.mat", info->option->supportFileCount++);
+	ImgWriteSupportMatrix(info, info->vector,
+				info->bwdClusteredRelationArray, filename);
+      } else if (writeMatrix && info->option->writeSupportMatrix == 2) {
+	sprintf(filename, "support%d.mat", info->option->supportFileCount++);
+	ImgWriteSupportMatrix(info, NIL(array_t),
+				info->bwdClusteredRelationArray, filename);
+      }
+      if (info->preKeepPiInTr) {
+	if (!info->intermediateBddVars)
+	  array_free(quantifyVarBddArray);
+	array_free(domainVarBddArray);
+      }
+      if (info->option->checkEquivalence && (!info->fullVector)) {
+	assert(ImgCheckEquivalence(info, info->vector,
+				   info->bwdClusteredRelationArray,
+				   NIL(mdd_t), NIL(mdd_t), 1));
+      }
+      if (info->option->debug) {
+	one = mdd_one(info->manager);
+	if (info->fullVector) {
+	  res1 = ImgImageByHybrid(info, info->fullVector, one);
+	  res2 = ImgImageByHybridWithStaticSplit(info, info->vector, one,
+					info->bwdClusteredRelationArray,
+					NIL(mdd_t), NIL(mdd_t));
+	} else {
+	  res1 = ImgImageByHybrid(info, info->vector, one);
+	  res2 = ImgImageByHybridWithStaticSplit(info, NIL(array_t), one,
+					info->bwdClusteredRelationArray,
+					NIL(mdd_t), NIL(mdd_t));
+	}
+	assert(mdd_equal(res1, res2));
+	mdd_free(one);
+	mdd_free(res1);
+	mdd_free(res2);
+      }
+    }
+
+    mdd_array_free(relationArray);
+  } else {
+    graph_t	*mddNetwork = functionData->mddNetwork;
+
+    if (bitRelationArray)
+      relationArray = bitRelationArray;
+    else {
+      if (Part_PartitionReadMethod(mddNetwork) == Part_Frontier_c &&
+	  info->nVars != info->nRealVars) {
+	if (info->option->composeIntermediateVars) {
+	  composeIntermediateVars = 1;
+	  findIntermediateVars = 0;
+	} else {
+	  composeIntermediateVars = 0;
+	  findIntermediateVars = 1;
+	}
+      } else {
+	composeIntermediateVars = 0;
+	findIntermediateVars = 0;
+      }
+
+      relationArray = TfmCreateBitRelationArray(info, composeIntermediateVars,
+						findIntermediateVars);
+    }
+
+    if (directionType == Img_Forward_c || directionType == Img_Both_c) {
+      if (info->imgKeepPiInTr) {
+	if (info->intermediateBddVars)
+	  quantifyVarBddArray = info->intermediateBddVars;
+	else
+	  quantifyVarBddArray = array_alloc(mdd_t *, 0);
+	domainVarBddArray = array_join(info->domainVarBddArray,
+					info->quantifyVarBddArray);
+      } else {
+	if (info->newQuantifyBddVars)
+	  quantifyVarBddArray = info->newQuantifyBddVars;
+	else
+	  quantifyVarBddArray = info->quantifyVarBddArray;
+	domainVarBddArray = info->domainVarBddArray;
+      }
+      info->fwdClusteredRelationArray = ImgClusterRelationArray(
+		info->manager, info->functionData, info->option->trMethod,
+		Img_Forward_c, info->trmOption, relationArray,
+		domainVarBddArray, quantifyVarBddArray,
+		info->rangeVarBddArray, &info->fwdArraySmoothVarBddArray,
+		&info->fwdSmoothVarCubeArray, 0);
+      if (writeMatrix && info->option->writeSupportMatrix >= 2) {
+	sprintf(filename, "support%d.mat", info->option->supportFileCount++);
+	ImgWriteSupportMatrix(info, NIL(array_t),
+				info->fwdClusteredRelationArray, filename);
+      }
+      if (info->imgKeepPiInTr) {
+	if (!info->intermediateBddVars)
+	  array_free(quantifyVarBddArray);
+	array_free(domainVarBddArray);
+      }
+    }
+    if (directionType == Img_Backward_c || directionType == Img_Both_c) {
+      if (info->preKeepPiInTr) {
+	if (info->intermediateBddVars)
+	  quantifyVarBddArray = info->intermediateBddVars;
+	else
+	  quantifyVarBddArray = array_alloc(mdd_t *, 0);
+	domainVarBddArray = array_join(info->domainVarBddArray,
+					info->quantifyVarBddArray);
+      } else {
+	if (info->newQuantifyBddVars)
+	  quantifyVarBddArray = info->newQuantifyBddVars;
+	else
+	  quantifyVarBddArray = info->quantifyVarBddArray;
+	domainVarBddArray = info->domainVarBddArray;
+      }
+      info->bwdClusteredRelationArray = ImgClusterRelationArray(
+	info->manager, info->functionData,
+	info->option->trMethod, Img_Backward_c, info->trmOption,
+	relationArray, domainVarBddArray, quantifyVarBddArray,
+	info->rangeVarBddArray, &info->bwdArraySmoothVarBddArray,
+	&info->bwdSmoothVarCubeArray, 0);
+      if (writeMatrix && info->option->writeSupportMatrix >= 2) {
+	sprintf(filename, "support%d.mat", info->option->supportFileCount++);
+	ImgWriteSupportMatrix(info, NIL(array_t),
+				info->bwdClusteredRelationArray, filename);
+      }
+      if (info->preKeepPiInTr) {
+	if (!info->intermediateBddVars)
+	  array_free(quantifyVarBddArray);
+	array_free(domainVarBddArray);
+      }
+    }
+
+    if (!bitRelationArray)
+      mdd_array_free(relationArray);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Rebuilds transition relation from function vector.]
+
+  Description [Rebuilds transition relation from function vector.]
+  
+  SideEffects []
+  
+  SeeAlso []
+  
+******************************************************************************/
+static void
+RebuildTransitionRelation(ImgTfmInfo_t *info, Img_DirectionType directionType)
+{
+  int			i;
+  mdd_t			*var, *relation;
+  ImgComponent_t	*comp;
+  array_t		*relationArray;
+  array_t		*quantifyVarBddArray, *domainVarBddArray;
+
+  relationArray = array_alloc(mdd_t *, 0);
+
+  for (i = 0; i < array_n(info->vector); i++) {
+    comp = array_fetch(ImgComponent_t *, info->vector, i);
+    var = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+    relation = mdd_xnor(var, comp->func);
+    array_insert_last(mdd_t *, relationArray, relation);
+    mdd_free(var);
+  }
+
+  if (directionType == Img_Forward_c || directionType == Img_Both_c) {
+    mdd_array_free(info->fwdClusteredRelationArray);
+    if (info->imgKeepPiInTr) {
+      if (info->intermediateBddVars)
+	quantifyVarBddArray = info->intermediateBddVars;
+      else
+	quantifyVarBddArray = array_alloc(mdd_t *, 0);
+      domainVarBddArray = array_join(info->domainVarBddArray,
+				     info->quantifyVarBddArray);
+    } else {
+      if (info->newQuantifyBddVars)
+	quantifyVarBddArray = info->newQuantifyBddVars;
+      else
+	quantifyVarBddArray = info->quantifyVarBddArray;
+      domainVarBddArray = info->domainVarBddArray;
+    }
+    info->fwdClusteredRelationArray = ImgClusterRelationArray(
+	info->manager, info->functionData, info->option->trMethod,
+	Img_Forward_c, info->trmOption, relationArray,
+	domainVarBddArray, quantifyVarBddArray,
+	info->rangeVarBddArray, &info->fwdArraySmoothVarBddArray,
+	&info->fwdSmoothVarCubeArray, 0);
+    if (info->imgKeepPiInTr) {
+      if (!info->intermediateBddVars)
+	array_free(quantifyVarBddArray);
+      array_free(domainVarBddArray);
+    }
+  }
+  if (directionType == Img_Backward_c || directionType == Img_Both_c) {
+    mdd_array_free(info->bwdClusteredRelationArray);
+    if (info->preKeepPiInTr) {
+      if (info->intermediateBddVars)
+	quantifyVarBddArray = info->intermediateBddVars;
+      else
+	quantifyVarBddArray = array_alloc(mdd_t *, 0);
+      domainVarBddArray = array_join(info->domainVarBddArray,
+				     info->quantifyVarBddArray);
+    } else {
+      if (info->newQuantifyBddVars)
+	quantifyVarBddArray = info->newQuantifyBddVars;
+      else
+	quantifyVarBddArray = info->quantifyVarBddArray;
+      domainVarBddArray = info->domainVarBddArray;
+    }
+    info->bwdClusteredRelationArray = ImgClusterRelationArray(
+	    info->manager, info->functionData,
+	    info->option->trMethod, Img_Backward_c, info->trmOption,
+	    relationArray, domainVarBddArray, quantifyVarBddArray,
+	    info->rangeVarBddArray, &info->fwdArraySmoothVarBddArray,
+	    &info->fwdSmoothVarCubeArray, 0);
+    if (info->preKeepPiInTr) {
+      if (!info->intermediateBddVars)
+	array_free(quantifyVarBddArray);
+      array_free(domainVarBddArray);
+    }
+  }
+
+  mdd_array_free(relationArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Minimizes function vector or relation with given constraint.]
+
+  Description [Minimizes function vector or relation with given constraint.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+MinimizeTransitionFunction(array_t *vector, array_t *relationArray,
+			   mdd_t *constrain, Img_MinimizeType minimizeMethod,
+			   int printStatus)
+{
+  int		i;
+  bdd_t		*relation, *simplifiedRelation, *simplifiedFunc;
+  long		sizeConstrain = 0, size = 0;
+  ImgComponent_t *comp;
+
+  if (bdd_is_tautology(constrain, 1))
+    return;
+
+  if (vector) {
+    if (printStatus) {
+      size = ImgVectorBddSize(vector);
+      sizeConstrain = bdd_size(constrain);
+    }
+
+    arrayForEachItem(ImgComponent_t *, vector, i, comp) {
+      simplifiedFunc = Img_MinimizeImage(comp->func, constrain, minimizeMethod,
+					 TRUE);
+      if (printStatus == 2) {
+	(void)fprintf(vis_stdout,
+	    "IMG Info: minimized function %d | %ld => %d in component %d\n",
+		      bdd_size(comp->func), sizeConstrain,
+		      bdd_size(simplifiedFunc), i);
+      }
+      mdd_free(comp->func);
+      comp->func = simplifiedFunc;
+    }
+
+    if (printStatus) {
+      (void) fprintf(vis_stdout,
+       "IMG Info: minimized function [%ld | %ld => %ld] with %d components\n",
+		     size, sizeConstrain,
+		     ImgVectorBddSize(vector), array_n(vector));
+    }
+  }
+
+  if (relationArray) {
+    if (printStatus) {
+      size = bdd_size_multiple(relationArray);
+      sizeConstrain = bdd_size(constrain);
+    }
+
+    arrayForEachItem(bdd_t*, relationArray, i, relation) {
+      simplifiedRelation = Img_MinimizeImage(relation, constrain,
+					     minimizeMethod, TRUE);
+      if (printStatus == 2) {
+	(void)fprintf(vis_stdout,
+		"IMG Info: minimized relation %d | %ld => %d in component %d\n",
+		      bdd_size(relation), sizeConstrain,
+		      bdd_size(simplifiedRelation), i);
+      }
+      mdd_free(relation);
+      array_insert(bdd_t *, relationArray, i, simplifiedRelation);
+    }
+
+    if (printStatus) {
+      (void) fprintf(vis_stdout,
+       "IMG Info: minimized relation [%ld | %ld => %ld] with %d components\n",
+		     size, sizeConstrain,
+		     bdd_size_multiple(relationArray), array_n(relationArray));
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adds dont cares to function vector or relation.]
+
+  Description [Adds dont cares to function vector or relation.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+AddDontCareToTransitionFunction(array_t *vector, array_t *relationArray,
+				mdd_t *constrain,
+				Img_MinimizeType minimizeMethod,
+				int printStatus)
+{
+  int			i;
+  bdd_t			*relation, *simplifiedRelation, *simplifiedFunc;
+  long			sizeConstrain = 0, size = 0;
+  ImgComponent_t	*comp;
+
+  if (bdd_is_tautology(constrain, 1))
+    return;
+
+  if (vector) {
+    if (printStatus) {
+      size = ImgVectorBddSize(vector);
+      sizeConstrain = bdd_size(constrain);
+    }
+
+    arrayForEachItem(ImgComponent_t *, vector, i, comp) {
+      simplifiedFunc = Img_AddDontCareToImage(comp->func, constrain,
+					      minimizeMethod);
+      if (printStatus == 2) {
+	(void)fprintf(vis_stdout,
+	    "IMG Info: minimized function %d | %ld => %d in component %d\n",
+		      bdd_size(comp->func), sizeConstrain,
+		      bdd_size(simplifiedFunc), i);
+      }
+      mdd_free(comp->func);
+      comp->func = simplifiedFunc;
+    }
+
+    if (printStatus) {
+      (void) fprintf(vis_stdout,
+       "IMG Info: minimized function [%ld | %ld => %ld] with %d components\n",
+		     size, sizeConstrain,
+		     ImgVectorBddSize(vector), array_n(vector));
+    }
+  }
+
+  if (relationArray) {
+    if (printStatus) {
+      size = bdd_size_multiple(relationArray);
+      sizeConstrain = bdd_size(constrain);
+    }
+
+    arrayForEachItem(bdd_t*, relationArray, i, relation) {
+      simplifiedRelation = Img_AddDontCareToImage(relation, constrain,
+						  minimizeMethod);
+      if (printStatus == 2) {
+	(void)fprintf(vis_stdout,
+		"IMG Info: minimized relation %d | %ld => %d in component %d\n",
+		      bdd_size(relation), sizeConstrain,
+		      bdd_size(simplifiedRelation), i);
+      }
+      mdd_free(relation);
+      array_insert(bdd_t *, relationArray, i, simplifiedRelation);
+    }
+
+    if (printStatus) {
+      (void) fprintf(vis_stdout,
+       "IMG Info: minimized relation [%ld | %ld => %ld] with %d components\n",
+		     size, sizeConstrain,
+		     bdd_size_multiple(relationArray), array_n(relationArray));
+    }
+  }
+}
Index: vis_dev/vis-2.3/src/img/imgTfmBwd.c
===================================================================
--- vis_dev/vis-2.3/src/img/imgTfmBwd.c	(revision 14)
+++ vis_dev/vis-2.3/src/img/imgTfmBwd.c	(revision 14)
@@ -0,0 +1,2741 @@
+/**CFile***********************************************************************
+
+  FileName    [imgTfmBwd.c]
+
+  PackageName [img]
+
+  Synopsis    [Routines for preimage computation using transition function
+  method.]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [In-Ho Moon]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF COLORADO BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  COLORADO HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF COLORADO SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF COLORADO HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+#include "imgInt.h"
+
+static char rcsid[] UNUSED = "$Id: imgTfmBwd.c,v 1.29 2002/08/18 04:47:07 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static bdd_t * PreImageByDomainCofactoring(ImgTfmInfo_t *info, array_t *delta, bdd_t *image, array_t *relationArray, mdd_t *cofactorCube, mdd_t *abstractCube, int splitMethod, int turnDepth, int depth);
+static mdd_t * PreImageByStaticDomainCofactoring(ImgTfmInfo_t *info, array_t *vector, mdd_t *from, array_t *relationArray, int turnDepth, int depth);
+static bdd_t * PreImageByConstraintCofactoring(ImgTfmInfo_t *info, array_t *delta, bdd_t *image, int splitMethod, int turnDepth, int depth);
+static mdd_t * PreImageBySubstitution(ImgTfmInfo_t *info, array_t *vector, mdd_t *from);
+static bdd_t * PreImageMakeVectorCanonical(ImgTfmInfo_t *info, array_t *vector, bdd_t *image, array_t *relationArray, array_t **newVector, array_t **newRelationArray, mdd_t **cofactorCube, mdd_t **abstractCube);
+static bdd_t * PreImageMakeRelationCanonical(ImgTfmInfo_t *info, array_t *vector, bdd_t *image, array_t *relationArray, array_t **newVector, array_t **newRelationArray);
+static bdd_t * PreImageDeleteOneComponent(ImgTfmInfo_t *info, array_t *delta, int index, array_t **newDelta);
+static int PreImageChooseSplitVar(ImgTfmInfo_t *info, array_t *delta, bdd_t *img, int splitMethod, int split);
+static mdd_t * DomainCofactoring(ImgTfmInfo_t *info, array_t *vector, mdd_t *from, array_t *relationArray, mdd_t *c, array_t **newVector, array_t **newRelationArray, mdd_t **cofactorCube, mdd_t **abstractCube);
+static int CheckPreImageVector(ImgTfmInfo_t *info, array_t *vector, mdd_t *image);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes a preimage with transition function method.]
+
+  Description [Computes a preimage with transition function method.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+ImgTfmPreImage(ImgTfmInfo_t *info, bdd_t *image)
+{
+  bdd_t		*preImg, *pre;
+  int		turnDepth;
+  bdd_t		*refResult, *one;
+  array_t	*relationArray;
+  int		partial;
+  bdd_t		*from;
+  array_t	*vector;
+
+  if (bdd_is_tautology(image, 1)) {
+    preImg = mdd_one(info->manager);
+    return(preImg);
+  } else if (bdd_is_tautology(image, 0)) {
+    preImg = mdd_zero(info->manager);
+    return(preImg);
+  }
+
+  info->maxIntermediateSize = 0;
+  if (info->buildTR) {
+    if (info->option->preSplitMethod == 4 &&
+	info->option->preSplitMaxDepth < 0 &&
+	info->option->buildPartialTR == FALSE &&
+	info->preKeepPiInTr == FALSE &&
+	info->option->preCanonical == FALSE) {
+      mdd_t *range;
+      range = ImgSubstitute(image, info->functionData, Img_D2R_c);
+      preImg = ImgBddLinearAndSmooth(info->manager, range,
+		      info->bwdClusteredRelationArray,
+		      info->bwdArraySmoothVarBddArray,
+		      info->bwdSmoothVarCubeArray,
+		      info->option->verbosity);
+      mdd_free(range);
+      return(preImg);
+    }
+    relationArray = mdd_array_duplicate(info->bwdClusteredRelationArray);
+  } else
+    relationArray = NIL(array_t);
+
+  one = mdd_one(info->manager);
+
+  vector = info->vector;
+  from = image;
+
+  partial = 0;
+  if (info->option->preSplitMethod == 0) {
+    preImg = PreImageByDomainCofactoring(info, vector, from,
+					 NIL(array_t), NIL(mdd_t), NIL(mdd_t),
+					 info->option->preSplitMethod, 0, 0);
+  } else if (info->option->preSplitMethod == 1) {
+    preImg = PreImageByConstraintCofactoring(info, vector, from,
+					     info->option->preSplitMethod,
+					     0, 0);
+  } else if (info->option->preSplitMethod == 3) {
+    preImg = PreImageBySubstitution(info, vector, from);
+  } else {
+    turnDepth = info->option->turnDepth;
+    if (turnDepth == 0) {
+      if (info->option->preSplitMethod == 2) {
+	preImg = PreImageByConstraintCofactoring(info, vector, from,
+						 info->option->preSplitMethod,
+						 turnDepth, 0);
+      } else
+	preImg = ImgPreImageByHybrid(info, vector, from);
+    } else if (info->option->preSplitMethod == 2) {
+      preImg = PreImageByDomainCofactoring(info, vector, from,
+					   relationArray,
+					   NIL(mdd_t), NIL(mdd_t),
+					   info->option->preSplitMethod,
+					   turnDepth, 0);
+    } else {
+      if (info->buildTR) {
+	if (info->buildTR == 2) {
+	  if (info->buildPartialTR) {
+	    preImg = PreImageByStaticDomainCofactoring(info, vector,
+							from, relationArray,
+							turnDepth, 0);
+	    partial = 1;
+	  } else {
+	    preImg = PreImageByStaticDomainCofactoring(info, NIL(array_t),
+							from, relationArray,
+							turnDepth, 0);
+	  }
+	} else if (info->option->delayedSplit) {
+	  preImg = PreImageByDomainCofactoring(info, vector, from,
+						relationArray, one, one,
+						info->option->preSplitMethod,
+						turnDepth, 0);
+	} else {
+	  preImg = PreImageByDomainCofactoring(info, vector, from,
+						relationArray,
+						NIL(mdd_t), NIL(mdd_t),
+						info->option->preSplitMethod,
+						turnDepth, 0);
+	}
+      } else {
+	preImg = PreImageByDomainCofactoring(info, vector, from,
+					     relationArray,
+					     NIL(mdd_t), NIL(mdd_t),
+					     info->option->preSplitMethod,
+					     turnDepth, 0);
+      }
+    }
+  }
+  mdd_free(one);
+
+  if (info->option->debug) {
+    if (info->buildTR == 2) {
+      refResult = ImgPreImageByHybridWithStaticSplit(info, NIL(array_t),
+							image, relationArray,
+							NIL(mdd_t), NIL(mdd_t));
+    } else {
+      if (partial) {
+	refResult = ImgPreImageByHybridWithStaticSplit(info, info->vector,
+							image, relationArray,
+							NIL(mdd_t), NIL(mdd_t));
+      } else
+	refResult = ImgPreImageByHybrid(info, info->vector, image);
+    }
+    assert(mdd_equal_mod_care_set_array(refResult, preImg,
+					info->toCareSetArray));
+    mdd_free(refResult);
+  }
+
+  if (relationArray)
+    mdd_array_free(relationArray);
+
+  if (info->preCache && info->option->autoFlushCache == 1)
+    ImgFlushCache(info->preCache);
+  if (info->preKeepPiInTr == TRUE) {
+    if (info->functionData->quantifyCube)
+      pre = bdd_smooth_with_cube(preImg, info->functionData->quantifyCube);
+    else
+      pre = bdd_smooth(preImg, info->functionData->quantifyBddVars);
+    mdd_free(preImg);
+  } else
+    pre = preImg;
+  if (info->option->verbosity) {
+    fprintf(vis_stdout,
+	    "** tfm info: max BDD size for intermediate product = %d\n",
+	    info->maxIntermediateSize);
+  }
+  return(pre);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes preimage with domain cofactoring method.]
+
+  Description [Computes preimage with domain cofactoring method.]
+
+  SideEffects []
+
+******************************************************************************/
+static bdd_t *
+PreImageByDomainCofactoring(ImgTfmInfo_t *info, array_t *delta, bdd_t *image,
+			    array_t *relationArray,
+			    mdd_t *cofactorCube, mdd_t *abstractCube,
+			    int splitMethod, int turnDepth, int depth)
+{
+  array_t	*newDelta, *tmpDelta, *vectorT, *vectorE;
+  bdd_t		*preImg, *preImgT, *preImgE, *imgT, *imgE, *newImg, *tmpImg;
+  int		split;
+  bdd_t		*var, *varNot, *refResult;
+  int		nRecur;
+  array_t	*relationArrayT, *relationArrayE;
+  array_t	*newRelationArray, *tmpRelationArray;
+  mdd_t		*cofactorCubeT, *cofactorCubeE;
+  mdd_t		*abstractCubeT, *abstractCubeE;
+  mdd_t		*newCofactorCube, *newAbstractCube;
+  mdd_t		*cofactor, *abstract;
+  mdd_t		*essentialCube, *tmp;
+  int		findEssential;
+  int		foundEssentialDepth, foundEssentialDepthT, foundEssentialDepthE;
+  int		turnFlag, size;
+  mdd_t		*saveCareSet = NIL(mdd_t);
+
+  newRelationArray = NIL(array_t);
+
+  if (info->option->checkEquivalence && relationArray) {
+    assert(ImgCheckEquivalence(info, delta, relationArray,
+				cofactorCube, abstractCube, 1));
+  }
+
+  info->nRecursionB++;
+  if (info->option->debug) {
+    if (relationArray) {
+      refResult = ImgPreImageByHybrid(info, delta, image);
+      preImg = ImgPreImageByHybridWithStaticSplit(info, NIL(array_t), image,
+						  relationArray,
+						  cofactorCube, abstractCube);
+      tmp = refResult;
+      refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
+      mdd_free(tmp);
+      tmp = preImg;
+      preImg = mdd_and(tmp, info->debugCareSet, 1, 1);
+      mdd_free(tmp);
+      assert(mdd_equal_mod_care_set_array(refResult, preImg,
+					  info->toCareSetArray));
+      mdd_free(refResult);
+      mdd_free(preImg);
+    }
+  }
+
+  if (info->nIntermediateVars)
+    size = ImgVectorFunctionSize(delta);
+  else
+    size = array_n(delta);
+  if (size == 1) {
+    preImg = PreImageBySubstitution(info, delta, image);
+    info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
+				(float)depth) / (float)(info->nLeavesB + 1);
+    if (depth > info->maxDepthB)
+      info->maxDepthB = depth;
+    info->nLeavesB++;
+    info->foundEssentialDepth = info->option->maxEssentialDepth;
+    return(preImg);
+  }
+
+  if (info->option->findEssential) {
+    if (info->option->findEssential == 1)
+      findEssential = 1;
+    else {
+      if (depth >= info->lastFoundEssentialDepth)
+	findEssential = 1;
+      else
+	findEssential = 0;
+    }
+  } else
+    findEssential = 0;
+  if (findEssential) {
+    essentialCube = bdd_find_essential_cube(image);
+
+    if (!bdd_is_tautology(essentialCube, 1)) {
+      info->averageFoundEssential = (info->averageFoundEssential *
+	(float)info->nFoundEssentials + (float)(bdd_size(essentialCube) - 1)) /
+	(float)(info->nFoundEssentials + 1);
+      info->averageFoundEssentialDepth = (info->averageFoundEssentialDepth *
+	(float)info->nFoundEssentials + (float)depth) /
+	(float)(info->nFoundEssentials + 1);
+      if (info->nFoundEssentials == 0 || depth < info->topFoundEssentialDepth)
+	info->topFoundEssentialDepth = depth;
+      if (info->option->printEssential && depth < IMG_TF_MAX_PRINT_DEPTH)
+	info->foundEssentials[depth]++;
+      info->nFoundEssentials++;
+      if (info->option->delayedSplit && relationArray) {
+	tmpRelationArray = relationArray;
+	tmpImg = ImgVectorMinimize(info, delta, essentialCube, image,
+			tmpRelationArray, &tmpDelta, NIL(mdd_t *),
+			NIL(array_t *), &cofactor, &abstract);
+	if (bdd_is_tautology(cofactor, 1))
+	  newCofactorCube = cofactorCube;
+	else
+	  newCofactorCube = mdd_and(cofactorCube, cofactor, 1, 1);
+	mdd_free(cofactor);
+	if (bdd_is_tautology(abstract, 1))
+	  newAbstractCube = abstractCube;
+	else
+	  newAbstractCube = mdd_and(abstractCube, abstract, 1, 1);
+	mdd_free(abstract);
+      } else {
+	if (relationArray)
+	  tmpRelationArray = mdd_array_duplicate(relationArray);
+	else
+	  tmpRelationArray = relationArray;
+	tmpImg = ImgVectorMinimize(info, delta, essentialCube, image,
+			tmpRelationArray, &tmpDelta, NIL(mdd_t *),
+			NIL(array_t *), NIL(mdd_t *), NIL(mdd_t *));
+	newCofactorCube = cofactorCube;
+	newAbstractCube = abstractCube;
+      }
+      foundEssentialDepth = depth;
+    } else {
+      tmpDelta = delta;
+      tmpRelationArray = relationArray;
+      tmpImg = image;
+      newCofactorCube = cofactorCube;
+      newAbstractCube = abstractCube;
+      foundEssentialDepth = info->option->maxEssentialDepth;
+    }
+    mdd_free(essentialCube);
+    foundEssentialDepthT = info->option->maxEssentialDepth;
+    foundEssentialDepthE = info->option->maxEssentialDepth;
+  } else {
+    tmpDelta = delta;
+    tmpRelationArray = relationArray;
+    tmpImg = image;
+    newCofactorCube = cofactorCube;
+    newAbstractCube = abstractCube;
+    /* To remove compiler warnings */
+    foundEssentialDepth = -1;
+    foundEssentialDepthT = -1;
+    foundEssentialDepthE = -1;
+  }
+
+  if (!info->option->preCanonical) {
+    newImg = tmpImg;
+    newDelta = tmpDelta;
+    newRelationArray = tmpRelationArray;
+  } else if (info->option->delayedSplit && relationArray) {
+    newImg = PreImageMakeVectorCanonical(info, tmpDelta, tmpImg,
+					tmpRelationArray, &newDelta,
+					&newRelationArray,
+					&cofactor, &abstract);
+    if (!bdd_is_tautology(cofactor, 1)) {
+      if (newCofactorCube == cofactorCube)
+	newCofactorCube = mdd_and(cofactorCube, cofactor, 1, 1);
+      else {
+	tmp = newCofactorCube;
+	newCofactorCube = mdd_and(tmp, cofactor, 1, 1);
+	mdd_free(tmp);
+      }
+    }
+    mdd_free(cofactor);
+    if (!bdd_is_tautology(abstract, 1)) {
+      if (newAbstractCube == abstractCube)
+	newAbstractCube = mdd_and(abstractCube, abstract, 1, 1);
+      else {
+	tmp = newAbstractCube;
+	newAbstractCube = mdd_and(tmp, abstract, 1, 1);
+	mdd_free(tmp);
+      }
+    }
+    mdd_free(abstract);
+  } else {
+    newImg = PreImageMakeVectorCanonical(info, tmpDelta, tmpImg,
+					tmpRelationArray, &newDelta,
+					&newRelationArray,
+					NIL(mdd_t *), NIL(mdd_t *));
+  }
+  if (tmpDelta != delta)
+    ImgVectorFree(tmpDelta);
+  if (tmpImg != image)
+    mdd_free(tmpImg);
+  if (tmpRelationArray && tmpRelationArray != relationArray &&
+      tmpRelationArray != newRelationArray) {
+    mdd_array_free(tmpRelationArray);
+  }
+
+  if (info->option->debug) {
+    if (relationArray) {
+      refResult = ImgPreImageByHybrid(info, newDelta, newImg);
+      preImg = ImgPreImageByHybridWithStaticSplit(info, NIL(array_t), newImg,
+						  newRelationArray,
+						  newCofactorCube,
+						  newAbstractCube);
+      tmp = refResult;
+      refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
+      mdd_free(tmp);
+      tmp = preImg;
+      preImg = mdd_and(tmp, info->debugCareSet, 1, 1);
+      mdd_free(tmp);
+      assert(mdd_equal_mod_care_set_array(refResult, preImg,
+					  info->toCareSetArray));
+      mdd_free(refResult);
+      mdd_free(preImg);
+    }
+  }
+
+  if (bdd_is_tautology(newImg, 1) || bdd_is_tautology(newImg, 0)) {
+    info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
+				(float)depth) / (float)(info->nLeavesB + 1);
+    if (depth > info->maxDepthB)
+      info->maxDepthB = depth;
+    info->nLeavesB++;
+    if (info->option->debug) {
+      refResult = ImgPreImageByHybrid(info, newDelta, newImg);
+      tmp = refResult;
+      refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
+      mdd_free(tmp);
+      tmp = mdd_and(newImg, info->debugCareSet, 1, 1);
+      assert(mdd_equal_mod_care_set_array(refResult, tmp,
+					  info->toCareSetArray));
+      mdd_free(refResult);
+      mdd_free(tmp);
+    }
+    if (newDelta != delta)
+      ImgVectorFree(newDelta);
+    if (relationArray && newRelationArray != relationArray)
+      mdd_array_free(newRelationArray);
+    if (newCofactorCube && newCofactorCube != cofactorCube)
+      mdd_free(newCofactorCube);
+    if (newAbstractCube && newAbstractCube != abstractCube)
+      mdd_free(newAbstractCube);
+    if (findEssential)
+      info->foundEssentialDepth = foundEssentialDepth;
+    return(newImg);
+  }
+  if (array_n(newDelta) <= 1) {
+    if (array_n(newDelta) == 0)
+      preImg = newImg;
+    else {
+      assert(array_n(newDelta) == 1);
+      preImg = PreImageBySubstitution(info, newDelta, newImg);
+      mdd_free(newImg);
+    }
+    info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
+				(float)depth) / (float)(info->nLeavesB + 1);
+    if (depth > info->maxDepthB)
+      info->maxDepthB = depth;
+    info->nLeavesB++;
+    if (info->option->debug) {
+      refResult = ImgPreImageByHybrid(info, delta, image);
+      tmp = refResult;
+      refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
+      mdd_free(tmp);
+      tmp = mdd_and(preImg, info->debugCareSet, 1, 1);
+      assert(mdd_equal_mod_care_set_array(refResult, tmp,
+					  info->toCareSetArray));
+      mdd_free(refResult);
+      mdd_free(tmp);
+    }
+    if (newDelta != delta)
+      ImgVectorFree(newDelta);
+    if (relationArray && newRelationArray != relationArray)
+      mdd_array_free(newRelationArray);
+    if (newCofactorCube && newCofactorCube != cofactorCube)
+      mdd_free(newCofactorCube);
+    if (newAbstractCube && newAbstractCube != abstractCube)
+      mdd_free(newAbstractCube);
+    if (findEssential)
+      info->foundEssentialDepth = foundEssentialDepth;
+    return(preImg);
+  }
+
+  if (info->preCache) {
+    preImg = ImgCacheLookupTable(info, info->preCache, newDelta, newImg);
+    if (preImg) {
+      info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
+				(float)depth) / (float)(info->nLeavesB + 1);
+      if (depth > info->maxDepthB)
+	info->maxDepthB = depth;
+      info->nLeavesB++;
+      if (info->option->debug) {
+	refResult = ImgPreImageByHybrid(info, newDelta, newImg);
+	tmp = refResult;
+	refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
+	mdd_free(tmp);
+	tmp = mdd_and(preImg, info->debugCareSet, 1, 1);
+	assert(mdd_equal_mod_care_set_array(refResult, tmp,
+					    info->toCareSetArray));
+	mdd_free(refResult);
+	mdd_free(tmp);
+      }
+      if (newDelta != delta)
+	ImgVectorFree(newDelta);
+      if (newImg != image)
+	mdd_free(newImg);
+      if (relationArray && newRelationArray != relationArray)
+	mdd_array_free(newRelationArray);
+      if (newCofactorCube && newCofactorCube != cofactorCube)
+	mdd_free(newCofactorCube);
+      if (newAbstractCube && newAbstractCube != abstractCube)
+	mdd_free(newAbstractCube);
+      if (findEssential)
+        info->foundEssentialDepth = foundEssentialDepth;
+      return(preImg);
+    }
+  }
+
+  turnFlag = 0;
+  if (splitMethod == 4 && turnDepth == -1) {
+    if (depth < info->option->preSplitMinDepth) {
+      info->nSplitsB++;
+      turnFlag = 0;
+    } else if (depth > info->option->preSplitMaxDepth) {
+      info->nConjoinsB++;
+      turnFlag = 1;
+    } else {
+      turnFlag = ImgDecideSplitOrConjoin(info, newDelta, newImg, 1,
+					 newRelationArray, newCofactorCube,
+					 newAbstractCube, 0, depth);
+    }
+  } else {
+    if (depth == turnDepth)
+      turnFlag = 1;
+    else
+      turnFlag = 0;
+  }
+  if (turnFlag) {
+    if (splitMethod == 2) {
+      preImg = PreImageByConstraintCofactoring(info, newDelta, newImg,
+						info->option->preSplitMethod,
+						0, depth + 1);
+    } else {
+      if (relationArray) {
+	preImg = ImgPreImageByHybridWithStaticSplit(info, NIL(array_t), newImg,
+						    newRelationArray,
+						    newCofactorCube,
+						    newAbstractCube);
+      } else
+	preImg = ImgPreImageByHybrid(info, newDelta, newImg);
+    }
+    if (info->option->debug) {
+      refResult = ImgPreImageByHybrid(info, newDelta, newImg);
+      tmp = refResult;
+      refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
+      mdd_free(tmp);
+      tmp = mdd_and(preImg, info->debugCareSet, 1, 1);
+      assert(mdd_equal_mod_care_set_array(refResult, tmp,
+					  info->toCareSetArray));
+      mdd_free(refResult);
+      mdd_free(tmp);
+    }
+    if (splitMethod == 4) {
+      if (info->preCache)
+	ImgCacheInsertTable(info->preCache, newDelta, newImg, mdd_dup(preImg));
+      else {
+	if (newDelta != delta)
+	  ImgVectorFree(newDelta);
+	if (newImg != image)
+	  mdd_free(newImg);
+      }
+      info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
+			      (float)depth) / (float)(info->nLeavesB + 1);
+      if (depth > info->maxDepthB)
+	info->maxDepthB = depth;
+      info->nLeavesB++;
+    } else {
+      if (newDelta != delta)
+	ImgVectorFree(newDelta);
+      if (newImg != image)
+	mdd_free(newImg);
+    }
+    if (relationArray && newRelationArray != relationArray)
+      mdd_array_free(newRelationArray);
+    if (newCofactorCube && newCofactorCube != cofactorCube)
+      mdd_free(newCofactorCube);
+    if (newAbstractCube && newAbstractCube != abstractCube)
+      mdd_free(newAbstractCube);
+    info->nTurnsB++;
+    if (findEssential)
+      info->foundEssentialDepth = foundEssentialDepth;
+    return(preImg);
+  }
+
+  split = PreImageChooseSplitVar(info, newDelta, newImg,
+				 0, info->option->preInputSplit);
+
+  /* No more present state variable to split */
+  if (split == -1) {
+    if (info->option->preDcLeafMethod == 0 ||
+	info->option->preDcLeafMethod == 2) {
+      if (info->option->preDcLeafMethod == 0)
+	preImg = PreImageBySubstitution(info, newDelta, newImg);
+      else if (relationArray) {
+	preImg = ImgPreImageByHybridWithStaticSplit(info, NIL(array_t), newImg,
+						    newRelationArray,
+						    newCofactorCube,
+						    newAbstractCube);
+      } else
+	preImg = ImgPreImageByHybrid(info, newDelta, newImg);
+      if (info->preCache)
+	ImgCacheInsertTable(info->preCache, newDelta, newImg, mdd_dup(preImg));
+      info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
+				(float)depth) / (float)(info->nLeavesB + 1);
+      if (depth > info->maxDepthB)
+	info->maxDepthB = depth;
+      info->nLeavesB++;
+    } else {
+      preImg = PreImageByConstraintCofactoring(info, newDelta, newImg,
+					    splitMethod, turnDepth,
+					    depth + 1);
+      info->nRecursionB--;
+    }
+    if (splitMethod == 0)
+      info->nTurnsB++;
+    if (info->option->debug) {
+      refResult = ImgPreImageByHybrid(info, newDelta, newImg);
+      tmp = refResult;
+      refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
+      mdd_free(tmp);
+      tmp = mdd_and(preImg, info->debugCareSet, 1, 1);
+      assert(mdd_equal_mod_care_set_array(refResult, tmp,
+					  info->toCareSetArray));
+      mdd_free(refResult);
+      mdd_free(tmp);
+    }
+    if (info->option->preDcLeafMethod != 0 || !info->preCache) {
+      if (newDelta != delta)
+	ImgVectorFree(newDelta);
+      if (newImg != image)
+	mdd_free(newImg);
+    }
+    if (relationArray && newRelationArray != relationArray)
+      mdd_array_free(newRelationArray);
+    if (newCofactorCube && newCofactorCube != cofactorCube)
+      mdd_free(newCofactorCube);
+    if (newAbstractCube && newAbstractCube != abstractCube)
+      mdd_free(newAbstractCube);
+    if (findEssential)
+      info->foundEssentialDepth = foundEssentialDepth;
+    return(preImg);
+  }
+
+  var = bdd_var_with_index(info->manager, split);
+  varNot = mdd_not(var);
+  if (info->option->delayedSplit && relationArray) {
+    imgT = DomainCofactoring(info, newDelta, newImg, newRelationArray, var,
+			     &vectorT, &relationArrayT, &cofactor, &abstract);
+    if (bdd_is_tautology(cofactor, 1))
+      cofactorCubeT = newCofactorCube;
+    else
+      cofactorCubeT = mdd_and(newCofactorCube, cofactor, 1, 1);
+    mdd_free(cofactor);
+    if (bdd_is_tautology(abstract, 1))
+      abstractCubeT = newAbstractCube;
+    else
+      abstractCubeT = mdd_and(newAbstractCube, abstract, 1, 1);
+    mdd_free(abstract);
+
+    imgE = DomainCofactoring(info, newDelta, newImg, newRelationArray, varNot,
+			     &vectorE, &relationArrayE, &cofactor, &abstract);
+    if (bdd_is_tautology(cofactor, 1))
+      cofactorCubeE = newCofactorCube;
+    else
+      cofactorCubeE = mdd_and(newCofactorCube, cofactor, 1, 1);
+    mdd_free(cofactor);
+    if (bdd_is_tautology(abstract, 1))
+      abstractCubeE = newAbstractCube;
+    else
+      abstractCubeE = mdd_and(newAbstractCube, abstract, 1, 1);
+    mdd_free(abstract);
+  } else {
+    imgT = DomainCofactoring(info, newDelta, newImg, newRelationArray, var,
+			     &vectorT, &relationArrayT,
+			     NIL(mdd_t *), NIL(mdd_t *));
+    cofactorCubeT = NIL(mdd_t);
+    abstractCubeT = NIL(mdd_t);
+
+    imgE = DomainCofactoring(info, newDelta, newImg, newRelationArray, varNot,
+			     &vectorE, &relationArrayE,
+			     NIL(mdd_t *), NIL(mdd_t *));
+    cofactorCubeE = NIL(mdd_t);
+    abstractCubeE = NIL(mdd_t);
+  }
+  if (relationArray && newRelationArray != relationArray)
+    mdd_array_free(newRelationArray);
+  mdd_free(varNot);
+
+  if (!info->preCache && !info->option->debug) {
+    if (newDelta != delta)
+      ImgVectorFree(newDelta);
+    if (newImg != image)
+      mdd_free(newImg);
+  }
+
+  nRecur = 0;
+  if (bdd_is_tautology(imgT, 1))
+    preImgT = mdd_one(info->manager);
+  else if (bdd_is_tautology(imgT, 0))
+    preImgT = mdd_zero(info->manager);
+  else {
+    if (info->option->debug) {
+      saveCareSet = info->debugCareSet;
+      info->debugCareSet = mdd_and(saveCareSet, var, 1, 1);
+    }
+    preImgT = PreImageByDomainCofactoring(info, vectorT, imgT, relationArrayT,
+					  cofactorCubeT, abstractCubeT,
+					  splitMethod, turnDepth,
+					  depth + 1);
+    if (info->option->debug) {
+      mdd_free(info->debugCareSet);
+      info->debugCareSet = saveCareSet;
+    }
+    if (findEssential)
+      foundEssentialDepthT = info->foundEssentialDepth;
+    nRecur++;
+  }
+  ImgVectorFree(vectorT);
+  mdd_free(imgT);
+  if (relationArrayT && relationArrayT != newRelationArray)
+    mdd_array_free(relationArrayT);
+  if (cofactorCubeT && cofactorCubeT != newCofactorCube)
+    mdd_free(cofactorCubeT);
+  if (abstractCubeT && abstractCubeT != newAbstractCube)
+    mdd_free(abstractCubeT);
+
+  if (bdd_is_tautology(imgE, 1))
+    preImgE = mdd_one(info->manager);
+  else if (bdd_is_tautology(imgE, 0))
+    preImgE = mdd_zero(info->manager);
+  else {
+    if (info->option->debug) {
+      saveCareSet = info->debugCareSet;
+      info->debugCareSet = mdd_and(saveCareSet, var, 1, 0);
+    }
+    preImgE = PreImageByDomainCofactoring(info, vectorE, imgE, relationArrayE,
+					  cofactorCubeE, abstractCubeE,
+					  splitMethod, turnDepth,
+					  depth + 1);
+    if (info->option->debug) {
+      mdd_free(info->debugCareSet);
+      info->debugCareSet = saveCareSet;
+    }
+    if (findEssential)
+      foundEssentialDepthE = info->foundEssentialDepth;
+    nRecur++;
+  }
+  ImgVectorFree(vectorE);
+  mdd_free(imgE);
+  if (relationArrayE && relationArrayT != newRelationArray)
+    mdd_array_free(relationArrayE);
+  if (cofactorCubeE && cofactorCubeE != newCofactorCube)
+    mdd_free(cofactorCubeE);
+  if (abstractCubeE && abstractCubeE != newAbstractCube)
+    mdd_free(abstractCubeE);
+  if (newCofactorCube && newCofactorCube != cofactorCube)
+    mdd_free(newCofactorCube);
+  if (newAbstractCube && newAbstractCube != abstractCube)
+    mdd_free(newAbstractCube);
+
+  preImg = bdd_ite(var, preImgT, preImgE, 1, 1, 1);
+  if (info->option->verbosity) {
+    size = bdd_size(preImg);
+    if (size > info->maxIntermediateSize)
+      info->maxIntermediateSize = size;
+    if (info->option->printBddSize) {
+      fprintf(vis_stdout, "** tfm info: bdd_ite(2,%d,%d) = %d\n",
+	      bdd_size(preImgT), bdd_size(preImgE), bdd_size(preImg));
+    }
+  }
+  mdd_free(var);
+  mdd_free(preImgE);
+  mdd_free(preImgT);
+
+  if (info->preCache)
+    ImgCacheInsertTable(info->preCache, newDelta, newImg, mdd_dup(preImg));
+
+  if (info->option->debug) {
+    refResult = ImgPreImageByHybrid(info, newDelta, newImg);
+    tmp = refResult;
+    refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
+    mdd_free(tmp);
+    tmp = mdd_and(preImg, info->debugCareSet, 1, 1);
+    assert(mdd_equal_mod_care_set_array(refResult, tmp,
+					info->toCareSetArray));
+    mdd_free(refResult);
+    mdd_free(tmp);
+    if (!info->preCache) {
+      if (newDelta != delta)
+	ImgVectorFree(newDelta);
+      if (newImg != image)
+	mdd_free(newImg);
+    }
+  }
+
+  if (nRecur == 0) {
+    info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
+				(float)depth) / (float)(info->nLeavesB + 1);
+    if (depth > info->maxDepthB)
+      info->maxDepthB = depth;
+    info->nLeavesB++;
+  }
+
+  if (findEssential) {
+    if (foundEssentialDepth == info->option->maxEssentialDepth) {
+      if (foundEssentialDepthT < foundEssentialDepthE)
+	foundEssentialDepth = foundEssentialDepthT;
+      else
+	foundEssentialDepth = foundEssentialDepthE;
+    }
+    info->foundEssentialDepth = foundEssentialDepth;
+  }
+  return(preImg);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes a preimage by static input splitting.]
+
+  Description [Computes a preimage by static input splitting.]
+
+  SideEffects []
+
+******************************************************************************/
+static mdd_t *
+PreImageByStaticDomainCofactoring(ImgTfmInfo_t *info, array_t *vector,
+				  mdd_t *from, array_t *relationArray,
+				  int turnDepth, int depth)
+{
+  array_t	*vectorT, *vectorE, *newVector;
+  mdd_t		*resT, *resE, *res, *cubeT, *cubeE;
+  mdd_t		*fromT, *fromE, *newFrom, *tmpFrom;
+  mdd_t		*var, *varNot;
+  array_t	*relationArrayT, *relationArrayE;
+  array_t	*newRelationArray, *tmpRelationArray;
+  int		nRecur;
+  mdd_t		*essentialCube, *refResult;
+  int		findEssential;
+  int		foundEssentialDepth, foundEssentialDepthT, foundEssentialDepthE;
+  int		turnFlag, size;
+  mdd_t		*saveCareSet = NIL(mdd_t), *tmp;
+
+  info->nRecursionB++;
+
+  turnFlag = 0;
+  if (turnDepth == -1) {
+    if (depth < info->option->preSplitMinDepth) {
+      info->nSplitsB++;
+      turnFlag = 0;
+    } else if (depth > info->option->preSplitMaxDepth) {
+      info->nConjoinsB++;
+      turnFlag = 1;
+    } else {
+      turnFlag = ImgDecideSplitOrConjoin(info, vector, from, 1,
+					 relationArray, NIL(mdd_t),
+					 NIL(mdd_t), 1, depth);
+    }
+  } else {
+    if (depth == turnDepth)
+      turnFlag = 1;
+    else
+      turnFlag = 0;
+  }
+  if (turnFlag) {
+    res = ImgPreImageByHybridWithStaticSplit(info, vector, from, relationArray,
+					     NIL(mdd_t), NIL(mdd_t));
+    info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
+			  (float)depth) / (float)(info->nLeavesB + 1);
+    if (depth > info->maxDepthB)
+      info->maxDepthB = depth;
+    info->nLeavesB++;
+    info->foundEssentialDepth = info->option->maxEssentialDepth;
+    return(res);
+  }
+
+  if (info->option->findEssential) {
+    if (info->option->findEssential == 1)
+      findEssential = 1;
+    else {
+      if (depth >= info->lastFoundEssentialDepth)
+	findEssential = 1;
+      else
+	findEssential = 0;
+    }
+  } else
+    findEssential = 0;
+  if (findEssential) {
+    essentialCube = bdd_find_essential_cube(from);
+
+    if (!bdd_is_tautology(essentialCube, 1)) {
+      info->averageFoundEssential = (info->averageFoundEssential *
+	(float)info->nFoundEssentials + (float)(bdd_size(essentialCube) - 1)) /
+	(float)(info->nFoundEssentials + 1);
+      info->averageFoundEssentialDepth = (info->averageFoundEssentialDepth *
+	(float)info->nFoundEssentials + (float)depth) /
+	(float)(info->nFoundEssentials + 1);
+      if (info->nFoundEssentials == 0 || depth < info->topFoundEssentialDepth)
+	info->topFoundEssentialDepth = depth;
+      if (info->option->printEssential && depth < IMG_TF_MAX_PRINT_DEPTH)
+	info->foundEssentials[depth]++;
+      info->nFoundEssentials++;
+      if (vector) {
+	array_t *tmpVector;
+	if (info->option->preCanonical) {
+	  tmpFrom = PreImageMakeRelationCanonical(info, vector, from,
+						relationArray, &newVector,
+						&newRelationArray);
+	} else {
+	  tmpFrom = from;
+	  newVector = vector;
+	  newRelationArray = relationArray;
+	}
+	tmpVector = newVector;
+	newFrom = ImgVectorMinimize(info, tmpVector, essentialCube, tmpFrom,
+			newRelationArray, &newVector, NIL(mdd_t *),
+			NIL(array_t *), NIL(mdd_t *), NIL(mdd_t *));
+	if (tmpVector != vector)
+	  ImgVectorFree(tmpVector);
+	if (tmpFrom != from)
+	  mdd_free(tmpFrom);
+      } else {
+	tmpRelationArray = ImgGetCofactoredRelationArray(relationArray,
+							 essentialCube);
+	if (info->option->preCanonical) {
+	  newFrom = PreImageMakeRelationCanonical(info, vector, from,
+						tmpRelationArray, &newVector,
+						&newRelationArray);
+	  mdd_array_free(tmpRelationArray);
+	} else {
+	  newFrom = from;
+	  newVector = vector;
+	  newRelationArray = tmpRelationArray;
+	}
+      }
+      foundEssentialDepth = depth;
+    } else {
+      if (info->option->preCanonical) {
+	newFrom = PreImageMakeRelationCanonical(info, vector, from,
+						relationArray,
+						&newVector, &newRelationArray);
+      } else {
+	newFrom = from;
+	newVector = vector;
+	newRelationArray = relationArray;
+      }
+      foundEssentialDepth = info->option->maxEssentialDepth;
+    }
+    mdd_free(essentialCube);
+    foundEssentialDepthT = info->option->maxEssentialDepth;
+    foundEssentialDepthE = info->option->maxEssentialDepth;
+  } else {
+    if (info->option->preCanonical) {
+      newFrom = PreImageMakeRelationCanonical(info, vector, from, relationArray,
+					    &newVector, &newRelationArray);
+    } else {
+      newFrom = from;
+      newVector = vector;
+      newRelationArray = relationArray;
+    }
+    /* To remove compiler warnings */
+    foundEssentialDepth = -1;
+    foundEssentialDepthT = -1;
+    foundEssentialDepthE = -1;
+  }
+
+  if (info->option->debug) {
+    refResult = ImgPreImageByHybridWithStaticSplit(info, vector, from,
+						   relationArray,
+						   NIL(mdd_t), NIL(mdd_t));
+    res = ImgPreImageByHybridWithStaticSplit(info, newVector, newFrom,
+						   newRelationArray,
+						   NIL(mdd_t), NIL(mdd_t));
+    tmp = refResult;
+    refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
+    mdd_free(tmp);
+    tmp = res;
+    res = mdd_and(tmp, info->debugCareSet, 1, 1);
+    mdd_free(tmp);
+    assert(mdd_equal_mod_care_set_array(refResult, res, info->toCareSetArray));
+    mdd_free(refResult);
+    mdd_free(res);
+  }
+
+  if (bdd_is_tautology(newFrom, 1)) {
+    if (newVector && newVector != vector)
+      ImgVectorFree(newVector);
+    if (newRelationArray != relationArray)
+      mdd_array_free(newRelationArray);
+    if (newFrom != from)
+      mdd_free(newFrom);
+    info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
+			  (float)depth) / (float)(info->nLeavesB + 1);
+    if (depth > info->maxDepthB)
+      info->maxDepthB = depth;
+    info->nLeavesB++;
+    if (findEssential)
+      info->foundEssentialDepth = foundEssentialDepth;
+    return(mdd_one(info->manager));
+  }
+
+  if (depth == turnDepth ||
+      (info->option->splitCubeFunc && bdd_is_cube(newFrom))) {
+    res = ImgPreImageByHybridWithStaticSplit(info, newVector, newFrom,
+					     newRelationArray,
+					     NIL(mdd_t), NIL(mdd_t));
+    if (newVector && newVector != vector)
+      ImgVectorFree(newVector);
+    if (newRelationArray != relationArray)
+      mdd_array_free(newRelationArray);
+    if (newFrom != from)
+      mdd_free(newFrom);
+    info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
+			  (float)depth) / (float)(info->nLeavesB + 1);
+    if (depth > info->maxDepthB)
+      info->maxDepthB = depth;
+    info->nLeavesB++;
+    if (findEssential)
+      info->foundEssentialDepth = foundEssentialDepth;
+    return(res);
+  }
+
+  var = ImgChooseTrSplitVar(info, newVector, newRelationArray,
+			    info->option->trSplitMethod, 0);
+  if (!var) {
+    res = ImgPreImageByHybridWithStaticSplit(info, newVector, newFrom,
+						   newRelationArray,
+						   NIL(mdd_t), NIL(mdd_t));
+    if (newVector && newVector != vector)
+      ImgVectorFree(newVector);
+    if (newRelationArray != relationArray)
+      mdd_array_free(newRelationArray);
+    if (newFrom != from)
+      mdd_free(newFrom);
+    info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
+			  (float)depth) / (float)(info->nLeavesB + 1);
+    if (depth > info->maxDepthB)
+      info->maxDepthB = depth;
+    info->nLeavesB++;
+    if (findEssential)
+      info->foundEssentialDepth = foundEssentialDepth;
+    return(res);
+  }
+
+  varNot = mdd_not(var);
+
+  nRecur = 0;
+  if (newVector) {
+    ImgVectorConstrain(info, newVector, var, NIL(array_t),
+			&vectorT, &cubeT, NIL(array_t *),
+			NIL(mdd_t *), NIL(mdd_t *), TRUE);
+    fromT = bdd_cofactor(newFrom, cubeT);
+    mdd_free(cubeT);
+  } else {
+    vectorT = NIL(array_t);
+    fromT = mdd_dup(newFrom);
+  }
+  relationArrayT = ImgGetCofactoredRelationArray(newRelationArray, var);
+  if (bdd_is_tautology(fromT, 1)) {
+    resT = mdd_one(info->manager);
+    if (vectorT)
+      ImgVectorFree(vectorT);
+  } else if (bdd_is_tautology(fromT, 0)) {
+    resT = mdd_zero(info->manager);
+    if (vectorT)
+      ImgVectorFree(vectorT);
+  } else {
+    if (info->option->debug) {
+      saveCareSet = info->debugCareSet;
+      info->debugCareSet = mdd_and(saveCareSet, var, 1, 1);
+    }
+    resT = PreImageByStaticDomainCofactoring(info, vectorT, fromT,
+			     relationArrayT, turnDepth, depth + 1);
+    if (info->option->debug) {
+      mdd_free(info->debugCareSet);
+      info->debugCareSet = saveCareSet;
+    }
+    if (findEssential)
+      foundEssentialDepthE = info->foundEssentialDepth;
+    if (vectorT)
+      ImgVectorFree(vectorT);
+    nRecur++;
+  }
+  mdd_free(fromT);
+  mdd_array_free(relationArrayT);
+
+  if (newVector) {
+    ImgVectorConstrain(info, newVector, varNot, NIL(array_t),
+			&vectorE, &cubeE, NIL(array_t *),
+			NIL(mdd_t *), NIL(mdd_t *), TRUE);
+    if (newVector != vector)
+      ImgVectorFree(newVector);
+    fromE = bdd_cofactor(newFrom, cubeE);
+    mdd_free(cubeE);
+  } else {
+    vectorE = NIL(array_t);
+    fromE = mdd_dup(newFrom);
+  }
+  if (newFrom != from)
+    mdd_free(newFrom);
+  relationArrayE = ImgGetCofactoredRelationArray(newRelationArray, varNot);
+  if (newRelationArray != relationArray)
+    mdd_array_free(newRelationArray);
+  if (bdd_is_tautology(fromE, 1)) {
+    resE = mdd_one(info->manager);
+    if (vectorE)
+      ImgVectorFree(vectorE);
+  } else if (bdd_is_tautology(fromE, 0)) {
+    resE = mdd_zero(info->manager);
+    if (vectorE)
+      ImgVectorFree(vectorE);
+  } else {
+    if (info->option->debug) {
+      saveCareSet = info->debugCareSet;
+      info->debugCareSet = mdd_and(saveCareSet, var, 1, 0);
+    }
+    resE = PreImageByStaticDomainCofactoring(info, vectorE, fromE,
+			     relationArrayE, turnDepth, depth + 1);
+    if (info->option->debug) {
+      mdd_free(info->debugCareSet);
+      info->debugCareSet = saveCareSet;
+    }
+    if (findEssential)
+      foundEssentialDepthE = info->foundEssentialDepth;
+    if (vectorE)
+      ImgVectorFree(vectorE);
+    nRecur++;
+  }
+  mdd_free(fromE);
+  mdd_array_free(relationArrayE);
+  
+  res = bdd_ite(var, resT, resE, 1, 1, 1);
+  if (info->option->verbosity) {
+    size = bdd_size(res);
+    if (size > info->maxIntermediateSize)
+      info->maxIntermediateSize = size;
+    if (info->option->printBddSize) {
+      fprintf(vis_stdout, "** tfm info: bdd_ite(2,%d,%d) = %d\n",
+	      bdd_size(resT), bdd_size(resE), bdd_size(res));
+    }
+  }
+  mdd_free(resT);
+  mdd_free(resE);
+  mdd_free(var);
+  mdd_free(varNot);
+
+  if (info->option->debug) {
+    refResult = ImgPreImageByHybridWithStaticSplit(info, vector, from,
+						   relationArray,
+						   NIL(mdd_t), NIL(mdd_t));
+    tmp = refResult;
+    refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
+    mdd_free(tmp);
+    tmp = mdd_and(res, info->debugCareSet, 1, 1);
+    assert(mdd_equal_mod_care_set_array(refResult, tmp, info->toCareSetArray));
+    mdd_free(refResult);
+    mdd_free(tmp);
+  }
+
+  if (nRecur == 0) {
+    info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
+			  (float)depth) / (float)(info->nLeavesB + 1);
+    if (depth > info->maxDepthB)
+      info->maxDepthB = depth;
+    info->nLeavesB++;
+  }
+
+  if (findEssential) {
+    if (foundEssentialDepth == info->option->maxEssentialDepth) {
+      if (foundEssentialDepthT < foundEssentialDepthE)
+	foundEssentialDepth = foundEssentialDepthT;
+      else
+	foundEssentialDepth = foundEssentialDepthE;
+    }
+    info->foundEssentialDepth = foundEssentialDepth;
+  }
+  return(res);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes preimage with constraint cofactoring method.]
+
+  Description [Computes preimage with constraint cofactoring method.]
+
+  SideEffects []
+
+******************************************************************************/
+static bdd_t *
+PreImageByConstraintCofactoring(ImgTfmInfo_t *info, array_t *delta,
+				bdd_t *image, int splitMethod,
+				int turnDepth, int depth)
+{
+  array_t		*newDelta, *tmpDelta, *vector;
+  bdd_t			*preImg, *preImgT, *preImgE, *imgT, *imgE;
+  bdd_t			*c, *newImg, *tmpImg;
+  int			split;
+  bdd_t			*var, *varNot, *refResult;
+  ImgComponent_t	*comp;
+  int			nRecur, size;
+  mdd_t			*essentialCube;
+  int			findEssential;
+  int			foundEssentialDepth;
+  int			foundEssentialDepthT, foundEssentialDepthE;
+  mdd_t			*saveCareSet = NIL(mdd_t), *tmp;
+
+  info->nRecursionB++;
+
+  if (info->nIntermediateVars)
+    size = ImgVectorFunctionSize(delta);
+  else
+    size = array_n(delta);
+  if (size == 1) {
+    preImg = PreImageBySubstitution(info, delta, image);
+    info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
+				(float)depth) / (float)(info->nLeavesB + 1);
+    if (depth > info->maxDepthB)
+      info->maxDepthB = depth;
+    info->nLeavesB++;
+    info->foundEssentialDepth = info->option->maxEssentialDepth;
+    return(preImg);
+  }
+
+  if (info->option->findEssential) {
+    if (info->option->findEssential == 1)
+      findEssential = 1;
+    else {
+      if (depth >= info->lastFoundEssentialDepth)
+	findEssential = 1;
+      else
+	findEssential = 0;
+    }
+  } else
+    findEssential = 0;
+  if (findEssential) {
+    essentialCube = bdd_find_essential_cube(image);
+
+    if (!bdd_is_tautology(essentialCube, 1)) {
+      info->averageFoundEssential = (info->averageFoundEssential *
+	(float)info->nFoundEssentials + (float)(bdd_size(essentialCube) - 1)) /
+	(float)(info->nFoundEssentials + 1);
+      info->averageFoundEssentialDepth = (info->averageFoundEssentialDepth *
+	(float)info->nFoundEssentials + (float)depth) /
+	(float)(info->nFoundEssentials + 1);
+      if (info->nFoundEssentials == 0 || depth < info->topFoundEssentialDepth)
+	info->topFoundEssentialDepth = depth;
+      if (info->option->printEssential && depth < IMG_TF_MAX_PRINT_DEPTH)
+	info->foundEssentials[depth]++;
+      info->nFoundEssentials++;
+      tmpImg = ImgVectorMinimize(info, delta, essentialCube, image,
+			NIL(array_t), &tmpDelta, NIL(mdd_t *),
+			NIL(array_t *), NIL(mdd_t *), NIL(mdd_t *));
+      foundEssentialDepth = depth;
+    } else {
+      tmpDelta = delta;
+      tmpImg = image;
+      foundEssentialDepth = info->option->maxEssentialDepth;
+    }
+    mdd_free(essentialCube);
+    foundEssentialDepthT = info->option->maxEssentialDepth;
+    foundEssentialDepthE = info->option->maxEssentialDepth;
+  } else {
+    tmpDelta = delta;
+    tmpImg = image;
+    /* To remove compiler warnings */
+    foundEssentialDepth = -1;
+    foundEssentialDepthT = -1;
+    foundEssentialDepthE = -1;
+  }
+
+  if (info->option->preCanonical) {
+    newImg = PreImageMakeVectorCanonical(info, tmpDelta, tmpImg, NIL(array_t),
+				&newDelta, NIL(array_t *), NIL(mdd_t *),
+				NIL(mdd_t *));
+  } else {
+    newImg = tmpImg;
+    newDelta = tmpDelta;
+  }
+  if (tmpDelta != delta)
+    ImgVectorFree(tmpDelta);
+  if (tmpImg != image)
+    mdd_free(tmpImg);
+
+  if (bdd_is_tautology(newImg, 1) || bdd_is_tautology(newImg, 0)) {
+    info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
+				(float)depth) / (float)(info->nLeavesB + 1);
+    if (depth > info->maxDepthB)
+      info->maxDepthB = depth;
+    info->nLeavesB++;
+    if (info->option->debug) {
+      refResult = ImgPreImageByHybrid(info, newDelta, newImg);
+      tmp = refResult;
+      refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
+      mdd_free(tmp);
+      tmp = mdd_and(newImg, info->debugCareSet, 1, 1);
+      assert(mdd_equal_mod_care_set_array(refResult, tmp,
+					  info->toCareSetArray));
+      mdd_free(refResult);
+      mdd_free(tmp);
+    }
+    ImgVectorFree(newDelta);
+    if (findEssential)
+      info->foundEssentialDepth = foundEssentialDepth;
+    return(newImg);
+  }
+
+  if (info->preCache) {
+    preImg = ImgCacheLookupTable(info, info->preCache, newDelta, newImg);
+    if (preImg) {
+      info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
+				(float)depth) / (float)(info->nLeavesB + 1);
+      if (depth > info->maxDepthB)
+	info->maxDepthB = depth;
+      info->nLeavesB++;
+      if (info->option->debug) {
+	refResult = ImgPreImageByHybrid(info, newDelta, newImg);
+	tmp = refResult;
+	refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
+	mdd_free(tmp);
+	tmp = mdd_and(preImg, info->debugCareSet, 1, 1);
+	assert(mdd_equal_mod_care_set_array(refResult, tmp,
+					    info->toCareSetArray));
+	mdd_free(refResult);
+	mdd_free(tmp);
+      }
+      ImgVectorFree(newDelta);
+      mdd_free(newImg);
+      if (findEssential)
+	info->foundEssentialDepth = foundEssentialDepth;
+      return(preImg);
+    }
+  }
+
+  if (depth == turnDepth) {
+    preImg = ImgPreImageByHybrid(info, newDelta, newImg);
+    if (info->option->debug) {
+      refResult = ImgPreImageByHybrid(info, newDelta, newImg);
+      tmp = refResult;
+      refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
+      mdd_free(tmp);
+      tmp = mdd_and(preImg, info->debugCareSet, 1, 1);
+      assert(mdd_equal_mod_care_set_array(refResult, tmp,
+					  info->toCareSetArray));
+      mdd_free(refResult);
+      mdd_free(tmp);
+    }
+    if (info->preCache)
+      ImgCacheInsertTable(info->preCache, newDelta, newImg, mdd_dup(preImg));
+    else {
+      ImgVectorFree(newDelta);
+      mdd_free(newImg);
+    }
+    info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
+				(float)depth) / (float)(info->nLeavesB + 1);
+    if (depth > info->maxDepthB)
+      info->maxDepthB = depth;
+    info->nLeavesB++;
+    info->nTurnsB++;
+    if (findEssential)
+      info->foundEssentialDepth = foundEssentialDepth;
+    return(preImg);
+  }
+
+  split = PreImageChooseSplitVar(info, newDelta, newImg,
+				 1, info->option->preOutputSplit);
+  comp = array_fetch(ImgComponent_t *, newDelta, split);
+  var = mdd_dup(comp->var);
+  varNot = mdd_not(var);
+  imgE = bdd_cofactor(newImg, varNot);
+  mdd_free(varNot);
+  imgT = bdd_cofactor(newImg, var);
+  mdd_free(var);
+  if (!info->preCache && !info->option->debug)
+    mdd_free(newImg);
+  c = PreImageDeleteOneComponent(info, newDelta, split, &vector);
+  if (!info->preCache && !info->option->debug)
+    ImgVectorFree(newDelta);
+
+  nRecur = 0;
+  if (bdd_is_tautology(imgT, 1))
+    preImgT = mdd_one(info->manager);
+  else if (bdd_is_tautology(imgT, 0))
+    preImgT = mdd_zero(info->manager);
+  else {
+    if (info->option->debug) {
+      saveCareSet = info->debugCareSet;
+      info->debugCareSet = mdd_and(saveCareSet, c, 1, 1);
+    }
+    preImgT = PreImageByConstraintCofactoring(info, vector, imgT, splitMethod,
+						turnDepth, depth + 1);
+    if (info->option->debug) {
+      mdd_free(info->debugCareSet);
+      info->debugCareSet = saveCareSet;
+    }
+    if (findEssential)
+      foundEssentialDepthT = info->foundEssentialDepth;
+    nRecur++;
+  }
+  mdd_free(imgT);
+  if (bdd_is_tautology(imgE, 1))
+    preImgE = mdd_one(info->manager);
+  else if (bdd_is_tautology(imgE, 0))
+    preImgE = mdd_zero(info->manager);
+  else {
+    if (info->option->debug) {
+      saveCareSet = info->debugCareSet;
+      info->debugCareSet = mdd_and(saveCareSet, c, 1, 0);
+    }
+    preImgE = PreImageByConstraintCofactoring(info, vector, imgE, splitMethod,
+						turnDepth, depth + 1);
+    if (info->option->debug) {
+      mdd_free(info->debugCareSet);
+      info->debugCareSet = saveCareSet;
+    }
+    if (findEssential)
+      foundEssentialDepthE = info->foundEssentialDepth;
+    nRecur++;
+  }
+  mdd_free(imgE);
+  ImgVectorFree(vector);
+  preImg = bdd_ite(c, preImgT, preImgE, 1, 1, 1);
+  if (info->option->verbosity) {
+    size = bdd_size(preImg);
+    if (size > info->maxIntermediateSize)
+      info->maxIntermediateSize = size;
+    if (info->option->printBddSize) {
+      fprintf(vis_stdout, "** tfm info: bdd_ite(%d,%d,%d) = %d\n",
+	      bdd_size(c), bdd_size(preImgT), bdd_size(preImgE),
+	      bdd_size(preImg));
+    }
+  }
+  mdd_free(c);
+  mdd_free(preImgT);
+  mdd_free(preImgE);
+
+  if (info->preCache)
+    ImgCacheInsertTable(info->preCache, newDelta, newImg, mdd_dup(preImg));
+
+  if (info->option->debug) {
+    refResult = ImgPreImageByHybrid(info, newDelta, newImg);
+    tmp = refResult;
+    refResult = mdd_and(tmp, info->debugCareSet, 1, 1);
+    mdd_free(tmp);
+    tmp = mdd_and(preImg, info->debugCareSet, 1, 1);
+    assert(mdd_equal_mod_care_set_array(refResult, tmp,
+					info->toCareSetArray));
+    mdd_free(refResult);
+    mdd_free(tmp);
+    if (!info->preCache) {
+      ImgVectorFree(newDelta);
+      mdd_free(newImg);
+    }
+  }
+
+  if (nRecur == 0) {
+    info->averageDepthB = (info->averageDepthB * (float)info->nLeavesB +
+				(float)depth) / (float)(info->nLeavesB + 1);
+    if (depth > info->maxDepthB)
+      info->maxDepthB = depth;
+    info->nLeavesB++;
+  }
+
+  if (findEssential) {
+    if (foundEssentialDepth == info->option->maxEssentialDepth) {
+      if (foundEssentialDepthT < foundEssentialDepthE)
+	foundEssentialDepth = foundEssentialDepthT;
+      else
+	foundEssentialDepth = foundEssentialDepthE;
+    }
+    info->foundEssentialDepth = foundEssentialDepth;
+  }
+  return(preImg);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes a preimage by Filkorn's substitution.]
+
+  Description [Computes a preimage by Filkorn's substitution.]
+
+  SideEffects []
+
+******************************************************************************/
+static mdd_t *
+PreImageBySubstitution(ImgTfmInfo_t *info, array_t *vector, mdd_t *from)
+{
+  int			i, index;
+  ImgComponent_t	*comp, *fromComp;
+  array_t		*varArray, *funcArray;
+  mdd_t			*result;
+
+  if (bdd_is_tautology(from, 1))
+    return(mdd_one(info->manager));
+  else if (bdd_is_tautology(from, 0))
+    return(mdd_zero(info->manager));
+
+  fromComp = ImgComponentAlloc(info);
+  fromComp->func = from;
+  ImgComponentGetSupport(fromComp);
+
+  varArray = array_alloc(mdd_t *, 0);
+  funcArray = array_alloc(mdd_t *, 0);
+
+  for (i = 0; i < array_n(vector); i++) {
+    comp = array_fetch(ImgComponent_t *, vector, i);
+    index = bdd_top_var_id(comp->var);
+    if (fromComp->support[index] || comp->intermediate) {
+      array_insert_last(mdd_t *, varArray, comp->var);
+      array_insert_last(mdd_t *, funcArray, comp->func);
+    }
+  }
+
+  fromComp->func = NIL(mdd_t);
+  ImgComponentFree(fromComp);
+
+  result = bdd_vector_compose(from, varArray, funcArray);
+  array_free(varArray);
+  array_free(funcArray);
+
+  /* quantify all primary inputs */
+  if (info->preKeepPiInTr == FALSE) {
+    array_t *quantifyVarBddArray;
+    mdd_t *tmp;
+
+    if (info->newQuantifyBddVars)
+      quantifyVarBddArray = info->newQuantifyBddVars;
+    else
+      quantifyVarBddArray = info->quantifyVarBddArray;
+
+    tmp = result;
+    result = bdd_smooth(tmp, quantifyVarBddArray);
+    mdd_free(tmp);
+  }
+
+  return(result);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makes a vector canonical for preimage.]
+
+  Description [Makes a vector canonical for preimage.
+  Delete all the components which doesn't appear as a support
+  in the image. If a component is constant, simplify the image with the
+  constant value and delete the corresponding component from delta
+  Side effect on delta.  Return new image.]
+
+  SideEffects []
+
+******************************************************************************/
+static bdd_t *
+PreImageMakeVectorCanonical(ImgTfmInfo_t *info, array_t *vector, bdd_t *image,
+			    array_t *relationArray, array_t **newVector,
+			    array_t **newRelationArray,
+			    mdd_t **cofactorCube, mdd_t **abstractCube)
+{
+  array_t		*tmpVector, *cofactoredVector;
+  bdd_t			*simple, *tmp, *newImage;
+  ImgComponent_t	*comp, *comp1, *imgComp;
+  int			i, id, n, pos;
+  st_table		*equivTable;
+  int			*ptr, *regularPtr;
+  mdd_t			*var, *cofactor, *abstract, *nsVar;
+  array_t		*tmpRelationArray;
+  int			changed = 0;
+
+  newImage = mdd_dup(image);
+
+  imgComp = ImgComponentAlloc(info);
+  imgComp->func = image;
+  ImgComponentGetSupport(imgComp);
+
+  if (relationArray) {
+    cofactor = mdd_one(info->manager);
+    abstract = mdd_one(info->manager);
+  } else {
+    cofactor = NIL(mdd_t);
+    abstract = NIL(mdd_t);
+  }
+
+  if (info->nIntermediateVars) {
+    mdd_t	*tmpCofactor, *tmpAbstract;
+    mdd_t	*constIntermediate;
+
+    if (ImgExistConstIntermediateVar(vector)) {
+      constIntermediate = mdd_one(info->manager);
+      for (i = 0; i < array_n(vector); i++) {
+	comp = array_fetch(ImgComponent_t *, vector, i);
+	if (comp->intermediate) {
+	  if (mdd_is_tautology(comp->func, 1)) {
+	    tmp = constIntermediate;
+	    constIntermediate = mdd_and(tmp, comp->var, 1, 1);
+	    mdd_free(tmp);
+	  } else if (mdd_is_tautology(comp->func, 0)) {
+	    tmp = constIntermediate;
+	    constIntermediate = mdd_and(tmp, comp->var, 1, 0);
+	    mdd_free(tmp);
+	  }
+	}
+      }
+      if (relationArray) {
+	cofactoredVector = ImgComposeConstIntermediateVars(info, vector,
+						  constIntermediate,
+						  &tmpCofactor, &tmpAbstract,
+						  NIL(mdd_t *), &newImage);
+
+	if (!bdd_is_tautology(tmpCofactor, 1)) {
+	  tmp = cofactor;
+	  cofactor = mdd_and(tmp, tmpCofactor, 1, 1);
+	  mdd_free(tmp);
+	}
+	mdd_free(tmpCofactor);
+	if (!bdd_is_tautology(tmpAbstract, 1)) {
+	  tmp = abstract;
+	  abstract = mdd_and(tmp, tmpAbstract, 1, 1);
+	  mdd_free(tmp);
+	}
+	mdd_free(tmpAbstract);
+      } else {
+	cofactoredVector = ImgComposeConstIntermediateVars(info, vector,
+						  constIntermediate,
+						  NIL(mdd_t *), NIL(mdd_t *),
+						  NIL(mdd_t *), &newImage);
+      }
+      mdd_free(constIntermediate);
+    } else
+      cofactoredVector = vector;
+  } else
+    cofactoredVector = vector;
+
+  /* Simplify image -- canonicalize the image first */
+  n = 0;
+  equivTable = st_init_table(st_ptrcmp, st_ptrhash);
+  tmpVector = array_alloc(ImgComponent_t *, 0);
+  for (i = 0; i < array_n(cofactoredVector); i++) {
+    comp = array_fetch(ImgComponent_t *, cofactoredVector, i);
+    if (comp->intermediate) {
+      comp1 = ImgComponentCopy(info, comp);
+      array_insert_last(ImgComponent_t *, tmpVector, comp1);
+      n++;
+      continue;
+    }
+    id = (int)bdd_top_var_id(comp->var);
+    if (!imgComp->support[id]) {
+      if (abstract) {
+	nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+	tmp = abstract;
+	abstract = mdd_and(tmp, nsVar, 1, 1);
+	mdd_free(tmp);
+	mdd_free(nsVar);
+      }
+      continue;
+    }
+    if (mdd_is_tautology(comp->func, 1)) {
+      changed = 1;
+      simple = bdd_cofactor(newImage, comp->var);
+      mdd_free(newImage);
+      newImage = simple;
+      if (abstract) {
+	nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+	tmp = abstract;
+	abstract = mdd_and(tmp, nsVar, 1, 1);
+	mdd_free(tmp);
+	mdd_free(nsVar);
+      }
+    } else if (mdd_is_tautology(comp->func, 0)) {
+      changed = 1;
+      tmp = mdd_not(comp->var);
+      simple = bdd_cofactor(newImage, tmp);
+      mdd_free(tmp);
+      mdd_free(newImage);
+      newImage = simple;
+      if (abstract) {
+	nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+	tmp = abstract;
+	abstract = mdd_and(tmp, nsVar, 1, 1);
+	mdd_free(tmp);
+	mdd_free(nsVar);
+      }
+    } else {
+      ptr = (int *)bdd_pointer(comp->func);
+      regularPtr = (int *)((unsigned long)ptr & ~01);
+      if (st_lookup_int(equivTable, (char *)regularPtr, &pos)) {
+	changed = 1;
+	comp1 = array_fetch(ImgComponent_t *, tmpVector, pos);
+	if (mdd_equal(comp->func, comp1->func)) {
+	  tmp = newImage;
+	  newImage = bdd_compose(tmp, comp->var, comp1->var);
+	  mdd_free(tmp);
+	} else {
+	  tmp = newImage;
+	  var = mdd_not(comp1->var);
+	  newImage = bdd_compose(tmp, comp->var, var);
+	  mdd_free(tmp);
+	  mdd_free(var);
+	}
+	if (abstract) {
+	  nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+	  tmp = abstract;
+	  abstract = mdd_and(tmp, nsVar, 1, 1);
+	  mdd_free(tmp);
+	  mdd_free(nsVar);
+	}
+      } else {
+	comp1 = ImgComponentCopy(info, comp);
+	array_insert_last(ImgComponent_t *, tmpVector, comp1);
+	st_insert(equivTable, (char *)regularPtr, (char *)(long)n);
+	n++;
+      }
+    }
+  }
+  st_free_table(equivTable);
+  if (cofactoredVector && cofactoredVector != vector)
+    ImgVectorFree(cofactoredVector);
+
+  if (changed) {
+    /* Now Simplify delta by deleting the non-affecting components */
+    *newVector = array_alloc(ImgComponent_t *, 0);
+
+    imgComp->func = NIL(mdd_t);
+    ImgComponentFree(imgComp);
+
+    imgComp = ImgComponentAlloc(info);
+    imgComp->func = newImage;
+    ImgSupportClear(info, imgComp->support);
+    ImgComponentGetSupport(imgComp);
+    for (i = 0; i < array_n(tmpVector); i++) {
+      comp = array_fetch(ImgComponent_t *, tmpVector, i);
+      id = (int)bdd_top_var_id(comp->var);
+      if (imgComp->support[id] || comp->intermediate)
+	array_insert_last(ImgComponent_t *, *newVector, comp);
+      else {
+	if (abstract) {
+	  nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+	  tmp = abstract;
+	  abstract = mdd_and(tmp, nsVar, 1, 1);
+	  mdd_free(tmp);
+	  mdd_free(nsVar);
+	}
+	ImgComponentFree(comp);
+      }
+    }
+    array_free(tmpVector);
+  } else
+    *newVector = tmpVector;
+
+  imgComp->func = NIL(mdd_t);
+  ImgComponentFree(imgComp);
+
+  if (newRelationArray)
+    *newRelationArray = relationArray;
+  if (cofactor) {
+    if (cofactorCube)
+      *cofactorCube = cofactor;
+    else {
+      if (!bdd_is_tautology(cofactor, 1)) {
+	tmpRelationArray = *newRelationArray;
+	*newRelationArray = ImgGetCofactoredRelationArray(tmpRelationArray,
+							  cofactor);
+	if (tmpRelationArray != relationArray)
+	  mdd_array_free(tmpRelationArray);
+      }
+      mdd_free(cofactor);
+    }
+  }
+  if (abstract) {
+    if (abstractCube)
+      *abstractCube = abstract;
+    else {
+      if (bdd_is_tautology(abstract, 1))
+	mdd_free(abstract);
+      else {
+	tmpRelationArray = *newRelationArray;
+	*newRelationArray = ImgGetAbstractedRelationArray(info->manager,
+							  tmpRelationArray,
+							  abstract);
+	mdd_free(abstract);
+	if (tmpRelationArray != relationArray)
+	  mdd_array_free(tmpRelationArray);
+      }
+    }
+  }
+  assert(CheckPreImageVector(info, *newVector, newImage));
+  return(newImage);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makes transition relation canonical for preimage.]
+
+  Description [Makes transition relation canonical for preimage.
+  Quantifies out the next state variables that do not occur in the image,
+  and when a vector exists, delete the components which do not appear
+  in the image. If a component is constant, simplify the image with the
+  constant value and delete the corresponding component from delta
+  Side effect on delta.  Return new image.]
+
+  SideEffects []
+
+******************************************************************************/
+static bdd_t *
+PreImageMakeRelationCanonical(ImgTfmInfo_t *info, array_t *vector, bdd_t *image,
+			      array_t *relationArray, array_t **newVector,
+			      array_t **newRelationArray)
+{
+  array_t		*tmpVector, *cofactoredVector;
+  bdd_t			*simple, *tmp, *newImage;
+  ImgComponent_t	*comp, *comp1, *imgComp;
+  int			i, j, id;
+  mdd_t			*cofactor, *abstract, *var, *nsVar;
+  array_t		*tmpRelationArray;
+  int			changed = 0;
+  mdd_t			*yVarsCube, *rangeCube, *relation, *tmp2;
+  array_t		*supportIds;
+
+  imgComp = ImgComponentAlloc(info);
+  imgComp->func = image;
+  ImgComponentGetSupport(imgComp);
+
+  if (vector) {
+    newImage = mdd_dup(image);
+    cofactor = mdd_one(info->manager);
+    abstract = mdd_one(info->manager);
+
+    if (info->nIntermediateVars) {
+      mdd_t	*tmpCofactor, *tmpAbstract;
+      mdd_t	*constIntermediate;
+
+      if (ImgExistConstIntermediateVar(vector)) {
+	constIntermediate = mdd_one(info->manager);
+
+	for (i = 0; i < array_n(vector); i++) {
+	  comp = array_fetch(ImgComponent_t *, vector, i);
+	  if (comp->intermediate) {
+	    if (mdd_is_tautology(comp->func, 1)) {
+	      tmp = constIntermediate;
+	      constIntermediate = mdd_and(tmp, comp->var, 1, 1);
+	      mdd_free(tmp);
+	    } else if (mdd_is_tautology(comp->func, 0)) {
+	      tmp = constIntermediate;
+	      constIntermediate = mdd_and(tmp, comp->var, 1, 0);
+	      mdd_free(tmp);
+	    }
+	  }
+	}
+
+	cofactoredVector = ImgComposeConstIntermediateVars(info, vector,
+							   constIntermediate,
+							   &tmpCofactor,
+							   &tmpAbstract,
+							   NIL(mdd_t *),
+							   &newImage);
+
+	if (!bdd_is_tautology(tmpCofactor, 1)) {
+	  tmp = cofactor;
+	  cofactor = mdd_and(tmp, tmpCofactor, 1, 1);
+	  mdd_free(tmp);
+	}
+	mdd_free(tmpCofactor);
+	if (!bdd_is_tautology(tmpAbstract, 1)) {
+	  tmp = abstract;
+	  abstract = mdd_and(tmp, tmpAbstract, 1, 1);
+	  mdd_free(tmp);
+	}
+	mdd_free(tmpAbstract);
+	mdd_free(constIntermediate);
+      } else
+	cofactoredVector = vector;
+    } else
+      cofactoredVector = vector;
+
+    /* Simplify image -- canonicalize vector */
+    tmpVector = array_alloc(ImgComponent_t *, 0);
+    for (i = 0; i < array_n(cofactoredVector); i++) {
+      comp = array_fetch(ImgComponent_t *, cofactoredVector, i);
+      if (comp->intermediate) {
+	comp1 = ImgComponentCopy(info, comp);
+	array_insert_last(ImgComponent_t *, tmpVector, comp1);
+	continue;
+      }
+      id = (int)bdd_top_var_id(comp->var);
+      if (!imgComp->support[id]) {
+	if (abstract) {
+	  nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+	  tmp = abstract;
+	  abstract = mdd_and(tmp, nsVar, 1, 1);
+	  mdd_free(tmp);
+	  mdd_free(nsVar);
+	}
+	continue;
+      }
+      if (mdd_is_tautology(comp->func, 1)) {
+	changed = 1;
+	simple = bdd_cofactor(newImage, comp->var);
+	mdd_free(newImage);
+	newImage = simple;
+	if (abstract) {
+	  nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+	  tmp = abstract;
+	  abstract = mdd_and(tmp, nsVar, 1, 1);
+	  mdd_free(tmp);
+	  mdd_free(nsVar);
+	}
+      } else if (mdd_is_tautology(comp->func, 0)) {
+	changed = 1;
+	tmp = mdd_not(comp->var);
+	simple = bdd_cofactor(newImage, tmp);
+	mdd_free(tmp);
+	mdd_free(newImage);
+	newImage = simple;
+	if (abstract) {
+	  nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+	  tmp = abstract;
+	  abstract = mdd_and(tmp, nsVar, 1, 1);
+	  mdd_free(tmp);
+	  mdd_free(nsVar);
+	}
+      } else {
+	comp1 = ImgComponentCopy(info, comp);
+	array_insert_last(ImgComponent_t *, tmpVector, comp1);
+      }
+    }
+    if (cofactoredVector && cofactoredVector != vector)
+      ImgVectorFree(cofactoredVector);
+
+    if (changed) {
+      /* Now Simplify delta by deleting the non-affecting components */
+      *newVector = array_alloc(ImgComponent_t *, 0);
+
+      imgComp->func = NIL(mdd_t);
+      ImgComponentFree(imgComp);
+
+      imgComp = ImgComponentAlloc(info);
+      imgComp->func = newImage;
+      ImgSupportClear(info, imgComp->support);
+      ImgComponentGetSupport(imgComp);
+      for (i = 0; i < array_n(tmpVector); i++) {
+	comp = array_fetch(ImgComponent_t *, tmpVector, i);
+	id = (int)bdd_top_var_id(comp->var);
+	if (imgComp->support[id] || comp->intermediate)
+	  array_insert_last(ImgComponent_t *, *newVector, comp);
+	else {
+	  if (abstract) {
+	    nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+	    tmp = abstract;
+	    abstract = mdd_and(tmp, nsVar, 1, 1);
+	    mdd_free(tmp);
+	    mdd_free(nsVar);
+	  }
+	  ImgComponentFree(comp);
+	}
+      }
+      array_free(tmpVector);
+    } else
+      *newVector = tmpVector;
+  } else {
+    newImage = image;
+    *newVector = vector;
+    cofactor = NIL(mdd_t);
+    abstract = NIL(mdd_t);
+  }
+
+  yVarsCube = mdd_one(info->manager);
+  for (i = 0; i < info->nVars; i++) {
+    if (imgComp->support[i]) {
+      imgComp->support[i] = 0;
+      if (st_lookup(info->quantifyVarsTable, (char *)(long)i, NIL(char *)))
+	continue;
+      if (info->intermediateVarsTable &&
+	  st_lookup(info->intermediateVarsTable, (char *)(long)i,
+		    NIL(char *))) {
+	continue;
+      }
+      var = bdd_var_with_index(info->manager, i);
+      nsVar = ImgSubstitute(var, info->functionData, Img_D2R_c);
+      mdd_free(var);
+      id = (int)bdd_top_var_id(nsVar);
+      imgComp->support[id] = 1;
+      tmp = yVarsCube;
+      yVarsCube = mdd_and(tmp, nsVar, 1, 1);
+      mdd_free(tmp);
+      mdd_free(nsVar);
+    }
+  }
+
+  if (vector) {
+    for (i = 0; i < array_n(*newVector); i++) {
+      comp = array_fetch(ImgComponent_t *, *newVector, i);
+      nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+      id = (int)bdd_top_var_id(nsVar);
+      imgComp->support[id] = 2;
+      mdd_free(nsVar);
+    }
+  }
+
+  for (i = 0; i < array_n(relationArray); i++) {
+    relation = array_fetch(mdd_t *, relationArray, i);
+    supportIds = mdd_get_bdd_support_ids(info->manager, relation);
+    for (j = 0; j < array_n(supportIds); j++) {
+      id = array_fetch(int, supportIds, j);
+      imgComp->support[id] = 2;
+    }
+    array_free(supportIds);
+  }
+
+  for (i = 0; i < info->nVars; i++) {
+    if (imgComp->support[i] == 1) {
+      nsVar = bdd_var_with_index(info->manager, i);
+      var = ImgSubstitute(nsVar, info->functionData, Img_R2D_c);
+      mdd_free(nsVar);
+      tmp = newImage;
+      newImage = bdd_smooth_with_cube(tmp, var);
+      if (tmp != image)
+	mdd_free(tmp);
+      mdd_free(var);
+    }
+  }
+
+  imgComp->func = NIL(mdd_t);
+  ImgComponentFree(imgComp);
+
+  if (bdd_get_package_name() == CUDD)
+    rangeCube = info->functionData->rangeCube;
+  else {
+    rangeCube = mdd_one(info->manager);
+    for (i = 0; i < array_n(info->functionData->rangeBddVars); i++) {
+      var = array_fetch(mdd_t *, info->functionData->rangeBddVars, i);
+      tmp = rangeCube;
+      rangeCube = mdd_and(tmp, var, 1, 1);
+      mdd_free(tmp);
+    }
+  }
+
+  cofactor = NIL(mdd_t);
+  if (abstract) {
+    tmp2 = bdd_smooth_with_cube(rangeCube, yVarsCube);
+    tmp = abstract;
+    abstract = mdd_and(tmp, tmp2, 1, 1);
+    mdd_free(tmp);
+    mdd_free(tmp2);
+  } else
+    abstract = bdd_smooth_with_cube(rangeCube, yVarsCube);
+  mdd_free(yVarsCube);
+  if (rangeCube != info->functionData->rangeCube)
+    mdd_free(rangeCube);
+
+  *newRelationArray = relationArray;
+  if (cofactor) {
+    if (!bdd_is_tautology(cofactor, 1)) {
+      tmpRelationArray = *newRelationArray;
+      *newRelationArray = ImgGetCofactoredRelationArray(tmpRelationArray,
+							cofactor);
+      if (tmpRelationArray != relationArray)
+	mdd_array_free(tmpRelationArray);
+    }
+    mdd_free(cofactor);
+  }
+  if (bdd_is_tautology(abstract, 1))
+    mdd_free(abstract);
+  else {
+    tmpRelationArray = *newRelationArray;
+    *newRelationArray = ImgGetAbstractedRelationArray(info->manager,
+						      tmpRelationArray,
+						      abstract);
+    mdd_free(abstract);
+    if (tmpRelationArray != relationArray)
+      mdd_array_free(tmpRelationArray);
+  }
+  return(newImage);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Deletes a component in a vector.]
+
+  Description [Deletes a component in a vector. Deletes index-th component
+  out of delta and copy it into newDelta.]
+
+  SideEffects []
+
+******************************************************************************/
+static bdd_t *
+PreImageDeleteOneComponent(ImgTfmInfo_t *info, array_t *delta, int index,
+			   array_t **newDelta)
+{
+  int			i;
+  ImgComponent_t	*comp, *tmpComp;
+  bdd_t			*func, *newFunc;
+  int			preMinimize = info->option->preMinimize;
+
+  assert(array_n(delta) > 0);
+
+  comp = array_fetch(ImgComponent_t *, delta, index);
+  func = mdd_dup(comp->func);
+
+  *newDelta = array_alloc(ImgComponent_t *, 0);
+  for (i = 0; i < array_n(delta); i++) {
+    if (i != index) {
+      comp = array_fetch(ImgComponent_t *, delta, i);
+      tmpComp = ImgComponentCopy(info, comp);
+      if (preMinimize) {
+	newFunc = bdd_minimize(tmpComp->func, func);
+	if (mdd_equal(newFunc, tmpComp->func))
+	  mdd_free(newFunc);
+	else {
+	  mdd_free(tmpComp->func);
+	  tmpComp->func = newFunc;
+	  ImgSupportClear(info, tmpComp->support);
+	  ImgComponentGetSupport(tmpComp);
+	}
+      }
+      array_insert_last(ImgComponent_t *, (*newDelta), tmpComp);
+    }
+  }
+
+  return(func);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Chooses a splitting variable for preimage.]
+
+  Description [Chooses a splitting variable for preimage.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+PreImageChooseSplitVar(ImgTfmInfo_t *info, array_t *delta, bdd_t *img,
+			int splitMethod, int split)
+{
+  ImgComponent_t	*comp, *imgComp;
+  int			i, j, bestCost, newCost;
+  int			index, bestVar, bestComp;
+  int			nFuncs, nVars, bestOccur = 0;
+  int			*varOccur, *varCost;
+  mdd_t			*var, *varNot, *pcFunc, *ncFunc;
+  int			tieCount = 0;
+
+  assert(array_n(delta) > 0);
+
+  if (splitMethod == 0) {
+    bestVar = -1;
+    bestComp = -1;
+    nFuncs = array_n(delta);
+    nVars = info->nVars;
+    varOccur = ALLOC(int, nVars);
+    memset(varOccur, 0, sizeof(int) * nVars);
+    varCost = NIL(int);
+    for (i = 0; i < nFuncs; i++) {
+      comp = array_fetch(ImgComponent_t *, delta, i);
+      for (j = 0; j < nVars; j++) {
+	if (comp->support[j])
+	  varOccur[j]++;
+      }
+    }
+    switch (split) {
+    case 0: /* largest support */
+      for (i = 0; i < nVars; i++) {
+	if (varOccur[i] == 0)
+	  continue;
+	if (st_lookup(info->quantifyVarsTable, (char *)(long)i, NIL(char *)))
+	  continue;
+	if (info->intermediateVarsTable &&
+	    st_lookup(info->intermediateVarsTable, (char *)(long)i,
+			NIL(char *))) {
+	  continue;
+	}
+	if (bestVar == -1 || varOccur[i] > bestOccur) {
+	  bestVar = i;
+	  bestOccur = varOccur[i];
+	  tieCount = 1;
+	} else if (varOccur[i] == bestOccur) {
+	  tieCount++;
+	  if (info->option->tieBreakMode == 0 &&
+	      bdd_get_level_from_id(info->manager, i) <
+	      bdd_get_level_from_id(info->manager, bestVar)) {
+	    bestVar = i;
+	  }
+	}
+      }
+
+      if (info->option->tieBreakMode == 1 && tieCount > 1) {
+	bestCost = IMG_TF_MAX_INT;
+	for (i = bestVar; i < nVars; i++) {
+	  if (varOccur[i] != bestOccur)
+	    continue;
+	  if (st_lookup(info->quantifyVarsTable, (char *)(long)i, NIL(char *)))
+	    continue;
+	  if (info->intermediateVarsTable &&
+	      st_lookup(info->intermediateVarsTable, (char *)(long)i,
+			NIL(char *))) {
+	    continue;
+	  }
+	  var = bdd_var_with_index(info->manager, i);
+	  newCost = 0;
+	  for (j = 0; j < array_n(delta); j++) {
+	    comp = array_fetch(ImgComponent_t *, delta, j);
+	    newCost += bdd_estimate_cofactor(comp->func, var, 1);
+	    newCost += bdd_estimate_cofactor(comp->func, var, 0);
+	  }
+	  mdd_free(var);
+
+	  if (newCost < bestCost) {
+	    bestVar = i;
+	    bestCost = newCost;
+	  } else if (newCost == bestCost) {
+	    if (bdd_get_level_from_id(info->manager, i) <
+		bdd_get_level_from_id(info->manager, bestVar)) {
+	      bestVar = i;
+	    }
+	  }
+	}
+      }
+      break;
+    case 1: /* smallest support after splitting */
+      /* Find the variable which makes the smallest support after splitting */
+      bestCost = IMG_TF_MAX_INT;
+      varCost = ALLOC(int, nVars);
+      memset(varCost, 0, sizeof(int) * nVars);
+      for (i = 0; i < nVars; i++) {
+	if (varOccur[i] == 0)
+	  continue;
+	if (st_lookup(info->quantifyVarsTable, (char *)(long)i, NIL(char *)))
+	  continue;
+	if (info->intermediateVarsTable &&
+	    st_lookup(info->intermediateVarsTable, (char *)(long)i,
+			NIL(char *))) {
+	  continue;
+	}
+	var = bdd_var_with_index(info->manager, i);
+	varNot = mdd_not(var);
+	for (j = 0; j < array_n(delta); j++) {
+	  comp = array_fetch(ImgComponent_t *, delta, j);
+	  pcFunc = bdd_cofactor(comp->func, var);
+	  varCost[i] += ImgCountBddSupports(pcFunc);
+	  mdd_free(pcFunc);
+	  ncFunc = bdd_cofactor(comp->func, varNot);
+	  varCost[i] += ImgCountBddSupports(ncFunc);
+	  mdd_free(ncFunc);
+	}
+	mdd_free(var);
+	mdd_free(varNot);
+
+	if (varCost[i] < bestCost) {
+	  bestCost = varCost[i];
+	  bestVar = i;
+	} else if (varCost[i] == bestCost) {
+	  if (varOccur[i] < varOccur[bestVar]) {
+	    bestVar = i;
+	  } else if (varOccur[i] == varOccur[bestVar]) {
+	    if (bdd_get_level_from_id(info->manager, i) <
+		bdd_get_level_from_id(info->manager, bestVar)) {
+	      bestVar = i;
+	    }
+	  }
+	}
+      }
+      break;
+    case 2: /* smallest BDD size after splitting */
+      /* Find the variable which makes the smallest BDDs of all functions
+	 after splitting */
+      bestCost = IMG_TF_MAX_INT;
+      varCost = ALLOC(int, nVars);
+      memset(varCost, 0, sizeof(int) * nVars);
+      for (i = 0; i < nVars; i++) {
+	if (varOccur[i] == 0)
+	  continue;
+	if (st_lookup(info->quantifyVarsTable, (char *)(long)i, NIL(char *)))
+	  continue;
+	if (info->intermediateVarsTable &&
+	    st_lookup(info->intermediateVarsTable, (char *)(long)i,
+			NIL(char *))) {
+	  continue;
+	}
+	var = bdd_var_with_index(info->manager, i);
+	for (j = 0; j < array_n(delta); j++) {
+	  comp = array_fetch(ImgComponent_t *, delta, j);
+	  varCost[i] += bdd_estimate_cofactor(comp->func, var, 1);
+	  varCost[i] += bdd_estimate_cofactor(comp->func, var, 0);
+	}
+	mdd_free(var);
+
+	if (varCost[i] < bestCost) {
+	  bestCost = varCost[i];
+	  bestVar = i;
+	} else if (varCost[i] == bestCost) {
+	  if (varOccur[i] < varOccur[bestVar]) {
+	    bestVar = i;
+	  } else if (varOccur[i] == varOccur[bestVar]) {
+	    if (bdd_get_level_from_id(info->manager, i) <
+		bdd_get_level_from_id(info->manager, bestVar)) {
+	      bestVar = i;
+	    }
+	  }
+	}
+      }
+      break;
+    case 3: /* top variable */
+    default:
+      for (i = 0; i < nVars; i++) {
+	if (varOccur[i] == 0)
+	  continue;
+	if (st_lookup(info->quantifyVarsTable, (char *)(long)i, NIL(char *)))
+	  continue;
+	if (info->intermediateVarsTable &&
+	    st_lookup(info->intermediateVarsTable, (char *)(long)i,
+			NIL(char *))) {
+	  continue;
+	}
+	if (bestVar == -1)
+	  bestVar = i;
+	else if (bdd_get_level_from_id(info->manager, i) <
+		 bdd_get_level_from_id(info->manager, bestVar)) {
+	  bestVar = i;
+	}
+      }
+    }
+    FREE(varOccur);
+    if (varCost)
+      FREE(varCost);
+  } else {
+    bestComp = -1;
+    bestVar = -1;
+    switch (split) {
+    case 0: /* smallest BDD size */
+      bestCost = IMG_TF_MAX_INT;
+      imgComp = ImgComponentAlloc(info);
+      imgComp->func = img;
+      ImgComponentGetSupport(imgComp);
+      for (i = 0; i < array_n(delta); i++) {
+	comp = array_fetch(ImgComponent_t *, delta, i);
+	if (comp->intermediate)
+	  continue;
+	index = (int)bdd_top_var_id(comp->var);
+	if (imgComp->support[index]) {
+	  newCost = bdd_size(comp->func);
+	  if (newCost < bestCost) {
+	    bestComp = i;
+	    bestCost = newCost;
+	  }
+	}
+      }
+      imgComp->func = NIL(mdd_t);
+      ImgComponentFree(imgComp);
+      break;
+    case 1: /* largest BDD size */
+      bestCost = 0;
+      imgComp = ImgComponentAlloc(info);
+      imgComp->func = img;
+      ImgComponentGetSupport(imgComp);
+      for (i = 0; i < array_n(delta); i++) {
+	comp = array_fetch(ImgComponent_t *, delta, i);
+	if (comp->intermediate)
+	  continue;
+	index = (int)bdd_top_var_id(comp->var);
+	if (imgComp->support[index]) {
+	  newCost = bdd_size(comp->func);
+	  if (newCost > bestCost) {
+	    bestComp = i;
+	    bestCost = newCost;
+	  }
+	}
+      }
+      imgComp->func = NIL(mdd_t);
+      ImgComponentFree(imgComp);
+      break;
+    case 2: /* top variable */
+    default:
+      for (i = 0; i < array_n(delta); i++) {
+	comp = array_fetch(ImgComponent_t *, delta, i);
+	if (comp->intermediate)
+	  continue;
+	index = (int)bdd_top_var_id(comp->var);
+	if (bestComp == -1 ||
+	    bdd_get_level_from_id(info->manager, index) <
+	    bdd_get_level_from_id(info->manager, bestVar)) {
+	  bestVar = index;
+	  bestComp = i;
+	}
+      }
+      break;
+    }
+    assert(bestComp != -1);
+  }
+
+  if (splitMethod == 0)
+    return(bestVar);
+  else
+    return(bestComp);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs domain cofactoring on a vector and from set with
+  respect to a variable.]
+
+  Description [Performs domain cofactoring on a vector and from set with
+  respect to a variable.]
+
+  SideEffects []
+
+******************************************************************************/
+static mdd_t *
+DomainCofactoring(ImgTfmInfo_t *info, array_t *vector, mdd_t *from,
+		  array_t *relationArray, mdd_t *c, array_t **newVector,
+		  array_t **newRelationArray, mdd_t **cofactorCube,
+		  mdd_t **abstractCube)
+{
+  mdd_t			*res, *tmp;
+  ImgComponent_t	*comp, *comp1;
+  array_t		*vector1;
+  int			i, index, n, pos;
+  mdd_t			*newFrom, *var, *nsVar;
+  mdd_t			*cofactor, *abstract, *constIntermediate;
+  array_t		*tmpRelationArray;
+  st_table		*equivTable;
+  int			*ptr, *regularPtr;
+  int			size;
+
+  newFrom = mdd_dup(from);
+  vector1 = array_alloc(ImgComponent_t *, 0);
+
+  if (relationArray) {
+    cofactor = mdd_one(info->manager);
+    abstract = mdd_one(info->manager);
+  } else {
+    cofactor = NIL(mdd_t);
+    abstract = NIL(mdd_t);
+  }
+
+  if (info->nIntermediateVars) {
+    size = ImgVectorFunctionSize(vector);
+    if (size == array_n(vector))
+      constIntermediate = NIL(mdd_t);
+    else
+      constIntermediate = mdd_one(info->manager);
+  } else
+    constIntermediate = NIL(mdd_t);
+
+  n = 0;
+  equivTable = st_init_table(st_ptrcmp, st_ptrhash);
+  index = (int)bdd_top_var_id(c);
+  for (i = 0; i < array_n(vector); i++) {
+    comp = array_fetch(ImgComponent_t *, vector, i);
+    if (comp->support[index])
+      res = bdd_cofactor(comp->func, c);
+    else
+      res = mdd_dup(comp->func);
+    if (bdd_is_tautology(res, 1)) {
+      if (comp->intermediate) {
+	tmp = constIntermediate;
+	constIntermediate = mdd_and(tmp, comp->var, 1, 1);
+	mdd_free(tmp);
+	mdd_free(res);
+	continue;
+      }
+      tmp = newFrom;
+      newFrom = bdd_cofactor(tmp, comp->var);
+      mdd_free(tmp);
+      mdd_free(res);
+      if (relationArray) {
+	nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+	tmp = abstract;
+	abstract = mdd_and(tmp, nsVar, 1, 1);
+	mdd_free(tmp);
+	mdd_free(nsVar);
+      }
+    } else if (bdd_is_tautology(res, 0)) {
+      if (comp->intermediate) {
+	tmp = constIntermediate;
+	constIntermediate = mdd_and(tmp, comp->var, 1, 0);
+	mdd_free(tmp);
+	mdd_free(res);
+	continue;
+      }
+      tmp = newFrom;
+      var = mdd_not(comp->var);
+      newFrom = bdd_cofactor(tmp, var);
+      mdd_free(tmp);
+      mdd_free(var);
+      mdd_free(res);
+      if (relationArray) {
+	nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+	tmp = abstract;
+	abstract = mdd_and(tmp, nsVar, 1, 1);
+	mdd_free(tmp);
+	mdd_free(nsVar);
+      }
+    } else {
+      if (comp->intermediate) {
+	comp1 = ImgComponentAlloc(info);
+	comp1->var = mdd_dup(comp->var);
+	comp1->func = res;
+	if (mdd_equal(res, comp->func))
+	  ImgSupportCopy(info, comp1->support, comp->support);
+	else
+	  ImgComponentGetSupport(comp1);
+	comp1->intermediate = 1;
+	array_insert_last(ImgComponent_t *, vector1, comp1);
+	n++;
+	continue;
+      }
+      ptr = (int *)bdd_pointer(res);
+      regularPtr = (int *)((unsigned long)ptr & ~01);
+      if (st_lookup_int(equivTable, (char *)regularPtr, &pos)) {
+	comp1 = array_fetch(ImgComponent_t *, vector1, pos);
+	if (mdd_equal(res, comp1->func)) {
+	  tmp = newFrom;
+	  newFrom = bdd_compose(tmp, comp->var, comp1->var);
+	  mdd_free(tmp);
+	} else {
+	  tmp = newFrom;
+	  var = mdd_not(comp1->var);
+	  newFrom = bdd_compose(tmp, comp->var, var);
+	  mdd_free(tmp);
+	  mdd_free(var);
+	}
+	mdd_free(res);
+	if (abstract) {
+	  nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+	  tmp = abstract;
+	  abstract = mdd_and(tmp, nsVar, 1, 1);
+	  mdd_free(tmp);
+	  mdd_free(nsVar);
+	}
+      } else {
+	comp1 = ImgComponentAlloc(info);
+	comp1->var = mdd_dup(comp->var);
+	comp1->func = res;
+	if (mdd_equal(res, comp->func))
+	  ImgSupportCopy(info, comp1->support, comp->support);
+	else
+	  ImgComponentGetSupport(comp1);
+	array_insert_last(ImgComponent_t *, vector1, comp1);
+	st_insert(equivTable, (char *)regularPtr, (char *)(long)n);
+	n++;
+      }
+    }
+  }
+  st_free_table(equivTable);
+
+  if (constIntermediate) {
+    if (!bdd_is_tautology(constIntermediate, 1)) {
+      mdd_t	*tmpCofactor, *tmpAbstract;
+
+      if (relationArray) {
+	vector1 = ImgComposeConstIntermediateVars(info, vector1,
+						  constIntermediate,
+						  &tmpCofactor, &tmpAbstract,
+						  NIL(mdd_t *), &newFrom);
+	if (!bdd_is_tautology(tmpCofactor, 1)) {
+	  tmp = cofactor;
+	  cofactor = mdd_and(tmp, tmpCofactor, 1, 1);
+	  mdd_free(tmp);
+	}
+	mdd_free(tmpCofactor);
+	if (!bdd_is_tautology(tmpAbstract, 1)) {
+	  tmp = abstract;
+	  abstract = mdd_and(tmp, tmpAbstract, 1, 1);
+	  mdd_free(tmp);
+	}
+	mdd_free(tmpAbstract);
+	tmp = cofactor;
+	cofactor = mdd_and(tmp, constIntermediate, 1, 1);
+	mdd_free(tmp);
+      } else {
+	vector1 = ImgComposeConstIntermediateVars(info, vector1,
+						  constIntermediate,
+						  NIL(mdd_t *), NIL(mdd_t *),
+						  NIL(mdd_t *), &newFrom);
+      }
+    }
+    mdd_free(constIntermediate);
+  }
+
+  *newVector = vector1;
+
+  if (relationArray) {
+    if (newRelationArray)
+      *newRelationArray = relationArray;
+    if (cofactorCube && abstractCube) {
+      if (cofactor) {
+	if (bdd_is_tautology(cofactor, 1)) {
+	  mdd_free(cofactor);
+	  *cofactorCube = mdd_dup(c);
+	} else {
+	  *cofactorCube = mdd_and(cofactor, c, 1, 1);
+	  mdd_free(cofactor);
+	}
+      }
+      if (abstract)
+	*abstractCube = abstract;
+    } else {
+      if (bdd_is_tautology(cofactor, 1)) {
+	*newRelationArray = ImgGetCofactoredRelationArray(relationArray, c);
+	mdd_free(cofactor);
+      } else {
+	tmp = cofactor;
+	cofactor = mdd_and(tmp, c, 1, 1);
+	mdd_free(tmp);
+	*newRelationArray = ImgGetCofactoredRelationArray(relationArray,
+							  cofactor);
+	mdd_free(cofactor);
+      }
+      if (bdd_is_tautology(abstract, 1))
+	mdd_free(abstract);
+      else {
+	tmpRelationArray = *newRelationArray;
+	*newRelationArray = ImgGetAbstractedRelationArray(info->manager,
+							tmpRelationArray,
+							abstract);
+	mdd_free(abstract);
+	if (tmpRelationArray != relationArray)
+	  mdd_array_free(tmpRelationArray);
+      }
+    }
+  } else
+    *newRelationArray = NIL(array_t);
+
+  return(newFrom);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks sanity of a vector for preimage.]
+
+  Description [Checks sanity of a vector for preimage.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CheckPreImageVector(ImgTfmInfo_t *info, array_t *vector, mdd_t *image)
+{
+  ImgComponent_t	*comp, *imgComp;
+  int			i, id, size, status;
+
+  status = 1;
+  if (info->nIntermediateVars)
+    size = ImgVectorFunctionSize(vector);
+  else
+    size = array_n(vector);
+  if (size != mdd_get_number_of_bdd_support(info->manager, image)) {
+    fprintf(vis_stderr,
+	    "** tfm error: function vector length is different. (%d != %d)\n",
+	    size, mdd_get_number_of_bdd_support(info->manager, image));
+    status = 0;
+  }
+
+  imgComp = ImgComponentAlloc(info);
+  imgComp->func = image;
+  ImgComponentGetSupport(imgComp);
+  for (i = 0; i < array_n(vector); i++) {
+    comp = array_fetch(ImgComponent_t *, vector, i);
+    id = (int)bdd_top_var_id(comp->var);
+    if (comp->intermediate)
+      imgComp->support[id] = 2;
+    else if (imgComp->support[id] == 0) {
+      fprintf(vis_stderr,
+	      "** tfm error: variable index[%d] is not in constraint\n", id);
+      status = 0;
+    } else
+      imgComp->support[id] = 2;
+  }
+  for (i = 0; i < info->nVars; i++) {
+    if (imgComp->support[i] == 1) {
+      fprintf(vis_stderr,
+	    "** tfm error: variable index[%d] is not in function vector\n", i);
+      status = 0;
+    }
+  }
+  imgComp->func = NIL(mdd_t);
+  ImgComponentFree(imgComp);
+  return(status);
+}
Index: vis_dev/vis-2.3/src/img/imgTfmCache.c
===================================================================
--- vis_dev/vis-2.3/src/img/imgTfmCache.c	(revision 14)
+++ vis_dev/vis-2.3/src/img/imgTfmCache.c	(revision 14)
@@ -0,0 +1,1119 @@
+/**CFile***********************************************************************
+
+  FileName    [imgTfmCache.c]
+
+  PackageName [img]
+
+  Synopsis    [Routines for image cache in transition function method.]
+
+  SeeAlso     [imgTfm.c imgTfmFwd.c imgTfmBwd.c imgTfmUtil.c]
+
+  Author      [In-Ho Moon]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF COLORADO BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  COLORADO HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF COLORADO SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF COLORADO HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+#include "imgInt.h"
+
+static char rcsid[] UNUSED = "$Id: imgTfmCache.c,v 1.8 2005/04/23 14:30:54 jinh Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+static	int		ComplementFlag; /* If set, returns the negation of the
+					   result from cache */
+static	array_t		*SubstituteVector; /* returns the result from cache by
+					      substituting the variables */
+static	ImgCacheTable_t	*ImgGlobalCache; /* global image cache */
+static	ImgCacheTable_t	*PreGlobalCache; /* global preimage cache */
+static	int		ImgGlobalCacheRef; /* the number of image-info
+					      refering to the image cache */
+static	int		PreGlobalCacheRef; /* the number of image-info
+					      refering to the preimage cache */
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void CacheDestroyEntry(ImgCacheEntry_t *entry, boolean freeEntry);
+static int VectorHash(ImgCacheTable_t *table, array_t *delta, bdd_t *constraint);
+static int VectorStHash(char *key, int modulus);
+static int KeyStHash(char *key, int modulus);
+static int VectorCompare(array_t *vector1, array_t *vector2);
+static int VectorSortCompare(array_t *vector1, array_t *vector2);
+static int VectorSortCompareWithConstraint(array_t *vector1, array_t *vector2);
+static int ImageKeyCompare(ImgCacheStKey_t *key1, ImgCacheStKey_t *key2);
+static int ImageKeySortCompare(ImgCacheStKey_t *key1, ImgCacheStKey_t *key2);
+static int PreImageKeyCompare(ImgCacheStKey_t *key1, ImgCacheStKey_t *key2);
+static mdd_t * SubstituteCacheResult(ImgTfmInfo_t *info, array_t *keyVector, array_t *cacheVector, mdd_t *result);
+static mdd_t * SubstituteCacheResultRecur(mdd_t *result, array_t *varArray, array_t *funcArray, int pos);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the statistics of image cache of transition function
+  method.]
+
+  Description [Gets the statistics of image cache of transition function
+  method]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Img_TfmGetCacheStatistics(Img_ImageInfo_t *imageInfo, int preFlag,
+			  double *inserts, double *lookups, double *hits,
+			  double *entries, int *nSlots, int *maxChainLength)
+{
+  ImgTfmInfo_t		*info;
+  ImgCacheTable_t	*cache;
+
+  if (imageInfo) {
+    if (imageInfo->methodType != Img_Tfm_c &&
+	imageInfo->methodType != Img_Hybrid_c) {
+      return(0);
+    }
+
+    info = (ImgTfmInfo_t *)imageInfo->methodData;
+    if (!info->option->useCache)
+      return(0);
+
+    if (preFlag)
+      cache = info->preCache;
+    else
+      cache = info->imgCache;
+    if (!cache)
+      return(0);
+  } else {
+    if (preFlag)
+      cache = PreGlobalCache;
+    else
+      cache = ImgGlobalCache;
+    if (!cache)
+      return(0);
+  }
+
+  *inserts = cache->inserts;
+  *lookups = cache->lookups;
+  *hits = cache->hits;
+  *entries = cache->entries;
+  if (cache->stTable) {
+    *nSlots = 0;
+    *maxChainLength = 0;
+  } else {
+    *nSlots = cache->nSlots;
+    *maxChainLength = cache->maxChainLength;
+  }
+  return(1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether a global cache is used for transition function
+  method.]
+
+  Description [Checks whether a global cache is used for transition function
+  method. If it is, returns 1, otherwise returns 0.
+  A global cache can be used when all image-info structs store the results
+  into one image cache. A local cache is used for each image-info struct stores
+  its results into its own image cache.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Img_TfmCheckGlobalCache(int preFlag)
+{
+  if (preFlag) {
+    if (PreGlobalCache)
+      return(1);
+    else
+      return(0);
+  } else {
+    if (ImgGlobalCache)
+      return(1);
+    else
+      return(0);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the statistics of image cache of transition function
+  method.]
+
+  Description [Prints the statistics of image cache of transition function
+  method.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Img_TfmPrintCacheStatistics(Img_ImageInfo_t *imageInfo, int preFlag)
+{
+  ImgTfmInfo_t		*info;
+  ImgCacheTable_t	*cache;
+
+  if (imageInfo) {
+    if (imageInfo->methodType != Img_Tfm_c &&
+	imageInfo->methodType != Img_Hybrid_c) {
+      return;
+    }
+
+    info = (ImgTfmInfo_t *)imageInfo->methodData;
+    if (!info->option->useCache)
+      return;
+
+    if (preFlag)
+      cache = info->preCache;
+    else
+      cache = info->imgCache;
+    if (!cache)
+      return;
+  } else {
+    if (preFlag)
+      cache = PreGlobalCache;
+    else
+      cache = ImgGlobalCache;
+    if (!cache)
+      return;
+  }
+  ImgPrintCacheStatistics(cache);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees all cache contents of image computation using transition
+  function method.]
+
+  Description [Frees all cache contents of image computation using transition
+  function method. This function is to free the cache contents only when
+  requested and when tfm_auto_flush_cache is off.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Img_TfmFlushCache(Img_ImageInfo_t *imageInfo, int preFlag)
+{
+  ImgTfmInfo_t	*info;
+
+  if (imageInfo) {
+    if (imageInfo->methodType != Img_Tfm_c &&
+	imageInfo->methodType != Img_Hybrid_c) {
+      return;
+    }
+
+    info = (ImgTfmInfo_t *)imageInfo->methodData;
+
+    if (info->option->autoFlushCache == 0) {
+      if (preFlag)
+	ImgFlushCache(info->preCache);
+      else
+	ImgFlushCache(info->imgCache);
+    }
+  }
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes a cache table.]
+
+  Description [Initializes a cache table.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgCacheInitTable(ImgTfmInfo_t *info, int num_slot, int globalCache,
+		boolean preImgFlag)
+{
+  ImgCacheTable_t	*table;
+  ImgTfmOption_t	*option = info->option;
+
+  if (globalCache) {
+    if (preImgFlag && PreGlobalCache) {
+      info->preCache = PreGlobalCache;
+      PreGlobalCacheRef++;
+      return;
+    } else if (!preImgFlag && ImgGlobalCache) {
+      info->imgCache = ImgGlobalCache;
+      ImgGlobalCacheRef++;
+      return;
+    }
+  }
+
+  table = ALLOC(ImgCacheTable_t, 1);
+  memset(table, 0, sizeof(ImgCacheTable_t));
+  table->nSlots = num_slot;
+  if (option->useCache == 2) {
+    if (preImgFlag)
+      table->stTable = st_init_table((ST_PFICPCP)PreImageKeyCompare,
+				     KeyStHash);
+    else if (info->useConstraint && option->sortVectorFlag)
+      table->stTable = st_init_table((ST_PFICPCP)ImageKeySortCompare,
+				     KeyStHash);
+    else if (info->useConstraint)
+      table->stTable = st_init_table((ST_PFICPCP)ImageKeyCompare,
+				     KeyStHash);
+    else if (option->sortVectorFlag)
+      table->stTable = st_init_table((ST_PFICPCP)VectorSortCompare,
+				     VectorStHash);
+    else
+      table->stTable = st_init_table((ST_PFICPCP)VectorCompare,
+				     VectorStHash);
+  } else {
+    table->slot = ALLOC(ImgCacheEntry_t *, num_slot);
+    memset(table->slot, 0, sizeof(ImgCacheEntry_t *) * num_slot);
+  }
+  table->maxChainLength = option->maxChainLength;
+  table->preImgFlag = preImgFlag;
+  table->useConstraint = info->useConstraint;
+  if (preImgFlag) {
+    table->compareFunc = VectorCompare;
+    info->preCache = table;
+  } else {
+    if (option->sortVectorFlag) {
+      if (info->useConstraint)
+	table->compareFunc = VectorSortCompareWithConstraint;
+      else
+	table->compareFunc = VectorSortCompare;
+    } else
+      table->compareFunc = VectorCompare;
+    info->imgCache = table;
+  }
+
+  if (globalCache) {
+    if (preImgFlag) {
+      PreGlobalCache = table;
+      PreGlobalCacheRef = 1;
+    } else {
+      ImgGlobalCache = table;
+      ImgGlobalCacheRef = 1;
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Destroys a cache table.]
+
+  Description [Destroys a cache table.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgCacheDestroyTable(ImgCacheTable_t *table, int globalCache)
+{
+  unsigned int		i;
+  ImgCacheEntry_t	*entry, *next;
+  array_t		*vector;
+  bdd_t			*result;
+  st_generator		*stGen;
+  ImgCacheStKey_t	*key;
+
+  if (globalCache) {
+    if (table->preImgFlag) {
+      PreGlobalCacheRef--;
+      if (PreGlobalCacheRef > 0)
+	return;
+    } else {
+      ImgGlobalCacheRef--;
+      if (ImgGlobalCacheRef > 0)
+	return;
+    }
+  }
+
+  if (table->stTable) {
+    if (table->preImgFlag || table->useConstraint) {
+      st_foreach_item(table->stTable, stGen, &key, &result) {
+	ImgVectorFree(key->vector);
+	if (key->constraint)
+	  mdd_free(key->constraint);
+	FREE(key);
+	mdd_free(result);
+      }
+    } else {
+      st_foreach_item(table->stTable, stGen, &vector, &result) {
+	ImgVectorFree(vector);
+	mdd_free(result);
+      }
+    }
+    st_free_table(table->stTable);
+  } else {
+    for (i = 0; i < table->nSlots; i++) {
+      entry = table->slot[i];
+      while (entry != NIL(ImgCacheEntry_t)) {
+	next = entry->next;
+	CacheDestroyEntry(entry, TRUE);
+	entry = next;
+      }
+    }
+    FREE(table->slot);
+  }
+
+  if (globalCache) {
+    if (table->preImgFlag)
+      PreGlobalCache = NIL(ImgCacheTable_t);
+    else
+      ImgGlobalCache = NIL(ImgCacheTable_t);
+  }
+
+  FREE(table);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Lookups cache table.]
+
+  Description [Lookups cache table.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+ImgCacheLookupTable(ImgTfmInfo_t *info, ImgCacheTable_t *table, array_t *delta,
+		    bdd_t *constraint)
+{
+  int			slot;
+  ImgCacheEntry_t	*entry;
+  bdd_t			*result, *newResult;
+  int			*ptr1, *ptr2;
+  ImgCacheStKey_t	key;
+
+  table->lookups += 1.0;
+
+  /* lossless cache */
+  if (table->stTable) {
+    if (table->preImgFlag) {
+      key.vector = delta;
+      key.constraint = constraint;
+      if (st_lookup(table->stTable, (char *)&key, &result)) {
+	table->hits += 1.0;
+	if (ComplementFlag)
+	  return(mdd_not(result));
+	else
+	  return(mdd_dup(result));
+      }
+    } else if (table->useConstraint) {
+      key.vector = delta;
+      key.constraint = constraint;
+      if (st_lookup(table->stTable, (char *)&key, &result)) {
+	table->hits += 1.0;
+	if (SubstituteVector) {
+	  newResult = SubstituteCacheResult(info, delta, SubstituteVector,
+					    result);
+	  return(newResult);
+	} else
+	  return(mdd_dup(result));
+      }
+    } else {
+      if (st_lookup(table->stTable, (char *)delta, &result)) {
+	table->hits += 1.0;
+	if (SubstituteVector) {
+	  newResult = SubstituteCacheResult(info, delta, SubstituteVector,
+					    result);
+	  return(newResult);
+	}
+	return(mdd_dup(result));
+      }
+    }
+
+    return(NIL(bdd_t));
+  }
+
+  slot = VectorHash(table, delta, constraint);
+
+  entry = table->slot[slot];
+  while (entry != NIL(ImgCacheEntry_t)) {
+    if ((*table->compareFunc)(delta, entry->vector) == 0) {
+      table->hits++;
+      if (table->preImgFlag) { /* preimage computation */
+	ptr1 = (int *)bdd_pointer(constraint);
+	ptr2 = (int *)bdd_pointer(entry->constraint);
+	if (((unsigned long)ptr1 ^ (unsigned long)ptr2) <= 01) {
+	  table->hits++;
+	  if (mdd_equal(constraint, entry->constraint))
+	    return(mdd_dup(entry->result));
+	  else
+	    return(mdd_not(entry->result));
+	}
+      } else if (constraint) { /* image computation */
+	if (mdd_equal(constraint, entry->constraint)) {
+	  if (SubstituteVector) {
+	    newResult = SubstituteCacheResult(info, delta, SubstituteVector,
+						entry->result);
+	    return(newResult);
+	  }
+	  return(mdd_dup(entry->result));
+	}
+      } else if (SubstituteVector) { /* range computation */
+	newResult = SubstituteCacheResult(info, delta, SubstituteVector,
+					  entry->result);
+	return(newResult);
+      } else {
+	return(mdd_dup(entry->result));
+      }
+    }
+    entry = entry->next;
+  }
+  return(NIL(bdd_t));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts an entry into cache table.]
+
+  Description [Inserts an entry into cache table.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgCacheInsertTable(ImgCacheTable_t *table, array_t *delta,
+		    bdd_t *constraint, bdd_t *result)
+{
+  int			slot, num, minSize;
+  ImgCacheEntry_t	*entry, *new_, *pos, *minDeltaEntry;
+
+  table->inserts += 1.0;
+
+  if (table->stTable) {
+    table->entries += 1.0;
+    if (table->preImgFlag || table->useConstraint) {
+      ImgCacheStKey_t	*key;
+
+      key = ALLOC(ImgCacheStKey_t, 1);
+      key->vector = delta;
+      key->constraint = constraint;
+      st_insert(table->stTable, (char *)key, (char *)result);
+    } else
+      st_insert(table->stTable, (char *)delta, (char *)result);
+    return;
+  }
+
+  slot = VectorHash(table, delta, constraint);
+
+  minSize = 0x7fffffff;
+  num = 0;
+  pos = table->slot[slot];
+  entry = minDeltaEntry = NIL(ImgCacheEntry_t);
+  while (pos != NIL(ImgCacheEntry_t)) {
+    if (array_n(pos->vector) < minSize) {
+      minDeltaEntry = pos;
+      minSize = array_n(pos->vector);
+    }
+    pos = pos->next;
+    num++;
+  }
+
+  /* num = the number entries in the slot */
+  if (num < table->maxChainLength) {
+    new_ = ALLOC(ImgCacheEntry_t, 1);
+    new_->vector = delta;
+    new_->constraint = constraint;
+    new_->result = result;
+    new_->next = table->slot[slot];
+    table->slot[slot] = new_;
+    table->entries += 1.0;
+  } else if (entry != NIL(ImgCacheEntry_t)) {
+    CacheDestroyEntry(entry, FALSE);
+    entry->vector = delta;
+    entry->constraint = constraint;
+    entry->result = result;
+  } else { /* all entries are full of latest entries */
+    if (0) { /* Rehash */
+      unsigned int	i, new_num_slot, new_slot, old_num_slot;
+      ImgCacheEntry_t	*next;
+      ImgCacheEntry_t	**old_bin;
+
+      old_num_slot = table->nSlots;
+      old_bin = table->slot;
+      new_num_slot = old_num_slot * 2;
+      table->slot = ALLOC(ImgCacheEntry_t *, new_num_slot);
+      if (!table->slot) {
+	printf("VI_insert_table:new_slots");
+	exit(-1);
+      }
+      memset(table->slot, 0, sizeof(ImgCacheEntry_t *) * new_num_slot);
+      table->nSlots = new_num_slot;
+
+      for (i = 0; i < old_num_slot; i++) {
+	pos = old_bin[i];
+	while (pos != NIL(ImgCacheEntry_t)) {
+	  next = pos->next;
+	  new_slot = VectorHash(table, pos->vector, pos->constraint);
+	  pos->next = table->slot[new_slot];
+	  table->slot[new_slot] = pos;
+	  pos = next;
+	}
+      }
+
+      new_slot = VectorHash(table, delta, constraint);
+      new_ = ALLOC(ImgCacheEntry_t, 1);
+      new_->vector = delta;
+      new_->constraint = constraint;
+      new_->result = result;
+      new_->next = table->slot[slot];
+      table->slot[slot] = new_;
+      table->entries += 1.0;
+    } else {
+      CacheDestroyEntry(minDeltaEntry, FALSE);
+      minDeltaEntry->vector = delta;
+      minDeltaEntry->constraint = constraint;
+      minDeltaEntry->result = result;
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Flushes all cache entries.]
+
+  Description [Flushes all cache entries.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgFlushCache(ImgCacheTable_t *table)
+{
+  unsigned int		i;
+  ImgCacheEntry_t	*entry, *next;
+  array_t		*vector;
+  bdd_t			*result;
+  st_generator		*stGen;
+  ImgCacheStKey_t	*key;
+
+  if (!table)
+    return;
+
+  if (table->stTable) {
+    if (table->preImgFlag || table->useConstraint) {
+      st_foreach_item(table->stTable, stGen, &key, &result) {
+	st_delete(table->stTable, &key, NIL(char *));
+	ImgVectorFree(key->vector);
+	mdd_free(key->constraint);
+	FREE(key);
+	mdd_free(result);
+      }
+    } else {
+      st_foreach_item(table->stTable, stGen, &vector, &result) {
+	st_delete(table->stTable, &vector, NIL(char *));
+	ImgVectorFree(vector);
+	mdd_free(result);
+      }
+    }
+  } else {
+    for (i = 0; i < table->nSlots; i++) {
+      entry = table->slot[i];
+      while (entry != NIL(ImgCacheEntry_t)) {
+	next = entry->next;
+	CacheDestroyEntry(entry, TRUE);
+	entry = next;
+      }
+      table->slot[i] = NIL(ImgCacheEntry_t);
+    }
+  }
+  table->entries = 0.0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints cache statistics for transition function method.]
+
+  Description [Prints cache statistics for transition function method.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+ImgPrintCacheStatistics(ImgCacheTable_t *cache)
+{
+  if (cache->preImgFlag)
+    fprintf(vis_stdout, "** cache statistics (preImg) **\n");
+  else
+    fprintf(vis_stdout, "** cache statistics (img) **\n");
+  fprintf(vis_stdout, "# insertions = %g\n", cache->inserts);
+  if (cache->inserts != 0.0) {
+    fprintf(vis_stdout, "# lookups = %g\n", cache->lookups);
+    fprintf(vis_stdout, "# hits = %g (%.2f%%)\n", cache->hits,
+	cache->hits / cache->lookups * 100.0);
+    fprintf(vis_stdout, "# misses = %g (%.2f%%)\n",
+	cache->lookups - cache->hits,
+	(cache->lookups - cache->hits) / cache->lookups * 100.0);
+    fprintf(vis_stdout, "# entries = %g\n", cache->entries);
+    if (!cache->stTable) {
+      fprintf(vis_stdout, "# slots = %d\n", cache->nSlots);
+      fprintf(vis_stdout, "maxChainLength = %d\n", cache->maxChainLength);
+    }
+  }
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Destroys a cache entry.]
+
+  Description [Destroys a cache entry.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+CacheDestroyEntry(ImgCacheEntry_t *entry, boolean freeEntry)
+{
+  ImgVectorFree(entry->vector);
+  mdd_free(entry->result);
+  if (entry->constraint)
+    mdd_free(entry->constraint);
+  if (freeEntry)
+    FREE(entry);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns hash value of a vector.]
+
+  Description [Returns hash value of a vector.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+VectorHash(ImgCacheTable_t *table, array_t *delta, bdd_t *constraint)
+{
+  unsigned long		value;
+  ImgComponent_t	*comp;
+  bdd_t			*func;
+  int			i;
+
+  value = array_n(delta);
+  if (constraint)
+    value += (unsigned long)bdd_pointer(constraint) & ~01;
+  for (i = 0; i < array_n(delta); i++) {
+    comp = array_fetch(ImgComponent_t *, delta, i);
+    func = comp->func;
+    value += (unsigned long)bdd_pointer(func) & ~01;
+  }
+  return((int)(value % table->nSlots));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns hash value of a vector for st_table.]
+
+  Description [Returns hash value of a vector for st_table.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+VectorStHash(char *key, int modulus)
+{
+  unsigned long		value;
+  array_t		*delta;
+  ImgComponent_t	*comp;
+  bdd_t			*func;
+  int			i;
+
+  delta = (array_t *)key;
+  value = array_n(delta);
+
+  for (i = 0; i < array_n(delta); i++) {
+    comp = array_fetch(ImgComponent_t *, delta, i);
+    func = comp->func;
+    value += (unsigned long)bdd_pointer(func) & ~01;
+  }
+  return((int)(value % modulus));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns hash value of a key for st_table.]
+
+  Description [Returns hash value of a key for st_table.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+KeyStHash(char *key, int modulus)
+{
+  ImgCacheStKey_t	*stKey;
+  unsigned long		value;
+  array_t		*delta;
+  ImgComponent_t	*comp;
+  bdd_t			*func;
+  int			i;
+
+  stKey = (ImgCacheStKey_t *)key;
+  delta = stKey->vector;
+  value = array_n(delta);
+  if (stKey->constraint)
+    value += (unsigned long)bdd_pointer(stKey->constraint) & ~01;
+
+  for (i = 0; i < array_n(delta); i++) {
+    comp = array_fetch(ImgComponent_t *, delta, i);
+    func = comp->func;
+    value += (unsigned long)bdd_pointer(func) & ~01;
+  }
+  return((int)(value % modulus));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compares two vectors.]
+
+  Description [Compares two vectors.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+VectorCompare(array_t *vector1, array_t *vector2)
+{
+  ImgComponent_t	*comp1, *comp2;
+  int			i, index1, index2;
+
+  if (array_n(vector1) != array_n(vector2))
+    return(1);
+
+  for (i = 0; i < array_n(vector1); i++) {
+    comp1 = array_fetch(ImgComponent_t *, vector1, i);
+    comp2 = array_fetch(ImgComponent_t *, vector2, i);
+    index1 = (int)bdd_top_var_id(comp1->var);
+    index2 = (int)bdd_top_var_id(comp2->var);
+    if (index1 != index2)
+      return(1);
+    if (!mdd_equal(comp1->func, comp2->func))
+      return(1);
+  }
+  SubstituteVector = NIL(array_t);
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compares two vectors considering substitution.]
+
+  Description [Compares two vectors considering substitution.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+VectorSortCompare(array_t *vector1, array_t *vector2)
+{
+  ImgComponent_t	*comp1, *comp2;
+  int			i, index1, index2;
+  int			*ptr1, *ptr2, *regularPtr1, *regularPtr2;
+
+  if (array_n(vector1) != array_n(vector2))
+    return(1);
+
+  SubstituteVector = NIL(array_t);
+  for (i = 0; i < array_n(vector1); i++) {
+    comp1 = array_fetch(ImgComponent_t *, vector1, i);
+    comp2 = array_fetch(ImgComponent_t *, vector2, i);
+    index1 = (int)bdd_top_var_id(comp1->var);
+    index2 = (int)bdd_top_var_id(comp2->var);
+    if (index1 != index2)
+      SubstituteVector = vector2;
+    ptr1 = (int *)bdd_pointer(comp1->func);
+    ptr2 = (int *)bdd_pointer(comp2->func);
+    regularPtr1 = (int *)((unsigned long)ptr1 & ~01);
+    regularPtr2 = (int *)((unsigned long)ptr2 & ~01);
+    if (regularPtr1 == regularPtr2) {
+      if (ptr1 != ptr2) {
+	if (comp1->intermediate || comp2->intermediate)
+	  return(1);
+	SubstituteVector = vector2;
+      }
+    } else
+      return(1);
+  }
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compares two vectors considering substitution.]
+
+  Description [Compares two vectors considering substitution.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+VectorSortCompareWithConstraint(array_t *vector1, array_t *vector2)
+{
+  ImgComponent_t	*comp1, *comp2;
+  int			i, index1, index2;
+
+  if (array_n(vector1) != array_n(vector2))
+    return(1);
+
+  SubstituteVector = NIL(array_t);
+  for (i = 0; i < array_n(vector1); i++) {
+    comp1 = array_fetch(ImgComponent_t *, vector1, i);
+    comp2 = array_fetch(ImgComponent_t *, vector2, i);
+    index1 = (int)bdd_top_var_id(comp1->var);
+    index2 = (int)bdd_top_var_id(comp2->var);
+    if (index1 != index2)
+      SubstituteVector = vector2;
+    if (!mdd_equal(comp1->func, comp2->func))
+      return(1);
+  }
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compares two keys.]
+
+  Description [Compares two keys.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+ImageKeyCompare(ImgCacheStKey_t *key1, ImgCacheStKey_t *key2)
+{
+  ComplementFlag = 0;
+  if (mdd_equal(key1->constraint, key2->constraint)) {
+    if (VectorCompare(key1->vector, key2->vector))
+      return(1);
+  } else
+    return(1);
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compares two keys considering substitution.]
+
+  Description [Compares two keys considering substitution.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+ImageKeySortCompare(ImgCacheStKey_t *key1, ImgCacheStKey_t *key2)
+{
+  ComplementFlag = 0;
+  if (mdd_equal(key1->constraint, key2->constraint)) {
+    if (VectorSortCompareWithConstraint(key1->vector, key2->vector))
+      return(1);
+  } else
+    return(1);
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compares two keys for preimage.]
+
+  Description [Compares two keys for preimage.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+PreImageKeyCompare(ImgCacheStKey_t *key1, ImgCacheStKey_t *key2)
+{
+  unsigned long	ptr1, ptr2;
+
+  ptr1 = (unsigned long)bdd_pointer(key1->constraint);
+  ptr2 = (unsigned long)bdd_pointer(key2->constraint);
+  if ((ComplementFlag = (int) (ptr1 ^ ptr2)) <= 01) {
+    if (VectorCompare(key1->vector, key2->vector))
+      return(1);
+  } else
+    return(1);
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Substitutes a cache result.]
+
+  Description [Substitutes a cache result.]
+
+  SideEffects []
+
+******************************************************************************/
+static mdd_t *
+SubstituteCacheResult(ImgTfmInfo_t *info, array_t *keyVector,
+		      array_t *cacheVector,
+			mdd_t *result)
+{
+  mdd_t			*newResult;
+  ImgComponent_t	*comp1, *comp2;
+  int			*ptr1, *ptr2;
+  int			i, id1, id2;
+  mdd_t			*var, *func;
+  array_t		*varArray, *funcArray;
+
+  varArray = array_alloc(mdd_t *, 0);
+  funcArray = array_alloc(mdd_t *, 0);
+
+  for (i = 0; i < array_n(keyVector); i++) {
+    comp1 = array_fetch(ImgComponent_t *, keyVector, i);
+    comp2 = array_fetch(ImgComponent_t *, cacheVector, i);
+    ptr1 = (int *)bdd_pointer(comp1->func);
+    ptr2 = (int *)bdd_pointer(comp2->func);
+    id1 = (int)bdd_top_var_id(comp1->var);
+    id2 = (int)bdd_top_var_id(comp2->var);
+    if (id1 == id2) {
+      if (ptr1 != ptr2) {
+	array_insert_last(mdd_t *, varArray, comp2->var);
+	func = mdd_not(comp1->var);
+	array_insert_last(mdd_t *, funcArray, func);
+      }
+    } else {
+      if (ptr1 == ptr2) {
+	array_insert_last(mdd_t *, varArray, comp2->var);
+	func = mdd_dup(comp1->var);
+	array_insert_last(mdd_t *, funcArray, func);
+      } else {
+	array_insert_last(mdd_t *, varArray, comp2->var);
+	func = mdd_not(comp1->var);
+	array_insert_last(mdd_t *, funcArray, func);
+      }
+    }
+  }
+  if (array_n(varArray) == 1) {
+    var = array_fetch(mdd_t *, varArray, 0);
+    func = array_fetch(mdd_t *, funcArray, 0);
+    newResult = bdd_compose(result, var, func);
+  } else if (bdd_get_package_name() == CUDD)
+    newResult = bdd_vector_compose(result, varArray, funcArray);
+  else
+    newResult = SubstituteCacheResultRecur(result, varArray, funcArray, 0);
+  array_free(varArray);
+  mdd_array_free(funcArray);
+  return(newResult);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Recursive procedure of SubstituteCacheResult.]
+
+  Description [Recursive procedure of SubstituteCacheResult.]
+
+  SideEffects []
+
+******************************************************************************/
+static mdd_t *
+SubstituteCacheResultRecur(mdd_t *result, array_t *varArray, array_t *funcArray,
+			   int pos)
+{
+  mdd_t	*var, *varNot, *func;
+  mdd_t	*resultT, *resultE, *newResultT, *newResultE, *newResult;
+
+  if (pos > array_n(varArray))
+    return(mdd_dup(result));
+
+  var = array_fetch(mdd_t *, varArray, pos);
+  func = array_fetch(mdd_t *, funcArray, pos);
+  varNot = mdd_not(var);
+  resultT = bdd_cofactor(result, var);
+  resultE = bdd_cofactor(result, varNot);
+  mdd_free(varNot);
+  newResultT = SubstituteCacheResultRecur(resultT, varArray, funcArray,
+					  pos + 1);
+  mdd_free(resultT);
+  newResultE = SubstituteCacheResultRecur(resultE, varArray, funcArray,
+					  pos + 1);
+  mdd_free(resultE);
+  newResult = bdd_ite(func, newResultT, newResultE, 1, 1, 1);
+  mdd_free(newResultT);
+  mdd_free(newResultE);
+  return(newResult);
+}
Index: vis_dev/vis-2.3/src/img/imgTfmFwd.c
===================================================================
--- vis_dev/vis-2.3/src/img/imgTfmFwd.c	(revision 14)
+++ vis_dev/vis-2.3/src/img/imgTfmFwd.c	(revision 14)
@@ -0,0 +1,3376 @@
+/**CFile***********************************************************************
+
+  FileName    [imgTfmFwd.c]
+
+  PackageName [img]
+
+  Synopsis    [Routines for image computation using transition function method.]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [In-Ho Moon]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF COLORADO BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  COLORADO HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF COLORADO SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF COLORADO HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+#include "imgInt.h"
+
+static char rcsid[] UNUSED = "$Id: imgTfmFwd.c,v 1.37 2005/04/22 19:45:46 jinh Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static mdd_t * ImageByInputSplit(ImgTfmInfo_t *info, array_t *vector, mdd_t *constraint, mdd_t *from, array_t *relationArray, mdd_t *cofactorCube, mdd_t *abstractCube, int splitMethod, int turnDepth, int depth);
+static mdd_t * ImageByStaticInputSplit(ImgTfmInfo_t *info, array_t *vector, mdd_t *from, array_t *relationArray, int turnDepth, int depth);
+static mdd_t * ImageByOutputSplit(ImgTfmInfo_t *info, array_t *vector, mdd_t *constraint, int depth);
+static int ImageDecomposeAndChooseSplitVar(ImgTfmInfo_t *info, array_t *vector, mdd_t *from, int splitMethod, int split, int piSplitFlag, array_t *vectorArray, array_t *varArray, mdd_t **singles, array_t *relationArray, array_t **newRelationArray, mdd_t **cofactorCube, mdd_t **abstractCube);
+static mdd_t * ImageFast2(ImgTfmInfo_t *info, array_t *vector);
+static int FindDecomposableVariable(ImgTfmInfo_t *info, array_t *vector);
+static int TfmCheckImageValidity(ImgTfmInfo_t *info, mdd_t *image);
+static void FindIntermediateSupport(array_t *vector, ImgComponent_t *comp, int nVars, int nGroups, int *stack, char *stackFlag, int *funcGroup, int *size, char *intermediateVarFlag, int *intermediateVarFuncMap);
+static void PrintVectorDecomposition(ImgTfmInfo_t *info, array_t *vectorArray, array_t *varArray);
+static int CheckIfValidSplitOrGetNew(ImgTfmInfo_t *info, int split, array_t *vector, array_t *relationArray, mdd_t *from);
+static int ChooseInputSplittingVariable(ImgTfmInfo_t *info, array_t *vector, mdd_t *from, int splitMethod, int decompose, int piSplitFlag, int *varOccur);
+static int ChooseOutputSplittingVariable(ImgTfmInfo_t *info, array_t *vector, int splitMethod);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes an image with transition function method.]
+
+  Description [Computes an image with transition function method.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+ImgTfmImage(ImgTfmInfo_t *info, mdd_t *from)
+{
+  mdd_t		*res, *r, *cube, *newFrom, *one;
+  array_t	*newVector, *depVector;
+  int		splitMethod, turnDepth;
+  mdd_t		*refResult;
+  array_t	*relationArray, *newRelationArray, *tmpRelationArray;
+  int		eliminateDepend;
+  int		partial, saveUseConstraint;
+  long		size1, size2;
+  mdd_t		*cofactorCube, *abstractCube;
+  int		i, maxDepth, size, nDependVars;
+
+  info->maxIntermediateSize = 0;
+  if (info->eliminateDepend == 1 ||
+      (info->eliminateDepend == 2 && info->nPrevEliminatedFwd > 0)) {
+    eliminateDepend = 1;
+  } else
+    eliminateDepend = 0;
+
+  saveUseConstraint = info->useConstraint;
+  if (info->buildTR) {
+    if (eliminateDepend == 0 &&
+	info->option->splitMethod == 3 &&
+	info->option->splitMaxDepth < 0 &&
+	info->option->buildPartialTR == FALSE &&
+	info->option->rangeComp == 0 &&
+	info->option->findEssential == FALSE) {
+      r = ImgBddLinearAndSmooth(info->manager, from,
+		      info->fwdClusteredRelationArray,
+		      info->fwdArraySmoothVarBddArray,
+		      info->fwdSmoothVarCubeArray,
+		      info->option->verbosity);
+      res = ImgSubstitute(r, info->functionData, Img_R2D_c);
+      mdd_free(r);
+      return(res);
+    }
+    relationArray = mdd_array_duplicate(info->fwdClusteredRelationArray);
+  } else
+    relationArray = NIL(array_t);
+  if (info->useConstraint == 1 ||
+      (info->useConstraint == 2 &&
+       info->nImageComps == info->option->rangeTryThreshold)) {
+    if (info->buildTR == 2) {
+      newVector = NIL(array_t);
+      cube = mdd_one(info->manager);
+      if (eliminateDepend) {
+	newFrom = ImgTrmEliminateDependVars(info->functionData, relationArray,
+					    from, NIL(mdd_t *), &nDependVars);
+	if (nDependVars) {
+	  if (info->option->verbosity > 0)
+	    (void)fprintf(vis_stdout, "Eliminated %d vars.\n", nDependVars);
+	  info->averageFoundDependVars = (info->averageFoundDependVars *
+		    (float)info->nFoundDependVars + (float)nDependVars) /
+		    (float)(info->nFoundDependVars + 1);
+	  info->nFoundDependVars++;
+	}
+
+	info->nPrevEliminatedFwd = nDependVars;
+      } else
+	newFrom = from;
+      cofactorCube = NIL(mdd_t);
+      abstractCube = NIL(mdd_t);
+    } else {
+      newVector = ImgVectorCopy(info, info->vector);
+      cube = mdd_one(info->manager);
+      if (eliminateDepend) {
+	newFrom = ImgTfmEliminateDependVars(info, newVector, relationArray,
+					    from, NIL(array_t *), NIL(mdd_t *));
+      } else
+	newFrom = from;
+      if (info->option->delayedSplit && relationArray && info->buildTR != 2) {
+	cofactorCube = mdd_one(info->manager);
+	abstractCube = mdd_one(info->manager);
+      } else {
+	cofactorCube = NIL(mdd_t);
+	abstractCube = NIL(mdd_t);
+      }
+    }
+  } else {
+    if (eliminateDepend) {
+      depVector = ImgVectorCopy(info, info->vector);
+      newFrom = ImgTfmEliminateDependVars(info, depVector, relationArray, from,
+					  NIL(array_t *), NIL(mdd_t *));
+      /* constrain delta w.r.t. from here */
+      if (info->option->delayedSplit && relationArray && info->buildTR != 2) {
+	ImgVectorConstrain(info, depVector, newFrom, relationArray,
+			   &newVector, &cube, &newRelationArray, &cofactorCube,
+			   &abstractCube, FALSE);
+      } else if (relationArray) {
+	ImgVectorConstrain(info, depVector, newFrom, relationArray,
+			   &newVector, &cube, NIL(array_t *), &cofactorCube,
+			   &abstractCube, FALSE);
+	newRelationArray = NIL(array_t);
+      } else {
+	ImgVectorConstrain(info, depVector, newFrom, NIL(array_t),
+			   &newVector, &cube, NIL(array_t *), NIL(mdd_t *),
+			   NIL(mdd_t *), FALSE);
+	newRelationArray = NIL(array_t);
+	cofactorCube = NIL(mdd_t);
+	abstractCube = NIL(mdd_t);
+      }
+
+      if (info->useConstraint == 2) {
+	size1 = ImgVectorBddSize(depVector);
+	size2 = ImgVectorBddSize(newVector);
+	if (info->option->rangeCheckReorder) {
+	  bdd_reorder(info->manager);
+	  size1 = ImgVectorBddSize(depVector);
+	  size2 = ImgVectorBddSize(newVector);
+	}
+	if (size2 > size1 * info->option->rangeThreshold) { /* cancel */
+	  if (info->option->verbosity)
+	    fprintf(vis_stdout, "** tfm info: canceled range computation.\n");
+	  info->useConstraint = 1;
+	  ImgVectorFree(newVector);
+	  newVector = depVector;
+	  mdd_free(cube);
+	  cube = mdd_one(info->manager);
+	  if (newRelationArray && newRelationArray != relationArray)
+	    mdd_array_free(newRelationArray);
+	  if (cofactorCube) {
+	    mdd_free(cofactorCube);
+	    cofactorCube = mdd_one(info->manager);
+	  }
+	  if (abstractCube) {
+	    mdd_free(abstractCube);
+	    abstractCube = mdd_one(info->manager);
+	  }
+	  info->nImageComps++;
+	} else {
+	  info->useConstraint = 0;
+	  info->nImageComps = 0;
+	  info->nRangeComps++;
+	}
+      }
+      if (info->useConstraint == 0)
+	ImgVectorFree(depVector);
+    } else {
+      newFrom = from;
+      /* constrain delta w.r.t. from here */
+      if (info->option->delayedSplit && relationArray && info->buildTR != 2) {
+	ImgVectorConstrain(info, info->vector, newFrom, relationArray,
+			   &newVector, &cube, &newRelationArray, &cofactorCube,
+			   &abstractCube, FALSE);
+	if (info->option->debug) {
+	  refResult = ImgImageByHybrid(info, newVector, NIL(mdd_t));
+	  res = ImgImageByHybridWithStaticSplit(info, NIL(array_t), NIL(mdd_t),
+						newRelationArray,
+						cofactorCube, abstractCube);
+	  assert(mdd_equal(refResult, res));
+	  mdd_free(refResult);
+	  mdd_free(res);
+	}
+      } else if (relationArray) {
+	ImgVectorConstrain(info, info->vector, newFrom, relationArray,
+			   &newVector, &cube, NIL(array_t *), &cofactorCube,
+			   &abstractCube, FALSE);
+	newRelationArray = NIL(array_t);
+      } else {
+	ImgVectorConstrain(info, info->vector, newFrom, NIL(array_t),
+			   &newVector, &cube, NIL(array_t *), NIL(mdd_t *),
+			   NIL(mdd_t *), FALSE);
+	newRelationArray = NIL(array_t);
+	cofactorCube = NIL(mdd_t);
+	abstractCube = NIL(mdd_t);
+      }
+
+      if (info->useConstraint == 2) {
+	size1 = ImgVectorBddSize(info->vector);
+	size2 = ImgVectorBddSize(newVector);
+	if (info->option->rangeCheckReorder) {
+	  bdd_reorder(info->manager);
+	  size1 = ImgVectorBddSize(info->vector);
+	  size2 = ImgVectorBddSize(newVector);
+	}
+	if (size2 > size1 * info->option->rangeThreshold) { /* cancel */
+	  if (info->option->verbosity)
+	    fprintf(vis_stdout, "** tfm info: canceled range computation.\n");
+	  info->useConstraint = 1;
+	  ImgVectorFree(newVector);
+	  newVector = info->vector;
+	  mdd_free(cube);
+	  cube = mdd_one(info->manager);
+	  if (newRelationArray && newRelationArray != relationArray)
+	    mdd_array_free(newRelationArray);
+	  if (cofactorCube) {
+	    mdd_free(cofactorCube);
+	    cofactorCube = mdd_one(info->manager);
+	  }
+	  if (abstractCube) {
+	    mdd_free(abstractCube);
+	    abstractCube = mdd_one(info->manager);
+	  }
+	  info->nImageComps++;
+	} else {
+	  info->useConstraint = 0;
+	  info->nImageComps = 0;
+	  info->nRangeComps++;
+	}
+      }
+    }
+    if (info->useConstraint == 0 && relationArray) {
+      if (!newRelationArray) {
+	if (bdd_is_tautology(cofactorCube, 1) &&
+	    bdd_is_tautology(abstractCube, 1)) {
+	  newRelationArray = ImgGetConstrainedRelationArray(info, relationArray,
+							    newFrom);
+	} else {
+	  tmpRelationArray = ImgGetConstrainedRelationArray(info, relationArray,
+							    newFrom);
+	  newRelationArray = ImgGetCofactoredAbstractedRelationArray(
+					info->manager, tmpRelationArray,
+					cofactorCube, abstractCube);
+	  if (info->option->debug) {
+	    array_t	*tmpVector;
+
+	    tmpVector = ImgGetConstrainedVector(info, info->vector, newFrom);
+	    if (info->option->checkEquivalence) {
+	      assert(ImgCheckEquivalence(info, tmpVector, tmpRelationArray,
+					 NIL(mdd_t), NIL(mdd_t), 0));
+	    }
+	    refResult = ImgImageByHybrid(info, tmpVector, NIL(mdd_t));
+	    ImgVectorFree(tmpVector);
+	    res = ImgImageByHybridWithStaticSplit(info, NIL(array_t),
+						  NIL(mdd_t),
+						  tmpRelationArray,
+						  NIL(mdd_t), NIL(mdd_t));
+	    assert(mdd_equal(refResult, res));
+	    mdd_free(refResult);
+	    mdd_free(res);
+	  }
+	  mdd_array_free(tmpRelationArray);
+	}
+	mdd_free(cofactorCube);
+	cofactorCube = NIL(mdd_t);
+	mdd_free(abstractCube);
+	abstractCube = NIL(mdd_t);
+	if (info->option->debug) {
+	  refResult = ImgImageByHybrid(info, newVector, NIL(mdd_t));
+	  res = ImgImageByHybridWithStaticSplit(info, NIL(array_t), NIL(mdd_t),
+						newRelationArray,
+						NIL(mdd_t), NIL(mdd_t));
+	  assert(mdd_equal(refResult, res));
+	  mdd_free(refResult);
+	  mdd_free(res);
+
+	  if (info->nIntermediateVars) {
+	    mdd_t	*tmp;
+
+	    refResult = ImgImageByHybrid(info, info->vector, newFrom);
+	    res = ImgImageByHybridWithStaticSplit(info, NIL(array_t), newFrom,
+						  relationArray,
+						  NIL(mdd_t), NIL(mdd_t));
+	    assert(mdd_equal(refResult, res));
+	    mdd_free(res);
+	    tmp = ImgImageByHybrid(info, newVector, NIL(mdd_t));
+	    res = mdd_and(tmp, cube, 1, 1);
+	    if (info->option->verbosity) {
+	      size = bdd_size(res);
+	      if (size > info->maxIntermediateSize)
+		info->maxIntermediateSize = size;
+	      if (info->option->printBddSize) {
+		fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
+			bdd_size(tmp), bdd_size(cube), size);
+	      }
+	    }
+	    mdd_free(tmp);
+	    assert(mdd_equal(refResult, res));
+	    mdd_free(refResult);
+	    mdd_free(res);
+	  }
+	}
+      }
+      if (relationArray != newRelationArray) {
+	mdd_array_free(relationArray);
+	relationArray = newRelationArray;
+      }
+    }
+    if (info->option->checkEquivalence) {
+      assert(ImgCheckEquivalence(info, newVector, newRelationArray,
+				  NIL(mdd_t), NIL(mdd_t), 0));
+    }
+  }
+  partial = 0;
+  one = mdd_one(info->manager);
+  splitMethod = info->option->splitMethod;
+  if (splitMethod == 0) {
+    r = ImageByInputSplit(info, newVector, one, newFrom, NIL(array_t),
+			  NIL(mdd_t), NIL(mdd_t), 0, 0, 0);
+  } else if (splitMethod == 1)
+    r = ImageByOutputSplit(info, newVector, one, 0);
+  else {
+    if (info->option->splitMethod == 0)
+      turnDepth = info->nVars + 1;
+    else
+      turnDepth = info->option->turnDepth;
+    if (turnDepth == 0) {
+      if (splitMethod == 2)
+	r = ImageByOutputSplit(info, newVector, one, 0);
+      else {
+	if (info->useConstraint && info->buildTR == 2) {
+	  if (info->buildPartialTR) {
+	    r = ImgImageByHybridWithStaticSplit(info, newVector, newFrom,
+						relationArray,
+						NIL(mdd_t), NIL(mdd_t));
+	  } else {
+	    r = ImgImageByHybridWithStaticSplit(info, NIL(array_t), newFrom,
+						relationArray,
+						NIL(mdd_t), NIL(mdd_t));
+	  }
+	} else
+	  r = ImgImageByHybrid(info, newVector, newFrom);
+      }
+    } else if (splitMethod == 2) {
+      r = ImageByInputSplit(info, newVector, one, newFrom, NIL(array_t),
+				NIL(mdd_t), NIL(mdd_t),
+				splitMethod, turnDepth, 0);
+    } else {
+      if (info->useConstraint) {
+	if (info->buildTR) {
+	  if (info->buildTR == 2) {
+	    if (info->buildPartialTR) {
+	      r = ImageByStaticInputSplit(info, newVector, newFrom,
+					  relationArray, turnDepth, 0);
+	      partial = 1;
+	    } else {
+	      r = ImageByStaticInputSplit(info, NIL(array_t), newFrom,
+					  relationArray, turnDepth, 0);
+	    }
+	  } else if (info->option->delayedSplit) {
+	    r = ImageByInputSplit(info, newVector, one, newFrom, relationArray,
+				  cofactorCube, abstractCube,
+				  splitMethod, turnDepth, 0);
+	  } else {
+	    r = ImageByInputSplit(info, newVector, one, newFrom, relationArray,
+				  NIL(mdd_t), NIL(mdd_t),
+				  splitMethod, turnDepth, 0);
+	  }
+	} else {
+	  r = ImageByInputSplit(info, newVector, one, newFrom, NIL(array_t),
+				NIL(mdd_t), NIL(mdd_t),
+				splitMethod, turnDepth, 0);
+	}
+      } else if (info->buildTR == 1 && info->option->delayedSplit) {
+	r = ImageByInputSplit(info, newVector, one, NIL(mdd_t), relationArray,
+				cofactorCube, abstractCube,
+				splitMethod, turnDepth, 0);
+      } else {
+	r = ImageByInputSplit(info, newVector, one, NIL(mdd_t), relationArray,
+				NIL(mdd_t), NIL(mdd_t),
+				splitMethod, turnDepth, 0);
+      }
+    }
+  }
+  info->useConstraint = saveUseConstraint;
+  if (relationArray &&
+      !(info->option->debug && (partial || info->buildTR == 2))) {
+    mdd_array_free(relationArray);
+  }
+  if (info->imgCache && info->option->autoFlushCache == 1)
+    ImgFlushCache(info->imgCache);
+  mdd_free(one);
+  if (cofactorCube)
+    mdd_free(cofactorCube);
+  if (abstractCube)
+    mdd_free(abstractCube);
+  if (newFrom && newFrom != from)
+    mdd_free(newFrom);
+  res = bdd_and(r, cube, 1, 1);
+  if (info->option->verbosity) {
+    size = bdd_size(res);
+    if (size > info->maxIntermediateSize)
+      info->maxIntermediateSize = size;
+    if (info->option->printBddSize) {
+      fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
+	      bdd_size(r), bdd_size(cube), size);
+    }
+  }
+  mdd_free(r);
+  mdd_free(cube);
+  if (newVector != info->vector)
+    ImgVectorFree(newVector);
+
+  if (info->option->debug) {
+    if (info->buildTR == 2) {
+      refResult = ImgImageByHybridWithStaticSplit(info, NIL(array_t), from,
+						  relationArray,
+						  NIL(mdd_t), NIL(mdd_t));
+      mdd_array_free(relationArray);
+    } else {
+      if (partial) {
+	refResult = ImgImageByHybrid(info, info->fullVector, from);
+	assert(mdd_equal(refResult, res));
+	mdd_free(refResult);
+	refResult = ImgImageByHybridWithStaticSplit(info, info->vector, from,
+						    relationArray,
+						    NIL(mdd_t), NIL(mdd_t));
+	mdd_array_free(relationArray);
+      } else
+	refResult = ImgImageByHybrid(info, info->vector, from);
+    }
+    assert(mdd_equal(refResult, res));
+    mdd_free(refResult);
+  }
+  if (info->option->findEssential)
+    info->lastFoundEssentialDepth = info->foundEssentialDepth;
+  if (info->option->printEssential == 2) {
+    maxDepth = info->maxDepth < IMG_TF_MAX_PRINT_DEPTH ?
+		info->maxDepth : IMG_TF_MAX_PRINT_DEPTH;
+    fprintf(vis_stdout, "foundEssential:");
+    for (i = 0; i < maxDepth; i++)
+      fprintf(vis_stdout, " [%d]%d", i, info->foundEssentials[i]);
+    fprintf(vis_stdout, "\n");
+  }
+  if (info->option->verbosity) {
+    fprintf(vis_stdout, "** tfm info: max intermediate BDD size = %d\n",
+	    info->maxIntermediateSize);
+  }
+  if (info->option->debug)
+    assert(TfmCheckImageValidity(info, res));
+  return(res);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Chooses splitting variables for static splitting.]
+
+  Description [Chooses splitting variables for static splitting.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+ImgChooseTrSplitVar(ImgTfmInfo_t *info, array_t *vector,
+		    array_t *relationArray, int trSplitMethod, int piSplitFlag)
+{
+  int			i, j, nVars;
+  ImgComponent_t	*comp;
+  char			*support;
+  int			*varCost, bestCost = 0;
+  int			id, split;
+  mdd_t			*var, *relation;
+
+  nVars = info->nVars;
+  varCost = ALLOC(int, nVars);
+  memset(varCost, 0, sizeof(int) * nVars);
+
+  if (trSplitMethod == 0) {
+    if (vector) {
+      for (i = 0; i < array_n(vector); i++) {
+	comp = array_fetch(ImgComponent_t *, vector, i);
+	support = comp->support;
+	for (j = 0; j < nVars; j++) {
+	  if (support[j])
+	    varCost[j]++;
+	}
+      }
+    }
+    comp = ImgComponentAlloc(info);
+    support = comp->support;
+    for (i = 0; i < array_n(relationArray); i++) {
+      relation = array_fetch(mdd_t *, relationArray, i);
+      comp->func = relation;
+      ImgSupportClear(info, comp->support);
+      ImgComponentGetSupport(comp);
+      for (j = 0; j < nVars; j++) {
+	if (support[j])
+	  varCost[j]++;
+      }
+    }
+    comp->func = NIL(mdd_t);
+    ImgComponentFree(comp);
+  } else {
+    for (i = 0; i < array_n(info->domainVarBddArray); i++) {
+      var = array_fetch(mdd_t *, info->domainVarBddArray, i);
+      id = (int)bdd_top_var_id(var);
+      if (vector) {
+	for (j = 0; j < array_n(vector); j++) {
+	  comp = array_fetch(ImgComponent_t *, vector, j);
+	  varCost[id] += bdd_estimate_cofactor(comp->func, var, 1);
+	  varCost[id] += bdd_estimate_cofactor(comp->func, var, 0);
+	}
+      }
+      for (j = 0; j < array_n(relationArray); j++) {
+	relation = array_fetch(mdd_t *, relationArray, j);
+	varCost[id] += bdd_estimate_cofactor(relation, var, 1);
+	varCost[id] += bdd_estimate_cofactor(relation, var, 0);
+      }
+      varCost[id] = IMG_TF_MAX_INT - varCost[id];
+    }
+  }
+
+  split = -1;
+  for (i = 0; i < nVars; i++) {
+    if (varCost[i] == 0)
+      continue;
+    if (!piSplitFlag) {
+      if (st_lookup(info->quantifyVarsTable, (char *)(long)i, NIL(char *)))
+	continue;
+    }
+    if (st_lookup(info->rangeVarsTable, (char *)(long)i, NIL(char *)))
+      continue;
+    if (info->intermediateVarsTable &&
+	st_lookup(info->intermediateVarsTable, (char *)(long)i, NIL(char *))) {
+      continue;
+    }
+
+    if (split == -1 || varCost[i] > bestCost) {
+      bestCost = varCost[i];
+      split = i;
+    }
+  }
+  FREE(varCost);
+  if (split == -1)
+    return(NIL(mdd_t));
+  var = bdd_var_with_index(info->manager, split);
+  return(var);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes an image by input splitting.]
+
+  Description [Computes an image by input splitting.]
+
+  SideEffects []
+
+******************************************************************************/
+static mdd_t *
+ImageByInputSplit(ImgTfmInfo_t *info, array_t *vector, mdd_t *constraint,
+		  mdd_t *from, array_t *relationArray, mdd_t *cofactorCube,
+		  mdd_t *abstractCube, int splitMethod, int turnDepth,
+		  int depth)
+{
+  array_t		*newVector, *tmpVector;
+  mdd_t			*new_, *resT, *resE, *res, *resPart, *resTmp;
+  mdd_t			*var, *varNot, *cube, *tmp, *func;
+  int			size, i, j, k, vectorSize;
+  array_t		*vectorArray, *varArray;
+  int			hit, turnFlag;
+  int			split, nGroups, cubeSize;
+  mdd_t			*refResult, *product;
+  mdd_t			*newFrom, *fromT, *fromE;
+  ImgComponent_t	*comp;
+  array_t		*relationArrayT, *relationArrayE, *partRelationArray;
+  int			constConstrain;
+  int			nRecur;
+  array_t		*newRelationArray, *tmpRelationArray, *abstractVars;
+  mdd_t			*cofactor, *abstract;
+  mdd_t			*newCofactorCube, *newAbstractCube;
+  mdd_t			*partCofactorCube, *partAbstractCube;
+  mdd_t			*cofactorCubeT, *cofactorCubeE;
+  mdd_t			*abstractCubeT, *abstractCubeE;
+  mdd_t			*essentialCube, *tmpRes;
+  int			findEssential;
+  int			foundEssentialDepth;
+  int			foundEssentialDepthT, foundEssentialDepthE;
+  array_t		*vectorT, *vectorE;
+  mdd_t			*andT, *andE, *one;
+  float			prevLambda;
+  int			prevTotal, prevVectorBddSize, prevVectorSize;
+  int			arraySize, nFuncs;
+
+  newRelationArray = NIL(array_t);
+
+  if (info->option->delayedSplit && relationArray) {
+    ImgVectorConstrain(info, vector, constraint, relationArray,
+			&newVector, &res, &newRelationArray,
+			&cofactor, &abstract, TRUE);
+    newCofactorCube = mdd_and(cofactorCube, cofactor, 1, 1);
+    mdd_free(cofactor);
+    newAbstractCube = mdd_and(abstractCube, abstract, 1, 1);
+    mdd_free(abstract);
+    if (info->option->debug) {
+      refResult = ImgImageByHybrid(info, newVector, from);
+      resPart = ImgImageByHybridWithStaticSplit(info, NIL(array_t), from,
+						newRelationArray,
+						newCofactorCube,
+						newAbstractCube);
+      assert(mdd_equal(refResult, resPart));
+      mdd_free(refResult);
+      mdd_free(resPart);
+    }
+  } else {
+    ImgVectorConstrain(info, vector, constraint, relationArray,
+			&newVector, &res, &newRelationArray,
+			NIL(mdd_t *), NIL(mdd_t *), TRUE);
+    newCofactorCube = NIL(mdd_t);
+    newAbstractCube = NIL(mdd_t);
+    if (info->option->debug) {
+      refResult = ImgImageByHybrid(info, newVector, from);
+      resPart = ImgImageByHybridWithStaticSplit(info, NIL(array_t), from,
+						newRelationArray,
+						NIL(mdd_t), NIL(mdd_t));
+      assert(mdd_equal(refResult, resPart));
+      mdd_free(refResult);
+
+      refResult = ImgImageByHybridWithStaticSplit(info, NIL(array_t), from,
+						relationArray,
+						NIL(mdd_t), NIL(mdd_t));
+      resTmp = mdd_and(resPart, res, 1, 1);
+      mdd_free(resPart);
+      assert(mdd_equal(refResult, resTmp));
+      mdd_free(refResult);
+      mdd_free(resTmp);
+    }
+  }
+
+  if (info->option->checkEquivalence &&
+      relationArray && !info->option->buildPartialTR) {
+    assert(ImgCheckEquivalence(info, newVector, newRelationArray,
+				newCofactorCube, newAbstractCube, 0));
+  }
+
+  if (from && info->option->findEssential) {
+    if (info->option->findEssential == 1)
+      findEssential = 1;
+    else {
+      if (depth >= info->lastFoundEssentialDepth)
+	findEssential = 1;
+      else
+	findEssential = 0;
+    }
+  } else
+    findEssential = 0;
+  if (findEssential) {
+    essentialCube = bdd_find_essential_cube(from);
+
+    if (!bdd_is_tautology(essentialCube, 1)) {
+      info->averageFoundEssential = (info->averageFoundEssential *
+	(float)info->nFoundEssentials + (float)(bdd_size(essentialCube) - 1)) /
+	(float)(info->nFoundEssentials + 1);
+      info->averageFoundEssentialDepth = (info->averageFoundEssentialDepth *
+	(float)info->nFoundEssentials + (float)depth) /
+	(float)(info->nFoundEssentials + 1);
+      if (info->nFoundEssentials == 0 || depth < info->topFoundEssentialDepth)
+	info->topFoundEssentialDepth = depth;
+      info->nFoundEssentials++;
+      if (info->option->printEssential && depth < IMG_TF_MAX_PRINT_DEPTH)
+	info->foundEssentials[depth]++;
+      tmpVector = newVector;
+      tmpRelationArray = newRelationArray;
+      if (info->option->delayedSplit && relationArray) {
+	ImgVectorMinimize(info, tmpVector, essentialCube, NIL(mdd_t),
+			  tmpRelationArray, &newVector, &tmpRes,
+			  &newRelationArray, &cofactor, &abstract);
+	tmp = newCofactorCube;
+	newCofactorCube = mdd_and(tmp, cofactor, 1, 1);
+	mdd_free(tmp);
+	mdd_free(cofactor);
+	tmp = newAbstractCube;
+	newAbstractCube = mdd_and(tmp, abstract, 1, 1);
+	mdd_free(tmp);
+	mdd_free(abstract);
+      } else {
+	ImgVectorMinimize(info, tmpVector, essentialCube, NIL(mdd_t),
+			  tmpRelationArray, &newVector, &tmpRes,
+			  &newRelationArray, NIL(mdd_t *), NIL(mdd_t *));
+      }
+      tmp = res;
+      res = mdd_and(tmp, tmpRes, 1, 1);
+      mdd_free(tmp);
+      ImgVectorFree(tmpVector);
+      if (tmpRelationArray && tmpRelationArray != relationArray &&
+	  tmpRelationArray != newRelationArray)
+	mdd_array_free(tmpRelationArray);
+      foundEssentialDepth = depth;
+    } else
+      foundEssentialDepth = info->option->maxEssentialDepth;
+    mdd_free(essentialCube);
+    foundEssentialDepthT = info->option->maxEssentialDepth;
+    foundEssentialDepthE = info->option->maxEssentialDepth;
+  } else {
+    /* To remove compiler warnings */
+    foundEssentialDepth = -1;
+    foundEssentialDepthT = -1;
+    foundEssentialDepthE = -1;
+  }
+
+  if (info->option->debug) {
+    if (relationArray && from) {
+      refResult = ImgImageByHybrid(info, newVector, from);
+      resPart = ImgImageByHybridWithStaticSplit(info, NIL(array_t), from,
+						newRelationArray,
+						newCofactorCube,
+						newAbstractCube);
+      assert(mdd_equal(refResult, resPart));
+      mdd_free(refResult);
+      mdd_free(resPart);
+    }
+  }
+
+  info->nRecursion++;
+  arraySize = array_n(newVector);
+  if (info->nIntermediateVars)
+    nFuncs = ImgVectorFunctionSize(newVector);
+  else
+    nFuncs = arraySize;
+  if (nFuncs <= 1) {
+    if (info->useConstraint) {
+      if (nFuncs == 1) {
+	comp = array_fetch(ImgComponent_t *, newVector, 0);
+	if (arraySize > 1)
+	  func = ImgGetComposedFunction(newVector);
+	else
+	  func = comp->func;
+	if (mdd_lequal(from, func, 1, 1)) { /* func | from = 1 */
+	  tmp = res;
+	  res = mdd_and(tmp, comp->var, 1, 1);
+	  mdd_free(tmp);
+	} else if (mdd_lequal(func, from, 1, 0)) { /* func | from = 0 */
+	  tmp = res;
+	  res = mdd_and(tmp, comp->var, 1, 0);
+	  mdd_free(tmp);
+	}
+	if (arraySize > 1)
+	  mdd_free(func);
+      }
+    }
+    if (relationArray && newRelationArray != relationArray)
+      mdd_array_free(newRelationArray);
+    if (newCofactorCube)
+      mdd_free(newCofactorCube);
+    if (newAbstractCube)
+      mdd_free(newAbstractCube);
+    ImgVectorFree(newVector);
+    info->averageDepth = (info->averageDepth * (float)info->nLeaves +
+			  (float)depth) / (float)(info->nLeaves + 1);
+    if (depth > info->maxDepth)
+      info->maxDepth = depth;
+    info->nLeaves++;
+    if (findEssential)
+      info->foundEssentialDepth = foundEssentialDepth;
+    if (info->option->debug)
+      assert(TfmCheckImageValidity(info, res));
+    return(res);
+  }
+
+  turnFlag = 0;
+  if (splitMethod == 3 && turnDepth == -1) {
+    if (depth < info->option->splitMinDepth) {
+      info->nSplits++;
+      turnFlag = 0;
+    } else if (depth > info->option->splitMaxDepth) {
+      info->nConjoins++;
+      turnFlag = 1;
+    } else {
+      turnFlag = ImgDecideSplitOrConjoin(info, newVector, from, 0,
+					 newRelationArray, newCofactorCube,
+					 newAbstractCube, 0, depth);
+    }
+  } else {
+    if (splitMethod != 0) {
+      if (depth == turnDepth)
+	turnFlag = 1;
+    }
+  }
+  if (turnFlag || nFuncs == 2) {
+    hit = 1;
+    if (!info->imgCache ||
+	!(resPart = ImgCacheLookupTable(info, info->imgCache, newVector,
+					from))) {
+      hit = 0;
+      if (nFuncs == 2) {
+	if (info->useConstraint) {
+	  ImgVectorConstrain(info, newVector, from, NIL(array_t),
+			     &tmpVector, &resTmp, NIL(array_t *),
+			     NIL(mdd_t *), NIL(mdd_t *), FALSE);
+	  if (array_n(tmpVector) <= 1)
+	    resPart = resTmp;
+	  else {
+	    mdd_free(resTmp);
+	    resPart = ImageFast2(info, tmpVector);
+	  }
+	  ImgVectorFree(tmpVector);
+	} else
+	  resPart = ImageFast2(info, newVector);
+      } else if (splitMethod == 2) {
+	if (info->useConstraint) {
+	  ImgVectorConstrain(info, newVector, from, NIL(array_t),
+			     &tmpVector, &resTmp, NIL(array_t *),
+			     NIL(mdd_t *), NIL(mdd_t *), FALSE);
+	  if (array_n(tmpVector) <= 1)
+	    resPart = resTmp;
+	  else if (array_n(tmpVector) == 2) {
+	    mdd_free(resTmp);
+	    resPart = ImageFast2(info, tmpVector);
+	  } else {
+	    tmp = mdd_one(info->manager);
+	    resPart = ImageByOutputSplit(info, tmpVector, tmp, depth + 1);
+	    mdd_free(tmp);
+	    tmp = resPart;
+	    resPart = mdd_and(tmp, resTmp, 1, 1);
+	    mdd_free(tmp);
+	    mdd_free(resTmp);
+	  }
+	  ImgVectorFree(tmpVector);
+	} else {
+	  tmp = mdd_one(info->manager);
+	  resPart = ImageByOutputSplit(info, newVector, tmp, depth + 1);
+	  mdd_free(tmp);
+	}
+      } else {
+	if (relationArray) {
+	  resPart = ImgImageByHybridWithStaticSplit(info, NIL(array_t), from,
+						    newRelationArray,
+						    newCofactorCube,
+						    newAbstractCube);
+	} else
+	  resPart = ImgImageByHybrid(info, newVector, from);
+      }
+      if (info->imgCache) {
+	if (from) {
+	  ImgCacheInsertTable(info->imgCache, newVector, mdd_dup(from),
+				resPart);
+	} else
+	  ImgCacheInsertTable(info->imgCache, newVector, NIL(mdd_t), resPart);
+      }
+    }
+
+    if (relationArray && newRelationArray != relationArray)
+      mdd_array_free(newRelationArray);
+    if (newCofactorCube)
+      mdd_free(newCofactorCube);
+    if (newAbstractCube)
+      mdd_free(newAbstractCube);
+
+    if (info->option->debug) {
+      refResult = ImgImageByHybrid(info, newVector, from);
+      assert(mdd_equal(refResult, resPart));
+      mdd_free(refResult);
+    }
+
+    new_ = mdd_and(res, resPart, 1, 1);
+    if (info->option->verbosity) {
+      size = bdd_size(new_);
+      if (size > info->maxIntermediateSize)
+	info->maxIntermediateSize = size;
+      if (info->option->printBddSize) {
+	fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
+		bdd_size(res), bdd_size(resPart), size);
+      }
+    }
+    mdd_free(res);
+    res = new_;
+    if (!info->imgCache || hit) {
+      mdd_free(resPart);
+      ImgVectorFree(newVector);
+    }
+    info->averageDepth = (info->averageDepth * (float)info->nLeaves +
+			  (float)depth) / (float)(info->nLeaves + 1);
+    if (depth > info->maxDepth)
+      info->maxDepth = depth;
+    info->nLeaves++;
+    if (turnFlag)
+      info->nTurns++;
+    if (findEssential)
+      info->foundEssentialDepth = foundEssentialDepth;
+    if (info->option->debug)
+      assert(TfmCheckImageValidity(info, res));
+    return(res);
+  }
+
+  if (info->imgCache) {
+    resPart = ImgCacheLookupTable(info, info->imgCache, newVector, from);
+    if (resPart) {
+      if (info->option->debug) {
+	refResult = ImgImageByHybrid(info, newVector, from);
+	assert(mdd_equal(refResult, resPart));
+	mdd_free(refResult);
+      }
+      new_ = mdd_and(res, resPart, 1, 1);
+      if (info->option->verbosity) {
+	size = bdd_size(new_);
+	if (size > info->maxIntermediateSize)
+	  info->maxIntermediateSize = size;
+	if (info->option->printBddSize) {
+	  fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
+		  bdd_size(res), bdd_size(resPart), size);
+	}
+      }
+      mdd_free(res);
+      mdd_free(resPart);
+      res = new_;
+      ImgVectorFree(newVector);
+      if (relationArray && newRelationArray != relationArray)
+	mdd_array_free(newRelationArray);
+      if (newCofactorCube)
+	mdd_free(newCofactorCube);
+      if (newAbstractCube)
+	mdd_free(newAbstractCube);
+      if (findEssential)
+	info->foundEssentialDepth = foundEssentialDepth;
+      if (info->option->debug)
+	assert(TfmCheckImageValidity(info, res));
+      return(res);
+    }
+  }
+
+  if (info->option->splitCubeFunc) {
+    split = -1;
+    cubeSize = 0;
+    for (i = 0; i < array_n(newVector); i++) {
+      comp = array_fetch(ImgComponent_t *, newVector, i);
+      if (bdd_is_cube(comp->func)) {
+	if (split == -1 || info->option->splitCubeFunc == 1 ||
+	    bdd_size(comp->func) > cubeSize) {
+	  split = i;
+	  cubeSize = bdd_size(comp->func);
+	  break;
+	}
+      }
+    }
+    if (split != -1) {
+      comp = array_fetch(ImgComponent_t *, newVector, split);
+      info->nCubeSplits++;
+      if (info->option->delayedSplit && relationArray) {
+	ImgVectorConstrain(info, newVector, comp->func, newRelationArray,
+			   &vectorT, &andT, &relationArrayT,
+			   &cofactor, &abstract, FALSE);
+	cofactorCubeT = mdd_and(newCofactorCube, cofactor, 1, 1);
+	mdd_free(cofactor);
+	abstractCubeT = mdd_and(newAbstractCube, abstract, 1, 1);
+	mdd_free(abstract);
+      } else {
+	ImgVectorConstrain(info, newVector, comp->func, newRelationArray,
+			   &vectorT, &andT, &relationArrayT,
+			   NIL(mdd_t *), NIL(mdd_t *), FALSE);
+	cofactorCubeT = NIL(mdd_t);
+	abstractCubeT = NIL(mdd_t);
+      }
+      if (from)
+	newFrom = bdd_cofactor(from, comp->func);
+      else
+	newFrom = from;
+      if (info->option->checkEquivalence &&
+	  relationArray && !info->option->buildPartialTR) {
+	assert(ImgCheckEquivalence(info, vectorT, relationArrayT,
+				   cofactorCubeT, abstractCubeT, 0));
+      }
+
+      one = mdd_one(info->manager);
+      if (newFrom && bdd_is_tautology(newFrom, 0))
+	resT = mdd_zero(info->manager);
+      else {
+	prevLambda = info->prevLambda;
+	prevTotal = info->prevTotal;
+	prevVectorBddSize = info->prevVectorBddSize;
+	prevVectorSize = info->prevVectorSize;
+	resT = ImageByInputSplit(info, vectorT, one, newFrom,
+			      relationArrayT, cofactorCubeT, abstractCubeT,
+			      splitMethod, turnDepth, depth + 1);
+	info->prevLambda = prevLambda;
+	info->prevTotal = prevTotal;
+	info->prevVectorBddSize = prevVectorBddSize;
+	info->prevVectorSize = prevVectorSize;
+      }
+      ImgVectorFree(vectorT);
+      if (newFrom)
+	mdd_free(newFrom);
+      if (!bdd_is_tautology(andT, 1)) {
+	tmp = resT;
+	resT = mdd_and(tmp, andT, 1, 1);
+	mdd_free(tmp);
+      }
+      if (findEssential)
+	foundEssentialDepthT = info->foundEssentialDepth;
+      if (relationArrayT && relationArrayT != newRelationArray)
+	mdd_array_free(relationArrayT);
+      if (cofactorCubeT && cofactorCubeT != newCofactorCube)
+	mdd_free(cofactorCubeT);
+      if (abstractCubeT && abstractCubeT != newAbstractCube)
+	mdd_free(abstractCubeT);
+
+      tmp = mdd_not(comp->func);
+      if (info->option->delayedSplit && relationArray) {
+	ImgVectorConstrain(info, newVector, tmp, newRelationArray,
+			   &vectorE, &andE, &relationArrayE,
+			   &cofactor, &abstract, FALSE);
+	cofactorCubeE = mdd_and(newCofactorCube, cofactor, 1, 1);
+	mdd_free(cofactor);
+	abstractCubeE = mdd_and(newAbstractCube, abstract, 1, 1);
+	mdd_free(abstract);
+      } else {
+	ImgVectorConstrain(info, newVector, tmp, newRelationArray,
+			   &vectorE, &andE, &relationArrayE,
+			   NIL(mdd_t *), NIL(mdd_t *), FALSE);
+	cofactorCubeE = NIL(mdd_t);
+	abstractCubeE = NIL(mdd_t);
+      }
+      if (from)
+	newFrom = bdd_cofactor(from, tmp);
+      else
+	newFrom = from;
+      mdd_free(tmp);
+      if (relationArray && newRelationArray != relationArray)
+	mdd_array_free(newRelationArray);
+      if (newCofactorCube)
+	mdd_free(newCofactorCube);
+      if (newAbstractCube)
+	mdd_free(newAbstractCube);
+      if (info->option->checkEquivalence &&
+	  relationArray && !info->option->buildPartialTR) {
+	assert(ImgCheckEquivalence(info, vectorE, relationArrayE,
+				   cofactorCubeE, abstractCubeE, 0));
+      }
+
+      if (newFrom && bdd_is_tautology(newFrom, 0))
+	resE = mdd_zero(info->manager);
+      else {
+	resE = ImageByInputSplit(info, vectorE, one, newFrom,
+			      relationArrayE, cofactorCubeE, abstractCubeE,
+			      splitMethod, turnDepth, depth + 1);
+      }
+      ImgVectorFree(vectorE);
+      if (newFrom)
+	mdd_free(newFrom);
+      if (!bdd_is_tautology(andE, 1)) {
+	tmp = resE;
+	resE = mdd_and(tmp, andE, 1, 1);
+	mdd_free(tmp);
+      }
+      if (findEssential)
+	foundEssentialDepthE = info->foundEssentialDepth;
+      if (relationArrayE && relationArrayE != newRelationArray)
+	mdd_array_free(relationArrayE);
+      if (cofactorCubeE && cofactorCubeE != newCofactorCube)
+	mdd_free(cofactorCubeE);
+      if (abstractCubeE && abstractCubeE != newAbstractCube)
+	mdd_free(abstractCubeE);
+
+      resPart = bdd_ite(comp->var, resT, resE, 1, 1, 1);
+      if (info->option->verbosity) {
+	size = bdd_size(resPart);
+	if (size > info->maxIntermediateSize)
+	  info->maxIntermediateSize = size;
+	if (info->option->printBddSize) {
+	  fprintf(vis_stdout, "** tfm info: bdd_ite(2,%d,%d) = %d\n",
+		  bdd_size(resT), bdd_size(resE), size);
+	}
+      }
+      mdd_free(one);
+
+      if (info->imgCache)
+	ImgCacheInsertTable(info->imgCache, newVector, NIL(mdd_t), resPart);
+
+      if (info->option->debug) {
+	refResult = ImgImageByHybrid(info, newVector, from);
+	assert(mdd_equal(refResult, resPart));
+	mdd_free(refResult);
+      }
+
+      new_ = mdd_and(res, resPart, 1, 1);
+      if (info->option->verbosity) {
+	size = bdd_size(new_);
+	if (size > info->maxIntermediateSize)
+	  info->maxIntermediateSize = size;
+	if (info->option->printBddSize) {
+	  fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
+		  bdd_size(res), bdd_size(resPart), size);
+	}
+      }
+      mdd_free(res);
+      res = new_;
+
+      if (info->option->debug) {
+	refResult = ImgImageByHybrid(info, newVector, from);
+	assert(mdd_equal(refResult, resPart));
+	mdd_free(refResult);
+      }
+
+      if (!info->imgCache) {
+	mdd_free(resPart);
+	ImgVectorFree(newVector);
+      }
+      info->averageDepth = (info->averageDepth * (float)info->nLeaves +
+			    (float)depth) / (float)(info->nLeaves + 1);
+      if (depth > info->maxDepth)
+	info->maxDepth = depth;
+      info->nLeaves++;
+      if (turnFlag)
+	info->nTurns++;
+      if (findEssential) {
+	if (foundEssentialDepth == info->option->maxEssentialDepth) {
+	  if (foundEssentialDepthT < foundEssentialDepthE)
+	    foundEssentialDepth = foundEssentialDepthT;
+	  else
+	    foundEssentialDepth = foundEssentialDepthE;
+	}
+	info->foundEssentialDepth = foundEssentialDepth;
+      }
+      if (info->option->debug)
+	assert(TfmCheckImageValidity(info, res));
+      return(res);
+    }
+  }
+
+  /* compute disconnected component and best variable selection */
+  vectorArray = array_alloc(array_t *, 0);
+  varArray = array_alloc(int, 0);
+  if (info->option->delayedSplit && relationArray) {
+    nGroups = ImageDecomposeAndChooseSplitVar(info, newVector, from, 0,
+  					info->option->inputSplit,
+					info->option->piSplitFlag,
+					vectorArray, varArray, &product,
+					newRelationArray, &tmpRelationArray,
+					&cofactor, &abstract);
+  } else {
+    nGroups = ImageDecomposeAndChooseSplitVar(info, newVector, from, 0,
+  					info->option->inputSplit,
+					info->option->piSplitFlag,
+					vectorArray, varArray, &product,
+					newRelationArray, &tmpRelationArray,
+					NIL(mdd_t *), NIL(mdd_t *));
+    cofactor = NIL(mdd_t);
+    abstract = NIL(mdd_t);
+
+    if (info->option->debug && nGroups >= 1) {
+      if (info->option->verbosity > 1) {
+	ImgPrintVectorDependency(info, newVector, info->option->verbosity);
+	PrintVectorDecomposition(info, vectorArray, varArray);
+      }
+
+      refResult = ImgImageByHybrid(info, newVector, from);
+      resPart = mdd_dup(product);
+      for (i = 0; i < array_n(vectorArray); i++) {
+	vector = array_fetch(array_t *, vectorArray, i);
+	resTmp = ImgImageByHybrid(info, vector, from);
+	tmp = resPart;
+	resPart = mdd_and(tmp, resTmp, 1, 1);
+	mdd_free(tmp);
+	mdd_free(resTmp);
+
+	if (arraySize > nFuncs) {
+	  split = array_fetch(int, varArray, i);
+	  assert(!st_is_member(info->intermediateVarsTable,
+		 (char *)(long)split));
+	}
+      }
+      assert(mdd_equal(refResult, resPart));
+      mdd_free(refResult);
+      mdd_free(resPart);
+    }
+  }
+  vectorSize = array_n(newVector);
+  if ((!info->imgCache || nGroups <= 1) && !info->option->debug)
+    ImgVectorFree(newVector);
+  if (newRelationArray) {
+    if (newRelationArray != relationArray &&
+	tmpRelationArray != newRelationArray) {
+      mdd_array_free(newRelationArray);
+    }
+    newRelationArray = tmpRelationArray;
+  }
+  if (nGroups == 0) {
+    if (relationArray && newRelationArray != relationArray)
+      mdd_array_free(newRelationArray);
+    if (newCofactorCube)
+      mdd_free(newCofactorCube);
+    if (newAbstractCube)
+      mdd_free(newAbstractCube);
+    if (cofactor)
+      mdd_free(cofactor);
+    if (abstract)
+      mdd_free(abstract);
+
+    array_free(vectorArray);
+    array_free(varArray);
+
+    if (info->option->debug) {
+      refResult = ImgImageByHybrid(info, newVector, from);
+      assert(mdd_equal(refResult, product));
+      mdd_free(refResult);
+      ImgVectorFree(newVector);
+    }
+
+    new_ = mdd_and(res, product, 1, 1);
+    if (info->option->verbosity) {
+      size = bdd_size(new_);
+      if (size > info->maxIntermediateSize)
+	info->maxIntermediateSize = size;
+      if (info->option->printBddSize) {
+	fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
+		bdd_size(res), bdd_size(product), size);
+      }
+    }
+    mdd_free(res);
+    mdd_free(product);
+    res = new_;
+
+    info->averageDepth = (info->averageDepth * (float)info->nLeaves +
+			  (float)depth) / (float)(info->nLeaves + 1);
+    if (depth > info->maxDepth)
+      info->maxDepth = depth;
+    info->nLeaves++;
+    if (findEssential)
+      info->foundEssentialDepth = foundEssentialDepth;
+    if (info->option->debug)
+      assert(TfmCheckImageValidity(info, res));
+    return(res);
+  }
+
+  if (info->option->delayedSplit && relationArray) {
+    tmp = newCofactorCube;
+    newCofactorCube = mdd_and(tmp, cofactor, 1, 1);
+    mdd_free(tmp);
+    mdd_free(cofactor);
+    tmp = newAbstractCube;
+    newAbstractCube = mdd_and(tmp, abstract, 1, 1);
+    mdd_free(tmp);
+    mdd_free(abstract);
+  }
+
+  if (nGroups > 1) {
+    if (info->nDecomps == 0 || depth < info->topDecomp)
+      info->topDecomp = depth;
+    if (info->nDecomps == 0 || vectorSize > info->maxDecomp)
+      info->maxDecomp = vectorSize;
+    info->averageDecomp = (info->averageDecomp * (float)info->nDecomps +
+			  (float)nGroups) / (float)(info->nDecomps + 1);
+    info->nDecomps++;
+  }
+
+  if (relationArray && nGroups > 1) {
+    abstractVars = array_alloc(mdd_t *, 0);
+    for (i = 0; i < array_n(vectorArray); i++) {
+      vector = array_fetch(array_t *, vectorArray, i);
+      cube = mdd_one(info->manager);
+      for (j = 0; j < nGroups; j++) {
+	if (j == i)
+	  continue;
+	tmpVector = array_fetch(array_t *, vectorArray, j);
+	for (k = 0; k < array_n(tmpVector); k++) {
+	  comp = array_fetch(ImgComponent_t *, tmpVector, k);
+	  tmp = cube;
+	  cube = mdd_and(cube, comp->var, 1, 1);
+	  mdd_free(tmp);
+	}
+      }
+      tmp = ImgSubstitute(cube, info->functionData, Img_D2R_c);
+      mdd_free(cube);
+      array_insert_last(mdd_t *, abstractVars, tmp);
+    }
+  } else
+    abstractVars = NIL(array_t);
+  for (i = 0; i < array_n(vectorArray); i++) {
+    vector = array_fetch(array_t *, vectorArray, i);
+    if (from)
+      newFrom = mdd_dup(from);
+    else
+      newFrom = from;
+
+    if (relationArray) {
+      if (nGroups == 1) {
+	partRelationArray = newRelationArray;
+	if (info->option->delayedSplit) {
+	  partCofactorCube = newCofactorCube;
+	  partAbstractCube = newAbstractCube;
+	} else {
+	  partCofactorCube = NIL(mdd_t);
+	  partAbstractCube = NIL(mdd_t);
+	}
+      } else {
+	cube = array_fetch(mdd_t *, abstractVars, i);
+	if (info->option->delayedSplit) {
+	  partRelationArray = newRelationArray;
+	  partCofactorCube = mdd_dup(newCofactorCube);
+	  partAbstractCube = mdd_and(newAbstractCube, cube, 1, 1);
+	} else {
+	  partRelationArray = ImgGetAbstractedRelationArray(info->manager,
+							    newRelationArray,
+							    cube);
+	  mdd_free(cube);
+	  partCofactorCube = NIL(mdd_t);
+	  partAbstractCube = NIL(mdd_t);
+	}
+      }
+      if (info->option->debug) {
+	refResult = ImgImageByHybrid(info, vector, from);
+	resPart = ImgImageByHybridWithStaticSplit(info, NIL(array_t), from,
+						  partRelationArray,
+						  partCofactorCube,
+						  partAbstractCube);
+	assert(mdd_equal(refResult, resPart));
+	mdd_free(refResult);
+	mdd_free(resPart);
+      }
+    } else {
+      partRelationArray = newRelationArray;
+      partCofactorCube = NIL(mdd_t);
+      partAbstractCube = NIL(mdd_t);
+    }
+    hit = 1;
+    if (!info->imgCache || nGroups == 1 ||
+	!(resPart = ImgCacheLookupTable(info, info->imgCache, vector,
+					newFrom))) {
+      hit = 0;
+      if (arraySize > nFuncs)
+	size = ImgVectorFunctionSize(vector);
+      else
+	size = array_n(vector);
+      if (size == 1) {
+	comp = array_fetch(ImgComponent_t *, vector, 0);
+	if (array_n(vector) > 1)
+	  func = ImgGetComposedFunction(vector);
+	else
+	  func = comp->func;
+	if (info->useConstraint) {
+	  constConstrain = ImgConstConstrain(func, newFrom);
+	  if (constConstrain == 1)
+	    resPart = mdd_dup(comp->var);
+	  else if (constConstrain == 0)
+	    resPart = mdd_not(comp->var);
+	  else
+	    resPart = mdd_one(info->manager);
+	} else {
+	  if (bdd_is_tautology(func, 1))
+	    resPart = mdd_dup(comp->var);
+	  else if (bdd_is_tautology(func, 0))
+	    resPart = mdd_not(comp->var);
+	  else
+	    resPart = mdd_one(info->manager);
+	}
+	if (array_n(vector) > 1)
+	  mdd_free(func);
+	info->averageDepth = (info->averageDepth * (float)info->nLeaves +
+				(float)depth) / (float)(info->nLeaves + 1);
+	if (depth > info->maxDepth)
+	  info->maxDepth = depth;
+	info->nLeaves++;
+      } else if (size == 2) {
+	if (info->useConstraint) {
+	  ImgVectorConstrain(info, vector, newFrom, NIL(array_t),
+			     &newVector, &resTmp, NIL(array_t *),
+			     NIL(mdd_t *), NIL(mdd_t *), FALSE);
+	  if (array_n(newVector) <= 1)
+	    resPart = resTmp;
+	  else {
+	    mdd_free(resTmp);
+	    resPart = ImageFast2(info, newVector);
+	  }
+	  ImgVectorFree(newVector);
+	} else
+	  resPart = ImageFast2(info, vector);
+	info->averageDepth = (info->averageDepth * (float)info->nLeaves +
+				(float)depth) / (float)(info->nLeaves + 1);
+	if (depth > info->maxDepth)
+	  info->maxDepth = depth;
+	info->nLeaves++;
+      } else {
+	nRecur = 0;
+	split = array_fetch(int, varArray, i);
+	if (partRelationArray && info->imgKeepPiInTr == FALSE) {
+	  if (st_lookup(info->quantifyVarsTable, (char *)(long)split,
+ 			NIL(char *))) {
+	    int newSplit;
+
+	    /* checks the splitting is valid */
+	    newSplit = CheckIfValidSplitOrGetNew(info, split, vector,
+						partRelationArray, from);
+	    if (newSplit == -1) {
+	      resPart = ImgImageByHybrid(info, vector, from);
+	      info->averageDepth = (info->averageDepth * (float)info->nLeaves +
+				(float)depth) / (float)(info->nLeaves + 1);
+	      if (depth > info->maxDepth)
+		info->maxDepth = depth;
+	      info->nLeaves++;
+	      info->nTurns++;
+	      goto cache;
+	    }
+	    split = newSplit;
+	  }
+	}
+	var = bdd_var_with_index(info->manager, split);
+	if (newFrom)
+	  fromT = bdd_cofactor(newFrom, var);
+	else
+	  fromT = NIL(mdd_t);
+	if (partRelationArray) {
+	  if (info->option->delayedSplit) {
+	    relationArrayT = partRelationArray;
+	    cofactorCubeT = mdd_and(partCofactorCube, var, 1, 1);
+	  } else {
+	    relationArrayT = ImgGetCofactoredRelationArray(partRelationArray,
+							   var);
+	    cofactorCubeT = partCofactorCube;
+	  }
+	} else {
+	  relationArrayT = NIL(array_t);
+	  cofactorCubeT = NIL(mdd_t);
+	}
+	if (!fromT || !bdd_is_tautology(fromT, 0)) {
+	  prevLambda = info->prevLambda;
+	  prevTotal = info->prevTotal;
+	  prevVectorBddSize = info->prevVectorBddSize;
+	  prevVectorSize = info->prevVectorSize;
+	  resT = ImageByInputSplit(info, vector, var, fromT,
+				relationArrayT, cofactorCubeT, partAbstractCube,
+				splitMethod, turnDepth, depth + 1);
+	  if (info->option->debug) {
+	    refResult = ImgImageByHybridWithStaticSplit(info, NIL(array_t),
+							fromT, relationArrayT,
+							cofactorCubeT,
+							partAbstractCube);
+	    assert(mdd_equal(refResult, resT));
+	    mdd_free(refResult);
+	  }
+	  info->prevLambda = prevLambda;
+	  info->prevTotal = prevTotal;
+	  info->prevVectorBddSize = prevVectorBddSize;
+	  info->prevVectorSize = prevVectorSize;
+	  if (findEssential)
+	    foundEssentialDepthT = info->foundEssentialDepth;
+	  nRecur++;
+	} else
+	  resT = mdd_zero(info->manager);
+	if (fromT)
+	  mdd_free(fromT);
+	if (relationArrayT && relationArrayT != partRelationArray)
+	  mdd_array_free(relationArrayT);
+	if (cofactorCubeT && cofactorCubeT != partCofactorCube)
+	  mdd_free(cofactorCubeT);
+
+	if (bdd_is_tautology(resT, 1)) {
+	  mdd_free(var);
+	  resPart = resT;
+	  info->nEmptySubImage++;
+	} else {
+	  varNot = mdd_not(var);
+	  mdd_free(var);
+	  if (newFrom)
+	    fromE = bdd_cofactor(newFrom, varNot);
+	  else
+	    fromE = NIL(mdd_t);
+	  if (partRelationArray) {
+	    if (info->option->delayedSplit) {
+	      relationArrayE = partRelationArray;
+	      cofactorCubeE = mdd_and(partCofactorCube, varNot, 1, 1);
+	    } else {
+	      relationArrayE = ImgGetCofactoredRelationArray(partRelationArray,
+							     varNot);
+	      cofactorCubeE = partCofactorCube;
+	    }
+	  } else {
+	    relationArrayE = NIL(array_t);
+	    cofactorCubeE = NIL(mdd_t);
+	  }
+	  if (!fromE || !bdd_is_tautology(fromE, 0)) {
+	    resE = ImageByInputSplit(info, vector, varNot, fromE,
+			  relationArrayE, cofactorCubeE, partAbstractCube,
+			  splitMethod, turnDepth, depth + 1);
+	    if (info->option->debug) {
+	      refResult = ImgImageByHybridWithStaticSplit(info, NIL(array_t),
+							  fromE, relationArrayE,
+							  cofactorCubeE,
+							  partAbstractCube);
+	      assert(mdd_equal(refResult, resE));
+	      mdd_free(refResult);
+	    }
+	    if (findEssential)
+	      foundEssentialDepthE = info->foundEssentialDepth;
+	    nRecur++;
+	  } else
+	    resE = mdd_zero(info->manager);
+	  mdd_free(varNot);
+	  if (fromE)
+	    mdd_free(fromE);
+	  if (relationArrayE && relationArrayE != partRelationArray)
+	    mdd_array_free(relationArrayE);
+	  if (cofactorCubeE && cofactorCubeE != partCofactorCube)
+	    mdd_free(cofactorCubeE);
+    
+	  resPart = mdd_or(resT, resE, 1, 1);
+	  if (info->option->debug) {
+	    refResult = ImgImageByHybrid(info, vector, from);
+	    assert(mdd_equal(refResult, resPart));
+	    mdd_free(refResult);
+	  }
+	  if (info->option->verbosity) {
+	    size = bdd_size(resPart);
+	    if (size > info->maxIntermediateSize)
+	      info->maxIntermediateSize = size;
+	    if (info->option->printBddSize) {
+	      fprintf(vis_stdout, "** tfm info: bdd_or(%d,%d) = %d\n",
+		      bdd_size(resT), bdd_size(resE), size);
+	    }
+	  }
+
+	  mdd_free(resT);
+	  mdd_free(resE);
+	}
+	if (nRecur == 0) {
+	  info->averageDepth = (info->averageDepth * (float)info->nLeaves +
+				(float)depth) / (float)(info->nLeaves + 1);
+	  if (depth > info->maxDepth)
+	    info->maxDepth = depth;
+	  info->nLeaves++;
+	}
+      }
+cache:
+      if (info->imgCache) {
+	ImgCacheInsertTable(info->imgCache, vector, newFrom, resPart);
+	if (info->option->debug) {
+	  refResult = ImgImageByHybrid(info, vector, newFrom);
+	  assert(mdd_equal(refResult, resPart));
+	  mdd_free(refResult);
+	}
+      }
+    }
+    if (!info->imgCache || hit) {
+      ImgVectorFree(vector);
+      if (newFrom)
+	mdd_free(newFrom);
+    }
+    new_ = mdd_and(product, resPart, 1, 1);
+    if (info->option->verbosity) {
+      size = bdd_size(new_);
+      if (size > info->maxIntermediateSize)
+	info->maxIntermediateSize = size;
+      if (info->option->printBddSize) {
+	fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
+		bdd_size(product), bdd_size(resPart), size);
+      }
+    }
+    mdd_free(product);
+    if (!info->imgCache || hit)
+      mdd_free(resPart);
+    product = new_;
+    if (nGroups > 1 && partRelationArray != newRelationArray)
+      mdd_array_free(partRelationArray);
+    if (partCofactorCube && partCofactorCube != newCofactorCube)
+      mdd_free(partCofactorCube);
+    if (partAbstractCube && partAbstractCube != newAbstractCube)
+      mdd_free(partAbstractCube);
+  }
+  if (abstractVars)
+    array_free(abstractVars);
+
+  if (relationArray && newRelationArray != relationArray)
+    mdd_array_free(newRelationArray);
+  if (newCofactorCube)
+    mdd_free(newCofactorCube);
+  if (newAbstractCube)
+    mdd_free(newAbstractCube);
+
+  array_free(vectorArray);
+  array_free(varArray);
+
+  if (info->imgCache && nGroups > 1) {
+    if (from) {
+      ImgCacheInsertTable(info->imgCache, newVector, mdd_dup(from),
+			  mdd_dup(product));
+    } else {
+      ImgCacheInsertTable(info->imgCache, newVector, NIL(mdd_t),
+			  mdd_dup(product));
+    }
+  }
+
+  if (info->option->debug) {
+    refResult = ImgImageByHybrid(info, newVector, from);
+    assert(mdd_equal(refResult, product));
+    mdd_free(refResult);
+    if (!info->imgCache || nGroups == 1)
+      ImgVectorFree(newVector);
+  }
+
+  new_ = mdd_and(res, product, 1, 1);
+  if (info->option->verbosity) {
+    size = bdd_size(new_);
+    if (size > info->maxIntermediateSize)
+      info->maxIntermediateSize = size;
+    if (info->option->printBddSize) {
+      fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
+	      bdd_size(res), bdd_size(product), size);
+    }
+  }
+  mdd_free(res);
+  mdd_free(product);
+  res = new_;
+
+  if (findEssential) {
+    if (foundEssentialDepth == info->option->maxEssentialDepth) {
+      if (foundEssentialDepthT < foundEssentialDepthE)
+	foundEssentialDepth = foundEssentialDepthT;
+      else
+	foundEssentialDepth = foundEssentialDepthE;
+    }
+    info->foundEssentialDepth = foundEssentialDepth;
+  }
+  if (info->option->debug)
+    assert(TfmCheckImageValidity(info, res));
+  return(res);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes an image by static input splitting.]
+
+  Description [Computes an image by static input splitting.]
+
+  SideEffects []
+
+******************************************************************************/
+static mdd_t *
+ImageByStaticInputSplit(ImgTfmInfo_t *info, array_t *vector, mdd_t *from,
+			array_t *relationArray, int turnDepth, int depth)
+{
+  array_t	*vectorT, *vectorE, *tmpVector;
+  mdd_t		*resT, *resE, *res, *tmp, *cubeT, *cubeE;
+  mdd_t		*fromT, *fromE;
+  mdd_t		*var, *varNot;
+  array_t	*relationArrayT, *relationArrayE;
+  array_t	*newRelationArray, *tmpRelationArray;
+  int		nRecur;
+  mdd_t		*refResult, *and_;
+  mdd_t		*essentialCube;
+  int		findEssential;
+  int		foundEssentialDepth, foundEssentialDepthT, foundEssentialDepthE;
+  int		turnFlag, size;
+
+  info->nRecursion++;
+
+  turnFlag = 0;
+  if (turnDepth == -1) {
+    if (depth < info->option->splitMinDepth) {
+      info->nSplits++;
+      turnFlag = 0;
+    } else if (depth > info->option->splitMaxDepth) {
+      info->nConjoins++;
+      turnFlag = 1;
+    } else {
+      turnFlag = ImgDecideSplitOrConjoin(info, vector, from, 0,
+					 relationArray, NIL(mdd_t),
+					 NIL(mdd_t), 1, depth);
+    }
+  } else {
+    if (depth == turnDepth)
+      turnFlag = 1;
+    else
+      turnFlag = 0;
+  }
+  if (turnFlag) {
+    res = ImgImageByHybridWithStaticSplit(info, vector, from, relationArray,
+					  NIL(mdd_t), NIL(mdd_t));
+    info->averageDepth = (info->averageDepth * (float)info->nLeaves +
+			  (float)depth) / (float)(info->nLeaves + 1);
+    if (depth > info->maxDepth)
+      info->maxDepth = depth;
+    info->nLeaves++;
+    info->foundEssentialDepth = info->option->maxEssentialDepth;
+    return(res);
+  }
+
+  if (info->option->findEssential) {
+    if (info->option->findEssential == 1)
+      findEssential = 1;
+    else {
+      if (depth >= info->lastFoundEssentialDepth)
+	findEssential = 1;
+      else
+	findEssential = 0;
+    }
+  } else
+    findEssential = 0;
+  if (findEssential) {
+    essentialCube = bdd_find_essential_cube(from);
+
+    if (!bdd_is_tautology(essentialCube, 1)) {
+      info->averageFoundEssential = (info->averageFoundEssential *
+	(float)info->nFoundEssentials + (float)(bdd_size(essentialCube) - 1)) /
+	(float)(info->nFoundEssentials + 1);
+      info->averageFoundEssentialDepth = (info->averageFoundEssentialDepth *
+	(float)info->nFoundEssentials + (float)depth) /
+	(float)(info->nFoundEssentials + 1);
+      if (info->nFoundEssentials == 0 || depth < info->topFoundEssentialDepth)
+	info->topFoundEssentialDepth = depth;
+      if (info->option->printEssential && depth < IMG_TF_MAX_PRINT_DEPTH)
+	info->foundEssentials[depth]++;
+      info->nFoundEssentials++;
+      ImgVectorMinimize(info, vector, essentialCube, NIL(mdd_t), relationArray,
+			&tmpVector, &and_,
+			&tmpRelationArray, NIL(mdd_t *), NIL(mdd_t *));
+      foundEssentialDepth = depth;
+    } else {
+      tmpVector = vector;
+      tmpRelationArray = relationArray;
+      and_ = NIL(mdd_t);
+      foundEssentialDepth = info->option->maxEssentialDepth;
+    }
+    mdd_free(essentialCube);
+    foundEssentialDepthT = info->option->maxEssentialDepth;
+    foundEssentialDepthE = info->option->maxEssentialDepth;
+  } else {
+    tmpVector = vector;
+    tmpRelationArray = relationArray;
+    and_ = NIL(mdd_t);
+    /* To remove compiler warnings */
+    foundEssentialDepth = -1;
+    foundEssentialDepthT = -1;
+    foundEssentialDepthE = -1;
+  }
+
+  var = ImgChooseTrSplitVar(info, tmpVector, tmpRelationArray,
+			    info->option->trSplitMethod,
+			    info->option->piSplitFlag);
+  if (!var) {
+    res = ImgImageByHybridWithStaticSplit(info, vector, from, relationArray,
+					  NIL(mdd_t), NIL(mdd_t));
+    info->averageDepth = (info->averageDepth * (float)info->nLeaves +
+			  (float)depth) / (float)(info->nLeaves + 1);
+    if (depth > info->maxDepth)
+      info->maxDepth = depth;
+    info->nLeaves++;
+    info->foundEssentialDepth = info->option->maxEssentialDepth;
+    return(res);
+  }
+
+  nRecur = 0;
+  if (tmpVector) {
+    ImgVectorConstrain(info, tmpVector, var, tmpRelationArray,
+			&vectorT, &cubeT, &newRelationArray,
+			NIL(mdd_t *), NIL(mdd_t *), TRUE);
+  } else {
+    vectorT = NIL(array_t);
+    cubeT = NIL(mdd_t);
+    newRelationArray = tmpRelationArray;
+  }
+  fromT = bdd_cofactor(from, var);
+  relationArrayT = ImgGetCofactoredRelationArray(newRelationArray, var);
+  if (relationArray && newRelationArray != tmpRelationArray)
+    mdd_array_free(newRelationArray);
+  if (!bdd_is_tautology(fromT, 0)) {
+    resT = ImageByStaticInputSplit(info, vectorT, fromT,
+			     relationArrayT, turnDepth, depth + 1);
+    if (findEssential)
+      foundEssentialDepthT = info->foundEssentialDepth;
+    if (vectorT) {
+      ImgVectorFree(vectorT);
+      if (!bdd_is_tautology(cubeT, 1)) {
+	tmp = resT;
+	resT = mdd_and(tmp, cubeT, 1, 1);
+	mdd_free(tmp);
+      }
+      mdd_free(cubeT);
+    }
+    nRecur++;
+  } else {
+    resT = mdd_zero(info->manager);
+    if (vectorT) {
+      ImgVectorFree(vectorT);
+      mdd_free(cubeT);
+    }
+  }
+  mdd_free(fromT);
+  mdd_array_free(relationArrayT);
+
+  if (bdd_is_tautology(resT, 1)) {
+    mdd_free(var);
+    if (vector && newRelationArray != relationArray)
+      mdd_array_free(newRelationArray);
+    res = resT;
+    info->nEmptySubImage++;
+  } else {
+    varNot = mdd_not(var);
+    mdd_free(var);
+    if (tmpVector) {
+      ImgVectorConstrain(info, tmpVector, varNot, tmpRelationArray,
+			 &vectorE, &cubeE, &newRelationArray,
+			 NIL(mdd_t *), NIL(mdd_t *), TRUE);
+    } else {
+      vectorE = NIL(array_t);
+      cubeE = NIL(mdd_t);
+      newRelationArray = tmpRelationArray;
+    }
+    fromE = bdd_cofactor(from, varNot);
+    relationArrayE = ImgGetCofactoredRelationArray(newRelationArray, varNot);
+    if (vector && newRelationArray != tmpRelationArray)
+      mdd_array_free(newRelationArray);
+    if (!bdd_is_tautology(fromE, 0)) {
+      resE = ImageByStaticInputSplit(info, vectorE, fromE,
+			       relationArrayE, turnDepth, depth + 1);
+      if (findEssential)
+	foundEssentialDepthE = info->foundEssentialDepth;
+      if (vectorE) {
+	ImgVectorFree(vectorE);
+	if (!bdd_is_tautology(cubeE, 1)) {
+	  tmp = resE;
+	  resE = mdd_and(tmp, cubeE, 1, 1);
+	  mdd_free(tmp);
+	}
+	mdd_free(cubeE);
+      }
+      nRecur++;
+    } else {
+      resE = mdd_zero(info->manager);
+      if (vectorE) {
+	ImgVectorFree(vectorE);
+	mdd_free(cubeE);
+      }
+    }
+    mdd_free(fromE);
+    mdd_array_free(relationArrayE);
+    
+    res = mdd_or(resT, resE, 1, 1);
+    if (info->option->verbosity) {
+      size = bdd_size(res);
+      if (size > info->maxIntermediateSize)
+	info->maxIntermediateSize = size;
+      if (info->option->printBddSize) {
+	fprintf(vis_stdout, "** tfm info: bdd_or(%d,%d) = %d\n",
+		bdd_size(resT), bdd_size(resE), size);
+      }
+    }
+    mdd_free(resT);
+    mdd_free(resE);
+    mdd_free(varNot);
+  }
+
+  if (tmpVector && tmpVector != vector)
+    ImgVectorFree(tmpVector);
+  if (tmpRelationArray && tmpRelationArray != relationArray)
+    mdd_array_free(tmpRelationArray);
+
+  if (and_) {
+    tmp = res;
+    res = mdd_and(tmp, and_, 1, 1);
+    if (info->option->verbosity) {
+      size = bdd_size(res);
+      if (size > info->maxIntermediateSize)
+	info->maxIntermediateSize = size;
+      if (info->option->printBddSize) {
+	fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
+		bdd_size(tmp), bdd_size(and_), size);
+      }
+    }
+    mdd_free(tmp);
+  }
+
+  if (info->option->debug) {
+    refResult = ImgImageByHybridWithStaticSplit(info, vector, from,
+						relationArray,
+						NIL(mdd_t), NIL(mdd_t));
+    assert(mdd_equal(refResult, res));
+    mdd_free(refResult);
+  }
+
+  if (nRecur == 0) {
+    info->averageDepth = (info->averageDepth * (float)info->nLeaves +
+			  (float)depth) / (float)(info->nLeaves + 1);
+    if (depth > info->maxDepth)
+      info->maxDepth = depth;
+    info->nLeaves++;
+  }
+
+  if (findEssential) {
+    if (foundEssentialDepth == info->option->maxEssentialDepth) {
+      if (foundEssentialDepthT < foundEssentialDepthE)
+	foundEssentialDepth = foundEssentialDepthT;
+      else
+	foundEssentialDepth = foundEssentialDepthE;
+    }
+    info->foundEssentialDepth = foundEssentialDepth;
+  }
+  return(res);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes an image by output splitting.]
+
+  Description [Computes an image by output splitting.]
+
+  SideEffects []
+
+******************************************************************************/
+static mdd_t *
+ImageByOutputSplit(ImgTfmInfo_t *info, array_t *vector, mdd_t *constraint,
+		   int depth)
+{
+  array_t		*newVector;
+  mdd_t			*new_, *resT, *resE, *res, *resPart;
+  mdd_t			*constrain, *tmp, *func;
+  int			size, i, vectorSize;
+  array_t		*vectorArray, *varArray;
+  ImgComponent_t	*comp;
+  int			hit;
+  int			split, nGroups;
+  mdd_t			*product, *refResult;
+
+  ImgVectorConstrain(info, vector, constraint, NIL(array_t),
+		     &newVector, &res, NIL(array_t *),
+		     NIL(mdd_t *), NIL(mdd_t *), FALSE);
+
+  info->nRecursion++;
+  if (info->nIntermediateVars)
+    size = ImgVectorFunctionSize(newVector);
+  else
+    size = array_n(newVector);
+  if (size <= 1) {
+    ImgVectorFree(newVector);
+    info->averageDepth = (info->averageDepth * (float)info->nLeaves +
+			  (float)depth) / (float)(info->nLeaves + 1);
+    if (depth > info->maxDepth)
+      info->maxDepth = depth;
+    info->nLeaves++;
+    return(res);
+  }
+
+  if (size == 2) {
+    hit = 1;
+    if (!info->imgCache ||
+	!(resPart = ImgCacheLookupTable(info, info->imgCache, newVector,
+					NIL(bdd_t)))) {
+      hit = 0;
+      resPart = ImageFast2(info, newVector);
+      if (info->imgCache)
+	ImgCacheInsertTable(info->imgCache, newVector, NIL(bdd_t), resPart);
+    }
+
+    if (info->option->debug) {
+      refResult = ImgImageByHybrid(info, newVector, NIL(mdd_t));
+      assert(mdd_equal(refResult, resPart));
+      mdd_free(refResult);
+    }
+    new_ = mdd_and(res, resPart, 1, 1);
+    if (info->option->verbosity) {
+      size = bdd_size(new_);
+      if (size > info->maxIntermediateSize)
+	info->maxIntermediateSize = size;
+      if (info->option->printBddSize) {
+	fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
+		bdd_size(res), bdd_size(resPart), size);
+      }
+    }
+    mdd_free(res);
+    if (!info->imgCache || hit) {
+      mdd_free(resPart);
+      ImgVectorFree(newVector);
+    }
+    info->averageDepth = (info->averageDepth * (float)info->nLeaves +
+			  (float)depth) / (float)(info->nLeaves + 1);
+    if (depth > info->maxDepth)
+      info->maxDepth = depth;
+    info->nLeaves++;
+    return(new_);
+  }
+
+  if (info->imgCache) {
+    resPart = ImgCacheLookupTable(info, info->imgCache, newVector, NIL(mdd_t));
+    if (resPart) {
+      if (info->option->debug) {
+	refResult = ImgImageByHybrid(info, newVector, NIL(mdd_t));
+	assert(mdd_equal(refResult, resPart));
+	mdd_free(refResult);
+      }
+      new_ = mdd_and(res, resPart, 1, 1);
+      if (info->option->verbosity) {
+	size = bdd_size(new_);
+	if (size > info->maxIntermediateSize)
+	  info->maxIntermediateSize = size;
+	if (info->option->printBddSize) {
+	  fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
+		  bdd_size(res), bdd_size(resPart), size);
+	}
+      }
+      mdd_free(res);
+      mdd_free(resPart);
+      res = new_;
+      ImgVectorFree(newVector);
+      return(res);
+    }
+  }
+
+  /* compute disconnected component and best variable selection */
+  vectorArray = array_alloc(array_t *, 0);
+  varArray = array_alloc(array_t *, 0);
+  nGroups = ImageDecomposeAndChooseSplitVar(info, newVector, NIL(mdd_t), 1,
+					    info->option->outputSplit, 0,
+					    vectorArray, varArray, &product,
+					    NIL(array_t), NIL(array_t *),
+					    NIL(mdd_t *), NIL(mdd_t *));
+  vectorSize = array_n(newVector);
+  if ((!info->imgCache || nGroups <= 1) && !info->option->debug)
+    ImgVectorFree(newVector);
+  if (nGroups == 0) {
+    array_free(vectorArray);
+    array_free(varArray);
+
+    if (info->option->debug) {
+      refResult = ImgImageByHybrid(info, newVector, NIL(mdd_t));
+      assert(mdd_equal(refResult, product));
+      mdd_free(refResult);
+      ImgVectorFree(newVector);
+    }
+
+    new_ = mdd_and(res, product, 1, 1);
+    if (info->option->verbosity) {
+      size = bdd_size(new_);
+      if (size > info->maxIntermediateSize)
+	info->maxIntermediateSize = size;
+      if (info->option->printBddSize) {
+	fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
+		bdd_size(res), bdd_size(product), size);
+      }
+    }
+    mdd_free(res);
+    mdd_free(product);
+    res = new_;
+
+    info->averageDepth = (info->averageDepth * (float)info->nLeaves +
+			  (float)depth) / (float)(info->nLeaves + 1);
+    if (depth > info->maxDepth)
+      info->maxDepth = depth;
+    info->nLeaves++;
+    return(res);
+  } else if (nGroups > 1) {
+    if (info->nDecomps == 0 || depth < info->topDecomp)
+      info->topDecomp = depth;
+    if (info->nDecomps == 0 || vectorSize > info->maxDecomp)
+      info->maxDecomp = vectorSize;
+    info->averageDecomp = (info->averageDecomp * (float)info->nDecomps +
+			  (float)nGroups) / (float)(info->nDecomps + 1);
+    info->nDecomps++;
+  }
+
+  product = mdd_one(info->manager);
+  for (i = 0; i < array_n(vectorArray); i++) {
+    vector = array_fetch(array_t *, vectorArray, i);
+
+    hit = 1;
+    if (!info->imgCache || nGroups == 1 ||
+	!(resPart = ImgCacheLookupTable(info, info->imgCache, vector,
+					NIL(bdd_t)))) {
+      hit = 0;
+      if (info->nIntermediateVars)
+	size = ImgVectorFunctionSize(vector);
+      else
+	size = array_n(vector);
+      if (size == 1) {
+	comp = array_fetch(ImgComponent_t *, vector, 0);
+	if (array_n(vector) > 1)
+	  func = ImgGetComposedFunction(vector);
+	else
+	  func = comp->func;
+	if (bdd_is_tautology(func, 1))
+	  resPart = mdd_dup(comp->var);
+	else if (bdd_is_tautology(func, 0))
+	  resPart = mdd_not(comp->var);
+	else
+	  resPart = mdd_one(info->manager);
+	if (array_n(vector) > 1)
+	  mdd_free(func);
+	info->averageDepth = (info->averageDepth * (float)info->nLeaves +
+				(float)depth) / (float)(info->nLeaves + 1);
+	if (depth > info->maxDepth)
+	  info->maxDepth = depth;
+	info->nLeaves++;
+      } else if (size == 2) {
+	resPart = ImageFast2(info, vector);
+	info->averageDepth = (info->averageDepth * (float)info->nLeaves +
+				(float)depth) / (float)(info->nLeaves + 1);
+	if (depth > info->maxDepth)
+	  info->maxDepth = depth;
+	info->nLeaves++;
+      } else {
+	split = array_fetch(int, varArray, i);
+	comp = array_fetch(ImgComponent_t *, vector, split);
+	constrain = comp->func;
+	resT = ImageByOutputSplit(info, vector, constrain, depth + 1);
+	tmp = mdd_not(constrain);
+	resE = ImageByOutputSplit(info, vector, tmp, depth + 1);
+	mdd_free(tmp);
+  
+	resPart = bdd_ite(comp->var, resT, resE, 1, 1, 1);
+	if (info->option->verbosity) {
+	  size = bdd_size(resPart);
+	  if (size > info->maxIntermediateSize)
+	    info->maxIntermediateSize = size;
+	  if (info->option->printBddSize) {
+	    fprintf(vis_stdout, "** tfm info: bdd_ite(2,%d,%d) = %d\n",
+		    bdd_size(resT), bdd_size(resE), size);
+	  }
+	}
+	mdd_free(resT);
+	mdd_free(resE);
+      }
+      if (info->imgCache)
+	ImgCacheInsertTable(info->imgCache, vector, NIL(bdd_t), resPart);
+    }
+    if (!info->imgCache || hit)
+      ImgVectorFree(vector);
+    new_ = mdd_and(product, resPart, 1, 1);
+    if (info->option->verbosity) {
+      size = bdd_size(new_);
+      if (size > info->maxIntermediateSize)
+	info->maxIntermediateSize = size;
+      if (info->option->printBddSize) {
+	fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
+		bdd_size(product), bdd_size(resPart), size);
+      }
+    }
+    mdd_free(product);
+    if (!info->imgCache || hit)
+      mdd_free(resPart);
+    product = new_;
+  }
+
+  array_free(vectorArray);
+  array_free(varArray);
+
+  if (info->imgCache && nGroups > 1) {
+    ImgCacheInsertTable(info->imgCache, newVector, NIL(mdd_t),
+			mdd_dup(product));
+  }
+
+  if (info->option->debug) {
+    refResult = ImgImageByHybrid(info, newVector, NIL(mdd_t));
+    assert(mdd_equal(refResult, product));
+    mdd_free(refResult);
+    if (!info->imgCache || nGroups == 1)
+      ImgVectorFree(newVector);
+  }
+
+  new_ = mdd_and(res, product, 1, 1);
+  if (info->option->verbosity) {
+    size = bdd_size(new_);
+    if (size > info->maxIntermediateSize)
+      info->maxIntermediateSize = size;
+    if (info->option->printBddSize) {
+      fprintf(vis_stdout, "** tfm info: bdd_and(%d,%d) = %d\n",
+	      bdd_size(res), bdd_size(product), size);
+    }
+  }
+  mdd_free(res);
+  mdd_free(product);
+  res = new_;
+
+  return(res);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Try to decompose function vector and find a splitting variable
+  for each decomposed block.]
+
+  Description [Try to decompose function vector and find a splitting variable
+  for each decomposed block.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+ImageDecomposeAndChooseSplitVar(ImgTfmInfo_t *info, array_t *vector,
+				mdd_t *from, int splitMethod, int split,
+				int piSplitFlag,
+				array_t *vectorArray, array_t *varArray,
+				mdd_t **singles, array_t *relationArray,
+				array_t **newRelationArray,
+				mdd_t **cofactorCube, mdd_t **abstractCube)
+{
+  int			i, j, f, index;
+  int			nGroups, nSingles, nChosen;
+  int			nVars, nFuncs, arraySize;
+  char			*varFlag;
+  int			*funcGroup;
+  int			*varOccur;
+  int			bestVar;
+  int			*stack, size;
+  ImgComponent_t	*comp, *newComp;
+  array_t		*partVector;
+  char			*stackFlag;
+  char			*support;
+  mdd_t			*func;
+  int			*varCost;
+  int			decompose;
+  int			res, constConstrain;
+  mdd_t			*tmp, *cofactor, *abstract, *nsVar;
+  array_t		*tmpRelationArray;
+  char			*intermediateVarFlag;
+  int			*intermediateVarFuncMap;
+
+  if (info->useConstraint && from && splitMethod == 0)
+    decompose = 0;
+  else
+    decompose = 1;
+
+  arraySize = array_n(vector);
+  if (info->nIntermediateVars)
+    nFuncs = ImgVectorFunctionSize(vector);
+  else
+    nFuncs = arraySize;
+  nVars = info->nVars;
+
+  *singles = mdd_one(info->manager);
+  if (relationArray) {
+    cofactor = mdd_one(info->manager);
+    abstract = mdd_one(info->manager);
+  } else {
+    cofactor = NIL(mdd_t);
+    abstract = NIL(mdd_t);
+  }
+
+  if (decompose) {
+    funcGroup = ALLOC(int, arraySize);
+    memset(funcGroup, 0, sizeof(int) * arraySize);
+    varFlag = ALLOC(char, nVars);
+    memset(varFlag, 0, sizeof(char) * nVars);
+    stack = ALLOC(int, arraySize);
+    stackFlag = ALLOC(char, arraySize);
+    memset(stackFlag, 0, sizeof(char) * arraySize);
+    if (arraySize > nFuncs) {
+      intermediateVarFlag = ALLOC(char, nVars);
+      memset(intermediateVarFlag, 0, sizeof(char) * nVars);
+      intermediateVarFuncMap = ALLOC(int, nVars);
+      memset(intermediateVarFuncMap, 0, sizeof(int) * nVars);
+      for (i = 0; i < arraySize; i++) {
+	comp = array_fetch(ImgComponent_t *, vector, i);
+	if (comp->intermediate) {
+	  index = (int)bdd_top_var_id(comp->var);
+	  intermediateVarFlag[index] = 1;
+	  intermediateVarFuncMap[index] = i;
+	}
+      }
+    } else {
+      /* To remove compiler warnings */
+      intermediateVarFlag = NIL(char);
+      intermediateVarFuncMap = NIL(int);
+    }
+  } else {
+    /* To remove compiler warnings */
+    funcGroup = NIL(int);
+    varFlag = NIL(char);
+    stack = NIL(int);
+    stackFlag = NIL(char);
+    intermediateVarFlag = NIL(char);
+    intermediateVarFuncMap = NIL(int);
+  }
+  varOccur = ALLOC(int, nVars);
+  if (splitMethod == 0 && split > 0)
+    varCost = ALLOC(int, nVars);
+  else
+    varCost = NIL(int);
+
+  nGroups = 0;
+  nSingles = 0;
+  nChosen = 0;
+  while (nChosen < nFuncs) {
+    bestVar = -1;
+    memset(varOccur, 0, sizeof(int) * nVars);
+    if (varCost)
+      memset(varCost, 0, sizeof(int) * nVars);
+
+    if (decompose) {
+      size = 0;
+      for (i = 0; i < arraySize; i++) {
+	if (funcGroup[i] == 0) {
+	  stack[0] = i;
+	  size = 1;
+	  stackFlag[i] = 1;
+	  break;
+	}
+      }
+      assert(size == 1);
+  
+      while (size) {
+	size--;
+	f = stack[size];
+	funcGroup[f] = nGroups + 1;
+	comp = array_fetch(ImgComponent_t *, vector, f);
+	nChosen++;
+	if (nChosen == arraySize)
+	  break;
+	support = comp->support;
+	if (comp->intermediate) {
+	  index = (int)bdd_top_var_id(comp->var);
+	  support[index] = 1;
+	}
+	for (i = 0; i < nVars; i++) {
+	  if (!support[i])
+	    continue;
+	  varOccur[i]++;
+	  if (varFlag[i])
+	    continue;
+	  varFlag[i] = 1;
+	  for (j = 0; j < arraySize; j++) {
+	    if (j == f || stackFlag[j])
+	      continue;
+	    comp = array_fetch(ImgComponent_t *, vector, j);
+	    if (arraySize != nFuncs) {
+	      if (intermediateVarFlag[i] && comp->intermediate) {
+		index = (int)bdd_top_var_id(comp->var);
+		if (index == i) {
+		  if (funcGroup[j] == 0) {
+		    stack[size] = j;
+		    size++;
+		    stackFlag[j] = 1;
+		  }
+		  FindIntermediateSupport(vector, comp, nVars, nGroups,
+					  stack, stackFlag, funcGroup, &size,
+					  intermediateVarFlag,
+					  intermediateVarFuncMap);
+		  continue;
+		}
+	      }
+	    }
+	    if (funcGroup[j])
+	      continue;
+	    if (comp->support[i]) {
+	      stack[size] = j;
+	      size++;
+	      stackFlag[j] = 1;
+	    }
+	  }
+	}
+	if (comp->intermediate) {
+	  index = (int)bdd_top_var_id(comp->var);
+	  support[index] = 0;
+	}
+      }
+    } else {
+      for (i = 0; i < arraySize; i++) {
+	comp = array_fetch(ImgComponent_t *, vector, i);
+	support = comp->support;
+	for (j = 0; j < nVars; j++) {
+	  if (support[j])
+	    varOccur[j]++;
+	}
+      }
+      nChosen = nFuncs;
+    }
+
+    nGroups++;
+
+    /* Collect the functions which belong to the current group */
+    partVector = array_alloc(ImgComponent_t *, 0);
+    for (i = 0; i < arraySize; i++) {
+      if (decompose == 0 || funcGroup[i] == nGroups) {
+	comp = array_fetch(ImgComponent_t *, vector, i);
+	newComp = ImgComponentCopy(info, comp);
+	array_insert_last(ImgComponent_t *, partVector, newComp);
+      }
+    }
+    if (arraySize == nFuncs)
+      size = array_n(partVector);
+    else
+      size = ImgVectorFunctionSize(partVector);
+    if (size == 1) {
+      nSingles++;
+      if (size == array_n(partVector)) {
+	comp = array_fetch(ImgComponent_t *, partVector, 0);
+	func = comp->func;
+      } else {
+	comp = ImgGetLatchComponent(partVector);
+	func = ImgGetComposedFunction(partVector);
+      }
+      if (from) {
+	constConstrain = ImgConstConstrain(func, from);
+	if (constConstrain == 1)
+	  res = 1;
+	else if (constConstrain == 0)
+	  res = 0;
+	else
+	  res = 2;
+      } else {
+	if (bdd_is_tautology(func, 1))
+	  res = 1;
+	else if (bdd_is_tautology(func, 0))
+	  res = 0;
+	else
+	  res = 2;
+      }
+      if (size != array_n(partVector))
+	mdd_free(func);
+      if (res == 1) {
+	tmp = *singles;
+	*singles = mdd_and(tmp, comp->var, 1, 1);
+	mdd_free(tmp);
+      } else if (res == 0) {
+	tmp = *singles;
+	*singles = mdd_and(tmp, comp->var, 1, 0);
+	mdd_free(tmp);
+      }
+      if (abstract) {
+	nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+	tmp = abstract;
+	abstract = mdd_and(tmp, nsVar, 1, 1);
+	mdd_free(tmp);
+	mdd_free(nsVar);
+      }
+
+      ImgVectorFree(partVector);
+      continue;
+    }
+
+    array_insert_last(array_t *, vectorArray, partVector);
+
+    if (splitMethod == 0) { /* input splitting */
+      if (decompose) {
+	if (info->option->findDecompVar) {
+	  bestVar = FindDecomposableVariable(info, partVector);
+	  if (bestVar != -1)
+	    split = -1;
+	}
+      } else if (from) {
+	comp = ImgComponentAlloc(info);
+	comp->func = from;
+	ImgComponentGetSupport(comp);
+	for (i = 0; i < nVars; i++) {
+	  if (comp->support[i])
+	    varOccur[i]++;
+	}
+	comp->func = NIL(mdd_t);
+	ImgComponentFree(comp);
+      }
+
+      if (split != -1) {
+	bestVar = ChooseInputSplittingVariable(info, partVector, from,
+			info->option->inputSplit, decompose,
+			info->option->piSplitFlag, varOccur);
+
+      }
+    } else { /* output splitting */
+      bestVar = ChooseOutputSplittingVariable(info, partVector,
+			info->option->outputSplit);
+    }
+    assert(bestVar != -1);
+    array_insert_last(int, varArray, bestVar);
+  }
+
+  if (newRelationArray)
+    *newRelationArray = relationArray;
+  if (cofactorCube && abstractCube) {
+    if (cofactor)
+      *cofactorCube = cofactor;
+    if (abstract)
+      *abstractCube = abstract;
+  } else {
+    if (cofactor) {
+      if (bdd_is_tautology(cofactor, 1))
+	mdd_free(cofactor);
+      else {
+	*newRelationArray = ImgGetCofactoredRelationArray(relationArray,
+							  cofactor);
+	mdd_free(cofactor);
+      }
+    }
+    if (abstract) {
+      if (bdd_is_tautology(abstract, 1))
+	mdd_free(abstract);
+      else {
+	tmpRelationArray = *newRelationArray;
+	*newRelationArray = ImgGetAbstractedRelationArray(info->manager,
+							  tmpRelationArray,
+							  abstract);
+	mdd_free(abstract);
+	if (tmpRelationArray != relationArray)
+	  mdd_array_free(tmpRelationArray);
+      }
+    }
+  }
+
+  if (decompose) {
+    FREE(stackFlag);
+    FREE(stack);
+    FREE(funcGroup);
+    FREE(varFlag);
+    if (arraySize > nFuncs) {
+      FREE(intermediateVarFlag);
+      FREE(intermediateVarFuncMap);
+    }
+  }
+  FREE(varOccur);
+  if (varCost)
+    FREE(varCost);
+  nGroups -= nSingles;
+  return(nGroups);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Fast image computation when function vector contains only two
+  functions.]
+
+  Description [Fast image computation when function vector contains only two
+  functions.]
+
+  SideEffects []
+
+******************************************************************************/
+static mdd_t *
+ImageFast2(ImgTfmInfo_t *info, array_t *vector)
+{
+  mdd_t			*f1, *f2;
+  int			f21n, f21p;
+  mdd_t			*res, *resp, *resn;
+  mdd_t			*i1, *i2;
+  ImgComponent_t	*comp;
+  mdd_t			*refResult;
+  int			i, freeFlag, size;
+  array_t		*varArray, *funcArray;
+
+  assert(ImgVectorFunctionSize(vector) == 2);
+
+  if (info->option->debug)
+    refResult = ImgImageByHybrid(info, vector, NIL(mdd_t));
+  else
+    refResult = NIL(mdd_t);
+
+  if (array_n(vector) == 2) {
+    comp = array_fetch(ImgComponent_t *, vector, 0);
+    f1 = comp->func;
+    i1 = comp->var;
+
+    comp = array_fetch(ImgComponent_t *, vector, 1);
+    f2 = comp->func;
+    i2 = comp->var;
+
+    freeFlag = 0;
+  } else {
+    varArray = array_alloc(mdd_t *, 0);
+    funcArray = array_alloc(mdd_t *, 0);
+
+    i1 = NIL(mdd_t);
+    i2 = NIL(mdd_t);
+    f1 = NIL(mdd_t);
+    f2 = NIL(mdd_t);
+
+    for (i = 0; i < array_n(vector); i++) {
+      comp = array_fetch(ImgComponent_t *, vector, i);
+      if (comp->intermediate) {
+	array_insert_last(mdd_t *, varArray, comp->var);
+	array_insert_last(mdd_t *, funcArray, comp->func);
+	continue;
+      }
+      if (f1) {
+	f2 = comp->func;
+	i2 = comp->var;
+      } else {
+	f1 = comp->func;
+	i1 = comp->var;
+      }
+    }
+
+    f1 = bdd_vector_compose(f1, varArray, funcArray);
+    f2 = bdd_vector_compose(f2, varArray, funcArray);
+    array_free(varArray);
+    array_free(funcArray);
+    freeFlag = 1;
+  }
+
+  ImgCheckConstConstrain(f1, f2, &f21p, &f21n);
+
+  if (f21p == 1)
+    resp = mdd_dup(i2);
+  else if (f21p == 0)
+    resp = mdd_not(i2);
+  else
+    resp = mdd_one(info->manager);
+
+  if (f21n == 1)
+    resn = mdd_dup(i2);
+  else if (f21n == 0)
+    resn = mdd_not(i2);
+  else
+    resn = mdd_one(info->manager);
+
+  /* merge final result */
+  res = bdd_ite(i1, resp, resn, 1, 1, 1);
+  if (info->option->verbosity) {
+    size = bdd_size(res);
+    if (size > info->maxIntermediateSize)
+      info->maxIntermediateSize = size;
+    if (info->option->printBddSize) {
+      fprintf(vis_stdout, "** tfm info: bdd_ite(2,%d,%d) = %d\n",
+		bdd_size(resp), bdd_size(resn), size);
+    }
+  }
+  mdd_free(resp);
+  mdd_free(resn);
+  if (freeFlag) {
+    mdd_free(f1);
+    mdd_free(f2);
+  }
+
+  if (info->option->debug) {
+    assert(mdd_equal(refResult, res));
+    mdd_free(refResult);
+  }
+
+  return(res);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds a decomposable variable (articulation)]
+
+  Description [Finds a decomposable variable (articulation)]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+FindDecomposableVariable(ImgTfmInfo_t *info, array_t *vector)
+{
+  int			i, j, f, split;
+  int			nChosen, index, varId;
+  int			nVars, nFuncs;
+  char			*varFlag;
+  int			*funcGroup;
+  int			*stack, size;
+  ImgComponent_t	*comp;
+  char			*stackFlag;
+  char			*support;
+  int			arraySize;
+  char			*intermediateVarFlag;
+  int			*intermediateVarFuncMap;
+
+  arraySize = array_n(vector);
+  if (info->nIntermediateVars)
+    nFuncs = ImgVectorFunctionSize(vector);
+  else
+    nFuncs = arraySize;
+  nVars = info->nVars;
+
+  funcGroup = ALLOC(int, arraySize);
+  varFlag = ALLOC(char, nVars);
+  stack = ALLOC(int, arraySize);
+  stackFlag = ALLOC(char, arraySize);
+
+  if (arraySize > nFuncs) {
+    intermediateVarFlag = ALLOC(char, nVars);
+    memset(intermediateVarFlag, 0, sizeof(char) * nVars);
+    intermediateVarFuncMap = ALLOC(int, nVars);
+    memset(intermediateVarFuncMap, 0, sizeof(int) * nVars);
+    for (i = 0; i < arraySize; i++) {
+      comp = array_fetch(ImgComponent_t *, vector, i);
+      if (comp->intermediate) {
+	index = (int)bdd_top_var_id(comp->var);
+	intermediateVarFlag[index] = 1;
+	intermediateVarFuncMap[index] = i;
+      }
+    }
+  } else {
+    intermediateVarFlag = NIL(char);
+    intermediateVarFuncMap = NIL(int);
+  }
+
+  varId = -1;
+  for (split = 0; split < nVars; split++) {
+    if (intermediateVarFlag[split])
+      continue;
+
+    memset(funcGroup, 0, sizeof(int) * arraySize);
+    memset(varFlag, 0, sizeof(char) * nVars);
+    memset(stackFlag, 0, sizeof(char) * arraySize);
+
+    varFlag[split] = 1;
+    nChosen = 0;
+  
+    stack[0] = 0;
+    size = 1;
+    stackFlag[0] = 1;
+  
+    while (size) {
+      size--;
+      f = stack[size];
+      funcGroup[f] = 1;
+      comp = array_fetch(ImgComponent_t *, vector, f);
+      nChosen++;
+      if (nChosen == arraySize)
+	break;
+      support = comp->support;
+      if (comp->intermediate) {
+	index = (int)bdd_top_var_id(comp->var);
+	support[index] = 1;
+      }
+      for (i = 0; i < nVars; i++) {
+	if (!support[i])
+	  continue;
+	if (varFlag[i])
+	  continue;
+	varFlag[i] = 1;
+	for (j = 0; j < nFuncs; j++) {
+	  if (j == f || stackFlag[j])
+	    continue;
+	  comp = array_fetch(ImgComponent_t *, vector, j);
+	  if (arraySize != nFuncs) {
+	    if (intermediateVarFlag[i] && comp->intermediate) {
+	      index = (int)bdd_top_var_id(comp->var);
+	      if (index == i) {
+		if (funcGroup[j] == 0) {
+		  stack[size] = j;
+		  size++;
+		  stackFlag[j] = 1;
+		}
+		FindIntermediateSupport(vector, comp, nVars, 0,
+					stack, stackFlag, funcGroup, &size,
+					intermediateVarFlag,
+					intermediateVarFuncMap);
+		continue;
+	      }
+	    }
+	  }
+	  if (funcGroup[j])
+	    continue;
+	  if (comp->support[i]) {
+	    stack[size] = j;
+	    size++;
+	    stackFlag[j] = 1;
+	  }
+	}
+      }
+      if (comp->intermediate) {
+	index = (int)bdd_top_var_id(comp->var);
+	support[index] = 0;
+      }
+    }
+
+    if (nChosen < nFuncs) {
+      varId = split;
+      break;
+    }
+  }
+
+  FREE(stackFlag);
+  FREE(stack);
+  FREE(funcGroup);
+  FREE(varFlag);
+  if (arraySize > nFuncs) {
+    FREE(intermediateVarFlag);
+    FREE(intermediateVarFuncMap);
+  }
+
+  return(varId);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks the support of image.]
+
+  Description [Checks the support of image.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+TfmCheckImageValidity(ImgTfmInfo_t *info, mdd_t *image)
+{
+  int		i, id;
+  array_t	*supportIds;
+  int		status = 1;
+
+  supportIds = mdd_get_bdd_support_ids(info->manager, image);
+  for (i = 0; i < array_n(supportIds); i++) {
+    id = array_fetch(int, supportIds, i);
+    if (st_lookup(info->quantifyVarsTable, (char *)(long)id, NIL(char *))) {
+      fprintf(vis_stderr,
+	      "** tfm error: image contains a primary input variable (%d)\n",
+	      id);
+      status = 0;
+    }
+    if (st_lookup(info->rangeVarsTable, (char *)(long)id, NIL(char *))) {
+      fprintf(vis_stderr,
+	      "** tfm error: image contains a range variable (%d)\n", id);
+      status = 0;
+    }
+    if (info->intermediateVarsTable &&
+	st_lookup(info->intermediateVarsTable, (char *)(long)id, NIL(char *))) {
+      fprintf(vis_stderr,
+	      "** tfm error: image contains an intermediate variable (%d)\n",
+	      id);
+      status = 0;
+    }
+  }
+  array_free(supportIds);
+  return(status);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds all other fanin intermediate functions of a given
+  intermediate function.]
+
+  Description [Finds all other fanin intermediate functions of a given 
+  intermediate function. Adds the only intermediate functions are not in
+  the stack. Updates the stack information.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+FindIntermediateSupport(array_t *vector, ImgComponent_t *comp,
+			int nVars, int nGroups,
+			int *stack, char *stackFlag, int *funcGroup, int *size,
+			char *intermediateVarFlag, int *intermediateVarFuncMap)
+{
+  int			i, f;
+  ImgComponent_t	*intermediateComp;
+
+  for (i = 0; i < nVars; i++) {
+    if (comp->support[i]) {
+      if (intermediateVarFlag[i]) {
+	f = intermediateVarFuncMap[i];
+	if (stackFlag[f] || funcGroup[f] == nGroups + 1)
+	  continue;
+	stack[*size] = f;
+	(*size)++;
+	stackFlag[f] = 1;
+
+	intermediateComp = array_fetch(ImgComponent_t *, vector, f);
+	FindIntermediateSupport(vector, intermediateComp, nVars, nGroups,
+				stack, stackFlag, funcGroup, size,
+				intermediateVarFlag, intermediateVarFuncMap);
+      }
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Print the information of the decomposition.]
+
+  Description [Print the information of the decomposition.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+PrintVectorDecomposition(ImgTfmInfo_t *info, array_t *vectorArray,
+			 array_t *varArray)
+{
+  int			i, j, n;
+  int			var, index;
+  ImgComponent_t	*comp;
+  array_t		*vector;
+
+  fprintf(vis_stdout, "** tfm info: vector decomposition\n");
+  n = array_n(vectorArray);
+  for (i = 0; i < n; i++) {
+    vector = array_fetch(array_t *, vectorArray, i);
+    var = array_fetch(int, varArray, i);
+    fprintf(vis_stdout, "Group[%d] : num = %d, split = %d\n",
+	    i, array_n(vector), var);
+    for (j = 0; j < array_n(vector); j++) {
+      comp = array_fetch(ImgComponent_t *, vector, j);
+      index = (int)bdd_top_var_id(comp->var);
+      fprintf(vis_stdout, " %d", index);
+    }
+    fprintf(vis_stdout, "\n");
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks the splitting variable is valid and chooses new one
+  if not valid.]
+
+  Description [Checks the splitting variable is already quantified from
+  the transition relation. If yes, chooses new splitting variable. If there
+  is no valid splitting variable, returns -1.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CheckIfValidSplitOrGetNew(ImgTfmInfo_t *info, int split, array_t *vector,
+			array_t *relationArray, mdd_t *from)
+{
+  int newSplit = split;
+  int i, j, nVars;
+  ImgComponent_t *comp;
+  char *support;
+  int *varOccur;
+  int decompose;
+
+  nVars = info->nVars;
+  support = ALLOC(char, sizeof(char) * nVars);
+  memset(support, 0, sizeof(char) * nVars);
+
+  comp = ImgComponentAlloc(info);
+  for (i = 0; i < array_n(relationArray); i++) {
+    comp->func = array_fetch(mdd_t *, relationArray, i);;
+    ImgSupportClear(info, comp->support);
+    ImgComponentGetSupport(comp);
+    for (j = 0; j < nVars; j++) {
+      if (comp->support[j]) {
+	if (j == split) {
+	  comp->func = NIL(mdd_t);
+	  ImgComponentFree(comp);
+	  FREE(support);
+	  return(split);
+	}
+	support[j] = 1;
+      }
+    }
+  }
+
+  comp->func = NIL(mdd_t);
+  ImgComponentFree(comp);
+
+  if (info->useConstraint && from)
+    decompose = 0;
+  else
+    decompose = 1;
+
+  varOccur = ALLOC(int, nVars);
+  memset(varOccur, 0, sizeof(int) * nVars);
+
+  if (from) {
+    comp = ImgComponentAlloc(info);
+    comp->func = from;
+    ImgComponentGetSupport(comp);
+    for (i = 0; i < nVars; i++) {
+      if (comp->support[i])
+	varOccur[i]++;
+    }
+    comp->func = NIL(mdd_t);
+    ImgComponentFree(comp);
+  }
+
+  FREE(support);
+
+  newSplit = ChooseInputSplittingVariable(info, vector, from,
+		info->option->inputSplit, decompose,
+		info->option->piSplitFlag, varOccur);
+
+  FREE(varOccur);
+
+  return(newSplit);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds a splitting variable for input splitting.]
+
+  Description [Finds a splitting variable for input splitting.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+ChooseInputSplittingVariable(ImgTfmInfo_t *info, array_t *vector, mdd_t *from,
+		int splitMethod, int decompose, int piSplitFlag, int *varOccur)
+{
+  int nVars = info->nVars;
+  int bestVar = -1;
+  int secondBestVar = -1;
+  int bestCost, newCost;
+  int bestOccur, tieCount;
+  int secondBestOccur, secondTieCount;
+  int i, j;
+  ImgComponent_t *comp;
+  mdd_t *var, *varNot, *pcFunc, *ncFunc;
+  int *varCost;
+  int size = ImgVectorFunctionSize(vector);
+
+  if (info->option->inputSplit > 0) {
+    varCost = ALLOC(int, nVars);
+    memset(varCost, 0, sizeof(int) * nVars);
+  } else
+    varCost = NIL(int);
+
+  switch (splitMethod) {
+  case 0:
+    /* Find the most frequently occurred variable */
+    bestOccur = 0;
+    tieCount = 0;
+    secondBestOccur = 0;
+    secondTieCount = 0;
+  
+    for (i = 0; i < nVars; i++) {
+      if (varOccur[i] == 0)
+	continue;
+      if (piSplitFlag == 0) {
+	if (st_lookup(info->quantifyVarsTable, (char *)(long)i,
+		      NIL(char *))) {
+	  if ((bestOccur == 0 && secondBestOccur == 0) ||
+	      (varOccur[i] > bestOccur && varOccur[i] > secondBestOccur)) {
+	    secondBestOccur = varOccur[i];
+	    secondBestVar = i;
+	    secondTieCount = 1;
+	  } else if (secondBestOccur > bestOccur &&
+		     varOccur[i] == secondBestOccur) {
+	    secondTieCount++;
+	    if (info->option->tieBreakMode == 0 &&
+		bdd_get_level_from_id(info->manager, i) <
+		bdd_get_level_from_id(info->manager, secondBestVar)) {
+	      secondBestVar = i;
+	    }
+	  }
+	  continue;
+	}
+      }
+      if (size < array_n(vector) &&
+	  st_lookup(info->intermediateVarsTable, (char *)(long)i,
+		    NIL(char *))) {
+	continue;
+      }
+      if (bestOccur == 0 || varOccur[i] > bestOccur) {
+	bestOccur = varOccur[i];
+	bestVar = i;
+	tieCount = 1;
+      } else if (varOccur[i] == bestOccur) {
+	tieCount++;
+	if (info->option->tieBreakMode == 0 &&
+	    bdd_get_level_from_id(info->manager, i) <
+	    bdd_get_level_from_id(info->manager, bestVar)) {
+	  bestVar = i;
+	}
+      }
+    }
+
+    if (piSplitFlag == 0 && bestVar == -1) {
+      bestVar = secondBestVar;
+      bestOccur = secondBestOccur;
+      tieCount = secondTieCount;
+    }
+  
+    if (info->option->tieBreakMode == 1 && tieCount > 1) {
+      bestCost = IMG_TF_MAX_INT;
+      for (i = bestVar; i < nVars; i++) {
+	if (varOccur[i] != bestOccur)
+	  continue;
+	if (size < array_n(vector) &&
+	    st_lookup(info->intermediateVarsTable, (char *)(long)i,
+		      NIL(char *))) {
+	  continue;
+	}
+	var = bdd_var_with_index(info->manager, i);
+	newCost = 0;
+	for (j = 0; j < array_n(vector); j++) {
+	  comp = array_fetch(ImgComponent_t *, vector, j);
+	  newCost += bdd_estimate_cofactor(comp->func, var, 1);
+	  newCost += bdd_estimate_cofactor(comp->func, var, 0);
+	}
+	if (decompose == 0) {
+	  newCost += bdd_estimate_cofactor(from, var, 1);
+	  newCost += bdd_estimate_cofactor(from, var, 0);
+	}
+	mdd_free(var);
+  
+	if (newCost < bestCost) {
+	  bestVar = i;
+	  bestCost = newCost;
+	} else if (newCost == bestCost) {
+	  if (bdd_get_level_from_id(info->manager, i) <
+	      bdd_get_level_from_id(info->manager, bestVar)) {
+	    bestVar = i;
+	  }
+	}
+      }
+    }
+    break;
+  case 1:
+    /* Find the variable which makes the smallest support after splitting */
+    bestCost = IMG_TF_MAX_INT;
+    for (i = 0; i < nVars; i++) {
+      if (varOccur[i] == 0)
+	continue;
+      if (size < array_n(vector) &&
+	  st_lookup(info->intermediateVarsTable, (char *)(long)i,
+		    NIL(char *))) {
+	continue;
+      }
+      var = bdd_var_with_index(info->manager, i);
+      varNot = mdd_not(var);
+      for (j = 0; j < array_n(vector); j++) {
+	comp = array_fetch(ImgComponent_t *, vector, j);
+	pcFunc = bdd_cofactor(comp->func, var);
+	varCost[i] += ImgCountBddSupports(pcFunc);
+	mdd_free(pcFunc);
+	ncFunc = bdd_cofactor(comp->func, varNot);
+	varCost[i] += ImgCountBddSupports(ncFunc);
+	mdd_free(ncFunc);
+      }
+      if (decompose == 0) {
+	pcFunc = bdd_cofactor(from, var);
+	varCost[i] += ImgCountBddSupports(pcFunc);
+	mdd_free(pcFunc);
+	ncFunc = bdd_cofactor(from, varNot);
+	varCost[i] += ImgCountBddSupports(ncFunc);
+	mdd_free(ncFunc);
+      }
+      mdd_free(var);
+      mdd_free(varNot);
+  
+      if (varCost[i] < bestCost) {
+	bestCost = varCost[i];
+	bestVar = i;
+      } else if (varCost[i] == bestCost) {
+	if (varOccur[i] < varOccur[bestVar]) {
+	  bestVar = i;
+	} else if (varOccur[i] == varOccur[bestVar]) {
+	  if (bdd_get_level_from_id(info->manager, i) <
+	      bdd_get_level_from_id(info->manager, bestVar)) {
+	    bestVar = i;
+	  }
+	}
+      }
+    }
+    break;
+  case 2:
+    /* Find the variable which makes the smallest BDDs of all functions
+       after splitting */
+    bestCost = IMG_TF_MAX_INT;
+    for (i = 0; i < nVars; i++) {
+      if (varOccur[i] == 0)
+	continue;
+      if (size < array_n(vector) &&
+	  st_lookup(info->intermediateVarsTable, (char *)(long)i,
+		    NIL(char *))) {
+	continue;
+      }
+      var = bdd_var_with_index(info->manager, i);
+      for (j = 0; j < array_n(vector); j++) {
+	comp = array_fetch(ImgComponent_t *, vector, j);
+	varCost[i] += bdd_estimate_cofactor(comp->func, var, 1);
+	varCost[i] += bdd_estimate_cofactor(comp->func, var, 0);
+      }
+      if (decompose == 0) {
+	varCost[i] += bdd_estimate_cofactor(from, var, 1);
+	varCost[i] += bdd_estimate_cofactor(from, var, 0);
+      }
+      mdd_free(var);
+  
+      if (varCost[i] < bestCost) {
+	bestCost = varCost[i];
+	bestVar = i;
+      } else if (varCost[i] == bestCost) {
+	if (varOccur[i] < varOccur[bestVar]) {
+	  bestVar = i;
+	} else if (varOccur[i] == varOccur[bestVar]) {
+	  if (bdd_get_level_from_id(info->manager, i) <
+	      bdd_get_level_from_id(info->manager, bestVar)) {
+	    bestVar = i;
+	  }
+	}
+      }
+    }
+    break;
+  case 3: /* top variable */
+    for (i = 0; i < nVars; i++) {
+      if (varOccur[i] == 0)
+	continue;
+      if (size < array_n(vector) &&
+	  st_lookup(info->intermediateVarsTable, (char *)(long)i,
+		    NIL(char *))) {
+	continue;
+      }
+      if (piSplitFlag == 0) {
+	if (st_lookup(info->quantifyVarsTable, (char *)(long)i,
+		      NIL(char *))) {
+	  if (bestVar == -1 && secondBestVar == -1)
+	    secondBestVar = i;
+	  else if (bdd_get_level_from_id(info->manager, i) <
+		   bdd_get_level_from_id(info->manager, secondBestVar)) {
+	    secondBestVar = i;
+	  }
+	  continue;
+	}
+      }
+      if (bestVar == -1 ||
+	  bdd_get_level_from_id(info->manager, i) <
+	  bdd_get_level_from_id(info->manager, bestVar)) {
+	bestVar = i;
+      }
+    }
+
+    if (piSplitFlag == 0 && bestVar == -1)
+      bestVar = secondBestVar;
+    break;
+  default:
+    break;
+  }
+
+  if (varCost)
+    FREE(varCost);
+
+  return(bestVar);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds a splitting variable for output splitting.]
+
+  Description [Finds a splitting variable for output splitting.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+ChooseOutputSplittingVariable(ImgTfmInfo_t *info, array_t *vector,
+			int splitMethod)
+{
+  int bestVar = -1;
+  int bestCost, newCost;
+  int i;
+  ImgComponent_t *comp;
+  int size = ImgVectorFunctionSize(vector);
+  int index;
+
+  switch (splitMethod) {
+  case 0: /* smallest */
+    bestCost = IMG_TF_MAX_INT;
+    for (i = 0; i < array_n(vector); i++) {
+      comp = array_fetch(ImgComponent_t *, vector, i);
+      if (size < array_n(vector) &&
+          st_lookup(info->intermediateVarsTable,
+                    (char *)(long)bdd_top_var_id(comp->var), NIL(char *))) {
+        continue;
+      }
+      newCost = bdd_size(comp->func);
+      if (newCost < bestCost) {
+        bestVar = i;
+        bestCost = newCost;
+      }
+    }
+    break;
+  case 1: /* largest */
+    bestCost = 0;
+    for (i = 0; i < array_n(vector); i++) {
+      comp = array_fetch(ImgComponent_t *, vector, i);
+      if (size < array_n(vector) &&
+          st_lookup(info->intermediateVarsTable,
+                    (char *)(long)bdd_top_var_id(comp->var), NIL(char *))) {
+        continue;
+      }
+      newCost = bdd_size(comp->func);
+      if (newCost > bestCost) {
+        bestVar = i;
+        bestCost = newCost;
+      }
+    }
+    break;
+  case 2: /* top variable */
+  default:
+    comp = array_fetch(ImgComponent_t *, vector, 0);
+    bestVar = (int)bdd_top_var_id(comp->var);
+    for (i = 0; i < array_n(vector); i++) {
+      comp = array_fetch(ImgComponent_t *, vector, i);
+      index = (int)bdd_top_var_id(comp->var);
+      if (size < array_n(vector) &&
+          st_lookup(info->intermediateVarsTable, (char *)(long)index,
+                    NIL(char *))) {
+        continue;
+      }
+      if (bestVar == -1 ||
+          bdd_get_level_from_id(info->manager, index) <
+          bdd_get_level_from_id(info->manager, bestVar)) {
+        bestVar = i;
+      }
+    }
+    break;
+  }
+
+  return(bestVar);
+}
Index: vis_dev/vis-2.3/src/img/imgTfmUtil.c
===================================================================
--- vis_dev/vis-2.3/src/img/imgTfmUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/img/imgTfmUtil.c	(revision 14)
@@ -0,0 +1,2208 @@
+/**CFile***********************************************************************
+
+  FileName    [imgTfmUtil.c]
+
+  PackageName [img]
+
+  Synopsis    [Routines for image computation using transition function method.]
+
+  SeeAlso     []
+
+  Author      [In-Ho Moon]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF COLORADO BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  COLORADO HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF COLORADO SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF COLORADO HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+#include "imgInt.h"
+
+static char rcsid[] UNUSED = "$Id: imgTfmUtil.c,v 1.23 2005/04/23 14:30:55 jinh Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+static	double	*signatures; /* used in finding dependent variables */
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int SignatureCompare(int *ptrX, int *ptrY);
+static int CompareBddPointer(const void *e1, const void *e2);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Constrains a function vector with respect to a constraint.]
+
+  Description [Constrains a function vector with respect to a constraint.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgVectorConstrain(ImgTfmInfo_t *info, array_t *vector, mdd_t *constraint,
+		   array_t *relationArray, array_t **newVector, mdd_t **cube,
+		   array_t **newRelationArray, mdd_t **cofactorCube,
+		   mdd_t **abstractCube, boolean singleVarFlag)
+{
+  mdd_t			*new_, *res, *old, *tmp;
+  ImgComponent_t	*comp, *comp1;
+  array_t		*vector1;
+  int			i, index;
+  int			dynStatus, dynOff;
+  bdd_reorder_type_t	dynMethod;
+  st_table		*equivTable;
+  int			*ptr, *regularPtr;
+  int			n, pos;
+  mdd_t			*cofactor, *abstract, *nsVar, *constIntermediate;
+  array_t		*tmpRelationArray;
+  int			size;
+
+  old = mdd_one(info->manager);
+  vector1 = array_alloc(ImgComponent_t *, 0);
+  dynStatus = 0;
+
+  if (singleVarFlag)
+    dynOff = 0;
+  else
+    dynOff = 1;
+  if (dynOff) {
+    dynStatus = bdd_reordering_status(info->manager, &dynMethod);
+    if (dynStatus != 0)
+      bdd_dynamic_reordering_disable(info->manager);
+  }
+
+  if (relationArray) {
+    cofactor = mdd_one(info->manager);
+    abstract = mdd_one(info->manager);
+  } else {
+    cofactor = NIL(mdd_t);
+    abstract = NIL(mdd_t);
+  }
+
+  if (info->nIntermediateVars) {
+    size = ImgVectorFunctionSize(vector);
+    if (size == array_n(vector))
+      constIntermediate = NIL(mdd_t);
+    else
+      constIntermediate = mdd_one(info->manager);
+  } else
+    constIntermediate = NIL(mdd_t);
+
+  n = 0;
+  equivTable = st_init_table(st_ptrcmp, st_ptrhash);
+  index = (int)bdd_top_var_id(constraint);
+  for (i = 0; i < array_n(vector); i++) {
+    comp = array_fetch(ImgComponent_t *, vector, i);
+    if (!bdd_is_tautology(constraint, 1)) {
+      if (singleVarFlag) {
+	if (comp->support[index])
+	  res = bdd_cofactor(comp->func, constraint);
+	else
+	  res = mdd_dup(comp->func);
+      } else
+	res = bdd_cofactor(comp->func, constraint);
+    } else
+      res = mdd_dup(comp->func);
+    if (bdd_is_tautology(res, 1)) {
+      if (comp->intermediate) {
+	tmp = constIntermediate;
+	constIntermediate = mdd_and(tmp, comp->var, 1, 1);
+	mdd_free(tmp);
+	mdd_free(res);
+	continue;
+      }
+      new_ = mdd_and(comp->var, old, 1, 1);
+      mdd_free(old);
+      mdd_free(res);
+      old = new_;
+      if (cofactor) {
+	nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+	tmp = cofactor;
+	cofactor = mdd_and(tmp, nsVar, 1, 1);
+	mdd_free(tmp);
+	mdd_free(nsVar);
+      }
+    } else if (bdd_is_tautology(res, 0)) {
+      if (comp->intermediate) {
+	tmp = constIntermediate;
+	constIntermediate = mdd_and(tmp, comp->var, 1, 0);
+	mdd_free(tmp);
+	mdd_free(res);
+	continue;
+      }
+      new_ = mdd_and(comp->var, old, 0, 1);
+      mdd_free(old);
+      mdd_free(res);
+      old = new_;
+      if (cofactor) {
+	nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+	tmp = cofactor;
+	cofactor = mdd_and(tmp, nsVar, 1, 0);
+	mdd_free(tmp);
+	mdd_free(nsVar);
+      }
+    } else {
+      if (comp->intermediate) {
+	comp1 = ImgComponentAlloc(info);
+	comp1->var = mdd_dup(comp->var);
+	comp1->func = res;
+	comp1->intermediate = 1;
+	if (mdd_equal(res, comp->func))
+	  ImgSupportCopy(info, comp1->support, comp->support);
+	else
+	  ImgComponentGetSupport(comp1);
+	array_insert_last(ImgComponent_t *, vector1, comp1);
+	n++;
+	continue;
+      }
+      ptr = (int *)bdd_pointer(res);
+      regularPtr = (int *)((unsigned long)ptr & ~01);
+      if (st_lookup_int(equivTable, (char *)regularPtr, &pos)) {
+	comp1 = array_fetch(ImgComponent_t *, vector1, pos);
+	if (mdd_equal(res, comp1->func))
+	  tmp = mdd_xnor(comp->var, comp1->var);
+	else
+	  tmp = mdd_xor(comp->var, comp1->var);
+	new_ = mdd_and(tmp, old, 1, 1);
+	mdd_free(tmp);
+	mdd_free(old);
+	mdd_free(res);
+	old = new_;
+	if (abstract) {
+	  nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+	  tmp = abstract;
+	  abstract = mdd_and(tmp, nsVar, 1, 1);
+	  mdd_free(tmp);
+	  mdd_free(nsVar);
+	}
+      } else {
+	comp1 = ImgComponentAlloc(info);
+	comp1->var = mdd_dup(comp->var);
+	comp1->func = res;
+	if (mdd_equal(res, comp->func))
+	  ImgSupportCopy(info, comp1->support, comp->support);
+	else
+	  ImgComponentGetSupport(comp1);
+	array_insert_last(ImgComponent_t *, vector1, comp1);
+	st_insert(equivTable, (char *)regularPtr, (char *)(long)n);
+	n++;
+      }
+    }
+  }
+  st_free_table(equivTable);
+
+  if (dynOff && dynStatus != 0) {
+    bdd_dynamic_reordering(info->manager, dynMethod,
+			   BDD_REORDER_VERBOSITY_DEFAULT);
+  }
+
+  if (constIntermediate) {
+    if (!bdd_is_tautology(constIntermediate, 1)) {
+      mdd_t	*tmpCofactor, *tmpAbstract;
+
+      if (relationArray) {
+	vector1 = ImgComposeConstIntermediateVars(info, vector1,
+						  constIntermediate,
+						  &tmpCofactor, &tmpAbstract,
+						  &old, NIL(mdd_t *));
+	if (!bdd_is_tautology(tmpCofactor, 1)) {
+	  tmp = cofactor;
+	  cofactor = mdd_and(tmp, tmpCofactor, 1, 1);
+	  mdd_free(tmp);
+	}
+	mdd_free(tmpCofactor);
+	if (!bdd_is_tautology(tmpAbstract, 1)) {
+	  tmp = abstract;
+	  abstract = mdd_and(tmp, tmpAbstract, 1, 1);
+	  mdd_free(tmp);
+	}
+	mdd_free(tmpAbstract);
+	tmp = cofactor;
+	cofactor = mdd_and(tmp, constIntermediate, 1, 1);
+	mdd_free(tmp);
+      } else {
+	vector1 = ImgComposeConstIntermediateVars(info, vector1,
+						  constIntermediate,
+						  NIL(mdd_t *), NIL(mdd_t *),
+						  &old, NIL(mdd_t *));
+      }
+    }
+    mdd_free(constIntermediate);
+  }
+
+  if (info->option->sortVectorFlag)
+    array_sort(vector1, CompareBddPointer);
+
+  if (relationArray && newRelationArray) {
+    if (singleVarFlag) {
+      *newRelationArray = relationArray;
+      tmp = cofactor;
+      cofactor = mdd_and(tmp, constraint, 1, 1);
+      mdd_free(tmp);
+    } else
+      *newRelationArray = ImgGetConstrainedRelationArray(info, relationArray,
+							 constraint);
+  }
+  if (cofactorCube && abstractCube) {
+    if (cofactor)
+      *cofactorCube = cofactor;
+    if (abstract)
+      *abstractCube = abstract;
+  } else {
+    if (cofactor) {
+      if (bdd_is_tautology(cofactor, 1))
+	mdd_free(cofactor);
+      else {
+	tmpRelationArray = *newRelationArray;
+	*newRelationArray = ImgGetCofactoredRelationArray(tmpRelationArray,
+							  cofactor);
+	mdd_free(cofactor);
+	if (tmpRelationArray != relationArray)
+	  mdd_array_free(tmpRelationArray);
+      }
+    }
+    if (abstract) {
+      if (bdd_is_tautology(abstract, 1))
+	mdd_free(abstract);
+      else {
+	tmpRelationArray = *newRelationArray;
+	*newRelationArray = ImgGetAbstractedRelationArray(info->manager,
+							  tmpRelationArray,
+							abstract);
+	mdd_free(abstract);
+	if (tmpRelationArray != relationArray)
+	  mdd_array_free(tmpRelationArray);
+      }
+    }
+  }
+
+  *newVector = vector1;
+  *cube = old;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Minimizes a function vector and a from set with respect to an
+  essential cube.]
+
+  Description [Minimizes a function vector and a from set with respect to an
+  essential cube. This function is called during eliminating dependent
+  variables.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+ImgVectorMinimize(ImgTfmInfo_t *info, array_t *vector, mdd_t *constraint,
+		  mdd_t *from, array_t *relationArray, array_t **newVector,
+		  mdd_t **cube, array_t **newRelationArray,
+		  mdd_t **cofactorCube, mdd_t **abstractCube)
+{
+  mdd_t			*new_, *res, *old, *tmp, *newFrom;
+  ImgComponent_t	*comp, *comp1;
+  array_t		*vector1;
+  int			i;
+  st_table		*equivTable;
+  int			*ptr, *regularPtr;
+  int			n, pos;
+  mdd_t			*cofactor, *abstract, *nsVar, *constIntermediate;
+  array_t		*tmpRelationArray;
+  int			size;
+
+  if (from)
+    newFrom = mdd_dup(from);
+  else
+    newFrom = NIL(mdd_t);
+  if (cube)
+    old = mdd_one(info->manager);
+  else
+    old = NIL(mdd_t);
+  assert(newVector)
+  vector1 = array_alloc(ImgComponent_t *, 0);
+
+  if (relationArray) {
+    cofactor = mdd_one(info->manager);
+    abstract = mdd_one(info->manager);
+  } else {
+    cofactor = NIL(mdd_t);
+    abstract = NIL(mdd_t);
+  }
+
+  if (info->nIntermediateVars) {
+    size = ImgVectorFunctionSize(vector);
+    if (size == array_n(vector))
+      constIntermediate = NIL(mdd_t);
+    else
+      constIntermediate = mdd_one(info->manager);
+  } else
+    constIntermediate = NIL(mdd_t);
+
+  n = 0;
+  equivTable = st_init_table(st_ptrcmp, st_ptrhash);
+  for (i = 0; i < array_n(vector); i++) {
+    comp = array_fetch(ImgComponent_t *, vector, i);
+    res = bdd_minimize(comp->func, constraint);
+    if (bdd_is_tautology(res, 1)) {
+      if (comp->intermediate) {
+	tmp = constIntermediate;
+	constIntermediate = mdd_and(tmp, comp->var, 1, 1);
+	mdd_free(tmp);
+	mdd_free(res);
+	continue;
+      }
+      if (newFrom) {
+	tmp = newFrom;
+	newFrom = bdd_cofactor(tmp, comp->var);
+	mdd_free(tmp);
+      }
+      if (old) {
+	new_ = mdd_and(comp->var, old, 1, 1);
+	mdd_free(old);
+	mdd_free(res);
+	old = new_;
+      }
+      if (cofactor) {
+	nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+	tmp = cofactor;
+	cofactor = mdd_and(tmp, nsVar, 1, 1);
+	mdd_free(tmp);
+	mdd_free(nsVar);
+      }
+    } else if (bdd_is_tautology(res, 0)) {
+      if (comp->intermediate) {
+	tmp = constIntermediate;
+	constIntermediate = mdd_and(tmp, comp->var, 1, 0);
+	mdd_free(tmp);
+	mdd_free(res);
+	continue;
+      }
+      if (newFrom) {
+	tmp = newFrom;
+	new_ = mdd_not(comp->var);
+	newFrom = bdd_cofactor(tmp, new_);
+	mdd_free(tmp);
+	mdd_free(new_);
+      }
+      if (old) {
+	new_ = mdd_and(comp->var, old, 0, 1);
+	mdd_free(old);
+	mdd_free(res);
+	old = new_;
+      }
+      if (cofactor) {
+	nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+	tmp = cofactor;
+	cofactor = mdd_and(tmp, nsVar, 1, 0);
+	mdd_free(tmp);
+	mdd_free(nsVar);
+      }
+    } else {
+      if (comp->intermediate) {
+	comp1 = ImgComponentAlloc(info);
+	comp1->var = mdd_dup(comp->var);
+	comp1->func = res;
+	comp1->intermediate = 1;
+	if (mdd_equal(res, comp->func))
+	  ImgSupportCopy(info, comp1->support, comp->support);
+	else
+	  ImgComponentGetSupport(comp1);
+	array_insert_last(ImgComponent_t *, vector1, comp1);
+	n++;
+	continue;
+      }
+      ptr = (int *)bdd_pointer(res);
+      regularPtr = (int *)((unsigned long)ptr & ~01);
+      if (st_lookup_int(equivTable, (char *)regularPtr, &pos)) {
+	comp1 = array_fetch(ImgComponent_t *, vector1, pos);
+	if (newFrom) {
+	  if (mdd_equal(res, comp1->func)) {
+	    tmp = newFrom;
+	    newFrom = bdd_compose(tmp, comp->var, comp1->var);
+	    mdd_free(tmp);
+	  } else {
+	    tmp = newFrom;
+	    new_ = mdd_not(comp1->var);
+	    newFrom = bdd_compose(tmp, comp->var, new_);
+	    mdd_free(tmp);
+	    mdd_free(new_);
+	  }
+	}
+	if (old) {
+	  if (mdd_equal(res, comp1->func))
+	    tmp = mdd_xnor(comp->var, comp1->var);
+	  else
+	    tmp = mdd_xor(comp->var, comp1->var);
+	  new_ = mdd_and(tmp, old, 1, 1);
+	  mdd_free(tmp);
+	  mdd_free(old);
+	  old = new_;
+	}
+	mdd_free(res);
+	if (abstract) {
+	  nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+	  tmp = abstract;
+	  abstract = mdd_and(tmp, nsVar, 1, 1);
+	  mdd_free(tmp);
+	  mdd_free(nsVar);
+	}
+      } else {
+	comp1 = ImgComponentAlloc(info);
+	comp1->var = mdd_dup(comp->var);
+	comp1->func = res;
+	if (mdd_equal(res, comp->func))
+	  ImgSupportCopy(info, comp1->support, comp->support);
+	else
+	  ImgComponentGetSupport(comp1);
+	array_insert_last(ImgComponent_t *, vector1, comp1);
+	st_insert(equivTable, (char *)regularPtr, (char *)(long)n);
+	n++;
+      }
+    }
+  }
+  st_free_table(equivTable);
+
+  if (constIntermediate) {
+    if (!bdd_is_tautology(constIntermediate, 1)) {
+      mdd_t	*tmpCofactor, *tmpAbstract;
+
+      if (relationArray) {
+	vector1 = ImgComposeConstIntermediateVars(info, vector1,
+						  constIntermediate,
+						  &tmpCofactor, &tmpAbstract,
+						  &old, NIL(mdd_t *));
+	if (!bdd_is_tautology(tmpCofactor, 1)) {
+	  tmp = cofactor;
+	  cofactor = mdd_and(tmp, tmpCofactor, 1, 1);
+	  mdd_free(tmp);
+	}
+	mdd_free(tmpCofactor);
+	if (!bdd_is_tautology(tmpAbstract, 1)) {
+	  tmp = abstract;
+	  abstract = mdd_and(tmp, tmpAbstract, 1, 1);
+	  mdd_free(tmp);
+	}
+	mdd_free(tmpAbstract);
+	tmp = cofactor;
+	cofactor = mdd_and(tmp, constIntermediate, 1, 1);
+	mdd_free(tmp);
+      } else {
+	vector1 = ImgComposeConstIntermediateVars(info, vector1,
+						  constIntermediate,
+						  NIL(mdd_t *), NIL(mdd_t *),
+						  &old, NIL(mdd_t *));
+      }
+    }
+    mdd_free(constIntermediate);
+  }
+
+  if (info->option->sortVectorFlag)
+    array_sort(vector1, CompareBddPointer);
+
+  if (newRelationArray)
+    *newRelationArray = relationArray;
+  if (cofactorCube && abstractCube) {
+    if (cofactor) {
+      if (bdd_is_tautology(cofactor, 1)) {
+	*cofactorCube = mdd_dup(constraint);
+	mdd_free(cofactor);
+      } else {
+	tmp = cofactor;
+	cofactor = mdd_and(tmp, constraint, 1, 1);
+	mdd_free(tmp);
+	*cofactorCube = cofactor;
+      }
+    }
+    if (abstract)
+      *abstractCube = abstract;
+  } else {
+    if (cofactor) {
+      if (bdd_is_tautology(cofactor, 1))
+	mdd_free(cofactor);
+      else {
+	tmp = cofactor;
+	cofactor = mdd_and(tmp, constraint, 1, 1);
+	mdd_free(tmp);
+	if (newRelationArray) {
+	  *newRelationArray = ImgGetCofactoredRelationArray(relationArray,
+							    cofactor);
+	} else
+	  ImgCofactorRelationArray(relationArray, cofactor);
+	mdd_free(cofactor);
+      }
+    }
+    if (abstract) {
+      if (bdd_is_tautology(abstract, 1))
+	mdd_free(abstract);
+      else {
+	if (newRelationArray) {
+	  tmpRelationArray = *newRelationArray;
+	  *newRelationArray = ImgGetAbstractedRelationArray(info->manager,
+							    tmpRelationArray,
+							    abstract);
+	  if (tmpRelationArray != relationArray)
+	    mdd_array_free(tmpRelationArray);
+	} else
+	  ImgAbstractRelationArray(info->manager, relationArray, abstract);
+	mdd_free(abstract);
+      }
+    }
+  }
+
+  if (*newVector == vector)
+    ImgVectorFree(vector);
+  *newVector = vector1;
+  if (cube)
+    *cube = old;
+
+  return(newFrom);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a function vector.]
+
+  Description [Frees a function vector.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgVectorFree(array_t *vector)
+{
+  int    		i;
+  ImgComponent_t	*comp;
+
+  for (i = 0; i < array_n(vector); i++) {
+    comp = array_fetch(ImgComponent_t *, vector, i);
+    ImgComponentFree(comp);
+  }
+  array_free(vector);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of functions in a vector.]
+
+  Description [Returns the number of functions in a vector. Excludes the
+  number of intermediate functions.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+ImgVectorFunctionSize(array_t *vector)
+{
+  ImgComponent_t	*comp;
+  int			i, size;
+
+  size = 0;
+  for (i = 0; i < array_n(vector); i++) {
+    comp = array_fetch(ImgComponent_t *, vector, i);
+    if (!comp->intermediate)
+      size++;
+  }
+
+  return(size);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the shared BDD size of a vector.]
+
+  Description [Returns the shared BDD size of a vector.]
+
+  SideEffects []
+
+******************************************************************************/
+long
+ImgVectorBddSize(array_t *vector)
+{
+  array_t		*nodeArray;
+  ImgComponent_t	*comp;
+  int			i, size;
+
+  nodeArray = array_alloc(mdd_t *, 0);
+  for (i = 0; i < array_n(vector); i++) {
+    comp = array_fetch(ImgComponent_t *, vector, i);
+    array_insert_last(mdd_t *, nodeArray, comp->func);
+  }
+  size = bdd_size_multiple(nodeArray);
+  array_free(nodeArray);
+
+  return(size);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Copies a vector.]
+
+  Description [Copies a vector.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+ImgVectorCopy(ImgTfmInfo_t *info, array_t *vector)
+{
+  array_t		*newVector;
+  ImgComponent_t	*comp, *newComp;
+  int			i;
+
+  newVector = array_alloc(ImgComponent_t *, 0);
+  for (i = 0; i < array_n(vector); i++) {
+    comp = array_fetch(ImgComponent_t *, vector, i);
+    newComp = ImgComponentCopy(info, comp);
+    array_insert_last(ImgComponent_t *, newVector, newComp);
+  }
+  return(newVector);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates a component.]
+
+  Description [Allocates a component.]
+
+  SideEffects []
+
+******************************************************************************/
+ImgComponent_t *
+ImgComponentAlloc(ImgTfmInfo_t *info)
+{
+  ImgComponent_t	*comp;
+
+  comp = ALLOC(ImgComponent_t, 1);
+  memset(comp, 0, sizeof(ImgComponent_t));
+  comp->support = ALLOC(char, info->nVars);
+  ImgSupportClear(info, comp->support);
+  comp->id = info->nComponents++;
+  return(comp);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Copies a component]
+
+  Description [Copies a component]
+
+  SideEffects []
+
+******************************************************************************/
+ImgComponent_t *
+ImgComponentCopy(ImgTfmInfo_t *info, ImgComponent_t *comp)
+{
+  ImgComponent_t	*newComp;
+
+  newComp = ImgComponentAlloc(info);
+  newComp->func = mdd_dup(comp->func);
+  newComp->var = mdd_dup(comp->var);
+  ImgSupportCopy(info, newComp->support, comp->support);
+  newComp->intermediate = comp->intermediate;
+  return(newComp);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a component.]
+
+  Description [Frees a component.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgComponentFree(ImgComponent_t *comp)
+{
+  if (comp->func)
+    mdd_free(comp->func);
+  if (comp->var != NULL)
+    mdd_free(comp->var);
+  FREE(comp->support);
+  FREE(comp);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the supports of a component.]
+
+  Description [Gets the supports of a component.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgComponentGetSupport(ImgComponent_t *comp)
+{
+  int		index;
+  var_set_t	*supportVarSet;
+
+  supportVarSet = bdd_get_support(comp->func);
+  for (index = 0; index < supportVarSet->n_elts; index++) {
+    if (var_set_get_elt(supportVarSet, index) == 1)
+      comp->support[index] = 1;
+  }
+  var_set_free(supportVarSet);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Copies the supports of a component.]
+
+  Description [Copies the supports of a component. Here support is an array
+  of char.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgSupportCopy(ImgTfmInfo_t *info, char *dsupport, char *ssupport)
+{
+  memcpy(dsupport, ssupport, sizeof(char) * info->nVars);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Clears a support array.]
+
+  Description [Clears a support array.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgSupportClear(ImgTfmInfo_t *info, char *support)
+{
+  memset(support, 0, sizeof(char) * info->nVars);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints a support array.]
+
+  Description [Prints a support array.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgSupportPrint(ImgTfmInfo_t *info, char *support)
+{
+  int	i;
+
+  for (i = 0; i < info->nVars; i++) {
+   if (support[i])
+     printf("*");
+   else
+     printf(".");
+  }
+  printf("\n");
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of support of a support array.]
+
+  Description [Returns the number of support of a support array.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+ImgSupportCount(ImgTfmInfo_t *info, char *support)
+{
+  int	i, nSupports;
+
+  nSupports = 0;
+  for (i = 0; i < info->nVars; i++) {
+   if (support[i])
+     nSupports++;
+  }
+  return(nSupports);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Constrains a relation array with respect to a constraint.]
+
+  Description [Constrains a relation array with respect to a constraint.
+  Returns new relation array.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+ImgGetConstrainedRelationArray(ImgTfmInfo_t *info, array_t *relationArray,
+				mdd_t *constraint)
+{
+  array_t		*constrainedRelationArray;
+  int			dynStatus;
+  bdd_reorder_type_t	dynMethod;
+
+  dynStatus = bdd_reordering_status(info->manager, &dynMethod);
+  if (dynStatus != 0)
+    bdd_dynamic_reordering_disable(info->manager);
+
+  constrainedRelationArray = ImgGetCofactoredRelationArray(relationArray,
+							   constraint);
+
+  if (dynStatus != 0) {
+    bdd_dynamic_reordering(info->manager, dynMethod,
+			   BDD_REORDER_VERBOSITY_DEFAULT);
+  }
+
+  return(constrainedRelationArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Cofactors a relation array with respect to a function.]
+
+  Description [Cofactors a relation array with respect to a function.
+  Returns new relation array.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+ImgGetCofactoredRelationArray(array_t *relationArray, mdd_t *func)
+{
+  int		i;
+  array_t	*cofactoredRelationArray;
+  mdd_t		*relation, *cofactoredRelation;
+
+  if (bdd_is_tautology(func, 1))
+    return(mdd_array_duplicate(relationArray));
+
+  cofactoredRelationArray = array_alloc(mdd_t *, 0);
+
+  for (i = 0; i < array_n(relationArray); i++) {
+    relation = array_fetch(mdd_t *, relationArray, i);
+    cofactoredRelation = bdd_cofactor(relation, func);
+    if (bdd_is_tautology(cofactoredRelation, 1))
+      mdd_free(cofactoredRelation);
+    else
+      array_insert_last(mdd_t *, cofactoredRelationArray, cofactoredRelation);
+  }
+
+  return(cofactoredRelationArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Cofactors a relation array with respect to a function.]
+
+  Description [Cofactors a relation array with respect to a function.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgCofactorRelationArray(array_t *relationArray, mdd_t *func)
+{
+  int		i;
+  mdd_t		*relation, *cofactoredRelation;
+
+  if (bdd_is_tautology(func, 1))
+    return;
+
+  for (i = 0; i < array_n(relationArray); i++) {
+    relation = array_fetch(mdd_t *, relationArray, i);
+    cofactoredRelation = bdd_cofactor(relation, func);
+    if (mdd_equal(cofactoredRelation, relation))
+      mdd_free(cofactoredRelation);
+    else {
+      mdd_free(relation);
+      array_insert(mdd_t *, relationArray, i, cofactoredRelation);
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Smoothes a relation array with respect to a cube.]
+
+  Description [Smoothes a relation array with respect to a cube.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+ImgGetAbstractedRelationArray(mdd_manager *manager, array_t *relationArray,
+			      mdd_t *cube)
+{
+  int		i;
+  array_t	*abstractedRelationArray;
+  mdd_t		*relation, *abstractedRelation;
+  array_t	*varsArray;
+
+  if (bdd_is_tautology(cube, 1))
+    return(mdd_array_duplicate(relationArray));
+
+  abstractedRelationArray = array_alloc(mdd_t *, 0);
+
+  if (bdd_get_package_name() != CUDD)
+    varsArray = mdd_get_bdd_support_vars(manager, cube);
+  else /* to remove uninitialized variable warning*/
+    varsArray = NIL(array_t);
+  for (i = 0; i < array_n(relationArray); i++) {
+    relation = array_fetch(mdd_t *, relationArray, i);
+    if (bdd_get_package_name() == CUDD)
+      abstractedRelation = bdd_smooth_with_cube(relation, cube);
+    else
+      abstractedRelation = bdd_smooth(relation, varsArray);
+    if (bdd_is_tautology(abstractedRelation, 1))
+      mdd_free(abstractedRelation);
+    else
+      array_insert_last(mdd_t *, abstractedRelationArray, abstractedRelation);
+  }
+  if (bdd_get_package_name() != CUDD)
+    mdd_array_free(varsArray);
+
+  return(abstractedRelationArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Smoothes a relation array with respect to a cube.]
+
+  Description [Smoothes a relation array with respect to a cube.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgAbstractRelationArray(mdd_manager *manager, array_t *relationArray,
+			 mdd_t *cube)
+{
+  int		i;
+  mdd_t		*relation, *abstractedRelation;
+  array_t	*varsArray;
+
+  if (bdd_is_tautology(cube, 1))
+    return;
+
+  if (bdd_get_package_name() != CUDD)
+    varsArray = mdd_get_bdd_support_vars(manager, cube);
+  else /* to remove uninitialized variable warning*/
+    varsArray = NIL(array_t);
+  for (i = 0; i < array_n(relationArray); i++) {
+    relation = array_fetch(mdd_t *, relationArray, i);
+    if (bdd_get_package_name() == CUDD)
+      abstractedRelation = bdd_smooth_with_cube(relation, cube);
+    else
+      abstractedRelation = bdd_smooth(relation, varsArray);
+    if (mdd_equal(abstractedRelation, relation))
+      mdd_free(abstractedRelation);
+    else {
+      mdd_free(relation);
+      array_insert(mdd_t *, relationArray, i, abstractedRelation);
+    }
+  }
+  if (bdd_get_package_name() != CUDD)
+    mdd_array_free(varsArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Cofactors and smooths a relation array.]
+
+  Description [Cofactors and smooths a relation array. Returns new
+  relation array.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+ImgGetCofactoredAbstractedRelationArray(mdd_manager *manager,
+					array_t *relationArray,
+					mdd_t *cofactorCube,
+					mdd_t *abstractCube)
+{
+  int		i;
+  array_t	*newRelationArray = array_alloc(mdd_t *, 0);
+  mdd_t		*relation, *newRelation, *tmpRelation;
+  array_t	*varsArray;
+
+  if (bdd_get_package_name() != CUDD)
+    varsArray = mdd_get_bdd_support_vars(manager, abstractCube);
+  else /* to remove uninitialized variable warning*/
+    varsArray = NIL(array_t);
+  for (i = 0; i < array_n(relationArray); i++) {
+    relation = array_fetch(mdd_t *, relationArray, i);
+    tmpRelation = bdd_cofactor(relation, cofactorCube);
+    if (bdd_get_package_name() == CUDD)
+      newRelation = bdd_smooth_with_cube(tmpRelation, abstractCube);
+    else
+      newRelation = bdd_smooth(tmpRelation, varsArray);
+    mdd_free(tmpRelation);
+    if (bdd_is_tautology(newRelation, 1))
+      mdd_free(newRelation);
+    else
+      array_insert_last(mdd_t *, newRelationArray, newRelation);
+  }
+  if (bdd_get_package_name() != CUDD)
+    mdd_array_free(varsArray);
+
+  return(newRelationArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Smothes and cofactors a relation array.]
+
+  Description [Smothes and cofactors a relation array. Returns new
+  relation array.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+ImgGetAbstractedCofactoredRelationArray(mdd_manager *manager,
+					array_t *relationArray,
+					mdd_t *cofactorCube,
+					mdd_t *abstractCube)
+{
+  int		i;
+  array_t	*newRelationArray = array_alloc(mdd_t *, 0);
+  mdd_t		*relation, *newRelation, *tmpRelation;
+  array_t	*varsArray;
+
+  if (bdd_get_package_name() != CUDD)
+    varsArray = mdd_get_bdd_support_vars(manager, abstractCube);
+  else /* to remove uninitialized variable warning*/
+    varsArray = NIL(array_t);
+  for (i = 0; i < array_n(relationArray); i++) {
+    relation = array_fetch(mdd_t *, relationArray, i);
+    if (bdd_get_package_name() == CUDD)
+      tmpRelation = bdd_smooth_with_cube(relation, abstractCube);
+    else
+      tmpRelation = bdd_smooth(relation, varsArray);
+    newRelation = bdd_cofactor(tmpRelation, cofactorCube);
+    mdd_free(tmpRelation);
+    if (bdd_is_tautology(newRelation, 1))
+      mdd_free(newRelation);
+    else
+      array_insert_last(mdd_t *, newRelationArray, newRelation);
+  }
+  if (bdd_get_package_name() != CUDD)
+    mdd_array_free(varsArray);
+
+  return(newRelationArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Constrains a function vector with respect to a constraint.]
+
+  Description [Constrains a function vector with respect to a constraint.
+  Returns new function vector.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+ImgGetConstrainedVector(ImgTfmInfo_t *info, array_t *vector, mdd_t *constraint)
+{
+  array_t		*constrainedVector;
+  int			dynStatus;
+  bdd_reorder_type_t	dynMethod;
+
+  dynStatus = bdd_reordering_status(info->manager, &dynMethod);
+  if (dynStatus != 0)
+    bdd_dynamic_reordering_disable(info->manager);
+
+  constrainedVector = ImgGetCofactoredVector(info, vector, constraint);
+
+  if (dynStatus != 0) {
+    bdd_dynamic_reordering(info->manager, dynMethod,
+			   BDD_REORDER_VERBOSITY_DEFAULT);
+  }
+
+  return(constrainedVector);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Cofactors a function vector with respect to a function.]
+
+  Description [Cofactors a function vector with respect to a function.
+  Returns new function vector.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+ImgGetCofactoredVector(ImgTfmInfo_t *info, array_t *vector, mdd_t *func)
+{
+  int			i;
+  array_t		*cofactoredVector = array_alloc(ImgComponent_t *, 0);
+  ImgComponent_t	*comp, *cofactoredComp;
+  mdd_t			*cofactoredFunc;
+
+  if (bdd_is_tautology(func, 1))
+    return(ImgVectorCopy(info, vector));
+
+  for (i = 0; i < array_n(vector); i++) {
+    comp = array_fetch(ImgComponent_t *, vector, i);
+    cofactoredFunc = bdd_cofactor(comp->func, func);
+    cofactoredComp = ImgComponentAlloc(info);
+    cofactoredComp->var = mdd_dup(comp->var);
+    cofactoredComp->func = cofactoredFunc;
+    cofactoredComp->intermediate = comp->intermediate;
+    if (mdd_equal(cofactoredFunc, comp->func))
+      ImgSupportCopy(info, cofactoredComp->support, comp->support);
+    else
+      ImgComponentGetSupport(cofactoredComp);
+    array_insert_last(ImgComponent_t *, cofactoredVector, cofactoredComp);
+  }
+
+  return(cofactoredVector);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Cofactors a function vector with respect to a function.]
+
+  Description [Cofactors a function vector with respect to a function.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgCofactorVector(ImgTfmInfo_t *info, array_t *vector, mdd_t *func)
+{
+  int			i;
+  ImgComponent_t	*comp;
+  mdd_t			*cofactoredFunc;
+
+  if (bdd_is_tautology(func, 1))
+    return;
+
+  for (i = 0; i < array_n(vector); i++) {
+    comp = array_fetch(ImgComponent_t *, vector, i);
+    cofactoredFunc = bdd_cofactor(comp->func, func);
+    if (mdd_equal(cofactoredFunc, comp->func))
+      mdd_free(cofactoredFunc);
+    else {
+      mdd_free(comp->func);
+      comp->func = cofactoredFunc;
+      ImgSupportClear(info, comp->support);
+      ImgComponentGetSupport(comp);
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Eliminates dependent variables from transition function.]
+
+  Description [Eliminates dependent variables from a transition
+  function.  Returns a simplified copy of the given states if successful;
+  NULL otherwise.]
+
+  SideEffects [vector is also modified.]
+
+  SeeAlso     []
+
+******************************************************************************/
+mdd_t *
+ImgTfmEliminateDependVars(ImgTfmInfo_t *info, array_t *vector,
+			  array_t *relationArray, mdd_t *states,
+			  array_t **newVector,
+			  mdd_t **dependRelations)
+{
+  int			i, j;
+  int			howMany = 0;
+			/* number of latches that can be eliminated */
+  mdd_t			*var, *newStates, *abs, *positive, *phi;
+  mdd_t			*tmp, *relation;
+  int			nVars;
+  int			nSupports; /* vars in the support of the state set */
+  int			*candidates; /* vars to be considered for elimination */
+  double		minStates;
+  ImgComponent_t	*comp, *newComp;
+
+  if (dependRelations) {
+    *dependRelations = mdd_one(info->manager);
+    *newVector = array_alloc(ImgComponent_t *, 0);
+  }
+  newStates = mdd_dup(states);
+  nVars = info->nVars;
+
+  candidates = ALLOC(int, nVars);
+  if (candidates == NULL)
+    return(NULL);
+
+  comp = ImgComponentAlloc(info);
+  comp->func = newStates;
+  ImgComponentGetSupport(comp);
+  nSupports = 0;
+  for (i = 0 ; i < nVars; i++) {
+    if (comp->support[i]) {
+      candidates[nSupports] = i;
+      nSupports++;
+    }
+  }
+  comp->func = NIL(mdd_t);
+  ImgComponentFree(comp);
+
+  /* The signatures of the variables in a function are the number
+  ** of minterms of the positive cofactors with respect to the
+  ** variables themselves. */
+  signatures = bdd_cof_minterm(newStates);
+  if (signatures == NULL) {
+    FREE(candidates);
+    return(NULL);
+  }
+  /* We now extract a positive quantity which is higher for those
+  ** variables that are closer to being essential. */
+  minStates = signatures[nSupports];
+  for (i = 0; i < nSupports; i++) {
+    double z = signatures[i] / minStates - 1.0;
+    signatures[i] = (z < 0.0) ? -z : z;    /* make positive */
+  }
+  qsort((void *)candidates, nSupports, sizeof(int),
+      (int (*)(const void *, const void *))SignatureCompare);
+  FREE(signatures);
+
+  /* Now process the candidates in the given order. */
+  for (i = 0; i < nSupports; i++) {
+    var = bdd_var_with_index(info->manager, candidates[i]);
+    if (bdd_var_is_dependent(newStates, var)) {
+      abs = bdd_smooth_with_cube(newStates, var);
+      if (abs == NULL)
+	return(NULL);
+      positive = bdd_cofactor(newStates, var);
+      if (positive == NULL)
+	return(NULL);
+      phi = Img_MinimizeImage(positive, abs, Img_DefaultMinimizeMethod_c,
+			      TRUE); 
+      if (phi == NULL)
+	return(NULL);
+      mdd_free(positive);
+      if (bdd_size(phi) < IMG_MAX_DEP_SIZE) {
+	howMany++;
+	if (dependRelations) {
+	  for (j = 0; j < array_n(vector); j++) {
+	    comp = array_fetch(ImgComponent_t *, vector, j);
+	    if (mdd_equal(comp->var, var))
+	      continue;
+	    newComp = ImgComponentCopy(info, comp);
+	    array_insert_last(ImgComponent_t *, *newVector, newComp);
+	  }
+	} else {
+	  for (j = 0; j < array_n(vector); j++) {
+	    comp = array_fetch(ImgComponent_t *, vector, j);
+	    tmp = bdd_compose(comp->func, var, phi);
+	    if (tmp == NULL)
+	      return(NULL);
+	    mdd_free(comp->func);
+	    comp->func = tmp;
+	    ImgSupportClear(info, comp->support);
+	    ImgComponentGetSupport(comp);
+	  }
+	}
+	if (relationArray) {
+	  for (j = 0; j < array_n(relationArray); j++) {
+	    relation = array_fetch(mdd_t *, relationArray, j);
+	    if (dependRelations)
+	      tmp = bdd_smooth_with_cube(relation, var);
+	    else
+	      tmp = bdd_compose(relation, var, phi);
+	    mdd_free(relation);
+	    array_insert(mdd_t *, relationArray, j, tmp);
+	  }
+	}
+	mdd_free(newStates);
+	newStates = abs;
+	if (dependRelations) {
+	  relation = mdd_xnor(var, phi);
+	  tmp = mdd_and(*dependRelations, relation, 1, 1);
+	  mdd_free(*dependRelations);
+	  mdd_free(relation);
+	  *dependRelations = tmp;
+	}
+      } else {
+	mdd_free(abs);
+      }
+      mdd_free(phi);
+    }
+  }
+  FREE(candidates);
+
+  if (howMany) {
+    if (info->imageVerbosity > 0)
+      (void)fprintf(vis_stdout, "Eliminated %d vars.\n", howMany);
+    info->averageFoundDependVars = (info->averageFoundDependVars *
+			(float)info->nFoundDependVars + (float)howMany) /
+			(float)(info->nFoundDependVars + 1);
+    info->nFoundDependVars++;
+  }
+
+  info->nPrevEliminatedFwd = howMany;
+  return(newStates);
+} /* end of TfmEliminateDependVars */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether there is a constant function of intermediate
+  variables.]
+
+  Description [Checks whether there is a constant function of intermediate
+  variables.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+ImgExistConstIntermediateVar(array_t *vector)
+{
+  int			i;
+  ImgComponent_t	*comp;
+
+  for (i = 0; i < array_n(vector); i++) {
+    comp = array_fetch(ImgComponent_t *, vector, i);
+    if (comp->intermediate) {
+      if (mdd_is_tautology(comp->func, 1) || mdd_is_tautology(comp->func, 0))
+	return(1);
+    }
+  }
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a function composed all intermediate variables.]
+
+  Description [Returns a function composed all intermediate variables.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+ImgGetComposedFunction(array_t *vector)
+{
+  ImgComponent_t	*comp;
+  mdd_t			*func, *newFunc;
+  int			i;
+  array_t		*varArray, *funcArray;
+
+  assert(ImgVectorFunctionSize(vector) == 1);
+
+  /* no intermediate variables */
+  if (array_n(vector) == 1) {
+    comp = array_fetch(ImgComponent_t *, vector, 0);
+    newFunc = mdd_dup(comp->func);
+    return(newFunc);
+  }
+
+  func = NIL(mdd_t);
+  varArray = array_alloc(mdd_t *, 0);
+  funcArray = array_alloc(mdd_t *, 0);
+
+  for (i = 0; i < array_n(vector); i++) {
+    comp = array_fetch(ImgComponent_t *, vector, i);
+    if (comp->intermediate) {
+      array_insert_last(mdd_t *, varArray, comp->var);
+      array_insert_last(mdd_t *, funcArray, comp->func);
+      continue;
+    }
+    func = comp->func;
+  }
+
+  newFunc = bdd_vector_compose(func, varArray, funcArray);
+  array_free(varArray);
+  array_free(funcArray);
+  return(newFunc);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the first latch component.]
+
+  Description [Returns the first latch component.]
+
+  SideEffects []
+
+******************************************************************************/
+ImgComponent_t *
+ImgGetLatchComponent(array_t *vector)
+{
+  ImgComponent_t	*comp;
+  int			i;
+
+  for (i = 0; i < array_n(vector); i++) {
+    comp = array_fetch(ImgComponent_t *, vector, i);
+    if (!comp->intermediate)
+      return(comp);
+  }
+  return(NIL(ImgComponent_t));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compose the constant intermediate variable functions.]
+
+  Description [Compose the constant intermediate variable functions.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+ImgComposeConstIntermediateVars(ImgTfmInfo_t *info, array_t *vector,
+				mdd_t *constIntermediate,
+				mdd_t **cofactorCube, mdd_t **abstractCube,
+				mdd_t **and_, mdd_t **from)
+{
+  int			i, n, pos;
+  array_t		*tmpVector, *cofactoredVector;
+  mdd_t			*cofactor, *abstract;
+  mdd_t			*curConstIntermediate, *newConstIntermediate;
+  mdd_t			*tmp, *new_, *func, *varNot, *nsVar;
+  ImgComponent_t	*comp, *comp1;
+  st_table		*equivTable;
+  int			*ptr, *regularPtr;
+
+  if (cofactorCube)
+    cofactor = mdd_one(info->manager);
+  else
+    cofactor = NIL(mdd_t);
+  if (abstractCube)
+    abstract = mdd_one(info->manager);
+  else
+    abstract = NIL(mdd_t);
+
+  cofactoredVector = vector;
+  tmpVector = cofactoredVector;
+  curConstIntermediate = constIntermediate;
+
+  while (!bdd_is_tautology(curConstIntermediate, 1)) {
+    newConstIntermediate = mdd_one(info->manager);
+    n = 0;
+    equivTable = st_init_table(st_ptrcmp, st_ptrhash);
+    cofactoredVector = array_alloc(ImgComponent_t *, 0);
+    for (i = 0; i < array_n(tmpVector); i++) {
+      comp = array_fetch(ImgComponent_t *, tmpVector, i);
+      func = bdd_cofactor(comp->func, curConstIntermediate);
+
+      if (comp->intermediate) {
+	if (mdd_is_tautology(func, 1)) {
+	  tmp = newConstIntermediate;
+	  newConstIntermediate = mdd_and(tmp, comp->var, 1, 1);
+	  mdd_free(tmp);
+	  mdd_free(func);
+	  continue;
+	} else if (mdd_is_tautology(func, 0)) {
+	  tmp = newConstIntermediate;
+	  newConstIntermediate = mdd_and(tmp, comp->var, 1, 0);
+	  mdd_free(tmp);
+	  mdd_free(func);
+	  continue;
+	}
+
+	comp1 = ImgComponentAlloc(info);
+	comp1->var = mdd_dup(comp->var);
+	comp1->func = func;
+	comp1->intermediate = 1;
+	if (mdd_equal(func, comp->func))
+	  ImgSupportCopy(info, comp1->support, comp->support);
+	else
+	  ImgComponentGetSupport(comp1);
+	array_insert_last(ImgComponent_t *, cofactoredVector, comp1);
+	n++;
+	continue;
+      }
+
+      if (mdd_is_tautology(func, 1)) {
+	if (cofactor) {
+	  nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+	  tmp = cofactor;
+	  cofactor = mdd_and(tmp, nsVar, 1, 1);
+	  mdd_free(tmp);
+	  mdd_free(nsVar);
+	}
+	if (and_) {
+	  tmp = *and_;
+	  *and_ = mdd_and(tmp, comp->var, 1, 1);
+	  mdd_free(tmp);
+	}
+	if (from) {
+	  tmp = *from;
+	  *from = bdd_cofactor(tmp, comp->var);
+	  mdd_free(tmp);
+	}
+	mdd_free(func);
+      } else if (mdd_is_tautology(func, 0)) {
+	if (cofactor) {
+	  nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+	  tmp = cofactor;
+	  cofactor = mdd_and(tmp, nsVar, 1, 0);
+	  mdd_free(tmp);
+	  mdd_free(nsVar);
+	}
+	if (and_) {
+	  tmp = *and_;
+	  *and_ = mdd_and(tmp, comp->var, 1, 0);
+	  mdd_free(tmp);
+	}
+	if (from) {
+	  tmp = *from;
+	  varNot = bdd_not(comp->var);
+	  *from = bdd_cofactor(tmp, varNot);
+	  mdd_free(tmp);
+	  mdd_free(varNot);
+	}
+	mdd_free(func);
+      } else {
+	ptr = (int *)bdd_pointer(func);
+	regularPtr = (int *)((unsigned long)ptr & ~01);
+	if (st_lookup_int(equivTable, (char *)regularPtr, &pos)) {
+	  comp1 = array_fetch(ImgComponent_t *, cofactoredVector, pos);
+	  if (and_) {
+	    if (mdd_equal(func, comp1->func))
+	      tmp = mdd_xnor(comp->var, comp1->var);
+	    else
+	      tmp = mdd_xor(comp->var, comp1->var);
+	    new_ = mdd_and(tmp, *and_, 1, 1);
+	    mdd_free(tmp);
+	    mdd_free(*and_);
+	    mdd_free(func);
+	    *and_ = new_;
+	  }
+	  if (abstract) {
+	    nsVar = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+	    tmp = abstract;
+	    abstract = mdd_and(tmp, nsVar, 1, 1);
+	    mdd_free(tmp);
+	    mdd_free(nsVar);
+	  }
+	  if (from) {
+	    tmp = *from;
+	    *from = bdd_compose(tmp, comp->var, comp1->var);
+	    mdd_free(tmp);
+	  }
+	} else {
+	  comp1 = ImgComponentAlloc(info);
+	  comp1->var = mdd_dup(comp->var);
+	  comp1->func = func;
+	  if (mdd_equal(func, comp->func))
+	    ImgSupportCopy(info, comp1->support, comp->support);
+	  else
+	    ImgComponentGetSupport(comp1);
+	  array_insert_last(ImgComponent_t *, cofactoredVector, comp1);
+	  st_insert(equivTable, (char *)regularPtr, (char *)(long)n);
+	  n++;
+	}
+      }
+    }
+
+    if (curConstIntermediate != constIntermediate)
+      mdd_free(curConstIntermediate);
+    curConstIntermediate = newConstIntermediate;
+
+    if (cofactor) {
+      tmp = cofactor;
+      cofactor = mdd_and(tmp, curConstIntermediate, 1, 1);
+      mdd_free(tmp);
+    }
+
+    st_free_table(equivTable);
+    ImgVectorFree(tmpVector);
+    tmpVector = cofactoredVector;
+  }
+
+  if (curConstIntermediate != constIntermediate)
+    mdd_free(curConstIntermediate);
+
+  if (cofactorCube)
+    *cofactorCube = cofactor;
+  if (abstractCube)
+    *abstractCube = abstract;
+
+  return(cofactoredVector);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of BDD supports in a function.]
+
+  Description [Returns the number of BDD supports in a function.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+ImgCountBddSupports(mdd_t *func)
+{
+  int		index, nSupports = 0;
+  var_set_t	*supportVarSet;
+
+  supportVarSet = bdd_get_support(func);
+  for (index = 0; index < supportVarSet->n_elts; index++) {
+    if (var_set_get_elt(supportVarSet, index) == 1)
+      nSupports++;
+  }
+  var_set_free(supportVarSet);
+  return(nSupports);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Quick checking whether the results of constrain between two
+  functions are constant.]
+
+  Description [Quick checking whether the results of constrain between two
+  functions are constant. Assumes that 1) f1 != f2 and f1 != f2', and
+  2) neither f1 nor f2 is constant.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgCheckConstConstrain(mdd_t *f1, mdd_t *f2, int *f21p, int *f21n)
+{
+  if (mdd_lequal(f1, f2, 1, 1)) { /* f2 > f1 */
+    *f21p = 1;
+    *f21n = 2;
+  } else if (mdd_lequal(f2, f1, 1, 0)) { /* f2&f1=0 -> f2 < f1' */
+    *f21p = 0;
+    *f21n = 2;
+  } else if (mdd_lequal(f1, f2, 0, 1)) { /* f2 > f1' */
+    *f21p = 2;
+    *f21n = 1;
+  } else if (mdd_lequal(f2, f1, 1, 1)) { /* f2&f1'=0 -> f2 < f1 */
+    *f21p = 2;
+    *f21n = 0;
+  } else {
+    *f21p = 2;
+    *f21n = 2;
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether the result of constrain is constant.]
+
+  Description [Checks whether the result of constrain is constant.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+ImgConstConstrain(mdd_t *func, mdd_t *constraint)
+{
+  if (mdd_lequal(constraint, func, 1, 1)) /* func | constraint = 1 */
+    return(1);
+  if (mdd_lequal(func, constraint, 1, 0)) /* func | constraint = 0 */
+    return(0);
+  return(2); /* non-constant */
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints vector dependencies with support.]
+
+  Description [Prints vector dependencies with support.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgPrintVectorDependency(ImgTfmInfo_t *info, array_t *vector, int verbosity)
+{
+  int			i, j, index, nFuncs, nSupports;
+  int			nLambdaLatches, nConstLatches, nIntermediateVars;
+  int			count, countStates, total;
+  int			start, end;
+  char			*support, line[80];
+  ImgComponent_t	*comp;
+
+  if (verbosity == 0 || (!vector))
+    return;
+
+  support = ALLOC(char, sizeof(char) * info->nVars);
+  memset(support, 0, sizeof(char) * info->nVars);
+
+  count = countStates = 0;
+  nFuncs = array_n(vector);
+  for (i = 0; i < nFuncs; i++) {
+    comp = array_fetch(ImgComponent_t *, vector, i);
+    for (j = 0; j < info->nVars; j++) {
+      if (comp->support[j]) {
+	support[j] = 1;
+	count++;
+	if (!st_lookup(info->quantifyVarsTable, (char *)(long)j, NIL(char *)))
+	  countStates++;
+      }
+    }
+  }
+  nSupports = 0;
+  for (i = 0; i < info->nVars; i++) {
+    if (support[i])
+      nSupports++;
+  }
+  nLambdaLatches = 0;
+  nConstLatches = 0;
+  nIntermediateVars = 0;
+  for (i = 0; i < nFuncs; i++) {
+    comp = array_fetch(ImgComponent_t *, vector, i);
+    index = bdd_top_var_id(comp->var);
+    if (!support[index])
+      nLambdaLatches++;
+    if (ImgSupportCount(info, comp->support) == 0)
+      nConstLatches++;
+    if (comp->intermediate)
+      nIntermediateVars++;
+  }
+  fprintf(vis_stdout, "** tfm info: #vars = %d(%d)\n",
+	  info->nVars - nFuncs + nIntermediateVars, info->nVars);
+  fprintf(vis_stdout, "** tfm info: #input vars = %d\n",
+	  info->nVars - (nFuncs - nIntermediateVars) * 2 - nIntermediateVars);
+  fprintf(vis_stdout, "** tfm info: #funcs = %d\n", nFuncs);
+  fprintf(vis_stdout, "** tfm info: #lambda funcs = %d\n", nLambdaLatches);
+  fprintf(vis_stdout, "** tfm info: #constant funcs = %d\n", nConstLatches);
+  fprintf(vis_stdout, "** tfm info: #intermediate funcs = %d\n",
+	  nIntermediateVars);
+  fprintf(vis_stdout,
+	  "Shared size of transition function vector is %10ld BDD nodes\n",
+	  ImgVectorBddSize(vector));
+  total = nFuncs * nFuncs;
+  fprintf(vis_stdout,
+"** tfm info: support distribution (state variables) = %.2f%%(%d out of %d)\n",
+	  (float)countStates / (float)total * 100.0, countStates, total);
+  total = nFuncs * nSupports;
+  fprintf(vis_stdout,
+"** tfm info: support distribution (all variables) = %.2f%% (%d out of %d)\n",
+	  (float)count / (float)total * 100.0, count, total);
+
+  if (verbosity < 3) {
+    FREE(support);
+    return;
+  }
+
+  fprintf(vis_stdout, "*** function list ***\n");
+  for (i = 0; i < nFuncs; i++) {
+    comp = array_fetch(ImgComponent_t *, vector, i);
+    index = bdd_top_var_id(comp->var);
+    fprintf(vis_stdout, "[%d] index = %d\n", i, index);
+  }
+
+  start = 0;
+  end = 74;
+  if (end >= nFuncs)
+    end = nFuncs - 1;
+  while (1) {
+    fprintf(vis_stdout, "========================================");
+    fprintf(vis_stdout, "========================================\n");
+    fprintf(vis_stdout, "     1234567890123456789012345678901234567890");
+    fprintf(vis_stdout, "12345678901234567890123456789012345\n");
+    fprintf(vis_stdout, "----------------------------------------");
+    fprintf(vis_stdout, "----------------------------------------\n");
+    for (i = 0; i < info->nVars; i++) {
+      if (!support[i])
+	continue;
+      if (st_lookup(info->rangeVarsTable, (char *)(long)i, NIL(char *)))
+	continue;
+      for (j = start; j <= end; j++) {
+	comp = array_fetch(ImgComponent_t *, vector, j);
+	if (comp->support[i])
+	  line[j - start] = '1';
+	else
+	  line[j - start] = '.';
+      }
+      line[j - start] = '\0';
+      fprintf(vis_stdout, "%4d %s\n", i, line);
+    }
+    if (end >= nFuncs - 1)
+      break;
+    start += 75;
+    end += 75;
+    if (end >= nFuncs)
+      end = nFuncs - 1;
+  }
+  FREE(support);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the percent of non-zero elements in dependency matrix.]
+
+  Description [Returns the percent of non-zero elements in dependency matrix.]
+
+  SideEffects []
+
+******************************************************************************/
+float
+ImgPercentVectorDependency(ImgTfmInfo_t *info, array_t *vector, int length,
+			   int *nLongs)
+{
+  int			i, j, index, nFuncs, nSupports, nLambdaLatches;
+  int			count, total;
+  char			*support;
+  ImgComponent_t	*comp;
+  float			percent;
+  int			*occurs;
+
+  support = ALLOC(char, sizeof(char) * info->nVars);
+  memset(support, 0, sizeof(char) * info->nVars);
+  occurs = ALLOC(int, sizeof(int) * info->nVars);
+  memset(occurs, 0, sizeof(int) * info->nVars);
+
+  count = 0;
+  nFuncs = array_n(vector);
+  for (i = 0; i < nFuncs; i++) {
+    comp = array_fetch(ImgComponent_t *, vector, i);
+    for (j = 0; j < info->nVars; j++) {
+      if (comp->support[j]) {
+	support[j] = 1;
+	count++;
+	occurs[i]++;
+      }
+    }
+  }
+  nSupports = 0;
+  for (i = 0; i < info->nVars; i++) {
+    if (support[i])
+      nSupports++;
+  }
+  nLambdaLatches = 0;
+  for (i = 0; i < nFuncs; i++) {
+    comp = array_fetch(ImgComponent_t *, vector, i);
+    index = bdd_top_var_id(comp->var);
+    if (!support[index])
+      nLambdaLatches++;
+  }
+  FREE(support);
+
+  *nLongs = 0;
+  for (i = 0; i < info->nVars; i++) {
+    if (occurs[i] >= length)
+      (*nLongs)++;
+  }
+
+  total = (nFuncs - nLambdaLatches) * nSupports;
+  percent = (float)count / (float)total * 100.0;
+  return(percent);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes a gnuplot file with support matrix.]
+
+  Description [Writes a gnuplot file with support matrix.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgWriteSupportMatrix(ImgTfmInfo_t *info, array_t *vector,
+		      array_t *relationArray, char *string)
+{
+  int			i, j, id, nFuncs, nRelations, nRows, nSupports;
+  int			*row, col, varType;
+  char			*support, **relationSupport;
+  ImgComponent_t	*comp;
+  FILE			*fout;
+  mdd_t			*relation, *var;
+  char			*filename;
+
+  support = ALLOC(char, sizeof(char) * info->nVars);
+  memset(support, 0, sizeof(char) * info->nVars);
+  nRows = 0;
+  if (vector)
+    nRows += array_n(vector);
+  if (relationArray)
+    nRows += array_n(relationArray);
+  row = ALLOC(int, sizeof(int) * nRows);
+  if (string)
+    filename = string;
+  else
+    filename = "support.mat";
+  fout = fopen(filename, "w");
+
+  nRows = 0;
+  if (vector) {
+    nFuncs = array_n(vector);
+    for (i = 0; i < nFuncs; i++) {
+      comp = array_fetch(ImgComponent_t *, vector, i);
+      if (ImgSupportCount(info, comp->support) == 0) {
+	row[i] = -1;
+	continue;
+      }
+      row[i] = nRows;
+      nRows++;
+      if (info->option->writeSupportMatrixWithYvars) {
+	var = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+	id = (int)bdd_top_var_id(var);
+	support[id] = 1;
+	mdd_free(var);
+      }
+      for (j = 0; j < info->nVars; j++) {
+	if (comp->support[j])
+	  support[j] = 1;
+      }
+    }
+  } else
+    nFuncs = 0;
+
+  relationSupport = 0;
+  if (relationArray && array_n(relationArray) > 0) {
+    comp = ImgComponentAlloc(info);
+    nRelations = 0;
+    relationSupport = ALLOC(char *, sizeof(char *) * array_n(relationArray));
+    for (i = 0; i < array_n(relationArray); i++) {
+      relation = array_fetch(mdd_t *, relationArray, i);
+      comp->func = relation;
+      ImgSupportClear(info, comp->support);
+      ImgComponentGetSupport(comp);
+      if (ImgSupportCount(info, comp->support) <= 1) {
+	row[i + nFuncs] = -1;
+	relationSupport[i] = NIL(char);
+	continue;
+      }
+      row[i + nFuncs] = nRows;
+      nRows++;
+      for (j = 0; j < info->nVars; j++) {
+	if (comp->support[j])
+	  support[j] = 1;
+      }
+      relationSupport[i] = ALLOC(char, sizeof(char) * info->nVars);
+      memcpy(relationSupport[i], comp->support, sizeof(char) * info->nVars);
+      nRelations++;
+    }
+    comp->func = NIL(mdd_t);
+    ImgComponentFree(comp);
+  } else
+    nRelations = 0;
+
+  nSupports = 0;
+  for (i = 0; i < info->nVars; i++) {
+    if (support[i]) {
+      if (!info->option->writeSupportMatrixWithYvars &&
+	  st_lookup(info->rangeVarsTable, (char *)(long)i, NIL(char *))) {
+	continue;
+      }
+      nSupports++;
+    }
+  }
+
+  col = 0;
+  for (i = 0; i < info->nVars; i++) {
+    if (!support[i])
+      continue;
+    if (st_lookup(info->rangeVarsTable, (char *)(long)i, NIL(char *))) {
+      if (info->option->writeSupportMatrixWithYvars)
+	varType = 3;
+      else
+	continue;
+    } else if (st_lookup(info->quantifyVarsTable, (char *)(long)i, NIL(char *)))
+      varType = 2;
+    else
+      varType = 1;
+    for (j = 0; j < nFuncs; j++) {
+      comp = array_fetch(ImgComponent_t *, vector, j);
+      if (comp->support[i]) {
+	if (info->option->writeSupportMatrixReverseRow) {
+	  if (info->option->writeSupportMatrixReverseCol) {
+	    fprintf(fout, "%d %d %d\n", nSupports - col, nRows - row[j],
+		    varType);
+	  } else
+	    fprintf(fout, "%d %d %d\n", col + 1, nRows - row[j], varType);
+	} else {
+	  if (info->option->writeSupportMatrixReverseCol)
+	    fprintf(fout, "%d %d %d\n", nSupports - col, row[j] + 1, varType);
+	  else
+	    fprintf(fout, "%d %d %d\n", col + 1, row[j] + 1, varType);
+	}
+      } else if (varType == 3) {
+	var = ImgSubstitute(comp->var, info->functionData, Img_D2R_c);
+	id = (int)bdd_top_var_id(var);
+	mdd_free(var);
+	if (id == i) {
+	  if (info->option->writeSupportMatrixReverseRow) {
+	    if (info->option->writeSupportMatrixReverseCol)
+	      fprintf(fout, "%d %d 3\n", nSupports - col, nRows - row[j]);
+	    else
+	      fprintf(fout, "%d %d 3\n", col + 1, nRows - row[j]);
+	  } else {
+	    if (info->option->writeSupportMatrixReverseCol)
+	      fprintf(fout, "%d %d 3\n", nSupports - col, row[j] + 1);
+	    else
+	      fprintf(fout, "%d %d 3\n", col + 1, row[j] + 1);
+	  }
+	}
+      }
+    }
+    if (relationArray) {
+      for (j = 0; j < array_n(relationArray); j++) {
+	if (relationSupport[j] && relationSupport[j][i]) {
+	  if (info->option->writeSupportMatrixReverseRow) {
+	    if (info->option->writeSupportMatrixReverseCol) {
+	      fprintf(fout, "%d %d %d\n", nSupports - col,
+		      nRows - row[j + nFuncs], varType);
+	    } else {
+	      fprintf(fout, "%d %d %d\n", col + 1, nRows - row[j + nFuncs],
+		      varType);
+	    }
+	  } else {
+	    if (info->option->writeSupportMatrixReverseCol) {
+	      fprintf(fout, "%d %d %d\n", nSupports - col, row[j + nFuncs] + 1,
+		      varType);
+	    } else {
+	      fprintf(fout, "%d %d %d\n", col + 1, row[j + nFuncs] + 1,
+		      varType);
+	    }
+	  }
+	}
+      }
+    }
+    col++;
+  }
+  fclose(fout);
+  FREE(support);
+  FREE(row);
+  if (nRelations) {
+    for (i = 0; i < nRelations; i++)
+      FREE(relationSupport[i]);
+    FREE(relationSupport);
+  }
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Comparison function used by qsort.]
+
+  Description [Comparison function used by qsort to order the
+  variables according to their signatures.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int
+SignatureCompare(int *ptrX, int *ptrY)
+{
+  if (signatures[*ptrY] > signatures[*ptrX])
+    return(1);
+  if (signatures[*ptrY] < signatures[*ptrX])
+    return(-1);
+  return(0);
+} /* end of SignatureCompare */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compares two function BDD pointers of components.]
+
+  Description [Compares two function BDD pointers of components.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CompareBddPointer(const void *e1, const void *e2)
+{
+  ImgComponent_t	*c1, *c2;
+  unsigned long		ptr1, ptr2;
+
+  c1 = *((ImgComponent_t **)e1);
+  c2 = *((ImgComponent_t **)e2);
+
+  ptr1 = (unsigned long)bdd_pointer(c1->func);
+  ptr2 = (unsigned long)bdd_pointer(c2->func);
+
+  if (ptr1 > ptr2)
+    return(1);
+  else if (ptr1 < ptr2)
+    return(-1);
+  else
+    return(0);
+}
Index: vis_dev/vis-2.3/src/img/imgUtil.c
===================================================================
--- vis_dev/vis-2.3/src/img/imgUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/img/imgUtil.c	(revision 14)
@@ -0,0 +1,2558 @@
+/**CFile***********************************************************************
+
+  FileName    [imgUtil.c]
+
+  PackageName [img]
+
+  Synopsis    [High-level routines to perform image computations.]
+
+  Description [This file provides the exported interface to the
+  method-specific image computation routines.
+
+  <p> Minimization of the transition relation can be done in three ways (for
+  Iwls95, not so sure about monolithic and hybrid) (RB):
+
+  <ol> <li>You can call MinimizeTR.  This way, you'll loose the old TR, though
+  it could potentially reconstruct it from the bit relations.  This is a good
+  option for (overapproximate) reachability info, since the TR will remain
+  valid.</li>
+
+
+  <li> You can call the triplet Img_DupTransitionRelation to copy the TR,
+  Img_MinimizeTransitionRelation to minimize the TR, and
+  Img_RestoreTransitionRelation to discard the minimized TR and to restore the
+  original.  
+  
+  <li>Finally, if you just want to minimize the TR for a single step,
+  you can pass the care set to the (pre)image computation routine.  This does
+  unfortunately (and queerly) not work for image, but only for preimage.  If
+  you pas a care set, the TR gets minimized, and the minimized relation is kept
+  and reused until you pass a different care set.  Hence, minimizaiton is not
+  done at every preimage computation, but only if you change the care set.
+  
+  </ol>]
+
+  Author      [Rajeev Ranjan, Tom Shiple, Abelardo Pardo, In-Ho Moon, Kavita Ravi]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+#include "imgInt.h"
+
+static char rcsid[] UNUSED = "$Id: imgUtil.c,v 1.74 2005/05/14 21:08:32 jinh Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+static	int	nImgComps = 0; /* number of image computations */
+static	int	nPreComps = 0; /* number of pre-image computations */
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CheckImageValidity(mdd_manager *mddManager, mdd_t *image, array_t *domainVarMddIdArray, array_t *quantifyVarMddIdArray);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+Img_OptimizeType Img_ImageInfoObtainOptimizeType(Img_ImageInfo_t * imageInfo);
+void Img_ImageInfoSetUseOptimizedRelationFlag(Img_ImageInfo_t * imageInfo);
+void Img_ImageInfoResetUseOptimizedRelationFlag(Img_ImageInfo_t * imageInfo);
+void Img_ImageInfoResetLinearComputeRange(Img_ImageInfo_t * imageInfo);
+void Img_ImageInfoSetLinearComputeRange(Img_ImageInfo_t * imageInfo);
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initialize the image package.]
+
+  SideEffects []
+
+  SeeAlso     [Img_End]
+
+******************************************************************************/
+void
+Img_Init(void)
+{
+  /* Set the default settings. */
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [End the image package.]
+
+  SideEffects []
+
+  SeeAlso     [Img_Init]
+
+******************************************************************************/
+void
+Img_End(void)
+{
+  /* Do Nothing. */
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Return the image method preferred by the user.]
+
+  Description [Returns the method selected by Img_ImageInfoInitialize if
+  Img_Default_c is passed in.  Note that this may change if the user changes
+  the definition of the image_method set flag.]
+  
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoIninitialize]
+
+******************************************************************************/
+Img_MethodType
+Img_UserSpecifiedMethod(void)
+{
+  char *userSpecifiedMethod;
+  
+  userSpecifiedMethod = Cmd_FlagReadByName("image_method");
+
+  if (userSpecifiedMethod == NIL(char)) 
+    return IMGDEFAULT_METHOD;
+  if (strcmp(userSpecifiedMethod, "monolithic") == 0) 
+    return Img_Monolithic_c;
+  if (strcmp(userSpecifiedMethod, "tfm") == 0) 
+    return Img_Tfm_c;
+  if (strcmp(userSpecifiedMethod, "hybrid") == 0) 
+    return Img_Hybrid_c;
+  if (strcmp(userSpecifiedMethod, "iwls95") == 0)
+    return Img_Iwls95_c;
+  if (strcmp(userSpecifiedMethod, "mlp") == 0)
+    return Img_Mlp_c;
+
+  fprintf(vis_stderr, "** img error: Unrecognized image_method %s",
+		 userSpecifiedMethod);
+  fprintf(vis_stderr,  "using default method.\n");
+
+  return IMGDEFAULT_METHOD;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes an imageInfo structure for the given method and
+  direction.]
+
+  Description [Initializes an imageInfo structure.  MethodType specifies which
+  image computation method to use.  If methodType is Img_Default_c, then if
+  the user-settable flag "image_method" has been set, then this method is
+  used, otherwise some default is used. DirectionType specifies which types of
+  image computations will be performed (forward, backward, or both).
+  Method-specific initialization takes into account the value of relevant
+  parameters in the global flag table.<p>
+
+  MddNetwork is a graph representing the functions to be used.  Each vertex of
+  the graph contains a multi-valued function (MVF) and an MDD id.  The MVF
+  gives the function of the vertex in terms of the MDD ids of the immediate
+  fanins of the vertex.<p>
+
+  Roots is an array of char* specifying the vertices of the graph which
+  represent those functions for which we want to compute the image (it must
+  not be empty); for example, for an FSM, roots represent the next state
+  functions.  DomainVars is an array of mddIds; for an FSM, these are the
+  present state variables.  Subsets of the domain are defined over these
+  variables. RangeVars is an array of mddIds over which the range is
+  expressed; for an FSM, these are the next state variables.  This array must
+  be in one-to-one correspondence with the array of roots.  QuantifyVars is an
+  array of mddIds, representing variables to be quantified from results of
+  backward images; for an FSM, these are the input variables.  This array may
+  be empty. No copies are made of any of the input parameters, and thus it is
+  the application's responsibility to free this data *after* the returned
+  Img_ImageInfo_t is freed.]
+
+  Comment     [To add a new method, see the instructions at the top of imgInt.h.]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoComputeFwd Img_ImageInfoComputeBwd Img_ImageInfoFree]
+
+******************************************************************************/
+Img_ImageInfo_t *
+Img_ImageInfoInitialize(
+  Img_ImageInfo_t *imageInfo,
+  graph_t * mddNetwork,
+  array_t * roots,
+  array_t * domainVars,
+  array_t * rangeVars,
+  array_t * quantifyVars,
+  mdd_t * domainCube,
+  mdd_t * rangeCube,
+  mdd_t * quantifyCube,
+  Ntk_Network_t * network,
+  Img_MethodType methodType,
+  Img_DirectionType  directionType,
+  int FAFWFlag,
+  mdd_t *Winning)
+{
+  char *flagValue;
+  int verbosity;
+  mdd_manager *mddManager = Part_PartitionReadMddManager(mddNetwork);
+  int updateFlag = 0;
+
+  assert(array_n(roots) != 0);
+
+  /* If it does not exist, create a new one and initialize fields appropriately
+  */
+  if (imageInfo == NIL(Img_ImageInfo_t)) {
+    imageInfo = ALLOC(Img_ImageInfo_t, 1);
+    memset(imageInfo, 0, sizeof(Img_ImageInfo_t));
+    imageInfo->directionType = directionType;
+    if (Cmd_FlagReadByName("linear_optimize")) 
+      imageInfo->linearOptimize = Opt_NS;
+
+    /*
+     * Initialization of the function structure inside ImageInfo .
+     * Since no duplication is needed, this process is not encapsulated
+     * inside a static procedure.
+     */
+    imageInfo->functionData.FAFWFlag     = FAFWFlag;
+    imageInfo->functionData.Winning     = Winning;
+    imageInfo->functionData.mddNetwork   = mddNetwork;
+    imageInfo->functionData.roots        = roots;
+    imageInfo->functionData.domainVars   = domainVars;
+    imageInfo->functionData.rangeVars    = rangeVars;
+    imageInfo->functionData.quantifyVars = quantifyVars;
+    imageInfo->functionData.domainCube   = domainCube;
+    imageInfo->functionData.rangeCube    = rangeCube;
+    imageInfo->functionData.quantifyCube = quantifyCube;
+    imageInfo->functionData.domainBddVars = mdd_id_array_to_bdd_array(
+						mddManager, domainVars);
+    imageInfo->functionData.rangeBddVars = mdd_id_array_to_bdd_array(
+						mddManager, rangeVars);
+    imageInfo->functionData.quantifyBddVars = mdd_id_array_to_bdd_array(
+						mddManager, quantifyVars);
+    if (bdd_get_package_name() == CUDD) {
+      int i, nVars, idD, idR;
+      mdd_t *varD, *varR;
+
+      nVars = bdd_num_vars(mddManager);
+      imageInfo->functionData.permutD2R = ALLOC(int, sizeof(int) * nVars);
+      imageInfo->functionData.permutR2D = ALLOC(int, sizeof(int) * nVars);
+      for (i = 0; i < nVars; i++) {
+	imageInfo->functionData.permutD2R[i] = i;
+	imageInfo->functionData.permutR2D[i] = i;
+      }
+      nVars = array_n(imageInfo->functionData.rangeBddVars);
+      for (i = 0; i < nVars; i++) {
+	varD = array_fetch(bdd_t *, imageInfo->functionData.domainBddVars, i);
+	varR = array_fetch(bdd_t *, imageInfo->functionData.rangeBddVars, i);
+	idD = (int)bdd_top_var_id(varD);
+	idR = (int)bdd_top_var_id(varR);
+	imageInfo->functionData.permutD2R[idD] = idR;
+	imageInfo->functionData.permutR2D[idR] = idD;
+      }
+    } else {
+      imageInfo->functionData.permutD2R = NIL(int);
+      imageInfo->functionData.permutR2D = NIL(int);
+    }
+    if (domainCube)
+      imageInfo->functionData.createVarCubesFlag = 1;
+    imageInfo->functionData.network      = network;
+    imageInfo->methodData                = NIL(void);
+    updateFlag = 1;
+  }
+
+  /*
+   * If methodType is default, use user-specified method if set.
+   */
+  if (methodType == Img_Default_c)
+    methodType = Img_UserSpecifiedMethod();
+
+  /* If image_method changes, we need to free existing method data and
+   * to update proper function calls.
+   */
+  if (imageInfo->methodData) {
+    if (imageInfo->methodType != methodType) {
+      (*imageInfo->imageFreeProc)(imageInfo->methodData);
+      imageInfo->methodData = NIL(void);
+      updateFlag = 1;
+    }
+  }
+
+  if (updateFlag) {
+    imageInfo->methodType = methodType;
+    switch (methodType) {
+    case Img_Monolithic_c:
+      imageInfo->imageComputeFwdProc = ImgImageInfoComputeFwdMono;
+      imageInfo->imageComputeBwdProc = ImgImageInfoComputeBwdMono;
+      imageInfo->imageComputeFwdWithDomainVarsProc =
+	ImgImageInfoComputeFwdWithDomainVarsMono;
+      imageInfo->imageComputeBwdWithDomainVarsProc =
+	ImgImageInfoComputeBwdWithDomainVarsMono;
+      imageInfo->imageFreeProc       = ImgImageInfoFreeMono;
+      imageInfo->imagePrintMethodParamsProc =
+	ImgImageInfoPrintMethodParamsMono;
+      break;
+
+    case Img_Tfm_c:
+    case Img_Hybrid_c:
+      imageInfo->imageComputeFwdProc = ImgImageInfoComputeFwdTfm;
+      imageInfo->imageComputeBwdProc = ImgImageInfoComputeBwdTfm;
+      imageInfo->imageComputeFwdWithDomainVarsProc =
+	ImgImageInfoComputeFwdWithDomainVarsTfm;
+      imageInfo->imageComputeBwdWithDomainVarsProc =
+	ImgImageInfoComputeBwdWithDomainVarsTfm;
+      imageInfo->imageFreeProc       = ImgImageInfoFreeTfm;
+      imageInfo->imagePrintMethodParamsProc =
+	ImgImageInfoPrintMethodParamsTfm;
+      break;
+
+    case Img_Linear_Range_c:
+    case Img_Iwls95_c:
+    case Img_Mlp_c:
+    case Img_Linear_c:
+      imageInfo->imageComputeFwdProc = ImgImageInfoComputeFwdIwls95;
+      imageInfo->imageComputeBwdProc = ImgImageInfoComputeBwdIwls95;
+      imageInfo->imageComputeFwdWithDomainVarsProc =
+	ImgImageInfoComputeFwdWithDomainVarsIwls95;
+      imageInfo->imageComputeBwdWithDomainVarsProc =
+	ImgImageInfoComputeBwdWithDomainVarsIwls95;
+      imageInfo->imageFreeProc       = ImgImageInfoFreeIwls95;
+      imageInfo->imagePrintMethodParamsProc =
+	ImgImageInfoPrintMethodParamsIwls95;
+      break;
+
+    default:
+      fail("** img error: Unexpected type when updating image method");
+    }
+    imageInfo->fwdTrMinimizedFlag = FALSE;
+    imageInfo->bwdTrMinimizedFlag = FALSE;
+    imageInfo->printMinimizeStatus = 0;
+    imageInfo->savedRelation = NIL(void);
+
+    flagValue = Cmd_FlagReadByName("image_verbosity");
+    if (flagValue != NIL(char)) {
+      verbosity = atoi(flagValue);
+      imageInfo->verbosity = verbosity;
+      if (verbosity == 1)
+	imageInfo->printMinimizeStatus = 1;
+      else if (verbosity > 1)
+	imageInfo->printMinimizeStatus = 2;
+    }
+  }
+
+  /*
+   * Perform method-specific initialization of methodData.
+   */
+  switch (imageInfo->methodType) {
+      case Img_Monolithic_c:
+        imageInfo->methodData =
+            ImgImageInfoInitializeMono(imageInfo->methodData,
+                                       &(imageInfo->functionData),
+                                       directionType);
+        break;
+      case Img_Tfm_c:
+      case Img_Hybrid_c:
+        imageInfo->methodData =
+            ImgImageInfoInitializeTfm(imageInfo->methodData,
+                                      &(imageInfo->functionData),
+                                      directionType,
+				      imageInfo->methodType);
+        break;
+      case Img_Iwls95_c:
+      case Img_Mlp_c:
+      case Img_Linear_c:
+      case Img_Linear_Range_c:
+        imageInfo->methodData =
+            ImgImageInfoInitializeIwls95(imageInfo->methodData,
+                                         &(imageInfo->functionData),
+                                         directionType,
+					 imageInfo->methodType);
+        break;
+
+      default:
+        fail("IMG Error : Unexpected type when initalizing image method");
+  }
+  return imageInfo;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Check the given address of mdd_t is same as the  functionData.quantifyCube.]
+
+  Description [This function is for remove memory leakage.]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoInitialize]
+
+******************************************************************************/
+
+int Img_IsQuantifyCubeSame(
+  Img_ImageInfo_t *imageInfo,
+  mdd_t *quantifyCube)
+{
+  if(imageInfo->functionData.quantifyCube == quantifyCube)
+    return (1);
+  else 
+    return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Check the given address of array+t is same as the  functionData.quantifyArray.]
+
+  Description [This function is for remove memory leakage.]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoInitialize]
+
+******************************************************************************/
+
+int Img_IsQuantifyArraySame(
+  Img_ImageInfo_t *imageInfo,
+  array_t *quantifyArray)
+{
+  if(imageInfo->functionData.quantifyVars == quantifyArray)
+    return (1);
+  else 
+    return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Updates present state and primary input variables.]
+
+  Description [Updates present state and primary input variables.
+  This function is called after calling ImageInfoInitialize for a
+  subFsm.]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoInitialize]
+
+******************************************************************************/
+void
+Img_ImageInfoUpdateVariables(
+  Img_ImageInfo_t *imageInfo,
+  graph_t * mddNetwork,
+  array_t * domainVars,
+  array_t * quantifyVars,
+  mdd_t * domainCube,
+  mdd_t * quantifyCube)
+{
+  mdd_manager *mddManager = Part_PartitionReadMddManager(mddNetwork);
+
+  imageInfo->functionData.domainVars   = domainVars;
+  imageInfo->functionData.quantifyVars = quantifyVars;
+  imageInfo->functionData.domainCube   = domainCube;
+  imageInfo->functionData.quantifyCube = quantifyCube;
+  mdd_array_free(imageInfo->functionData.domainBddVars);
+  imageInfo->functionData.domainBddVars = mdd_id_array_to_bdd_array(
+						mddManager, domainVars);
+  mdd_array_free(imageInfo->functionData.quantifyBddVars);
+  imageInfo->functionData.quantifyBddVars = mdd_id_array_to_bdd_array(
+						mddManager, quantifyVars);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Sets the flag to allow the next image computation to
+  return a subset of the actual image.]
+
+  Description [Sets the flag to allow the next image computation to
+  return a subset of the actual image. Default is to not allow partial
+  image computations. This flag is reset at the end of every
+  image/preimage computation i.e., has to be specified before every
+  image/preimage computation if partial image is desired. ]
+
+  SideEffects [Flag is reset at the end of every image/preimage
+  computation.]
+
+  SeeAlso     [Img_ImageWasPartialImage]
+
+******************************************************************************/
+void
+Img_ImageAllowPartialImage(Img_ImageInfo_t *info,
+			  boolean value)
+{
+ if (info->methodType == Img_Iwls95_c || info->methodType == Img_Mlp_c) {
+   ImgImageAllowPartialImageIwls95(info->methodData, value);
+ }
+ return;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Prints partial image options.]
+
+  Description [Prints partial image options.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Img_ImagePrintPartialImageOptions(void)
+{
+  ImgPrintPartialImageOptions();
+  return;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Queries whether the last image computation was partial.]
+
+  Description [Queries whether the last image computation was
+  partial. Reset before every image/preimage computation i.e., this
+  information is valid for only the previous image/preimage
+  computation.]
+
+  SideEffects [Reset before every image/preimage computation.]
+
+  SeeAlso     [Img_ImageAllowPartialImage]
+
+******************************************************************************/
+boolean
+Img_ImageWasPartial(Img_ImageInfo_t *info)
+{
+ if (info->methodType == Img_Iwls95_c || info->methodType == Img_Mlp_c)
+   return (ImgImageWasPartialIwls95(info->methodData));
+ else
+   return FALSE;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Computes the forward image of a set and expresses it in terms of
+  domain variables.]
+
+  Description [Computes the forward image of a set and expresses it in terms
+  of domain variables. FromLowerBound, fromUpperBound, and toCareSet are
+  expressed in terms of domain variables. See Img_ImageInfoComputeFwd for more
+  information. (Takes care set as an array.)]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoComputeFwd]
+
+******************************************************************************/
+mdd_t *
+Img_ImageInfoComputeImageWithDomainVars(
+  Img_ImageInfo_t * imageInfo,
+  mdd_t           * fromLowerBound,
+  mdd_t           * fromUpperBound,
+  array_t         * toCareSetArray)
+{
+  mdd_t		*image;
+  mdd_manager	*mddManager;
+  long		peakMem;
+  int		peakLiveNode;
+
+  if (mdd_is_tautology(fromLowerBound, 0)){
+    mddManager = Part_PartitionReadMddManager(
+	imageInfo->functionData.mddNetwork);
+    return (mdd_zero(mddManager));
+  }
+  image  = ((*imageInfo->imageComputeFwdWithDomainVarsProc)
+            (&(imageInfo->functionData), imageInfo,
+             fromLowerBound, fromUpperBound, toCareSetArray));
+  nImgComps++;
+
+  if (imageInfo->verbosity >= 2 && bdd_get_package_name() == CUDD) {
+    mddManager = Part_PartitionReadMddManager(
+	imageInfo->functionData.mddNetwork);
+    peakMem = bdd_read_peak_memory(mddManager);
+    peakLiveNode = bdd_read_peak_live_node(mddManager);
+    fprintf(vis_stdout, "** img info: current peak memory = %ld\n", peakMem);
+    fprintf(vis_stdout, "** img info: current peak live nodes = %d\n",
+	    peakLiveNode);
+  }
+#ifndef NDEBUG
+  assert(CheckImageValidity(
+    Part_PartitionReadMddManager(imageInfo->functionData.mddNetwork),
+    image,
+    imageInfo->functionData.rangeVars,
+    imageInfo->functionData.quantifyVars));
+#endif
+  return(image);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Computes the forward image of a set and expresses it in terms of
+  domain variables.]
+
+  Description [Computes the forward image of a set and expresses it in terms
+  of domain variables. FromLowerBound, fromUpperBound, and toCareSet are
+  expressed in terms of domain variables. See Img_ImageInfoComputeFwd for more
+  information. (Takes care states as a set.)]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoComputeFwd]
+
+******************************************************************************/
+mdd_t *
+Img_ImageInfoComputeFwdWithDomainVars(
+  Img_ImageInfo_t * imageInfo,
+  mdd_t           * fromLowerBound,
+  mdd_t           * fromUpperBound,
+  mdd_t           * toCareSet)
+{
+  array_t	*toCareSetArray;
+  mdd_t		*image;
+
+  toCareSetArray = array_alloc(mdd_t *, 0);
+  array_insert(mdd_t *, toCareSetArray, 0, toCareSet);
+  image = Img_ImageInfoComputeImageWithDomainVars(imageInfo, fromLowerBound,
+					fromUpperBound, toCareSetArray);
+  array_free(toCareSetArray);
+  return(image);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the forward image of a set.]
+
+  Description [Computes the forward image of a set, under the function vector
+  in imageInfo, using the image computation method specified in imageInfo.  The
+  set for which the forward image is computed is some set containing
+  fromLowerBound and contained in fromUpperBound. The exact set used is chosen
+  to simplify the computation.  ToCareSet specifies those forward image points
+  of interest; any points not in this set may or may not belong to the returned
+  set.  The MDDs fromLowerBound and fromUpperBound are defined over the domain
+  variables.  The MDD toCareSet and the returned MDD are defined over the range
+  variables. If fromLowerBound is zero, then zero will be returned. (Takes care
+  states as an array.)]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoInitialize Img_ImageInfoComputeBwd
+  Img_ImageInfoFree Img_ImageInfoComputeFwdWithDomainVars]
+
+******************************************************************************/
+mdd_t *
+Img_ImageInfoComputeFwd(Img_ImageInfo_t * imageInfo,
+                        mdd_t * fromLowerBound,
+                        mdd_t * fromUpperBound,
+                        array_t * toCareSetArray)
+{
+  mdd_t *image;
+  if (mdd_is_tautology(fromLowerBound, 0)){
+    mdd_manager *mddManager = Part_PartitionReadMddManager(
+	imageInfo->functionData.mddNetwork);
+    return (mdd_zero(mddManager));
+  }
+  image =  ((*imageInfo->imageComputeFwdProc) (&(imageInfo->functionData),
+                                               imageInfo,
+                                               fromLowerBound,
+                                               fromUpperBound,
+                                               toCareSetArray));
+  nImgComps++;
+#ifndef NDEBUG
+  assert(CheckImageValidity(
+    Part_PartitionReadMddManager(imageInfo->functionData.mddNetwork),
+    image,
+    imageInfo->functionData.domainVars,
+    imageInfo->functionData.quantifyVars));
+#endif
+  return image;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the backward image of a set expressed in terms of domain
+  variables.]
+
+  Description [Computes the backward image of a set expressed in terms
+  of domain variables. FromLowerBound, fromUpperBound, and
+  toCareSetArray are expressed in terms of domain variables. See
+  Img_ImageInfoComputeBwd for more information.  This function takes a
+  care-set array, as opposed to Img_ImageInfoComputeBwdWithDomainVars,
+  which takes a care set.]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoComputeBwd]
+
+******************************************************************************/
+mdd_t *
+Img_ImageInfoComputePreImageWithDomainVars(
+  Img_ImageInfo_t * imageInfo,
+  mdd_t           * fromLowerBound,
+  mdd_t           * fromUpperBound,
+  array_t         * toCareSetArray)
+{
+  mdd_t *image;
+  if (mdd_is_tautology(fromLowerBound, 0)){
+    mdd_manager *mddManager = Part_PartitionReadMddManager(imageInfo->functionData.mddNetwork);
+    return (mdd_zero(mddManager));
+  }
+  image =  ((*imageInfo->imageComputeBwdWithDomainVarsProc)
+            (&(imageInfo->functionData), imageInfo,
+             fromLowerBound, fromUpperBound, toCareSetArray));
+  nPreComps++;
+#ifndef NDEBUG
+  assert(CheckImageValidity(
+    Part_PartitionReadMddManager(imageInfo->functionData.mddNetwork),
+    image,
+    imageInfo->functionData.rangeVars,
+    imageInfo->functionData.quantifyVars));
+#endif
+  return image;
+}
+/**Function********************************************************************
+
+  Synopsis [Computes the backward image of a set expressed in terms of domain
+  variables.]
+
+  Description [Computes the backward image of a set expressed in terms
+  of domain variables. FromLowerBound, fromUpperBound, and
+  toCareSetArray are expressed in terms of domain variables. See
+  Img_ImageInfoComputeBwd for more information.  This function takes a
+  care-set array, as opposed to Img_ImageInfoComputeBwdWithDomainVars,
+  which takes a care set.]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoComputeBwd]
+
+******************************************************************************/
+mdd_t *
+Img_ImageInfoComputeEXWithDomainVars(
+  Img_ImageInfo_t * imageInfo,
+  mdd_t           * fromLowerBound,
+  mdd_t           * fromUpperBound,
+  array_t         * toCareSetArray)
+{
+  mdd_t *image;
+  if (mdd_is_tautology(fromLowerBound, 0)){
+    mdd_manager *mddManager = Part_PartitionReadMddManager(imageInfo->functionData.mddNetwork);
+    return (mdd_zero(mddManager));
+  }
+  image =  ((*imageInfo->imageComputeBwdWithDomainVarsProc)
+            (&(imageInfo->functionData), imageInfo,
+             fromLowerBound, fromUpperBound, toCareSetArray));
+  nPreComps++;
+
+  return image;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the backward image of a set expressed in terms of domain
+  variables.]
+
+  Description [Computes the backward image of a set expressed in terms of
+  domain variables. FromLowerBound, fromUpperBound, and toCareSet are
+  expressed in terms of domain variables. See Img_ImageInfoComputeBwd for more
+  information.  This function takes a care set, as opposed to ComputeBwd,
+  which takes a care-set array.]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoComputeBwd]
+
+******************************************************************************/
+mdd_t *
+Img_ImageInfoComputeBwdWithDomainVars(
+  Img_ImageInfo_t * imageInfo,
+  mdd_t           * fromLowerBound,
+  mdd_t           * fromUpperBound,
+  mdd_t           * toCareSet)
+{
+  array_t	*toCareSetArray;
+  mdd_t		*preImage;
+
+  toCareSetArray = array_alloc(mdd_t *, 0);
+  array_insert(mdd_t *, toCareSetArray, 0, toCareSet);
+  preImage = Img_ImageInfoComputePreImageWithDomainVars(imageInfo,
+			fromLowerBound, fromUpperBound, toCareSetArray);
+  array_free(toCareSetArray);
+  return(preImage);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the backward image of a set.]
+
+  Description [Computes the backward image of a set, under the function vector
+  in imageInfo, using the image computation method specified in imageInfo.  The
+  set for which the backward image is computed is some set containing
+  fromLowerBound and contained in fromUpperBound.  The exact set used is chosen
+  to simplify the computation.  ToCareSet specifies those backward image points
+  of interest; any points not in this set may or may not belong to the returned
+  set.  The MDDs fromLowerBound and fromUpperBound are defined over the range
+  variables.  The MDD toCareSet and the returned MDD are defined over the
+  domain variables. If fromLowerBound is zero, then zero will be returned.]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoInitialize Img_ImageInfoComputeFwd
+  Img_ImageInfoFree Img_ImageInfoComputeBwdWithDomainVars]
+
+******************************************************************************/
+mdd_t *
+Img_ImageInfoComputeBwd(Img_ImageInfo_t * imageInfo,
+                        mdd_t * fromLowerBound,
+                        mdd_t * fromUpperBound,
+                        array_t * toCareSetArray)
+{
+  mdd_t *image;
+  if (mdd_is_tautology(fromLowerBound, 0)){
+    mdd_manager *mddManager =
+        Part_PartitionReadMddManager(imageInfo->functionData.mddNetwork);
+    return (mdd_zero(mddManager));
+  }
+  image =  ((*imageInfo->imageComputeBwdProc) (&(imageInfo->functionData),
+                                             imageInfo,
+                                             fromLowerBound,
+                                             fromUpperBound,
+                                             toCareSetArray));
+  nPreComps++;
+#ifndef NDEBUG
+  assert(CheckImageValidity(
+    Part_PartitionReadMddManager(imageInfo->functionData.mddNetwork),
+    image,
+    imageInfo->functionData.rangeVars,
+    imageInfo->functionData.quantifyVars));
+#endif
+  return image;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the memory associated with imageInfo.]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoInitialize Img_ImageInfoComputeFwd
+  Img_ImageInfoComputeBwd]
+
+******************************************************************************/
+void
+Img_ImageInfoFree(Img_ImageInfo_t * imageInfo)
+{
+  (*imageInfo->imageFreeProc) (imageInfo->methodData);
+  if (imageInfo->functionData.domainBddVars)
+    mdd_array_free(imageInfo->functionData.domainBddVars);
+  if (imageInfo->functionData.rangeBddVars)
+    mdd_array_free(imageInfo->functionData.rangeBddVars);
+  if (imageInfo->functionData.quantifyBddVars)
+    mdd_array_free(imageInfo->functionData.quantifyBddVars);
+  if (imageInfo->functionData.permutD2R)
+    FREE(imageInfo->functionData.permutD2R);
+  if (imageInfo->functionData.permutR2D)
+    FREE(imageInfo->functionData.permutR2D);
+  if (imageInfo->savedRelation)
+    mdd_array_free((array_t *) imageInfo->savedRelation);
+  FREE(imageInfo);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the memory associated with imageInfo.]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoInitialize Img_ImageInfoComputeFwd
+  Img_ImageInfoComputeBwd]
+
+******************************************************************************/
+void
+Img_ImageInfoFreeFAFW(Img_ImageInfo_t * imageInfo)
+{
+  if (imageInfo->functionData.quantifyVars)
+    mdd_array_free(imageInfo->functionData.quantifyVars);
+  if (imageInfo->functionData.quantifyCube)
+    mdd_free(imageInfo->functionData.quantifyCube);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a string giving the method type of an imageInfo.]
+
+  Description [Returns a string giving the method type of an imageInfo. It is
+  the user's responsibility to free this string.]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoInitialize]
+
+******************************************************************************/
+char *
+Img_ImageInfoObtainMethodTypeAsString(Img_ImageInfo_t * imageInfo)
+{
+  char *methodString;
+  Img_MethodType methodType = imageInfo->methodType;
+
+  switch (methodType) {
+    case Img_Monolithic_c:
+      methodString = util_strsav("monolithic");
+      break;
+    case Img_Tfm_c:
+      methodString = util_strsav("tfm");
+      break;
+    case Img_Hybrid_c:
+      methodString = util_strsav("hybrid");
+      break;
+    case Img_Iwls95_c:
+      methodString = util_strsav("iwls95");
+      break;
+    case Img_Mlp_c:
+      methodString = util_strsav("mlp");
+      break;
+    case Img_Linear_c:
+      methodString = util_strsav("linear");
+      break;
+    case Img_Default_c:
+      methodString = util_strsav("default");
+      break;
+    default:
+      fail("IMG Error : Unexpected type when initalizing image method");
+  }
+  return methodString;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the method type of an imageInfo.]
+
+  Description [Returns the method type of an imageInfo.]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoInitialize]
+
+******************************************************************************/
+Img_MethodType
+Img_ImageInfoObtainMethodType(Img_ImageInfo_t * imageInfo)
+{
+  return(imageInfo->methodType);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the method type of an imageInfo.]
+
+  Description [Returns the method type of an imageInfo.]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoInitialize]
+
+******************************************************************************/
+Img_OptimizeType
+Img_ImageInfoObtainOptimizeType(Img_ImageInfo_t * imageInfo)
+{
+  return(imageInfo->linearOptimize);
+}
+
+/**Function********************************************************************
+  
+  Synopsis    [set optimization relation flag .]
+
+  Description [set optimization relation flag .]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoInitialize]
+
+******************************************************************************/
+void
+Img_ImageInfoSetUseOptimizedRelationFlag(Img_ImageInfo_t * imageInfo)
+{
+  imageInfo->useOptimizedRelationFlag = 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [reset optimization relation flag .]
+
+  Description [reset optimization relation flag .]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoInitialize]
+
+******************************************************************************/
+void
+Img_ImageInfoResetUseOptimizedRelationFlag(Img_ImageInfo_t * imageInfo)
+{
+  imageInfo->useOptimizedRelationFlag = 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Reset linear compute range flag.]
+
+  Description  [Reset linear compute range flag.]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoInitialize]
+
+******************************************************************************/
+void
+Img_ImageInfoResetLinearComputeRange(Img_ImageInfo_t * imageInfo)
+{
+  imageInfo->linearComputeRange = 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Set linear compute range flag.]
+
+  Description [Set linear compute range flag.]
+
+  SideEffects []
+
+  SeeAlso     [Img_ImageInfoInitialize]
+
+******************************************************************************/
+void
+Img_ImageInfoSetLinearComputeRange(Img_ImageInfo_t * imageInfo)
+{
+  imageInfo->linearComputeRange = 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Prints information about the image technique currently used.]
+
+  Description [Prints information about the image technique currently used.]
+
+  SideEffects [None.]
+
+******************************************************************************/
+void
+Img_ImageInfoPrintMethodParams(Img_ImageInfo_t *imageInfo, FILE *fp)
+{
+  (*imageInfo->imagePrintMethodParamsProc)(imageInfo->methodData, fp);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Resets the flag that transition relation is minimized.]
+
+  Description [Resets the flag that transition relation is minimized.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Img_ResetTrMinimizedFlag(Img_ImageInfo_t *imageInfo,
+	Img_DirectionType directionType)
+{
+  if (directionType == Img_Forward_c || directionType == Img_Both_c)
+    imageInfo->fwdTrMinimizedFlag = FALSE;
+  if (directionType == Img_Backward_c || directionType == Img_Both_c)
+    imageInfo->bwdTrMinimizedFlag = FALSE;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns current method of minimizing transition relation.]
+
+  Description [Returns current method of minimizing transition relation. Default is restrict.]
+
+  SideEffects []
+
+******************************************************************************/
+Img_MinimizeType
+Img_ReadMinimizeMethod(void)
+{
+
+  int			value;
+  char			*flagValue;
+  Img_MinimizeType	minimizeMethod = Img_Restrict_c;
+
+  flagValue = Cmd_FlagReadByName("image_minimize_method");
+  if (flagValue != NIL(char)) {
+    sscanf(flagValue, "%d", &value);
+    switch (value) {
+    case 0 :
+      minimizeMethod = Img_Restrict_c;
+      break;
+    case 1 :
+      minimizeMethod = Img_Constrain_c;
+      break;
+    case 2 :
+      if (bdd_get_package_name() != CUDD) {
+	fprintf(vis_stderr, "** img error : Compact in image_minimize_method ");
+	fprintf(vis_stderr, "is currently supported only by CUDD. ***\n");
+	fprintf(vis_stderr,
+	  "** img error : Reverting to default minimize method : restrict\n");
+	break;
+      }
+      minimizeMethod = Img_Compact_c;
+      break;
+    case 3 :
+      if (bdd_get_package_name() != CUDD) {
+	fprintf(vis_stderr, "** img error : Squeeze in image_minimize_method ");
+	fprintf(vis_stderr, "is currently supported only by CUDD. ***\n");
+	fprintf(vis_stderr,
+	  "** img error : Reverting to default minimize method : restrict\n");
+	break;
+      }
+      minimizeMethod = Img_Squeeze_c;
+      break;
+    case 4 :
+      minimizeMethod = Img_And_c;
+      break;
+    default :
+      fprintf(vis_stderr,
+      "** img error : invalid value %s for image_minimize_method[0-4]. ***\n",
+	      flagValue);
+      fprintf(vis_stderr,
+	"** img error : Reverting to default minimize method : restrict\n");
+      break;
+    }
+  }
+  return(minimizeMethod);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Minimizes transition relation with given constraint if it
+  hasn't been minimized already.]
+
+  Description [Minimizes transition relation with given constraint if it hasn't
+  been minimized already (does nothing otherwise). The constraint is expressed
+  as an array of conjuncts of BDDs, The transition relation is minimized with
+  each one of the conjuncts.
+
+  <p>The boolean reorderIwls95Clusters is only relevant to the iwls95 image
+  method.  It causes the clusters to be ordered again after minimization.
+  
+  <p>The conjuncts have to be in terms of present-state variables or inputs.
+  Next-state variables are not allowed.
+
+  <p>For the hybrid and tfm methods, for image, we can only minimize wrt a set
+  that includes any possible argument.  For preimage, the result is only
+  correct for as far as it lies within the set that the TR is minimized with.
+  That means that reachability info can be usefully applied here.
+
+  <p>For the other methods, we can also minimize wrt different sets.  The
+  edges in the TR that are outgoing from states not in this set may then get
+  removed.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Img_MinimizeTransitionRelation(
+  Img_ImageInfo_t *imageInfo,
+  array_t *constrainArray,
+  Img_MinimizeType minimizeMethod,
+  Img_DirectionType directionType,
+  boolean reorderIwls95Clusters)
+{
+  if (minimizeMethod == Img_DefaultMinimizeMethod_c)
+   minimizeMethod = Img_ReadMinimizeMethod();
+
+  switch (imageInfo->methodType) {
+    case Img_Monolithic_c:
+      if (imageInfo->fwdTrMinimizedFlag)
+	break;
+      ImgMinimizeTransitionRelationMono(imageInfo, constrainArray,
+      	minimizeMethod, imageInfo->printMinimizeStatus);
+      imageInfo->fwdTrMinimizedFlag = TRUE;
+      break;
+    case Img_Tfm_c:
+    case Img_Hybrid_c:
+      if (imageInfo->fwdTrMinimizedFlag)
+	break;
+      ImgMinimizeTransitionFunction(imageInfo->methodData, constrainArray,
+			minimizeMethod, directionType,
+			imageInfo->printMinimizeStatus);
+      if (directionType == Img_Forward_c || directionType == Img_Both_c)
+	imageInfo->fwdTrMinimizedFlag = TRUE;
+      if (directionType == Img_Backward_c || directionType == Img_Both_c)
+	imageInfo->bwdTrMinimizedFlag = TRUE;
+      break;
+    case Img_Iwls95_c:
+    case Img_Mlp_c:
+    case Img_Linear_c:
+      if (directionType == Img_Forward_c || directionType == Img_Both_c) {
+	if (imageInfo->fwdTrMinimizedFlag == FALSE) {
+	  ImgMinimizeTransitionRelationIwls95(imageInfo->methodData,
+					      &(imageInfo->functionData),
+					      constrainArray, minimizeMethod,
+					      Img_Forward_c,
+					      reorderIwls95Clusters,
+					      imageInfo->printMinimizeStatus);
+	  imageInfo->fwdTrMinimizedFlag = TRUE;
+	}
+      }
+      if (directionType == Img_Backward_c || directionType == Img_Both_c) {
+	if (imageInfo->bwdTrMinimizedFlag == FALSE) {
+	  ImgMinimizeTransitionRelationIwls95(imageInfo->methodData,
+					      &(imageInfo->functionData),
+					      constrainArray, minimizeMethod,
+					      Img_Backward_c, 
+					      reorderIwls95Clusters,
+					      imageInfo->printMinimizeStatus);
+	  imageInfo->bwdTrMinimizedFlag = TRUE;
+	}
+      }
+      break;
+    default:
+      fail("** img error: Unexpected type when minimizing transition relation");
+  }
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Minimizes an image with given constraint.]
+
+  Description [Minimizes an image with given constraint. This function
+  can be used to minimize any BDDs.
+  
+  <p>If underapprox is 1, the the bdds are underapproximated.  If it is 0, they
+  are overapproximated, and the minimizeMethod has to be either ornot or
+  squeeze.
+  ]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Img_MinimizeImage(
+  mdd_t *image,
+  mdd_t *constraint,
+  Img_MinimizeType method,
+  boolean underapprox)
+{
+  mdd_t *newImage;
+  mdd_t *l, *u;
+
+  if (method == Img_DefaultMinimizeMethod_c)
+    method = Img_ReadMinimizeMethod();
+
+  if(underapprox){
+    switch (method) {
+    case Img_Restrict_c :
+      newImage = bdd_minimize(image, constraint);
+      break;
+    case Img_Constrain_c :
+      newImage = bdd_cofactor(image, constraint);
+      break;
+    case Img_Compact_c :
+      newImage = bdd_compact(image, constraint);
+      break;
+    case Img_Squeeze_c :
+      l = bdd_and(image, constraint, 1, 1);
+      u = bdd_or(image, constraint, 1, 0);
+      newImage = bdd_squeeze(l, u);
+      if (bdd_size(newImage) >= bdd_size(image)) {
+	bdd_free(newImage);
+	newImage = bdd_dup(image);
+      }
+      mdd_free(l);
+      mdd_free(u);
+      break;
+    case Img_And_c :
+      newImage = bdd_and(image, constraint, 1, 1);
+      break;
+    default :
+      fail("** img error : Unexpected type when minimizing an image");
+    }
+  }else{ /* if underapprox */
+    switch (method) {
+    case Img_Squeeze_c :
+      l = image;
+      u = bdd_or(image, constraint, 1, 0);
+      newImage = bdd_squeeze(l, u);
+      if (bdd_size(newImage) >= bdd_size(image)) {
+	bdd_free(newImage);
+	newImage = bdd_dup(image);
+      }
+      mdd_free(u);
+      break;
+    case Img_OrNot_c :
+      newImage = bdd_or(image, constraint, 1, 0);
+      break;
+    default :
+      fail("** img error: Unexpected type when adding dont-cares to an image");
+    }
+  }/* if underapprox */
+    
+  return(newImage);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Adds a dont care set to the given image.]
+
+  Description [Adds a dont care set to the given image.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Img_AddDontCareToImage(
+  mdd_t *image,
+  mdd_t *constraint,
+  Img_MinimizeType method)
+{
+  return(Img_MinimizeImage(image, constraint, Img_Restrict_c, method));
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis [Minimizes a single bdd with a set of constraint.]
+
+  Description [Minimizes a bdd with given set of constraints.
+  Underapproximates if underapprox is true, otherwise overapproximated (in
+  which case method has to be ornot or squeeze).]
+
+  SideEffects [Img_MinimizeImage]
+
+******************************************************************************/
+mdd_t *
+Img_MinimizeImageArray(
+  mdd_t *image,
+  array_t *constraintArray,
+  Img_MinimizeType method,
+  boolean underapprox)
+{
+  int	i;
+  mdd_t *newImage, *tmpImage;
+  mdd_t *constraint;
+
+  if (method == Img_DefaultMinimizeMethod_c)
+    method = Img_ReadMinimizeMethod();
+
+  newImage = mdd_dup(image);
+  arrayForEachItem(mdd_t *, constraintArray, i, constraint) {
+    tmpImage = newImage;
+    newImage = Img_MinimizeImage(tmpImage, constraint, method, underapprox);
+    mdd_free(tmpImage);
+  }
+  return(newImage);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the flag whether to print the status of minimizing
+  transition relation.]
+
+  Description [Sets the flag whether to print the status of minimizing
+  transition relation.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Img_SetPrintMinimizeStatus(Img_ImageInfo_t *imageInfo, int status)
+{
+    if (status < 0 || status > 2)
+	(void)fprintf(vis_stderr,
+		"** img error: invalid value[%d] for status.\n", status);
+    else
+	imageInfo->printMinimizeStatus = status;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the flag whether to print the status of minimizing
+  transition relation.]
+
+  Description [Reads the flag whether to print the status of minimizing
+  transition relation.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+Img_ReadPrintMinimizeStatus(Img_ImageInfo_t *imageInfo)
+{
+    return(imageInfo->printMinimizeStatus);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Abstracts out given variables from transition relation.]
+
+  Description [Abstracts out given variables from transition relation.
+  abstractVars should be an array of bdd variables.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Img_AbstractTransitionRelation(Img_ImageInfo_t *imageInfo,
+	array_t *abstractVars, mdd_t *abstractCube,
+	Img_DirectionType directionType)
+{
+  switch (imageInfo->methodType) {
+    case Img_Monolithic_c:
+      ImgAbstractTransitionRelationMono(imageInfo, abstractVars,
+				abstractCube, imageInfo->printMinimizeStatus);
+      break;
+    case Img_Tfm_c:
+    case Img_Hybrid_c:
+      ImgAbstractTransitionFunction(imageInfo, abstractVars,
+				abstractCube, directionType,
+				imageInfo->printMinimizeStatus);
+      break;
+    case Img_Iwls95_c:
+    case Img_Mlp_c:
+    case Img_Linear_c:
+      ImgAbstractTransitionRelationIwls95(imageInfo, abstractVars,
+				abstractCube, directionType,
+				imageInfo->printMinimizeStatus);
+      break;
+    default:
+      fail("** img error : Unexpected type when abstracting transition relation");
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Duplicates the transition relation for backup.]
+
+  Description [Duplicates the transition relation for backup. Copies transition
+  relation as well as quantification schedule for temporary use.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Img_DupTransitionRelation(Img_ImageInfo_t *imageInfo,
+	Img_DirectionType directionType)
+{
+  switch (imageInfo->methodType) {
+    case Img_Monolithic_c:
+      ImgDuplicateTransitionRelationMono(imageInfo);
+      break;
+    case Img_Tfm_c:
+    case Img_Hybrid_c:
+      ImgDuplicateTransitionFunction(imageInfo, directionType);
+      break;
+    case Img_Iwls95_c:
+    case Img_Mlp_c:
+    case Img_Linear_c:
+      ImgDuplicateTransitionRelationIwls95(imageInfo, directionType);
+      break;
+    default:
+      fail("** img error: Unexpected type when duplicating transition relation");
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Restores original transition relation from saved.]
+
+  Description [Restores original transition relation from saved.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Img_RestoreTransitionRelation(Img_ImageInfo_t *imageInfo,
+	Img_DirectionType directionType)
+{
+
+  switch (imageInfo->methodType) {
+    case Img_Monolithic_c:
+      ImgRestoreTransitionRelationMono(imageInfo, directionType);
+      break;
+    case Img_Tfm_c:
+    case Img_Hybrid_c:
+      ImgRestoreTransitionFunction(imageInfo, directionType);
+      break;
+    case Img_Iwls95_c:
+    case Img_Mlp_c:
+    case Img_Linear_c:
+      ImgRestoreTransitionRelationIwls95(imageInfo, directionType);
+      break;
+    default:
+      fail("** img error : Unexpected type when backup transition relation");
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Approximate transition relation.]
+
+  Description [Approximate transition relation.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+Img_ApproximateTransitionRelation(Img_ImageInfo_t *imageInfo,
+				  bdd_approx_dir_t approxDir,
+				  bdd_approx_type_t approxMethod,
+				  int approxThreshold,
+				  double approxQuality,
+				  double approxQualityBias,
+				  Img_DirectionType directionType,
+				  mdd_t *bias)
+{
+  int unchanged = 0;
+  mdd_manager *mgr =
+    Part_PartitionReadMddManager(imageInfo->functionData.mddNetwork);
+
+  switch (imageInfo->methodType) {
+    case Img_Monolithic_c:
+      unchanged = ImgApproximateTransitionRelationMono(mgr, imageInfo,
+						approxDir, approxMethod,
+						approxThreshold,
+						approxQuality,
+						approxQualityBias, bias);
+      break;
+    case Img_Tfm_c:
+    case Img_Hybrid_c:
+      unchanged = ImgApproximateTransitionFunction(mgr,
+      						imageInfo->methodData,
+						approxDir, approxMethod,
+						approxThreshold,
+						approxQuality,
+						approxQualityBias,
+						directionType, bias);
+      break;
+    case Img_Iwls95_c:
+    case Img_Mlp_c:
+    case Img_Linear_c:
+      if (directionType == Img_Forward_c || directionType == Img_Both_c) {
+	unchanged = ImgApproximateTransitionRelationIwls95(mgr,
+	  					imageInfo->methodData,
+						approxDir, approxMethod,
+						approxThreshold,
+						approxQuality,
+						approxQualityBias,
+						Img_Forward_c, bias);
+      }
+      if (directionType == Img_Backward_c || directionType == Img_Both_c) {
+	unchanged += ImgApproximateTransitionRelationIwls95(mgr,
+	  					imageInfo->methodData,
+						approxDir, approxMethod,
+						approxThreshold,
+						approxQuality,
+						approxQualityBias,
+						Img_Backward_c, bias);
+      }
+      break;
+    default:
+      fail(
+       "** img error : Unexpected type when approximating transition relation");
+  }
+  return(unchanged);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Approximate image.]
+
+  Description [Approximate image.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Img_ApproximateImage(mdd_manager *mgr,
+		     mdd_t *image,
+		     bdd_approx_dir_t approxDir,
+		     bdd_approx_type_t approxMethod,
+		     int approxThreshold,
+		     double approxQuality,
+		     double approxQualityBias,
+		     mdd_t *bias)
+{
+  double quality;
+  double qualityBias;
+  int nvars = mdd_get_number_of_bdd_support(mgr, image);
+  mdd_t *approxImage;
+
+  if (approxQuality != 0.0)
+    quality = approxQuality;
+  else
+    quality = 1.0; /* default */
+
+  /* based on approximation method specified, compute subset or superset */
+  switch (approxMethod) {
+  case BDD_APPROX_HB:
+    approxImage = bdd_approx_hb(image, approxDir, nvars, approxThreshold);
+    break;
+  case BDD_APPROX_SP:
+    approxImage = bdd_approx_sp(image, approxDir, nvars, approxThreshold, 0);
+    break;
+  case BDD_APPROX_UA:
+    approxImage = bdd_approx_ua(image, approxDir, nvars, approxThreshold, 0,
+				quality);
+    break;
+  case BDD_APPROX_RUA:
+    approxImage = bdd_approx_remap_ua(image, approxDir, nvars, approxThreshold,
+				      quality);
+    break;
+  case BDD_APPROX_BIASED_RUA:
+    if (approxQualityBias != 0.0)
+      qualityBias = approxQualityBias;
+    else
+      qualityBias = 0.5; /* default */
+    approxImage = bdd_approx_biased_rua(image, approxDir, bias, nvars,
+					approxThreshold, quality, qualityBias);
+    break;
+  case BDD_APPROX_COMP:
+    approxImage = bdd_approx_compress(image, approxDir, nvars, approxThreshold);
+    break;
+  default:
+    assert(0);
+    approxImage = NIL(mdd_t);
+    break;
+  }
+
+  return(approxImage);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns 1 if partitioned transition relation is used.]
+
+  Description [Returns 1 if partitioned transition relation is used.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+Img_IsPartitionedTransitionRelation(Img_ImageInfo_t *imageInfo)
+{
+  if (imageInfo->methodType == Img_Iwls95_c ||
+      imageInfo->methodType == Img_Mlp_c ||
+      imageInfo->methodType == Img_Linear_c)
+    return(1);
+  else if (imageInfo->methodType == Img_Hybrid_c)
+    return(ImgIsPartitionedTransitionRelationTfm(imageInfo));
+  else
+    return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Resets number of image/preimage computation.]
+
+  Description [Resets number of image/preimage computation.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Img_ResetNumberOfImageComputation(Img_DirectionType imgDir)
+{
+  if (imgDir == Img_Forward_c || imgDir == Img_Both_c)
+    nImgComps = 0;
+  if (imgDir == Img_Backward_c || imgDir == Img_Both_c)
+    nPreComps = 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns number of image/preimage computation.]
+
+  Description [Returns number of image/preimage computation.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+Img_GetNumberOfImageComputation(Img_DirectionType imgDir)
+{
+  if (imgDir == Img_Forward_c)
+    return(nImgComps);
+  else if (imgDir == Img_Backward_c)
+    return(nPreComps);
+  else
+    return(nImgComps + nPreComps);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns current partitioned transition relation.]
+
+  Description [Returns current partitioned transition relation.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+Img_GetPartitionedTransitionRelation(Img_ImageInfo_t *imageInfo,
+				     Img_DirectionType directionType)
+{
+  array_t	*relationArray;
+
+  switch (imageInfo->methodType) {
+    case Img_Monolithic_c:
+      relationArray = (array_t *)imageInfo->methodData;
+      break;
+    case Img_Tfm_c:
+    case Img_Hybrid_c:
+      relationArray = ImgGetTransitionFunction(imageInfo->methodData,
+						directionType);
+      break;
+    case Img_Iwls95_c:
+    case Img_Mlp_c:
+    case Img_Linear_c:
+      relationArray = ImgGetTransitionRelationIwls95(imageInfo->methodData,
+							directionType);
+      break;
+    default:
+      fail("** img error: Unexpected image method type.\n");
+  }
+
+  return(relationArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Replace ith partitioned transition relation.]
+
+  Description [Replace ith partitioned transition relation.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Img_ReplaceIthPartitionedTransitionRelation(Img_ImageInfo_t *imageInfo,
+	int i, mdd_t *relation, Img_DirectionType directionType)
+{
+  switch (imageInfo->methodType) {
+    case Img_Monolithic_c:
+      break;
+    case Img_Tfm_c:
+    case Img_Hybrid_c:
+      ImgReplaceIthTransitionFunction(imageInfo->methodData, i, relation,
+					directionType);
+      break;
+    case Img_Iwls95_c:
+    case Img_Mlp_c:
+    case Img_Linear_c:
+      ImgReplaceIthPartitionedTransitionRelationIwls95(imageInfo->methodData,
+					i, relation, directionType);
+      break;
+    default:
+      fail("** img error: Unexpected image method type.\n");
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Replace partitioned transition relation.]
+
+  Description [Replace partitioned transition relation.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Img_ReplacePartitionedTransitionRelation(Img_ImageInfo_t *imageInfo,
+	array_t *relationArray, Img_DirectionType directionType)
+{
+  switch (imageInfo->methodType) {
+    case Img_Monolithic_c:
+      break;
+    case Img_Tfm_c:
+    case Img_Hybrid_c:
+      ImgUpdateTransitionFunction(imageInfo->methodData, relationArray,
+				  directionType);
+      break;
+    case Img_Iwls95_c:
+    case Img_Mlp_c:
+    case Img_Linear_c:
+      ImgUpdateTransitionRelationIwls95(imageInfo->methodData,
+					relationArray, directionType);
+      break;
+    default:
+      fail("** img error: Unexpected image method type.\n");
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Replace partitioned transition relation.]
+
+  Description [Replace partitioned transition relation.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Img_ComposeIntermediateNodes(graph_t *partition, mdd_t *node,
+		array_t *psVars, array_t *nsVars, array_t *inputVars)
+{
+  mdd_manager		*mgr = Part_PartitionReadMddManager(partition);
+  array_t		*supportList;
+  st_table		*supportTable = st_init_table(st_numcmp, st_numhash);
+  int			i, j;
+  int			existIntermediateVars;
+  int			mddId;
+  vertex_t		*vertex;
+  array_t		*varBddFunctionArray, *varArray;
+  mdd_t			*var, *func, *tmpMdd;
+  mdd_t			*composedNode;
+  Mvf_Function_t	*mvf;
+
+  if (psVars) {
+    for (i = 0; i < array_n(psVars); i++) {
+      mddId = array_fetch(int, psVars, i);
+      st_insert(supportTable, (char *)(long)mddId, NULL);
+    }
+  }
+  if (nsVars) {
+    for (i = 0; i < array_n(nsVars); i++) {
+      mddId = array_fetch(int, nsVars, i);
+      st_insert(supportTable, (char *)(long)mddId, NULL);
+    }
+  }
+  if (inputVars) {
+    for (i = 0; i < array_n(inputVars); i++) {
+      mddId = array_fetch(int, inputVars, i);
+      st_insert(supportTable, (char *)(long)mddId, NULL);
+    }
+  }
+
+  composedNode = mdd_dup(node);
+
+  existIntermediateVars = 1;
+  while (existIntermediateVars) {
+    existIntermediateVars = 0;
+    supportList = mdd_get_support(mgr, composedNode);
+    for (i = 0; i < array_n(supportList); i++) {
+      mddId = array_fetch(int, supportList, i);
+      if (!st_lookup(supportTable, (char *)(long)mddId, NULL)) {
+	vertex = Part_PartitionFindVertexByMddId(partition, mddId);
+	mvf = Part_VertexReadFunction(vertex);
+	varBddFunctionArray = mdd_fn_array_to_bdd_fn_array(mgr, mddId, mvf);
+	varArray = mdd_id_to_bdd_array(mgr, mddId);
+	assert(array_n(varBddFunctionArray) == array_n(varArray));
+	for (j = 0; j < array_n(varBddFunctionArray); j++) {
+	  var = array_fetch(mdd_t *, varArray, j);
+	  func = array_fetch(mdd_t *, varBddFunctionArray, j);
+	  tmpMdd = composedNode;
+	  composedNode = bdd_compose(composedNode, var, func);
+	  mdd_free(tmpMdd);
+	  mdd_free(var);
+	  mdd_free(func);
+	}
+	array_free(varBddFunctionArray);
+	array_free(varArray);
+	existIntermediateVars = 1;
+      }
+    }
+    array_free(supportList);
+  }
+  st_free_table(supportTable);
+  return(composedNode);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Constrains/adds dont-cares to the bit relations with the
+  given constraint and creates a new transtion relation.]
+
+  Description [Constrains/adds dont-cares to the bit relations with
+  the given constraint and creates a new transition relation in the
+  direction indicated. This procedure will incur the cost of creating
+  the bit relations if they dont already exist. An over/under
+  approximation of the transition relation may be created according to
+  the underApprox flag. The flag is TRUE for underapproximations and
+  FALSE for over approximation. An underapproximation of the
+  transition relation will be in the interval [T.C, T] and an
+  overapproximation of the transition relation will be in the interval
+  [T, T+ C']. THe method used in minimization is set in
+  Img_GuidedSearchReadUnderApproxMinimizeMethod and
+  Img_GuidedSearchReadOverApproxMinimizeMethod. The cleanup flag
+  cleans up the data (e.g., bit relations) stored for applying
+  constraints repeatedly. ]
+  
+  SideEffects [Current transition relation and quantification schedule
+  are freed. Bit relations are freed if indicated by the cleanUp flag.]
+
+  SeeAlso [Img_GuidedSearchReadUnderApproxMinimizeMethod
+  Img_GuidedSearchReadOverApproxMinimizeMethod]
+
+******************************************************************************/
+void
+Img_ImageConstrainAndClusterTransitionRelation(Img_ImageInfo_t *imageInfo,
+					       Img_DirectionType direction,
+					       mdd_t *constrain,
+					       Img_MinimizeType minimizeMethod,
+					       boolean underApprox,
+					       boolean cleanUp,
+					       boolean forceReorder,
+					       int printStatus)
+{
+    switch (imageInfo->methodType) {
+    case Img_Monolithic_c:
+      ImgImageConstrainAndClusterTransitionRelationMono(imageInfo,
+							constrain,
+							minimizeMethod,
+							underApprox,
+							cleanUp,
+							forceReorder,
+							printStatus);
+      break;
+    case Img_Tfm_c:
+    case Img_Hybrid_c:
+      ImgImageConstrainAndClusterTransitionRelationTfm(imageInfo,
+						       direction,
+						       constrain,
+						       minimizeMethod,
+						       underApprox,
+						       cleanUp,
+						       forceReorder,
+						       printStatus);
+      break;
+    case Img_Iwls95_c:
+    case Img_Mlp_c:
+    case Img_Linear_c:
+      ImgImageConstrainAndClusterTransitionRelationIwls95OrMlp(imageInfo,
+							       direction,
+							       constrain,
+							       minimizeMethod,
+							       underApprox,
+							       cleanUp,
+							       forceReorder,
+							       printStatus);
+      break;
+    default:
+      fail("** img error: Unexpected image method type.\n");
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis [Returns the guided search minimize method of underapproximating the
+  transition relation.]
+
+  Description [Returns the guided search minimize method of underapproximating the
+  transition relation. Default is And.]
+
+  SideEffects []
+
+******************************************************************************/
+Img_MinimizeType
+Img_GuidedSearchReadUnderApproxMinimizeMethod(void)
+{
+  char                  *flagValue;
+  Img_MinimizeType      minimizeMethod = Img_And_c;
+
+  flagValue = Cmd_FlagReadByName("guided_search_underapprox_minimize_method");
+  if (flagValue != NIL(char)) {
+    if (strcmp(flagValue, "constrain") == 0) {
+      minimizeMethod = Img_Constrain_c;
+    } else if (strcmp(flagValue, "and") == 0) {
+      minimizeMethod = Img_And_c;
+    } else {
+      fprintf(vis_stderr,
+      "** img error : invalid value %s for guided_search_underapprox_minimize_method. ***\n",
+              flagValue);
+      fprintf(vis_stderr,
+        "** img error : Reverting to default minimize method : And\n");
+    }
+  }
+  return(minimizeMethod);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Returns the guided search minimize method of overapproximating the
+  transition relation.]
+
+  Description [Returns the guided search minimize method of overapproximating the
+  transition relation. Default is OrNot.]
+
+  SideEffects []
+
+******************************************************************************/
+Img_MinimizeType
+Img_GuidedSearchReadOverApproxMinimizeMethod(void)
+{
+  char                  *flagValue;
+  Img_MinimizeType      minimizeMethod = Img_OrNot_c;
+
+  flagValue = Cmd_FlagReadByName("guided_search_overapprox_minimize_method");
+  if (flagValue != NIL(char)) {
+    if (strcmp(flagValue, "ornot") == 0) {
+      minimizeMethod = Img_OrNot_c;
+    } else if (strcmp(flagValue, "squeeze") == 0) {
+      minimizeMethod = Img_Squeeze_c;
+    } else {
+      fprintf(vis_stderr,
+      "** img error : invalid value %s for guided_search_overapprox_minimize_method. ***\n",
+              flagValue);
+      fprintf(vis_stderr,
+        "** img error : Reverting to default method : OrNot\n");
+    }
+  }
+  return(minimizeMethod);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Substitutes variables between domain and range.]
+
+  Description [Substitutes variables between domain and range.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Img_Substitute(Img_ImageInfo_t *imageInfo, mdd_t *f, Img_SubstituteDir dir)
+{
+  mdd_t *new_;
+
+  new_ = ImgSubstitute(f, &(imageInfo->functionData), dir);
+  return(new_);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Minimize array of bdds wrt a set of constraints]
+
+  Description [Compute a new array, such that every element corresponds to an
+  element of imageArray minimized with all elements of careSetArray
+  successively, using minimizeMethod.  This function can be used for any array
+  of bdds.
+
+  <p>If underapprox is 1, the the bdds are underapproximated.  If it is 0, they
+  are overapproximated, and the minimizeMethod has to be either ornot or
+  squeeze.]
+
+  SideEffects []
+
+  SeeAlso[Img_MinimizeImage ImgMinimizeImageArrayWithCareSetArrayInSitu]
+
+******************************************************************************/
+array_t *
+ImgMinimizeImageArrayWithCareSetArray(
+  array_t *imageArray,
+  array_t *careSetArray,
+  Img_MinimizeType minimizeMethod,
+  boolean underapprox,
+  boolean printInfo,
+  Img_DirectionType dir 
+  )
+{
+  array_t *result; /* of mdd_t * */
+
+  result = mdd_array_duplicate(imageArray);
+  ImgMinimizeImageArrayWithCareSetArrayInSitu(result, careSetArray,
+					      minimizeMethod, underapprox,
+					      printInfo, dir); 
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Minimize array of bdds wrt a set of constraints]
+
+  Description [Compute a new array, such that every element corresponds to an
+  element of imageArray minimized with all elements of careSetArray
+  successively, using minimizeMethod.  This function can be used for any array
+  of bdds.
+
+  <p>If underapprox is 1, the the bdds are underapproximated.  If it is 0, they
+  are overapproximated, and the minimizeMethod has to be either ornot or
+  squeeze.
+  
+  <p>In-situ variant of ImgMinimizeImageArrayWithCareSetArray.  Probably saves
+  space. ]
+
+  SideEffects []
+
+  SeeAlso[Img_MinimizeImage,ImgMinimizeImageArrayWithCareSetArray]
+
+******************************************************************************/
+void
+ImgMinimizeImageArrayWithCareSetArrayInSitu(
+  array_t *imageArray,
+  array_t *careSetArray,
+  Img_MinimizeType minimizeMethod,
+  boolean underapprox,
+  boolean printInfo,
+  Img_DirectionType dir)
+{
+  int i;
+  mdd_t *cluster = NIL(mdd_t);
+  long constrainSize, initialTotalSize;
+  char *dirname = NIL(char);
+  
+  if (minimizeMethod == Img_DefaultMinimizeMethod_c)
+    minimizeMethod = Img_ReadMinimizeMethod();   
+  
+  if(printInfo){
+    constrainSize    = mdd_size_multiple(careSetArray);
+    initialTotalSize =  mdd_size_multiple(imageArray);
+    assert(dir != Img_Both_c);
+    if(dir == Img_Forward_c)
+      dirname = "fwd";
+    else
+      dirname = "bwd";
+  } else { /* to remove uninitialized variable warnings */
+    constrainSize = 0;
+    initialTotalSize = 0;
+  }
+  
+  arrayForEachItem(mdd_t *, imageArray, i, cluster){
+    mdd_t *minimized;
+    
+    minimized = Img_MinimizeImageArray(cluster, careSetArray,
+				       minimizeMethod, underapprox);
+    array_insert(mdd_t *, imageArray, i, minimized);
+    
+    if(printInfo)
+      (void) fprintf(vis_stdout,
+	  "IMG Info: minimized %s relation %d | %ld => %d in component %d.\n",
+		     dirname, mdd_size(cluster), constrainSize,
+		     mdd_size(minimized), i);  
+     mdd_free(cluster);
+ }
+  
+  if(printInfo)
+    (void) fprintf(vis_stdout,
+      "IMG Info: minimized %s relation %ld | %ld => %ld with %d components.\n",
+		   dirname, initialTotalSize, constrainSize,
+		   mdd_size_multiple(imageArray), array_n(imageArray)); 
+  
+ return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Substitutes variables between domain and range.]
+
+  Description [Substitutes variables between domain and range.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+ImgSubstitute(mdd_t *f, ImgFunctionData_t *functionData, Img_SubstituteDir dir)
+{
+  mdd_t *new_;
+
+  if (bdd_get_package_name() == CUDD) {
+    if (dir == Img_D2R_c)
+      new_ = bdd_substitute_with_permut(f, functionData->permutD2R);
+    else
+      new_ = bdd_substitute_with_permut(f, functionData->permutR2D);
+  } else {
+    if (dir == Img_D2R_c) {
+      new_ = bdd_substitute(f, functionData->domainBddVars,
+			    functionData->rangeBddVars);
+    } else {
+      new_ = bdd_substitute(f, functionData->rangeBddVars,
+			    functionData->domainBddVars);
+    }
+  }
+  return(new_);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Substitutes variables between domain and range.]
+
+  Description [Substitutes variables between domain and range.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+ImgSubstituteArray(array_t *f_array, ImgFunctionData_t *functionData,
+		Img_SubstituteDir dir)
+{
+  array_t *new_array;
+
+  if (bdd_get_package_name() == CUDD) {
+    if (dir == Img_D2R_c) {
+      new_array = bdd_substitute_array_with_permut(f_array,
+			functionData->permutD2R);
+    } else {
+      new_array = bdd_substitute_array_with_permut(f_array,
+			functionData->permutR2D);
+    }
+  } else {
+    if (dir == Img_D2R_c) {
+      new_array = bdd_substitute_array(f_array, functionData->domainBddVars,
+		functionData->rangeBddVars);
+    } else {
+      new_array = bdd_substitute_array(f_array, functionData->rangeBddVars,
+		functionData->domainBddVars);
+    }
+  }
+  return(new_array);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Prints Partial Image options.]
+
+  Description [Prints Partial Image options.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgPrintPartialImageOptions(void)
+{
+  ImgPartialImageOption_t *PIoption;
+  char *dummy;
+  PIoption = ImgGetPartialImageOptions();
+
+  dummy = ALLOC(char, 25);
+  switch (PIoption->partialImageMethod) {
+  case Img_PIApprox_c: sprintf(dummy, "%s", "approx");break;
+  case Img_PIClipping_c: sprintf(dummy, "%s", "clipping");break;
+  default: sprintf(dummy, "%s", "approx");break;
+  }
+  fprintf(vis_stdout, "HD: Partial Image number of variables = %d\n", PIoption->nvars);
+  fprintf(vis_stdout, "HD: Partial Image Method = %s\n", dummy);
+  fprintf(vis_stdout, "HD: Partial Image Threshold = %d\n", PIoption->partialImageThreshold);
+  fprintf(vis_stdout, "HD: Partial Image Size = %d\n", PIoption->partialImageSize);
+  switch (PIoption->partialImageApproxMethod) {
+  case BDD_APPROX_HB: sprintf(dummy, "%s", "heavy_branch"); break;
+  case BDD_APPROX_SP: sprintf(dummy, "%s", "short_paths"); break;
+
+  case BDD_APPROX_UA: sprintf(dummy, "%s", "under_approx"); break;
+  case BDD_APPROX_RUA: sprintf(dummy, "%s", "remap_ua"); break;
+
+  case BDD_APPROX_COMP: sprintf(dummy, "%s", "compress"); break;
+  default: sprintf(dummy, "%s", "remap_ua"); break;
+  }
+  fprintf(vis_stdout, "HD: Partial Image Approximation Method = %s\n", dummy);
+
+  fprintf(vis_stdout, "HD: Partial Image Approximation quality factor = %g\n", PIoption->quality);
+  fprintf(vis_stdout, "HD: Partial Image Approximation Bias quality factor = %g\n", PIoption->qualityBias);
+  fprintf(vis_stdout, "HD: Partial Image Clipping factor = %g\n", PIoption->clippingDepthFrac);
+
+  FREE(dummy);
+  FREE(PIoption);
+  return;
+
+} /* end of ImgPrintPartialImageOptions */
+
+/**Function********************************************************************
+
+  Synopsis    [Get partial image options.]
+
+  Description [Get partial image options.]
+
+  SideEffects []
+
+******************************************************************************/
+ImgPartialImageOption_t *
+ImgGetPartialImageOptions(void)
+{
+  ImgPartialImageOption_t *options;
+  char *qualityString;
+  char *partialImageThresholdString, *partialImageApproxString, *partialImageSizeString;
+  char *partialImageMethodString, *clippingDepthString;
+
+  options = ALLOC(ImgPartialImageOption_t , 1);
+  if (options == NIL(ImgPartialImageOption_t)) return NIL(ImgPartialImageOption_t);
+
+  /* initialize to default values; */
+  options->nvars = 0;
+  options->partialImageMethod = Img_PIApprox_c;
+  options->partialImageThreshold = 200000;
+  options->partialImageSize = 100000;
+  options->partialImageApproxMethod = BDD_APPROX_RUA;
+  options->quality = 1.0;
+  options->qualityBias = 0.5;
+  options->clippingDepthFrac = IMG_PI_CLIP_DEPTH;
+
+  /* what kind of approximation to apply to the image */
+  partialImageMethodString = Cmd_FlagReadByName("hd_partial_image_method");
+  if (partialImageMethodString != NIL(char)) {
+    if (strcmp(partialImageMethodString, "approx") == 0) {
+      options->partialImageMethod = Img_PIApprox_c;
+    } else if (strcmp(partialImageMethodString, "clipping") == 0) {
+      options->partialImageMethod = Img_PIClipping_c;
+    }
+  }
+
+  /* threshold to trigger partial image computation */
+  partialImageThresholdString = Cmd_FlagReadByName("hd_partial_image_threshold");
+  if (partialImageThresholdString != NIL(char)) {
+    options->partialImageThreshold = strtol(partialImageThresholdString, NULL, 10);
+    if (options->partialImageThreshold < 0) {
+      options->partialImageThreshold = 200000;
+    }
+  }
+
+  /* intended size of partial image */
+  partialImageSizeString = Cmd_FlagReadByName("hd_partial_image_size");
+  if (partialImageSizeString != NIL(char)) {
+    options->partialImageSize = strtol(partialImageSizeString, NULL, 10);
+    if (options->partialImageSize < 0) {
+      options->partialImageSize = 100000;
+    }
+  }
+
+  /* which approximation method to apply */
+  partialImageApproxString = Cmd_FlagReadByName("hd_partial_image_approx");
+  if (partialImageApproxString != NIL(char)) {
+    if (strcmp(partialImageApproxString, "heavy_branch") == 0) {
+      options->partialImageApproxMethod = BDD_APPROX_HB;
+    } else if (strcmp(partialImageApproxString, "short_paths") == 0) {
+      options->partialImageApproxMethod = BDD_APPROX_SP;
+    } else if (strcmp(partialImageApproxString, "under_approx") == 0) {
+      options->partialImageApproxMethod = BDD_APPROX_UA;
+    } else if (strcmp(partialImageApproxString, "remap_ua") == 0) {
+      options->partialImageApproxMethod = BDD_APPROX_RUA;
+    } else if (strcmp(partialImageApproxString, "compress") == 0) {
+      options->partialImageApproxMethod = BDD_APPROX_COMP;
+    } else if (strcmp(partialImageApproxString, "biased_rua") == 0) {
+      options->partialImageApproxMethod = BDD_APPROX_BIASED_RUA;
+    }
+  }
+  /* quality factor for remap_ua and under_approx methods */
+  qualityString = Cmd_FlagReadByName("hd_partial_image_approx_quality");
+  if (qualityString != NIL(char)) {
+    options->quality = strtod(qualityString, NULL);
+    if (options->quality < 0.0) {
+      options->quality = 1.0;
+    }
+  }
+
+  /* quality factor for remap_ua and under_approx methods */
+  qualityString = Cmd_FlagReadByName("hd_partial_image_approx_bias_quality");
+  if (qualityString != NIL(char)) {
+    options->qualityBias = strtod(qualityString, NULL);
+    if (options->qualityBias < 0.0) {
+      options->qualityBias = 0.5;
+    }
+  }
+
+  /* fraction of depth of Bdd to clip at. */
+  clippingDepthString = Cmd_FlagReadByName("hd_partial_image_clipping_depth");
+  if (clippingDepthString != NIL(char)) {
+    options->clippingDepthFrac = strtod(clippingDepthString, NULL);
+    if ((options->clippingDepthFrac > 1.0) ||
+	(options->clippingDepthFrac < 0.0)) {
+      options->clippingDepthFrac = IMG_PI_CLIP_DEPTH;
+    }
+  }
+
+  return (options);
+} /* end of ImgGetPartialImageOptions */
+
+/**Function********************************************************************
+
+  Synopsis    [This function checks the validity of an array of array
+  of BDD nodes.]
+
+  SideEffects []
+
+  SeeAlso     [ImgBddCheckValidity]
+
+******************************************************************************/
+int
+ImgArrayBddArrayCheckValidity(array_t *arrayBddArray)
+{
+  int i;
+  for(i=0; i<array_n(arrayBddArray); i++) {
+    ImgBddArrayCheckValidity(array_fetch(array_t*, arrayBddArray, i));
+  }
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [This function checks the validity of array of BDD nodes.]
+
+  SideEffects []
+
+  SeeAlso     [ImgBddCheckValidity]
+
+******************************************************************************/
+int
+ImgBddArrayCheckValidity(array_t *bddArray)
+{
+  int i;
+  for(i=0; i<array_n(bddArray); i++) {
+    ImgBddCheckValidity(array_fetch(bdd_t*, bddArray, i));
+  }
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [This function checks the validity of a BDD.]
+
+  Description [[This function checks the validity of a BDD. Three checks are done:
+  1. The BDD should not be freed. "free" field should be 0.
+  2. The node pointer of the BDD should be a valid pointer.
+  3. The manager pointer of the BDD should be a valid pointer.
+  The assumption for 2 and 3 is that, the value of a valid pointer
+  should be > 0xf.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+ImgBddCheckValidity(bdd_t *bdd)
+{
+#ifndef NDEBUG
+  int i;
+#endif
+  assert(bdd_get_free(bdd) == 0); /* Bdd should not have been freed */
+  assert(((unsigned long)bdd_get_node(bdd, &i)) & ~0xf); /* Valid node pointer */
+  assert(((unsigned long)bdd_get_manager(bdd)) & ~0xf); /* Valid manager pointer */
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the content of a table containing integers.]
+
+  Description [Prints the content of a table containing integers.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+ImgPrintVarIdTable(st_table *table)
+{
+  st_generator *stgen;
+  long varId;
+  st_foreach_item(table, stgen, &varId, NULL){
+    (void) fprintf(vis_stdout, "%d ", (int) varId);
+  }
+  (void) fprintf(vis_stdout, "\n");
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether toCareSetArray changed.]
+
+  Description [Checks whether toCareSetArray changed.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+ImgCheckToCareSetArrayChanged(array_t *toCareSetArray1,
+				array_t *toCareSetArray2)
+{
+  int	i, size1, size2;
+  mdd_t	*careSet1, *careSet2;
+
+  size1 = array_n(toCareSetArray1);
+  size2 = array_n(toCareSetArray2);
+
+  if (size1 != size2)
+    return(1);
+
+  for (i = 0; i < size1; i++) {
+    careSet1 = array_fetch(mdd_t *, toCareSetArray1, i);
+    careSet2 = array_fetch(mdd_t *, toCareSetArray2, i);
+    if (bdd_equal(careSet1, careSet2) == 0)
+      return(1);
+  }
+
+  return(0);
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Checks the validity of image]
+
+  Description [In a properly formed image, there should not be any
+  domain or quantify variables in its support. This function checks
+  for that fact.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CheckImageValidity(mdd_manager *mddManager, mdd_t *image, array_t
+                   *domainVarMddIdArray, array_t *quantifyVarMddIdArray)
+{
+  int i;
+  array_t *imageSupportArray = mdd_get_support(mddManager, image);
+  st_table *imageSupportTable = st_init_table(st_numcmp, st_numhash);
+  for (i=0; i<array_n(imageSupportArray); i++){
+    long mddId = (long) array_fetch(int, imageSupportArray, i);
+    (void) st_insert(imageSupportTable, (char *) mddId, NIL(char));
+  }
+  for (i=0; i<array_n(domainVarMddIdArray); i++){
+    int domainVarId;
+    domainVarId = array_fetch(int, domainVarMddIdArray, i);
+    assert(st_is_member(imageSupportTable, (char *)(long)domainVarId) == 0);
+  }
+  for (i=0; i<array_n(quantifyVarMddIdArray); i++){
+    int quantifyVarId;
+    quantifyVarId = array_fetch(int, quantifyVarMddIdArray, i);
+    assert(st_is_member(imageSupportTable, (char *)(long)quantifyVarId) == 0);
+  }
+  st_free_table(imageSupportTable);
+  array_free(imageSupportArray);
+  return 1;
+}
+
+
Index: vis_dev/vis-2.3/src/io/io.h
===================================================================
--- vis_dev/vis-2.3/src/io/io.h	(revision 14)
+++ vis_dev/vis-2.3/src/io/io.h	(revision 14)
@@ -0,0 +1,72 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [io.h]
+
+  PackageName [io]
+
+  Synopsis    [Routines for reading and writing BLIF-MV files.]
+
+  Author      [Yuji Kukimoto]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: io.h,v 1.8 2005/04/27 02:55:37 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _IO_VIS
+#define _IO_VIS
+
+#include "hrc.h"
+#include <setjmp.h>
+
+
+/**Enum************************************************************************
+
+  Synopsis    [Types of encodings allowed.]
+
+  Description []
+
+  SeeAlso     []
+
+******************************************************************************/
+typedef enum {
+    SIMPLE,
+    OTHER
+} Io_Encoding_Type_t;
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void Io_Init(void);
+EXTERN void Io_End(void);
+EXTERN Hrc_Manager_t * Io_BlifMvRead(FILE *fp, Hrc_Manager_t *hmgr, boolean isCanonical, boolean isIncremental, boolean isVerbose);
+EXTERN Hrc_Manager_t * Io_BlifRead(char *fileName, boolean isVerbose);
+EXTERN void Io_SmvPrintVar(FILE *fp, Var_Variable_t *var);
+EXTERN int Io_HnodeWriteBlif(Io_Encoding_Type_t encodingType, Hrc_Node_t *hnode, FILE *fp, FILE *encFp, int verbosity, int combinationalOnly, int makeLatchIOsPOs);
+EXTERN int Io_HnodeWriteBlifTotal(Io_Encoding_Type_t encodingType, Hrc_Node_t *hnode, FILE *fp, int verbosity);
+EXTERN void Io_SmvPrintVar(FILE *fp, Var_Variable_t *var);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _IO_VIS */
Index: vis_dev/vis-2.3/src/io/io.l
===================================================================
--- vis_dev/vis-2.3/src/io/io.l	(revision 14)
+++ vis_dev/vis-2.3/src/io/io.l	(revision 14)
@@ -0,0 +1,264 @@
+%{
+/**CFile***********************************************************************
+
+  FileName    [io.l]
+
+  PackageName [io]
+
+  Synopsis    [Lexical analyzer for BLIF-MV.]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [Yuji Kukimoto, Rajeev Ranjan, Huey-Yih Wang]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ioYacc.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define IoMAXSTACKDEPTH (32)
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+YY_BUFFER_STATE globalFilePtrStack[IoMAXSTACKDEPTH];
+int globalCurrentStackDepth = 0;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+static char * _IoFileNameExtract(char *string);
+
+%}
+
+/*---------------------------------------------------------------------------*/
+/* Lexical analyzer rules                                                    */
+/*---------------------------------------------------------------------------*/
+
+%option noyywrap
+
+/* -, =, (, ), {, }, ! and ; are intentionally removed from symbol
+   - is for dashes in tables
+   = is for the = construct in tables
+   ( and ) are for lists in tables
+   { and } are for ranges in tables
+   ! is for complements in tables
+   ; is for delimitters in CTL formulas
+removing - has another effect. Since - is not a symbol, -> in the table
+construct is always found by the lexer
+ */
+blank  [ \t\r\b]
+alpha  [A-Za-z]
+number [0-9]
+symbol [\^\?\|\/\[\]\+\*\$\<\>~@\_#\$%\:\"\'\.]
+/*symbol [\^\?\|\/\[\]\+\*\$\<\>~@\_#\$%\:\;\"\'\.]*/
+/*symbol [\^\?\|\/\+\*\$\<\>~@\_#\$%\:\;\"\'\.]*/
+alnumsymbol  {alpha}|{number}|{symbol}
+alnumsymbolblank  {alnumsymbol}|{blank}
+
+%%
+
+"->"	{
+	return ARROW;
+	}       
+"="	{ 
+        return ASSIGN; 
+	}
+^{blank}*\n	{
+		globalLineNumber++;
+		continue;
+		}
+\n	{
+	globalLineNumber++;
+	return NEWLINE;
+	}
+\\\n{blank}*\n	{
+		globalLineNumber += 2;
+		return NEWLINE;
+		}
+\\$		{
+#ifdef __cplusplus
+                (void)yyinput();
+#else
+		(void)input();
+#endif
+		globalLineNumber++;
+		continue;
+		}
+
+\.include{blank}+{alnumsymbol}*\n {
+			char *fileName, *realFileName;
+
+			fileName = _IoFileNameExtract(IoYytext);
+                        if (globalCurrentStackDepth >= IoMAXSTACKDEPTH){
+                           error_append("Error: .include nested too deeply.\n");
+                           IoError();
+                        }
+			globalFilePtrStack[globalCurrentStackDepth++] = YY_CURRENT_BUFFER;
+			IoYyin = Cmd_FileOpen(fileName,"r",&realFileName,1);
+			if (IoYyin == NIL(FILE)) {
+				error_append("Error: Include file ");
+				error_append(fileName);
+				error_append(" is not found.\n");
+				IoError();
+			}
+                        IoYy_switch_to_buffer(IoYy_create_buffer(IoYyin,YY_BUF_SIZE));
+                        BEGIN(INITIAL);
+			continue;
+			}
+<<EOF>>		{
+		if (--globalCurrentStackDepth < 0){
+		yyterminate();
+		}
+		else {
+                  IoYy_delete_buffer(YY_CURRENT_BUFFER);
+                  IoYy_switch_to_buffer(globalFilePtrStack[globalCurrentStackDepth]);
+                }
+                }
+                  
+
+\.{alpha}*	{
+		if (strcmp(IoYytext,".model") == 0) {
+			return MODEL;
+		}
+		else if (strcmp(IoYytext,".inputs") == 0) {
+		        return INPUTS;
+		}
+		else if (strcmp(IoYytext,".outputs") == 0) {
+			return OUTPUTS;
+		}
+		else if (strcmp(IoYytext, ".mv" ) == 0 ){
+			return MV;
+		}
+		else if (strcmp(IoYytext,".latch") == 0) {
+			return LATCH;
+		}
+		else if (strcmp(IoYytext,".table") == 0 || strcmp(IoYytext,".names") == 0) {
+			return NAMES;
+		}
+		else if (strcmp(IoYytext,".reset") == 0 || strcmp(IoYytext,".r") == 0) {
+			return RESET;
+		}
+		else if (strcmp(IoYytext,".subckt") == 0) {
+			return SUBCKT;
+		}
+		else if (strcmp(IoYytext,".default") == 0 || strcmp(IoYytext,".def") == 0) {
+			return DEFAULT;
+		}
+		else if (strcmp(IoYytext,".root") == 0) {
+			return ROOT;
+		}
+		else if (strcmp(IoYytext,".end") == 0) {
+			return END;
+		}
+		else {
+			error_append("Error: Unknown construct ");
+			error_append(IoYytext);
+			error_append("\n");
+			IoError();
+		}
+		}
+{alnumsymbol}+	{
+		return IDENTIFIER;
+		}
+^{blank}*#[^\n]*\n	{
+		/* for lines containing only comments can be skipped */
+		globalLineNumber++;
+		continue;
+		}
+{blank}+	{
+		/* skip white spaces */
+	        continue;
+		}
+#[^\n]*\n		{
+			/* for lines containing meaningful info 
+			followed by comments; should return NEWLINE */ 
+			globalLineNumber++;
+			return NEWLINE;
+			}
+.	{
+	return IoYytext[0];
+	}
+
+%%
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Chops off the initial .include from a given string.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+static char *
+_IoFileNameExtract(char *string)
+{
+  char *fileName;
+
+  fileName = string + strlen(".include ");
+  fileName[strlen(fileName)-1] = '\0';
+  return fileName;
+}
Index: vis_dev/vis-2.3/src/io/io.make
===================================================================
--- vis_dev/vis-2.3/src/io/io.make	(revision 14)
+++ vis_dev/vis-2.3/src/io/io.make	(revision 14)
@@ -0,0 +1,17 @@
+CSRC += ioCheck.c ioCmd.c ioParse.c ioReadBlifMv.c ioTable.c ioWriteBlif.c ioWriteBlifUtil.c ioWriteBlifIo.c ioWriteBlifMv.c ioWriteSmv.c
+HEADERS += io.h ioInt.h
+LEXSRC += io.l
+YACCSRC += io.y
+GENERATEDCSRC += ioYacc.c
+
+ioLex.c: io.l io.h ioInt.h
+	$(LEX) -PIoYy -o$(objectdir)/ioLex.c $<
+	-@chmod 0664 $(objectdir)/ioLex.c
+
+$(objectdir)/ioYacc.c $(objectdir)/ioYacc.h: io.y io.h ioInt.h ioLex.c
+	$(YACC) -pIoYy -t -d -o $(objectdir)/ioYacc.c $<
+	-@chmod 0664 $(objectdir)/ioYacc.c
+
+$(objectdir)/ioYacc.o: $(objectdir)/ioYacc.c
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/io/io.y
===================================================================
--- vis_dev/vis-2.3/src/io/io.y	(revision 14)
+++ vis_dev/vis-2.3/src/io/io.y	(revision 14)
@@ -0,0 +1,517 @@
+%{
+/**CFile***********************************************************************
+
+  FileName    [io.y]
+
+  PackageName [io]
+
+  Synopsis    [Yacc file for the BLIF-MV parser.]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [Yuji Kukimoto, Rajeev Ranjan, Huey-Yih Wang]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ioInt.h"
+
+/*
+ * The following is a workaround for a bug in bison, which generates code
+ * that uses alloca().  Their lengthy sequence of #ifdefs for defining
+ * alloca() does the wrong thing for HPUX (it should do what is defined below)
+ */
+#ifdef __hpux
+#  include <alloca.h>
+#endif
+ 
+static char rcsid[] UNUSED = "$Id: io.y,v 1.11 2010/04/09 23:32:13 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+int globalLineNumber;
+Hrc_Manager_t *globalYaccHmgr;
+Hrc_Model_t *globalModel;
+Hrc_Node_t *globalHnode;
+Hrc_Model_t *globalFirstModel;
+Hrc_Model_t *globalRootModel;
+char *globalRootInstanceName;
+array_t *globalMvNameArray;
+array_t *globalSymValueArray;
+array_t *globalTableInputArray;
+array_t *globalTableOutputArray;
+array_t *globalTableDefaultArray;
+array_t *globalTableSymCubeArray;
+array_t *globalFormalNameArray;
+array_t *globalActualNameArray;
+array_t *globalSubcktArray;
+array_t *globalResetArray;
+st_table *globalParserResetInfo;
+st_table *globalParserSubcktInfo;
+array_t *globalNewModelArray;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+#include "ioLex.c"
+
+static void
+IoYyerror(char *string)
+{
+  (void)fprintf(vis_stderr,"%s",error_string());
+  (void)fprintf(vis_stderr,"%s in line %d with token %s\n",string,globalLineNumber,IoYytext);
+  fflush(vis_stderr);
+}
+
+%}
+
+/* %token YYERROR_VERBOSE */
+
+%token MODEL END INPUTS OUTPUTS MV LATCH RESET NAMES DEFAULT SUBCKT ROOT
+%token IDENTIFIER ARROW ASSIGN NEWLINE
+
+%union {
+  char *string;
+  int integer;
+  IoSymValue_t *IoSymValue_t_ptr;
+  array_t *array_t_ptr;
+}
+
+%type <string> name;
+%type <integer> range;
+%type <IoSymValue_t_ptr> sym_value sym_value_without_assign basic_sym_value;
+%type <array_t_ptr> sub_sym_value;
+
+%start models
+
+%%
+
+models:
+	  model
+	| models model
+	| models error {
+		IoError();
+	  }
+	;
+model:
+	  model_start model_content model_end 
+	;
+model_start:
+	  MODEL name NEWLINE {
+	  if ( Hrc_ManagerFindModelByName(globalYaccHmgr,$2) ){
+	    error_append("Model ");
+	    error_append($2);
+	    error_append(" is multiply-defined\n");
+	    FREE($2);
+	    IoError();
+	  } 
+	  globalModel = Hrc_ModelAlloc(globalYaccHmgr,$2); 
+	  globalHnode = Hrc_ModelReadMasterNode(globalModel);
+	  if ( globalFirstModel == NIL(Hrc_Model_t) )
+	    globalFirstModel = globalModel;
+	  FREE($2);
+          array_insert_last(Hrc_Model_t *,globalNewModelArray,globalModel);
+	  }
+	  option_root
+	;
+option_root:
+	  /* empty */
+	| ROOT NEWLINE {
+	  if ( globalRootModel != NIL(Hrc_Model_t) ){
+	    error_append("Two models ");
+	    error_append(Hrc_ModelReadName(globalRootModel));
+	    error_append(" and ");
+	    error_append(Hrc_ModelReadName(globalModel));
+	    error_append(" are defined as the root model\n");
+            IoError();
+	  }
+	  globalRootModel = globalModel;
+	  }	
+	| ROOT name NEWLINE {
+	  if ( globalRootModel != NIL(Hrc_Model_t) ){
+	    error_append("Two models ");
+	    error_append(Hrc_ModelReadName(globalRootModel));
+	    error_append(" and ");
+	    error_append(Hrc_ModelReadName(globalModel));
+	    error_append(" are defined as the root model\n");
+            IoError();
+	  }
+	  globalRootModel = globalModel;
+	  globalRootInstanceName = $2;
+	  }	
+	;
+model_end:
+	  END NEWLINE {
+	  if (st_is_member(globalParserResetInfo,(char *)globalModel) == 1){
+	    error_append("Model ");
+	    error_append(Hrc_ModelReadName(globalModel));
+	    error_append(" is multiply-defined.\n");
+            IoError();
+	  }
+	  /* the following st_insert should return 0 */
+	  (void)st_insert(globalParserResetInfo,(char *)globalModel,(char *)globalResetArray);
+	  if (st_is_member(globalParserSubcktInfo,(char *)globalModel) == 1){
+	    error_append("Model ");
+	    error_append(Hrc_ModelReadName(globalModel));
+	    error_append(" is multiply-defined.\n");
+	    IoError();
+	  }
+	  /* the following st_insert should return 0 */
+	  (void)st_insert(globalParserSubcktInfo,(char *)globalModel,(char *)globalSubcktArray);
+	  globalResetArray = NIL(array_t);
+	  globalSubcktArray = NIL(array_t);
+	  globalModel = NIL(Hrc_Model_t);
+	  globalHnode = NIL(Hrc_Node_t);
+	  }
+	;
+model_content:
+	  /* empty */
+	| model_content command
+	;
+command:
+	  input
+	| output
+	| mv
+	| latch
+	| table
+	| reset
+	| subckt
+	;
+input:
+	  INPUTS input_names NEWLINE
+	;
+input_names:
+	  /* empty */
+	| input_names input_name
+	;
+input_name:
+	  name {
+	  if (IoInputProcess(globalHnode,$1) == 0){
+	    error_append("Input ");
+	    error_append($1);
+	    error_append(" is multiply defined.\n");
+	    FREE($1);
+            IoError();
+	  }
+	  FREE($1);
+	  }
+	;
+output:
+	  OUTPUTS output_names NEWLINE
+	;
+output_names:
+	  /* empty */
+	| output_names output_name
+	;
+output_name:
+	  name {
+	  if (IoOutputProcess(globalHnode,$1) == 0){
+	    error_append("Output ");
+	    error_append($1);
+	    error_append(" is multiply defined.\n");
+	    FREE($1);
+            IoError();
+	  }
+	  FREE($1);
+	  }
+	;
+mv:
+	  MV mv_names range NEWLINE {
+	  if (IoMvProcess(globalModel,globalHnode,globalMvNameArray,$3,NIL(array_t)) == 0){
+            IoStringArrayFree(globalMvNameArray);
+            IoError();
+	  }
+          IoStringArrayFree(globalMvNameArray);
+          globalMvNameArray = NIL(array_t);
+	  }
+	| MV mv_names range val_names NEWLINE {
+          if (IoMvProcess(globalModel,globalHnode,globalMvNameArray,$3,globalSymValueArray) == 0){
+            IoStringArrayFree(globalMvNameArray);
+            IoStringArrayFree(globalSymValueArray);
+            IoError();
+          }
+          IoStringArrayFree(globalMvNameArray);
+          IoStringArrayFree(globalSymValueArray);
+          globalMvNameArray = NIL(array_t);
+          globalSymValueArray = NIL(array_t);
+	  }
+	;
+mv_names:
+	  mv_name
+	| mv_names ',' mv_name 
+	;
+mv_name:
+	  name {
+	  IoNameInsertInArray(&globalMvNameArray,$1);
+	  }
+	;
+range:
+	  name {
+	  $$ = IoAtoi($1);
+          FREE($1);
+	  }
+	;
+val_names:
+	  val_name
+	| val_names val_name
+	;
+val_name:
+	  name {
+	  IoNameInsertInArray(&globalSymValueArray,$1);
+	  }
+	;
+latch:
+	  LATCH name name NEWLINE {
+	  if (IoLatchProcess(globalModel,globalHnode,$2,$3) == 0){
+	    IoError();
+	    FREE($2);
+	    FREE($3);
+          }
+	  FREE($2);
+	  FREE($3);
+	  }
+	;
+
+
+reset:
+	  RESET table_io_names NEWLINE option_default table_content {
+	  if (IoResetProcess(&globalResetArray,globalModel,globalHnode,globalTableInputArray,globalTableOutputArray,globalTableDefaultArray,globalTableSymCubeArray) == 0){
+	    IoError();
+	  }
+	  globalTableInputArray = NIL(array_t);
+	  globalTableOutputArray = NIL(array_t);
+	  globalTableDefaultArray = NIL(array_t);
+	  globalTableSymCubeArray = NIL(array_t);
+	  }
+	;
+table:
+	  NAMES table_io_names NEWLINE option_default table_content {
+	  if (IoTableProcess(globalModel,globalHnode, globalTableInputArray,globalTableOutputArray,globalTableDefaultArray,globalTableSymCubeArray) == 0){
+	    IoError();
+	  }
+	  globalTableInputArray = NIL(array_t);
+          globalTableOutputArray = NIL(array_t);
+          globalTableDefaultArray = NIL(array_t);
+          globalTableSymCubeArray = NIL(array_t);
+	  }
+	;
+table_io_names:
+	  table_input_names ARROW table_output_names
+	| table_input_names table_output_name
+	;
+table_input_names:
+	  /* empty */
+	| table_input_names table_input_name
+	;
+table_input_name:
+	  name {
+	  IoNameInsertInArray(&globalTableInputArray,$1);
+	  }
+	;
+table_output_names:
+	  table_output_name
+	| table_output_names table_output_name
+	;
+table_output_name:
+	  name {
+	  IoNameInsertInArray(&globalTableOutputArray,$1);
+	  }
+	;
+option_default:
+	  /* empty */
+	| DEFAULT def_values NEWLINE 
+	; 
+def_values:
+	  def_value
+	| def_values def_value
+	;
+def_value:
+	  sym_value {
+	  IoSymValueInsertInArray(&globalTableDefaultArray,$1);
+	  }
+	; 
+sym_values:
+	  sym_value {
+	  IoSymValueInsertInArray(&globalSymValueArray,$1);
+	  }
+	| sym_values sym_value {
+	  IoSymValueInsertInArray(&globalSymValueArray,$2);
+	  }
+	;
+sym_value:
+	  basic_sym_value 
+	| ASSIGN name {
+	  IoSymValue_t *entry;
+	  entry = IoSymValueAlloc();
+	  entry->left = (IoSymValue_t *)$2;
+	  entry->flag = IoAssign_c;
+	  $$ = entry;
+	  }
+	| '(' sub_sym_value ')' {
+	  IoSymValue_t *entry;
+	  entry = IoSymValueAlloc();
+	  entry->elements = $2;
+	  entry->flag = IoList_c;
+	  $$ = entry;
+	  }
+	| '!' sym_value_without_assign {
+	  IoSymValue_t *entry;
+	  entry = IoSymValueAlloc();
+	  entry->left = $2;
+	  entry->flag = IoComplement_c;
+	  $$ = entry;
+	  }
+	;
+sym_value_without_assign:
+	  basic_sym_value 
+	| '(' sub_sym_value ')' {
+	  IoSymValue_t *entry;
+	  entry = IoSymValueAlloc();
+	  entry->elements = $2;
+	  entry->flag = IoList_c;
+	  $$ = entry;
+	  }
+	| '!' sym_value_without_assign {
+	  IoSymValue_t *entry;
+	  entry = IoSymValueAlloc();
+	  entry->left = $2;
+	  entry->flag = IoComplement_c;
+	  $$ = entry;
+	  }
+	;
+basic_sym_value:
+	  '-' {
+	  IoSymValue_t *entry;
+          entry = IoSymValueAlloc();
+          entry->flag = IoUniverse_c;
+          $$ = entry;
+	  }
+	| name {
+	  IoSymValue_t *entry;
+	  entry = IoSymValueAlloc();
+	  entry->flag = IoLeaf_c;
+	  entry->left = (IoSymValue_t *)$1;
+	  $$ = entry;
+	  }
+	| '{' name '-' name '}' {
+	  IoSymValue_t *entry;
+	  entry = IoSymValueAlloc();
+	  entry->left = (IoSymValue_t *)$2;
+	  entry->right = (IoSymValue_t *)$4;
+	  entry->flag = IoRange_c;
+	  $$ = entry;
+	  }
+	;
+sub_sym_value:
+	  sym_value_without_assign {
+	  array_t *array;
+	  array = array_alloc(IoSymValue_t *,0);
+	  array_insert_last(IoSymValue_t *,array,$1);
+	  $$ = array; 
+	  }
+	| sub_sym_value ',' sym_value_without_assign {
+	  array_insert_last(IoSymValue_t *,$1,$3);
+	  }
+	;
+table_content: /* must have at least one row */
+          /* empty */
+	/*
+	  sym_values NEWLINE {
+	  IoSymCubeInsertInArray(&globalTableSymCubeArray,globalSymValueArray);	  
+	  globalSymValueArray = NIL(array_t);
+	  }
+	*/
+	| table_content sym_values NEWLINE {
+	  IoSymCubeInsertInArray(&globalTableSymCubeArray,globalSymValueArray);	  
+	  globalSymValueArray = NIL(array_t);
+	  }
+	;
+
+subckt:
+	  SUBCKT name name connections NEWLINE {
+          if (IoSubcktProcess(&globalSubcktArray,globalModel,globalHnode,$2,$3,globalFormalNameArray,globalActualNameArray) == 0 ){
+            IoError();
+	  }
+	  globalFormalNameArray = NIL(array_t);
+	  globalActualNameArray = NIL(array_t);
+	  }
+	;
+connections:
+	  connection
+	| connections connection
+	;
+connection:
+	  name ASSIGN name {
+	  IoNameInsertInArray(&globalFormalNameArray,$1);
+	  IoNameInsertInArray(&globalActualNameArray,$3);
+	  }	
+	;  
+name:
+	  IDENTIFIER {
+	  $$ = util_strsav(IoYytext);	
+	  }
+	;
+
+%%
+
Index: vis_dev/vis-2.3/src/io/ioCheck.c
===================================================================
--- vis_dev/vis-2.3/src/io/ioCheck.c	(revision 14)
+++ vis_dev/vis-2.3/src/io/ioCheck.c	(revision 14)
@@ -0,0 +1,817 @@
+/**CFile***********************************************************************
+
+  FileName    [ioCheck.c]
+
+  PackageName [io]
+
+  Synopsis    [Routines to test if a blif-mv file is consistent.]
+
+  Description [Routines to test if a blif-mv file is consistent. They are
+  also responsible for setting several internal data structures. Here are
+  the list of checks we can do on an hsis network. For each model, we first
+  check if there is no node labeled both as PI and PS or both as PI and PO.
+  Then, for each subcircuit in the model, the compatibllity of the interface
+  is verified namewise and rangewise. This is detailed below. Then,
+  we verify that there is no combinational cycle in any model.  Furthermore,
+  for each latch in the model, we make sure that the input and the output
+  of the latch are of the same type and that every latch has a reset table.  
+  Finally, we check to see if each variable is an output of at
+  most one table. As for the check to be done for a subcircuit, we first check
+  if the model to be instantiated is present in the hmanager. Then, we 
+  test if all the formal variables in the subcircuit definition exist
+  in the model and at the same time they are of the same type of the
+  corresponding actual variables. More thoroughly, we have to check
+  if a flattened network has no cycle, but it is not currently implemented.]
+
+  SeeAlso     []
+
+  Author      [Yuji Kukimoto, Rajeev Ranjan, Huey-Yih Wang]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ioInt.h"
+
+static char rcsid[] UNUSED = "$Id: ioCheck.c,v 1.11 2005/04/16 06:17:45 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static boolean _IoModelTestMasterNodeConsistency(Hrc_Model_t *model, Hrc_Node_t *hnode);
+static boolean _IoModelTestConnectionConsistency(Hrc_Manager_t *hmgr, Hrc_Model_t *model, Hrc_Node_t *hnode, array_t *subcktArray);
+static boolean _IoModelTestLatchConsistency(Hrc_Node_t *hnode);
+static boolean _IoModelTestResetConsistency(Hrc_Manager_t *hmgr, Hrc_Model_t *model, Hrc_Node_t *hnode, array_t *resetArray);
+static boolean _IoModelTestInternalConnectionConsistency(Hrc_Model_t *model, Hrc_Node_t *hnode, boolean isVerbose);
+static boolean _IoModelTestIsAcyclic(Hrc_Model_t *model, Hrc_Node_t *hnode, st_table *varToTable, st_table *outputVarToSubckt, st_table *visitTable);
+static void _IoModelTestIsAcyclicError(Hrc_Model_t *model, Var_Variable_t *var);
+static int _IoModelTestIsAcyclicRecursive(Hrc_Model_t *model, Hrc_Node_t *hnode, Var_Variable_t *var, st_table *varToTable, st_table *outputVarToSubckt, st_table *visitTable, boolean isResetLogic);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Checks to see if a given blif-mv network is consistent.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+IoNetworkTestConsistency(
+  Hrc_Manager_t *hmgr, 
+  array_t *modelArray,
+  st_table *parserSubcktInfo,
+  st_table *parserResetInfo,
+  boolean isVerbose)
+{
+  char *subcktArray, *resetArray;
+  Hrc_Model_t *model;
+  Hrc_Node_t *hnode;
+  int i;
+
+  for (i=0; i < array_n(modelArray); i++){
+    model = array_fetch(Hrc_Model_t *,modelArray,i);
+
+    hnode = Hrc_ModelReadMasterNode(model);
+
+    if (_IoModelTestMasterNodeConsistency(model,hnode) == 0){
+      return 0;
+    }
+    /* the following st_lookup should return 1 */
+    (void)st_lookup(parserSubcktInfo,(char *)model,&subcktArray);
+    if ((array_t *)subcktArray != NIL(array_t)){
+      if (_IoModelTestConnectionConsistency(hmgr,model,hnode,(array_t *)subcktArray) == 0){
+        return 0;
+      }
+    }
+    /* the following st_lookup should return 1 */
+    (void)st_lookup(parserResetInfo,(char *)model,&resetArray);
+    if ((array_t *)resetArray != NIL(array_t)){
+      if (_IoModelTestResetConsistency(hmgr,model,hnode,(array_t *)resetArray) == 0){
+        return 0;
+      }
+    }
+    if (_IoModelTestLatchConsistency(hnode) == 0){
+      return 0;
+    }
+    if (_IoModelTestInternalConnectionConsistency(model,hnode,isVerbose) == 0){
+      return 0;
+    }
+  }
+  return 1;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Checks to see if there is no inconsistency in a model.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static boolean
+_IoModelTestMasterNodeConsistency(
+  Hrc_Model_t *model,
+  Hrc_Node_t *hnode)
+{
+  char *varName;
+  Var_Variable_t *var;
+  st_generator *gen;
+
+  Hrc_NodeForEachVariable(hnode,gen,varName,var){
+    if (Var_VariableTestTypeConsistency(var) == 0){
+      st_free_gen(gen);
+      return 0;
+    }
+  }
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Checks to see if there is no inconsistency in subcircuit connections.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static boolean
+_IoModelTestConnectionConsistency(
+  Hrc_Manager_t *hmgr, 
+  Hrc_Model_t *model, 
+  Hrc_Node_t *hnode, 
+  array_t *subcktArray)
+{
+  int i, j;
+  IoSubckt_t *subckt;
+  char *nameOfSubcktModel, *instanceName, *formalName, *actualName, *actualPort;
+  Hrc_Model_t *subcktModel;
+  Hrc_Node_t *subcktHnode;
+  st_table *tmpTable;
+  st_table *outputCheckTable;
+  array_t *formalNameArray, *actualNameArray, *actualInputArray, *actualOutputArray;
+  Var_Variable_t *port, *var;
+
+  for (i=0; i < array_n(subcktArray); i++){
+    subckt = array_fetch(IoSubckt_t *,subcktArray,i);
+    nameOfSubcktModel = subckt->modelName;
+    if ((subcktModel = Hrc_ManagerFindModelByName(hmgr,nameOfSubcktModel)) == NIL(Hrc_Model_t)){
+      error_append("Error: Model ");
+      error_append(Hrc_ModelReadName(model));
+      error_append(" has a subcircuit whose model ");
+      error_append(nameOfSubcktModel);
+      error_append(" is not defined.\n");
+      return 0;
+    }
+
+    subcktHnode = Hrc_ModelReadMasterNode(subcktModel);
+    instanceName = subckt->instanceName;
+    formalNameArray = subckt->formalNameArray;
+    actualNameArray = subckt->actualNameArray;
+    assert(array_n(formalNameArray) == array_n(actualNameArray));
+
+    if (array_n(formalNameArray) != 
+        Hrc_NodeReadNumFormalInputs(subcktHnode) + Hrc_NodeReadNumFormalOutputs(subcktHnode)){
+      error_append("Error: Subcircuit ");
+      error_append(instanceName);
+      error_append(" in model ");
+      error_append(Hrc_ModelReadName(model));
+      error_append(" and the corresponding model ");
+      error_append(nameOfSubcktModel);
+      error_append(" have different number of i/o ports.\n");
+      return 0;
+    }
+
+    /* creating a temporary hash table from formal names to actual names */
+    tmpTable = st_init_table(strcmp,st_strhash);
+    for (j=0; j < array_n(formalNameArray); j++){
+      formalName = array_fetch(char *,formalNameArray,j);
+      actualName = array_fetch(char *,actualNameArray,j);
+      if (st_insert(tmpTable,(char *)formalName,(char *)actualName)){
+        error_append("Error: In subcircuit ");
+        error_append(instanceName);
+        error_append(" in model ");
+        error_append(Hrc_ModelReadName(model));
+        error_append(", formal variable ");
+        error_append(formalName);
+        error_append(" is used more than once.\n");
+        st_free_table(tmpTable);
+        return 0;
+      }
+    }
+
+    /* create actualInputArray */
+    actualInputArray = array_alloc(Var_Variable_t *,0);
+    actualOutputArray = array_alloc(Var_Variable_t *,0);
+    Hrc_NodeForEachFormalInput(subcktHnode,j,port){
+      if (st_lookup(tmpTable,(char *)Var_VariableReadName(port),&actualPort) == 0){
+        error_append("Error: Subcircuit ");
+        error_append(instanceName);
+        error_append(" in model ");
+        error_append(Hrc_ModelReadName(model));
+        error_append(" has no actual variable defined for variable ");
+        error_append(Var_VariableReadName(port));
+        error_append(".\n");
+        return 0;
+      }
+      /* var should get a non-nil pointer */
+      var = Hrc_NodeFindVariableByName(hnode,actualPort);
+      if (Var_VariablesTestHaveSameDomain(var,port) == 0){
+        error_append("Error: Formal variable ");
+        error_append(Var_VariableReadName(port));
+        error_append(" and actual variable ");
+        error_append(actualPort);
+        error_append(" have different types in subcircuit ");
+        error_append(instanceName);
+        error_append(" in model ");
+        error_append(Hrc_ModelReadName(model));
+        error_append(".\n");
+        return 0;
+      }
+      if (Var_VariableSetSI(var) == -1){
+        return 0;
+      };
+      array_insert_last(Var_Variable_t *,actualInputArray,var); 
+    }
+
+    /* create actualOutputArray */
+    outputCheckTable = st_init_table(strcmp,st_strhash);
+    Hrc_NodeForEachFormalOutput(subcktHnode,j,port){
+
+      if (st_lookup(tmpTable,(char *)Var_VariableReadName(port),&actualPort) == 0){
+        error_append("Error: Subcircuit ");
+        error_append(instanceName);
+        error_append(" in model ");
+        error_append(Hrc_ModelReadName(model));
+        error_append(" has no actual variable defined for variable ");
+        error_append(Var_VariableReadName(port));
+        error_append(".\n");
+        return 0;
+      }
+      if (st_is_member(outputCheckTable,actualPort) == 1){
+        error_append("Error: Subcircuit ");
+        error_append(instanceName);
+        error_append(" in model ");
+        error_append(Hrc_ModelReadName(model));
+        error_append(" has more than one output connected to the same variable ");
+        error_append(actualPort);
+        error_append(".\n");
+        return 0;
+      }
+      (void)st_insert(outputCheckTable,actualPort,(char *)0);
+      /* var should get a non-nil pointer */
+      var = Hrc_NodeFindVariableByName(hnode,actualPort);
+      if (Var_VariablesTestHaveSameDomain(var,port) == 0){
+        error_append("Error: Formal variable ");
+        error_append(Var_VariableReadName(port));
+        error_append(" and actual variable ");
+        error_append(actualPort);
+        error_append(" have different types in subcircuit ");
+        error_append(instanceName);
+        error_append(" in model ");
+        error_append(Hrc_ModelReadName(model));
+        error_append(".\n");
+        return 0;
+      }
+      if (Var_VariableSetSO(var) == -1){
+        return 0;
+      };
+      array_insert_last(Var_Variable_t *,actualOutputArray,var); 
+    }
+    st_free_table(outputCheckTable);
+    st_free_table(tmpTable);
+    if (Hrc_ModelAddSubckt(model,subcktModel,instanceName,actualInputArray,actualOutputArray) == 0){
+      error_append("Error: Model ");
+      error_append(Hrc_ModelReadName(model));
+      error_append(" has two subcircuits with the same instance name ");
+      error_append(instanceName);
+      error_append("\n");
+      return 0;
+    }
+  }
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks to see if there is no inconsistency in a latch definition.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static boolean
+_IoModelTestLatchConsistency(Hrc_Node_t *hnode)
+{
+  Hrc_Latch_t *latch;
+  Var_Variable_t *varIn, *varOut;
+  st_generator *gen;
+  char *latchName;
+
+  Hrc_NodeForEachLatch(hnode,gen,latchName,latch){
+    varIn = Hrc_LatchReadInput(latch);
+    varOut = Hrc_LatchReadOutput(latch);
+    if (Var_VariablesTestHaveSameDomain(varIn,varOut) == 0){
+      error_append("Error: The input and the output of latch ");
+      error_append(latchName);
+      error_append(" have different domains.\n"); 
+      return 0; 
+    }
+    if (Hrc_LatchReadResetTable(latch) == NIL(Tbl_Table_t)){
+      error_append("Error: Latch ");
+      error_append(Var_VariableReadName(varOut));
+      error_append(" has no reset table.\n");
+      return 0;
+    }
+  }
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Checks to see if there is no inconsistency in reset declarations.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+static boolean
+_IoModelTestResetConsistency(
+  Hrc_Manager_t *hmgr,
+  Hrc_Model_t *model,
+  Hrc_Node_t *hnode,
+  array_t *resetArray)
+{
+  int i;
+  Var_Variable_t *output;
+  Tbl_Table_t *resetTable;
+  Hrc_Latch_t *latch;
+
+  for (i=0; i < array_n(resetArray); i++){
+    resetTable = array_fetch(Tbl_Table_t *,resetArray,i);
+    if (Tbl_TableReadNumOutputs(resetTable) != 1){
+      error_append("Error: Reset table with output ");
+      error_append(Var_VariableReadName(Tbl_TableReadIndexVar(resetTable,0,1)));
+      error_append(" has to be a single output table.\n");
+      return 0;
+    }
+    output = Tbl_TableReadIndexVar(resetTable,0,1);
+    if (Var_VariableTestIsPS(output) == 0){
+      error_append("Error: Reset table with output ");
+      error_append(Var_VariableReadName(output));
+      error_append(" is not attached to a latch.\n");
+      return 0;
+    }
+    latch = Hrc_NodeFindLatchByName(hnode,Var_VariableReadName(output));
+    if (Hrc_LatchSetResetTable(latch,resetTable) == 0){
+      error_append("Error: You try to overwrite the reset table of ");
+      error_append(Var_VariableReadName(output));
+      error_append(".\n");
+      return 0;
+    }
+    /* once a reset table is associated with a latch,
+    we remove the table from resetArray */
+    array_insert(Tbl_Table_t *,resetArray,i,NIL(Tbl_Table_t));
+  }
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks the consistency of the internal connection of a model.]
+
+  Description [Checks the consistency of the internal connection of a model.
+  Returns 1 if success. Otherwise returns 0.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static boolean
+_IoModelTestInternalConnectionConsistency(
+  Hrc_Model_t *model,
+  Hrc_Node_t *hnode,
+  boolean isVerbose)
+{
+  st_table *varToTable, *outputVarToSubckt, *inputVarToSubckt, *visitTable;
+  st_generator *gen;
+  int i, j, status, warningStatus;
+  Var_Variable_t *var, *actualOutput;
+  Tbl_Table_t *table;
+  char *varName, *subcktName, *latchName;
+  Hrc_Subckt_t *subckt, *anotherSubckt;
+  Hrc_Latch_t *latch;
+  
+  /* creates a hash table from variables to tables */ 
+  varToTable = st_init_table(st_ptrcmp,st_ptrhash);
+  Hrc_NodeForEachNameTable(hnode,i,table){
+    Tbl_TableForEachOutputVar(table,j,var){
+      if (Var_VariableTestIsPI(var) == 1){
+        error_append("Error: Primary input ");
+        error_append(Var_VariableReadName(var));
+        error_append(" is an output of a table in model ");
+        error_append(Hrc_ModelReadName(model));
+        error_append(".\n");
+        st_free_table(varToTable);
+        return 0; 
+      }
+      if (st_insert(varToTable,(char *)var,(char *)table) == 1){
+        error_append("Error: Variable ");
+        error_append(Var_VariableReadName(var));
+        error_append(" is an output of more than one table in model ");
+        error_append(Hrc_ModelReadName(model));
+        error_append(".\n");
+        st_free_table(varToTable);
+        return 0;
+      }
+    }
+  }
+  Hrc_NodeForEachLatch(hnode,gen,latchName,latch){
+    if (st_insert(varToTable,(char *)Hrc_LatchReadOutput(latch),(char *)Hrc_LatchReadResetTable(latch)) == 1){
+      error_append("Error: Latch output ");
+      error_append(Var_VariableReadName(Hrc_LatchReadOutput(latch)));
+      error_append(" is an output of a table in model ");
+      error_append(Hrc_ModelReadName(model));
+      error_append(".\n");
+      st_free_table(varToTable);
+      return 0;
+    }
+  }
+
+  /* creates two hash tables
+     one from output variables of subckts to subckts
+     the other one from input variables of subckts to subckts */
+  outputVarToSubckt = st_init_table(st_ptrcmp,st_ptrhash);
+  inputVarToSubckt = st_init_table(st_ptrcmp,st_ptrhash);
+
+  Hrc_ModelForEachSubckt(model,gen,subcktName,subckt){
+    array_t *actualOutputs = Hrc_SubcktReadActualOutputVars(subckt);
+    array_t *actualInputs = Hrc_SubcktReadActualInputVars(subckt);
+
+    for (i=0; i < array_n(actualOutputs); i++){
+      actualOutput = array_fetch(Var_Variable_t *,actualOutputs,i);
+      if (st_lookup(varToTable,(char *)actualOutput,&table) == 1){
+        error_append("Error: Subckt output ");
+        error_append(Var_VariableReadName(actualOutput));
+        error_append(" in ");
+        error_append(subcktName);
+        error_append(" is an output of a table in model ");
+        error_append(Hrc_ModelReadName(model));
+        error_append(".\n");
+        st_free_table(varToTable);
+        st_free_table(outputVarToSubckt);
+        st_free_gen(gen);
+        return 0;
+      }
+      if (st_lookup(outputVarToSubckt,(char *)actualOutput,&anotherSubckt) == 1){
+        error_append("Error: Subckt output ");
+        error_append(Var_VariableReadName(actualOutput));
+        error_append(" in ");
+        error_append(subcktName);
+        error_append(" is also a subckt output of ");
+        error_append(Hrc_SubcktReadInstanceName(anotherSubckt));
+        error_append(" in model ");
+        error_append(Hrc_ModelReadName(model));
+        error_append(".\n");
+        st_free_table(varToTable);
+        st_free_table(outputVarToSubckt);
+        st_free_gen(gen);
+        return 0;
+      }
+      (void)st_insert(outputVarToSubckt,(char *)actualOutput,(char *)subckt);
+    }
+    
+    for (i=0; i < array_n(actualInputs); i++){
+      Var_Variable_t *actualInput = array_fetch(Var_Variable_t *,actualInputs,i);
+      (void)st_insert(inputVarToSubckt,(char *)actualInput,(char *)subckt);
+    }
+
+  }
+
+  /* start checking the consistency of a hnode */
+  Hrc_NodeForEachVariable(hnode,gen,varName,var) {
+    if (st_lookup(varToTable,(char *)var,&table) == 0){
+      if (Var_VariableTestIsPS(var) == 1 || Var_VariableTestIsPI(var) == 1){
+        continue;
+      }
+      else {
+       if (st_lookup(outputVarToSubckt,(char *)var,&subckt) == 0) { 
+         error_append("Error: Variable "); 
+         error_append(varName); 
+         error_append(" is not defined as an output of a table in model "); 
+         error_append(Hrc_ModelReadName(model)); 
+         error_append(".\n"); 
+         st_free_table(varToTable); 
+         st_free_gen(gen); 
+         return 0; 
+       }
+    }
+    }
+  }
+
+  
+  /* compute numFanoutTables */
+  Hrc_NodeForEachNameTable(hnode,i,table){
+    Tbl_TableForEachInputVar(table,j,var){
+      Var_VariableIncrementNumFanoutTables(var);
+    }
+  }
+
+  /* acyclic check */
+  visitTable = st_init_table(st_ptrcmp,st_ptrhash);
+  status = _IoModelTestIsAcyclic(model,hnode,varToTable,outputVarToSubckt,visitTable);
+  warningStatus = 0;
+  if (status == 1){
+  /* as a by-product of the acyclic check, visitTable now contains
+  all the variables reachable from either PO, NS, or reset tables.
+  We use this to detect all the variables not used in the hnode */
+    Hrc_NodeForEachVariable(hnode,gen,varName,var){
+      if (st_is_member(visitTable,(char *)var) == 0 && 
+          st_is_member(inputVarToSubckt,(char *)var) == 0 &&
+          Var_VariableTestIsPO(var) == 0 &&
+          Var_VariableTestIsNS(var) == 0 &&
+          Var_VariableTestIsPS(var) == 0 ){
+        warningStatus = 1;
+        if (isVerbose){
+          /* the following is just a warning. We do not return a failure status */
+          error_append("Warning: Variable ");
+          error_append(Var_VariableReadName(var));
+          error_append(" is not used in ");
+          error_append(Hrc_ModelReadName(model));
+          error_append(".\n");
+        }
+      }
+    }
+  }
+  if (isVerbose == 0 && warningStatus == 1){
+    error_append("Warning: Some variables are unused in model ");
+    error_append(Hrc_ModelReadName(model));
+    error_append(".\n");
+  }
+  st_free_table(varToTable);
+  st_free_table(outputVarToSubckt);
+  st_free_table(inputVarToSubckt);
+  st_free_table(visitTable);
+
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [A DFS-based procedure for checking acyclicity.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static boolean
+_IoModelTestIsAcyclic(
+  Hrc_Model_t *model,
+  Hrc_Node_t *hnode,
+  st_table *varToTable,
+  st_table *outputVarToSubckt,
+  st_table *visitTable)
+{
+  int i;
+  Var_Variable_t *var;
+  st_generator *gen;
+  char *latchName;
+  Hrc_Latch_t *latch;
+
+  Hrc_NodeForEachFormalOutput(hnode,i,var){
+    if (_IoModelTestIsAcyclicRecursive(model,hnode,var,varToTable,outputVarToSubckt,visitTable,0) == 0){
+      _IoModelTestIsAcyclicError(model,var);
+      return 0;
+    }
+  }
+  Hrc_NodeForEachLatch(hnode,gen,latchName,latch){
+    Tbl_Table_t *resetTable;
+
+    resetTable = Hrc_LatchReadResetTable(latch);
+    Tbl_TableForEachInputVar(resetTable,i,var){
+      int status;
+      if ((status = _IoModelTestIsAcyclicRecursive(model,hnode,
+          var,varToTable,outputVarToSubckt,visitTable,1)) == 0){
+        _IoModelTestIsAcyclicError(model,var);
+        st_free_gen(gen);
+        return 0;
+      }
+      /* found a path from a PS to a reset table */
+      if (status == -1){
+        error_append(latchName);
+        error_append(" in model ");
+        error_append(Hrc_ModelReadName(model));
+        error_append(".\n");
+        st_free_gen(gen);
+        return 0;
+      }
+    } 
+  }
+  Hrc_NodeForEachLatch(hnode,gen,latchName,latch){
+    if (_IoModelTestIsAcyclicRecursive(model,hnode,
+        (var = Hrc_LatchReadInput(latch)),varToTable,outputVarToSubckt,visitTable,0) == 0){
+      _IoModelTestIsAcyclicError(model,var);
+      st_free_gen(gen);
+      return 0;
+    } 
+  }
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Prints out error messages during an acyclic check.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+_IoModelTestIsAcyclicError(
+  Hrc_Model_t *model,
+  Var_Variable_t *var)
+{
+  error_append("Warning: Model ");
+  error_append(Hrc_ModelReadName(model));
+  error_append(" may have a cyclic connection which involves variable ");
+  error_append(Var_VariableReadName(var));
+  error_append("\n");
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Recursive DFS routine for acyclic check.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+_IoModelTestIsAcyclicRecursive(
+  Hrc_Model_t *model,
+  Hrc_Node_t *hnode,
+  Var_Variable_t *var,
+  st_table *varToTable,
+  st_table *outputVarToSubckt,
+  st_table *visitTable,
+  boolean isResetLogic)
+{
+  int val, i;
+  Var_Variable_t *input;
+  Tbl_Table_t *table;
+  Hrc_Subckt_t *subckt;
+
+  if (st_lookup_int(visitTable,(char *)var, &val) == 1){
+    return (!val);
+  }
+  else{
+    (void)st_insert(visitTable,(char *)var,(char *)1);
+    
+    if (Var_VariableTestIsPI(var) == 0 &&
+           (isResetLogic || Var_VariableTestIsPS(var) == 0)){
+      if (isResetLogic && (Var_VariableTestIsPS(var) == 1)){
+        error_append("Warning: There is a path from latch output ");
+        error_append(Var_VariableReadName(var));
+        error_append(" to reset table ");
+
+        /* the error message is to be continued in _IoModelTestIsAcyclic() */
+        return -1;  
+      }
+      if (st_lookup(varToTable,(char *)var,&table) == 1){
+        Tbl_TableForEachInputVar(table,i,input){
+          int status;
+          if ((status = _IoModelTestIsAcyclicRecursive(model,hnode,input,
+                           varToTable,outputVarToSubckt,visitTable,isResetLogic)) == 0){
+            return 0;
+          }
+          if (status == -1){
+            return -1;
+          }
+        }
+      }
+      else {
+        array_t *actualInputs;
+        /* the return value of the following st_lookup should be 1 */
+        (void)st_lookup(outputVarToSubckt,(char *)var,&subckt);
+        actualInputs = Hrc_SubcktReadActualInputVars(subckt);
+        assert (actualInputs != NIL(array_t));
+        for (i=0; i < array_n(actualInputs); i++){
+          int status;
+          input = array_fetch(Var_Variable_t *,actualInputs,i);
+          if ((status = _IoModelTestIsAcyclicRecursive(model,hnode,input,
+                         varToTable,outputVarToSubckt,visitTable,0)) == 0){
+            return 0;
+          }
+          if (status == -1){
+            return -1;
+          }
+        }
+      }
+    }
+    (void)st_insert(visitTable,(char *)var,(char *)0);
+    return 1;
+  }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/io/ioCmd.c
===================================================================
--- vis_dev/vis-2.3/src/io/ioCmd.c	(revision 14)
+++ vis_dev/vis-2.3/src/io/ioCmd.c	(revision 14)
@@ -0,0 +1,1126 @@
+/**CFile***********************************************************************
+
+  FileName	[ioCmd.c]
+
+  PackageName	[io]
+
+  Synopsis	[Top-level routines for reading and writing files.]
+
+  Description	[This file contains top-level routines for I/O functions of VIS.]
+
+  Author	[Yuji Kukimoto, Rajeev K. Ranjan, Sunil P. Khatri, Huey-Yih Wang]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ioInt.h"
+
+static char rcsid[] UNUSED = "$Id: ioCmd.c,v 1.16 2005/05/19 02:34:33 awedh Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+#ifndef NAWK
+#define NAWK "gawk"
+#endif
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+extern FILE *yyin;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandReadBlifMv(Hrc_Manager_t **hmgr, int argc, char **argv);
+static int CommandWriteBlifMv(Hrc_Manager_t **hmgr, int argc, char **argv);
+static int CommandReadVerilog(Hrc_Manager_t **hmgr, int argc, char **argv);
+static int CommandReadBlif(Hrc_Manager_t **hmgr, int argc, char **argv);
+static int CommandWriteBlif(Hrc_Manager_t **hmgr, int argc, char **argv);
+static int CommandWriteSmv(Hrc_Manager_t **hmgr, int argc, char **argv);
+ 
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the I/O package.]
+
+  SideEffects []
+
+  SeeAlso     [Io_End]
+
+******************************************************************************/
+void
+Io_Init(void)
+{
+  Cmd_CommandAdd("read_blif_mv", CommandReadBlifMv, 0);
+  Cmd_CommandAdd("write_blif_mv", CommandWriteBlifMv, 0);
+  Cmd_CommandAdd("write_smv", CommandWriteSmv, 0);
+  Cmd_CommandAdd("read_verilog", CommandReadVerilog, 0);
+  Cmd_CommandAdd("read_blif", CommandReadBlif, 0);
+  Cmd_CommandAdd("write_blif", CommandWriteBlif, 0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Ends the I/O package.]
+
+  SideEffects []
+
+  SeeAlso     [Io_Init]
+
+******************************************************************************/
+void
+Io_End(void)
+{
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [The top-level routine for read_blif_mv.]
+
+  Description []
+
+  SideEffects []
+
+  CommandName [read_blif_mv]
+  CommandSynopsis [read a blif-mv file]
+  CommandArguments [\[-c\] \[-h\] \[-r\] \[-v\] &lt;file_name&gt;]
+  CommandDescription [Reads a blif-mv file into VIS. The existing
+  hierarchy for the blif-mv file
+  previously read in is overwritten upon a successful read. If
+  an error is detected while reading a file, the previous hierarchy is
+  preserved.<p>
+  Command options:<p>
+  <dl><dt> -c
+  <dd> Semi-canonicalize all the tables in each model. The canonicalization
+  process, assigns a linear order to the table rows and columns, based on the
+  value of their entries. For a table with binary valued entries, this value
+  is exactly the number of 1's in the row or column. Once this linear
+  order is assigned, the rows and columns of the table are swapped so as to
+  order rows and columns with higher value at the beginning of the
+  corresponding row or column order. It is called semi-canonicalization
+  because two tables representing the same logic function need not have the
+  same canonical form. 
+  </dl>
+  <dl><dt> -h
+  <dd> Print the command usage.
+  </dl>
+  <dl><dt> -r
+  <dd> If set, the program replaces the subhierarchy rooted at
+  the current node with a new hierarchy specified by a blif-mv file.
+  The file to be read in has to be compatible with the i/o interface 
+  of the current hnode (the same i/o names with the same domains). 
+  Otherwise, the current hierarchy is kept intact. If -r is not specified,
+  the entire hierarchy is replaced, not just the subhierarchy at the current
+  node.
+  </dl>
+  <dl><dt> -v 
+  <dd> If set, the program prints out all the unused variables
+  in the blif-mv file. Otherwise, only a warning is printed that 
+  some variables are not used.
+  </dl>
+  <dl><dt> &lt;file_name&gt;
+  <dd> blif-mv file to be read in.
+  </dl>
+
+  For more information on blif-mv, refer to the 
+  <A HREF="http://www-cad.eecs.berkeley.edu/Respep/Research/vis/doc/blifmv/blifmv/blifmv.html">blif-mv manual</A>.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+CommandReadBlifMv(
+  Hrc_Manager_t **hmgr,
+  int argc,
+  char **argv)
+{
+  int status, c;
+  boolean isCanonical, isIncremental, isVerbose;
+  char *fileName;
+  FILE *fp;
+  Hrc_Manager_t *newHmgr;
+  
+  isCanonical = 0;
+  isIncremental = 0;
+  isVerbose = 0;
+  util_getopt_reset();
+  while ((c = util_getopt(argc,argv,"chrv")) != EOF){
+    switch(c){
+      case 'c':
+        isCanonical = 1;
+        break;
+      case 'h':
+        goto usage;
+      case 'r':
+        isIncremental = 1;
+        break;
+      case 'v':
+        isVerbose = 1;
+        break;
+      default:
+        goto usage;
+    }
+  }
+  
+  /* check to see if there is only one argument left for a file name */
+  if (argc-1 != util_optind){
+    goto usage;
+  }
+  fileName = argv[util_optind];
+
+  fp = Cmd_FileOpen(fileName, "r", NIL(char *), 1);
+  
+  if (fp == NIL(FILE)){
+    (void)fprintf(vis_stderr,"File %s cannot be opened\n", fileName);
+    return 1;
+  }
+  error_init();
+
+  newHmgr = Io_BlifMvRead(fp,*hmgr,isCanonical,isIncremental,isVerbose);
+  /* success */
+  if (newHmgr != NIL(Hrc_Manager_t)){
+    status = 0;
+    if (isIncremental == 0){
+      Hrc_ManagerFree(*hmgr);
+      *hmgr = newHmgr;
+    }
+  }
+  /* failure */
+  else {
+    status = 1;
+  }
+  (void)fprintf(vis_stderr,"%s",error_string());
+  fflush(vis_stderr);
+  if (fp != stdin) {
+    (void) fclose(fp);
+  }
+  return (status);
+
+  usage:
+    (void)fprintf(vis_stderr, "usage: read_blif_mv [-c] [-h] [-r] [-v] file\n");
+    (void)fprintf(vis_stderr, "   -c  semi-canonicalize all the tables\n");
+    (void)fprintf(vis_stderr, "   -h  print the command usage\n");  
+    (void)fprintf(vis_stderr, "   -r  replace the current subhierarchy\n");
+    (void)fprintf(vis_stderr, "   -v  verbose\n");
+    return 1 ;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [The top-level routine for write_blif_mv.]
+
+  Description []
+
+  SideEffects []
+
+  CommandName [write_blif_mv]
+  CommandSynopsis [write a blif-mv file]
+  CommandArguments [\[-h\] \[&lt;file&gt;\]]
+  CommandDescription [Writes out the hierarchy below the current
+  node in blif-mv format to the file specified as an argument.
+  If no argument is specified,
+  the output is available at the standard output.<p>
+  Command options:<p>
+  <dl><dt> -h
+  <dd> Print the command usage.
+  </dl>
+  <dl><dt> &lt;file&gt;
+  <dd> name of blif-mv file to be written.
+  </dl>
+  For more information on blif-mv, refer to the
+  <A HREF="http://www-cad.eecs.berkeley.edu/Respep/Research/vis/doc/blifmv/blifmv/blifmv.html">blif-mv manual</A>.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+CommandWriteBlifMv(
+  Hrc_Manager_t **hmgr,
+  int argc,
+  char **argv)
+{
+  FILE *fp;
+  int c;
+  Hrc_Node_t *currentNode;
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc,argv,"h")) != EOF){
+    switch(c){
+      case 'h':
+        goto usage;
+      default:
+        goto usage;
+    }
+  }
+
+  currentNode = Hrc_ManagerReadCurrentNode(*hmgr);
+  if (currentNode == NIL(Hrc_Node_t)){
+    (void)fprintf(vis_stderr,"No file has been read in.\n");
+    return 1;
+  }
+
+  if (argc == 1){
+    fp = stdout;
+  }
+  else if (argc == 2){
+    fp = Cmd_FileOpen(*(++argv), "w", NIL(char *), 1);
+    if (fp == NIL(FILE)){
+      (void)fprintf(vis_stderr,"Cannot write to %s\n", *argv);
+      return 1;
+    }
+  }
+  else {
+    goto usage; 
+  }
+  
+  error_init();
+  IoBlifMvWrite(fp,*hmgr);
+  (void)fprintf(vis_stderr,"%s",error_string());
+  fflush(fp);
+  if (fp != stdout) {
+    (void) fclose(fp);
+  }
+  return 0;
+
+  usage:
+    (void)fprintf(vis_stderr, "usage: write_blif_mv [-h] [file]\n");
+    (void)fprintf(vis_stderr, "   -h  print the command usage\n");  
+    return 1;
+}
+
+/**Function********************************************************************
+ 
+  Synopsis    [The top-level routine for write_smv.]
+
+  Description []
+
+  SideEffects []
+
+  CommandName [write_smv]
+  CommandSynopsis [write an smv file]
+  CommandArguments [\[-h\] \[&lt;file&gt;\]]
+  CommandDescription [Writes out the hierarchy below the current
+  node in smv format to the file specified as an argument.
+  If no argument is specified,
+  the output is available at the standard output.<p>
+  Command options:<p>
+  <dl><dt> -h
+  <dd> Print the command usage.
+  </dl>
+  <dl><dt> &lt;file&gt;
+  <dd> name of smv file to be written.
+  </dl>
+  For more information on smv, refer to the
+ <A HREF="http://www-2.cs.cmu.edu/~modelcheck/smv.html">smv manual</A>.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+CommandWriteSmv(
+  Hrc_Manager_t **hmgr,
+  int argc,
+  char **argv)
+{
+  FILE *fp;
+  int c;
+  Hrc_Node_t *currentNode;
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc,argv,"h")) != EOF){
+    switch(c){
+      case 'h':
+        goto usage;
+      default:
+        goto usage;
+    }
+  }
+
+  currentNode = Hrc_ManagerReadCurrentNode(*hmgr);
+  if (currentNode == NIL(Hrc_Node_t)){
+    (void)fprintf(vis_stderr,"No file has been read in.\n");
+    return 1;
+  }
+
+  if (argc == 1){
+    fp = stdout;
+  }else if (argc == 2){
+    fp = Cmd_FileOpen(*(++argv), "w", NIL(char *), 1);
+    if (fp == NIL(FILE)){
+      (void)fprintf(vis_stderr,"Cannot write to %s\n", *argv);
+      return 1;
+    }
+  }else {
+    goto usage; 
+  }
+  
+  error_init();
+  IoSmvWrite(fp,*hmgr);
+  (void)fprintf(vis_stderr,"%s",error_string());
+  fflush(fp);
+  if (fp != stdout) {
+    (void) fclose(fp);
+  }
+  return 0;
+
+  usage:
+    (void)fprintf(vis_stderr, "usage: write_smv [-h] [file]\n");
+    (void)fprintf(vis_stderr, "   -h  print the command usage\n");  
+    return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [The top-level routine for read_verilog.]
+
+  Description []
+
+  SideEffects []
+
+  CommandName [read_verilog]
+  CommandSynopsis [read a verilog file]
+  CommandArguments [\[-c\] \[-h\] \[-u\] \[-F\] &lt;file_name&gt;]
+  CommandDescription [Reads a verilog file into VIS. Internally
+  the file is transformed into an equivalent blif-mv file, which is
+  then read into VIS. The existing hierarchy for the blif-mv file 
+  previously read in is 
+  overwritten upon a successful read. If an error is detected while 
+  reading a file, the previous hierarchy is preserved.<p>
+  Command options:<p>
+  <dl><dt> -c
+  <dd> Use explicit clocking.
+  </dl>
+  <dl><dt> -h
+  <dd> Print the command usage.
+  </dl>
+  <dl><dt> -u
+  <dd> Turn off loop unroling.
+  </dl>
+  <dl><dt> -F
+  <dd> Ignore all timing.
+  </dl>
+  <dl><dt> &lt;file_name&gt;
+  <dd> Verilog file to be read in.
+  </dl>]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+CommandReadVerilog(Hrc_Manager_t **hmgr, int argc, char **argv)
+{
+  int c;
+  char *realFileName, *verilogFileName;
+#if HAVE_MKSTEMP && HAVE_CLOSE
+  char outFileName[] = "/tmp/vis.XXXXXX";
+  int  fd;
+#else
+  char *outFileName;
+  char buffer[512];
+#endif
+  FILE *fp;
+  static char parseBuffer[1024];
+  int vl2mvStatus;
+  int cSet = 0;
+  int uSet = 0;
+  int FSet = 0;
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc,argv,"chuF")) != EOF){
+    switch(c){
+      case 'c':
+        cSet = 1;
+        break;
+      case 'h': 
+        goto usage;
+      case 'u':
+        uSet = 1;
+        break;
+      case 'F':
+        FSet = 1;
+        break;
+      default:
+        goto usage;
+    }
+  }
+  
+  /* check to see if there is only one argument left for a file name */
+  if (argc-1 != util_optind){
+    goto usage;
+  }
+  verilogFileName = argv[util_optind];
+
+  fp = Cmd_FileOpen(verilogFileName, "r", &realFileName, /* silent */ 1);
+  
+  if (fp == NIL(FILE)){
+    FREE(realFileName);
+    (void)fprintf(vis_stderr,"File %s  cannot be opened\n", verilogFileName);
+    return 1;
+  }
+  fclose(fp);
+
+#if HAVE_MKSTEMP && HAVE_CLOSE
+  fd = mkstemp(outFileName);
+  if (fd == -1){
+#else
+  outFileName = util_strsav(tmpnam(buffer));
+  if (outFileName == NIL(char)){
+#endif
+    FREE(realFileName);
+    (void)fprintf(vis_stderr,"Can not create temporary file. ");
+    (void)fprintf(vis_stderr,"Clean up /tmp an try again.\n");
+    return  1;
+  }  
+ 
+  strcpy(parseBuffer,"vl2mv ");
+  strcat(parseBuffer,"-o ");
+  strcat(parseBuffer,outFileName);
+  strcat(parseBuffer," ");
+  /* start inserting options for vl2mv */
+  if (cSet){
+    strcat(parseBuffer,"-c ");
+  }
+  if (uSet){
+    strcat(parseBuffer,"-u ");
+  }
+  if (FSet){
+    strcat(parseBuffer,"-F ");
+  }
+  strcat(parseBuffer, realFileName);
+  FREE(realFileName);
+#if HAVE_MKSTEMP && HAVE_CLOSE
+  close(fd);
+#endif
+  vl2mvStatus = system(parseBuffer);
+  if (vl2mvStatus != 0){
+    return 1;
+  }
+  sprintf(parseBuffer,"read_blif_mv %s",outFileName);
+  Cmd_CommandExecute(hmgr, parseBuffer);
+#if HAVE_UNLINK
+  unlink(outFileName);
+#endif
+  return 0;
+  
+  usage:
+    (void)fprintf(vis_stderr, "usage: read_verilog [-c] [-h] [-u] [-F] file\n");
+    (void)fprintf(vis_stderr, "   -c  use explicit clocking\n");
+    (void)fprintf(vis_stderr, "   -h  print the command usage\n");
+    (void)fprintf(vis_stderr, "   -u  turn off unroling\n");
+    (void)fprintf(vis_stderr, "   -F  ignore all timing\n");
+    return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [The top-level routine for read_blif.]
+
+  Description []
+
+  SideEffects []
+
+  CommandName [read_blif]
+  CommandSynopsis [read a blif file]
+  CommandArguments [\[-c\] \[-e &lt;encoding_file_name&gt;\] \[-h\] [-v\] &lt;file_name&gt;]
+  CommandDescription [Reads a file in blif format into VIS. 
+  All the synthesis-specific constructs of blif are ignored. 
+  Internally the blif file is automatically translated into an equivalent 
+  blif-mv file, which is then read in with read_blif_mv. Note that,
+  currently this command cannot read blif files which describe mapped
+  circuits. To get around this problem, please use SIS synthesis tool
+  to generate an ordinary  blif file.
+  
+  Command options:<p>
+  <dl><dt> -c
+  <dd> Semi-canonicalize all the tables in each model. See the documentation
+  of <A HREF=./read_blif_mvCmd.html> read_blif_mv </A> for details.
+  </dl>
+  <dl><dt> -e &lt;encoding_file_name&gt;
+  <dd> If set, the program reads in a blif file using the encoding
+  information specified in the encoding_file_name. Only the current
+  hnode is altered in the process, and hence the read is incremental.
+  Typically the encoding file is written out by a write_blif operation.
+  Note that this option cannot be used if no file has been read in.
+  Internally, the encoding file is used in combination with the blif file
+  to create a blif-mv file which is compatible with the I/O interface
+  of the current node.
+  </dl>
+  <dl><dt> -h
+  <dd> Print the command usage.
+  </dl>
+  <dl><dt> -v
+  <dd> If set, the program prints out all the unused variables
+  in the blif file.
+  </dl>
+  <dl><dt> &lt;file_name&gt;
+  <dd> Name of a blif file to be read in. This can be the output written by SIS.
+  in the blif file.
+  </dl>
+  ]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+CommandReadBlif(
+  Hrc_Manager_t **hmgr,
+  int argc,
+  char **argv)
+{
+  int c, status;
+  boolean isCanonical = 0;
+  boolean isIncremental = 0;
+  boolean isVerbose = 0;
+  char *fileName, *realFileName, *visDirectoryName, *blifMvFileName;
+  char *encodingFileName;
+  char command[512];
+  FILE *fp;
+#if HAVE_MKSTEMP && HAVE_CLOSE
+  int  fd;
+#else
+  char buffer[512];
+#endif
+  Hrc_Manager_t *newHmgr;
+  
+  util_getopt_reset();
+  while ((c = util_getopt(argc,argv,"ce:hv")) != EOF){
+    switch(c){
+      case 'c':
+        isCanonical = 1;
+        break;
+      case 'e':
+        isIncremental = 1;
+        fp = Cmd_FileOpen(util_optarg, "r", &encodingFileName, 1);
+        if (fp == NIL(FILE)){
+          (void)fprintf(vis_stderr,"Encoding file %s is not found\n", util_optarg);
+          return 1;
+        }
+        if (fp != stdin){
+          (void)fclose(fp);
+        }
+        break;
+      case 'h':
+        goto usage;
+      case 'v':
+        isVerbose = 1;
+        break;
+      default:
+        goto usage;
+    }
+  }
+
+  /* check to see if there is only one argument left for a file name */
+  if (argc-1 != util_optind){
+    goto usage;
+  }
+  fileName = argv[util_optind];
+
+  fp = Cmd_FileOpen(fileName, "r", &realFileName, 1);
+  
+  if (fp == NIL(FILE)){
+    /*
+    FREE(realFileName);
+    */
+    (void)fprintf(vis_stderr,"File %s cannot be opened\n", fileName);
+    return 1;
+  }
+  if (fp != stdin){
+    (void)fclose(fp);
+  }
+
+#if HAVE_MKSTEMP && HAVE_CLOSE
+  blifMvFileName = util_strsav("/tmp/vis.XXXXXX");
+  fd = mkstemp(blifMvFileName);
+  if (fd == -1){
+#else
+  blifMvFileName = util_strsav(tmpnam(buffer));
+  if (blifMvFileName == NIL(char)){
+#endif
+    FREE(realFileName);
+    (void)fprintf(vis_stderr,"Could not create temporary file. ");
+    (void)fprintf(vis_stderr,"Clean up /tmp an try again.\n");
+    return 1;
+  }
+#if HAVE_MKSTEMP && HAVE_CLOSE
+  close(fd);
+#endif
+  /* Invoking an awk script */
+  visDirectoryName = Vm_VisObtainLibrary();
+  if (isIncremental == 0){
+    (void)sprintf(command,"sed 's/^\\./@/g' %s | sed 's/\\./$/g' | sed 's/^@/\\./g' | sed 's/{/</g' | sed 's/}/>/g'| sed 's/(/<</g' | sed 's/)/>>/g'| %s -f %s/ioBlifToMv.nawk > %s", realFileName, NAWK, visDirectoryName, blifMvFileName);
+  }
+  else {
+    (void)sprintf(command,"sed 's/^\\./@/g' %s | sed 's/\\./$/g' | sed 's/^@/\\./g' | sed 's/{/</g' | sed 's/}/>/g'| %s -f %s/ioBlifToMvForIncremental.nawk > %s", realFileName, NAWK, visDirectoryName, blifMvFileName);
+  }
+  (void)system(command);
+  FREE(visDirectoryName);
+  FREE(realFileName);
+
+  error_init();
+
+  if (isIncremental == 0){
+    fp = Cmd_FileOpen(blifMvFileName, "r", NIL(char *), 1);
+  }
+  else {
+    char *finalBlifMvFileName;
+    
+#if HAVE_MKSTEMP && HAVE_CLOSE
+    finalBlifMvFileName = util_strsav("/tmp/vis.XXXXXX");
+    fd = mkstemp(finalBlifMvFileName);
+    if (fd == -1){
+#else
+    finalBlifMvFileName = util_strsav(tmpnam(buffer));
+    if (finalBlifMvFileName == NIL(char)){
+#endif
+      FREE(blifMvFileName);
+      (void)fprintf(vis_stderr,"Could not create temporary file. ");
+      (void)fprintf(vis_stderr,"Clean up /tmp an try again.\n");
+      return 1;
+    }
+#if HAVE_MKSTEMP && HAVE_CLOSE
+    close(fd);
+#endif
+
+    (void)sprintf(command,"cat %s %s > %s",encodingFileName,blifMvFileName,finalBlifMvFileName);
+    (void)system(command);
+    FREE(encodingFileName);
+#if HAVE_UNLINK
+    unlink(blifMvFileName);
+#endif
+    FREE(blifMvFileName);
+    blifMvFileName = finalBlifMvFileName;
+
+    fp = Cmd_FileOpen(blifMvFileName, "r", NIL(char *), 1);
+  }
+  assert(fp != NIL(FILE));
+  newHmgr = Io_BlifMvRead(fp,*hmgr,isCanonical,isIncremental,isVerbose);
+  if (newHmgr != NIL(Hrc_Manager_t)){
+    status = 0;
+    if (isIncremental == 0){
+      Hrc_ManagerFree(*hmgr);
+      *hmgr = newHmgr;
+    }
+  }
+  else {
+    status = 1;
+  }
+
+  (void)fprintf(vis_stderr,"%s",error_string());
+  fflush(vis_stderr);
+  if (fp != stdin) {
+    (void) fclose(fp);
+#if HAVE_UNLINK
+    unlink(blifMvFileName);
+#endif
+  }
+  FREE(blifMvFileName);
+  return (status);
+
+  usage:
+    (void)fprintf(vis_stderr, "usage: read_blif [-c] [-e encoding_file] [-h] [-v] file\n");
+    (void)fprintf(vis_stderr, "   -c  table canonicalization\n");
+    (void)fprintf(vis_stderr, "   -e  read a file into the current node using encoding file\n");
+    (void)fprintf(vis_stderr, "   -h  print the command usage\n");    
+    (void)fprintf(vis_stderr, "   -v  verbose\n");
+    return 1 ;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [The top-level routine for write_blif]
+
+  Description [Determinizes, encodes and writes a set of tables into blif]
+
+  SideEffects []
+
+  CommandName [write_blif]
+  CommandSynopsis [determinize, encode and write an hnode to a blif file]
+  CommandArguments [\[-c\] \[-l\] \[-e &lt;encoding_file_name&gt;\] \[-R\] \[-h\] \[-v &lt;verbosity_value&gt;\] \[&lt;file&gt;\]]
+  CommandDescription [Encodes, determinizes, and writes all tables in the current hnode
+  to a BLIF file. With the '-l' or '-c' options, or when 'write_blif'
+  is used with no options, only the current hnode is written out as 
+  a blif file. The '-R' option writes the entire hierarchy rooted at the 
+  current hnode to the blif file, assuming all tables are deterministic 
+  and all variables are boolean. <p>
+  
+
+  Encoding the Multi-Valued Variables: <p>
+  
+  First, all multi-valued variables in the hnode are binary
+  encoded. Each multi-valued variable requires 'm' binary variables in
+  its encoding, where m = log2(n). Here 'n' is the number of values in 
+  the domain of the multi-valued variable. If variable X has n binary
+  variables in its encoding, these are called X0, X1, ... X<n-1>. X0
+  is the least significant encoding variable. The value i of multi-valued 
+  variable X is encoded such that 
+   X0 + 2^1 * X1 + ... + 2^(n-1) * X<n-1> = i.
+  After encoding, each table in the hnode is written out to the blif file. 
+  <p>
+  Determinizing Non-Deterministic Tables:<p>
+
+  
+  Non-deterministic tables are determinized by adding more binary variables 
+  to a particular variable's encoding. The variable that is chosen is the 
+  one that has the smallest number of binary variables in its encoding. 
+  Determinization is explained by means of an example:
+  <p>
+  Consider the BLIF-MV table, where each of a, b, and c can have 4 values.
+  Each multi-valued variable has two binary variables in its encoding. These
+  are called a0, a1, b0, b1, c0 and c1.
+  <p>
+  .model foo<p>
+  .inputs a b<p>
+  .outputs c<p>
+  .mv a, b, c 4<p>
+  .table a b ->c<p>
+  2 1 (1,2)<p>
+  (1,2) 1 3<p>
+  .end<p>
+  <p>
+  The first row of this table represents non-determinism, since for a 
+  given assignment of input values (i.e. a=2, b=1), the output can take 
+  on two values (1 or 2). To determinize this row, it is split into two 
+  rows, each with a unique singleton output value. A new binary variable 
+  is added to the encoding of a (or b, since in this case each of them has
+  the same number of binary variables in its encoding). The new variable 
+  a2 is given separate values in each of the new rows. The resulting blif 
+  table looks like:
+  <p>
+  .model foo<p>
+  .inputs a0 a1 a2 b0 b1 <p>
+  .outputs c0 c1<p>
+  .names a0 a1 a2 b0 b1 ->c0 c1<p>
+  0 1 0 1 0 1 0          (these two rows represent<p>
+  0 1 1 1 0 0 1          row 1 of the MV table)<p>
+  1 0 - 1 0 1 1          (these two rows represent            <p>
+  0 1 - 1 0 1 1          row 2 of the MV table)<p>
+  .end<p>
+  <p>
+  Note that this table is still not deterministic, since rows 1 and
+  4 have input minterm(s) in common, but the corresponding outputs
+  are different. To resolve this, a new binary variable is added to
+  the encoding for b (since b currently has the smallest encoding).
+  For the conflicting rows, this variable b2 is assigned different 
+  values, and for all other rows, it is assigned a '-' value. After
+  this change, rows 1 and 4 no longer have common input minterm(s).
+  The intermediate table now looks like:
+  <p>
+  .model foo<p>
+  .inputs a0 a1 a2 b0 b1 b2<p>
+  .outputs c0 c1<p>
+  .names a0 a1 a2 b0 b1 b2->c0 c1<p>
+  0 1 0 1 0 1 1 0<p>
+  0 1 1 1 0 - 0 1<p>
+  1 0 - 1 0 - 1 1<p>
+  0 1 - 1 0 0 1 1<p>
+  .end<p>
+  <p>
+  This process is continued until the table is determinized. In this
+  example, the final blif file looks like:
+  <p>
+  .model foo<p>
+  .inputs a0 a1 a2 a3 b0 b1 b2<p>
+  .outputs c0 c1<p>
+  .table a0 a1 a2 a3 b0 b1 b2 ->c0 c1 <p>
+  0 1 0 - 1 0 1 1 0 <p>
+  0 1 1 1 1 0 - 0 1 <p>
+  1 0 - - 1 0 - 1 1 <p>
+  0 1 - 0 1 0 0 1 1 <p>
+  .end<p>
+  <p>
+  Blif allows only single output tables, so in reality the above table
+  is split into two single output tables before being written out to 
+  the blif file. The new binary variables that are thus introduced are 
+  treated as primary inputs in the blif file.
+  <p>
+  We make no claim on the optimality of this process, just that it is 
+  simple. It may turn out that the number of new variables is much larger than
+  the optimum one.
+  <p>
+  Interfacing Between Binary and Multi-Valued Variables:<p>
+  <p>
+  In order for the SIS-optimized version of this file to be read back into
+  VIS, we need to re-create the corresponding multi-valued variables. For 
+  this purpose, interface information (model name, input and output 
+  declarations for the hnode) is written out to a special encoding file
+  (e.g. foo.enc).
+  Additionally, binary->multi-valued encoding tables are written to the 
+  encoding file for each PO. In the above example, the binary->multi-valued
+  table for variable c looks like<p>
+  .table c0 c1 -> c<p>
+  0 0 0<p>
+  1 0 1<p>
+  0 1 2<p>
+  1 1 3<p>
+  and this can be seen as a decoder of the binary variables.
+  Similarly, multi-valued->binary encoding tables are written to the encoding
+  file for each PI. The multi-valued->binary table for variable b in the above
+  example is:<p>
+  .table b -> b0 b1<p>
+  0 0 0  <p>
+  1 1 0<p>
+  2 0 1<p>
+  3 1 1<p>
+  and this can be seen as an encoder of the multi-valued variables.
+  Similar tables are written to the encoding file for sub-circuit inputs and 
+  outputs. Likewise, such tables are written out for latch inputs and outputs.
+  This is needed so that the original multi-valued latches can be reinstated 
+  while the blif file is being read back into VIS. These multi-valued latch 
+  declarations are written to the encoding file during the write_blif process.
+  <p>
+  The combination of this encoding file and the blif file results in a legal 
+  BLIF-MV hnode description.
+  <p>
+  If no file is specified, the blif file is written out to the standard output. 
+  If the encoding file is not specified, encoding information is written out 
+  to <modelname>.enc. 
+  <p>
+  Options:<p>
+  <p>
+  The '-R' option writes the entire hierarchy rooted at the current hnode to 
+  the blif file, first checking that all tables are deterministic and all variables are 
+  boolean. Other options ('-c', '-l', or write_blif with no options) only write 
+  out the current hnode. Also, when the '-R' option is specified, no encoding
+  file is written since none is needed.
+  
+  <p>
+  Command options:<p>
+  <dl><dt> -c
+  <dd> Writes only combinational part to blif file.
+  </dl>
+  <dl><dt> -l
+  <dd> Writes out latches, making latch IOs primary outputs in the blif file.
+  </dl>
+  <dl><dt> -e &lt;encoding_file_name&gt;
+  <dd> If set, the program writes the encoding information into this 
+  file. The default is the model name for the current node
+  extended by .enc.
+  </dl>
+  <dl><dt> -R
+  <dd> Recursively writes out the entire hierarchy rooted at the current hnode to the blif file.
+  In this sub-hierarchy, all tables must be deterministic and all variables must be boolean.
+  Either of the -c, -l or -e options cannot be used together with this option.
+  </dl>
+  <dl><dt> -h
+  <dd> Prints the command usage.
+  </dl>
+  <dl><dt> -v &lt;verbosity_value&gt;
+  <dd> Specifies verbosity level, an integer less than 3.
+  </dl>
+  <dl><dt> &lt;file&gt;
+  <dd> name of blif file to be written, default is standard output.
+  </dl>
+  <dl><dt> 
+  <dd> Note that if neither the -c or the -l options are chosen, then latches are written out,
+  without making latch IOs primary outputs in the blif file. Currently the files written out 
+  using this option cannot be read back into VIS.
+  </dl>
+  ]
+
+  SeeAlso     []
+
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+CommandWriteBlif(
+  Hrc_Manager_t **hmgr,
+  int argc, 
+  char **argv)
+{
+  FILE *enc_fp, *fp;
+  char *modelName, *dupname;
+  int status, verbosity, combinationalOnly, makeLatchIOsPOs;
+  Io_Encoding_Type_t encoding_type;
+  Hrc_Node_t *hnode;
+  int c;
+  boolean recursive;
+
+  fp = stdout;
+  enc_fp = NIL(FILE);
+  verbosity = 0;
+  combinationalOnly = 0;
+  makeLatchIOsPOs = 0;
+  recursive = 0;
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "clRe:hv:")) != EOF) {
+      switch(c) {
+      case 'c':
+	  combinationalOnly = 1;
+	  break;
+      case 'l':
+	  makeLatchIOsPOs = 1;
+	  break;
+      case 'R':
+	  recursive = 1;
+	  break;
+      case 'e':
+	  enc_fp = Cmd_FileOpen(util_optarg, "w", NIL(char *), 1);
+	  if (enc_fp == NIL(FILE)){
+	      (void)fprintf(vis_stderr,"Cannot write to %s\n", util_optarg);
+	      return 1;
+	  }
+	  break;
+      case 'h':
+	  goto usage;
+      case 'v':
+	  verbosity = atoi(util_optarg);
+	  break;
+      default:
+	  goto usage;
+      }
+  }
+
+  if(makeLatchIOsPOs && combinationalOnly){
+    (void)fprintf(vis_stderr,"Cannot use -c and -l options simultaneously.\n");
+    goto usage;
+  }
+  if(recursive){
+    if(makeLatchIOsPOs || combinationalOnly){
+      (void)fprintf(vis_stderr,"Cannot use -c or -l options with -R option.\n");      
+      goto usage;
+    }
+    if(enc_fp != NIL(FILE)){
+      (void)fprintf(vis_stderr,"Cannot use -e option with -R option.\n");            
+      goto usage;
+    }
+  }
+  hnode = Hrc_ManagerReadCurrentNode(*hmgr);
+  if (hnode == NIL(Hrc_Node_t)){
+    (void)fprintf(vis_stderr,"No file has been read in.\n");
+    return 1;
+  }
+
+  /* check to see if there is only one argument left for a file name */
+  if (argc == util_optind){
+    fp = stdout;
+  }
+  else if (argc-1 == util_optind){
+    fp = Cmd_FileOpen(argv[util_optind], "w", NIL(char *), 1);
+    if (fp == NIL(FILE)){
+      (void)fprintf(vis_stderr,"Cannot write to %s\n", argv[util_optind]);
+       if (enc_fp != NIL(FILE)){
+         fclose(enc_fp);
+       }
+       return 1;
+    }
+  }
+  else {
+    if (enc_fp != NIL(FILE)){
+      fclose(enc_fp);
+    }
+    goto usage;
+  }
+
+  if((enc_fp == NIL(FILE)) && !recursive){
+      modelName = Hrc_NodeReadModelName(hnode);
+      dupname = ALLOC(char, strlen(modelName) + strlen(".enc") + 1);
+      sprintf(dupname, "%s%s", modelName, ".enc");
+      enc_fp = Cmd_FileOpen(dupname, "w", NIL(char *), 1);
+      if (enc_fp == NIL(FILE)){
+        (void)fprintf(vis_stderr,"Cannot write to %s\n", dupname);
+        return 1;
+      }
+      (void)fprintf(stdout, "Writing encoding information to %s\n",dupname);
+      FREE(dupname);
+  }
+
+  if(!recursive){
+    if(!(makeLatchIOsPOs || combinationalOnly)){
+      (void)fprintf(vis_stderr,"Warning - The blif and encoding files generated cannot be read back into \n");
+      (void)fprintf(vis_stderr, "VIS. If you would like to read the optimized blif file back into VIS, then \n");
+      (void)fprintf(vis_stderr, "please use 'write_blif -l' or 'write_blif -c' instead.\n");
+    }
+  }
+
+  error_init();
+  encoding_type = SIMPLE;
+  if(recursive){
+    status = Io_HnodeWriteBlifTotal(encoding_type, hnode, fp, verbosity);
+  }
+  else{
+    status = Io_HnodeWriteBlif(encoding_type, hnode, fp, enc_fp, verbosity, combinationalOnly, makeLatchIOsPOs);
+  }
+  (void)fprintf(vis_stderr,"%s",error_string());
+  fflush(fp);
+  if (fp != stdout) {
+    (void) fclose(fp);
+  }
+
+  if(status == 0){
+    return 0;
+  }
+  else{
+    return 1;
+  }
+
+  usage:
+    (void)fprintf(vis_stderr, "usage: write_blif [-c] [-l] [-e encoding_file] [-R] [-h] [-v verbosity] [blif_file]\n");
+    (void)fprintf(vis_stderr, "   -c write only combinational part to blif file\n");  
+    (void)fprintf(vis_stderr, "   -l make latch IOs primary outputs in the blif file\n");  
+    (void)fprintf(vis_stderr, "   -e encoding_file, default is <model_name>.enc\n");
+    (void)fprintf(vis_stderr, "   -R recursively write out the hierarchy rooted at the current hnode.\n");
+    (void)fprintf(vis_stderr, "      In this sub-hierarchy, all tables must be deterministic and all\n");
+    (void)fprintf(vis_stderr, "      variables must be boolean. Either of the -c, -l, or -e options \n");
+    (void)fprintf(vis_stderr, "      cannot be simultaneously with the -R option \n");
+    (void)fprintf(vis_stderr, "   -h print this usage message\n");  
+    (void)fprintf(vis_stderr, "   -v verbosity, an integer < 3, default is 0\n");
+    (void)fprintf(vis_stderr, "Note: * If neither the -c or -l options are chosen, then latches will \n");
+    (void)fprintf(vis_stderr, "        be written out to the blif file. Latch IOs will not be made\n");
+    (void)fprintf(vis_stderr, "        into primary outputs in the blif file\n");
+    (void)fprintf(vis_stderr, "      * After optimizing the blif file in SIS, do not write out the\n");
+    (void)fprintf(vis_stderr, "        optimized file using 'write_blif -s' if you want to read\n");
+    (void)fprintf(vis_stderr, "        it back into VIS. Use 'write_blif' instead \n");
+    return 1 ;
+    
+}
+
Index: vis_dev/vis-2.3/src/io/ioInt.h
===================================================================
--- vis_dev/vis-2.3/src/io/ioInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/io/ioInt.h	(revision 14)
@@ -0,0 +1,371 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [ioInt.h]
+
+  PackageName [io]
+
+  Synopsis    [Internal declarations of the I/O package.]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [Yuji Kukimoto, Sunil P. Khatri, Rajeev Ranjan, Huey-Yih Wang]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: ioInt.h,v 1.10 2004/07/16 00:05:26 wangc Exp $]
+
+******************************************************************************/
+
+#ifndef _IOINT
+#define _IOINT
+
+#include "var.h"
+#include "tbl.h"
+#include "io.h"
+#include "cmd.h"
+#include "ord.h"
+#include "ntk.h"
+#include "ntm.h"
+#include <string.h>
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef struct IoSymValueStruct IoSymValue_t;
+typedef struct IoParsedTableStruct IoPTable_t;
+typedef struct IoSubcktStruct IoSubckt_t;
+typedef struct IoBlifInfoStruct IoBlifInfo_t;
+typedef struct IoVarEncEntryStruct IoVarEncEntry_t;
+typedef struct IoBinRangeEntryStruct IoBinRangeEntry_t;
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**Enum************************************************************************
+
+  Synopsis    [Types of a node in the tree data structure for a table.]
+
+  Description []
+
+  SeeAlso     []
+
+******************************************************************************/
+typedef enum {
+  IoLeaf_c,
+  IoRange_c,
+  IoComplement_c,
+  IoList_c,
+  IoAssign_c,
+  IoUniverse_c
+} IoSymValueType;
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [A tree representation of a table. This structure is used
+  to represent a node in the tree. The parser translates 
+  tables represented in IoParsedTable_t to this data structure so that
+  it is easy to construct the table data structure Tbl_Table_t
+  corresponding to the table.]
+
+  Description []
+
+  SeeAlso     []
+
+******************************************************************************/
+struct IoSymValueStruct {
+  IoSymValueType flag;
+  struct IoSymValueStruct *left;
+  struct IoSymValueStruct *right;
+  array_t *elements;	/* array_t of SymValueStruct * */
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [A temporary data structure to keep the textual information
+  on tables. Only used in the parser. ]
+
+  Description []
+
+  SeeAlso     []
+
+******************************************************************************/
+struct IoParsedTableStruct {
+  array_t *inputs;  /* array of table input names */
+  array_t *outputs;  /* array of table output names */
+  array_t *cubes; /* array of array_t *, each array_t is a symCube */
+  array_t *defaultOutput; /* this field is a single symCube */
+};
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [A temporary data structure to keep the textual information
+  on subcircuits. Only used in the parser.]
+
+  Description []
+
+  SeeAlso     []
+
+******************************************************************************/
+struct IoSubcktStruct {
+  char *modelName;
+  char *instanceName;
+  array_t *formalNameArray;
+  array_t *actualNameArray;
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [info for write blif]
+
+  Description []
+
+  SeeAlso     []
+
+******************************************************************************/
+struct IoBlifInfoStruct {
+  Tbl_Table_t *blifmvTable;
+  Tbl_Table_t *binTable;
+  array_t *inputEncTblArray;
+  array_t *outputEncTblArray;
+  array_t *varArray;
+  array_t *binTblArray;
+  array_t *dcTblArray;
+  int verbosity;
+  boolean pseudoinputFlag;
+  FILE *EncFp;
+  FILE *BlifFp;
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [Binary ranges structure, for binary entries compaction 
+               in write_blif ]
+
+  Description []
+
+  SeeAlso     []
+
+******************************************************************************/
+struct IoBinRangeEntryStruct {
+    int startValue;
+    int runLength;
+    int skipLength;
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [info for encoding variablen]
+
+  Description []
+
+  SeeAlso     []
+
+******************************************************************************/
+struct IoVarEncEntryStruct {
+    Var_Variable_t *variable;
+    int index;
+    int numEncBits;
+};
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+extern int globalLineNumber;
+extern Hrc_Manager_t *globalYaccHmgr;
+extern Hrc_Model_t *globalModel;
+extern Hrc_Node_t *globalHnode;
+extern Hrc_Model_t *globalFirstModel;
+extern Hrc_Model_t *globalRootModel;
+extern char *globalRootInstanceName;
+extern array_t *globalMvNameArray;
+extern array_t *globalSymValueArray;
+extern array_t *globalTableInputArray;
+extern array_t *globalTableOutputArray;
+extern array_t *globalTableDefaultArray;
+extern array_t *globalTableSymCubeArray;
+extern array_t *globalFormalNameArray;
+extern array_t *globalActualNameArray;
+extern array_t *globalSubcktArray;
+extern array_t *globalResetArray;
+extern array_t *globalNewModelArray;
+extern st_table *globalParserResetInfo;
+extern st_table *globalParserSubcktInfo;
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN boolean IoNetworkTestConsistency(Hrc_Manager_t *hmgr, array_t *modelArray, st_table *parserSubcktInfo, st_table *parserResetInfo, boolean isVerbose);
+EXTERN Var_Variable_t * IoVariableFindOrAllocByName(Hrc_Node_t *hnode, char *name);
+EXTERN int IoAtoi(char *string);
+EXTERN void IoStringArrayFree(array_t *array);
+EXTERN void IoNameInsertInArray(array_t **arrayPtrPtr, char *name);
+EXTERN void IoSymValueInsertInArray(array_t **arrayPtrPtr, IoSymValue_t *value);
+EXTERN void IoSymCubeInsertInArray(array_t **arrayPtrPtr, array_t *symCube);
+EXTERN boolean IoInputProcess(Hrc_Node_t *hnode, char *name);
+EXTERN boolean IoOutputProcess(Hrc_Node_t *hnode, char *name);
+EXTERN boolean IoMvProcess(Hrc_Model_t *model, Hrc_Node_t *hnode, array_t *varNames, int range, array_t *symValues);
+EXTERN boolean IoLatchProcess(Hrc_Model_t *model, Hrc_Node_t *hnode, char *latchInput, char *latchOutput);
+EXTERN boolean IoTableProcess(Hrc_Model_t *model, Hrc_Node_t *hnode, array_t *inputArray, array_t *outputArray, array_t *defaultArray, array_t *symCubeArray);
+EXTERN boolean IoResetProcess(array_t **resetArray, Hrc_Model_t *model, Hrc_Node_t *hnode, array_t *inputArray, array_t *outputArray, array_t *defaultArray, array_t *symCubeArray);
+EXTERN boolean IoSubcktProcess(array_t **subcktArray, Hrc_Model_t *model, Hrc_Node_t *hnode, char *modelName, char *instanceName, array_t *formalNameArray, array_t *actualNameArray);
+EXTERN void IoError(void);
+EXTERN boolean _IoNodeTestCompatibility(Hrc_Manager_t *hmgr, Hrc_Node_t *hnode1, Hrc_Node_t *hnode2);
+EXTERN Tbl_Table_t * IoPTableTransformToTable(Hrc_Model_t *model, Hrc_Node_t *hnode, IoPTable_t *pTable);
+EXTERN IoSymValue_t * IoSymValueAlloc(void);
+EXTERN void IoSymValueArrayFree(array_t *valueArray);
+EXTERN void IoBlifMvWrite(FILE *fp, Hrc_Manager_t *hmgr);
+EXTERN void IoMvPrint(FILE *fp, Var_Variable_t *var);
+EXTERN void IoMvPrintSpecial(FILE *fp, Var_Variable_t *var);
+EXTERN void IoSmvWrite(FILE *fp, Hrc_Manager_t *hmgr);
+EXTERN void IoSmvPrint(FILE *fp, Var_Variable_t *var);
+EXTERN void IoSmvPrintSpecial(FILE *fp, Var_Variable_t *var);
+EXTERN IoVarEncEntry_t *IoFindSmallestCode(IoBlifInfo_t *blifInfo);
+EXTERN array_t *IoMakeBinaryRangesArray(Tbl_Entry_t *entry, int colnum, IoBlifInfo_t *blifInfo);
+EXTERN Tbl_Table_t *IoMakeSingleOutputTable(Tbl_Table_t *table, int i);
+EXTERN int IoBlifWriteInputs(Hrc_Node_t *hnode, FILE *fp, st_table *blifInputsStTable, int combinationalOnly, int makeLatchIOsPOs);
+EXTERN int IoBlifWriteOutputs(Hrc_Node_t *hnode, FILE *fp, st_table *blifOutputsStTable, int combinationalOnly, int makeLatchIOsPOs);
+EXTERN void IoChangeBlifmvTableRows(IoBlifInfo_t *blifInfo, IoVarEncEntry_t *varEnc, int row1, int row2);
+EXTERN void IoChangeBlifmvTableEntries(IoBlifInfo_t *blifInfo, int rownum, int numValues, IoVarEncEntry_t *varEnc, array_t *MvOutputArray);
+EXTERN void IoChangeEncTableEntries(IoBlifInfo_t *blifInfo, st_table *blifInputsStTable, IoVarEncEntry_t *varEnc, int numValues);
+EXTERN void IoEncWriteBinToMvTables(Hrc_Node_t *hnode, FILE *encFp, st_table *encOutputsStTable, st_table *encInputsStTable, int combinationalOnly, int makeLatchIOsPOs);
+EXTERN void IoEncWriteMvToBinTables(Hrc_Node_t *hnode, FILE *encFp, st_table *encOutputsStTable, st_table *encInputsStTable, int combinationalOnly);
+EXTERN void IoEncodeVariable(IoBlifInfo_t *blifInfo, Var_Variable_t *var, int varNum, int output);
+EXTERN void IoFreeBlifInfo(IoBlifInfo_t *blifInfo);
+EXTERN void IoIncreaseCodeSize(IoVarEncEntry_t *varEnc, int numValues, int verbosity);
+EXTERN void IoInitBlifInfo(IoBlifInfo_t *blifInfo, Tbl_Table_t *origBlifmvTable, FILE *fp, FILE *encFp, int verbosity);
+EXTERN void IoInvertBinTableOutput(IoBlifInfo_t * blifInfo, int colnumToInvert);
+EXTERN int IoLog(int n);
+EXTERN void IoMvCheckPrint(FILE *fp, Var_Variable_t *var, st_table *printedMvsStTable);
+EXTERN void IoMvCheckPrintSpecial(FILE *fp, Var_Variable_t *var, st_table *printedMvsStTable);
+EXTERN int IoNumBinVars(int colnum, array_t *encTblArray);
+EXTERN int IoNumDigits(int n);
+EXTERN int IoNumEncBits(int n);
+EXTERN int IoNumValuesFromBinRangesArray(int colnum, array_t *binRangesArray);
+EXTERN boolean IoOutputExpansionRequired(Tbl_Table_t *table);
+EXTERN boolean IoVarIsHnodePIO(Hrc_Node_t *hnode, Var_Variable_t *var);
+EXTERN void IoWriteBinTablesToFile(IoBlifInfo_t *blifInfo);
+EXTERN int IoWriteExpandedValueToBinTable(Tbl_Table_t *binTable, int rootRow, int rootCol, IoBinRangeEntry_t *binRangeEntry, int entryRepetitionCount, int numBits, int output);
+EXTERN void IoWriteLatches(Hrc_Node_t *hnode, FILE *fp, FILE *encFp, st_table *printedMvsStTable, st_table *blifOutputsStTable, st_table *blifInputsStTable, st_table *encOutputsStTable, st_table *encInputsStTable, int combinationalOnly, int makeLatchIOsPOs, int verbosity);
+
+
+/**AutomaticEnd***************************************************************/
+
+EXTERN int IoYyparse(void);
+EXTERN void IoYyrestart(FILE *);
+
+#endif /* _ */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/io/ioParse.c
===================================================================
--- vis_dev/vis-2.3/src/io/ioParse.c	(revision 14)
+++ vis_dev/vis-2.3/src/io/ioParse.c	(revision 14)
@@ -0,0 +1,639 @@
+/**CFile***********************************************************************
+
+  FileName    [ioParse.c]
+
+  PackageName [io]
+
+  Synopsis    [Functions used in parsing BLIF-MV files.]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [Yuji Kukimoto, Rajeev Ranjan, Huey-Yih Wang]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ioInt.h"
+
+static char rcsid[] UNUSED = "$Id: ioParse.c,v 1.4 2002/08/16 17:35:01 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void _IoParserAddSubckt(array_t **subcktArray, char *modelName, char *instanceName, array_t *formalNameArray, array_t *actualNameArray);
+static int _IoIOProcess(Hrc_Node_t *hnode, char *name, int type);
+static IoPTable_t * _IoPTableCreate(array_t *inputArray, array_t *outputArray, array_t *defaultArray, array_t *symCubeArray);
+static void _IoPTableFree(IoPTable_t *pTable);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Finds or allocate a variable by name in a hnode.]
+
+  Description [Finds a variable by name in a hnode. If success, returns
+  a pointer to the variable. Otherwise allocates a new variable
+  and return a pointer to the variable..]
+
+  SideEffects []
+
+  SeeAlso     [Var_VariableFree]
+
+******************************************************************************/
+
+Var_Variable_t *
+IoVariableFindOrAllocByName(
+  Hrc_Node_t *hnode,
+  char *name)
+{
+  Var_Variable_t *var;
+
+  if ((var = Hrc_NodeFindVariableByName(hnode,name)) != NIL(Var_Variable_t)){
+    return var;
+  }
+  var = Var_VariableAlloc(hnode,name);
+  return var;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Converts a character string to the integer.]
+
+  Description [Converts a character string to the positive integer. Returns
+  -1 if the string does not represent an integer.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+IoAtoi(char *string)
+{
+  char *s;
+  for (s=string; *s!='\0'; s++) {
+    if (isdigit((int) *s)==0){
+      return -1;
+    }
+  } 
+  return atoi(string);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees an array of strings.]
+
+  Description [Frees an array of strings. Strings themselves are also
+  freed.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+IoStringArrayFree(array_t *array)
+{
+  int i;
+  char *symbol;
+
+  for (i=0; i < array_n(array); i++) {
+    symbol = array_fetch(char *, array, i);
+    FREE(symbol);
+  }
+  array_free(array);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Insert a character string to an array.]
+
+  Description [Insert a character string to an array. The string is not copied.
+  Note that the first argument is not a pointer to an array, but a pointer
+  to a pointer to an array.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+IoNameInsertInArray(array_t **arrayPtrPtr, char *name)
+{
+  if (*arrayPtrPtr == NIL(array_t)){
+    *arrayPtrPtr = array_alloc(char *, 0);
+  }
+  array_insert_last(char *, *arrayPtrPtr, name);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts a IoSymValue_t structure to an array.]
+
+  Description [Inserts a IoSymValue_t structure to an array. Note that
+  the first argument is a pointer to a pointer to the array.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+IoSymValueInsertInArray(array_t **arrayPtrPtr, IoSymValue_t *value)
+{
+  if (*arrayPtrPtr == NIL(array_t)){
+    *arrayPtrPtr = array_alloc(IoSymValue_t *, 0);
+  }
+  array_insert_last(IoSymValue_t *, *arrayPtrPtr, value);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts a SymCube(an array of IoSymValue_t) to an array.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+IoSymCubeInsertInArray(array_t **arrayPtrPtr, array_t *symCube)
+{
+  if (*arrayPtrPtr == NIL(array_t)){
+    *arrayPtrPtr = array_alloc(array_t *, 0);
+  }
+  array_insert_last(array_t *, *arrayPtrPtr, symCube);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Reads in .inputs constructs.]
+
+  Description [Reads in .inputs constructs. Returns 1 if success. 0 otherwise.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+IoInputProcess(
+  Hrc_Node_t *hnode, 
+  char *name)
+{
+  return _IoIOProcess(hnode, name, 0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Reads in .outputs constructs.]
+
+  Description [Reads in .outputs constructs. Returns 1 if success. 0 otherwise.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+IoOutputProcess(
+  Hrc_Node_t *hnode, 
+  char *name)
+{
+  return _IoIOProcess(hnode, name, 1);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Reads in .mv constructs.]
+
+  Description [Reads in .mv constructs. Returns 1 if success. 0 otherwise.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+IoMvProcess(
+  Hrc_Model_t *model, 
+  Hrc_Node_t *hnode, 
+  array_t *varNames, 
+  int range, 
+  array_t *symValues)
+{
+  int i;
+  char *varName;
+  Var_Variable_t *var;
+
+  if (range == -1) {
+    error_append("Invalid .mv specification of ");
+    error_append(array_fetch(char *,varNames,0));
+    error_append(" in model ");
+    error_append(Hrc_ModelReadName(model));
+    error_append("\n- Range should be an integer.\n");
+    return 0;
+  }
+
+  for (i=0; i < array_n(varNames); i++){
+    varName = array_fetch(char *,varNames,i);
+    if ((var = Hrc_NodeFindVariableByName(hnode,varName)) != NIL(Var_Variable_t)) {
+      if (Var_VariableAddRangeInfo(var,range,symValues) == 0){
+        error_append("Invalid .mv specification of ");
+        error_append(varName);
+        error_append(" in model ");
+        error_append(Hrc_ModelReadName(model));
+        error_append("\n- You are trying to redefine the above variable.\n");
+        return 0;
+      }
+    }
+    else {
+      var = Var_VariableAlloc(hnode,varName);
+      (void)Var_VariableAddRangeInfo(var,range,symValues);
+    }
+  }
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Reads in .latch constructs.]
+
+  Description [Reads in .latch constructs. Returns 1 if success. 0 otherwise.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+IoLatchProcess(
+  Hrc_Model_t *model,
+  Hrc_Node_t *hnode, 
+  char *latchInput,
+  char *latchOutput)
+{
+  Var_Variable_t *varIn, *varOut;
+
+  varIn = IoVariableFindOrAllocByName(hnode,latchInput);
+  varOut = IoVariableFindOrAllocByName(hnode,latchOutput);
+  if (varIn == NIL(Var_Variable_t) || varOut == NIL(Var_Variable_t)){
+    return 0;
+  }
+  if ((Hrc_LatchCreate(model,varIn,varOut)) == NIL(Hrc_Latch_t)){
+    return 0; 
+  }
+  (void)Var_VariableSetNS(varIn);
+  /* a latch can have only one fanin */
+  if (Var_VariableSetPS(varOut) == 0){
+    error_append("Variable ");
+    error_append(latchOutput);
+    error_append(" are fed by more than one latch\n");
+    return 0;
+  }
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Reads in .table constructs.]
+
+  Description [Reads in .table constructs. Returns 1 if success. 0 otherwise.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+IoTableProcess(
+  Hrc_Model_t *model,
+  Hrc_Node_t *hnode,
+  array_t *inputArray,
+  array_t *outputArray,
+  array_t *defaultArray,
+  array_t *symCubeArray)
+{
+  IoPTable_t *pTable;
+  Tbl_Table_t *table;
+
+  pTable = _IoPTableCreate(inputArray,outputArray,defaultArray,symCubeArray);
+
+  if ((table = IoPTableTransformToTable(model, hnode, pTable)) == NIL(Tbl_Table_t)){
+    _IoPTableFree(pTable);
+    return 0;
+  }
+  _IoPTableFree(pTable);
+  Hrc_ModelAddNameTable(model,table);
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Reads in .reset constructs.]
+
+  Description [Reads in .reset constructs. Returns 1 if success. 0 otherwise.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+IoResetProcess(
+  array_t **resetArray,
+  Hrc_Model_t *model, 
+  Hrc_Node_t *hnode, 
+  array_t *inputArray, 
+  array_t *outputArray, 
+  array_t *defaultArray, 
+  array_t *symCubeArray)
+{
+  IoPTable_t *pTable;
+  Tbl_Table_t *table;
+
+  pTable = _IoPTableCreate(inputArray,outputArray,defaultArray,symCubeArray);
+  if ((table = IoPTableTransformToTable(model,hnode,pTable)) == NIL(Tbl_Table_t)){
+    _IoPTableFree(pTable);
+    return 0;
+  }
+  _IoPTableFree(pTable);
+
+  if (*resetArray == NIL(array_t)){
+    *resetArray = array_alloc(Tbl_Table_t *,0);
+  }
+  array_insert_last(Tbl_Table_t *,*resetArray,table);
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads in .subckt constructs.]
+
+  Description [Reads in .subckt constructs. Returns 1 if success. 0 otherwise.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+IoSubcktProcess(
+  array_t **subcktArray,
+  Hrc_Model_t *model, 
+  Hrc_Node_t *hnode, 
+  char *modelName, 
+  char *instanceName, 
+  array_t *formalNameArray, 
+  array_t *actualNameArray)
+{
+  int i;
+  char *actual;
+  Var_Variable_t *var;
+
+  for (i=0; i < array_n(actualNameArray); i++){
+    actual = array_fetch(char *,actualNameArray,i);
+    var = IoVariableFindOrAllocByName(hnode,actual);
+    if (var == NIL(Var_Variable_t)){
+      error_append("Problem in defining variable ");
+      error_append(actual);
+      error_append(" found in subckt ");
+      error_append(instanceName);
+      error_append(" in model ");
+      error_append(Hrc_ModelReadName(model));
+      error_append("\n");
+      return 0;
+    }
+  }
+
+  _IoParserAddSubckt(subcktArray,modelName,instanceName,formalNameArray,actualNameArray);
+  return 1;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Add subckt information to the data structure where the parser
+  maintains all the subckt data.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+_IoParserAddSubckt(
+  array_t **subcktArray,
+  char *modelName,
+  char *instanceName,
+  array_t *formalNameArray,
+  array_t *actualNameArray)
+{
+  IoSubckt_t *subckt;
+
+  subckt = ALLOC(IoSubckt_t,1);
+  subckt->modelName = modelName;
+  subckt->instanceName = instanceName;
+  subckt->formalNameArray = formalNameArray;
+  subckt->actualNameArray = actualNameArray;
+
+  if (*subcktArray == NIL(array_t)){
+    *subcktArray = array_alloc(IoSubckt_t *,0);
+  }
+  array_insert_last(IoSubckt_t *, *subcktArray, subckt);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Process .inputs and .outputs construct.]
+
+  Description [Process .inputs and .outputs construct. Returns 1 if success.
+  Otherwise returns 0.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+static int
+_IoIOProcess(
+  Hrc_Node_t *hnode,
+  char *name,
+  int type)
+{
+  Var_Variable_t *var;
+
+  if (Hrc_NodeFindVariableByName(hnode, name) != NIL(Var_Variable_t)) {
+    error_append("Variable ");
+    error_append(name);
+    error_append(" is tried to be set to PI and PO in model ");
+    error_append(Hrc_NodeReadModelName(hnode));
+    error_append("\n");
+    return 0;
+  }
+  var = Var_VariableAlloc(hnode,name);
+  switch(type){
+    case 0:  /* PI */
+      Hrc_NodeAddFormalInput(hnode,var);
+      /* the following is now a part of Hrc_NodeAddFormalInput */
+      /*(void)Var_VariableSetPI(var);*/
+      break;
+    case 1:  /* PO */
+      Hrc_NodeAddFormalOutput(hnode,var);
+      /* the following is now a part of Hrc_NodeAddFormalOutput */
+      /*(void)Var_VariableSetPO(var);*/
+      break;
+    default:
+      fail("Strange argument is given to variable type in IOProcess\n");
+  }
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates a temporary data structure for parsing tables.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static IoPTable_t *
+_IoPTableCreate(
+  array_t *inputArray,
+  array_t *outputArray,
+  array_t *defaultArray,
+  array_t *symCubeArray)
+{
+  IoPTable_t *pTable;
+
+  pTable = ALLOC(IoPTable_t,1);
+  if (inputArray == NIL(array_t)){
+    pTable->inputs = array_alloc(char *,0);
+  }
+  else {
+    pTable->inputs = inputArray;
+  }
+  assert(outputArray != NIL(array_t));
+  pTable->outputs = outputArray;
+  pTable->defaultOutput = defaultArray;
+  pTable->cubes = symCubeArray;
+
+  return pTable;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a temporary data structure for parsing the tables.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+static void
+_IoPTableFree(IoPTable_t *pTable)
+{
+  int i;
+  array_t *symValueArray;
+
+  IoStringArrayFree(pTable->inputs);
+  IoStringArrayFree(pTable->outputs);
+  if (pTable->defaultOutput != NIL(array_t)){
+    IoSymValueArrayFree(pTable->defaultOutput);
+  }
+  if (pTable->cubes != NIL(array_t)){
+    for (i=0; i < array_n(pTable->cubes); i++){
+      symValueArray = array_fetch(array_t *,pTable->cubes,i);
+      IoSymValueArrayFree(symValueArray);
+    }
+    array_free(pTable->cubes);
+  }
+  FREE(pTable);
+}
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/io/ioReadBlifMv.c
===================================================================
--- vis_dev/vis-2.3/src/io/ioReadBlifMv.c	(revision 14)
+++ vis_dev/vis-2.3/src/io/ioReadBlifMv.c	(revision 14)
@@ -0,0 +1,608 @@
+/**CFile***********************************************************************
+
+  FileName    [ioReadBlifMv.c]
+
+  PackageName [io]
+
+  Synopsis    [Routines related to reading in blif-mv files.]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [Yuji Kukimoto, Rajeev Ranjan, Huey-Yih Wang]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ioInt.h"
+
+static char rcsid[] UNUSED = "$Id: ioReadBlifMv.c,v 1.12 2002/09/10 04:35:24 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+#ifndef NAWK
+#define NAWK "gawk"
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+static jmp_buf env;
+extern FILE *IoYyin;
+extern int globalCurrentStackDepth;
+#ifdef IODEBUG
+extern int IoYydebug;
+#endif /*IODEBUG */
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void _IoGlobalVariablesInitialize(void);
+static void _IoGlobalVariablesFree(void);
+static void _IoGlobalSubcktInfoFree(void);
+static void _IoSubcktArrayFree(array_t *array);
+static void _IoSubcktFree(IoSubckt_t *subckt);
+static void _IoGlobalResetInfoFree(void);
+static boolean _IoNodeTestCompatibilityAux(Hrc_Manager_t *hmgr, Hrc_Node_t *hnode1, Hrc_Node_t *hnode2, boolean mode);
+static void _IoManagerCanonicalize(Hrc_Manager_t *hmgr);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Reads in a blif-mv file.]
+
+  Description [Reads in a blif-mv file. Returns a pointer to a new hierarchy 
+  manager if isIncremental == 0. If isIncremental == 1, hmgr should
+  be set to the current manager and will be updated by this function call.
+  If isCanonical == 1, then all the tables in each model will be 
+  canonicalized with Tbl_TableCanonicalize(). If isVerbose == 1,
+  all the unused variables are listed for each model while if isVerbose == 0,
+  all the models that have an unused variable are simply listed. 
+  These messages can be referred to by error_string() after the call.
+  Returns NIL(Hrc_Manager_t) if failure.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Hrc_Manager_t *
+Io_BlifMvRead(
+  FILE *fp, 
+  Hrc_Manager_t *hmgr, 
+  boolean isCanonical,
+  boolean isIncremental,
+  boolean isVerbose)
+{
+  Hrc_Node_t *root;
+  static Hrc_Manager_t *newHmgr;
+
+  if (isIncremental == 0){
+    newHmgr = Hrc_ManagerAlloc(); 
+  }
+  else { /* isIncremental == 1 */
+    if (Hrc_ManagerReadCurrentNode(hmgr) == NIL(Hrc_Node_t)){
+      (void)fprintf(vis_stderr,"No hierarchy has been created. Cannot do inremental read-in.\n");
+      return NIL(Hrc_Manager_t);
+    }
+    newHmgr = hmgr;
+  }
+
+  if (setjmp(env)){
+    if (isIncremental == 0){
+      Hrc_ManagerFree(newHmgr);
+    }
+    else {
+      int i;
+      /* free all the new models defined in an incremental file */
+      for (i=0; i < array_n(globalNewModelArray); i++){
+        Hrc_ModelDelete(hmgr,Hrc_ModelReadName(array_fetch(Hrc_Model_t *,globalNewModelArray,i)));
+      }
+    }
+    _IoGlobalVariablesFree();
+    return NIL(Hrc_Manager_t);
+  }
+  else {
+    _IoGlobalVariablesInitialize();
+    if (isIncremental == 0){
+      globalYaccHmgr = newHmgr;
+    }
+    else {
+      globalYaccHmgr = hmgr;
+    }
+#ifdef IODEBUG
+    IoYydebug = 1;
+#endif /* IODEBUG */
+    IoYyin = fp;
+    IoYyrestart(IoYyin);
+    if (IoYyparse() == 1){
+      IoError();
+    }
+
+    /* globalNewModelArray contains all the models defined in the previous
+    IoYyparse(). If isIncremental==0, then they are simply all the models.
+    If isIncremental==1, then they are new models defined in the file. */
+
+    if (IoNetworkTestConsistency(newHmgr,globalNewModelArray,globalParserSubcktInfo,globalParserResetInfo,isVerbose) == 0){
+      IoError();
+    }
+
+    if (globalRootModel == NIL(Hrc_Model_t)){
+      globalRootModel = globalFirstModel;
+      globalRootInstanceName = util_strsav(Hrc_ModelReadName(globalRootModel));
+    }
+    else if (globalRootInstanceName == NIL(char)){
+      globalRootInstanceName = util_strsav(Hrc_ModelReadName(globalRootModel));
+    }
+
+    if (isCanonical == 1){
+      _IoManagerCanonicalize(newHmgr);
+    }
+
+    root = Hrc_ModelCreateHierarchy(newHmgr,globalRootModel,globalRootInstanceName);
+    FREE(globalRootInstanceName);
+
+    if (isIncremental == 0){
+      Hrc_ManagerSetRootNode(newHmgr,root);
+      Hrc_ManagerSetCurrentNode(newHmgr,root);
+      _IoGlobalVariablesFree();
+      return newHmgr;
+    }    
+    else { /* isIncremental == 1, note that newHmgr == hmgr  */
+      if (_IoNodeTestCompatibility(hmgr,Hrc_ManagerReadCurrentNode(hmgr),root) == 0){
+        int i;
+        (void)fprintf(vis_stderr,"The blif-mv file is not compatible with the existing hierarchy.\n");
+        Hrc_TreeReplace(NIL(Hrc_Node_t),root);
+        /* free all the new models defined in an incremental file */
+        for (i=0; i < array_n(globalNewModelArray); i++){
+          Hrc_ModelDelete(hmgr,Hrc_ModelReadName(array_fetch(Hrc_Model_t *,globalNewModelArray,i)));
+        }
+        _IoGlobalVariablesFree();
+        return NIL(Hrc_Manager_t);
+      }
+      Hrc_TreeReplace(Hrc_ManagerReadCurrentNode(hmgr),root);
+      Hrc_ManagerSetCurrentNode(hmgr,root);
+      _IoGlobalVariablesFree();
+      return hmgr;
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Reads in a blif file.]
+
+  Description [Reads in a blif file specified by its file name. Returns 
+  a pointer to a new hierarchy manager. All the error/warning messages
+  obtained while  parsing the file are stored in error_string(). 
+  isVerbose should be set either to one or to zero depending on how much 
+  detailed error/warning information is needed. Returns NIL(Hrc_Manager_t) 
+  if failure.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Hrc_Manager_t *
+Io_BlifRead(
+  char *fileName,
+  boolean isVerbose)
+{
+  FILE *fp;
+#if HAVE_MKSTEMP && HAVE_CLOSE
+  int  fd;
+#else
+  char buffer[512];
+#endif
+  char *realFileName, *blifMvFileName, *visDirectoryName;
+  char command[512];
+  Hrc_Manager_t *hmgr;
+  
+  fp = Cmd_FileOpen(fileName, "r", &realFileName, /* silent */ 1);
+
+  if (fp == NIL(FILE)){
+    FREE(realFileName);
+    (void)fprintf(vis_stderr,"File %s is not found.\n", fileName);
+    return NIL(Hrc_Manager_t);
+  }
+  if (fp != stdin){
+    (void)fclose(fp);
+  }
+
+#if HAVE_MKSTEMP && HAVE_CLOSE
+  blifMvFileName = util_strsav("/tmp/vis.XXXXXX");
+  fd = mkstemp(blifMvFileName);
+  if (fd == -1){
+#else
+  blifMvFileName = util_strsav(tmpnam(buffer));
+  if (blifMvFileName == NIL(char)){
+#endif
+    FREE(realFileName);
+    (void)fprintf(vis_stderr,"Could not create temporary file. ");
+    (void)fprintf(vis_stderr,"Clean up /tmp an try again.\n");
+    return NIL(Hrc_Manager_t);
+  }
+#if HAVE_MKSTEMP && HAVE_CLOSE
+  close(fd);
+#endif
+  /* Invoking an awk script */
+  visDirectoryName = Vm_VisObtainLibrary();
+  (void)sprintf(command,"sed 's/^\\./@/g' %s | sed 's/\\./$/g' | sed 's/^@/\\./g' | sed 's/{/</g' | sed 's/}/>/g'| sed 's/(/<</g' | sed 's/)/>>/g'| %s -f %s/ioBlifToMv.nawk > %s", realFileName, NAWK, visDirectoryName, blifMvFileName);
+  /* the following is missing two new sed processings 
+  (void)sprintf(command,"sed 's/^\\./@/g' %s | sed 's/\\./$/g' | sed 's/^@/\\./g' | sed 's/{/</g' | sed 's/}/>/g'| %s -f %s/ioBlifToMv.nawk > %s", realFileName, NAWK, visDirectoryName, blifMvFileName);
+  */
+  (void)system(command);
+  FREE(visDirectoryName);
+  FREE(realFileName);
+
+  error_init();
+
+  fp = Cmd_FileOpen(blifMvFileName, "r", NIL(char *), 1);
+  assert(fp != NIL(FILE));
+  hmgr = Io_BlifMvRead(fp,NIL(Hrc_Manager_t),0,0,isVerbose);
+  fclose(fp);
+#if HAVE_UNLINK
+  unlink(blifMvFileName);
+#endif
+  FREE(blifMvFileName);
+  return hmgr;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Jumps out of an error state.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+IoError(void)
+{
+  longjmp(env,1);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initilizes all the global variables used in the parser.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+_IoGlobalVariablesInitialize(void)
+{
+  globalLineNumber = 1;
+  globalModel = NIL(Hrc_Model_t);
+  globalHnode = NIL(Hrc_Node_t);
+  globalFirstModel = NIL(Hrc_Model_t); /* set once */
+  globalRootModel = NIL(Hrc_Model_t); /* set once */
+  globalRootInstanceName = NIL(char); /* set once */
+  globalMvNameArray = NIL(array_t);
+  globalSymValueArray = NIL(array_t);
+  globalTableInputArray = NIL(array_t);
+  globalTableOutputArray = NIL(array_t);
+  globalTableDefaultArray = NIL(array_t);
+  globalTableSymCubeArray = NIL(array_t);
+  globalFormalNameArray = NIL(array_t);
+  globalActualNameArray = NIL(array_t);
+
+  globalSubcktArray = NIL(array_t);
+  globalResetArray = NIL(array_t);
+
+  globalNewModelArray = array_alloc(Hrc_Model_t *,0);
+
+  globalCurrentStackDepth = 0;
+
+  /* a hash table from a model name to an array of resets/subcircuits in the model */
+  globalParserResetInfo = st_init_table(st_ptrcmp,st_ptrhash);
+  globalParserSubcktInfo = st_init_table(st_ptrcmp,st_ptrhash);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees all the global data structures used in the parser.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+_IoGlobalVariablesFree(void)
+{
+   array_free(globalNewModelArray);
+   _IoGlobalResetInfoFree(); 
+   _IoGlobalSubcktInfoFree();
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the subckt information only used by the parser.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+_IoGlobalSubcktInfoFree(void)
+{
+  st_generator *gen;
+  char *key, *val;
+
+  st_foreach_item(globalParserSubcktInfo,gen,&key,&val){
+    if ((array_t *)val != NIL(array_t)){
+      _IoSubcktArrayFree((array_t *)val);
+    }
+  }
+  st_free_table(globalParserSubcktInfo);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees an array of the subckt data structure only used by the parser.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+_IoSubcktArrayFree(array_t *array)
+{
+  int i;
+
+  for (i=0; i < array_n(array); i++){
+    _IoSubcktFree(array_fetch(IoSubckt_t *,array,i));
+  }
+  array_free(array);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the subckt data structure used by the parser.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+_IoSubcktFree(IoSubckt_t *subckt)
+{
+  FREE(subckt->modelName);
+  FREE(subckt->instanceName);
+  IoStringArrayFree(subckt->formalNameArray);
+  IoStringArrayFree(subckt->actualNameArray);
+  FREE(subckt);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the reset data structure used only by the parser.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+_IoGlobalResetInfoFree(void)
+{
+  st_generator *gen;
+  char *key, *val;
+  int i;
+  Tbl_Table_t *resetTable;
+
+  st_foreach_item(globalParserResetInfo,gen,&key,&val){
+    if ((array_t *)val != NIL(array_t)){
+      for (i=0; i < array_n((array_t *)val); i++){
+        resetTable = array_fetch(Tbl_Table_t *,(array_t *)val,i);
+        if (resetTable != NIL(Tbl_Table_t)){
+          Tbl_TableFree(resetTable);
+        }
+      }
+      array_free((array_t *)val);
+    }
+  }
+  st_free_table(globalParserResetInfo);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks if two hnodes are compatible with respect to their i/o
+  interface.]
+
+  Description [Checks if two hnodes are compatible with respect to their i/o
+  interface. Used in incremental read-in.]
+
+  SideEffects []
+
+  SeeAlso     [_IoNodeTestCompatibilityAux]
+
+******************************************************************************/
+boolean
+_IoNodeTestCompatibility(
+  Hrc_Manager_t *hmgr,
+  Hrc_Node_t *hnode1,
+  Hrc_Node_t *hnode2)
+{
+  return (_IoNodeTestCompatibilityAux(hmgr,hnode1,hnode2,0)
+          && _IoNodeTestCompatibilityAux(hmgr,hnode1,hnode2,1));
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Checks if two hnodes are compatible with respect to their input
+  or output interface depending on the last boolean flag.]
+
+  Description [Checks if two hnodes are compatible with respect to their input
+  or output interface depending on the last boolean flag. 0 for input and 1
+  for output.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static boolean
+_IoNodeTestCompatibilityAux(
+  Hrc_Manager_t *hmgr,
+  Hrc_Node_t *hnode1,
+  Hrc_Node_t *hnode2,
+  boolean mode)
+{
+  int i, n;
+  array_t *formalVars1, *formalVars2;
+  Var_Variable_t *var1, *var2;
+
+  if (mode == 0){
+    formalVars1 = Hrc_NodeReadFormalInputs(hnode1);
+    formalVars2 = Hrc_NodeReadFormalInputs(hnode2);
+  }
+  else {
+    formalVars1 = Hrc_NodeReadFormalOutputs(hnode1);
+    formalVars2 = Hrc_NodeReadFormalOutputs(hnode2);
+  }
+  if ((n = array_n(formalVars1)) != array_n(formalVars2)){
+    error_append("Two hnodes have different number of formal ");
+    if (mode == 0){
+      error_append("inputs.\n");
+    }
+    else {
+      error_append("outputs.\n");
+    }
+    return 0;
+  } 
+  for (i=0; i < n; i++){
+    var1 = array_fetch(Var_Variable_t *,formalVars1,i);
+    var2 = array_fetch(Var_Variable_t *,formalVars2,i);
+    if (strcmp(Var_VariableReadName(var1),Var_VariableReadName(var2)) != 0){
+      error_append("Two hnodes have different ports, ");
+      error_append(Var_VariableReadName(var1));
+      error_append(" and ");
+      error_append(Var_VariableReadName(var2));
+      error_append("\n");
+      return 0; 
+    }
+    if (Var_VariablesTestHaveSameDomain(var1,var2) == 0){
+      error_append("Two hnodes have ports defined over different domains, ");
+      error_append(Var_VariableReadName(var1));
+      error_append(" and ");
+      error_append(Var_VariableReadName(var2));
+      error_append("\n");
+      return 0; 
+    }
+  }
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Canonicalizes all the tables in a given manager using
+  Tbl_TableCanonicalize().]
+
+  SideEffects [The original tables will be overwritten.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+_IoManagerCanonicalize(
+  Hrc_Manager_t *hmgr)
+{
+  int i;
+  Hrc_Model_t *model;
+  Hrc_Node_t *node;
+  Tbl_Table_t *table;
+  st_generator *gen, *gen2;
+  char *modelName, *latchName;
+  Hrc_Latch_t *latch;
+
+  Hrc_ManagerForEachModel(hmgr,gen,modelName,model){
+    node = Hrc_ModelReadMasterNode(model);
+    Hrc_NodeForEachNameTable(node,i,table){
+      Tbl_TableCanonicalize(table);
+    }
+    Hrc_NodeForEachLatch(node,gen2,latchName,latch){
+      Tbl_TableCanonicalize(Hrc_LatchReadResetTable(latch));
+    }
+  }
+}
Index: vis_dev/vis-2.3/src/io/ioTable.c
===================================================================
--- vis_dev/vis-2.3/src/io/ioTable.c	(revision 14)
+++ vis_dev/vis-2.3/src/io/ioTable.c	(revision 14)
@@ -0,0 +1,554 @@
+/**CFile***********************************************************************
+
+  FileName    [ioTable.c]
+
+  PackageName [io]
+
+  Synopsis    [Routines for generating the table data structure from
+               textual information. Used in the parser.]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [Yuji Kukimoto, Rajeev Ranjan, Huey-Yih Wang]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ioInt.h"
+
+static char rcsid[] UNUSED = "$Id: ioTable.c,v 1.8 2002/09/08 23:40:00 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void _IoSymValueFree(IoSymValue_t *value);
+static int _IoSymCubeInsertInTable(Tbl_Table_t *table, array_t *symCube, int numIp, int numOp);
+static int _IoDefaultSymCubeInsertInTable(Tbl_Table_t *table, array_t *symCube, int numOp);
+static Tbl_Entry_t * _IoSymValueTransformToEntry(IoSymValue_t *value, Var_Variable_t *var, Tbl_Table_t *table);
+static int VariableReadIndex(Var_Variable_t *var, char *value);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Transforms table information stored in a special data structure
+  IoPTable_t used by the parser to the table data structure.]
+
+  Description [Transforms table information stored in a special data structure
+  IoPTable_t used by the parser to the table data structure. The second and 
+  the third arguments and the model and the corresponding master hnode
+  being parsed.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+Tbl_Table_t *
+IoPTableTransformToTable(
+  Hrc_Model_t *model, 
+  Hrc_Node_t *hnode, 
+  IoPTable_t *pTable)
+{
+  int i, numIo, numIp, numOp;
+  char *input, *output;
+  array_t *symCubes, *symCube;
+  Tbl_Table_t *table;
+  Var_Variable_t *var;
+
+  symCubes = pTable->cubes;  
+
+  /* if neither symCubes nor default is set, the table is illegal */
+  if (symCubes == NIL(array_t) && pTable->defaultOutput == NIL(array_t)){
+    error_append("Error: Table ");
+    error_append(array_fetch(char *,pTable->outputs,0));
+    error_append(" has neither relation nor default.\n");
+    return NIL(Tbl_Table_t);
+  }
+
+  /* partial check to see if symCubes is properly set up */
+  numIp = array_n(pTable->inputs);
+  numOp = array_n(pTable->outputs);
+  numIo = numIp + numOp;
+  if (symCubes != NIL(array_t)){
+    for (i=0; i < array_n(symCubes); i++){
+      symCube = array_fetch(array_t *,symCubes,i);
+      if (numIo != array_n(symCube)){
+        error_append("Error: The number of columns in the table where output ");
+        error_append(array_fetch(char *,pTable->outputs,0));
+        error_append(" is defined is not equal to the number of input/output variables.\n");
+        return NIL(Tbl_Table_t);
+      }
+    }
+  }
+
+  table = Tbl_TableAlloc();
+
+  /* add input columns to the table */
+  for (i=0; i < array_n(pTable->inputs); i++){
+    input = array_fetch(char *,pTable->inputs,i);
+    /* the following if should not fail due to the spec of IoVariableFindOrAllocByName() -- To be fixed */
+    if ((var = IoVariableFindOrAllocByName(hnode,input)) == NIL(Var_Variable_t)){
+      return NIL(Tbl_Table_t);
+    }
+    /* the following if should not fail due to the spec of Tbl_TableAddColumn() -- To be fixed */
+    if (Tbl_TableAddColumn(table,var,0) == 0){
+      return NIL(Tbl_Table_t);
+    }
+  }  
+  /* add output columns to the table */
+  for (i=0; i < array_n(pTable->outputs); i++){
+    output = array_fetch(char *,pTable->outputs,i);
+    /* the following if should not fail due to the spec of IoVariableFindOrAllocByName() -- To be fixed */
+    if ((var = IoVariableFindOrAllocByName(hnode,output)) == NIL(Var_Variable_t)){
+      return NIL(Tbl_Table_t);
+    }
+    /* the following if should not fail due to the spec of Tbl_TableAddColumn() -- To be fixed */
+    if (Tbl_TableAddColumn(table,var,1) == 0){
+      return NIL(Tbl_Table_t);
+    }
+  } 
+
+  /* insert a cube one by one to the table */
+  if (symCubes != NIL(array_t)){
+    for (i=0; i < array_n(symCubes); i++){
+      symCube = array_fetch(array_t *,symCubes,i);
+      if (_IoSymCubeInsertInTable(table, symCube, numIp, numOp) == 0){
+        Tbl_TableFree(table);
+        return NIL(Tbl_Table_t);
+      }
+    }
+  }
+
+  /* check if the default and the output has the same number of variables */
+  if (pTable->defaultOutput != NIL(array_t) && array_n(pTable->outputs) != array_n(pTable->defaultOutput)){
+    error_append("Error: Default is not compatible with the number of outputs in output of ");
+    error_append(array_fetch(char *,pTable->outputs,0));
+    error_append("\n");
+    Tbl_TableFree(table);
+    return NIL(Tbl_Table_t);
+  }
+  /* insert the default cube to the table */
+  if (_IoDefaultSymCubeInsertInTable(table, pTable->defaultOutput, numOp) == 0) {
+    Tbl_TableFree(table);
+    return NIL(Tbl_Table_t);
+  }
+
+  return table;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates a IoSymValue_t.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+IoSymValue_t *
+IoSymValueAlloc(void)
+{
+  return ALLOC(IoSymValue_t,1);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees an array of the IoSymValue_t data structure.]
+
+  Description [Frees an array of the IoSymValue_t data structure.
+  All the elements of the array are also freed.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void
+IoSymValueArrayFree(array_t *valueArray)
+{
+  int i;
+
+  for (i=0; i < array_n(valueArray); i++){
+    _IoSymValueFree(array_fetch(IoSymValue_t *,valueArray,i));
+  }
+  array_free(valueArray);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the IoSymValue_t data structure.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+static void
+_IoSymValueFree(IoSymValue_t *value)
+{
+  IoSymValueType flag;
+
+  /* if flag == IoUniverse_c, we have no extra work to do */
+  if ((flag = value->flag) == IoLeaf_c ){
+    FREE(value->left);
+  }
+  if (flag == IoRange_c){
+    FREE(value->left);
+    FREE(value->right);
+  }
+  if (flag == IoComplement_c){
+    _IoSymValueFree(value->left);
+  }
+  if (flag == IoList_c){
+    int i;
+    IoSymValue_t *valueTmp;
+    for (i=0; i < array_n(value->elements); i++){
+      valueTmp = array_fetch(IoSymValue_t *,value->elements,i);
+      _IoSymValueFree(valueTmp);
+    } 
+    array_free(value->elements);
+  }
+  if (flag == IoAssign_c){
+    FREE(value->left);
+  }
+  FREE(value); 
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Given a symbolic cube in textual format and a table, updates
+  the table by adding the cube.]
+
+  Description [Given a symbolic cube in textual format and a table, updates
+  the table by adding the cube. The arguments are a pointer to the working 
+  table, a cube to be inserted in textual format, the number of inputs of 
+  the table, and the number of outputs of the table.]
+
+  SideEffects [The new cube represented in symCube is inserted in the table.]
+
+  SeeAlso     []
+
+******************************************************************************/
+
+static int
+_IoSymCubeInsertInTable(
+  Tbl_Table_t *table, 
+  array_t *symCube, 
+  int numIp, 
+  int numOp)
+{
+  int index, i;
+  IoSymValue_t *symValue;
+  Tbl_Entry_t *entry;
+
+  /* get a new row for the cube */
+  index = Tbl_TableAddRow(table);
+
+  for (i=0; i < numIp; i++){
+    symValue = array_fetch(IoSymValue_t *,symCube,i);
+    entry = _IoSymValueTransformToEntry(symValue,Tbl_TableReadIndexVar(table,i,0),table);
+    if (entry == NIL(Tbl_Entry_t))
+      return 0;
+    Tbl_TableSetEntry(table,entry,index,i,0); 
+  }
+  for (i=0; i < numOp; i++){
+    symValue = array_fetch(IoSymValue_t *,symCube, numIp+i);
+    entry = _IoSymValueTransformToEntry(symValue,Tbl_TableReadIndexVar(table,i,1),table);
+    if (entry == NIL(Tbl_Entry_t))
+      return 0;
+    Tbl_TableSetEntry(table,entry,index,i,1); 
+  }
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Given a default symbolic cube in textual format and a table, 
+  updates the table by adding the cube.]
+
+  Description []
+
+  SideEffects [The default cube is added to the table.]
+
+  SeeAlso     []
+
+******************************************************************************/
+
+static int
+_IoDefaultSymCubeInsertInTable(
+  Tbl_Table_t *table, 
+  array_t *symCube, 
+  int numOp)
+{
+  int i;
+  IoSymValue_t *symValue;
+  Tbl_Entry_t *entry;
+
+  /* no defaults is asserted. */
+  if (symCube == NIL(array_t)){
+    return 1;
+  }
+
+  for (i=0; i < array_n(symCube); i++){
+    symValue = array_fetch(IoSymValue_t *,symCube, i);
+    entry = _IoSymValueTransformToEntry(symValue,Tbl_TableReadIndexVar(table,i,1),table);
+    if (entry == NIL(Tbl_Entry_t))
+      return 0;
+    Tbl_TableDefaultSetEntry(table,entry,i);
+  }
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Generates a set of ranges used in the table data structure
+               from textual representation of symbolic values.]
+
+  Description [Generates a set of ranges used in the table data structure
+  from textual representation of symbolic values. Symbolic values are 
+  representations which can be put into an entry of a table, i.e. 
+  a symbolic element in a row. The arguments of the function are
+  a symbolic value in IoSymValue_t *, a pointer to the corresponding variable,
+  and the table we are working on. The last argument is needed to 
+  resolve = constructs.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+static Tbl_Entry_t *
+_IoSymValueTransformToEntry(
+  IoSymValue_t *value, 
+  Var_Variable_t *var,
+  Tbl_Table_t *table)
+{
+  IoSymValueType flag;
+  Tbl_Entry_t *entry;
+
+  if ((flag = value->flag) == IoLeaf_c){
+    int index;
+    index = VariableReadIndex(var,(char *)(value->left));
+    if (index == -1){
+      return NIL(Tbl_Entry_t);
+    }
+    entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+    Tbl_EntrySetValue(entry,index,index);
+    return entry;
+  }
+  if (flag == IoUniverse_c){
+    int range;
+    range = Var_VariableReadNumValues(var);
+    entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+    Tbl_EntrySetValue(entry,0,range-1);
+    return entry;
+  }
+  if (flag == IoRange_c){
+    int indexFrom, indexTo;
+    indexFrom = VariableReadIndex(var,(char *)(value->left));
+    indexTo = VariableReadIndex(var,(char *)(value->right));
+    if (indexFrom == -1 || indexTo == -1){
+      return NIL(Tbl_Entry_t);
+    }
+    entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+    Tbl_EntrySetValue(entry,indexFrom,indexTo);
+    return entry;
+  }
+  if (flag == IoComplement_c){
+    entry = _IoSymValueTransformToEntry(value->left,var,table);
+    if (entry == NIL(Tbl_Entry_t)){
+      return NIL(Tbl_Entry_t);
+    }
+    Tbl_EntryComplement(entry,0,Var_VariableReadNumValues(var)-1);
+    return entry;
+  }
+  if (flag == IoList_c){
+    int i;
+    IoSymValue_t *valueTmp;
+    Tbl_Entry_t *entryTmp, *entryUnion;
+
+    entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+    for (i=0; i < array_n(value->elements); i++){
+      valueTmp = array_fetch(IoSymValue_t *,value->elements,i);
+      entryTmp = _IoSymValueTransformToEntry(valueTmp,var,table);
+      if (entryTmp == NIL(Tbl_Entry_t)){
+        Tbl_EntryFree(entry);
+        return NIL(Tbl_Entry_t);
+      }
+      entryUnion = Tbl_EntryMerge(entry,entryTmp);
+      Tbl_EntryFree(entry);
+      Tbl_EntryFree(entryTmp);
+      entry = entryUnion;
+    } 
+    return entry;
+  }
+  if (flag == IoAssign_c){
+    int i;
+    Var_Variable_t *varCandidate = NIL(Var_Variable_t);
+
+    entry = Tbl_EntryAlloc(Tbl_EntryEqual_c);
+    for (i=0; i < Tbl_TableReadNumInputs(table); i++){
+      varCandidate = Tbl_TableReadIndexVar(table,i,0);
+      if (strcmp(Var_VariableReadName(varCandidate),(char *)value->left) == 0){
+      /* found the variable referred in = construct as an input of the table */
+        break;
+      }
+    }
+    /* the following if-clause is only true when the above for-loop cannot
+    find the variable referred in = construct */
+    if (i == Tbl_TableReadNumInputs(table)){
+      error_append("Variable ");
+      error_append((char *)value->left);
+      error_append(" is not an input of the table where ");
+      error_append(Var_VariableReadName(var));
+      error_append(" is an output. It cannot be used as an argument of = construct.\n");
+      Tbl_EntryFree(entry);
+      return NIL(Tbl_Entry_t);
+    }
+    /* check if the two variables connected with = construct have the same domain */
+    if (Var_VariablesTestHaveSameDomain(var,varCandidate) == 0){
+      error_append("Variables ");
+      error_append((char *)value->left);
+      error_append(" and ");
+      error_append(Var_VariableReadName(var));
+      error_append(" have different domains. Cannot be used in = construct.\n");
+      Tbl_EntryFree(entry);
+      return NIL(Tbl_Entry_t);
+    }
+    Tbl_EntrySetEqual(entry,i);
+    return entry;
+  }
+  else {
+    return NIL(Tbl_Entry_t);
+  }
+}
+
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the integer index given a value.]
+
+  Description [Returns the integer index given a value. The value is either
+  an integer or a symbolic name. If the latter is the case,
+  it is transformed into the corresponding integer. If
+  a given symbolic name is not valid, the routine returns -1.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+VariableReadIndex(
+  Var_Variable_t *var,
+  char *value)
+{
+  int integer;
+  if (Var_VariableTestIsEnumerative(var) == 1){
+    integer = IoAtoi(value);
+    if (integer == -1 || integer >= Var_VariableReadNumValues(var)){
+      error_append("Value ");
+      error_append(value);
+      error_append(" is not a proper value for variable ");
+      error_append(Var_VariableReadName(var));
+      error_append("\n");
+      return -1;
+    }
+    return integer;
+  }
+  /* var is now a symbolic variable */
+  if ((integer = Var_VariableReadIndexFromSymbolicValue(var,value)) == -1){
+    error_append("Value ");
+    error_append(value);
+    error_append(" is not a proper value for variable ");
+    error_append(Var_VariableReadName(var));
+    error_append("\n");
+    return -1;
+  }
+  return integer;
+}
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/io/ioWriteBlif.c
===================================================================
--- vis_dev/vis-2.3/src/io/ioWriteBlif.c	(revision 14)
+++ vis_dev/vis-2.3/src/io/ioWriteBlif.c	(revision 14)
@@ -0,0 +1,1557 @@
+ /**CFile***********************************************************************
+
+  FileName    [ ioWriteBlif.c ] 
+
+  PackageName [ io ]
+
+  Synopsis    [ This file contains blifmv -> blif write routines ]
+
+  Description [ Routines for (determinizing, encoding and) writing a blifmv table
+                into a blif description are provided. The encoding of multivalued 
+                vars is written to separate files. ]
+
+  SeeAlso     [ ioReadBlifmv.c, ioWriteBlifIo.c, IoWriteBlifUtil.c]
+
+  Author      [ Sunil P. Khatri ]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ioInt.h"
+
+static char rcsid[] UNUSED = "$Id: ioWriteBlif.c,v 1.14 2005/04/29 14:23:29 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+#define MAX_NUMBER_BDD_VARS 500
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int _IoTableWriteBlif(Io_Encoding_Type_t encodingType, Hrc_Node_t *hnode, Tbl_Table_t *origBlifmvTable, st_table *blifInputsStTable, FILE *fp, FILE *encFp, int verbosity);
+static int _IoMakeInitialEncodings(IoBlifInfo_t *blifInfo, Hrc_Node_t *hnode);
+static void _IoDeterminizeEncodeOutputPart(IoBlifInfo_t *blifInfo, st_table *blifInputsStTable);
+static void _IoDeterminizeEncodeRows(IoBlifInfo_t *blifInfo, st_table *blifInputsStTable);
+static void _IoMakeDcTables(IoBlifInfo_t *blifInfo);
+static void _IoMakeBinTable(IoBlifInfo_t *blifInfo);
+static int _IoCheckHnodeTreeIsBooleanAndDeterministic(mdd_manager **mddMgr, Hrc_Node_t *hnode, st_table *modelTable, boolean *pSymVarsPresent, int verbosity);
+static int _IoCheckHnodeVarsAreBoolean(Hrc_Node_t *hnode, boolean *pSymVarsPresent);
+static int _IoCheckHnodeLatchResetIsConstant(Hrc_Node_t *hnode);
+static int _IoCheckHnodeTablesAreDeterministic(mdd_manager **mddMgr, Hrc_Node_t *hnode);
+static void _MddManagerResetIfNecessary(mdd_manager **mddMgr);
+static void _IoHnodeWriteBlifRecursively(Io_Encoding_Type_t encodingType, Hrc_Node_t *hnode, st_table *modelTable, FILE *fp, FILE *encFp, int verbosity);
+static int _IoHnodeWriteBlifRecursivelyStep(Io_Encoding_Type_t encodingType, Hrc_Node_t *hnode, FILE *fp, FILE *encFp, int verbosity);
+static int _IoCheckHnodeIsBooleanAndDeterministic(mdd_manager **mddMgr, Hrc_Node_t *hnode, boolean *pSymVarsPresent);
+static int _IoCheckPseudoinputIsPO(Tbl_Table_t *table);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function***********************************************************
+
+
+  Synopsis	[ Recursively write out the entire hierarchy below the current 
+                  hnode to a blif file. ]
+
+  Description	[ This routine recursively writes out the entire hierarchy below
+                  the given hnode to a named blif file. This sub-hierarchy must 
+                  comply with the following restrictions. First all tables in it
+                  should be deterministic. Secondly, all variables should be 
+                  binary. The function returns a 0 upon success, 1 in case of 
+                  failure. Upon failure, appropriate error messages are printed 
+                  to stderr. The function is passed an enumerated type called 
+                  encodingType, only SIMPLE is supported. Refer to the description 
+                  of Io_HnodeWriteBlif for more information on this. The hnode 
+                  is passed, along with the file pointer fp, for the file into which 
+                  the resulting blif network is to be written. A verbosity flag 
+                  (valid values are between 0 and 2) causes intermediate information 
+		  to be printed to stderr.
+		  ]
+
+  SideEffects	[ ]
+
+  SeeAlso	[  ]
+**********************************************************************/
+int
+Io_HnodeWriteBlifTotal(
+    Io_Encoding_Type_t encodingType,
+    Hrc_Node_t *hnode, 
+    FILE *fp, 
+    int verbosity)
+{
+  st_table *modelTable;
+  Hrc_Manager_t *manager;
+  mdd_manager *mddMgr;
+  FILE *encFp;
+  boolean symVarsPresent;
+  
+  manager = Hrc_NodeReadManager(hnode);
+  modelTable = st_init_table(st_ptrcmp, st_ptrhash);
+  mddMgr = mdd_init_empty();
+  bdd_dynamic_reordering(mddMgr, BDD_REORDER_SIFT, BDD_REORDER_VERBOSITY_DEFAULT);
+  symVarsPresent = FALSE;
+
+  /* check that the node and all its children are boolean and deterministic. */
+  if(_IoCheckHnodeTreeIsBooleanAndDeterministic(&mddMgr, hnode, modelTable, &symVarsPresent, verbosity)){
+    mdd_quit(mddMgr);
+    st_free_table(modelTable);
+    return 1;
+  }
+  if(verbosity > 0){
+    fprintf(vis_stderr, "Done with hierarcy checks\n");
+  }
+  
+  if(symVarsPresent == TRUE){
+    fprintf(vis_stderr, "Warning - some variables in the hierarchy are symbolic\n");
+  }
+  
+  st_free_table(modelTable);
+  modelTable = st_init_table(st_ptrcmp, st_ptrhash);  
+  encFp = Cmd_FileOpen("/dev/null", "w", NIL(char *), 1);
+
+  _IoHnodeWriteBlifRecursively(encodingType, hnode, modelTable, fp, encFp, verbosity);
+  Hrc_ManagerSetCurrentNode(manager, hnode);
+
+  st_free_table(modelTable);
+  mdd_quit(mddMgr);
+  return 0;
+}
+    
+
+/**Function***********************************************************
+
+
+  Synopsis	[ Determinize, encode and write all blifmv tables in a hnode 
+                  to a blif file. Also writes all encoding information to a 
+		  encoding file. This encoding file can later be read in, along 
+		  with the blif file (potentially after optimization in SIS), 
+		  into that hnode (see "read_blif -i" for details).  Currently, only the 
+		  combinational part of the hnode is written to the blif file.]
+
+  Description	[ This routine determinizes, encodes and writes all blifmv tables
+                  in a hnode to a named blif file.
+		  It also writes encoding information to another named file.
+		  This encoding file must be used while reading back the (optimized) 
+		  blif file into blifmv. 
+		  The function returns a 0 upon success, 1 in case of failure. It 
+		  should be supplied a Io_Encoding_Type_t. Currently only SIMPLE is 
+		  supported. Under this scheme, binary encoding is done on the 
+		  multi-valued variables, and the binary variable with smallest length
+		  is chosen at any step of the  determinization process. Other parameters 
+		  to this function  include a Hrc_Node_t *, and file pointers for the 
+		  blif output file and the encoding file. The default blif file is 
+		  stdout, and the default encoding file is <model>.enc. A verbosity flag 
+		  (valid values are between 0 and 2) print intermediate information to 
+		  stdout.
+		  ]
+
+  SideEffects	[ ]
+
+  SeeAlso	[  ]
+  **********************************************************************/
+int
+Io_HnodeWriteBlif(
+    Io_Encoding_Type_t encodingType,
+    Hrc_Node_t *hnode,
+    FILE *fp,
+    FILE *encFp,
+    int verbosity,
+    int combinationalOnly,
+    int makeLatchIOsPOs)
+{
+    Tbl_Table_t *table, *singleOutputTable;
+    Tbl_Entry_t *entry;
+    int i, j, k, numVal, numInputs, numOutputs;
+    Var_Variable_t *var, *actualVar, *outputVar;
+    char *name, *instanceName, *modelName, *newModelName;
+    st_generator *gen;
+    st_table *blifInputsStTable, *blifOutputsStTable, *printedMvsStTable;
+    st_table *encOutputsStTable, *encInputsStTable;
+    Hrc_Node_t *subcktHnode;
+    Hrc_Model_t *model, *subcktModel;
+    Hrc_Subckt_t *subckt;
+    Hrc_Manager_t *manager;
+    array_t *subcktActualInputVars, *subcktActualOutputVars;
+   
+
+    Hrc_NodeForEachNameTable(hnode, i, table){
+      if(_IoCheckPseudoinputIsPO(table)){
+	fprintf(stdout, "Hnode contains a pseudoinput which is also a primary output - quitting\n");
+	return 1;
+      }
+      for(j = 0; j < Tbl_TableReadNumOutputs(table); j++){
+	entry = Tbl_TableDefaultReadEntry(table, j);
+	if(entry != NIL(Tbl_Entry_t)){
+	  if(Tbl_EntryReadType(entry) == Tbl_EntryNormal_c){
+	    if(Tbl_EntryReadNumValues(entry) > 1){
+	      outputVar = Tbl_TableReadIndexVar(table, j, 1);
+	      (void)fprintf(stdout, "The table with %s as an output has non-singleton default values - quitting\n", Var_VariableReadName(outputVar));
+	      return 1;
+	    }
+	  }
+	  else{
+	    var = Tbl_EntryReadVar(table, entry);
+	    k = Tbl_TableReadVarIndex(table, var, 1);
+	    if(k<0){
+	      outputVar = Tbl_TableReadIndexVar(table, j, 1);	      
+	      (void)fprintf(stdout, "Output %s has a default value that refers to an input variable - quitting\n", Var_VariableReadName(outputVar));
+	      return 1;
+	    }
+	  }
+	}
+      }
+    }
+
+    printedMvsStTable = st_init_table(strcmp, st_strhash);
+
+    if(!(combinationalOnly || makeLatchIOsPOs)){
+      fprintf(encFp,"# This encoding file and the blif file that was written out with it cannot\n");           
+      fprintf(encFp,"# currently be read back into VIS. If you would like to read the blif and\n");           
+      fprintf(encFp,"# encoding files back into VIS, then use the 'write_blif -l' or\n");
+      fprintf(encFp,"#'write_blif -c' options.\n");
+    }
+
+  /* .model */
+    modelName = Hrc_NodeReadModelName(hnode);
+    manager = Hrc_NodeReadManager(hnode);
+    model = Hrc_ManagerFindModelByName(manager, modelName);
+    newModelName = ALLOC(char, strlen(modelName) + 256);
+    i = 0;
+    sprintf(newModelName, "%s[%d]", modelName, i);
+
+    while(Hrc_ManagerFindModelByName(manager, newModelName) != NIL(Hrc_Model_t)){
+	i++;
+	sprintf(newModelName, "%s[%d]", modelName, i);
+    }
+    (void)fprintf(encFp,".model %s\n",newModelName);
+    FREE(newModelName);
+    /* .inputs line of enc file*/
+    if (Hrc_NodeReadNumFormalInputs(hnode) != 0){
+	(void)fprintf(encFp,".inputs ");
+	Hrc_NodeForEachFormalInput(hnode,i,var){
+	    (void)fprintf(encFp,"%s ",Var_VariableReadName(var));
+	}
+	(void)fprintf(encFp,"\n");
+    }
+    
+    /* .outputs line of enc file*/
+    if (Hrc_NodeReadNumFormalOutputs(hnode) != 0){
+	(void)fprintf(encFp,".outputs ");
+	Hrc_NodeForEachFormalOutput(hnode,i,var){
+	    (void)fprintf(encFp,"%s ",Var_VariableReadName(var));
+	}
+	(void)fprintf(encFp,"\n");
+    }
+    
+    /* .mv for primary inputs, printed to enc file*/
+    Hrc_NodeForEachFormalInput(hnode,i,var){
+	IoMvCheckPrint(encFp,var,printedMvsStTable);
+    }
+    /* .mv for primary outputs, printed to enc file*/
+    Hrc_NodeForEachFormalOutput(hnode,i,var){
+	IoMvCheckPrint(encFp,var,printedMvsStTable);
+    }
+    
+    /* .subckt stuff */
+    Hrc_ModelForEachSubckt(model,gen,instanceName,subckt){
+	subcktModel = Hrc_SubcktReadModel(subckt);
+	subcktHnode = Hrc_ModelReadMasterNode(subcktModel);
+	subcktActualInputVars = Hrc_SubcktReadActualInputVars(subckt);
+	subcktActualOutputVars = Hrc_SubcktReadActualOutputVars(subckt);
+	
+	/* .mv for subckt inputs */
+	for (i=0; i < array_n(subcktActualInputVars); i++){
+	    var = array_fetch(Var_Variable_t *,subcktActualInputVars,i);
+	    IoMvCheckPrint(encFp,var,printedMvsStTable);
+	}
+
+	/* .mv for subckt outputs */
+	for (i=0; i < array_n(subcktActualOutputVars); i++){
+	    var = array_fetch(Var_Variable_t *,subcktActualOutputVars,i);
+	    IoMvCheckPrint(encFp,var,printedMvsStTable);
+	}
+
+	/* .subckt declarations */
+	(void)fprintf(encFp,".subckt %s %s ",
+		      Hrc_ModelReadName(subcktModel), Hrc_SubcktReadInstanceName(subckt));
+	Hrc_NodeForEachFormalInput(subcktHnode,i,var){
+	    actualVar = array_fetch(Var_Variable_t *,subcktActualInputVars,i);
+	    (void)fprintf(encFp,"%s = %s ",Var_VariableReadName(var),Var_VariableReadName(actualVar)); 
+	}   
+	Hrc_NodeForEachFormalOutput(subcktHnode,i,var){
+	    actualVar = array_fetch(Var_Variable_t *,subcktActualOutputVars,i);
+	    (void)fprintf(encFp,"%s = %s ",Var_VariableReadName(var),Var_VariableReadName(actualVar)); 
+	}   
+	(void)fprintf(encFp,"\n");
+    }
+
+    encOutputsStTable = st_init_table(st_ptrcmp, st_ptrhash);
+    encInputsStTable = st_init_table(st_ptrcmp, st_ptrhash);
+    blifInputsStTable = st_init_table(strcmp, st_strhash);
+    blifOutputsStTable = st_init_table(strcmp, st_strhash);
+
+    /* encoding tables to .enc file */
+    IoEncWriteMvToBinTables(hnode, encFp, encOutputsStTable, encInputsStTable, combinationalOnly);
+
+    /* decoding tables to .enc file */
+    IoEncWriteBinToMvTables(hnode, encFp, encOutputsStTable, encInputsStTable, combinationalOnly, makeLatchIOsPOs);
+
+    /* if write_blif called without -c or -l options, then print a warning saying
+       that the files cant be read back into vis..
+    */
+    if(!(combinationalOnly || makeLatchIOsPOs)){
+      fprintf(fp,"# This blif file and the encoding file that was written out with it cannot\n");           
+      fprintf(fp,"# currently be read back into VIS. If you would like to read the blif and\n");           
+      fprintf(fp,"# encoding files back into VIS, then use the 'write_blif -l' or\n");
+      fprintf(fp,"#'write_blif -c' options.\n");
+    }
+    
+    /* .inputs declarations for blif file */
+    fprintf(fp,".model %s\n",modelName );     
+    numInputs = IoBlifWriteInputs(hnode, fp, blifInputsStTable, combinationalOnly, makeLatchIOsPOs);
+
+    /* .outputs declarations for blif file */
+    numOutputs = IoBlifWriteOutputs(hnode, fp, blifOutputsStTable, combinationalOnly, makeLatchIOsPOs);
+
+    if((numInputs == 0) && (numOutputs != 0)){
+      fprintf(vis_stderr, "Warning: Blif file has zero inputs\n");
+    }
+    if((numOutputs == 0) && (numInputs != 0)){
+      fprintf(vis_stderr, "Warning: Blif file has zero outputs\n");
+    }
+    if((numInputs == 0) && (numOutputs == 0)){
+      fprintf(vis_stderr, "Warning: Blif file has zero inputs and zero outputs\n");
+    }
+
+    /* .latch declarations for blif file */
+    IoWriteLatches(hnode, fp, encFp, printedMvsStTable, blifOutputsStTable, blifInputsStTable, encOutputsStTable, encInputsStTable, combinationalOnly, makeLatchIOsPOs, verbosity);
+    Hrc_NodeForEachNameTable(hnode, i, table){
+	if((Tbl_TableReadNumInputs(table) == 0) && (Tbl_TableReadNumOutputs(table) > 1)){
+	    (void)fprintf(stdout, "Warning: ");
+	    Tbl_TableForEachOutputVar(table, j, var){
+		(void)fprintf(stdout, "%s, ", Var_VariableReadName(var));
+	    }
+	    (void)fprintf(stdout, "assumed to be pseudoinputs\n");
+	    Tbl_TableForEachOutputVar(table, j, var){
+		singleOutputTable = Tbl_TableAlloc();
+		Tbl_TableAddColumn(singleOutputTable, var, 1);
+	        (void) Tbl_TableAddRow(singleOutputTable);
+		entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+		numVal = Var_VariableReadNumValues(var);
+		Tbl_EntrySetValue(entry, 0, numVal - 1);
+		Tbl_TableSetEntry(singleOutputTable, entry, 0, 0, 1);
+		_IoTableWriteBlif(encodingType, hnode, singleOutputTable, blifInputsStTable, fp, encFp,
+				  verbosity);
+		Tbl_TableFree(singleOutputTable);
+	    }
+	}
+	else{
+	  if(IoOutputExpansionRequired(table)){
+	    if(verbosity > 0){
+	      (void)fprintf(stdout, "Splitting into Single Output Table before Processing\n");
+	    }
+	    for(j = 0; j < Tbl_TableReadNumOutputs(table); j++){
+	      singleOutputTable = IoMakeSingleOutputTable(table, j);
+	      _IoTableWriteBlif(encodingType, hnode, singleOutputTable, blifInputsStTable, fp, encFp,
+				verbosity);
+	      Tbl_TableFree(singleOutputTable);
+	    }
+	  }
+	  else{
+	    if(!((Tbl_TableReadNumInputs(table) == 0) && (Tbl_TableReadNumOutputs(table) > 1))){
+	      _IoTableWriteBlif(encodingType, hnode, table, blifInputsStTable, fp, encFp,
+				verbosity);
+	    }
+	  }
+	}
+    }
+    st_foreach_item_int(blifInputsStTable, gen, &name, &i){
+	FREE(name);
+    }
+    st_free_table(blifInputsStTable);
+    st_foreach_item_int(blifOutputsStTable, gen, &name, &i){
+	FREE(name);
+    }
+    st_free_table(blifOutputsStTable);
+    st_free_table(encInputsStTable);
+    st_free_table(encOutputsStTable);
+    st_foreach_item_int(printedMvsStTable, gen, &name, &i){
+	FREE(name);
+    }
+    st_free_table(printedMvsStTable);
+    /* printing an empty .exdc network keeps sis from sweeping away the
+       dummy buffers that latch outputs are made to drive as a result of the 
+       "write_blif -l" cmd. The dummy buffers were added because if they were 
+       not present, sis would introduce buffers whenever latch outputs drive POs
+       directly (in the "xdc" command), ruining the name correspondence required 
+       for read_blif to work and reinstate mv latches.
+    */
+    fprintf(fp,".exdc\n");
+    fprintf(fp,".end\n");
+    if(encFp != stdout){
+      (void) fclose(encFp);
+    }
+    return 0;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+    
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function***********************************************************
+
+
+  Synopsis	[ Determinize, encode and write a blifmv table to blif file ]
+
+  Description	[ Note that this routine cannot handle the "=" construct of 
+                  blifmv. It is my opinion that a front-end routine should be
+                  used to remove the "="'s. ]
+
+  SideEffects	[ ]
+
+  SeeAlso	[  ]
+  **********************************************************************/
+static int
+_IoTableWriteBlif(
+    Io_Encoding_Type_t encodingType,
+    Hrc_Node_t *hnode,		 
+    Tbl_Table_t *origBlifmvTable,
+    st_table *blifInputsStTable,
+    FILE *fp,
+    FILE *encFp,
+    int verbosity )
+{
+    IoBlifInfo_t *blifInfo;
+
+    blifInfo = ALLOC(IoBlifInfo_t, 1);
+    if(verbosity > 1){
+	(void)fprintf(stdout, "Original Blifmv Table :\n");
+	Tbl_TableWriteBlifMvToFile(origBlifmvTable, 0, stdout);
+    }
+    IoInitBlifInfo(blifInfo, origBlifmvTable, fp, encFp, verbosity);
+    if(encodingType == SIMPLE){
+	if(_IoMakeInitialEncodings(blifInfo, hnode)){
+	    blifInfo->binTblArray = array_alloc(Tbl_Table_t *, 0);
+	    IoFreeBlifInfo(blifInfo);
+	    return 0;
+	}
+	_IoDeterminizeEncodeOutputPart(blifInfo, blifInputsStTable);
+	_IoMakeBinTable(blifInfo);
+	if(blifInfo->verbosity > 0){
+	    (void)fprintf(stdout, "Done with Output Singletonization\n");
+	}
+	if(blifInfo->verbosity > 1){
+	    (void)fprintf(stdout, "Final Blifmv Table After Output Singletonization:\n");
+	    Tbl_TableWriteBlifMvToFile(blifInfo->blifmvTable, 0, stdout);    
+	    (void)fprintf(stdout, "Bin Table After Output Singletonization:\n");
+	    Tbl_TableWriteBlifMvToFile(blifInfo->binTable, 0, stdout);    
+	}
+	_IoDeterminizeEncodeRows(blifInfo, blifInputsStTable);     
+	if(blifInfo->verbosity > 0){
+	    (void)fprintf(stdout, "Done with Row Intersection and Determinization\n");
+	}
+	if(blifInfo->verbosity > 1){
+	    (void)fprintf(stdout, "Final Bin Table After Determinization \n");
+	    Tbl_TableWriteBlifMvToFile(blifInfo->binTable, 0, stdout);    
+	}
+	_IoMakeDcTables(blifInfo);
+	blifInfo->binTblArray = Tbl_TableSplit(blifInfo->binTable);
+	IoWriteBinTablesToFile(blifInfo);
+	IoFreeBlifInfo(blifInfo);
+	return 0;
+    }
+    else{
+	(void)fprintf(vis_stderr, "This encoding strategy has not been implemented yet\n");
+	return 1;
+    }
+}
+  
+
+/**Function********************************************************************
+
+  Synopsis    [Encodes variables based on their ranges]
+
+  Description [Returns encodings in the form of an array of tables for each
+               multivalued variable. ] 
+
+  SideEffects [Populates the array of tables describing the encoding]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+_IoMakeInitialEncodings(
+   IoBlifInfo_t *blifInfo,
+   Hrc_Node_t *hnode		       
+   )
+{
+    Var_Variable_t *var, *origVar;
+    int i, colnum, numRows, numValues, varRange, value, numEncBits;
+    char *name, *varname, *dupName;
+    Tbl_Entry_t *entry, *newEntry, *defEntry, *newDefEntry;
+    lsGen gen;
+    Tbl_Range_t *range;
+    Tbl_Table_t *table, *origTable;
+
+    if(Tbl_TableReadNumInputs(blifInfo->blifmvTable) == 0){
+	value = -1;
+	if(Tbl_TableReadNumRows(blifInfo->blifmvTable) != 0){
+	  entry = Tbl_TableReadEntry(blifInfo->blifmvTable, 0, 0, 1);
+	  numValues = Tbl_EntryReadNumValues(entry);
+	}
+	else{
+	  entry = Tbl_TableDefaultReadEntry(blifInfo->blifmvTable, 0);
+	  numValues = Tbl_EntryReadNumValues(entry);
+	}
+	origTable = Tbl_TableHardDup(blifInfo->blifmvTable);
+
+	if(Tbl_TableReadNumRows(blifInfo->blifmvTable) <= 1){
+	    if(numValues == 1){
+	    /* not a pseudoinput */
+		Tbl_EntryForEachValue(entry, value, gen, range);
+		assert(value != -1);
+		var = Tbl_TableReadIndexVar(blifInfo->blifmvTable, 0, 1);
+		varRange = Var_VariableReadNumValues(var);
+		numEncBits = IoNumEncBits(varRange);
+		varname = Var_VariableReadName(var);
+		for(i = numEncBits - 1; i >= 0; i--){
+		    dupName = ALLOC(char, strlen(varname) + IoNumDigits(numEncBits) + 2);
+		    sprintf(dupName, "%s%d", varname, i);
+		    (void)fprintf(blifInfo->BlifFp, ".names %s\n", dupName);
+		    FREE(dupName);
+		    if(value > (int) pow((double) 2, (double) i)){
+			(void)fprintf(blifInfo->BlifFp, "1\n");
+			value -= (int) pow((double) 2, (double) i);
+		    }
+		    else{
+			(void)fprintf(blifInfo->BlifFp, "0\n");
+		    }
+		}
+		Tbl_TableFree(origTable);
+		return 1;
+	    }
+	    else{
+		/* is a pseudoinput! */
+		/* make it look like a table with many rows, and singleton output entries per row */
+		table = Tbl_TableAlloc();
+
+		Tbl_TableForEachOutputVar(blifInfo->blifmvTable, i, var){
+		    Tbl_TableAddColumn(table, var, 1);
+		}
+		Tbl_TableForEachDefaultEntry(blifInfo->blifmvTable, defEntry, i) {
+		    if (defEntry != NIL(Tbl_Entry_t)) {
+			newDefEntry = Tbl_EntryDup(defEntry);
+		    }
+		    else {
+			newDefEntry = NIL(Tbl_Entry_t);
+		    }
+		    (void) Tbl_TableDefaultSetEntry(table, newDefEntry, i);
+		}
+		Tbl_EntryForEachValue(entry, value, gen, range){
+		    i = Tbl_TableAddRow(table);
+		    newEntry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+		    Tbl_EntrySetValue(newEntry, value, value);
+		    Tbl_TableSetEntry(table, newEntry, i, 0, 1);
+		}
+		Tbl_TableFree(blifInfo->blifmvTable);
+		blifInfo->blifmvTable = table;
+	    }
+	}
+	/* it is a pseudoinput, and has been singletonized wrt outputs */
+	if(Tbl_TableReadNumRows(blifInfo->blifmvTable) > 1){
+	    name = ALLOC(char, 256);
+	    i = 0;
+	    sprintf(name, "[%d]", i);
+	    while(!(Hrc_NodeFindVariableByName(hnode, name) == NULL)){	
+		i++;
+		sprintf(name, "[%d]", i);
+	    }
+	    
+	    blifInfo->pseudoinputFlag = TRUE;
+	    var = Var_VariableAlloc(hnode, name);
+	    Tbl_TableAddColumn(blifInfo->blifmvTable, var, 0);
+	    (void)fprintf(blifInfo->BlifFp, ".inputs %s0\n", name);
+	    origVar = Tbl_TableReadIndexVar(origTable, 0, 1);
+	    IoMvPrint(blifInfo->EncFp, origVar);
+	    Tbl_TableWriteBlifMvToFile(origTable, 0, blifInfo->EncFp);    
+	    Tbl_TableFree(origTable);
+	    numRows = Tbl_TableReadNumRows(blifInfo->blifmvTable);
+	    for(i = 0; i < numRows; i++){
+		if(i % 2 == 1){
+		    entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+		    Tbl_EntrySetValue(entry, 1, 1);
+		    Tbl_TableSetEntry(blifInfo->blifmvTable, entry, i, 0, 0);
+		}
+		else{
+		    entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+		    Tbl_EntrySetValue(entry, 0, 0);
+		    Tbl_TableSetEntry(blifInfo->blifmvTable, entry, i, 0, 0);
+		}
+	    }
+	    FREE(name);
+	}
+    }
+
+    Tbl_TableForEachInputVar(blifInfo->blifmvTable, colnum, var){
+	IoEncodeVariable(blifInfo, var, colnum, 0);
+    }
+
+    Tbl_TableForEachOutputVar(blifInfo->blifmvTable, colnum, var){
+	IoEncodeVariable(blifInfo, var, colnum, 1);
+    }
+    return 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Encodes variables to make singleton output values in every row]
+
+  Description [Returns modified table along with a modified array of tables for 
+               encoding the multivalued variables. If the original table
+               has singleton output values then it is returned unmodified, 
+	       with the unmodified variable encoding tables.]
+
+  SideEffects [Potentially modifies the array of tables describing the encoding]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+_IoDeterminizeEncodeOutputPart( 
+   IoBlifInfo_t *blifInfo,
+   st_table *blifInputsStTable
+   )
+{
+    Tbl_Entry_t *entry;
+    int numValues, i, j, numRows, numOutputs;
+    IoVarEncEntry_t *varEnc;
+    array_t *MvOutputArray;
+
+    numRows = Tbl_TableReadNumRows(blifInfo->blifmvTable);
+    numOutputs = Tbl_TableReadNumOutputs(blifInfo->blifmvTable);
+    for(i = 0; i < numRows; i++){
+	MvOutputArray = array_alloc(int, 0);
+    	numValues = 1;
+	for(j = 0; j < numOutputs; j++){
+	    entry = Tbl_TableReadEntry(blifInfo->blifmvTable, i, j, 1);
+	    numValues *= Tbl_EntryReadNumValues(entry);
+	    array_insert_last(int, MvOutputArray, Tbl_EntryReadNumValues(entry));
+	}
+	if(numValues > 1){
+	    varEnc = IoFindSmallestCode(blifInfo);
+	    if(blifInfo->verbosity > 2){
+		(void)fprintf(stdout, "Singletonizing Outputs in Row %d\n", i);
+		(void)fprintf(stdout, "Best Variable is %s\n", Var_VariableReadName(varEnc->variable));
+	    }
+	    IoIncreaseCodeSize(varEnc, numValues, blifInfo->verbosity);
+	    IoChangeBlifmvTableEntries(blifInfo, i, numValues, varEnc, MvOutputArray);
+	    IoChangeEncTableEntries(blifInfo, blifInputsStTable, varEnc, numValues);
+	    i = -1;
+	    array_free(MvOutputArray);
+	    
+	    if(blifInfo->verbosity > 2){
+		(void)fprintf(stdout, "Blifmv Table After Output Singletonization\n");
+		Tbl_TableWriteBlifMvToFile(blifInfo->blifmvTable, 0, stdout);    
+	    }
+	}
+	else{
+	    array_free(MvOutputArray);
+	}
+    }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Encodes variables to make table deterministic]
+
+  Description [Returns modified table along with a modified array of tables for 
+               encoding the multivalued variables. If the original table
+               is deterministic, then it is returned unmodified, 
+	       with the unmodified variable encoding tables.]
+
+  SideEffects [Potentially modifies the array of tables describing the encoding]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+_IoDeterminizeEncodeRows( 
+   IoBlifInfo_t *blifInfo,
+   st_table *blifInputsStTable
+   )
+{
+    int i, j, k, numRows, numOutputs, numInputs, mvValue;
+    boolean rowsIntersect;
+    IoVarEncEntry_t *varEnc;
+    char *pseudoInputName, *realPseudoInputName;
+    Var_Variable_t *outvar, *var, *origVar;
+    Tbl_Entry_t *entry;
+    
+    
+    numRows = Tbl_TableReadNumRows(blifInfo->binTable);
+    for(i = 0; i < numRows; i++){
+	for(j = i + 1; j < numRows; j++){	
+	    if(blifInfo->verbosity > 2){
+		(void)fprintf(stdout, "Intersecting Rows %d and %d \n", i, j);
+	    }
+	    rowsIntersect = Tbl_RowInputIntersect(blifInfo->binTable, i, j); 
+	    if(rowsIntersect == 1){  
+		if(blifInfo->verbosity > 2){
+		    (void)fprintf(stdout, "Input Intersection non-null\n");
+		}
+		if(!Tbl_RowOutputIntersect(blifInfo->binTable, i, j)){
+		    varEnc = IoFindSmallestCode(blifInfo);
+		    if(blifInfo->verbosity > 2){
+			(void)fprintf(stdout, "Output Intersection null\n");
+			(void)fprintf(stdout, "Best Variable is %s\n", Var_VariableReadName(varEnc->variable));
+
+		    }
+		    IoIncreaseCodeSize(varEnc, 2, blifInfo->verbosity); 
+		    IoChangeBlifmvTableRows(blifInfo, varEnc, i, j);
+		    IoChangeEncTableEntries(blifInfo, blifInputsStTable, varEnc, 2); 
+		    
+		    if(blifInfo->verbosity > 2){
+			(void)fprintf(stdout, "Bin Table After Row Overlap elimination \n");
+			Tbl_TableWriteBlifMvToFile(blifInfo->binTable, 0, stdout);    
+		    }
+		}
+	    }
+	}
+    }
+    if(blifInfo->pseudoinputFlag == TRUE){
+	/* pseudoinput cant have .def construct */
+	outvar = Tbl_TableReadIndexVar(blifInfo->binTable, 0, 1);
+	pseudoInputName = Var_VariableReadName(outvar);
+	realPseudoInputName = ALLOC(char, strlen(pseudoInputName) + 2);
+	sprintf(realPseudoInputName, "%s", pseudoInputName);
+	realPseudoInputName[strlen(pseudoInputName) - 1] = '\0';
+	numOutputs = Tbl_TableReadNumOutputs(blifInfo->binTable);
+	numInputs = Tbl_TableReadNumInputs(blifInfo->binTable);
+	for(i = 0; i < numInputs; i++){
+	    (void)fprintf(blifInfo->EncFp, ".table %s ->", realPseudoInputName);
+	    var = Tbl_TableReadIndexVar(blifInfo->binTable, i, 0);
+	    (void)fprintf(blifInfo->EncFp, "%s\n", Var_VariableReadName(var));		
+	    (void)fprintf(blifInfo->EncFp, ".default 0\n");
+	    for(j = 0; j < numRows; j++){
+		mvValue = 0;
+		for(k = 0; k < numOutputs; k++){
+		    entry = Tbl_TableReadEntry(blifInfo->binTable, j, k, 1);
+		    if(Tbl_EntryCheckRange(entry, 1, 1)){
+			mvValue += (int) pow((double)2, (double) k);
+		    }
+		}
+		origVar = Tbl_TableReadIndexVar(blifInfo->blifmvTable, 0, 1);
+		if(Var_VariableTestIsSymbolic(origVar)){
+		    (void)fprintf(blifInfo->EncFp, "%s ",
+				  Var_VariableReadSymbolicValueFromIndex(origVar, mvValue));		    
+		}
+		else{
+		    (void)fprintf(blifInfo->EncFp, "%d ", mvValue);
+		}
+
+		entry = Tbl_TableReadEntry(blifInfo->binTable, j, i, 0);
+		if(Tbl_EntryCheckRange(entry, 1, 1)){
+		    (void)fprintf(blifInfo->EncFp, "%d\n", 1);
+		}
+		else{ 
+		    if(Tbl_EntryCheckRange(entry, 0, 0)){
+			(void)fprintf(blifInfo->EncFp, "%d\n", 0);
+		    }
+		    else{
+			(void)fprintf(blifInfo->EncFp, "-\n");
+		    }
+		}
+	    }
+	}
+	FREE(realPseudoInputName);
+    }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates Dont-Care Tables for Variable Encodings]
+
+  Description [For each table in the blifInfo->inputEncTblArray, this
+               function creates dont-care tables]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+_IoMakeDcTables( 
+   IoBlifInfo_t *blifInfo
+   )
+{
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes out blifmvTable to binTable in encoded form]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+_IoMakeBinTable( 
+  IoBlifInfo_t *blifInfo
+  )
+{
+    int i, j, k, m, n, colnum, numRowsAfterExpansion, numEncBits;
+    int rootCol, rootRow, entryRepetitionCount, numCycles, value, numBits, currRow;
+    int numOutputs, numRows, numInputs, defValue, varRange;
+    Tbl_Entry_t *entry, *workingEntry;
+    array_t *binRangesArray, *mvEntryBinRanges;
+    IoVarEncEntry_t *varEnc;
+    char *varname, *dupName;
+    Var_Variable_t *var;
+    lsGen gen, gen2;
+    Tbl_Range_t *range, *range2;
+    IoBinRangeEntry_t *binRangeEntry;
+    
+    
+    /* initialize the binTable, defining input vars etc   */
+    
+    numRows = Tbl_TableReadNumRows(blifInfo->blifmvTable);
+    numInputs = Tbl_TableReadNumInputs(blifInfo->blifmvTable);
+    numOutputs = Tbl_TableReadNumOutputs(blifInfo->blifmvTable);
+    for(j = 0; j < Tbl_TableReadNumInputs(blifInfo->blifmvTable); j++){
+	varEnc = array_fetch(IoVarEncEntry_t *, blifInfo->inputEncTblArray, j);
+	numEncBits = varEnc->numEncBits;
+	for(k = 0; k < numEncBits ; k++){
+	    varname = Var_VariableReadName(varEnc->variable);
+	    dupName = ALLOC(char, strlen(varname) + IoNumDigits(numEncBits) + 2);
+	    sprintf(dupName, "%s%d", varname, k);
+	    var = Var_VariableAlloc(NIL(Hrc_Node_t), dupName);
+	    FREE(dupName);
+	    array_insert_last(Var_Variable_t *, blifInfo->varArray, var);
+	    colnum = Tbl_TableAddColumn(blifInfo->binTable, var, 0);
+	}
+    }
+    
+    for(j = 0; j < Tbl_TableReadNumOutputs(blifInfo->blifmvTable); j++){
+	varEnc = array_fetch(IoVarEncEntry_t *, blifInfo->outputEncTblArray, j);
+	numEncBits = varEnc->numEncBits;
+	for(k = 0; k < numEncBits ; k++){
+	    varname = Var_VariableReadName(varEnc->variable);
+	    dupName = ALLOC(char, strlen(varname) + IoNumDigits(numEncBits) + 2);
+	    sprintf(dupName, "%s%d", varname, k);
+	    var = Var_VariableAlloc(NIL(Hrc_Node_t), dupName);
+	    FREE(dupName);
+	    array_insert_last(Var_Variable_t *, blifInfo->varArray, var);
+	    colnum = Tbl_TableAddColumn(blifInfo->binTable, var, 1);
+	}
+    }
+    
+    
+/*
+    fprintf(stdout, "\n");    
+*/
+    for(i = 0; i < numRows; i++){
+	
+	/* make temp array of number of values for each input var  */
+	numRowsAfterExpansion = 1;
+	binRangesArray = array_alloc(array_t *, 0);
+	
+	for(colnum = 0; colnum < numInputs; colnum++){
+	    entry = Tbl_TableReadEntry(blifInfo->blifmvTable, i, colnum, 0);
+	    workingEntry = Tbl_EntryDup(entry);
+	    mvEntryBinRanges = IoMakeBinaryRangesArray(workingEntry, colnum, blifInfo);
+	    numRowsAfterExpansion *= array_n(mvEntryBinRanges);
+	    array_insert_last(array_t *, binRangesArray, mvEntryBinRanges); 
+	}
+
+/*
+	for(j = 0; j < array_n(binRangesArray); j++){
+	    mvEntryBinRanges = array_fetch(array_t *, binRangesArray, j);
+	    for(k = 0; k < array_n(mvEntryBinRanges); k++){
+		binRangeEntry = array_fetch(IoBinRangeEntry_t *, mvEntryBinRanges, k);
+		fprintf(stdout, "start %d\t runlen%d\t skip %d\n", binRangeEntry->startValue, binRangeEntry->runLength, binRangeEntry->skipLength);
+	    }
+	    (void)fprintf(stdout, "\n");
+	}
+	fprintf(stdout, "numRowsAfterExpansion %d\n", numRowsAfterExpansion);
+
+*/
+	/* add numRowsAfterExpansion rows to binTable */
+	
+	rootCol = 0;
+	rootRow = Tbl_TableReadNumRows(blifInfo->binTable);
+	for(j = 0; j < numRowsAfterExpansion; j++){
+	    Tbl_TableAddRow(blifInfo->binTable);
+	}
+
+	/* write out binary encoded variable values for the determinized, encoded blifmvTable
+	   (input parts) */
+
+	entryRepetitionCount = numRowsAfterExpansion;
+	m = 0;
+	numCycles = 1;
+
+	for(colnum = 0; colnum < numInputs; colnum++){
+	    mvEntryBinRanges = array_fetch(array_t *, binRangesArray, colnum);
+	    currRow = rootRow;
+	    rootCol += IoNumBinVars(colnum, blifInfo->inputEncTblArray);
+	    entryRepetitionCount = entryRepetitionCount / array_n(array_fetch(array_t *, binRangesArray, m));
+	    numCycles *= IoNumValuesFromBinRangesArray(colnum, binRangesArray);
+	    numBits = IoNumBinVars(colnum + 1, blifInfo->inputEncTblArray);
+	    for(k=0; k<numCycles; k++){
+		for(n = 0; n < array_n(mvEntryBinRanges); n++){
+		    binRangeEntry = array_fetch(IoBinRangeEntry_t *, mvEntryBinRanges, n);
+		    IoWriteExpandedValueToBinTable(blifInfo->binTable, currRow, rootCol, binRangeEntry, entryRepetitionCount, numBits, 0);
+		    currRow = currRow + entryRepetitionCount;
+		}
+	    }
+	    m++;
+	}
+
+	/* write out binary encoded variable values for the determinized, encoded blifmvTable
+	   (output parts) */
+
+	rootCol = 0;
+
+	for(colnum = 0; colnum < numOutputs; colnum++){
+	    entry = Tbl_TableReadEntry(blifInfo->blifmvTable, i, colnum, 1);
+	    rootCol += IoNumBinVars(colnum, blifInfo->outputEncTblArray);
+	    numBits = IoNumBinVars(colnum + 1, blifInfo->outputEncTblArray);
+	    Tbl_EntryForEachValue(entry, value, gen, range){
+		binRangeEntry = ALLOC(IoBinRangeEntry_t, 1);
+		binRangeEntry->startValue = value;
+		binRangeEntry->runLength = 1;
+		binRangeEntry->skipLength = 1;
+		IoWriteExpandedValueToBinTable(blifInfo->binTable, rootRow, rootCol, binRangeEntry, numRowsAfterExpansion, numBits, 1);
+		FREE(binRangeEntry);
+	    }
+	}
+	for(j = 0; j < array_n(binRangesArray); j++){
+	    mvEntryBinRanges = array_fetch(array_t *, binRangesArray, j);
+	    for(n = 0; n < array_n(mvEntryBinRanges); n++){
+		binRangeEntry = array_fetch(IoBinRangeEntry_t *, mvEntryBinRanges, n);
+		FREE(binRangeEntry);
+	    }
+	    array_free(mvEntryBinRanges);
+	}
+	array_free(binRangesArray);
+    }
+    
+    rootCol = 0;
+    Tbl_TableForEachOutputVar(blifInfo->blifmvTable, colnum, var){
+	entry = Tbl_TableDefaultReadEntry(blifInfo->blifmvTable, colnum);
+	if(entry != NIL(Tbl_Entry_t)){
+	    varRange = Var_VariableReadNumValues(var);
+	    numEncBits = IoNumEncBits(varRange);
+	    defValue = -1;
+	    Tbl_EntryForEachValue(entry, value, gen2, range2){
+		defValue = value;
+		assert(defValue != -1);
+	    }
+	    for(j = numEncBits - 1; j >= 0; j--){
+		if(((int)(defValue / pow((double) 2, (double) j))) == 1){
+		    IoInvertBinTableOutput(blifInfo, rootCol + j);
+		    defValue = defValue - (int)pow((double)2,(double)j);
+		}
+	    }
+	    rootCol += numEncBits;
+	}
+    }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks that all hnodes rooted at the give hnode are boolean and 
+               deterministic]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+_IoCheckHnodeTreeIsBooleanAndDeterministic(
+  mdd_manager **mddMgr,				       
+  Hrc_Node_t *hnode, 
+  st_table *modelTable,
+  boolean *pSymVarsPresent,
+  int verbosity
+  )
+{
+  char *modelName, *childName;
+  Hrc_Model_t *model;
+  st_generator *stGen;
+  Hrc_Manager_t *manager;  
+  Hrc_Node_t *childNode;
+
+  manager = Hrc_NodeReadManager(hnode);
+  /* enter current model in modelTable */
+  modelName = Hrc_NodeReadModelName(hnode);
+  model = Hrc_ManagerFindModelByName(manager, modelName);
+  if(st_is_member(modelTable, (char *) model)){
+    return 0;
+  }
+  else{
+    st_insert(modelTable, (char *)model, (char *) (long) (-1));
+  }
+  
+  if(_IoCheckHnodeIsBooleanAndDeterministic(mddMgr, hnode, pSymVarsPresent)){
+    if(verbosity > 1){
+      fprintf(vis_stderr, "Model %s is NOT boolean and deterministic\n", modelName);
+    }
+    return 1;
+  }
+  if(verbosity > 1){
+    fprintf(vis_stderr, "Model %s is boolean and deterministic\n", modelName);
+  }
+  Hrc_NodeForEachChild(hnode, stGen, childName, childNode){
+    if(_IoCheckHnodeTreeIsBooleanAndDeterministic(mddMgr, childNode, modelTable, pSymVarsPresent, verbosity)){
+      st_free_gen(stGen);
+      return 1;
+    }
+  }
+  return 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks that the given hnode is boolean and deterministic]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+_IoCheckHnodeIsBooleanAndDeterministic(
+  mdd_manager **mddMgr,				       
+  Hrc_Node_t *hnode,
+  boolean *pSymVarsPresent
+  )
+{
+  
+  /* check that variables of all models are boolean */
+  if(_IoCheckHnodeVarsAreBoolean(hnode, pSymVarsPresent)){
+    return 1;
+  }
+
+  /* check that latch resets of all models are either 0/1/2 */
+  if(_IoCheckHnodeLatchResetIsConstant(hnode)){
+    return 1;
+  }
+
+  /* check that tables of all models are deterministic */
+  if(_IoCheckHnodeTablesAreDeterministic(mddMgr, hnode)){
+    return 1;
+  }
+
+  return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Checks that the variables of a model are boolean]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+_IoCheckHnodeVarsAreBoolean(
+  Hrc_Node_t *hnode,
+  boolean *pSymVarsPresent
+  )
+{
+  st_generator *stGen;
+  char *varName;
+  Var_Variable_t *var;
+  
+  Hrc_NodeForEachVariable(hnode, stGen, varName, var){
+    if(Var_VariableReadNumValues(var) > 2){
+      fprintf(vis_stderr, "Variable %s is not boolean - quitting.\n", varName);      
+      st_free_gen(stGen);
+      return 1;
+    }
+    if(Var_VariableTestIsSymbolic(var)){
+      *pSymVarsPresent = TRUE;
+    }
+  }
+  return 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks that the latches of a model have constant reset tables]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+_IoCheckHnodeLatchResetIsConstant(
+  Hrc_Node_t *hnode 
+  )
+{
+  st_generator *stGen;
+  char *latchName;
+  Hrc_Latch_t *latch;
+  boolean test;
+  Tbl_Table_t *table, *resetTable;
+  Tbl_Entry_t *entry;
+  Var_Variable_t *var, *parentVar;
+  int i, j;
+
+  Hrc_NodeForEachLatch(hnode, stGen, latchName, latch){
+    resetTable = Hrc_LatchReadResetTable(latch);
+    test = Tbl_TableTestIsConstant(resetTable, 0);
+    /*
+      Tbl_TableTestIsConstant gives 0 result for reset tables of
+      the type .reset a ->b; - =a; where a is a constant defined 
+      in another table. So check for this case as well. 
+      */
+    if(test == FALSE){
+      if(Tbl_TableReadNumRows(resetTable) == 1){
+	entry = Tbl_TableReadEntry(resetTable, 0, 0, 1);
+	if(Tbl_EntryReadType(entry) == Tbl_EntryEqual_c){
+	  parentVar = Tbl_EntryReadVar(resetTable, entry);
+	  Hrc_NodeForEachNameTable(hnode, i, table){
+	    Tbl_TableForEachOutputVar(table, j, var){
+	      if(var == parentVar){
+		test = Tbl_TableTestIsConstant(table, j);
+	      }
+	    }
+	  }
+	}
+      }
+    }
+    if (test == FALSE){
+      fprintf(vis_stderr, "Latch %s has a non-constant reset value - quitting.\n", latchName);
+      st_free_gen(stGen);
+      return 1;
+    }
+  }
+  return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Checks that all tables in a model are deterministic]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+_IoCheckHnodeTablesAreDeterministic(
+  mdd_manager **mddMgr,				    
+  Hrc_Node_t *hnode 
+  )
+{
+  int i, j, k, index, colNum, offset, numInputs;
+  Tbl_Table_t *table;
+  Var_Variable_t *inputVar, *outputVar, *var;
+  Mvf_Function_t *faninMvf, *outMvf;
+  array_t *faninMvfArray;
+  array_t *mvarValues;
+  Tbl_Entry_t *entry;
+
+
+  /* note that reset tables are not handled here */
+  Hrc_NodeForEachNameTable(hnode, i, table){
+    Tbl_TableForEachOutputVar(table, index, outputVar){
+
+      faninMvfArray = array_alloc(Mvf_Function_t *, 0);
+      mvarValues = array_alloc(int, 0);
+      
+      /* Create MDD variables for the table inputs. */
+      Tbl_TableForEachInputVar(table, colNum, inputVar) {
+	array_insert_last(int, mvarValues, Var_VariableReadNumValues(inputVar));
+      }
+      offset = array_n(mdd_ret_mvar_list(*mddMgr));  /* number of existing mvars */
+      mdd_create_variables(*mddMgr, mvarValues, NIL(array_t), NIL(array_t));
+      array_free(mvarValues);
+      
+      /*
+       * Construct an MVF for each table input. The MVF for column j is the MVF
+       * for MDD variable j.
+       */
+      
+      numInputs = Tbl_TableReadNumInputs(table );
+      for (j = 0; j < numInputs; j++) {
+	faninMvf = Mvf_FunctionCreateFromVariable(*mddMgr, (j + offset));
+	array_insert_last(Mvf_Function_t *, faninMvfArray, faninMvf);
+      }
+      
+      /* Compute the MVF of the output indexed by index. */
+      outMvf = Tbl_TableBuildMvfFromFanins(table, index, faninMvfArray, *mddMgr);
+      Mvf_FunctionArrayFree(faninMvfArray);
+      
+      /*
+       * If the function is a non-deterministic constant, or it has some
+       * inputs, and is non-deterministic, then fail
+       */
+      if((numInputs > 0) && !Mvf_FunctionTestIsDeterministic(outMvf)){
+	(void) fprintf(vis_stderr, "Table %s is non-deterministic - quitting\n", Var_VariableReadName(outputVar));
+	Mvf_FunctionFree(outMvf);
+	return 1;
+      }
+      if(Mvf_FunctionTestIsNonDeterministicConstant(outMvf)){
+	(void) fprintf(vis_stderr, "Table %s is a non-deterministic constant - quitting\n", Var_VariableReadName(outputVar));
+	Mvf_FunctionFree(outMvf);
+	return 1;
+      }
+      if (!Mvf_FunctionTestIsCompletelySpecified(outMvf)) {
+	(void) fprintf(vis_stderr, "Table %s is not completely specified - quitting\n", Var_VariableReadName(outputVar));
+	Mvf_FunctionFree(outMvf);
+	return 1; 
+      } 
+      Mvf_FunctionFree(outMvf);
+      _MddManagerResetIfNecessary(mddMgr);
+
+    }
+  }
+
+  Hrc_NodeForEachNameTable(hnode, i, table){
+    for(j = 0; j < Tbl_TableReadNumOutputs(table); j++){
+      entry = Tbl_TableDefaultReadEntry(table, j);
+      if(entry != NIL(Tbl_Entry_t)){
+	if(Tbl_EntryReadType(entry) == Tbl_EntryNormal_c){
+	  if(Tbl_EntryReadNumValues(entry) > 1){
+	    outputVar = Tbl_TableReadIndexVar(table, j, 1);
+	    (void)fprintf(stdout, "The table with %s as an output has non-singleton default values - quitting\n", Var_VariableReadName(outputVar));
+	    return 1;
+	  }
+	}
+	else{
+	  var = Tbl_EntryReadVar(table, entry);
+	  k = Tbl_TableReadVarIndex(table, var, 1);
+	  if(k<0){
+	    outputVar = Tbl_TableReadIndexVar(table, j, 1);
+	    (void)fprintf(stdout, "Output %s has a default value that refers to an input variable - quitting\n", Var_VariableReadName(outputVar));
+	    return 1;
+	  }
+	}
+      }
+    }
+  }
+  return 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Potentially quits mddMgr and starts a new one.]
+
+  Description [Quits mddMgr if the number of binary variables exceeds
+  MAX_NUMBER_BDD_VARS, and starts a new manager with no variables.
+  Initializing an empty MDD manager is costly in some BDD packages, so we want
+  to avoid doing it often (say, once per table).  On the other hand, we don't
+  want the manager to have too many variables, because then reordering becomes
+  expensive.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+_MddManagerResetIfNecessary(
+  mdd_manager **mddMgr)
+{
+  if (bdd_num_vars(*mddMgr) > MAX_NUMBER_BDD_VARS) {
+    mdd_quit(*mddMgr);
+    *mddMgr = mdd_init_empty();
+  }
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Write out a Hnode and recurse on its children]
+
+  Description [Call the function to write out the given hnode in blif, and 
+  recursively call the same function on its children.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+_IoHnodeWriteBlifRecursively(
+   Io_Encoding_Type_t encodingType,
+   Hrc_Node_t *hnode,
+   st_table *modelTable, 
+   FILE *fp,
+   FILE *encFp,
+   int verbosity
+  )
+{
+  char *modelName, *childName;
+  Hrc_Model_t *model;
+  Hrc_Manager_t *manager;  
+  st_generator *stGen;
+  Hrc_Node_t *childNode;
+
+  manager = Hrc_NodeReadManager(hnode);
+  /* enter current model in modelTable */
+  modelName = Hrc_NodeReadModelName(hnode);
+  model = Hrc_ManagerFindModelByName(manager, modelName);
+  if(st_is_member(modelTable, (char *) model)){
+    return;
+  }
+  else{
+    st_insert(modelTable, (char *)model, (char *) (long) (-1));
+  }
+
+  _IoHnodeWriteBlifRecursivelyStep(encodingType, hnode, fp, encFp, verbosity);  
+  Hrc_NodeForEachChild(hnode, stGen, childName, childNode){
+    _IoHnodeWriteBlifRecursively(encodingType, childNode, modelTable, fp, encFp, verbosity);
+  }
+  return;
+}
+
+
+/**Function***********************************************************
+
+
+  Synopsis	[ Writes out an hnode to blif]
+
+  Description	[ Writes out IO declarations, subckt declarations and tables to
+                  the blif file specified.]
+
+  SideEffects	[ ]
+
+  SeeAlso	[  ]
+**********************************************************************/
+static int
+_IoHnodeWriteBlifRecursivelyStep(
+    Io_Encoding_Type_t encodingType,
+    Hrc_Node_t *hnode,
+    FILE *fp,
+    FILE *encFp,
+    int verbosity)
+{
+    Tbl_Table_t *table, *singleOutputTable;
+    int i, j;
+    Var_Variable_t *var, *actualVar;
+    char *name, *instanceName, *modelName;
+    st_generator *gen;
+    st_table *blifInputsStTable, *blifOutputsStTable, *printedMvsStTable;
+    st_table *encOutputsStTable, *encInputsStTable;
+    Hrc_Node_t *subcktHnode;
+    Hrc_Model_t *model, *subcktModel;
+    Hrc_Subckt_t *subckt;
+    Hrc_Manager_t *manager;
+    array_t *subcktActualInputVars, *subcktActualOutputVars;
+
+
+    printedMvsStTable = st_init_table(strcmp, st_strhash);
+
+  /* .model */
+    modelName = Hrc_NodeReadModelName(hnode);
+    manager = Hrc_NodeReadManager(hnode);
+    model = Hrc_ManagerFindModelByName(manager, modelName);
+    (void)fprintf(fp,".model %s\n", modelName);
+
+    /* .inputs line of blif file*/
+    if (Hrc_NodeReadNumFormalInputs(hnode) != 0){
+	(void)fprintf(fp,".inputs ");
+	Hrc_NodeForEachFormalInput(hnode,i,var){
+	    (void)fprintf(fp,"%s0 ",Var_VariableReadName(var));
+	}
+	(void)fprintf(fp,"\n");
+    }
+    
+    /* .outputs line of blif file*/
+    if (Hrc_NodeReadNumFormalOutputs(hnode) != 0){
+	(void)fprintf(fp,".outputs ");
+	Hrc_NodeForEachFormalOutput(hnode,i,var){
+	    (void)fprintf(fp,"%s0 ",Var_VariableReadName(var));
+	}
+	(void)fprintf(fp,"\n");
+    }
+    
+    /* .subckt stuff */
+    Hrc_ModelForEachSubckt(model,gen,instanceName,subckt){
+      subcktModel = Hrc_SubcktReadModel(subckt);
+      subcktHnode = Hrc_ModelReadMasterNode(subcktModel);
+      subcktActualInputVars = Hrc_SubcktReadActualInputVars(subckt);
+      subcktActualOutputVars = Hrc_SubcktReadActualOutputVars(subckt);
+      
+      /* .subckt declarations */
+      (void)fprintf(fp,".subckt %s ",
+		    Hrc_ModelReadName(subcktModel));
+      Hrc_NodeForEachFormalInput(subcktHnode,i,var){
+	actualVar = array_fetch(Var_Variable_t *,subcktActualInputVars,i);
+	(void)fprintf(fp,"%s0=%s0 ",Var_VariableReadName(var),Var_VariableReadName(actualVar)); 
+      }   
+      Hrc_NodeForEachFormalOutput(subcktHnode,i,var){
+	actualVar = array_fetch(Var_Variable_t *,subcktActualOutputVars,i);
+	(void)fprintf(fp,"%s0=%s0 ",Var_VariableReadName(var),Var_VariableReadName(actualVar)); 
+      }   
+      (void)fprintf(fp,"\n");
+    }
+
+    encOutputsStTable = st_init_table(st_ptrcmp, st_ptrhash);
+    encInputsStTable = st_init_table(st_ptrcmp, st_ptrhash);
+    blifInputsStTable = st_init_table(strcmp, st_strhash);
+    blifOutputsStTable = st_init_table(strcmp, st_strhash);
+
+    /* .latch declarations for blif file */
+    IoWriteLatches(hnode, fp, encFp, printedMvsStTable, blifOutputsStTable, blifInputsStTable, encOutputsStTable, encInputsStTable, 0, 0, verbosity);
+    Hrc_NodeForEachNameTable(hnode, i, table){
+	if(IoOutputExpansionRequired(table)){
+	    if(verbosity > 0){
+		(void)fprintf(stdout, "Splitting into Single Output Table before Processing\n");
+	    }
+	    for(j = 0; j < Tbl_TableReadNumOutputs(table); j++){
+		singleOutputTable = IoMakeSingleOutputTable(table, j);
+		_IoTableWriteBlif(encodingType, hnode, singleOutputTable, blifInputsStTable, fp, encFp,
+				  verbosity);
+		Tbl_TableFree(singleOutputTable);
+	    }
+	}
+	else{
+	    if(!((Tbl_TableReadNumInputs(table) == 0) && (Tbl_TableReadNumOutputs(table) > 1))){
+		_IoTableWriteBlif(encodingType, hnode, table, blifInputsStTable, fp, encFp,
+				  verbosity);
+	    }
+	}
+    }
+    st_foreach_item_int(blifInputsStTable, gen, &name, &i){
+	FREE(name);
+    }
+    st_foreach_item_int(blifOutputsStTable, gen, &name, &i){
+	FREE(name);
+    }
+    st_free_table(blifInputsStTable);
+    st_free_table(blifOutputsStTable);
+    st_free_table(encInputsStTable);
+    st_free_table(encOutputsStTable);
+    st_foreach_item_int(printedMvsStTable, gen, &name, &i){
+	FREE(name);
+    }
+    st_free_table(printedMvsStTable);
+    fprintf(fp,".end\n");
+    return 1;
+}
+
+
+
+/**Function***********************************************************
+
+
+  Synopsis	[ Checks if pseudoinput is also a PO]
+
+  Description	[ Checks if table has 0input, >1 output, or 1 output 
+                  with multiple valued entry]
+
+  SideEffects	[ ]
+
+  SeeAlso	[  ]
+**********************************************************************/
+static int
+_IoCheckPseudoinputIsPO(
+   Tbl_Table_t *table)
+{
+  int j;
+  Var_Variable_t *var = NIL(Var_Variable_t); /* to suppress warning */
+  Tbl_Entry_t *entry;
+  int numValues;
+    
+  if((Tbl_TableReadNumInputs(table) == 0) && (Tbl_TableReadNumOutputs(table) > 1)){
+    /* assume all are pseudoinputs */
+    Tbl_TableForEachOutputVar(table, j, var){
+      if(Var_VariableTestIsPO(var)){
+	return 1;
+      }
+    }
+  }
+
+  if(Tbl_TableReadNumInputs(table) == 0){
+    if(Tbl_TableReadNumRows(table) != 0){
+      entry = Tbl_TableReadEntry(table, 0, 0, 1);
+      numValues = Tbl_EntryReadNumValues(entry);
+    }
+    else{
+      entry = Tbl_TableDefaultReadEntry(table, 0);
+      numValues = Tbl_EntryReadNumValues(entry);
+    }
+
+    Tbl_TableForEachOutputVar(table, j, var);
+    if(Tbl_TableReadNumRows(table) <= 1){
+      if(numValues > 1){
+	if(Var_VariableTestIsPO(var)){
+	  return 1;
+	}
+      }
+    }
+    else{
+      if(Var_VariableTestIsPO(var)){      
+	return 1;
+      }
+    }
+  }
+
+  return 0;
+}
Index: vis_dev/vis-2.3/src/io/ioWriteBlifIo.c
===================================================================
--- vis_dev/vis-2.3/src/io/ioWriteBlifIo.c	(revision 14)
+++ vis_dev/vis-2.3/src/io/ioWriteBlifIo.c	(revision 14)
@@ -0,0 +1,1163 @@
+/**CFile***********************************************************************
+
+  FileName    [ ioWriteBlifIo.c ]
+
+  PackageName [ io ]
+
+  Synopsis    [ This file contains blifmv -> blif write routines that handle
+                the functionality of files IO.]
+
+  Description [ Routines for writing determinized, encoded tables to a file
+                as requested by the write_blif command. All file IO routines
+                are contained in this file. ]
+
+  SeeAlso     [ ioReadBlifmv.c, ioWriteBlif.c, ioWriteBlifUtil.c]
+
+  Author      [ Sunil P. Khatri ]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ioInt.h"
+
+static char rcsid[] UNUSED = "$Id: ioWriteBlifIo.c,v 1.13 2005/05/14 02:15:22 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void _IoEncodeWriteVariable(Var_Variable_t *var, FILE *encFp, int varIsOutput, st_table *encOutputsStTable, st_table *encInputsStTable);
+static void _IoEncodeWriteVariableSpecial(Var_Variable_t *var, FILE *encFp, int varIsOutput, st_table *encOutputsStTable, st_table *encInputsStTable);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+    
+/**Function***********************************************************
+
+  Synopsis	[ Writes out mv->binary encoding tables  for relevant variables]
+
+  Description	[ ]
+
+  SideEffects	[ ]
+
+  SeeAlso	[  ]
+************************************************************************/
+void
+IoEncWriteMvToBinTables(
+  Hrc_Node_t *hnode, 
+  FILE *encFp, 
+  st_table *encOutputsStTable, 
+  st_table *encInputsStTable,
+  int combinationalOnly
+  )
+{
+  int i;
+  Var_Variable_t *var;
+  st_generator *gen;
+  char *childname;
+  Hrc_Node_t *childnode;
+  
+  /* latch IOs encoding tables not handled here */
+  /* if a PI or SO drives a latch, then in the combinational case, this
+     PI is not encoded (since the (mv) latch will be reinstated after
+     sis optimization. In the non-comvinational case ("wl" or "wl -l")
+     every PI and SO is encoded. 
+  */
+  if(combinationalOnly){
+    Hrc_NodeForEachFormalInput(hnode, i, var){
+      if(!((Var_VariableReadNumFanoutTables(var) == 0))){
+	_IoEncodeWriteVariable(var, encFp, 0, encOutputsStTable, encInputsStTable);
+      }
+    }
+    Hrc_NodeForEachChild(hnode, gen, childname, childnode){
+      Hrc_NodeForEachActualOutput(childnode, i, var){
+	if(!((Var_VariableReadNumFanoutTables(var) == 0))){
+	  _IoEncodeWriteVariable(var, encFp, 0, encOutputsStTable, encInputsStTable);
+	}
+      }
+    }
+  }
+  else{
+    Hrc_NodeForEachFormalInput(hnode, i, var){
+      _IoEncodeWriteVariable(var, encFp, 0, encOutputsStTable, encInputsStTable);
+    }
+    Hrc_NodeForEachChild(hnode, gen, childname, childnode){
+      Hrc_NodeForEachActualOutput(childnode, i, var){
+	_IoEncodeWriteVariable(var, encFp, 0, encOutputsStTable, encInputsStTable);
+      }
+    }
+  }
+}
+
+/**Function***********************************************************
+
+  Synopsis	[ Writes out binary->mv  decoding tables  for relevant variables]
+
+  Description	[ ]
+
+  SideEffects	[ ]
+
+  SeeAlso	[  ]
+************************************************************************/
+void
+IoEncWriteBinToMvTables(
+  Hrc_Node_t *hnode, 
+  FILE *encFp, 
+  st_table *encOutputsStTable, 
+  st_table *encInputsStTable,
+  int combinationalOnly,
+  int makeLatchIOsPOs
+  )
+{
+  int i;
+  Var_Variable_t *var;
+  st_generator *gen;
+  char *childname;
+  Hrc_Node_t *childnode;
+
+  /* latch IOs encoding tables not handled here */
+  /* if a PO or SI is driven by a latch, then in the combinational case, this
+     var is not encoded (since the (mv) latch will be reinstated after
+     sis optimization. In case of "wl -l" the same applies, since we are sure
+     to be able to reinstate teh mv latch after sis optimization. However, in "wl" 
+     every PI and SO is encoded since we are not sure  that mv latches can be 
+     reinstated after sis optimization. Similarly, if teh PO or SI is a PI/SO  
+     then no encoding is needed in all cases (comb or non-comb)
+  */
+  /*  if(combinationalOnly || makeLatchIOsPOs){ */
+  /* The above line was changed since "wl -l" now writes out latches such that
+     they drive a buffer node. As a result, even if a PO or SI is driven by the 
+     latch, the PO/SI needs bin-mv tables 
+  */
+  if(combinationalOnly){ 
+    Hrc_NodeForEachFormalOutput(hnode, i, var){
+      if(!((Var_VariableTestIsSO(var) || Var_VariableTestIsPI(var) ||
+	    Var_VariableTestIsPS(var)))){
+	_IoEncodeWriteVariable(var, encFp, 1, encOutputsStTable, encInputsStTable);
+      }
+    }
+    Hrc_NodeForEachChild(hnode, gen, childname, childnode){
+      Hrc_NodeForEachActualInput(childnode, i, var){
+	if(!((Var_VariableTestIsSO(var) || Var_VariableTestIsPI(var) ||
+	      Var_VariableTestIsPS(var)))){
+	  _IoEncodeWriteVariable(var, encFp, 1, encOutputsStTable, encInputsStTable);
+	}
+      }
+    }
+  }
+  else{
+    Hrc_NodeForEachFormalOutput(hnode, i, var){
+      if(!((Var_VariableTestIsSO(var) || Var_VariableTestIsPI(var)))){
+        _IoEncodeWriteVariable(var, encFp, 1, encOutputsStTable, encInputsStTable);
+      }
+    }
+    Hrc_NodeForEachChild(hnode, gen, childname, childnode){
+      Hrc_NodeForEachActualInput(childnode, i, var){
+        if(!((Var_VariableTestIsSO(var) || Var_VariableTestIsPI(var)))){
+          _IoEncodeWriteVariable(var, encFp, 1, encOutputsStTable, encInputsStTable);
+        }
+      }
+    }
+  }
+}
+
+/**Function***********************************************************
+
+  Synopsis	[ Writes out .input line for blif file]
+
+  Description	[ ]
+
+  SideEffects	[ ]
+
+  SeeAlso	[  ]
+************************************************************************/
+ int
+IoBlifWriteInputs(
+  Hrc_Node_t *hnode, 
+  FILE *fp, 
+  st_table *blifInputsStTable,
+  int combinationalOnly,
+  int makeLatchIOsPOs
+  )
+{
+  int i, j, k, numVal, numEncBits, numInputsWritten;
+  Tbl_Table_t *table;
+  st_generator *gen;
+  Var_Variable_t *var;
+  char *name, *dupName, *varName;
+  boolean test;
+  
+  numInputsWritten = 0;
+  fprintf(fp,".inputs ");     
+  Hrc_NodeForEachNameTable(hnode, i, table){
+    Tbl_TableForEachInputVar(table, k, var){
+      if(combinationalOnly){
+	test = Var_VariableTestIsPS(var) || Var_VariableTestIsSO(var) || Var_VariableTestIsPI(var);
+      }
+      else{
+	test = Var_VariableTestIsSO(var) || Var_VariableTestIsPI(var);
+      }
+      if(test){
+	name = Var_VariableReadName(var);
+	numVal = Var_VariableReadNumValues(var);
+	numEncBits = IoNumEncBits(numVal);
+	for(j=0; j<numEncBits; j++){
+	  dupName = ALLOC(char, strlen(name) + IoNumDigits(numEncBits) + 2);
+	  sprintf(dupName, "%s%d", name, j);
+	  if(!st_is_member(blifInputsStTable, (char *)dupName)){
+	    fprintf(fp,"%s ",dupName);
+	    numInputsWritten++;
+	    st_insert(blifInputsStTable, (char *)dupName, (char *)1);
+	  }
+	  else{
+	    FREE(dupName);
+	  }
+	}
+      }
+    }
+  }
+  if(!combinationalOnly){
+    Hrc_NodeForEachVariable(hnode, gen, varName, var){
+      if(Var_VariableTestIsPI(var)){
+	name = Var_VariableReadName(var);
+	numVal = Var_VariableReadNumValues(var);
+	numEncBits = IoNumEncBits(numVal);
+	for(j=0; j<numEncBits; j++){
+	  dupName = ALLOC(char, strlen(name) + IoNumDigits(numEncBits) + 2);
+	  sprintf(dupName, "%s%d", name, j);
+	  if(!st_is_member(blifInputsStTable, (char *)dupName)){
+	    fprintf(fp,"%s ",dupName);
+	    numInputsWritten++;
+	    st_insert(blifInputsStTable, (char *)dupName, (char *)1);
+	  }
+	  else{
+	    FREE(dupName);
+	  }
+	}
+      }
+    }
+  }
+  return numInputsWritten;
+}
+
+
+/**Function***********************************************************
+
+  Synopsis	[ Writes out .output line for blif file]
+
+  Description	[ ]
+
+  SideEffects	[ ]
+
+  SeeAlso	[  ]
+************************************************************************/
+ int
+IoBlifWriteOutputs(
+  Hrc_Node_t *hnode, 
+  FILE *fp,
+  st_table *blifOutputsStTable,
+  int combinationalOnly,
+  int makeLatchIOsPOs
+  )
+{
+  int i, j, k, numVal, numEncBits, numOutputsWritten;
+  Tbl_Table_t *table;
+  st_generator *gen;
+  Var_Variable_t *var;
+  char *name, *dupName, *varName;
+  boolean test;
+
+  numOutputsWritten = 0;
+  fprintf(fp,"\n.outputs "); 
+  Hrc_NodeForEachNameTable(hnode, i, table){
+    Tbl_TableForEachOutputVar(table, k, var){
+      if(combinationalOnly){
+	test = Var_VariableTestIsNS(var) || Var_VariableTestIsSI(var) || Var_VariableTestIsPO(var);
+      }
+      else{
+	test = Var_VariableTestIsSI(var) || Var_VariableTestIsPO(var);
+      }
+      if(test){
+	name = Var_VariableReadName(var);
+	numVal = Var_VariableReadNumValues(var);
+	numEncBits = IoNumEncBits(numVal);
+	for(j=0; j<numEncBits; j++){
+	  dupName = ALLOC(char, strlen(name) + IoNumDigits(numEncBits) + 2);
+	  sprintf(dupName, "%s%d", name, j);
+	  if(!st_is_member(blifOutputsStTable, (char *)dupName)){
+	    fprintf(fp,"%s ",dupName);
+	    numOutputsWritten++;
+	    st_insert(blifOutputsStTable, (char *)dupName, (char *)1);
+	  }
+          else{
+	    FREE(dupName);
+	  }
+	}
+      }
+    }
+  }
+  if(!combinationalOnly){
+    Hrc_NodeForEachVariable(hnode, gen, varName, var){
+      if(Var_VariableTestIsPO(var) && Var_VariableTestIsPS(var)){
+	name = Var_VariableReadName(var);
+	numVal = Var_VariableReadNumValues(var);
+	numEncBits = IoNumEncBits(numVal);
+	for(j=0; j<numEncBits; j++){
+	  dupName = ALLOC(char, strlen(name) + IoNumDigits(numEncBits) + 2);
+	  sprintf(dupName, "%s%d", name, j);
+	  if(!st_is_member(blifOutputsStTable, (char *)dupName)){
+	    fprintf(fp,"%s ",dupName);
+	    numOutputsWritten++;
+	    st_insert(blifOutputsStTable, (char *)dupName, (char *)1);
+	  }
+	  else{
+	    FREE(dupName);
+	  }
+	}
+      }
+    }
+  }
+  fprintf(fp,"\n");
+  return numOutputsWritten;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Writes out latches to the blif file]
+
+  Description [ ] 
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+IoWriteLatches(
+   Hrc_Node_t *hnode,
+   FILE *fp,	      
+   FILE *encFp,
+   st_table *printedMvsStTable,	       
+   st_table *blifOutputsStTable,	       
+   st_table *blifInputsStTable,
+   st_table *encOutputsStTable,	       
+   st_table *encInputsStTable,
+   int combinationalOnly,
+   int makeLatchIOsPOs,
+   int verbosity
+   )
+{
+  Hrc_Latch_t *latch;
+  st_generator *gen;
+  char *varName, *latchName, *inputVarName, *outputVarName;
+  char *latchInName, *latchOutName, *dupName;
+  Var_Variable_t *outputVar, *inputVar, *var;
+  Tbl_Table_t *resetTable;
+  boolean test;
+  int i, j, index, tempResetValue, resetValue, numEncBits, numVal;
+  st_table *encodedResetVarsStTable;
+
+    mdd_manager *mddMgr;
+    Ntk_Node_t *ntkLatch, *ntkCombInput, *latchResetNtkNode;
+    Ntk_Network_t *network;
+    st_table *tableOfLeaves;
+    array_t *singletonArrayOfRoots, *singletonMvfArray;
+    Mvf_Function_t *mvf;
+    lsGen listGen;
+    Hrc_Manager_t *HrcMgr;
+
+  /* stuff for doing reset table constantness check. Needs to do a "flt -b", "ord"
+     and create a leaves table for mvf computation later.
+  */
+  mddMgr = mdd_init_empty();
+  bdd_dynamic_reordering(mddMgr, BDD_REORDER_SIFT,BDD_REORDER_VERBOSITY_DEFAULT);
+
+  HrcMgr = Hrc_NodeReadManager(hnode);
+  Hrc_ManagerSetCurrentNode(HrcMgr, hnode);
+  
+  network = Ntk_HrcNodeConvertToNetwork(hnode, TRUE, (lsList) NULL);
+  Ord_NetworkOrderVariables(network, Ord_RootsByDefault_c, Ord_NodesByDefault_c, 0, Ord_InputAndLatch_c, Ord_Unassigned_c, (lsList) NULL, 0);
+  tableOfLeaves = st_init_table(st_ptrcmp, st_ptrhash);
+  Ntk_NetworkForEachCombInput(network, listGen, ntkCombInput) {
+    st_insert(tableOfLeaves, (char *)ntkCombInput, (char *) (long) (-1) );
+  }
+
+  encodedResetVarsStTable = st_init_table(strcmp, st_strhash);
+  Hrc_NodeForEachLatch(hnode, gen, latchName, latch){
+    inputVar = Hrc_LatchReadInput(latch);
+    outputVar = Hrc_LatchReadOutput(latch);
+    inputVarName = Var_VariableReadName(inputVar);
+    outputVarName = Var_VariableReadName(outputVar);
+    resetTable = Hrc_LatchReadResetTable(latch);
+    
+    IoMvCheckPrint(encFp,inputVar,printedMvsStTable);
+    /* if makeLatchIOsPOs, then the .mv statement should have "_bufin" appended to the 
+       variable names */
+    if(makeLatchIOsPOs){
+      IoMvCheckPrintSpecial(encFp,outputVar,printedMvsStTable);
+    }
+    else{
+      IoMvCheckPrint(encFp,outputVar,printedMvsStTable);
+    }
+	  
+    
+    /* Write bin2mv table for input var if needed */
+    /* if makeLatchIOsPOs, then the test for writing the bin2mv table should not include 
+       a check to see if the var is a PS. This was previously required, since in hte case
+       where a latchOutput drove a latchInput, we wanted to reinstate both mv latches after
+       read_blif, and so didnt need any enc/dec tables. However, if makeLatchIOsPOs, then we
+       will insert a buffer after latches, so enc/dec tables _will_ be needed. 
+    */
+    if(makeLatchIOsPOs){
+      if(!IoVarIsHnodePIO(hnode, inputVar)){
+	if(!st_is_member(encodedResetVarsStTable, (char *)Var_VariableReadName(inputVar))){
+	  _IoEncodeWriteVariable(inputVar, encFp, 1, encOutputsStTable, encInputsStTable);
+	  st_insert(encodedResetVarsStTable, (char *)Var_VariableReadName(inputVar), (char *)1);
+	}
+      }
+    }
+    else{      
+      if(!IoVarIsHnodePIO(hnode, inputVar) && !Var_VariableTestIsPS(inputVar)){
+	if(!st_is_member(encodedResetVarsStTable, (char *)Var_VariableReadName(inputVar))){
+	  _IoEncodeWriteVariable(inputVar, encFp, 1, encOutputsStTable, encInputsStTable);
+	  st_insert(encodedResetVarsStTable, (char *)Var_VariableReadName(inputVar), (char *)1);
+	}
+      }
+    }
+    
+    /* Write mv2bin table for output var if needed */
+    /* if makeLatchIOsPOs, then the enc tables should have "_bufin" appended to the 
+       names. This is a hack, and I dont insert this name in the table since it does
+       not correspond to a real name in the hrc node.
+    */
+    if(makeLatchIOsPOs){
+      _IoEncodeWriteVariableSpecial(outputVar, encFp, 0, encOutputsStTable, encInputsStTable);  
+    }
+    else{      
+      if(!(Var_VariableReadNumFanoutTables(outputVar) == 0)){
+	if(!st_is_member(encodedResetVarsStTable, (char *)Var_VariableReadName(outputVar))){
+	  _IoEncodeWriteVariable(outputVar, encFp, 0, encOutputsStTable, encInputsStTable);    
+	  st_insert(encodedResetVarsStTable, (char *)Var_VariableReadName(outputVar), (char *)1);
+	}
+      }
+    }
+    /* Write latch IOs as POs if the "-l" option was used */
+    if(makeLatchIOsPOs){
+      /* 
+	 first deal with inputVar - check if it has been printed to 
+	 blif file in binary form, by looking up blifInputsStTable
+      */
+      numVal = Var_VariableReadNumValues(inputVar);
+      numEncBits = IoNumEncBits(numVal);
+      for(j=0; j<numEncBits; j++){
+	dupName = ALLOC(char, strlen(inputVarName) + IoNumDigits(numEncBits) + 2);
+	sprintf(dupName, "%s%d", inputVarName, j);
+	if(!st_is_member(blifInputsStTable, (char *)dupName)){
+	  fprintf(fp,".outputs %s\n",dupName);
+	  st_insert(blifInputsStTable, (char *)dupName, (char *)1);
+	}
+	else{
+	  FREE(dupName);
+	}
+      }
+      /* 
+	 next deal with outputVar - check if it has been printed to 
+	 blif file in binary form, by looking up blifOutputsStTable
+      */
+      numVal = Var_VariableReadNumValues(outputVar);
+      numEncBits = IoNumEncBits(numVal);
+      for(j=0; j<numEncBits; j++){
+	dupName = ALLOC(char, strlen(outputVarName) + IoNumDigits(numEncBits) + 2);
+	sprintf(dupName, "%s%d", outputVarName, j);
+	if(!st_is_member(blifOutputsStTable, (char *)dupName)){
+	  fprintf(fp,".outputs %s\n",dupName);
+	  st_insert(blifOutputsStTable, (char *)dupName, (char *)1);
+	}
+	else{
+	  FREE(dupName);
+	}
+      }
+    }
+
+    /* handle reset tables (all cases "wl -c", "wl -l", and "wl")*/
+    Tbl_TableForEachInputVar(resetTable, index, var){
+      if(!IoVarIsHnodePIO(hnode, var)){
+	IoMvCheckPrint(encFp, var,printedMvsStTable);
+      }
+      /* dont encode if (comb&ps) or (makeLatchIOsPOs&ps) */
+      /*      if(!((combinationalOnly || makeLatchIOsPOs) && Var_VariableTestIsPS(var))){ */
+      /* since we insert a buffer after each latch whenever makeLatchIOsPOs, there will
+	 be a need for a bin2mv table for the latch output var. Previously, it was assumed
+	 that when the mv latch will replace the bin latches, there will be no need for a
+	 bin2mv table since the mv latch was directly driving the reset table.
+      */
+      if(!(combinationalOnly && Var_VariableTestIsPS(var))){ 
+	/* if var is a PI or SO, then mv->bin tables exist for it, so dont 
+	   make bin->mv tables since the mv variable will exist anyway 
+        */
+	if(!Var_VariableTestIsPI(var) && !Var_VariableTestIsSO(var)){
+	  if(!st_is_member(encodedResetVarsStTable, (char *)Var_VariableReadName(var))){
+	    _IoEncodeWriteVariable(var, encFp, 1, encOutputsStTable, encInputsStTable);
+	    st_insert(encodedResetVarsStTable, (char *)Var_VariableReadName(var), (char *)1);
+	  }
+	}
+      }
+      /*
+         if we are doing "wl -c" and there is a resetTable input var
+	 which is also a PS which does not have fanout tbls, then this 
+	 variable will not be encoded and listed in the blif file.
+	 Hence such a variable should not be encoded and listed in teh 
+         blif file as a PO, since it will have no driving tables.
+      */
+      if(!(combinationalOnly && Var_VariableTestIsPS(var) && 
+	 (Var_VariableReadNumFanoutTables(var) == 0))){
+	/* 
+	   write encoded vars as outputs after checking that they havent 
+	   already been written as outputs or inputs to the blif file
+        */
+	varName = Var_VariableReadName(var);
+	numVal = Var_VariableReadNumValues(var);
+	numEncBits = IoNumEncBits(numVal);
+	for(j=0; j<numEncBits; j++){
+	  dupName = ALLOC(char, strlen(varName) + IoNumDigits(numEncBits) + 2);
+	  sprintf(dupName, "%s%d", varName, j);
+	  if(!st_is_member(blifInputsStTable, (char *)dupName) && !st_is_member(blifOutputsStTable, (char *)dupName)){
+	    fprintf(fp,".outputs %s\n",dupName);
+	    st_insert(blifOutputsStTable, (char *)dupName, (char *)1);
+	  }
+	  else{
+	    FREE(dupName);
+	  }
+	}
+      }
+    }
+  }
+
+  /* write latch stmts to blif file */
+  Hrc_NodeForEachLatch(hnode, gen, latchName, latch){
+    inputVar = Hrc_LatchReadInput(latch);
+    outputVar = Hrc_LatchReadOutput(latch);
+    inputVarName = Var_VariableReadName(inputVar);
+    outputVarName = Var_VariableReadName(outputVar);
+    resetTable = Hrc_LatchReadResetTable(latch);
+    /* write out mv latches to enc file, they are needed even if we are 
+       writing only combinational part of the network */
+    /* if makeLatchIOsPOs, then append "_bufin" to the output name, since latch 
+       outputs are buffered. Also, reset table should reflect this new name.
+    */
+    if(makeLatchIOsPOs){
+      (void)fprintf(encFp, ".latch %s %s_bufin \n", inputVarName, outputVarName);	    
+      Tbl_TableWriteBlifMvToFileSpecial(resetTable, 1, encFp);
+    }
+    else{
+      (void)fprintf(encFp, ".latch %s %s \n", inputVarName, outputVarName);	    
+      Tbl_TableWriteBlifMvToFile(resetTable, 1, encFp);
+    }      
+    
+    /* determine value of reset table - whether const, or not */
+    if(!combinationalOnly){      
+      ntkLatch = Ntk_NetworkFindNodeByName(network, latchName);
+      assert(Ntk_NodeTestIsLatch(ntkLatch));
+      latchResetNtkNode = Ntk_LatchReadInitialInput(ntkLatch);
+      singletonArrayOfRoots = array_alloc(Ntk_Node_t *, 0);
+      array_insert_last(Ntk_Node_t *, singletonArrayOfRoots, latchResetNtkNode);
+      singletonMvfArray = Ntm_NetworkBuildMvfs(network, singletonArrayOfRoots, tableOfLeaves, NIL(mdd_t));
+      mvf = array_fetch(Mvf_Function_t *, singletonMvfArray, 0);
+      array_free(singletonMvfArray);
+      array_free(singletonArrayOfRoots);
+      test = Mvf_FunctionTestIsConstant(mvf, &resetValue);
+      Mvf_FunctionFree(mvf);
+      if(verbosity > 1){
+	(void)fprintf(stdout, "Reset table is: \n");                
+	Tbl_TableWriteBlifMvToFile(resetTable, 0, stdout);
+      }
+      if(verbosity > 0){
+	(void)fprintf(stdout, "Reset table constantness test result was %d\n", test);          
+      }
+      if(test == FALSE){
+	resetValue = VIS_INFINITY;
+      }
+      if(verbosity > 0){
+	fprintf(stdout, "Reset value %d\n", resetValue);
+      }
+      
+      /* write latches to blif file */
+      numEncBits = IoNumEncBits(Var_VariableReadNumValues(inputVar));
+      if(resetValue == VIS_INFINITY){
+	for(i = 0; i < numEncBits; i++){
+	  resetValue = 2;
+	  latchInName = ALLOC(char, strlen(inputVarName) + IoNumDigits(numEncBits) + 2);
+	  latchOutName = ALLOC(char, strlen(outputVarName) + IoNumDigits(numEncBits) + 10); 
+	  sprintf(latchInName, "%s%d", inputVarName, i);
+	  /* if makelatchIOsPOs, then latch drives buffer input, and buffer needs to be 
+             be written to the blif file too
+          */
+	  if(makeLatchIOsPOs){
+	    sprintf(latchOutName, "%s_bufin%d", outputVarName, i);
+	  }
+	  else{
+	    sprintf(latchOutName, "%s%d", outputVarName, i);
+	  }
+	  (void)fprintf(fp, ".latch %s %s %d\n", latchInName, latchOutName, resetValue);
+	  if(makeLatchIOsPOs){
+	    (void)fprintf(fp, ".names %s %s%d\n", latchOutName, outputVarName, i);
+	    (void)fprintf(fp, "1 1\n");
+	  }
+	  FREE(latchInName);
+	  FREE(latchOutName);
+	}
+      }
+      else{
+	tempResetValue = resetValue;
+	for(i = numEncBits - 1; i >= 0; i--){
+	  if(((int)(tempResetValue / pow((double) 2, (double) i))) == 1){
+	    resetValue = 1;
+	    tempResetValue = tempResetValue - (int)pow((double)2,(double)i);	    
+	  }
+	  else{
+	    resetValue = 0;
+	  }
+	  latchInName = ALLOC(char, strlen(inputVarName) + IoNumDigits(numEncBits) + 2);
+	  latchOutName = ALLOC(char, strlen(outputVarName) + IoNumDigits(numEncBits) + 10); 
+	  sprintf(latchInName, "%s%d", inputVarName, i);
+	  /* if makelatchIOsPOs, then latch drives buffer input, and buffer needs to be 
+             be written to the blif file too.
+          */
+	  if(makeLatchIOsPOs){
+	    sprintf(latchOutName, "%s_bufin%d", outputVarName, i);
+	  }
+	  else{
+	    sprintf(latchOutName, "%s%d", outputVarName, i);
+	  }	    
+	  (void)fprintf(fp, ".latch %s %s %d\n", latchInName, latchOutName, resetValue);
+	  if(makeLatchIOsPOs){
+	    (void)fprintf(fp, ".names %s %s%d\n", latchOutName, outputVarName, i);
+	    (void)fprintf(fp, "1 1\n");
+	  }
+	  FREE(latchInName);
+	  FREE(latchOutName);
+	}
+      }
+    }
+  }
+  st_free_table(encodedResetVarsStTable);
+  st_free_table(tableOfLeaves);
+  Ntk_NetworkFree(network);
+  mdd_quit(mddMgr);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the .mv declaration of a variable, to file, if it is not in the 
+               st_table variables already printed]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+IoMvCheckPrint(
+   FILE *fp, 
+   Var_Variable_t *var,
+   st_table *printedMvsStTable
+  )
+{
+    char *varname, *tmpName;
+
+    tmpName = Var_VariableReadName(var);
+    varname = ALLOC(char, strlen(tmpName) + 2);
+    sprintf(varname, "%s", tmpName);
+    if(!st_is_member(printedMvsStTable, (char *)varname)){
+	st_insert(printedMvsStTable, (char *)varname, (char *)1);
+	IoMvPrint(fp, var);
+    }
+    else{
+        FREE(varname);
+    }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the .mv declaration of a variable, to file, if it is not in the 
+               st_table variables already printed. Appends a special string "_bufin"
+	       at the end of the name.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+IoMvCheckPrintSpecial(
+   FILE *fp, 
+   Var_Variable_t *var,
+   st_table *printedMvsStTable
+  )
+{
+    char *varname, *tmpName;
+
+    tmpName = Var_VariableReadName(var);
+    varname = ALLOC(char, strlen(tmpName) + 10);
+    sprintf(varname, "%s_bufin", tmpName);
+    if(!st_is_member(printedMvsStTable, (char *)varname)){
+	st_insert(printedMvsStTable, (char *)varname, (char *)1);
+	IoMvPrintSpecial(fp, var);
+    }
+    else{
+        FREE(varname);
+    }
+}
+
+    
+/**Function********************************************************************
+
+  Synopsis    [Writes a blifmv value, in expanded form, into binTable]
+
+  Description [Writes the binary value corresponding to "value" in the binTable
+               starting from the rootRow, rootCol entry. The values are repeated
+	       "entryRepetitionCount" times]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+ int
+IoWriteExpandedValueToBinTable( 
+   Tbl_Table_t *binTable,
+   int rootRow,
+   int rootCol,
+   IoBinRangeEntry_t *binRangeEntry,
+   int entryRepetitionCount,
+   int numBits,
+   int output
+   )
+{
+    int i, j, row, value, numDash, end;
+    Tbl_Entry_t *entry;
+
+    numDash = IoLog(binRangeEntry->runLength);
+    end = IoLog(binRangeEntry->skipLength);
+    value = binRangeEntry->startValue;
+    for(j = numBits - 1; j >= 0; j--){
+      row = rootRow;
+	if((j < end) || (j >= numDash + end)){
+	    if(((int)(value / pow((double) 2, (double) j))) == 1){
+		for(i = 0; i < entryRepetitionCount; i++){
+		    entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+		    Tbl_EntrySetValue(entry, 1, 1);
+		    Tbl_TableSetEntry(binTable, entry, row++, rootCol+j, output);
+		}
+		value -= (int)pow((double)2,(double)j);
+	    }
+	    else{
+		for(i = 0; i < entryRepetitionCount; i++){
+		    entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+		    Tbl_EntrySetValue(entry, 0, 0);
+		    Tbl_TableSetEntry(binTable, entry, row++, rootCol+j, output);
+		}
+	    }
+	}
+	else{
+	    for(i = 0; i < entryRepetitionCount; i++){
+		entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+		Tbl_EntrySetValue(entry, 0, 1);
+		Tbl_TableSetEntry(binTable, entry, row++, rootCol+j, output);
+	    }
+	}
+    }
+    return 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes out tables in binTblArray to a named blif file]
+
+  Description [Writes out binary tables in the binTblArray to 
+               blif file pointed to by fp]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+IoWriteBinTablesToFile( 
+   IoBlifInfo_t *blifInfo	       		      
+   )
+{
+    int i, colnum, rownum, value, hasZeroRows;
+    Tbl_Table_t *table;
+    Var_Variable_t *outputVar, *dupOutputVar;
+    char *outputVarName;
+    Tbl_Entry_t *entry;
+    Tbl_Range_t *range;
+    lsGen gen;
+
+    for(i = 0; i < array_n(blifInfo->binTblArray); i++){
+	table = array_fetch(Tbl_Table_t *, blifInfo->binTblArray, i);
+   /* if table has zero rows, print it as ".names <var>" */
+	hasZeroRows = 1;
+	Tbl_TableForEachOutputEntry(table, colnum, rownum, entry){
+	    Tbl_EntryForEachValue(entry, value, gen, range){
+		if(value == 1){
+		    hasZeroRows = 0;
+		}
+	    }
+	}
+	if(hasZeroRows){
+	    outputVar = Tbl_TableReadIndexVar(table, 0, 1);
+	    table = Tbl_TableAlloc();
+	    outputVarName = Var_VariableReadName(outputVar);
+	    dupOutputVar = Var_VariableAlloc(NIL(Hrc_Node_t), outputVarName);
+	    (void)Tbl_TableAddColumn(table, dupOutputVar, 1);
+	    Tbl_TableWriteBlifToFile(table, blifInfo->BlifFp); 
+	    Tbl_TableFree(table);
+	    Var_VariableFree(dupOutputVar);
+	}
+	else{
+	    Tbl_TableWriteBlifToFile(table, blifInfo->BlifFp); 
+	}
+    }
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Encodes individual variable based on its ranges, and writes to the file called
+               "encoding"]
+
+  Description []
+
+  SideEffects [Program state is not changed]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+_IoEncodeWriteVariable(
+   Var_Variable_t *var,
+   FILE *encFp,		      
+   int varIsOutput,
+   st_table *encOutputsStTable, 
+   st_table *encInputsStTable
+   )
+{
+    int j, i, tempI, range, numEncBits, rownum, varIsInput;
+    Tbl_Table_t *encTable;
+    char *varname, *dupName;
+    Var_Variable_t *encVar;
+    Tbl_Entry_t *entry;
+    array_t *varArray;
+
+    if(varIsOutput == 1){
+	varIsInput = 0;
+    }
+    else{
+	varIsInput = 1;
+    }
+
+    if(varIsOutput){
+	if(st_is_member(encOutputsStTable, (char *)var)){
+	    return;
+	}
+	else{
+	    st_insert(encOutputsStTable, (char *) var, (char *) 1);
+	}
+    }
+    else{
+	if(st_is_member(encInputsStTable, (char *)var)){
+	    return;
+	}
+	else{
+	    st_insert(encInputsStTable, (char *) var, (char *) 1);
+	}
+    }
+	    
+
+        /* declare encoding input vars based on range. These are associated
+           with their encoding table. These have names <var>0, <var>1, ...  */
+
+    varArray = array_alloc(Var_Variable_t *, 0);
+    range = Var_VariableReadNumValues(var);
+    numEncBits = IoNumEncBits(range);
+    /* create encoding table */
+    encTable = Tbl_TableAlloc();
+    varname = Var_VariableReadName(var);
+    for(i=0; i<numEncBits; i++){
+	dupName = ALLOC(char, strlen(varname) + IoNumDigits(numEncBits) + 2);
+	sprintf(dupName, "%s%d", varname, i);
+	encVar = Var_VariableAlloc(NIL(Hrc_Node_t), dupName);
+	FREE(dupName);
+	array_insert_last(Var_Variable_t *, varArray, encVar);
+	(void) Tbl_TableAddColumn(encTable, encVar, varIsInput);
+    }
+
+        /* declare output var for the encoding table. It is called <var>     */
+
+    (void) Tbl_TableAddColumn(encTable, var, varIsOutput);
+    
+        /* fill in entries of the variable encoding table. Assign codes based on 
+           the variable's index. Nothing fancy here...                        */
+
+    for(i=0; i<range; i++){    
+	tempI = i;
+ 	rownum = Tbl_TableAddRow(encTable);
+	for(j = numEncBits - 1; j >= 0; j--){
+	    if(((int)(tempI / pow((double) 2, (double) j))) == 1){
+		entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+		Tbl_EntrySetValue(entry, 1, 1);
+		Tbl_TableSetEntry(encTable, entry, rownum, j, varIsInput);
+		tempI = tempI - (int)pow((double)2,(double)j);
+	    }
+	    else{
+		entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+		Tbl_EntrySetValue(entry, 0, 0);
+		Tbl_TableSetEntry(encTable, entry, rownum, j, varIsInput);
+	    }
+	}
+	entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+	Tbl_EntrySetValue(entry, i, i);
+	Tbl_TableSetEntry(encTable, entry, rownum, 0, varIsOutput);
+    }
+    /* make sure not inc specced if var is output */
+    if(varIsOutput){
+	for(i = range; i < ((int) pow((double)2, (double)numEncBits)); i++){
+	    tempI = i;
+	    rownum = Tbl_TableAddRow(encTable);
+	    for(j = numEncBits - 1; j >= 0; j--){
+		if(((int)(tempI / pow((double) 2, (double) j))) == 1){
+		    entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+		    Tbl_EntrySetValue(entry, 1, 1);
+		    Tbl_TableSetEntry(encTable, entry, rownum, j, varIsInput);
+		    tempI = tempI - (int)pow((double)2,(double)j);
+		}
+		else{
+		    entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+		    Tbl_EntrySetValue(entry, 0, 0);
+		    Tbl_TableSetEntry(encTable, entry, rownum, j, varIsInput);
+		}
+	    }
+	    entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+	    Tbl_EntrySetValue(entry, 0, 0);
+	    Tbl_TableSetEntry(encTable, entry, rownum, 0, varIsOutput);
+	}
+    }
+    
+    
+    /* store the var, var number, and its table in the encTblArray. */
+    
+    Tbl_TableWriteBlifMvToFile(encTable, 0, encFp);
+    Tbl_TableFree(encTable);
+
+    for(i=0; i < array_n(varArray); i++){
+	Var_VariableFree(array_fetch(Var_Variable_t *, varArray, i));
+    }
+    array_free(varArray);
+
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Encodes individual variable based on its ranges. Variable name has
+               the string "_bufin" appended to it.]
+
+  Description []
+
+  SideEffects [Program state is not changed]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+_IoEncodeWriteVariableSpecial(
+   Var_Variable_t *var,
+   FILE *encFp,		      
+   int varIsOutput,
+   st_table *encOutputsStTable, 
+   st_table *encInputsStTable
+   )
+{
+    int j, i, tempI, range, numEncBits, rownum, varIsInput;
+    Tbl_Table_t *encTable;
+    char *varname, *dupName;
+    Var_Variable_t *encVar, *outVar;
+    Tbl_Entry_t *entry;
+    array_t *varArray, *symValArray;
+
+    if(varIsOutput == 1){
+	varIsInput = 0;
+    }
+    else{
+	varIsInput = 1;
+    }
+
+    if(varIsOutput){
+	if(st_is_member(encOutputsStTable, (char *)var)){
+	    return;
+	}
+	else{
+	    st_insert(encOutputsStTable, (char *) var, (char *) 1);
+	}
+    }
+    else{
+	if(st_is_member(encInputsStTable, (char *)var)){
+	    return;
+	}
+	else{
+	    st_insert(encInputsStTable, (char *) var, (char *) 1);
+	}
+    }
+	    
+
+        /* declare encoding input vars based on range. These are associated
+           with their encoding table. These have names <var>0, <var>1, ...  */
+
+    varArray = array_alloc(Var_Variable_t *, 0);
+    range = Var_VariableReadNumValues(var);
+    numEncBits = IoNumEncBits(range);
+    /* create encoding table */
+    encTable = Tbl_TableAlloc();
+    varname = Var_VariableReadName(var);
+    for(i=0; i<numEncBits; i++){
+	dupName = ALLOC(char, strlen(varname) + IoNumDigits(numEncBits) + 10);
+	sprintf(dupName, "%s_bufin%d", varname, i);
+	encVar = Var_VariableAlloc(NIL(Hrc_Node_t), dupName);
+	FREE(dupName);
+	array_insert_last(Var_Variable_t *, varArray, encVar);
+	(void) Tbl_TableAddColumn(encTable, encVar, varIsInput);
+    }
+
+        /* declare output var for the encoding table. It is called <var>_bufin     */
+
+    varname = Var_VariableReadName(var);
+    dupName = ALLOC(char, strlen(varname) + 10);    
+    sprintf(dupName, "%s_bufin", varname);
+    outVar = Var_VariableAlloc(NIL(Hrc_Node_t), dupName);
+    array_insert_last(Var_Variable_t *, varArray, outVar);
+    FREE(dupName);
+    if(Var_VariableTestIsSymbolic(var)){
+      symValArray = array_alloc(char *, 0);
+      for(i = 0; i < range; i++){
+	array_insert_last(char *, symValArray, Var_VariableReadSymbolicValueFromIndex(var, i));
+      }
+      Var_VariableAddRangeInfo(outVar, range, symValArray);
+      array_free(symValArray);
+    }
+    else{
+      if(range > 2){
+	Var_VariableExpandRange(outVar, range);
+      }
+    }
+    (void) Tbl_TableAddColumn(encTable, outVar, varIsOutput);
+
+
+        /* fill in entries of the variable encoding table. Assign codes based on 
+           the variable's index. Nothing fancy here...                        */
+
+    for(i=0; i<range; i++){    
+	tempI = i;
+ 	rownum = Tbl_TableAddRow(encTable);
+	for(j = numEncBits - 1; j >= 0; j--){
+	    if(((int)(tempI / pow((double) 2, (double) j))) == 1){
+		entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+		Tbl_EntrySetValue(entry, 1, 1);
+		Tbl_TableSetEntry(encTable, entry, rownum, j, varIsInput);
+		tempI = tempI - (int)pow((double)2,(double)j);
+	    }
+	    else{
+		entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+		Tbl_EntrySetValue(entry, 0, 0);
+		Tbl_TableSetEntry(encTable, entry, rownum, j, varIsInput);
+	    }
+	}
+	entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+	Tbl_EntrySetValue(entry, i, i);
+	Tbl_TableSetEntry(encTable, entry, rownum, 0, varIsOutput);
+    }
+    /* make sure not inc specced if var is output */
+    if(varIsOutput){
+	for(i = range; i < ((int) pow((double)2, (double)numEncBits)); i++){
+	    tempI = i;
+	    rownum = Tbl_TableAddRow(encTable);
+	    for(j = numEncBits - 1; j >= 0; j--){
+		if(((int)(tempI / pow((double) 2, (double) j))) == 1){
+		    entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+		    Tbl_EntrySetValue(entry, 1, 1);
+		    Tbl_TableSetEntry(encTable, entry, rownum, j, varIsInput);
+		    tempI = tempI - (int)pow((double)2,(double)j);
+		}
+		else{
+		    entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+		    Tbl_EntrySetValue(entry, 0, 0);
+		    Tbl_TableSetEntry(encTable, entry, rownum, j, varIsInput);
+		}
+	    }
+	    entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+	    Tbl_EntrySetValue(entry, 0, 0);
+	    Tbl_TableSetEntry(encTable, entry, rownum, 0, varIsOutput);
+	}
+    }
+    
+    
+    /* store the var, var number, and its table in the encTblArray. */
+    
+    Tbl_TableWriteBlifMvToFile(encTable, 0, encFp);
+    Tbl_TableFree(encTable);
+
+    for(i=0; i < array_n(varArray); i++){
+	Var_VariableFree(array_fetch(Var_Variable_t *, varArray, i));
+    }
+    array_free(varArray);
+
+}
Index: vis_dev/vis-2.3/src/io/ioWriteBlifMv.c
===================================================================
--- vis_dev/vis-2.3/src/io/ioWriteBlifMv.c	(revision 14)
+++ vis_dev/vis-2.3/src/io/ioWriteBlifMv.c	(revision 14)
@@ -0,0 +1,211 @@
+/**CFile***********************************************************************
+
+  FileName    [ioWriteBlifMv.c]
+
+  PackageName [io]
+
+  Synopsis    [Writes out a blif-mv file.]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [Yuji Kukimoto]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ioInt.h"
+
+static char rcsid[] UNUSED = "$Id: ioWriteBlifMv.c,v 1.8 1998/09/24 00:07:34 hsv Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [The top-level routine for writing out a BLIF-MV file.]
+
+  Description [The top-level routine for writing out a blif-mv file.
+  The user has to check if the hmgr has a hierarchy read in before
+  calling this procedure.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+IoBlifMvWrite(
+  FILE *fp,
+  Hrc_Manager_t *hmgr)
+{ 
+  char *rootModelName;
+  Hrc_Model_t *model, *rootModel;
+  Hrc_Node_t *currentNode;
+  array_t *models;
+  int i;
+  boolean isRootModel;
+  char *rootInstanceName, *instanceName;
+  
+  currentNode = Hrc_ManagerReadCurrentNode(hmgr);
+  models = Hrc_ManagerObtainComponentModels(hmgr);
+
+  rootModelName = Hrc_NodeReadModelName(currentNode);
+  rootModel = Hrc_ManagerFindModelByName(hmgr,rootModelName);
+  rootInstanceName = Hrc_NodeReadInstanceName(currentNode);
+  assert(rootModel != NIL(Hrc_Model_t));
+  
+  for (i=0; i < array_n(models); i++){
+    model = array_fetch(Hrc_Model_t *,models,i);
+    isRootModel = (model == rootModel) ? TRUE : FALSE;
+    instanceName = (isRootModel == TRUE) ? rootInstanceName : NIL(char);
+    Hrc_ModelWriteBlifMv(fp,model,isRootModel,instanceName);
+  }  
+
+  array_free(models);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Prints out .mv declaration for a given variable.]
+
+  Description [Prints out .mv declaration for a given variable.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+IoMvPrint(
+  FILE *fp,
+  Var_Variable_t *var)
+{
+  int is_enum, range, i;
+
+  is_enum = Var_VariableTestIsEnumerative(var);
+  range = Var_VariableReadNumValues(var);
+    
+  if (is_enum == 1){
+    if (range == 2){
+      /* Boolean enumerative variables need no .mv declaration. */
+      return;
+    }
+    else {
+      (void)fprintf(fp,".mv %s %d\n",Var_VariableReadName(var),range);
+    }
+  }
+  else {
+  /* variable var is symbolic */
+    (void)fprintf(fp,".mv %s %d ",Var_VariableReadName(var),range);
+    for (i=0; i < range; i++){
+      (void)fprintf(fp,"%s ",Var_VariableReadSymbolicValueFromIndex(var,i));
+    }
+    (void)fprintf(fp,"\n");
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Prints out .mv declaration for a given variable, with the special
+               string "_bufin" appended to the variable name.]
+
+  Description [Prints out .mv declaration for a given variable.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+IoMvPrintSpecial(
+  FILE *fp,
+  Var_Variable_t *var)
+{
+  int is_enum, range, i;
+
+  is_enum = Var_VariableTestIsEnumerative(var);
+  range = Var_VariableReadNumValues(var);
+    
+  if (is_enum == 1){
+    if (range == 2){
+      /* Boolean enumerative variables need no .mv declaration. */
+      return;
+    }
+    else {
+      (void)fprintf(fp,".mv %s_bufin %d\n",Var_VariableReadName(var),range);
+    }
+  }
+  else {
+  /* variable var is symbolic */
+    (void)fprintf(fp,".mv %s_bufin %d ",Var_VariableReadName(var),range);
+    for (i=0; i < range; i++){
+      (void)fprintf(fp,"%s ",Var_VariableReadSymbolicValueFromIndex(var,i));
+    }
+    (void)fprintf(fp,"\n");
+  }
+}
+
+
+
Index: vis_dev/vis-2.3/src/io/ioWriteBlifUtil.c
===================================================================
--- vis_dev/vis-2.3/src/io/ioWriteBlifUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/io/ioWriteBlifUtil.c	(revision 14)
@@ -0,0 +1,1339 @@
+/**CFile***********************************************************************
+
+  FileName    [ ioWriteBlifUtil.c ]
+
+  PackageName [ io ]
+
+  Synopsis    [ This file contains blifmv -> blif write routines, which perform
+                miscellaneous lower-level functions ]
+
+  Description [ Routines that perform lower-level tasks in the determinizing, 
+                encoding and) writing a blifmv table into a blif description 
+                are included in this file]
+
+  SeeAlso     [ ioReadBlifmv.c, ioWriteBlif.c, ioWriteBlifIo.c]
+
+  Author      [ Sunil P. Khatri ]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ioInt.h"
+
+static char rcsid[] UNUSED = "$Id: ioWriteBlifUtil.c,v 1.12 2005/05/14 02:15:22 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void _IoWriteEntryToTable(Tbl_Entry_t *entry, Tbl_Table_t *table, int row, int col, int output);
+static void _IoWriteValueToTable(int value, Tbl_Table_t *table, int row, int col, int output);
+static Tbl_Table_t *_IoTableRemoveEqualsContruct(Tbl_Table_t *origBlifmvTable, array_t *freeVarArray, int verbosity);
+static void _IoVarEncEntryFree(IoVarEncEntry_t *varEnc);
+static int _IoNumValues(int colnum, array_t *numValuesArray);
+static Tbl_Entry_t *_IoCreateBinRange(array_t *mvEntryBinRanges, Tbl_Entry_t *entry, int numBits, int runLength, int skipLength);
+static boolean _IoEntryCheckRange(Tbl_Entry_t *entry, int startValue, int runLength, int skipLength);
+static Tbl_Entry_t *_IoAddBinRange(array_t *mvEntryBinRanges, Tbl_Entry_t *entry, int startValue, int runLength, int skipLength);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function***********************************************************
+
+
+  Synopsis	[ Makes a single output table for the outputNum'th output]
+
+  Description	[ Allows for ='s in output entries to refer only to input vars ]
+
+  SideEffects	[ ]
+
+  SeeAlso	[  ]
+************************************************************************/
+Tbl_Table_t *
+IoMakeSingleOutputTable(
+  Tbl_Table_t *table,
+  int outputNum
+  )
+{
+    Tbl_Table_t * tableDup;
+    int i, j, numRows, numCols;
+    Tbl_Entry_t *newEntry, *entry, *parentVarEntry;
+    Var_Variable_t *var;
+    
+    tableDup = Tbl_TableAlloc();
+    numRows = Tbl_TableReadNumRows(table);
+    numCols = Tbl_TableReadNumInputs(table);
+    
+    Tbl_TableForEachInputVar(table,i,var){
+	Tbl_TableAddColumn(tableDup,var,0);
+    }
+    
+    var = Tbl_TableReadIndexVar(table,outputNum,1);
+    Tbl_TableAddColumn(tableDup,var,1);
+    
+    entry = Tbl_TableDefaultReadEntry(table,outputNum);
+    if (entry != NIL(Tbl_Entry_t)){
+	if(Tbl_EntryReadType(entry) != Tbl_EntryNormal_c){
+	    var = Tbl_EntryReadVar(table, entry);
+	    j = Tbl_TableReadVarIndex(table, var, 1);
+	    parentVarEntry = Tbl_TableDefaultReadEntry(table, j);
+	    newEntry = Tbl_EntryDup(parentVarEntry);
+	}
+	else{
+	    newEntry = Tbl_EntryDup(entry);
+	}
+    }
+    else {
+	newEntry = NIL(Tbl_Entry_t);
+    }
+    (void) Tbl_TableDefaultSetEntry(tableDup,newEntry,0);
+    
+    for(i = 0; i < numRows; i++){
+	(void) Tbl_TableAddRow(tableDup);
+	for(j = 0; j < numCols; j++){
+	    entry = Tbl_TableReadEntry(table, i, j, 0);
+	    newEntry = Tbl_EntryDup(entry);
+	    Tbl_TableSetEntry(tableDup, newEntry, i, j, 0);
+	}
+	entry = Tbl_TableReadEntry(table, i, outputNum, 1);
+	newEntry = Tbl_EntryDup(entry);
+	Tbl_TableSetEntry(tableDup, newEntry, i, 0, 1);
+    }
+    return tableDup;
+}
+
+
+
+/**Function***********************************************************
+
+  Synopsis	[ Checks if the number of rows after expansion, due to the 
+                  outputs = expansion, is more than a given threshold.]
+
+  Description	[ Allows for ='s in output entries to refer only to input
+  vars ]
+
+  SideEffects	[ ]
+
+  SeeAlso	[ ]
+
+************************************************************************/
+boolean
+IoOutputExpansionRequired(
+  Tbl_Table_t *table
+  )
+{
+    int numRows, numOutputs, i, colnum, parentVarIndex;
+    Tbl_Entry_t *entry;
+    Var_Variable_t *parentVar;
+
+    /* previously used to find out the estimated size of the resulting binary 
+       table (in number of entries) and return TRUE if this number was greater
+       than 250. Removed this check, and now return TRUE if the table is multi-
+       output. This is at the cost of potentially increasing runtime.
+    */
+    /* if any of the output entries has an =var where var is another output
+       variable, then output splitting is not done */
+
+    numRows = Tbl_TableReadNumRows(table);
+    numOutputs = Tbl_TableReadNumOutputs(table);
+
+    for(i = 0; i < numRows; i++){
+	for(colnum = 0; colnum < numOutputs; colnum++){
+	    entry = Tbl_TableReadEntry(table, i, colnum, 1);
+	    if(Tbl_EntryReadType(entry) == Tbl_EntryEqual_c){
+		parentVar = Tbl_EntryReadVar(table, entry);
+		parentVarIndex = Tbl_TableReadVarIndex(table, parentVar, 0);
+		if(parentVarIndex == -1){
+		  fprintf(vis_stderr, "Output entry mimics another output with an '=' construct - error\n");
+		  assert(parentVarIndex != -1);
+		}
+	    }
+	}
+    }
+    if(numOutputs > 1){
+      return TRUE;
+    }
+    return FALSE;
+}
+    
+/**Function********************************************************************
+
+  Synopsis    [Initializes IoBlifInfo_t data structure]
+
+  Description [] 
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+IoInitBlifInfo(
+   IoBlifInfo_t *blifInfo, 
+   Tbl_Table_t *origBlifmvTable,
+   FILE *fp,
+   FILE *encFp,
+   int verbosity
+   )
+{
+    blifInfo->varArray = array_alloc(Var_Variable_t *, 0);
+    blifInfo->blifmvTable = _IoTableRemoveEqualsContruct(origBlifmvTable, blifInfo->varArray, verbosity);
+    blifInfo->binTable = Tbl_TableAlloc();
+    blifInfo->inputEncTblArray = array_alloc(IoVarEncEntry_t *, 0);
+    blifInfo->outputEncTblArray = array_alloc(IoVarEncEntry_t *, 0);
+    blifInfo->dcTblArray = array_alloc(Tbl_Table_t *, 0);
+    blifInfo->verbosity = verbosity;
+    blifInfo->pseudoinputFlag = FALSE;
+    blifInfo->BlifFp = fp;
+    blifInfo->EncFp = encFp;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees IoBlifInfo_t data structure]
+
+  Description [ ] 
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+IoFreeBlifInfo(
+   IoBlifInfo_t *blifInfo
+   )
+{
+    int i;
+
+    Tbl_TableFree(blifInfo->blifmvTable);
+    Tbl_TableFree(blifInfo->binTable); 
+
+    for(i=0; i < array_n(blifInfo->inputEncTblArray); i++){
+	_IoVarEncEntryFree(array_fetch(IoVarEncEntry_t *, blifInfo->inputEncTblArray, i));
+    }
+    array_free(blifInfo->inputEncTblArray);
+
+    for(i=0; i < array_n(blifInfo->outputEncTblArray); i++){
+	_IoVarEncEntryFree(array_fetch(IoVarEncEntry_t *, blifInfo->outputEncTblArray, i));
+    }
+    array_free(blifInfo->outputEncTblArray);
+
+    for(i=0; i < array_n(blifInfo->varArray); i++){
+	Var_VariableFree(array_fetch(Var_Variable_t *, blifInfo->varArray, i));
+    }
+    array_free(blifInfo->varArray);
+
+    for(i=0; i < array_n(blifInfo->binTblArray); i++){
+	Tbl_TableFree(array_fetch(Tbl_Table_t *, blifInfo->binTblArray, i));
+    }
+    array_free(blifInfo->binTblArray);
+
+    for(i=0; i < array_n(blifInfo->dcTblArray); i++){
+	Tbl_TableFree(array_fetch(Tbl_Table_t *, blifInfo->dcTblArray, i));
+    }
+    array_free(blifInfo->dcTblArray);
+    FREE(blifInfo);
+      
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Determines if a variable is a PI/PO of an hnode. ]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean		
+IoVarIsHnodePIO(
+  Hrc_Node_t *hnode, 
+  Var_Variable_t *var
+  )
+{
+    boolean test;
+    
+    test = FALSE;
+    if(Var_VariableTestIsPO(var) || Var_VariableTestIsPI(var) || Var_VariableTestIsSO(var) || Var_VariableTestIsSI(var)){
+	test = TRUE;
+    }
+    return test;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Encodes individual variable based on its ranges]
+
+  Description [Returns encoding as an entry in the array of encodings' tables]
+
+  SideEffects [Populates a table in the array of tables describing the IO encodings]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+IoEncodeVariable(
+   IoBlifInfo_t *blifInfo,
+   Var_Variable_t *var,
+   int varNum,		 
+   int output
+   )
+{
+    int range, numEncBits;
+    IoVarEncEntry_t *varEncEntry;
+
+    range = Var_VariableReadNumValues(var);
+    numEncBits = IoNumEncBits(range);
+    
+    varEncEntry = ALLOC(IoVarEncEntry_t, 1);
+    varEncEntry->variable = Var_VariableDup(var, NIL(Hrc_Node_t));
+    varEncEntry->index = varNum;
+    varEncEntry->numEncBits = numEncBits;
+    if(output == 1){
+	array_insert_last(IoVarEncEntry_t *, blifInfo->outputEncTblArray, varEncEntry);
+    }
+    else{
+	array_insert_last(IoVarEncEntry_t *, blifInfo->inputEncTblArray, varEncEntry);
+    }
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns number of bits in encoding]
+
+  Description [Returns n such that 2^n >= range of the variable ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+IoNumEncBits(
+   int n
+   )
+{
+    int i=0;
+    int j=1;
+
+    if (n<2){
+	return 1;
+    }
+    else{
+	while (j < n){
+	    j = j * 2;
+	    i++;
+	}
+    }
+    return i;
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of digits in the base 10 representation of a number]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int 
+IoNumDigits(
+   int n
+   )
+{
+    double j;
+    
+    j = log10((double) n) + 1;
+    return ((int) j);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns log-base-2 of a number which is a power of 2]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+IoLog(
+   int n
+   )
+{
+    int i=0;
+    int j=1;
+
+    while (j < n){
+	j = j * 2;
+	i++;
+    }
+    return i;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the IoVarEncEntry_t with the smallest encoding length]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+IoVarEncEntry_t *
+IoFindSmallestCode( 
+   IoBlifInfo_t *blifInfo
+   )
+{
+    int i, smallestCode, index;
+    IoVarEncEntry_t *varEnc;
+
+    index = -1;
+    smallestCode = VIS_INFINITY;
+    for(i = 0; i < array_n(blifInfo->inputEncTblArray); i++){
+	varEnc = array_fetch(IoVarEncEntry_t *, blifInfo->inputEncTblArray, i);
+	if((Var_VariableReadNumValues(varEnc->variable)) < smallestCode){
+	    smallestCode = Var_VariableReadNumValues(varEnc->variable);
+	    index = i;
+	}
+    }
+    
+    assert(index != -1);
+    varEnc = array_fetch(IoVarEncEntry_t *, blifInfo->inputEncTblArray, index);
+    return varEnc;
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Increases the code size of a variable]
+
+  Description [Invoked when a output for a row has multiple values. To determinize 
+               this scenario, an input has pseudovariables appended to its code. The
+	       number of pseudoinputs = log(n) where n is the number of values of the
+	       output]
+
+  SideEffects [alters encoding of mv variables]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+IoIncreaseCodeSize(
+  IoVarEncEntry_t *varEnc, 
+  int numValues,
+  int verbosity		  
+  )
+{
+    int temp1, temp2, range, numAddedPseudovars, numExpand;
+
+    range = Var_VariableReadNumValues(varEnc->variable);
+    numAddedPseudovars = IoNumEncBits(numValues);
+    temp1 = ((int) pow((double) 2, (double)numAddedPseudovars)) - 1;
+    temp2 = (int) pow((double) 2, (double)varEnc->numEncBits);
+    numExpand = (temp1 * temp2) + range;
+    if(verbosity > 2){
+	(void)fprintf(stdout, "New Number of Values for the variable = %d\n", numExpand);
+    }
+    Var_VariableExpandRange(varEnc->variable, numExpand);
+	
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Alters blifmv table to reflect the increase in code size from IoIncreaseCodeSize]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+IoChangeBlifmvTableRows(
+   IoBlifInfo_t *blifInfo,		 
+   IoVarEncEntry_t *varEnc, 
+   int row1,
+   int row2
+  )
+{
+    int numCurrentBits, i, numRows, colnum, tempCol, reqdColnum;
+    Tbl_Entry_t *entry;
+    char *varname, *dupName;
+    Var_Variable_t *newVar;
+    IoVarEncEntry_t *tempVarEnc;
+
+    /* add a new column to bin table */
+    numCurrentBits = varEnc->numEncBits;
+    varname = Var_VariableReadName(varEnc->variable);
+    dupName = ALLOC(char, strlen(varname) + IoNumDigits(numCurrentBits) + 2);
+    sprintf(dupName, "%s%d", varname, numCurrentBits);
+    newVar = Var_VariableAlloc(NIL(Hrc_Node_t), dupName);
+    FREE(dupName);
+    array_insert_last(Var_Variable_t *, blifInfo->varArray, newVar);
+    colnum = Tbl_TableAddColumn(blifInfo->binTable, newVar, 0);
+    numRows = Tbl_TableReadNumRows(blifInfo->binTable);
+    for(i = 0; i < numRows; i++){
+	entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+	if(i == row1){
+	    Tbl_EntrySetValue(entry, 0, 0);
+	}
+	if(i == row2){
+	    Tbl_EntrySetValue(entry, 1, 1);
+	}
+	if((i != row1) && (i != row2)){
+	    Tbl_EntrySetValue(entry, 0, 1);
+	}
+	Tbl_TableSetEntry(blifInfo->binTable, entry, i, colnum - 1, 0);
+    }
+    tempCol = 0;
+    reqdColnum = -1;
+    for(i = 0; i < array_n(blifInfo->inputEncTblArray); i++){
+	tempVarEnc = array_fetch(IoVarEncEntry_t *, blifInfo->inputEncTblArray, i);
+	if(tempVarEnc == varEnc){
+	    reqdColnum = tempCol + varEnc->numEncBits;
+	}
+	tempCol += tempVarEnc->numEncBits;
+    }
+    colnum--;    
+    assert(reqdColnum != -1);
+    while(reqdColnum < colnum){
+	Tbl_TableSwapColumns(blifInfo->binTable, colnum, colnum - 1, 0);
+	colnum--;
+    }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Alters table to reflect the increase in code size from IoIncreaseCodeSize]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+IoChangeBlifmvTableEntries(
+   IoBlifInfo_t *blifInfo,
+   int rownum,
+   int numValues,
+   IoVarEncEntry_t *varEnc, 
+   array_t *MvOutputArray
+  )
+{
+    int i, j, k, newrownum, colnum, inputColnumToChange, value, offset;
+    int numInputs, numOutputs, entryRepetitionCount, numCycles, numNewBits, maxValue, numOldBits;
+    Tbl_Entry_t *entry, *dupEntry;
+    lsGen gen;
+    Tbl_Range_t *range;
+
+    numInputs = Tbl_TableReadNumInputs(blifInfo->blifmvTable);
+    numOutputs = Tbl_TableReadNumOutputs(blifInfo->blifmvTable);
+    numNewBits = IoNumEncBits(numValues);
+    numOldBits = varEnc->numEncBits;
+    maxValue = (int) pow((double) 2, (double)(numNewBits + numOldBits));
+
+    inputColnumToChange = varEnc->index;
+    for(i = 0; i < Tbl_TableReadNumRows(blifInfo->blifmvTable); i++){
+	if (i != rownum){
+	    entry = Tbl_TableReadEntry(blifInfo->blifmvTable, i, inputColnumToChange, 0);
+	    dupEntry = Tbl_EntryDup(entry);
+	    offset = (int) pow((double) 2, (double)varEnc->numEncBits);
+	    Tbl_EntryForEachValue(entry, value, gen, range){
+		for(j = value ; j < maxValue; j = j + offset){
+		    Tbl_EntrySetValue(dupEntry, j, j);
+		}
+	    }
+	    Tbl_TableSetEntry(blifInfo->blifmvTable, dupEntry, i, inputColnumToChange, 0);
+	}
+    }
+    newrownum = -1;
+    for(i = 0; i < numValues; i++){
+ 
+         /* add a row, and duplicate all entries of the original row except for 
+            the one that needs a new entry (because of the new code). This entry
+            gets code = oldCode + i * (2^numCurrentEncBits)      */
+
+	newrownum = Tbl_TableAddRow(blifInfo->blifmvTable);
+	assert(newrownum != -1);
+	for(colnum = 0; colnum < numInputs; colnum++){
+	    entry = Tbl_TableReadEntry(blifInfo->blifmvTable, rownum, colnum, 0);
+	    if(colnum != inputColnumToChange){
+		dupEntry = Tbl_EntryDup(entry);
+		Tbl_TableSetEntry(blifInfo->blifmvTable, dupEntry, newrownum, colnum, 0);
+	    }
+	    else{
+		dupEntry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+		offset = i * ((int) pow((double) 2, (double) varEnc->numEncBits));
+		Tbl_EntryForEachValue(entry, value, gen, range){
+		    Tbl_EntrySetValue(dupEntry, value + offset, value + offset);
+		}
+		Tbl_TableSetEntry(blifInfo->blifmvTable, dupEntry, newrownum, colnum, 0);
+	    }
+	}
+    }
+
+    /* This section singleton-izes the output entries of the new row. 
+       Multiple outputs are accounted for. If more than one output has 
+       non-singleton entries, they are all singleton-ized. Finally,
+       the original row is deleted...                                       */ 
+    
+    entryRepetitionCount = numValues;
+    numCycles = 1;
+    newrownum++;
+    
+    for(colnum = 0; colnum < numOutputs; colnum++){
+	newrownum = newrownum - numValues;
+	numCycles *= _IoNumValues(colnum, MvOutputArray);
+	entryRepetitionCount /= array_fetch(int, MvOutputArray, colnum);
+	entry = Tbl_TableReadEntry(blifInfo->blifmvTable, rownum, colnum, 1);
+	for(j = 0; j < numCycles; j++){
+	    Tbl_EntryForEachValue(entry, value, gen, range){
+		for(k = 0; k < entryRepetitionCount; k++){
+		    dupEntry = Tbl_EntryAlloc(Tbl_EntryNormal_c);			
+		    Tbl_EntrySetValue(dupEntry, value, value);	     
+		    Tbl_TableSetEntry(blifInfo->blifmvTable, dupEntry, newrownum++, colnum, 1);
+		}
+	    }
+	}
+    }
+    blifInfo->blifmvTable = Tbl_TableRowDelete(blifInfo->blifmvTable, rownum, blifInfo->varArray); 
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Alters table to reflect the increase in code size from IoIncreaseCodeSize]
+
+  Description []
+               
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+IoChangeEncTableEntries(
+   IoBlifInfo_t *blifInfo,		 
+   st_table *blifInputsStTable,
+   IoVarEncEntry_t *varEnc, 
+   int numValues
+  )
+{
+    int numOrigBits, numAddedBits, i;
+    char *varname, *dupName;
+    
+    numAddedBits = IoNumEncBits(numValues);
+    numOrigBits = varEnc->numEncBits;
+
+    varname = Var_VariableReadName(varEnc->variable);
+    for(i=0; i<numAddedBits; i++){
+	dupName = ALLOC(char, strlen(varname) + IoNumDigits(numAddedBits + numOrigBits)+ 2);
+	sprintf(dupName, "%s%d", varname, i + numOrigBits);
+	if(!st_is_member(blifInputsStTable, (char *)dupName)){
+	    (void)fprintf(blifInfo->BlifFp, ".inputs %s\n", dupName);
+	    if(blifInfo->pseudoinputFlag == FALSE){
+		(void)fprintf(blifInfo->EncFp, ".table %s\n", dupName);
+		(void)fprintf(blifInfo->EncFp, "-\n");
+	    }
+	    st_insert(blifInputsStTable, (char *)dupName, (char *)1);
+	}
+	else{
+	    FREE(dupName);
+	}
+    }
+    varEnc->numEncBits += numAddedBits;
+
+}
+
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inverts a specified binary output of binTable]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+IoInvertBinTableOutput(
+   IoBlifInfo_t * blifInfo,
+   int colnumToInvert
+   )
+{
+    int i;
+    char *name, *newname;
+    Var_Variable_t *var;
+    
+    var = Tbl_TableReadIndexVar(blifInfo->binTable, colnumToInvert, 1);
+    name = Var_VariableReadName(var);
+    newname = ALLOC(char, strlen(name) + 4);
+    sprintf(newname, "%s_b", name);
+    (void)fprintf(blifInfo->BlifFp, ".names %s %s\n", newname, name);
+    (void)fprintf(blifInfo->BlifFp, "0 1\n");
+    Var_VariableChangeName(var, newname);
+    FREE(newname);
+    for(i = 0; i < Tbl_TableReadNumRows(blifInfo->binTable); i++){
+	Tbl_TableComplementEntry(blifInfo->binTable, i, colnumToInvert, 1);
+    }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns array that represents a simple way of compacting a mv 
+               entry while representing it in binary.]
+
+  Description [The array contains IoBinRangeEntry_t *'s. Each item of the array represents
+               a starting value and a run length and a skip length. The union of all such values contains
+               exactly the values of the entry passed]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+array_t *
+IoMakeBinaryRangesArray(
+   Tbl_Entry_t *entry,
+   int colnum,
+   IoBlifInfo_t *blifInfo		       
+   )
+{
+    array_t *mvEntryBinRanges;
+    int i, j, numBits, runLength, skipLength;
+    
+    mvEntryBinRanges = array_alloc(IoBinRangeEntry_t *, 0);
+    numBits = IoNumBinVars(colnum + 1, blifInfo->inputEncTblArray);
+    for(i = numBits; i > 0; i--){
+	for(j = 0; j < numBits; j++){
+	    runLength = (int) pow((double) 2, (double) i);
+	    skipLength = (int) pow((double) 2, (double) j);
+	    if((runLength * skipLength) <= (int) pow((double) 2, (double) numBits)){
+/*		fprintf(stdout, "run %d, skip %d\n", runLength, skipLength); */
+		entry = _IoCreateBinRange(mvEntryBinRanges, entry, numBits, runLength, skipLength);
+	    }
+	}
+    }
+    entry = _IoCreateBinRange(mvEntryBinRanges, entry, numBits, 1, 1);	    
+    assert(Tbl_EntryReadNumValues(entry) == 0);
+    Tbl_EntryFree(entry);
+    return mvEntryBinRanges;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of values in the entrycolnum-1) ]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+IoNumValuesFromBinRangesArray( 
+   int colnum,
+   array_t *binRangesArray
+   )
+{
+    array_t *mvEntryBinRanges;
+
+    if(colnum == 0){
+	return 1;
+    }
+    else{
+	mvEntryBinRanges = array_fetch(array_t *, binRangesArray, colnum - 1);
+	return(array_n(mvEntryBinRanges));
+    }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of binary vars in the variable index (colnum-1) ]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+IoNumBinVars( 
+   int colnum,
+   array_t *encTblArray
+   )
+{
+    IoVarEncEntry_t *varEnc;
+    
+    if(colnum == 0){
+	return 0;
+    }
+    else{
+	varEnc = array_fetch(IoVarEncEntry_t *, encTblArray, colnum-1);
+	return(varEnc->numEncBits);
+    }
+}
+
+    
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Duplicate an entry and set it  in a table]
+
+  Description [] 
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+_IoWriteEntryToTable(
+   Tbl_Entry_t *entry, 
+   Tbl_Table_t *table, 
+   int row, 
+   int col, 
+   int output
+)
+{
+    Tbl_Entry_t *dupEntry;
+    
+    dupEntry = Tbl_EntryDup(entry);
+    Tbl_TableSetEntry(table, dupEntry, row, col, output);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Make an entry from a value, and set it  in a table]
+
+  Description [] 
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+_IoWriteValueToTable(
+   int value, 
+   Tbl_Table_t *table, 
+   int row, 
+   int col, 
+   int output
+)
+{
+    Tbl_Entry_t *entry;
+    
+    entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+    Tbl_EntrySetValue(entry, value, value);
+    Tbl_TableSetEntry(table, entry, row, col, output);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Removes "=" constructs in a table]
+
+  Description [] 
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static Tbl_Table_t *
+_IoTableRemoveEqualsContruct(
+   Tbl_Table_t *origBlifmvTable,
+   array_t *freeVarArray,
+   int verbosity
+   )
+{
+    Tbl_Table_t *resultTable;
+    int numRows, numInputs, numOutputs, numRowsAfterExpansion, i, j, k, colnum, rownum, currRow, value;
+    int parentVarnumValues, parentVarIndex, rootRow, entryRepetitionCount ;
+    st_table *parentsStTable;
+    Tbl_Entry_t *entry, *parentVarEntry, *dupEntry;
+    Var_Variable_t *parentVar, *var;
+    boolean parentVarIsOutput, rowContainsEqualEntries, insertedI;
+    st_generator *gen;
+    Tbl_Range_t *range;
+    lsGen listgen;
+    array_t *rowDeleteArray;
+    char *dummy;
+
+    resultTable = Tbl_TableHardDup(origBlifmvTable);
+    /* remove "="s in original defaults table*/
+    for(i = 0; i < Tbl_TableReadNumOutputs(resultTable); i++){
+	entry = Tbl_TableDefaultReadEntry(resultTable, i);
+	if(entry != NIL(Tbl_Entry_t)){
+	    if(Tbl_EntryReadType(entry) != Tbl_EntryNormal_c){
+		var = Tbl_EntryReadVar(resultTable, entry);
+		j = Tbl_TableReadVarIndex(resultTable, var, 1);
+		parentVarEntry = Tbl_TableDefaultReadEntry(resultTable, j);
+		dupEntry = Tbl_EntryDup(parentVarEntry);
+		Tbl_TableDefaultSetEntry(resultTable, dupEntry, i);
+		Tbl_EntryFree(entry);
+	    }
+	}
+    }
+
+    /* first expand all rows with "=" constructs, in the same table */
+    numRows = Tbl_TableReadNumRows(resultTable);
+    numInputs = Tbl_TableReadNumInputs(resultTable);
+    numOutputs = Tbl_TableReadNumOutputs(resultTable);
+    rootRow = numRows;
+
+    for(i = 0; i < numRows; i++){
+	numRowsAfterExpansion = 1;
+	rowContainsEqualEntries = FALSE;	
+	parentsStTable = st_init_table(st_ptrcmp, st_ptrhash);
+
+	/* find variables that are parent variables, ie variables 'var' that
+           have =var references in that row of the table    */
+	for(colnum = 0; colnum < numInputs; colnum++){
+	    entry = Tbl_TableReadEntry(resultTable, i, colnum, 0);
+	    if(Tbl_EntryReadType(entry) == Tbl_EntryEqual_c){
+		rowContainsEqualEntries = TRUE;
+		parentVar = Tbl_EntryReadVar(resultTable, entry);
+		st_insert(parentsStTable, (char *) parentVar, (char *) 1);
+	    }
+	}
+	for(colnum = 0; colnum < numOutputs; colnum++){
+	    entry = Tbl_TableReadEntry(resultTable, i, colnum, 1);
+	    if(Tbl_EntryReadType(entry) == Tbl_EntryEqual_c){
+		rowContainsEqualEntries = TRUE;
+		parentVar = Tbl_EntryReadVar(resultTable, entry);
+		st_insert(parentsStTable, (char *) parentVar, (char *) 1);
+	    }
+	}
+	if(rowContainsEqualEntries == FALSE){
+	    st_free_table(parentsStTable);
+	    continue;
+	}
+	
+	/* find the number of rows after expansion */
+	st_foreach_item(parentsStTable, gen, &parentVar, &dummy){
+	    parentVarIndex = Tbl_TableReadVarIndex(resultTable, parentVar, 0);
+	    if(parentVarIndex != -1){
+		parentVarIsOutput = 0;
+	    }
+	    else{
+		parentVarIsOutput = 1;
+		parentVarIndex = Tbl_TableReadVarIndex(resultTable, parentVar, 1);		
+	    }
+	    parentVarEntry = Tbl_TableReadEntry(resultTable, i, parentVarIndex, parentVarIsOutput);
+	    numRowsAfterExpansion *= Tbl_EntryReadNumValues(parentVarEntry);
+	}
+
+	/* write out expanded form of this row */
+	for(j = 0; j < numRowsAfterExpansion; j++){
+	    Tbl_TableAddRow(resultTable);
+	}
+	/* expand parent variables first */
+	entryRepetitionCount = numRowsAfterExpansion;
+	st_foreach_item(parentsStTable, gen, &parentVar, &dummy){
+	    parentVarIndex = Tbl_TableReadVarIndex(resultTable, parentVar, 0);
+	    if(parentVarIndex != -1){
+		parentVarIsOutput = 0;
+	    }
+	    else{
+		parentVarIsOutput = 1;
+		parentVarIndex = Tbl_TableReadVarIndex(resultTable, parentVar, 1);		
+	    }
+	    parentVarEntry = Tbl_TableReadEntry(resultTable, i, parentVarIndex,
+						  parentVarIsOutput);
+	    parentVarnumValues = Tbl_EntryReadNumValues(parentVarEntry);
+	    currRow = rootRow;
+	    entryRepetitionCount = entryRepetitionCount / parentVarnumValues;
+	    while(currRow < rootRow + numRowsAfterExpansion){
+		Tbl_EntryForEachValue(parentVarEntry, value, listgen, range){	    
+		    for(k = 0; k < entryRepetitionCount; k++){
+			_IoWriteValueToTable(value, resultTable, currRow, parentVarIndex,
+					    parentVarIsOutput);
+			currRow++;
+		    }
+		}
+	    }
+	}
+
+	/* next expand variables that reference parent vars */
+	for(colnum = 0; colnum < numInputs; colnum++){
+	    entry = Tbl_TableReadEntry(resultTable, i, colnum, 0);
+	    if(Tbl_EntryReadType(entry) == Tbl_EntryEqual_c){
+		parentVar = Tbl_EntryReadVar(resultTable, entry);
+		parentVarIndex = Tbl_TableReadVarIndex(resultTable, parentVar, 0);
+		if(parentVarIndex != -1){
+		    parentVarIsOutput = 0;
+		}
+		else{
+		    parentVarIsOutput = 1;
+		    parentVarIndex = Tbl_TableReadVarIndex(resultTable, parentVar, 1);		
+		}
+		parentVarEntry = Tbl_TableReadEntry(resultTable, i, parentVarIndex,
+						      parentVarIsOutput);
+		for(k = rootRow; k < rootRow + numRowsAfterExpansion; k++){
+		    entry = Tbl_TableReadEntry(resultTable, k, parentVarIndex,
+					       parentVarIsOutput);	    
+		    _IoWriteEntryToTable(entry, resultTable, k, colnum, 0);
+		}
+	    }
+	    else{
+		if(!st_is_member(parentsStTable, (char *) Tbl_TableReadIndexVar(resultTable,
+										  colnum, 0))){
+		    for(k = rootRow; k < rootRow + numRowsAfterExpansion; k++){
+			_IoWriteEntryToTable(entry, resultTable, k, colnum, 0);
+		    }
+		}
+	    }
+	}
+	for(colnum = 0; colnum < numOutputs; colnum++){
+	    entry = Tbl_TableReadEntry(resultTable, i, colnum, 1);
+	    if(Tbl_EntryReadType(entry) == Tbl_EntryEqual_c){
+		parentVar = Tbl_EntryReadVar(resultTable, entry);
+		parentVarIndex = Tbl_TableReadVarIndex(resultTable, parentVar, 0);
+		if(parentVarIndex != -1){
+		    parentVarIsOutput = 0;
+		}
+		else{
+		    parentVarIsOutput = 1;
+		    parentVarIndex = Tbl_TableReadVarIndex(resultTable, parentVar, 1);		
+		}
+		parentVarEntry = Tbl_TableReadEntry(resultTable, i, parentVarIndex,
+						      parentVarIsOutput);
+		for(k = rootRow; k < rootRow + numRowsAfterExpansion; k++){
+		    entry = Tbl_TableReadEntry(resultTable, k, parentVarIndex,
+					       parentVarIsOutput);	    
+		    _IoWriteEntryToTable(entry, resultTable, k, colnum, 1);
+		}
+	    }
+	    else{
+		if(!st_is_member(parentsStTable, (char *) Tbl_TableReadIndexVar(resultTable,
+										  colnum, 1))){
+		    for(k = rootRow; k < rootRow + numRowsAfterExpansion; k++){
+			_IoWriteEntryToTable(entry, resultTable, k, colnum, 1);
+		    }
+		}
+	    }
+	}
+	rootRow += numRowsAfterExpansion;
+	st_free_table(parentsStTable);
+    }
+    
+    
+    /* now delete rows with "=" constructs */
+    rowDeleteArray = array_alloc(int, 0);
+    for(i = 0; i < numRows; i++){
+	insertedI = FALSE;
+	for(colnum = 0; colnum < numInputs; colnum++){
+	    entry = Tbl_TableReadEntry(resultTable, i, colnum, 0);
+	    if(Tbl_EntryReadType(entry) == Tbl_EntryEqual_c){
+		if(!insertedI){
+		    array_insert_last(int, rowDeleteArray, i);
+		    insertedI = TRUE;
+		}
+	    }
+	}
+	for(colnum = 0; colnum < numOutputs; colnum++){
+	    entry = Tbl_TableReadEntry(resultTable, i, colnum, 1);
+	    if(Tbl_EntryReadType(entry) == Tbl_EntryEqual_c){
+		if(!insertedI){
+		    array_insert_last(int, rowDeleteArray, i);
+		    insertedI = TRUE;
+		}
+	    }
+	}
+    }
+    /* array of vars that are to be freed. Since these are called with 
+      a NIL(Hrc_Node_t), they need to be freed separately, and kept track 
+      of
+    */
+    for(i = 0; i < array_n(rowDeleteArray); i++){
+	rownum = array_fetch(int, rowDeleteArray, i) - i;
+	resultTable = Tbl_TableRowDelete(resultTable, rownum, freeVarArray); 
+    }
+    array_free(rowDeleteArray);
+
+
+    if(verbosity > 1){
+	(void)fprintf(stdout, "Blifmv Table after = removal is\n");
+	Tbl_TableWriteBlifMvToFile(resultTable, 0, stdout);
+    }
+    return resultTable;
+
+}
+	
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the IoVarEncEntry_t ]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+_IoVarEncEntryFree(
+  IoVarEncEntry_t *varEnc
+  )
+{
+    Var_VariableFree(varEnc->variable);
+    free(varEnc);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks if runLength entries from startValue with skipLength increments are contained in entry
+              ]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static boolean
+_IoEntryCheckRange(
+ Tbl_Entry_t *entry,
+ int startValue,
+ int runLength,
+ int skipLength
+ )
+{
+    boolean startFound;
+    int value, i;
+    lsGen gen;
+    Tbl_Range_t *range;
+
+    startFound = FALSE;
+    i = 1;
+    Tbl_EntryForEachValue(entry, value, gen, range){
+	if(value == startValue){
+	    startFound = TRUE;
+	}
+	if((!startFound) && (value > startValue)){
+	    lsFinish(gen);
+	    return FALSE;
+	}
+	if(value == startValue + (i * skipLength)){
+	    i++;
+	}
+	if(value > startValue + (i * skipLength)){
+	    lsFinish(gen);
+	    return FALSE;
+	}
+	if(i == runLength){
+	    lsFinish(gen);
+	    return TRUE;
+	}
+    }
+    return FALSE;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a (startValue, runLength) pair such that the runLength
+               is the largest number of contiguous values in entry, starting from 
+               startValue]
+
+  Description [adds  a IoBinRangeEntry_t * to the mvEntryBinRanges. Also returns the
+               value upto which all values of the entry have been entered in the
+	       mvEntryBinRanges.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static Tbl_Entry_t *
+_IoCreateBinRange(
+   array_t *mvEntryBinRanges,
+   Tbl_Entry_t *entry,
+   int numBits,		 
+   int runLength,	      
+   int skipLength
+   )		 
+{
+    int i, j, bitPos, tempI, numDash, end, numStartValues, startValue;
+    array_t *freeBitsArray;
+
+    numDash = IoLog(runLength);
+    end = IoLog(skipLength);
+    freeBitsArray = array_alloc(int, 0);
+    for(i = 0; i < numBits; i++){
+	if(i < end){
+	    array_insert_last(int, freeBitsArray, i);
+	}
+	if(i >= end + numDash){
+	    array_insert_last(int, freeBitsArray, i);
+	}
+    }
+    numStartValues = (int) pow((double) 2, (double) array_n(freeBitsArray));
+    for(i = 0; i < numStartValues; i++){
+	startValue = 0;
+	tempI = i;
+	for(j = array_n(freeBitsArray) - 1; j >= 0; j--){
+	    if(tempI >= (int) pow((double) 2, (double) j)){
+		bitPos = array_fetch(int, freeBitsArray, j);
+		startValue += (int) pow((double) 2, (double) bitPos);
+		tempI -= (int) pow((double) 2, (double) j);
+	    }
+	} 
+/*	fprintf(stdout, "trying start %d, run %d, skip %d\n", startValue, runLength, skipLength); */
+	if(_IoEntryCheckRange(entry, startValue, runLength, skipLength)){
+	    entry = _IoAddBinRange(mvEntryBinRanges, entry, startValue, runLength, skipLength);
+	}
+    }
+    array_free(freeBitsArray);
+    return entry;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Enters a (startValue, runLength, skipLength) tuple into the mvEntryBinRanges array]
+
+  Description [adds  a IoBinRangeEntry_t * to the mvEntryBinRanges. ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static Tbl_Entry_t *
+_IoAddBinRange(
+   array_t *mvEntryBinRanges,
+   Tbl_Entry_t *entry,
+   int startValue,
+   int runLength,	      
+   int skipLength
+   )
+{
+    IoBinRangeEntry_t *binRangeEntry;
+    int i, value;
+    Tbl_Entry_t *newEntry;
+    lsGen gen;
+    Tbl_Range_t *range;
+    
+    binRangeEntry = ALLOC(IoBinRangeEntry_t, 1);
+    binRangeEntry->startValue = startValue;
+    binRangeEntry->runLength = runLength;
+    binRangeEntry->skipLength = skipLength;
+    array_insert_last(IoBinRangeEntry_t *, mvEntryBinRanges, binRangeEntry);
+    newEntry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+    i = 0;
+    Tbl_EntryForEachValue(entry, value, gen, range){
+	if((value == startValue + (i * skipLength)) && (i < runLength)){
+	    i++;
+	}
+	else{
+	    Tbl_EntrySetValue(newEntry, value, value);
+	}
+    }
+    Tbl_EntryFree(entry);
+    return newEntry;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of values in the entrycolnum-1) ]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+_IoNumValues(
+  int colnum,
+  array_t *numValuesArray
+  )
+{
+    if(colnum == 0){
+	return 1;
+    }
+    else{
+	return(array_fetch(int, numValuesArray, colnum - 1));
+    }
+}
+	       
+
Index: vis_dev/vis-2.3/src/io/ioWriteSmv.c
===================================================================
--- vis_dev/vis-2.3/src/io/ioWriteSmv.c	(revision 14)
+++ vis_dev/vis-2.3/src/io/ioWriteSmv.c	(revision 14)
@@ -0,0 +1,231 @@
+/**CFile***********************************************************************
+
+  FileName    [ioWriteSmv.c]
+
+  PackageName [io]
+
+  Synopsis    [Writes out an Smv file.]
+
+  Description [Write the current model to a file compatible with NuSMV v2.1]
+
+  Author      [Daniel Sheridan, Chao Wang]
+
+  Copyright   [Copyright (c) 2004 The Regents of the Univ. of Colorado. All 
+  rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.]
+
+******************************************************************************/
+
+#include "ioInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints out variable name, cleaned for NuSMV]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Io_SmvPrintVar(
+  FILE *fp,
+  Var_Variable_t *var)
+{
+  char * varname = Var_VariableReadName(var);
+  int i;
+
+  for(i=0; varname[i]; i++) {
+    if(varname[i] == '<' || 
+       varname[i] == '>' || 
+       varname[i] == '*' || 
+       varname[i] == '$') {
+      fputc('_', fp);
+    } else {
+      fputc(varname[i], fp);
+    }
+  }
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [The top-level routine for writing out an NuSMV file.]
+
+  Description [The top-level routine for writing out an NuSMV file.
+  The user has to check if the hmgr has a hierarchy read in before
+  calling this procedure.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+IoSmvWrite(
+  FILE *fp,
+  Hrc_Manager_t *hmgr)
+{ 
+  char *rootModelName;
+  Hrc_Model_t *model, *rootModel;
+  Hrc_Node_t *currentNode;
+  array_t *models;
+  int i;
+  boolean isRootModel;
+  char *rootInstanceName, *instanceName;
+  
+  currentNode = Hrc_ManagerReadCurrentNode(hmgr);
+  models = Hrc_ManagerObtainComponentModels(hmgr);
+
+  rootModelName = Hrc_NodeReadModelName(currentNode);
+  rootModel = Hrc_ManagerFindModelByName(hmgr,rootModelName);
+  rootInstanceName = Hrc_NodeReadInstanceName(currentNode);
+  assert(rootModel != NIL(Hrc_Model_t));
+  
+  for (i=0; i < array_n(models); i++){
+    model = array_fetch(Hrc_Model_t *,models,i);
+    isRootModel = (model == rootModel) ? TRUE : FALSE;
+    instanceName = (isRootModel == TRUE) ? rootInstanceName : NIL(char);
+    Hrc_ModelWriteSmv(fp,model,isRootModel,instanceName);
+  }  
+
+  array_free(models);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Prints out VAR declaration for a given variable.]
+
+  Description [Prints out VAR declaration for a given variable.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+IoSmvPrint(
+  FILE *fp,
+  Var_Variable_t *var)
+{
+  int is_enum, range, i;
+
+  is_enum = Var_VariableTestIsEnumerative(var);
+  range = Var_VariableReadNumValues(var);
+    
+  if (is_enum == 1){
+    if (range == 2){
+      (void)fprintf(fp,"VAR %s : boolean;\n",Var_VariableReadName(var));
+    }
+    else {
+      (void)fprintf(fp,"VAR %s : 0..%d;\n",Var_VariableReadName(var),range-1);
+    }
+  }
+  else {
+  /* variable var is symbolic */
+    (void)fprintf(fp,"VAR %s : {",Var_VariableReadName(var));
+    for (i=0; i < range; i++){
+      if (i == (range-1))
+        (void)fprintf(fp,"%s ",Var_VariableReadSymbolicValueFromIndex(var,i));
+      else
+        (void)fprintf(fp,"%s, ",Var_VariableReadSymbolicValueFromIndex(var,i));
+    }
+    (void)fprintf(fp,"};\n");
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Prints out VAR declaration for a given variable, with the
+               special string "_bufin" appended to the variable name.]
+
+  Description [Prints out VAR declaration for a given variable.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+IoSmvPrintSpecial(
+  FILE *fp,
+  Var_Variable_t *var)
+{
+  int is_enum, range, i;
+
+  is_enum = Var_VariableTestIsEnumerative(var);
+  range = Var_VariableReadNumValues(var);
+    
+  if (is_enum == 1){
+    if (range == 2){
+      (void)fprintf(fp,"VAR %s_bufin : boolean;\n",Var_VariableReadName(var));
+    }
+    else {
+      (void)fprintf(fp,"VAR %s_bufin : 0..%d;\n",Var_VariableReadName(var),
+		    range-1);
+    }
+  }
+  else {
+  /* variable var is symbolic */
+    (void)fprintf(fp,"VAR %s_bufin : {",Var_VariableReadName(var));
+    for (i=0; i < range; i++){
+      if (i == (range-1)) 
+	(void)fprintf(fp,"%s_bufin ",
+		      Var_VariableReadSymbolicValueFromIndex(var,i));
+      else
+	(void)fprintf(fp,"%s_bufin, ",
+		      Var_VariableReadSymbolicValueFromIndex(var,i));
+    }
+    (void)fprintf(fp,"};\n");
+  }
+}
Index: vis_dev/vis-2.3/src/ltl/ltl.c
===================================================================
--- vis_dev/vis-2.3/src/ltl/ltl.c	(revision 14)
+++ vis_dev/vis-2.3/src/ltl/ltl.c	(revision 14)
@@ -0,0 +1,2040 @@
+/**CFile***********************************************************************
+
+  FileName    [ltl.c]
+
+  PackageName [ltl]
+
+  Synopsis    [LTL model checking.]
+
+  Author      [Chao Wang <chao.wang@colorado.EDU>]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "ltlInt.h"
+#include <errno.h>
+
+static char rcsid[] UNUSED = "$Id: ltl.c,v 1.74 2009/04/11 01:41:30 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+static jmp_buf timeOutEnv;
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandLtlMc(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandLtl2Aut(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static LtlMcOption_t * ParseLtlMcOptions(int argc, char **argv);
+static LtlMcOption_t * ParseLtlTestOptions(int argc, char **argv);
+static boolean LtlMcAtomicFormulaCheckSemantics(Ctlsp_Formula_t *formula, Ntk_Network_t *network, boolean inputsAllowed);
+static void TimeOutHandle(void);
+static void ShuffleMddIdsToTop(mdd_manager *mddManager, array_t *mddIdArray);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the Ltl package.]
+
+  SideEffects []
+
+  SeeAlso     [Ltl_End]
+
+******************************************************************************/
+void
+Ltl_Init(void)
+{
+  /* LTL model checking. Before using this command, the design must be read
+   * and 'init_verify' has been executed.
+   */
+  Cmd_CommandAdd("ltl_model_check", CommandLtlMc,  0);
+
+  /* Test the LTL->Buechi Automaton Translator, may or may not need to read
+   * the design. But If the design is read, the semantic of the formula
+   * will be checked on the model before translation
+   */
+  Cmd_CommandAdd("ltl_to_aut", CommandLtl2Aut, 0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Ends the Ltl package.]
+
+  SideEffects []
+
+  SeeAlso     [Ltl_Init]
+
+******************************************************************************/
+void
+Ltl_End(void)
+{
+}
+
+
+/**Function********************************************************************
+
+   Synopsis    [Translate the LTL formula into a Buechi automaton.]
+
+   Description [The wrapper of LtlMcFormulaToAutomaton.]
+
+   SideEffects [The returned automaton should be freed by the caller.]
+
+   SeeAlso     [LtlMcFormulaToAutomaton]
+
+******************************************************************************/
+Ltl_Automaton_t *
+Ltl_McFormulaToAutomaton(
+  Ntk_Network_t *network,
+  Ctlsp_Formula_t *Formula,
+  int options_algorithm,
+  int options_rewriting,
+  int options_prunefair,
+  int options_iocompatible,
+  int options_directsim,
+  int options_reversesim,
+  int options_directsimMaximize,
+  int options_verbosity,
+  int checkSemantics
+  )
+{
+  LtlMcOption_t *options = LtlMcOptionAlloc();
+  Ltl_Automaton_t *aut;
+
+  options->algorithm = (Ltl2AutAlgorithm) options_algorithm;
+  if (options_algorithm == Ltl2Aut_WRING_c) {
+    options->rewriting = 1;
+    options->prunefair = 1;
+    options->iocompatible = 1;
+    options->directsim = 1;
+    options->reversesim = 1;
+  }else {
+    options->rewriting = options_rewriting;
+    options->prunefair = options_prunefair;
+    options->iocompatible = options_iocompatible;
+    options->directsim = options_directsim;
+    options->reversesim = options_reversesim;
+  }
+  options->directsimMaximize = options_directsimMaximize;
+  options->verbosity = (Mc_VerbosityLevel) options_verbosity;
+
+  aut = LtlMcFormulaToAutomaton(network, Formula, options, checkSemantics);
+
+  LtlMcOptionFree(options);
+
+  return aut;
+}
+
+
+/**Function********************************************************************
+
+   Synopsis    [Translate the Buechi automaton into a network.]
+
+   Description [A new Hrc_Manager_t is created, in which the network will
+   be stored. The translation goes as the following:
+
+   1) translate the Buechi automaton into a temp file (in blifmv format);
+   2) read in the temp file (into the new hrcMgr) by default blifmv parser
+   3) flatten_hierarchy to get the network   ]
+
+   SideEffects [The returned Hrc_Manager_t should be freed by the caller.]
+
+   SeeAlso     []
+
+******************************************************************************/
+Hrc_Manager_t *
+Ltl_McAutomatonToNetwork(
+  Ntk_Network_t *designNetwork,
+  Ltl_Automaton_t *automaton,
+  int verbosity)
+{
+  FILE *fp;
+  Hrc_Manager_t *buechiHrcMgr;
+  Hrc_Node_t    *buechiHrcNode;
+  Ntk_Network_t *buechiNetwork;
+  int flag;
+
+  /* 1) translate the automaton to a temporary blif_mv file */
+  fp = tmpfile();
+  if (fp == NIL(FILE)) {
+    fail("Aut->Ntk: can't open temp file");
+  }
+#ifdef DEBUG_LTLMC
+  if (verbosity >= 2) {
+    fprintf(vis_stdout, "\nPrint the automaton Blif_Mv file:\n");
+    flag = Ltl_AutomatonToBlifMv(vis_stdout, designNetwork, automaton);
+    fprintf(vis_stdout, "\n");
+    fflush(vis_stdout);
+  }
+#endif
+  flag = Ltl_AutomatonToBlifMv(fp, designNetwork, automaton);
+  if (!flag) {
+    return NIL(Hrc_Manager_t);
+  }
+
+  /* 2) read and parse the tmp blifmv file */
+  rewind(fp);
+  error_init();
+  buechiHrcMgr = Io_BlifMvRead(fp, NIL(Hrc_Manager_t), 0, 0, 0);
+  fclose(fp);
+  if (buechiHrcMgr == NIL(Hrc_Manager_t))
+    fail(error_string());
+
+  /* 3) flatten_hierarchy */
+  buechiHrcNode = Hrc_ManagerReadCurrentNode(buechiHrcMgr);
+  buechiNetwork = Ntk_HrcNodeConvertToNetwork(buechiHrcNode, TRUE, (lsList)0);
+  Hrc_NodeAddApplInfo(buechiHrcNode, NTK_HRC_NODE_APPL_KEY,
+		      (Hrc_ApplInfoFreeFn) Ntk_NetworkFreeCallback,
+		      (Hrc_ApplInfoChangeFn) NULL,
+		      (void *) buechiNetwork);
+
+  /* 4) static_order (!!! using the default mddManager) */
+  Ntk_NetworkSetMddManager(buechiNetwork,
+			   Ntk_NetworkReadMddManager(designNetwork));
+  Ord_NetworkOrderVariables(buechiNetwork,
+			    Ord_RootsByDefault_c,
+			    Ord_NodesByDefault_c,
+			    FALSE,
+			    Ord_InputAndLatch_c,
+			    Ord_Unassigned_c,
+			    (lsList)NULL,
+			    0);
+
+  return buechiHrcMgr;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Perform static semantic check of ltl formula on network.]
+
+  Description [Perform static semantic check of ltl formula on network.
+  Specifically, given an atomic formula of the form LHS=RHS, check that the LHS
+  is the name of a latch/wire in the network, and that RHS is of appropriate
+  type (enum/integer) and is lies in the range of the latch/wire values. If LHS
+  is a wire, and inputsAllowed is false, check to see that the algebraic
+  support of the wire consists of only latches and constants.]
+
+  SideEffects []
+
+******************************************************************************/
+boolean
+Ltl_FormulaStaticSemanticCheckOnNetwork(
+  Ctlsp_Formula_t *formula,
+  Ntk_Network_t *network,
+  boolean inputsAllowed
+  )
+{
+  boolean lCheck;
+  boolean rCheck;
+  Ctlsp_Formula_t *leftChild;
+  Ctlsp_Formula_t *rightChild;
+
+  if(formula == NIL(Ctlsp_Formula_t)){
+    return TRUE;
+  }
+
+  if(Ctlsp_FormulaReadType(formula) == Ctlsp_ID_c){
+    return LtlMcAtomicFormulaCheckSemantics(formula, network, inputsAllowed);
+  }
+
+  leftChild = Ctlsp_FormulaReadLeftChild(formula);
+  rightChild = Ctlsp_FormulaReadRightChild(formula);
+
+  lCheck = Ltl_FormulaStaticSemanticCheckOnNetwork(leftChild, network,
+						   inputsAllowed);
+  if(!lCheck)
+    return FALSE;
+
+  rCheck = Ltl_FormulaStaticSemanticCheckOnNetwork(rightChild, network,
+						   inputsAllowed);
+  if (!rCheck)
+    return FALSE;
+
+  return TRUE;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+   Synopsis    [Translate the LTL formula to a Buechi automaton.]
+
+   Description [State-of-the-art Optiomization/Minimization is used to shrink
+   the size of the automaton:
+   1) Rewriting the Formula  (before translation)
+   2) Boolean Minimization   (during translation)
+   3) Automaton Minimization (after translation)
+	 - prune fair states
+	 - simulation-based minimization (io/direct/reverse)
+
+   For more information, refer to: Fabio Somenzi and Roderick Bloem,"Efficient
+   Buechi Automaton from LTL Formula," CAV'00.
+
+   Before translation, the sementics of the formula is checked on the model.
+   In the case it fails, a NIL pointer will be returned.]
+
+   SideEffects [The returned automaton should be freed by the caller.]
+
+   SeeAlso     []
+
+******************************************************************************/
+Ltl_Automaton_t *
+LtlMcFormulaToAutomaton(
+  Ntk_Network_t *network,
+  Ctlsp_Formula_t *Formula,
+  LtlMcOption_t *options,
+  int checkSemantics)
+{
+
+  char *tmpString;
+  Ctlsp_Formula_t *ltlFormula, *negFormula;
+  LtlTableau_t *tableau;
+  Ltl_Automaton_t *automaton;
+
+  /* check the semantic of the formula on the given network */
+  if (checkSemantics && network != NIL(Ntk_Network_t)) {
+    if (!network) {
+      fprintf(vis_stderr,
+	      "ltl_mc error: empty network. use flatten_hierarchy\n");
+      return NIL(Ltl_Automaton_t);
+    }
+    error_init();
+    if (!Ltl_FormulaStaticSemanticCheckOnNetwork(Formula, network, 1)) {
+      fprintf(vis_stderr,
+	      "ltl_mc error: formula semantic check on design fails:\n%s\n",
+	      error_string());
+      return NIL(Ltl_Automaton_t);
+    }
+  }
+
+  /* print out the given LTL formula */
+  fprintf(vis_stdout, "Formula: ");
+  Ctlsp_FormulaPrint(vis_stdout, Formula);
+  fprintf(vis_stdout, "\n");
+
+  /* Negate Formula and Expand the abbreaviations */
+  negFormula = Ctlsp_FormulaCreate(Ctlsp_NOT_c, Formula, NIL(Ctlsp_Formula_t));
+  ltlFormula = Ctlsp_LtlFormulaExpandAbbreviation(negFormula);
+  tmpString = Ctlsp_FormulaConvertToString(negFormula);
+  FREE(negFormula);
+#ifdef DEBUG_LTLMC
+  if (options->verbosity)
+    fprintf(vis_stdout, "\nNegation Print: %s\n", tmpString);
+#endif
+
+  /* 1) Simplify the formula by 'Rewriting' */
+  if (options->rewriting) {
+    Ctlsp_Formula_t *tmpF = ltlFormula;
+    ltlFormula = Ctlsp_LtlFormulaSimpleRewriting(ltlFormula);
+    Ctlsp_FormulaFree(tmpF);
+  }
+
+  /* create the alph_beta table */
+  tableau = LtlTableauGenerateTableau(ltlFormula);
+  tableau->verbosity = options->verbosity;
+  tableau->algorithm = options->algorithm;
+  tableau->booleanmin = options->booleanmin;
+#ifdef DEBUG_LTLMC
+  /* print out the tableau rules */
+  if (options->verbosity > 1)
+    LtlTableauPrint(vis_stdout, tableau);
+#endif
+
+  /* we dont' need this formula any more */
+  Ctlsp_FormulaFree(ltlFormula);
+
+
+  /* 2) create the automaton */
+  automaton = LtlAutomatonGeneration(tableau);
+  automaton->name = tmpString;
+
+  /* 3-1) minimize the automaton by Pruning fairness */
+  if (options->prunefair) {
+#ifdef DEBUG_LTLMC
+    if (options->verbosity >= McVerbosityMax_c) {
+      Ltl_AutomatonPrint(automaton, options->verbosity);
+      fprintf(vis_stdout, "\nPruneF-Minimization:\n");
+    }
+#endif
+    Ltl_AutomatonMinimizeByPrune(automaton, options->verbosity) ;
+  }
+
+  /* 3-2) minimize the automaton by I/O compatible and dominance */
+  if (options->iocompatible) {
+#ifdef DEBUG_LTLMC
+    if (options->verbosity >= McVerbosityMax_c) {
+      Ltl_AutomatonPrint(automaton, options->verbosity);
+      fprintf(vis_stdout, "\nIOC-Minimization:\n");
+    }
+#endif
+    while(Ltl_AutomatonMinimizeByIOCompatible(automaton,options->verbosity));
+  }
+
+  /* 3-3) minimize the automaton by Direct Simulation */
+  if (options->directsim) {
+#ifdef DEBUG_LTLMC
+    if (options->verbosity >= McVerbosityMax_c) {
+      Ltl_AutomatonPrint(automaton, options->verbosity);
+      fprintf(vis_stdout, "\nDirSim-Minimization:\n");
+    }
+#endif
+    Ltl_AutomatonMinimizeByDirectSimulation(automaton, options->verbosity);
+  }
+
+  /* 3-4) minimize the automaton by Direct Simulation */
+  if (options->reversesim) {
+#ifdef DEBUG_LTLMC
+    if (options->verbosity >= McVerbosityMax_c) {
+      Ltl_AutomatonPrint(automaton, options->verbosity);
+      fprintf(vis_stdout, "\nRevSim-Minimization:\n");
+    }
+#endif
+    Ltl_AutomatonMinimizeByReverseSimulation(automaton, options->verbosity);
+  }
+
+  /* 3-5) minimize the automaton by Pruning fairness */
+  if (options->prunefair) {
+#ifdef DEBUG_LTLMC
+    if (options->verbosity >= McVerbosityMax_c) {
+      Ltl_AutomatonPrint(automaton, options->verbosity);
+      fprintf(vis_stdout, "\nPruneF-Minimization:\n");
+    }
+#endif
+    Ltl_AutomatonMinimizeByPrune(automaton, options->verbosity) ;
+  }
+  /* print out the Buechi automaton */
+  if (options->verbosity) {
+    Ltl_AutomatonPrint(automaton, options->verbosity);
+  }
+
+  return automaton;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Load the Fairness Constraint for the compFsm.]
+
+  Description [The fairness constraint comes from two places:
+      1) the fairness constraints on the model (designFairness);
+      2) the fairsets from the Buechi automaton (the LTL formula).
+  *AutomatonStrength is unchanged unless there are external fairness and the
+  automaton is terminal (in which case the strength is assumed to be "1-weak".]
+
+  SideEffects [*AutomatonStrength might be changed.]
+
+******************************************************************************/
+void
+LtlFsmLoadFairness(
+  Fsm_Fsm_t *compFsm,
+  Fsm_Fairness_t *designFairness,
+  int NumberOfFairSets,
+  int *AutomatonStrength)
+{
+  array_t *fairformulaArray;
+  Ctlp_Formula_t *F;
+  int j;
+
+  /* The fairness constraint on the model (before ltl_model_check is invoked)
+   * should be Buechi fairness
+   */
+  if (!Fsm_FairnessTestIsBuchi(designFairness)) {
+    fprintf(vis_stderr, "ltl_mc error: Can not handle non-Buchi Fairness \n");
+    assert(0);
+  }
+
+  /* store the new fairness constraint (for compFsm) */
+  fairformulaArray = array_alloc(Ctlp_Formula_t *, 0);
+
+  /* copy the fairness constraints from the automaton */
+  if (*AutomatonStrength == Mc_Aut_Strong_c/*2*/) {
+    if (NumberOfFairSets > 0) {
+      for (j=0; j<NumberOfFairSets; j++) {
+	char tmpstr[30];
+	sprintf(tmpstr, "fair%d$AUT$NTK2", j+1);
+	F = Ctlp_FormulaCreate(Ctlp_ID_c, (void *)util_strsav(tmpstr),
+			       (void *)util_strsav("1"));
+	array_insert_last(Ctlp_Formula_t *, fairformulaArray, F);
+      }
+    }else {
+      F = Ctlp_FormulaCreate(Ctlp_ID_c, (void *)util_strsav("fair1$AUT$NTK2"),
+			     (void *)util_strsav("1"));
+      array_insert_last(Ctlp_Formula_t *, fairformulaArray, F);
+    }
+  }
+
+  /* copy the fairness constraints on the model */
+  for (j=0; j<Fsm_FairnessReadNumConjunctsOfDisjunct(designFairness, 0); j++) {
+    F = Fsm_FairnessReadFinallyInfFormula(designFairness, 0, j);
+    if (array_n(fairformulaArray) && Ctlp_FormulaReadType(F) == Ctlp_TRUE_c)
+      continue;
+    array_insert_last(Ctlp_Formula_t *,fairformulaArray, Ctlp_FormulaDup(F));
+  }
+
+  /* this is a conservative conclusion ! */
+  if (*AutomatonStrength == Mc_Aut_Terminal_c /*0*/) {
+    F = array_fetch(Ctlp_Formula_t *, fairformulaArray, 0);
+    if (array_n(fairformulaArray) > 1 ||
+	Ctlp_FormulaReadType(F) != Ctlp_TRUE_c) {
+      *AutomatonStrength = Mc_Aut_Weak_c /*1*/;
+    }
+  }
+
+  /* update the fairness constraints on 'compFsm' */
+  Fsm_FsmFairnessUpdate(compFsm, fairformulaArray);
+
+  array_free(fairformulaArray);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Alloc Memory for LtlMcOption_t.]
+
+  SideEffects []
+
+  SeeAlso []
+******************************************************************************/
+LtlMcOption_t *
+LtlMcOptionAlloc(void)
+{
+  LtlMcOption_t *result = ALLOC(LtlMcOption_t, 1);
+  if (result == NIL(LtlMcOption_t))
+    return NIL(LtlMcOption_t);
+  memset(result, 0, sizeof(LtlMcOption_t));
+
+  result->algorithm = Ltl2Aut_WRING_c;
+  result->schedule = McGSH_EL_c;
+  result->lockstep = MC_LOCKSTEP_OFF;
+  result->outputformat = Aut2File_ALL_c;
+
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Free LtlMcOption_t, and close the ltl formula file.]
+
+  SideEffects []
+
+  SeeAlso []
+******************************************************************************/
+void
+LtlMcOptionFree(
+  LtlMcOption_t *result)
+{
+  if (result->ltlFile)
+    fclose(result->ltlFile);
+
+  if (result->debugFile)
+    fclose(result->debugFile);
+
+  if (result->outputfilename)
+    FREE(result->outputfilename);
+
+  FREE(result);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Check LTL formulae given in file are modeled by flattened network]
+
+  CommandName [ltl_model_check]
+
+  CommandSynopsis [perform LTL model checking on a flattened network]
+
+  CommandArguments [ \[-a &lt;ltl2aut_algorithm&gt;\] \[-b\]
+  \[-d &lt;dbg_level&gt;\] \[-f &lt;dbg_file&gt;\] \[-h\] \[-i\] \[-m\] \[-s\]
+  \[-t &lt;time_out_period&gt;\]\[-v &lt;verbosity_level&gt;\]
+  \[-A &lt;le_method&gt;\]
+  \[-D &lt;dc_level&gt;\] \[-L &lt;lockstep_mode&gt;\] \[-S &lt;schedule&gt;\]
+  \[-F\] \[-X\] \[-Y\] \[-M\] &lt;ltl_file&gt;] \[-Z\]
+
+
+  CommandDescription [Performs LTL model checking on a flattened
+  network.  Before calling this command, the user should have
+  initialized the design by calling the command <A
+  HREF="init_verifyCmd.html"> <code> init_verify</code></A>.
+  Regardless of the options, no 'false positives' or 'false negatives'
+  will occur: the result is correct for the given circuit.  <p>
+
+  Properties to be verified should be provided as LTL formulae in the
+  file <code>ltl_file</code>.  Note that the support of any wire
+  referred to in a formula should consist only of latches.  For the
+  precise syntax of LTL formulas, see the <A
+  HREF="../ctl/ctl/ctl.html"> VIS CTL and LTL syntax manual</A>.
+  <p>
+
+  A formula passes iff it is true for all initial states of the
+  system.  Therefore, in the presence of multiple initial states, if a
+  formula fails, the negation of the formula may also fail.<p>
+
+  If a formula does not pass, a (potentially partial) proof of failure
+  (referred to as a debug trace) is demonstrated. Fair paths are
+  represented by a finite sequence of states (the stem) leading to a
+  fair cycle, i.e. a cycle on which there is a state from each
+  fairness condition. Whether demostrate the proof or not can be
+  specified (see option <code>-d</code>).  <p>
+
+
+  Command options:
+  <p>
+
+  <dl>
+
+  <dt> -a <code> &lt;ltl2aut_algorithm&gt; </code> <dd> Specify the algorithm
+  used in LTL formula -> Buechi automaton translation.
+  <p> <dd> <code> ltl2aut_algorithm</code> must be one  of the following:
+
+  <p><code>0</code>: GPVW.
+
+  <p><code>1</code>: GPVW+.
+
+  <p><code>2</code>: LTL2AUT.
+
+  <p><code>3</code>: WRING (default).
+
+  <p>
+
+  <dt> -b
+  <dd> Use boolean minimization during the LTL to Automaton translation.
+  <p>
+
+  <dt> -d <code> &lt;dbg_level&gt; </code> <dd> Specify whether to demonstrate
+  a counter-example when the system fails a formula being checked.
+
+  <p> <dd> <code> dbg_level</code> must be one of the following:
+
+  <p><code>0</code>: No debugging performed.
+  <code>dbg_level</code>=<code>0</code> is the default.
+
+  <p><code>1</code>: Generate a counter-example (a path to a fair cycle).
+  <p>
+
+  <dt> -f &lt;<code>dbg_file</code>&gt;
+  <dd> Write the debugger output to <code>dbg_file</code>.
+  <p>
+
+
+  <dt> -h
+  <dd> Print the command usage.
+  <p>
+
+  <dt> -i
+  <dd> Print input values causing transitions between states during debugging.
+  Both primary and pseudo inputs are printed.
+  <p>
+
+  <dt> -m
+  <dd> Pipe debugger output through the UNIX utility  more.
+  <p>
+
+  <dt> -t  <code>&lt;timeOutPeriod&gt;</code>
+  <dd> Specify the time out period (in seconds) after which the command aborts.
+  By default this option is set to infinity.
+  <p>
+
+  <dt> -s
+  <dd> Print debug output in the format accepted by the
+       <A HREF="simulateCmd.html"><code>simulate</code></A> command.
+  <p>
+
+
+  <dt> -v  <code>&lt;verbosity_level&gt;</code>
+  <dd> Specify verbosity level. This sets the amount of feedback  on CPU usage
+  and code status.
+
+  <br><code>verbosity_level</code>  must be one of the following:<p>
+
+  <code>0</code>: No feedback provided. This is the default.<p>
+
+  <code>1</code>: Feedback on code location.<p>
+
+  <code>2</code>: Feedback on code location and CPU usage.<p>
+
+  <p>
+
+  <dt> -A <code> &lt;le_method&gt; </code>
+  <dd>
+  Specify whether the compositional SCC analysis algorithm, Divide and
+  Compose (DnC), is enabled for language emptiness checking.
+  The DnC algorithm first enumerates fair SCCs in an over-approximated
+  abstract model, and then successively refines them in the more
+  concrete models.
+  Since non-fair SCCs can be ignored in the more concrete models, a
+  potentially large part of the state space are pruned away early on
+  when the computations are cheap.
+  <p>
+
+  <dd>
+  <code> le_method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: no use of Divide and Compose (Default). <p>
+  <code> 1 </code>: use Divide and Compose. <p>
+
+  <dt> -D <code> &lt;dc_level&gt; </code>
+
+  <dd> Specify extent to which don't cares are used to simplify MDDs in model
+  checking.  Don't cares are minterms on which the value taken by functions
+  does not affect the computation; potentially, these minterms can be used to
+  simplify MDDs and reduce the time taken to perform model checking.
+
+  <br>
+  <code> dc_level </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: No don't cares are used.
+
+  <p> <code> 1 </code>: Use unreachable states as don't cares. This is the
+  default.
+
+  <p> <code> 2 </code>: Use unreachable states as don't cares and in the EU
+  computation, use 'frontiers' for image computation.<p>
+
+  <code> 3 </code>: First compute an overapproximation of the reachable states
+  (ARDC), and use that as the cares set.  Use `frontiers' for image
+  computation.  For help on controlling options for ARDC, look up help on the
+  command: <A HREF="print_ardc_optionsCmd.html">print_ardc_options</A>. Refer
+  to Moon, Jang, Somenzi, Pixley, Yuan, "Approximate Reachability Don't Cares
+  for {CTL} Model Checking", ICCAD98, and to two papers by Cho et al, IEEE TCAD
+  December 1996: one is for State Space Decomposition and the other is for
+  Approximate FSM Traversal.<p>
+
+  <dt> -S <code> &lt;schedule&gt; </code>
+
+  <dd> Specify schedule for GSH algorithm, which generalizes the
+  Emerson-Lei algorithm and is used to compute greatest fixpoints.
+  The choice of schedule affects the sequence in which EX and EU
+  operators are applied.  It makes a difference only when fairness
+  constraints are specified.
+
+  <br>
+  <code> &lt;schedule&gt; </code> must be one of the following:
+
+  <p> <code> EL </code>: EU and EX operators strictly alternate.  This
+  is the default.
+
+  <p> <code> EL1 </code>: EX is applied once for every application of all EUs.
+
+  <p> <code> EL2 </code>: EX is applied repeatedly after each application of
+  all EUs.
+
+  <p> <code> budget </code>: a hybrid of EL and EL2
+
+  <p> <code> random </code>: enabled operators are applied in
+  (pseudo-)random order.
+
+  <p> <code> off </code>: GSH is disabled, and the old algorithm is
+  used instead.  The old algorithm uses the <code> EL </code>, but the
+  termination checks are less sophisticated than in GSH.
+  <p>
+
+  <dt> -F
+
+  <dd> Use forward analysis in the computation of the greatest fixpoint.
+  This option is incompatible with -d 1 or higher and can only be used
+  with -D 1.
+
+  <dt> -L <code> &lt;lockstep_mode&gt; </code>
+
+  <dd> Use the lockstep algorithm, which is based on fair SCC enumeration.
+
+  <br>
+  <code> &lt;lockstep_mode&gt; </code> must be one of the following:
+
+  <p> <code> off </code>: Lockstep is disabled.  This is the default.
+  Language emptiness is checked by computing a hull of the fair SCCs.
+
+  <p> <code> on </code>: Lockstep is enabled.
+
+  <p> <code> all </code>: Lockstep is enabled; all fair SCCs are
+  enumerated instead of terminating as soon as one is found.  This can
+  be used to study the SCCs of a graph, but it is slower than the
+  default option.
+
+  <p> <code> n </code>: (n is a positive integer).  Lockstep is
+  enabled and up to <code> n </code> fair SCCs are enumerated.  This
+  is less expensive than <code> all </code>, but still less efficient
+  than <code> on </code>, even when <code> n = 1 </code>.
+
+  <dt> -X
+  <dd> Disable strength reduction (use different decision procedures for
+  strong, weak, and terminal automaton). Strength reduction is the default.
+  Refer to Bloem, Ravi, Somenzi, "Efficient Decision Procedures for LTL Model
+  Checking," CAV99.
+  <p>
+
+  <dt> -Y
+  <dd> Disable incremental construction of the partition for (MxA). Instead,
+  build a new partition from the scratch. Incremental construction of the
+  partition is the default.
+  <p>
+
+  <dt> -Z
+  <dd> Add arcs into the Buechi automaton by direct simulation relation, to
+  heuristically reduce the length of shortest counter-example in model
+  checking. Refer to Awedh and Somenze, "Proving More Properties with
+  Bounded Model Checking," CAV04.
+  <p>
+
+  <dt> -M
+  <dd> Maximize (adding arcs to) Buechi automaton using Direct Simulation.
+
+  <dt> <code> &lt;ltl_file&gt; </code>
+
+  <dd> File containing LTL formulas to be model checked.
+  </dl>
+
+  Related "set" options:
+  <dl>
+  <dt> ltl_change_bracket &lt;yes/no&gt;
+  <dd> Vl2mv automatically converts "\[\]" to "&lt;&gt;" in node names,
+  therefore CTL* parser does the same thing. However, in some cases a user
+  does not want to change node names in CTL* parsing. Then, use this set
+  option by giving "no". Default is "yes".
+  <p>
+
+  See also commands : model_check, approximate_model_check,
+  incremental_ctl_verification ]
+
+  Description [First, the LTL formula is parsed and translated into a
+  Buechi automaton (minimization techniques can by applied during the process).
+
+  Then, the Buechi Automaton is translated into a Hrc_Node in a newly created
+  Hrc_Manager. flatten_hierarchy/static_order are used to obtain the automaton
+  Network. In this process the same mddManager (as that of the design network)
+  is used.
+
+  Now we need to compose the (M x A). We choose to append the automaton network
+  to the design network. Partition is updated (or regenerated) for the composed
+  network.
+
+  A new FSM is created and the fairness are loaded in it. The fairness
+  constraints comes from both the design network and the automaton network.
+  Finally we use Mc_FsmCheckLanguageEmptiness() to do the language emptiness
+  checking. "Strength Reduction Technique" -- using different decision
+  procedures for strong, weak, and terminal automaon -- is used.
+
+  After the model check, we free everything we created in this command:
+  partition for (MxA), the new FSM, newly-created network nodes, the
+  automaton network as well as the automaton Hrc_Manager.
+
+  If necessary, the result mdd (which is the bad state -- a state that leads
+  to a fair path) can be saved. (for example, in the CTL*  model checker).]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandLtlMc(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  array_t *ltlArray;
+  LtlMcOption_t *options;
+  Ctlsp_Formula_t *ltlFormula;
+  Ltl_Automaton_t *automaton;
+  LtlTableau_t *tableau;
+  Hrc_Manager_t *buechiHrcMgr;
+  Hrc_Node_t *designNode;
+  Fsm_Fsm_t *designFsm = NIL(Fsm_Fsm_t);
+  Fsm_Fsm_t *compFsm = NIL(Fsm_Fsm_t);
+  Ntk_Network_t *designNetwork,*buechiNetwork = NIL(Ntk_Network_t);
+  Ntk_Node_t *node1, *node2;
+  array_t *modelCareStatesArray;
+  lsGen lsgen2;
+  lsList nodeList;
+  graph_t *partition, *save_partition;
+  mdd_t *fairInitStates, *modelCareStates, *mddOne;
+  char *designModelName, *name1;
+  int i;
+  long startLtlMcTime, endLtlMcTime;
+  static int timeOutPeriod = 0;
+
+  Img_ResetNumberOfImageComputation(Img_Both_c);
+
+  if (!(options = ParseLtlMcOptions(argc, argv))) {
+    return 1;
+  }
+  timeOutPeriod = options->timeOutPeriod;
+
+  if (options->dbgLevel != 0 && options->direction == McFwd_c) {
+    (void) fprintf(vis_stderr, "** ltl_mc error: -d is incompatible with -F\n");
+    LtlMcOptionFree(options);
+    return 1;
+  }
+  if (options->dcLevel !=  McDcLevelRch_c && options->direction == McFwd_c) {
+    (void) fprintf(vis_stderr, "** ltl_mc error: -F can only be used with -D1\n");
+    LtlMcOptionFree(options);
+    return 1;
+  }
+
+  /* 'designFsm' and 'designNetwork' are for the model */
+  designFsm = Fsm_HrcManagerReadCurrentFsm(*hmgr);
+  if (designFsm == NIL(Fsm_Fsm_t)) {
+    return 1;
+  }
+  designNetwork = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+
+  /* Parse LTL formulae */
+  ltlArray = Ctlsp_FileParseFormulaArray(options->ltlFile);
+  if (ltlArray != NIL(array_t)) {
+    array_t *tmpArray = Ctlsp_FormulaArrayConvertToLTL(ltlArray);
+    Ctlsp_FormulaArrayFree(ltlArray);
+    ltlArray = tmpArray;
+  }
+  if (ltlArray == NIL(array_t)) {
+    (void) fprintf(vis_stderr,
+		   "** ltl_mc error: error in parsing formulas from file\n");
+    LtlMcOptionFree(options);
+    return 1;
+  }
+  /* Semantic Check of the Ltl formula array on the network */
+  arrayForEachItem(Ctlsp_Formula_t *, ltlArray, i, ltlFormula) {
+    if (!Ltl_FormulaStaticSemanticCheckOnNetwork(ltlFormula,
+						 designNetwork, 1)) {
+      fprintf(vis_stderr,
+	      "ltl_mc error: formula semantic check on design fails:\n%s\n",
+	      error_string());
+      Ctlsp_FormulaArrayFree(ltlArray);
+      LtlMcOptionFree(options);
+      return 1;
+    }
+  }
+
+  /* Set time out processing (if timeOutPeriod is set) */
+  if (timeOutPeriod > 0) {
+    (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
+    (void) alarm(timeOutPeriod);
+    if (setjmp(timeOutEnv) > 0) {
+      (void) fprintf(vis_stdout, "# LTL_MC: Ltl modelchecking - timeout occurred after %d seconds.\n", timeOutPeriod);
+      (void) fprintf(vis_stdout, "# LTL_MC: data may be corrupted.\n");
+      if (options->verbosity > McVerbosityNone_c) {
+	(void) fprintf(vis_stdout, "-- total %d image computations and %d preimage computations\n", Img_GetNumberOfImageComputation(Img_Forward_c), Img_GetNumberOfImageComputation(Img_Backward_c));
+      }
+      alarm(0);
+      return 1;
+    }
+  }
+  startLtlMcTime = util_cpu_time();
+
+  mddOne = mdd_one(Ntk_NetworkReadMddManager(designNetwork));
+
+  /* Start LTL model checking for each formula */
+  for (i=0; i<array_n(ltlArray); i++) {
+    st_table *tbl;
+    array_t *mddIds;
+    lsList rootList;
+    int NumberOfFairSet, AutomatonStrength;
+    long initialTime, finalTime; /* for checking each formula */
+    int nImgComps, nPreComps;
+
+    /* stats */
+    if (options->verbosity > McVerbosityNone_c) {
+      initialTime = util_cpu_time();
+      nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c);
+      nPreComps = Img_GetNumberOfImageComputation(Img_Backward_c);
+    } else {
+      /* to remove uninitialized variable warning */
+      initialTime = 0;
+      nImgComps = 0;
+      nPreComps = 0;
+    }
+    ltlFormula = array_fetch(Ctlsp_Formula_t *, ltlArray, i);
+
+    /*---------------------------------------------------------------------
+     * 1) create the Buechi Automaton/Network/Mdd_Order/Partition in a new
+     * Hrc_Manager. It shares nothing with the Design but the mddManager.
+     *--------------------------------------------------------------------*/
+    automaton = LtlMcFormulaToAutomaton(designNetwork, ltlFormula, options, 1);
+    assert(automaton != NIL(Ltl_Automaton_t));
+
+    if (options->noStrengthReduction)
+      AutomatonStrength = Mc_Aut_Strong_c /*2*/;
+    else
+      AutomatonStrength = Ltl_AutomatonGetStrength(automaton);
+
+    /* add arcs by Direct Simulation, to reduce the counter-example length */
+    if (options->directsimMaximize) {
+#ifdef DEBUG_LTLMC
+      if (options->verbosity >= McVerbosityMax_c) {
+	Ltl_AutomatonPrint(automaton, options->verbosity);
+	fprintf(vis_stdout, "\nDirSim-Maximization:\n");
+      }
+#endif
+      Ltl_AutomatonMaximizeByDirectSimulation(automaton, options->verbosity);
+    }
+    NumberOfFairSet = lsLength(automaton->Fair);
+    buechiHrcMgr = Ltl_McAutomatonToNetwork(designNetwork, automaton,
+					    options->verbosity);
+    assert(buechiHrcMgr != NIL(Hrc_Manager_t));
+    tableau = automaton->tableau;
+    Ltl_AutomatonFree((gGeneric) automaton);
+    LtlTableauFree(tableau);
+    buechiNetwork =  Ntk_HrcManagerReadCurrentNetwork(buechiHrcMgr);
+
+    /*---------------------------------------------------------------------
+     * 2) build (M x A) by attaching buechiNetwork(A) to designNetwork(M).
+     * The result network M x A (designNetwork) shares some data with the
+     * buechiNetwork (Variables, and Tables). The newly created nodes in
+     * designNetwork retain their MddId in buechiNetwork
+     *--------------------------------------------------------------------*/
+    /* 2-a) Retrieve the Model (in the default hrc_manager) */
+    designNode = Hrc_ManagerReadCurrentNode(*hmgr);
+    designModelName = Hrc_NodeReadModelName(designNode);
+    /* 2-b) Attach buechiNetwork to designNetwork */
+    tbl = st_init_table(strcmp, st_strhash);
+    Ntk_NetworkAppendNetwork(designNetwork, buechiNetwork, tbl);
+    st_free_table(tbl);
+
+    /* Here we have the choice of incrementally build the partition,
+     * or build it from scratch. In both cases, the original partition
+     * will be saved (and restored later)
+     */
+    if (!options->noIncrementalPartition) {
+      rootList = lsCreate();
+      mddIds = array_alloc(int, 2);
+      /* 2-c) Assign MddId to the newly-created nodes */
+      Ntk_NetworkForEachNode(buechiNetwork, lsgen2, node2) {
+	if (!Ntk_NodeTestIsPrimaryInput(node2)) {
+	  name1 = util_strcat3(Ntk_NodeReadName(node2),"$NTK2", "");
+	  node1 = Ntk_NetworkFindNodeByName(designNetwork, name1);
+	  Ntk_NodeSetMddId(node1, Ntk_NodeReadMddId(node2));
+	  if (!strcmp(name1, "state$AUT$NTK2"))
+	    array_insert(int, mddIds, 1, Ntk_NodeReadMddId(node1));
+	  else if (!strcmp(name1, "state$AUT$NS$NTK2"))
+	    array_insert(int, mddIds, 0, Ntk_NodeReadMddId(node1));
+	  else if (!strcmp(name1, "selector$AUT$NTK2"))
+	    array_insert(int, mddIds, 2, Ntk_NodeReadMddId(node1));
+	  FREE(name1);
+	  if (Ntk_NodeTestIsCombOutput(node1))
+	    lsNewEnd(rootList, (lsGeneric)node1, (lsHandle *)0);
+	}
+      }
+      /* move the automaton variables to the top most -- this is believed
+       * to be an optimal ordering */
+      if (!options->noShuffleToTop)
+	ShuffleMddIdsToTop(Ntk_NetworkReadMddManager(designNetwork), mddIds);
+      array_free(mddIds);
+
+      /* 2-d) Create the Partition information for (M x A) */
+      save_partition = Part_NetworkReadPartition(designNetwork);
+      partition = Part_PartitionDuplicate(save_partition);
+      Part_UpdatePartitionFrontier(designNetwork, partition, rootList,
+				   (lsList)0, mddOne);
+      Ntk_NetworkSetApplInfo(designNetwork, PART_NETWORK_APPL_KEY,
+			     (Ntk_ApplInfoFreeFn) Part_PartitionFreeCallback,
+			     (void *)partition);
+      lsDestroy(rootList, (void (*)(lsGeneric))0);
+
+    }else {
+      mddIds = array_alloc(int, 2);
+      /* 2-c) Assign MddId to the newly-created nodes */
+      Ntk_NetworkForEachNode(buechiNetwork, lsgen2, node2) {
+	if (Ntk_NodeTestIsPrimaryInput(node2))  continue;
+	name1 = util_strcat3(Ntk_NodeReadName(node2),"$NTK2", "");
+	node1 = Ntk_NetworkFindNodeByName(designNetwork, name1);
+	Ntk_NodeSetMddId(node1, Ntk_NodeReadMddId(node2));
+	if (!strcmp(name1, "state$AUT$NTK2"))
+	  array_insert(int, mddIds, 1, Ntk_NodeReadMddId(node1));
+	else if (!strcmp(name1, "state$AUT$NS$NTK2"))
+	  array_insert(int, mddIds, 0, Ntk_NodeReadMddId(node1));
+	else if (!strcmp(name1, "selector$AUT$NTK2"))
+	  array_insert(int, mddIds, 2, Ntk_NodeReadMddId(node1));
+	FREE(name1);
+      }
+      /* move the automaton variables to the top most. This might be the
+       * best BDD variable ordering for (M x A)! */
+      if (!options->noShuffleToTop)
+	ShuffleMddIdsToTop(Ntk_NetworkReadMddManager(designNetwork), mddIds);
+      array_free(mddIds);
+
+      /* 2-d) Create the Partition information for (M x A) */
+      nodeList = lsCreate();
+      partition = Part_NetworkCreatePartition(designNetwork,
+					      designNode,
+					      designModelName,
+					      (lsList)0,
+					      (lsList)0,
+					      NIL(mdd_t),
+					      Part_Default_c,
+					      nodeList,
+					      FALSE, 0, 0);
+      save_partition = Part_NetworkReadPartition(designNetwork);
+      Ntk_NetworkSetApplInfo(designNetwork, PART_NETWORK_APPL_KEY,
+			     (Ntk_ApplInfoFreeFn) Part_PartitionFreeCallback,
+			     (void *)partition);
+
+      lsDestroy(nodeList, (void (*)(lsGeneric))0);
+    }
+
+    /*---------------------------------------------------------------------
+     * 3) Create the FSM for (M x A) and load Fairness constraints
+     *--------------------------------------------------------------------*/
+    /* try to get a reduced Fsm (w.r.t. each individual property) first */
+    {
+      array_t *ctlArray = array_alloc(Ctlp_Formula_t *, 0);
+      Ctlp_Formula_t *ctlF = Ctlp_FormulaCreate(Ctlp_ID_c,
+						util_strsav("state$AUT$NTK2"),
+						util_strsav("Trap"));
+      array_insert(Ctlp_Formula_t *, ctlArray, 0, ctlF);
+      compFsm = Mc_ConstructReducedFsm(designNetwork, ctlArray);
+      Ctlp_FormulaFree(ctlF);
+      array_free(ctlArray);
+      if (compFsm == NIL(Fsm_Fsm_t))
+	compFsm = Fsm_FsmCreateFromNetworkWithPartition(designNetwork,
+							NIL(graph_t));
+    }
+    /* merge fairnesses from outside and those from the automaton ... */
+    LtlFsmLoadFairness(compFsm, Fsm_FsmReadFairnessConstraint(designFsm),
+		       NumberOfFairSet, &AutomatonStrength);
+
+
+    /*---------------------------------------------------------------------
+     * 4) Language emptiness checking (store result if necessary)
+     *--------------------------------------------------------------------*/
+    if (options->dcLevel == McDcLevelArdc_c) {
+      Fsm_ArdcOptions_t *ardcOptions = Fsm_ArdcAllocOptionsStruct();
+      array_t *tmpArray;
+      long startRchTime;
+      Fsm_ArdcGetDefaultOptions(ardcOptions);
+      startRchTime = util_cpu_time();
+      tmpArray =
+	Fsm_ArdcComputeOverApproximateReachableStates(compFsm, 0,
+						      options->verbosity,
+						      0, 0, 0, 0, 0, 0,
+						      ardcOptions);
+      modelCareStatesArray = mdd_array_duplicate(tmpArray);
+      FREE(ardcOptions);
+      if (options->verbosity > McVerbosityNone_c)
+	Fsm_ArdcPrintReachabilityResults(compFsm,
+					 util_cpu_time() - startRchTime);
+    }else if (options->dcLevel >= McDcLevelRch_c) {
+      long startRchTime;
+      startRchTime = util_cpu_time();
+      modelCareStates =
+	Fsm_FsmComputeReachableStates(compFsm, 0, options->verbosity, 0, 0,
+				      (options->lockstep != MC_LOCKSTEP_OFF),
+				      0, 0, Fsm_Rch_Default_c, 0, 0,
+				      NIL(array_t), FALSE, NIL(array_t));
+      if (options->verbosity > McVerbosityNone_c) {
+	Fsm_FsmReachabilityPrintResults(compFsm,
+					util_cpu_time() - startRchTime,
+					Fsm_Rch_Default_c);
+      }
+      modelCareStatesArray = array_alloc(mdd_t *, 0);
+      array_insert_last(mdd_t *, modelCareStatesArray, modelCareStates);
+    } else {
+      modelCareStates = mdd_one(Fsm_FsmReadMddManager(compFsm));
+      modelCareStatesArray = array_alloc(mdd_t *, 0);
+      array_insert_last(mdd_t *, modelCareStatesArray, modelCareStates);
+    }
+    /*
+    Fsm_MinimizeTransitionRelationWithReachabilityInfo(compFsm,
+						       Img_Backward_c,
+						       options->verbosity > 1);
+    */
+
+    /* language emptiness checking */
+    fairInitStates = Mc_FsmCheckLanguageEmptiness(compFsm,
+						  modelCareStatesArray,
+						  (Mc_AutStrength_t) AutomatonStrength,
+						  options->leMethod,
+						  options->dcLevel,
+						  options->dbgLevel,
+						  options->printInputs,
+						  options->verbosity,
+						  options->schedule,
+						  options->direction,
+						  options->lockstep,
+						  options->debugFile,
+						  options->useMore,
+						  options->simValue,
+						  "LTL_MC");
+    mdd_array_free(modelCareStatesArray);
+
+    if (fairInitStates)
+      mdd_free(fairInitStates);
+
+    /*---------------------------------------------------------------------
+     * 5) Remove 'A' from designNetwork (M x A), which contains 3 steps:
+     * a) free compFsm/partition
+     * b) remove newly-created nodes from designNetwork;
+     * c) destory buechiHrcMgr (buechiNetwork)
+     *--------------------------------------------------------------------*/
+    Ntk_NetworkAddApplInfo(designNetwork, PART_NETWORK_APPL_KEY,
+			   (Ntk_ApplInfoFreeFn) Part_PartitionFreeCallback,
+			   (void *)save_partition);
+    Fsm_FsmFree(compFsm);
+    {
+      int tmpi, tmpj;
+      Ntk_Node_t *node3, *node4;
+      /* first, remove the newly-added A nodes ('xxxlabel$AUT$NTK2') from the
+       * fanout list of the M nodes */
+      Ntk_NetworkForEachNode(buechiNetwork, lsgen2, node2) {
+	if (strstr(Ntk_NodeReadName(node2), "label$AUT") == NULL)
+	  continue;
+	name1 = util_strcat3(Ntk_NodeReadName(node2),"$NTK2", "");
+	node1 = Ntk_NetworkFindNodeByName(designNetwork, name1);
+	FREE(name1);
+	assert(node1);
+	Ntk_NodeForEachFanin(node1, tmpi, node3) {
+	  array_t *oldFanouts = Ntk_NodeReadFanouts(node3);
+	  array_t *newFanouts;
+	  if (oldFanouts != NIL(array_t)) {
+	    newFanouts = array_alloc(Ntk_Node_t *, 0);
+	    arrayForEachItem(Ntk_Node_t *, oldFanouts, tmpj, node4) {
+	      if (node4 != node1)
+		array_insert_last(Ntk_Node_t *, newFanouts, node4);
+	    }
+	    Ntk_NodeSetFanouts(node3, newFanouts);
+	  }
+	}
+      }
+      /* Now we can safely remove all the newly-added A nodes */
+      Ntk_NetworkForEachNode(buechiNetwork, lsgen2, node2) {
+	if (Ntk_NodeTestIsPrimaryInput(node2))	continue;
+	name1 = util_strcat3(Ntk_NodeReadName(node2),"$NTK2", "");
+	node1 = Ntk_NetworkFindNodeByName(designNetwork, name1);
+	FREE(name1);
+	Ntk_NodeRemoveFromNetwork(designNetwork, node1, 1, 1, 0);
+	Ntk_NodeFree(node1);
+      }
+    }
+    Ntk_NetworkSetMddManager(buechiNetwork, (mdd_manager *)0);
+    Hrc_ManagerFree(buechiHrcMgr);
+
+    if (options->verbosity > McVerbosityNone_c) {
+      finalTime = util_cpu_time();
+      fprintf(vis_stdout, "-- ltl_mc time = %10g\n",
+	(double)(finalTime - initialTime) / 1000.0);
+      fprintf(vis_stdout,
+	      "-- %d image computations and %d preimage computations\n",
+	      Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps,
+	      Img_GetNumberOfImageComputation(Img_Backward_c) - nPreComps);
+    }
+  }
+
+  /* Print stats if verbose. */
+  endLtlMcTime = util_cpu_time();
+  if (options->verbosity > McVerbosityNone_c) {
+    fprintf(vis_stdout, "-- total ltl_mc time: %10g\n",
+	    (double)(endLtlMcTime-startLtlMcTime)/1000.0);
+    fprintf(vis_stdout,
+	    "-- total %d image computations and %d preimage computations\n",
+	    Img_GetNumberOfImageComputation(Img_Forward_c),
+	    Img_GetNumberOfImageComputation(Img_Backward_c));
+  }
+
+  /* Clean-ups */
+  Ctlsp_FormulaArrayFree(ltlArray);
+  LtlMcOptionFree(options);
+  mdd_free(mddOne);
+
+  alarm(0);
+  return 0;		/* normal exit */
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Translate LTL formulae given in file into Buechi automata]
+
+  CommandName [ltl_to_aut]
+
+  CommandSynopsis [translate LTL formulae into Buechi automata]
+
+  CommandArguments [ \[-f &lt;ltl_file&gt;\] \[-m &lt;algorithm&gt;\] \[-o &lt;output_file&gt;\] \[-t &lt;output_format&gt;\] \[-w\] \[-b\] \[-p\] \[-d\] \[-r\] \[-i\] \[-M\] \[-v &lt;verbosity&gt;\] \[-h\] ]
+
+  CommandDescription [Translate the given LTL formulae into Buechi automata,
+  and output the automaton into a file. <p>
+
+  The translation algorithms are the same as the one used in <A
+  HREF="ltl_model_checkCmd.html"> <code> ltl_model_check </code></A>. However,
+  more flexible combination of the options can be used with this command. <p>
+
+  The automaton can be displayed on the screen and written into a file. The
+  format of the output can be dot, blifmv, verilog and smv. <p>
+
+
+  Command options:
+  <p>
+
+  <dl>
+
+  <dt> -f <code> &lt;ltl_file&gt; </code>
+  <dd> The input file containing LTL formulae.
+
+  <dt> -m <code> &lt;algorithm&gt; </code>
+  <dd> Specify the algorithm used in LTL formula -> Buechi automaton
+  translation algorithm.
+  <p> <dd> <code>algorithm</code> must be one  of the following:
+  <p><code>0</code>: GPVW.
+  <p><code>1</code>: GPVW+.
+  <p><code>2</code>: LTL2AUT.
+  <p><code>3</code>: WRING (default).
+
+  <dt> -o <code> &lt;output_file&gt; </code>
+  <dd> Write the automata into this file.
+
+  <dt> -t <code> &lt;output_format&gt; </code>
+  <dd> Specify the output format of the automata.
+  <p> <dd> <code>output_format</code> must be one of the following:
+  <p><code>0</code>: dot.
+  <p><code>1</code>: blif_mv.
+  <p><code>2</code>: verilog.
+  <p><code>3</code>: all of the formats above (default).
+  <p>
+
+
+  <dt> -w
+  <dd> Rewriting the formula before translation.
+
+  <dt> -b
+  <dd> Boolean minimization during the translation.
+
+  <dt> -p
+  <dd> Pruning the fair states in the Buechi automaton.
+
+  <dt> -d
+  <dd> Direct-simulation minimization of the Buechi automaton.
+
+  <dt> -r
+  <dd> Reverse-simulation minimization of the Buechi automaton.
+
+  <dt> -i
+  <dd> Minimization based ont the I/O structural information.
+
+  <dt> -M
+  <dd> Maximize (adding arcs to) Buechi automaton using Direct Simulation.
+
+  <dt> -v <code>&lt;verbosity_level&gt;</code>
+  <dd> Specify verbosity level. It must be one of the following: 0,1,2,3.
+
+  <dt> -h
+  <dd> Print the command usage.
+
+  </dl>
+  ]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandLtl2Aut(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  array_t        *ltlArray;
+  Ctlsp_Formula_t        *ltlFormula;
+  LtlTableau_t           *tableau;
+  Ltl_Automaton_t        *automaton;
+  int            i;
+  LtlMcOption_t *options;
+  int            verbosity = 0;   /* verbosity level */
+  int            algorithm = 0;   /* translation algorithm */
+  int            rewriting = 0;   /* simplify Formula by rewriting */
+  int            booleanmin = 0;  /* boolean minimization */
+  int            prunefair = 0;   /* prune fairness */
+  int            iocompatible = 0;/* simplify by io-compatible */
+  int            directsim = 0;   /* simplify by Direct simulation */
+  int            reversesim = 0;  /* simplify by reverse simulation */
+  int            directsimMaximize = 0;   /* simplify by Direct simulation */
+  Ntk_Network_t  *network;
+  char  *tmpString;
+  long           beginTime, finalTime;
+
+
+  if (!(options = ParseLtlTestOptions(argc, argv))) {
+    return 1;
+  }
+  rewriting = options->rewriting;
+  verbosity = options->verbosity;
+  algorithm = options->algorithm;
+  booleanmin = options->booleanmin;
+  prunefair = options->prunefair;
+  iocompatible = options->iocompatible;
+  directsim = options->directsim;
+  reversesim = options->reversesim;
+  directsimMaximize = options->directsimMaximize;
+
+  beginTime = util_cpu_time();
+  network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+
+  /* Parse the LTL Formulae */
+  ltlArray = Ctlsp_FileParseFormulaArray(options->ltlFile);
+  if (ltlArray != NIL(array_t)) {
+    array_t *tmpArray = Ctlsp_FormulaArrayConvertToLTL(ltlArray);
+    Ctlsp_FormulaArrayFree(ltlArray);
+    ltlArray = tmpArray;
+  }
+  if (ltlArray == NIL(array_t)) {
+    (void) fprintf(vis_stderr,
+		   "** ltl_to_aut error: error in parsing formulas file\n");
+    LtlMcOptionFree(options);
+    return 1;
+  }
+
+  /* For each LTL formula, build a Buechi automaton ... */
+  for (i=0; i<array_n(ltlArray); i++) {
+    ltlFormula = array_fetch(Ctlsp_Formula_t *, ltlArray, i);
+    tmpString = Ctlsp_FormulaConvertToString(ltlFormula);
+
+    /* expand the abbreaviations */
+    ltlFormula = Ctlsp_LtlFormulaExpandAbbreviation(ltlFormula);
+    fprintf(vis_stdout, "\nFormula: %s\n", tmpString);
+
+    /* 1) Simplify the formula by 'Rewriting' */
+    if (rewriting) {
+      Ctlsp_Formula_t *tmpF = ltlFormula;
+      ltlFormula = Ctlsp_LtlFormulaSimpleRewriting(ltlFormula);
+      tmpString = Ctlsp_FormulaConvertToString(ltlFormula);
+      Ctlsp_FormulaFree(tmpF);
+    }
+
+    /* create the alph_beta table */
+    tableau = LtlTableauGenerateTableau(ltlFormula);
+    tableau->verbosity = verbosity;
+    tableau->algorithm = algorithm;
+    tableau->booleanmin = booleanmin;
+    /* print out the tableau rules */
+    if (verbosity >= McVerbosityMax_c)
+      LtlTableauPrint(vis_stdout, tableau);
+
+    /* 2) create the automaton */
+    automaton = LtlAutomatonGeneration(tableau);
+    automaton->name = tmpString;
+
+    /* 3) minimize the automaton by Pruning fairness */
+    if (prunefair) {
+      if (verbosity >= McVerbosityMax_c) {
+	Ltl_AutomatonPrint(automaton, verbosity);
+	fprintf(vis_stdout, "\nPruneF-Minimization:\n");
+      }
+      Ltl_AutomatonMinimizeByPrune(automaton, verbosity) ;
+    }
+
+    /* 4) minimize the automaton by I/O compatible and dominance */
+    if (iocompatible) {
+      if (verbosity >= McVerbosityMax_c) {
+	Ltl_AutomatonPrint(automaton, verbosity);
+	fprintf(vis_stdout, "\nIOC-Minimization:\n");
+      }
+      while(Ltl_AutomatonMinimizeByIOCompatible(automaton, verbosity));
+    }
+
+    /* 5) minimize the automaton by Direct Simulation */
+    if (directsim) {
+      if (verbosity >= McVerbosityMax_c) {
+	Ltl_AutomatonPrint(automaton, verbosity);
+	fprintf(vis_stdout, "\nDirSim-Minimization:\n");
+      }
+      Ltl_AutomatonMinimizeByDirectSimulation(automaton, verbosity);
+    }
+
+    /* 6) minimize the automaton by Reverse Simulation */
+    if (reversesim) {
+      if (verbosity >= McVerbosityMax_c) {
+	Ltl_AutomatonPrint(automaton, verbosity);
+	fprintf(vis_stdout, "\nRevSim-Minimization:\n");
+      }
+      Ltl_AutomatonMinimizeByReverseSimulation(automaton, verbosity);
+    }
+
+    /* 7/3) minimize the automaton by Pruning fairness */
+    if (prunefair) {
+      if (verbosity >= McVerbosityMax_c) {
+	Ltl_AutomatonPrint(automaton, verbosity);
+	fprintf(vis_stdout, "\nPruneF-Minimization:\n");
+      }
+      Ltl_AutomatonMinimizeByPrune(automaton, verbosity) ;
+    }
+
+    /* 8) add arcs by Direct Simulation, to reduce counter-example length */
+    if (directsimMaximize) {
+      if (verbosity >= McVerbosityMax_c) {
+	Ltl_AutomatonPrint(automaton, verbosity);
+	fprintf(vis_stdout, "\nDirSim-Maximization:\n");
+      }
+      Ltl_AutomatonMaximizeByDirectSimulation(automaton, verbosity);
+    }
+
+    /* print out the Buechi automaton */
+    Ltl_AutomatonPrint(automaton, verbosity+1);
+
+    /* write the automaton in a file in the proper format */
+    if (options->outputfilename) {
+      FILE *fp;
+      fp = Cmd_FileOpen( options->outputfilename, (char *)((i==0)?"w":"a"),
+			 NIL(char *), 0);
+      if (options->outputformat == Aut2File_DOT_c)
+	Ltl_AutomatonToDot(fp, automaton, 0);
+      else if (options->outputformat == Aut2File_BLIFMV_c)
+	Ltl_AutomatonToBlifMv(fp, network, automaton);
+      else if (options->outputformat == Aut2File_VERILOG_c)
+	Ltl_AutomatonToVerilog(fp, network, automaton);
+      else {
+	Ltl_AutomatonToDot(fp, automaton, 0);
+	Ltl_AutomatonToBlifMv(fp, network, automaton);
+	Ltl_AutomatonToVerilog(fp, network, automaton);
+      }
+      fclose(fp);
+    }
+
+    /* Clean-ups: the current formula*/
+    Ltl_AutomatonFree((gGeneric) automaton);
+    LtlTableauFree(tableau);
+    Ctlsp_FormulaFree(ltlFormula);
+  }
+
+  /* Clean-ups */
+  Ctlsp_FormulaArrayFree(ltlArray);
+  LtlMcOptionFree(options);
+
+  finalTime = util_cpu_time();
+  fprintf(vis_stdout, "# LTL_TO_AUT time: %10g\n",
+	  (double)(finalTime-beginTime)/1000.0);
+
+  return 0;		/* normal exit */
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Parse the user input for command "ltl_model_check."]
+
+  Description []
+
+  SideEffects []
+
+******************************************************************************/
+static LtlMcOption_t *
+ParseLtlMcOptions(
+  int argc,
+  char **argv)
+{
+  LtlMcOption_t *options = LtlMcOptionAlloc();
+  char *ltlFileName = (char *)0;
+  char *debugOutName = (char *)0;
+  Mc_GSHScheduleType schedule = McGSH_EL_c;
+  Mc_FwdBwdAnalysis direction = McBwd_c;
+  int lockstep = MC_LOCKSTEP_OFF;
+  int c;
+
+  if (options == NIL(LtlMcOption_t))
+    return NIL(LtlMcOption_t);
+  options->leMethod = Mc_Le_Default_c;
+  options->dcLevel = McDcLevelRch_c;
+  options->noStrengthReduction = 0;
+  options->noIncrementalPartition = 0;
+
+  /* Parse command line options.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "a:bd:f:t:A:D:v:S:L:FhimsXYM")) != EOF) {
+    switch(c) {
+    case 'a':
+      options->algorithm = (Ltl2AutAlgorithm) atoi(util_optarg);
+      if (options->algorithm < 0 || options->algorithm > 3)
+	goto usage;
+      break;
+    case 'b':
+      options->booleanmin = 1;
+      break;
+    case 'd':
+      options->dbgLevel = (LtlMcDbgLevel) atoi(util_optarg);
+      break;
+    case 'f':
+      debugOutName = util_strsav(util_optarg);
+      break;
+    case 't':
+      options->timeOutPeriod = atoi(util_optarg);
+      break;
+    case 'A':
+      options->leMethod = (Mc_LeMethod_t) atoi(util_optarg);
+      break;
+    case 'D':
+      options->dcLevel = (Mc_DcLevel) atoi(util_optarg);
+      break;
+    case 'v':
+      options->verbosity = (Mc_VerbosityLevel) atoi(util_optarg);
+      break;
+    case 'S' :
+      schedule = Mc_StringConvertToScheduleType(util_optarg);
+      break;
+    case 'L' :
+      lockstep = Mc_StringConvertToLockstepMode(util_optarg);
+      break;
+    case 'F' :
+      direction = McFwd_c;
+      break;
+    case 'i':
+      options->printInputs = 1;
+      break;
+    case 'm':
+      options->useMore = TRUE;
+      break;
+    case 's' :
+      options->simValue = TRUE;
+      break;
+    case 'X':
+      options->noStrengthReduction = 1;
+      break;
+    case 'Y':
+      options->noIncrementalPartition = 1;
+      break;
+    case 'Z':
+      options->noShuffleToTop = 1;
+      break;
+    case 'M':
+      options->directsimMaximize = 1;
+      break;
+    case 'h':
+      goto usage;
+    default:
+      goto usage;
+    }
+  }
+  if (options->algorithm == Ltl2Aut_WRING_c) {
+    options->rewriting =    TRUE;
+    options->prunefair =    TRUE;
+    options->directsim =    TRUE;
+    options->reversesim =   TRUE;
+    options->iocompatible = TRUE;
+  }
+
+  if (schedule == McGSH_Unassigned_c) {
+    (void) fprintf(vis_stderr, "unknown schedule: %s\n", util_optarg);
+    goto usage;
+  } else {
+    options->schedule = schedule;
+  }
+  if (lockstep == MC_LOCKSTEP_UNASSIGNED) {
+    (void) fprintf(vis_stderr, "invalid lockstep option: %s\n", util_optarg);
+    goto usage;
+  } else {
+    options->lockstep = lockstep;
+  }
+  options->direction = direction;
+
+  /* Open the ltl file.
+   */
+  if (argc - util_optind == 0) {
+    (void) fprintf(vis_stderr, "** ltl_mc error: file containing ltl formulae not provided\n");
+    goto usage;
+  }
+  else if (argc - util_optind > 1) {
+    (void) fprintf(vis_stderr, "** ltl_mc error: too many arguments\n");
+    goto usage;
+  }
+  ltlFileName = util_strsav(argv[util_optind]);
+
+  /* Read LTL Formulae */
+  if (!ltlFileName)
+    goto usage;
+  options->ltlFile = Cmd_FileOpen(ltlFileName, "r", NIL(char *), 0);
+  if (options->ltlFile == NIL(FILE)) {
+    (void) fprintf(vis_stdout,  "** ltl_mc error: error in opening file %s\n", ltlFileName);
+    FREE(ltlFileName);
+    LtlMcOptionFree(options);
+    return NIL(LtlMcOption_t);
+  }
+  FREE(ltlFileName);
+
+  if (debugOutName != NIL(char)) {
+    options->debugFile = Cmd_FileOpen(debugOutName, "w", NIL(char *), 0);
+    if (options->debugFile == NIL(FILE)) {
+      (void) fprintf(vis_stdout,"** ltl_mc error: error in opening file %s\n", debugOutName);
+      FREE(debugOutName);
+      LtlMcOptionFree(options);
+      return NIL(LtlMcOption_t);
+    }
+    FREE(debugOutName);
+  }
+
+  return options;
+
+ usage:
+  (void) fprintf(vis_stderr, "usage: ltl_model_check [-a ltl2aut_algorithm][-b][-d dbg_level][-f dbg_file][-h][-i][-m][-s][-t period][-v verbosity_level][-A le_method][-D dc_level][-L lockstep_mode][-S schedule][-F][-X][-Y][-M] <ltl_file>\n");
+  (void) fprintf(vis_stderr, "    -a <ltl2aut_algorithm>\n");
+  (void) fprintf(vis_stderr, "        ltl2aut_algorithm = 0 => GPVW\n");
+  (void) fprintf(vis_stderr, "        ltl2aut_algorithm = 1 => GPVW+\n");
+  (void) fprintf(vis_stderr, "        ltl2aut_algorithm = 2 => LTL2AUT\n");
+  (void) fprintf(vis_stderr, "        ltl2aut_algorithm = 3 => WRING (Default)\n");
+  (void) fprintf(vis_stderr, "    -b \tUse boolean minimization in automaton generation\n");
+  (void) fprintf(vis_stderr, "    -d <dbg_level>\n");
+  (void) fprintf(vis_stderr, "        debug_level = 0 => no debugging (Default)\n");
+  (void) fprintf(vis_stderr, "        debug_level = 1 => automatic debugging\n");
+  (void) fprintf(vis_stderr, "    -f <dbg_out>\n");
+  (void) fprintf(vis_stderr, "        write error trace to dbg_out\n");
+  (void) fprintf(vis_stderr, "    -i \tPrint input values in debug traces.\n");
+  (void) fprintf(vis_stderr, "    -m \tPipe debugger output through the UNIX utility more.\n");
+  (void) fprintf(vis_stderr, "    -s \tWrite error trace in sim format.\n");
+  (void) fprintf(vis_stderr, "    -v <verbosity_level>\n");
+  (void) fprintf(vis_stderr, "        verbosity_level = 0 => no feedback (Default)\n");
+  (void) fprintf(vis_stderr, "        verbosity_level = 1 => code status\n");
+  (void) fprintf(vis_stderr, "        verbosity_level = 2 => code status and CPU usage profile\n");
+  (void) fprintf(vis_stderr, "    -t <period> time out period\n");
+  (void) fprintf(vis_stderr, "    -A <le_method>\n");
+  (void) fprintf(vis_stderr, "        le_method = 0 => no use of Divide and Compose (Default)\n");
+  (void) fprintf(vis_stderr, "        le_method = 1 => use Divide and Compose\n");
+  (void) fprintf(vis_stderr, "    -D <dc_level>\n");
+  (void) fprintf(vis_stderr, "        dc_level = 0 => no use of don't cares\n");
+  (void) fprintf(vis_stderr, "        dc_level = 1 => use unreached states as don't cares (Default)\n");
+  (void) fprintf(vis_stderr, "        dc_level = 2 => use unreached states as don't cares\n");
+
+  (void) fprintf(vis_stderr, "                        and aggressive use of DC's to simplify MDD's\n");
+  (void) fprintf(vis_stderr, "        dc_level = 3 => use over-approximate unreached states as don't cares\n");
+  (void) fprintf(vis_stderr, "                        and aggressive use of DC's to simplify MDD's\n");
+  (void) fprintf(vis_stderr, "    -L <lockstep_mode>\n");
+  (void) fprintf(vis_stderr, "       lockstep_mode is one of {off,on,all,n}\n");
+  (void) fprintf(vis_stderr, "    -S <schedule>\n");
+  (void) fprintf(vis_stderr, "       schedule is one of {EL,EL1,EL2,budget,random,off}\n");
+  (void) fprintf(vis_stderr, "    -F \tUse forward analysis in fixpoint computation.\n");
+  (void) fprintf(vis_stderr, "    -X \tDisable strength reduction (using different decision procedure \n");
+  (void) fprintf(vis_stderr, "       \tfor strong, weak, terminal automaton).\n");
+  (void) fprintf(vis_stderr, "    -Y \tDisable incremental partition of the composed system (M x A).\n");
+  (void) fprintf(vis_stderr, "	  -Z \tAdd arcs into the Buechi automaton by direct simulation relation.\n");
+
+  (void) fprintf(vis_stderr, "    -M \tAdd arcs to the automaton to reduce counter-example length.\n");
+  (void) fprintf(vis_stderr, "    <ltl_file> The input file containing LTL formulae to be checked.\n");
+  (void) fprintf(vis_stderr, "    -h \tPrints this usage message.\n");
+
+  LtlMcOptionFree(options);
+  return NIL(LtlMcOption_t);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Parse the user input for command "ltl_to_aut".]
+
+  Description []
+
+  SideEffects []
+
+******************************************************************************/
+static LtlMcOption_t *
+ParseLtlTestOptions(
+  int argc,
+  char **argv)
+{
+  LtlMcOption_t *options = LtlMcOptionAlloc();
+  char *ltlFileName = (char *)0;
+  int c;
+
+  if (options == NIL(LtlMcOption_t))
+    return NIL(LtlMcOption_t);
+
+  /*
+   * Parse command line options.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "wbpdMrif:m:v:o:t:h")) != EOF) {
+    switch(c) {
+    case 'w':
+      options->rewriting = 1;
+      break;
+    case 'b':
+      options->booleanmin = 1;
+      break;
+    case 'p':
+      options->prunefair = 1;
+      break;
+    case 'd':
+      options->directsim = 1;
+      break;
+    case 'M':
+      options->directsimMaximize = 1;
+      break;
+    case 'r':
+      options->reversesim = 1;
+      break;
+    case 'i':
+      options->iocompatible = 1;
+      break;
+    case 'f':
+      ltlFileName = util_strsav(util_optarg);
+      break;
+    case 'm':
+      options->algorithm = (Ltl2AutAlgorithm) atoi(util_optarg);
+      break;
+    case 'v':
+      options->verbosity = (Mc_VerbosityLevel) atoi(util_optarg);
+      break;
+    case 'o':
+      options->outputfilename = util_strsav(util_optarg);
+      break;
+    case 't':
+      options->outputformat = (Aut2FileType) atoi(util_optarg);
+      break;
+    case 'h':
+      goto usage;
+    default:
+      goto usage;
+    }
+  }
+
+  /* 'Wring' is equivalent to
+  *    LTL2AUT +
+  *    rewriting +
+  *    prunefair + directsim + reversesim + iocompatible
+  */
+  if (options->algorithm ==3) {
+    options->rewriting = 1;
+    options->prunefair = 1;
+    options->directsim = 1;
+    options->reversesim = 1;
+    options->iocompatible = 1;
+  }
+
+  /* Read LTL Formulae */
+  if (!ltlFileName)
+    goto usage;
+
+  options->ltlFile = Cmd_FileOpen(ltlFileName, "r", NIL(char *), 0);
+  FREE(ltlFileName);
+  if (options->ltlFile == NIL(FILE)) {
+    (void) fprintf(vis_stdout,  "** ltl_to_aut error: error in opening file %s\n", ltlFileName);
+    LtlMcOptionFree(options);
+    return NIL(LtlMcOption_t);
+  }
+
+  return options;
+
+  usage:
+  (void) fprintf(vis_stderr, "usage: ltl_to_aut <-f ltl_file> [-m algorithm] [-o output_file] [-t output_format] [-w] [-b] [-p] [-d] [-r] [-i] [-M] [-v verbosity_level] [-h]\n");
+  (void) fprintf(vis_stderr, "    -f <ltl_file>\n");
+  (void) fprintf(vis_stderr, "       The input file containing LTL formulae\n");
+  (void) fprintf(vis_stderr, "    -m <algorithm>\n");
+  (void) fprintf(vis_stderr, "        algorithm = 0 => GPVW\n");
+  (void) fprintf(vis_stderr, "        algorithm = 1 => GPVW+\n");
+  (void) fprintf(vis_stderr, "        algorithm = 2 => LTL2AUT\n");
+  (void) fprintf(vis_stderr, "        algorithm = 3 => Wring (default)\n");
+  (void) fprintf(vis_stderr, "    -o <output_file>\n");
+  (void) fprintf(vis_stderr, "       Write the automata to output_file\n");
+  (void) fprintf(vis_stderr, "    -t <output_format>\n");
+  (void) fprintf(vis_stderr, "        output_format = 0 => dot\n");
+  (void) fprintf(vis_stderr, "        output_format = 1 => blif_mv\n");
+  (void) fprintf(vis_stderr, "        output_format = 2 => verilog\n");
+  (void) fprintf(vis_stderr, "        output_format = 3 => all (default)\n");
+  (void) fprintf(vis_stderr, "    -w \tRewriting the formula\n");
+  (void) fprintf(vis_stderr, "    -b \tBoolean minimization \n");
+  (void) fprintf(vis_stderr, "    -p \tPruning the fairness\n");
+  (void) fprintf(vis_stderr, "    -d \tDirect-simulation minimization\n");
+  (void) fprintf(vis_stderr, "    -r \tReverse-simulation minimization\n");
+  (void) fprintf(vis_stderr, "    -i \tI/O compatible minimization\n");
+  (void) fprintf(vis_stderr, "    -M \tAdd arcs by direct-simulation to reduce the counter-example length\n");
+  (void) fprintf(vis_stderr, "    -v <verbosity>\n");
+  (void) fprintf(vis_stderr, "       \tVerbosity can be 0,1,2,3\n");
+  (void) fprintf(vis_stderr, "    -h \tPrints this usage message.\n");
+
+  LtlMcOptionFree(options);
+  return NIL(LtlMcOption_t);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Perform simple static semantic checks on formula.]
+
+  SideEffects []
+
+  SeeAlso [Ltl_FormulaStaticSemanticCheckOnNetwork]
+******************************************************************************/
+static boolean
+LtlMcAtomicFormulaCheckSemantics(
+  Ctlsp_Formula_t *formula,
+  Ntk_Network_t *network,
+  boolean inputsAllowed)
+{
+  char *nodeNameString = Ctlsp_FormulaReadVariableName( formula );
+  char *nodeValueString = Ctlsp_FormulaReadValueName( formula );
+  Ntk_Node_t *node = Ntk_NetworkFindNodeByName( network, nodeNameString );
+
+  Var_Variable_t *nodeVar;
+  int nodeValue;
+
+  if ( !node ) {
+    error_append("Could not find node corresponding to the name\n\t- ");
+    error_append( nodeNameString );
+    return FALSE;
+  }
+
+  nodeVar = Ntk_NodeReadVariable( node );
+  if ( Var_VariableTestIsSymbolic( nodeVar ) ){
+    nodeValue = Var_VariableReadIndexFromSymbolicValue( nodeVar, nodeValueString );
+    if ( nodeValue == -1 ) {
+      error_append("Value specified in RHS is not in domain of variable\n");
+      error_append( Ctlsp_FormulaReadVariableName( formula ) );
+      error_append("=");
+      error_append( Ctlsp_FormulaReadValueName( formula ) );
+      return FALSE;
+    }
+  }
+  else {
+    int check;
+
+    check = Cmd_StringCheckIsInteger(nodeValueString, &nodeValue);
+    if( check==0 ) {
+      error_append("Value in the RHS is illegal\n");
+      error_append( Ctlsp_FormulaReadVariableName( formula ) );
+      error_append("=");
+      error_append( Ctlsp_FormulaReadValueName( formula ) );
+      return FALSE;
+    }
+    if( check==1 ) {
+      error_append("Value in the RHS is out of range of int\n");
+      error_append( Ctlsp_FormulaReadVariableName( formula ) );
+      error_append("=");
+      error_append( Ctlsp_FormulaReadValueName( formula ) );
+      return FALSE;
+    }
+    if ( !(Var_VariableTestIsValueInRange( nodeVar, nodeValue ) ) ) {
+      error_append("Value specified in RHS is not in domain of variable\n");
+      error_append( Ctlsp_FormulaReadVariableName( formula ) );
+      error_append("=");
+      error_append( Ctlsp_FormulaReadValueName( formula ) );
+      return FALSE;
+    }
+  }
+
+  if(!inputsAllowed){
+    boolean coverSupport;
+    lsGen tmpGen;
+    Ntk_Node_t *tmpNode;
+    st_table *supportNodes    = st_init_table(st_ptrcmp, st_ptrhash);
+    array_t *thisNodeArray = array_alloc( Ntk_Node_t *, 0);
+
+    array_insert_last( Ntk_Node_t *, thisNodeArray, node );
+    Ntk_NetworkForEachNode(network, tmpGen, tmpNode) {
+      if (Ntk_NodeTestIsConstant(tmpNode) || Ntk_NodeTestIsLatch(tmpNode)) {
+	st_insert(supportNodes,  tmpNode, NIL(char));
+      }
+    }
+
+    coverSupport = Ntk_NetworkTestLeavesCoverSupportOfRoots(network,
+							    thisNodeArray,
+							    supportNodes);
+    array_free(thisNodeArray);
+    st_free_table(supportNodes);
+
+    if ( coverSupport == FALSE ) {
+      char *tmpString =
+	util_strcat3( "\nNode ", nodeNameString,
+		      " is not driven only by latches and constants.\n");
+      error_append(tmpString);
+      return FALSE;
+    }
+  }
+
+  return TRUE;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Handle function for timeout.]
+
+  Description [This function is called when the process receives a signal of
+  type alarm. Since alarm is set with elapsed time, this function checks if the
+  CPU time corresponds to the timeout of the command. If not, it reprograms the
+  alarm to fire later and check if the CPU limit has been reached.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+TimeOutHandle(void)
+{
+  longjmp(timeOutEnv, 1);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Move the mdd variables to the top most.]
+
+  Description [This function is called to move the automaton variables to the
+  top most. This is believed to be the best variable ordering for the composed
+  system (M x A). The variable corresponding to the first item in mddIdArray
+  will be the top most.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+ShuffleMddIdsToTop(mdd_manager *mddManager, array_t *mddIdArray)
+{
+  array_t *mvar_list = mdd_ret_mvar_list(mddManager);
+  int *invPermArray = ALLOC(int, bdd_num_vars(mddManager));
+  int invPermIndex, i, j, bvarId, mddId, result;
+  st_table *stored = st_init_table(st_ptrcmp, st_ptrhash);
+  mvar_type mvar;
+
+  /* put mddId on the top most */
+  invPermIndex = 0;
+  arrayForEachItem(int, mddIdArray, j, mddId) {
+    if (mddId == 0) continue;
+    mvar = array_fetch(mvar_type, mvar_list, mddId);
+    for (i = 0; i<mvar.encode_length; i++) {
+      bvarId = mdd_ret_bvar_id(&mvar, i);
+      invPermArray[invPermIndex++] = bvarId;
+      st_insert(stored, (char *) (long) bvarId, (char *)0);
+    }
+  }
+  /* shift every one else down */
+  for (i = 0; (unsigned) i< bdd_num_vars(mddManager); i++) {
+    bvarId = bdd_get_id_from_level(mddManager, i);
+    if (!st_is_member(stored, (char *) (long) bvarId)) {
+      invPermArray[invPermIndex++] = bvarId;
+    }
+  }
+  /* call bdd_shuffle */
+  result = bdd_shuffle_heap(mddManager, invPermArray);
+#ifdef DEBUG_LTLMC
+  if (result)
+    fprintf(vis_stdout, "\nShuffle automaton vars to the top: success!\n");
+  else
+    fprintf(vis_stdout, "\nShuffle automaton vars to the top: failure!\n");
+#endif
+
+  /* Clean up */
+  st_free_table(stored);
+  FREE(invPermArray);
+}
Index: vis_dev/vis-2.3/src/ltl/ltl.h
===================================================================
--- vis_dev/vis-2.3/src/ltl/ltl.h	(revision 14)
+++ vis_dev/vis-2.3/src/ltl/ltl.h	(revision 14)
@@ -0,0 +1,92 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [ltl.h]
+
+  PackageName [ltl]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Chao Wang<chao.wang@colorado.EDU>]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+  Revision    [$Id: ltl.h,v 1.19 2005/04/30 04:00:25 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _LTL
+#define _LTL
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "vm.h"
+#include "ctlsp.h"
+#include "hrc.h"
+#include "ntk.h"
+#include "fsm.h"
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+/*define DEBUG_LTLMC */
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef struct LtlAutomatonStruct Ltl_Automaton_t;
+typedef struct LtlAutomatonNodeStruct Ltl_AutomatonNode_t;
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void Ltl_Init(void);
+EXTERN void Ltl_End(void);
+EXTERN Ltl_Automaton_t * Ltl_McFormulaToAutomaton(Ntk_Network_t *network, Ctlsp_Formula_t *Formula, int options_algorithm, int options_rewriting, int options_prunefair, int options_iocompatible, int options_directsim, int options_reversesim, int options_directsimMaximize, int options_verbosity, int checkSemantics);
+EXTERN Hrc_Manager_t * Ltl_McAutomatonToNetwork(Ntk_Network_t *designNetwork, Ltl_Automaton_t *automaton, int verbosity);
+EXTERN boolean Ltl_FormulaStaticSemanticCheckOnNetwork(Ctlsp_Formula_t *formula, Ntk_Network_t *network, boolean inputsAllowed);
+EXTERN Ltl_Automaton_t * Ltl_AutomatonCreate(void);
+EXTERN void Ltl_AutomatonFree(gGeneric g);
+EXTERN Ltl_AutomatonNode_t * Ltl_AutomatonNodeCreate(Ltl_Automaton_t *aut);
+EXTERN void Ltl_AutomatonNodeFree(gGeneric g);
+EXTERN void Ltl_AutomatonNodePrint(Ltl_Automaton_t *aut, Ltl_AutomatonNode_t *node);
+EXTERN void Ltl_AutomatonPrint(Ltl_Automaton_t *aut, int verbosity);
+EXTERN void Ltl_AutomatonToDot(FILE *fp, Ltl_Automaton_t *aut, int level);
+EXTERN int Ltl_AutomatonToBlifMv(FILE *fp, Ntk_Network_t *network, Ltl_Automaton_t *A);
+EXTERN int Ltl_AutomatonToVerilog(FILE *fp, Ntk_Network_t *network, Ltl_Automaton_t *A);
+EXTERN int Ltl_AutomatonToSmv(FILE *fp, Ntk_Network_t *network, Ltl_Automaton_t *A);
+EXTERN int Ltl_AutomatonMinimizeByIOCompatible(Ltl_Automaton_t *A, int verbosity);
+EXTERN int Ltl_AutomatonMinimizeByDirectSimulation(Ltl_Automaton_t *A, int verbosity);
+EXTERN void Ltl_AutomatonAddFairStates(Ltl_Automaton_t *A);
+EXTERN int Ltl_AutomatonMaximizeByDirectSimulation(Ltl_Automaton_t *A, int verbosity);
+EXTERN int Ltl_AutomatonMinimizeByReverseSimulation(Ltl_Automaton_t *A, int verbosity);
+EXTERN int Ltl_AutomatonMinimizeByPrune(Ltl_Automaton_t *A, int verbosity);
+EXTERN void Ltl_AutomatonComputeSCC(Ltl_Automaton_t *A, int force);
+EXTERN int Ltl_AutomatonIsWeak(Ltl_Automaton_t *A);
+EXTERN Mc_AutStrength_t Ltl_AutomatonGetStrength(Ltl_Automaton_t *A);
+EXTERN Ltl_Automaton_t * Ltl_AutomatonCreateQuotient(Ltl_Automaton_t *A, st_table *partition);
+EXTERN int Ltl_AutomatonVtxGetNodeIdx(vertex_t *v);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _LTL */
Index: vis_dev/vis-2.3/src/ltl/ltl.make
===================================================================
--- vis_dev/vis-2.3/src/ltl/ltl.make	(revision 14)
+++ vis_dev/vis-2.3/src/ltl/ltl.make	(revision 14)
@@ -0,0 +1,17 @@
+CSRC += ltl.c ltlSet.c ltlTableau.c ltlAutomaton.c ltlMinimize.c ltlCompose.c ltlUtil.c
+HEADERS += ltl.h ltlInt.h
+
+DEPENDENCYFILES = $(CSRC)
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/ltl/ltlAutomaton.c
===================================================================
--- vis_dev/vis-2.3/src/ltl/ltlAutomaton.c	(revision 14)
+++ vis_dev/vis-2.3/src/ltl/ltlAutomaton.c	(revision 14)
@@ -0,0 +1,1164 @@
+/**CFile***********************************************************************
+
+  FileName    [ltlAutomaton.c]
+
+  PackageName [ltl]
+
+  Synopsis    [Translate LTL formula to the Buechi Automaton.]
+
+  Author      [Chao Wang<chao.wang@colorado.EDU>]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "ltlInt.h"
+
+static char rcsid[] UNUSED = "$Id: ltlAutomaton.c,v 1.34 2005/04/28 08:47:15 bli Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int HasToBeStored(LtlTableau_t *tableau, int index);
+static int Contradiction(LtlTableau_t *tableau, int index, LtlSet_t *ToCover, LtlSet_t *Current, LtlSet_t *Covered);
+static int Redundant(LtlTableau_t *tableau, int index, LtlSet_t *ToCover, LtlSet_t *Current, LtlSet_t *Covered);
+static int SI(LtlTableau_t *tableau, int index, LtlSet_t *A);
+static void AutomatonComputeFair(LtlTableau_t *tableau, LtlSet_t *r, vertex_t *vtx1);
+static int AutomatonCreateFairList(LtlTableau_t *tableau, Ltl_Automaton_t *aut);
+static void AutomatonAssignNext(LtlTableau_t *tableau, LtlSet_t * toCover, LtlSet_t * s);
+static LtlSet_t * AutomatonSetCreate(LtlTableau_t *tableau, Ctlsp_Formula_t *F);
+static lsList AutomatonBuildCover(LtlTableau_t *tableau, LtlSet_t *ToCover);
+static void AutomatonBuildCover_Aux(LtlTableau_t *tableau, LtlSet_t *pToCover, LtlSet_t *pCurrent, LtlSet_t *pCovered, lsList Cover);
+
+/**AutomaticEnd***************************************************************/
+    
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Allocate the automaton data structure.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ltl_Automaton_t *
+Ltl_AutomatonCreate(void)
+{
+  Ltl_Automaton_t *aut = ALLOC(Ltl_Automaton_t, 1);  
+  (void)memset((void *)aut, 0, sizeof(Ltl_Automaton_t));
+  
+  aut->name = 0;
+  aut->SCC = (st_table *)0;
+  aut->G = g_alloc();
+  /* table of the initial states */
+  aut->Init = st_init_table(st_ptrcmp, st_ptrhash);  
+  /* these states can be either in or outside the "FairSet" */
+  aut->dontcare = st_init_table(st_ptrcmp, st_ptrhash); 
+  /* list of FairSets (each FairSet is a table of states) */
+  aut->Fair = lsCreate();  
+  aut->node_idx = 1;
+  
+  return aut;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Free the automaton data structure.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Ltl_AutomatonFree(gGeneric g)
+{
+  st_table *tbl;
+  st_generator *stgen;
+  int i, n;
+  Ltl_Automaton_t *aut = (Ltl_Automaton_t *) g;
+
+  if (aut->name)  FREE(aut->name);
+
+  g_free(aut->G, (void (*)(gGeneric))0, Ltl_AutomatonNodeFree,
+	 (void (*)(gGeneric))0);
+
+  st_free_table(aut->Init);
+  st_free_table(aut->dontcare);
+  
+  while (lsDelBegin(aut->Fair, &tbl) != LS_NOMORE) {
+      st_free_table(tbl);
+  }
+  lsDestroy(aut->Fair, (void (*)(lsGeneric)) NULL);
+
+  if (aut->labelTable) {
+      n = array_n(aut->labelTable);
+      for (i=0; i<n; i++) 
+          Ctlsp_FormulaFree(array_fetch(Ctlsp_Formula_t *, 
+                                        aut->labelTable, i));
+      array_free(aut->labelTable);
+      array_free(aut->labelTableNegate);
+  }
+
+  /* free the partition/quotient */
+  if (aut->SCC) {
+    /* for a Buechi automaton, this is a st_table of st_table of vertices;
+     * otherwise, this is a st_table of vertices */
+    if (aut->isQuotientGraph == 0) {
+      st_foreach_item(aut->SCC, stgen, &tbl, NIL(char *)) {
+	st_free_table(tbl);
+      }
+    }
+    st_free_table(aut->SCC);
+  }
+
+  if (aut->Q)
+      Ltl_AutomatonFree((gGeneric) aut->Q);
+
+  FREE(aut);
+}
+	
+/**Function********************************************************************
+
+  Synopsis    [Allocate the automaton node data structure.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Ltl_AutomatonNode_t *
+Ltl_AutomatonNodeCreate(Ltl_Automaton_t *aut)
+{
+  Ltl_AutomatonNode_t *node = ALLOC(Ltl_AutomatonNode_t, 1);
+  (void)memset((void *)node, 0, sizeof(Ltl_AutomatonNode_t));
+
+  node->index = aut->node_idx++;
+  node->Labels = NIL(LtlSet_t);
+  node->CoverSet = NIL(LtlSet_t);
+  node->Class = (st_table *)0;        /* used in Quotient graph */
+      
+  return node;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Free the automaton node data structure.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Ltl_AutomatonNodeFree(gGeneric g)
+{
+  Ltl_AutomatonNode_t *node = (Ltl_AutomatonNode_t *) g;
+  if (node->Labels)
+    LtlSetFree(node->Labels);
+  if (node->CoverSet)
+    LtlSetFree(node->CoverSet);
+  /*  if (node->Class)
+        st_free_table(node->Class);*/
+  
+  FREE(node);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Print the automaton node.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Ltl_AutomatonNodePrint(
+  Ltl_Automaton_t *aut,
+  Ltl_AutomatonNode_t *node)
+{
+  st_generator *stgen;
+  vertex_t *vtx;
+  Ltl_AutomatonNode_t *state;
+  Ctlsp_Formula_t *F;
+  int first, i, n;
+  
+  /* index (required) */
+  fprintf(vis_stdout, "n%d: ", node->index);
+  
+  /* 1. cover (set of formulae) ? */
+  if (aut->tableau && node->CoverSet) 
+    LtlSetPrint(aut->tableau, node->CoverSet);
+  
+  /* 2. label ? */
+  if (node->Labels) {
+    fprintf(vis_stdout, " label: {");
+    first = 1; n = array_n(aut->labelTable);
+    for (i=0; i<n; i++) {
+      if (LtlSetGetElt(node->Labels, i)) {
+	if (!first)	  fprintf(vis_stdout, ",");
+	else       	  first = 0;
+	F = array_fetch(Ctlsp_Formula_t *, aut->labelTable, i);
+	Ctlsp_FormulaPrint(vis_stdout, F);
+      }
+    }
+    fprintf(vis_stdout, "}");
+  }
+
+  /* 3. Class ? (for quotient graph node) */
+  if (node->Class) {
+    fprintf(vis_stdout, "scc{");
+    st_foreach_item(node->Class, stgen, &vtx, NIL(char *)) {
+      state = (Ltl_AutomatonNode_t *)vtx->user_data;
+      fprintf(vis_stdout, "n%d ", state->index);
+    }
+    fprintf(vis_stdout, "}");
+  }
+  
+  fprintf(vis_stdout, "\n");
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Print the automaton.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Ltl_AutomatonPrint(
+  Ltl_Automaton_t *aut,
+  int verbosity)
+{
+  edge_t   *edge;
+  vertex_t *vtx1, *vtx2;           
+  Ltl_AutomatonNode_t *node, *node2;
+  lsGen     gen;
+  lsGeneric data;
+
+  st_table  *tbl;
+  st_generator *stgen;
+
+  int n_states = 0;
+  int n_trans = 0;
+  int n_fairsets = 0;
+  int n_init = 0;
+  int strength;
+  
+  /* name ? */
+  if (verbosity)
+    fprintf(vis_stdout, "Automaton:\n");
+
+  if (verbosity > 1) {
+    fprintf(vis_stdout, "-----------------------------------------------\n");
+    if (aut->name)
+      fprintf(vis_stdout, "Name: %s \n", aut->name);
+    fprintf(vis_stdout, "-----------------------------------------------\n");
+    
+    /* negation normal form ?*/
+    if(aut->tableau)
+      Ctlsp_FormulaPrint(vis_stdout, aut->tableau->F);
+    
+    /* States & Labels */
+    fprintf(vis_stdout, "\nStates: \n");
+    foreach_vertex( aut->G, gen, vtx1) {
+      node = (Ltl_AutomatonNode_t *) vtx1->user_data;
+      Ltl_AutomatonNodePrint(aut, node);
+    }
+    
+    /* Init States ? */
+    fprintf(vis_stdout, "Arcs: \n");  
+    st_foreach_item(aut->Init, stgen,  &vtx1, NIL(char *)) {
+      node = (Ltl_AutomatonNode_t *) vtx1->user_data;
+      fprintf(vis_stdout, "-> n%d\n", node->index);
+    }
+    
+    /* Edges */
+    foreach_edge(aut->G, gen, edge) {
+      vtx1 = g_e_source(edge);
+      vtx2 = g_e_dest(edge);
+      node = (Ltl_AutomatonNode_t *) vtx1->user_data;
+      node2 = (Ltl_AutomatonNode_t *) vtx2->user_data;
+	  
+      if (node)
+	fprintf(vis_stdout, "   n%d -> ", node->index);
+      if (node2)
+	fprintf(vis_stdout, "n%d\n", node2->index);
+    }
+
+    /* Sets of Fair Sets */
+    fprintf(vis_stdout, "Fair Sets: \n");  
+    lsForEachItem (aut->Fair, gen, data) {
+      tbl = (st_table *) data;
+      fprintf(vis_stdout, "{ ");
+      st_foreach_item(tbl, stgen,  &vtx1, NIL(char *)) {
+	node = (Ltl_AutomatonNode_t *) vtx1->user_data;
+	fprintf(vis_stdout, "n%d ", node->index);
+      }
+      fprintf(vis_stdout, " }\n");
+    }
+    
+#ifdef DEBUG_LTLMC      
+    /* Dontcare states */
+    fprintf(vis_stdout, "Dontcare States: \n{");
+    if (aut->dontcare) {
+      st_foreach_item(aut->dontcare, stgen, &vtx1, NIL(char *)) {
+	node = (Ltl_AutomatonNode_t *) vtx1->user_data;
+	fprintf(vis_stdout, "n%d ", node->index);
+      }
+    }
+    fprintf(vis_stdout, " }\n");
+#endif
+  
+    fprintf(vis_stdout, "End\n");
+  }
+  
+  /* Get the strength (2, 1, 0) */
+  n_states = lsLength(g_get_vertices(aut->G));
+  n_init = st_count(aut->Init);
+  n_trans = lsLength(g_get_edges(aut->G));
+  n_fairsets = lsLength(aut->Fair);
+  strength = Ltl_AutomatonGetStrength(aut);
+
+  if (verbosity) 
+    fprintf(vis_stdout, "Stats: %d states, %d trans, %d fair sets, %d init states, %s\n", n_states, n_trans, n_fairsets, n_init, (strength==2)? "strong":((strength==1)?"weak":"terminal") );
+
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Generate the Buechi automaton from the formula.]
+
+  Description [Before calling this function, 'tableau' should contains:
+   1) LTL Formula (NNF) and its negation in a DAG (or UniqueTable)
+   2) alpha-beta Table (tableau-rule expansion of each sub-formulae )
+   3) Until formulae list.]
+
+  SideEffects [The returned automaton should be freed by the caller.]
+
+  SeeAlso     []
+
+******************************************************************************/
+Ltl_Automaton_t *
+LtlAutomatonGeneration(
+  LtlTableau_t *tableau)
+{
+  LtlSet_t *toCover, *s, *r, *rprime; /* terms (set) */
+  lsList Cover;                       /* current list of terms (cover) */
+  lsList U = lsCreate();              /* a list of terms <to be processed>*/
+  lsList Q = lsCreate();              /* unique table for terms <processed> */
+  st_table  *Set2Vtx = st_init_table(st_ptrcmp, st_ptrhash);
+  vertex_t *vtx1, *vtx2;              /* vertex in graph, related to node */
+  Ltl_Automaton_t *A = Ltl_AutomatonCreate();
+  Ltl_AutomatonNode_t *node;
+  Ctlsp_Formula_t *F;
+  int i;
+
+  A->tableau = tableau;
+  
+  /* Compute Cover( {F} ), the init states, and U */
+  toCover = AutomatonSetCreate(tableau, tableau->F); 
+  Cover = AutomatonBuildCover(tableau, toCover);     
+  while (lsDelBegin(Cover, &r) != LS_NOMORE) {
+#ifdef DEBUG_LTLMC
+    if (tableau->verbosity >=2) {
+      fprintf(vis_stdout, "**** term: ");
+      LtlSetPrintIndex(tableau->abIndex, r);
+      fprintf(vis_stdout, "**** n%d added! \n", A->node_idx);
+    }
+#endif
+    lsNewEnd(U, (lsGeneric) r, (lsHandle *) 0);
+    lsNewEnd(Q, (lsGeneric) r, (lsHandle *) 0);
+    /* Build the initial states of the Buechi automaton 
+     * add a new node in G
+     */
+    node = Ltl_AutomatonNodeCreate(A);
+    node->Labels = LtlSetToLabelSet(tableau, r);
+    node->CoverSet = LtlSetCopy(r); 
+    vtx1 = g_add_vertex(A->G);
+    vtx1->user_data = (gGeneric) node;
+    /* add into A->Init */
+    st_insert(A->Init, vtx1,  vtx1);
+    /* put this node to proper Fair sets */
+    AutomatonComputeFair(tableau, r, vtx1);
+    /* add into the (Set, Vtx) unique table */
+    st_insert(Set2Vtx, r,  vtx1);
+  }
+  lsDestroy(Cover, (void (*)(lsGeneric))0);
+
+  /* Each time, remove one set 's' from the to-be-processed list 'U' */
+  while (lsDelBegin(U, &s) == LS_OK) {
+    /* Put all the next (state) formulae into toCover */
+    AutomatonAssignNext(tableau, toCover, s);
+#ifdef DEBUG_LTLMC
+    if (tableau->verbosity >= 2) {
+      fprintf(vis_stdout, "\n** AssignNext Of:");
+      LtlSetPrintIndex(tableau->abIndex, s);
+      fprintf(vis_stdout, "** ==>           ");
+      LtlSetPrintIndex(tableau->abIndex, toCover);
+    }
+#endif
+    /* Build the cover for next state */
+    Cover = AutomatonBuildCover(tableau, toCover);
+    while (lsDelBegin(Cover, &r) == LS_OK) {
+      /* Get the existing identical copy of r from Q (if exist) */
+      rprime = LtlSetIsInList(r, Q);
+#ifdef DEBUG_LTLMC	  
+      if (tableau->verbosity >=2 ) {
+	fprintf(vis_stdout, "** term: ");
+	LtlSetPrintIndex(tableau->abIndex, r);
+      }
+#endif
+      /* If the next state exists, simply add the new edge; Otherwise,
+	 create the next state, and add the new edge */
+      if (rprime) {
+	/* both s and r' are already in G */
+	st_lookup(Set2Vtx,  rprime,  &vtx1);
+	assert(vtx1 != NIL(vertex_t));
+	st_lookup(Set2Vtx, s,  &vtx2); 
+	assert(vtx2 != NIL(vertex_t));
+	/* add edge(s, r') */
+	g_add_edge(vtx2, vtx1);	      
+	LtlSetFree(r);
+      }else {
+#ifdef DEBUG_LTLMC	      
+	if (tableau->verbosity >=2 ) {
+	  fprintf(vis_stdout, "** n%d added!\n", A->node_idx);
+	}
+#endif
+	/* add a new state in G */
+	node = Ltl_AutomatonNodeCreate(A);
+	node->Labels = LtlSetToLabelSet(tableau, r);
+	node->CoverSet = LtlSetCopy(r); 
+	vtx1 = g_add_vertex(A->G);  
+	vtx1->user_data = (gGeneric) node;
+	/* add edge(s, r) */
+	st_lookup(Set2Vtx,  s,  &vtx2);
+	assert(vtx2 != NIL(vertex_t));     
+	g_add_edge(vtx2, vtx1); 
+	/* put the new state to the proper Fair Sets */
+	AutomatonComputeFair(tableau, r, vtx1);
+	/* add r in the (Set, Vtx) unique table */
+	st_insert(Set2Vtx,  r,  vtx1);	      
+	lsNewEnd(Q, (lsGeneric) r, (lsHandle *) 0);
+	lsNewEnd(U, (lsGeneric) r, (lsHandle *) 0);
+      }
+    }
+      
+    lsDestroy(Cover, (void (*)(lsGeneric))0);
+  }
+
+  /* Convert fair sets of the tableau into fair sets of the automaton:
+   * if there is an empty fairset, create an empty automaton and return;
+   * otherwise, keep going ...
+   */
+  if (AutomatonCreateFairList(tableau, A) == 0) {
+    st_table *tbl;
+    while (lsDelBegin(A->Fair, &tbl) != LS_NOMORE) {
+      st_free_table(tbl);
+    }
+    g_free(A->G, (void (*)(gGeneric))0, Ltl_AutomatonNodeFree,
+	   (void (*)(gGeneric))0);
+    A->G = g_alloc();
+    st_free_table(A->Init);
+    A->Init = st_init_table(st_ptrcmp, st_ptrhash);
+  }
+
+  /* Copy the lable table of the tableau into the automaton 
+   * Note that the new one shares nothing with the one in the tableau 
+   */
+  A->labelTable = array_alloc(Ctlsp_Formula_t *, tableau->labelIndex);
+  for (i=0; i<tableau->labelIndex; i++) {
+    F = Ctlsp_LtlFormulaNegationNormalForm(tableau->labelTable[i]);
+    array_insert(Ctlsp_Formula_t *, A->labelTable, i, F);
+  }
+  A->labelTableNegate = array_dup(tableau->labelTableNegate);
+  
+  /* Free all the sets in the list 
+   * toCover/U  should be empty sets, while Q contains all the processed set 
+   */
+  LtlSetFree(toCover);         
+  lsDestroy(U, (void (*)(lsGeneric)) 0);    
+  lsDestroy(Q, (void (*)(lsGeneric))LtlSetFree);    
+  st_free_table(Set2Vtx);
+
+#ifdef DEBUG_LTLMC  
+  /* sanity check */
+  g_check(A->G);
+#endif
+  
+  return A;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Return 1 if the given set belongs to a fair set.]
+
+  Description [It is used in Boolean minimization. It might prevent
+  over-simplification.]
+
+  SideEffects []
+
+******************************************************************************/
+int 
+LtlAutomatonSetIsFair(
+  LtlTableau_t *tableau,
+  LtlSet_t *r)
+{
+#if 0
+  st_table *uniqueTable = tableau->untilUniqueTable;
+  char *key, *value;
+  st_generator *gen;
+  int flag = 0;
+#endif
+
+  /* this is the same as "Wring" */
+  return 0;  
+
+#if 0  
+  st_foreach_item(uniqueTable, gen, &key, &value) {
+    Ctlsp_Formula_t *F = (Ctlsp_Formula_t *) key;
+    Ctlsp_Formula_t *right = Ctlsp_FormulaReadRightChild(F);
+    int F_ab_idx = Ctlsp_FormulaReadABIndex(F);
+    int right_ab_idx = Ctlsp_FormulaReadABIndex(right);
+      
+    if ( SI(tableau, right_ab_idx, r) ||
+	 !(SI(tableau, F_ab_idx, r)) ) {
+      /* set 'r' belongs to one fair set */
+      flag = 1;
+      st_free_gen(gen);
+      break;
+    }
+  }
+  return flag;
+#endif
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Return 1 iff the elementary formula need to be stored.]
+
+  Description [The formula is represented by its index in the abTable]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+HasToBeStored(
+  LtlTableau_t *tableau,
+  int index)
+{
+  int result = 1;
+  Ctlsp_Formula_t *F;
+  Ctlsp_FormulaType F_type;
+  
+  F = tableau->abTable[index].F;
+  
+  switch(tableau->algorithm) {
+  case Ltl2Aut_GPVW_c:
+    result = 1;
+    break;
+  case Ltl2Aut_GPVWplus_c:
+    /* T iff 'u' is an until formula or 'u' is the right hand of an until */
+    F_type = Ctlsp_FormulaReadType(F);
+    result = (F_type == Ctlsp_U_c || Ctlsp_FormulaReadRhs(F) == 1);
+    break;
+  case Ltl2Aut_LTL2AUT_c:  
+  case Ltl2Aut_WRING_c:   
+    result = 0;
+    break;
+  }
+#ifdef DEBUG_LTLMC
+  if (tableau->verbosity >2)
+    fprintf(vis_stdout, "...HasToBeStored=%d\n", result);
+#endif
+  
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return 1 iff there is there is a contradition so far.]
+
+  Description [The formula is represented by its index in the abTable]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+Contradiction(
+  LtlTableau_t *tableau,
+  int index,
+  LtlSet_t *ToCover,
+  LtlSet_t *Current,
+  LtlSet_t *Covered)
+{
+  int result = 0;
+  Ctlsp_Formula_t *F, *notF;
+  LtlSet_t *UC;
+  int notF_ab_idx;
+  Ctlsp_FormulaType F_type;
+  
+  F = tableau->abTable[index].F;
+  F_type = Ctlsp_FormulaReadType(F);
+  notF = tableau->abTable[index].notF;
+  notF_ab_idx = Ctlsp_FormulaReadABIndex(notF);
+
+  
+  switch(tableau->algorithm) {
+  case Ltl2Aut_GPVW_c:
+    /* if 'u' is False, or (!u) exists in Current */
+    result = ( F_type == Ctlsp_FALSE_c ||
+	       LtlSetGetElt(Current, notF_ab_idx) );
+    break;
+  case Ltl2Aut_GPVWplus_c:
+    /* if 'u' is False, or !(u) exists in Covered */
+    result = ( F_type == Ctlsp_FALSE_c ||
+	       LtlSetGetElt(Covered, notF_ab_idx) );
+    break;
+  case Ltl2Aut_LTL2AUT_c:
+  case Ltl2Aut_WRING_c:
+    UC = LtlSetCopy(ToCover);
+    LtlSetOR(UC, ToCover, Current);
+    /* T iff (!u) \in SI(ToCover U Current) */
+    result = SI(tableau, notF_ab_idx, UC);
+    LtlSetFree(UC);
+    break;
+  }
+#ifdef DEBUG_LTLMC
+  if (tableau->verbosity >2)
+    fprintf(vis_stdout, "...Contradiction=%d\n", result);
+#endif
+  
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return 1 iff the given formula is redundant.]
+
+  Description [The formula is represented by its index in the abTable]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+Redundant(
+  LtlTableau_t *tableau,
+  int index,
+  LtlSet_t *ToCover,
+  LtlSet_t *Current,
+  LtlSet_t *Covered)
+{
+  int result = 0;
+  Ctlsp_Formula_t *F;
+  LtlSet_t *UC = LtlSetCopy(ToCover);
+  int Fleft_ab_idx , Fright_ab_idx;
+  Ctlsp_FormulaType F_type;
+  
+  LtlSetOR(UC, ToCover, Current);
+  
+  F = tableau->abTable[index].F;
+  
+  F_type = Ctlsp_FormulaReadType(F);
+  if (F_type == Ctlsp_U_c || F_type == Ctlsp_R_c) {
+    Fleft_ab_idx = Ctlsp_FormulaReadABIndex(Ctlsp_FormulaReadLeftChild(F));
+    Fright_ab_idx = Ctlsp_FormulaReadABIndex(Ctlsp_FormulaReadRightChild(F));
+  } else { /* to remove uninitialized variable warnings */
+    Fleft_ab_idx = 0;
+    Fright_ab_idx = 0;
+  }
+  switch(tableau->algorithm) {
+  case Ltl2Aut_GPVW_c:
+    result = 0;
+    break;
+  case Ltl2Aut_GPVWplus_c:
+    /* T iff  'u' is (n U v) and {v} is in (ToCover U Current),
+     *   or   'u' is (n R v) and {n,v} is in (ToCover U Current) 
+     */
+    if (F_type == Ctlsp_U_c) 
+      result = LtlSetGetElt(UC, Fright_ab_idx);
+    else if (F_type == Ctlsp_R_c) 
+      result = ( LtlSetGetElt(UC, Fleft_ab_idx) &&
+		 LtlSetGetElt(UC, Fright_ab_idx) );
+    else
+      result = 0;
+    break;
+  case Ltl2Aut_LTL2AUT_c:
+  case Ltl2Aut_WRING_c:
+    /* T iff the following two cases are both true:
+     *  (1) 'u' is in SI(ToCover U Current)
+     *  (2) if 'u' is (n U v), then 'v' is in (ToCover U Current) 
+     */
+    result = SI(tableau, index, UC);
+    if (result && F_type == Ctlsp_U_c) {
+      result = SI(tableau, Fright_ab_idx, UC);
+    }
+    break;
+  }
+  LtlSetFree(UC);
+#ifdef DEBUG_LTLMC  
+  if (tableau->verbosity >2)
+    fprintf(vis_stdout, "...Redundant=%d\n", result);
+#endif
+  
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Test if the given formula is synatically implied by the
+  existing set (product term).]
+
+  Description [Return 1 if the formula is implied. The formula is represented
+  by its index in the abTable]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+SI(
+  LtlTableau_t *tableau,
+  int index,
+  LtlSet_t *A)
+{
+  int result = 0;
+  Ctlsp_Formula_t *XF;
+  Ctlsp_Formula_t *F = tableau->abTable[index].F;
+  Ctlsp_FormulaType F_type = Ctlsp_FormulaReadType(F);
+  int Fleft_ab_idx, Fright_ab_idx;
+  
+  if (tableau->algorithm == Ltl2Aut_GPVW_c ||
+      tableau->algorithm == Ltl2Aut_GPVWplus_c) {
+    result = LtlSetGetElt(A, index);
+  } else {
+    if (F_type == Ctlsp_AND_c || F_type == Ctlsp_OR_c ||
+	F_type == Ctlsp_U_c || F_type == Ctlsp_R_c) {
+      Fleft_ab_idx =
+	Ctlsp_FormulaReadABIndex(Ctlsp_FormulaReadLeftChild(F));
+      Fright_ab_idx =
+	Ctlsp_FormulaReadABIndex(Ctlsp_FormulaReadRightChild(F));
+    } else { /* to remove uninitialized variable warnings */
+      Fleft_ab_idx = 0;
+      Fright_ab_idx = 0;
+    }
+    
+    switch(Ctlsp_FormulaReadType(F)) {
+    case Ctlsp_FALSE_c:
+      result = 0;
+      break;
+    case Ctlsp_TRUE_c:
+      result = 1;
+      break;
+    case Ctlsp_X_c:
+    case Ctlsp_NOT_c:
+    case Ctlsp_ID_c:
+      result = LtlSetGetElt(A, index);
+      break;
+    case Ctlsp_AND_c:
+      if (Ctlsp_LtlFormulaIsPropositional(F))
+	result = LtlSetGetElt(A, index);
+      else {
+	result = (SI(tableau, Fleft_ab_idx, A) &&
+		  SI(tableau, Fright_ab_idx, A));
+      }
+      break;
+    case Ctlsp_OR_c:
+      if (Ctlsp_LtlFormulaIsPropositional(F))
+	result = LtlSetGetElt(A, index);
+      else {
+	result = (SI(tableau, Fleft_ab_idx, A) ||
+		  SI(tableau, Fright_ab_idx, A));
+      }
+      break;
+    case Ctlsp_U_c:
+      XF = LtlTableauGetUniqueXFormula(tableau, F);	  
+      result = (SI(tableau, Fright_ab_idx, A) ||
+		(SI(tableau, Fleft_ab_idx, A) &&
+		 LtlSetGetElt(A, Ctlsp_FormulaReadABIndex(XF))));
+      break;
+    case Ctlsp_R_c:
+      XF = LtlTableauGetUniqueXFormula(tableau, F);	  
+      result = SI(tableau, Fright_ab_idx, A) &&
+	(SI(tableau, Fleft_ab_idx, A) ||
+	 LtlSetGetElt(A, Ctlsp_FormulaReadABIndex(XF)));
+      break;
+    default:
+      assert(0);
+    }
+  }
+  
+#ifdef DEBUG_LTLMC
+  if (tableau->verbosity > 3) {
+    fprintf(vis_stdout, "...SI( %d, ", index);
+    LtlSetPrintIndex(tableau->abIndex, A);
+    fprintf(vis_stdout, "     )=%d\n", result);
+  }
+#endif
+  
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Put the node into the fairset if it contains a until formula.]
+
+  Description [Each until formula in the 'untilUnqiueTable' corresponds to
+  a fair set (a set of vertices in the automaton, represented by a hash
+  table. A vertex belongs to a fair set iff its cover set contains the until
+  formula.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+AutomatonComputeFair(
+  LtlTableau_t *tableau,
+  LtlSet_t *r,
+  vertex_t *vtx1)
+{
+  st_table *uniqueTable = tableau->untilUniqueTable;
+  char *key, *value;
+  st_generator *gen;
+
+  /* Notice that each pair in 'uniqueTable' is a (Unitl formula, Fair set) */
+  st_foreach_item(uniqueTable, gen, &key, &value) {
+    Ctlsp_Formula_t *F = (Ctlsp_Formula_t *) key;
+    Ctlsp_Formula_t *right = Ctlsp_FormulaReadRightChild(F);
+    int F_ab_idx = Ctlsp_FormulaReadABIndex(F);
+    int right_ab_idx = Ctlsp_FormulaReadABIndex(right);
+    lsList Fair = (lsList) value;
+      
+    if ( SI(tableau, right_ab_idx, r) || !(SI(tableau, F_ab_idx, r)) ) {
+      lsNewEnd(Fair, (lsGeneric) vtx1, (lsHandle *) 0); 
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Convert the fair sets of the tableau into the fair set in the
+  automaton.]
+
+  Description [The fairness in the tableau is "a hash table (Until formula,
+  FairVerticesList)". The fairness in the automaton should be " a list of
+  hash tables" (each hash table corresponds to a fair set, and a vertex is
+  in the hash table iff it's in that fair set).
+
+  Return 0 iff there is an empty fairset (which means the language of the 
+  automaton is empty no matter what);  Return 1 otherwise.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+AutomatonCreateFairList(
+  LtlTableau_t *tableau,
+  Ltl_Automaton_t *aut)
+{
+  lsList FairList = aut->Fair;
+  char *key, *value;
+  st_generator *gen;
+  int noEmptyFairSet = 1;
+
+  st_foreach_item(tableau->untilUniqueTable, gen, &key, &value) {
+    lsList Fair = (lsList) value;
+
+    /* translate a lsList into a st_table */
+    if (lsLength(Fair) > 0) {
+      lsGen lsgen;
+      lsGeneric lsdata;
+      st_table *tbl = st_init_table(st_ptrcmp, st_ptrhash);
+      
+      lsForEachItem (Fair, lsgen, lsdata) {
+	st_insert(tbl, lsdata, lsdata);
+      }
+      lsNewEnd(FairList, (lsGeneric) tbl, (lsHandle *) 0); 
+    }else 
+      noEmptyFairSet = 0;
+
+    lsDestroy(Fair, (void (*)(lsGeneric)) NULL);
+  }
+
+  return noEmptyFairSet;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Generate the next-formulae set.]
+  
+  Description [toCover = { u: X(u) is in s }. In other words, for each formula
+  of the form X(u) in the set 's', add the subformula u into 'toCover'.]
+
+  SideEffects ['toCover' is changed.]
+
+******************************************************************************/
+static void
+AutomatonAssignNext(
+  LtlTableau_t *tableau,
+  LtlSet_t * toCover,
+  LtlSet_t * s)
+{
+  int i;
+  Ctlsp_FormulaType type;
+  Ctlsp_Formula_t *left;
+  int left_ab_idx;
+      
+  LtlSetClear(toCover);
+  
+  for (i=0; i<tableau->abIndex; i++) {
+    if (LtlSetGetElt(s, i)) {
+      type = Ctlsp_FormulaReadType(tableau->abTable[i].F);
+      if (type == Ctlsp_X_c) {
+	left = Ctlsp_FormulaReadLeftChild(tableau->abTable[i].F);
+	left_ab_idx = Ctlsp_FormulaReadABIndex(left);
+	LtlSetSetElt(toCover, left_ab_idx);
+	
+      }
+    }
+  }
+}  
+
+
+/**Function********************************************************************
+
+  Synopsis    [Create the set representation of the given formula.]
+
+  Description [Its size will be the total number of sub-formulae in the
+  tableau. Only the bit corresponding to the given formula is set.]
+
+  SideEffects [The result should be freed by the caller.]
+
+******************************************************************************/
+static LtlSet_t *
+AutomatonSetCreate(
+  LtlTableau_t *tableau,
+  Ctlsp_Formula_t *F)  
+{
+  LtlSet_t *cs = LtlSetNew(tableau->abIndex);
+
+  if (!F)
+    return cs;
+
+  LtlSetSetElt(cs, Ctlsp_FormulaReadABIndex(F));
+    
+  return cs;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Build the cover for a given set 'toCover'.]
+
+  Description [The cover is "a list of sets", where the sets are product terms
+  and the list is in DNF form (union of all its product terms).]
+
+  SideEffects [The result should be freed by the caller.]
+
+******************************************************************************/
+static lsList
+AutomatonBuildCover(
+  LtlTableau_t *tableau,
+  LtlSet_t *ToCover)
+{
+  LtlSet_t *Current = LtlSetNew(tableau->abIndex);
+  LtlSet_t *Covered = LtlSetNew(tableau->abIndex);
+  lsList Cover = lsCreate();
+
+  AutomatonBuildCover_Aux(tableau, ToCover, Current, Covered, Cover);
+  LtlSetFree(Current);
+  LtlSetFree(Covered);
+  
+  /* Boolean Minimization -- heuristics */
+  if (tableau->booleanmin == 1) {
+    if (lsLength(Cover)) {
+      lsList list = Cover;
+      Cover = LtlCoverPrimeAndIrredundant(tableau, Cover,
+					  tableau->abTableNegate);
+      lsDestroy(list, (void (*)(lsGeneric))LtlSetFree);
+    }
+  }
+  return Cover;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Recursively construct the cover.]
+
+  Description [the cover is updated in the parameter 'lsList Cover'. This
+  function is used in AutomatonBuildCover() only.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+AutomatonBuildCover_Aux(
+  LtlTableau_t *tableau,
+  LtlSet_t *pToCover,
+  LtlSet_t *pCurrent,
+  LtlSet_t *pCovered,
+  lsList Cover)
+{
+  LtlSet_t *ToCover = LtlSetCopy(pToCover);
+  LtlSet_t *Current = LtlSetCopy(pCurrent);
+  LtlSet_t *Covered = LtlSetCopy(pCovered);
+  int i;
+
+#ifdef DEBUG_LTLMC  
+  if (tableau->verbosity >2 ) {
+    fprintf(vis_stdout, "ToCover=");
+    LtlSetPrintIndex(tableau->abIndex, ToCover);
+    fprintf(vis_stdout, "Current=");
+    LtlSetPrintIndex(tableau->abIndex, Current);
+    fprintf(vis_stdout, "Covered=");
+    LtlSetPrintIndex(tableau->abIndex, Covered);
+    fflush(vis_stdout);
+  }      
+#endif
+  
+  if (LtlSetIsEmpty(ToCover)) {
+#if 1
+    /* chao: 7/22/2002 remove identical set in current Cover */
+    if (!LtlSetIsInList(Current, Cover))
+#endif
+      lsNewEnd(Cover, (lsGeneric) LtlSetCopy(Current), (lsHandle *) 0);
+    /* return */
+  }else {
+    /* select 'u' from 'ToCover' */
+    for (i=0; i<tableau->abIndex; i++) {
+      if (LtlSetGetElt(ToCover,i))
+	break;
+    }
+    /* remove 'u' from 'ToCover' and add it to 'Covered' */
+    LtlSetClearElt(ToCover, i);
+    LtlSetSetElt(Covered, i);
+    
+    /* if HAS_TO_BE_STORED(u), store into 'Current' */
+    if (HasToBeStored(tableau,i)) 
+      LtlSetSetElt(Current, i);
+    
+    /* if CONTRADICTION(u, ToCover, Current, Covered), return 'Cover' */
+    if (Contradiction(tableau, i, ToCover, Current, Covered)) {
+      ; /* return */
+    }else if (Redundant(tableau, i, ToCover, Current, Covered)) {
+      AutomatonBuildCover_Aux(tableau, ToCover, Current, Covered, Cover);
+      /* return */
+    }else {
+      if (Ctlsp_LtlFormulaIsElementary(tableau->abTable[i].F)) {
+	LtlSetSetElt(Current, i);
+	AutomatonBuildCover_Aux(tableau, ToCover, Current, Covered,
+				Cover);
+	/* return */
+      }else {
+	int A0B0 = tableau->abTable[i].A[0].B[0];
+	int A0B1 = tableau->abTable[i].A[0].B[1];
+	int A0n = tableau->abTable[i].A[0].n;
+	int A1B0 = tableau->abTable[i].A[1].B[0];
+	int A1B1 = tableau->abTable[i].A[1].B[1];
+	int A1n = tableau->abTable[i].A[1].n;
+	
+	/* cover( (ToCover+alph2(u)-Current), Current, Covered, Cover) */
+	if (A1B0 != -1 || A1B1!= -1 || A1n!= -1) {
+	  LtlSet_t *saveToCover = LtlSetCopy(ToCover);	      
+	  if (A1B0 != -1)
+	    if (!LtlSetGetElt(Current, A1B0))
+	      LtlSetSetElt(ToCover, A1B0);
+	  if (A1B1 != -1)
+	    if (!LtlSetGetElt(Current, A1B1))
+	      LtlSetSetElt(ToCover, A1B1);
+	  if (A1n != -1)
+	    if (!LtlSetGetElt(Current, A1n))
+	      LtlSetSetElt(ToCover, A1n);
+	  
+	  AutomatonBuildCover_Aux(tableau, ToCover, Current, Covered,
+				  Cover);
+	  
+	  LtlSetAssign(ToCover, saveToCover);
+	  LtlSetFree(saveToCover);
+	}
+	
+	/* cover( (ToCover+alph1(u)-Current), Current, Covered, Cover) */
+	if (A0B0 != -1 || A0B1!= -1 || A0n!= -1) {	      
+	  if (A0B0 != -1)
+	    if (!LtlSetGetElt(Current, A0B0))
+	      LtlSetSetElt(ToCover, A0B0);
+	  if (A0B1 != -1)
+	    if (!LtlSetGetElt(Current, A0B1))
+	      LtlSetSetElt(ToCover, A0B1);
+	  if (A0n != -1)
+	    if (!LtlSetGetElt(Current, A0n))
+	      LtlSetSetElt(ToCover, A0n);
+	  
+	  AutomatonBuildCover_Aux(tableau, ToCover, Current, Covered,
+				  Cover);
+	}
+	/* return */
+      }
+    }
+  }
+  
+  /* Clean-Ups */
+  LtlSetFree(ToCover);
+  LtlSetFree(Current);
+  LtlSetFree(Covered);
+}
+
+
+
+
+
Index: vis_dev/vis-2.3/src/ltl/ltlCompose.c
===================================================================
--- vis_dev/vis-2.3/src/ltl/ltlCompose.c	(revision 14)
+++ vis_dev/vis-2.3/src/ltl/ltlCompose.c	(revision 14)
@@ -0,0 +1,1722 @@
+/**CFile***********************************************************************
+
+  FileName    [ltlCompose.c]
+
+  PackageName [ltl]
+
+  Synopsis    [Write the Buechi automaton into a file.]
+
+  Author      [Chao Wang<chao.wang@colorado.EDU>]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "ltlInt.h"
+
+static char rcsid[] UNUSED = "$Id: ltlCompose.c,v 1.30 2005/04/28 08:51:19 bli Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void AutomatonGetInputNames(Ltl_Automaton_t *A, array_t *InputNames, array_t *Name2LabelIdx);
+static int AutomatonCountSelector(Ltl_Automaton_t *A);
+static int AutomatonComputeInitState(Ltl_Automaton_t *A);
+/*static lsList AutomatonLabelGetCubes(Ltl_Automaton_t *A, LtlSet_t *compositeLabel, Ntk_Network_t *network);*/
+static lsList GetCubes_Aux(Ltl_Automaton_t *A, int index);
+static char * StringNormalize(char *inputString);
+static void AutomatonVtxLabelToBlifMv(FILE *fp, Ltl_Automaton_t *A, vertex_t *vtx);
+static void VtxLabelToBlifMv_Aux(FILE *fp, Ltl_Automaton_t *A, int node_idx, int index, st_table *CreatedSignals);
+
+/**AutomaticEnd***************************************************************/
+    
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Translate the Automaton into Dot format.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Ltl_AutomatonToDot(
+  FILE *fp,
+  Ltl_Automaton_t *aut,
+  int level)
+{
+  edge_t   *edge;
+  vertex_t *vtx1, *vtx2;         
+  Ltl_AutomatonNode_t *node, *node2;
+  lsGen     lsgen, lsgen2;
+  st_table  *FairSet;
+  st_generator *stgen;
+  Ctlsp_Formula_t *F;
+  char *tmpString;
+  int fairindex, first, i, n;
+  
+  /*-------------------------------------------------
+   * digraph "G(F(p=1))" {
+   * node [shape=ellipse];
+   * size = "7.5,10"
+   * center = true;
+   * "title" [label="G(F(p=1))", shape=plaintext];
+   *-------------------------------------------------
+   */
+  if (aut->name)
+    tmpString = aut->name;
+  else
+    tmpString = "";
+  
+  fprintf(fp, "\ndigraph \"%s\" {\nnode [shape=ellipse];\nsize = \"7.5,10\"\ncenter = true;\n\"title\" [label=\"%s\",shape=plaintext];", tmpString, tmpString);
+  
+  /*-------------------------------------------------
+   * "n1" [label="n1\n{p=1}\n(1)"];
+   *-------------------------------------------------
+   */
+  foreach_vertex( aut->G, lsgen, vtx1) {
+    node = (Ltl_AutomatonNode_t *)vtx1->user_data;
+    fprintf(fp,"\n\"n%d\" [label=\"n%d\\n{", node->index, node->index);
+    if (node->Labels) {
+      first = 1; n = array_n(aut->labelTable);
+      for (i=0; i<n; i++) {
+	if (LtlSetGetElt(node->Labels, i)) {
+	  if (!first)	  fprintf(fp, ",");
+	  else       	  first = 0;
+	  F = array_fetch(Ctlsp_Formula_t *, aut->labelTable, i);
+	  Ctlsp_FormulaPrint(fp, F);
+	}
+      }
+    }
+    fprintf(fp, "}\\n(");
+    fairindex = 1;
+    lsForEachItem(aut->Fair, lsgen2, FairSet) {
+      if (st_is_member(FairSet, vtx1))
+	fprintf(fp, " %d ", fairindex);
+      fairindex++;
+    }
+    fprintf(fp, ")\"];");
+  }
+
+  /*-------------------------------------------------
+   * "init-n2" [style=invis]
+   * "init-n2" -> "n2";
+   *-------------------------------------------------
+   */
+  st_foreach_item(aut->Init, stgen, &vtx1, NIL(char *)) {
+    node = (Ltl_AutomatonNode_t *) vtx1->user_data;
+    fprintf(fp, "\n\"init-n%d\" [style=invis]", node->index);
+    fprintf(fp, "\n\"init-n%d\" -> \"n%d\";", node->index, node->index);
+  }
+
+
+  /*-------------------------------------------------
+   * "n1" -> "n1";
+   *-------------------------------------------------
+   */
+  foreach_edge(aut->G, lsgen, edge) {
+    vtx1 = g_e_source(edge);
+    vtx2 = g_e_dest(edge);
+    node = (Ltl_AutomatonNode_t *) vtx1->user_data;
+    node2 = (Ltl_AutomatonNode_t *) vtx2->user_data;
+    fprintf(fp, "\n\"n%d\" -> \"n%d\";", node->index, node2->index);
+  }
+  fprintf(fp, "\n}\n");
+}
+
+
+/**Function********************************************************************
+   
+  Synopsis    [Translate the automaton to a BlifMv file.]
+  
+  Description [The Hrc_Manager may or may not be provided. If not, the blifmv
+  file generated is not complete (all the inputs are assummed to be boolean).
+  
+  Notice that the labels on each state are propositional subformulae, not
+  necessarily atomic propositions.]
+  
+  SideEffects []
+  
+  SeeAlso     []
+
+******************************************************************************/
+int
+Ltl_AutomatonToBlifMv(
+  FILE *fp,             
+  Ntk_Network_t *network,
+  Ltl_Automaton_t *A)     
+{
+  Var_Variable_t *inputVar;
+  array_t *InputNames = array_alloc(char *, 0);
+  array_t *Name2LabelIdx = array_alloc(st_table *, 0);
+  Ntk_Node_t *ntknode;
+  char *inputName;
+  st_generator *stgen;
+  lsGen lsgen, lsgen2;
+  int i, j, is_enum, range;
+  int sel_num, sel_cnt;
+  edge_t *edge;
+  vertex_t *vtx, *vtx2;
+  st_table *FairSet, *tmptbl;
+  int InitIdx = AutomatonComputeInitState(A);
+  char InitStr[10];
+  int result = 1;
+  array_t *labelArray;
+  
+  /* The initState of the automaton */
+  if (InitIdx == -1) 
+    sprintf(InitStr, "Init");
+  else
+    sprintf(InitStr, "n%d", InitIdx);
+  
+  if (network == NIL(Ntk_Network_t)) {
+    result = 0;
+    fprintf(vis_stderr, "Warning: the BlifMv output is incomplete. (The current node is empty. Read in design.)\n");
+  }
+
+  /* Retrieve all the input names on the labels; For each input, create a
+   *  hash table and add all the label subformulae contains that input;
+   *  Finally, calculate the size of the "selector" 
+   */
+  AutomatonGetInputNames(A, InputNames, Name2LabelIdx);
+  sel_num = AutomatonCountSelector(A);
+  fprintf(fp, "\n# Buechi automaton: %s\n\n", A->name);
+  
+  /*-------------------------------------------------------
+   * .model Buechi$AUT
+   * .root  Buechi$AUT
+   *-------------------------------------------------------
+   */
+   fprintf(fp, ".model Buechi$AUT\n.root Buechi$AUT");
+  
+   /*-------------------------------------------------------
+    * .inputs in1 in2 in3 ... inN 
+    *-------------------------------------------------------
+    */
+   fprintf(fp, "\n.inputs ");
+   for (i=0; i<array_n(InputNames); i++) {
+     inputName = array_fetch(char *, InputNames, i);
+     fprintf(fp, "%s ", inputName);
+   }
+
+   /*-------------------------------------------------------
+    * .outputs fair1 fair2 fair3... fairN
+    *-------------------------------------------------------
+    */
+   fprintf(fp, "\n.outputs ");
+   if ( lsLength(A->Fair) != 0) {
+     for (i=0; i<lsLength(A->Fair); i++) {
+       fprintf(fp, "fair%d$AUT ", i+1);
+     }
+   }else
+     fprintf(fp, "fair1$AUT");
+
+   /*-------------------------------------------------------
+    * .mv in1 3 RED GREEN YELLOW 
+    *-------------------------------------------------------
+    */
+   if (network != NIL(Ntk_Network_t)) {
+     for (i=0; i<array_n(InputNames); i++) {
+       inputName = array_fetch(char *, InputNames, i);
+       ntknode = Ntk_NetworkFindNodeByName(network, inputName);
+       assert(ntknode != NIL(Ntk_Node_t));
+       inputVar = Ntk_NodeReadVariable(ntknode);
+       is_enum = Var_VariableTestIsEnumerative(inputVar);
+       range = Var_VariableReadNumValues(inputVar);
+       if (is_enum) {
+	 if (range != 2) 
+	   fprintf(fp, "\n.mv %s %d\n", inputName, range);
+       }else {
+	 fprintf(fp, "\n.mv %s %d ", inputName, range);
+	 for (j=0; j<range; j++) {
+	   fprintf(fp, "%s ",
+		   Var_VariableReadSymbolicValueFromIndex(inputVar,j));
+	 }
+       }
+     }
+   }
+
+   /*-------------------------------------------------------  
+    * .mv stateD$AUT N Init n1 n2 n3 ... nN 
+    * .mv state$AUT  N Init n1 n2 n3 ... nN
+    *-------------------------------------------------------
+    */
+   if (InitIdx == -1) 
+     fprintf(fp, "\n.mv stateD$AUT %d Init Trap ",
+	     lsLength(g_get_vertices(A->G)) + 2);
+   else
+     fprintf(fp, "\n.mv stateD$AUT %d Trap ",
+	     lsLength(g_get_vertices(A->G)) + 1);
+   foreach_vertex(A->G, lsgen, vtx) {
+     fprintf(fp, "n%d ", Ltl_AutomatonVtxGetNodeIdx(vtx));
+   }
+   if (InitIdx == -1)
+     fprintf(fp, "\n.mv state$AUT %d Init Trap ",
+	     lsLength(g_get_vertices(A->G)) + 2);
+   else
+     fprintf(fp, "\n.mv state$AUT %d Trap ",
+	     lsLength(g_get_vertices(A->G)) + 1);
+   foreach_vertex(A->G, lsgen, vtx) {  
+     fprintf(fp, "n%d ", Ltl_AutomatonVtxGetNodeIdx(vtx));
+   }
+
+   /*-------------------------------------------------------
+    * .mv selector n
+    * .table selector 
+    * - 
+    *-------------------------------------------------------
+    */
+   if (sel_num > 1) 
+     fprintf(fp, "\n.mv selector$AUT %d\n.table selector$AUT\n-", sel_num);
+
+   /*-------------------------------------------------------
+    * for each state label, create a signal n1_##_label$AUT (recursively)
+    *-------------------------------------------------------
+    */
+   labelArray = array_alloc(vertex_t *, 0);
+   foreach_vertex(A->G, lsgen, vtx) {
+     AutomatonVtxLabelToBlifMv(fp, A, vtx);
+     array_insert_last(vertex_t *, labelArray, vtx);
+   }
+   
+   /*-------------------------------------------------------  
+    * .latch stateD$AUT state$AUT
+    * .reset state$AUT
+    * Init (or ns) 
+    *-------------------------------------------------------
+    */
+   fprintf(fp, "\n.latch stateD$AUT state$AUT\n.reset -> state$AUT\n%s",
+	   InitStr);
+
+
+   /*------------------------------------------------------
+    * .table selector$AUT state$AUT n1_label$AUT n2_label... -> stateD$AUT
+    * .default Trap
+    * 0 1 0 0 ... n1
+    * 1 0 1       n2
+    * ...
+    *------------------------------------------------------
+    */
+   if (sel_num >1)
+     fprintf(fp, "\n.table selector$AUT state$AUT ");
+   else
+     fprintf(fp, "\n.table state$AUT ");
+
+   arrayForEachItem(vertex_t *, labelArray, i, vtx) {
+     fprintf(fp, "n%d_label$AUT ", Ltl_AutomatonVtxGetNodeIdx(vtx));
+   }
+   fprintf(fp, " -> stateD$AUT\n.default Trap");
+
+   if (InitIdx == -1) {
+     sel_cnt = 0;
+     arrayForEachItem(vertex_t *, labelArray, i, vtx) {
+       if (!st_is_member(A->Init, vtx))
+	 continue;
+       if (sel_num > 1) {
+	 if (st_count(A->Init) == 1) 
+	   fprintf(fp, "\n- Init ");
+	 else
+	   fprintf(fp, "\n%d Init ", sel_cnt);
+       }else
+	 fprintf(fp, "\nInit ");
+       
+       for(j=0; j<array_n(labelArray); j++)
+	 fprintf(fp, "%s ", ((i==j)?"1":"-"));
+
+       fprintf(fp, "   n%d", Ltl_AutomatonVtxGetNodeIdx(vtx));
+
+       if (sel_num > 1)
+	 sel_cnt++;
+     }
+   }
+
+   /* for each edge (n1, n2) with n2 labeled n2_label$AUT, add entry: 
+    *-------------------------------------------------------     
+    * selector 1 0 0  ...     n1
+    * selector 0 1 0  ...     n2
+    * ...
+    *-------------------------------------------------------
+    */
+   foreach_vertex(A->G, lsgen, vtx) {
+     int n1 = Ltl_AutomatonVtxGetNodeIdx(vtx);
+     int outDegree = lsLength(g_get_out_edges(vtx));
+     sel_cnt = 0;
+     foreach_out_edge(vtx, lsgen2, edge) {
+       int n2 = Ltl_AutomatonVtxGetNodeIdx(g_e_dest(edge));
+
+       if (sel_num > 1) {
+	 if (outDegree == 1) 
+	   fprintf(fp, "\n- n%d ", n1);
+	 else
+	   fprintf(fp, "\n%d n%d ", sel_cnt, n1);
+       }else {
+	 fprintf(fp, "\nn%d ", n1);
+       }
+       
+       arrayForEachItem(vertex_t *, labelArray, i, vtx2) {
+	 fprintf(fp, "%s ", ((vtx2 == g_e_dest(edge))?"1":"-"));
+       }
+       fprintf(fp, "   n%d", n2);
+	  
+       if (sel_num > 1)
+	 sel_cnt++;
+     }
+   }
+   array_free(labelArray);
+
+   /*-------------------------------------------------------  
+    * .table state -> fair1
+    * .default 0 
+    * ------------------------------------------------------
+    */
+   if (lsLength(A->Fair) != 0) {
+     i = 1;
+     lsForEachItem(A->Fair, lsgen, FairSet) {
+       int isFirst = 1;
+       fprintf(fp, "\n.table state$AUT -> fair%d$AUT ", i++);
+       fprintf(fp, "\n.default 0\n(");
+       st_foreach_item(FairSet, stgen, &vtx, NIL(char *)) {
+	 if (isFirst)
+	   isFirst = 0;
+	 else
+	   fprintf(fp, ",");
+	 fprintf(fp, "n%d", Ltl_AutomatonVtxGetNodeIdx(vtx));
+       }
+       fprintf(fp, ")   1");
+     }
+   }else {
+     fprintf(fp, "\n.table state$AUT -> fair1$AUT ");
+     if (InitIdx == -1)
+       fprintf(fp, "\n.default 0\n!(Trap,Init)   1");
+     else
+       fprintf(fp, "\n.default 0\n!(Trap)   1");
+   }
+
+   /*-------------------------------------------------------  
+    * .end 
+    * ------------------------------------------------------
+    */
+   fprintf(fp, "\n.end\n");
+
+   /* free the name array 
+    */
+   array_free(InputNames);
+   arrayForEachItem(st_table *, Name2LabelIdx, i, tmptbl) {
+     st_free_table(tmptbl);
+   }
+   array_free(Name2LabelIdx);
+ 
+   return result;
+}
+
+#if 0
+int
+Ltl_AutomatonToBlifMv_Old(
+  FILE *fp,             
+  Ntk_Network_t *network,
+  Ltl_Automaton_t *A)     
+{
+  Var_Variable_t *inputVar;
+  array_t *InputNames = array_alloc(char *, 0);
+  array_t *Name2LabelIdx = array_alloc(st_table *, 0);
+  Ntk_Node_t *ntknode;
+  char *inputName;
+  st_generator *stgen, *stgen2;
+  lsGen lsgen, lsgen2, lsgen3;
+  int i, j, is_enum, range;
+  long index;
+  int sel_num, sel_cnt;
+  edge_t *edge;
+  vertex_t *vtx;
+  st_table *FairSet, *tmptbl;
+  LtlSet_t *label;
+  int InitIdx = AutomatonComputeInitState(A);
+  char InitStr[10];
+  int result = 1;
+
+  /* The initState of the automaton */
+  if (InitIdx == -1) 
+    sprintf(InitStr, "Init");
+  else
+    sprintf(InitStr, "n%d", InitIdx);
+  
+  if (network == NIL(Ntk_Network_t)) {
+    result = 0;
+    fprintf(vis_stderr, "Warning: the BlifMv output is incomplete. (The current node is empty. Read in design.)\n");
+  }
+
+  /* Retrieve all the input names on the labels; For each input, create a
+   *  hash table and add all the label subformulae contains that input;
+   *  Finally, calculate the size of the "selector" 
+   */
+  AutomatonGetInputNames(A, InputNames, Name2LabelIdx);
+  sel_num = AutomatonCountSelector(A);
+  fprintf(fp, "\n# Buechi automaton: %s\n\n", A->name);
+  
+  /*-------------------------------------------------------
+   * .model Buechi$AUT
+   * .root  Buechi$AUT
+   *-------------------------------------------------------
+   */
+   fprintf(fp, ".model Buechi$AUT\n.root Buechi$AUT");
+  
+   /*-------------------------------------------------------
+    * .inputs in1 in2 in3 ... inN 
+    *-------------------------------------------------------
+    */
+   fprintf(fp, "\n.inputs ");
+   for (i=0; i<array_n(InputNames); i++) {
+     inputName = array_fetch(char *, InputNames, i);
+     fprintf(fp, "%s ", inputName);
+   }
+
+   /*-------------------------------------------------------
+    * .outputs fair1 fair2 fair3... fairN
+    *-------------------------------------------------------
+    */
+   fprintf(fp, "\n.outputs ");
+   if ( lsLength(A->Fair) != 0) {
+     for (i=0; i<lsLength(A->Fair); i++) {
+       fprintf(fp, "fair%d$AUT ", i+1);
+     }
+   }else
+     fprintf(fp, "fair1$AUT");
+
+   /*-------------------------------------------------------
+    * .mv in1 3 RED GREEN YELLOW 
+    *-------------------------------------------------------
+    */
+   if (network != NIL(Ntk_Network_t)) {
+     for (i=0; i<array_n(InputNames); i++) {
+       inputName = array_fetch(char *, InputNames, i);
+       ntknode = Ntk_NetworkFindNodeByName(network, inputName);
+       assert(ntknode != NIL(Ntk_Node_t));
+       inputVar = Ntk_NodeReadVariable(ntknode);
+       is_enum = Var_VariableTestIsEnumerative(inputVar);
+       range = Var_VariableReadNumValues(inputVar);
+       if (is_enum) {
+	 if (range != 2) 
+	   fprintf(fp, "\n.mv %s %d\n", inputName, range);
+       }else {
+	 fprintf(fp, "\n.mv %s %d ", inputName, range);
+	 for (j=0; j<range; j++) {
+	   fprintf(fp, "%s ",
+		   Var_VariableReadSymbolicValueFromIndex(inputVar,j));
+	 }
+       }
+     }
+   }
+
+   /*-------------------------------------------------------  
+    * .mv stateD$AUT N Init n1 n2 n3 ... nN 
+    * .mv state$AUT  N Init n1 n2 n3 ... nN
+    *-------------------------------------------------------
+    */
+   if (InitIdx == -1) 
+     fprintf(fp, "\n.mv stateD$AUT %d Init Trap ",
+	     lsLength(g_get_vertices(A->G)) + 2);
+   else
+     fprintf(fp, "\n.mv stateD$AUT %d Trap ",
+	     lsLength(g_get_vertices(A->G)) + 1);
+   foreach_vertex(A->G, lsgen, vtx) {
+     fprintf(fp, "n%d ", Ltl_AutomatonVtxGetNodeIdx(vtx));
+   }
+   if (InitIdx == -1)
+     fprintf(fp, "\n.mv state$AUT %d Init Trap ",
+	     lsLength(g_get_vertices(A->G)) + 2);
+   else
+     fprintf(fp, "\n.mv state$AUT %d Trap ",
+	     lsLength(g_get_vertices(A->G)) + 1);
+   foreach_vertex(A->G, lsgen, vtx) {  
+     fprintf(fp, "n%d ", Ltl_AutomatonVtxGetNodeIdx(vtx));
+   }
+
+   /*-------------------------------------------------------
+    * .mv selector n
+    * .table selector 
+    * - 
+    *-------------------------------------------------------
+    */
+   if (sel_num > 1) 
+     fprintf(fp, "\n.mv selector$AUT %d\n.table selector$AUT\n-", sel_num);
+
+   /*-------------------------------------------------------  
+    * .latch stateD$AUT state$AUT
+    * .reset state$AUT
+    * Init (or ns) 
+    *-------------------------------------------------------
+    */
+   fprintf(fp, "\n.latch stateD$AUT state$AUT\n.reset -> state$AUT\n%s",
+	   InitStr);
+   
+   /*------------------------------------------------------
+    * .table selector$AUT state$AUT in1 in2 ... inN -> stateD$AUT
+    * .default Trap 
+    *------------------------------------------------------
+    */
+   if (sel_num >1)
+     fprintf(fp, "\n.table selector$AUT state$AUT ");
+   else
+     fprintf(fp, "\n.table state$AUT ");
+   
+   for (i=0; i<array_n(InputNames); i++) {
+     inputName = array_fetch(char *, InputNames, i);
+     fprintf(fp, "%s ", inputName);
+   }
+   fprintf(fp, " -> stateD$AUT\n.default Trap");
+   
+  
+   /* for each initial state n2 with label "in1=p  !in3=q...", add entry: 
+    *-------------------------------------------------------
+    *  selector Init (p) -  (!(q)) ..  n2   
+    *-------------------------------------------------------
+    */
+   if (InitIdx == -1) {
+     sel_cnt = 0;
+     st_foreach_item(A->Init, stgen, &vtx, NIL(char *)) {
+       int n2 = Ltl_AutomatonVtxGetNodeIdx(vtx);
+       /* each 'compLabel' is a set of "propositional formulae" */
+       LtlSet_t *compLabel = LtlAutomatonVertexGetLabels(vtx);
+       /* each item in labelList is a set of "atomic proposition" */
+       lsList labelList = AutomatonLabelGetCubes(A, compLabel, network);
+       lsForEachItem(labelList, lsgen, label) {
+	 if (sel_num > 1) {
+	   if (st_count(A->Init) == 1) 
+	     fprintf(fp, "\n- Init ");
+	   else
+	     fprintf(fp, "\n%d Init ", sel_cnt);
+	 }else
+	   fprintf(fp, "\nInit ");
+	 arrayForEachItem(st_table *, Name2LabelIdx, i, tmptbl) {
+	   int isFirst = 1;
+	   int is_universe = 1;
+	   /* The value is the universe '-' iff it is not in the label */
+	   if (!LtlSetIsEmpty(label)) {
+	     st_foreach_item(tmptbl, stgen2, &index, NIL(char *)) {
+	       if (LtlSetGetElt(label, (int) index)) {
+		 is_universe = 0;
+		 st_free_gen(stgen2);
+		 break;
+	       }
+	     }
+	   }
+	   if (is_universe) {
+	     fprintf(fp, "- ");
+	     continue;
+	   }
+	   /* Otherwise, write the value. Note that the value should be
+	    * the conjunction of the values of the atomic propositions.
+	    * A * B * C = !(!A + !B +!C) 
+	    */
+	   fprintf(fp, "!(");
+	   st_foreach_item(tmptbl, stgen2, &index, NIL(char *)) {
+	     if (LtlSetGetElt(label, (int) index)) {
+	       Ctlsp_Formula_t *F = array_fetch(Ctlsp_Formula_t *,
+						A->labelTable,
+						(int) index);
+	       if (isFirst)
+		 isFirst = 0;
+	       else
+		 fprintf(fp, ",");
+	       if (Ctlsp_FormulaReadType(F) == Ctlsp_NOT_c) {
+		 F = Ctlsp_FormulaReadLeftChild(F);
+	       }else {
+		 fprintf(fp, "!");
+	       }
+	       
+	       fprintf(fp, "(%s)", Ctlsp_FormulaReadValueName(F));
+	     }
+	   }
+	   fprintf(fp, ") ");
+	 }
+	 fprintf(fp, "   n%d", n2);
+       }
+       lsDestroy(labelList, (void (*)(lsGeneric))LtlSetFree);
+       
+       if (sel_num > 1)
+	 sel_cnt++;
+     }
+   }
+
+   /* for each edge (n1, n2) with n2 labelled "in1=p !in3=q...", add entry: 
+    *-------------------------------------------------------     
+    * selector n1 (p) - (!(q)) ...     n2
+    *-------------------------------------------------------
+    */
+   foreach_vertex(A->G, lsgen, vtx) {
+     int n1 = Ltl_AutomatonVtxGetNodeIdx(vtx);
+     int outDegree = lsLength(g_get_out_edges(vtx));
+     sel_cnt = 0;
+     foreach_out_edge(vtx, lsgen2, edge) {
+       int n2 = Ltl_AutomatonVtxGetNodeIdx(g_e_dest(edge));
+       /* 'compLabel' contains a set of "propositional formulae" */
+       LtlSet_t *compLabel =   LtlAutomatonVertexGetLabels(g_e_dest(edge));
+       /* each item in 'labelList' is a set of "atomic propositions" */ 
+       lsList labelList = AutomatonLabelGetCubes(A, compLabel, network);
+       lsForEachItem(labelList, lsgen3, label) {
+	 if (sel_num > 1) {
+	   if (outDegree == 1) 
+	     fprintf(fp, "\n- n%d ", n1);
+	   else
+	     fprintf(fp, "\n%d n%d ", sel_cnt, n1);
+	 }else {
+	   fprintf(fp, "\nn%d ", n1);
+	 }
+	 arrayForEachItem(st_table *, Name2LabelIdx, i, tmptbl) {
+	   int isFirst = 1;
+	   int is_universe = 1;
+	   /* the value is universe '-' iff it is not in the label */
+	   if (!LtlSetIsEmpty(label)) {
+	     st_foreach_item(tmptbl,stgen2,&index, NIL(char *)){
+	       if (LtlSetGetElt(label, (int) index)) {
+		 is_universe = 0;
+		 st_free_gen(stgen2);
+		 break;
+	       }
+	     }
+	   }
+	   if (is_universe) {
+	     fprintf(fp, "- ");
+	     continue;
+	   }
+	   /* write the value as the conjunction of the values in the
+	    * atomic proposition. for example, if the state is labeled
+	    * 'in1={R,G,B}' and 'in1={G}', we should write as
+	    * !( !(R,G,B), !(G) )
+	    * Note that it's the same as {R,G,B}^{G}={G} 
+	    */
+	   fprintf(fp, "!(");
+	   st_foreach_item(tmptbl, stgen, &index, NIL(char *)) {
+	     if (LtlSetGetElt(label, (int) index)) {
+	       Ctlsp_Formula_t *F = array_fetch(Ctlsp_Formula_t *,
+						A->labelTable,
+						(int) index);
+	       if (isFirst)
+		 isFirst = 0;
+	       else
+		 fprintf(fp, ",");
+	       if (Ctlsp_FormulaReadType(F) == Ctlsp_NOT_c) 
+		 F = Ctlsp_FormulaReadLeftChild(F);
+	       else 
+		 fprintf(fp, "!");
+	       fprintf(fp, "(%s)",	Ctlsp_FormulaReadValueName(F));
+	     }
+	   }
+	   fprintf(fp, ") ");
+	 }
+	 fprintf(fp, "   n%d", n2);
+       }
+       lsDestroy(labelList, (void (*)(lsGeneric))LtlSetFree);
+	  
+       if (sel_num > 1)
+	 sel_cnt++;
+     }
+   }
+ 
+
+   /*-------------------------------------------------------  
+    * .table state -> fair1
+    * .default 0 
+    * ------------------------------------------------------
+    */
+   if (lsLength(A->Fair) != 0) {
+     i = 1;
+     lsForEachItem(A->Fair, lsgen, FairSet) {
+       int isFirst = 1;
+       fprintf(fp, "\n.table state$AUT -> fair%d$AUT ", i++);
+       fprintf(fp, "\n.default 0\n(");
+       st_foreach_item(FairSet, stgen, &vtx, NIL(char *)) {
+	 if (isFirst)
+	   isFirst = 0;
+	 else
+	   fprintf(fp, ",");
+	 fprintf(fp, "n%d", Ltl_AutomatonVtxGetNodeIdx(vtx));
+       }
+       fprintf(fp, ")   1");
+     }
+   }else {
+     fprintf(fp, "\n.table state$AUT -> fair1$AUT ");
+     if (InitIdx == -1)
+       fprintf(fp, "\n.default 0\n!(Trap,Init)   1");
+     else
+       fprintf(fp, "\n.default 0\n!(Trap)   1");
+   }
+
+   /*-------------------------------------------------------  
+    * .end 
+    * ------------------------------------------------------
+    */
+   fprintf(fp, "\n.end\n");
+
+   /* free the name array 
+    */
+   array_free(InputNames);
+   arrayForEachItem(st_table *, Name2LabelIdx, i, tmptbl) {
+     st_free_table(tmptbl);
+   }
+   array_free(Name2LabelIdx);
+   
+   return result;
+}
+#endif
+
+      
+/**Function********************************************************************
+
+  Synopsis    [Translate the automaton to Verilog file.]
+
+  Description [The Hrc_Manager may or may not be provided. If not, the verilog
+  file generated is not accurate (all the inputs are assummed to be boolean).]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Ltl_AutomatonToVerilog(
+  FILE *fp,             
+  Ntk_Network_t *network,
+  Ltl_Automaton_t *A)     
+{
+  Var_Variable_t *inputVar;
+  array_t *InputNames = array_alloc(char *, 0);
+  array_t *Name2LabelIdx = array_alloc(st_table *, 0);
+  Ntk_Node_t *ntknode;
+  char *inputName, *formulaString, *normalString;
+  st_generator *stgen;
+  lsGen lsgen, lsgen2;
+  int i, j, is_enum, range, isFirst;
+  int sel_num, sel_cnt;
+  edge_t *edge;
+  vertex_t *vtx;
+  st_table *FairSet;
+  int InitIdx = AutomatonComputeInitState(A);
+  char InitStr[10];
+  int result = 1;
+  
+  /* The initState of the automaton */
+  if (InitIdx == -1) 
+    sprintf(InitStr, "Init");
+  else
+    sprintf(InitStr, "n%d", InitIdx);
+
+  if (network == NIL(Ntk_Network_t)) {
+    result = 0;
+    fprintf(vis_stderr, "Warning: the Verilog output is incomplete. (The current node is empty. Read in design.)\n");
+  }
+
+  /* Retrieve all the input names of the automaton into 'InputNames', And for
+   * each name, put into a hash table all the subformulae contains it 
+   */
+  AutomatonGetInputNames(A, InputNames, Name2LabelIdx);
+  sel_num = AutomatonCountSelector(A);
+  fprintf(fp, "\n// Buechi automaton: %s", A->name);
+   
+  /*-------------------------------------------------------
+   * typedef enum {Init, trap, n1, n2, ... nN} states;
+   * typedef enum {READ, GREEN, YELLOW} type_in1;
+   *-------------------------------------------------------
+   */    
+  if (InitIdx == -1)
+    fprintf(fp, "\ntypedef enum {Init,Trap");
+  else
+    fprintf(fp, "\ntypedef enum {Trap");
+  foreach_vertex(A->G, lsgen, vtx) {
+    fprintf(fp, ",n%d", Ltl_AutomatonVtxGetNodeIdx(vtx));
+  }
+  fprintf(fp, "} type_states;");
+
+  if (network != NIL(Ntk_Network_t)) {
+    arrayForEachItem(char *, InputNames, i, inputName) {
+      /* replace illegal characters in the input name string */
+      normalString = StringNormalize(inputName);
+      fprintf(fp, "\n//Input name mapping:\t %s => %s;", inputName,
+	      normalString);
+
+      ntknode = Ntk_NetworkFindNodeByName(network, inputName);
+      assert(ntknode != NIL(Ntk_Node_t));
+      inputVar = Ntk_NodeReadVariable(ntknode);
+      
+      is_enum = Var_VariableTestIsEnumerative(inputVar);
+      range = Var_VariableReadNumValues(inputVar);
+      if (is_enum) {
+	if (range>2)
+	  fprintf(fp, "\ntypedef enum {0-%d}  type_%s;", 
+		  range-1, normalString);
+      }else {
+	fprintf(fp, "\ntypedef enum {");
+	isFirst = 1;
+	for (j=0; j<range; j++) {
+	  char *vstr =
+	    Var_VariableReadSymbolicValueFromIndex(inputVar,j);
+	  if (isFirst)  {
+	    fprintf(fp, "%s ", vstr);
+	    isFirst = 0;
+	  } else 
+	    fprintf(fp, ",%s ", vstr);
+	}
+	fprintf(fp, "}  type_%s;", normalString);
+      }
+      
+      FREE(normalString);
+    }
+  }
+ 
+  /*-------------------------------------------------------    
+   * module Buechi (clock, in1, in2 ... inN, fair1, ...);
+   *-------------------------------------------------------
+   */
+  fprintf(fp, "\n//Buechi Buechi (clock");
+  for (i=0; i<array_n(InputNames); i++) {
+    inputName = array_fetch(char *, InputNames, i);
+    fprintf(fp, ",%s", inputName);
+  }
+  for (i=0; i<lsLength(A->Fair); i++) {
+    fprintf(fp, ",fair%d", i+1);
+  }
+  fprintf(fp, ");");
+  
+  fprintf(fp, "\nmodule Buechi (clock");
+  for (i=0; i<array_n(InputNames); i++) {
+    inputName = array_fetch(char *, InputNames, i);
+    normalString = StringNormalize(inputName);
+    fprintf(fp, ",%s", normalString);
+    FREE(normalString);
+  }
+  for (i=0; i<lsLength(A->Fair); i++) {
+    fprintf(fp, ",fair%d", i+1);
+  }
+  fprintf(fp, ");");
+
+  
+  /*-------------------------------------------------------
+   * input clock, in1, in2 ... inN ;
+   * output fair1, fair2 ... fairN ;
+   *-------------------------------------------------------
+   */
+  fprintf(fp, "\n\tinput clock");
+  for (i=0; i<array_n(InputNames); i++) {
+    inputName = array_fetch(char *, InputNames, i);
+    normalString = StringNormalize(inputName);
+    fprintf(fp, ", %s", normalString);
+    FREE(normalString);
+  }
+  if (lsLength(A->Fair)>0) {
+    fprintf(fp, ";\n\toutput ");
+    isFirst = 1;
+    for (i=0; i<lsLength(A->Fair); i++) {
+      if (isFirst)  {
+	fprintf(fp, "fair%d", i+1);
+	isFirst = 0;
+      } else {
+	fprintf(fp, ",fair%d", i+1);
+      }
+    }
+  }
+  fprintf(fp, ";");
+
+  
+  /*-------------------------------------------------------
+   * type_in1 wire in1;
+   * type_in2 wire in2;
+   * ...
+   * type_states reg state;
+   * wire[0:logN] sel;
+   *-------------------------------------------------------
+   */
+  if (network != NIL(Ntk_Network_t)) {
+    arrayForEachItem(char *, InputNames, i, inputName) {
+      normalString = StringNormalize(inputName);
+
+      ntknode = Ntk_NetworkFindNodeByName(network, inputName);
+      assert(ntknode != NIL(Ntk_Node_t));
+      inputVar = Ntk_NodeReadVariable(ntknode);
+      
+      is_enum = Var_VariableTestIsEnumerative(inputVar);
+      range = Var_VariableReadNumValues(inputVar);
+      
+      if (!is_enum || range > 2)
+	fprintf(fp, "\n\ttype_%s  wire  %s;", normalString,normalString);
+      FREE(normalString);
+    }
+  }
+  fprintf(fp, "\n\ttype_states reg state;");
+  if (sel_num >1) {
+    if (sel_num == 2)
+      fprintf(fp, "\n\twire sel;");
+    else
+      fprintf(fp, "\n\twire [0:%d] sel;", (int)(ceil(log(sel_num)))-1);
+  }
+  
+  /*-------------------------------------------------------
+   * assign sel = $ND( {0-N} );
+   * assign fair = (state==n1 || state==n2 || ... );
+   *-------------------------------------------------------
+   */
+  fprintf(fp, "\n\tassign sel = $ND( {0-%d} );", sel_num-1 );
+  i = 1;
+  lsForEachItem(A->Fair, lsgen, FairSet) {
+    int isFirst = 1;
+    fprintf(fp, "\n\tassign fair%d = (state==", i++);
+    st_foreach_item(FairSet, stgen, &vtx, NIL(char *)) {
+      if (isFirst)
+	isFirst = 0;
+      else
+	fprintf(fp, "|| state==");
+      fprintf(fp, "n%d", Ltl_AutomatonVtxGetNodeIdx(vtx));
+    }
+    fprintf(fp, ");");
+  }
+  
+  /*-------------------------------------------------------
+   * initial state = Init;
+   *-------------------------------------------------------
+   */
+  fprintf(fp, "\n\tinitial state = %s;", InitStr);
+
+  /*-------------------------------------------------------
+   * always @ (posedge clock) begin
+   *    case (state)
+   *-------------------------------------------------------
+   */
+  fprintf(fp, "\n\talways @ (posedge clock) begin");
+  fprintf(fp, "\n\t\tcase (state)");  
+
+  /* for each initial state n2 with label "in1=p  !in3=q...", add entry: 
+   *-------------------------------------------------------
+   *      Init:
+   *         if( sel==0 && in1==p && !in3=q ... ) 
+   *            state = n2;
+   *         else if( sel==1 && ...) 
+   *            state = n3;
+   *         else
+   *            state = Trap;
+   *------------------------------------------------------
+   */
+  if (InitIdx == -1) {
+    fprintf(fp, "\n\t\tInit:");
+    sel_cnt = 0;
+    st_foreach_item(A->Init, stgen, &vtx, NIL(char *)) {
+      int n2 = Ltl_AutomatonVtxGetNodeIdx(vtx);
+      LtlSet_t *label = LtlAutomatonVertexGetLabels(vtx);
+      
+      /* universal label (no label) on n2 */
+      if (LtlSetIsEmpty(label)) {
+	if (st_count(A->Init) == 1 || sel_num == 0)
+	  fprintf(fp,"\n\t\t\tif(1) \n\t\t\t\tstate = n%d;", n2);
+	else if (sel_cnt == 0)
+	  fprintf(fp,"\n\t\t\tif(sel==%d)\n\t\t\t\tstate = n%d;",
+		  sel_cnt++, n2);
+	else 
+	  fprintf(fp, "\n\t\t\telse if(sel==%d)\n\t\t\t\tstate = n%d;",
+		  sel_cnt++, n2);
+      }else {
+	/* there is at least one label on n2 */
+	if (st_count(A->Init) == 1 || sel_num == 0)
+	  fprintf(fp, "\n\t\t\tif(");
+	else if (sel_cnt==0)
+	  fprintf(fp, "\n\t\t\tif(sel==%d && ", sel_cnt++);
+	else 
+	  fprintf(fp, "\n\t\t\telse if(sel==%d && ", sel_cnt++);
+	
+	isFirst = 1;
+	for (i=0; i<array_n(A->labelTable); i++) {
+	  if (LtlSetGetElt(label, i)) {
+	    Ctlsp_Formula_t *F = array_fetch(Ctlsp_Formula_t *,
+					     A->labelTable, i);
+	    formulaString = Ctlsp_FormulaConvertToString(F);
+	    normalString = StringNormalize(formulaString);
+	    FREE(formulaString);
+	    
+	    if (isFirst)
+	      isFirst = 0;
+	    else
+	      fprintf(fp, " && ");
+	    
+	    fprintf(fp, "%s", normalString);
+	    FREE(normalString);
+	  }
+	}
+	fprintf(fp, ")\n\t\t\t\tstate = n%d;", n2);
+      }
+    }      
+    fprintf(fp, "\n\t\t\telse\n\t\t\t\tstate = Trap;");
+  }
+  
+  /* for each edge (n1, n2) with n2 labelled "in1=p !in3=q...", add entry: 
+   *-------------------------------------------------------     
+   *      n1:
+   *         if( sel==0 && in1==p && !in3=q ... ) 
+   *            state = n2;
+   *         else if( sel==1 && ...) 
+   *            state = n3;
+   *         else
+   *            state = Trap;
+   *-------------------------------------------------------
+   */
+  foreach_vertex(A->G, lsgen, vtx) {
+    int n1 = Ltl_AutomatonVtxGetNodeIdx(vtx);
+    int outDegree = lsLength(g_get_out_edges(vtx));
+    fprintf(fp, "\n\t\tn%d:", n1);
+    sel_cnt = 0;
+    foreach_out_edge(vtx, lsgen2, edge) {
+      int n2 = Ltl_AutomatonVtxGetNodeIdx(g_e_dest(edge));
+      LtlSet_t *label =   LtlAutomatonVertexGetLabels(g_e_dest(edge));
+	  
+      /* universal label (no label) on n2 */
+      if (LtlSetIsEmpty(label)) {
+	if (outDegree == 1 || sel_num == 0)
+	  fprintf(fp, "\n\t\t\tif(1) \n\t\t\t\tstate = n%d;", n2);
+	else if (sel_cnt == 0)
+	  fprintf(fp, "\n\t\t\tif(sel==%d) \n\t\t\t\tstate = n%d;",
+		  sel_cnt++, n2);
+	else 
+	  fprintf(fp, "\n\t\t\telse if(sel==%d)\n\t\t\t\tstate = n%d;",
+		  sel_cnt++, n2);
+      }else {  
+	/* at least 1 label on n2 */
+	if (outDegree == 1 || sel_num == 0)
+	  fprintf(fp, "\n\t\t\tif(");
+	else if (sel_cnt==0)
+	  fprintf(fp, "\n\t\t\tif(sel==%d && ", sel_cnt++);
+	else 
+	  fprintf(fp, "\n\t\t\telse if(sel==%d && ", sel_cnt++);
+	
+	isFirst = 1;
+	for (i=0; i<array_n(A->labelTableNegate); i++) {
+	  if (LtlSetGetElt(label, i)) {
+	    Ctlsp_Formula_t *F = array_fetch(Ctlsp_Formula_t *,
+					     A->labelTable, i);
+	    formulaString = Ctlsp_FormulaConvertToString(F);
+	    normalString = StringNormalize(formulaString);
+	    FREE(formulaString);
+	    
+	    if (isFirst)  isFirst = 0;
+	    else fprintf(fp, " && ");
+	    
+	    fprintf(fp, "%s", normalString);
+	    FREE(normalString);
+	  }
+	}
+	fprintf(fp, ")\n\t\t\t\tstate = n%d;", n2);
+      }
+    }      
+    fprintf(fp, "\n\t\t\telse\n\t\t\t\tstate = Trap;");
+  }
+  
+  /*-------------------------------------------------------
+   *        default: state = Trap;
+   *      endcase
+   *    end
+   * endmodule
+   *-------------------------------------------------------
+   */
+  fprintf(fp, "\n\t\tdefault: state = Trap;\n\t\tendcase\n\tend\nendmodule\n");
+  
+  /* free the name array */
+  array_free(InputNames);
+  for(i=0; i<array_n(Name2LabelIdx); i++) {
+    st_table *tmptbl = array_fetch(st_table *, Name2LabelIdx, i);
+    st_free_table(tmptbl);
+  }
+  array_free(Name2LabelIdx);
+  
+  return result;
+}
+
+      
+/**Function********************************************************************
+
+  Synopsis    [Translate the automaton to SMV file.]
+
+  Description [The Hrc_Manager may or may not be provided. If not, the blifmv
+  file generated is not complete (inputs are assummed to be boolean.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Ltl_AutomatonToSmv(
+  FILE *fp,             
+  Ntk_Network_t *network,
+  Ltl_Automaton_t *A)     
+{
+    return 1;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Return a array of all the inputnames of the automaton.]
+  
+  Description [InputNames and Name2LabelIdx are two "array_t" provided by the
+  caller. InputNames will be filled by all the labels on the automaton nodes;
+  Each item of Name2LabelIdx is a "st_table" from a label to all the related
+  formulae in A->labelTable that contains the label.]
+  
+  SideEffects []
+
+******************************************************************************/
+static void
+AutomatonGetInputNames(
+  Ltl_Automaton_t *A,
+  array_t *InputNames,
+  array_t *Name2LabelIdx)
+{
+  st_table *Visited = st_init_table(strcmp, st_strhash);
+  Ctlsp_Formula_t *F;
+  Ctlsp_FormulaType F_type;
+  long i, index, counter;
+
+  counter = 0;
+  for (i=0; i<array_n(A->labelTable); i++) {
+    /* get the positive formula string */
+    F = array_fetch(Ctlsp_Formula_t *, A->labelTable, i);
+    F_type = Ctlsp_FormulaReadType(F);
+    /* if it's not an AP (just a propositional formula), skip ... */
+    if (F_type != Ctlsp_NOT_c && F_type != Ctlsp_ID_c)
+      continue;
+    if (F_type == Ctlsp_NOT_c) 
+      F = Ctlsp_FormulaReadLeftChild(F);
+    /* put into the InputNames array */
+    if (!st_lookup(Visited, Ctlsp_FormulaReadVariableName(F),&index)){
+      st_table *tmptbl = st_init_table(st_numcmp, st_numhash);
+      st_insert(tmptbl, (char *) i, (char *)i);
+      
+      array_insert(st_table *, Name2LabelIdx, counter, tmptbl);
+      array_insert(char *, InputNames, counter,
+		   Ctlsp_FormulaReadVariableName(F));
+      
+      st_insert(Visited, Ctlsp_FormulaReadVariableName(F), (char *)counter++);
+    }else {
+      st_table *tmptbl = array_fetch(st_table *, Name2LabelIdx, index);
+      st_insert(tmptbl, (char *)i, (char *)i);
+    }
+  }
+  
+  st_free_table(Visited);
+}
+    
+/**Function********************************************************************
+
+  Synopsis    [Return the upper bound number of nondeterministic selectors.]
+  
+  Description [The automaton is nondeterministic, but the blif_mv file should
+  be deterministic. Selector (variable with random output) is used to make
+  the .table determinstic. We need to know how many outputs the Selector
+  should have. Here we take the maximum out-degree among all nodes as the
+  upper bound estimation.] 
+  
+  SideEffects []
+
+******************************************************************************/
+static int
+AutomatonCountSelector(
+  Ltl_Automaton_t *A)
+{
+  int sel_num = st_count(A->Init);
+  int local_num;
+  lsGen lsgen;
+  vertex_t *vtx;
+  
+  foreach_vertex(A->G, lsgen, vtx) {
+    local_num = lsLength(g_get_out_edges(vtx));
+    if (sel_num < local_num)
+      sel_num = local_num;
+  }
+  
+  return sel_num;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Determine if "Init" state is necessary.]
+  
+  Description [If there exists such a state 'ns', "Init" is not necessary:
+  (1) ns  is in Aut->Init
+  (2) there is a edge from ns to every state in Aut->Init (including itself)
+  In another word, ns is equivalent to "Init".
+  (3) there is no edge fron ns to states not in Aut->Init.
+
+  Return the index of the state 'ns' if exist, otherwise return -1.  ]
+  
+  SideEffects []
+
+******************************************************************************/
+static int
+AutomatonComputeInitState(
+  Ltl_Automaton_t *A)
+{
+  int initIdx = -1;
+  vertex_t *vtx, *vtx2, *s;
+  edge_t *e;
+  st_generator *stgen, *stgen2;
+  lsGen lsgen;
+
+  st_foreach_item(A->Init, stgen, &vtx, NIL(char *)) {
+    int isInit = 1;
+    /* first, compute the set of sucessors of 'vtx' */
+    lsList Img = g_get_out_edges(vtx);
+    st_table *uTable = st_init_table(st_ptrcmp, st_ptrhash);
+    lsForEachItem(Img, lsgen, e) {
+      s = g_e_dest(e);
+      st_insert(uTable,  s,  s);
+    }
+    /* then, test if it is equivalent to 'A->Init': No more, No less */
+    st_foreach_item(A->Init, stgen2, &vtx2, NIL(char *)) {
+      if (!st_is_member(uTable, vtx2)) {
+	isInit = 0;
+	st_free_gen(stgen2);
+	break;
+      }
+    }
+    if (isInit) {
+      st_foreach_item(uTable, stgen2, &vtx2, NIL(char *)) {
+	if (!st_is_member(A->Init, vtx2)) {
+	  isInit = 0;
+	  st_free_gen(stgen2);
+	  break;
+	}
+      }
+    }
+    st_free_table(uTable);
+
+    if (isInit == 1) {
+      initIdx = ((Ltl_AutomatonNode_t *)vtx->user_data)->index;
+      st_free_gen(stgen);
+      break;
+    }
+  }
+   
+  return initIdx;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Given a composite label, return a list of label (each of which
+  is a cube.]
+  
+  Description [The composite label can any combination of !, + , *.]
+    
+  SideEffects []
+
+******************************************************************************/
+/*static lsList
+AutomatonLabelGetCubes(
+  Ltl_Automaton_t *A,
+  LtlSet_t *compositeLabel,
+  Ntk_Network_t *network)
+{
+  LtlTableau_t *tableau = A->tableau;
+  int size = tableau->labelIndex;
+  LtlSet_t *tempSet, *tempSet2, *tempSet3;
+  lsList conjunctList;
+  lsList disjunctList;
+  lsList tempList, tempList2, tempList3;
+  lsGen lsgen, lsgen2;
+  int i;
+
+  if (LtlSetIsEmpty(compositeLabel)) {
+    tempList = lsCreate();
+    lsNewEnd(tempList, (lsGeneric)LtlSetNew(size), (lsHandle *)0);
+    return tempList;
+  }
+  
+  first, get a list of disjunctLists (which should be conjoin together
+    to form a cartesian product 
+   
+  conjunctList = lsCreate();
+  tempSet = LtlSetNew(size);
+  for (i=0; i<size; i++) {
+    if (LtlSetGetElt(compositeLabel, i)) {
+      if (Ctlsp_LtlFormulaIsAtomicPropositional(tableau->labelTable[i]))
+	LtlSetSetElt(tempSet, i);
+      else {
+	disjunctList = GetCubes_Aux(A, i);
+	lsNewEnd(conjunctList, (lsGeneric)disjunctList, (lsHandle *)0);
+      }
+    }
+  }
+  if (LtlSetIsEmpty(tempSet))
+    LtlSetFree(tempSet);
+  else {
+    disjunctList = lsCreate();
+    lsNewEnd(disjunctList, (lsGeneric)tempSet, (lsHandle *)0);
+    lsNewBegin(conjunctList, (lsGeneric)disjunctList, (lsHandle *)0);
+  }
+    
+
+  compute the cartesian product of the conjuncts 
+  while(lsLength(conjunctList)>1) {
+    lsList thisList;
+    lsList leftList;
+    lsList rightList;
+    
+    lsDelBegin(conjunctList, (lsGeneric *)&leftList);
+    lsDelBegin(conjunctList, (lsGeneric *)&rightList);
+     form the cartesian product of the two lists 
+    thisList = lsCreate();
+    lsForEachItem(leftList, lsgen, tempSet) {
+      lsForEachItem(rightList, lsgen2, tempSet2) {
+	tempSet3 = LtlSetNew(size);
+	LtlSetOR(tempSet3, tempSet, tempSet2);
+	
+	if (0)
+	  fprintf(vis_stdout,
+		  "tempSet = %d  tempSet2 = %d tempSet3 = %d\n",
+		  LtlSetIsEmpty(tempSet),
+		  LtlSetIsEmpty(tempSet2),
+		  LtlSetIsEmpty(tempSet3));
+	
+	 if no contradictory, retain it 
+	if (LtlSetIsContradictory(tempSet3,tableau->labelTableNegate))
+	  LtlSetFree(tempSet3);
+	else
+	  lsNewEnd(thisList, (lsGeneric)tempSet3, (lsHandle *)0);
+      }
+    }
+    lsDestroy(leftList, (void (*)(lsGeneric))LtlSetFree);
+    lsDestroy(rightList, (void (*)(lsGeneric))LtlSetFree);
+    
+    lsNewBegin(conjunctList, (lsGeneric)thisList, (lsHandle *)0);
+  }
+  
+  lsDelBegin(conjunctList, (lsGeneric *)&tempList);
+  lsDestroy(conjunctList, (void(*)(lsGeneric))0);
+
+   remove redundant minterms from 'tempList' 
+  tempList3 = lsCreate();
+  tempList2 = lsCopy(tempList, (lsGeneric(*)(lsGeneric))0);
+  lsForEachItem(tempList, lsgen, tempSet) {
+     If tempSet is a superset of other cubes, discard it 
+    int flag = 1;
+    lsForEachItem(tempList2, lsgen2, tempSet2) {
+      if (tempSet != tempSet2 && LtlSetInclude(tempSet, tempSet2)) {
+	flag = 0;
+	lsFinish(lsgen2);
+	break;
+      }
+    }
+    if (!flag) continue;
+     If tempSet is an "emptyset" (for example, comtains both
+     signal=0 and signal=1, where signal has only these two
+      values),  discard it 
+     
+    flag = 1;
+    if (network != NIL(Ntk_Network_t)) {
+      Fsm_Fsm_t *fsm = Fsm_NetworkReadOrCreateFsm(network);
+      if (fsm != NIL(Fsm_Fsm_t)) {
+	mdd_t *minterm = LtlSetModelCheckFormulae(tempSet, 
+						  A->labelTable, 
+						  fsm);
+	flag = !(mdd_is_tautology(minterm, 0));
+	mdd_free(minterm);
+      }
+    }
+    if (!flag) continue;
+     otherwise, save a copy into tempList3 
+    lsNewBegin(tempList3, (lsGeneric)LtlSetCopy(tempSet), (lsHandle *)0); 
+  }
+  lsDestroy(tempList2, (void(*)(lsGeneric))0);
+  lsDestroy(tempList, (void (*)(lsGeneric))LtlSetFree);
+  tempList = tempList3;
+
+  return tempList;
+}
+  */
+
+/**Function********************************************************************
+
+  Synopsis    [Given a index in A->tableau->labelTable, return a list of label
+  (each of which  is a cube.]
+  
+  Description [The formula A->tableau->labelTable[index] can be  any
+  combination of !, + , *.]
+    
+  SideEffects []
+
+******************************************************************************/
+static lsList
+GetCubes_Aux(
+  Ltl_Automaton_t *A,
+  int index)
+{
+  Ctlsp_Formula_t *F = A->tableau->labelTable[index];
+  int size = A->tableau->labelIndex;
+  lsList leftList;
+  lsList rightList;
+  lsList thisList =(lsList)0;
+  lsGen lsgen, lsgen2;
+  LtlSet_t *tempSet, *tempSet2, *tempSet3;
+  
+  if (Ctlsp_LtlFormulaIsAtomicPropositional(F)) {
+    thisList = lsCreate();
+    tempSet = LtlSetNew(size);
+    LtlSetSetElt(tempSet, Ctlsp_FormulaReadLabelIndex(F));
+    lsNewEnd(thisList, (lsGeneric)tempSet, (lsHandle *)0);
+  }else {
+    Ctlsp_Formula_t *F_left = Ctlsp_FormulaReadLeftChild(F);
+    Ctlsp_Formula_t *F_right = Ctlsp_FormulaReadRightChild(F);
+    
+    switch(Ctlsp_FormulaReadType(F)) {
+    case Ctlsp_OR_c:
+      leftList = GetCubes_Aux(A, Ctlsp_FormulaReadLabelIndex(F_left));
+      rightList = GetCubes_Aux(A, Ctlsp_FormulaReadLabelIndex(F_right));
+      /* merge two list together */
+      thisList = leftList;
+      lsForEachItem(rightList, lsgen, tempSet) {
+	lsNewEnd(thisList, (lsGeneric)tempSet, (lsHandle *)0);
+      }
+      lsDestroy(rightList, (void (*)(lsGeneric))0);
+      break;
+    case Ctlsp_AND_c:
+      leftList = GetCubes_Aux(A, Ctlsp_FormulaReadLabelIndex(F_left));
+      rightList = GetCubes_Aux(A, Ctlsp_FormulaReadLabelIndex(F_right));
+      /* generate the cartesian product of the two lists */
+      thisList = lsCreate();
+      lsForEachItem(leftList, lsgen, tempSet) {
+	lsForEachItem(rightList, lsgen2, tempSet2) {
+	  tempSet3 = LtlSetNew(size);
+	  LtlSetOR(tempSet3, tempSet, tempSet2);
+	  lsNewEnd(thisList, (lsGeneric)tempSet3, (lsHandle *)0);
+	}
+      }
+      lsDestroy(leftList, (void (*)(lsGeneric))LtlSetFree);
+      lsDestroy(rightList, (void (*)(lsGeneric))LtlSetFree);
+      break;
+    default:
+      assert(0);
+      break;
+    }
+  }
+  
+  return thisList;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Given a string, do the following replacement.]
+  
+  Description [
+  =   =>   ==
+  +   =>   ||
+  *   =>   &&
+  .   =>   _
+  <   =>   _
+  >   =>   _  ]
+    
+  SideEffects [The caller should free the result]
+
+******************************************************************************/
+static char *
+StringNormalize(
+  char *inputString)
+{
+  char *normalString = ALLOC(char, strlen(inputString)*2);
+  char *from = inputString;
+  char *to = normalString;
+  
+  while( *from ) {
+    switch(*from) {
+    case '=':
+      *(to++) = '=';
+      *(to) = '=';
+      break;
+    case '+':
+      *(to++) = '|';
+      *(to) = '|';
+      break;
+    case '*':
+      *(to++) = '&';
+      *(to) = '&';
+      break;
+    case '.':
+    case '<':
+    case '>':
+      *(to) = '_';
+      break;
+    default:
+      *(to) = *from;
+    }
+    from++;
+    to++;
+  }
+  *to = '\0';
+  
+  return normalString;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Create the "label" signal in blif_mv format and print out.]
+  
+  Description [Assume that the label is a propositional formula with *, +, !.
+  *
+  * For Ctlsp_ID_c/Ctlsp_NOT_c:
+  *   .table in1 n1_##_label$AUT
+  *   !(RED) 1
+  * For Ctlsp_AND_c:
+  *   .table n1_#1_label$AUT n1_#2_label$AUT n1_##_label$AUT
+  *   1 1  1
+  * For Ctlsp_OR_c:
+  *   .table n1_#1_label$AUT n1_#2_label$AUT n1_##_label$AUT
+  *   1 -  1
+  *   - 1  1
+  ]
+  
+  SideEffects []
+
+******************************************************************************/
+static void
+AutomatonVtxLabelToBlifMv(
+  FILE *fp,
+  Ltl_Automaton_t *A,
+  vertex_t *vtx)
+{
+    /* each 'compLabel' is a "propositional formulae" */
+    LtlSet_t *compositeLabel = LtlAutomatonVertexGetLabels(vtx);
+    int idx = Ltl_AutomatonVtxGetNodeIdx(vtx);
+    int size = A->tableau->labelIndex;
+    int i;
+    st_table *CreatedSignals;
+	
+    if (LtlSetIsEmpty(compositeLabel)) {
+	fprintf(fp, "\n.table n%d_label$AUT\n1\n", idx);
+	return;
+    }
+    
+    /* first, we should create the signals for each subformula */
+    CreatedSignals = st_init_table(st_ptrcmp, st_ptrhash);
+    for (i=0; i<size; i++) {
+      if (LtlSetGetElt(compositeLabel, i))
+	VtxLabelToBlifMv_Aux(fp, A, idx, i, CreatedSignals);
+    }
+    st_free_table(CreatedSignals);
+    
+    /* the label signal is the AND or all the conjuncts */
+    fprintf(fp, "\n.table ");
+    for (i=0; i<size; i++) {
+      if (LtlSetGetElt(compositeLabel, i))
+	fprintf(fp, "n%d_%d_label$AUT ", idx, i);
+    }
+    fprintf(fp, "  -> n%d_label$AUT\n.default 0\n", idx);
+    for (i=0; i<size; i++) {
+      if (LtlSetGetElt(compositeLabel, i))
+	fprintf(fp, "1 ");
+    }
+    fprintf(fp, "1\n");
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Create the "label" signal in blif_mv format and print out.]
+  
+  Description [Assume that "i" is the index in the label table]
+  
+  SideEffects []
+
+******************************************************************************/
+static void
+VtxLabelToBlifMv_Aux(
+  FILE *fp,
+  Ltl_Automaton_t *A,
+  int node_idx,
+  int index,
+  st_table *CreatedSignals)
+{
+    Ctlsp_Formula_t *F = A->tableau->labelTable[index];
+    Ctlsp_Formula_t *F_left, *F_right;
+    int l_index, r_index;
+
+    if (st_is_member(CreatedSignals, F))
+	return;
+    else
+	st_insert(CreatedSignals, F, (char *)0);
+  
+    switch(Ctlsp_FormulaReadType(F)) {
+    case Ctlsp_ID_c:
+	fprintf(fp, "\n.table %s -> n%d_%d_label$AUT\n.default 0\n%s 1",
+		(char *)Ctlsp_FormulaReadVariableName(F),
+		node_idx, index,
+		(char *)Ctlsp_FormulaReadValueName(F));
+	break;
+    case Ctlsp_NOT_c:
+	F_left = Ctlsp_FormulaReadLeftChild(F);
+	fprintf(fp, "\n.table %s -> n%d_%d_label$AUT\n.default 1\n%s 0",
+		(char *)Ctlsp_FormulaReadVariableName(F_left),
+		node_idx, index,
+		(char *)Ctlsp_FormulaReadValueName(F_left));
+	break;
+    case Ctlsp_AND_c:
+	F_left = Ctlsp_FormulaReadLeftChild(F);
+	F_right = Ctlsp_FormulaReadRightChild(F);
+	l_index = Ctlsp_FormulaReadLabelIndex(F_left);
+	r_index = Ctlsp_FormulaReadLabelIndex(F_right);
+	VtxLabelToBlifMv_Aux(fp, A, node_idx, l_index, CreatedSignals);
+	VtxLabelToBlifMv_Aux(fp, A, node_idx, r_index, CreatedSignals);
+	fprintf(fp,"\n.table n%d_%d_label$AUT n%d_%d_label$AUT -> n%d_%d_label$AUT\n.default 0\n1 1 1",
+		node_idx, l_index,
+		node_idx, r_index,
+		node_idx, index);
+	break;
+    case Ctlsp_OR_c:
+	F_left = Ctlsp_FormulaReadLeftChild(F);
+	F_right = Ctlsp_FormulaReadRightChild(F);
+	l_index = Ctlsp_FormulaReadLabelIndex(F_left);
+	r_index = Ctlsp_FormulaReadLabelIndex(F_right);
+	VtxLabelToBlifMv_Aux(fp, A, node_idx, l_index, CreatedSignals);
+	VtxLabelToBlifMv_Aux(fp, A, node_idx, r_index, CreatedSignals);
+	fprintf(fp,
+	"\n.table n%d_%d_label$AUT n%d_%d_label$AUT -> n%d_%d_label$AUT\n.default 0\n1 - 1\n- 1 1",
+		node_idx, l_index,
+		node_idx, r_index,
+		node_idx, index);
+	break;
+    default:
+	fail("unkown formula type");
+    }
+}
+    
+
+
Index: vis_dev/vis-2.3/src/ltl/ltlInt.h
===================================================================
--- vis_dev/vis-2.3/src/ltl/ltlInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/ltl/ltlInt.h	(revision 14)
@@ -0,0 +1,318 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [ltlInt.h]
+
+  PackageName [ltl]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Chao Wang<chao.wang@colorado.EDU>]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+  Revision    [$Id: ltlInt.h,v 1.26 2008/04/22 21:21:45 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _LTLINT
+#define _LTLINT
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "io.h"
+#include "ltl.h"
+#include "cmd.h"
+#include "ctlsp.h"
+#include "fsm.h"
+#include "ntk.h"
+#include "ord.h"
+#include "part.h"
+#include "mc.h"
+#include <string.h>
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+typedef struct LtlMcOption LtlMcOption_t;
+typedef struct LtlTableauEntry  LtlTableauEntry_t;
+typedef struct LtlTableauStruct LtlTableau_t;
+typedef struct LtlSetStruct  LtlSet_t;
+typedef struct LtlPairStruct LtlPair_t;
+
+
+/**Enum************************************************************************
+
+  Synopsis    [Level to which debugging of CTL formulae is performed.]
+
+******************************************************************************/
+
+typedef enum {
+  LtlMcDbgLevelNone_c,
+  LtlMcDbgLevelMin_c,
+  LtlMcDbgLevelMinVerbose_c,
+  LtlMcDbgLevelMax_c,
+  LtlMcDbgLevelInteractive_c
+} LtlMcDbgLevel;
+
+/**Enum************************************************************************
+
+  Synopsis    [Automaton->File Formats.]
+
+  Description []
+
+******************************************************************************/
+
+typedef enum {
+    Aut2File_DOT_c,
+    Aut2File_BLIFMV_c,
+    Aut2File_VERILOG_c,
+    Aut2File_ALL_c
+}Aut2FileType;
+
+/**Enum************************************************************************
+
+  Synopsis    [LTL->Automaton Translation Algorithm.]
+
+  Description []
+
+******************************************************************************/
+
+typedef enum {
+    Ltl2Aut_GPVW_c,
+    Ltl2Aut_GPVWplus_c,
+    Ltl2Aut_LTL2AUT_c,
+    Ltl2Aut_WRING_c
+} Ltl2AutAlgorithm;
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [A struct for keeping the command line options.]
+
+******************************************************************************/
+struct LtlMcOption {
+  boolean printInputs;
+  FILE *ltlFile;              /* contains the ltl formulae */
+  FILE *debugFile;
+  boolean useMore;            /* use more as pipe for debug output */
+  boolean simValue;
+  Mc_LeMethod_t leMethod;
+  Mc_DcLevel dcLevel;
+  LtlMcDbgLevel dbgLevel;
+  Mc_GSHScheduleType schedule;
+  Mc_FwdBwdAnalysis direction;
+  int lockstep;
+  Mc_VerbosityLevel verbosity;
+  int timeOutPeriod;
+
+  Ltl2AutAlgorithm algorithm; /* GPVW/GPVW+/LTL2AUT/WRING */
+  boolean booleanmin;         /* use boolean minimization to simplify cover */
+  boolean rewriting;          /* rewriting the fomula */
+  boolean prunefair;          /* prune the fairness */
+  boolean iocompatible;       /* minimization by io-compatible */
+  boolean directsim;          /* minimization by direct simulation rln */
+  boolean reversesim;         /* minimization by reverse simulation rln */
+  boolean directsimMaximize;  /* adding arcs by direct simulation rln */
+
+  int noIncrementalPartition; /* ? build the parition of MxA incrementally */
+  int noStrengthReduction;    /* ? use different decision procedures */
+                              /*   for different automaton strength */
+  int noShuffleToTop;         /* ? shuffle automaton vars to the top */
+
+  Aut2FileType outputformat;  /* write blifmv/verilog/smv/dot file as output */
+  char *outputfilename;
+};
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [A struct for holding the Tableau Rule Expansition of 1 Formula.]
+
+******************************************************************************/
+struct LtlTableauEntry {
+  Ctlsp_Formula_t  *F;        /* the formula */
+  struct alpha {              /* alpha[0].beta[0]*alpha[0].beta[1] + */
+    int B[2];                 /* alpha[1].beta[0]*alpha[1].beta[1]   */
+    int n;
+  } A[2];
+  int notF_idx;               /* negation of 'f' */
+  Ctlsp_Formula_t  *notF;
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [A struct for holding the Tableau Rule Expansition of All the
+  sub-Formulae of the given LTL Formula F and its negation.]
+
+******************************************************************************/
+struct LtlTableauStruct {
+  Ctlsp_Formula_t *F;         /* Formula in NNF */
+  Ctlsp_Formula_t *notF;      /* & its negation */
+  st_table *formulaUniqueTable;
+  st_table *untilUniqueTable;
+
+  int abIndex;                /* Alpha_Beta_Table */
+  LtlTableauEntry_t *abTable;
+  array_t *abTableNegate;     /* provide Negate method, for set operation */
+  
+  int labelIndex;             /* label table: (ID/TRUE/FALSE) */
+  Ctlsp_Formula_t **labelTable;
+  array_t *labelTableNegate;  /*provide Negate method, for set operation */
+
+  int algorithm;              /* algorithm GPVW/GPVW+/LTL2AUT/WRING */
+  int booleanmin;             /* switch: for boolean minimization */
+  int verbosity;
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [A struct for holding a set, in which each index corresponds to
+  an elementary formula.]
+
+******************************************************************************/
+struct LtlSetStruct {
+  var_set_t *e;       
+};
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [The Buechi Automaton / Quotient Graph  struct.]
+
+******************************************************************************/
+struct LtlAutomatonStruct {
+  LtlTableau_t *tableau;      /* <optional>, the tableau */
+  Ltl_Automaton_t *Q;         /* <optional>, Quotion graph */
+  st_table *SCC;              /* <optional>, SCC partitions */
+  int isQuotientGraph;
+  /* in automaton graph, Q->SCC is (component, 0) */
+  /* in quotient graph, Q->SCC is a mapping (component, Q_vtx) */
+
+  /*--below are required fields-------------------------------------------*/
+  char *name;
+  graph_t *G;
+  st_table  *Init;            /* initial states (vertices) */
+  st_table *dontcare;         /* these state can be in/out FairSets*/
+  lsList  Fair;               /* list of sets (hash tables) */
+  array_t *labelTable;        /* unique table for propositionals (labels),
+				 'node->Labes' is a var_set_t refer to it.
+				 Initially it's a Clone of
+				 'tableau->labelTable',
+				 from which it shares nothing in common */
+  array_t *labelTableNegate;  /* provide Negate method for each label item */
+  int node_idx;               /* auxilary counter in creating nodes */
+  bdd_t     *transitionRelation; /* Holds the bdd of the translation relation */
+  bdd_t     *initialStates;      /* Holds the bdd of the initial states */
+  bdd_t     *fairSets;           /* Holds the bdd of the fair states */
+  array_t   *fairSetArray;       /* Holda bdd of all fair sets.*/
+  st_table  *psNsTable;          /* Maps present state to next state*/
+  st_table  *nsPsTable;          /* Maps next state to present state*/
+};
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [The struct for a node in the Buechi Automaton / Quotient
+  graph. It's attached to each vertex (vertex->user_data).]
+
+******************************************************************************/
+struct LtlAutomatonNodeStruct { 
+  int index;
+  LtlSet_t *Labels;           /* a list of constant formulae, state labels */
+    
+  LtlSet_t *CoverSet;         /* <optional> */
+  st_table *Class;
+  mdd_t    *Encode;           /* Encode the state of automaton */
+  int      *cnfIndex;
+};
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [The struct for holding a Generic Pair (ordered).]
+
+******************************************************************************/
+struct LtlPairStruct {
+  char *First;
+  char *Second;
+};
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN Ltl_Automaton_t * LtlMcFormulaToAutomaton(Ntk_Network_t *network, Ctlsp_Formula_t *Formula, LtlMcOption_t *options, int checkSemantics);
+EXTERN void LtlFsmLoadFairness(Fsm_Fsm_t *compFsm, Fsm_Fairness_t *designFairness, int NumberOfFairSets, int *AutomatonStrength);
+EXTERN LtlMcOption_t * LtlMcOptionAlloc(void);
+EXTERN void LtlMcOptionFree(LtlMcOption_t *result);
+EXTERN Ltl_Automaton_t * LtlAutomatonGeneration(LtlTableau_t *tableau);
+EXTERN int LtlAutomatonSetIsFair(LtlTableau_t *tableau, LtlSet_t *r);
+EXTERN LtlSet_t * LtlAutomatonVertexGetLabels(vertex_t *vtx);
+EXTERN LtlSet_t * LtlSetNew(int size);
+EXTERN void LtlSetFree(LtlSet_t *set);
+EXTERN LtlSet_t * LtlSetCopy(LtlSet_t *from);
+EXTERN void LtlSetAssign(LtlSet_t *to, LtlSet_t *from);
+EXTERN int LtlSetEqual(LtlSet_t *s1, LtlSet_t *s2);
+EXTERN int LtlSetCardinality(LtlSet_t *set);
+EXTERN int LtlSetCompareCardinality(const void *p1, const void *p2);
+EXTERN int LtlSetIsContradictory(LtlSet_t *set, array_t *Negate);
+EXTERN int LtlSetInclude(LtlSet_t *large, LtlSet_t *small);
+EXTERN void LtlSetOR(LtlSet_t *to, LtlSet_t *from1, LtlSet_t *from2);
+EXTERN void LtlSetClear(LtlSet_t *set);
+EXTERN void LtlSetSetElt(LtlSet_t *set, int index);
+EXTERN void LtlSetClearElt(LtlSet_t *set, int index);
+EXTERN int LtlSetGetElt(LtlSet_t *set, int index);
+EXTERN int LtlSetIsEmpty(LtlSet_t *set);
+EXTERN LtlSet_t * LtlSetIsInList(LtlSet_t *set, lsList list);
+EXTERN LtlSet_t * LtlSetToLabelSet(LtlTableau_t *tableau, LtlSet_t *set);
+EXTERN void LtlSetPrint(LtlTableau_t *tableau, LtlSet_t *set);
+EXTERN void LtlSetPrintIndex(int length, LtlSet_t *set);
+EXTERN LtlPair_t * LtlPairNew(char *First, char *Second);
+EXTERN void LtlPairFree(LtlPair_t *pair);
+EXTERN int LtlPairHash(char *key, int modulus);
+EXTERN int LtlPairCompare(const char *key1, const char *key2);
+EXTERN void LtlPairPrint(LtlPair_t *pair);
+EXTERN void LtlCoverPrintIndex(int length, lsList cover);
+EXTERN lsList LtlCoverCompleteSum(lsList Cover, array_t *Negate);
+EXTERN LtlSet_t * LtlSetConsensus(LtlSet_t *first, LtlSet_t *second, array_t *Negate);
+EXTERN lsList LtlCoverCofactor(lsList Cover, LtlSet_t *c, array_t *Negate);
+EXTERN int LtlCoverIsTautology(lsList Cover, array_t *Negate);
+EXTERN int LtlCoverIsImpliedBy(lsList Cover, LtlSet_t *term, array_t *Negate);
+EXTERN lsList LtlCoverPrimeAndIrredundant(LtlTableau_t *tableau, lsList Cover, array_t *Negate);
+EXTERN LtlSet_t * LtlCoverGetSuperCube(lsList Cover, array_t *Negate);
+EXTERN mdd_t * LtlSetModelCheckFormulae(LtlSet_t *set, array_t *labelTable, Fsm_Fsm_t *fsm);
+EXTERN LtlTableau_t * LtlTableauGenerateTableau(Ctlsp_Formula_t *formula);
+EXTERN LtlTableau_t * LtlTableauCreate(void);
+EXTERN void LtlTableauFree(LtlTableau_t *tableau);
+EXTERN void LtlTableauPrint(FILE *fp, LtlTableau_t *tableau);
+EXTERN Ctlsp_Formula_t * LtlTableauGetUniqueXFormula(LtlTableau_t *tableau, Ctlsp_Formula_t *F);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _LTLINT */
Index: vis_dev/vis-2.3/src/ltl/ltlMinimize.c
===================================================================
--- vis_dev/vis-2.3/src/ltl/ltlMinimize.c	(revision 14)
+++ vis_dev/vis-2.3/src/ltl/ltlMinimize.c	(revision 14)
@@ -0,0 +1,2383 @@
+/**CFile***********************************************************************
+
+  FileName    [ltlMinimize.c]
+
+  PackageName [ltl]
+
+  Synopsis    [Buechi automaton minimization.]
+
+  Author      [Chao Wang<chao.wang@colorado.EDU>]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "ltlInt.h"
+
+static char rcsid[] UNUSED = "$Id: ltlMinimize.c,v 1.33 2009/04/09 02:21:13 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static lsList AutomatonPickInputCandidate(graph_t *G, vertex_t *vtx);
+static lsList AutomatonPickOutputCandidate(graph_t *G, vertex_t *vtx);
+static st_table * AutomatonVertexGetPreImg(graph_t *G, vertex_t *vtx);
+static st_table * AutomatonVertexGetImg(graph_t *G, vertex_t *vtx);
+static int AutomatonVertexHasSelfLoop(graph_t *G, vertex_t *vtx);
+static int AutomatonPfairEquivQfair(Ltl_Automaton_t *A, vertex_t *state, vertex_t *otherstate);
+static int AutomatonPfairImplyQfair(Ltl_Automaton_t *A, vertex_t *state, vertex_t *otherstate);
+static char * StTableDelete(st_table *tbl, char *item);
+static st_table * StTableAppend(st_table *tbl1, st_table *tbl2);
+static st_table * StTableRestrict(st_table *tbl1, st_table *tbl2);
+static st_table * StTableSubtract(st_table *tbl1, st_table *tbl2);
+static int StTableIsEqual(st_table *tbl1, st_table *tbl2, st_table *dontcare);
+static int StTableInclude(st_table *large, st_table *small, st_table *dontcare);
+static int StTableIsDisjoint(st_table *tbl1, st_table *tbl2, st_table *dontcare);
+static int StTableIsFair(lsList A_Fair, st_table *Class);
+static int AutomatonPartitionIsClique(graph_t *G, st_table *set);
+static st_table * AutomatonPartitionLabelLUB(st_table *set, array_t *Negate);
+static st_table * AutomatonPartitionLabelGLB(st_table *set, array_t *Negate);
+static st_table * AutomatonQuotientVertexGetClass(vertex_t *vtx);
+/*static int AutomatonVtxGetNodeIdx(vertex_t *v);*/
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Minimize the Automaton using I/O Compatiblility and Dominance.]
+
+  Description [These minimizations are based on the structural information,
+  and are less effective than simulation-based techniques. They are used for
+  pre-processing since they are faster.Also, in some cases they go beyond what
+  simulation based minimization can do.
+
+  Here we consider 3 cases: Input Compatible, Output Compatible and Dominance.]
+
+  SideEffects [The automaton might be changed. In that case return 1.]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Ltl_AutomatonMinimizeByIOCompatible(
+  Ltl_Automaton_t *A,
+  int verbosity)
+{
+  int changed = 0;
+  int flag;
+  lsList states, incand, outcand;
+  lsGen lsgen, lsgen2, lsgen3;
+  vertex_t *state, *otherstate, *s;
+  LtlSet_t *set, *set2;
+  st_table *FairSet, *tbl0, *tbl1, *tbl2, *tbl3, *tbl4;
+  st_generator *stgen;
+
+
+  /* We go through all the states in A->G, and check for Input-Compatible,
+   * Output-Compatible, and Dominance
+   */
+  states = lsCopy(g_get_vertices(A->G), (lsGeneric (*)(lsGeneric)) NULL);
+  lsForEachItem (states, lsgen, state) {
+    int localchanged = 0;
+    /* Compute the Image adn PreImg of 'state' for later use */
+    tbl0 = AutomatonVertexGetPreImg(A->G, state);
+    tbl1 = AutomatonVertexGetImg(A->G, state);
+
+    /* ############################
+     *  Check for Input Compatible
+     * ############################*/
+    incand = AutomatonPickInputCandidate(A->G, state);
+    lsForEachItem (incand, lsgen2, otherstate) {
+      /* p is 'state', q is 'otherstate' */
+      /* p != q */
+      if (state == otherstate) continue;
+      /* L(p) = L(q) */
+      set = LtlAutomatonVertexGetLabels(state);
+      set2 = LtlAutomatonVertexGetLabels(otherstate);
+      if (!LtlSetEqual(set, set2)) continue;
+      /* p \in Q0  <-> q \in Q0 */
+      if (st_is_member(A->Init, state) !=
+	  st_is_member(A->Init, otherstate))
+	continue;
+      /* p \in F   <-> q \in F */
+      if (!AutomatonPfairEquivQfair(A, state, otherstate))  continue;
+      /* preImg(p) - {p,q} == preImg(q) - {p,q} */
+      tbl2 = AutomatonVertexGetPreImg(A->G, otherstate);
+      tbl3 = st_init_table(st_ptrcmp, st_ptrhash);
+      st_insert(tbl3, state, state);
+      st_insert(tbl3 , otherstate, otherstate);
+      flag = StTableIsEqual(tbl0, tbl2, tbl3);
+      st_free_table(tbl2);
+      st_free_table(tbl3);
+      if (!flag)	      continue;
+      /* q \in [delta(p)+delta(q)] <-> p \in [delta(p)+delta(q)] */
+      tbl2 = AutomatonVertexGetImg(A->G, otherstate);
+      if ( (st_is_member(tbl1,state) ||
+	    st_is_member(tbl2,state))
+	   !=
+	   (st_is_member(tbl1,otherstate) ||
+	    st_is_member(tbl2,otherstate)) ) {
+	      st_free_table(tbl2);
+	      continue;
+      }
+
+      /* ######## (state, otherstate) :: input compatible #######
+       * we merge the two state by deleting 'state'
+       * Notice that now we have the following data available:
+       * tbl0 = PreImg(state),
+       * tbl1 = Img(state),
+       * tbl2 = Img(otherstate)
+       */
+
+      /* Update intial states */
+      StTableDelete(A->Init, (char *)state);
+      /* Add edges (otherstate, s), here s is the sucessor of 'state' */
+      st_foreach_item(tbl1, stgen, &s, NIL(char *)) {
+	if (s != state && !st_is_member(tbl2, s))
+	  g_add_edge(otherstate, s);
+      }
+      /* Remove 'otherstate' also if state isn't in dontcare */
+      if (!st_is_member(A->dontcare, state))
+	StTableDelete(A->dontcare, (char *)otherstate);
+      /* Remove 'state' from dontcare (if applicable) */
+      StTableDelete(A->dontcare, (char *)state);
+      /* Update fairness conditions */
+      lsForEachItem (A->Fair, lsgen3, FairSet) {
+	StTableDelete(FairSet, (char *)state);
+      }
+      /* Remove 'state' from the automaton */
+      g_delete_vertex(state, Ltl_AutomatonNodeFree, (void(*)(gGeneric))0);
+
+      st_free_table(tbl2);
+      /* terminate iteration on incand list */
+      changed = localchanged = 1;
+
+      lsFinish(lsgen2);
+      break;
+    }
+    lsDestroy(incand, (void (*)(lsGeneric)) 0);
+    if (localchanged) {
+      st_free_table(tbl0);
+      st_free_table(tbl1);
+      continue;
+    }
+
+
+    /* ############################
+     * Check for Output Compatible
+     * ############################
+     */
+    outcand = AutomatonPickOutputCandidate(A->G, state);
+    lsForEachItem (outcand, lsgen2, otherstate) {
+      /* p != q */
+      if (state == otherstate) continue;
+      /* L(p) = L(q) */
+      set = LtlAutomatonVertexGetLabels(state);
+      set2 = LtlAutomatonVertexGetLabels(otherstate);
+      if (!LtlSetEqual(set, set2)) continue;
+      /* p \in F   <-> q \in F */
+      if (!AutomatonPfairEquivQfair(A, state, otherstate)) continue;
+      /* Img(p) - {p,q} == Img(q) - {p,q} */
+      tbl2 = AutomatonVertexGetImg(A->G, otherstate);
+      tbl3 = st_init_table(st_ptrcmp, st_ptrhash);
+      st_insert(tbl3, state, state);
+      st_insert(tbl3, otherstate, otherstate);
+      flag = StTableIsEqual(tbl1, tbl2, tbl3);
+      st_free_table(tbl3);
+      if (!flag) {
+	st_free_table(tbl2);
+	continue;
+      }
+      /* q \in delta(p) + p \in delta(p)] <->
+       * q \in delta(q) + p \in delta(q)]
+       */
+      flag = 0;
+      if ( (st_is_member(tbl1, state) ||
+	    st_is_member(tbl1, otherstate))
+	   !=
+	   (st_is_member(tbl2, state) ||
+	    st_is_member(tbl2, otherstate)) ) {
+	st_free_table(tbl2);
+	continue;
+      }
+
+      /* ######## (state, otherstate) :: output compatible #######
+       * Merge the two state by deleting 'state'
+       * Notice that now we have the following data:
+       *     tbl0 = PreImg(state)
+       *     tbl1 = Img(state)
+       *     tbl2 = Img(otherstate)
+       */
+      tbl3 = AutomatonVertexGetPreImg(A->G, otherstate);
+
+      /* Add 'otherstate to Q0 if 'state' is in it */
+      if (st_is_member(A->Init, state)) {
+	st_delete(A->Init, &state, NIL(char *));
+	if(!st_is_member(A->Init, otherstate))
+	  st_insert(A->Init, otherstate, otherstate);
+      }
+      /* Add edge (s, otherstate) where 's' is in PreImg(state) */
+      st_foreach_item(tbl0, stgen, &s, NIL(char *)) {
+	if (s != state && s != otherstate &&
+	    !st_is_member(tbl3, s))
+	  g_add_edge(s, otherstate);
+      }
+      /* Add edge (otherstate, otherstate) if there exist (state, state) or
+       * (state, otherstate)
+       */
+      if (st_is_member(tbl1, otherstate) ||
+	  st_is_member(tbl1, state))
+	if (!st_is_member(tbl2, otherstate))
+	  g_add_edge(otherstate, otherstate);
+      /* Update don't care conditions. If 'state' isn't in dontcare, also
+       * remove 'otherstate'
+       */
+      if (!st_is_member(A->dontcare, state)) {
+	StTableDelete(A->dontcare, (char *)otherstate);
+      }
+      StTableDelete(A->dontcare, (char *)state);
+      /* Remove 'state' from FairSets */
+      lsForEachItem (A->Fair, lsgen3, FairSet) {
+	StTableDelete(FairSet, (char *)state);
+      }
+      /* Remove 'state' from the automaton */
+      g_delete_vertex(state, Ltl_AutomatonNodeFree, (void(*)(gGeneric))0);
+
+      st_free_table(tbl2);
+      st_free_table(tbl3);
+      /* terminate iteration on incand list */
+      changed = localchanged = 1;
+
+      lsFinish(lsgen2);
+      break;
+    }
+    if (localchanged) {
+      lsDestroy(outcand, (void (*)(lsGeneric)) 0);
+      st_free_table(tbl0);
+      st_free_table(tbl1);
+      continue;
+    }
+
+
+    /* ############################
+     * Check for Dominance
+     * ############################
+     * We already have the lsList 'outcand'
+     */
+    lsForEachItem (outcand, lsgen2, otherstate) {
+      /* p != q */
+      if (state == otherstate) continue;
+      /* L(p) \leq L(q) (set(Lp) > set(Lq) */
+      set = LtlAutomatonVertexGetLabels(state);
+      set2 = LtlAutomatonVertexGetLabels(otherstate);
+      if (!LtlSetInclude(set, set2)) continue;
+      /* p \in Q0 -> q \in Q0 */
+      if (st_is_member(A->Init, state) &&
+	  !st_is_member(A->Init, otherstate))
+	continue;
+      /* p \in F   -> q \in F */
+      if (!AutomatonPfairImplyQfair(A, state, otherstate)) continue;
+      /* Img(p) is less than Img(q) */
+      tbl2 = AutomatonVertexGetImg(A->G, otherstate);
+      flag = StTableInclude(tbl2, tbl1, NIL(st_table));
+      /* p is in Img(p)  ->  q is in Img(q) */
+      if (flag) {
+	flag = (!st_is_member(tbl1, state) ||
+		st_is_member(tbl2, otherstate));
+      }
+      st_free_table(tbl2);
+      if (!flag)       continue;
+      /* PreImg(p)-{p} \leq PreImg(q)-{p} */
+      tbl3 =  AutomatonVertexGetPreImg(A->G, otherstate);
+      tbl4 = st_init_table(st_ptrcmp, st_ptrhash);
+      st_insert(tbl4, state, state);
+      flag = StTableInclude(tbl3, tbl0, tbl4);
+      st_free_table(tbl4);
+      st_free_table(tbl3);
+      if (!flag)       continue;
+
+      /* ######## otherstate dominates state #######
+       * Remove 'state'
+       * Notice that now we have the following data:
+       *     tbl0 = PreImg(state)
+       *     tbl1 = Img(state)
+       */
+      /* Remove 'state' from Initial states */
+      StTableDelete(A->Init, (char *)state);
+      /* Remove 'otherstate' if 'state' isn't in dontcare */
+      if (!st_is_member(A->dontcare, state)) {
+	StTableDelete(A->dontcare, (char *)otherstate);
+      }
+      StTableDelete(A->dontcare, (char *)state);
+      /* Remove 'state' from FairSets */
+      lsForEachItem (A->Fair, lsgen3, FairSet) {
+	StTableDelete(FairSet, (char *)state);
+      }
+      /* Remove 'state' from the automaton */
+      g_delete_vertex(state, Ltl_AutomatonNodeFree, (void(*)(gGeneric))0);
+
+      /* terminate iteration on incand list */
+      changed = localchanged = 1;
+
+      lsFinish(lsgen2);
+      break;
+    }
+    lsDestroy(outcand, (void (*)(lsGeneric)) 0);
+
+
+    st_free_table(tbl0);
+    st_free_table(tbl1);
+
+  }
+  lsDestroy(states, (void (*)(lsGeneric)) 0);
+
+
+  return changed;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Minimize the Automaton using Direct Simulation.]
+
+  Description [Compute direct-simulation relation, and minimize the automaton
+  according to the following two cases:
+  1) Remove p if (p,q) is a Bi-simulation relation (Bis-aa)
+  2) Remove edges from their common predecessors to p if p is direct
+  simulated by q.]
+
+  SideEffects [The automaton might be changed. if so, return 1.]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Ltl_AutomatonMinimizeByDirectSimulation(
+  Ltl_Automaton_t *A,
+  int verbosity)
+{
+  int changed = 0;
+  int flag = 0;
+
+  lsList states, otherstates, list, queue;
+  lsGen lsgen, lsgen1;
+
+  edge_t *e;
+  vertex_t *state, *otherstate;
+  vertex_t *p, *q, *s, *t, *u, *v;
+  LtlSet_t *set, *set2;
+
+  st_table *FairSet, *tbl0, *tbl1, *tbl2, *tbl3;
+  st_table *simul, *enqueued;
+  st_generator *stgen, *stgen1, *stgen2;
+
+  LtlPair_t *pair, *pair2;
+
+
+  /* store the simulation-relation in hash tables and queue list */
+  simul = st_init_table(LtlPairCompare, LtlPairHash);
+  enqueued = st_init_table(LtlPairCompare, LtlPairHash);
+  queue = lsCreate();
+
+  /*######################################
+   * Initialize sim rln to all pairs (p,q)
+   *######################################
+   */
+  states = lsCopy(g_get_vertices(A->G), (lsGeneric (*)(lsGeneric)) NULL);
+  otherstates = lsCopy(states, (lsGeneric (*)(lsGeneric)) NULL);
+  lsForEachItem (states, lsgen, state) {
+    lsForEachItem (otherstates, lsgen1, otherstate) {
+      /* p != q */
+      if (state == otherstate) continue;
+      /* L(p) \leq L(q) (set(Lp) > set(Lq) */
+      set = LtlAutomatonVertexGetLabels(state);
+      set2 = LtlAutomatonVertexGetLabels(otherstate);
+      if (!LtlSetInclude(set, set2)) continue;
+      /* p \in F   -> q \in F */
+      if (!AutomatonPfairImplyQfair(A, state, otherstate))   continue;
+
+      /* put (state, otherstate) into simul-relation (candidate) */
+      pair = LtlPairNew((char *)state, (char *)otherstate);
+      st_insert(simul, pair, pair);
+      st_insert(enqueued, pair, pair);
+      lsNewEnd(queue, (lsGeneric)pair, NIL(lsHandle));
+    }
+  }
+  lsDestroy(states, (void (*)(lsGeneric)) NULL);
+  lsDestroy(otherstates, (void (*)(lsGeneric)) NULL);
+
+
+  /*######################################
+   * Compute the "Greatest Fixpoint"
+   *######################################
+   */
+  while (lsDelBegin(queue, &pair) != LS_NOMORE) {
+    st_delete(enqueued, &pair, NIL(char *));
+    p = (vertex_t *)pair->First;
+    q = (vertex_t *)pair->Second;
+
+    /* Check for each 's' in Img(p), if there exists a 't' in Img(q) such
+     * that (s, t) is in simulation relation candidate list
+     */
+    tbl0 = AutomatonVertexGetImg(A->G, p);
+    tbl1 = AutomatonVertexGetImg(A->G, q);
+    st_foreach_item(tbl0, stgen, &s, NIL(char *)) {
+      flag = 0;
+      st_foreach_item(tbl1, stgen1, &t, NIL(char *)) {
+	flag = (s==t);
+	if (flag) {
+	  st_free_gen(stgen1);
+	  break;
+	}
+	pair2 = LtlPairNew((char *)s, (char *)t);
+	flag = st_is_member(simul, pair2);
+	LtlPairFree(pair2);
+	if (flag) {
+	  st_free_gen(stgen1);
+	  break;
+	}
+      }
+      if (!flag)  {
+	st_free_gen(stgen);
+	break;
+      }
+    }
+    st_free_table(tbl0);
+    st_free_table(tbl1);
+    if (flag) continue;
+
+    /*  (p, q) is not a simulation relation */
+    st_delete(simul, &pair, &pair);
+    LtlPairFree(pair);
+
+    /* Enqueue perturbed pairs */
+    tbl2 = AutomatonVertexGetPreImg(A->G, p);
+    tbl3 = AutomatonVertexGetPreImg(A->G, q);
+    st_foreach_item(tbl2, stgen1, &u, NIL(char *)) {
+      st_foreach_item(tbl3, stgen2, &v, NIL(char *)) {
+	pair2 = LtlPairNew((char *)u, (char *)v);
+	if (st_lookup(simul, pair2, &pair)) {
+	  if (!st_is_member(enqueued, pair2)) {
+	    st_insert(enqueued, pair, pair);
+	    lsNewEnd(queue, (lsGeneric)pair, NIL(lsHandle));
+	  }
+	}
+	LtlPairFree(pair2);
+      }
+    }
+    st_free_table(tbl2);
+    st_free_table(tbl3);
+
+  }
+  lsDestroy(queue, (void (*)(lsGeneric))0);
+  st_free_table(enqueued);
+
+
+  /*######################################
+   * Simplify by Bi-Sim equivalent states
+   *######################################
+   */
+  /* to store removed states */
+  tbl1 = st_init_table(st_ptrcmp, st_ptrhash);
+  /* so that we can modify 'simul' within for loop */
+  tbl0 = st_copy(simul);
+  st_foreach_item (tbl0, stgen, &pair, NIL(char *)) {
+    p = (vertex_t *)pair->First;
+    q = (vertex_t *)pair->Second;
+    /* make sure neither has been removed */
+    if (st_is_member(tbl1, p) || st_is_member(tbl1, q))
+      continue;
+    /* make sure it is Bi-simulation by testing the other direction */
+    pair2 = LtlPairNew((char *)q, (char *)p);
+    flag = st_lookup(simul, pair2, &pair);
+    LtlPairFree(pair2);
+    if (!flag) continue;
+
+    /*#### Direct BI-SIMULATION equivalent states####*/
+    /* Theorem applies */
+    /* remove its swap: (q, p) from simul-rln */
+    st_delete(simul, &pair, &pair);
+    LtlPairFree(pair);
+    /* Remove p, and connect its predecessors to q */
+    tbl2 = AutomatonVertexGetPreImg(A->G, p);
+    tbl3 = AutomatonVertexGetPreImg(A->G, q);
+    st_foreach_item(tbl2, stgen1, &s, NIL(char *)) {
+      if (s == p) continue;
+      if (!st_is_member(tbl3, (char *)s))
+	g_add_edge(s, q);
+    }
+    st_free_table(tbl2);
+    st_free_table(tbl3);
+    /* Update the fair sets */
+    lsForEachItem (A->Fair, lsgen, FairSet) {
+      StTableDelete(FairSet, (char *)p);
+    }
+    /* If 'p' is in Q0, Remove 'p' and put 'q' in Q0 */
+    if (st_is_member(A->Init, p)) {
+      st_delete(A->Init, &p, NIL(char *));
+      if (!st_is_member(A->Init, q))
+	st_insert(A->Init, q, q);
+    }
+    /* Remove 'p' from dontcare (if it's in it ) */
+    StTableDelete(A->dontcare, (char *)p);
+
+    /* Remove 'p' from the automaton */
+    st_insert(tbl1, p, p);
+    g_delete_vertex(p, Ltl_AutomatonNodeFree, (void(*)(gGeneric))0);
+    changed = 1;
+  }
+  st_free_table(tbl0);
+
+
+  /*######################################
+   * Remove arcs to direct-simulated states
+   *######################################
+   */
+  /* so that we can modify simul with the for loop */
+  tbl0 = st_copy(simul);
+  st_foreach_item (tbl0, stgen, &pair, NIL(char *)) {
+    /* 'p' is simulated by 'q' */
+    p = (vertex_t *)pair->First;
+    q = (vertex_t *)pair->Second;
+    /* Make sure neither hasn't been removed yet */
+    if (st_is_member(tbl1, p) || st_is_member(tbl1, q))
+      continue;
+
+    /*#### p is direct-simulated by q####*/
+    /* Theorem applies */
+    /* Drop arcs from their common predecessors to p */
+    tbl3 = AutomatonVertexGetPreImg(A->G, q);
+    list = lsCopy(g_get_in_edges(p), (lsGeneric (*)(lsGeneric)) NULL);
+    lsForEachItem (list, lsgen,  e) {
+      if (!st_is_member(tbl3, g_e_source(e)))  continue;
+      g_delete_edge(e, (void (*)(gGeneric))0);
+      changed = 1;
+    }
+    lsDestroy(list, (void (*)(lsGeneric)) 0);
+    st_free_table(tbl3);
+    /* Remove 'p' from Q0 if 'q' is in Q0 */
+    if (st_is_member(A->Init, q)) {
+      StTableDelete(A->Init, (char *)p);
+      changed = 1;
+    }
+
+  }
+  st_free_table (tbl0);
+
+  st_free_table (tbl1);
+
+  st_foreach_item(simul, stgen, &pair, NIL(char *)) {
+    LtlPairFree(pair);
+  }
+  st_free_table (simul);
+
+  return changed;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Mark trivial SCCs as Fair states]
+
+  Description [Mark trivial SCCs as Fair states]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Ltl_AutomatonAddFairStates(
+  Ltl_Automaton_t *A)
+{
+
+  long isFair;
+
+  lsGen lsgen1;
+
+  st_generator *stgen, *stgen2;
+  st_table *FairSet, *Class;
+
+  Ltl_AutomatonComputeSCC(A, 1);
+  if (A->Q) {
+    Ltl_AutomatonFree((gGeneric) A->Q);
+    A->Q = NIL(Ltl_Automaton_t);
+  }
+  A->Q = Ltl_AutomatonCreateQuotient(A, A->SCC);
+  /*
+    Mark trivial SCCs as Fair states
+   */
+  st_foreach_item(A->SCC, stgen, &Class, &isFair) {
+    vertex_t *state;
+
+    if (isFair == 2) { /* trivial SCC */
+      lsForEachItem (A->Fair, lsgen1, FairSet) {
+	st_foreach_item(Class, stgen2, &state, NIL(char *)) {
+	  if (!st_is_member(FairSet, state)) {
+	    if (st_is_member(A->dontcare, state)){
+	      StTableDelete(A->dontcare, (char *)state);
+	    }
+	    st_insert(FairSet, state, state);
+	  }
+	}
+      }
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Maximize the Automaton using Direct Simulation.]
+
+  Description [Compute direct-simulation relation, and minimize the automaton
+  according to the following two cases:
+  1) Remove p if (p,q) is a Bi-simulation relation (Bis-aa)
+  2) Remove edges from their common predecessors to p if p is direct
+  simulated by q.]
+
+  SideEffects [The automaton might be changed. if so, return 1.]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Ltl_AutomatonMaximizeByDirectSimulation(
+  Ltl_Automaton_t *A,
+  int verbosity)
+{
+  int changed = 0;
+  int flag = 0;
+
+  lsList states, otherstates, queue;
+  lsGen lsgen, lsgen1;
+
+  vertex_t *state, *otherstate;
+  vertex_t *p, *q, *s, *t, *u, *v;
+  LtlSet_t *set, *set2;
+
+  st_table *tbl0, *tbl1, *tbl2, *tbl3;
+  st_table *simul, *enqueued;
+  st_generator *stgen, *stgen1, *stgen2;
+
+  LtlPair_t *pair, *pair2;
+
+  /*
+    Ltl_AutomatonAddFairStates(A);
+  */
+  /* store the simulation-relation in hash tables and queue list */
+  simul = st_init_table(LtlPairCompare, LtlPairHash);
+  enqueued = st_init_table(LtlPairCompare, LtlPairHash);
+  queue = lsCreate();
+
+  /*######################################
+   * Initialize sim rln to all pairs (p,q)
+   *######################################
+   */
+  states = lsCopy(g_get_vertices(A->G), (lsGeneric (*)(lsGeneric)) NULL);
+  otherstates = lsCopy(states, (lsGeneric (*)(lsGeneric)) NULL);
+  lsForEachItem (states, lsgen, state) {
+    lsForEachItem (otherstates, lsgen1, otherstate) {
+      /* p != q */
+      if (state == otherstate) continue;
+      /* L(p) \leq L(q) (set(Lp) > set(Lq) */
+      set = LtlAutomatonVertexGetLabels(state);
+      set2 = LtlAutomatonVertexGetLabels(otherstate);
+      if (!LtlSetInclude(set, set2)) continue;
+      /* p \in F   -> q \in F */
+      if (!AutomatonPfairImplyQfair(A, state, otherstate))   continue;
+
+      /* put (state, otherstate) into simul-relation (candidate) */
+      pair = LtlPairNew((char *)state, (char *)otherstate);
+      st_insert(simul, pair, pair);
+      st_insert(enqueued, pair, pair);
+      lsNewEnd(queue, (lsGeneric)pair, NIL(lsHandle));
+    }
+  }
+  lsDestroy(states, (void (*)(lsGeneric)) NULL);
+  lsDestroy(otherstates, (void (*)(lsGeneric)) NULL);
+
+
+  /*######################################
+   * Compute the "Greatest Fixpoint"
+   *######################################
+   */
+  while (lsDelBegin(queue, &pair) != LS_NOMORE) {
+    st_delete(enqueued, &pair, NIL(char *));
+    p = (vertex_t *)pair->First;
+    q = (vertex_t *)pair->Second;
+
+    /* Check for each 's' in Img(p), if there exists a 't' in Img(q) such
+     * that (s, t) is in simulation relation candidate list
+     */
+    tbl0 = AutomatonVertexGetImg(A->G, p);
+    tbl1 = AutomatonVertexGetImg(A->G, q);
+    st_foreach_item(tbl0, stgen, &s, NIL(char *)) {
+      flag = 0;
+      st_foreach_item(tbl1, stgen1, &t, NIL(char *)) {
+	flag = (s==t);
+	if (flag) {
+	  st_free_gen(stgen1);
+	  break;
+	}
+	pair2 = LtlPairNew((char *)s, (char *)t);
+	flag = st_is_member(simul, pair2);
+	LtlPairFree(pair2);
+	if (flag) {
+	  st_free_gen(stgen1);
+	  break;
+	}
+      }
+      if (!flag)  {
+	st_free_gen(stgen);
+	break;
+      }
+    }
+    st_free_table(tbl0);
+    st_free_table(tbl1);
+    if (flag) continue;
+
+    /*  (p, q) is not a simulation relation */
+    st_delete(simul, &pair, &pair);
+    LtlPairFree(pair);
+
+    /* Enqueue perturbed pairs */
+    tbl2 = AutomatonVertexGetPreImg(A->G, p);
+    tbl3 = AutomatonVertexGetPreImg(A->G, q);
+    st_foreach_item(tbl2, stgen1, &u, NIL(char *)) {
+      st_foreach_item(tbl3, stgen2, &v, NIL(char *)) {
+	pair2 = LtlPairNew((char *)u, (char *)v);
+	if (st_lookup(simul, pair2, &pair)) {
+	  if (!st_is_member(enqueued, pair2)) {
+	    st_insert(enqueued, pair, pair);
+	    lsNewEnd(queue, (lsGeneric)pair, NIL(lsHandle));
+	  }
+	}
+	LtlPairFree(pair2);
+      }
+    }
+    st_free_table(tbl2);
+    st_free_table(tbl3);
+
+  }
+  lsDestroy(queue, (void (*)(lsGeneric))0);
+  st_free_table(enqueued);
+
+
+  /*######################################
+   * Add arcs to direct-simulated states
+   *######################################
+   */
+
+  /* so that we can modify simul with the for-loop */
+  tbl0 = st_copy(simul);
+  st_foreach_item (tbl0, stgen, &pair, NIL(char *)) {
+    /* 'p' is simulated by 'q' */
+    p = (vertex_t *)pair->First;
+    q = (vertex_t *)pair->Second;
+    /*
+      Add arcs from the predecessors of q to p
+     */
+    tbl2 = AutomatonVertexGetPreImg(A->G, p);
+    tbl3 = AutomatonVertexGetPreImg(A->G, q);
+    st_foreach_item(tbl3, stgen1, &s, NIL(char *)) {
+      if (!st_is_member(tbl2, s)){
+	g_add_edge(s, p);
+	changed = 1;
+      }
+    }
+    st_free_table(tbl2);
+    st_free_table(tbl3);
+  }
+  st_free_table (tbl0);
+
+  st_foreach_item(simul, stgen, &pair, NIL(char *)) {
+    LtlPairFree(pair);
+  }
+  st_free_table (simul);
+
+  return changed;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Minimize the Automaton using Reverse Simulation.]
+
+  Description [Compute Reverse-Simulation relation, and minimize the automaton
+  according to the following 2 cases:
+  1) remove p if (p,q) is a Bi-Simulation relation
+  2) remove edges from p to their common sucessors if p is reverse simulated
+  by q.]
+
+  SideEffects [The automaton might be changed. if so, return 1.]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Ltl_AutomatonMinimizeByReverseSimulation(
+  Ltl_Automaton_t *A,
+  int verbosity)
+{
+  int changed = 0;
+  int flag = 0;
+
+  lsList states, otherstates, list, queue;
+  lsGen lsgen, lsgen1;
+
+  edge_t *e;
+  vertex_t *state, *otherstate;
+  vertex_t *p, *q, *s, *t, *u, *v;
+  LtlSet_t *set, *set2;
+
+  st_table *FairSet, *tbl0, *tbl1, *tbl2, *tbl3;
+  st_table *simul, *enqueued;
+  st_generator *stgen, *stgen1, *stgen2;
+
+  LtlPair_t *pair, *pair2;
+
+
+  /* store the simulation-relation in hash tables and queue list */
+  simul = st_init_table(LtlPairCompare, LtlPairHash);
+  enqueued = st_init_table(LtlPairCompare, LtlPairHash);
+  queue = lsCreate();
+
+  /*######################################
+   * Initialize sim rln to all pairs (p,q)
+   *######################################
+   */
+  states = lsCopy(g_get_vertices(A->G), (lsGeneric (*)(lsGeneric)) NULL);
+  otherstates = lsCopy(states, (lsGeneric (*)(lsGeneric)) NULL);
+  lsForEachItem (states, lsgen, state) {
+    lsForEachItem (otherstates, lsgen1, otherstate) {
+      /* p != q */
+      if (state == otherstate) continue;
+      /* L(p) <= L(q), in other words, (set(Lp) >= set(Lq) */
+      set = LtlAutomatonVertexGetLabels(state);
+      set2 = LtlAutomatonVertexGetLabels(otherstate);
+      if (!LtlSetInclude(set, set2))  continue;
+      /* p is in Q0  ->  q is in Q0 */
+      if (st_is_member(A->Init, state) &&
+	  !st_is_member(A->Init, otherstate))
+	continue;
+      /* p is in F   ->  q is in F */
+      if (!AutomatonPfairImplyQfair(A, state, otherstate)) continue;
+
+      /* put (state, otherstate) into simul-relation */
+      pair = LtlPairNew((char *)state, (char *)otherstate);
+      st_insert(simul, pair, pair);
+      st_insert(enqueued, pair, pair);
+      lsNewEnd(queue, (lsGeneric)pair, NIL(lsHandle));
+    }
+  }
+  lsDestroy(states, (void (*)(lsGeneric)) NULL);
+  lsDestroy(otherstates, (void (*)(lsGeneric)) NULL);
+
+
+  /*######################################
+   * Compute the "Greatest Fixpoint"
+   *######################################
+   */
+  while (lsDelBegin(queue, &pair) != LS_NOMORE) {
+    st_delete(enqueued, &pair, NIL(char *));
+    p = (vertex_t *)pair->First;
+    q = (vertex_t *)pair->Second;
+
+    /* For each 's' in Img(p), there must exists a 't' Img(q) such that
+     * (s, t) is also a reverse simulation pair
+     */
+    tbl0 = AutomatonVertexGetPreImg(A->G, p);
+    tbl1 = AutomatonVertexGetPreImg(A->G, q);
+    st_foreach_item(tbl0, stgen, &s, NIL(char *)) {
+      flag = 0;
+      st_foreach_item(tbl1, stgen1, &t, NIL(char *)) {
+	flag = (s==t);
+	if (flag) {
+	  st_free_gen(stgen1);
+	  break;
+	}
+	pair2 = LtlPairNew((char *)s, (char *)t);
+	flag = st_is_member(simul, pair2);
+	LtlPairFree(pair2);
+	if (flag) {
+	  st_free_gen(stgen1);
+	  break;
+	}
+      }
+      if (!flag) {
+	st_free_gen(stgen);
+	break;
+      }
+    }
+    st_free_table(tbl0);
+    st_free_table(tbl1);
+
+    if (flag) continue;
+
+    /* (p, q) is not a simulation relation */
+    st_delete(simul, &pair, &pair);
+    LtlPairFree(pair);
+
+    /* Enqueue perturbed pairs */
+    tbl2 = AutomatonVertexGetImg(A->G, p);
+    tbl3 = AutomatonVertexGetImg(A->G, q);
+    st_foreach_item(tbl2, stgen1, &u, NIL(char *)) {
+      st_foreach_item(tbl3, stgen2, &v, NIL(char *)) {
+	pair2 = LtlPairNew((char *)u, (char *)v);
+	if (st_lookup(simul, pair2, &pair))
+	  if(!st_is_member(enqueued, pair2)) {
+	    st_insert(enqueued, pair, pair);
+	    lsNewEnd(queue, (lsGeneric)pair, NIL(lsHandle));
+	  }
+	LtlPairFree(pair2);
+      }
+    }
+    st_free_table(tbl2);
+    st_free_table(tbl3);
+  }
+  lsDestroy(queue, (void (*)(lsGeneric))0);
+  st_free_table(enqueued);
+
+
+  /*######################################
+   * Simplify by Bi-Sim equivalent states
+   *######################################
+   */
+  /* to store removed states */
+  tbl1 = st_init_table(st_ptrcmp, st_ptrhash);
+  /* so that we can modify simul with the for loop */
+  tbl0 = st_copy(simul);
+  st_foreach_item (tbl0, stgen, &pair, NIL(char *)) {
+    p = (vertex_t *)pair->First;
+    q = (vertex_t *)pair->Second;
+    /* Make sure neither has been removed */
+    if (st_is_member(tbl1, p) || st_is_member(tbl1, q))
+      continue;
+    /* Make sure it is Bi-simulation by checking the other direction*/
+    pair2 = LtlPairNew((char *)q, (char *)p);
+    flag = st_lookup(simul, pair2, &pair);
+    LtlPairFree(pair2);
+    if (!flag) continue;
+
+    /*#### Direct BI-SIMULATION equivalent states####*/
+    /* Theorem applies */
+    /* Remove its swap: (q, p) from simul-rln */
+    st_delete(simul, &pair, &pair);
+    LtlPairFree(pair);
+    /* Remove 'p' and connect 'q' to all its successors */
+    tbl2 = AutomatonVertexGetImg(A->G, p);
+    tbl3 = AutomatonVertexGetImg(A->G, q);
+    st_foreach_item(tbl2, stgen1, &s, NIL(char *)) {
+      if (s == p) continue;
+      if (!st_is_member(tbl3, s))
+	g_add_edge(q, s);
+    }
+    st_free_table(tbl2);
+    st_free_table(tbl3);
+    /* Update the fairsets (remove 'p') */
+    lsForEachItem (A->Fair, lsgen, FairSet) {
+      StTableDelete(FairSet, (char *)p);
+    }
+    /* Remove 'p' from Q0 */
+    StTableDelete(A->Init, (char *)p);
+    /* Remove 'p' form dontcare if it's in it */
+    StTableDelete(A->dontcare, (char *)p);
+
+    /* Remove 'p' from the automaton */
+    st_insert(tbl1, p, p);
+    g_delete_vertex(p, Ltl_AutomatonNodeFree, (void(*)(gGeneric))0);
+    changed = 1;
+  }
+  st_free_table(tbl0);
+
+
+  /*######################################
+   * Remove arcs from Reverse-simulated states
+   *#####################################*/
+  /* so that we can modify simul with the for loop */
+  tbl0 = st_copy(simul);
+  st_foreach_item (tbl0, stgen, &pair, NIL(char *)) {
+    /* 'p' is simulated by 'q' */
+    p = (vertex_t *)pair->First;
+    q = (vertex_t *)pair->Second;
+    /* Make sure that neither has been removed */
+    if (st_is_member(tbl1, p) || st_is_member(tbl1, q))
+      continue;
+
+    /*#### p is reverse-simulated by q####*/
+    /* Theorem applies */
+    /* Drop arcs from 'p' to their common successors */
+    tbl3 = AutomatonVertexGetImg(A->G, q);
+    list = lsCopy(g_get_out_edges(p), (lsGeneric (*)(lsGeneric)) NULL);
+    lsForEachItem (list, lsgen,  e) {
+      if (!st_is_member(tbl3, g_e_dest(e)))  continue;
+      g_delete_edge(e, (void (*)(gGeneric))0);
+      changed = 1;
+    }
+    lsDestroy(list, (void (*)(lsGeneric)) 0);
+    st_free_table(tbl3);
+  }
+  st_free_table (tbl0);
+
+  st_free_table (tbl1);
+
+  st_foreach_item(simul, stgen, &pair, NIL(char *)) {
+    LtlPairFree(pair);
+  }
+  st_free_table (simul);
+
+  return changed;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Remove states that cannot reach any fair SCC and perform other
+  simplifications (simplify fair sets).]
+
+  Description [We consider the following cases concerning fair SCCs:
+  1. Remove redundant transitions from predecessors of universal states (a
+  state with TRUE label and a self-loop, and it belongs to all fair sets.)
+  2. Remove all states that can not reach any fair SCC
+  3. Remove duplicate fair set and Shrink the fair sets
+  ]
+
+  SideEffects [The automaton might be changed, in which case return 1. Also,
+  the A->SCC and A->Q are RE-computed.]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Ltl_AutomatonMinimizeByPrune(
+  Ltl_Automaton_t *A,
+  int verbosity)
+{
+  st_generator *stgen, *stgen1, *stgen2;
+  st_table *FairSet, *otherset, *Class, *scc, *rest;
+  st_table *tbl, *tbl1, *tbl2;
+  lsList states, list;
+  lsGen lsgen, lsgen1;
+  vertex_t *state, *s, *greatest, *qstate;
+  edge_t *e;
+  long isFair;
+  int flag, totalnum, procnum;
+
+  /* Eliminate redundant edges  from the predecessors of universal states.
+   * (A universal state is a state labeled 'TRUE' with a self-loop, and it
+   * should belong to all FairSets)
+   */
+  states = lsCopy(g_get_vertices(A->G), (lsGeneric (*)(lsGeneric)) NULL);
+  lsForEachItem (states, lsgen, state) {
+    /* label = TRUE */
+    if (LtlSetCardinality(LtlAutomatonVertexGetLabels(state)) != 0)
+      continue;
+    /* self-loop */
+    if (!AutomatonVertexHasSelfLoop(A->G, state)) continue;
+    /* blongs to all fairSet */
+    flag = 1;
+    lsForEachItem (A->Fair, lsgen1, FairSet) {
+      if (!st_is_member(FairSet, state)) {
+	flag = 0;
+	lsFinish(lsgen1);
+	break;
+      }
+    }
+    if (!flag)  continue;
+    /* We can apply the theorem: Remove edges from its predecessors to
+     * other siblings
+     */
+    tbl = AutomatonVertexGetPreImg(A->G, state);
+    st_foreach_item(tbl, stgen, &s, NIL(char *)) {
+      if (s == state) continue;
+      list = lsCopy(g_get_out_edges(s), (lsGeneric (*)(lsGeneric))0);
+      lsForEachItem(list, lsgen1, e) {
+	if (g_e_dest(e) != state)
+	  g_delete_edge(e, (void (*)(gGeneric))0);
+      }
+      lsDestroy(list, (void (*)(lsGeneric))0);
+    }
+    st_free_table(tbl);
+  }
+
+
+  /*2) Compute all the SCCs, and build the SCC-quotient graph
+   * every time before pruning, we need to re-compute the SCC graph
+   */
+  Ltl_AutomatonComputeSCC(A, 1);
+  if (A->Q) {
+    Ltl_AutomatonFree((gGeneric) A->Q);
+    A->Q = NIL(Ltl_Automaton_t);
+  }
+  A->Q = Ltl_AutomatonCreateQuotient(A, A->SCC);
+
+  /* Mark those states without loop going through as "don't care states" */
+  st_foreach_item(A->SCC, stgen, &Class, &isFair) {
+    if (isFair == 2)
+      StTableAppend(A->dontcare, Class);
+  }
+
+  /* Restrict automaton to those states that can reach a fair SCC
+   * There are two cases: (a) with fairness    (b) without fairness
+   */
+  lsFirstItem(A->Q->Fair, &FairSet, NIL(lsHandle));
+  if (lsLength(A->Fair) > 0) {
+    /* (a) */
+    tbl = st_init_table(st_ptrcmp, st_ptrhash);
+    /* Find states that are on fair cycles */
+    st_foreach_item(FairSet, stgen, &qstate, NIL(char *)) {
+      Class = AutomatonQuotientVertexGetClass(qstate);
+      StTableAppend(tbl, Class);
+    }
+    /* Shrink fair sets in A->Fair */
+    lsForEachItem (A->Fair, lsgen, FairSet) {
+      StTableRestrict(FairSet, tbl);
+    }
+    /* Find states that can reach fair cycles */
+    tbl1 = tbl;
+    tbl = g_EF(A->G, tbl);
+    st_free_table(tbl1);
+    /* Remove the rest part of A->G  */
+    StTableRestrict(A->Init, tbl);
+    StTableRestrict(A->dontcare, tbl);
+    lsForEachItem (states, lsgen, state) {
+      if (!st_is_member(tbl, state))
+	g_delete_vertex(state, Ltl_AutomatonNodeFree, (void(*)(gGeneric))0);
+    }
+  }else {
+    /* (b) */
+    /* Find all the reachable state */
+    tbl = g_reachable(A->G, A->Init);
+    /* Remove the rest part of A->G  */
+    StTableRestrict(A->Init, tbl);
+    StTableRestrict(A->dontcare, tbl);
+    lsForEachItem (states, lsgen, state) {
+      if (!st_is_member(tbl, state))
+	g_delete_vertex(state, Ltl_AutomatonNodeFree, (void(*)(gGeneric))0);
+    }
+  }
+  /* Clean up the Quotient graph */
+  st_foreach_item(A->SCC, stgen, &Class, &isFair) {
+    StTableRestrict(Class, tbl);
+  }
+  st_free_table(tbl);
+
+
+  /* 3. Remove duplicate FairSet */
+  /* Discard duplicate fair sets and fair sets including all states. Here we
+   * also restrict fair sets by analyzing each SCC. If within an SCC, one fair
+   * set dominates another, it can be restricted to the dominated one. As a
+   * special case: if an SCC does not intersect all fair sets, its states are
+   * removed from all fair sets.
+   */
+  totalnum = lsLength(A->Fair);
+  procnum = 0;
+  while(lsDelBegin(A->Fair, &FairSet) != LS_NOMORE) {
+    /* Remove this FairSet if it includes all states in the SCC */
+    if (st_count(FairSet) == lsLength(g_get_vertices(A->G))) {
+      st_free_table(FairSet);
+      totalnum--;
+    }else {
+      /* After restricted to the SCC: if fair set2 is contained in set1,
+       * shrink set1 to set2 (remove (set1-set2) from set1
+       */
+      st_foreach_item(A->SCC, stgen, &scc, &isFair) {
+	lsForEachItem(A->Fair, lsgen, otherset) {
+	  tbl1 = st_copy(scc);
+	  tbl2 = st_copy(scc);
+	  StTableRestrict(tbl1, FairSet);
+	  StTableRestrict(tbl2, otherset);
+	  if (StTableInclude(tbl1, tbl2, NIL(st_table))) {
+	    /* tbl1 <= (tbl1 - tbl2) */
+	    StTableSubtract(tbl1, tbl2);
+	    StTableSubtract(FairSet, tbl1);
+	  }
+	  st_free_table(tbl1);
+	  st_free_table(tbl2);
+	}
+      }
+      /* Remove the fair set if another fair set is contained in it */
+      flag = 1;
+      lsForEachItem(A->Fair, lsgen, otherset) {
+	if (StTableInclude(FairSet,otherset,NIL(st_table))) {
+	  flag = 0;
+	  lsFinish(lsgen);
+	  break;
+	}
+      }
+      if (!flag) {
+	st_free_table(FairSet);
+	totalnum--;
+      }else
+	lsNewEnd(A->Fair, (lsGeneric) FairSet, NIL(lsHandle));
+    }
+    procnum++;
+    if (procnum > totalnum)  break;
+  }
+
+  /* 4. GLB reduction */
+  /* If an SCC is a clique, and there is a state 's' whose label exactly matches
+   * the GLB of all the labels of the clique, we can remove 's' from every fair
+   * set such that it contains at least another state of the SCC besides 's'
+   */
+  st_foreach_item(A->SCC, stgen, &Class, &isFair) {
+    /* 1-state SCC won't work */
+    if (st_count(Class) <= 1) continue;
+    /* must be a clique */
+    if (!AutomatonPartitionIsClique(A->G, Class)) continue;
+    tbl = AutomatonPartitionLabelGLB(Class, A->labelTableNegate);
+    if (!tbl) continue;
+    rest = st_copy(Class);
+    StTableSubtract(rest, tbl);
+    lsForEachItem(A->Fair, lsgen, FairSet) {
+      if (StTableInclude(FairSet, tbl, NIL(st_table)) &&
+	  !StTableIsDisjoint(FairSet, rest, NIL(st_table)))
+	/* we apply the theorem here */
+	StTableSubtract(FairSet, tbl);
+    }
+    st_free_table(rest);
+    st_free_table(tbl);
+  }
+
+  /* 5. LUB reduction */
+  /* If an SCC contains a state 's' that simulates all the other states in the
+   * same SCC (both forward and backward), then all states of the SCC except
+   * 's' can be removed from all fair sets. The following code checks for a
+   * special case of this theorem
+   */
+  st_foreach_item(A->SCC, stgen, &Class, &isFair) {
+    vertex_t *qstate;
+    st_lookup(A->Q->SCC, Class, &qstate);
+    /* 1-state SCC won't work */
+    if (st_count(Class) <= 1)   continue;
+    tbl = AutomatonPartitionLabelLUB(Class, A->labelTableNegate);
+    if (!tbl)   continue;
+    st_foreach_item(tbl, stgen1, &greatest, NIL(char *)) {
+      /* that state should have a self-loop */
+      if (!AutomatonVertexHasSelfLoop(A->G, greatest)) continue;
+      /* that state should be initial if the SCC contains initial states */
+      if (st_is_member(A->Q->Init, qstate) &&
+	  !st_is_member(A->Init, greatest))
+	continue;
+      /* that state should belong to FairSet if the SCC intersect it */
+      flag = 1;
+      lsForEachItem(A->Fair, lsgen, FairSet) {
+	if (!st_is_member(FairSet, greatest) &&
+	    !StTableIsDisjoint(FairSet,Class,NIL(st_table))){
+	  flag = 0;
+	  lsFinish(lsgen);
+	  break;
+	}
+      }
+      if (!flag)  continue;
+      /* Every state outside of the SCC with a transition into the SCC
+       * should also have a transition to that state
+       */
+      tbl1 = st_init_table(st_ptrcmp, st_ptrhash);
+      st_foreach_item(Class, stgen2, &state, NIL(char *)) {
+	tbl2 = AutomatonVertexGetPreImg(A->G, state);
+	StTableAppend(tbl1, tbl2);
+	st_free_table(tbl2);
+      }
+      tbl2 = AutomatonVertexGetPreImg(A->G, greatest);
+      flag = StTableInclude(tbl2, tbl1, Class);
+      st_free_table(tbl2);
+      st_free_table(tbl1);
+      if (!flag) continue;
+
+      /* we now apply the theorem */
+      tbl1 = st_copy(Class);
+      if (st_is_member(tbl1, greatest))
+	st_delete(tbl1, &greatest, NIL(char *));
+      lsForEachItem(A->Fair, lsgen, FairSet) {
+	StTableSubtract(FairSet, tbl1);
+      }
+      st_free_table(tbl1);
+    }
+    st_free_table(tbl);
+  }
+
+
+  lsDestroy(states, (void (*)(lsGeneric))0);
+
+  return 1;
+}
+
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compute the SCCs of the Automaton.]
+
+  Description [Traverse the entire reachable graph of the automaton, and
+  put all the SCCs in a hash table.
+
+  If force=1, the existing partition (A->SCC) is freed and the new partition
+  is computed.
+  If force=0, the partition is computed only if A->SCC=null.]
+
+  SideEffects [A->SCC is assigned the new partition.]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Ltl_AutomatonComputeSCC(
+  Ltl_Automaton_t *A,
+  int force)
+{
+  st_generator *stgen;
+  st_table *component;
+
+  /* compute A->SCC if not exist */
+  if (!force && A->SCC)
+    return;
+
+  if (force && A->SCC) {
+    st_foreach_item(A->SCC, stgen, &component, NIL(char *)) {
+      st_free_table(component);
+    }
+    st_free_table(A->SCC);
+  }
+
+  A->SCC = g_SCC(A->G, A->Init);
+
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return 1 if if the automaton is 'WEAK']
+
+  Description [The definition of WEAK: For each fair SCC in the automaton,
+  every fairset F contains all its states.
+
+  A special case: If there is no fairness constraint at all, it's WEAK.]
+
+  SideEffects [Compute the SCCs and Quotient graph(A->SCC,A->Q) if not exist.]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Ltl_AutomatonIsWeak(
+  Ltl_Automaton_t *A)
+{
+  int weak;
+  long isFair;
+  st_generator *stgen;
+  st_table *scc, *FairSet;
+  lsGen lsgen;
+
+  /* A SCC without fairness constraint is WEAK */
+  if (lsLength(A->Fair) == 0)
+    return 1;
+
+  /* compute the partition(A->SCC) and Quotient graph(A->Q) if not exist */
+  if (!A->SCC)
+    Ltl_AutomatonComputeSCC(A,0);
+  if (!A->Q)
+    A->Q = Ltl_AutomatonCreateQuotient(A, A->SCC);
+
+  /* weak: for each SCC,
+   * either it's included in all FairSets
+   * or it intersects none of them
+   */
+  weak = 1;
+  st_foreach_item(A->SCC, stgen, &scc, &isFair) {
+    int flag = 0;
+    /* intersect none of them ? */
+    lsForEachItem (A->Fair, lsgen, FairSet) {
+      if (!StTableIsDisjoint(FairSet, scc, NIL(st_table))) {
+	lsFinish(lsgen);
+	flag = 1;
+	break;
+      }
+    }
+    if (!flag) continue;
+
+    /* included in all of them ? */
+    lsForEachItem (A->Fair, lsgen, FairSet) {
+      if (!StTableInclude(FairSet, scc, NIL(st_table))) {
+	weak = 0;
+	lsFinish(lsgen);
+	break;
+      }
+    }
+
+    if (!weak) {
+      st_free_gen(stgen);
+      break;
+    }
+  }
+
+  return weak;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return the strength of the automaton.]
+
+  Description [0 -terminal  1 -weak  2 -strong.]
+
+  SideEffects [Compute the parition and quotient graph if not exist.]
+
+  SeeAlso     []
+
+******************************************************************************/
+Mc_AutStrength_t
+Ltl_AutomatonGetStrength(
+  Ltl_Automaton_t *A)
+{
+  Mc_AutStrength_t result;
+  vertex_t *qstate, *state, *state2;
+  st_generator *stgen, *stgen1, *stgen2;
+  st_table *tbl, *FairSet, *scc;
+  lsList cover;
+  lsGen lsgen;
+
+  /* Every time we need to re-compute the partition(A->SCC) and
+   * the Quotient graph(A->Q)
+   */
+  Ltl_AutomatonComputeSCC(A, 1);
+  if (A->Q) {
+    Ltl_AutomatonFree((gGeneric) A->Q);
+    A->Q = NIL(Ltl_Automaton_t);
+  }
+  A->Q = Ltl_AutomatonCreateQuotient(A, A->SCC);
+
+  /* is it strong ? */
+  if (!Ltl_AutomatonIsWeak(A))
+    return Mc_Aut_Strong_c /*2*/;
+
+  /* it's terminal (0) if all the weak SCCs are COMPLETE and FINAL.*/
+  result = Mc_Aut_Terminal_c;
+  st_foreach_item(A->SCC, stgen, &scc, NIL(char *)) {
+    int disjoint_flag = 1;
+    int final_flag = 1;
+    int complete_flag = 1;
+
+    /* if it does not intersect any fair set, we don't care about it */
+    if (lsLength(A->Fair) == 0)
+      disjoint_flag = 0;
+    else {
+      lsForEachItem(A->Fair, lsgen, FairSet) {
+	if (!StTableIsDisjoint(FairSet, scc, NIL(st_table))) {
+	  disjoint_flag = 0;
+	  lsFinish(lsgen);
+	  break;
+	}
+      }
+    }
+    if (disjoint_flag) continue;
+
+    /* FINAL:
+     * it shouldn't be trivial, and shouldn't have edge to other sccs
+     */
+    st_lookup(A->Q->SCC, scc, &qstate);
+    tbl = AutomatonVertexGetImg(A->Q->G, qstate);
+    final_flag = (st_count(tbl) == 1 && st_is_member(tbl, qstate));
+    st_free_table(tbl);
+    if (!final_flag) {
+      st_free_gen(stgen);
+      result = Mc_Aut_Weak_c;  /* weak */
+      break;
+    }
+
+    /* COMPLETE:
+     * for each state in the SCC: the union of the labels in all
+     * its successors is tautology
+     */
+    st_foreach_item(scc, stgen1, &state, NIL(char *)) {
+      tbl = AutomatonVertexGetImg(A->G, state);
+      cover = lsCreate();
+      st_foreach_item(tbl, stgen2, &state2, NIL(char *)) {
+	lsNewEnd(cover, (lsGeneric)LtlAutomatonVertexGetLabels(state2),
+		 NIL(lsHandle));
+      }
+      st_free_table(tbl);
+      complete_flag = LtlCoverIsTautology(cover, A->labelTableNegate);
+      lsDestroy(cover, (void (*)(lsGeneric))0);
+      if (!complete_flag) {
+	st_free_gen(stgen1);
+	break;
+      }
+    }
+    if (!complete_flag) {
+      st_free_gen(stgen);
+      result = Mc_Aut_Weak_c;  /* weak */
+      break;
+    }
+  }
+
+  /* Weak = 1;  Terminal = 0 */
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return the Quotient graph for the given partition.]
+
+  Description [The Quotient graph is represented as an automaton Q:
+
+  Q->SCC : partition component  TO  vertex in Q graph hash table
+  Q->Init: initial vertices in Q graph
+  Q->Fair: only 1 FairSet in it, which contains the Q vertices corresponding
+	   to the fair components
+  Q->G   : The actual graph_t
+
+  Each Q vertex is associated with an automaton node:
+  node->index:  the index # of the Q vertex
+  node->Class:  the partition component associated with this vertex.
+
+  NOTICE: the Quotient graph is NOT a DAG, non-trivial SCCs have self-loops.]
+
+
+  SideEffects [A->SCC is updated with the following information:
+  if (key) is a trivial SCC (obviously non-fair), (value)=2;
+  if (key) is a non-trivial non-fair SCC, (value) = 0;
+  if (key) is a fair SCC, (value)=1;
+  otherwise, (value)=1;
+  The result should be freed by the caller.]
+
+  SeeAlso     []
+
+******************************************************************************/
+Ltl_Automaton_t *
+Ltl_AutomatonCreateQuotient(
+  Ltl_Automaton_t *A,
+  st_table *partition)
+{
+  long isFair;
+  int flag;
+  st_generator *stgen, *stgen1;
+  st_table *Class, *FairSet;
+  lsGen lsgen;
+
+  st_table *Avtx2Qvtx, *Class2Qvtx, *EdgeUtable;
+  Ltl_Automaton_t *Q;
+  Ltl_AutomatonNode_t *node;
+  vertex_t *q, *p;
+  edge_t *e;
+  LtlPair_t *pair;
+
+  /* create the Q graph as a Automaton */
+  Q = Ltl_AutomatonCreate();
+  Q->isQuotientGraph = 1;
+
+  /*### for each class, add vtx in Q->G ###*/
+  /* hash tables : (vtx in A, vtx in Q), (class_st_table, vtx in Q) */
+  Avtx2Qvtx = st_init_table(st_ptrcmp, st_ptrhash);
+  Class2Qvtx = st_init_table(st_ptrcmp, st_ptrhash);
+  st_foreach_item(partition, stgen, &Class, NIL(char *)) {
+    /* add 'q' in Q->G */
+    q = g_add_vertex(Q->G);
+    node = Ltl_AutomatonNodeCreate(Q);
+    node->Class = Class;
+    q->user_data = (gGeneric) node;
+    st_insert(Class2Qvtx, Class, q);
+    /* hash table (A_vtx -> Q_vtx) */
+    flag = 0;
+    st_foreach_item(Class, stgen1, &p, NIL(char *)) {
+      st_insert(Avtx2Qvtx, p, q);
+      if (st_is_member(A->Init, p))
+	flag = 1;
+    }
+    /* if any state in class is in A->Init, put class into Q->Init */
+    if (flag)
+      st_insert(Q->Init, q, q);
+  }
+
+
+  /*### for each (class, class2), add edges ###*/
+  /* edge unique table in Q graph, key = (class, class2) */
+  EdgeUtable = st_init_table(LtlPairCompare, LtlPairHash);
+  pair = LtlPairNew(0,0);
+  foreach_edge(A->G, lsgen, e) {
+    if (!st_lookup(Avtx2Qvtx, g_e_source(e), &pair->First))
+      continue;
+    if (!st_lookup(Avtx2Qvtx, g_e_dest(e),   &pair->Second))
+      continue;
+    /* only consider reachable states in A->G */
+    if (!st_is_member(EdgeUtable, pair)) {
+      LtlPair_t *tmpPair = LtlPairNew(pair->First, pair->Second);
+      st_insert(EdgeUtable, tmpPair, tmpPair);
+      g_add_edge((vertex_t *)pair->First, (vertex_t *)pair->Second);
+    }
+  }
+
+  /*### put fair sccs into the only FairSet ###*/
+  /* isFair = 1 (fair SCC); isFair = 0 (non-trivial non-fair SCC);
+   * isFair = 2 (dontcare: trivial SCC, obviously non-fair)*/
+  FairSet = st_init_table(st_ptrcmp, st_ptrhash);
+  st_foreach_item(partition, stgen, &Class, &isFair) {
+    st_insert(partition, Class, (char *)0);
+
+    /* it should be a nontrivial scc (size >1 or have self-loop) */
+    if (st_count(Class)==1) {
+      st_lookup(Class2Qvtx, Class, &pair->First);
+      st_lookup(Class2Qvtx, Class, &pair->Second);
+      if (!st_is_member(EdgeUtable, pair)) {
+	/*trivial scc (1 state without self-loop) */
+	st_insert(partition, Class, (char *)2);
+	continue;
+      }
+    }
+    /* for non trivial SCC, check if it intersect all FairSets */
+    if (!StTableIsFair(A->Fair, Class)) continue;
+    /* it's a "fair SCC" */
+    st_insert(partition, Class, (char *)1);
+
+    st_lookup(Class2Qvtx, Class, &pair->First);
+    st_insert(FairSet, pair->First, pair->First);
+  }
+  lsNewEnd(Q->Fair, (lsGeneric) FairSet, (lsHandle *) 0);
+
+  /* free */
+  LtlPairFree(pair);
+  st_foreach_item(EdgeUtable, stgen, &pair, NIL(char *)) {
+    LtlPairFree(pair);
+  }
+  st_free_table(EdgeUtable);
+
+  st_free_table(Avtx2Qvtx);
+  /*  st_free_table(Class2Qvtx); */
+  Q->SCC = Class2Qvtx;
+
+  return Q;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return the node index associated with the given vertex.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+Ltl_AutomatonVtxGetNodeIdx(
+  vertex_t *v)
+{
+  Ltl_AutomatonNode_t *node = (Ltl_AutomatonNode_t *) v->user_data;
+  return node->index;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return the automaton node label set associated with the vertex.]
+
+  SideEffects [The result is owned by the node, and should not be freed.]
+
+******************************************************************************/
+LtlSet_t *
+LtlAutomatonVertexGetLabels(
+  vertex_t *vtx)
+{
+  Ltl_AutomatonNode_t *node = (Ltl_AutomatonNode_t *) vtx->user_data;
+  return node->Labels;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Return the input-compatible candidates.]
+
+  SideEffects [Result should be freed by the caller.]
+
+******************************************************************************/
+static lsList
+AutomatonPickInputCandidate(
+  graph_t *G,
+  vertex_t *vtx)
+{
+  st_table *uTable;
+  lsList candi, preImg;
+  lsGen lsgen, lsgen2;
+  edge_t *e, *e2;
+  vertex_t *s, *t;
+  int size;
+
+  preImg = g_get_in_edges(vtx); /* shouldn't be freed */
+  size = lsLength(preImg);
+
+  /* No predecessor */
+  if (size == 0) {
+    return  lsCopy(g_get_vertices(G), (lsGeneric (*)(lsGeneric)) NULL);
+  }
+  /* The only predecessor is itself */
+  if (size == 1) {
+    lsFirstItem(preImg, &e, NIL(lsHandle));
+    if (g_e_source(e) == vtx) {          /* all the vertices in G */
+      return  lsCopy(g_get_vertices(G), (lsGeneric (*)(lsGeneric)) NULL);
+    }
+  }
+  /* Has predecessor(s) other than itself */
+  uTable = st_init_table(st_ptrcmp, st_ptrhash);
+  candi = lsCreate();
+  lsForEachItem (preImg, lsgen,  e) {
+    s = g_e_source(e);
+    foreach_out_edge(s, lsgen2, e2) {
+      t = g_e_dest(e2);
+      if (t != vtx) {
+	if(!st_insert(uTable,  t,  t))
+	  lsNewEnd(candi, (lsGeneric) t, NIL(lsHandle));
+      }
+    }
+    if (size == 1) {
+      if (!st_insert(uTable, s, s))
+	lsNewEnd(candi, (lsGeneric)s, NIL(lsHandle));
+    }
+  }
+  st_free_table(uTable);
+
+  return candi;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return the output-compatible candidates.]
+
+  SideEffects [Result should be freed by the caller.]
+
+******************************************************************************/
+static lsList
+AutomatonPickOutputCandidate(
+  graph_t *G,
+  vertex_t *vtx)
+{
+  st_table *uTable;
+  lsList candi, Img;
+  lsGen lsgen, lsgen2;
+  edge_t *e, *e2;
+  vertex_t *s, *t;
+  int size;
+
+  Img = g_get_out_edges(vtx);
+  size = lsLength(Img);
+
+  /* No successor */
+  if (size == 0) {
+    return  lsCopy(g_get_vertices(G), (lsGeneric (*)(lsGeneric)) NULL);
+  }
+  /* The only successor is itself */
+  if (size == 1) {
+    lsFirstItem(Img, &e, NIL(lsHandle));
+    if (g_e_dest(e) == vtx) {
+      return  lsCopy(g_get_vertices(G), (lsGeneric (*)(lsGeneric)) NULL);
+    }
+  }
+  /* Has successor(s) other than itself */
+  uTable = st_init_table(st_ptrcmp, st_ptrhash);
+  candi = lsCreate();
+  lsForEachItem(Img, lsgen, e) {
+    s = g_e_dest(e);
+    foreach_in_edge(s, lsgen2, e2) {
+      t = g_e_source(e2);
+      if (t != vtx) {
+	if(!st_insert(uTable,  t,  t))
+	  lsNewEnd(candi, (lsGeneric) t, NIL(lsHandle));
+      }
+    }
+    if (size == 1) {
+      if(!st_insert(uTable, s, s))
+	lsNewEnd(candi, (lsGeneric)s, NIL(lsHandle));
+    }
+  }
+  st_free_table(uTable);
+
+  return candi;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Return the pre-image of the given vertex in the hash table.]
+
+  SideEffects [Result should be freed by the caller.]
+
+******************************************************************************/
+static st_table *
+AutomatonVertexGetPreImg(
+  graph_t *G,
+  vertex_t *vtx)
+{
+  lsList preImg;
+  lsGen lsgen;
+  edge_t *e;
+  vertex_t *s;
+  st_table *uTable;
+
+  preImg = g_get_in_edges(vtx);
+
+  uTable = st_init_table(st_ptrcmp, st_ptrhash);
+  lsForEachItem(preImg, lsgen,  e) {
+    s = g_e_source(e);
+    st_insert(uTable,  s,  s);
+  }
+
+  return uTable;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return the image of the given vertex in the hash table.]
+
+  SideEffects [Result should be freed by the caller.]
+
+******************************************************************************/
+static st_table *
+AutomatonVertexGetImg(
+  graph_t *G,
+  vertex_t *vtx)
+{
+  lsList Img;
+  lsGen lsgen;
+  edge_t *e;
+  vertex_t *s;
+  st_table *uTable;
+
+  Img = g_get_out_edges(vtx);
+
+  uTable = st_init_table(st_ptrcmp, st_ptrhash);
+  lsForEachItem(Img, lsgen, e) {
+    s = g_e_dest(e);
+    st_insert(uTable,  s,  s);
+  }
+
+  return uTable;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return 1 iff the given vertex has a self-loop.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+AutomatonVertexHasSelfLoop(
+  graph_t *G,
+  vertex_t *vtx)
+{
+  lsList Img;
+  lsGen lsgen;
+  edge_t *e;
+  int flag = 0;
+
+  Img = g_get_out_edges(vtx);
+
+  lsForEachItem(Img, lsgen, e) {
+    if (g_e_dest(e) == vtx) {
+      flag = 1;
+      lsFinish(lsgen);
+      break;
+    }
+  }
+
+  return flag;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return 1 iff the following statement in the automaton holds:
+  For each fair set,  both states are in it or none of them]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+AutomatonPfairEquivQfair(
+  Ltl_Automaton_t *A,
+  vertex_t *state,
+  vertex_t *otherstate)
+{
+  int  flag = 1;
+  st_table *FairSet;
+  lsGen lsgen;
+
+  lsForEachItem (A->Fair, lsgen, FairSet) {
+    if (st_is_member(FairSet, state) !=
+	st_is_member(FairSet, otherstate)) {
+      flag = 0;
+      lsFinish(lsgen);
+      break;
+    }
+  }
+
+  return flag;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return 1 iff the following statement in the automaton holds:
+  For each fair set,  if 'state' is in it, 'otherstate' must also in it.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+AutomatonPfairImplyQfair(
+  Ltl_Automaton_t *A,
+  vertex_t *state,
+  vertex_t *otherstate)
+{
+  int  flag = 1;
+  st_table *FairSet;
+  lsGen lsgen;
+
+  lsForEachItem (A->Fair, lsgen, FairSet) {
+    if (st_is_member(FairSet, state) &&
+	!st_is_member(FairSet, otherstate)) {
+      flag = 0;
+      lsFinish(lsgen);
+      break;
+    }
+  }
+
+  return flag;
+}
+
+/**Function********************************************************************
+
+  Synopsis [If 'item' is in the hash table, Delete it and return the real key;
+  Otherwise, return  0.]
+
+  SideEffects ['item' will not be modified.]
+
+******************************************************************************/
+static char *
+StTableDelete(
+  st_table *tbl,
+  char *item)
+{
+  char *key = item;
+
+  if (st_is_member(tbl, key)) {
+    st_delete(tbl, &key, NIL(char *));
+    return key;
+  }else
+    return NIL(char);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Append the tbl2 to tbl1 and return tbl1.]
+
+  SideEffects [tbl1 is permenently changed.]
+
+******************************************************************************/
+static st_table *
+StTableAppend(
+  st_table *tbl1,
+  st_table *tbl2)
+{
+  char *key, *value;
+  st_generator *stgen;
+
+  st_foreach_item(tbl2, stgen, &key, &value) {
+    if (!st_is_member(tbl1, key))
+      st_insert(tbl1, key, value);
+  }
+
+  return tbl1;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Remove from tbl1 all the items that are not in tbl2.]
+
+  SideEffects [tbl1 is changed and returned.]
+
+******************************************************************************/
+static st_table *
+StTableRestrict(
+  st_table *tbl1,
+  st_table *tbl2)
+{
+  char *key, *value;
+  st_table *tbl = st_copy(tbl1);
+  st_generator *stgen;
+
+  st_foreach_item(tbl, stgen, &key, &value) {
+    if (!st_is_member(tbl2, key))
+      st_delete(tbl1, &key, &value);
+  }
+  st_free_table(tbl);
+
+  return tbl1;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Remove from tbl1 all the items that are in tbl2.]
+
+  SideEffects [tbl1 is changed and returned.]
+
+******************************************************************************/
+static st_table *
+StTableSubtract(
+  st_table *tbl1,
+  st_table *tbl2)
+{
+  char *key, *value;
+  st_generator *stgen;
+
+  st_foreach_item(tbl2, stgen, &key, &value) {
+    if (st_is_member(tbl1, key))
+      st_delete(tbl1, &key, &value);
+  }
+
+  return tbl1;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return 1 if tbl1 and tbl2 have the same items except those also
+  in 'dontcare'. 'dontcare' can be a null pointer.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+StTableIsEqual(
+  st_table *tbl1,
+  st_table *tbl2,
+  st_table *dontcare)
+{
+  int flag = 1;
+  st_generator *stgen;
+  vertex_t *vtx;
+
+  flag = 1;
+  st_foreach_item(tbl1, stgen, &vtx, NIL(char *)) {
+    if (dontcare) {
+      if (st_is_member(dontcare,vtx)) continue;
+    }
+    if (!st_is_member(tbl2,vtx)) {
+      flag = 0;
+      st_free_gen(stgen);
+      break;
+    }
+  }
+  if (!flag) return 0;
+
+  st_foreach_item(tbl2, stgen, &vtx, NIL(char *)) {
+    if (dontcare) {
+      if (st_is_member(dontcare,vtx)) continue;
+    }
+    if (!st_is_member(tbl1, vtx)) {
+      flag = 0;
+      st_free_gen(stgen);
+      break;
+    }
+  }
+  return flag;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return 1 if 'larger' include every items in 'small' except those
+  also in 'dontcare'. Notice that 'dontcare' can be a null pointer.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+StTableInclude(
+  st_table *large,
+  st_table *small,
+  st_table *dontcare)
+{
+  int flag = 1;
+  st_generator *stgen;
+  vertex_t *vtx;
+
+  flag = 1;
+  st_foreach_item(small, stgen, &vtx, NIL(char *)) {
+    if (dontcare) {
+      if (st_is_member(dontcare, vtx)) continue;
+    }
+    if (!st_is_member(large,vtx)) {
+      flag = 0;
+      st_free_gen(stgen);
+      break;
+    }
+  }
+
+  return flag;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Return 1 if the two tables shares nothing except those items also
+  in 'dontcare'. Notice that 'dontcare' can be a null pointer.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+StTableIsDisjoint(
+  st_table *tbl1,
+  st_table *tbl2,
+  st_table *dontcare)
+{
+  int flag = 1;
+  st_generator *stgen;
+  vertex_t *vtx;
+
+  flag = 1;
+  st_foreach_item(tbl1, stgen, &vtx, NIL(char *)) {
+    if (dontcare) {
+      if (st_is_member(dontcare, vtx))     continue;
+    }
+    if (st_is_member(tbl2,vtx)) {
+      flag = 0;
+      st_free_gen(stgen);
+      break;
+    }
+  }
+  if (!flag)  return 0;
+
+  st_foreach_item(tbl2, stgen, &vtx, NIL(char *)) {
+    if (dontcare) {
+      if (st_is_member(dontcare, vtx)) continue;
+    }
+    if (st_is_member(tbl1,vtx)) {
+      flag = 0;
+      st_free_gen(stgen);
+      break;
+    }
+  }
+  return flag;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return 1 if the given tables intersect every tables in the list.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+StTableIsFair(
+  lsList A_Fair,
+  st_table *Class)
+{
+  int flag;
+  st_table *FairSet;
+  lsGen lsgen;
+
+  flag = 1;
+  lsForEachItem (A_Fair, lsgen, FairSet) {
+    if (StTableIsDisjoint(FairSet,Class,NIL(st_table))) {
+      flag = 0;
+      lsFinish(lsgen);
+      break;
+    }
+  }
+
+  return flag;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return 1 if the given table forms a clique (for each state, there
+  are edges to all the states in the set).]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+AutomatonPartitionIsClique(
+  graph_t *G,
+  st_table *set)
+{
+  int flag = 1;
+  st_table *Img;
+  st_generator *stgen;
+  vertex_t *state;
+
+  st_foreach_item(set, stgen, &state, NIL(char *)) {
+    Img = AutomatonVertexGetImg(G, state);
+    flag = StTableInclude(Img, set, NIL(st_table));
+    st_free_table(Img);
+    if (!flag) {
+      st_free_gen(stgen);
+      break;
+    }
+  }
+
+  return flag;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Find the Least Upper Bound of the labels of a set of states, and
+  Return a hash table of states that satisfy this 'LUB'. Return null if the
+  hash table is empty.]
+
+  SideEffects [The result should be freed by the caller.]
+
+******************************************************************************/
+static st_table *
+AutomatonPartitionLabelLUB(
+  st_table *set,
+  array_t *Negate)
+{
+  vertex_t *state;
+  st_table *greatest = NIL(st_table);
+  st_generator *stgen;
+  LtlSet_t *lub = NIL(LtlSet_t);
+  LtlSet_t *label;
+
+  st_foreach_item(set, stgen, &state, NIL(char *)) {
+    label = LtlAutomatonVertexGetLabels(state);
+    if (greatest) {
+      if (LtlSetEqual(label, lub))
+	st_insert(greatest, state, state);
+      else if (LtlSetInclude(lub, label)) {
+	LtlSetAssign(lub, label);
+	st_free_table(greatest);
+	greatest = st_init_table(st_ptrcmp, st_ptrhash);
+	st_insert(greatest, state, state);
+      }else if (!LtlSetInclude(label, lub)) {
+	st_free_table(greatest);
+	greatest = NIL(st_table);
+	st_free_gen(stgen);
+	break;
+      }
+    }else {
+      lub = LtlSetCopy(label);
+      greatest = st_init_table(st_ptrcmp, st_ptrhash);
+      st_insert(greatest, state, state);
+    }
+  }
+
+  if (lub)
+    LtlSetFree(lub);
+
+  return greatest;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Find the Greatest Lower Bound of the labels of a set of states, and
+  Return a hash table of A state that satisfy this 'GLB'. Return null if the
+  hash table is empty.]
+
+  SideEffects [The result should be freed by the caller.]
+
+******************************************************************************/
+static st_table *
+AutomatonPartitionLabelGLB(
+  st_table *set,
+  array_t *Negate)
+{
+  vertex_t *state, *least;
+  LtlSet_t *glb, *label;
+  st_table *tbl;
+  st_generator *stgen;
+
+  least = NIL(vertex_t);
+  glb = NIL(LtlSet_t);
+  st_foreach_item(set, stgen, &state, NIL(char *)) {
+    label = LtlAutomatonVertexGetLabels(state);
+    if (!glb)
+      glb = LtlSetCopy(label);
+    else
+      LtlSetOR(glb, glb, label);
+
+    if (LtlSetIsContradictory(glb, Negate)) {
+      least = NIL(vertex_t);
+      st_free_gen(stgen);
+      break;
+    }else if (!least) {
+      if (LtlSetEqual(glb, label))
+	least = state;
+    }else if (!LtlSetEqual(glb, LtlAutomatonVertexGetLabels(least))) {
+      if (LtlSetEqual(glb, label))
+	least = state;
+      else
+	least = NIL(vertex_t);
+    }
+  }
+
+  if (glb)
+    LtlSetFree(glb);
+
+  if (least) {
+    tbl = st_init_table(st_ptrcmp, st_ptrhash);
+    st_insert(tbl, least, least);
+  }else
+    tbl = NIL(st_table);
+
+  return tbl;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return the partition component (a st_table) associated with the
+  given vertex in the Quotient graph.]
+
+  SideEffects [The result is owned by the node, and should NOT be freed.]
+
+******************************************************************************/
+static st_table *
+AutomatonQuotientVertexGetClass(
+  vertex_t *vtx)
+{
+  Ltl_AutomatonNode_t *node = (Ltl_AutomatonNode_t *)vtx->user_data;
+  return node->Class;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return the node index associated with the given vertex.]
+
+  SideEffects []
+
+******************************************************************************/
+/*static int
+AutomatonVtxGetNodeIdx(
+  vertex_t *v)
+{
+  Ltl_AutomatonNode_t *node = (Ltl_AutomatonNode_t *) v->user_data;
+  return node->index;
+}*/
Index: vis_dev/vis-2.3/src/ltl/ltlSet.c
===================================================================
--- vis_dev/vis-2.3/src/ltl/ltlSet.c	(revision 14)
+++ vis_dev/vis-2.3/src/ltl/ltlSet.c	(revision 14)
@@ -0,0 +1,1050 @@
+/**CFile***********************************************************************
+
+  FileName    [ltlSet.c]
+
+  PackageName [ltl]
+
+  Synopsis    [Set/Pair/Cover Manipulation functions used in the ltl package.]
+
+  Author      [Chao Wang<chao.wang@colorado.EDU>]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "ltlInt.h"
+
+static char rcsid[] UNUSED = "$Id: ltlSet.c,v 1.25 2005/04/28 08:45:27 bli Exp $";
+
+/* Set manipulation functions.
+ *  
+ * Set is a term -- the conjunction of literals. In the Ltl->Aut process, a
+ * literal can be an propositional formula, a X-formula and its negation.
+ * In order to interpret a Set, we need to corresponding arrays: Table and
+ * Negate. An '1' in the i-th position of the Set means "Table[i] is contained
+ * in the Set", and the negation of "Table[i]" is "Negate[i]".
+ * 
+ * Cover is a lsList of terms -- the "union" of all the items (product terms).
+ *
+ * Pair is a data structure to hold a 'ordered pair of items': (First, Second).
+ */
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Allocate the set data structure.]
+
+  Description []
+
+  SideEffects [The result should be freed by the caller.]
+
+******************************************************************************/
+LtlSet_t *
+LtlSetNew(
+  int size)
+{
+  LtlSet_t *set = ALLOC(LtlSet_t, 1);
+    
+  set->e = var_set_new(size);
+
+  return set;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Free the data structure associated with 'set'.]
+
+  Description []
+
+  SideEffects []
+
+******************************************************************************/
+void
+LtlSetFree(
+  LtlSet_t *set)
+{
+  var_set_free(set->e);
+  FREE(set);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Allocate the new set and copy the content of the given set.]
+
+  Description []
+
+  SideEffects [The result should be freed by the caller.]
+
+******************************************************************************/
+LtlSet_t *
+LtlSetCopy(
+  LtlSet_t *from)
+{
+  LtlSet_t *set = ALLOC(LtlSet_t, 1);
+  
+  set->e = var_set_copy(from->e);
+  
+  return set;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Assign the content of 'from' to set 'to'.]
+
+  Description []
+
+  SideEffects [set 'to' is changed.]
+
+******************************************************************************/
+void
+LtlSetAssign(
+  LtlSet_t *to,
+  LtlSet_t *from)
+{
+  var_set_assign(to->e, from->e);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return 1 if the two sets have the same content.]
+
+  Description []
+
+  SideEffects []
+
+******************************************************************************/
+int
+LtlSetEqual(
+  LtlSet_t *s1,
+  LtlSet_t *s2)
+{
+  return var_set_equal(s1->e, s2->e);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Return how many bit is set to 1 in the given set.]
+
+  Description []
+
+  SideEffects []
+
+******************************************************************************/
+int
+LtlSetCardinality(
+  LtlSet_t *set)
+{
+  return (var_set_n_elts(set->e));
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return -1/0/+1 when 's1' has more/equal/less cardinality than
+  's2'.]
+
+  Description []
+
+  SideEffects []
+
+******************************************************************************/
+int
+LtlSetCompareCardinality(
+  const void *p1,
+  const void *p2)
+{
+  LtlSet_t **s1 = (LtlSet_t **) p1;
+  LtlSet_t **s2 = (LtlSet_t **) p2;
+  int c1;
+  int c2;
+  
+  c1 = LtlSetCardinality(*s1);
+  c2 = LtlSetCardinality(*s2);
+  
+  if (c1 < c2)
+    return -1;
+  else if (c1 == c2)
+    return 0;
+  else
+    return +1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return 1 iff the set contains both 'F' and '!F'.]
+
+  Description []
+
+  SideEffects []
+
+******************************************************************************/
+int
+LtlSetIsContradictory(
+  LtlSet_t *set,
+  array_t *Negate)
+{
+  int i, negi;
+  int flag = 0;
+
+  for (i=0; i<array_n(Negate); i++) {
+    if (LtlSetGetElt(set, i)) {
+      negi = array_fetch(int, Negate, i);
+      if (LtlSetGetElt(set, negi)) {
+	flag = 1;
+	break;
+      }
+    }
+  }
+  
+  return flag;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return 1 iff 'large' includes 'small'.]
+
+  Description []
+
+  SideEffects []
+
+******************************************************************************/
+int
+LtlSetInclude(
+  LtlSet_t *large,
+  LtlSet_t *small)
+{
+  var_set_t *neg_large = var_set_not(var_set_copy(large->e),large->e);
+  int result = ! var_set_intersect(small->e, neg_large);
+  var_set_free(neg_large);
+  
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Union the two sets 'from1' and 'from2', and assign to set 'to'.]
+
+  Description []
+
+  SideEffects [set 'to' is changed.]
+
+******************************************************************************/
+void
+LtlSetOR(
+  LtlSet_t *to,
+  LtlSet_t *from1,
+  LtlSet_t *from2)
+{
+  var_set_or(to->e, from1->e, from2->e);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Clear all bits in the set.]
+
+  Description []
+
+  SideEffects [The set is changed.]
+
+******************************************************************************/
+void
+LtlSetClear(
+  LtlSet_t *set)
+{
+  var_set_clear(set->e);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Set the bit indicated by 'index'.]
+
+  Description []
+
+  SideEffects [The set is changed.]
+
+******************************************************************************/
+void
+LtlSetSetElt(
+  LtlSet_t *set,
+  int index)
+{
+  var_set_set_elt(set->e, index);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Clear the bit indicated by 'index'.]
+
+  Description []
+
+  SideEffects [The set is changed.]
+
+******************************************************************************/
+void
+LtlSetClearElt(
+  LtlSet_t *set,
+  int index)
+{
+  var_set_clear_elt(set->e, index);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return the value of the bit indicated by 'index'.]
+
+  Description []
+
+  SideEffects [The set is changed.]
+
+******************************************************************************/
+int
+LtlSetGetElt(
+  LtlSet_t *set,
+  int index)
+{
+  return var_set_get_elt(set->e,index);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return 1 if the set is empty.]
+
+  Description []
+
+  SideEffects []
+
+******************************************************************************/
+int
+LtlSetIsEmpty(
+  LtlSet_t *set)
+{
+  return var_set_is_empty(set->e);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return the set in the list that matches the given set.]
+
+  Description [Null will be return if there does not exist a match set.]
+
+  SideEffects []
+
+******************************************************************************/
+LtlSet_t *
+LtlSetIsInList(
+  LtlSet_t *set,
+  lsList list)
+{
+  lsGen gen;
+  lsGeneric data;
+  LtlSet_t *s = NIL(LtlSet_t);
+  int flag = 0;
+  
+  lsForEachItem(list, gen, data) {
+    s = (LtlSet_t *) data;
+    if ( var_set_equal(s->e, set->e) ) {
+      flag = 1;
+      lsFinish(gen);
+      break;
+    }
+  }
+  
+  return flag? s: NIL(LtlSet_t);
+}
+    
+/**Function********************************************************************
+
+  Synopsis    [Transform the given set to the label set and return it.]
+
+  Description [The given set may contain all the 'elementary formulae'. Its
+  table and negation are 'tableau->abTable' and 'tableau->abTableNegate'.
+  
+  The label set contain only the propositional formulae and their
+  negations. Its table and negation array are 'labelTable' and 'labelNegate'.
+
+  The above two table could have been the same, but we choose to implement
+  them differently: Since labelTable might be smaller than abTable, it will
+  make the boolean minimization based on it faster.]
+
+  SideEffects [The result should be freed by the caller.]
+
+******************************************************************************/
+LtlSet_t *
+LtlSetToLabelSet(
+  LtlTableau_t *tableau,
+  LtlSet_t *set)
+{
+  int i;
+  LtlSet_t *vset = LtlSetNew(tableau->labelIndex);
+  Ctlsp_Formula_t *F;
+  
+  for (i=0; i<tableau->abIndex; i++) {
+    if (var_set_get_elt(set->e, i)) {
+      F = tableau->abTable[i].F;
+      if (Ctlsp_LtlFormulaIsPropositional(F)&&
+	  Ctlsp_FormulaReadType(F) != Ctlsp_TRUE_c &&
+	  Ctlsp_FormulaReadType(F) != Ctlsp_FALSE_c)
+	var_set_set_elt(vset->e, 
+			Ctlsp_FormulaReadLabelIndex(tableau->abTable[i].F));
+    }
+  }
+  
+  return vset;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Print all the 'elementary formulae' contained in the set.]
+
+  Description [Assume the set is based on the index table 'tableau->abTable'.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+LtlSetPrint(
+  LtlTableau_t *tableau,
+  LtlSet_t *set)
+{
+  int i;
+  
+  fprintf(vis_stdout, "{ ");
+  for (i=0; i<tableau->abIndex; i++) {
+    if (LtlSetGetElt(set, i)) {
+      Ctlsp_FormulaPrint(vis_stdout, tableau->abTable[i].F);
+      fprintf(vis_stdout, "; ");
+    }
+  }
+  fprintf(vis_stdout, " }");
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Print all index that are set in the set.]
+
+  Description [The length of the set should be provided.]
+  
+  SideEffects []
+
+******************************************************************************/
+void
+LtlSetPrintIndex(
+  int length,
+  LtlSet_t *set)
+{
+  int i;
+  
+  fprintf(vis_stdout, "{ ");
+  for (i=0; i<length; i++) {
+    if (LtlSetGetElt(set, i)) {
+      fprintf(vis_stdout, " %d ", i);
+    }
+  }
+  fprintf(vis_stdout, " }\n");
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocate the data struture for 'pair'.]
+
+  Description []
+  
+  SideEffects []
+
+******************************************************************************/
+LtlPair_t *
+LtlPairNew(
+  char *First,
+  char *Second)
+{
+  LtlPair_t *pair = ALLOC(LtlPair_t, 1);
+
+  pair->First = First;
+  pair->Second= Second;
+  return pair;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Free the LtlPair_t data struture.]
+
+  Description []
+  
+  SideEffects []
+
+******************************************************************************/
+void
+LtlPairFree(
+  LtlPair_t *pair)
+{
+  FREE(pair);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return a hash key for the given pair.]
+
+  Description [The key is based on the content. Thus two pair with the same
+  content (not necessarily the same pointer) have the same hash key.]
+  
+  SideEffects []
+
+******************************************************************************/
+int
+LtlPairHash(
+  char *key,
+  int modulus)
+{
+  LtlPair_t *pair = (LtlPair_t *) key;
+  
+  return (int) ((((unsigned long) pair->First >>2) +
+		 ((unsigned long) pair->Second>>4)) % modulus);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return -1/0/+1 when the key1 is greater/equal/less than key2.]
+
+  Description [For two keys with the same content, they are equal.]
+  
+  SideEffects []
+
+******************************************************************************/
+int 
+LtlPairCompare(
+  const char *key1,
+  const char *key2)
+{
+  LtlPair_t *pair1 = (LtlPair_t *) key1;
+  LtlPair_t *pair2 = (LtlPair_t *) key2;
+  
+  assert(key1 != NIL(char));
+  assert(key2 != NIL(char));
+
+  if ((pair1->First == pair2->First) && (pair1->Second == pair2->Second))
+    return 0;
+  else if (pair1->First >= pair2->First && pair1->Second >= pair2->Second)
+    return 1;
+  else
+    return -1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Print the pair as index pair.]
+
+  Description []
+  
+  SideEffects []
+
+******************************************************************************/
+void
+LtlPairPrint(
+  LtlPair_t *pair)
+{
+  vertex_t *first = (vertex_t *) pair->First;
+  vertex_t *second= (vertex_t *) pair->Second;
+  Ltl_AutomatonNode_t *node1 = (Ltl_AutomatonNode_t *) first->user_data;
+  Ltl_AutomatonNode_t *node2 = (Ltl_AutomatonNode_t *) second->user_data;
+
+  fprintf(vis_stdout, " (n%d, n%d) ", node1->index, node2->index);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Print the cover as a set of index.]
+
+  Description []
+  
+  SideEffects []
+
+******************************************************************************/
+void
+LtlCoverPrintIndex(
+  int length,
+  lsList cover)
+{
+  int first = 1;
+  lsGen gen;
+  LtlSet_t *set;
+
+  fprintf(vis_stdout, "{ ");
+  lsForEachItem(cover, gen, set) {
+    if (first)	  first = 0;
+    else          	  fprintf(vis_stdout, " + ");
+    LtlSetPrintIndex(length, set);
+  }
+  fprintf(vis_stdout, " }");
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Return the 'Complete Sum' of the cover by iterated consensus.]
+
+  Description [The cover is represented by a list of sets (product terms).]
+  
+  SideEffects [The result should be freed by the caller. The given cover is
+  NOT changed.]
+
+******************************************************************************/
+lsList 
+LtlCoverCompleteSum(
+  lsList Cover,
+  array_t *Negate)
+{
+  lsList cs = lsCreate();
+  lsGen lsgen;
+  array_t *products = array_alloc(LtlSet_t *, 0);
+  LtlSet_t *term, *term1, *term2, *consensus;
+  long i, j, k, flag;
+  st_table *removed, *consList;  /* removed, and consensus generated */
+  
+  /* Check and remove contraditory terms -- containing both F and !F */
+  lsForEachItem(Cover, lsgen, term) {
+    if (!LtlSetIsContradictory(term, Negate))
+      array_insert_last(LtlSet_t *, products, term);
+  }
+  
+  /* Sort terms by increasing number of literals */
+  array_sort(products, LtlSetCompareCardinality);
+
+  /* Check tautologous term */
+  term = array_fetch(LtlSet_t *, products, 0);
+  if (LtlSetCardinality(term) == 0) {
+    lsNewEnd(cs, (lsGeneric) LtlSetCopy(term), (lsHandle *)0);
+    array_free(products);
+    return cs;
+  }
+
+  /* In the following, we won't change 'products'. Instead, if a term need to
+   * be removed, we will store it (its index number) in the hash table
+   */
+  removed = st_init_table(st_ptrcmp, st_ptrhash);
+  /* In the following, we might generate some new consensus terms, and we will
+   * store them (LtlSet_t) in the list 
+   */
+  consList = st_init_table(st_ptrcmp, st_ptrhash);
+  
+  /* Check terms for single-cube containment. Rely on ordering for efficiency.
+   * A term can only be contained by another term with fewer literals 
+   */
+  for (i=array_n(products)-1; i>0; i--) {
+    term = array_fetch(LtlSet_t *, products, i);
+    for (j=0; j<i; j++) {
+      term1 = array_fetch(LtlSet_t *, products, j);
+      if (LtlSetCardinality(term1) == LtlSetCardinality(term)) break;
+      if (LtlSetInclude(term, term1)) {
+	/* remember the removed term */
+	st_insert(removed, (char *)i, (char *)i);
+	break;
+      }
+    }
+  }
+  
+  /* Now do iterated consensus */
+  for (i=1; i<array_n(products); i++) {
+    if (st_is_member(removed, (char *)i)) continue;
+    term = array_fetch(LtlSet_t *, products, i);
+      
+    for (j=0; j<i; j++) {
+      if (st_is_member(removed, (char *)j)) continue;	  
+      term1 = array_fetch(LtlSet_t *, products, j);
+      
+      consensus = LtlSetConsensus(term, term1, Negate);
+	  
+      if (consensus) {
+	/* should store consensus ? */
+	flag = 1;  
+	for(k=0; k<array_n(products); k++) {
+	  if (st_is_member(removed, (char *)k)) continue;
+	  term2 = array_fetch(LtlSet_t *, products, k);
+	  
+	  if (LtlSetInclude(consensus, term2)) {
+	    /* redudant new term */
+	    flag = 0;  
+	    break;
+	  } 
+	  if (LtlSetInclude(term2, consensus)) {
+	    /* remember the removed term2 (k)  */
+	    st_insert(removed, (char *)k, (char *)k);
+	  }
+	}
+	if (flag) {
+	  array_insert_last(LtlSet_t *, products, consensus);
+	  st_insert(consList, consensus, (char *)0);
+	}else
+	  LtlSetFree(consensus);
+      }
+    }
+  }
+
+#if 0
+  if (0) {
+    fprintf(vis_stdout, "\nLtlCompleteSum: products = {  ");
+    for(i=0; i<array_n(products); i++) {
+      term = array_fetch(LtlSet_t *, products, i);
+      LtlSetPrintIndex(array_n(Negate), term);
+    }
+    fprintf(vis_stdout, "}\nLtlCompleteSum: removed = {  ");
+    st_foreach_item(removed, stgen, &i, NIL(char *)) {
+      term = array_fetch(LtlSet_t *, products, i);
+      LtlSetPrintIndex(array_n(Negate), term);
+    }
+    fprintf(vis_stdout, "}\nLtlCompleteSum: consList = {  ");
+    st_foreach_item(consList, stgen, &term, NIL(char *)) {
+      LtlSetPrintIndex(array_n(Negate), term);
+    }
+    fprintf(vis_stdout, "}\n");
+    
+    fflush(vis_stdout);
+  }
+#endif      
+  
+  arrayForEachItem(LtlSet_t *, products, i, term) {
+    if (!st_is_member(removed, (char *)i)) {
+      /* put it into the complete sum list */
+      if (!st_is_member(consList, term))
+	term1 = LtlSetCopy(term);
+      else
+	term1 = term;
+      lsNewEnd(cs, (lsGeneric) term1, NIL(lsHandle));
+    }else {
+      /* it has been removed. If it was allocated locally, free it */
+      if (st_is_member(consList, term))
+	LtlSetFree(term);
+    }
+  }
+
+  array_free(products);
+  st_free_table(removed);
+  st_free_table(consList);
+
+  return cs;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Return the consensus of two given set (product terms).]
+
+  Description [If the consesus does not exist, return a null pointer.]
+  
+  SideEffects [The result should be freed by the caller.]
+
+******************************************************************************/
+LtlSet_t *
+LtlSetConsensus(
+  LtlSet_t *first,
+  LtlSet_t *second,
+  array_t *Negate)
+{
+  LtlSet_t *consensus = LtlSetNew(array_n(Negate));
+  int pivot = -1;
+  int literal, complement;
+  
+  for (literal=0; literal<array_n(Negate); literal++) {
+    if (LtlSetGetElt(first, literal)) {
+      complement = array_fetch(int, Negate, literal);
+      if (LtlSetGetElt(second, complement)) {
+	if (pivot != -1) {
+	  LtlSetFree(consensus);
+	  return NIL(LtlSet_t);
+	}else {
+	  pivot = complement;
+	}
+      }else {
+	LtlSetSetElt(consensus, literal);
+      }
+    }
+  }
+  /* if pivot has never been defined, return NIL */
+  if (pivot == -1) {
+    LtlSetFree(consensus);
+    return NIL(LtlSet_t);
+  }
+
+  for (literal=0; literal<array_n(Negate); literal++) {
+    if (LtlSetGetElt(second, literal)) {
+      if (literal != pivot)
+	LtlSetSetElt(consensus, literal);
+    }
+  }
+
+  return consensus;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return the cofactor of the cover with respect to the set.]
+
+  Description [We need the Negate method for each item in the set.]
+  
+  SideEffects [The result need to be freed by the caller. The input is left
+  unchanged.]
+
+******************************************************************************/
+lsList
+LtlCoverCofactor(
+  lsList Cover,
+  LtlSet_t *c,
+  array_t *Negate)
+{
+  lsList cofactor = lsCopy(Cover, (lsGeneric (*)(lsGeneric))LtlSetCopy);
+  lsList list;
+  lsGen  lsgen;
+  st_table *removed = st_init_table(st_ptrcmp, st_ptrhash);
+  int literal, complement;
+  LtlSet_t *term;
+  
+  for (literal=0; literal<array_n(Negate); literal++) {
+    if (!LtlSetGetElt(c, literal))  continue;
+    complement = array_fetch(int, Negate, literal);
+    lsForEachItem(cofactor, lsgen, term) {
+      if (st_is_member(removed, term)) continue;
+      if (LtlSetGetElt(term, complement)) 
+	st_insert(removed, term, term);
+      else if (LtlSetGetElt(term, literal))
+	LtlSetClearElt(term, literal);
+    }
+  }
+
+  list = cofactor;
+  cofactor = lsCreate();
+  lsForEachItem(list, lsgen, term) {
+    if (st_is_member(removed, term)) 
+      LtlSetFree(term);
+    else
+      lsNewEnd(cofactor, (lsGeneric) term, (lsHandle *) 0);
+  }
+  lsDestroy(list, (void (*)(lsGeneric))0);
+
+  st_free_table(removed);
+
+  return cofactor;
+}
+      
+/**Function********************************************************************
+
+  Synopsis    [Return 1 if the given cover is tautology.]
+
+  Description [The test is not fast: the compute sum of the cover should be
+  computed.]
+  
+  SideEffects []
+
+******************************************************************************/
+int
+LtlCoverIsTautology(
+  lsList Cover,
+  array_t *Negate)
+{
+  lsList complete = LtlCoverCompleteSum(Cover, Negate);
+  LtlSet_t *term;
+  int result;
+
+  if (lsLength(complete) !=1)
+    result = 0;
+  else {
+    lsFirstItem(complete, &term, (lsHandle *)0);
+    result = (LtlSetCardinality(term) == 0);
+  }
+
+  lsDestroy(complete, (void (*)(lsGeneric))LtlSetFree);
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return 1 if the given cover is implied BY the set.]
+
+  Description []
+  
+  SideEffects []
+
+******************************************************************************/
+int
+LtlCoverIsImpliedBy(
+  lsList Cover,
+  LtlSet_t *term,
+  array_t *Negate)
+{
+  lsList cofactor = LtlCoverCofactor(Cover, term, Negate);
+  int result = LtlCoverIsTautology(Cover, Negate);
+  lsDestroy(cofactor, (void (*)(lsGeneric))LtlSetFree);
+  
+  return result;
+}
+    
+
+/**Function********************************************************************
+
+  Synopsis    [Boolean minimization of the given cover.]
+
+  Description [First, compute a prime and irredundant version of the Cover;
+  Then try to drop each item iff it is implied by the remaining items.
+  
+  Notice: there might be a bug in the algorithm. Need to be fixed.
+  Need to talke to Fabio/Roderick
+  ]
+  
+  SideEffects []
+
+******************************************************************************/
+lsList
+LtlCoverPrimeAndIrredundant(
+  LtlTableau_t *tableau,
+  lsList Cover,
+  array_t *Negate)
+{
+  lsList pai = LtlCoverCompleteSum(Cover, Negate);
+  int totalnum;   /* total num of terms in current lsList pai */
+  int procnum;    /* how many are already processed so far ? */
+  LtlSet_t *term;
+  
+  totalnum = lsLength(pai);
+  procnum = 0;
+  /* Try to drop each term in turn */
+  while(lsDelBegin(pai, &term) != LS_NOMORE) {
+    if ( (lsLength(pai) != 0) &&
+	 /* !LtlAutomatonSetIsFair(tableau, term) && */
+	 LtlCoverIsImpliedBy(pai, term, Negate) ) {
+      LtlSetFree(term);
+      totalnum--;
+    }else 
+      lsNewEnd(pai, (lsGeneric) term, (lsHandle *)0);
+    
+    procnum++;
+    if (procnum >= totalnum)
+      break;
+  }
+  
+  return pai;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Return the supercube of a cover.]
+
+  Description []
+  
+  SideEffects [The result should be freed by the caller.]
+
+******************************************************************************/
+LtlSet_t *
+LtlCoverGetSuperCube(
+  lsList Cover,
+  array_t *Negate)
+{
+  LtlSet_t *unate = LtlSetNew(array_n(Negate));
+  LtlSet_t *binate = LtlSetNew(array_n(Negate));
+  lsGen  lsgen;
+  LtlSet_t *term;
+  int literal, neg;
+
+  lsForEachItem( Cover, lsgen, term ) {
+    for (literal=0; literal<array_n(Negate); literal++) {
+      if (!LtlSetGetElt(term, literal))  continue;
+      if (LtlSetGetElt(binate, literal) || LtlSetGetElt(unate, literal))
+	continue;
+      neg = array_fetch(int, Negate, literal);
+      if (LtlSetGetElt(unate, neg)) {
+	LtlSetClearElt(unate, neg);
+	LtlSetSetElt(binate, literal);
+	LtlSetSetElt(binate, neg);
+      }else
+	LtlSetSetElt(unate, literal);
+    }
+  }
+
+  LtlSetFree(binate);
+  
+  return unate;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Return the supercube of a cover.]
+
+  Description []
+  
+  SideEffects [The result should be freed by the caller.]
+
+******************************************************************************/
+mdd_t *
+LtlSetModelCheckFormulae(
+  LtlSet_t *set,
+  array_t *labelTable,
+  Fsm_Fsm_t *fsm)
+{
+  mdd_t *minterm, *mdd1, *mdd2;
+  mdd_manager *mddManager = Fsm_FsmReadMddManager(fsm);
+  mdd_t *mddOne = mdd_one(mddManager);
+  array_t *careStatesArray = array_alloc(mdd_t *, 0);
+  int i;
+
+  array_insert(mdd_t *, careStatesArray, 0, mddOne);
+
+  minterm = mdd_dup(mddOne);
+  for (i=0; i<array_n(labelTable); i++) {
+    if (LtlSetGetElt(set, i)) {
+      Ctlsp_Formula_t *F = array_fetch(Ctlsp_Formula_t *, labelTable, i);
+      Ctlp_Formula_t *ctlF = Ctlsp_PropositionalFormulaToCTL(F);
+      mdd1 = Mc_FsmEvaluateFormula(fsm, ctlF, mddOne, 
+				   NIL(Fsm_Fairness_t),
+				   careStatesArray, 
+				   MC_NO_EARLY_TERMINATION,
+				   NIL(Fsm_HintsArray_t), Mc_None_c,
+				   McVerbosityNone_c, McDcLevelNone_c, 0,
+				   McGSH_EL_c);
+      mdd2 = minterm;
+      minterm = mdd_and(minterm, mdd1, 1, 1);
+      mdd_free(mdd2);
+      mdd_free(mdd1);
+      Ctlp_FormulaFree(ctlF);
+    }
+  }
+
+  mdd_array_free(careStatesArray);
+
+  return minterm;
+}
Index: vis_dev/vis-2.3/src/ltl/ltlTableau.c
===================================================================
--- vis_dev/vis-2.3/src/ltl/ltlTableau.c	(revision 14)
+++ vis_dev/vis-2.3/src/ltl/ltlTableau.c	(revision 14)
@@ -0,0 +1,488 @@
+/**CFile***********************************************************************
+
+  FileName    [ltlTableau.c]
+
+  PackageName [ltl]
+
+  Synopsis    [Expand the LTL Formula by applying the Tableau Rules.]
+
+  Author      [Chao Wang<chao.wang@colorado.EDU>]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "ltlInt.h"
+
+static char rcsid[] UNUSED = "$Id: ltlTableau.c,v 1.15 2008/04/22 21:22:33 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void TableauClearMarks(LtlTableau_t *tableau);
+static int TableauRules(LtlTableau_t *tableau, Ctlsp_Formula_t *F);
+static void HashNextFormulae(LtlTableau_t *tableau, Ctlsp_Formula_t *F);
+static void TableauLoadUntilSubFormulae(LtlTableau_t *tableau, Ctlsp_Formula_t *F);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Generate the 'Tableau' sturcture for the LTL->AUT problem.
+  It first computes the NNF of the input formula, then create the alpha/beta
+  entry table for both the input formula and its negation according the
+  tableau rules, and finally compute the list of 'Until formulae'.]
+
+  SideEffects []
+
+  SeeAlso     [LtlTableauGenerateRules]
+
+******************************************************************************/
+LtlTableau_t *
+LtlTableauGenerateTableau(
+  Ctlsp_Formula_t *formula)
+{
+  Ctlsp_Formula_t *F, *notF, *tmpF;
+  LtlTableau_t   *tableau;
+  int save_n;
+  int i, j;
+
+  /* compute the NNF of (formula) and (its negation) */
+  F = Ctlsp_LtlFormulaNegationNormalForm(formula);
+  tmpF = Ctlsp_FormulaCreate(Ctlsp_NOT_c, formula, NIL(Ctlsp_Formula_t));
+  notF = Ctlsp_LtlFormulaNegationNormalForm(tmpF);
+  FREE(tmpF);
+
+  /* Create the 'tableau' for this LTL->AUT problem */
+  tableau = LtlTableauCreate();
+  
+  /* Hash F & notF into the unique table */
+  F = Ctlsp_LtlFormulaHashIntoUniqueTable(F,tableau->formulaUniqueTable);
+  notF = Ctlsp_LtlFormulaHashIntoUniqueTable(notF,tableau->formulaUniqueTable);
+  tableau->F = F;
+  tableau->notF = notF;
+
+  /* tricky part:: for each U-formula/R-formula 'F', also hash 'XF' */
+  TableauClearMarks(tableau);
+  HashNextFormulae(tableau, F);
+  
+  /* Build the Alpha/Beta entry table */
+  tableau->abIndex = st_count(tableau->formulaUniqueTable);
+  tableau->abTable = ALLOC(LtlTableauEntry_t, tableau->abIndex);
+  tableau->labelTable = ALLOC(Ctlsp_Formula_t *, tableau->abIndex);
+
+  save_n = tableau->abIndex;
+  tableau->abIndex = 0;
+  TableauClearMarks(tableau);
+  TableauRules(tableau,F);      /* build the Alpha-Beta table */
+  TableauRules(tableau, notF);
+  tableau->abIndex = save_n;
+
+  /* compute the negation field (.notF) for each Alpha-Beta entry */
+  for (i=0; i<tableau->abIndex; i++) {
+    if (!tableau->abTable[i].notF) {
+      Ctlsp_Formula_t *thisF = Ctlsp_FormulaCreate(Ctlsp_NOT_c,
+						   tableau->abTable[i].F,
+						   NIL(Ctlsp_Formula_t));
+      Ctlsp_Formula_t *nnfF = Ctlsp_LtlFormulaNegationNormalForm(thisF);
+      FREE(thisF);
+						       
+      tableau->abTable[i].notF = 
+	Ctlsp_LtlFormulaHashIntoUniqueTable(nnfF, tableau->formulaUniqueTable);
+      for (j=0; j<tableau->abIndex; j++) {
+	if (tableau->abTable[j].F == tableau->abTable[i].notF) {
+	  tableau->abTable[i].notF_idx = j;
+	  tableau->abTable[j].notF_idx = i;
+	  tableau->abTable[j].notF = tableau->abTable[i].F;
+	  break;
+	}
+      }
+      assert(j < tableau->abIndex);
+    }
+    array_insert(int, tableau->abTableNegate, i, tableau->abTable[i].notF_idx);
+  }
+
+  /* put all constant formulae (labels) into tableau->labelTable
+   * includes: ID/NOT(ID) */
+  j = 0;
+  for (i=0; i<tableau->abIndex; i++) {
+    Ctlsp_Formula_t *holdF = tableau->abTable[i].F;
+    if (Ctlsp_LtlFormulaIsPropositional(holdF) &&
+	Ctlsp_FormulaReadType(holdF) != Ctlsp_TRUE_c &&
+	Ctlsp_FormulaReadType(holdF) != Ctlsp_FALSE_c) {
+      tableau->labelTable[j] = tableau->abTable[i].F;
+      Ctlsp_FormulaSetLabelIndex(tableau->abTable[i].F, j);
+      j++;
+    }
+  }
+  tableau->labelIndex = j;
+  
+  /* Create the Negate Method for abTable and labelTable */
+  for (i=0; i<tableau->abIndex; i++) {
+    array_insert(int, tableau->abTableNegate, i,
+		 Ctlsp_FormulaReadABIndex(tableau->abTable[i].notF));
+  }
+  for (i=0; i<tableau->labelIndex; i++) {
+    int idx = Ctlsp_FormulaReadABIndex(tableau->labelTable[i]);
+    array_insert(int, tableau->labelTableNegate, i,
+		 Ctlsp_FormulaReadLabelIndex(tableau->abTable[idx].notF));
+  }
+  
+  /* put all the 'until sub-formulae' into tableau->untilUniqueTable */
+  TableauClearMarks(tableau);
+  TableauLoadUntilSubFormulae(tableau, F);
+  
+  return tableau;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocate the data structure of tableau.]
+
+  Description []
+  
+  SideEffects []
+
+******************************************************************************/
+LtlTableau_t *
+LtlTableauCreate(
+  void)
+{
+  LtlTableau_t *tableau = ALLOC(LtlTableau_t, 1);
+  memset(tableau, 0, sizeof(LtlTableau_t));
+
+  tableau->F = tableau->notF = NIL(Ctlsp_Formula_t);
+  tableau->abIndex = 0;
+  tableau->abTable = 0;
+  tableau->abTableNegate = array_alloc(int, 0);
+  tableau->labelTable = 0;
+  tableau->labelTableNegate = array_alloc(int, 0);
+  /* create empty hash tables */
+  tableau->formulaUniqueTable = Ctlsp_LtlFormulaCreateUniqueTable();
+  tableau->untilUniqueTable = Ctlsp_LtlFormulaCreateUniqueTable();
+  
+  return tableau;
+} 
+
+
+/**Function********************************************************************
+
+  Synopsis    [Free the tableau data structure.]
+
+  SideEffects []
+
+  SeeAlso     [LtlTableauGenerateTableau]
+
+******************************************************************************/
+void
+LtlTableauFree(
+  LtlTableau_t *tableau)
+{
+  int i;
+  char *tmpstr;
+  
+  /* free all the LTL formulae */
+  for (i=0; i<tableau->abIndex; i++) {
+    if (Ctlsp_FormulaReadType(tableau->abTable[i].F) == Ctlsp_ID_c) {
+      tmpstr = Ctlsp_FormulaReadVariableName(tableau->abTable[i].F);
+      FREE(tmpstr);
+      tmpstr = Ctlsp_FormulaReadValueName(tableau->abTable[i].F);
+      FREE(tmpstr);
+    }
+    FREE(tableau->abTable[i].F);
+  }
+
+  FREE(tableau->abTable);
+  FREE(tableau->labelTable);
+  array_free(tableau->abTableNegate);
+  array_free(tableau->labelTableNegate);
+  
+  st_free_table(tableau->formulaUniqueTable);
+  st_free_table(tableau->untilUniqueTable);
+
+  FREE(tableau);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Print the content of the tableau.]
+
+  SideEffects []
+
+  SeeAlso     [LtlTableauGenerateTableau]
+
+******************************************************************************/
+void 
+LtlTableauPrint(
+  FILE *fp,
+  LtlTableau_t *tableau)
+{
+  int i;
+
+  (void) fprintf(fp, "Tableau Rules for {");
+  Ctlsp_FormulaPrint(fp,tableau->F);
+  (void) fprintf(fp, "} : # of sub-formulae = %d\n", tableau->abIndex);
+    
+  for (i=0; i<tableau->abIndex; i++) {
+    fprintf(fp, "%d   [", i);
+    Ctlsp_FormulaPrint(fp, tableau->abTable[i].F);
+    fprintf(fp, "]\n\t");
+    fprintf(fp, "(%3d * %3d * X%3d) + (%3d * %3d * X%3d) -- notF= %3d\n",
+	    tableau->abTable[i].A[0].B[0],
+	    tableau->abTable[i].A[0].B[1],
+	    tableau->abTable[i].A[0].n,
+	    tableau->abTable[i].A[1].B[0],
+	    tableau->abTable[i].A[1].B[1],
+	    tableau->abTable[i].A[1].n,
+	    tableau->abTable[i].notF_idx);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Return the unique formula 'X F' in the tableu by giving 'F'.]
+
+  Description [If there does not exist, create and hash it into the unique
+  table.]
+  
+  SideEffects []
+
+******************************************************************************/
+Ctlsp_Formula_t *
+LtlTableauGetUniqueXFormula(
+  LtlTableau_t *tableau,
+  Ctlsp_Formula_t *F)
+{
+  Ctlsp_Formula_t *tmpF, *XF;
+  
+  tmpF = Ctlsp_FormulaCreate(Ctlsp_X_c, F, NIL(Ctlsp_Formula_t));
+  XF = Ctlsp_LtlFormulaNegationNormalForm(tmpF);
+  FREE(tmpF);
+  XF = Ctlsp_LtlFormulaHashIntoUniqueTable(XF,tableau->formulaUniqueTable);
+
+  return XF;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Clear the marks of all the formula in the tableau.]
+
+  Description []
+  
+  SideEffects []
+
+******************************************************************************/
+static void
+TableauClearMarks(
+  LtlTableau_t *tableau)
+{
+  st_table *tbl = tableau->formulaUniqueTable;
+  st_generator *stgen;
+  Ctlsp_Formula_t *F;
+
+  st_foreach_item(tbl, stgen, &F, NIL(char *)) {
+    Ctlsp_FormulaResetMarked(F);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Fill out the Alpha-Beta entry table recursively.]
+
+  Description [1) assign each formula F an index and an entry;
+  2) build for each formula F a expansion  ( {A0B0 ^ A0B1} + {A1B0 ^ A1B1} )]
+  
+  SideEffects []
+
+******************************************************************************/
+static int
+TableauRules(
+  LtlTableau_t *tableau,
+  Ctlsp_Formula_t *F)
+{
+  int index;
+  int A0B0=-1, A0B1=-1, A0n=-1;
+  int A1B0=-1, A1B1=-1, A1n=-1;
+  Ctlsp_Formula_t *XF;
+  Ctlsp_Formula_t *F_left, *F_right;
+  Ctlsp_FormulaType F_type;
+  
+  assert( F );
+  
+  if (Ctlsp_FormulaReadMarked(F))
+    return Ctlsp_FormulaReadABIndex(F);
+
+  Ctlsp_FormulaSetMarked(F);
+  index = tableau->abIndex++;
+  Ctlsp_FormulaSetABIndex(F, index);
+
+  F_type = Ctlsp_FormulaReadType(F);
+  F_left = Ctlsp_FormulaReadLeftChild(F);
+  F_right = Ctlsp_FormulaReadRightChild(F);
+  
+  switch(F_type) {
+  case Ctlsp_X_c:
+    TableauRules(tableau, F_left); 
+    A0n = index;
+    break;
+  case Ctlsp_OR_c:
+    A0B0 = TableauRules(tableau, F_left);
+    A1B0 = TableauRules(tableau, F_right);
+    break;
+  case Ctlsp_AND_c:
+    A0B0 = TableauRules(tableau, F_left);
+    A0B1 = TableauRules(tableau, F_right);
+    break;
+  case Ctlsp_U_c:
+    A0B0 = TableauRules(tableau, F_left);
+    A1B0 = TableauRules(tableau, F_right);
+    XF = LtlTableauGetUniqueXFormula(tableau, F);
+    A0n = TableauRules(tableau, XF);
+    break;
+  case Ctlsp_R_c:
+    A0B0 = TableauRules(tableau, F_right);
+    A1B0 = TableauRules(tableau, F_right);
+    A1B1 = TableauRules(tableau, F_left);
+    XF = LtlTableauGetUniqueXFormula(tableau, F);
+    A0n = TableauRules(tableau, XF);
+    break;
+  default:
+    break;
+  }
+  
+  tableau->abTable[index].F = F;
+  tableau->abTable[index].A[0].B[0] = A0B0;
+  tableau->abTable[index].A[0].B[1] = A0B1;
+  tableau->abTable[index].A[1].B[0] = A1B0;
+  tableau->abTable[index].A[1].B[1] = A1B1;
+  tableau->abTable[index].A[0].n = A0n;
+  tableau->abTable[index].A[1].n = A1n;
+  
+  tableau->abTable[index].notF_idx = -1;
+  tableau->abTable[index].notF = NIL(Ctlsp_Formula_t);
+
+  return index;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Hash the formula 'X F' and its negation in the unique tableau.]
+
+  Description [Construct the 'X F' from the given 'F', and hash it.]
+  
+  SideEffects []
+
+******************************************************************************/
+static void
+HashNextFormulae(
+  LtlTableau_t *tableau,
+  Ctlsp_Formula_t *F)
+{
+  Ctlsp_Formula_t *XF, *NXF, *tmpF;
+  Ctlsp_FormulaType F_type = Ctlsp_FormulaReadType(F);
+  Ctlsp_Formula_t *F_left = Ctlsp_FormulaReadLeftChild(F);
+  Ctlsp_Formula_t *F_right = Ctlsp_FormulaReadRightChild(F);
+  
+  switch( F_type ) {
+  case Ctlsp_X_c:
+    HashNextFormulae(tableau, F_left);
+    break;
+  case Ctlsp_OR_c:
+  case Ctlsp_AND_c:
+    HashNextFormulae(tableau, F_left);
+    HashNextFormulae(tableau, F_right);
+    break;
+  case Ctlsp_U_c:
+  case Ctlsp_R_c:
+    HashNextFormulae(tableau, F_left);
+    HashNextFormulae(tableau, F_right);
+    XF = LtlTableauGetUniqueXFormula(tableau, F);      
+    tmpF = Ctlsp_FormulaCreate(Ctlsp_NOT_c, XF, NIL(Ctlsp_Formula_t));
+    NXF = Ctlsp_LtlFormulaNegationNormalForm(tmpF);
+    FREE(tmpF);
+    Ctlsp_LtlFormulaHashIntoUniqueTable(NXF,tableau->formulaUniqueTable);
+    break;
+  default:
+    break;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Put all the Until sub-formulae in a list.]
+
+  Description []
+  
+  SideEffects []
+
+******************************************************************************/
+static void
+TableauLoadUntilSubFormulae(
+  LtlTableau_t *tableau,
+  Ctlsp_Formula_t *F)
+{
+  char *list;
+  st_table *uniqueTable = tableau->untilUniqueTable;
+  Ctlsp_FormulaType F_type;
+  
+  if (!F)
+    return;
+
+  if (Ctlsp_FormulaReadMarked(F))
+    return;
+
+  
+  Ctlsp_FormulaSetMarked(F);
+  F_type = Ctlsp_FormulaReadType(F);
+  if (F_type == Ctlsp_U_c) {
+    if(!st_is_member(uniqueTable,  F)) {
+      list = (char *) lsCreate();
+      st_insert(uniqueTable,  F, list);
+    }
+    Ctlsp_FormulaSetRhs(Ctlsp_FormulaReadRightChild(F));
+  }
+  if (F_type != Ctlsp_ID_c) {
+    TableauLoadUntilSubFormulae(tableau, Ctlsp_FormulaReadLeftChild(F));
+    TableauLoadUntilSubFormulae(tableau, Ctlsp_FormulaReadRightChild(F));
+  }
+}      
+
Index: vis_dev/vis-2.3/src/ltl/ltlUtil.c
===================================================================
--- vis_dev/vis-2.3/src/ltl/ltlUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/ltl/ltlUtil.c	(revision 14)
@@ -0,0 +1,48 @@
+/**CFile***********************************************************************
+
+  FileName    [ltlUtil.c]
+
+  PackageName [ltl]
+
+  Synopsis    [Utilities for LTL model checker]
+
+  Author      [Chao Wang <chao.wang@colorado.EDU]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "ltlInt.h"
+#include <errno.h>
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
Index: vis_dev/vis-2.3/src/maig/maig.h
===================================================================
--- vis_dev/vis-2.3/src/maig/maig.h	(revision 14)
+++ vis_dev/vis-2.3/src/maig/maig.h	(revision 14)
@@ -0,0 +1,128 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [maig.h]
+
+  PackageName [maig]
+
+  Synopsis    [multi-valued AND/INVERTER graph]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [Mohammad Awedh]
+
+  Copyright [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+  Revision    [$Id: maig.h,v 1.8 2005/05/18 18:11:59 jinh Exp $]
+
+
+******************************************************************************/
+
+#ifndef _MAIG
+#define _MAIG
+
+#include "vm.h"
+#include "util.h"
+#include "var_set.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+ 
+#define mAig_And   bAig_And
+#define mAig_Or    bAig_Or
+#define mAig_Xor   bAig_Xor
+#define mAig_Not   bAig_Not
+#define mAig_Eq    bAig_Eq
+#define mAig_Then  bAig_Then
+#define mAig_Zero  bAig_Zero
+#define mAig_One   bAig_One
+#define mAig_NULL  bAig_NULL
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef struct mAigMvarStruct mAigMvar_t;
+typedef struct mAigBvarStruct mAigBvar_t;
+
+typedef long     mAigEdge_t;
+typedef struct bAigManagerStruct mAig_Manager_t;
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [Multi-valued Variable]
+
+  Description [This structure stores an information about a Multi-value variable.]
+
+******************************************************************************/
+struct mAigMvarStruct {
+    int  mVarId;          /* Uniquely identifies this mVar node in mVarList*/
+    char *name;	          /* Name of multi-value node */
+    int  values;	  /* This mvar takes vlaues from 0 -- values-1 */
+    int  encodeLength;    /* Number of binary variables needed to encode this 
+                             mvar */
+    int  bVars;          /* The array index of the first bVar in the bVarList
+                            the size of the binary encoding equal encodeLength
+                            and code arrange from  most significant bit to 
+                            least significant bit */
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [Binary-valued varaible]
+
+  Description [Thsi structure contians information about binary-vlaue node]
+
+*****************************************************************************/
+struct mAigBvarStruct {
+    mAigEdge_t node;  /* Binary function of this node in the AndInv graph */
+    int mVarId;          /* This bVar node belongs to mVar node mVarId       */
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void mAig_Init(void);
+EXTERN void mAig_End(void);
+EXTERN array_t * mAig_ArrayDuplicate(array_t *mAigArray);
+EXTERN mAig_Manager_t * mAig_initAig(void);
+EXTERN void mAig_quit(mAig_Manager_t *manager);
+EXTERN mAigEdge_t mAig_EquC(mAig_Manager_t * mgr, mAigEdge_t mVarId, int constant);
+EXTERN mAigEdge_t mAig_CreateVar(mAig_Manager_t * mgr, char * name, int value);
+EXTERN array_t * mAigReadBinVarList(mAig_Manager_t * manager);
+EXTERN array_t * mAigReadMulVarList(mAig_Manager_t * manager);
+EXTERN mAigEdge_t mAig_CreateVarFromAig(mAig_Manager_t * mgr, char * name, array_t *mvfAig);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _MAIG */
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/maig/maig.make
===================================================================
--- vis_dev/vis-2.3/src/maig/maig.make	(revision 14)
+++ vis_dev/vis-2.3/src/maig/maig.make	(revision 14)
@@ -0,0 +1,4 @@
+CSRC += maigUtil.c
+HEADERS += maig.h maigInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/maig/maigInt.h
===================================================================
--- vis_dev/vis-2.3/src/maig/maigInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/maig/maigInt.h	(revision 14)
@@ -0,0 +1,62 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [maigInt.h]
+
+  PackageName [maig]
+
+  Synopsis    []
+
+  Description [Internal data structures of Multi-vlaued AND/INVERTER package]
+
+  SeeAlso     []
+
+  Author      [Mohammad Awedh]
+
+  Copyright [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+  Revision    [$Id: maigInt.h,v 1.4 2005/04/27 00:31:03 jinh Exp $]
+
+
+******************************************************************************/
+
+#ifndef _MAIGINT
+#define _MAIGINT
+
+#include "maig.h"
+#include "baigInt.h"
+#include "array.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _MIGINT */
+
+
+
+
+
Index: vis_dev/vis-2.3/src/maig/maigUtil.c
===================================================================
--- vis_dev/vis-2.3/src/maig/maigUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/maig/maigUtil.c	(revision 14)
@@ -0,0 +1,519 @@
+/**CFile***********************************************************************
+
+  FileName    [maigUtil.c]
+
+  PackageName [maig]
+
+  Synopsis    [Utilities for Multi-Valued AndInv graph]
+
+  Author      [Mohammad Awedh]
+
+  Copyright [ This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "maigInt.h"
+#include "mvfaig.h"
+#include "mvfaigInt.h"
+#include "ctlspInt.h"
+#include "ctlsp.h"
+#include "ntk.h"
+
+static char rcsid[] UNUSED = "$Id: maigUtil.c,v 1.20 2005/05/18 18:11:59 jinh Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int NoOfBitEncode(int n);
+static bAigEdge_t Case(mAig_Manager_t * mgr, array_t * encodeList, int index);
+static int mCommandmAigTest(void);
+
+/**AutomaticEnd***************************************************************/
+
+  
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Initialize maig package]
+
+  SideEffects [none]
+
+  SeeAlso     [mAig_End]
+
+******************************************************************************/
+void
+mAig_Init(void)
+{
+  Cmd_CommandAdd("_mAig_test",
+		 (int(*)(Hrc_Manager_t **, int, char **))  mCommandmAigTest,
+		 0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [End maig package]
+
+  SideEffects []
+
+  SeeAlso     [mAig_Init]
+
+******************************************************************************/
+void
+mAig_End(void)
+{
+}
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+mAig_ArrayDuplicate(
+  array_t *mAigArray)
+{
+  int      i;
+  int      length = array_n(mAigArray);
+  array_t *result = array_alloc(mAigEdge_t *, length);
+  for (i = 0; i < length; i++) {
+    mAigEdge_t *tempMAig = array_fetch(mAigEdge_t *, mAigArray, i);
+    array_insert(mAigEdge_t *, result, i, tempMAig);
+  }
+
+  return (result);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a new mAig manager]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+mAig_Manager_t *
+mAig_initAig(void)
+{
+  return bAig_initAig(5000); /* Initial number of nodes in the bAIG greaph*/
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Quit mAig manager]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+mAig_quit(
+  mAig_Manager_t *manager)
+{
+ bAig_quit(manager);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Build the binary representation of multi-valued variable that
+  equal to constant.]
+
+  Description [It builds the binary And/Inverter graph of a multi-valued
+  variable of value equal to constant.]
+  
+  SideEffects []
+
+  SeeAlso     [Case]
+
+******************************************************************************/
+mAigEdge_t
+mAig_EquC(
+  mAig_Manager_t * mgr,
+  mAigEdge_t     mVarId,
+  int            constant)
+{
+  array_t *mVarList    = mAigReadMulVarList(mgr);
+  mAigMvar_t mVar      = array_fetch(mAigMvar_t, mVarList, mVarId);
+  array_t  *encodeList = array_alloc(bAigEdge_t, 0);
+  int i;
+  bAigEdge_t bVarId;
+  for(i=0; i< mVar.values; i++){
+    if( i == constant){
+      array_insert_last(bAigEdge_t, encodeList, mAig_One);      
+    }
+    else{
+      array_insert_last(bAigEdge_t, encodeList, mAig_Zero);
+    } /* if */
+  } /* for */
+  bVarId = Case(mgr, encodeList, mVar.bVars + mVar.encodeLength-1); /* Build the bAig grpah */
+  array_free(encodeList);
+  return bVarId;  
+}
+
+/**Function********************************************************************
+
+  Synopsis [Creates Multi-valued Variable]
+
+  Description [Creates Multi-valued variable of name 'name' and value 'value',
+               and returns the Id for this variable. It creates the binary 
+               variable that are used to rpresent this multi-valued variable.]
+
+  SideEffects []
+
+  SeeAlso     [bAig_CreateVarNode]
+
+******************************************************************************/
+mAigEdge_t
+mAig_CreateVar(
+  mAig_Manager_t * mgr,
+  char           * name,
+  int            value)
+{
+  array_t *mVarList    = mAigReadMulVarList(mgr);
+  array_t *bVarList    = mAigReadBinVarList(mgr);
+
+  int         noBits      = NoOfBitEncode(value);
+  int         i, startBvar, startMvar;
+  /*
+  char        bName[100];
+  */
+  char        *bName = ALLOC(char, strlen(name) + 10);
+  mAigMvar_t  mVar;   
+  mAigBvar_t  bVar; 
+
+  assert(mVarList != NIL(array_t));
+  assert(bVarList != NIL(array_t));
+
+  startBvar = array_n(bVarList);
+  startMvar = array_n(mVarList);
+
+  /* Create Multi-valued variable */
+  mVar.mVarId       = startMvar;
+  mVar.bVars        = startBvar;
+  mVar.values       = value;
+  mVar.name         = name;
+  mVar.encodeLength = noBits;
+ 
+  array_insert_last(mAigMvar_t, mVarList, mVar);
+
+  /* Create binary Variables of the Multi-valued variable */
+  for (i=0; i<noBits; i++){
+    sprintf(bName, "%s_%d", name, i);
+    bVar.node = bAig_CreateVarNode(mgr,  util_strsav(bName));
+
+    bVar.mVarId = mVar.mVarId; 
+    array_insert_last(mAigBvar_t, bVarList, bVar);
+  } /* for */
+  return (mVar.mVarId);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Creates Multi-valued Variable from multi-valued logic]
+
+  Description [Creates Multi-valued variable of name 'name' and value 'value',
+               and returns the Id for this variable. It creates the binary 
+               variable that are used to rpresent this multi-valued variable.]
+
+  SideEffects []
+
+  SeeAlso     [bAig_CreateVarNode]
+
+******************************************************************************/
+mAigEdge_t
+mAig_CreateVarFromAig(
+  mAig_Manager_t * mgr,
+  char           * name,
+  array_t        *mvfAig)
+{
+  array_t *mVarList    = mAigReadMulVarList(mgr);
+  array_t *bVarList    = mAigReadBinVarList(mgr);
+
+  int noBits, value, index1;
+  int startBvar, startMvar;
+  int i, j, divider, orFlag;
+  bAigEdge_t v, resultOn, resultOff;
+  mAigMvar_t  mVar;   
+  mAigBvar_t  bVar; 
+
+  assert(mVarList != NIL(array_t));
+  assert(bVarList != NIL(array_t));
+
+  value = array_n(mvfAig);
+  noBits = NoOfBitEncode(value);
+  startBvar = array_n(bVarList);
+  startMvar = array_n(mVarList);
+
+  /* Create Multi-valued variable */
+  mVar.mVarId       = startMvar;
+  mVar.bVars        = startBvar;
+  mVar.values       = value;
+  mVar.name         = name;
+  mVar.encodeLength = noBits;
+ 
+  array_insert_last(mAigMvar_t, mVarList, mVar);
+
+  for(i=0, index1=mVar.bVars; i<mVar.encodeLength; i++) {
+
+    resultOn = bAig_Zero;
+    resultOff = bAig_Zero;
+/*    divider = (int)pow(2.0, (double)(i)); */
+    divider = (int)pow(2.0, (double)(mVar.encodeLength-i-1));
+    orFlag = 1;
+    for(j=0; j<value; j++) {
+      if(j%divider == 0)orFlag = !orFlag;
+      v = array_fetch(bAigEdge_t, mvfAig, j);
+      if(orFlag){
+        resultOn = bAig_Or(mgr, resultOn, v);
+      }
+      else {
+        resultOff = bAig_Or(mgr, resultOff, v);
+      }
+    }
+    bVar.node = resultOn;
+    bVar.mVarId = mVar.mVarId; 
+    array_insert_last(mAigBvar_t, bVarList, bVar);
+    index1++;
+  }
+  return (mVar.mVarId);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Return the Binary Variables List]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+array_t * 
+mAigReadBinVarList(
+    mAig_Manager_t * manager)
+{
+  return (manager->bVarList);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Retunrs the Multi-Valued variables List]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+array_t *
+mAigReadMulVarList(
+    mAig_Manager_t * manager)
+{
+  return (manager->mVarList);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns no. of Bit encoding needed for n]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+NoOfBitEncode(
+   int n)
+{
+    int i = 0;
+    int j = 1;
+
+    if (n < 2) return 1; /* Takes care of mv.values <= 1 */
+
+    while (j < n) {
+	j = j * 2;
+	i++;
+    }
+    return i;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the binary And/Inverter graph of a multi-valued
+               variable.]
+
+  Description [The encodingList array has bAig_Zero in all its entries except
+  the enrty at which the multi-valued variable equal to the required value.
+  At which the value is bAig_One.]
+
+  SideEffects []
+
+  SeeAlso     [mAig_EquC]
+
+******************************************************************************/
+static bAigEdge_t
+Case(
+  mAig_Manager_t * mgr,
+  array_t *       encodeList,
+  int             index)
+{
+  array_t       *bVarList    = mAigReadBinVarList(mgr);
+  mAigBvar_t    bVar; 
+  array_t       *newEncodeList;
+  int           encodeLen = array_n(encodeList);  
+  bAigEdge_t    andResult1, andResult2, orResult, result;
+  bAigEdge_t    node1, node2;
+  int i; 
+  int count=0;
+
+  if (encodeLen == 1){
+    return array_fetch(bAigEdge_t, encodeList, 0);
+  }
+  bVar   = array_fetch(mAigBvar_t, bVarList, index); 
+  newEncodeList =  array_alloc(bAigEdge_t, 0);
+
+  for (i=0; i< (encodeLen/2); i++){
+     node1 = array_fetch(bAigEdge_t, encodeList, count++);
+     node2 = array_fetch(bAigEdge_t, encodeList, count++);
+  
+     /*  performs ITE operator */
+     andResult1 = bAig_And(mgr, bVar.node,           node2);
+     andResult2 = bAig_And(mgr, bAig_Not(bVar.node), node1);
+     orResult   = bAig_Or (mgr, andResult1,          andResult2);
+    
+     array_insert_last(bAigEdge_t, newEncodeList, orResult);
+    
+  }
+  if (encodeLen %2){ /* Odd */
+     node1 = array_fetch(bAigEdge_t, encodeList, count);
+     array_insert_last(bAigEdge_t, newEncodeList, node1);
+  }
+  result = Case(mgr, newEncodeList, index-1);
+  array_free(newEncodeList);
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  CommandName [_mAig_test]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+mCommandmAigTest(void)
+{
+  array_t *mVarList;
+  array_t *bVarList;
+
+  MvfAig_Function_t * aa;
+  MvfAig_Function_t * bb;
+  MvfAig_Function_t * cc;
+
+  mAigMvar_t mVar;   
+  mAigBvar_t bVar; 
+
+  int i;
+
+  mAig_Manager_t *manager = mAig_initAig();
+  mAigEdge_t      node1, node2, node3, node4, node5, node6;
+
+  node1 = mAig_CreateVar(manager,"a",5); /* var a of 5 values */
+  node2 = mAig_CreateVar(manager,"b",6); /* var b of 6 values */
+  node3 = mAig_CreateVar(manager,"c",2); /* var c of 2 values */
+
+  aa = MvfAig_FunctionCreateFromVariable(manager, node1);
+  bb = MvfAig_FunctionCreateFromVariable(manager, node2);
+  cc = MvfAig_FunctionCreateFromVariable(manager, node3);
+
+  mVarList    = mAigReadMulVarList(manager);
+  bVarList    = mAigReadBinVarList(manager);  
+  fprintf(vis_stdout,"mValist: \n");
+  for (i=0; i< array_n(mVarList); i++){
+    mVar   = array_fetch(mAigMvar_t, mVarList, i);
+    fprintf(vis_stdout,"mVarId=%d name=%s bVarId=%d values:%d\n",  mVar.mVarId, mVar.name, mVar.bVars, mVar.values);
+  }
+
+  fprintf(vis_stdout,"bValist: \n");
+  for (i=0; i< array_n(bVarList); i++){
+    bVar   = array_fetch(mAigBvar_t, bVarList, i);
+    fprintf(vis_stdout,"mVar ID=%d bVar ID=%ld \n",  bVar.mVarId, bVar.node);
+  }
+
+  node4 = array_fetch(bAigEdge_t, aa, 3);
+  node5 = array_fetch(bAigEdge_t, bb, 2);
+  node6 = mAig_Or(manager, node4, node5);
+
+  node4 = array_fetch(bAigEdge_t, cc, 0);
+  node5 = bAig_Eq(manager, node6, node4);
+
+  fprintf(vis_stdout,"%ld %ld %ld %ld %ld %ld\n",node1, node2, node3, node4, node5, node6);
+  fprintf(vis_stdout,"Nodes Array:\n\n");
+  for (i=0; i< manager->nodesArraySize ; i++)
+    fprintf(vis_stdout,"Node #%d  value=%ld \n",i,manager->NodesArray[i]);
+
+  fprintf(vis_stdout,"\n\nName List:\n");
+  for (i=0; i< 20; i++)
+    fprintf(vis_stdout,"index %d  Name %s \n",i, manager->nameList[i]);
+
+  bAig_PrintDot(vis_stdout, manager);
+
+  return 0;
+
+}
Index: vis_dev/vis-2.3/src/mark/mark.c
===================================================================
--- vis_dev/vis-2.3/src/mark/mark.c	(revision 14)
+++ vis_dev/vis-2.3/src/mark/mark.c	(revision 14)
@@ -0,0 +1,1011 @@
+/**CFile***********************************************************************
+
+  FileName    [mark.c]
+
+  PackageName [mark]
+
+  Synopsis    [Functions for Markov analysis.]
+
+  Description [External procedures included in this module:
+		<ul>
+		<li> Mark_FsmComputeStateProbs()
+		<li> Mark_ComputeStateProbsWithTr()
+		</ul>
+	Internal procedures included in this module:
+		<ul>
+		<li> MarkAverageBitChange()
+		</ul> ]
+
+  Author      [Balakrishna Kumthekar]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "markInt.h"
+
+static char rcsid[] UNUSED = "$Id: mark.c,v 1.29 2005/04/27 05:24:08 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void ckInterface(CK *ck);
+static bdd_node * recTC(CK *ck, bdd_node *tr);
+static bdd_node * transitiveClosureByIterSquaring(bdd_manager *ddManager, bdd_node *TR, bdd_node **xVars, bdd_node **yVars, bdd_node **zVars, int nVars);
+static bdd_node * bddCollapseTSCC(CK *ck);
+static int sccGetPeriod(CK *ck, bdd_node *reset);
+static array_t * markGetBddArray(array_t *mvfArray);
+static bdd_node ** BddNodeArrayFromIdArray(bdd_manager *ddManager, array_t *idArray);
+static bdd_node * computeTransitionRelationWithIds(bdd_manager *ddManager, array_t *nextBdds, bdd_node **yVars, int nVars);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Perform markovian analysis for Fsm.]
+
+  Description [Performs Markovian analysis on the given FSM. The function
+  takes as an input an FSM and computes the steady state probabilites. The 
+  function returns a pair of DdNodes. The first bdd_node is an ADD representing
+  the steady state probabilities. The support of the ADD is the present state
+  variables. The second one is an ADD representing the one-step transition 
+  probability matrix. The support of this ADD is both the present state
+  variables and the next state variables.
+
+  The function assumes that the partition of the network representing the 
+  FSM, has vertices corresponding to the next state functions. No check is
+  made regarding this. Hence, this function should be called only after
+  creating BDDs for the next state functions.
+
+  solveMethod is one of Solve_GenMethod_c, Solve_FPMethod_c, Solve_CKMethod_c
+  or Solve_Default_c. Currently only Solve_FPMethod_c is supported. 
+  Solve_Default_c corresponds to Solve_FPMethod_c.
+
+  startMethod is one of Start_Default_c, Start_Reset_c or Start_EquiProb_c.
+  The default method is Start_Reset_c.
+
+  inputProb is a hash table (<name>,<probability>) of primary inputs. If 
+  inputProb is NULL, the primary inputs are assumed to be equi probable.
+  Probability here means the probability of the primary input to be 1.
+
+  roundOff is used to round off the calculations to "roundOff" digits 
+  after the decimal.
+
+  The description of algorithms implemented here can be found in <Ref>.]
+
+  SideEffects [Reachability analysis is done.]
+
+  SeeAlso [Mark_ComputeStateProbsWithTr]
+******************************************************************************/
+bdd_node **
+Mark_FsmComputeStateProbs(
+  Fsm_Fsm_t *fsm,
+  Mark_SolveMethod solveMethod,
+  Mark_StartMethod startMethod,
+  st_table *inputProb,
+  int roundOff)
+{
+    graph_t *partition;
+    bdd_manager *ddManager;
+
+    array_t *tranFunArray, *leaveIds;
+    array_t *nextBdds, *nextMvfs;
+
+    int i, phase;
+    int nVars, nPi;
+
+    bdd_node *tranRelation, **result;
+    bdd_node **xVars,**yVars, **piVars;
+    bdd_node *ddTemp, *reachable;
+
+    mdd_t *reachStates;
+    
+    if (bdd_get_package_name() != CUDD) {
+	(void) fprintf(vis_stderr,"Synthesis package can be used only with CUDD package\n");
+	(void) fprintf(vis_stderr,"Please compile with CUDD package\n");
+	return 0;
+    }
+
+    if (solveMethod == Solve_CKMethod_c ||
+	solveMethod == Solve_GenMethod_c) {
+	fprintf(vis_stdout,"Mark: Solve_CKMethod_c and Solve_GenMethod_c");
+	fprintf(vis_stdout," not implemented yet\n");
+	return NIL(bdd_node *);
+    }
+
+    ddManager = (bdd_manager *)Fsm_FsmReadMddManager(fsm);
+
+    /*
+     * tranFunArray is a list of next state funs.
+     */
+
+    tranFunArray = Fsm_FsmReadNextStateFunctionNames(fsm);
+
+    leaveIds = array_join(Fsm_FsmReadInputVars(fsm),
+			  Fsm_FsmReadPresentStateVars(fsm));
+    /*
+     * Get the BDDs for transition functions.Duplicate functions are returned.
+     */
+    partition = Fsm_FsmReadPartition(fsm);
+    nextMvfs = Part_PartitionBuildFunctions(partition,tranFunArray,leaveIds,
+					    NIL(mdd_t));
+    array_free(leaveIds);
+    array_free(tranFunArray);
+    nextBdds = markGetBddArray(nextMvfs);
+
+    Mvf_FunctionArrayFree(nextMvfs);
+
+    /* Get the DdNodes for all the variables.*/
+
+    piVars = BddNodeArrayFromIdArray(ddManager, 
+					 Fsm_FsmReadInputVars(fsm));
+    xVars = BddNodeArrayFromIdArray(ddManager, 
+					Fsm_FsmReadPresentStateVars(fsm));
+    yVars = BddNodeArrayFromIdArray(ddManager,
+					Fsm_FsmReadNextStateVars(fsm));
+
+    nVars = array_n(Fsm_FsmReadNextStateVars(fsm));
+    nPi = array_n(Fsm_FsmReadInputVars(fsm));
+
+    /* Compute the transition relation */
+    tranRelation = computeTransitionRelationWithIds(ddManager, nextBdds,
+						    yVars, nVars);
+
+    arrayForEachItem(bdd_node *, nextBdds, i, ddTemp) {
+ 	bdd_recursive_deref(ddManager,ddTemp);
+    }
+    array_free(nextBdds);
+
+    /* Compute the reachable states. */
+    reachStates = Fsm_FsmComputeReachableStates(fsm,0,0,0,0,0,0,1000,
+						Fsm_Rch_Default_c,0,0,
+						NIL(array_t),FALSE, NIL(array_t));
+
+    ddTemp = (bdd_node *)bdd_get_node(reachStates,&phase);
+    reachable = phase ?  bdd_not_bdd_node(ddTemp) : ddTemp;
+    bdd_ref(reachable);
+    mdd_free(reachStates);
+
+    /* Restrict the STG to only the reachale states */
+    bdd_ref(ddTemp = bdd_bdd_constrain(ddManager,tranRelation,reachable));
+    bdd_recursive_deref(ddManager,tranRelation);
+    tranRelation = ddTemp;
+    
+    /* Compute the state probabilities */
+    /* result[0] = state probabilities, result[1] = transition prob. matrix */
+    result = Mark_ComputeStateProbsWithTr(ddManager,tranRelation,
+					  reachable,piVars,
+					  xVars,yVars,NIL(bdd_node *),inputProb,
+					  nVars,nPi,roundOff,
+					  solveMethod,startMethod);
+    
+    bdd_recursive_deref(ddManager,tranRelation);
+    bdd_recursive_deref(ddManager,reachable);
+    
+    for(i = 0; i < nVars; i++) {
+	bdd_recursive_deref(ddManager,xVars[i]);
+	bdd_recursive_deref(ddManager,yVars[i]);
+    }
+    for(i = 0 ; i < nPi; i++) {
+	bdd_recursive_deref(ddManager,piVars[i]);
+    }
+    FREE(xVars);
+    FREE(yVars);
+    FREE(piVars);
+        
+    return (result);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the state probabilities of an FSM.]
+
+  Description [Computes the state probabilities of an FSM via Markovian 
+  analysis. Returns a pointer to a pair ADDs if successful; The ADD in index
+  0 represents the steady state probabiliites and the ADD in index 1 represents
+  the one step transition probability matrix. NULL is returned in case of a 
+  failure. 
+
+  TR is the transition relation of the finite state machine. reachable is a
+  BDD of reachable states. piVars, xVars and yVars are the array of primary
+  inputs, present state variables and next state variables. It is optional to
+  specify a set of auxillary variables zVars for internal use. It could be NULL.
+  If specified the size of zVars equals nVars. inputProb is a 
+  hash table (<name>,<probability>) for primary inputs. Probability here means
+  the probability of the primary input to be 1. nVars equal the number of
+  present state variables, nPi the number of primary inputs, roundOff implies
+  the number of digits after decimal to round off the calculations.
+
+  method is one of Solve_GenMethod_c, Solve_FPMethod_c, Solve_CKMethod_c
+  or Solve_Default_c. Currently only Solve_FPMethod_c is supported. 
+  Solve_Default_c corresponds to Solve_FPMethod_c.
+
+  start is one of Start_Default_c, Start_Reset_c or Start_EquiProb_c.
+  The default method is Start_Reset_c.]
+
+  SideEffects [None]
+
+  SeeAlso     [Mark_ComputeStateProbs]
+
+******************************************************************************/
+bdd_node **
+Mark_ComputeStateProbsWithTr(
+  bdd_manager *ddManager,
+  bdd_node *TR,
+  bdd_node *reachable,
+  bdd_node **piVars,
+  bdd_node **xVars,
+  bdd_node **yVars,
+  bdd_node **zVars,
+  st_table *inputProb,
+  int nVars,
+  int nPi,
+  int roundOff,
+  Mark_SolveMethod method,
+  Mark_StartMethod start)
+{
+    CK *ck;
+    bdd_node **piAddVars, **xAddVars, **yAddVars, **zAddVars;
+    bdd_node *rep, *scc;
+    bdd_node **result;
+    st_generator *gen;
+    int i, index;
+    int createdPia, createdXa, createdYa, createdZa;
+    int createdZ;
+    int period;
+
+    /* To suppress Alpha warnings */
+    yAddVars = NIL(bdd_node *);
+    zAddVars = NIL(bdd_node *);
+
+    if (bdd_get_package_name() != CUDD) {
+	(void) fprintf(vis_stderr,"Synthesis package can be used only with CUDD package\n");
+	(void) fprintf(vis_stderr,"Please compile with CUDD package\n");
+	return 0;
+    }
+    
+    createdPia = createdXa = createdYa = createdZa = 0;
+    createdZ = 0;
+
+    piAddVars = ALLOC(bdd_node *, nPi);
+    if (piAddVars == NULL)
+	return NULL;
+    createdPia = 1;
+
+    xAddVars = ALLOC(bdd_node *, nVars);
+    if (xAddVars == NULL)
+	goto endgame;
+    createdXa = 1;
+
+    yAddVars = ALLOC(bdd_node *, nVars);
+    if (yAddVars == NULL)
+	goto endgame;
+    createdYa = 1;
+
+    zAddVars = ALLOC(bdd_node *, nVars);
+    if (zAddVars == NULL)
+	goto endgame;
+    createdZa = 1;
+  
+    if (zVars == NULL) {
+	zVars = ALLOC(bdd_node *, nVars);
+	if (zVars == NULL) 
+	    goto endgame;
+	createdZ = 1;
+	for (i = 0; i < nVars; i++)
+	    bdd_ref(zVars[i] = bdd_bdd_new_var(ddManager));
+    }
+
+    for(i = 0;i < nPi; i++) {
+	index = bdd_node_read_index(piVars[i]);
+	bdd_ref(piAddVars[i] = bdd_add_ith_var(ddManager,index));
+    }
+
+    for(i = 0; i < nVars; i++) {
+	index = bdd_node_read_index(xVars[i]);
+	bdd_ref(xAddVars[i] = bdd_add_ith_var(ddManager,index));
+	index = bdd_node_read_index(yVars[i]);
+	bdd_ref(yAddVars[i] = bdd_add_ith_var(ddManager,index));
+	index = bdd_node_read_index(zVars[i]);
+	bdd_ref(zAddVars[i] = bdd_add_ith_var(ddManager,index));
+    }
+
+    /* Allocate the structure for internal use */
+    ck = ALLOC(CK,1);
+  
+    ck->manager = ddManager;
+    ck->piVars = piVars;
+    ck->xVars = xVars;
+    ck->yVars = yVars;
+    ck->zVars = zVars;
+    ck->piAddVars = piAddVars;
+    ck->xAddVars = xAddVars;
+    ck->yAddVars = yAddVars;
+    ck->zAddVars = zAddVars;
+    ck->coeff = NULL; /* assigned in ckInterface - ADD */
+    ck->nVars = nVars;
+    ck->nPi = nPi;
+    ck->abstol = bdd_read_epsilon(ddManager);
+    ck->scale = 1.0;
+    ck->reltol = 1.0e-4;
+    ck->start = start;
+    ck->roundOff = roundOff;
+    ck->inputProb = inputProb;
+    ck->transition = TR;
+    ck->reached = reachable;
+    ck->indexSCC = NULL;       /* assigned in MarkGetSCC called by recTC */
+    ck->collapsedcoeff = NULL; /* assigned in ckInterface */
+    ck->term_SCC_states = 0;
+    ck->periods = NULL;        /* assigned in bddCollapseTSCC */
+    ck->term_scc = NULL;       /* assigned in ckInterface - ADD */
+    ck->init_guess = NULL;     /* assigned and derefed in all the methods.*/
+
+    ckInterface(ck);
+
+    /* select resolution method */
+    if (method == Solve_CKMethod_c) {
+	fprintf(stdout,"Mark<->Equations' Solver uses CK Method\n");
+	result = MarkAddCKSolve(ck); 
+    } 
+    else if (method == Solve_GenMethod_c) {
+	fprintf(stdout,"Mark<->Equations' Solver uses General Method\n");
+	result = MarkAddGenSolve(ck); 
+    }
+    else {
+	fprintf(stdout,"Mark<->Equations's Solver uses FP Method\n");
+	result = MarkAddFPSolve(ck);
+    }
+
+    /* Clean up */
+    bdd_recursive_deref(ddManager,ck->coeff);
+    st_foreach_item(ck->indexSCC,gen,&rep,&scc) {
+	bdd_recursive_deref(ddManager,rep);
+	bdd_recursive_deref(ddManager,scc);
+    }
+    st_free_table(ck->indexSCC);
+    bdd_recursive_deref(ddManager,ck->collapsedcoeff);
+    st_foreach_item_int(ck->periods,gen,&rep, &period) {
+	bdd_recursive_deref(ddManager,rep);
+    }
+    st_free_table(ck->periods);
+
+    bdd_recursive_deref(ddManager,ck->term_scc);
+
+    for(i = 0; i < nPi; i++) {
+	bdd_recursive_deref(ddManager,piAddVars[i]);
+    }
+
+    for(i = 0; i < nVars; i++) {
+	bdd_recursive_deref(ddManager,xAddVars[i]);
+	bdd_recursive_deref(ddManager,yAddVars[i]);
+	bdd_recursive_deref(ddManager,zAddVars[i]);
+    }
+
+    if (createdZ) {
+	for(i = 0; i < nVars; i++) {
+	    bdd_recursive_deref(ddManager,zVars[i]);
+	}
+	FREE(zVars);
+    }
+    FREE(xAddVars);
+    FREE(yAddVars);
+    FREE(zAddVars);
+    FREE(piAddVars);
+    FREE(ck);
+
+    return result;
+
+endgame:
+    if (createdPia)
+	FREE(piAddVars);
+    if (createdXa)
+	FREE(xAddVars);
+    if (createdYa)
+	FREE(yAddVars);
+    if (createdZa)
+	FREE(zAddVars);
+    if (createdZ)
+	FREE(zVars);
+
+    return NULL;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Not implemented yet.]
+
+  Description [Not implemented yet.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+bdd_node **
+MarkAddCKSolve(
+  CK *ck)
+{
+    (void) fprintf(vis_stdout,"Not implemented yet. \n");
+    return NIL(bdd_node *);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Not implemented yet.]
+
+  Description [Not implemented yet.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+bdd_node **
+MarkAddGenSolve(
+  CK *ck)
+{
+    (void) fprintf(vis_stdout,"Not implemented yet. \n");
+    return NIL(bdd_node *);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Calculate the average bit change in the STG.]
+
+  Description [Calculate the average bit change in the STG. probTR is an ADD
+  representing the absolute transition probability matrix of the STG.
+  xVars and yVars are the present and next state variables respectively. nVars
+  is the number of state variables. 
+
+  average bit change = (\exists^+_x(probTr * HD(x,y))). 
+
+  The interested reader is referred to 
+  
+  R. I. Bahar and E. A. Frohm and C. M. Gaona and G. D. Hachtel and E.
+  Macii and A. Pardo and F. Somenzi, "Algebraic Decision Diagrams and
+  their Applications", International Conference on Computer Aided
+  Design, 1993.
+  
+  on details pertaining to ADDs. ]
+
+  SideEffects [None]
+
+  SeeAlso []
+******************************************************************************/
+double 
+MarkAverageBitChange(
+  bdd_manager *manager,
+  bdd_node *probTR,
+  bdd_node **xVars,
+  bdd_node **yVars,
+  int nVars)
+{
+    bdd_node *diff, *cube, *PA, *QA;
+    bdd_node **vars;
+    double Mean;
+    int i;
+
+    vars = ALLOC(bdd_node *,2*nVars);
+    for (i = 0; i < nVars; i++) {
+	vars[i] = bdd_add_ith_var(manager,bdd_node_read_index(xVars[i]));
+	bdd_ref(vars[i]);
+    }
+    for (i = nVars; i < 2*nVars; i++) {
+	vars[i] = bdd_add_ith_var(manager,bdd_node_read_index(yVars[i-nVars]));
+	bdd_ref(vars[i]);
+    }
+
+    cube = bdd_add_compute_cube(manager,vars,NULL,2*nVars);
+    bdd_ref(cube);
+
+    /* Calculate the Hamming distance ADD. This ADD represents the hamming
+     * distance between two vectors represented by xVars and yVars.
+     */
+    bdd_ref(diff = bdd_add_hamming(manager,xVars,yVars,nVars));
+    bdd_ref(PA = bdd_add_apply(manager,bdd_add_times,probTR,diff));
+    bdd_recursive_deref(manager,diff);
+  
+    /* And now add and abstract all the variables.*/
+    bdd_ref(QA = bdd_add_exist_abstract(manager,PA,cube));
+    bdd_recursive_deref(manager,PA);
+    bdd_recursive_deref(manager,cube);
+    Mean = (double)bdd_add_value(QA);
+    bdd_recursive_deref(manager,QA); 
+
+    for (i = 0; i < 2*nVars; i++) {
+	bdd_recursive_deref(manager,vars[i]);
+    }
+    FREE(vars);
+    return Mean;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis           [Perform structural decomposition of the markov chain.]
+
+  Description        []
+
+  SideEffects        [The data structure ck is changed.]
+
+  SeeAlso            []
+
+******************************************************************************/
+static void
+ckInterface(
+  CK *ck)
+{
+    bdd_manager *ddManager;
+    bdd_node *piCube;
+    bdd_node *new_;
+    bdd_node *tmp1,*tmp2;
+    bdd_node *p, *t;
+    bdd_node *reachable, *TR;
+    bdd_node *q, *r;
+    st_table *newSCC;
+    st_table *newperiods;
+    st_generator *gen;
+    int	len, nVars;
+
+    ddManager = ck->manager;
+    reachable = ck->reached;
+    TR = ck->transition;
+    nVars = ck->nVars;
+
+    bdd_ref(piCube = bdd_bdd_compute_cube(ddManager,ck->piVars,NULL,ck->nPi));
+    /* abstract the PI variables for the SCC computation */
+    bdd_ref(new_ = bdd_bdd_exist_abstract(ddManager,TR,piCube));
+    bdd_recursive_deref(ddManager,piCube);
+
+    /* now find the set of nodes in terminal SCC's */
+    p = recTC(ck,new_);
+    bdd_recursive_deref(ddManager,new_);
+
+    /* Collapse the TSCC in the graph */
+    ck->collapsedcoeff = bddCollapseTSCC(ck);
+    bdd_ref(ck->collapsedcoeff);
+
+    /* retain only reachable terminal SCC's */
+    bdd_ref(t = bdd_bdd_and(ddManager,p,reachable));
+    bdd_recursive_deref(ddManager,p);
+
+    /* count the number of states in the terminal SCC's */
+    ck->term_SCC_states = bdd_count_minterm(ddManager,t,nVars);
+    (void) fprintf(vis_stdout,"# of states in TSCCs = %f\n",
+		   ck->term_SCC_states);
+
+    /* Translate the data in ck->collapsedcoeff and 
+     * ck->indexSCC from BDDs to ADDs.
+     */
+
+    newSCC = st_init_table(st_ptrcmp,st_ptrhash);
+    newperiods = st_init_table(st_ptrcmp,st_ptrhash);
+    st_foreach_item(ck->indexSCC,gen,&tmp1,&tmp2) {
+	bdd_ref(q = bdd_bdd_to_add(ddManager,tmp1));
+	bdd_ref(r = bdd_bdd_to_add(ddManager,tmp2));
+	st_lookup_int(ck->periods,(char *)tmp1, &len);
+	st_insert(newSCC,(char *)q,(char *)r);
+	st_insert(newperiods,(char *)q,(char *)(long)len);
+	bdd_recursive_deref(ddManager,tmp1);
+	bdd_recursive_deref(ddManager,tmp2);
+    }
+    st_free_table(ck->indexSCC);
+    st_free_table(ck->periods);
+    bdd_ref(q = bdd_bdd_to_add(ddManager,ck->collapsedcoeff));
+    bdd_recursive_deref(ddManager,ck->collapsedcoeff);
+    ck->collapsedcoeff = q;
+    ck->indexSCC = newSCC;
+    ck->periods = newperiods;
+
+    /* Print the number of TSCCs */
+    (void) fprintf(vis_stdout,"# of TSCCs = %d\n",st_count(newSCC));
+
+    /* convert the transition relation BDD into an ADD */
+    bdd_ref(q = bdd_bdd_to_add(ddManager,TR));
+    ck->coeff = q;
+
+    /* convert the term_scc set BDD into an ADD */
+    bdd_ref(q = bdd_bdd_to_add(ddManager,t));
+    ck->term_scc = q;
+    bdd_recursive_deref(ddManager,t);
+
+} /* End of ckInterface */
+
+/**Function********************************************************************
+
+  Synopsis           [Compute the strongly connected components.]
+
+  Description        []
+
+  SideEffects        [ck->indexSCC changed.]
+
+  SeeAlso            []
+
+******************************************************************************/
+static bdd_node * 
+recTC(
+  CK *ck,
+  bdd_node *tr)
+{
+
+    bdd_manager *manager = ck->manager;
+    bdd_node **xVars, **yVars, **zVars;
+    bdd_node *closure;
+    bdd_node *lastScc;
+    int nVars;
+
+    xVars = ck->xVars;
+    yVars = ck->yVars;
+    zVars = ck->zVars;
+    nVars = ck->nVars;
+
+    /* Matsunaga's procedure could also be used. Will have to implement it
+     * later.
+     */ 
+    
+    closure = transitiveClosureByIterSquaring(manager,tr,xVars,yVars,zVars, 
+					      nVars);
+    bdd_ref(closure);
+    lastScc = MarkGetSCC(manager,tr,closure,ck->reached,
+		     xVars, yVars, nVars, &(ck->indexSCC));
+
+    bdd_recursive_deref(manager,closure);
+
+    return(lastScc);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [Computes the transitive closure by iterative squaring.]
+
+  Description        []
+
+  SideEffects        [None]
+
+  SeeAlso            []
+
+******************************************************************************/
+static bdd_node *
+transitiveClosureByIterSquaring(
+  bdd_manager *ddManager,
+  bdd_node *TR,
+  bdd_node **xVars,
+  bdd_node **yVars,
+  bdd_node **zVars,
+  int nVars)
+{
+    bdd_node *prev, *next, *TRxz, *TRzy;
+    bdd_node *inter;
+    bdd_node *zCube;
+  
+    bdd_ref(zCube = bdd_bdd_compute_cube(ddManager,zVars,NULL,nVars));
+
+    bdd_ref(prev = TR);
+    while(1) {
+	TRxz = bdd_bdd_swap_variables(ddManager,prev,yVars,zVars,nVars);
+	bdd_ref(TRxz);
+	TRzy = bdd_bdd_swap_variables(ddManager,prev,xVars,zVars,nVars);
+	bdd_ref(TRzy);
+	inter = bdd_bdd_and_abstract(ddManager,TRxz,TRzy,zCube);
+	bdd_ref(inter);
+	bdd_recursive_deref(ddManager,TRxz);
+	bdd_recursive_deref(ddManager,TRzy);
+	next = bdd_bdd_or(ddManager,TR,inter);
+	bdd_ref(next);
+	bdd_recursive_deref(ddManager,inter);
+	if(prev == next)
+	    break;
+	bdd_recursive_deref(ddManager,prev);
+	prev = next;
+    }
+    bdd_recursive_deref(ddManager,zCube);
+    bdd_recursive_deref(ddManager,prev);
+    bdd_deref(next);
+    return next;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [Collapse the Terminal SCCs into a macro node.]
+
+  Description        []
+
+  SideEffects        [ck->periods is changed.]
+
+  SeeAlso            []
+
+******************************************************************************/
+static bdd_node *
+bddCollapseTSCC(
+  CK *ck)
+{
+    bdd_manager *manager = ck->manager;
+    bdd_node *tmp1,*tmp2;
+    bdd_node *repr,*scc,*restscc;
+    bdd_node *newtr;
+    bdd_node *xCube,*yCube;
+    bdd_node *sccfanout,*sccfanin;
+    st_generator *gen;
+    int i;
+
+    bdd_ref(xCube = bdd_bdd_compute_cube(manager,ck->xVars,NULL,ck->nVars));
+    bdd_ref(yCube = bdd_bdd_compute_cube(manager,ck->yVars,NULL,ck->nVars));
+
+    ck->periods = st_init_table(st_ptrcmp,st_ptrhash);
+  
+    bdd_ref(newtr = ck->transition);
+    i = 0;
+    st_foreach_item(ck->indexSCC,gen,&repr,&scc) {
+	/* Traverse the SCC to obtain the period */
+	st_insert(ck->periods,(char *)repr,(char *)(long)sccGetPeriod(ck,repr));
+      
+	/* Add edges from scc to the representatives in the fanout */
+	bdd_ref(sccfanout = bdd_bdd_and_abstract(manager,newtr,scc,xCube));
+      
+	bdd_ref(tmp1 = bdd_bdd_and(manager,scc,sccfanout));
+	bdd_recursive_deref(manager,sccfanout);
+	bdd_ref(tmp2 = bdd_bdd_or(manager,newtr,tmp1));
+	bdd_recursive_deref(manager,tmp1);
+	bdd_recursive_deref(manager,newtr);
+	newtr = tmp2;
+      
+	/* Add edges from fanin to representative */
+	bdd_ref(tmp2 = bdd_bdd_swap_variables(manager,scc,ck->xVars,ck->yVars,
+					      ck->nVars));
+	bdd_ref(sccfanin = bdd_bdd_and_abstract(manager,newtr,tmp2,yCube));
+	bdd_recursive_deref(manager,tmp2);
+      
+	/* Add edges (fanin,representative) to the TR */
+	bdd_ref(tmp1 = bdd_bdd_swap_variables(manager,repr,ck->xVars,
+					      ck->yVars,ck->nVars));
+	bdd_ref(tmp2 = bdd_bdd_and(manager,sccfanin,tmp1));
+	bdd_recursive_deref(manager,tmp1);
+	bdd_recursive_deref(manager,sccfanin);
+	bdd_ref(tmp1 = bdd_bdd_or(manager,newtr,tmp2));
+	bdd_recursive_deref(manager,tmp2);
+	bdd_recursive_deref(manager,newtr);
+	newtr = tmp1;
+      
+	/*Delete the edges that go to the non-representative nodes */
+	bdd_ref(restscc = bdd_bdd_and(manager,scc,bdd_not_bdd_node(repr)));
+      
+	bdd_ref(tmp1 = bdd_bdd_and(manager,newtr,bdd_not_bdd_node(restscc)));
+	bdd_ref(tmp2 = bdd_bdd_swap_variables(manager,restscc,ck->xVars,
+					    ck->yVars,ck->nVars));
+	bdd_recursive_deref(manager,restscc);
+	bdd_recursive_deref(manager,newtr);
+	bdd_ref(newtr = bdd_bdd_and(manager,tmp1,bdd_not_bdd_node(tmp2)));
+	bdd_recursive_deref(manager,tmp1);
+	bdd_recursive_deref(manager,tmp2);
+      
+	i++;
+    }
+  
+    bdd_recursive_deref(manager,xCube);
+    bdd_recursive_deref(manager,yCube);
+  
+    bdd_deref(newtr);
+    return(newtr);
+}
+
+/**Function********************************************************************
+
+  Synopsis           [Compute the period of the SCC.]
+
+  Description        []
+
+  SideEffects        [None]
+
+  SeeAlso            []
+
+******************************************************************************/
+static int
+sccGetPeriod(
+  CK *ck,
+  bdd_node *reset)
+{
+
+    bdd_manager *manager = ck->manager;
+    bdd_node *new_,*from;
+    bdd_node *tmp1;
+    bdd_node *xCube, *inputCube;
+    bdd_node *transition;
+    int pos,result = 0;
+    int depth;
+    int stop = 0; 
+    st_table *tos;
+    st_generator *gen;
+  
+    /* Calculate the cube for abstraction */
+
+    bdd_ref(xCube = bdd_bdd_compute_cube(manager,ck->xVars,NULL,ck->nVars));
+    bdd_ref(inputCube = bdd_bdd_compute_cube(manager,ck->piVars,NULL,ck->nPi));
+    bdd_ref(transition = bdd_bdd_exist_abstract(manager,ck->transition,
+						inputCube));
+    bdd_recursive_deref(manager,inputCube);
+  
+    depth = 0;
+    bdd_ref(from = reset);
+    bdd_ref(tmp1 = reset);
+    tos = st_init_table(st_ptrcmp,st_ptrhash);
+    depth++;
+    st_insert(tos,(char *)tmp1,(char *)(long)depth);
+
+    while(!stop) {
+	bdd_ref(tmp1 = bdd_bdd_and_abstract(manager,from,transition,xCube));
+	bdd_ref(new_ = bdd_bdd_swap_variables(manager,tmp1,ck->yVars,ck->xVars,
+					     ck->nVars));
+	bdd_recursive_deref(manager,tmp1);
+      
+	if((stop = st_lookup_int(tos,(char *)new_, &pos)))
+	    result = depth - pos;
+	else
+	    st_insert(tos,(char *)new_,(char *)(long)depth);
+	
+	bdd_recursive_deref(manager,from);
+	bdd_ref(from = new_);
+	depth++;
+    }
+
+    bdd_recursive_deref(manager,new_);
+    bdd_recursive_deref(manager,xCube);
+    bdd_recursive_deref(manager,from);
+
+    st_foreach_item_int(tos,gen,&new_, &pos) {
+	bdd_recursive_deref(manager,new_);
+    }
+    st_free_table(tos);
+
+    return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns a BDD array from an Mvf array]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static array_t *
+markGetBddArray(array_t *mvfArray)
+{
+    int 	  i,phase;
+    array_t *bddArray;
+    Mvf_Function_t *mvf;
+
+    bddArray = array_alloc(bdd_node *,0);
+
+    arrayForEachItem(Mvf_Function_t *, mvfArray,i,mvf) {
+	mdd_t     *mddTemp;
+	bdd_node    *ddNode;
+
+	mddTemp = array_fetch(mdd_t *, mvf, 1);
+	ddNode = (bdd_node *) bdd_get_node(mddTemp,&phase);
+	bdd_ref(ddNode);
+
+	ddNode = phase ? bdd_not_bdd_node(ddNode) : ddNode;
+	array_insert_last(bdd_node *, bddArray, ddNode);
+    }
+    return bddArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Returns a BDD array given an integer array of variable indices.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static bdd_node **
+BddNodeArrayFromIdArray(
+  bdd_manager	*ddManager,
+  array_t	*idArray)
+{
+    bdd_node **xvars;
+    int i,id;
+    int nvars = array_n(idArray);
+
+    xvars = ALLOC(bdd_node *, nvars);
+    if (xvars == NULL)
+	return NULL;
+
+    for(i = 0; i < nvars; i++) {
+	id = array_fetch(int,idArray,i);
+	xvars[i] = bdd_bdd_ith_var(ddManager,id);
+	bdd_ref(xvars[i]);
+    }
+    return xvars;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Compute the relation between an array of function and a 
+  corresponding array of variables. A BDD is returned which represents
+  AND(i=0 -> i<nVars)(yVars[i]==nextBdds). ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static bdd_node *
+computeTransitionRelationWithIds(
+  bdd_manager	*ddManager,
+  array_t	*nextBdds,
+  bdd_node	**yVars,
+  int		nVars)
+{
+    bdd_node	*ddtemp1, *ddtemp2;
+    bdd_node	*oldTR, *fn;
+    int 		 i;
+
+
+    oldTR = bdd_read_one(ddManager);
+
+    for(i = 0; i < nVars; i++) {
+	ddtemp2  = array_fetch(bdd_node *, nextBdds, i);
+
+	fn = bdd_bdd_xnor(ddManager,ddtemp2,yVars[i]);
+	bdd_ref(fn);
+	ddtemp1 = bdd_bdd_and(ddManager,oldTR,fn);
+	bdd_ref(ddtemp1);
+	bdd_recursive_deref(ddManager,fn);
+	bdd_recursive_deref(ddManager,oldTR);
+	oldTR = ddtemp1;
+    }
+
+    return oldTR;
+}
+
Index: vis_dev/vis-2.3/src/mark/mark.h
===================================================================
--- vis_dev/vis-2.3/src/mark/mark.h	(revision 14)
+++ vis_dev/vis-2.3/src/mark/mark.h	(revision 14)
@@ -0,0 +1,102 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [mark.h]
+
+  PackageName [mark]
+
+  Synopsis    [Data structures used in Markovian analysis.]
+
+  Description [Data structures used in Markovian analysis.]
+
+  SeeAlso     [markInt.h]
+
+  Author      [Balakrishna Kumthekar]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+#ifndef _MARK
+#define _MARK
+
+#include "fsm.h"
+#include "util.h"
+#include "st.h"
+#include "bdd.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Enum************************************************************************
+
+  Synopsis    [Different methods of solving for steady state probabilities.
+  For more details consult 
+  
+  G. D. Hachtel, E. Macii, A. Pardo and F. Somenzi, "Markovian Analysis
+  of Large Finite State Machines", IEEE Trans. on CAD, December 1996.  ]
+
+  SeeAlso     [Mark_StartMethod]
+
+******************************************************************************/
+typedef enum {
+  Solve_Default_c,  /* Default method. It is Solve_FPMethod_c. */
+  Solve_GenMethod_c,
+  Solve_FPMethod_c, /* This is the only one that is currently supported */
+  Solve_CKMethod_c
+} Mark_SolveMethod;
+
+
+/**Enum************************************************************************
+
+  Synopsis    [Different methods of chosing the reset state. For more details
+  consult 
+
+  G. D. Hachtel, E. Macii, A. Pardo and F. Somenzi, "Markovian Analysis
+  of Large Finite State Machines", IEEE Trans. on CAD, December 1996.]
+
+  SeeAlso     [Markov_SolveMethod]
+
+******************************************************************************/
+typedef enum {
+  Start_Default_c,  /* Default method. It is Start_Reset_c. */
+  Start_Reset_c,
+  Start_EquiProb_c
+} Mark_StartMethod;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN bdd_node ** Mark_FsmComputeStateProbs(Fsm_Fsm_t *fsm, Mark_SolveMethod solveMethod, Mark_StartMethod startMethod, st_table *inputProb, int roundOff);
+EXTERN bdd_node ** Mark_ComputeStateProbsWithTr(bdd_manager *ddManager, bdd_node *TR, bdd_node *reachable, bdd_node **piVars, bdd_node **xVars, bdd_node **yVars, bdd_node **zVars, st_table *inputProb, int nVars, int nPi, int roundOff, Mark_SolveMethod method, Mark_StartMethod start);
+EXTERN bdd_node * Mark_addInProb(bdd_manager *manager, bdd_node *tr, bdd_node *cube, st_table *probTable);
+EXTERN void Mark_Init(void);
+EXTERN void Mark_End(void);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _MARK */
Index: vis_dev/vis-2.3/src/mark/mark.make
===================================================================
--- vis_dev/vis-2.3/src/mark/mark.make	(revision 14)
+++ vis_dev/vis-2.3/src/mark/mark.make	(revision 14)
@@ -0,0 +1,5 @@
+CSRC += mark.c markFPSolve.c markGetScc.c markInProb.c
+
+HEADERS += mark.h markInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/mark/markFPSolve.c
===================================================================
--- vis_dev/vis-2.3/src/mark/markFPSolve.c	(revision 14)
+++ vis_dev/vis-2.3/src/mark/markFPSolve.c	(revision 14)
@@ -0,0 +1,248 @@
+/**CFile***********************************************************************
+
+  FileName    [markFPSolve.c]
+
+  PackageName [mark]
+
+  Synopsis    [This file contains functions that implement the fixed point
+  method. For more details please refer 
+  
+  G. D. Hachtel, E. Macii, A. Pardo and F. Somenzi, "Markovian Analysis
+  of Large Finite State Machines", IEEE Trans. on CAD, December 1996.  ]
+
+  Description [This file contains functions that implement the fixed point
+  method. For more details please refer
+  
+  G. D. Hachtel, E. Macii, A. Pardo and F. Somenzi, "Markovian Analysis
+  of Large Finite State Machines", IEEE Trans. on CAD, December 1996.  ]
+
+  Author      [Balakrishna Kumthekar]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "markInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Computes steady state probabilities vis fixed point method.]
+
+  Description [Computes steady state probabilities via fixed point method.
+  The function returns an array of two ADDs. The ADD with index 0, represents
+  the steady state probabilities and the second one the one-step transition
+  probability matrix.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+bdd_node ** 
+MarkAddFPSolve(
+  CK *ck)
+{
+    bdd_manager *manager;
+    bdd_node **xAddVars, **yAddVars;
+    bdd_node *Scaling;
+    bdd_node *InitG, *G, *NewG;
+    bdd_node *p, *q, *newTr;
+    bdd_node *xCube, *ddTemp, *guess; 
+    bdd_node *zero;
+    bdd_node **result;
+    bdd_node *probMatrix;
+    int nVars, iter = 0;
+    int converged;
+    double max;
+
+    manager = ck->manager;
+    nVars = ck->nVars;
+    xAddVars = ck->xAddVars;
+    yAddVars = ck->yAddVars;
+
+    result = ALLOC(bdd_node *, 2);
+    if (result == NULL)
+	return NULL;
+    zero = bdd_read_zero(manager);
+
+    /* Build an ADD for one step transition probability matrix */
+    bdd_ref(probMatrix = MarkAddBuildCoeff(manager,ck->coeff, ck->piAddVars,
+					    ck->inputProb, ck->scale, nVars,
+					    ck->nPi));
+    result[1] = probMatrix;
+
+    /* create initial guess and print it;
+     * equiprobability to all the states and probability 1 to one of the
+     * reset states are currently supported
+     */
+    switch(ck->start) {
+    case Start_EquiProb_c:
+	(void)printf("Initial guess: equiprob\n");
+	bdd_ref(ck->init_guess = ck->term_scc);
+	p = bdd_add_const(manager,
+			  (double) (1/(double)(ck->term_SCC_states)));
+	bdd_ref(p);
+	bdd_ref(q = bdd_add_ite(manager,ck->init_guess,p,zero)); 
+	bdd_recursive_deref(manager,p);
+	InitG = bdd_add_swap_variables(manager,q,xAddVars,yAddVars,nVars);
+	bdd_ref(InitG);
+	bdd_recursive_deref(manager,q);
+	bdd_recursive_deref(manager,ck->init_guess);
+	break;
+    case Start_Reset_c:
+    default:
+	/* Pick one of the states in the TSCC as the initial guess */
+	bdd_ref(ddTemp = bdd_add_bdd_threshold(manager,ck->term_scc,1));
+	bdd_ref(guess = bdd_bdd_pick_one_minterm(manager, ddTemp,
+					     ck->xVars, nVars));
+	bdd_recursive_deref(manager,ddTemp);
+	bdd_ref(ck->init_guess = bdd_bdd_to_add(manager,guess));
+	bdd_recursive_deref(manager,guess);
+	bdd_ref(InitG = bdd_add_swap_variables(manager,ck->init_guess,
+					       xAddVars, yAddVars,nVars));
+	bdd_recursive_deref(manager,ck->init_guess);
+	break;
+    }
+
+    /* put prob. transition matrix in appropriate form (transpose)*/
+    newTr = bdd_add_swap_variables(manager,probMatrix,xAddVars,yAddVars,nVars);
+    bdd_ref(newTr);
+
+    /* calculate the x-cube for abstraction */
+    bdd_ref(xCube = bdd_add_compute_cube(manager,xAddVars,NULL,nVars));
+ 
+    do {
+	iter++;
+	G = bdd_add_matrix_multiply(manager,newTr,InitG,yAddVars,nVars);
+	bdd_ref(G);
+        bdd_ref(Scaling = bdd_add_exist_abstract(manager,G,xCube));
+
+	bdd_ref(NewG = bdd_add_apply(manager,bdd_add_divide,G,Scaling));
+	bdd_recursive_deref(manager,G);
+	G = NewG; 
+	bdd_recursive_deref(manager,Scaling);
+	q = bdd_add_swap_variables(manager,G,xAddVars,yAddVars,nVars);
+	bdd_ref(q);
+	max = bdd_add_value(bdd_add_find_max(manager,InitG));
+	converged = bdd_equal_sup_norm(manager,q,InitG,ck->reltol*max,0);
+	bdd_recursive_deref( manager,InitG);
+	if (converged) {
+	    (void) fprintf(vis_stdout,"Iteration = %d\n",iter);
+	    bdd_recursive_deref( manager,newTr);
+	    bdd_recursive_deref( manager,q);
+	    bdd_recursive_deref(manager,xCube);
+	    result[0] = G;
+	    return result;
+	}
+	bdd_recursive_deref( manager,G);
+	InitG = q;
+    } while (1);
+
+} /* end of addFPSolve */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds the one-step transition probability matrix given primary
+  input probabilities and 0-1 ADD transition relation.]
+
+  Description [Builds the one-step transition probability matrix given primary
+  input probabilities and 0-1 ADD transition relation.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+bdd_node *
+MarkAddBuildCoeff(
+  bdd_manager *manager,
+  bdd_node *func,
+  bdd_node **piAddVars,
+  st_table *inputProb,
+  double scale,
+  int nVars,
+  int nPi)
+{
+    /* Given func, the coefficient matrix is built */
+    /* this function is used first to build the collapsed coeff matrix */
+    /* and then the matrix for every TSCC */
+
+    bdd_node *Correction;
+    bdd_node *q;
+    bdd_node *matrix;
+    bdd_node *piAddCube;
+
+    bdd_ref(piAddCube = bdd_add_compute_cube(manager,piAddVars,NULL,nPi));
+
+    /* Create the transition matrix either with equiprobable
+       or specific input probs. */
+
+    if (inputProb != NULL) {
+      bdd_ref(matrix = Mark_addInProb(manager,func,piAddCube,inputProb));
+    }
+    else {
+      /* create correction ADD and print it */
+      bdd_ref(Correction = bdd_add_const(manager,
+					  (scale/(double)(1 << nPi))));
+      
+      bdd_ref(q = bdd_add_exist_abstract(manager,func,piAddCube));
+      
+      /* apply correction to the transition relation matrix and print it */
+      bdd_ref(matrix = bdd_add_apply(manager, bdd_add_times,q, Correction));
+      bdd_recursive_deref( manager,Correction);
+      bdd_recursive_deref(manager,q);
+    }
+    bdd_recursive_deref(manager,piAddCube);
+    bdd_deref(matrix);
+    return(matrix);
+}
+
+
Index: vis_dev/vis-2.3/src/mark/markGetScc.c
===================================================================
--- vis_dev/vis-2.3/src/mark/markGetScc.c	(revision 14)
+++ vis_dev/vis-2.3/src/mark/markGetScc.c	(revision 14)
@@ -0,0 +1,255 @@
+/**CFile***********************************************************************
+
+  FileName    [markGetScc.c]
+
+  PackageName [mark]
+
+  Synopsis    [Functions to compute terminal strongly connected components
+  in a markov chain.]
+
+  Description [Functions to compute terminal strongly connected components
+  in a markov chain.]
+
+  Author      [Balakrishna Kumthekar]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "markInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static bdd_node * pickOneCube(bdd_manager *manager, bdd_node *node, bdd_node **xVars, int nVars);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Computes terminal strongly connected components of a
+  markov chain.]
+
+  Description [Computes terminal strongly connected components of a
+  markov chain. tr is the transition relation, tc represents the transitive
+  closure. xVars are the present state variables, yVars the next state
+  variables.]
+
+  SideEffects [scc_table is modified.]
+
+  SeeAlso []
+
+******************************************************************************/
+bdd_node *
+MarkGetSCC(
+  bdd_manager *manager,
+  bdd_node *tr,
+  bdd_node *tc,
+  bdd_node *reached,
+  bdd_node **xVars,
+  bdd_node **yVars,
+  int nVars,
+  st_table **scc_table)
+
+{
+    bdd_node *zero = bdd_read_logic_zero(manager);
+    bdd_node *cr,	        /* Cycle relation */
+	*ee,	        /* Exterior edges relation, edges between SCCs */
+	*nofanout,	/* Nodes without fanout outside the SCC */
+	*nocycle,	/* Nodes that are not in any cycle */
+	*tnofanout,     /* Temporary nodes without fanout when
+			 * decomposing into SCCs.
+			 */
+	*cub,	        /* Arbitrary cube picked inside the SCC */
+	*scc,	        /* States in the current SCC */
+	*tmp1,*tmp2;   
+    bdd_node *yCube;
+    bdd_node **permutArray;
+    int i, size;
+  
+
+    /* Build the cycle relation CR(x,y) = TC(x,y)*TC(y,x) */
+    /* tmp1 = tc(y,x) -- retain it to use later in edge relation */
+    bdd_ref(tmp1 = bdd_bdd_swap_variables(manager,tc,xVars,yVars,nVars));
+    bdd_ref(cr = bdd_bdd_and(manager,tc,tmp1));
+  
+    /* Break into SCCs */
+    *scc_table = st_init_table(st_ptrcmp,st_ptrhash);
+  
+    /* Build the exterior edge relation EE(x,y) = tTC(x,y)*tTC'(y,x) */
+    bdd_ref(ee = bdd_bdd_and(manager,tc,bdd_not_bdd_node(tmp1)));
+    bdd_recursive_deref(manager,tmp1);
+  
+    /* Calculate nodes without outgoing edges out the SCCS */
+    bdd_ref(yCube = bdd_bdd_compute_cube(manager,yVars,NULL,nVars));
+    bdd_ref(tmp2 = bdd_bdd_exist_abstract(manager,ee,yCube));
+    bdd_ref(tmp1 = bdd_bdd_and(manager,bdd_not_bdd_node(tmp2),reached));
+    bdd_recursive_deref(manager,tmp2);
+    bdd_recursive_deref(manager,ee);
+    nofanout = tmp1;
+
+    /* Detect the Single SCCs ( SSCCs ) */
+    bdd_ref(tmp2 = bdd_bdd_and(manager,nofanout,cr));
+    bdd_ref(tmp1 = bdd_bdd_exist_abstract(manager,tmp2,yCube));
+    bdd_recursive_deref(manager,tmp2);
+    bdd_ref(nocycle = bdd_bdd_and(manager,nofanout,bdd_not_bdd_node(tmp1)));
+    bdd_recursive_deref(manager,tmp1);
+
+    bdd_recursive_deref(manager,yCube);
+  
+    /* Given the nofanout nodes, expand the SCCs that are inside */
+    bdd_ref(tnofanout = bdd_bdd_and(manager,nofanout,bdd_not_bdd_node(nocycle)));
+    bdd_recursive_deref(manager,nocycle);
+
+    size = bdd_num_vars(manager);
+    permutArray = ALLOC(bdd_node *, size);
+    for(i = 0; i < size; i++) {
+	permutArray[i] = bdd_bdd_ith_var(manager,i);
+	bdd_ref(permutArray[i]);
+    }
+    for(i = 0; i < nVars; i++) {
+	int yindex;
+    
+	yindex = bdd_node_read_index(yVars[i]);
+	bdd_recursive_deref(manager,permutArray[yindex]);
+	bdd_ref(permutArray[yindex] = xVars[i]);
+    }
+
+    /* While there are still nodes in the set tnofanout */
+    while(tnofanout != zero) {
+      
+	/* Pick a point inside the nofanout set */
+	bdd_ref(cub = pickOneCube(manager,tnofanout,xVars,nVars));
+
+	/* Obtain the points connected to "cube" by a cycle and 
+	 * rename variables.
+	 */
+
+	bdd_ref(tmp1 = bdd_bdd_constrain(manager,cr,cub));
+
+	bdd_ref(tmp2 = bdd_bdd_vector_compose(manager,tmp1,permutArray));
+	bdd_recursive_deref(manager,tmp1);
+
+	/* Add the cube to the set, because may be it is not in it */
+	bdd_ref(scc = bdd_bdd_or(manager,tmp2,cub));
+	bdd_recursive_deref(manager,tmp2);
+	st_insert(*scc_table,(char *)cub,(char *)scc);
+
+	/* Delete the SCC from the points without fanout */
+	bdd_ref(tmp2 = bdd_bdd_and(manager,tnofanout,bdd_not_bdd_node(scc)));
+	bdd_recursive_deref(manager,tnofanout);
+	tnofanout = tmp2; 
+    }
+  
+    for(i = 0; i < size; i++) {
+	bdd_recursive_deref(manager,permutArray[i]);
+    }
+    FREE(permutArray);
+    bdd_recursive_deref(manager,tnofanout);
+    bdd_recursive_deref(manager,cr);
+  
+    return(nofanout);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static   functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Randomly picks a cube from a given function.]
+
+  Description [Randomly picks a cube from a given function.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static bdd_node *
+pickOneCube(
+  bdd_manager *manager,
+  bdd_node *node,
+  bdd_node **xVars,
+  int nVars)
+{
+    char *string;
+    int i, size;
+    int *indices;
+    bdd_node *old, *new_;
+  
+    size = bdd_num_vars(manager);
+    indices = ALLOC(int,nVars);
+    string = ALLOC(char,size);
+    if(! bdd_bdd_pick_one_cube(manager,node,string)) {
+	fprintf(stdout,"mark<->MarkPickOneCube: could not pick a cube\n");
+	exit(-1);
+    }
+    for (i = 0; i < nVars; i++) {
+	indices[i] = bdd_node_read_index(xVars[i]);
+    }
+
+    bdd_ref(old = bdd_read_one(manager));
+
+    for (i = 0; i < nVars; i++) {
+	switch(string[indices[i]]) {
+	case 0:
+	    bdd_ref(new_ = bdd_bdd_and(manager,old,bdd_not_bdd_node(xVars[i])));
+	    bdd_recursive_deref(manager,old);
+	    old = new_;
+	    break;
+	case 1:
+	    bdd_ref(new_ = bdd_bdd_and(manager,old,xVars[i]));
+	    bdd_recursive_deref(manager,old);
+	    old = new_;
+	    break;
+	}
+    }
+    FREE(string);
+    FREE(indices);
+    bdd_deref(old);
+    return old;
+}
+
+
Index: vis_dev/vis-2.3/src/mark/markInProb.c
===================================================================
--- vis_dev/vis-2.3/src/mark/markInProb.c	(revision 14)
+++ vis_dev/vis-2.3/src/mark/markInProb.c	(revision 14)
@@ -0,0 +1,259 @@
+/**CFile***********************************************************************
+
+  FileName    [markInProb.c]
+
+  PackageName [mark]
+
+  Synopsis    [Computation of transition probability matrix and convergence
+  checks in markov analysis.]
+
+  Description [[Computation of transition probability matrix and convergence
+  checks in markov analysis.]
+
+  Author      [Balakrishna Kumthekar]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "markInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Computes one-step transition probability matrix given the 0-1
+  ADD of transition relation and a table of primary input probabiliites.]
+
+  Description [Computes one-step transition probability matrix given the 0-1
+  ADD of transition relation and a table of primary input probabiliites. tr is
+  the 0-1 ADD, cube is a cube of primary inputs and probTable is a hash table
+  that stores (<mdd_id>,<probability of x = 1>). The function returns the ADD
+  for one-step transition probability matrix.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+bdd_node *
+Mark_addInProb(
+  bdd_manager *manager,
+  bdd_node *tr,
+  bdd_node *cube,
+  st_table *probTable)
+{
+    st_table *visited;
+    st_generator *gen;
+    bdd_node *result, *r, *k;
+
+    do {
+	bdd_set_reordered_field(manager, 0);
+	visited = st_init_table(st_ptrcmp,st_ptrhash);
+	bdd_ref(result = bdd_read_one(manager));
+	st_insert(visited,(char *)result,(char *)result);
+	bdd_ref(result = bdd_read_zero(manager));
+	st_insert(visited,(char *)result,(char *)result);
+	result = MarkAddInProbRecur(manager,tr,cube,probTable,visited);
+	if (result)
+	  bdd_ref(result);
+	st_foreach_item(visited,gen,&k,&r) {
+	    bdd_recursive_deref(manager,r);
+	}
+	st_free_table(visited);
+    } while (bdd_read_reordered_field(manager) == 1);
+    
+    bdd_deref(result);
+    return(result);
+
+} /* end of Mark_addInProb */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the recursive step of Mark_addInProb.]
+
+  Description [Implements the recursive step of Mark_addInProb.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+bdd_node *
+MarkAddInProbRecur(
+  bdd_manager *manager,
+  bdd_node *tr,
+  bdd_node *cube,
+  st_table *probTable,
+  st_table *visited)
+{
+    int topTR,topC;
+    int index;
+    double *prob;
+    bdd_node *solT,*solE;
+    bdd_node *solPT,*solPE;
+    bdd_node *result;
+    bdd_node *unique;
+
+    /* lookup in the cache */
+    if(st_lookup(visited,tr,&result)) 
+	return(result);
+
+    /* the cube is one then return */
+    if ( cube == bdd_read_one(manager)) 
+	return tr;
+
+    /* Obtain the top variable indexes */
+    topTR = bdd_get_level_from_id(manager,bdd_node_read_index(tr));
+    topC = bdd_get_level_from_id(manager,bdd_node_read_index(cube));
+
+    /* The function does not depend on the top variable of the cube */
+    if (topTR > topC ) {
+	result = MarkAddInProbRecur(manager,tr,bdd_bdd_T(cube),probTable,visited);
+	return(result);
+    }
+
+    /* If both top variables are equal, solve subproblems and combine */
+    if (topTR == topC ) {
+	solT = MarkAddInProbRecur(manager,bdd_bdd_T(tr),bdd_bdd_T(cube),
+				  probTable,visited);
+	if (solT == NULL) {
+	    return NULL;
+	}
+	bdd_ref(solT);
+        solE = MarkAddInProbRecur(manager,bdd_bdd_E(tr),bdd_bdd_T(cube),
+				  probTable,visited);
+	if (solE == NULL) {
+	    bdd_recursive_deref(manager,solT);
+	    return NULL;
+	}
+	bdd_ref(solE);
+	index = bdd_node_read_index(cube);
+        st_lookup(probTable,(char *)(long)index,&prob);
+        unique = bdd_add_const(manager,*prob);
+	if(unique == NULL) {
+	    bdd_recursive_deref(manager,solT);
+	    bdd_recursive_deref(manager,solE);
+	    return NULL;
+	}
+	bdd_ref(unique);
+        solPT = bdd_add_apply_recur(manager,bdd_add_times,solT,unique);
+	if (solPT == NULL) {
+	    bdd_recursive_deref(manager,solT);
+	    bdd_recursive_deref(manager,solE);
+	    bdd_recursive_deref(manager,unique);
+	    return NULL;
+	}
+	bdd_ref(solPT);
+        bdd_recursive_deref(manager,unique);
+        bdd_recursive_deref(manager,solT);
+        unique = bdd_add_const(manager,1.0 - *prob);
+	if (unique == NULL) {
+	    bdd_recursive_deref(manager,solE);
+	    bdd_recursive_deref(manager,solPT);
+	    return NULL;
+	}
+	bdd_ref(unique);
+        solPE = bdd_add_apply_recur(manager,bdd_add_times,solE,unique);
+	if (solPE == NULL) {
+	    bdd_recursive_deref(manager,unique);
+	    bdd_recursive_deref(manager,solPT);
+	    bdd_recursive_deref(manager,solE);
+	    return NULL;
+	}
+	bdd_ref(solPE);
+        bdd_recursive_deref(manager,unique);
+        bdd_recursive_deref(manager,solE);
+        result = bdd_add_apply_recur(manager,bdd_add_plus,solPT,solPE);
+	if (result == NULL) {
+	    bdd_recursive_deref(manager,solPT);
+	    bdd_recursive_deref(manager,solPE);
+	    return NULL;
+	}
+	bdd_ref(result);
+        bdd_recursive_deref(manager,solPE);
+        bdd_recursive_deref(manager,solPT);
+        st_insert(visited,(char *)tr,(char *)result);
+	/* bdd_deref(result); */
+        return(result);
+    }
+    
+    /* Split on a state variable, solve subproblems and combine by ite */
+    solT = MarkAddInProbRecur(manager,bdd_bdd_T(tr),cube, probTable,visited);
+    if (solT == NULL) {
+	return NULL;
+    }
+    bdd_ref(solT);
+    solE = MarkAddInProbRecur(manager,bdd_bdd_E(tr),cube,
+			      probTable,visited);
+    if (solE == NULL) {
+	bdd_recursive_deref(manager,solT);
+	return NULL;
+    }
+    bdd_ref(solE);
+    result = bdd_unique_inter(manager,bdd_node_read_index(tr),
+			      solT,solE);
+    if (result == NULL) {
+	bdd_recursive_deref(manager,solT);
+	bdd_recursive_deref(manager,solE);
+	return NULL;
+    }
+    bdd_ref(result);
+    bdd_recursive_deref(manager,solT);
+    bdd_recursive_deref(manager,solE);
+    st_insert(visited,(char *)tr,(char *)result);
+    /* bdd_deref(result); */
+    return(result);
+
+} /* end of MarkAddInProbRecur */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
Index: vis_dev/vis-2.3/src/mark/markInt.h
===================================================================
--- vis_dev/vis-2.3/src/mark/markInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/mark/markInt.h	(revision 14)
@@ -0,0 +1,103 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [markInt.h]
+
+  PackageName [mark]
+
+  Synopsis    [Data structures used in Markovian analysis.]
+
+  Description [optional]
+
+  SeeAlso     [optional]
+
+  Author      [Balakrishna Kumthekar]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+#ifndef _MARKINT
+#define _MARKINT
+
+#include "mark.h"
+#include <string.h>
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [Data structure for performing Markovian Analysis.]
+
+  SeeAlso     []
+
+******************************************************************************/
+typedef struct CK {
+  bdd_manager *manager;
+  bdd_node **piVars;      /* Primary input variables. BDD variables */
+  bdd_node **xVars;       /* Present state variables. BDD variables. */
+  bdd_node **yVars;       /* Next state variables. BDD variables. */
+  bdd_node **zVars;       /* Auxillary BDD variables, used internally */
+  bdd_node **piAddVars;   /* Primary input variables, ADD variables */
+  bdd_node **xAddVars;    /* Present state variables. ADD variables. */
+  bdd_node **yAddVars;    /* Next state variables. ADD variables. */
+  bdd_node **zAddVars;    /* Auxillary ADD variables, used internally */
+  bdd_node *coeff;        /* 0-1 ADD of TR(x,w,y) */
+  int nVars;            /* Number of state variables */
+  int nPi;              /* Number of input variables */
+  double abstol;        /* Tolerance values, used internally */
+  double scale;
+  double reltol;
+  Mark_StartMethod start;
+  int roundOff;         /* Roundoff to "roundOff" digit after decimal */
+  st_table *inputProb;  /* input probabilities */
+  bdd_node *transition;   /* BDD transition relation T(x,w,y) */
+  bdd_node *reached;      /* Set of reachable states R(x) */
+  st_table *indexSCC;
+  bdd_node *collapsedcoeff;
+  double term_SCC_states;  /* # of terminal SCCs */
+  st_table *periods;    /* period of TSCCs */
+  bdd_node *term_scc;    /* ADD of reachable terminal SCCs */
+  bdd_node *init_guess;  /* equi. probability to all TSCC states
+			 or probabiliy 1 to one of the TSCC states.*/
+} CK;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN bdd_node ** MarkAddCKSolve(CK *ck);
+EXTERN bdd_node ** MarkAddGenSolve(CK *ck);
+EXTERN double MarkAverageBitChange(bdd_manager *manager, bdd_node *probTR, bdd_node **xVars, bdd_node **yVars, int nVars);
+EXTERN bdd_node ** MarkAddFPSolve(CK *ck);
+EXTERN bdd_node * MarkAddBuildCoeff(bdd_manager *manager, bdd_node *func, bdd_node **piAddVars, st_table *inputProb, double scale, int nVars, int nPi);
+EXTERN bdd_node * MarkGetSCC(bdd_manager *manager, bdd_node *tr, bdd_node *tc, bdd_node *reached, bdd_node **xVars, bdd_node **yVars, int nVars, st_table **scc_table);
+EXTERN bdd_node * MarkAddInProbRecur(bdd_manager *manager, bdd_node *tr, bdd_node *cube, st_table *probTable, st_table *visited);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _MARKINT */
Index: vis_dev/vis-2.3/src/mc/mc.h
===================================================================
--- vis_dev/vis-2.3/src/mc/mc.h	(revision 14)
+++ vis_dev/vis-2.3/src/mc/mc.h	(revision 14)
@@ -0,0 +1,361 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [mc.h]
+
+  PackageName [mc]
+
+  Synopsis    [Fair CTL model checker and debugger.]
+
+  Description [Fair CTL model checker and debugger.  Works on a flattened
+  network.]
+
+  Author      [Adnan Aziz, Tom Shiple, In-Ho Moon]
+
+  Comment     []
+  
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: mc.h,v 1.54 2007/04/17 00:01:22 sohail Exp $]
+
+******************************************************************************/
+
+#ifndef _MC
+#define _MC
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "cmd.h"
+#include "ctlp.h"
+#include "ctlsp.h"
+#include "ntk.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/* Use this if you don't want early termination */
+#define MC_NO_EARLY_TERMINATION (NIL(Mc_EarlyTermination_t))
+
+/* Constants for lockstep mode. */
+#define MC_LOCKSTEP_UNASSIGNED		-3
+#define MC_LOCKSTEP_OFF			-2
+#define MC_LOCKSTEP_EARLY_TERMINATION	-1
+#define MC_LOCKSTEP_ALL_SCCS		0
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Enum************************************************************************
+
+  Synopsis    [Use forward or backward analysis]
+
+******************************************************************************/
+
+typedef enum {
+  McFwd_c,
+  McBwd_c /* someday there may be a mixed method */
+} Mc_FwdBwdAnalysis;
+
+/**Enum************************************************************************
+
+  Synopsis    [Extent to which Mc functions provide feedback/stats.]
+
+******************************************************************************/
+
+typedef enum {
+  McVerbosityNone_c,
+  McVerbosityLittle_c,
+  McVerbositySome_c,
+  McVerbosityMax_c
+} Mc_VerbosityLevel;
+
+/**Enum************************************************************************
+
+  Synopsis    [Extent to which don't cares are used in Mc functions.]
+
+******************************************************************************/
+
+typedef enum {
+  McDcLevelNone_c,
+  McDcLevelRch_c,
+  McDcLevelRchFrontier_c,
+  McDcLevelArdc_c
+} Mc_DcLevel;
+
+
+/**Enum************************************************************************
+
+  Synopsis [When creating a path from aState to bState, make it non trivial
+  (ie a cycle) when aState == bState and McPathLengthType is McGreaterZero_c.]
+
+******************************************************************************/
+
+typedef enum {
+  McGreaterZero_c,
+  McGreaterOrEqualZero_c
+} Mc_PathLengthType;
+
+
+/**Enum************************************************************************
+
+  Synopsis    [Some,all or care, for Mc_EarlyTermination_t]
+
+******************************************************************************/
+
+typedef enum {
+  McSome_c,
+  McAll_c,
+  McCare_c
+} Mc_EarlyTerminationType;
+
+/**Enum************************************************************************
+
+  Synopsis [What kind of hints?]
+
+  Description [Would you like that with no hints, global hints or
+  local hints?  Paper or plastic?]
+
+  SideEffects []
+
+  SeeAlso []
+  
+******************************************************************************/
+typedef enum {
+  Mc_None_c,
+  Mc_Global_c,
+  Mc_Local_c
+} Mc_GuidedSearch_t;
+
+/**Enum************************************************************************
+
+  Synopsis [Specifies the method for language emptiness checking]
+
+  Description [Specifies the method used by command ltl and le for
+  checking the language emptiness.]
+
+  SideEffects []
+
+  SeeAlso []
+  
+******************************************************************************/
+typedef enum {
+  Mc_Le_Default_c,
+  Mc_Le_Dnc_c
+} Mc_LeMethod_t;
+
+/**Enum************************************************************************
+
+  Synopsis [Specifies the automaton strength]
+
+  Description [Specifies the automaton strength]
+
+  SideEffects []
+
+  SeeAlso []
+  
+******************************************************************************/
+typedef enum {
+    Mc_Aut_Terminal_c,
+    Mc_Aut_Weak_c,
+    Mc_Aut_Strong_c
+} Mc_AutStrength_t;
+
+/**Enum************************************************************************
+
+  Synopsis    [Type of GSH schedule.]
+
+  Description [The GSH schedule is the policy followed by the GSH
+  algorithm in applying the EU and EX operators.  If there are
+  <code>n</code> fairness constraints, the operators are
+  <code>EU1,...,EUn,EX</code>.  Currently, three schedules are
+  supported: EL, EL1, EL2, budget, and random.
+  <ul>
+  <li> EL: <code>EU1 EX ... EUn EX EU1 EX ... EUn EX ...</code>.
+  <li> EL1: <code>EU1 ... EUn EX EU1 ... EUn EX ...</code>.
+  <li> EL2: <code>EU1 ... EUn EX EX ... EU1 ... EUn EX EX ... ...</code>.
+  <li> budget: like EL2, but <code>EX</code> not allowed more times than
+       number of <code>EXs</code> performed inside <code>EUs</code>.
+  <li> random: operators are chosen in a pseudorandom fashion with 0.5
+       probability assigned to <code>EX</code> (as in EL).
+  </ul>]
+
+******************************************************************************/
+
+typedef enum {
+  McGSH_old_c,       /* do not use GSH */
+  McGSH_EL_c,        /* Emerson-Lei schedule */
+  McGSH_EL1_c,       /* modified Emerson-Lei schedule */
+  McGSH_EL2_c,       /* Hojati's EL2 schedule (a.k.a. OWCTY) */
+  McGSH_Budget_c,    /* EL2 with EX budget */
+  McGSH_Random_c,    /* Random schedule */
+  McGSH_Unassigned_c /* invalid schedule */
+} Mc_GSHScheduleType;
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------------
+
+  Synopsis    [The type of the onion rings]
+
+  Description [Onion rings are arrays of mdd_t*s, decribes in onionRings.c]
+
+-----------------------------------------------------------------------------*/
+typedef array_t OnionRing_t;
+
+typedef struct McEarlyTerminationStruct Mc_EarlyTermination_t;
+typedef struct McSccGenStruct Mc_SccGen_t;
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the fair SCCs of a FSM.]
+
+  Description  [Iterates over the fair SCCs of a FSM.  The parameters are:
+  <ul>
+  <li> Fsm_Fsm_t *fsm,
+  <li> Mc_SccGen_t *gen,
+  <li> mdd_t *scc,
+  <li> array_t *sccClosedSetArray, ( of mdd_t * )
+  <li> array_t *leftover,          ( of mdd_t *, can be NULL )
+  <li> array_t *buechiFairness,    ( of mdd_t * )
+  <li> array_t *onionRings,        ( of mdd_t * )
+  <li> boolean earlyTermination,
+  <li> Mc_VerbosityLevel verbosity,
+  <li> Mc_DcLevel dcLevel.
+  </ul>
+  Mc_FsmForEachFairScc allocates and frees the generator.  Therefore the
+  application should not try to do that unless it breaks out of the
+  loop, in which case it must call Mc_FsmSccGenFree explicitly.  If
+  earlyTermination is TRUE, at most one fair SCC is enumerated.
+  Setting earlyTermination to TRUE differs from breaking out of hte
+  loop after the first fair SCC is enumerated in three respects.
+  <ul>
+  <li> The set of states returned in scc is guaranteed to contain a fair
+       SCC, but it may also contain states not belonging to that SCC.
+  <li> early termination is typically faster, however,
+  <li> one cannot retrive the sets of states not yet processed.  Even if
+       leftover is non NIL, nothing is added to it.
+  </ul>]
+
+  SideEffects  [none]
+
+  SeeAlso      [Mc_FsmFirstScc Mc_FsmNextScc Mc_FsmIsSccGenEmpty
+  Mc_FsmSccGenFree]
+
+******************************************************************************/
+#define Mc_FsmForEachFairScc(fsm, gen, scc, sccClosedSetArray, leftover,\
+                             buechiFairness, onionRings, earlyTermination,\
+			     verbosity, dcLevel)\
+  for((gen) = Mc_FsmFirstScc(fsm, &scc, sccClosedSetArray, buechiFairness,\
+                             onionRings, earlyTermination,\
+                             verbosity, dcLevel);\
+    Mc_FsmIsSccGenEmpty(gen) ? Mc_FsmSccGenFree(gen, leftover) : TRUE;\
+    (void) Mc_FsmNextScc(gen, &scc))
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "fsm.h"
+#include "part.h"
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void Mc_Init(void);
+EXTERN void Mc_End(void);
+EXTERN mdd_t * Mc_FsmCheckLanguageEmptiness(Fsm_Fsm_t *modelFsm, array_t *modelCareStatesArray, Mc_AutStrength_t automatonStrength, Mc_LeMethod_t leMethod, int dcLevel, int dbgLevel, int printInputs, int verbosity, Mc_GSHScheduleType GSHschedule, Mc_FwdBwdAnalysis GSHdirection, int lockstep, FILE *dbgFile, int UseMore, int SimValue, char *driverName);
+EXTERN mdd_t * Mc_FsmEvaluateFormula(Fsm_Fsm_t *fsm, Ctlp_Formula_t *ctlFormula, mdd_t *fairStates, Fsm_Fairness_t *fairCondition, array_t *careStatesArray, Mc_EarlyTermination_t *earlyTermination, Fsm_HintsArray_t *hintsArray, Mc_GuidedSearch_t hintType, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, int buildOnionRing, Mc_GSHScheduleType GSHschedule);
+EXTERN mdd_t * Mc_FsmEvaluateEXFormula(Fsm_Fsm_t *modelFsm, mdd_t *targetMdd, mdd_t *fairStates, array_t *careStatesArray, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel);
+EXTERN mdd_t * Mc_FsmEvaluateMXFormula(Fsm_Fsm_t *modelFsm, mdd_t *targetMdd, mdd_t *fairStates, array_t *careStatesArray, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel);
+EXTERN mdd_t * Mc_FsmEvaluateAXFormula(Fsm_Fsm_t *modelFsm, mdd_t *targetMdd, mdd_t *fairStates, array_t *careStatesArray, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel);
+EXTERN mdd_t * Mc_FsmEvaluateEYFormula(Fsm_Fsm_t *modelFsm, mdd_t *targetMdd, mdd_t *fairStates, array_t *careStatesArray, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel);
+EXTERN mdd_t * Mc_FsmEvaluateEUFormula(Fsm_Fsm_t *fsm, mdd_t *invariant, mdd_t *target, mdd_t *underapprox, mdd_t *fairStates, array_t *careStatesArray, Mc_EarlyTermination_t *earlyTermination, Fsm_HintsArray_t *hintsArray, Mc_GuidedSearch_t hintType, array_t *onionRings, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, boolean *fixpoint);
+EXTERN mdd_t * Mc_FsmEvaluateAUFormula(Fsm_Fsm_t *fsm, mdd_t *invariant, mdd_t *target, mdd_t *underapprox, mdd_t *fairStates, array_t *careStatesArray, Mc_EarlyTermination_t *earlyTermination, Fsm_HintsArray_t *hintsArray, Mc_GuidedSearch_t hintType, array_t *onionRings, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, boolean *fixpoint);
+EXTERN mdd_t * Mc_FsmEvaluateESFormula(Fsm_Fsm_t *fsm, mdd_t *invariant, mdd_t *source, mdd_t *underapprox, mdd_t *fairStates, array_t *careStatesArray, Mc_EarlyTermination_t *earlyTermination, Fsm_HintsArray_t *hintsArray, Mc_GuidedSearch_t hintType, array_t *onionRings, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, boolean *fixpoint);
+EXTERN mdd_t * Mc_FsmEvaluateEGFormula(Fsm_Fsm_t *fsm, mdd_t *invariant, mdd_t *overapprox, mdd_t *fairStates, Fsm_Fairness_t *modelFairness, array_t *careStatesArray, Mc_EarlyTermination_t *earlyTermination, Fsm_HintsArray_t *hintsArray, Mc_GuidedSearch_t hintType, array_t **pOnionRingsArrayForDbg, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, boolean *fixpoint, Mc_GSHScheduleType GSHschedule);
+EXTERN mdd_t * Mc_FsmEvaluateEHFormula(Fsm_Fsm_t *fsm, mdd_t *invariant, mdd_t *overapprox, mdd_t *fairStates, Fsm_Fairness_t *modelFairness, array_t *careStatesArray, Mc_EarlyTermination_t *earlyTermination, Fsm_HintsArray_t *hintsArray, Mc_GuidedSearch_t hintType, array_t **pOnionRingsArrayForDbg, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, boolean *fixpoint, Mc_GSHScheduleType GSHschedule);
+EXTERN mdd_t * Mc_FsmEvaluateFwdUFormula(Fsm_Fsm_t *modelFsm, mdd_t *targetMdd, mdd_t *invariantMdd, mdd_t *fairStates, array_t *careStatesArray, array_t *onionRings, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel);
+EXTERN mdd_t * Mc_FsmEvaluateFwdGFormula(Fsm_Fsm_t *modelFsm, mdd_t *targetMdd, mdd_t *invariantMdd, mdd_t *fairStates, Fsm_Fairness_t *modelFairness, array_t *careStatesArray, array_t *onionRingsArrayForDbg, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel);
+EXTERN mdd_t * Mc_FsmEvaluateFwdEHFormula(Fsm_Fsm_t *modelFsm, mdd_t *invariantMdd, mdd_t *fairStates, Fsm_Fairness_t *modelFairness, array_t *careStatesArray, array_t *onionRingsArrayForDbg, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel);
+EXTERN void Mc_FsmEvaluateFormulaForVacuity(Fsm_Fsm_t *fsm, Ctlp_Formula_t *ctlFormula, mdd_t *fairStates, Fsm_Fairness_t *fairCondition, array_t *careStatesArray, Mc_EarlyTermination_t *earlyTermination, Fsm_HintsArray_t *hintsArray, Mc_GuidedSearch_t hintType, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, int buildOnionRing, Mc_GSHScheduleType GSHschedule, mdd_t *modelInitialStates);
+EXTERN mdd_t *Mc_QuantifyInputFAFW(Fsm_Fsm_t *fsm, bdd_t *result);
+EXTERN Mc_SccGen_t * Mc_FsmFirstScc(Fsm_Fsm_t *fsm, mdd_t **scc, array_t *sccClosedSetArray, array_t *buechiFairness, array_t *onionRings, boolean earlyTermination, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel);
+EXTERN boolean Mc_FsmNextScc(Mc_SccGen_t *gen, mdd_t **scc);
+EXTERN boolean Mc_FsmIsSccGenEmpty(Mc_SccGen_t *gen);
+EXTERN boolean Mc_FsmSccGenFree(Mc_SccGen_t *gen, array_t *leftover);
+EXTERN int Mc_FsmComputeStatesReachingToSet(Fsm_Fsm_t *modelFsm, mdd_t *targetStates, array_t *careStatesArray, mdd_t *specialStates, array_t *onionRings, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel);
+EXTERN int Mc_FsmComputeStatesReachableFromSet(Fsm_Fsm_t *modelFsm, mdd_t *initialStates, array_t *careStatesArray, mdd_t *specialStates, array_t *onionRings, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel);
+EXTERN boolean Mc_FormulaStaticSemanticCheckOnNetwork(Ctlp_Formula_t *formula, Ntk_Network_t *network, boolean inputsAllowed);
+EXTERN array_t * Mc_BuildPathToCore(mdd_t *aState, array_t *onionRings, Fsm_Fsm_t *modelFsm, Mc_PathLengthType PathLengthType);
+EXTERN array_t * Mc_BuildPathToCoreFAFW(mdd_t *aState, array_t *onionRings, Fsm_Fsm_t *modelFsm, Mc_PathLengthType PathLengthType);
+EXTERN array_t * Mc_BuildPathFromCore(mdd_t *aState, array_t *onionRings, Fsm_Fsm_t *modelFsm, Mc_PathLengthType PathLengthType);
+EXTERN array_t * Mc_BuildPathFromCoreFAFW(mdd_t *aState, array_t *onionRings, Fsm_Fsm_t *modelFsm, Mc_PathLengthType PathLengthType);
+EXTERN array_t * Mc_CompletePath(mdd_t *aState, mdd_t *bState, mdd_t *invariantStates, Fsm_Fsm_t *modelFsm, array_t *careSetArray, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, Mc_FwdBwdAnalysis dirn);
+EXTERN mdd_t * Mc_ComputeAMinterm(mdd_t *aSet, array_t *Support, mdd_manager *mddMgr);
+EXTERN mdd_t * Mc_ComputeACloseMinterm(mdd_t *aSet, mdd_t *target, array_t *Support, mdd_manager *mddMgr);
+EXTERN char * Mc_MintermToString(mdd_t *aMinterm, array_t *aSupport, Ntk_Network_t *aNetwork);
+EXTERN char * Mc_MintermToStringAiger(mdd_t *aMinterm, array_t *aSupport, Ntk_Network_t *aNetwork);
+EXTERN char * Mc_MintermToStringAigerInput(mdd_t *aMinterm, array_t *aSupport, Ntk_Network_t *aNetwork);
+EXTERN int Mc_PrintPath(array_t *aPath, Fsm_Fsm_t *modelFsm, boolean printInput);
+EXTERN int Mc_PrintPathAiger(array_t *aPath, Fsm_Fsm_t *modelFsm, boolean printInput);
+EXTERN mdd_t * Mc_FsmComputeDrivingInputMinterms(Fsm_Fsm_t *fsm, mdd_t *aState, mdd_t *bState);
+EXTERN mdd_t * Mc_ComputeAState(mdd_t *states, Fsm_Fsm_t *modelFsm);
+EXTERN mdd_t * Mc_ComputeACloseState(mdd_t *states, mdd_t *target, Fsm_Fsm_t *modelFsm);
+EXTERN void Mc_MintermPrint(mdd_t *aMinterm, array_t *support, Ntk_Network_t *aNetwork);
+EXTERN void Mc_NodeTableAddCtlFormulaNodes(Ntk_Network_t *network, Ctlp_Formula_t *formula, st_table * nodesTable);
+EXTERN void Mc_NodeTableAddLtlFormulaNodes(Ntk_Network_t *network, Ctlsp_Formula_t *formula, st_table * nodesTable);
+EXTERN Fsm_Fsm_t * Mc_ConstructReducedFsm(Ntk_Network_t *network, array_t *ctlFormulaArray);
+EXTERN Mc_GSHScheduleType Mc_StringConvertToScheduleType(char *string);
+EXTERN int Mc_StringConvertToLockstepMode(char *string);
+EXTERN Mc_EarlyTermination_t * Mc_EarlyTerminationAlloc(Mc_EarlyTerminationType mode, mdd_t *states);
+EXTERN void Mc_EarlyTerminationFree(Mc_EarlyTermination_t *earlyTermination);
+EXTERN boolean Mc_EarlyTerminationIsSkip(Mc_EarlyTermination_t *earlyTermination);
+EXTERN array_t * Mc_ReadHints(FILE *guideFP);
+EXTERN st_table * Mc_ReadSystemVariablesFAFW(Fsm_Fsm_t *fsm, FILE *systemFP);
+EXTERN array_t * Mc_EvaluateHints(Fsm_Fsm_t *fsm, Ctlp_FormulaArray_t *invarArray);
+EXTERN array_t * Mc_ComputeGuideArray(Fsm_Fsm_t *fsm, FILE *guideFP);
+EXTERN Mc_GuidedSearch_t Mc_ReadGuidedSearchType(void);
+EXTERN array_t *
+Mc_BuildShortestPathFAFW(mdd_t *win, mdd_t *S, mdd_t *T, array_t *rings, mdd_manager *mgr, Fsm_Fsm_t *fsm, int prevFlag);
+EXTERN st_table *Mc_SetAllInputToSystem(Fsm_Fsm_t *fsm);
+EXTERN array_t * Mc_BuildFAFWLayer(Fsm_Fsm_t *modelFsm, mdd_t *T, mdd_t *H);
+EXTERN array_t * MC_BuildCounterExampleFAFWGeneral( Fsm_Fsm_t *modelFsm, mdd_t *I, mdd_t *T, mdd_t *H, array_t *L);
+EXTERN array_t * Mc_BuildPathFromCoreFAFWGeneral( mdd_t *T, array_t *rings, Fsm_Fsm_t *modelFsm, Mc_PathLengthType PathLengthType);
+EXTERN array_t * Mc_BuildForwardRingsWithInvariants( mdd_t *S, mdd_t *T, mdd_t *invariants, Fsm_Fsm_t *fsm);
+EXTERN array_t * Mc_CreateStaticRefinementScheduleArray(Ntk_Network_t *network, array_t *ctlArray, array_t *ltlArray, array_t *fairArray, boolean dynamicIncrease, boolean isLatchNameSort, int verbosity, int incrementalSize, Part_CMethod correlationMethod);
+EXTERN mdd_t * Mc_FsmCheckLanguageEmptinessByDnC(Fsm_Fsm_t *modelFsm, array_t *modelCareStatesArray, Mc_AutStrength_t automatonStrength, int dcLevel, int dbgLevel, int printInputs, int verbosity, Mc_GSHScheduleType GSHschedule, Mc_FwdBwdAnalysis GSHdirection, int lockstep, FILE *dbgFile, int UseMore, int SimValue, char *driverName);
+
+
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _MC */
Index: vis_dev/vis-2.3/src/mc/mc.make
===================================================================
--- vis_dev/vis-2.3/src/mc/mc.make	(revision 14)
+++ vis_dev/vis-2.3/src/mc/mc.make	(revision 14)
@@ -0,0 +1,5 @@
+CSRC += mcCmd.c mcCover.c mcDbg.c mcDnC.c mcGFP.c mcMc.c mcSCC.c mcUtil.c \
+        mcVacuum.c
+HEADERS += mc.h mcInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/mc/mcCmd.c
===================================================================
--- vis_dev/vis-2.3/src/mc/mcCmd.c	(revision 14)
+++ vis_dev/vis-2.3/src/mc/mcCmd.c	(revision 14)
@@ -0,0 +1,3251 @@
+/**CFile***********************************************************************
+
+  FileName    [mcCmd.c]
+
+  PackageName [mc]
+
+  Synopsis    [Functions for CTL model checking commands.]
+
+  Description [This file contains the functions implementing the CTL
+  model checking commands.]
+
+  SeeAlso     []
+
+  Author      [Adnan Aziz, Tom Shiple, Rajeev Ranjan, In-Ho Moon,
+  Roderick Bloem, and others]
+
+  Copyright   [Copyright (c) 2002-2005, 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 "ctlpInt.h"
+#include "grab.h"
+#include "puresat.h"
+#include "mcInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] UNUSED = "$Id: mcCmd.c,v 1.27 2009/04/11 01:43:30 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+static jmp_buf timeOutEnv;
+static int mcTimeOut;		/* timeout value */
+static long alarmLapTime;	/* starting CPU time for timeout */
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandMc(Hrc_Manager_t **hmgr, int argc, char **argv);
+static McOptions_t * ParseMcOptions(int argc, char **argv);
+static int CommandLe(Hrc_Manager_t **hmgr, int argc, char **argv);
+static McOptions_t * ParseLeOptions(int argc, char **argv);
+static int CommandInv(Hrc_Manager_t **hmgr, int argc, char **argv);
+static McOptions_t * ParseInvarOptions(int argc, char **argv);
+static void TimeOutHandle(void);
+static int UpdateResultArray(mdd_t *reachableStates, array_t *invarStatesArray, int *resultArray);
+static void PrintInvPassFail(array_t *invarFormulaArray, int *resultArray);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Initialize mc package]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Mc_Init(void)
+{
+  Cmd_CommandAdd("model_check", CommandMc, /* doesn't changes_network */ 0);
+  Cmd_CommandAdd("check_invariant", CommandInv, /* doesn't changes_network */ 0);
+  Cmd_CommandAdd("lang_empty", CommandLe, /* doesn't changes_network */ 0);
+  Cmd_CommandAdd("_init_state_formula", McCommandInitState, /* doesn't changes_network */ 0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [End mc package]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Mc_End(void)
+{
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Check CTL formulas given in file are modeled by flattened network]
+
+  CommandName [model_check]
+
+  CommandSynopsis [perform fair CTL model checking on a flattened network]
+
+  CommandArguments [ \[-b\] \[-c\] \[-d &lt;dbg_level&gt;\]
+  \[-f &lt;dbg_file&gt;\] \[-g &lt;hints_file&gt;\] \[-h\] \[-i\] \[-m\] \[-r\]
+  \[-t &lt;time_out_period&gt;\]\[-v &lt;verbosity_level&gt;\]
+  \[-D &lt;dc_level&gt;\] \[-F\] \[-S &lt;schedule&gt;\] \[-V\] \[-B\] \[-I\]
+  \[-C\] \[-w  &lt;node_file&gt;\] \[-W\] \[-G\] &lt;ctl_file&gt;]
+
+  CommandDescription [Performs fair CTL model checking on a flattened
+  network.  Before calling this command, the user should have
+  initialized the design by calling the command <A
+  HREF="init_verifyCmd.html"> <code> init_verify</code></A>.
+  Regardless of the options, no 'false positives' or 'false negatives'
+  will occur: the result is correct for the given circuit.  <p>
+
+  Properties to be verified should be provided as CTL formulas in the
+  file <code>ctl_file</code>.  Note that the support of any wire
+  referred to in a formula should consist only of latches.  For the
+  precise syntax of CTL formulas, see the <A
+  HREF="../ctl/ctl/ctl.html"> VIS CTL and LTL syntax manual</A>.  <p>
+
+  Properties of the form <code> AG f</code>, where  <code>f</code> is a formula not
+  involving path quantifiers are referred to as invariants; for such properties
+  it may be substantially faster to use the <A HREF="check_invariantCmd.html">
+  <code> check_invariant</code></A> command.
+  <p>
+
+  A fairness constraint can be specified by invoking the
+  <A HREF="read_fairnessCmd.html"><code>read_fairness</code></A> command;
+  if none is specified, all paths are taken to be fair.
+  If some initial states
+  do not lie on a fair path, the model checker prints a message to this effect.
+  <p>
+
+  A formula passes iff it is true for all initial states of the
+  system.  Therefore, in the presence of multiple initial states, if a
+  formula fails, the negation of the formula may also fail.<p>
+
+  If a formula does not pass, a (potentially partial) proof of failure
+  (referred to as a debug trace) is demonstrated. Fair paths are
+  represented by a finite sequence of states (the stem) leading to a
+  fair cycle, i.e. a cycle on which there is a state from each
+  fairness condition. The level of detail of the proof can be
+  specified (see option <code>-d</code>). <p>
+
+  Both backward (future tense CTL formulas) and forward (past tense CTL
+  formulas) model checking can be performed. Forward model checking is
+  based on Iwashita's ICCAD96 paper. Future tense CTL formulas are
+  automatically converted to past tense ones as much as possible in
+  forward model checking. <p>
+
+  Command options:
+  <p>
+
+  <dl>
+
+  <dt> -b
+  <dd> Use backward analysis when performing debugging; the default is
+  to use forward analysis. This should be tried when the debugger spends a
+  large amount of time when creating a path to a fair cycle. This option is not
+  compatible with forward model checking option (-F).</dd><p>
+
+  <dt> -c
+  <dd> Use the formula tree so that there is no sharing of sub-formulae among
+  the formulae in the input file. This option is useful in the following
+  scenario - formulae A, B and C are being checked in order and there is
+  sub-formula sharing between A and C. If the BDDs corresponding to the shared
+  sub-formula is huge then computation for B might not be able to finish
+  without using this option.
+  </dd><p>
+
+  <dt> -d <code> &lt;dbg_level&gt; </code> <dd> Specify the amount of
+  debugging performed when the system fails a formula being checked.
+  Note that it may not always be possible to give a simple
+  counter-example to show that a formula is false, since this may
+  require enumerating all paths from a state.  In such a case the
+  model checker will print a message to this effect.  This option is
+  incompatible with -F.</dd>  <p>
+  <dd> <code> dbg_level</code> must be one of the following:
+
+  <p><code>0</code>: No debugging performed.
+  <code>dbg_level</code>=<code>0</code> is the default.
+
+  <p><code>1</code>: Debugging with minimal output: generate counter-examples
+  for universal formulas (formulas of the form <code>AX|AF|AU|AG</code>) and
+  witnesses for existential formulas (formulas of the form
+  <code>EX|EF|EU|EG</code>).  States on a path are not further analyzed.
+
+  <p><code>2</code>: Same as <code>dbg_level</code>=<code>1</code>, but more
+  verbose. (The subformulas are printed, too.)
+
+  <p><code>3</code>: Maximal automatic debugging: as for level <code>1</code>,
+  except that states occurring on paths will be recursively analyzed.
+
+  <p><code>4</code>: Manual debugging: at each state, the user is queried if
+  more feedback is desired.
+  </dd>
+
+  <p>
+
+  <dt> -f &lt;<code>dbg_file</code>&gt;
+  <dd> Write the debugger output to <code>dbg_file</code>.
+  This option is incompatible with -F.
+  Notes: when you use -d4 (interactive mode), -f is not recommended, since you
+  can't see the output of vis on stdout.</dd>
+
+  <dt> -g &lt;<code>hints_file</code>&gt; <dd> Use guided search.  The file
+  <code>hints_file</code> contains a series of hints.  A hint is a formula that
+  does not contain any temporal operators, so <code>hints_file</code> has the
+  same syntax as a file of invariants used for check_invariant.  The hints are
+  used in the order given to change the transition relation.  In the case of
+  least fixpoints (EF, EU), the transition relation is conjoined with the hint,
+  whereas for greatest fixpoints the transition relation is disjoined with the
+  negation of the hint.  If the hints are cleverly chosen, this may speed up
+  the computation considerably, because a search with the changed transition
+  relation may be much simpler than one with the original transition relation,
+  and results obtained can be reused, so that we may never have to do a
+  complicated search with the original relation.  Note: hints in terms of
+  primary inputs are not useful for greatest fixpoints.  See also: Ravi and
+  Somenzi, Hints to accelerate symbolic traversal. CHARME'99; Bloem, Ravi, and
+  Somenzi, Efficient Decision Procedures for Model Checking of Linear Time
+  Logic Properties, CAV'99; Bloem, Ravi, and Somenzi, Symbolic Guided Search
+  for CTL Model Checking, DAC'00.
+
+  <p>For formulae that contain both least and greatest fixpoints, the
+  behavior depends on the flag <code>guided_search_hint_type</code>.
+  If it is set to local (default) then every subformula is evaluated
+  to completion, using all hints in order, before the next subformula
+  is started.  For pure ACTL or pure ECTL formulae, we can also set
+  guided_search_hint_type to global, in which case the entire formula
+  is evaluated for one hint before moving on to the next hint, using
+  underapproximations.  The description of the options for guided
+  search can be found in the help page for
+  print_guided_search_options.
+
+  <p>model_check will call reachability without any guided search, even
+  if -g is used.  If you want to perform reachability with guided
+  search, call rch directly.
+
+  <p>Incompatible with -F.</dd>
+
+  <dt> -h
+  <dd> Print the command usage.</dd>
+  <p>
+
+  <dt> -i
+  <dd> Print input values causing transitions between states during debugging.
+  Both primary and pseudo inputs are printed.
+  This option is incompatible with -F.</dd>
+  <p>
+
+  <dt> -m
+  <dd> Pipe debugger output through the UNIX utility  more.
+  This option is incompatible with -F.</dd>
+  <p>
+
+  <dt> -r
+  <dd> Reduce the FSM derived from the flattened network with respect to each
+  formula being checked. By default, the FSM is reduced with respect to the
+  conjunction of the formulae in the input file. If this option is used and
+  don't cares are being used for simplification, then subformula sharing is
+  disabled (result might be incorrect otherwise).</dd>
+  <p>
+
+  <dd> The truth of  a formula may be independent of parts of the network
+  (such as when wires have been abstracted; see
+  <A HREF="flatten_hierarchyCmd.html"><code>flatten_hierarchy</code></A>).
+  These parts are effectively removed when this option is invoked; this may
+  result in more efficient model checking.</dd>
+  <p>
+
+  <dt> -t  <code>&lt;timeOutPeriod&gt;</code>
+  <dd> Specify the time out period (in seconds) after which the command
+  aborts. By default this option is set to infinity.</dd>
+  <p>
+
+  <dt> -v  <code>&lt;verbosity_level&gt;</code>
+  <dd> Specify verbosity level. This sets the amount of feedback  on CPU usage
+  and code status.
+
+  <br><code>verbosity_level</code>  must be one of the following:<p>
+
+  <code>0</code>: No feedback provided. This is the default.<p>
+
+  <code>1</code>: Feedback on code location.<p>
+
+  <code>2</code>: Feedback on code location and CPU usage.</dd><p>
+
+  <dt> -B
+  <dd> Check for vacuously passing formulae using the algorithm of Beer et al.
+  (CAV97).  The algorithm applies to a subset of ACTL (w-ACTL) and replaces
+  the smallest important subformula of a passing property with either FALSE
+  or TRUE depending on its negation parity.  It then applies model checking
+  to the resulting witness formula.  If the witness formula also passes, then
+  the original formula is deemed to pass vacuously.  If the witness formula
+  fails, a counterexample to it provides an interesting witness to the
+  original passing formula.  See the CAV97 paper for the definitions of
+  w-ACTL, important subformula, and interesting witness.  In short, one of the
+  operands of a binary operator in a w-ACTL formula must be a propositional
+  formula.  See also the -V option.
+  </dd><p>
+
+  <dt> -C
+  <dd> Compute coverage of all observable signals in a set of CTL formulae
+  using the algorithm of Hoskote, Kam, Ho, Zhao (DAC'99). If the verbosity
+  level (-v option) is equal to 0, only the coverage stats are printed. If
+  verbosity level is greater than zero, then detailed information of the
+  computation at each step of the algorithm is also provided.
+  Debug information is provided in the form of states not covered for each
+  observable signal if the dbg_level (-d option) is greater than 0. The number
+  of states printed is set by the vis environment variable
+  'nr_uncoveredstates'. By default the number of states printed is 1.
+  The value of nr_uncoveredstates can be set using the set command.
+  See also the -I option.</dd>
+  <p>
+
+  <dt> -D <code> &lt;dc_level&gt; </code>
+
+  <dd> Specify extent to which don't cares are used to simplify MDDs in model
+  checking.  Don't cares are minterms on which the values taken by functions
+  do not affect the computation; potentially, these minterms can be used to
+  simplify MDDs and reduce the time taken to perform model checking.  The -g
+  flag for guided search does not affect the way in which the don't-care
+  conditions are computed.
+
+  <br>
+  <code> dc_level </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: No don't cares are used.
+
+  <p> <code> 1 </code>: Use unreachable states as don't cares. This is the
+  default.
+
+  <p> <code> 2 </code>: Use unreachable states as don't cares and in the EU
+  computation, use 'frontiers' for image computation.<p>
+
+  <code> 3 </code>: First compute an overapproximation of the reachable states
+  (ARDC), and use that as the cares set.  Use `frontiers' for image
+  computation.  For help on controlling options for ARDC, look up help on the
+  command: <A HREF="print_ardc_optionsCmd.html">print_ardc_options</A>. Refer
+  to Moon, Jang, Somenzi, Pixley, Yuan, "Approximate Reachability Don't Cares
+  for {CTL} Model Checking", ICCAD98, and to two papers by Cho et al, IEEE TCAD
+  December 1996: one is for State Space Decomposition and the other is for
+  Approximate FSM Traversal.</dd>
+  <p>
+
+  <dt> -F
+  <dd> Use forward model checking based on Iwashita's method in ICCAD96.
+  Future tense CTL formulas are automatically converted to past tense
+  ones as much as possible. Converted forward formulas are printed when
+  verbosity is greater than 0. Debug options (-b, -d, -f, -i, and -m)
+  are ignored with this option. We have seen that forward model checking
+  was much faster than backward in many cases, also forward was much slower
+  than backward in many cases.</dd>
+  <p>
+
+  <dt> -I
+  <dd> Compute coverage of all observable signals in a set of CTL formulae
+  using an improved algorithm of Jayakumar, Purandare, Somenzi (DAC'03). If
+  the verbosity level (-v option) is equal to 0, only the coverage stats are
+  printed. If verbosity level is greater than zero, then detailed information
+  of the computation at each step of the algorithm is also provided.
+  Debug information is provided in the form of states not covered for each
+  observable signal if the dbg_level (-d option) is greater than 0. The number
+  of states printed is set by the vis environment variable
+  'nr_uncoveredstates'. By default the number of states printed is 1.
+  The value of nr_uncoveredstates can be set using the set command.
+  Compared to the -C option, this one produces more accurate results and deals
+  with a larger subset of CTL.</dd>
+  <p>
+
+  <dt> -S <code> &lt;schedule&gt; </code>
+
+  <dd> Specify schedule for GSH algorithm, which generalizes the
+  Emerson-Lei algorithm and is used to compute greatest fixpoints.
+  The choice of schedule affects the sequence in which EX and EU
+  operators are applied.  It makes a difference only when fairness
+  constraints are specified.
+
+  <br>
+  <code> &lt;schedule&gt; </code> must be one of the following:
+
+  <p> <code> EL </code>: EU and EX operators strictly alternate.  This
+  is the default.
+
+  <p> <code> EL1 </code>: EX is applied once for every application of all EUs.
+
+  <p> <code> EL2 </code>: EX is applied repeatedly after each application of
+  all EUs.
+
+  <p> <code> budget </code>: a hybrid of EL and EL2.
+
+  <p> <code> random </code>: enabled operators are applied in
+  (pseudo-)random order.
+
+  <p> <code> off </code>: GSH is disabled, and the old algorithm is
+  used instead.  The old algorithm uses the <code> EL </code> schedule, but
+  the termination checks are less sophisticated than in GSH.</dd>
+  <p>
+
+  <dt> -V
+  <dd> Check for vacuously passing formulae with the algorithm
+  of Purandare and Somenzi (CAV2002).  The algorithm applies to all of
+  CTL, and to both passing and failing properties.  It says whether a
+  passing formula may be strengthened and still pass, and whether a
+  failing formula may be weakened and still fail.  It considers all
+  leaves of a formula that are under one negation parity (e.g., not
+  descendants of a XOR or EQ node) for replacement by either TRUE or
+  FALSE.  See also the -B option.
+  </dd><p>
+
+
+  <dt> -w  &lt;<code>node_file</code>&gt;
+
+  This option invoked the algorithm to generate an error trace divided
+  into fated and free segements. Fate represents the inevitability and
+  free is asserted when there is no inevitability. This can be formulated
+  as a two-player concurrent reachability game. The two players are
+  the environment and the system. The node_file is given to specify the
+  variables the are controlled by the system.
+
+  <dt> -W <dt>
+
+  This option represents the case that all input variables are controlled
+  by system.
+
+  <dt> -G <dt>
+
+  We proposed two algorithm to generate segemented counter example.
+  They are general and restrcited algorithm. Bu default we use restricted
+  algorithm. We can invoke general algorithm with -G option.
+
+  For more information, please check the STTT'04
+  paper of Jin et al., "Fate and Free Will in Error Traces" <p>
+
+  <dt> <code> &lt;ctl_file&gt; </code>
+
+  <dd> File containing CTL formulas to be model checked.
+  </dl>
+
+  Related "set" options:
+  <dl>
+  <dt> ctl_change_bracket &lt;yes/no&gt;
+  <dd> Vl2mv automatically converts "\[\]" to "&lt;&gt;" in node names,
+  therefore CTL parser does the same thing. However, in some cases a user
+  does not want to change node names in CTL parsing. Then, use this set
+  option by giving "no". Default is "yes".
+  <p>
+  <dt>guided_search_hint_type</dt> <dd>Switches between local and
+  global hints (see the -g option, or the help page for set).
+  </dl>
+
+  See also commands : approximate_model_check, incremental_ctl_verification
+  ]
+
+  Description [First argument is a file containing a set of CTL formulas - see
+  ctlp package for grammar. Second argument is an FSM that we will check the
+  formulas on. Formulas are checked by calling the recursive function
+  Mc_ModelCheckFormula. When the formula fails, the debugger is invoked.]
+
+  Comment [Ctlp creates duplicate formulas when converting to
+  existential form; e.g.  when converting AaUb. We aren't using this
+  fact, which leads to some performance degradation.
+
+  A system satisfies a formula if all its initial states are in the satisfying
+  set of the formula.  Hence, we do not need to continue the computation if we
+  know that all initial states are in the satisfying set, or if there are
+  initial states that we are sure are not in the satisfying set.  This is what
+  early termination does: it supplies an extra termination condition for the
+  fixpoints that kicks in when we can decide the truth of the formula.  Note
+  that this leads to some nasty consequences in storing the satisfying sets.
+  A computation that has terminated early does not yield the exact satisfying
+  set, and hence we can not always reuse this result when there is subformula
+  sharing.]
+
+  SideEffects []
+
+  SeeAlso [CommandInv]
+
+******************************************************************************/
+static int
+CommandMc(
+  Hrc_Manager_t **hmgr,
+  int argc,
+  char **argv)
+{
+ /* options */
+  McOptions_t         *options;
+  Mc_VerbosityLevel   verbosity;
+  Mc_DcLevel          dcLevel;
+  FILE                *ctlFile;
+  int                 timeOutPeriod     = 0;
+  Mc_FwdBwdAnalysis   traversalDirection;
+  int                 buildOnionRings   = 0;
+  FILE                *guideFile;
+  FILE                *systemFile;
+  Mc_GuidedSearch_t   guidedSearchType  = Mc_None_c;
+  Ctlp_FormulaArray_t *hintsArray       = NIL(Fsm_HintsArray_t);
+  array_t             *hintsStatesArray = NIL(array_t); /* array of mdd_t* */
+  st_table            *systemVarBddIdTable;
+  boolean             noShare           = 0;
+  Mc_GSHScheduleType  GSHschedule;
+  boolean             checkVacuity;
+  boolean             performCoverageHoskote;
+  boolean             performCoverageImproved;
+
+  /* CTL formulae */
+  array_t *ctlArray;
+  array_t *ctlNormalFormulaArray;
+  int i;
+  int numFormulae;
+  /* FSM, network and image */
+  Fsm_Fsm_t       *totalFsm = NIL(Fsm_Fsm_t);
+  Fsm_Fsm_t       *modelFsm = NIL(Fsm_Fsm_t);
+  Fsm_Fsm_t       *reducedFsm = NIL(Fsm_Fsm_t);
+  Ntk_Network_t   *network;
+  mdd_t           *modelCareStates = NIL(mdd_t);
+  array_t         *modelCareStatesArray = NIL(array_t);
+  mdd_t           *modelInitialStates;
+  mdd_t           *fairStates;
+  Fsm_Fairness_t  *fairCond;
+  mdd_manager     *mddMgr;
+  array_t         *bddIdArray;
+  Img_ImageInfo_t *imageInfo;
+  Mc_EarlyTermination_t *earlyTermination;
+  /* Coverage estimation */
+  mdd_t           *totalcoveredstates = NIL(mdd_t);
+  array_t         *signalTypeList = array_alloc(int,0);
+  array_t         *signalList = array_alloc(char *,0);
+  array_t         *statesCoveredList = array_alloc(mdd_t *,0);
+  array_t         *newCoveredStatesList = array_alloc(mdd_t *,0);
+  array_t         *statesToRemoveList = array_alloc(mdd_t *,0);
+
+  /* Early termination is only partially implemented right now.  It needs
+     distribution over all operators, including limited cases of temporal
+     operators.  That should be relatively easy to implement. */
+
+  /* time keeping */
+  long totalInitialTime; /* for model checking */
+  long initialTime, finalTime; /* for model checking */
+
+  error_init();
+  Img_ResetNumberOfImageComputation(Img_Both_c);
+
+  /* read options */
+  if (!(options = ParseMcOptions(argc, argv))) {
+    return 1;
+  }
+  verbosity = McOptionsReadVerbosityLevel(options);
+  dcLevel = McOptionsReadDcLevel(options);
+  ctlFile = McOptionsReadCtlFile(options);
+  timeOutPeriod = McOptionsReadTimeOutPeriod(options);
+  traversalDirection = McOptionsReadTraversalDirection(options);
+  buildOnionRings =
+    (McOptionsReadDbgLevel(options) != McDbgLevelNone_c || verbosity);
+  noShare = McOptionsReadUseFormulaTree(options);
+  GSHschedule = McOptionsReadSchedule(options);
+  checkVacuity = McOptionsReadVacuityDetect(options);
+   /* for the command mc -C foo.ctl */
+  performCoverageHoskote = McOptionsReadCoverageHoskote(options);
+  /* for the command mc -I foo.ctl */
+  performCoverageImproved = McOptionsReadCoverageImproved(options);
+
+  /* Check for incompatible options and do some option-specific
+   * intializations.
+   */
+
+  if (traversalDirection == McFwd_c) {
+    if (checkVacuity) {
+      fprintf(vis_stderr, "** mc error: -V and -B are incompatible with -F\n");
+      McOptionsFree(options);
+      return 1;
+    }
+    if (performCoverageHoskote || performCoverageImproved) {
+      fprintf(vis_stderr, "** mc error: -I and -C are incompatible with -F\n");
+      McOptionsFree(options);
+      return 1;
+    }
+  }
+
+  if (checkVacuity) {
+    if (performCoverageHoskote || performCoverageImproved) {
+      fprintf(vis_stderr, "** mc error: -I and -C are incompatible with -V and -B\n");
+      McOptionsFree(options);
+      return 1;
+    }
+  }
+
+  guideFile =  McOptionsReadGuideFile(options);
+
+  if(guideFile != NIL(FILE) ){
+    guidedSearchType = Mc_ReadGuidedSearchType();
+    if(guidedSearchType == Mc_None_c){  /* illegal setting */
+      fprintf(vis_stderr, "** mc error: Unknown  hint type\n");
+      fclose(guideFile);
+      McOptionsFree(options);
+      return 1;
+    }
+
+    if(traversalDirection == McFwd_c){  /* illegal combination */
+      fprintf(vis_stderr, "** mc error: -g is incompatible with -F\n");
+      fclose(guideFile);
+      McOptionsFree(options);
+      return 1;
+    }
+
+    if(Img_UserSpecifiedMethod() != Img_Iwls95_c &&
+       Img_UserSpecifiedMethod() != Img_Monolithic_c &&
+       Img_UserSpecifiedMethod() != Img_Mlp_c){
+      fprintf(vis_stderr, "** mc error: -g only works with iwls95, MLP, or monolithic image methods.\n");
+      fclose(guideFile);
+      McOptionsFree(options);
+      return 1;
+    }
+
+    hintsArray = Mc_ReadHints(guideFile);
+    fclose(guideFile); guideFile = NIL(FILE);
+    if( hintsArray == NIL(array_t) ){
+      McOptionsFree(options);
+      return 1;
+    }
+
+  } /* if guided search */
+
+  /* If don't-cares are used, -r implies -c.  Note that the satisfying
+     sets of a subformula are only in terms of propositions therein
+     and their cone of influence.  Hence, we can share satisfying sets
+     among formulae.  I don't quite understand what the problem with
+     don't-cares is (RB) */
+  if (McOptionsReadReduceFsm(options))
+    if (dcLevel != McDcLevelNone_c)
+      McOptionsSetUseFormulaTree(options, TRUE);
+
+  if (traversalDirection == McFwd_c &&
+      McOptionsReadDbgLevel(options) != McDbgLevelNone_c) {
+    McOptionsSetDbgLevel(options, McDbgLevelNone_c);
+    (void)fprintf(vis_stderr, "** mc warning : option -d is ignored.\n");
+  }
+
+  /* Read CTL formulae */
+  ctlArray = Ctlsp_FileParseCTLFormulaArray(ctlFile);
+  fclose(ctlFile); ctlFile = NIL(FILE);
+  if (ctlArray == NIL(array_t)) {
+    (void) fprintf(vis_stderr,
+		   "** mc error: error in parsing formulas from file\n");
+    McOptionsFree(options);
+    return 1;
+  }
+
+  /* read network */
+  network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+  if (network == NIL(Ntk_Network_t)) {
+    fprintf(vis_stdout, "%s\n", error_string());
+    error_init();
+    Ctlp_FormulaArrayFree(ctlArray);
+    McOptionsFree(options);
+    return 1;
+  }
+
+  /* read fsm */
+  totalFsm = Fsm_NetworkReadOrCreateFsm(network);
+  if (totalFsm == NIL(Fsm_Fsm_t)) {
+    fprintf(vis_stdout, "%s\n", error_string());
+    error_init();
+    Ctlp_FormulaArrayFree(ctlArray);
+    McOptionsFree(options);
+    return 1;
+  }
+
+  /* Assign variables to system if doing FAFW */
+  systemVarBddIdTable = NIL(st_table);
+  systemFile = McOptionsReadSystemFile(options);
+  if (systemFile != NIL(FILE)) {
+    systemVarBddIdTable = Mc_ReadSystemVariablesFAFW(totalFsm, systemFile);
+    fclose(systemFile); systemFile = NIL(FILE);
+    if (systemVarBddIdTable == (st_table *)-1 ) { /* FS: error message? */
+      Ctlp_FormulaArrayFree(ctlArray);
+      McOptionsFree(options);
+      return 1;
+    }
+  } /* if FAFW */
+
+  if(options->FAFWFlag && systemVarBddIdTable == 0) {
+    systemVarBddIdTable = Mc_SetAllInputToSystem(totalFsm);
+  }
+
+  if (verbosity > McVerbosityNone_c)
+    totalInitialTime = util_cpu_time();
+  else /* to remove uninitialized variable warning */
+    totalInitialTime = 0;
+
+  if(traversalDirection == McFwd_c){
+    mdd_t *totalInitialStates;
+    double nInitialStates;
+
+    totalInitialStates = Fsm_FsmComputeInitialStates(totalFsm);
+    nInitialStates = mdd_count_onset(Fsm_FsmReadMddManager(totalFsm),
+				     totalInitialStates,
+				     Fsm_FsmReadPresentStateVars(totalFsm));
+    mdd_free(totalInitialStates);
+
+    /* If the number of initial states is only one, we can use both
+     * conversion formulas(init ^ f != FALSE and init ^ !f == FALSE),
+     * however, if we have multiple initial states, we should use
+     * p0 ^ !f == FALSE.
+     */
+    ctlNormalFormulaArray =
+      Ctlp_FormulaArrayConvertToForward(ctlArray, (nInitialStates == 1.0),
+					noShare);
+    /* end conversion for forward traversal */
+  } else if (noShare) { /* conversion for backward, no sharing */
+    ctlNormalFormulaArray =
+      Ctlp_FormulaArrayConvertToExistentialFormTree(ctlArray);
+  }else{ /* conversion for backward, with sharing */
+    /* Note that converting to DAG after converting to existential form would
+       lead to more sharing, but it cannot be done since equal subformula that
+       are converted from different formulae need different pointers back to
+       their originals */
+    if (checkVacuity) {
+      ctlNormalFormulaArray =
+	Ctlp_FormulaArrayConvertToExistentialFormTree(ctlArray);
+    }
+    else {
+      array_t *temp = Ctlp_FormulaArrayConvertToDAG( ctlArray );
+      array_free( ctlArray );
+      ctlArray = temp;
+      ctlNormalFormulaArray =
+	Ctlp_FormulaDAGConvertToExistentialFormDAG(ctlArray);
+    }
+  }
+  /* At this point, ctlNormalFormulaArray contains the formulas that are
+     actually going to be checked, and ctlArray contains the formulas from
+     which the conversion has been done.  Both need to be kept around until the
+     end, for debugging purposes. */
+
+  numFormulae = array_n(ctlNormalFormulaArray);
+
+  /* time out */
+  if (timeOutPeriod > 0) {
+    /* Set the static variables used by the signal handler. */
+    mcTimeOut = timeOutPeriod;
+    alarmLapTime = util_cpu_ctime();
+    (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
+    (void) alarm(timeOutPeriod);
+    if (setjmp(timeOutEnv) > 0) {
+      (void) fprintf(vis_stdout,
+		"# MC: timeout occurred after %d seconds.\n", timeOutPeriod);
+      (void) fprintf(vis_stdout, "# MC: data may be corrupted.\n");
+      if (verbosity > McVerbosityNone_c) {
+	fprintf(vis_stdout, "-- total %d image computations and %d preimage computations\n",
+		Img_GetNumberOfImageComputation(Img_Forward_c),
+		Img_GetNumberOfImageComputation(Img_Backward_c));
+      }
+      alarm(0);
+      return 1;
+    }
+  }
+
+  /* Create reduced fsm, if necessary */
+  if (!McOptionsReadReduceFsm(options)){
+    /* We want to minimize only when "-r" option is not specified */
+    /* reduceFsm would be NIL, if there is no reduction observed */
+    assert (reducedFsm == NIL(Fsm_Fsm_t));
+    reducedFsm = McConstructReducedFsm(network, ctlNormalFormulaArray);
+    if (reducedFsm != NIL(Fsm_Fsm_t) && verbosity != McVerbosityNone_c) {
+      mddMgr = Fsm_FsmReadMddManager(reducedFsm);
+      bddIdArray = mdd_id_array_to_bdd_id_array(mddMgr,
+		   Fsm_FsmReadPresentStateVars(reducedFsm));
+      (void)fprintf(vis_stdout,"Local system includes ");
+      (void)fprintf(vis_stdout,"%d (%d) multi-value (boolean) variables.\n",
+		    array_n(Fsm_FsmReadPresentStateVars(reducedFsm)),
+		    array_n(bddIdArray));
+      array_free(bddIdArray);
+    }
+  }
+
+  /************** for all formulae **********************************/
+  for(i = 0; i < numFormulae; i++) {
+    int nImgComps, nPreComps;
+    boolean result;
+    Ctlp_Formula_t *ctlFormula = array_fetch(Ctlp_Formula_t *,
+					     ctlNormalFormulaArray, i);
+
+    modelFsm = NIL(Fsm_Fsm_t);
+
+    /* do a check */
+    if (!Mc_FormulaStaticSemanticCheckOnNetwork(ctlFormula, network, FALSE)) {
+      (void) fprintf(vis_stdout,
+		     "** mc error: error in parsing Atomic Formula:\n%s\n",
+		     error_string());
+      error_init();
+      Ctlp_FormulaFree(ctlFormula);
+      continue;
+    }
+
+    /* Create reduced fsm */
+    if (McOptionsReadReduceFsm(options)) {
+      /* We have not done top level reduction. */
+      /* Using the same variable reducedFsm here   */
+      array_t *oneFormulaArray = array_alloc(Ctlp_Formula_t *, 1);
+
+      assert(reducedFsm == NIL(Fsm_Fsm_t));
+      array_insert_last(Ctlp_Formula_t *, oneFormulaArray, ctlFormula);
+      reducedFsm = McConstructReducedFsm(network, oneFormulaArray);
+      array_free(oneFormulaArray);
+
+      if (reducedFsm && verbosity != McVerbosityNone_c) {
+	mddMgr = Fsm_FsmReadMddManager(reducedFsm);
+	bddIdArray = mdd_id_array_to_bdd_id_array(mddMgr,
+		       Fsm_FsmReadPresentStateVars(reducedFsm));
+	(void)fprintf(vis_stdout,"Local system includes ");
+	(void)fprintf(vis_stdout,"%d (%d) multi-value (boolean) variables.\n",
+		      array_n(Fsm_FsmReadPresentStateVars(reducedFsm)),
+		      array_n(bddIdArray));
+	array_free(bddIdArray);
+      }
+    }/* if readreducefsm */
+
+    /* Let us see if we got any reduction via top level or via "-r" */
+    if (reducedFsm == NIL(Fsm_Fsm_t))
+      modelFsm = totalFsm; /* no reduction */
+    else
+      modelFsm = reducedFsm; /* some reduction at some point */
+
+    /* compute initial states */
+    modelInitialStates = Fsm_FsmComputeInitialStates(modelFsm);
+    if (modelInitialStates == NIL(mdd_t)) {
+      int j;
+      (void) fprintf(vis_stdout,
+      "** mc error: Cannot build init states (mutual latch dependency?)\n%s\n",
+		     error_string());
+      if (modelFsm != totalFsm)
+	Fsm_FsmFree(reducedFsm);
+
+      alarm(0);
+
+      for(j = i; j < numFormulae; j++)
+	Ctlp_FormulaFree(
+	  array_fetch( Ctlp_Formula_t *, ctlNormalFormulaArray, j ) );
+      array_free( ctlNormalFormulaArray );
+
+      Ctlp_FormulaArrayFree( ctlArray );
+
+      McOptionsFree(options);
+
+      return 1;
+    }
+
+    earlyTermination = Mc_EarlyTerminationAlloc(McAll_c, modelInitialStates);
+
+    if(hintsArray != NIL(Ctlp_FormulaArray_t)) {
+      hintsStatesArray = Mc_EvaluateHints(modelFsm, hintsArray);
+      if( hintsStatesArray == NIL(array_t) ||
+	  (guidedSearchType == Mc_Global_c &&
+	   Ctlp_CheckClassOfExistentialFormula(ctlFormula) == Ctlp_Mixed_c)) {
+	int j;
+
+	if( guidedSearchType == Mc_Global_c &&
+	    Ctlp_CheckClassOfExistentialFormula(ctlFormula) == Ctlp_Mixed_c)
+	  fprintf(vis_stderr, "** mc error: global hints incompatible with "
+		  "mixed formulae\n");
+
+	Mc_EarlyTerminationFree(earlyTermination);
+	mdd_free(modelInitialStates);
+	if (modelFsm != totalFsm)
+	  Fsm_FsmFree(reducedFsm);
+	alarm(0);
+	for(j = i; j < numFormulae; j++)
+	  Ctlp_FormulaFree(
+	    array_fetch( Ctlp_Formula_t *, ctlNormalFormulaArray, j ) );
+	array_free( ctlNormalFormulaArray );
+	Ctlp_FormulaArrayFree( ctlArray );
+	McOptionsFree(options);
+	return 1;
+      } /* problem with hints */
+    } /* hints exist */
+
+    /* stats */
+    if (verbosity > McVerbosityNone_c) {
+      initialTime = util_cpu_time();
+      nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c);
+      nPreComps = Img_GetNumberOfImageComputation(Img_Backward_c);
+    } else { /* to remove uninitialized variable warnings */
+      initialTime = 0;
+      nImgComps = 0;
+      nPreComps = 0;
+    }
+    mddMgr = Fsm_FsmReadMddManager(modelFsm);
+
+    /* compute don't cares. */
+    if (modelCareStatesArray == NIL(array_t)) {
+      long iTime; /* starting time for reachability analysis */
+      if (verbosity > McVerbosityNone_c && i == 0)
+	iTime = util_cpu_time();
+      else /* to remove uninitialized variable warnings */
+	iTime = 0;
+
+      /* ardc */
+      if (dcLevel == McDcLevelArdc_c) {
+	Fsm_ArdcOptions_t *ardcOptions = McOptionsReadArdcOptions(options);
+
+	modelCareStatesArray = Fsm_ArdcComputeOverApproximateReachableStates(
+	  modelFsm, 0, verbosity, 0, 0, 0, 0, 0, 0, ardcOptions);
+	if (verbosity > McVerbosityNone_c && i == 0)
+	  Fsm_ArdcPrintReachabilityResults(modelFsm, util_cpu_time() - iTime);
+
+      /* rch dc */
+      } else if (dcLevel >= McDcLevelRch_c) {
+	modelCareStates =
+	  Fsm_FsmComputeReachableStates(modelFsm, 0, 1, 0, 0, 0, 0, 0,
+					Fsm_Rch_Default_c, 0, 0,
+					NIL(array_t), FALSE, NIL(array_t));
+	if (verbosity > McVerbosityNone_c && i == 0) {
+	  Fsm_FsmReachabilityPrintResults(modelFsm, util_cpu_time() - iTime,
+					  Fsm_Rch_Default_c);
+	}
+
+	modelCareStatesArray = array_alloc(mdd_t *, 0);
+	array_insert(mdd_t *, modelCareStatesArray, 0, modelCareStates);
+      } else {
+	modelCareStates = mdd_one(mddMgr);
+	modelCareStatesArray = array_alloc(mdd_t *, 0);
+	array_insert(mdd_t *, modelCareStatesArray, 0, modelCareStates);
+      }
+    }
+
+    Fsm_MinimizeTransitionRelationWithReachabilityInfo(
+      modelFsm, (traversalDirection == McFwd_c) ? Img_Both_c : Img_Backward_c,
+      verbosity > 1);
+
+    /* fairness conditions */
+    fairStates = Fsm_FsmComputeFairStates(modelFsm, modelCareStatesArray,
+					  verbosity, dcLevel, GSHschedule,
+					  McBwd_c, FALSE);
+    fairCond = Fsm_FsmReadFairnessConstraint(modelFsm);
+
+    if (mdd_lequal(modelInitialStates, fairStates, 1, 0)) {
+      (void)fprintf(vis_stdout,
+		    "** mc warning: There are no fair initial states\n");
+    }
+    else if (!mdd_lequal(modelInitialStates, fairStates, 1, 1)) {
+      (void)fprintf(vis_stdout,
+		    "** mc warning: Some initial states are not fair\n");
+    }
+
+    /* some user feedback */
+    if (verbosity != McVerbosityNone_c) {
+      (void)fprintf(vis_stdout, "Checking formula[%d] : ", i + 1);
+      Ctlp_FormulaPrint(vis_stdout,
+			Ctlp_FormulaReadOriginalFormula(ctlFormula));
+      (void)fprintf (vis_stdout, "\n");
+      if (traversalDirection == McFwd_c) {
+	(void)fprintf(vis_stdout, "Forward formula : ");
+	Ctlp_FormulaPrint(vis_stdout, ctlFormula);
+	(void)fprintf(vis_stdout, "\n");
+      }
+    }
+
+    /************** the actual computation **********************************/
+    if (checkVacuity) {
+      McVacuityDetection(modelFsm, ctlFormula, i,
+			 fairStates, fairCond, modelCareStatesArray,
+			 earlyTermination, hintsStatesArray,
+			 guidedSearchType, modelInitialStates,
+			 options);
+    }
+    else { /* Normal Model Checking */
+      mdd_t *ctlFormulaStates =
+	Mc_FsmEvaluateFormula(modelFsm, ctlFormula, fairStates,
+			      fairCond, modelCareStatesArray,
+			      earlyTermination, hintsStatesArray,
+			      guidedSearchType, verbosity, dcLevel,
+			      buildOnionRings, GSHschedule);
+
+      McEstimateCoverage(modelFsm, ctlFormula, i, fairStates, fairCond,
+			 modelCareStatesArray, earlyTermination,
+			 hintsStatesArray, guidedSearchType, verbosity,
+			 dcLevel, buildOnionRings, GSHschedule,
+			 traversalDirection, modelInitialStates,
+			 ctlFormulaStates, &totalcoveredstates,
+			 signalTypeList, signalList, statesCoveredList,
+			 newCoveredStatesList, statesToRemoveList,
+			 performCoverageHoskote, performCoverageImproved);
+
+      Mc_EarlyTerminationFree(earlyTermination);
+      if(hintsStatesArray != NIL(array_t))
+	mdd_array_free(hintsStatesArray);
+      /* Set up things for possible FAFW analysis of counterexample. */
+      Fsm_FsmSetFAFWFlag(modelFsm, options->FAFWFlag);
+      Fsm_FsmSetSystemVariableFAFW(modelFsm, systemVarBddIdTable);
+      /* user feedback on succes/fail */
+      result = McPrintPassFail(mddMgr, modelFsm, traversalDirection,
+			       ctlFormula, ctlFormulaStates,
+			       modelInitialStates, modelCareStatesArray,
+			       options, verbosity);
+      Fsm_FsmSetFAFWFlag(modelFsm, 0);
+      Fsm_FsmSetSystemVariableFAFW(modelFsm, NULL);
+      mdd_free(ctlFormulaStates);
+    }
+
+    if (verbosity > McVerbosityNone_c) {
+      finalTime = util_cpu_time();
+      fprintf(vis_stdout, "-- mc time = %10g\n",
+	(double)(finalTime - initialTime) / 1000.0);
+      fprintf(vis_stdout,
+	      "-- %d image computations and %d preimage computations\n",
+	      Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps,
+	      Img_GetNumberOfImageComputation(Img_Backward_c) - nPreComps);
+    }
+    mdd_free(modelInitialStates);
+    mdd_free(fairStates);
+    Ctlp_FormulaFree(ctlFormula);
+
+    if ((McOptionsReadReduceFsm(options)) &&
+	(reducedFsm != NIL(Fsm_Fsm_t))) {
+      /*
+      ** We need to free the reducedFsm only if it was created under "-r"
+      ** option and was non-NIL.
+      */
+      Fsm_FsmFree(reducedFsm);
+      reducedFsm = NIL(Fsm_Fsm_t);
+      modelFsm = NIL(Fsm_Fsm_t);
+      if (modelCareStates) {
+	mdd_array_free(modelCareStatesArray);
+	modelCareStates = NIL(mdd_t);
+	modelCareStatesArray = NIL(array_t);
+      } else if (modelCareStatesArray) {
+	modelCareStatesArray = NIL(array_t);
+      }
+    }
+  }/* for all formulae */
+
+  if (verbosity > McVerbosityNone_c) {
+    finalTime = util_cpu_time();
+    fprintf(vis_stdout, "-- total mc time = %10g\n",
+      (double)(finalTime - totalInitialTime) / 1000.0);
+    fprintf(vis_stdout,
+	    "-- total %d image computations and %d preimage computations\n",
+	    Img_GetNumberOfImageComputation(Img_Forward_c),
+	    Img_GetNumberOfImageComputation(Img_Backward_c));
+    /* Print tfm options if we have a global fsm. */
+    if (!McOptionsReadReduceFsm(options) && modelFsm != NIL(Fsm_Fsm_t)) {
+      imageInfo = Fsm_FsmReadImageInfo(modelFsm);
+      if (Img_ImageInfoObtainMethodType(imageInfo) == Img_Tfm_c ||
+	  Img_ImageInfoObtainMethodType(imageInfo) == Img_Hybrid_c) {
+	Img_TfmPrintStatistics(imageInfo, Img_Both_c);
+      }
+    }
+  }
+
+  /* Print results of coverage computation */
+  McPrintCoverageSummary(modelFsm, dcLevel,
+			 options, modelCareStatesArray,
+			 modelCareStates, totalcoveredstates,
+			 signalTypeList, signalList, statesCoveredList,
+			 performCoverageHoskote, performCoverageImproved);
+  mdd_array_free(newCoveredStatesList);
+  mdd_array_free(statesToRemoveList);
+  array_free(signalTypeList);
+  array_free(signalList);
+  mdd_array_free(statesCoveredList);
+  if (totalcoveredstates != NIL(mdd_t))
+    mdd_free(totalcoveredstates);
+
+  if (modelCareStates) {
+    mdd_array_free(modelCareStatesArray);
+  }
+
+  if(hintsArray)
+    Ctlp_FormulaArrayFree(hintsArray);
+
+  if ((McOptionsReadReduceFsm(options) == FALSE) &&
+      (reducedFsm != NIL(Fsm_Fsm_t))) {
+    /* If "-r" was not specified and we did some reduction at top
+       level, we need to free it */
+    Fsm_FsmFree(reducedFsm);
+    reducedFsm = NIL(Fsm_Fsm_t);
+    modelFsm = NIL(Fsm_Fsm_t);
+  }
+
+  if(systemVarBddIdTable)
+    st_free_table(systemVarBddIdTable);
+  array_free(ctlNormalFormulaArray);
+  (void) fprintf(vis_stdout, "\n");
+
+  Ctlp_FormulaArrayFree(ctlArray);
+  McOptionsFree(options);
+  alarm(0);
+  return 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Parse command line options for mc.]
+
+  SideEffects []
+
+******************************************************************************/
+static McOptions_t *
+ParseMcOptions(
+  int argc,
+  char **argv)
+{
+  unsigned int i;
+  int c;
+  char *guideFileName = NIL(char);
+  char *variablesForSystem = NIL(char);
+  FILE *guideFile = NIL(FILE);
+  FILE *systemFile = NIL(FILE);
+  boolean doCoverageHoskote = FALSE;
+  boolean doCoverageImproved = FALSE;
+  boolean useMore = FALSE;
+  boolean reduceFsm = FALSE;
+  boolean printInputs = FALSE;
+  boolean useFormulaTree = FALSE;
+  boolean vd = FALSE;
+  boolean beer = FALSE;
+  boolean FAFWFlag = FALSE;
+  boolean GFAFWFlag = FALSE;
+  FILE *inputFp=NIL(FILE);
+  FILE *debugOut=NIL(FILE);
+  char *debugOutName=NIL(char);
+  Mc_DcLevel dcLevel = McDcLevelRch_c;
+  McDbgLevel dbgLevel = McDbgLevelNone_c;
+  Mc_VerbosityLevel verbosityLevel = McVerbosityNone_c;
+  Mc_FwdBwdAnalysis fwdBwd = McFwd_c;
+  McOptions_t *options = McOptionsAlloc();
+  int timeOutPeriod = 0;
+  Mc_FwdBwdAnalysis traversalDirection = McBwd_c;
+  Fsm_ArdcOptions_t *ardcOptions;
+  Mc_GSHScheduleType schedule = McGSH_EL_c;
+
+  /*
+   * Parse command line options.
+   */
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "bcirmg:hv:d:D:VBf:t:CIFR:S:GWw:")) != EOF) {
+    switch(c) {
+    case 'g':
+      guideFileName = util_strsav(util_optarg);
+      break;
+    case 'h':
+      goto usage;
+    case 'v':
+      for (i = 0; i < strlen(util_optarg); i++) {
+	if (!isdigit((int)util_optarg[i])) {
+	  goto usage;
+	}
+      }
+      verbosityLevel = (Mc_VerbosityLevel) atoi(util_optarg);
+      break;
+    case 'd':
+      for (i = 0; i < strlen(util_optarg); i++) {
+	if (!isdigit((int)util_optarg[i])) {
+	  goto usage;
+	}
+      }
+      dbgLevel = (McDbgLevel) atoi(util_optarg);
+      break;
+    case 'D':
+      for (i = 0; i < strlen(util_optarg); i++) {
+	if (!isdigit((int)util_optarg[i])) {
+	  goto usage;
+	}
+      }
+      dcLevel = (Mc_DcLevel) atoi(util_optarg);
+      break;
+    case 'b':
+      fwdBwd = McBwd_c;
+      break;
+    case 'V':	      /*Vacuity detection option*/
+      vd = TRUE;
+      break;
+    case 'B':	      /*Vacuity detection Beer et al method option*/
+      vd = TRUE;
+      beer = TRUE;
+      break;
+    case 'f':
+      debugOutName = util_strsav(util_optarg);
+      break;
+    case 'm':
+      useMore = TRUE;
+      break;
+    case 'r' :
+      reduceFsm = TRUE;
+      break;
+    case 'c':
+      useFormulaTree = TRUE;
+      break;
+    case 't' :
+      timeOutPeriod  = atoi(util_optarg);
+      break;
+    case 'i' :
+      printInputs = TRUE;
+      break;
+    case 'F' :
+      traversalDirection = McFwd_c;
+      break;
+    case 'S' :
+      schedule = McStringConvertToScheduleType(util_optarg);
+      break;
+    case 'w':
+      variablesForSystem = util_strsav(util_optarg);
+    case 'W':
+      FAFWFlag = 1;
+      break;
+    case 'G':
+      GFAFWFlag = 1;
+      break;
+    case 'C' :
+      doCoverageHoskote = TRUE;
+      break;
+    case 'I' :
+      doCoverageImproved = TRUE;
+      break;
+    default:
+      goto usage;
+    }
+  }
+
+  /*
+   * Open the ctl file.
+   */
+  if (argc - util_optind == 0) {
+    (void) fprintf(vis_stderr, "** mc error: file containing ctl formulas not provided\n");
+    goto usage;
+  }
+  else if (argc - util_optind > 1) {
+    (void) fprintf(vis_stderr, "** mc error: too many arguments\n");
+    goto usage;
+  }
+
+  McOptionsSetFwdBwd(options, fwdBwd);
+  McOptionsSetUseMore(options, useMore);
+  McOptionsSetReduceFsm(options, reduceFsm);
+  McOptionsSetVacuityDetect(options, vd);
+  McOptionsSetBeerMethod(options, beer);
+  McOptionsSetUseFormulaTree(options, useFormulaTree);
+  McOptionsSetPrintInputs(options, printInputs);
+  McOptionsSetTimeOutPeriod(options, timeOutPeriod);
+  McOptionsSetFAFWFlag(options, FAFWFlag + GFAFWFlag);
+  McOptionsSetCoverageHoskote(options, doCoverageHoskote);
+  McOptionsSetCoverageImproved(options, doCoverageImproved);
+
+  if((FAFWFlag > 0 || GFAFWFlag > 0) &&  dbgLevel == 0) {
+    fprintf(vis_stderr, "** mc warning : -w and -W options are ignored without -d option\n");
+  }
+
+  if((FAFWFlag > 0 || GFAFWFlag > 0) &&  printInputs == 0) {
+    fprintf(vis_stderr, "** mc warning : -i is recommended with -w or -W option\n");
+  }
+  if(FAFWFlag) {
+    if (bdd_get_package_name() != CUDD) {
+      fprintf(vis_stderr, "** mc warning : -w and -W option is only available with CUDD\n");
+      FAFWFlag = 0;
+      FREE(variablesForSystem);
+      variablesForSystem = NIL(char);
+    }
+  }
+
+
+  if (schedule == McGSH_Unassigned_c) {
+    (void) fprintf(vis_stderr, "unknown schedule: %s\n", util_optarg);
+    goto usage;
+  } else {
+    McOptionsSetSchedule(options, schedule);
+  }
+  inputFp = Cmd_FileOpen(argv[util_optind], "r", NIL(char *), 0);
+  if (inputFp == NIL(FILE)) {
+    McOptionsFree(options);
+    if (guideFileName != NIL(char)) FREE(guideFileName);
+    return NIL(McOptions_t);
+  }
+  McOptionsSetCtlFile(options, inputFp);
+
+  if (debugOutName != NIL(char)) {
+    debugOut = Cmd_FileOpen(debugOutName, "w", NIL(char *), 0);
+    FREE(debugOutName);
+    if (debugOut == NIL(FILE)) {
+      McOptionsFree(options);
+      if (guideFileName != NIL(char)) FREE(guideFileName);
+      return NIL(McOptions_t);
+    }
+  }
+  McOptionsSetDebugFile(options, debugOut);
+
+
+  if (guideFileName != NIL(char)) {
+    guideFile = Cmd_FileOpen(guideFileName, "r", NIL(char *), 0);
+    if (guideFile == NIL(FILE)) {
+      fprintf(vis_stderr, "** mc error: cannot open guided search file %s.\n",
+	      guideFileName);
+      FREE(guideFileName);
+      guideFileName = NIL(char);
+      McOptionsFree(options);
+      return NIL(McOptions_t);
+    }
+    FREE(guideFileName);
+    guideFileName = NIL(char);
+  }
+  McOptionsSetGuideFile(options, guideFile);
+
+  if (variablesForSystem != NIL(char)) {
+    systemFile = Cmd_FileOpen(variablesForSystem, "r", NIL(char *), 0);
+    if (systemFile == NIL(FILE)) {
+      fprintf(vis_stderr, "** mc error: cannot open system variables file for FAFW %s.\n",
+	      variablesForSystem);
+      FREE(variablesForSystem);
+      variablesForSystem = NIL(char);
+      McOptionsFree(options);
+      return NIL(McOptions_t);
+    }
+    FREE(variablesForSystem);
+    variablesForSystem = NIL(char);
+  }
+  McOptionsSetVariablesForSystem(options, systemFile);
+
+  if ((verbosityLevel != McVerbosityNone_c) &&
+       (verbosityLevel != McVerbosityLittle_c) &&
+       (verbosityLevel != McVerbositySome_c) &&
+       (verbosityLevel != McVerbosityMax_c)) {
+    goto usage;
+  }
+  else {
+    McOptionsSetVerbosityLevel(options, verbosityLevel);
+  }
+
+  if ((dbgLevel != McDbgLevelNone_c) &&
+       (dbgLevel != McDbgLevelMin_c) &&
+       (dbgLevel != McDbgLevelMinVerbose_c) &&
+       (dbgLevel != McDbgLevelMax_c) &&
+       (dbgLevel != McDbgLevelInteractive_c)) {
+    goto usage;
+  }
+  else {
+    McOptionsSetDbgLevel(options, dbgLevel);
+  }
+
+  if ((dcLevel != McDcLevelNone_c) &&
+       (dcLevel != McDcLevelRch_c ) &&
+       (dcLevel != McDcLevelRchFrontier_c ) &&
+       (dcLevel != McDcLevelArdc_c )) {
+    goto usage;
+  }
+  else {
+    McOptionsSetDcLevel(options, dcLevel);
+  }
+
+  McOptionsSetTraversalDirection(options, traversalDirection);
+  if (dcLevel == McDcLevelArdc_c) {
+    ardcOptions = Fsm_ArdcAllocOptionsStruct();
+    Fsm_ArdcGetDefaultOptions(ardcOptions);
+  } else
+    ardcOptions = NIL(Fsm_ArdcOptions_t);
+  McOptionsSetArdcOptions(options, ardcOptions);
+
+  return options;
+
+  usage:
+  (void) fprintf(vis_stderr, "usage: model_check [-b][-c][-d dbg_level][-f dbg_file][-g <hintfile>][-h][-i][-m][-r][-V][-B][-t period][-C][-I][-P][-v verbosity_level][-D dc_level][-F][-S <schedule>] <ctl_file>\n");
+  (void) fprintf(vis_stderr, "    -b \tUse backward analysis in debugging\n");
+  (void) fprintf(vis_stderr, "    -c \tNo sharing of CTL parse tree. This option does not matter for vacuity detection.\n");
+  (void) fprintf(vis_stderr, "    -d <dbg_level>\n");
+  (void) fprintf(vis_stderr, "        debug_level = 0 => no debugging (Default)\n");
+  (void) fprintf(vis_stderr, "        debug_level = 1 => automatic minimal debugging\n");
+  (void) fprintf(vis_stderr, "        debug_level = 2 => automatic minimal debugging with extra verbosity\n");
+  (void) fprintf(vis_stderr, "        debug_level = 3 => automatic maximal debugging\n");
+  (void) fprintf(vis_stderr, "        debug_level = 4 => interactive debugging\n");
+  (void) fprintf(vis_stderr, "    -f <dbg_out>\n");
+  (void) fprintf(vis_stderr, "        write error trace to dbg_out\n");
+  (void) fprintf(vis_stderr, "    -g <hint_file> \tSpecify file for guided search.\n");
+  (void) fprintf(vis_stderr, "    -h \tPrints this usage message.\n");
+  (void) fprintf(vis_stderr, "    -i \tPrint input values in debug traces.\n");
+  (void) fprintf(vis_stderr, "    -m \tPipe debug output through more.\n");
+  (void) fprintf(vis_stderr, "    -r  reduce FSM with respect to formula being verified\n");
+  (void) fprintf(vis_stderr, "    -t <period> time out period\n");
+  (void) fprintf(vis_stderr, "    -v <verbosity_level>\n");
+  (void) fprintf(vis_stderr, "        verbosity_level = 0 => no feedback (Default)\n");
+  (void) fprintf(vis_stderr, "        verbosity_level = 1 => code status\n");
+  (void) fprintf(vis_stderr, "        verbosity_level = 2 => code status and CPU usage profile\n");
+  (void) fprintf(vis_stderr, "    -w <node file> \tSpecify variables controlled by system.\n");
+  (void) fprintf(vis_stderr, "    -B  vacuity detection for w-ACTL formulae using method of Beer et al \n");
+  (void) fprintf(vis_stderr, "    -C Compute coverage of all observable signals using Hoskote et.al's implementation\n");
+  (void) fprintf(vis_stderr, "    -D <dc_level>\n");
+  (void) fprintf(vis_stderr, "        dc_level = 0 => no use of don't cares\n");
+  (void) fprintf(vis_stderr, "        dc_level = 1 => use unreached states as don't cares (Default)\n");
+  (void) fprintf(vis_stderr, "        dc_level = 2 => use unreached states as don't cares\n");
+
+  (void) fprintf(vis_stderr, "                        and aggressive use of DC's to simplify MDD's\n");
+  (void) fprintf(vis_stderr, "        dc_level = 3 => use over-approximate unreached states as don't cares\n");
+  (void) fprintf(vis_stderr, "                        and aggressive use of DC's to simplify MDD's\n");
+  (void) fprintf(vis_stderr, "    -F \tUse forward model checking.\n");
+  (void) fprintf(vis_stderr, "    -G \tUse general fate and free will algorithm.\n");
+  (void) fprintf(vis_stderr, "    -I Compute coverage of all observable signals using improved coverage implementation\n");
+  (void) fprintf(vis_stderr, "    -S <schedule>\n");
+  (void) fprintf(vis_stderr, "       schedule is one of {EL,EL1,EL2,budget,random,off}\n");
+  (void) fprintf(vis_stderr, "    -V  thorough vacuity detection\n");
+  (void) fprintf(vis_stderr, "    -W \tUse fate and free will algorithm when all the variables are controlled by system.\n");
+  (void) fprintf(vis_stderr, "    <ctl_file> The input file containing CTL formula to be checked.\n");
+
+  if (guideFileName != NIL(char)) FREE(guideFileName);
+  McOptionsFree(options);
+
+  return NIL(McOptions_t);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Check whether language of FSM is empty.]
+
+  CommandName [lang_empty]
+
+  CommandSynopsis [perform language emptiness check on a flattened network]
+
+  CommandArguments [ \[-b\] \[-d &lt;dbg_level&gt;\] \[-f &lt;dbg_file&gt;\]
+  \[-h\] \[-i\] \[-s\] \[-t &lt;time_out_period&gt;\]
+  \[-v &lt;verbosity_level&gt;\]
+  \[-A &lt;le_method&gt;\] \[-D &lt;dc_level&gt;\]
+  \[-S &lt;schedule&gt;\] \[-L &lt;lockstep_mode&gt;\] ]
+
+  CommandDescription [
+  Performs language emptiness check on a flattened network.  The
+  language is not empty when there is a fair path starting at an
+  initial state.  Before calling this command, the user should have
+  initialized the design by calling the command <A
+  HREF="init_verifyCmd.html"> <code> init_verify</code></A>.  <p>
+
+  A fairness constraint can be read in by calling the
+  <A HREF="read_fairnessCmd.html"><code>read_fairness</code></A> command;
+  if none is specified, all paths are taken to be fair.
+  <p>
+
+  The system is reduced automatically with respect to the set of
+  fairness constraints.  If the language is not empty, a proof of this
+  fact is generated.  A proof is a fair path starting at an initial
+  state.  This is represented by a finite sequence of states starting
+  at an initial state (the stem) leading to a fair cycle, i.e., a
+  cycle on which there lies a state from each fairness condition.
+  <p>
+
+  Command options:
+  <p>
+
+  <dl>
+
+  <dt> -b
+  <dd> Use backward analysis when performing debugging; the default is to use forward
+	   analysis. This should be tried when the debugger spends a large amount of time when
+	   creating a path to a fair cycle.
+  <p>
+
+  <dt> -d <code> &lt;dbg_level&gt; </code>
+  <dd> Specify whether to demonstrate a proof of the language non-emptiness
+  <p>
+  <dd>
+  <code> dbg_level</code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: No debugging  performed. This is the default.
+  <p>
+
+  <code> 1 </code>: Generate a path to a fair cycle.
+  <p>
+
+  <dt> -f &lt;<code>dbg_file</code>&gt;
+  <dd> Write the debugger output to <code>dbg_file</code>.
+  <p>
+
+  <dt> -h
+  <dd> Print the command usage.
+  <p>
+
+  <dt> -m
+  <dd> Pipe debugger output through the UNIX utility more.
+  <p>
+
+  <dt> -i
+  <dd> Print input values causing transitions between states during debugging.
+  Both primary and pseudo inputs are printed.
+  <p>
+
+  <dt> -s
+  <dd> Print debug output in the format accepted by the
+       <A HREF="simulateCmd.html"><code>simulate</code></A> command.
+  <p>
+
+  <dt> -t  <code>&lt;timeOutPeriod&gt;</code>
+  <dd> Specify the time out period (in seconds) after which the command
+  aborts.  By default this option is set to infinity.
+  <p>
+
+  <dt> -v  <code>&lt;verbosity_level&gt;</code>
+  <dd> Specify verbosity level. This sets the amount of feedback on CPU
+  usage and code status.
+  <p>
+
+  <dd>
+  <code>verbosity_level</code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: No feedback provided. This is the default.<p>
+
+  <code> 1 </code>: Feedback on code location.<p>
+
+  <code> 2 </code>: Feedback on code location and CPU usage.<p>
+
+  <dt> -A <code> &lt;le_method&gt; </code>
+  <dd>
+  Specify whether the compositional SCC analysis algorithm, Divide and
+  Compose (DnC), is enabled for language emptiness checking.
+  The DnC algorithm first enumerates fair SCCs in an over-approximated
+  abstract model, and then successively refines them in the more
+  concrete models.
+  Since non-fair SCCs can be ignored in the more concrete models, a
+  potentially large part of the state space are pruned away early on
+  when the computations are cheap.
+  <p>
+
+  <dd>
+  <code> le_method </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: no use of Divide and Compose (Default). <p>
+  <code> 1 </code>: use Divide and Compose. <p>
+
+  <dt> -D <code> &lt;dc_level&gt; </code>
+  <dd> Specify extent to which don't cares are used to simplify MDDs.
+  Don't cares are minterms on which the value taken by functions does not affect the computation;
+  potentially, these minterms can be used to simplify MDDs and reduce time taken to perform
+  MDD computations.
+  <p>
+
+  <dd>
+  <code> dc_level </code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: No don't cares are used. <p>
+  <code> 1 </code>: Use unreachable states as don't cares.  This is the
+  default. <p>
+
+  <dt> -S <code> &lt;schedule&gt; </code>
+
+  <dd> Specify schedule for GSH algorithm, which generalizes the
+  Emerson-Lei algorithm and is used to compute greatest fixpoints.
+  The choice of schedule affects the sequence in which EX and EU
+  operators are applied.  It makes a difference only when fairness
+  constraints are specified.
+
+  <br>
+  <code> &lt;schedule&gt; </code> must be one of the following:
+
+  <p> <code> EL </code>: EU and EX operators strictly alternate.  This
+  is the default.
+
+  <p> <code> EL1 </code>: EX is applied once for every application of all EUs.
+
+  <p> <code> EL2 </code>: EX is applied repeatedly after each application of
+  all EUs.
+
+  <p> <code> budget </code>: a hybrid of EL and EL2.
+
+  <p> <code> random </code>: enabled operators are applied in
+  (pseudo-)random order.
+
+  <p> <code> off </code>: GSH is disabled, and the old algorithm is
+  used instead.  The old algorithm uses the <code> EL </code>, but the
+  termination checks are less sophisticated than in GSH.
+  <p>
+
+  <dt> -F
+
+  <dd> Use forward analysis in the computation of the greatest fixpoint.
+  This option is incompatible with -d 1 or higher and can only be used
+  with -D 1.
+
+  <dt> -L <code> &lt;lockstep_mode&gt; </code>
+
+  <dd> Use the lockstep algorithm, which is based on fair SCC enumeration.
+
+  <br>
+  <code> &lt;lockstep_mode&gt; </code> must be one of the following:
+
+  <p> <code> off </code>: Lockstep is disabled.  This is the default.
+  Language emptiness is checked by computing a hull of the fair SCCs.
+
+  <p> <code> on </code>: Lockstep is enabled.
+
+  <p> <code> all </code>: Lockstep is enabled; all fair SCCs are
+  enumerated instead of terminating as soon as one is found.  This can
+  be used to study the SCCs of a graph, but it is slower than the
+  default option.
+
+  <p> <code> n </code>: (n is a positive integer).  Lockstep is
+  enabled and up to <code> n </code> fair SCCs are enumerated.  This
+  is less expensive than <code> all </code>, but still less efficient
+  than <code> on </code>, even when <code> n = 1 </code>.
+
+  </dl>
+
+  ]
+
+  SideEffects []
+
+  SeeAlso []
+
+******************************************************************************/
+static int
+CommandLe(
+  Hrc_Manager_t **hmgr,
+  int argc,
+  char **argv)
+{
+  McOptions_t *options;
+  Mc_VerbosityLevel verbosity;
+  Mc_LeMethod_t leMethod;
+  Mc_DcLevel dcLevel;
+  McDbgLevel dbgLevel;
+  FILE *dbgFile= NIL(FILE);
+  boolean printInputs = FALSE;
+  int timeOutPeriod = 0;
+  Mc_GSHScheduleType GSHschedule;
+  Mc_FwdBwdAnalysis GSHdirection;
+  int lockstep;
+  int useMore;
+  int simValue;
+  int reduceFsm_flag = 1;
+  long startRchTime;
+  mdd_t *modelCareStates;
+  Fsm_Fsm_t *totalFsm;
+  Fsm_Fsm_t *modelFsm, *reducedFsm = NIL(Fsm_Fsm_t);
+  mdd_t *fairInitStates;
+  array_t *modelCareStatesArray;
+  long initialTime, finalTime; /* for lang_empty checking */
+
+  Img_ResetNumberOfImageComputation(Img_Both_c);
+
+  /* Read options and set timeout if requested. */
+  if (!(options = ParseLeOptions(argc, argv))) {
+    return 1;
+  }
+
+  totalFsm = Fsm_HrcManagerReadCurrentFsm(*hmgr);
+  if (totalFsm == NIL(Fsm_Fsm_t)) {
+    (void) fprintf(vis_stdout, "%s\n", error_string());
+    error_init();
+    McOptionsFree(options);
+    return 1;
+  }
+
+  initialTime = util_cpu_time();
+
+  verbosity     = McOptionsReadVerbosityLevel(options);
+  leMethod      = McOptionsReadLeMethod(options);
+  dcLevel       = McOptionsReadDcLevel(options);
+  dbgLevel      = McOptionsReadDbgLevel(options);
+  printInputs   = McOptionsReadPrintInputs(options);
+  timeOutPeriod = McOptionsReadTimeOutPeriod(options);
+  GSHschedule   = McOptionsReadSchedule(options);
+  GSHdirection  = McOptionsReadTraversalDirection(options);
+  lockstep      = McOptionsReadLockstep(options);
+  dbgFile       = McOptionsReadDebugFile(options);
+  useMore       = McOptionsReadUseMore(options);
+  simValue      = McOptionsReadSimValue(options);
+
+  if (dbgLevel != McDbgLevelNone_c && GSHdirection == McFwd_c) {
+    (void) fprintf(vis_stderr, "** le error: -d is incompatible with -F\n");
+    McOptionsFree(options);
+    return 1;
+  }
+  if (dcLevel !=  McDcLevelRch_c && GSHdirection == McFwd_c) {
+    (void) fprintf(vis_stderr, "** le error: -F can only be used with -D1\n");
+    McOptionsFree(options);
+    return 1;
+  }
+
+  if (timeOutPeriod > 0) {
+    /* Set the static variables used by the signal handler. */
+    mcTimeOut = timeOutPeriod;
+    alarmLapTime  = util_cpu_ctime();
+    (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
+    (void) alarm(timeOutPeriod);
+    if (setjmp(timeOutEnv) > 0) {
+      (void) fprintf(vis_stdout,
+		     "# LE: language emptiness - timeout occurred after %d seconds.\n",
+		     timeOutPeriod);
+      (void) fprintf(vis_stdout, "# LE: data may be corrupted.\n");
+      if (verbosity > McVerbosityNone_c) {
+	(void) fprintf(vis_stdout,
+		       "-- total %d image computations and %d preimage computations\n",
+		       Img_GetNumberOfImageComputation(Img_Forward_c),
+		       Img_GetNumberOfImageComputation(Img_Backward_c));
+      }
+      alarm(0);
+      return 1;
+    }
+  }
+
+  /* Reduce FSM to cone of influence of fairness constraints. */
+  if (reduceFsm_flag) {
+    Ntk_Network_t *network = Fsm_FsmReadNetwork(totalFsm);
+    array_t *ctlNormalFormulaArray = array_alloc(Ctlp_Formula_t *, 0);
+    reducedFsm = McConstructReducedFsm(network, ctlNormalFormulaArray);
+    array_free(ctlNormalFormulaArray);
+  }
+
+  if (reducedFsm == NIL(Fsm_Fsm_t)) {
+    modelFsm = totalFsm;
+  }else {
+    modelFsm = reducedFsm;
+  }
+
+  /* Find care states and put them in an array */
+  if (dcLevel == McDcLevelArdc_c) { /* aRDC */
+    Fsm_ArdcOptions_t *ardcOptions = Fsm_ArdcAllocOptionsStruct();
+    array_t *tmpArray;
+    Fsm_ArdcGetDefaultOptions(ardcOptions);
+
+    if (verbosity > 0)
+      startRchTime = util_cpu_time();
+    else /* to remove uninitialized variable warning */
+      startRchTime = 0;
+    tmpArray = Fsm_ArdcComputeOverApproximateReachableStates(
+      modelFsm, 0, verbosity, 0, 0, 0, 0, 0, 0, ardcOptions);
+    modelCareStatesArray = mdd_array_duplicate(tmpArray);
+
+    FREE(ardcOptions);
+
+    if (verbosity > 0 )
+      Fsm_ArdcPrintReachabilityResults(modelFsm,
+				       util_cpu_time() - startRchTime);
+
+  }else if (dcLevel >= McDcLevelRch_c) { /*RDC*/
+    if (verbosity > 0)
+      startRchTime = util_cpu_time();
+    else /* to remove uninitialized variable warning */
+      startRchTime = 0;
+    modelCareStates =
+      Fsm_FsmComputeReachableStates(modelFsm, 0, verbosity, 0, 0,
+				    (lockstep != MC_LOCKSTEP_OFF), 0, 0,
+				    Fsm_Rch_Default_c, 0, 0,
+				    NIL(array_t), FALSE, NIL(array_t));
+    if (verbosity > 0) {
+      Fsm_FsmReachabilityPrintResults(modelFsm,
+				      util_cpu_time() - startRchTime,
+				      Fsm_Rch_Default_c);
+    }
+    modelCareStatesArray = array_alloc(mdd_t *, 0);
+    array_insert_last(mdd_t *, modelCareStatesArray, modelCareStates);
+
+  } else {  /* mdd_one */
+    modelCareStates = mdd_one(Fsm_FsmReadMddManager(modelFsm));
+    modelCareStatesArray = array_alloc(mdd_t *, 0);
+    array_insert_last(mdd_t *, modelCareStatesArray, modelCareStates);
+  }
+
+
+  fairInitStates = Mc_FsmCheckLanguageEmptiness(modelFsm,
+						modelCareStatesArray,
+						Mc_Aut_Strong_c,
+						leMethod,
+						dcLevel,
+						dbgLevel,
+						printInputs,
+						verbosity,
+						GSHschedule,
+						GSHdirection,
+						lockstep,
+						dbgFile,
+						useMore,
+						simValue,
+						"LE");
+
+  if (verbosity > McVerbosityNone_c) {
+    finalTime = util_cpu_time();
+    fprintf(vis_stdout, "-- total le time = %10g\n",
+	    (double)(finalTime - initialTime) / 1000.0);
+    fprintf(vis_stdout,
+	    "-- total %d image computations and %d preimage computations\n",
+	    Img_GetNumberOfImageComputation(Img_Forward_c),
+	    Img_GetNumberOfImageComputation(Img_Backward_c));
+  }
+
+  /* Clean up. */
+  if (fairInitStates) {
+    mdd_free(fairInitStates);
+  }
+  mdd_array_free(modelCareStatesArray);
+  McOptionsFree(options);
+  if (reducedFsm) {
+    Fsm_FsmFree(reducedFsm);
+  }
+
+  alarm(0);
+  return 0;
+
+} /* CommandLe */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Parse command line options for lang_empty.]
+
+  SideEffects []
+
+******************************************************************************/
+static McOptions_t *
+ParseLeOptions(
+  int argc,
+  char **argv)
+{
+  unsigned int i;
+  int c;
+  boolean useSimFormat = FALSE;
+  FILE *debugOut=NIL(FILE);
+  char *debugOutName=NIL(char);
+  Mc_DcLevel dcLevel = McDcLevelRch_c;
+  Mc_LeMethod_t leMethod = Mc_Le_Default_c;
+  McDbgLevel dbgLevel = McDbgLevelNone_c;
+  Mc_VerbosityLevel verbosityLevel = McVerbosityNone_c;
+  Mc_FwdBwdAnalysis fwdBwd = McFwd_c;
+  McOptions_t *options = McOptionsAlloc();
+  boolean printInputs = FALSE;
+  boolean useMore = FALSE;
+  int timeOutPeriod = 0;
+  Mc_GSHScheduleType schedule = McGSH_EL_c;
+  Mc_FwdBwdAnalysis direction = McBwd_c;
+  int lockstep = MC_LOCKSTEP_OFF;
+  Fsm_ArdcOptions_t *ardcOptions;
+
+  /*
+   * Parse command line options.
+   */
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "bihmt:v:d:A:D:f:sS:L:F")) != EOF) {
+    switch(c) {
+    case 'h':
+      goto usage;
+    case 'v':
+      for (i = 0; i < strlen(util_optarg); i++) {
+	if (!isdigit((int)util_optarg[i])) {
+	  goto usage;
+	}
+      }
+      verbosityLevel = (Mc_VerbosityLevel) atoi(util_optarg);
+      break;
+    case 'd':
+      for (i = 0; i < strlen(util_optarg); i++) {
+	if (!isdigit((int)util_optarg[i])) {
+	  goto usage;
+	}
+      }
+      dbgLevel = (McDbgLevel) atoi(util_optarg);
+      break;
+    case 'A':
+      for (i = 0; i < strlen(util_optarg); i++) {
+	if (!isdigit((int)util_optarg[i])) {
+	  goto usage;
+	}
+      }
+      leMethod = (Mc_LeMethod_t) atoi(util_optarg);
+      break;
+    case 'D':
+      for (i = 0; i < strlen(util_optarg); i++) {
+	if (!isdigit((int)util_optarg[i])) {
+	  goto usage;
+	}
+      }
+      dcLevel = (Mc_DcLevel) atoi(util_optarg);
+      break;
+    case 'f':
+      debugOutName = util_strsav(util_optarg);
+      break;
+    case 's':
+      useSimFormat = TRUE;
+      break;
+    case 't':
+      timeOutPeriod = atoi(util_optarg);
+      break;
+    case 'i':
+      printInputs = TRUE;
+      break;
+    case 'm':
+      useMore = TRUE;
+      break;
+    case 'b':
+      fwdBwd = McBwd_c;
+      break;
+    case 'S' :
+      schedule = McStringConvertToScheduleType(util_optarg);
+      break;
+    case 'L' :
+      lockstep = McStringConvertToLockstepMode(util_optarg);
+      break;
+    case 'F' :
+      direction = McFwd_c;
+      break;
+    default:
+      goto usage;
+    }
+  }
+
+  if (schedule == McGSH_Unassigned_c) {
+    (void) fprintf(vis_stderr, "unknown schedule: %s\n", util_optarg);
+    goto usage;
+  } else {
+    McOptionsSetSchedule(options, schedule);
+  }
+  McOptionsSetTraversalDirection(options, direction);
+  if (lockstep == MC_LOCKSTEP_UNASSIGNED) {
+    (void) fprintf(vis_stderr, "invalid lockstep option: %s\n", util_optarg);
+    goto usage;
+  } else {
+    McOptionsSetLockstep(options, lockstep);
+  }
+  if ((verbosityLevel != McVerbosityNone_c) &&
+       (verbosityLevel != McVerbosityLittle_c) &&
+       (verbosityLevel != McVerbositySome_c) &&
+       (verbosityLevel != McVerbosityMax_c)) {
+    goto usage;
+  }
+  else {
+    McOptionsSetVerbosityLevel(options, verbosityLevel);
+  }
+
+  if (debugOutName != NIL(char)) {
+    debugOut = Cmd_FileOpen(debugOutName, "w", NIL(char *), 0);
+    if (debugOut == NIL(FILE)) {
+      McOptionsFree(options);
+      return NIL(McOptions_t);
+    }
+  }
+  McOptionsSetDebugFile(options, debugOut);
+
+  if ((dbgLevel != McDbgLevelNone_c) &&
+       (dbgLevel != McDbgLevelMin_c)) {
+    goto usage;
+  }
+  else {
+    McOptionsSetDbgLevel(options, dbgLevel);
+  }
+
+  if ((dcLevel != McDcLevelNone_c)  &&
+       (dcLevel != McDcLevelRch_c )  &&
+       (dcLevel != McDcLevelRchFrontier_c )  &&
+       (dcLevel != McDcLevelArdc_c )) {
+    goto usage;
+  }
+  else {
+    McOptionsSetDcLevel(options, dcLevel);
+  }
+
+  if ((leMethod != Mc_Le_Default_c) &&
+      (leMethod != Mc_Le_Dnc_c)) {
+    goto usage;
+  }
+  else {
+    McOptionsSetLeMethod(options, leMethod);
+  }
+
+  /* set Ardc options for le : C.W. */
+  if (dcLevel == McDcLevelArdc_c) {
+      ardcOptions = Fsm_ArdcAllocOptionsStruct();
+      Fsm_ArdcGetDefaultOptions(ardcOptions);
+  } else
+      ardcOptions = NIL(Fsm_ArdcOptions_t);
+  McOptionsSetArdcOptions(options, ardcOptions);
+
+  McOptionsSetFwdBwd(options, fwdBwd);
+  McOptionsSetSimValue(options, useSimFormat);
+  McOptionsSetUseMore(options, useMore);
+  McOptionsSetPrintInputs(options, printInputs);
+  McOptionsSetTimeOutPeriod(options, timeOutPeriod);
+  return options;
+
+  usage:
+  (void) fprintf(vis_stderr, "usage: lang_empty [-b][-d dbg_level][-f dbg_file][-h][-i][-m][-s][-t period][-v verbosity_level][-A <le_method>][-D <dc_level>][-S <schedule>][-F][-L <lockstep_mode>]\n");
+  (void) fprintf(vis_stderr, "    -b \tUse backward analysis in debugging\n");
+  (void) fprintf(vis_stderr, "    -d <dbg_level>\n");
+  (void) fprintf(vis_stderr, "        debug_level = 0 => no debugging (Default)\n");
+  (void) fprintf(vis_stderr, "        debug_level = 1 => automatic debugging\n");
+  (void) fprintf(vis_stderr, "    -f <dbg_out>\n");
+  (void) fprintf(vis_stderr, "        write error trace to dbg_out\n");
+  (void) fprintf(vis_stderr, "    -h \tPrints this usage message.\n");
+  (void) fprintf(vis_stderr, "    -i \tPrint input values in debug traces.\n");
+  (void) fprintf(vis_stderr, "    -m \tPipe debug output through more\n");
+  (void) fprintf(vis_stderr, "    -s \tWrite error trace in sim format.\n");
+  (void) fprintf(vis_stderr, "    -t <period> time out period\n");
+  (void) fprintf(vis_stderr, "    -v <verbosity_level>\n");
+  (void) fprintf(vis_stderr, "        verbosity_level = 0 => no feedback (Default)\n");
+  (void) fprintf(vis_stderr, "        verbosity_level = 1 => feedback\n");
+  (void) fprintf(vis_stderr, "        verbosity_level = 2 => feedback and CPU usage profile\n");
+  (void) fprintf(vis_stderr, "    -A <le_method>\n");
+  (void) fprintf(vis_stderr, "        le_method = 0 => no use of Divide and Compose (Default)\n");
+  (void) fprintf(vis_stderr, "        le_method = 1 => use Divide and Compose\n");
+  (void) fprintf(vis_stderr, "    -D <dc_level>\n");
+  (void) fprintf(vis_stderr, "        dc_level = 0 => no use of don't cares\n");
+  (void) fprintf(vis_stderr, "        dc_level = 1 => use unreached states as don't cares (Default)\n");
+  (void) fprintf(vis_stderr, "        dc_level = 2 => use unreached states as don't cares\n");
+
+  (void) fprintf(vis_stderr, "                        and aggressive use of DC's to simplify MDD's\n");
+  (void) fprintf(vis_stderr, "        dc_level = 3 => use over-approximate unreached states as don't cares\n");
+  (void) fprintf(vis_stderr, "                        and aggressive use of DC's to simplify MDD's\n");
+  (void) fprintf(vis_stderr, "    -S <schedule>\n");
+  (void) fprintf(vis_stderr, "       schedule is one of {EL,EL1,EL2,budget,random,off}\n");
+  (void) fprintf(vis_stderr, "    -F \tUse forward analysis in fixpoint computation.\n");
+  (void) fprintf(vis_stderr, "    -L <lockstep_mode>\n");
+  (void) fprintf(vis_stderr, "       lockstep_mode is one of {off,on,all,n}\n");
+
+  McOptionsFree(options);
+
+  return NIL(McOptions_t);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [checks that all reachable states in flattened network satisfy invariants]
+
+  CommandName [check_invariant]
+
+  CommandSynopsis [check all states reachable in flattened network satisfy specified invariants]
+
+  CommandArguments [ \[-c\] \[-d &lt;dbg_level&gt;\] \[-g
+  &lt;<code>hints_file</code>&gt;\] \[-f\] \[-h\] \[-i\] \[-m\] \[-r\]
+  \[-t &lt;time_out_period&gt;\] \[-v &lt;verbosity_level&gt;\] \[-A &lt;reachability_analysis_type&gt;\] \[-D\] &lt;invar_file&gt;]
+
+  CommandDescription [Performs invariant checking on a flattened
+  network.  Before calling this command, the user should have
+  initialized the design by calling the command <A
+  HREF="init_verifyCmd.html"> <code> init_verify</code></A>.
+  <p>
+
+  If the option -A3 (abstraction refinement method GRAB) is used, the command
+  <A
+  HREF="build_partition_maigsCmd.html"><code>build_partition_maigs</code></A>
+  should also have been executed. However, in this case, the default BDD
+  manager and network partition are not mandatory, though they will be used if
+  available. (In other words, the user must run the commands <A
+  HREF="flatten_hierarchyCmd.html"><code> flatten_hierarchy</code></A> and <A
+  HREF="build_partition_maigsCmd.html"><code>build_partition_maigs</code></A>, but
+  doesn't have to run the commands <A
+  HREF="static_orderCmd.html"><code>static_order</code></A> and <A
+  HREF="build_partition_mddsCmd.html"><code>build_partition_mdds</code></A> before
+  calling this command.) For extremely large networks, it is actually favorable
+  not to build them for the entire concrete model, but let this procedure
+  assign bdd ids and construct the partition incrementally.
+
+  <p>
+
+  Option -A4 means abstraction refinement approach using puresat algorithm,
+  which is entirely based on SAT solver.
+  <p>
+
+  An invariant is a set of states.
+  Checking the invariant is the process of determining that all states reachable
+  from the initial states lie in the invariant.
+  <p>
+
+
+  One way of defining an invariant is through a CTL formula which has no path operators.
+  Such formulas should be specified in the file <code>invar_file</code>.
+  Note that the support  of any wire referred to in a formula should consist only
+  of latches.
+  For the precise syntax of CTL formulas,
+  see the <A HREF="../ctl/ctl/ctl.html"> VIS CTL and LTL syntax manual</A>.
+  <p>
+
+  <code>check_invariant</code> ignores all fairness conditions associated with the FSM.
+  <p>
+
+  <code>check_invariant<code> involves reachability analysis where at
+   every step of the reachability computation all the specified
+   invariants are checked in the reachable states computed thus
+   far. If some invariant does not hold, a proof of failure is
+   demonstrated. This consists of a path starting from an initial
+   state to a state lying outside the invariant. This path is made as
+   short as possible. For the -A 0 option or default -A option, it is
+   the shortest path leading to a state outside the invariant. If a
+   set of invariants is specified, the failed formulas are reported as
+   soon as they are detected. The check is continued with the
+   remaining invariants.<p>
+
+  Command options:
+  <p>
+
+  <dl>
+
+  <dt> -d <code> &lt;dbg_level&gt; </code>
+  <dd> Specify the amount of debugging performed when the system fails a formula being checked.
+  <p>
+  <dd>
+  <code> dbg_level</code> must be one of the following:
+  <p>
+
+  <code> 0 </code>: No debugging  performed. This is the default.
+  <p>
+
+  <code> 1 </code>: Generate a path from an initial state to a state
+  lying outside the invariant. This option stores the onion rings just
+  as specifying -f would have. Therefore, it may take more time and
+  memory if the formula passes. This option is incompatible with -A 2
+  option. <p>
+
+  <dt> -f
+  <dd> Store the set of new states (onion rings) reached at each step of
+  invariant. This option is likely to use more memory but possibly
+  faster results for invariants that fail. Therefore, the debug
+  information for a failed invariant, if requested, may be provided
+  faster. This option is not compatible with -A 2 options.<p>
+
+  <dt> -g &lt;<code>hints_file</code>&gt;</dt>
+
+  <dd> Use guided search.  The file <code>hints_file</code> contains a
+  series of hints.  A hint is a formula that does not contain any
+  temporal operators, so <code>hints_file</code> has the same syntax
+  as a file of invariants used for check_invariant.  The hints are
+  used in the order given to change the transition relation.  The
+  transition relation is conjoined with the hint to yield an
+  underapproximation of the transition relation.  If the hints are
+  cleverly chosen, this may speed up the computation considerably,
+  because a search with the changed transition relation may be much
+  simpler than one with the original transition relation, and results
+  obtained can be reused, so that we may never have to do an expensive
+  search with the original relation.  See also: Ravi and Somenzi,
+  Hints to accelerate symbolic traversal. CHARME'99; Bloem, Ravi, and
+  Somenzi, Efficient Decision Procedures for Model Checking of Linear
+  Time Logic Properties, CAV'99; Bloem, Ravi, and Somenzi, Symbolic
+  Guided Search for CTL Model Checking, DAC'00. This option is not
+  compatible with -A 2 option. The description of some options for
+  guided search can be found in the help page for
+  print_guided_search_options. <p>
+
+  <dt> -h
+  <dd> Print the command usage.
+  <p>
+
+  <dt> -c
+  <dd> Use the formula tree so that subformulae are not shared among the CTL
+  formulae in the input file. This option is useful in the following
+  scenario - formulae A, B and C are being checked in order and there is
+  sub-formula sharing between A and C. If the BDDs corresponding to the shared
+  sub-formula is huge then computation for B might not be able to finish
+  without using this option.
+  <p>
+
+  <dt> -i
+  <dd> Print input values causing transitions between states during
+  debugging. Both primary and pseudo inputs are printed.  <p>
+
+  <dt> -m
+  <dd> Pipe debugger output through the UNIX utility  more.
+  <p>
+
+  <dt> -r
+  <dd> Reduce the FSM derived from the flattened network with respect to each
+  of the invariants in the input file. By default, the FSM is reduced with
+  respect to the conjunction of the invariants in the input file. If this
+  option is used and don't cares are being used for simplification, then
+  subformula sharing is disabled (result might be incorrect otherwise).
+  <p>
+
+  <dd> The truth of  an invariant  may be independant  of  parts of the network (such as when wires have
+  been abstracted; see <A HREF="flatten_hierarchyCmd.html"><code>flatten_hierarchy</code></A>).
+  These parts are effectively removed when this option is invoked; this may result in
+  more efficient invariant checking.
+  <p>
+
+  <dt> -t  <code>&lt;timeOutPeriod&gt;</code>
+  <dd> Specify the time out period (in seconds) after which the command aborts. By default this option is set to infinity.
+  <p>
+  <dt> -v  <code>&lt;verbosity_level&gt;</code>
+  <dd> Specify verbosity level. This sets the amount of feedback  on CPU usage and code status.
+  <p>
+
+  <dd>
+  <code>verbosity_level</code>  must be one of the following:
+  <p>
+
+  <code> 0 </code>: No feedback provided. This is the default.<p>
+
+  <code> 1 </code>: Feedback on code location.<p>
+
+  <code> 2 </code>: Feedback on code location and CPU usage.<p>
+
+  <dt> -A &lt;reachability_analysis_type&gt;
+  <dd> This option allows specification of the type of reachability computation. <p>
+
+  0:  (default) Breadth First Search. No approximate reachability computation. <p>
+
+  1: High Density Reachability Analysis (HD). Computes reachable states in a
+  manner that keeps BDD sizes under control. May be faster than BFS in some
+  cases. For larger circuits, this option could compute more reachable states
+  than the -A 0 option for the same memory constraints, consequently may prove
+  more invariants false. For help on controlling options for HD, look up help
+  on the command: print_hd_options <A HREF="print_hd_optionsCmd.html"> <code>
+  print_hd_options</code></A>. Refer Ravi & Somenzi, ICCAD95.  The path
+  generated for a failed invariant using this method may not be the shortest
+  path. This option is available only when compiled with the CUDD package. <p>
+
+  2. Approximate Reachability Don't Cares(ARDC). Computes over-approximated
+  reachable states in the reachability analysis step. This may be faster than
+  the -A 0 option . The invariants are checked in the over-approximation. This
+  may produce false negatives, but these are resolved internally using the
+  exact reachable states. The final results produced are the same as those for
+  exact reachable states. For help on controlling options for ARDC, look up
+  help on the command: print_ardc_options. <A
+  HREF="print_ardc_optionsCmd.html"><code> print_ardc_options</code></A> Refer
+  2 papers in TCAD96 Dec. Cho et al, one is for State Space Decomposition and
+  the other is for Approximate FSM Traversal. This option is incompatible with
+  -d 1 and -g options.<p>
+
+  3. The GRAB Abstraction Refinement Method. Conducts the reachability
+  analysis on an abstract model. If the invariants are true in the
+  abstract model, they are also true in the original model. If the
+  invariants are false, the abstract counter-examples are used to
+  refine the abstract model (since it is still inconclusive). This
+  procedure iterates until a conclusive result is reached.  Note that,
+  with this option, "build_partitioned_mdds" and "static_order" does
+  not have to be executed before calling "check_invariants," though
+  the default BDD partition and order will be reused if available.
+  (When checking extremely large models, skipping either or both
+  "static_order" and "build_partitioned_mdds" can often make the
+  verification much faster.)  The grainularity of abstraction
+  refinement also depends on the parameter "partition_threshold",
+  which by default is 5000; one can use the VIS command "set
+  partition_threshold 1000" to change its value. For experienced users
+  who want to fine-tune the different parameters of GRAB, please try
+  the test command "_grab_test" ("_grab_test -h" prints out its usage
+  information).  Refer to Wang et al., ICCAD2003 and ICCD2004 for more
+  information about the GRAB algorithm. Note that this option is
+  incompatible with the "-d 1" and "-g" options.  <p>
+
+  4. Abstraction refinement approach using puresat algorithm, which is
+  entirely based on SAT solver. It has several parts:
+
+  * Localization base Abstraction
+  * K-induction to prove the truth of a property
+  * Bounded Model Checking to find bugs
+  * Incremental concretization based methods to verify abstract bugs
+  * UNSAT proof based method to obtain refinement
+  * Refinement minization to guarrantee a minimal refinement
+
+  For more information, please check the BMC'03 and STTT'05
+  paper of Li et al., "A satisfiability-based appraoch to abstraction
+  refinement in model checking", and " Abstraction in symbolic model checking
+  using satisfiability as the only decision procedure" <p>
+
+  <dt> -D</dt>
+
+  <dd>First compute an overapproximation to the reachable states.  Minimize the
+  transition relation using this approximation, and then compute the set of
+  reachable states exactly. This may accelerate reachability analysis. Refer to
+  the paper by Moon et al, ICCAD98. The BDD minimizing method can be chosen by
+  using "set image_minimize_method <method>" <A HREF = "setCmd.html">
+  <code>set</code></A>.  This option is incompatible with -g.  <p>
+
+  <dt> -F &lt;<code>dbg_file</code>&gt;
+  <dd> Write the debugger output to <code>dbg_file</code>.
+  <p>
+
+  <dt> -w  &lt;<code>node_file</code>&gt;
+
+  This option invokes the algorithm to generate an error trace divided
+  into fated and free segements. Fate represents the inevitability and
+  free is asserted when there is no inevitability. This can be formulated
+  as a two-player concurrent reachability game. The two players are
+  the environment and the system. The node_file is given to specify the
+  variables the are controlled by the system.
+
+  <dt> -W <dt>
+
+  This option represents the case that all input variables are controlled
+  by system.
+
+  <dt> -G <dt>
+
+  We proposed two algorithms to generate segmented counterexamples:
+  general and restricted. By default we use the restricted
+  algorithm. We can invoke the general algorithm with -G option.
+
+  For more information, please read the STTT'04
+  paper by Jin et al., "Fate and Free Will in Error Traces" <p>
+
+  <dt> &lt;invarFile&gt;
+  <dd> File containing invariants to be checked.
+  <p>
+  </dl>
+
+  <dt> Related "set" options: <p>
+  <dt> rch_simulate &lt;#&gt;
+  <dd> The set option can be used to set this flag rch_simulate to specify the
+  number of random vectors to be simulated. Default value for this number is 0.
+  <p>
+
+  <dt> ctl_change_bracket &lt;yes/no&gt;
+  <dd> Vl2mv automatically converts "\[\]" to "&lt;&gt;" in node names,
+  therefore CTL parser does the same thing. However, in some cases a user
+  does not want to change node names in CTL parsing. Then, use this set
+  option by giving "no". Default is "yes".
+  <p>
+
+  <dt> See also command : compute_reach <p>
+
+
+  ]
+
+  SideEffects []
+
+  SeeAlso [CommandMc]
+
+******************************************************************************/
+static int
+CommandInv(
+  Hrc_Manager_t **hmgr,
+  int argc,
+  char **argv)
+{
+  int i, j;
+  mdd_t *tautology;
+  McOptions_t *options;
+  FILE *invarFile;
+  array_t *invarArray, *formulas, *sortedFormulaArray;
+  static Fsm_Fsm_t *totalFsm, *modelFsm;
+  mdd_manager *mddMgr;
+  Ntk_Network_t *network;
+  Mc_VerbosityLevel verbosity;
+  Mc_DcLevel dcLevel;
+  array_t *invarNormalFormulaArray, *invarStatesArray;
+  int timeOutPeriod = 0;
+  int debugFlag;
+  int buildOnionRings;
+  Fsm_RchType_t approxFlag;
+  int ardc;
+  int someLeft;
+  Ctlp_Formula_t *invarFormula;
+  mdd_t *invarFormulaStates;
+  mdd_t *reachableStates;
+  array_t *fsmArray;
+  int printStep = 0;
+  long initTime, finalTime;
+  array_t *careSetArray;
+  FILE              *guideFile;
+  FILE		*systemFile;
+  st_table      *systemVarBddIdTable;
+  Ctlp_FormulaArray_t *hintsArray    = NIL(Fsm_HintsArray_t);
+  array_t             *hintsStatesArray = NIL(array_t); /* array of mdd_t* */
+
+  error_init();
+  initTime = util_cpu_time();
+
+  /* get command line options */
+  if (!(options = ParseInvarOptions(argc, argv))) {
+    return 1;
+  }
+  verbosity = McOptionsReadVerbosityLevel(options);
+  dcLevel = McOptionsReadDcLevel(options);
+  invarFile = McOptionsReadCtlFile(options);
+  timeOutPeriod = McOptionsReadTimeOutPeriod(options);
+  approxFlag = McOptionsReadInvarApproxFlag(options);
+  buildOnionRings = (int)McOptionsReadInvarOnionRingsFlag(options);
+
+  /* read the array of invariants */
+  invarArray = Ctlp_FileParseFormulaArray(invarFile);
+  fclose(invarFile);
+  if (invarArray == NIL(array_t)) {
+    (void) fprintf(vis_stderr, "** inv error: Error in parsing invariants from file\n");
+    McOptionsFree(options);
+    return 1;
+  }
+  if (array_n(invarArray) == 0) {
+    (void) fprintf(vis_stderr, "** inv error: No formula in file\n");
+    McOptionsFree(options);
+    return 1;
+  }
+
+  /* read the netwrok */
+  network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+  if (network == NIL(Ntk_Network_t)) {
+    fprintf(vis_stderr, "%s\n", error_string());
+    error_init();
+    McOptionsFree(options);
+    return 1;
+  }
+
+  /**************************************************************************
+   * if "-A 3" is enabled (using the abstraction refinement method GRAB ),
+   *    call GRAB.
+   **************************************************************************/
+  if (approxFlag == Fsm_Rch_Grab_c) {
+
+    if (Ntk_NetworkReadMAigManager(network) == NIL(mAig_Manager_t)) {
+      McOptionsFree(options);
+      fprintf(vis_stderr,
+	      "** inv error: To use GRAB, please run build_partition_maigs first\n");
+      /*McOptionsFree(options);*/
+      return 1;
+    }
+
+    if (timeOutPeriod > 0) {
+      /* Set the static variables used by the signal handler. */
+      mcTimeOut = timeOutPeriod;
+      alarmLapTime = util_cpu_ctime();
+      (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
+      (void) alarm(timeOutPeriod);
+      if (setjmp(timeOutEnv) > 0) {
+	(void) fprintf(vis_stdout,
+	   "# INV: Checking Invariant: timeout occurred after %d seconds.\n",
+		       timeOutPeriod);
+	(void) fprintf(vis_stdout, "# INV: data may be corrupted.\n");
+	alarm(0);
+	return 1;
+      }
+    }
+
+    Grab_NetworkCheckInvariants(network,
+				invarArray,
+				"GRAB", /* refineAlgorithm, */
+				TRUE,   /* fineGrainFlag, */
+				TRUE,   /* refineMinFlag, */
+				FALSE,  /* useArdcFlag, */
+				2,      /* cexType = SOR */
+				verbosity,
+				McOptionsReadDbgLevel(options),
+				McOptionsReadPrintInputs(options),
+				McOptionsReadDebugFile(options),
+				McOptionsReadUseMore(options),
+				"INV" /* driverName */
+				);
+    McOptionsFree(options);
+    return 0;
+  }
+
+  if (approxFlag == Fsm_Rch_PureSat_c) {
+
+    if (Ntk_NetworkReadMAigManager(network) == NIL(mAig_Manager_t)) {
+      McOptionsFree(options);
+      fprintf(vis_stderr,
+	      "** inv error: Please run build_partition_maigs first\n");
+      McOptionsFree(options);
+      return 1;
+    }
+
+    if (timeOutPeriod > 0) {
+      /* Set the static variables used by the signal handler. */
+      mcTimeOut = timeOutPeriod;
+      alarmLapTime = util_cpu_ctime();
+      (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
+      (void) alarm(timeOutPeriod);
+      if (setjmp(timeOutEnv) > 0) {
+	(void) fprintf(vis_stdout,
+	   "# INV by PURESAT: Checking Invariant using PURESAT: timeout occurred after %d seconds.\n",
+		       timeOutPeriod);
+	(void) fprintf(vis_stdout, "# INV by PURESAT: data may be corrupted.\n");
+	alarm(0);
+	return 1;
+      }
+    }
+    PureSat_CheckInvariant(network,invarArray,
+			   (int)options->verbosityLevel,
+			   options->dbgLevel,McOptionsReadDebugFile(options),
+			   McOptionsReadPrintInputs(options),options->incre,
+			   options->sss, options->flatIP, options->IPspeed);
+    McOptionsFree(options);
+    return 0;
+  }
+  guideFile =  McOptionsReadGuideFile(options);
+
+  if(guideFile != NIL(FILE) ){
+    hintsArray = Mc_ReadHints(guideFile);
+    fclose(guideFile); guideFile = NIL(FILE);
+    if( hintsArray == NIL(array_t) ){
+      McOptionsFree(options);
+      return 1;
+    }
+  } /* if guided search */
+
+  if(Img_UserSpecifiedMethod() != Img_Iwls95_c &&
+     Img_UserSpecifiedMethod() != Img_Monolithic_c &&
+     Img_UserSpecifiedMethod() != Img_Mlp_c &&
+     guideFile != NIL(FILE)){
+    fprintf(vis_stdout,
+ "** inv error: The Tfm and Hybrid image methods are incompatible with -g\n");
+    McOptionsFree(options);
+    return 1;
+  }
+
+  if (dcLevel == McDcLevelArdc_c)
+    ardc = 1;
+  else
+    ardc = 0;
+
+  /* obtain the fsm and mdd manager */
+  totalFsm = Fsm_NetworkReadOrCreateFsm(network);
+  if (totalFsm == NIL(Fsm_Fsm_t)) {
+    fprintf(vis_stderr, "%s\n", error_string());
+    error_init();
+    McOptionsFree(options);
+    return 1;
+  }
+
+  systemVarBddIdTable = 0;
+  systemFile = McOptionsReadSystemFile(options);
+  if(systemFile != NIL(FILE) ){
+    systemVarBddIdTable = Mc_ReadSystemVariablesFAFW(totalFsm, systemFile);
+    fclose(systemFile); systemFile = NIL(FILE);
+    if(systemVarBddIdTable == (st_table *)-1 ){
+      McOptionsFree(options);
+      return 1;
+    }
+  } /* if FAFW */
+
+  if(options->FAFWFlag && systemVarBddIdTable == 0) {
+    systemVarBddIdTable = Mc_SetAllInputToSystem(totalFsm);
+  }
+
+  mddMgr = Fsm_FsmReadMddManager(totalFsm);
+  tautology = mdd_one(mddMgr);
+
+  /* set time out */
+  if (timeOutPeriod > 0) {
+    /* Set the static variables used by the signal handler. */
+    mcTimeOut = timeOutPeriod;
+    alarmLapTime = util_cpu_ctime();
+    (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
+    (void) alarm(timeOutPeriod);
+    if (setjmp(timeOutEnv) > 0) {
+      (void) fprintf(vis_stdout, "# INV: Checking Invariant: timeout occurred after %d seconds.\n", timeOutPeriod);
+      (void) fprintf(vis_stdout, "# INV: data may be corrupted.\n");
+      alarm(0);
+      return 1;
+    }
+  }
+
+  /* debugFlag = 1 -> need to store/compute onion shells, else not */
+  debugFlag = (McOptionsReadDbgLevel(options) != McDbgLevelNone_c);
+
+  /* use formula tree if reduce option and dont-care level is high */
+  if ((McOptionsReadReduceFsm(options) == TRUE) &&
+     (dcLevel != McDcLevelNone_c)) {
+      McOptionsSetUseFormulaTree(options, TRUE);
+  }
+
+  /* derive the normalized array of invariant formulas */
+  if (McOptionsReadUseFormulaTree(options) == TRUE) {
+    invarNormalFormulaArray =
+      Ctlp_FormulaArrayConvertToExistentialFormTree(invarArray);
+  } else {
+    array_t *temp = Ctlp_FormulaArrayConvertToDAG( invarArray );
+    array_free( invarArray );
+    invarArray = temp;
+    invarNormalFormulaArray = Ctlp_FormulaDAGConvertToExistentialFormDAG(
+      invarArray );
+  }
+
+  if (array_n(invarNormalFormulaArray) == 0) {
+    array_free(invarNormalFormulaArray);
+    Ctlp_FormulaArrayFree(invarArray);
+    mdd_free(tautology);
+    return 1;
+  }
+  fsmArray = array_alloc(Fsm_Fsm_t *, 0);
+  sortedFormulaArray = SortFormulasByFsm(totalFsm, invarNormalFormulaArray,
+					 fsmArray, options);
+  if (sortedFormulaArray == NIL(array_t)) {
+    array_free(invarNormalFormulaArray);
+    Ctlp_FormulaArrayFree(invarArray);
+    mdd_free(tautology);
+    return 1;
+  }
+  assert(array_n(fsmArray) == array_n(sortedFormulaArray));
+
+  careSetArray = array_alloc(mdd_t *, 0);
+
+  /* main loop for array of array of formulas. Each of the latter
+     arrays corresponds to one reduced fsm. */
+  arrayForEachItem(array_t *, sortedFormulaArray, i, formulas) {
+    int *resultArray;
+    int fail;
+    /* initialize pass, fail array */
+    resultArray = ALLOC(int, array_n(formulas));
+    for (j = 0; j < array_n(formulas); j++) {
+      resultArray[j] = 1;
+    }
+    /* get reduced fsm for this set of formulas */
+    modelFsm = array_fetch(Fsm_Fsm_t *, fsmArray, i);
+
+    /* evaluate hints for this reduced fsm, stop if the hints contain variables
+     * outside this model FSM.
+     */
+    if (hintsArray != NIL(Ctlp_FormulaArray_t)) {
+      int k;
+      hintsStatesArray = Mc_EvaluateHints(modelFsm, hintsArray);
+      if( hintsStatesArray == NIL(array_t)) { /* something wrong, clean up */
+	int l;
+	fprintf(vis_stdout, "Hints dont match the reduced FSM for this set of invariants.\n");
+	fprintf(vis_stdout, "Continuing with the next set of invariants\n");
+	for (k = i; k < array_n(sortedFormulaArray); k++) {
+	  formulas = array_fetch(array_t *, sortedFormulaArray, k);
+	  arrayForEachItem(Ctlp_Formula_t *, formulas, l, invarFormula) {
+	    Ctlp_FormulaFree(invarFormula);
+	  }
+	  array_free(formulas);
+	  /* get reduced fsm for this set of formulas */
+	  modelFsm = array_fetch(Fsm_Fsm_t *, fsmArray, k);
+	  /* free the Fsm if it was reduced here */
+	  if (modelFsm != totalFsm) Fsm_FsmFree(modelFsm);
+	}
+	array_free(careSetArray);
+	array_free(fsmArray);
+	array_free(sortedFormulaArray);
+	array_free(invarNormalFormulaArray);
+	(void) fprintf(vis_stdout, "\n");
+
+	Ctlp_FormulaArrayFree(invarArray);
+	McOptionsFree(options);
+	mdd_free(tautology);
+	return 1;
+      }
+    }/* hints exist */
+
+    if(options->FAFWFlag > 1) {
+      reachableStates = Fsm_FsmComputeReachableStates(
+	  modelFsm, 0, verbosity , 0, 0, 1, 0, 0,
+	  approxFlag, ardc, 0, 0, (verbosity > 1),
+	  hintsStatesArray);
+      mdd_free(reachableStates);
+    }
+
+
+    invarStatesArray = array_alloc(mdd_t *, 0);
+    array_insert(mdd_t *, careSetArray, 0, tautology);
+    arrayForEachItem(Ctlp_Formula_t *, formulas, j, invarFormula) {
+      /* compute the set of states represented by the invariant. */
+      invarFormulaStates =
+	Mc_FsmEvaluateFormula(modelFsm, invarFormula, tautology,
+			      NIL(Fsm_Fairness_t), careSetArray,
+			      MC_NO_EARLY_TERMINATION,
+			      NIL(Fsm_HintsArray_t), Mc_None_c,
+			      verbosity, dcLevel, buildOnionRings,
+			      McGSH_EL_c);
+
+      array_insert_last(mdd_t *, invarStatesArray, invarFormulaStates);
+    }
+
+    printStep = (verbosity == McVerbosityMax_c) && (totalFsm == modelFsm);
+    /* main loop to check a set of invariants. */
+    do {
+      boolean compute = FALSE;
+      /* check if the computed reachable set in the total FSM already violates an invariant. */
+      compute = TestInvariantsInTotalFsm(totalFsm, invarStatesArray, (debugFlag ||
+							 buildOnionRings));
+
+      /* compute reachable set or until early failure */
+      if (compute)
+	reachableStates = Fsm_FsmComputeReachableStates(
+	  modelFsm, 0, verbosity , 0, 0, (debugFlag || buildOnionRings), 0, 0,
+	  approxFlag, ardc, 0, invarStatesArray, (verbosity > 1),
+	  hintsStatesArray);
+      else if (debugFlag || buildOnionRings) {
+	(void)Fsm_FsmReachabilityOnionRingsStates(totalFsm, &reachableStates);
+      } else {
+	reachableStates = mdd_dup(Fsm_FsmReadCurrentReachableStates(totalFsm));
+      }
+
+      ardc = 0; /* once ardc is applied, we don't need it again. */
+      /* updates result array and sets fail if any formula failed.*/
+      fail = UpdateResultArray(reachableStates, invarStatesArray, resultArray);
+      mdd_free(reachableStates);
+      someLeft = 0;
+      if (fail) {
+	/* some invariant failed */
+	if (debugFlag) {
+	  assert (approxFlag != Fsm_Rch_Oa_c);
+	  Fsm_FsmSetFAFWFlag(modelFsm, options->FAFWFlag);
+	  Fsm_FsmSetSystemVariableFAFW(modelFsm, systemVarBddIdTable);
+	  InvarPrintDebugInformation(modelFsm, formulas, invarStatesArray,
+				     resultArray, options, hintsStatesArray);
+	  Fsm_FsmSetFAFWFlag(modelFsm, 0);
+	  Fsm_FsmSetSystemVariableFAFW(modelFsm, 0);
+	} else if (approxFlag == Fsm_Rch_Oa_c) {
+	  assert(!buildOnionRings);
+	  /* May be a false negative */
+	  /* undo failed results in the result array, report passed formulae */
+	  arrayForEachItem(mdd_t *, invarStatesArray, j, invarFormulaStates) {
+	    if (invarFormulaStates == NIL(mdd_t)) continue;
+	    /* print all formulae that are known to have passed */
+	    if (resultArray[j] == 1) {
+	      mdd_free(invarFormulaStates);
+	      array_insert(mdd_t *, invarStatesArray, j, NIL(mdd_t));
+	      (void) fprintf(vis_stdout, "# INV: Early detection - formula passed --- ");
+	      invarFormula = array_fetch(Ctlp_Formula_t *, formulas, j);
+	      Ctlp_FormulaPrint(vis_stdout, Ctlp_FormulaReadOriginalFormula(invarFormula));
+	      fprintf(vis_stdout, "\n");
+	    } else resultArray[j] = 1;
+	  }
+	  fprintf(vis_stdout, "# INV: Invariant violated by over-approximated reachable states\n");
+	  fprintf(vis_stdout, "# INV: Switching to BFS (exact computation) to resolve false negatives\n");
+	  /* compute reachable set or until early failure */
+	  reachableStates = Fsm_FsmComputeReachableStates(
+	    modelFsm, 0, verbosity , 0, 0, 0, 0, 0, Fsm_Rch_Bfs_c, ardc, 0,
+	    invarStatesArray, (verbosity > 1), hintsStatesArray);
+	  /* either invariant has failed or all reachable states are computed */
+	  /* updates result array */
+	  fail = UpdateResultArray(reachableStates, invarStatesArray, resultArray);
+	  mdd_free(reachableStates);
+	}
+	/* remove the failed invariants from the invariant list. */
+	if (fail) {
+	  arrayForEachItem(mdd_t *, invarStatesArray, j, invarFormulaStates) {
+	    if (invarFormulaStates == NIL(mdd_t)) continue;
+	    /* free the failed invariant mdds */
+	    if (resultArray[j] == 0) {
+	      mdd_free(invarFormulaStates);
+	      array_insert(mdd_t *, invarStatesArray, j, NIL(mdd_t));
+	      if (!debugFlag) {
+		(void) fprintf(vis_stdout, "# INV: Early detection - formula failed --- ");
+		invarFormula = array_fetch(Ctlp_Formula_t *, formulas, j);
+		Ctlp_FormulaPrint(vis_stdout, Ctlp_FormulaReadOriginalFormula(invarFormula));
+		fprintf(vis_stdout, "\n");
+	      }
+	    } else {
+	      someLeft = 1;
+	    }
+	  }
+	}
+      } /* end of recomputation dur to over approximate computation */
+    } while (someLeft);
+
+    arrayForEachItem(mdd_t *, invarStatesArray, j, invarFormulaStates) {
+      if (invarFormulaStates == NIL(mdd_t)) continue;
+      /* free the passed invariant mdds */
+      mdd_free(invarFormulaStates);
+    }
+    array_free(invarStatesArray);
+    if (printStep) {
+      finalTime = util_cpu_time();
+      Fsm_FsmReachabilityPrintResults(modelFsm,finalTime-initTime ,approxFlag);
+    }
+    /* free the Fsm if it was reduced here */
+    if (modelFsm != totalFsm) Fsm_FsmFree(modelFsm);
+
+
+    PrintInvPassFail(formulas, resultArray);
+
+
+    arrayForEachItem(Ctlp_Formula_t *, formulas, j, invarFormula) {
+      Ctlp_FormulaFree(invarFormula);
+    }
+    array_free(formulas);
+    FREE(resultArray);
+  } /* end of processing the sorted array of array of invariants */
+
+  if(hintsStatesArray != NIL(array_t))
+    mdd_array_free(hintsStatesArray);
+  if(hintsArray)
+    Ctlp_FormulaArrayFree(hintsArray);
+  array_free(careSetArray);
+  array_free(fsmArray);
+  array_free(sortedFormulaArray);
+  array_free(invarNormalFormulaArray);
+  (void) fprintf(vis_stdout, "\n");
+
+  if (options->FAFWFlag) {
+    st_free_table(systemVarBddIdTable);
+  }
+
+  Ctlp_FormulaArrayFree(invarArray);
+  McOptionsFree(options);
+  mdd_free(tautology);
+
+  alarm(0);
+  return 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Parse command line options for invar.]
+
+  SideEffects []
+
+******************************************************************************/
+static McOptions_t *
+ParseInvarOptions(
+  int argc,
+  char **argv)
+{
+  unsigned int i;
+  int c;
+  boolean useMore = FALSE;
+  boolean reduceFsm = FALSE;
+  boolean printInputs = FALSE;
+  boolean useFormulaTree = FALSE;
+  FILE *inputFp=NIL(FILE);
+  FILE *debugOut=NIL(FILE);
+  char *debugOutName=NIL(char);
+  McDbgLevel dbgLevel = McDbgLevelNone_c;
+  Mc_VerbosityLevel verbosityLevel = McVerbosityNone_c;
+  int timeOutPeriod = 0;
+  McOptions_t *options = McOptionsAlloc();
+  int approxFlag = 0, ardc = 0, shellFlag = 0;
+  Fsm_RchType_t rchType;
+  FILE *guideFile;
+  FILE *systemFile = NIL(FILE);
+  boolean FAFWFlag = FALSE;
+  boolean GFAFWFlag = FALSE;
+  char *guideFileName = NIL(char);
+  char *variablesForSystem = NIL(char);
+  int incre, speed;
+  /* int sss; */
+
+  /*
+   * Parse command line options.
+   */
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "ifcrt:g:hmv:d:A:DO:Ww:I:SPs:")) != EOF) {
+    switch(c) {
+      case 'g':
+	guideFileName = util_strsav(util_optarg);
+	break;
+      case 'h':
+	goto usage;
+      case 't':
+	timeOutPeriod = atoi(util_optarg);
+	break;
+      case 'v':
+	for (i = 0; i < strlen(util_optarg); i++) {
+	  if (!isdigit((int)util_optarg[i])) {
+	    goto usage;
+	  }
+	}
+	verbosityLevel = (Mc_VerbosityLevel) atoi(util_optarg);
+	break;
+      case 'd':
+	for (i = 0; i < strlen(util_optarg); i++) {
+	  if (!isdigit((int)util_optarg[i])) {
+	    goto usage;
+	  }
+	}
+	dbgLevel = (McDbgLevel) atoi(util_optarg);
+	break;
+      case 'f':
+	shellFlag = 1;
+	break;
+      case 'r' :
+	reduceFsm = TRUE;
+	break;
+      case 'm':
+	useMore = TRUE;
+	break;
+      case 'i' :
+	printInputs = TRUE;
+	break;
+      case 'c' :
+	useFormulaTree = TRUE;
+	break;
+      case 'A':
+	approxFlag = atoi(util_optarg);
+	if ((approxFlag > 4) || (approxFlag < 0)) {
+	    goto usage;
+	}
+	break;
+      case 'D':
+	ardc = 1;
+	break;
+      case 'O':
+	debugOutName = util_strsav(util_optarg);
+	break;
+      case 'w':
+	variablesForSystem = util_strsav(util_optarg);
+      case 'W':
+	FAFWFlag = 1;
+	break;
+      case 'G':
+	GFAFWFlag = 1;
+	break;
+      case 'I':
+	incre = atoi(util_optarg);
+	options->incre = (incre==0)? FALSE:TRUE;
+	break;
+      case 'S':
+	/*sss = atoi(util_optarg);*/
+	/*options->sss = (sss==0)? FALSE:TRUE;*/
+	options->sss = TRUE;
+	break;
+      case 'P':
+	options->flatIP = TRUE;
+	break;
+      case 's':
+	speed = atoi(util_optarg);
+	options->IPspeed = speed;
+	break;
+      default:
+	goto usage;
+    }
+  }
+
+  if((FAFWFlag > 0 || GFAFWFlag > 0) &&  dbgLevel == 0) {
+    fprintf(vis_stderr, "** inv warning : -w and -W options are ignored without -d option\n");
+  }
+
+  if((FAFWFlag > 0 || GFAFWFlag > 0) &&  printInputs == 0) {
+    fprintf(vis_stderr, "** inv warning : -i is recommended with -w or -W option\n");
+  }
+
+  if(FAFWFlag) {
+    if (bdd_get_package_name() != CUDD) {
+      fprintf(vis_stderr, "** inv warning : -w and -W option is only available with CUDD\n");
+      FAFWFlag = 0;
+      FREE(variablesForSystem);
+      variablesForSystem = NIL(char);
+    }
+  }
+
+
+  /* translate approx flag */
+  switch(approxFlag) {
+  case 0: rchType = Fsm_Rch_Bfs_c; break;
+  case 1: rchType = Fsm_Rch_Hd_c; break;
+  case 2: rchType = Fsm_Rch_Oa_c; break;
+  case 3: rchType = Fsm_Rch_Grab_c; break;
+  case 4: rchType = Fsm_Rch_PureSat_c; break;
+  default: rchType = Fsm_Rch_Default_c; break;
+  }
+
+  if ((approxFlag == 1) && (bdd_get_package_name() != CUDD)) {
+    fprintf(vis_stderr, "** inv error: check_invariant with -A 1 option is currently supported by only CUDD.\n");
+    return NIL(McOptions_t);
+  }
+
+  if (rchType == Fsm_Rch_Oa_c) {
+    if (dbgLevel > 0) {
+      fprintf(vis_stdout, "Over approximation and debug level 1 are incompatible\n");
+      fprintf(vis_stdout, "Read check_invariant help page\n");
+      goto usage;
+    } else if (shellFlag == 1) {
+      fprintf(vis_stdout, "Over approximation and shell flag are incompatible\n");
+      fprintf(vis_stdout, "Read check_invariant help page\n");
+      goto usage;
+    }
+  }
+
+  if (rchType == Fsm_Rch_Grab_c) {
+    if (guideFileName != NIL(char)) {
+      fprintf(vis_stdout, "Abstraction refinement Grab and guided search are incompatible\n");
+      fprintf(vis_stdout, "Read check_invariant help page\n");
+      goto usage;
+    }
+  }
+
+  if (rchType == Fsm_Rch_PureSat_c) {
+    if (guideFileName != NIL(char)) {
+      fprintf(vis_stdout, "Abstraction refinement PureSat and guided search are incompatible\n");
+      fprintf(vis_stdout, "Read check_invariant help page\n");
+      goto usage;
+    }
+  }
+
+  if (guideFileName != NIL(char)) {
+    guideFile = Cmd_FileOpen(guideFileName, "r", NIL(char *), 0);
+    FREE(guideFileName);
+    if (guideFile == NIL(FILE)) {
+      McOptionsFree(options);
+      return NIL(McOptions_t);
+    }
+    McOptionsSetGuideFile(options, guideFile);
+  }
+
+  /*
+   * Open the ctl file.
+   */
+  if (argc - util_optind == 0) {
+    (void) fprintf(vis_stderr, "** inv error: file containing invariant formulas not provided\n");
+    goto usage;
+  }
+  else if (argc - util_optind > 1) {
+    (void) fprintf(vis_stderr, "** inv error: too many arguments\n");
+    goto usage;
+  }
+
+  McOptionsSetUseMore(options, useMore);
+  McOptionsSetReduceFsm(options, reduceFsm);
+  McOptionsSetPrintInputs(options, printInputs);
+  McOptionsSetUseFormulaTree(options, useFormulaTree);
+  McOptionsSetTimeOutPeriod(options, timeOutPeriod);
+  McOptionsSetInvarApproxFlag(options, rchType);
+  if (ardc)
+    McOptionsSetDcLevel(options, McDcLevelArdc_c);
+  else
+    McOptionsSetDcLevel(options, McDcLevelNone_c);
+  McOptionsSetInvarOnionRingsFlag(options, shellFlag);
+  McOptionsSetFAFWFlag(options, FAFWFlag + GFAFWFlag);
+
+  inputFp = Cmd_FileOpen(argv[util_optind], "r", NIL(char *), 0);
+  if (inputFp == NIL(FILE)) {
+    McOptionsFree(options);
+    return NIL(McOptions_t);
+  }
+  McOptionsSetCtlFile(options, inputFp);
+
+  if (debugOutName != NIL(char)) {
+    debugOut = Cmd_FileOpen(debugOutName, "w", NIL(char *), 0);
+    if (debugOut == NIL(FILE)) {
+      McOptionsFree(options);
+      return NIL(McOptions_t);
+    }
+  }
+  McOptionsSetDebugFile(options, debugOut);
+
+  if ((verbosityLevel != McVerbosityNone_c) &&
+       (verbosityLevel != McVerbosityLittle_c) &&
+       (verbosityLevel != McVerbositySome_c) &&
+       (verbosityLevel != McVerbosityMax_c)) {
+    goto usage;
+  }
+  else {
+    McOptionsSetVerbosityLevel(options, verbosityLevel);
+  }
+
+  if ((dbgLevel != McDbgLevelNone_c) &&
+       (dbgLevel != McDbgLevelMin_c)) {
+    if(((rchType == Fsm_Rch_Grab_c) && (dbgLevel == McDbgLevelMinVerbose_c)))
+    {
+      McOptionsSetDbgLevel(options, dbgLevel);
+    }
+    else
+    {
+      if((rchType == Fsm_Rch_PureSat_c) && (options->flatIP == TRUE) && (dbgLevel == McDbgLevelMinVerbose_c))
+      {
+	McOptionsSetDbgLevel(options, dbgLevel);
+      }
+      else
+      {
+	if((rchType == Fsm_Rch_Bfs_c) && (dbgLevel == McDbgLevelMinVerbose_c))
+	{
+	  McOptionsSetDbgLevel(options, dbgLevel);
+	}
+	else
+	{
+	  goto usage;
+	}
+      }
+    }
+  }
+  else {
+    McOptionsSetDbgLevel(options, dbgLevel);
+  }
+
+  if (variablesForSystem != NIL(char)) {
+    systemFile = Cmd_FileOpen(variablesForSystem, "r", NIL(char *), 0);
+    if (systemFile == NIL(FILE)) {
+      fprintf(vis_stderr, "** inv error: cannot open system variables file for FAFW %s.\n",
+	      variablesForSystem);
+      FREE(variablesForSystem);
+      variablesForSystem = NIL(char);
+      McOptionsFree(options);
+      return NIL(McOptions_t);
+    }
+    FREE(variablesForSystem);
+    variablesForSystem = NIL(char);
+  }
+  McOptionsSetVariablesForSystem(options, systemFile);
+
+
+  return options;
+
+  usage:
+  (void) fprintf(vis_stderr, "usage: check_invariant [-c][-d dbg_level][-f][-g <hintfile>][-h][-i][-m][-r][-v verbosity_level][-t time_out][-A <number>][-D dc_level] [-O <dbg_out>] <invar_file>\n");
+  (void) fprintf(vis_stderr, "    -c  avoid sub-formula sharing between formulae\n");
+  (void) fprintf(vis_stderr, "    -d  <dbg_level>");
+  (void) fprintf(vis_stderr, "        dbg_level = 0 => no debug output (Default)\n");
+  (void) fprintf(vis_stderr, "	      dbg_level = 1 => print debug trace. (available for all options)\n ");
+  (void) fprintf(vis_stderr, "	      dbg_level = 2 => print debug trace in Aiger format. (available for -A0, -A3, -A4 and -A4 -P)\n");
+  (void) fprintf(vis_stderr, "    -f \tStore the onion rings at each step.\n");
+  (void) fprintf(vis_stderr, "    -g <hint_file> \tSpecify file for guided search.\n");
+  (void) fprintf(vis_stderr, "    -i \tPrint input values in debug traces.\n");
+  (void) fprintf(vis_stderr, "    -m  pipe debugger output through UNIX utility more\n");
+  (void) fprintf(vis_stderr, "    -r  reduce FSM with respect to invariant being checked\n");
+  (void) fprintf(vis_stderr, "    -t <period> Time out period.\n");
+  (void) fprintf(vis_stderr, "    -v <verbosity_level>\n");
+  (void) fprintf(vis_stderr, "        verbosity_level = 0 => no feedback (Default)\n");
+  (void) fprintf(vis_stderr, "        verbosity_level = 1 => code status\n");
+  (void) fprintf(vis_stderr, "        verbosity_level = 2 => code status and CPU usage profile\n");
+  (void) fprintf(vis_stderr, "    -A  <number> Use Different types of reachability analysis\n");
+  (void) fprintf(vis_stderr, "            0 (default) - BFS method.\n");
+  (void) fprintf(vis_stderr, "            1 - HD method.\n");
+  (void) fprintf(vis_stderr, "            2 - Over-approximation.\n");
+  (void) fprintf(vis_stderr, "            3 - Abstraction refinement GRAB.\n");
+  (void) fprintf(vis_stderr, "    -D  minimize transition relation with ARDCs\n");
+  (void) fprintf(vis_stderr, "    -O <dbg_out>\n");
+  (void) fprintf(vis_stderr, "        write error trace to dbg_out\n");
+  (void) fprintf(vis_stderr, "    -W \tUse fate and free will algorithm when all the variables are controlled by system.\n");
+  (void) fprintf(vis_stderr, "    -G \tUse general fate and free will algorithm.\n");
+  (void) fprintf(vis_stderr, "    -w <node file> \tSpecify variables controlled by system.\n");
+  (void) fprintf(vis_stderr, "    <invar_file> The input file containing invariants to be checked.\n");
+  (void) fprintf(vis_stderr, "    -h \tPrints this usage message.\n");
+  (void) fprintf(vis_stderr, "    -I \tSwitch for Incremental SAT solver in PureSAT method abstraction refinement\n");
+  McOptionsFree(options);
+
+  return NIL(McOptions_t);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Handle function for timeout.]
+
+  Description [This function is called when the time out occurs.
+  Since alarm is set with an elapsed time, this function checks if the
+  CPU time corresponds to the timeout of the command.  If not, it
+  reprograms the alarm to fire again later.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+TimeOutHandle(void)
+{
+  int seconds = (int) ((util_cpu_ctime() - alarmLapTime) / 1000);
+
+  if (seconds < mcTimeOut) {
+    unsigned slack = (unsigned) (mcTimeOut - seconds);
+    (void) signal(SIGALRM, (void(*)(int)) TimeOutHandle);
+    (void) alarm(slack);
+  } else {
+    longjmp(timeOutEnv, 1);
+  }
+} /* TimeOutHandle */
+
+
+/**Function********************************************************************
+
+  Synopsis [Check whether the reachable states violate the array of
+  invariants.]
+
+  Description [Check whether the reachable states violate the array of
+  invariants. Return 1 if any formula failed. Update the result
+  array. Entry 0 implies fail, 1 implies pass.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+UpdateResultArray(mdd_t *reachableStates,
+		  array_t *invarStatesArray,
+		  int *resultArray)
+{
+  int i;
+  mdd_t *invariant;
+  int fail = 0;
+  arrayForEachItem(mdd_t *, invarStatesArray, i, invariant) {
+    if (invariant == NIL(mdd_t)) continue;
+    if (!mdd_lequal(reachableStates, invariant, 1, 1)) {
+      fail = 1;
+      resultArray[i] = 0;
+    }
+  }
+  return fail;
+} /* end of UpdateResultArray */
+
+
+/**Function********************************************************************
+
+  Synopsis [Prints whether the set of invariants passed or failed]
+
+  Description [Prints whether the set of invariants passed or failed.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+PrintInvPassFail(array_t *invarFormulaArray,
+		 int *resultArray)
+{
+  int i;
+  Ctlp_Formula_t *formula;
+  fprintf(vis_stdout, "\n# INV: Summary of invariant pass/fail\n");
+  arrayForEachItem(Ctlp_Formula_t *, invarFormulaArray, i, formula) {
+    if (resultArray[i]) {
+      (void) fprintf(vis_stdout, "# INV: formula passed --- ");
+      Ctlp_FormulaPrint(vis_stdout, Ctlp_FormulaReadOriginalFormula(formula));
+      fprintf(vis_stdout, "\n");
+    } else {
+      (void) fprintf(vis_stdout, "# INV: formula failed --- ");
+      Ctlp_FormulaPrint(vis_stdout, Ctlp_FormulaReadOriginalFormula(formula));
+      fprintf(vis_stdout, "\n");
+    }
+  }
+  return;
+} /* end of PrintInvPassFail */
Index: vis_dev/vis-2.3/src/mc/mcCover.c
===================================================================
--- vis_dev/vis-2.3/src/mc/mcCover.c	(revision 14)
+++ vis_dev/vis-2.3/src/mc/mcCover.c	(revision 14)
@@ -0,0 +1,2504 @@
+/**CFile***********************************************************************
+
+  FileName    [mcCover.c]
+
+  PackageName [mc]
+
+  Synopsis    [Functions for coverage estimation.]
+
+  Description [This file contains the functions implementing coverage
+  estimation for CTL.  According to the proposal of Hoskote et al. (DAC99)
+  a state is covered by a passing property with respect to an observable
+  binary signal if flipping the value of the signal at that state causes
+  the property to fail.  Hoskote et al. proposed an algorithm for the
+  estimation of coverage for a subset of ACTL loosely based on this
+  definition of coverage.<p>
+  This file contains an implementation of Hoskote's algorithm as well as an
+  implementation of the improved algorithm by Jayakumar et al. presented
+  at DAC2003.  The improved algorithm deals with a larger subset of CTL and
+  provides more accurate estimates.]
+
+  SeeAlso     [mcMc.c]
+
+  Author      [Nikhil Jayakumar]
+
+  Copyright   [Copyright (c) 2002-2005, 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 "ctlpInt.h"
+#include "mcInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] UNUSED = "$Id: mcCover.c,v 1.4 2005/05/15 07:32:10 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static mdd_t * CoveredStatesHoskote(mdd_t *startstates_old, Fsm_Fsm_t *fsm, Ctlp_Formula_t *OrigFormula, mdd_t *fairStates, Fsm_Fairness_t *fairCondition, array_t *careStatesArray, Mc_EarlyTermination_t *earlyTermination, Fsm_HintsArray_t *hintsArray, Mc_GuidedSearch_t hintType, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, int buildOnionRing, Mc_GSHScheduleType GSHschedule, array_t *signalList, array_t *statesCoveredList, array_t *newCoveredStatesList, array_t *statesToRemoveList);
+static mdd_t * CoveredStatesImproved(mdd_t *startstates_old, Fsm_Fsm_t *fsm, Ctlp_Formula_t *OrigFormula, mdd_t *fairStates, Fsm_Fairness_t *fairCondition, array_t *careStatesArray, Mc_EarlyTermination_t *earlyTermination, Fsm_HintsArray_t *hintsArray, Mc_GuidedSearch_t hintType, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, int buildOnionRing, Mc_GSHScheduleType GSHschedule, array_t *signalList, array_t *statesCoveredList, array_t *newCoveredStatesList, array_t *statesToRemoveList);
+static mdd_t * CoveragePropositional(mdd_t *startstates_old, Fsm_Fsm_t *fsm, Ctlp_Formula_t *OrigFormula, mdd_t *fairStates, Fsm_Fairness_t *fairCondition, array_t *careStatesArray, Mc_EarlyTermination_t *earlyTermination, Fsm_HintsArray_t *hintsArray, Mc_GuidedSearch_t hintType, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, int buildOnionRing, Mc_GSHScheduleType GSHschedule, array_t *signalList, array_t *statesCoveredList, array_t *newCoveredStatesList, array_t *statesToRemoveList);
+static mdd_t * computedepend(Fsm_Fsm_t *fsm, Ctlp_Formula_t *formula, mdd_t *fairStates, Fsm_Fairness_t *fairCondition, array_t *careStatesArray, Mc_EarlyTermination_t *earlyTermination, Fsm_HintsArray_t *hintsArray, Mc_GuidedSearch_t hintType, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, int buildOnionRing, Mc_GSHScheduleType GSHschedule, char *signal, mdd_t *SoAndTb_old);
+static mdd_t * computedependHoskote(Fsm_Fsm_t *fsm, Ctlp_Formula_t *formula, mdd_t *fairStates, Fsm_Fairness_t *fairCondition, array_t *careStatesArray, Mc_EarlyTermination_t *earlyTermination, Fsm_HintsArray_t *hintsArray, Mc_GuidedSearch_t hintType, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, int buildOnionRing, Mc_GSHScheduleType GSHschedule, mdd_t *startstates_old, char *signal, mdd_t *Tb, mdd_t *statesCovered, mdd_t *newCoveredStates, mdd_t *statesToRemove);
+static mdd_t * traverse(Fsm_Fsm_t *fsm, mdd_t *fairStates, Fsm_Fairness_t *fairCondition, array_t *careStatesArray, Mc_EarlyTermination_t *earlyTermination, Fsm_HintsArray_t *hintsArray, Mc_GuidedSearch_t hintType, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, int buildOnionRing, Mc_GSHScheduleType GSHschedule, mdd_t *startstates, Ctlp_Formula_t *formula1, Ctlp_Formula_t *formula2);
+static mdd_t * firstReached(Fsm_Fsm_t *fsm, mdd_t *fairStates, Fsm_Fairness_t *fairCondition, array_t *careStatesArray, Mc_EarlyTermination_t *earlyTermination, Fsm_HintsArray_t *hintsArray, Mc_GuidedSearch_t hintType, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, int buildOnionRing, Mc_GSHScheduleType GSHschedule, mdd_t *startstates, Ctlp_Formula_t *formula);
+static Ctlp_Formula_t * FormulaConvertSignalComplement(Fsm_Fsm_t *fsm, char *signal, Ctlp_Formula_t *formula);
+static void findallsignals(Fsm_Fsm_t *fsm, array_t *signalTypeList, array_t *signalList, array_t *statesCoveredList, array_t *newCoveredStatesList, array_t *statesToRemoveList, Ctlp_Formula_t *formula, mdd_t *zeroMdd);
+static void findallsignalsInFormula(array_t *signalList, Ctlp_Formula_t *formula);
+static int positionOfSignalinList(char *signal, array_t *signalList);
+static int RangeofSignalinFormula(Fsm_Fsm_t *fsm, char *signal, Ctlp_Formula_t *formula);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Estimate coverage of one CTL formula.]
+
+  Description [Depending on the options, this function applies either
+  the original algorithm of Hoskote et al. or the improved algorithm of
+  Jayakumar et al..  It then prints statistics on coverage (if the formula
+  passes).]
+
+  SideEffects [Updates running totals]
+
+  SeeAlso     [CommandMc CoveredStatesHoskote CoveredStatesImproved
+  McPrintCoverageSummary]
+
+******************************************************************************/
+void
+McEstimateCoverage(
+  Fsm_Fsm_t *modelFsm,
+  Ctlp_Formula_t *ctlFormula,
+  int i,
+  mdd_t *fairStates,
+  Fsm_Fairness_t *fairCond,
+  array_t *modelCareStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  array_t *hintsStatesArray,
+  Mc_GuidedSearch_t guidedSearchType,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  int buildOnionRings,
+  Mc_GSHScheduleType GSHschedule,
+  Mc_FwdBwdAnalysis traversalDirection,
+  mdd_t *modelInitialStates,
+  mdd_t *ctlFormulaStates,
+  mdd_t **totalcoveredstates,
+  array_t *signalTypeList,
+  array_t *signalList,
+  array_t *statesCoveredList,
+  array_t *newCoveredStatesList,
+  array_t *statesToRemoveList,
+  boolean performCoverageHoskote,
+  boolean performCoverageImproved)
+{
+  double numtotcoveredstates;
+  double numnewcoveredstates;
+  mdd_t *CovstatesHoskote;
+  mdd_t *CovstatesImproved;
+  Ctlp_Formula_t *origFormula;
+
+  if (performCoverageHoskote &&
+      (modelCareStatesArray != NIL(array_t))) { /* and no errors till now? */
+    mdd_t *tmp_mdd, *zero_mdd;
+    int sigarr;
+    array_t *listOfSignals = array_alloc(char *,0);
+    origFormula = Ctlp_FormulaReadOriginalFormula(ctlFormula);
+    if ( ( (traversalDirection == McFwd_c) && bdd_is_tautology(ctlFormulaStates, 1) ) ||
+	 mdd_lequal(modelInitialStates, ctlFormulaStates, 1, 1) ) { /* formula passes */
+
+      if (*totalcoveredstates == NIL(mdd_t))
+	*totalcoveredstates = mdd_zero(Fsm_FsmReadMddManager(modelFsm));
+
+      /* add new signals if any found */
+      zero_mdd = mdd_zero(Fsm_FsmReadMddManager(modelFsm));
+      findallsignals(modelFsm, signalTypeList, signalList,
+		     statesCoveredList, newCoveredStatesList,
+		     statesToRemoveList, origFormula,
+		     zero_mdd);
+      mdd_free(zero_mdd);
+      fprintf(vis_stdout,"\n--Checking coverage for formula<%d>\n",i+1);
+      fprintf(vis_stdout,"===================================\n");
+
+      CovstatesHoskote = CoveredStatesHoskote(modelInitialStates,
+					      modelFsm, origFormula,
+					      fairStates, fairCond,
+					      modelCareStatesArray,
+					      earlyTermination,
+					      hintsStatesArray,
+					      guidedSearchType, verbosity,
+					      dcLevel, buildOnionRings,
+					      GSHschedule, signalList,
+					      statesCoveredList,
+					      newCoveredStatesList,
+					      statesToRemoveList);
+      numtotcoveredstates = mdd_count_onset(Fsm_FsmReadMddManager(modelFsm),
+					    CovstatesHoskote,
+					    Fsm_FsmReadPresentStateVars(modelFsm));
+      tmp_mdd = mdd_and(CovstatesHoskote,*totalcoveredstates,1,0);
+
+      numnewcoveredstates = mdd_count_onset(Fsm_FsmReadMddManager(modelFsm),
+					    tmp_mdd,
+					    Fsm_FsmReadPresentStateVars(modelFsm));
+      mdd_free(tmp_mdd);
+      fprintf(vis_stdout,"\n--Total states covered by formula<%d> = %.0f , new = %.0f\n",i+1,
+	      numtotcoveredstates,numnewcoveredstates);
+      findallsignalsInFormula(listOfSignals,origFormula);
+      for (sigarr=0;sigarr<array_n(listOfSignals);sigarr++) {
+	mdd_t *newCoveredStates,*statesCovered,*tmp_mdd;
+	char *signalInFormula;
+	int positionInList;
+	signalInFormula = array_fetch(char *,listOfSignals,sigarr);
+	positionInList = positionOfSignalinList(signalInFormula,signalList);
+    
+	newCoveredStates = array_fetch(mdd_t *,newCoveredStatesList,positionInList);
+	statesCovered = array_fetch(mdd_t *,statesCoveredList,positionInList);
+	tmp_mdd = mdd_and(newCoveredStates,statesCovered,1,0);	/*newly covered States*/	
+	fprintf(vis_stdout,"---States covered w.r.t. %s = %.0f, new = %.0f\n",
+		signalInFormula,
+		mdd_count_onset(Fsm_FsmReadMddManager(modelFsm),
+				newCoveredStates,
+				Fsm_FsmReadPresentStateVars(modelFsm)),
+		mdd_count_onset(Fsm_FsmReadMddManager(modelFsm),
+				tmp_mdd,
+				Fsm_FsmReadPresentStateVars(modelFsm)));
+	mdd_free(tmp_mdd);
+
+	/* add on the newcoveredstates*/
+	tmp_mdd = mdd_or(statesCovered,newCoveredStates,1,1);
+	mdd_free(statesCovered);
+	/*update statesCoveredList*/
+	array_insert(mdd_t *,statesCoveredList,positionInList,tmp_mdd);
+	mdd_free(newCoveredStates);
+
+	/* reset newCoveredStatesList to zeroMdds for the next formula */
+	tmp_mdd = mdd_zero(Fsm_FsmReadMddManager(modelFsm));
+	array_insert(mdd_t *,newCoveredStatesList,positionInList,tmp_mdd);
+      }
+  
+    } else { /* formula fails */
+      CovstatesHoskote = mdd_zero(Fsm_FsmReadMddManager(modelFsm));
+      fprintf(vis_stdout,"\n--Checking coverage for formula<%d>\n",i+1);
+      fprintf(vis_stdout,"===================================\n");
+      fprintf(vis_stdout,"Coverage for failing formulae = 0\n");
+    }
+    if (*totalcoveredstates == NIL(mdd_t))
+      *totalcoveredstates = mdd_zero(Fsm_FsmReadMddManager(modelFsm));
+	
+    if (CovstatesHoskote != NIL(mdd_t)){
+      mdd_t *tmp_mdd = mdd_or(*totalcoveredstates,CovstatesHoskote,1,1);
+      mdd_free(*totalcoveredstates);
+      *totalcoveredstates = tmp_mdd;
+    }
+	
+    numtotcoveredstates = mdd_count_onset(Fsm_FsmReadMddManager(modelFsm),
+					  *totalcoveredstates,
+					  Fsm_FsmReadPresentStateVars(modelFsm));
+    mdd_free(CovstatesHoskote);
+    array_free(listOfSignals);
+  }
+
+  if (performCoverageImproved && (modelCareStatesArray != NIL(array_t))) { /* and no errors till now ??*/
+    mdd_t *tmp_mdd, *zero_mdd;
+    int sigarr;
+    array_t *listOfSignals = array_alloc(char *,0);
+    origFormula = Ctlp_FormulaReadOriginalFormula(ctlFormula);
+    if ( ( (traversalDirection == McFwd_c) &&
+	   bdd_is_tautology(ctlFormulaStates, 1) ) ||
+	 (mdd_lequal(modelInitialStates, ctlFormulaStates, 1, 1)) ) {
+      /* formula passes */
+
+      if (*totalcoveredstates == NIL(mdd_t))
+	*totalcoveredstates = mdd_zero(Fsm_FsmReadMddManager(modelFsm));  
+
+      /*add new signals if any found*/
+      zero_mdd = mdd_zero(Fsm_FsmReadMddManager(modelFsm));
+      findallsignals(modelFsm, signalTypeList, signalList,
+		     statesCoveredList, newCoveredStatesList,
+		     statesToRemoveList, origFormula, zero_mdd);
+      mdd_free(zero_mdd);
+      fprintf(vis_stdout,"\n--Checking coverage for formula<%d>\n",i+1);
+      fprintf(vis_stdout,"===================================\n");
+
+      CovstatesImproved = CoveredStatesImproved(modelInitialStates,
+						modelFsm, origFormula,
+						fairStates, fairCond,
+						modelCareStatesArray,
+						earlyTermination,
+						hintsStatesArray,
+						guidedSearchType,
+						verbosity,
+						dcLevel, buildOnionRings,
+						GSHschedule, signalList,
+						statesCoveredList,
+						newCoveredStatesList,
+						statesToRemoveList);
+      numtotcoveredstates = mdd_count_onset(Fsm_FsmReadMddManager(modelFsm),
+					    CovstatesImproved,
+					    Fsm_FsmReadPresentStateVars(modelFsm));
+      tmp_mdd = mdd_and(CovstatesImproved,*totalcoveredstates,1,0);
+
+      numnewcoveredstates = mdd_count_onset(Fsm_FsmReadMddManager(modelFsm),
+					    tmp_mdd,
+					    Fsm_FsmReadPresentStateVars(modelFsm));
+      mdd_free(tmp_mdd);
+      fprintf(vis_stdout,"\n--Total states covered by formula<%d> = %.0f , new = %.0f\n",i+1,
+	      numtotcoveredstates,numnewcoveredstates);
+      findallsignalsInFormula(listOfSignals,origFormula);
+      for (sigarr=0;sigarr<array_n(listOfSignals);sigarr++) {
+	mdd_t *newCoveredStates,*statesCovered,*tmp_mdd;
+	char *signalInFormula;
+	int positionInList;
+	signalInFormula = array_fetch(char *,listOfSignals,sigarr);
+	positionInList = positionOfSignalinList(signalInFormula,signalList);
+    
+	newCoveredStates = array_fetch(mdd_t *,newCoveredStatesList,positionInList);
+	statesCovered = array_fetch(mdd_t *,statesCoveredList,positionInList);
+	tmp_mdd = mdd_and(newCoveredStates,statesCovered,1,0);	/*newly covered States*/	
+	fprintf(vis_stdout,"---States covered w.r.t. %s = %.0f, new = %.0f\n",
+		signalInFormula,
+		mdd_count_onset(Fsm_FsmReadMddManager(modelFsm),
+				newCoveredStates,
+				Fsm_FsmReadPresentStateVars(modelFsm)),
+		mdd_count_onset(Fsm_FsmReadMddManager(modelFsm),
+				tmp_mdd,
+				Fsm_FsmReadPresentStateVars(modelFsm)));
+	mdd_free(tmp_mdd);
+
+	/* add on the newcoveredstates*/
+	tmp_mdd = mdd_or(statesCovered,newCoveredStates,1,1);
+	mdd_free(statesCovered);
+	/*update statesCoveredList*/
+	array_insert(mdd_t *,statesCoveredList,positionInList,tmp_mdd);
+	mdd_free(newCoveredStates);
+
+	/* reset newCoveredStatesList to zeroMdds for the next formula */
+	tmp_mdd = mdd_zero(Fsm_FsmReadMddManager(modelFsm));
+	array_insert(mdd_t *,newCoveredStatesList,positionInList,tmp_mdd);
+      }
+
+    } else { /* formula fails */
+      CovstatesImproved = mdd_zero(Fsm_FsmReadMddManager(modelFsm));
+      fprintf(vis_stdout,"\n--Checking coverage for formula<%d>\n",i+1);
+      fprintf(vis_stdout,"===================================\n");
+      fprintf(vis_stdout,"Coverage for failing formulae = 0\n");
+    }
+    if (*totalcoveredstates == NIL(mdd_t))
+      *totalcoveredstates = mdd_zero(Fsm_FsmReadMddManager(modelFsm));
+	
+    if (CovstatesImproved != NIL(mdd_t)){
+      mdd_t *tmp_mdd = mdd_or(*totalcoveredstates,CovstatesImproved,1,1);
+      mdd_free(*totalcoveredstates);
+      *totalcoveredstates = tmp_mdd;
+    }
+	
+    numtotcoveredstates = mdd_count_onset(Fsm_FsmReadMddManager(modelFsm),
+					  *totalcoveredstates,
+					  Fsm_FsmReadPresentStateVars(modelFsm));
+    mdd_free(CovstatesImproved);
+    array_free(listOfSignals);
+  }
+
+} /* McEstimateCoverage */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Print summary for the coverage of a property file.]
+
+  SideEffects [none]
+
+  SeeAlso     [CommandMc McEstimateCoverage]
+
+******************************************************************************/
+void
+McPrintCoverageSummary(
+  Fsm_Fsm_t *modelFsm,
+  Mc_DcLevel dcLevel,
+  McOptions_t *options,
+  array_t *modelCareStatesArray,
+  mdd_t *modelCareStates,
+  mdd_t *totalcoveredstates,
+  array_t *signalTypeList,
+  array_t *signalList,
+  array_t *statesCoveredList,
+  boolean performCoverageHoskote,
+  boolean performCoverageImproved
+  )
+{
+  float coverage;
+  float coveragePI;
+  float coveragePO;
+  float coverageOther;
+  float numPI;
+  float numPO;
+  float numOther;
+  float avgCoverage;
+  float avgPICoverage;
+  float avgPOCoverage;
+  float avgOtherCoverage;
+  double numrchstates;
+  double numtotcoveredstates;
+
+  if (performCoverageHoskote &&
+      (modelCareStatesArray != NIL(array_t))) { /* and no errors till now */
+    int sigarr;
+    if (totalcoveredstates != NIL(mdd_t) && (modelCareStates != NIL(mdd_t))) {
+      numtotcoveredstates = mdd_count_onset(
+	Fsm_FsmReadMddManager(modelFsm),
+	totalcoveredstates,
+	Fsm_FsmReadPresentStateVars(modelFsm));
+    }
+    else {
+      numtotcoveredstates = 0;
+    }
+    
+    if ((dcLevel == McDcLevelRch_c)||(dcLevel == McDcLevelRchFrontier_c)) {
+      if (!mdd_lequal(totalcoveredstates, modelCareStates, 1, 1)) {
+	(void)fprintf(vis_stdout,
+		    "** mc warning: Some of the covered states are not reachable\n");
+      }
+      if (modelCareStates !=NIL(mdd_t)){
+	int sigType;
+	coveragePI = 0;
+	coveragePO = 0;
+	coverageOther = 0;
+	numPI = 0;
+	numPO = 0;
+	numOther = 0;
+	avgCoverage = 0;
+	avgPICoverage = 0;
+	avgPOCoverage = 0;
+	avgOtherCoverage = 0;
+	numrchstates = mdd_count_onset(Fsm_FsmReadMddManager(modelFsm),
+				       modelCareStates,
+				       Fsm_FsmReadPresentStateVars(modelFsm));
+	if (McOptionsReadDbgLevel(options) != McDbgLevelNone_c) { /*print debug info*/
+	  fprintf(vis_stdout,"\nCoverage for all the Formulae w.r.t. all observable signals\n");
+	  fprintf(vis_stdout,"=============================================================\n");
+	}
+	for (sigarr=0;sigarr<array_n(signalList);sigarr++) {
+	  mdd_t *statesCovered, *uncoveredStateCube, *uncoveredStates;
+	  double numStatesCovered;
+	  char *nrOfUncoveredStatesString;
+	  int nrOfUncoveredStates, prntStates;   /* nr of uncovered states that we output */
+
+	  Ntk_Network_t *modelNetworkC = Fsm_FsmReadNetwork(modelFsm);
+	  array_t *PSVarsC = Fsm_FsmReadPresentStateVars(modelFsm);
+	  mdd_manager *mddMgrC = Ntk_NetworkReadMddManager(Fsm_FsmReadNetwork(modelFsm));
+
+	  statesCovered = array_fetch(mdd_t *,statesCoveredList,sigarr);
+	  numStatesCovered = mdd_count_onset(Fsm_FsmReadMddManager(modelFsm),
+					     statesCovered,Fsm_FsmReadPresentStateVars(modelFsm));
+	  coverage = (numStatesCovered / numrchstates) * 100;
+	  avgCoverage = avgCoverage + coverage;
+	  sigType = array_fetch(int, signalTypeList,sigarr);
+	  if (sigType == 1) {
+	    coveragePI = coveragePI + numStatesCovered;
+	    avgPICoverage = avgPICoverage + coverage;
+	    numPI = numPI + 1;
+	  }
+	  else if (sigType == 0) {
+	    coveragePO = coveragePO + numStatesCovered;
+	    avgPOCoverage = avgPOCoverage + coverage;
+	    numPO = numPO + 1;
+	  }
+	  else {
+	    coverageOther = coverageOther + numStatesCovered;
+	    avgOtherCoverage = avgOtherCoverage + coverage;
+	    numOther = numOther + 1;
+	  }
+	  if (McOptionsReadDbgLevel(options) != McDbgLevelNone_c) { /*print debug info*/
+	    fprintf(vis_stdout,"\n# States covered w.r.t. %s = %.0f, Percentage of Coverage = %f\n",
+		    array_fetch(char *,signalList,sigarr), numStatesCovered, coverage);
+	    nrOfUncoveredStatesString = Cmd_FlagReadByName("nr_uncoveredstates");
+	    if(nrOfUncoveredStatesString == NIL(char))
+	      nrOfUncoveredStates = 1;
+	    else
+	      nrOfUncoveredStates = atoi(nrOfUncoveredStatesString);
+	    if (numStatesCovered < numrchstates) {
+	      if ((numrchstates-numStatesCovered) < nrOfUncoveredStates)
+		nrOfUncoveredStates = (int)(numrchstates-numStatesCovered);
+	      fprintf(vis_stdout,"#Printing reachable states NOT covered w.r.t. %s :\n",array_fetch(char *,signalList,sigarr));
+	      for (prntStates = 0;prntStates<nrOfUncoveredStates;prntStates++){  
+		fprintf(vis_stdout,"\n#State %d :\n",prntStates+1);
+		uncoveredStates = mdd_and(modelCareStates,statesCovered,1,0);
+		uncoveredStateCube = Mc_ComputeAMinterm(uncoveredStates, PSVarsC, mddMgrC);
+		mdd_free(uncoveredStates);
+		Mc_MintermPrint(uncoveredStateCube, PSVarsC, modelNetworkC);
+		mdd_free(uncoveredStateCube);
+	      }
+	    }
+	  }
+	}
+	fprintf(vis_stdout,"\nTotal Coverage for all the Formulae\n");
+	fprintf(vis_stdout,"=====================================\n");
+	for (sigarr=0;sigarr<array_n(signalList);sigarr++) {
+	  mdd_t *statesCovered;
+	  double numStatesCovered;
+	  char *type;
+	  int sigType;
+
+	  sigType = array_fetch(int, signalTypeList,sigarr);
+	  if (sigType == 1)
+	    type = "Primary Input";
+	  else if (sigType == 0)
+	    type = "Primary Output";
+	  else
+	    type = "Neither Primary output nor input";
+
+	  statesCovered = array_fetch(mdd_t *,statesCoveredList,sigarr);
+
+	  numStatesCovered = mdd_count_onset(Fsm_FsmReadMddManager(modelFsm),
+					     statesCovered,Fsm_FsmReadPresentStateVars(modelFsm));
+	  coverage = (numStatesCovered / numrchstates) * 100;
+	  fprintf(vis_stdout,"# States covered w.r.t. %s(%s) = %.0f, Percentage of Coverage = %f\n",type,
+		  array_fetch(char *,signalList,sigarr), numStatesCovered, coverage);
+	}
+	fprintf(vis_stdout,"--There are %.0f covered states (using Hoskote et.al's implementation)\n",numtotcoveredstates);
+	fprintf(vis_stdout,"--%.0f states covered by Primary Input Signals\n",coveragePI);
+	fprintf(vis_stdout,"--%.0f states covered by Primary Ouput Signals\n",coveragePO);
+	fprintf(vis_stdout,"--%.0f states covered by signals which are neither Primary input nor output Signals\n",coverageOther);
+	fprintf(vis_stdout,"--There are %.0f reachable states\n",numrchstates);
+
+	coverage = (numtotcoveredstates / numrchstates) * 100;
+	fprintf(vis_stdout,"Percentage of coverage (using Hoskote et.al's implementation)= %f\n ",coverage);
+	avgCoverage = avgCoverage / array_n(signalList);
+	fprintf(vis_stdout,"Average Percentage of coverage = %f\n",avgCoverage);
+	if (numPI < 1)
+	  fprintf(vis_stdout,"No Primary Input signals\n");
+	else {
+	  avgPICoverage = avgPICoverage / numPI;
+	  fprintf(vis_stdout,"Average Percentage of coverage for Primary inputs = %f\n",avgPICoverage);
+	}
+	if (numPO < 1)
+	  fprintf(vis_stdout,"No Primary Output signals\n");
+	else {
+	  avgPOCoverage = avgPOCoverage / numPO;
+	  fprintf(vis_stdout,"Average Percentage of coverage for Primary outputs = %f\n",avgPOCoverage);
+	}
+	if (numOther < 1)
+	  fprintf(vis_stdout,"No signals which are neither primary inputs nor outputs\n");
+	else {
+	  avgOtherCoverage = avgOtherCoverage / numOther;
+	  fprintf(vis_stdout,"Average Percentage of coverage for Primary inputs = %f\n",avgOtherCoverage);
+	}
+      }
+      else {
+	fprintf(vis_stdout,"Reachable states = NIL !\n");
+      }
+    }
+  }
+
+  if (performCoverageImproved && (modelCareStatesArray != NIL(array_t))) { /* and no errors till now */
+    int sigarr;
+    if (totalcoveredstates != NIL(mdd_t) && (modelCareStates != NIL(mdd_t))) {
+      numtotcoveredstates = mdd_count_onset(Fsm_FsmReadMddManager(modelFsm),totalcoveredstates,Fsm_FsmReadPresentStateVars(modelFsm));
+    }
+    else {
+      numtotcoveredstates = 0;
+    }
+   
+    if ((dcLevel == McDcLevelRch_c)||(dcLevel == McDcLevelRchFrontier_c)) {
+      if (!mdd_lequal(totalcoveredstates, modelCareStates, 1, 1)) {
+	(void)fprintf(vis_stdout,
+		      "** mc warning: Some of the covered states are not reachable\n");
+      }
+      if (modelCareStates !=NIL(mdd_t)){
+	int sigType;
+
+	coveragePI = 0;
+	coveragePO = 0;
+	coverageOther = 0;
+	numPI = 0;
+	numPO = 0;
+	numOther = 0;
+	avgCoverage = 0;
+	avgPICoverage = 0;
+	avgPOCoverage = 0;
+	avgOtherCoverage = 0;
+
+	numrchstates = mdd_count_onset(Fsm_FsmReadMddManager(modelFsm),modelCareStates,Fsm_FsmReadPresentStateVars(modelFsm));
+	if (McOptionsReadDbgLevel(options) != McDbgLevelNone_c) { /*print debug info*/
+	  fprintf(vis_stdout,"\nCoverage for all the Formulae w.r.t. all observable signals\n");
+	  fprintf(vis_stdout,"=============================================================\n");
+	}
+	for (sigarr=0;sigarr<array_n(signalList);sigarr++) {
+	  mdd_t *statesCovered, *uncoveredStateCube, *uncoveredStates;
+	  double numStatesCovered;
+	  char *nrOfUncoveredStatesString;
+	  int nrOfUncoveredStates, prntStates; /* nr of uncovered states that we output */
+
+	  Ntk_Network_t *modelNetworkC = Fsm_FsmReadNetwork(modelFsm);
+	  array_t *PSVarsC = Fsm_FsmReadPresentStateVars(modelFsm);
+	  mdd_manager *mddMgrC = Ntk_NetworkReadMddManager(Fsm_FsmReadNetwork(modelFsm));
+
+	  statesCovered = array_fetch(mdd_t *,statesCoveredList,sigarr);
+	  numStatesCovered = mdd_count_onset(Fsm_FsmReadMddManager(modelFsm),
+					     statesCovered,Fsm_FsmReadPresentStateVars(modelFsm));
+	  coverage = (numStatesCovered / numrchstates) * 100;
+	  avgCoverage = avgCoverage + coverage;
+	  sigType = array_fetch(int, signalTypeList,sigarr);
+	  if (sigType == 1) {
+	    coveragePI = coveragePI + numStatesCovered;
+	    avgPICoverage = avgPICoverage + coverage;
+	    numPI = numPI + 1;
+	  }
+	  else if (sigType == 0) {
+	    coveragePO = coveragePO + numStatesCovered;
+	    avgPOCoverage = avgPOCoverage + coverage;
+	    numPO = numPO + 1;
+	  }
+	  else {
+	    coverageOther = coverageOther + numStatesCovered;
+	    avgOtherCoverage = avgOtherCoverage + coverage;
+	    numOther = numOther + 1;
+	  }
+	  if (McOptionsReadDbgLevel(options) != McDbgLevelNone_c) { /*print debug info*/
+	    fprintf(vis_stdout,"\n# States covered w.r.t. %s = %.0f, Percentage of Coverage = %f\n",
+		    array_fetch(char *,signalList,sigarr), numStatesCovered, coverage);
+	    nrOfUncoveredStatesString = Cmd_FlagReadByName("nr_uncoveredstates");
+	    if(nrOfUncoveredStatesString == NIL(char))
+	      nrOfUncoveredStates = 1;
+	    else
+	      nrOfUncoveredStates = atoi(nrOfUncoveredStatesString);
+	    if (numStatesCovered < numrchstates) {
+	      if ((numrchstates-numStatesCovered) < nrOfUncoveredStates)
+		nrOfUncoveredStates = (int)(numrchstates-numStatesCovered);
+	      fprintf(vis_stdout,"#Printing reachable states NOT covered w.r.t. %s :\n",array_fetch(char *,signalList,sigarr));
+	      for (prntStates = 0;prntStates<nrOfUncoveredStates;prntStates++){  
+		fprintf(vis_stdout,"\n#State %d :\n",prntStates+1);
+		uncoveredStates = mdd_and(modelCareStates,statesCovered,1,0);
+		uncoveredStateCube = Mc_ComputeAMinterm(uncoveredStates, PSVarsC, mddMgrC);
+		mdd_free(uncoveredStates);
+		Mc_MintermPrint(uncoveredStateCube, PSVarsC, modelNetworkC);
+		mdd_free(uncoveredStateCube);
+	      }
+	    }
+	  }
+	}
+	fprintf(vis_stdout,"\nTotal Coverage for all the Formulae\n");
+	fprintf(vis_stdout,"=====================================\n");
+	for (sigarr=0;sigarr<array_n(signalList);sigarr++) {
+	  mdd_t *statesCovered;
+	  double numStatesCovered;
+	  char *type;
+	  int sigType;
+	  sigType = array_fetch(int, signalTypeList,sigarr);
+	  if (sigType == 1)
+	    type = "Primary Input";
+	  else if (sigType == 0)
+	    type = "Primary Output";
+	  else
+	    type = "Neither Primary output nor input";
+	  statesCovered = array_fetch(mdd_t *,statesCoveredList,sigarr);
+	  numStatesCovered = mdd_count_onset(Fsm_FsmReadMddManager(modelFsm),
+					     statesCovered,Fsm_FsmReadPresentStateVars(modelFsm));
+	  coverage = (numStatesCovered / numrchstates) * 100;
+	  fprintf(vis_stdout,"# States covered w.r.t. %s(%s) = %.0f, Percentage of Coverage = %f\n",type,
+		  array_fetch(char *,signalList,sigarr), numStatesCovered, coverage);
+	}
+	fprintf(vis_stdout,"--There are %.0f covered states (using improved coverage implementation)\n",numtotcoveredstates);
+	fprintf(vis_stdout,"--%.0f states covered by Primary Input Signals\n",coveragePI);
+	fprintf(vis_stdout,"--%.0f states covered by Primary Ouput Signals\n",coveragePO);
+	fprintf(vis_stdout,"--%.0f states covered by signals which are neither Primary input nor output Signals\n",coverageOther);
+	fprintf(vis_stdout,"--There are %.0f reachable states\n",numrchstates);
+
+	coverage = (numtotcoveredstates / numrchstates) * 100;
+	fprintf(vis_stdout,"Percentage of coverage (using improved coverage implementation)= %f\n ",coverage);
+	avgCoverage = avgCoverage / array_n(signalList);
+	fprintf(vis_stdout,"Average Percentage of coverage = %f\n",avgCoverage);
+	if (numPI < 1)
+	  fprintf(vis_stdout,"No Primary Input signals\n");
+	else {
+	  avgPICoverage = avgPICoverage / numPI;
+	  fprintf(vis_stdout,"Average Percentage of coverage for Primary inputs = %f\n",avgPICoverage);
+	}
+	if (numPO < 1)
+	  fprintf(vis_stdout,"No Primary Output signals\n");
+	else {
+	  avgPOCoverage = avgPOCoverage / numPO;
+	  fprintf(vis_stdout,"Average Percentage of coverage for Primary outputs = %f\n",avgPOCoverage);
+	}
+	if (numOther < 1)
+	  fprintf(vis_stdout,"No signals which are not primary\n");
+	else {
+	  avgOtherCoverage = avgOtherCoverage / numOther;
+	  fprintf(vis_stdout,"Average Percentage of coverage for signals which are not primary = %f\n",avgOtherCoverage);
+	}
+      }
+      else {
+	fprintf(vis_stdout,"Reachable states = NIL !\n");
+      }
+    }
+  }
+} /* McPrintCoverageSummary */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes a the set of covered states for a given formula and 
+               initial set of states given.]
+
+  Description [Presently Works for only a subset 
+  of ACTL viz. (propostional formulae, ->, AX, AG, AF, AU, ^ )]
+
+  SideEffects [Updates running totals.]
+
+  SeeAlso     [McEstimateCoverage CoveredStatesImproved]
+
+******************************************************************************/
+static mdd_t *
+CoveredStatesHoskote(
+  mdd_t *startstates_old,
+  Fsm_Fsm_t *fsm,
+  Ctlp_Formula_t *OrigFormula,
+  mdd_t *fairStates,
+  Fsm_Fairness_t *fairCondition,
+  array_t *careStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  Fsm_HintsArray_t *hintsArray,
+  Mc_GuidedSearch_t hintType,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  int buildOnionRing,
+  Mc_GSHScheduleType GSHschedule,
+  array_t *signalList,
+  array_t *statesCoveredList,
+  array_t *newCoveredStatesList,
+  array_t *statesToRemoveList)
+{
+  mdd_t *Covstates1, *temp1, *temp2;
+  mdd_t *Covstates2;
+  mdd_t *result;
+  mdd_t *travstates;
+  mdd_t *frstrchstates;
+  
+  mdd_t *startstates;
+
+  Ctlp_FormulaType formulaType;
+  Ctlp_Formula_t *rightFormula, *leftFormula, *tmp_formula, *existFormula;
+  double numresultstates; /* used for debugging <NJ> */
+
+  startstates = mdd_and(startstates_old,fairStates,1,1);
+
+  if (mdd_is_tautology(startstates,0)) {
+    if (verbosity > McVerbosityNone_c)
+      fprintf(vis_stdout,
+	      "\n--Startstates are down to zero. Coverage is hence zero.\n");
+    result = mdd_zero(Fsm_FsmReadMddManager(fsm));
+    numresultstates = mdd_count_onset(Fsm_FsmReadMddManager(fsm),result,
+				      Fsm_FsmReadPresentStateVars(fsm));
+    mdd_free(startstates);
+    return result;
+  }
+  if (Ctlp_FormulaTestIsQuantifierFree(OrigFormula)) {
+    /*propositional formula*/
+    result = CoveragePropositional(startstates, fsm, OrigFormula, fairStates,
+				   fairCondition, careStatesArray,
+				   earlyTermination, hintsArray, hintType,
+				   verbosity, dcLevel,buildOnionRing,
+				   GSHschedule, signalList, statesCoveredList,
+				   newCoveredStatesList, statesToRemoveList);
+    temp1 = result;
+    result = mdd_and(temp1,fairStates,1,1);
+    mdd_free(temp1);
+    mdd_free(startstates);
+    return result;
+  }
+  formulaType = Ctlp_FormulaReadType(OrigFormula);
+  switch (formulaType) {
+  case Ctlp_EG_c: 
+  case Ctlp_EF_c:
+  case Ctlp_EU_c:
+  case Ctlp_FwdU_c:
+  case Ctlp_FwdG_c:
+  case Ctlp_EY_c:
+  case Ctlp_EH_c:
+  case Ctlp_Cmp_c:
+  case Ctlp_EX_c:
+  case Ctlp_Init_c:  {
+    fprintf(vis_stdout,"** Can presently compute coverage for only a certain subset of ACTL,\n");
+    fprintf(vis_stdout,"** can't compute coverage of : ");
+    Ctlp_FormulaPrint(vis_stdout,OrigFormula);
+    fprintf(vis_stdout,"\n");
+    result = mdd_zero(Fsm_FsmReadMddManager(fsm));
+    numresultstates = mdd_count_onset(Fsm_FsmReadMddManager(fsm),result,Fsm_FsmReadPresentStateVars(fsm));
+    mdd_free(startstates);
+    return result;
+    break;
+  }
+  case Ctlp_AX_c:{
+    temp1 = Mc_FsmEvaluateEYFormula(fsm, startstates, fairStates, careStatesArray, verbosity, dcLevel);
+    Covstates1 = mdd_and(temp1,fairStates,1,1);
+    mdd_free(temp1);
+    leftFormula = Ctlp_FormulaReadLeftChild(OrigFormula);
+    result = CoveredStatesHoskote(Covstates1, fsm, leftFormula, fairStates,
+				  fairCondition, careStatesArray,
+				  earlyTermination, hintsArray,
+				  hintType, verbosity, dcLevel, buildOnionRing,
+				  GSHschedule, signalList, statesCoveredList,
+				  newCoveredStatesList, statesToRemoveList);
+    numresultstates = mdd_count_onset(Fsm_FsmReadMddManager(fsm),result,
+				      Fsm_FsmReadPresentStateVars(fsm));
+    mdd_free(Covstates1);
+    temp1 = result;
+    result = mdd_and(temp1,fairStates,1,1);
+    mdd_free(temp1);
+    mdd_free(startstates);
+    return result;
+    break;
+  }
+  case Ctlp_AG_c:{
+    mdd_t *initStates;
+    double numststates;
+    initStates = Fsm_FsmComputeInitialStates(fsm);
+    temp1 = mdd_one(Fsm_FsmReadMddManager(fsm));
+    if (mdd_equal_mod_care_set_array(startstates,initStates,careStatesArray)) {
+      if (verbosity > McVerbosityNone_c)
+	fprintf(vis_stdout,"\nUsing the reachable states already computed...");
+      temp2 = Fsm_FsmComputeReachableStates(fsm, 0, 1, 0, 0, 0, 0, 0,
+					    Fsm_Rch_Default_c, 0, 0,
+					    NIL(array_t), FALSE, NIL(array_t));
+    } else
+      temp2 = Mc_FsmEvaluateFwdUFormula(fsm, startstates, temp1, fairStates,
+					careStatesArray, NIL(array_t),
+					verbosity, dcLevel);
+    mdd_free(initStates);
+    numststates = mdd_count_onset(Fsm_FsmReadMddManager(fsm),startstates,
+				  Fsm_FsmReadPresentStateVars(fsm));
+    numresultstates = mdd_count_onset(Fsm_FsmReadMddManager(fsm),temp2,
+				      Fsm_FsmReadPresentStateVars(fsm));
+    mdd_free(temp1);
+    Covstates1 = mdd_and(temp2,fairStates,1,1);
+    mdd_free(temp2);
+    leftFormula = Ctlp_FormulaReadLeftChild(OrigFormula);
+    result = CoveredStatesHoskote(Covstates1, fsm, leftFormula, fairStates,
+				  fairCondition, careStatesArray,
+				  earlyTermination, hintsArray, hintType,
+				  verbosity, dcLevel, buildOnionRing,
+				  GSHschedule, signalList, statesCoveredList,
+				  newCoveredStatesList, statesToRemoveList);
+    numresultstates = mdd_count_onset(Fsm_FsmReadMddManager(fsm),result,
+				      Fsm_FsmReadPresentStateVars(fsm));
+    mdd_free(Covstates1);
+    temp1 = result;
+    result = mdd_and(temp1,fairStates,1,1);
+    mdd_free(temp1);
+    mdd_free(startstates);
+    return result;
+    break;
+  }
+  case Ctlp_AF_c:{
+    tmp_formula = OrigFormula;
+    OrigFormula = Ctlp_FormulaConvertAFtoAU(tmp_formula);
+    if (verbosity > McVerbosityNone_c) {
+      fprintf(vis_stdout,"Converting formula from\n");
+      Ctlp_FormulaPrint(vis_stdout,tmp_formula);
+      fprintf(vis_stdout,"\nto\n");
+      Ctlp_FormulaPrint(vis_stdout,OrigFormula);
+      fprintf(vis_stdout,"\n");
+    }
+#if 0
+    Ctlp_FormulaFree(tmp_formula);
+    formulaType = Ctlp_AU_c;
+#endif
+    /* convert to AFp to A (TRUE) U p  and then step thru to do coverage
+       for AU computation below*/
+  }
+  case Ctlp_AU_c:{
+    leftFormula = Ctlp_FormulaReadLeftChild(OrigFormula);
+    rightFormula = Ctlp_FormulaReadRightChild(OrigFormula);
+    travstates = traverse(fsm, fairStates, fairCondition, careStatesArray,
+			  earlyTermination, hintsArray, hintType, verbosity,
+			  dcLevel, buildOnionRing, GSHschedule, startstates,
+			  leftFormula,rightFormula);
+    if (verbosity > McVerbosityNone_c) {
+      fprintf(vis_stdout,"\n---Computing coverage for LHS of U formula i.e: ");
+      Ctlp_FormulaPrint(vis_stdout,leftFormula);
+      fprintf(vis_stdout,
+	      "\n------------------------------------------------\n");
+    }
+    Covstates1 = CoveredStatesHoskote(travstates, fsm, leftFormula, fairStates,
+				      fairCondition, careStatesArray,
+				      earlyTermination, hintsArray, hintType,
+				      verbosity, dcLevel, buildOnionRing,
+				      GSHschedule, signalList,
+				      statesCoveredList, newCoveredStatesList,
+				      statesToRemoveList);
+    mdd_free(travstates);
+    frstrchstates = firstReached(fsm, fairStates, fairCondition,
+				 careStatesArray, earlyTermination, hintsArray,
+				 hintType, verbosity, dcLevel, buildOnionRing,
+				 GSHschedule, startstates, rightFormula);
+    if (verbosity > McVerbosityNone_c) {
+      fprintf(vis_stdout,"\n---Computing coverage for RHS of U formula i.e: ");
+      Ctlp_FormulaPrint(vis_stdout,rightFormula);
+      fprintf(vis_stdout,
+	      "\n------------------------------------------------\n");
+    }
+    Covstates2 = CoveredStatesHoskote(frstrchstates, fsm, rightFormula,
+				      fairStates, fairCondition,
+				      careStatesArray, earlyTermination,
+				      hintsArray, hintType, verbosity, dcLevel,
+				      buildOnionRing, GSHschedule, signalList,
+				      statesCoveredList, newCoveredStatesList,
+				      statesToRemoveList);
+    mdd_free(frstrchstates);
+    result = mdd_or(Covstates1,Covstates2,1,1);
+    numresultstates = mdd_count_onset(Fsm_FsmReadMddManager(fsm),result,
+				      Fsm_FsmReadPresentStateVars(fsm));
+    mdd_free(Covstates1);
+    mdd_free(Covstates2);
+    temp1 = result;
+    result = mdd_and(temp1,fairStates,1,1);
+    if (formulaType == Ctlp_AF_c)
+      Ctlp_FormulaFree(OrigFormula);
+    mdd_free(temp1);
+    mdd_free(startstates);
+    return result;
+    break;
+  }
+  case Ctlp_AND_c:{
+    leftFormula = Ctlp_FormulaReadLeftChild(OrigFormula);
+    if (verbosity > McVerbosityNone_c) {
+      fprintf(vis_stdout,"---Computing coverage for LHS sub-formula: ");
+      Ctlp_FormulaPrint(vis_stdout,leftFormula);
+      fprintf(vis_stdout,
+	      "\n------------------------------------------------\n");
+    }
+    Covstates1 = CoveredStatesHoskote(startstates,fsm, leftFormula, fairStates,
+				      fairCondition, careStatesArray,
+				      earlyTermination, hintsArray, hintType,
+				      verbosity, dcLevel, buildOnionRing,
+				      GSHschedule, signalList,
+				      statesCoveredList, newCoveredStatesList,
+				      statesToRemoveList);
+    rightFormula = Ctlp_FormulaReadRightChild(OrigFormula);
+    if (verbosity > McVerbosityNone_c) {
+      fprintf(vis_stdout,"---Computing coverage for RHS sub-formula: ");
+      Ctlp_FormulaPrint(vis_stdout,rightFormula);
+      fprintf(vis_stdout,
+	      "\n------------------------------------------------\n");
+    }
+    Covstates2 = CoveredStatesHoskote(startstates,fsm, rightFormula,
+				      fairStates, fairCondition, 
+				      careStatesArray, earlyTermination,
+				      hintsArray, hintType, verbosity, dcLevel,
+				      buildOnionRing,GSHschedule, signalList,
+				      statesCoveredList, newCoveredStatesList,
+				      statesToRemoveList);
+    result = mdd_or(Covstates1, Covstates2, 1, 1);
+    numresultstates = mdd_count_onset(Fsm_FsmReadMddManager(fsm),result,
+				      Fsm_FsmReadPresentStateVars(fsm));
+    mdd_free(Covstates1);
+    mdd_free(Covstates2);
+    temp1 = result;
+    result = mdd_and(temp1,fairStates,1,1);
+    mdd_free(temp1);
+    mdd_free(startstates);
+    return result;
+    break;
+  }
+  case Ctlp_THEN_c:{ /*f1 -> f2 = !f2 -> !f1*/
+    mdd_t *nextstartstates, *Tb;
+   
+    if (Ctlp_FormulaTestIsQuantifierFree(Ctlp_FormulaReadLeftChild(OrigFormula))) { /*if f1 is propositional*/
+      leftFormula = Ctlp_FormulaReadLeftChild(OrigFormula);
+      rightFormula = Ctlp_FormulaReadRightChild(OrigFormula);
+    } else if (Ctlp_FormulaTestIsQuantifierFree(Ctlp_FormulaReadRightChild(OrigFormula))) { /*if f2 is propositional*/
+       /* Convert f1->f2 to !f2->!f1      */
+      leftFormula = Ctlp_FormulaConverttoComplement(Ctlp_FormulaReadRightChild(OrigFormula));
+      rightFormula = Ctlp_FormulaConverttoComplement(Ctlp_FormulaReadLeftChild(OrigFormula));
+    } else { /*neither are propositional*/
+      fprintf(vis_stdout,"\nCan't compute coverage of implications where neither side is propositional\n");
+      fprintf(vis_stdout,"Could not compute coverage of :");
+      Ctlp_FormulaPrint(vis_stdout,OrigFormula);
+      result = mdd_zero(Fsm_FsmReadMddManager(fsm));
+      mdd_free(startstates);
+      return result;
+    }
+    existFormula = Ctlp_FormulaConvertToExistentialForm(leftFormula);
+    Tb = Mc_FsmEvaluateFormula(fsm, existFormula, fairStates,
+			       fairCondition, careStatesArray,
+			       earlyTermination, hintsArray, hintType,
+			       verbosity, dcLevel, buildOnionRing,GSHschedule);
+    Ctlp_FormulaFree(existFormula);
+    nextstartstates = mdd_and(startstates, Tb,1,1);
+    mdd_free(Tb);
+    Covstates1 = CoveredStatesHoskote(nextstartstates,fsm, rightFormula,
+				      fairStates, fairCondition, 
+				      careStatesArray, earlyTermination,
+				      hintsArray, hintType, verbosity, dcLevel,
+				      buildOnionRing,GSHschedule, signalList,
+				      statesCoveredList, newCoveredStatesList,
+				      statesToRemoveList);
+    mdd_free(nextstartstates);
+    mdd_free(startstates);
+    return Covstates1;
+    break;
+  }
+  case Ctlp_XOR_c: {
+    tmp_formula = Ctlp_FormulaConvertXORtoOR(OrigFormula);
+    if (verbosity > McVerbosityNone_c) {
+      fprintf(vis_stdout,"\n--Converting XOR to AND and OR from:\n");
+      Ctlp_FormulaPrint(vis_stdout,OrigFormula);
+      fprintf(vis_stdout,"\nto\n");
+      Ctlp_FormulaPrint(vis_stdout, tmp_formula);
+      fprintf(vis_stdout,"\n");
+    } 
+    result = CoveredStatesHoskote(startstates, fsm, tmp_formula, fairStates,
+				  fairCondition, careStatesArray,
+				  earlyTermination, hintsArray,
+				  hintType, verbosity, dcLevel,buildOnionRing,
+				  GSHschedule, signalList, statesCoveredList,
+				  newCoveredStatesList, statesToRemoveList);
+    mdd_free(startstates);
+    return result;
+    break;
+  } 
+  case Ctlp_EQ_c: {
+    tmp_formula = Ctlp_FormulaConvertEQtoOR(OrigFormula);
+    if (verbosity > McVerbosityNone_c) {
+      fprintf(vis_stdout,"\n--Converting EQ to AND and OR from:\n");
+      Ctlp_FormulaPrint(vis_stdout,OrigFormula);
+      fprintf(vis_stdout,"\nto\n");
+      Ctlp_FormulaPrint(vis_stdout, tmp_formula);
+      fprintf(vis_stdout,"\n");
+    } 
+    result = CoveredStatesHoskote(startstates, fsm, tmp_formula, fairStates,
+				  fairCondition, careStatesArray,
+				  earlyTermination, hintsArray,
+				  hintType, verbosity, dcLevel,buildOnionRing,
+				  GSHschedule, signalList, statesCoveredList,
+				  newCoveredStatesList, statesToRemoveList);
+    mdd_free(startstates);
+    return result;
+    break;
+  }
+  case Ctlp_OR_c:{  /*f1+f2 = !f1 -> f2 = !f2 -> f1*/
+    mdd_t *nextstartstates, *Tb;
+
+    if (Ctlp_FormulaTestIsQuantifierFree(Ctlp_FormulaReadLeftChild(OrigFormula))) { /*if f1 is propositional*/
+      /* Convert f1+f2 to !f1->f2      */
+      leftFormula = Ctlp_FormulaConverttoComplement(Ctlp_FormulaReadLeftChild(OrigFormula));
+      rightFormula = Ctlp_FormulaReadRightChild(OrigFormula);
+    } else if (Ctlp_FormulaTestIsQuantifierFree(Ctlp_FormulaReadRightChild(OrigFormula))) { /*if f2 is propositional*/
+       /* Convert f1+f2 to !f2->f1      */
+      leftFormula = Ctlp_FormulaConverttoComplement(Ctlp_FormulaReadRightChild(OrigFormula));
+      rightFormula = Ctlp_FormulaReadLeftChild(OrigFormula);
+    } else { /*neither are propositional*/
+      fprintf(vis_stdout,"\nCan't compute coverage of disjunctions where neither side is propositional\n");
+      fprintf(vis_stdout,"Could not compute coverage of :");
+      Ctlp_FormulaPrint(vis_stdout,OrigFormula);
+      result = mdd_zero(Fsm_FsmReadMddManager(fsm));
+      mdd_free(startstates);
+      return result;
+    }
+    existFormula = Ctlp_FormulaConvertToExistentialForm(leftFormula);
+    Tb = Mc_FsmEvaluateFormula(fsm, existFormula, fairStates,
+			       fairCondition, careStatesArray,
+			       earlyTermination, hintsArray, hintType,
+			       verbosity, dcLevel, buildOnionRing,GSHschedule);
+    Ctlp_FormulaFree(existFormula);
+    Ctlp_FormulaFree(leftFormula);
+    nextstartstates = mdd_and(startstates, Tb,1,1);
+    mdd_free(Tb);
+    Covstates1 = CoveredStatesHoskote(nextstartstates,fsm, rightFormula,
+				      fairStates, fairCondition, 
+				      careStatesArray, earlyTermination,
+				      hintsArray, hintType, verbosity, dcLevel,
+				      buildOnionRing,GSHschedule, signalList,
+				      statesCoveredList, newCoveredStatesList,
+				      statesToRemoveList);
+    mdd_free(nextstartstates);
+    mdd_free(startstates);
+    return Covstates1;
+    break;
+  }
+  case Ctlp_NOT_c:{ /*include code for checking for 2 NOTs*/
+    leftFormula = Ctlp_FormulaReadLeftChild(OrigFormula);
+    if (!(Ctlp_FormulaTestIsQuantifierFree(leftFormula))) {
+      tmp_formula = Ctlp_FormulaPushNegation(leftFormula);
+      if (verbosity > McVerbosityNone_c) {
+	fprintf(vis_stdout,"\n--Pushing down negation one level. Converting formula from:\n");
+	Ctlp_FormulaPrint(vis_stdout,OrigFormula);
+	fprintf(vis_stdout,"\nto\n");
+	Ctlp_FormulaPrint(vis_stdout,tmp_formula);
+	fprintf(vis_stdout,"\n");
+      }
+      Covstates1 = CoveredStatesHoskote(startstates, fsm, tmp_formula,
+					fairStates, fairCondition, 
+					careStatesArray, earlyTermination,
+					hintsArray, hintType, verbosity,
+					dcLevel, buildOnionRing,GSHschedule,
+					signalList, statesCoveredList,
+					newCoveredStatesList,
+					statesToRemoveList);
+      Ctlp_FormulaFree(tmp_formula);
+      result = mdd_and(Covstates1,fairStates,1,1);
+      mdd_free(Covstates1);
+      mdd_free(startstates);
+      return result;
+#if 0
+      fprintf(vis_stdout,"** Can presently compute coverage for only a certain subset of ACTL\n");
+      fprintf(vis_stdout,"** can't compute coverage of : ");
+      Ctlp_FormulaPrint(vis_stdout,OrigFormula);
+      fprintf(vis_stdout,"\n");
+      mdd_free(startstates);
+      return mdd_zero(Fsm_FsmReadMddManager(fsm));
+#endif
+    } else { /*this part of the code is now never executed*/
+      fprintf(vis_stdout, "\n****Error, Should not have reached here\n");
+      mdd_free(startstates);
+      return mdd_zero(Fsm_FsmReadMddManager(fsm));
+    }
+    break;
+  }
+  case Ctlp_TRUE_c:
+  case Ctlp_FALSE_c: {
+    if (verbosity > McVerbosityNone_c)
+      fprintf(vis_stdout,"No observable signal, hence no coverage\n");
+    result = mdd_zero(Fsm_FsmReadMddManager(fsm));
+    mdd_free(startstates);
+    return result;
+    break;
+  }
+  case Ctlp_ID_c:{ /*should not reach here*/
+    fprintf(vis_stdout, "\n****Error, Should not have reached here\n");
+    mdd_free(startstates);
+    return mdd_zero(Fsm_FsmReadMddManager(fsm));
+    break;
+  }
+  default:
+    fprintf(vis_stderr, "**Ctlp Error: Unexpected operator detected.\n");
+    break;
+  }
+  assert(0);
+  return NIL(mdd_t);
+
+} /* CoveredStatesHoskote */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes a the set of covered states for a given formula and 
+               initial set of states given. ]
+
+  Description [Works for a larger subset of CTL than CoveredStatesHoskote.]
+
+  SideEffects [Updates running totals.]
+
+  SeeAlso     [McEstimateCoverage CoveredStatesHoskote]
+
+******************************************************************************/
+static mdd_t *
+CoveredStatesImproved(
+  mdd_t *startstates_old,
+  Fsm_Fsm_t *fsm,
+  Ctlp_Formula_t *OrigFormula,
+  mdd_t *fairStates,
+  Fsm_Fairness_t *fairCondition,
+  array_t *careStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  Fsm_HintsArray_t *hintsArray,
+  Mc_GuidedSearch_t hintType,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  int buildOnionRing,
+  Mc_GSHScheduleType GSHschedule,
+  array_t *signalList,
+  array_t *statesCoveredList,
+  array_t *newCoveredStatesList,
+  array_t *statesToRemoveList)
+{
+  mdd_t *Covstates1, *temp1, *temp2;
+  mdd_t *Covstates2;
+  mdd_t *result;
+  mdd_t *travstates;
+  mdd_t *frstrchstates;
+  
+  mdd_t *startstates;
+
+  Ctlp_FormulaType formulaType;
+  Ctlp_Formula_t *rightFormula, *leftFormula, *tmp_formula, *existFormula;
+  double numresultstates; /* used for debugging <NJ> */
+
+  startstates = mdd_and(startstates_old,fairStates,1,1);
+  
+  if (mdd_is_tautology(startstates,0)) {
+    if (verbosity > McVerbosityNone_c)
+      fprintf(vis_stdout,
+	      "\n--Startstates are down to zero. Coverage is hence zero.\n");
+    result = mdd_zero(Fsm_FsmReadMddManager(fsm));
+    numresultstates = mdd_count_onset(Fsm_FsmReadMddManager(fsm),result,
+				      Fsm_FsmReadPresentStateVars(fsm));
+    mdd_free(startstates);
+    return result;
+  }
+  if (Ctlp_FormulaTestIsQuantifierFree(OrigFormula)) {
+    /* propositional formula */
+    result = CoveragePropositional(startstates, fsm, OrigFormula, fairStates,
+				   fairCondition, careStatesArray,
+				   earlyTermination, hintsArray, hintType,
+				   verbosity, dcLevel,buildOnionRing,
+				   GSHschedule, signalList, statesCoveredList,
+				   newCoveredStatesList, statesToRemoveList);
+    temp1 = result;
+    result = mdd_and(temp1,fairStates,1,1);
+    mdd_free(temp1);
+    mdd_free(startstates);
+    return result;
+  }
+  formulaType = Ctlp_FormulaReadType(OrigFormula);
+  switch (formulaType) {
+  case Ctlp_EG_c: {/*EGp = p * EX(EGp) => C(So,EGp) = C(So,p) */
+    if (verbosity > McVerbosityNone_c) {
+      fprintf(vis_stdout,"\n--Computing underapproximation for EG formula:\n");
+      Ctlp_FormulaPrint(vis_stdout,OrigFormula);
+      fprintf(vis_stdout,"\n");
+    }
+    leftFormula = Ctlp_FormulaReadLeftChild(OrigFormula);
+    result = CoveredStatesImproved(startstates, fsm, leftFormula, fairStates,
+				   fairCondition, careStatesArray,
+				   earlyTermination, hintsArray, hintType,
+				   verbosity, dcLevel,buildOnionRing,
+				   GSHschedule, signalList, statesCoveredList,
+				   newCoveredStatesList, statesToRemoveList);
+    temp1 = result;
+    result = mdd_and(temp1,fairStates,1,1);
+    mdd_free(temp1);
+    mdd_free(startstates);
+    return result;
+    break;
+  }
+  case Ctlp_EF_c: {
+    if (verbosity > McVerbosityNone_c) {
+      fprintf(vis_stdout,"\n--Computing underapproximation for EF formula:\n");
+      Ctlp_FormulaPrint(vis_stdout,OrigFormula);
+      fprintf(vis_stdout,"\n");
+    }
+    tmp_formula = Ctlp_FormulaConvertEFtoOR(OrigFormula);
+    result = CoveredStatesImproved(startstates, fsm, tmp_formula, fairStates,
+				   fairCondition, careStatesArray,
+				   earlyTermination, hintsArray,
+				   hintType, verbosity, dcLevel,buildOnionRing,
+				   GSHschedule, signalList, statesCoveredList,
+				   newCoveredStatesList, statesToRemoveList);
+    Ctlp_FormulaFree(tmp_formula);
+    mdd_free(startstates);
+    return result;
+    break;
+  }
+  case Ctlp_EU_c: {
+    if (verbosity > McVerbosityNone_c) {
+      fprintf(vis_stdout,"\n--Computing underapproximation for EU formula: ");
+      Ctlp_FormulaPrint(vis_stdout,OrigFormula);
+      fprintf(vis_stdout,"\n");
+    }
+    tmp_formula = Ctlp_FormulaConvertEUtoOR(OrigFormula);
+    result = CoveredStatesImproved(startstates, fsm, tmp_formula, fairStates,
+				   fairCondition, careStatesArray,
+				   earlyTermination, hintsArray, hintType,
+				   verbosity, dcLevel,buildOnionRing,
+				   GSHschedule, signalList, statesCoveredList,
+				   newCoveredStatesList,statesToRemoveList);
+    mdd_free(startstates);
+    return result;
+    break;
+  }
+  case Ctlp_FwdU_c:
+  case Ctlp_FwdG_c:
+  case Ctlp_EY_c:
+  case Ctlp_EH_c:
+  case Ctlp_Cmp_c:
+  case Ctlp_EX_c:
+  case Ctlp_Init_c:  {
+    fprintf(vis_stdout,"** Can presently compute coverage for only a certain subset of ACTL,\n");
+    fprintf(vis_stdout,"** can't compute coverage of : ");
+    Ctlp_FormulaPrint(vis_stdout,OrigFormula);
+    fprintf(vis_stdout,"\n");
+    result = mdd_zero(Fsm_FsmReadMddManager(fsm));
+    numresultstates = mdd_count_onset(Fsm_FsmReadMddManager(fsm),result,
+				      Fsm_FsmReadPresentStateVars(fsm));
+    mdd_free(startstates);
+    return result;
+    break;
+  }
+  case Ctlp_AX_c:{
+    temp1 = Mc_FsmEvaluateEYFormula(fsm, startstates, fairStates, careStatesArray, verbosity, dcLevel);
+    Covstates1 = mdd_and(temp1,fairStates,1,1);
+    mdd_free(temp1);
+    leftFormula = Ctlp_FormulaReadLeftChild(OrigFormula);
+    result = CoveredStatesImproved(Covstates1, fsm, leftFormula, fairStates,
+				   fairCondition, careStatesArray,
+				   earlyTermination, hintsArray, hintType,
+				   verbosity, dcLevel,buildOnionRing,
+				   GSHschedule, signalList, statesCoveredList,
+				   newCoveredStatesList, statesToRemoveList);
+    numresultstates = mdd_count_onset(Fsm_FsmReadMddManager(fsm),result,
+				      Fsm_FsmReadPresentStateVars(fsm));
+    mdd_free(Covstates1);
+    temp1 = result;
+    result = mdd_and(temp1,fairStates,1,1);
+    mdd_free(temp1);
+    mdd_free(startstates);
+    return result;
+    break;
+  }
+  case Ctlp_AG_c:{
+    double numststates;
+    mdd_t  *initStates;
+    initStates = Fsm_FsmComputeInitialStates(fsm);
+    temp1 = mdd_one(Fsm_FsmReadMddManager(fsm));
+    if (mdd_equal_mod_care_set_array(startstates,initStates,careStatesArray)) {
+      if (verbosity > McVerbosityNone_c)
+	fprintf(vis_stdout,"\nUsing the reachable states already computed...");
+      temp2 = Fsm_FsmComputeReachableStates(fsm, 0, 1, 0, 0, 0, 0, 0,
+					    Fsm_Rch_Default_c, 0, 0,
+					    NIL(array_t), FALSE, NIL(array_t));
+    } else
+      temp2 = Mc_FsmEvaluateFwdUFormula(fsm, startstates, temp1, fairStates,
+					careStatesArray, NIL(array_t),
+					verbosity, dcLevel);
+    mdd_free(initStates);
+#if 0
+    temp2 = McForwardReachable(fsm, startstates, temp1, fairStates,
+			       careStatesArray, NIL(array_t),verbosity,
+			       dcLevel);
+#endif
+    numststates = mdd_count_onset(Fsm_FsmReadMddManager(fsm),startstates,
+				  Fsm_FsmReadPresentStateVars(fsm));
+    numresultstates = mdd_count_onset(Fsm_FsmReadMddManager(fsm),temp2,
+				      Fsm_FsmReadPresentStateVars(fsm));
+#if 0
+    fprintf(vis_stdout,"\nNum of forward reachable states from %.0f startstates = %.0f\n",numststates,numresultstates);
+#endif
+    mdd_free(temp1);
+    Covstates1 = mdd_and(temp2,fairStates,1,1);
+    mdd_free(temp2);
+    leftFormula = Ctlp_FormulaReadLeftChild(OrigFormula);
+    result = CoveredStatesImproved(Covstates1, fsm, leftFormula, fairStates,
+				   fairCondition, careStatesArray,
+				   earlyTermination, hintsArray, hintType,
+				   verbosity, dcLevel, buildOnionRing,
+				   GSHschedule, signalList, statesCoveredList,
+				   newCoveredStatesList, statesToRemoveList);
+    numresultstates = mdd_count_onset(Fsm_FsmReadMddManager(fsm),result,
+				      Fsm_FsmReadPresentStateVars(fsm));
+    mdd_free(Covstates1);
+    temp1 = result;
+    result = mdd_and(temp1,fairStates,1,1);
+    mdd_free(temp1);
+    mdd_free(startstates);
+    return result;
+    break;
+  }
+  case Ctlp_AF_c:{
+    tmp_formula = OrigFormula;
+    OrigFormula = Ctlp_FormulaConvertAFtoAU(tmp_formula);
+    if (verbosity > McVerbosityNone_c) {
+      fprintf(vis_stdout,"Converting formula from\n");
+      Ctlp_FormulaPrint(vis_stdout,tmp_formula);
+      fprintf(vis_stdout,"\nto\n");
+      Ctlp_FormulaPrint(vis_stdout,OrigFormula);
+      fprintf(vis_stdout,"\n");
+    }
+#if 0
+    Ctlp_FormulaFree(tmp_formula);
+    formulaType = Ctlp_AU_c;
+#endif
+    /* convert to AFp to A (TRUE) U p  and then step thru to do coverage
+       for AU computation below*/
+  }
+  case Ctlp_AU_c:{
+    leftFormula = Ctlp_FormulaReadLeftChild(OrigFormula);
+    rightFormula = Ctlp_FormulaReadRightChild(OrigFormula);
+    tmp_formula = Ctlp_FormulaCreate(Ctlp_OR_c,leftFormula,rightFormula);
+    CtlpFormulaIncrementRefCount(leftFormula);
+    CtlpFormulaIncrementRefCount(rightFormula);
+    travstates = traverse(fsm, fairStates, fairCondition, careStatesArray,
+			  earlyTermination, hintsArray, hintType, verbosity,
+			  dcLevel, buildOnionRing, GSHschedule, startstates,
+			  leftFormula, rightFormula);
+    if (verbosity > McVerbosityNone_c) {
+      fprintf(vis_stdout,"\n---Computing coverage for LHS of U formula i.e: ");
+      Ctlp_FormulaPrint(vis_stdout,leftFormula);
+      fprintf(vis_stdout,
+	      "\n------------------------------------------------\n");
+    }
+    Covstates1 = CoveredStatesImproved(travstates, fsm, tmp_formula,
+				       fairStates, fairCondition,
+				       careStatesArray, earlyTermination,
+				       hintsArray, hintType, verbosity,
+				       dcLevel, buildOnionRing, GSHschedule,
+				       signalList, statesCoveredList,
+				       newCoveredStatesList,
+				       statesToRemoveList);
+    mdd_free(travstates);
+    Ctlp_FormulaFree(tmp_formula);
+    frstrchstates = firstReached(fsm, fairStates, fairCondition,
+				 careStatesArray, earlyTermination, hintsArray,
+				 hintType, verbosity, dcLevel, buildOnionRing,
+				 GSHschedule,startstates,rightFormula);
+    if (verbosity > McVerbosityNone_c) {
+      fprintf(vis_stdout,"\n---Computing coverage for RHS of U formula i.e: ");
+      Ctlp_FormulaPrint(vis_stdout,rightFormula);
+      fprintf(vis_stdout,
+	      "\n------------------------------------------------\n");
+    }
+    Covstates2 = CoveredStatesImproved(frstrchstates, fsm, rightFormula,
+				       fairStates, fairCondition,
+				       careStatesArray, earlyTermination,
+				       hintsArray, hintType, verbosity,
+				       dcLevel, buildOnionRing, GSHschedule,
+				       signalList, statesCoveredList,
+				       newCoveredStatesList,
+				       statesToRemoveList);
+    mdd_free(frstrchstates);
+    result = mdd_or(Covstates1,Covstates2,1,1);
+    numresultstates = mdd_count_onset(Fsm_FsmReadMddManager(fsm),result,
+				      Fsm_FsmReadPresentStateVars(fsm));
+    mdd_free(Covstates1);
+    mdd_free(Covstates2);
+    temp1 = result;
+    result = mdd_and(temp1,fairStates,1,1);
+    if (formulaType == Ctlp_AF_c)
+      Ctlp_FormulaFree(OrigFormula);
+    mdd_free(temp1);
+    mdd_free(startstates);
+    return result;
+    break;
+  }
+  case Ctlp_AND_c:{
+    leftFormula = Ctlp_FormulaReadLeftChild(OrigFormula);
+    if (verbosity > McVerbosityNone_c) {
+      fprintf(vis_stdout,"\n---Computing coverage for LHS sub-formula: ");
+      Ctlp_FormulaPrint(vis_stdout,leftFormula);
+      fprintf(vis_stdout,
+	      "\n------------------------------------------------\n");
+    }
+    Covstates1 = CoveredStatesImproved(startstates,fsm, leftFormula,
+				       fairStates, fairCondition, 
+				       careStatesArray, earlyTermination,
+				       hintsArray, hintType, verbosity,
+				       dcLevel, buildOnionRing,GSHschedule,
+				       signalList, statesCoveredList,
+				       newCoveredStatesList,
+				       statesToRemoveList);
+    rightFormula = Ctlp_FormulaReadRightChild(OrigFormula);
+    if (verbosity > McVerbosityNone_c) {
+      fprintf(vis_stdout,"\n---Computing coverage for RHS sub-formula: ");
+      Ctlp_FormulaPrint(vis_stdout,rightFormula);
+      fprintf(vis_stdout,
+	      "\n------------------------------------------------\n");
+    }
+    Covstates2 = CoveredStatesImproved(startstates,fsm, rightFormula,
+				       fairStates, fairCondition, 
+				       careStatesArray, earlyTermination,
+				       hintsArray, hintType, verbosity,
+				       dcLevel, buildOnionRing,GSHschedule,
+				       signalList, statesCoveredList,
+				       newCoveredStatesList,
+				       statesToRemoveList);
+    result = mdd_or(Covstates1,Covstates2,1,1);
+    numresultstates = mdd_count_onset(Fsm_FsmReadMddManager(fsm),result,
+				      Fsm_FsmReadPresentStateVars(fsm));
+    mdd_free(Covstates1);
+    mdd_free(Covstates2);
+    temp1 = result;
+    result = mdd_and(temp1,fairStates,1,1);
+    mdd_free(temp1);
+    mdd_free(startstates);
+    return result;
+    break;
+  }
+  case Ctlp_THEN_c:{ /*f1 -> f2 = !f2 -> !f1*/
+    int sigarr;
+    array_t *listOfF2Signals = array_alloc(char *,0);
+    array_t *listOfF1Signals = array_alloc(char *,0);
+    array_t *newstatesToRemoveList = NIL(array_t);
+    mdd_t *nextstartstates, *Tb, *tmp_mdd;
+
+    leftFormula = Ctlp_FormulaReadLeftChild(OrigFormula);
+    rightFormula = Ctlp_FormulaReadRightChild(OrigFormula);
+    existFormula = Ctlp_FormulaConvertToExistentialForm(leftFormula);
+    Tb = Mc_FsmEvaluateFormula(fsm, existFormula,
+			       fairStates, fairCondition, careStatesArray,
+			       earlyTermination, hintsArray, hintType,
+			       verbosity, dcLevel, buildOnionRing,GSHschedule);
+    Ctlp_FormulaFree(existFormula);
+    nextstartstates = mdd_and(startstates, Tb,1,1);
+    mdd_free(Tb);
+    /*To compute C(So*T(f1),f2),    *
+     *first compute states to remove*/
+    newstatesToRemoveList = mdd_array_duplicate(statesToRemoveList);
+    findallsignalsInFormula(listOfF2Signals,rightFormula); /*find all signals in f2*/
+    for (sigarr=0;sigarr<array_n(listOfF2Signals);sigarr++) {
+      /*for all signals in f2*/
+      mdd_t *tmp_mdd2;
+      char *signalInF2;
+      int positionInGlobalList;
+      int rangeOfF2SigInF1;
+      signalInF2 = array_fetch(char *,listOfF2Signals,sigarr);
+      positionInGlobalList = positionOfSignalinList(signalInF2,signalList);
+      if (positionInGlobalList < 0) /*shouldn't happen*/
+	fprintf(vis_stdout,"Serious trouble. Found a new signal!\n");
+      rangeOfF2SigInF1 = RangeofSignalinFormula(fsm,signalInF2,leftFormula);
+      tmp_mdd = mdd_dup(nextstartstates);
+      if (rangeOfF2SigInF1 > 0) { /*signal in F2 also in F1*/
+	if (Ctlp_FormulaTestIsQuantifierFree(leftFormula)) { /*if f1 is propositional*/
+	  tmp_mdd2 = computedepend(fsm, leftFormula, fairStates, fairCondition,
+				   careStatesArray, earlyTermination,
+				   hintsArray, hintType, verbosity, dcLevel,
+				   buildOnionRing, GSHschedule, signalInF2,
+				   tmp_mdd);
+	  mdd_free(tmp_mdd);
+	  tmp_mdd = tmp_mdd2;
+	}
+	tmp_mdd2 = array_fetch(mdd_t *, newstatesToRemoveList,
+			       positionInGlobalList);
+	if (tmp_mdd2 != NIL(mdd_t))
+	  mdd_free(tmp_mdd2);
+	array_insert(mdd_t *,newstatesToRemoveList,positionInGlobalList,
+		     tmp_mdd);
+      } else {
+	mdd_free(tmp_mdd);
+      }
+    }
+    Covstates1 = CoveredStatesImproved(nextstartstates,fsm, rightFormula,
+				       fairStates, fairCondition, 
+				       careStatesArray, earlyTermination,
+				       hintsArray, hintType, verbosity,
+				       dcLevel, buildOnionRing, GSHschedule,
+				       signalList, statesCoveredList,
+				       newCoveredStatesList,
+				       newstatesToRemoveList);
+    mdd_free(nextstartstates);
+    mdd_array_free(newstatesToRemoveList);
+    array_free(listOfF2Signals);
+    /*End of coverage computation of f2*/
+
+    /*Now simillar computation for !f1 *
+     * Convert f1->f2 to !f2->!f1      */
+    leftFormula = Ctlp_FormulaConverttoComplement(Ctlp_FormulaReadRightChild(OrigFormula));
+    rightFormula = Ctlp_FormulaConverttoComplement(Ctlp_FormulaReadLeftChild(OrigFormula));
+    existFormula = Ctlp_FormulaConvertToExistentialForm(leftFormula);
+    Tb = Mc_FsmEvaluateFormula(fsm, existFormula,
+			       fairStates, fairCondition, careStatesArray,
+			       earlyTermination, hintsArray, hintType,
+			       verbosity, dcLevel, buildOnionRing,GSHschedule);
+    Ctlp_FormulaFree(existFormula);
+    nextstartstates = mdd_and(startstates, Tb, 1, 1);
+    mdd_free(Tb);
+    newstatesToRemoveList = mdd_array_duplicate(statesToRemoveList);
+    findallsignalsInFormula(listOfF1Signals,rightFormula);/*find all signals in !f1*/
+    for (sigarr=0;sigarr<array_n(listOfF1Signals);sigarr++) {
+      /*for all signals in !f1*/
+      mdd_t *tmp_mdd2;
+      char *signalInNotF1;
+      int positionInGlobalList;
+      int rangeOfNotF1SigInNotF2;
+      signalInNotF1 = array_fetch(char *,listOfF1Signals,sigarr);
+      positionInGlobalList = positionOfSignalinList(signalInNotF1,signalList);
+      if (positionInGlobalList < 0) fprintf(vis_stdout,"Serious trouble. Found a new signal!\n");
+      rangeOfNotF1SigInNotF2 = RangeofSignalinFormula(fsm,signalInNotF1,leftFormula);
+      tmp_mdd = mdd_dup(nextstartstates);
+      if (rangeOfNotF1SigInNotF2 > 0) {/*signal in !F1 also in !F2*/
+	if (Ctlp_FormulaTestIsQuantifierFree(leftFormula)) { /*if !f2 is propositional*/
+	  tmp_mdd2 = computedepend(fsm, leftFormula, fairStates, fairCondition,
+				   careStatesArray, earlyTermination,
+				   hintsArray, hintType, verbosity, dcLevel,
+				   buildOnionRing, GSHschedule, signalInNotF1,
+				   tmp_mdd);
+	  mdd_free(tmp_mdd);
+	  tmp_mdd = tmp_mdd2;
+	}
+	tmp_mdd2 = array_fetch(mdd_t *, newstatesToRemoveList,
+			       positionInGlobalList);
+	if (tmp_mdd2 != NIL(mdd_t))
+	  mdd_free(tmp_mdd2);
+	array_insert(mdd_t *,newstatesToRemoveList,positionInGlobalList,
+		     tmp_mdd);
+      } else {
+	mdd_free(tmp_mdd);
+      }
+    }
+    Ctlp_FormulaFree(leftFormula);
+    Covstates2 = CoveredStatesImproved(nextstartstates,fsm, rightFormula,
+				       fairStates, fairCondition, 
+				       careStatesArray, earlyTermination,
+				       hintsArray, hintType, verbosity,
+				       dcLevel, buildOnionRing,GSHschedule,
+				       signalList, statesCoveredList,
+				       newCoveredStatesList,
+				       newstatesToRemoveList);
+    
+    mdd_free(nextstartstates);
+    mdd_array_free(newstatesToRemoveList);
+    array_free(listOfF1Signals);
+    /*End of coverage computation of !f1*/
+    Ctlp_FormulaFree(rightFormula);
+    result = mdd_or(Covstates1,Covstates2,1,1);
+    mdd_free(Covstates1);
+    mdd_free(Covstates2);
+    mdd_free(startstates);
+    return result;
+    break;
+  }
+  case Ctlp_XOR_c: {
+    tmp_formula = Ctlp_FormulaConvertXORtoOR(OrigFormula);
+    if (verbosity > McVerbosityNone_c) {
+      fprintf(vis_stdout,"\n--Converting XOR to AND and OR from:\n");
+      Ctlp_FormulaPrint(vis_stdout,OrigFormula);
+      fprintf(vis_stdout,"\nto\n");
+      Ctlp_FormulaPrint(vis_stdout, tmp_formula);
+      fprintf(vis_stdout,"\n");
+    } 
+    result = CoveredStatesImproved(startstates, fsm, tmp_formula, fairStates,
+				   fairCondition, careStatesArray,
+				   earlyTermination, hintsArray, hintType,
+				   verbosity, dcLevel,buildOnionRing,
+				   GSHschedule, signalList, statesCoveredList,
+				   newCoveredStatesList, statesToRemoveList);
+    mdd_free(startstates);
+    return result;
+    break;
+  }
+  case Ctlp_EQ_c: {
+    tmp_formula = Ctlp_FormulaConvertEQtoOR(OrigFormula);
+    if (verbosity > McVerbosityNone_c) {
+      fprintf(vis_stdout,"\n--Converting EQ to AND and OR");
+      Ctlp_FormulaPrint(vis_stdout,OrigFormula);
+      fprintf(vis_stdout,"\nto\n");
+      Ctlp_FormulaPrint(vis_stdout, tmp_formula);
+      fprintf(vis_stdout,"\n");
+    } 
+    result = CoveredStatesImproved(startstates, fsm, tmp_formula, fairStates,
+				   fairCondition, careStatesArray,
+				   earlyTermination, hintsArray, hintType,
+				   verbosity, dcLevel,buildOnionRing,
+				   GSHschedule, signalList, statesCoveredList,
+				   newCoveredStatesList, statesToRemoveList);
+    mdd_free(startstates);
+    return result;
+    break;
+  }     
+  case Ctlp_OR_c:{  /*f1+f2 = !f1 -> f2 = !f2 -> f1*/
+    int sigarr;
+    array_t *listOfF2Signals = array_alloc(char *,0);
+    array_t *listOfF1Signals = array_alloc(char *,0);
+    array_t *newstatesToRemoveList = NIL(array_t);
+    mdd_t *nextstartstates, *Tb, *tmp_mdd;
+    
+    /*To compute C(So*T(!f1),f2),  *
+     *convert to form like !f1->f2 */
+    leftFormula = Ctlp_FormulaConverttoComplement(Ctlp_FormulaReadLeftChild(OrigFormula));
+    rightFormula = Ctlp_FormulaReadRightChild(OrigFormula);
+    existFormula = Ctlp_FormulaConvertToExistentialForm(leftFormula);
+    Tb = Mc_FsmEvaluateFormula(fsm, existFormula,
+			       fairStates, fairCondition, careStatesArray,
+			       earlyTermination, hintsArray, hintType,
+			       verbosity, dcLevel, buildOnionRing,GSHschedule);
+    Ctlp_FormulaFree(existFormula);
+    nextstartstates = mdd_and(startstates, Tb, 1, 1);
+    mdd_free(Tb);
+    /*first compute states to remove*/
+    newstatesToRemoveList = mdd_array_duplicate(statesToRemoveList);
+    findallsignalsInFormula(listOfF2Signals,rightFormula);/*find all signals in f2*/
+    for (sigarr=0;sigarr<array_n(listOfF2Signals);sigarr++) {
+      /*for all signals in f2*/
+      mdd_t *tmp_mdd2;
+      char *signalInF2;
+      int positionInGlobalList;
+      int rangeOfF2SigInF1;
+      signalInF2 = array_fetch(char *,listOfF2Signals,sigarr);
+      positionInGlobalList = positionOfSignalinList(signalInF2,signalList);
+      if (positionInGlobalList < 0) fprintf(vis_stdout,"Serious trouble. Found a new signal!\n");
+      rangeOfF2SigInF1 = RangeofSignalinFormula(fsm,signalInF2,leftFormula);
+      tmp_mdd = mdd_dup(nextstartstates);
+      if (rangeOfF2SigInF1 > 0) {/*signal in F2 also in F1*/
+	if (Ctlp_FormulaTestIsQuantifierFree(leftFormula)) { /*if f1 is propositional*/
+	  tmp_mdd2 = computedepend(fsm, leftFormula, fairStates, fairCondition,
+				   careStatesArray, earlyTermination,
+				   hintsArray, hintType, verbosity, dcLevel,
+				   buildOnionRing, GSHschedule, signalInF2,
+				   tmp_mdd);
+	  mdd_free(tmp_mdd);
+	  tmp_mdd = tmp_mdd2;
+	}
+	tmp_mdd2 = array_fetch(mdd_t *, newstatesToRemoveList,
+			       positionInGlobalList);
+	if (tmp_mdd2 != NIL(mdd_t))
+	  mdd_free(tmp_mdd2);
+	array_insert(mdd_t *,newstatesToRemoveList,positionInGlobalList,
+		     tmp_mdd);
+      } else {
+	mdd_free(tmp_mdd);
+      }
+    }
+    Ctlp_FormulaFree(leftFormula);
+    Covstates1 = CoveredStatesImproved(nextstartstates,fsm, rightFormula,
+				       fairStates, fairCondition, 
+				       careStatesArray, earlyTermination,
+				       hintsArray, hintType, verbosity,
+				       dcLevel, buildOnionRing,GSHschedule,
+				       signalList, statesCoveredList,
+				       newCoveredStatesList,
+				       newstatesToRemoveList);
+    mdd_free(nextstartstates);
+    mdd_array_free(newstatesToRemoveList);
+    array_free(listOfF2Signals);
+    /*End of coverage computation of f2*/
+
+    /*Now simillar computation for !f1 *
+     * Convert f1+f2 to !f2->f1      */
+    leftFormula = Ctlp_FormulaConverttoComplement(Ctlp_FormulaReadRightChild(OrigFormula));
+    rightFormula = Ctlp_FormulaReadLeftChild(OrigFormula);
+    existFormula = Ctlp_FormulaConvertToExistentialForm(leftFormula);
+    Tb = Mc_FsmEvaluateFormula(fsm, existFormula,
+			       fairStates, fairCondition, careStatesArray,
+			       earlyTermination, hintsArray, hintType,
+			       verbosity, dcLevel, buildOnionRing,GSHschedule);
+    Ctlp_FormulaFree(existFormula);
+    nextstartstates = mdd_and(startstates, Tb,1,1);
+    mdd_free(Tb);
+    newstatesToRemoveList = mdd_array_duplicate(statesToRemoveList);
+    findallsignalsInFormula(listOfF1Signals,rightFormula);/*find all signals in f1*/
+    for (sigarr=0;sigarr<array_n(listOfF1Signals);sigarr++) {
+      /*for all signals in f1*/
+      mdd_t *tmp_mdd2;
+      char *signalInF1;
+      int positionInGlobalList;
+      int rangeOfF1SigInF2;
+      signalInF1 = array_fetch(char *,listOfF1Signals,sigarr);
+      positionInGlobalList = positionOfSignalinList(signalInF1,signalList);
+      if (positionInGlobalList < 0) fprintf(vis_stdout,"Serious trouble. Found a new signal!\n");
+      rangeOfF1SigInF2 = RangeofSignalinFormula(fsm,signalInF1,leftFormula);
+      tmp_mdd = mdd_dup(nextstartstates);
+      if (rangeOfF1SigInF2 > 0) {/*signal in !F1 also in !F2*/
+	if (Ctlp_FormulaTestIsQuantifierFree(leftFormula)) { /*if !f2 is propositional*/
+	  tmp_mdd2 = computedepend(fsm, leftFormula, fairStates, fairCondition,
+				   careStatesArray, earlyTermination,
+				   hintsArray, hintType, verbosity, dcLevel,
+				   buildOnionRing, GSHschedule, signalInF1,
+				   tmp_mdd);
+	  mdd_free(tmp_mdd);
+	  tmp_mdd = tmp_mdd2;
+	}
+	tmp_mdd2 = array_fetch(mdd_t *, newstatesToRemoveList,
+			       positionInGlobalList);
+	if (tmp_mdd2 != NIL(mdd_t))
+	  mdd_free(tmp_mdd2);
+	array_insert(mdd_t *,newstatesToRemoveList,positionInGlobalList,
+		     tmp_mdd);
+      } else {
+	mdd_free(tmp_mdd);
+      }
+    }
+    Ctlp_FormulaFree(leftFormula);
+    Covstates2 = CoveredStatesImproved(nextstartstates,fsm, rightFormula,
+				       fairStates, fairCondition, 
+				       careStatesArray, earlyTermination,
+				       hintsArray, hintType, verbosity,
+				       dcLevel, buildOnionRing,GSHschedule,
+				       signalList, statesCoveredList,
+				       newCoveredStatesList,
+				       newstatesToRemoveList);
+    mdd_free(nextstartstates);
+    mdd_array_free(newstatesToRemoveList);
+    array_free(listOfF1Signals);
+    /*End of coverage computation of !f1*/
+    
+    result = mdd_or(Covstates1,Covstates2,1,1);
+    mdd_free(Covstates1);
+    mdd_free(Covstates2);
+    mdd_free(startstates);
+    return result;
+    break;
+  }
+  case Ctlp_NOT_c:{ /*include code for checking for 2 NOTs*/
+    leftFormula = Ctlp_FormulaReadLeftChild(OrigFormula);
+    if (!(Ctlp_FormulaTestIsQuantifierFree(leftFormula))) {
+      tmp_formula = Ctlp_FormulaPushNegation(leftFormula);
+      if (verbosity > McVerbosityNone_c) {
+	fprintf(vis_stdout,"\n--Pushing down negation one level. Converting formula from:\n");
+	Ctlp_FormulaPrint(vis_stdout,OrigFormula);
+	fprintf(vis_stdout,"\nto\n");
+	Ctlp_FormulaPrint(vis_stdout,tmp_formula);
+	fprintf(vis_stdout,"\n");
+      }
+      Covstates1 = CoveredStatesImproved(startstates,fsm, tmp_formula,
+					 fairStates, fairCondition, 
+					 careStatesArray, earlyTermination,
+					 hintsArray, hintType, verbosity,
+					 dcLevel, buildOnionRing,GSHschedule,
+					 signalList, statesCoveredList,
+					 newCoveredStatesList,
+					 statesToRemoveList);
+      result = mdd_and(Covstates1,fairStates,1,1);
+      Ctlp_FormulaFree(tmp_formula);
+      mdd_free(Covstates1);
+      mdd_free(startstates);
+      return result;
+    } else { /*this part of the code is now never executed*/
+       fprintf(vis_stdout, "\n****Error, Should not have reached here\n");
+       mdd_free(startstates);
+       return mdd_zero(Fsm_FsmReadMddManager(fsm));
+    }
+    break;
+  }
+  case Ctlp_TRUE_c:
+  case Ctlp_FALSE_c: {
+    if (verbosity > McVerbosityNone_c)
+      fprintf(vis_stdout,"No observable signal, hence no coverage\n");
+    result = mdd_zero(Fsm_FsmReadMddManager(fsm));
+    mdd_free(startstates);
+    return result;
+    break;
+  }
+  case Ctlp_ID_c:{ /*should not reach here*/
+    fprintf(vis_stdout, "\n****Error, Should not have reached here\n");
+    mdd_free(startstates);
+    return mdd_zero(Fsm_FsmReadMddManager(fsm));
+    break;
+  }
+  default:
+    fprintf(vis_stderr, "**Ctlp Error: Unexpected operator detected.\n");
+    mdd_free(startstates);
+    break;
+  }
+  assert(0);
+  return NIL(mdd_t);
+
+} /* End of CoveredStatesImproved */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the coverage for propositional formulae]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     [CoveredStatesImproved CoveredStatesHoskote]
+  
+******************************************************************************/
+static mdd_t *
+CoveragePropositional(
+  mdd_t *startstates_old,
+  Fsm_Fsm_t *fsm,
+  Ctlp_Formula_t *OrigFormula,
+  mdd_t *fairStates,
+  Fsm_Fairness_t *fairCondition,
+  array_t *careStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  Fsm_HintsArray_t *hintsArray,
+  Mc_GuidedSearch_t hintType,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  int buildOnionRing,
+  Mc_GSHScheduleType GSHschedule,
+  array_t *signalList,
+  array_t *statesCoveredList,
+  array_t *newCoveredStatesList,
+  array_t *statesToRemoveList)
+{
+  mdd_t *Tb, *result;
+  mdd_t *startstates;
+  array_t *listOfSignals = array_alloc(char *,0);
+  int i,positionInList;
+  char *signal;
+  Ctlp_Formula_t *tmpFormula;
+  
+  result = mdd_zero(Fsm_FsmReadMddManager(fsm));
+  findallsignalsInFormula(listOfSignals,OrigFormula);
+  if (array_n(listOfSignals)==0) {
+    if (verbosity > McVerbosityNone_c)
+      fprintf(vis_stdout,"No observable signals, hence no coverage\n");
+    array_free(listOfSignals);
+    return result;
+  }
+  /*else*/
+  startstates = mdd_and(startstates_old,fairStates,1,1);
+  tmpFormula = Ctlp_FormulaConvertToExistentialForm(OrigFormula);
+  Tb = Mc_FsmEvaluateFormula(fsm, tmpFormula, fairStates,
+			     fairCondition, careStatesArray, earlyTermination, 
+			     hintsArray, hintType, verbosity, dcLevel,
+			     buildOnionRing,GSHschedule);
+  Ctlp_FormulaFree(tmpFormula);
+  for (i=0;i<array_n(listOfSignals);i++) {
+    mdd_t *statesCovered, *newCoveredStates, *statesToRemove, *CovStates, *tmp_mdd, *tmp_mdd2;
+    signal = array_fetch(char *,listOfSignals,i);
+    positionInList = positionOfSignalinList(signal,signalList);
+    if (positionInList < 0) fprintf(vis_stdout,"Serious trouble. Found a new signal!\n");
+    statesCovered = array_fetch(mdd_t *,statesCoveredList,positionInList);
+    newCoveredStates = array_fetch(mdd_t *,newCoveredStatesList,positionInList);
+    statesToRemove = array_fetch(mdd_t *,statesToRemoveList,positionInList);
+    CovStates = computedependHoskote(fsm, OrigFormula, fairStates,
+				     fairCondition, careStatesArray,
+				     earlyTermination, hintsArray,
+				     hintType, verbosity, dcLevel,
+				     buildOnionRing, GSHschedule,
+				     startstates, signal, Tb, statesCovered,
+				     newCoveredStates,statesToRemove);
+    tmp_mdd = mdd_or(newCoveredStates,CovStates,1,1);
+    mdd_free(newCoveredStates);
+    array_insert(mdd_t *,newCoveredStatesList,positionInList,tmp_mdd);/*update newCoveredStatesList*/
+    tmp_mdd2 = result;
+    result = mdd_or(tmp_mdd2,CovStates,1,1);
+    mdd_free(tmp_mdd2);
+    mdd_free(CovStates);
+  }
+  mdd_free(Tb);
+  mdd_free(startstates);
+  array_free(listOfSignals);
+  return result;
+} /* CoveragePropositional */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the following for use in coverage computation for 
+               propositional formulae:
+
+               computedepend = T(b) ^ T(!b|q->!q)
+	      where,
+	          T(f) => Set of states satisfying f
+		  b is a propositional formula
+		  q is an observed signal]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     [computedependHoskote]
+
+******************************************************************************/
+static mdd_t *
+computedepend(
+  Fsm_Fsm_t *fsm,
+  Ctlp_Formula_t *formula,
+  mdd_t *fairStates,
+  Fsm_Fairness_t *fairCondition,
+  array_t *careStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  Fsm_HintsArray_t *hintsArray,
+  Mc_GuidedSearch_t hintType,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  int buildOnionRing,
+  Mc_GSHScheduleType GSHschedule,
+  char *signal,
+  mdd_t *SoAndTb_old)     
+{
+  mdd_t *TnotBnotQ, *Covstates, *SoAndTb;
+  Ctlp_Formula_t *convertedformula, *tmp_formula, *existFormula;
+  SoAndTb = mdd_and(SoAndTb_old,fairStates,1,1); 
+  convertedformula = FormulaConvertSignalComplement(fsm,signal,formula);
+  if (convertedformula != NIL(Ctlp_Formula_t)) {
+    tmp_formula = Ctlp_FormulaConverttoComplement(convertedformula);
+    existFormula = Ctlp_FormulaConvertToExistentialForm(tmp_formula);
+    TnotBnotQ =  Mc_FsmEvaluateFormula(fsm, existFormula,
+				       fairStates, fairCondition,
+				       careStatesArray, earlyTermination,
+				       hintsArray, hintType, verbosity,
+				       dcLevel, buildOnionRing,GSHschedule);
+    Ctlp_FormulaFree(existFormula);
+    Ctlp_FormulaFree(tmp_formula);
+  } else {
+    TnotBnotQ = mdd_zero(Fsm_FsmReadMddManager(fsm));
+  }
+  Ctlp_FormulaFree(convertedformula);
+  Covstates = mdd_and(SoAndTb,TnotBnotQ,1,1); /*covered states*/
+  mdd_free(SoAndTb);
+  mdd_free(TnotBnotQ);
+  return Covstates;
+} /* computedepend */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the following for use in coverage computation for 
+               propositional formulae:
+
+               computedepend = T(b) ^ T(!b|q->!q)
+	      where,
+	          T(f) => Set of states satisfying f
+		  b is a propositional formula
+		  q is an observed signal]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     [computedepend]
+  
+******************************************************************************/
+static mdd_t *
+computedependHoskote(
+  Fsm_Fsm_t *fsm,
+  Ctlp_Formula_t *formula,
+  mdd_t *fairStates,
+  Fsm_Fairness_t *fairCondition,
+  array_t *careStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  Fsm_HintsArray_t *hintsArray,
+  Mc_GuidedSearch_t hintType,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  int buildOnionRing,
+  Mc_GSHScheduleType GSHschedule,
+  mdd_t *startstates_old,
+  char *signal,
+  mdd_t *Tb,
+  mdd_t *statesCovered,
+  mdd_t *newCoveredStates,
+  mdd_t *statesToRemove)     
+{
+  mdd_t *TnotBnotQ,*Covstates,*startstates,*tmp_mdd, *newCovstates;
+  Ctlp_Formula_t *convertedformula;
+  startstates = mdd_and(startstates_old,fairStates,1,1); 
+  convertedformula = FormulaConvertSignalComplement(fsm,signal,formula);
+
+  if (convertedformula != NIL(Ctlp_Formula_t)) {
+    Ctlp_Formula_t *tmp_formula, *tmp_formula2;
+    tmp_formula = Ctlp_FormulaConverttoComplement(convertedformula);
+    Ctlp_FormulaFree(convertedformula);
+    tmp_formula2 = Ctlp_FormulaConvertToExistentialForm(tmp_formula);
+    Ctlp_FormulaFree(tmp_formula);
+    TnotBnotQ =  Mc_FsmEvaluateFormula(fsm, tmp_formula2, 
+				       fairStates, fairCondition,
+				       careStatesArray, earlyTermination,
+				       hintsArray, hintType, verbosity,
+				       dcLevel, buildOnionRing,GSHschedule);
+    Ctlp_FormulaFree(tmp_formula2);
+  } else {
+    TnotBnotQ = mdd_zero(Fsm_FsmReadMddManager(fsm));
+  }
+  
+  tmp_mdd = mdd_and(Tb,TnotBnotQ,1,1);
+  mdd_free(TnotBnotQ);
+  Covstates = mdd_and(startstates,tmp_mdd,1,1); /*covered states*/
+  mdd_free(tmp_mdd);
+  tmp_mdd = Covstates;
+  mdd_free(startstates);
+  Covstates = mdd_and(Covstates, statesToRemove,1,0); /*remove the states to remove*/
+  mdd_free(tmp_mdd);
+  tmp_mdd = mdd_or(statesCovered,newCoveredStates,1,1);
+  newCovstates = mdd_and(Covstates,tmp_mdd,1,0); /* newly covered states*/
+  mdd_free(tmp_mdd);
+#if 0
+  fprintf(vis_stdout,"States covered w.r.t. %s = %0.f , new = %0.f\n",signal,
+	    mdd_count_onset(Fsm_FsmReadMddManager(fsm),Covstates,
+			    Fsm_FsmReadPresentStateVars(fsm)),
+	    mdd_count_onset(Fsm_FsmReadMddManager(fsm),newCovstates,
+			    Fsm_FsmReadPresentStateVars(fsm)));
+#endif
+  mdd_free(newCovstates);  
+  return Covstates;
+
+} /* computedependHoskote */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the following for use in coverage computation for AU:
+              traverse(So,f1,f2) = newstartstates(So) U 
+	                             traverse(EY(newstartstates(So)),f1,f2)
+	       (see function newstartstates for its definition ]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     [newstartstates]
+
+******************************************************************************/
+static mdd_t *
+traverse(
+  Fsm_Fsm_t *fsm,
+  mdd_t *fairStates,
+  Fsm_Fairness_t *fairCondition,
+  array_t *careStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  Fsm_HintsArray_t *hintsArray,
+  Mc_GuidedSearch_t hintType,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  int buildOnionRing,
+  Mc_GSHScheduleType GSHschedule,
+  mdd_t *startstates,
+  Ctlp_Formula_t *formula1,
+  Ctlp_Formula_t *formula2)
+{
+  mdd_t *temp_mdd,*newSo, *Tf1_and_Tnotf2, *newStates, *oldStates, *Tf1, *Tnotf2;
+  Ctlp_Formula_t *tmp_formula, *existFormula;
+  int travcnt;
+  oldStates = mdd_zero(Fsm_FsmReadMddManager(fsm));
+  newStates = mdd_zero(Fsm_FsmReadMddManager(fsm));
+  newSo = mdd_dup(startstates);
+  existFormula = Ctlp_FormulaConvertToExistentialForm(formula1);
+  Tf1 = Mc_FsmEvaluateFormula(fsm, existFormula, fairStates,
+			      fairCondition, careStatesArray,
+			      earlyTermination, hintsArray,
+			      hintType, verbosity, dcLevel,
+			      buildOnionRing,GSHschedule);
+  Ctlp_FormulaFree(existFormula);
+  tmp_formula = Ctlp_FormulaConverttoComplement(formula2);
+  existFormula = Ctlp_FormulaConvertToExistentialForm(tmp_formula);
+  Tnotf2 = Mc_FsmEvaluateFormula(fsm, existFormula, fairStates, fairCondition,
+				 careStatesArray, earlyTermination, hintsArray,
+				 hintType, verbosity, dcLevel,
+				 buildOnionRing, GSHschedule);
+  Ctlp_FormulaFree(existFormula);
+  Ctlp_FormulaFree(tmp_formula);
+  temp_mdd = mdd_and(Tf1,Tnotf2,1,1);
+  mdd_free(Tf1);
+  mdd_free(Tnotf2);
+  Tf1_and_Tnotf2 = mdd_and(temp_mdd,fairStates,1,1);
+  mdd_free(temp_mdd);
+  temp_mdd = newSo;
+  newSo = mdd_and(temp_mdd,Tf1_and_Tnotf2,1,1);
+  mdd_free(temp_mdd);
+  temp_mdd = newStates;
+  newStates = mdd_or(temp_mdd,newSo,1,1);
+  mdd_free(temp_mdd);
+  travcnt = 0;
+  while (!(mdd_equal_mod_care_set_array(newStates,oldStates,careStatesArray))) {
+    mdd_t *tmp_mdd = oldStates;
+    oldStates = mdd_or(tmp_mdd,newStates,1,1);
+    mdd_free(tmp_mdd);
+    tmp_mdd = newSo;
+    newSo = Mc_FsmEvaluateEYFormula(fsm, tmp_mdd, fairStates, careStatesArray, verbosity, dcLevel);
+    mdd_free(tmp_mdd);
+    tmp_mdd = newSo;
+    newSo = mdd_and(tmp_mdd,Tf1_and_Tnotf2,1,1);
+    mdd_free(tmp_mdd);
+    tmp_mdd = newStates;
+    newStates = mdd_or(tmp_mdd,newSo,1,1);
+    mdd_free(tmp_mdd);
+  }
+  mdd_free(oldStates);
+  mdd_free(newSo);
+  mdd_free(Tf1_and_Tnotf2);
+  return newStates;
+
+} /* traverse */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the following for use in coverage computation for AU:
+              firstReached(So,f2) = (So ^ T(f2)) U 
+	                             firstReached(EY(So^T(!f2)),f2)
+	      where,
+	          T(f2) => Set of states satisfying f2 ]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static mdd_t *
+firstReached(
+  Fsm_Fsm_t *fsm,
+  mdd_t *fairStates,
+  Fsm_Fairness_t *fairCondition,
+  array_t *careStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  Fsm_HintsArray_t *hintsArray,
+  Mc_GuidedSearch_t hintType,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  int buildOnionRing,
+  Mc_GSHScheduleType GSHschedule,
+  mdd_t *startstates,
+  Ctlp_Formula_t *formula)
+{
+  int frstcnt;
+  mdd_t *temp1, *temp2, *oldSo, *CovStates, *Tf2, *Tnotf2, *zeroMDD;
+  Ctlp_Formula_t *tmp_formula, *existFormula;
+  oldSo = mdd_dup(startstates);
+  zeroMDD = mdd_zero(Fsm_FsmReadMddManager(fsm));
+  existFormula = Ctlp_FormulaConvertToExistentialForm(formula);
+  Tf2 =  Mc_FsmEvaluateFormula(fsm, existFormula, fairStates,
+			       fairCondition, careStatesArray,
+			       earlyTermination, hintsArray,
+			       hintType, verbosity,
+			       dcLevel, buildOnionRing, GSHschedule);
+  Ctlp_FormulaFree(existFormula);
+  tmp_formula = Ctlp_FormulaConverttoComplement(formula);
+  existFormula = Ctlp_FormulaConvertToExistentialForm(tmp_formula);
+  Tnotf2 = Mc_FsmEvaluateFormula(fsm, existFormula,
+				 fairStates, fairCondition, 
+				 careStatesArray,earlyTermination, 
+				 hintsArray, hintType, verbosity, 
+				 dcLevel, buildOnionRing,GSHschedule);
+  Ctlp_FormulaFree(existFormula);
+  Ctlp_FormulaFree(tmp_formula);
+  CovStates = mdd_and(oldSo,Tf2,1,1);
+  temp1 = mdd_dup(oldSo);
+  temp2 = mdd_and(oldSo,Tnotf2,1,1);
+  frstcnt = 0;
+  while (!(mdd_equal_mod_care_set_array(temp2,zeroMDD,careStatesArray))) {
+    mdd_t *tmp_mdd1, *tmp_mdd2, *tmp_mdd;
+    tmp_mdd = Mc_FsmEvaluateEYFormula(fsm, temp2, fairStates, careStatesArray, verbosity, dcLevel); /*forward(So^Tnotf2)*/
+    tmp_mdd2 = mdd_and(tmp_mdd,Tf2,1,1);
+    tmp_mdd1 = CovStates;
+    CovStates = mdd_or(CovStates,tmp_mdd2,1,1); /*add on the new states*/
+    mdd_free(tmp_mdd1);
+    mdd_free(tmp_mdd2);
+    tmp_mdd1 = mdd_and(tmp_mdd,Tnotf2,1,1); /*newSo^Tnotf2*/
+    tmp_mdd2 = temp2;
+    temp2 = mdd_and(tmp_mdd1,temp1,1,0); /*take out the startstates already encountered temp2 = newSo*/
+    mdd_free(tmp_mdd2);
+    mdd_free(tmp_mdd1);
+    tmp_mdd1 = temp1;
+    temp1 = mdd_or(temp1,tmp_mdd,1,1);
+    mdd_free(tmp_mdd1);
+    mdd_free(tmp_mdd);
+  }
+  mdd_free(zeroMDD);
+  mdd_free(oldSo);
+  mdd_free(Tf2);
+  mdd_free(Tnotf2);
+  mdd_free(temp1);
+  mdd_free(temp2);
+  return CovStates;
+
+} /* firstreached */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Duplicates a CTL formula but with a given signal's value
+  complemented]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+static Ctlp_Formula_t *
+FormulaConvertSignalComplement(
+  Fsm_Fsm_t *fsm,
+  char *signal,
+  Ctlp_Formula_t *formula)
+{
+  Ctlp_Formula_t *result = NIL(Ctlp_Formula_t);
+  Ctlp_Formula_t *leftChildConverted, *leftFormula;
+  Ctlp_Formula_t *rightChildConverted, *rightFormula;
+  Ntk_Network_t *network;
+  char *nodeNameString;
+  char *nodeValueString;
+  Ntk_Node_t *node;
+  Var_Variable_t *nodeVar;
+
+  if ( formula == NIL(Ctlp_Formula_t)) {
+	return NIL(Ctlp_Formula_t);
+  }
+
+  if (Ctlp_FormulaReadType(formula) != Ctlp_ID_c )  {
+    leftFormula = Ctlp_FormulaReadLeftChild(formula);
+    leftChildConverted = FormulaConvertSignalComplement(fsm, signal,
+							leftFormula);
+    rightFormula = Ctlp_FormulaReadRightChild(formula);
+    rightChildConverted = FormulaConvertSignalComplement(fsm, signal,
+							 rightFormula);
+    result = Ctlp_FormulaCreate(Ctlp_FormulaReadType(formula),
+				leftChildConverted,rightChildConverted);
+  }
+  else { /* if atomic proposition*/
+    network = Fsm_FsmReadNetwork(fsm);
+    nodeNameString = Ctlp_FormulaReadVariableName(formula);
+    nodeValueString = Ctlp_FormulaReadValueName(formula);
+    node = Ntk_NetworkFindNodeByName(network, nodeNameString);
+    nodeVar = Ntk_NodeReadVariable(node);
+    if ((strcmp(signal,nodeNameString)) != 0) { /* not the signal that we want to flip */
+      result = Ctlp_FormulaCreate(Ctlp_FormulaReadType(formula),
+				  (Ctlp_Formula_t *) util_strsav(nodeNameString),
+				  (Ctlp_Formula_t *) util_strsav(nodeValueString));
+    }
+    else { /* this is the signal that we want to flip */
+      result  = Ctlp_FormulaConverttoComplement(formula);
+    }
+  }
+  return result;
+} /* FormulaConvertSignalComplement */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Used in the coverage code to gather all possible observable
+               signals in a given formula and create necessary arrays]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+findallsignals(
+  Fsm_Fsm_t *fsm,
+  array_t *signalTypeList,
+  array_t *signalList,
+  array_t *statesCoveredList,
+  array_t *newCoveredStatesList,
+  array_t *statesToRemoveList,
+  Ctlp_Formula_t *formula,
+  mdd_t *zeroMdd)
+{
+  Ntk_Network_t *network;
+  Ntk_Node_t *node;
+  Var_Variable_t *nodeVar;
+  char *nodeNameString;
+  int signalType;
+  Ctlp_Formula_t *leftFormula, *rightFormula;
+  if ( formula == NIL(Ctlp_Formula_t)) {
+	return;
+  }
+
+  if (Ctlp_FormulaReadType(formula) != Ctlp_ID_c )  {
+    leftFormula = Ctlp_FormulaReadLeftChild(formula);
+    rightFormula = Ctlp_FormulaReadRightChild(formula);
+    findallsignals(fsm, signalTypeList, signalList, statesCoveredList,
+		   newCoveredStatesList, statesToRemoveList,
+		   leftFormula, zeroMdd);
+    findallsignals(fsm, signalTypeList, signalList, statesCoveredList,
+		   newCoveredStatesList, statesToRemoveList,
+		   rightFormula,zeroMdd);
+  }
+  else { /* atomic proposition */
+    nodeNameString = Ctlp_FormulaReadVariableName(formula);
+    if ((positionOfSignalinList(nodeNameString,signalList)) == -1) {
+      fprintf(vis_stdout,"Found new signal = %s\n",nodeNameString);
+      network = Fsm_FsmReadNetwork(fsm);
+      node = Ntk_NetworkFindNodeByName(network, nodeNameString);
+      nodeVar = Ntk_NodeReadVariable(node);
+      if (Var_VariableTestIsPI(nodeVar))
+	signalType = 1;
+      else if (Var_VariableTestIsPO(nodeVar))
+	signalType = 0;
+      else
+	signalType = 2;
+      array_insert_last(int,signalTypeList,signalType);
+      array_insert_last(char *,signalList,nodeNameString);
+      array_insert_last(mdd_t *,statesCoveredList,mdd_dup(zeroMdd));
+      array_insert_last(mdd_t *,newCoveredStatesList,mdd_dup(zeroMdd));
+      array_insert_last(mdd_t *,statesToRemoveList,mdd_dup(zeroMdd));
+    }
+  }
+  return;
+} /* findallsignals */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Used in the coverage code to gather all possible observable
+               signals in a given formula]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+findallsignalsInFormula(
+  array_t *signalList,
+  Ctlp_Formula_t *formula)
+{
+  char *nodeNameString;
+
+  Ctlp_Formula_t *leftFormula, *rightFormula;
+  if ( formula == NIL(Ctlp_Formula_t)) {
+    return;
+  }
+
+  if (Ctlp_FormulaReadType(formula) != Ctlp_ID_c )  {
+    leftFormula = Ctlp_FormulaReadLeftChild(formula);
+    rightFormula = Ctlp_FormulaReadRightChild(formula);
+    findallsignalsInFormula(signalList,leftFormula);
+    findallsignalsInFormula(signalList,rightFormula);
+  }
+  else { /* atomic proposition */
+    nodeNameString = Ctlp_FormulaReadVariableName(formula);
+    if ((positionOfSignalinList(nodeNameString,signalList)) == -1) {
+      array_insert_last(char *,signalList,nodeNameString); 
+    }
+  }
+  return;
+} /* findallsignalsInFormula */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Used in the coverage code to find the index of a signal in an
+               array of signals previously collected]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+positionOfSignalinList(
+  char *signal,
+  array_t *signalList)
+{
+  int arraysize = array_n(signalList);
+  int i;
+
+  for (i=0;i<arraysize;i++) {
+    if (strcmp(signal,array_fetch(char *,signalList,i)) == 0)
+      return i;
+  }
+  return -1;
+} /* positionOfSignalinList */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds the range of values that a given observed signal can take
+               in a CTL formula]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+RangeofSignalinFormula(
+  Fsm_Fsm_t *fsm,
+  char *signal,
+  Ctlp_Formula_t *formula)
+{
+  Ntk_Network_t *network;
+  char *nodeNameString;
+  char *nodeValueString;
+  Ntk_Node_t *node;
+  Ctlp_Formula_t *leftFormula;
+  Ctlp_Formula_t *rightFormula;
+ 
+  Var_Variable_t *nodeVar;
+  int range_left,range_right;
+  int range = 0;
+  /*nodeVar = Ntk_NodeReadVariable(node);*/
+  
+  if ( formula == NIL(Ctlp_Formula_t)) {
+    return range;
+  }
+
+  if (Ctlp_FormulaReadType(formula) != Ctlp_ID_c )  {
+    leftFormula = Ctlp_FormulaReadLeftChild(formula);
+    range_left = RangeofSignalinFormula(fsm, signal, leftFormula);
+#if 0
+    Ctlp_FormulaFree(leftFormula);
+#endif
+    rightFormula = Ctlp_FormulaReadRightChild (formula);
+    range_right = RangeofSignalinFormula(fsm, signal, rightFormula);
+#if 0
+    Ctlp_FormulaFree(rightFormula);
+#endif
+    if (range_left==range_right) /* to avoid situation where signal exists on both sides of formula*/
+      range = range_left;
+    else
+      range = range_right+range_left; /* 0 + some value */
+  }
+  else {
+    network = Fsm_FsmReadNetwork(fsm);
+    nodeNameString = Ctlp_FormulaReadVariableName(formula);
+    nodeValueString = Ctlp_FormulaReadValueName(formula);
+    node = Ntk_NetworkFindNodeByName(network, nodeNameString);
+    nodeVar = Ntk_NodeReadVariable(node);
+    if ((strcmp(signal,nodeNameString)) != 0) { 
+      range = 0;
+    }
+    else { 
+      range = Var_VariableReadNumValues(nodeVar);
+    }
+  }
+  return range;
+} /* RangeofSignalinFormula */
Index: vis_dev/vis-2.3/src/mc/mcDbg.c
===================================================================
--- vis_dev/vis-2.3/src/mc/mcDbg.c	(revision 14)
+++ vis_dev/vis-2.3/src/mc/mcDbg.c	(revision 14)
@@ -0,0 +1,1686 @@
+/**CFile***********************************************************************
+
+  FileName    [mcDbg.c]
+
+  PackageName [mc]
+
+  Synopsis    [Debugger for Fair CTL models]
+
+  Author      [Adnan Aziz, Tom Shiple, In-Ho Moon]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "mcInt.h"
+
+static char rcsid[] UNUSED = "$Id: mcDbg.c,v 1.43 2005/04/23 04:40:54 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void DebugID(McOptions_t *options, Ctlp_Formula_t *aFormula, mdd_t *aState, Fsm_Fsm_t *modelFsm);
+static void DebugTrueFalse(Ctlp_Formula_t *aFormula, mdd_t *aState, Fsm_Fsm_t *modelFsm);
+static void DebugBoolean(McOptions_t *options, Ctlp_Formula_t *aFormula, mdd_t *aState, Fsm_Fsm_t *modelFsm, array_t *careSetArray);
+static McPath_t * DebugEX(Ctlp_Formula_t *aFormula, mdd_t *aState, Fsm_Fsm_t *modelFsm, array_t *careSetArray);
+static McPath_t * DebugEU(Ctlp_Formula_t *aFormula, mdd_t *aState, Fsm_Fsm_t *modelFsm, array_t *careSetArray);
+static McPath_t * DebugEG(Ctlp_Formula_t *aFormula, mdd_t *aState, Fsm_Fsm_t *modelFsm, array_t *careSetArray, McOptions_t *options);
+static void FsmStateDebugConvertedFormula(McOptions_t *options, Ctlp_Formula_t *ctlFormula, mdd_t *aState, Fsm_Fsm_t *modelFsm, array_t *careSetArray);
+static void FsmPathDebugFormula(McOptions_t *options, Ctlp_Formula_t *ctlFormula, Fsm_Fsm_t *modelFsm, McPath_t *witnessPath, array_t *careSetArray);
+static void FsmPathDebugEXFormula(McOptions_t *options, Ctlp_Formula_t *ctlFormula, Fsm_Fsm_t *modelFsm, McPath_t *witnessPath, array_t *careSetArray);
+static void FsmPathDebugEUFormula(McOptions_t *options, Ctlp_Formula_t *ctlFormula, Fsm_Fsm_t *modelFsm, McPath_t *witnessPath, array_t *careSetArray);
+static void FsmPathDebugEGFormula(McOptions_t *options, Ctlp_Formula_t *ctlFormula, Fsm_Fsm_t *modelFsm, McPath_t *witnessPath, array_t *careSetArray);
+static void FsmPathDebugEFFormula(McOptions_t *options, Ctlp_Formula_t *ctlFormula, Fsm_Fsm_t *modelFsm, McPath_t *witnessPath, array_t *careSetArray);
+static void FsmPathDebugAXFormula(McOptions_t *options, Ctlp_Formula_t *ctlFormula, Fsm_Fsm_t *modelFsm, McPath_t *counterExamplePath, array_t *careSetArray);
+static void FsmPathDebugAFFormula(McOptions_t *options, Ctlp_Formula_t *ctlFormula, Fsm_Fsm_t *modelFsm, McPath_t *counterExamplePath, array_t *careSetArray);
+static void FsmPathDebugAGFormula(McOptions_t *options, Ctlp_Formula_t *ctlFormula, Fsm_Fsm_t *modelFsm, McPath_t *counterExamplePath, array_t *careSetArray);
+static void FsmPathDebugAUFormula(McOptions_t *options, mdd_t *aState, Ctlp_Formula_t *ctlFormula, Fsm_Fsm_t *modelFsm, array_t *careSetArray);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Debug CTL formula in existential normal form]
+
+  Description [Debug CTL formula in existential normal form. The extent to
+  which debug information is generated is a function of options settings.
+
+  The debugger works with ctlFormula, but uses the pointers back to
+  the original formula that it was converted from, to give the user
+  more sensible feedback.  To do this, it relies on a specific
+  translation: only EF, AU, AF, AG, and AX are converted.  Hence, the
+  only times that the converted bit is set, we have a conversion of
+  one of these formulas, and the operator is either EU, or negation.
+  in the latter case, we can conclude from the child of the negation
+  what formula we converted from: EX means AX, EG means AF, EU means AG,
+  and OR means AU.
+  ]
+
+  SideEffects [Affects vis_stdpipe]
+
+  SeeAlso     [Ctlp_FormulaConvertToExistentialForm]
+
+******************************************************************************/
+int
+McFsmDebugFormula(
+  McOptions_t *options,
+  Ctlp_Formula_t *ctlFormula,
+  Fsm_Fsm_t *modelFsm,
+  array_t *careSetArray)
+{
+  mdd_t *modelInitialStates = Fsm_FsmComputeInitialStates(modelFsm);
+  mdd_t *goodStates = Ctlp_FormulaObtainLatestApprox(ctlFormula);
+  mdd_t *badStates = mdd_and(modelInitialStates, goodStates, 1, 0);
+  mdd_t *witnessSuccState;
+  FILE *debugFile = McOptionsReadDebugFile(options);
+  FILE *oldStdOut;
+  FILE *oldStdErr;
+  extern FILE *vis_stdpipe;
+  char *nrOfTracesString;
+  int nrOfTraces;   /* nr of debug traces that we output */
+  int i;            /* counts debug traces               */
+
+  mdd_free(modelInitialStates);
+
+  oldStdOut = vis_stdout;
+  oldStdErr = vis_stderr;
+  
+  nrOfTracesString = Cmd_FlagReadByName("nr_counterexamples");
+  if(nrOfTracesString == NIL(char))
+    nrOfTraces = 1;
+  else
+    nrOfTraces = atoi(nrOfTracesString);
+  
+  if (debugFile) {
+    vis_stdpipe = debugFile;
+    vis_stdout = vis_stdpipe;
+   (void)fprintf(vis_stdpipe, "# MC: formula failed --- ");
+    Ctlp_FormulaPrint(vis_stdpipe,Ctlp_FormulaReadOriginalFormula(ctlFormula));
+    (void)fprintf(vis_stdpipe, "\n");
+  } else if (McOptionsReadUseMore(options)){
+    vis_stdpipe = popen("more", "w");
+    vis_stdout = vis_stdpipe;
+    vis_stderr = vis_stdpipe;
+  }
+  else
+    vis_stdpipe = vis_stdout;
+
+  for(i = 0; i < nrOfTraces; i++){
+    (void)fprintf(vis_stdout, "# MC: Calling debugger for trace %d\n",
+		  i+1);
+    witnessSuccState = McComputeACloseState(badStates, goodStates, modelFsm);
+    McFsmStateDebugFormula(options, ctlFormula, witnessSuccState, modelFsm,
+			   careSetArray);
+    (void)fprintf(vis_stdout, "\n");
+
+    mdd_free(witnessSuccState);
+  }
+  mdd_free(badStates);
+  mdd_free(goodStates);
+
+  if (vis_stdout != oldStdOut && vis_stdout != debugFile)
+    (void)pclose(vis_stdpipe);
+
+  vis_stdout = oldStdOut;
+  vis_stderr = oldStdErr;
+
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Debug CTL formula in existential normal form at state aState]
+
+  Description [Debug CTL formula in existential normal form at state
+  aState. Formula is assumed to have been CONVERTED to existential normal
+  form.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McFsmStateDebugFormula(
+  McOptions_t *options,
+  Ctlp_Formula_t *ctlFormula,
+  mdd_t *aState,
+  Fsm_Fsm_t *modelFsm,
+  array_t *careSetArray)
+{
+  Ctlp_Formula_t *originalFormula;
+  McDbgLevel debugLevel = McOptionsReadDbgLevel( options );
+
+  if ( ctlFormula == NIL(Ctlp_Formula_t) )
+    return;
+
+  if ( Ctlp_FormulaTestIsConverted( ctlFormula ) ) {
+    FsmStateDebugConvertedFormula(options, ctlFormula, aState, modelFsm,
+				  careSetArray);
+    return;
+  }
+
+  originalFormula = Ctlp_FormulaReadOriginalFormula( ctlFormula );
+
+  switch ( Ctlp_FormulaReadType( ctlFormula ) ) {
+
+    case Ctlp_ID_c :
+      DebugID( options, ctlFormula, aState, modelFsm );
+      break;
+
+    case Ctlp_TRUE_c:
+    case Ctlp_FALSE_c:
+      DebugTrueFalse( ctlFormula, aState, modelFsm );
+      break;
+
+    case Ctlp_EQ_c:
+    case Ctlp_XOR_c:
+    case Ctlp_THEN_c:
+    case Ctlp_NOT_c:
+    case Ctlp_AND_c:
+    case Ctlp_OR_c:
+      DebugBoolean(options, ctlFormula, aState, modelFsm, careSetArray);
+      break;
+
+    case Ctlp_EX_c:
+    case Ctlp_EU_c:
+    case Ctlp_EG_c:
+      if ( !McStateSatisfiesFormula( ctlFormula, aState ) ) {
+	mdd_t *passStates = Ctlp_FormulaObtainLatestApprox(ctlFormula);
+	mdd_t *closeState;
+	Ntk_Network_t *modelNetwork = Fsm_FsmReadNetwork(modelFsm);
+	array_t *PSVars = Fsm_FsmReadPresentStateVars(modelFsm);
+        McStateFailsFormula(aState, originalFormula, debugLevel, modelFsm);
+	if (mdd_is_tautology(passStates, 0)) {
+	  fprintf(vis_stdout,
+		  "--No state satisfies the formula\n");
+	  mdd_free(passStates);
+	  break;
+	}
+        fprintf(vis_stdout,
+		"--A simple counter example does not exist since it\n");
+        fprintf(vis_stdout,
+		"  requires generating all paths from the state\n");
+	fprintf(vis_stdout,
+		"--A state at minimum distance satisfying the formula is\n");
+	closeState = McComputeACloseState(passStates, aState, modelFsm);
+	mdd_free(passStates);
+	Mc_MintermPrint(closeState, PSVars, modelNetwork);
+	mdd_free(closeState);
+        break;
+      }
+      else {
+        McPath_t *witnessPath = NIL(McPath_t);
+        if ( Ctlp_FormulaReadType( ctlFormula ) == Ctlp_EX_c ) {
+          witnessPath = DebugEX(ctlFormula, aState, modelFsm, careSetArray);
+        }
+        else if  ( Ctlp_FormulaReadType( ctlFormula ) == Ctlp_EU_c ) {
+          witnessPath = DebugEU(ctlFormula, aState, modelFsm, careSetArray);
+        }
+        else {
+          witnessPath = DebugEG(ctlFormula, aState, modelFsm, careSetArray,
+				options);
+        }
+
+        FsmPathDebugFormula(options, ctlFormula, modelFsm, witnessPath,
+			    careSetArray);
+        McPathFree( witnessPath );
+      }
+      break;
+
+    case Ctlp_Cmp_c:
+    case Ctlp_Init_c:
+    case Ctlp_FwdU_c:
+    case Ctlp_FwdG_c:
+    case Ctlp_EY_c:
+    case Ctlp_EH_c:
+      break;
+
+    default: {
+      fail("Bad switch in debugging normal formula\n");
+    }
+  }
+}
+
+
+
+
+/**Function********************************************************************
+
+  Synopsis [Build fair path starting from aState, using given debug information.]
+
+  Description [Build fair path starting from aState, using given array of
+  onion rings.  Each member of this array of onion rings is an array of rings
+  of states leading to a fairness constraint. Function returns an McPath_t,
+  which consists of a stem array which is a sequence of states, and a path
+  array which is a sequence of states starting from the last state in stem
+  array, leading back to a state existing in stem array. In this sense, it is
+  confusing, since the "cycle" is not a true cycle (it just completes a
+  cycle).]
+
+  Comment [Proceed by building a path which passes through each fairness
+  constraint.  Then attempt to complete a cycle by seeing if a path can be
+  found from the last state to the first state satisfying the first fairness
+  constraint.]
+
+  SideEffects []
+
+******************************************************************************/
+McPath_t *
+McBuildFairPath(
+  mdd_t *startState,
+  mdd_t *invariantStates,
+  array_t *arrayOfOnionRings,
+  Fsm_Fsm_t *modelFsm,
+  array_t *careSetArray,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  Mc_FwdBwdAnalysis fwdBwd )
+{
+  mdd_t *tmpState;
+  mdd_t *lastState;
+  mdd_t *rootState = mdd_dup( startState );
+  mdd_t *currentState = mdd_dup( rootState );
+  mdd_t *stemState = NIL(mdd_t);
+
+  array_t *tmpStemArray;
+  array_t *dupArrayOfOnionRings = array_dup( arrayOfOnionRings );
+  array_t *stemArray = array_alloc(mdd_t *, 0 );
+  array_t *cycleArray = NIL(array_t);
+  McPath_t *fairPath;
+
+  array_insert_last( mdd_t *, stemArray, currentState );
+
+  while ( array_n( dupArrayOfOnionRings ) > 0 ) {
+    int index = McComputeOnionRingsWithClosestCore(currentState,
+			dupArrayOfOnionRings, modelFsm);
+    array_t *onionRingsWithClosestFairness = array_fetch(array_t *,
+			dupArrayOfOnionRings, index);
+    array_t *tmpArray = Mc_BuildPathToCore(currentState,
+				onionRingsWithClosestFairness,
+				modelFsm, McGreaterOrEqualZero_c);
+
+    if ( stemState == NIL(mdd_t) ) {
+      tmpState = array_fetch_last( mdd_t *, tmpArray );
+      stemState = mdd_dup( tmpState );
+    }
+
+    tmpStemArray = McCreateMergedPath( stemArray, tmpArray );
+    McNormalizeBddPointer(stemArray);
+    McNormalizeBddPointer(tmpArray);
+    mdd_array_free( stemArray );
+    mdd_array_free( tmpArray );
+    stemArray = tmpStemArray;
+
+    currentState = array_fetch_last( mdd_t *, stemArray );
+
+    tmpArray = McRemoveIndexedOnionRings( index, dupArrayOfOnionRings );
+    array_free( dupArrayOfOnionRings );
+    dupArrayOfOnionRings = tmpArray;
+  } /* while onionrings left */
+    array_free( dupArrayOfOnionRings );
+
+  tmpState = GET_NORMAL_PT(array_fetch_last( mdd_t *, stemArray ));
+  lastState = mdd_dup( tmpState );
+
+  cycleArray = Mc_CompletePath(lastState, stemState, invariantStates, modelFsm,
+                               careSetArray, verbosity, dcLevel, fwdBwd);
+
+  if ( cycleArray != NIL(array_t) ) {
+    mdd_free( lastState );
+  }
+  else {
+    McPath_t *tmpFairPath;
+    array_t *tmpStemArray;
+
+    /*
+     * Get shortest path to lastState
+     */
+    McNormalizeBddPointer(stemArray);
+    mdd_array_free( stemArray );
+    if ( !mdd_equal( rootState, lastState ) ) {
+      stemArray = Mc_CompletePath(rootState, lastState, invariantStates,
+				  modelFsm, careSetArray, verbosity, dcLevel,
+				  fwdBwd);
+    }
+    else {
+      stemArray = array_alloc( mdd_t *, 0 );
+      tmpState = mdd_dup( rootState );
+      array_insert_last( mdd_t *, stemArray, tmpState );
+    }
+    mdd_free( lastState );
+
+    tmpState = GET_NORMAL_PT(array_fetch_last( mdd_t *, stemArray ));
+    lastState = mdd_dup( tmpState );
+
+    if ( mdd_equal( lastState, rootState ) ) {
+      /*
+       * Force a descent in the SCC DAG
+      mdd_t *descendantState = McGetSuccessorInTarget(lastState,
+						invariantStates, modelFsm);
+       */
+      mdd_t *descendantState = McGetSuccessorInTargetAmongFairStates(lastState,
+						invariantStates, arrayOfOnionRings, modelFsm);
+      tmpFairPath = McBuildFairPath(descendantState, invariantStates,
+				    arrayOfOnionRings, modelFsm,
+                                    careSetArray,
+				    verbosity, dcLevel, fwdBwd);
+      tmpStemArray = McCreateJoinedPath(stemArray,
+					McPathReadStemArray(tmpFairPath));
+      mdd_free( descendantState );
+    }
+    else {
+      tmpFairPath = McBuildFairPath(lastState, invariantStates,
+				    arrayOfOnionRings, modelFsm,
+                                    careSetArray, 
+				    verbosity, dcLevel, fwdBwd);
+      tmpStemArray = McCreateMergedPath(stemArray,
+					McPathReadStemArray(tmpFairPath));
+    }
+    mdd_free( lastState );
+    McNormalizeBddPointer(stemArray);
+    mdd_array_free( stemArray );
+    stemArray = tmpStemArray;
+
+    cycleArray = McMddArrayDuplicateFAFW( McPathReadCycleArray( tmpFairPath ) );
+
+    McPathFree( tmpFairPath );
+
+    if(Fsm_FsmReadUniQuantifyInputCube(modelFsm)) {
+       mdd_t *S = GET_NORMAL_PT(array_fetch(mdd_t *, stemArray, 0));
+       mdd_t *T = GET_NORMAL_PT(array_fetch(mdd_t *, stemArray, array_n(stemArray)-1));
+       array_t *forwardRings = Mc_BuildForwardRingsWithInvariants(
+	       			S, T, invariantStates, modelFsm);
+       tmpStemArray = Mc_BuildPathFromCoreFAFW(
+  				T, forwardRings, modelFsm, McGreaterOrEqualZero_c);
+       McNormalizeBddPointer(stemArray);
+       mdd_array_free(stemArray);
+       mdd_array_free(forwardRings);
+       stemArray = tmpStemArray;
+    }
+  }
+
+  mdd_free( rootState );
+  mdd_free( stemState );
+
+  fairPath = McPathAlloc();
+  McPathSetStemArray( fairPath, stemArray );
+  McPathSetCycleArray( fairPath, cycleArray );
+
+  return fairPath;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Debug an Atomic Formula]
+
+  Description [Debug an Atomic Formula. As per the semantics of fair CTL, a
+  state satisfies an Atomic Formula just in case the given wire computes the
+  appropriate Boolean function on that state as input. The state has to be
+  fair; however we do NOT justify the fairness by printing a path to a fair
+  cycle.  THe user can achieve this effect by adding ANDing in a formula EG
+  TRUE.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+DebugID(
+  McOptions_t *options,
+  Ctlp_Formula_t *aFormula,
+  mdd_t *aState,
+  Fsm_Fsm_t *modelFsm)
+{
+  Ctlp_Formula_t *originalFormula = Ctlp_FormulaReadOriginalFormula(aFormula); 
+  McDbgLevel debugLevel = McOptionsReadDbgLevel( options );
+
+  if ( McStateSatisfiesFormula( aFormula, aState ) ) {
+    McStatePassesFormula( aState, originalFormula, debugLevel, modelFsm );
+  }
+  else {
+    McStateFailsFormula( aState, originalFormula, debugLevel, modelFsm );
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Debug a TRUE/FALSE formula]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+DebugTrueFalse(
+  Ctlp_Formula_t *aFormula,
+  mdd_t *aState,
+  Fsm_Fsm_t *modelFsm)
+{
+  fprintf(vis_stdout, "--Nothing to debug for %s\n",
+    ((Ctlp_FormulaReadType(aFormula) == Ctlp_TRUE_c) ? "TRUE\n" : "FALSE\n"));
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Debug a Boolean formula]
+
+  Desciption  [Debug a Boolean formula. For Boolean formula built out of binary
+  connective, we may debug only one branch, if say the formula is an AND and
+  the left branch is fails.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+DebugBoolean(
+  McOptions_t *options,
+  Ctlp_Formula_t *aFormula,
+  mdd_t *aState,
+  Fsm_Fsm_t *modelFsm,
+  array_t *careSetArray)
+{
+  Ctlp_Formula_t *originalFormula = Ctlp_FormulaReadOriginalFormula(aFormula);
+  Ctlp_Formula_t *lFormula = Ctlp_FormulaReadLeftChild( aFormula );
+  Ctlp_Formula_t *rFormula = Ctlp_FormulaReadRightChild( aFormula );
+  McDbgLevel debugLevel = McOptionsReadDbgLevel(options);
+
+  if (McStateSatisfiesFormula(aFormula, aState)) {
+    McStatePassesFormula(aState, originalFormula, debugLevel, modelFsm);
+  } else {
+    McStateFailsFormula(aState, originalFormula, debugLevel, modelFsm);
+  }
+
+  /* We always debug the first (left) child. */
+  McFsmStateDebugFormula(options, lFormula, aState, modelFsm, careSetArray);
+
+  /* What we do for the second child depends on the type of the formula.
+   * For Ctlp_AND_c, Ctlp_OR_c, Ctlp_THEN_c the right child may not be
+   * needed.  With early termination, the right child may not have the
+   * information required to produce a counterexample;  hence, its debugging
+   * is not optional.  (We may get incorrect answers.) 
+   */
+  if (Ctlp_FormulaReadType(aFormula) == Ctlp_AND_c) {
+    /* If aFormula fails and aState does not satisfy lFormula
+     * 1. The information about aState at the right child is not
+     *    necessarilty correct.  (aState was a don't care state.)
+     * 2. A counterexample to lFormula is a counterexample to
+     *    aFormula.
+     * So, if aFormula fails, we should debug the right child only if
+     * aState satisfies lFormula.
+     * If, on the other hand, aFormula passes, then aState must satisfy
+     * lFormula, and we need to witness both lFormula and rFormula.
+     */
+    if (McStateSatisfiesFormula(lFormula, aState)) {
+      McFsmStateDebugFormula(options, rFormula, aState, modelFsm,
+			     careSetArray);
+    }
+  } else if (Ctlp_FormulaReadType(aFormula) == Ctlp_OR_c) {
+    /* if aFormula passes, we should debug the right child only if
+     * aState does not satisfy lFormula.
+     * If, on the other hand, aFormula fails, then aState may not satisfy
+     * lFormula, and we need to produce counterexamples for both lFormula
+     * and rFormula.
+     */
+    if (!McStateSatisfiesFormula(lFormula, aState)) {
+      McFsmStateDebugFormula(options, rFormula, aState, modelFsm,
+			     careSetArray);
+    }
+  } else if (Ctlp_FormulaReadType(aFormula) == Ctlp_THEN_c) {
+    /* This case is like the OR, with the polarity of the left
+     * left child reversed.
+     */
+    if (McStateSatisfiesFormula(lFormula, aState)) {
+      McFsmStateDebugFormula(options, rFormula, aState, modelFsm,
+			     careSetArray);
+    }
+  } else if (Ctlp_FormulaReadType(aFormula) != Ctlp_NOT_c) {
+    /* For Ctlp_EQ_c and Ctlp_XOR_c both children must be debugged. */
+    McFsmStateDebugFormula(options, rFormula, aState, modelFsm, careSetArray);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Debug a formula of type EX.]
+
+  Description [Debug a formula of type EX at specified state. It is assumed
+  that aState satisfies the EX formula.]
+
+  SideEffects []
+
+******************************************************************************/
+static McPath_t *
+DebugEX(
+  Ctlp_Formula_t *aFormula,
+  mdd_t *aState,
+  Fsm_Fsm_t *modelFsm,
+  array_t *careSetArray)
+{
+  mdd_t *aDupState = mdd_dup( aState );
+  mdd_t *aStateSuccs;
+  mdd_t *statesSatisfyingLeftFormula;
+  mdd_t *targetStates;
+  mdd_t *witnessSuccState;
+  Ctlp_Formula_t *lFormula;
+  McPath_t *witnessPath = McPathAlloc();
+  array_t *stemArray = array_alloc( mdd_t *, 0 );
+  Img_ImageInfo_t * imageInfo = Fsm_FsmReadOrCreateImageInfo(modelFsm, 0, 1);
+
+  /*
+   * By using careSet here, can end up with unreachable successors
+   */
+  aStateSuccs = Img_ImageInfoComputeImageWithDomainVars(imageInfo,
+			aState, aState, careSetArray);
+
+  lFormula = Ctlp_FormulaReadLeftChild( aFormula );
+  statesSatisfyingLeftFormula = Ctlp_FormulaObtainLatestApprox( lFormula );
+
+  targetStates = mdd_and( aStateSuccs, statesSatisfyingLeftFormula, 1, 1 );
+  mdd_free( aStateSuccs ); mdd_free( statesSatisfyingLeftFormula );
+
+  witnessSuccState = Mc_ComputeACloseState( targetStates, aState, modelFsm );
+  mdd_free( targetStates );
+
+  array_insert_last( mdd_t *, stemArray, aDupState );
+  array_insert_last( mdd_t *, stemArray, witnessSuccState );
+
+  McPathSetStemArray( witnessPath, stemArray );
+
+  return witnessPath;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Debug a formula of type EU.]
+
+  Description [Debug a formula of type EU at specified state. It is assumed that
+  state fails formula.]
+
+  SideEffects []
+
+******************************************************************************/
+static McPath_t *
+DebugEU(
+  Ctlp_Formula_t *aFormula,
+  mdd_t *aState,
+  Fsm_Fsm_t *modelFsm,
+  array_t *careSetArray)
+{
+  McPath_t *witnessPath = McPathAlloc();
+  array_t *OnionRings = (array_t *) Ctlp_FormulaReadDebugData( aFormula );
+  array_t *pathToCore = Mc_BuildPathToCore(aState, OnionRings, 
+		     			   modelFsm,
+					   McGreaterOrEqualZero_c );
+
+  McPathSetStemArray( witnessPath, pathToCore );
+
+  return witnessPath;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Debug a formula of type EG.]
+
+  Description [Debug a formula of type EG at specified state. It is assumed
+  that state fails formula. Refer to Clarke et al DAC 1995 for details of the
+  algorithm.]
+
+  SideEffects []
+
+******************************************************************************/
+static McPath_t *
+DebugEG(
+  Ctlp_Formula_t *aFormula,
+  mdd_t *aState,
+  Fsm_Fsm_t *modelFsm,
+  array_t *careSetArray,
+  McOptions_t *options)
+{
+  array_t *arrayOfOnionRings = (array_t *) Ctlp_FormulaReadDebugData(aFormula);
+  mdd_t *invariantMdd = Ctlp_FormulaObtainLatestApprox( aFormula );
+  McPath_t *fairPath = McBuildFairPath(aState, invariantMdd, arrayOfOnionRings,
+					modelFsm, careSetArray,
+					McOptionsReadVerbosityLevel(options),
+					McOptionsReadDcLevel(options),
+					McOptionsReadFwdBwd(options));
+  mdd_free( invariantMdd );
+
+  return fairPath;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Debug a converted formula]
+
+  Comment [There are five kinds of formula that are converted: EF, AU, AF, AG,
+  AX.  The Ctlp_Formula_t structure has a pointer back to the original formula
+  (where one exists). For the non-trivial cases (AU, AF, AG, AX) if the
+  formula is false, we create a counter example, i.e. a fair path which fails
+  the property. The AG, AX, AF cases are simple; the AU case is tricky because
+  this can be failed on two ways.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+FsmStateDebugConvertedFormula(
+  McOptions_t *options,
+  Ctlp_Formula_t *ctlFormula,
+  mdd_t *aState,
+  Fsm_Fsm_t *modelFsm,
+  array_t *careSetArray)
+{
+  McPath_t *witnessPath;
+  McPath_t *counterExamplePath;
+
+  Ctlp_Formula_t *originalFormula =Ctlp_FormulaReadOriginalFormula(ctlFormula);
+  Ctlp_Formula_t *lFormula = Ctlp_FormulaReadLeftChild( ctlFormula );
+  McDbgLevel debugLevel = McOptionsReadDbgLevel( options );
+
+  if ( Ctlp_FormulaReadType( ctlFormula ) == Ctlp_EU_c ) {
+    if ( !McStateSatisfiesFormula( ctlFormula, aState ) ) {
+      mdd_t *passStates = Ctlp_FormulaObtainLatestApprox(ctlFormula);
+      mdd_t *closeState;
+      Ntk_Network_t *modelNetwork = Fsm_FsmReadNetwork(modelFsm);
+      array_t *PSVars = Fsm_FsmReadPresentStateVars(modelFsm);
+      McStateFailsFormula( aState, originalFormula, debugLevel, modelFsm );
+      if (mdd_is_tautology(passStates, 0)) {
+	  fprintf(vis_stdout,
+		  "--No state satisfies the formula\n");
+      } else {
+	fprintf(vis_stdout,
+		"\n--A simple counter example does not exist since it\n");
+	fprintf(vis_stdout,
+		"  requires generating all paths from the state\n");
+	fprintf(vis_stdout,
+		"--A state at minimum distance satisfying the formula is\n");
+	closeState = McComputeACloseState(passStates, aState, modelFsm);
+	Mc_MintermPrint(closeState, PSVars, modelNetwork);
+	mdd_free(closeState);
+      }
+      mdd_free(passStates);
+    }
+    else {
+      witnessPath = DebugEU(ctlFormula, aState, modelFsm, careSetArray);
+      FsmPathDebugEFFormula(options, ctlFormula, modelFsm, witnessPath,
+			    careSetArray);
+      McPathFree( witnessPath );
+    }
+    return;
+  }
+
+  /*
+   * The original formula must be an AX,AF,AG, or AU formula
+   */
+  if ( McStateSatisfiesFormula( ctlFormula, aState ) ) {
+    McStatePassesFormula( aState, originalFormula, debugLevel, modelFsm );
+    fprintf(vis_stdout,
+	    "--A simple witness does not exist since it requires\n");
+    fprintf(vis_stdout, "  generating all paths from the state\n");
+    return;
+  }
+
+  switch ( Ctlp_FormulaReadType( lFormula ) ) {
+    case Ctlp_EX_c: {
+      counterExamplePath = DebugEX(lFormula, aState, modelFsm, careSetArray);
+      FsmPathDebugAXFormula(options, ctlFormula, modelFsm, counterExamplePath,
+			    careSetArray);
+      McPathFree( counterExamplePath );
+      break;
+    }
+
+    case Ctlp_EG_c: {
+      counterExamplePath = DebugEG(lFormula, aState, modelFsm, careSetArray,
+				   options);
+      FsmPathDebugAFFormula(options, ctlFormula, modelFsm, counterExamplePath,
+			    careSetArray);
+      McPathFree( counterExamplePath );
+      break;
+    }
+
+    case Ctlp_EU_c: {
+      counterExamplePath = DebugEU(lFormula, aState, modelFsm, careSetArray);
+      FsmPathDebugAGFormula(options, ctlFormula, modelFsm, counterExamplePath,
+			    careSetArray);
+      McPathFree( counterExamplePath );
+      break;
+    }
+
+    case Ctlp_OR_c: {
+      /*
+       * need special functions bcoz of two possibilities
+       */
+      FsmPathDebugAUFormula(options, aState, ctlFormula, modelFsm,
+			    careSetArray);
+      break;
+    }
+
+    default: fail("Bad formula type in handling converted operator\n");
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Debug a formula of the form EX, EG, EU, EF.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+FsmPathDebugFormula(
+  McOptions_t *options,
+  Ctlp_Formula_t *ctlFormula,
+  Fsm_Fsm_t *modelFsm,
+  McPath_t *witnessPath,
+  array_t *careSetArray)
+{
+  switch ( Ctlp_FormulaReadType( ctlFormula ) ) {
+    case Ctlp_EX_c: {
+      FsmPathDebugEXFormula(options, ctlFormula, modelFsm, witnessPath,
+			    careSetArray);
+      break;
+    }
+
+    case Ctlp_EU_c: {
+      FsmPathDebugEUFormula(options, ctlFormula, modelFsm, witnessPath,
+			    careSetArray);
+      break;
+    }
+
+    case Ctlp_EG_c: {
+      FsmPathDebugEGFormula(options, ctlFormula, modelFsm, witnessPath,
+			    careSetArray);
+      break;
+    }
+    default: {
+      fail("bad switch in converting converted formula\n");
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis [Debug a path for EX type formula.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+FsmPathDebugEXFormula(
+  McOptions_t *options,
+  Ctlp_Formula_t *ctlFormula,
+  Fsm_Fsm_t *modelFsm,
+  McPath_t *witnessPath,
+  array_t *careSetArray)
+{
+  array_t *PSVars = Fsm_FsmReadPresentStateVars( modelFsm );
+  array_t *witnessArray = McPathReadStemArray( witnessPath );
+  mdd_t *firstState = array_fetch( mdd_t *, witnessArray, 0 );
+  char *firstStateName = Mc_MintermToString(firstState, PSVars,
+				Fsm_FsmReadNetwork(modelFsm));
+  Ctlp_Formula_t *lChild = Ctlp_FormulaReadLeftChild( ctlFormula );
+  char *ctlFormulaText = Ctlp_FormulaConvertToString( ctlFormula );
+  boolean printInputs = McOptionsReadPrintInputs( options );
+  mdd_t *secondlastState;
+  if(array_n(witnessArray)<2)
+    {
+      fprintf(vis_stdout,"witnessArray has less than two elements, return\n");
+      return;
+    }
+  secondlastState= array_fetch( mdd_t *, witnessArray, (array_n(witnessArray)-1) );
+
+  if( McOptionsReadDbgLevel( options ) == McDbgLevelMin_c)
+    fprintf(vis_stdout, "--State\n%spasses EX formula\n\n",
+	    firstStateName); 
+  else
+    fprintf(vis_stdout, "--State\n%spasses formula %s\n\n", firstStateName,
+	    ctlFormulaText );
+  
+  FREE(firstStateName);
+  FREE(ctlFormulaText);
+  
+  
+  switch ( McOptionsReadDbgLevel( options ) ) {
+  case McDbgLevelMin_c:
+  case McDbgLevelMinVerbose_c:
+  case McDbgLevelMax_c:
+    fprintf(vis_stdout, " --Counter example begins\n");
+    Mc_PrintPath( witnessArray, modelFsm, printInputs );
+    fprintf(vis_stdout, " --Counter example ends\n\n");
+    McFsmStateDebugFormula(options, lChild, secondlastState, modelFsm,
+			   careSetArray);
+    break;
+  case McDbgLevelInteractive_c:
+    fprintf(vis_stdout, " --Counter example begins\n");
+    Mc_PrintPath( witnessArray, modelFsm, printInputs );
+    fprintf(vis_stdout, " --Counter example ends\n\n");
+    if (McQueryContinue("Continue debugging EX formula? (1-yes,0-no)\n")) 
+    McFsmStateDebugFormula(options, lChild, secondlastState, modelFsm,
+			     careSetArray);
+    break;
+  default: 
+    fail("Reached bad switch in FsmPathDebugEXFormula\n");
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis [Debug a path for EU type formula.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+FsmPathDebugEUFormula(
+  McOptions_t *options,
+  Ctlp_Formula_t *ctlFormula,
+  Fsm_Fsm_t *modelFsm,
+  McPath_t *witnessPath,
+  array_t *careSetArray)
+{
+  char *ctlFormulaText = Ctlp_FormulaConvertToString( ctlFormula );
+  Ctlp_Formula_t *lFormula = Ctlp_FormulaReadLeftChild( ctlFormula );
+  Ctlp_Formula_t *rFormula = Ctlp_FormulaReadRightChild( ctlFormula );
+  char *lFormulaText = Ctlp_FormulaConvertToString( lFormula );
+  char *rFormulaText = Ctlp_FormulaConvertToString( rFormula );
+  array_t *PSVars = Fsm_FsmReadPresentStateVars( modelFsm );
+  array_t *witnessArray = McPathReadStemArray( witnessPath );
+  mdd_t *firstState = array_fetch( mdd_t *, witnessArray, 0 );
+  mdd_t *lastState = GET_NORMAL_PT(array_fetch_last( mdd_t *, witnessArray ));
+  char *firstStateName = Mc_MintermToString(firstState, PSVars,
+					    Fsm_FsmReadNetwork(modelFsm));
+  McDbgLevel debugLevel = McOptionsReadDbgLevel( options );
+  boolean printInputs = McOptionsReadPrintInputs( options );
+
+ if( McOptionsReadDbgLevel( options ) == McDbgLevelMin_c)
+   fprintf(vis_stdout, "--State\n%spasses EU formula\n\n",
+	   firstStateName); 
+ else
+   fprintf(vis_stdout, "--State\n%spasses formula %s\n\n", firstStateName,
+	   ctlFormulaText );
+
+ FREE(firstStateName);
+ FREE(ctlFormulaText);
+ 
+  switch ( debugLevel ) {
+  case McDbgLevelMin_c:
+  case McDbgLevelMinVerbose_c:
+      if ( array_n(witnessArray ) == 1 ) {
+	if( debugLevel != McDbgLevelMin_c )
+	  fprintf(vis_stdout, "since %s is true at this state", rFormulaText);
+        McFsmStateDebugFormula(options, rFormula, lastState, modelFsm,
+			       careSetArray);
+      }
+      else {
+      	if( debugLevel != McDbgLevelMin_c )
+	  fprintf(vis_stdout, "--Path on which %s is true till %s is true\n",
+		  lFormulaText, rFormulaText);
+	fprintf(vis_stdout, " --Counter example begins\n");
+        Mc_PrintPath(witnessArray, modelFsm, printInputs);
+	fprintf(vis_stdout, " --Counter example ends\n\n");
+        McFsmStateDebugFormula(options, rFormula, lastState, modelFsm,
+			       careSetArray);
+      }
+    break;
+  case McDbgLevelMax_c:
+  case McDbgLevelInteractive_c: 
+    if ( array_n(witnessArray ) == 1 ) {
+      fprintf(vis_stdout, "since %s is true at this state", rFormulaText);
+      McFsmStateDebugFormula(options, rFormula, lastState, modelFsm,
+			     careSetArray); 
+    }
+    else {
+      int i;
+      fprintf(vis_stdout, "--Path on which %s is true till %s is true\n",
+		  lFormulaText, rFormulaText);
+      fprintf(vis_stdout, " --Counter example begins\n");
+      Mc_PrintPath(witnessArray,modelFsm,printInputs);
+      fprintf(vis_stdout, " --Counter example ends\n\n");
+      for( i=0 ; i < ( array_n( witnessArray ) - 1 ); i++ ) {
+	mdd_t *aState = array_fetch( mdd_t *, witnessArray, i );
+      
+	if (debugLevel == McDbgLevelMax_c ||
+	    (debugLevel == McDbgLevelInteractive_c &&
+	     McQueryContinue(
+	       "Continue debugging EU formula? (1-yes,0-no)\n"))) {
+	  McFsmStateDebugFormula(options, lFormula, aState, modelFsm,
+				 careSetArray);
+	}
+    }
+      McFsmStateDebugFormula(options, rFormula, lastState, modelFsm,
+			     careSetArray);
+    }
+    break;
+  default: 
+    fail("Should not be here - bad switch in debugging EU formula\n");
+  }
+  FREE(lFormulaText);
+  FREE(rFormulaText);
+}
+/**Function********************************************************************
+
+  Synopsis [Debug a path for EG type formula.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+FsmPathDebugEGFormula(
+  McOptions_t *options,
+  Ctlp_Formula_t *ctlFormula,
+  Fsm_Fsm_t *modelFsm,
+  McPath_t *witnessPath,
+  array_t *careSetArray)
+{
+  mdd_t *firstState;
+  char *firstStateName;
+  array_t *witnessArray;
+  char *ctlFormulaText = Ctlp_FormulaConvertToString( ctlFormula );
+  array_t *PSVars = Fsm_FsmReadPresentStateVars( modelFsm );
+  array_t *stemArray = McPathReadStemArray( witnessPath );
+  array_t *cycleArray = McPathReadCycleArray( witnessPath );
+  Ctlp_Formula_t *lFormula = Ctlp_FormulaReadLeftChild( ctlFormula );
+  char *lFormulaText = Ctlp_FormulaConvertToString( lFormula );
+  McDbgLevel debugLevel = McOptionsReadDbgLevel( options );
+  boolean printInputs = McOptionsReadPrintInputs( options );
+
+  witnessArray = McCreateMergedPath( stemArray, cycleArray );
+  firstState = array_fetch( mdd_t *, witnessArray, 0 );
+  firstStateName = Mc_MintermToString(firstState, PSVars,Fsm_FsmReadNetwork(modelFsm));
+  
+  if( McOptionsReadDbgLevel( options ) == McDbgLevelMin_c)
+    fprintf(vis_stdout, "--State\n%spasses EG formula\n\n",
+	    firstStateName); 
+  else
+    fprintf(vis_stdout, "--State\n%spasses formula %s\n\n", firstStateName,
+	    ctlFormulaText );
+ 
+  FREE(firstStateName);
+  FREE(ctlFormulaText);
+
+  switch ( debugLevel ) {
+  case McDbgLevelMin_c:
+  case McDbgLevelMinVerbose_c: {
+    McPath_t *normalPath = McPathNormalize( witnessPath );
+    array_t *stem = McPathReadStemArray( normalPath );
+    array_t *cycle = McPathReadCycleArray( normalPath );
+
+    if(debugLevel != McDbgLevelMin_c)
+      fprintf(vis_stdout, "--Witness is a fair path where %s is always true\n",
+	      lFormulaText);
+    
+    FREE( lFormulaText );
+    fprintf(vis_stdout, " --Counter example begins\n");
+    (void) fprintf( vis_stdout, "--Fair path stem:\n");
+    Mc_PrintPath( stem, modelFsm, printInputs );
+    
+    (void) fprintf( vis_stdout, "--Fair path cycle:\n");
+    Mc_PrintPath( cycle, modelFsm, printInputs );
+    fprintf(vis_stdout, "\n");
+    fprintf(vis_stdout, " --Counter example ends\n\n");
+    McPathFree( normalPath );
+    break;
+  }
+  case McDbgLevelMax_c:
+  case McDbgLevelInteractive_c: {
+    McPath_t *normalPath = McPathNormalize( witnessPath );
+    array_t *stem = McPathReadStemArray( normalPath );
+    array_t *cycle = McPathReadCycleArray( normalPath );
+    int i;
+    fprintf(vis_stdout, "--Witness is a fair path where %s is always true\n",
+	      lFormulaText);
+    fprintf(vis_stdout, " --Counter example begins\n");
+    (void) fprintf( vis_stdout, "--Fair path stem:\n");
+    Mc_PrintPath( stem, modelFsm, printInputs );
+    (void) fprintf( vis_stdout, "--Fair path cycle:\n");
+    Mc_PrintPath( cycle, modelFsm, printInputs );
+    fprintf(vis_stdout, " --Counter example ends\n\n");
+    for( i=0 ; i < ( array_n( witnessArray )-1  ); i++ ) {
+      mdd_t *aState = array_fetch( mdd_t *, witnessArray, i );
+   
+      if (debugLevel == McDbgLevelMax_c ||
+	  (debugLevel == McDbgLevelInteractive_c &&
+	   McQueryContinue(
+	     "--Continue debugging EG formula? (1-yes,0-no)\n"))) {
+	McFsmStateDebugFormula(options, lFormula, aState, modelFsm,
+			       careSetArray);
+      }
+    }
+    break;
+  }
+  default:
+    fail("Bad switch in FsmPathDebugEGFormula\n");
+  }
+  McNormalizeBddPointer(witnessArray);
+  mdd_array_free( witnessArray );
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Debug a EF  formula]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+FsmPathDebugEFFormula(
+  McOptions_t *options,
+  Ctlp_Formula_t *ctlFormula,
+  Fsm_Fsm_t *modelFsm,
+  McPath_t *witnessPath,
+  array_t *careSetArray)
+{
+  Ctlp_Formula_t *originalFormula = Ctlp_FormulaReadOriginalFormula(ctlFormula);
+  char *originalFormulaText = Ctlp_FormulaConvertToString( originalFormula );
+
+  array_t *PSVars = Fsm_FsmReadPresentStateVars( modelFsm );
+  array_t *witnessArray = McPathReadStemArray( witnessPath );
+
+  mdd_t *firstState = array_fetch( mdd_t *, witnessArray, 0 );
+  mdd_t *lastState = array_fetch_last( mdd_t *, witnessArray );
+  char *firstStateName = Mc_MintermToString(firstState, PSVars,
+					Fsm_FsmReadNetwork(modelFsm));
+
+  Ctlp_Formula_t *rFormula = Ctlp_FormulaReadRightChild( ctlFormula );
+  Ctlp_Formula_t *rOriginalFormula = Ctlp_FormulaReadOriginalFormula(rFormula);
+  char *rOriginalFormulaText = Ctlp_FormulaConvertToString( rOriginalFormula );
+  char *rFormulaText = Ctlp_FormulaConvertToString( rFormula );
+  McDbgLevel debugLevel = McOptionsReadDbgLevel( options );
+  boolean printInputs = McOptionsReadPrintInputs( options );
+
+  if( McOptionsReadDbgLevel( options ) == McDbgLevelMin_c)
+    fprintf(vis_stdout, "--State\n%spasses EF formula\n\n",
+	    firstStateName); 
+  else
+    fprintf(vis_stdout, "--State\n%spasses formula %s\n\n", firstStateName,
+	  originalFormulaText );
+  
+  FREE(firstStateName);
+  FREE(originalFormulaText);
+
+  switch ( debugLevel ) {
+  case McDbgLevelMin_c:
+  case McDbgLevelMinVerbose_c:
+    if ( array_n(witnessArray ) == 1 ) {
+      if( debugLevel !=  McDbgLevelMin_c)
+	fprintf(vis_stdout, "since %s is true at this state\n",
+		rOriginalFormulaText);
+      
+      FREE( rOriginalFormulaText );
+      McFsmStateDebugFormula(options, rFormula, lastState, modelFsm,
+			     careSetArray);
+    }
+    else {
+      if( debugLevel !=  McDbgLevelMin_c)
+	fprintf(vis_stdout,
+		"--Witness is a path to a state where %s is finally true\n",
+		rOriginalFormulaText);
+      (void) fprintf( vis_stdout, "\n--Fair path stem:\n");
+      FREE( rOriginalFormulaText );
+      fprintf(vis_stdout, " --Counter example begins\n");
+      Mc_PrintPath( witnessArray, modelFsm, printInputs );
+      fprintf(vis_stdout, " --Counter example ends\n\n");
+    }
+    break;
+  case McDbgLevelMax_c:
+  case McDbgLevelInteractive_c:
+    if ( array_n(witnessArray ) == 1 ) {
+      McFsmStateDebugFormula(options, rFormula, lastState, modelFsm,
+			     careSetArray);
+    }
+    else
+      {
+	fprintf(vis_stdout,
+		"--Witness is a path to a state where %s is finally true\n",
+		rOriginalFormulaText);
+	fprintf(vis_stdout, " --Counter example begins\n");
+      Mc_PrintPath( witnessArray, modelFsm, printInputs);
+      fprintf(vis_stdout, " --Counter example ends\n\n");
+      if (debugLevel == McDbgLevelMax_c ||
+	  (debugLevel == McDbgLevelInteractive_c &&
+	   McQueryContinue(
+	     "--Continue debugging EF formula? (1-yes,0-no)\n")))
+	{
+	McFsmStateDebugFormula(options, rFormula, lastState, modelFsm,
+			       careSetArray);
+	}
+      }
+    break;
+  default:
+    fail("bad switch in debugging EF\n");
+  }
+  FREE(rFormulaText);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Debug a AX formula]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+FsmPathDebugAXFormula(
+  McOptions_t *options,
+  Ctlp_Formula_t *ctlFormula,
+  Fsm_Fsm_t *modelFsm,
+  McPath_t *counterExamplePath,
+  array_t *careSetArray)
+{
+  Ctlp_Formula_t *originalFormula = Ctlp_FormulaReadOriginalFormula(ctlFormula);
+  char *originalFormulaText = Ctlp_FormulaConvertToString( originalFormula );
+  Ctlp_Formula_t *lFormula = Ctlp_FormulaReadLeftChild( ctlFormula );
+  Ctlp_Formula_t *llFormula = Ctlp_FormulaReadLeftChild( lFormula );
+  Ctlp_Formula_t *lllFormula = Ctlp_FormulaReadLeftChild( llFormula );
+
+  array_t *PSVars = Fsm_FsmReadPresentStateVars( modelFsm );
+  array_t *witnessArray = McPathReadStemArray( counterExamplePath );
+  mdd_t *firstState = array_fetch( mdd_t *, witnessArray, 0 );
+  mdd_t *lastState = array_fetch( mdd_t *, witnessArray, 1 );
+  char *firstStateName = Mc_MintermToString(firstState, PSVars,
+					    Fsm_FsmReadNetwork(modelFsm));
+  boolean printInputs = McOptionsReadPrintInputs( options );
+
+  
+  if( McOptionsReadDbgLevel( options ) == McDbgLevelMin_c)
+    fprintf(vis_stdout, "--State\n%sfails AX formula\n\n",
+	    firstStateName); 
+  else
+      fprintf(vis_stdout, "--State\n%sfails %s\n\n", firstStateName,
+	  originalFormulaText );
+
+  FREE(firstStateName);
+  FREE(originalFormulaText);
+
+  switch ( McOptionsReadDbgLevel( options ) ) {
+  case McDbgLevelMin_c:
+  case McDbgLevelMinVerbose_c:
+  case McDbgLevelMax_c:
+    fprintf(vis_stdout, " --Counter example begins\n"); 
+    Mc_PrintPath( witnessArray, modelFsm, printInputs );
+    fprintf(vis_stdout, " --Counter example ends\n\n");
+    fprintf(vis_stdout, "\n");
+    McFsmStateDebugFormula(options, lllFormula, lastState, modelFsm,
+			   careSetArray);
+    break;
+  case McDbgLevelInteractive_c:
+    fprintf(vis_stdout, " --Counter example begins\n");
+    Mc_PrintPath( witnessArray, modelFsm, printInputs );
+    fprintf(vis_stdout, " --Counter example ends\n\n");
+    if ( McQueryContinue("Continue debugging EX formula? (1-yes,0-no)\n") ) {
+      McFsmStateDebugFormula(options, lllFormula, lastState, modelFsm,
+			     careSetArray);
+    }
+    break;
+  default: 
+    fail("Bad switch in FsmPathDebugAXFormula\n");
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Debug a AF formula]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+FsmPathDebugAFFormula(
+  McOptions_t *options,
+  Ctlp_Formula_t *ctlFormula,
+  Fsm_Fsm_t *modelFsm,
+  McPath_t *counterExamplePath,
+  array_t *careSetArray)
+{
+  Ctlp_Formula_t *originalFormula = Ctlp_FormulaReadOriginalFormula(ctlFormula);
+  char *originalFormulaText = Ctlp_FormulaConvertToString( originalFormula );
+  Ctlp_Formula_t *lFormula = Ctlp_FormulaReadLeftChild( ctlFormula );
+  Ctlp_Formula_t *llFormula = Ctlp_FormulaReadLeftChild( lFormula );
+  Ctlp_Formula_t *lllFormula = Ctlp_FormulaReadLeftChild( llFormula );
+  Ctlp_Formula_t *lllOriginalFormula = Ctlp_FormulaReadOriginalFormula(
+					lllFormula);
+  char *lllOriginalFormulaText = Ctlp_FormulaConvertToString(
+					lllOriginalFormula);
+
+  mdd_t *firstState;
+  array_t *witnessArray;
+  array_t *PSVars = Fsm_FsmReadPresentStateVars( modelFsm );
+  array_t *stemArray = McPathReadStemArray( counterExamplePath );
+  array_t *cycleArray = McPathReadCycleArray( counterExamplePath );
+  char *firstStateName;
+  McDbgLevel debugLevel = McOptionsReadDbgLevel( options );
+  boolean printInputs = McOptionsReadPrintInputs( options );
+
+  witnessArray = McCreateMergedPath( stemArray, cycleArray );
+  firstState = array_fetch( mdd_t *, witnessArray, 0 );
+  firstStateName = Mc_MintermToString(firstState, PSVars,
+					Fsm_FsmReadNetwork(modelFsm));
+
+  if( McOptionsReadDbgLevel( options ) == McDbgLevelMin_c)
+    fprintf(vis_stdout, "--State\n%sfails AF formula\n\n",
+	    firstStateName); 
+  else
+    fprintf(vis_stdout, "--State\n%sfails %s\n\n", firstStateName,
+	    originalFormulaText );
+  FREE(firstStateName);
+  FREE(originalFormulaText);
+
+  switch ( debugLevel ) {
+  case McDbgLevelMin_c:
+  case McDbgLevelMinVerbose_c: {
+    McPath_t *normalPath = McPathNormalize( counterExamplePath );
+    array_t *stem = McPathReadStemArray( normalPath );
+    array_t *cycle = McPathReadCycleArray( normalPath );
+    if( debugLevel !=  McDbgLevelMin_c)
+      fprintf(vis_stdout, "--A fair path on which %s is always false:\n",
+	      lllOriginalFormulaText );
+    
+    fprintf(vis_stdout, " --Counter example begins\n");
+    (void) fprintf( vis_stdout, "--Fair path stem:\n");
+    Mc_PrintPath( stem, modelFsm, printInputs );
+    
+    (void) fprintf( vis_stdout, "--Fair path cycle:\n");
+    Mc_PrintPath( cycle, modelFsm, printInputs );
+    fprintf(vis_stdout, "\n");
+    fprintf(vis_stdout, " --Counter example ends\n\n");
+    McPathFree( normalPath );
+    break;
+  }
+  case McDbgLevelMax_c:
+  case McDbgLevelInteractive_c: {
+    int i;
+    McPath_t *normalPath = McPathNormalize( counterExamplePath );
+    array_t *stem = McPathReadStemArray( normalPath );
+    array_t *cycle = McPathReadCycleArray( normalPath );
+    fprintf(vis_stdout, "--A fair path on which %s is always false:\n",
+	      lllOriginalFormulaText ); 
+    fprintf(vis_stdout, " --Counter example begins\n");
+    (void) fprintf( vis_stdout, "--Fair path stem:\n");
+    Mc_PrintPath( stem, modelFsm, printInputs );
+    
+    (void) fprintf( vis_stdout, "--Fair path cycle:\n");
+    Mc_PrintPath( cycle, modelFsm, printInputs );
+    fprintf(vis_stdout, "\n");
+    fprintf(vis_stdout, " --Counter example ends\n\n");
+    McPathFree( normalPath );
+    for( i=0 ; i < ( array_n( witnessArray )-1  ); i++ ) {
+      mdd_t *aState = array_fetch( mdd_t *, witnessArray, i );
+   
+      if (debugLevel == McDbgLevelMax_c ||
+	  (debugLevel == McDbgLevelInteractive_c &&
+	   McQueryContinue(
+	     "--Continue debugging AF formula? (1-yes,0-no)\n"))) {
+	McFsmStateDebugFormula(options, lllFormula, aState, modelFsm,
+			       careSetArray);
+      }
+    }
+
+    break;
+  }
+  default: {
+    fail("Bad case in switch for debugging AF formula\n");
+  }
+  }
+  McNormalizeBddPointer(witnessArray);
+  mdd_array_free( witnessArray );
+  FREE(lllOriginalFormulaText);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Debug an AG formula.]
+  
+  Description [Debugs an AG formula.  What it really wants is a formula of the
+  form !EF! phi, that was converted from the formula AG phi, with all the
+  converted pointers set as required: the top ! points to the original AG
+  formula, and top node of phi points to the original phi.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+FsmPathDebugAGFormula(
+  McOptions_t *options,
+  Ctlp_Formula_t *ctlFormula,
+  Fsm_Fsm_t *modelFsm,
+  McPath_t *counterExamplePath,
+  array_t *careSetArray)
+{
+  Ctlp_Formula_t *originalFormula = Ctlp_FormulaReadOriginalFormula(ctlFormula);
+  char *originalFormulaText = Ctlp_FormulaConvertToString( originalFormula );
+  Ctlp_Formula_t *lFormula = Ctlp_FormulaReadLeftChild( ctlFormula );
+  Ctlp_Formula_t *lrFormula = Ctlp_FormulaReadRightChild( lFormula );
+  Ctlp_Formula_t *lrlFormula = Ctlp_FormulaReadLeftChild( lrFormula );
+  Ctlp_Formula_t *lrlOriginalFormula = Ctlp_FormulaReadOriginalFormula(
+					lrlFormula);
+  char *lrlOriginalFormulaText = Ctlp_FormulaConvertToString(
+					lrlOriginalFormula);
+
+  array_t *PSVars = Fsm_FsmReadPresentStateVars( modelFsm );
+  array_t *witnessArray = McPathReadStemArray( counterExamplePath );
+  mdd_t *firstState = array_fetch( mdd_t *, witnessArray, 0 );
+  mdd_t *lastState = GET_NORMAL_PT(array_fetch_last( mdd_t *, witnessArray ));
+  char *firstStateName = Mc_MintermToString(firstState, PSVars,
+					    Fsm_FsmReadNetwork(modelFsm));
+  McDbgLevel debugLevel = McOptionsReadDbgLevel( options );
+  boolean printInputs = McOptionsReadPrintInputs( options );
+
+  assert( Ctlp_FormulaReadType(ctlFormula) == Ctlp_NOT_c );
+  assert( Ctlp_FormulaTestIsConverted(ctlFormula) );
+  assert( Ctlp_FormulaReadType(originalFormula) == Ctlp_AG_c );
+  assert( originalFormulaText != NIL(char) );
+  assert( Ctlp_FormulaReadType(lFormula) == Ctlp_EU_c );
+  assert( Ctlp_FormulaReadType(Ctlp_FormulaReadLeftChild(lFormula)) ==
+	  Ctlp_TRUE_c );
+  assert( Ctlp_FormulaReadType(lrFormula) == Ctlp_NOT_c  );
+  assert( lrlOriginalFormula != NIL(Ctlp_Formula_t) );
+  
+  if( McOptionsReadDbgLevel( options ) == McDbgLevelMin_c)
+    fprintf(vis_stdout, "--State\n%sfails AG formula\n\n",
+	    firstStateName); 
+  else
+    fprintf(vis_stdout, "--State\n%sfails %s\n\n", firstStateName,
+	    originalFormulaText );
+  FREE(firstStateName);
+  FREE(originalFormulaText);
+
+  switch ( debugLevel ) {
+  case McDbgLevelMin_c:
+  case McDbgLevelMinVerbose_c:{
+    if ( array_n(witnessArray ) == 1 ) {
+      if( debugLevel !=  McDbgLevelMin_c)
+	fprintf(vis_stdout, "since %s is false at this state\n",
+		lrlOriginalFormulaText );
+      McFsmStateDebugFormula(options, lrlFormula, lastState, modelFsm,
+			     careSetArray);
+    }
+    else {
+      if( debugLevel !=  McDbgLevelMin_c)
+	fprintf(vis_stdout,
+		"--Counter example is a path to a state where %s is false\n",
+		lrlOriginalFormulaText);
+      fprintf(vis_stdout, " --Counter example begins\n");
+      Mc_PrintPath(witnessArray, modelFsm, printInputs);
+      fprintf(vis_stdout, " --Counter example ends\n\n");
+      McFsmStateDebugFormula(options, lrlFormula, lastState, modelFsm,
+			     careSetArray);
+    }
+    break;
+  }
+  case McDbgLevelMax_c:
+  case McDbgLevelInteractive_c: {
+    if ( array_n(witnessArray ) == 1 ) {
+      if( debugLevel !=  McDbgLevelMin_c)
+	fprintf(vis_stdout, "since %s is false at this state\n",
+		lrlOriginalFormulaText );
+      McFsmStateDebugFormula(options, lrlFormula, lastState, modelFsm,
+			     careSetArray);
+    }
+    else {
+      fprintf(vis_stdout,
+		"--Counter example is a path to a state where %s is false\n",
+		lrlOriginalFormulaText);
+      fprintf(vis_stdout, " --Counter example begins\n");
+      Mc_PrintPath( witnessArray, modelFsm, printInputs);
+      fprintf(vis_stdout, " --Counter example ends\n\n");
+      if (debugLevel == McDbgLevelMax_c ||
+	  (debugLevel == McDbgLevelInteractive_c &&
+	   McQueryContinue(
+	     "--Continue debugging AG formula? (1-yes,0-no)\n")))
+	{
+	McFsmStateDebugFormula(options, lrlFormula, lastState, modelFsm,
+			       careSetArray);
+	}
+      }
+    break;
+  }
+  default: {
+    fail("bad switch in debugging AG\n");
+  }
+  }
+  FREE(lrlOriginalFormulaText);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Debug a AU formula]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+FsmPathDebugAUFormula(
+  McOptions_t *options,
+  mdd_t *aState,
+  Ctlp_Formula_t *ctlFormula,
+  Fsm_Fsm_t *modelFsm,
+  array_t *careSetArray)
+{
+  Ctlp_Formula_t *originalFormula = Ctlp_FormulaReadOriginalFormula(ctlFormula);
+  char *originalFormulaText = Ctlp_FormulaConvertToString( originalFormula );
+  Ctlp_Formula_t *lFormula = Ctlp_FormulaReadLeftChild( ctlFormula );
+  Ctlp_Formula_t *lrFormula = Ctlp_FormulaReadRightChild( lFormula );
+  Ctlp_Formula_t *lrlFormula = Ctlp_FormulaReadLeftChild( lrFormula );
+  Ctlp_Formula_t *lrllFormula = Ctlp_FormulaReadLeftChild( lrlFormula );
+  Ctlp_Formula_t *llFormula = Ctlp_FormulaReadLeftChild( lFormula );
+  Ctlp_Formula_t *llrFormula = Ctlp_FormulaReadRightChild( llFormula );
+  Ctlp_Formula_t *llrlFormula = Ctlp_FormulaReadLeftChild( llrFormula );
+  Ctlp_Formula_t *llrllFormula = Ctlp_FormulaReadLeftChild( llrlFormula );
+  Ctlp_Formula_t *fFormula = llrllFormula;
+  Ctlp_Formula_t *gFormula = lrllFormula;
+  Ctlp_Formula_t *fOriginalFormula = Ctlp_FormulaReadOriginalFormula(fFormula);
+  Ctlp_Formula_t *gOriginalFormula = Ctlp_FormulaReadOriginalFormula(gFormula);
+  char *fText = Ctlp_FormulaConvertToString( fOriginalFormula );
+  char *gText = Ctlp_FormulaConvertToString( gOriginalFormula );
+
+  array_t *PSVars = Fsm_FsmReadPresentStateVars( modelFsm );
+  char *firstStateName = Mc_MintermToString(aState, PSVars,
+					Fsm_FsmReadNetwork(modelFsm));
+  McDbgLevel debugLevel = McOptionsReadDbgLevel( options );
+  boolean printInputs = McOptionsReadPrintInputs( options );
+
+  if( McOptionsReadDbgLevel( options ) == McDbgLevelMin_c)
+    fprintf(vis_stdout, "--State\n%sfails AU formula\n\n",
+	    firstStateName); 
+  else
+    fprintf(vis_stdout, "--State\n%sfails %s\n\n", firstStateName,
+	    originalFormulaText );
+  FREE(firstStateName);
+  FREE(originalFormulaText);
+
+  /* orginal formula is A(fUg) => converted is !((E[!g U (!f*!g)]) + (EG!g)) */
+
+  if ( McStateSatisfiesFormula( llFormula, aState ) ) {
+    /*
+     * the case E[!g U (!f*!g)] is true
+     */
+    McPath_t *counterExamplePath = DebugEU(llFormula, aState, modelFsm,
+					   careSetArray);
+    
+    array_t *stemArray = McPathReadStemArray( counterExamplePath );
+    array_t *witnessArray = stemArray;
+    mdd_t *firstState = array_fetch( mdd_t *, witnessArray, 0 );
+    mdd_t *lastState = array_fetch_last( mdd_t *, witnessArray );
+    char *firstStateName = Mc_MintermToString(firstState, PSVars,
+				Fsm_FsmReadNetwork(modelFsm));
+
+    switch ( debugLevel ) {
+    case McDbgLevelMinVerbose_c: 
+      fprintf(vis_stdout,
+	      "--Counter example is a fair path where %s is false until %s is also false\n",
+	      gText, fText);
+    case McDbgLevelMin_c:
+      fprintf(vis_stdout, " --Counter example begins\n");
+      Mc_PrintPath(witnessArray, modelFsm, printInputs);
+      fprintf(vis_stdout, " --Counter example ends\n\n");
+      McFsmStateDebugFormula(options, llrFormula, lastState, modelFsm,
+			     careSetArray);
+      break;
+        
+    case McDbgLevelMax_c:
+    case McDbgLevelInteractive_c: {
+      if ( array_n(witnessArray ) == 1 ) {
+	fprintf(vis_stdout,
+		"--At state %s\nformula %s is false and\nformula %s is also false\n",
+		firstStateName, fText, gText);
+	if (debugLevel == McDbgLevelMax_c ||
+	    (debugLevel == McDbgLevelInteractive_c &&
+	     McQueryContinue(
+	       "Continue debugging AU formula? (1-yes,0-no)\n"))) {
+	  McFsmStateDebugFormula(options, fFormula, aState, modelFsm,
+				 careSetArray);
+	  McFsmStateDebugFormula(options, gFormula, aState, modelFsm,
+				 careSetArray);
+	}
+      }
+      else {
+	int i;
+	fprintf(vis_stdout, " --Counter example begins\n");
+	Mc_PrintPath(witnessArray,modelFsm,printInputs);
+	fprintf(vis_stdout, " --Counter example ends\n\n");
+	for( i=0 ; i < ( array_n( witnessArray ) - 1 ); i++ ) {
+	  mdd_t *aState = array_fetch( mdd_t *, witnessArray, i );
+	  
+	  if (debugLevel == McDbgLevelMax_c ||
+	      (debugLevel == McDbgLevelInteractive_c &&
+	       McQueryContinue(
+		 "Continue debugging AU formula? (1-yes,0-no)\n"))) {
+	    McFsmStateDebugFormula(options, gFormula, aState, modelFsm,
+				   careSetArray);
+	  }
+	}
+	
+	if (debugLevel == McDbgLevelMax_c ||
+	    (debugLevel == McDbgLevelInteractive_c &&
+	     McQueryContinue(
+	       "Continue debugging AU formula? (1-yes,0-no)\n"))) {
+	  McFsmStateDebugFormula(options, fFormula, lastState, modelFsm,
+				 careSetArray);
+	  McFsmStateDebugFormula(options, gFormula, lastState, modelFsm,
+				 careSetArray);
+	}
+      }
+      break;
+    }
+    
+    default: {
+      fail("Unknown case in debugging AU\n");
+    }
+    }/* case */
+    McPathFree( counterExamplePath );
+  }
+  else {
+    /*
+     * must be the case that EG!g
+     */
+    McPath_t *counterExamplePath = DebugEG(lrFormula, aState, modelFsm,
+					   careSetArray, 
+					   options);
+
+    assert( McStateSatisfiesFormula( lrFormula, aState ) );
+
+    if( debugLevel !=  McDbgLevelMin_c)
+      fprintf(vis_stdout,
+	      "--Counter example is a fair path where %s is always false\n",
+	      gText);
+
+    switch ( debugLevel ) {
+    case McDbgLevelMin_c:
+    case McDbgLevelMinVerbose_c:{
+      McPath_t *normalPath = McPathNormalize( counterExamplePath );
+      array_t *stem = McPathReadStemArray( normalPath );
+      array_t *cycle = McPathReadCycleArray( normalPath );
+      
+      fprintf(vis_stdout, " --Counter example begins\n");
+      (void) fprintf( vis_stdout, "--Fair path stem:\n");
+      Mc_PrintPath( stem, modelFsm, printInputs );
+      
+      (void) fprintf( vis_stdout, "--Fair path cycle:\n");
+      Mc_PrintPath( cycle, modelFsm, printInputs );
+      fprintf(vis_stdout, " --Counter example ends\n\n");
+      McPathFree( normalPath );
+      break;
+    }
+    
+    case McDbgLevelMax_c:
+    case McDbgLevelInteractive_c:
+      {
+    int i;
+    array_t *stemArray = McPathReadStemArray( counterExamplePath );
+    array_t *cycleArray = McPathReadCycleArray( counterExamplePath );
+    array_t *witnessArray = McCreateMergedPath( stemArray, cycleArray );
+    McPath_t *normalPath = McPathNormalize( counterExamplePath );
+    array_t *stem = McPathReadStemArray( normalPath );
+    array_t *cycle = McPathReadCycleArray( normalPath );
+    
+    fprintf(vis_stdout, " --Counter example begins\n");
+    (void) fprintf( vis_stdout, "--Fair path stem:\n");
+    Mc_PrintPath( stem, modelFsm, printInputs );
+    
+    (void) fprintf( vis_stdout, "--Fair path cycle:\n");
+    Mc_PrintPath( cycle, modelFsm, printInputs );
+    fprintf(vis_stdout, " --Counter example ends\n\n");
+    McPathFree( normalPath );
+    for( i=0 ; i < ( array_n( witnessArray )-1  ); i++ ) {
+      mdd_t *aState = array_fetch( mdd_t *, witnessArray, i );
+   
+      if (debugLevel == McDbgLevelMax_c ||
+	  (debugLevel == McDbgLevelInteractive_c &&
+	   McQueryContinue(
+	     "--Continue debugging AU formula? (1-yes,0-no)\n"))) {
+	McFsmStateDebugFormula(options, lrllFormula, aState, modelFsm,
+			       careSetArray);
+      }
+    }
+    break;
+  }
+
+    default: {
+      fail("Bad switch in debugging AU formula\n");
+    }
+    }/* case */
+    McPathFree( counterExamplePath );
+  }
+  
+  FREE( fText );
+  FREE( gText );
+}
Index: vis_dev/vis-2.3/src/mc/mcDnC.c
===================================================================
--- vis_dev/vis-2.3/src/mc/mcDnC.c	(revision 14)
+++ vis_dev/vis-2.3/src/mc/mcDnC.c	(revision 14)
@@ -0,0 +1,1059 @@
+/**CFile***********************************************************************
+
+  FileName    [mcDnC.c]
+
+  PackageName [mc]
+
+  Synopsis    [The Divide and Compose (D'n'C) Approach of SCC Enumeration.]
+
+  Description [This file contains the functions to compute the fair
+  Strongly Connected Components (SCCs) of the state translation graph
+  of an FSM by Divide and Compose.  Knowledge of the fair SCCs can be
+  used to decide language emptiness.  For more information, please
+  check the CONCUR'01 paper of Wang et al., "Divide and Compose: SCC
+  refinement for language emptiness." Other applications are also
+  possible.]
+
+  SeeAlso     []
+
+  Author      [Chao Wang]
+
+  Copyright   [Copyright (c) 2004 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without
+  license or royalty fees, to use, copy, modify, and distribute this
+  software and its documentation for any purpose, provided that the
+  above copyright notice and the following two paragraphs appear in
+  all copies of this software.]
+
+******************************************************************************/
+#include "mcInt.h"
+
+static char rcsid[] UNUSED = "$Id: mcDnC.c,v 1.9 2005/05/18 18:12:00 jinh Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+static int SccIsStrong(mdd_manager *mddMgr, array_t *buechiFairness, mdd_t *SCC);
+static array_t * SortMddArrayBySize(Fsm_Fsm_t *fsm, array_t *mddArray);
+static int stringCompare(const void * s1, const void * s2);
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Compute all the states that lead to a fair cycle by
+  Compositional SCC analysis (DnC -- Divide and Compose).]
+
+  Comment [Used by LE/LTL/CTL* model checking. The Divide and Compose
+  (D'n'C) approach is used for the symbolic SCC enumeration, which
+  first creates SCC-closed sets on an abstract model and then
+  successively refines these sets on the refined abstract models,
+  until either no fair SCC exists or the concrete (original) model is
+  reached.
+
+  Strength reduction is also applied during the process -- as soon as
+  the SCC-closed sets become weak/terminal, special decision
+  procedures will be used to determine their language emptiness.
+
+  For more information, please check the CONCUR'01 paper of Wang et
+  al., "Divide and Compose: SCC refinement for language emptiness."
+  
+  Debugging information will be print out if dbgLevel is non-zero.
+
+  Return the set of initial states from where fair paths exist.]
+  
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Mc_FsmCheckLanguageEmptinessByDnC(
+  Fsm_Fsm_t *modelFsm,
+  array_t *modelCareStates,
+  Mc_AutStrength_t automatonStrength,
+  int dcLevel,
+  int dbgLevel,
+  int printInputs,
+  int verbosity,
+  Mc_GSHScheduleType GSHschedule,
+  Mc_FwdBwdAnalysis GSHdirection,
+  int lockstep,
+  FILE *dbgFile,
+  int UseMore,
+  int SimValue,
+  char *driverName)
+{
+  Ntk_Network_t   *network = Fsm_FsmReadNetwork(modelFsm);
+  mdd_manager     *mddManager = Fsm_FsmReadMddManager(modelFsm);
+  Fsm_Fairness_t  *modelFairness = NIL(Fsm_Fairness_t);
+  array_t         *buechiFairness = NIL(array_t);
+  int             isExactReachableStatesAvailable = 0;
+  mdd_t           *reachableStates, *initialStates = NIL(mdd_t);
+  mdd_t           *fairStates, *fairInitialStates = NIL(mdd_t);
+  array_t         *onionRings = NIL(array_t);
+  array_t         *strongSccClosedSets = NIL(array_t);
+  array_t         *absLatchNameTableArray = NIL(array_t);
+  int             numOfAbstractModels, iter, i, exitFlag;
+  array_t         *arrayOfOnionRings = NIL(array_t);
+  array_t         *ctlArray = array_alloc(Ctlp_Formula_t *, 0);
+  array_t         *modelCareStatesArray = mdd_array_duplicate(modelCareStates);
+  Mc_SccGen_t     *sccgen;
+  int             composeIncSize, numOfLatches, maxLatchesToCompose;
+
+  int             maxComposePercentage = 30;
+  int             maxSccsToEnum = 100;
+
+
+  /*
+   * Read fairness constraints.
+   */
+  modelFairness = Fsm_FsmReadFairnessConstraint(modelFsm);
+  buechiFairness = array_alloc(mdd_t *, 0);
+  if (modelFairness != NIL(Fsm_Fairness_t)) {
+    if (!Fsm_FairnessTestIsBuchi(modelFairness)) {
+      (void) fprintf(vis_stdout, 
+		     "** non-Buechi fairness constraints not supported\n");
+      array_free(buechiFairness);
+      assert(0);
+    } else {
+      int j;
+      int numBuchi = Fsm_FairnessReadNumConjunctsOfDisjunct(modelFairness, 0);
+      for (j = 0; j < numBuchi; j++) {
+	Ctlp_Formula_t *tmpFormula;
+	mdd_t *tempMdd;
+	tmpFormula = Fsm_FairnessReadFinallyInfFormula(modelFairness, 0, j );
+	tempMdd = Fsm_FairnessObtainFinallyInfMdd(modelFairness, 0, j,
+						  modelCareStatesArray, 
+						  (Mc_DcLevel) dcLevel);
+	array_insert_last(mdd_t *, buechiFairness, tempMdd);
+        array_insert_last( Ctlp_Formula_t *, ctlArray, 
+			   Ctlp_FormulaDup(tmpFormula));
+#if 1
+	fprintf(vis_stdout,"\nFairness[%d]:",j);
+	Ctlp_FormulaPrint(vis_stdout, tmpFormula);
+	fprintf(vis_stdout,"\n");
+#endif
+      }
+    }
+  } else {
+    array_insert_last(mdd_t *, buechiFairness, mdd_one(mddManager));
+  }
+
+  /*
+   * If we need debugging information, arrayOfOnionRings != NIL(array_t), 
+   */
+  if (dbgLevel != McDbgLevelNone_c)
+    arrayOfOnionRings = array_alloc(array_t *, 0);
+  else
+    arrayOfOnionRings = NIL(array_t);
+
+  /* 
+   * If exact/approximate reachable states are available, use them.
+   */
+  initialStates = Fsm_FsmComputeInitialStates(modelFsm);
+  reachableStates = Fsm_FsmReadReachableStates(modelFsm);
+  isExactReachableStatesAvailable = (reachableStates != NIL(mdd_t));
+  if (!isExactReachableStatesAvailable) 
+    reachableStates = McMddArrayAnd(modelCareStatesArray);
+  else
+    reachableStates = mdd_dup(reachableStates);
+  onionRings = Fsm_FsmReadReachabilityOnionRings(modelFsm);
+  if (onionRings == NIL(array_t)) {
+    onionRings = array_alloc(mdd_t *, 0);
+    array_insert(mdd_t *, onionRings, 0, mdd_dup(reachableStates));
+  }else
+    onionRings = mdd_array_duplicate(onionRings);
+
+  strongSccClosedSets = array_alloc(mdd_t *, 0);
+  array_insert(mdd_t *, strongSccClosedSets, 0, mdd_dup(reachableStates));
+
+  /*
+   * Compute a series of over-approximated abstract models
+   */
+  numOfLatches = array_n(Fsm_FsmReadPresentStateVars(modelFsm));
+  maxLatchesToCompose = (numOfLatches * maxComposePercentage/100);
+  maxLatchesToCompose = (maxLatchesToCompose > 20)? maxLatchesToCompose:20;
+  composeIncSize = maxLatchesToCompose/10;
+  composeIncSize = (composeIncSize > 4)? composeIncSize:4;
+
+  absLatchNameTableArray = 
+    Mc_CreateStaticRefinementScheduleArray(network,
+					   ctlArray,
+					   NIL(array_t),
+					   NIL(array_t),
+					   FALSE,
+					   FALSE,
+					   ((verbosity<McVerbosityMax_c)?
+					    0:McVerbositySome_c),
+					   composeIncSize,
+					   Part_CorrelationWithSupport);
+  numOfAbstractModels = (array_n(absLatchNameTableArray) - 1);
+  if (verbosity >= McVerbosityLittle_c) {
+    fprintf(vis_stdout, 
+	    "-- DnC: scheduled total %d abs models with %d latches\n",
+	    numOfAbstractModels, numOfLatches);
+  }
+
+  if (verbosity >= McVerbositySome_c) {
+    fprintf(vis_stdout, "-- DnC:\n");
+    fprintf(vis_stdout, 
+	    "-- DnC: maxComposePercentage = %d\n", maxComposePercentage);
+    fprintf(vis_stdout, 
+	    "-- DnC: numOfLatches         = %d\n", numOfLatches);
+    fprintf(vis_stdout, 
+	    "-- DnC: composeIncSize       = %d\n", composeIncSize);
+    fprintf(vis_stdout, 
+	    "-- DnC: numOfAbstractModels  = %d\n", numOfAbstractModels);
+    fprintf(vis_stdout, 
+	    "-- DnC: maxLatchesToCompose  = %d\n", maxLatchesToCompose);
+    fprintf(vis_stdout, 
+	    "-- DnC: maxSccsToEnum        = %d\n", maxSccsToEnum);
+    fprintf(vis_stdout, "-- Dnc: \n");
+  }
+
+  exitFlag = 0;
+  for (iter=0; iter<numOfAbstractModels; iter++) {
+    Fsm_Fsm_t *absFsm = NIL(Fsm_Fsm_t);
+    st_table  *absLatchNameTable = NIL(st_table);
+    array_t   *absOnionRings;
+    array_t   *tempArray = NIL(array_t);
+    mdd_t     *sccClosedSet = NIL(mdd_t);
+    mdd_t     *tempMdd = NIL(mdd_t);
+    mdd_t     *absReachableStates = NIL(mdd_t);
+
+    absLatchNameTable = array_fetch(st_table *, absLatchNameTableArray, iter);
+    absFsm = Fsm_FsmCreateSubsystemFromNetwork(network, NIL(graph_t),
+					       absLatchNameTable, TRUE, 1);
+
+    if (!isExactReachableStatesAvailable) {
+      absReachableStates = Fsm_FsmComputeReachableStates(absFsm, 0, 0, 0, 0,
+							 1, 0, 0,
+							 Fsm_Rch_Default_c, 
+							 0, 0,
+							 NIL(array_t), FALSE,
+							 NIL(array_t));
+      absOnionRings = Fsm_FsmReadReachabilityOnionRings(absFsm);
+      assert(absOnionRings);
+      absOnionRings = mdd_array_duplicate(absOnionRings);
+    }else {
+      absReachableStates = McComputeAbstractStates(absFsm, reachableStates);
+      absOnionRings = array_alloc(mdd_t *, array_n(onionRings));
+      arrayForEachItem(mdd_t *, onionRings, i, tempMdd) {
+	array_insert(mdd_t *, absOnionRings, i, 
+		     McComputeAbstractStates(absFsm, tempMdd) );
+      }
+    }
+
+    tempArray = strongSccClosedSets;
+    strongSccClosedSets = array_alloc(mdd_t *, 0);
+    arrayForEachItem(mdd_t *, tempArray, i, sccClosedSet) {
+      sccClosedSet = (iter == 0)? 
+	McComputeAbstractStates(absFsm, sccClosedSet): mdd_dup(sccClosedSet);
+      tempMdd = mdd_and(sccClosedSet, absReachableStates, 1, 1);
+      if (mdd_is_tautology(tempMdd, 0)) 
+	mdd_free(tempMdd);
+      else
+	array_insert_last(mdd_t *, strongSccClosedSets, tempMdd);
+      mdd_free(sccClosedSet);
+    }
+    mdd_array_free(tempArray);
+
+    /* Refine SCC-closed sets, but up to a certain number */
+    tempArray = strongSccClosedSets;
+    strongSccClosedSets = array_alloc(mdd_t *, 0);
+    Mc_FsmForEachFairScc(absFsm, sccgen, sccClosedSet, tempArray, 
+			 strongSccClosedSets, /* new scc-closed sets */
+			 buechiFairness, absOnionRings, FALSE,
+			 ((verbosity<McVerbosityMax_c)?
+			  McVerbosityNone_c:McVerbositySome_c),
+			 (Mc_DcLevel) dcLevel) {
+      if (SccIsStrong(mddManager, buechiFairness, sccClosedSet)) {
+	array_insert_last(mdd_t *, strongSccClosedSets, sccClosedSet);
+	if (maxSccsToEnum>0 && array_n(strongSccClosedSets)>maxSccsToEnum) {
+	  Mc_FsmSccGenFree(sccgen, strongSccClosedSets);
+	  break;
+	}
+
+      }else {
+	array_t  *newCareStatesArray;
+	newCareStatesArray = mdd_array_duplicate(modelCareStatesArray);
+	if (!isExactReachableStatesAvailable) 
+	  array_insert_last(mdd_t *, newCareStatesArray, absReachableStates);
+
+	if (verbosity >= McVerbositySome_c) 
+	  fprintf(vis_stdout, "-- DnC: search in a weak SCC-closed set\n");
+
+	fairStates = McFsmRefineWeakFairSCCs(modelFsm, sccClosedSet, 
+					     newCareStatesArray, 
+					     arrayOfOnionRings, FALSE, 
+					     dcLevel, 
+                         ((verbosity<McVerbosityMax_c)? 0:McVerbositySome_c) );
+	fairInitialStates = mdd_and(initialStates, fairStates, 1, 1);
+	mdd_free(fairStates);
+	if (!mdd_is_tautology(fairInitialStates, 0)) { 
+	  /* Done, find a reachable fair cycle */
+	  exitFlag = 2;  
+	  if (verbosity >= McVerbosityLittle_c) 
+	    fprintf(vis_stdout, "-- DnC: find a weak SCC!\n");
+	  Mc_FsmSccGenFree(sccgen, NIL(array_t));
+	  break;
+	}else {
+	  mdd_free(fairInitialStates); 
+	}
+      }
+
+    }/*Mc_FsmForEachFairScc( ) {*/ 
+    mdd_array_free(tempArray);
+
+    SortMddArrayBySize(absFsm, strongSccClosedSets);
+	  
+    if (verbosity >= McVerbosityLittle_c && exitFlag != 2) {
+      fprintf(vis_stdout, 
+	      "-- DnC: found %d SCC-closed sets in abs model %d with %d latches\n",
+	      array_n(strongSccClosedSets), iter+1, 
+	      st_count(absLatchNameTable));
+      if (verbosity >= McVerbositySome_c) {
+	array_t *absPSvars = Fsm_FsmReadPresentStateVars(absFsm);
+	array_t *PSvars = Fsm_FsmReadPresentStateVars(modelFsm);
+	arrayForEachItem(mdd_t *, strongSccClosedSets, i, tempMdd) {
+	  fprintf(vis_stdout, "-- An SCC-closed set with %5g abs (%5g concrete) states\n",
+		  mdd_count_onset(mddManager, tempMdd, absPSvars),
+		  mdd_count_onset(mddManager, tempMdd, PSvars)
+		  );
+	}
+      }
+    }
+
+    if(exitFlag == 0 && array_n(strongSccClosedSets) == 0) {
+      /* Done, no reachable fair cycle exists */
+      exitFlag = 1; 
+    }
+
+    mdd_array_free(absOnionRings);
+    Fsm_FsmFree(absFsm);
+
+    /* existFlag: 0 --> unknown;  1 --> no fair SCC; 2 --> find a fair SCC */
+    if ( exitFlag != 0 || st_count(absLatchNameTable) > maxLatchesToCompose ) {
+      if (!isExactReachableStatesAvailable) {
+	array_insert_last(mdd_t *, modelCareStatesArray, absReachableStates);
+	tempMdd = reachableStates;
+	reachableStates = mdd_and(reachableStates, absReachableStates,1,1);
+	mdd_free(tempMdd);
+      }
+      break;
+    }
+
+    mdd_free(absReachableStates);
+	
+  }/*for (iter=0; iter<numOfAbstractModels; iter++) {*/
+
+  for (i=0; i<array_n(absLatchNameTableArray); i++) {
+    st_free_table( array_fetch(st_table *, absLatchNameTableArray, i) );
+  }
+  array_free(absLatchNameTableArray);
+
+
+  /*
+   * Compute fair SCCs on the concrete model if necessary
+   */
+  if (exitFlag == 0) {
+    array_t *tempArray;
+    mdd_t   *sccClosedSet = NIL(mdd_t);
+    mdd_t   *tempMdd = NIL(mdd_t);
+
+    if (verbosity >= McVerbosityLittle_c) 
+      fprintf(vis_stdout, "-- DnC: check the concrete model\n");
+
+    tempArray = strongSccClosedSets;
+    strongSccClosedSets = array_alloc(mdd_t *, 0);
+    arrayForEachItem(mdd_t *, tempArray, i, sccClosedSet) {
+      tempMdd = mdd_and(sccClosedSet, reachableStates, 1, 1);
+      if (mdd_is_tautology(tempMdd, 0)) 
+	mdd_free(tempMdd);
+      else
+	array_insert_last(mdd_t *, strongSccClosedSets, tempMdd);
+      mdd_free(sccClosedSet);
+    }
+    array_free(tempArray);
+
+    if (lockstep != MC_LOCKSTEP_OFF) {
+      tempArray = array_alloc(mdd_t *, 0);
+      fairStates = McFsmRefineFairSCCsByLockStep(modelFsm, lockstep,
+						 tempArray, 
+						 strongSccClosedSets,
+						 NIL(array_t),
+						 arrayOfOnionRings,
+						 (Mc_VerbosityLevel) verbosity,
+						 (Mc_DcLevel) dcLevel);
+      mdd_array_free(tempArray);
+    }else{
+      mdd_t   *fairStates0, *sccClosedSet;
+      array_t *EUonionRings;
+      mdd_t   *mddOne = mdd_one(mddManager);
+      Mc_EarlyTermination_t *earlyTermination;
+
+      sccClosedSet = McMddArrayOr(strongSccClosedSets);
+      fairStates0 = Mc_FsmEvaluateEGFormula(modelFsm, sccClosedSet,
+					    NIL(mdd_t), mddOne,
+					    modelFairness,
+					    modelCareStatesArray,
+					    MC_NO_EARLY_TERMINATION,
+					    NIL(array_t),
+					    Mc_None_c, 
+					    &arrayOfOnionRings,
+					    (Mc_VerbosityLevel) verbosity,
+					    (Mc_DcLevel) dcLevel,
+					    NIL(boolean),
+					    GSHschedule);
+      mdd_free(sccClosedSet);
+
+      EUonionRings = ( (arrayOfOnionRings == NIL(array_t))? 
+		       NIL(array_t):array_alloc(mdd_t *,0) );
+
+      earlyTermination = Mc_EarlyTerminationAlloc(McSome_c, initialStates);
+      fairStates = Mc_FsmEvaluateEUFormula(modelFsm, mddOne,
+					   fairStates0, NIL(mdd_t), mddOne,
+					   modelCareStatesArray,
+					   earlyTermination,
+					   NIL(array_t), Mc_None_c,
+					   EUonionRings,
+					   (Mc_VerbosityLevel) verbosity,
+					   (Mc_DcLevel) dcLevel,
+					   NIL(boolean));
+      mdd_free(fairStates0);
+      mdd_free(mddOne);
+      Mc_EarlyTerminationFree(earlyTermination);
+
+      if (arrayOfOnionRings != NIL(array_t)) {
+	int j;
+	arrayForEachItem(array_t *, arrayOfOnionRings, i, tempArray) {
+#ifndef NDEBUG
+	  mdd_t *mdd1 = array_fetch_last(mdd_t *, tempArray);
+#endif
+	  arrayForEachItem(mdd_t *, EUonionRings, j, tempMdd) {
+	    if (j != 0) 
+	      array_insert_last(mdd_t *, tempArray, mdd_dup(tempMdd));
+	    else    
+	      assert( mdd_equal(tempMdd, mdd1) );
+	  }
+	}
+	mdd_array_free(EUonionRings);
+      }
+    }
+
+    fairInitialStates = mdd_and(initialStates, fairStates, 1, 1);
+    mdd_free(fairStates);
+    exitFlag = mdd_is_tautology(fairInitialStates, 0)? 1:2;
+  }
+  
+  /* Clean-Ups */
+  mdd_array_free(modelCareStatesArray);
+  mdd_array_free(strongSccClosedSets);
+  mdd_array_free(onionRings);
+  mdd_free(reachableStates);
+  mdd_free(initialStates);
+
+  /*
+   * Print out the verification result (pass/fail, empty/non-empty)
+   */
+  if (exitFlag == 1) {
+    if (strcmp(driverName, "LE") == 0)
+      fprintf(vis_stdout, "# LE: language emptiness check passes\n");
+    else
+      fprintf(vis_stdout, "# %s: formula passed\n", driverName);
+    if (arrayOfOnionRings != NIL(array_t))
+      mdd_array_array_free(arrayOfOnionRings);
+    return fairInitialStates;
+
+  }else if (exitFlag == 2) {
+    if (strcmp(driverName, "LE") == 0)
+      fprintf(vis_stdout, "# LE: language is not empty\n");
+    else
+      fprintf(vis_stdout, "# %s: formula failed\n", driverName);
+ 
+  }else {
+    fprintf(vis_stderr, "* DnC error, result is unknown!\n");
+    assert(0);
+  }
+
+  /*
+   * Print out the debugging information if requested
+   */
+  if (dbgLevel == McDbgLevelNone_c) {
+    if (arrayOfOnionRings != NIL(array_t)) 
+      mdd_array_array_free(arrayOfOnionRings);
+    return fairInitialStates;
+
+  }else {
+    mdd_t    *badStates, *aBadState, *mddOne;
+    McPath_t *fairPath, *normalPath;
+    array_t  *stemArray, *cycleArray;
+    FILE     *tmpFile = vis_stdout;
+    extern  FILE *vis_stdpipe;
+    fprintf(vis_stdout, "# %s: generating path to fair cycle\n", driverName);
+
+    /* Generate witness. */
+    badStates = mdd_dup(fairInitialStates);
+    aBadState = Mc_ComputeAState(badStates, modelFsm);
+    mdd_free(badStates);
+    
+    mddOne = mdd_one(mddManager);
+    fairPath = McBuildFairPath(aBadState, mddOne, arrayOfOnionRings, modelFsm,
+			       modelCareStates, 
+			       (Mc_VerbosityLevel) verbosity,
+			       (Mc_DcLevel) dcLevel,
+			       McFwd_c);
+    mdd_free(mddOne);
+    mdd_free(aBadState);
+    mdd_array_array_free(arrayOfOnionRings);
+    
+    /* Print witness. */
+    normalPath = McPathNormalize(fairPath);
+    McPathFree(fairPath);
+    
+    stemArray = McPathReadStemArray(normalPath);
+    cycleArray = McPathReadCycleArray(normalPath);
+    
+    /* we should pass dbgFile/UseMore as parameters 
+       dbgFile = McOptionsReadDebugFile(options);*/
+    if (dbgFile != NIL(FILE)) {
+      vis_stdpipe = dbgFile;
+    } else if (UseMore == TRUE) {
+      vis_stdpipe = popen("more","w");
+    } else {
+      vis_stdpipe = vis_stdout;
+    }
+    vis_stdout = vis_stdpipe;
+    
+    /* We should also pass SimValue as a parameter */
+    if (SimValue == FALSE) {
+      (void) fprintf(vis_stdout, "# %s: path to fair cycle:\n\n", driverName);
+      Mc_PrintPath(stemArray, modelFsm, printInputs);
+      fprintf (vis_stdout, "\n");
+      
+      (void) fprintf(vis_stdout, "# %s: fair cycle:\n\n", driverName);
+      Mc_PrintPath(cycleArray, modelFsm, printInputs);
+      fprintf (vis_stdout, "\n");
+    }else {
+      array_t *completePath = McCreateMergedPath(stemArray, cycleArray);
+      (void) fprintf(vis_stdout, "# %s: counter-example\n", driverName);
+      McPrintSimPath(vis_stdout, completePath, modelFsm);
+      mdd_array_free(completePath);
+    }
+
+    if (dbgFile == NIL(FILE) && UseMore == TRUE) {
+      (void) pclose(vis_stdpipe);
+    }  
+    vis_stdout = tmpFile;
+    
+    McPathFree(normalPath);
+  }
+
+  return fairInitialStates;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [Create a refinement schedule array.] 
+
+  Description [If dynamicIncrease is true, the first element of return
+  array includes varibales appeared in formula. The size of the first
+  element should be less than or equal to incrementalSize. The second
+  element includes all variables in formula's cone of influence. When
+  dynamicIncrease is false, all variables in formula's cone of
+  influence (let's say n variables) are partitioned into
+  ceil(n/incrementalSize) elements. Then one more element which
+  includes all n variables are added to return array.]
+
+  SideEffects        []
+
+  SeeAlso            [Part_SubsystemInfo_t]
+
+******************************************************************************/
+array_t	*
+Mc_CreateStaticRefinementScheduleArray(
+  Ntk_Network_t         *network,
+  array_t               *ctlArray,
+  array_t               *ltlArray,
+  array_t               *fairArray,
+  boolean               dynamicIncrease,
+  boolean               isLatchNameSort,
+  int                   verbosity,
+  int                   incrementalSize,
+  Part_CMethod          correlationMethod)
+{
+  array_t		*partitionArray;
+  Part_Subsystem_t	*partitionSubsystem;
+  Part_SubsystemInfo_t  *subsystemInfo; 
+  st_table	        *latchNameTable;
+  st_table	        *latchNameTableSum, *latchNameTableSumCopy;
+  char		        *flagValue;
+  st_generator          *stGen;
+  char                  *name;
+  double		affinityFactor;
+  array_t               *scheduleArray;
+  boolean               dynamicAndDependency = isLatchNameSort;
+  array_t               *tempArray, *tempArray2;
+  int                   i, count;
+
+  /* affinity factor to decompose state space */
+  flagValue = Cmd_FlagReadByName("part_group_affinity_factor");
+  if(flagValue != NIL(char)){
+    affinityFactor = atof(flagValue); 
+  }
+  else{
+    /* default value */
+    affinityFactor = 0.5; 
+  }
+
+  /* 
+   * Obtain submachines as array: The first sub-system includes
+   * variables in CTL/LTL/fair formulas and other latches are grouped
+   * in the same way as Part_PartCreateSubsystems()
+   */
+  subsystemInfo = Part_PartitionSubsystemInfoInit(network);
+  Part_PartitionSubsystemInfoSetBound(subsystemInfo, incrementalSize);
+  Part_PartitionSubsystemInfoSetVerbosity(subsystemInfo, verbosity);
+  Part_PartitionSubsystemInfoSetCorrelationMethod(subsystemInfo,
+    correlationMethod); 
+  Part_PartitionSubsystemInfoSetAffinityFactor(subsystemInfo, affinityFactor);
+  partitionArray = Part_PartCreateSubsystemsWithCtlAndLtl(subsystemInfo,
+                   ctlArray, ltlArray, fairArray, 
+		   dynamicIncrease,dynamicAndDependency,FALSE);
+  Part_PartitionSubsystemInfoFree(subsystemInfo);
+
+  scheduleArray = array_alloc(st_table *, 0);
+
+
+  /* 
+   * For each partitioned submachines build an FSM. 
+   */
+  latchNameTableSum = st_init_table(strcmp, st_strhash);
+  if (!dynamicAndDependency){
+    for (i=0;i<array_n(partitionArray);i++){
+      partitionSubsystem = array_fetch(Part_Subsystem_t *, partitionArray, i);
+      if (partitionSubsystem != NIL(Part_Subsystem_t)) {
+        latchNameTable = Part_PartitionSubsystemReadVertexTable(partitionSubsystem);
+        st_foreach_item(latchNameTable, stGen, &name, NIL(char *)) {
+          if (!st_lookup(latchNameTableSum, name, NIL(char *))){ 
+            st_insert(latchNameTableSum, name, NIL(char));
+          }
+        }
+        Part_PartitionSubsystemFree(partitionSubsystem);
+      } 
+      latchNameTableSumCopy = st_copy(latchNameTableSum);
+      array_insert_last(st_table *, scheduleArray, latchNameTableSumCopy);
+    }
+  }else{
+    partitionSubsystem = array_fetch(Part_Subsystem_t *, partitionArray, 0);
+    latchNameTable = Part_PartitionSubsystemReadVertexTable(partitionSubsystem);
+    st_foreach_item(latchNameTable, stGen, &name, NIL(char *)) {
+      st_insert(latchNameTableSum, name, NIL(char));
+    }
+    latchNameTableSumCopy = st_copy(latchNameTableSum);
+    array_insert_last(st_table *, scheduleArray, latchNameTableSumCopy);
+    Part_PartitionSubsystemFree(partitionSubsystem);
+    
+    partitionSubsystem = array_fetch(Part_Subsystem_t *, partitionArray, 1);
+    tempArray = array_alloc(char *, 0);    
+    if (partitionSubsystem != NIL(Part_Subsystem_t)){
+      latchNameTable = Part_PartitionSubsystemReadVertexTable(partitionSubsystem);
+      st_foreach_item(latchNameTable, stGen, &name, NIL(char *)) {
+        array_insert_last(char *, tempArray, name);
+      }
+      array_sort(tempArray, stringCompare);
+      Part_PartitionSubsystemFree(partitionSubsystem);
+    }
+    
+    partitionSubsystem = array_fetch(Part_Subsystem_t *, partitionArray, 2);
+    tempArray2 = array_alloc(char *, 0);
+    if (partitionSubsystem != NIL(Part_Subsystem_t)) {
+      latchNameTable = Part_PartitionSubsystemReadVertexTable(partitionSubsystem);
+      st_foreach_item(latchNameTable, stGen, &name, NIL(char *)) {
+        array_insert_last(char *, tempArray2, name);
+      }
+      array_sort(tempArray2, stringCompare);
+      Part_PartitionSubsystemFree(partitionSubsystem);
+    }
+
+    array_append(tempArray, tempArray2);
+    array_free(tempArray2);
+    
+    count = 0;
+    arrayForEachItem(char *, tempArray, i, name){   
+      if (!st_lookup(latchNameTableSum, name, NIL(char *))){ 
+        st_insert(latchNameTableSum, (char *)name, (char *)0);
+        count++;
+      }
+      if ((count == incrementalSize) && (i < array_n(tempArray)-1)){
+        latchNameTableSumCopy = st_copy(latchNameTableSum);
+        array_insert_last(st_table *, scheduleArray, latchNameTableSumCopy);
+        count = 0;
+      }
+    }
+    array_free(tempArray);
+    latchNameTableSumCopy = st_copy(latchNameTableSum);
+    array_insert_last(st_table *, scheduleArray, latchNameTableSumCopy);
+  }
+  
+  array_free(partitionArray);
+  st_free_table(latchNameTableSum);
+  
+  return (scheduleArray);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+    
+/**Function********************************************************************
+
+  Synopsis [Compute the fair SCCs within the given weak SCC-closed
+  set.]
+
+  Description [Used by the Divide and Compose (D'n'C) approach for
+  language emptiness checking. Because it's a weak SCC-closed set,
+  fair states can be computed through the evaluation of EF EG
+  (sccClosedSet). 
+  
+  Debugging information will be returned if arrayOfOnionRings is not NIL.
+
+  Return the fair states leading to a fair cycle within the given
+  SCC-closed set.]
+  
+  SideEffects [arrayOfOnionRings will be changed if it is not NIL and
+  the initial states intersect the fair states.]
+
+******************************************************************************/
+mdd_t *
+McFsmRefineWeakFairSCCs(
+  Fsm_Fsm_t *modelFsm, 
+  mdd_t *sccClosedSet, 
+  array_t *modelCareStatesArray, 
+  array_t *arrayOfOnionRings,
+  boolean isSccTerminal,
+  int dcLevel, 
+  int verbosity) 
+{
+  mdd_manager *mddManager = Fsm_FsmReadMddManager(modelFsm);
+  mdd_t *initialStates;
+  mdd_t *mddOne, *mddEgFair, *mddEfEgFair, *fairInitStates, *mdd1;
+  array_t *EFonionRings, *EGArrayOfOnionRings, *EGonionRings;
+  array_t *newOnionRings;
+  int i, j;
+  Mc_EarlyTermination_t *earlyTermination;
+
+  initialStates = Fsm_FsmComputeInitialStates(modelFsm);
+  mddOne = mdd_one(mddManager);
+
+  /* if debugging information is requested, arrayOfOnionRings!=NIL(array_t) */
+  if (arrayOfOnionRings != NIL(array_t)) {
+    EGArrayOfOnionRings = array_alloc(array_t *, 0);
+    EFonionRings = array_alloc(mdd_t *, 0);
+  }else {
+    EGArrayOfOnionRings = NIL(array_t);
+    EFonionRings = NIL(array_t);
+  }
+
+  if (isSccTerminal)
+    mddEgFair = mdd_dup(sccClosedSet);
+  else
+    mddEgFair = Mc_FsmEvaluateEGFormula(modelFsm, sccClosedSet, 
+					NIL(mdd_t), mddOne, 
+					NIL(Fsm_Fairness_t),
+					modelCareStatesArray, 
+					NIL(Mc_EarlyTermination_t),
+					NIL(array_t), Mc_None_c,
+					&EGArrayOfOnionRings,
+					(Mc_VerbosityLevel) verbosity,
+					(Mc_DcLevel) dcLevel,
+					NIL(boolean), McGSH_EL_c);
+
+  earlyTermination = Mc_EarlyTerminationAlloc(McSome_c, initialStates);
+  mddEfEgFair = Mc_FsmEvaluateEUFormula(modelFsm, mddOne,
+					mddEgFair, NIL(mdd_t), mddOne,
+					modelCareStatesArray,
+					earlyTermination,
+					NIL(array_t), Mc_None_c,
+					EFonionRings,
+					(Mc_VerbosityLevel) verbosity,
+					(Mc_DcLevel) dcLevel,
+					NIL(boolean));
+  mdd_free(mddEgFair);
+  Mc_EarlyTerminationFree(earlyTermination);
+
+  fairInitStates = mdd_and(mddEfEgFair, initialStates, 1, 1);
+
+  /* create the arrayOfOnionRings */
+  if (arrayOfOnionRings!=NIL(array_t) && !mdd_is_tautology(fairInitStates,0)) {
+    if (isSccTerminal) 
+      array_insert_last(array_t *, 
+			arrayOfOnionRings, mdd_array_duplicate(EFonionRings));
+    else {
+      arrayForEachItem(array_t *, EGArrayOfOnionRings, i, EGonionRings) {
+	newOnionRings = mdd_array_duplicate(EGonionRings);
+	arrayForEachItem(mdd_t *, EFonionRings, j, mdd1) {
+	  if (j != 0)
+	    array_insert_last(mdd_t *, newOnionRings, mdd_dup(mdd1));
+	}
+	array_insert_last(array_t *, arrayOfOnionRings, newOnionRings);
+      }
+    }
+  }
+  mdd_free(fairInitStates);
+  
+  if (arrayOfOnionRings != NIL(array_t)) {
+    mdd_array_free(EFonionRings);
+    mdd_array_array_free(EGArrayOfOnionRings);
+  }
+
+  mdd_free(initialStates);
+  mdd_free(mddOne);
+
+  return mddEfEgFair;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Compute the abstract states from the concrete states.]
+
+  Description [By existentially quantify out the invisible
+  variables. Invisible variables are those state variables (or
+  latches) that are not in the supports of the abstract states---they
+  have been abstracted away.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t * 
+McComputeAbstractStates(
+  Fsm_Fsm_t *absFsm, 
+  mdd_t *states)
+{
+  mdd_t	      *result;
+  mdd_manager *mddManager = Fsm_FsmReadMddManager(absFsm);
+  array_t     *psVars = Fsm_FsmReadPresentStateVars(absFsm);
+  array_t     *supportVars;
+  array_t     *invisibleVars = array_alloc(long, 0);
+  st_table    *psVarTable = st_init_table(st_numcmp, st_numhash);
+  int         i;
+  long        mddId;
+
+  arrayForEachItem(long, psVars, i, mddId) {
+    st_insert(psVarTable, (char *)mddId, NIL(char));
+  }
+  
+  supportVars = mdd_get_support(mddManager, states);
+  arrayForEachItem(long, supportVars, i, mddId) {
+    if (!st_is_member(psVarTable, (char *)mddId)) 
+      array_insert_last(long, invisibleVars, mddId);
+  }
+  array_free(supportVars);
+  st_free_table(psVarTable);
+
+  result = mdd_smooth(mddManager, states, invisibleVars);
+
+  array_free(invisibleVars);
+
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Return true if the Divide and Compose (D'n'C) approach for
+  language emptiness checking is enabled.]
+
+  Description [Return true if the D'n'C approach for language emptiness
+  is enabled.]
+
+  SideEffects []
+
+******************************************************************************/
+boolean
+McGetDncEnabled(void)
+{
+  char *flagValue;
+  boolean result = FALSE;
+ 
+  flagValue = Cmd_FlagReadByName("divide_and_compose");
+  if (flagValue != NIL(char)) {
+    if (strcmp(flagValue, "true") == 0)
+      result = TRUE;
+    else if (strcmp(flagValue, "false") == 0)
+      result = FALSE;
+    else {
+      fprintf(vis_stderr, "** dnc error: invalid dnc_enable flag %s, dnc is disabled. \n", flagValue);
+    }
+  }
+
+  return result;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Return true if the given SCC is strong.]
+
+  Description [Return true if the given SCC is strong. Note that the
+  check is conservative -- for the purpose of efficiency -- When it
+  returns false, the SCC is definitely weak; when it returns true, the
+  SCC may be still be weak. For the language emptiness checking, this
+  is not going to hurt us.]
+
+  SideEffects []
+
+******************************************************************************/
+static boolean
+SccIsStrong(mdd_manager *mddMgr, array_t *buechiFairness, mdd_t *SCC)
+{
+  boolean strength;
+  mdd_t *LabeledAllFairness = mdd_dup(SCC);
+  mdd_t *NotLabeledAllFairness;
+  mdd_t *fairSet;
+  int i;
+    
+  /*
+   * check whether SCC intersects all the fairness constraints
+   * if yes, WEAK
+   * if no,  WEAK or STRONG
+   */
+  arrayForEachItem(mdd_t *, buechiFairness, i, fairSet) {
+    mdd_t *tmpMdd = LabeledAllFairness;
+    LabeledAllFairness = mdd_and(LabeledAllFairness, fairSet, 1,1 );
+    mdd_free( tmpMdd );
+  }
+  NotLabeledAllFairness = mdd_and(SCC, LabeledAllFairness, 1, 0);
+  mdd_free(LabeledAllFairness);
+  
+  if(mdd_is_tautology(NotLabeledAllFairness, 0)) {
+    mdd_free(NotLabeledAllFairness);
+    strength = FALSE; /* WEAK*/
+  }
+  else {
+    mdd_free(NotLabeledAllFairness);
+    strength = TRUE;
+  }
+  
+  return strength;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Compare the size of two mdds.]
+
+  Description [Used to sort the array of mdds by their number of minterms.]
+
+  SideEffects [SortMddArrayBySize]
+
+******************************************************************************/
+static st_table *array_mdd_compare_table = NIL(st_table);
+static int 
+array_mdd_compare_size(
+  const void *obj1, 
+  const void *obj2) 
+{
+  double *val1, *val2;
+  int flag1, flag2;
+
+  flag1 = st_lookup(array_mdd_compare_table, *((char **)obj1), &val1);
+  flag2 = st_lookup(array_mdd_compare_table, *((char **)obj2), &val2);
+  assert(flag1 && flag2);
+
+  if (*val1 < *val2)
+    return -1;
+  else if (*val1> *val2)
+    return +1;
+  else 
+    return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Sort the array of mdds by their number of minterms.]
+
+  Description [Sort the array of mdds by their number of minterms. The
+  present state variables of the given FSM is used to count the
+  minterms. The sorting will be skipped if the number of present state
+  variables is larger than 1024.]
+
+  SideEffects [array_mdd_compare_size]
+
+******************************************************************************/
+static array_t *
+SortMddArrayBySize(Fsm_Fsm_t *fsm, array_t *mddArray)
+{
+  mdd_manager *mddManager = Fsm_FsmReadMddManager(fsm);
+  array_t     *psVars = Fsm_FsmReadPresentStateVars(fsm);
+  
+  if (array_n(psVars) < 1024) {
+    st_table    *mddToSizeTable =st_init_table(st_ptrcmp, st_ptrhash);
+    double      *sizes = ALLOC(double, array_n(mddArray));
+    mdd_t       *mdd1;
+    int         i;
+
+    arrayForEachItem(mdd_t *, mddArray, i, mdd1) {
+      *(sizes+i) = mdd_count_onset(mddManager, mdd1, psVars);
+      st_insert(mddToSizeTable, (char *)mdd1, (char *)(sizes+i));
+    }
+    
+    array_mdd_compare_table = mddToSizeTable;
+    array_sort(mddArray, array_mdd_compare_size);
+
+    FREE(sizes);
+    st_free_table(mddToSizeTable);
+  }
+
+  return mddArray;
+}
+
+	
+/**Function********************************************************************
+
+  Synopsis [Compare two strings]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+stringCompare(
+  const void * s1,
+  const void * s2)
+{
+  return(strcmp(*(char **)s1, *(char **)s2));
+}
+
+    
Index: vis_dev/vis-2.3/src/mc/mcGFP.c
===================================================================
--- vis_dev/vis-2.3/src/mc/mcGFP.c	(revision 14)
+++ vis_dev/vis-2.3/src/mc/mcGFP.c	(revision 14)
@@ -0,0 +1,877 @@
+/**CFile***********************************************************************
+
+  FileName    [mcGFP.c]
+
+  PackageName [mc]
+
+  Synopsis    [Computation of greatest fixpoints.]
+
+  Description [This file contains the functions implementing the Generalized
+  SCC Hull algorithm (GSH) for language emptiness check and for the
+  computation of the states satisfying an EG formula.]
+
+  SeeAlso     [mcMc.c]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "mcInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [Structure to store disabled operators in GSH.]
+
+  Description [Structure to store disabled operators in GSH.  A
+  disabled operator is one whose application is known not to cause any
+  progress towards the fixpoint.  When all operators are disabled, the
+  computation has converged to the fixpoint.  If there are n fairness
+  constraints, the EU operators receive the indices from 0 to n-1,
+  while the one EX is given index n.]
+
+******************************************************************************/
+struct McGSHOpSetStruct {
+  array_t *flags;		/* flag array for quick membership test */
+  int cnt;			/* number of operators in set */
+  int last;			/* last operator applied */
+  int nextToLast;		/* next to last operator applied */
+  int exBudget;			/* allowed number of EXs in budget schedule */
+  int exCount;			/* EXs applied so far (EUs included) */
+  Mc_GSHScheduleType schedule;	/* operator schedule */
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef struct McGSHOpSetStruct McGSHOpSet_t;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] UNUSED = "$Id: mcGFP.c,v 1.10 2002/09/16 00:47:16 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**Macro***********************************************************************
+
+  Synopsis    [Returns TRUE if an operator of GSH is an EX.]
+
+  SideEffects [none]
+
+******************************************************************************/
+#define GSHoperatorIsEX(op,set) ((op) == (array_n((set)->flags) - 1))
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int PickOperatorForGSH ARGS((McGSHOpSet_t *set));
+static boolean ConvergedGSH ARGS((mdd_t *Z, mdd_t *zeta, int opIndex, McGSHOpSet_t *opSet, array_t *careStatesArray, Mc_EarlyTermination_t *earlyTermination, boolean *fixpoint));
+static McGSHOpSet_t * AllocOperatorSetGSH ARGS((int n, Mc_GSHScheduleType schedule));
+static void FreeOperatorSetGSH ARGS((McGSHOpSet_t *set));
+static void EmptyOperatorSetGSH ARGS((McGSHOpSet_t *set));
+static boolean IsMemberOperatorSetGSH ARGS((McGSHOpSet_t *set, int opIndex));
+static int SizeOperatorSetGSH ARGS((McGSHOpSet_t *set));
+static int PushOperatorSetGSH ARGS((McGSHOpSet_t *set, int opIndex));
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Evaluate states satisfying EG(invariantMdd), given
+  a transition relation.]
+
+  Description [Evaluate states satisfying EG(invariantMdd) under
+  Buechi fairness conditions, given a transition relation.  Use the
+  GSH (Generalized SCC Hull, Ravi et al., FMCAD00) algorithm
+  restricted to backward operators.  (We can mix forward and backward
+  operators in language emptiness, but not in the EG computation.)]
+
+  SideEffects [If onionRingsArrayForDbg is not NULL on entry, leaves
+  the onion rings of the EU computations in the array it points to.
+  If fixpoint is not NULL, stores in the location pointed by it the
+  information about the cause for termination.  (That is, whether a
+  fixpoint was reached or not.)]
+
+  SeeAlso     [Mc_FsmEvaluateEGFormula]
+
+******************************************************************************/
+mdd_t*
+McFsmEvaluateEGFormulaUsingGSH(
+  Fsm_Fsm_t *modelFsm,
+  mdd_t *invariantMdd,
+  mdd_t *overapprox,
+  mdd_t *fairStates,
+  Fsm_Fairness_t *modelFairness,
+  array_t *careStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  array_t **pOnionRingsArrayForDbg,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  boolean *fixpoint,
+  Mc_GSHScheduleType schedule)
+{
+  int i,n;
+  array_t *onionRings;
+  boolean useRings;
+  mdd_manager *mddManager;
+  mdd_t *mddOne;
+  mdd_t *iterate;
+  array_t *buechiFairness;
+  int nPreComps;
+  int nIterations;
+  McGSHOpSet_t *operatorSet;
+
+  /* Here's how the pOnionRingsArrayForDbg works.  It is a pointer to
+  ** an array of arrays of mdds.  There is one entry for every
+  ** fairness constraint, and this entry is the array of the onion
+  ** rings of the EU computation that corresponds to this constraint.
+  ** Every time the EU for a given constraint is recomputed, the
+  ** corresponding array of rings is renewed.  */
+  assert(pOnionRingsArrayForDbg == NIL(array_t *) ||
+	 *pOnionRingsArrayForDbg == NIL(array_t) ||
+	 array_n(*pOnionRingsArrayForDbg) == 0);  
+
+  useRings = (pOnionRingsArrayForDbg != NIL(array_t *) &&
+	      *pOnionRingsArrayForDbg != NIL(array_t));
+
+  /* Initialization. */
+  nIterations = 0;
+  nPreComps = Img_GetNumberOfImageComputation(Img_Backward_c);
+  onionRings = NIL(array_t);
+  mddManager = Fsm_FsmReadMddManager(modelFsm);
+  mddOne = mdd_one(mddManager);
+
+  /* If an overapproxiamtion of the greatest fixpoint is given, use it. */
+  if(overapprox != NIL(mdd_t)){
+    iterate = mdd_and(invariantMdd, overapprox, 1, 1);
+  } else {
+    iterate = mdd_dup(invariantMdd);
+  }
+
+  /* See if we need to enter the loop at all.  If we wanted to test for
+  ** early termination here, we should fix the onion rings. */
+  if (mdd_is_tautology(iterate, 0)) {
+    mdd_free(mddOne);
+    if (fixpoint != NIL(boolean)) *fixpoint = mdd_is_tautology(iterate, 0);
+    return(iterate);
+  }
+
+  /* Read fairness constraints. */
+  buechiFairness = array_alloc(mdd_t *, 0);
+  if (modelFairness != NIL(Fsm_Fairness_t)) {
+    if (!Fsm_FairnessTestIsBuchi(modelFairness)) {
+      (void) fprintf(vis_stdout,
+	       "** mc error: non-Buechi fairness constraints not supported\n");
+      array_free(buechiFairness);
+      mdd_free(iterate);
+      mdd_free(mddOne);
+
+      if (fixpoint != NIL(boolean)) *fixpoint = FALSE;
+      return NIL(mdd_t);
+    } else {
+      int j;
+      int numBuechi = Fsm_FairnessReadNumConjunctsOfDisjunct(modelFairness, 0);
+      for (j = 0; j < numBuechi; j++) {
+	mdd_t *tmpMdd = Fsm_FairnessObtainFinallyInfMdd(modelFairness, 0, j,
+						careStatesArray, dcLevel);
+	array_insert_last(mdd_t *, buechiFairness, tmpMdd);
+      }
+    }
+  } else {
+    array_insert_last(mdd_t *, buechiFairness, mdd_one(mddManager));
+  }
+
+  /* Initialize set of disabled operators (to the empty set). */
+  n = array_n(buechiFairness);
+  operatorSet = AllocOperatorSetGSH(n, schedule);
+
+  /* Iterate until all operators disabled or early termination. */
+  while (TRUE) {
+    mdd_t *oldIterate = iterate;
+    int opIndex = PickOperatorForGSH(operatorSet);
+    nIterations++;
+    if (GSHoperatorIsEX(opIndex,operatorSet)) {
+      mdd_t *EX = Mc_FsmEvaluateEXFormula(modelFsm, oldIterate, mddOne,
+					  careStatesArray, verbosity,
+					  dcLevel);
+      iterate = mdd_and(EX, oldIterate, 1, 1);
+      mdd_free(EX);
+    } else {
+      mdd_t *Fi = array_fetch(mdd_t *, buechiFairness, opIndex);
+      mdd_t *target = mdd_and(Fi, iterate, 1, 1);
+
+      /* Dispose of the old set of onion rings for this fairness constraint
+      ** if it exists, and allocate a fresh array for a new set of rings. */
+      if (useRings) {
+	if (opIndex < array_n(*pOnionRingsArrayForDbg)) {
+	  onionRings = array_fetch(array_t *, *pOnionRingsArrayForDbg,
+				   opIndex);
+	  mdd_array_free(onionRings);
+	}
+	onionRings = array_alloc(mdd_t *, 0);
+	array_insert(array_t *, *pOnionRingsArrayForDbg, opIndex, onionRings);
+      }
+
+      iterate = Mc_FsmEvaluateEUFormula(modelFsm, oldIterate, target,
+					NIL(mdd_t), mddOne, careStatesArray,
+					MC_NO_EARLY_TERMINATION, NIL(array_t),
+					Mc_None_c, onionRings, verbosity,
+					dcLevel, NIL(boolean));
+      mdd_free(target);
+    }
+    if (ConvergedGSH(iterate, oldIterate, opIndex, operatorSet,
+		     careStatesArray, earlyTermination, fixpoint)) {
+      mdd_free(oldIterate);
+      break;
+    }
+    mdd_free(oldIterate);
+  }
+
+  /* Free operator set. */
+  FreeOperatorSetGSH(operatorSet);
+
+  /* Sanity checks for onion rings and diagnostic prints. */
+  if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) {
+    if (useRings) {
+      for (i = 0 ; i < array_n(*pOnionRingsArrayForDbg); i++) {
+	int j;
+	mdd_t *Fi = array_fetch(mdd_t *, buechiFairness, i);
+	array_t *onionRings = array_fetch(array_t *, *pOnionRingsArrayForDbg,
+					  i);
+	/* Early termination with random schedules may leave holes. */
+	if (onionRings == NIL(array_t)) continue;
+	for (j = 0; j < array_n(onionRings); j++) {
+	  mdd_t *ring = array_fetch(mdd_t *, onionRings, j);
+	  if (j == 0) {
+	    if (!mdd_lequal_mod_care_set_array(ring, Fi, 1, 1,
+					       careStatesArray)) {
+	      fprintf(vis_stderr, "** mc error: Problem w/ dbg in EG - ");
+	      fprintf(vis_stderr,
+		      "inner most ring not in Fi (fairness constraint).\n");
+	    }
+	  }
+	  if (!mdd_lequal_mod_care_set_array(ring, invariantMdd, 1, 1,
+					     careStatesArray)) {
+	    fprintf(vis_stderr, "** mc error: Problem w/ dbg in EG - ");
+	    fprintf(vis_stderr, "onion ring of last EU fails invariant\n");
+	  }
+	}
+      }
+    }
+
+    if (verbosity == McVerbosityMax_c) {
+      mdd_t *tmpMdd = careStatesArray ?
+	mdd_and_array(iterate, careStatesArray, 1, 1) : mdd_dup(iterate);
+      fprintf(vis_stdout,
+	      "--There are %.0f care states satisfying EG formula\n",
+	      mdd_count_onset(mddManager, tmpMdd,
+			      Fsm_FsmReadPresentStateVars(modelFsm)));
+#ifdef DEBUG_MC
+      /* The following 2 lines are just for debug. */
+      fprintf(vis_stdout, "EG satisfying minterms :\n");
+      (void)_McPrintSatisfyingMinterms(tmpMdd, modelFsm);
+#endif
+      mdd_free(tmpMdd);
+    } else {
+      fprintf(vis_stdout, "--There are %.0f states satisfying EG formula\n",
+	      mdd_count_onset(mddManager, iterate,
+			      Fsm_FsmReadPresentStateVars(modelFsm)));
+    }
+
+    fprintf(vis_stdout, "--EG: %d iterations, %d preimage computations\n",
+	    nIterations,
+	    Img_GetNumberOfImageComputation(Img_Backward_c) - nPreComps);
+  }
+
+  mdd_array_free(buechiFairness);
+  mdd_free(mddOne);
+
+  return iterate;
+
+} /* McFsmEvaluateEGFormulaUsingGSH */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Evaluate states satisfying EH(invariantMdd), given
+  a transition relation.]
+
+  Description [Evaluate states satisfying EH(invariantMdd) under
+  Buechi fairness conditions, given a transition relation.  Use the
+  GSH (Generalized SCC Hull, Ravi et al., FMCAD00) algorithm
+  restricted to forward operators.  (We can mix forward and backward
+  operators in language emptiness, but not in the EH computation.)]
+
+  SideEffects [If onionRingsArrayForDbg is not NULL on entry, leaves
+  the onion rings of the ES computations in the array it points to.
+  If fixpoint is not NULL, stores in the location pointed by it the
+  information about the cause for termination.  (That is, whether a
+  fixpoint was reached or not.)]
+
+  SeeAlso     [Mc_FsmEvaluateEHFormula]
+
+******************************************************************************/
+mdd_t*
+McFsmEvaluateEHFormulaUsingGSH(
+  Fsm_Fsm_t *modelFsm,
+  mdd_t *invariantMdd,
+  mdd_t *overapprox,
+  mdd_t *fairStates,
+  Fsm_Fairness_t *modelFairness,
+  array_t *careStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  array_t **pOnionRingsArrayForDbg,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  boolean *fixpoint,
+  Mc_GSHScheduleType schedule)
+{
+  int i,n;
+  array_t *onionRings;
+  boolean useRings;
+  mdd_manager *mddManager;
+  mdd_t *mddOne;
+  mdd_t *iterate;
+  array_t *buechiFairness;
+  int nImgComps;
+  int nIterations;
+  McGSHOpSet_t *operatorSet;
+
+  /* Here's how the pOnionRingsArrayForDbg works.  It is a pointer to
+  ** an array of arrays of mdds.  There is one entry for every
+  ** fairness constraint, and this entry is the array of the onion
+  ** rings of the ES computation that corresponds to this constraint.
+  ** Every time the ES for a given constraint is recomputed, the
+  ** corresponding array of rings is renewed.  */
+  assert(pOnionRingsArrayForDbg == NIL(array_t *) ||
+	 *pOnionRingsArrayForDbg == NIL(array_t) ||
+	 array_n(*pOnionRingsArrayForDbg) == 0);  
+
+  useRings = (pOnionRingsArrayForDbg != NIL(array_t *) &&
+	      *pOnionRingsArrayForDbg != NIL(array_t));
+
+  /* Initialization. */
+  nIterations = 0;
+  nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c);
+  onionRings = NIL(array_t);
+  mddManager = Fsm_FsmReadMddManager(modelFsm);
+  mddOne = mdd_one(mddManager);
+
+  /* If an overapproxiamtion of the greatest fixpoint is given, use it. */
+  if(overapprox != NIL(mdd_t)){
+    iterate = mdd_and(invariantMdd, overapprox, 1, 1);
+  } else {
+    iterate = mdd_dup(invariantMdd);
+  }
+
+  /* See if we need to enter the loop at all. */
+  if (mdd_is_tautology(iterate, 0) ||
+    McCheckEarlyTerminationForOverapprox(earlyTermination,
+					 iterate, careStatesArray)) {
+    mdd_free(mddOne);
+
+    if (fixpoint != NIL(boolean)) *fixpoint = mdd_is_tautology(iterate, 0);
+    return(iterate);
+  }
+
+  /* Read fairness constraints. */
+  buechiFairness = array_alloc(mdd_t *, 0);
+  if (modelFairness != NIL(Fsm_Fairness_t)) {
+    if (!Fsm_FairnessTestIsBuchi(modelFairness)) {
+      (void) fprintf(vis_stdout,
+	       "** mc error: non-Buechi fairness constraints not supported\n");
+      array_free(buechiFairness);
+      mdd_free(iterate);
+      mdd_free(mddOne);
+
+      if (fixpoint != NIL(boolean)) *fixpoint = FALSE;
+      return NIL(mdd_t);
+    } else {
+      int j;
+      int numBuechi = Fsm_FairnessReadNumConjunctsOfDisjunct(modelFairness, 0);
+      for (j = 0; j < numBuechi; j++) {
+	mdd_t *tmpMdd = Fsm_FairnessObtainFinallyInfMdd(modelFairness, 0, j,
+						careStatesArray, dcLevel);
+	array_insert_last(mdd_t *, buechiFairness, tmpMdd);
+      }
+    }
+  } else {
+    array_insert_last(mdd_t *, buechiFairness, mdd_one(mddManager));
+  }
+
+  /* Initialize set of disabled operators (to the empty set). */
+  n = array_n(buechiFairness);
+  operatorSet = AllocOperatorSetGSH(n, schedule);
+
+  /* Iterate until all operators disabled or early termination. */
+  while (TRUE) {
+    mdd_t *oldIterate = iterate;
+    int opIndex = PickOperatorForGSH(operatorSet);
+    nIterations++;
+    if (GSHoperatorIsEX(opIndex,operatorSet)) {
+      mdd_t *EY = Mc_FsmEvaluateEYFormula(modelFsm, oldIterate, mddOne,
+					  careStatesArray, verbosity,
+					  dcLevel);
+      iterate = mdd_and(EY, oldIterate, 1, 1);
+      mdd_free(EY);
+    } else {
+      mdd_t *Fi = array_fetch(mdd_t *, buechiFairness, opIndex);
+      mdd_t *source = mdd_and(Fi, iterate, 1, 1);
+
+      /* Dispose of the old set of onion rings for this fairness constraint
+      ** if it exists, and allocate a fresh array for a new set of rings. */
+      if (useRings) {
+	if (opIndex < array_n(*pOnionRingsArrayForDbg)) {
+	  onionRings = array_fetch(array_t *, *pOnionRingsArrayForDbg,
+				   opIndex);
+	  mdd_array_free(onionRings);
+	}
+	onionRings = array_alloc(mdd_t *, 0);
+	array_insert(array_t *, *pOnionRingsArrayForDbg, opIndex, onionRings);
+      }
+
+      iterate = Mc_FsmEvaluateESFormula(modelFsm, oldIterate, source,
+					NIL(mdd_t), mddOne, careStatesArray,
+					MC_NO_EARLY_TERMINATION, NIL(array_t),
+					Mc_None_c, onionRings, verbosity,
+					dcLevel, NIL(boolean));
+      mdd_free(source);
+    }
+    if (ConvergedGSH(iterate, oldIterate, opIndex, operatorSet,
+		     careStatesArray, earlyTermination, fixpoint)) {
+      mdd_free(oldIterate);
+      break;
+    }
+    mdd_free(oldIterate);
+  }
+
+  /* Free operator set. */
+  FreeOperatorSetGSH(operatorSet);
+
+  /* Sanity checks for onion rings and diagnostic prints. */
+  if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) {
+    if (useRings) {
+      for (i = 0 ; i < array_n(*pOnionRingsArrayForDbg); i++) {
+	int j;
+	mdd_t *Fi = array_fetch(mdd_t *, buechiFairness, i);
+	array_t *onionRings = array_fetch(array_t *, *pOnionRingsArrayForDbg,
+					  i);
+	/* Early termination with random schedules may leave holes. */
+	if (onionRings == NIL(array_t)) continue;
+	for (j = 0; j < array_n(onionRings); j++) {
+	  mdd_t *ring = array_fetch(mdd_t *, onionRings, j);
+	  if (j == 0) {
+	    if (!mdd_lequal_mod_care_set_array(ring, Fi, 1, 1,
+					       careStatesArray)) {
+	      fprintf(vis_stderr, "** mc error: Problem w/ dbg in EH - ");
+	      fprintf(vis_stderr,
+		      "inner most ring not in Fi (fairness constraint).\n");
+	    }
+	  }
+	  if (!mdd_lequal_mod_care_set_array(ring, invariantMdd, 1, 1,
+					     careStatesArray)) {
+	    fprintf(vis_stderr, "** mc error: Problem w/ dbg in EH - ");
+	    fprintf(vis_stderr, "onion ring of last ES fails invariant\n");
+	  }
+	}
+      }
+    }
+
+    if (verbosity == McVerbosityMax_c) {
+      mdd_t *tmpMdd = careStatesArray ?
+	mdd_and_array(iterate, careStatesArray, 1, 1) : mdd_dup(iterate);
+      fprintf(vis_stdout,
+	      "--There are %.0f care states satisfying EH formula\n",
+	      mdd_count_onset(mddManager, tmpMdd,
+			      Fsm_FsmReadPresentStateVars(modelFsm)));
+#ifdef DEBUG_MC
+      /* The following 2 lines are just for debug. */
+      fprintf(vis_stdout, "EH satisfying minterms :\n");
+      (void)_McPrintSatisfyingMinterms(tmpMdd, modelFsm);
+#endif
+      mdd_free(tmpMdd);
+    } else {
+      fprintf(vis_stdout, "--There are %.0f states satisfying EH formula\n",
+	      mdd_count_onset(mddManager, iterate,
+			      Fsm_FsmReadPresentStateVars(modelFsm)));
+    }
+
+    fprintf(vis_stdout, "--EH: %d iterations, %d image computations\n",
+	    nIterations,
+	    Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps);
+  }
+
+  mdd_array_free(buechiFairness);
+  mdd_free(mddOne);
+
+  return iterate;
+
+} /* McFsmEvaluateEHFormulaUsingGSH */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the next operator for the GSH algorithm.]
+
+  Description [Returns the next operator for the GSH algorithm.]
+
+  SideEffects [Updates the operator set.]
+
+  SeeAlso     [McFsmEvaluateEGFormulaUsingGSH]
+
+******************************************************************************/
+static int
+PickOperatorForGSH(
+  McGSHOpSet_t *set)
+{
+  int nop = array_n(set->flags);
+  int opIndex;
+  if (set->schedule == McGSH_EL_c) {
+    int exIndex = nop - 1;
+    if ((set->last != exIndex) && !array_fetch(int, set->flags, exIndex)) {
+      opIndex = exIndex;
+    } else {
+      if (set->last == exIndex) {
+	opIndex = (set->nextToLast + 1) % exIndex;
+      } else {
+	opIndex = (set->last + 1) % exIndex;
+      }
+      while (array_fetch(int, set->flags, opIndex))
+	opIndex = (opIndex + 1) % nop;
+    }
+    set->nextToLast = set->last;
+  } else if (set->schedule == McGSH_EL1_c) {
+    /* EL1 implements a round-robin policy. */
+    opIndex = (set->last + 1) % nop;
+    while (array_fetch(int, set->flags, opIndex))
+      opIndex = (opIndex + 1) % nop;
+  } else if (set->schedule == McGSH_EL2_c) {
+    /* EL2 differs from EL1 in that it repeats EX to convergence.
+     * We rely on the fact that EUs are always disabled after their
+     * application. */
+    opIndex = set->last;
+    while (array_fetch(int, set->flags, opIndex))
+      opIndex = (opIndex + 1) % nop;
+  } else if (set->schedule == McGSH_Budget_c) {
+    int exIndex = nop - 1;
+    int newCount = Img_GetNumberOfImageComputation(Img_Backward_c);
+    if (set->last == exIndex)
+      set->exBudget--;
+    else
+      set->exBudget += newCount - set->exCount;
+    set->exCount = newCount;
+    /* (void) printf("budget = %d\n", set->exBudget); */
+    if ((set->last != exIndex) && !array_fetch(int, set->flags, exIndex)) {
+      /* At least one EX after each EU, unless EX is disabled */
+      opIndex = exIndex;
+      set->nextToLast = set->last;
+    } else {
+      if (set->last == exIndex) {
+	if (set->exBudget > 0 && set->nextToLast == exIndex - 1) {
+	  opIndex = exIndex;
+	} else {
+	  opIndex = (set->nextToLast + 1) % exIndex;
+	  set->nextToLast = set->last;
+	}
+      } else { /* EX is disabled */
+	opIndex = (set->last + 1) % exIndex;
+	set->nextToLast = set->last;
+      }
+      while (array_fetch(int, set->flags, opIndex))
+	opIndex = (opIndex + 1) % nop;
+    }
+    if (opIndex == 0)
+      set->exBudget = 0;
+#if 0
+    opIndex = set->last;
+    if (opIndex == exIndex && set->exBudget == 0)
+      opIndex = 0;
+    while (array_fetch(int, set->flags, opIndex))
+      opIndex = (opIndex + 1) % nop;
+#endif
+  } else {
+    /* The random schedule uses a rather primitive way of selecting a
+     * random integer.  However, as long as the number of operators is
+     * small, the distribution is acceptably uniform even if we use
+     * mod to map the result of util_random to 0 ... nop-1. */
+    int exIndex = nop - 1;
+    long rn = util_random();
+    int exDisabled = array_fetch(int, set->flags, exIndex);
+    if ((!exDisabled) && ((rn & 1024) || (set->cnt == exIndex))) {
+      /* rn & 1024 should be true 50% of the times */
+      opIndex = exIndex;
+    } else {
+      int enabledEUs = exIndex - (set->cnt - exDisabled);
+      rn = rn % enabledEUs;
+      assert(0 <= rn && rn < exIndex);
+      for (opIndex = 0; TRUE; opIndex++) {
+	assert(opIndex < exIndex);
+	if (!array_fetch(int, set->flags, opIndex)) {
+	  if (rn == 0) {
+	    break;
+	  } else {
+	    rn--;
+	  }
+	}
+      }
+    }
+  }
+  set->last = opIndex;
+  return opIndex;
+
+} /* PickOperatorForGSH */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the convergence test for the GSH algorithm.]
+
+  Description [Performs the convergence test for the GSH algorithm.
+  Returns TRUE if convergence is achived; FALSE otherwise.]
+
+  SideEffects [Updates the operator set.  An operator is disabled
+  after application if it is an EU, or if has caused no progress
+  toward the fixpoint.  If convergence is reached, ConvergedGSH sets
+  the location pointed by parameter fixpoint to TRUE if a fixpoint was
+  reached, or to FALSE if early termination occured.]
+
+  SeeAlso     [McFsmEvaluateEGFormulaUsingGSH]
+
+******************************************************************************/
+static boolean
+ConvergedGSH(
+  mdd_t *Z			/* new iterate */,
+  mdd_t *zeta			/* old iterate */,
+  int opIndex			/* operator that has been just applied */,
+  McGSHOpSet_t *opSet		/* set of disabled operators */,
+  array_t *careStatesArray	/* array for care states */,
+  Mc_EarlyTermination_t *earlyTermination /* early termination criterion */,
+  boolean *fixpoint		/* reason for termination */)
+{
+  boolean term_tautology = FALSE;
+  boolean term_fixpoint = FALSE;
+  boolean term_early = FALSE;
+
+  term_tautology = mdd_is_tautology(Z, 0);
+  if (!term_tautology)
+    term_fixpoint =  mdd_equal_mod_care_set_array(Z, zeta, careStatesArray);
+  if (!term_tautology && !term_fixpoint)
+    term_early = McCheckEarlyTerminationForOverapprox(earlyTermination, Z, 
+						      careStatesArray);
+  if (term_tautology || term_early) {
+    if (fixpoint != NIL(boolean))
+      *fixpoint = term_tautology;
+    return TRUE;
+  } else if (term_fixpoint) {
+    if (PushOperatorSetGSH(opSet,opIndex) == SizeOperatorSetGSH(opSet)) {
+      if (fixpoint != NIL(boolean))
+	*fixpoint = TRUE;
+      return TRUE;
+    } else {
+      return FALSE;
+    }
+  } else {
+    EmptyOperatorSetGSH(opSet);
+    if (!GSHoperatorIsEX(opIndex,opSet)) {
+      /* The operator is an EU.  Add to set. */
+      (void) PushOperatorSetGSH(opSet,opIndex);
+    }
+    return FALSE;
+  }
+
+} /* ConvergedGSH */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a new operator set.]
+
+  Description [Creates a new operator set to hold n operators.]
+
+  SideEffects [None]
+
+  SeeAlso     [McFsmEvaluateEGFormulaUsingGSH FreeOperatorSetGSH]
+
+******************************************************************************/
+static McGSHOpSet_t *
+AllocOperatorSetGSH(
+  int n,
+  Mc_GSHScheduleType schedule)
+{
+  int i;
+  McGSHOpSet_t *set = ALLOC(McGSHOpSet_t, 1);
+  array_t *flags = set->flags = array_alloc(int, n+1);
+  for (i = 0; i < n+1; i++) {
+    array_insert(int, flags, i, 0);
+  }
+  set->cnt = 0;
+  set->schedule = schedule;
+  if (set->schedule == McGSH_EL_c) {
+    set->last = n;
+    set->nextToLast = n - 1;
+  } else if (set->schedule == McGSH_EL1_c) {
+    set->last = n;
+  } else if (set->schedule == McGSH_EL2_c) {
+    set->last = 0;
+  } else if (set->schedule == McGSH_Budget_c) {
+    set->last = n;
+    set->nextToLast = n - 1;
+    set->exBudget = 1;
+    set->exCount = Img_GetNumberOfImageComputation(Img_Backward_c);
+  } else {
+    /* The random schedule has no history.  Hence, this initialization is
+     * immaterial. */
+    set->last = 0;
+  }
+  return set;
+
+} /* AllocOperatorSetGSH */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees an operator set.]
+
+  Description [Frees an operator set.]
+
+  SideEffects [None]
+
+  SeeAlso     [McFsmEvaluateEGFormulaUsingGSH AllocOperatorSetGSH]
+
+******************************************************************************/
+static void
+FreeOperatorSetGSH(
+  McGSHOpSet_t *set)
+{
+  array_free(set->flags);
+  FREE(set);
+  return;
+
+} /* FreeOperatorSetGSH */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Empties an operator set.]
+
+  Description [Empties an operator set.  This is done in the GSH
+  algorithm when progress is made towards the fixpoint.  The
+  information about the last operator applied is unaffected.]
+
+  SideEffects [None]
+
+  SeeAlso     [McFsmEvaluateEGFormulaUsingGSH]
+
+******************************************************************************/
+static void
+EmptyOperatorSetGSH(
+  McGSHOpSet_t *set)
+{
+  int i;
+  for (i = 0; i < array_n(set->flags); i++) {
+    array_insert(int, set->flags, i, 0);
+  }
+  set->cnt = 0;
+  return;
+
+} /* EmptyOperatorSetGSH */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks for membership of an operator in a set.]
+
+  Description [Checks for membership of an operator in a set.]
+
+  SideEffects [None]
+
+  SeeAlso     [McFsmEvaluateEGFormulaUsingGSH]
+
+******************************************************************************/
+static boolean
+IsMemberOperatorSetGSH(
+  McGSHOpSet_t *set,
+  int opIndex)
+{
+  return array_fetch(int, set->flags, opIndex);
+
+} /* IsMemberOperatorSetGSH */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the cardinality of an operator set.]
+
+  Description [Returns the cardinality of an operator set.]
+
+  SideEffects [None]
+
+  SeeAlso     [McFsmEvaluateEGFormulaUsingGSH]
+
+******************************************************************************/
+static int
+SizeOperatorSetGSH(
+  McGSHOpSet_t *set)
+{
+  return array_n(set->flags);
+
+} /* SizeOperatorSetGSH */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adds an element to an operator set.]
+
+  Description [Adds an element to an operator set.]
+
+  SideEffects [None]
+
+  SeeAlso     [McFsmEvaluateEGFormulaUsingGSH]
+
+******************************************************************************/
+static int
+PushOperatorSetGSH(
+  McGSHOpSet_t *set,
+  int opIndex)
+{
+  assert(opIndex < array_n(set->flags));
+  array_insert(int, set->flags, opIndex, 1);
+  set->cnt++;
+  return set->cnt;
+
+} /* PushOperatorSetGSH */
Index: vis_dev/vis-2.3/src/mc/mcInt.h
===================================================================
--- vis_dev/vis-2.3/src/mc/mcInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/mc/mcInt.h	(revision 14)
@@ -0,0 +1,354 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [mcInt.h]
+
+  PackageName [mc]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Adnan Aziz and Tom Shiple, In-Ho Moon]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: mcInt.h,v 1.51 2008/04/22 21:24:49 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _MCINT
+#define _MCINT
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "heap.h"
+#include "ntm.h"
+#include "part.h"
+#include "mc.h"
+#include <string.h>
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define McMaxStringLength_c 1000
+
+
+/**Enum************************************************************************
+
+  Synopsis    [Level to which debugging of CTL formulae is performed.]
+
+******************************************************************************/
+
+typedef enum {
+  McDbgLevelNone_c,
+  McDbgLevelMin_c,
+  McDbgLevelMinVerbose_c,
+  McDbgLevelMax_c,
+  McDbgLevelInteractive_c
+} McDbgLevel;
+
+/**Enum************************************************************************
+
+  Synopsis    [Trimming mode for the enqueued sets of states.]
+
+  Description []
+
+******************************************************************************/
+
+typedef enum {
+  McLS_none_c, /* do not apply any trimming */
+  McLS_G_c,    /* apply EG to set of states */
+  McLS_H_c,    /* apply EH to set of states */
+  McLS_GH_c    /* apply both EG and EH to set of states */
+} McLockstepMode;
+
+
+/**Enum************************************************************************
+
+  Synopsis    [SCC generator status.]
+
+  Description [SCC generator status.  Empty means that there are no more
+  fair SCCs to be enumerated.]
+
+******************************************************************************/
+
+typedef enum {
+  McSccGenEmpty_c,
+  McSccGenNonEmpty_c
+} McSccGenStatus;
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [A struct for representing a paths.]
+
+  Description [Structure consists of two arrays of mdd's - the stem,
+  and the cycle (possibley empty if we are dealing with finite paths)]
+
+******************************************************************************/
+
+struct McPathStruct {
+  array_t *stemArray; /* represents a sequence of mdd's each corresponding to
+                       * a state, for the finite segment of the path
+                       */
+
+  array_t *cycleArray; /* represents a sequence of mdd's each corresponding to
+                        * a state, for the cycle of the path
+                        */
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [A struct for keeping the command line options.]
+
+******************************************************************************/
+
+struct McOptionsStruct {
+  boolean useMore;      /* use more as pipe for debug output */
+  boolean reduceFsm;
+  boolean printInputs;
+  boolean useFormulaTree;
+  boolean vd;   
+  boolean beer;   
+  boolean simFormat;
+  boolean FAFWFlag;
+  FILE *ctlFile;
+  FILE *guideFile;      /* file with hints (null if no guided search) */
+  FILE *systemFile;      /* file with system controlled variable for FAFW */
+  FILE *debugFile;
+  Mc_FwdBwdAnalysis fwdBwd;
+  Mc_LeMethod_t leMethod;
+  Mc_DcLevel dcLevel;
+  McDbgLevel dbgLevel;
+  Mc_GSHScheduleType schedule;
+  int lockstep;
+  Mc_VerbosityLevel verbosityLevel;
+  int timeOutPeriod;
+  boolean doCoverageHoskote;
+  boolean doCoverageImproved;
+  /* The following options are related with ARDC */
+  Fsm_ArdcOptions_t *ardcOptions;
+  Fsm_RchType_t invarApproxFlag; /* the type of reachability analysis for
+				    invariant checking */
+  boolean invarOnionRingsFlag; /* flag to indicate whether onion rings should
+				  be kept during reahability analysis */
+  /* The following option is for forward traversal */
+  Mc_FwdBwdAnalysis traversalDirection;
+  boolean incre; /* flag for incremental SAT solver in PureSAT*/
+  boolean sss; /* flag for SSS/Interpolation, 0 for ip, 1 for SSS*/
+  boolean flatIP; /* flag for flat interpolation algorithm*/
+  int IPspeed; /*enable various speed up techniques for PureSat+IP algorithm*/
+};
+
+/**Struct**********************************************************************
+
+  Synopsis [Keeps info on early termination: you can stop model
+  checking if you have some or all of the states]
+
+******************************************************************************/
+
+struct McEarlyTerminationStruct {
+  Mc_EarlyTerminationType mode;
+  mdd_t *states;
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [Fair SCC generator.]
+
+  Description []
+
+******************************************************************************/
+
+struct McSccGenStruct {
+  McSccGenStatus status;
+  Fsm_Fsm_t *fsm;
+  Heap_t *heap;
+  array_t *rings;		/* of mdd_t */
+  array_t *buechiFairness;	/* of mdd_t */
+  boolean earlyTermination;
+  Mc_VerbosityLevel verbosity;
+  Mc_DcLevel dcLevel;
+  int fairSccsFound;
+  int totalExamined;
+  int nImgComps;
+  int nPreComps;
+};
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef struct McPathStruct McPath_t;
+typedef struct McOptionsStruct McOptions_t;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#define GET_NORMAL_PT(_pt) ((mdd_t *)((unsigned long)(_pt) & ~01L))
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN int McFsmDebugFormula(McOptions_t *options, Ctlp_Formula_t *ctlFormula, Fsm_Fsm_t *modelFsm, array_t *careSetArray);
+EXTERN void McFsmStateDebugFormula(McOptions_t *options, Ctlp_Formula_t *ctlFormula, mdd_t *aState, Fsm_Fsm_t *modelFsm, array_t *careSetArray);
+EXTERN McPath_t * McBuildFairPath(mdd_t *startState, mdd_t *invariantStates, array_t *arrayOfOnionRings, Fsm_Fsm_t *modelFsm, array_t *careSetArray, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, Mc_FwdBwdAnalysis fwdBwd);
+EXTERN mdd_t* McFsmEvaluateEGFormulaUsingGSH(Fsm_Fsm_t *modelFsm, mdd_t *invariantMdd, mdd_t *overapprox, mdd_t *fairStates, Fsm_Fairness_t *modelFairness, array_t *careStatesArray, Mc_EarlyTermination_t *earlyTermination, array_t **pOnionRingsArrayForDbg, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, boolean *fixpoint, Mc_GSHScheduleType schedule);
+EXTERN mdd_t* McFsmEvaluateEHFormulaUsingGSH(Fsm_Fsm_t *modelFsm, mdd_t *invariantMdd, mdd_t *overapprox, mdd_t *fairStates, Fsm_Fairness_t *modelFairness, array_t *careStatesArray, Mc_EarlyTermination_t *earlyTermination, array_t **pOnionRingsArrayForDbg, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, boolean *fixpoint, Mc_GSHScheduleType schedule);
+EXTERN mdd_t * McEvaluateEUFormulaWithGivenTR(Fsm_Fsm_t *modelFsm, mdd_t *invariantMdd, mdd_t *targetMdd, mdd_t *underapprox, mdd_t *fairStates, array_t *careStatesArray, Mc_EarlyTermination_t *earlyTermination, array_t *onionRings, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, boolean *fixpoint);
+EXTERN mdd_t * McEvaluateAUFormulaWithGivenTR(Fsm_Fsm_t *modelFsm, mdd_t *invariantMdd, mdd_t *targetMdd, mdd_t *underapprox, mdd_t *fairStates, array_t *careStatesArray, Mc_EarlyTermination_t *earlyTermination, array_t *onionRings, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, boolean *fixpoint);
+EXTERN mdd_t * McEvaluateESFormulaWithGivenTR(Fsm_Fsm_t *modelFsm, mdd_t *invariantMdd, mdd_t *sourceMdd, mdd_t *underapprox, mdd_t *fairStates, array_t *careStatesArray, Mc_EarlyTermination_t *earlyTermination, array_t *onionRings, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, boolean *fixpoint);
+EXTERN mdd_t * McEvaluateEGFormulaWithGivenTR(Fsm_Fsm_t *modelFsm, mdd_t *invariantMdd, mdd_t *overapprox, mdd_t *fairStates, Fsm_Fairness_t *modelFairness, array_t *careStatesArray, Mc_EarlyTermination_t *earlyTermination, array_t **pOnionRingsArrayForDbg, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, boolean *fixpoint);
+EXTERN mdd_t * McEvaluateEHFormulaWithGivenTR(Fsm_Fsm_t *modelFsm, mdd_t *invariantMdd, mdd_t *overapprox, mdd_t *fairStates, Fsm_Fairness_t *modelFairness, array_t *careStatesArray, Mc_EarlyTermination_t *earlyTermination, array_t **pOnionRingsArrayForDbg, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, boolean *fixpoint);
+EXTERN mdd_t * McEvaluateESFormulaWithGivenTRWithTarget( Fsm_Fsm_t *modelFsm, mdd_t *invariantMdd, mdd_t *sourceMdd, mdd_t *targetMdd, mdd_t *underapprox, mdd_t *fairStates, array_t *careStatesArray, Mc_EarlyTermination_t *earlyTermination, array_t *onionRings, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, boolean *fixpoint);
+EXTERN mdd_t * McEvaluateESFormulaWithGivenTRFAFW( Fsm_Fsm_t *modelFsm, mdd_t *invariantMdd, mdd_t *sourceMdd, mdd_t *underapprox, mdd_t *fairStates, array_t *careStatesArray, Mc_EarlyTermination_t *earlyTermination, array_t *onionRings, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, boolean *fixpoint, mdd_t *Swin);
+EXTERN void McFormulaFreeDebugData(Ctlp_Formula_t *formula);
+EXTERN void _McPrintSatisfyingMinterms(mdd_t *aMdd, Fsm_Fsm_t *fsm);
+EXTERN mdd_t * McFsmComputeFairSCCsByLockStep(Fsm_Fsm_t *fsm, int maxNumberOfSCCs, array_t *SCCs, array_t *onionRingsArrayForDbg, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel);
+EXTERN mdd_t * McFsmRefineFairSCCsByLockStep(Fsm_Fsm_t *fsm, int maxNumberOfSCCs, array_t *SCCs, array_t *sccClosedSets, array_t *careStates, array_t *onionRingsArrayForDbg, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel);
+EXTERN mdd_t * McFsmRefineWeakFairSCCs(Fsm_Fsm_t *modelFsm, mdd_t *sccClosedSet, array_t *modelCareStatesArray, array_t *arrayOfOnionRings,boolean isSccTerminal,int dcLevel, int verbosity);
+EXTERN mdd_t * McFsmComputeOneFairSccByLinearStep(Fsm_Fsm_t *fsm, Heap_t *priorityQueue, array_t *buechiFairness, array_t *onionRings, boolean earlyTermination, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, int *sccExamined);
+EXTERN mdd_t * McFsmComputeOneFairSccByLockStep(Fsm_Fsm_t *fsm, Heap_t *priorityQueue, array_t *buechiFairness, array_t *onionRings, boolean earlyTermination, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, int *sccExamined);
+EXTERN array_t * McCompletePathFwd(mdd_t *aState, mdd_t *bState, mdd_t *invariantStates, Fsm_Fsm_t *modelFsm, array_t *careSetArray, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel);
+EXTERN array_t * McCompletePathBwd(mdd_t *aState, mdd_t *bState, mdd_t *invariantStates, Fsm_Fsm_t *modelFsm, array_t *careSetArray, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel);
+EXTERN int McCommandInitState(Hrc_Manager_t **hmgr, int argc, char **argv);
+EXTERN char * McStatePrintAsFormula(mdd_t *aMinterm, array_t *aSupport, Fsm_Fsm_t *modelFsm);
+EXTERN int McComputeOnionRingsWithClosestCore(mdd_t *aState, array_t *arrayOfOnionRings, Fsm_Fsm_t *modelFsm);
+EXTERN array_t * McRemoveIndexedOnionRings(int index, array_t *arrayOfOnionRings);
+EXTERN array_t * McConvertMintermToValueArray(mdd_t *aMinterm, array_t *aSupport, mdd_manager *mddMgr);
+EXTERN void McPrintTransition(mdd_t *aState, mdd_t *bState, mdd_t *uInput, mdd_t *vInput, array_t *stateSupport, array_t *inputSupport, boolean printInputs, Fsm_Fsm_t *modelFsm, int seqNumber);
+EXTERN void McPrintTransitionAiger(mdd_t *aState, mdd_t *bState, mdd_t *uInput, mdd_t *vInput, array_t *stateSupport, array_t *inputSupport, boolean printInputs, Fsm_Fsm_t *modelFsm, int seqNumber);
+EXTERN void McStatePassesFormula(mdd_t *aState, Ctlp_Formula_t *formula, McDbgLevel debugLevel, Fsm_Fsm_t *modelFsm);
+EXTERN void McStateFailsFormula(mdd_t *aState, Ctlp_Formula_t *formula, McDbgLevel debugLevel, Fsm_Fsm_t *modelFsm);
+EXTERN void McStatePassesOrFailsFormula(mdd_t *aState, Ctlp_Formula_t *formula, int pass, McDbgLevel debugLevel, Fsm_Fsm_t *modelFsm);
+EXTERN McPath_t * McPathNormalize(McPath_t *aPath);
+EXTERN array_t * McCreateMergedPath(array_t *aPath, array_t *bPath);
+EXTERN array_t * McCreateJoinedPath(array_t *aPath, array_t *bPath);
+EXTERN boolean McStateSatisfiesFormula(Ctlp_Formula_t *aFormula, mdd_t *aState);
+EXTERN boolean McStateTestMembership(mdd_t *aState, mdd_t *setOfStates);
+EXTERN mdd_t * McGetSuccessorInTarget(mdd_t *aState, mdd_t *targetStates, Fsm_Fsm_t *modelFsm);
+EXTERN mdd_t * McGetSuccessorInTargetAmongFairStates(mdd_t *aState, mdd_t *targetStates, array_t *arrayOfOnionRings, Fsm_Fsm_t *modelFsm);
+EXTERN array_t * McPathReadStemArray(McPath_t *aPath);
+EXTERN array_t * McPathReadCycleArray(McPath_t *aPath);
+EXTERN void McPathSetStemArray(McPath_t *aPath, array_t *stemArray);
+EXTERN void McPathSetCycleArray(McPath_t *aPath, array_t *cycleArray);
+EXTERN McPath_t * McPathAlloc(void);
+EXTERN void McPathFree(McPath_t * aPath);
+EXTERN McOptions_t * McOptionsAlloc(void);
+EXTERN void McOptionsFree(McOptions_t *options);
+EXTERN Mc_LeMethod_t McOptionsReadLeMethod(McOptions_t *options);
+EXTERN McDbgLevel McOptionsReadDbgLevel(McOptions_t *options);
+EXTERN FILE * McOptionsReadGuideFile(McOptions_t *options);
+EXTERN FILE * McOptionsReadSystemFile(McOptions_t *options);
+EXTERN int McOptionsReadTimeOutPeriod(McOptions_t *options);
+EXTERN Mc_VerbosityLevel McOptionsReadVerbosityLevel(McOptions_t *options);
+EXTERN Mc_DcLevel McOptionsReadDcLevel(McOptions_t *options);
+EXTERN FILE * McOptionsReadCtlFile(McOptions_t *options);
+EXTERN FILE * McOptionsReadDebugFile(McOptions_t *options);
+EXTERN int McOptionsReadSimValue(McOptions_t *options);
+EXTERN int McOptionsReadUseMore(McOptions_t *options);
+EXTERN int McOptionsReadReduceFsm(McOptions_t *options);
+EXTERN int McOptionsReadPrintInputs(McOptions_t *options);
+EXTERN boolean McOptionsReadUseFormulaTree(McOptions_t *options);
+EXTERN Mc_GSHScheduleType McOptionsReadSchedule(McOptions_t *options);
+EXTERN int McOptionsReadLockstep(McOptions_t *options);
+EXTERN Fsm_RchType_t McOptionsReadInvarApproxFlag(McOptions_t *options);
+EXTERN boolean McOptionsReadInvarOnionRingsFlag(McOptions_t *options);
+EXTERN Mc_FwdBwdAnalysis McOptionsReadFwdBwd(McOptions_t *options);
+EXTERN Mc_FwdBwdAnalysis McOptionsReadTraversalDirection(McOptions_t *options);
+EXTERN Fsm_ArdcOptions_t * McOptionsReadArdcOptions(McOptions_t *options);
+EXTERN int McOptionsReadCoverageHoskote(McOptions_t *options);
+EXTERN int McOptionsReadCoverageImproved(McOptions_t *options);
+EXTERN void McOptionsSetFwdBwd(McOptions_t *options, Mc_FwdBwdAnalysis fwdBwd);
+EXTERN void McOptionsSetGuideFile(McOptions_t *options, FILE *guideFile);
+EXTERN void McOptionsSetTraversalDirection(McOptions_t *options, Mc_FwdBwdAnalysis fwdBwd);
+EXTERN void McOptionsSetUseMore(McOptions_t *options, boolean useMore);
+EXTERN void McOptionsSetReduceFsm(McOptions_t *options, boolean reduceFsm);
+EXTERN void McOptionsSetPrintInputs(McOptions_t *options, boolean printInputs);
+EXTERN void McOptionsSetUseFormulaTree(McOptions_t *options, boolean useFormulaTree);
+EXTERN void McOptionsSetSchedule(McOptions_t *options, Mc_GSHScheduleType schedule);
+EXTERN void McOptionsSetLockstep(McOptions_t *options, int lockstep);
+EXTERN void McOptionsSetSimValue(McOptions_t *options, boolean simValue);
+EXTERN void McOptionsSetDbgLevel(McOptions_t *options, McDbgLevel dbgLevel);
+EXTERN void McOptionsSetVerbosityLevel(McOptions_t *options, Mc_VerbosityLevel verbosityLevel);
+EXTERN void McOptionsSetLeMethod(McOptions_t *options, Mc_LeMethod_t leMethod);
+EXTERN void McOptionsSetDcLevel(McOptions_t *options, Mc_DcLevel dcLevel);
+EXTERN void McOptionsSetArdcOptions(McOptions_t *options, Fsm_ArdcOptions_t *ardcOptions);
+EXTERN void McOptionsSetInvarOnionRingsFlag(McOptions_t *options, int shellFlag);
+EXTERN void McOptionsSetCtlFile(McOptions_t *options, FILE *file);
+EXTERN void McOptionsSetDebugFile(McOptions_t *options, FILE *file);
+EXTERN void McOptionsSetTimeOutPeriod(McOptions_t *options, int timeOutPeriod);
+EXTERN void McOptionsSetInvarApproxFlag(McOptions_t *options, Fsm_RchType_t approxFlag);
+EXTERN void McOptionsSetCoverageHoskote(McOptions_t *options, boolean doCoverageHoskote);
+EXTERN void McOptionsSetCoverageImproved(McOptions_t *options, boolean doCoverageImproved);
+EXTERN void McOptionsSetVacuityDetect(McOptions_t *options, boolean vd);
+EXTERN boolean McOptionsReadVacuityDetect(McOptions_t *options);
+EXTERN void McOptionsSetBeerMethod(McOptions_t *options, boolean beer);
+EXTERN int McOptionsReadBeerMethod(McOptions_t *options);
+EXTERN void McOptionsSetFAFWFlag(McOptions_t *options, boolean FAFWFlag);
+EXTERN void McOptionsSetVariablesForSystem(McOptions_t *options, FILE  *systemFile);
+EXTERN boolean McQueryContinue(char *query);
+EXTERN void McPrintSupport(mdd_t *aMdd, mdd_manager *mddMgr, Ntk_Network_t *aNetwork);
+EXTERN int McPrintSimPath(FILE *outputFile, array_t *aPath, Fsm_Fsm_t *modelFsm);
+EXTERN Fsm_Fsm_t * McConstructReducedFsm(Ntk_Network_t *network, array_t *ctlFormulaArray);
+EXTERN Mc_EarlyTermination_t * McObtainUpdatedEarlyTerminationCondition(Mc_EarlyTermination_t *earlyTermination, mdd_t *careStates, Ctlp_FormulaType formulaType);
+EXTERN boolean McCheckEarlyTerminationForUnderapprox(Mc_EarlyTermination_t *earlyTermination, mdd_t *underApprox, array_t *careStatesArray);
+EXTERN boolean McCheckEarlyTerminationForOverapprox(Mc_EarlyTermination_t *earlyTermination, mdd_t *overApprox, array_t *careStatesArray);
+EXTERN mdd_t * McComputeACloseMinterm(mdd_t *aSet, mdd_t *target, array_t *Support, mdd_manager *mddMgr);
+EXTERN mdd_t * McComputeACloseState(mdd_t *states, mdd_t *target, Fsm_Fsm_t *modelFsm);
+EXTERN Mc_GSHScheduleType McStringConvertToScheduleType(char *string);
+EXTERN int McStringConvertToLockstepMode(char *string);
+EXTERN array_t *McMddArrayDuplicateFAFW(array_t *aPath);
+EXTERN void McNormalizeBddPointer(array_t *bddArray);
+
+EXTERN mdd_t *McMddArrayAnd(array_t *mddArray);
+EXTERN mdd_t *McMddArrayOr(array_t *mddArray);
+EXTERN mdd_t *McComputeAbstractStates(Fsm_Fsm_t *absFsm, mdd_t *reachableStates);
+EXTERN boolean McGetDncEnabled(void);
+EXTERN array_t * Mc_BuildForwardRings(mdd_t *S, Fsm_Fsm_t *fsm, array_t *onionRings); 
+EXTERN void Mc_CheckPathToCore(Fsm_Fsm_t *fsm, array_t *pathToCore);
+EXTERN void Mc_CheckPathFromCore(Fsm_Fsm_t *fsm, array_t *pathFromCore);
+EXTERN void Mc_PrintStates( Fsm_Fsm_t *modelFsm, mdd_t *states);
+EXTERN void Mc_PrintNumStates( Fsm_Fsm_t *modelFsm, mdd_t *states);
+EXTERN void Mc_PrintRings( Fsm_Fsm_t *modelFsm, array_t *onionRings);
+EXTERN void Mc_PrintNumRings( Fsm_Fsm_t *modelFsm, array_t *onionRings);
+EXTERN boolean McPrintPassFail(mdd_manager *mddMgr, Fsm_Fsm_t *modelFsm, Mc_FwdBwdAnalysis traversalDirection, Ctlp_Formula_t *ctlFormula, mdd_t *ctlFormulaStates, mdd_t *modelInitialStates, array_t *modelCareStatesArray, McOptions_t *options, Mc_VerbosityLevel verbosity);
+EXTERN mdd_t * McModelCheckAtomicFormula(Fsm_Fsm_t *modelFsm, Ctlp_Formula_t *ctlFormula);
+EXTERN void InvarPrintDebugInformation(Fsm_Fsm_t *modelFsm, array_t *invarFormulaArray, array_t *invarStatesArray, int *resultArray, McOptions_t *options, array_t *hintsStatesArray);
+EXTERN array_t * SortFormulasByFsm(Fsm_Fsm_t *totalFsm, array_t *invarFormulaArray, array_t *fsmArray, McOptions_t *options);
+EXTERN int TestInvariantsInTotalFsm(Fsm_Fsm_t *totalFsm, array_t *invarStatesArray, int shellFlag);
+EXTERN void McEstimateCoverage(Fsm_Fsm_t *modelFsm, Ctlp_Formula_t *ctlFormula, int i, mdd_t *fairStates, Fsm_Fairness_t *fairCond, array_t *modelCareStatesArray, Mc_EarlyTermination_t *earlyTermination, array_t *hintsStatesArray, Mc_GuidedSearch_t guidedSearchType, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, int buildOnionRings, Mc_GSHScheduleType GSHschedule, Mc_FwdBwdAnalysis traversalDirection, mdd_t *modelInitialStates, mdd_t *ctlFormulaStates, mdd_t **totalcoveredstates, array_t *signalTypeList, array_t *signalList, array_t *statesCoveredList, array_t *newCoveredStatesList, array_t *statesToRemoveList, boolean performCoverageHoskote, boolean performCoverageImproved);
+EXTERN void McPrintCoverageSummary(Fsm_Fsm_t *modelFsm, Mc_DcLevel dcLevel, McOptions_t *options, array_t *modelCareStatesArray, mdd_t *modelCareStates, mdd_t *totalcoveredstates, array_t *signalTypeList, array_t *signalList, array_t *statesCoveredList, boolean performCoverageHoskote, boolean performCoverageImproved);
+EXTERN Ctlp_Approx_t ComputeResultingApproximation(Ctlp_FormulaType formulaType, Ctlp_Approx_t leftApproxType, Ctlp_Approx_t rightApproxType, Ctlp_Approx_t TRMinimization, Mc_EarlyTermination_t *earlyTermination, boolean fixpoint);
+EXTERN void McVacuityDetection(Fsm_Fsm_t *modelFsm, Ctlp_Formula_t *ctlFormula, int i, mdd_t *fairStates, Fsm_Fairness_t *fairCond, array_t *modelCareStatesArray, Mc_EarlyTermination_t *earlyTermination, array_t *hintsStatesArray, Mc_GuidedSearch_t guidedSearchType, mdd_t *modelInitialStates, McOptions_t *options);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _MCINT */
Index: vis_dev/vis-2.3/src/mc/mcMc.c
===================================================================
--- vis_dev/vis-2.3/src/mc/mcMc.c	(revision 14)
+++ vis_dev/vis-2.3/src/mc/mcMc.c	(revision 14)
@@ -0,0 +1,4112 @@
+/**CFile***********************************************************************
+
+  FileName    [mcMc.c]
+
+  PackageName [mc]
+
+  Synopsis    [Fair CTL model checker.]
+
+  Description [This file contains the functions for both backward and
+  forward model checking. Forward model checking is based on Iwashta's
+  ICCAD96 paper. Future tense CTLs are automatically converted to past
+  tense ones as much as possible in forward model checking.]
+
+  Author [Adnan Aziz, Tom Shiple, Rajeev Ranjan, In-Ho Moon, Roderick Bloem]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ctlpInt.h"
+#include "mcInt.h"
+#include "fsm.h"
+#include "bmc.h"
+
+static char rcsid[] UNUSED = "$Id: mcMc.c,v 1.257 2007/04/17 00:01:22 sohail Exp $";
+
+#ifdef DEBUG_MC
+void _McPrintSatisfyingMinterms(mdd_t *aMdd, Fsm_Fsm_t *fsm);
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static mdd_t * EvaluateFormulaRecur(Fsm_Fsm_t *modelFsm, Ctlp_Formula_t *ctlFormula, mdd_t *fairStates, Fsm_Fairness_t *fairCondition, array_t *modelCareStatesArray, Mc_EarlyTermination_t *earlyTermination, Fsm_HintsArray_t *hintsArray, Mc_GuidedSearch_t hintType, Ctlp_Approx_t TRMinimization, Ctlp_Approx_t *resultApproxType, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, int buildOnionRings, Mc_GSHScheduleType GSHschedule);
+static mdd_t * McForwardReachable(Fsm_Fsm_t *modelFsm, mdd_t *targetMdd, mdd_t *invariantMdd, mdd_t *fairStates, array_t *careStatesArray, array_t *onionRings, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Compute all the states that lead to a fair cycle]
+
+  Comment  [Used by LE/LTL/CTL* model checking. Different dicision procedures 
+  are applied according to the "strength of the  buechi automaton": For the 
+  strong automaton, we need to compute EG(true) under the fairness constraints;
+  If the automaton is weak, we will check !EFEG(fair); If the automaton is 
+  terminal, we only need to check !EF(fair). This is based on the CAV'99 paper
+  of Bloem, Ravi & Somenzi: "Efficient Decision Procedures for Model Checking 
+  of Linear Time Logic Properties".
+  
+  Debugging information will be print out if dbgLevel is non-zero.
+
+  Return the set of initial states from where fair paths exist.]
+  
+  SideEffects [The caller should free the returned mdd_t.]
+
+******************************************************************************/
+mdd_t *
+Mc_FsmCheckLanguageEmptiness(
+  Fsm_Fsm_t *modelFsm,
+  array_t *modelCareStatesArray,
+  Mc_AutStrength_t automatonStrength,
+  Mc_LeMethod_t leMethod,
+  int dcLevel,
+  int dbgLevel,
+  int printInputs,
+  int verbosity,
+  Mc_GSHScheduleType GSHschedule,
+  Mc_FwdBwdAnalysis GSHdirection,
+  int lockstep,
+  FILE *dbgFile,
+  int UseMore,
+  int SimValue,
+  char *driverName)
+{
+  mdd_t *result;
+  mdd_t *mddOne;
+  mdd_t *badStates;
+  mdd_t *aBadState;
+  mdd_t *initialStates;
+  mdd_t *fairStates;
+  mdd_manager *mddMgr;
+  Ctlp_Formula_t *ctlFair, *ctlFormula;
+  Mc_EarlyTermination_t *earlyTermination;
+  array_t *arrayOfOnionRings;
+  array_t *stemArray;
+  array_t *cycleArray;
+  McPath_t *fairPath;
+  McPath_t *normalPath;
+  FILE *tmpFile = vis_stdout;
+  extern FILE *vis_stdpipe;
+  int i;
+
+  if (leMethod == Mc_Le_Dnc_c && automatonStrength == 2) {
+    return  Mc_FsmCheckLanguageEmptinessByDnC(modelFsm,
+					      modelCareStatesArray,
+					      Mc_Aut_Strong_c,
+					      dcLevel,
+					      dbgLevel,
+					      printInputs,
+					      verbosity,
+					      GSHschedule,
+					      GSHdirection,
+					      lockstep,
+					      dbgFile,
+					      UseMore,
+					      SimValue,
+					      driverName);
+  }
+  
+  /**************************************************************************
+   * CASE1 & CASE2: TERMINAL/WEAK AUTOMATON
+   *                problem is reduced to checking !EF (fair) for TERMINAL
+   *                or !EF EG (fair) for WEAK
+   **************************************************************************/
+  if (automatonStrength == 0 || automatonStrength == 1) {
+    Fsm_Fairness_t *modelFairness;
+    modelFairness = Fsm_FsmReadFairnessConstraint(modelFsm);
+    assert(Fsm_FairnessTestIsBuchi(modelFairness));
+    ctlFair = Ctlp_FormulaCreate(Ctlp_ID_c,
+				 (void *)util_strsav("fair1$AUT$NTK2"),
+				 (void *)util_strsav("1"));
+    /*    Dup(Fsm_FairnessReadFinallyInfFormula(modelFairness, 0, 0));    */
+    if (automatonStrength == 0) {
+      Ctlp_Formula_t *ctlTRUE;
+      ctlTRUE = Ctlp_FormulaCreate(Ctlp_TRUE_c, NIL(Ctlp_Formula_t),
+				   NIL(Ctlp_Formula_t));
+      ctlFormula = Ctlp_FormulaCreate(Ctlp_EU_c, ctlTRUE, ctlFair);
+      if (dbgLevel || verbosity) 
+	fprintf(vis_stdout, "# %s: Terminal automaton -- check EF(states satisfy fairness)\n",
+		driverName);
+    }else {
+      Ctlp_Formula_t *ctlTRUE, *ctlEGfair;
+      ctlTRUE = Ctlp_FormulaCreate(Ctlp_TRUE_c, NIL(Ctlp_Formula_t), NIL(Ctlp_Formula_t));
+      ctlEGfair = Ctlp_FormulaCreate(Ctlp_EG_c, ctlFair, NIL(Ctlp_Formula_t));
+      ctlFormula = Ctlp_FormulaCreate(Ctlp_EU_c, ctlTRUE, ctlEGfair);
+      if (dbgLevel || verbosity) 
+	fprintf(vis_stdout, "# %s: Weak automaton -- check EF EG (states satisfy fairness)\n",
+		driverName);
+    }
+
+    /* Evaluate ctlFormula */
+    mddMgr = Fsm_FsmReadMddManager(modelFsm);
+    mddOne = mdd_one(mddMgr);
+    initialStates = Fsm_FsmComputeInitialStates(modelFsm);
+    earlyTermination = Mc_EarlyTerminationAlloc(McSome_c, initialStates);
+    fairStates = 
+      Mc_FsmEvaluateFormula(modelFsm, ctlFormula, mddOne, modelFairness, 
+			    modelCareStatesArray,
+			    earlyTermination,
+			    NIL(Fsm_HintsArray_t), Mc_None_c,
+			    (Mc_VerbosityLevel) verbosity,
+			    (Mc_DcLevel) dcLevel, 
+			    (dbgLevel != McDbgLevelNone_c || verbosity),
+			    GSHschedule);
+    Mc_EarlyTerminationFree(earlyTermination);
+    mdd_free(mddOne);
+
+    /* If there is at least one fair initial state, language is not empty. */
+    if (!mdd_lequal(initialStates, fairStates, 1, 0)) {
+      if (strcmp(driverName, "LE") == 0)
+	fprintf(vis_stdout, "# LE: language is not empty\n");
+      else
+	fprintf(vis_stdout, "# %s: formula failed\n", driverName);
+      result = mdd_and(fairStates, initialStates, 1, 1);
+    } else {
+      if (strcmp(driverName, "LE") == 0)
+	fprintf(vis_stdout, "# LE: language emptiness check passes\n");
+      else
+	fprintf(vis_stdout, "# %s: formula passed\n", driverName);
+      Ctlp_FormulaFree(ctlFormula);
+      mdd_free(fairStates);
+      mdd_free(initialStates);
+      return NIL(mdd_t);
+    }
+
+    /* If no wintness is requested, clean up and return. */
+    if (dbgLevel == McDbgLevelNone_c) {
+      Ctlp_FormulaFree(ctlFormula);
+      mdd_free(initialStates);
+      mdd_free(fairStates);
+      return result;
+    }else {
+      Ctlp_Formula_t *F;
+      array_t *EGArrayOfOnionRings, *EGonionRings, *EFonionRings;
+      array_t *newOnionRings;
+      mdd_t *mdd1;
+      int j;
+      arrayOfOnionRings = array_alloc(array_t *, 0);
+      EFonionRings = (array_t *) Ctlp_FormulaReadDebugData(ctlFormula);
+      if (automatonStrength == 0) {
+	array_insert_last(array_t *, arrayOfOnionRings,
+			  mdd_array_duplicate(EFonionRings));
+      }else if (automatonStrength == 1) {
+        F = Ctlp_FormulaReadRightChild(ctlFormula);
+	/* EG (states labelled fair) */
+	EGArrayOfOnionRings = (array_t *)Ctlp_FormulaReadDebugData(F);
+	arrayForEachItem(array_t *, EGArrayOfOnionRings, i, EGonionRings) {
+	  newOnionRings = mdd_array_duplicate(EGonionRings);
+	  arrayForEachItem(mdd_t *, EFonionRings, j, mdd1) {
+	    if (j != 0)
+	      array_insert_last(mdd_t *, newOnionRings, mdd_dup(mdd1));
+	  }
+	  array_insert_last(array_t *, arrayOfOnionRings, newOnionRings);
+	}
+      }
+      Ctlp_FormulaFree(ctlFormula);
+      fprintf(vis_stdout, "# %s: generating path to fair cycle\n", driverName);
+    }
+    
+  }else {
+    /*************************************************************************
+     * CASE3:     STRONG AUTOMATON 
+     *            need to solve the problem by computing EG_fair (true) 
+     *************************************************************************/
+    mddMgr = Fsm_FsmReadMddManager(modelFsm);
+    initialStates = Fsm_FsmComputeInitialStates(modelFsm);
+
+    /* Compute fair states. */
+    if (lockstep == MC_LOCKSTEP_OFF) {
+      fairStates = Fsm_FsmComputeFairStates(modelFsm, modelCareStatesArray,
+					    verbosity, dcLevel, GSHschedule,
+					    GSHdirection, FALSE);
+      arrayOfOnionRings = Fsm_FsmReadDebugArray(modelFsm);
+    } else {
+      /* For lockstep, the computed set of states is a subset of the
+	 reachable fair states, with the property that the subset is
+	 empty only if there are no reachable fair states.  Since the
+	 onion rings are built for the fairness constraint restricted to
+	 the subset of the fair states, they are not valid in general
+	 for the FSM.  Hence, they are not saved.  */
+      array_t *SCCs = array_alloc(mdd_t *, 0);
+      arrayOfOnionRings = array_alloc(array_t *, 0);
+      fairStates = McFsmComputeFairSCCsByLockStep(modelFsm, lockstep, SCCs,
+						  arrayOfOnionRings,
+						  (Mc_VerbosityLevel)
+						  verbosity,
+						  (Mc_DcLevel) dcLevel);
+      mdd_array_free(SCCs);
+    }
+
+    
+    /* Lockstep guarantees that all fair SCCs are reachable.  However,
+       it does not extend the fair states backward unless a
+       counterexample is requested.  For the SCC hull approach with backward
+       operators, the language is not empty if there is at least one
+       fair initial state.  Finally, For SCC hull with forward operators,
+       currently we do not extend the hull backward, but we enforce
+       reachability of the hull.  Hence, nonemptiness of the hull signals that
+       the language is not empty. */
+    if ((lockstep == MC_LOCKSTEP_OFF &&
+	 (!mdd_lequal(initialStates, fairStates, 1, 0) ||
+	  (GSHdirection == McFwd_c &&
+	   !mdd_lequal_array(fairStates, modelCareStatesArray, 1, 0)))) ||
+	(lockstep != MC_LOCKSTEP_OFF &&
+	 !mdd_is_tautology(fairStates, 0))) {
+      if (strcmp(driverName, "LE") == 0)
+	fprintf(vis_stdout, "# LE: language is not empty\n");
+      else
+	fprintf(vis_stdout, "# %s: formula failed\n", driverName);
+      result = mdd_and(fairStates, initialStates, 1, 1);
+    } else {
+      if (strcmp(driverName, "LE") == 0)
+	fprintf(vis_stdout, "# LE: language emptiness check passes\n");
+      else
+	fprintf(vis_stdout, "# %s: formula passed\n", driverName);
+      /* Dispose of onion rings if produced by lockstep. */
+      if (lockstep != MC_LOCKSTEP_OFF) {
+	mdd_array_array_free(arrayOfOnionRings);
+      }
+      mdd_free(fairStates);
+      mdd_free(initialStates);
+      return NIL(mdd_t);
+    }
+
+    /* If no witness is requested, clean up and return. */
+    if (dbgLevel == McDbgLevelNone_c) {
+      /* Dispose of onion rings if produced by lockstep. */
+      if (lockstep != MC_LOCKSTEP_OFF) {
+	mdd_array_array_free(arrayOfOnionRings);
+      }
+      mdd_free(fairStates);
+      mdd_free(initialStates);
+      return result;
+    } else {
+      (void) fprintf(vis_stdout, "# %s: generating path to fair cycle\n",
+		     driverName);
+    }
+  }
+
+  /* Generate witness. */
+  badStates = mdd_and(initialStates, fairStates, 1, 1);
+  mdd_free(fairStates);
+  mdd_free(initialStates);
+  aBadState = Mc_ComputeAState(badStates, modelFsm);
+  mdd_free(badStates);
+
+  mddOne = mdd_one(mddMgr);
+  fairPath = McBuildFairPath(aBadState, mddOne, arrayOfOnionRings, modelFsm,
+			     modelCareStatesArray, 
+			     (Mc_VerbosityLevel) verbosity,
+			     (Mc_DcLevel) dcLevel,
+			     McFwd_c);
+  mdd_free(mddOne);
+  mdd_free(aBadState);
+  
+  /* Dispose of onion rings if produced by lockstep. */
+  if (lockstep != MC_LOCKSTEP_OFF || automatonStrength != 2) {
+    mdd_array_array_free(arrayOfOnionRings);
+  }
+
+  /* Print witness. */
+  normalPath = McPathNormalize(fairPath);
+  McPathFree(fairPath);
+
+  stemArray = McPathReadStemArray(normalPath);
+  cycleArray = McPathReadCycleArray(normalPath);
+
+  /* we should pass dbgFile/UseMore as parameters 
+     dbgFile = McOptionsReadDebugFile(options);*/
+  if (dbgFile != NIL(FILE)) {
+    vis_stdpipe = dbgFile;
+  } else if (UseMore == TRUE) {
+    vis_stdpipe = popen("more","w");
+  } else {
+    vis_stdpipe = vis_stdout;
+  }
+  vis_stdout = vis_stdpipe;
+
+  /* We should also pass SimValue as a parameter */
+  if (SimValue == FALSE) {
+      (void) fprintf(vis_stdout, "# %s: path to fair cycle:\n\n", driverName);
+      Mc_PrintPath(stemArray, modelFsm, printInputs);
+      fprintf (vis_stdout, "\n");
+
+      (void) fprintf(vis_stdout, "# %s: fair cycle:\n\n", driverName);
+      Mc_PrintPath(cycleArray, modelFsm, printInputs);
+      fprintf (vis_stdout, "\n");
+  }else {
+      array_t *completePath = McCreateMergedPath(stemArray, cycleArray);
+      (void) fprintf(vis_stdout, "# %s: counter-example\n", driverName);
+      McPrintSimPath(vis_stdout, completePath, modelFsm);
+      mdd_array_free(completePath);
+  }
+
+  if (dbgFile == NIL(FILE) && UseMore == TRUE) {
+    (void) pclose(vis_stdpipe);
+  }  
+  vis_stdout = tmpFile;
+
+  McPathFree(normalPath);
+
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Model check formula on given FSM under fairness]
+
+  Description [Model check formula on given FSM under fairness.]
+
+  Comment [ Recursive evaluation using Emerson-Lei LICS 1986 algorithms. The
+  states satisfying subformulas are stored and used later if there is sharing
+  of subformulas. Therefore, each subformula is computed just once. Large
+  switch - base case is atomic formula, TRUE, and FALSE.  Boolean operators -
+  straightforward. Path modalities are reduced to one of the three - EX, EU,
+  EG which are evaluated under fairness. Note the semantics for atomic
+  formulas carefully - in addition to generating the prescribed output, the
+  state must also be fair. Don't cares from unreached, unfair states are both
+  used. The proof of correctness of using all these dont cares hinges on the
+  invariant that restricted to the reached state set, the computed sets are
+  exactly as they should be. Both backward and forward formulas are handled.
+
+  This function sets the states and debug info of the formula for use
+  with the debugger.
+  
+  ARGUMENTS:
+
+  ctlFormula: a ctl formula in simple(!) existential form, using
+  forward and/or backward operators.
+  
+  EarlyTermination: If earlyTermination.mode is McAll_c
+  (McSome_c), the algorithm can stop as soon as
+
+  1. it is sure that all (some) of earlyTermination.states are
+  included in the evaluation of the formula, or
+
+  2. It is sure that some (all) of these states are not included in
+  the evaluation.
+  
+  If earlyTermination.mode is McCare_c, then the algorithm can stop as
+  soon as it is guaranteed that either all or none of
+  earlyTermination.states are included in the evaluation.
+
+  These checks are done modulo the care set, but not modulo the fair
+  states, which means that they will not be effective if you
+  require unfair states to be in the evaluation.
+  Typically {ALL, initialStates} will be good. NULL means the option has no
+  effect.
+
+  Debugging only works if this function is called with {ALL,
+  initialStates}.  Otherwise, debugging of the EG formulae may go
+  wrong.
+
+  hintsArray is an array of hints.  Pass NULL and set hintType to
+  Mc_None_c to ignore.
+
+  If hintType is Mc_Global_c, then the formula is evaluated once for
+  each hint, where every hint defines an underapproximation of the
+  formula.  This only works for pure A/E CTL formulae.  If hintType is
+  Mc_Local_c, then every fixpoint goes through the sequence of hints
+  until completion, before moving up to the next temporal operator. 
+  
+  ]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Mc_FsmEvaluateFormula(
+  Fsm_Fsm_t *fsm,
+  Ctlp_Formula_t *ctlFormula,
+  mdd_t *fairStates,
+  Fsm_Fairness_t *fairCondition,
+  array_t *careStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  Fsm_HintsArray_t *hintsArray,
+  Mc_GuidedSearch_t hintType,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  int buildOnionRing,
+  Mc_GSHScheduleType GSHschedule)
+{
+  mdd_t *hint;      /* to iterate over hintsArray */
+  int   hintnr;     /* idem                       */
+  Ctlp_Approx_t resultApproxType;
+
+  assert(hintType == Mc_None_c || hintsArray != NIL(Fsm_HintsArray_t));
+  
+  if(hintType != Mc_Global_c)
+    return EvaluateFormulaRecur(fsm, ctlFormula, fairStates,
+				fairCondition, careStatesArray,
+				earlyTermination, hintsArray, hintType,
+				Ctlp_Exact_c, &resultApproxType,
+				verbosity, dcLevel,
+				buildOnionRing, GSHschedule);
+  else{
+    mdd_t *result = NIL(mdd_t);
+    Ctlp_Approx_t approx;
+
+    if(verbosity >= McVerbosityMax_c)
+      fprintf(vis_stdout, "--Using global hints\n");
+    
+    arrayForEachItem(mdd_t *, hintsArray, hintnr, hint){
+      if(result != NIL(mdd_t))
+	mdd_free(result);
+      
+      if(verbosity >= McVerbosityMax_c)
+	fprintf(vis_stdout, "--Instantiating global hint %d\n", hintnr);
+
+      Fsm_InstantiateHint(fsm, hint, FALSE, TRUE, Ctlp_Underapprox_c,
+			  (verbosity >= McVerbosityMax_c));
+
+      approx = mdd_is_tautology(hint, 1) ? Ctlp_Exact_c : Ctlp_Underapprox_c;
+
+      result = EvaluateFormulaRecur(fsm, ctlFormula, fairStates,
+				    fairCondition, careStatesArray,
+				    earlyTermination, hintsArray, hintType,
+				    approx, &resultApproxType, verbosity,
+				    dcLevel, buildOnionRing, GSHschedule); 
+      /* TBD: take into account (early) termination here */
+    }
+    Fsm_CleanUpHints(fsm, FALSE, TRUE, (verbosity >= McVerbosityMax_c));
+
+    return result;
+  }
+
+} /* Mc_FsmEvaluateFormula */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Evaluate states satisfying EX target]
+
+  Description [Evaluate states satisfying EX target.  Basically, calls
+  the image package -- all the smarts are in there, parameters for it
+  can be set from the VIS prompt.  In the presence of fairness, a
+  state satisifies EX foo just in case it has a sucessor where foo is
+  true AND that successor can be continued to an infinite path which
+  is fair.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Mc_FsmEvaluateEXFormula(
+  Fsm_Fsm_t *modelFsm,
+  mdd_t *targetMdd,
+  mdd_t *fairStates,
+  array_t *careStatesArray,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel)
+{
+  mdd_t *fromLowerBound;
+  mdd_t *fromUpperBound;
+  mdd_t *result;
+  Img_ImageInfo_t * imageInfo;
+  
+  if(Fsm_FsmReadUseUnquantifiedFlag(modelFsm))
+    imageInfo = Fsm_FsmReadOrCreateImageInfoFAFW(modelFsm, 1, 0);
+  else
+    imageInfo = Fsm_FsmReadOrCreateImageInfo(modelFsm, 1, 0);
+
+  /*
+   * The lower bound is the conjunction of the fair states,
+   * and the target states.
+   */
+  fromLowerBound = mdd_and(targetMdd, fairStates, 1, 1);
+  /*
+   * The upper bound is the same as the lower bound.
+   */
+  fromUpperBound = mdd_dup(fromLowerBound);
+
+  result = Img_ImageInfoComputePreImageWithDomainVars(imageInfo,
+		fromLowerBound, fromUpperBound, careStatesArray);
+  mdd_free(fromLowerBound);
+  mdd_free(fromUpperBound);
+
+  if (verbosity == McVerbosityMax_c) {
+    static int refCount=0;
+    mdd_manager *mddMgr = Fsm_FsmReadMddManager(modelFsm);
+    array_t *psVars = Fsm_FsmReadPresentStateVars(modelFsm);
+    mdd_t *tmpMdd = careStatesArray ?
+	mdd_and_array(result, careStatesArray, 1, 1) : mdd_dup(result);
+    fprintf(vis_stdout, "--EX called %d (bdd_size - %d)\n", ++refCount,
+	    mdd_size(result));
+    fprintf(vis_stdout, "--There are %.0f care states satisfying EX formula\n",
+	    mdd_count_onset(mddMgr, tmpMdd, psVars));
+    mdd_free(tmpMdd);
+  }
+
+  return result;
+
+} /* Mc_FsmEvaluateEXFormula */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Evaluate states satisfying MX target]
+
+  Description [Compute EX with transition relation that contains input varaibles
+               and then apply universial quantification to get MX target.
+               To use this function, one has to run 
+               Fsm_FsmReadOrCreateImageInfoFAFW to create the trasition relation
+	       that contains input variables. And Fsm_FsmSetUseUnquantifiedFlag 
+	       has to be called. That useUnquantifiedFlag is used to specify 
+	       which imageInfo can be used in image computation. 
+	       This is function for FateAndFreeWill counterexample generation.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Mc_FsmEvaluateMXFormula(
+  Fsm_Fsm_t *modelFsm,
+  mdd_t *targetMdd,
+  mdd_t *fairStates,
+  array_t *careStatesArray,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel)
+{
+  mdd_t *resultBar, *result;
+
+  result = Mc_FsmEvaluateEXFormula(modelFsm, targetMdd, fairStates,
+                                 careStatesArray, verbosity, dcLevel);
+
+  if(Fsm_FsmReadUniQuantifyInputCube(modelFsm)) {
+    resultBar = Mc_QuantifyInputFAFW(modelFsm, result);
+    mdd_free(result);
+    result = resultBar;
+  }
+
+  return(result);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Quantify the input variables]
+
+  Description [Quantify the input variables after applying EX.
+               To use this function, one has to run 
+               Fsm_FsmReadOrCreateImageInfoFAFW to create the trasition relation
+	       that contains input variables. 
+	       To get the result of real MX operation, the bdd_smooth_with_cube
+	       has to be applied after bdd_consensus_with_cube, but we need 
+	       those input variables for path generation. If one needs real MX 
+	       then bdd_smooth_with_cube has to be applied.
+	       This is function for FateAndFreeWill counterexample generation.]
+
+  SideEffects []
+
+******************************************************************************/
+bdd_t *
+Mc_QuantifyInputFAFW(Fsm_Fsm_t *fsm, bdd_t *result) 
+{
+  bdd_t *uniCube, *extCube, *newResult;
+  bdd_t *oneMdd, *notResult;
+  mdd_manager *mgr = Fsm_FsmReadMddManager(fsm);
+
+  oneMdd = mdd_one(mgr);
+  uniCube = Fsm_FsmReadUniQuantifyInputCube(fsm);
+  extCube = Fsm_FsmReadExtQuantifyInputCube(fsm);
+  if(!mdd_equal(uniCube, oneMdd)) {
+      /**
+    newResult = bdd_consensus_with_cube(result, uniCube); 
+    **/
+    notResult = bdd_not(result);
+    newResult = bdd_smooth_with_cube(notResult, uniCube); 
+    bdd_free(notResult);
+    result    = bdd_not(newResult);
+    bdd_free(newResult);
+  }
+  else {
+    result = mdd_dup(result);
+  }
+  mdd_free(oneMdd);
+  return(result);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Evaluate states satisfying EY target]
+
+  Description [Evaluate states satisfying EY target.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Mc_FsmEvaluateEYFormula(
+  Fsm_Fsm_t *modelFsm,
+  mdd_t *targetMdd,
+  mdd_t *fairStates,
+  array_t *careStatesArray,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel)
+{
+  mdd_t *fromLowerBound;
+  mdd_t *fromUpperBound;
+  mdd_t *result;
+
+  Img_ImageInfo_t * imageInfo = Fsm_FsmReadOrCreateImageInfo(modelFsm, 0, 1);
+
+  /*
+   * The lower bound is the conjunction of the fair states,
+   * and the target states.
+   */
+  fromLowerBound = mdd_and(targetMdd, fairStates, 1, 1);
+  /*
+   * The upper bound is the same as the lower bound.
+   */
+  fromUpperBound = fromLowerBound;
+
+  result = Img_ImageInfoComputeImageWithDomainVars(imageInfo,
+		fromLowerBound, fromUpperBound, careStatesArray);
+  mdd_free(fromLowerBound);
+
+  if (verbosity == McVerbosityMax_c) {
+    static int refCount=0;
+    mdd_manager *mddMgr = Fsm_FsmReadMddManager(modelFsm);
+    array_t *psVars = Fsm_FsmReadPresentStateVars(modelFsm);
+    mdd_t *tmpMdd = careStatesArray ?
+	mdd_and_array(result, careStatesArray, 1, 1) : mdd_dup(result);
+    fprintf(vis_stdout, "--EY called %d (bdd_size - %d)\n", ++refCount,
+	    mdd_size(result));
+    fprintf(vis_stdout, "--There are %.0f care states satisfying EY formula\n",
+	    mdd_count_onset(mddMgr, tmpMdd, psVars));
+    mdd_free(tmpMdd);
+  }
+
+  return result;
+
+} /* Mc_FsmEvaluateEYFormula */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Evaluate states satisfying E(invariant U target)]
+
+  Description [Evaluate states satisfying E(invariant U target).
+  Performed by a least fixed point computation -- start with target
+  AND fair, see what can get to this set by a path solely in
+  invariant.  If the onionRings array is not NIL(array_t *), the
+  ``onion rings'' arising in the least fixed point computation are
+  stored in the array, starting from the target.  The onion rings
+  explain how to get from any state in the result to the target.
+
+  The evaluation stops once all (some) of earlyTermination.states
+  have been found (depending on earlyTermination.mode).  See
+  Mc_FsmEvaluateFormula()
+
+  If underapprox is not NIL, it must hold a valid underapproximation
+  of the fixpoint.  This is used to kick off the new computation.
+
+  The arguments hintsArray and hints are used for guided search.  Set
+  hintType to Mc_None_c to ignore.  If hintType is Mc_Local_c,
+  hintsArray should be an array of mdds, of which the last entry is 1.
+  This array will be used to obtain underapproximations of the
+  transition system.  (See Mc_FsmEvaluateFormula.)
+
+  fixpoint is a return argument.  It is true if the formula is
+  evaluated exactly, false if early termination kicked in.  If
+  earlyTermination is NIL, the formula is evaluated exacty, and this
+  argument may be NIL too.
+
+  OnionRings is an array of mdd_t *.  It can be NULL, in which case no
+  onion rings are returned.  If it is not NULL, there are two
+  possibilities.  In the simple case, the onion rings are empty, and
+  underapprox is NULL.  In this case, the onion rings returned explain
+  how to get to the target from any state in the result returned (r).
+  If underapprox u is not NULL, the onion rings that are passed in
+  should explain how to get from any state in u to any state in the
+  target.  Rings will be added by the procudure to explain how to get
+  from the r to a state in underapprox, resulting in an explanation of
+  how to get from a state in r to the target.  ]
+
+  Comment     [Check that evaluation mod reached AND fair will lead to
+  faster convergence.  Also, it is possible there is more (?)
+  flexibility in dont care minimization - use only the layer of the
+  onion rings as set for evaluating EX.]
+
+  SideEffects []
+
+  SeeAlso [Mc_FsmEvaluateFormula, McEvaluateEUFormulaWithGivenTR]
+
+******************************************************************************/
+mdd_t *
+Mc_FsmEvaluateEUFormula(
+  Fsm_Fsm_t *fsm,
+  mdd_t *invariant,
+  mdd_t *target,
+  mdd_t *underapprox,
+  mdd_t *fairStates,
+  array_t *careStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  Fsm_HintsArray_t *hintsArray,
+  Mc_GuidedSearch_t hintType,
+  array_t *onionRings,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  boolean *fixpoint)
+{
+  /* should be strengthened to check that rings supply a correct explanation.
+   */
+  /*check out
+   *  assert(underapprox == NULL || onionRings == NULL ||
+   *	 array_n(onionRings) != 0);  */
+ 
+  if(hintType != Mc_Local_c)
+    /* postcondition: rings should explain how to get from return value to
+     * target.
+     */
+    return McEvaluateEUFormulaWithGivenTR(fsm, invariant, target,
+					  underapprox, fairStates,
+					  careStatesArray,
+					  earlyTermination, onionRings,
+					  verbosity, dcLevel, fixpoint);  
+  else{
+    mdd_t *iterate, *newiterate;
+    mdd_t *hint;
+    int hintnr;
+
+    if(verbosity >= McVerbosityMax_c)
+	fprintf(vis_stdout, "--Using local hints\n");
+
+    if(underapprox != NIL(mdd_t))
+      iterate = mdd_dup(underapprox);
+    else
+      iterate = mdd_zero(Fsm_FsmReadMddManager(fsm));
+
+    arrayForEachItem(mdd_t *, hintsArray, hintnr, hint){
+	if(verbosity >= McVerbosityMax_c)
+	    fprintf(vis_stdout, "--Instantiating local hint %d\n", hintnr);
+      Fsm_InstantiateHint(fsm, hint, FALSE, TRUE, Ctlp_Underapprox_c,
+ 			  (verbosity >= McVerbosityMax_c));
+      
+      newiterate =
+	McEvaluateEUFormulaWithGivenTR(fsm, invariant, target, iterate,
+				       fairStates, careStatesArray,
+				       earlyTermination, onionRings,
+				       verbosity, dcLevel, fixpoint);    
+      mdd_free(iterate);
+      iterate = newiterate;
+
+      /* check if we can terminate without considering all hints */ 
+      if(mdd_is_tautology(iterate, 1)){
+	*fixpoint = 1;
+	break;
+      }
+      if(McCheckEarlyTerminationForUnderapprox(earlyTermination, iterate,
+					       careStatesArray)){ 
+	*fixpoint = 0;
+	break;
+      }
+
+    }/* for all hints */
+    Fsm_CleanUpHints(fsm, FALSE, TRUE, (verbosity >= McVerbosityMax_c));
+
+    /* postcondition: rings should explain how to get from return value to
+     * target.
+     */
+    return iterate;
+  }/* if hinttype */
+
+} /* Mc_FsmEvaluateEUFormula */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Evaluate states satisfying E(invariant S source)]
+
+  Description [Evaluate states satisfying E(invariant U target).
+  Performed by a least fixed point computation -- start with source
+  AND fair, see what can be reached from this set by a path solely in
+  invariant.  If the onionRings array is not NIL(array_t *), the
+  ``onion rings'' arising in the least fixed point computation are
+  stored in the array, starting from the target.
+
+  The evaluation stops once all (some) of earlyTermination.states
+  have been found (depending on earlyTermination.mode).  See
+  Mc_FsmEvaluateFormula()
+
+  If underapprox is not NIL, it must hold a valid underapproximation
+  of the fixpoint.  This is used to kick off the new computation.
+
+  The arguments hintsArray and hints are used for guided search.  Set
+  hintType to Mc_None_c to ignore.  If hintType is Mc_Local_c,
+  hintsArray should be an array of mdds, of which the last entry is 1.
+  This array will be used to obtain underapproximations of the
+  transition system.  (See Mc_FsmEvaluateFormula.)
+
+  fixpoint is a return argument.  It is true if the formula is
+  evaluated exactly, false if early termination kicked in.  If
+  earlyTermination is NIL, the formula is evaluated exacty, and this
+  argument may be NIL too.
+
+  OnionRIngs is an array of mdd_t *.  It should be empty on call if
+  you want debug info, NULL otherwise.  After the call, it contains
+  the onion rings (frontier sets) that occured while computing the
+  ES.  This is used for debugging.]
+
+  Comment [Check that evaluation mod reached AND fair will lead to
+  faster convergence.  Also, it is possible there is more (?)
+  flexibility in don't care minimization - use only the layer of the
+  onion rings as set for evaluating EX.]
+
+  SideEffects []
+
+  SeeAlso [Mc_FsmEvaluateFormula, McEvaluateESFormulaWithGivenTR]
+
+******************************************************************************/
+mdd_t *
+Mc_FsmEvaluateESFormula(
+  Fsm_Fsm_t *fsm,
+  mdd_t *invariant,
+  mdd_t *source,
+  mdd_t *underapprox,
+  mdd_t *fairStates,
+  array_t *careStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  Fsm_HintsArray_t *hintsArray,
+  Mc_GuidedSearch_t hintType,
+  array_t *onionRings,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  boolean *fixpoint)
+{
+  /* should be strengthened to check that rings supply a correct explanation.
+   */
+  assert(underapprox == NULL || onionRings == NULL ||
+	 array_n(onionRings) != 0);
+
+  if(hintType != Mc_Local_c)
+    /* postcondition: rings should explain how to get from return value to
+     * target.
+     */
+    return McEvaluateESFormulaWithGivenTR(fsm, invariant, source,
+					  underapprox, fairStates,
+					  careStatesArray,
+					  earlyTermination, onionRings,
+					  verbosity, dcLevel, fixpoint);  
+  else{
+    mdd_t *iterate, *newiterate;
+    mdd_t *hint;
+    int hintnr;
+
+    if(verbosity >= McVerbosityMax_c)
+	fprintf(vis_stdout, "--Using local hints\n");
+
+    if(underapprox != NIL(mdd_t))
+      iterate = mdd_dup(underapprox);
+    else
+      iterate = mdd_zero(Fsm_FsmReadMddManager(fsm));
+
+    arrayForEachItem(mdd_t *, hintsArray, hintnr, hint){
+	if(verbosity >= McVerbosityMax_c)
+	    fprintf(vis_stdout, "--Instantiating local hint %d\n", hintnr);
+      Fsm_InstantiateHint(fsm, hint, FALSE, TRUE, Ctlp_Underapprox_c,
+ 			  (verbosity >= McVerbosityMax_c));
+      
+      newiterate =
+	McEvaluateESFormulaWithGivenTR(fsm, invariant, source, iterate,
+				       fairStates, careStatesArray,
+				       earlyTermination, onionRings,
+				       verbosity, dcLevel, fixpoint);    
+      mdd_free(iterate);
+      iterate = newiterate;
+
+      /* check if we can terminate without considering all hints */ 
+      if(mdd_is_tautology(iterate, 1)){
+	*fixpoint = 1;
+	break;
+      }
+      if(McCheckEarlyTerminationForUnderapprox(earlyTermination, iterate,
+					       careStatesArray)){ 
+	*fixpoint = 0;
+	break;
+      }
+
+    }/* for all hints */
+    Fsm_CleanUpHints(fsm, FALSE, TRUE, (verbosity >= McVerbosityMax_c));
+
+    /* postcondition: rings should explain how to get from return value to
+     * target.
+     */
+
+    return iterate;
+  }/* if hinttype */
+
+} /* Mc_FsmEvaluateESFormula */
+
+mdd_t *
+Mc_FsmEvaluateAUFormula(
+  Fsm_Fsm_t *fsm,
+  mdd_t *invariant,
+  mdd_t *target,
+  mdd_t *underapprox,
+  mdd_t *fairStates,
+  array_t *careStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  Fsm_HintsArray_t *hintsArray,
+  Mc_GuidedSearch_t hintType,
+  array_t *onionRings,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  boolean *fixpoint)
+{
+
+  return McEvaluateAUFormulaWithGivenTR(fsm, invariant, target,
+                                        underapprox, fairStates,
+                                        careStatesArray,
+                                        earlyTermination, onionRings,
+                                        verbosity, dcLevel, fixpoint);
+
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Evaluate states satisfying EG invariant]
+
+  Description [Evaluate states satisfying EG invariant.  This is done
+  by starting with all states marked with the invariant.  From this
+  initial set, recursively remove states that can not reach Buechi
+  contraints (through paths entirely within the current set).
+
+  If overapprox is not nil, then it is a valid overapproximation to the
+  satisfiable set of the formula that will be used to kick off the
+  computation.
+
+  pOnionRingsArrayForDbg is a pointer to (a pointer to) an array of
+  arrays of mdd_t *s.  Upon calling this formula, it should point to
+  an empty array if you want debug information, or be NIL (or a
+  pointer to NIL) if you do not.  After the call, it points to an
+  array that contains one entry for every fairness constraint: entry i
+  contains the onionrings for the last EU computation that was
+  performed for fairness constraint i.  There are two exceptions: if
+  the satisfying set is 0, or if early termination kicks in, the onion
+  ring array is not changed.
+
+  The arguments hintsArray and hints are used for guided search.  Set
+  hintType to Mc_None_c to ignore.  If hintType is Mc_Local_c,
+  hintsArray should be an array of mdds, of which the last entry is 1.
+  This array will be used to obtain overapproximations of the
+  transition system (See Mc_FsmEvaluateFormula).
+
+  fixpoint is a return argument.  It is true if the formula is
+  evaluated exactly, false if early termination kicked in.  If
+  earlyTermination is NIL, the formula is evaluated exacty, and this
+  argument may be NIL too.  See Mc_FsmEvaluateFormula for a discussion
+  of early termination.]
+
+  SideEffects []
+
+  SeeAlso     [Mc_FsmEvaluateFormula]
+
+******************************************************************************/
+mdd_t *
+Mc_FsmEvaluateEGFormula(
+  Fsm_Fsm_t *fsm,
+  mdd_t *invariant,
+  mdd_t *overapprox,
+  mdd_t *fairStates,
+  Fsm_Fairness_t *modelFairness,
+  array_t *careStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  Fsm_HintsArray_t *hintsArray,
+  Mc_GuidedSearch_t hintType,
+  array_t **pOnionRingsArrayForDbg,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  boolean *fixpoint,
+  Mc_GSHScheduleType GSHschedule)
+{
+  /* Illegal to pass in onion rings. */
+#if 0
+  assert(pOnionRingsArrayForDbg == NIL(array_t *) ||
+  *pOnionRingsArrayForDbg == NIL(array_t) ||
+  array_n(*pOnionRingsArrayForDbg) == 0);
+#endif
+  if(hintType != Mc_Local_c)
+    if (GSHschedule == McGSH_old_c) {
+      return McEvaluateEGFormulaWithGivenTR(fsm, invariant, overapprox,
+					    fairStates,
+					    modelFairness, careStatesArray,
+					    earlyTermination,
+					    pOnionRingsArrayForDbg,
+					    verbosity,
+					    dcLevel, fixpoint);
+    } else {
+      return McFsmEvaluateEGFormulaUsingGSH(fsm, invariant, overapprox,
+					    fairStates,
+					    modelFairness, careStatesArray,
+					    earlyTermination,
+					    pOnionRingsArrayForDbg, verbosity,
+					    dcLevel, fixpoint, GSHschedule);
+    }
+  else {
+    mdd_t *iterate, *newiterate;
+    mdd_t *hint;
+    int hintnr;
+    boolean useRings;
+
+    useRings = (pOnionRingsArrayForDbg != NIL(array_t *) &&
+		*pOnionRingsArrayForDbg != NIL(array_t));
+    
+    if(verbosity >= McVerbosityMax_c)
+	fprintf(vis_stdout, "** mc Info: Using local hints\n");
+
+    if(overapprox != NIL(mdd_t))
+      iterate = mdd_dup(overapprox);
+    else
+      iterate = mdd_one(Fsm_FsmReadMddManager(fsm));
+    
+    arrayForEachItem(mdd_t *, hintsArray, hintnr, hint){
+	if(verbosity >= McVerbosityMax_c)
+	    fprintf(vis_stdout, "--Instantiating local hint %d\n", hintnr);
+      Fsm_InstantiateHint(fsm, hint, FALSE, TRUE, Ctlp_Overapprox_c,
+ 			  (verbosity >= McVerbosityMax_c));
+
+      /* old onionrings go stale.  Fry 'em */
+      if(useRings){
+	mdd_array_array_free(*pOnionRingsArrayForDbg);
+	*pOnionRingsArrayForDbg = array_alloc(array_t *, 0);
+      }
+
+      if (GSHschedule == McGSH_old_c) {
+	newiterate =
+	  McEvaluateEGFormulaWithGivenTR(fsm, invariant, iterate, fairStates,
+					 modelFairness, careStatesArray,
+					 earlyTermination,
+					 pOnionRingsArrayForDbg,
+					 verbosity, dcLevel, fixpoint);
+      } else {
+	newiterate =
+	  McFsmEvaluateEGFormulaUsingGSH(fsm, invariant, iterate,
+					 fairStates,
+					 modelFairness, careStatesArray,
+					 earlyTermination,
+					 pOnionRingsArrayForDbg, verbosity,
+					 dcLevel, fixpoint, GSHschedule);
+      }
+      mdd_free(iterate);
+      iterate = newiterate;
+
+      /* check if we can terminate without considering all hints */ 
+      if(mdd_is_tautology(iterate, 0)){
+	*fixpoint = 1;
+	break;
+      }
+      if(McCheckEarlyTerminationForOverapprox(earlyTermination, iterate,
+					      careStatesArray)){  
+	*fixpoint = 0;
+	break;
+      }
+
+    } /* For all hints */
+    Fsm_CleanUpHints(fsm, FALSE, TRUE, (verbosity >= McVerbosityMax_c));
+
+    return iterate;
+  }/* if hinttype */
+
+} /* Mc_FsmEvaluateEGFormula */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Evaluate states satisfying EH invariant.]
+
+  Description [Evaluate states satisfying EH invariant.  This is done
+  by starting with all states marked with the invariant.  From this
+  initial set, recursively remove states that cannot reach Buechi
+  contraints (through paths entirely within the current set).
+
+  If overapprox is not nil, then it is a valid overapproximation to the
+  satisfiable set of the formula that will be used to kick off the
+  computation.
+
+  pOnionRingsArrayForDbg is a pointer to (a pointer to) an array of
+  arrays of mdd_t *s.  Upon calling this formula, it should point to
+  an empty array if you want debug information, or be NIL (or a
+  pointer to NIL) if you do not.  After the call, it points to an
+  array that contains one entry for every fairness constraint: entry i
+  contains the onionrings for the last ES computation that was
+  performed for fairness constraint i.  There are two exceptions: if
+  the satisfying set is 0, or if early termination kicks in, the onion
+  ring array is not changed.
+
+  The arguments hintsArray and hints are used for guided search.  Set
+  hintType to Mc_None_c to ignore.  If hintType is Mc_Local_c,
+  hintsArray should be an array of mdds, of which the last entry is 1.
+  This array will be used to obtain overapproximations of the
+  transition system (See Mc_FsmEvaluateFormula).
+
+  fixpoint is a return argument.  It is true if the formula is
+  evaluated exactly, false if early termination kicked in.  If
+  earlyTermination is NIL, the formula is evaluated exacty, and this
+  argument may be NIL too.  See Mc_FsmEvaluateFormula for a discussion
+  of early termination.]
+
+  SideEffects []
+
+  SeeAlso [Mc_FsmEvaluateFormula]
+
+******************************************************************************/
+mdd_t *
+Mc_FsmEvaluateEHFormula(
+  Fsm_Fsm_t *fsm,
+  mdd_t *invariant,
+  mdd_t *overapprox,
+  mdd_t *fairStates,
+  Fsm_Fairness_t *modelFairness,
+  array_t *careStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  Fsm_HintsArray_t *hintsArray,
+  Mc_GuidedSearch_t hintType,
+  array_t **pOnionRingsArrayForDbg,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  boolean *fixpoint,
+  Mc_GSHScheduleType GSHschedule)
+{
+  /* Illegal to pass in onion rings. */
+  assert(pOnionRingsArrayForDbg == NIL(array_t *) ||
+	 *pOnionRingsArrayForDbg == NIL(array_t) ||
+	 array_n(*pOnionRingsArrayForDbg) == 0);
+
+  if(hintType != Mc_Local_c)
+    if (GSHschedule == McGSH_old_c) {
+      return McEvaluateEHFormulaWithGivenTR(fsm, invariant, overapprox,
+					    fairStates,
+					    modelFairness, careStatesArray,
+					    earlyTermination,
+					    pOnionRingsArrayForDbg,
+					    verbosity,
+					    dcLevel, fixpoint);
+    } else {
+      return McFsmEvaluateEHFormulaUsingGSH(fsm, invariant, overapprox,
+					    fairStates,
+					    modelFairness, careStatesArray,
+					    earlyTermination,
+					    pOnionRingsArrayForDbg, verbosity,
+					    dcLevel, fixpoint, GSHschedule);
+    }
+  else {
+    mdd_t *iterate, *newiterate;
+    mdd_t *hint;
+    int hintnr;
+    boolean useRings;
+
+    useRings = (pOnionRingsArrayForDbg != NIL(array_t *) &&
+		*pOnionRingsArrayForDbg != NIL(array_t));
+    
+    if(verbosity >= McVerbosityMax_c)
+	fprintf(vis_stdout, "** mc Info: Using local hints\n");
+
+    if(overapprox != NIL(mdd_t))
+      iterate = mdd_dup(overapprox);
+    else
+      iterate = mdd_one(Fsm_FsmReadMddManager(fsm));
+    
+    arrayForEachItem(mdd_t *, hintsArray, hintnr, hint){
+	if(verbosity >= McVerbosityMax_c)
+	    fprintf(vis_stdout, "--Instantiating local hint %d\n", hintnr);
+      Fsm_InstantiateHint(fsm, hint, FALSE, TRUE, Ctlp_Overapprox_c,
+ 			  (verbosity >= McVerbosityMax_c));
+
+      /* old onionrings go stale.  Fry 'em */
+      if(useRings){
+	mdd_array_array_free(*pOnionRingsArrayForDbg);
+	*pOnionRingsArrayForDbg = array_alloc(array_t *, 0);
+      }
+
+      if (GSHschedule == McGSH_old_c) {
+	newiterate =
+	  McEvaluateEHFormulaWithGivenTR(fsm, invariant, iterate, fairStates,
+					 modelFairness, careStatesArray,
+					 earlyTermination,
+					 pOnionRingsArrayForDbg,
+					 verbosity, dcLevel, fixpoint);
+      } else {
+	newiterate =
+	  McFsmEvaluateEHFormulaUsingGSH(fsm, invariant, iterate,
+					 fairStates,
+					 modelFairness, careStatesArray,
+					 earlyTermination,
+					 pOnionRingsArrayForDbg, verbosity,
+					 dcLevel, fixpoint, GSHschedule);
+      }
+      mdd_free(iterate);
+      iterate = newiterate;
+
+      /* check if we can terminate without considering all hints */ 
+      if(mdd_is_tautology(iterate, 0)){
+	*fixpoint = 1;
+	break;
+      }
+      if(McCheckEarlyTerminationForOverapprox(earlyTermination, iterate,
+					      careStatesArray)){  
+	*fixpoint = 0;
+	break;
+      }
+
+    } /* For all hints */
+    Fsm_CleanUpHints(fsm, FALSE, TRUE, (verbosity >= McVerbosityMax_c));
+
+    return iterate;
+  }/* if hinttype */
+
+} /* Mc_FsmEvaluateEHFormula */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Evaluate states satisfying FwdUntil]
+
+  Description [Evaluate states satisfying FwdUntil.]
+
+  Comment []
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Mc_FsmEvaluateFwdUFormula(
+  Fsm_Fsm_t *modelFsm,
+  mdd_t *targetMdd,
+  mdd_t *invariantMdd,
+  mdd_t *fairStates,
+  array_t *careStatesArray,
+  array_t *onionRings,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel)
+{
+  mdd_t *aMdd;
+  mdd_t *bMdd;
+  mdd_t *cMdd;
+  mdd_t *resultMdd;
+  mdd_t *ringMdd;
+  int nImgComps;
+
+  /*							    t
+  ** E[p U q]      = lfp Z[q V (p ^ EX(Z))]   :   p p ... p q
+  ** FwdUntil(p,q) = lfp Z[p V EY(Z ^ q)]     :		    pq q q ... q
+  */
+
+  nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c);
+  resultMdd = mdd_and(targetMdd, fairStates, 1, 1);
+  ringMdd = mdd_dup(resultMdd);
+
+  /* if until is trivially satisfied, */
+  if (onionRings) {
+    array_insert_last(mdd_t *, onionRings, mdd_dup(resultMdd));
+  }
+  if (mdd_is_tautology(fairStates, 1)) {
+    if (mdd_equal_mod_care_set_array(invariantMdd, resultMdd, careStatesArray))
+    { 
+      bdd_free(ringMdd);
+      return(resultMdd);
+    }
+  } else {
+    bdd_t *trivialCheck = mdd_and(invariantMdd, fairStates, 1, 1);
+    if (mdd_equal_mod_care_set_array(trivialCheck, resultMdd, careStatesArray)) {
+      bdd_free(trivialCheck);
+      bdd_free(ringMdd);
+      return(resultMdd);
+    }
+    bdd_free(trivialCheck);
+  }
+
+  while (TRUE) {
+    aMdd = mdd_and(ringMdd, invariantMdd, 1, 1);
+    mdd_free(ringMdd);
+    bMdd = Mc_FsmEvaluateEYFormula(modelFsm, aMdd, fairStates, careStatesArray,
+				   verbosity, dcLevel);
+    mdd_free(aMdd);
+    cMdd = mdd_or(resultMdd, bMdd, 1, 1);
+    mdd_free(bMdd);
+
+    if (mdd_equal_mod_care_set_array(cMdd, resultMdd, careStatesArray)) {
+      mdd_free(cMdd);
+      break;
+    }
+
+    if (dcLevel >= McDcLevelRchFrontier_c) {
+      mdd_t *tmpMdd = mdd_and(resultMdd, cMdd, 0, 1);
+      ringMdd = bdd_between(tmpMdd, cMdd);
+      if (verbosity == McVerbosityMax_c) {
+	fprintf(vis_stdout,
+	  "-- FwdU |A(n+1)-A(n)| = %d\t|A(n+1)| = %d\t|between-dc| = %d\n",
+	  mdd_size(tmpMdd), mdd_size(resultMdd), mdd_size(ringMdd));
+      }
+      mdd_free(tmpMdd);
+    }
+    else {
+      ringMdd = mdd_dup(cMdd);
+      if (verbosity == McVerbosityMax_c) {
+	fprintf(vis_stdout, "-- FwdU |ringMdd| = %d\n", mdd_size(ringMdd));
+      }
+    }
+
+    mdd_free(resultMdd);
+    resultMdd = cMdd;
+    if (onionRings) {
+      array_insert_last(mdd_t *, onionRings, mdd_dup(resultMdd));
+    }
+  } /* while(!termination) for LFP */
+
+  /* Print some debug info */
+  if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) {
+    static int refCount=0;
+    mdd_manager *mddMgr = Fsm_FsmReadMddManager(modelFsm);
+    array_t *psVars = Fsm_FsmReadPresentStateVars(modelFsm);
+
+    if (verbosity == McVerbosityMax_c) {
+      mdd_t *tmpMdd = careStatesArray ?
+		      mdd_and_array(resultMdd, careStatesArray, 1, 1) :
+		      mdd_dup(resultMdd);
+      fprintf(vis_stdout, "--FwdU called %d (bdd_size - %d)\n",
+		++refCount, mdd_size(resultMdd));
+      fprintf(vis_stdout,
+		"--There are %.0f care states satisfying FwdU formula\n",
+		mdd_count_onset(mddMgr, tmpMdd, psVars));
+#ifdef DEBUG_MC
+      /* The following 2 lines are just for debug */
+      fprintf(vis_stdout, "FwdU satisfying minterms :\n");
+      (void)_McPrintSatisfyingMinterms(tmpMdd, modelFsm);
+#endif
+      mdd_free(tmpMdd);
+    } else {
+      fprintf(vis_stdout,
+		"--There are %.0f states satisfying FwdU formula\n",
+		mdd_count_onset(mddMgr, resultMdd, psVars));
+    }
+    fprintf(vis_stdout, "--FwdU: %d image computations\n",
+      Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps);
+  }
+
+  return resultMdd;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Evaluate states satisfying FwdG invariant]
+
+  Description [Evaluate states satisfying FwdG invariant.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Mc_FsmEvaluateFwdGFormula(
+  Fsm_Fsm_t *modelFsm,
+  mdd_t *targetMdd,
+  mdd_t *invariantMdd,
+  mdd_t *fairStates,
+  Fsm_Fairness_t *modelFairness,
+  array_t *careStatesArray,
+  array_t *onionRingsArrayForDbg,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel)
+{
+  mdd_t *resultMdd, *invariant;
+  array_t *onionRings;
+  int nImgComps;
+
+  nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c);
+  onionRings = NIL(array_t);
+
+  invariant = McForwardReachable(modelFsm, targetMdd, invariantMdd, fairStates,
+				 careStatesArray, onionRings, verbosity,
+				 dcLevel);
+  resultMdd = Mc_FsmEvaluateFwdEHFormula(modelFsm, invariant, fairStates,
+					 modelFairness, careStatesArray,
+					 onionRingsArrayForDbg, verbosity,
+					 dcLevel);
+  mdd_free(invariant);
+
+  if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) {
+    fprintf(vis_stdout, "--FwdG: %d image computations\n",
+      Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps);
+  }
+#ifdef DEBUG_MC
+  /* The following 2 lines are just for debug */
+  if ((verbosity == McVerbosityMax_c)) {
+    fprintf(vis_stdout, "FwdG satisfying minterms :\n");
+    (void)_McPrintSatisfyingMinterms(resultMdd, modelFsm);
+  }
+#endif
+  return resultMdd;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Evaluate states satisfying EH invariant]
+
+  Description [Evaluate states satisfying EH invariant.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Mc_FsmEvaluateFwdEHFormula(
+  Fsm_Fsm_t *modelFsm,
+  mdd_t *invariantMdd,
+  mdd_t *fairStates,
+  Fsm_Fairness_t *modelFairness,
+  array_t *careStatesArray,
+  array_t *onionRingsArrayForDbg,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel)
+{
+  int i;
+  array_t *onionRings = NIL(array_t);
+  array_t *tmpOnionRingsArrayForDbg = NIL(array_t);
+  mdd_manager *mddManager = Fsm_FsmReadMddManager(modelFsm);
+  mdd_t *mddOne = mdd_one(mddManager);
+  mdd_t *Zmdd;
+  int nIterations = 0;
+  int nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c);
+
+  /*
+  **  EG(f) = gfp Z[f ^ EX(Z)]
+  **  EH(f) = gfp Z[f ^ EY(Z)]
+  **
+  **  EcG(f) = gfp Z[f ^ EX( ^ E[Z U Z ^ c])]
+  **                        c<C
+  **  EcH(f) = gfp Z[f ^ EY( ^ Reachable(c,Z))]
+  **                        c<C
+  **  Reachable(p,q) = FwdUntil(p,q) ^ q
+  */
+
+  array_t *buchiFairness = array_alloc(mdd_t *, 0);
+  if (modelFairness) {
+    if (!Fsm_FairnessTestIsBuchi(modelFairness)) {
+      (void) fprintf(vis_stdout,
+	 "** mc error: non-Buechi fairness constraints not supported\n");
+      return NIL(mdd_t);
+    }
+    else {
+      int j;
+      int numBuchi = Fsm_FairnessReadNumConjunctsOfDisjunct(modelFairness, 0);
+      for (j = 0; j < numBuchi; j++) {
+	mdd_t *tmpMdd = Fsm_FairnessObtainFinallyInfMdd(modelFairness, 0, j,
+						careStatesArray, dcLevel);
+	array_insert_last(mdd_t *, buchiFairness, tmpMdd);
+      }
+    }
+  }
+  else {
+    array_insert_last(mdd_t *, buchiFairness, mdd_one(mddManager));
+  }
+
+  if (onionRingsArrayForDbg !=NIL(array_t)) {
+    tmpOnionRingsArrayForDbg = array_alloc(array_t *, 0);
+  }
+
+  Zmdd = mdd_dup(invariantMdd);
+  while (TRUE) {
+    mdd_t *ZprimeMdd = mdd_dup(Zmdd);
+    mdd_t *conjunctsMdd = NIL(mdd_t);
+    mdd_t *AAmdd = mdd_dup(Zmdd);
+
+    nIterations++;
+    for (i = 0; i < array_n(buchiFairness); i++) {
+      mdd_t *aMdd, *bMdd;
+      mdd_t *FiMdd = array_fetch(mdd_t *, buchiFairness, i);
+
+      if (tmpOnionRingsArrayForDbg) {
+	onionRings = array_alloc(mdd_t *, 0);
+	array_insert_last(array_t *, tmpOnionRingsArrayForDbg, onionRings);
+      }
+
+      aMdd = McForwardReachable(modelFsm, FiMdd, AAmdd, mddOne, careStatesArray,
+				onionRings, verbosity, dcLevel);
+      bMdd = Mc_FsmEvaluateEYFormula(modelFsm, aMdd, mddOne, careStatesArray,
+				     verbosity, dcLevel);
+      mdd_free(aMdd);
+
+      if (conjunctsMdd == NIL(mdd_t)) {
+	conjunctsMdd = mdd_dup(bMdd);
+      }
+      else {
+	mdd_t *tmpMdd = mdd_and(bMdd, conjunctsMdd, 1, 1);
+	mdd_free(conjunctsMdd);
+	conjunctsMdd = tmpMdd;
+      }
+      mdd_free(AAmdd); AAmdd = mdd_and(conjunctsMdd, invariantMdd, 1, 1);
+      mdd_free(bMdd);
+    }
+    mdd_free(AAmdd);
+
+    mdd_free(ZprimeMdd);
+    ZprimeMdd = mdd_and(invariantMdd, conjunctsMdd, 1, 1);
+    mdd_free(conjunctsMdd);
+
+    if (mdd_equal_mod_care_set_array(ZprimeMdd, Zmdd, careStatesArray)) {
+      mdd_free(ZprimeMdd);
+      break;
+    }
+
+    mdd_free(Zmdd);
+    Zmdd = ZprimeMdd;
+
+    if (tmpOnionRingsArrayForDbg) {
+      arrayForEachItem(array_t *, tmpOnionRingsArrayForDbg, i, onionRings) {
+	mdd_array_free(onionRings);
+      }
+      array_free(tmpOnionRingsArrayForDbg);
+      tmpOnionRingsArrayForDbg = array_alloc(array_t *, 0);
+    }
+  }
+
+  if (onionRingsArrayForDbg != NIL(array_t)) {
+    arrayForEachItem(array_t *, tmpOnionRingsArrayForDbg, i, onionRings) {
+      array_insert_last(array_t *, onionRingsArrayForDbg, onionRings);
+    }
+    array_free(tmpOnionRingsArrayForDbg);
+  }
+
+  if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) {
+    if (onionRingsArrayForDbg) {
+      for (i = 0; i < array_n(onionRingsArrayForDbg); i++) {
+	int j;
+	mdd_t *Fi = array_fetch(mdd_t *, buchiFairness, i);
+	array_t *onionRings = array_fetch(array_t *, onionRingsArrayForDbg, i);
+	for (j = 0; j < array_n(onionRings); j++) {
+	  mdd_t *ring = array_fetch(mdd_t *, onionRings, j);
+	  if (j == 0) {
+	    if (!mdd_lequal(ring, Fi, 1, 1)) {
+	      fprintf(vis_stderr, "** mc error: Problem w/ dbg in EH - ");
+	      fprintf(vis_stderr,
+		      "inner most ring not in Fi(fairness constraint).\n");
+	    }
+	  }
+	  if (!mdd_lequal(ring, Zmdd, 1, 1)) {
+	    fprintf(vis_stderr, "** mc error: Problem w/ dbg in EH - ");
+	    fprintf(vis_stderr, "onion ring of last FwdU fails invariant\n");
+	  }
+	}
+      }
+    }
+
+    if (verbosity == McVerbosityMax_c) {
+      mdd_t *tmpMdd = careStatesArray ?
+		      mdd_and_array(Zmdd, careStatesArray, 1, 1) :
+		      mdd_dup(Zmdd);
+      fprintf(vis_stdout,
+	      "--There are %.0f care states satisfying EH formula\n",
+	      mdd_count_onset(Fsm_FsmReadMddManager(modelFsm), tmpMdd,
+			      Fsm_FsmReadPresentStateVars(modelFsm)));
+#ifdef DEBUG_MC
+      /* The following 2 lines are just for debug */
+      fprintf(vis_stdout, "EH satisfying minterms :\n");
+      (void)_McPrintSatisfyingMinterms(tmpMdd, modelFsm);
+#endif
+      mdd_free(tmpMdd);
+    } else {
+      fprintf(vis_stdout, "--There are %.0f states satisfying EH formula\n",
+	      mdd_count_onset(Fsm_FsmReadMddManager(modelFsm), Zmdd,
+			      Fsm_FsmReadPresentStateVars(modelFsm)));
+    }
+
+    fprintf(vis_stdout, "--EH: %d iterations, %d image computations\n",
+      nIterations, Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps);
+  }
+
+  mdd_array_free(buchiFairness);
+  mdd_free(mddOne);
+
+  return Zmdd;
+
+} /* Mc_FsmEvaluateFwdEHFormula */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Evaluate states satisfying E(invariant U target), given
+  a transition relation]
+
+  Description [Does the same as Mc_FsmEvaluateEUFormula, minus the hints.]
+
+  SeeAlso     [Mc_FsmEvaluateEUFormula]
+  
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+McEvaluateEUFormulaWithGivenTR(
+  Fsm_Fsm_t *modelFsm,
+  mdd_t *invariantMdd,
+  mdd_t *targetMdd,
+  mdd_t *underapprox,
+  mdd_t *fairStates,
+  array_t *careStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  array_t *onionRings,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  boolean *fixpoint
+  )
+{
+  mdd_t *aMdd;
+  mdd_t *bMdd;
+  mdd_t *cMdd;
+  mdd_t *resultMdd;
+  mdd_t *ringMdd;
+  int nPreComps;
+  boolean term_tautology = FALSE; /* different termination conditions */
+  boolean term_early     = FALSE; 
+  boolean term_fixpoint  = FALSE; 
+
+  nPreComps = Img_GetNumberOfImageComputation(Img_Backward_c);
+  resultMdd = mdd_and(targetMdd, fairStates, 1, 1);
+
+  if(underapprox != NIL(mdd_t)){
+    mdd_t *tmp = mdd_or(resultMdd, underapprox, 1, 1);
+    mdd_free(resultMdd);
+    resultMdd = tmp;
+  }
+
+  ringMdd = mdd_dup(resultMdd);
+
+  if (onionRings) {
+    array_insert_last(mdd_t *, onionRings, mdd_dup(resultMdd));
+  }
+  
+  /* if until is trivially satisfied, or
+     the early termination condition holds*/ 
+  {
+    bdd_t *fairInvariantStates = mdd_and(invariantMdd, fairStates, 1, 1);
+    boolean trivial;
+
+    trivial = mdd_lequal_mod_care_set_array(fairInvariantStates, resultMdd,
+					    1, 1, careStatesArray);
+    /* the lequal also takes care of the case where result = 1 */
+    if(trivial ||
+       McCheckEarlyTerminationForUnderapprox(earlyTermination,
+					     resultMdd,
+					     careStatesArray)){
+      bdd_free(fairInvariantStates);
+      bdd_free(ringMdd);
+
+      /* trivially satisfied means that the fixpoint is complete.  If this
+	 information is requested, give it. */
+      if(fixpoint != NIL(boolean))
+	*fixpoint = trivial;
+      return(resultMdd);
+    }
+    bdd_free(fairInvariantStates);
+  }
+
+  /* The LFP loop */
+  while (!term_fixpoint && !term_tautology && !term_early) {
+    /* If dclevel is maximal, ringbdd is between the frontier and the
+       reached set */
+    aMdd = Mc_FsmEvaluateEXFormula(modelFsm, ringMdd, fairStates,
+				   careStatesArray, verbosity, dcLevel);
+    mdd_free(ringMdd);
+
+    bMdd = mdd_and(aMdd, invariantMdd, 1, 1);
+    mdd_free(aMdd);
+
+    cMdd = mdd_or(resultMdd, bMdd, 1, 1);
+    mdd_free(bMdd);
+
+    /* Can we stop?  The tautology condition can be weakened to
+       cMdd <= careStatesArray */
+    term_fixpoint = mdd_equal_mod_care_set_array(cMdd, resultMdd,
+						 careStatesArray);
+    if(!term_fixpoint)
+      term_tautology = mdd_is_tautology(cMdd, 1);
+    if(!term_fixpoint && !term_tautology)
+      term_early = McCheckEarlyTerminationForUnderapprox(earlyTermination, 
+							 cMdd,
+							 careStatesArray);
+
+    /* Print some debug info, and set ringmdd */
+    if (dcLevel >= McDcLevelRchFrontier_c) {
+      mdd_t *tmpMdd = mdd_and(resultMdd, cMdd, 0, 1);
+      ringMdd = bdd_between(tmpMdd, cMdd);
+      if (verbosity == McVerbosityMax_c) {
+	fprintf(vis_stdout,
+		"--EU |A(n+1)-A(n)|= %d\t|A(n+1)| = %d\t|between-dc| = %d\n",
+		mdd_size(tmpMdd), mdd_size(resultMdd), mdd_size(ringMdd));
+      }
+      mdd_free(tmpMdd);
+    }
+    else {
+      ringMdd = mdd_dup(cMdd);
+      if (verbosity == McVerbosityMax_c) {
+	  fprintf(vis_stdout, "-- EU |ringMdd| = %d\n", mdd_size(ringMdd));
+      }
+    }
+
+    mdd_free(resultMdd);
+    resultMdd = cMdd;
+    /* add onion ring unless fixpoint reached */
+    if (!term_fixpoint && onionRings != NIL(array_t)) {
+      array_insert_last(mdd_t *, onionRings, mdd_dup(resultMdd));
+    }
+  } /* while(!termination) for LFP */
+
+  mdd_free(ringMdd);
+
+  /* Print some debug info */
+  if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) {
+    static int refCount=0;
+    mdd_manager *mddMgr = Fsm_FsmReadMddManager(modelFsm);
+    array_t *psVars = Fsm_FsmReadPresentStateVars(modelFsm);
+
+    if (verbosity == McVerbosityMax_c) {
+      mdd_t *tmpMdd = careStatesArray ?
+		      mdd_and_array(resultMdd, careStatesArray, 1, 1) :
+		      mdd_dup(resultMdd);
+      fprintf(vis_stdout, "--EU called %d (bdd_size - %d)\n", ++refCount,
+	      mdd_size(resultMdd));
+      fprintf(vis_stdout,
+	      "--There are %.0f care states satisfying EU formula\n",
+	      mdd_count_onset(mddMgr, tmpMdd, psVars));
+#ifdef DEBUG_MC
+      /* The following 2 lines are just for debug */
+      fprintf(vis_stdout, "EU satisfying minterms :\n");
+      (void)_McPrintSatisfyingMinterms(tmpMdd, modelFsm);
+#endif
+      mdd_free(tmpMdd);
+    } else {
+      fprintf(vis_stdout,
+	      "--There are %.0f states satisfying EU formula\n",
+	      mdd_count_onset(mddMgr, resultMdd, psVars));
+    }
+
+    fprintf(vis_stdout, "--EU: %d preimage computations\n",
+      Img_GetNumberOfImageComputation(Img_Backward_c) - nPreComps);
+  }
+
+  if(fixpoint != NIL(boolean))
+    *fixpoint = term_fixpoint || term_tautology;
+  return resultMdd;
+
+} /* McEvaluateEUFormulaWithGivenTR */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Evaluate states satisfying E(invariant S target), given
+  a transition relation]
+
+  Description [Does the same as Mc_FsmEvaluateESFormula, minus the hints.]
+
+  SeeAlso [Mc_FsmEvaluateESFormula]
+  
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+McEvaluateESFormulaWithGivenTR(
+  Fsm_Fsm_t *modelFsm,
+  mdd_t *invariantMdd,
+  mdd_t *sourceMdd,
+  mdd_t *underapprox,
+  mdd_t *fairStates,
+  array_t *careStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  array_t *onionRings,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  boolean *fixpoint
+  )
+{
+  mdd_t *aMdd;
+  mdd_t *bMdd;
+  mdd_t *cMdd;
+  mdd_t *resultMdd;
+  mdd_t *ringMdd;
+  int nImgComps;
+  boolean term_tautology = FALSE; /* different termination conditions */
+  boolean term_early     = FALSE; 
+  boolean term_fixpoint  = FALSE; 
+
+  nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c);
+  resultMdd = mdd_and(sourceMdd, fairStates, 1, 1);
+
+  if(underapprox != NIL(mdd_t)){
+    mdd_t *tmp = mdd_or(resultMdd, underapprox, 1, 1);
+    mdd_free(resultMdd);
+    resultMdd = tmp;
+  }
+
+  ringMdd = mdd_dup(resultMdd);
+
+  if (onionRings) {
+    array_insert_last(mdd_t *, onionRings, mdd_dup(resultMdd));
+  }
+  
+  /* if Since is trivially satisfied, or
+     the early termination condition holds*/ 
+  {
+    bdd_t *fairInvariantStates = mdd_and(invariantMdd, fairStates, 1, 1);
+    boolean trivial;
+
+    trivial = mdd_lequal_mod_care_set_array(fairInvariantStates, resultMdd,
+					    1, 1, careStatesArray);
+    /* the lequal also takes care of the case where result = 1 */
+    if(trivial ||
+       McCheckEarlyTerminationForUnderapprox(earlyTermination,
+					     resultMdd,
+					     careStatesArray)){
+      bdd_free(fairInvariantStates);
+      bdd_free(ringMdd);
+
+      /* trivially satisfied means that the fixpoint is complete.  If this
+	 information is requested, give it. */
+      if(fixpoint != NIL(boolean))
+	*fixpoint = trivial;
+      return(resultMdd);
+    }
+    bdd_free(fairInvariantStates);
+  }
+
+  /* The LFP loop */
+  while (!term_fixpoint && !term_tautology && !term_early) {
+    /* If dclevel is maximal, ringbdd is between the frontier and the
+       reached set */
+    aMdd = Mc_FsmEvaluateEYFormula(modelFsm, ringMdd, fairStates,
+				   careStatesArray, verbosity, dcLevel);
+    mdd_free(ringMdd);
+
+    bMdd = mdd_and(aMdd, invariantMdd, 1, 1);
+    mdd_free(aMdd);
+
+    cMdd = mdd_or(resultMdd, bMdd, 1, 1);
+    mdd_free(bMdd);
+
+    /* Can we stop?  The tautology condition can be weakened to
+       cMdd <= careStatesArray */
+    term_fixpoint = mdd_equal_mod_care_set_array(cMdd, resultMdd,
+						 careStatesArray);
+    if(!term_fixpoint)
+      term_tautology = mdd_is_tautology(cMdd, 1);
+    if(!term_fixpoint && !term_tautology)
+      term_early = McCheckEarlyTerminationForUnderapprox(earlyTermination, 
+							 cMdd,
+							 careStatesArray);
+
+    /* Print some debug info, and set ringmdd */
+    if (dcLevel >= McDcLevelRchFrontier_c) {
+      mdd_t *tmpMdd = mdd_and(resultMdd, cMdd, 0, 1);
+      ringMdd = bdd_between(tmpMdd, cMdd);
+      if (verbosity == McVerbosityMax_c) {
+	fprintf(vis_stdout,
+		"--ES |A(n+1)-A(n)|= %d\t|A(n+1)| = %d\t|between-dc| = %d\n",
+		mdd_size(tmpMdd), mdd_size(resultMdd), mdd_size(ringMdd));
+      }
+      mdd_free(tmpMdd);
+      }
+    else {
+      ringMdd = mdd_dup(cMdd);
+      if (verbosity == McVerbosityMax_c) {
+	  fprintf(vis_stdout, "-- ES |ringMdd| = %d\n", mdd_size(ringMdd));
+      }
+    }
+
+    mdd_free(resultMdd);
+    resultMdd = cMdd;
+    /* add onion ring unless fixpoint reached */
+    if (!term_fixpoint && onionRings != NIL(array_t)) {
+      array_insert_last(mdd_t *, onionRings, mdd_dup(resultMdd));
+    }
+  } /* while(!termination) for LFP */
+
+  mdd_free(ringMdd);
+
+  /* Print some debug info */
+  if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) {
+    static int refCount=0;
+    mdd_manager *mddMgr = Fsm_FsmReadMddManager(modelFsm);
+    array_t *psVars = Fsm_FsmReadPresentStateVars(modelFsm);
+
+    if (verbosity == McVerbosityMax_c) {
+      mdd_t *tmpMdd = careStatesArray ?
+		      mdd_and_array(resultMdd, careStatesArray, 1, 1) :
+		      mdd_dup(resultMdd);
+      fprintf(vis_stdout, "--ES called %d (bdd_size - %d)\n", ++refCount,
+	      mdd_size(resultMdd));
+      fprintf(vis_stdout,
+	      "--There are %.0f care states satisfying ES formula\n",
+	      mdd_count_onset(mddMgr, tmpMdd, psVars));
+#ifdef DEBUG_MC
+      /* The following 2 lines are just for debug */
+      fprintf(vis_stdout, "ES satisfying minterms :\n");
+      (void)_McPrintSatisfyingMinterms(tmpMdd, modelFsm);
+#endif
+      mdd_free(tmpMdd);
+    } else {
+      fprintf(vis_stdout,
+	      "--There are %.0f states satisfying ES formula\n",
+	      mdd_count_onset(mddMgr, resultMdd, psVars));
+    }
+
+    fprintf(vis_stdout, "--ES: %d image computations\n",
+      Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps);
+  }
+
+  if(fixpoint != NIL(boolean))
+    *fixpoint = term_fixpoint || term_tautology;
+  return resultMdd;
+
+} /* McEvaluateESFormulaWithGivenTR */
+
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SeeAlso []
+  
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+McEvaluateESFormulaWithGivenTRWithTarget(
+  Fsm_Fsm_t *modelFsm,
+  mdd_t *invariantMdd,
+  mdd_t *sourceMdd,
+  mdd_t *targetMdd,
+  mdd_t *underapprox,
+  mdd_t *fairStates,
+  array_t *careStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  array_t *onionRings,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  boolean *fixpoint
+  )
+{
+  mdd_t *aMdd;
+  mdd_t *bMdd;
+  mdd_t *cMdd;
+  mdd_t *resultMdd;
+  mdd_t *ringMdd;
+  mdd_t *zeroMdd;
+  int nImgComps;
+  boolean term_tautology = FALSE; /* different termination conditions */
+  boolean term_early     = FALSE; 
+  boolean term_fixpoint  = FALSE; 
+
+  mdd_manager *mddMgr = Fsm_FsmReadMddManager(modelFsm);
+
+  nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c);
+  resultMdd = mdd_and(sourceMdd, fairStates, 1, 1);
+
+  if(underapprox != NIL(mdd_t)){
+    mdd_t *tmp = mdd_or(resultMdd, underapprox, 1, 1);
+    mdd_free(resultMdd);
+    resultMdd = tmp;
+  }
+
+  ringMdd = mdd_dup(resultMdd);
+  zeroMdd = mdd_zero(mddMgr);
+
+  if (onionRings) {
+    array_insert_last(mdd_t *, onionRings, mdd_dup(resultMdd));
+  }
+  
+  /* if Since is trivially satisfied, or
+     the early termination condition holds*/ 
+  {
+    bdd_t *fairInvariantStates = mdd_and(invariantMdd, fairStates, 1, 1);
+    boolean trivial;
+
+    trivial = mdd_lequal_mod_care_set_array(fairInvariantStates, resultMdd,
+					    1, 1, careStatesArray);
+    /* the lequal also takes care of the case where result = 1 */
+    if(trivial ||
+       McCheckEarlyTerminationForUnderapprox(earlyTermination,
+					     resultMdd,
+					     careStatesArray)){
+      bdd_free(fairInvariantStates);
+      bdd_free(ringMdd);
+
+      /* trivially satisfied means that the fixpoint is complete.  If this
+	 information is requested, give it. */
+      if(fixpoint != NIL(boolean))
+	*fixpoint = trivial;
+      return(resultMdd);
+    }
+    bdd_free(fairInvariantStates);
+  }
+
+  /* The LFP loop */
+  while (!term_fixpoint && !term_tautology && !term_early) {
+    /* If dclevel is maximal, ringbdd is between the frontier and the
+       reached set */
+    aMdd = Mc_FsmEvaluateEYFormula(modelFsm, ringMdd, fairStates,
+				   careStatesArray, verbosity, dcLevel);
+    mdd_free(ringMdd);
+
+    bMdd = mdd_and(aMdd, invariantMdd, 1, 1);
+    mdd_free(aMdd);
+
+    cMdd = mdd_or(resultMdd, bMdd, 1, 1);
+    mdd_free(bMdd);
+
+    /* Can we stop?  The tautology condition can be weakened to
+       cMdd <= careStatesArray */
+    term_fixpoint = mdd_equal_mod_care_set_array(cMdd, resultMdd,
+						 careStatesArray);
+    if(!term_fixpoint)
+      term_tautology = mdd_is_tautology(cMdd, 1);
+    if(!term_fixpoint && !term_tautology)
+      term_early = McCheckEarlyTerminationForUnderapprox(earlyTermination, 
+							 cMdd,
+							 careStatesArray);
+
+    /* Print some debug info, and set ringmdd */
+    if (dcLevel >= McDcLevelRchFrontier_c) {
+      mdd_t *tmpMdd = mdd_and(resultMdd, cMdd, 0, 1);
+      ringMdd = bdd_between(tmpMdd, cMdd);
+      if (verbosity == McVerbosityMax_c) {
+	fprintf(vis_stdout,
+		"--ES |A(n+1)-A(n)|= %d\t|A(n+1)| = %d\t|between-dc| = %d\n",
+		mdd_size(tmpMdd), mdd_size(resultMdd), mdd_size(ringMdd));
+      }
+      mdd_free(tmpMdd);
+      }
+    else {
+      ringMdd = mdd_dup(cMdd);
+      if (verbosity == McVerbosityMax_c) {
+	  fprintf(vis_stdout, "-- ES |ringMdd| = %d\n", mdd_size(ringMdd));
+      }
+    }
+
+    mdd_free(resultMdd);
+    resultMdd = cMdd;
+
+    aMdd = mdd_and(resultMdd, targetMdd, 1, 1);
+    if(!mdd_equal(aMdd, zeroMdd)) {
+      array_insert_last(mdd_t *, onionRings, mdd_dup(targetMdd));
+      mdd_free(aMdd);
+      break;
+    }
+    mdd_free(aMdd);
+
+    /* add onion ring unless fixpoint reached */
+    if (!term_fixpoint && onionRings != NIL(array_t)) {
+      array_insert_last(mdd_t *, onionRings, mdd_dup(resultMdd));
+    }
+  } /* while(!termination) for LFP */
+
+  mdd_free(ringMdd);
+
+  /* Print some debug info */
+  if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) {
+    static int refCount=0;
+    array_t *psVars = Fsm_FsmReadPresentStateVars(modelFsm);
+
+    if (verbosity == McVerbosityMax_c) {
+      mdd_t *tmpMdd = careStatesArray ?
+		      mdd_and_array(resultMdd, careStatesArray, 1, 1) :
+		      mdd_dup(resultMdd);
+      fprintf(vis_stdout, "--ES called %d (bdd_size - %d)\n", ++refCount,
+	      mdd_size(resultMdd));
+      fprintf(vis_stdout,
+	      "--There are %.0f care states satisfying ES formula\n",
+	      mdd_count_onset(mddMgr, tmpMdd, psVars));
+#ifdef DEBUG_MC
+      /* The following 2 lines are just for debug */
+      fprintf(vis_stdout, "ES satisfying minterms :\n");
+      (void)_McPrintSatisfyingMinterms(tmpMdd, modelFsm);
+#endif
+      mdd_free(tmpMdd);
+    } else {
+      fprintf(vis_stdout,
+	      "--There are %.0f states satisfying ES formula\n",
+	      mdd_count_onset(mddMgr, resultMdd, psVars));
+    }
+
+    fprintf(vis_stdout, "--ES: %d image computations\n",
+      Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps);
+  }
+  mdd_free(zeroMdd);
+
+  if(fixpoint != NIL(boolean))
+    *fixpoint = term_fixpoint || term_tautology;
+  return resultMdd;
+
+} /* McEvaluateESFormulaWithGivenTR */
+
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SeeAlso []
+  
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+McEvaluateESFormulaWithGivenTRFAFW(
+  Fsm_Fsm_t *modelFsm,
+  mdd_t *invariantMdd,
+  mdd_t *sourceMdd,
+  mdd_t *underapprox,
+  mdd_t *fairStates,
+  array_t *careStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  array_t *onionRings,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  boolean *fixpoint,
+  mdd_t *Swin
+  )
+{
+  mdd_t *aMdd;
+  mdd_t *bMdd;
+  mdd_t *cMdd;
+  mdd_t *resultMdd;
+  mdd_t *ringMdd;
+  Img_ImageInfo_t *imageInfo;
+  int nImgComps;
+  boolean term_tautology = FALSE; /* different termination conditions */
+  boolean term_early     = FALSE; 
+  boolean term_fixpoint  = FALSE; 
+
+  nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c);
+  resultMdd = mdd_and(sourceMdd, fairStates, 1, 1);
+
+  if(underapprox != NIL(mdd_t)){
+    mdd_t *tmp = mdd_or(resultMdd, underapprox, 1, 1);
+    mdd_free(resultMdd);
+    resultMdd = tmp;
+  }
+
+  ringMdd = mdd_dup(resultMdd);
+
+  if (onionRings) {
+    array_insert_last(mdd_t *, onionRings, mdd_dup(resultMdd));
+  }
+  
+  /* if Since is trivially satisfied, or
+     the early termination condition holds*/ 
+  {
+    bdd_t *fairInvariantStates = mdd_and(invariantMdd, fairStates, 1, 1);
+    boolean trivial;
+
+    trivial = mdd_lequal_mod_care_set_array(fairInvariantStates, resultMdd,
+					    1, 1, careStatesArray);
+    /* the lequal also takes care of the case where result = 1 */
+    if(trivial ||
+       McCheckEarlyTerminationForUnderapprox(earlyTermination,
+					     resultMdd,
+					     careStatesArray)){
+      bdd_free(fairInvariantStates);
+      bdd_free(ringMdd);
+
+      /* trivially satisfied means that the fixpoint is complete.  If this
+	 information is requested, give it. */
+      if(fixpoint != NIL(boolean))
+	*fixpoint = trivial;
+      return(resultMdd);
+    }
+    bdd_free(fairInvariantStates);
+  }
+
+  imageInfo = Fsm_FsmReadOrCreateImageInfoPrunedFAFW(modelFsm, Swin, 0, 1);
+  /* The LFP loop */
+  while (!term_fixpoint && !term_tautology && !term_early) {
+    /* If dclevel is maximal, ringbdd is between the frontier and the
+       reached set */
+    aMdd = Img_ImageInfoComputeImageWithDomainVars(imageInfo,
+		ringMdd, ringMdd, careStatesArray);
+    mdd_free(ringMdd);
+
+    bMdd = mdd_and(aMdd, invariantMdd, 1, 1);
+    mdd_free(aMdd);
+
+    cMdd = mdd_or(resultMdd, bMdd, 1, 1);
+    mdd_free(bMdd);
+
+    /* Can we stop?  The tautology condition can be weakened to
+       cMdd <= careStatesArray */
+    term_fixpoint = mdd_equal_mod_care_set_array(cMdd, resultMdd,
+						 careStatesArray);
+    if(!term_fixpoint)
+      term_tautology = mdd_is_tautology(cMdd, 1);
+    if(!term_fixpoint && !term_tautology)
+      term_early = McCheckEarlyTerminationForUnderapprox(earlyTermination, 
+							 cMdd,
+							 careStatesArray);
+
+    /* Print some debug info, and set ringmdd */
+    if (dcLevel >= McDcLevelRchFrontier_c) {
+      mdd_t *tmpMdd = mdd_and(resultMdd, cMdd, 0, 1);
+      ringMdd = bdd_between(tmpMdd, cMdd);
+      if (verbosity == McVerbosityMax_c) {
+	fprintf(vis_stdout,
+		"--ES |A(n+1)-A(n)|= %d\t|A(n+1)| = %d\t|between-dc| = %d\n",
+		mdd_size(tmpMdd), mdd_size(resultMdd), mdd_size(ringMdd));
+      }
+      mdd_free(tmpMdd);
+      }
+    else {
+      ringMdd = mdd_dup(cMdd);
+      if (verbosity == McVerbosityMax_c) {
+	  fprintf(vis_stdout, "-- ES |ringMdd| = %d\n", mdd_size(ringMdd));
+      }
+    }
+
+    mdd_free(resultMdd);
+    resultMdd = cMdd;
+    /* add onion ring unless fixpoint reached */
+    if (!term_fixpoint && onionRings != NIL(array_t)) {
+      array_insert_last(mdd_t *, onionRings, mdd_dup(resultMdd));
+    }
+  } /* while(!termination) for LFP */
+
+  /* Img_ImageInfoRecoverFromWinningStrategy(modelFsm, Img_Forward_c); */
+  Img_ImageInfoFreeFAFW(imageInfo);
+  Img_ImageInfoFree(imageInfo);
+
+  mdd_free(ringMdd);
+
+  /* Print some debug info */
+  if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) {
+    static int refCount=0;
+    mdd_manager *mddMgr = Fsm_FsmReadMddManager(modelFsm);
+    array_t *psVars = Fsm_FsmReadPresentStateVars(modelFsm);
+
+    if (verbosity == McVerbosityMax_c) {
+      mdd_t *tmpMdd = careStatesArray ?
+		      mdd_and_array(resultMdd, careStatesArray, 1, 1) :
+		      mdd_dup(resultMdd);
+      fprintf(vis_stdout, "--ES called %d (bdd_size - %d)\n", ++refCount,
+	      mdd_size(resultMdd));
+      fprintf(vis_stdout,
+	      "--There are %.0f care states satisfying ES formula\n",
+	      mdd_count_onset(mddMgr, tmpMdd, psVars));
+#ifdef DEBUG_MC
+      /* The following 2 lines are just for debug */
+      fprintf(vis_stdout, "ES satisfying minterms :\n");
+      (void)_McPrintSatisfyingMinterms(tmpMdd, modelFsm);
+#endif
+      mdd_free(tmpMdd);
+    } else {
+      fprintf(vis_stdout,
+	      "--There are %.0f states satisfying ES formula\n",
+	      mdd_count_onset(mddMgr, resultMdd, psVars));
+    }
+
+    fprintf(vis_stdout, "--ES: %d image computations\n",
+      Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps);
+  }
+
+  if(fixpoint != NIL(boolean))
+    *fixpoint = term_fixpoint || term_tautology;
+  return resultMdd;
+
+} /* McEvaluateESFormulaWithGivenTR */
+
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SeeAlso []
+  
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+McEvaluateAUFormulaWithGivenTR(
+  Fsm_Fsm_t *modelFsm,
+  mdd_t *invariantMdd,
+  mdd_t *targetMdd,
+  mdd_t *underapprox,
+  mdd_t *fairStates,
+  array_t *careStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  array_t *onionRings,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  boolean *fixpoint
+  )
+{
+  mdd_t *aMdd;
+  mdd_t *bMdd;
+  mdd_t *cMdd;
+  mdd_t *resultMdd;
+  mdd_t *ringMdd;
+  boolean term_tautology = FALSE; /* different termination conditions */
+  boolean term_early     = FALSE;
+  boolean term_fixpoint  = FALSE;
+
+  resultMdd = mdd_and(targetMdd, fairStates, 1, 1);
+
+  ringMdd = mdd_dup(resultMdd);
+  if (onionRings) {
+    array_insert_last(mdd_t *, onionRings, mdd_dup(resultMdd));
+  }
+  /* The LFP loop */
+  while (!term_fixpoint && !term_tautology && !term_early) {
+    /* If dclevel is maximal, ringbdd is between the frontier and the
+     reached set */
+    aMdd = Mc_FsmEvaluateMXFormula(modelFsm, ringMdd, fairStates, 
+                                    careStatesArray, verbosity, dcLevel);
+
+    bMdd = mdd_and(aMdd, invariantMdd, 1, 1);
+    mdd_free(aMdd);
+
+    cMdd = mdd_or(resultMdd, bMdd, 1, 1);
+    mdd_free(bMdd);
+    mdd_free(ringMdd);
+
+    /* Can we stop?  The tautology condition can be weakened to
+       cMdd <= careStatesArray */
+    term_fixpoint = mdd_equal_mod_care_set_array(cMdd, resultMdd,
+                                                 careStatesArray);
+    if(!term_fixpoint)
+      term_tautology = mdd_is_tautology(cMdd, 1);
+    if(!term_fixpoint && !term_tautology)
+      term_early = McCheckEarlyTerminationForUnderapprox(earlyTermination,
+                                                         cMdd,
+                                                         careStatesArray);
+
+    /* Print some debug info, and set ringmdd */
+    if (dcLevel >= McDcLevelRchFrontier_c) {
+      mdd_t *tmpMdd = mdd_and(resultMdd, cMdd, 0, 1);
+      ringMdd = bdd_between(tmpMdd, cMdd);
+      if (verbosity == McVerbosityMax_c) {
+        fprintf(vis_stdout,
+                "--AU |A(n+1)-A(n)|= %d\t|A(n+1)| = %d\t|between-dc| = %d\n",
+                mdd_size(tmpMdd), mdd_size(resultMdd), mdd_size(ringMdd));
+      }
+      mdd_free(tmpMdd);
+      }
+    else {
+      ringMdd = mdd_dup(cMdd);
+      if (verbosity == McVerbosityMax_c) {
+          fprintf(vis_stdout, "-- AU |ringMdd| = %d\n", mdd_size(ringMdd));
+      }
+    }
+
+    mdd_free(resultMdd);
+    resultMdd = cMdd;
+    /* add onion ring unless fixpoint reached */
+    if (!term_fixpoint && onionRings) {
+      array_insert_last(mdd_t *, onionRings, mdd_dup(resultMdd));
+    }
+  } /* while(!termination) for LFP */
+
+  mdd_free(ringMdd);
+
+
+  if(fixpoint != NIL(boolean))
+    *fixpoint = term_fixpoint || term_tautology;
+  return resultMdd;  
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Evaluate states satisfying EG(invariantMdd), given
+  a transition relation]
+
+  Description [Does the same as Mc_FsmEvaluateEGFormula, minus the hints.]
+
+  SeeAlso [Mc_FsmEvaluateEGFormula]
+  
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+McEvaluateEGFormulaWithGivenTR(
+  Fsm_Fsm_t *modelFsm,
+  mdd_t *invariantMdd,
+  mdd_t *overapprox,
+  mdd_t *fairStates,
+  Fsm_Fairness_t *modelFairness,
+  array_t *careStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  array_t **pOnionRingsArrayForDbg,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  boolean *fixpoint)
+{
+  int i;
+  array_t *onionRings;
+  boolean useRings;
+  mdd_manager *mddManager;
+  mdd_t *mddOne;
+  mdd_t *iterate;
+  array_t *buchiFairness;
+  int nPreComps;
+  int nIterations;
+  boolean term_fixpoint = FALSE;        /* different termination conditions */
+  boolean term_tautology = FALSE;
+  boolean term_early = FALSE;
+
+  /* Here's how the onionRingsArrayForDbg works.  It is an array of
+     arrays of mdds.  It is filled in anew for every pass of the
+     algorithm, that is for every /\_{c inC} EXE(Y U Y*c).  There is
+     one entry for every fairness constraint, and this entry contains
+     the onionrings of the EU computation that corresponds to this
+     constraint. */
+  assert(pOnionRingsArrayForDbg == NIL(array_t *) ||
+	 *pOnionRingsArrayForDbg == NIL(array_t) ||
+	 array_n(*pOnionRingsArrayForDbg) == 0);  
+
+  useRings = (pOnionRingsArrayForDbg != NIL(array_t *) &&
+	      *pOnionRingsArrayForDbg != NIL(array_t));
+
+  nIterations = 0;
+  nPreComps  = Img_GetNumberOfImageComputation(Img_Backward_c);
+  onionRings = NIL(array_t);
+  mddManager = Fsm_FsmReadMddManager(modelFsm);
+  mddOne  = mdd_one(mddManager);
+
+  /* If an overapproximation of the greatest fixpoint is given, use it. */
+  if(overapprox != NIL(mdd_t)){
+    iterate = mdd_and(invariantMdd, overapprox, 1, 1);
+  } else {
+    iterate = mdd_dup(invariantMdd);
+  }
+
+  /* See if we need to enter the loop at all.  If we wanted to test for
+   * early termination here, we should fix the onion rings.  In the current
+   * case, we do not need to, since the EG does not hold, and hence a
+   * counterexample does not exist.
+   */
+  if( mdd_is_tautology(iterate, 0)){
+    mdd_free(mddOne);
+    if(fixpoint != NIL(boolean)) *fixpoint = mdd_is_tautology(iterate, 0);
+    return(iterate);
+  }
+
+  /* read fairness constraints */
+  buchiFairness = array_alloc(mdd_t *, 0);
+  if(modelFairness != NIL(Fsm_Fairness_t)) {
+    if(!Fsm_FairnessTestIsBuchi(modelFairness)) {
+      (void)fprintf(vis_stdout,
+	       "** mc error: non-Buechi fairness constraints not supported\n");
+      array_free(buchiFairness);
+      mdd_free(iterate);
+      mdd_free(mddOne);
+
+      if(fixpoint != NIL(boolean)) *fixpoint = FALSE;
+      return NIL(mdd_t);
+    }
+    else {
+      int j;
+      int numBuchi = Fsm_FairnessReadNumConjunctsOfDisjunct(modelFairness, 0);
+      for (j = 0 ; j < numBuchi; j++) {
+	mdd_t *tmpMdd = Fsm_FairnessObtainFinallyInfMdd(modelFairness, 0, j,
+						careStatesArray, dcLevel);
+	array_insert_last(mdd_t *, buchiFairness, tmpMdd);
+      }
+    }
+  }
+  else {
+    array_insert_last(mdd_t *, buchiFairness, mdd_one(mddManager));
+  }
+
+
+  /* GFP.  If we know that the result is a subset of a set S, we can conjoin
+   the iterate with that set.  We use this to converge faster.  */
+  while (TRUE) {
+    mdd_t *newIterate;           /* the new iterate */
+
+    nIterations++;
+    newIterate = mdd_dup(iterate);
+    
+    /* for all fairness constraints */
+    for (i = 0 ; i < array_n(buchiFairness) ; i++) {
+      mdd_t *aMdd, *bMdd, *cMdd, *dMdd;
+      mdd_t *FiMdd = array_fetch(mdd_t *, buchiFairness, i);
+      
+      if(useRings) {
+	onionRings = array_alloc(mdd_t *, 0);
+	array_insert_last(array_t *, *pOnionRingsArrayForDbg, onionRings);
+      }
+
+      aMdd = mdd_and(FiMdd, newIterate, 1, 1);
+
+      bMdd = Mc_FsmEvaluateEUFormula(modelFsm, newIterate, aMdd, NIL(mdd_t),
+				     mddOne, careStatesArray,
+				     MC_NO_EARLY_TERMINATION, NIL(array_t),
+				     Mc_None_c, onionRings, verbosity, dcLevel,
+				     NIL(boolean));  
+      mdd_free(aMdd);
+      cMdd = Mc_FsmEvaluateEXFormula(modelFsm, bMdd, mddOne, careStatesArray,
+				     verbosity, dcLevel);
+      mdd_free(bMdd);
+
+      dMdd  = mdd_and(newIterate, cMdd, 1, 1);
+
+      mdd_free(cMdd);
+      mdd_free(newIterate);
+      newIterate = dMdd;
+
+      /* invariants that hold here: newiterate <= iterate <= invariant. */
+    }/* for all fairness constraints */
+
+    /* termination */
+    term_tautology = mdd_is_tautology(newIterate, 0);
+    if(!term_tautology)
+      term_fixpoint =  mdd_equal_mod_care_set_array(newIterate, iterate,
+						    careStatesArray);
+    if(!term_tautology && !term_fixpoint)
+      term_early = McCheckEarlyTerminationForOverapprox(earlyTermination,
+							newIterate, 
+							careStatesArray);
+    if(term_tautology || term_fixpoint || term_early){
+      mdd_free(iterate);
+      iterate = newIterate;
+      break; /* from the GFP loop */
+    }
+
+    /* update iterate */
+    mdd_free(iterate);
+    iterate = newIterate;
+
+    if(useRings){
+      mdd_array_array_free(*pOnionRingsArrayForDbg);
+      *pOnionRingsArrayForDbg = array_alloc(array_t *, 0);
+    }
+  } /* while(true) for gfp */
+
+  /* Check if onionrings are OK */
+  if(verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) {
+    if(useRings){
+      for (i = 0 ; i < array_n(*pOnionRingsArrayForDbg); i++) {
+	int j;
+	mdd_t *Fi = array_fetch(mdd_t *,  buchiFairness, i);
+	array_t *onionRings = array_fetch(array_t *, *pOnionRingsArrayForDbg,
+					  i); 
+	for (j = 0 ; j < array_n(onionRings); j++) {
+	  mdd_t *ring = array_fetch(mdd_t *, onionRings, j);
+	  if(j == 0) {
+	    if(!mdd_lequal_mod_care_set_array(ring, Fi, 1, 1,
+					       careStatesArray)) {
+	      fprintf(vis_stderr, "** mc error: Problem w/ dbg in EG - ");
+	      fprintf(vis_stderr,
+		      "inner most ring not in Fi (fairness constraint).\n");
+	    }
+	  }
+	  if(!mdd_lequal_mod_care_set_array(ring, invariantMdd, 1, 1,
+					     careStatesArray)) {
+	    fprintf(vis_stderr, "** mc error: Problem w/ dbg in EG - ");
+	    fprintf(vis_stderr, "An onion ring of last EU fails invariant\n");
+	  }
+	} /* for all onionrings in array i */ 
+      } /* for all onionringarrays in onionringsarray */
+    }/* if useRings */
+
+    if(verbosity == McVerbosityMax_c) {
+      mdd_t *tmpMdd = careStatesArray ?
+	mdd_and_array(iterate, careStatesArray, 1, 1) : mdd_dup(iterate);
+      fprintf(vis_stdout,
+	      "--There are %.0f care states satisfying EG formula\n",
+	      mdd_count_onset(Fsm_FsmReadMddManager(modelFsm), tmpMdd,
+				Fsm_FsmReadPresentStateVars(modelFsm)));
+#ifdef DEBUG_MC
+      /* The following 2 lines are just for debug */
+      fprintf(vis_stdout, "EG satisfying minterms :\n");
+      (void)_McPrintSatisfyingMinterms(tmpMdd, modelFsm);
+#endif
+      mdd_free(tmpMdd);
+    } else {
+      fprintf(vis_stdout, "--There are %.0f states satisfying EG formula\n",
+	      mdd_count_onset(Fsm_FsmReadMddManager(modelFsm), iterate,
+				Fsm_FsmReadPresentStateVars(modelFsm)));
+    }
+
+    fprintf(vis_stdout, "--EG: %d iterations, %d preimage computations\n",
+      nIterations, Img_GetNumberOfImageComputation(Img_Backward_c) - nPreComps);
+  }
+
+  mdd_array_free(buchiFairness);
+  mdd_free(mddOne);
+
+  if(fixpoint != NIL(boolean))
+     *fixpoint = term_fixpoint || term_tautology;
+  return iterate;
+
+} /* McEvaluateEGFormulaWithGivenTR */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Evaluate states satisfying EH(invariantMdd), given
+  a transition relation]
+
+  Description [Does the same as Mc_FsmEvaluateEHFormula, minus the hints.]
+
+  SeeAlso     [Mc_FsmEvaluateEHFormula]
+  
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+McEvaluateEHFormulaWithGivenTR(
+  Fsm_Fsm_t *modelFsm,
+  mdd_t *invariantMdd,
+  mdd_t *overapprox,
+  mdd_t *fairStates,
+  Fsm_Fairness_t *modelFairness,
+  array_t *careStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  array_t **pOnionRingsArrayForDbg,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  boolean *fixpoint)
+{
+  int i;
+  array_t *onionRings;
+  boolean useRings;
+  mdd_manager *mddManager;
+  mdd_t *mddOne;
+  mdd_t *iterate;
+  array_t *buchiFairness;
+  int nImgComps;
+  int nIterations;
+  boolean term_fixpoint = FALSE;        /* different termination conditions */
+  boolean term_tautology = FALSE;
+  boolean term_early = FALSE;
+
+  /* Here's how the onionRingsArrayForDbg works.  It is an array of
+     arrays of mdds.  It is filled in anew for every pass of the
+     algorithm, that is for every /\_{c inC} EYE(Y S Y*c).  There is
+     one entry for every fairness constraint, and this entry contains
+     the onionrings of the ES computation that corresponds to this
+     constraint. */
+  assert(pOnionRingsArrayForDbg == NIL(array_t *) ||
+	 *pOnionRingsArrayForDbg == NIL(array_t) ||
+	 array_n(*pOnionRingsArrayForDbg) == 0);  
+
+  useRings = (pOnionRingsArrayForDbg != NIL(array_t *) &&
+	      *pOnionRingsArrayForDbg != NIL(array_t));
+
+  nIterations = 0;
+  nImgComps  = Img_GetNumberOfImageComputation(Img_Forward_c);
+  onionRings = NIL(array_t);
+  mddManager = Fsm_FsmReadMddManager(modelFsm);
+  mddOne  = mdd_one(mddManager);
+
+  /* If an overapproxiamtion of the greatest fixpoint is given, use it. */
+  if(overapprox != NIL(mdd_t)){
+    iterate = mdd_and(invariantMdd, overapprox, 1, 1);
+  } else {
+    iterate = mdd_dup(invariantMdd);
+  }
+
+  /* See if we need to enter the loop at all */
+  if( mdd_is_tautology(iterate, 0) ||
+      McCheckEarlyTerminationForOverapprox(earlyTermination,
+					   iterate,
+					   careStatesArray)){
+    mdd_free(mddOne);
+
+    if(fixpoint != NIL(boolean)) *fixpoint = mdd_is_tautology(iterate, 0);
+    return(iterate);
+  }
+
+  /* read fairness constraints */
+  buchiFairness = array_alloc(mdd_t *, 0);
+  if(modelFairness != NIL(Fsm_Fairness_t)) {
+    if(!Fsm_FairnessTestIsBuchi(modelFairness)) {
+      (void)fprintf(vis_stdout,
+	       "** mc error: non-Buechi fairness constraints not supported\n");
+      array_free(buchiFairness);
+      mdd_free(iterate);
+      mdd_free(mddOne);
+
+      if(fixpoint != NIL(boolean)) *fixpoint = FALSE;
+      return NIL(mdd_t);
+    }
+    else {
+      int j;
+      int numBuchi = Fsm_FairnessReadNumConjunctsOfDisjunct(modelFairness, 0);
+      for (j = 0 ; j < numBuchi; j++) {
+	mdd_t *tmpMdd = Fsm_FairnessObtainFinallyInfMdd(modelFairness, 0, j,
+						careStatesArray, dcLevel);
+	array_insert_last(mdd_t *, buchiFairness, tmpMdd);
+      }
+    }
+  }
+  else {
+    array_insert_last(mdd_t *, buchiFairness, mdd_one(mddManager));
+  }
+
+
+  /* GFP.  If we know that the result is a subset of a set S, we can conjoin
+   the iterate with that set.  We use this to converge faster.  */
+  while (TRUE) {
+    mdd_t *newIterate;           /* the new iterate */
+
+    nIterations++;
+    newIterate = mdd_dup(iterate);
+    
+    /* for all fairness constraints */
+    for (i = 0 ; i < array_n(buchiFairness) ; i++) {
+      mdd_t *aMdd, *bMdd, *cMdd, *dMdd;
+      mdd_t *FiMdd = array_fetch(mdd_t *, buchiFairness, i);
+      
+      if(useRings) {
+	onionRings = array_alloc(mdd_t *, 0);
+	array_insert_last(array_t *, *pOnionRingsArrayForDbg, onionRings);
+      }
+
+      aMdd = mdd_and(FiMdd, newIterate, 1, 1);
+
+      bMdd = Mc_FsmEvaluateESFormula(modelFsm, newIterate, aMdd, NIL(mdd_t),
+				     mddOne, careStatesArray,
+				     MC_NO_EARLY_TERMINATION, NIL(array_t),
+				     Mc_None_c, onionRings, verbosity, dcLevel,
+				     NIL(boolean));  
+      mdd_free(aMdd);
+      cMdd = Mc_FsmEvaluateEYFormula(modelFsm, bMdd, mddOne, careStatesArray,
+				     verbosity, dcLevel);
+      mdd_free(bMdd);
+
+      dMdd  = mdd_and(newIterate, cMdd, 1, 1);
+
+      mdd_free(cMdd);
+      mdd_free(newIterate);
+      newIterate = dMdd;
+
+      /* invariants that hold here: newiterate <= iterate <= invariant. */
+    }/* for all fairness constraints */
+
+    /* termination */
+    term_tautology = mdd_is_tautology(newIterate, 0);
+    if(!term_tautology)
+      term_fixpoint =  mdd_equal_mod_care_set_array(newIterate, iterate,
+						    careStatesArray);
+    if(!term_tautology && !term_fixpoint)
+      term_early = McCheckEarlyTerminationForOverapprox(earlyTermination,
+							newIterate, 
+							careStatesArray);
+    if(term_tautology || term_fixpoint || term_early){
+      mdd_free(iterate);
+      iterate = newIterate;
+      break; /* from the GFP loop */
+    }
+
+    /* update iterate */
+    mdd_free(iterate);
+    iterate = newIterate;
+
+    if(useRings){
+      mdd_array_array_free(*pOnionRingsArrayForDbg);
+      *pOnionRingsArrayForDbg = array_alloc(array_t *, 0);
+    }
+  } /* while(true) for gfp */
+
+  /* Check if onionrings are OK */
+  if(verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) {
+    if(useRings){
+      for (i = 0 ; i < array_n(*pOnionRingsArrayForDbg); i++) {
+	int j;
+	mdd_t *Fi = array_fetch(mdd_t *,  buchiFairness, i);
+	array_t *onionRings = array_fetch(array_t *, *pOnionRingsArrayForDbg,
+					  i); 
+	for (j = 0 ; j < array_n(onionRings); j++) {
+	  mdd_t *ring = array_fetch(mdd_t *, onionRings, j);
+	  if(j == 0) {
+	    if(!mdd_lequal_mod_care_set_array(ring, Fi, 1, 1,
+					       careStatesArray)) {
+	      fprintf(vis_stderr, "** mc error: Problem w/ dbg in EH - ");
+	      fprintf(vis_stderr,
+		      "inner most ring not in Fi (fairness constraint).\n");
+	    }
+	  }
+	  if(!mdd_lequal_mod_care_set_array(ring, invariantMdd, 1, 1,
+					     careStatesArray)) {
+	    fprintf(vis_stderr, "** mc error: Problem w/ dbg in EH - ");
+	    fprintf(vis_stderr, "An onion ring of last ES fails invariant\n");
+	  }
+	} /* for all onionrings in array i */ 
+      } /* for all onionringarrays in onionringsarray */
+    }/* if useRings */
+
+    if(verbosity == McVerbosityMax_c) {
+      mdd_t *tmpMdd = careStatesArray ?
+	mdd_and_array(iterate, careStatesArray, 1, 1) : mdd_dup(iterate);
+      fprintf(vis_stdout,
+	      "--There are %.0f care states satisfying EH formula\n",
+	      mdd_count_onset(Fsm_FsmReadMddManager(modelFsm), tmpMdd,
+				Fsm_FsmReadPresentStateVars(modelFsm)));
+#ifdef DEBUG_MC
+      /* The following 2 lines are just for debug */
+      fprintf(vis_stdout, "EH satisfying minterms :\n");
+      (void)_McPrintSatisfyingMinterms(tmpMdd, modelFsm);
+#endif
+      mdd_free(tmpMdd);
+    } else {
+      fprintf(vis_stdout, "--There are %.0f states satisfying EH formula\n",
+	      mdd_count_onset(Fsm_FsmReadMddManager(modelFsm), iterate,
+				Fsm_FsmReadPresentStateVars(modelFsm)));
+    }
+
+    fprintf(vis_stdout, "--EH: %d iterations, %d image computations\n",
+      nIterations, Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps);
+  }
+
+  mdd_array_free(buchiFairness);
+  mdd_free(mddOne);
+
+  if(fixpoint != NIL(boolean))
+     *fixpoint = term_fixpoint || term_tautology;
+  return iterate;
+
+} /* McEvaluateEHFormulaWithGivenTR */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees memory stored at formula corresponding to debug data.]
+
+  Description [Frees memory stored at formula corresponding to debug data.  It
+  is assumed that the debug data is valid.  It is an error to call this
+  function on a formula which is not of the type EG or EU.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McFormulaFreeDebugData(
+  Ctlp_Formula_t *formula)
+{
+  Ctlp_FormulaType  type     = Ctlp_FormulaReadType(formula);
+  array_t          *dbgArray = (array_t *) Ctlp_FormulaReadDebugData(formula);
+
+  if (type == Ctlp_EU_c || type == Ctlp_FwdU_c) {
+    mdd_array_free(dbgArray);
+  }
+  else if (type == Ctlp_EG_c || type == Ctlp_FwdG_c || type == Ctlp_EH_c) 
+    mdd_array_array_free(dbgArray);
+  else {
+    fail("Error - called on non EG/EU formula.\n");
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Print satisfying minterms.]
+
+  Description [Print satisfying minterms. Just made for debug.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+_McPrintSatisfyingMinterms(mdd_t *aMdd, Fsm_Fsm_t *fsm)
+{
+  array_t *support = Fsm_FsmReadPresentStateVars(fsm);
+  mdd_manager *mddMgr = Fsm_FsmReadMddManager(fsm);
+  Ntk_Network_t *network = Fsm_FsmReadNetwork(fsm);
+  int i, n;
+  array_t *mintermArray;
+  mdd_t *aMinterm;
+
+  n = (int) mdd_count_onset(mddMgr, aMdd, support);
+  mintermArray = mdd_pick_arbitrary_minterms(mddMgr, aMdd, support, n);
+
+  for (i = 0; i < n; i++) {
+    aMinterm = array_fetch(mdd_t *, mintermArray, i);
+    Mc_MintermPrint(aMinterm, support, network);
+    mdd_free(aMinterm);
+  }
+
+  array_free(mintermArray);
+
+}
+
+/**Function********************************************************************
+
+  Synopsis [Prints whether model checking passed or failed]
+
+  Description [Prints whether model checking passed or failed, and if
+  requested, a debug trace.]
+
+  SideEffects []
+
+******************************************************************************/
+boolean
+McPrintPassFail(
+  mdd_manager *mddMgr,
+  Fsm_Fsm_t *modelFsm,
+  Mc_FwdBwdAnalysis traversalDirection,
+  Ctlp_Formula_t *ctlFormula,
+  mdd_t *ctlFormulaStates,
+  mdd_t *modelInitialStates,
+  array_t *modelCareStatesArray,
+  McOptions_t *options,
+  Mc_VerbosityLevel verbosity)
+{
+  if (mdd_lequal(modelInitialStates, ctlFormulaStates, 1, 1)) {
+    fprintf(vis_stdout, "# MC: formula passed --- ");
+    Ctlp_FormulaPrint(vis_stdout, Ctlp_FormulaReadOriginalFormula(ctlFormula));
+    fprintf(vis_stdout, "\n");
+    return TRUE;
+  }
+  else {
+    fprintf(vis_stdout, "# MC: formula failed --- ");
+    Ctlp_FormulaPrint(vis_stdout, Ctlp_FormulaReadOriginalFormula(ctlFormula));
+    fprintf(vis_stdout, "\n");
+    if (McOptionsReadDbgLevel(options) != McDbgLevelNone_c) {
+      McFsmDebugFormula(options, ctlFormula,modelFsm, modelCareStatesArray);
+    }
+    return FALSE;
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Find Mdd for states satisfying Atomic Formula.]
+
+  Description [An atomic formula defines a set of states in the following
+  way: it states a designated ``net'' (specified by the full path name)
+  takes a certain value. The net should be purely a function of latches;
+  as a result an evaluation of the net yields a set of states.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+McModelCheckAtomicFormula(
+  Fsm_Fsm_t *modelFsm,
+  Ctlp_Formula_t *ctlFormula)
+{
+  mdd_t * resultMdd;
+  mdd_t *tmpMdd;
+  Ntk_Network_t *network = Fsm_FsmReadNetwork(modelFsm);
+  char *nodeNameString = Ctlp_FormulaReadVariableName(ctlFormula);
+  char *nodeValueString = Ctlp_FormulaReadValueName(ctlFormula);
+  Ntk_Node_t *node = Ntk_NetworkFindNodeByName(network, nodeNameString);
+
+  Var_Variable_t *nodeVar;
+  int nodeValue;
+
+  graph_t *modelPartition;
+  vertex_t *partitionVertex;
+  Mvf_Function_t *MVF;
+
+  nodeVar = Ntk_NodeReadVariable(node);
+  if (Var_VariableTestIsSymbolic(nodeVar)) {
+    nodeValue = Var_VariableReadIndexFromSymbolicValue(nodeVar, nodeValueString);
+  }
+  else {
+    nodeValue = atoi(nodeValueString);
+  }
+
+#if 0
+  modelPartition = Part_NetworkReadPartition(network);
+#endif
+  modelPartition = Fsm_FsmReadPartition(modelFsm);
+  if (!(partitionVertex = Part_PartitionFindVertexByName(modelPartition,
+							 nodeNameString))) {
+    lsGen tmpGen;
+    Ntk_Node_t *tmpNode;
+    array_t *mvfArray;
+    array_t *tmpRoots = array_alloc(Ntk_Node_t *, 0);
+    st_table *tmpLeaves = st_init_table(st_ptrcmp, st_ptrhash);
+    array_insert_last(Ntk_Node_t *, tmpRoots, node);
+
+    Ntk_NetworkForEachCombInput(network, tmpGen, tmpNode) {
+      st_insert(tmpLeaves, (char *) tmpNode, (char *) NTM_UNUSED);
+    }
+
+    mvfArray =  Ntm_NetworkBuildMvfs(network, tmpRoots, tmpLeaves,
+				      NIL(mdd_t));
+    MVF = array_fetch(Mvf_Function_t *, mvfArray, 0);
+    array_free(tmpRoots);
+    st_free_table(tmpLeaves);
+    array_free(mvfArray);
+
+    tmpMdd = Mvf_FunctionReadComponent(MVF, nodeValue);
+    resultMdd = mdd_dup(tmpMdd);
+    Mvf_FunctionFree(MVF);
+  }
+  else {
+    MVF = Part_VertexReadFunction(partitionVertex);
+    tmpMdd = Mvf_FunctionReadComponent(MVF, nodeValue);
+    resultMdd = mdd_dup(tmpMdd);
+  }
+  if (Part_PartitionReadMethod(modelPartition) == Part_Frontier_c &&
+      Ntk_NodeTestIsCombOutput(node)) {
+    array_t	*psVars = Fsm_FsmReadPresentStateVars(modelFsm);
+    mdd_manager	*mgr = Ntk_NetworkReadMddManager(Fsm_FsmReadNetwork(modelFsm));
+    array_t	*supportList;
+    st_table	*supportTable = st_init_table(st_numcmp, st_numhash);
+    int		i, j;
+    int		existIntermediateVars;
+    int		mddId;
+    Mvf_Function_t	*mvf;
+    vertex_t	*vertex;
+    array_t	*varBddRelationArray, *varArray;
+    mdd_t	*iv, *ivMdd, *relation;
+
+    for (i = 0; i < array_n(psVars); i++) {
+      mddId = array_fetch(int, psVars, i);
+      st_insert(supportTable, (char *)(long)mddId, NULL);
+    }
+
+    existIntermediateVars = 1;
+    while (existIntermediateVars) {
+      existIntermediateVars = 0;
+      supportList = mdd_get_support(mgr, resultMdd);
+      for (i = 0; i < array_n(supportList); i++) {
+	mddId = array_fetch(int, supportList, i);
+	if (!st_lookup(supportTable, (char *)(long)mddId, NULL)) {
+	  vertex = Part_PartitionFindVertexByMddId(modelPartition, mddId);
+	  mvf = Part_VertexReadFunction(vertex);
+	  varBddRelationArray = mdd_fn_array_to_bdd_rel_array(mgr, mddId, mvf);
+	  varArray = mdd_id_to_bdd_array(mgr, mddId);
+	  assert(array_n(varBddRelationArray) == array_n(varArray));
+	  for (j = 0; j < array_n(varBddRelationArray); j++) {
+	    iv = array_fetch(mdd_t *, varArray, j);
+	    relation = array_fetch(mdd_t *, varBddRelationArray, j);
+	    ivMdd = bdd_cofactor(relation, iv);
+	    mdd_free(relation);
+	    tmpMdd = resultMdd;
+	    resultMdd = bdd_compose(resultMdd, iv, ivMdd);
+	    mdd_free(tmpMdd);
+	    mdd_free(iv);
+	    mdd_free(ivMdd);
+	  }
+	  array_free(varBddRelationArray);
+	  array_free(varArray);
+	  existIntermediateVars = 1;
+	}
+      }
+      array_free(supportList);
+    }
+    st_free_table(supportTable);
+  }
+  return resultMdd;
+} /* McModelCheckAtomicFormula */
+
+
+/**Function********************************************************************
+
+  Synopsis [Prints out a path from the initial state to a state that
+  violates the invariant. ]
+
+  Description [Prints out a path from the initial state to a state
+  that violates the invariant. First it checks whether there any onion
+  rings built for this fsm. If the onion rings already exist, it
+  checks whether there is any violation in these rings. If not,
+  additional onion rings are computed.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+InvarPrintDebugInformation(Fsm_Fsm_t *modelFsm,
+			   array_t *invarFormulaArray,
+			   array_t *invarStatesArray,
+			   int *resultArray,
+			   McOptions_t *options,
+			   array_t *hintsStatesArray)
+{
+  FILE *debugFile = McOptionsReadDebugFile(options);
+  FILE *tmpFile = vis_stdout;
+  extern FILE *vis_stdpipe;
+  mdd_t *outerOnionRing=NIL(mdd_t);
+  mdd_t *reachableBadStates;
+  mdd_t *aBadReachableState, *reachableStates;
+  array_t *aPath;
+  boolean computeReach = TRUE;
+  int ringsUpToDate;
+  array_t *onionRings=NIL(array_t);
+  int i, j;
+  Fsm_RchType_t approxFlag;
+  Ctlp_Formula_t *invarFormula;
+  mdd_t *invarFormulaStates;
+  approxFlag = McOptionsReadInvarApproxFlag(options);
+
+  if (debugFile)
+    vis_stdpipe = debugFile;
+  else if (McOptionsReadUseMore(options) == TRUE)
+    vis_stdpipe = popen("more", "w");
+  else
+    vis_stdpipe = vis_stdout;
+  vis_stdout = vis_stdpipe;
+
+  arrayForEachItem(mdd_t *, invarStatesArray, i, invarFormulaStates) {
+    if ((invarFormulaStates == NIL(mdd_t)) || (resultArray[i] == 1))
+      continue;
+    onionRings = Fsm_FsmReadReachabilityOnionRings(modelFsm);
+    ringsUpToDate = Fsm_FsmTestReachabilityOnionRingsUpToDate(modelFsm);
+    /* search for onion ring intersecting invarStates' */
+    if (onionRings != NIL(array_t)) {
+      for (j = 0; j < array_n(onionRings); j++) {
+	outerOnionRing = array_fetch(mdd_t *, onionRings, j);
+	if (!mdd_lequal(outerOnionRing, invarFormulaStates, 1, 1)) {
+	  computeReach = FALSE;
+	  break;
+	}
+      }
+    }
+
+    /* no onion ring found, hence recompute with onion rings */
+    if (computeReach == TRUE) {
+      Mc_VerbosityLevel verbosity;
+      int debugFlag;
+      int ardc;
+      int dcLevel = McOptionsReadDcLevel(options);
+      verbosity = McOptionsReadVerbosityLevel(options);
+      debugFlag = (McOptionsReadDbgLevel(options) != McDbgLevelNone_c);
+      if (dcLevel == McDcLevelArdc_c)
+	ardc = 1;
+      else
+	ardc = 0;
+      assert(!ringsUpToDate);
+      reachableStates = Fsm_FsmComputeReachableStates(
+	modelFsm, 0, (int)verbosity , 0, 0, debugFlag, 0, 0, approxFlag, ardc,
+	0, invarStatesArray, (verbosity > 1), hintsStatesArray);
+      mdd_free(reachableStates);
+      /* find the onion ring with invariant failure */
+      onionRings = Fsm_FsmReadReachabilityOnionRings(modelFsm);
+      if (onionRings == NIL(array_t)) {
+	fprintf(vis_stdout, "Unable to generate onion rings for counterexample.\n");
+	fprintf(vis_stdout, "Try again with standard (without -A) options.\n");
+	if (vis_stdout != tmpFile && vis_stdout != debugFile)
+	  (void)pclose(vis_stdpipe);
+	vis_stdout = tmpFile;
+	return;
+      }
+      ringsUpToDate = Fsm_FsmTestReachabilityOnionRingsUpToDate(modelFsm);
+      for (j = 0; j < array_n(onionRings); j++) {
+	outerOnionRing = array_fetch(mdd_t *, onionRings, j);
+	if (!mdd_lequal(outerOnionRing, invarFormulaStates, 1, 1)) {
+	  break;
+	}
+      }
+    }
+    invarFormula = array_fetch(Ctlp_Formula_t *, invarFormulaArray, i);
+    /* this is the case of  true negative */
+    if (outerOnionRing != NIL(mdd_t)) {
+      /* compute the set of bad states */
+      if(Fsm_FsmReadFAFWFlag(modelFsm) > 1 && McOptionsReadInvarApproxFlag(options) == Fsm_Rch_Bfs_c)
+        reachableBadStates = mdd_not(invarFormulaStates);
+      else
+        reachableBadStates = mdd_and(invarFormulaStates, outerOnionRing, 0, 1);
+      /* pick one bad state */
+      aBadReachableState = Mc_ComputeAState(reachableBadStates, modelFsm);
+      mdd_free(reachableBadStates);
+
+      /* build a path from the initial states to the bad state */
+      aPath = Mc_BuildPathFromCore(aBadReachableState, onionRings,
+				   modelFsm, McGreaterOrEqualZero_c);
+      mdd_free(aBadReachableState);
+
+
+      if(McOptionsReadDbgLevel(options)==2)
+      {
+
+        (void) Mc_PrintPathAiger(aPath, modelFsm, McOptionsReadPrintInputs(options));
+      }
+      else
+      {
+        (void) fprintf(vis_stdout, "# INV: formula %d failed --- ", i+1);
+        Ctlp_FormulaPrint(vis_stdout,
+			Ctlp_FormulaReadOriginalFormula(invarFormula));
+        fprintf(vis_stdout, "\n");
+
+        (void) fprintf(vis_stdout, "# INV: calling debugger\n");
+        if (array_n(aPath) > 1) {
+	  (void) fprintf(vis_stdout,
+			"# INV: a sequence of states starting at an initial ");
+	  (void) fprintf(vis_stdout, "state leading to a bad state\n");
+        } else {
+	  (void) fprintf(vis_stdout,
+		    "# INV: invariant fails at the following initial state\n");
+        }
+        (void) Mc_PrintPath(aPath, modelFsm, McOptionsReadPrintInputs(options));
+      }
+      (void) fprintf(vis_stdout, "\n");
+
+      McNormalizeBddPointer(aPath);
+      mdd_array_free(aPath);
+    } else {
+      /* Was a false negative */
+      assert (approxFlag == Fsm_Rch_Oa_c);
+      (void) fprintf(vis_stdout, "# INV: formula passed --- ");
+      Ctlp_FormulaPrint(vis_stdout,
+			Ctlp_FormulaReadOriginalFormula(invarFormula));
+      fprintf(vis_stdout, "\n");
+    }
+  }
+
+  if (vis_stdout != tmpFile && vis_stdout != debugFile)
+    (void)pclose(vis_stdpipe);
+  vis_stdout = tmpFile;
+} /* end of InvarPrintDebugInformation */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sort formulae by fsm]
+
+  Description [Sort formulae by fsm. This creates an array of array of
+  formulae. Each element of the outer array corresponds to an fsm
+  reduced w.r.t the element (array of formulae). Both the array of
+  formulae and the reduced fsms are returned. If there is no
+  reduction, the reduced fsm is set to the totalFsm. While freeing the
+  reduced fsms in the fsmArray, if the reduced fsm is set to total
+  fsm, DO NOT free. ]
+
+  SideEffects [fsmArray is populated with reduced fsms.]
+
+******************************************************************************/
+array_t *
+SortFormulasByFsm(Fsm_Fsm_t *totalFsm,
+		  array_t *invarFormulaArray,
+		  array_t *fsmArray,
+		  McOptions_t *options)
+{
+  array_t *resultArray;
+  array_t *formulaArray;
+  array_t *tempArray;
+  int i, j, found;
+  Ctlp_Formula_t *formula;
+  Ntk_Network_t *network = Fsm_FsmReadNetwork(totalFsm);
+  Fsm_Fsm_t *reducedFsm, *fsm;
+  int reducedFsmPos = -1;
+
+  if (invarFormulaArray == NIL(array_t)) return invarFormulaArray;
+  if (array_n(invarFormulaArray) == 0) return NIL(array_t);
+
+  tempArray = array_alloc(array_t *, 0);
+  /* do a semantic check and a quantifier check */
+  arrayForEachItem (Ctlp_Formula_t *, invarFormulaArray, i, formula) {
+    if (!Mc_FormulaStaticSemanticCheckOnNetwork(formula, network, FALSE)){
+      (void) fprintf(vis_stderr, "** inv error: error in parsing Atomic Formula:\n%s\n", error_string());
+      error_init();
+      Ctlp_FormulaFree(formula);
+      continue;
+    } else {
+      if (Ctlp_FormulaTestIsQuantifierFree(formula) == FALSE) {
+	(void) fprintf(vis_stderr, "** inv error: invariant formula refers to path quantifiers\n");
+	Ctlp_FormulaFree(formula);
+	continue;
+      }
+    }
+    array_insert_last(Ctlp_Formula_t *, tempArray, formula);
+  }
+  if (array_n(tempArray) == 0) {
+    array_free(tempArray);
+    return NIL(array_t);
+  }
+
+  /* if no -r option, return the original array */
+  resultArray = array_alloc(array_t *, 0);
+  if (McOptionsReadReduceFsm(options) == FALSE) {
+    array_insert_last(array_t *, resultArray, tempArray);
+    reducedFsm = McConstructReducedFsm(network, tempArray);
+    if (reducedFsm != NIL(Fsm_Fsm_t)) {
+      array_insert_last(Fsm_Fsm_t *, fsmArray, reducedFsm);
+    } else {
+      array_insert_last(Fsm_Fsm_t *, fsmArray, totalFsm);
+    }
+    return resultArray;
+  }
+
+  /* We want to minimize per formula only when "-r" option is not specified */
+  arrayForEachItem (Ctlp_Formula_t *, tempArray, i, formula) {
+    /* Create reduced fsm */
+    formulaArray = array_alloc(Ctlp_Formula_t *, 0);
+    array_insert_last(Ctlp_Formula_t *, formulaArray, formula);
+
+    reducedFsm = McConstructReducedFsm(network, formulaArray);
+    if (reducedFsm == NIL(Fsm_Fsm_t)) {
+      /* no reduction */
+      reducedFsm = totalFsm;
+    }
+
+    /* Check if fsm already created */
+    found = 0;
+    for (j = 0; j < array_n(fsmArray); j++) {
+      fsm = array_fetch (Fsm_Fsm_t *, fsmArray, j);
+      found = Fsm_FsmCheckSameSubFsmInTotalFsm(totalFsm, reducedFsm, fsm);
+      if (found) break;
+    }
+
+    /* If found, add to the existing list. Else add a new reduced fsm */
+    if (found) {
+      if (reducedFsm != totalFsm) Fsm_FsmFree(reducedFsm);
+      array_free(formulaArray);
+      formulaArray = array_fetch(array_t *, resultArray, j);
+      array_insert_last(Ctlp_Formula_t *, formulaArray, formula);
+    } else {
+      array_insert_last(Fsm_Fsm_t *, fsmArray, reducedFsm);
+      array_insert_last(array_t *, resultArray, formulaArray);
+      if (reducedFsm == totalFsm) reducedFsmPos = array_n(fsmArray)-1;
+    }
+  }
+
+  array_free(tempArray);
+  /* swap the last reduced fsm with the total fsm. */
+  if ((reducedFsmPos != -1) && (reducedFsmPos != array_n(fsmArray)-1)) {
+    array_t *totalFsmFormulaArray;
+    assert(array_n(fsmArray) == array_n(resultArray));
+    fsm = array_fetch(Fsm_Fsm_t *, fsmArray, array_n(fsmArray)-1);
+    array_insert(Fsm_Fsm_t *, fsmArray, reducedFsmPos, fsm);
+    array_insert(Fsm_Fsm_t *, fsmArray, array_n(fsmArray)-1, totalFsm);
+    formulaArray =  array_fetch(array_t *, resultArray, array_n(resultArray)-1);
+    totalFsmFormulaArray = array_fetch(array_t *, resultArray, reducedFsmPos);
+    array_insert(array_t *, resultArray, reducedFsmPos, formulaArray);
+    array_insert(array_t *, resultArray, array_n(resultArray)-1, totalFsmFormulaArray);
+  }
+
+  return resultArray;
+} /* end of SortFormulasByFsm */
+
+
+/**Function********************************************************************
+
+  Synopsis [Test if an invariant is violated in the current reachable
+  set of the given FSM.]
+
+  Description [Test if an invariant is violated in the current
+  reachable set of the given FSM. Returns FALSE if an invariant is
+  violated and TRUE is no invariant is violated.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+TestInvariantsInTotalFsm(Fsm_Fsm_t *totalFsm,
+			 array_t *invarStatesArray,
+			 int shellFlag)
+{
+  int i;
+  mdd_t *invariant;
+  mdd_t *reachableStates;
+  boolean upToDate = FALSE; /* don't care initialization */
+  if (shellFlag) {
+    upToDate = Fsm_FsmReachabilityOnionRingsStates(totalFsm, &reachableStates);
+  } else {
+    reachableStates = Fsm_FsmReadCurrentReachableStates(totalFsm);
+  }
+  if (reachableStates == NIL(mdd_t)) return TRUE;
+  if (mdd_is_tautology(reachableStates, 0)) return TRUE;
+  
+  arrayForEachItem(mdd_t *, invarStatesArray, i, invariant) {
+    if (invariant == NIL(mdd_t)) continue;
+    if (!mdd_lequal(reachableStates, invariant, 1, 1)) {
+      if (shellFlag) mdd_free(reachableStates);
+      return FALSE;
+    }
+  }
+  if (shellFlag) mdd_free(reachableStates);
+  if ((shellFlag && !upToDate) ||
+      (Fsm_FsmReadReachabilityApproxComputationStatus(totalFsm) ==
+       Fsm_Rch_Under_c))
+    return TRUE;
+  else
+    return FALSE;
+    
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compute the approximation of the result for
+  EvaluateFormulaRecur.]
+
+  Description []
+
+  SideEffects [None]
+
+  SeeAlso     [EvaluateFormulaRecur]
+
+******************************************************************************/
+Ctlp_Approx_t
+ComputeResultingApproximation(
+  Ctlp_FormulaType formulaType,
+  Ctlp_Approx_t leftApproxType,
+  Ctlp_Approx_t rightApproxType,
+  Ctlp_Approx_t TRMinimization,
+  Mc_EarlyTermination_t *earlyTermination,
+  boolean fixpoint)
+{
+  Ctlp_Approx_t thisApproxType;
+
+  switch (formulaType) {
+  case Ctlp_ID_c:
+  case Ctlp_TRUE_c:
+  case Ctlp_FALSE_c:
+    thisApproxType = Ctlp_Exact_c;
+    break;
+  case Ctlp_NOT_c:
+    if (leftApproxType == Ctlp_Incomparable_c) {
+      thisApproxType = Ctlp_Incomparable_c;
+    } else if (leftApproxType == Ctlp_Overapprox_c) {
+      thisApproxType = Ctlp_Underapprox_c;
+    } else if (leftApproxType == Ctlp_Underapprox_c) {
+      thisApproxType = Ctlp_Overapprox_c;
+    } else {
+      thisApproxType = Ctlp_Exact_c;
+    }
+    break;
+  case Ctlp_AND_c:
+    if (leftApproxType == Ctlp_Incomparable_c ||
+	rightApproxType == Ctlp_Incomparable_c ||
+	(leftApproxType == Ctlp_Overapprox_c &&
+	 rightApproxType == Ctlp_Underapprox_c) ||
+	(leftApproxType == Ctlp_Underapprox_c &&
+	 rightApproxType == Ctlp_Overapprox_c)) {
+      thisApproxType = Ctlp_Incomparable_c;
+    } else if (rightApproxType == Ctlp_Overapprox_c) {
+      if (earlyTermination == MC_NO_EARLY_TERMINATION &&
+	  leftApproxType == Ctlp_Exact_c) {
+	thisApproxType = Ctlp_Exact_c;
+      } else {
+	thisApproxType = Ctlp_Overapprox_c;
+      }
+    } else if (leftApproxType == Ctlp_Overapprox_c) {
+      thisApproxType = Ctlp_Overapprox_c;
+    } else if (rightApproxType == Ctlp_Underapprox_c) {
+      if (earlyTermination == MC_NO_EARLY_TERMINATION &&
+	  leftApproxType == Ctlp_Exact_c) {
+	thisApproxType = Ctlp_Exact_c;
+      } else {
+	thisApproxType = Ctlp_Underapprox_c;
+      }
+    } else if (leftApproxType == Ctlp_Underapprox_c) {
+      thisApproxType = Ctlp_Underapprox_c;
+    } else {
+      thisApproxType = Ctlp_Exact_c;
+    }
+    break;
+  case Ctlp_EQ_c:
+  case Ctlp_XOR_c:
+    if (leftApproxType != Ctlp_Exact_c || rightApproxType != Ctlp_Exact_c) {
+      thisApproxType = Ctlp_Incomparable_c;
+    } else {
+      thisApproxType = Ctlp_Exact_c;
+    }
+    break;
+  case Ctlp_THEN_c:
+    if (leftApproxType == Ctlp_Incomparable_c ||
+	rightApproxType == Ctlp_Incomparable_c ||
+	(leftApproxType == Ctlp_Overapprox_c &&
+	 rightApproxType == Ctlp_Overapprox_c) ||
+	(leftApproxType == Ctlp_Underapprox_c &&
+	 rightApproxType == Ctlp_Underapprox_c)) {
+      thisApproxType = Ctlp_Incomparable_c;
+    } else if (rightApproxType == Ctlp_Overapprox_c) {
+      if (earlyTermination == MC_NO_EARLY_TERMINATION &&
+	  leftApproxType == Ctlp_Exact_c) {
+	thisApproxType = Ctlp_Exact_c;
+      } else {
+	thisApproxType = Ctlp_Overapprox_c;
+      }
+    } else if (leftApproxType == Ctlp_Underapprox_c) {
+      thisApproxType = Ctlp_Overapprox_c;
+    } else if (rightApproxType == Ctlp_Underapprox_c) {
+      if (earlyTermination == MC_NO_EARLY_TERMINATION &&
+	  leftApproxType == Ctlp_Exact_c) {
+	thisApproxType = Ctlp_Exact_c;
+      } else {
+	thisApproxType = Ctlp_Underapprox_c;
+      }
+    } else if (leftApproxType == Ctlp_Overapprox_c) {
+      thisApproxType = Ctlp_Underapprox_c;
+    } else {
+      thisApproxType = Ctlp_Exact_c;
+    }
+    break;
+  case Ctlp_OR_c:
+    if (leftApproxType == Ctlp_Incomparable_c ||
+	rightApproxType == Ctlp_Incomparable_c ||
+	(leftApproxType == Ctlp_Overapprox_c &&
+	 rightApproxType == Ctlp_Underapprox_c) ||
+	(leftApproxType == Ctlp_Underapprox_c &&
+	 rightApproxType == Ctlp_Overapprox_c)) {
+      thisApproxType = Ctlp_Incomparable_c;
+    } else if (rightApproxType == Ctlp_Overapprox_c) {
+      if (earlyTermination == MC_NO_EARLY_TERMINATION &&
+	  leftApproxType == Ctlp_Exact_c) {
+	thisApproxType = Ctlp_Exact_c;
+      } else {
+	thisApproxType = Ctlp_Overapprox_c;
+      }
+    } else if (leftApproxType == Ctlp_Overapprox_c) {
+      thisApproxType = Ctlp_Overapprox_c;
+    } else if (rightApproxType == Ctlp_Underapprox_c) {
+      if (earlyTermination == MC_NO_EARLY_TERMINATION &&
+	  leftApproxType == Ctlp_Exact_c) {
+	thisApproxType = Ctlp_Exact_c;
+      } else {
+	thisApproxType = Ctlp_Underapprox_c;
+      }
+    } else if (leftApproxType == Ctlp_Underapprox_c) {
+      thisApproxType = Ctlp_Underapprox_c;
+    } else {
+      thisApproxType = Ctlp_Exact_c;
+    }
+    break;
+  case Ctlp_EX_c:
+    if (leftApproxType == Ctlp_Underapprox_c) {
+      if (TRMinimization == Ctlp_Overapprox_c) {
+	thisApproxType = Ctlp_Incomparable_c;
+      } else {
+	thisApproxType = Ctlp_Underapprox_c;
+      }
+    } else if (leftApproxType == Ctlp_Overapprox_c) {
+      if (TRMinimization == Ctlp_Underapprox_c) {
+	thisApproxType = Ctlp_Incomparable_c;
+      } else {
+	thisApproxType = Ctlp_Overapprox_c;
+      }
+    } else if (leftApproxType == Ctlp_Exact_c) {
+      thisApproxType = TRMinimization;
+    } else {
+      thisApproxType = Ctlp_Incomparable_c;
+    }
+    break;
+  case Ctlp_EU_c:
+    if (leftApproxType == Ctlp_Incomparable_c ||
+	rightApproxType == Ctlp_Incomparable_c ||
+	(leftApproxType == Ctlp_Overapprox_c &&
+	 rightApproxType == Ctlp_Underapprox_c) ||
+	(leftApproxType == Ctlp_Underapprox_c &&
+	 rightApproxType == Ctlp_Overapprox_c)) {
+      thisApproxType = Ctlp_Incomparable_c;
+    } else if (leftApproxType == Ctlp_Overapprox_c ||
+	       rightApproxType == Ctlp_Overapprox_c) {
+      thisApproxType = Ctlp_Overapprox_c;
+    } else if (leftApproxType == Ctlp_Underapprox_c ||
+	       rightApproxType == Ctlp_Underapprox_c) {
+      thisApproxType = Ctlp_Underapprox_c;
+    } else {
+      thisApproxType = Ctlp_Exact_c;
+    }
+    if (!fixpoint) {
+      if (TRMinimization == Ctlp_Overapprox_c ||
+	  thisApproxType == Ctlp_Overapprox_c) {
+	thisApproxType = Ctlp_Incomparable_c;
+      } else if (thisApproxType == Ctlp_Exact_c) {
+	thisApproxType = Ctlp_Underapprox_c;
+      }
+    } else {
+      if ((TRMinimization == Ctlp_Overapprox_c &&
+	   thisApproxType == Ctlp_Underapprox_c) ||
+	  (TRMinimization == Ctlp_Underapprox_c &&
+	   thisApproxType == Ctlp_Overapprox_c)) {
+	thisApproxType = Ctlp_Incomparable_c;
+      } else if (thisApproxType == Ctlp_Exact_c) {
+	thisApproxType = TRMinimization;
+      }
+    }
+    break;
+  case Ctlp_EG_c:
+    if (leftApproxType == Ctlp_Incomparable_c ||
+	rightApproxType == Ctlp_Incomparable_c ||
+	(leftApproxType == Ctlp_Overapprox_c &&
+	 rightApproxType == Ctlp_Underapprox_c) ||
+	(leftApproxType == Ctlp_Underapprox_c &&
+	 rightApproxType == Ctlp_Overapprox_c)) {
+      thisApproxType = Ctlp_Incomparable_c;
+    } else if (leftApproxType == Ctlp_Overapprox_c ||
+	       rightApproxType == Ctlp_Overapprox_c) {
+      thisApproxType = Ctlp_Overapprox_c;
+    } else if (leftApproxType == Ctlp_Underapprox_c ||
+	       rightApproxType == Ctlp_Underapprox_c) {
+      thisApproxType = Ctlp_Underapprox_c;
+    } else {
+      thisApproxType = Ctlp_Exact_c;
+    }
+    if (!fixpoint) {
+      if (TRMinimization == Ctlp_Underapprox_c ||
+	  thisApproxType == Ctlp_Underapprox_c) {
+	thisApproxType = Ctlp_Incomparable_c;
+      } else if (thisApproxType == Ctlp_Exact_c) {
+	thisApproxType = Ctlp_Overapprox_c;
+      }
+    } else {
+      if ((TRMinimization == Ctlp_Overapprox_c &&
+	   thisApproxType == Ctlp_Underapprox_c) ||
+	  (TRMinimization == Ctlp_Underapprox_c &&
+	   thisApproxType == Ctlp_Overapprox_c)) {
+	thisApproxType = Ctlp_Incomparable_c;
+      } else if (thisApproxType == Ctlp_Exact_c) {
+	thisApproxType = TRMinimization;
+      }
+    }
+    break;
+  case Ctlp_Cmp_c:
+  case Ctlp_Init_c:
+  case Ctlp_FwdU_c:
+  case Ctlp_FwdG_c:
+  case Ctlp_EY_c:
+    /* no early termination and no hints in forward model checking */
+    thisApproxType = Ctlp_Exact_c;
+    break;
+  default: fail("Encountered unknown type of CTL formula\n");
+  }
+
+  return thisApproxType;
+  
+} /* ComputeResultingApproximation */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Model check formula on given fsm under fairness]
+
+  Description [This is the recursive part of Mc_FsmEvaluateFormula]
+
+  Comment [See Mc_EvaluateFormula.  The only difference is that
+  EvaluateFormula takes care of global hints, and passes on an extra
+  flag, TRMinimization that indicates how the current TR related to
+  the exact TR.  Using this flag, the procedure decides in which field
+  of the formula to store results (states, underapproxStates or
+  overapproxStates) ]
+
+  SideEffects []
+
+******************************************************************************/
+static mdd_t *
+EvaluateFormulaRecur(
+  Fsm_Fsm_t *modelFsm,
+  Ctlp_Formula_t *ctlFormula,
+  mdd_t *fairStates,
+  Fsm_Fairness_t *fairCondition,
+  array_t *modelCareStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  Fsm_HintsArray_t *hintsArray,
+  Mc_GuidedSearch_t hintType,
+  Ctlp_Approx_t TRMinimization,
+  Ctlp_Approx_t *resultApproxType,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  int buildOnionRings,
+  Mc_GSHScheduleType GSHschedule)
+{
+  mdd_t *leftMdd  = NIL(mdd_t);
+  mdd_t *rightMdd = NIL(mdd_t);
+  mdd_t *result   = NIL(mdd_t);
+  
+  mdd_manager *mddMgr = Fsm_FsmReadMddManager(modelFsm);
+  array_t     *careStatesArray = NIL(array_t);
+  mdd_t       *tmpMdd;
+  mdd_t       *approx = NIL(mdd_t); /* prev computed approx of sat set */ 
+  mdd_t *ctlFormulaStates = Ctlp_FormulaObtainStates( ctlFormula );
+  Ctlp_Approx_t leftApproxType = Ctlp_Exact_c;
+  Ctlp_Approx_t rightApproxType = Ctlp_Exact_c;
+  Ctlp_Approx_t thisApproxType = Ctlp_Exact_c;
+  boolean fixpoint = FALSE;
+  boolean skipRight = FALSE;
+
+  if ( ctlFormulaStates ) {
+    return ctlFormulaStates;
+  }
+  
+  {
+    Ctlp_Formula_t *leftChild = Ctlp_FormulaReadLeftChild(ctlFormula);
+
+    if (leftChild) {
+      Mc_EarlyTermination_t *nextEarlyTermination =
+	McObtainUpdatedEarlyTerminationCondition(
+	  earlyTermination, NIL(mdd_t), Ctlp_FormulaReadType(ctlFormula));
+
+      leftMdd = EvaluateFormulaRecur(modelFsm, leftChild, fairStates,
+				     fairCondition, modelCareStatesArray,
+				     nextEarlyTermination,
+				     hintsArray, hintType, TRMinimization,
+				     &leftApproxType, verbosity, dcLevel,
+				     buildOnionRings, GSHschedule);
+      Mc_EarlyTerminationFree(nextEarlyTermination);
+      if (!leftMdd) {
+	return NIL(mdd_t);
+      }
+    }
+  }
+
+  {/* read right */
+    Ctlp_Formula_t *rightChild = Ctlp_FormulaReadRightChild(ctlFormula);
+
+    if (rightChild) {
+      Mc_EarlyTermination_t *nextEarlyTermination =
+	McObtainUpdatedEarlyTerminationCondition(
+	  earlyTermination, leftMdd, Ctlp_FormulaReadType(ctlFormula));
+
+      skipRight = Mc_EarlyTerminationIsSkip(nextEarlyTermination);
+      if (!skipRight) {
+	rightMdd = EvaluateFormulaRecur(modelFsm, rightChild, fairStates,
+					fairCondition, modelCareStatesArray,
+					nextEarlyTermination,
+					hintsArray, hintType, TRMinimization,
+					&rightApproxType, verbosity, dcLevel,
+					buildOnionRings, GSHschedule);
+      }
+      Mc_EarlyTerminationFree(nextEarlyTermination);
+      if (!(rightMdd || skipRight)) {
+	if (leftMdd)
+	  mdd_free(leftMdd);
+	return NIL(mdd_t);
+      }
+    }
+  }/* read right */
+
+  if (modelCareStatesArray != NIL(array_t)) {
+    careStatesArray = modelCareStatesArray;
+  } else {
+    careStatesArray = array_alloc(mdd_t *, 0);
+    array_insert_last(mdd_t *, careStatesArray, mdd_one(mddMgr));
+  }
+  switch (Ctlp_FormulaReadType(ctlFormula)) {
+  case Ctlp_ID_c:
+    assert(!skipRight);
+    result = McModelCheckAtomicFormula(modelFsm, ctlFormula);
+    break;
+
+  case Ctlp_TRUE_c:
+    assert(!skipRight);
+    result = mdd_one(mddMgr); break;
+
+  case Ctlp_FALSE_c:
+    assert(!skipRight);
+    result = mdd_zero(mddMgr); break;
+
+  case Ctlp_NOT_c:
+    assert(!skipRight);
+    result = mdd_not(leftMdd); break;
+
+  case Ctlp_AND_c:
+    if (skipRight) {
+      result = mdd_dup(leftMdd);
+      rightApproxType = Ctlp_Overapprox_c;
+    } else {
+      result = mdd_and(leftMdd, rightMdd, 1, 1);
+    }
+    break;
+
+  case Ctlp_EQ_c:
+    assert(!skipRight);
+    result = mdd_xnor(leftMdd, rightMdd); break;
+
+  case Ctlp_XOR_c:
+    assert(!skipRight);
+    result = mdd_xor(leftMdd, rightMdd); break;
+
+  case Ctlp_THEN_c:
+    if (skipRight) {
+      result = mdd_dup(leftMdd);
+      rightApproxType = Ctlp_Underapprox_c;
+    } else {
+      result = mdd_or(leftMdd, rightMdd, 0, 1);
+    }
+    break;
+
+  case Ctlp_OR_c:
+    if (skipRight) {
+      result = mdd_dup(leftMdd);
+      rightApproxType = Ctlp_Underapprox_c;
+    } else {
+      result = mdd_or(leftMdd, rightMdd, 1, 1);
+    }
+    break;
+
+  case Ctlp_EX_c:
+    assert(!skipRight);
+    result = Mc_FsmEvaluateEXFormula(modelFsm, leftMdd, fairStates,
+				     careStatesArray, verbosity, dcLevel);
+    break;
+
+  case Ctlp_EU_c: {
+    array_t *onionRings = NIL(array_t); /* array of mdd_t */
+    boolean newrings;
+
+    assert(!skipRight);
+    /* An underapproximation, together with its explanation may be stored. */
+    approx = Ctlp_FormulaObtainApproxStates( ctlFormula, Ctlp_Underapprox_c );
+    onionRings = (array_t *) Ctlp_FormulaReadDebugData(ctlFormula);
+    newrings = onionRings == NIL(array_t);
+
+    if (buildOnionRings){
+      assert((approx != NIL(mdd_t) && onionRings != NIL(array_t)) ||
+	     (approx == NIL(mdd_t) && onionRings == NIL(array_t)));
+      if(onionRings == NIL(array_t))
+	onionRings = array_alloc(mdd_t *, 0);
+    }
+
+    result = Mc_FsmEvaluateEUFormula(modelFsm, leftMdd, rightMdd,
+				     approx, fairStates,
+				     careStatesArray,
+				     earlyTermination, hintsArray,
+				     hintType, onionRings,
+				     verbosity, dcLevel, &fixpoint);
+
+    if(buildOnionRings && newrings)
+      Ctlp_FormulaSetDbgInfo(ctlFormula, (void *) onionRings,
+			     McFormulaFreeDebugData);
+    if(approx != NIL(mdd_t))
+      mdd_free(approx);
+
+    break;
+  }
+  case Ctlp_EG_c: {
+    array_t  *arrayOfOnionRings = NIL(array_t); /* array of array of mdd_t* */
+
+    assert(!skipRight);
+    if(buildOnionRings)
+      arrayOfOnionRings = array_alloc(array_t *, 0);
+
+    approx = Ctlp_FormulaObtainApproxStates( ctlFormula, Ctlp_Overapprox_c );
+
+    result = Mc_FsmEvaluateEGFormula(modelFsm, leftMdd, approx, fairStates, 
+				     fairCondition, careStatesArray,
+				     earlyTermination, hintsArray, hintType, 
+				     &arrayOfOnionRings, verbosity,
+				     dcLevel, &fixpoint, GSHschedule);
+
+    if(buildOnionRings)
+      Ctlp_FormulaSetDbgInfo(ctlFormula, (void *)arrayOfOnionRings,
+			     McFormulaFreeDebugData);
+
+    if(approx != NIL(mdd_t)) mdd_free(approx);
+
+    break;
+  }
+  case Ctlp_Cmp_c: {
+    assert(!skipRight);
+    if (Ctlp_FormulaReadCompareValue(ctlFormula) == 0)
+      result = bdd_is_tautology(leftMdd, 0) ?
+      		mdd_one(mddMgr) : mdd_zero(mddMgr);
+    else
+      result = bdd_is_tautology(leftMdd, 0) ?
+      		mdd_zero(mddMgr) : mdd_one(mddMgr);
+    break;
+  }
+  case Ctlp_Init_c:
+    assert(!skipRight);
+    result = Fsm_FsmComputeInitialStates(modelFsm);
+    break;
+  case Ctlp_FwdU_c:
+    assert(!skipRight);
+    if (buildOnionRings) {
+      array_t *onionRings = array_alloc(mdd_t *, 0);
+      result = Mc_FsmEvaluateFwdUFormula(modelFsm, leftMdd, rightMdd,
+					 fairStates, careStatesArray,
+					 onionRings, verbosity, dcLevel);
+      Ctlp_FormulaSetDbgInfo(ctlFormula, (void *) onionRings,
+			     McFormulaFreeDebugData);
+    }
+    else {
+      if (Ctlp_FormulaReadLeftChild(ctlFormula) &&
+	  Ctlp_FormulaReadType(Ctlp_FormulaReadLeftChild(ctlFormula)) ==
+	  Ctlp_Init_c &&
+	  Ctlp_FormulaReadRightChild(ctlFormula) &&
+	  Ctlp_FormulaReadType(Ctlp_FormulaReadRightChild(ctlFormula)) ==
+	  Ctlp_TRUE_c &&
+	  Fsm_FsmTestIsReachabilityDone(modelFsm)) {
+	result = mdd_dup(Fsm_FsmReadReachableStates(modelFsm));
+	break;
+      }
+      result = Mc_FsmEvaluateFwdUFormula(modelFsm, leftMdd, rightMdd,
+					 fairStates, careStatesArray,
+					 NIL(array_t), verbosity, 
+					 dcLevel);
+    }
+    break;
+  case Ctlp_FwdG_c:
+    assert(!skipRight);
+    if (buildOnionRings) {
+      array_t *arrayOfOnionRings = array_alloc(array_t *, 0);
+      result = Mc_FsmEvaluateFwdGFormula(modelFsm, leftMdd, rightMdd,
+					 fairStates, fairCondition,
+					 careStatesArray,
+					 arrayOfOnionRings, verbosity,
+					 dcLevel);   
+      Ctlp_FormulaSetDbgInfo(ctlFormula, (void *)arrayOfOnionRings,
+			     McFormulaFreeDebugData);
+    } else {
+      result = Mc_FsmEvaluateFwdGFormula(modelFsm, leftMdd, rightMdd,
+					 fairStates, fairCondition,
+					 careStatesArray,
+					 NIL(array_t), verbosity,
+					 dcLevel);
+    }
+    break;
+  case Ctlp_EY_c:
+    assert(!skipRight);
+    result = Mc_FsmEvaluateEYFormula(modelFsm, leftMdd, fairStates,
+				     careStatesArray, verbosity, dcLevel);
+    break;
+
+  default: fail("Encountered unknown type of CTL formula\n");
+  }
+
+  tmpMdd = mdd_dup(result);
+  thisApproxType = ComputeResultingApproximation(
+    Ctlp_FormulaReadType(ctlFormula), leftApproxType,
+    rightApproxType, TRMinimization, earlyTermination, fixpoint);
+  Ctlp_FormulaSetApproxStates(ctlFormula, tmpMdd, thisApproxType);
+
+#ifdef DEBUG_MC
+  /* The following code is just for debugging */
+  if ((verbosity == McVerbosityMax_c)) {
+    char *type = Ctlp_FormulaGetTypeString(ctlFormula);
+    if (Ctlp_FormulaReadType(ctlFormula) == Ctlp_Cmp_c) {
+      fprintf(vis_stdout, "Info : result for [Cmp]\n");
+      if (bdd_is_tautology(result, 1))
+	fprintf(vis_stdout, "TRUE\n");
+      else
+	fprintf(vis_stdout, "FALSE\n");
+    }
+    else if (Ctlp_FormulaReadType(ctlFormula) == Ctlp_ID_c) {
+      char *atomic = Ctlp_FormulaConvertToString(ctlFormula);
+      fprintf(vis_stdout, "Info : satisfying minterms for [%s(%s)]:\n",
+	      type, atomic);
+      free(atomic);
+      if (bdd_is_tautology(result, 1))
+	fprintf(vis_stdout, "-- TAUTOLOGY --\n");
+      else if (bdd_is_tautology(result, 0))
+	fprintf(vis_stdout, "-- null --\n");
+      else
+	(void)_McPrintSatisfyingMinterms(result, modelFsm);
+    }
+    else {
+      fprintf(vis_stdout, "Info : satisfying minterms for [%s]:\n", type);
+      if (bdd_is_tautology(result, 1))
+	fprintf(vis_stdout, "-- TAUTOLOGY --\n");
+      else if (bdd_is_tautology(result, 0))
+	fprintf(vis_stdout, "-- null --\n");
+      else
+	(void)_McPrintSatisfyingMinterms(result, modelFsm);
+    }
+    free(type);
+  }
+#endif
+  
+  if (modelCareStatesArray == NIL(array_t))
+    mdd_array_free(careStatesArray);
+  if (leftMdd)
+    mdd_free(leftMdd);
+  if (rightMdd)
+    mdd_free(rightMdd);
+  *resultApproxType = thisApproxType;
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reachable(p,q) = FwdUntil(p,q) ^ q]
+
+  Description [Reachable(p,q) = FwdUntil(p,q) ^ q. This Reachable operation is
+  described in the paper "CTL Model Checking Based on Forward State Traversal"
+  by H. Iwashita et al.]
+
+  SideEffects []
+
+******************************************************************************/
+static mdd_t *
+McForwardReachable(
+  Fsm_Fsm_t *modelFsm,
+  mdd_t *targetMdd,
+  mdd_t *invariantMdd,
+  mdd_t *fairStates,
+  array_t *careStatesArray,
+  array_t *onionRings,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel)
+{
+  mdd_t *resultMdd, *fuMdd;
+
+  /* When McForwardReachable is called by Mc_FsmEvaluateFwdEHFormula
+   * with no fairness constraints, this test saves one image
+   * computation. */
+  if (mdd_is_tautology(fairStates, 1) &&
+      mdd_lequal_mod_care_set_array(invariantMdd, targetMdd,
+				    1, 1, careStatesArray)) {
+    resultMdd = mdd_dup(invariantMdd);
+    if (onionRings) {
+      array_insert_last(mdd_t *, onionRings, mdd_dup(resultMdd));
+    }
+  } else {
+    fuMdd = Mc_FsmEvaluateFwdUFormula(modelFsm, targetMdd, invariantMdd,
+				      fairStates, careStatesArray, onionRings,
+				      verbosity, dcLevel);
+    resultMdd = mdd_and(fuMdd, invariantMdd, 1, 1);
+    mdd_free(fuMdd);
+  }
+
+  /* Updates onionRings not to have warning message in
+   * Mc_FsmEvaluateFwdEHFormula since Reachable(p,q) = FwdUntil(p,q) ^ q.
+   */
+  if (onionRings) {
+    int		i;
+    mdd_t	*ring, *tmp;
+
+    for (i = 0 ; i < array_n(onionRings); i++) {
+      tmp = array_fetch(mdd_t *, onionRings, i);
+      ring = mdd_and(tmp, invariantMdd, 1, 1);
+      mdd_free(tmp);
+      array_insert(mdd_t *, onionRings, i, ring);
+    }
+  }
+
+  return(resultMdd);
+}
Index: vis_dev/vis-2.3/src/mc/mcSCC.c
===================================================================
--- vis_dev/vis-2.3/src/mc/mcSCC.c	(revision 14)
+++ vis_dev/vis-2.3/src/mc/mcSCC.c	(revision 14)
@@ -0,0 +1,1499 @@
+/**CFile***********************************************************************
+
+  FileName    [mcSCC.c]
+
+  PackageName [mc]
+
+  Synopsis    [Computation of Fair Strongly Connected Components.]
+
+  Description [This file contains the functions to compute the fair
+  Strongly Connected Components (SCCs) of the state transtion graph of
+  an FSM.  Knowledge of the fair SCCs can be used to decide language
+  emptiness.  Other applications are also possible.]
+
+  SeeAlso     []
+
+  Author      [Fabio Somenzi, Chao Wang]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "mcInt.h"
+
+/*#define  SCC_NO_TRIM */
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+struct GraphNodeSpineSet {
+  mdd_t *states;  /* V    */
+  mdd_t *spine;   /* S    */
+  mdd_t *node;    /* Node */
+};
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef struct GraphNodeSpineSet gns_t;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] UNUSED = "$Id: mcSCC.c,v 1.11 2005/05/18 19:35:19 jinh Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static mdd_t * LockstepPickSeed(Fsm_Fsm_t *fsm, mdd_t *V, array_t *buechiFairness, array_t *onionRings, int ringIndex);
+static void LockstepQueueEnqueue(Fsm_Fsm_t *fsm, Heap_t *queue, mdd_t *states, array_t *onionRings, McLockstepMode mode, array_t *buechiFairness, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel);
+static void LinearstepQueueEnqueue(Fsm_Fsm_t *fsm, Heap_t *queue, mdd_t *states, mdd_t *spine, mdd_t *node, array_t *onionRings, McLockstepMode mode, array_t *buechiFairness, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel);
+static int GetSccEnumerationMethod( void );
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates the first fair SCC of a FSM.]
+
+  Description [Defines an iterator on the fair SCCs of a FSM and finds the
+  first fair SCC.  Returns a generator that contains the information
+  necessary to continue the enumeration if successful; NULL
+  otherwise.]
+
+  SideEffects [The fair SCC is retuned as a side effect.]
+
+  SeeAlso     [Mc_FsmForEachScc Mc_FsmNextScc Mc_FsmIsSccGenEmpty
+  Mc_FsmSccGenFree]
+
+******************************************************************************/
+Mc_SccGen_t *
+Mc_FsmFirstScc(
+  Fsm_Fsm_t *fsm,
+  mdd_t **scc,
+  array_t *sccClosedSetArray,
+  array_t *buechiFairness,
+  array_t *onionRings,
+  boolean earlyTermination,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel)
+{
+  Mc_SccGen_t *gen;
+  Heap_t      *heap;
+  int         i;
+  mdd_t       *closedSet;
+  int         linearStepMethod;
+
+  if (fsm == NIL(Fsm_Fsm_t)) return NIL(Mc_SccGen_t);
+
+  /* Allocate generator and initialize it. */
+  gen = ALLOC(Mc_SccGen_t, 1);
+  if (gen == NIL(Mc_SccGen_t))  return NIL(Mc_SccGen_t);
+
+  gen->fsm = fsm;
+  gen->heap = heap = Heap_HeapInit(1);
+  gen->rings = onionRings;
+  gen->buechiFairness = buechiFairness;
+  gen->earlyTermination = earlyTermination;
+  gen->verbosity = verbosity;
+  gen->dcLevel = dcLevel;
+  gen->totalExamined = 0;
+  gen->nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c);
+  gen->nPreComps = Img_GetNumberOfImageComputation(Img_Backward_c);
+
+  linearStepMethod = GetSccEnumerationMethod();
+  /* Initialize the heap from the given sets of states. */
+  arrayForEachItem(mdd_t *, sccClosedSetArray, i, closedSet) {
+    if (linearStepMethod == 1) {
+      mdd_manager *mddManager = Fsm_FsmReadMddManager(fsm);
+      LinearstepQueueEnqueue(fsm, heap, mdd_dup(closedSet), 
+			     mdd_zero(mddManager),
+			     mdd_zero(mddManager), onionRings,
+			     McLS_none_c, buechiFairness, verbosity, dcLevel);
+    }else {
+      LockstepQueueEnqueue(fsm, heap, mdd_dup(closedSet), onionRings,
+			   McLS_none_c, buechiFairness, verbosity, dcLevel);
+    }
+  }
+  /* Find first SCC. */
+  if (Heap_HeapCount(heap) == 0) {
+    *scc = NIL(mdd_t);
+  } else {
+    if (linearStepMethod == 1)
+      *scc = McFsmComputeOneFairSccByLinearStep(fsm, heap, buechiFairness,
+						onionRings, earlyTermination,
+						verbosity, dcLevel,
+						&(gen->totalExamined));
+    else
+      *scc = McFsmComputeOneFairSccByLockStep(fsm, heap, buechiFairness,
+					      onionRings, earlyTermination,
+					      verbosity, dcLevel,
+					      &(gen->totalExamined));
+  }
+  if (*scc == NIL(mdd_t)) {
+    gen->status = McSccGenEmpty_c;
+    gen->fairSccsFound = 0;
+  } else {
+    gen->status = McSccGenNonEmpty_c;
+    gen->fairSccsFound = 1;
+  }
+  return gen;
+
+} /* Mc_FsmFirstScc */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates the next fair SCC of a FSM.]
+
+  Description [Generates the next fair SCC of a FSM, using generator
+  gen. Returns FALSE if the enumeration is completed; TRUE otherwise.]
+
+  SideEffects [The fair SCC is returned as side effect.]
+
+  SeeAlso     [Mc_FsmForEachScc Mc_FsmFirstScc Mc_FsmIsSccGenEmpty
+  Mc_FsmSccGenFree]
+
+******************************************************************************/
+boolean
+Mc_FsmNextScc(
+  Mc_SccGen_t *gen,
+  mdd_t **scc)
+{
+  int linearStepMethod;
+
+  if (gen->earlyTermination == TRUE) {
+    gen->status = McSccGenEmpty_c;
+    return FALSE;
+  }
+  linearStepMethod = GetSccEnumerationMethod();
+  if (linearStepMethod == 1) 
+    *scc = McFsmComputeOneFairSccByLinearStep(gen->fsm, gen->heap,
+					      gen->buechiFairness, gen->rings,
+					      gen->earlyTermination,
+					      gen->verbosity, gen->dcLevel,
+					      &(gen->totalExamined));
+  else
+    *scc = McFsmComputeOneFairSccByLockStep(gen->fsm, gen->heap,
+					    gen->buechiFairness, gen->rings,
+					    gen->earlyTermination,
+					    gen->verbosity, gen->dcLevel,
+					    &(gen->totalExamined));
+  if (*scc == NIL(mdd_t)) {
+    gen->status = McSccGenEmpty_c;
+    return FALSE;
+  } else {
+    gen->status = McSccGenNonEmpty_c;
+    gen->fairSccsFound++;
+    return TRUE;
+  }
+
+} /* Mc_FsmNextScc */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns TRUE if a generator is empty; FALSE otherwise.]
+
+  Description []
+
+  SideEffects [none]
+
+  SeeAlso     [Mc_FsmForEachScc Mc_FsmFirstScc Mc_FsmNextScc Mc_FsmSccGenFree]
+
+******************************************************************************/
+boolean
+Mc_FsmIsSccGenEmpty(
+  Mc_SccGen_t *gen)
+{
+  if (gen == NIL(Mc_SccGen_t)) return TRUE;
+  return gen->status == McSccGenEmpty_c;
+
+} /* Mc_FsmIsSccGenEmpty */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a SCC generator.]
+
+  Description [Frees a SCC generator.  Always returns FALSE, so that it
+  can be used in iterators.
+
+  leftover is an array_t of mdd_t *s.]
+
+  SideEffects [The sets of states in the heap are returned in leftover
+  if the array pointer is non-null.]
+
+  SeeAlso     [Mc_FsmForEachScc Mc_FsmFirstScc Mc_FsmNextScc
+  Mc_FsmIsSccGenEmpty]
+
+******************************************************************************/
+boolean
+Mc_FsmSccGenFree(
+  Mc_SccGen_t *gen,
+  array_t *leftover)	
+{
+  int linearStepMethod;
+
+  if (gen == NIL(Mc_SccGen_t)) return FALSE;
+  /* Print some stats. */
+  if (gen->verbosity == McVerbositySome_c || gen->verbosity == McVerbosityMax_c) {
+    fprintf(vis_stdout,
+	    "--SCC: found %d fair SCC(s) out of %d examined\n",
+	    gen->fairSccsFound, gen->totalExamined);
+    fprintf(vis_stdout,
+	    "--SCC: %d image computations, %d preimage computations\n",
+	    Img_GetNumberOfImageComputation(Img_Forward_c) - gen->nImgComps,
+	    Img_GetNumberOfImageComputation(Img_Backward_c) - gen->nPreComps);
+  }
+  /* Create array from elements still on queue if so requested. */
+  linearStepMethod = GetSccEnumerationMethod();
+  if (linearStepMethod == 1) {
+    while (Heap_HeapCount(gen->heap)) {
+      gns_t *set;
+      long index;
+      int retval UNUSED = Heap_HeapExtractMin(gen->heap, &set, &index);
+      assert(retval);
+      if (leftover == NIL(array_t) || gen->earlyTermination == TRUE) {
+	mdd_free(set->states); 
+      } else {
+	array_insert_last(mdd_t *, leftover, set->states);
+      }
+      mdd_free(set->spine); mdd_free(set->node);
+      FREE(set);
+    }
+  }else {
+    while (Heap_HeapCount(gen->heap)) {
+      mdd_t *set;
+      long index;
+      int retval UNUSED = Heap_HeapExtractMin(gen->heap, &set, &index);
+      assert(retval);
+      if (leftover == NIL(array_t) || gen->earlyTermination == TRUE) {
+	mdd_free(set);
+      } else {
+	array_insert_last(mdd_t *, leftover, set);
+      }
+    }
+  }
+
+  Heap_HeapFree(gen->heap);
+  FREE(gen);
+  return FALSE;
+
+} /* Mc_FsmSccGenFree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes fair SCCs of an FSM.]
+
+  Description [Returns some fair SCCs of an FSM and the states on the
+  paths leading to them.  Parameter <code>maxNumberOfSCCs</code>
+  controls the enumeration.  If its value is 0, all fair SCCs are
+  enumerated; if it is negative, early termination is applied, and at
+  most one fair SCC is computed.  Finally, if
+  <code>maxNumberOfSCCs</code> is a positive integer <code>n</code>,
+  then exactly <code>n</code> fair SCCs are computed.]
+
+  SideEffects [Returns an array with one SCC per entry as side
+  effect. May update reachability information.]
+
+  SeeAlso     []
+
+******************************************************************************/
+mdd_t *
+McFsmComputeFairSCCsByLockStep(
+  Fsm_Fsm_t *fsm,
+  int maxNumberOfSCCs,
+  array_t *SCCs,
+  array_t *onionRingsArrayForDbg,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel)
+{
+  Mc_SccGen_t *sccGen;
+  mdd_t *mddOne, *reached, *hull, *scc, *fairStates;
+  array_t *onionRings, *sccClosedSetArray, *careStatesArray;
+  mdd_manager *mddManager = Fsm_FsmReadMddManager(fsm);
+  int nPreComps = Img_GetNumberOfImageComputation(Img_Backward_c);
+  int nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c);
+  Fsm_Fairness_t *modelFairness = Fsm_FsmReadFairnessConstraint(fsm);
+  array_t *buechiFairness = array_alloc(mdd_t *, 0);
+
+  /* Initialization. */
+  mddOne = mdd_one(mddManager);
+
+  sccClosedSetArray = array_alloc(mdd_t *, 0);
+  reached = Fsm_FsmComputeReachableStates(fsm, 0, verbosity, 0, 0, 1, 0, 0,
+					  Fsm_Rch_Default_c, 0, 0,
+					  NIL(array_t), FALSE, NIL(array_t));
+  array_insert_last(mdd_t *, sccClosedSetArray, reached);
+  onionRings = Fsm_FsmReadReachabilityOnionRings(fsm);
+
+  careStatesArray = array_alloc(mdd_t *, 0);
+  array_insert_last(mdd_t *, careStatesArray, reached);
+  Img_MinimizeTransitionRelation(Fsm_FsmReadOrCreateImageInfo(fsm, 1, 1),
+				 careStatesArray, Img_DefaultMinimizeMethod_c,
+				 Img_Both_c, FALSE);
+
+  /* Read fairness constraints. */
+  if (modelFairness != NIL(Fsm_Fairness_t)) {
+    if (!Fsm_FairnessTestIsBuchi(modelFairness)) {
+      (void) fprintf(vis_stdout,
+	       "** mc error: non-Buechi fairness constraints not supported\n");
+      array_free(buechiFairness);
+      return NIL(mdd_t);
+    } else {
+      int j;
+      int numBuchi = Fsm_FairnessReadNumConjunctsOfDisjunct(modelFairness, 0);
+      for (j = 0; j < numBuchi; j++) {
+	mdd_t *tmpMdd = Fsm_FairnessObtainFinallyInfMdd(modelFairness, 0, j,
+							careStatesArray,
+							dcLevel);
+	array_insert_last(mdd_t *, buechiFairness, tmpMdd);
+      }
+    }
+  } else {
+    array_insert_last(mdd_t *, buechiFairness, mdd_one(mddManager));
+  }
+
+  /* Enumerate the fair SCCs and accumulate their disjunction in hull. */
+  hull = mdd_zero(mddManager);
+  Mc_FsmForEachFairScc(fsm, sccGen, scc, sccClosedSetArray, NIL(array_t),
+		       buechiFairness, onionRings,
+		       maxNumberOfSCCs == MC_LOCKSTEP_EARLY_TERMINATION,
+		       verbosity, dcLevel) {
+    mdd_t *tmp = mdd_or(hull, scc, 1, 1);
+    mdd_free(hull);
+    hull = tmp;
+    array_insert_last(mdd_t *, SCCs, scc);
+    if (maxNumberOfSCCs > MC_LOCKSTEP_ALL_SCCS &&
+	array_n(SCCs) == maxNumberOfSCCs) {
+      Mc_FsmSccGenFree(sccGen, NIL(array_t));
+      break;
+    }
+  }
+
+  /* Compute (subset of) fair states and onion rings. */
+  if (onionRingsArrayForDbg != NIL(array_t)) {
+    mdd_t *fairSet;
+    int i;
+    fairStates = Mc_FsmEvaluateEUFormula(fsm, reached, hull,
+					 NIL(mdd_t), mddOne, careStatesArray,
+					 MC_NO_EARLY_TERMINATION,
+					 NIL(array_t), Mc_None_c, NIL(array_t),
+					 verbosity, dcLevel, NIL(boolean));
+    arrayForEachItem(mdd_t *, buechiFairness, i, fairSet) {
+      mdd_t *restrictedFairSet = mdd_and(fairSet, hull, 1, 1);
+      array_t *setOfRings = array_alloc(mdd_t *, 0);
+      mdd_t *EU = Mc_FsmEvaluateEUFormula(fsm, fairStates, restrictedFairSet,
+					  NIL(mdd_t), mddOne, careStatesArray,
+					  MC_NO_EARLY_TERMINATION,
+					  NIL(array_t), Mc_None_c, setOfRings,
+					  verbosity, dcLevel, NIL(boolean));
+      array_insert_last(array_t *, onionRingsArrayForDbg, setOfRings);
+      mdd_free(restrictedFairSet);
+      mdd_free(EU);
+    }
+  } else {
+    fairStates = mdd_dup(hull);
+  }
+  if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) {
+    fprintf(vis_stdout,
+	    "--Fair States: %d image computations, %d preimage computations\n",
+	    Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps,
+	    Img_GetNumberOfImageComputation(Img_Backward_c) - nPreComps);
+  }
+
+  /* Clean up. */
+  array_free(sccClosedSetArray);
+  mdd_free(reached);
+  mdd_free(hull);
+  mdd_free(mddOne);
+  array_free(careStatesArray);
+  mdd_array_free(buechiFairness);
+  return fairStates;
+
+} /* McFsmComputeFairSCCsByLockStep */
+
+/**Function********************************************************************
+
+  Synopsis    [Computes fair SCCs of an FSM within SCC-closed sets.]
+
+  Description [Same as McFsmComputeFairSCCsByLockStep, except that the
+  fair SCCs returned are within the given array of SCC-closed sets.]
+
+
+  SideEffects [Returns an array with one SCC per entry as side
+  effect. May update reachability information.]
+
+  SeeAlso     [McFsmComputeFairSCCsByLockStep]
+
+******************************************************************************/
+mdd_t *
+McFsmRefineFairSCCsByLockStep(
+  Fsm_Fsm_t *fsm,
+  int maxNumberOfSCCs,
+  array_t *SCCs,
+  array_t *sccClosedSets,
+  array_t *careStates,
+  array_t *onionRingsArrayForDbg,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel)
+{
+  Mc_SccGen_t *sccGen;
+  mdd_t *mddOne, *reached, *hull, *scc, *fairStates;
+  array_t *onionRings, *careStatesArray, *sccClosedSetArray;
+  mdd_manager *mddManager = Fsm_FsmReadMddManager(fsm);
+  int nPreComps = Img_GetNumberOfImageComputation(Img_Backward_c);
+  int nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c);
+  Fsm_Fairness_t *modelFairness = Fsm_FsmReadFairnessConstraint(fsm);
+  array_t *buechiFairness = array_alloc(mdd_t *, 0);
+
+  /* Initialization. */
+  mddOne = mdd_one(mddManager);
+
+  if (careStates == NIL(array_t)) {
+    reached = Fsm_FsmComputeReachableStates(fsm, 0, verbosity, 0, 0, 1, 0, 0,
+					    Fsm_Rch_Default_c, 0, 0,
+					    NIL(array_t), FALSE, NIL(array_t));
+    careStatesArray = array_alloc(mdd_t *, 0);
+    array_insert_last(mdd_t *, careStatesArray, mdd_dup(reached));
+  }else {
+    reached = McMddArrayAnd(careStates);
+    careStatesArray = mdd_array_duplicate(careStates);
+  }
+
+  onionRings = Fsm_FsmReadReachabilityOnionRings(fsm);
+  if (onionRings == NIL(array_t)) {
+    onionRings = array_alloc(mdd_t *, 0);
+    array_insert_last(mdd_t *, onionRings, mdd_dup(mddOne));
+  }else
+    onionRings = mdd_array_duplicate(onionRings);
+
+  if (sccClosedSets == NIL(array_t)) {
+    sccClosedSetArray = array_alloc(mdd_t *, 0);
+    array_insert_last(mdd_t *, sccClosedSetArray, mdd_dup(reached));
+  }else {
+    if (careStates != NIL(array_t))
+      sccClosedSetArray = mdd_array_duplicate(sccClosedSets);
+    else {
+      mdd_t *mdd1, *mdd2;
+      int i;
+      sccClosedSetArray = array_alloc(mdd_t *, 0);
+      arrayForEachItem(mdd_t *, sccClosedSets, i, mdd1) {
+	mdd2 = mdd_and(mdd1, reached, 1, 1);
+	if (mdd_is_tautology(mdd2, 0)) 
+	  mdd_free(mdd2);
+	else
+	  array_insert_last(mdd_t *, sccClosedSetArray, mdd2);
+      }
+    }
+  }
+
+  Img_MinimizeTransitionRelation(Fsm_FsmReadOrCreateImageInfo(fsm, 1, 1),
+				 careStatesArray, Img_DefaultMinimizeMethod_c,
+				 Img_Both_c, FALSE);
+
+  /* Read fairness constraints. */
+  if (modelFairness != NIL(Fsm_Fairness_t)) {
+    if (!Fsm_FairnessTestIsBuchi(modelFairness)) {
+      (void) fprintf(vis_stdout,
+	       "** mc error: non-Buechi fairness constraints not supported\n");
+      array_free(buechiFairness);
+      mdd_array_free(sccClosedSetArray);
+      mdd_array_free(onionRings);
+      mdd_array_free(careStatesArray);
+      mdd_free(reached);
+      return NIL(mdd_t);
+    } else {
+      int j;
+      int numBuchi = Fsm_FairnessReadNumConjunctsOfDisjunct(modelFairness, 0);
+      for (j = 0; j < numBuchi; j++) {
+	mdd_t *tmpMdd = Fsm_FairnessObtainFinallyInfMdd(modelFairness, 0, j,
+							careStatesArray,
+							dcLevel);
+	array_insert_last(mdd_t *, buechiFairness, tmpMdd);
+      }
+    }
+  } else {
+    array_insert_last(mdd_t *, buechiFairness, mdd_one(mddManager));
+  }
+
+  /* Enumerate the fair SCCs and accumulate their disjunction in hull. */
+  hull = mdd_zero(mddManager);
+  Mc_FsmForEachFairScc(fsm, sccGen, scc, sccClosedSetArray, NIL(array_t),
+		       buechiFairness, onionRings,
+		       maxNumberOfSCCs == MC_LOCKSTEP_EARLY_TERMINATION,
+		       verbosity, dcLevel) {
+    mdd_t *tmp = mdd_or(hull, scc, 1, 1);
+    mdd_free(hull);
+    hull = tmp;
+    array_insert_last(mdd_t *, SCCs, scc);
+    if (maxNumberOfSCCs > MC_LOCKSTEP_ALL_SCCS &&
+	array_n(SCCs) == maxNumberOfSCCs) {
+      Mc_FsmSccGenFree(sccGen, NIL(array_t));
+      break;
+    }
+  }
+
+  /* Compute (subset of) fair states and onion rings. */
+  if (onionRingsArrayForDbg != NIL(array_t)) {
+    mdd_t *fairSet;
+    int i;
+    fairStates = Mc_FsmEvaluateEUFormula(fsm, reached, hull,
+					 NIL(mdd_t), mddOne, careStatesArray,
+					 MC_NO_EARLY_TERMINATION,
+					 NIL(array_t), Mc_None_c, NIL(array_t),
+					 verbosity, dcLevel, NIL(boolean));
+    arrayForEachItem(mdd_t *, buechiFairness, i, fairSet) {
+      mdd_t *restrictedFairSet = mdd_and(fairSet, hull, 1, 1);
+      array_t *setOfRings = array_alloc(mdd_t *, 0);
+      mdd_t *EU = Mc_FsmEvaluateEUFormula(fsm, fairStates, restrictedFairSet,
+					  NIL(mdd_t), mddOne, careStatesArray,
+					  MC_NO_EARLY_TERMINATION,
+					  NIL(array_t), Mc_None_c, setOfRings,
+					  verbosity, dcLevel, NIL(boolean));
+      array_insert_last(array_t *, onionRingsArrayForDbg, setOfRings);
+      mdd_free(restrictedFairSet);
+      mdd_free(EU);
+    }
+  } else {
+    fairStates = mdd_dup(hull);
+  }
+  if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) {
+    fprintf(vis_stdout,
+	    "--Fair States: %d image computations, %d preimage computations\n",
+	    Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps,
+	    Img_GetNumberOfImageComputation(Img_Backward_c) - nPreComps);
+  }
+
+  /* Clean up. */
+  mdd_array_free(sccClosedSetArray);
+  mdd_free(reached);
+  mdd_free(hull);
+  mdd_free(mddOne);
+  mdd_array_free(careStatesArray);
+  mdd_array_free(buechiFairness);
+  return fairStates;
+
+} /* McFsmRefineFairSCCsByLockStep */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes one fair SCC of an FSM, by LinearStep.]
+
+  Description [Computes one fair SCC of the state transition graph of
+  an FSM.  Returns the fair SCC if one exists; NULL otherwise.  This
+  function uses the linear steps SCC enumeration algorithm of
+  Gentilini, Piazza, and Policriti, "Computing strongly connected
+  components in a linear number of symbolic steps," and with the
+  addition of an early termination test.<p>
+
+  On input, the heap is supposed to contain a set of SCC-closed state
+  sets together with their spine-sets.  If earlyTermination is
+  requested, the heap is left in an inconsistent state; otherwise, it
+  contains a set of SCC-closed sets that contains all fair SCCs that
+  were on the heap on input, except the one that has been enumerated.
+  The number of sets may be different, and some non-fair SCCs may no
+  longer be present.<p>
+
+  The onionRing parameter is an array of state sets that is used to
+  pick a seed close to a target.  Typically, these onion rings come
+  from reachability analysis.  The target states in this case are the
+  initial states of the FSM, and the objective of choosing a seed
+  close to them is to reduce the length of the stem of a
+  counterexample in the language emptiness check.  However, any
+  collection of sets that together cover all the states on the heap
+  will work.  If one is not concerned with a specific target, but
+  rather with speed, then passing an array with just one component set
+  to the constant one is preferable.]
+
+  SideEffects [Updates the priority queue. The number of SCC examined
+  (i.e., the number of chosen seeds) is added to sccExamined.]
+
+  SeeAlso     [Mc_FsmForEachFairScc]
+
+******************************************************************************/
+mdd_t *
+McFsmComputeOneFairSccByLinearStep( 
+  Fsm_Fsm_t *fsm,
+  Heap_t *priorityQueue,
+  array_t *buechiFairness,
+  array_t *onionRings,
+  boolean earlyTermination,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  int *sccExamined)
+{
+  mdd_t *mddOne, *SCC = NIL(mdd_t);
+  mdd_manager *mddManager = Fsm_FsmReadMddManager(fsm);
+  int nPreComps = Img_GetNumberOfImageComputation(Img_Backward_c);
+  int nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c);
+  array_t *careStatesArray = array_alloc(mdd_t *, 0);
+  int totalSCCs = 0;
+  boolean foundScc = FALSE;
+  array_t *activeFairness = NIL(array_t);
+  int firstActive = 0;
+  gns_t *gns;
+
+  /* Initialization. */
+  mddOne = mdd_one(mddManager);
+  array_insert(mdd_t *, careStatesArray, 0, mddOne); 
+
+  while (Heap_HeapCount(priorityQueue)) {
+    mdd_t *V, *F, *fFront, *bFront, *fairSet;
+    mdd_t *S, *NODE, *newS, *newNODE, *preNODE;
+    long ringIndex;
+    int retval UNUSED = Heap_HeapExtractMin(priorityQueue, &gns, 
+					    &ringIndex);
+    assert(retval && ringIndex < array_n(onionRings));
+
+    /* Extract the SCC-closed set, together with its spine-set */
+    V = gns->states;
+    S = gns->spine;
+    NODE = gns->node;
+    FREE(gns);
+
+    /* Determine the seed for which the SCC is computed */
+    if (mdd_is_tautology(S, 0) ) {
+      assert( mdd_is_tautology(NODE, 0) );
+      mdd_free(NODE);
+      NODE = LockstepPickSeed(fsm, V, buechiFairness, onionRings, ringIndex);
+    } 
+
+    if (earlyTermination == TRUE) {
+      int i;
+      activeFairness = array_alloc(mdd_t *, 0);
+      for (i = 0; i < array_n(buechiFairness); i++) {
+	mdd_t *fairSet = array_fetch(mdd_t *, buechiFairness, i);
+	if (!mdd_lequal(NODE, fairSet, 1, 1)) {
+	  array_insert_last(mdd_t *, activeFairness, fairSet);
+	}
+      }
+    }
+    
+    /* Compute the forward-set of seed, together with a new spine-set */
+    {
+      array_t *newCareStatesArray = array_alloc(mdd_t *, 0);
+      array_t *stack = array_alloc(mdd_t *, 0);
+      mdd_t   *tempMdd, *tempMdd2;
+      int i;
+      /* (1) Compute the forward-set, and push it onto STACK */
+      F = mdd_zero(mddManager);
+      fFront = mdd_dup(NODE);
+      while (!mdd_is_tautology(fFront, 0)) {
+	array_insert_last(mdd_t *, stack, mdd_dup(fFront));
+
+	tempMdd = F;
+	F = mdd_or(F, fFront, 1, 1);
+	mdd_free(tempMdd);
+
+	tempMdd = Mc_FsmEvaluateEYFormula(fsm, fFront, mddOne, careStatesArray,
+					  verbosity, dcLevel);
+	mdd_free(fFront);
+	tempMdd2 = mdd_and(tempMdd, V, 1, 1);
+	mdd_free(tempMdd);
+	fFront = mdd_and(tempMdd2, F, 1, 0);
+	mdd_free(tempMdd2);
+      }
+      mdd_free(fFront);
+      /* (2) Determine a spine-set of the forward-set */
+      i = array_n(stack) - 1;
+      fFront = array_fetch(mdd_t *, stack, i);
+      newNODE = Mc_ComputeAState(fFront, fsm);
+      mdd_free(fFront);
+
+      newS = mdd_dup(newNODE);
+      while (i > 0) {
+	fFront = array_fetch(mdd_t *, stack, --i);
+	/* Chao: The use of DCs here may slow down the computation,
+	 *       even though it reduces the peak BDD size
+	 */
+	/* array_insert(mdd_t *, newCareStatesArray, 0, fFront); */
+	array_insert(mdd_t *, newCareStatesArray, 0, mddOne);
+	tempMdd = Mc_FsmEvaluateEXFormula(fsm, newS, mddOne, newCareStatesArray,
+					  verbosity, dcLevel);
+	tempMdd2 = mdd_and(tempMdd, fFront, 1, 1);
+	mdd_free(tempMdd);
+	mdd_free(fFront);
+	
+	tempMdd = Mc_ComputeAState(tempMdd2, fsm);
+	mdd_free(tempMdd2);
+
+	tempMdd2 = newS;
+	newS = mdd_or(newS, tempMdd, 1, 1);
+	mdd_free(tempMdd2);
+	mdd_free(tempMdd);
+      }
+      array_free(stack);
+      array_free(newCareStatesArray);
+    }
+    /* now, we have {F, newS, newNODE} */
+    
+    /* Determine the SCC containing NODE */
+    SCC    = mdd_dup(NODE);
+    bFront = mdd_dup(NODE);
+    while (1) {
+      mdd_t   *tempMdd, *tempMdd2;
+
+      if (earlyTermination == TRUE) {
+	mdd_t * meet = mdd_and(SCC, NODE, 1, 0);
+	if (!mdd_is_tautology(meet, 0)) {
+	  assert(mdd_lequal(meet, V, 1, 1));
+	  for ( ; firstActive < array_n(activeFairness); firstActive++) {
+	    mdd_t *fairSet = array_fetch(mdd_t *, activeFairness, firstActive);
+	    if (mdd_lequal(meet, fairSet, 1, 0)) break;
+	  }
+	  mdd_free(meet);
+	  if (firstActive == array_n(activeFairness)) {
+	    int i;
+	    (void) fprintf(vis_stdout, "EARLY TERMINATION!\n");
+	    totalSCCs++;
+	    /* Trim fair sets to guarantee counterexample will go through
+	     * this SCC. 
+	     */
+	    for (i = 0; i < array_n(buechiFairness); i++) {
+	      mdd_t *fairSet = array_fetch(mdd_t *, buechiFairness, i);
+	      mdd_t *trimmed = mdd_and(fairSet, SCC, 1, 1);
+	      mdd_free(fairSet);
+	      array_insert(mdd_t *, buechiFairness, i, trimmed);
+	    }
+	    mdd_free(bFront);
+	    mdd_free(F);
+	    mdd_free(V); 
+	    mdd_free(S); 
+	    mdd_free(NODE);
+	    mdd_free(newS);
+	    mdd_free(newNODE);
+	    array_free(activeFairness);
+
+	    foundScc = TRUE;
+	    goto cleanUp;
+	  }
+	}
+	mdd_free(meet);
+      }
+
+      tempMdd = Mc_FsmEvaluateEXFormula(fsm, bFront, mddOne, careStatesArray,
+					verbosity, dcLevel);
+      tempMdd2 = mdd_and(tempMdd, F, 1, 1);
+      mdd_free(tempMdd);
+      
+      tempMdd = bFront;
+      bFront = mdd_and(tempMdd2, SCC, 1, 0);
+      mdd_free(tempMdd2);
+      mdd_free(tempMdd);
+      if (mdd_is_tautology(bFront, 0))  break;
+
+      tempMdd = SCC;
+      SCC = mdd_or(SCC, bFront, 1, 1);
+      mdd_free(tempMdd);
+    }
+    mdd_free(bFront);
+
+    totalSCCs++;
+    preNODE = Mc_FsmEvaluateEYFormula(fsm, NODE, mddOne, careStatesArray,
+				    verbosity, dcLevel);
+     
+    /* Check for fairness. If SCC is a trival SCC, skip the check */
+    if ( !mdd_equal(SCC, NODE) ||  mdd_lequal(NODE, preNODE, 1, 1) ) {
+      /* Check fairness constraints. */
+      int i;
+      arrayForEachItem(mdd_t *, buechiFairness, i, fairSet) {
+	if (mdd_lequal(SCC, fairSet, 1, 0)) break;
+      }
+      if (i == array_n(buechiFairness)) {
+	/* All fairness iconditions intersected.  We have a fair SCC. */
+	if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) {
+	  array_t *PSvars = Fsm_FsmReadPresentStateVars(fsm);
+	  fprintf(vis_stdout, "--linearSCC: found a fair SCC with %.0f states\n",
+		  mdd_count_onset(mddManager, SCC, PSvars));
+	  /* (void) bdd_print_minterm(SCC); */
+	}
+	foundScc = TRUE;
+      }
+    }
+    mdd_free(preNODE);
+    mdd_free(NODE);
+
+    /* Divide the remaining states of V into V minus
+     * the forward set F, and the rest (minus the fair SCC).  Add the two
+     * sets thus obtained to the priority queue. */
+    {
+      mdd_t *V1, *S1, *NODE1;
+      mdd_t *tempMdd, *tempMdd2;
+
+      V1 = mdd_and(V, F, 1, 0);
+      S1 = mdd_and(S, SCC, 1, 0);
+      tempMdd = mdd_and(SCC, S, 1, 1);
+      tempMdd2 = Mc_FsmEvaluateEXFormula(fsm, tempMdd, mddOne, 
+					 careStatesArray,
+					 verbosity, dcLevel);
+      mdd_free(tempMdd);
+      NODE1 = mdd_and(tempMdd2, S1, 1, 1);
+      mdd_free(tempMdd2);
+      LinearstepQueueEnqueue(fsm, priorityQueue, V1, S1, NODE1, 
+			     onionRings, McLS_G_c,
+			     buechiFairness, verbosity, dcLevel);
+
+      V1 = mdd_and(F, SCC, 1, 0);
+      S1 = mdd_and(newS, SCC, 1, 0);
+      NODE1 = mdd_and(newNODE, SCC, 1, 0);
+      LinearstepQueueEnqueue(fsm, priorityQueue, V1, S1, NODE1,
+			     onionRings, McLS_H_c,
+			     buechiFairness, verbosity, dcLevel);
+    }
+    mdd_free(F);
+    mdd_free(V);
+    mdd_free(S);
+    mdd_free(newS);
+    mdd_free(newNODE);
+    
+    if (foundScc == TRUE) break;
+    mdd_free(SCC);
+  }
+
+cleanUp:
+  mdd_free(mddOne);
+  array_free(careStatesArray);
+  if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) {
+    fprintf(vis_stdout,
+	    "--linearSCC: found %s fair SCC out of %d examined\n",
+	    foundScc ? "one" : "no", totalSCCs);
+    fprintf(vis_stdout,
+	    "--linearSCC: %d image computations, %d preimage computations\n",
+	    Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps,
+	    Img_GetNumberOfImageComputation(Img_Backward_c) - nPreComps);
+  }
+  *sccExamined += totalSCCs;
+  return foundScc ? SCC : NIL(mdd_t);
+
+} /* McFsmComputeOneFairSccByLinearStep */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes one fair SCC of an FSM, by LockStep.]
+
+  Description [Computes one fair SCC of the state transition graph of
+  an FSM.  Returns the fair SCC if one exists; NULL otherwise.  This
+  function uses the lockstep SCC enumeration algorithm of Bloem,
+  Gabow, and Somenzi (FMCAD'00) implemented as described in Ravi,
+  Bloem, and Somenzi (FMCAD'00), and with the addition of an early
+  termination test.<p>
+
+  On input, the heap is supposed to contain a set of SCC-closed state
+  sets.  If earlyTermination is requested, the heap is left in an
+  inconsistent state; otherwise, it contains a set of SCC-closed sets
+  that contains all fair SCCs that were on the heap on input except
+  the one that has been enumerated.  The number of sets may be
+  different, and some non-fair SCCs may no longer be present.<p>
+
+  The onionRing parameter is an array of state sets that is used to
+  pick a seed close to a target.  Typically, these onion rings come
+  from reachability analysis.  The target states in this case are the
+  initial states of the FSM, and the objective of choosing a seed
+  close to them is to reduce the length of the stem of a
+  counterexample in the language emptiness check.  However, any
+  collection of sets that together cover all the states on the heap
+  will work.  If one is not concerned with a specific target, but
+  rather with speed, then passing an array with just one component set
+  to the constant one is preferable.]
+
+  SideEffects [Updates the priority queue. The number of SCC examined
+  (i.e., the number of chosen seeds) is added to sccExamined.]
+
+  SeeAlso     [Mc_FsmForEachFairScc]
+
+******************************************************************************/
+mdd_t *
+McFsmComputeOneFairSccByLockStep(
+  Fsm_Fsm_t *fsm,
+  Heap_t *priorityQueue,
+  array_t *buechiFairness,
+  array_t *onionRings,
+  boolean earlyTermination,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  int *sccExamined)
+{
+  mdd_t *mddOne, *SCC = NIL(mdd_t);
+  mdd_manager *mddManager = Fsm_FsmReadMddManager(fsm);
+  int nPreComps = Img_GetNumberOfImageComputation(Img_Backward_c);
+  int nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c);
+  array_t *careStatesArray = array_alloc(mdd_t *, 0);
+  int totalSCCs = 0;
+  boolean foundScc = FALSE;
+  array_t *activeFairness = NIL(array_t);
+  int firstActive = 0;
+
+  /* Initialization. */
+  mddOne = mdd_one(mddManager);
+  array_insert(mdd_t *, careStatesArray, 0, mddOne); 
+
+  while (Heap_HeapCount(priorityQueue)) {
+    mdd_t *V, *seed, *B, *F, *fFront, *bFront, *fairSet;
+    mdd_t *converged, *first, *second;
+    long ringIndex;
+    McLockstepMode firstMode, secondMode;
+    int retval UNUSED = Heap_HeapExtractMin(priorityQueue, &V, &ringIndex);
+    assert(retval && ringIndex < array_n(onionRings));
+    /* Here, V contains at least one nontrivial SCC. We then choose the
+     * seed for a new SCC, which may turn out to be trivial. */
+    seed = LockstepPickSeed(fsm, V, buechiFairness, onionRings, ringIndex);
+
+    if (earlyTermination == TRUE) {
+      int i;
+      activeFairness = array_alloc(mdd_t *, 0);
+      for (i = 0; i < array_n(buechiFairness); i++) {
+	mdd_t *fairSet = array_fetch(mdd_t *, buechiFairness, i);
+	if (!mdd_lequal(seed, fairSet, 1, 1)) {
+	  array_insert_last(mdd_t *, activeFairness, fairSet);
+	}
+      }
+    }
+
+    /* Do lockstep search from seed.  Leave the seed initially out of
+     * F and B to facilitate the detection of trivial SCCs.  Intersect
+     * all results with V so that we can simplify the transition
+     * relation. */
+    fFront = Mc_FsmEvaluateEYFormula(fsm, seed, mddOne, careStatesArray,
+				     verbosity, dcLevel);
+    F = mdd_and(fFront, V, 1, 1);
+    mdd_free(fFront);
+    fFront = mdd_dup(F);
+    bFront = Mc_FsmEvaluateEXFormula(fsm, seed, mddOne, careStatesArray,
+				     verbosity, dcLevel);
+    B = mdd_and(bFront, V , 1, 1);
+    mdd_free(bFront);
+    bFront = mdd_dup(B);
+    /* Go until the fastest search converges. */
+    while (!(mdd_is_tautology(fFront, 0) || mdd_is_tautology(bFront, 0))) {
+      mdd_t *tmp;
+
+      /* If the intersection of F and B intersects all fairness
+       * constraints the union of F and B contains at least one fair
+       * SCC.  Since the intersection of F and B is monotonically
+       * non-decreasing, once a fair set has been intersected, there
+       * is no need to check for it any more. */
+      if (earlyTermination == TRUE) {
+	mdd_t * meet = mdd_and(F, B, 1, 1);
+	if (!mdd_is_tautology(meet, 0)) {
+	  assert(mdd_lequal(meet, V, 1, 1));
+	  for ( ; firstActive < array_n(activeFairness); firstActive++) {
+	    mdd_t *fairSet = array_fetch(mdd_t *, activeFairness, firstActive);
+	    if (mdd_lequal(meet, fairSet, 1, 0)) break;
+	  }
+	  if (firstActive == array_n(activeFairness)) {
+	    int i;
+	    (void) fprintf(vis_stdout, "EARLY TERMINATION!\n");
+	    totalSCCs++;
+	    /* A fair SCC is contained in the union of F, B, and seed. */
+	    tmp = mdd_or(F, B, 1, 1);
+	    SCC = mdd_or(tmp, seed, 1, 1);
+	    mdd_free(tmp);
+	    /* Trim fair sets to guarantee counterexample will go through
+	     * this SCC. */
+	    tmp = mdd_or(meet, seed, 1, 1);
+	    mdd_free(meet);
+	    meet = tmp;
+	    for (i = 0; i < array_n(buechiFairness); i++) {
+	      mdd_t *fairSet = array_fetch(mdd_t *, buechiFairness, i);
+	      mdd_t *trimmed = mdd_and(fairSet, meet, 1, 1);
+	      mdd_free(fairSet);
+	      array_insert(mdd_t *, buechiFairness, i, trimmed);
+	    }
+	    mdd_free(meet);
+	    mdd_free(F); mdd_free(B);
+	    mdd_free(fFront); mdd_free(bFront);
+	    mdd_free(seed); mdd_free(V);
+	    foundScc = TRUE;
+	    array_free(activeFairness);
+	    goto cleanUp;
+	  }
+	}
+	mdd_free(meet);
+      }
+
+      /* Forward step. */
+      tmp = Mc_FsmEvaluateEYFormula(fsm, fFront, mddOne, careStatesArray,
+				    verbosity, dcLevel);
+      mdd_free(fFront);
+      fFront = mdd_and(tmp, F, 1, 0);
+      mdd_free(tmp);
+      tmp = mdd_and(fFront, V, 1, 1);
+      mdd_free(fFront);
+      fFront = tmp;
+      if (mdd_is_tautology(fFront, 0)) break;
+      tmp = mdd_or(F, fFront, 1, 1);
+      mdd_free(F);
+      F = tmp;
+      /* Backward step. */
+      tmp = Mc_FsmEvaluateEXFormula(fsm, bFront, mddOne, careStatesArray,
+				    verbosity, dcLevel);
+      mdd_free(bFront);
+      bFront = mdd_and(tmp, B, 1, 0);
+      mdd_free(tmp);
+      tmp = mdd_and(bFront, V, 1, 1);
+      mdd_free(bFront);
+      bFront = tmp;
+      tmp = mdd_or(B, bFront, 1, 1);
+      mdd_free(B);
+      B = tmp;
+    }
+    /* Complete the slower search within the converged one. */
+    if (mdd_is_tautology(fFront, 0)) {
+      /* Forward search converged. */
+      mdd_t *tmp = mdd_and(bFront, F, 1, 1);
+      mdd_free(bFront);
+      bFront = tmp;
+      mdd_free(fFront);
+      converged = mdd_dup(F);
+      /* The two sets to be enqueued come from a set that has been
+       * already trimmed.  Hence, we want to remove the trivial SCCs
+       * left exposed at the rearguard of F, and the trivial SCCs left
+       * exposed at the vanguard of B. */
+      firstMode = McLS_H_c;
+      secondMode = McLS_G_c;
+      while (!mdd_is_tautology(bFront, 0)) {
+	tmp =  Mc_FsmEvaluateEXFormula(fsm, bFront, mddOne,
+				       careStatesArray, verbosity, dcLevel);
+	mdd_free(bFront);
+	bFront = mdd_and(tmp, B, 1, 0);
+	mdd_free(tmp);
+	tmp = mdd_and(bFront, converged, 1, 1);
+	mdd_free(bFront);
+	bFront = tmp;
+	tmp = mdd_or(B, bFront, 1, 1);
+	mdd_free(B);
+	B = tmp;
+      }
+      mdd_free(bFront);
+    } else {
+      /* Backward search converged. */
+      mdd_t *tmp = mdd_and(fFront, B, 1, 1);
+      mdd_free(fFront);
+      fFront = tmp;
+      mdd_free(bFront);
+      converged = mdd_dup(B);
+      firstMode = McLS_G_c;
+      secondMode = McLS_H_c;
+      while (!mdd_is_tautology(fFront, 0)) {
+	tmp =  Mc_FsmEvaluateEYFormula(fsm, fFront, mddOne,
+				       careStatesArray, verbosity, dcLevel);
+	mdd_free(fFront);
+	fFront = mdd_and(tmp, F, 1 ,0);
+	mdd_free(tmp);
+	tmp = mdd_and(fFront, converged, 1, 1);
+	mdd_free(fFront);
+	fFront = tmp;
+	tmp = mdd_or(F, fFront, 1, 1);
+	mdd_free(F);
+	F = tmp;
+      }
+      mdd_free(fFront);
+    }
+
+    totalSCCs++;
+    SCC = mdd_and(F, B, 1, 1);
+    mdd_free(F);
+    mdd_free(B);
+    /* Check for fairness.  If SCC is the empty set we know that seed
+     * is a trivial strong component; hence, it is not fair. */
+    if (mdd_is_tautology(SCC, 0)) {
+      mdd_t *tmp = mdd_or(converged, seed, 1, 1);
+      mdd_free(converged);
+      converged = tmp;
+      mdd_free(SCC);
+      SCC = mdd_dup(seed);
+    } else {
+      /* Check fairness constraints. */
+      int i;
+      arrayForEachItem(mdd_t *, buechiFairness, i, fairSet) {
+	if (mdd_lequal(SCC, fairSet, 1, 0)) break;
+      }
+      if (i == array_n(buechiFairness)) {
+	/* All fairness conditions intersected.  We have a fair SCC. */
+	if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) {
+	  array_t *PSvars = Fsm_FsmReadPresentStateVars(fsm);
+	  fprintf(vis_stdout, "--SCC: found a fair SCC with %.0f states\n",
+		  mdd_count_onset(mddManager, SCC, PSvars));
+	  /* (void) bdd_print_minterm(SCC); */
+	}
+	foundScc = TRUE;
+      }
+    }
+    /* Divide the remaining states of V into the converged set minus
+     * the fair SCC, and the rest (minus the fair SCC).  Add the two
+     * sets thus obtained to the priority queue. */
+    mdd_free(seed);
+    first = mdd_and(converged, SCC, 1, 0);
+    LockstepQueueEnqueue(fsm, priorityQueue, first, onionRings, firstMode,
+			 buechiFairness, verbosity, dcLevel);
+    second = mdd_and(V, converged, 1, 0);
+    mdd_free(converged);
+    mdd_free(V);
+    LockstepQueueEnqueue(fsm, priorityQueue, second, onionRings, secondMode,
+			 buechiFairness, verbosity, dcLevel);
+    if (earlyTermination == TRUE) {
+      array_free(activeFairness);
+    }
+    if (foundScc == TRUE) break;
+    mdd_free(SCC);
+  }
+
+cleanUp:
+  mdd_free(mddOne);
+  array_free(careStatesArray);
+  if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) {
+    fprintf(vis_stdout,
+	    "--SCC: found %s fair SCC out of %d examined\n",
+	    foundScc ? "one" : "no", totalSCCs);
+    fprintf(vis_stdout,
+	    "--SCC: %d image computations, %d preimage computations\n",
+	    Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps,
+	    Img_GetNumberOfImageComputation(Img_Backward_c) - nPreComps);
+  }
+  *sccExamined += totalSCCs;
+  return foundScc ? SCC : NIL(mdd_t);
+
+} /* McFsmComputeOneFairSccByLockStep */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a seed state for lockstep search.]
+
+  Description [Returns a seed state for lockstep search, or NULL in
+  case of failure.  The strategy is to first find the innermost ring
+  that intersects the given set of states (V) and one fairness
+  constraint.  The other fairness constraints are then checked to
+  increase the number of fairness constraints that are satisfied by
+  the seed.  The search is greedy.]
+
+  SideEffects [none]
+
+  SeeAlso     [McFsmComputeOneFairSccByLockStep]
+
+******************************************************************************/
+static mdd_t *
+LockstepPickSeed(
+  Fsm_Fsm_t *fsm,
+  mdd_t *V,
+  array_t *buechiFairness,
+  array_t *onionRings,
+  int ringIndex)
+{
+  mdd_t *seed;
+  int i, j;
+
+  /* We know that there is at least one state in V from each fairness
+   * constraint. */
+  for (i = ringIndex; i < array_n(onionRings); i++) {
+    mdd_t *ring = array_fetch(mdd_t *, onionRings, i);
+    for (j = 0; j < array_n(buechiFairness); j++) {
+      mdd_t *fairSet = array_fetch(mdd_t *, buechiFairness, j);
+      if (!mdd_lequal_mod_care_set(ring, fairSet, 1, 0, V)) {
+	mdd_t *tmp = mdd_and(V, ring, 1, 1);
+	mdd_t *candidates = mdd_and(tmp, fairSet, 1, 1);
+	mdd_free(tmp);
+	for (j++; j < array_n(buechiFairness); j++) {
+	  fairSet = array_fetch(mdd_t *, buechiFairness, j);
+	  if (!mdd_lequal(candidates, fairSet, 1, 0)) {
+	    tmp = mdd_and(candidates, fairSet, 1, 1);
+	    mdd_free(candidates);
+	    candidates = tmp;
+	  }
+	}
+	seed = Mc_ComputeAState(candidates, fsm);
+	mdd_free(candidates);
+	return seed;
+      }
+    }
+  }
+
+  assert(FALSE);		/* we should never get here */
+  return NIL(bdd_t);
+
+} /* LockstepPickSeed */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adds a set of states to the priority queue of the lockstep
+  algorithm.]
+
+  Description [Given a set of states, applies trimming as specified by
+  mode.  Checks then if the trimmed set may contain a fair SCC, in
+  which case it adds the set to the priority queue.]
+
+  SideEffects [May change the set of states as a result of trimming.
+  The old set of states is freed.]
+
+  SeeAlso     [McFsmComputeOneFairSccByLockStep]
+
+******************************************************************************/
+static void
+LockstepQueueEnqueue(
+  Fsm_Fsm_t *fsm,
+  Heap_t *queue,
+  mdd_t *states,
+  array_t *onionRings,
+  McLockstepMode mode,
+  array_t *buechiFairness,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel)
+{
+  mdd_t *fairSet, *ring;
+  int i;
+  mdd_manager *mddManager = Fsm_FsmReadMddManager(fsm);
+  mdd_t *mddOne = mdd_one(mddManager);
+  array_t *careStatesArray = array_alloc(mdd_t *, 0);
+  array_insert_last(mdd_t *, careStatesArray, mddOne);
+
+#ifndef SCC_NO_TRIM
+  if (mode == McLS_G_c || mode == McLS_GH_c) {
+    mdd_t *trimmed = Mc_FsmEvaluateEGFormula(fsm, states, NIL(mdd_t), mddOne,
+					     NIL(Fsm_Fairness_t),
+					     careStatesArray,
+					     MC_NO_EARLY_TERMINATION,
+					     NIL(array_t),
+					     Mc_None_c, NIL(array_t *),
+					     verbosity, dcLevel, NIL(boolean),
+					     McGSH_EL_c);
+    mdd_free(states);
+    states = trimmed;
+  }
+  if (mode == McLS_H_c || mode == McLS_GH_c) {
+    mdd_t *trimmed = Mc_FsmEvaluateEHFormula(fsm, states, NIL(mdd_t), mddOne,
+					     NIL(Fsm_Fairness_t),
+					     careStatesArray,
+					     MC_NO_EARLY_TERMINATION,
+					     NIL(array_t),
+					     Mc_None_c, NIL(array_t *),
+					     verbosity, dcLevel, NIL(boolean),
+					     McGSH_EL_c);
+    mdd_free(states);
+    states = trimmed;
+  }
+#endif
+
+  mdd_free(mddOne);
+  array_free(careStatesArray);
+  if (mode == McLS_none_c) {
+    mdd_t *range = mdd_range_mdd(mddManager, Fsm_FsmReadPresentStateVars(fsm));
+    mdd_t *valid = mdd_and(states, range, 1, 1);
+    mdd_free(range);
+    mdd_free(states);
+    states = valid;
+  }
+  /* Discard set of states if it does not intersect all fairness conditions. */
+  arrayForEachItem(mdd_t *, buechiFairness, i, fairSet) {
+    if (mdd_lequal(states, fairSet, 1, 0)) {
+      mdd_free(states);
+      return;
+    }
+  }
+  /* Find the innermost onion ring intersecting the set of states.
+   * Its index is the priority of the set. */
+  arrayForEachItem(mdd_t *, onionRings, i, ring) {
+    if (!mdd_lequal(states, ring, 1, 0)) break;
+  }
+  assert(i < array_n(onionRings));
+  Heap_HeapInsert(queue,states,i);
+  return;
+
+} /* LockstepQueueEnqueue */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adds a set of states to the priority queue of the lockstep
+  algorithm.]
+
+  Description [Given a set of states, applies trimming as specified by
+  mode.  Checks then if the trimmed set may contain a fair SCC, in
+  which case it adds the set to the priority queue.]
+
+  SideEffects [May change the set of states as a result of trimming.
+  The old set of states is freed.]
+
+  SeeAlso     [McFsmComputeOneFairSccByLockStep]
+
+******************************************************************************/
+static void
+LinearstepQueueEnqueue(
+  Fsm_Fsm_t *fsm,
+  Heap_t *queue,
+  mdd_t *states,
+  mdd_t *spine,
+  mdd_t *node,
+  array_t *onionRings,
+  McLockstepMode mode,
+  array_t *buechiFairness,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel)
+{
+  mdd_t *fairSet, *ring;
+  mdd_t *tmp, *tmp1;
+  int   i;
+  gns_t *gns;
+  mdd_manager *mddManager = Fsm_FsmReadMddManager(fsm);
+  mdd_t *mddOne = mdd_one(mddManager);
+  array_t *careStatesArray = array_alloc(mdd_t *, 0);
+  array_insert_last(mdd_t *, careStatesArray, mddOne);
+
+#ifndef SCC_NO_TRIM
+  if (mode == McLS_G_c || mode == McLS_GH_c) {
+    mdd_t *trimmed = Mc_FsmEvaluateEGFormula(fsm, states, NIL(mdd_t), mddOne,
+					     NIL(Fsm_Fairness_t),
+					     careStatesArray,
+					     MC_NO_EARLY_TERMINATION,
+					     NIL(array_t),
+					     Mc_None_c, NIL(array_t *),
+					     verbosity, dcLevel, NIL(boolean),
+					     McGSH_EL_c);
+    mdd_free(states);
+    states = trimmed;
+  }
+  if (mode == McLS_H_c || mode == McLS_GH_c) {
+    mdd_t *trimmed = Mc_FsmEvaluateEHFormula(fsm, states, NIL(mdd_t), mddOne,
+					     NIL(Fsm_Fairness_t),
+					     careStatesArray,
+					     MC_NO_EARLY_TERMINATION,
+					     NIL(array_t),
+					     Mc_None_c, NIL(array_t *),
+					     verbosity, dcLevel, NIL(boolean),
+					     McGSH_EL_c);
+    mdd_free(states);
+    states = trimmed;
+  }
+#endif
+
+  if (mode == McLS_none_c) {
+    mdd_t *range = mdd_range_mdd(mddManager, Fsm_FsmReadPresentStateVars(fsm));
+    mdd_t *valid = mdd_and(states, range, 1, 1);
+    mdd_free(range);
+    mdd_free(states);
+    states = valid;
+  }
+  /* Discard set of states if it does not intersect all fairness conditions. */
+  arrayForEachItem(mdd_t *, buechiFairness, i, fairSet) {
+    if (mdd_lequal(states, fairSet, 1, 0)) {
+      mdd_free(states);
+      mdd_free(mddOne);
+      array_free(careStatesArray);
+      return;
+    }
+  }
+  /* Find the innermost onion ring intersecting the set of states.
+   * Its index is the priority of the set. */
+  arrayForEachItem(mdd_t *, onionRings, i, ring) {
+    if (!mdd_lequal(states, ring, 1, 0)) break;
+  }
+  assert(i < array_n(onionRings));
+
+  /* Trim the spine-set. */
+  while ( !mdd_lequal(node, states, 1, 1) ) {
+    tmp = node;
+    tmp1 =  Mc_FsmEvaluateEXFormula(fsm, node, mddOne,
+				    careStatesArray, verbosity, dcLevel);
+    mdd_free(tmp);
+    node = mdd_and(tmp1, spine, 1, 1); 
+    mdd_free(tmp1);
+  }
+  
+  tmp = spine;
+  spine = mdd_and(spine, states, 1, 1);
+  mdd_free(tmp);
+
+#if 0
+  /* Invariants that should always hold */
+  assert( mdd_is_tautology(node, 0) == mdd_is_tautology(spine, 0) );
+  assert(mdd_lequal(node, states, 1, 1));
+  assert(mdd_lequal(node, spine, 1, 1));
+  assert(mdd_lequal(spine, states, 1, 1));
+#endif
+
+  mdd_free(mddOne);
+  array_free(careStatesArray);
+  
+  gns = ALLOC(gns_t, 1);
+  gns->states = states;
+  gns->node = node;
+  gns->spine = spine;
+
+
+  Heap_HeapInsert(queue,gns,i);
+  return;
+
+} /* LinearstepQueueEnqueue */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Return the SCC enumeration method.]
+
+  Description [Get the SCC enumeration method from the environment
+  setting scc_method. Return 0 if it is LockStep (default), 1 if it is
+  LinearStep.  ]
+
+  SideEffects []
+
+  SeeAlso     [GetSccEnumerationMethod]
+
+******************************************************************************/
+static int 
+GetSccEnumerationMethod( void )
+{
+  char *flagValue;
+  int  linearStepMethod = 0;
+ 
+  flagValue = Cmd_FlagReadByName("scc_method");
+  if (flagValue != NIL(char)) {
+    if (strcmp(flagValue, "linearstep") == 0)
+      linearStepMethod = 1;
+    else if (strcmp(flagValue, "lockstep") == 0)
+      linearStepMethod = 0;
+    else {
+      fprintf(vis_stderr, "** scc error: invalid scc method %s, method lockstep is used. \n", 
+	      flagValue);
+    }
+  }
+
+  return linearStepMethod;
+}
Index: vis_dev/vis-2.3/src/mc/mcUtil.c
===================================================================
--- vis_dev/vis-2.3/src/mc/mcUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/mc/mcUtil.c	(revision 14)
@@ -0,0 +1,6039 @@
+/**CFile***********************************************************************
+
+  FileName    [mcUtil.c]
+
+  PackageName [mc]
+
+  Synopsis    [Utilities for Fair CTL model checker and debugger]
+
+  Author      [Adnan Aziz, Tom Shiple, In-Ho Moon]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "mcInt.h"
+#include "mdd.h"
+#include "cmd.h"
+#include "fsm.h"
+#include "img.h"
+#include "sat.h"
+#include "baig.h"
+#include <errno.h>
+
+static char rcsid[] UNUSED = "$Id: mcUtil.c,v 1.113 2009/04/11 18:26:10 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void PrintNodes(array_t *mddIdArray, Ntk_Network_t *network);
+static array_t * SortMddIds(array_t *mddIdArray, Ntk_Network_t *network);
+static void PrintDeck(array_t *mddValues, array_t *mddIdArray, Ntk_Network_t *network);
+static int cmp(const void * s1, const void * s2);
+static boolean AtomicFormulaCheckSemantics(Ctlp_Formula_t *formula, Ntk_Network_t *network, boolean inputsAllowed);
+static void NodeTableAddCtlFormulaNodes(Ntk_Network_t *network, Ctlp_Formula_t *formula, st_table * nodesTable);
+static void NodeTableAddLtlFormulaNodes(Ntk_Network_t *network, Ctlsp_Formula_t *formula, st_table * nodesTable);
+static boolean MintermCheckWellFormed(mdd_t *aMinterm, array_t *aSupport, mdd_manager *mddMgr);
+static boolean SetCheckSupport(mdd_t *aMinterm, array_t *aSupport, mdd_manager *mddMgr);
+static mdd_t * Mc_ComputeRangeOfPseudoInputs(Ntk_Network_t *network);
+static array_t *Mc_BuildBackwardRingsWithInvariants(mdd_t *S, mdd_t *T, mdd_t *invariants, Fsm_Fsm_t *fsm);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Return Boolean TRUE/FALSE depending on whether states in
+  specialStates can reach states in targetStates.]
+
+  Description [Return Boolean TRUE/FALSE depending on whether states in
+  specialStates can reach states in targetStates. If true, onionRings is set
+  to results of fixed point computation going back from targetStates to
+  specialStates.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+Mc_FsmComputeStatesReachingToSet(
+  Fsm_Fsm_t *modelFsm,
+  mdd_t *targetStates,
+  array_t *careStatesArray,
+  mdd_t *specialStates,
+  array_t *onionRings,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel)
+{
+  mdd_t *fromUpperBound;
+  mdd_t *toCareSet;
+  array_t *toCareSetArray = array_alloc(mdd_t *, 0);
+  mdd_t *image;
+  Img_ImageInfo_t *imageInfo = Fsm_FsmReadOrCreateImageInfo(modelFsm, 1, 0);
+
+  mdd_t *reachingStates = mdd_dup( targetStates );
+  mdd_t *fromLowerBound = mdd_dup( targetStates );
+
+  /* Iterate until fromLowerBound is empty. */
+  while (mdd_is_tautology(fromLowerBound, 0) == 0){
+    /* fromLowerBound is the "onion shell" of states just examined. */
+    array_insert_last(mdd_t*, onionRings,
+		      mdd_dup(fromLowerBound));
+    if ( !mdd_lequal(  fromLowerBound, specialStates, 1, 0 ) ) {
+      mdd_free( fromLowerBound );
+      mdd_free( reachingStates );
+      return TRUE;
+    }
+
+    /* fromUpperBound is the set of all states reaching targets thus far. */
+    fromUpperBound = mdd_dup( reachingStates );
+
+    /* toCareSet is the set of all states not reached so far. */
+    toCareSet = mdd_not(reachingStates);
+    array_insert(mdd_t *, toCareSetArray, 0, toCareSet);
+
+    /*
+     * Pre-Image of some set between lower and upper, where we care
+     * about the image only on unreaching states.
+     */
+    image = Img_ImageInfoComputePreImageWithDomainVars(imageInfo,
+		fromLowerBound, fromUpperBound, toCareSetArray);
+    mdd_free(toCareSet);
+    mdd_free(fromLowerBound);
+
+    /* New set of reaching states is old set plus new image. */
+    mdd_free( reachingStates );
+    reachingStates = mdd_or(fromUpperBound, image, 1, 1);
+    mdd_free(image);
+
+    /*
+     * New lower bound is the states just reached (note not on
+     * fromUpperBound).
+     */
+    fromLowerBound = mdd_and(reachingStates, fromUpperBound, 1, 0);
+
+    mdd_free(fromUpperBound);
+  }
+  mdd_array_free( onionRings );
+  mdd_free( reachingStates );
+  mdd_free(fromLowerBound);
+  array_free(toCareSetArray);
+
+  return FALSE;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return Boolean TRUE/FALSE depending on whether states in
+  specialStates are reachable from  initialStates.]
+
+  Description [Return Boolean TRUE/FALSE depending on whether states in
+  specialStates are reachable from  initialStates.If true, onionRings is set
+  to results of fixed point computation going forward from initialStates to
+  specialStates.  Otherwise onionRings is freed.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+Mc_FsmComputeStatesReachableFromSet(
+  Fsm_Fsm_t *modelFsm,
+  mdd_t *initialStates,
+  array_t *careStatesArray,
+  mdd_t *specialStates,
+  array_t *onionRings,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel)
+{
+  boolean reachable=FALSE;
+  mdd_t *fromUpperBound;
+  mdd_t *toCareSet;
+  array_t *toCareSetArray = array_alloc(mdd_t *, 0);
+  mdd_t *image;
+  Img_ImageInfo_t *imageInfo = Fsm_FsmReadOrCreateImageInfo(modelFsm, 0, 1);
+
+  mdd_t *reachableStates = mdd_dup( initialStates );
+  mdd_t *fromLowerBound = mdd_dup( initialStates );
+
+  /* Iterate until fromLowerBound is empty. */
+  while (mdd_is_tautology(fromLowerBound, 0) == 0){
+    /* fromLowerBound is the "onion shell" of states just reached. */
+    array_insert_last(mdd_t*, onionRings,
+		      mdd_dup(fromLowerBound));
+    if (!mdd_lequal(  fromLowerBound, specialStates, 1, 0 ) ) {
+      mdd_free( fromLowerBound );
+      mdd_free( reachableStates );
+      return TRUE;
+    }
+
+    /* fromUpperBound is the set of all states reached thus far. */
+    fromUpperBound = mdd_dup( reachableStates );
+
+    /* toCareSet is the set of all states not reached so far. */
+    toCareSet = mdd_not(reachableStates);
+    array_insert(mdd_t *, toCareSetArray, 0, toCareSet);
+
+    /*
+     * Image of some set between lower and upper, where we care
+     * about the image only on unreached states.
+     */
+    image = Img_ImageInfoComputeImageWithDomainVars(imageInfo,
+		fromLowerBound, fromUpperBound, toCareSetArray);
+    mdd_free(toCareSet);
+    mdd_free(fromLowerBound);
+
+    /* New set of reachable states is old set plus new image. */
+    mdd_free( reachableStates );
+    reachableStates = mdd_or(fromUpperBound, image, 1, 1);
+    mdd_free(image);
+
+    /*
+     * New lower bound is the states just reached (note not on
+     * fromUpperBound).
+     */
+    fromLowerBound = mdd_and(reachableStates, fromUpperBound, 1, 0);
+    mdd_free(fromUpperBound);
+  }
+  mdd_array_free( onionRings );
+  mdd_free( reachableStates );
+  mdd_free(fromLowerBound);
+  array_free(toCareSetArray);
+
+  return reachable;
+
+}
+
+/**Function********************************************************************
+
+  Synopsis [Perform static semantic check of ctl formula on network.]
+
+  Description [Perform static semantic check of ctl formula on network.
+  Specifically, given an atomic formula of the form LHS=RHS, check that the LHS
+  is the name of a latch/wire in the network, and that RHS is of appropriate
+  type (enum/integer) and is lies in the range of the latch/wire values. If LHS
+  is a wire, and inputsAllowed is false, check to see that the algebraic
+  support of the wire consists of only latches and constants.]
+
+  SideEffects []
+
+******************************************************************************/
+boolean
+Mc_FormulaStaticSemanticCheckOnNetwork(
+  Ctlp_Formula_t *formula,
+  Ntk_Network_t *network,
+  boolean inputsAllowed
+  )
+{
+  boolean lCheck;
+  boolean rCheck;
+  Ctlp_Formula_t *leftChild;
+  Ctlp_Formula_t *rightChild;
+
+  if(formula == NIL(Ctlp_Formula_t)){
+    return TRUE;
+  }
+
+  if(Ctlp_FormulaReadType(formula) == Ctlp_ID_c){
+    return AtomicFormulaCheckSemantics(formula, network, inputsAllowed);
+  }
+
+  leftChild = Ctlp_FormulaReadLeftChild(formula);
+  rightChild = Ctlp_FormulaReadRightChild(formula);
+
+  lCheck = Mc_FormulaStaticSemanticCheckOnNetwork(leftChild, network,
+						  inputsAllowed);
+  if(!lCheck)
+    return FALSE;
+
+  rCheck = Mc_FormulaStaticSemanticCheckOnNetwork(rightChild, network,
+						  inputsAllowed);
+  if (!rCheck)
+      return FALSE;
+
+  return TRUE;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Build Path to Core starting at aState.]
+
+  Description [Build Path to Core (the first onion ring) starting at aState.
+
+  <p> For the onion rings should be built in such a way that for every state v
+  in ring i+1 there is a state v' in ring i such that there is an edge from v
+  to v'.  This function will also works for non-BFS rings, where we just
+  require that for every state v in a ring i > 0, there is a state in a ring 0
+  <= j < i that is a successor of v.
+
+  <p>For paths of length at least one, set PathLengthType to McGreaterZero_c.
+  Otherwise, use McGreaterOrEqualZero_c.  The function returns a sequence of
+  states to a state in the core of onionRings, starting at aState. It is the
+  users responsibility to free the array returned as well as its members.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+Mc_BuildPathToCore(
+  mdd_t *aState,
+  array_t *onionRings,
+  Fsm_Fsm_t *modelFsm,
+  Mc_PathLengthType PathLengthType)
+{
+  int i;  /* index into the onionRings */
+  int startingPoint;
+  mdd_t *currentState;
+  Img_ImageInfo_t * imageInfo = Fsm_FsmReadOrCreateImageInfo(modelFsm, 0, 1);
+  array_t *pathToCore;
+  mdd_manager *mddMgr         = Fsm_FsmReadMddManager(modelFsm);
+  array_t *toCareSetArray;
+
+  if(Fsm_FsmReadUniQuantifyInputCube(modelFsm)) {
+    return(Mc_BuildPathToCoreFAFW(
+			    aState, onionRings, modelFsm, PathLengthType));
+  }
+
+  pathToCore         = array_alloc( mdd_t * , 0 );
+  toCareSetArray     = array_alloc(mdd_t *, 0);
+  array_insert_last(mdd_t *, toCareSetArray, mdd_one(mddMgr));
+
+  if ( PathLengthType == McGreaterZero_c )
+    startingPoint = 1;
+  else if ( PathLengthType == McGreaterOrEqualZero_c )
+    startingPoint = 0;
+  else
+    fail("Called Mc_BuildPathToCore with ill formed PathLengthType\n");
+
+  /* RB: How do you guarantee that aState is in one of the onion rings [1,n]?*/
+
+  /*Find the lowest ring that holds aState*/
+  for ( i = startingPoint ; i < array_n( onionRings ); i++ ) {
+    mdd_t *ring = array_fetch( mdd_t *, onionRings, i );
+    if ( McStateTestMembership( aState, ring ) )
+      break;
+  }
+  if ( i == array_n( onionRings ) )
+    return NIL(array_t);
+
+  currentState = mdd_dup( aState );
+  array_insert_last( mdd_t *, pathToCore, currentState );
+
+  /* until we get to ring 0, keep finding successors for currentState */
+  while( i > 0 ) {
+    mdd_t *currentStateSuccs;
+    mdd_t *innerRing;
+    mdd_t *currentStateSuccsInInnerRing;
+    mdd_t *witnessSuccState;
+
+    i--;
+
+    currentStateSuccs =
+      Img_ImageInfoComputeImageWithDomainVars(imageInfo, currentState,
+					      currentState, toCareSetArray);
+    currentStateSuccsInInnerRing = mdd_zero(mddMgr);
+
+    /* find the highest ring that contains a successor, starting with i */
+    while(mdd_is_tautology(currentStateSuccsInInnerRing, 0)){
+      assert(i >= 0);
+      if(i < 0) return NIL(array_t);
+
+      innerRing = array_fetch( mdd_t *, onionRings, i );
+      mdd_free(currentStateSuccsInInnerRing);
+      currentStateSuccsInInnerRing = mdd_and(currentStateSuccs, innerRing,
+					     1, 1 );
+      i--;
+    }
+
+    i++;
+
+    witnessSuccState = Mc_ComputeACloseState(currentStateSuccsInInnerRing,
+					     currentState,
+					     modelFsm );
+    array_insert_last( mdd_t *, pathToCore, witnessSuccState );
+    currentState = witnessSuccState;
+
+    mdd_free( currentStateSuccs );
+    mdd_free( currentStateSuccsInInnerRing );
+
+    /* next, see if we cannot move a few more rings down.  We have to do this,
+     * since a nontrivial path is not guaranteed to exist from a node in ring i
+     * to a node in a lower ring.  In fact a state in ring i may also be in
+     * ring 0. */
+    {
+      boolean contained = TRUE;
+      while(contained && i > 0){
+	i--;
+	innerRing = array_fetch( mdd_t *, onionRings, i );
+	contained = mdd_lequal(witnessSuccState, innerRing, 1, 1);
+      }
+      /* i is highest ring not containing witnessSuccState, or i = 0 */
+
+      if(!contained){
+	i++;
+      }
+      /* i is lowest ring containing witnessSuccState */
+    }
+  }
+
+  mdd_array_free(toCareSetArray);
+
+  return pathToCore;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Build a onion ring from initial state.]
+
+  Description [Build a onion ring from initial state.
+	       This is function for FateAndFreeWill counterexample generation.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+Mc_BuildForwardRings(
+  mdd_t *S,
+  Fsm_Fsm_t *fsm,
+  array_t *onionRings)
+{
+  mdd_t *nextStates;
+  mdd_t *states, *nStates, *oneMdd;
+  array_t *toCareSetArray, *forwardRings;
+  int i;
+  mdd_manager *mddMgr = Fsm_FsmReadMddManager(fsm);
+
+  states = mdd_zero(mddMgr);
+  oneMdd = mdd_one(mddMgr);
+  for(i=0; i<array_n(onionRings); i++) {
+    mdd_t *ring = array_fetch( mdd_t *, onionRings, i );
+    nStates = mdd_or(ring, states, 1, 1);
+    mdd_free(states);
+    states = nStates;
+  }
+  forwardRings = array_alloc(mdd_t *, 0);
+  toCareSetArray = array_alloc(mdd_t *, 0);
+  array_insert(mdd_t *, toCareSetArray, 0, oneMdd);
+  nextStates = Mc_FsmEvaluateESFormula(fsm, states, S,
+				       NIL(mdd_t), oneMdd, toCareSetArray,
+				       MC_NO_EARLY_TERMINATION, NIL(array_t),
+				       Mc_None_c, forwardRings,
+				       McVerbosityNone_c, McDcLevelNone_c,
+				       NIL(boolean));
+  mdd_free(nextStates);
+  mdd_free(states);
+  mdd_array_free(toCareSetArray);
+
+  return(forwardRings);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Build a onion ring to target under invariants.]
+
+  Description [Build a onion ring to target under invariants.
+	       This is function for FateAndFreeWill counterexample generation.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+Mc_BuildForwardRingsWithInvariants(mdd_t *S,
+				   mdd_t *T,
+				   mdd_t *invariants,
+				   Fsm_Fsm_t *fsm)
+{
+  mdd_t *oneMdd, *nextStates, *fairStates;
+  array_t *toCareSetArray, *forwardRings;
+  mdd_manager *mddMgr = Fsm_FsmReadMddManager(fsm);
+
+  oneMdd = mdd_one(mddMgr);
+  forwardRings = array_alloc(mdd_t *, 0);
+  toCareSetArray = array_alloc(mdd_t *, 0);
+  array_insert(mdd_t *, toCareSetArray, 0, oneMdd);
+  fairStates = Fsm_FsmReadFairnessStates(fsm);
+  if(fairStates == 0)	fairStates = oneMdd;
+  nextStates = McEvaluateESFormulaWithGivenTRWithTarget(fsm, invariants, S, T,
+				   NIL(mdd_t), fairStates, toCareSetArray,
+				   MC_NO_EARLY_TERMINATION,
+				   forwardRings, McVerbosityNone_c,
+				   McDcLevelNone_c, NIL(boolean));
+  mdd_free(nextStates);
+  mdd_array_free(toCareSetArray);
+
+  return(forwardRings);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Build a onion ring from target under invariants.]
+
+  Description [Build a onion ring from target under invariants.
+	       This is function for FateAndFreeWill counterexample generation.]
+
+  SideEffects []
+
+******************************************************************************/
+static array_t *
+Mc_BuildBackwardRingsWithInvariants(
+  mdd_t *S,
+  mdd_t *T,
+  mdd_t *invariants,
+  Fsm_Fsm_t *fsm)
+{
+  mdd_t *oneMdd, *nextStates, *fairStates;
+  array_t *toCareSetArray, *backwardRings;
+  mdd_manager *mddMgr = Fsm_FsmReadMddManager(fsm);
+
+  oneMdd = mdd_one(mddMgr);
+  backwardRings = array_alloc(mdd_t *, 0);
+  toCareSetArray = array_alloc(mdd_t *, 0);
+  array_insert(mdd_t *, toCareSetArray, 0, oneMdd);
+  fairStates = Fsm_FsmReadFairnessStates(fsm);
+  if(fairStates == 0)	fairStates = oneMdd;
+  nextStates = McEvaluateEUFormulaWithGivenTR(fsm, invariants, T,
+				   NIL(mdd_t), fairStates, toCareSetArray,
+				   MC_NO_EARLY_TERMINATION,
+				   backwardRings, McVerbosityNone_c,
+				   McDcLevelNone_c, NIL(boolean));
+  mdd_free(nextStates);
+  mdd_array_free(toCareSetArray);
+
+  return(backwardRings);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Build Path from Core to aState.]
+
+  Description [Build Path starting at a Core state (a state in the first onion
+  ring) to aState.  For paths of length at least one, set PathLengthType to
+  McGreaterZero_c; otherwise, use McGreaterOrEqualZero_c.  The function returns
+  a sequence of states from the core of onionRings to a aState.
+
+  <p>In the case of BFS search, the onion rings are built forward, so that any
+  state in ring i+1 has at least one predecessor in ring i-1.  In non-BFS
+  search that may not be true, but we will have that every state in ring i+1
+  has a predecessor in ring i or less.  The fsm is checked to see if the search
+  was BFS. If not, every ring from the beginning is searched to find the
+  shortest path. This is a greedy heuristic and the shortest path is not
+  guaranteed to be found.  McBuildPathToCore takes a different approach.
+
+  <p>It is the users responsibility to free the array returned as well as its
+  members.]
+
+  SideEffects []
+
+  SeeAlso[Mc_BuildPathToCore]
+
+******************************************************************************/
+array_t *
+Mc_BuildPathFromCore(
+  mdd_t *aStates,
+  array_t *onionRings,
+  Fsm_Fsm_t *modelFsm,
+  Mc_PathLengthType PathLengthType)
+{
+  int i, j;
+  int startingPoint;
+  mdd_t *currentState, *aState;
+  Img_ImageInfo_t * imageInfo = Fsm_FsmReadOrCreateImageInfo(modelFsm, 1, 0);
+  array_t *pathToCore;
+  mdd_manager *mddMgr = Fsm_FsmReadMddManager(modelFsm);
+  array_t *toCareSetArray;
+  array_t *pathFromCore;
+  mdd_t *currentStatePreds, *currentStatePredsInInnerRing;
+  mdd_t *innerRing = NIL(mdd_t), *witnessPredState;
+  boolean shortestDist =
+	(Fsm_FsmReadReachabilityOnionRingsMode(modelFsm) == Fsm_Rch_Bfs_c);
+
+
+  if(Fsm_FsmReadUniQuantifyInputCube(modelFsm)) {
+    pathFromCore = Mc_BuildPathFromCoreFAFW(
+			    aStates, onionRings,
+			    modelFsm, PathLengthType);
+    return(pathFromCore);
+  }
+  aState = Mc_ComputeAState(aStates, modelFsm);
+
+  pathToCore = array_alloc( mdd_t * , 0 );
+  toCareSetArray = NIL(array_t);
+
+  if ( PathLengthType == McGreaterZero_c ) {
+    startingPoint = 1;
+  }
+  else if ( PathLengthType == McGreaterOrEqualZero_c ) {
+    startingPoint = 0;
+  }
+  else {
+    fail("Called Mc_BuildPathFromCore with ill formed PathLengthType\n");
+  }
+
+  /* check that the state occurs in an onion ring. */
+  for ( i = startingPoint ; i < array_n( onionRings ); i++ ) {
+    mdd_t *ring = array_fetch( mdd_t *, onionRings, i );
+    if ( McStateTestMembership( aState, ring ) )
+      break;
+  }
+  if ( i == array_n( onionRings ) ) {
+    mdd_free(aState);
+    return NIL(array_t);
+  }
+
+  /* insert the state in the path to the core */
+  currentState = aState;
+  array_insert_last( mdd_t *, pathToCore, currentState );
+
+  /* initialize */
+  toCareSetArray = array_alloc(mdd_t *, 0);
+  array_insert_last(mdd_t *, toCareSetArray, mdd_one(mddMgr));
+
+  /* loop until a path is found to the core */
+  while( i-- > 0 ) {
+    if (shortestDist) {
+      /* a predecessor is guaranteed to be in the previous ring */
+      mdd_array_free(toCareSetArray);
+      toCareSetArray = array_alloc(mdd_t *, 0);
+      innerRing = array_fetch( mdd_t *, onionRings, i );
+      array_insert(mdd_t *, toCareSetArray, 0, mdd_dup(innerRing));
+      currentStatePreds = Img_ImageInfoComputePreImageWithDomainVars(
+				imageInfo, currentState,
+				currentState, toCareSetArray);
+    } else {
+      /* compute the predecessors */
+      currentStatePreds = Img_ImageInfoComputePreImageWithDomainVars(
+				imageInfo, currentState,
+				currentState, toCareSetArray );
+      /* search for a predecessor in the earliest onion ring */
+      for (j = 0; j <= i; j++) {
+	innerRing = array_fetch( mdd_t *, onionRings, j );
+	if (!mdd_lequal(currentStatePreds, innerRing, 1, 0)) {
+	  i = j;
+	  break;
+	}
+      }
+    }
+    /* compute the set of predecessors in the chosen ring. */
+    currentStatePredsInInnerRing = mdd_and(currentStatePreds, innerRing, 1, 1);
+    mdd_free( currentStatePreds );
+    /* find a state in the predecessor */
+    witnessPredState = Mc_ComputeACloseState(currentStatePredsInInnerRing,
+					     currentState, modelFsm);
+    mdd_free( currentStatePredsInInnerRing );
+    /* insert predecessor in the path */
+    array_insert_last( mdd_t *, pathToCore, witnessPredState );
+    currentState = witnessPredState;
+  }
+
+  mdd_array_free(toCareSetArray);
+
+  /* flip the path to a path from the core */
+  {
+    int i;
+    pathFromCore = array_alloc( mdd_t *, 0 );
+
+    for( i=0; i < array_n( pathToCore ); i++ ) {
+      mdd_t *tmpMdd = array_fetch(mdd_t *, pathToCore,
+				  (array_n(pathToCore) - (i+1)));
+      array_insert_last( mdd_t *, pathFromCore, tmpMdd );
+    }
+    array_free( pathToCore );
+    return pathFromCore;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis [Build a path from initial state to target.]
+
+  Description [Build a path from initial state to target.
+	       This is function for FateAndFreeWill counterexample generation.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+Mc_BuildPathToCoreFAFW(
+  mdd_t *aStates,
+  array_t *onionRings,
+  Fsm_Fsm_t *modelFsm,
+  Mc_PathLengthType PathLengthType)
+{
+  int i, startingPoint;
+  array_t *pathFromCore, *pathToCore;
+  array_t *reachableOnionRings;
+  mdd_t *currentStates;
+
+  if ( PathLengthType == McGreaterZero_c ) {
+    startingPoint = 1;
+  }
+  else if ( PathLengthType == McGreaterOrEqualZero_c ) {
+    startingPoint = 0;
+  }
+  else {
+    fail("Called Mc_BuildPathToCore with ill formed PathLengthType\n");
+  }
+
+  for ( i = startingPoint ; i < array_n( onionRings ); i++ ) {
+    mdd_t *ring = array_fetch( mdd_t *, onionRings, i );
+    if ( McStateTestMembership( aStates, ring ) )
+      break;
+  }
+  if(i==0) {
+    pathToCore = array_alloc( mdd_t * , 0 );
+    array_insert_last( mdd_t *, pathToCore, mdd_dup(aStates) );
+    return pathToCore;
+  }
+
+  reachableOnionRings = Mc_BuildForwardRings(aStates, modelFsm, onionRings);
+  currentStates = array_fetch(mdd_t *, onionRings, 0);
+  pathFromCore = Mc_BuildPathFromCoreFAFW(
+				currentStates,
+				reachableOnionRings, modelFsm, PathLengthType);
+  mdd_array_free(reachableOnionRings);
+
+  return(pathFromCore);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Build a path from target to initial state with general algorithm.]
+
+  Description [Build a path from target to initial state with general algorithm.
+	       This is function for FateAndFreeWill counterexample generation.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+Mc_BuildPathFromCoreFAFWGeneral(
+  mdd_t *T,
+  array_t *rings,
+  Fsm_Fsm_t *modelFsm,
+  Mc_PathLengthType PathLengthType)
+{
+  mdd_manager *mgr = Fsm_FsmReadMddManager(modelFsm);
+  mdd_t *S, *H, *nH, *ring;
+  int i;
+  array_t *L;
+  array_t *pathFromCore;
+  array_t *npathFromCore;
+
+  H = mdd_zero(mgr);
+  for(i=0; i<array_n(rings); i++) {
+    ring = array_fetch(mdd_t *, rings, i);
+    nH = mdd_or(ring, H, 1, 1);
+    mdd_free(H);
+    H = nH;
+  }
+
+  nH = mdd_and(H, T, 1, 1);
+  T = nH;
+
+  L = Mc_BuildFAFWLayer(modelFsm, mdd_dup(T), mdd_dup(H));
+
+  if ( PathLengthType == McGreaterZero_c ) {
+    S = mdd_dup(array_fetch(mdd_t *, rings, 1));
+  }
+  else if( PathLengthType == McGreaterOrEqualZero_c ) {
+    S = mdd_dup(array_fetch(mdd_t *, rings, 0));
+  }
+  else {
+    fail("Called Mc_BuildPathFromCoreFAFW with ill formed PathLengthType\n");
+  }
+  pathFromCore =
+      MC_BuildCounterExampleFAFWGeneral(modelFsm, mdd_dup(S), mdd_dup(T), H, L);
+
+  if(PathLengthType == McGreaterZero_c ) {
+    S = array_fetch(mdd_t *, rings, 0);
+    npathFromCore = array_alloc(mdd_t *, 0);
+    array_insert_last(mdd_t *, npathFromCore, mdd_dup(S));
+    for(i=0; i<array_n(pathFromCore); i++) {
+      S = array_fetch(mdd_t *, pathFromCore, i);
+      array_insert_last(mdd_t *, npathFromCore, S);
+    }
+    array_free(pathFromCore);
+    pathFromCore = npathFromCore;
+  }
+  mdd_free(T);
+  return(pathFromCore);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Build a counterexample path with general algorithm.]
+
+  Description [Build a counterexample path with general algorithm
+	       This is function for FateAndFreeWill counterexample generation.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+MC_BuildCounterExampleFAFWGeneral(
+	Fsm_Fsm_t *modelFsm,
+	mdd_t *I,
+	mdd_t *T,
+	mdd_t *H,
+	array_t *L)
+{
+  mdd_t *oneMdd, *zeroMdd;
+  mdd_t *T_I, *P, *Li, *Q_Li, *Q_T, *nLi;
+  mdd_t *ring, *ring_Q, *Q;
+  mdd_t *layer, *Lm, *nLayer;
+  mdd_t *extCube;
+  mdd_t *invariantStates, *nInvariantStates;
+  int m, q, free, i;
+  array_t *path, *R;
+  array_t *careStatesArray;
+  Img_ImageInfo_t *imageInfo = Fsm_FsmReadOrCreateImageInfo(modelFsm, 1, 0);
+  mdd_manager *mgr = Fsm_FsmReadMddManager(modelFsm);
+
+  oneMdd = mdd_one(mgr);
+  zeroMdd = mdd_zero(mgr);
+  path = array_alloc(mdd_t *, 0);
+
+  T_I = mdd_and(T, I, 1, 1);
+  if(!mdd_equal(T_I, zeroMdd)) {
+    mdd_free(oneMdd);
+    mdd_free(zeroMdd);
+    P = Mc_ComputeACloseState(T_I, T, modelFsm);
+    mdd_free(T_I);
+    array_insert_last(mdd_t *, path, P);
+    return(path);
+  }
+  mdd_free(T_I);
+
+  extCube = Fsm_FsmReadExtQuantifyInputCube(modelFsm);
+  invariantStates = mdd_zero(mgr);
+  layer = NULL;
+  Lm = NULL;
+  for(m=0; m<array_n(L); m++) {
+    layer = array_fetch(mdd_t *, L, m);
+    nLayer = bdd_smooth_with_cube(layer, extCube);
+    nInvariantStates = mdd_or(invariantStates, nLayer, 1, 1);
+    mdd_free(nLayer);
+    mdd_free(invariantStates);
+    invariantStates = nInvariantStates;
+    Lm = mdd_and(I, layer, 1, 1);
+    if(!mdd_equal(Lm, zeroMdd)) {
+      break;
+    }
+    mdd_free(Lm);
+  }
+
+  R = Mc_BuildBackwardRingsWithInvariants(Lm, T, invariantStates, modelFsm);
+
+  imageInfo = Fsm_FsmReadOrCreateImageInfoFAFW(modelFsm, 0, 1);
+  Img_ForwardImageInfoConjoinWithWinningStrategy(imageInfo, layer);
+  /**
+  Img_ImageInfoConjoinWithWinningStrategy(modelFsm, Img_Forward_c, layer);
+  **/
+
+  i = m;
+  Q = mdd_and(I, Lm, 1, 1);
+  ring_Q = NULL;
+  for(q=0; q<array_n(R); q++) {
+    ring = array_fetch(mdd_t *, R, q);
+    ring_Q = mdd_and(ring, Q, 1, 1);
+    if(!mdd_equal(ring_Q, zeroMdd)) {
+      break;
+    }
+    mdd_free(ring_Q);
+  }
+  mdd_free(Q);
+  P = Mc_ComputeACloseState(ring_Q, T, modelFsm);
+  mdd_free(ring_Q);
+
+  free = 0;
+  careStatesArray = array_alloc(mdd_t *, 0);
+  array_insert_last(mdd_t *, careStatesArray, oneMdd);
+  while(1) {
+    Q = Img_ImageInfoComputeImageWithDomainVars(
+			       imageInfo, P, P, careStatesArray);
+    Q_T = mdd_and(Q, P, 1, 0);
+    mdd_free(Q);
+    Q = Q_T;
+
+    if(i>0) {
+      Li = array_fetch(mdd_t *, L, i-1);
+      nLi = bdd_smooth_with_cube(Li, extCube);
+      Q_Li = mdd_and(Q, nLi, 1, 1);
+      mdd_free(nLi);
+      if(!mdd_equal(Q_Li, zeroMdd)) {
+	i--;
+	mdd_free(Q);
+	Q = Q_Li;
+	free = 1;
+	imageInfo = Fsm_FsmReadOrCreateImageInfoFAFW(modelFsm, 0, 1);
+	Img_ForwardImageInfoRecoverFromWinningStrategy(imageInfo);
+	Img_ForwardImageInfoConjoinWithWinningStrategy(imageInfo, layer);
+	/**
+	Fsm_ImageInfoRecoverFromWinningStrategy(modelFsm, Img_Forward_c);
+	Fsm_ImageInfoConjoinWithWinningStrategy(modelFsm, Img_Forward_c, Li);
+	**/
+      }
+    }
+
+    ring_Q = NULL;
+    for(q=0; q<array_n(R); q++) {
+      ring = array_fetch(mdd_t *, R, q);
+      ring_Q = mdd_and(ring, Q, 1, 1);
+      if(!mdd_equal(ring_Q, zeroMdd)) {
+	  break;
+      }
+      mdd_free(ring_Q);
+    }
+    mdd_free(Q);
+
+    if(q >= array_n(R)) {
+      imageInfo = Fsm_FsmReadOrCreateImageInfoFAFW(modelFsm, 0, 1);
+      Img_ForwardImageInfoRecoverFromWinningStrategy(imageInfo);
+      /**
+      Img_ImageInfoRecoverFromWinningStrategy(modelFsm, Img_Forward_c);
+      **/
+      continue;
+    }
+
+    Q = Mc_ComputeACloseState(ring_Q, T, modelFsm);
+    mdd_free(ring_Q);
+
+    if(free == 0) {
+      array_insert_last(mdd_t *, path, (mdd_t *)((long)P+1));
+    }
+    else if(free ==1) {
+      array_insert_last(mdd_t *, path, P);
+      free = 0;
+    }
+
+    Q_T = mdd_and(Q, T, 1, 1);
+    if(!mdd_equal(Q_T, zeroMdd)) {
+      array_insert_last(mdd_t *, path, (mdd_t *)((long)Q+1));
+      mdd_free(Q_T);
+      break;
+    }
+    mdd_free(Q_T);
+
+    P = Q;
+  }
+
+  array_free(careStatesArray);
+  mdd_free(oneMdd);
+  mdd_free(zeroMdd);
+
+  imageInfo = Fsm_FsmReadOrCreateImageInfoFAFW(modelFsm, 0, 1);
+  Img_ForwardImageInfoRecoverFromWinningStrategy(imageInfo);
+  /**
+  Img_ImageInfoRecoverFromWinningStrategy(modelFsm, Img_Forward_c);
+  **/
+  return(path);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Build a fate and free will layer.]
+
+  Description [Build a fate and free will layer.
+	       This is function for FateAndFreeWill counterexample generation.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+Mc_BuildFAFWLayer(Fsm_Fsm_t *modelFsm, mdd_t *T, mdd_t *H)
+{
+  mdd_manager *mgr = Fsm_FsmReadMddManager(modelFsm);
+  Img_ImageInfo_t *imageInfo = Fsm_FsmReadOrCreateImageInfo(modelFsm, 1, 0);
+  mdd_t *zeroMdd, *oneMdd;
+  mdd_t *S, *nH, *EX_S, *extCube, *S_new;
+  array_t *L;
+  array_t *careStatesArray;
+
+  zeroMdd = mdd_zero(mgr);
+  oneMdd = mdd_one(mgr);
+  L = array_alloc(mdd_t *, 0);
+
+  extCube = Fsm_FsmReadExtQuantifyInputCube(modelFsm);
+  careStatesArray = array_alloc(mdd_t *, 0);
+  array_insert_last(mdd_t *, careStatesArray, oneMdd);
+  while(!mdd_equal(H, zeroMdd)) {
+      Fsm_FsmSetUseUnquantifiedFlag(modelFsm, 1);
+      S = Mc_FsmEvaluateAUFormula(modelFsm, H, T,
+				   NIL(mdd_t), oneMdd, careStatesArray,
+				   MC_NO_EARLY_TERMINATION, NIL(array_t),
+				   Mc_None_c, 0, McVerbosityNone_c,
+				   McDcLevelNone_c, NIL(boolean));
+      Fsm_FsmSetUseUnquantifiedFlag(modelFsm, 0);
+      array_insert_last(mdd_t *, L, S);
+
+      S_new = bdd_smooth_with_cube(S, extCube);
+      mdd_free(S);
+      nH = mdd_and(H, S_new, 1, 0);
+
+      if(mdd_equal(H, nH)) {
+	mdd_free(nH);
+	mdd_free(S_new);
+	break;
+      }
+      mdd_free(H);
+      H = nH;
+      mdd_free(T);
+      EX_S = Img_ImageInfoComputePreImageWithDomainVars(
+				imageInfo, S_new, S_new, careStatesArray);
+      mdd_free(S_new);
+      T = mdd_and(EX_S, H, 1, 1);
+  }
+  array_free(careStatesArray);
+  mdd_free(zeroMdd);
+  mdd_free(oneMdd);
+  mdd_free(T);
+  mdd_free(H);
+
+  return(L);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Build a path from target to initial state.]
+
+  Description [Build a path from target to initial state.
+	       This is function for FateAndFreeWill counterexample generation.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+Mc_BuildPathFromCoreFAFW(
+  mdd_t *Ts,
+  array_t *rings,
+  Fsm_Fsm_t *modelFsm,
+  Mc_PathLengthType PathLengthType)
+{
+  int startingPoint, prevFlag;
+  int i, p, dist, forced;
+  bdd_t *T, *S, *H, *nH, *Hp, *S1, *Swin;
+  bdd_t *ring, *oneMdd, *zeroMdd;
+  array_t *C, *newC, *AUrings, *segment;
+  array_t *R, *ESrings;
+  array_t *careStatesArray;
+  array_t *pathFromCore;
+  bdd_t *T_wedge_ring, *S1_wedge_ring, *Hp_wedge_S1;
+  bdd_t *T_wedge_S, *C_T_wedge_S, *ESresult, *EX_T;
+  bdd_t *EX_T_wedge_ring, *Hp_wedge_EX_T, *lastR;
+  bdd_t *C_T_wedge_ring, *new_, *extCube;
+  bdd_t *bundle, *single, *preSingle;
+  Img_ImageInfo_t *imageInfo;
+  mdd_manager *mgr = Fsm_FsmReadMddManager(modelFsm);
+
+  if(Fsm_FsmReadFAFWFlag(modelFsm) == 2) {
+      pathFromCore = Mc_BuildPathFromCoreFAFWGeneral(
+			    Ts, rings,
+			    modelFsm, PathLengthType);
+      return(pathFromCore);
+  }
+
+  T = mdd_dup(Ts);
+  imageInfo = Fsm_FsmReadOrCreateImageInfo(modelFsm, 1, 0);
+  if ( PathLengthType == McGreaterZero_c ) {
+    startingPoint = 1;
+  }
+  else if( PathLengthType == McGreaterOrEqualZero_c ) {
+    startingPoint = 0;
+  }
+  else {
+    fail("Called Mc_BuildPathFromCoreFAFW with ill formed PathLengthType\n");
+  }
+
+  oneMdd = mdd_one(mgr);
+  zeroMdd = mdd_zero(mgr);
+  S = mdd_dup(array_fetch(mdd_t *, rings, startingPoint));
+  prevFlag = 0; /** free **/
+
+  H = mdd_zero(mgr);
+  for(i=startingPoint; i<array_n(rings); i++) {
+    ring = array_fetch(mdd_t *, rings, i);
+    new_ = mdd_and(ring, H, 1, 0);
+    mdd_free(ring);
+    nH = mdd_or(new_, H, 1, 1);
+    mdd_free(H);
+    H = nH;
+    array_insert(mdd_t *, rings, i, new_);
+  }
+
+  C = array_alloc(mdd_t *, 0);
+  T_wedge_S = mdd_and(T, S, 1, 1);
+  if(!mdd_equal(T_wedge_S, zeroMdd)) {
+    if(startingPoint == 1) {
+      mdd_free(T);
+      T = array_fetch(mdd_t *, rings, 0);
+      array_insert_last(mdd_t *, C, bdd_dup(T));
+    }
+    C_T_wedge_S = bdd_closest_cube(T_wedge_S, S, &dist);
+    array_insert_last(mdd_t *, C, C_T_wedge_S);
+    mdd_free(S);
+    mdd_free(oneMdd);
+    mdd_free(zeroMdd);
+    mdd_free(H);
+    mdd_free(T_wedge_S);
+
+    return(C);
+  }
+  mdd_free(T_wedge_S);
+
+  T_wedge_ring = NULL;
+  for(p=startingPoint; p<array_n(rings); p++) {
+    ring = array_fetch(mdd_t *, rings, p);
+    T_wedge_ring = mdd_and(T, ring, 1, 1);
+    if(!mdd_equal(T_wedge_ring, zeroMdd)) {
+      break;
+    }
+    mdd_free(T_wedge_ring);
+  }
+  mdd_free(T);
+
+  C_T_wedge_ring = bdd_closest_cube(T_wedge_ring, S, &dist);
+  mdd_free(T_wedge_ring);
+  array_insert_last(mdd_t *, C, C_T_wedge_ring);
+  T = C_T_wedge_ring;
+
+  extCube = Fsm_FsmReadExtQuantifyInputCube(modelFsm);
+  careStatesArray = array_alloc(mdd_t *, 0);
+  array_insert_last(mdd_t *, careStatesArray, oneMdd);
+  while(1) {
+    if(prevFlag == 0) { /* free segement */
+      prevFlag = 1; /* force segment */
+
+      for(i=array_n(rings)-1; i>p; i--) {
+	ring = array_fetch(mdd_t *, rings, i);
+	nH = mdd_and(H, ring, 1, 0);
+	mdd_free(H);
+	H = nH;
+      }
+
+      AUrings = array_alloc(mdd_t *, 0);
+      Fsm_FsmSetUseUnquantifiedFlag(modelFsm, 1);
+      Swin = Mc_FsmEvaluateAUFormula(modelFsm, H, T,
+				   NIL(mdd_t), oneMdd, careStatesArray,
+				   MC_NO_EARLY_TERMINATION, NIL(array_t),
+				   Mc_None_c, AUrings, McVerbosityNone_c,
+				   McDcLevelNone_c, NIL(boolean));
+      Fsm_FsmSetUseUnquantifiedFlag(modelFsm, 0);
+
+
+      S1 = bdd_smooth_with_cube(Swin, extCube);
+      mdd_array_free(AUrings);
+      if(mdd_equal(S1, T)) {
+	mdd_free(S1);
+	mdd_free(Swin);
+	continue;
+      }
+
+      for(i=p-1; i>=startingPoint; i--) {
+	ring = array_fetch(mdd_t *, rings, i);
+	S1_wedge_ring = mdd_and(S1, ring, 1, 1);
+	if(mdd_equal(S1_wedge_ring, zeroMdd)) {
+	  mdd_free(S1_wedge_ring);
+	  break;
+	}
+	mdd_free(S1_wedge_ring);
+      }
+      p = i+1;
+      Hp = array_fetch(mdd_t *, rings, p);
+
+      ESrings = array_alloc(mdd_t *, 0);
+      Hp_wedge_S1 = mdd_and(Hp, S1, 1, 1);
+
+      ESresult = McEvaluateESFormulaWithGivenTRFAFW( modelFsm, S1, Hp_wedge_S1,
+				       NIL(mdd_t), oneMdd, careStatesArray,
+				       MC_NO_EARLY_TERMINATION, ESrings,
+				       McVerbosityNone_c, McDcLevelNone_c,
+				       NIL(boolean), Swin);
+      mdd_free(ESresult);
+      mdd_free(Hp_wedge_S1);
+      mdd_free(S1);
+      R = ESrings;
+      if(array_n(R) <= 1) {
+	mdd_array_free(R);
+	mdd_free(Swin);
+	continue;
+      }
+    }
+    else { /* force segment */
+      Swin = 0;
+      prevFlag = 0; /* free segment */
+      EX_T = Img_ImageInfoComputePreImageWithDomainVars(
+				imageInfo, T, T, careStatesArray);
+
+      for(i=p-1; i>=startingPoint; i--) {
+	ring = array_fetch(mdd_t *, rings, i);
+	EX_T_wedge_ring = mdd_and(EX_T, ring, 1, 1);
+	if(mdd_equal(EX_T_wedge_ring, zeroMdd)) {
+	  mdd_free(EX_T_wedge_ring);
+	  break;
+	}
+	mdd_free(EX_T_wedge_ring);
+      }
+      p = i+1;
+
+      Hp = array_fetch(mdd_t *, rings, p);
+      R = array_alloc(mdd_t *, 0);
+      Hp_wedge_EX_T = mdd_and(Hp, EX_T, 1, 1);
+      array_insert_last(mdd_t *, R, Hp_wedge_EX_T);
+      /**array_insert_last(mdd_t *, R, T); **/
+      array_insert_last(mdd_t *, R, mdd_dup(T));
+      mdd_free(EX_T);
+    }
+
+    lastR = array_fetch(mdd_t *, R, 0);
+    segment = Mc_BuildShortestPathFAFW(Swin, lastR, T, R, mgr, modelFsm, prevFlag);
+    if(Swin)	{
+      mdd_free(Swin);
+      Swin = 0;
+    }
+    mdd_array_free(R);
+
+    newC = array_join(C, segment);
+    array_free(C);
+    C = newC;
+
+    T = array_fetch(mdd_t *, segment, array_n(segment)-1);
+    if((long)T %2) T = (mdd_t *)((long)T - 1);
+/**    T = mdd_dup(T); **/
+    array_free(segment);
+
+    T_wedge_S = mdd_and(T, S, 1, 1);
+    if(!mdd_equal(T_wedge_S, zeroMdd)) {
+      mdd_free(T_wedge_S);
+/**      mdd_free(T);  **/
+      mdd_free(S);
+      mdd_free(H);
+      break;
+    }
+    mdd_free(T_wedge_S);
+
+    startingPoint = 0;
+    mdd_free(S);
+    S = mdd_dup(array_fetch(mdd_t *, rings, startingPoint));
+
+  }
+
+  array_free(careStatesArray);
+  mdd_free(oneMdd);
+  mdd_free(zeroMdd);
+
+  {
+    int i;
+    pathFromCore = array_alloc( mdd_t *, 0 );
+
+    if(startingPoint == 1) {
+      T = array_fetch(mdd_t *, rings, 0);
+      array_insert_last(mdd_t *, pathFromCore, bdd_dup(T));
+    }
+
+    preSingle = NULL;
+    for( i=0; i < array_n( C ); i++ ) {
+      bundle = array_fetch(mdd_t *, C, (array_n(C) - (i+1)));
+      forced = 0;
+      if((long)bundle%2) {
+	bundle = (mdd_t *)((long)bundle -1);
+	forced++;
+      }
+      if(i==0)
+	single = Mc_ComputeAState(bundle, modelFsm);
+      else
+	single = Mc_ComputeACloseState(bundle, preSingle, modelFsm);
+      array_insert_last( mdd_t *, pathFromCore,
+	      (mdd_t *)((long)(single) + forced) );
+      preSingle = single;
+    }
+    McNormalizeBddPointer(C);
+    mdd_array_free(C);
+    return pathFromCore;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis [Build a shortest path from T to S.]
+
+  Description [Make a shortest path from T to S which only passes through
+	       states in rings. There is always a path from T to S.
+	       Returns a sequence of states starting from T, leading to S.
+	       It is the users responsibility to free the returned
+	       array as well as its members.
+	       This is function for FateAndFreeWill counterexample generation.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+Mc_BuildShortestPathFAFW(mdd_t *win,
+			 mdd_t *S,
+			 mdd_t *T,
+			 array_t *rings,
+			 mdd_manager *mgr,
+			 Fsm_Fsm_t *fsm,
+			 int prevFlag)
+{
+  int q, dist;
+  mdd_t *zeroMdd, *oneMdd;
+  mdd_t *inputCube;
+  mdd_t *ring, *ring_wedge_T, *Cn, *Cs;
+  mdd_t *K, *realK, *range;
+  mdd_t *preimage_of_Cn;
+  array_t *C, *stateVars, *inputVars;
+  array_t *toCareSetArray;
+  Img_ImageInfo_t *imageInfo;
+
+  imageInfo = Fsm_FsmReadOrCreateImageInfo(fsm, 1, 0);
+  stateVars = Fsm_FsmReadPresentStateVars(fsm);
+  inputVars = Fsm_FsmReadInputVars(fsm);
+  inputCube = mdd_id_array_to_bdd_cube(mgr, inputVars);
+  zeroMdd = mdd_zero(mgr);
+  oneMdd = mdd_one(mgr);
+  ring_wedge_T = NULL;
+  for (q = 0; q < array_n(rings); q++){
+    ring = array_fetch(mdd_t *, rings, q);
+    ring_wedge_T = mdd_and(T, ring, 1, 1);
+    if(!mdd_equal(ring_wedge_T, zeroMdd))
+      break;
+    mdd_free(ring_wedge_T);
+    ring_wedge_T = 0;
+  }
+  if(ring_wedge_T) {
+    mdd_free(ring_wedge_T);
+  }
+  else {
+    fprintf(stdout, "We cannot find T\n");
+  }
+
+  C = array_alloc(mdd_t *, 0);
+  Cn = (T);
+  toCareSetArray = array_alloc(mdd_t *, 0);
+  array_insert(mdd_t *, toCareSetArray, 0, oneMdd);
+  range = mdd_range_mdd(mgr, stateVars);
+  while(q > 0) {
+    preimage_of_Cn = Img_ImageInfoComputePreImageWithDomainVars(
+				imageInfo, Cn, Cn, toCareSetArray);
+
+    K = NULL;
+    for (q = 0; q < array_n(rings); q++){
+      ring = array_fetch(mdd_t *, rings, q);
+      K = mdd_and(preimage_of_Cn, ring, 1, 1);
+      if(!mdd_equal(K, zeroMdd))
+	break;
+      mdd_free(K);
+      K = 0;
+    }
+
+    mdd_free(preimage_of_Cn);
+    realK = mdd_and(K, range, 1, 1);
+    mdd_free(K);
+    Cs = bdd_closest_cube(realK, Cn, &dist);
+    mdd_free(realK);
+
+
+    Cn = bdd_smooth_with_cube(Cs, inputCube);
+    mdd_free(Cs);
+    if(!prevFlag) /** free segment **/
+      array_insert_last(mdd_t *, C, Cn);
+    else          /** fated segment **/
+      array_insert_last(mdd_t *, C, (mdd_t *)((long)Cn+1));
+  }
+  array_free(toCareSetArray);
+  mdd_free(zeroMdd);
+  mdd_free(oneMdd);
+  mdd_free(range);
+  mdd_free(inputCube);
+  return(C);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis [Make a path from aState to bState.]
+
+  Description [Make a path from aState to bState which only passes through
+  invariantStates; it is assumed that aState and bState lie in invariantStates.
+  Returns a sequence of states starting from aState, leading to bState. If
+  aState == bState, a non trivial path is returned (ie a cycle). If no
+  path exists, return NIL. It is the users responsibility to free the returned
+  array as well as its members.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+Mc_CompletePath(
+  mdd_t *aState,
+  mdd_t *bState,
+  mdd_t *invariantStates,
+  Fsm_Fsm_t *modelFsm,
+  array_t *careSetArray,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  Mc_FwdBwdAnalysis dirn)
+{
+
+  if ( dirn == McFwd_c )  {
+    return McCompletePathFwd(aState, bState, invariantStates, modelFsm,
+			     careSetArray, verbosity, dcLevel );
+  }
+  else {
+    return McCompletePathBwd(aState, bState, invariantStates, modelFsm,
+			     careSetArray, verbosity, dcLevel );
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis [Pick an arbitrary minterm from the given set.]
+
+  Description [Pick an arbitrary minterm from the given set. Support is an
+  array of mddids representing the total support; that is, all the variables
+  on which aSet may depend.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Mc_ComputeAMinterm(
+  mdd_t *aSet,
+  array_t *Support,
+  mdd_manager *mddMgr)
+{
+  /* check that support of set is contained in Support */
+  assert( SetCheckSupport( aSet, Support, mddMgr ));
+  assert(!mdd_is_tautology(aSet, 0));
+
+  if(bdd_get_package_name() == CUDD){
+    mdd_t *range;             /* range of Support             */
+    mdd_t *legalSet;          /* aSet without the don't cares */
+    array_t *bddSupport;      /* Support in terms of bdd vars */
+    mdd_t *minterm;           /* a random minterm             */
+
+    range      = mdd_range_mdd(mddMgr, Support);
+    legalSet   = bdd_intersects(aSet, range);
+    mdd_free(range);
+    bddSupport = mdd_id_array_to_bdd_array(mddMgr, Support);
+    minterm    = bdd_pick_one_minterm(legalSet, bddSupport);
+
+    assert(MintermCheckWellFormed(minterm, Support, mddMgr));
+    assert(mdd_count_onset(mddMgr, minterm, Support) == 1);
+    assert(mdd_lequal(minterm,legalSet,1,1));
+
+    mdd_array_free(bddSupport);
+    mdd_free(legalSet);
+
+    return minterm;
+  }else{
+    int i, j;
+    mdd_t *aSetDup;
+    mdd_t *resultMdd;
+    array_t *resultMddArray = array_alloc( mdd_t *, 0 );
+
+    aSetDup = mdd_dup( aSet );
+    for( i = 0 ; i < array_n( Support ); i++ ) {
+
+      int aSupportVar = array_fetch( int, Support, i );
+
+      for( j = 0 ;;) {
+	mdd_t *faceMdd, *tmpMdd;
+	array_t *tmpArray = array_alloc( int, 0 );
+	array_insert_last( int, tmpArray, j );
+
+	/* this call will crash if have run through range of mvar */
+	faceMdd = mdd_literal( mddMgr, aSupportVar, tmpArray );
+	array_free( tmpArray );
+	tmpMdd = mdd_and( faceMdd, aSetDup, 1, 1 );
+
+	if ( !mdd_is_tautology( tmpMdd, 0 ) ) {
+	  array_insert_last( mdd_t *, resultMddArray, faceMdd );
+	  mdd_free( aSetDup );
+	  aSetDup = tmpMdd;
+	  break;
+	}
+	mdd_free( faceMdd );
+	mdd_free( tmpMdd );
+	j++;
+      }
+    }
+    mdd_free( aSetDup );
+
+    resultMdd = mdd_one( mddMgr );
+    for ( i = 0 ; i < array_n( resultMddArray ); i++ ) {
+      mdd_t *faceMdd = array_fetch( mdd_t *, resultMddArray, i );
+      mdd_t *tmpMdd = mdd_and( faceMdd, resultMdd, 1, 1 );
+      mdd_free( resultMdd ); mdd_free( faceMdd );
+      resultMdd = tmpMdd;
+    }
+    array_free( resultMddArray );
+
+    return resultMdd;
+  }/* IF CUDD */
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Pick a minterm from the given set close to target. Support
+  is an array of mddids representing the total support; that is, all
+  the variables on which aSet may depend.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Mc_ComputeACloseMinterm(
+  mdd_t *aSet,
+  mdd_t *target,
+  array_t *Support,
+  mdd_manager *mddMgr)
+{
+  if (bdd_get_package_name() == CUDD && target != NIL(mdd_t)) {
+    mdd_t *range;             /* range of Support             */
+    mdd_t *legalSet;          /* aSet without the don't cares */
+    mdd_t *closeCube;
+    int dist;
+    array_t *bddSupport;      /* Support in terms of bdd vars */
+    mdd_t *minterm;           /* a random minterm             */
+
+    /* Check that support of set is contained in Support. */
+    assert(SetCheckSupport(aSet, Support, mddMgr));
+    assert(!mdd_is_tautology(aSet, 0));
+    range      = mdd_range_mdd(mddMgr, Support);
+    legalSet   = bdd_and(aSet, range, 1, 1);
+    mdd_free(range);
+    closeCube = mdd_closest_cube(legalSet, target, &dist);
+    bddSupport = mdd_id_array_to_bdd_array(mddMgr, Support);
+    minterm    = bdd_pick_one_minterm(closeCube, bddSupport);
+
+    assert(MintermCheckWellFormed(minterm, Support, mddMgr));
+    assert(mdd_count_onset(mddMgr, minterm, Support) == 1);
+    assert(mdd_lequal(minterm,legalSet,1,1));
+
+    mdd_array_free(bddSupport);
+    mdd_free(legalSet);
+    mdd_free(closeCube);
+
+    return minterm;
+  } else {
+    return Mc_ComputeAMinterm(aSet, Support, mddMgr);
+  }/* if CUDD */
+
+} /* McComputeACloseMinterm */
+
+
+
+
+/**Function********************************************************************
+
+  Synopsis [Return a string for a minterm.]
+
+  SideEffects []
+
+******************************************************************************/
+char *
+Mc_MintermToStringAiger(
+  mdd_t *aMinterm,
+  array_t *aSupport,
+  Ntk_Network_t *aNetwork)
+{
+  int i;
+  char *tmp1String;
+  char *tmp2String;
+  char bodyString[McMaxStringLength_c];
+  char *mintermString = NIL(char);
+  mdd_manager *mddMgr = Ntk_NetworkReadMddManager( aNetwork );
+  array_t *valueArray;
+  array_t *stringArray = array_alloc( char *, 0 );
+
+  aMinterm = GET_NORMAL_PT(aMinterm);
+  valueArray = McConvertMintermToValueArray(aMinterm, aSupport, mddMgr);
+  for ( i = 0 ; i < array_n( aSupport ); i++ ) {
+
+    int mddId = array_fetch( int, aSupport, i );
+    int value = array_fetch( int, valueArray, i );
+    Ntk_Node_t *node = Ntk_NetworkFindNodeByMddId( aNetwork, mddId );
+    char *nodeName = Ntk_NodeReadName( node );
+    if(!((nodeName[0] == '$') && (nodeName[1] == '_')))
+    {
+      Var_Variable_t *nodeVar = Ntk_NodeReadVariable( node );
+
+      if ( Var_VariableTestIsSymbolic( nodeVar ) ) {
+	char *symbolicValue = Var_VariableReadSymbolicValueFromIndex(nodeVar,
+								   value );
+	sprintf( bodyString, "%s", symbolicValue );
+      }
+      else {
+	sprintf( bodyString, "%d", value );
+      }
+      tmp1String = util_strsav( bodyString );
+      array_insert_last( char *, stringArray, tmp1String );
+    }
+  }
+  array_free(valueArray);
+
+  array_sort( stringArray, cmp);
+
+  for ( i = 0 ; i < array_n( stringArray ); i++ ) {
+    tmp1String = array_fetch( char *, stringArray, i );
+    if( i == 0 )  {
+      mintermString = util_strcat3(tmp1String, "", "" );
+    }
+    else {
+      tmp2String = util_strcat3(mintermString, "", tmp1String );
+      FREE(mintermString);
+      mintermString = tmp2String;
+    }
+    FREE(tmp1String);
+  }
+  array_free( stringArray );
+
+  tmp1String = util_strcat3(mintermString, " ", "");
+  FREE(mintermString);
+  mintermString = tmp1String;
+
+  return mintermString;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Return a string for a minterm.]
+
+  SideEffects []
+
+******************************************************************************/
+char *
+Mc_MintermToStringAigerInput(
+  mdd_t *aMinterm,
+  array_t *aSupport,
+  Ntk_Network_t *aNetwork)
+{
+  int i;
+  char *tmp1String;
+  char *tmp2String;
+  char bodyString[McMaxStringLength_c];
+  char *mintermString = NIL(char);
+  mdd_manager *mddMgr = Ntk_NetworkReadMddManager( aNetwork );
+  array_t *valueArray;
+  array_t *stringArray = array_alloc( char *, 0 );
+
+  aMinterm = GET_NORMAL_PT(aMinterm);
+  valueArray = McConvertMintermToValueArray(aMinterm, aSupport, mddMgr);
+  for ( i = 0 ; i < array_n( aSupport ); i++ ) {
+
+    int mddId = array_fetch( int, aSupport, i );
+    int value = array_fetch( int, valueArray, i );
+    Ntk_Node_t *node = Ntk_NetworkFindNodeByMddId( aNetwork, mddId );
+    char *nodeName = Ntk_NodeReadName( node );
+    if((nodeName[0] == '$') && (nodeName[1] == '_'))
+    {
+      Var_Variable_t *nodeVar = Ntk_NodeReadVariable( node );
+
+      if ( Var_VariableTestIsSymbolic( nodeVar ) ) {
+	char *symbolicValue = Var_VariableReadSymbolicValueFromIndex(nodeVar,
+								   value );
+	sprintf( bodyString, "%s", symbolicValue );
+      }
+      else {
+	sprintf( bodyString, "%d", value );
+      }
+      tmp1String = util_strsav( bodyString );
+      array_insert_last( char *, stringArray, tmp1String );
+    }
+  }
+  array_free(valueArray);
+
+  array_sort( stringArray, cmp);
+
+  for ( i = 0 ; i < array_n( stringArray ); i++ ) {
+    tmp1String = array_fetch( char *, stringArray, i );
+    if( i == 0 )  {
+      mintermString = util_strcat3(tmp1String, "", "" );
+    }
+    else {
+      tmp2String = util_strcat3(mintermString, "", tmp1String );
+      FREE(mintermString);
+      mintermString = tmp2String;
+    }
+    FREE(tmp1String);
+  }
+  array_free( stringArray );
+
+  tmp1String = util_strcat3(mintermString, " ", "");
+  FREE(mintermString);
+  mintermString = tmp1String;
+
+  return mintermString;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return a string for a minterm.]
+
+  SideEffects []
+
+******************************************************************************/
+char *
+Mc_MintermToString(
+  mdd_t *aMinterm,
+  array_t *aSupport,
+  Ntk_Network_t *aNetwork)
+{
+  int i;
+  char *tmp1String;
+  char *tmp2String;
+  char bodyString[McMaxStringLength_c];
+  char *mintermString = NIL(char);
+  mdd_manager *mddMgr = Ntk_NetworkReadMddManager( aNetwork );
+  array_t *valueArray;
+  array_t *stringArray = array_alloc( char *, 0 );
+
+  aMinterm = GET_NORMAL_PT(aMinterm);
+  valueArray = McConvertMintermToValueArray(aMinterm, aSupport, mddMgr);
+  for ( i = 0 ; i < array_n( aSupport ); i++ ) {
+
+    int mddId = array_fetch( int, aSupport, i );
+    int value = array_fetch( int, valueArray, i );
+    Ntk_Node_t *node = Ntk_NetworkFindNodeByMddId( aNetwork, mddId );
+    char *nodeName = Ntk_NodeReadName( node );
+    Var_Variable_t *nodeVar = Ntk_NodeReadVariable( node );
+
+    if ( Var_VariableTestIsSymbolic( nodeVar ) ) {
+      char *symbolicValue = Var_VariableReadSymbolicValueFromIndex(nodeVar,
+								   value );
+      sprintf( bodyString, "%s:%s", nodeName, symbolicValue );
+    }
+    else {
+      sprintf( bodyString, "%s:%d", nodeName, value );
+    }
+    tmp1String = util_strsav( bodyString );
+    array_insert_last( char *, stringArray, tmp1String );
+  }
+  array_free(valueArray);
+
+  array_sort( stringArray, cmp);
+
+  for ( i = 0 ; i < array_n( stringArray ); i++ ) {
+    tmp1String = array_fetch( char *, stringArray, i );
+    if( i == 0 )  {
+      mintermString = util_strcat3(tmp1String, "", "" );
+    }
+    else {
+      tmp2String = util_strcat3(mintermString, "\n", tmp1String );
+      FREE(mintermString);
+      mintermString = tmp2String;
+    }
+    FREE(tmp1String);
+  }
+  array_free( stringArray );
+
+  tmp1String = util_strcat3(mintermString, "\n", "");
+  FREE(mintermString);
+  mintermString = tmp1String;
+
+  return mintermString;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Utility function - prints states on path, inputs for transitions]
+
+  SideEffects []
+
+******************************************************************************/
+int
+Mc_PrintPath(
+  array_t *aPath,
+  Fsm_Fsm_t *modelFsm,
+  boolean printInput)
+{
+  int check, forced, i;
+  int numForced;
+  mdd_t *inputSet=NIL(mdd_t);
+  mdd_t *uInput = NIL(mdd_t);
+  mdd_t *vInput = NIL(mdd_t);
+
+  array_t *psVars = Fsm_FsmReadPresentStateVars( modelFsm );
+  array_t *inputVars = Fsm_FsmReadInputVars( modelFsm );
+  mdd_manager *mddMgr =  Fsm_FsmReadMddManager( modelFsm );
+
+  forced = 0;
+  check = 1;
+  numForced = 0;
+
+
+  for( i = -1 ; i < (array_n( aPath )-1); i++ ) {
+
+    mdd_t *aState = ( i == -1 ) ? NIL(mdd_t) : array_fetch( mdd_t *, aPath, i );
+    mdd_t *bState = array_fetch( mdd_t *, aPath, (i+1) );
+
+    if((long)aState%2) {
+      aState = (mdd_t *)((long)aState -1);
+      forced++;
+    }
+    else	forced = 0;
+
+    if((long)bState%2) {
+      bState = (mdd_t *)((long)bState -1);
+    }
+
+    if ( printInput == TRUE && i != -1) {
+      inputSet = Mc_FsmComputeDrivingInputMinterms( modelFsm, aState, bState );
+      vInput = Mc_ComputeACloseMinterm( inputSet, uInput, inputVars, mddMgr );
+    }
+    if(forced)	{
+      fprintf(vis_stdout, "---- Forced %d\n", forced);
+      numForced ++;
+    }
+    McPrintTransition( aState, bState, uInput, vInput, psVars, inputVars,
+		       printInput, modelFsm, (i+1) );
+
+
+    if ( uInput != NIL(mdd_t) ) {
+      mdd_free(uInput);
+    }
+    uInput = vInput;
+
+    if ( inputSet != NIL(mdd_t) ) {
+      mdd_free(inputSet);
+    }
+  }
+
+  if ( vInput != NIL(mdd_t) ) {
+    mdd_free(uInput);
+  }
+
+  if(Fsm_FsmReadFAFWFlag(modelFsm) > 0) {
+    fprintf(vis_stdout,
+	"# MC: the number of non-trivial forced segments %d\n",
+	numForced);
+  }
+
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Utility function - prints states on path, inputs for transitions]
+
+  SideEffects []
+
+******************************************************************************/
+int
+Mc_PrintPathAiger(
+  array_t *aPath,
+  Fsm_Fsm_t *modelFsm,
+  boolean printInput)
+{
+  int check, forced, i;
+  int numForced;
+  mdd_t *inputSet=NIL(mdd_t);
+  mdd_t *uInput = NIL(mdd_t);
+  mdd_t *vInput = NIL(mdd_t);
+
+  array_t *psVars = Fsm_FsmReadPresentStateVars( modelFsm );
+  array_t *inputVars = Fsm_FsmReadInputVars( modelFsm );
+
+  forced = 0;
+  check = 1;
+  numForced = 0;
+
+  Ntk_Network_t *network = Fsm_FsmReadNetwork( modelFsm );
+
+  FILE *psO = Cmd_FileOpen("inputOrder.txt", "w", NIL(char *), 0);
+  for(i=0; i<array_n(psVars); i++)
+  {
+    int mddId = array_fetch( int, psVars, i );
+    Ntk_Node_t *node = Ntk_NetworkFindNodeByMddId( network, mddId );
+    char *nodeName = Ntk_NodeReadName( node );
+    if((nodeName[0] == '$') && (nodeName[1] == '_'))
+    {
+      fprintf(psO, "%s\n", &nodeName[2]);
+    }
+  }
+  fclose(psO);
+
+  for( i = -1 ; i < (array_n( aPath )-1); i++ ) {
+
+    mdd_t *aState = ( i == -1 ) ? NIL(mdd_t) : array_fetch( mdd_t *, aPath, i );
+    mdd_t *bState = array_fetch( mdd_t *, aPath, (i+1) );
+
+    if((long)aState%2) {
+      aState = (mdd_t *)((long)aState -1);
+      forced++;
+    }
+    else	forced = 0;
+
+    if((long)bState%2) {
+      bState = (mdd_t *)((long)bState -1);
+    }
+
+    if(forced)	{
+      fprintf(vis_stdout, "---- Forced %d\n", forced);
+      numForced ++;
+    }
+
+    /* The following fix is only for Sat-competition 2007 and will need to be fixed for future */
+
+    if(i == (array_n(aPath)-2))
+    {
+      McPrintTransitionAiger( aState, bState, uInput, vInput, psVars, inputVars,
+		       printInput, modelFsm, 1 );
+    }
+    else
+    {
+      McPrintTransitionAiger( aState, bState, uInput, vInput, psVars, inputVars,
+		       printInput, modelFsm, 0 );
+    }
+
+
+    if ( uInput != NIL(mdd_t) ) {
+      mdd_free(uInput);
+    }
+    uInput = vInput;
+
+    if ( inputSet != NIL(mdd_t) ) {
+      mdd_free(inputSet);
+    }
+  }
+
+  if ( vInput != NIL(mdd_t) ) {
+    mdd_free(uInput);
+  }
+
+  if(Fsm_FsmReadFAFWFlag(modelFsm) > 0) {
+    fprintf(vis_stdout,
+	"# MC: the number of non-trivial forced segments %d\n",
+	numForced);
+  }
+
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds MVF for a node that is a pseudo input.]
+
+  Description [Builds MVF for a node that is a pseudo input.  This node has a
+  single output and no inputs. Its table has several row entries.  We build an
+  MVF whose components correspond exactly to possible table outputs.]
+
+  SideEffects []
+
+  Comment [Although pseudo inputs, constants, and internal nodes all have
+  tables, a single procedure cannot be used to build their MVF.  A pseudo
+  input MVF is built in terms of its mddId, whereas a constant or internal is
+  not.  A constant or pseudo input doesn't have any inputs, whereas an
+  internal does.]
+
+  SeeAlso     [Tbl_TableBuildMvfForNonDetConstant]
+
+******************************************************************************/
+static Mvf_Function_t *
+NodeBuildPseudoInputMvf(
+  Ntk_Node_t * node,
+  mdd_manager * mddMgr)
+{
+  Mvf_Function_t *mvf;
+  int             columnIndex = Ntk_NodeReadOutputIndex(node);
+  Tbl_Table_t    *table       = Ntk_NodeReadTable(node);
+  int             mddId       = Ntk_NodeReadMddId(node);
+
+  assert(mddId != NTK_UNASSIGNED_MDD_ID);
+  mvf = Tbl_TableBuildNonDetConstantMvf(table, columnIndex, mddId, mddMgr);
+  return mvf;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return the range of pseudo inputs if they are defined by subsets of range.]
+
+  Description [The result can be used to extract correct input conditions.]
+
+  SideEffects []
+
+******************************************************************************/
+static mdd_t *
+Mc_ComputeRangeOfPseudoInputs(
+  Ntk_Network_t *network)
+{
+  mdd_manager *mddMgr = Ntk_NetworkReadMddManager( network );
+  Mvf_Function_t *nodeMvf;
+  mdd_t *tmpMdd, *zeroMdd;
+  mdd_t *restrictMdd, *sumMdd;
+  int restrictFlag;
+  lsGen gen;
+  Ntk_Node_t *node;
+  int i;
+
+  zeroMdd = mdd_zero(mddMgr);
+  restrictMdd = mdd_one(mddMgr);
+  restrictFlag = 0;
+  Ntk_NetworkForEachPseudoInput(network, gen, node) {
+    nodeMvf = NodeBuildPseudoInputMvf(node, mddMgr);
+    for(i=0; i<nodeMvf->num; i++) {
+      tmpMdd = array_fetch(mdd_t *, nodeMvf, i);
+      if(mdd_equal(tmpMdd, zeroMdd)) {
+	restrictFlag = 1;
+	break;
+      }
+    }
+    if(restrictFlag) {
+      sumMdd = mdd_zero(mddMgr);
+      for(i=0; i<nodeMvf->num; i++) {
+	tmpMdd = array_fetch(mdd_t *, nodeMvf, i);
+	if(!mdd_equal(tmpMdd, zeroMdd)) {
+	  tmpMdd = mdd_or( sumMdd, tmpMdd, 1, 1 );
+	  mdd_free(sumMdd);
+	  sumMdd = tmpMdd;
+	}
+      }
+      tmpMdd = mdd_and( sumMdd, restrictMdd, 1, 1 );
+      mdd_free(sumMdd);
+      mdd_free(restrictMdd);
+      restrictMdd = tmpMdd;
+    }
+    Mvf_FunctionFree(nodeMvf);
+  }
+  mdd_free(zeroMdd);
+
+  return(restrictMdd);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Return all inputs which cause a transition from aState to bState.]
+
+  Description [Return all inputs which cause a transition from aState to bState.
+  It is assumed that aState,bState are truly minterms over the PS variables.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Mc_FsmComputeDrivingInputMinterms(
+  Fsm_Fsm_t *fsm,
+  mdd_t *aState,
+  mdd_t *bState )
+{
+  int i;
+  int psMddId;
+  int inputMddId;
+  mdd_gen *mddGen;
+  Ntk_Node_t *latch, *node, *dataNode;
+  array_t *aMinterm, *bMinterm;
+  mdd_t *resultMdd;
+  array_t *resultMvfs;
+  array_t *inputArray = Fsm_FsmReadInputVars( fsm );
+  array_t *psArray = Fsm_FsmReadPresentStateVars( fsm );
+  Ntk_Network_t *network = Fsm_FsmReadNetwork( fsm );
+  st_table *leaves = st_init_table(st_ptrcmp, st_ptrhash);
+  array_t *roots = array_alloc( Ntk_Node_t *, 0 );
+  array_t *latches = array_alloc( Ntk_Node_t *, 0 );
+  array_t *support = array_alloc( int, 0 );
+  mdd_t *rangeOfPseudoInputs, *tmpMdd;
+
+  arrayForEachItem(int , psArray, i, psMddId ) {
+    latch = Ntk_NetworkFindNodeByMddId( network, psMddId );
+    dataNode = Ntk_LatchReadDataInput( latch );
+    array_insert_last( int, support, psMddId );
+    array_insert_last( Ntk_Node_t *, roots, dataNode );
+    array_insert_last( Ntk_Node_t *, latches, latch );
+  }
+
+  /* Convert the  minterm to an array of assignments to support vars. */
+  foreach_mdd_minterm(aState, mddGen, aMinterm, support) {
+    mdd_gen_free(mddGen);
+    break;
+    /* NOT REACHED */
+  }
+
+  foreach_mdd_minterm(bState, mddGen, bMinterm, support) {
+    mdd_gen_free(mddGen);
+    break;
+     /* NOT REACHED */
+  }
+  array_free( support );
+
+  arrayForEachItem(int , inputArray, i, inputMddId ) {
+    node = Ntk_NetworkFindNodeByMddId( network, inputMddId );
+    st_insert(leaves, (char *) node, (char *) NTM_UNUSED );
+  }
+
+  for ( i = 0 ; i < array_n( roots ); i++ ) {
+    int value = array_fetch( int, aMinterm, i );
+    latch = array_fetch( Ntk_Node_t *, latches, i );
+    st_insert( leaves, (char *) latch, (char *) (long) value );
+  }
+
+  resultMvfs = Ntm_NetworkBuildMvfs( network, roots, leaves, NIL(mdd_t) );
+
+  array_free( roots );
+  array_free( latches );
+  st_free_table( leaves );
+
+  rangeOfPseudoInputs = Mc_ComputeRangeOfPseudoInputs(network);
+
+  resultMdd = rangeOfPseudoInputs;
+  for ( i = 0 ; i < array_n( resultMvfs ) ; i++ ) {
+    Mvf_Function_t *mvf = array_fetch( Mvf_Function_t *, resultMvfs, i );
+    int value = array_fetch( int, bMinterm, i );
+    mdd_t *activeMdd = Mvf_FunctionReadComponent( mvf, value );
+    tmpMdd = mdd_and( activeMdd, resultMdd, 1, 1 );
+    if(mdd_is_tautology(tmpMdd, 0)) {
+	fprintf(stdout, "current error\n");
+    }
+    mdd_free( resultMdd );
+    resultMdd = tmpMdd;
+    Mvf_FunctionFree( mvf );
+  }
+  array_free( resultMvfs);
+  array_free( aMinterm );
+  array_free( bMinterm );
+
+  return resultMdd;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Select an arbitrary  state from the given set]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Mc_ComputeAState(
+  mdd_t *states,
+  Fsm_Fsm_t *modelFsm)
+{
+  array_t *PSVars = Fsm_FsmReadPresentStateVars( modelFsm );
+  mdd_manager *mddMgr = Ntk_NetworkReadMddManager( Fsm_FsmReadNetwork( modelFsm ) );
+  mdd_t *result = Mc_ComputeAMinterm( states, PSVars, mddMgr );
+
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Select a state from the given set close to target.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Mc_ComputeACloseState(
+  mdd_t *states,
+  mdd_t *target,
+  Fsm_Fsm_t *modelFsm)
+{
+  array_t *PSVars = Fsm_FsmReadPresentStateVars( modelFsm );
+  mdd_manager *mddMgr = Ntk_NetworkReadMddManager( Fsm_FsmReadNetwork( modelFsm ) );
+  mdd_t *result = Mc_ComputeACloseMinterm( states, target, PSVars, mddMgr );
+
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Print a minterm.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Mc_MintermPrint(
+  mdd_t *aMinterm,
+  array_t *support,
+  Ntk_Network_t *aNetwork)
+{
+  char *tmpString = Mc_MintermToString( aMinterm, support, aNetwork );
+  fprintf( vis_stdout, "%s", tmpString );
+  FREE(tmpString);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Add nodes for wires referred to in formula to nodesTable.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Mc_NodeTableAddCtlFormulaNodes(
+  Ntk_Network_t *network,
+  Ctlp_Formula_t *formula,
+  st_table * nodesTable )
+{
+  NodeTableAddCtlFormulaNodes( network, formula, nodesTable );
+}
+
+/**Function********************************************************************
+
+  Synopsis [Add nodes for wires referred to in formula to nodesTable.]
+
+  Description [Add nodes for wires referred to in formula to nodesTable.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Mc_NodeTableAddLtlFormulaNodes(
+  Ntk_Network_t *network,
+  Ctlsp_Formula_t *formula,
+  st_table * nodesTable )
+{
+  NodeTableAddLtlFormulaNodes(network, formula, nodesTable);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Form an FSM reduced with respect to the specified formula]
+
+  Description [Form an FSM reduced with respect to the CTL formula array.
+  All latches and inputs which affect the given formula AND the fairness
+  conditions of the system are included in this reduced fsm.]
+
+  SideEffects []
+
+******************************************************************************/
+Fsm_Fsm_t *
+Mc_ConstructReducedFsm(
+  Ntk_Network_t *network,
+  array_t *ctlFormulaArray)
+{
+  return(McConstructReducedFsm(network, ctlFormulaArray));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts a string to a schedule type.]
+
+  Description [Converts a string to a schedule type.  If string does
+  not refer to one of the allowed schedule types, then returns
+  McGSH_Unassigned_c.]
+
+  SideEffects []
+
+******************************************************************************/
+Mc_GSHScheduleType
+Mc_StringConvertToScheduleType(
+  char *string)
+{
+  return McStringConvertToScheduleType(string);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Converts a string to a lockstep mode.]
+
+  Description [Converts a string to a lockstep mode.  If string does
+  not refer to one of the allowed lockstep modes, it returns
+  MC_LOCKSTEP_UNASSIGNED.  The allowed values are: MC_LOCKSTEP_OFF,
+  MC_LOCKSTEP_EARLY_TERMINATION, MC_LOCKSTEP_ALL_SCCS, and a positive
+  integer n (lockstep enumerates up to n fair SCCs).]
+
+  SideEffects []
+
+******************************************************************************/
+int
+Mc_StringConvertToLockstepMode(
+  char *string)
+{
+  return McStringConvertToLockstepMode(string);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Allocate an earlytermination struct and initialize with arguments]
+
+  SideEffects []
+******************************************************************************/
+Mc_EarlyTermination_t *
+Mc_EarlyTerminationAlloc(
+  Mc_EarlyTerminationType mode,
+  mdd_t *states)
+{
+  Mc_EarlyTermination_t *result = ALLOC(Mc_EarlyTermination_t, 1);
+
+  result->mode   = mode;
+  if (states != NIL(mdd_t)) {
+    result->states = mdd_dup(states);
+  } else {
+    result->states = NIL(mdd_t);
+  }
+
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Free an earlytermination struct (you are allowed to pass
+  MC_NO_EARLY_TERMINATION, or NULL, and it will have no effect. ]
+
+  SideEffects []
+******************************************************************************/
+void
+Mc_EarlyTerminationFree(Mc_EarlyTermination_t *earlyTermination)
+{
+  if(earlyTermination == NIL(Mc_EarlyTermination_t) ||
+     earlyTermination == MC_NO_EARLY_TERMINATION)
+    return;
+
+  if(earlyTermination->states != NIL(mdd_t))
+    mdd_free(earlyTermination->states);
+
+  free(earlyTermination);
+
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return TRUE iff the early termination condition specifies that
+  the computation can be entirely skipped.]
+
+  SideEffects [none]
+******************************************************************************/
+boolean
+Mc_EarlyTerminationIsSkip(Mc_EarlyTermination_t *earlyTermination)
+{
+  if (earlyTermination == NIL(Mc_EarlyTermination_t) ||
+     earlyTermination == MC_NO_EARLY_TERMINATION)
+    return FALSE;
+
+  return (earlyTermination->mode == McCare_c &&
+	  earlyTermination->states == NIL(mdd_t));
+
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Make a path from aState to bState using fwd reachability.]
+
+  Description [Make a path from aState to bState which only passes through
+  invariantStates; it is assumed that aState and bState lie in invariantStates.
+  Returns a sequence of states starting from aState, leading to bState. If
+  aState == bState, a non trivial path is returned (ie a cycle). If no
+  path exists, return NIL. It is the users responsibility to free the returned
+  array as well as its members. This function starts from aState and does
+  forward reachability till it hits bState or a fixed point.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+McCompletePathFwd(
+  mdd_t *aState,
+  mdd_t *bState,
+  mdd_t *invariantStates,
+  Fsm_Fsm_t *modelFsm,
+  array_t *careSetArray,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel)
+{
+  mdd_t *tmp1Mdd;
+  array_t *result;
+  mdd_manager *mddMgr = Fsm_FsmReadMddManager( modelFsm );
+  mdd_t *zeroMdd = mdd_zero( mddMgr );
+  array_t *onionRings = array_alloc( mdd_t *, 0 );
+  Img_ImageInfo_t * imageInfo = Fsm_FsmReadOrCreateImageInfo(modelFsm, 0, 1);
+  mdd_t *c0, *c1;
+
+  assert( mdd_lequal( aState, invariantStates, 1, 1 ) );
+  assert( mdd_lequal( bState, invariantStates, 1, 1 ) );
+
+  if ( mdd_equal( aState, bState ) ) {
+
+    /*
+     * Alter the starting point to force routine to produce cycle if exists
+     * Question: would it be quicker to do simultaneous backward/forward
+     * analysis?
+     */
+
+    c0 = mdd_dup( aState );
+    array_insert_last( mdd_t *, onionRings, c0 );
+
+    tmp1Mdd = Img_ImageInfoComputeImageWithDomainVars(imageInfo,
+		aState, aState, careSetArray);
+    c1 = mdd_and( tmp1Mdd, invariantStates, 1, 1 );
+    mdd_free(tmp1Mdd);
+    array_insert_last( mdd_t *, onionRings, c1 );
+  }
+  else {
+    c0 = zeroMdd;
+    c1 = mdd_dup( aState );
+    array_insert_last( mdd_t *, onionRings, c1 );
+  }
+
+  while (!mdd_equal_mod_care_set_array(c0, c1, careSetArray)) {
+
+    mdd_t *tmp2Mdd;
+
+    if ( McStateTestMembership( bState, c1 ) ) {
+      break;
+    }
+
+    /*
+     *  performance gain from using dc's in this fp computation.
+     *  use only when dclevel >= max
+     */
+    if ( dcLevel >= McDcLevelRchFrontier_c ) {
+      mdd_t *annulusMdd = mdd_and(  c0, c1, 0, 1 );
+      mdd_t *discMdd = mdd_dup( c1 );
+      mdd_t *dcMdd = bdd_between( annulusMdd, discMdd );
+
+      tmp2Mdd = Img_ImageInfoComputeImageWithDomainVars(imageInfo,
+			annulusMdd, discMdd, careSetArray);
+
+      if ( verbosity > McVerbosityNone_c ) {
+	fprintf(vis_stdout,
+		"--Fwd completion: |low| = %d\t|upper| = %d\t|between|=%d\n",
+		mdd_size(annulusMdd), mdd_size(discMdd), mdd_size(dcMdd));
+      }
+
+      mdd_free( annulusMdd );
+      mdd_free( discMdd );
+      mdd_free( dcMdd );
+    }
+    else {
+      tmp2Mdd = Img_ImageInfoComputeImageWithDomainVars(imageInfo, c1, c1,
+							careSetArray);
+    }
+
+    tmp1Mdd = mdd_and( tmp2Mdd, invariantStates, 1, 1);
+    mdd_free(tmp2Mdd);
+
+    c0 = c1;
+    c1 = mdd_or( c1, tmp1Mdd, 1, 1 );
+    mdd_free( tmp1Mdd );
+
+    array_insert_last( mdd_t *, onionRings, c1 );
+  }
+
+  if ( McStateTestMembership( bState, c1 ) )  {
+    result = Mc_BuildPathFromCore(bState, onionRings, modelFsm,
+				  McGreaterZero_c );
+  }
+  else {
+    result = NIL(array_t);
+  }
+
+  mdd_free( zeroMdd );
+  mdd_array_free( onionRings);
+
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Make a path from aState to bState using bwd reachability.]
+
+  Description [Make a path from aState to bState which only passes through
+  invariantStates; it is assumed that aState and bState lie in invariantStates.
+  Returns a sequence of states starting from aState, leading to bState. If
+  aState == bState, a non trivial path is returned (ie a cycle). If no
+  path exists, return NIL. It is the users responsibility to free the returned
+  array as well as its members. This function starts from bState and does
+  backward reachability till it hits aState or a fixed point.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+McCompletePathBwd(
+  mdd_t *aState,
+  mdd_t *bState,
+  mdd_t *invariantStates,
+  Fsm_Fsm_t *modelFsm,
+  array_t *careSetArray,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel)
+{
+  mdd_t *tmp1Mdd;
+  array_t *result;
+  mdd_manager *mddMgr = Fsm_FsmReadMddManager( modelFsm );
+  mdd_t *zeroMdd = mdd_zero( mddMgr );
+  array_t *onionRings = array_alloc( mdd_t *, 0 );
+  Img_ImageInfo_t * imageInfo = Fsm_FsmReadOrCreateImageInfo(modelFsm, 1, 0);
+  mdd_t *c0, *c1;
+
+
+  assert( mdd_lequal( aState, invariantStates, 1, 1 ) );
+  assert( mdd_lequal( bState, invariantStates, 1, 1 ) );
+
+  if ( mdd_equal( aState, bState ) ) {
+
+    /*
+     * Alter the starting point to force routine to produce cycle if exists
+     * Question: would it be quicker to do simultaneous backward/forward
+     * analysis?
+     */
+
+    c0 = mdd_dup( bState );
+    array_insert_last( mdd_t *, onionRings, c0 );
+
+    tmp1Mdd = Img_ImageInfoComputePreImageWithDomainVars(imageInfo, bState,
+							 bState, careSetArray);
+    c1 = mdd_and( tmp1Mdd, invariantStates, 1, 1 );
+    mdd_free(tmp1Mdd);
+    array_insert_last( mdd_t *, onionRings, c1 );
+  }
+  else {
+    c0 = zeroMdd;
+    c1 = mdd_dup( bState );
+    array_insert_last( mdd_t *, onionRings, c1 );
+  }
+
+  while (!mdd_equal_mod_care_set_array(c0, c1, careSetArray)) {
+
+    mdd_t *tmp2Mdd;
+
+    if ( McStateTestMembership( aState, c1 ) ) {
+      break;
+    }
+
+    /*
+     *  performance gain from using dc's in this fp computation.
+     *  use only when dclevel >= max
+     */
+    if ( dcLevel >= McDcLevelRchFrontier_c ) {
+      mdd_t *annulusMdd = mdd_and(  c0, c1, 0, 1 );
+      mdd_t *discMdd = mdd_dup( c1 );
+      mdd_t *dcMdd = bdd_between( annulusMdd, discMdd );
+
+      tmp2Mdd = Img_ImageInfoComputePreImageWithDomainVars(imageInfo,
+			annulusMdd, discMdd, careSetArray);
+
+      if ( verbosity > McVerbosityNone_c ) {
+	fprintf(vis_stdout,
+		"--Bwd completion: |low| = %d\t|upper| = %d\t|between|=%d\n",
+		mdd_size(annulusMdd), mdd_size(discMdd), mdd_size(dcMdd));
+      }
+
+      mdd_free( annulusMdd );
+      mdd_free( discMdd );
+      mdd_free( dcMdd );
+    }
+    else {
+      tmp2Mdd = Img_ImageInfoComputePreImageWithDomainVars(imageInfo, c1, c1,
+							   careSetArray);
+    }
+
+    tmp1Mdd = mdd_and( tmp2Mdd, invariantStates, 1, 1);
+    mdd_free(tmp2Mdd);
+
+    c0 = c1;
+    c1 = mdd_or( c1, tmp1Mdd, 1, 1 );
+    mdd_free( tmp1Mdd );
+
+    array_insert_last( mdd_t *, onionRings, c1 );
+  }
+
+  if ( McStateTestMembership( aState, c1 ) )  {
+    result = Mc_BuildPathToCore(aState, onionRings, modelFsm, McGreaterZero_c);
+  }
+  else {
+    result = NIL(array_t);
+  }
+
+  mdd_free( zeroMdd );
+  mdd_array_free( onionRings);
+
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Write resettability condition as a CTL formula]
+
+  CommandName      [_init_state_formula]
+
+  CommandSynopsis [write resettability condition as a CTL formula]
+
+  CommandArguments [ \[-h\] \[&lt;init_file&gt;\] ]
+
+  CommandDescription [Write resettability condition as a CTL formula. Writes to
+  <code>init_file</code> is specified, else stdout.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+McCommandInitState(
+  Hrc_Manager_t **hmgr,
+  int argc,
+  char **argv)
+{
+  mdd_t *modelInitialStates;
+  mdd_t *anInitialState;
+  Fsm_Fsm_t *modelFsm;
+  char *formulaTxt;
+  array_t *stateVars;
+  FILE *ctlFile;
+
+  if ( argc == 1 ) {
+    ctlFile = vis_stdout;
+  }
+  else {
+    if ( !strcmp( "-h", argv[1] ) || ( argc > 2 ) ) {
+      fprintf( vis_stdout, "Usage: _init_state_formula [-h] init_file\n\tinit_file - file to write init state formula to (default is stdout)\n");
+      return 1;
+    }
+    ctlFile = Cmd_FileOpen( argv[1], "w", NIL(char *), 0 );
+  }
+
+  modelFsm = Fsm_HrcManagerReadCurrentFsm(*hmgr);
+  if (modelFsm == NIL(Fsm_Fsm_t)) {
+    if ( argc != 1 ) {
+      fclose( ctlFile );
+    }
+    return 1;
+  }
+  stateVars = Fsm_FsmReadPresentStateVars( modelFsm );
+
+  modelInitialStates = Fsm_FsmComputeInitialStates( modelFsm );
+  if ( modelInitialStates == NIL(mdd_t) ) {
+    (void) fprintf( vis_stdout, "** mc error: - cant build init states (mutual latch dependancy?)\n%s\n",
+		    error_string() );
+    if ( argc != 1 ) {
+      fclose( ctlFile );
+    }
+    return 1;
+  }
+  anInitialState = Mc_ComputeAState( modelInitialStates, modelFsm );
+  mdd_free(modelInitialStates);
+
+  formulaTxt = McStatePrintAsFormula( anInitialState, stateVars, modelFsm );
+  mdd_free(anInitialState);
+
+  fprintf( ctlFile, "AG EF %s;\n", formulaTxt );
+  FREE(formulaTxt);
+
+  if ( argc != 1 ) {
+    fclose(ctlFile);
+  }
+
+  return 0;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis [Return a CTL formula for a minterm.]
+
+  SideEffects []
+
+******************************************************************************/
+char *
+McStatePrintAsFormula(
+  mdd_t *aMinterm,
+  array_t *aSupport,
+  Fsm_Fsm_t *modelFsm)
+{
+  int i;
+  char *tmp1String;
+  char *tmp2String;
+  char *tmp3String;
+  char bodyString[McMaxStringLength_c];
+  char *mintermString = NIL(char);
+  mdd_manager *mddMgr = Ntk_NetworkReadMddManager( Fsm_FsmReadNetwork( modelFsm ) );
+  Ntk_Network_t *aNetwork = Fsm_FsmReadNetwork( modelFsm );
+  array_t *valueArray = McConvertMintermToValueArray( aMinterm, aSupport, mddMgr );
+  array_t *stringArray = array_alloc( char *, 0 );
+
+  for ( i = 0 ; i < array_n( aSupport ); i++ ) {
+
+    int mddId = array_fetch( int, aSupport, i );
+    int value = array_fetch( int, valueArray, i );
+    Ntk_Node_t *node = Ntk_NetworkFindNodeByMddId( aNetwork, mddId );
+    char *nodeName = Ntk_NodeReadName( node );
+    Var_Variable_t *nodeVar = Ntk_NodeReadVariable( node );
+
+    if ( Var_VariableTestIsSymbolic( nodeVar ) ) {
+      char *symbolicValue = Var_VariableReadSymbolicValueFromIndex( nodeVar, value );
+      sprintf( bodyString, "%s=%s", nodeName, symbolicValue );
+    }
+    else {
+      sprintf( bodyString, "%s=%d", nodeName, value );
+    }
+    tmp1String = util_strsav( bodyString );
+    array_insert_last( char *, stringArray, tmp1String );
+  }
+  array_free(valueArray);
+
+  array_sort( stringArray, cmp);
+
+  for ( i = 0 ; i < array_n( stringArray ); i++ ) {
+    tmp1String = array_fetch( char *, stringArray, i );
+    if( i == 0 )  {
+      mintermString = util_strcat3("(", tmp1String, ")" );
+    }
+    else {
+      tmp2String = util_strcat3( mintermString, " * (", tmp1String );
+      FREE(mintermString);
+      tmp3String = util_strcat3( tmp2String, ")", "" );
+      FREE(tmp2String);
+      mintermString = tmp3String;
+    }
+    FREE(tmp1String);
+  }
+  array_free( stringArray );
+
+  tmp1String = util_strcat3( "( ", mintermString, " )" );
+  FREE(mintermString);
+  mintermString = tmp1String;
+
+  return mintermString;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Search the given array of "Onion Rings" for the Onion Rings
+  with the clore closest to specified state.]
+
+  Description [Search the given array of "Onion Rings" for the Onion Rings with
+  the core closest to specified state. By "Onion Rings" we refer to an array of
+  sets of states (so arrayOfOnionRings is an array of arrays of states).  The
+  first member of a set of onion rings is referred to as the "core". The "Onion
+  Rings" array has the property that the first set is all states that can reach
+  the core (this may be mod a care set like the reached states).  The succesive
+  sets are those which can reach the core in successively fewer iterations.
+
+  We find the i with the smallest index j for which arrayOfOnionRings[i][j]
+  contains aState.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+McComputeOnionRingsWithClosestCore(
+  mdd_t *aState,
+  array_t *arrayOfOnionRings,
+  Fsm_Fsm_t *modelFsm)
+{
+  int index;
+  int distance = 0;
+
+  while( TRUE ) {
+    for( index = 0 ; index < array_n( arrayOfOnionRings ) ; index++ ) {
+      array_t *iOnionRings = array_fetch( array_t *, arrayOfOnionRings, index );
+
+      /* will crash if run out of rings -> if not in there */
+      mdd_t *stateSet = array_fetch( mdd_t *, iOnionRings, distance );
+
+      if ( McStateTestMembership( aState, stateSet ) )
+	return index;
+    }
+    distance++;
+  }
+  assert(0);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis [Remove array indexed by index from array of arrays.]
+
+  Description [Remove array indexed by index from array of arrays. Does NOT
+  free the input arrayOfOnionRings.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+McRemoveIndexedOnionRings(
+  int index,
+  array_t *arrayOfOnionRings)
+{
+  int i;
+  array_t *dupArrayOfOnionRings = array_alloc( array_t *, 0 );
+  array_t *OnionRings;
+
+  for ( i = 0 ; i < array_n( arrayOfOnionRings ) ; i++ ) {
+    if ( i == index ) {
+      continue;
+    }
+    OnionRings = array_fetch( array_t *, arrayOfOnionRings, i );
+    array_insert_last( array_t *, dupArrayOfOnionRings, OnionRings );
+  }
+
+  return dupArrayOfOnionRings;
+}
+
+
+
+
+
+
+
+/**Function********************************************************************
+
+  Synopsis [Convert a minterm to an array of integers]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+McConvertMintermToValueArray(
+  mdd_t *aMinterm,
+  array_t *aSupport,
+  mdd_manager *mddMgr)
+{
+  array_t *resultValueArray;
+
+  /* this will be performed only in v0s-g executables */
+  assert( MintermCheckWellFormed( aMinterm, aSupport, mddMgr ));
+
+  resultValueArray = array_alloc( int, 0 );
+  {
+    int i;
+    for( i = 0 ; i < array_n( aSupport ); i++ ) {
+      int aSupportVar = array_fetch( int, aSupport, i );
+      int j;
+      for( j = 0 ; TRUE ; j++) {
+
+	mdd_t *faceMdd, *tmpMdd;
+	array_t *tmpArray = array_alloc( int, 0 );
+
+	array_insert_last( int, tmpArray, j );
+	faceMdd = mdd_literal( mddMgr, aSupportVar, tmpArray );
+	array_free( tmpArray );
+
+	tmpMdd = mdd_and( faceMdd, aMinterm, 1, 1 );
+	mdd_free( faceMdd );
+	if ( !mdd_is_tautology( tmpMdd, 0 ) ) {
+	  mdd_free( tmpMdd );
+	  array_insert_last( int, resultValueArray, j );
+	  break;
+	}
+	mdd_free( tmpMdd );
+      }
+    }
+  }
+
+  return resultValueArray;
+}
+
+
+
+
+
+/**Function********************************************************************
+
+  Synopsis [Print a transition to vis_stdout.]
+
+  Description [Print a transition to vis_stdout. The transition is supposed to be
+  from aState to bState on input vInput. If uInput is not NIL, instead of
+  printing vInput, we only print the places where it differs from uInput. If there
+  is no difference anywhere, we print "-Unchanged-". Similarly, we print only the
+  incremental difference from aState to bState; if there is none, we print "-Unchanged-".
+  If aState is NIL we simply print bState and return.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McPrintTransitionAiger(
+  mdd_t *aState,
+  mdd_t *bState,
+  mdd_t *uInput,
+  mdd_t *vInput,
+  array_t *stateSupport,
+  array_t *inputSupport,
+  boolean printInputs,
+  Fsm_Fsm_t *modelFsm,
+  int seqNumber)
+{
+  Ntk_Network_t *modelNetwork = Fsm_FsmReadNetwork( modelFsm );
+  char *aString = aState ? Mc_MintermToStringAiger( aState, stateSupport, modelNetwork ) : NIL(char);
+  char *bString = Mc_MintermToStringAiger( bState, stateSupport, modelNetwork );
+  char *inpString = aState ? Mc_MintermToStringAigerInput( aState, stateSupport, modelNetwork ) : NIL(char);
+
+  st_table   *node2MvfAigTable;
+
+  node2MvfAigTable =
+	(st_table *)Ntk_NetworkReadApplInfo(modelNetwork, MVFAIG_NETWORK_APPL_KEY);
+
+  if ( aState == NIL(mdd_t) ) {
+    FREE(bString);
+    return;
+  }
+
+  fprintf(vis_stdout, "%s", aString);
+  fprintf(vis_stdout, "%s", inpString);
+
+
+   /* first test that there are inputs */
+  /* if ( array_n( inputSupport ) > 0 ) {
+    if ( uInput == NIL(mdd_t) ) {
+      char *vString = Mc_MintermToStringAiger( vInput, inputSupport, modelNetwork );
+      FREE(vString);
+    }
+    else {
+      boolean unchanged=TRUE;
+      char *uString = Mc_MintermToStringAiger( uInput, inputSupport, modelNetwork );
+      char *vString = Mc_MintermToStringAiger( vInput, inputSupport, modelNetwork );
+      FREE(uString);
+      FREE(vString);
+    }
+  } */
+
+  if(seqNumber == 1)
+  {
+    fprintf(vis_stdout, "1 ");
+  }
+  else
+  {
+    fprintf(vis_stdout, "0 ");
+  }
+
+
+  fprintf(vis_stdout, "%s", bString);
+
+  FREE( aString );
+  FREE( bString );
+  fprintf (vis_stdout, "\n");
+  return;
+}
+
+
+
+
+/**Function********************************************************************
+
+  Synopsis [Print a transition to vis_stdout.]
+
+  Description [Print a transition to vis_stdout. The transition is supposed to be
+  from aState to bState on input vInput. If uInput is not NIL, instead of
+  printing vInput, we only print the places where it differs from uInput. If there
+  is no difference anywhere, we print "-Unchanged-". Similarly, we print only the
+  incremental difference from aState to bState; if there is none, we print "-Unchanged-".
+  If aState is NIL we simply print bState and return.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McPrintTransition(
+  mdd_t *aState,
+  mdd_t *bState,
+  mdd_t *uInput,
+  mdd_t *vInput,
+  array_t *stateSupport,
+  array_t *inputSupport,
+  boolean printInputs,
+  Fsm_Fsm_t *modelFsm,
+  int seqNumber)
+{
+  Ntk_Network_t *modelNetwork = Fsm_FsmReadNetwork( modelFsm );
+  char *aString = aState ? Mc_MintermToString( aState, stateSupport, modelNetwork ) : NIL(char);
+  char *bString = Mc_MintermToString( bState, stateSupport, modelNetwork );
+
+  char *tmp1String = aString;
+  char *tmp2String = bString;
+  char *ptr1;
+  char *ptr2;
+  st_table   *node2MvfAigTable;
+
+  node2MvfAigTable =
+	(st_table *)Ntk_NetworkReadApplInfo(modelNetwork, MVFAIG_NETWORK_APPL_KEY);
+
+  if ( aState == NIL(mdd_t) ) {
+    fprintf( vis_stdout, "--State %d:\n%s\n", seqNumber, bString );
+    FREE(bString);
+    return;
+  }
+
+  fprintf(vis_stdout, "--Goes to state %d:\n", seqNumber );
+
+  {
+    boolean unchanged=TRUE;
+    while ( (tmp1String != NIL(char)) && ((ptr1 = strchr( tmp1String, '\n' ) ) != NIL(char) ) ) {
+      ptr2 = strchr( tmp2String, '\n' );
+      *ptr1 = 0;
+      *ptr2 = 0;
+      if ( (strcmp( tmp1String, tmp2String ) ) ) {
+	fprintf( vis_stdout, "%s\n", tmp2String );
+	unchanged = FALSE;
+      }
+      tmp1String = & (ptr1[1]);
+      tmp2String = & (ptr2[1]);
+    }
+    if (unchanged == TRUE) {
+      fprintf( vis_stdout, "<Unchanged>\n");
+    }
+  }
+
+
+  if ( printInputs == TRUE ) {
+    /* first test that there are inputs */
+    if ( array_n( inputSupport ) > 0 ) {
+      fprintf(vis_stdout, "--On input:\n");
+      if ( uInput == NIL(mdd_t) ) {
+	char *vString = Mc_MintermToString( vInput, inputSupport, modelNetwork );
+	fprintf(vis_stdout, "%s", vString );
+	FREE(vString);
+      }
+      else {
+	boolean unchanged=TRUE;
+	char *uString = Mc_MintermToString( uInput, inputSupport, modelNetwork );
+	char *vString = Mc_MintermToString( vInput, inputSupport, modelNetwork );
+	tmp1String = uString;
+	tmp2String = vString;
+	while ( (tmp1String != NIL(char)) && ((ptr1 = strchr( tmp1String, '\n' ) ) != NIL(char) ) ) {
+	  ptr2 = strchr( tmp2String, '\n' );
+	  *ptr1 = 0;
+	  *ptr2 = 0;
+	  if ( (strcmp( tmp1String, tmp2String ) ) ) {
+	    fprintf( vis_stdout, "%s\n", tmp2String );
+	    unchanged = FALSE;
+	  }
+	  tmp1String = & (ptr1[1]);
+	  tmp2String = & (ptr2[1]);
+	}
+	if (unchanged == TRUE) {
+	  fprintf( vis_stdout, "<Unchanged>\n");
+	}
+	FREE(uString);
+	FREE(vString);
+      }
+    }
+  }
+
+  FREE( aString );
+  FREE( bString );
+  fprintf (vis_stdout, "\n");
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Print message saying given state passes formula.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McStatePassesFormula(
+  mdd_t *aState,
+  Ctlp_Formula_t *formula,
+  McDbgLevel debugLevel,
+ Fsm_Fsm_t *modelFsm)
+{
+  McStatePassesOrFailsFormula( aState, formula, 1, debugLevel,  modelFsm );
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Print message saying given state fails formula.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McStateFailsFormula(
+  mdd_t *aState,
+  Ctlp_Formula_t *formula,
+  McDbgLevel debugLevel,
+  Fsm_Fsm_t *modelFsm)
+{
+  McStatePassesOrFailsFormula( aState, formula, 0,  debugLevel, modelFsm );
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Utility function - prints state passes or fails formula]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McStatePassesOrFailsFormula(
+  mdd_t *aState,
+  Ctlp_Formula_t *formula,
+  int pass,
+  McDbgLevel debugLevel,
+  Fsm_Fsm_t *modelFsm)
+{
+  array_t *PSVars = Fsm_FsmReadPresentStateVars( modelFsm );
+  char *formulaText = Ctlp_FormulaConvertToString( formula );
+  Ntk_Network_t *modelNetwork = Fsm_FsmReadNetwork( modelFsm );
+
+  /* Nodes created in converting formulae like AU may not have text
+   * attached to them. */
+  if (formulaText == NIL(char))
+    return;
+
+  fprintf( vis_stdout, "--State\n");
+  Mc_MintermPrint( aState, PSVars, modelNetwork );
+  if ( pass )
+    fprintf( vis_stdout, "passes ");
+  else
+    fprintf( vis_stdout, "fails ");
+
+  if( debugLevel > McDbgLevelMin_c)
+    fprintf(vis_stdout, "%s.\n\n", formulaText);
+  else
+    fprintf(vis_stdout, "\n\n");
+
+  FREE(formulaText);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis [Utility function - convert McPath_t to normal form.]
+
+  Description [Utility function - convert McPath_t to normal form.
+  A normal McPath_t is one where the stem leads to a state, which then returns
+  it self in the cycle.]
+
+  SideEffects []
+
+******************************************************************************/
+
+McPath_t *
+McPathNormalize(
+  McPath_t *aPath)
+{
+  int i, j;
+  int forced;
+
+  array_t *stemArray = McPathReadStemArray( aPath );
+  array_t *cycleArray = McPathReadCycleArray( aPath );
+
+  McPath_t *result = McPathAlloc();
+  array_t *newStem = array_alloc( mdd_t *, 0 );
+  array_t *newCycle = array_alloc( mdd_t *, 0 );
+
+  mdd_t *lastState = GET_NORMAL_PT(array_fetch_last(mdd_t *, cycleArray));
+
+  McPathSetStemArray( result, newStem );
+  McPathSetCycleArray( result, newCycle );
+
+  for( i = 0 ; i < array_n( stemArray ) ; i++ ) {
+    mdd_t *tmpState = array_fetch( mdd_t *, stemArray, i );
+    forced = 0;
+    if((long)tmpState % 2) {
+       forced = 1;
+       tmpState = (mdd_t *)((long)tmpState - 1);
+    }
+    array_insert_last(mdd_t *, newStem,
+	    (mdd_t *)((long)(mdd_dup(tmpState)) + forced) );
+
+    if ( mdd_equal( lastState, tmpState ) ) {
+      break;
+    }
+  }
+
+  for( j = i; j < array_n( stemArray ); j++ ) {
+    mdd_t *tmpState = array_fetch( mdd_t *, stemArray, j );
+    forced = 0;
+    if((long)tmpState % 2) {
+       forced = 1;
+       tmpState = (mdd_t *)((long)tmpState - 1);
+    }
+
+    array_insert_last(mdd_t *, newCycle,
+	    (mdd_t *)((long)(mdd_dup(tmpState)) + forced) );
+
+  }
+
+  /* first state of cycle array == last state of stem array => start from j=1 */
+  for( j = 1; j < array_n( cycleArray ); j++ ) {
+    mdd_t *tmpState = array_fetch( mdd_t *, cycleArray, j );
+    forced = 0;
+    if((long)tmpState % 2) {
+       forced = 1;
+       tmpState = (mdd_t *)((long)tmpState - 1);
+    }
+    array_insert_last(mdd_t *, newCycle,
+	    (mdd_t *)((long)(mdd_dup(tmpState)) + forced) );
+
+  }
+
+  return result;
+
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis [Utility function - merges two paths.]
+
+  Description [Utility function - merges two paths. Note that the merge is done
+  by adding the elements of the second array starting from the second element onwards.
+  This is because we often have to merge paths where the end point of the first is the
+  starting point of the second.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+McCreateMergedPath(
+  array_t *aPath,
+  array_t *bPath)
+{
+  int i, pos, forced;
+  mdd_t *tmpState, *endOfAPath;
+  array_t *aPathDup = McMddArrayDuplicateFAFW( aPath );
+  array_t *bPathDup = McMddArrayDuplicateFAFW( bPath );
+
+  for( i = 1 ; i < array_n( bPathDup ) ; i++ ) {
+    tmpState = array_fetch( mdd_t *, bPathDup, i );
+    array_insert_last( mdd_t *, aPathDup, tmpState );
+  }
+  pos = array_n(aPathDup) - array_n(bPathDup);
+  endOfAPath = array_fetch(mdd_t *, aPathDup, pos);
+
+  tmpState = array_fetch( mdd_t *, bPathDup, 0 );
+  forced = 0;
+  if((long)tmpState % 2) {
+    forced = 1;
+    tmpState = (mdd_t *)((long)tmpState - 1);
+  }
+  if(forced && mdd_equal(tmpState, endOfAPath)) {
+    array_insert(mdd_t *, aPathDup, pos, (mdd_t *)((long)endOfAPath + forced) );
+  }
+
+  mdd_free( tmpState );
+  array_free( bPathDup );
+
+  return aPathDup;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Utility function - duplicate bdd array.]
+
+  Description [To represent the forced segment, the mdd_t is complemented.
+	       Therefore one cannot use mdd_array_duplicate.
+	       This is function for FateAndFreeWill counterexample generation.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+McMddArrayDuplicateFAFW(array_t *mddArray)
+{
+  int   i, forced;
+  mdd_t *newTempMdd;
+  int      length = array_n(mddArray);
+  array_t *result = array_alloc(mdd_t *, length);
+
+  for (i = 0; i < length; i++) {
+    mdd_t *tempMdd = array_fetch(mdd_t *, mddArray, i);
+    forced = 0;
+    if((long)tempMdd % 2) {
+      forced = 1;
+      tempMdd = (mdd_t *)((long)tempMdd - 1);
+    }
+
+    newTempMdd = mdd_dup(tempMdd);
+    array_insert(mdd_t *, result, i, (mdd_t *)((long)newTempMdd + forced));
+  }
+
+  return (result);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Utility function - compute the intersection of the elements.]
+
+  Description [Utility function - compute the intersection of the elements.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+McMddArrayAnd(array_t *mddArray)
+{
+  mdd_t *result, *mdd1, *mdd2 = NIL(mdd_t);
+  int i;
+
+  result = NIL(mdd_t);
+  arrayForEachItem(mdd_t *, mddArray, i, mdd1) {
+    if (result == NIL(mdd_t))
+      result = mdd_dup(mdd1);
+    else {
+      mdd2 = result;
+      result = mdd_and(result, mdd1, 1, 1);
+      mdd_free(mdd2);
+    }
+  }
+
+  return (result);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Utility function - compute the union of the elements.]
+
+  Description [Utility function - compute the union of the elements.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+McMddArrayOr(array_t *mddArray)
+{
+  mdd_t *result, *mdd1, *mdd2 = NIL(mdd_t);
+  int i;
+
+  result = NIL(mdd_t);
+  arrayForEachItem(mdd_t *, mddArray, i, mdd1) {
+    if (result == NIL(mdd_t))
+      result = mdd_dup(mdd1);
+    else {
+      mdd2 = result;
+      result = mdd_or(result, mdd1, 1, 1);
+      mdd_free(mdd2);
+    }
+  }
+
+  return (result);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Utility function - joins two paths.]
+
+  Description [Utility function - joins two paths. Note that the joins is done
+  by adding the elements of the second array starting from the first element onwards.]
+
+  SeeAlso [McCreateMergedPath]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+McCreateJoinedPath(
+  array_t *aPath,
+  array_t *bPath)
+{
+  int i;
+  mdd_t *tmpState;
+  array_t *aPathDup = McMddArrayDuplicateFAFW( aPath );
+  array_t *bPathDup = McMddArrayDuplicateFAFW( bPath );
+
+  for( i = 0 ; i < array_n( bPathDup ) ; i++ ) {
+    tmpState = array_fetch( mdd_t *, bPathDup, i );
+    array_insert_last( mdd_t *, aPathDup, tmpState );
+  }
+  array_free( bPathDup );
+
+  return aPathDup;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [ Check to see if aState lies in set of states satisfying aFormula ]
+
+  SideEffects []
+
+******************************************************************************/
+boolean
+McStateSatisfiesFormula(
+  Ctlp_Formula_t *aFormula,
+  mdd_t *aState )
+{
+  mdd_t *passStates = Ctlp_FormulaObtainLatestApprox( aFormula );
+
+  if ( mdd_lequal( aState, passStates, 1, 1 ) ) {
+    mdd_free( passStates );
+    return TRUE;
+  }
+  else {
+    mdd_free( passStates );
+    return FALSE;
+  }
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis [ Tests aState is a member of setOfStates ]
+
+  SideEffects []
+
+******************************************************************************/
+boolean
+McStateTestMembership(
+  mdd_t *aState,
+  mdd_t *setOfStates )
+{
+  return mdd_lequal( aState, setOfStates, 1, 1 );
+}
+
+/**Function********************************************************************
+
+  Synopsis [Obtain a successor of aState which is in targetStates]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+McGetSuccessorInTarget(
+  mdd_t *aState,
+  mdd_t *targetStates,
+  Fsm_Fsm_t *modelFsm )
+{
+  mdd_t *tmpMdd, *succsInTarget, *result;
+  array_t *careSetArray = array_alloc(mdd_t *, 0);
+  Img_ImageInfo_t * imageInfo = Fsm_FsmReadOrCreateImageInfo(modelFsm, 0, 1);
+
+  array_insert_last(mdd_t *, careSetArray, targetStates);
+  tmpMdd = Img_ImageInfoComputeImageWithDomainVars(imageInfo, aState,
+						   aState, careSetArray);
+  array_free(careSetArray);
+  succsInTarget = mdd_and(tmpMdd, targetStates, 1, 1);
+#if 1
+  result = Mc_ComputeAState(succsInTarget, modelFsm);
+#else
+  result = Mc_ComputeACloseState(succsInTarget, aState, modelFsm);
+#endif
+
+  mdd_free( tmpMdd );
+  mdd_free( succsInTarget );
+
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Obtain a successor of aState which is in targetStates]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+McGetSuccessorInTargetAmongFairStates(
+  mdd_t *aState,
+  mdd_t *targetStates,
+  array_t *arrayOfOnionRings,
+  Fsm_Fsm_t *modelFsm )
+{
+  mdd_t *tmpMdd, *succsInTarget, *result;
+  mdd_t *fairStates, *newFairStates, *onionRing;
+  mdd_t *targetStatesInFairStates;
+  array_t *onionRings;
+  int i, j;
+  array_t *careSetArray = array_alloc(mdd_t *, 0);
+
+  Img_ImageInfo_t * imageInfo = Fsm_FsmReadOrCreateImageInfo(modelFsm, 0, 1);
+
+
+  fairStates = 0;
+  for(i=0; i<array_n(arrayOfOnionRings); i++) {
+    onionRings = array_fetch(array_t *, arrayOfOnionRings, i);
+    for(j=0; j<array_n(onionRings); j++) {
+      onionRing = array_fetch(mdd_t *,onionRings, j);
+
+      if(fairStates) {
+	newFairStates = mdd_or(fairStates, onionRing, 1, 1);
+	mdd_free(fairStates);
+	fairStates = newFairStates;
+      }
+      else {
+	fairStates = mdd_dup(onionRing);
+      }
+    }
+  }
+  targetStatesInFairStates = mdd_and(fairStates, targetStates, 1, 1);
+  mdd_free(fairStates);
+
+  array_insert_last(mdd_t *, careSetArray, targetStatesInFairStates);
+  tmpMdd = Img_ImageInfoComputeImageWithDomainVars(imageInfo, aState,
+						   aState, careSetArray);
+  succsInTarget = mdd_and(tmpMdd, targetStatesInFairStates, 1, 1);
+  mdd_array_free(careSetArray);
+  result = Mc_ComputeACloseState(succsInTarget, aState, modelFsm);
+
+  mdd_free( tmpMdd );
+  mdd_free( succsInTarget );
+
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Obtain stem of fair path]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+McPathReadStemArray(
+  McPath_t *aPath )
+{
+  return aPath->stemArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Obtain cycle of fair path]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+McPathReadCycleArray(
+  McPath_t *aPath )
+{
+  return aPath->cycleArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set stem of fair path]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McPathSetStemArray(
+  McPath_t *aPath,
+  array_t *stemArray)
+{
+  aPath->stemArray = stemArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set cycle of fair path]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McPathSetCycleArray(
+  McPath_t *aPath,
+  array_t *cycleArray )
+{
+  aPath->cycleArray = cycleArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Allocate a  Path Struct]
+
+  SideEffects []
+
+******************************************************************************/
+McPath_t *
+McPathAlloc(void)
+{
+  McPath_t *tmpPath = ( McPath_t * ) malloc( sizeof( McPath_t ) );
+
+  tmpPath->stemArray = NIL(array_t);
+  tmpPath->cycleArray = NIL(array_t);
+
+  return tmpPath;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Free a  Path Struct]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McNormalizeBddPointer(array_t *bddArray)
+{
+  int i;
+  bdd_t *p;
+
+  for(i=0; i<array_n(bddArray); i++) {
+    p = array_fetch(bdd_t *, bddArray, i);
+    if((long)p%2) p = (mdd_t *)( (long)p -1 );
+    array_insert(bdd_t *, bddArray, i, p);
+  }
+}
+
+void
+McPathFree(
+  McPath_t * aPath )
+{
+  if ( aPath->stemArray ) {
+    McNormalizeBddPointer(aPath->stemArray);
+    mdd_array_free( aPath->stemArray );
+  }
+
+  if ( aPath->cycleArray ) {
+    McNormalizeBddPointer(aPath->cycleArray);
+    mdd_array_free( aPath->cycleArray );
+  }
+
+  FREE( aPath );
+}
+
+/**Function********************************************************************
+
+  Synopsis [Allocate an McOptions_t struct.]
+
+  SideEffects []
+
+******************************************************************************/
+McOptions_t *
+McOptionsAlloc(void)
+{
+  McOptions_t *result = ALLOC(McOptions_t, 1);
+
+  memset(result, 0, sizeof(McOptions_t));
+
+  result->useMore = FALSE;
+  result->reduceFsm = FALSE;
+  result->printInputs = FALSE;
+  result->useFormulaTree = FALSE;
+  result->simFormat = FALSE;
+  result->ctlFile = NIL(FILE);
+  result->guideFile = NIL(FILE);
+  result->debugFile = NIL(FILE);
+  result->fwdBwd = McFwd_c;
+  result->dcLevel = McDcLevelNone_c;
+  result->dbgLevel = McDbgLevelMin_c;
+  result->schedule = McGSH_EL_c;
+  result->lockstep = MC_LOCKSTEP_OFF;
+  result->verbosityLevel = McVerbosityNone_c;
+  result->timeOutPeriod = 0;
+  result->ardcOptions = NIL(Fsm_ArdcOptions_t);
+  result->invarApproxFlag = Fsm_Rch_Default_c;
+  result->invarOnionRingsFlag = FALSE;
+  result->traversalDirection = McBwd_c;
+  result->doCoverageHoskote = FALSE;
+  result->doCoverageImproved = FALSE;
+  result->incre = TRUE;
+
+
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Free an McOptions_t struct.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsFree(
+  McOptions_t *options)
+{
+  if (options->debugFile != NIL(FILE)){
+    fclose(options->debugFile);
+  }
+  if (options->ardcOptions != NIL(Fsm_ArdcOptions_t)){
+    FREE(options->ardcOptions);
+  }
+  FREE(options);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Return Dbg level set at options.]
+
+  SideEffects []
+
+******************************************************************************/
+McDbgLevel
+McOptionsReadDbgLevel(
+  McOptions_t *options )
+{
+  return options->dbgLevel;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return filepointer for guide file (NULL if guided search
+  is disabled)]
+
+  SideEffects []
+
+******************************************************************************/
+FILE *
+McOptionsReadGuideFile(
+  McOptions_t *options )
+{
+  return options->guideFile;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return filepointer for system variables file for FAFW ]
+
+  SideEffects []
+
+******************************************************************************/
+FILE *
+McOptionsReadSystemFile(
+  McOptions_t *options )
+{
+  return options->systemFile;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return time out period set at options.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+McOptionsReadTimeOutPeriod(
+  McOptions_t *options )
+{
+  return options->timeOutPeriod;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return Verbosity level of options.]
+
+  SideEffects []
+
+******************************************************************************/
+Mc_VerbosityLevel
+McOptionsReadVerbosityLevel(
+  McOptions_t *options )
+{
+  return options->verbosityLevel;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return the language emptiness checking method of options.]
+
+  SideEffects []
+
+******************************************************************************/
+Mc_LeMethod_t
+McOptionsReadLeMethod(
+  McOptions_t *options )
+{
+  return options->leMethod;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return Dbg level of options.]
+
+  SideEffects []
+
+******************************************************************************/
+Mc_DcLevel
+McOptionsReadDcLevel(
+  McOptions_t *options )
+{
+  return options->dcLevel;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return ctl file set at options.]
+
+  SideEffects []
+
+******************************************************************************/
+FILE *
+McOptionsReadCtlFile(
+  McOptions_t *options )
+{
+  return options->ctlFile;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return debug file set at options.]
+
+  SideEffects []
+
+******************************************************************************/
+FILE *
+McOptionsReadDebugFile(
+  McOptions_t *options )
+{
+  return options->debugFile;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Read sim flag at options.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+McOptionsReadSimValue(
+  McOptions_t *options)
+{
+  return options->simFormat;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Read use more as pipe at options.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+McOptionsReadUseMore(
+  McOptions_t *options)
+{
+  return options->useMore;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Returns the value of Vacuity Detection option.]
+
+  SideEffects []
+
+******************************************************************************/
+boolean
+McOptionsReadVacuityDetect(
+  McOptions_t *options)
+{
+  return options->vd ;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Returns the value of the option for the Beer method.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+McOptionsReadBeerMethod(
+  McOptions_t *options)
+{
+  return options->beer ;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Read use CTL formula specific reduction.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+McOptionsReadReduceFsm(
+  McOptions_t *options)
+{
+  return options->reduceFsm;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Read print inputs in debug trace.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+McOptionsReadPrintInputs(
+  McOptions_t *options)
+{
+  return options->printInputs;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Read use of CTL formula tree.]
+
+  SideEffects []
+
+******************************************************************************/
+boolean
+McOptionsReadUseFormulaTree(
+  McOptions_t *options)
+{
+  return options->useFormulaTree;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Read schedule for GSH.]
+
+  SideEffects []
+
+******************************************************************************/
+Mc_GSHScheduleType
+McOptionsReadSchedule(
+  McOptions_t *options)
+{
+  return options->schedule;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Read lockstep option.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+McOptionsReadLockstep(
+  McOptions_t *options)
+{
+  return options->lockstep;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Read reachability analysis type for check_invariant]
+
+  SideEffects []
+
+******************************************************************************/
+Fsm_RchType_t
+McOptionsReadInvarApproxFlag(
+  McOptions_t *options)
+{
+  return (options->invarApproxFlag);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Read onion rings flag for check_invariant]
+
+  SideEffects []
+
+******************************************************************************/
+boolean
+McOptionsReadInvarOnionRingsFlag(
+  McOptions_t *options)
+{
+  return (options->invarOnionRingsFlag);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Read whether to use forward or backward analysis]
+
+  SideEffects []
+
+******************************************************************************/
+Mc_FwdBwdAnalysis
+McOptionsReadFwdBwd(
+  McOptions_t *options)
+{
+  return options->fwdBwd;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Read whether to use forward or backward traversal.]
+
+  SideEffects []
+
+******************************************************************************/
+Mc_FwdBwdAnalysis
+McOptionsReadTraversalDirection(
+  McOptions_t *options)
+{
+  return options->traversalDirection;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Read ARDC options.]
+
+  SideEffects []
+
+******************************************************************************/
+Fsm_ArdcOptions_t *
+McOptionsReadArdcOptions(
+  McOptions_t *options)
+{
+  return options->ardcOptions;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Read whether to do coverage computation using Hoskote et.al's algorithm]
+
+  SideEffects []
+
+******************************************************************************/
+int
+McOptionsReadCoverageHoskote(
+  McOptions_t *options)
+{
+  return options->doCoverageHoskote;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Read whether to do coverage computation using the improved algorithm]
+
+  SideEffects []
+
+******************************************************************************/
+int
+McOptionsReadCoverageImproved(
+  McOptions_t *options)
+{
+  return options->doCoverageImproved;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set use forward or backward analysis]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsSetFwdBwd(
+  McOptions_t *options,
+  Mc_FwdBwdAnalysis fwdBwd )
+{
+  options->fwdBwd = fwdBwd;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set guided search file (set to NULL if no guided search)]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsSetGuideFile(
+  McOptions_t *options,
+  FILE  *guideFile )
+{
+  options->guideFile = guideFile;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set varibles for system file for FAFW]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsSetVariablesForSystem(
+  McOptions_t *options,
+  FILE  *systemFile )
+{
+  options->systemFile = systemFile;
+}
+/**Function********************************************************************
+
+  Synopsis [Set use forward or backward traversal]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsSetTraversalDirection(
+  McOptions_t *options,
+  Mc_FwdBwdAnalysis fwdBwd )
+{
+  options->traversalDirection = fwdBwd;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set use more pipe flag at options.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsSetUseMore(
+  McOptions_t *options,
+  boolean useMore )
+{
+  options->useMore = useMore;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set reduce fsm flag]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsSetReduceFsm(
+  McOptions_t *options,
+  boolean reduceFsm )
+{
+  options->reduceFsm = reduceFsm;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set Vacuity Detect flag]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsSetVacuityDetect(
+  McOptions_t *options,
+  boolean vd )
+{
+  options->vd = vd;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set Beer Method for vacuity detection flag]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsSetBeerMethod(
+  McOptions_t *options,
+  boolean beer )
+{
+  options->beer = beer;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set flag for fate and free will algorithm]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsSetFAFWFlag(
+  McOptions_t *options,
+  boolean FAFWFlag )
+{
+  options->FAFWFlag = FAFWFlag;
+}
+/**Function********************************************************************
+
+  Synopsis [Set print inputs flag]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsSetPrintInputs(
+  McOptions_t *options,
+  boolean printInputs )
+{
+  options->printInputs = printInputs;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set use formula tree flag]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsSetUseFormulaTree(
+  McOptions_t *options,
+  boolean useFormulaTree )
+{
+  options->useFormulaTree = useFormulaTree;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set GSH schedule]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsSetSchedule(
+  McOptions_t *options,
+  Mc_GSHScheduleType schedule )
+{
+  options->schedule = schedule;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set lockstep option]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsSetLockstep(
+  McOptions_t *options,
+  int lockstep )
+{
+  options->lockstep = lockstep;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set sim flag at options.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsSetSimValue(
+  McOptions_t *options,
+  boolean simValue )
+{
+  options->simFormat = simValue;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set Dbg level at options.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsSetDbgLevel(
+  McOptions_t *options,
+  McDbgLevel dbgLevel )
+{
+  options->dbgLevel = dbgLevel;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set Verbosity at options.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsSetVerbosityLevel(
+  McOptions_t *options,
+  Mc_VerbosityLevel verbosityLevel )
+{
+  options->verbosityLevel = verbosityLevel;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set language emptiness checking method at options.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsSetLeMethod(
+  McOptions_t *options,
+  Mc_LeMethod_t leMethod)
+{
+  options->leMethod = leMethod;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set Dc level at options.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsSetDcLevel(
+  McOptions_t *options,
+  Mc_DcLevel dcLevel)
+{
+  options->dcLevel = dcLevel;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set ARDC options.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsSetArdcOptions(
+  McOptions_t *options,
+  Fsm_ArdcOptions_t *ardcOptions)
+{
+  options->ardcOptions = ardcOptions;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set a flag to store onion rings during invariant checking.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsSetInvarOnionRingsFlag(
+  McOptions_t *options, int shellFlag)
+{
+  if (shellFlag) options->invarOnionRingsFlag = TRUE;
+  else options->invarOnionRingsFlag = FALSE;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Set CTL File at options.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsSetCtlFile(
+  McOptions_t *options,
+  FILE *file)
+{
+  options->ctlFile = file;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set Debug File at options.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsSetDebugFile(
+  McOptions_t *options,
+  FILE *file)
+{
+  options->debugFile = file;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set ime out periopd at options.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsSetTimeOutPeriod(
+  McOptions_t *options,
+  int timeOutPeriod)
+{
+  options->timeOutPeriod = timeOutPeriod;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set reachability analysis type]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsSetInvarApproxFlag(
+  McOptions_t *options,
+  Fsm_RchType_t approxFlag)
+{
+  options->invarApproxFlag = approxFlag;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis [Set do Coverage-Hoskote flag]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsSetCoverageHoskote(
+  McOptions_t *options,
+  boolean doCoverageHoskote )
+{
+  options->doCoverageHoskote = doCoverageHoskote;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Set do Coverage-Improved flag]
+
+  SideEffects []
+
+******************************************************************************/
+void
+McOptionsSetCoverageImproved(
+  McOptions_t *options,
+  boolean doCoverageImproved )
+{
+  options->doCoverageImproved = doCoverageImproved;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Query user to continue.]
+
+  SideEffects []
+
+******************************************************************************/
+boolean
+McQueryContinue(char *query)
+{
+  char result[2];
+
+  fprintf(vis_stdout, "%s", query);
+  if (fgets(result, 2, stdin) == NULL) return FALSE;
+
+  if(!strcmp(result,"1"))
+    return TRUE;
+  else if(!strcmp(result,"0"))
+    return FALSE;
+  else {
+    fprintf(vis_stdout, "-- Must enter 0/1\n");
+    return McQueryContinue(query);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Print Support of Function]
+
+  SideEffects []
+
+******************************************************************************/
+
+void
+McPrintSupport(
+  mdd_t *aMdd,
+  mdd_manager *mddMgr,
+  Ntk_Network_t *aNetwork )
+{
+  int i;
+  char *tmp1String, *tmp2String;
+  char *mintermString = NIL(char);
+  char bodyString[McMaxStringLength_c];
+  array_t *aSupport = mdd_get_support( mddMgr, aMdd );
+  array_t *stringArray = array_alloc( char *, 0 );
+
+  for ( i = 0 ; i < array_n( aSupport ); i++ ) {
+
+    int mddId = array_fetch( int, aSupport, i );
+    Ntk_Node_t *node = Ntk_NetworkFindNodeByMddId( aNetwork, mddId );
+    char *nodeName = Ntk_NodeReadName( node );
+    sprintf( bodyString, "%s", nodeName );
+    tmp1String = util_strsav( bodyString );
+    array_insert_last( char *, stringArray, tmp1String );
+  }
+
+  array_sort( stringArray, cmp);
+
+  for ( i = 0 ; i < array_n( stringArray ); i++ ) {
+    tmp1String = array_fetch( char *, stringArray, i );
+    if( i == 0 )  {
+      mintermString = util_strcat3(tmp1String, "", "" );
+    }
+    else {
+      tmp2String = util_strcat3(mintermString, "\n", tmp1String );
+      FREE(mintermString);
+      mintermString = tmp2String;
+    }
+    FREE(tmp1String);
+  }
+  fprintf(vis_stdout, "%s\n", mintermString );
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis [Print path as sim trace]
+
+  SideEffects []
+
+******************************************************************************/
+
+
+
+int
+McPrintSimPath(
+  FILE *outputFile,
+  array_t *aPath,
+  Fsm_Fsm_t *modelFsm)
+{
+  int i;
+
+  array_t *inputVars = Fsm_FsmReadInputVars( modelFsm );
+  array_t *psVars = Fsm_FsmReadPresentStateVars( modelFsm );
+
+  Ntk_Network_t *network = Fsm_FsmReadNetwork( modelFsm );
+  mdd_manager *mddMgr =  Fsm_FsmReadMddManager( modelFsm );
+
+  array_t *inputSortedVars = SortMddIds( inputVars, network );
+  array_t *psSortedVars = SortMddIds( psVars, network );
+
+  fprintf(outputFile, "# UC Berkeley, VIS Release 1.3\n");
+  fprintf(outputFile, "# Network: %s\n", Ntk_NetworkReadName( network ) );
+  fprintf(outputFile, "# Simulation vectors have been generated to show language non-empty\n\n");
+
+  fprintf( outputFile, ".inputs " );
+  PrintNodes( inputSortedVars, network );
+  fprintf( outputFile, "\n" );
+
+  fprintf( outputFile, ".latches " );
+  PrintNodes( psSortedVars, network );
+  fprintf( outputFile, "\n" );
+
+  fprintf( outputFile, ".outputs\n" );
+
+  for( i = -1 ; i < (array_n( aPath ) - 1); i++ ) {
+
+    if ( i == -1 ) {
+      mdd_t *initState = array_fetch( mdd_t *, aPath, (i+1) );
+      array_t *initValues = McConvertMintermToValueArray( initState, psSortedVars, mddMgr );
+
+      fprintf( outputFile, ".initial ");
+      PrintDeck( initValues, psSortedVars, network );
+      array_free( initValues );
+
+      fprintf( outputFile, "\n" );
+      fprintf( outputFile, ".start_vectors\n");
+    }
+    else {
+      array_t *psValues;
+      array_t *nsValues;
+      array_t *inputValues;
+
+      mdd_t *psState = array_fetch( mdd_t *, aPath, i );
+      mdd_t *nsState = array_fetch( mdd_t *, aPath, (i+1) );
+      mdd_t *inputSet = Mc_FsmComputeDrivingInputMinterms( modelFsm, psState, nsState );
+      mdd_t *input = Mc_ComputeAMinterm( inputSet, inputVars, mddMgr );
+
+      inputValues = McConvertMintermToValueArray( input, inputSortedVars, mddMgr );
+      PrintDeck( inputValues, inputSortedVars, network );
+      array_free( inputValues );
+      fprintf( outputFile, " ;");
+
+      psValues = McConvertMintermToValueArray( psState, psSortedVars, mddMgr );
+      PrintDeck( psValues, psSortedVars, network );
+      array_free( psValues );
+      fprintf( outputFile, " ;");
+
+      nsValues = McConvertMintermToValueArray( nsState, psSortedVars, mddMgr );
+      PrintDeck( nsValues, psSortedVars, network );
+      array_free( nsValues );
+      fprintf( outputFile, " ;\n");
+
+      mdd_free( inputSet );
+      mdd_free( input );
+    }
+  }
+  array_free( psSortedVars );
+  array_free( inputSortedVars );
+
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Form an FSM reduced with respect to the specified formula]
+
+  Description [Form an FSM reduced with respect to the CTL formula array. All latches
+  and inputs which affect the given formula AND the fairness conditions of the
+  system are included in this reduced fsm.]
+
+  SideEffects []
+
+******************************************************************************/
+Fsm_Fsm_t *
+McConstructReducedFsm(
+  Ntk_Network_t *network,
+  array_t *ctlFormulaArray )
+{
+  int i;
+  Ntk_Node_t *node;
+  array_t *nodeArray;
+  st_table *formulaNodes;
+  Ctlp_Formula_t *fairnessCondition;
+  Ctlp_Formula_t *ctlFormula;
+  array_t *formulaCombNodes;
+  Fsm_Fsm_t *netFsm =  Fsm_NetworkReadFsm( network );
+  Fsm_Fsm_t *reducedFsm;
+  Fsm_Fairness_t *netFairness = Fsm_FsmReadFairnessConstraint( netFsm );
+  array_t *reducedFsmFairness = array_alloc( Ctlp_Formula_t *, 0 );
+
+  if (netFairness) {
+    if ( !Fsm_FairnessTestIsBuchi( netFairness ) ) {
+      (void) fprintf(vis_stderr, "** mc error: non Buchi fairness constraints not supported\n");
+      (void) fprintf(vis_stderr, "** mc error: ignoring fairness constraints\n");
+    }
+    else {
+      int j;
+      int numBuchi = Fsm_FairnessReadNumConjunctsOfDisjunct( netFairness, 0 );
+      for( j = 0 ; j < numBuchi; j++ ) {
+	Ctlp_Formula_t *tmpFormula = Fsm_FairnessReadFinallyInfFormula( netFairness, 0, j );
+	Ctlp_Formula_t *reducedFsmCondition = Ctlp_FormulaDup( tmpFormula );
+	array_insert_last( Ctlp_Formula_t *, reducedFsmFairness, reducedFsmCondition );
+      }
+    }
+  }
+
+  formulaNodes = st_init_table( st_ptrcmp, st_ptrhash );
+  arrayForEachItem( Ctlp_Formula_t *, ctlFormulaArray, i, ctlFormula ) {
+    NodeTableAddCtlFormulaNodes( network, ctlFormula, formulaNodes );
+  }
+
+  arrayForEachItem( Ctlp_Formula_t *, reducedFsmFairness, i, fairnessCondition ) {
+    NodeTableAddCtlFormulaNodes( network, fairnessCondition, formulaNodes );
+  }
+
+  {
+    st_generator *stGen;
+    nodeArray = array_alloc( Ntk_Node_t *, 0 );
+    st_foreach_item( formulaNodes, stGen, &node, NIL(char *) ) {
+      array_insert_last( Ntk_Node_t *, nodeArray, node );
+    }
+  }
+  st_free_table( formulaNodes );
+
+  formulaCombNodes  = Ntk_NodeComputeCombinationalSupport( network, nodeArray, FALSE );
+  array_free( nodeArray );
+  if(array_n(formulaCombNodes) == 0) {
+
+    /* Free the fairness constraint array (if any) */
+    for (i=0; i<array_n(reducedFsmFairness); i++){
+      Ctlp_Formula_t *formula = array_fetch(Ctlp_Formula_t*,
+					    reducedFsmFairness, i);
+      Ctlp_FormulaFree(formula);
+    }
+    array_free(reducedFsmFairness);
+    /* Free the formulaCombNodes */
+    array_free(formulaCombNodes);
+    /* We should return a NIL fsm */
+    return NIL(Fsm_Fsm_t);
+  }
+  {
+    graph_t *dupPart;
+    graph_t *origPart = Part_NetworkReadPartition( network );
+    array_t *reducedFsmLatches = array_alloc( Ntk_Node_t *, 0 );
+    array_t *reducedFsmInputs = array_alloc( Ntk_Node_t *, 0 );
+    int i;
+    arrayForEachItem( Ntk_Node_t *, formulaCombNodes, i, node ) {
+      if ( Ntk_NodeTestIsInput( node ) == TRUE ) {
+	array_insert_last( Ntk_Node_t *, reducedFsmInputs, node );
+      }
+      else {
+	assert( Ntk_NodeTestIsLatch( node ) == TRUE );
+	array_insert_last( Ntk_Node_t *, reducedFsmLatches, node );
+      }
+    }
+    if ((array_n(reducedFsmInputs) ==
+	 Ntk_NetworkReadNumInputs(network)) &&
+	(array_n(reducedFsmLatches) ==
+	 Ntk_NetworkReadNumLatches(network))){
+      /* We did not observe any reduction. Return a NIL fsm. */
+      /* After freeing appropriate stuff */
+
+      /* Free the fairness constraint array (if any) */
+      for (i=0; i<array_n(reducedFsmFairness); i++){
+	Ctlp_Formula_t *formula = array_fetch(Ctlp_Formula_t*,
+					      reducedFsmFairness, i);
+	Ctlp_FormulaFree(formula);
+      }
+      array_free(reducedFsmFairness);
+      array_free(formulaCombNodes);
+      array_free(reducedFsmLatches);
+      array_free(reducedFsmInputs);
+      return NIL(Fsm_Fsm_t);
+    }
+    dupPart = Part_PartitionDuplicate( origPart );
+    array_free( formulaCombNodes );
+    reducedFsm = Fsm_FsmCreateReducedFsm( network, dupPart, reducedFsmLatches,
+					  reducedFsmInputs, reducedFsmFairness );
+    array_free( reducedFsmLatches );
+    array_free( reducedFsmInputs );
+    array_free( reducedFsmFairness );
+  }
+
+  return reducedFsm;
+
+}
+
+/**Function********************************************************************
+
+  Synopsis [Update the early termination condition.]
+
+  Description [Update the early termination condition.
+
+  MC_NO_EARLY_TERMINATION is equivalent to mode=CARE and
+  states=mdd_one.  careStates=NIL is equivalent to either
+  careStates=mdd_zero (for disjunction) or careStates=mdd_one (in the
+  other cases).  With these provisions, the propagation algorithm can
+  be summarized thus.
+
+  <p> For negation, ALL becomes SOME and vice versa, while CARE is
+  passed unchanged.
+
+  <p> For conjunction, disjunction, and implication: if the current
+  node has a termination condition of type ALL or SOME, this is
+  refined and propagated.  Otherwise, the returned early termination
+  condition is of type CARE.  The care states are the conjunction of
+  earlyTermination->states and either careStates (for conjunction and
+  implication) or the complement of careStates (for disjunction).
+
+  <p> In some cases, one can immediately determine that the goal
+  cannot be reached, or has already been reached.  In these cases, the
+  termination condition has mode=CARE and states=mdd_zero.
+
+  <p> The other types of formulae produce no early termination
+  condition for their children.  That is, they declare that all states
+  are care states.]
+
+  SideEffects []
+
+******************************************************************************/
+Mc_EarlyTermination_t *
+McObtainUpdatedEarlyTerminationCondition(
+  Mc_EarlyTermination_t *earlyTermination,
+  mdd_t *careStates,
+  Ctlp_FormulaType formulaType)
+{
+  Mc_EarlyTermination_t *result;
+
+  switch (formulaType) {
+  case Ctlp_NOT_c:
+    if (earlyTermination == MC_NO_EARLY_TERMINATION)
+      return MC_NO_EARLY_TERMINATION;
+    result = Mc_EarlyTerminationAlloc(earlyTermination->mode,
+				      earlyTermination->states);
+    switch (result->mode) {
+    case McAll_c:
+      result->mode = McSome_c;
+      break;
+    case McSome_c:
+      result->mode = McAll_c;
+      break;
+    case McCare_c:
+      break;
+    default:
+      assert(0);
+    }
+    break;
+  case Ctlp_AND_c:
+    if (careStates == NIL(mdd_t)) {
+      if (earlyTermination == MC_NO_EARLY_TERMINATION) {
+	result = MC_NO_EARLY_TERMINATION;
+      } else if (earlyTermination->mode == McAll_c) {
+	result = Mc_EarlyTerminationAlloc(McAll_c, earlyTermination->states);
+      } else {
+	/* Here mode is CARE or SOME: inherit care states from parent. */
+	result = Mc_EarlyTerminationAlloc(McCare_c, earlyTermination->states);
+      }
+    } else {
+      /* There are care states from sibling. */
+      if (earlyTermination == MC_NO_EARLY_TERMINATION) {
+	/* No early termination from parent: just use sibling's care states. */
+	result = Mc_EarlyTerminationAlloc(McCare_c, careStates);
+      } else if (earlyTermination->mode == McAll_c) {
+	/* If some goal states are not in care set, we know we cannot achieve
+	 * the goal; otherwise, we just propagate the parent's condition.
+	 */
+	if (mdd_lequal(earlyTermination->states, careStates, 1, 1)) {
+	  result = Mc_EarlyTerminationAlloc(McAll_c, earlyTermination->states);
+	} else {
+	  result = Mc_EarlyTerminationAlloc(McCare_c, NIL(mdd_t)); /* failure */
+	}
+      } else if (earlyTermination->mode == McSome_c) {
+	/* If no goal states are in the care set, we have failed; otherwise
+	 * we refine the goal set to those states also in the care set.
+	 */
+	if (mdd_lequal(earlyTermination->states, careStates, 1, 0)) {
+	  result = Mc_EarlyTerminationAlloc(McCare_c, NIL(mdd_t)); /* failure */
+	} else {
+	  mdd_t *andMdd = mdd_and(earlyTermination->states, careStates, 1, 1);
+	  result = Mc_EarlyTerminationAlloc(McSome_c, andMdd);
+	  mdd_free(andMdd);
+	}
+      } else { /* if (earlyTermination->mode == McCare_c) */
+	/* Intersect care states from parent and sibling. */
+	mdd_t *andMdd = mdd_and(earlyTermination->states, careStates, 1, 1);
+	result = Mc_EarlyTerminationAlloc(McCare_c, andMdd);
+	mdd_free(andMdd);
+      }
+    }
+    break;
+  case Ctlp_THEN_c:
+  case Ctlp_OR_c:
+    if (careStates == NIL(mdd_t)) {
+      if (earlyTermination == MC_NO_EARLY_TERMINATION) {
+	result = MC_NO_EARLY_TERMINATION;
+      } else if (earlyTermination->mode == McSome_c) {
+	if (formulaType == Ctlp_OR_c) {
+	  result = Mc_EarlyTerminationAlloc(McSome_c,
+					    earlyTermination->states);
+	} else {
+	  result = Mc_EarlyTerminationAlloc(McAll_c,
+					    earlyTermination->states);
+	}
+      } else {
+	/* Here mode is CARE or ALL: inherit care states from parent. */
+	result = Mc_EarlyTerminationAlloc(McCare_c, earlyTermination->states);
+      }
+    } else {
+      /* There are care states from sibling.
+       * Since f->g is !f+g, we treat the THEN and OR cases together by
+       * complementing the care set in the latter case. */
+      mdd_t *mask = (formulaType == Ctlp_OR_c) ?
+	bdd_not(careStates) : bdd_dup(careStates);
+      if (earlyTermination == MC_NO_EARLY_TERMINATION) {
+	/* No early termination from parent: just use sibling's care states. */
+	result = Mc_EarlyTerminationAlloc(McCare_c, mask);
+      } else if (earlyTermination->mode == McAll_c) {
+	/* Remove the goal states already attained from the goal set. */
+	mdd_t *andMdd = mdd_and(earlyTermination->states, mask, 1, 1);
+	result = Mc_EarlyTerminationAlloc(McAll_c, andMdd);
+	mdd_free(andMdd);
+      } else if (earlyTermination->mode == McSome_c) {
+	/* If some goal states were already attained, declare success;
+	 * otherwise just propagate the parent's condition.
+	 */
+	if (mdd_lequal(earlyTermination->states, mask, 1, 1)) {
+	  result = Mc_EarlyTerminationAlloc(McSome_c,
+					    earlyTermination->states);
+	} else {
+	  result = Mc_EarlyTerminationAlloc(McCare_c, NIL(mdd_t)); /* success */
+	}
+      } else { /* if (earlyTermination->mode == McCare_c) */
+	/* Intersect care states from parent and sibling. */
+	mdd_t *andMdd = mdd_and(earlyTermination->states, mask, 1, 1);
+	result = Mc_EarlyTerminationAlloc(McCare_c, andMdd);
+	mdd_free(andMdd);
+      }
+      mdd_free(mask);
+    }
+    break;
+  default:
+    result = MC_NO_EARLY_TERMINATION;
+  }
+  return result;
+
+} /* McObtainUpdatedEarlyTerminationCondition */
+
+
+/**Function********************************************************************
+
+  Synopsis [Check if an underapproximation of the evaluation
+  guarantees that the early termination conditions hold.]
+
+  Description [Check if an underapproximation of the evaluation
+  guarantees that the early termination conditions hold , modulo a
+  care set modeled by an implicitly conjoined array of bdds.
+
+  If we are looking for ALL of ETstates, or we are are given a set of
+  CARE states, then we are done if ETstates \subseteq underapprox,
+  because that implies ETstates \subseteq exactset.
+
+  If we are looking for SOME of ETstates, we are done if underapprox and
+  ETstates overlap, because that means that the exact set and ETstates also
+  overlap.
+
+  If earlyTermination == MC_NO_EARLY_TERMINATION, the result of the
+  function is false.]
+
+  SideEffects []
+
+******************************************************************************/
+boolean
+McCheckEarlyTerminationForUnderapprox(
+  Mc_EarlyTermination_t *earlyTermination,
+  mdd_t *underApprox,
+  array_t *careStatesArray)
+{
+  if(earlyTermination == MC_NO_EARLY_TERMINATION)
+    return FALSE;
+
+  /* for an underapproximation and McAll_c (McSome_c), you just check
+     whether all states (some states) are already reached */
+  return(((earlyTermination->mode != McSome_c) &&
+	  (mdd_lequal_mod_care_set_array(earlyTermination->states, underApprox,
+					 1, 1, careStatesArray)))
+	 ||
+	 (
+	   (earlyTermination->mode == McSome_c) &&
+	   (!mdd_lequal_mod_care_set_array(underApprox,
+					   earlyTermination->states, 1,
+					   0, careStatesArray))));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Check if an overapproximation of the evaluation guarantees
+  that the early termination conditions hold.]
+
+  Description [Check if an overapproximation of the evaluation
+  guarantees that the early termination conditions hold, modulo a care
+  set modeled by an implicitly conjoined array of bdds.
+
+  If we are looking for ALL of ETstates, then we are done if we have
+  overapprox is not a superset of ETstates, because the exact set will
+  not hold all of ETstates.
+
+  If we are looking for SOME of ETstates, or we are given a set of
+  CARE states, we are done if overapprox is disjoint from ETstates,
+  because that means that the exact set is also disjoint from
+  ETstates.
+
+  If earlyTermination == MC_NO_EARLY_TERMINATION, the result of the
+  function is false.]
+
+  SideEffects []
+
+******************************************************************************/
+boolean
+McCheckEarlyTerminationForOverapprox(
+  Mc_EarlyTermination_t *earlyTermination,
+  mdd_t *overApprox,
+  array_t *careStatesArray)
+{
+  if(earlyTermination == MC_NO_EARLY_TERMINATION)
+    return FALSE;
+
+  /* For an overapproximation and McAll_c (McSome_c), you check
+     whether some state (all states) are already missing */
+  return(((earlyTermination->mode == McAll_c) &&
+	  (!mdd_lequal_mod_care_set_array(earlyTermination->states,
+					  overApprox, 1, 1, careStatesArray)))
+	 ||
+	 ((earlyTermination->mode != McAll_c) &&
+	  (mdd_lequal_mod_care_set_array(earlyTermination->states,
+					  overApprox, 1, 0,
+					  careStatesArray))));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Return an array of formulae representing the hints]
+
+  Description [Read the guide file and store the hint formulae in an
+  array. Adds the 1 hint to the end of the array.
+
+  Returns NIL if something goes wrong: parse error in the file or temporal
+  operators in the hints]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+Mc_ReadHints(
+  FILE *guideFP
+  )
+{
+  Ctlp_FormulaArray_t *invarArray;   /* formulae representing hints */
+  int i;                      /* to iterate over formulae        */
+  Ctlp_Formula_t *formula;    /* idem                            */
+
+  if (guideFP == NIL(FILE)){
+    fprintf(vis_stderr,
+	    "** mc error: can't read hint file.\n");
+    return NIL(array_t);
+  }
+
+  invarArray = Ctlp_FileParseFormulaArray( guideFP );
+
+  if (invarArray == NIL(array_t)){
+    fprintf(vis_stderr,
+	    "** mc error: parse error in hints file.\n");
+    return NIL(array_t);
+  }
+
+  if (array_n(invarArray) == 0){
+    fprintf(vis_stdout, "** mc error: File contained no hints.\n");
+    Ctlp_FormulaArrayFree(invarArray);
+    return NIL(array_t);
+  }
+
+
+  array_insert_last(Ctlp_Formula_t *, invarArray,
+		    Ctlp_FormulaCreate(Ctlp_TRUE_c, NIL(void), NIL(void)));
+
+  /* some checks */
+  arrayForEachItem(Ctlp_Formula_t *, invarArray, i, formula){
+    if(!Ctlp_FormulaTestIsQuantifierFree(formula)){
+      (void) fprintf(vis_stdout,
+		     "** mc error: Hints contain temporal operators\n");
+
+      Ctlp_FormulaArrayFree(invarArray);
+      return NIL(array_t);
+    } /* quantifier free */
+
+  }/* checks */
+
+
+  return invarArray;
+}/* Mc_ReadHints */
+
+/**Function********************************************************************
+
+  Synopsis [Return an array of variables controlled by system ]
+
+  Description [Read the system variables file and store the variables controlled by system in an array.
+
+  Returns NIL if something goes wrong: parse error in the file or variables that  are not contained in model.]
+
+  SideEffects []
+
+******************************************************************************/
+st_table *
+Mc_ReadSystemVariablesFAFW(
+  Fsm_Fsm_t *fsm,
+  FILE *systemFP
+  )
+{
+  st_table *variablesTable;
+  array_t *bddIdArray;
+  char line[1024], nodeName[1024], *next;
+  int mddId, bddId;
+  int i, j, len, index;
+  int errorFlag;
+  Ntk_Node_t *node;
+  Ntk_Network_t *network;
+  mdd_manager *mgr;
+
+  errorFlag = 0;
+  if (systemFP == NIL(FILE)){
+    fprintf(vis_stderr,
+	    "** mc error: can't read system file.\n");
+    return NIL(st_table);
+  }
+
+  network = Fsm_FsmReadNetwork(fsm);
+  mgr = Fsm_FsmReadMddManager(fsm);
+  variablesTable = st_init_table(st_numcmp, st_numhash);
+  while(fgets(line, 1024, systemFP)) {
+    len = strlen(line);
+    for(i=0; i<len; i++) {
+      if(line[i] == ' ')	continue;
+      if(line[i] == '\t')	continue;
+      break;
+    }
+    next = &(line[i]);
+    if(next[0] == '\n')	continue;
+    if(next[0] == '#')	continue;
+    len = strlen(next);
+    index = 0;
+    nodeName[0] = '\0';
+    for(i=0; i<len; i++) {
+      if(next[i] == ' ') break;
+      if(next[i] == '\t') break;
+      if(next[i] == '\n') break;
+      nodeName[index] = next[i];
+      index++;
+    }
+    nodeName[index] = '\0';
+    node = Ntk_NetworkFindNodeByName(network, nodeName);
+    if(node == NIL(Ntk_Node_t)) {
+      fprintf(vis_stderr, "Error : Can't find node '%s'\n", nodeName);
+      errorFlag = 1;
+      continue;
+    }
+    mddId = Ntk_NodeReadMddId(node);
+    bddIdArray = mdd_id_to_bdd_id_array(mgr, mddId);
+    for(j=0; j<array_n(bddIdArray); j++) {
+      bddId = array_fetch(int, bddIdArray, j);
+      st_insert(variablesTable, (char *)(long)bddId, (char *)(long)bddId);
+    }
+    array_free(bddIdArray);
+  }
+
+  if(variablesTable->num_entries == 0)  {
+    st_free_table(variablesTable);
+    variablesTable = 0;
+  }
+  if(errorFlag) {
+    if(variablesTable)
+      st_free_table(variablesTable);
+    variablesTable = 0;
+    return((st_table *)-1);
+  }
+  return variablesTable;
+}/* Mc_ReadSystemVariablesFAFW */
+
+
+/**Function********************************************************************
+
+  Synopsis []
+
+  Description []
+
+  SideEffects []
+
+******************************************************************************/
+st_table *
+Mc_SetAllInputToSystem(Fsm_Fsm_t *fsm)
+{
+  mdd_manager *mgr;
+  array_t *inputVars, *bddIdArray;
+  int i, j;
+  int mddId, bddId;
+  st_table *idTable;
+
+  idTable = st_init_table(st_numcmp, st_numhash);
+  mgr = Fsm_FsmReadMddManager(fsm);
+  /* inputVars = Fsm_FsmReadPrimaryInputVars(fsm); */
+  inputVars = Fsm_FsmReadInputVars(fsm);
+
+  if(inputVars) {
+    for(i=0; i<array_n(inputVars); i++) {
+      mddId = array_fetch(int, inputVars, i);
+      bddIdArray = mdd_id_to_bdd_id_array(mgr, mddId);
+      for(j=0; j<array_n(bddIdArray); j++) {
+	bddId = array_fetch(int, bddIdArray, j);
+	st_insert(idTable, (char *)(long)bddId, (char *)(long)bddId);
+      }
+    }
+  }
+  return(idTable);
+
+}
+
+/**Function********************************************************************
+
+  Synopsis [Return an array of states corresponding to the hints]
+
+  Description [Flushes the states associated with the hints,and reevaluates
+  them in the current fsm. Quantifies out variables in the hint that are not in
+  present state or primary input set of the current FSM.
+
+  Returns NIL if something goes wrong (the hint does not fit the fsm).]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+Mc_EvaluateHints(
+  Fsm_Fsm_t *fsm,
+  Ctlp_FormulaArray_t *invarArray
+  )
+{
+  array_t *invarStatesArray = NIL(array_t);/* array of sets of states: hints*/
+  int i, j;                                       /* to iterate over formulae  */
+  Ctlp_Formula_t *formula= NIL(Ctlp_Formula_t);/* idem                      */
+  mdd_t *invarFormulaStates = NIL(mdd_t);/* states in which formula is true */
+  mdd_t *one = NIL(mdd_t);
+  array_t *psVars = Fsm_FsmReadPresentStateVars(fsm);
+  array_t *inputVars = Fsm_FsmReadInputVars(fsm);
+  array_t *psInputVars = array_join(psVars, inputVars);
+  mdd_manager *mddMgr = Fsm_FsmReadMddManager(fsm);
+
+  invarStatesArray = array_alloc(mdd_t *, 0);
+
+  one = mdd_one(Fsm_FsmReadMddManager(fsm));
+
+  arrayForEachItem(Ctlp_Formula_t *, invarArray, i, formula){
+    /* semantic checks */
+    if(!Mc_FormulaStaticSemanticCheckOnNetwork(formula,
+					       Fsm_FsmReadNetwork(fsm),
+					       TRUE)){
+      (void) fprintf(vis_stdout,
+		     "** mc error: Error evaluating hint:\n%s\n",
+		     error_string());
+
+      mdd_free(one);
+      mdd_array_free(invarStatesArray);
+      return NIL(array_t);
+    }/* if semantic error */
+
+    assert(Ctlp_FormulaTestIsQuantifierFree(formula));
+
+    Ctlp_FlushStates(formula);
+
+
+    /* compute the set of states represented by the invariant. */
+    invarFormulaStates =
+      Mc_FsmEvaluateFormula(fsm, formula, one,
+			    NIL(Fsm_Fairness_t), NIL(array_t),
+			    MC_NO_EARLY_TERMINATION,
+			    NIL(Fsm_HintsArray_t), Mc_None_c,
+			    McVerbosityNone_c, McDcLevelNone_c, 0,
+			    McGSH_EL_c);
+
+
+    if (!mdd_check_support(mddMgr, invarFormulaStates, psInputVars)) {
+      mdd_t *temp;
+      int mddId;
+      array_t *supportArray = mdd_get_support(mddMgr, invarFormulaStates);
+      array_t *leftOverVars = array_alloc(int, 0);
+      /* store the PS and the Input Vars of this FSM */
+      st_table *supportTable = st_init_table(st_numcmp, st_numhash);
+
+      arrayForEachItem(int, psInputVars, j, mddId) {
+	(void) st_insert(supportTable, (char *) (long) mddId, NIL(char));
+      }
+
+      /* isolate the vars outside this FSM */
+      arrayForEachItem(int, supportArray, j, mddId) {
+	if (st_is_member(supportTable, (char *)(long)mddId) == 0) {
+	  array_insert_last(int, leftOverVars, mddId);
+	}
+      }
+
+      /* Quantify them out */
+      if (array_n(leftOverVars) > 0) {
+	fprintf(vis_stdout, "GS warning ** Quantifying out variables not relevant to the reduced FSM in hint %d. \n", i+1);
+	arrayForEachItem(int, leftOverVars, j, mddId) {
+	  fprintf(vis_stdout, "%s\n", (mdd_get_var_by_id(mddMgr, mddId)).name);
+	}
+	temp = mdd_smooth(mddMgr,  invarFormulaStates, leftOverVars);
+	mdd_free(invarFormulaStates);
+	invarFormulaStates = temp;
+      }
+      array_free(leftOverVars);
+      st_free_table(supportTable);
+      array_free(supportArray);
+    }
+
+    array_insert_last(mdd_t *, invarStatesArray, invarFormulaStates);
+  }/* for each formula */
+
+  array_free(psInputVars);
+  mdd_free(one);
+  return invarStatesArray;
+}/* Mc_EvaluateHints */
+
+/**Function********************************************************************
+
+  Synopsis [Return an array of hints]
+
+  Description [Read the guide file and compute the BDDs of the hints
+  and store in an array. Adds the 1 hint to the end of the array.
+
+  Closes the guideFP.
+
+  Returns NIL if something goes wrong.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+Mc_ComputeGuideArray(
+  Fsm_Fsm_t *fsm,
+  FILE *guideFP
+  )
+{
+  Ctlp_FormulaArray_t *hintFormulae;
+  array_t             * hintSets;
+
+  hintFormulae = Mc_ReadHints(guideFP);
+  fclose(guideFP);
+
+  if( hintFormulae == NIL(Ctlp_FormulaArray_t))
+    return NIL(array_t);
+
+  hintSets = Mc_EvaluateHints(fsm, hintFormulae);
+
+  Ctlp_FormulaArrayFree(hintFormulae);
+
+  return hintSets;
+}/* Mc_ComputeGuideArray */
+
+
+/**Function********************************************************************
+
+  Synopsis [Read and parse the hints_type set flag]
+
+  Description [Read and parse the hints_type set flag.  If it is not
+  set return the default: local.  Return Mc_None_c if there is an
+  error.]
+
+  SideEffects []
+
+******************************************************************************/
+Mc_GuidedSearch_t Mc_ReadGuidedSearchType(void)
+{
+  char *string =  Cmd_FlagReadByName("guided_search_hint_type");
+
+  if(string == NIL(char))  /* default */
+    return Mc_Local_c;
+  if(!strcmp(string, "global"))
+    return Mc_Global_c;
+  if(!strcmp(string, "local"))
+    return Mc_Local_c;
+  else
+    return Mc_None_c;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Debug function to check if there exists a proper input value]
+
+  Description [Check the existence of path by extracting input condition.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Mc_CheckPathToCore(Fsm_Fsm_t *fsm, array_t *pathToCore)
+{
+  array_t *inputVars;
+  int i;
+  mdd_t *fromState, *toState, *inputSet;
+  mdd_manager	*mgr = Ntk_NetworkReadMddManager(Fsm_FsmReadNetwork(fsm));
+
+  inputVars = Fsm_FsmReadInputVars( fsm );
+  for(i=-1; i<array_n(pathToCore)-1; i++) {
+    fromState = (i==-1) ? 0 : array_fetch(mdd_t *, pathToCore, i);
+    toState = array_fetch(mdd_t *, pathToCore, i+1);
+    if((long)fromState % 2)	fromState = (mdd_t *)((long)fromState - 1);
+    if((long)toState % 2)	toState = (mdd_t *)((long)toState - 1);
+    inputSet = ( i == -1) ? 0 :
+		 Mc_FsmComputeDrivingInputMinterms( fsm, fromState, toState );
+
+    if(inputSet)
+      Mc_ComputeAMinterm( inputSet, inputVars, mgr );
+    else if(i != -1)
+      fprintf(vis_stderr, "Illegal path from %d to %d\n", i, i+1);
+  }
+
+}
+
+/**Function********************************************************************
+
+  Synopsis [Debug function to check if there exists a proper input value]
+
+  Description [Check the existence of path by extracting input condition.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Mc_CheckPathFromCore(Fsm_Fsm_t *fsm, array_t *pathFromCore)
+{
+  array_t *inputVars;
+  int i;
+  mdd_t *fromState, *toState, *inputSet;
+  mdd_manager	*mgr = Ntk_NetworkReadMddManager(Fsm_FsmReadNetwork(fsm));
+
+  inputVars = Fsm_FsmReadInputVars( fsm );
+  for(i=array_n(pathFromCore); i>0; i--) {
+    fromState = (i==array_n(pathFromCore)) ? 0 : array_fetch(mdd_t *, pathFromCore, i);
+    toState = array_fetch(mdd_t *, pathFromCore, i-1);
+    if((long)fromState % 2)	fromState = (mdd_t *)((long)fromState - 1);
+    if((long)toState % 2)	toState = (mdd_t *)((long)toState - 1);
+    inputSet = ( i == array_n(pathFromCore)) ? 0 :
+      Mc_FsmComputeDrivingInputMinterms( fsm, fromState, toState );
+
+    if(inputSet)
+      Mc_ComputeAMinterm( inputSet, inputVars, mgr );
+    else if(i != array_n(pathFromCore))
+      fprintf(vis_stderr, "Illegal path from %d to %d\n", i, i+1);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis [Print states in terms of state variables]
+
+  Description [Print states in terms of state variables]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Mc_PrintStates(
+  Fsm_Fsm_t *modelFsm,
+  mdd_t *states)
+{
+  array_t *PSVars = Fsm_FsmReadPresentStateVars( modelFsm );
+  Ntk_Network_t *aNetwork = Fsm_FsmReadNetwork( modelFsm );
+  mdd_manager *mddMgr = Fsm_FsmReadMddManager( modelFsm );
+  mdd_t *zeroMdd, *new_states;
+  char  *tmpString;
+  double   size;
+
+ /*
+  *  sometimes, this function will be constrained by number of minterm
+  *     in the given set of states.
+  *     num_minterm = mdd_num_of_mintern(states);
+  *     if(num_minterm > MAX_MINTERM)   {
+  *       fprintf( stdout, "Too many minterms in given states\n" );
+  *       return;
+  *     }
+  */
+  if((long)states % 2) {
+    states = (mdd_t *)((long)states - 1);
+  }
+  zeroMdd = mdd_zero( mddMgr );
+  states = mdd_dup(states);
+  if(mdd_equal(states, zeroMdd)) {
+    fprintf(stdout, "ZERO mdd\n");
+    mdd_free(zeroMdd);
+    return;
+  }
+  size = mdd_count_onset(mddMgr, states, PSVars);
+  if(size > 40.0) {
+    fprintf(stdout, "Too many minterms in given states %.0f\n", size);
+    return;
+  }
+  fprintf( stdout, "    " );
+  while(1) {
+    mdd_t *result = Mc_ComputeAMinterm( states, PSVars, mddMgr );
+
+    new_states = mdd_and( states, result, 1, 0 );
+    mdd_free( states );
+    states = new_states;
+
+    tmpString = Mc_MintermToString( result, PSVars, aNetwork );
+    fprintf( stdout, "%s ", tmpString );
+    FREE(tmpString);
+    mdd_free( result );
+
+    if(mdd_equal(states, zeroMdd)) {
+      mdd_free(zeroMdd);
+      mdd_free(states);
+      break;
+    }
+  }
+  fprintf(stdout, "\n");
+}
+
+/**Function********************************************************************
+
+  Synopsis [Print the number of states]
+
+  Description [Print the number of states.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Mc_PrintNumStates(
+  Fsm_Fsm_t *modelFsm,
+  mdd_t *states)
+{
+  array_t *PSVars = Fsm_FsmReadPresentStateVars( modelFsm );
+  mdd_manager *mddMgr = Fsm_FsmReadMddManager( modelFsm );
+  mdd_t *zeroMdd;
+  double size;
+
+ /*
+  *  sometimes, this function will be constrained by number of minterm
+  *     in the given set of states.
+  *     num_minterm = mdd_num_of_mintern(states);
+  *     if(num_minterm > MAX_MINTERM)   {
+  *       fprintf( stdout, "Too many minterms in given states\n" );
+  *       return;
+  *     }
+  */
+  if((long)states % 2) {
+    states = (mdd_t *)((long)states - 1);
+  }
+  zeroMdd = mdd_zero( mddMgr );
+  states = mdd_dup(states);
+  if(mdd_equal(states, zeroMdd)) {
+    fprintf(stdout, "ZERO mdd\n");
+    mdd_free(zeroMdd);
+    mdd_free(states);
+    return;
+  }
+  size = mdd_count_onset(mddMgr, states, PSVars);
+  fprintf(stdout, "num states : %.0f\n", size);
+  mdd_free(zeroMdd);
+  mdd_free(states);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Print the states of each ring]
+
+  Description [Print the states of each ring]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Mc_PrintRings(
+  Fsm_Fsm_t *modelFsm,
+  array_t *onionRings)
+{
+  int j;
+  mdd_t *innerRing;
+
+  if(array_n(onionRings) > 0) {
+    for(j=0; j<array_n(onionRings); j++) {
+      innerRing = array_fetch(mdd_t *, onionRings, j);
+      fprintf(vis_stdout, "%d'th ring : ", j);
+      if(innerRing)
+	Mc_PrintStates(modelFsm, innerRing);
+      else
+	fprintf(vis_stdout, "\n");
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis [Print the number of states of each ring]
+
+  Description [Print the number of states of each ring]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Mc_PrintNumRings(
+  Fsm_Fsm_t *modelFsm,
+  array_t *onionRings)
+{
+  int j;
+  mdd_t *innerRing;
+
+  if(array_n(onionRings) > 0) {
+    for(j=0; j<array_n(onionRings); j++) {
+      innerRing = array_fetch(mdd_t *, onionRings, j);
+      fprintf(vis_stdout, "%d'th ring : ", j);
+      if(innerRing)
+	Mc_PrintNumStates(modelFsm, innerRing);
+      else
+	fprintf(vis_stdout, "\n");
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Pick a minterm from the given set close to target. Support
+  is an array of mddids representing the total support; that is, all
+  the variables on which aSet may depend.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+McComputeACloseMinterm(
+  mdd_t *aSet,
+  mdd_t *target,
+  array_t *Support,
+  mdd_manager *mddMgr)
+{
+  if (bdd_get_package_name() == CUDD) {
+    mdd_t *range;             /* range of Support             */
+    mdd_t *legalSet;          /* aSet without the don't cares */
+    mdd_t *closeCube;
+    int dist;
+    array_t *bddSupport;      /* Support in terms of bdd vars */
+    mdd_t *minterm;           /* a random minterm             */
+
+    /* Check that support of set is contained in Support. */
+    assert(SetCheckSupport(aSet, Support, mddMgr));
+    assert(!mdd_is_tautology(aSet, 0));
+    range      = mdd_range_mdd(mddMgr, Support);
+    legalSet   = bdd_and(aSet, range, 1, 1);
+    mdd_free(range);
+    closeCube = mdd_closest_cube(legalSet, target, &dist);
+    bddSupport = mdd_id_array_to_bdd_array(mddMgr, Support);
+    minterm    = bdd_pick_one_minterm(closeCube, bddSupport);
+
+    assert(MintermCheckWellFormed(minterm, Support, mddMgr));
+    assert(mdd_count_onset(mddMgr, minterm, Support) == 1);
+    assert(mdd_lequal(minterm,legalSet,1,1));
+
+    mdd_array_free(bddSupport);
+    mdd_free(legalSet);
+    mdd_free(closeCube);
+
+    return minterm;
+  } else {
+    return Mc_ComputeAMinterm(aSet, Support, mddMgr);
+  }/* if CUDD */
+
+} /* McComputeACloseMinterm */
+
+/**Function********************************************************************
+
+  Synopsis [Select a state from the given set]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+McComputeACloseState(
+  mdd_t *states,
+  mdd_t *target,
+  Fsm_Fsm_t *modelFsm)
+{
+  array_t *PSVars = Fsm_FsmReadPresentStateVars(modelFsm);
+  mdd_manager *mddMgr = Ntk_NetworkReadMddManager(
+    Fsm_FsmReadNetwork(modelFsm));
+  mdd_t *result;
+
+  if (mdd_is_tautology(target, 0)) {
+    result = Mc_ComputeAMinterm(states, PSVars, mddMgr);
+  } else {
+    result = McComputeACloseMinterm(states, target, PSVars, mddMgr);
+  }
+
+  return result;
+
+} /* McComputeACloseState */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts a string to a schedule type.]
+
+  Description [Converts a string to a schedule type.  If string does
+  not refer to one of the allowed schedule types, then returns
+  McGSH_Unassigned_c.]
+
+  SideEffects []
+
+******************************************************************************/
+Mc_GSHScheduleType
+McStringConvertToScheduleType(
+  char *string)
+{
+  if (strcmp("off", string) == 0) {
+    return McGSH_old_c;
+  } else if (strcmp("EL", string) == 0) {
+    return McGSH_EL_c;
+  } else if (strcmp("EL1", string) == 0) {
+    return McGSH_EL1_c;
+  } else if (strcmp("EL2", string) == 0) {
+    return McGSH_EL2_c;
+  } else if (strcmp("random", string) == 0) {
+    return McGSH_Random_c;
+  } else if (strcmp("budget", string) == 0) {
+    return McGSH_Budget_c;
+  } else {
+    return McGSH_Unassigned_c;
+  }
+
+} /* McStringConvertToScheduleType */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts a string to a lockstep mode.]
+
+  Description [Converts a string to a lockstep mode.  If string does
+  not refer to one of the allowed lockstep modes, it returns
+  MC_LOCKSTEP_UNASSIGNED.  The allowed values are: MC_LOCKSTEP_OFF,
+  MC_LOCKSTEP_EARLY_TERMINATION, MC_LOCKSTEP_ALL_SCCS, and a positive
+  integer n (lockstep enumerates up to n fair SCCs).]
+
+  SideEffects []
+
+******************************************************************************/
+int
+McStringConvertToLockstepMode(
+  char *string)
+{
+  int n;
+
+  if (strcmp("off", string) == 0) {
+    return MC_LOCKSTEP_OFF;
+  } else if (strcmp("on", string) == 0) {
+    return MC_LOCKSTEP_EARLY_TERMINATION;
+  } else if (strcmp("all", string) == 0) {
+    return MC_LOCKSTEP_ALL_SCCS;
+  } else if (Cmd_StringCheckIsInteger(string, &n) == 2) {
+    return n;
+  } else {
+    return MC_LOCKSTEP_UNASSIGNED;
+  }
+
+} /* McStringConvertToLockstepMode */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Print  an array of nodes]
+
+  SideEffects []
+
+******************************************************************************/
+
+static void
+PrintNodes(
+  array_t *mddIdArray,
+  Ntk_Network_t *network )
+{
+  int i;
+  int mddId;
+
+  arrayForEachItem(int , mddIdArray, i, mddId) {
+    Ntk_Node_t *node = Ntk_NetworkFindNodeByMddId( network, mddId );
+    char *nodeName = Ntk_NodeReadName( node );
+    fprintf(vis_stdout, " %s ", nodeName );
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Print  an array of nodes]
+
+  SideEffects []
+
+******************************************************************************/
+
+static array_t *
+SortMddIds(
+  array_t *mddIdArray,
+  Ntk_Network_t *network )
+{
+  int i;
+  int mddId;
+  char *nodeName;
+  st_table *nameToIndex = st_init_table( strcmp, st_strhash );
+  array_t *nodeNameArray = array_alloc( char *, 0 );
+  array_t *result = array_alloc( int, 0 );
+
+  arrayForEachItem(int, mddIdArray, i, mddId) {
+    Ntk_Node_t *node = Ntk_NetworkFindNodeByMddId( network, mddId );
+    nodeName = Ntk_NodeReadName( node );
+    st_insert( nameToIndex, nodeName, (char *) (long) i );
+    array_insert_last(  char *, nodeNameArray, nodeName );
+  }
+  array_sort( nodeNameArray, cmp);
+
+  arrayForEachItem(char *, nodeNameArray, i, nodeName ) {
+    int index;
+    st_lookup_int( nameToIndex, nodeName, & index );
+    mddId = array_fetch( int, mddIdArray, index );
+    array_insert_last( int, result, mddId );
+  }
+  st_free_table( nameToIndex );
+  array_free( nodeNameArray );
+
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Print  an array of nodes]
+
+  SideEffects []
+
+******************************************************************************/
+
+
+static void
+PrintDeck(
+  array_t *mddValues,
+  array_t *mddIdArray,
+  Ntk_Network_t *network )
+{
+  int i;
+  int mddId;
+
+  arrayForEachItem(int, mddIdArray, i, mddId) {
+    int value = array_fetch( int, mddValues, i );
+    Ntk_Node_t *node = Ntk_NetworkFindNodeByMddId( network, mddId );
+    Var_Variable_t *nodeVar = Ntk_NodeReadVariable( node );
+    if ( Var_VariableTestIsSymbolic( nodeVar ) ) {
+      char *symbolicValue = Var_VariableReadSymbolicValueFromIndex( nodeVar, value );
+      fprintf( vis_stdout, "%s ", symbolicValue );
+    }
+    else {
+      fprintf( vis_stdout, "%d ", value );
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis [Compare two strings in the from of char **]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+cmp(
+  const void * s1,
+  const void * s2)
+{
+  return(strcmp(*(char **)s1, *(char **)s2));
+}
+
+/**Function********************************************************************
+
+  Synopsis [Perform simple static semantic checks on formula.]
+
+  SideEffects []
+
+  SeeAlso [Mc_FormulaStaticSemanticCheckOnNetwork]
+******************************************************************************/
+static boolean
+AtomicFormulaCheckSemantics(
+  Ctlp_Formula_t *formula,
+  Ntk_Network_t *network,
+  boolean inputsAllowed)
+{
+
+  char *nodeNameString = Ctlp_FormulaReadVariableName( formula );
+  char *nodeValueString = Ctlp_FormulaReadValueName( formula );
+  Ntk_Node_t *node = Ntk_NetworkFindNodeByName( network, nodeNameString );
+
+  Var_Variable_t *nodeVar;
+  int nodeValue;
+
+  if ( !node ) {
+    error_append("Could not find node corresponding to the name\n\t- ");
+    error_append( nodeNameString );
+    error_append("\n(Wire for this name may have been removed by synthesis)");
+    return FALSE;
+  }
+
+  nodeVar = Ntk_NodeReadVariable( node );
+  if ( Var_VariableTestIsSymbolic( nodeVar ) ){
+
+    nodeValue = Var_VariableReadIndexFromSymbolicValue( nodeVar, nodeValueString );
+    if ( nodeValue == -1 ) {
+      error_append("Value specified in RHS is not in domain of variable\n");
+      error_append( Ctlp_FormulaReadVariableName( formula ) );
+      error_append("=");
+      error_append( Ctlp_FormulaReadValueName( formula ) );
+      return FALSE;
+    }
+  }
+  else {
+    int check;
+
+    check = Cmd_StringCheckIsInteger(nodeValueString, &nodeValue);
+    if( check==0 ) {
+      error_append("Value in the RHS is illegal\n");
+      error_append( Ctlp_FormulaReadVariableName( formula ) );
+      error_append("=");
+      error_append( Ctlp_FormulaReadValueName( formula ) );
+      return FALSE;
+    }
+    if( check==1 ) {
+      error_append("Value in the RHS is out of range of int\n");
+      error_append( Ctlp_FormulaReadVariableName( formula ) );
+      error_append("=");
+      error_append( Ctlp_FormulaReadValueName( formula ) );
+      return FALSE;
+    }
+    if ( !(Var_VariableTestIsValueInRange( nodeVar, nodeValue ) ) ) {
+      error_append("Value specified in RHS is not in domain of variable\n");
+      error_append( Ctlp_FormulaReadVariableName( formula ) );
+      error_append("=");
+      error_append( Ctlp_FormulaReadValueName( formula ) );
+      return FALSE;
+    }
+  }
+
+  if(!inputsAllowed){
+    boolean coverSupport;
+    lsGen tmpGen;
+    Ntk_Node_t *tmpNode;
+    st_table *supportNodes    = st_init_table(st_ptrcmp, st_ptrhash);
+    array_t *thisNodeArray = array_alloc( Ntk_Node_t *, 0);
+
+    array_insert_last( Ntk_Node_t *, thisNodeArray, node );
+    Ntk_NetworkForEachNode(network, tmpGen, tmpNode) {
+      if (Ntk_NodeTestIsConstant(tmpNode) || Ntk_NodeTestIsLatch(tmpNode)) {
+	st_insert(supportNodes, (char *) tmpNode, NIL(char));
+      }
+    }
+
+    coverSupport = Ntk_NetworkTestLeavesCoverSupportOfRoots(network,
+							    thisNodeArray,
+							    supportNodes);
+    array_free(thisNodeArray);
+    st_free_table(supportNodes);
+
+    if ( coverSupport == FALSE ) {
+      char *tmpString =
+	util_strcat3( "\nNode ", nodeNameString,
+		      " is not driven only by latches and constants.\n");
+      error_append(tmpString);
+      return FALSE;
+    }
+  }
+
+  return TRUE;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Add nodes for wires referred to in formula to nodesTable.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+NodeTableAddCtlFormulaNodes(
+  Ntk_Network_t *network,
+  Ctlp_Formula_t *formula,
+  st_table * nodesTable )
+{
+  if ( formula == NIL(Ctlp_Formula_t) ) {
+	return;
+  }
+
+  if ( Ctlp_FormulaReadType( formula ) == Ctlp_ID_c ) {
+    char *nodeNameString = Ctlp_FormulaReadVariableName( formula );
+    Ntk_Node_t *node = Ntk_NetworkFindNodeByName( network, nodeNameString );
+    if( node )
+      st_insert( nodesTable, ( char *) node, NIL(char) );
+    return;
+  }
+
+  NodeTableAddCtlFormulaNodes( network, Ctlp_FormulaReadRightChild( formula ), nodesTable );
+  NodeTableAddCtlFormulaNodes( network, Ctlp_FormulaReadLeftChild( formula ), nodesTable );
+
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Add nodes for wires referred to in formula to nodesTable.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+NodeTableAddLtlFormulaNodes(
+  Ntk_Network_t *network,
+  Ctlsp_Formula_t *formula,
+  st_table * nodesTable )
+{
+  if ( formula == NIL(Ctlsp_Formula_t) ) {
+	return;
+  }
+
+  if ( Ctlsp_FormulaReadType( formula ) == Ctlsp_ID_c ) {
+    char *nodeNameString = Ctlsp_FormulaReadVariableName( formula );
+    Ntk_Node_t *node = Ntk_NetworkFindNodeByName( network, nodeNameString );
+    if( node )
+      st_insert( nodesTable, ( char *) node, NIL(char) );
+    return;
+  }
+
+  NodeTableAddLtlFormulaNodes( network, Ctlsp_FormulaReadRightChild( formula ), nodesTable );
+  NodeTableAddLtlFormulaNodes( network, Ctlsp_FormulaReadLeftChild( formula ), nodesTable );
+
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Test that given mdd is a minterm.]
+
+  SideEffects []
+
+******************************************************************************/
+static boolean
+MintermCheckWellFormed(
+  mdd_t *aMinterm,
+  array_t *aSupport,
+  mdd_manager *mddMgr)
+{
+
+  /* first check its support */
+  if (!SetCheckSupport(aMinterm, aSupport, mddMgr)) {
+    return FALSE;
+  }
+
+  /* now check its a minterm */
+  {
+    float cardinality = mdd_count_onset( mddMgr, aMinterm, aSupport );
+    if ( cardinality != 1 ) {
+      fprintf( vis_stderr, "-- onset is not one\n");
+      return FALSE;
+    }
+  }
+  return TRUE;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Test that given mdd is a minterm.]
+
+  SideEffects []
+
+******************************************************************************/
+static boolean
+SetCheckSupport(
+  mdd_t *aMinterm,
+  array_t *aSupport,
+  mdd_manager *mddMgr)
+{
+  if (!mdd_check_support(mddMgr, aMinterm, aSupport)) {
+    fprintf(vis_stderr,
+      "** mc error: support of minterm is not contained in claimed support\n");
+    return FALSE;
+  }
+  return TRUE;
+}
Index: vis_dev/vis-2.3/src/mc/mcVacuum.c
===================================================================
--- vis_dev/vis-2.3/src/mc/mcVacuum.c	(revision 14)
+++ vis_dev/vis-2.3/src/mc/mcVacuum.c	(revision 14)
@@ -0,0 +1,2490 @@
+/**CFile***********************************************************************
+
+  FileName    [mcVacuum.c]
+
+  PackageName [mc]
+
+  Synopsis    [Functions for vacuity detection.]
+
+  Description [This file contains the functions implementing vacuity
+  detection for CTL.  A CTL formula passes vacuously if it can be strengthened
+  by replacing subformulae by "bottom" (either TRUE or FALSE, depending on the
+  negation parity) without changing the outcome of model checking.  Likewise,
+  a formula fails vacuously if it can be weakened by replacing subformulae by
+  top (the negation of bottom) and still fail.  Under the assumption that a
+  formula is represented by a parse tree (as opposed to a more general parse
+  DAG) each subformula has a given negation parity.  Bottom stands for FALSE
+  if the replaced subformula appears under an even number of negation; it
+  stands for TRUE otherwise.  Since all CTL operators besides neagtion are
+  monotonically increasing in their operands, replacing a subformula with
+  bottom result in a stronger property, that is, one that implies the original
+  one.  A dual argument applies to replacements with top.<p>
+  This file contains two algorithms for CTL vacuity detection: The original
+  one of Beer et al. (CAV97), and an extension of the thorough vacuity
+  detection algorithm of Purandare and Somenzi (CAV2002), also known as "CTL
+  vacuum cleaning."<p>
+  The algorithm of Beer et al. applies to passing weak ACTL (w-ACTL)
+  properties.  Roughly speaking, in a w-ACTL property each binary opeartor has
+  at least one child that is a propositional formula.  A w-ACTL formula
+  contains a unique smallest important subformula.  This is replaced by bottom
+  to produce a witness formula.  If the witness formula passes, then the
+  original formula passed vacuously; otherwise, the counterexample to the
+  witness formula is an interesting witness to the original one.<p>
+  The implementation of the CTL vacuum cleaning algorithm in this file applies
+  to both passing and failing CTL properties.  For each formula, replacement
+  is attempted for all leaves, therefore identifying many more cases of
+  vacuity.  All the replacements are dealt with in one traversal of the parse
+  tree of the formula, paying attention to combining the cases that produce
+  identical sets of states.  For this reason, thorough vacuity detection is
+  usually much cheaper than running as many model checking experiments as
+  there are leaves.]
+
+  SeeAlso     [mcCmd.c mcMc.c]
+
+  Author      [Mitra Purandare]
+
+  Copyright   [Copyright (c) 2002-2005, 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 "ctlpInt.h"
+#include "mcInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifndef lint
+static char rcsid[] UNUSED = "$Id: mcVacuum.c,v 1.1 2005/05/13 05:54:05 fabio Exp $";
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void EvaluateFormulaThoroughVacuity(Fsm_Fsm_t *fsm, Ctlp_Formula_t *ctlFormula, mdd_t *fairStates, Fsm_Fairness_t *fairCondition, array_t *careStatesArray, Mc_EarlyTermination_t *earlyTermination, Fsm_HintsArray_t *hintsArray, Mc_GuidedSearch_t hintType, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, int buildOnionRing, Mc_GSHScheduleType GSHschedule, mdd_t *modelInitialStates);
+static void EvaluateFormulaWactlVacuity(Fsm_Fsm_t *modelFsm, Ctlp_Formula_t *ctlFormula, int i, mdd_t *fairStates, Fsm_Fairness_t *fairCond, array_t *modelCareStatesArray, Mc_EarlyTermination_t *earlyTermination, array_t *hintsStatesArray, Mc_GuidedSearch_t guidedSearchType, mdd_t *modelInitialStates, McOptions_t *options);
+static void PrintVacuousBottom(mdd_t *modelInitialStates, Fsm_Fsm_t *modelFsm, Ctlp_Formula_t *ctlFormula, Mc_FwdBwdAnalysis traversalDirection, array_t *modelCareStatesArray, McOptions_t *options, Mc_VerbosityLevel verbosity);
+static void PrintVacuous(mdd_t *modelInitialStates, Fsm_Fsm_t *modelFsm, Ctlp_Formula_t *ctlFormula, Mc_FwdBwdAnalysis traversalDirection, array_t *modelCareStatesArray, McOptions_t *options, Mc_VerbosityLevel verbosity);
+static void ModelcheckAndVacuity(Fsm_Fsm_t *modelFsm, Ctlp_Formula_t *ctlFormula, mdd_t *fairStates, Fsm_Fairness_t *fairCondition, array_t *modelCareStatesArray, Mc_EarlyTermination_t *earlyTermination, Fsm_HintsArray_t *hintsArray, Mc_GuidedSearch_t hintType, Ctlp_Approx_t TRMinimization, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, int buildOnionRings, Mc_GSHScheduleType GSHschedule, mdd_t *modelInitialStates);
+static void CreateImportantWitness(Ctlp_Formula_t *OldctlFormula, Ctlp_Formula_t *ctlFormula, int i);
+static void CreateImportantCounterexample(Ctlp_Formula_t *OldctlFormula, Ctlp_Formula_t *ctlFormula, int i);
+static array_t * McMddArrayArrayDup(array_t *arrayBddArray);
+static void match_top(Ctlp_Formula_t *ctlFormula, array_t *mddArray, array_t *matchfound, array_t *matchelement);
+static void match_bot(Ctlp_Formula_t *ctlFormula, array_t *mddArray, array_t *matchfound, array_t *matchelement);
+static array_t * GenerateOnionRings(array_t* TempOnionRings, array_t* onionRings);
+static void FormulaFreeDebugDataVac(Ctlp_Formula_t *formula);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Model checks a formula and checks for its vacuity.]
+
+  Description [This function dispatches either w-ACTL vacuity detection or
+  CTL vacuum cleaning.  In the latter case also takes care of printing
+  results.]
+
+  SideEffects [Annotates the nodes of the CTL formula with various sets.]
+
+  SeeAlso     [EvaluateFormulaWactlVacuity EvaluateFormulaThoroughVacuity]
+
+******************************************************************************/
+void
+McVacuityDetection(
+  Fsm_Fsm_t *modelFsm,
+  Ctlp_Formula_t *ctlFormula,
+  int i,
+  mdd_t *fairStates,
+  Fsm_Fairness_t *fairCond,
+  array_t *modelCareStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  array_t *hintsStatesArray,
+  Mc_GuidedSearch_t guidedSearchType,
+  mdd_t *modelInitialStates,
+  McOptions_t *options)
+{
+
+  if (McOptionsReadBeerMethod(options)) {
+    EvaluateFormulaWactlVacuity(modelFsm, ctlFormula, i, fairStates, fairCond,
+				modelCareStatesArray, earlyTermination,
+				hintsStatesArray, guidedSearchType,
+				modelInitialStates, options);
+  }
+  else {
+    mdd_t *ctlFormulaStates;
+    boolean result;
+    Mc_VerbosityLevel verbosity = McOptionsReadVerbosityLevel(options);
+    Mc_DcLevel dcLevel = McOptionsReadDcLevel(options);
+    Mc_GSHScheduleType GSHschedule = McOptionsReadSchedule(options);
+    int buildOnionRings =
+      (McOptionsReadDbgLevel(options) != McDbgLevelNone_c || verbosity);
+    Mc_FwdBwdAnalysis traversalDirection =
+      McOptionsReadTraversalDirection(options);
+    mdd_manager *mddMgr = Fsm_FsmReadMddManager(modelFsm);
+
+    Ctlp_FormulaNegations(ctlFormula,Ctlp_Even_c);
+    EvaluateFormulaThoroughVacuity(modelFsm, ctlFormula, fairStates,
+				   fairCond, modelCareStatesArray,
+				   earlyTermination, hintsStatesArray,
+				   guidedSearchType, verbosity, dcLevel,
+				   buildOnionRings, GSHschedule,
+				   modelInitialStates);
+    Mc_EarlyTerminationFree(earlyTermination);
+    if(hintsStatesArray != NIL(array_t))
+      mdd_array_free(hintsStatesArray);
+    ctlFormulaStates = array_fetch(mdd_t *,ctlFormula->Bottomstates,0);
+    /* user feedback on succes/fail */
+    result = McPrintPassFail(mddMgr, modelFsm, traversalDirection,
+			     ctlFormula, ctlFormulaStates,
+			     modelInitialStates, modelCareStatesArray,
+			     options, verbosity);
+    if (result == TRUE) {
+      PrintVacuous(modelInitialStates,modelFsm,ctlFormula,
+		   traversalDirection,modelCareStatesArray,
+		   options, verbosity);
+    }
+    else {
+      PrintVacuousBottom(modelInitialStates,modelFsm,ctlFormula,
+			 traversalDirection,modelCareStatesArray,
+			 options, verbosity);
+    }
+    FormulaFreeDebugDataVac(ctlFormula);
+  }
+
+} /* McVacuityDetection */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Applies vacuum cleaning to a CTL formula.]
+
+  Description [This function evaluates all possible leaf replacements in
+  parallel and attaches the information to the parse tree.  This is a wrapper
+  around ModelcheckAndVacuity; it is mainly responsible of dealing with
+  global/local hints.]
+
+  SideEffects [Annotates the formula parse tree.]
+
+  SeeAlso     [McVacuityDetection EvaluateFormulaWactlVacuity
+  ModelcheckAndVacuity]
+
+******************************************************************************/
+static void
+EvaluateFormulaThoroughVacuity(
+  Fsm_Fsm_t *fsm,
+  Ctlp_Formula_t *ctlFormula,
+  mdd_t *fairStates,
+  Fsm_Fairness_t *fairCondition,
+  array_t *careStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  Fsm_HintsArray_t *hintsArray,
+  Mc_GuidedSearch_t hintType,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  int buildOnionRing,
+  Mc_GSHScheduleType GSHschedule,
+  mdd_t *modelInitialStates)
+{
+  mdd_t *hint;	    /* to iterate over hintsArray */
+  int	hintnr;	    /* idem			  */
+  assert(hintType == Mc_None_c || hintsArray != NIL(Fsm_HintsArray_t));
+
+  if(hintType != Mc_Global_c) {
+    ModelcheckAndVacuity(fsm, ctlFormula, fairStates,
+			 fairCondition, careStatesArray,
+			 earlyTermination, hintsArray, hintType,
+			 Ctlp_Exact_c, verbosity, dcLevel,
+			 buildOnionRing, GSHschedule,
+			 modelInitialStates);
+    return;
+  }
+  else{
+    array_t *result = NIL(array_t);
+    Ctlp_Approx_t approx;
+
+    if(verbosity >= McVerbosityMax_c)
+      fprintf(vis_stdout, "--Using global hints\n");
+    
+    arrayForEachItem(mdd_t *, hintsArray, hintnr, hint){
+      if(result != NIL(array_t))
+	array_free(result);
+      
+      if(verbosity >= McVerbosityMax_c)
+	fprintf(vis_stdout, "--Instantiating global hint %d\n", hintnr);
+      
+      Fsm_InstantiateHint(fsm, hint, FALSE, TRUE, Ctlp_Underapprox_c,
+			  (verbosity >= McVerbosityMax_c));
+      
+      approx = mdd_is_tautology(hint, 1) ? Ctlp_Exact_c : Ctlp_Underapprox_c;
+
+      ModelcheckAndVacuity(fsm,ctlFormula, fairStates,
+			   fairCondition, careStatesArray,
+			   earlyTermination, hintsArray, hintType,
+			   approx, verbosity,
+			   dcLevel, buildOnionRing,GSHschedule,
+			   modelInitialStates); 
+      /* TBD: take into account (early) termination here */
+    }
+    Fsm_CleanUpHints(fsm, FALSE, TRUE, (verbosity >= McVerbosityMax_c));
+
+    return;
+  }
+} /* EvaluateFormulaThoroughVacuity */
+
+
+/**Function********************************************************************
+
+  Synopsis [Applies vacuity detection to a w-ACTL formula.]
+
+  Description [This function applies the algorithm of Beer et al. (CAV97) for
+  vacuity detection of passing w-ACTL formulae.  First regular model checking
+  is applied to the given CTL formula.  If the formula passes and is in w-ACTL,
+  the witness formula is obtained by replacing the smallest important
+  subformula with bottom.  Model checking is then applied to the witness
+  formula.  A vacuous pass is reported if the witness property holds.
+  Otherwise, the counterexample is an interesting witness to the original
+  formula, that is, an execution of the model in which the given property
+  holds in a non trivial manner.]
+
+  SideEffects [Annotates the parse tree of the formula.]
+
+  SeeAlso     [McVacuityDetection EvaluateFormulaThoroughVacuity]
+
+******************************************************************************/
+static void
+EvaluateFormulaWactlVacuity(
+  Fsm_Fsm_t *modelFsm,
+  Ctlp_Formula_t *ctlFormula,
+  int i,
+  mdd_t *fairStates,
+  Fsm_Fairness_t *fairCond,
+  array_t *modelCareStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  array_t *hintsStatesArray,
+  Mc_GuidedSearch_t guidedSearchType,
+  mdd_t *modelInitialStates,
+  McOptions_t *options)
+{
+  mdd_t *ctlFormulaStates;
+  boolean result1, result2;
+  Mc_VerbosityLevel verbosity = McOptionsReadVerbosityLevel(options);
+  Mc_DcLevel dcLevel = McOptionsReadDcLevel(options);
+  Mc_GSHScheduleType GSHschedule = McOptionsReadSchedule(options);
+  int buildOnionRings =
+    (McOptionsReadDbgLevel(options) != McDbgLevelNone_c || verbosity);
+  Mc_FwdBwdAnalysis traversalDirection =
+    McOptionsReadTraversalDirection(options);
+  mdd_manager *mddMgr = Fsm_FsmReadMddManager(modelFsm);
+
+  ctlFormulaStates =
+    Mc_FsmEvaluateFormula(modelFsm, ctlFormula, fairStates,
+			  fairCond, modelCareStatesArray,
+			  earlyTermination, hintsStatesArray,
+			  guidedSearchType, verbosity, dcLevel,
+			  buildOnionRings,GSHschedule);
+
+  Mc_EarlyTerminationFree(earlyTermination);
+  if(hintsStatesArray != NIL(array_t))
+    mdd_array_free(hintsStatesArray);
+  result1 = McPrintPassFail(mddMgr, modelFsm, traversalDirection,
+			    ctlFormula, ctlFormulaStates,
+			    modelInitialStates, modelCareStatesArray,
+			    options, verbosity); 
+  mdd_free(ctlFormulaStates);
+
+  if (result1 == FALSE)
+    fprintf(vis_stdout,
+	    "# MC: Original formula failed. Aborting vacuity detection\n");
+  else {
+    /* see if we can create a witness formula */
+    if ((Ctlp_CheckClassOfExistentialFormula(ctlFormula) != Ctlp_ACTL_c) &&
+	(Ctlp_CheckClassOfExistentialFormula(ctlFormula) != Ctlp_QuantifierFree_c)) {
+      fprintf(vis_stdout,
+	      "# MC: Not an ACTL Formula. Aborting vacuity detection\n");
+    }
+    else {
+      if (Ctlp_CheckIfWACTL(Ctlp_FormulaReadOriginalFormula(ctlFormula)) == Ctlp_NONWACTL_c) {
+	fprintf(vis_stdout, "# MC: Not a w-ACTL Formula. Aborting vacuity detection\n");
+      }
+      else {
+	Ctlp_Formula_t *origFormula, *witFormula;
+	/* We can create a witness formula.  Annotate the original
+	 * formula with negation parity info and then create a copy
+	 * with the smallest important formula replaced by bottom. */
+	fprintf(vis_stdout, "Model checking the witness formula\n");
+	origFormula = Ctlp_FormulaReadOriginalFormula(ctlFormula);
+	Ctlp_FormulaNegations(origFormula, Ctlp_Even_c);
+	witFormula = Ctlp_FormulaCreateWitnessFormula(origFormula);
+	ctlFormula = Ctlp_FormulaConvertToExistentialForm(witFormula);
+
+	/* some user feedback */
+	if (verbosity != McVerbosityNone_c) {
+	  (void)fprintf(vis_stdout, "Checking witness formula[%d] : ", i + 1);
+	  Ctlp_FormulaPrint(vis_stdout,
+			    Ctlp_FormulaReadOriginalFormula(ctlFormula));
+	  (void)fprintf (vis_stdout, "\n");
+	  assert(traversalDirection != McFwd_c);
+	}
+	/************** the actual computation *************************/
+	earlyTermination = Mc_EarlyTerminationAlloc(McAll_c, modelInitialStates);
+	ctlFormulaStates =
+	  Mc_FsmEvaluateFormula(modelFsm, ctlFormula, fairStates,
+				fairCond, modelCareStatesArray,
+				earlyTermination, hintsStatesArray,
+				guidedSearchType, verbosity, dcLevel,
+				buildOnionRings,GSHschedule);
+
+	Mc_EarlyTerminationFree(earlyTermination);
+	if(hintsStatesArray != NIL(array_t))
+	  mdd_array_free(hintsStatesArray);
+	/* user feedback on succes/fail */
+	result2 = McPrintPassFail(mddMgr, modelFsm, traversalDirection,
+				  ctlFormula, ctlFormulaStates,
+				  modelInitialStates,
+				  modelCareStatesArray,
+				  options, verbosity);
+	if (result2)
+	  (void)fprintf(vis_stdout, "# MC: Vacuous pass\n");
+	else
+	  (void)fprintf(vis_stdout, "# MC: Not a vacuous pass\n");
+	mdd_free(ctlFormulaStates);
+	Ctlp_FormulaFree(ctlFormula);
+	Ctlp_FormulaFree(witFormula);
+      }
+    }
+  }
+
+} /* EvaluateFormulaWactlVacuity */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints results of vacuum cleaning for a failing CTL property.]
+
+  Description [For a failing CTL property reports all vacuous failures.  If so
+  requested, it also produces interesting counterexamples, that is,
+  computations of the model for which even the weakened property fails.]
+
+  SideEffects [none]
+
+  SeeAlso     [PrintVacuous]
+
+******************************************************************************/
+static void
+PrintVacuousBottom(
+  mdd_t *modelInitialStates,
+  Fsm_Fsm_t *modelFsm,
+  Ctlp_Formula_t *ctlFormula,
+  Mc_FwdBwdAnalysis traversalDirection,
+  array_t *modelCareStatesArray,
+  McOptions_t *options,
+  Mc_VerbosityLevel verbosity)
+{
+  Ctlp_Formula_t *formula,*Int_Counter_CtlFormula;
+  boolean vacuous = FALSE;
+  int i;
+  Ctlp_FormulaType  type;
+  if (traversalDirection == McBwd_c){
+    for (i=1;i<array_n(ctlFormula->Topstates);i++){
+      if (!(mdd_lequal(modelInitialStates, array_fetch(mdd_t *,ctlFormula->Topstates,i),1,1))){
+	formula = array_fetch(Ctlp_Formula_t *,ctlFormula->leaves,(i-1));
+	type = Ctlp_FormulaReadType(formula);
+	if((type != Ctlp_FALSE_c) && (type != Ctlp_TRUE_c)) {
+	  fprintf(vis_stdout, "# MC: Vacuous failure : ");
+	  Ctlp_FormulaPrint(vis_stdout, formula);
+	  fprintf(vis_stdout, "\n");
+	  if (McOptionsReadDbgLevel(options) != McDbgLevelNone_c){
+	    fprintf(vis_stdout, "# Generating interesting counterexample :\n");
+	    Int_Counter_CtlFormula = Ctlp_FormulaDup(ctlFormula);
+	    CreateImportantCounterexample(ctlFormula,Int_Counter_CtlFormula,i);
+	    McFsmDebugFormula(options,Int_Counter_CtlFormula,modelFsm,
+			      modelCareStatesArray);
+	    Ctlp_FormulaFree(Int_Counter_CtlFormula);
+	  }
+	  vacuous = TRUE;
+	}
+      }
+    }
+    if (vacuous == FALSE){
+      (void)fprintf(vis_stdout, "# MC: No vacuous failures\n");
+    }
+  }
+  else{
+    (void)fprintf(vis_stderr, "# MC: Vacuity can not be checked\n");
+  }
+} /* PrintVacuousBottom */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints results of vacuum cleaning for a passing CTL property.]
+
+  Description [For a passing CTL property reports all vacuous passes.  If so
+  requested, it also produces interesting witnesses, that is,
+  computations of the model for which the original property holds non
+  trivially. (Alternatively, the strengthened property that gave the vacuous
+  pass fails.)]
+
+  SideEffects [none]
+
+  SeeAlso     [McVacuityDetection PrintVacuousBottom]
+
+******************************************************************************/
+static void
+PrintVacuous(
+  mdd_t *modelInitialStates,
+  Fsm_Fsm_t *modelFsm,
+  Ctlp_Formula_t *ctlFormula,
+  Mc_FwdBwdAnalysis traversalDirection,
+  array_t *modelCareStatesArray,
+  McOptions_t *options,
+  Mc_VerbosityLevel verbosity)
+{
+  Ctlp_Formula_t *formula,*Int_Wit_CtlFormula;
+  boolean vacuous = FALSE;
+  int i;
+  Ctlp_FormulaType  type;
+  if (traversalDirection == McBwd_c) {
+    for (i=1;i<array_n(ctlFormula->Bottomstates);i++) {
+      formula = array_fetch(Ctlp_Formula_t *,ctlFormula->leaves,(i-1));
+      type = Ctlp_FormulaReadType(formula);
+      if (mdd_lequal(modelInitialStates, array_fetch(mdd_t *,ctlFormula->Bottomstates,i),1,1)) {
+	if((type != Ctlp_FALSE_c) && (type != Ctlp_TRUE_c)) {
+	  fprintf(vis_stdout, "# MC: Vacuous pass : ");
+	  Ctlp_FormulaPrint(vis_stdout, formula);
+	  fprintf(vis_stdout, "\n");
+	  vacuous = TRUE;
+	}
+      }
+      else { /* CounterExample Generation */
+	if (McOptionsReadDbgLevel(options) != McDbgLevelNone_c){
+	  fprintf(vis_stdout, "# MC: Not a vacuous pass : ");
+	  Ctlp_FormulaPrint(vis_stdout, formula);
+	  fprintf(vis_stdout, "\n");
+	  fprintf(vis_stdout, "# Generating interesting witness :\n");
+	  Int_Wit_CtlFormula = Ctlp_FormulaDup(ctlFormula);
+	  CreateImportantWitness(ctlFormula,Int_Wit_CtlFormula,i);
+	  McFsmDebugFormula(options,Int_Wit_CtlFormula,modelFsm,
+			    modelCareStatesArray);
+	  Ctlp_FormulaFree(Int_Wit_CtlFormula);
+	}
+      }
+    }
+    if (vacuous == FALSE){
+      (void)fprintf(vis_stdout, "# MC: No vacuous passes\n");
+    }
+  }
+  else{
+    (void)fprintf(vis_stderr, "# MC: Vacuity cannot be checked\n");
+  }
+} /* PrintVacuous */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Core algorithm for CTL vacuum cleaning.]
+
+  Description [This function recursively annotates the parse tree of a
+  CTL formula with the sets of states that satisfy the original formula as
+  well as the various replacements.  If debugging is requested, it also stores
+  onion rings.  Since it is not known in advance whether the original formula
+  passes or fails, this function computes both bottom and top replacements and
+  tries to use monotonicity properties to accelerate fixpoint computations.]
+
+  SideEffects [Annotates the formula parse tree.]
+
+  SeeAlso [EvaluateFormulaThoroughVacuity]
+
+******************************************************************************/
+static void
+ModelcheckAndVacuity(
+  Fsm_Fsm_t *modelFsm,
+  Ctlp_Formula_t *ctlFormula,
+  mdd_t *fairStates,
+  Fsm_Fairness_t *fairCondition,
+  array_t *modelCareStatesArray,
+  Mc_EarlyTermination_t *earlyTermination,
+  Fsm_HintsArray_t *hintsArray,
+  Mc_GuidedSearch_t hintType,
+  Ctlp_Approx_t TRMinimization,
+  Mc_VerbosityLevel verbosity,
+  Mc_DcLevel dcLevel,
+  int buildOnionRings,
+  Mc_GSHScheduleType GSHschedule,
+  mdd_t *modelInitialStates)
+{
+  mdd_t *result  = NIL(mdd_t);
+  mdd_t *result_new = NIL(mdd_t);
+  mdd_t *result_bot  = NIL(mdd_t);
+  mdd_t *result_top  = NIL(mdd_t);
+  mdd_t *result_underapprox = NIL(mdd_t);
+  mdd_manager *mddMgr = Fsm_FsmReadMddManager(modelFsm);
+  array_t     *careStatesArray = NIL(array_t);
+  array_t     *mddArray_bot = NIL(array_t);
+  array_t     *mddArray_top = NIL(array_t);
+  array_t     *leavesArray = NIL(array_t);
+  array_t     *leavesLeftArray = NIL(array_t);
+  array_t     *leavesRightArray = NIL(array_t);
+  array_t     *matchfound_bot = NIL(array_t);
+  array_t     *matchfound_top = NIL(array_t);
+  array_t     *matchelement_bot = NIL(array_t);
+  array_t     *matchelement_top = NIL(array_t);
+  mdd_t	      *tmpMdd;
+  mdd_t	      *approx = NIL(mdd_t); /* prev computed approx of sat set */ 
+  /*  mdd_t *ctlFormulaStates = Ctlp_FormulaObtainStates( ctlFormula ); */
+  Ctlp_Formula_t *leftChild,*rightChild ;
+  mdd_t *leftMdd = NIL(mdd_t);
+  mdd_t *rightMdd = NIL(mdd_t);
+  Ctlp_Approx_t leftApproxType = Ctlp_Exact_c;
+  Ctlp_Approx_t rightApproxType = Ctlp_Exact_c;
+  Ctlp_Approx_t thisApproxType = Ctlp_Exact_c;
+  boolean fixpoint = FALSE;
+  /* boolean approx_decide = FALSE; */
+  /* We will propagate early termination ONLY to the outmost fixpoint,
+     and only propagate through negation. We should also propagate
+     over other boolean operators, and maybe temporal operators.
+     Propagation over negation is done by complementing the type. */
+  rightChild = Ctlp_FormulaReadRightChild(ctlFormula);
+  leftChild = Ctlp_FormulaReadLeftChild(ctlFormula);
+
+  if (leftChild) {
+    if ((leftChild->share) == 1){
+      Mc_EarlyTermination_t *nextEarlyTermination =
+	McObtainUpdatedEarlyTerminationCondition(
+	  earlyTermination, NIL(mdd_t), Ctlp_FormulaReadType(ctlFormula));
+
+      ModelcheckAndVacuity(modelFsm, leftChild,fairStates,
+			   fairCondition, modelCareStatesArray,
+			   nextEarlyTermination,
+			   hintsArray, hintType,
+			   TRMinimization, verbosity,dcLevel,
+			   buildOnionRings, GSHschedule,
+			   modelInitialStates);
+      Mc_EarlyTerminationFree(nextEarlyTermination);
+    }
+  }
+
+  if (rightChild) {
+    if((rightChild->share) == 1) {
+      Mc_EarlyTermination_t *nextEarlyTermination =
+	McObtainUpdatedEarlyTerminationCondition(
+	  earlyTermination,NIL(mdd_t) ,Ctlp_FormulaReadType(ctlFormula));
+      ModelcheckAndVacuity(modelFsm, rightChild, fairStates,
+			   fairCondition,
+			   modelCareStatesArray,
+			   nextEarlyTermination,
+			   hintsArray, hintType,
+			   TRMinimization, verbosity, dcLevel,
+			   buildOnionRings, GSHschedule,
+			   modelInitialStates);
+      Mc_EarlyTerminationFree(nextEarlyTermination);
+    }
+  }
+  if (modelCareStatesArray != NIL(array_t)) {
+    careStatesArray = modelCareStatesArray;
+  } else {
+    careStatesArray = array_alloc(mdd_t *, 0);
+    array_insert_last(mdd_t *, careStatesArray, mdd_one(mddMgr));
+  }
+  mddArray_bot = array_alloc(mdd_t *, 0);
+  mddArray_top = array_alloc(mdd_t *, 0);
+  ctlFormula->share = 2;
+  switch (Ctlp_FormulaReadType(ctlFormula)) {
+  case Ctlp_ID_c :{
+    result = McModelCheckAtomicFormula(modelFsm, ctlFormula);
+    matchfound_top = array_alloc(boolean, 0);
+    matchfound_bot = array_alloc(boolean, 0);
+    matchelement_top = array_alloc(int, 0);
+    matchelement_bot = array_alloc(int, 0);
+    leavesArray = array_alloc(Ctlp_Formula_t *, 0);
+    array_insert(mdd_t *, mddArray_bot , 0, mdd_dup(result));
+    array_insert(mdd_t *, mddArray_top , 0, result);
+    /* if the formula is an important subformula, we need to find the
+       bottom and top set for it as well. */
+    if (ctlFormula->negation_parity != Ctlp_EvenOdd_c) {
+      array_insert_last(Ctlp_Formula_t *, leavesArray, ctlFormula);
+      if (ctlFormula->negation_parity == Ctlp_Even_c) {
+	/* if the formula has even negation partity, it should be replaced
+	   with FALSE. */
+	result_bot = mdd_zero(mddMgr);
+	result_top = mdd_one(mddMgr);
+      }
+      else {
+	/* if the formula has odd negation parity, it should be replaced
+	   with TRUE. */
+	result_bot = mdd_one(mddMgr);
+	result_top = mdd_zero(mddMgr);
+      }
+      array_insert_last(mdd_t *,mddArray_bot ,result_bot);
+      array_insert_last(mdd_t *,mddArray_top ,result_top);
+      /*  Finding match for bottom sets */
+      if(mdd_equal(result_bot,array_fetch(mdd_t *, mddArray_bot, 0))){
+	array_insert(boolean, matchfound_bot, 1 ,TRUE);
+	array_insert(int, matchelement_bot, 1 ,0);
+      }
+      else
+	array_insert(boolean, matchfound_bot, 1 ,FALSE);
+      /* Finding match for top sets */
+      if(mdd_equal(result_top,array_fetch(mdd_t *, mddArray_top, 0))){
+	array_insert(boolean, matchfound_top, 1 ,TRUE);
+	array_insert(int, matchelement_top, 1 ,0);
+      }
+      else
+	array_insert(boolean, matchfound_top, 1 ,FALSE);
+    }
+    array_insert(boolean, matchfound_bot, 0 ,FALSE);
+    array_insert(boolean, matchfound_top, 0 ,FALSE);
+    /* only exact set will be there if the formula is not an important
+       subformula. */
+    ctlFormula->Topstates= mddArray_top;
+    ctlFormula->matchfound_top = matchfound_top;
+    ctlFormula->matchelement_top = matchelement_top;
+    ctlFormula->Bottomstates = mddArray_bot;
+    ctlFormula->matchfound_bot = matchfound_bot;
+    ctlFormula->matchelement_bot = matchelement_bot;
+    ctlFormula->leaves = leavesArray;
+    break;
+  }
+  case Ctlp_TRUE_c :{
+    result = mdd_one(mddMgr);
+    leavesArray = array_alloc(Ctlp_Formula_t *, 0);
+    matchfound_top = array_alloc(boolean, 0);
+    matchfound_bot = array_alloc(boolean, 0);
+    matchelement_top = array_alloc(int, 0);
+    matchelement_bot = array_alloc(int, 0);
+    array_insert_last(mdd_t *,mddArray_bot , mdd_dup(result));
+    array_insert_last(mdd_t *,mddArray_top , result);
+    array_insert(boolean, matchfound_bot, 0 ,FALSE);
+    array_insert(boolean, matchfound_top, 0 ,FALSE);
+    ctlFormula->Bottomstates = mddArray_bot;
+    ctlFormula->matchfound_bot = matchfound_bot;
+    ctlFormula->matchelement_bot = matchelement_bot;
+    ctlFormula->Topstates = mddArray_top;
+    ctlFormula->matchfound_top = matchfound_top;
+    ctlFormula->matchelement_top = matchelement_top;
+    ctlFormula->leaves = leavesArray;
+    break;
+  }
+  case Ctlp_FALSE_c :{
+    result = mdd_zero(mddMgr);
+    leavesArray = array_alloc(Ctlp_Formula_t *, 0);
+    matchfound_top = array_alloc(boolean, 0);
+    matchfound_bot = array_alloc(boolean, 0);
+    matchelement_top = array_alloc(int, 0);
+    matchelement_bot = array_alloc(int, 0);
+    array_insert_last(mdd_t *,mddArray_bot ,mdd_dup(result));
+    array_insert_last(mdd_t *,mddArray_top ,mdd_dup(result));    
+    array_insert(boolean, matchfound_bot, 0 ,FALSE);
+    array_insert(boolean, matchfound_top, 0 ,FALSE);
+    ctlFormula->Bottomstates = mddArray_bot;
+    ctlFormula->matchfound_bot = matchfound_bot;
+    ctlFormula->matchelement_bot = matchelement_bot;
+    ctlFormula->Topstates = mddArray_top;
+    ctlFormula->matchfound_top = matchfound_top;
+    ctlFormula->matchelement_top = matchelement_top;
+    ctlFormula->leaves = leavesArray;
+    break;
+  }
+  case Ctlp_NOT_c :{
+    int i,positionmatch;
+    arrayForEachItem(mdd_t *, leftChild->Bottomstates, i, leftMdd) {
+      /* Now we shoud negate the accurate as well bottom mdds */
+      /* Compute Bottom sets */
+      if(array_fetch(boolean,leftChild->matchfound_bot,i) == FALSE){
+	result = mdd_not(leftMdd);
+	array_insert_last(mdd_t *, mddArray_bot, mdd_dup(result));
+	mdd_free(result);
+      }
+      else{
+	positionmatch =  array_fetch(int, leftChild->matchelement_bot, i);
+	result = mdd_dup(array_fetch(mdd_t *, mddArray_bot, positionmatch));
+	array_insert_last(mdd_t *, mddArray_bot,result);
+      }
+    }
+    arrayForEachItem(mdd_t *, leftChild->Topstates, i, leftMdd) {
+      /* Compute for Top States */
+      if(array_fetch(boolean,leftChild->matchfound_top,i) == FALSE){
+	result = mdd_not(leftMdd);
+	array_insert_last(mdd_t *, mddArray_top, mdd_dup(result));
+	mdd_free(result);
+      }
+      else{
+	positionmatch =  array_fetch(int, leftChild->matchelement_top, i);
+	result = mdd_dup(array_fetch(mdd_t *, mddArray_top, positionmatch));
+	array_insert_last(mdd_t *, mddArray_top, result);
+      }
+    }
+    /* Now attach the array to the ctlFormula */
+    ctlFormula->Bottomstates = mddArray_bot;
+    ctlFormula->matchfound_bot = array_dup(leftChild->matchfound_bot);
+    ctlFormula->matchelement_bot = array_dup(leftChild->matchelement_bot);
+    ctlFormula->Topstates = mddArray_top;
+    ctlFormula->matchfound_top = array_dup(leftChild->matchfound_top);
+    ctlFormula->matchelement_top = array_dup(leftChild->matchelement_top);
+    /* find out the leaves attached to this nodes.*/
+    leavesLeftArray = leftChild->leaves;
+    ctlFormula->leaves = array_dup(leavesLeftArray);    
+    break;
+  }
+  case Ctlp_AND_c:{
+    int number_right_bot = array_n(rightChild->Bottomstates);
+    int number_right_top = array_n(rightChild->Topstates);
+    int number_left_bot = array_n(leftChild->Bottomstates);
+    int number_left_top = array_n(leftChild->Topstates);
+    int i,positionmatch;
+    leavesArray = array_alloc(Ctlp_Formula_t *, 0);
+    matchfound_top = array_alloc(boolean, 0);
+    matchfound_bot = array_alloc(boolean, 0);
+    matchelement_top = array_alloc(int, 0);
+    matchelement_bot = array_alloc(int, 0);
+    /* And operation*/
+    /* for bottom sets */
+    rightMdd = array_fetch(mdd_t *,rightChild->Bottomstates,0);
+    arrayForEachItem(mdd_t *, leftChild->Bottomstates, i, leftMdd) {
+      if (array_fetch(boolean,(leftChild->matchfound_bot),i) == FALSE){
+	result = mdd_and(leftMdd, rightMdd, 1, 1);
+	array_insert_last(mdd_t *, mddArray_bot, result);
+      }
+      else{
+	positionmatch = array_fetch(int,leftChild->matchelement_bot, i);
+	result = mdd_dup(array_fetch(mdd_t *,mddArray_bot,positionmatch));
+	array_insert_last(mdd_t *, mddArray_bot, result);
+      }
+    }
+    leftMdd = array_fetch(mdd_t *,leftChild->Bottomstates,0);
+    for(i=1;i<number_right_bot;i++){
+      if ((array_fetch(boolean,rightChild->matchfound_bot,i) == FALSE)){
+	rightMdd = array_fetch(mdd_t *,rightChild->Bottomstates,i);
+	result = mdd_and(leftMdd, rightMdd, 1, 1);
+	array_insert_last(mdd_t *, mddArray_bot, result);
+      }
+      else{
+	positionmatch = array_fetch(int,rightChild->matchelement_bot, i);
+	result = mdd_dup(array_fetch(mdd_t *, mddArray_bot,(positionmatch + number_left_bot - 1)));
+	array_insert_last(mdd_t *, mddArray_bot, result);
+      }
+    }
+    match_bot(ctlFormula,mddArray_bot,matchfound_bot,matchelement_bot);
+
+    /* for top sets */
+    rightMdd = array_fetch(mdd_t *,rightChild->Topstates,0);
+    arrayForEachItem(mdd_t *, leftChild->Topstates, i, leftMdd) {
+      if (array_fetch(boolean,(leftChild->matchfound_top),i) == FALSE){
+	result = mdd_and(leftMdd, rightMdd, 1, 1);
+	array_insert_last(mdd_t *, mddArray_top, result);
+      }
+      else{
+	positionmatch = array_fetch(int,leftChild->matchelement_top, i);
+	result = mdd_dup(array_fetch(mdd_t *,mddArray_top,positionmatch));
+	array_insert_last(mdd_t *, mddArray_top, result);
+      }
+    }
+    leftMdd = array_fetch(mdd_t *,leftChild->Topstates,0);
+    for(i=1;i<number_right_top;i++){
+      if ((array_fetch(boolean,rightChild->matchfound_top,i) == FALSE)){
+	rightMdd = array_fetch(mdd_t *,rightChild->Topstates,i);
+	result = mdd_and(leftMdd, rightMdd, 1, 1);
+	array_insert_last(mdd_t *, mddArray_top, result);
+      }
+      else{
+	positionmatch = array_fetch(int,rightChild->matchelement_top, i);
+	result = mdd_dup(array_fetch(mdd_t *, mddArray_top,(positionmatch + number_left_top - 1)));
+	array_insert_last(mdd_t *, mddArray_top, result);
+      }
+    }
+    match_top(ctlFormula,mddArray_top,matchfound_top,matchelement_top);
+    /* Now attach the array to the ctlFormula */
+    ctlFormula->Bottomstates = mddArray_bot;
+    ctlFormula->Topstates = mddArray_top;
+    /* find out the leaves attached to this nodes.*/	
+    leavesLeftArray = leftChild->leaves;
+    leavesRightArray = rightChild->leaves;    
+    array_append(leavesArray,leavesLeftArray);
+    array_append(leavesArray,leavesRightArray);
+    ctlFormula->leaves = leavesArray;
+    break;
+  }
+  /* Use of EQ, XOR, THEN, OR is discouraged.	 Please use convert
+     formula to simple existential form. */
+  case Ctlp_EQ_c :{
+    int number_right_bot = array_n(rightChild->Bottomstates);
+    int number_right_top = array_n(rightChild->Topstates);
+    int number_left_bot  = array_n(leftChild->Bottomstates);
+    int number_left_top  = array_n(leftChild->Topstates);
+    int i,positionmatch;
+    leavesArray = array_alloc(Ctlp_Formula_t *, 0);
+    matchfound_top = array_alloc(boolean, 0);
+    matchfound_bot = array_alloc(boolean, 0);
+    matchelement_top = array_alloc(int, 0);
+    matchelement_bot = array_alloc(int, 0);
+    /* for bottom sets */
+    rightMdd= array_fetch(mdd_t *,rightChild->Bottomstates,0);
+    arrayForEachItem(mdd_t *, leftChild->Bottomstates, i, leftMdd) {
+      if (array_fetch(boolean,(leftChild->matchfound_bot),i) == FALSE){
+	result = mdd_xnor(leftMdd,rightMdd);
+	array_insert_last(mdd_t *, mddArray_bot, result);
+      }
+      else{
+	positionmatch = array_fetch(int,leftChild->matchelement_bot, i);
+	result = mdd_dup(array_fetch(mdd_t *, mddArray_bot, positionmatch));
+	array_insert_last(mdd_t *, mddArray_bot, result);
+      }
+    }
+    leftMdd = array_fetch(mdd_t *,leftChild->Bottomstates,0);
+    for(i=1;i<number_right_bot;i++){
+      if ((array_fetch(boolean,rightChild->matchfound_bot,i) == FALSE)){
+	rightMdd = array_fetch(mdd_t *,rightChild->Bottomstates,i);
+	result = mdd_xnor(leftMdd,rightMdd );
+	array_insert_last(mdd_t *, mddArray_bot, result);
+      }
+      else{
+	positionmatch = array_fetch(int,rightChild->matchelement_bot, i);
+	result = mdd_dup(array_fetch(mdd_t *, mddArray_bot,(positionmatch+ number_left_bot - 1)));
+	array_insert_last(mdd_t *, mddArray_bot, result);
+      }
+    }
+    match_bot(ctlFormula,mddArray_bot,matchfound_bot,matchelement_bot);
+
+    /* for top sets */
+    rightMdd= array_fetch(mdd_t *,rightChild->Topstates,0);
+    arrayForEachItem(mdd_t *, leftChild->Topstates, i, leftMdd) {
+      if (array_fetch(boolean,(leftChild->matchfound_top),i) == FALSE){
+	result = mdd_xnor(leftMdd,rightMdd);
+	array_insert_last(mdd_t *, mddArray_top, result);
+      }
+      else{
+	positionmatch = array_fetch(int,leftChild->matchelement_top, i);
+	result = mdd_dup(array_fetch(mdd_t *, mddArray_top, positionmatch));
+	array_insert_last(mdd_t *, mddArray_top, result);
+      }
+    }
+    leftMdd = array_fetch(mdd_t *,leftChild->Topstates,0);
+    for(i=1;i<number_right_top;i++){
+      if ((array_fetch(boolean,rightChild->matchfound_top,i) == FALSE)){
+	rightMdd = array_fetch(mdd_t *,rightChild->Topstates,i);
+	result = mdd_xnor(leftMdd,rightMdd );
+	array_insert_last(mdd_t *, mddArray_top, result);
+      }
+      else{
+	positionmatch = array_fetch(int,rightChild->matchelement_top, i);
+	result = mdd_dup(array_fetch(mdd_t *, mddArray_top,(positionmatch+ number_left_top - 1)));
+	array_insert_last(mdd_t *, mddArray_top, result);
+      }
+    }
+    match_top(ctlFormula,mddArray_top,matchfound_top,matchelement_top);
+
+    /* Now attach the array to the ctlFormula */
+    ctlFormula->Bottomstates = mddArray_bot;
+    ctlFormula->Topstates = mddArray_top;
+    /* find out the leaves attached to this nodes.*/	
+    leavesLeftArray = leftChild->leaves;
+    leavesRightArray = rightChild->leaves;    
+    array_append(leavesArray,leavesLeftArray);
+    array_append(leavesArray,leavesRightArray);
+    ctlFormula->leaves = leavesArray;
+    break;
+  }
+  case Ctlp_XOR_c :{
+    int number_right_bot = array_n(rightChild->Bottomstates);
+    int number_right_top = array_n(rightChild->Topstates);
+    int number_left_bot  = array_n(leftChild->Bottomstates);
+    int number_left_top  = array_n(leftChild->Topstates);
+    int i,positionmatch;
+    leavesArray = array_alloc(Ctlp_Formula_t *, 0);
+    matchfound_top = array_alloc(boolean, 0);
+    matchfound_bot = array_alloc(boolean, 0);
+    matchelement_top = array_alloc(int, 0);
+    matchelement_bot = array_alloc(int, 0);
+    /* for bottom sets */
+    rightMdd = array_fetch(mdd_t *,rightChild->Bottomstates,0);
+    arrayForEachItem(mdd_t *, leftChild->Bottomstates, i, leftMdd) {
+      if (array_fetch(boolean,(leftChild->matchfound_bot),i) == FALSE){
+	result = mdd_xor(leftMdd,rightMdd);
+	array_insert_last(mdd_t *, mddArray_bot, result);
+      }
+      else{
+	positionmatch = array_fetch(int,leftChild->matchelement_bot, i);
+	result = mdd_dup(array_fetch(mdd_t *,mddArray_bot,positionmatch));
+	array_insert_last(mdd_t *, mddArray_bot, result);
+      }
+    }
+    leftMdd = array_fetch(mdd_t *,leftChild->Bottomstates,0);
+    for(i=1;i<number_right_bot;i++){
+      if ((array_fetch(boolean,rightChild->matchfound_bot,i) == FALSE)){
+	rightMdd = array_fetch(mdd_t *,rightChild->Bottomstates,i);
+	result = mdd_xor(leftMdd,rightMdd );
+	array_insert_last(mdd_t *, mddArray_bot, result);
+      }
+      else{
+	positionmatch = array_fetch(int,rightChild->matchelement_bot, i);
+	result = mdd_dup(array_fetch(mdd_t *, mddArray_bot,(positionmatch+ number_left_bot - 1)));
+	array_insert_last(mdd_t *, mddArray_bot, result);
+      }
+    }
+    match_bot(ctlFormula,mddArray_bot,matchfound_bot,matchelement_bot);
+
+    /* for top sets */
+    rightMdd = array_fetch(mdd_t *,rightChild->Topstates,0);
+    arrayForEachItem(mdd_t *, leftChild->Topstates, i, leftMdd) {
+      if (array_fetch(boolean,(leftChild->matchfound_top),i) == FALSE){
+	result = mdd_xor(leftMdd,rightMdd);
+	array_insert_last(mdd_t *, mddArray_top, result);
+      }
+      else{
+	positionmatch = array_fetch(int,leftChild->matchelement_top, i);
+	result = mdd_dup(array_fetch(mdd_t *,mddArray_top,positionmatch));
+	array_insert_last(mdd_t *, mddArray_top, result);
+      }
+    }
+    leftMdd = array_fetch(mdd_t *,leftChild->Topstates,0);
+    for(i=1;i<number_right_top;i++){
+      if ((array_fetch(boolean,rightChild->matchfound_top,i) == FALSE)){
+	rightMdd = array_fetch(mdd_t *,rightChild->Topstates,i);
+	result = mdd_xor(leftMdd,rightMdd );
+	array_insert_last(mdd_t *, mddArray_top, result);
+      }
+      else{
+	positionmatch = array_fetch(int,rightChild->matchelement_top, i);
+	result = mdd_dup(array_fetch(mdd_t *, mddArray_top,(positionmatch + number_left_top - 1)));
+	array_insert_last(mdd_t *, mddArray_top, result);
+      }
+    }
+    match_top(ctlFormula,mddArray_top,matchfound_top,matchelement_top);
+
+    /* Now attach the array to the ctlFormula */
+    ctlFormula->Bottomstates = mddArray_bot;
+    ctlFormula->Topstates = mddArray_top;
+    /* find out the leaves attached to this nodes.*/	
+    leavesLeftArray = leftChild->leaves;
+    leavesRightArray = rightChild->leaves;    
+    array_append(leavesArray,leavesLeftArray);
+    array_append(leavesArray,leavesRightArray);
+    ctlFormula->leaves = leavesArray;
+    break;
+  }
+
+  case Ctlp_THEN_c :{
+    int number_right_bot = array_n(rightChild->Bottomstates);
+    int number_right_top = array_n(rightChild->Topstates);
+    int number_left_bot = array_n(leftChild->Bottomstates);
+    int number_left_top = array_n(leftChild->Topstates);
+    int i,positionmatch;
+    leavesArray = array_alloc(Ctlp_Formula_t *, 0);
+    matchfound_top = array_alloc(boolean, 0);
+    matchfound_bot = array_alloc(boolean, 0);
+    matchelement_top = array_alloc(int, 0);
+    matchelement_bot = array_alloc(int, 0);
+    /* bottom sets */
+    rightMdd = array_fetch(mdd_t *,rightChild->Bottomstates,0);
+    arrayForEachItem(mdd_t *, leftChild->Bottomstates, i, leftMdd) {
+      if (array_fetch(boolean,(leftChild->matchfound_bot),i) == FALSE){
+	result = mdd_or(leftMdd ,rightMdd,0,1);
+	array_insert_last(mdd_t *, mddArray_bot, result);
+      }
+      else{
+	positionmatch = array_fetch(int,leftChild->matchelement_bot, i);
+	result = mdd_dup(array_fetch(mdd_t *,mddArray_bot,positionmatch));
+	array_insert_last(mdd_t *, mddArray_bot, result);
+      }
+    }
+
+    leftMdd = array_fetch(mdd_t *,leftChild->Bottomstates,0);
+    for(i=1;i<number_right_bot;i++){
+      if ((array_fetch(boolean,rightChild->matchfound_bot,i) == FALSE)){
+      rightMdd = array_fetch(mdd_t *,rightChild->Bottomstates,i);
+      result = mdd_or(leftMdd,rightMdd ,0,1);
+      array_insert_last(mdd_t *, mddArray_bot, result);
+    }
+      else{
+	positionmatch = array_fetch(int,rightChild->matchelement_bot, i);
+	result = mdd_dup(array_fetch(mdd_t *, mddArray_bot, (positionmatch + number_left_bot - 1)));
+	array_insert_last(mdd_t *, mddArray_bot, result);
+      }
+    }
+    match_bot(ctlFormula,mddArray_bot,matchfound_bot,matchelement_bot);
+    /* top sets */
+    rightMdd = array_fetch(mdd_t *,rightChild->Topstates,0);
+    arrayForEachItem(mdd_t *, leftChild->Topstates, i, leftMdd) {
+      if (array_fetch(boolean,(leftChild->matchfound_top),i) == FALSE){
+	result = mdd_or(leftMdd ,rightMdd,0,1);
+	array_insert_last(mdd_t *, mddArray_top, result);
+      }
+      else{
+	positionmatch = array_fetch(int,leftChild->matchelement_top, i);
+	result = mdd_dup(array_fetch(mdd_t *,mddArray_top,positionmatch));
+	array_insert_last(mdd_t *, mddArray_top, result);
+      }
+    }
+    leftMdd = array_fetch(mdd_t *,leftChild->Topstates,0);
+    for(i=1;i<number_right_top;i++){
+      if ((array_fetch(boolean,rightChild->matchfound_top,i) == FALSE)){
+      rightMdd = array_fetch(mdd_t *,rightChild->Topstates,i);
+      result = mdd_or(leftMdd,rightMdd ,0,1);
+      array_insert_last(mdd_t *, mddArray_top, result);
+    }
+      else{
+	positionmatch = array_fetch(int,rightChild->matchelement_top, i);
+	result = mdd_dup(array_fetch(mdd_t *, mddArray_top, (positionmatch + number_left_top - 1)));
+	array_insert_last(mdd_t *, mddArray_top, result);
+      }
+    }
+    match_top(ctlFormula,mddArray_top,matchfound_top,matchelement_top);
+    
+    /* Now attach the array to the ctlFormula */
+    ctlFormula->Bottomstates = mddArray_bot;
+    ctlFormula->Topstates = mddArray_top;
+    /* find out the leaves attached to this nodes.*/	
+    leavesLeftArray = leftChild->leaves;
+    leavesRightArray = rightChild->leaves;    
+    array_append(leavesArray,leavesLeftArray);
+    array_append(leavesArray,leavesRightArray);
+    ctlFormula->leaves = leavesArray;
+    break;
+  }
+  case Ctlp_OR_c:{
+    int number_right_bot = array_n(rightChild->Bottomstates);
+    int number_right_top = array_n(rightChild->Topstates);
+    int number_left_bot = array_n(leftChild->Bottomstates);
+    int number_left_top = array_n(leftChild->Topstates);
+    int i,positionmatch;
+    leavesArray = array_alloc(Ctlp_Formula_t *, 0);
+    matchfound_top = array_alloc(boolean, 0);
+    matchfound_bot = array_alloc(boolean, 0);
+    matchelement_top = array_alloc(int, 0);
+    matchelement_bot = array_alloc(int, 0);
+
+    /* OR operation*/
+    /* bottom sets */
+    rightMdd = array_fetch(mdd_t *,rightChild->Bottomstates,0);
+    arrayForEachItem(mdd_t *, leftChild->Bottomstates, i, leftMdd) {
+      if (array_fetch(boolean,(leftChild->matchfound_bot),i) == FALSE){
+	result = mdd_or(leftMdd,rightMdd,1,1);
+	array_insert_last(mdd_t *, mddArray_bot, result);
+      }
+      else{
+	positionmatch = array_fetch(int,leftChild->matchelement_bot, i);
+	result = mdd_dup(array_fetch(mdd_t *, mddArray_bot, positionmatch));
+	array_insert_last(mdd_t *, mddArray_bot, result);
+      }
+    }
+
+    leftMdd = array_fetch(mdd_t *,leftChild->Bottomstates,0);
+    for(i=1;i<number_right_bot;i++){
+      if ((array_fetch(boolean,rightChild->matchfound_bot,i) == FALSE)){
+      rightMdd = array_fetch(mdd_t *,rightChild->Bottomstates,i);
+      result = mdd_or(leftMdd,rightMdd ,1,1);
+      array_insert_last(mdd_t *, mddArray_bot, result);
+      }
+      else{
+	positionmatch = array_fetch(int,rightChild->matchelement_bot, i);
+	result = mdd_dup(array_fetch(mdd_t *, mddArray_bot, (positionmatch + number_left_bot - 1)));
+	array_insert_last(mdd_t *, mddArray_bot, result);
+      }
+    }
+
+    match_bot(ctlFormula,mddArray_bot,matchfound_bot,matchelement_bot);
+
+    /* top sets */
+    rightMdd = array_fetch(mdd_t *,rightChild->Topstates,0);
+    arrayForEachItem(mdd_t *, leftChild->Topstates, i, leftMdd) {
+      if (array_fetch(boolean,(leftChild->matchfound_top),i) == FALSE){
+	result = mdd_or(leftMdd,rightMdd,1,1);
+	array_insert_last(mdd_t *, mddArray_top, result);
+      }
+      else{
+	positionmatch = array_fetch(int,leftChild->matchelement_top, i);
+	result = mdd_dup(array_fetch(mdd_t *, mddArray_top, positionmatch));
+	array_insert_last(mdd_t *, mddArray_top, result);
+      }
+    }
+
+    leftMdd = array_fetch(mdd_t *,leftChild->Topstates,0);
+    for(i=1;i<number_right_top;i++){
+      if ((array_fetch(boolean,rightChild->matchfound_top,i) == FALSE)){
+      rightMdd = array_fetch(mdd_t *,rightChild->Topstates,i);
+      result = mdd_or(leftMdd,rightMdd ,1,1);
+      array_insert_last(mdd_t *, mddArray_top, result);
+      }
+      else{
+	positionmatch = array_fetch(int,rightChild->matchelement_top, i);
+	result = mdd_dup(array_fetch(mdd_t *, mddArray_top, (positionmatch + number_left_top - 1)));
+	array_insert_last(mdd_t *, mddArray_top, result);
+      }
+    }
+
+    match_top(ctlFormula,mddArray_top,matchfound_top,matchelement_top);
+    /* Now attach the array to the ctlFormula */
+    ctlFormula->Topstates = mddArray_top;
+    ctlFormula->Bottomstates = mddArray_bot;
+    /* ctlFormula->states = array_fetch(mdd_t *, mddArray, 0); */
+    /* find out the leaves attached to this nodes.*/	
+    leavesLeftArray = leftChild->leaves;
+    leavesRightArray = rightChild->leaves;    
+    array_append(leavesArray,leavesLeftArray);
+    array_append(leavesArray,leavesRightArray);
+    ctlFormula->leaves = leavesArray;
+    break;
+  }
+  case Ctlp_EX_c:{
+    int i,positionmatch;
+    if (ctlFormula->negation_parity == Ctlp_Even_c) {
+      /* bottom sets shoud be computed first i.e underapproximations */
+      arrayForEachItem(mdd_t *, leftChild->Bottomstates, i, leftMdd) {
+	if(array_fetch(boolean,leftChild->matchfound_bot,i) == FALSE){
+	  result = Mc_FsmEvaluateEXFormula(modelFsm, leftMdd, fairStates,
+					   careStatesArray, verbosity, dcLevel);
+	  array_insert_last(mdd_t *, mddArray_bot, result);
+	}
+	else{
+	  positionmatch =  array_fetch(int, leftChild->matchelement_bot, i);
+	  result = mdd_dup(array_fetch(mdd_t *, mddArray_bot, positionmatch));
+	  array_insert_last(mdd_t *, mddArray_bot, result);
+	}
+      }
+      result = array_fetch(mdd_t *, mddArray_bot, 0); /* exact set */
+    }
+    else{
+      /* top sets should be computed first i.e., underapproximations */
+      arrayForEachItem(mdd_t *, leftChild->Topstates, i, leftMdd) {
+	if(array_fetch(boolean,leftChild->matchfound_top,i) == FALSE){
+	  result = Mc_FsmEvaluateEXFormula(modelFsm, leftMdd, fairStates,
+					   careStatesArray, verbosity, dcLevel);
+	  array_insert_last(mdd_t *, mddArray_top, result);
+	}
+	else{
+	  positionmatch =  array_fetch(int, leftChild->matchelement_top, i);
+	  result = mdd_dup(array_fetch(mdd_t *, mddArray_top, positionmatch));
+	  array_insert_last(mdd_t *, mddArray_top, result);
+	}
+      }
+      result = array_fetch(mdd_t *, mddArray_top, 0); /* exact set */
+    }
+    if(McCheckEarlyTerminationForUnderapprox(earlyTermination,result,careStatesArray)){
+      if (ctlFormula->negation_parity == Ctlp_Even_c) {
+	ctlFormula->Bottomstates = mddArray_bot;
+	arrayForEachItem(mdd_t *, leftChild->Topstates, i, leftMdd) {
+	  array_insert_last(mdd_t *, mddArray_top, mdd_dup(result));
+	}
+	ctlFormula->Topstates = mddArray_top;
+	ctlFormula->matchfound_bot = array_dup(leftChild->matchfound_bot);
+	ctlFormula->matchelement_bot = array_dup(leftChild->matchelement_bot);
+	matchfound_top = array_alloc(boolean, 0);
+	matchelement_top = array_alloc(int, 0);
+	match_top(ctlFormula,mddArray_top,matchfound_top,matchelement_top);
+      }
+      else{
+	ctlFormula->Topstates = mddArray_top;
+	arrayForEachItem(mdd_t *, leftChild->Bottomstates, i, leftMdd) {
+	  array_insert_last(mdd_t *, mddArray_bot, mdd_dup(result));
+	}
+	ctlFormula->Bottomstates = mddArray_bot;
+	ctlFormula->matchfound_top = array_dup(leftChild->matchfound_bot);
+	ctlFormula->matchelement_top = array_dup(leftChild->matchelement_bot);
+	matchfound_bot = array_alloc(int, 0);
+	matchelement_bot = array_alloc(int, 0);
+	match_bot(ctlFormula,mddArray_bot,matchfound_bot,matchelement_bot);
+      }
+      /* find out the leaves attached to this nodes.*/
+      leavesLeftArray = leftChild->leaves;
+      ctlFormula->leaves = array_dup(leavesLeftArray);    
+      break;
+    }
+    if (ctlFormula->negation_parity == Ctlp_Even_c) {
+      /* top sets */
+      arrayForEachItem(mdd_t *, leftChild->Topstates, i, leftMdd) {
+	if(array_fetch(boolean,leftChild->matchfound_top,i) == FALSE){
+	  result = Mc_FsmEvaluateEXFormula(modelFsm, leftMdd, fairStates,
+					   careStatesArray, verbosity, dcLevel);
+	  array_insert_last(mdd_t *, mddArray_top, result);
+	}
+	else{
+	  positionmatch =  array_fetch(int, leftChild->matchelement_top, i);
+	  result = mdd_dup(array_fetch(mdd_t *, mddArray_top, positionmatch));
+	  array_insert_last(mdd_t *, mddArray_top, result);
+	}
+
+      }
+    }
+    else {
+      arrayForEachItem(mdd_t *, leftChild->Bottomstates, i, leftMdd) {
+	if(array_fetch(boolean,leftChild->matchfound_bot,i) == FALSE){
+	  result = Mc_FsmEvaluateEXFormula(modelFsm, leftMdd, fairStates,
+					   careStatesArray, verbosity, dcLevel);
+	  array_insert_last(mdd_t *, mddArray_bot, result);
+	}
+	else{
+	  positionmatch =  array_fetch(int, leftChild->matchelement_bot, i);
+	  result = mdd_dup(array_fetch(mdd_t *, mddArray_bot, positionmatch));
+	  array_insert_last(mdd_t *, mddArray_bot, result);
+	}
+
+      }
+    }
+    /* Now attach the array to the ctlFormula */
+    ctlFormula->Bottomstates = mddArray_bot;
+    ctlFormula->matchfound_bot = array_dup(leftChild->matchfound_bot);
+    ctlFormula->matchelement_bot = array_dup(leftChild->matchelement_bot);
+    ctlFormula->Topstates = mddArray_top;
+    ctlFormula->matchfound_top = array_dup(leftChild->matchfound_top);
+    ctlFormula->matchelement_top = array_dup(leftChild->matchelement_top);
+    /* find out the leaves attached to this nodes.*/
+    leavesLeftArray = leftChild->leaves;
+    ctlFormula->leaves = array_dup(leavesLeftArray);    
+    break;
+    }
+
+  case Ctlp_EU_c:{
+    array_t *onionRings = NIL(array_t);
+    array_t *MergeOnionRings = NIL(array_t);
+    array_t *ExactOnionRings = NIL(array_t);
+    array_t *NewOnionRings = NIL(array_t); /* array of mdd_t */
+    boolean fixpoint;
+    int number_left_bot = array_n(leftChild->Bottomstates);
+    int number_right_bot = array_n(rightChild->Bottomstates);
+    int number_left_top = array_n(leftChild->Topstates);
+    int number_right_top = array_n(rightChild->Topstates);
+    int i;
+    int j = 1;
+    mdd_t *approx_under = NIL(mdd_t);
+    array_t *botrings = NIL(array_t);
+    array_t *toprings = NIL(array_t);
+    leavesArray = array_alloc(Ctlp_Formula_t *, 0);
+    matchfound_top = array_alloc(boolean, 0);
+    matchfound_bot = array_alloc(boolean, 0);
+    matchelement_top = array_alloc(int, 0);
+    matchelement_bot = array_alloc(int, 0);
+    approx = Ctlp_FormulaObtainApproxStates( ctlFormula, Ctlp_Underapprox_c );
+    onionRings = NIL(array_t);
+    if (buildOnionRings) {
+      MergeOnionRings = array_alloc(mdd_t *, 0);
+      botrings = array_alloc(array_t*,0);
+      toprings = array_alloc(array_t*,0);
+    }
+    if (ctlFormula->negation_parity == Ctlp_Even_c) {
+      rightMdd = array_fetch(mdd_t *,rightChild->Bottomstates,0);
+      result_underapprox = mdd_zero(mddMgr);
+      /* Compute the bottom mdds first which provide the underapproximation
+       * to the exact set*/
+      for(i=1;i<number_left_bot;i++) {
+	if (buildOnionRings)
+	  onionRings = array_alloc(mdd_t *, 0);
+	leftMdd = array_fetch(mdd_t *,leftChild->Bottomstates,i);
+	result = Mc_FsmEvaluateEUFormula(modelFsm,leftMdd,
+					 rightMdd,
+					 approx, fairStates,
+					 careStatesArray,
+					 earlyTermination, hintsArray,
+					 hintType, onionRings,
+					 verbosity, dcLevel, &fixpoint);
+	array_insert(mdd_t *, mddArray_bot, j, result);
+	if (buildOnionRings) {
+	  if(i==1) {
+	    mdd_array_free(MergeOnionRings);
+	    MergeOnionRings = mdd_array_duplicate(onionRings);
+	    /* saving the bottom computation onion rings */
+	    array_insert(array_t*,botrings,j,onionRings);
+	  }
+	  else {
+	    MergeOnionRings = GenerateOnionRings(MergeOnionRings,onionRings);
+	    /* saving the bottom computation onion rings */
+	    array_insert(array_t*,botrings,j,onionRings);
+	  }
+	}
+	j++;
+	result_new = mdd_or(result,result_underapprox,1,1);
+	mdd_free(result_underapprox);
+	result_underapprox = result_new;
+      }
+      leftMdd = array_fetch(mdd_t *,leftChild->Bottomstates,0);
+      for(i=1;i<number_right_bot;i++) {
+	if (buildOnionRings)
+	  onionRings = array_alloc(mdd_t *, 0);
+	rightMdd = array_fetch(mdd_t *,rightChild->Bottomstates,i);
+	result = Mc_FsmEvaluateEUFormula(modelFsm, leftMdd,
+					 rightMdd,
+					 approx, fairStates,
+					 careStatesArray,
+					 earlyTermination, hintsArray,
+					 hintType, onionRings,
+					 verbosity, dcLevel, &fixpoint);
+	array_insert(mdd_t *, mddArray_bot, j, result);
+	if (buildOnionRings) {
+	  if(i==1) {
+	    mdd_array_free(MergeOnionRings);
+	    MergeOnionRings = mdd_array_duplicate(onionRings);
+	    /* saving the bottom computation onion rings */
+	    array_insert(array_t*,botrings,j,onionRings);
+	  }
+	  else {
+	    MergeOnionRings = GenerateOnionRings(MergeOnionRings,onionRings);
+	    /* saving the bottom computation onion rings */
+	    array_insert(array_t*,botrings,j,onionRings);
+	  }
+	}
+	j++;
+	result_new = mdd_or(result,result_underapprox,1,1);
+	mdd_free(result_underapprox);
+	result_underapprox = result_new;
+      }
+      /* Use the under approximations to calculate the exact set. */
+      if (approx != NIL(mdd_t)) {
+	mdd_t *tmp = mdd_or(result_underapprox,approx,1,1);
+	mdd_free(approx);
+	mdd_free(result_underapprox);
+	approx = tmp;
+      } else {
+	approx = result_underapprox; 
+      }
+      if (buildOnionRings) {
+	onionRings = array_alloc(mdd_t *, 0);
+      }
+      rightMdd = array_fetch(mdd_t *,rightChild->Bottomstates,0);
+      leftMdd = array_fetch(mdd_t *,leftChild->Bottomstates,0);
+      result = Mc_FsmEvaluateEUFormula(modelFsm,leftMdd,
+				       rightMdd,
+				       approx, fairStates,
+				       careStatesArray,
+				       earlyTermination, hintsArray,
+				       hintType, onionRings,
+				       verbosity, dcLevel, &fixpoint);
+      array_insert(mdd_t *, mddArray_bot, 0, mdd_dup(result));
+      array_insert(mdd_t *, mddArray_top, 0, result);
+      if (buildOnionRings) {
+	MergeOnionRings = GenerateOnionRings(MergeOnionRings,onionRings);
+	mdd_array_free(onionRings);
+	Ctlp_FormulaSetDbgInfo(ctlFormula, (void *) MergeOnionRings,
+			       McFormulaFreeDebugData);
+	array_insert(array_t *,botrings,0,mdd_array_duplicate(MergeOnionRings));
+	array_insert(array_t *,toprings,0,mdd_array_duplicate(MergeOnionRings));
+      }
+      result = array_fetch(mdd_t *,mddArray_bot,0);
+      if(McCheckEarlyTerminationForUnderapprox(earlyTermination,result,careStatesArray)) {
+	leavesLeftArray = leftChild->leaves;
+	array_append(leavesArray,leavesLeftArray);
+	leavesRightArray = rightChild->leaves;
+	array_append(leavesArray,leavesRightArray);
+	ctlFormula->leaves = leavesArray;
+	j=1;
+	for(i=1;i<number_left_top;i++) {
+	  array_insert(mdd_t *, mddArray_top, j, mdd_dup(result));
+	  if (buildOnionRings) {
+	    array_insert(array_t *,toprings,j,
+			 mdd_array_duplicate(MergeOnionRings));
+	  }
+	  j++;
+	} 
+	for(i=1;i<number_right_top;i++) {
+	  array_insert(mdd_t *, mddArray_top, j, mdd_dup(result));
+	  if (buildOnionRings){
+	    array_insert(array_t *,toprings,j,
+			 mdd_array_duplicate(MergeOnionRings));
+	  }
+	  j++;
+      }
+	ctlFormula->Bottomstates = mddArray_bot;
+	ctlFormula->Topstates = mddArray_top;
+	match_bot(ctlFormula,mddArray_bot,matchfound_bot,matchelement_bot);
+	match_top(ctlFormula,mddArray_top,matchfound_top,matchelement_top);
+	if (buildOnionRings) {
+	  ctlFormula->BotOnionRings = botrings;
+	  ctlFormula->TopOnionRings = toprings;
+	}
+	mdd_free(approx);
+	break; /* bottom failing */
+      }
+      /* top sets
+       * we can use the exact set as an approximation to compute the top
+       * set. */
+      rightMdd = array_fetch(mdd_t *,rightChild->Topstates,0);
+      j=1;
+      if (buildOnionRings) 
+	ExactOnionRings = mdd_array_duplicate(MergeOnionRings);
+      /* Compute the Top mdds now */
+      for(i=1;i<number_left_top;i++) {
+	if (buildOnionRings)
+	  onionRings = array_alloc(mdd_t *, 0);
+	leftMdd = array_fetch(mdd_t *,leftChild->Topstates,i);
+	approx_under = array_fetch(mdd_t *,mddArray_bot,0);
+	result = Mc_FsmEvaluateEUFormula(modelFsm,leftMdd,
+					 rightMdd,
+					 approx_under, fairStates,
+					 careStatesArray,
+					 earlyTermination, hintsArray,
+					 hintType, onionRings,
+					 verbosity, dcLevel, &fixpoint);
+	array_insert(mdd_t *, mddArray_top, j, result);
+	if (buildOnionRings) {
+	  array_t *dupOnionRings = mdd_array_duplicate(ExactOnionRings);
+	  NewOnionRings = GenerateOnionRings(dupOnionRings,onionRings);
+	  /* saving the bottom computation onion rings */
+	  array_insert(array_t*,toprings,j,NewOnionRings);
+	  mdd_array_free(onionRings);
+	}
+	j++;
+      }
+      leftMdd = array_fetch(mdd_t *,leftChild->Topstates,0);
+      for(i=1;i<number_right_top;i++) {
+	if (buildOnionRings)
+	  onionRings = array_alloc(mdd_t *, 0);
+	rightMdd = array_fetch(mdd_t *,rightChild->Topstates,i);
+	approx_under = array_fetch(mdd_t *,mddArray_top,0);
+	result = Mc_FsmEvaluateEUFormula(modelFsm, leftMdd,
+					 rightMdd,
+					 approx_under, fairStates,
+					 careStatesArray,
+					 earlyTermination, hintsArray,
+					 hintType, onionRings,
+					 verbosity, dcLevel, &fixpoint);
+	array_insert(mdd_t *, mddArray_top, j, result);
+	if (buildOnionRings) {
+	  array_t *dupOnionRings = mdd_array_duplicate(ExactOnionRings);
+	  NewOnionRings = GenerateOnionRings(dupOnionRings,onionRings);
+	  /* saving the bottom computation onion rings */
+	  array_insert(array_t*,toprings,j,NewOnionRings);
+	  mdd_array_free(onionRings);
+	}
+	j++;
+      }
+    }
+    else {
+      /* The negation parity is odd. So the top sets will provide
+	 underapproximations now. */
+      rightMdd = array_fetch(mdd_t *,rightChild->Topstates,0);
+      result_underapprox = mdd_zero(mddMgr);
+      /* Compute the top mdds first */
+      for(i=1;i<number_left_top;i++) {
+	if (buildOnionRings)
+	  onionRings = array_alloc(mdd_t *, 0);
+	leftMdd = array_fetch(mdd_t *,leftChild->Topstates,i);
+	result = Mc_FsmEvaluateEUFormula(modelFsm,leftMdd,
+					 rightMdd,
+					 NIL(mdd_t), fairStates,
+					 careStatesArray,
+					 earlyTermination, hintsArray,
+					 hintType, onionRings,
+					 verbosity, dcLevel, &fixpoint);
+	array_insert(mdd_t *, mddArray_top, j, result);
+	if (buildOnionRings){
+	  if(i==1){
+	    mdd_array_free(MergeOnionRings);
+	    MergeOnionRings = mdd_array_duplicate(onionRings);
+	    array_insert(array_t*,toprings,j,onionRings); /* saving the bottom computation onion rings */
+	  }
+	  else {
+	    array_insert(array_t*,toprings,j,onionRings); /* saving the bottom computation onion rings */
+	    MergeOnionRings=GenerateOnionRings(MergeOnionRings,onionRings);
+	  }
+	}
+	j++;
+	result_new = mdd_or(result,result_underapprox,1,1);
+	mdd_free(result_underapprox);
+	result_underapprox = result_new;
+      }
+      leftMdd = array_fetch(mdd_t *,leftChild->Topstates,0);
+      for(i=1;i<number_right_top;i++) {
+	if (buildOnionRings)
+	  onionRings = array_alloc(mdd_t *, 0);
+	rightMdd = array_fetch(mdd_t *,rightChild->Topstates,i);
+	result = Mc_FsmEvaluateEUFormula(modelFsm, leftMdd,
+					 rightMdd,
+					 NIL(mdd_t), fairStates,
+					 careStatesArray,
+					 earlyTermination, hintsArray,
+					 hintType, onionRings,
+					 verbosity, dcLevel, &fixpoint);
+	array_insert(mdd_t *, mddArray_top, j, result);
+	if (buildOnionRings) {
+	  if(j==1){
+	    mdd_array_free(MergeOnionRings);
+	    MergeOnionRings = mdd_array_duplicate(onionRings);
+	    array_insert(array_t*,toprings,j,onionRings); /* saving the top computation onion rings */
+	  }
+	  else {
+	    MergeOnionRings = GenerateOnionRings(MergeOnionRings,onionRings);
+	    array_insert(array_t*,toprings,j,onionRings); /* saving the bottom computation onion rings */
+	  }
+	}
+	j++;
+	result_new = mdd_or(result,result_underapprox,1,1);
+	mdd_free(result_underapprox);
+	result_underapprox = result_new;
+      }
+      /* Use the under approximations to calculate the exact set. */
+      if (approx != NIL(mdd_t)) {
+	mdd_t *tmp = mdd_or(result_underapprox,approx,1,1);
+	mdd_free(approx);
+	mdd_free(result_underapprox);
+	approx = tmp;
+      } else {
+	approx = result_underapprox; 
+      }
+      if (buildOnionRings) {
+	onionRings = array_alloc(mdd_t *, 0);
+      }
+      /* exact set computation */
+      rightMdd = array_fetch(mdd_t *,rightChild->Topstates,0);
+      leftMdd = array_fetch(mdd_t *,leftChild->Topstates,0);
+      result = Mc_FsmEvaluateEUFormula(modelFsm,leftMdd,
+				       rightMdd,
+				       approx, fairStates,
+				       careStatesArray,
+				       earlyTermination, hintsArray,
+				       hintType, onionRings,
+				       verbosity, dcLevel, &fixpoint);
+      array_insert(mdd_t *, mddArray_bot, 0, mdd_dup(result));
+      array_insert(mdd_t *, mddArray_top, 0, result);
+      if (buildOnionRings) {
+	MergeOnionRings = GenerateOnionRings(MergeOnionRings,onionRings);
+	mdd_array_free(onionRings);
+	Ctlp_FormulaSetDbgInfo(ctlFormula, (void *) MergeOnionRings,
+			       McFormulaFreeDebugData);
+	array_insert(array_t *,botrings,0,
+		     mdd_array_duplicate(MergeOnionRings));
+	array_insert(array_t *,toprings,0,
+		     mdd_array_duplicate(MergeOnionRings));
+      }
+      result = array_fetch(mdd_t *,mddArray_bot,0);
+      if(McCheckEarlyTerminationForUnderapprox(earlyTermination,result,careStatesArray)) {
+	leavesLeftArray = leftChild->leaves;
+	array_append(leavesArray,leavesLeftArray);
+	leavesRightArray = rightChild->leaves;
+	array_append(leavesArray,leavesRightArray);
+	ctlFormula->leaves = leavesArray;
+	j=1;
+	for(i=1;i<number_left_bot;i++) {
+	  array_insert(mdd_t *, mddArray_bot, j, mdd_dup(result));
+	  if (buildOnionRings){
+	    array_insert(array_t *,botrings,j,
+			 mdd_array_duplicate(MergeOnionRings));
+	  }
+	  j++;
+	} 
+	for(i=1;i<number_right_bot;i++) {
+	  array_insert(mdd_t *, mddArray_bot, j, mdd_dup(result));
+	  if (buildOnionRings){
+	    array_insert(array_t *,botrings,j,
+			 mdd_array_duplicate(MergeOnionRings));
+	  }
+	  j++;
+	}
+	match_bot(ctlFormula,mddArray_bot,matchfound_bot,matchelement_bot);
+	match_top(ctlFormula,mddArray_top,matchfound_top,matchelement_top);
+	ctlFormula->Bottomstates = mddArray_bot;
+	ctlFormula->Topstates = mddArray_top;
+	if (buildOnionRings){
+	  ctlFormula->BotOnionRings = botrings;
+	  ctlFormula->TopOnionRings = toprings;
+	}
+	assert(approx != NIL(mdd_t));
+	mdd_free(approx);
+	break; /* bottom failing */
+      }
+      if (buildOnionRings) 
+	ExactOnionRings = mdd_array_duplicate(MergeOnionRings);
+      /* we can use the exact set as an approximation to compute
+	 the bottom set. */
+      rightMdd = array_fetch(mdd_t *,rightChild->Topstates,0);
+      j=1;
+      /* Compute the botom mdds now */
+      for(i=1;i<number_left_bot;i++) {
+	if (buildOnionRings)
+	  onionRings = array_alloc(mdd_t *, 0);
+	leftMdd = array_fetch(mdd_t *,leftChild->Bottomstates,i);
+	approx_under = array_fetch(mdd_t *,mddArray_bot,0);
+	result = Mc_FsmEvaluateEUFormula(modelFsm,leftMdd,
+					 rightMdd,
+					 approx_under, fairStates,
+					 careStatesArray,
+					 earlyTermination, hintsArray,
+					 hintType, onionRings,
+					 verbosity, dcLevel, &fixpoint);
+	array_insert(mdd_t *, mddArray_bot, j, result);
+	if (buildOnionRings){
+	  array_t *dupOnionRings = mdd_array_duplicate(ExactOnionRings);
+	  NewOnionRings = GenerateOnionRings(dupOnionRings,onionRings);
+	  /* saving the bottom computation onion rings */
+	  array_insert(array_t*,botrings,j,NewOnionRings);
+	  mdd_array_free(onionRings);
+	}
+	j++;
+      } 
+      leftMdd = array_fetch(mdd_t *,leftChild->Bottomstates,0);
+      for(i=1;i<number_right_bot;i++) {
+	if (buildOnionRings)
+	  onionRings = array_alloc(mdd_t *, 0);
+	else
+	  onionRings = NIL(array_t);
+	rightMdd = array_fetch(mdd_t *,rightChild->Bottomstates,i);
+	approx_under = array_fetch(mdd_t *,mddArray_bot,0);
+	result = Mc_FsmEvaluateEUFormula(modelFsm, leftMdd,
+					 rightMdd,
+					 NIL(mdd_t), fairStates,
+					 careStatesArray,
+					 earlyTermination, hintsArray,
+					 hintType, onionRings,
+					 verbosity, dcLevel, &fixpoint);
+	array_insert(mdd_t *, mddArray_bot, j, result);
+	if (buildOnionRings) {
+	  array_t *dupOnionRings = mdd_array_duplicate(ExactOnionRings);
+	  NewOnionRings = GenerateOnionRings(dupOnionRings,onionRings);
+	  array_insert(array_t*,botrings,j,NewOnionRings);
+	  mdd_array_free(onionRings);
+	}
+	j++;
+      }
+    }
+    match_bot(ctlFormula,mddArray_bot,matchfound_bot,matchelement_bot);
+    match_top(ctlFormula,mddArray_top,matchfound_top,matchelement_top);
+    ctlFormula->Bottomstates = mddArray_bot;
+    ctlFormula->Topstates = mddArray_top;
+    leavesLeftArray = leftChild->leaves;
+    array_append(leavesArray,leavesLeftArray);
+    leavesRightArray = rightChild->leaves;
+    array_append(leavesArray,leavesRightArray);
+    ctlFormula->leaves = leavesArray;
+    if (buildOnionRings) {
+      ctlFormula->BotOnionRings = botrings;
+      ctlFormula->TopOnionRings = toprings;
+      mdd_array_free(ExactOnionRings);
+    }
+    if(approx != NIL(mdd_t))
+      mdd_free(approx);   
+    /* Can't combine under and overapprox */
+    if(!fixpoint && TRMinimization == Ctlp_Overapprox_c)
+      TRMinimization = Ctlp_Incomparable_c;
+    break;
+  }
+
+  case Ctlp_EG_c:{
+    boolean fixpoint;
+    mdd_t *result_ub;
+    mdd_t *approx_over = NIL(mdd_t)    ;
+    int number_bot = array_n(leftChild->Bottomstates);
+    int number_top = array_n(leftChild->Topstates);
+    int i;
+    array_t *arrayOfOnionRings = NIL(array_t); /* array of array of mdd_t* */
+    array_t *botrings = NIL(array_t);
+    array_t *toprings = NIL(array_t);
+    matchfound_top = array_alloc(boolean, 0);
+    matchfound_bot = array_alloc(boolean, 0);
+    matchelement_top = array_alloc(int, 0);
+    matchelement_bot = array_alloc(int, 0);
+    approx = Ctlp_FormulaObtainApproxStates(ctlFormula, Ctlp_Overapprox_c);
+    if(buildOnionRings) {
+      botrings = array_alloc(array_t*,0);
+      toprings = array_alloc(array_t*,0);
+    }
+    if (approx == NIL(mdd_t)) {
+      result_ub = mdd_one(mddMgr);
+    } else {
+      result_ub = mdd_dup(approx);
+    }
+    if (ctlFormula->negation_parity == Ctlp_Even_c) {
+      /* compute the top sets first which will give us
+	 overapproximation to the exact set */
+      for(i=1;i<number_top;i++) {
+	if(buildOnionRings) 
+	  arrayOfOnionRings = array_alloc(array_t *, 0);
+	leftMdd = array_fetch(mdd_t *,leftChild->Topstates,i);
+	result = Mc_FsmEvaluateEGFormula(modelFsm, leftMdd,
+					 NIL(mdd_t), fairStates, 
+					 fairCondition, careStatesArray,
+					 earlyTermination, hintsArray,
+					 hintType, 
+					 &arrayOfOnionRings, verbosity,
+					 dcLevel, &fixpoint, GSHschedule);
+	array_insert(mdd_t *, mddArray_top, i, result);
+	if(buildOnionRings) {
+	  array_insert(array_t*,toprings,i,arrayOfOnionRings);
+	}
+	result_new =  mdd_and(result_ub,result,1,1);
+	mdd_free(result_ub);
+	result_ub = result_new;
+      }
+      /* calculate the exact set */
+      if(buildOnionRings)
+	arrayOfOnionRings = array_alloc(array_t *, 0);
+      leftMdd = array_fetch(mdd_t *,leftChild->Topstates,0);
+      result = Mc_FsmEvaluateEGFormula(modelFsm, leftMdd,
+				       NIL(mdd_t), fairStates,
+				       fairCondition, careStatesArray,
+				       earlyTermination, hintsArray,
+				       hintType,
+				       &arrayOfOnionRings, verbosity,
+				       dcLevel, &fixpoint, GSHschedule);
+      array_insert(mdd_t *,mddArray_bot,0,mdd_dup(result));
+      array_insert(mdd_t *,mddArray_top,0,mdd_dup(result));
+      mdd_free(result);
+      if(buildOnionRings) {
+	Ctlp_FormulaSetDbgInfo(ctlFormula, (void *)arrayOfOnionRings,
+			       McFormulaFreeDebugData);
+	array_insert(array_t*,toprings,0,McMddArrayArrayDup(arrayOfOnionRings));
+	array_insert(array_t*,botrings,0,McMddArrayArrayDup(arrayOfOnionRings));
+      }
+      result = array_fetch(mdd_t *,mddArray_bot,0);
+      if (McCheckEarlyTerminationForOverapprox(earlyTermination, result, careStatesArray)) {
+	leavesLeftArray = leftChild->leaves;
+	ctlFormula->leaves = array_dup(leavesLeftArray);
+	for(i=1;i<number_bot;i++) {
+	  array_insert(mdd_t *, mddArray_bot, i, mdd_dup(result));
+	  if(buildOnionRings) {
+	    array_insert(array_t*,botrings,i,McMddArrayArrayDup(arrayOfOnionRings));
+	  }
+	}
+	ctlFormula->Bottomstates = mddArray_bot;
+	ctlFormula->Topstates = mddArray_top;
+	match_bot(ctlFormula,mddArray_bot,matchfound_bot,matchelement_bot);
+	match_top(ctlFormula,mddArray_top,matchfound_top,matchelement_top);
+	if (buildOnionRings) {
+	  ctlFormula->BotOnionRings = botrings;
+	  ctlFormula->TopOnionRings = toprings;
+	}
+	break;/* top passing */
+      }
+      /* now calculate the bottom set */
+      for(i=1;i<number_bot;i++) {
+	if(buildOnionRings) 
+	  arrayOfOnionRings = array_alloc(array_t *, 0);
+	leftMdd = array_fetch(mdd_t *,leftChild->Bottomstates,i);
+	approx_over = array_fetch(mdd_t *,mddArray_bot,0);
+	result = Mc_FsmEvaluateEGFormula(modelFsm, leftMdd,
+					 approx_over, fairStates, 
+					 fairCondition, careStatesArray,
+					 earlyTermination, hintsArray,
+					 hintType, 
+					 &arrayOfOnionRings, verbosity,
+					 dcLevel, &fixpoint, GSHschedule);
+	array_insert(mdd_t *, mddArray_bot, i, result);
+	if(buildOnionRings) {
+	  array_insert(array_t*,botrings,i,arrayOfOnionRings);
+	}
+      }
+    }
+    else {
+      /* compute the bottom sets first which will give us
+	 overapproximation to the exact set */
+      for(i=1;i<number_bot;i++) {
+	if(buildOnionRings) 
+	  arrayOfOnionRings = array_alloc(array_t *, 0);
+	leftMdd = array_fetch(mdd_t *,leftChild->Bottomstates,i);
+	result = Mc_FsmEvaluateEGFormula(modelFsm, leftMdd,
+					 NIL(mdd_t), fairStates, 
+					 fairCondition, careStatesArray,
+					 earlyTermination, hintsArray,
+					 hintType, 
+					 &arrayOfOnionRings, verbosity,
+					 dcLevel, &fixpoint, GSHschedule);
+	if(buildOnionRings) {
+	  array_insert(array_t*,botrings,i,arrayOfOnionRings);
+	}
+	array_insert(mdd_t *, mddArray_bot, i, result);
+	result_new =  mdd_and(result_ub,result,1,1);
+	mdd_free(result_ub);
+	result_ub = result_new;
+      }
+      /* calculate the exact set */
+      if(buildOnionRings){
+	arrayOfOnionRings = array_alloc(array_t *, 0);
+      }
+      leftMdd = array_fetch(mdd_t *,leftChild->Topstates,0);
+      result = Mc_FsmEvaluateEGFormula(modelFsm, leftMdd,
+				       result_ub, fairStates, 
+				       fairCondition, careStatesArray,
+				       earlyTermination, hintsArray,
+				       hintType, 
+				       &arrayOfOnionRings, verbosity,
+				       dcLevel, &fixpoint, GSHschedule);
+      array_insert(mdd_t *,mddArray_bot,0,mdd_dup(result));
+      array_insert(mdd_t *,mddArray_top,0,mdd_dup(result));
+      mdd_free(result);
+      if (buildOnionRings) {
+	Ctlp_FormulaSetDbgInfo(ctlFormula, (void *)arrayOfOnionRings,
+			       McFormulaFreeDebugData);
+	array_insert(array_t*,botrings,0,McMddArrayArrayDup(arrayOfOnionRings));
+	array_insert(array_t*,toprings,0,McMddArrayArrayDup(arrayOfOnionRings));
+      }
+      result = array_fetch(mdd_t *,mddArray_bot,0);
+      if (McCheckEarlyTerminationForOverapprox(earlyTermination, result, careStatesArray)) {
+	leavesLeftArray = leftChild->leaves;
+	ctlFormula->leaves = array_dup(leavesLeftArray);
+	for(i=1;i<number_top;i++) {
+	  array_insert(mdd_t *, mddArray_top, i, mdd_dup(result));
+	  if(buildOnionRings)
+	    array_insert(array_t*,toprings,i,McMddArrayArrayDup(arrayOfOnionRings));
+	}
+	ctlFormula->Bottomstates = mddArray_bot;
+	ctlFormula->Topstates = mddArray_top;
+	match_bot(ctlFormula,mddArray_bot,matchfound_bot,matchelement_bot);
+	match_top(ctlFormula,mddArray_top,matchfound_top,matchelement_top);
+	if (buildOnionRings) {
+	  ctlFormula->BotOnionRings = botrings;
+	  ctlFormula->TopOnionRings = toprings;
+	}
+	break; /* top passing */
+      }
+      /* calculate the top set now */
+      for(i=1;i<number_top;i++) {
+	if (buildOnionRings) {
+	  arrayOfOnionRings = array_alloc(array_t *, 0);
+	}
+	leftMdd = array_fetch(mdd_t *,leftChild->Topstates,i);
+	approx_over = array_fetch(mdd_t *,mddArray_bot,0);
+	result = Mc_FsmEvaluateEGFormula(modelFsm, leftMdd,
+					 approx, fairStates, 
+					 fairCondition, careStatesArray,
+					 earlyTermination, hintsArray,
+					 hintType, 
+					 &arrayOfOnionRings, verbosity,
+					 dcLevel, &fixpoint, GSHschedule);
+	array_insert(mdd_t *, mddArray_top, i, result);
+	if(buildOnionRings)
+	  array_insert(array_t*,toprings,i,arrayOfOnionRings);
+      }
+    }
+    mdd_free(result_ub);
+    /* Now attach the array to the ctlFormula */
+    ctlFormula->Bottomstates = mddArray_bot;
+    ctlFormula->Topstates = mddArray_top;
+    /* Discard previous copies. */
+    array_free(matchfound_bot);
+    array_free(matchelement_bot);
+    array_free(matchfound_top);
+    array_free(matchelement_top);
+    ctlFormula->matchfound_bot = array_dup(leftChild->matchfound_bot);
+    ctlFormula->matchelement_bot = array_dup(leftChild->matchelement_bot);
+    ctlFormula->matchfound_top = array_dup(leftChild->matchfound_top);
+    ctlFormula->matchelement_top = array_dup(leftChild->matchelement_top);
+    /* find out the leaves attached to this nodes.*/
+    leavesLeftArray = leftChild->leaves;
+    ctlFormula->leaves = array_dup(leavesLeftArray);
+    if (buildOnionRings) {
+      ctlFormula->BotOnionRings = botrings;
+      ctlFormula->TopOnionRings = toprings;
+    }
+    if(approx != NIL(mdd_t)) mdd_free(approx);
+
+    /* Can't combine under and overapprox */
+    if(!fixpoint && TRMinimization == Ctlp_Underapprox_c)
+      TRMinimization = Ctlp_Incomparable_c;
+
+    break;
+  }
+  
+  case Ctlp_Init_c:
+    result = Fsm_FsmComputeInitialStates(modelFsm);
+    break;
+    
+  default: fail("Encountered unknown type of CTL formula\n");
+  }
+  tmpMdd = mdd_dup(array_fetch(mdd_t *,mddArray_bot,0));
+  thisApproxType = ComputeResultingApproximation(
+    Ctlp_FormulaReadType(ctlFormula), leftApproxType,
+    rightApproxType, TRMinimization, earlyTermination, fixpoint);
+  Ctlp_FormulaSetApproxStates(ctlFormula,tmpMdd, TRMinimization);
+  
+#ifdef DEBUG_MC
+  /* The following code is just for debugging */
+  if ((verbosity == McVerbosityMax_c)) {
+    char *type = Ctlp_FormulaGetTypeString(ctlFormula);
+    if (Ctlp_FormulaReadType(ctlFormula) == Ctlp_Cmp_c) {
+      fprintf(vis_stdout, "Info : result for [Cmp]\n");
+      if (bdd_is_tautology(result, 1))
+	fprintf(vis_stdout, "TRUE\n");
+      else
+	fprintf(vis_stdout, "FALSE\n");
+    }
+    else if (Ctlp_FormulaReadType(ctlFormula) == Ctlp_ID_c) {
+      char *atomic = Ctlp_FormulaConvertToString(ctlFormula);
+      fprintf(vis_stdout, "Info : satisfying minterms for [%s(%s)]:\n",
+	      type, atomic);
+      free(atomic);
+      if (bdd_is_tautology(result, 1))
+	fprintf(vis_stdout, "-- TAUTOLOGY --\n");
+      else if (bdd_is_tautology(result, 0))
+	fprintf(vis_stdout, "-- null --\n");
+      else
+	(void)_McPrintSatisfyingMinterms(result, modelFsm);
+    }
+    else {
+      fprintf(vis_stdout, "Info : satisfying minterms for [%s]:\n", type);
+      if (bdd_is_tautology(result, 1))
+	fprintf(vis_stdout, "-- TAUTOLOGY --\n");
+      else if (bdd_is_tautology(result, 0))
+	fprintf(vis_stdout, "-- null --\n");
+      else
+	(void)_McPrintSatisfyingMinterms(result, modelFsm);
+    }
+    free(type);
+  }
+#endif
+  if (modelCareStatesArray == NIL(array_t))
+      mdd_array_free(careStatesArray);
+  return;
+} /* ModelcheckAndVacuity */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Annotates formula with satisfying sets of i-th replacement.]
+  
+  Description [This function is applied to vacuously passing properties
+  to generate intersting witnesses.]
+
+  SideEffects []
+
+  SeeAlso     [CreateImportantCounterexample]
+
+******************************************************************************/
+static void
+CreateImportantWitness(
+  Ctlp_Formula_t *OldctlFormula,
+  Ctlp_Formula_t *ctlFormula,
+  int i)
+{
+  Ctlp_Formula_t *rightChild, *leftChild,*OldrightChild, *OldleftChild;
+  int number_left_bot;
+  array_t *onionRings = NIL(array_t); /* array of mdd_t */
+  array_t  *arrayOfOnionRings = NIL(array_t);
+  Ctlp_FormulaType formulaType;
+  formulaType = Ctlp_FormulaReadType(ctlFormula);
+  rightChild = Ctlp_FormulaReadRightChild(ctlFormula);
+  leftChild = Ctlp_FormulaReadLeftChild(ctlFormula);
+  OldrightChild = Ctlp_FormulaReadRightChild(OldctlFormula);
+  OldleftChild = Ctlp_FormulaReadLeftChild(OldctlFormula);
+
+  if(leftChild)
+    number_left_bot = array_n(OldleftChild->Bottomstates);
+  else
+    number_left_bot = -1; /* don't care */
+
+  switch (formulaType) {
+  case Ctlp_EU_c:
+    if(ctlFormula->states != NIL(mdd_t))
+      mdd_free(ctlFormula->states);
+    ctlFormula->states = mdd_dup(array_fetch(mdd_t *, OldctlFormula->Bottomstates,i));
+#if 0
+    fprintf(vis_stdout,"Attaching bdd for EU %d",i);
+    bdd_print(ctlFormula->states);
+    mdd_array_free(array_fetch(array_t*,OldctlFormula->BotOnionRings,i));
+#endif
+    onionRings = mdd_array_duplicate(array_fetch(array_t*,OldctlFormula->BotOnionRings,i));
+    Ctlp_FormulaSetDbgInfo(ctlFormula, (void *) onionRings,
+    			   McFormulaFreeDebugData);
+    assert(leftChild != NULL && rightChild != NULL);
+    if(i<number_left_bot){
+      CreateImportantWitness(OldleftChild,leftChild,i);
+    }
+    else{
+      CreateImportantWitness(OldleftChild,leftChild,0);
+    }
+
+    if(i<number_left_bot ){
+      CreateImportantWitness(OldrightChild,rightChild,0);
+    }
+    else {
+      CreateImportantWitness(OldrightChild,rightChild,i - number_left_bot + 1);
+    }
+    break;
+  case Ctlp_EG_c:
+    if(ctlFormula->states != NIL(mdd_t))
+      mdd_free(ctlFormula->states);
+    ctlFormula->states = mdd_dup(array_fetch(mdd_t *, OldctlFormula->Bottomstates,i));
+#if 0
+    fprintf(vis_stdout,"Attaching bdd for EG %d",i);
+    bdd_print(ctlFormula->states);
+    mdd_array_free(array_fetch(array_t*,OldctlFormula->BotOnionRings,i));
+#endif
+    arrayOfOnionRings = McMddArrayArrayDup(array_fetch(array_t* ,OldctlFormula->BotOnionRings,i));
+    Ctlp_FormulaSetDbgInfo(ctlFormula, (void *)arrayOfOnionRings,
+			   McFormulaFreeDebugData);
+    CreateImportantWitness(OldleftChild,leftChild,i);
+    break;
+  case Ctlp_AX_c:
+  case Ctlp_AG_c:
+  case Ctlp_AF_c:
+  case Ctlp_AU_c:
+  case Ctlp_EX_c:
+  case Ctlp_EF_c:
+  case Ctlp_OR_c:
+  case Ctlp_AND_c:  
+  case Ctlp_NOT_c:  
+  case Ctlp_THEN_c:
+  case Ctlp_XOR_c:
+  case Ctlp_EQ_c:
+    if(ctlFormula->states != NIL(mdd_t))
+      mdd_free(ctlFormula->states);
+    ctlFormula->states = mdd_dup(array_fetch(mdd_t *, OldctlFormula->Bottomstates,i));
+#if 0
+    fprintf(vis_stdout,"Attaching bdd for NOT,THEN %d",i);
+    bdd_print(ctlFormula->states);
+#endif
+
+    if(leftChild){
+      if(i<number_left_bot){
+	CreateImportantWitness(OldleftChild,leftChild,i);
+      }
+      else {
+	CreateImportantWitness(OldleftChild,leftChild,0);
+      }
+    }
+
+    if(rightChild){
+      if(i<number_left_bot ){
+	CreateImportantWitness(OldrightChild,rightChild,0);
+      }
+      else{
+	CreateImportantWitness(OldrightChild,rightChild,i - number_left_bot + 1);
+      }
+    }
+    break;
+  case Ctlp_ID_c:
+  case Ctlp_TRUE_c:
+  case Ctlp_FALSE_c:
+  case Ctlp_Init_c:
+    if(ctlFormula->states != NIL(mdd_t))
+      mdd_free(ctlFormula->states);
+    ctlFormula->states = mdd_dup(array_fetch(mdd_t *, OldctlFormula->Bottomstates,i));
+#if 0
+    fprintf(vis_stdout,"Attaching bdd for ID,TRUE %d",i);
+    bdd_print(ctlFormula->states);
+#endif
+    break;
+
+  default:
+    break;
+  }
+} /* CreateImportantWitness */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Annotates formula with satisfying sets of i-th replacement.]
+
+  Description [This function is applied to vacuously failing properties
+  to generate intersting counterexamples.]
+
+  SideEffects []
+
+  SeeAlso     [CreateImportantWitness]
+
+******************************************************************************/
+static void
+CreateImportantCounterexample(
+  Ctlp_Formula_t *OldctlFormula,
+  Ctlp_Formula_t *ctlFormula,
+  int i)
+{
+  Ctlp_Formula_t *rightChild, *leftChild, *OldrightChild, *OldleftChild;
+  int number_left_top;
+  array_t *onionRings = NIL(array_t); /* array of mdd_t */
+  array_t  *arrayOfOnionRings = NIL(array_t);
+  Ctlp_FormulaType formulaType;
+  formulaType = Ctlp_FormulaReadType(ctlFormula);
+  rightChild = Ctlp_FormulaReadRightChild(ctlFormula);
+  leftChild = Ctlp_FormulaReadLeftChild(ctlFormula);
+  OldrightChild = Ctlp_FormulaReadRightChild(OldctlFormula);
+  OldleftChild = Ctlp_FormulaReadLeftChild(OldctlFormula);
+
+  if(leftChild)
+    number_left_top = array_n(OldleftChild->Topstates);
+  else
+    number_left_top = -1; /* don't care */
+
+  switch (formulaType) {
+  case Ctlp_EU_c:
+    if(ctlFormula->states != NIL(mdd_t))
+      mdd_free(ctlFormula->states);
+    ctlFormula->states = mdd_dup(array_fetch(mdd_t *, OldctlFormula->Topstates,i));
+    onionRings = mdd_array_duplicate(array_fetch(array_t*,OldctlFormula->TopOnionRings,i));
+    Ctlp_FormulaSetDbgInfo(ctlFormula, (void *) onionRings,
+    			   McFormulaFreeDebugData);
+    assert(leftChild != NULL && rightChild != NULL);
+    if(i<number_left_top){
+      CreateImportantCounterexample(OldleftChild,leftChild,i);
+    }
+    else{
+      CreateImportantCounterexample(OldleftChild,leftChild,0);
+    }
+
+    if(i<number_left_top ){
+      CreateImportantCounterexample(OldrightChild,rightChild,0);
+    }
+    else {
+      CreateImportantCounterexample(OldrightChild,rightChild,i -
+				    number_left_top + 1);
+    }
+    break;
+  case Ctlp_EG_c:
+    if(ctlFormula->states != NIL(mdd_t))
+      mdd_free(ctlFormula->states);
+    ctlFormula->states = mdd_dup(array_fetch(mdd_t *, OldctlFormula->Topstates,i));
+    arrayOfOnionRings = McMddArrayArrayDup(array_fetch(array_t* ,OldctlFormula->TopOnionRings,i));
+    Ctlp_FormulaSetDbgInfo(ctlFormula, (void *)arrayOfOnionRings,
+			   McFormulaFreeDebugData);
+    CreateImportantCounterexample(OldleftChild,leftChild,i);
+    break;
+  case Ctlp_AX_c:
+  case Ctlp_AG_c:
+  case Ctlp_AF_c:
+  case Ctlp_AU_c:
+  case Ctlp_EX_c:
+  case Ctlp_EF_c:
+  case Ctlp_OR_c:
+  case Ctlp_AND_c:  
+  case Ctlp_NOT_c:  
+  case Ctlp_THEN_c:
+  case Ctlp_XOR_c:
+  case Ctlp_EQ_c:
+    if(ctlFormula->states != NIL(mdd_t))
+      mdd_free(ctlFormula->states);
+    ctlFormula->states = mdd_dup(array_fetch(mdd_t *, OldctlFormula->Topstates,i));
+
+    if(leftChild){
+      if(i<number_left_top){
+	CreateImportantCounterexample(OldleftChild,leftChild,i);
+      }
+      else {
+	CreateImportantCounterexample(OldleftChild,leftChild,0);
+      }
+    }
+
+    if(rightChild){
+      if(i<number_left_top ){
+	CreateImportantCounterexample(OldrightChild,rightChild,0);
+      }
+      else{
+	CreateImportantCounterexample(OldrightChild,rightChild,i -
+				      number_left_top + 1);
+      }
+    }
+    break;
+  case Ctlp_ID_c:
+  case Ctlp_TRUE_c:
+  case Ctlp_FALSE_c:
+  case Ctlp_Init_c:
+    if(ctlFormula->states != NIL(mdd_t))
+      mdd_free(ctlFormula->states);
+    ctlFormula->states = mdd_dup(array_fetch(mdd_t *, OldctlFormula->Topstates,i));
+#if 0
+    fprintf(vis_stdout,"Attaching bdd for ID,TRUE %d",i);
+    bdd_print(ctlFormula->states);
+#endif
+    break;
+
+  default:
+    break;
+  }
+} /* CreateImportantCounterexample */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Duplicates an array of arrays of MDDs.]
+
+  Description [Makes sure ref counts are correct.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+static array_t *
+McMddArrayArrayDup(array_t *arrayBddArray)
+{
+  int		i;
+  array_t	*bddArray, *tmpbddArray;
+  int		length;
+  array_t	*result;
+  /* put assert for this  if (arrayBddArray != NIL(array_t)) { */
+  length = array_n(arrayBddArray);
+  result = array_alloc(array_t *, length);
+  for (i = 0; i < length; i++) {
+    bddArray = array_fetch(array_t *, arrayBddArray, i);
+    tmpbddArray = mdd_array_duplicate(bddArray);
+    array_insert(array_t *,result,i,tmpbddArray);
+  }
+  return(result);
+} /* McMddArrayArrayDup */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Searches an mdd array of top sets for matches.]
+
+  Description []
+
+  SideEffects [The node of the formula is annotated with the match info.]
+
+  SeeAlso     [match_bot]
+
+******************************************************************************/
+static void
+match_top(
+  Ctlp_Formula_t *ctlFormula,
+  array_t *mddArray,
+  array_t *matchfound,
+  array_t *matchelement)
+{
+  int i, j, positionmatch;
+  mdd_t *leftMdd1 = NIL(mdd_t);
+  mdd_t *leftMdd2 = NIL(mdd_t);
+
+  arrayForEachItem(mdd_t *, mddArray, i, leftMdd1){
+    array_insert(boolean, matchfound, i, FALSE);
+  }
+
+  arrayForEachItem(mdd_t *, mddArray, i, leftMdd1) {
+    arrayForEachItem(mdd_t *, mddArray, j, leftMdd2) {
+      if((i != 0) && (j != 0) && (i != j)) {
+	if (mdd_equal(leftMdd2, leftMdd1)) {
+	  if (array_fetch(boolean, matchfound,i) == TRUE) {
+	    if(array_fetch(int, matchelement,i) != j) {
+	      positionmatch = array_fetch(int, matchelement, i);
+	      array_insert(int, matchelement, j, positionmatch);
+	    }
+	  }
+	  else{
+	    array_insert(int, matchelement, j, i);
+	    array_insert(boolean, matchfound, j, TRUE);
+	  }
+	}
+      }
+    }
+  }
+  ctlFormula->matchfound_top = matchfound;
+  ctlFormula->matchelement_top = matchelement;
+  return;
+} /* match_top */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Searches an mdd array of bottom sets for matches.]
+
+  Description []
+
+  SideEffects [The node of the formula is annotated with the match info.]
+
+  SeeAlso     [match_top]
+
+******************************************************************************/
+static void
+match_bot(
+  Ctlp_Formula_t *ctlFormula,
+  array_t *mddArray,
+  array_t *matchfound,
+  array_t *matchelement)
+{
+  int i, j, positionmatch;
+  mdd_t *leftMdd1 = NIL(mdd_t);
+  mdd_t *leftMdd2 = NIL(mdd_t);
+
+  arrayForEachItem(mdd_t *, mddArray, i, leftMdd1){
+    array_insert(boolean, matchfound, i, FALSE);
+  }
+
+  arrayForEachItem(mdd_t *, mddArray, i, leftMdd1) {
+    arrayForEachItem(mdd_t *, mddArray, j, leftMdd2) {
+      if ((i != 0) && (j != 0) && (i != j)) {
+	if (mdd_equal(leftMdd2, leftMdd1)) {
+	  if (array_fetch(boolean, matchfound, i) == TRUE) {
+	    if (array_fetch(int, matchelement, i) != j) {
+	      positionmatch = array_fetch(int, matchelement, i);
+	      array_insert(int, matchelement, j, positionmatch);
+	    }
+	  }
+	  else {
+	    array_insert(int, matchelement, j, i);
+	    array_insert(boolean, matchfound, j ,TRUE);
+	  }
+	}
+      }
+    }
+  }
+  ctlFormula->matchfound_bot = matchfound;
+  ctlFormula->matchelement_bot = matchelement;
+  return;
+} /* match_bot */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Merge onion rings for EU operators.]
+
+  Description []
+  
+  SideEffects [The first argument is freed.]
+
+  SeeAlso     [ModelcheckAndVacuity]
+
+******************************************************************************/
+static array_t *
+GenerateOnionRings(
+  array_t* TempOnionRings,
+  array_t* onionRings)
+{
+  array_t* MergeOnionRings;
+  int  mdd1number, mdd2number, k;
+  mdd_t *temp,*temp1,*mdd1,*mdd2,*mdd3 = NIL(mdd_t);
+
+  mdd1number = array_n(TempOnionRings);
+  mdd2number = array_n(onionRings);
+  if(mdd1number == 0) {
+    MergeOnionRings = mdd_array_duplicate(onionRings);
+    array_free(TempOnionRings);
+    return (MergeOnionRings);
+  }
+  MergeOnionRings = array_alloc(mdd_t *, 0);
+  mdd1 = array_fetch(mdd_t *,TempOnionRings,0);
+  mdd2 = array_fetch(mdd_t *,onionRings,0);
+  temp = mdd_or(mdd1,mdd2,1,1); /* Building the core for EU */
+  array_insert(mdd_t *,MergeOnionRings,0, temp);
+  if(mdd2number>=mdd1number) {
+    for(k=1;k<mdd1number;k++) {
+      mdd1 = array_fetch(mdd_t *, onionRings, k);
+      mdd2 = array_fetch(mdd_t *, MergeOnionRings, k-1);
+      mdd3 = array_fetch(mdd_t *, TempOnionRings, k);
+      temp1 = mdd_or(mdd1,mdd3,1,1); 
+      temp = mdd_and(temp1,mdd2,1,0);
+      mdd_free(temp1);
+      array_insert(mdd_t*, MergeOnionRings, k, temp);
+    }
+    for(k=mdd1number;k<mdd2number;k++) {
+      mdd1 = array_fetch(mdd_t *, onionRings, k);
+      mdd2 = array_fetch(mdd_t *, MergeOnionRings, k-1);
+      temp = mdd_and(mdd1,mdd2,1,0);
+      array_insert(mdd_t*, MergeOnionRings, k, temp);
+    }
+  }
+  else {
+    for(k=1;k<mdd2number;k++) {
+      mdd1 =array_fetch(mdd_t *, onionRings, k);
+      mdd2 =array_fetch(mdd_t *, MergeOnionRings, k-1);
+      mdd3 =array_fetch(mdd_t *, TempOnionRings, k);
+      temp1 = mdd_or(mdd1,mdd3,1,1); 
+      temp = mdd_and(temp1,mdd2,1,0);
+      mdd_free(temp1);
+      array_insert(mdd_t*, MergeOnionRings, k, temp);
+    }
+  }
+  mdd_array_free(TempOnionRings);
+  return(MergeOnionRings);
+} /* GenerateOnionRings */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Free debugging info computed during CTL vacuum cleaning.]
+
+  Description [Frees debugging info attached to the parse tree by the
+  CTL vacuum cleaning algorithm.]
+  
+  SideEffects [Disposes of various sets attached to nodes of the parse tree.]
+
+  SeeAlso     [McVacuityDetection]
+
+******************************************************************************/
+static void
+FormulaFreeDebugDataVac(
+  Ctlp_Formula_t *formula)
+{
+  int i;
+  array_t *TopOnion, *BottomOnion;
+  Ctlp_FormulaType  type = Ctlp_FormulaReadType(formula);
+  if(formula->type != Ctlp_ID_c ){
+    if (formula->left  != NIL(Ctlp_Formula_t)) {
+      FormulaFreeDebugDataVac(formula->left);
+    }
+    if (formula->right != NIL(Ctlp_Formula_t)) {
+      FormulaFreeDebugDataVac(formula->right);
+    }
+  }
+  if (type == Ctlp_EU_c || type == Ctlp_EG_c ) {
+    if (formula->TopOnionRings != NIL(array_t)) {
+      TopOnion = formula->TopOnionRings;
+      for (i = 0; i < array_n(TopOnion); i++) {
+	if (type == Ctlp_EU_c) {
+	  mdd_array_free(array_fetch(array_t *, TopOnion, i));
+	}
+	else if (type == Ctlp_EG_c)
+	  mdd_array_array_free(array_fetch(array_t *, TopOnion, i));
+      }
+      array_free(TopOnion);
+    }
+    if (formula->BotOnionRings != NIL(array_t)) {
+      BottomOnion = formula->BotOnionRings;
+      for (i = 0; i < array_n(BottomOnion); i++) {
+	if (type == Ctlp_EU_c) {
+	  mdd_array_free(array_fetch(array_t *, BottomOnion, i));
+	}
+	else if (type == Ctlp_EG_c)
+	  mdd_array_array_free(array_fetch(array_t *, BottomOnion, i));
+      }
+      array_free(BottomOnion);
+    }
+  }
+} /* FormulaFreeDebugDataVac */
Index: vis_dev/vis-2.3/src/mvf/mvf.h
===================================================================
--- vis_dev/vis-2.3/src/mvf/mvf.h	(revision 14)
+++ vis_dev/vis-2.3/src/mvf/mvf.h	(revision 14)
@@ -0,0 +1,138 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [mvf.h]
+
+  PackageName [mvf]
+
+  Synopsis    [Creation and manipulation of MDD-based multi-valued functions.]
+
+  Description [This package is used to create and manipulate single output
+  functions that take multiple values, and are defined over multi-valued
+  variables.  Mathematically, such a function is described as, f: Y1 x Y2 x
+  ... x Yn --> Yn+1.  Each Yi is a finite, ordered set; if Yi is of
+  cardinality k, then the elements of Yi are {0, 1, ..., k-1}. We use yi do
+  denote a variable over Yi. If<p>
+
+  A single MDD over variables y1,...,yn cannot be used to represent f, because
+  an MDD can only represent binary-valued functions, not multi-valued
+  functions.  Instead, to represent f, we use an array of MDDs, of length
+  equal to the cardinality of Yn+1.  Each MDD of this array is defined over
+  y1,...,yn.  Furthermore, the minterms for which the ith MDD, fi, evaluates
+  to one, are exactly those minterms for which f evaluates to the ith member
+  of Yn+1.  If f is deterministic, then the intersection of fi and fj, for i
+  not equal to j, is empty.  If f is completely specified, then the union of
+  the fi's is the tautology.  The union of the fi's is referred to as the
+  "domain" of the function.]
+
+  SeeAlso     [mdd]
+
+  Author      [Tom Shiple]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: mvf.h,v 1.2 2002/09/08 21:42:15 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _MVF
+#define _MVF
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "vm.h"
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef array_t Mvf_Function_t;
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the components of a multi-valued function.]
+
+  Description [This macro iterates over the components of a multi-valued
+  function.]
+
+  SideEffects  [This macro instantiates macros from the array package.  Hence
+  it is advisable not to nest this macro within array macros.]
+
+  SeeAlso      [Mvf_FunctionAlloc]
+
+******************************************************************************/
+#define Mvf_FunctionForEachComponent(                                       \
+  /* Mvf_Function_t * */ function  /* function to iterate components */,    \
+  /* int */              i         /* local variable for iterator */,       \
+  /* mdd_t * */          component /* component of function */              \
+)                                                                           \
+  arrayForEachItem(mdd_t *, (array_t *) function, i, component)
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void Mvf_Init(void);
+EXTERN void Mvf_End(void);
+EXTERN Mvf_Function_t * Mvf_FunctionAlloc(mdd_manager *mddManager, int n);
+EXTERN void Mvf_FunctionAddMintermsToComponent(Mvf_Function_t *function, int i, mdd_t *g);
+EXTERN mdd_t * Mvf_FunctionBuildRelationWithVariable(Mvf_Function_t *function, int mddId);
+EXTERN int Mvf_FunctionReadNumComponents(Mvf_Function_t *function);
+EXTERN mdd_manager * Mvf_FunctionReadMddManager(Mvf_Function_t *function);
+EXTERN Mvf_Function_t * Mvf_FunctionDuplicate(Mvf_Function_t *function);
+EXTERN void Mvf_FunctionFree(Mvf_Function_t *function);
+EXTERN void Mvf_FunctionArrayFree(array_t *functionArray);
+EXTERN mdd_t * Mvf_FunctionObtainComponent(Mvf_Function_t *function, int i);
+EXTERN mdd_t * Mvf_FunctionReadComponent(Mvf_Function_t *function, int i);
+EXTERN Mvf_Function_t * Mvf_FunctionCreateFromVariable(mdd_manager *mddManager, int mddId);
+EXTERN Mvf_Function_t * Mvf_FunctionComposeWithFunctionArray(Mvf_Function_t *f, array_t *mddIdArray, array_t *functionArray);
+EXTERN Mvf_Function_t * Mvf_FunctionComposeWithFunction(Mvf_Function_t *f, int mddId, Mvf_Function_t *g);
+EXTERN mdd_t * Mvf_MddComposeWithFunction(mdd_t *f, int mddId, Mvf_Function_t *g);
+EXTERN boolean Mvf_FunctionTestIsDeterministic(Mvf_Function_t *function);
+EXTERN boolean Mvf_FunctionTestIsCompletelySpecified(Mvf_Function_t *function);
+EXTERN boolean Mvf_FunctionTestIsConstant(Mvf_Function_t *function, int *constantValue);
+EXTERN boolean Mvf_FunctionTestIsNonDeterministicConstant(Mvf_Function_t *function);
+EXTERN mdd_t * Mvf_FunctionComputeDomain(Mvf_Function_t *function);
+EXTERN boolean Mvf_FunctionTestIsWellFormed(Mvf_Function_t *function);
+EXTERN boolean Mvf_FunctionTestIsEqualToFunction(Mvf_Function_t *function1, Mvf_Function_t *function2);
+EXTERN mdd_t * Mvf_FunctionsComputeEquivalentSet(Mvf_Function_t *function1, Mvf_Function_t *function2);
+EXTERN Mvf_Function_t * Mvf_FunctionCofactor(Mvf_Function_t * function, mdd_t * wrtMdd);
+EXTERN Mvf_Function_t * Mvf_FunctionMinimize(Mvf_Function_t *f, mdd_t *c);
+EXTERN long Mvf_FunctionArrayComputeNumBddNodes(array_t * functionArray);
+EXTERN long Mvf_FunctionComputeNumBddNodes(Mvf_Function_t * function);
+EXTERN int Mvf_FunctionFindFirstTrueComponent(Mvf_Function_t * function);
+EXTERN int Mvf_FunctionComputeHashValue(Mvf_Function_t * function);
+EXTERN array_t * Mvf_FunctionComputeSupport(Mvf_Function_t *outMvf, mdd_manager *mddMgr, int *value);
+
+
+/**AutomaticEnd***************************************************************/
+
+
+#endif /* _MVF */
+
+
+
Index: vis_dev/vis-2.3/src/mvf/mvf.make
===================================================================
--- vis_dev/vis-2.3/src/mvf/mvf.make	(revision 14)
+++ vis_dev/vis-2.3/src/mvf/mvf.make	(revision 14)
@@ -0,0 +1,4 @@
+CSRC += mvfMvf.c
+HEADERS += mvf.h mvfInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/mvf/mvfInt.h
===================================================================
--- vis_dev/vis-2.3/src/mvf/mvfInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/mvf/mvfInt.h	(revision 14)
@@ -0,0 +1,54 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [mvfInt.h]
+
+  PackageName [mvf]
+
+  Synopsis    [Internal definitions for the mvf package.]
+
+  Author      [Tom Shiple]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: mvfInt.h,v 1.1.1.2 1997/02/12 22:22:00 hsv Exp $]
+
+******************************************************************************/
+
+#ifndef _MVFINT
+#define _MVFINT
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "mvf.h"
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _MVFINT */
+
+
+
Index: vis_dev/vis-2.3/src/mvf/mvfMvf.c
===================================================================
--- vis_dev/vis-2.3/src/mvf/mvfMvf.c	(revision 14)
+++ vis_dev/vis-2.3/src/mvf/mvfMvf.c	(revision 14)
@@ -0,0 +1,1079 @@
+/**CFile***********************************************************************
+
+  FileName    [mvfMvf.c]
+
+  PackageName [mvf]
+
+  Synopsis    [Routines to create, manipulate and free multi-valued functions.]
+
+  SeeAlso     [mvf.h]
+
+  Author      [Tom Shiple]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "mvfInt.h"
+
+static char rcsid[] UNUSED = "$Id: mvfMvf.c,v 1.6 2002/09/08 21:48:24 fabio Exp $";
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the mvf package.]
+
+  SideEffects []
+
+  SeeAlso     [Mvf_End]
+
+******************************************************************************/
+void
+Mvf_Init(void)
+{
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Ends the mvf package.]
+
+  SideEffects []
+
+  SeeAlso     [Mvf_Init]
+
+******************************************************************************/
+void
+Mvf_End(void)
+{
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates a multi-valued function of n components.]
+
+  Description [Allocates a multi-valued function of n components.  Each
+  component is initialized to the zero MDD.]
+
+  SideEffects []
+
+  SeeAlso     [Mvf_FunctionAddMintermsToComponent Mvf_FunctionCreateFromVariable]
+
+******************************************************************************/
+Mvf_Function_t *
+Mvf_FunctionAlloc(
+  mdd_manager *mddManager,
+  int n)
+{
+  int      i;
+  array_t *mddArray = array_alloc(mdd_t *, n);
+
+  for (i = 0; i < n; i++) {
+    array_insert(mdd_t *, mddArray, i, mdd_zero(mddManager));
+  }
+  return ((Mvf_Function_t *) mddArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adds a set of minterms to the ith component of a function.]
+
+  Description [Adds a set of minterms, represented by the onset of an MDD g,
+  to the onset of the ith component of a function.  The MDD g is not freed.]
+
+  SideEffects []
+
+  SeeAlso     [Mvf_FunctionAlloc]
+
+******************************************************************************/
+void
+Mvf_FunctionAddMintermsToComponent(
+  Mvf_Function_t *function,
+  int             i,
+  mdd_t          *g)
+{
+  mdd_t   *oldComponent;
+  mdd_t   *newComponent;
+  array_t *mddArray = (array_t *) function;
+
+  assert((i >= 0) && (i < array_n(mddArray)));
+
+  oldComponent = array_fetch(mdd_t *, mddArray, i);
+  newComponent = mdd_or(oldComponent, g, 1, 1);
+  mdd_free(oldComponent);
+  array_insert(mdd_t *, mddArray, i, newComponent);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the MDD representation of the relation (var == function).]
+
+  Description [Given a variable x, represented by MDD var "mddId", and a
+  function f:y->z, represented by "function", where x and z take the same
+  number of values, returns the MDD for a (binary) function F(x,y) such that
+  F(x,y) = 1 iff x = f(y).  In the binary case it reduces to F(x,y) = x XNOR
+  f(y).  Intuitively it describes a function of multi-valued variables by the
+  characteristic function of its input-output relation.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Mvf_FunctionBuildRelationWithVariable(
+  Mvf_Function_t *function,
+  int mddId)
+{
+  int          i;
+  mvar_type    mddVar;
+  array_t     *mddArray     = (array_t *) function;
+  mdd_manager *mddManager   = Mvf_FunctionReadMddManager(function);
+  mdd_t       *sumOfFactors = mdd_zero(mddManager);
+  
+  mddVar = array_fetch(mvar_type, mdd_ret_mvar_list(mddManager), mddId);
+  assert(mddVar.values == Mvf_FunctionReadNumComponents(function));
+
+  for (i = 0; i < array_n(mddArray); i++) {
+    mdd_t *varLiteral;
+    mdd_t *factor;
+    mdd_t *tmp;
+    mdd_t *fComponent = array_fetch(mdd_t *, mddArray, i);
+
+    varLiteral = mdd_eq_c(mddManager, mddId, i);
+    factor = mdd_and(fComponent, varLiteral, 1, 1);
+    mdd_free(varLiteral);
+
+    /* Take the or of the sumOfFactors so far and the new factor */
+    tmp = mdd_or(sumOfFactors, factor, 1, 1);
+    mdd_free(factor);
+    mdd_free(sumOfFactors);
+    sumOfFactors = tmp;
+  } 
+
+  return sumOfFactors;
+} 
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of components of a multi-valued function.]
+
+  Description [Returns the number of components of a multi-valued function.
+  This is the same number as the value of the parameter passed to
+  Mvf_FunctionAlloc.]
+
+  SideEffects []
+
+  SeeAlso     [Mvf_FunctionAlloc]
+
+******************************************************************************/
+int
+Mvf_FunctionReadNumComponents(
+  Mvf_Function_t *function)
+{
+  return (array_n((array_t *) function));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the MDD manager of a multi-valued function.]
+
+  Description [Returns the MDD manager of a multi-valued function.  This
+  procedure assumes that the function has at least one component.]
+
+  SideEffects []
+
+  SeeAlso     [Mvf_FunctionAlloc]
+
+******************************************************************************/
+mdd_manager *
+Mvf_FunctionReadMddManager(
+  Mvf_Function_t *function)
+{
+  mdd_t *component = array_fetch(mdd_t *, (array_t *) function, 0);
+  
+  return (mdd_get_manager(component));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Duplicates a multi-valued output function.]
+
+  Description [Returns a new multi-valued output function, whose constituent
+  MDDs have been duplicated. Assumes that function is not NULL.] 
+
+  SideEffects []
+
+  SeeAlso     [Mvf_FunctionFree]
+
+******************************************************************************/
+Mvf_Function_t *
+Mvf_FunctionDuplicate(
+  Mvf_Function_t *function)
+{
+  return ((Mvf_Function_t *) mdd_array_duplicate((array_t *) function));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a multi-valued output function.]
+
+  Description [Frees a multi-valued output function. Does nothing if
+  function is NULL.]
+  
+  SideEffects []
+
+  SeeAlso     [Mvf_FunctionAlloc]
+
+******************************************************************************/
+void
+Mvf_FunctionFree(
+  Mvf_Function_t *function)
+{
+  mdd_array_free((array_t *) function);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees an array of multi-valued output functions.]
+
+  Description [Frees an array of multi-valued output functions.  Does nothing
+  if functionArray is NULL.]
+
+  SideEffects []
+
+  SeeAlso     [Mvf_FunctionFree]
+
+******************************************************************************/
+void
+Mvf_FunctionArrayFree(
+  array_t *functionArray)
+{
+  int i;
+
+  if (functionArray != NIL(array_t)) {
+    for (i = 0; i < array_n(functionArray); i++) {
+      Mvf_Function_t *function = array_fetch(Mvf_Function_t *, functionArray, i);
+      Mvf_FunctionFree(function);
+    }
+    array_free(functionArray);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis [Returns a copy of the ith component of a multi-valued function.]
+
+  Synopsis [Returns a copy of the MDD giving the minterms for which a
+  multi-valued function evaluates to its ith value.]
+
+  SideEffects []
+
+  SeeAlso     [Mvf_FunctionAlloc Mvf_FunctionCreateFromVariable]
+
+******************************************************************************/
+mdd_t *
+Mvf_FunctionObtainComponent(
+  Mvf_Function_t *function,
+  int i)
+{
+  mdd_t *component = array_fetch(mdd_t *, (array_t *) function, i);
+  return (mdd_dup(component));
+}
+
+/**Function********************************************************************
+
+  Synopsis [Returns the ith component of a multi-valued function.]
+
+  Synopsis [Returns the MDD giving the minterms for which a
+  multi-valued function evaluates to its ith value. The user should not free
+  this MDD.]
+
+  SideEffects []
+
+  SeeAlso     [Mvf_FunctionObtainComponent Mvf_FunctionAlloc
+  Mvf_FunctionCreateFromVariable]
+
+******************************************************************************/
+mdd_t *
+Mvf_FunctionReadComponent(
+  Mvf_Function_t *function,
+  int i)
+{
+  mdd_t *component = array_fetch(mdd_t *, (array_t *) function, i);
+  return (component);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Creates the multi-output function for a variable.]
+
+  Description [Given a variable, creates a function with as many components as
+  values of the variable.  The ith component of the function is true exactly
+  when the variable is equal to the ith value (i.e. fi(x) = (x==i), where x is
+  the variable specified by mddId).  For the case where x is binary valued,
+  the result is \[!x, x\]. Assumes that mddId is non-negative.]
+
+  SideEffects []
+
+  SeeAlso [Mvf_FunctionAlloc]
+
+******************************************************************************/
+Mvf_Function_t *
+Mvf_FunctionCreateFromVariable(
+  mdd_manager *mddManager,
+  int mddId)
+{
+  int        i;
+  array_t   *mvar_list = mdd_ret_mvar_list(mddManager);
+  mvar_type  varInfo;
+  array_t   *result;
+
+  assert(mddId >= 0);
+
+  varInfo   = array_fetch(mvar_type, mvar_list, mddId);
+  result    = array_alloc(mdd_t *, varInfo.values);
+
+  for(i = 0; i < varInfo.values; i++) {
+    mdd_t *literal;
+
+    literal = mdd_eq_c(mddManager, mddId, i);
+    array_insert(mdd_t *, result, i, literal);
+  } 
+
+  return ((Mvf_Function_t *) result);
+} 
+
+
+/**Function********************************************************************
+
+  Synopsis [Substitutes a set of variables by a set of functions in a function.]
+
+  Description [Given a multi-valued function f, an array of variables
+  x1,...,xk, and an array of multi-valued functions g1,...,gk, iteratively
+  calls Mvf_MddComposeWithFunction to substitute each xi by gi.  The
+  parameters of the ith call to Mvf_MddComposeWithFunction are the result of
+  composing the first i-1 variables, xi, and gi.  The multi-valued function gi
+  must not depend on xi.]
+
+  SideEffects []
+
+  SeeAlso     [Mvf_MddComposeWithFunction]
+
+******************************************************************************/
+Mvf_Function_t *
+Mvf_FunctionComposeWithFunctionArray(
+  Mvf_Function_t *f,
+  array_t        *mddIdArray /* of int */,   
+  array_t        *functionArray /* of Mvf_Function_t* */)
+{
+  Mvf_Function_t *result;
+  int i;
+
+  assert(array_n(mddIdArray) == array_n(functionArray));
+
+  /* Make an initial copy of the function */
+  result = Mvf_FunctionDuplicate(f);
+
+  for(i = 0; i < array_n(mddIdArray); i++) {
+    Mvf_Function_t *tmp;
+    int             mddId = array_fetch(int, mddIdArray, i);
+    Mvf_Function_t *g     = array_fetch(Mvf_Function_t *, functionArray, i);
+    
+    tmp = Mvf_FunctionComposeWithFunction(result, mddId, g);
+
+    Mvf_FunctionFree(result);
+    result = tmp;
+  } 
+
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Substitutes a variable by a function in a function.]
+
+  Description [Given a multi-valued function f, a variable x (mddId), and a
+  multi-valued function g, the procedure replaces every appearance of x in f
+  by function g.  That is, if the function f is f(..., x, ...), then the
+  result is f(..., g(), ...).  The number of values that x can take and the
+  number of components of g must be equal. The algorithm first computes the
+  sum of factors (x==i)*gi for every value i in the domain of x, where gi is
+  the ith component of g.  Then, for each component fi of f, the sum of
+  factors is conjuncted with fi, and x is existentially quantified. The
+  function g must not depend on x.  The result depends on all the variables of
+  g and all the variables of f, except for x.]
+
+  SideEffects []
+
+  SeeAlso     [Mvf_MddComposeWithFunction]
+
+******************************************************************************/
+Mvf_Function_t *
+Mvf_FunctionComposeWithFunction(
+  Mvf_Function_t *f,
+  int             mddId,
+  Mvf_Function_t *g)
+{
+  mdd_t   *sumOfFactors;
+  array_t *result;
+  array_t *values;
+  int      i;
+  mdd_manager *mddManager = Mvf_FunctionReadMddManager(f);
+
+  /* Allocate array to hold values for the literal and the result */
+  result = array_alloc(mdd_t *, array_n(f));
+
+  /*
+   * Create the sum of factors (x==i * gi). This function will verify that the
+   * domain of x and the range of g have the same cardinality.
+   */
+  sumOfFactors = Mvf_FunctionBuildRelationWithVariable(g, mddId);
+
+  /* 
+   * Result is an array of mdd_t * , result[i] = Exists(x) (f[i] * sumOfFactors)
+   * The array values holds now the index of the variable to smooth out.
+   */
+  values = array_alloc(int, 1);
+  array_insert(int, values, 0, mddId);
+  for(i = 0; i < array_n(f); i++) {
+    mdd_t *functionUnit = array_fetch(mdd_t *, f, i);
+    mdd_t *tmp          = mdd_and_smooth(mddManager, functionUnit, sumOfFactors, values);
+
+    array_insert(mdd_t *, result, i, tmp);
+  } 
+
+  /* Clean up */
+  array_free(values);
+  mdd_free(sumOfFactors);
+
+  return ((Mvf_Function_t *) result);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Substitutes a variable by a function in an mdd_t *.]
+
+  Description [Given a binary-valued function f, a variable x, and a
+  multi-valued function g, the procedure replaces every appearance of x in f
+  by function g.  That is, if the function f is f(..., x, ...), then the
+  result is f(..., g(), ...). The number of values that x can take and the
+  number of components of g must be equal. The algorithm first computes the
+  sum of factors (x==i)*gi for every value i in the domain of x, where gi is
+  the ith component of g, then conjuncts this with f, and finally
+  existentially quantifies x.  The function g must not depend on x.  The
+  result depends on all the variables of g and all the variables of f, except
+  for x.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Mvf_MddComposeWithFunction(
+  mdd_t          *f,
+  int             mddId,
+  Mvf_Function_t *g)
+{
+  mdd_t       *sumOfFactors;
+  mdd_t       *result;
+  array_t     *values;
+  mdd_manager *mddManager = mdd_get_manager(f);
+  
+  /*
+   * Create the sum of factors (x==i * gi). This function will verify that the
+   * domain of x and the range of g have the same cardinality.
+   */
+  sumOfFactors = Mvf_FunctionBuildRelationWithVariable(g, mddId);
+
+  /* Result is an mdd_t * , result = Exists(x) (f * sumOfFactors) */
+  values = array_alloc(int, 1);
+  array_insert(int, values, 0, mddId);
+  result = mdd_and_smooth(mddManager, f, sumOfFactors, values);
+
+  /* Clean up */
+  array_free(values);
+  mdd_free(sumOfFactors);
+
+  return result;
+} 
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns true if a multi-valued function is deterministic, else
+  false.]
+
+  Description [Returns true if a multi-valued function is deterministic, else
+  false.  A function is deterministic if, for every minterm over the input
+  space of the function, the function takes at most one value. The complexity
+  of this procedure is linear in the number of values the function can
+  take.]
+
+  SideEffects []
+
+  SeeAlso     [Mvf_FunctionTestIsCompletelySpecified Mvf_FunctionTestIsWellFormed]
+
+******************************************************************************/
+boolean
+Mvf_FunctionTestIsDeterministic(
+  Mvf_Function_t *function)
+{
+  int      i;
+  array_t *mddArray      = (array_t *) function;
+  int      numComponents = array_n(mddArray);
+  mdd_t   *sum;
+
+  if (numComponents == 0) {
+    return TRUE;
+  }
+  
+  sum = mdd_dup(array_fetch(mdd_t *, mddArray, 0));
+  
+  for (i = 1; i < numComponents; i++) {
+    mdd_t *temp         = sum;
+    mdd_t *ithComponent = array_fetch(mdd_t *, mddArray, i);
+    boolean intersectionIsEmpty = mdd_lequal(ithComponent, sum, 1, 0);
+    
+    /* If the intersection is not empty, then return FALSE. */
+    if (!intersectionIsEmpty) {
+      mdd_free(sum);
+      return FALSE;
+    }
+
+    sum = mdd_or(temp, ithComponent, 1, 1);
+    mdd_free(temp);
+  }
+  mdd_free(sum);
+  
+  /* The components are pairwise disjoint. */
+  return TRUE;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns true if a multi-valued function is completely specified, else
+  false.]
+
+  Description [Returns true if a multi-valued function is completely
+  specified, else false.  A function is completely specified if, for every
+  minterm over the input space of the function, the function takes at least
+  one value. The complexity of this procedure is linear in the number of
+  values the function can take.]
+
+  SideEffects []
+
+  SeeAlso     [Mvf_FunctionTestIsDeterministic Mvf_FunctionTestIsWellFormed]
+
+******************************************************************************/
+boolean
+Mvf_FunctionTestIsCompletelySpecified(
+  Mvf_Function_t *function)
+{
+  mdd_t   *sum            = Mvf_FunctionComputeDomain(function);
+  boolean  sumIsTautology = mdd_is_tautology(sum, 1);
+
+  mdd_free(sum);
+  return sumIsTautology;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns true if a multi-valued function is constant, else
+  false.]
+
+  Description [Returns true if a multi-valued function is constant, else
+  false.  A function is constant if exactly one component is the tautology,
+  and the remaining components are zero.  If the function is a constant, then
+  "value" is set to the constant value of the function. The complexity of this
+  procedure is linear in the number of values the function can take.]
+
+  SideEffects []
+
+  SeeAlso     [Mvf_FunctionTestIsNonDeterministicConstant]
+
+******************************************************************************/
+boolean
+Mvf_FunctionTestIsConstant(
+  Mvf_Function_t *function,
+  int            *constantValue /* return value */ )
+{
+  int      i;
+  array_t *mddArray      = (array_t *) function;
+  int      numComponents = array_n(mddArray);
+  int      numTautComps  = 0;
+
+  for (i = 0; i < numComponents; i++) {
+    mdd_t *ithComponent = array_fetch(mdd_t *, mddArray, i);
+
+    if (mdd_is_tautology(ithComponent, 1)) {
+      *constantValue = i;
+      numTautComps++;
+    }
+    else if (!mdd_is_tautology(ithComponent, 0)) {
+      /* this component is not 1 nor 0, so function can't be a constant */
+      return FALSE;
+    }
+    /* else, must be the zero function */
+  }
+
+  return (numTautComps == 1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns true if a multi-valued function is a non-deterministic
+  constant, else false.]
+
+  Description [Returns true if a multi-valued function is a non-deterministic
+  constant, else false.  A function is a non-deterministic constant if more
+  than one component is the tautology, and the remaining components are zero.
+  The complexity of this procedure is linear in the number of values the
+  function can take.]
+
+  SideEffects []
+
+  SeeAlso     [Mvf_FunctionTestIsConstant]
+
+******************************************************************************/
+boolean
+Mvf_FunctionTestIsNonDeterministicConstant(
+  Mvf_Function_t *function)
+{
+  int      i;
+  array_t *mddArray      = (array_t *) function;
+  int      numComponents = array_n(mddArray);
+  int      numTautComps  = 0;
+
+  for (i = 0; i < numComponents; i++) {
+    mdd_t *ithComponent = array_fetch(mdd_t *, mddArray, i);
+
+    if (mdd_is_tautology(ithComponent, 1)) {
+      numTautComps++;
+    }
+    else if (!mdd_is_tautology(ithComponent, 0)) {
+      /* this component is not 1 nor 0, so function can't be a non-det constant */
+      return FALSE;
+    }
+    /* else, must be the zero function */
+  }
+
+  return (numTautComps > 1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the domain of a multi-valued function.]
+
+  Description [Returns an MDD representing the set of minterms which turn on
+  some component of a function.  In other words, returns the union of the
+  onsets of the components.  The domain is the tautology if and only if the
+  function is completely specified.]
+
+  SideEffects []
+
+  SeeAlso     [Mvf_FunctionTestIsCompletelySpecified]
+
+******************************************************************************/
+mdd_t *
+Mvf_FunctionComputeDomain(
+  Mvf_Function_t *function)
+{
+  array_t     *mddArray   = (array_t *) function;
+  mdd_manager *mddManager = Mvf_FunctionReadMddManager(function);
+  mdd_t       *sum        = mdd_multiway_or(mddManager, mddArray);
+
+  return sum;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns true if a function is deterministic and completely
+  specified, else false.]
+
+  SideEffects []
+
+  SeeAlso     [Mvf_FunctionTestIsDeterministic
+  Mvf_FunctionTestIsCompletelySpecified]
+
+******************************************************************************/
+boolean
+Mvf_FunctionTestIsWellFormed(
+  Mvf_Function_t *function)
+{
+  return (Mvf_FunctionTestIsDeterministic(function) 
+          && Mvf_FunctionTestIsCompletelySpecified(function));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns true if two multi-valued functions are equal, else false.]
+
+  Description [Returns true if two multi-valued functions are equal, else
+  false.  Two functions are equal if they have the same number of components,
+  and the ith component of one is equal to the ith component of the other.]
+
+  SideEffects []
+
+******************************************************************************/
+boolean
+Mvf_FunctionTestIsEqualToFunction(
+  Mvf_Function_t *function1,
+  Mvf_Function_t *function2)
+{
+  int      i;
+  array_t *mddArray1     = (array_t *) function1;
+  array_t *mddArray2     = (array_t *) function2;
+  int      numComponents = array_n(mddArray1);
+
+  if (numComponents != array_n(mddArray2)) {
+    return FALSE;
+  }
+
+  for (i = 0; i < numComponents; i++) {
+    mdd_t *mdd1 = array_fetch(mdd_t *, mddArray1, i);
+    mdd_t *mdd2 = array_fetch(mdd_t *, mddArray2, i);
+    if (!mdd_equal(mdd1, mdd2)) {
+      return FALSE;
+    }
+  }
+
+  return TRUE;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the set of minterms on which two functions agree.]
+
+  Description [Returns the set of minterms on which two functions agree.  For
+  f = \[f1, f2, ..., fn\] and g = \[g1, g2, ..., gn\], the returned set is:
+  AND(i = 1, ..., n) (fi XNOR gi).  For the special case where f and g are
+  binary valued, this function computes (f XNOR g).  It is an error if the two
+  functions have a different number of components.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Mvf_FunctionsComputeEquivalentSet(
+  Mvf_Function_t *function1,
+  Mvf_Function_t *function2)
+{
+  int          i;
+  array_t     *mddArray1     = (array_t *) function1;
+  array_t     *mddArray2     = (array_t *) function2;
+  int          numComponents = array_n(mddArray1);
+  mdd_manager *mddManager    = Mvf_FunctionReadMddManager(function1);
+  mdd_t       *product       = mdd_one(mddManager);
+
+  assert(numComponents == array_n(mddArray2));
+  
+  for (i = 0; i < numComponents; i++) {
+    mdd_t *mdd1 = array_fetch(mdd_t *, mddArray1, i);
+    mdd_t *mdd2 = array_fetch(mdd_t *, mddArray2, i);
+    mdd_t *xnor = mdd_xnor(mdd1, mdd2);
+    mdd_t *temp = product;
+
+    product = mdd_and(temp, xnor, 1, 1);
+    mdd_free(temp);
+    mdd_free(xnor);
+  }
+
+  return product;
+}
+
+  
+/**Function********************************************************************
+
+  Synopsis [Calls bdd_cofactor on each component of a multi-valued function.]
+
+  Description [Calls bdd_cofactor on each component of a multi-valued
+  function, cofactoring with respect to wrtMDD. Returns the cofactored
+  function. It is an error to call this function with a multi-valued
+  function that contains null MDDs or with a null wrtMdd.]
+
+  SideEffects []
+
+******************************************************************************/
+Mvf_Function_t *
+Mvf_FunctionCofactor(
+  Mvf_Function_t * function,
+  mdd_t          * wrtMdd)
+{
+  int      i;
+  array_t *mddArray      = (array_t *) function;
+  int      numComponents = array_n(mddArray);
+  array_t *newFunction   = array_alloc(mdd_t *, numComponents);
+  
+  for(i = 0; i < numComponents; i++) {
+    mdd_t *component = array_fetch(mdd_t *, mddArray, i);
+    mdd_t *cofactor  = bdd_cofactor(component, wrtMdd);
+
+    array_insert(mdd_t *, newFunction, i, cofactor);
+  }
+  return((Mvf_Function_t *)newFunction);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Calls bdd_minimize on each component of a multi-valued function.]
+
+  Description [Calls bdd_minimize on each component of a multi-valued function
+  f, minimizing with respect to the care function c.  The returned function
+  agrees with f wherever c is true, and may or may not agree with f wherever c
+  is false. It is an error to call this function with a multi-valued function
+  that contains null MDDs or with a null care.]
+
+  SideEffects []
+
+******************************************************************************/
+Mvf_Function_t *
+Mvf_FunctionMinimize(
+  Mvf_Function_t *f,
+  mdd_t          *c)
+{
+  int      i;
+  array_t *mddArray      = (array_t *) f;
+  int      numComponents = array_n(mddArray);
+  array_t *newFunction   = array_alloc(mdd_t *, numComponents);
+  
+  for(i = 0; i < numComponents; i++) {
+    mdd_t *component = array_fetch(mdd_t *, mddArray, i);
+    mdd_t *minimize  = bdd_minimize(component, c);
+
+    array_insert(mdd_t *, newFunction, i, minimize);
+  }
+  return((Mvf_Function_t *)newFunction);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the number of BDD nodes of an array of multi-valued
+  functions.]
+
+  Description [Returns the number of BDD nodes of an array of multi-valued
+  functions. A node shared by several functions is counted only once.]
+
+  SideEffects []
+
+******************************************************************************/
+long
+Mvf_FunctionArrayComputeNumBddNodes(
+  array_t * functionArray)
+{
+  int      i;
+  long     numNodes;
+  array_t *mddArray = array_alloc(mdd_t *, 0);
+
+  /* Build an array of all MDDs */
+  for(i = 0; i < array_n(functionArray); i++) {
+    int      j;
+    array_t *function = (array_t *)array_fetch(Mvf_Function_t *, functionArray, i);
+
+    for(j = 0; j < array_n(function); j++) {
+      mdd_t *component = array_fetch(mdd_t *, function, j);
+      array_insert_last(mdd_t *, mddArray, component);
+    }
+  }
+  
+  /* Compute the reduced number of bdd nodes */
+  numNodes = mdd_size_multiple(mddArray);
+  array_free(mddArray);
+  
+  return(numNodes);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the number of BDD nodes of a multi-valued function.]
+
+  SideEffects []
+
+******************************************************************************/
+long
+Mvf_FunctionComputeNumBddNodes(
+  Mvf_Function_t * function)
+{
+  return(mdd_size_multiple((array_t *)function));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the index of the first component of a multi-valued
+  function that is equal to the tautology.]
+
+  Description [Returns the index of the first component of a multi-valued
+  function that is equal to the tautology. If the multi-valued function is
+  deterministic, this component is unique. Returns -1 if such a component is
+  not found. It is an error to call this function with a multi-valued function
+  that contains null MDDs.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+Mvf_FunctionFindFirstTrueComponent(
+  Mvf_Function_t * function)
+{
+  int      i;
+  array_t *mddArray = (array_t *) function;
+  
+  for(i = 0; i < array_n(mddArray); i++) {
+    mdd_t *component = array_fetch(mdd_t *, mddArray, i);
+    if (mdd_is_tautology(component, 1)) {
+      return(i);
+    }
+  }
+  return(-1);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Hashes A multi-valued function.]
+
+  Description [Hashes A multi-valued function. Each component's top variable id
+  is multiplied by the index of component (+ 1). Returns the sum of this computation
+  on every component. It is an error to call this function with a null
+  multi-valued function.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+Mvf_FunctionComputeHashValue(
+  Mvf_Function_t * function)
+{
+  int      i;
+  int      result   = 0;
+  array_t *mddArray = (array_t *) function;
+  
+  for(i = 0; i < array_n(mddArray); i++) {
+    mdd_t *component = array_fetch(mdd_t *, mddArray, i);
+    result += (mdd_top_var_id(component)) * (i + 1);
+  }
+  return(result);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the variables in the true support of a function.]
+
+  Description [Computes the variables in the true support of a function.  Does
+  this by taking the union of the result of mdd_get_support on each component
+  of the function.  Returns the support as an (ascending) ordered array of MDD
+  ids. If the function is a constant, then a NULL array is returned, and the
+  constant value of the function is written in the "value" variable.]
+
+  SideEffects []
+
+  SeeAlso     [Mvf_FunctionTestIsConstant]
+
+******************************************************************************/
+array_t *
+Mvf_FunctionComputeSupport(
+  Mvf_Function_t *function,
+  mdd_manager *mddMgr,
+  int *value)
+{
+  int        i;
+  mdd_t     *component;
+  array_t   *totalSupportArray;
+  var_set_t *totalSupportSet;
+  int        numMddVars = array_n(mdd_ret_mvar_list(mddMgr));
+
+  /*
+   * Handle the case where function is just a constant.
+   */
+  if (Mvf_FunctionTestIsConstant(function, value)) {
+    return NIL(array_t);
+  }
+  
+  /*
+   * Accumulate the union of supports of the function components into a bit
+   * array.
+   */
+  totalSupportArray = array_alloc(int, 0);
+  totalSupportSet   = var_set_new(numMddVars);
+
+  Mvf_FunctionForEachComponent(function, i, component) {
+    int      j;
+    int      mddVarId;
+    array_t *support = mdd_get_support(mddMgr, component);
+
+    arrayForEachItem(int, support, j, mddVarId) {
+      var_set_set_elt(totalSupportSet, mddVarId);
+    }
+    array_free(support);
+  }
+  
+  /* Convert the bit array to an array of mdd ids. */
+  for (i = 0; i < numMddVars; i++) {
+    if (var_set_get_elt(totalSupportSet, i)) {
+      array_insert_last(int, totalSupportArray, i);
+    }
+  }
+  var_set_free(totalSupportSet);
+
+  return totalSupportArray;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
Index: vis_dev/vis-2.3/src/mvfaig/mvfaig.h
===================================================================
--- vis_dev/vis-2.3/src/mvfaig/mvfaig.h	(revision 14)
+++ vis_dev/vis-2.3/src/mvfaig/mvfaig.h	(revision 14)
@@ -0,0 +1,91 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [mvfaig.h]
+
+  PackageName [mvfaig]
+
+  Synopsis    [Creation and manipulation of AndInv-based multi-valued functions.]
+
+  Description [.]
+
+  Author      [Mohammad Awedh]
+
+  Copyright [ This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+  Revision    [$Id: mvfaig.h,v 1.7 2009/01/21 02:08:09 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _MVFAIG
+#define _MVFAIG
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "maig.h"
+#include "vm.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constatn declarations                                                         */
+/*---------------------------------------------------------------------------*/
+#define MVFAIG_NETWORK_APPL_KEY "MvfAig_NetworkApplKey"
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef array_t MvfAig_Function_t;
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the components of a multi-valued function.]
+
+  Description [This macro iterates over the components of a multi-valued
+  function.]
+
+  SideEffects  [This macro instantiates macros from the array package.  Hence
+  it is advisable not to nest this macro within array macros.]
+
+  SeeAlso      [MvfAig_FunctionAlloc]
+
+******************************************************************************/
+#define MvfAig_FunctionForEachComponent(                                    \
+  /* MvfAig_Function_t * */ function  /* function to iterate components */, \
+  /* int                 */ i         /* local variable for iterator */,    \
+  /* bAndInvEdge_t       */ component /* component of function */           \
+)                                                                           \
+  arrayForEachItem(bAigEdge_t, (array_t *) function, i, component)
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void MvfAig_Init(void);
+EXTERN void MvfAig_End(void);
+EXTERN MvfAig_Function_t * MvfAig_FunctionAlloc(int n);
+EXTERN void MvfAig_FunctionFree(MvfAig_Function_t *function);
+EXTERN MvfAig_Function_t * MvfAig_FunctionDuplicate(MvfAig_Function_t *function);
+EXTERN void MvfAig_FunctionArrayFree(array_t *functionArray);
+EXTERN int MvfAig_FunctionReadNumComponents(MvfAig_Function_t *function);
+EXTERN mAigEdge_t MvfAig_FunctionReadComponent(MvfAig_Function_t *function, int i);
+EXTERN MvfAig_Function_t * MvfAig_FunctionCreateFromVariable(mAig_Manager_t *manager, mAigEdge_t mVarId);
+EXTERN void MvfAig_FunctionAddMintermsToComponent(mAig_Manager_t *manager, MvfAig_Function_t *function, int i, mAigEdge_t g);
+EXTERN mAigEdge_t MvfAig_FunctionsComputeEquivalentSet(mAig_Manager_t *manager, MvfAig_Function_t *function1, MvfAig_Function_t *function2);
+EXTERN mAigEdge_t MvfAig_FunctionComputeDomain(mAig_Manager_t *manager, MvfAig_Function_t *function);
+
+
+/**AutomaticEnd***************************************************************/
+
+
+#endif /* _MVFAIG */
+
Index: vis_dev/vis-2.3/src/mvfaig/mvfaig.make
===================================================================
--- vis_dev/vis-2.3/src/mvfaig/mvfaig.make	(revision 14)
+++ vis_dev/vis-2.3/src/mvfaig/mvfaig.make	(revision 14)
@@ -0,0 +1,4 @@
+CSRC += mvfaigUtil.c
+HEADERS += mvfaig.h mvfaigInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/mvfaig/mvfaigInt.h
===================================================================
--- vis_dev/vis-2.3/src/mvfaig/mvfaigInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/mvfaig/mvfaigInt.h	(revision 14)
@@ -0,0 +1,50 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [mvfaigInt.h]
+
+  PackageName [mvfaig]
+
+  Synopsis    [Internal definitions for the mvf package using And/Inverter graph.]
+
+  Author      [Mohammad Awedh]
+
+  Copyright [ This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#ifndef _MVFAIGINT
+#define _MVFAIGINT
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+
+#include "mvfaig.h"
+#include "maigInt.h"
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _MVFAIGINT */
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/mvfaig/mvfaigUtil.c
===================================================================
--- vis_dev/vis-2.3/src/mvfaig/mvfaigUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/mvfaig/mvfaigUtil.c	(revision 14)
@@ -0,0 +1,369 @@
+/**CFile***********************************************************************
+
+  FileName    [mvfaigUtil.c]
+
+  PackageName [mvfaig]
+
+  Synopsis    [Routines to create, manipulate and free multi-valued functions.]
+
+  SeeAlso     [mvfAig.h]
+
+  Author      [Mohammad Awedh]
+
+  Copyright  [.]
+
+******************************************************************************/
+
+#include "mvfaigInt.h"
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the mvfAig package.]
+
+  SideEffects []
+
+  SeeAlso     [MvfAig_End]
+
+******************************************************************************/
+void
+MvfAig_Init(void)
+{
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Ends the mvfAig package.]
+
+  SideEffects []
+
+  SeeAlso     [MvfAig_Init]
+
+******************************************************************************/
+void
+MvfAig_End(void)
+{
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates a multi-valued function of n components.]
+
+  Description [Allocates a multi-valued function of n components.  Each
+  component is initialized to the zero bAig.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+MvfAig_Function_t *
+MvfAig_FunctionAlloc(
+  int n)
+{
+  int      i;
+  array_t *bAndInvArray = array_alloc(bAigEdge_t, n);
+
+  for (i = 0; i < n; i++) {
+    array_insert(bAigEdge_t, bAndInvArray, i, bAig_Zero);
+  }
+  return ((MvfAig_Function_t *) bAndInvArray);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a multi-valued output function.]
+
+  Description [Frees a multi-valued output function. Does nothing if
+  function is NULL.]
+  
+  SideEffects []
+
+  SeeAlso     [MvfAig_FunctionAlloc]
+
+******************************************************************************/
+void
+MvfAig_FunctionFree(
+  MvfAig_Function_t *function)
+{
+  array_free((array_t *) function);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Duplicates a multi-valued output function.]
+
+  Description [Returns a new multi-valued output function, whose constituent
+  MAIGs have been duplicated. Assumes that function is not NULL.] 
+
+  SideEffects []
+
+  SeeAlso     [Mvf_FunctionFree]
+
+******************************************************************************/
+MvfAig_Function_t *
+MvfAig_FunctionDuplicate(
+  MvfAig_Function_t *function)
+{
+  return ((MvfAig_Function_t *) array_dup((array_t *) function));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees an array of multi-valued output functions.]
+
+  Description [Frees an array of multi-valued output functions.  Does nothing
+  if functionArray is NULL.]
+
+  SideEffects []
+
+  SeeAlso     [Mvf_FunctionFree]
+
+******************************************************************************/
+void
+MvfAig_FunctionArrayFree(
+  array_t *functionArray)
+{
+  int i;
+
+  if (functionArray != NIL(array_t)) {
+    for (i = 0; i < array_n(functionArray); i++) {
+      MvfAig_Function_t *function = array_fetch(MvfAig_Function_t*, functionArray, i);
+      MvfAig_FunctionFree(function);
+    }
+    array_free(functionArray);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of components of a multi-valued function.]
+
+  Description [Returns the number of components of a multi-valued function.
+  This is the same number as the value of the parameter passed to
+  Mvf_FunctionAlloc.]
+
+  SideEffects []
+
+  SeeAlso     [Mvf_FunctionAlloc]
+
+******************************************************************************/
+int
+MvfAig_FunctionReadNumComponents(
+  MvfAig_Function_t *function)
+{
+  return (array_n((array_t *) function));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the ith component of a multi-valued function.]
+
+  Description [Returns the mAndInv giving the minterms for which a
+  multi-valued function evaluates to its ith value. ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+mAigEdge_t
+MvfAig_FunctionReadComponent(
+  MvfAig_Function_t *function,
+  int i)
+{
+  bAigEdge_t component = array_fetch(bAigEdge_t, (array_t *) function, i);
+  return (component);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Creates the multi-output function for a variable.]
+
+  Description [Given a variable, creates a function with as many components as
+  values of the variable.  The ith component of the function is true exactly
+  when the variable is equal to the ith value (i.e. fi(x) = (x==i), where x is
+  the variable specified by mddId).  For the case where x is binary valued,
+  the result is \[!x, x\]. Assumes that mddId is non-negative.]
+
+  SideEffects []
+
+  SeeAlso [Mvf_FunctionAlloc]
+
+******************************************************************************/
+MvfAig_Function_t *
+MvfAig_FunctionCreateFromVariable(
+  mAig_Manager_t *manager,
+  mAigEdge_t mVarId)
+{
+  int        i;
+  array_t   *mVarList    = mAigReadMulVarList(manager);
+  mAigMvar_t mVar;
+  array_t   *result;
+
+  assert( (mVarId >= 0) && (mVarId <= array_n(mVarList)));
+  mVar   = array_fetch(mAigMvar_t, mVarList, mVarId);
+  result = array_alloc(bAigEdge_t, mVar.values);  /* array of all possible values of this variable */
+  for(i = 0; i < mVar.values; i++) {
+    bAigEdge_t literal;
+
+    literal = mAig_EquC(manager, mVarId, i);       /* AndInv graph = 1 if the variable = i*/
+    array_insert(bAigEdge_t, result, i, literal);
+    {
+      /*
+	The name of the node in AIG is node name = node value.
+       */
+      /*
+      char *valueStr = util_inttostr(i);
+      char *name     = util_strcat3(mVar.name,"=", valueStr);
+      char *tmpName;
+      int  index;
+      
+      bAig_NodeSetName(manager, literal, name);
+      FREE(valueStr);
+      */
+    }
+  }
+  return ((MvfAig_Function_t *) result);
+} 
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adds a set of minterms to the ith component of a function.]
+
+  Description [Adds a set of minterms, represented by the onset of an mAig g,
+  to the onset of the ith component of a function.  The mAig g is not freed.]
+
+  SideEffects []
+
+  SeeAlso     [Mvf_FunctionAlloc]
+
+******************************************************************************/
+void
+MvfAig_FunctionAddMintermsToComponent(
+  mAig_Manager_t    *manager,
+  MvfAig_Function_t *function,
+  int               i,
+  mAigEdge_t        g)
+{
+  mAigEdge_t oldComponent;
+  mAigEdge_t newComponent;
+  array_t    *mAigArray = (array_t *) function;
+
+  assert((i >= 0) && (i < array_n(mAigArray)));
+
+  oldComponent = array_fetch(mAigEdge_t , mAigArray, i);
+  newComponent = mAig_Or(manager, oldComponent, g);
+  array_insert(mAigEdge_t , mAigArray, i, newComponent);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the set of minterms on which two functions agree.]
+
+  Description [Returns the set of minterms on which two functions agree.  For
+  f = \[f1, f2, ..., fn\] and g = \[g1, g2, ..., gn\], the returned set is:
+  AND(i = 1, ..., n) (fi XNOR gi).  For the special case where f and g are
+  binary valued, this function computes (f XNOR g).  It is an error if the two
+  functions have a different number of components.]
+
+  SideEffects []
+
+******************************************************************************/
+mAigEdge_t 
+MvfAig_FunctionsComputeEquivalentSet(
+  mAig_Manager_t *manager, 
+  MvfAig_Function_t *function1,
+  MvfAig_Function_t *function2)
+{
+  int          i;
+  array_t     *mAigArray1     = (array_t *) function1;
+  array_t     *mAigArray2     = (array_t *) function2;
+  int          numComponents = array_n(mAigArray1);
+  mAigEdge_t   product       = mAig_One;
+
+  assert(numComponents == array_n(mAigArray1));
+  assert(numComponents == array_n(mAigArray2));
+  
+  for (i = 0; i < numComponents; i++) {
+    mAigEdge_t mAig1 = array_fetch(mAigEdge_t, mAigArray1, i);
+    mAigEdge_t mAig2 = array_fetch(mAigEdge_t, mAigArray2, i);
+    mAigEdge_t xnor = mAig_Eq(manager, mAig1, mAig2);
+    mAigEdge_t temp = product;
+
+    product = mAig_And(manager, temp, xnor);
+  }
+
+  return product;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the domain of a multi-valued function.]
+
+  Description [Returns an mAig representing the set of minterms which turn on
+  some component of a function.  In other words, returns the union of the
+  onsets of the components.  The domain is the tautology if and only if the
+  function is completely specified.]
+
+  SideEffects []
+
+  SeeAlso     [Mvf_FunctionTestIsCompletelySpecified]
+
+******************************************************************************/
+mAigEdge_t 
+MvfAig_FunctionComputeDomain(
+  mAig_Manager_t *manager,
+  MvfAig_Function_t *function)
+{
+  int          i;
+  array_t     *mAigArray     = (array_t *) function;
+  int          numComponents = array_n(mAigArray);
+  mAigEdge_t   sum           = mAig_Zero;
+
+  for (i = 0; i < numComponents; i++) {
+    mAigEdge_t ithComponent = array_fetch(mAigEdge_t , mAigArray, i);
+    mAigEdge_t temp = sum;
+    
+    sum = mAig_Or(manager, temp, ithComponent);
+  }
+  return sum;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/ntk/ntk.h
===================================================================
--- vis_dev/vis-2.3/src/ntk/ntk.h	(revision 14)
+++ vis_dev/vis-2.3/src/ntk/ntk.h	(revision 14)
@@ -0,0 +1,504 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [ntk.h]
+
+  PackageName [ntk]
+
+  Synopsis    [Flat network of multi-valued combinational nodes and latches.]
+
+  Description [A network is a directed graph, where the vertices are nodes (of
+  type Ntk_Node_t) and the edges are stored as fanin and fanout arrays of each
+  node.  Each node has a single output, which may fanout to multiple nodes. A
+  node is one of 5 types.  In addition, it may have one or more optional
+  attributes, respecting the following table:
+
+  <pre>
+    type         |             attributes
+  ---------------+-------------------------------------------
+                 | primary  latch data  latch init  constant  
+                 |  output    input        input             
+  ---------------+-------------------------------------------
+  pseudo input   |   x          x            x               
+  primary input  |   x          x            x               
+  latch          |   x          x            
+  shadow         |                           
+  combinational  |   x          x            x         x
+ 
+  Legend:
+    primary input:    a node with no fanins that is a port of the network;
+                      does not have a table defining its function - it can
+                      take any value in its domain
+    pseudo input:     a node with no fanins, introduced to model
+                      nondeterminism; its table defines which values it can
+                      take 
+    latch:            an edge triggered latch with data and initial inputs
+    shadow:           a node with no fanins and no fanouts; it serves as a
+                      "shadow" for a node; for example, a shadow node for a
+                      latch is used to store information about the next
+                      state variable; any node can have a shadow, except a
+                      shadow node
+    combinational:    a node that has a table and is not a primary or pseudo
+                      input 
+
+    primary output:   a node that is a port of the network
+    latch data input: a node driving the data input of a latch
+    latch init input: a node driving the initial input of a latch
+    constant:         a combinational node with no fanins that can take
+                      exactly one value 
+  </pre>
+
+  An "x" in the table means that it's permissible for a node of the given type
+  to have the given attribute; the absence of an "x" means it's not
+  permissible.<p>
+  
+  In addition, there are several derived attributes: all primary inputs,
+  pseudo inputs, and latches are "combinational inputs"; all latch data
+  inputs, latch initial inputs, and primary outputs are "combinational
+  outputs"; all primary inputs and pseudo inputs are "inputs".<p>
+  
+  Each combinational node has a table defining the function of the node in
+  terms of its immediate fanins.  This function must be deterministic
+  (i.e. for a given valuation of the fanins, the function can assume at most
+  one value) and completely specified (i.e. for a given valuation of the
+  fanins, the function can assume at least one value) in order to ensure
+  correctness of verification results downstream .  (The exception is that
+  pseudo inputs are nondeterministic.)  The table may have multiple output
+  columns, so the node keeps an index giving the output column to which it
+  refers.<p>
+  
+  The ntk package contains facilities to create a network (Ntk_Network_t) from
+  a hierarchical network.  In particular, it supports the concept of "actual
+  names" and "formal names". Consider the following hierarchical network:
+  <pre>
+             +--------------------+
+             |  A                 |
+             |                    |
+             |  +-----+    +----+ |
+             |  | B   |    | C  | |
+             |  |     |    |    | |
+             |  |   x |  y | z  | |
+             |  |  ---+----+--  | |
+             |  |     |    |    | |
+             |  +-----+    +----+ |
+             |                    |
+             +--------------------+
+  </pre>
+  This is meant to depict a block A that contains two blocks B and C.  There
+  is a wire originating in block B, passing through block A, and terminating
+  in block C.  This wire has three different names, A.y, A.B.x, and A.C.z,
+  depending on from which block it is viewed. When a hierarchical network is
+  flattened into a Ntk_Network_t, each node is assigned a unique name,
+  referred to as the "actual name".  The actual name is the name with the
+  fewest levels of hierarchy in it (in this example, A.y).  All other names
+  are referred to as "formal names" (in this example, A.B.x, and A.C.z).  The
+  following functions deal with actual and formal names: Ntk_NodeReadName,
+  Ntk_NetworkFindNodeByActualName, Ntk_NetworkReadActualNameFromFormalName,
+  Ntk_NetworkInsertFormalNameToActualName, Ntk_NetworkFindNodeByName.  See the
+  function descriptions for more details.<p>
+
+  A network may have an MDD manager associated with it, and the nodes may have
+  MDD ids.  However, the network itself does not keep track of any MDDs.  This
+  is the job of the partition package.]
+
+  Author      [Adnan Aziz, Tom Shiple]
+
+  Comment     [The authors would like to acknowledge the ideas of Olivier
+  Coudert, Jean Christophe Madre, and Herve Touati on how to organize the
+  network and node data structures, and functions.]
+  
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: ntk.h,v 1.24 2010/04/09 23:44:05 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _NTK
+#define _NTK
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+
+#include "var.h"
+#include "tbl.h"
+#include "hrc.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+#define NTK_UNASSIGNED_MDD_ID     -1
+#define NTK_UNASSIGNED_MAIG_ID    -1
+#define NTK_UNDEFINED_FANIN_INDEX -1
+#define NTK_HRC_NODE_APPL_KEY     "Ntk_HrcNodeApplKey"
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef struct NtkNetworkStruct Ntk_Network_t;
+typedef struct NtkNodeStruct    Ntk_Node_t;
+typedef void   (*Ntk_ApplInfoFreeFn) (void *);
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the fanins of a node.]
+
+  Description  [This macro iterates over the fanins of a node. It is an error
+  to modify the fanins of a node while iterating its fanins.]
+
+  SideEffects  [This macro instantiates macros from the array package.  Hence
+  it is advisable not to nest this macro within array macros.]
+
+  SeeAlso      [Ntk_NodeForEachFanout]
+
+******************************************************************************/
+#define Ntk_NodeForEachFanin(                                       \
+  /* Ntk_Node_t * */ node   /* node to iterate fanins */,            \
+  /* int */          i      /* local variable for iterator */,       \
+  /* Ntk_Node_t * */ fanin  /* fanin of node */                      \
+)                                                                   \
+  arrayForEachItem(Ntk_Node_t *, Ntk_NodeReadFanins(node), i, fanin)
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the fanouts of a node.]
+
+  Description  [This macro iterates over the fanouts of a node. It is an error
+  to modify the fanouts of a node while iterating its fanouts.]
+
+  SideEffects  [This macro instantiates macros from the array package.  Hence
+  it is advisable not to nest this macro within array macros.]
+
+  SeeAlso      [Ntk_NodeForEachFanout]
+
+******************************************************************************/
+#define Ntk_NodeForEachFanout(                                       \
+  /* Ntk_Node_t * */ node   /* node to iterate fanouts */,           \
+  /* int */          i      /* local variable for iterator */,       \
+  /* Ntk_Node_t * */ fanout /* fanout of node */                     \
+)                                                                    \
+  arrayForEachItem(Ntk_Node_t *, Ntk_NodeReadFanouts(node), i, fanout)
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the nodes of a network.]
+
+  Description  [This macro iterates over the nodes of a network. It is an error
+  to modify the nodes of a network while iterating its nodes.]
+
+  SideEffects  []
+
+  SeeAlso      [Ntk_NetworkForEachPrimaryOutput Ntk_NetworkForEachPrimaryInput]
+
+******************************************************************************/
+#define Ntk_NetworkForEachNode(                                      \
+  /* Ntk_Network_t * */ network /* network to iterate nodes */,      \
+  /* lsGen */           gen     /* local variable for iterator */,   \
+  /* Ntk_Node_t * */    node    /* node of network */                \
+)                                                                    \
+  lsForEachItem(Ntk_NetworkReadNodes(network), gen, node)
+      
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the latches of a network.]
+
+  Description [This macro iterates over the latches of a network. It is an
+  error to modify the latches of a network while iterating its latches.]
+
+  SideEffects  []
+
+  SeeAlso      [Ntk_NetworkForEachPrimaryOutput Ntk_NetworkForEachPrimaryInput]
+
+******************************************************************************/
+#define Ntk_NetworkForEachLatch(                                     \
+  /* Ntk_Network_t * */ network /* network to iterate latches  */,   \
+  /* lsGen */           gen     /* local variable for iterator */,   \
+  /* Ntk_Node_t * */    latch   /* latch of network */               \
+)                                                                    \
+  lsForEachItem(Ntk_NetworkReadLatches(network), gen, latch)
+
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the combinational inputs of a network.]
+
+  Description [This macro iterates over the combinational inputs of a
+  network. Primary inputs, pseudo inputs, and latches are combinational
+  inputs. It is an error to modify the combinational inputs of a network while
+  iterating its combinational inputs.]
+
+  SideEffects  []
+
+  SeeAlso      [Ntk_NetworkForEachPrimaryOutput Ntk_NetworkForEachPrimaryInput]
+
+******************************************************************************/
+#define Ntk_NetworkForEachCombInput(                                   \
+  /* Ntk_Network_t * */ network /* network to iterate comb inputs */,  \
+  /* lsGen */           gen     /* local variable for iterator */,     \
+  /* Ntk_Node_t * */    node    /* node of network */                  \
+)                                                                      \
+  lsForEachItem(Ntk_NetworkReadCombInputs(network), gen, node)
+
+      
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the combinational outputs of a network.]
+
+  Description [This macro iterates over the combinational outputs of a
+  network. Primary outputs, latch data inputs, and latch initial inputs, are
+  combinational outputs. A node may be a combinational output for more than
+  one reason (e.g. both a latch data input and a primary output), however, it
+  appears only once in the iteration. It is an error to modify the
+  combinational outputs of a network while iterating its combinational
+  outputs.]
+
+  SideEffects  []
+
+  SeeAlso      [Ntk_NetworkForEachPrimaryOutput Ntk_NetworkForEachPrimaryInput]
+
+******************************************************************************/
+#define Ntk_NetworkForEachCombOutput(                                  \
+  /* Ntk_Network_t * */ network /* network to iterate comb outputs */, \
+  /* lsGen */           gen     /* local variable for iterator */,     \
+  /* Ntk_Node_t * */    node    /* node of network */                  \
+)                                                                      \
+  lsForEachItem(Ntk_NetworkReadCombOutputs(network), gen, node)
+
+      
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the primary inputs of a network.]
+
+  Description [This macro iterates over the primary inputs of a network. It is
+  an error to modify the primary inputs of a network while iterating its
+  primary inputs.]
+
+  SideEffects  []
+
+  SeeAlso      [Ntk_NetworkForEachPrimaryOutput Ntk_NetworkForEachPseudoInput
+  Ntk_NetworkForEachInput] 
+
+******************************************************************************/
+#define Ntk_NetworkForEachPrimaryInput(                                  \
+  /* Ntk_Network_t * */ network /* network to iterate primary inputs */, \
+  /* lsGen */           gen     /* local variable for iterator */,       \
+  /* Ntk_Node_t * */    input   /* primary input of network */           \
+)                                                                        \
+  lsForEachItem(Ntk_NetworkReadPrimaryInputs(network), gen, input)
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the pseudo inputs of a network.]
+
+  Description [This macro iterates over the pseudo inputs of a network. It is
+  an error to modify the pseudo inputs of a network while iterating its
+  pseudo inputs.]
+
+  SideEffects  []
+
+  SeeAlso      [Ntk_NetworkForEachPrimaryInput Ntk_NetworkForEachInput]
+
+******************************************************************************/
+#define Ntk_NetworkForEachPseudoInput(                                  \
+  /* Ntk_Network_t * */ network /* network to iterate pseudo inputs */, \
+  /* lsGen */           gen     /* local variable for iterator */,      \
+  /* Ntk_Node_t * */    input   /* pseudo input of network */           \
+)                                                                       \
+  lsForEachItem(Ntk_NetworkReadPseudoInputs(network), gen, input)
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the inputs of a network.]
+
+  Description [This macro iterates over the primary inputs and pseudo inputs
+  of a network. It is an error to modify the inputs of a network while
+  iterating its inputs.]
+
+  SideEffects  []
+
+  SeeAlso      [Ntk_NetworkForEachPrimaryInput Ntk_NetworkForEachPseudoInput]
+
+******************************************************************************/
+#define Ntk_NetworkForEachInput(                                     \
+  /* Ntk_Network_t * */ network /* network to iterate inputs */,     \
+  /* lsGen */           gen     /* local variable for iterator */,   \
+  /* Ntk_Node_t * */    input   /* input of network */               \
+)                                                                    \
+  lsForEachItem(Ntk_NetworkReadInputs(network), gen, input)
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over the primary outputs of a network.]
+
+  Description [This macro iterates over the primary outputs of a network. It is
+  an error to modify the primary outputs of a network while iterating its
+  primary outputs.]
+
+  SideEffects  []
+
+  SeeAlso      [Ntk_NetworkForEachPrimaryLatch Ntk_NetworkForEachLatch]
+
+******************************************************************************/
+#define Ntk_NetworkForEachPrimaryOutput(                                   \
+  /* Ntk_Network_t * */ network /* network to iterate primary outputs */,  \
+  /* lsGen */           gen     /* local variable for iterator */,         \
+  /* Ntk_Node_t * */    po      /* primary output of network */            \
+)                                                                          \
+  lsForEachItem(Ntk_NetworkReadPrimaryOutputs(network), gen, po)
+
+
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void Ntk_Init(void);
+EXTERN void Ntk_End(void);
+EXTERN Ntk_Network_t * Ntk_HrcManagerReadCurrentNetwork(Hrc_Manager_t *hmgr);
+EXTERN Ntk_Network_t * Ntk_HrcNodeConvertToNetwork(Hrc_Node_t *hrcNode, boolean buildMvfs, lsList abstractedNames);
+EXTERN array_t * Ntk_NodeComputeTransitiveFanoutNodes(array_t * nodeArray, int depth);
+EXTERN array_t * Ntk_NodeComputeTransitiveFanInputNodes(array_t * nodeArray, int depth);
+EXTERN array_t * Ntk_NodeComputeCombinationalSupport(Ntk_Network_t *network, array_t * nodeArray, boolean stopAtLatches);
+EXTERN array_t * Ntk_NodeComputeTransitiveFaninNodes(Ntk_Network_t *network, array_t * nodeArray, boolean stopAtLatches, boolean combInputsOnly);
+
+EXTERN st_table * Ntk_RegionFindNodes(array_t *roots, st_table *leaves);
+EXTERN st_table * Ntk_NetworkComputeLatchDependencies(Ntk_Network_t * network);
+EXTERN boolean Ntk_NetworkTestIsAcyclic(Ntk_Network_t * network);
+EXTERN boolean Ntk_NetworkTestLeavesCoverSupportOfRoots(Ntk_Network_t *network, array_t *roots, st_table *leaves);
+EXTERN lsList Ntk_NetworkComputeTopologicalOrder(Ntk_Network_t *network, array_t *rootNodesArray, st_table *leafNodesTable);
+EXTERN char * Ntk_NodeReadName(Ntk_Node_t * node);
+EXTERN Ntk_Network_t * Ntk_NodeReadNetwork(Ntk_Node_t * node);
+EXTERN Var_Variable_t * Ntk_NodeReadVariable(Ntk_Node_t * node);
+EXTERN int Ntk_NodeReadOutputIndex(Ntk_Node_t * node);
+EXTERN int Ntk_NodeReadMddId(Ntk_Node_t * node);
+EXTERN void Ntk_NodeSetMddId(Ntk_Node_t * node, int id);
+EXTERN void * Ntk_NodeReadUndef(Ntk_Node_t * node);
+EXTERN void Ntk_NodeSetUndef(Ntk_Node_t * node, void * value);
+EXTERN boolean Ntk_NodeTestIsPrimaryInput(Ntk_Node_t * node);
+EXTERN boolean Ntk_NodeTestIsPseudoInput(Ntk_Node_t * node);
+EXTERN boolean Ntk_NodeTestIsInput(Ntk_Node_t * node);
+EXTERN boolean Ntk_NodeTestIsUndefined(Ntk_Node_t * node);
+EXTERN boolean Ntk_NodeTestIsLatch(Ntk_Node_t * node);
+EXTERN boolean Ntk_NodeTestIsNextStateNode(Ntk_Node_t * node);
+EXTERN boolean Ntk_NodeTestIsShadow(Ntk_Node_t * node);
+EXTERN boolean Ntk_NodeTestIsCombInput(Ntk_Node_t * node);
+EXTERN boolean Ntk_NodeTestIsCombOutput(Ntk_Node_t * node);
+EXTERN boolean Ntk_NodeTestIsCombinational(Ntk_Node_t * node);
+EXTERN boolean Ntk_NodeTestIsPrimaryOutput(Ntk_Node_t * node);
+EXTERN boolean Ntk_NodeTestIsLatchDataInput(Ntk_Node_t * node);
+EXTERN boolean Ntk_NodeTestIsLatchInitialInput(Ntk_Node_t * node);
+EXTERN boolean Ntk_NodeTestIsConstant(Ntk_Node_t * node);
+EXTERN Ntk_Node_t * Ntk_NodeReadShadow(Ntk_Node_t * node);
+EXTERN Ntk_Node_t * Ntk_ShadowReadOrigin(Ntk_Node_t * shadow);
+EXTERN Ntk_Node_t * Ntk_LatchReadDataInput(Ntk_Node_t * node);
+EXTERN Ntk_Node_t * Ntk_LatchReadInitialInput(Ntk_Node_t * node);
+EXTERN int Ntk_NodeReadNumFanins(Ntk_Node_t * node);
+EXTERN int Ntk_NodeReadNumFanouts(Ntk_Node_t * node);
+EXTERN Ntk_Node_t * Ntk_NodeReadFaninNode(Ntk_Node_t * node, int faninIndex);
+EXTERN int Ntk_NodeReadFaninIndex(Ntk_Node_t * node, Ntk_Node_t * faninNode);
+EXTERN array_t * Ntk_NodeReadFanins(Ntk_Node_t * node);
+EXTERN array_t * Ntk_NodeReadFanouts(Ntk_Node_t * node);
+EXTERN void Ntk_NodeSetFanins(Ntk_Node_t * node, array_t *faninArray);
+EXTERN void Ntk_NodeSetFanouts(Ntk_Node_t * node, array_t *fanoutArray);
+EXTERN char * Ntk_NodeObtainTypeAsString(Ntk_Node_t * node);
+EXTERN void Ntk_NetworkWriteBlifMv(FILE *fp, Ntk_Network_t *network, boolean promotePseudo);
+EXTERN void Ntk_NodePrint(FILE * fp, Ntk_Node_t * node, boolean printIo, boolean printTableStats);
+EXTERN Ntk_Node_t * Ntk_NodeCreateInNetwork(Ntk_Network_t * network, char * name, Var_Variable_t *variable);
+EXTERN void Ntk_NodeDeclareAsLatch(Ntk_Node_t * latch, char * dataName, char * initName);
+EXTERN void Ntk_NodeDeclareAsPrimaryInput(Ntk_Node_t * node);
+EXTERN void Ntk_NodeDeclareAsPrimaryOutput(Ntk_Node_t * node);
+EXTERN void Ntk_NodeDeclareAsShadow(Ntk_Node_t * shadow, Ntk_Node_t * origin);
+EXTERN void Ntk_NodeFree(Ntk_Node_t * node);
+EXTERN char * Ntk_NetworkReadName(Ntk_Network_t * network);
+EXTERN mdd_manager * Ntk_NetworkReadMddManager(Ntk_Network_t * network);
+EXTERN void Ntk_NetworkSetMddManager(Ntk_Network_t * network, mdd_manager * mddManager);
+EXTERN mdd_manager * Ntk_NetworkInitializeMddManager(Ntk_Network_t * network);
+EXTERN bdd_reorder_type_t Ntk_NetworkReadDynamicVarOrderingMethod(Ntk_Network_t * network);
+EXTERN void Ntk_NetworkSetDynamicVarOrderingMethod(Ntk_Network_t * network, bdd_reorder_type_t dynVarOrdMethod, bdd_reorder_verbosity_t verbosity);
+EXTERN void * Ntk_NetworkReadUndef(Ntk_Network_t * network);
+EXTERN void Ntk_NetworkSetUndef(Ntk_Network_t * network, void * value);
+EXTERN Ntk_Node_t * Ntk_NetworkFindNodeByMddId(Ntk_Network_t * network, int mddId);
+EXTERN Ntk_Node_t * Ntk_NetworkFindNodeByActualName(Ntk_Network_t * network, char * name);
+EXTERN Ntk_Node_t * Ntk_NetworkFindNodeByName(Ntk_Network_t * network, char * name);
+EXTERN char * Ntk_NetworkReadActualNameFromFormalName(Ntk_Network_t * network, char * formalName);
+EXTERN void Ntk_NetworkInsertFormalNameToActualName(Ntk_Network_t * network, char * formalName, char * actualName);
+EXTERN int Ntk_NetworkReadNumNodes(Ntk_Network_t * network);
+EXTERN int Ntk_NetworkReadNumLatches(Ntk_Network_t * network);
+EXTERN int Ntk_NetworkReadNumCombInputs(Ntk_Network_t * network);
+EXTERN int Ntk_NetworkReadNumCombOutputs(Ntk_Network_t * network);
+EXTERN int Ntk_NetworkReadNumPrimaryInputs(Ntk_Network_t * network);
+EXTERN int Ntk_NetworkReadNumPseudoInputs(Ntk_Network_t * network);
+EXTERN int Ntk_NetworkReadNumInputs(Ntk_Network_t * network);
+EXTERN int Ntk_NetworkReadNumPrimaryOutputs(Ntk_Network_t * network);
+EXTERN lsList Ntk_NetworkReadNodes(Ntk_Network_t * network);
+EXTERN lsList Ntk_NetworkReadCombInputs(Ntk_Network_t * network);
+EXTERN lsList Ntk_NetworkReadCombOutputs(Ntk_Network_t * network);
+EXTERN lsList Ntk_NetworkReadLatches(Ntk_Network_t * network);
+EXTERN lsList Ntk_NetworkReadPrimaryInputs(Ntk_Network_t * network);
+EXTERN lsList Ntk_NetworkReadPseudoInputs(Ntk_Network_t * network);
+EXTERN lsList Ntk_NetworkReadInputs(Ntk_Network_t * network);
+EXTERN lsList Ntk_NetworkReadPrimaryOutputs(Ntk_Network_t * network);
+EXTERN boolean Ntk_NetworkAddApplInfo(Ntk_Network_t * network, char * key, Ntk_ApplInfoFreeFn freeFn, void * data);
+EXTERN boolean Ntk_NetworkSetApplInfo(Ntk_Network_t * network, char * key, Ntk_ApplInfoFreeFn freeFn, void * data);
+EXTERN void * Ntk_NetworkReadApplInfo(Ntk_Network_t * network, char * key);
+EXTERN boolean Ntk_NetworkFreeApplInfo(Ntk_Network_t * network, char * key);
+EXTERN Ntk_Network_t * Ntk_NetworkAlloc(char * name);
+EXTERN void Ntk_NetworkFree(Ntk_Network_t * network);
+EXTERN void Ntk_NetworkFreeCallback(void * data);
+EXTERN void Ntk_NetworkPrint(FILE * fp, Ntk_Network_t * network, boolean printIo, boolean printTableStats);
+EXTERN void Ntk_NetworkPrintStats(FILE * fp, Ntk_Network_t * network);
+EXTERN Ntk_Network_t * Ntk_NetworkDuplicate(Ntk_Network_t * oldNetwork);
+EXTERN void Ntk_NetworkAppendNetwork(Ntk_Network_t * network1, Ntk_Network_t * network2, st_table *name2ToName1);
+EXTERN int Ntk_NetworkPrintDot(FILE *fp, Ntk_Network_t *network);
+EXTERN void Ntk_NetworkSweep(Ntk_Network_t *network, int verbosity);
+EXTERN boolean Ntk_NodeRemoveFromNetwork(Ntk_Network_t *network, Ntk_Node_t *node, int force, boolean removeFromNodeList, int verbosity);
+EXTERN void Ntk_NetworkSetMAigManager(Ntk_Network_t * network, mAig_Manager_t * mAigManager);
+EXTERN mAigEdge_t Ntk_NodeReadMAigId(Ntk_Node_t * node);
+EXTERN mAig_Manager_t * Ntk_NetworkReadMAigManager(Ntk_Network_t * network);
+EXTERN void Ntk_NodeSetMAigId(Ntk_Node_t * node, mAigEdge_t mAigId);
+EXTERN void Ntk_NodeSetTable(Ntk_Node_t * node, Tbl_Table_t *table);
+EXTERN Tbl_Table_t * Ntk_NodeReadTable(Ntk_Node_t * node);
+EXTERN void Ntk_NodeDeclareAsPseudoInput(Ntk_Node_t * node, Tbl_Table_t * table, int outputIndex);
+EXTERN void Ntk_NodeDeclareAsCombinational(Ntk_Node_t * node, Tbl_Table_t * table, array_t * inputNames, int outputIndex);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _NTK */
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/ntk/ntk.make
===================================================================
--- vis_dev/vis-2.3/src/ntk/ntk.make	(revision 14)
+++ vis_dev/vis-2.3/src/ntk/ntk.make	(revision 14)
@@ -0,0 +1,4 @@
+CSRC += ntkCmd.c ntkFlt.c ntkGraph.c ntkNode.c ntkNtk.c ntkSweep.c
+HEADERS += ntk.h ntkInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/ntk/ntkCmd.c
===================================================================
--- vis_dev/vis-2.3/src/ntk/ntkCmd.c	(revision 14)
+++ vis_dev/vis-2.3/src/ntk/ntkCmd.c	(revision 14)
@@ -0,0 +1,1101 @@
+/**CFile***********************************************************************
+
+  FileName    [ntkCmd.c]
+
+  PackageName [ntk]
+
+  Synopsis    [Command interface to the ntk package.]
+
+  Author      [Adnan Aziz, Tom Shiple]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ntkInt.h"
+
+static char rcsid[] UNUSED = "$Id: ntkCmd.c,v 1.19 2010/04/09 23:44:05 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+/*
+ * States of the state machine used to parse the input variable name list file.
+ */
+#define STATE_TEST 0 /* next char is in first column */
+#define STATE_WAIT 1 /* wait until end of line '\n' is reached */
+#define STATE_IN   2 /* parsing a variable name */
+
+/*
+ * Maximum permissible length of a variable name in the input variable name list file.
+ */
+#define MAX_NAME_LENGTH 200
+
+int NtkDebug;
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandPrintNetworkStats(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandPrintNetwork(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandPrintNetworkDot(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandWriteNetworkBlifMv(Hrc_Manager_t ** hmgr, int  argc, char ** argv);
+static int CommandFlattenHierarchy(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandTestNetworkAcyclic(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandInitVerify(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandNetworkSweep(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static boolean FileReadNameList(FILE * fp, lsList * nameList, int verbose);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the network package.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_End]
+
+******************************************************************************/
+void
+Ntk_Init(void)
+{
+  Cmd_CommandAdd("print_network_stats",   CommandPrintNetworkStats,   0);
+  Cmd_CommandAdd("print_network",         CommandPrintNetwork,        0);
+  Cmd_CommandAdd("print_network_dot",     CommandPrintNetworkDot,     0);
+  Cmd_CommandAdd("flatten_hierarchy",     CommandFlattenHierarchy,    1);
+  Cmd_CommandAdd("test_network_acyclic",  CommandTestNetworkAcyclic,  0);
+  Cmd_CommandAdd("init_verify",           CommandInitVerify,          0);
+  Cmd_CommandAdd("network_sweep",         CommandNetworkSweep,        1);
+  Cmd_CommandAdd("write_network_blif_mv", CommandWriteNetworkBlifMv,  0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Ends the network package.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_Init]
+
+******************************************************************************/
+void
+Ntk_End(void)
+{
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the current network of a hierarchy manager.]
+
+  Description [Returns the network of the current node of a hierarchy
+  manager. Assumes hmgr is non-NULL. If the current node or network is NULL,
+  then a message is printed to vis_stderr, and NULL is returned.]
+
+  SideEffects []
+
+  SeeAlso     [Hrc_ManagerReadCurrentNode]
+
+******************************************************************************/
+Ntk_Network_t *
+Ntk_HrcManagerReadCurrentNetwork(Hrc_Manager_t *hmgr)
+{
+  Hrc_Node_t *currentNode;
+  Ntk_Network_t *network;
+
+  assert(hmgr != NIL(Hrc_Manager_t));
+  currentNode = Hrc_ManagerReadCurrentNode(hmgr);
+  if (currentNode == NIL(Hrc_Node_t)) {
+    (void) fprintf(vis_stderr, "The hierarchy manager is empty.  Read in design.\n");
+    return NIL(Ntk_Network_t);
+  }
+
+  network = (Ntk_Network_t *) Hrc_NodeReadApplInfo(currentNode,
+                                                   NTK_HRC_NODE_APPL_KEY);
+  if (network == NIL(Ntk_Network_t)) {
+    (void) fprintf(vis_stdout, "There is no network. Use flatten_hierarchy.\n");
+    return NIL(Ntk_Network_t);
+  }
+
+  return network;
+}
+
+  
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the print_network_stats command.]
+
+  CommandName [print_network_stats]
+
+  CommandSynopsis [print statistics about the flattened network]
+
+  CommandArguments [\[-h\]]
+
+  CommandDescription [Prints the following statistics about the flattened
+  network:
+
+  <dl>
+  
+  <li> <b>name:</b> the name of the flattened network
+
+  <li> <b>combinational:</b> the number of nodes which have a table defining
+  the function of the node (excludes pseudo inputs)
+
+  <li> <b>primary inputs:</b> the number of primary input nodes of the
+  flattened network
+
+  <li> <b>primary outputs:</b> the number of primary output nodes of the
+  flattened network
+
+  <li> <b>latches:</b> the number of (multi-valued) latches
+
+  <li> <b>pseudo inputs:</b> the number of pseudo input nodes of the
+  flattened network
+
+  <li> <b>constants:</b> the number of combinational nodes that implement a
+  multi-valued constant
+
+  <li> <b>edges:</b> the number of fanouts in the network (e.g. if the output
+  of a node is used in two places, this contributes two to the sum)
+
+  </dl>
+
+  Note that <tt>flatten_hierarchy</tt> must be called before this command.<p>
+
+  Example output:
+  <pre>
+  small  combinational=2  pi=2  po=0  latches=1  pseudo=0  const=1  edges=4
+  </pre>
+
+  Command options:<p>  
+
+  <dl><dt> -h
+  <dd> Print the command usage.<p> 
+  </dl>
+
+  ]
+  
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandPrintNetworkStats(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int            c;
+  Ntk_Network_t *network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+
+  /*
+   * Parse the command line.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "h")) != EOF) {
+    switch (c) {
+      case 'h':
+        goto usage;
+      default:
+        goto usage;
+    }
+  }
+  
+  if (network == NIL(Ntk_Network_t)) {
+    return 1;
+  }
+
+  Ntk_NetworkPrintStats(vis_stdout, network);
+  return 0;		/* normal exit */
+
+usage:
+  (void) fprintf(vis_stderr, "usage: print_network_stats [-h]\n");
+  (void) fprintf(vis_stderr, "   -h  print the command usage\n");
+  return 1;		/* error exit */
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the print_network command.]
+
+  CommandName [print_network]
+
+  CommandSynopsis [print information about the flattened network]
+
+  CommandArguments [\[-f\] \[-h\] \[-t\]]
+
+  CommandDescription [Prints the name of the flattened network, and
+  information about each node.  For each node, prints the following:
+
+  <dl>
+
+  <li> <b>name:</b> the name of the node
+
+  <li> <b>mdd:</b> MDD id (-1 is uninitialized)
+
+  <li> <b>type:</b> one of combinational, primary-input, pseudo-input, latch,
+  or shadow
+
+  <li> <b>derived attributes:</b> list of derived attributes of the node
+
+  </dl>
+
+  See the ntk documentation for more information on types and attributes. The
+  following is an example describing information associated with a node.
+
+  <pre>
+  small.latch_in: mdd=2, combinational; data-input comb-output
+  </pre>
+
+  The flattened name of the node is "small.latch_in", its MDD id is 2, it is
+  of type combinational, and it is both a data input to a latch, and a
+  combinational output.<p>
+  
+  Command options:<p>  
+
+  <dl>
+
+  <dt> -f
+  <dd> Print the fanins and fanouts of each node.<p> 
+
+  <dt> -h
+  <dd> Print the command usage.<p> 
+
+  <dt> -t
+  <dd> Print table statistics for those nodes having tables.<p> 
+
+  </dl>]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandPrintNetwork(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int            c;
+  boolean        printIo         = FALSE;  /* default */
+  boolean        printTableStats = FALSE;  /* default */
+  Ntk_Network_t *network         = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+
+  /*
+   * Parse the command line.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "fth")) != EOF) {
+    switch (c) {
+      case 'f':
+        printIo = TRUE;
+        break;
+      case 't':
+        printTableStats = TRUE;
+        break;
+      case 'h':
+        goto usage;
+      default:
+        goto usage;
+    }
+  }
+  
+  if (network == NIL(Ntk_Network_t)) {
+    return 1;
+  }
+
+  Ntk_NetworkPrint(vis_stdout, network, printIo, printTableStats);
+  return 0;		/* normal exit */
+
+usage:
+  (void) fprintf(vis_stderr, "usage: print_network [-f] [-h] [-t]\n");
+  (void) fprintf(vis_stderr, "   -f  print fanins and fanouts of nodes\n");
+  (void) fprintf(vis_stderr, "   -h  print the command usage\n");
+  (void) fprintf(vis_stderr, "   -t  print table stats of nodes having tables\n");
+  return 1;		/* error exit */
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the print_network_dot command.]
+
+  CommandName [print_network_dot]
+
+  CommandSynopsis [print a dot description of the flattened network]
+
+  CommandArguments [\[-h\] &lt;file_name&gt;]
+
+  CommandDescription [Write a file in the format taken by the tool <tt>dot</tt>
+  depicting the topology of the network. Dot is a tool that given a description
+  of a graph in a certain format it produces a postscript print of the
+  graph. For more information about <tt>dot</tt> look in <a
+  href="http://www.research.att.com/orgs/ssr/book/reuse">
+  http://www.research.att.com/orgs/ssr/book/reuse</a>. Once a dot file is
+  produced with this command, the shell command <tt>dot -Tps <filename>
+  &gt;<file>.ps</tt> will produce the postscript file depicting the network.<p>
+
+  If no argument is specified on the command line, the description is written
+  to the standard output.<p>
+
+  Command options:<p>
+  <dl><dt> -h
+  <dd> Print the command usage.
+  </dl>]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandPrintNetworkDot(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  FILE *fp;
+  int c, status;
+  Ntk_Network_t *network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc,argv,"h")) != EOF){
+    switch(c){
+      case 'h':
+        goto usage;
+      default:
+        goto usage;
+    }
+  }
+
+  /* Check if the network has been read in */
+  if (network == NIL(Ntk_Network_t)) {
+    return 1;
+  }
+
+  if (argc == 1) {
+    fp = stdout;
+  }
+  else if (argc == 2) {
+    fp = Cmd_FileOpen(*(++argv), "w", NIL(char *), /* silent */ 1);
+    if (fp == NIL(FILE)) {
+      (void) fprintf(vis_stderr, "Cannot write to %s\n", *argv);
+      return 1;
+    }
+  }
+  else {
+    goto usage;
+  }
+
+  error_init();
+  status = Ntk_NetworkPrintDot(fp, network);
+  (void) fprintf(vis_stderr, "%s", error_string());
+  fflush(fp);
+  if (fp != stdout) {
+    (void) fclose(fp);
+  }
+  return (status ? 0 : 1);
+
+ usage:
+  (void) fprintf(vis_stderr, "usage: print_network_dot [-h] [file]\n");
+  (void) fprintf(vis_stderr, "    -h\t\tprint the command usage\n");
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Write a (flattened) network in blif-MV format.]
+
+  CommandName [write_network_blif_mv]
+
+  CommandSynopsis [write a blif-MV description of the flattened network]
+
+  CommandArguments [\[-h\] \[-p\] &lt;file_name&gt;]
+
+  CommandDescription [Write a file in Blif-MV format describing the
+  network. <p>
+
+  If no argument is specified on the command line, the description is written
+  to the vis standard output.<p>
+
+  Command options:<p>
+  <dl><dt> -h
+  <dd> Print the command usage.
+  <dt> -p
+  <dd> Promote pseudo inputs to primary inputs.
+  </dl>]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandWriteNetworkBlifMv(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  FILE *fp;
+  int c;
+  boolean promotePseudo = FALSE;
+  Ntk_Network_t *network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+
+  /* Check whether the network has been created. */
+  if (network == NIL(Ntk_Network_t)) {
+    return 1;
+  }
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc,argv,"hp")) != EOF){
+    switch(c){
+    case 'h':
+      goto usage;
+    case 'p':
+      promotePseudo = TRUE;
+      argv++;
+      argc--;
+      break;
+    default:
+      goto usage;
+    }
+  }
+
+  if (argc == 1) {
+    fp = vis_stdout;
+  } else if (argc == 2) {
+    fp = Cmd_FileOpen(*(++argv), "w", NIL(char *), /* silent */ 1);
+    if (fp == NIL(FILE)) {
+      (void) fprintf(vis_stderr, "Cannot write to %s\n", *argv);
+      return 1;
+    }
+  } else {
+    goto usage;
+  }
+
+  error_init();
+  Ntk_NetworkWriteBlifMv(fp, network, promotePseudo);
+  (void) fprintf(vis_stderr, "%s", error_string());
+  fflush(fp);
+  if (fp != vis_stdout) {
+    (void) fclose(fp);
+  }
+  return 1;
+
+ usage:
+  (void) fprintf(vis_stderr, "usage: write_network_blif_mv [-h] [file]\n");
+  (void) fprintf(vis_stderr, "    -h\t\tprint the command usage\n");
+  (void) fprintf(vis_stderr, "    -p\t\tpromote pseudo inputs to primary inputs\n");
+  return 1;
+
+} /* CommandWriteNetworkBlifMv */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the flatten_hierarchy command.]
+
+  CommandName [flatten_hierarchy]
+
+  CommandSynopsis [create a flattened network]
+
+  CommandArguments [\[-a &lt;file&gt;\] \[-b\] \[-h\] \[-s\] \[-v #\]]
+
+  CommandDescription [Creates a flattened network from a hierarchical
+  description.  The flattened network encompasses everything from the
+  current node of the hierarchy (reached by the command <tt>cd</tt>),
+  down to and including the leaves.  It creates a view with the
+  hierarchy removed, but retains the multi-level logic structure.  The
+  resulting flattened network is stored with the current node. Every
+  table in the flattened network is checked whether it is completely
+  specified and deterministic. This is the starting point for
+  verification related commands. <p>
+
+  A limited form of abstraction can be done by providing a list of variables
+  to treat as primary inputs.  See the information under &lt;file&gt;
+  below.<p>
+  
+  The verification part of VIS requires the functions specified by the BLIF-MV
+  tables to be completely specified and deterministic.  These conditions are
+  checked during the flattening process; if a table is found that is
+  incompletely specified or is nondeterministic, then an error message is
+  written and a flattened network is not created.  The exception to this
+  rule is tables specifying "pseudo inputs"; these are tables with no inputs,
+  and a single output that can take more than one value.  Such tables are
+  generated by vl2mv to model the "$ND" construct in Verilog.<p>
+  
+  If this command is invoked a second time from the same point in the
+  hierarchy, the previous network is deleted and a new one is created.  This
+  is the tactic to follow if you want to change some aspect of the current
+  network, such as MDD variable ordering or <tt>image_method</tt>.<p>
+
+  Command options:<p>  
+
+  <dl>
+
+  <dt> -a &lt;file&gt;
+
+  <dd> A file containing names of variables, used to specify which variables
+  to abstract. The name of a variable is the full hierarchical path name,
+  starting from just after the current hierarchy node (i.e., if the current
+  node is foo, and you want to refer to variable x in foo, then just use x).
+  A variable should appear at most once in the file.  Each variable name
+  should appear at the beginning of a new line, with no white space preceding
+  it.  The end of a variable name is marked by white space, and any other text
+  on the rest of the line is ignored.  Any line starting with "#" or white
+  space is ignored.  A sample file is shown here.<p>
+
+  <pre>
+  # variables to abstract to model check liveness property
+  choosing0 
+  p0.pc     
+  </pre>
+
+  For each variable x appearing in the file, a new primary input node named
+  x$ABS is created to drive all the nodes that were previously driven by x.
+  Hence, the node x will not have any fanouts; however, x and its transitive
+  fanins will remain in the network. <p>
+
+  Abstracting a net effectively allows it to take any value in its range, at
+  every clock cycle. This mechanism can be used to perform manual
+  abstractions.  The variables to abstract should not affect the correctness
+  of the property being checked.  This usually simplifies the network, and
+  permits some verification tasks to complete that would not otherwise.  Note,
+  however, that by increasing the behavior of the system, false negatives are
+  possible when checking universal properties, and false positives are
+  possible when checking existential properties. <p>
+
+  A convenient way of generating the hierarchical variable names is by using
+  the write_order command. Note that abstracting next state variables has no
+  effect.<p>
+
+
+  <dt> -b
+  <dd> This option has no effect any longer.<p>
+
+  <dt> -h
+  <dd> Print the command usage. <p>
+
+  <dt> -s
+  <dd> Do not perform a sweep. <p>
+
+  <dt> -v #
+  <dd> Print debug information.
+  <dd>
+
+  0: (default) Nothing is printed out.<p>
+  
+  >= 2: Prints the variables read from the input file.<p>
+  
+  
+  </dl>
+
+  ]
+  
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandFlattenHierarchy(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int            c;
+  Ntk_Network_t *network;
+  char          *fileName    = NIL(char);
+  int            verbose     = 0;       /* default */
+  int            sweep       = 1;  
+  lsList         varNameList = (lsList) NULL;
+  Hrc_Node_t    *currentNode = Hrc_ManagerReadCurrentNode(*hmgr);
+  
+  /*
+   * Parse the command line.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "a:bhsv:")) != EOF) {
+    switch (c) {
+      case 'a':
+        fileName = util_optarg;
+        break;
+      case 'b':
+        break;
+      case 'h':
+        goto usage;
+      case 's':
+        sweep = 0;
+        break;        
+      case 'v':
+        verbose = atoi(util_optarg);
+        break;
+      default:
+        goto usage;
+    }
+  }
+
+  if (currentNode == NIL(Hrc_Node_t)) { 
+    (void) fprintf(vis_stdout, "The hierarchy manager is empty.  Read in design.\n");
+    return 1;
+  }
+    
+  /*
+   * Process the file containing the variable names.
+   */
+  if (fileName != NIL(char)) {
+    FILE *fp = Cmd_FileOpen(fileName, "r", NIL(char *), 0);
+    if (fp == NIL(FILE)) {
+      return 1;
+    }
+    else {
+      boolean status;
+      
+      error_init();
+      status = FileReadNameList(fp, &varNameList, verbose);
+      (void) fclose(fp);
+      if (status == FALSE) {
+        (void) fprintf(vis_stderr, "Error reading variable name file:\n");
+        (void) fprintf(vis_stderr, "%s", error_string());
+        (void) fprintf(vis_stderr, "Cannot perform flatten_hierarchy.\n");
+        return 1;
+      }
+    }
+  }
+
+  
+  /*
+   * If a network already exists, delete it.  Then create the new one, and
+   * register it with the hrcNode.
+   */
+  network = (Ntk_Network_t *) Hrc_NodeReadApplInfo(currentNode,
+                                                   NTK_HRC_NODE_APPL_KEY);
+  if (network != NIL(Ntk_Network_t)) {
+    (void) fprintf(vis_stdout, "Deleting current network and creating new one.\n");
+    Hrc_NodeFreeApplInfo(currentNode, NTK_HRC_NODE_APPL_KEY);
+  }
+
+  error_init();
+
+  network = Ntk_HrcNodeConvertToNetwork(currentNode, TRUE, varNameList);
+
+  /* Clean up the varNameList. */
+  if (varNameList != (lsList) NULL) {
+    lsGen  gen;
+    char  *varName;
+    
+    lsForEachItem(varNameList, gen, varName) {
+      FREE(varName);
+    }
+    (void) lsDestroy(varNameList, (void (*) (lsGeneric)) NULL);
+  }
+  /* sweep network */
+  if (network != NIL(Ntk_Network_t) && sweep ==1) {
+    Ntk_NetworkSweep(network, verbose); 
+  }
+  
+  if (network == NIL(Ntk_Network_t)) {
+    (void) fprintf(vis_stderr, "%s", error_string());
+    (void) fprintf(vis_stderr, "Cannot perform flatten_hierarchy.\n");
+    return 1;
+  }
+  
+  Hrc_NodeAddApplInfo(currentNode, NTK_HRC_NODE_APPL_KEY,
+                      (Hrc_ApplInfoFreeFn) Ntk_NetworkFreeCallback,
+                      (Hrc_ApplInfoChangeFn) NULL,  /* not currently used by hrc */
+                      (void *) network);
+
+  return 0;		/* normal exit */
+
+usage:
+  (void) fprintf(vis_stderr, "usage: flatten_hierarchy [-a file] [-b] [-h] [-s] [-v #]\n");
+  (void) fprintf(vis_stderr, "   -a file  variables to abstract\n");
+  (void) fprintf(vis_stderr, "   -b       not used any longer\n");
+  (void) fprintf(vis_stderr, "   -h       print the command usage\n");
+  (void) fprintf(vis_stderr, "   -s       do not perform a sweep\n");  
+  (void) fprintf(vis_stderr, "   -v #     verbosity level\n");
+  return 1;		/* error exit */
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the test_network_acyclic command.]
+
+  CommandName [test_network_acyclic]
+
+  CommandSynopsis [determine whether the network is acyclic]
+
+  CommandArguments [\[-h\]]
+
+  CommandDescription [If the flattened network has a combinational
+  cycle, then prints information about one of the cycles.  If no cycles are
+  present, then it prints a message to this effect.<p>  
+
+  Command options:<p>  
+
+  <dl><dt> -h
+  <dd> Print the command usage.<p> 
+  </dl>
+  ]
+  
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandTestNetworkAcyclic(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int            c;
+  Ntk_Network_t *network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+
+  /*
+   * Parse the command line.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "h")) != EOF) {
+    switch (c) {
+      case 'h':
+        goto usage;
+      default:
+        goto usage;
+    }
+  }
+  
+  if (network == NIL(Ntk_Network_t)) {
+    return 1;
+  }
+
+  error_init();
+  if (Ntk_NetworkTestIsAcyclic(network) == 0) {
+    (void) fprintf(vis_stdout, "Combinational cycle found: ");
+    (void) fprintf(vis_stdout, "%s", error_string());
+    (void) fprintf(vis_stdout, "\n");
+  }
+  else {
+    (void) fprintf(vis_stdout, "Network has no combinational cycles\n");
+  }
+  return 0;		/* normal exit */
+
+
+usage:
+  (void) fprintf(vis_stderr, "usage: test_network_acyclic [-h]\n");
+  (void) fprintf(vis_stderr, "   -h  print the command usage\n");
+  return 1;		/* error exit */
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the init_verify command.]
+
+  CommandName [init_verify]
+
+  CommandSynopsis [create and initialize a flattened network for verification]
+
+  CommandArguments [\[-b\] \[-h\]]
+
+  CommandDescription [This command initializes the system for verification,
+  and is equivalent to the command sequence <tt>flatten_hierarchy;
+  static_order; build_partition_mdds</tt>.  If a command returns an error
+  condition, then the sequence is aborted.  After <tt>init_verify</tt> has
+  successfully executed, various commands can be invoked, like
+  <tt>model_check</tt>, <tt>compute_reach</tt>, <tt>simulate</tt>,
+  <tt>print_network_stats</tt>, and <tt>seq_verify</tt>.<p>
+
+  Please note that init_verify does not enable dynamic variable
+  reordering. Sometimes, though, this is needed to complete building
+  the partitions, and one has to initialize the verification by hand.
+  Similarly, it may be wise to turn on dynamic variable reordering after
+  init, so that further commands complete more easily. See the help page
+  for <tt>dynamic_var_ordering</tt>.
+
+
+  <p>Command options:<p>  
+
+  <dl><dt> -b
+  <dd> This option has no effect any longer. <p>
+  </dl>
+  <dl><dt> -h
+  <dd> Print the command usage.<p> 
+  </dl>
+
+  ]
+  
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandInitVerify(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int         c;
+  Hrc_Node_t *currentNode = Hrc_ManagerReadCurrentNode(*hmgr);
+  
+  /*
+   * Parse the command line.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "bh")) != EOF) {
+    switch (c) {
+      case 'b':
+        break;
+      case 'h':
+        goto usage;
+      default:
+        goto usage;
+    }
+  }
+
+  if (currentNode == NIL(Hrc_Node_t)) { 
+    (void) fprintf(vis_stdout, "The hierarchy manager is empty.  Read in design.\n");
+    return 1;
+  }
+    
+  /*
+   * Call the commands one-by-one, returning upon the first error.
+   */
+  if (Cmd_CommandExecute(hmgr, "flatten_hierarchy")) {
+    return 1;
+  }
+  
+  if (Cmd_CommandExecute(hmgr, "static_order")) {
+    return 1;
+  }
+  
+  if (Cmd_CommandExecute(hmgr, "build_partition_mdds")) {
+    return 1;
+  }
+  
+  return 0;		/* normal exit */
+
+
+usage:
+  (void) fprintf(vis_stderr, "usage: init_verify [-b] [-h]\n");
+  (void) fprintf(vis_stderr, "   -b  not used any longer.\n");
+  (void) fprintf(vis_stderr, "   -h  print the command usage\n");
+  return 1;		/* error exit */
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the network_sweep command.]
+
+  CommandName [network_sweep]
+
+  CommandSynopsis [sweeps the network to ensure that deterministic constants
+  are removed]
+
+  CommandArguments [\[-h\]\[-v\]]
+
+  CommandDescription [This function performs a sweep on the given
+  Ntk_Network_t. It propagates all the deterministic constant nodes, and
+  removes all buffer nodes. It modifies the network.
+
+  Command options:<p>  
+
+  <dl><dt> -h
+  <dd> Print the command usage.<p> 
+  </dl>
+
+  <dl><dt> -v
+  <dd> Print debug information.<p> 
+  </dl>
+  ]
+  
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandNetworkSweep(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int		c;
+  Ntk_Network_t *network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+  int		verbosity = 0;
+
+  /*
+   * Parse the command line.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "hv")) != EOF) {
+    switch (c) {
+      case 'h':
+        goto usage;
+      case 'v':
+        verbosity = 1;
+        break;
+      default:
+        goto usage;
+    }
+  }
+  
+  if (network == NIL(Ntk_Network_t)) {
+    return 1;
+  }
+  
+  Ntk_NetworkSweep(network, verbosity);
+  return 0;
+
+usage:
+  (void) fprintf(vis_stderr, "usage: network_sweep [-h][-v]\n");
+  (void) fprintf(vis_stderr, "   -h  print the command usage\n");
+  (void) fprintf(vis_stderr, "   -v  print debug information\n");  
+  return 1;		/* error exit */
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a list of names corresponding to the names in a file.]
+
+  Description [Parses a file and builds a name list corresponding to the names
+  found in the first "column" of each line of the file.  Any line starting
+  with the comment character '#' or white space is ignored.  No checks are
+  made to see if the names are well-formed in any respect. If a problem is
+  found while parsing the file (e.g. name length exceeded), then a message is
+  written to error_string, the partial name list is freed, and the function
+  returns FALSE; otherwise, it returns TRUE, and a pointer to a list is
+  returned.]
+
+  Comment [The parser consists of 3 states.  See the documentation
+  accompanying the #defines defining the state names.  This code was adapted
+  from Ord_FileReadNodeList.]
+  
+  SideEffects []
+
+******************************************************************************/
+static boolean
+FileReadNameList(
+  FILE * fp,
+  lsList * nameList /* of char *, for return */,
+  int verbose)
+{
+  int     c;
+  int     state;
+  int     curPosition = 0;
+  char   *name;
+  char    string[MAX_NAME_LENGTH];
+  boolean returnFlag = TRUE;
+  
+  *nameList = lsCreate();
+
+  state = STATE_TEST;
+  while ((c = fgetc(fp)) != EOF) {
+
+    switch (state) {
+      case STATE_TEST:
+        /* At start of a new line. */
+        if (c == '#') {
+          /* Line starting with comment character; wait for newline */
+          state = STATE_WAIT;
+        }
+        else if ((c == ' ') || (c == '\t')) {
+          /* Line starting with white space; wait for newline */
+          state = STATE_WAIT;
+        }
+        else if (c == '\n') {
+          /* Line starting with newline; go to next line */
+          state = STATE_TEST;
+        }
+        else {
+          /* Assume starting a name. */
+          curPosition = 0;
+          string[curPosition++] = c;
+          state = STATE_IN;
+        }
+        break;
+      case STATE_WAIT:
+        /*
+         * Waiting for the newline character.
+         */
+        state = (c == '\n') ? STATE_TEST : STATE_WAIT;
+        break;
+      case STATE_IN:
+        /*
+         * Parsing a name.  If white space reached, then terminate the
+         * name and process it.  Else, continue parsing.
+         */
+        if ((c == ' ') || (c == '\n') || (c == '\t')) {
+          string[curPosition] = '\0';
+          name = util_strsav(string);
+          if (verbose > 1) {
+            (void) fprintf(vis_stdout, "Reading name: %s\n", name);
+          }
+          (void) lsNewEnd(*nameList, (lsGeneric) name, LS_NH);  
+          
+          state = (c == '\n') ? STATE_TEST : STATE_WAIT;
+        }
+        else {
+          string[curPosition++] = c;
+          if (curPosition >= MAX_NAME_LENGTH) {
+            error_append("maximum name length exceeded");
+            returnFlag = FALSE;
+          }
+          state = STATE_IN; /* redundant, but be explicit */
+        }
+        break;
+      default:
+        fail("unrecognized state");
+    }
+  }
+
+  /*
+   * Handle case where EOF terminates a name.
+   */
+  if (state == STATE_IN) {
+    string[curPosition] = '\0';
+    name = util_strsav(string);
+    if (verbose > 1) {
+      (void) fprintf(vis_stdout, "Reading name: %s\n", name);
+    }
+    (void) lsNewEnd(*nameList, (lsGeneric) name, LS_NH);  
+          
+  }
+
+  if (returnFlag) {
+    return TRUE;
+  }
+  else {
+    (void) lsDestroy(*nameList, (void (*) (lsGeneric)) NULL);
+    return FALSE;
+  }
+}
+
+  
Index: vis_dev/vis-2.3/src/ntk/ntkFlt.c
===================================================================
--- vis_dev/vis-2.3/src/ntk/ntkFlt.c	(revision 14)
+++ vis_dev/vis-2.3/src/ntk/ntkFlt.c	(revision 14)
@@ -0,0 +1,962 @@
+/**CFile***********************************************************************
+
+  FileName    [ntkFlt.c]
+
+  PackageName [ntk]
+
+  Synopsis    [Routines for creating a network from a hierarchy manager.]
+
+  Author      [Adnan Aziz, Tom Shiple]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ntkInt.h"
+
+static char rcsid[] UNUSED = "$Id: ntkFlt.c,v 1.13 2009/04/11 22:17:58 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+#define MAX_NUMBER_BDD_VARS 500
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void NetworkBuildFormalToActualTableRecursively(Ntk_Network_t *network, Hrc_Node_t *hrcNode);
+static void NetworkCreateNodesRecursively(Ntk_Network_t *network, Hrc_Node_t *hrcNode);
+static void NodeCreateAsNecessary(Ntk_Network_t *network, char *nodeName, Var_Variable_t *var);
+static boolean NetworkDeclareNodesRecursively(Ntk_Network_t *network, Hrc_Node_t *hrcNode, boolean buildMvfs, mdd_manager **mddMgr);
+static array_t * LocalArrayJoin(array_t *array1, array_t *array2);
+static array_t * TableCreateFormalInputNameArray(Tbl_Table_t *table, char *namePrefix);
+static void NameArrayFree(array_t *nameArray);
+static boolean NetworkAbstractNodes(Ntk_Network_t *network, lsList abstractedNames);
+static boolean NodeDeclareWithTable(Ntk_Node_t *node, Tbl_Table_t *table, int outIndex, char *path, boolean buildMvfs, mdd_manager *mddMgr);
+static void NetworkDeclareIONodes(Ntk_Network_t *network, Hrc_Node_t *hrcNode);
+static void NetworkDeclareLatches(Ntk_Network_t *network, Hrc_Node_t *hrcNode);
+static void MddManagerResetIfNecessary(mdd_manager **mddMgr);
+static Mvf_Function_t * LocalMvfFunctionForTable(Tbl_Table_t *table, int outIndex, mdd_manager *mddMgr, array_t *varMap, int *offset);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Builds a flat description of a subtree of hierarchy manager.]
+
+  Description [Builds a flat description of a subtree of a hierarchy manager.
+  The flattened names of variables are taken as those hierarchical names where
+  the variables are defined.  The names are relative to the "current" node
+  of the hierarchy manager, which can be set by calling
+  Hrc_ManagerSetCurrentNode() first.  Nodes are created even for unused
+  variables (i.e. variables that don't fanout to anything.)<p>
+
+  AbstractedNames is a list of char*.  If the list is not NULL, then this list
+  is interpreted as a list of variables to abstract.  If a given name in the
+  list does not correspond to the hierarchical name of a node in the network,
+  then NULL is returned, and an error message is written to error_string.
+  Otherwise, a new primary input is created to drive the net identified by the
+  variable name.  See the documentation for the command flatten_hierarchy for
+  more information.<p>
+
+  The verification routines assume deterministic and completely specified
+  tables. If a table is found that is locally non-deterministic or incompletely
+  specified, then a message is written to vis_stderr, and a NIL network is
+  returned (the non-deterministic test is not performed on non-deterministic
+  constant tables).  This test can be bypassed (in order to save time) by
+  passing FALSE for buildMvfs. Note that this should be done with extreme
+  caution, because bad tables could inadvertantly be allowed through and
+  invalidate verification results obtained downstream.<p>
+
+  Also, if a table has no inputs and more than 1 output, and its output space
+  is not complete (i.e. the outputs are correlated), then the table is
+  declared a "relation", and NIL is returned.]
+
+  SideEffects []
+
+  Comment [Proceeds in 3 phases: 1) builds a map from formals to actuals, 2)
+  adds a node for each actual (i.e. for each node that will appear in the
+  network) and 3) sets the types (and tables, where appropriate) for each
+  node.]
+
+  SeeAlso [Ntk_NetworkAlloc NetworkBuildFormalToActualTableRecursively
+  NetworkCreateNodesRecursively NetworkDeclareNodesRecursively]
+
+******************************************************************************/
+Ntk_Network_t *
+Ntk_HrcNodeConvertToNetwork(
+  Hrc_Node_t *hrcNode,
+  boolean     buildMvfs,
+  lsList abstractedNames)
+{
+  mdd_manager   *mddMgr;
+  boolean        status1     = TRUE;
+  boolean        status2     = TRUE;
+  char          *hrcNodeName = Hrc_NodeReadInstanceName(hrcNode);
+  Ntk_Network_t *network     = Ntk_NetworkAlloc(hrcNodeName);
+
+  NetworkBuildFormalToActualTableRecursively(network, hrcNode);
+  NetworkCreateNodesRecursively(network, hrcNode);
+
+  /*
+   * The MDD manager is for building temporary MDDs.  For robustness, enable
+   * reordering.
+   */
+  mddMgr = mdd_init_empty();
+  bdd_dynamic_reordering(mddMgr, BDD_REORDER_SIFT, BDD_REORDER_VERBOSITY_DEFAULT);
+  status1 = NetworkDeclareNodesRecursively(network, hrcNode, buildMvfs, &mddMgr);
+  mdd_quit(mddMgr);
+
+  if (abstractedNames != (lsList) NULL) {
+    status2 = NetworkAbstractNodes(network, abstractedNames);
+  }
+
+  if (!(status1 && status2)) {
+    Ntk_NetworkFree(network);
+    return NIL(Ntk_Network_t);
+  }
+  else {
+    return network;
+  }
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates mapping from formal names to actual names.]
+
+  Description [Loads the formal-to-actual table of network.  For each formal
+  variable name in hrcNode, maps it to a unique actual variable name.  The map
+  is many-to-one.  The rule is that a formal is resolved to the actual as high
+  in the hierarchy as possible.  Proceeds recursively by examining
+  subcircuits. Note that only formals are in the domain of the map. Also, care
+  has to be taken when looking at net in parent since they may also be
+  formals.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+NetworkBuildFormalToActualTableRecursively(
+  Ntk_Network_t *network,
+  Hrc_Node_t *hrcNode)
+{
+  st_generator *stGen;
+  char         *childName;
+  Hrc_Node_t   *childHrcNode;
+
+  /*
+   * For each child of the current hnode, process its I/O variables, and
+   * then recurse on its children.
+   */
+  Hrc_NodeForEachChild(hrcNode, stGen, childName, childHrcNode) {
+
+    int i;
+    array_t *childFormalInputs  = Hrc_NodeReadFormalInputs(childHrcNode);
+    array_t *childFormalOutputs = Hrc_NodeReadFormalOutputs(childHrcNode);
+    array_t *childFormalIoArray = LocalArrayJoin(childFormalInputs, childFormalOutputs);
+
+    array_t *childActualInputs  = Hrc_NodeReadActualInputs(childHrcNode);
+    array_t *childActualOutputs = Hrc_NodeReadActualOutputs(childHrcNode);
+    array_t *childActualIoArray = LocalArrayJoin(childActualInputs, childActualOutputs);
+
+
+    /*
+     * For each I/O variable, construct the appropriate hierarchical name for
+     * the variable in childHrcNode (formalName) and the variable in the
+     * hrcNode (actualName).  If actualName already has a corresponding
+     * actual, then use that, otherwise use actualName as is.  Add
+     * correspondence from formal (formalName) to actual (actualName).
+     */
+    for(i = 0 ; i < array_n(childActualIoArray) ; i++) {
+      Var_Variable_t *actualVar = array_fetch(Var_Variable_t *, childActualIoArray, i);
+      Var_Variable_t *formalVar = array_fetch(Var_Variable_t *, childFormalIoArray, i);
+
+      char *nodeName   = Hrc_NodeFindHierarchicalName(hrcNode, TRUE);
+      /* Special case the situation where hrcNode is current node. */
+      char *actualName = (strcmp(nodeName, ""))
+	  ? util_strcat3(nodeName, ".",
+			 Var_VariableReadName(actualVar))
+	  : util_strsav(Var_VariableReadName(actualVar));
+
+      char *childNodeName = Hrc_NodeFindHierarchicalName(childHrcNode, TRUE);
+      char *formalName = util_strcat3(childNodeName, ".",
+				      Var_VariableReadName(formalVar));
+
+      /*
+       * It is correct to call this function with actualName.  We want to
+       * check if actualVar is itself a formalVar one level up.
+       */
+      char *tempName   = Ntk_NetworkReadActualNameFromFormalName(network, actualName);
+
+      FREE(nodeName);
+      FREE(childNodeName);
+
+      /*
+       * (tempName != NIL) => this net is a formal in hrcNode
+       */
+      if (tempName != NIL(char)) {
+	FREE(actualName);
+	actualName = tempName;
+      }
+
+      /*
+       * Ntk_NetworkInsertFormalNameToActualName makes copies of the strings
+       */
+      Ntk_NetworkInsertFormalNameToActualName(network, formalName, actualName);
+
+      if (tempName == NIL(char)) {
+	FREE(actualName);
+      }
+      FREE(formalName);
+    }
+    array_free(childFormalIoArray);
+    array_free(childActualIoArray);
+
+    /*
+     * Recurse.
+     */
+    NetworkBuildFormalToActualTableRecursively(network, childHrcNode);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates placeholders for all the nodes in the network.]
+
+  Description [Working top-down, creates placeholders for all the nodes in the
+  network.  After this function is executed, each node will have a name and
+  Var_Variable_t, but nothing else.  Note that nodes are created for reset
+  logic; they are given the name of their corresponding latch, suffixed by
+  $INIT.]
+
+  SideEffects []
+
+  SeeAlso     [NodeCreateAsNecessary]
+
+******************************************************************************/
+static void
+NetworkCreateNodesRecursively(
+  Ntk_Network_t *network,
+  Hrc_Node_t    *hrcNode)
+{
+  st_generator   *stGen;
+  Var_Variable_t *var;
+  Hrc_Latch_t    *latch;
+  char           *varName;
+  char           *latchName;
+  char           *childName;
+  Hrc_Node_t     *childHrcNode;
+  char           *path = Hrc_NodeFindHierarchicalName(hrcNode, TRUE);
+  char           *separator = (char *) ((strcmp(path, "")) ? "." : "");
+
+  /*
+   * The separator is used to handle the special case when hrcNode is the
+   * current node in the hierarchy.  If it is, we don't want a "." before the
+   * variable names.
+   */
+
+  Hrc_NodeForEachVariable(hrcNode, stGen, varName, var) {
+    char *nodeName = util_strcat3(path, separator, varName);
+    NodeCreateAsNecessary(network, nodeName, var);
+    FREE(nodeName);
+  }
+
+  /*
+   * Variable for reset is the same as for present state.  Hence, iterating
+   * through the list of variables gets us just the present state.  Therefore,
+   * we need to special case the reset (or init) nodes.
+   */
+  Hrc_NodeForEachLatch(hrcNode, stGen, latchName, latch) {
+    char *partialNodeName = util_strcat3(path, separator, latchName);
+    char *nodeName        = util_strcat3(partialNodeName, "$INIT", "");
+
+    FREE(partialNodeName);
+    NodeCreateAsNecessary(network, nodeName, Hrc_LatchReadOutput(latch));
+    FREE(nodeName);
+  }
+  FREE(path);
+
+  /* Recurse. */
+  Hrc_NodeForEachChild(hrcNode, stGen, childName, childHrcNode) {
+    NetworkCreateNodesRecursively(network, childHrcNode);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Creates a node with a given name, if one doesn't already exist.]
+
+  Description [If a node with nodeName already exists in the network, then
+  does nothing.  Otherwise, creates a new node in the network with nodeName
+  and variable.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+NodeCreateAsNecessary(
+  Ntk_Network_t  *network,
+  char           *nodeName,
+  Var_Variable_t *var)
+{
+  if (Ntk_NetworkFindNodeByName(network, nodeName)) {
+    return;
+  }
+
+  (void) Ntk_NodeCreateInNetwork(network, nodeName, var);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Add functionality to the Ntk_Node_t's for this Hrc_Node_t.]
+
+  Description [Add functionality to the Ntk_Node_t's for this Hrc_Node_t.
+  Proceeds in 3 stages: 1) sets PI's and PO's; this is achieved by looking at
+  PI/POs which are not formals, 2) adds tables to combinational logic, taking
+  care to get the non-deterministic/deterministic constants right, 3) iterates
+  over latches, adding type latch to nodes which have a name correspoding to
+  this latch's ps name, and declaring the initialization logic for the
+  latch.<p>
+
+  If a table is found that is non-deterministic or incompletely specified,
+  then a message is written to vis_stderr, and FALSE is returned (the
+  non-deterministic test is not performed on non-deterministic constant
+  tables).  Also, if a table has no inputs and more than 1 output and its
+  output space is not complete, then it's declared a "relation", and FALSE is
+  returned.  However, even if FALSE is returned, the nodes are still
+  declared.<p>
+
+  The non-deterministic or incompletely specified tests can be bypassed by
+  passing FALSE for buildMvfs. See Ntk_HrcNodeConvertToNetwork for more info.]
+
+  SideEffects []
+
+******************************************************************************/
+static boolean
+NetworkDeclareNodesRecursively(
+  Ntk_Network_t *network,
+  Hrc_Node_t    *hrcNode,
+  boolean        buildMvfs,
+  mdd_manager  **mddMgr)
+{
+  int i;
+  st_generator   *stGen;
+  char           *latchName;
+  Var_Variable_t *var;
+  Hrc_Latch_t    *latch;
+  Tbl_Table_t    *table;
+  char           *childName;
+  Hrc_Node_t     *childHrcNode;
+  boolean         result = TRUE;
+  char           *path = Hrc_NodeFindHierarchicalName(hrcNode, TRUE);
+  char           *separator = (char *) ((strcmp(path, "")) ? "." : "");
+
+  /*
+   * First declare the network's PI/PO nodes.
+   */
+  NetworkDeclareIONodes(network, hrcNode);
+
+  /*
+   * Next, declare those nodes whose function is represented by a table.  Note
+   * that his iterator does not pick up those tables that define the
+   * initialization logic of latches.
+   */
+  Hrc_NodeForEachNameTable(hrcNode, i, table) {
+    int index;
+    Tbl_TableForEachOutputVar(table, index, var) {
+      boolean     status;
+      char       *fullVarName = util_strcat3(path, separator,
+					       Var_VariableReadName(var));
+      Ntk_Node_t *node        = Ntk_NetworkFindNodeByName(network, fullVarName);
+
+      FREE(fullVarName);
+      status = NodeDeclareWithTable(node, table, index, path, buildMvfs, *mddMgr);
+      if (!status) {
+	result = FALSE;
+      }
+      MddManagerResetIfNecessary(mddMgr);
+    }
+  }
+
+  /*
+   * Declare each latch and its corresponding next state shadow node.
+   */
+  NetworkDeclareLatches(network, hrcNode);
+
+  /*
+   * Declare the "initial" node corresponding to each latch.
+   */
+  Hrc_NodeForEachLatch(hrcNode, stGen, latchName, latch) {
+    int index;
+
+    table = Hrc_LatchReadResetTable(latch);
+
+    /*
+     * There is only one output variable (the 0th output) for any table
+     * defining the initial function of a latch, but we use an iterator to get
+     * the variable for convenience.
+     */
+    Tbl_TableForEachOutputVar(table, index, var) {
+      boolean      status;
+      char        *fullVarName = util_strcat3(path, separator, Var_VariableReadName(var));
+      char        *initName    = util_strcat3(fullVarName, "$INIT", "");
+      Ntk_Node_t  *node        = Ntk_NetworkFindNodeByName(network, initName);
+
+      /*
+       * Since the output of this table corresponds to a latch PS, can get name
+       * of the initial node by attaching $INIT.
+       */
+      FREE(fullVarName);
+      FREE(initName);
+
+      status = NodeDeclareWithTable(node, table, index, path, buildMvfs, *mddMgr);
+      if (!status) {
+	result = FALSE;
+      }
+      MddManagerResetIfNecessary(mddMgr);
+    }
+  }
+  FREE(path);
+
+  /* Recurse. */
+  Hrc_NodeForEachChild(hrcNode, stGen, childName, childHrcNode) {
+    boolean status = NetworkDeclareNodesRecursively(network, childHrcNode,
+						    buildMvfs, mddMgr);
+    if (!status) {
+      result = FALSE;
+    }
+  }
+
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a new array consisting of array1 and array2.]
+
+  Description [Returns a new array which consists of the elements of array 1
+  followed by the elements of array2.]
+
+  Comment     [It is suspected that the array_join from the array package is
+  buggy when one of the arrays has 0 length.  Hence, we defined our own.]
+
+  SideEffects []
+
+******************************************************************************/
+static array_t *
+LocalArrayJoin(
+  array_t *array1,
+  array_t *array2)
+{
+  if (array_n(array1) == 0) {
+    return (array_dup(array2));
+  }
+  else if (array_n(array2) == 0) {
+    return (array_dup(array1));
+  }
+  else {
+    return (array_join(array1, array2));
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates an array of table input names.]
+
+  Description [Creates an array of table input names.  For the ith input of
+  table, the string "namePrefix.variableName_i" is placed in the ith position
+  of the returned array, where variableName_i is the name of the variable
+  corresponding to the ith input.  (If namePrefix is "", then just
+  "variableName_i" is used.)  It is the responsiblity of the caller to free
+  the strings in the returned array.]
+
+  SideEffects []
+
+  SeeAlso     [NameArrayFree]
+
+******************************************************************************/
+static array_t *
+TableCreateFormalInputNameArray(
+  Tbl_Table_t *table,
+  char        *namePrefix)
+{
+  int             index;
+  array_t        *nameArray;
+  Var_Variable_t *var;
+  char           *separator = (char *) ((strcmp(namePrefix, "")) ? "." : "");
+
+  /*
+   * Allocate an array of length equal to the number of inputs of the table.
+   * Then, for each input, add the full path name of the input to the array.
+   */
+  nameArray = array_alloc(char *, Tbl_TableReadNumInputs(table));
+  Tbl_TableForEachInputVar(table, index, var) {
+    char *inputFullName = util_strcat3(namePrefix, separator, Var_VariableReadName(var));
+    array_insert(char *, nameArray, index, inputFullName);
+  }
+
+  return (nameArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the strings in an array, and frees the array itself.]
+
+  SideEffects []
+
+  SeeAlso     [TableCreateFormalInputNameArray]
+
+******************************************************************************/
+static void
+NameArrayFree(
+  array_t *nameArray)
+{
+  int i;
+
+  for (i = 0; i < array_n(nameArray); i++) {
+    char *name = array_fetch(char *, nameArray, i);
+    FREE(name);
+  }
+  array_free(nameArray);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Abstract each node named in abstractedNames.]
+
+  Description [Abstract each node named in abstractedNames. A node x is
+  abstracted by creating a single new primary input node, with the name x$ABS
+  and with the same variable as x, which will fanout to every node the
+  original node fanned out to. The old node will continue to exists as before
+  but will have no fanouts after abstraction; it can still be referred to in
+  CTL formulas, etc.]
+
+  SideEffects []
+
+******************************************************************************/
+static boolean
+NetworkAbstractNodes(
+  Ntk_Network_t *network,
+  lsList abstractedNames)
+{
+  char  *name;
+  lsGen gen;
+
+  /*
+   * For each abstracted name, cut the corresponding net, and introduce a new
+   * node.
+   */
+  lsForEachItem(abstractedNames, gen, name) {
+    Var_Variable_t *var;
+    Ntk_Node_t     *abstractNode;
+    array_t        *abstractNodeFanouts;
+    int             i;
+    Ntk_Node_t     *fanout;
+    char           *abstractNodeName;
+    Ntk_Node_t     *node = Ntk_NetworkFindNodeByName(network, name);
+
+    /* Make sure the name corresponds to a node in the network. */
+    if (node == NIL(Ntk_Node_t)) {
+      error_append("Could not find node corresponding to name: ");
+      error_append(name);
+      error_append("\n");
+      return FALSE;
+    }
+
+    /* Create the new node in the network as a primary input. */
+    abstractNodeName = util_strcat3(name, "$ABS", "");
+    var = Ntk_NodeReadVariable(node);
+    abstractNode = Ntk_NodeCreateInNetwork(network, abstractNodeName, var);
+    FREE(abstractNodeName);
+    Ntk_NodeDeclareAsPrimaryInput(abstractNode);
+
+    /*
+     * For each fanout y of the node x being abstracted, replace x in y's
+     * fanin list by the new node, and add y to the fanout list of the new
+     * node.
+     */
+    abstractNodeFanouts = Ntk_NodeReadFanouts(abstractNode);
+    Ntk_NodeForEachFanout(node, i, fanout) {
+      int      index        = Ntk_NodeReadFaninIndex(fanout, node);
+      array_t *fanoutFanins = Ntk_NodeReadFanins(fanout);
+
+      array_insert(Ntk_Node_t *, fanoutFanins, index, abstractNode);
+      array_insert_last(Ntk_Node_t *, abstractNodeFanouts, fanout);
+    }
+
+    /*
+     * Replace the fanout array of the node being abstracted with an empty
+     * array.
+     */
+    array_free(node->fanouts);
+    node->fanouts = array_alloc(Ntk_Node_t *, 0);
+  }
+
+  return TRUE;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Declare a node with a table, and run some tests.]
+
+  Description [Declare a node with a table, and run some tests.  Creates the
+  MVF for the output of table denoted by outIndex, in terms of the table
+  inputs (new MDD variables are created).  This MVF is created within mddMgr,
+  and freed at the end of the function.  The MVF is checked to see if it
+  represents nondeterministic or incompletely specified behavior.  If it does,
+  a message is written to vis_stderr, and FALSE is returned.  Also, if a table
+  has no inputs and more than 1 output and its output space is not complete,
+  then it's declared a "relation", and FALSE is returned.<p>
+
+  If the table passes these tests, then a reduced table is built for this
+  table output, consisting of just that output and the input columns in the
+  support of that output.  The node is then declared as a "pseudo-input" if
+  the table represents a nondeterministic constant, or a "combinational" node
+  otherwise.<p>
+
+  Building the MVF, performing the tests, and building the reduced table, is
+  bypassed if the input buildMvfs is FALSE.  Note that this should be done with
+  extreme caution, because bad tables could inadvertantly be allowed through
+  and invalidate verification results obtained downstream.]
+
+  SideEffects []
+
+******************************************************************************/
+static boolean
+NodeDeclareWithTable(
+  Ntk_Node_t  *node,
+  Tbl_Table_t *table,
+  int          outIndex,
+  char        *path,
+  boolean      buildMvfs,
+  mdd_manager *mddMgr)
+{
+  Tbl_Table_t *newTable;
+  int          newOutIndex;
+  boolean      result   = TRUE;
+  char        *nodeName = Ntk_NodeReadName(node);
+
+  /*
+   * If table has no inputs and more than one output, and its output space is
+   * not complete (i.e. not all output minterms are present, so the outputs
+   * are correlated), then declare the table a relation.
+   */
+  if ((Tbl_TableReadNumInputs(table) == 0)
+      && (Tbl_TableReadNumOutputs(table) > 1)) {
+    if (!Tbl_TableTestIsOutputSpaceComplete(table, mddMgr)) {
+      (void) fprintf(vis_stderr, "Table %s is a relation\n", nodeName);
+      result = FALSE;
+    }
+  }
+
+  if (!buildMvfs) {
+    newTable = Tbl_TableSoftDup(table);
+    newOutIndex = outIndex;
+  }
+  else {
+    Mvf_Function_t *outMvf;
+    int             offset;
+    int             numInputs     = Tbl_TableReadNumInputs(table);
+    array_t	   *varMap	  = array_alloc(int, numInputs);
+
+    outMvf = LocalMvfFunctionForTable(table, outIndex, mddMgr,
+				      varMap, &offset);
+    /*
+     * If the function is not a non-deterministic constant, or it has some
+     * inputs, then check that it is deterministic. Always check that it is
+     * completely specified.
+     */
+    if ((numInputs > 0)
+	|| !Mvf_FunctionTestIsNonDeterministicConstant(outMvf)) {
+      if (!Mvf_FunctionTestIsDeterministic(outMvf)) {
+	(void) fprintf(vis_stderr, "Table %s is not deterministic\n", nodeName);
+	result = FALSE;
+      }
+    }
+    if (!Mvf_FunctionTestIsCompletelySpecified(outMvf)) {
+      (void) fprintf(vis_stderr, "Table %s is not completely specified\n", nodeName);
+      result = FALSE;
+    }
+
+    /*
+     * Build the reduced table for the output corresponding to outIndex.  The
+     * reduced table will have only one output column (column 0), and will have
+     * only those input columns corresponding to the variables appearing in the
+     * support of outMvf.
+     */
+    newTable = Tbl_TableCreateTrueSupportTableForOutput(table, outMvf, mddMgr,
+							offset, outIndex,
+							varMap);
+    newOutIndex = 0;
+    array_free(varMap);
+    Mvf_FunctionFree(outMvf);
+  }
+
+
+  /*
+   * Declare the node with the reduced table.
+   */
+  if (Tbl_TableTestIsNonDeterministicConstant(newTable, newOutIndex)) {
+    Ntk_NodeDeclareAsPseudoInput(node, newTable, newOutIndex);
+  }
+  else {
+    array_t *formalInputNameArray = TableCreateFormalInputNameArray(newTable, path);
+
+    /* Ntk_NodeDeclareAsCombinational will test for constants. */
+    Ntk_NodeDeclareAsCombinational(node, newTable, formalInputNameArray, newOutIndex);
+    NameArrayFree(formalInputNameArray);
+  }
+
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Declares the primary inputs and outputs of the network.]
+
+  Description [Declares the primary inputs and outputs of the network. Does
+  this by iterating over the variables of the hrcNode.  Any variable it finds
+  that doesn't have a corresponding actual name in the network's corresponding
+  formal-to-actual table is considered a primary IO.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+NetworkDeclareIONodes(
+  Ntk_Network_t *network,
+  Hrc_Node_t    *hrcNode)
+{
+  st_generator   *stGen;
+  char           *varName;
+  Var_Variable_t *var;
+  char           *path = Hrc_NodeFindHierarchicalName(hrcNode, TRUE);
+  char           *separator = (char *) ((strcmp(path, "")) ? "." : "");
+
+  Hrc_NodeForEachVariable(hrcNode, stGen, varName, var) {
+    if (Var_VariableTestIsPO(var) || Var_VariableTestIsPI(var)) {
+      char *fullVarName = util_strcat3(path, separator, Var_VariableReadName(var));
+      char *tmpName     = Ntk_NetworkReadActualNameFromFormalName(network, fullVarName);
+
+      /*
+       * If tmpName == NIL, this must be a PI/PO of the top most node in the hierarchy of
+       * nodes. Hence, this is a true input/output of the hierarchy.
+       */
+      if (tmpName == NIL(char)) {
+	Ntk_Node_t *node = Ntk_NetworkFindNodeByName(network, fullVarName);
+	if (Var_VariableTestIsPO(var)) {
+	  Ntk_NodeDeclareAsPrimaryOutput(node);
+	}
+	else {
+	  Ntk_NodeDeclareAsPrimaryInput(node);
+	}
+      }
+      FREE(fullVarName);
+    }
+  }
+  FREE(path);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Declares the latches of the network.]
+
+  Description [Declares the latches of the network. Does this by iterating
+  over the latches of the hrcNode.  For each latch, also creates and declares
+  a corresponding next state shadow node.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+NetworkDeclareLatches(
+  Ntk_Network_t *network,
+  Hrc_Node_t    *hrcNode)
+{
+  st_generator   *stGen;
+  char           *name;
+  Hrc_Latch_t    *latch;
+  char           *path = Hrc_NodeFindHierarchicalName(hrcNode, TRUE);
+  char           *separator = (char *) ((strcmp(path, "")) ? "." : "");
+
+  Hrc_NodeForEachLatch(hrcNode, stGen, name, latch) {
+    char       *nextStateName;
+    Ntk_Node_t *nextStateNode;
+    char       *latchName = util_strcat3(path, separator,
+			     Var_VariableReadName(Hrc_LatchReadOutput(latch)));
+    char       *initName  = util_strcat3(latchName, "$INIT", "");
+    char       *dataName  = util_strcat3(path, separator,
+			     Var_VariableReadName(Hrc_LatchReadInput(latch)));
+    Ntk_Node_t *latchNode = Ntk_NetworkFindNodeByName(network, latchName);
+
+    FREE(latchName);
+    Ntk_NodeDeclareAsLatch(latchNode, dataName, initName);
+    FREE(initName);
+    FREE(dataName);
+
+    /*
+     * Create the corresponding shadow next state node for the latch.  This holds
+     * the next state variable.
+     */
+    nextStateName = util_strcat3(Ntk_NodeReadName(latchNode), "$NS", "");
+    nextStateNode = Ntk_NodeCreateInNetwork(network, nextStateName,
+					    Hrc_LatchReadOutput(latch));
+    FREE(nextStateName);
+    Ntk_NodeDeclareAsShadow(nextStateNode, latchNode);
+  }
+  FREE(path);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Potentially quits mddMgr and starts a new one.]
+
+  Description [Quits mddMgr if the number of binary variables exceeds
+  MAX_NUMBER_BDD_VARS, and starts a new manager with no variables.
+  Initializing an empty MDD manager is costly in some BDD packages, so we want
+  to avoid doing it often (say, once per table).  On the other hand, we don't
+  want the manager to have too many variables, because then reordering becomes
+  expensive.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+MddManagerResetIfNecessary(
+  mdd_manager **mddMgr)
+{
+  if (bdd_num_vars(*mddMgr) > MAX_NUMBER_BDD_VARS) {
+    mdd_quit(*mddMgr);
+    *mddMgr = mdd_init_empty();
+    bdd_dynamic_reordering(*mddMgr, BDD_REORDER_SIFT, BDD_REORDER_VERBOSITY_DEFAULT);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds the MVF of a table in terms of local variables.]
+
+  Description [Builds the MVF of a table in terms of local variables.  Also
+  computes the offset of the local variables in the MDD manager and builds
+  a map from the input columns of the table to the MDD id's.  The offset is
+  always 0 if the MDD manager is restarted.]
+
+  SideEffects [varMap and offsetPtr are returned as side effects]
+
+******************************************************************************/
+static Mvf_Function_t *
+LocalMvfFunctionForTable(
+  Tbl_Table_t *table,
+  int outIndex,
+  mdd_manager *mddMgr,
+  array_t *varMap,
+  int *offsetPtr
+  )
+{
+  Mvf_Function_t *outMvf;
+  Var_Variable_t *var;
+  int             colNum;
+  int             offset;
+  int		  i;
+  int             numInputs     = Tbl_TableReadNumInputs(table);
+  array_t        *faninMvfArray = array_alloc(Mvf_Function_t *, numInputs);
+  array_t        *mvarValues    = array_alloc(int, numInputs);
+  st_table	 *varTable	= st_init_table(st_ptrcmp,st_ptrhash);
+
+  /* Create MDD variables for the table inputs.  If there are more inputs
+   * tied to the sameVar_Variable_t, create just one MDD variable.  Record
+   * the mapping from inputs to variable indices in varMap.
+   */
+  Tbl_TableForEachInputVar(table, colNum, var) {
+    int index;
+    if (st_lookup_int(varTable,var,&index)) {
+      array_insert_last(int, varMap, index);
+    } else {
+      index = array_n(mvarValues);
+      array_insert_last(int, varMap, index);
+      st_insert(varTable, var, (char *) (long) index);
+      array_insert_last(int, mvarValues, Var_VariableReadNumValues(var));
+    }
+  }
+  st_free_table(varTable);
+
+  /* Restarting the manager is optional.  The effect is to get rid of the
+   * MDD variable information in the manager, without incurring the cost
+   * of quitting and re-initializing the manager. */
+  mdd_restart(mddMgr);
+  offset = array_n(mdd_ret_mvar_list(mddMgr));  /* number of existing mvars */
+  assert(offset == 0);
+  mdd_create_variables(mddMgr, mvarValues, NIL(array_t), NIL(array_t));
+  array_free(mvarValues);
+
+  /*
+   * Construct an MVF for each table input. The MVF for column i is the MVF
+   * for MDD variable i.
+   */
+  for (i = 0; i < numInputs; i++) {
+    int index = array_fetch(int, varMap, i);
+    Mvf_Function_t *faninMvf = Mvf_FunctionCreateFromVariable(mddMgr, (index + offset));
+    array_insert_last(Mvf_Function_t *, faninMvfArray, faninMvf);
+  }
+
+  /* Compute the MVF of the output indexed by outIndex. */
+  outMvf = Tbl_TableBuildMvfFromFanins(table, outIndex, faninMvfArray, mddMgr);
+  Mvf_FunctionArrayFree(faninMvfArray);
+
+  *offsetPtr = offset;
+  return outMvf;
+
+} /* LocalMvfFunctionForTable */
Index: vis_dev/vis-2.3/src/ntk/ntkGraph.c
===================================================================
--- vis_dev/vis-2.3/src/ntk/ntkGraph.c	(revision 14)
+++ vis_dev/vis-2.3/src/ntk/ntkGraph.c	(revision 14)
@@ -0,0 +1,974 @@
+/**CFile***********************************************************************
+
+  FileName    [ntkGraph.c]
+
+  PackageName [ntk]
+
+  Synopsis    [Routines related to the abstract graph of a network.]
+
+  Author      [Adnan Aziz, Tom Shiple]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ntkInt.h"
+
+static char rcsid[] UNUSED = "$Id: ntkGraph.c,v 1.11 2005/04/16 04:24:15 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**Enum************************************************************************
+
+  Synopsis [Used to keep track of the state of a node during depth first
+  search.required]
+
+******************************************************************************/
+typedef enum {
+  dfsWhite_c,   /* unvisited node */
+  dfsGrey_c,    /* node on "stack" */
+  dfsBlack_c    /* node completely visited */
+} DfsColor;
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void RegionFindNodesRecursively(Ntk_Node_t *node, st_table *leaves, st_table *result);
+static boolean NodeTestCannotReachCycle(Ntk_Node_t * node);
+static boolean NodeTestCoveredByLeaves(Ntk_Node_t *node, st_table *leaves, st_table *visited);
+static DfsColor NodeReadColor(Ntk_Node_t * node);
+static void NodeSetColor(Ntk_Node_t * node, DfsColor color);
+static void NodeSetTfoLatchList(Ntk_Node_t * node, lsList tfoLatchList);
+static lsList NodeReadTfoLatchList(Ntk_Node_t * node);
+static void NodeFreeTfoLatchList(Ntk_Node_t * node);
+static void ListAppendList(lsList list1, lsList list2);
+static lsList NodeComputeTfoLatchList(Ntk_Node_t * node);
+static void NodeRecursivelyComputeTransitiveFaninNodes(Ntk_Node_t *node, st_table *resultTable, boolean stopAtLatches);
+static void NodeComputeTopologicalOrderRecursively(Ntk_Node_t *node, st_table *leafNodesTable, lsList topologicalNodeList);
+static void NodeComputeTransitiveFaninNodes(Ntk_Node_t *node, st_table *resultTable, boolean stopAtLatches);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Returns array of nodes in transitive fanout of node.]
+
+  Description [Returns array of nodes in transitive fanout of node.  If depth is
+  non-zero, then only includes nodes within depth of node.  If depth is zero,
+  then includes all nodes up to and including combinational outputs.]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+array_t *
+Ntk_NodeComputeTransitiveFanoutNodes(
+  array_t * nodeArray,
+  int  depth)
+{
+  fail("not yet implemented");
+  return(NIL(array_t));
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns array of nodes in transitive fanin of node.]
+
+  Description [Returns array of nodes in transitive fanin of node.  If depth is
+  non-zero, then only includes nodes within depth of node.  If depth is zero,
+  then includes all nodes up to and including combinational inputs.]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+array_t *
+Ntk_NodeComputeTransitiveFanInputNodes(
+  array_t * nodeArray,
+  int  depth)
+{
+  fail("not yet implemented");
+  return(NIL(array_t));
+}
+
+/**Function********************************************************************
+
+  Synopsis [Returns array of nodes in transitive fanin of nodeArray.]
+
+  Description [Returns array of nodes in transitive fanin of nodes in
+  nodeArray.  If stopAtLatches is TRUE, the search terminates at
+  combinational inputs which are latches; otherwise it continues, and
+  the search terminates only at primary inputs and pseudo inputs. It
+  is an error if this function is called with an empty array.]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+array_t *
+Ntk_NodeComputeTransitiveFaninNodes(
+  Ntk_Network_t *network,
+  array_t * nodeArray,
+  boolean stopAtLatches,
+  boolean combInputsOnly)
+{
+  int i;
+  Ntk_Node_t *node;
+  st_generator *stGen;
+  st_table *resultTable = st_init_table( st_ptrcmp, st_ptrhash );
+  array_t *resultArray = array_alloc( Ntk_Node_t *, 0 );
+
+  arrayForEachItem( Ntk_Node_t *, nodeArray, i, node ) {
+    NodeComputeTransitiveFaninNodes(node, resultTable, stopAtLatches );
+  }
+  
+  st_foreach_item( resultTable, stGen, &node, NULL ){
+    if ( !combInputsOnly || Ntk_NodeTestIsCombInput(node) ) 
+      array_insert_last( Ntk_Node_t *, resultArray, node );
+  }
+  st_free_table( resultTable );
+  
+  return resultArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns array of combinational inputs in transitive fanin
+  of nodeArray.]
+
+  Description [Returns array of nodes in transitive fanin of nodes in
+  nodeArray.  If stopAtLatches is TRUE, the search terminates at
+  combinational inputs which are latches; otherwise it continues, and
+  the search terminates only at primary inputs and pseudo inputs. It
+  is an error if this function is called with an empty array.]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+array_t *
+Ntk_NodeComputeCombinationalSupport(
+  Ntk_Network_t *network,
+  array_t * nodeArray,
+  boolean stopAtLatches )
+{
+  lsGen gen;
+  int i;
+  Ntk_Node_t *node;
+  st_generator *stGen;
+  st_table *resultTable = st_init_table( st_ptrcmp, st_ptrhash );
+  array_t *resultArray = array_alloc( Ntk_Node_t *, 0 );
+
+  Ntk_NetworkForEachNode( network, gen, node ) {
+	NodeSetColor( node, dfsWhite_c );
+  }
+
+  arrayForEachItem( Ntk_Node_t *, nodeArray, i, node ) {
+	NodeRecursivelyComputeTransitiveFaninNodes( node, resultTable, stopAtLatches );
+  }
+
+  st_foreach_item( resultTable, stGen, &node, NULL ){
+	array_insert_last( Ntk_Node_t *, resultArray, node );
+  }
+  st_free_table( resultTable );
+
+  return resultArray;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Return table of all nodes lying in fanin of roots, stopping
+  whenever a leaf node is reached. The search also stops on nodes that pass
+  the test Ntk_NodeTestIsConstant.  Note that the leaves are also present in
+  the returned table.]
+
+  SideEffects []
+
+******************************************************************************/
+st_table *
+Ntk_RegionFindNodes(
+  array_t *roots, 
+  st_table *leaves)
+{
+  int i;
+  st_table *result = st_init_table(st_ptrcmp, st_ptrhash);
+  for (i = 0; i < array_n(roots); i++) {
+    Ntk_Node_t *root = array_fetch(Ntk_Node_t *, roots, i);
+    RegionFindNodesRecursively(root, leaves, result);
+  }
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the set of latches that each latch transitively
+  fanouts to.]
+
+  Description [For each latch, builds a list containing those latches which
+  can be transitively reached from the fanout of the latch.  If a latch
+  doesn't have any latches in its TFO, then an empty list will be built. The
+  dependencies are returned as a hash table mapping each latch (Ntk_Node_t *)
+  to a list (lsList). It is the user's responsibility to free the returned
+  hash table and the lists stored as values in the table.  NOTE: this function
+  name is a misnomer because it does not compute the latches on which a given
+  latch depends, but instead computes the latches to which a given latch
+  fanouts.]
+
+  SideEffects []
+
+******************************************************************************/
+st_table *
+Ntk_NetworkComputeLatchDependencies(
+  Ntk_Network_t * network)
+{
+  lsGen       gen;
+  Ntk_Node_t *node;
+  Ntk_Node_t *latch;
+  st_table   *latchDependencies = st_init_table(st_ptrcmp, st_ptrhash);
+
+  /*
+   * Initialize the TFO latch list of each node to NULL.
+   */
+  Ntk_NetworkForEachNode(network, gen, node) {
+    NodeSetTfoLatchList(node, (lsList) NULL);
+  }
+
+  /*
+   * For each latch, compute the set of latches in its TFO (including possibly
+   * itself).  Accumulate this set of latches into a list, and when the list
+   * is complete, store the latch and list as the key and value in the hash
+   * table.
+   */
+  Ntk_NetworkForEachLatch(network, gen, latch) {
+    int         i;
+    Ntk_Node_t *fanout;
+    lsList      tfoLatchList = lsCreate();  /* allocate a fresh list */
+
+    /*
+     * Get the latches in the TFO of each fanout of latch, and accumulate into
+     * a list. Note that we can't call NodeComputeTfoLatchList on latch
+     * itself, because latches serve as the terminal case of the recursion.
+     */
+    Ntk_NodeForEachFanout(latch, i, fanout) {
+      lsList fanoutTfoLatchList = NodeComputeTfoLatchList(fanout);
+
+      ListAppendList(tfoLatchList, fanoutTfoLatchList);
+    }
+
+    st_insert(latchDependencies, (char *) latch, (char *) tfoLatchList);
+    
+  }
+
+  /*
+   * Free the tfoLatchList stored at the nodes.  Only nodes in the transitive
+   * fanout of latches will have a non-NULL list, but we just call free
+   * tfoLatchList function on each node.  Note that the lists being returned
+   * in the hash table are distinct from those stored at nodes.
+   */
+  Ntk_NetworkForEachNode(network, gen, node) {
+    NodeFreeTfoLatchList(node);
+  }
+
+  return (latchDependencies);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 0 if a combinational cycle exists, else returns 1.]
+
+  Description [Returns 0 if a cycle exists in the network, else returns 1.
+  Latches are considered to break cycles.  If a cycle is found, then a message
+  is written to error_string (see the error package) giving two nodes in the
+  cycle.  Use a code fragment like the following to retrieve the error message:
+  <pre>
+    error_init();
+    status = Ntk_NetworkTestIsAcyclic(network);
+    if (status == 0) {
+      (void) fprintf(fp, "%s", error_string());
+    }
+  </pre>]
+  
+  SideEffects []
+
+  Comment     [This function implements the DFS routine outlined in Cormen,
+  Leiserson, Rivest, "Introduction to Algorithms", p. 478. It has been
+  specialized to just detect cycles.]
+
+******************************************************************************/
+boolean
+Ntk_NetworkTestIsAcyclic(
+  Ntk_Network_t * network)
+{
+  lsGen       gen;
+  Ntk_Node_t *node;
+  boolean     status = 1; /* In case network has no vertices. */
+
+  /* The meaning of the colors is:
+   *   white: node has not been visited yet
+   *   grey:  node is on the "stack"
+   *   black: node, and all its descendents, have been visited
+   */
+
+  /*
+   * Initialize the color of each node to white.
+   */
+  Ntk_NetworkForEachNode(network, gen, node) {
+    NodeSetColor(node, dfsWhite_c);
+  }
+  
+  /*
+   * Recursively visit each unvisited node.  The order in which we visit the
+   * nodes is immaterial.  
+   */  
+  Ntk_NetworkForEachNode(network, gen, node) {
+    if (NodeReadColor(node) == dfsWhite_c) {
+      status = NodeTestCannotReachCycle(node);
+      if (status == 0) {
+	/* A cycle has been found. */
+	break;
+      }
+    }
+  }
+
+  /*
+   * Colors will be left in the undef field of the nodes, but we don't care.
+   */
+  return (status);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns TRUE if leaves cover the support of roots, otherwise
+  returns FALSE.]
+
+  Description [The function takes as input a network, a hash table of nodes
+  called leaves, and an array of nodes called roots. It returns TRUE if the
+  nodes in leaves cover the support of the nodes in roots, otherwise it
+  returns FALSE.  In other words, if there exists a combinational input in the
+  transitive fanin of a root, which can be reached from the root without
+  passing through a leaf, then FALSE is returned.  If FALSE is returned, then
+  the message "Node b found in the support of node c" is written to
+  error_string, where b is a combinational input not in leaves and c is a
+  root. It is allowed that some roots are themselves leaves, and that some
+  leaves are in the transitive fanin of other leaves.  Combinational cycles
+  within the region defined by roots and leaves have no effect on the result.
+  If TRUE is returned, then the runtime of this procedure is proportional to
+  the number of nodes in the region defined by roots and leaves; if FALSE is
+  returned, then the worst case is proportional to the number of nodes in the
+  network.]
+
+  Comment [The undef field is modified of some of the nodes in the network to
+  which node belongs.]
+  
+  SideEffects []
+
+******************************************************************************/
+boolean
+Ntk_NetworkTestLeavesCoverSupportOfRoots(
+  Ntk_Network_t *network,
+  array_t       *roots,
+  st_table      *leaves)
+{
+  int         i;
+  Ntk_Node_t *root;
+  st_table   *visited = st_init_table(st_ptrcmp, st_ptrhash);
+  
+  /* Perform DFS from the roots.  Return FALSE upon the first failure. */
+  arrayForEachItem(Ntk_Node_t *, roots, i, root) {
+    boolean status = NodeTestCoveredByLeaves(root, leaves, visited);
+    
+    if(!status) {
+      error_append(Ntk_NodeReadName(root));
+      error_append(".\n");
+      st_free_table(visited);
+      return FALSE; 
+    }
+  }
+  st_free_table(visited);
+  return TRUE;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Computes the topological order of nodes in the network
+  for a given array of root nodes and the leaf nodes.]
+
+  Description [Depth first traversal is used from each node in the
+  root node array. The search is terminated when a node in the leaf
+  table is reached. It is necessary that all the root nodes eventually
+  depend on the leaf nodes. The returned list contains the nodes in
+  the topological order.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+lsList
+Ntk_NetworkComputeTopologicalOrder(Ntk_Network_t *network, array_t
+                                  *rootNodesArray, st_table
+                                  *leafNodesTable) 
+{
+  int i;
+  lsList topologicalNodeList = lsCreate();
+  Ntk_Node_t *node;
+  lsGen gen;
+  
+  Ntk_NetworkForEachNode(network, gen, node) {
+    NodeSetColor(node, dfsWhite_c);
+  }
+
+  for (i=0; i<array_n(rootNodesArray); i++){
+    node = array_fetch(Ntk_Node_t *, rootNodesArray, i);
+    NodeComputeTopologicalOrderRecursively(node, leafNodesTable,
+                                           topologicalNodeList);
+  }
+  return topologicalNodeList;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Recursively add all fanins of node to result, stopping at leaves
+  and constants.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+RegionFindNodesRecursively(
+  Ntk_Node_t *node, 
+  st_table *leaves,
+  st_table *result)
+{
+  int i;
+  Ntk_Node_t *fanin;
+
+  if (st_is_member(result, (char *) node)) {
+    /* already visited this node */
+    return;
+  }
+  else {
+    /*
+     * Add to table before recursing, to avoid infinite loops in presence of
+     * combinational cycles.
+     */
+    st_insert(result, (char *) node, NIL(char));
+  }
+  
+  
+  if (!st_is_member(leaves, (char *) node) && !Ntk_NodeTestIsConstant(node)) {
+    /* not a leaf; recurse */
+    Ntk_NodeForEachFanin(node, i, fanin) {
+      RegionFindNodesRecursively(fanin, leaves, result);
+    }
+  }
+
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if node cannot reach a cycle, else returns 0.]
+
+  Description [Visits a node, and recursively all of its children, to
+  determine if the node can reach a combinational cycle. If it cannot, the
+  function return 1, else it returns 0.  If a cycle is found, then a message
+  is written to error_string.]
+
+  SideEffects []
+
+******************************************************************************/
+static boolean
+NodeTestCannotReachCycle(
+  Ntk_Node_t * node)
+{
+  Ntk_Node_t *fanout;
+  int i;
+
+  /*
+   * Set the color of node to grey to indicate that it is on the "stack".
+   */
+  NodeSetColor(node, dfsGrey_c);
+
+  Ntk_NodeForEachFanout(node, i, fanout) {
+    /*
+     * Traverse fanout if it is *not* a latch; latches break combinational cycles.
+     */
+    if (Ntk_NodeTestIsLatch(fanout) == 0) {
+      DfsColor fanoutColor = NodeReadColor(fanout);
+
+      /* 
+       * If fanout is white, it has not been visited yet, so visit it, and 
+       * break the search if it can reach a cycle.  Else if fanout is grey, it 
+       * means that fanout is also on the stack, so a cycle has been found; 
+       * thus break.  Else, the fanout is black, and there is nothing to do.
+       */
+      if (fanoutColor == dfsWhite_c) {
+	if (NodeTestCannotReachCycle(fanout) == 0) {
+	  return (0);
+	}
+      }
+      else if (fanoutColor == dfsGrey_c) {
+        error_append("(");
+        error_append(Ntk_NodeReadName(node));
+        error_append(", ");
+        error_append(Ntk_NodeReadName(fanout));
+        error_append(")");
+	return (0);
+      } 
+    }
+  }
+
+  /*
+   * Set the color of node to black to indicate that it has been visited.
+   */
+  NodeSetColor(node, dfsBlack_c);
+  
+  /*
+   * No cycles found from node.
+   */
+  return (1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns FALSE if the support of node contains a combinational
+  input that is not a leaf, otherwise returns TRUE.]
+
+  Description [The function does a DFS starting from node, never going beyond
+  a leaf or a node already visited. If it reaches a combinational input that
+  is not a leaf it returns FALSE.  If this doesn't happen for all the fanins
+  of the node, then TRUE is returned.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkTestLeavesCoverSupportOfRoots]
+
+******************************************************************************/
+static boolean
+NodeTestCoveredByLeaves(
+  Ntk_Node_t *node,
+  st_table   *leaves,
+  st_table   *visited)
+{
+  int         i;
+  Ntk_Node_t *fanin;
+
+  /*
+   * If node has already been visited, just return.  Else, mark it as
+   * visited. Note that it is important to mark it as visited BEFORE recursing,
+   * in case combinational cycles are present.
+   */
+  if (st_is_member(visited, (char *) node)) {
+    return TRUE;
+  }
+  else {
+    st_insert(visited, (char *) node, NIL(char));
+  }
+
+  if (st_is_member(leaves, (char *) node)) {
+    /*
+     * Positive termination of recursion: if node is a leaf, then everything
+     * is fine.
+     */ 
+    return TRUE;
+  }
+  else {
+    /* Node is not a leaf. */
+    if (Ntk_NodeTestIsCombInput(node)) {
+      /*
+       * Negative termination of recursion: a combinational input was reached
+       * without seeing a leaf.
+       */ 
+      error_append("Node ");
+      error_append(Ntk_NodeReadName(node));
+      error_append(" found in the support of node ");
+      return FALSE;
+    }
+    else {
+      /*
+       * Node is not a leaf nor a combinational input.  Recurse over fanins.
+       * Return FALSE if any fanins fail the test.
+       */
+      Ntk_NodeForEachFanin(node, i, fanin) {
+        boolean status = NodeTestCoveredByLeaves(fanin, leaves, visited);
+        if (!status) {
+          return FALSE;
+        }
+      }
+      /*
+       * If the loop terminates without the function returning, then each
+       * fanin has already been visited and no dfsWhite_c-labelled comb input
+       * can be reached from the fanins. Therefore, return TRUE.
+       */
+      return TRUE;
+    }
+  }
+  
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the color of a node.]
+
+  SideEffects []
+
+  SeeAlso     [NodeSetColor]
+
+******************************************************************************/
+static DfsColor
+NodeReadColor(
+  Ntk_Node_t * node)
+{
+  return ((DfsColor) (long) Ntk_NodeReadUndef(node));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the color of a node.]
+
+  SideEffects []
+
+  SeeAlso     [NodeReadColor]
+
+******************************************************************************/
+static void
+NodeSetColor(
+  Ntk_Node_t * node,
+  DfsColor  color)
+{
+  Ntk_NodeSetUndef(node, (void *) (long) color);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the tfoLatchList of a node.]
+
+  SideEffects []
+
+  SeeAlso     [NodeReadTfoLatchList NodeFreeTfoLatchList]
+
+******************************************************************************/
+static void
+NodeSetTfoLatchList(
+  Ntk_Node_t * node,
+  lsList  tfoLatchList)
+{
+  Ntk_NodeSetUndef(node, (void *) tfoLatchList);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the TfoLatchList of a node.]
+
+  SideEffects []
+
+  SeeAlso     [NodeSetTfoLatchList NodeFreeTfoLatchList]
+
+******************************************************************************/
+static lsList
+NodeReadTfoLatchList(
+  Ntk_Node_t * node)
+{
+  return ((lsList) Ntk_NodeReadUndef(node));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the tfoLatchList of a node.]
+
+  Description [If the node has a non-NULL tfoLatchList, then frees the list
+  and sets the tfoLatchList of node to NULL; else, does nothing.]
+  
+  SideEffects []
+
+  SeeAlso     [NodeReadTfoLatchList NodeSetTfoLatchList ]
+
+******************************************************************************/
+static void
+NodeFreeTfoLatchList(
+  Ntk_Node_t * node)
+{
+  lsList tfoLatchList = NodeReadTfoLatchList(node);
+
+  if (tfoLatchList != (lsList) NULL) {
+    (void) lsDestroy(tfoLatchList, (void (*) (lsGeneric)) NULL);
+    Ntk_NodeSetUndef(node, (void *) NULL);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Appends list2 to list1.]
+
+  Description [Adds the elements of list2 to the end of list1.  The elements
+  of list2 are not copied. If an element of list2 already exists in list1,
+  then it is not added to the end of list1. List2 is not changed by this
+  operation.]
+
+  SideEffects [List1 is modified.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ListAppendList(
+  lsList  list1,
+  lsList  list2)
+{
+  lsGen      gen;
+  lsGeneric  data;
+  st_table  *table1 = st_init_table(st_ptrcmp, st_ptrhash);
+  
+  /*
+   * Load a hash table mapping each item in list1 to NULL.
+   */
+  gen = lsStart(list1);
+  while (lsNext(gen, &data, LS_NH) == LS_OK) {
+    st_insert(table1, (char *) data, (char *) NULL);
+  }
+  (void) lsFinish(gen);
+
+  /*
+   * For each item in list2, if it's not already present in list1, then add it
+   * to the end of list1.
+   */
+  lsForEachItem(list2, gen, data) {
+    if (st_is_member(table1, (char *) data) == 0) {
+      lsNewEnd(list1, data, LS_NH);
+    }
+  }
+  st_free_table(table1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the set of latches in the TFO of a node.]
+
+  Description [Computes the set of latches in the TFO of a node.  If there are
+  no latches in the TFO, then an empty list is returned.  In the special case
+  where the node is itself a latch, then a list containing just the node is
+  returned; this is one of the terminal cases of the recursion. The other
+  terminal case is a node with no immediate fanouts.]
+
+  SideEffects []
+
+******************************************************************************/
+static lsList
+NodeComputeTfoLatchList(
+  Ntk_Node_t * node)
+{
+  lsList tfoLatchList = NodeReadTfoLatchList(node);
+
+  /*
+   * If node already has a non-NULL tfoLatchList, then just return it (this
+   * can happen if the node was already visited via one of its other
+   * fanins). Otherwise, create an empty list and fill it appropriately.
+   */
+  if (tfoLatchList != (lsList) NULL) {
+    return (tfoLatchList);
+  }
+  else {
+    tfoLatchList = lsCreate();
+
+    if (Ntk_NodeTestIsLatch(node)) {
+      /*
+       * Special case; terminal condition.
+       */
+      lsNewEnd(tfoLatchList, (lsGeneric) node, LS_NH);
+    }
+    else {
+      int         i;
+      Ntk_Node_t *fanout;
+      
+      /*
+       * Get the latches in the TFO of each fanout of node, and accumulate into
+       * a list.
+       */
+      Ntk_NodeForEachFanout(node, i, fanout) {
+        lsList fanoutTfoLatchList = NodeComputeTfoLatchList(fanout);
+
+        ListAppendList(tfoLatchList, fanoutTfoLatchList);
+      }
+    }
+
+    /*
+     * Store the list with the node, then return the list.
+     */
+    NodeSetTfoLatchList(node, tfoLatchList);
+    return (tfoLatchList);    
+  }
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the set of combinational inputs in the TFI of the node.]
+
+  Description [Computes the set of combinational inputs in the TFI of the node.
+  If stopAtLatches is TRUE, the search terminates at combinational inputs which
+  are latches; otherwise it continues, and the search terminates only at primary 
+  inputs and pseudo inputs.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+NodeRecursivelyComputeTransitiveFaninNodes( 
+  Ntk_Node_t *node, 
+  st_table *resultTable,
+  boolean stopAtLatches) 
+{
+  int i;
+  Ntk_Node_t * fanin;
+
+  /* test if we have already started processing this node */
+  if ( NodeReadColor( node ) == dfsBlack_c ) {
+	return;
+  }
+  NodeSetColor( node, dfsBlack_c );
+
+  if ( Ntk_NodeTestIsCombInput( node ) ) {
+	st_insert( resultTable, (char *) node, (char *) 0 );
+  }
+
+  if ( Ntk_NodeTestIsInput(node) || ((stopAtLatches == TRUE)&&(Ntk_NodeTestIsLatch(node))) ) {
+	return;
+  }
+
+  Ntk_NodeForEachFanin( node, i, fanin ) {
+	NodeRecursivelyComputeTransitiveFaninNodes( fanin, resultTable, stopAtLatches );
+  }
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Recursively performs the depth-first traversal of the
+  network starting at the given node.]
+
+  Description [Recursively performs the depth-first traversal of the
+  network starting at the given node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+NodeComputeTopologicalOrderRecursively(Ntk_Node_t *node, st_table
+                                       *leafNodesTable, lsList
+                                       topologicalNodeList) 
+{
+  int i;
+  Ntk_Node_t *fanin;
+  
+  if (NodeReadColor(node) == dfsBlack_c){
+    /* Has already been put in the list. */
+    return;
+  }
+  if (NodeReadColor(node) == dfsGrey_c){
+    /* Indicates that this node is currently being processed (possibly a
+       combinational loop). */
+    return;
+  }
+  if (st_is_member(leafNodesTable, (char *)node)== 0){
+    NodeSetColor(node, dfsGrey_c);
+    Ntk_NodeForEachFanin(node, i, fanin){
+      NodeComputeTopologicalOrderRecursively(fanin, leafNodesTable,
+                                             topologicalNodeList);
+    }
+  }
+  NodeSetColor(node, dfsBlack_c);
+  lsNewEnd(topologicalNodeList, (lsGeneric)node, LS_NH);
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Computes the set of nodes in the TFI of the node.]
+
+  Description [Computes the set of nodes in the TFI of the node.  If
+  stopAtLatches is TRUE, the search terminates at combinational inputs
+  which are latches; otherwise it continues, and the search terminates
+  only at primary inputs and pseudo inputs.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+NodeComputeTransitiveFaninNodes( 
+  Ntk_Node_t *node, 
+  st_table *resultTable,
+  boolean stopAtLatches) 
+{
+  int i;
+  Ntk_Node_t * fanin;
+  
+  /* test if we have already started processing this node */
+  if (st_is_member(resultTable, node))
+    return;
+
+  st_insert(resultTable, node, (char *)(long)2);
+
+  if (Ntk_NodeTestIsInput(node) || (stopAtLatches && Ntk_NodeTestIsLatch(node)))
+    return;
+
+  Ntk_NodeForEachFanin(node, i, fanin) {
+    NodeComputeTransitiveFaninNodes(fanin, resultTable, stopAtLatches);
+  }
+}
+
Index: vis_dev/vis-2.3/src/ntk/ntkInt.h
===================================================================
--- vis_dev/vis-2.3/src/ntk/ntkInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/ntk/ntkInt.h	(revision 14)
@@ -0,0 +1,147 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [ntkInt.h]
+
+  PackageName [ntk]
+
+  Synopsis    [Internal declarations for the network package.]
+
+  Author      [Adnan Aziz, Tom Shiple]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: ntkInt.h,v 1.9 2002/03/05 23:24:35 awedh Exp $]
+
+******************************************************************************/
+
+#ifndef _NTKINT
+#define _NTKINT
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include <time.h>
+#include "ntk.h"
+#include "cmd.h"
+#include <string.h>
+
+extern int NtkDebug;
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Enum************************************************************************
+
+  Synopsis    [Types of network nodes.]
+
+  Description [Types of network nodes.  See the corresponding
+  Ntk_NodeTestIs<type> functions for a description of each type.]
+
+******************************************************************************/
+typedef enum {
+  NtkLatch_c,         
+  NtkShadow_c,         
+  NtkCombinational_c,
+  NtkPrimaryInput_c,
+  NtkPseudoInput_c,
+  NtkUnassigned_c
+} NtkNodeType;
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [A network of nodes.]
+
+  Description [A network is a directed graph of nodes.  Lists are maintained
+  to provide easy access to various groups of nodes.  Applications can
+  associate information with a network via the application info mechanism.]
+
+******************************************************************************/
+struct NtkNetworkStruct {
+  char           *name;            /* name of network */
+  lsList          nodes;           /* all nodes of network */
+  lsList          combInputs;      /* all primary inputs and latch outputs */
+  lsList          combOutputs;     /* all primary outputs and latch inputs */
+  lsList          latches;         /* all latches */
+  lsList          primaryInputs;   /* all primary inputs */
+  lsList          pseudoInputs;    /* all pseduo inputs */
+  lsList          inputs;          /* all primary and pseudo inputs */
+  lsList          primaryOutputs;  /* all primary outputs */
+  st_table       *combOutputsTable;/* membership for combOutputs list */
+  st_table       *mddIdToNode;     /* int to Ntk_Node_t * */
+  st_table       *actualNameToNode;/* char * to Ntk_Node_t * */
+  st_table       *formalNameToActualName;  /* char * to char * */
+  mdd_manager    *mddManager;      /* MDD manager of network */
+  bdd_reorder_type_t dynVarOrdMethod; /* method to perform dynamic variable ordering */
+  st_table       *applInfoTable;   /* char * to ApplInfo_t * */
+  mAig_Manager_t *mAigManager;     /* AndInv graph manager [MHA] */
+  void           *undef;           /* for programmer's use; make no assumptions */
+};
+  
+
+/**Struct**********************************************************************
+
+  Synopsis    [A network node.]
+
+  Description [A node is a vertex in the directed graph represented by a
+  network.  Edges of the graph are given by the fanin and fanout arrays of a
+  node.  A node has a type describing its role in the context of a
+  circuit.  Also, a node has a unique name, and a unique MDD id (unless it's
+  undefined).]
+
+******************************************************************************/
+struct NtkNodeStruct {
+  char           *name;        /* actual name of output of node */
+  Ntk_Network_t  *network;     /* network to which this node belongs */
+  Var_Variable_t *variable;    /* info about the multi-valued variable of this node */
+  NtkNodeType     type;        /* type of node */
+  array_t        *fanins;      /* array of Ntk_Node_t * giving fanins of this node */
+  array_t        *fanouts;     /* array of Ntk_Node_t * giving fanouts of this node */
+  Tbl_Table_t    *table;       /* table in which the function of this node is defined */
+  int             outputIndex; /* column of table which defines this node */
+  int             mddId;       /* mddId of the output variable of this node */
+  union {
+    Ntk_Node_t   *shadow;      /* if type is not shadow, corr. shadow node (may be NULL) */
+    Ntk_Node_t   *origin;      /* if type is shadow, corresponding node */
+  } shadowInfo;
+  boolean         outputFlag;  /* 1 if node is a primary output, else 0 */
+  boolean         constant;    /* 1 if node is a constant, else 0 */
+  boolean         latchDataInput; /* 1 if node is the data input to some latch, else 0 */
+  boolean         latchInitialInput; /* 1 if node is the init input to some latch, else 0 */
+  mAigEdge_t      mAigId;     /*Node Id of this node in the AndInv graph */
+  void           *undef;       /* for programmer's use; make no assumptions */
+};
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN boolean NtkNodeDeleteFromList(lsList nodeList, Ntk_Node_t *node);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _NTKINT */
+
+
+
+
Index: vis_dev/vis-2.3/src/ntk/ntkNode.c
===================================================================
--- vis_dev/vis-2.3/src/ntk/ntkNode.c	(revision 14)
+++ vis_dev/vis-2.3/src/ntk/ntkNode.c	(revision 14)
@@ -0,0 +1,1490 @@
+/**CFile***********************************************************************
+
+  FileName    [ntkNode.c]
+
+  PackageName [ntk]
+
+  Synopsis    [Routines to access the node data structure.]
+
+  Author      [Adnan Aziz, Tom Shiple]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ntkInt.h"
+#include "baig.h"
+
+static char rcsid[] UNUSED = "$Id: ntkNode.c,v 1.15 2009/04/11 01:56:10 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+#define UNASSIGNED_OUTPUT_INDEX -1
+#define LATCH_DATA    0 
+#define LATCH_INITIAL 1
+
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void NetworkAddCombOutput(Ntk_Network_t *network, Ntk_Node_t *node);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the name of a node.]
+
+  Description [Returns the (actual) name of a node.  User must not free this
+  string.  Every node must have a non-NULL name. It is an error to call this
+  function on a NULL node.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeCreateInNetwork]
+
+******************************************************************************/
+char *
+Ntk_NodeReadName(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  return (node->name);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the network of a node.]
+
+  Description [Returns the network to which node belongs.  User must not free
+  this network.  Every node must have a non-NULL network.  It is an error to
+  call this function on a NULL node.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeCreateInNetwork]
+
+******************************************************************************/
+Ntk_Network_t *
+Ntk_NodeReadNetwork(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  return (node->network);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the variable of a node.]
+
+  Description [Returns the multi-valued variable at the output of a node.
+  User must not free this variable.  Every node must have a non-NULL variable.
+  The returned variable actually belongs to the hierarchy manager from which
+  the node's network was derived.  However, in the context of the network, the
+  only information contained in the variable that should be used, is the
+  information relating to the number (and name, if symbolic) of values. It is
+  an error to call this function on a NULL node.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeCreateInNetwork Var_VariableReadNumValues
+  Var_VariableReadIndexFromSymbolicValue
+  Var_VariableReadSymbolicValueFromIndex Var_VariableTestIsSymbolic
+  Var_VariableTestIsEnumerative]
+
+******************************************************************************/
+Var_Variable_t *
+Ntk_NodeReadVariable(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  return (node->variable);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the table of a node.]
+
+  Description [Returns the table which defines the function of this node.  User
+  must not free this table.  Every combinational node and every pseudo input
+  has a table.  It is an error to call this function on a NULL node or a node
+  that isn't combinational or a pseudo input.]
+
+  SideEffects []
+
+  SeeAlso [Ntk_NodeDeclareAsCombinational Ntk_NodeDeclareAsPseudoInput
+  Ntk_NodeSetTable]
+
+******************************************************************************/
+Tbl_Table_t *
+Ntk_NodeReadTable(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  assert((node->type == NtkCombinational_c) || (node->type == NtkPseudoInput_c));
+  return (node->table);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the AndInv Id  of a node.]
+
+  Description [Returns the AndInv Id of the node in the AndInv graph.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+mAigEdge_t
+Ntk_NodeReadMAigId(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  return (node->mAigId);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the AndInv Id  of a node.]
+
+  Description [Setss the AndInv Id of the node to a given vlaue.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Ntk_NodeSetMAigId(
+  Ntk_Node_t * node,
+  mAigEdge_t mAigId)
+{
+  assert(node != NIL(Ntk_Node_t));
+  node->mAigId = mAigId;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the table of the node to supplied table.]
+
+  Description [Sets the table of the node to supplied table. THIS FUNCTION
+  SHOULD BE USED WITH UTMOST CAUTION. It is assumed that the reference count of
+  the supplied table is appropriately incremented. If a table already exists in
+  the node it is NOT deleted. It is the users responsibility to free memory
+  associated with the old table. Every combinational node and every pseudo
+  input has a table. It is an error to call this function on a NULL node or a
+  node that isn't combinational or a pseudo input. No checks are done to ensure
+  that the supplied table infact has an output column for the specified node or
+  the variables corresponding to the input columns are indeed those of the
+  fanin nodes.]
+
+  SideEffects [The old table pointed to by the node is NOT deleted.]
+
+  SeeAlso [Ntk_NodeDeclareAsCombinational Ntk_NodeDeclareAsPseudoInput
+  Ntk_NodeReadTable]
+
+******************************************************************************/
+void
+Ntk_NodeSetTable(
+  Ntk_Node_t * node,
+  Tbl_Table_t *table)
+{
+
+  assert(node != NIL(Ntk_Node_t));
+  assert((node->type == NtkCombinational_c) || (node->type == NtkPseudoInput_c));
+
+  node->table = table;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the output index of a node.]
+
+  Description [Returns the output column of the node's table that defines the
+  node's function.  It is an error to call this function on a NULL node or a
+  node of type other than combinational or pseudo input.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeDeclareAsCombinational Ntk_NodeDeclareAsPrimaryInput
+  Ntk_NodeReadTable] 
+
+******************************************************************************/
+int
+Ntk_NodeReadOutputIndex(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  assert((node->type == NtkCombinational_c) || (node->type == NtkPseudoInput_c));
+  return (node->outputIndex);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the MDD id of a node.]
+
+  Description [Returns the MDD id of a node.  Whether or not a node has an MDD
+  id depends on which nodes were assigned an id in Ord_NetworkOrderVariables.
+  Returns NTK_UNASSIGNED_MDD_ID if node does not have an assigned MDD id.  It
+  is an error to call this function on a NULL node.]
+
+  SideEffects []
+
+  SeeAlso     [Ord_NetworkOrderVariables Ntk_NodeSetMddId]
+
+******************************************************************************/
+int
+Ntk_NodeReadMddId(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  return (node->mddId);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the MDD id of a node.]
+
+  Description [Sets the MDD id of a node. Any node can have its MDD id set. No
+  check is made to see if node already has an MDD id.  Use the constant
+  NTK_UNASSIGNED_MDD_ID to indicate that the id is not set.  If mddId is not
+  NTK_UNASSIGNED_MDD_ID, then this mddId/node pair will be added to the
+  network's mddId to node table, and any previous pair involving this node
+  will be removed from the table.  Note that this function does *not* register
+  this mddId with the MDD manager; this must be done by calling
+  mdd_create_variables. It is an error to call this function on a NULL node.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeReadMddId Ord_NetworkOrderVariables
+  Ntk_NetworkFindNodeByMddId] 
+
+******************************************************************************/
+void
+Ntk_NodeSetMddId(
+  Ntk_Node_t * node,
+  int  id)
+{
+  Ntk_Network_t *network = node->network;
+  char *entry;
+  
+  assert(node != NIL(Ntk_Node_t));
+
+  /* If the node already has an assigned id, then clean it from the table. */
+  if (node->mddId != NTK_UNASSIGNED_MDD_ID) {
+    entry = (char *) (long) node->mddId;
+    (void) st_delete(network->mddIdToNode, &entry, NIL(char *));
+  }
+
+  /* Set the new id, and add it to the table (if it's not unassigned). */
+  node->mddId = id;
+  if (id != NTK_UNASSIGNED_MDD_ID) {
+    st_insert(network->mddIdToNode, (char *) (long) id, (char *) node);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the undef field of a node.]
+
+  Description [Returns the undef field of a node.  There is no restriction on how
+  this field is used.  However, you should use extreme caution to make sure
+  that you are not using this field to store more that one thing at a given
+  time (if you can't be sure, then use a hash table).  It is an error to call
+  this function on a NULL node.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeSetUndef]
+
+******************************************************************************/
+void *
+Ntk_NodeReadUndef(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  return (node->undef);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the undef field of a node.]
+
+  Description [Sets the undef field of a node.  There is no restriction on
+  how this field is used.  It is an error to call this function on a NULL
+  node.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeReadUndef]
+
+******************************************************************************/
+void
+Ntk_NodeSetUndef(
+  Ntk_Node_t * node,
+  void * value)
+{
+  assert(node != NIL(Ntk_Node_t));
+  node->undef = value;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if node is a primary input, else returns 0.]
+
+  Description [Returns 1 if node is a primary input, else returns 0.  A node
+  is a primary input only if it has been so declared using
+  Ntk_NodeDeclareAsPrimaryInput. It is an error to call this function on a
+  NULL node.]
+  
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeDeclareAsPrimaryInput Ntk_NodeTestIsInput]
+  
+******************************************************************************/
+boolean
+Ntk_NodeTestIsPrimaryInput(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  return (node->type == NtkPrimaryInput_c);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if node is a pseudo input, else returns 0.]
+
+  Description [Returns 1 if node is a pseudo input, else returns 0.  A node is
+  a pseudo input only if it has been so declared using
+  Ntk_NodeDeclareAsPseudoInput. A pseudo input has no fanins, but has a table
+  defining its function. It is an error to call this function on a NULL node.]
+  
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeDeclareAsPseudoInput Ntk_NodeTestIsInput]
+  
+******************************************************************************/
+boolean
+Ntk_NodeTestIsPseudoInput(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  return (node->type == NtkPseudoInput_c);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if node is a primary or pseudo input, else returns 0.]
+
+  Description [Returns 1 if node is a primary or pseudo input, else returns 0.
+  It is an error to call this function on a NULL node.]
+  
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeDeclareAsPrimaryInput Ntk_NodeDeclareAsPseudoInput
+  Ntk_NodeTestIsPrimaryInput Ntk_NodeTestIsPseudoInput]
+  
+******************************************************************************/
+boolean
+Ntk_NodeTestIsInput(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  return ((node->type == NtkPrimaryInput_c) || (node->type == NtkPseudoInput_c));
+  
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if node is undefined, else returns 0.]
+
+  Description [Returns 1 if node is undefined, else returns 0. A node is
+  undefined if it has been created but not declared as anything. It is an
+  error to call this function on a NULL node.]
+  
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeCreateInNetwork Ntk_NodeDeclareAsCombinational]
+
+******************************************************************************/
+boolean
+Ntk_NodeTestIsUndefined(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  return (node->type == NtkUnassigned_c);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if node is a latch, else returns 0.]
+
+  Description [Returns 1 if node is a latch, else returns 0.  A node is a
+  latch only if it has been so declared using Ntk_NodeDeclareAsLatch. It is an
+  error to call this function on a NULL node.]
+  
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeDeclareAsLatch]
+
+******************************************************************************/
+boolean
+Ntk_NodeTestIsLatch(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  return (node->type == NtkLatch_c);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if node is a next state node, else returns 0.]
+
+  Description [Returns 1 if node is a next state node, else returns 0.  A next
+  state node is a shadow node whose origin node is a latch.  It is an
+  error to call this function on a NULL node.]
+  
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeDeclareAsShadow]
+
+******************************************************************************/
+boolean
+Ntk_NodeTestIsNextStateNode(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  if (Ntk_NodeTestIsShadow(node)) {
+    Ntk_Node_t *origin = Ntk_ShadowReadOrigin(node);
+    if (Ntk_NodeTestIsLatch(origin)) {
+      return (TRUE);
+    }
+  }
+  
+  return (FALSE);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if node is a shadow node, else returns 0.]
+
+  Description [Returns 1 if node is a shadow node, else returns 0.  A shadow
+  node is used to associate extra information with a node, in particular
+  another MDD id. It is an error to call this function on a NULL node.]
+  
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeDeclareAsShadow Ntk_ShadowReadOrigin Ntk_NodeReadShadow]
+
+******************************************************************************/
+boolean
+Ntk_NodeTestIsShadow(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  return (node->type == NtkShadow_c);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if node is a combinational input, else returns 0.]
+
+  Description [Returns 1 if node is a combinational input, else returns 0.  A
+  node is a combinational input if it is a primary input, a pseudo input, or a
+  latch. It is an error to call this function on a NULL node.]
+  
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeDeclareAsPrimaryInput Ntk_NodeDeclareAsLatch
+  Ntk_NodeDeclareAsPseudoInput]
+
+******************************************************************************/
+boolean
+Ntk_NodeTestIsCombInput(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  return ((node->type == NtkLatch_c)
+          || (node->type == NtkPrimaryInput_c)
+          || (node->type == NtkPseudoInput_c));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if node is a combinational output, else returns 0.]
+
+  Description [Returns 1 if node is a combinational output, else returns 0.  A
+  node is a combinational output if it is a primary output, a data input to a
+  latch, or an initial input to a latch. This is a constant time operation.
+  It is an error to call this function on a NULL node.]
+  
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeDeclareAsPrimaryOutput Ntk_NodeDeclareAsLatch]
+  
+******************************************************************************/
+boolean
+Ntk_NodeTestIsCombOutput(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  return (Ntk_NodeTestIsPrimaryOutput(node)
+          || Ntk_NodeTestIsLatchDataInput(node)
+          || Ntk_NodeTestIsLatchInitialInput(node));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if node is combinational, else returns 0.]
+
+  Description [Returns 1 if node is combinational, else returns 0.  A node is
+  combinational only if it has been so declared using
+  Ntk_NodeDeclareAsCombinational.  Combinational nodes have tables.]
+  
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeDeclareAsCombinational]
+
+******************************************************************************/
+boolean
+Ntk_NodeTestIsCombinational(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  return (node->type == NtkCombinational_c);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if node is a primary output, else returns 0.]
+
+  Description [Returns 1 if node is a primary output, else returns 0.  Any
+  node can be a primary output, except those of type shadow.  A node is a
+  primary output only if it has been so declared using
+  Ntk_NodeDeclareAsPrimaryOutput.  It is an error to call this function on a
+  NULL node.]
+  
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeDeclareAsPrimaryOutput]
+  
+******************************************************************************/
+boolean
+Ntk_NodeTestIsPrimaryOutput(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  return (node->outputFlag);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if node is a data input to a latch, else returns 0.]
+
+  Description [Returns 1 if node is a data input to a latch, else returns 0.
+  Nodes of all types can be data inputs to latches.  A node is declared as a
+  data input to a latch by virtue of a call to Ntk_NodeDeclareAsLatch. It is
+  an error to call this function on a NULL node.]
+  
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeDeclareAsLatch]
+
+******************************************************************************/
+boolean
+Ntk_NodeTestIsLatchDataInput(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  return (node->latchDataInput);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if node is an initial input to a latch, else returns 0.]
+
+  Description [Returns 1 if node is an initial input to a latch, else returns
+  0.  Nodes of all types can be initial inputs to latches. The initial input
+  to a latch gives the initial value of the latch. A node is declared as a
+  initial input to a latch by virtue of a call to Ntk_NodeDeclareAsLatch. It
+  is an error to call this function on a NULL node.]
+  
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeDeclareAsLatch]
+
+******************************************************************************/
+boolean
+Ntk_NodeTestIsLatchInitialInput(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  return (node->latchInitialInput);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if node is a constant, else returns 0.]
+
+  Description [Returns 1 if node is a constant, else returns 0.  A constant is
+  a combinational node that has no inputs, and whose output can take exactly
+  one of its values.  It is an error to call this function on a NULL node.]
+  
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeDeclareAsCombinational]
+
+******************************************************************************/
+boolean
+Ntk_NodeTestIsConstant(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  return (node->constant);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the shadow of a node.]
+
+  Description [Returns the shadow of a node if one exists, else returns NULL.
+  A shadow node can serve as a placeholder for an extra MDD variable, such as
+  a next state variable.  It is an error to call this function on a node that
+  is a shadow.]
+  
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeDeclareAsShadow Ntk_ShadowReadOrigin Ntk_NodeTestIsShadow]
+
+******************************************************************************/
+Ntk_Node_t *
+Ntk_NodeReadShadow(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  assert(node->type != NtkShadow_c);
+  return (node->shadowInfo.shadow);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the origin node of a shadow node.]
+
+  Description [Returns the origin node of a shadow node.  The origin of a
+  shadow node is that node that is "casting" the shadow.  A shadow is used as
+  a placeholder for a node, in particular a place to store an additional MDD
+  variable.  It is an error to call this function on a node that is not a
+  shadow.]
+  
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeDeclareAsShadow Ntk_NodeReadShadow Ntk_NodeTestIsShadow]
+
+******************************************************************************/
+Ntk_Node_t *
+Ntk_ShadowReadOrigin(
+  Ntk_Node_t * shadow)
+{
+  assert(shadow != NIL(Ntk_Node_t));
+  assert(shadow->type == NtkShadow_c);
+  return (shadow->shadowInfo.origin);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the of data input of a latch.]
+
+  Description [Returns the data input of a latch.  The data input determines the
+  value of the latch output at the next clock. It is an error to call this
+  function on a node that is not a latch.]
+  
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeDeclareAsLatch]
+
+******************************************************************************/
+Ntk_Node_t *
+Ntk_LatchReadDataInput(
+  Ntk_Node_t * node)
+{
+  Ntk_Node_t *data;
+  
+  assert(node != NIL(Ntk_Node_t));
+  assert(node->type == NtkLatch_c);
+  data = array_fetch(Ntk_Node_t *, node->fanins, LATCH_DATA);
+  
+  return (data);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the initial input of a latch.]
+
+  Description [Returns the initial input of a latch.  The initial value
+  of the latch is determined by the value of the initial input. It is
+  an error to call this function on a node that is not a latch.]
+  
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeDeclareAsLatch]
+
+******************************************************************************/
+Ntk_Node_t *
+Ntk_LatchReadInitialInput(
+  Ntk_Node_t * node)
+{
+  Ntk_Node_t *initial;
+  
+  assert(node != NIL(Ntk_Node_t));
+  assert(node->type == NtkLatch_c);
+  initial = array_fetch(Ntk_Node_t *, node->fanins, LATCH_INITIAL);
+  
+  return (initial);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of fanins of a node.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeReadNumFanouts]
+
+******************************************************************************/
+int
+Ntk_NodeReadNumFanins(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  return (array_n(node->fanins));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of fanouts of a node.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeReadNumFanins]
+
+******************************************************************************/
+int
+Ntk_NodeReadNumFanouts(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  return (array_n(node->fanouts));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the fanin of node corresponding to faninIndex.]
+
+  Description [Returns the fanin of node corresponding to faninIndex.  Fanins are
+  numbered starting from 0.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeReadFaninIndex]
+
+******************************************************************************/
+Ntk_Node_t *
+Ntk_NodeReadFaninNode(
+  Ntk_Node_t * node,
+  int  faninIndex)
+{
+  Ntk_Node_t *faninNode;
+  
+  assert(node != NIL(Ntk_Node_t));
+  assert((faninIndex >= 0) && (faninIndex < Ntk_NodeReadNumFanins(node)));
+  faninNode = array_fetch(Ntk_Node_t *, node->fanins, faninIndex);
+  return (faninNode);
+}
+
+  
+/**Function********************************************************************
+
+  Synopsis    [Returns the fanin index of node corresponding to faninNode.]
+
+  Description [Returns the fanin index of node corresponding to faninNode. If
+  faninNode is not a fanin of node, then returns NTK_UNDEFINED_FANIN_INDEX.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeReadFaninNode]
+
+******************************************************************************/
+int
+Ntk_NodeReadFaninIndex(
+  Ntk_Node_t * node,
+  Ntk_Node_t * faninNode)
+{
+  int         i;
+  Ntk_Node_t *tempNode;
+  
+  assert(node != NIL(Ntk_Node_t));
+  Ntk_NodeForEachFanin(node, i, tempNode) {
+    if (tempNode == faninNode) {
+      return (i);
+    }
+  }
+
+  return (NTK_UNDEFINED_FANIN_INDEX);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the array of fanins of a node.]
+
+  Description [Returns the array of fanins of a node.  The user must not free or
+  modify this array in any way.]
+  
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeReadNumFanins]
+
+******************************************************************************/
+array_t *
+Ntk_NodeReadFanins(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  return (node->fanins);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the array of fanouts of a node.]
+
+  Description [Returns the array of fanouts of a node.  The user must not free or
+  modify this array in any way.]
+  
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeReadNumFanouts]
+
+******************************************************************************/
+array_t *
+Ntk_NodeReadFanouts(
+  Ntk_Node_t * node)
+{
+  assert(node != NIL(Ntk_Node_t));
+  return (node->fanouts);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the array of fanins of a node.]
+
+  Description [Sets the array of fanins of a node. This function must be used
+  with UTMOST caution. Use this only when you know EXACTLY what you are doing.]
+  
+  SideEffects [Old fanin array is deleted.]
+
+  SeeAlso     [Ntk_NodeReadNumFanins Ntk_NodeReadFanins]
+
+******************************************************************************/
+void
+Ntk_NodeSetFanins(
+  Ntk_Node_t * node,
+  array_t *faninArray)
+{
+  assert(node != NIL(Ntk_Node_t));
+  if (node->fanins)
+    array_free(node->fanins);
+  
+  node->fanins = faninArray;
+
+  return;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the array of fanouts of a node.]
+
+  Description [Sets the array of fanouts of a node. This function must be used
+  with UTMOST caution. Use this only when you know EXACTLY what you are doing.]
+  
+  SideEffects [Old fanout array is deleted.]
+
+  SeeAlso     [Ntk_NodeReadNumFanouts Ntk_NodeReadFanouts]
+
+******************************************************************************/
+void
+Ntk_NodeSetFanouts(
+  Ntk_Node_t * node,
+  array_t *fanoutArray)
+{
+  assert(node != NIL(Ntk_Node_t));
+  if (node->fanouts)
+    array_free(node->fanouts);
+  
+  node->fanouts = fanoutArray;
+
+  return;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a string giving a node's type.]
+
+  Description [Returns a string giving a node's type.  The return string can
+  be one of the following: "latch", "shadow", "primary-input", "pseudo-input",
+  "combinational", or "unassigned".  It is the user's responsibility to free
+  this string.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NodePrint]
+
+******************************************************************************/
+char *
+Ntk_NodeObtainTypeAsString(
+  Ntk_Node_t * node)
+{
+  char *typeString;
+
+  assert(node != NIL(Ntk_Node_t));
+  switch(node->type) {
+      case NtkLatch_c:
+        typeString = util_strsav("latch");
+        break;
+      case NtkShadow_c:
+        typeString = util_strsav("shadow");
+        break;
+      case NtkPrimaryInput_c:
+        typeString = util_strsav("primary-input");
+        break;
+      case NtkPseudoInput_c:
+        typeString = util_strsav("pseudo-input");
+        break;
+      case NtkCombinational_c:
+        typeString = util_strsav("combinational");
+        break;
+      case NtkUnassigned_c:
+        typeString = util_strsav("unassigned");
+        break;
+      default:
+        fail("Unexpected type");
+  }
+  return (typeString);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints information about a node.]
+
+  Description [Prints the node's name, MDD id, type, and attributes. In
+  addition, if printIo is TRUE, prints the name of each fanin node and each
+  fanout node. And if printTableStats is TRUE, print table statistics for
+  those nodes having a table.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkPrint]
+
+******************************************************************************/
+void
+Ntk_NodePrint(
+  FILE * fp,
+  Ntk_Node_t * node,
+  boolean printIo,
+  boolean printTableStats)
+{
+  int         i;
+  Ntk_Node_t *fanin;
+  Ntk_Node_t *fanout;
+  char       *typeString = Ntk_NodeObtainTypeAsString(node);
+  
+
+  /*
+   * Print the node's name, MDD id, type, and attributes.
+   */
+  (void) fprintf(fp, "%s: mdd=%d, %s;%s%s%s%s%s%s\n",
+                 Ntk_NodeReadName(node),
+                 Ntk_NodeReadMddId(node),
+                 typeString,
+                 (Ntk_NodeTestIsPrimaryOutput(node) ? " output" : ""),
+                 (Ntk_NodeTestIsConstant(node) ? " constant" : ""),
+                 (Ntk_NodeTestIsLatchDataInput(node) ? " data-input" : ""),
+                 (Ntk_NodeTestIsLatchInitialInput(node) ? " initial-input" : ""),
+                 (Ntk_NodeTestIsCombInput(node) ? " comb-input" : ""),
+                 (Ntk_NodeTestIsCombOutput(node) ? " comb-output" : "")
+                 );
+
+  FREE(typeString);
+  
+  if (printIo) {
+    /*
+     * Print the name of each fanin.
+     */
+    (void) fprintf(fp, "Fanins:  ");
+    Ntk_NodeForEachFanin(node, i, fanin) {
+      if (i != 0) (void) fprintf(fp, ",");
+      (void) fprintf(fp, " %s", Ntk_NodeReadName(fanin));
+    }
+    (void) fprintf(fp, "\n");
+
+    /*
+     * Print the name of each fanout.
+     */
+    (void) fprintf(fp, "Fanouts: ");
+    Ntk_NodeForEachFanout(node, i, fanout) {
+      if (i != 0) (void) fprintf(fp, ",");
+      (void) fprintf(fp, " %s", Ntk_NodeReadName(fanout));
+    }
+    (void) fprintf(fp, "\n");
+  }
+
+  if (printTableStats) {
+    if (Ntk_NodeTestIsCombinational(node) || Ntk_NodeTestIsPseudoInput(node)) {
+      Tbl_TablePrintStats(Ntk_NodeReadTable(node), fp);
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a node in a network with a name and a variable.]
+
+  Description [Creates a node in a network.  The name, network, and variable
+  fields are initialized with the supplied values (a copy of name is made
+  first, a copy of the variable is not made).  The fanins and fanouts fields
+  are initialized with empty arrays.  All other fields are initialized to NULL
+  or UNASSIGNED values.  A non-NULL name, non-NULL network, and non-NULL
+  variable are required. This is the only way to allocate a node; in other
+  words, a node can only exist with a name and a variable, within the context
+  of a network.]
+
+  SideEffects [The node is added to the network's information.]
+
+  SeeAlso     [Ntk_NodeFree]
+
+******************************************************************************/
+Ntk_Node_t *
+Ntk_NodeCreateInNetwork(
+  Ntk_Network_t * network,
+  char * name,
+  Var_Variable_t *variable)
+{
+  Ntk_Node_t *node = ALLOC(Ntk_Node_t, 1);
+
+  assert(network != NIL(Ntk_Network_t));
+  assert(name != NIL(char));
+  assert(variable != NIL(Var_Variable_t));
+  
+  node->name                  = util_strsav(name);
+  node->network               = network;
+  node->variable              = variable;
+  node->type                  = NtkUnassigned_c;
+  node->fanins                = array_alloc(Ntk_Node_t *, 0);
+  node->fanouts               = array_alloc(Ntk_Node_t *, 0);
+  node->table                 = NIL(Tbl_Table_t);
+  node->outputIndex           = UNASSIGNED_OUTPUT_INDEX;
+  node->mddId                 = NTK_UNASSIGNED_MDD_ID;
+  node->mAigId                = -1;
+  node->shadowInfo.shadow     = NIL(Ntk_Node_t);
+  node->outputFlag            = 0;
+  node->constant              = 0;
+  node->latchDataInput        = 0;
+  node->latchInitialInput     = 0;
+  node->undef                 = NIL(void);
+
+  /*
+   * Update the state of the network. Note: it's important to use node->name
+   * here, rather than just name, because we don't own name.
+   */
+  st_insert(network->actualNameToNode, (char *) node->name, (char *) node);
+  lsNewEnd(network->nodes, (lsGeneric) node, LS_NH);
+
+  return (node);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Declares a node as combinational and sets the table.]
+
+  Description [Declares a node as combinational using the column of table
+  corresponding to outputIndex as the function of the node.  This function
+  does not make a copy of the table; instead, it just sets a pointer to it.
+  However, it's assumed that the table will own the table, and the table is
+  freed when the node is freed.  Connections are made to the nodes
+  corresponding to the inputs in the table.  The node for the ith table input
+  is found by calling Ntk_NetworkFindNodeByName with the ith entry of
+  inputNames.  The order of the fanins of node returned by
+  Ntk_NodeForEachFanin are guaranteed to be the same as the order of the
+  corresponding input columns in the table.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeDeclareAsPrimaryInput Ntk_NodeDeclareAsPrimaryOutput]
+
+******************************************************************************/
+void
+Ntk_NodeDeclareAsCombinational(
+  Ntk_Node_t * node,
+  Tbl_Table_t * table,
+  array_t * inputNames /* array of char */,
+  int  outputIndex)
+{
+  int            i;
+  Ntk_Network_t *network = node->network;
+
+  assert(node->type == NtkUnassigned_c);
+  
+  node->type        = NtkCombinational_c;
+  node->table       = table;
+  node->outputIndex = outputIndex;
+
+  /*
+   * If it can be determined that the corresponding output column of table can
+   * take assume just a single value, then set the constant flag. 
+   */
+  if (Tbl_TableTestIsConstant(table, outputIndex)) {
+    node->constant = 1;
+  }
+  
+  /*
+   * Create a connection to each input of table. 
+   */
+  for (i = 0; i < array_n(inputNames); i++) {
+    char        *faninName = array_fetch(char *, inputNames, i);
+    Ntk_Node_t  *fanin     = Ntk_NetworkFindNodeByName(network, faninName);
+
+    assert(fanin != NIL(Ntk_Node_t));
+
+    /*
+     * Make the connections between node and fanin.  Note: it is critical
+     * that the fanins of node are added to node->fanins in the same order
+     * they appear in the table.
+     */
+    array_insert_last(Ntk_Node_t *, fanin->fanouts, node);
+    array_insert_last(Ntk_Node_t *, node->fanins, fanin);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Declares a node as a latch.]
+
+  Description [Declares a node as a latch.  Makes connections to the data and
+  initial input nodes.  The data node is taken as that one found by calling
+  Ntk_NetworkFindNodeByName with the name "dataName"; likewise for the initial
+  node.  Adds the node to the end of the latch list of the node's network, and
+  the combinational input list.  This function does not automatically create
+  a shadow node for the latch (i.e. a node to store information about the next
+  state variable of the latch); to do this, use Ntk_NodeCreateInNetwork and
+  Ntk_NodeDeclareAsShadow.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_LatchReadDataInput Ntk_LatchReadInitialInput]
+
+******************************************************************************/
+void
+Ntk_NodeDeclareAsLatch(
+  Ntk_Node_t * latch,
+  char * dataName,
+  char * initName)
+{
+  Ntk_Node_t    *dataNode;
+  Ntk_Node_t    *initNode;
+  Ntk_Network_t *network = latch->network;
+  
+  assert(latch->type == NtkUnassigned_c);
+  latch->type = NtkLatch_c;
+
+  /*
+   * Get the nodes corresponding to dataName and initName.
+   */
+  dataNode = Ntk_NetworkFindNodeByName(network, dataName);
+  initNode = Ntk_NetworkFindNodeByName(network, initName);
+  assert(dataNode != NIL(Ntk_Node_t));
+  assert(initNode != NIL(Ntk_Node_t));
+
+  /*
+   * Make the necessary connections. Note the predefined locations of the data
+   * and initial inputs in the fanin array of latch.
+   */
+  array_insert(Ntk_Node_t *, latch->fanins, LATCH_DATA, dataNode);
+  array_insert(Ntk_Node_t *, latch->fanins, LATCH_INITIAL, initNode);
+
+  array_insert_last(Ntk_Node_t *, dataNode->fanouts, latch);
+  array_insert_last(Ntk_Node_t *, initNode->fanouts, latch);
+
+  /*
+   * Set the special flags in the data and init nodes, and add them to the
+   * list of combinational outputs.
+   */
+  dataNode->latchDataInput = 1;
+  NetworkAddCombOutput(network, dataNode);
+
+  initNode->latchInitialInput = 1;
+  NetworkAddCombOutput(network, initNode);
+
+  /*
+   * Add the latch to the appropriate lists in network.
+   */
+  lsNewEnd(network->latches,    (lsGeneric) latch, LS_NH);
+  lsNewEnd(network->combInputs, (lsGeneric) latch, LS_NH);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Declares a node as a primary input.]
+
+  Description [Declares a node as a primary input.  Adds node to the relevant
+  node lists maintained by the node's network.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeDeclareAsPrimaryOutput]
+
+******************************************************************************/
+void
+Ntk_NodeDeclareAsPrimaryInput(
+  Ntk_Node_t * node)
+{
+  assert(node->type == NtkUnassigned_c);
+  node->type = NtkPrimaryInput_c;
+
+  lsNewEnd(node->network->primaryInputs, (lsGeneric) node, LS_NH);
+  lsNewEnd(node->network->inputs,        (lsGeneric) node, LS_NH);
+  lsNewEnd(node->network->combInputs,    (lsGeneric) node, LS_NH);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Declares a node as a pseudo input.]
+
+  Description [Declares a node as a pseudo input.  The function of a pseudo
+  input is given by the column of table corresponding to outputIndex.  This
+  function does not make a copy of the table; instead, it just sets a pointer
+  to it.  However, it's assumed that the table will own the table, and the
+  table is freed when the node is freed.  Adds node to the relevant node lists
+  maintained by the node's network.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeDeclareAsPrimaryInput]
+
+******************************************************************************/
+void
+Ntk_NodeDeclareAsPseudoInput(
+  Ntk_Node_t * node,
+  Tbl_Table_t * table,
+  int  outputIndex)
+{
+  assert(node->type == NtkUnassigned_c);
+
+  node->type        = NtkPseudoInput_c;
+  node->table       = table;
+  node->outputIndex = outputIndex;
+  
+  if (Tbl_TableTestIsConstant(table, outputIndex)) {
+    node->constant = 1;
+  }
+  
+  lsNewEnd(node->network->pseudoInputs, (lsGeneric) node, LS_NH);
+  lsNewEnd(node->network->inputs,       (lsGeneric) node, LS_NH);
+  lsNewEnd(node->network->combInputs,   (lsGeneric) node, LS_NH);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Declares a node as a primary output.]
+
+  Description [Declares a node as a primary output.  Node can be of any type,
+  except type shadow.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_TestIsPrimaryOutput]
+
+******************************************************************************/
+void
+Ntk_NodeDeclareAsPrimaryOutput(
+  Ntk_Node_t * node)
+{
+  assert(node->type != NtkShadow_c);
+  node->outputFlag = 1;
+  lsNewEnd(node->network->primaryOutputs, (lsGeneric) node, LS_NH);
+  NetworkAddCombOutput(node->network, node);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Declares a node as a shadow node.]
+
+  Description [Declares a node as a shadow node. A shadow node is used to
+  associate extra information with a node, in particular another MDD id.  Any
+  "origin" node can have a shadow node, except a node which itself is of type
+  shadow. This function makes the bidirectional link between the shadow and
+  origin nodes.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeTestIsShadow Ntk_ShadowReadOrigin Ntk_NodeReadShadow]
+
+******************************************************************************/
+void
+Ntk_NodeDeclareAsShadow(
+  Ntk_Node_t * shadow,
+  Ntk_Node_t * origin)
+{
+  assert(shadow->type == NtkUnassigned_c);
+  assert(origin->type != NtkShadow_c);
+  
+  shadow->type = NtkShadow_c;
+
+  shadow->shadowInfo.origin = origin;
+  origin->shadowInfo.shadow = shadow;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees all the memory local to the node.]
+
+  Description [Frees all the memory local to the node, including the node
+  itself. Does not free the nodes in the fanin and fanout of node, nor does it
+  free the network of node.  Also, this function does not update the lists
+  maintained by the network to reflect that this node no longer exists, nor
+  does it update the fanin and fanout lists of neighboring nodes.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeCreateInNetwork]
+
+******************************************************************************/
+void
+Ntk_NodeFree(
+  Ntk_Node_t * node)
+{
+  FREE(node->name);
+  array_free(node->fanins);
+  array_free(node->fanouts);
+  Tbl_TableFree(node->table);
+  
+  /*
+   * Unassign a few key fields for safety's sake.
+   */
+  node->name              = NIL(char);
+  node->network           = NIL(Ntk_Network_t);
+  node->variable          = NIL(Var_Variable_t);
+  node->type              = NtkUnassigned_c;
+  node->fanins            = NIL(array_t);
+  node->fanouts           = NIL(array_t);
+  node->table             = NIL(Tbl_Table_t);
+  node->mddId             = NTK_UNASSIGNED_MDD_ID;
+
+  FREE(node);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Adds a node to the network's list of combinational outputs.]
+
+  Description [Adds a node to the network's list of combinational outputs. If
+  the list already contains the node, then nothing is done.  List membership
+  is maintained via a hash table.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkForEachCombOutput]
+
+******************************************************************************/
+static void
+NetworkAddCombOutput(
+  Ntk_Network_t *network,
+  Ntk_Node_t    *node)
+{
+  if (!st_is_member(network->combOutputsTable, (char *) node)) {
+    st_insert(network->combOutputsTable, (char *) node, (char *) 0);
+    lsNewEnd(network->combOutputs, (lsGeneric) node, LS_NH);
+  }
+}
+
+    
+
+
+
Index: vis_dev/vis-2.3/src/ntk/ntkNtk.c
===================================================================
--- vis_dev/vis-2.3/src/ntk/ntkNtk.c	(revision 14)
+++ vis_dev/vis-2.3/src/ntk/ntkNtk.c	(revision 14)
@@ -0,0 +1,1800 @@
+/**CFile***********************************************************************
+
+  FileName    [ntkNtk.c]
+
+  PackageName [ntk]
+
+  Synopsis    [Routines to access the network data structure.]
+
+  Author      [Adnan Aziz, Tom Shiple]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ntkInt.h"
+#include "mdd.h"
+
+static char rcsid[] UNUSED = "$Id: ntkNtk.c,v 1.23 2010/04/09 23:44:05 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+/**Struct**********************************************************************
+
+  Synopsis    [Structure to store uninterpreted application info.]
+
+  SeeAlso     [Ntk_NetworkAddApplInfo]
+
+******************************************************************************/
+typedef struct ApplInfoStruct {
+  Ntk_ApplInfoFreeFn  freeFn;  /* application function to free data */
+  void               *data;    /* application data */
+} ApplInfo_t;
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static char * NodeReadNameFromTable(Ntk_Node_t *node, st_table *name2ToName1);
+static Tbl_Table_t * DuplicateTableAndVars(Ntk_Node_t *node, char *name);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the name of a network.]
+
+  Description [Returns the name of a network.  Every network must have a name. It
+  is an error to call this function on a NULL network.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkAlloc]
+
+******************************************************************************/
+char *
+Ntk_NetworkReadName(
+  Ntk_Network_t * network)
+{
+  return (network->name);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the MDD manager of a network.]
+
+  Description [Returns the MDD manager of a network.  The MDD manager is set
+  by calling Ntk_NetworkSetMddManager.  If the application frees the returned
+  MDD manager, then it should in turn set the network's MDD manager pointer to
+  NULL.  If the pointer is non-NULL when Ntk_NetworkFree is called, then the MDD
+  manager will be freed. It is an error to call this function on a NULL
+  network.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkSetMddManager Ntk_NetworkInitializeMddManager]
+
+******************************************************************************/
+mdd_manager *
+Ntk_NetworkReadMddManager(
+  Ntk_Network_t * network)
+{
+  return (network->mddManager);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the MDD manager of a network.]
+
+  Description [Sets the MDD manager of a network.  This could be useful, for
+  example, to force two networks to have the same MDD manager.  However, be
+  careful that in the end the manager is only freed once.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkReadMddManager Ntk_NetworkInitializeMddManager]
+
+******************************************************************************/
+void
+Ntk_NetworkSetMddManager(
+  Ntk_Network_t  * network,
+  mdd_manager * mddManager)
+{
+  network->mddManager = mddManager;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the MAig manager of a network.]
+
+  Description [Returns the MAig manager of a network.  The MAig manager is set
+  by calling Ntk_NetworkSetMAigManager.  If the application frees the returned
+  MAig manager, then it should in turn set the network's MAig manager pointer to
+  NULL.  If the pointer is non-NULL when Ntk_NetworkFree is called, then the MAig
+  manager will be freed. It is an error to call this function on a NULL
+  network.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkSetMAigManager Ntk_NetworkInitializeMAigManager]
+
+******************************************************************************/
+mAig_Manager_t *
+Ntk_NetworkReadMAigManager(
+  Ntk_Network_t * network)
+{
+  return (network->mAigManager);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the mAig manager of a network and the netowrk for the
+	       mAig manager.]
+
+  Description [Sets the MAig manager of a network.  This could be useful, for
+  example, to force two networks to have the same MAig manager.  However, be
+  careful that in the end the manager is only freed once.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkReadMAigManager Ntk_NetworkInitializeMAigManager]
+
+******************************************************************************/
+void
+Ntk_NetworkSetMAigManager(
+  Ntk_Network_t * network,
+  mAig_Manager_t * mAigManager)
+{
+  network->mAigManager = mAigManager;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Creates and initializes an empty MDD manager for a network.]
+
+  Description [Creates and initializes an empty MDD manager for a
+  network. Sets the MDD manager field of the network, and returns a pointer to
+  the newly created manager.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkReadMddManager Ntk_NetworkSetMddManager]
+
+******************************************************************************/
+mdd_manager *
+Ntk_NetworkInitializeMddManager(
+  Ntk_Network_t * network)
+{
+  network->mddManager = mdd_init_empty();
+
+  return (network->mddManager);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the dynamic variable ordering method of a network.]
+
+  Description [Returns the dynamic variable ordering method of a network.  The
+  method is set by calling Ntk_NetworkSetDynamicVarOrderingMethod.  The method
+  is set to BDD_REORDER_NONE when the network is first created.  It is an
+  error to call this function on a NULL network.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkSetDynamicVarOrderingMethod]
+
+******************************************************************************/
+bdd_reorder_type_t
+Ntk_NetworkReadDynamicVarOrderingMethod(
+  Ntk_Network_t * network)
+{
+  return (network->dynVarOrdMethod);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the dynamic variable ordering method of a network.]
+
+  Description [Sets the dynamic variable ordering method of a
+  network. Allowable values of dynVarOrdMethod are BDD_REORDER_SIFT,
+  BDD_REORDER_WINDOW, and BDD_REORDER_NONE.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkReadDynamicVarOrderingMethod]
+
+******************************************************************************/
+void
+Ntk_NetworkSetDynamicVarOrderingMethod(
+  Ntk_Network_t * network,
+  bdd_reorder_type_t dynVarOrdMethod,
+  bdd_reorder_verbosity_t verbosity)
+{
+  bdd_dynamic_reordering(network->mddManager, dynVarOrdMethod, verbosity);
+  if (bdd_get_package_name() != CUDD) {
+    if (dynVarOrdMethod == BDD_REORDER_SIFT ||
+	dynVarOrdMethod == BDD_REORDER_WINDOW ||
+	dynVarOrdMethod == BDD_REORDER_NONE) {
+      network->dynVarOrdMethod = dynVarOrdMethod;
+    } else
+      network->dynVarOrdMethod = BDD_REORDER_SIFT;
+  } else
+    network->dynVarOrdMethod = dynVarOrdMethod;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the undef field of a network.]
+
+  Description [Returns the undef field of a network.  There is no restriction on
+  how this field is used.  It is an error to call this function on a NULL
+  network.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkAlloc Ntk_NetworkSetUndef]
+
+******************************************************************************/
+void *
+Ntk_NetworkReadUndef(
+  Ntk_Network_t * network)
+{
+  return (network->undef);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the undef field of a network.]
+
+  Description [Sets the undef field of a network.  There is no restriction on
+  how this field is used.  It is an error to call this function on a NULL
+  network.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkAlloc Ntk_NetworkReadUndef]
+
+******************************************************************************/
+void
+Ntk_NetworkSetUndef(
+  Ntk_Network_t * network,
+  void * value)
+{
+  network->undef = value;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds a node in a network by its MDD id.]
+
+  Description [Finds a node in a network by its MDD id.  The MDD id of a node
+  is the MDD id returned by Ntk_NodeReadMddId. If the MDD id doesn't
+  correspond to an existing node in the network, a NULL pointer is returned.
+  Also, if MDD id is equal to NTK_UNASSIGNED_MDD_ID, a NULL pointer is
+  returned.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NodeSetMddId Ntk_NodeReadMddId]
+
+******************************************************************************/
+Ntk_Node_t *
+Ntk_NetworkFindNodeByMddId(
+  Ntk_Network_t * network,
+  int             mddId)
+{
+  Ntk_Node_t *node = NIL(Ntk_Node_t);
+
+  if (mddId != NTK_UNASSIGNED_MDD_ID) {
+    st_lookup(network->mddIdToNode, (char *) (long) mddId, &node);
+  }
+
+  return (node);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds a node in a network by its actual name.]
+
+  Description [Finds a node in a network by its actual name.  The actual name
+  of a node is the name stored with the node (i.e returned by
+  Ntk_NodeReadName). If the name doesn't correspond to an existing node in the
+  network, a NULL pointer is returned.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkReadActualNameFromFormalName Ntk_NodeReadName]
+
+******************************************************************************/
+Ntk_Node_t *
+Ntk_NetworkFindNodeByActualName(
+  Ntk_Network_t * network,
+  char * name)
+{
+  Ntk_Node_t *node = NIL(Ntk_Node_t);
+
+  st_lookup(network->actualNameToNode, name, &node);
+
+  return (node);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds a node in a network by its formal name, or actual name.]
+
+  Description [Finds a node in a network by its name.  First, the formal name
+  to actual name table is checked to see if there is an actual name
+  corresponding to the name.  If so, then the node corresponding to the actual
+  name is returned.  If there is no corresponding actual name, then it's
+  assumed that the name is an actual name, and the corresponding node is
+  returned.  If no corresponding node is found, then a NULL pointer is
+  returned.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkReadActualNameFromFormalName
+  Ntk_NetworkFindNodeByActualName]
+
+******************************************************************************/
+Ntk_Node_t *
+Ntk_NetworkFindNodeByName(
+  Ntk_Network_t * network,
+  char * name)
+{
+  Ntk_Node_t *node = NIL(Ntk_Node_t);
+  char *actualName = Ntk_NetworkReadActualNameFromFormalName(network, name);
+
+  /*
+   * If there was no actual name corresponding to name in the formal to actual
+   * table, then treat name as an actualName.
+   */
+  if (actualName == NIL(char)) {
+    actualName = name;
+  }
+
+  st_lookup(network->actualNameToNode, actualName, &node);
+
+  return (node);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the actual name corresponding to a formal name.]
+
+  Description [Returns the actual name corresponding to a formal name in a
+  network.  The actual name is unique in a network.  Nodes of a network are
+  identified by their actual names. If the formal name doesn't correspond to
+  an actual name in the network, a NULL pointer is returned.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkFindNodeByActualName
+  Ntk_NetworkInsertFormalNameToActualName]
+
+******************************************************************************/
+char *
+Ntk_NetworkReadActualNameFromFormalName(
+  Ntk_Network_t * network,
+  char * formalName)
+{
+  char *actualName = NIL(char);
+
+  st_lookup(network->formalNameToActualName, formalName, &actualName);
+
+  return (actualName);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates correspondence from formalName to actualName.]
+
+  Description [Creates correspondence from formalName to actualName. Copies
+  are made of formalName and actualName before storing them.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkReadActualNameFromFormalName]
+
+******************************************************************************/
+void
+Ntk_NetworkInsertFormalNameToActualName(
+  Ntk_Network_t * network,
+  char * formalName,
+  char * actualName)
+{
+  char *formalNameCopy = util_strsav(formalName);
+  char *actualNameCopy = util_strsav(actualName);
+
+  st_insert(network->formalNameToActualName, formalNameCopy, actualNameCopy);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of nodes of a network.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkReadNumPrimaryInputs Ntk_NetworkReadNumLatches]
+
+******************************************************************************/
+int
+Ntk_NetworkReadNumNodes(
+  Ntk_Network_t * network)
+{
+  return (lsLength(network->nodes));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of latches of a network.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkReadNumNodes Ntk_NetworkReadNumPrimaryInputs]
+
+******************************************************************************/
+int
+Ntk_NetworkReadNumLatches(
+  Ntk_Network_t * network)
+{
+  return (lsLength(network->latches));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of combinational inputs of a network.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkReadNumNodes Ntk_NetworkReadNumLatches]
+
+******************************************************************************/
+int
+Ntk_NetworkReadNumCombInputs(
+  Ntk_Network_t * network)
+{
+  return (lsLength(network->combInputs));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of combinational outputs of a network.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkReadCombOutputs Ntk_NetworkReadNumNodes
+  Ntk_NetworkReadNumLatches]
+
+******************************************************************************/
+int
+Ntk_NetworkReadNumCombOutputs(
+  Ntk_Network_t * network)
+{
+  return (lsLength(network->combOutputs));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of primary inputs of a network.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkReadNumPseudoInputs Ntk_NetworkReadNumInputs]
+
+******************************************************************************/
+int
+Ntk_NetworkReadNumPrimaryInputs(
+  Ntk_Network_t * network)
+{
+  return (lsLength(network->primaryInputs));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of pseudo inputs of a network.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkReadNumPrimaryInputs Ntk_NetworkReadNumInputs]
+
+******************************************************************************/
+int
+Ntk_NetworkReadNumPseudoInputs(
+  Ntk_Network_t * network)
+{
+  return (lsLength(network->pseudoInputs));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of inputs (primary plus pseudo) of a network.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkReadNumPrimaryInputs Ntk_NetworkReadNumPseudoInputs]
+
+******************************************************************************/
+int
+Ntk_NetworkReadNumInputs(
+  Ntk_Network_t * network)
+{
+  return (lsLength(network->inputs));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of primary outputs of a network.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkReadNumNodes Ntk_NetworkReadNumLatches]
+
+******************************************************************************/
+int
+Ntk_NetworkReadNumPrimaryOutputs(
+  Ntk_Network_t * network)
+{
+  return (lsLength(network->primaryOutputs));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the list of nodes of a network.]
+
+  Description [Returns the list of all the nodes of a network.  The application
+  must not free or modify this list in any way.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkReadNumNodes]
+
+******************************************************************************/
+lsList
+Ntk_NetworkReadNodes(
+  Ntk_Network_t * network)
+{
+  return (network->nodes);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the list of combinational inputs of a network.]
+
+  Description [Returns the list of combinational inputs of a network.  The
+  application must not free or modify this list in any way.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkReadNumCombInputs]
+
+******************************************************************************/
+lsList
+Ntk_NetworkReadCombInputs(
+  Ntk_Network_t * network)
+{
+  return (network->combInputs);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the list of combinational outputs of a network.]
+
+  Description [Returns the list of combinational outputs of a network.  A node
+  can appear at most once in this list (e.g. even if a node serves as the data
+  input for more than one latch, it appears just once in this list). The
+  application must not free or modify this list in any way.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkReadNumCombOutputs]
+
+******************************************************************************/
+lsList
+Ntk_NetworkReadCombOutputs(
+  Ntk_Network_t * network)
+{
+  return (network->combOutputs);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the list of latches of a network.]
+
+  Description [Returns the list of latches of a network.  The application must
+  not free or modify this list in any way.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkReadNumLatches]
+
+******************************************************************************/
+lsList
+Ntk_NetworkReadLatches(
+  Ntk_Network_t * network)
+{
+  return (network->latches);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the list of primary inputs of a network.]
+
+  Description [Returns the list of primary inputs of a network.  The application
+  must not free or modify this list in any way.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkReadNumPrimaryInputs]
+
+******************************************************************************/
+lsList
+Ntk_NetworkReadPrimaryInputs(
+  Ntk_Network_t * network)
+{
+  return (network->primaryInputs);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the list of pseudo inputs of a network.]
+
+  Description [Returns the list of pseudo inputs of a network.  The application
+  must not free or modify this list in any way.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkReadNumPseudoInputs]
+
+******************************************************************************/
+lsList
+Ntk_NetworkReadPseudoInputs(
+  Ntk_Network_t * network)
+{
+  return (network->pseudoInputs);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the list of primary and pseudo inputs of a network.]
+
+  Description [Returns the list of primary and pseudo inputs of a network.  The
+  application must not free or modify this list in any way.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkReadNumInputs]
+
+******************************************************************************/
+lsList
+Ntk_NetworkReadInputs(
+  Ntk_Network_t * network)
+{
+  return (network->inputs);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the list of primary outputs of a network.]
+
+  Description [Returns the list of primary outputs of a network.  The application
+  must not free or modify this list in any way.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkReadNumPrimaryOutputs]
+
+******************************************************************************/
+lsList
+Ntk_NetworkReadPrimaryOutputs(
+  Ntk_Network_t * network)
+{
+  return (network->primaryOutputs);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Associates application specified data with a network.]
+
+  Description [Adds the key/data pair to the network's applInfoTable. Key may
+  be an arbitrary string; to avoid possible conflicts with other applications,
+  key should be prefixed with the application's package name, for example
+  "Pkg_NetworkApplKey".  The contents of data are arbitrary; the network
+  package does not interpret the data. The freeFn is called on data when a
+  network is freed, or when Ntk_NetworkFreeApplInfo is called with the same
+  value of key. The freeFn takes (void *) as its only argument, and returns
+  void.  A copy is made of the string key before it is inserted into
+  applInfoTable.<p>
+
+  If this function is called with a key that already exists in the
+  applInfoTable, then the data for the previous entry is freed using the
+  freeFn, a new entry is created using the freeFn and data supplied as
+  arguments, and TRUE is returned. Otherwise, FALSE is returned.<p>
+
+  WARNING:  This function does not make a copy of data before inserting it
+  into the table.  By calling this function, the application is surrendering
+  responsibility to the network to free the data.  Once this function is
+  called on data, the data should be freed only by calling
+  Ntk_NetworkFreeApplInfo or Ntk_NetworkFree.  In other words, it is an error
+  for the application to explicitly free the data without using one of these
+  two functions. </p>]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkFreeApplInfo Ntk_NetworkReadApplInfo]
+
+******************************************************************************/
+boolean
+Ntk_NetworkAddApplInfo(
+  Ntk_Network_t * network,
+  char * key,
+  Ntk_ApplInfoFreeFn  freeFn,
+  void * data)
+{
+  ApplInfo_t *applInfo;
+  boolean     status;
+
+  if (st_lookup(network->applInfoTable, key, &applInfo)) {
+    (*applInfo->freeFn)(applInfo->data);
+    status = TRUE;
+  }
+  else {
+    char *keyCopy = util_strsav(key);
+
+    applInfo = ALLOC(ApplInfo_t, 1);
+    st_insert(network->applInfoTable, keyCopy, (char *) applInfo);
+    status = FALSE;
+  }
+
+  applInfo->freeFn = freeFn;
+  applInfo->data   = data;
+  return status;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Set application specified data with a network.]
+
+  Description [Same as Ntk_NetworkAddApplInfo, but this function simply set
+  the ApplInfo without checking/freeing if there already exists one. Instead,
+  the caller should take care of that case.]
+
+  SeeAlso     [Ntk_NetworkFreeApplInfo Ntk_NetworkAddApplInfo]
+
+  SideEffects [ApplInfo of the argument network is modified]
+
+******************************************************************************/
+boolean
+Ntk_NetworkSetApplInfo(
+  Ntk_Network_t * network,
+  char * key,
+  Ntk_ApplInfoFreeFn  freeFn,
+  void * data)
+{
+  ApplInfo_t *applInfo;
+  boolean     status;
+
+  if (st_lookup(network->applInfoTable, key, &applInfo)) {
+    status = TRUE;
+  }
+  else {
+    char *keyCopy = util_strsav(key);
+
+    applInfo = ALLOC(ApplInfo_t, 1);
+    st_insert(network->applInfoTable, keyCopy, (char *) applInfo);
+    status = FALSE;
+  }
+
+  applInfo->freeFn = freeFn;
+  applInfo->data   = data;
+  return status;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns data corresponding to key if it exists, else returns NULL.]
+
+  Description [If data corresponding to key is associated to the network, then
+  returns a pointer to data (as void *).  Otherwise, returns NULL.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkAddApplInfo Ntk_NetworkFreeApplInfo]
+
+******************************************************************************/
+void *
+Ntk_NetworkReadApplInfo(
+  Ntk_Network_t * network,
+  char * key)
+{
+  int         status;
+  ApplInfo_t *applInfo;
+
+  status = st_lookup(network->applInfoTable, key, &applInfo);
+  if (status == 1) {
+    return (applInfo->data);
+  }
+  else {
+    return (NIL(void));
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees application-specified data from a network.]
+
+  Description [If data corresponding to key exists in the network, then frees
+  the data using the associated free function, removes the key/data pair from
+  the network's applInfoTable, and returns TRUE.  If key does not exist, then
+  the function does nothing and returns FALSE.
+  <p>
+  WARNING: This function should be called only if a corresponding call to
+  Ntk_NetworkAddApplInfo has already been made.</p>]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkAddApplInfo Ntk_NetworkReadApplInfo]
+
+******************************************************************************/
+boolean
+Ntk_NetworkFreeApplInfo(
+  Ntk_Network_t * network,
+  char * key)
+{
+  int         status;
+  ApplInfo_t *applInfo;
+
+  status = st_lookup(network->applInfoTable, key, &applInfo);
+
+  if (status == 1) {
+    st_delete(network->applInfoTable, &key, &applInfo);
+    (*applInfo->freeFn)(applInfo->data);
+    FREE(key);  /* frees the string contained in the table */
+    FREE(applInfo);
+  }
+
+  return ((status) ? TRUE : FALSE);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates a network with a name.]
+
+  Description [Allocates a network with a name (a copy of name is made
+  first). Name must be non-NULL.  The remaining fields are initialized to
+  empty (e.g. empty lists, empty hash tables) or NULL (mddManager). The
+  dynVarOrdMethod is set to BDD_REORDER_NONE.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkFree]
+
+******************************************************************************/
+Ntk_Network_t *
+Ntk_NetworkAlloc(
+  char * name)
+{
+  Ntk_Network_t *network = ALLOC(Ntk_Network_t, 1);
+
+  network->name                   = util_strsav(name);
+  network->nodes                  = lsCreate();
+  network->combInputs             = lsCreate();
+  network->combOutputs            = lsCreate();
+  network->latches                = lsCreate();
+  network->primaryInputs          = lsCreate();
+  network->pseudoInputs           = lsCreate();
+  network->inputs                 = lsCreate();
+  network->primaryOutputs         = lsCreate();
+  network->combOutputsTable       = st_init_table(st_ptrcmp, st_ptrhash);
+  network->mddIdToNode            = st_init_table(st_numcmp, st_numhash);
+  network->actualNameToNode       = st_init_table(strcmp, st_strhash);
+  network->formalNameToActualName = st_init_table(strcmp, st_strhash);
+  network->applInfoTable          = st_init_table(strcmp, st_strhash);
+  network->mddManager             = NIL(mdd_manager);
+  network->mAigManager            = NIL(mAig_Manager_t);
+  network->dynVarOrdMethod        = BDD_REORDER_NONE;
+  network->undef                  = NIL(void);
+
+  return network;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees all the memory associated with a network.]
+
+  Description [Calls Ntk_NodeFree on each node of network, and then frees the
+  data local to network, and the network itself.  Also frees the MDD manager
+  of the network, if it is not NULL. If network is NULL, just returns.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkAlloc Ntk_NodeFree]
+
+******************************************************************************/
+void
+Ntk_NetworkFree(
+  Ntk_Network_t * network)
+{
+  char *formal;
+  char *actual;
+  char *key;
+  ApplInfo_t *applInfo;
+  Ntk_Node_t *node;
+  lsGen gen;
+  st_generator *stGen;
+
+
+  if (network == NIL(Ntk_Network_t)) {
+    return;
+  }
+
+  FREE(network->name);
+
+  Ntk_NetworkForEachNode(network, gen, node) {
+    Ntk_NodeFree(node);
+  }
+
+  (void) lsDestroy(network->nodes,           (void (*) (lsGeneric)) NULL);
+  (void) lsDestroy(network->combInputs,      (void (*) (lsGeneric)) NULL);
+  (void) lsDestroy(network->combOutputs,     (void (*) (lsGeneric)) NULL);
+  (void) lsDestroy(network->latches,         (void (*) (lsGeneric)) NULL);
+  (void) lsDestroy(network->primaryInputs,   (void (*) (lsGeneric)) NULL);
+  (void) lsDestroy(network->pseudoInputs,    (void (*) (lsGeneric)) NULL);
+  (void) lsDestroy(network->inputs,          (void (*) (lsGeneric)) NULL);
+  (void) lsDestroy(network->primaryOutputs,  (void (*) (lsGeneric)) NULL);
+  st_free_table(network->combOutputsTable);
+  st_free_table(network->mddIdToNode);
+
+  /*
+   * The keys in this table are strings representing node names.  The strings
+   * are owned by the nodes, so we don't free them here.
+   */
+  st_free_table(network->actualNameToNode);
+
+  /*
+   * Free all the strings in the formalNameToActualName table before freeing
+   * the table itself.
+   */
+  st_foreach_item(network->formalNameToActualName, stGen, &formal, &actual) {
+    FREE(formal);
+    FREE(actual);
+  }
+
+  st_free_table(network->formalNameToActualName);
+
+  /*
+   * Free all the key/applInfo pairs in the applInfoTable, and then free the
+   * table itself.
+   */
+  st_foreach_item(network->applInfoTable, stGen, &key, &applInfo) {
+    FREE(key);
+    (*applInfo->freeFn)(applInfo->data);
+    FREE(applInfo);
+  }
+  st_free_table(network->applInfoTable);
+
+  if (network->mddManager != NIL(mdd_manager)) {
+    mdd_quit(network->mddManager);
+  }
+
+  if (network->mAigManager != NIL(mAig_Manager_t)) {
+    mAig_quit(network->mAigManager);
+  }
+
+  FREE(network);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Callback function to free a network.]
+
+  Description [Typecasts data to (Ntk_Network_t *) and then calls
+  Ntk_NetworkFree.  This function should only be used as a callback for other
+  applications that don't know the network type, for example the Hrc_Node
+  ApplInfoTable.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkFree]
+
+******************************************************************************/
+void
+Ntk_NetworkFreeCallback(
+  void * data /* an object of type Ntk_Network_t*  type casted to void* */)
+{
+  Ntk_NetworkFree((Ntk_Network_t *) data);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Write a network in blif-MV format to a file.]
+
+  Description [Work in progress.  Still bogus in one major way:
+  Equal entries in tables use formal names.]
+
+  SideEffects [none]
+
+  SeeAlso     [Ntk_NetworkPrint Hrc_ModelWriteBlifMv]
+
+******************************************************************************/
+void
+Ntk_NetworkWriteBlifMv(
+  FILE *fp,
+  Ntk_Network_t *network,
+  boolean promotePseudo
+  )
+{
+  lsGen gen;
+  Ntk_Node_t *node;
+  int i;
+
+  (void) fprintf(fp, ".model %s\n", Ntk_NetworkReadName(network));
+
+  /* .inputs */
+  if (Ntk_NetworkReadNumPrimaryInputs(network) != 0) {
+    (void) fprintf(fp, ".inputs");
+    Ntk_NetworkForEachPrimaryInput(network, gen, node) {
+      (void) fprintf(fp, " %s", Ntk_NodeReadName(node));
+    }
+    (void) fprintf(fp, "\n");
+  }
+
+  if (promotePseudo && Ntk_NetworkReadNumPseudoInputs(network) != 0) {
+    (void) fprintf(fp, "# pseudo inputs\n");
+    (void) fprintf(fp, ".inputs");
+    Ntk_NetworkForEachPseudoInput(network, gen, node) {
+      (void) fprintf(fp, " %s", Ntk_NodeReadName(node));
+    }
+    (void) fprintf(fp, "\n");
+  }
+
+  /* .outputs */
+  if (Ntk_NetworkReadNumPrimaryOutputs(network) != 0) {
+    (void) fprintf(fp, ".outputs");
+    Ntk_NetworkForEachPrimaryOutput(network, gen, node) {
+      (void) fprintf(fp, " %s", Ntk_NodeReadName(node));
+    }
+    (void) fprintf(fp, "\n");
+  }
+
+  /* .mv .names .latch .reset */
+  Ntk_NetworkForEachNode(network, gen, node) {
+    Var_Variable_t *var = Ntk_NodeReadVariable(node);
+    char *nodeName = Ntk_NodeReadName(node);
+    boolean is_enum = Var_VariableTestIsEnumerative(var);
+    int range = Var_VariableReadNumValues(var);
+
+    if (Ntk_NodeTestIsShadow(node)) continue;
+    if (Ntk_NodeTestIsCombinational(node) &&
+	Ntk_NodeTestIsLatchInitialInput(node)) continue;
+
+    if (is_enum) {
+      if (range != 2) {
+	/* Boolean enumerative variables need no .mv declaration. */
+	(void) fprintf(fp, ".mv %s %d\n", nodeName, range);
+      }
+    } else {
+      /* Variable is symbolic. */
+      (void) fprintf(fp, ".mv %s %d", nodeName, range);
+      for (i = 0; i < range; i++) {
+	(void) fprintf(fp, " %s",
+		       Var_VariableReadSymbolicValueFromIndex(var, i));
+      }
+      (void) fprintf(fp, "\n");
+    }
+  }
+
+  if (!promotePseudo && Ntk_NetworkReadNumPseudoInputs(network) != 0) {
+    (void) fprintf(fp, "# pseudo inputs start\n");
+    Ntk_NetworkForEachPseudoInput(network, gen, node) {
+      Tbl_Table_t *dupTable = DuplicateTableAndVars(node,
+						    Ntk_NodeReadName(node));
+      Tbl_TableWriteBlifMvToFile(dupTable, 0, fp);
+      Tbl_TableFree(dupTable);
+    }
+    (void) fprintf(fp, "# pseudo inputs end\n");
+  }
+
+  Ntk_NetworkForEachNode(network, gen, node) {
+
+    if (Ntk_NodeTestIsShadow(node)) continue;
+    if (Ntk_NodeTestIsCombinational(node) &&
+	Ntk_NodeTestIsLatchInitialInput(node)) continue;
+
+    if (Ntk_NodeTestIsCombinational(node)) {
+      Tbl_Table_t *dupTable = DuplicateTableAndVars(node,
+						    Ntk_NodeReadName(node));
+      Tbl_TableWriteBlifMvToFile(dupTable, 0, fp);
+      Tbl_TableFree(dupTable);
+    } else if (Ntk_NodeTestIsLatch(node)) {
+      Ntk_Node_t *data = Ntk_LatchReadDataInput(node);
+      Ntk_Node_t *reset = Ntk_LatchReadInitialInput(node);
+      Tbl_Table_t *dupTable = DuplicateTableAndVars(reset,
+						    Ntk_NodeReadName(node));
+      (void) fprintf(fp, ".latch %s %s\n", Ntk_NodeReadName(data),
+		     Ntk_NodeReadName(node));
+      Tbl_TableWriteBlifMvToFile(dupTable, 1, fp);
+      Tbl_TableFree(dupTable);
+    }
+  }
+
+  (void) fprintf(fp, ".end\n");
+
+} /* Ntk_NetworkWriteBlifMv */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints information about a network.]
+
+  Description [Prints name of network, and calls Ntk_NodePrint on each node of
+  network.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NodePrint]
+
+******************************************************************************/
+void
+Ntk_NetworkPrint(
+  FILE * fp,
+  Ntk_Network_t * network,
+  boolean printIo,
+  boolean printTableStats)
+{
+  Ntk_Node_t *node;
+  lsGen       gen;
+
+  (void) fprintf(fp, "Nodes of network %s:\n", Ntk_NetworkReadName(network));
+
+  Ntk_NetworkForEachNode(network, gen, node) {
+    Ntk_NodePrint(fp, node, printIo, printTableStats);
+    /*
+     * It's nice to have a line separating nodes when we print the fanins and
+     * fanouts or table stats.
+     */
+    if (printIo || printTableStats) {
+      (void) fprintf(fp, "\n");
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints statistics about a network.]
+
+  Description [Prints the following information about a network: name, number
+  of combinational nodes, number of primary inputs, number of primary outputs,
+  number of latches.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Ntk_NetworkPrintStats(
+  FILE * fp,
+  Ntk_Network_t * network)
+{
+  lsGen          gen;
+  Ntk_Node_t     *node;
+  int            numConstants     = 0;
+  int            numCombinational = 0;
+  int            numEdges         = 0;
+  mdd_manager  *mddMgr;
+
+  /*
+   * Count the number of constants and the number of combinational nodes.
+   */
+  Ntk_NetworkForEachNode(network, gen, node) {
+    numEdges += Ntk_NodeReadNumFanouts(node);
+    if (Ntk_NodeTestIsConstant(node)) {
+      numConstants++;
+    }
+    if (Ntk_NodeTestIsCombinational(node)) {
+      numCombinational++;
+    }
+  }
+
+  mddMgr = Ntk_NetworkReadMddManager(network);
+
+  if (mddMgr == NIL(mdd_manager)){
+     (void) fprintf(fp, "%s  combinational=%d  pi=%d  po=%d  latches=%d  pseudo=%d  const=%d  edges=%d\n",
+		 Ntk_NetworkReadName(network),
+		 numCombinational,
+		 Ntk_NetworkReadNumPrimaryInputs(network),
+		 Ntk_NetworkReadNumPrimaryOutputs(network),
+		 Ntk_NetworkReadNumLatches(network),
+		 Ntk_NetworkReadNumPseudoInputs(network),
+		 numConstants,
+		 numEdges
+		 );
+  }else{
+     array_t *bddIdArray;
+     lsGen gen;
+     Ntk_Node_t *latch;
+     int n_boolean_latches;
+     array_t *mddIdArray = array_alloc(int, 0);
+
+     Ntk_NetworkForEachLatch(network, gen, latch){
+       array_insert_last(int, mddIdArray, Ntk_NodeReadMddId(latch));
+     }
+
+     bddIdArray = mdd_id_array_to_bdd_id_array(mddMgr, mddIdArray);
+     n_boolean_latches = array_n(bddIdArray);
+     array_free(mddIdArray);
+     array_free(bddIdArray);
+
+     (void) fprintf(fp, "%s  combinational=%d  pi=%d  po=%d  latches=%d (boolean_latches=%d)  pseudo=%d  const=%d  edges=%d\n",
+		 Ntk_NetworkReadName(network),
+		 numCombinational,
+		 Ntk_NetworkReadNumPrimaryInputs(network),
+		 Ntk_NetworkReadNumPrimaryOutputs(network),
+		 Ntk_NetworkReadNumLatches(network),
+		 n_boolean_latches,
+		 Ntk_NetworkReadNumPseudoInputs(network),
+		 numConstants,
+		 numEdges
+		 );
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Duplicates a network.]
+
+  Description [Duplicates a network.  The network name and all node names are
+  preserved.  The new network does not have an MDD manager.  The nodes of the
+  new network have unassigned MDD ids.  The tables (Tbl_Table_t) of the new
+  nodes are "soft duplicates" of the original tables in oldNetwork; they
+  should not be modified.  The application information (ApplInfo) of the new
+  network is empty.  The formalNameToActualName table of the new network is
+  empty.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkFree Ntk_NetworkAppendNetwork]
+
+******************************************************************************/
+Ntk_Network_t *
+Ntk_NetworkDuplicate(
+  Ntk_Network_t * oldNetwork)
+{
+  int            i;
+  lsGen          gen;
+  Ntk_Node_t    *oldNode;
+  Ntk_Node_t    *oldFaninNode;
+  Ntk_Node_t    *oldOriginNode;
+  Ntk_Node_t    *newOriginNode;
+  array_t       *faninNameArray;
+  Ntk_Network_t *newNetwork = Ntk_NetworkAlloc(Ntk_NetworkReadName(oldNetwork));
+
+
+  /*
+   * For each node in oldNetwork, create a node in newNetwork.
+   */
+  Ntk_NetworkForEachNode(oldNetwork, gen, oldNode) {
+    (void) Ntk_NodeCreateInNetwork(newNetwork, Ntk_NodeReadName(oldNode),
+				   Ntk_NodeReadVariable(oldNode));
+  }
+
+  /*
+   * For each node in oldNetwork, declare the corresponding node in newNetwork
+   * using the type of the oldNode.
+   */
+  Ntk_NetworkForEachNode(oldNetwork, gen, oldNode) {
+    char       *nodeName = Ntk_NodeReadName(oldNode);
+    Ntk_Node_t *newNode  = Ntk_NetworkFindNodeByActualName(newNetwork, nodeName);
+    assert(newNode != NIL(Ntk_Node_t));
+
+    /*
+     * Handle items that are independent of node type.
+     */
+    if (Ntk_NodeTestIsPrimaryOutput(oldNode)) {
+      Ntk_NodeDeclareAsPrimaryOutput(newNode);
+    }
+
+    switch (oldNode->type) {
+      case NtkPrimaryInput_c:
+	Ntk_NodeDeclareAsPrimaryInput(newNode);
+	break;
+      case NtkPseudoInput_c:
+	Ntk_NodeDeclareAsPseudoInput(newNode,
+				     Tbl_TableSoftDup(Ntk_NodeReadTable(oldNode)),
+				     Ntk_NodeReadOutputIndex(oldNode));
+	break;
+      case NtkLatch_c:
+	Ntk_NodeDeclareAsLatch(newNode,
+			       Ntk_NodeReadName(Ntk_LatchReadDataInput(oldNode)),
+			       Ntk_NodeReadName(Ntk_LatchReadInitialInput(oldNode)));
+	break;
+      case NtkCombinational_c:
+	/*
+	 * Create the array of names of the fanins of oldNode.
+	 */
+	faninNameArray = array_alloc(char *, Ntk_NodeReadNumFanins(oldNode));
+	Ntk_NodeForEachFanin(oldNode, i, oldFaninNode) {
+	  char *faninName = Ntk_NodeReadName(oldFaninNode);
+	  array_insert(char *, faninNameArray, i, faninName);
+	}
+
+	Ntk_NodeDeclareAsCombinational(newNode,
+				       Tbl_TableSoftDup(Ntk_NodeReadTable(oldNode)),
+				       faninNameArray,
+				       Ntk_NodeReadOutputIndex(oldNode));
+	array_free(faninNameArray);
+	break;
+      case NtkShadow_c:
+	oldOriginNode = Ntk_ShadowReadOrigin(oldNode);
+	newOriginNode = Ntk_NetworkFindNodeByActualName(newNetwork,
+							Ntk_NodeReadName(oldOriginNode));
+	Ntk_NodeDeclareAsShadow(newNode, newOriginNode);
+	break;
+      case NtkUnassigned_c:
+	fail("Unexpected unassigned node type");
+	break;
+      default:
+	fail("Unexpected type");
+	break;
+    }
+  }
+
+  return (newNetwork);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Appends network2 to network1.]
+
+  Description [Appends network2 to network1. Network2 is not modified, but
+  network1 is modified.  Name1ToName2 is a hash table mapping char* keys to
+  char* values (the table should use st_strhash and strcmp). The set of keys
+  is an arbitrary subset (including empty set) of the set of names of the
+  inputs (primary and pseudo) of network2.  The value of each key is the name
+  of an arbitrary node in network1.<p>
+
+  The inputs of network2 can be divided into 3 types: I - those appearing in
+  name2ToName1 as keys, II - those not appearing in name2ToName1, but which
+  have nodes with the same names in network1, and III - all other inputs
+  (i.e. those neither appearing in name2ToName1, nor having nodes of the same
+  names in network1).  An input of type II could be equivalently specified as a
+  type I input, where the key and value are the same.  If there are no type I
+  inputs, an empty symbol table should be provided.<p>
+
+  A node of network2 is appended to network1 if it is a type III input, or it
+  is not an input.  All appended nodes have the string $NTK2 added to the end
+  of their names.  Inputs of type I or II are not appended to network1.  When
+  a node of network2 is appended to network1, if there exists a fanin of the
+  node that is a type I or II input, then that fanin is modified to refer to
+  the node in network1 corresponding to the type I or II.  The MDD ids of the
+  appended nodes are unassigned.  The tables of the appended nodes are "soft
+  duplicates" of the original tables in network2; they should not be
+  modified.<p>
+
+  Note that it is impossible for the set of fanins of a node (originally) in
+  network1 to be modified.  The only changes that occur to the original nodes
+  of network1 are that the fanout sets will increase for those nodes
+  corresponding to type I or II inputs of network2.<p>
+
+  The application information of network1 is not modified; the information
+  should be invalidated by the caller as necessary.  The MDD manager of
+  network1 is not modified in any way.  The formalNameToActualName table of
+  network1 is not updated to reflect the addition of the nodes from network2.
+  Currently, it is assumed that type I and II inputs do not have shadow
+  nodes.
+
+  !!! Chao Says: I have changed all the FindNodeByActualName with
+		 FindNodeByName, since the later one subsume the former.
+      replace  Ntk_NetworkFindNodeByActualName(network1, name1);
+      with     Ntk_NetworkFindNodeByName(network1, name1);
+  ]
+
+  SideEffects [Network1 is modified.]
+
+  SeeAlso     [Ntk_NetworkDuplicate Ntk_NetworkFreeApplInfo]
+
+******************************************************************************/
+void
+Ntk_NetworkAppendNetwork(
+  Ntk_Network_t * network1,
+  Ntk_Network_t * network2,
+  st_table *name2ToName1)
+{
+  st_generator *stGen;
+  lsGen         gen;
+  Ntk_Node_t   *node1;
+  Ntk_Node_t   *node2;
+  char         *name1;
+  char         *name2;
+  st_table     *localName2ToName1 = st_init_table(strcmp, st_strhash);
+
+
+  /*
+   * For each node in network2, create a node in network1 as necessary. The
+   * undef field of node2 is set to TRUE if a new node is created in network1
+   * for it; else, it is set to FALSE. localName2ToName1 is a superset of
+   * name2ToName1; in addition to the contents of name2ToName1, it contains
+   * the new names (those appended with $NTK2) for those nodes being appended
+   * to network2, and type II inputs.
+   */
+  Ntk_NetworkForEachNode(network2, gen, node2) {
+    name1 = NIL(char);
+    name2 = Ntk_NodeReadName(node2);
+    st_lookup(name2ToName1, name2, &name1);
+    if (name1 != NIL(char)) {
+      /*
+       * Name2 is in name2ToName1 table (type I input).  Hence, we will be
+       * using the node in network1 corresponding to name1.  Assert that node2
+       * is in fact an input, that name1 refers to an input node in network1, and
+       * that node1 and node2 have the same variable domains.
+       */
+      Ntk_NodeSetUndef(node2, (void *) FALSE);
+      st_insert(localName2ToName1, name2, util_strsav(name1));
+
+      assert(Ntk_NodeTestIsInput(node2));
+      node1 = Ntk_NetworkFindNodeByName(network1, name1);
+      assert(node1 != NIL(Ntk_Node_t));
+      assert(Var_VariablesTestHaveSameDomain(Ntk_NodeReadVariable(node1),
+					     Ntk_NodeReadVariable(node2)));
+    }
+    else {
+      /*
+       * Name2 is *not* in name2ToName1 table.  There are 2 possibilities: 1)
+       * a node with name2 already exists in network1, and node2 is an input
+       * (type II input); in this case, a) add map of name2 to name2 in the
+       * localName2ToName1, b) assert that node1 is in fact an input, and c)
+       * don't create a new node in network1; 2) a node with name2 doesn't
+       * exist in network1, or node2 is not an input (type III inputs and
+       * non-inputs); in this case, we unconditionally create a new node in
+       * network1 using name2$NTK2.
+       */
+      node1 = Ntk_NetworkFindNodeByName(network1, name2);
+
+      if ((node1 != NIL(Ntk_Node_t)) && Ntk_NodeTestIsInput(node2)) {
+	Ntk_NodeSetUndef(node2, (void *) FALSE);
+	st_insert(localName2ToName1, name2, util_strsav(name2));
+      }
+      else {
+	char *newName = util_strcat3(name2, "$NTK2", "");
+	Ntk_NodeSetUndef(node2, (void *) TRUE);
+	st_insert(localName2ToName1, name2, newName);
+	(void) Ntk_NodeCreateInNetwork(network1, newName,
+				       Ntk_NodeReadVariable(node2));
+      }
+    }
+  }
+
+  /*
+   * For each node in network2 for which a new node was created in network1,
+   * declare the corresponding node in network1 using the type of the node2.
+   * (NOTE: this section shares a lot with Ntk_NetworkDuplicate, but is
+   * sufficiently different that we don't share any code.)
+   */
+  Ntk_NetworkForEachNode(network2, gen, node2) {
+    if (Ntk_NodeReadUndef(node2) == NIL(void)) {
+      /*
+       * node2 is superseded by a node in network1.
+       */
+      continue;
+    }
+
+    name2 = NodeReadNameFromTable(node2, localName2ToName1);
+    node1 = Ntk_NetworkFindNodeByName(network1, name2);
+    assert(node1 != NIL(Ntk_Node_t));
+
+    /*
+     * Handle items that are independent of node type.
+     */
+    if (Ntk_NodeTestIsPrimaryOutput(node2)) {
+      Ntk_NodeDeclareAsPrimaryOutput(node1);
+    }
+
+    switch (node2->type) {
+      case NtkPrimaryInput_c:
+	Ntk_NodeDeclareAsPrimaryInput(node1);
+	break;
+
+      case NtkPseudoInput_c:
+	Ntk_NodeDeclareAsPseudoInput(node1,
+				     Tbl_TableSoftDup(Ntk_NodeReadTable(node2)),
+				     Ntk_NodeReadOutputIndex(node2));
+	break;
+
+      case NtkLatch_c:
+      {
+	char *dataName = NodeReadNameFromTable(Ntk_LatchReadDataInput(node2),
+					       localName2ToName1);
+	char *initName = NodeReadNameFromTable(Ntk_LatchReadInitialInput(node2),
+					       localName2ToName1);
+
+	Ntk_NodeDeclareAsLatch(node1, dataName, initName);
+	break;
+      }
+
+      case NtkCombinational_c:
+      {
+	int         i;
+	Ntk_Node_t *faninNode2;
+	array_t    *faninNameArray;
+
+	/*
+	 * Create the array of names of the fanins of node2.
+	 */
+	faninNameArray = array_alloc(char *, Ntk_NodeReadNumFanins(node2));
+	Ntk_NodeForEachFanin(node2, i, faninNode2) {
+	  char *faninName = NodeReadNameFromTable(faninNode2, localName2ToName1);
+	  array_insert(char *, faninNameArray, i, faninName);
+	}
+
+	Ntk_NodeDeclareAsCombinational(node1,
+				       Tbl_TableSoftDup(Ntk_NodeReadTable(node2)),
+				       faninNameArray,
+				       Ntk_NodeReadOutputIndex(node2));
+	array_free(faninNameArray);
+	break;
+      }
+
+      case NtkShadow_c:
+      {
+	char       *originName;
+	Ntk_Node_t *originNode2;
+	Ntk_Node_t *originNode1;
+
+	originNode2 = Ntk_ShadowReadOrigin(node2);
+	/*
+	 * Currently, we don't allow a shadow node whose origin in a type I or
+	 * II input.  This is because, what if the corresponding node in
+	 * network1 (of the type I or II input), also has a shadow node?  Then
+	 * we would try to add a shadow node to a node already having a shadow;
+	 * this is illegal.
+	 */
+	assert((boolean) (long) Ntk_NodeReadUndef(node2));
+	originName = NodeReadNameFromTable(originNode2, localName2ToName1);
+	originNode1 = Ntk_NetworkFindNodeByName(network1, originName);
+
+	Ntk_NodeDeclareAsShadow(node1, originNode1);
+	break;
+      }
+
+      case NtkUnassigned_c:
+	fail("Unexpected unassigned node type");
+	break;
+      default:
+	fail("Unexpected type");
+	break;
+    }
+  }
+
+  /*
+   * Free all the values strings in the localName2ToName1, before freeing
+   * the table itself.  The keys are not freed.
+   */
+  st_foreach_item(localName2ToName1, stGen, &name2, &name1) {
+    FREE(name1);
+  }
+  st_free_table(localName2ToName1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [print a description of the topology of the network in dot format]
+
+  Description [The format used for the description is <b>dot</b>, a tool for
+  graph visualization developed at AT&T. It can be obtained from <a
+  href="http://www.research.att.com/orgs/ssr/book/reuse">
+  http://www.research.att.com/orgs/ssr/book/reuse</a>. The function
+  receives as a parameter a file pointer in case the print wants to be
+  redirected. This function is used by the command routine
+  CommandPrintNetworkDot.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+Ntk_NetworkPrintDot(
+  FILE *fp,
+  Ntk_Network_t *network)
+{
+  lsGen       gen;
+  int i;
+  Ntk_Node_t *nodePtr;
+  Ntk_Node_t *fanoutPtr;
+  time_t      now           = time(0);
+  struct tm  *nowStructPtr  = localtime(& now);
+  char       *nowTxt        = asctime(nowStructPtr);
+  char       *networkName   = Ntk_NetworkReadName(network);
+
+  /*
+   * Write out the header for the output file.
+   */
+
+  (void) fprintf(fp, "# %s\n", Vm_VisReadVersion());
+  (void) fprintf(fp, "# network name: %s\n", networkName);
+  (void) fprintf(fp, "# generated: %s", nowTxt);
+  (void) fprintf(fp, "#\n");
+
+  (void) fprintf(fp, "# Network with %d nodes\n",
+		 Ntk_NetworkReadNumNodes(network));
+
+  (void) fprintf(fp, "digraph \"%s\" {\n  rotate=90;\n", networkName);
+  (void) fprintf(fp, "  margin=0.5;\n  label=\"%s\";\n", networkName);
+  (void) fprintf(fp, "  size=\"10,7.5\";\n  ratio=\"fill\";\n");
+
+  /* Force the inputs and outputs to be printed at the same level in the graph */
+  (void) fprintf(fp, "  { rank=same; ");
+  Ntk_NetworkForEachCombInput(network,gen, nodePtr) {
+    (void) fprintf(fp, "\"%s\"; ", Ntk_NodeReadName(nodePtr));
+  }
+  (void) fprintf(fp, "}\n");
+  (void) fprintf(fp, "  { rank=same; ");
+  Ntk_NetworkForEachCombOutput(network,gen, nodePtr) {
+    (void) fprintf(fp, "\"%s\"; ", Ntk_NodeReadName(nodePtr));
+  }
+  (void) fprintf(fp, "}\n");
+
+  /* Print all the edges */
+  Ntk_NetworkForEachNode(network, gen, nodePtr) {
+
+    if (Ntk_NodeReadNumFanouts(nodePtr) == 0 &&
+	Ntk_NodeReadNumFanins(nodePtr) == 0) {
+      /* Print the dot description for a node */
+      (void) fprintf(fp, "  \"%s\";\n", Ntk_NodeReadName(nodePtr));
+    } /* End of if */
+
+    /* Print the edges comming out of that node */
+    Ntk_NodeForEachFanout(nodePtr, i, fanoutPtr) {
+      (void) fprintf(fp, "  \"%s\" -> \"%s\";\n", Ntk_NodeReadName(nodePtr),
+		     Ntk_NodeReadName(fanoutPtr));
+    }
+  }
+
+  (void) fprintf(fp, "}\n");
+
+  return 1;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Returns node name from table.]
+
+  Description [Given a node, uses the name of the node as key to lookup the
+  corresponding (new) name for the node.  If the node does not exist as a key
+  in the table, then fails.  The returned string should not be freed.]
+
+  SideEffects []
+
+******************************************************************************/
+static char *
+NodeReadNameFromTable(
+  Ntk_Node_t *node,
+  st_table *name2ToName1)
+{
+  char    *name1  = NIL(char);
+  char    *name2  = Ntk_NodeReadName(node);
+  boolean  status UNUSED = st_lookup(name2ToName1, name2, &name1);
+
+  assert(status);
+  return name1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Duplicate a table and corresponding variables.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso []
+
+******************************************************************************/
+static Tbl_Table_t *
+DuplicateTableAndVars(
+  Ntk_Node_t *node,
+  char *name
+  )
+{
+  Var_Variable_t *var, *newVar;
+  Tbl_Table_t *dupTable, *tbl;
+  int col;
+  Tbl_Table_t *table = Ntk_NodeReadTable(node);
+  array_t *split = Tbl_TableSplit(table);
+  int outIndex = Ntk_NodeReadOutputIndex(node);
+
+  arrayForEachItem(Tbl_Table_t *, split, col, tbl) {
+    if (col == outIndex) {
+      dupTable = tbl;
+    } else {
+      Tbl_TableFree(tbl);
+    }
+  }
+  array_free(split);
+
+  Tbl_TableForEachInputVar(dupTable, col, var) {
+    Ntk_Node_t *fanin = Ntk_NodeReadFaninNode(node, col);
+    char *newName = Ntk_NodeReadName(fanin);
+    newVar = Var_VariableDup(var, NIL(Hrc_Node_t));
+    Var_VariableChangeName(newVar, newName);
+    Tbl_TableSetVar(dupTable, col, newVar, 0);
+  }
+
+  var = array_fetch(Var_Variable_t *,Tbl_TableReadOutputVars(dupTable), 0);
+  newVar = Var_VariableDup(var, NIL(Hrc_Node_t));
+  Var_VariableChangeName(newVar, name);
+  Tbl_TableSetVar(dupTable, 0, newVar, 1);
+
+  return dupTable;
+
+} /* DuplicateTableAndVars */
Index: vis_dev/vis-2.3/src/ntk/ntkSweep.c
===================================================================
--- vis_dev/vis-2.3/src/ntk/ntkSweep.c	(revision 14)
+++ vis_dev/vis-2.3/src/ntk/ntkSweep.c	(revision 14)
@@ -0,0 +1,545 @@
+/**CFile***********************************************************************
+
+  FileName    [ntkSweep.c]
+
+  PackageName [Ntk]
+
+  Synopsis    [Utilities for Cleaning the Ntk_Network_t]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [Gitanjali Swamy]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ntkInt.h"
+
+static char rcsid[] UNUSED = "$Id: ntkSweep.c,v 1.18 2010/04/09 23:44:05 fabio Exp $";
+
+/*comment */
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void NetworkCollapseConstantNode(Ntk_Network_t *network, Ntk_Node_t *node);
+static void NetworkCollapseIdentityNode(Ntk_Network_t *network, Ntk_Node_t *node);
+static void NetworkCollapseInverterNode(Ntk_Network_t *network, Ntk_Node_t *node);
+static int NodeRemoveFanout(Ntk_Node_t *node, Ntk_Node_t *delFanoutNode);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis           [Sweep given network]
+
+  Description        [This function performs a sweep on the given
+  Ntk_Network_t. It propagates all the deterministic constant nodes, and
+  removes all buffer nodes. The function returns TRUE if it succeeds and
+  FALSE it it does not. Note that constant nodes that have fanins may
+  not be propogated right now.]
+
+  SideEffects        []
+
+******************************************************************************/
+void
+Ntk_NetworkSweep(Ntk_Network_t *network, int verbosity)
+{
+  lsList nodeList;
+  Ntk_Node_t *node;
+  lsGen gen;
+  array_t *rootArray = array_alloc(Ntk_Node_t *,
+				   Ntk_NetworkReadNumCombOutputs(network));
+  st_table *leafNodesTable = st_init_table(st_ptrcmp, st_ptrhash);
+  int count = 0;
+
+  /* Get a topologically sorted list of all nodes so that one pass
+     through the network is enough to remove all constant nodes. */
+  Ntk_NetworkForEachNode(network, gen, node) {
+    if (Ntk_NodeTestIsPrimaryOutput(node)
+	|| Ntk_NodeTestIsLatchDataInput(node)
+	|| Ntk_NodeReadNumFanouts(node) == 0)
+      array_insert_last(Ntk_Node_t *, rootArray, node);
+    if (Ntk_NodeTestIsInput(node) || Ntk_NodeReadNumFanins(node) == 0)
+      st_insert(leafNodesTable, node, NIL(char));
+  }
+  nodeList = Ntk_NetworkComputeTopologicalOrder(network, rootArray,
+						leafNodesTable);
+  /* Check that all nodes are included. */
+  assert(lsLength(nodeList) == lsLength(network->nodes));
+  array_free(rootArray);
+  st_free_table(leafNodesTable);
+
+  /* Check for constants, identities and inverters. */
+  lsForEachItem(nodeList, gen, node) {
+    char *name = Ntk_NodeReadName(node);
+    /* Try to remove only nodes created by vl2mv. */
+    if (name[0] != '_' && strstr(name, "._") == NIL(char) &&
+	strstr(name, "$") == NIL(char)) continue;
+    if (Ntk_NodeTestIsConstant(node) == TRUE) {
+      if (Ntk_NodeReadNumFanins(node) == 0) {
+	NetworkCollapseConstantNode(network, node);
+	if (Ntk_NodeReadNumFanouts(node) == 0) {
+	  if (Ntk_NodeRemoveFromNetwork(network,node,0,0,verbosity) == TRUE) {
+	    lsDelBefore(gen, &node);
+	    Ntk_NodeFree(node);
+	    count++;
+	  }
+	}
+      }
+    } else if (Ntk_NodeTestIsCombinational(node)) {
+      if (!Ntk_NodeTestIsCombOutput(node)) {
+	Tbl_Table_t *table = Ntk_NodeReadTable(node);
+	if (Tbl_TableIsIdentity(table)) {
+	  NetworkCollapseIdentityNode(network, node);
+	  if (Ntk_NodeRemoveFromNetwork(network,node,1,0,verbosity) == TRUE) {
+	    lsDelBefore(gen, &node);
+	    Ntk_NodeFree(node);
+	    count++;
+	  }
+	} else if (Tbl_TableIsInverter(table)) {
+	  NetworkCollapseInverterNode(network, node);
+	  if (Ntk_NodeReadNumFanins(node) == 0) {
+	    if (Ntk_NodeRemoveFromNetwork(network,node,0,0,verbosity) == TRUE) {
+	      lsDelBefore(gen, &node);
+	      Ntk_NodeFree(node);
+	      count++;
+	    }
+	  }
+	}
+      }
+    }
+  }
+
+  if (verbosity > 0) {
+    fprintf(vis_stderr,"Removed %d node%s\n", count, count == 1 ? "" : "s");
+  }
+
+  (void) lsDestroy(network->nodes,(void (*) (lsGeneric)) NULL);
+  network->nodes = nodeList;
+
+  if (verbosity > 0) {
+    Ntk_NetworkWriteBlifMv(vis_stdout, network, TRUE);
+  }
+
+} /* Ntk_NetworkSweep */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Remove node from network]
+
+  Description        [If force=0, the node to be removed should not be a
+  fanin/fanout/latch. If force=1, the node is removed from the network no
+  matter what. ]
+
+  SideEffects        [Appropriate fields in the network are updated.]
+
+  SeeAlso            []
+
+******************************************************************************/
+boolean
+Ntk_NodeRemoveFromNetwork(Ntk_Network_t *network, Ntk_Node_t *node,
+			  int force, boolean removeFromNodeList, int verbosity)
+{
+  if (!force) {
+    assert(Ntk_NodeReadNumFanins(node) == 0);
+    assert(Ntk_NodeReadNumFanouts(node) == 0);
+
+    if (Ntk_NodeTestIsPrimaryOutput(node)==TRUE) {
+      return FALSE;
+    }
+    if (Ntk_NodeTestIsLatch(node)==TRUE) {
+      return FALSE;
+    }
+    if (Ntk_NodeTestIsPrimaryInput(node)==TRUE) {
+      return FALSE;
+    }
+  }
+
+  if (verbosity) {
+    fprintf(vis_stdout, "** ntk info: Node Removed %s\n", node->name);
+  }
+
+  node->network = NIL(Ntk_Network_t);
+  if (Ntk_NodeTestIsCombOutput(node)) {
+    NtkNodeDeleteFromList(network->combOutputs, node);
+    st_delete(network->combOutputsTable, &node, NULL);
+  }
+  if (Ntk_NodeTestIsCombInput(node)) {
+    NtkNodeDeleteFromList(network->combInputs, node);
+  }
+
+  st_delete(network->actualNameToNode, &(node->name), NIL(char *));
+  /* BALA: I don't understand why the following line was not present
+     earlier. */
+  /* When this function is called by Ntk_NetworkSweep, it is not
+     necessary to remove the node from the network's node list because
+     the node list is re-generated regardless.  In addition, it may
+     get very expensive.
+   */
+  if (removeFromNodeList)
+    NtkNodeDeleteFromList(network->nodes, node);
+
+  switch(node->type) {
+    case NtkShadow_c:
+      break;
+    case NtkPseudoInput_c:
+      NtkNodeDeleteFromList(network->inputs, node);
+      NtkNodeDeleteFromList(network->pseudoInputs, node);
+      break;
+    case NtkCombinational_c:
+      break;
+    case NtkUnassigned_c:
+      break;
+    case NtkLatch_c:
+      NtkNodeDeleteFromList(network->latches, node);
+      break;
+  case NtkPrimaryInput_c:
+      NtkNodeDeleteFromList(network->primaryInputs, node);
+      break;
+      /*
+    default:
+    fail("Type cannot be deleted");*/
+  }
+
+  /* for PO */
+  if (Ntk_NodeTestIsPrimaryOutput(node)==TRUE)
+      NtkNodeDeleteFromList(network->primaryOutputs, node);
+
+  return TRUE;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis           [Delete a node from given list]
+
+  Description        [Given a node and a list of nodes, this function deletes
+  the node from the list.]
+
+  SideEffects        []
+
+  SeeAlso            []
+
+******************************************************************************/
+boolean
+NtkNodeDeleteFromList(
+  lsList nodeList,
+  Ntk_Node_t *node)
+{
+
+  lsGen gen;
+  lsGeneric data;
+  Ntk_Node_t *listnode;
+  Ntk_Node_t *delNode;
+  boolean check;
+  int i;
+
+  check = FALSE;
+  i = 0;
+  lsForEachItem(nodeList, gen, listnode) {
+    if (node == listnode) {
+      if (i > 0)
+	lsDelBefore(gen, &data);
+      else
+	lsDelBegin(nodeList, &data);
+      check = TRUE;
+    }
+    i++;
+  }
+  delNode = (Ntk_Node_t*)data;
+
+  assert(delNode == node);
+  assert(check);
+  return check;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis [Collapse given input (constant) into its fanouts.]
+
+  Description [This routine removes a given constant node.  It also
+  readjusts network parameters; i.e., removes the constant node from
+  the network. Finally, it also patches the fanouts of node. If a node
+  fanout is a latch, it is not possible to collapse it.  Note that the
+  constant node must have no fanins.]
+
+  SideEffects []
+
+
+******************************************************************************/
+static void
+NetworkCollapseConstantNode(Ntk_Network_t *network, Ntk_Node_t *node)
+{
+  Tbl_Table_t *table, *newtable;
+  Ntk_Node_t *fanout, *fanin;
+  int i,j,index;
+  array_t *newFaninArray;
+  array_t *tmpFanoutArray;
+
+  table = Ntk_NodeReadTable(node);
+
+  tmpFanoutArray = array_dup(Ntk_NodeReadFanouts(node));
+  arrayForEachItem(Ntk_Node_t *, tmpFanoutArray, i, fanout) {
+    if (fanout->type == NtkCombinational_c) {
+      index = Ntk_NodeReadFaninIndex(fanout,node);
+      while (index != NTK_UNDEFINED_FANIN_INDEX) {
+	Tbl_Table_t *fantable = Ntk_NodeReadTable(fanout);
+
+	NodeRemoveFanout(node,fanout);
+	newtable = Tbl_TableCollapse(fantable,table,index);
+	Tbl_TableFree(fantable);
+	Ntk_NodeSetTable(fanout, newtable);
+
+	if (Tbl_TableTestIsConstant(fanout->table, 0)) {
+	  fanout->constant = TRUE;
+	}
+
+	newFaninArray = array_alloc(Ntk_Node_t*, 0);
+	Ntk_NodeForEachFanin(fanout, j, fanin) {
+	  if (j != index) {
+	    array_insert_last(Ntk_Node_t*, newFaninArray, fanin);
+	  }
+	}
+	array_free(fanout->fanins);
+	fanout->fanins = newFaninArray;
+
+	index = Ntk_NodeReadFaninIndex(fanout, node);
+      }
+    }
+  }
+  array_free(tmpFanoutArray);
+
+  Ntk_NodeForEachFanin(node, i, fanin) {
+    NodeRemoveFanout(fanin, node);
+  }
+
+  array_free(node->fanins);
+  node->fanins = array_alloc(Ntk_Node_t*, 0);
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Collapse given identity node into its fanouts.]
+
+  Description [This routine removes a given identity node.  It also
+  readjusts network parameters; i.e., removes the identity node from
+  the network. Finally, it also patches the fanins and fanouts of
+  node.]
+
+  SideEffects [The network is modified.]
+
+  SeeAlso [NetworkCollapseConstantNode NetworkCollapseInverterNode]
+
+******************************************************************************/
+static void
+NetworkCollapseIdentityNode(Ntk_Network_t *network, Ntk_Node_t *node)
+{
+  Ntk_Node_t *fanout, *fanin;
+  Var_Variable_t *invar, *outvar;
+  int i;
+
+  fanin = Ntk_NodeReadFaninNode(node, 0);
+  invar = Ntk_NodeReadVariable(fanin);
+  outvar = Ntk_NodeReadVariable(node);
+  NodeRemoveFanout(fanin, node);
+  /* array_remove_last(Ntk_NodeReadFanins(node)); */
+
+  Ntk_NodeForEachFanout(node, i, fanout) {
+    int index = Ntk_NodeReadFaninIndex(fanout,node);
+    /* Since a node may be connected to another node multiple times,
+     * we iterate until node is not found any more.
+     */
+    while (index != NTK_UNDEFINED_FANIN_INDEX) {
+      if (fanout->type == NtkCombinational_c) {
+	Tbl_Table_t *fantable = Ntk_NodeReadTable(fanout);
+	Tbl_TableSubstituteVar(fantable, outvar, invar);
+      }
+      /* NodeRemoveFanout(node,fanout); */
+
+      /* Replace node with its input node in the fanins of fanout. */
+      array_insert(Ntk_Node_t *, Ntk_NodeReadFanins(fanout), index, fanin);
+      array_insert_last(Ntk_Node_t*, Ntk_NodeReadFanouts(fanin), fanout);
+
+      index = Ntk_NodeReadFaninIndex(fanout, node);
+    }
+  }
+
+} /* NetworkCollapseIdentityNode */
+
+
+/**Function********************************************************************
+
+  Synopsis [Collapse given inverter node into its fanouts.]
+
+  Description [This routine collapses a given inverter node into its
+  fanouts.  It also readjusts network parameters; i.e., removes the
+  inverter node from the network. Finally, it also patches the fanins
+  and fanouts of node.]
+
+  SideEffects [The network is modified.]
+
+  SeeAlso [NetworkCollapseConstantNode NetworkCollapseIdentityNode]
+
+******************************************************************************/
+static void
+NetworkCollapseInverterNode(Ntk_Network_t *network, Ntk_Node_t *node)
+{
+  Ntk_Node_t *fanout, *fanin;
+  Var_Variable_t *invar, *outvar;
+  int i;
+  boolean failure = FALSE;
+  array_t *dupFanoutArray;
+
+  assert(Ntk_NodeReadNumFanins(node) == 1);
+  fanin = Ntk_NodeReadFaninNode(node, 0);
+  invar = Ntk_NodeReadVariable(fanin);
+  outvar = Ntk_NodeReadVariable(node);
+
+  dupFanoutArray = array_dup(Ntk_NodeReadFanouts(node));
+  arrayForEachItem(Ntk_Node_t *, dupFanoutArray, i, fanout) {
+    if (fanout->type == NtkCombinational_c) {
+      int index = Ntk_NodeReadFaninIndex(fanout,node);
+      /* Since a node may be connected to another node multiple times,
+       * we iterate until node is not found any more.
+       */
+      while (index != NTK_UNDEFINED_FANIN_INDEX) {
+	Tbl_Table_t *fantable = Ntk_NodeReadTable(fanout);
+	Tbl_Table_t *newTable =
+	  Tbl_TableInvertBinaryInputColumn(fantable, index);
+	if (newTable != NIL(Tbl_Table_t)) {
+	  Tbl_TableFree(fantable);
+	  Tbl_TableSubstituteVar(newTable, outvar, invar);
+	  Ntk_NodeSetTable(fanout, newTable);
+	  NodeRemoveFanout(node, fanout);
+
+	  /* Replace node with its input node in the fanins of fanout. */
+	  array_insert(Ntk_Node_t *, Ntk_NodeReadFanins(fanout), index, fanin);
+	  array_insert_last(Ntk_Node_t*, Ntk_NodeReadFanouts(fanin), fanout);
+	} else {
+	  failure = TRUE;
+	  /* Test: */ fprintf(vis_stdout, "achtung!\n");
+	}
+	index = Ntk_NodeReadFaninIndex(fanout, node);
+      }
+    } else {
+      failure = TRUE;
+    }
+  }
+  array_free(dupFanoutArray);
+
+  if (!failure) {
+    NodeRemoveFanout(fanin, node);
+    array_remove_last(Ntk_NodeReadFanins(node));
+  }
+
+} /* NetworkCollapseInverterNode */
+
+
+/**Function********************************************************************
+
+  Synopsis    [remove given delFanoutNode from the fanouts of given node]
+
+  Description [Given a Ntk_Node_t* node and one of its fanouts Ntk_Node_t*
+  delFanoutNode, this routine will remove the fanout from the fanouts of
+  the given node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+NodeRemoveFanout(
+  Ntk_Node_t *node,
+  Ntk_Node_t *delFanoutNode)
+{
+  array_t *newFanoutArray;
+  Ntk_Node_t *fanout, *fanin;
+  int j;
+
+  if (node == NIL(Ntk_Node_t))
+    return(0);
+
+  newFanoutArray = array_alloc(Ntk_Node_t*, 0);
+  Ntk_NodeForEachFanout(node, j, fanout) {
+    if (fanout != delFanoutNode) {
+      array_insert_last(Ntk_Node_t*, newFanoutArray, fanout);
+    }
+  }
+  array_free(node->fanouts);
+  node->fanouts = newFanoutArray;
+
+  Ntk_NodeForEachFanin(delFanoutNode, j, fanin) {
+    if (fanin == node) {
+      array_insert(Ntk_Node_t*, delFanoutNode->fanins, j, NIL(Ntk_Node_t));
+      /* to break not to delete another fanin if any */
+      j = Ntk_NodeReadNumFanins(delFanoutNode);
+    }
+  }
+
+  return(1);
+}
Index: vis_dev/vis-2.3/src/ntm/ntm.c
===================================================================
--- vis_dev/vis-2.3/src/ntm/ntm.c	(revision 14)
+++ vis_dev/vis-2.3/src/ntm/ntm.c	(revision 14)
@@ -0,0 +1,796 @@
+/**CFile***********************************************************************
+
+  FileName    [ntm.c]
+
+  PackageName [ntm]
+
+  Synopsis    [Routines to build MDDs from a network.]
+
+  Author      [Adnan Aziz and Tom Shiple]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ntmInt.h"
+
+static char rcsid[] UNUSED = "$Id: ntm.c,v 1.11 2009/04/11 01:45:44 fabio Exp $";
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static Mvf_Function_t * NodeBuildMvfRecursively(Ntk_Node_t * node, st_table * leaves, st_table * nodeToMvfTable, mdd_manager *mddMgr, mdd_t *careSet);
+static Mvf_Function_t * NodeBuildInputMvf(Ntk_Node_t * node, mdd_manager *mddMgr);
+#if 0
+static Mvf_Function_t * NodeBuildPseudoInputMvf(Ntk_Node_t * node, mdd_manager * mddMgr);
+#endif
+static Mvf_Function_t * NodeBuildPseudoInputMvfNew(Ntk_Node_t * node, mdd_manager * mddMgr);
+static Mvf_Function_t * NodeBuildConstantMvf(Ntk_Node_t * node, int constantValue, mdd_manager *mddMgr);
+static Mvf_Function_t * NodeBuildInternalMvf(Ntk_Node_t * node, st_table * leaves, st_table * nodeToMvfTable, mdd_manager *mddMgr, mdd_t *careSet);
+static Mvf_Function_t * NodeReadMvf(Ntk_Node_t * node, st_table * nodeToMvfTable);
+static void NodeSetMvf(Ntk_Node_t * node, st_table * nodeToMvfTable, Mvf_Function_t * mvf);
+static int CommandNtmTest(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static void MvfSanityCheck(array_t *roots, array_t *mvfs);
+static void RegionInitializeReferenceCounts(array_t *roots, st_table *leaves);
+static void NodeDecrementRefCount(Ntk_Node_t *node, st_table *nodeToMvfTable);
+static boolean TableTestIsContainedInArray(st_table *table1, array_t *nodeArrary);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the network to MDD package.]
+
+  SideEffects []
+
+  SeeAlso     [Ntm_End]
+
+******************************************************************************/
+void
+Ntm_Init(void)
+{
+  Cmd_CommandAdd("_ntm_test", CommandNtmTest, /* doesn't changes_network */ 0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Ends the network to MDD package.]
+
+  SideEffects []
+
+  SeeAlso     [Ntm_Init]
+
+******************************************************************************/
+void
+Ntm_End(void)
+{
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds multi-valued functions for roots, in terms of leaves.]
+
+  Description [Takes an array of root nodes and a table of leaf nodes, and
+  builds the multi-valued functions (MVFs) for the roots in terms of the
+  leaves. This function returns an array of Mvf_Function_t*, in one-to-one
+  correspondence with the roots array.  It is assumed that every path, from a
+  root backwards to a combinational input, passes through a node in the leaves
+  table, and that there are no combinational cycles within the region defined
+  by the roots and leaves. Also, it is assumed that every node in the leaves
+  table already has an MDD id.<p>
+
+  A leaf that is a primary input, latch, or combinational node, is treated as
+  a "free" input (i.e. can assume any value in its domain). A leaf that is a
+  pseudo input can assume only those values for which it was specified.<p>
+
+  The leaves table maps nodes (Ntk_Node_t*) to integers.  If the value
+  corresponding to a leaf is NTM_UNUSED, then the MVF for the leaf is built
+  as described above.  However, the value can be specified as the index of
+  some value in the domain of the variable of the leaf.  For example, if leaf
+  node x can take values (RED, GREEN, BLUE), then the value 1 refers to GREEN.
+  In this case, the MVF built for x is simply the constant MVF representing
+  GREEN. This feature can be used to evaluate the MVFs of the roots on a
+  minterm, or partial minterm, over the leaves.<p>
+
+  This function also takes the MDD careSet as an input.  If this argument is
+  NULL, then it is ignored.  However, if it is not NULL, then all intermediate
+  and final MDDs constructed are minimized with respect to the careSet.  Thus,
+  the MVFs returned by the function may take an arbitrary value outside of the
+  careSet.  This can be useful to keep the MDDs small.]
+
+  Comment [We create a table mapping nodes to Mvf_Function_t's (for nodes for
+  which Mvf_Function's have already been built); Call NodeBuildMvfRecursively
+  on the roots. Free MVF's at internal nodes ASAP, so no excessive storage.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+Ntm_NetworkBuildMvfs(
+  Ntk_Network_t * network,
+  array_t * roots,
+  st_table * leaves,
+  mdd_t *careSet)
+{
+  int             i;
+  st_generator   *stGen;
+  Mvf_Function_t *mvf;
+  Ntk_Node_t     *node;
+  st_table       *nodeToMvfTable;
+  Mvf_Function_t *tmpMvf;
+  int             numRoots = array_n(roots);
+  array_t        *result   = array_alloc(Mvf_Function_t *, numRoots);
+  mdd_manager    *mddMgr   = Ntk_NetworkReadMddManager(network);
+
+  /*
+   * Before initializing the reference counts, verify that the leaves form a
+   * support set for the roots.
+   */
+  if (!Ntk_NetworkTestLeavesCoverSupportOfRoots(network, roots, leaves)) {
+    (void)fprintf(vis_stderr,"%s",error_string());
+    fflush(vis_stderr);
+    fail("Leaves do not cover support of roots");
+  }
+
+  /*
+   * Each node in the region defined by the roots and leaves is assigned a
+   * reference count equaling the number of fanouts within the region.  As a
+   * special case, the roots are initialized to MAX_INT.
+   */
+  RegionInitializeReferenceCounts(roots, leaves);
+
+  /*
+   * For each root, compute its MVF and store a duplicate copy of it in the
+   * result array. The nodeToMvfTable is used to keep track of intermediate
+   * computations. Intermediate MVFs are freed as soon as possible by using
+   * the reference count mechanism.
+   */
+  nodeToMvfTable = st_init_table(st_ptrcmp, st_ptrhash);
+  for (i = 0; i < numRoots; i++) {
+    Ntk_Node_t     *root   = array_fetch(Ntk_Node_t *, roots, i);
+
+    tmpMvf = NodeBuildMvfRecursively(root, leaves,
+						     nodeToMvfTable, mddMgr,
+						     careSet);
+
+    mvf = Mvf_FunctionDuplicate(tmpMvf);
+    array_insert(Mvf_Function_t *, result, i, mvf);
+  }
+
+  /*
+   * Because of the use of reference counting, the only nodes left in
+   * nodeToMvfTable should be the roots.
+   */
+  assert(TableTestIsContainedInArray(nodeToMvfTable, roots));
+
+  /*
+   * Free the remaining MVFs (corresponding to the roots) from the
+   * nodeToMvfTable.
+   */
+  st_foreach_item(nodeToMvfTable, stGen, &node, &mvf) {
+    Mvf_FunctionFree(mvf);
+  }
+  st_free_table(nodeToMvfTable);
+
+  return result;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds MVF for a node, recursively in terms of fanins.]
+
+  Description [Recursively builds Mvf_Functions_t's. Base cases - input nodes,
+  latch nodes, constant nodes, pseudo inputs, and leaf nodes. Fail if a
+  combinational input is reached that is not in leaves.  In the case that the
+  node is combinational, and in the leaves, we treat it as an input.  When
+  it's a pseudo input, we treat it as taking only values designated in table.]
+
+  SideEffects []
+
+  SeeAlso     [NodeBuildInputMvf,NodeBuildPseudoInputMvf,NodeBuildInternalMvf]
+
+******************************************************************************/
+static Mvf_Function_t *
+NodeBuildMvfRecursively(
+  Ntk_Node_t * node,
+  st_table * leaves,
+  st_table * nodeToMvfTable,
+  mdd_manager *mddMgr,
+  mdd_t *careSet)
+{
+  Mvf_Function_t *mvf = NodeReadMvf(node, nodeToMvfTable);
+
+
+  /* If the MVF for this node has already been computed, then just return it. */
+  if (mvf != NIL(Mvf_Function_t)) {
+    return mvf;
+  }
+
+
+  if (Ntk_NodeTestIsConstant(node)) {
+    /* Doesn't matter if constant is a leaf or not. */
+    mvf = NodeBuildConstantMvf(node, NTM_UNUSED, mddMgr);
+  }
+
+  else {
+    int constValue;
+    if (st_lookup_int(leaves, (char *) node, &constValue)) {
+
+      if (constValue == NTM_UNUSED) {
+
+	/* Node is a leaf. */
+	if ((Ntk_NodeTestIsPrimaryInput(node)) ||
+	    (Ntk_NodeTestIsLatch(node)) ||
+	    (Ntk_NodeTestIsCombinational(node))) {
+	  /* Node can assume any value. */
+	  mvf = NodeBuildInputMvf(node, mddMgr);
+	}
+	else if (Ntk_NodeTestIsPseudoInput(node)) {
+	  /* Node may assume only a subset of possible values. */
+	  mvf = NodeBuildPseudoInputMvfNew(node, mddMgr);
+	}
+	else {
+	  fail("Encountered unknown type in MVF recursion\n");
+	}
+      }
+      else {
+	/* treat the leaf node as being a constant taking the value constValue */
+	mvf = NodeBuildConstantMvf(node, constValue, mddMgr);
+      }
+    }
+    else {
+
+      /* Node is not a leaf.  If it is a combinational input, then fail. */
+      if (Ntk_NodeTestIsCombInput(node)) {
+	fail("Encountered combinational input not in leaves table\n");
+      }
+      else {
+	mvf = NodeBuildInternalMvf(node, leaves, nodeToMvfTable, mddMgr,
+				   careSet);
+      }
+    }
+  }
+
+  /* Minimize mvf wrt careSet, if careSet is not NULL. */
+  if (careSet != NIL(mdd_t)) {
+    Mvf_Function_t *tempMvf = mvf;
+
+    mvf = Mvf_FunctionMinimize(tempMvf, careSet);
+    Mvf_FunctionFree(tempMvf);
+  }
+  NodeSetMvf(node, nodeToMvfTable, mvf);
+  return mvf;
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis  [Builds MVF for a node that is treated as a free input.]
+
+  SideEffects []
+
+******************************************************************************/
+static Mvf_Function_t *
+NodeBuildInputMvf(
+  Ntk_Node_t * node,
+  mdd_manager *mddMgr)
+{
+  int mddId = Ntk_NodeReadMddId(node);
+
+  assert(mddId != NTK_UNASSIGNED_MDD_ID);
+  return Mvf_FunctionCreateFromVariable(mddMgr, mddId);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds MVF for a node that is a pseudo input.]
+
+  Description [Builds MVF for a node that is a pseudo input.  This node has a
+  single output and no inputs. Its table has several row entries.  We build an
+  MVF whose components correspond exactly to possible table outputs.]
+
+  SideEffects []
+
+  Comment [Although pseudo inputs, constants, and internal nodes all have
+  tables, a single procedure cannot be used to build their MVF.  A pseudo
+  input MVF is built in terms of its mddId, whereas a constant or internal is
+  not.  A constant or pseudo input doesn't have any inputs, whereas an
+  internal does.]
+
+  SeeAlso     [Tbl_TableBuildMvfForNonDetConstant]
+
+******************************************************************************/
+static Mvf_Function_t *
+NodeBuildPseudoInputMvfNew(
+  Ntk_Node_t * node,
+  mdd_manager * mddMgr)
+{
+  mdd_t *vMdd, *tMdd, *rMdd;
+  int lIndex, needProcess, i;
+  Mvf_Function_t *mvf;
+  int             columnIndex = Ntk_NodeReadOutputIndex(node);
+  Tbl_Table_t    *table       = Ntk_NodeReadTable(node);
+  int             mddId       = Ntk_NodeReadMddId(node);
+
+  assert(mddId != NTK_UNASSIGNED_MDD_ID);
+  mvf = Tbl_TableBuildNonDetConstantMvf(table, columnIndex, mddId, mddMgr);
+
+  rMdd = mdd_zero(mddMgr);
+  needProcess = 0;
+  lIndex = 0;
+  for(i=0; i<mvf->num; i++) {
+    vMdd = array_fetch(mdd_t *, mvf, i);
+    if(mdd_equal(vMdd, rMdd)) {
+      needProcess = 1;
+    }
+    else {
+      lIndex = i;
+    }
+  }
+  if(needProcess) {
+    for(i=0; i<lIndex; i++) {
+      vMdd = array_fetch(mdd_t *, mvf, i);
+      tMdd = mdd_or(vMdd, rMdd, 1, 1);
+      mdd_free(rMdd);
+      rMdd = tMdd;
+    }
+    vMdd = array_fetch(mdd_t *, mvf, lIndex);
+    mdd_free(vMdd);
+    tMdd = mdd_not(rMdd);
+    mdd_free(rMdd);
+    array_insert(mdd_t *, mvf, lIndex, tMdd);
+  }
+  else {
+    mdd_free(rMdd);
+  }
+  return mvf;
+}
+
+#if 0
+static Mvf_Function_t *
+NodeBuildPseudoInputMvf(
+  Ntk_Node_t * node,
+  mdd_manager * mddMgr)
+{
+  Mvf_Function_t *mvf;
+  int             columnIndex = Ntk_NodeReadOutputIndex(node);
+  Tbl_Table_t    *table       = Ntk_NodeReadTable(node);
+  int             mddId       = Ntk_NodeReadMddId(node);
+
+  assert(mddId != NTK_UNASSIGNED_MDD_ID);
+  mvf = Tbl_TableBuildNonDetConstantMvf(table, columnIndex, mddId, mddMgr);
+
+  return mvf;
+}
+#endif
+
+
+/**Function********************************************************************
+
+  Synopsis [Builds MVF for a node with no inputs, and only one row in its
+  table.]
+
+  Description [Builds MVF for a constant.  If constantValue is NTM_UNUSED,
+  then constantValue should be a legal index in the domain of the variable of
+  node. In this case, regardless of the type of the node, an MVF is built
+  where the component indexed by constantValue is one (i.e. the tautology) and
+  all other components are zero.<p>
+
+  If constantValue is not NTM_UNUSED, then node should be a constant,
+  combinational node.  In this case, an MVF is built with a single component
+  (indexed by the value of node) is one, and all other components are zero.]
+
+  SideEffects []
+
+******************************************************************************/
+static Mvf_Function_t *
+NodeBuildConstantMvf(
+  Ntk_Node_t * node,
+  int constantValue,
+  mdd_manager *mddMgr)
+{
+  int             value        = 0; /* initialized to stop lint complaining */
+  mdd_t          *oneMdd       = mdd_one(mddMgr);
+  Var_Variable_t *variable     = Ntk_NodeReadVariable(node);
+  int             numVarValues = Var_VariableReadNumValues(variable);
+  Mvf_Function_t *mvf          = Mvf_FunctionAlloc(mddMgr, numVarValues);
+
+
+  if (constantValue != NTM_UNUSED) {
+    /* Use the given value. */
+    assert((constantValue >= 0) && (constantValue < numVarValues));
+    value = constantValue;
+  }
+  else {
+    int          outputIndex = Ntk_NodeReadOutputIndex(node);
+    Tbl_Table_t *table       = Ntk_NodeReadTable(node);
+
+    assert(Ntk_NodeTestIsConstant(node));
+    value = Tbl_TableReadConstValue(table, outputIndex);
+    assert(value != -1);
+  }
+
+  Mvf_FunctionAddMintermsToComponent(mvf, value, oneMdd);
+  mdd_free(oneMdd);
+  return mvf;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Builds MVF for an internal node in terms of its fanin's MVFs.]
+
+  Description [Builds MVF for an internal node in terms of its fanin's
+  MVFs. An internal node is a node that is in the transitive fanin of a root,
+  but is not a leaf.]
+
+  SideEffects []
+
+******************************************************************************/
+static Mvf_Function_t *
+NodeBuildInternalMvf(
+  Ntk_Node_t * node,
+  st_table * leaves,
+  st_table * nodeToMvfTable,
+  mdd_manager *mddMgr,
+  mdd_t *careSet)
+{
+  int             i;
+  Mvf_Function_t *resultMvf;
+  Ntk_Node_t     *faninNode;
+  array_t        *faninMvfs   = array_alloc(Mvf_Function_t *, Ntk_NodeReadNumFanins(node));
+  int             outputIndex = Ntk_NodeReadOutputIndex(node);
+  Tbl_Table_t    *table       = Ntk_NodeReadTable(node);
+
+
+  Ntk_NodeForEachFanin(node, i, faninNode) {
+    Mvf_Function_t *tmpMvf = NodeBuildMvfRecursively(faninNode, leaves,
+						     nodeToMvfTable, mddMgr,
+						     careSet);
+    array_insert(Mvf_Function_t *, faninMvfs, i, tmpMvf);
+  }
+  resultMvf = Tbl_TableBuildMvfFromFanins(table, outputIndex, faninMvfs, mddMgr);
+
+  /* Mc_CheckValdityOfMvf(Ntk_NodeReadNetwork(node), mddMgr, node, resultMvf); */
+
+  Ntk_NodeForEachFanin(node, i, faninNode) {
+    NodeDecrementRefCount(faninNode, nodeToMvfTable);
+  }
+
+  /* Don't free the MVFs themselves, but just free the array. */
+  array_free(faninMvfs);
+
+  return resultMvf;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns MVF corresponding to a node; returns NIL if node not in
+  table.]
+
+  SideEffects []
+
+******************************************************************************/
+static Mvf_Function_t *
+NodeReadMvf(
+  Ntk_Node_t * node,
+  st_table * nodeToMvfTable)
+{
+  Mvf_Function_t *result = NIL(Mvf_Function_t);
+  st_lookup(nodeToMvfTable, node, &result);
+
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts node and corresponding MVF into table.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+NodeSetMvf(
+  Ntk_Node_t * node,
+  st_table * nodeToMvfTable,
+  Mvf_Function_t * mvf)
+{
+  st_insert(nodeToMvfTable, (char *) node, (char *) mvf);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Hacked test for the ntm package.]
+
+  CommandName [_ntm_test]
+
+  CommandSynopsis [test the ntm package]
+
+  CommandArguments [\[-h\] \[-v\]]
+
+  CommandDescription [Test the ntm package.  This package is responsible for
+  building the multi-valued functions (represented as MDDs) of the flattened
+  network.  This command builds the multi-valued functions of the
+  combinational outputs in terms of the combinational inputs.  The
+  multi-valued functions are then deleted. <p>
+
+  Command options:<p>
+
+  <dl>
+
+  <dt> -h
+  <dd> Print the command usage.
+
+  <dt> -v
+  <dd> Print the sizes of the MDDs built.
+
+  </dl>
+  ]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandNtmTest(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int            c;
+  Ntk_Node_t    *node;
+  lsGen          gen;
+  array_t       *result; /* array of Mvf_Function_t* */
+  array_t       *roots;
+  st_table      *leaves;
+  boolean        verbose = FALSE;              /* default */
+  Ntk_Network_t *network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+
+  /*
+   * Parse the command line.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "vh")) != EOF) {
+    switch (c) {
+      case 'v':
+	verbose = 1;
+	break;
+      case 'h':
+	goto usage;
+      default:
+	goto usage;
+    }
+  }
+
+  if (network == NIL(Ntk_Network_t)) {
+    return 1;
+  }
+
+  if (Ord_NetworkTestAreVariablesOrdered(network, Ord_InputAndLatch_c) == FALSE) {
+    (void) fprintf(vis_stderr, "The MDD variables have not been ordered. ");
+    (void) fprintf(vis_stderr, "Use static_order.\n");
+    return 1;
+  }
+
+  roots = array_alloc(Ntk_Node_t *, 0);
+  Ntk_NetworkForEachCombOutput(network, gen, node) {
+    array_insert_last(Ntk_Node_t *, roots, node);
+  }
+
+  leaves = st_init_table(st_ptrcmp, st_ptrhash);
+  Ntk_NetworkForEachCombInput(network, gen, node) {
+    st_insert(leaves, (char *) node, (char *) NTM_UNUSED);
+  }
+
+  result = Ntm_NetworkBuildMvfs(network, roots, leaves, NIL(mdd_t));
+
+  if (verbose) {
+    MvfSanityCheck(roots, result);
+  }
+
+  array_free(roots);
+  st_free_table(leaves);
+
+  /*
+   * Free the array of MVFs.
+   */
+  Mvf_FunctionArrayFree(result);
+
+  return 0;
+
+usage:
+  (void) fprintf(vis_stderr, "usage: _ntm_test [-h] [-v]\n");
+  (void) fprintf(vis_stderr, "   -h print the command usage\n");
+  (void) fprintf(vis_stderr, "   -v verbose\n");
+  return 1;		/* error exit */
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks that MDD sizes are meaningful.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+MvfSanityCheck(
+  array_t *roots /* of Ntk_Node_t* */,
+  array_t *mvfs  /* of Mvf_Function_t* */)
+{
+  int i;
+
+  assert(array_n(roots) == array_n(mvfs));
+
+  for (i = 0; i < array_n(roots); i ++) {
+    int             value;
+    mdd_t          *valueMdd;
+    Ntk_Node_t     *root = array_fetch(Ntk_Node_t *, roots, i);
+    Mvf_Function_t *mvf  = array_fetch(Mvf_Function_t *, mvfs, i);
+
+    (void) fprintf(vis_stdout, "\nMDD stats for node %s:\n", Ntk_NodeReadName(root));
+
+    Mvf_FunctionForEachComponent(mvf, value, valueMdd) {
+      (void) fprintf(vis_stdout, "\tSize of MDD for value %d is %d\n", i,
+		     mdd_size(valueMdd));
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the reference counts in a region.]
+
+  Description [Initializes the reference counts in the region defined by the
+  roots and leaves.  This region includes the roots, and all nodes in the
+  transitive fanin of the roots up to and including the leaves.  The reference
+  count for a node in the region is set to be the number of fanouts of that
+  node in the region (fanouts to leaf nodes and constant nodes are excluded).
+  Root nodes are set to MAXINT, so that even after some decrements, their ref
+  count won't fall to zero.]
+
+  SideEffects [Uses the undef field of node.]
+
+******************************************************************************/
+static void
+RegionInitializeReferenceCounts(
+  array_t *roots,
+  st_table *leaves)
+{
+  int           i;
+  Ntk_Node_t   *node;
+  st_generator *stGen;
+  st_table     *regionNodes = Ntk_RegionFindNodes(roots, leaves);
+
+  st_foreach_item(regionNodes, stGen, &node, NULL) {
+    Ntk_Node_t *fanoutNode;
+    long        refCount = 0;
+
+    Ntk_NodeForEachFanout(node, i, fanoutNode) {
+      if (st_is_member(regionNodes, (char *) fanoutNode)
+	  && !st_is_member(leaves, (char *) fanoutNode)
+	  && !Ntk_NodeTestIsConstant(fanoutNode)) {
+	refCount++;
+      }
+    }
+    Ntk_NodeSetUndef(node, (void *) refCount);
+  }
+
+  for(i = 0; i < array_n(roots); i++) {
+    node = array_fetch(Ntk_Node_t *, roots, i);
+    Ntk_NodeSetUndef(node, (void *) MAXINT);
+  }
+
+  st_free_table(regionNodes);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Decrements the ref count of a node.]
+
+  Description [Decrements the ref count of a node.  If the ref count becomes
+  zero, then remove node from nodeToMvfTable and free the MVF corresponding to
+  node.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+NodeDecrementRefCount(
+  Ntk_Node_t *node,
+  st_table *nodeToMvfTable)
+{
+  Mvf_Function_t *mvf;
+  long            refCount = (long) Ntk_NodeReadUndef(node);
+
+  assert(refCount != 0);
+
+  refCount--;
+
+  if (refCount == 0) {
+    st_delete(nodeToMvfTable, &node, &mvf);
+    Mvf_FunctionFree(mvf);
+  }
+
+  Ntk_NodeSetUndef(node, (void *) refCount);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns TRUE if table1 is contained in nodeArray; else FALSE.]
+
+  Description [Table1 is a hash table where the keys are nodes. NodeArray is
+  an array of nodes.  This function returns TRUE if the set of key nodes in
+  table1 is contained in the set of nodes in nodeArray.  It returns FALSE upon
+  finding the first key node in table1 that is not in nodeArray.]
+
+  SideEffects []
+
+******************************************************************************/
+static boolean
+TableTestIsContainedInArray(
+  st_table *table1,
+  array_t *nodeArrary)
+{
+  int             i;
+  st_generator   *stGen;
+  Ntk_Node_t     *node;
+  Mvf_Function_t *mvf;
+  st_table       *table2 = st_init_table(st_ptrcmp, st_ptrhash);
+
+  /* Create a hash table from the array. */
+  arrayForEachItem(Ntk_Node_t *, nodeArrary, i, node) {
+    st_insert(table2, (char *) node, NIL(char));
+  }
+
+  st_foreach_item(table1, stGen, &node, &mvf) {
+    if (!st_is_member(table2, node)) {
+      st_free_table(table2);
+      return FALSE;
+    }
+  }
+
+  st_free_table(table2);
+  return TRUE;
+}
Index: vis_dev/vis-2.3/src/ntm/ntm.h
===================================================================
--- vis_dev/vis-2.3/src/ntm/ntm.h	(revision 14)
+++ vis_dev/vis-2.3/src/ntm/ntm.h	(revision 14)
@@ -0,0 +1,64 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [ntm.h]
+
+  PackageName [ntm]
+
+  Synopsis    [Construction of MDDs from a flattened network.]
+
+  Description [Provides a routine to build the MVFs of the roots of an
+  arbitrary region of a network, in terms of the leaves of the region. The
+  leaves can be treated as variables or as specific constants.]
+
+  Author      [Adnan Aziz and Tom Shiple]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: ntm.h,v 1.3 2002/09/08 21:56:34 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _NTM
+#define _NTM
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "ntk.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+#define NTM_UNUSED (-1)
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void Ntm_Init(void);
+EXTERN void Ntm_End(void);
+EXTERN array_t * Ntm_NetworkBuildMvfs(Ntk_Network_t * network, array_t * roots, st_table * leaves, mdd_t *careSet);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _NTM */
+
Index: vis_dev/vis-2.3/src/ntm/ntm.make
===================================================================
--- vis_dev/vis-2.3/src/ntm/ntm.make	(revision 14)
+++ vis_dev/vis-2.3/src/ntm/ntm.make	(revision 14)
@@ -0,0 +1,4 @@
+CSRC += ntm.c
+HEADERS += ntm.h ntmInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/ntm/ntmInt.h
===================================================================
--- vis_dev/vis-2.3/src/ntm/ntmInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/ntm/ntmInt.h	(revision 14)
@@ -0,0 +1,55 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [ntmInt.h]
+
+  PackageName [ntm]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Adnan Aziz and Tom Shiple]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: ntmInt.h,v 1.1.1.2 1997/02/12 22:23:42 hsv Exp $]
+
+******************************************************************************/
+
+#ifndef _NTMINT
+#define _NTMINT
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "ntm.h"
+#include "cmd.h"
+#include "ord.h"
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _NTMINT */
+
Index: vis_dev/vis-2.3/src/ntmaig/ntmaig.c
===================================================================
--- vis_dev/vis-2.3/src/ntmaig/ntmaig.c	(revision 14)
+++ vis_dev/vis-2.3/src/ntmaig/ntmaig.c	(revision 14)
@@ -0,0 +1,573 @@
+/**CFile***********************************************************************
+
+  FileName    [ntmaig.c]
+
+  PackageName [ntmaig]
+
+  Synopsis    [Routines to build mAigs from a network.]
+
+  Author      [Mohammad Awedh]
+
+  Copyright [ This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "ntmaigInt.h"
+#include "baig.h"
+
+static char rcsid[] UNUSED = "$Id: ntmaig.c,v 1.15 2005/04/28 08:54:35 bli Exp $";
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static MvfAig_Function_t * NodeBuildMvfAigRecursively(Ntk_Node_t * node, st_table * leaves, st_table * nodeToMvfTable, mAig_Manager_t *manager);
+static MvfAig_Function_t * NodeBuildInputMvfAig(mAig_Manager_t *manager, Ntk_Node_t * node);
+static MvfAig_Function_t * NodeBuildPseudoInputMvfAigNew(mAig_Manager_t *manager, Ntk_Node_t * node);
+/*static MvfAig_Function_t * NodeBuildPseudoInputMvfAig(mAig_Manager_t *manager, Ntk_Node_t * node);*/
+static MvfAig_Function_t * NodeBuildConstantMvfAig(Ntk_Node_t * node, int constantValue, mAig_Manager_t *manager);
+static MvfAig_Function_t * NodeBuildInternalMvfAig(Ntk_Node_t * node, st_table * leaves, st_table * nodeToMvfAigTable, mAig_Manager_t *manager);
+static MvfAig_Function_t * NodeReadMvfAig(Ntk_Node_t * node, st_table * nodeToMvfAigTable);
+static void NodeSetMvfAig(Ntk_Node_t * node, st_table * nodeToMvfAigTable, MvfAig_Function_t * MvfAig);
+static void RegionInitializeReferenceCounts(array_t *roots, st_table *leaves);
+static void NodeDecrementRefCount(Ntk_Node_t *node, st_table *nodeToMvfTable);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Builds multi-valued functions for roots, in terms of leaves.]
+
+  Description [Takes an array of root nodes and a table of leaf nodes, and
+  builds the multi-valued functions (MvfAigs) for the roots in terms of the
+  leaves. This function returns an array of MvfAig_Function_t*, in one-to-one
+  correspondence with the roots array.  It is assumed that every path, from a
+  root backwards to a combinational input, passes through a node in the leaves
+  table, and that there are no combinational cycles within the region defined
+  by the roots and leaves. Also, it is assumed that every node in the leaves
+  table already has an mAig Id.<p>
+
+  A leaf that is a primary input, latch, or combinational node, is treated as
+  a "free" input (i.e. can assume any value in its domain). A leaf that is a
+  pseudo input can assume only those values for which it was specified.<p>
+
+  The leaves table maps nodes (Ntk_Node_t*) to integers.  If the value
+  corresponding to a leaf is ntmaig_UNUSED, then the MvfAig for the leaf is built
+  as described above.  However, the value can be specified as the index of
+  some value in the domain of the variable of the leaf.  For example, if leaf
+  node x can take values (RED, GREEN, BLUE), then the value 1 refers to GREEN.
+  In this case, the MvfAig built for x is simply the constant MvfAig representing
+  This feature can be used to evaluate the MvfAigs of the roots on a minterm, or 
+  partial minterm, over the leaves.<p>
+
+  nodeToMvfAigTable is a table mapping nodes to MvfAig_Function_t's (for nodes for
+  which MvfAig_Function's have already been built); Call NodeBuildMvfAigRecursively
+  on the roots. Free MvfAig's at internal nodes ASAP, so no excessive storage.]
+
+  SideEffects []
+******************************************************************************/
+array_t *
+ntmaig_NetworkBuildMvfAigs(
+  Ntk_Network_t * network,
+  array_t       * roots,
+  st_table      * leaves)
+{
+  int               i;
+  MvfAig_Function_t *MvfAig;
+  st_table          *nodeToMvfAigTable;  /* mapes each node with its mvfAig */
+  int                numRoots = array_n(roots);
+  array_t           *result   = array_alloc(MvfAig_Function_t *, numRoots);
+  mAig_Manager_t    *manager  = Ntk_NetworkReadMAigManager(network);
+  MvfAig_Function_t *tmpMvf;
+
+  
+  /*
+   * Before initializing the reference counts, verify that the leaves form a
+   * support set for the roots.
+   */
+  if (!Ntk_NetworkTestLeavesCoverSupportOfRoots(network, roots, leaves)) {
+    fail("Leaves do not cover support of roots");
+  }
+  /*
+   * Each node in the region defined by the roots and leaves is assigned a
+   * reference count equaling the number of fanouts within the region.  As a
+   * special case, the roots are initialized to MAX_INT.
+   */
+  RegionInitializeReferenceCounts(roots, leaves);
+  /*
+   * For each root, compute its MvfAig and store a duplicate copy of it in the
+   * result array. The nodeToMvfAigTable is used to keep track of intermediate
+   * computations. Intermediate MvfAigs are freed as soon as possible by using
+   * the reference count mechanism.
+   */
+  nodeToMvfAigTable = (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+  if (nodeToMvfAigTable == NIL(st_table)){
+    nodeToMvfAigTable = st_init_table(st_ptrcmp, st_ptrhash);
+    /* Register the MvfAig Table in the network*/
+    Ntk_NetworkAddApplInfo(network, MVFAIG_NETWORK_APPL_KEY,
+	  		 (Ntk_ApplInfoFreeFn) ntmAig_MvfAigTableFreeCallback,
+			 (void *) nodeToMvfAigTable);
+  }
+  for (i = 0; i < numRoots; i++) {
+    Ntk_Node_t        *root   = array_fetch(Ntk_Node_t *, roots, i);
+    tmpMvf = NodeBuildMvfAigRecursively(root, leaves,
+                                     nodeToMvfAigTable, manager);
+    MvfAig = MvfAig_FunctionDuplicate(tmpMvf);
+    array_insert(MvfAig_Function_t *, result, i, MvfAig);
+  }
+
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Call-back function to free a MvfAig Table.]
+
+  Description [This function will be stored in the network together with the
+  pointer to the MvfAig Table. Whenever the network deletes the MvfAig 
+  information, this function is called and it will free the table and
+  the information attached to it.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkAddApplInfo]
+
+******************************************************************************/
+void
+ntmAig_MvfAigTableFreeCallback(
+   void *data)
+{
+  st_generator      *stGen;
+  MvfAig_Function_t *MvfAig;
+  Ntk_Node_t        *node;
+  st_table          *nodeToMvfAigTable = (st_table*) data;
+
+  st_foreach_item(nodeToMvfAigTable, stGen,  &node,  &MvfAig) {
+    MvfAig_FunctionFree(MvfAig);
+  }
+  st_free_table(nodeToMvfAigTable);
+} /* End of ntmAig_MvfAigTableFreeCallback */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds MvfAig for a node, recursively in terms of fanins.]
+
+  Description [Recursively builds MvfAig_Functions_t's. Base cases - input nodes,
+  latch nodes, constant nodes, pseudo inputs, and leaf nodes. Fail if a
+  combinational input is reached that is not in leaves.  In the case that the
+  node is combinational, and in the leaves, we treat it as an input.  When
+  it's a pseudo input, we treat it as taking only values designated in table.]
+
+  SideEffects []
+
+  SeeAlso     [NodeBuildInputMvfAig,NodeBuildPseudoInputMvfAig,NodeBuildInternalMvfAig]
+[Done]
+******************************************************************************/
+static MvfAig_Function_t *
+NodeBuildMvfAigRecursively(
+  Ntk_Node_t * node,
+  st_table * leaves,
+  st_table * nodeToMvfTable,
+  mAig_Manager_t *manager)
+{
+  MvfAig_Function_t *MvfAig = NodeReadMvfAig(node, nodeToMvfTable);
+  
+  /* If the MvfAig for this node has already been computed, then just return it. */
+
+  if (MvfAig != NIL(MvfAig_Function_t)) {
+    return MvfAig;
+  }
+  if (Ntk_NodeTestIsConstant(node)) {
+    /* Doesn't matter if constant is a leaf or not. */
+    MvfAig = NodeBuildConstantMvfAig(node, ntmaig_UNUSED, manager);
+  }
+  else {
+    int constValue;
+  
+    if (st_lookup_int(leaves,  node, &constValue)) { 
+      if (constValue == ntmaig_UNUSED) {
+        /* Node is a leaf. */
+        if ((Ntk_NodeTestIsPrimaryInput(node)) ||
+            (Ntk_NodeTestIsLatch(node)) ||
+            (Ntk_NodeTestIsCombinational(node))) {
+          /* Node can assume any value. */
+          MvfAig = NodeBuildInputMvfAig(manager, node);
+        }
+        else if (Ntk_NodeTestIsPseudoInput(node)) {
+          /* Node may assume only a subset of possible values. */
+          MvfAig = NodeBuildPseudoInputMvfAigNew(manager, node);
+        }
+        else {
+          fail("Encountered unknown type in MvfAig recursion\n");
+        }
+      }
+      else {
+        /* treat the leaf node as being a constant taking the value constValue */
+        MvfAig = NodeBuildConstantMvfAig(node, constValue, manager);
+      }
+    }
+    else {
+
+      /* Node is not a leaf.  If it is a combinational input, then fail. */
+      if (Ntk_NodeTestIsCombInput(node)) {
+        fail("Encountered combinational input not in leaves table\n");
+      }
+      else {
+        MvfAig = NodeBuildInternalMvfAig(node, leaves, nodeToMvfTable, manager);
+      }
+    }
+  }
+  NodeSetMvfAig(node, nodeToMvfTable, MvfAig);
+  return MvfAig;
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis  [Builds MvfAig for a node that is treated as a free input.]
+
+  SideEffects []
+[Done]
+******************************************************************************/
+static MvfAig_Function_t *
+NodeBuildInputMvfAig(
+  mAig_Manager_t *manager,
+  Ntk_Node_t * node)
+{
+  int mAigId = Ntk_NodeReadMAigId(node);
+
+  assert(mAigId != NTK_UNASSIGNED_MAIG_ID);
+  return MvfAig_FunctionCreateFromVariable(manager, mAigId);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Builds MvfAig for a node that is a pseudo input.]
+
+  Description [Builds MvfAig for a node that is a pseudo input.  This node has
+  a single output and no inputs. Its table has several row entries.  We build
+  an MvfAig whose components correspond exactly to possible table outputs.]
+
+  SideEffects []
+
+ Comment [Although pseudo inputs, constants, and internal nodes all have
+  tables, a single procedure cannot be used to build their MvfAig.  A pseudo
+  input MvfAig is built in terms of its mddId, whereas a constant or internal is
+  not.  A constant or pseudo input doesn't have any inputs, whereas an
+  internal does.]
+  
+  SeeAlso     [Tbl_TableBuildMvfAigForNonDetConstant]
+[Done]
+******************************************************************************/
+static MvfAig_Function_t *
+NodeBuildPseudoInputMvfAigNew(
+  mAig_Manager_t *manager,
+  Ntk_Node_t * node)
+{
+  int lIndex=0, needProcess, i;
+  mAigEdge_t  mAig, tmpAig;
+  MvfAig_Function_t *MvfAig;
+  int                columnIndex = Ntk_NodeReadOutputIndex(node);
+  Tbl_Table_t       *table       = Ntk_NodeReadTable(node);
+  int                mAigId      = Ntk_NodeReadMAigId(node);
+
+  assert(mAigId != NTK_UNASSIGNED_MAIG_ID);
+  MvfAig = Tbl_TableBuildNonDetConstantMvfAig(table, columnIndex,
+mAigId,
+					      manager);
+  needProcess = 0;
+  tmpAig = mAig_Zero;
+  for(i=0; i<MvfAig->num; i++) {
+    mAig = array_fetch(mAigEdge_t, MvfAig, i);
+    if(mAig == tmpAig) {
+      needProcess = 1;
+    }
+    else {
+      lIndex = i;
+    }
+  }
+  if(needProcess) {
+    for(i=0; i<lIndex; i++) {
+      mAig   = array_fetch(mAigEdge_t, MvfAig, i);
+      tmpAig = mAig_Or(manager, tmpAig, mAig);
+    }
+    array_insert(mAigEdge_t, MvfAig, lIndex, mAig_Not(tmpAig));
+  }
+  
+  return MvfAig;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Builds MvfAig for a node that is a pseudo input.]
+
+  Description [Builds MvfAig for a node that is a pseudo input.  This node has a
+  single output and no inputs. Its table has several row entries.  We build an
+  MvfAig whose components correspond exactly to possible table outputs.]
+
+  SideEffects []
+
+  Comment [Although pseudo inputs, constants, and internal nodes all have
+  tables, a single procedure cannot be used to build their MvfAig.  A pseudo
+  input MvfAig is built in terms of its mddId, whereas a constant or internal is
+  not.  A constant or pseudo input doesn't have any inputs, whereas an
+  internal does.]
+  
+  SeeAlso     [Tbl_TableBuildMvfAigForNonDetConstant]
+[Done]
+******************************************************************************/
+/*static MvfAig_Function_t *
+NodeBuildPseudoInputMvfAig(
+  mAig_Manager_t *manager,
+  Ntk_Node_t * node)
+{
+  MvfAig_Function_t *MvfAig;
+  int                columnIndex = Ntk_NodeReadOutputIndex(node);
+  Tbl_Table_t       *table       = Ntk_NodeReadTable(node);
+  int                mAigId      = Ntk_NodeReadMAigId(node);
+
+  assert(mAigId != NTK_UNASSIGNED_MAIG_ID);
+  MvfAig = Tbl_TableBuildNonDetConstantMvfAig(table, columnIndex, mAigId, manager);
+  return MvfAig;
+}*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Builds MvfAig for a node with no inputs, and only one row in its
+  table.]
+
+  Description [Builds MvfAig for a constant.  If constantValue is ntmaig_UNUSED,
+  then constantValue should be a legal index in the domain of the variable of
+  node. In this case, regardless of the type of the node, an MvfAig is built
+  where the component indexed by constantValue is one (i.e. the tautology) and
+  all other components are zero.<p>
+
+  If constantValue is not ntmaig_UNUSED, then node should be a constant,
+  combinational node.  In this case, an MvfAig is built with a single component
+  (indexed by the value of node) is one, and all other components are zero.]
+
+  SideEffects []
+[Done]
+******************************************************************************/
+static MvfAig_Function_t *
+NodeBuildConstantMvfAig(
+  Ntk_Node_t * node,
+  int constantValue,
+  mAig_Manager_t *manager)
+{
+  int             value        = 0; /* initialized to stop lint complaining */
+  Var_Variable_t *variable     = Ntk_NodeReadVariable(node);
+  int             numVarValues = Var_VariableReadNumValues(variable);
+  MvfAig_Function_t *MvfAig    = MvfAig_FunctionAlloc(numVarValues);
+
+  if (constantValue != ntmaig_UNUSED) {
+    /* Use the given value. */
+    assert((constantValue >= 0) && (constantValue < numVarValues));
+    value = constantValue;
+  }
+  else {
+    int          outputIndex = Ntk_NodeReadOutputIndex(node);
+    Tbl_Table_t *table       = Ntk_NodeReadTable(node);
+
+    assert(Ntk_NodeTestIsConstant(node));
+    value = Tbl_TableReadConstValue(table, outputIndex);
+    assert(value != -1);
+  }
+  
+  MvfAig_FunctionAddMintermsToComponent(manager, MvfAig, value, bAig_One);
+  return MvfAig;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Builds MvfAig for an internal node in terms of its fanin's MvfAigs.]
+
+  Description [Builds MvfAig for an internal node in terms of its fanin's
+  MvfAigs. An internal node is a node that is in the transitive fanin of a root,
+  but is not a leaf.]
+
+  SideEffects []
+[Done]
+******************************************************************************/
+static MvfAig_Function_t *
+NodeBuildInternalMvfAig(
+  Ntk_Node_t * node,
+  st_table   * leaves,
+  st_table   * nodeToMvfAigTable,
+  mAig_Manager_t *manager)
+{
+  int               i;
+  MvfAig_Function_t *resultMvfAig;
+  Ntk_Node_t        *faninNode;
+  array_t           *faninMvfAigs = array_alloc(MvfAig_Function_t *, Ntk_NodeReadNumFanins(node));
+  int               outputIndex   = Ntk_NodeReadOutputIndex(node);
+  Tbl_Table_t       *table        = Ntk_NodeReadTable(node);
+
+  Ntk_NodeForEachFanin(node, i, faninNode) {
+    MvfAig_Function_t *tmpMvfAig = NodeBuildMvfAigRecursively(faninNode, leaves,
+                                                              nodeToMvfAigTable, manager);
+    array_insert(MvfAig_Function_t *, faninMvfAigs, i, tmpMvfAig);
+  }
+  resultMvfAig = Tbl_TableBuildMvfAigFromFanins(table, outputIndex, faninMvfAigs, manager); 
+  Ntk_NodeForEachFanin(node, i, faninNode) {
+    NodeDecrementRefCount(faninNode, nodeToMvfAigTable);
+  }
+  /* Don't free the MvfAigs themselves, but just free the array. */
+  array_free(faninMvfAigs);
+  return resultMvfAig;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns MvfAig corresponding to a node; returns NIL if node not in
+  table.]
+
+  SideEffects []
+[Done]
+******************************************************************************/
+static MvfAig_Function_t *
+NodeReadMvfAig(
+  Ntk_Node_t * node,
+  st_table   * nodeToMvfAigTable)
+{
+  MvfAig_Function_t *result = NIL(MvfAig_Function_t);
+  st_lookup(nodeToMvfAigTable,  node,  &result);
+
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts node and corresponding MvfAig into table.]
+
+  SideEffects []
+[Done]
+******************************************************************************/
+static void
+NodeSetMvfAig(
+  Ntk_Node_t * node,
+  st_table   * nodeToMvfAigTable,
+  MvfAig_Function_t * MvfAig)
+{
+  st_insert(nodeToMvfAigTable,  node,  MvfAig);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the reference counts in a region.]
+
+  Description [Initializes the reference counts in the region defined by the
+  roots and leaves.  This region includes the roots, and all nodes in the
+  transitive fanin of the roots up to and including the leaves.  The reference
+  count for a node in the region is set to be the number of fanouts of that
+  node in the region (fanouts to leaf nodes and constant nodes are excluded).
+  Root nodes are set to MAXINT, so that even after some decrements, their ref
+  count won't fall to zero.]
+
+  SideEffects [Uses the undef field of node.]
+
+******************************************************************************/
+static void
+RegionInitializeReferenceCounts(
+  array_t *roots, 
+  st_table *leaves)
+{
+  int           i;
+  Ntk_Node_t   *node;
+  st_generator *stGen;
+  st_table     *regionNodes = Ntk_RegionFindNodes(roots, leaves);
+
+  st_foreach_item(regionNodes, stGen,  &node, NIL(char *)) {
+    Ntk_Node_t *fanoutNode;
+    long        refCount = 0;
+
+    Ntk_NodeForEachFanout(node, i, fanoutNode) {
+      if (st_is_member(regionNodes,  fanoutNode)
+          && !st_is_member(leaves,  fanoutNode)
+          && !Ntk_NodeTestIsConstant(fanoutNode)) {
+        refCount++;
+      }
+    }
+    Ntk_NodeSetUndef(node, (void *) refCount);
+  }
+
+  for(i = 0; i < array_n(roots); i++) {
+    node = array_fetch(Ntk_Node_t *, roots, i);
+    Ntk_NodeSetUndef(node, (char *) MAXINT);
+  }
+
+  st_free_table(regionNodes);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Decrements the ref count of a node.]
+
+  Description [Decrements the ref count of a node.  If the ref count becomes
+  zero, then remove node from nodeToMvfTable and free the MVF corresponding to
+  node.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+NodeDecrementRefCount(
+  Ntk_Node_t *node, 
+  st_table *nodeToMvfTable)
+{
+  long              refCount = (long) Ntk_NodeReadUndef(node);
+
+  assert(refCount != 0);
+
+  refCount--;
+  /*  
+    Want to keep the entry of this node, so we may get the MvfAig of this node
+    whenever we need it.  The pointer to the nodeToMvfTable is stored in the network
+    information.
+   */
+  /*  
+  if (refCount == 0) {
+    st_delete(nodeToMvfTable, (char **) &node, (char **) &mvf);
+    MvfAig_FunctionFree(mvf);
+  }
+  */
+  Ntk_NodeSetUndef(node, (void *) refCount);
+}
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/ntmaig/ntmaig.h
===================================================================
--- vis_dev/vis-2.3/src/ntmaig/ntmaig.h	(revision 14)
+++ vis_dev/vis-2.3/src/ntmaig/ntmaig.h	(revision 14)
@@ -0,0 +1,51 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [ntmaig.h]
+
+  PackageName [ntmaig]
+
+  Synopsis    [Construction of mAigs from a flattened network.]
+
+  Description [Provides a routine to build the mvfAigs of the roots of an
+  arbitrary region of a network, in terms of the leaves of the region. The
+  leaves can be treated as variables or as specific constants.]
+
+  Author      [Mohammad Awedh]
+
+  Copyright   []
+
+  Revision    [$Id: ntmaig.h,v 1.3 2005/04/17 14:18:22 awedh Exp $]
+
+******************************************************************************/
+
+#ifndef _ntmaig
+#define _ntmaig
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "ntk.h"
+#include "baig.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+#define ntmaig_UNUSED (-1)
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN array_t * ntmaig_NetworkBuildMvfAigs(Ntk_Network_t * network, array_t * roots, st_table * leaves);
+EXTERN void ntmAig_MvfAigTableFreeCallback(void *data);
+EXTERN void ntmaig_Init(void);
+EXTERN void ntmaig_End(void);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _ntmaig */
+
+
+
Index: vis_dev/vis-2.3/src/ntmaig/ntmaig.make
===================================================================
--- vis_dev/vis-2.3/src/ntmaig/ntmaig.make	(revision 14)
+++ vis_dev/vis-2.3/src/ntmaig/ntmaig.make	(revision 14)
@@ -0,0 +1,4 @@
+CSRC += ntmaig.c ntmaigCmd.c
+HEADERS += ntmaig.h ntmaigInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/ntmaig/ntmaigCmd.c
===================================================================
--- vis_dev/vis-2.3/src/ntmaig/ntmaigCmd.c	(revision 14)
+++ vis_dev/vis-2.3/src/ntmaig/ntmaigCmd.c	(revision 14)
@@ -0,0 +1,296 @@
+/**CFile***********************************************************************
+
+  FileName    [ntmaigCmd.c]
+
+  PackageName [ntmaig]
+
+  Synopsis    [Command interface for the Aig partition package]
+
+  Author      [Mohammad Awedh]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+******************************************************************************/
+
+#include "ntmaigInt.h"
+
+static char rcsid[] UNUSED = "$Id: ntmaigCmd.c,v 1.26 2009/01/18 01:54:51 fabio Exp $";
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandBuildPartitionMAigs(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int nodenameCompare(const void * node1, const void * node2);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+extern void bAig_BuildAigBFSManner( Ntk_Network_t *network, mAig_Manager_t *manager, st_table *leaves, int sweep);
+extern void bAig_BddSweepMain(Ntk_Network_t *network, array_t *nodeArray);
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the network to MAIG package.]
+
+  SideEffects []
+
+  SeeAlso     [ntmaig_End]
+
+******************************************************************************/
+void
+ntmaig_Init(void)
+{
+  Cmd_CommandAdd("build_partition_maigs", CommandBuildPartitionMAigs, /* doesn't changes_network */ 0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Ends the network to MAIG package.]
+
+  SideEffects []
+
+  SeeAlso     [ntmaig_Init]
+
+******************************************************************************/
+void
+ntmaig_End(void)
+{
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+  
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+nodenameCompare(
+  const void * node1,
+  const void * node2)
+{
+Ntk_Node_t *v1, *v2;
+char *name1, *name2;
+
+  v1 = *(Ntk_Node_t **)(node1);
+  v2 = *(Ntk_Node_t **)(node2);
+  name1 = Ntk_NodeReadName(v1);
+  name2 = Ntk_NodeReadName(v2);
+  
+  return (strcmp(name1, name2));
+} 
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the build_partition_maigs command.]
+
+  Description []
+  
+  CommandName [build_partition_maigs]
+
+  CommandSynopsis [build a partition of MAIGs for the flattened network]
+
+  CommandArguments [\[-h\] \[-d\] \[-n\] ]
+
+  CommandDescription [
+   Build the multi-valued AND/INVERTER graph (MAIG) of a flattened network. 
+   It builds the MAIG for the combinational outputs (COs) in terms of the 
+   combinational inputs (CIs). The pointer to this graph is stored in the
+   network to be used by other commands, such as bounded_model_check.
+
+   This command  must be preceded by the commands flatten_hierarchy. This
+   command will remove any previous build to this graph.
+
+   <p>
+
+  Command options:
+  <p>
+
+  <dl>
+
+  <dt> -n
+  <dd> Disable BDD sweeping.
+
+  <p>
+  <dt> -d 
+  <dd> Build aig structure in depth first manner.
+  <p>
+  ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+CommandBuildPartitionMAigs(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  Ntk_Node_t    *node, *latch;
+  lsGen          gen;
+  array_t       *result; /* array of MvfAig_Function_t* */
+  array_t       *roots;
+  st_table      *leaves;
+  array_t *inputs;
+  Ntk_Network_t *network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+  mAig_Manager_t *manager;
+  MvfAig_Function_t  *mvfAig;
+  st_table       *nodeToMvfAigTable;  /* mapes each node with its mvfAig */
+  int c, sweepFlag, DFSFlag;
+  int i;
+
+  sweepFlag = 1;
+  DFSFlag = 0;
+  util_getopt_reset();
+  while ((c = util_getopt(argc,argv,"sdnh")) != EOF){
+    switch(c){
+      case 's':
+	sweepFlag = 1;
+	break;
+      case 'd':
+	DFSFlag = 1;
+	break;
+      case 'n':
+	sweepFlag = 0;
+	break;
+      case 'h':
+        goto usage;
+      default:
+        goto usage;
+    }
+  }
+  if (network == NIL(Ntk_Network_t)) {
+    return 1;
+  }
+
+  manager = Ntk_NetworkReadMAigManager(network);
+
+  if (manager == NIL(mAig_Manager_t)) {
+      manager = mAig_initAig();
+      Ntk_NetworkSetMAigManager(network, manager);
+      /*
+      mAig_mAigSetNetwork(manager, network);
+      */
+  }
+
+  /* Check if there is already a MvfAigs Table attached to the network */
+  nodeToMvfAigTable = (st_table *) Ntk_NetworkReadApplInfo(network, 
+						  MVFAIG_NETWORK_APPL_KEY);
+
+  if (nodeToMvfAigTable != NIL(st_table)){
+    /* 
+    st_foreach_item(nodeToMvfAigTable, stGen, (char **) &node, (char **) &MvfAig) {
+       printf("\nNode name = %s :",Ntk_NodeReadName(node));
+       for (j=0; j< array_n(MvfAig); j++){
+        printf(" %d ",array_fetch(bAigEdge_t, (array_t *) MvfAig, j));
+       }
+    }
+    */
+    (void) fprintf(vis_stderr, "maig partition already built; reinvoke\n");
+    (void) fprintf(vis_stderr, "flatten_hierarchy to remove the current maig partition\n");
+     return 1;
+  }
+
+  roots = array_alloc(Ntk_Node_t *, 0);
+  Ntk_NetworkForEachCombOutput(network, gen, node) {
+    array_insert_last(Ntk_Node_t *, roots, node);
+  }
+  Ntk_NetworkForEachNode(network, gen, node) {
+    if(Ntk_NodeTestIsShadow(node))	continue;
+    if(Ntk_NodeTestIsCombInput(node))	continue;
+    if(Ntk_NodeTestIsCombOutput(node))continue;
+
+    if(Ntk_NodeReadNumFanouts(node) == 0 && Ntk_NodeReadNumFanins(node)) {
+	/**
+      fprintf(vis_stdout, "WARNING : dangling node %s\n", Ntk_NodeReadName(node));
+      **/
+      array_insert_last(Ntk_Node_t *, roots, node);
+    }
+  }
+
+  leaves = st_init_table(st_ptrcmp, st_ptrhash);
+
+  inputs = array_alloc(Ntk_Node_t *, 16);
+  Ntk_NetworkForEachCombInput(network, gen, node) {
+    array_insert_last(Ntk_Node_t *, inputs, node);
+  }
+  array_sort(inputs, nodenameCompare);
+  for(i=0; i<array_n(inputs); i++) {
+    node = array_fetch(Ntk_Node_t *, inputs, i);
+    st_insert(leaves,  node, (char *) ntmaig_UNUSED);
+    Ntk_NodeSetMAigId(node, 
+                       mAig_CreateVar(manager,
+		                      Ntk_NodeReadName(node),
+                                      Var_VariableReadNumValues(Ntk_NodeReadVariable(node))));
+  }
+
+  if(DFSFlag == 0)
+    bAig_BuildAigBFSManner(network, manager, leaves, sweepFlag);
+
+  result = ntmaig_NetworkBuildMvfAigs(network, roots, leaves);
+
+  nodeToMvfAigTable = (st_table *) Ntk_NetworkReadApplInfo(network, 
+						  MVFAIG_NETWORK_APPL_KEY);
+  Ntk_NetworkForEachLatch(network, gen, latch) {
+    node  = Ntk_LatchReadDataInput(latch);
+    st_lookup(nodeToMvfAigTable, node,  &mvfAig);
+    Ntk_NodeSetMAigId(node, 
+            mAig_CreateVarFromAig(manager, Ntk_NodeReadName(node), mvfAig));
+    node  = Ntk_LatchReadInitialInput(latch);
+    st_lookup(nodeToMvfAigTable, node,  &mvfAig);
+    Ntk_NodeSetMAigId(node, 
+            mAig_CreateVarFromAig(manager, Ntk_NodeReadName(node), mvfAig));
+  }
+
+  roots->num = 0;
+  Ntk_NetworkForEachLatch(network, gen, latch) {
+    if(!st_lookup(nodeToMvfAigTable, latch,  &mvfAig))
+      array_insert_last(Ntk_Node_t *, roots, latch);
+  }
+  result = ntmaig_NetworkBuildMvfAigs(network, roots, leaves);
+
+  array_free(roots);
+  array_free(inputs);
+  st_free_table(leaves);
+
+  /*
+   * Free the array of MvfAigs.
+   */
+  MvfAig_FunctionArrayFree(result);
+
+  if(sweepFlag) 
+    bAig_BddSweepMain(network, 0);
+  
+  return 0;
+  
+usage:
+  (void) fprintf(vis_stderr, "usage: build_partition_maig [-h]\n");
+  (void) fprintf(vis_stderr, "   -h print the command usage\n");
+  (void) fprintf(vis_stderr, "   -n disable bdd sweeping\n");
+  (void) fprintf(vis_stderr, "   -d build AIG DFS manner\n");
+  return 1;		/* error exit */
+}
Index: vis_dev/vis-2.3/src/ntmaig/ntmaigInt.h
===================================================================
--- vis_dev/vis-2.3/src/ntmaig/ntmaigInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/ntmaig/ntmaigInt.h	(revision 14)
@@ -0,0 +1,44 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [ntmaigInt.h]
+
+  PackageName [ntmaig]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Mohammad Awedh]
+
+  Copyright   []
+
+  Revision    [$Id: ntmaigInt.h,v 1.1 2002/03/05 23:14:14 awedh Exp $]
+
+******************************************************************************/
+
+#ifndef _ntmaigINT
+#define _ntmaigINT
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "ntmaig.h"
+#include "cmd.h"
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _ntmaigINT */
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/ord/ord.h
===================================================================
--- vis_dev/vis-2.3/src/ord/ord.h	(revision 14)
+++ vis_dev/vis-2.3/src/ord/ord.h	(revision 14)
@@ -0,0 +1,173 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [ord.h]
+
+  PackageName [ord]
+
+  Synopsis    [Routines for ordering MDD variables of a flattened network.]
+
+  Description [The routines in this package relate to ordering MDD variables
+  corresponding to the nodes of a network.  The enumerated type Ord_OrderType
+  is used to specify to which set of nodes certain ordering routines should
+  be applied.  The following matrix shows which node types are included in
+  each ordering type:
+  <pre>
+                  |             Ord_OrderType
+   node type      |  All   InputAndLatch   NextStateNode
+  ----------------+--------------------------------------- 
+  primary input   |   x          x 
+  pseudo input    |   x          x
+  latch           |   x          x
+  shadow          |   x          x               x  
+  combinational   |   x
+  
+  </pre>
+
+  In addition, the order type Partial can be used to specify an arbitrary
+  subset of nodes.<p>
+
+  There are various methods for ordering the roots of a network, and for
+  ordering the nodes of a network.  These are explained in the documentation
+  for the static_order command.]
+  
+  Author      [Adnan Aziz, Tom Shiple, Serdar Tasiran]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: ord.h,v 1.10 2002/09/08 23:26:15 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _ORD
+#define _ORD
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include <time.h>
+#include <math.h>
+#include "ntk.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                     */
+/*---------------------------------------------------------------------------*/
+/**Enum************************************************************************
+
+  Synopsis    [Used to specify particular subsets of network nodes.]
+
+  Description [Used to specify particular subsets of network nodes. This
+  enumerated type is used to specify which nodes are to be ordered, or which
+  nodes are supplied in an ordering file. "All" nodes of a network is exactly
+  the set returned by Ntk_NetworkReadNodes (this includes shadow nodes). ]
+
+  SeeAlso     [Ord_NetworkOrderVariables]
+
+******************************************************************************/
+typedef enum {
+  Ord_All_c,           /* all nodes in network */
+  Ord_NextStateNode_c, /* latch NS nodes */
+  Ord_Partial_c,       /* arbitrary subset of all nodes in network */
+  Ord_InputAndLatch_c, /* primary and pseudo inputs, latches, and latch NS */
+  Ord_Unassigned_c     /* not specified */
+} Ord_OrderType;
+
+
+/**Enum************************************************************************
+
+  Synopsis    [Used to specify a particular method to order the roots of a network.]
+
+  Description [Used to specify a particular method to order the roots of a
+  network.  The nodes of a network are explored in DFS order, starting from
+  the ordered list of roots.]
+
+  SeeAlso     [Ord_NetworkOrderRoots]
+
+******************************************************************************/
+typedef enum {
+  Ord_RootsByDepth_c,   /* decreasing order of logic depth */
+  Ord_RootsByPerm_c,    /* permutation that minimizes a communication-based
+                           cost function */
+  Ord_RootsByDefault_c  /* hardcoded default method (one of the above) */
+} Ord_RootMethod;
+
+
+/**Enum************************************************************************
+
+  Synopsis    [Used to specify a particular method to order the nodes of a network.]
+
+  Description [Used to specify a particular method to order the nodes of a
+  network.  These methods produce a total ordering on all of the nodes of a
+  network, including the next state nodes.]
+
+  SeeAlso     [Ord_NetworkOrderNodes]
+
+******************************************************************************/
+typedef enum {
+  Ord_NodesByInterleaving_c, /* Interleaving algorithm of Fujii et al. */
+  Ord_NodesByMergingLeft_c,  /* DFS by depth, merging left orderings of fanins */
+  Ord_NodesByMergingRight_c, /* DFS by depth, merging right orderings of fanins */
+  Ord_NodesByAppending_c,    /* DFS by depth, appending nodes as visited */
+  Ord_NodesByDefault_c       /* hardcoded default method (one of the above) */
+} Ord_NodeMethod;
+
+
+/**Enum************************************************************************
+
+  Synopsis    [Used to specify a particular method to merge two lists.]
+
+  SeeAlso     [Ord_ListMergeListUsingTable]
+
+******************************************************************************/
+typedef enum {
+  Ord_ListMergeLeft_c, /* merge left two lists */
+  Ord_ListMergeRight_c /* merge right two lists */
+} Ord_ListMergeMethod;
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void Ord_Init(void);
+EXTERN void Ord_End(void);
+EXTERN boolean Ord_NetworkTestAreVariablesOrdered(Ntk_Network_t * network, Ord_OrderType orderType);
+EXTERN int Ord_NetworkPrintVariableOrder(FILE * fp, Ntk_Network_t * network, Ord_OrderType orderType);
+EXTERN char ** Ord_NetworkGetCombInputNamesInOrder(Ntk_Network_t *network);
+EXTERN boolean Ord_FileReadNodeList(FILE * fp, Ntk_Network_t * network, lsList * nodeList, int verbose);
+EXTERN void Ord_NetworkOrderVariables(Ntk_Network_t *network, Ord_RootMethod rootOrderMethod, Ord_NodeMethod nodeOrderMethod, boolean nsAfterSupport, Ord_OrderType generatedOrderType, Ord_OrderType suppliedOrderType, lsList suppliedNodeList, int verbose);
+EXTERN lsList Ord_NetworkOrderNodes(Ntk_Network_t *network, Ord_RootMethod rootOrderMethod, Ord_NodeMethod nodeOrderMethod, boolean nsAfterSupport, Ord_OrderType generatedOrderType, Ord_OrderType suppliedOrderType, lsList suppliedNodeList, int verbose);
+EXTERN void Ord_NetworkAssignMddIdForNode(Ntk_Network_t *network, Ntk_Node_t *node);
+EXTERN void Ord_ListMergeLeftListUsingTable(lsList list1, lsList list2, st_table *dataToHandle1);
+EXTERN void Ord_ListMergeRightListUsingTable(lsList list1, lsList list2, st_table *dataToHandle1);
+EXTERN void Ord_ListMergeListUsingTable(lsList list1, lsList list2, st_table *dataToHandle1, Ord_ListMergeMethod method);
+EXTERN void Ord_ListAppendList(lsList list1, lsList list2);
+EXTERN void Ord_ListMergeList(lsList list1, lsList list2, Ord_ListMergeMethod method);
+EXTERN lsList Ord_NetworkOrderRoots(Ntk_Network_t *network, Ord_RootMethod rootMethod, lsList partialOrder, boolean verbose);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _ORD */
Index: vis_dev/vis-2.3/src/ord/ord.make
===================================================================
--- vis_dev/vis-2.3/src/ord/ord.make	(revision 14)
+++ vis_dev/vis-2.3/src/ord/ord.make	(revision 14)
@@ -0,0 +1,4 @@
+CSRC += ordCmd.c ordIo.c ordMain.c ordNodes.c ordPerm.c ordRoots.c
+HEADERS += ord.h ordInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/ord/ordCmd.c
===================================================================
--- vis_dev/vis-2.3/src/ord/ordCmd.c	(revision 14)
+++ vis_dev/vis-2.3/src/ord/ordCmd.c	(revision 14)
@@ -0,0 +1,1622 @@
+/**CFile***********************************************************************
+
+  FileName    [ordCmd.c]
+
+  PackageName [ord]
+
+  Synopsis    [Command interface to the ordering package.]
+
+  Author      [Adnan Aziz, Tom Shiple, Serdar Tasiran]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ordInt.h"
+
+static char rcsid[] UNUSED = "$Id: ordCmd.c,v 1.37 2005/05/19 03:22:55 awedh Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+static jmp_buf timeOutEnv;
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandStaticOrder(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandReadOrder(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandWriteOrder(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandDynamicVarOrdering(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandPrintBddStats(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static Ord_OrderType StringConvertToOrderType(char *string);
+static bdd_reorder_type_t StringConvertToDynOrderType(char *string);
+static char * DynOrderTypeConvertToString(bdd_reorder_type_t method);
+static boolean NetworkCheckSuppliedNodeList(Ntk_Network_t * network, lsList suppliedNodeList, Ord_OrderType orderType);
+static void TimeOutHandle(void);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the order package.]
+
+  SideEffects []
+
+  SeeAlso     [Ord_End]
+
+******************************************************************************/
+void
+Ord_Init(void)
+{
+  Cmd_CommandAdd("static_order", CommandStaticOrder, 0);
+  Cmd_CommandAdd("read_order", CommandReadOrder, 0);
+  Cmd_CommandAdd("write_order", CommandWriteOrder, 0);
+  Cmd_CommandAdd("dynamic_var_ordering", CommandDynamicVarOrdering, 0);
+  Cmd_CommandAdd("print_bdd_stats", CommandPrintBddStats, 0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Ends the order package.]
+
+  SideEffects []
+
+  SeeAlso     [Ord_Init]
+
+******************************************************************************/
+void
+Ord_End(void)
+{
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks that all nodes corresponding to orderType have MDD ids.]
+
+  Description [For each node of network that falls in the class given by
+  orderType, checks that the node has an MDD id.  If all such nodes have MDD
+  ids, return 1, else returns 0.  orderType can have one of 3 values:
+  Ord_All_c, checks all nodes of network; Ord_InputAndLatch_c, checks all
+  combinational inputs and latch next states; Ord_NextStateNode_c, checks all
+  next state nodes.  Returns 0 on the first such node not having an MDD id,
+  and writes an error message in error_string.  Also returns 0 if the network
+  doesn't have an MDD manager.]
+
+  SideEffects []
+
+******************************************************************************/
+boolean
+Ord_NetworkTestAreVariablesOrdered(
+  Ntk_Network_t * network,
+  Ord_OrderType  orderType)
+{
+  lsGen          gen;
+  Ntk_Node_t    *node;
+  mdd_manager   *mddManager = Ntk_NetworkReadMddManager(network);
+  
+  assert((orderType == Ord_All_c) || (orderType == Ord_InputAndLatch_c)
+         || (orderType == Ord_NextStateNode_c));
+
+  if (mddManager == NIL(mdd_manager)) {
+    error_append("network doesn't have an MDD manager\n");
+  return 0;
+  }
+
+  /*
+   * Next state nodes are included by all 3 order types.
+   */
+  Ntk_NetworkForEachNode(network, gen, node) {
+    if ((orderType == Ord_All_c) || Ntk_NodeTestIsNextStateNode(node)) {
+      if (Ntk_NodeReadMddId(node) == NTK_UNASSIGNED_MDD_ID) {
+        error_append("node ");
+        error_append(Ntk_NodeReadName(node));
+        error_append(" not ordered\n");
+        (void) lsFinish(gen);
+        return 0;
+      }
+    }
+    else if ((orderType == Ord_InputAndLatch_c)
+             && Ntk_NodeTestIsCombInput(node)) {
+      if (Ntk_NodeReadMddId(node) == NTK_UNASSIGNED_MDD_ID) {
+        error_append("node ");
+        error_append(Ntk_NodeReadName(node));
+        error_append(" not ordered\n");
+        (void) lsFinish(gen);
+        return 0;
+      }
+    }
+    /* else, this node is not included by orderType */
+  }
+
+  return 1;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the static_order command.]
+
+  SideEffects []
+
+  CommandName [static_order]
+
+  CommandSynopsis [order the MDD variables of the flattened network]
+
+  CommandArguments [\[-a\] \[-h\] \[-n &lt;method&gt;\] \[-o &lt;type&gt;\] 
+  \[-r &lt;method&gt;\] -s &lt;type&gt; \[-t &lt;timeOut&gt;\] \[-v #\]
+  &lt;file&gt;] 
+
+  CommandDescription [Order the MDD variables of the flattened network.  MDD
+  variables must be created before MDDs can be built.  Networks with
+  combinational cycles cannot be ordered.  If the MDD variables have already
+  been ordered, then this command does nothing.  To undo the current ordering,
+  reinvoke the command <tt>flatten_hierarchy</tt>. 
+  <p>
+  
+
+  Command options:<p>
+
+  <dl>
+
+  <dt> -a
+  <dd> Order each next state variable immediately following the variables in
+  the support of the corresponding next state function.  By default, each next
+  state variable is placed immeadiately following the corresponding present
+  state variable.  It has been observed experimentally that ordering the NS
+  variable after the PS variable is almost always better; however, as a last
+b  resort, you might want to try this option.<p>
+
+  Unless the -a flag is set, the PS and NS variables corresponding to latches
+  are grouped together and cannot be separated by dynamic reordering. (This is
+  done even when the ordering is read from a file - adjacent PS/NS vars in the
+  file are grouped).<p>
+  
+  <dt> -h
+  <dd> Print the command usage.<p>
+  
+  <dt> -n &lt;method&gt;
+
+  <dd> Specify which node ordering method to use.  Node ordering is the
+  process of computing a total ordering on all the network nodes.  This
+  ordering is then projected onto the set of nodes specified by <tt>-o
+  type</tt>. In the complexity measures below, n is the number of network
+  nodes, E is the number of network edges, and k is the number of
+  latches. "Method" must be one of the following:<p>
+
+  <b>interleave:</b> (default) Uses Algorithm 2 of Fujii et al.,
+  "Interleaving Based Variable Ordering Methods for OBDDs", ICCAD 1993.
+  The complexity is O(E+nlog(n)).<p>
+
+  <b>append:</b> Uses the algorithm of Malik, et al. "Logic Verification using
+  Binary Decision Diagrams in a Logic Synthesis Environment," ICCAD,
+  1988. Nodes are visited in DFS order, and appended to a global order list in
+  the order they are visited.  The fanins of a node are visited in order of
+  decreasing depth. The roots of the DFS are visited in the order determined
+  by the <tt>-r method</tt>.  The complexity is O(E+nlog(n)).<p>
+  
+  <b>merge_left:</b> Uses an algorithm alluded to in Fujii et al.,
+  "Interleaving Based Variable Ordering Methods for OBDDs", ICCAD 1993. Nodes
+  are visited in DFS order.  At a given node g, its fanins are visited in
+  order of decreasing depth.  For each fanin fi, a total order is computed for
+  all the nodes in the transitive fanin (TFI) of fi, including fi itself.
+  This ordering is merged into the combined ordering from fanins of higher
+  priority.  After processing all of the fanins, the result is a total
+  ordering on all TFI nodes of g.  Finally, g is appended to the end of this
+  ordering, yielding a topological ordering. For example if the ordering for
+  f1 is list1 = (a,b,d,f1) and for f2 is list2=(c,d,e,f2), and f1 has greater
+  depth than f2, then the ordering for g is (c,a,b,d,e,f2,f1,g). The merge is
+  done by inserting into list1 those nodes in list2 not already in list1, in
+  such a way that the inserted nodes remain as close as possible to their left
+  neighbors in list2 ("insert as far left as possible"). The roots of the DFS
+  are merged in the order determined by <tt>-r method</tt>.  The complexity is
+  O(n^2) (currently, there is a bug which causes more memory to be consumed
+  than necessary).<p>
+
+  <b>merge_right:</b> Same as <tt>merge_left</tt>, except that the merge is
+  done in such a way that the inserted nodes remain as close as possible to
+  their right neighbors in list2 ("insert as far right as possible"). For the
+  example above, the ordering for g is (a,b,c,d,f1,e,f2,g).  It has been
+  observed experimentally that neither <tt>merge_left</tt> nor
+  <tt>merge_right</tt> is superior to the other; there are cases where
+  verification times out with <tt>merge_left</tt> but not
+  <tt>merge_right</tt>, and vice versa.<p>
+
+
+  <dt> -o &lt;type&gt; <dd> Specify the network nodes for which MDD variables
+  should be created.  Type can be one of the following:<p>
+
+  <b>all:</b> Order all the nodes of the network.  This is normally not used.<p>
+
+  <b>input_and_latch:</b> (default) Order the primary inputs, pseudo
+  inputs, latches, and next state variables.  This is the minimum set of nodes
+  that need to be ordered to perform operations on FSMs (e.g. model checking,
+  reachability).  For purely combinational circuits, just the primary and
+  pseudo inputs are ordered.<p>
+
+  
+  <dt> -r &lt;method&gt;
+
+  <dd> Specify which root ordering method to use.  The "roots" of a network
+  refer to the roots of the cones of logic driving the combinational outputs
+  (data latch inputs, initial state latch inputs, and primary outputs) of a
+  network. Root ordering is used to determine in which order to visit the
+  roots of the network for the DFS carried out in node ordering (see
+  <tt>-n</tt>). "Method" must be one of the following:<p>
+
+  <b>depth:</b> (default for 30 or more latches) Roots are ordered based on
+  logic depth (i.e. longest path to a combinational input).  Greater depth
+  roots appear earlier in the ordering. All data latch inputs appear before
+  all other combinational outputs. The complexity is O(E+nlog(n)). It has been
+  observed experimentally that <tt>mincomm</tt> produces superior orderings to
+  <tt>depth</tt>.  However, the complexity of the <tt>mincomm</tt> algorithm
+  is such that it cannot produce orderings for designs with more than a
+  hundred or so latches.  Hence, for big designs, use <tt>depth</tt>, followed
+  optionally by <tt>dynamic_var_ordering</tt>.<p>
+
+  <b>mincomm:</b> (default for less than 30 latches) Uses the algorithm of
+  Aziz, et al. "BDD Variable Ordering for Interacting Finite State Machines,"
+  DAC, 1994. First, the latches are ordered to decrease a communication
+  complexity bound (where backward edges are more expensive than forward
+  edges) on the latch communication graph. This directly gives an ordering for
+  the data latch inputs.  The remaining combinational outputs are ordered
+  after the data latch inputs, in decreasing order of their depth. The total
+  complexity is O(nlog(n)+E+k^3).<p>
+
+
+  <dt> -s &lt;type&gt;
+
+  <dd> Used in conjunction with <tt>&lt;file&gt;</tt> to specify which
+  nodes are supplied in the ordering file. Type can be one of the following
+  (there is no default):<p>
+
+  <b>all:</b> The ordering file supplies all the nodes of the network.
+  The ordering generated is the supplied order, projected onto the set of nodes
+  specified by <tt>-o</tt>.<p>
+
+  <b>input_and_latch:</b> The ordering file supplies the primary inputs,
+  pseudo inputs, latches, and next state variables. The ordering generated is
+  exactly what is supplied (in the case of <tt>-o input_and_latch</tt>). <tt>-o
+  all</tt> is incompatible with <tt>-s input_and_latch</tt>.<p>
+
+  <b>next_state_node:</b> The ordering file supplies next state
+  variables. During the ordering algorithm, the next state functions are
+  visited in the order in which their corresponding next state variables
+  appear in the file. The order of the next state variables in the ordering
+  generated is not necessarily maintained.<p>
+
+  <b>partial:</b> The ordering file supplies an arbitrary subset of nodes
+  of the network. The ordering algorithm works by finding a total ordering on
+  all the nodes (independent of the ordering supplied), then merging the
+  computed order into the supplied order (maintaining the relative order of
+  the supplied order), and then projecting the resulting ordering onto the set
+  of nodes specified by <tt>-o</tt>.<p>
+  
+
+  <dt> -t &lt;timeOut&gt;
+  <dd> Time in seconds allowed to perform static ordering.  If the flattened
+  network has more than a couple hundred latches and you are using option
+  <tt>-r mincomm</tt>, then you might want to set a timeOut to limit the
+  allowed time.  The default is no limit.<p>
+
+  <dt> -v #
+  <dd> Print debug information.
+  <dd>
+
+  0 Nothing is printed out.  This is the default.<p>
+  
+  >= 1 Prints the nodes read from the input file (satisfying the supplied
+  order type); prints the root order used for exploring the network.<p>
+  
+  >= 2 Prints the depth of nodes.<p>
+  
+  >= 3 Prints the ordering computed at each node.<p>
+
+  
+  <dt> &lt;file&gt;
+
+  <dd> A file containing names of network nodes, used to specify a variable
+  ordering. The name of a node is the full hierarchical path name, starting
+  from the current hierarchical node.  A node should appear at most once in
+  the file.  Each node name should appear at the beginning of a new line, with
+  no white space preceeding it.  The end of a node name is marked by white
+  space, and any other text on the rest of the line is ignored.  Any line
+  starting with "#" or white space is ignored. See <tt>write_order</tt>
+  for a sample file. Note that the variable ordering cannot be specified at
+  the bit-level; it can only be specified at the multi-valued variable level.
+
+  </dl>
+  ]
+
+  
+  SeeAlso     [CommandWriteOrder]
+
+******************************************************************************/
+static int
+CommandStaticOrder(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int                   c;
+  FILE                 *fp;
+  static int            timeOutPeriod;
+  static int            verbose;
+  static Ord_NodeMethod nodeMethod;
+  static Ord_RootMethod rootMethod;
+  static Ord_OrderType  suppliedOrderType;
+  static Ord_OrderType  generatedOrderType;
+  static boolean        nsAfterSupport;
+  lsList                suppliedNodeList = (lsList) NULL;
+				/* list of Ntk_Node_t * */
+  Ntk_Network_t        *network;
+
+  /*
+   * These are the default values.  These variables must be declared static
+   * to avoid lint warnings.  Since they are static, we must reinitialize
+   * them outside of the variable declarations.
+   */
+  timeOutPeriod      = 0;  
+  verbose            = 0;
+  nodeMethod         = Ord_NodesByDefault_c;
+  rootMethod         = Ord_RootsByDefault_c;
+  suppliedOrderType  = Ord_Unassigned_c;   /* default */
+  generatedOrderType = Ord_InputAndLatch_c;/* default */
+  nsAfterSupport     = FALSE;              /* default */
+  
+  /*
+   * Parse the command line.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "av:o:s:t:n:r:h")) != EOF) {
+    switch (c) {
+      case 'a':
+        nsAfterSupport = TRUE;
+        break;
+      case 'h':
+        goto usage;
+      case 'v':
+        verbose = atoi(util_optarg);
+        break;
+      case 't':
+        timeOutPeriod = atoi(util_optarg);
+        break;
+      case 'o':
+        generatedOrderType = StringConvertToOrderType(util_optarg);
+        if ((generatedOrderType == Ord_NextStateNode_c)
+            || (generatedOrderType == Ord_Partial_c)) { 
+          (void) fprintf(vis_stderr, "disallowed output order type: %s\n", util_optarg);
+          goto usage;
+        }
+        else if (generatedOrderType == Ord_Unassigned_c) {
+          (void) fprintf(vis_stderr, "unknown output order type: %s\n", util_optarg);
+          goto usage;
+        }
+        break;
+      case 's':
+        suppliedOrderType = StringConvertToOrderType(util_optarg);
+        if (suppliedOrderType == Ord_Unassigned_c) {
+          (void) fprintf(vis_stderr, "unknown input order type: %s\n", util_optarg);
+          goto usage;
+        }
+        break;
+      case 'n':
+	if (strcmp("interleave", util_optarg) == 0) { 
+          nodeMethod = Ord_NodesByInterleaving_c;
+        }
+        else if (strcmp("merge_left", util_optarg) == 0) { 
+          nodeMethod = Ord_NodesByMergingLeft_c;
+        }
+        else if (strcmp("merge_right", util_optarg) == 0) { 
+          nodeMethod = Ord_NodesByMergingRight_c;
+        }
+        else if (strcmp("append", util_optarg) == 0) { 
+          nodeMethod = Ord_NodesByAppending_c;
+        }
+        else {
+          (void) fprintf(vis_stderr, "unknown node order method: %s\n", util_optarg);
+          goto usage;
+        }
+        break;
+      case 'r':
+        if (strcmp("depth", util_optarg) == 0) { 
+          rootMethod = Ord_RootsByDepth_c;
+        }
+        else if (strcmp("mincomm", util_optarg) == 0) { 
+          rootMethod = Ord_RootsByPerm_c;
+        }
+        else {
+          (void) fprintf(vis_stderr, "unknown root order method: %s\n", util_optarg);
+          goto usage;
+        }
+        break;
+      default:
+        goto usage;
+    }
+  }
+
+  network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+  if (network == NIL(Ntk_Network_t)) {
+    return 1;
+  }
+
+  if ((suppliedOrderType == Ord_InputAndLatch_c) && (generatedOrderType == Ord_All_c)) {
+    (void) fprintf(vis_stderr, "-o all -s input_and_latch not currently supported\n");
+    return 1;
+  }
+
+  /*
+   * The minimum set of variables that can be ordered are those specified by
+   * Ord_InputAndLatch_c.  If these have already been ordered, then just return.
+   */
+  if (Ord_NetworkTestAreVariablesOrdered(network, Ord_InputAndLatch_c)) {
+    (void) fprintf(vis_stderr, "Variables already ordered. ");
+    (void) fprintf(vis_stderr, "Reinvoke flatten_hierarchy to undo variable ordering.\n");
+    return 1;
+  }
+  
+    
+  /*
+   * Process the input ordering file.
+   */
+  if (suppliedOrderType == Ord_Unassigned_c) {
+    if (argc - util_optind > 0) {
+      (void) fprintf(vis_stderr, "must specify -s if supplying order file\n");
+      goto usage;
+    }
+  }
+  else {
+    if (argc - util_optind == 0) {
+      (void) fprintf(vis_stderr, "order file not provided\n");
+      goto usage;
+    }
+    else if (argc - util_optind > 1) {
+      (void) fprintf(vis_stderr, "too many arguments\n");
+      goto usage;
+    }
+
+    fp = Cmd_FileOpen(argv[util_optind], "r", NIL(char *), 0);
+    if (fp == NIL(FILE)) {
+      (void) fprintf(vis_stderr, "File %s is not readable, please check if it exists\n", argv[util_optind]);
+      return 1;
+    }
+    else {
+      boolean status;
+      
+      error_init();
+      status = Ord_FileReadNodeList(fp, network, &suppliedNodeList, verbose);
+      if (status == FALSE) {
+        (void) fprintf(vis_stderr, "Error reading ordering file:\n");
+        (void) fprintf(vis_stderr, "%s", error_string());
+        (void) fprintf(vis_stderr, "Cannot perform static ordering.\n");
+        (void) fclose(fp);
+        return 1;
+      }
+      else if (NetworkCheckSuppliedNodeList(network, suppliedNodeList,
+                                            suppliedOrderType) == FALSE) { 
+        (void) fprintf(vis_stderr, "Incorrect nodes supplied:\n");
+        (void) fprintf(vis_stderr, "%s", error_string());
+        (void) fprintf(vis_stderr, "Cannot perform static ordering.\n");
+        (void) fclose(fp);
+        (void) lsDestroy(suppliedNodeList, (void (*) (lsGeneric)) NULL);
+        return 1;
+      }
+      else {
+        (void) fclose(fp);
+        if (verbose > 0) {
+          (void) fprintf(vis_stdout, "\nNodes supplied in ordering file, ");
+          (void) fprintf(vis_stdout, "according to -s option: \n");
+          OrdNodeListWrite(vis_stdout, suppliedNodeList);
+        }
+      }
+    }
+  }
+  
+  
+  /*
+   * In order for static ordering to proceed, network must not have any
+   * combinational cycles.
+   */
+  error_init();
+  if(Ntk_NetworkTestIsAcyclic(network) == 0) {
+    (void) fprintf(vis_stderr, "Combinational cycle found: ");
+    (void) fprintf(vis_stderr, "%s\n", error_string());
+    (void) fprintf(vis_stderr, "cannot perform static ordering\n");
+    if (suppliedOrderType != Ord_Unassigned_c) {
+      (void) lsDestroy(suppliedNodeList, (void (*) (lsGeneric)) NULL);
+    }
+    return 1;
+  }
+
+  /* Start the timer before calling the variable ordering routine. */
+  if (timeOutPeriod > 0){
+    (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
+    (void) alarm(timeOutPeriod);
+    if (setjmp(timeOutEnv) > 0) {
+      (void) fprintf(vis_stderr, "Timeout occurred after %d seconds.\n", timeOutPeriod);
+      alarm(0);
+      return 1;
+    }
+  }
+
+  /*
+   * Order the variables.
+   */
+  Ord_NetworkOrderVariables(network, rootMethod, nodeMethod, nsAfterSupport, 
+                            generatedOrderType, suppliedOrderType,
+                            suppliedNodeList, verbose);
+
+  if (suppliedOrderType != Ord_Unassigned_c) {
+    (void) lsDestroy(suppliedNodeList, (void (*) (lsGeneric)) NULL);
+  }
+
+  /*
+   * As a sanity check, make sure that all the variables in generatedOrderType
+   * have an MDD id. 
+   */
+  assert(Ord_NetworkTestAreVariablesOrdered(network, generatedOrderType));
+  
+  alarm(0);
+  return 0;  /* Everything okay */
+
+  usage:
+  (void) fprintf(vis_stderr, "usage: static_order [-a] [-h] [-n method] [-o type] [-r method] -s type [-t time] [-v #] file\n");
+  (void) fprintf(vis_stderr, "   -a        order NS variables after support\n");
+  (void) fprintf(vis_stderr, "   -h        print the command usage\n");
+  (void) fprintf(vis_stderr, "   -n method node ordering method\n");
+  (void) fprintf(vis_stderr, "             (interleave (default), append, merge_left, merge_right)\n");
+  (void) fprintf(vis_stderr, "   -o type   nodes to order (all, input_and_latch (default))\n");
+  (void) fprintf(vis_stderr, "   -r method root ordering method (depth, mincomm (default for < 30 latches))\n");
+  (void) fprintf(vis_stderr, "   -s type   nodes in file (all, input_and_latch, next_state_node, partial)\n");
+  (void) fprintf(vis_stderr, "   -t time   time out period (in seconds)\n");
+  (void) fprintf(vis_stderr, "   -v #      verbosity level\n");
+  (void) fprintf(vis_stderr, "   file      supplied ordering of nodes\n");
+
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the read_order command.]
+
+  SideEffects []
+
+  CommandName [read_order]
+
+  CommandSynopsis [Read and reorder variable order from a file.]
+
+  CommandArguments [\[-h\] \[-v\] \[&lt;file&gt;\]] 
+
+  CommandDescription [This command reads variable order from a file and
+  reorder variable order according to the order. This command can be used
+  any time after static_order command. However, the users should notice that
+  there is a possibility to get BDD blowups during this command.
+  <p>
+  
+
+  Command options:<p>
+
+  <dl>
+
+  <dt> -h
+  <dd> Print the command usage.<p>
+
+  <dt> -g &lt;group&gt;
+
+  <dd> Specify whether to group present and next state variables or not.<p>
+
+  <b>0:</b> Do not group.<p>
+
+  <b>1:</b> Do group (default).<p>
+
+  <dt> -v
+  <dd> Print debug information.
+  <dd>
+  
+  <dt> &lt;file&gt;
+
+  <dd> A file containing names of network nodes, used to specify a variable
+  ordering. The name of a node is the full hierarchical path name, starting
+  from the current hierarchical node.  A node should appear at most once in
+  the file.  Each node name should appear at the beginning of a new line, with
+  no white space preceeding it.  The end of a node name is marked by white
+  space, and any other text on the rest of the line is ignored.  Any line
+  starting with "#" or white space is ignored. See <tt>write_order</tt>
+  for a sample file. Note that the variable ordering cannot be specified at
+  the bit-level; it can only be specified at the multi-valued variable level.
+
+  </dl>
+  ]
+
+  
+  SeeAlso     [CommandStaticOrder CommandWriteOrder]
+
+******************************************************************************/
+static int
+CommandReadOrder(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int		c, status;
+  FILE		*fp;
+  int		verbose = 0;
+  int		group = 0;
+  lsList	suppliedNodeList = (lsList)NULL; /* list of Ntk_Node_t * */
+  Ntk_Network_t	*network;
+  mdd_manager	*mddMgr;
+
+  if (bdd_get_package_name() != CUDD) {
+    fprintf(vis_stderr,
+	   "** ord error: read_order can be used only with the CUDD package\n");
+  }
+
+  /*
+   * Parse the command line.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "hg:v")) != EOF) {
+    switch (c) {
+      case 'h':
+        goto usage;
+      case 'g':
+        group = atoi(util_optarg);
+        break;
+      case 'v':
+        verbose = 1;
+        break;
+      default:
+        goto usage;
+    }
+  }
+
+  network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+  if (network == NIL(Ntk_Network_t)) {
+    return 1;
+  }
+
+  if (!Ord_NetworkTestAreVariablesOrdered(network, Ord_InputAndLatch_c)) {
+    (void) fprintf(vis_stderr,
+		   "** ord error: static_order was not called yet.\n");
+    return 1;
+  }
+
+  /*
+   * Process the input ordering file.
+   */
+  if (argc - util_optind == 0) {
+    (void) fprintf(vis_stderr, "order file not provided\n");
+    goto usage;
+  }
+  else if (argc - util_optind > 1) {
+    (void) fprintf(vis_stderr, "too many arguments\n");
+    goto usage;
+  }
+
+  fp = Cmd_FileOpen(argv[util_optind], "r", NIL(char *), 0);
+  if (fp == NIL(FILE)) {
+    return 1;
+  } else {
+    boolean status;
+    
+    error_init();
+    status = Ord_FileReadNodeList(fp, network, &suppliedNodeList, verbose);
+    if (status == FALSE) {
+      (void) fprintf(vis_stderr, "Error reading ordering file:\n");
+      (void) fprintf(vis_stderr, "%s", error_string());
+      (void) fprintf(vis_stderr, "Cannot perform static ordering.\n");
+      (void) fclose(fp);
+      return 1;
+    } else if (NetworkCheckSuppliedNodeList(network, suppliedNodeList,
+					    Ord_InputAndLatch_c) == FALSE) { 
+      (void) fprintf(vis_stderr, "Incorrect nodes supplied:\n");
+      (void) fprintf(vis_stderr, "%s", error_string());
+      (void) fprintf(vis_stderr, "Cannot perform read_order.\n");
+      (void) fclose(fp);
+      (void) lsDestroy(suppliedNodeList, (void (*) (lsGeneric)) NULL);
+      return 1;
+    } else {
+      (void) fclose(fp);
+      if (verbose > 0) {
+	(void) fprintf(vis_stdout, "\nNew variable order from file %s:\n",
+			argv[util_optind]);
+	OrdNodeListWrite(vis_stdout, suppliedNodeList);
+      }
+    }
+  }
+  
+  /*
+   * Reorder the variables.
+   */
+  mddMgr = Ntk_NetworkReadMddManager(network);
+  status = OrdMakeNewVariableOrder(mddMgr, suppliedNodeList, group, verbose);
+
+  (void) lsDestroy(suppliedNodeList, (void (*) (lsGeneric)) NULL);
+  if (status)
+    return 1;
+
+  alarm(0);
+  return 0;  /* Everything okay */
+
+  usage:
+  (void) fprintf(vis_stderr, "usage: read_order [-g #] [-h] [-v] file\n");
+  (void) fprintf(vis_stderr, "   -h        print the command usage\n");
+  (void) fprintf(vis_stderr, "   -g #      ps/ns variables grouping\n");
+  (void) fprintf(vis_stderr, "             0 : do not group ps/ns\n");
+  (void) fprintf(vis_stderr, "             1 : group ps/ns (default)\n");
+  (void) fprintf(vis_stderr, "   -v        verbosity on\n");
+  (void) fprintf(vis_stderr, "   file      variable order file\n");
+
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the write_order command.]
+
+  SideEffects [none]
+
+  CommandName [write_order]
+
+  CommandSynopsis [write the current order of the MDD variables of the
+  flattened network] 
+
+  CommandArguments [\[-h\] \[-o &lt;type&gt;\] \[&lt;file&gt;\]]
+
+  CommandDescription [Write the current order of the MDD variables of the
+  flattened network.  If no file name is specified, the output is written to
+  stdout. A sample output is shown here.
+
+  <pre>
+  # name                 type            mddId vals levs
+  system.choosing0      primary-input       31    2 (61)
+  system.p0.pc          latch               32   11 (62, 63, 64, 65)
+  </pre>
+
+  The first column gives the full hierarchical path name of the node, starting
+  from the current hierarchical node. The second column gives the type of the
+  node in the flattened network (see the command <tt>print_network</tt>).  The third
+  column gives the MDD id of the node; this can be thought of as just another
+  name for the node.  The fourth column gives the number of values that the
+  multi-valued variable at the output of the node can assume.  The last column
+  gives the levels of the BDD variables that encode the multi-valued variable
+  (0 is the topmost level of the BDD). <p>
+
+  The bits of a multi-valued variable need not appear consecutively (due to
+  dynamic variable ordering).  Each node appears at most once in the output
+  file. The nodes in the file appear in ascending order of the lowest level
+  bit in the encoding of the node's multi-valued variable (e.g. a node with
+  levels (12, 73) will appear before a node with levels (17, 21, 25)).<p>
+  
+  To specify a variable ordering for static_order, a convenient tactic is to
+  write out the current ordering, edit the file to rearrange the ordering (or
+  comment out some nodes, using "#"), and then read the file back in using
+  <tt>static_order</tt>. Note that everything after the first column is
+  ignored when the file is read in.<p>
+
+  Command options:<p>  
+  
+  <dl>
+
+  <dt> -h
+  <dd> Print the command usage.<p>
+
+  <dt> -o &lt;type&gt;
+  <dd> Specify the network nodes to write out.  Type can be one of the following:<p>
+
+  <b>all:</b> Write out all the nodes of the network.  This option is
+  allowed only if all variables have been ordered.<p>
+
+  <b>input_and_latch:</b> (default) Write out the primary inputs, pseudo
+  inputs, latches, and next state variables.  <p>
+
+  <b>next_state_node:</b> Write out the next state variables (node type is
+  "shadow").  This file can be modified and read back in using the
+  <tt>static_order -s next_state_node</tt> command.<p>
+  
+  <dt> &lt;file&gt;
+
+  <dd> File to which to write the ordering.  By default, the ordering is
+  written to stdout.<p>
+  
+  </dl>]
+
+******************************************************************************/
+static int
+CommandWriteOrder(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int            c;
+  FILE          *fp;
+  int            status;
+  Ord_OrderType  orderType = Ord_InputAndLatch_c; /* default */
+  Ntk_Network_t *network;
+  
+  /*
+   * Parse the command line.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "ho:")) != EOF) {
+    switch (c) {
+      case 'h':
+        goto usage;
+      case 'o':
+        orderType = StringConvertToOrderType(util_optarg);
+        if (orderType == Ord_Partial_c) { 
+          (void) fprintf(vis_stderr, "disallowed output order type: %s\n", util_optarg);
+          goto usage;
+        }
+        else if (orderType == Ord_Unassigned_c) {
+          (void) fprintf(vis_stderr, "unknown output order type: %s\n", util_optarg);
+          goto usage;
+        }
+        break;
+      default:
+        goto usage;
+    }
+  }
+
+  network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+  if (network == NIL(Ntk_Network_t)) {
+    return 1;
+  }
+
+  /*
+   * Open the destination file.
+   */
+  if (argc - util_optind == 0) {
+    fp = Cmd_FileOpen("-", "w", NIL(char *), /* silent */0);
+  }
+  else if (argc - util_optind == 1) {
+    fp = Cmd_FileOpen(argv[util_optind], "w", NIL(char *), /* silent */0);
+  }
+  else {
+    goto usage;
+  }
+  if (fp == NIL(FILE)) {
+    return 1;
+  }
+
+  error_init();
+  if (Ord_NetworkPrintVariableOrder(fp, network, orderType) == 0) {
+    (void) fprintf(vis_stderr, "Not all nodes are ordered: ");
+    (void) fprintf(vis_stderr, "%s", error_string());
+    status = 1;
+  }
+  else {
+    status = 0;  /* success */
+  }
+
+  if (fp != stdout) {
+    (void) fclose(fp);
+  }
+  return (status);
+  
+usage:
+  (void) fprintf(vis_stderr, "usage: write_order [-h] [-o type] [file]\n");
+  (void) fprintf(vis_stderr, "   -h        print the command usage\n");
+  (void) fprintf(vis_stderr, "   -o type   nodes to write (all, input_and_latch (default), next_state_node)\n");
+  (void) fprintf(vis_stderr, "   file      output file name\n");
+
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the dynamic_var_ordering command.]
+
+  SideEffects []
+
+  CommandName [dynamic_var_ordering]
+
+  CommandSynopsis [control the application of dynamic variable ordering]
+
+  CommandArguments [ \[-d\] \[-e &lt;method&gt;\] \[-f &lt;method&gt;\]
+  \[-h\]]
+
+  CommandDescription [Control the application of dynamic variable ordering to the
+  flattened network. Dynamic ordering is a technique to reorder the MDD
+  variables to reduce the size of the existing MDDs.  When no options are
+  specified, the current status of dynamic ordering is displayed.  At most one
+  of the options -e, -f, and -d should be specified.  The commands
+  <tt>flatten_hierarchy</tt> and <tt>static_order</tt> must be invoked before
+  this command.<p>
+
+  Dynamic ordering may be time consuming, but can often reduce the size of the
+  MDDs dramatically.  The good points to invoke dynamic ordering explicitly
+  (using the -f option) are after the commands <tt>build_partition_mdds</tt>
+  and <tt>print_img_info</tt>.  If dynamic ordering finds a good ordering,
+  then you may wish to save this ordering (using <tt>write_order</tt>) and
+  reuse it (using <tt>static_order -s</tt>) in the future. A common sequence
+  used to get a good ordering is the following:<p>
+
+  <pre>
+  init_verify
+  print_img_info
+  dynamic_var_ordering -f sift
+  write_order <file>
+  flatten_hierarchy
+  static_order -s input_and_latch -f <file>
+  build_partition_mdds
+  print_img_info
+  dynamic_var_ordering -f sift
+  </pre>  
+  
+  <p>For many large examples, there is no single best variable order,
+  or that order is hard to find.  For example, the best ordering
+  during partitioning of the network may be different from the best
+  ordering during a model check. In that case you can use automatic
+  reordering, using the <tt>-e</tt> option. This will trigger
+  reordering whenever the total size of the MDD increases by a certain
+  factor. Often, the <tt>init</tt> command is replaced by the
+  following sequence:
+  
+  <pre>
+  flatten_hierarchy 
+  static_order
+  dynamic_var_ordering -e sift
+  build_partition_mdds
+  </pre>
+  
+  Command options:<p>  
+
+  <dl>
+
+  <dt> -d
+  <dd> Disable dynamic ordering from triggering automatically.<p>
+  
+  <dt> -e &lt;method&gt;
+  <dd> Enable dynamic ordering to trigger automatically whenever a certain
+  threshold on the overall MDD size is reached. "Method" must be one of the following:<p>
+
+  <b>window:</b> Permutes the variables within windows of three adjacent
+  variables so as to minimize the overall MDD size.  This process is repeated
+  until no more reduction in size occurs.<p>
+
+  <b>sift:</b> Moves each variable throughout the order to find an optimal
+  position for that variable (assuming all other variables are fixed).  This
+  generally achieves greater size reductions than the window method, but is
+  slower.<p>
+  
+  The following methods are only available if VIS has been linked with the Bdd
+  package from the University of Colorado (cuBdd).</b><p>
+
+  <b>random:</b> Pairs of variables are randomly chosen, and swapped in the
+  order. The swap is performed by a series of swaps of adjacent variables. The
+  best order among those obtained by the series of swaps is retained. The
+  number of pairs chosen for swapping equals the number of variables in the
+  diagram.<p>
+
+  <b>random_pivot:</b> Same as <b>random</b>, but the two variables are chosen
+  so that the first is above the variable with the largest number of nodes, and
+  the second is below that variable.  In case there are several variables tied
+  for the maximum number of nodes, the one closest to the root is used.<p>
+
+  <b>sift_converge:</b> The <b>sift</b> method is iterated until no further
+  improvement is obtained.<p>
+
+  <b>symmetry_sift:</b> This method is an implementation of symmetric
+  sifting. It is similar to sifting, with one addition: Variables that become
+  adjacent during sifting are tested for symmetry. If they are symmetric, they
+  are linked in a group. Sifting then continues with a group being moved,
+  instead of a single variable.<p>
+
+  <b>symmetry_sift_converge:</b> The <b>symmetry_sift</b> method is iterated
+  until no further improvement is obtained.<p>
+
+  <b>window{2,3,4}:</b> Permutes the variables within windows of n adjacent
+  variables, where "n" can be either 2, 3 or 4, so as to minimize the overall
+  MDD size.<p>
+
+  <b>window{2,3,4}_converge:</b> The <b>window{2,3,4}</b> method is iterated
+  until no further improvement is obtained.<p>
+
+  <b>group_sift:</b> This method is similar to <b>symmetry_sift</b>,
+  but uses more general criteria to create groups.<p>
+
+  <b>group_sift_converge:</b> The <b>group_sift</b> method is iterated until no
+  further improvement is obtained.<p>
+
+  <b>lazy_sift:</b> This method is similar to <b>group_sift</b>, but the
+  creation of groups takes into account the pairing of present and next state
+  variables.<p>
+
+  <b>annealing:</b> This method is an implementation of simulated annealing for
+  variable ordering. This method is potentially very slow.<p>
+
+  <b>genetic:</b> This method is an implementation of a genetic algorithm for
+  variable ordering. This method is potentially very slow.<p>
+
+  <dt> -f &lt;method&gt;
+  <dd> Force dynamic ordering to be invoked immediately.  The values for
+  method are the same as in option -e.<p>
+
+  <dt> -h
+  <dd> Print the command usage.
+
+  <dt> -v &lt;#&gt;
+  <dd> Verbosity level. Default is 0. For values greater than 0,
+  statistics pertaining to reordering will be printed whenever
+  reordering occurs.
+  
+  </dl>
+  ]
+  
+******************************************************************************/
+static int
+CommandDynamicVarOrdering(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int                 c;
+  bdd_reorder_type_t  currentMethod;
+  bdd_reorder_type_t  dynOrderingMethod = BDD_REORDER_NONE; /* for lint */
+  boolean             disableFlag       = FALSE;
+  boolean             enableFlag        = FALSE;
+  boolean             forceFlag         = FALSE;
+  Ntk_Network_t      *network;
+  int verbosityFlag = -1;
+  bdd_reorder_verbosity_t reorderVerbosity = BDD_REORDER_VERBOSITY_DEFAULT;
+
+  /*
+   * Parse the command line.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "df:e:hv:")) != EOF) {
+    switch (c) {
+      case 'h':
+        goto usage;
+      case 'f':
+        forceFlag = TRUE;
+        dynOrderingMethod = StringConvertToDynOrderType(util_optarg);
+        if (dynOrderingMethod == BDD_REORDER_NONE) {
+          (void) fprintf(vis_stderr, "unknown method: %s\n", util_optarg);
+          goto usage;
+        }
+        break;
+      case 'e':
+        enableFlag = TRUE;
+        dynOrderingMethod = StringConvertToDynOrderType(util_optarg);
+        if (dynOrderingMethod == BDD_REORDER_NONE) {
+          (void) fprintf(vis_stderr, "unknown method: %s\n", util_optarg);
+          goto usage;
+        }
+        break;
+      case 'd':
+        disableFlag = TRUE;
+        break;
+      case 'v':
+	verbosityFlag = atoi(util_optarg);
+        break;
+    default:
+        goto usage;
+    }
+  }
+  if (c == EOF && argc != util_optind)
+    goto usage;
+
+  switch (verbosityFlag) {
+  case 0: reorderVerbosity = BDD_REORDER_NO_VERBOSITY; break;
+  case 1: reorderVerbosity = BDD_REORDER_VERBOSITY; break;
+  default: reorderVerbosity = BDD_REORDER_VERBOSITY_DEFAULT; break;
+  }
+  
+  /* flatten_hierarchy and static_order must have been invoked already. */
+  network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+  if (network == NIL(Ntk_Network_t)) {
+    return 1;
+  }
+  if (Ord_NetworkTestAreVariablesOrdered(network, Ord_InputAndLatch_c) == FALSE) {
+    (void) fprintf(vis_stderr, "The MDD variables have not been ordered. ");
+    (void) fprintf(vis_stderr, "Use static_order.\n");
+    return 1;
+  }
+
+  /* At most one option is allowed. */
+  if ((disableFlag && enableFlag) || (disableFlag && forceFlag)
+      || (enableFlag && forceFlag)) {
+    (void) fprintf(vis_stderr, "Only one of -d, -f, -e is allowed.\n");
+    return 1;
+  }
+
+  /*
+   * Get the current method for reading and to save in case temporarily
+   * overwritten.
+   */
+  currentMethod = Ntk_NetworkReadDynamicVarOrderingMethod(network);
+  
+  /* If no options are given, then just display current status. */
+  if (!(disableFlag || enableFlag || forceFlag)) {
+    if (currentMethod == BDD_REORDER_NONE) {
+      (void) fprintf(vis_stdout, "Dynamic variable ordering is disabled.\n");
+    }
+    else {
+      (void) fprintf(vis_stdout, "Dynamic variable ordering is enabled ");
+      (void) fprintf(vis_stdout, "with method %s.\n",
+                     DynOrderTypeConvertToString(currentMethod));
+    }
+  }
+
+  if (disableFlag) {
+    if (currentMethod == BDD_REORDER_NONE) {
+      (void) fprintf(vis_stdout, "Dynamic variable ordering is already disabled.\n");
+    }
+    else {
+      (void) fprintf(vis_stdout, "Dynamic variable ordering is disabled.\n");
+      Ntk_NetworkSetDynamicVarOrderingMethod(network, BDD_REORDER_NONE, reorderVerbosity);
+    }
+  }
+
+  /*
+   * Set the dynamic ordering method of the network.  Note that
+   * Ntk_NetworkSetDynamicVarOrderingMethod makes the necessary call to
+   * bdd_dynamic_reordering.
+   */
+  if (enableFlag) {
+    Ntk_NetworkSetDynamicVarOrderingMethod(network, dynOrderingMethod,
+					   reorderVerbosity);
+    if (bdd_get_package_name() != CUDD)
+      dynOrderingMethod = Ntk_NetworkReadDynamicVarOrderingMethod(network);
+    (void) fprintf(vis_stdout,
+		   "Dynamic variable ordering is enabled with method %s.\n",
+                   DynOrderTypeConvertToString(dynOrderingMethod));
+  }
+
+  /*
+   * Force a reordering.  Note that the mddManager has to have the method set
+   * before calling bdd_reorder.  This is done via a call to
+   * Ntk_NetworkSetDynamicVarOrderingMethod with dynOrderingMethod.  The value
+   * of the ordering method is restored afterwards.
+   */
+  if (forceFlag) {
+    mdd_manager *mddManager = Ntk_NetworkReadMddManager(network);
+    bdd_reorder_verbosity_t prevReorderVerbosity;
+    prevReorderVerbosity = bdd_reordering_reporting(mddManager);
+
+    (void) fprintf(vis_stdout, "Dynamic variable ordering forced ");
+    (void) fprintf(vis_stdout, "with method %s....\n",
+                   DynOrderTypeConvertToString(dynOrderingMethod));
+    Ntk_NetworkSetDynamicVarOrderingMethod(network, dynOrderingMethod, reorderVerbosity);
+    bdd_reorder(Ntk_NetworkReadMddManager(network));
+    Ntk_NetworkSetDynamicVarOrderingMethod(network, currentMethod, prevReorderVerbosity);
+  }
+
+  return 0;  /* Everything okay */
+
+usage:
+  (void) fprintf(vis_stderr, "usage: dynamic_var_ordering [-d] [-e method] [-f method] [-h]\n");
+  (void) fprintf(vis_stderr, "   -d        disable dynamic ordering\n");
+  (void) fprintf(vis_stderr, "   -e method enable dynamic ordering with method (window, sift)\n");
+  (void) fprintf(vis_stderr, "   -f method force dynamic ordering with method (window, sift)\n");
+  (void) fprintf(vis_stderr, "   -h        print the command usage\n");
+  (void) fprintf(vis_stderr, "   -v #      verbosity level \n");
+  
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the print_bdd_stats command.]
+
+  SideEffects []
+
+  CommandName [print_bdd_stats]
+
+  CommandSynopsis [print the BDD statistics for the flattened network]
+
+  CommandArguments [\[-h\]]
+
+  CommandDescription [Print the BDD statistics for the flattened network.  The
+  MDDs representing the functions of the network are themselves represented by
+  BDDs via an encoding of the multi-valued variables into binary valued
+  variables.  The statistics given by this command depend on the underlying
+  BDD package with which VIS was linked.  To get more information about the
+  statistics, consult the documentation for the given BDD package.  The
+  commands <tt>flatten_hierarchy</tt> and <tt>static_order</tt> must be
+  invoked before this command.<p>
+
+  Command options:<p>  
+
+  <dl>
+
+  <dt> -h
+  <dd> Print the command usage.
+
+  </dl>
+  ]
+  
+******************************************************************************/
+static int
+CommandPrintBddStats(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int            c;
+  Ntk_Network_t *network;
+
+  /*
+   * Parse the command line.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "h")) != EOF) {
+    switch (c) {
+      case 'h':
+        goto usage;
+      default:
+        goto usage;
+    }
+  }
+
+  /* flatten_hierarchy and static_order must have been invoked already. */
+  network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+  if (network == NIL(Ntk_Network_t)) {
+    return 1;
+  }
+  if (Ord_NetworkTestAreVariablesOrdered(network, Ord_InputAndLatch_c) == FALSE) {
+    (void) fprintf(vis_stderr, "The MDD variables have not been ordered. ");
+    (void) fprintf(vis_stderr, "Use static_order.\n");
+    return 1;
+  }
+
+  bdd_print_stats(Ntk_NetworkReadMddManager(network), vis_stdout);
+
+  return 0;  /* Everything okay */
+
+usage:
+  (void) fprintf(vis_stderr, "usage: print_bdd_stats [-h]\n");
+  (void) fprintf(vis_stderr, "   -h  print the command usage\n");
+
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts a string to an order type.]
+
+  Description [Converts a string to an order type. If string does not refer to 
+  one of the allowed order types, then returns Ord_Unassigned_c.]
+
+  SideEffects []
+
+******************************************************************************/
+static Ord_OrderType
+StringConvertToOrderType(
+  char *string)
+{
+  if (strcmp("all", string) == 0) { 
+    return Ord_All_c; 
+  }
+  else if (strcmp("input_and_latch", string) == 0) { 
+    return Ord_InputAndLatch_c;
+  }
+  else if (strcmp("next_state_node", string) == 0) {
+    return Ord_NextStateNode_c;
+  }
+  else if (strcmp("partial", string) == 0) {
+    return Ord_Partial_c;
+  }
+  else {
+    return Ord_Unassigned_c;
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts a string to a dynamic ordering method type.]
+
+  Description [Converts a string to a dynamic ordering method type. If string
+  is not "sift" or "window", then returns BDD_REORDER_NONE.]
+
+  SideEffects []
+
+******************************************************************************/
+static bdd_reorder_type_t
+StringConvertToDynOrderType(
+  char *string)
+{
+  if (strcmp("sift", string) == 0) { 
+    return BDD_REORDER_SIFT;
+  }
+  else if (strcmp("window", string) == 0) { 
+    return BDD_REORDER_WINDOW;
+  }
+  else if (strcmp("random", string) == 0) { 
+    return BDD_REORDER_RANDOM;
+  }
+  else if (strcmp("random_pivot", string) == 0) { 
+    return  BDD_REORDER_RANDOM_PIVOT;
+  }
+  else if (strcmp("sift_converge", string) == 0) { 
+    return  BDD_REORDER_SIFT_CONVERGE;
+  }
+  else if (strcmp("symmetry_sift", string) == 0) { 
+    return  BDD_REORDER_SYMM_SIFT;
+  }
+  else if (strcmp("symmetry_sift_converge", string) == 0) { 
+    return  BDD_REORDER_SYMM_SIFT_CONV;
+  }
+  else if (strcmp("window2", string) == 0) { 
+    return  BDD_REORDER_WINDOW2;
+  }
+  else if (strcmp("window3", string) == 0) { 
+    return  BDD_REORDER_WINDOW3;
+  }
+  else if (strcmp("window4", string) == 0) { 
+    return  BDD_REORDER_WINDOW4;
+  }
+  else if (strcmp("window2_converge", string) == 0) { 
+    return  BDD_REORDER_WINDOW2_CONV;
+  }
+  else if (strcmp("window3_converge", string) == 0) { 
+    return  BDD_REORDER_WINDOW3_CONV;
+  }
+  else if (strcmp("window4_converge", string) == 0) { 
+    return  BDD_REORDER_WINDOW4_CONV;
+  }
+  else if (strcmp("group_sift", string) == 0) { 
+    return  BDD_REORDER_GROUP_SIFT;
+  }
+  else if (strcmp("group_sift_converge", string) == 0) { 
+    return  BDD_REORDER_GROUP_SIFT_CONV;
+  }
+  else if (strcmp("annealing", string) == 0) { 
+    return  BDD_REORDER_ANNEALING;
+  }
+  else if (strcmp("genetic", string) == 0) { 
+    return  BDD_REORDER_GENETIC;
+  }
+  else if (strcmp("exact", string) == 0) { 
+    return  BDD_REORDER_EXACT;
+  }
+  else if (strcmp("lazy_sift", string) == 0) {
+    return BDD_REORDER_LAZY_SIFT;
+  }
+  else {
+    return BDD_REORDER_NONE;
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts a dynamic ordering method type to a string.]
+
+  Description [Converts a dynamic ordering method type to a string.  This
+  string must NOT be freed by the caller.]
+
+  SideEffects []
+
+******************************************************************************/
+static char *
+DynOrderTypeConvertToString(
+  bdd_reorder_type_t method)
+{
+  if (method == BDD_REORDER_SIFT) {
+    return "sift"; 
+  }
+  else if (method == BDD_REORDER_WINDOW) {
+    return "window"; 
+  }
+  else if (method == BDD_REORDER_NONE) {
+    return "none"; 
+  }
+  else if (method == BDD_REORDER_RANDOM) { 
+    return "random";
+  }
+  else if (method == BDD_REORDER_RANDOM_PIVOT) { 
+    return "random_pivot";
+  }
+  else if (method == BDD_REORDER_SIFT_CONVERGE) { 
+    return "sift_converge";
+  }
+  else if (method == BDD_REORDER_SYMM_SIFT) { 
+    return "symmetry_sift";
+  }
+  else if (method == BDD_REORDER_SYMM_SIFT_CONV) { 
+    return "symmetry_sift_converge";
+  }
+  else if (method == BDD_REORDER_WINDOW2) { 
+    return "window2";
+  }
+  else if (method == BDD_REORDER_WINDOW3) { 
+    return "window3";
+  }
+  else if (method == BDD_REORDER_WINDOW4) { 
+    return "window4";
+  }
+  else if (method == BDD_REORDER_WINDOW2_CONV) { 
+    return "window2_converge";
+  }
+  else if (method == BDD_REORDER_WINDOW3_CONV) { 
+    return "window3_converge";
+  }
+  else if (method == BDD_REORDER_WINDOW4_CONV) { 
+    return "window4_converge";
+  }
+  else if (method == BDD_REORDER_GROUP_SIFT) { 
+    return "group_sift";
+  }
+  else if (method == BDD_REORDER_GROUP_SIFT_CONV) { 
+    return "group_sift_converge";
+  }
+  else if (method == BDD_REORDER_ANNEALING) { 
+    return "annealing";
+  }
+  else if (method == BDD_REORDER_GENETIC) { 
+    return "genetic";
+  }
+  else if (method ==  BDD_REORDER_EXACT) { 
+    return "exact";
+  }
+  else if (method == BDD_REORDER_LAZY_SIFT) {
+    return "lazy_sift";
+  }
+  else {
+    fail("unrecognized method");
+    return NIL(char); /* not reached */
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Verifies that suppliedNodeList has the correct nodes.]
+
+  Description [Returns TRUE if the set of nodes in suppliedNodeList matches
+  the set of nodes in network specified by orderType; else returns FALSE and
+  writes a message to error_string. OrderType should be one of the following:
+  1) Ord_All_c: should match the set of all nodes in network; 2)
+  Ord_InputAndLatch_c: should match the set of inputs (primary + pseudo),
+  latches, and next state nodes; 3) Ord_NextStateNode_c: should match the set
+  of next state nodes; number should be the number of latches; 4)
+  Ord_Partial_c: returns TRUE automatically.]
+
+  SideEffects []
+
+******************************************************************************/
+static boolean
+NetworkCheckSuppliedNodeList(
+  Ntk_Network_t * network,
+  lsList  suppliedNodeList,
+  Ord_OrderType  orderType)
+{
+  lsGen         gen;
+  st_generator *stGen;
+  Ntk_Node_t   *node;
+  st_table     *requiredNodes;
+  st_table     *suppliedNodes;
+  char         *dummy;
+  boolean       returnFlag = TRUE;
+  
+  assert(orderType != Ord_Unassigned_c);
+
+  if (orderType == Ord_Partial_c) {
+    return TRUE;
+  }
+  
+  /* At this point, orderType must be one of the these. */
+  assert((orderType == Ord_All_c) || (orderType == Ord_InputAndLatch_c)
+         || (orderType == Ord_NextStateNode_c));
+  
+
+  /*
+   * Build up the table of required nodes. Next state nodes are included by
+   * all 3 order types. 
+   */
+  requiredNodes = st_init_table(st_ptrcmp, st_ptrhash);
+  Ntk_NetworkForEachNode(network, gen, node) {
+    if ((orderType == Ord_All_c) || Ntk_NodeTestIsNextStateNode(node)) {
+      st_insert(requiredNodes, (char *) node, NIL(char));
+    }
+    else if ((orderType == Ord_InputAndLatch_c)
+             && Ntk_NodeTestIsCombInput(node)) {
+      st_insert(requiredNodes, (char *) node, NIL(char));
+    }
+    /* else, this node is not included by orderType */
+  }
+
+  /*
+   * Convert suppliedNodeList to the table of supplied nodes.
+   */
+  suppliedNodes = st_init_table(st_ptrcmp, st_ptrhash);
+  lsForEachItem(suppliedNodeList, gen, node) {
+    int status = st_insert(suppliedNodes, (char *) node, NIL(char));
+    if (status) {
+      error_append("node ");
+      error_append(Ntk_NodeReadName(node));
+      error_append(" appears more than once in ordering file\n");
+      returnFlag = FALSE;
+    }
+  }
+
+  /*
+   * Check that suppliedNodes is contained in requiredNodes.
+   */
+  st_foreach_item(suppliedNodes, stGen, &node, &dummy) {
+    if (!st_is_member(requiredNodes, node)) {
+      error_append("node ");
+      error_append(Ntk_NodeReadName(node));
+      error_append(" supplied but not required\n");
+      returnFlag = FALSE;
+    }
+  }
+  
+  /*
+   * Check that suppliedNodes is contained in requiredNodes.
+   */
+  st_foreach_item(requiredNodes, stGen, &node, &dummy) {
+    if (!st_is_member(suppliedNodes, node)) {
+      error_append("node ");
+      error_append(Ntk_NodeReadName(node));
+      error_append(" required but not supplied\n");
+      returnFlag = FALSE;
+    }
+  }
+  
+  st_free_table(requiredNodes);
+  st_free_table(suppliedNodes);
+  return returnFlag;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Handle function for timeout.]
+
+  Description [This function is called when the time out occurs.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+TimeOutHandle(void)
+{
+  longjmp(timeOutEnv, 1);
+}
Index: vis_dev/vis-2.3/src/ord/ordInt.h
===================================================================
--- vis_dev/vis-2.3/src/ord/ordInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/ord/ordInt.h	(revision 14)
@@ -0,0 +1,76 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [ordInt.h]
+
+  PackageName [ord]
+
+  Synopsis    [Internal declarations for the order package.]
+
+  Author      [Adnan Aziz, Tom Shiple, Serdar Tasiran]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: ordInt.h,v 1.6 2004/07/28 19:50:49 wangc Exp $]
+
+******************************************************************************/
+
+#ifndef _ORDINT
+#define _ORDINT
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "cmd.h"
+#include "var.h"
+#include "ord.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+#define ORDUNASSIGNED_DEPTH -1
+
+#ifndef MAX
+#  define MAX(a,b)              ((a) > (b) ? (a) : (b))
+#endif
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN int OrdNodesFromListCompareDepth(lsGeneric node1, lsGeneric node2);
+EXTERN int OrdNodesFromArrayCompareDepth(const void * node1, const void * node2);
+EXTERN void OrdNetworkComputeNodeDepths(Ntk_Network_t * network, lsList roots);
+EXTERN void OrdNodeListWrite(FILE *fp, lsList nodeList);
+EXTERN long OrdNodeReadDepth(Ntk_Node_t * node);
+EXTERN void OrdNetworkAssignMddIds(Ntk_Network_t * network, Ord_OrderType orderType, lsList orderList, boolean nsAfterSupport);
+EXTERN lsList OrdNetworkOrderTFIOfRoots(Ntk_Network_t *network, lsList roots, Ord_NodeMethod nodeOrderMethod, st_table *nodeToHandle, int verbose);
+EXTERN lsList OrdNetworkOrderRootsByPerm(Ntk_Network_t *network, int verbose);
+EXTERN lsList OrdNetworkOrderRootsByDepth(Ntk_Network_t *network, boolean verbose);
+EXTERN void OrdNodeAddToList(lsList nodeList, st_table *nodeTable, Ntk_Node_t *node);
+EXTERN int OrdMakeNewVariableOrder(mdd_manager *mddMgr, lsList suppliedNodeList, int group, int verbose);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _ORDINT */
+
+
+
Index: vis_dev/vis-2.3/src/ord/ordIo.c
===================================================================
--- vis_dev/vis-2.3/src/ord/ordIo.c	(revision 14)
+++ vis_dev/vis-2.3/src/ord/ordIo.c	(revision 14)
@@ -0,0 +1,711 @@
+/**CFile***********************************************************************
+
+  FileName    [ordIo.c]
+
+  PackageName [ord]
+
+  Synopsis    [Routines to read and write variable orderings.]
+
+  Author      [Adnan Aziz, Tom Shiple]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ordInt.h"
+
+static char rcsid[] UNUSED = "$Id: ordIo.c,v 1.15 2004/07/28 20:42:10 jinh Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+/*
+ * States of the state machine used to parse the input node list file.
+ */
+#define STATE_TEST 0 /* next char is in first column */
+#define STATE_WAIT 1 /* wait until end of line '\n' is reached */
+#define STATE_IN   2 /* parsing a node name */
+
+/*
+ * Maximum permissible length of a node name in the input node list file.
+ */
+#define MAX_NAME_LENGTH 32768
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static array_t * NodeBuildBddLevelArrayFromNtkNode(Ntk_Node_t * node);
+static array_t * NodeBuildBddIdArrayFromNtkNode(Ntk_Node_t * node);
+static int IntegersCompare(const void * obj1, const void * obj2);
+static int NodesCompareBddLevelArray(lsGeneric node1, lsGeneric node2);
+static array_t * NodeReadBddLevelArray(Ntk_Node_t * node);
+static void NodeSetBddLevelArray(Ntk_Node_t * node, array_t * bddLevelArray);
+static boolean NameStringProcess(char * nameString, Ntk_Network_t * network, lsList nodeList, int verbose);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Prints to a file the current ordering of MDD variables.]
+
+  Description [Prints to a file all the nodes specified by orderType.
+  OrderType can be one of Ord_All_c, Ord_InputAndLatch_c or
+  Ord_NextStateNode_c (see ord.h for the meaning of these types).  For each
+  node, prints the following: name, node type, MDD id, number of values in the
+  range of the node output, and a list of the levels (in the current ordering)
+  of the BDD variables that constitute this multi-valued variable.  The nodes
+  are printed to the file in ascending order of the lowest level corresponding
+  BDD variable. If there exists a node in the class specified by orderType
+  that doesn't have an mddId, then the routine writes a message to
+  error_string, and returns 0.  In all other cases, it writes to the file and
+  then returns 1.  It is the responsibility of the user to close the file.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+Ord_NetworkPrintVariableOrder(
+  FILE * fp,
+  Ntk_Network_t * network,
+  Ord_OrderType  orderType /* Ord_All_c, Ord_InputAndLatch_c or Ord_NextStateNode_c */)
+{
+  lsGen        gen;
+  lsList       nodeList;
+  Ntk_Node_t  *node;
+  int          maxNameLength;
+  time_t       now;
+  struct tm   *nowStructPtr;
+  char        *nowTxt;
+
+  assert((orderType == Ord_All_c) || (orderType == Ord_InputAndLatch_c)
+         || (orderType == Ord_NextStateNode_c));
+
+  /*
+   * First, build up a list of all the nodes covered by orderType.
+   */
+  if (orderType == Ord_All_c) {
+    nodeList = lsCopy(Ntk_NetworkReadNodes(network),
+		      (lsGeneric (*) (lsGeneric)) NULL);
+  }
+  else {
+    nodeList = lsCreate();
+    Ntk_NetworkForEachNode(network, gen, node) {
+      if (Ntk_NodeTestIsNextStateNode(node)
+          || ((orderType == Ord_InputAndLatch_c) && Ntk_NodeTestIsCombInput(node))) {
+        (void) lsNewEnd(nodeList, (lsGeneric) node, LS_NH);
+      }
+    }
+  }
+  
+  /*
+   * As a sanity check, make sure that all the variables in orderType have an
+   * MDD id.
+   */
+  lsForEachItem(nodeList, gen, node) {
+    if (Ntk_NodeReadMddId(node) == NTK_UNASSIGNED_MDD_ID) {
+      error_append("node ");
+      error_append(Ntk_NodeReadName(node));
+      error_append(" not ordered\n");
+
+      (void) lsFinish(gen);
+      (void) lsDestroy(nodeList, (void (*) (lsGeneric)) NULL);
+      return (0);
+    }
+  }
+
+  /*
+   * For each node in nodeList, get the array of levels of the BDD variables
+   * which make up the MDD variable of node.
+   */
+  lsForEachItem(nodeList, gen, node) {
+    array_t *bddLevelArray = NodeBuildBddLevelArrayFromNtkNode(node);
+
+    NodeSetBddLevelArray(node, bddLevelArray);
+  }
+
+  /*
+   * Sort the nodes of nodeList in ascending order of the lowest level BDD
+   * variable corresponding to a node's MDD variable.
+   */
+  (void) lsSort(nodeList, NodesCompareBddLevelArray);
+
+  /*
+   * Compute the maximum length of a node name, for pretty printing.
+   */
+  maxNameLength = 0;
+  lsForEachItem(nodeList, gen, node) {
+    int nameLength = strlen(Ntk_NodeReadName(node));
+    maxNameLength = (nameLength > maxNameLength) ? nameLength : maxNameLength;
+  }
+  
+  /*
+   * Write out the header for the output file.
+   */
+  now = time(0);
+  nowStructPtr = localtime(& now);
+  nowTxt = asctime(nowStructPtr);
+  
+  (void) fprintf(fp, "# %s\n", Vm_VisReadVersion());
+  (void) fprintf(fp, "# network name: %s\n", Ntk_NetworkReadName(network));
+  (void) fprintf(fp, "# generated: %s", nowTxt);
+  (void) fprintf(fp, "#\n");
+  (void) fprintf(fp, "# %-*s type            mddId vals levs\n",
+                 maxNameLength, "name");
+  
+  /*
+   * Write out the nodes in order.
+   */
+  lsForEachItem(nodeList, gen, node) {
+    int i;
+    array_t *bddLevelArray = NodeReadBddLevelArray(node);
+    char *nodeType = Ntk_NodeObtainTypeAsString(node);
+    
+    (void) fprintf(fp, "%-*s  %-16s %5d %4d ",
+                   maxNameLength,
+                   Ntk_NodeReadName(node),
+                   nodeType,
+                   Ntk_NodeReadMddId(node),
+                   Var_VariableReadNumValues(Ntk_NodeReadVariable(node)));
+    FREE(nodeType);
+
+    (void) fprintf(fp, "(");
+    for (i = 0; i < array_n(bddLevelArray); i++) {
+      int level = array_fetch(int, bddLevelArray, i);
+      
+      if (i == 0) {
+        (void) fprintf(fp, "%d", level);
+      }
+      else {
+        (void) fprintf(fp, ", %d", level);
+      }
+    }
+    (void) fprintf(fp, ")\n");
+    array_free(bddLevelArray);
+  }
+
+  (void) lsDestroy(nodeList, (void (*) (lsGeneric)) NULL);
+  return (1);
+}
+  
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a name array of combinational input variables in order.]
+
+  SideEffects []
+
+******************************************************************************/
+char **
+Ord_NetworkGetCombInputNamesInOrder(
+  Ntk_Network_t *network)
+{
+  lsGen		gen;
+  lsList	nodeList;
+  Ntk_Node_t	*node;
+  int		i;
+  char		**names;
+
+  i = 0;
+  nodeList = lsCreate();
+  Ntk_NetworkForEachNode(network, gen, node) {
+    if (Ntk_NodeTestIsCombInput(node)) {
+      (void) lsNewEnd(nodeList, (lsGeneric) node, LS_NH);
+      i++;
+    }
+  }
+
+  names = (char **)ALLOC(char *, i);
+  if (!names)
+    return(NULL);
+  
+  /*
+   * For each node in nodeList, get the array of levels of the BDD variables
+   * which make up the MDD variable of node.
+   */
+  lsForEachItem(nodeList, gen, node) {
+    array_t *bddLevelArray = NodeBuildBddLevelArrayFromNtkNode(node);
+
+    NodeSetBddLevelArray(node, bddLevelArray);
+  }
+
+  /*
+   * Sort the nodes of nodeList in ascending order of the lowest level BDD
+   * variable corresponding to a node's MDD variable.
+   */
+  (void) lsSort(nodeList, NodesCompareBddLevelArray);
+
+  /*
+   * Write out the nodes in order.
+   */
+  i = 0;
+  lsForEachItem(nodeList, gen, node) {
+    names[i] = (char *)malloc(strlen(Ntk_NodeReadName(node)) + 1);
+    strcpy(names[i], Ntk_NodeReadName(node));
+    i++;
+  }
+
+  (void) lsDestroy(nodeList, (void (*) (lsGeneric)) NULL);
+  return(names);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a list of nodes corresponding to the names in a file.]
+
+  Description [Parses a file and builds a node list corresponding to the names
+  found in the first "column" of each line of the file.  Any line starting
+  with the comment character '#' or white space is ignored.  If a name is
+  found for which there doesn't exist a corresponding node in network, then a
+  message is written to error_string, the partial node list is freed, and the
+  function returns FALSE; otherwise, it returns TRUE, and a pointer to a list
+  is returned.]
+
+  Comment [The parser consists of 3 states.  See the documentation
+  accompanying the #defines defining the state names.]
+  
+  SideEffects []
+
+******************************************************************************/
+boolean
+Ord_FileReadNodeList(
+  FILE * fp,
+  Ntk_Network_t * network,
+  lsList * nodeList /* of Ntk_Node_t , for return */,
+  int verbose)
+{
+  int     c;
+  int     state;
+  int     curPosition = 0;
+  boolean status;
+  char    nameString[MAX_NAME_LENGTH];
+  boolean returnFlag = TRUE;
+  
+  *nodeList = lsCreate();
+
+  state = STATE_TEST;
+  while ((c = fgetc(fp)) != EOF) {
+
+    switch (state) {
+        case STATE_TEST:
+          /* At start of a new line. */
+          if (c == '#') {
+            /* Line starting with comment character; wait for newline */
+            state = STATE_WAIT;
+          }
+          else if ((c == ' ') || (c == '\t')) {
+            /* Line starting with white space; wait for newline */
+            state = STATE_WAIT;
+          }
+          else if (c == '\n') {
+            /* Line starting newline; go to next line */
+            state = STATE_TEST;
+          }
+          else {
+            /* Assume starting a node name. */
+            curPosition = 0;
+            nameString[curPosition++] = c;
+            state = STATE_IN;
+          }
+          break;
+        case STATE_WAIT:
+          /*
+           * Waiting for the newline character.
+           */
+          state = (c == '\n') ? STATE_TEST : STATE_WAIT;
+          break;
+        case STATE_IN:
+          /*
+           * Parsing a node name.  If white space reached, then terminate the
+           * node name and process it.  Else, continue parsing.
+           */
+          if ((c == ' ') || (c == '\n') || (c == '\t')) {
+            nameString[curPosition] = '\0';
+            status = NameStringProcess(nameString, network, *nodeList, verbose);
+            if (status == FALSE) {
+              returnFlag = FALSE;
+            }
+            state = (c == '\n') ? STATE_TEST : STATE_WAIT;
+          }
+          else {
+            nameString[curPosition++] = c;
+            if (curPosition >= MAX_NAME_LENGTH) {
+              error_append("maximum node name length exceeded");
+              returnFlag = FALSE;
+            }
+            state = STATE_IN; /* redundant, but be explicit */
+          }
+          break;
+        default:
+          fail("unrecognized state");
+    }
+  }
+
+  /*
+   * Handle case where EOF terminates a name.
+   */
+  if (state == STATE_IN) {
+    nameString[curPosition] = '\0';
+    status = NameStringProcess(nameString, network, *nodeList, verbose);
+    if (status == FALSE) {
+      returnFlag = FALSE;
+    }
+  }
+
+  if (returnFlag) {
+    return TRUE;
+  }
+  else {
+    (void) lsDestroy(*nodeList, (void (*) (lsGeneric)) NULL);
+    return FALSE;
+  }
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makes new variable order.]
+
+  Description [Makes new variable order. Returns 1 if not successful.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+OrdMakeNewVariableOrder(mdd_manager *mddMgr, lsList suppliedNodeList,
+		     int group, int verbose)
+{
+  int		i, nVars;
+  int		*invPerm = NIL(int);
+  int		*groupInfo = NIL(int);
+  int		length, bddId, mvLen;
+  lsGen		gen;
+  Ntk_Node_t	*node;
+  array_t	*bddIdArray;
+  char		*name = NIL(char), *prevName = NIL(char), *longName;
+  int		len1, len2, minLen;
+
+  nVars = bdd_num_vars(mddMgr);
+  invPerm = ALLOC(int, nVars);
+
+  length = 0;
+  if (group) {
+    prevName = NIL(char);
+    groupInfo = ALLOC(int, nVars);
+    memset(groupInfo, 0, sizeof(int) * nVars);
+  }
+  lsForEachItem(suppliedNodeList, gen, node) {
+    bddIdArray = NodeBuildBddIdArrayFromNtkNode(node);
+    mvLen = array_n(bddIdArray);
+    if (group) {
+      name = Ntk_NodeReadName(node);
+      if (prevName) {
+	len1 = strlen(prevName);
+	len2 = strlen(name);
+	if (len1 < len2) {
+	  minLen = len1;
+	  longName = name;
+	} else {
+	  minLen = len2;
+	  longName = prevName;
+	}
+	if (strncmp(name, prevName, minLen) == 0) {
+	  if (strcmp(longName + minLen, "$NS") == 0)
+	    groupInfo[length - mvLen] = mvLen * 2;
+	}
+      }
+    }
+    for (i = 0; i < mvLen; i++) {
+      bddId = array_fetch(int, bddIdArray, i);
+      invPerm[length] = bddId;
+      length++;
+    }
+    array_free(bddIdArray);
+    if (group)
+      prevName = name;
+  }
+
+  if (length != nVars) {
+    fprintf(vis_stderr,
+	    "** ord error: the number of variables does not match\n");
+    FREE(invPerm);
+    if (group)
+      FREE(groupInfo);
+    return(1);
+  }
+
+  bdd_discard_all_var_groups(mddMgr);
+  bdd_shuffle_heap(mddMgr, invPerm);
+
+  if (group) {
+    mdd_t	*var;
+
+    for (i = 0; i < nVars; i++) {
+      if (groupInfo[i]) {
+	var = bdd_var_with_index(mddMgr, invPerm[i]);
+	bdd_new_var_block(var, groupInfo[i]);
+	i += groupInfo[i] - 1;
+      }
+    }
+    FREE(groupInfo);
+  }
+
+  FREE(invPerm);
+  return(0);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the levels of the BDD variables corresponding to the MDD
+  variable of a node.]
+
+  Description [Returns an array (of int's) of the levels of the BDD variables
+  corresponding to the MDD variable of a node.  The level of a BDD variable is
+  it place in the current variable ordering of the BDD manager.  The returned
+  array is sorted in ascending order.  It is the responsibility of the caller
+  to free this array.]
+
+  SideEffects []
+
+******************************************************************************/
+static array_t *
+NodeBuildBddLevelArrayFromNtkNode(
+  Ntk_Node_t * node)
+{
+  int            i;
+  Ntk_Network_t *network       = Ntk_NodeReadNetwork(node);
+  mdd_manager   *mddManager    = Ntk_NetworkReadMddManager(network);
+  array_t       *mvarArray     = mdd_ret_mvar_list(mddManager);
+  int            mddId         = Ntk_NodeReadMddId(node);
+  mvar_type      mv;
+  array_t       *bddLevelArray;
+
+  mv            = array_fetch(mvar_type, mvarArray, mddId);
+  bddLevelArray = array_alloc(int, mv.encode_length);
+
+  for (i = 0; i < mv.encode_length; i++) {
+    int    bddId    = mdd_ret_bvar_id(&mv, i);
+    bdd_t *varBdd   = bdd_get_variable((bdd_manager *) mddManager, bddId);
+    int    varLevel = (int) bdd_top_var_level((bdd_manager *) mddManager, varBdd);
+
+    bdd_free(varBdd);
+    array_insert_last(int, bddLevelArray, varLevel);
+  }
+  array_sort(bddLevelArray, IntegersCompare);
+
+  return (bddLevelArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the indices of the BDD variables corresponding to the MDD
+  variable of a node.]
+
+  Description [Returns an array (of int's) of the indices of the BDD variables
+  corresponding to the MDD variable of a node. It is the responsibility of the
+  caller to free this array.]
+
+  SideEffects []
+
+******************************************************************************/
+static array_t *
+NodeBuildBddIdArrayFromNtkNode(
+  Ntk_Node_t * node)
+{
+  int            i, bddId;
+  Ntk_Network_t *network    = Ntk_NodeReadNetwork(node);
+  mdd_manager   *mddManager = Ntk_NetworkReadMddManager(network);
+  array_t       *mvarArray  = mdd_ret_mvar_list(mddManager);
+  int            mddId      = Ntk_NodeReadMddId(node);
+  mvar_type      mv;
+  array_t       *bddIdArray;
+
+  mv         = array_fetch(mvar_type, mvarArray, mddId);
+  bddIdArray = array_alloc(int, mv.encode_length);
+
+  for (i = 0; i < mv.encode_length; i++) {
+    bddId = mdd_ret_bvar_id(&mv, i);
+    array_insert_last(int, bddIdArray, bddId);
+  }
+
+  return (bddIdArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Used to sort an array of integers in ascending order.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+IntegersCompare(
+  const void * obj1,
+  const void * obj2)
+{
+  int int1 = *(int *) obj1;
+  int int2 = *(int *) obj2;
+  
+  if (int1 < int2) {
+    return -1;
+  }
+  else if (int1 == int2) {
+    return 0;
+  }
+  else {
+    return 1;
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Used to sort an array of nodes in ascending order of lowest BDD
+  level.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+NodesCompareBddLevelArray(
+  lsGeneric node1,
+  lsGeneric node2)
+{
+  array_t *bddLevelArray1 = NodeReadBddLevelArray((Ntk_Node_t *) node1);
+  array_t *bddLevelArray2 = NodeReadBddLevelArray((Ntk_Node_t *) node2);
+  int      firstLevel1    = array_fetch(int, bddLevelArray1, 0);
+  int      firstLevel2    = array_fetch(int, bddLevelArray2, 0);
+  
+  if (firstLevel1 < firstLevel2) {
+    return -1;
+  }
+  else if (firstLevel1 == firstLevel2) {
+    return 0;
+  }
+  else {
+    return 1;
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the BDD level array of a node.]
+
+  SideEffects []
+
+  SeeAlso     [NodeSetBddLevelArray NodesCompareBddLevelArray]
+
+******************************************************************************/
+static array_t *
+NodeReadBddLevelArray(
+  Ntk_Node_t * node)
+{
+  return ((array_t *) Ntk_NodeReadUndef(node));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the BDD level array of a node.]
+
+  SideEffects []
+
+  SeeAlso     [NodeReadBddLevelArray]
+
+******************************************************************************/
+static void
+NodeSetBddLevelArray(
+  Ntk_Node_t * node,
+  array_t * bddLevelArray)
+{
+  Ntk_NodeSetUndef(node, (void *) bddLevelArray);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Processes the name of a node.]
+
+  Description [Processes the name of a node. If there is no node in network
+  with name nameString, then the function writes a message in error_string,
+  and returns FALSE.  If the corresponding node is found, then the node is
+  added to the end of nodeList; else, nothing is done.  In either case, TRUE
+  is returned.]
+
+  SideEffects []
+
+******************************************************************************/
+static boolean
+NameStringProcess(
+  char * nameString,
+  Ntk_Network_t * network,
+  lsList  nodeList,
+  int verbose)
+{
+  Ntk_Node_t *node = Ntk_NetworkFindNodeByActualName(network, nameString);
+
+  if (node == NIL(Ntk_Node_t)) {
+    error_append("Node not found for name: ");
+    error_append(nameString);
+    error_append("\n");
+    return FALSE;
+  }
+
+  if (verbose > 1) {
+    (void) fprintf(vis_stdout, "Reading node: %s\n", Ntk_NodeReadName(node));
+  }
+
+  (void) lsNewEnd(nodeList, (lsGeneric) node, LS_NH);  
+  return TRUE;
+}
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/ord/ordMain.c
===================================================================
--- vis_dev/vis-2.3/src/ord/ordMain.c	(revision 14)
+++ vis_dev/vis-2.3/src/ord/ordMain.c	(revision 14)
@@ -0,0 +1,1242 @@
+/**CFile***********************************************************************
+
+  FileName    [ordMain.c]
+
+  PackageName [ord]
+
+  Synopsis    [Routines for static ordering of MDD variables.]
+
+  Author      [Adnan Aziz, Tom Shiple, Serdar Tasiran]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ordInt.h"
+
+static char rcsid[] UNUSED = "$Id: ordMain.c,v 1.17 2005/04/16 06:15:25 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int NodesCompareDepth(Ntk_Node_t *node1, Ntk_Node_t *node2);
+static long NodeComputeDepth(Ntk_Node_t * node);
+static void NetworkAddDanglingNodesToOrderList(Ntk_Network_t * network, lsList nodeOrderList, st_table *nodeToHandle);
+static void NetworkAddNSVarsToOrderList(Ntk_Network_t * network, lsList nodeOrderList, st_table *nodeToHandle, boolean nsAfterSupport);
+static lsList LatchNSListConvertToLatchDataInputList(lsList latchNSList);
+static void NodeSetDepth(Ntk_Node_t * node, long depth);
+static void MddGroupVariables(mdd_manager *mddMgr, int initMddId, int blockSize);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Orders the MDD variables of a network.]
+
+  Description [Orders the MDD variables of a network.  The ordering is based
+  solely on the topology of the network; the binary variables that make up the
+  MDD variables are not interleaved. OutputOrderType can be either Ord_All_c
+  or Ord_InputAndLatch_c. If it is Ord_All_c, then every node (and latch NS)
+  in the network is assigned an MDD id.  If it is Ord_InputAndLatch_c, then
+  every primary input, pseudo input, latch, and latch NS is assigned an MDD
+  id.<p>
+
+  SuppliedOrderType can be any value of Ord_OrderType.  If it is Ord_All_c or
+  Ord_InputAndLatch_c, then suppliedNodeList must give an ordering of the
+  network nodes (included in the set specified by suppliedOrderType).
+  Otherwise, Ord_NetworkOrderNodes is called, with the same arguments as this
+  function, to compute an ordering of the network nodes.  In any case, the
+  ordering of nodes is projected onto the set specified by generatedOrderType,
+  and MDD ids are assigned (in order) to the nodes in the projection.  The
+  starting MDD id is the total number of variables currently in the MDD
+  manager of the network.  An MDD manager is created for the network if one
+  doesn't already exist.<p>
+
+  No checks are made to insure that suppliedNodeList contains what is implied
+  by the value of suppliedOrderType.  The MDD ids of nodes not specified by
+  generatedOrderType are unaffected.<p>
+
+  If nsAfterSupport is TRUE, then for a given latch, its next state variable
+  is ordered just after the variables in the support of the latch's
+  corresponding dataInput function. <p>
+
+  If nsAfterSupport is FALSE, then for a given latch, its NS variable is
+  ordered just after the corresponding present state variable. In this case,
+  the ps variable and the ns variable are grouped together in the variable
+  ordering, so that when reordering is performed they remain adjacent in the
+  new variable ordering. Similarly, when an ordering is read from a file, NS
+  variables immediately following corresponding PS variables are grouped
+  together.<p>]
+
+  SideEffects [Writes over the MDD id field of nodes.]
+
+  SeeAlso [Ord_NetworkOrderNodes]
+  
+******************************************************************************/
+void
+Ord_NetworkOrderVariables(
+  Ntk_Network_t *network,
+  Ord_RootMethod rootOrderMethod,
+  Ord_NodeMethod nodeOrderMethod,
+  boolean        nsAfterSupport,
+  Ord_OrderType  generatedOrderType /* Ord_All_c or Ord_InputAndLatch_c */,
+  Ord_OrderType  suppliedOrderType /* no restrictions */,
+  lsList         suppliedNodeList /* list of nodes Ntk_Node_t* from ordering file */,
+  int            verbose)
+{
+  lsList totalOrderList;      /* list of nodes (Ntk_Node_t *) */
+  long   initialTime = util_cpu_time();
+  
+  /*
+   * The condition where suppliedOrderType==InputAndLatch and
+   * generatedOrderType==All is not currently allowed because we're not sure
+   * if it's useful.
+   */
+  assert(!((suppliedOrderType == Ord_InputAndLatch_c)
+           && (generatedOrderType == Ord_All_c))); 
+
+  /*
+   * Either get a total ordering of the network nodes from suppliedNodeList,
+   * or compute it working from the network.
+   */
+  if ((suppliedOrderType == Ord_All_c)
+      || (suppliedOrderType == Ord_InputAndLatch_c)) {
+    totalOrderList = lsCopy(suppliedNodeList,
+			    (lsGeneric (*) (lsGeneric)) NULL);
+  }
+  else {
+    totalOrderList = Ord_NetworkOrderNodes(network, rootOrderMethod,
+                                           nodeOrderMethod, nsAfterSupport,
+                                           generatedOrderType,
+                                           suppliedOrderType,
+                                           suppliedNodeList, 
+                                           verbose);
+  }
+    
+
+  OrdNetworkAssignMddIds(network, generatedOrderType, totalOrderList, nsAfterSupport);
+  (void) lsDestroy(totalOrderList, (void (*) (lsGeneric)) NULL);
+
+  /*
+   * If nsAfterSupport is FALSE, this implies that NS comes right after PS.
+   *
+   */
+  if ( nsAfterSupport == FALSE ) {
+    lsGen tmpGen;
+    Ntk_Node_t *tmpLatch;
+ 
+   /*
+    * Iterate over each latch, and group the PS variable with the next
+    * variable in the ordering, which is guaranteed to be the corresponding NS
+    * variable.
+    */
+    Ntk_NetworkForEachLatch(network, tmpGen, tmpLatch) {
+      mdd_manager *mddMgr = Ntk_NetworkReadMddManager( network );
+	  Ntk_Node_t *nsNode = Ntk_NodeReadShadow( tmpLatch );
+      int psMddId = Ntk_NodeReadMddId( tmpLatch );
+      int nsMddId = Ntk_NodeReadMddId( nsNode );
+
+      /* 
+       * Group size = 2 ( ps and ns )
+       */
+      if (nsMddId == (psMddId+1)) {
+        MddGroupVariables(mddMgr, psMddId, 2);
+      }
+      /* Adnan's fix: See his mail to vis@ic on Oct 24, 1997 */
+      if (nsMddId == (psMddId-1)) {
+        MddGroupVariables(mddMgr, nsMddId, 2);
+      }
+    }
+  }
+
+  if (verbose > 0) {
+    long finalTime = util_cpu_time();
+    (void) fprintf(vis_stdout, "\nTotal ordering time = %2.1f\n",
+                   (finalTime-initialTime)/1000.0);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Orders the nodes of a network.]
+
+  Description [Orders the nodes of a network. The ordering is based solely on
+  the topology of the network, and is intended to be suitable for deriving an
+  MDD variable ordering by extracting those nodes for which MDD variables are
+  needed.  GeneratedOrderType can be either Ord_All_c or
+  Ord_InputAndLatch_c. If it is Ord_All_c, then every node (and latch NS) in
+  the network is ordered.  If it is Ord_InputAndLatch_c, then every primary
+  input, pseudo input, latch, and latch NS is ordered. <p>
+
+  SuppliedOrderType can be any of the following values: Ord_NextStateNode_c,
+  Ord_Partial_c, or Ord_Unassigned_c.  If it is Ord_Unassigned_c, then
+  suppliedNodeList is ignored, and there is no effect.  If it is *not*
+  Ord_Unassigned_c, then suppliedNodeList must be a non-empty list of
+  (pointers to) nodes. SuppliedNodeList can be used to specify the relative
+  order of some or the nodes.<p>
+
+  If suppliedOrderType is Ord_NextStateNode_c, then suppliedNodeList should
+  contain a complete list of next state nodes; the transitive fanins of the
+  latches are visited according to the order of the next state nodes in
+  suppliedNodeList.  If suppliedOrderType is Ord_Partial_c, then
+  suppliedNodeList may contain an arbitrary subset of network nodes; in this
+  case, an ordering is found disregarding suppliedNodeList, and then this
+  ordering is merged into the suppliedNodeList.  No checks are made to insure
+  that suppliedNodeList contains what is implied by the value of
+  suppliedOrderType.<p>
+
+  If nsAfterSupport is TRUE, then for a given latch, its next state variable
+  is ordered just after the latch's corresponding dataInput node. If
+  nsAfterSupport is FALSE, then for a given latch, its next state variable is
+  ordered just after the latch (i.e. its present state variable). (If the
+  latch itself is not present yet in the nodeOrderList, then first adds latch
+  to the end of the ordering.)]
+
+  SideEffects []
+
+  SeeAlso [Ord_NetworkOrderVariables]
+
+******************************************************************************/
+lsList
+Ord_NetworkOrderNodes(
+  Ntk_Network_t *network,
+  Ord_RootMethod rootOrderMethod,
+  Ord_NodeMethod nodeOrderMethod,
+  boolean        nsAfterSupport,
+  Ord_OrderType  generatedOrderType /* Ord_All_c or Ord_InputAndLatch_c */,
+  Ord_OrderType  suppliedOrderType  /* Ord_NextStateNode_c, Ord_Partial_c, or
+                                        Ord_Unassigned_c */, 
+  lsList         suppliedNodeList   /* list of nodes Ntk_Node_t* from ordering file */,
+  int            verbose)
+{
+  lsList      partialRootOrder;   /* list of nodes (Ntk_Node_t *) */
+  lsList      roots;              /* list of nodes (Ntk_Node_t *) */
+  lsList      nodeOrderList;      /* list of nodes (Ntk_Node_t *) */
+  st_table   *nodeToHandle;       /* Ntk_Node_t* to lsHandle */
+
+  /*
+   * Check the input arguments.
+   */
+  assert(   (generatedOrderType == Ord_All_c)
+         || (generatedOrderType == Ord_InputAndLatch_c));
+
+  assert(   (suppliedOrderType == Ord_NextStateNode_c)
+         || (suppliedOrderType == Ord_Partial_c)
+         || (suppliedOrderType == Ord_Unassigned_c));
+  
+
+  /*
+   * Compute an ordering on the roots. The nodes of the network are explored
+   * in DFS order from the roots, in the root order computed.  If
+   * suppliedOrderType is Ord_NextStateNode_c, then suppliedNodeList contains
+   * the next state nodes; this list serves as a seed to compute the root
+   * ordering.
+   */
+  partialRootOrder = (suppliedOrderType == Ord_NextStateNode_c)
+      ? LatchNSListConvertToLatchDataInputList(suppliedNodeList)
+      : (lsList) NULL;
+  roots = Ord_NetworkOrderRoots(network, rootOrderMethod,
+                                partialRootOrder, verbose);
+  if (suppliedOrderType == Ord_NextStateNode_c) {
+    (void) lsDestroy(partialRootOrder, (void (*) (lsGeneric)) NULL);
+  }
+  if (verbose > 0) {
+    (void) fprintf(vis_stdout, "\nOrder in which roots are visited:\n");
+    OrdNodeListWrite(vis_stdout, roots);
+  }
+  
+  /*
+   * Compute an order on all nodes in the transitive fanin of roots, including
+   * the roots themselves. Pass in an empty nodeToHandle table.
+   */
+  nodeToHandle  = st_init_table(st_ptrcmp, st_ptrhash);
+  nodeOrderList = OrdNetworkOrderTFIOfRoots(network, roots, nodeOrderMethod,
+                                            nodeToHandle, verbose);
+  (void) lsDestroy(roots, (void (*) (lsGeneric)) NULL);
+
+  if (verbose > 0) {
+    (void) fprintf(vis_stdout, "\nOrder of network nodes without NS:\n");
+    OrdNodeListWrite(vis_stdout, nodeOrderList);
+  }
+  
+  /*
+   * Add in the next state variables (represented by the shadow nodes of
+   * latches).
+   */
+  NetworkAddNSVarsToOrderList(network, nodeOrderList, nodeToHandle, nsAfterSupport);
+  if (verbose > 2) {
+    (void) fprintf(vis_stdout, "\nOrder of network nodes with NS:\n");
+    OrdNodeListWrite(vis_stdout, nodeOrderList);
+  }
+  
+  
+  /*
+   * There may be some nodes that are not in the TFI of any root. Put such
+   * nodes at the end of nodeOrderList (in no particular order).
+   */
+  NetworkAddDanglingNodesToOrderList(network, nodeOrderList, nodeToHandle);
+  st_free_table(nodeToHandle);
+  
+  /*
+   * If the suppliedOrderType is Partial, then merge (left, arbitrarily) the
+   * computed node order into the supplied node order and return the result.
+   * Otherwise, just return the nodeOrderList computed.
+   */
+  if (suppliedOrderType == Ord_Partial_c) {
+    lsList suppliedNodeListCopy = lsCopy(suppliedNodeList,
+					 (lsGeneric (*) (lsGeneric)) NULL);
+
+    Ord_ListMergeList(suppliedNodeListCopy, nodeOrderList, Ord_ListMergeLeft_c);
+    (void) lsDestroy(nodeOrderList, (void (*) (lsGeneric)) NULL);
+    return suppliedNodeListCopy;
+  }
+  else {
+    return nodeOrderList;
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Assigns an mddId to a node.]
+
+  Description [Assigns an mddId to a node.  If the node already has a valid
+  mddId (i.e. it is not NTK_UNASSIGNED_MDD_ID), then nothing is done.
+  Otherwise, the node is assigned an mddId, and this Id is created within the
+  MDD manager of the network. (An MDD manager is created for the network if
+  the network doesn't already have one.) ]
+
+  SideEffects []
+
+  Comment [(Tom): this should be more intelligent, and get the id from the
+  total ordering on all the network nodes, and then do insertion into variable
+  ordering.  Use ntk appl info to store total node order.]
+  
+******************************************************************************/
+void
+Ord_NetworkAssignMddIdForNode(
+  Ntk_Network_t *network,
+  Ntk_Node_t    *node)
+{
+  if (Ntk_NodeReadMddId(node) != NTK_UNASSIGNED_MDD_ID) {
+    return;
+  }
+  else {
+    int          mddId;
+    mdd_manager *mddManager = Ntk_NetworkReadMddManager(network);
+    array_t     *mvarValues = array_alloc(int, 0);
+    array_t     *mvarNames  = array_alloc(char *, 0);
+  
+    /*
+     * If the network doesn't already have an MDD manager, then create one.  In
+     * any case, set mddId to be the number of variables currently existing in
+     * the manager.
+     */
+    if (mddManager == NIL(mdd_manager)) {
+      mddManager = Ntk_NetworkInitializeMddManager(network);
+      mddId = 0;
+    }
+    else {
+      array_t *mvarArray  = mdd_ret_mvar_list(mddManager);
+      mddId = array_n(mvarArray);
+    }
+  
+    Ntk_NodeSetMddId(node, mddId);
+
+    array_insert_last(int, mvarValues,
+                      Var_VariableReadNumValues(Ntk_NodeReadVariable(node)));
+    array_insert_last(char *, mvarNames, Ntk_NodeReadName(node));
+
+    /*
+     * Create the variable in the MDD manager.  The last argument being NIL
+     * means that the variable will not be interleaved.
+     */
+    mdd_create_variables(mddManager, mvarValues, mvarNames, NIL(array_t));
+
+    array_free(mvarValues);
+    array_free(mvarNames);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Merges left list2 into list1, using the provided table for efficiency.]
+
+  Description [Merges left list2 into list1, using the provided table for
+  efficiency. dataToHandle1 is a hash table mapping each item in list1 to its
+  handle in list1. <p>
+
+  This function implements the merge described in Algorithm 1 by Fujii et al.,
+  "Interleaving Based Variable Ordering Methods for OBDDs", ICCAD 1993, p. 38.
+  For each item in list2: if item is already present in list1, do nothing;
+  else if item is the head of list2, then insert item at the head of list1;
+  else, insert item into list1 immediately following the location in list1 of
+  the item's predessor item in list2. This has the effect of locating the
+  items in list2 as far to the left as possible in list1, while still
+  preserving the partial order for those elements of list2 not initially
+  appearing in list1 (a "merge left"). Examples:
+
+  <pre>
+  list1=abc, list2=dbe --> list1=dabec
+  list1=abc, list2=deb --> list1=deabc.
+  </pre>
+
+  Note that this merging is not commutative.  That is, Ord_ListMergeLeftList(l1,l2)
+  may give a different ordering than Ord_ListMergeLeftList(l2,l1).]
+  
+  SideEffects [List1 is modified, and dataToHandle1 is modified to reflect the
+  newly inserted items.]
+
+  Comment     [All references to "handle" in the code are references to
+  handles in list1.  We never reference or care about handles in list2. ]
+
+  SeeAlso [Ord_ListMergeRightListUsingTable]
+
+******************************************************************************/
+void
+Ord_ListMergeLeftListUsingTable(
+  lsList    list1,
+  lsList    list2,
+  st_table *dataToHandle1)
+{
+  lsGen      gen1;   /* generator for list1 */
+  lsGen      gen2;   /* generator for list2 */
+  lsHandle   handle; /* handle of an item in list1 */
+  lsGeneric  data;   
+  lsGeneric  prevData;
+
+  /*
+   * Walk through list2 forwards, keeping track of the previous item just visited.
+   */
+  gen2 = lsStart(list2);
+  prevData = NULL;
+  while (lsNext(gen2, &data, LS_NH) == LS_OK) {
+
+    if (!st_is_member(dataToHandle1, (char *) data)) {
+      /*
+       * Data is not present in list1, so we must insert it at the proper
+       * location.
+       */
+      if (prevData == NULL) {
+        /*
+         * Data is the head of list2, so insert it at the head of list1.
+         */
+        (void) lsNewBegin(list1, data, &handle);
+      }
+      else {
+        lsGeneric dummyData;
+        lsHandle  prevHandle;
+
+        /*
+         * Data is not the head of list1.  Hence, insert it just to the right
+         * of the location of prevData in list1 (by induction, prevData must
+         * currently exist in list1). Do this by getting the handle of
+         * prevData in list1, creating a generator initialized to just after
+         * prevData, and then inserting data at this point. Note that
+         * lsInAfter and lsInBefore are equivalent in this case, since we
+         * immediately kill gen1. 
+         */
+        st_lookup(dataToHandle1, prevData, &prevHandle);
+        gen1 = lsGenHandle(prevHandle, &dummyData, LS_AFTER);
+        (void) lsInAfter(gen1, data, &handle);
+        (void) lsFinish(gen1);
+      }
+      st_insert(dataToHandle1, data, handle);
+
+    } /* else, data already present in list1, so do nothing */
+
+    prevData = data;
+
+  } /* end while */
+  (void) lsFinish(gen2);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Merges right list2 into list1, using the provided table for efficiency.]
+
+  Description [Merges right list2 into list1, using the provided table for
+  efficiency. This function is the same as Ord_ListMergeLeftListUsingTable,
+  except that a "merge right" is done, rather than a "merge left".  For each
+  item in list2: if item is already present in list1, do nothing; else if item
+  is the tail of list2, then insert item at the tail of list1; else, insert
+  item into list1 immediately preceeding the location in list1 of the item's
+  successor item in list2. This has the effect of locating the items in list2
+  as far to the right as possible in list1, while still preserving the partial
+  order for those elements of list2 not initially appearing in list1 (a "merge
+  right"). Examples:
+
+  <pre>
+  list1=abc, list2=dbe --> list1=adbce
+  list1=abc, list2=deb --> list1=adebc.
+  </pre>
+
+  ]
+  
+  SideEffects [List1 is modified, and dataToHandle1 is modified to reflect the
+  newly inserted items.]
+
+  Comment     [All references to "handle" in the code are references to
+  handles in list1.  We never reference or care about handles in list2. ]
+  
+  SeeAlso [Ord_ListMergeLeftListUsingTable]
+
+******************************************************************************/
+void
+Ord_ListMergeRightListUsingTable(
+  lsList    list1,
+  lsList    list2,
+  st_table *dataToHandle1)
+{
+  lsGen      gen1;   /* generator for list1 */
+  lsGen      gen2;   /* generator for list2 */
+  lsHandle   handle; /* handle of an item in list1 */
+  lsGeneric  data;   
+  lsGeneric  succData;
+
+  /*
+   * Walk through list2 backwards, keeping track of the successor item just visited.
+   */
+  gen2 = lsEnd(list2);
+  succData = NULL;
+  while (lsPrev(gen2, &data, LS_NH) == LS_OK) {
+
+    if (!st_is_member(dataToHandle1, (char *) data)) {
+      /*
+       * Data is not present in list1, so we must insert it at the proper
+       * location.
+       */
+      if (succData == NULL) {
+        /*
+         * Data is the tail of list2, so insert it at the tail of list1.
+         */
+        (void) lsNewEnd(list1, data, &handle);
+      }
+      else {
+        lsGeneric dummyData;
+        lsHandle  succHandle;
+
+        /*
+         * Data is not the tail of list1.  Hence, insert it just to the left
+         * of the location of succData in list1 (by induction, succData must
+         * currently exist in list1). Do this by getting the handle of
+         * succData in list1, creating a generator initialized to just before
+         * succData, and then inserting data at this point. Note that
+         * lsInAfter and lsInBefore are equivalent in this case, since we are
+         * immediately kill gen1. 
+         */
+        st_lookup(dataToHandle1, succData, &succHandle);
+        gen1 = lsGenHandle(succHandle, &dummyData, LS_BEFORE);
+        (void) lsInAfter(gen1, data, &handle);
+        (void) lsFinish(gen1);
+      }
+      st_insert(dataToHandle1, data, handle);
+
+    } /* else, data already present in list1, so do nothing */
+
+    succData = data;
+
+  } /* end while */
+  (void) lsFinish(gen2);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Merges list2 into list1, using the provided table for efficiency.]
+
+  Description [Merges list2 into list1, using the provided table for
+  efficiency. Calls Ord_ListMergeLeftListUsingTable or
+  Ord_ListMergeRightListUsingTable depending on the value of method.]
+
+  SideEffects [list1 is modified]
+
+  SeeAlso [Ord_ListMergeLeftListUsingTable Ord_ListMergeRightListUsingTable]
+
+******************************************************************************/
+void
+Ord_ListMergeListUsingTable(
+  lsList               list1,
+  lsList               list2,
+  st_table            *dataToHandle1,
+  Ord_ListMergeMethod  method)
+{
+  if (method == Ord_ListMergeLeft_c) {
+    Ord_ListMergeLeftListUsingTable(list1, list2, dataToHandle1);
+  }
+  else if (method == Ord_ListMergeRight_c) {
+    Ord_ListMergeRightListUsingTable(list1, list2, dataToHandle1);
+  }
+  else {
+    fail("unrecognized method");
+  }
+}
+    
+
+/**Function********************************************************************
+
+  Synopsis    [Merges list2 into list1.]
+
+  Description [Merges list2 into list1. Creates a hash table mapping the items
+  of list1 to their handles in list1, and then calls Ord_ListMergeListUsingTable.]
+
+  SideEffects [list1 is modified]
+
+  SeeAlso     [Ord_ListMergeListUsingTable]
+
+******************************************************************************/
+void
+Ord_ListMergeList(
+  lsList              list1,
+  lsList              list2,
+  Ord_ListMergeMethod method)
+{
+  lsGen      gen1;   /* generator for list1 */
+  lsHandle   handle; /* handle of an item in list1 */
+  lsGeneric  data;   
+  st_table  *dataToHandle1 = st_init_table(st_ptrcmp, st_ptrhash);
+
+  /*
+   * Load a hash table mapping each item in list1 to its handle in list1.
+   */
+  gen1 = lsStart(list1);
+  while (lsNext(gen1, &data, &handle) == LS_OK) {
+    st_insert(dataToHandle1, (char *) data, (char *) handle);
+  }
+  (void) lsFinish(gen1);
+
+  Ord_ListMergeListUsingTable(list1, list2, dataToHandle1, method);
+
+  st_free_table(dataToHandle1);
+}
+
+  
+/**Function********************************************************************
+
+  Synopsis    [Appends list2 into list1.]
+
+  Description [Appends list2 into list1. List1 is modified; list2 is not
+  changed.]
+
+  SideEffects [list1 is modified]
+
+******************************************************************************/
+void
+Ord_ListAppendList(
+  lsList list1,
+  lsList list2)
+{
+  lsGen gen;
+  lsHandle handle; /* unused */
+  lsGeneric data;   
+
+  /*
+   * Walk through list2 forwards, inserting each element to the end of list1.
+   */
+  gen = lsStart(list2);
+  while (lsNext(gen, &data, LS_NH) == LS_OK) {
+    (void) lsNewEnd(list1, data, &handle);
+  } 
+  (void) lsFinish(gen);
+}
+
+  
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Compares the depth of two nodes in an lsList.]
+
+  Description [Compares the depth of two nodes in an lsList. Greater depth
+  node should appear before a lower depth node.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+OrdNodesFromListCompareDepth(
+  lsGeneric node1,
+  lsGeneric node2)
+{
+  return NodesCompareDepth((Ntk_Node_t *) node1, (Ntk_Node_t *) node2);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compares the depth of two nodes in an array_t.]
+
+  Description [Compares the depth of two nodes in an array_t. Greater depth
+  node should appear before a lower depth node.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+OrdNodesFromArrayCompareDepth(
+  const void * node1,
+  const void * node2)
+{
+  return NodesCompareDepth(*(Ntk_Node_t **) node1, *(Ntk_Node_t **) node2);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the depth of each node in the TFI of roots.]
+
+  Description [Computes the depth of each node in the transitive fanin of the
+  list of roots. The depth of a node is defined inductively: latches, and
+  nodes with no inputs, have depth 0. Otherwise, the depth of a node is 1 more
+  than the maximum depth over the node's fanins.  Intuitively, the depth of a
+  node is the length of the longest (backward) path from the node to a latch,
+  primary input, pseudo input, or constant.]
+
+  SideEffects [Uses undef field of Ntk_Node_t.]
+
+  SeeAlso     [Ord_NetworkOrderVariables]
+
+******************************************************************************/
+void
+OrdNetworkComputeNodeDepths(
+  Ntk_Network_t * network,
+  lsList  roots /* list of Ntk_Node_t  */)
+{
+  lsGen       gen;
+  Ntk_Node_t *node;
+  Ntk_Node_t *root;
+
+  /*
+   * Initialize the depth of each node to unassigned.
+   */
+  Ntk_NetworkForEachNode(network, gen, node) {
+    NodeSetDepth(node, ORDUNASSIGNED_DEPTH);
+  }
+
+  /*
+   * Start the recursive computation from each root.
+   */
+  lsForEachItem(roots, gen, root) {
+    (void) NodeComputeDepth(root);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the names of a list of nodes, one per line.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+OrdNodeListWrite(
+  FILE *fp,
+  lsList nodeList)
+{
+  lsGen gen;
+  Ntk_Node_t *node;
+
+  lsForEachItem(nodeList, gen, node) {
+    (void) fprintf(fp, "%s\n", Ntk_NodeReadName(node));
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the depth of a node.]
+
+  SideEffects []
+
+  Comment [The depth is not stored in a hash table of orderingState, because,
+  for OrdNodesFromArrayCompareDepth, we need to be able to access the depth of
+  a node given *just* the node.]
+
+  SeeAlso     [NodeSetDepth OrdNodesFromArrayCompareDepth
+  OrdNodesFromListCompareDepth] 
+
+******************************************************************************/
+long
+OrdNodeReadDepth(
+  Ntk_Node_t * node)
+{
+  return ((long) Ntk_NodeReadUndef(node));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Assigns consecutive MDD ids to nodes in orderList.]
+
+  Description [Assigns consecutive MDD ids to nodes in orderList.  Ids are
+  assigned starting from the number of variables in the MDD manager of
+  network.  (An MDD manager is created for the network if the network doesn't
+  already have one.) OrderType can be Ord_All_c or Ord_InputAndLatch_c.  If
+  orderType is Ord_All_c, then all nodes in orderList are assigned an id.  If
+  orderType is Ord_InputAndLatch_c only primary inputs, pseudo input, latches,
+  and latch NSs are assigned ids. Presently, nsAfterSupport is unused.<p>]
+
+  SideEffects []
+
+  SeeAlso     [OrdNetworkOrderTFIOfRoots Ntk_NetworkInitializeMddManager]
+
+******************************************************************************/
+void
+OrdNetworkAssignMddIds(
+  Ntk_Network_t * network,
+  Ord_OrderType  orderType,
+  lsList  orderList,
+  boolean nsAfterSupport)
+{
+  lsGen        gen;
+  Ntk_Node_t  *node;
+  int          mddId;
+  mdd_manager *mddManager = Ntk_NetworkReadMddManager(network);
+  array_t     *mvarValues = array_alloc(int, lsLength(orderList));
+  array_t     *mvarNames  = array_alloc(char *, lsLength(orderList));
+
+  assert((orderType == Ord_All_c) || (orderType == Ord_InputAndLatch_c));
+
+  /*
+   * If the network doesn't already have an MDD manager, then create one.  In
+   * any case, set mddId to be the number of variables currently existing in
+   * the manager.
+   */
+  if (mddManager == NIL(mdd_manager)) {
+    mddManager = Ntk_NetworkInitializeMddManager(network);
+    mddId = 0;
+  }
+  else {
+    array_t *mvarArray  = mdd_ret_mvar_list(mddManager);
+    mddId = array_n(mvarArray);
+  }
+  
+  lsForEachItem(orderList, gen, node) {
+    /*
+     * A node gets an MDD id if node is a combinational input, next state
+     * node, or orderType is Ord_All_c.
+     */
+    if (Ntk_NodeTestIsCombInput(node) || Ntk_NodeTestIsNextStateNode(node)
+        || (orderType == Ord_All_c) ) {
+
+      Ntk_NodeSetMddId(node, mddId);
+      mddId++;
+
+      array_insert_last(int, mvarValues,
+                        Var_VariableReadNumValues(Ntk_NodeReadVariable(node)));
+      array_insert_last(char *, mvarNames, Ntk_NodeReadName(node));
+    }
+  }
+
+  /*
+   * Create the variables in the MDD manager.  The last argument being NIL
+   * means that the variables will not be interleaved.
+   */
+  mdd_create_variables(mddManager, mvarValues, mvarNames, NIL(array_t));
+
+  array_free(mvarValues);
+  array_free(mvarNames);
+}
+    
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Compares depths of node1 and node2 for sorting; greater depth
+  node should appear before a lower depth node.  Ties are broken based on the
+  node names; it's an error if the two nodes have the same name.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+NodesCompareDepth(
+  Ntk_Node_t *node1,
+  Ntk_Node_t *node2)
+{
+  long depth1 = OrdNodeReadDepth(node1);
+  long depth2 = OrdNodeReadDepth(node2);
+
+  if (depth1 > depth2) {
+    return -1;
+  }
+  else if (depth1 < depth2) {
+    return 1;
+  }
+  else {
+    char *name1 = Ntk_NodeReadName(node1);
+    char *name2 = Ntk_NodeReadName(node2);
+
+    /*
+     * As a tiebreaker, sort based on name, so that the sorted result is not
+     * sensitive to the order in which the nodes are passed to the compare
+     * function. When sorting based on name, the order doesn't really matter,
+     * but right now it's done so that "foo<i>" will come before "foo<j>" in
+     * the ordering, where i < j.  This is just a little heuristic to put lower
+     * order bits first. */
+    if (strcmp(name1, name2) < 0) {
+      return -1;
+    }
+    else if (strcmp(name1, name2) > 0) {
+      return 1;
+    }
+    else {
+      return 0;
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the depth of a node.]
+
+  SideEffects []
+
+  SeeAlso     [OrdNetworkComputeNodeDepths]
+
+******************************************************************************/
+static long
+NodeComputeDepth(
+  Ntk_Node_t * node)
+{
+  long depth = OrdNodeReadDepth(node);
+
+  /*
+   * If the node's depth has already been computed (i.e. it's not unassigned),
+   * then just return it below.  If it's unassigned, then recursively compute
+   * it.
+   */
+  if (depth == ORDUNASSIGNED_DEPTH) {
+
+    if (Ntk_NodeTestIsCombInput(node) || Ntk_NodeTestIsConstant(node)) {
+      /*
+       * Latches, and nodes with no fanins, get depth 0. This is the terminal
+       * case of recursion. 
+       */
+      depth = 0;
+    }
+    else {
+      int         i;
+      Ntk_Node_t *fanin;
+      /*
+       * Compute the depth of each fanin node in the support of node, and
+       * maintain the maximum.  We start depth at 0 for max calculation.
+       */
+      depth = 0;
+      Ntk_NodeForEachFanin(node, i, fanin) {  
+        long faninDepth = NodeComputeDepth(fanin);
+
+        depth = (depth > faninDepth) ? depth : faninDepth;
+      }
+      
+      /*
+       * The depth of node is one more than the max depths of its fanins.
+       */
+      depth++;
+    }
+
+    /*
+     * Store the depth.
+     */
+    NodeSetDepth(node, depth);
+  }
+  
+  return depth;
+}
+
+  
+/**Function********************************************************************
+
+  Synopsis    [Adds to nodeOrderList all network nodes not currently in the list.]
+
+  Description [Adds to the end of nodeOrderList all network nodes that are not
+  yet present in nodeOrderList.  This is used to pick up those (dangling)
+  nodes that weren't in the transitive fanins of the roots in the call to
+  OrdNetworkOrderTFIOfRoots. nodeToHandle is a hash table mapping each node in
+  nodeOrderList to its handle in the list; dangling nodes are inserted into
+  this table.]
+
+  SideEffects [nodeOrderList and nodeToHandle will be modified if dangling
+  nodes exist.]
+
+  SeeAlso     [OrdNetworkOrderTFIOfRoots]
+
+******************************************************************************/
+static void
+NetworkAddDanglingNodesToOrderList(
+  Ntk_Network_t * network,
+  lsList  nodeOrderList /* of Ntk_Node_t*  */,
+  st_table *nodeToHandle /* Ntk_Node_t* to lsHandle */)
+{
+  lsGen       gen;
+  Ntk_Node_t *node;
+
+  /*
+   * For each network node, if it's not in nodeOrderList, then add it to the
+   * end of the list. 
+   * (NOTE: may be sensitive to ordering in memory.)
+   */
+  Ntk_NetworkForEachNode(network, gen, node) {
+    if (!st_is_member(nodeToHandle, (char *) node)) {
+      lsHandle handle;
+      
+      (void) lsNewEnd(nodeOrderList, (lsGeneric) node, &handle);
+      st_insert(nodeToHandle, (char *) node, (char *) handle);
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adds to nodeOrderList all next state variables.]
+
+  Description [Adds to nodeOrderList all next state variables. If
+  nsAfterSupport is TRUE, then for a given latch, its NS variable is added in
+  nodeOrderList just after the latch's corresponding dataInput node. If
+  nsAfterSupport is FALSE, then for a given latch, its NS variable is added in
+  nodeOrderList just after the latch (i.e. its present state variable). (If the
+  latch itself is not present yet in the nodeOrderList, then first adds latch
+  to the end of the ordering.)<p>
+
+  nodeToHandle is a hash table mapping each node in nodeOrderList to its
+  handle in the list; next state nodes are inserted into this table.]
+
+  SideEffects [nodeOrderList and nodeToHandle will be modified if latches
+  exist.]
+
+  SeeAlso     [OrdNetworkOrderTFIOfRoots]
+
+******************************************************************************/
+static void
+NetworkAddNSVarsToOrderList(
+  Ntk_Network_t * network,
+  lsList  nodeOrderList /* of Ntk_Node_t  */,
+  st_table *nodeToHandle /* Ntk_Node_t* to lsHandle */,
+  boolean nsAfterSupport)
+{
+  lsGen       gen1;
+  Ntk_Node_t *latch;
+
+  /*
+   * For each latch, add the latch's corresponding NS node to the ordering.
+   * (NOTE: may be sensitive to ordering in memory.)
+   */
+  Ntk_NetworkForEachLatch(network, gen1, latch) {
+    lsHandle    handle;
+    lsGen       gen2;
+    lsGeneric   dummyData;
+    Ntk_Node_t *latchNS   = Ntk_NodeReadShadow(latch);
+
+    if (nsAfterSupport) {
+      /* Add just after the latch's dataInput. */
+      lsHandle    dataInputHandle;
+      Ntk_Node_t *dataInput = Ntk_LatchReadDataInput(latch);
+      int         status UNUSED = st_lookup(nodeToHandle, dataInput,
+					    &dataInputHandle);
+
+      assert(status);
+      gen2 = lsGenHandle(dataInputHandle, &dummyData, LS_AFTER);
+    }
+    else {
+      /* Add just after the latch. */
+      lsHandle latchHandle;
+      int      status = st_lookup(nodeToHandle, latch, &latchHandle);
+
+      if (!status) {
+        /*
+         * Latch itself is not yet in the ordering.  This can happen if the
+         * latch is not in the TFI of any other latch.  So add the latch first
+         * (at the end of the ordering). 
+         */
+        (void) lsNewEnd(nodeOrderList, (lsGeneric) latch, &latchHandle);
+        st_insert(nodeToHandle, (char *) latch, (char *) latchHandle);
+      }
+    
+      gen2 = lsGenHandle(latchHandle, &dummyData, LS_AFTER);
+    }
+
+    /* Actually add to list here. */
+    (void) lsInAfter(gen2, (lsGeneric) latchNS, &handle);  
+    st_insert(nodeToHandle, (char *) latchNS, (char *) handle);
+    (void) lsFinish(gen2);
+      
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Converts a list of latch next state nodes to the corresponding
+  list of latch data input nodes.]
+
+  SideEffects []
+
+******************************************************************************/
+static lsList
+LatchNSListConvertToLatchDataInputList(
+  lsList latchNSList)
+{
+  lsGen       gen;
+  Ntk_Node_t *node;
+  Ntk_Node_t *latch;
+  lsList      latchDataInputList = lsCreate();
+
+  lsForEachItem(latchNSList, gen, node) {
+    assert(Ntk_NodeTestIsNextStateNode(node));
+    latch = Ntk_ShadowReadOrigin(node);
+    (void) lsNewEnd(latchDataInputList, (lsGeneric)
+                    Ntk_LatchReadDataInput(latch), LS_NH); 
+  }
+
+  return latchDataInputList;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the depth of a node.]
+
+  SideEffects []
+
+  SeeAlso     [OrdNodeReadDepth]
+
+******************************************************************************/
+static void
+NodeSetDepth(
+  Ntk_Node_t * node,
+  long depth)
+{
+  Ntk_NodeSetUndef(node, (void *) depth);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Group all bdd vars corresponding to mdd vars initMddId to
+  initMddId + (blockSize-1) in a block which will not be split in reordering.]
+
+  Description [Group all bdd vars corresponding to mdd vars initMddId to
+  initMddId + blockSize in a block which will not be reordered internally.
+  Ths bdd's corresponding to these mdd's should be contiguous; if not the
+  function will fail.]
+
+  SideEffects []
+
+******************************************************************************/
+
+static void
+MddGroupVariables(
+  mdd_manager *mddMgr,
+  int initMddId,
+  int blockSize )
+{
+  int i, j;
+  int length;
+  int aIndex;
+  int startingBddIndex;
+  int sanityCheck;
+  mvar_type initMv, anMv;
+  bvar_type initBvar, aBvar;
+  array_t *mvar_list, *bvar_list;
+  bdd_t *bdd;
+  
+  mvar_list = mdd_ret_mvar_list(mddMgr);
+  bvar_list = mdd_ret_bvar_list(mddMgr);
+
+  /*
+   * mvar for initMddId 
+   */
+  initMv = array_fetch(mvar_type, mvar_list, initMddId);
+
+  /*
+   * bvar for first bdd for initMddId 
+   */
+  initBvar = mdd_ret_bvar(&initMv, 0, bvar_list);
+
+  /*
+   * number of bdd variables to group 
+   */
+  length = 0;
+
+  /*
+   * startingBddIndex is the level of the first bdd variable 
+   */
+  startingBddIndex = bdd_top_var_level( mddMgr, initBvar.node );
+  sanityCheck = startingBddIndex;
+
+  /*
+   * in this loop we are simply ensuring that the bdd variables
+   * corresponding to the mdd vars are infact contiguous. If this
+   * is not the case we fail. length is the total number of bdd variables
+   * to be grouped.
+   */
+  for( i = 0; i < blockSize; i++) {
+    anMv = array_fetch(mvar_type, mvar_list, ( initMddId + i ) );
+    for ( j = 0 ; j < anMv.encode_length; j++ ) {
+
+      aBvar = mdd_ret_bvar( & anMv, j, bvar_list );
+      aIndex = bdd_top_var_level( mddMgr,  aBvar.node );
+
+      if ( sanityCheck != aIndex ) {
+        /* bdd vars are not contiguous!! */
+        fprintf(vis_stderr, "Badly formed block - bdd vars for %s (mvar_id = %d) are not contiguous!!\n",
+                             anMv.name, anMv.mvar_id );
+        fail("Wont go on\n");
+      }
+      else {
+        /* number of variables to group increased by one */
+        sanityCheck++;
+        length++;
+      }
+    }
+  }
+
+  bdd = bdd_var_with_index(mddMgr, startingBddIndex);
+  (void) bdd_new_var_block(bdd, length);
+  bdd_free(bdd);
+}
+
+
Index: vis_dev/vis-2.3/src/ord/ordNodes.c
===================================================================
--- vis_dev/vis-2.3/src/ord/ordNodes.c	(revision 14)
+++ vis_dev/vis-2.3/src/ord/ordNodes.c	(revision 14)
@@ -0,0 +1,841 @@
+/**CFile***********************************************************************
+
+  FileName    [ordNodes.c]
+
+  PackageName [ord]
+
+  Synopsis    [Routines to order the nodes in the TFI of the roots of a network.]
+
+  Description [Routines to order the nodes in the TFI of the roots of a
+  network. To add a new method, create a new value for the Ord_NodeMethod
+  enumerated type, and add a call to the new procedure from
+  OrdNetworkOrderTFIOfRoots.]
+
+  Author      [Tom Shiple and Fabio Somenzi]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ordInt.h"
+
+static char rcsid[] UNUSED = "$Id: ordNodes.c,v 1.12 2005/04/16 06:15:25 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+/**Struct**********************************************************************
+
+  Synopsis    [State needed for performing variable ordering.]
+
+  SeeAlso     [NetworkInitializeOrderingState OrderingStateFree]
+
+******************************************************************************/
+typedef struct OrderingStateStruct {
+  st_table *nodeToOrderList;	/* Ntk_Node_t * to lsList; top. order of tfi
+                                   nodes */
+  st_table *from;		/* Ntk_Node_t * to Ntk_Node_t */
+  lsGen last;			/* insertion point */
+  Ntk_Node_t *root;		/* current output */
+} OrderingState_t;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static lsList NetworkOrderTFIOfRootsByMerging(Ntk_Network_t *network, lsList roots, Ord_ListMergeMethod method, st_table *nodeToHandle, int verbose);
+static lsList NodeOrderRecursivelyByMerging(Ntk_Node_t * node, OrderingState_t * orderingState, Ord_ListMergeMethod method, int verbose);
+static lsList NetworkOrderTFIOfRootsByAppending(Ntk_Network_t *network, lsList roots, st_table *nodeToHandle, int verbose);
+static void NodeOrderRecursivelyByAppending(Ntk_Node_t * node, lsList orderList, st_table *nodeToHandle, int verbose);
+static lsList NetworkOrderTFIOfRootsByInterleaving(Ntk_Network_t *network, lsList roots, st_table *nodeToHandle, int verbose);
+static void NodeOrderRecursivelyByInterleaving(Ntk_Node_t * node, lsList orderList, st_table *nodeToHandle, OrderingState_t *orderingState, int verbose);
+static OrderingState_t * NetworkInitializeOrderingState(Ntk_Network_t * network);
+static void OrderingStateSetLast(Ntk_Node_t * node, st_table * nodeToHandle, OrderingState_t * orderingState);
+static void OrderingStateFree(OrderingState_t * orderingState);
+static lsList NodeReadOrderList(Ntk_Node_t * node, OrderingState_t * orderingState);
+static void NodeSetOrderList(Ntk_Node_t * node, lsList orderList, OrderingState_t * orderingState);
+static Ntk_Node_t * NodeReadFrom(Ntk_Node_t * node, OrderingState_t * orderingState);
+static void NodeSetFrom(Ntk_Node_t * node, OrderingState_t * orderingState);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Orders the nodes of a network in TFI of roots.]
+
+  Description [Orders the nodes of a network that are in the transitive fanin
+  of the list of roots, including the roots themselves.  The roots are visited
+  in the order given in the root list.  Combinational inputs (primary inputs,
+  pseudo inputs, and latches) and constants terminate the recursion.  If you
+  want a latch next state function to be a root, then the corresponding data
+  input should be in the root list, not the latch itself. Note that next state
+  variables are not included in the ordering; these should be added as a
+  post-processing step.<p>
+
+  The different node ordering methods are documented in the static_order
+  command. If nodeMethod is Ord_NodesByDefault_c, then one of the ordering
+  methods is called by default.<p>
+
+  nodeToHandle should be an empty table created using st_init_table(st_ptrcmp,
+  st_ptrhash).  For every node in the returned list, there is an entry in
+  nodeToHandle mapping the node to the node's handle in the returned list.]
+
+  SideEffects [nodeToHandle table is modified]
+
+  SeeAlso     [Ord_NetworkOrderRoots]
+
+******************************************************************************/
+lsList
+OrdNetworkOrderTFIOfRoots(
+  Ntk_Network_t *network,
+  lsList  roots /* of Ntk_Node_t  */,
+  Ord_NodeMethod nodeOrderMethod,
+  st_table *nodeToHandle /* modified */,
+  int verbose)
+{
+  switch (nodeOrderMethod) {
+    case Ord_NodesByDefault_c:
+    case Ord_NodesByInterleaving_c:
+      return NetworkOrderTFIOfRootsByInterleaving(network, roots,
+						  nodeToHandle, verbose);
+    case Ord_NodesByMergingLeft_c:
+      return NetworkOrderTFIOfRootsByMerging(network, roots,
+					     Ord_ListMergeLeft_c,
+                                             nodeToHandle, verbose);
+    case Ord_NodesByMergingRight_c:
+      return NetworkOrderTFIOfRootsByMerging(network, roots,
+					     Ord_ListMergeRight_c,
+                                             nodeToHandle, verbose);
+    case Ord_NodesByAppending_c:
+      return NetworkOrderTFIOfRootsByAppending(network, roots,
+					       nodeToHandle, verbose);
+    default:
+      fail("unrecognized node ordering method");
+      return (lsList) 0;
+  }
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Orders the nodes of a network by the merging method.]
+
+  Description [Orders the nodes of a network by the merging method.  The
+  parameters are the same as in OrdNetworkOrderTFIOfRoots.<p>
+  
+  This function implements an algorithm alluded to in Section 3.2 of Fujii et
+  al., "Interleaving Based Variable Ordering Methods for OBDDs", ICCAD 1993,
+  p. 38.  The ordering returned is a topological ordering.  The algorithm
+  works as follows.  For every node, a topological ordering on the tfi nodes
+  is created and stored at the node.  This is done recursively.  For leaves of
+  the recursion, a trivial list of length 1 is created.  For the general case,
+  the order lists at the fanins are merged together, and then the node itself
+  is appended to the end of the list.  The merging is done from the highest
+  priority fanin to the lowest priority, where a "merge right" or "merge
+  right" is performed, depending on the value of method. Nodes with greater
+  depth have higher priority.<p>
+
+  TODO: This function is consuming more memory than is
+  necessary. Specifically, a node list is computed and stored at each network
+  node.  Currently, this list is not freed until the very end of the node
+  ordering computation.  Instead, a reference count could be precomputed for
+  each node, and when this falls to zero, the list can be immediately freed.]
+
+  SideEffects [nodeToHandle table is modified]
+
+  SeeAlso     [OrdNetworkOrderTFIOfRoots NodeOrderRecursivelyByMerging
+  OrdNetworkComputeNodeDepths]
+
+******************************************************************************/
+static lsList
+NetworkOrderTFIOfRootsByMerging(
+  Ntk_Network_t *network,
+  lsList  roots /* list of Ntk_Node_t  */,
+  Ord_ListMergeMethod method,
+  st_table *nodeToHandle /* modified */,
+  int verbose)
+{
+  lsGen            gen;
+  Ntk_Node_t      *root;
+  OrderingState_t *orderingState;
+  lsList           orderList = lsCreate(); /* return list */
+
+  
+  /*
+   * Compute and store the depth of each node in the network.  (The depth of a
+   * node is stored in the undef field of the node).
+   */
+  OrdNetworkComputeNodeDepths(network, roots);
+
+  /*
+   * Initialize the necessary state needed for recursing through the network.
+   */
+  orderingState = NetworkInitializeOrderingState(network);
+
+  /*
+   * For each root, recursively order all nodes in its transitive fanin, and
+   * merge this ordering into the nodes already ordered.
+   */
+  lsForEachItem(roots, gen, root) {
+    lsList rootOrderList = NodeOrderRecursivelyByMerging(root, orderingState,
+                                                         method, verbose);
+    Ord_ListMergeListUsingTable(orderList, rootOrderList, nodeToHandle, method);
+
+    if (verbose > 2) {
+      /* This can generate a lot of output. */
+      (void) fprintf(vis_stdout, "\nOrder list after merging node %s\n",
+                     Ntk_NodeReadName(root));
+      OrdNodeListWrite(vis_stdout, orderList);
+    }
+  }
+  
+  /*
+   * Clean up and return the ordering list.
+   */
+  OrderingStateFree(orderingState);
+  return orderList;
+}
+
+  
+/**Function********************************************************************
+
+  Synopsis    [Orders the fanins of a node, and then orders the node itself.]
+
+  Description [Orders the fanins of a node, and then orders the node
+  itself. The fanins of a node are visited in order of decreasing depth, and
+  their orderings are merged.  The node appears in the order just after its
+  fanins, yielding a topological order.  If node has already been visited,
+  then simply return the order previously found.]
+
+  SideEffects []
+
+  SeeAlso     [OrdNetworkComputeNodeDepths NetworkOrderTFIOfRootsByMerging]
+
+******************************************************************************/
+static lsList
+NodeOrderRecursivelyByMerging(
+  Ntk_Node_t * node,
+  OrderingState_t * orderingState,
+  Ord_ListMergeMethod method,
+  int verbose)
+{
+  lsList orderList;
+  
+  
+  /*
+   * If node has already been visited (i.e. its orderList is non-NULL), then
+   * just return the orderList already computed.
+   */
+  orderList = NodeReadOrderList(node, orderingState);
+  if (orderList != (lsList) NULL) {
+    return orderList;
+  }
+
+  /*
+   * Node has not yet been visited.  Create the orderList for node.
+   */
+  if (Ntk_NodeTestIsCombInput(node) || Ntk_NodeTestIsConstant(node)) {
+    /*
+     * Combinational inputs and constants terminate the recursion. If node is
+     * one of these, then just create an empty list, to which we will add the
+     * node.
+     */
+    orderList = lsCreate();
+  }
+  else if (Ntk_NodeReadNumFanins(node) == 1) {
+    /*
+     * If there is just one fanin, then just make a copy of the the fanin's
+     * orderList. This case is distinguished from the general case for
+     * efficiency. 
+     */
+    lsList faninOrderList = NodeOrderRecursivelyByMerging(Ntk_NodeReadFaninNode(node, 0),
+                                                          orderingState,
+                                                          method, verbose);
+    orderList = lsCopy(faninOrderList, (lsGeneric (*) (lsGeneric)) NULL);
+  }
+  else {
+    int       i;
+    array_t  *sortedFanins;
+    st_table *nodeToHandle;
+
+    /*
+     * Sort the fanins of node in decreasing order of depth.  See
+     * OrdNetworkComputeNodeDepths.
+     */
+    sortedFanins = array_dup(Ntk_NodeReadFanins(node)); 
+    array_sort(sortedFanins, OrdNodesFromArrayCompareDepth);
+
+    /*
+     * Start with an empty list for the orderList of the node.  Also, start
+     * with an empty nodeToHandle table.  This table is only used locally, and
+     * will be deleted below.
+     */
+    orderList = lsCreate();
+    nodeToHandle  = st_init_table(st_ptrcmp, st_ptrhash);
+    
+    /*
+     * Recursively visit the fanins in order of decreasing depth. The
+     * nodeToHandle table keeps track of the nodes currently in orderList.
+     */
+    for (i = 0; i < array_n(sortedFanins); i++) {
+      Ntk_Node_t *fanin          = array_fetch(Ntk_Node_t *, sortedFanins, i);
+      lsList      faninOrderList = NodeOrderRecursivelyByMerging(fanin,
+                                                                 orderingState,
+                                                                 method, verbose);
+      /*
+       * Merge faninOrderList into the list of nodes already ordered.
+       */
+      Ord_ListMergeListUsingTable(orderList, faninOrderList, nodeToHandle, method);
+    }
+    array_free(sortedFanins);
+    st_free_table(nodeToHandle);
+  }
+
+  /*
+   * Regardless of the branch taken above, add node to the end of the
+   * orderList, and set the node's orderList.
+   */
+  (void) lsNewEnd(orderList, (lsGeneric) node, LS_NH);
+  NodeSetOrderList(node, orderList, orderingState);
+
+  if (verbose > 2) {
+    /* This can generate a lot of output. */
+    (void) fprintf(vis_stdout, "\nOrder list for node %s\n", Ntk_NodeReadName(node));
+    OrdNodeListWrite(vis_stdout, orderList);
+  }
+  
+  return orderList;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Orders the nodes of a network by the appending method.]
+
+  Description [Orders the nodes of a network by the appending method.  The
+  parameters are the same as in OrdNetworkOrderTFIOfRoots.<p>
+  
+  This function implements the algorithm of Malik, et al. "Logic Verification
+  using Binary Decision Diagrams in a Logic Synthesis Environment," ICCAD,
+  1988.  The ordering returned is a topological ordering.  The algorithm works
+  as follows.  For every root, a topological ordering on the tfi nodes not
+  yet ordered is generated by DFS. The ordered obtained starting from a root
+  is appended to the order already found.]
+
+  SideEffects [nodeToHandle table is modified]
+
+  SeeAlso     [OrdNetworkOrderTFIOfRoots NodeOrderRecursivelyByAppending]
+
+******************************************************************************/
+static lsList
+NetworkOrderTFIOfRootsByAppending(
+  Ntk_Network_t *network,
+  lsList  roots /* list of Ntk_Node_t  */,
+  st_table *nodeToHandle /* modified */,
+  int verbose)
+{
+  lsGen       gen;
+  Ntk_Node_t *root;
+  lsList      orderList = lsCreate(); /* return list */
+
+  
+  /*
+   * Compute and store the depth of each node in the network.  (The depth of a
+   * node is stored in the undef field of the node).
+   */
+  OrdNetworkComputeNodeDepths(network, roots);
+
+  if (verbose > 1) {
+    Ntk_Node_t *node;
+    (void) fprintf(vis_stdout, "\nDepths of network nodes:\n");
+    Ntk_NetworkForEachNode(network, gen, node) {
+      (void) fprintf(vis_stdout, "%s: depth = %ld\n", Ntk_NodeReadName(node),
+                     OrdNodeReadDepth(node));
+    }
+  }
+
+  /*
+   * For each root, recursively order all nodes in its transitive fanin.
+   */
+  lsForEachItem(roots, gen, root) {
+    NodeOrderRecursivelyByAppending(root, orderList, nodeToHandle, verbose);
+  }
+  
+  return orderList;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Orders the fanins of a node, and then orders the node itself.]
+
+  Description [Orders the fanins of a node, and then orders the node
+  itself. The fanins of a node are visited in order of decreasing depth.  The
+  node appears in the order just after its fanins, yielding a topological
+  order.  If node has already been visited, then simply return the order
+  previously found.]
+
+  Comment [The nodeToHandle table serves as the visited table for the DFS.]
+  
+  SideEffects [nodeToHandle table is modified]
+
+  SeeAlso     [NetworkOrderTFIOfRootsByAppending OrdNetworkComputeNodeDepths]
+
+******************************************************************************/
+static void
+NodeOrderRecursivelyByAppending(
+  Ntk_Node_t * node,
+  lsList orderList,
+  st_table *nodeToHandle,
+  int verbose)
+{
+  lsHandle handle;
+  
+  /*
+   * If node has already been visited (i.e. its in the nodeToHandle table), then
+   * just return.
+   */
+  if (st_is_member(nodeToHandle, (char *) node)) {
+    return;
+  }
+  
+  /*
+   * Node has not yet been visited.  Recurse on the inputs, and then add node
+   * to the end of the current ordering.
+   */
+  if (!(Ntk_NodeTestIsCombInput(node) || Ntk_NodeTestIsConstant(node))) {
+    /*
+     * Combinational inputs and constants terminate the recursion. If node is
+     * not one of these, then recurse on the inputs.
+     */
+    int       i;
+    array_t  *sortedFanins;
+
+    /*
+     * Sort the fanins of node in decreasing order of depth.  See
+     * OrdNetworkComputeNodeDepths.
+     */
+    sortedFanins = array_dup(Ntk_NodeReadFanins(node)); 
+    array_sort(sortedFanins, OrdNodesFromArrayCompareDepth);
+
+    /*
+     * Recursively visit the fanins in order of decreasing depth. The
+     * nodeToHandle table keeps track of the nodes currently in orderList.
+     */
+    for (i = 0; i < array_n(sortedFanins); i++) {
+      Ntk_Node_t *fanin = array_fetch(Ntk_Node_t *, sortedFanins, i);
+
+      NodeOrderRecursivelyByAppending(fanin, orderList, nodeToHandle, verbose);
+    }
+    array_free(sortedFanins);
+  }
+
+  /*
+   * Regardless of the branch taken above, add node to the end of the
+   * orderList and to the nodeToHandle table.
+   */
+  (void) lsNewEnd(orderList, (lsGeneric) node, &handle);
+  st_insert(nodeToHandle, (char *) node, (char *) handle);
+}
+
+  
+/**Function********************************************************************
+
+  Synopsis    [Orders the nodes of a network by the interleaving method.]
+
+  Description [Orders the nodes of a network by the interleaving method.  The
+  parameters are the same as in OrdNetworkOrderTFIOfRoots.<p>
+  
+  This function implements Algorithm 2 of Fujii, et al. "Inteleaving Based
+  Variable Ordering Methods for Ordered Binary Decision Diagrams," ICCAD,
+  1993.  The ordering returned is a topological ordering.  The algorithm is a
+  modified DFS that keeps track of an insertion point so that variables in the
+  tfi of the second and successive outputs be properly interleaved with the
+  variables already ordered.]
+
+  SideEffects [nodeToHandle table is modified]
+
+  SeeAlso     [OrdNetworkOrderTFIOfRoots NodeOrderRecursivelyByInterleaving]
+
+******************************************************************************/
+static lsList
+NetworkOrderTFIOfRootsByInterleaving(
+  Ntk_Network_t *network,
+  lsList roots /* list of Ntk_Node_t  */,
+  st_table *nodeToHandle /* modified */,
+  int verbose)
+{
+  lsGen       gen;
+  Ntk_Node_t *root;
+  lsList      orderList = lsCreate(); /* return list */
+  OrderingState_t *orderingState;
+
+  /*
+   * Compute and store the depth of each node in the network.  (The depth of a
+   * node is stored in the undef field of the node.)
+   */
+  OrdNetworkComputeNodeDepths(network, roots);
+
+  /*
+   * Initialize the state needed for recurring through the network.
+   */
+  orderingState = NetworkInitializeOrderingState(network);
+
+  if (verbose > 1) {
+    Ntk_Node_t *node;
+    (void) fprintf(vis_stdout, "\nDepths of network nodes:\n");
+    Ntk_NetworkForEachNode(network, gen, node) {
+      (void) fprintf(vis_stdout, "%s: depth = %ld\n", Ntk_NodeReadName(node),
+                     OrdNodeReadDepth(node));
+    }
+  }
+
+  /*
+   * For each root, recursively order all nodes in its transitive fanin.
+   */
+  lsForEachItem(roots, gen, root) {
+    orderingState->root = root;
+    orderingState->last = lsStart(orderList);
+    NodeOrderRecursivelyByInterleaving(root, orderList, nodeToHandle,
+				       orderingState, verbose);
+    lsFinish(orderingState->last);
+
+    if (verbose > 2) {
+      /* This can generate a lot of output. */
+      (void) fprintf(vis_stdout, "\nOrder list after merging node %s\n",
+                     Ntk_NodeReadName(root));
+      OrdNodeListWrite(vis_stdout, orderList);
+    }
+  }
+
+  /*
+   * Clean up and return the ordering list.
+   */
+  OrderingStateFree(orderingState);
+  return orderList;
+}
+
+  
+/**Function********************************************************************
+
+  Synopsis    [Orders the fanins of a node, and then orders the node itself.]
+
+  Description [Orders the fanins of a node, and then orders the node
+  itself. The fanins of a node are visited in order of decreasing depth.  The
+  node appears in the order just after its fanins, yielding a topological
+  order.  If node has already been visited, then simply update the info on
+  the output from which it was last reached, and change the insertion point.]
+
+  Comment [The nodeToHandle table serves as the visited table for the DFS.]
+  
+  SideEffects [nodeToHandle table is modified]
+
+  SeeAlso     [NetworkOrderTFIOfRootsByAppending OrdNetworkComputeNodeDepths]
+
+******************************************************************************/
+static void
+NodeOrderRecursivelyByInterleaving(
+  Ntk_Node_t * node,
+  lsList orderList,
+  st_table *nodeToHandle,
+  OrderingState_t *orderingState,
+  int verbose)
+{
+  lsHandle handle;
+  
+  /*
+   * If node has already been visited (i.e., it is in the nodeToHandle table),
+   * then update the info on the output from which it was last reached,
+   * and change the insertion point to this node.
+   */
+  if (st_is_member(nodeToHandle, (char *) node)) {
+    if (NodeReadFrom(node, orderingState) != orderingState->root) {
+      OrderingStateSetLast(node, nodeToHandle, orderingState);
+      NodeSetFrom(node, orderingState);
+    }
+    return;
+  }
+
+  /*
+   * Node has not yet been visited.  Recur on the inputs, and then add node
+   * to the end of the current ordering.
+   */
+  if (!(Ntk_NodeTestIsCombInput(node) || Ntk_NodeTestIsConstant(node))) {
+    /*
+     * Combinational inputs and constants terminate the recursion. If node is
+     * not one of these, then recur on the inputs.
+     */
+    int       i;
+    array_t  *sortedFanins;
+
+    /*
+     * Sort the fanins of node in decreasing order of depth.  See
+     * OrdNetworkComputeNodeDepths.
+     */
+    sortedFanins = array_dup(Ntk_NodeReadFanins(node)); 
+    array_sort(sortedFanins, OrdNodesFromArrayCompareDepth);
+
+    /*
+     * Recursively visit the fanins in order of decreasing depth. The
+     * nodeToHandle table keeps track of the nodes currently in orderList.
+     */
+    for (i = 0; i < array_n(sortedFanins); i++) {
+      Ntk_Node_t *fanin = array_fetch(Ntk_Node_t *, sortedFanins, i);
+
+      NodeOrderRecursivelyByInterleaving(fanin, orderList, nodeToHandle,
+					 orderingState,verbose);
+    }
+    array_free(sortedFanins);
+  }
+
+  /*
+   * Regardless of the branch taken above, add node to orderList at the
+   * insertion point and to the nodeToHandle table. Make node the new
+   * insertion point.
+   */
+  NodeSetFrom(node, orderingState);
+  (void) lsInBefore(orderingState->last, (lsGeneric) node, &handle);
+  st_insert(nodeToHandle, (char *) node, (char *) handle);
+  OrderingStateSetLast(node, nodeToHandle, orderingState);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes structure needed to maintain state of ordering
+  routine.]
+
+  Description [Allocates and initializes data structure needed to maintain the
+  state of the variable ordering routine.]
+
+  SideEffects []
+
+  Comment [The node depths are not stored in a hash table of orderingState,
+  because, for OrdNodesFromArrayCompareDepth, we need to be able to access the
+  depth of a node given *just* the node.]
+  
+  SeeAlso     [OrderingStateFree]
+
+******************************************************************************/
+static OrderingState_t *
+NetworkInitializeOrderingState(
+  Ntk_Network_t * network)
+{
+  OrderingState_t *orderingState = ALLOC(OrderingState_t, 1);
+
+  /* nodeToOrderList is used by the merging method. */
+  orderingState->nodeToOrderList = st_init_table(st_ptrcmp, st_ptrhash);
+
+  /* from, last, and root used by the interleaving method. */
+  orderingState->from = st_init_table(st_ptrcmp, st_ptrhash);
+  orderingState->last = NULL;
+  orderingState->root = NULL;
+
+  return orderingState;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Updates the insertion point in orderingState.]
+
+  Description [Updates the insertion point in orderingState. Assumes that
+  node is already in nodeToHandle.]
+
+  SideEffects []
+
+  SeeAlso     [NetworkInitializeOrderingState]
+
+******************************************************************************/
+static void
+OrderingStateSetLast(
+  Ntk_Node_t * node,
+  st_table * nodeToHandle,
+  OrderingState_t * orderingState)
+{
+  lsHandle handle;
+  lsGen gen;
+  lsGeneric data;
+
+  /* Dispose of the current generator. */
+  lsFinish(orderingState->last);
+
+  /* Get a handle for the current node. */
+  st_lookup(nodeToHandle, node, &handle);
+
+  /*
+   * Create a new generator positioned after node and register it
+   * in orderingState.
+   */
+  gen = lsGenHandle(handle,&data,LS_AFTER);
+  orderingState->last = gen;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees all memory associated with an ordering state.]
+
+  SideEffects []
+
+  SeeAlso     [NetworkInitializeOrderingState]
+
+******************************************************************************/
+static void
+OrderingStateFree(
+  OrderingState_t * orderingState)
+{
+  st_generator *stGen;
+  lsList orderList;
+  Ntk_Node_t *node;
+  
+  st_foreach_item(orderingState->nodeToOrderList, stGen, &node, &orderList) {
+    (void) lsDestroy(orderList, (void (*) (lsGeneric)) NULL);
+  }
+  
+  st_free_table(orderingState->nodeToOrderList);
+  st_free_table(orderingState->from);
+  
+  FREE(orderingState);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the order list of a node.]
+
+  Description [Gets the order list of a node.  This is a topological ordering
+  of all the nodes in the transitive fanin of the node.  Returns NULL if node
+  is not in the nodeToOrderList hash table of orderingState.]
+  
+  SideEffects []
+
+  SeeAlso     [NodeSetOrderList]
+
+******************************************************************************/
+static lsList
+NodeReadOrderList(
+  Ntk_Node_t * node,
+  OrderingState_t * orderingState)
+{
+  lsList orderList = (lsList) NULL;
+
+  st_lookup(orderingState->nodeToOrderList, node, &orderList);
+  
+  return orderList;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the orderList of a node.]
+
+  SideEffects []
+
+  SeeAlso     [NodeReadOrderList]
+
+******************************************************************************/
+static void
+NodeSetOrderList(
+  Ntk_Node_t * node,
+  lsList orderList,
+  OrderingState_t * orderingState)
+{
+  st_insert(orderingState->nodeToOrderList, (char *) node, (char *) orderList);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the from root of a node.]
+
+  Description [Gets the from node of a node.  This is the root from
+  which the node was last reached during DFS. Returns NULL if node is
+  not in the from hash table of orderingState.]
+  
+  SideEffects [none]
+
+  SeeAlso     [NodeSetFrom]
+
+******************************************************************************/
+static Ntk_Node_t *
+NodeReadFrom(
+  Ntk_Node_t * node,
+  OrderingState_t * orderingState)
+{
+  Ntk_Node_t * from = NULL;
+
+  st_lookup(orderingState->from, node, &from);
+  
+  return from;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the from root of a node to the current root.]
+
+  SideEffects [The from table of orderingState is modified.]
+
+  SeeAlso     [NodeReadFrom]
+
+******************************************************************************/
+static void
+NodeSetFrom(
+  Ntk_Node_t * node,
+  OrderingState_t * orderingState)
+{
+  st_insert(orderingState->from, (char *) node, (char *) orderingState->root);
+}
Index: vis_dev/vis-2.3/src/ord/ordPerm.c
===================================================================
--- vis_dev/vis-2.3/src/ord/ordPerm.c	(revision 14)
+++ vis_dev/vis-2.3/src/ord/ordPerm.c	(revision 14)
@@ -0,0 +1,1071 @@
+/**CFile***********************************************************************
+
+  FileName    [ordPerm.c]
+
+  PackageName [ord]
+
+  Synopsis    [Routines to find permutation on latches to minimize MDD size.]
+
+  Author      [Serdar Tasiran, Tom Shiple]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ordInt.h"
+
+static char rcsid[] UNUSED = "$Id: ordPerm.c,v 1.9 2005/04/16 06:15:25 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+typedef struct proc_pair {
+    long proc_no;
+    long var_no;
+} pair;
+
+typedef struct proc_struct {
+  int num_loc_vars;
+  array_t *o_list; /* of pair */
+  array_t *i_list; /* of pair */
+} proc_struct;	
+
+typedef struct Proc_Com_Graph {
+    int          num_vars;
+    int          num_proc;
+    int         *width_list;
+    proc_struct *proc_list;
+    int         *locations;      /* Array of length num_proc used as temporary storage by some
+                                    functions */
+    int         *variables;      /* Array of length num_vars used as temporary storage by some
+                                    functions */
+    
+} Proc_Com_Graph;
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+/**Variable********************************************************************
+
+  Synopsis    [required]
+
+  Description [
+  CHOICE = 0 -->Look-ahead of 2 
+           1 -->Look-ahead of 1
+           2 -->Touati's heuristic 
+           3 -->Enter permutation manually
+           4 -->Random ordering]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static int number_of_calls;
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static lsList NetworkComputeLatchOrder(Ntk_Network_t * network, int verbose);
+static int * LatchPermutationCompute(Proc_Com_Graph *PCG, int choice, int verbose);
+static double rev_fac(int num_rev_bits);
+static double cost_for_cut(Proc_Com_Graph * PCG, int * perm, int end_of_set1);
+static void append_best(int * opt_perm, int loc, Proc_Com_Graph * PCG);
+static double cost_2(int * opt_perm, int loc, Proc_Com_Graph * PCG);
+static long int cost_touati_2(int * opt_perm, int loc, Proc_Com_Graph * PCG);
+static void swap(int * opt_perm, int i, int j);
+static void append_best_2(int * opt_perm, int loc, Proc_Com_Graph * PCG);
+static void append_touati_2(int * opt_perm, int loc, Proc_Com_Graph * PCG);
+static void init_heur(Proc_Com_Graph * PCG, int * opt_perm);
+static void heur_2(Proc_Com_Graph * PCG, int * opt_perm);
+static void heur_touati_la2(Proc_Com_Graph * PCG, int * opt_perm);
+static int * opt_proc_order(Proc_Com_Graph * PCG);
+static int * opt_touati_order(Proc_Com_Graph * PCG);
+static double cost_total(Proc_Com_Graph * PCG, int * perm);
+static int * random_permutation(int seed, int n_elts);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Computes a total ordering on the combinational outputs of a
+  network.]
+
+  Description [Computes a total ordering on the combinational outputs of a
+  network. First, the algorithm orders the data inputs using the permutation
+  algorithm (Aziz et al, "BDD Variable Ordering for Interacting FSMs", DAC
+  1994, p. 283).  Then, it orders the remaining combinational outputs in order
+  of decreasing depth.  Finally, the second list is appended to the first.]
+
+  SideEffects []
+
+  SeeAlso     [OrdNetworkComputeNodeDepths]
+
+******************************************************************************/
+lsList
+OrdNetworkOrderRootsByPerm(
+  Ntk_Network_t *network,
+  int verbose)
+{
+  lsGen gen;
+  Ntk_Node_t *node;
+  lsList dataInputs;
+  st_table *processedTable = st_init_table(st_ptrcmp, st_ptrhash);
+  lsList otherCombOuts = lsCreate();
+
+  /*
+   * Create a list of all combinational outputs that are not data inputs to
+   * latches. A node can drive more than one latch data input, latch initial
+   * input, or primary output. Use a hash table to ensure that no node appears
+   * twice in the list.
+   */
+  Ntk_NetworkForEachCombOutput(network, gen, node) {
+    if (!Ntk_NodeTestIsLatchDataInput(node)) {
+      OrdNodeAddToList(otherCombOuts, processedTable, node);
+    }
+  }
+  st_free_table(processedTable);
+
+  /* Compute depth of all roots in otherCombOuts. */
+  OrdNetworkComputeNodeDepths(network, otherCombOuts);
+
+  /* Sort otherCombOuts based on depth. */
+  lsSort(otherCombOuts, OrdNodesFromListCompareDepth);
+
+  /* Compute order on dataInputs roots using the permutation method. */
+  dataInputs = NetworkComputeLatchOrder(network, verbose);
+
+  /* Add the otherCombOuts list to the end of the dataInputs list. */
+  Ord_ListAppendList(dataInputs, otherCombOuts);
+  (void) lsDestroy(otherCombOuts, (void (*) (lsGeneric)) NULL);
+  
+  return dataInputs;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Computes an ordering on the latches.]
+
+  Description [Computes an ordering on the latches, to be used for variable
+  ordering.  Returns a list of the corresponding latch data inputs (Ntk_Node_t
+  *) giving the ordering.  Implements the algorithm given in Aziz et al, "BDD
+  Variable Ordering for Interacting FSMs", DAC 1994, p. 283.]
+
+  SideEffects [Creates a file in /tmp.]
+
+  SeeAlso     [NetworkOrderNodes]
+
+******************************************************************************/
+static lsList
+NetworkComputeLatchOrder(
+  Ntk_Network_t * network,
+  int verbose)
+{
+  int           i, j;
+  lsGen         listGen;
+  st_generator *stGen;
+  Ntk_Node_t   *latch;
+  lsList        tfoLatchList;
+  int          *latchOrderArray;
+  long          count             = 0L;
+  st_table     *idToLatch         = st_init_table(st_numcmp, st_numhash);
+  int           numLatches        = Ntk_NetworkReadNumLatches(network);
+  st_table     *latchDependencies = Ntk_NetworkComputeLatchDependencies(network);
+  lsList        latchOrderList    = lsCreate();
+  int           latchOrderingMode = 1;  /* FIX: make an option */
+  double        convConstant      = log10(2.0);
+  Proc_Com_Graph *PCG;
+  pair         *cur_pair;
+  
+  /*
+   * Assign unique integer between 0 and numLatches-1 to each latch.  Store
+   * this correspondance in the idToLatch hash table.
+   * (NOTE: may be sensitive to ordering in memory.)
+   */
+  Ntk_NetworkForEachLatch(network, listGen, latch) {
+    Ntk_NodeSetUndef(latch, (void *) count);
+    st_insert(idToLatch, (char *) count, (char *) latch);
+    count++;
+  }
+
+  /* Create a Proc_Com_Graph and write the communications
+   * structure of the network into it
+   */
+  
+  PCG = ALLOC(Proc_Com_Graph, 1);
+  PCG->num_proc = numLatches; /*  SER (void) fprintf(pcgFile, "%d\n", numLatches);  */
+  PCG->num_vars = numLatches; /*  SER (void) fprintf(pcgFile, "%d\n", numLatches);  */
+
+  PCG->proc_list = ALLOC(proc_struct, PCG->num_proc);
+  PCG->width_list= ALLOC(int, PCG->num_vars);
+  PCG->locations = ALLOC(int, PCG->num_proc);  
+  PCG->variables = ALLOC(int, PCG->num_vars);
+
+  for(i=0;i< PCG->num_proc ; i++) {
+      PCG->proc_list[i].o_list= array_alloc(pair *, 0);
+      PCG->proc_list[i].i_list= array_alloc(pair *, 0);
+  };
+
+  /*
+   * For each latch/tfoLatchList pair, write information about the latch, and
+   * write the latches to which the latch fanouts. Finish the entry with "%%".
+   * Here is the general format for a process:
+   * process # list of local vars to process #
+   *     fanout-latch : local-var-fanning-to  width-of-local-var /
+   *       ....
+   *     fanout-latch : local-var-fanning-to  width-of-local-var / %%
+   *
+   * When this format is specialized to case where each process is a single
+   * latch, then the format looks like:
+   * latch # latch #
+   *     fanout-latch : latch  width-of-latch /
+   *       ....
+   *     fanout-latch : latch  width-of-latch / %%
+   */
+  st_foreach_item(latchDependencies, stGen, &latch, &tfoLatchList) {
+    Ntk_Node_t *tfoLatch;
+    int         varWidth;
+    long        var_no, fr_no, to_no;
+    
+
+    /*
+     * Write the latch id and the cardinality of the latch variable
+     * domain.
+     */
+    fr_no =  (long) Ntk_NodeReadUndef(latch);
+    PCG->proc_list[fr_no].num_loc_vars = 1;
+    
+    
+    /*
+     * For each transitive fanout latch, write the tfoLatch id, the latch
+     * id, and the width of the latch variable (assumes minimum
+     * encoding). Width is ceiling(log2(number of values in domain)).
+     */
+    varWidth = (int) ceil(log10
+             ((double)Var_VariableReadNumValues(Ntk_NodeReadVariable(latch)))
+                          / convConstant);
+    lsForEachItem(tfoLatchList, listGen, tfoLatch) {
+        to_no = (long) Ntk_NodeReadUndef(tfoLatch);
+        var_no = (long) Ntk_NodeReadUndef(latch);
+
+        cur_pair = ALLOC(pair,1);
+        cur_pair->proc_no = to_no;
+        cur_pair->var_no = var_no;
+        array_insert_last(pair *, PCG->proc_list[fr_no].o_list, cur_pair);
+
+        cur_pair = ALLOC(pair,1);
+        cur_pair->proc_no = fr_no;
+        cur_pair->var_no = var_no;         
+        array_insert_last(pair *, PCG->proc_list[to_no].i_list, cur_pair);
+        
+        PCG->width_list[var_no] = varWidth;
+    }
+  }
+
+  /*
+   * We don't need the latchDependencies table anymore.  Free the list stored
+   * at each value, and then free the table itself.
+   */
+  st_foreach_item(latchDependencies, stGen, &latch, &tfoLatchList) {
+    (void) lsDestroy(tfoLatchList, (void (*) (lsGeneric)) NULL);
+  }
+  st_free_table(latchDependencies);
+
+  /*
+   * Compute the order on the latches. This is returned as an array of
+   * integers, where the latch whose id is latchOrderArray[i] is ordered in
+   * the ith position of latchOrderList. Note that the returned list actually
+   * contains the latch data inputs, not the latches themselves.
+   */
+  latchOrderArray = LatchPermutationCompute(PCG, latchOrderingMode, verbose);
+  
+  for (i=0; i < PCG->num_proc; i++) {
+      for (j=0; j<array_n(PCG->proc_list[i].o_list); j++) {
+              cur_pair = array_fetch(pair *, PCG->proc_list[i].o_list, j);
+              FREE(cur_pair);
+      }
+
+      for (j=0; j<array_n(PCG->proc_list[i].i_list); j++) {
+              cur_pair = array_fetch(pair *, PCG->proc_list[i].i_list, j);
+              FREE(cur_pair);
+      }
+      
+      array_free(PCG->proc_list[i].o_list);
+      array_free(PCG->proc_list[i].i_list);
+  }
+
+  FREE(PCG->proc_list);
+  FREE(PCG->width_list);
+  FREE(PCG->variables);
+  FREE(PCG->locations);
+  FREE(PCG);
+  
+  for (i = 0; i < numLatches; i++) {
+    int status UNUSED = st_lookup(idToLatch,
+				  (char *) (long) (latchOrderArray[i]),
+				  &latch);
+    assert(status);
+    (void) lsNewEnd(latchOrderList, (lsGeneric) Ntk_LatchReadDataInput(latch), LS_NH);
+  }
+
+  /*
+   * We are done with idToLatch and latchOrderArray.
+   */
+  st_free_table(idToLatch);
+  FREE(latchOrderArray); 
+  
+  return (latchOrderList);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static int *
+LatchPermutationCompute(
+  Proc_Com_Graph *PCG,
+  int choice,
+  int verbose)
+{
+  int *opt_perm;
+
+  if (choice == 0) {      
+      opt_perm = opt_proc_order(PCG);
+  }
+  else if (choice == 1) {
+    opt_perm = ALLOC(int, PCG->num_proc);
+    init_heur(PCG, opt_perm);
+  }
+  else if (choice == 2) {
+    opt_perm = opt_touati_order(PCG);
+  }
+  else if (choice == 3) {
+    opt_perm = random_permutation(7,PCG->num_vars);
+  }
+  else {
+    fail("Unknown Option for Computing Latch Permutation");
+  }
+
+  if (verbose > 1) {
+    (void) fprintf(vis_stdout, "TOTAL COST= %e \n",cost_total(PCG,opt_perm));
+  }
+  
+  return opt_perm;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static double
+rev_fac(
+  int  num_rev_bits)
+{
+  double result;
+  
+  result  = pow( ((double) 2.0),((double) num_rev_bits) );
+ 
+  return result; 
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [Calculates the cost for a single cut that divides the
+  permutation into 2.]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static double
+cost_for_cut(
+  Proc_Com_Graph * PCG,
+  int * perm,
+  int  end_of_set1)
+{
+  int i, j;
+  double result; 
+  int forw  = 0,  rev = 0; 
+  pair *cur_pair;
+  
+  for (i=0; i<=end_of_set1; i++) {
+    PCG->locations[perm[i]]=1;
+  }
+        
+  for (i=end_of_set1+1; i<PCG->num_proc; i++) {
+    PCG->locations[perm[i]]=2;
+  }
+
+  for (i=0; i<PCG->num_vars; i++) {
+    PCG->variables[i]=0;
+  }
+        
+  /* Count the # of   forward crossing  bits   */
+/*  for (i=0; i<=end_of_set1; i++) {
+    st_foreach_item(PCG->proc_list[perm[i]].o_list, 
+                    gen,(char **)&bit_no,(char **)&to_proc) {  
+      if (PCG->locations[to_proc] ==2)  {
+        PCG->variables[bit_no]++ ;
+      }
+    }
+  }
+*/
+  for (i=0; i<=end_of_set1; i++) 
+      for (j=0; j<array_n(PCG->proc_list[perm[i]].o_list); j++) {
+          cur_pair = array_fetch(pair *, PCG->proc_list[perm[i]].o_list, j);
+          if (PCG->locations[cur_pair->proc_no] ==2)  {
+              PCG->variables[cur_pair->var_no]++ ;
+          }      
+      }
+  
+  
+  for (i=0; i<PCG->num_vars; i++) {
+    if (PCG->variables[i] > 0) {
+      ++forw ;
+    }
+  }
+
+  for (i=0; i<PCG->num_vars; i++) {
+    PCG->variables[i]=0;
+  }
+
+  /* Count the # of   reverse crossing  bits   */
+/*  for (i=end_of_set1+1; i<PCG->num_proc; i++) {
+    st_foreach_item(PCG->proc_list[perm[i]].o_list, 
+                    gen,(char **)&bit_no,(char **)&to_proc) {  
+      if (PCG->locations[to_proc] ==1)  {
+        PCG->variables[bit_no]++;
+      }
+    }
+  }
+  */
+  for (i=end_of_set1+1; i<PCG->num_proc; i++) 
+      for (j=0; j<array_n(PCG->proc_list[perm[i]].o_list); j++) {
+          cur_pair = array_fetch(pair *, PCG->proc_list[perm[i]].o_list, j);
+          if (PCG->locations[cur_pair->proc_no] ==1)  {
+              PCG->variables[cur_pair->var_no]++ ;
+          }      
+      }
+
+      
+  for (i=0; i<PCG->num_vars; i++) {
+    if (PCG->variables[i] > 0) {
+      ++rev;
+    }
+  }
+
+  {
+    double rev_cost = rev_fac(rev);
+    result =  ((double) forw) + rev_cost;
+    number_of_calls++;
+  }
+  return result; 
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [Adds the next best element in the greedy sense as described for
+  init_heur below.]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+append_best(
+  int * opt_perm,
+  int  loc,
+  Proc_Com_Graph * PCG)
+{
+  int i,  temp, bestswap, cur_fanout, best_fanout; 
+  double cur_cost, best_cost;
+  int j;
+  pair *cur_pair;
+    
+  best_cost = cost_for_cut(PCG, opt_perm, loc);
+  cur_cost = best_cost;
+  bestswap = loc;
+
+  best_fanout = 100000;
+  for(i=loc+1; i<PCG->num_proc;  i++) {
+      temp = opt_perm[loc];
+      opt_perm[loc] = opt_perm[i];
+      opt_perm[i] = temp;
+      
+      cur_cost = cost_for_cut(PCG, opt_perm, loc);
+      
+      if ( cur_cost == best_cost ) {
+          cur_fanout = 0;
+          
+          for ( j = 0 ; j <= loc ; j++ ) {
+              PCG->locations[opt_perm[j]] = 1;
+          }
+                        
+          for ( j = loc + 1 ; j < PCG->num_proc ; j++ ) {
+              PCG->locations[opt_perm[j]] = 2;
+          }
+      
+/*          st_foreach_item( PCG->proc_list[opt_perm[i]].o_list,
+                           stgen, ( char ** ) &bit_no, ( char ** )  &to_proc ) {
+              if ( PCG->locations[to_proc] == 2 ) {
+                  cur_fanout++;
+              }
+          }
+*/          
+          for (j=0; j<array_n(PCG->proc_list[opt_perm[i]].o_list); j++) {
+              cur_pair = array_fetch(pair *, PCG->proc_list[opt_perm[i]].o_list, j);
+              if (PCG->locations[cur_pair->proc_no] ==2)
+                  cur_fanout++;
+          }
+          
+          
+          
+          
+          if ( cur_fanout < best_fanout ) {
+              best_fanout = cur_fanout;
+              bestswap = i;
+          }
+      }
+      
+      if (cur_cost < best_cost) {
+          best_cost = cur_cost;
+          bestswap = i;
+      }
+
+      temp = opt_perm[loc];
+      opt_perm[loc] = opt_perm[i];
+      opt_perm[i] = temp;
+  }
+
+  temp = opt_perm[loc];
+  opt_perm[loc] = opt_perm[bestswap];
+  opt_perm[bestswap] = temp;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static double
+cost_2(
+  int * opt_perm,
+  int  loc,
+  Proc_Com_Graph * PCG)
+{
+    
+  double cost_0 = cost_for_cut(PCG, opt_perm, loc);
+  double cost_1 = cost_for_cut(PCG, opt_perm, loc+1);
+  double result = cost_0 + cost_1;
+  
+  return result;
+    
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static long int
+cost_touati_2(
+  int * opt_perm,
+  int  loc,
+  Proc_Com_Graph * PCG)
+{
+  int i, j;
+  long int result;
+  pair *cur_pair;
+
+
+  for (i=0; i<loc; i++) {
+      PCG->locations[opt_perm[i]]=1;
+  }
+
+  for (i=loc+1; i<PCG->num_proc; i++) {
+      PCG->locations[opt_perm[i]]=0;
+  }
+
+  for (i=0; i<PCG->num_vars; i++)
+      PCG->variables[i]=0;
+  
+/*  st_foreach_item(PCG->proc_list[opt_perm[loc]].i_list, 
+                  gen,(char **)&bit_no,(char **)&from_proc) {  
+    if (PCG->locations[from_proc] == 0)  {
+      PCG->variables[bit_no]++ ;
+    }
+  }
+*/
+  
+  for (j=0; j<array_n(PCG->proc_list[opt_perm[loc]].i_list); j++) {
+      cur_pair = array_fetch(pair *, PCG->proc_list[opt_perm[loc]].i_list, j);
+      if (PCG->locations[cur_pair->proc_no] ==0)  {
+          PCG->variables[cur_pair->var_no]++ ;
+      }      
+  }
+
+  result = 0;
+  for (i=0; i<PCG->num_vars; i++)  {
+    if (PCG->variables[i] != 0) {
+      result++;
+    }
+  }
+                                                              
+  for (i=0; i<PCG->num_vars; i++)
+      PCG->variables[i]=0;
+
+/*  st_foreach_item(PCG->proc_list[opt_perm[loc+1]].i_list, 
+                  gen,(char **)&bit_no,(char **)&from_proc) {  
+    if (PCG->locations[from_proc] == 0)  {
+      PCG->variables[bit_no]++ ;
+    }
+  }
+  */
+
+  for (j=0; j<array_n(PCG->proc_list[opt_perm[loc+1]].i_list); j++) {
+      cur_pair = array_fetch(pair *, PCG->proc_list[opt_perm[loc+1]].i_list, j);
+      if (PCG->locations[cur_pair->proc_no] ==0)  {
+          PCG->variables[cur_pair->var_no]++ ;
+      }      
+  }
+  
+  for (i=0; i<PCG->num_vars; i++)  {
+    if (PCG->variables[i] != 0) {
+      result++;
+    }
+  }
+
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+swap(
+  int * opt_perm,
+  int  i,
+  int  j)
+{
+  int temp;
+
+  temp = opt_perm[i];
+  opt_perm[i] = opt_perm[j];
+  opt_perm[j] = temp;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+append_best_2(
+  int * opt_perm,
+  int  loc,
+  Proc_Com_Graph * PCG)
+{
+  double best_cost, cur_cost;
+  int i,j;
+  int best[2];
+
+
+  best_cost = cost_2(opt_perm, loc, PCG); 
+  cur_cost =  best_cost;
+  best[0] = loc;
+  best[1] = loc+1;
+
+  for(i=loc; i<PCG->num_proc;  i++) {
+    swap(opt_perm,loc,i);
+    for(j=loc+1; j<PCG->num_proc;  j++) {
+      swap(opt_perm,loc+1,j);
+      cur_cost = cost_2(opt_perm, loc, PCG);
+      if (cur_cost < best_cost) {
+        best_cost = cur_cost;
+        best[0] = i;
+        best[1] = j;
+      };
+      swap(opt_perm,loc+1,j);
+    }
+    swap(opt_perm,loc,i);
+  };
+
+  swap(opt_perm,loc,best[0]);
+  swap(opt_perm,loc+1,best[1]);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+append_touati_2(
+  int * opt_perm,
+  int  loc,
+  Proc_Com_Graph * PCG)
+{
+  long int best_cost, cur_cost;
+  int i,j;
+  int best[2];
+
+  /*
+   * FIX: this is the same function as append_best_2, except that
+   * cost_touati_2 is used rather than cost_2; just pass the cost function in
+   * as a parameter.
+   */
+
+  best_cost = cost_touati_2(opt_perm, loc, PCG); 
+  cur_cost =  best_cost;
+  best[0] = loc;
+  best[1] = loc+1;
+
+  for(i=loc; i<PCG->num_proc;  i++) {
+    swap(opt_perm,loc,i);
+    for(j=loc+1; j<PCG->num_proc;  j++) {
+      swap(opt_perm,loc+1,j);
+      cur_cost = cost_touati_2(opt_perm, loc, PCG);
+      if (cur_cost < best_cost) {
+        best_cost = cur_cost;
+        best[0] = i;
+        best[1] = j;
+      };
+      swap(opt_perm,loc+1,j);
+    }
+    swap(opt_perm,loc,i);
+  };
+
+  swap(opt_perm,loc,best[0]);
+  swap(opt_perm,loc+1,best[1]);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [Returns an initial guess for the optimum permutation by forming
+  it one element at a time at each step choosing the element that minimizes
+  cost_for_cut for the set obtained by adding it to the first part of the
+  permutation, writes the permutation to opt_perm.]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+init_heur(
+  Proc_Com_Graph * PCG,
+  int * opt_perm)
+{
+  int i;  
+      
+  for(i=0; i<PCG->num_proc; i++) {
+    opt_perm[i]  = i;
+  }
+
+  
+  
+  /*printf("\nEntering ordering code:\n");*/
+  for(i=0; i<PCG->num_proc; i++)  {
+    /*printf("Iteration\t:\t%d(%d)\n", i, PCG->num_proc );*/
+    append_best(opt_perm,  i,  PCG); 
+  }
+  /*printf("\n\t--- Total number of calls = %d ---\n",  number_of_calls );*/
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+heur_2(
+  Proc_Com_Graph * PCG,
+  int * opt_perm)
+{
+
+  int i;
+
+  for(i=0; i<PCG->num_proc; i++) {
+    opt_perm[i]  = i;
+  }
+
+  for(i=0; i<(2*floor(((double)PCG->num_proc) / 2.0 )); i = i+2) { 
+    /*printf("Iteration\t:\t%d(%d)\n", i, PCG->num_proc );*/
+    append_best_2(opt_perm,i,PCG);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+heur_touati_la2(
+  Proc_Com_Graph * PCG,
+  int * opt_perm)
+{
+  int i;
+
+  for(i=0; i<PCG->num_proc; i++) {
+    opt_perm[i]  = i;
+  }
+
+  for(i=0; i<(2*floor(((double)PCG->num_proc) / 2.0 )); i = i+2) {
+				/*printf("Iteration\t:\t%d(%d)\n", i, PCG->num_proc );*/
+    append_touati_2(opt_perm,i,PCG);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [Returns the ordering of processes that minimizes the bound.]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static int *
+opt_proc_order(
+  Proc_Com_Graph * PCG)
+{
+  int *cur_opt;
+
+	
+  cur_opt = ALLOC(int, PCG->num_proc);
+  heur_2(PCG, cur_opt);
+    
+  /*for (i=0;i<PCG->num_proc; i++) printf(" %d ",cur_opt[i]+1);*/
+
+  return  cur_opt;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [Returns the ordering of processes that minimizes the bound.]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static int *
+opt_touati_order(
+  Proc_Com_Graph * PCG)
+{
+  int *cur_opt;
+
+
+  /*
+   * FIX: same function as opt_proc_order except for heuristic call.
+   */
+  
+  cur_opt = ALLOC(int, PCG->num_proc);
+  heur_touati_la2(PCG, cur_opt);
+    
+  /*for (i=0;i<PCG->num_proc; i++) printf(" %d ",cur_opt[i]+1);*/
+
+  return  cur_opt;
+}
+ 
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static double
+cost_total(
+  Proc_Com_Graph * PCG,
+  int * perm)
+{
+  int i;
+
+  double cost=0;
+
+  for(i=0; i<PCG->num_proc-1; i++) {
+    cost += cost_for_cut(PCG, perm, i);
+  }
+        
+  return  cost;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static int *
+random_permutation(
+  int  seed,
+  int  n_elts)
+{
+  int i, j;
+  int *permutation;
+  int *remaining;
+  int next_entry;
+  int next_value;
+  int n_entries;
+
+  if (n_elts <= 0) {
+    return NIL(int);
+  }
+
+  n_entries = n_elts;
+  permutation = ALLOC(int, n_entries);
+  remaining = ALLOC(int, n_entries);
+  for (i = 0; i < n_entries; i++) {
+    remaining[i] = i;
+  }
+
+  util_srandom((long) seed);
+
+  next_entry = 0;
+  for (; n_entries > 0; n_entries--) {
+    next_value = util_random() % n_entries;
+    permutation[next_entry++] = remaining[next_value];
+    for (j = next_value; j < n_entries - 1; j++) {
+      remaining[j] = remaining[j + 1];
+    }
+  }
+  FREE(remaining);
+  return permutation;
+}
Index: vis_dev/vis-2.3/src/ord/ordRoots.c
===================================================================
--- vis_dev/vis-2.3/src/ord/ordRoots.c	(revision 14)
+++ vis_dev/vis-2.3/src/ord/ordRoots.c	(revision 14)
@@ -0,0 +1,244 @@
+/**CFile***********************************************************************
+
+  FileName    [ordRoots.c]
+
+  PackageName [ord]
+
+  Synopsis    [Routines to order the roots of the network.]
+
+  Description [Routines to order the roots of the network.  The nodes of the
+  network are explored in DFS order from the roots, in the root order
+  computed. To add a new method, create a new value for the Ord_RootMethod
+  enumerated type, and add a call to the new procedure from
+  Ord_NetworkOrderRoots.]
+
+  Author      [Tom Shiple]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "ordInt.h"
+
+static char rcsid[] UNUSED = "$Id: ordRoots.c,v 1.7 2002/08/27 08:43:16 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Orders the roots of a network.]
+
+  Description [Orders the combinational outputs of a network.  The data inputs
+  of latches always precede the other combinational outputs.  This gives
+  priority to finding the best ordering for the variables in the next state
+  functions. <p>
+
+  The different root ordering methods are documented in the static_order
+  command. If rootMethod is Ord_RootsByDefault_c, then one of the ordering
+  methods is called by default, depending on the number of latches in the
+  network.<p>
+
+  An arbitrary subset of roots can be specified in partialOrder. No check is
+  made to determine if the nodes in partialOrder are contained within the set
+  specified by orderType.  If partialOrder is non-NULL, then a total order on
+  the roots is computed according to rootMethod (as described above), and then
+  the computed order is merged into the partialOrder.]
+
+  SideEffects []
+
+  SeeAlso     [OrdNetworkOrderRootsByDepth OrdNetworkOrderRootsByPerm]
+
+******************************************************************************/
+lsList
+Ord_NetworkOrderRoots(
+  Ntk_Network_t *network,
+  Ord_RootMethod rootMethod,
+  lsList partialOrder,
+  boolean verbose)
+{
+  lsList rootOrderList;
+  
+  switch (rootMethod) {
+    case Ord_RootsByDepth_c:
+      rootOrderList = OrdNetworkOrderRootsByDepth(network, verbose); 
+      break;
+    case Ord_RootsByPerm_c:
+      rootOrderList = OrdNetworkOrderRootsByPerm(network, verbose);
+      break;
+    case Ord_RootsByDefault_c:
+      /*
+       * RootByPerm method is cubic in the number of latches, so use it by
+       * default only if the number of latches is not too large (30 is somewhat
+       * arbitrary).
+       */
+      if (Ntk_NetworkReadNumLatches(network) < 30) {
+        rootOrderList = OrdNetworkOrderRootsByPerm(network, verbose);
+      }
+      else {
+        rootOrderList = OrdNetworkOrderRootsByDepth(network, verbose);
+      }
+      break;
+    default:
+      fail("unrecognized root order method");
+  }
+
+  /*
+   * If a partial order is supplied, merge (left, arbitrarily) the computed
+   * order into the supplied order, to get a total ordering on all of the
+   * roots.
+   */
+  if (partialOrder != (lsList) NULL) {
+    lsList partialOrderCopy = lsCopy(partialOrder,
+				     (lsGeneric (*) (lsGeneric)) NULL);
+
+    Ord_ListMergeList(partialOrderCopy, rootOrderList, Ord_ListMergeLeft_c);
+    (void) lsDestroy(rootOrderList, (void (*) (lsGeneric)) NULL);
+    return partialOrderCopy;
+  }
+  else {
+    return rootOrderList;
+  }
+}
+
+    
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Computes a total ordering on the combinational outputs of a
+  network.]
+
+  Description [Computes a total ordering on the combinational outputs of a
+  network.  First, the depth of each combinational output is calculated.  The
+  depth of a node is the longest path (going backwards) to a combinational
+  input or constant. Then, the algorithm creates two lists: 1) data inputs to
+  latches, and 2) all remaining combinational outputs. Next, each list is
+  sorted in order of decreasing depth.  Finally, the second list is appended
+  to the first.]
+
+  SideEffects []
+
+  SeeAlso     [Ord_NetworkOrderRoots OrdNetworkComputeNodeDepths]
+
+******************************************************************************/
+lsList
+OrdNetworkOrderRootsByDepth(
+  Ntk_Network_t *network,
+  boolean verbose)
+{
+  lsGen       gen;
+  Ntk_Node_t *node;
+  st_table   *processedTable = st_init_table(st_ptrcmp, st_ptrhash);
+  lsList dataInputs = lsCreate();
+  lsList otherCombOuts = lsCreate();
+  lsList combOutputs = Ntk_NetworkReadCombOutputs(network);
+
+  /*
+   * A node can drive more than one latch data input, latch initial input,
+   * or primary output. Use a hash table to ensure that no node appears twice
+   * across the two lists.
+   */
+  Ntk_NetworkForEachCombOutput(network, gen, node) {
+    if (Ntk_NodeTestIsLatchDataInput(node)) {
+      OrdNodeAddToList(dataInputs, processedTable, node);
+    }
+    else {
+      OrdNodeAddToList(otherCombOuts, processedTable, node);
+    }
+  }
+  st_free_table(processedTable);
+
+  /* Compute depth of all combinational outputs. */
+  OrdNetworkComputeNodeDepths(network, combOutputs);
+
+  /* Sort each list independently. */
+  lsSort(dataInputs, OrdNodesFromListCompareDepth);
+  lsSort(otherCombOuts, OrdNodesFromListCompareDepth);
+
+  Ord_ListAppendList(dataInputs, otherCombOuts);
+  (void) lsDestroy(otherCombOuts, (void (*) (lsGeneric)) NULL);
+  
+  return dataInputs;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Inserts a node into a list, unless it already appears in the list.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+OrdNodeAddToList(
+  lsList nodeList,
+  st_table *nodeTable,
+  Ntk_Node_t *node)
+{
+  if (!st_is_member(nodeTable, (char *) node)) {
+    st_insert(nodeTable, (char *) node, NIL(char));
+    (void) lsNewEnd(nodeList, (lsGeneric) node, LS_NH);
+  }
+}
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
Index: vis_dev/vis-2.3/src/part/part.h
===================================================================
--- vis_dev/vis-2.3/src/part/part.h	(revision 14)
+++ vis_dev/vis-2.3/src/part/part.h	(revision 14)
@@ -0,0 +1,227 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [part.h]
+
+  PackageName [part]
+
+  Synopsis    [Partition of a system and creation of MDDs.]
+
+  Description [Once the description of a system has been read, and the ordering
+  of the variables has been assigned, the partition package creates an
+  abstracted view of the system in which only information in terms of MDDs is
+  stored. The MDDs belong to the MDD manager of the system. Different options
+  may be considered when creating this abstracted view. If the system is
+  described as a network there are several options to create this partition. As
+  a first choice, the system may be considered as a set of functions
+  representing the combinational outputs as functions of the combinational
+  inputs. In general, the latch functions may be specified as functions of any
+  intermediate variables. These intermediate variables are themselves functions
+  of other variables, and ultimately the dependency on the combinational inputs
+  is achieved. The structure to represent these arbitrary dependencies is a
+  DAG. The combinational inputs of the network will be represented as
+  vertices. Every other function (either representing a latch or any other
+  intermediate node) is represented as a vertex with in-coming edges from the
+  vertices representing the function's domain. Hence, the vertices representing
+  the combinational inputs will not have any in-coming edges, and conversely,
+  the vertices representing the combinational outputs will not have any fanout
+  edges.<p>
+
+  The partition may have two types of vertices, called single and
+  clustered. Single vertices are the ones that represent, for example, nodes in
+  a network. Clustered vertices are used solely for the purpose of grouping
+  single vertices into disjoint sets. No clustered vertex can be member of a
+  clustered vertex, and every single vertex may be a member of a unique clustered
+  vertex. The edges of the graph are connecting only single vertices. Functions
+  are provided to access the list of vertices represented by a clustered vertex
+  as well as for testing the type of a vertex.<p>
+
+  A partition is the central input to the image computation
+  package.  However, it is important to note that there is no network-specific
+  information stored in the partition data structure itself.  Hence, it is
+  possible that another application (i.e. besides the network application)
+  could create a partition, and use that partition as input to the image
+  computation package.]
+
+  Author      [Abelardo Pardo]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+  Revision    [$Id: part.h,v 1.33 2009/04/11 01:47:18 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _PART
+#define _PART
+
+#include "ntk.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+#define PART_NETWORK_APPL_KEY "Part_NetworkApplKey"
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**Enum************************************************************************
+
+  Synopsis    [Different methods of partitioning a system.]
+
+  SeeAlso     [PartPartitionInputsOutputs PartPartitionTotal
+  PartPartitionPartial]
+
+******************************************************************************/
+typedef enum {
+  Part_Default_c,  /* Default partition. (Right now Outputs as function of
+		    * inputs) */
+  Part_InOut_c,    /* Outputs as function of inputs */
+  Part_Total_c,    /* Replicates the system's structure */
+  Part_Partial_c,   /* Preserves certain user-provided nodes */
+  Part_Frontier_c,
+  Part_Boundary_c,  /* partition nodes are subckt IOs */
+  Part_Fine_c   /* partition nodes are subckt IOs */
+} Part_PartitionMethod;
+
+/**Enum************************************************************************
+
+  Synopsis    [Type of vertex in the partition.]
+
+  Description [There are two types of vertices in the partition: single and
+  clustered. A single vertex represents itself and it may have a multi-valued
+  function and a MddId attached to it. A clustered vertex represents a set of
+  single vertices. The only information stored in this type of vertex is the
+  list of single vertices being represented by the cluster. Only one level of
+  hierarchy is allowed, that is, clustered vertices may only represent single
+  vertices. Every single vertex may only be represented by a unique clustered
+  vertex. In other words, a vertex representing a cluster of vertices cannot be
+  a member of another cluster.]
+
+  SeeAlso     [PartVertexInfo]
+
+******************************************************************************/
+typedef enum {
+  Part_VertexCluster_c,  /* Vertex represents a cluster of vertices */
+  Part_VertexSingle_c    /* Vertex represents itself */
+} Part_VertexType;
+
+/**Enum************************************************************************
+
+  Synopsis    [ Methods of Breaking for State Space Decomposition ]
+
+  SeeAlso     []
+
+******************************************************************************/
+typedef enum{
+  Part_BSRR_s,    /* static round robin seed choice */
+  Part_BFix_v     /* fixed order vertex choice */
+} Part_BMethod;
+
+/**Enum************************************************************************
+
+  Synopsis    [ Method of Correlation calculation. ]
+
+  Description [ Correlation is calculated by ratio of minterm count of XOR.
+  If BDD function is not available or try to avoid using MDD operation,
+  correaltion can be calculated by second method. Then, support set is
+  generated from network and correlation is simply the ration of common support
+  to union of two support sets.]
+
+  SeeAlso     []
+
+******************************************************************************/
+typedef enum{
+  Part_CorrelationWithBDD,    /* correlation is based on BDD correlation */
+  Part_CorrelationWithSupport,   /* correlation is based on support */
+  Part_CorrelationDefault
+} Part_CMethod;
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef struct PartSubsystemInfo Part_SubsystemInfo_t;
+typedef struct PartSubsystem Part_Subsystem_t;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void Part_Init(void);
+EXTERN void Part_End(void);
+EXTERN array_t * Part_PartitionBuildFunctions(graph_t *partition, array_t *roots, array_t *leaves, mdd_t *careSet);
+EXTERN array_t * Part_PartitionCollapse(graph_t *partition, array_t *roots, st_table *leaves, mdd_t *careSet);
+EXTERN array_t * Part_PartGroupVeriticesBasedOnHierarchy(Ntk_Network_t *network, array_t *latchDataInputNames);
+EXTERN array_t * Part_PartCreateSubsystems(Part_SubsystemInfo_t *subInfo, array_t *arrayOfLatchNames, array_t *arrayOfGroupIndex);
+EXTERN array_t * Part_PartCreateSubsystemsWithCTL(Part_SubsystemInfo_t *subInfo, array_t *ctlArray, array_t *fairArray,boolean dynamicIncrease,boolean dynamicAndDependency);
+EXTERN array_t * Part_PartCreateSubsystemsWithCtlAndLtl(Part_SubsystemInfo_t *subInfo, array_t *ctlArray, array_t *ltlArray, array_t *fairArray,boolean dynamicIncrease,boolean dynamicAndDependency,boolean strictBound);
+EXTERN st_table * Part_PartitionSubsystemReadVertexTable(Part_Subsystem_t *partitionedSubsystem);
+EXTERN array_t * Part_PartitionSubsystemReadFanIn(Part_Subsystem_t *partitionedSubsystem);
+EXTERN array_t * Part_PartitionSubsystemReadFanOut(Part_Subsystem_t *partitionedSubsystem);
+EXTERN Part_SubsystemInfo_t * Part_PartitionSubsystemInfoInit(Ntk_Network_t *network);
+EXTERN void Part_PartitionSubsystemInfoFree(Part_SubsystemInfo_t *partSubInfo);
+EXTERN void Part_PartitionSubsystemFree(Part_Subsystem_t *partSubsystem);
+EXTERN void Part_PartitionSubsystemInfoSetNetwork(Part_SubsystemInfo_t *subInfo, Ntk_Network_t *network);
+EXTERN void Part_PartitionSubsystemInfoSetBreakingMethod(Part_SubsystemInfo_t *subInfo, Part_BMethod bMethod);
+EXTERN void Part_PartitionSubsystemInfoSetBound(Part_SubsystemInfo_t *subInfo, int bound);
+EXTERN void Part_PartitionSubsystemInfoSetThreshold(Part_SubsystemInfo_t *subInfo, float threshold);
+EXTERN void Part_PartitionSubsystemInfoSetVerbosity(Part_SubsystemInfo_t *subInfo, int verbosity);
+EXTERN void Part_PartitionSubsystemInfoSetCorrelationMethod(Part_SubsystemInfo_t *subInfo, Part_CMethod corMethod);
+EXTERN void Part_PartitionSubsystemInfoSetAffinityFactor( Part_SubsystemInfo_t *subInfo, float affinity);
+EXTERN Part_Subsystem_t * Part_PartCreateSingleSubSystem( array_t *arrayOfNodes, Ntk_Network_t *network);
+EXTERN graph_t * Part_CreatePartitionFromMvfs(mdd_manager *manager, st_table *nameToMvf, st_table *nameToId,  st_table *leafTable,  char *partName);
+EXTERN graph_t * Part_NetworkCreatePartitionFromMvfs(Ntk_Network_t *network, st_table *nameToMvf);
+EXTERN void Part_PartitionFree(graph_t *partition);
+EXTERN void Part_PartitionFreeCallback(void *data);
+EXTERN vertex_t * Part_PartitionFindVertexByName(graph_t *partition, char *name);
+EXTERN vertex_t * Part_PartitionFindVertexByMddId(graph_t *partition, int mddId);
+EXTERN char * Part_PartitionReadName(graph_t *partition);
+EXTERN Part_PartitionMethod Part_PartitionReadMethod(graph_t *partition);
+EXTERN char * Part_PartitionObtainMethodAsString(graph_t *partition);
+EXTERN mdd_manager * Part_PartitionReadMddManager(graph_t *partition);
+EXTERN Part_VertexType Part_VertexReadType(vertex_t *vertexPtr);
+EXTERN char * Part_VertexReadName(vertex_t *vertexPtr);
+EXTERN array_t * Part_VertexReadClusterMembers(vertex_t *vertexPtr);
+EXTERN Mvf_Function_t * Part_VertexReadFunction(vertex_t *vertexPtr);
+EXTERN void Part_VertexSetFunction(vertex_t *vertexPtr, Mvf_Function_t *mvf);
+EXTERN int Part_VertexReadMddId(vertex_t *vertexPtr);
+EXTERN boolean Part_VertexTestIsClustered(vertex_t *vertexPtr);
+EXTERN graph_t * Part_NetworkCreatePartition(Ntk_Network_t *network, Hrc_Node_t *hnode, char *name, lsList rootList, lsList leaveList, mdd_t *careSet, Part_PartitionMethod method, lsList nodes, boolean inTermsOfLeaves, int verbose, int sanityCheck);
+EXTERN graph_t * Part_PartitionDuplicate(graph_t *partition);
+EXTERN graph_t * Part_NetworkReadPartition(Ntk_Network_t *network);
+EXTERN vertex_t * Part_PartitionCreateClusterVertex(graph_t *partition, char *name, array_t *arrayOfVertices);
+EXTERN void Part_UpdatePartitionFrontier(Ntk_Network_t *network, graph_t *partition, lsList rootList, lsList leaveList, mdd_t *careSet);
+EXTERN void Part_VertexInfoFreeCluster(vertex_t *vertexPtr);
+EXTERN boolean Part_PartitionTestCompletelySp(graph_t *partition, array_t *roots, st_table *leaves);
+EXTERN boolean Part_PartitionTestDeterministic(graph_t *partition, array_t *roots, st_table *leaves);
+EXTERN graph_t * Part_PartCreatePartitionWithCTL(Hrc_Manager_t ** hmgr, Part_PartitionMethod method, int verbose, int sanityCheck, boolean inTermsOfLeaves, array_t *ctlArray, array_t *fairArray);
+EXTERN graph_t * Part_PartCreatePartitionWithCtlAndLtl(Hrc_Manager_t ** hmgr, Part_PartitionMethod method, int verbose, int sanityCheck, boolean inTermsOfLeaves, array_t *ctlArray, array_t *ltlArray, array_t *fairArray);
+EXTERN int Part_PartitionChangeRoots(Ntk_Network_t *network, graph_t *partition, lsList rootList, int verbosity);
+EXTERN void Part_PartitionPrintStats(FILE *fp, graph_t *partition, boolean printNodeNames);
+EXTERN int Part_PartitionGetLatchInputListFromCTL(Ntk_Network_t *network, array_t *ctlArray, array_t *fairArray, lsList latchInputList);
+EXTERN int Part_PartitionGetLatchInputListFromCtlAndLtl(Ntk_Network_t *network, array_t *ctlArray, array_t *ltlArray, array_t *fairArray, lsList latchInputList, boolean stopAtLatch);
+EXTERN void Part_PartitionReadOrCreateBnvs(Ntk_Network_t *network, st_table *coiLatchTable, st_table *coiBnvTable);
+EXTERN void PartPartitionFineGrain( Ntk_Network_t *network, graph_t       *partition, mdd_t *careSet);
+EXTERN int Part_CheckLeafNodeCondition(Ntk_Node_t *node, st_table *leafTable, int fanoutFreeLimit, int numVariableLimit);
+EXTERN int Img_CutCalcTransitiveFanin(st_table *table, st_table *ownTable, Ntk_Node_t *node, Ntk_Node_t *fanin, int limit);
+EXTERN Ntk_Node_t * Part_GetFaninFreeLogic(Ntk_Node_t *node);
+EXTERN Ntk_Node_t * Part_GetFanoutFreeLogic(Ntk_Node_t *node);
+EXTERN void Part_PartitionWithExistingBnvs(Ntk_Network_t *network, graph_t *partition, st_table *coiBnvTable, st_table *absLatchTable, st_table *absBnvTable);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _PART */
Index: vis_dev/vis-2.3/src/part/part.make
===================================================================
--- vis_dev/vis-2.3/src/part/part.make	(revision 14)
+++ vis_dev/vis-2.3/src/part/part.make	(revision 14)
@@ -0,0 +1,4 @@
+CSRC += partCmd.c partCollapse.c partInOut.c partPart.c partPartial.c partTotal.c partFrontier.c partBoundary.c partGroup.c partFine.c
+HEADERS += part.h partInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/part/partBoundary.c
===================================================================
--- vis_dev/vis-2.3/src/part/partBoundary.c	(revision 14)
+++ vis_dev/vis-2.3/src/part/partBoundary.c	(revision 14)
@@ -0,0 +1,179 @@
+/**CFile***********************************************************************
+
+  FileName    [partBoundary.c]
+
+  PackageName [part]
+
+  Synopsis [Implements the partition of the network with respect to the 
+  nodes that comprise the submodules boundaries.]
+
+  Description [The network is composed of an arbitrary set of nodes, each of
+  them implementing some function. This partitioning method will produce a
+  graph representing the network in which the nodes that constitute submodule 
+  boundaries will be preserved in the graph structure.]
+
+  SeeAlso     [partInOut.c partTotal.c]
+
+  Author      [Sunil P Khatri]
+
+  Copyright   [This file was created at the University of California at
+  Berkeley.  The University of California at Berkeley makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "partInt.h"
+
+static char rcsid[] UNUSED = "$Id: partBoundary.c,v 1.5 2002/09/10 05:06:25 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Finds names of all partition nodes the boundary partitioning method.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+partCreateBoundaryNames(
+  Hrc_Node_t    *hnode,
+  st_table      *tableOfFormalNames)
+{
+  st_generator *stGen;
+  char *childName, *nodeName, *inputVarName, *outputVarName, *formalName;
+  Hrc_Node_t *childNode;
+  int i;
+  Var_Variable_t *inputVar, *outputVar;
+
+  
+  Hrc_NodeForEachChild(hnode, stGen, childName, childNode){
+    /* add childrens inputs' formal names to tableOfFormalNames */
+    Hrc_NodeForEachFormalInput(childNode, i, inputVar){
+      inputVarName = Var_VariableReadName(inputVar);
+      nodeName = Hrc_NodeFindHierarchicalName(childNode, 1);
+      formalName = ALLOC(char, strlen(nodeName) + strlen(inputVarName) +2);
+      sprintf(formalName, "%s.%s", nodeName, inputVarName);      
+      FREE(nodeName);
+      st_insert(tableOfFormalNames, (char *) formalName, (char *) (long) ( -1));
+    }
+    /* add childrens outputs' formal names to tableOfFormalNames */
+    Hrc_NodeForEachFormalOutput(childNode, i, outputVar){
+      outputVarName = Var_VariableReadName(outputVar);
+      nodeName = Hrc_NodeFindHierarchicalName(childNode, 1);
+      formalName = ALLOC(char, strlen(nodeName) + strlen(outputVarName) +2);
+      sprintf(formalName, "%s.%s", nodeName, outputVarName);      
+      FREE(nodeName);
+      st_insert(tableOfFormalNames, (char *) formalName, (char *) (long) ( -1));
+    }
+    /* recurse */
+    partCreateBoundaryNames(childNode, tableOfFormalNames);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Implements the partition with respect to the submodule boundary
+  nodes.]
+
+  SideEffects []
+
+  SeeAlso     [PartPartitionTotal PartPartitionInputsOutputs]
+
+******************************************************************************/
+void
+PartPartitionBoundary(
+  Ntk_Network_t *network,
+  Hrc_Node_t    *hnode,
+  graph_t       *partition,
+  lsList        rootList,
+  lsList        leaveList,
+  mdd_t         *careSet,
+  int           inTermsOfCombInputs)
+{
+  int            i;                /* Index for loops */
+  st_generator   *stGen;           /* To iterate over the MddIds of the support */
+  char           *formalName;
+  char           *actualName;
+  st_table       *tableOfActualNames;
+  st_table       *tableOfFormalNames;
+  lsList         nodeList;
+
+
+  assert(rootList == (lsList)0);
+  assert(leaveList == (lsList)0);
+
+  /* create table of all formal names */
+  tableOfFormalNames = st_init_table(strcmp, st_strhash);
+  partCreateBoundaryNames(hnode, tableOfFormalNames);
+
+  nodeList = lsCreate();
+  tableOfActualNames = st_init_table(strcmp, st_strhash);
+  st_foreach_item_int(tableOfFormalNames, stGen, &formalName, &i){
+    actualName = Ntk_NetworkReadActualNameFromFormalName(network, formalName);
+    if(!st_is_member(tableOfActualNames, actualName)){
+      lsNewEnd(nodeList, (lsGeneric) actualName, NIL(lsHandle));
+      st_insert(tableOfActualNames, actualName, (char *) (long) ( -1));
+    }
+  }
+  
+  
+  PartPartitionPartial(network, partition, rootList, leaveList, careSet, nodeList,
+		       inTermsOfCombInputs);
+  lsDestroy(nodeList, (void (*)(lsGeneric))0);  
+  st_free_table(tableOfActualNames);
+  st_foreach_item_int(tableOfFormalNames, stGen, &formalName, &i){
+    FREE(formalName);
+  }
+  st_free_table(tableOfFormalNames);
+} /* End of PartPartitionPartial */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
Index: vis_dev/vis-2.3/src/part/partCmd.c
===================================================================
--- vis_dev/vis-2.3/src/part/partCmd.c	(revision 14)
+++ vis_dev/vis-2.3/src/part/partCmd.c	(revision 14)
@@ -0,0 +1,688 @@
+/**CFile***********************************************************************
+
+  FileName    [partCmd.c]
+
+  PackageName [part]
+
+  Synopsis    [Command interface for the partition package.]
+
+  Author      [Abelardo Pardo]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "partInt.h"
+
+static char rcsid[] UNUSED = "$Id: partCmd.c,v 1.22 2009/04/11 01:47:18 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+/**Variable********************************************************************
+
+  Synopsis    [Buffer to store the environment in a setjmp call]
+
+  SeeAlso     [TimeOutHandle]
+
+******************************************************************************/
+static jmp_buf timeOutEnv;
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandBuildPartitionMdds(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int CommandPrintPartition(Hrc_Manager_t **hmgr, int argc, char **argv);
+static int CommandPrintPartitionStats(Hrc_Manager_t **hmgr, int argc, char **argv);
+static void TimeOutHandle(void);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the partitioning package.]
+
+  SideEffects []
+
+  SeeAlso     [Part_End]
+
+******************************************************************************/
+void
+Part_Init(void)
+{
+  Cmd_CommandAdd("build_partition_mdds", CommandBuildPartitionMdds,
+		 0/* doesn't change network */);
+  Cmd_CommandAdd("print_partition", CommandPrintPartition,
+		 0/* doesn't change network */);
+  Cmd_CommandAdd("print_partition_stats", CommandPrintPartitionStats,
+		 0/* doesn't change network*/);
+} /* End of Part_Init */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Ends the partitioning package.]
+
+  SideEffects []
+
+  SeeAlso     [Part_Init]
+
+******************************************************************************/
+void
+Part_End(void)
+{
+} /* End of Part_End */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the build_partition_mdds command.]
+
+  Description [The data structure needed to store the information
+  related to the partitioning process will be stored in a graph_t
+  structure that will become part of the network. This procedure
+  checks if the network has already registered this application. If
+  not, a new structure is allocated. After this process, depending on
+  the type of method specified in the command line, the specific
+  routine is executed. The user may set the specific flag
+  <tt>partition_method</tt> as the default to be used whenever no
+  method is specified in the command line. If no flag is defined, the
+  <tt>frontier</tt> method will be used.]
+
+  CommandName [build_partition_mdds]
+
+  CommandSynopsis [build a partition of MDDs for the flattened network]
+
+  CommandArguments [\[-h\] \[-i\] \[-n &lt;list&gt;\] \[-s &lt;num&gt;\] \[-t
+  &lt;seconds&gt;\] \[-v\] \[&lt;method&gt;\]]
+
+  CommandDescription [Build the MDDs of a flattened network.  Depending on the
+  <tt>method</tt> selected, the MDDs for the combinational outputs (COs) are
+  built in terms of either the combinational inputs (CIs) or in terms of some
+  subset of intermediate nodes of the network.  The MDDs built are stored in a
+  DAG called a "partition".  The vertices of a partition correspond to the
+  CIs, COs, and any intermediate nodes used.  Each vertex has a multi-valued
+  function (represented by MDDs) expressing the function of the corresponding
+  network node in terms of the partition vertices in its transitive fanin.
+  Hence, the MDDs of the partition represent a partial collapsing of the
+  network.<p>
+
+  This command must be preceded by the commands <tt>flatten_hierarchy</tt> and
+  <tt>static_order</tt>.  The partition built is stored with the network for
+  use by other commands, such as <tt>simulate</tt>, <tt>compute_reach</tt>,
+  <tt>model_check</tt>, etc.  This command has no affect when invoked on a
+  network that already has a partition.  To remove the existing partition of a
+  network, reinvoke <tt>flatten_hierarchy</tt>.<p>
+
+  The choice of <tt>method</tt> determines which intermediate nodes are
+  used. The <tt>inout</tt> method represents one extreme where no intermediate
+  nodes are used, and <tt>total</tt> represents the other extreme where every
+  node in the network has a corresponding vertex in the partition. If no
+  <tt>method</tt> is specified on the command line, then the value of the flag
+  <tt>partition_method</tt> is used (this flag is set by the command <tt>set
+  partition_method</tt>), unless it does not have a value, in which case the
+  <tt>forntier</tt> method is used. The different methods available are:
+
+  <dl>
+  <li> <tt>inout</tt>  Expresses the combinational
+  outputs in terms of the combinational inputs.
+
+  <li> <tt>total</tt> The partition built is isomorphic to the combinational
+  part of the network.  The function of each node is expressed in terms of its
+  immediate fanins. If the <tt>-i</tt> is used the function attached to each
+  vertex is computed as a function of the combinational inputs.
+
+  <li> <tt>partial</tt> Builds a partition using the intermediate nodes specified
+  with the <tt>-n</tt> option or the <tt>-f</tt> option.
+
+  <li> <tt>frontier</tt> (default) Builds a partition creating vertices for the intermediate nodes
+  as needed in order to control the BDD size. The threshold value for the BDD size can
+  be set by the parameter "partition_threshold". This method encompasses both "inout"
+  (set partition_threshold parameter to infinity) and
+  "total" (set partition_threshold parameter to 0).
+
+  <li> <tt>boundary</tt> Builds a partition in a fashion that preserves all nodes that
+  are Input/Output nodes of any hnode in the hierarchy rooted at the current hnode.
+
+  </dl>
+
+  Command options: <p>
+
+  <dl>
+
+  <dt> -h
+  <dd> Print the command usage.<p>
+
+  <dt> -i
+  <dd> Build the multi-valued functions of each partition vertex in terms of
+  the combinational inputs, rather than in terms of its transitive fanin
+  vertices.<p>
+
+  <dt> -n &lt;list&gt;
+  <dd> Used in conjunction with the <tt>partial</tt> method. <tt>List</tt> is
+  a comma separated list of network nodes to use as intermediate nodes in the
+  partition.<p>
+
+  <dt> -s &lt;num&gt;
+  <dd> Level of severity of a post-computation check applied to the partition data
+  structure (0 by default, meaning no check).<p>
+
+  <dt> -t &lt;seconds&gt;
+  <dd> Time in seconds allowed to build the partition. If the computation time
+  goes above that limit, the process of building the partition is aborted.  The
+  default is no limit.<p>
+
+  <dt> -v
+  <dd> Turn on the verbosity.<p>
+
+  </ul>]
+
+  SideEffects [Registers in the network the partition application with
+  the key specified by PART_NETWORK_APPL_KEY]
+
+  SeeAlso     [Ntk_NetworkAddApplInfo]
+
+******************************************************************************/
+static int
+CommandBuildPartitionMdds(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  static Part_PartitionMethod method;
+  static boolean              inTermsOfLeaves;
+  lsList                      nodeList = lsCreate();
+  graph_t                     *partition;
+  static int                  verbose;
+  static int                  sanityCheck;
+  static int                  timeOutPeriod;
+  int                         c;
+  int                         length;
+  char                        *methodString;
+  char                        *modelName;
+  Hrc_Node_t                  *currentNode;
+  Ntk_Network_t               *network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+  char *nodeName;
+  char *tmpNodeName;
+  char *realName;
+  FILE *nodeFile;
+  static boolean fileUsed;
+
+  fileUsed = FALSE;
+  inTermsOfLeaves = FALSE;
+  verbose = 0;
+  sanityCheck = 0;
+  timeOutPeriod = 0;
+
+  nodeFile = NIL(FILE);
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "f:hvin:s:t:")) != EOF) {
+    switch(c) {
+      case 'f':
+	fileUsed = TRUE;
+	nodeFile = Cmd_FileOpen(util_optarg, "r", &realName, 1);
+	FREE(realName);
+	if (nodeFile == NIL(FILE)){
+	  (void)fprintf(vis_stderr,"Cannot open %s\n", util_optarg);
+	  lsDestroy(nodeList, (void (*)(lsGeneric))0);
+	  return 1;
+	}
+	else{
+	  tmpNodeName = ALLOC(char, 512);
+	  while(fscanf(nodeFile, "%s\n", tmpNodeName) != EOF){
+	    if(*tmpNodeName != '#'){
+	      nodeName = ALLOC(char, strlen(tmpNodeName) + 2);
+	      sprintf(nodeName, "%s", tmpNodeName);
+	      lsNewEnd(nodeList, (lsGeneric)nodeName, NIL(lsHandle));
+	    }
+	  }
+	  FREE(tmpNodeName);
+	}
+	break;
+      case 'h':
+	goto usage;
+      case 'i':
+	inTermsOfLeaves = TRUE;
+	break;
+      case 'v':
+	verbose = 1;
+	break;
+      case 's':
+	sanityCheck = atoi(util_optarg);
+	break;
+      case 't':
+	timeOutPeriod = atoi(util_optarg);
+	break;
+      case 'n':
+	length = strlen(util_optarg);
+	for(c = 0; c < length; c++) {
+	  if (util_optarg[c] == ',') {
+	    util_optarg[c] = 0;
+	  } /* End of if */
+	} /* End of for */
+	c = 0;
+	while (c < length) {
+	  lsNewEnd(nodeList, &util_optarg[c], NIL(lsHandle));
+	  while (util_optarg[c++] != 0);
+	} /* End of while */
+	break;
+      default:
+	goto usage;
+    }
+  }
+
+  if (argc == util_optind) {
+    /* No method specified. Choosing default */
+    methodString = Cmd_FlagReadByName("partition_method");
+    if (methodString == NIL(char)) {
+      methodString = "default";
+    }
+  }
+  else {
+    methodString = argv[util_optind];
+  }
+
+  if (strcmp(methodString,"inout") == 0) {
+    method = Part_InOut_c;
+    if (lsLength(nodeList) != 0) {
+      (void) fprintf(vis_stderr, "Ignoring provided list of nodes in <inout>");
+      (void) fprintf(vis_stderr, " method\n");
+    } /* End of if */
+    if (inTermsOfLeaves) {
+      (void) fprintf(vis_stderr, "Ignoring -i flag in the <inout> method\n");
+    } /* End of if */
+  }
+  else if (strcmp(methodString,"partial") == 0) {
+    method = Part_Partial_c;
+    /* Make sure a list of nodes has been provided */
+    if (lsLength(nodeList) == 0) {
+      (void) fprintf(vis_stderr, "Method <partial> requires a non-empty list");
+      (void) fprintf(vis_stderr, " of nodes\n");
+
+      lsDestroy(nodeList, (void (*)(lsGeneric))0);
+      goto usage;
+    } /* End of if */
+  }
+  else if (strcmp(methodString,"total") == 0) {
+    method = Part_Total_c;
+    if (lsLength(nodeList) != 0) {
+      (void) fprintf(vis_stderr, "Ignoring provided list of nodes in <total>");
+      (void) fprintf(vis_stderr, " method\n");
+    } /* End of if */
+  }
+  else if (strcmp(methodString,"frontier") == 0) {
+    method = Part_Frontier_c;
+  }
+  else if (strcmp(methodString,"boundary") == 0) {
+    method = Part_Boundary_c;
+  }
+  else if (strcmp(methodString, "fine") == 0) {
+    method = Part_Fine_c;
+  }
+  else if (strcmp(methodString, "default") == 0) {
+    method = Part_Default_c;
+  }
+  else {
+    goto usage;
+  }
+
+
+  /* Check if the network has been read in */
+  if (network == NIL(Ntk_Network_t)) {
+    lsDestroy(nodeList, (void (*)(lsGeneric))0);
+    return 1;
+  }
+
+  /* Check if the network has the variables ordered */
+  if (Ord_NetworkTestAreVariablesOrdered(network, Ord_InputAndLatch_c) ==
+      FALSE) {
+    (void) fprintf(vis_stdout, "The MDD variables have not been ordered. Use static_order.\n");
+
+    lsDestroy(nodeList, (void (*)(lsGeneric))0);
+    return 1;
+  }
+
+  /* Check if there is already a partition attached to the network */
+  partition = (graph_t *) Ntk_NetworkReadApplInfo(network,
+						  PART_NETWORK_APPL_KEY);
+
+  /* If there is, just return. */
+  if (partition != NIL(graph_t)) {
+    (void) fprintf(vis_stderr, "partition already built; reinvoke ");
+    (void) fprintf(vis_stderr, "flatten_hierarchy to remove the current partition\n");
+    return 1;
+  }
+
+  /* Read the name of the model to be passed to Part_NetworkCreatePartition */
+  currentNode = Hrc_ManagerReadCurrentNode(*hmgr);
+  modelName = Hrc_NodeReadModelName(currentNode);
+
+  /* Set the timeout */
+  if (timeOutPeriod > 0) {
+    (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
+    (void) alarm(timeOutPeriod);
+    if (setjmp(timeOutEnv) > 0) {
+      (void) fprintf(vis_stdout, "Partition: timeout occurred after ");
+      (void) fprintf(vis_stdout, "%d seconds\n", timeOutPeriod);
+      alarm(0);
+
+      /* Partial clean up */
+      lsDestroy(nodeList, (void (*)(lsGeneric))0);
+      return 1;
+    }
+  }
+
+  /*
+   * Execute the partition algorithm. The two nil pointers is to indicate
+   * that the graph must represent the complete network.
+   */
+  partition = Part_NetworkCreatePartition(network, currentNode, modelName, (lsList)0,
+					  (lsList)0, NIL(mdd_t), method, nodeList,
+					  inTermsOfLeaves, verbose,
+					  sanityCheck);
+
+  /* Register the partition in the network if any */
+  Ntk_NetworkAddApplInfo(network, PART_NETWORK_APPL_KEY,
+			 (Ntk_ApplInfoFreeFn) Part_PartitionFreeCallback,
+			 (void *) partition);
+
+  /* Deactivate the alarm */
+  alarm(0);
+
+  /* Clean up */
+  if(fileUsed){
+    lsDestroy(nodeList, PartNameFree);
+  }
+  else{
+    lsDestroy(nodeList, (void (*)(lsGeneric))0);
+  }
+  return 0;
+
+usage:
+  (void) fprintf(vis_stderr, "usage: build_partition_mdds [options] [method]\n");
+  (void) fprintf(vis_stderr, "Options:\n");
+  (void) fprintf(vis_stderr, "    -h\t\tprint the command usage\n");
+  (void) fprintf(vis_stderr, "    -i\t\tBuild the functions in the partition in terms of the\n");
+  (void) fprintf(vis_stderr, "      \t\tcombinational inputs of the system. This option is redundant if\n");
+  (void) fprintf(vis_stderr, "      \t\tthe inout partition is chosen.\n");
+  (void) fprintf(vis_stderr, "    -n <list>\tComma separated list of network nodes to preserve in the\n");
+  (void) fprintf(vis_stderr, "             \tpartitioning. It only matters if the partial method has been\n");
+  (void) fprintf(vis_stderr, "             \tselected.\n");
+  (void) fprintf(vis_stderr, "    -f <file>\tSpecifies the file containing names of network nodes\n");
+  (void) fprintf(vis_stderr, "             \tto preserve while partitioning. This option matters only \n");
+  (void) fprintf(vis_stderr, "             \tif the partial method has been selected. Each node name must\n");
+  (void) fprintf(vis_stderr, "             \tbe listed on a new line. Comments in <file> must begin with '#'.\n");
+  (void) fprintf(vis_stderr, "    -s <num>\tLevel of severity check applied after computation. 0 being no\n");
+  (void) fprintf(vis_stderr, "      \t\tcheck, 1 begin simple check and >1 being exhaustive check.\n");
+  (void) fprintf(vis_stderr, "    -t <sec>\tTime in seconds allowed to build the partition. If the\n");
+  (void) fprintf(vis_stderr, "            \tcomputation time goes above that limit, the process of building\n");
+  (void) fprintf(vis_stderr, "            \tthe partition is aborted.\n");
+  (void) fprintf(vis_stderr, "    -v\t\tverbose\n");
+  (void) fprintf(vis_stderr, "Methods\n");
+  (void) fprintf(vis_stderr, "    inout\tIt represents the network with one MDD for\n");
+  (void) fprintf(vis_stderr, "         \teach combinational output as a function of the combinational\n");
+  (void) fprintf(vis_stderr, "         \tinputs\n");
+  (void) fprintf(vis_stderr, "    total\tPartitions the network preserving its structure. Every node in\n");
+  (void) fprintf(vis_stderr, "         \tthe network will produce a vertex in the partition graph. The\n");
+  (void) fprintf(vis_stderr, "         \tflag -i explained above controls the support of\n");
+  (void) fprintf(vis_stderr, "         \tthe functions attached to the vertices.\n");
+  (void) fprintf(vis_stderr, "    frontier\tThe default method. Partitions the network creating vertices for intermediate nodes\n");
+  (void) fprintf(vis_stderr, "         \tas necessary to control the BDD size. The threshold value of the\n");
+  (void) fprintf(vis_stderr, "         \tBDD can be specified by partition_threshold.\n");
+  (void) fprintf(vis_stderr, "    partial\tPartitions the network preserving certain nodes specified with\n");
+  (void) fprintf(vis_stderr, "           \tthe option -n or -f.\n");
+  (void) fprintf(vis_stderr, "    boundary\tPartitions the network preserving all nodes that are \n");
+  (void) fprintf(vis_stderr, "           \tsubcircuit IOs.\n");
+
+  lsDestroy(nodeList, (void (*)(lsGeneric))0);
+
+  return 1;            /* Error exit */
+} /* End of CommandBuildPartitionMdds */
+
+
+/**Function********************************************************************
+
+  Synopsis    [This frees a given char *]
+
+  Description [This function frees the memory assocated with a char * that
+	       is given as input]
+
+  SideEffects [ ]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+PartNameFree(
+  lsGeneric name)
+{
+  FREE(name);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Command level routine to write a file in dot format of the
+  partition DAG.]
+
+  SideEffects []
+
+  SeeAlso     [CommandBuildPartitionMdds]
+
+  CommandName [print_partition]
+
+  CommandSynopsis [print the "dot" format describing the partition graph]
+
+  CommandArguments [\[-h\] &lt;file&gt;]
+
+  CommandDescription [Write a file in the format taken by the tool
+  <tt>dot</tt>. Dot is a tool that, given a description of a graph in a
+  certain format, produces a postscript print of the graph. For more
+  information about <tt>dot</tt> look in <a
+  href="http://www.research.att.com/sw/tools/graphviz">
+  http://www.research.att.com/sw/tools/graphviz</a>.<p>
+
+  If no argument is specified on the command line, the output is written to
+  the standard output.<p>
+
+  Command options:<p>
+  <dl>
+
+  <dt> -h
+  <dd> Print the command usage.<p>
+
+  <dt> &lt;file&gt;
+  <dd> Name of file where the partition is to be written in "dot" format.
+
+  </dl>]
+
+******************************************************************************/
+static int
+CommandPrintPartition(
+  Hrc_Manager_t **hmgr,
+  int argc,
+  char **argv)
+{
+  FILE *fp;
+  int c, status;
+  graph_t *partition;
+  Ntk_Network_t *network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc,argv,"h")) != EOF){
+    switch(c){
+      case 'h':
+	goto usage;
+      default:
+	goto usage;
+    }
+  }
+
+  /* Check if the network has been read in */
+  if (network == NIL(Ntk_Network_t)) {
+    return 1;
+  }
+
+  /* Check if there is a partition attached to the network */
+  partition = (graph_t *) Ntk_NetworkReadApplInfo(network,
+						  PART_NETWORK_APPL_KEY);
+  if (partition == NIL(graph_t)) {
+    (void) fprintf(vis_stderr, "No partition has been created for this network.\n");
+    return 1;
+  }
+
+  if (argc == 1) {
+    fp = vis_stdout;
+  }
+  else if (argc == 2) {
+    fp = Cmd_FileOpen(*(++argv), "w", NIL(char *), /* silent */ 1);
+    if (fp == NIL(FILE)) {
+      (void) fprintf(vis_stderr, "Cannot write to %s\n", *argv);
+      return 1;
+    }
+  }
+  else {
+    goto usage;
+  }
+
+  error_init();
+  status = PartPartitionPrint(fp, partition);
+  (void) fprintf(vis_stderr, "%s", error_string());
+  fflush(fp);
+
+  /* If we opened a file before, close it */
+  if (argc == 2) {
+    (void) fclose(fp);
+  }
+  return (status ? 0 : 1);
+
+ usage:
+  (void) fprintf(vis_stderr, "usage: print_partition [-h] [file]\n");
+  (void) fprintf(vis_stderr, "    -h\t\tprint the command usage\n");
+  return 1;
+} /* End of CommandPrintPartition */
+
+/**Function********************************************************************
+
+  Synopsis [Command level routine to print some stats of the partition DAG.]
+
+  SideEffects []
+
+  SeeAlso     [CommandBuildPartitionMdds]
+
+  CommandName [print_partition_stats]
+
+  CommandSynopsis [print statistics about the partition graph]
+
+  CommandArguments [\[-h\] \[-n\]]
+
+  CommandDescription [Print statistics about the partition currently attached
+  to the network, such as:
+
+  <dl>
+  <li>Method used to build the partition.
+  <li>Number of sink vertices.
+  <li>Number of source vertices.
+  <li>Total number of vertices.
+  <li>Number of shared MDD nodes used to represent the functions.
+  </dl>
+
+  Command options:<p>
+
+  <dl>
+
+  <dt> -h
+  <dd> Print the command usage.<p>
+
+  <dt> -n
+  <dd> Print the name of the network nodes represented by vertices in the
+  partition.
+
+  </dl>]
+
+******************************************************************************/
+static int
+CommandPrintPartitionStats(
+  Hrc_Manager_t **hmgr,
+  int argc,
+  char **argv)
+{
+  int c;
+  graph_t *partition;
+  Ntk_Network_t *network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+  boolean printNodeNames = FALSE;
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc,argv,"hn")) != EOF){
+    switch(c){
+      case 'n':
+	printNodeNames = TRUE;
+	break;
+      case 'h':
+	goto usage;
+      default:
+	goto usage;
+    }
+  }
+
+  /* Check if the network has been read in */
+  if (network == NIL(Ntk_Network_t)) {
+    return 1;
+  }
+
+  /* Check if there is a partition attached to the network */
+  partition = (graph_t *) Ntk_NetworkReadApplInfo(network,
+						  PART_NETWORK_APPL_KEY);
+  if (partition == NIL(graph_t)) {
+    (void) fprintf(vis_stderr, "No partition has been created for this network.\n");
+    return 1;
+  }
+
+  /* Print the statistics to vis_stdout */
+  Part_PartitionPrintStats(vis_stdout, partition, printNodeNames);
+  return 0;
+
+ usage:
+  (void) fprintf(vis_stderr, "usage: print_partition_stats [-h] [-n]\n");
+  (void) fprintf(vis_stderr, "    -h\t\tprint the command usage\n");
+  (void) fprintf(vis_stderr, "    -n\t\tprint names of network nodes ");
+  (void) fprintf(vis_stderr, "represented by vertices\n");
+  return 1;
+} /* End of CommandPrintPartitionStats */
+
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [required]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+TimeOutHandle(void)
+{
+  longjmp(timeOutEnv, 1);
+} /* End of TimeOutHandle */
Index: vis_dev/vis-2.3/src/part/partCollapse.c
===================================================================
--- vis_dev/vis-2.3/src/part/partCollapse.c	(revision 14)
+++ vis_dev/vis-2.3/src/part/partCollapse.c	(revision 14)
@@ -0,0 +1,312 @@
+/**CFile***********************************************************************
+
+  FileName    [partCollapse.c]
+
+  PackageName [part]
+
+  Synopsis [Implements a procedure to collapse several internal vertices of a
+  partition into a single one.]
+
+  Description [Given a partition, a set of root vertices and a set of leaf
+  vertices, obtain the array_t of Mvf_Function_t * representing the functions
+  at the root vertices in terms of the variables at the leaf vertices.]
+
+  Author      [Abelardo Pardo]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "partInt.h"
+
+static char rcsid[] UNUSED = "$Id: partCollapse.c,v 1.5 2005/04/16 06:14:54 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static Mvf_Function_t * CollapseRecur(graph_t *partition, vertex_t *vertexPtr, st_table *tableOfLeaves, mdd_t *careSet, st_table *alreadyComputed);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Create Mdd Arrays given leaves and roots.]
+
+  Description [Given an array of vertex names as roots and an array of
+  mddIds as leaves, obtain the Mvf_Function_t of the root vertices in terms
+  of the mddIds given as leaves. This function just creates the proper
+  parameters to later call Part_PartitionCollapse.]
+
+  SideEffects []
+
+  SeeAlso     [Part_PartitionCollapse]
+
+******************************************************************************/
+array_t *
+Part_PartitionBuildFunctions(
+  graph_t *partition,
+  array_t *roots,
+  array_t *leaves,
+  mdd_t *careSet)
+{
+  st_table *leavesTable;      /* To pass to Part_PartitionCollapse */
+  array_t  *rootVertexArray;  /* To pass to Part_PartitionCollapse */
+  array_t  *result;           /* Array of Arrays of mdd_t * */
+  int      i;
+
+  /* Create the table of leaves */
+  leavesTable = st_init_table(st_ptrcmp, st_ptrhash);
+  for(i = 0; i < array_n(leaves); i++) {
+    int varId = array_fetch(int, leaves, i);
+    vertex_t *vertexPtr;
+
+    /* turned off the check below since it is done later in the */
+    /* function SimTestPartInTermsOfCI                          */
+    /* Make sure the leaves have a valid mddId */
+/*    assert(varId != NTK_UNASSIGNED_MDD_ID); */
+    
+    vertexPtr = Part_PartitionFindVertexByMddId(partition, varId);
+    if (vertexPtr != NIL(vertex_t)) {
+      st_insert(leavesTable, (char *)vertexPtr, NIL(char));
+    } /* End of if */
+  } /* End of for */
+
+  /* Create array of roots */
+  rootVertexArray = array_alloc(vertex_t *, array_n(roots));
+  for(i = 0; i < array_n(roots); i++) {
+    char *vertexName = array_fetch(char *, roots, i);
+    vertex_t *vertexPtr = Part_PartitionFindVertexByName(partition, 
+							 vertexName);
+    
+    /* Make sure the vertex is member of the partition */
+    assert(vertexPtr != NIL(vertex_t));
+
+    array_insert(vertex_t *, rootVertexArray, i, vertexPtr);
+  } /* End of for */
+
+  /* Effectively build the functions */
+  result = Part_PartitionCollapse(partition, rootVertexArray,
+				  leavesTable, careSet);
+
+  /* Clean up */
+  array_free(rootVertexArray);
+  st_free_table(leavesTable);
+
+  return result;
+} /* End of Part_PartitionBuildFunctions */
+
+/**Function********************************************************************
+
+  Synopsis    [Computes root functions in terms of leaf variables.]
+
+  Description [The partition is a DAG. Given an array of vertices (vertex_t*)
+  called roots and a table of vertices (vertex_t*) called leaves, obtains one
+  Mvf_Function_t for every root in terms of the variables attached to the leaf
+  vertices.  Returns the array of Mvf_Function_t*, in one-to-correspondence
+  with the roots.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+Part_PartitionCollapse(
+  graph_t *partition,
+  array_t *roots,
+  st_table *leaves,
+  mdd_t *careSet)
+{
+  int            i;
+  st_table       *vertexCache;          /* Store already processed vertices */
+  st_generator   *stGen;                /* To iterate over st_table */
+  vertex_t       *vertexPtr;            /* Pointer to vertex being processed */
+  array_t        *result;               /* Mvf_Function_ts for the roots */ 
+  Mvf_Function_t *collapsedFunction;
+
+  /* Array holding the result */
+  result = array_alloc(Mvf_Function_t *, array_n(roots));
+  
+  /* Table to store the already computed vertices */
+  vertexCache = st_init_table(st_ptrcmp, st_ptrhash);
+
+  /* iterate over the given roots */
+  arrayForEachItem(vertex_t *, roots, i, vertexPtr) {
+    /* No cluster vertices are allowed in the roots specification */
+    if (PartVertexReadType(vertexPtr) == Part_VertexCluster_c) {
+      (void) fprintf(vis_stderr, "Warning -- Ignoring cluster vertices in");
+      (void) fprintf(vis_stderr, " PartitionCollapse\n");
+    } /* End of if */
+    else {
+      Mvf_Function_t *functionLookUp;
+
+      if (st_lookup(vertexCache, vertexPtr, &functionLookUp) == 1) {
+        collapsedFunction = Mvf_FunctionDuplicate(functionLookUp);
+      }
+      else {
+        collapsedFunction = CollapseRecur(partition, vertexPtr, 
+					  leaves, careSet, vertexCache);
+      }
+      /* Store the function in the result array */
+      array_insert(Mvf_Function_t *, result, i, collapsedFunction);
+    }
+  } /* End of arrayForEachItem */
+  
+  /* 
+   * Save the root nodes from deletion and save their mdds from
+   * deallocation.
+   */
+  arrayForEachItem(vertex_t *, roots, i, vertexPtr) {
+    st_delete(vertexCache, &vertexPtr, NULL);
+  }
+
+  /* Delete the intermediate results produced in the computation */
+  st_foreach_item(vertexCache, stGen, &vertexPtr, &collapsedFunction) {
+    Mvf_FunctionFree(collapsedFunction);
+  }
+  st_free_table(vertexCache);
+
+  return result;
+} /* End of Part_PartitionCollapse */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Executes the recursive step of the collapsing procedure.]
+
+  Description [Given a node, recursively collapses its fanins and then
+  composes the result to obtain the new function. The result is the
+  function after substituting the variables are represented by
+  functions in terms of the leaves.]
+
+  SideEffects []
+
+  SeeAlso     [Part_PartitionCollapse]
+
+******************************************************************************/
+static Mvf_Function_t *
+CollapseRecur(
+  graph_t *partition,
+  vertex_t *vertexPtr,
+  st_table *tableOfLeaves,
+  mdd_t *careSet,
+  st_table *alreadyComputed)
+{
+  Mvf_Function_t *result;      /* Array to return the result */
+  Mvf_Function_t *preresult;   /* Result before careSet minimization */
+  Mvf_Function_t *vertexFn;    /* Mvf attached to vertexPtr */
+  array_t        *faninMddIds; /* Ids of every vertex of the fanin */
+  array_t        *faninMvfs;   /* Array of functions obtained for the fanins */
+  Mvf_Function_t *faninResult; /* Function obtained for one fanin */
+  edge_t         *edgePtr;     /* Fanin edge*/
+  lsGen          gen;          /* List generator used for iteration */
+  int            i;
+    
+  /* Look up in the alreadyComputedTable */
+  if (st_lookup(alreadyComputed, vertexPtr, &result) == 1) {
+    return result;
+  } /* End of if */
+
+  /* 
+   * Initialize the arrays needed to call the function
+   * Mvf_FunctionComposeWithFunctionArray 
+   */
+  faninMddIds = array_alloc(int, 0);
+  faninMvfs = array_alloc(Mvf_Function_t *, 0);
+
+  /* Obtain results for each fanin */
+  i=0;
+  foreach_in_edge(vertexPtr, gen, edgePtr) {
+    vertex_t *fromVertex = g_e_source(edgePtr);
+
+    /* Skip the fanins that are leaves */
+    if (!st_is_member(tableOfLeaves, (char *)fromVertex) ) {
+      /* Compute the array recursively */
+      faninResult = CollapseRecur(partition, fromVertex, tableOfLeaves, careSet,
+				  alreadyComputed);
+      array_insert(int, faninMddIds, i, PartVertexReadMddId(fromVertex));
+      array_insert(Mvf_Function_t *, faninMvfs, i, faninResult);
+      i++;
+    } /* End of if */
+  }
+
+  /* 
+   * Compose the obtained fanin functions as variables in the
+   * vertexPtr's function. If all the fanins are leaves, the function
+   * Mvf_FunctionComposeWithFunctionArray returns a duplicate of the
+   * array which is needed to be stored in the alreadyComputed table.
+   */
+  vertexFn = PartVertexReadFunction(vertexPtr);
+  preresult = Mvf_FunctionComposeWithFunctionArray(vertexFn, 
+						faninMddIds,
+						faninMvfs);
+  /* Minimize the result with respect to the given care set */
+  if (careSet != NIL(mdd_t)) {
+    result = Mvf_FunctionMinimize(preresult, careSet);
+    Mvf_FunctionFree(preresult);
+  } 
+  else {
+    result = preresult;
+  }
+  
+  array_free(faninMddIds);
+  /* 
+   * There is no need to delete the mdds stored in this array since
+   * they are stored in the alreadyComputed table.
+   */
+  array_free(faninMvfs);
+
+  /* Insert the result in the already-obtained results */
+  st_insert(alreadyComputed, (char *)vertexPtr, (char *)result);
+
+  return result;
+} /* End of CollapseRecur */
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/part/partFine.c
===================================================================
--- vis_dev/vis-2.3/src/part/partFine.c	(revision 14)
+++ vis_dev/vis-2.3/src/part/partFine.c	(revision 14)
@@ -0,0 +1,534 @@
+/**CFile***********************************************************************
+
+  FileName    [partFine.c]
+
+  PackageName [part]
+
+  Synopsis [Implements the partition of the network with respect to a
+  list of nodes provided by the user.]
+
+  Description [The network is composed of an arbitrary set of nodes, each of
+  them implementing some function. This partitioning method will produce a
+  graph representing the network in which the nodes specified in a list will be
+  preserved in the graph structure. Different heuristics will control the
+  structure of the rest of the partition.]
+
+  SeeAlso     [partInOut.c partTotal.c]
+
+  Author      [HoonSang Jin]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "partInt.h"
+
+static char rcsid[] UNUSED = "$Id: partFine.c,v 1.5 2005/04/30 04:00:38 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#define PartVertexReadGeneric(vPtr)  ((PartVertexInfo_t *)(vPtr)->user_data)->generic
+#define PartVertexReadGeneric1(vPtr)  ((PartVertexInfo_t *)(vPtr)->user_data)->generic1
+#define BASIC_PARTITION_UNIT 15
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static 	int 		Part_IsFanoutInverter(Ntk_Node_t *node);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Implements the partition with respect to the given list of
+  nodes.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     [PartPartitionTotal PartPartitionInputsOutputs]
+
+******************************************************************************/
+void
+PartPartitionFineGrain(
+  Ntk_Network_t *network,
+  graph_t       *partition,
+  mdd_t         *careSet)
+{
+  Ntk_Node_t     *node;            /* Pointer to iterate over nodes */
+  Mvf_Function_t *mddFunction;     /* Pointer to a MDD */
+  mdd_manager    *manager;         /* Mdd manager in the partition */
+  st_table       *tableOfLeaves;   /* To store the leaves of the graph */
+  st_table       *mddIdToNodeName; /* For quick lookup of node's name */
+  array_t        *arrayOfMvf;      /* To store the next state functions */
+  array_t        *arrayOfRoots;    /* To store the roots of the graph */
+  lsList         sinkList;         /* Vertices representing comb. outputs */
+  lsGen          gen;              /* To iterate over lists */
+  vertex_t       *toVertex;        /* Will hold the current function vertex */
+  int            i;                /* Index for loops */
+  long           mddId;            /* Will hold the mddId being processed */
+  st_table       *mddSupport;      /* To store the support of the Mvf_Function */
+  st_generator   *stGen;           /* To iterate over the MddIds of the support */
+  vertex_t       *fromVertex;      /* Will hold the current vertex in the support */
+  array_t        *singletonMvfArray;
+  array_t        *singletonArrayOfRoots;
+  array_t        *tmpArrayOfMvf;
+  Mvf_Function_t *nodeMvf;
+  lsList         sortedListOfNodes;     
+  array_t        *sortedArrayOfPartitionNodes;
+  array_t        *unsortedArrayOfPartitionNodes;
+  st_table       *tableOfPartitionNodes;
+  Ntk_Node_t 	 *fanin, *fanout;
+
+  manager = PartPartitionReadMddManager(partition);
+  
+  /* Make the combinational input  nodes into leaves */
+  tableOfLeaves = st_init_table(st_ptrcmp, st_ptrhash);
+  mddIdToNodeName = st_init_table(st_numcmp, st_numhash);
+  Ntk_NetworkForEachCombInput(network, gen, node) {
+    if(Ntk_NodeReadMddId(node) == NTK_UNASSIGNED_MDD_ID)
+      Ord_NetworkAssignMddIdForNode(network, node);
+    st_insert(tableOfLeaves, (char *)node, (char *) (long) (-1) );
+    st_insert(mddIdToNodeName, (char *) (long)Ntk_NodeReadMddId(node), 
+	      Ntk_NodeReadName(node));
+  }
+
+  unsortedArrayOfPartitionNodes = array_alloc(Ntk_Node_t *, 0);  
+  tableOfPartitionNodes = st_init_table(st_ptrcmp, st_ptrhash);
+  /* Make the target node list for partition */
+  Ntk_NetworkForEachNode(network, gen, node) {
+    if(Ntk_NodeTestIsShadow(node))	continue;
+    else if(Ntk_NodeTestIsCombInput(node))	continue;
+    else if(Ntk_NodeTestIsCombOutput(node))	continue;
+    else if(Ntk_NodeReadNumFanouts(node) == 1) { 
+      fanout = Part_GetFanoutFreeLogic(node);
+      if(Ntk_NodeTestIsCombOutput(fanout));
+      else if(Ntk_NodeReadNumFanins(node) > 10);
+      else if(Ntk_NodeReadNumFanins(fanout) == 1)	continue;
+      else if(!Part_CheckLeafNodeCondition(node, tableOfPartitionNodes, 5, 10)) {
+        if(Ntk_NodeReadNumFanins(node) == 1) {
+           fanin = Part_GetFaninFreeLogic(node);
+           if(!fanin)	continue;
+           if(Ntk_NodeTestIsCombInput(fanin))	continue;
+        }
+        continue;
+      }
+/**
+      if(Part_IsFanoutInverter(node))	continue;
+      if(Ntk_NodeReadNumFanins(node) == 1)	continue;
+**/
+    }
+    /**
+    else if(Ntk_NodeReadNumFanins(node) == 1) {
+       fanin = Part_GetFaninFreeLogic(node);
+       if(!fanin)	continue;
+       if(Ntk_NodeTestIsCombInput(fanin))	continue;
+    }
+    **/
+
+    array_insert_last(Ntk_Node_t *, unsortedArrayOfPartitionNodes, node);
+    st_insert(tableOfPartitionNodes, (char *) node, (char *) (long) (-1));
+  }
+
+  /* create sorted array of partition nodes */
+  sortedListOfNodes = Ntk_NetworkComputeTopologicalOrder(network, 
+                               unsortedArrayOfPartitionNodes, tableOfLeaves);
+
+  sortedArrayOfPartitionNodes = array_alloc(Ntk_Node_t *, 0);  
+  lsForEachItem(sortedListOfNodes, gen, node){
+    /* sortedListOfNodes includes many internal nodes, need to filter them out */
+    if(st_is_member(tableOfPartitionNodes, (char *) node)){
+      array_insert_last(Ntk_Node_t *, sortedArrayOfPartitionNodes, node);
+      if(Ntk_NodeReadMddId(node) == NTK_UNASSIGNED_MDD_ID) 
+        Ord_NetworkAssignMddIdForNode(network, node);
+    }   
+  }
+  array_free(unsortedArrayOfPartitionNodes);
+  lsDestroy(sortedListOfNodes, (void (*)(lsGeneric))0);  
+  st_free_table(tableOfPartitionNodes);
+      
+
+  tmpArrayOfMvf = array_alloc(Mvf_Function_t *, 0);
+  for(i=0; i < array_n(sortedArrayOfPartitionNodes); i++){
+    node = array_fetch(Ntk_Node_t *, sortedArrayOfPartitionNodes, i);
+    singletonArrayOfRoots = array_alloc(Ntk_Node_t *, 0);
+    array_insert_last(Ntk_Node_t *, singletonArrayOfRoots, node);
+    singletonMvfArray = Ntm_NetworkBuildMvfs(network, singletonArrayOfRoots, 
+					     tableOfLeaves, careSet);
+    nodeMvf = array_fetch(Mvf_Function_t *, singletonMvfArray, 0);
+    array_insert_last(Mvf_Function_t *, tmpArrayOfMvf, nodeMvf);
+    array_free(singletonMvfArray);
+    array_free(singletonArrayOfRoots);
+    
+    if(Ntk_NodeReadMddId(node) == NTK_UNASSIGNED_MDD_ID){
+      Ord_NetworkAssignMddIdForNode(network, node);
+    }
+    st_insert(tableOfLeaves, (char *)node, (char *) (long) (-1) );    
+    st_insert(mddIdToNodeName, (char *) (long)Ntk_NodeReadMddId(node), 
+		Ntk_NodeReadName(node));
+
+  }
+
+
+  arrayOfRoots = array_alloc(Ntk_Node_t *, 0);
+  Ntk_NetworkForEachCombOutput(network, gen, node) {
+    array_insert_last(Ntk_Node_t *, arrayOfRoots, node);
+  }
+  arrayOfMvf = Ntm_NetworkBuildMvfs(network, arrayOfRoots, tableOfLeaves, 
+				    careSet);
+
+  array_append(arrayOfRoots, sortedArrayOfPartitionNodes);
+  array_append(arrayOfMvf, tmpArrayOfMvf);
+  array_free(sortedArrayOfPartitionNodes);
+  array_free(tmpArrayOfMvf);
+
+
+  /* Create one vertex for every component of arrayOfMvf */
+  for (i=0; i < array_n(arrayOfRoots); i++) {
+    node = array_fetch(Ntk_Node_t *, arrayOfRoots, i);
+    mddId = Ntk_NodeReadMddId(node);
+
+    /* obtain the function attached to the node */
+    mddFunction = array_fetch(Mvf_Function_t *, arrayOfMvf, i);
+
+
+    toVertex = g_add_vertex(partition);
+    
+    /* Update the look-up tables in the graph */
+    st_insert(PartPartitionReadNameToVertex(partition),
+	      Ntk_NodeReadName(node), (char *)toVertex);
+    if (mddId != -1) {
+      st_insert(PartPartitionReadMddIdToVertex(partition),
+		(char *)(long) mddId, (char *)toVertex);
+    } 
+    toVertex->user_data = 
+      (gGeneric)PartVertexInfoCreateSingle(Ntk_NodeReadName(node), 
+					   mddFunction, 
+					   mddId);
+  } 
+  
+  /* Read the list of vertices on the graph */
+  sinkList = lsCopy(g_get_vertices(partition), (lsGeneric (*)(lsGeneric))0);
+
+  /* 
+   * For every function on every combinational output, compute the
+   * support and create vertices in the graph when needed 
+   */
+  lsForEachItem(sinkList, gen, toVertex) {
+    mddFunction = PartVertexReadFunction(toVertex);
+    mddSupport = PartCreateFunctionSupportTable(mddFunction);
+
+    /* 
+     * Create one edge (and one vertex if necessary) for every element
+     * in mddSupport 
+     */
+    st_foreach_item(mddSupport, stGen, &mddId, NULL) {
+      char *name;
+
+      /* Create vertex with the information if needed */
+      if (st_lookup(PartPartitionReadMddIdToVertex(partition), 
+		    (char *)(long) mddId, &fromVertex) == 0) {
+	fromVertex = g_add_vertex(partition);
+	
+	st_lookup(mddIdToNodeName, (char *)(long) mddId, &name);
+
+	/* Update the look-up tables in the graph */
+	st_insert(PartPartitionReadNameToVertex(partition), 
+		  name, (char *)fromVertex);
+	st_insert(PartPartitionReadMddIdToVertex(partition),
+		  (char *)(long) mddId, (char *)fromVertex);
+	
+	/* Create vertex data */
+	fromVertex->user_data = 
+	  (gGeneric)PartVertexInfoCreateSingle(name,
+					       Mvf_FunctionCreateFromVariable(manager,mddId),
+					       mddId);
+      } 
+      
+      /* 
+       * Add the edge to the graph. Make sure a self loop is not added. The
+       * self loop may be produced by a mdd that has in its support the same
+       * variables that represent the mddId of the node.
+       */
+      if (fromVertex != toVertex) {
+	g_add_edge(fromVertex, toVertex);
+      } /* End of if */
+      
+    } /* End of st_foreach_item */
+    
+    /* Clean the support table */
+    st_free_table(mddSupport);
+  } /* End of lsForEachItem */
+  
+  /* Clean up */
+  st_free_table(mddIdToNodeName);
+  st_free_table(tableOfLeaves);
+  array_free(arrayOfRoots);
+  lsDestroy(sinkList, (void (*)(lsGeneric))0);
+  /* 
+   * The contents of this array (array of mdds) is not deallocated because the
+   * information has been transferred to the partition structure. All the
+   * functions are stored now as part of the vertex information.
+   */
+  array_free(arrayOfMvf);
+  fprintf(stdout, "NOTICE : current peak memory = %ld\n",
+  bdd_read_peak_memory(manager));
+
+} /* End of PartPartitionCut */
+
+
+/**Function********************************************************************
+
+  Synopsis [Check if the fanout of given node is inverter.]
+
+  Description [ Check if the fanout of given node is inverter.]
+
+  SideEffects []
+
+  SeeAlso     [PartPartitionTotal PartPartitionInputsOutputs]
+
+******************************************************************************/
+int 
+Part_IsFanoutInverter(Ntk_Node_t *node)
+{
+  Ntk_Node_t *fanout;
+
+  fanout = Part_GetFanoutFreeLogic(node);
+  if(!fanout)	return(1);
+  if(Ntk_NodeReadNumFanins(fanout) == 1)	return(1);
+  else 					return(0);
+
+}
+
+/**Function********************************************************************
+
+  Synopsis [Check if the node can be assumed as leaf node based on given threshold.]
+
+  Description [ This function identify the leaf node for fine grain partition based on threshold.]
+
+  SideEffects []
+
+  SeeAlso     [PartPartitionTotal PartPartitionInputsOutputs]
+
+******************************************************************************/
+int
+Part_CheckLeafNodeCondition(Ntk_Node_t *node, 
+                            st_table *leafTable,
+                            int fanoutFreeLimit,
+		            int numVariableLimit)
+{
+  int nVar, nDepth, i;
+  Ntk_Node_t *fanout, *tnode, *tfanin;
+  st_table *ownTable;
+
+
+  nVar = Ntk_NodeReadNumFanins(node);
+  nDepth = 0;
+  fanout = node;
+  ownTable = st_init_table(st_ptrcmp, st_ptrhash);
+  while(1) {
+    if(nDepth > fanoutFreeLimit)return(1);
+    if(nVar > numVariableLimit)	return(1);
+
+    if(!st_lookup(leafTable, fanout, &tnode)) {
+       fanout = Part_GetFanoutFreeLogic(fanout);
+       if(fanout == 0)	break;
+       if(Ntk_NodeTestIsCombInput(fanout))	break;
+       if(Ntk_NodeTestIsCombOutput(fanout))	break;
+    }
+    else break;
+    nDepth++;
+    if(fanout == 0)	break;
+    nVar += Img_CutCalcTransitiveFanin(leafTable, ownTable, fanout,
+    node, numVariableLimit);
+    if(nVar > numVariableLimit) {
+      st_free_table(ownTable);
+      return(1);
+    }
+  }
+
+  Ntk_NodeForEachFanin(node, i, tfanin) {
+    if(tfanin == 0)	continue;
+    if(Ntk_NodeReadNumFanouts(tfanin) != 1)	continue;
+    nVar += Img_CutCalcTransitiveFanin(leafTable, ownTable, tfanin, 0, numVariableLimit)-1;
+    if(nVar > numVariableLimit) {	
+      st_free_table(ownTable);
+      return(1);
+    }
+  }
+  if(nVar > numVariableLimit) {
+    st_free_table(ownTable);
+    return(1);
+  }
+/**
+  fanin = node;
+  nDepth = 0;
+  while(1) {
+    if(nDepth > fanoutFreeLimit)return(1);
+    if(nVar > numVariableLimit)	return(1);
+    if(!st_lookup(leafTable, (char *)fanin, (char **)&tnode)) {
+
+      Ntk_NodeForEachFanin(fanin, i, tfanin) {
+        if(tfanin == 0)	continue;
+        if(Ntk_NodeReadNumFanouts(tfanin) != 1)	continue;
+        nVar += Ntk_NodeReadNumFanins(tfanin) - 1;
+      }
+      if(nVar > numVariableLimit)	return(1);
+
+      fanin = Part_GetFaninFreeLogic(fanin);
+      if(fanin == 0)	break;
+      if(Ntk_NodeTestIsCombInput(fanin))	break;
+      if(Ntk_NodeTestIsCombOutput(fanin))	break;
+
+    }
+    else break;
+    nDepth++;
+    
+  }
+**/
+  return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Compute the number of support variables of given node.]
+
+  Description [ Compute the number of support variables of given node.]
+
+  SideEffects []
+
+  SeeAlso     [PartPartitionTotal PartPartitionInputsOutputs]
+
+******************************************************************************/
+int
+Img_CutCalcTransitiveFanin(st_table *table, 
+                           st_table *ownTable,
+                           Ntk_Node_t *node, 
+			   Ntk_Node_t *fanin,
+			   int limit)
+{
+  int i, nVar;
+  Ntk_Node_t *tfanin, *tnode;
+
+  nVar = 0;
+  Ntk_NodeForEachFanin(node, i, tfanin) {
+    if(tfanin == fanin)	continue;
+    if(tfanin == 0)	continue;
+    if(Ntk_NodeReadNumFanouts(tfanin) != 1){
+      if(!st_lookup(ownTable, tfanin, &tnode)) {
+        st_insert(ownTable, tfanin, tfanin);
+        nVar++;
+      }
+      continue;
+    }
+    if(Ntk_NodeTestIsCombInput(tfanin))	{
+      if(!st_lookup(ownTable, tfanin, &tnode)) {
+        st_insert(ownTable, tfanin, tfanin);
+        nVar++;
+      }
+      continue;
+    }
+    if(Ntk_NodeTestIsCombOutput(tfanin)) {
+      if(!st_lookup(ownTable, tfanin, &tnode)) {
+        st_insert(ownTable, tfanin, tfanin);
+        nVar++;
+      }
+      continue;
+    }
+    if(!st_lookup(table, tfanin, &tnode)) {
+      nVar += Img_CutCalcTransitiveFanin(table, ownTable, tfanin,  0, limit);
+    }
+    else
+      nVar++;
+    if(nVar > limit)	return(nVar);
+  }
+  return(nVar);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Check if the fanin of given node is fanout free.]
+
+  Description [Check if the fanin of given node is fanout free.]
+
+  SideEffects []
+
+  SeeAlso     [PartPartitionTotal PartPartitionInputsOutputs]
+
+******************************************************************************/
+Ntk_Node_t *
+Part_GetFaninFreeLogic(Ntk_Node_t *node)
+{
+  int i;
+  Ntk_Node_t *fanin;
+
+  Ntk_NodeForEachFanin(node, i, fanin) {
+    if(Ntk_NodeReadNumFanouts(fanin) != 1)	continue;
+    return(fanin); 
+  }
+  return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Check if the fanout of given node is fanout free.]
+
+  Description [Check if the fanout of given node is fanout free.]
+
+  SideEffects []
+
+  SeeAlso     [PartPartitionTotal PartPartitionInputsOutputs]
+
+******************************************************************************/
+Ntk_Node_t *
+Part_GetFanoutFreeLogic(Ntk_Node_t *node)
+{
+  int i;
+  Ntk_Node_t *fanout;
+
+  if(Ntk_NodeReadNumFanouts(node) != 1)	return(0);
+  Ntk_NodeForEachFanout(node, i, fanout) {
+    return(fanout); 
+  }
+  return(0);
+}
Index: vis_dev/vis-2.3/src/part/partFrontier.c
===================================================================
--- vis_dev/vis-2.3/src/part/partFrontier.c	(revision 14)
+++ vis_dev/vis-2.3/src/part/partFrontier.c	(revision 14)
@@ -0,0 +1,1472 @@
+/**CFile***********************************************************************
+
+  FileName    [partFrontier.c]
+
+  PackageName [part]
+
+  Synopsis [Implements the partition of the network based on the strategy of
+  creating a node whenever the size of the BDD representing the functionality
+  of the node increases the threshold value.]
+
+  Description [The network is composed of an arbitrary set of nodes each of
+  them implementing some simple function.  This method will create a graph such
+  that every vertex in that graph represents a node in the network.  Each node 
+  in the primary he result
+  is a graph with exactly the same topology as the network and such that every
+  node has an MddId and a corresponding function.]
+
+  SeeAlso     [part.h]
+
+  Author      [Rajeev K. Ranjan, Chao Wang]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+******************************************************************************/
+#include "partInt.h"
+
+static char rcsid[] UNUSED = "$Id: partFrontier.c,v 1.25 2005/05/11 20:50:32 jinh Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void PartitionCreateEdges(graph_t *partition);
+static Mvf_Function_t * NodeBuildMvf(Ntk_Node_t * node, st_table * nodeToMvfTable);
+static Mvf_Function_t * NodeBuildMvf2(Ntk_Node_t * node, st_table * nodeToMvfTable, st_table *faninNumberTable);
+static Mvf_Function_t * NodeBuildPseudoInputMvf(Ntk_Node_t * node);
+static void PrintPartitionRecursively(vertex_t *vertex, st_table *vertexTable, int indent);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Read or create the Boolean network variables (BNVs).]
+
+  Description [Read or create the Boolean network variables. If the
+  partition is available, find the BNVs directly inside the
+  graph. Otherwise, sweep the network with the Frontier partition
+  method, and selectively insert BNVs. In both cases, the BNVs are put
+  into the hash table coiBnvTable.]
+
+  SideEffects []
+
+******************************************************************************/
+void 
+Part_PartitionReadOrCreateBnvs(
+  Ntk_Network_t *network,
+  st_table *coiLatchTable,
+  st_table *coiBnvTable)
+{
+  graph_t    *partition;
+  lsGen      lsgen;
+  vertex_t   *vertex;
+  long       mddId;
+  Ntk_Node_t *node;
+
+  /* if the partition is not available, sweep the network  */
+  partition = Part_NetworkReadPartition(network);
+  if (partition == NIL(graph_t)) {
+    PartInsertBnvs(network, coiLatchTable, coiBnvTable);
+    return;
+  }
+
+  /* otherwise, go through the vertices */
+  foreach_vertex(partition, lsgen, vertex) {
+    mddId = PartVertexReadMddId(vertex);
+    if (mddId == -1) continue;
+
+    node = Ntk_NetworkFindNodeByMddId(network, mddId);
+    assert(node != NIL(Ntk_Node_t));
+
+    if ( !Ntk_NodeTestIsCombInput(node) &&
+	 Ntk_NodeReadNumFanouts(node)!=0 )
+      st_insert(coiBnvTable, (char *)node, NIL(char));
+  }
+ 
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Read or create the Boolean network variables (BNVs).]
+
+  Description [Read or create the Boolean network variables. If the
+  partition is available, find the BNVs directly inside the
+  graph. Otherwise, sweep the network with the Frontier partition
+  method, and selectively insert BNVs. In both cases, the BNVs are put
+  into the hash table coiBnvTable.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Part_PartitionWithExistingBnvs(
+  Ntk_Network_t *network,
+  graph_t *partition,
+  st_table *coiBnvTable,
+  st_table *absLatchTable,
+  st_table *absBnvTable)
+{
+
+  PartPartitionWithExistingBnvs(network, partition, coiBnvTable, 
+				absLatchTable, absBnvTable);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Creates the graph representing the combinational outputs
+  as functions of the combinational inputs as well as possibly some
+  intermediate variables.]
+
+  Description [The idea behind this partition method is representing
+  the functionality of combinational outputs in terms of combinational
+  inputs as well as some intermediate variables. Using intermediate
+  variables helps in controlling size of the BDDs for the combinational
+  outputs. These intermediate variables themselves may depend on other
+  intermediate variables and priamry inputs. Ultimately, the
+  functionality is realized in terms of combinational inputs alone.
+
+  The procedure works as follows:
+
+  i) First a topological order of the nodes is computed.
+  ii) A table mapping node to mvf is initialized for combinational
+  inputs.
+  iii) The functionality of nodes is computed in topological order in
+  terms of the fanin functions.
+  iii) If the bdd size of the mvf for a node exceeds the given bdd size
+  limit (set by partition_threshold), and the node has non-zero
+  fanouts, an mdd variable corresponding to that node is created and
+  node-mvf table is updated appropriately.
+  iv) For all the nodes in the fanouts of that node, the given node is
+  treated as primary input.
+  ]
+  
+
+  SideEffects [Partition is changed.]
+
+  SeeAlso     [Part_NetworkCreatePartition PartPartitionTotal PartPartitionInputsOutputs]
+
+******************************************************************************/
+void
+PartPartitionFrontier(Ntk_Network_t *network,
+                      graph_t *partition,
+                      lsList  rootList,
+                      lsList  leaveList,
+                      mdd_t   *careSet)
+{
+  Ntk_Node_t    *node;           /* Pointer to iterate over nodes */
+  lsGen         gen;                /* To iterate over lists */
+  vertex_t      *vertex;          /* Destination of the edge being added */
+  char          *name;              /* Name of the node being processed */
+  int           mddId;              /* Id of the node being processed */
+  int           i;
+  mdd_manager   *mddManager = PartPartitionReadMddManager(partition);
+  /* nodeToMvfTable maps a node to the mvf in the form that is needed to build
+     mvfs for the fanouts of the node.  I.e., a cutpoint node is mapped to an
+     mdd for a new variable. */
+  st_table *nodeToMvfTable = st_init_table(st_ptrcmp, st_ptrhash);
+  st_table *leafNodesTable = st_init_table(st_ptrcmp, st_ptrhash);
+  st_table *topoNodeTable;
+  Ntk_Node_t *fanoutNode;
+  array_t *rootNodesArray;
+  long fanoutNumber = 0;
+  Mvf_Function_t *nodeMvf; 
+  long bddSize;
+  int sizeThreshold;
+  lsList topologicalNodeList;
+  lsGen lsgen;
+  st_generator *stgen;
+  char *flagValue =  Cmd_FlagReadByName("partition_threshold");
+
+  if (flagValue == NIL(char)){
+    sizeThreshold = 1000; /* the default value */
+  }
+  else {
+    sizeThreshold = atoi(flagValue);
+  }
+
+  /* Put combinational inputs in the leafNodesTable. */
+  if (leaveList == (lsList)0) {
+    Ntk_NetworkForEachCombInput(network, gen, node) {
+      st_insert(leafNodesTable, (char *)node, (char *) (long) (-1) );
+    }
+  } /* End of then */ 
+  else {
+    lsForEachItem(leaveList, gen, node) {
+      st_insert(leafNodesTable, (char *)node, (char *) (long) (-1) );
+    }
+  } /* End of if-then-else */
+
+  
+  /* Take the nodes in rootList as the roots */
+  if (rootList == (lsList)0) {
+    rootNodesArray = array_alloc(Ntk_Node_t *, 
+			       Ntk_NetworkReadNumCombOutputs(network));
+    i = 0;
+    Ntk_NetworkForEachCombOutput(network, gen, node) {
+      array_insert(Ntk_Node_t *, rootNodesArray, i++, node);
+    }
+
+  } /* End of then */ 
+  else {
+    rootNodesArray = array_alloc(Ntk_Node_t *, lsLength(rootList));
+    i = 0;
+    lsForEachItem(rootList, gen, node) {
+      array_insert(Ntk_Node_t *, rootNodesArray, i++, node);
+    }
+  } /* End of if-then-else */
+
+  /* Get an array of nodes sorted in topological order */
+  topologicalNodeList = Ntk_NetworkComputeTopologicalOrder(network,
+                                                           rootNodesArray,
+                                                           leafNodesTable);   
+
+  /* For each node, compute the number of its fanouts */
+  topoNodeTable = st_init_table(st_ptrcmp, st_ptrhash);
+  lsForEachItem(topologicalNodeList, lsgen, node){
+    st_insert(topoNodeTable, (char *)node, NIL(char));
+  }
+  lsForEachItem(topologicalNodeList, lsgen, node){
+    fanoutNumber = 0;
+    Ntk_NodeForEachFanout(node, i, fanoutNode) {
+      if (st_is_member(topoNodeTable, fanoutNode) &&
+	  !st_is_member(leafNodesTable, fanoutNode))
+	fanoutNumber++;
+    }
+    st_insert(topoNodeTable, node, (char *) fanoutNumber);
+  }
+
+  /* For each leaf nodes, create a vertex in the partition, create the mvf, and
+   * a mapping of name to vertex, and mddId to vertex.
+   */
+  st_foreach_item(leafNodesTable, stgen, &node, NULL) {
+    if (!st_lookup(topoNodeTable, node, &fanoutNumber)) {
+      continue;
+    }
+    mddId = Ntk_NodeReadMddId(node);
+    assert(mddId != NTK_UNASSIGNED_MDD_ID);
+    vertex = g_add_vertex(partition);
+    name  = Ntk_NodeReadName(node);
+    st_insert(PartPartitionReadNameToVertex(partition), name, vertex);
+    st_insert(PartPartitionReadMddIdToVertex(partition), (char *)(long)mddId,
+              vertex); 
+
+    if (Ntk_NodeTestIsPseudoInput(node)){
+      nodeMvf = NodeBuildPseudoInputMvf(node);
+    }
+    else {
+      nodeMvf = Mvf_FunctionCreateFromVariable(mddManager,mddId);
+    }
+
+    if (fanoutNumber <= 0) {
+      st_insert(nodeToMvfTable, (char *)node, NIL(char));
+    }else
+      st_insert(nodeToMvfTable, (char *)node, 
+		(char *)Mvf_FunctionDuplicate(nodeMvf));
+
+    vertex->user_data = (gGeneric)PartVertexInfoCreateSingle(name, nodeMvf,
+                                                             mddId);
+  }
+
+  st_free_table(leafNodesTable);
+  
+
+  fflush(vis_stdout);
+
+  /* Go through the topologicalNodeList
+   * a. If the node is of combinational input type, continue.
+   *
+   * b. Otherwise, Build the Mdd for this node, in terms of the function of the
+   *    fanin nodes in. If the Mdd size exceeds the threshold, create an Mdd ID
+   *    for this node.
+   */
+
+  lsForEachItem(topologicalNodeList, lsgen, node){
+    if (st_is_member(nodeToMvfTable, (char *)node)) continue;
+
+    nodeMvf = NodeBuildMvf2(node, nodeToMvfTable, topoNodeTable);
+    bddSize = bdd_size_multiple(nodeMvf);
+
+    if ((bddSize <= sizeThreshold) && !Ntk_NodeTestIsCombOutput(node)) {
+      st_insert(nodeToMvfTable, node, nodeMvf);
+      continue;
+    }
+
+    /* node either is a primary output, or has an mvf exceeding the
+     * threshold. 
+     */
+    st_lookup(topoNodeTable, node, &fanoutNumber);
+    if ( (bddSize > sizeThreshold) &&  fanoutNumber > 0 ) {
+      if ((mddId = Ntk_NodeReadMddId(node)) == -1){
+        Ord_NetworkAssignMddIdForNode(network, node);
+        mddId = Ntk_NodeReadMddId(node);
+      }
+      st_insert(nodeToMvfTable, node,
+                Mvf_FunctionCreateFromVariable(mddManager,mddId));
+    }else {
+      if (fanoutNumber <= 0) {
+	st_insert(nodeToMvfTable, node, NIL(char));
+      }else
+	st_insert(nodeToMvfTable, (char *)node, 
+		  (char *)Mvf_FunctionDuplicate(nodeMvf));
+    }
+
+    vertex = g_add_vertex(partition);
+    name  = Ntk_NodeReadName(node);
+    mddId = Ntk_NodeReadMddId(node);
+    st_insert(PartPartitionReadNameToVertex(partition), name, (char *)vertex);
+    vertex->user_data = (gGeneric)PartVertexInfoCreateSingle(name, nodeMvf, 
+                                                             mddId);
+    if (mddId != -1){
+      st_insert(PartPartitionReadMddIdToVertex(partition),
+                (char *)(long)mddId, (char *)vertex);
+    }
+  }/* for each member of topologicalNodeList */
+  
+
+  /* sanity check */
+  st_foreach_item(nodeToMvfTable, stgen, &node, &nodeMvf) {
+#if 0
+    if (nodeMvf != NIL(Mvf_Function_t)) {
+      int chk = st_lookup(topoNodeTable, node, &fanoutNumber);
+      Ntk_NodeForEachFanout(node, i, fanoutNode) {
+	fprintf(vis_stdout, "\nunclean node %s   =>   %s", 
+		Ntk_NodeReadName(node),
+		Ntk_NodeReadName(fanoutNode));
+	if (Ntk_NodeTestIsLatch(fanoutNode))
+	  fprintf(vis_stdout, "\t(latch)");
+      }
+    }
+#else
+    assert (nodeMvf == NIL(Mvf_Function_t)) ;
+#endif
+  }
+
+  PartitionCreateEdges(partition);
+  array_free(rootNodesArray);
+  st_free_table(nodeToMvfTable);
+  st_free_table(topoNodeTable);
+  lsDestroy(topologicalNodeList, (void (*)(lsGeneric))0);
+}
+
+#if 0
+void
+PartPartitionFrontierOld(Ntk_Network_t *network,
+                      graph_t *partition,
+                      lsList  rootList,
+                      lsList  leaveList,
+                      mdd_t   *careSet)
+{
+  Ntk_Node_t    *node;           /* Pointer to iterate over nodes */
+  lsGen         gen;                /* To iterate over lists */
+  vertex_t      *vertex;          /* Destination of the edge being added */
+  char          *name;              /* Name of the node being processed */
+  int           mddId;              /* Id of the node being processed */
+  int           i;
+  mdd_manager   *mddManager = PartPartitionReadMddManager(partition);
+  /* nodeToMvfTable maps a node to the mvf in the form that is needed to build
+     mvfs for the fanouts of the node.  I.e., a cutpoint node is mapped to an
+     mdd for a new variable. */
+  st_table *nodeToMvfTable = st_init_table(st_ptrcmp, st_ptrhash);
+  st_table *leafNodesTable = st_init_table(st_ptrcmp, st_ptrhash);
+  array_t *rootNodesArray;
+  Mvf_Function_t *nodeMvf; 
+  long bddSize;
+  int sizeThreshold;
+  lsList topologicalNodeList;
+  lsGen lsgen;
+  st_generator *stgen;
+  char *flagValue =  Cmd_FlagReadByName("partition_threshold");
+  if (flagValue == NIL(char)){
+    sizeThreshold = 1000; /* the default value */
+  }
+  else {
+    sizeThreshold = atoi(flagValue);
+  }
+
+  /* Put combinational inputs in the leafNodesTable. */
+  if (leaveList == (lsList)0) {
+    Ntk_NetworkForEachCombInput(network, gen, node) {
+      st_insert(leafNodesTable, (char *)node, (char *) (long) (-1) );
+    }
+  } /* End of then */ 
+  else {
+    lsForEachItem(leaveList, gen, node) {
+      st_insert(leafNodesTable, (char *)node, (char *) (long) (-1) );
+    }
+  } /* End of if-then-else */
+
+  /*
+   * For each leaf nodes, create a vertex in the partition, create the mvf, and
+   * a mapping of name to vertex, and mddId to vertex.
+   */
+  st_foreach_item(leafNodesTable, stgen, &node, NULL){
+    mddId = Ntk_NodeReadMddId(node);
+    assert(mddId != NTK_UNASSIGNED_MDD_ID);
+    vertex = g_add_vertex(partition);
+    name  = Ntk_NodeReadName(node);
+    st_insert(PartPartitionReadNameToVertex(partition), name, (char *)vertex);
+    st_insert(PartPartitionReadMddIdToVertex(partition), (char *)(long)mddId,
+              (char *)vertex); 
+    if (Ntk_NodeTestIsPseudoInput(node)){
+      nodeMvf = NodeBuildPseudoInputMvf(node);
+    }
+    else {
+      nodeMvf = Mvf_FunctionCreateFromVariable(mddManager,mddId);
+    }
+    st_insert(nodeToMvfTable, (char *)node, (char *)nodeMvf);
+    vertex->user_data = (gGeneric)PartVertexInfoCreateSingle(name, nodeMvf,
+                                                             mddId);
+  }
+
+  
+  /* Take the nodes in rootList as the roots */
+  if (rootList == (lsList)0) {
+    rootNodesArray = array_alloc(Ntk_Node_t *, 
+			       Ntk_NetworkReadNumCombOutputs(network));
+    i = 0;
+    Ntk_NetworkForEachCombOutput(network, gen, node) {
+      array_insert(Ntk_Node_t *, rootNodesArray, i++, node);
+    }
+  } /* End of then */ 
+  else {
+    rootNodesArray = array_alloc(Ntk_Node_t *, lsLength(rootList));
+    i = 0;
+    lsForEachItem(rootList, gen, node) {
+      array_insert(Ntk_Node_t *, rootNodesArray, i++, node);
+    }
+  } /* End of if-then-else */
+
+  
+
+  /* Get an array of nodes sorted in topological order */
+  topologicalNodeList = Ntk_NetworkComputeTopologicalOrder(network,
+                                                           rootNodesArray,
+                                                           leafNodesTable);   
+  
+  st_free_table(leafNodesTable);
+  
+
+  /* Go through the topologicalNodeList
+   * a. If the node is of combinational input type, continue.
+   *
+   * b. Otherwise, Build the Mdd for this node, in terms of the function of the
+   *    fanin nodes in. If the Mdd size exceeds the threshold, create an Mdd ID
+   *    for this node.
+   */
+
+  lsForEachItem(topologicalNodeList, lsgen, node){
+    if (st_is_member(nodeToMvfTable, (char *)node)) continue;
+    nodeMvf = NodeBuildMvf(node, nodeToMvfTable);
+    bddSize = bdd_size_multiple(nodeMvf);
+    if ((bddSize <= sizeThreshold) &&
+        (Ntk_NodeTestIsCombOutput(node) == 0)){
+      st_insert(nodeToMvfTable, (char *)node, (char *)nodeMvf);
+      continue;
+    }
+    /* node either is a primary output, or has an mvf exceeding the
+       threshold. */
+    vertex = g_add_vertex(partition);
+    name  = Ntk_NodeReadName(node);
+    st_insert(PartPartitionReadNameToVertex(partition), name,
+              (char *)vertex);
+    if ((bddSize > sizeThreshold) &&
+        (Ntk_NodeReadNumFanouts(node) != 0)){
+      if ((mddId = Ntk_NodeReadMddId(node)) == -1){
+        Ord_NetworkAssignMddIdForNode(network, node);
+        mddId = Ntk_NodeReadMddId(node);
+      }
+      st_insert(nodeToMvfTable, (char *)node,
+                (char *)Mvf_FunctionCreateFromVariable(mddManager,mddId));
+    }
+    else {
+      /* Small mvf, or no fanout */
+      st_insert(nodeToMvfTable, (char *)node, (char *)nodeMvf);
+    }
+    mddId = Ntk_NodeReadMddId(node);
+    vertex->user_data = (gGeneric)PartVertexInfoCreateSingle(name,
+                                                             nodeMvf, 
+                                                             mddId);
+    if (mddId != -1){
+      st_insert(PartPartitionReadMddIdToVertex(partition),
+                (char *)(long)mddId, (char *)vertex);
+    }
+  }/* for each member of topologicalNodeList */
+  
+  /*
+   * Free the Mvfs in nodeToMvfTable not associated with vertices in the
+   * partition.  The mvfs of inputs are always in the partition; hence,
+   * their mvfs should always be preserved.  For outputs, we have to free
+   * the mvf in nodeToMvfTable if the output is also a cutpoint, because in
+   * this case the mvf in the partition vertex and the one in the
+   * nodeToMvfTable are different.
+   */
+
+  lsForEachItem(topologicalNodeList, gen, node){ 
+    if (!Ntk_NodeTestIsCombInput(node)){
+      if(!Ntk_NodeTestIsCombOutput(node)){ 
+	st_lookup(nodeToMvfTable, node, &nodeMvf); 
+	assert(nodeMvf != NIL(Mvf_Function_t)); 
+	Mvf_FunctionFree(nodeMvf);
+      } else {
+	Mvf_Function_t *vertexMvf;
+	
+	name =  Ntk_NodeReadName(node);
+	vertex = Part_PartitionFindVertexByName(partition, name);
+	st_lookup(nodeToMvfTable, node, &nodeMvf);
+	vertexMvf = PartVertexReadFunction(vertex);
+	assert(nodeMvf != NIL(Mvf_Function_t) &&
+	       vertexMvf != NIL(Mvf_Function_t));
+	if(vertexMvf != nodeMvf){
+	  Mvf_FunctionFree(nodeMvf);
+	}
+      }
+    }/* not input */
+  }/* for each node */
+
+  PartitionCreateEdges(partition);
+  array_free(rootNodesArray);
+  st_free_table(nodeToMvfTable);
+  lsDestroy(topologicalNodeList, (void (*)(lsGeneric))0);
+}
+#endif
+
+/**Function********************************************************************
+
+  Synopsis [Creates the graph representing the combinational outputs
+  as functions of the combinational inputs as well as possibly some
+  intermediate variables.]
+
+  Description [The same as PartPartitionFrontier, but only add vertices for
+  nodes that are not in partition. This function can be used to update the 
+  partition after more network nodes are added.]
+  
+  SideEffects [Partition is changed.]
+
+  SeeAlso     [PartPartitionFrontier]
+
+******************************************************************************/
+void
+PartUpdateFrontier(Ntk_Network_t *network,
+		   graph_t *partition,
+		   lsList  rootList,
+		   lsList  leaveList,
+		   mdd_t   *careSet)
+{
+  Ntk_Node_t    *node;           /* Pointer to iterate over nodes */
+  lsGen         gen;                /* To iterate over lists */
+  vertex_t      *vertex;          /* Destination of the edge being added */
+  char          *name;              /* Name of the node being processed */
+  int           mddId;              /* Id of the node being processed */
+  int           i, flag;
+  mdd_manager   *mddManager = PartPartitionReadMddManager(partition);
+  /* nodeToMvfTable maps a node to the mvf in the form that is needed to build
+     mvfs for the fanouts of the node.  I.e., a cutpoint node is mapped to an
+     mdd for a new variable. */
+  st_table *nodeToMvfTable = st_init_table(st_ptrcmp, st_ptrhash);
+  st_table *leafNodesTable = st_init_table(st_ptrcmp, st_ptrhash);
+  array_t *rootNodesArray;
+  Mvf_Function_t *nodeMvf; 
+  long bddSize;
+  int sizeThreshold;
+  lsList topologicalNodeList;
+  lsGen lsgen;
+  st_generator *stgen;
+  char *flagValue =  Cmd_FlagReadByName("partition_threshold");
+  
+  if (flagValue == NIL(char)){
+    sizeThreshold = 1000; /* the default value */
+  }
+  else {
+    sizeThreshold = atoi(flagValue);
+  }
+
+  /* Put combinational inputs in the leafNodesTable. */
+  if (leaveList == (lsList)0) {
+    Ntk_NetworkForEachCombInput(network, gen, node) {
+      st_insert(leafNodesTable, (char *)node, (char *) (long) (-1) );
+    }
+  } /* End of then */ 
+  else {
+    lsForEachItem(leaveList, gen, node) {
+      st_insert(leafNodesTable, (char *)node, (char *) (long) (-1) );
+    }
+  } /* End of if-then-else */
+
+  /*
+   * For each leaf nodes, create a vertex in the partition, create the mvf, and
+   * a mapping of name to vertex, and mddId to vertex.
+   * Notices that: if a vertex exists in the partition, use it instead of 
+   * creating a new one.
+   */
+  st_foreach_item(leafNodesTable, stgen, &node, NULL){
+    mddId = Ntk_NodeReadMddId(node);
+    name  = Ntk_NodeReadName(node);
+    assert(mddId != NTK_UNASSIGNED_MDD_ID);
+    flag = st_lookup(PartPartitionReadNameToVertex(partition), 
+		     name, &vertex);
+    if (flag) {
+      nodeMvf = ((PartVertexInfo_t *)(vertex->user_data))->functionality.mvf;
+      st_insert(nodeToMvfTable, node, nodeMvf);
+      /*
+      name = Ntk_NodeReadName(node);
+      fprintf(vis_stdout, "warning: node %s already in the partition\n",
+	      name);
+      */
+    }else {
+      vertex = g_add_vertex(partition);
+      st_insert(PartPartitionReadNameToVertex(partition), name, (char *)vertex);
+      st_insert(PartPartitionReadMddIdToVertex(partition), (char *)(long)mddId,
+		(char *)vertex); 
+      if (Ntk_NodeTestIsPseudoInput(node)){
+	nodeMvf = NodeBuildPseudoInputMvf(node);
+      }else {
+	nodeMvf = Mvf_FunctionCreateFromVariable(mddManager,mddId);
+      }
+      st_insert(nodeToMvfTable, (char *)node, (char *)nodeMvf);
+      vertex->user_data = (gGeneric)PartVertexInfoCreateSingle(name, nodeMvf,
+							       mddId);
+    }
+  }
+  
+  /* Take the nodes in rootList as the roots */
+  if (rootList == (lsList)0) {
+    rootNodesArray = array_alloc(Ntk_Node_t *, 
+			       Ntk_NetworkReadNumCombOutputs(network));
+    i = 0;
+    Ntk_NetworkForEachCombOutput(network, gen, node) {
+      name = Ntk_NodeReadName(node);
+      if ( !st_is_member(PartPartitionReadNameToVertex(partition), name) )
+	array_insert(Ntk_Node_t *, rootNodesArray, i++, node);
+    }
+  } /* End of then */ 
+  else {
+    rootNodesArray = array_alloc(Ntk_Node_t *, lsLength(rootList));
+    i = 0;
+    lsForEachItem(rootList, gen, node) {
+      name = Ntk_NodeReadName(node);
+      if ( !st_is_member(PartPartitionReadNameToVertex(partition), name) )
+	array_insert(Ntk_Node_t *, rootNodesArray, i++, node);
+    }
+  } /* End of if-then-else */
+
+  
+
+  /* Get an array of nodes sorted in topological order */
+  topologicalNodeList = Ntk_NetworkComputeTopologicalOrder(network,
+                                                           rootNodesArray,
+                                                           leafNodesTable);   
+  
+  st_free_table(leafNodesTable);
+  
+
+  /* Go through the topologicalNodeList
+   * a. If the node is of combinational input type, continue.
+   *
+   * b. Otherwise, Build the Mdd for this node, in terms of the function of the
+   *    fanin nodes in. If the Mdd size exceeds the threshold, create an Mdd ID
+   *    for this node.
+   */
+
+  lsForEachItem(topologicalNodeList, lsgen, node){
+    if (st_is_member(nodeToMvfTable, node)) continue;
+    name = Ntk_NodeReadName(node);
+    flag = st_lookup(PartPartitionReadNameToVertex(partition), 
+		     name, &vertex);
+    if (flag) {
+      mddId = Ntk_NodeReadMddId(node);
+      if (mddId != -1)
+	st_insert(nodeToMvfTable, node,
+		  (char *)Mvf_FunctionCreateFromVariable(mddManager,mddId));
+      else {
+	nodeMvf = PartVertexReadFunction(vertex);
+	st_insert(nodeToMvfTable, node, nodeMvf);
+      }
+      continue;
+    }
+    nodeMvf = NodeBuildMvf(node, nodeToMvfTable);
+    bddSize = bdd_size_multiple(nodeMvf);
+    if ((bddSize <= sizeThreshold) &&
+        (Ntk_NodeTestIsCombOutput(node) == 0)){
+      st_insert(nodeToMvfTable, (char *)node, (char *)nodeMvf);
+      continue;
+    }
+    /* node either is a primary output, or has an mvf exceeding the
+       threshold. */
+    vertex = g_add_vertex(partition);
+    name  = Ntk_NodeReadName(node);
+    st_insert(PartPartitionReadNameToVertex(partition), name,
+              (char *)vertex);
+    if ((bddSize > sizeThreshold) &&
+        (Ntk_NodeReadNumFanouts(node) != 0)){
+      if ((mddId = Ntk_NodeReadMddId(node)) == -1){
+        Ord_NetworkAssignMddIdForNode(network, node);
+        mddId = Ntk_NodeReadMddId(node);
+      }
+      st_insert(nodeToMvfTable, (char *)node,
+                (char *)Mvf_FunctionCreateFromVariable(mddManager,mddId));
+    }
+    else {
+      /* Small mvf, or no fanout */
+      st_insert(nodeToMvfTable, (char *)node, (char *)nodeMvf);
+    }
+    mddId = Ntk_NodeReadMddId(node);
+    vertex->user_data = (gGeneric)PartVertexInfoCreateSingle(name,
+                                                             nodeMvf, 
+                                                             mddId);
+    if (mddId != -1){
+      st_insert(PartPartitionReadMddIdToVertex(partition),
+                (char *)(long)mddId, (char *)vertex);
+    }
+  }/* for each member of topologicalNodeList */
+  
+  /*
+   * Free the Mvfs in nodeToMvfTable not associated with vertices in the
+   * partition.  The mvfs of inputs are always in the partition; hence,
+   * their mvfs should always be preserved.  For outputs, we have to free
+   * the mvf in nodeToMvfTable if the output is also a cutpoint, because in
+   * this case the mvf in the partition vertex and the one in the
+   * nodeToMvfTable are different.
+   */
+
+  lsForEachItem(topologicalNodeList, gen, node){ 
+    if (!Ntk_NodeTestIsCombInput(node)){
+      if(!Ntk_NodeTestIsCombOutput(node)){ 
+	st_lookup(nodeToMvfTable, node, &nodeMvf); 
+	assert(nodeMvf != NIL(Mvf_Function_t)); 
+	Mvf_FunctionFree(nodeMvf);
+      } else {
+	Mvf_Function_t *vertexMvf;
+	
+	name =  Ntk_NodeReadName(node);
+	vertex = Part_PartitionFindVertexByName(partition, name);
+	st_lookup(nodeToMvfTable, node, &nodeMvf);
+	vertexMvf = PartVertexReadFunction(vertex);
+	assert(nodeMvf != NIL(Mvf_Function_t) &&
+	       vertexMvf != NIL(Mvf_Function_t));
+	if(vertexMvf != nodeMvf){
+	  Mvf_FunctionFree(nodeMvf);
+	}
+      }
+    }/* not input */
+  }/* for each node */
+
+  PartitionCreateEdges(partition);
+  array_free(rootNodesArray);
+  st_free_table(nodeToMvfTable);
+  lsDestroy(topologicalNodeList, (void (*)(lsGeneric))0);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Selectively insert Boolean network variables.]
+
+  Description [Selectively insert Boolean network varibles using the
+  Frontier partition method---every time the BDD size exceeds the
+  partition threshold, a boolean network variable is inserted.
+
+  The added boolean network variables are inserted into the coiBnvTable. ]
+  
+
+  SideEffects []
+
+  SeeAlso     [PartPartitionFrontier]
+
+******************************************************************************/
+void
+PartInsertBnvs(
+  Ntk_Network_t *network,
+  st_table *coiLatchTable,
+  st_table *coiBnvTable)
+{
+  mdd_manager    *mddManager = Ntk_NetworkReadMddManager(network);
+  st_table       *nodeToMvfTable = st_init_table(st_ptrcmp, st_ptrhash);
+  st_table       *leafNodesTable = st_init_table(st_ptrcmp, st_ptrhash);
+  lsList         topologicalNodeList;
+  st_table       *topoNodeTable;
+  array_t        *rootNodesArray;
+  Ntk_Node_t     *fanoutNode, *node;
+  Mvf_Function_t *nodeMvf; 
+  long           bddSize, sizeThreshold, fanoutNumber, mddId;
+  int            i;
+  lsGen          lsgen;
+  st_generator   *stgen;
+  char           *flagValue;
+
+  flagValue =  Cmd_FlagReadByName("partition_threshold");
+  if (flagValue == NIL(char)){
+    sizeThreshold = 1000; /* the default value */
+  }
+  else {
+    sizeThreshold = atoi(flagValue);
+  }
+
+  /* Put latch data inputs in the rootNodesArray */
+  rootNodesArray = array_alloc(Ntk_Node_t *, 0);
+  st_foreach_item(coiLatchTable, stgen, &node, NULL) {
+    array_insert_last(Ntk_Node_t *, rootNodesArray, 
+		      Ntk_LatchReadDataInput(node));
+    array_insert_last(Ntk_Node_t *, rootNodesArray, 
+    		      Ntk_LatchReadInitialInput(node));
+  }
+
+  /* Put combinational inputs, as well as the existing coiBnvs, in the
+   * leafNodesTable. */
+  Ntk_NetworkForEachCombInput(network, lsgen, node) {
+    st_insert(leafNodesTable, node, (char *) (long) (-1) );
+  }
+  st_foreach_item(coiBnvTable, stgen, &node, NULL) {
+    st_insert(leafNodesTable, node, (char *) (long) (-1) );
+  }
+  
+  /* Get an array of nodes sorted in topological order */
+  topologicalNodeList = Ntk_NetworkComputeTopologicalOrder(network,
+                                                           rootNodesArray,
+                                                           leafNodesTable);   
+
+  /* For each node, compute the number of fanouts */
+  topoNodeTable = st_init_table(st_ptrcmp, st_ptrhash);
+  lsForEachItem(topologicalNodeList, lsgen, node){
+    st_insert(topoNodeTable, (char *)node, NIL(char));
+  }
+  lsForEachItem(topologicalNodeList, lsgen, node){
+    fanoutNumber = 0;
+    Ntk_NodeForEachFanout(node, i, fanoutNode) {
+      if (st_is_member(topoNodeTable, (char *)fanoutNode) &&
+	  !st_is_member(leafNodesTable, (char *)fanoutNode) )
+	fanoutNumber++;
+    }
+    st_insert(topoNodeTable, (char *)node, (char *)fanoutNumber);
+  }
+
+  /* assign mddIds to latches if necessary */
+  /* chao: this may be too slow! */
+  /* chao: this order may not be as good as static_order */
+  lsForEachItem(topologicalNodeList, lsgen, node){
+    if (Ntk_NodeTestIsInput(node)) {
+      Ord_NetworkAssignMddIdForNode(network, node);
+    }else if (Ntk_NodeTestIsLatch(node)) {
+      Ord_NetworkAssignMddIdForNode(network, node);
+      Ord_NetworkAssignMddIdForNode(network, Ntk_NodeReadShadow(node));
+    }
+  }
+  st_foreach_item(coiLatchTable, stgen, &node, NULL) {
+    Ord_NetworkAssignMddIdForNode(network, node);
+    Ord_NetworkAssignMddIdForNode(network, Ntk_NodeReadShadow(node));
+  }
+
+  /* create nodeMvf for leaf nodes */
+  st_foreach_item(leafNodesTable, stgen, &node, NULL) {
+    if (!st_lookup(topoNodeTable, node, &fanoutNumber)) {
+      continue;
+    }
+    mddId = Ntk_NodeReadMddId(node);
+    assert(mddId != NTK_UNASSIGNED_MDD_ID);
+
+    if (Ntk_NodeTestIsPseudoInput(node)){
+      nodeMvf = NodeBuildPseudoInputMvf(node);
+    }
+    else {
+      nodeMvf = Mvf_FunctionCreateFromVariable(mddManager,mddId);
+    }
+
+    if (fanoutNumber <= 0) {
+      Mvf_FunctionFree(nodeMvf);
+      st_insert(nodeToMvfTable, (char *)node, NIL(char));
+    }
+    else
+      st_insert(nodeToMvfTable, (char *)node, (char *)nodeMvf);
+  }
+
+  st_free_table(leafNodesTable);
+
+
+  /* Go through the topologicalNodeList
+   * a. If the node is of combinational input type, continue.
+   *
+   * b. Otherwise, Build the Mdd for this node, in terms of the function of the
+   *    fanin nodes in. If the Mdd size exceeds the threshold, create an Mdd ID
+   *    for this node.
+   */
+  lsForEachItem(topologicalNodeList, lsgen, node){
+    if (st_is_member(nodeToMvfTable, node)) 
+      continue;
+
+    nodeMvf = NodeBuildMvf2(node, nodeToMvfTable, topoNodeTable);
+    bddSize = bdd_size_multiple(nodeMvf);
+    st_lookup(topoNodeTable, node, &fanoutNumber);
+
+    if ((bddSize <= sizeThreshold) && !Ntk_NodeTestIsCombOutput(node)) {
+      assert(fanoutNumber > 0);
+      st_insert(nodeToMvfTable, node, nodeMvf);
+      continue;
+    }
+    /* node either is a primary output, or has an mvf exceeding the
+       threshold. */
+    if ((bddSize > sizeThreshold) && fanoutNumber > 0) {
+                                   /*(Ntk_NodeReadNumFanouts(node) != 0)) { */
+      /* ADD A bnv !!! */
+      st_insert(coiBnvTable, (char *)node, NIL(char));
+
+      if ((mddId = Ntk_NodeReadMddId(node)) == -1){
+        Ord_NetworkAssignMddIdForNode(network, node);
+        mddId = Ntk_NodeReadMddId(node);
+      }
+
+      st_insert(nodeToMvfTable, (char *)node,
+                (char *)Mvf_FunctionCreateFromVariable(mddManager,mddId));
+      Mvf_FunctionFree(nodeMvf);
+    }else {
+      if (fanoutNumber <= 0) {
+	Mvf_FunctionFree(nodeMvf);
+	st_insert(nodeToMvfTable, node, NIL(char));
+      }
+      else
+	st_insert(nodeToMvfTable, node, (char *)nodeMvf);
+    }
+
+  }/* for each member of topologicalNodeList */
+  
+  /* sanity check */
+  st_foreach_item(nodeToMvfTable, stgen, &node, &nodeMvf) {
+#if 0
+    if (nodeMvf != NIL(Mvf_Function_t)) {
+      st_lookup(topoNodeTable, node, &fanoutNumber);
+      fprintf(vis_stdout, "\nunclean node = %s, fanout# = %d",
+	      Ntk_NodeReadName(node), fanoutNumber);
+    }
+#else
+    assert (nodeMvf == NIL(Mvf_Function_t));
+#endif
+  }
+
+  array_free(rootNodesArray);
+  st_free_table(nodeToMvfTable);
+  st_free_table(topoNodeTable);
+  lsDestroy(topologicalNodeList, (void (*)(lsGeneric))0);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Update the partition with the given set of internal nodes.]
+
+  Description [Update the partition with the given set of internal
+  nodes. Insert intermediate variables, or Boolean Network Variables
+  (BNVs) only for the given set of internal nodes
+  (coiBnvTable). Intermediate variables (or Bnvs) that do not appear
+  in absBnvTable will not be included in the partition---they will be
+  treated as inputs.]
+
+  SideEffects []
+
+  SeeAlso     [PartPartitionFrontier PartPartitionInsertBnvs]
+
+******************************************************************************/
+void
+PartPartitionWithExistingBnvs(
+  Ntk_Network_t *network,
+  graph_t *partition,
+  st_table *coiBnvTable,
+  st_table *absLatchTable,
+  st_table *absBnvTable)
+{
+  mdd_manager    *mddManager = PartPartitionReadMddManager(partition);
+  st_table       *nodeToMvfTable = st_init_table(st_ptrcmp, st_ptrhash);
+  st_table       *leafNodesTable = st_init_table(st_ptrcmp, st_ptrhash);
+  array_t        *rootNodesArray, *combNodesArray;
+  lsList         topologicalNodeList;
+  st_table       *topoNodeTable;
+  Ntk_Node_t     *fanoutNode, *node;
+  Mvf_Function_t *nodeMvf; 
+  vertex_t       *vertex;         
+  long           mddId, fanoutNumber;
+  char           *name;           
+  lsGen          lsgen;
+  st_generator   *stgen;
+  int            i;
+
+  /* Put latch data inputs in the rootNodesArray */
+  rootNodesArray = array_alloc(Ntk_Node_t *, 0);
+  st_foreach_item(absLatchTable, stgen, &node, NULL) {
+    array_insert_last(Ntk_Node_t *, rootNodesArray, 
+		      Ntk_LatchReadDataInput(node));
+    array_insert_last(Ntk_Node_t *, rootNodesArray, 
+    		      Ntk_LatchReadInitialInput(node));
+  }
+
+  /* Put also latch initial inputs in the rootNodesArray */
+  combNodesArray = Ntk_NodeComputeTransitiveFaninNodes(network,
+						       rootNodesArray,
+						       TRUE, TRUE);
+  arrayForEachItem(Ntk_Node_t *, combNodesArray, i, node) {
+    if ( Ntk_NodeTestIsLatch(node) && 
+	 !st_is_member(absLatchTable, (char *)node) )
+      array_insert_last(Ntk_Node_t *, rootNodesArray, 
+			Ntk_LatchReadInitialInput(node));
+  }
+  array_free(combNodesArray);
+
+
+  /* Put combinational inputs in the leafNodesTable. */
+  Ntk_NetworkForEachCombInput(network, lsgen, node) {
+    st_insert(leafNodesTable, (char *)node, (char *) (long) (-1) );
+  }
+  /* Put BNVs that are not in absBnvTable in the leafNodesTable */
+  st_foreach_item(coiBnvTable, stgen, &node, NULL) {
+    if (!st_is_member(absBnvTable, (char *)node))
+      st_insert(leafNodesTable, node, (char *) (long) (-1) );
+  }
+
+  /* Get an array of nodes sorted in topological order  */
+  topologicalNodeList = Ntk_NetworkComputeTopologicalOrder(network,
+                                                           rootNodesArray,
+                                                           leafNodesTable);
+
+  /* For each node, compute the number of fanouts */
+  topoNodeTable = st_init_table(st_ptrcmp, st_ptrhash);
+  lsForEachItem(topologicalNodeList, lsgen, node){
+    st_insert(topoNodeTable, (char *)node, NIL(char));
+  }
+  lsForEachItem(topologicalNodeList, lsgen, node){
+    fanoutNumber = 0;
+    Ntk_NodeForEachFanout(node, i, fanoutNode) {
+      if (st_is_member(topoNodeTable, (char *)fanoutNode) &&
+	  !st_is_member(leafNodesTable, (char *)fanoutNode))
+	fanoutNumber++;
+    }
+    st_insert(topoNodeTable, (char *)node, (char *)fanoutNumber);
+   }
+
+  /* Create partition vertices for the leaves 
+   */
+  st_foreach_item(leafNodesTable, stgen, &node, NULL){
+    if (!st_lookup(topoNodeTable, node, &fanoutNumber))
+      continue;
+    mddId = Ntk_NodeReadMddId(node);
+    if (mddId == NTK_UNASSIGNED_MDD_ID) {
+	/* it is a input sign under the fanin cone of the initialInput
+         * of some invisible latches */
+	assert(Ntk_NodeTestIsInput(node));
+	Ord_NetworkAssignMddIdForNode(network, node);
+	mddId = Ntk_NodeReadMddId(node);
+    }
+    /*assert(mddId != NTK_UNASSIGNED_MDD_ID);*/
+    vertex = g_add_vertex(partition);
+    name  = Ntk_NodeReadName(node);
+    st_insert(PartPartitionReadNameToVertex(partition), name, (char *)vertex);
+    st_insert(PartPartitionReadMddIdToVertex(partition), (char *)(long)mddId,
+              (char *)vertex); 
+    if (Ntk_NodeTestIsPseudoInput(node)){
+      nodeMvf = NodeBuildPseudoInputMvf(node);
+    }
+    else {
+      nodeMvf = Mvf_FunctionCreateFromVariable(mddManager,mddId);
+    }
+
+    if (fanoutNumber <= 0) 
+      st_insert(nodeToMvfTable, (char *)node, NIL(char));
+    else
+      st_insert(nodeToMvfTable, (char *)node, 
+		(char *)Mvf_FunctionDuplicate(nodeMvf));
+
+    vertex->user_data = (gGeneric)PartVertexInfoCreateSingle(name, nodeMvf,
+                                                             mddId);
+  }
+
+  /* Go through the topologicalNodeList, and build Mdds for nodes in
+   * the absBnvTable
+   */
+  lsForEachItem(topologicalNodeList, lsgen, node){
+    if (st_is_member(nodeToMvfTable, (char *)node)) continue;
+
+    nodeMvf = NodeBuildMvf2(node, nodeToMvfTable, topoNodeTable);
+
+    if ( !st_is_member(absBnvTable,(char *)node) && 
+	 !Ntk_NodeTestIsCombOutput(node)) {
+      st_insert(nodeToMvfTable, (char *)node, (char *)nodeMvf);
+      continue;  
+    }
+    
+    /* node is either a primary output, or a boolean network var */
+    vertex = g_add_vertex(partition);
+    name  = Ntk_NodeReadName(node);
+    st_insert(PartPartitionReadNameToVertex(partition), name, (char *)vertex);
+
+    if (st_is_member(absBnvTable,node)) {
+      /* ADD a bnv !!! */
+      mddId = Ntk_NodeReadMddId(node);
+      assert(mddId != -1);
+      st_insert(nodeToMvfTable, node,
+                (char *)Mvf_FunctionCreateFromVariable(mddManager,mddId));
+    }else {
+      st_lookup(topoNodeTable, node, &fanoutNumber);
+      if (fanoutNumber <= 0) 
+	st_insert(nodeToMvfTable, node, NIL(char));
+      else
+	st_insert(nodeToMvfTable, node, 
+		  (char *)Mvf_FunctionDuplicate(nodeMvf));
+    }
+
+    mddId = Ntk_NodeReadMddId(node);
+    vertex->user_data = (gGeneric)PartVertexInfoCreateSingle(name, nodeMvf, 
+                                                             mddId);
+    if (mddId != -1){
+      st_insert(PartPartitionReadMddIdToVertex(partition),
+                (char *)(long)mddId, (char *)vertex);
+    }
+  }/* for each member of topologicalNodeList */
+
+  /* sanity check */
+  st_foreach_item(nodeToMvfTable, stgen, &node, &nodeMvf) {
+#if 1
+    if (nodeMvf != NIL(Mvf_Function_t)) {
+      st_lookup(topoNodeTable, node, &fanoutNumber);
+      fprintf(vis_stdout, "\nunclean node = %s, fanout# = %ld",
+	      Ntk_NodeReadName(node), fanoutNumber);
+    }
+#else
+    assert(nodeMvf == NIL(Mvf_Function_t));
+#endif
+  }
+
+  PartitionCreateEdges(partition);
+  array_free(rootNodesArray);
+  st_free_table(nodeToMvfTable);
+  st_free_table(topoNodeTable);
+  st_free_table(leafNodesTable);
+  lsDestroy(topologicalNodeList, (void (*)(lsGeneric))0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the integers from a symbol table.]
+
+  Description [Prints the integers from a symbol table.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+PartPrintPartition(graph_t *partition)
+{
+  vertex_t *vertex;
+  lsList vertexList = g_get_vertices(partition);
+  lsGen gen;
+  st_table *vertexTable = st_init_table(st_ptrcmp, st_ptrhash);
+  fprintf(vis_stdout,"******* Printing Partition *********\n");
+  lsForEachItem(vertexList, gen, vertex){
+    PrintPartitionRecursively(vertex,vertexTable,0);
+  }
+  fprintf(vis_stdout,"******* End Printing Partition *********\n");
+  st_free_table(vertexTable);
+}
+
+  
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Creates edges in the graph corresponding to a partition.]
+
+  Description [Creates edges in the graph corresponding to a
+  partition. An edge exists between node i and node j, if node j is in
+  the support of functionality of node i.]
+
+  SideEffects [Partition is changed.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+PartitionCreateEdges(graph_t *partition)
+{
+  lsList vertexList;
+  lsGen gen;
+  vertex_t *toVertex;
+  edge_t *edge;
+
+  /* this will be executed only when used inside PartitionUpdateFrontier */
+  foreach_edge(partition, gen, edge) {
+    g_delete_edge(edge, (void(*)(gGeneric))0);
+  }
+
+  vertexList = g_get_vertices(partition);
+
+  lsForEachItem(vertexList, gen, toVertex) {
+    st_table     *mddSupport; /* To store the support of the Mvf_Function */
+    st_generator *stGen;      /* To iterate over the MddIds of the support */
+    vertex_t     *fromVertex; /* Will hold the current vertex in the support */
+    Mvf_Function_t *mddFunction;
+    long          mddId;
+    
+    mddFunction = PartVertexReadFunction(toVertex);
+    mddSupport = PartCreateFunctionSupportTable(mddFunction);
+    st_foreach_item(mddSupport, stGen, &mddId, NULL) {
+      st_lookup(PartPartitionReadMddIdToVertex(partition), (char *) mddId,
+		&fromVertex);  
+      /* 
+       * Add the edge to the graph. Make sure a self loop is not added. The
+       * self loop may be produced by a mdd that has in its support the same
+       * variables that represent the mddId of the node.
+       */
+      if (fromVertex != toVertex) {
+        g_add_edge(fromVertex, toVertex);
+      }
+    }
+    st_free_table(mddSupport);
+  } 
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Builds the functionality of a node, given the
+  functionality of its fanins.]
+
+  Description [The nodeToMvfTable must contain the functionality of
+  all the fanins of the node.]
+
+  SideEffects [none.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static Mvf_Function_t *
+NodeBuildMvf(Ntk_Node_t * node, st_table * nodeToMvfTable)
+{
+  int i;
+  Mvf_Function_t *resultMvf;
+  Ntk_Node_t *faninNode;
+  array_t *faninMvfs = array_alloc(Mvf_Function_t *,
+                                            Ntk_NodeReadNumFanins(node));
+  mdd_manager *mddMgr = Ntk_NetworkReadMddManager(Ntk_NodeReadNetwork(node)); 
+  int columnIndex = Ntk_NodeReadOutputIndex(node);
+  Tbl_Table_t *table = Ntk_NodeReadTable(node);
+  
+  Ntk_NodeForEachFanin(node, i, faninNode) {
+    Mvf_Function_t *tmpMvf;
+    st_lookup(nodeToMvfTable, faninNode, &tmpMvf); 
+    assert(tmpMvf);
+    array_insert(Mvf_Function_t *, faninMvfs, i, tmpMvf);
+  }
+  
+  resultMvf = Tbl_TableBuildMvfFromFanins(table, columnIndex,
+                                          faninMvfs, mddMgr);    
+  
+  /* Don't free the MVFs themselves, but just free the array. */
+  array_free(faninMvfs);
+  return resultMvf;
+}
+    
+/**Function********************************************************************
+
+  Synopsis    [Builds the functionality of a node, given the
+  functionality of its fanins.]
+
+  Description [The nodeToMvfTable must contain the functionality of
+  all the fanins of the node. When the faninNumber counter is
+  decreased to 0, free the corresponding MVF in the nodeToMvfTable.]
+
+  SideEffects [none.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static Mvf_Function_t *
+NodeBuildMvf2(
+  Ntk_Node_t * node, 
+  st_table * nodeToMvfTable,
+  st_table * faninNumberTable)
+{
+  long faninNumber;
+  int i;
+  Mvf_Function_t *resultMvf;
+  Ntk_Node_t *faninNode;
+  array_t *faninMvfs = array_alloc(Mvf_Function_t *,
+				   Ntk_NodeReadNumFanins(node));
+  mdd_manager *mddMgr = Ntk_NetworkReadMddManager(Ntk_NodeReadNetwork(node)); 
+  int columnIndex = Ntk_NodeReadOutputIndex(node);
+  Tbl_Table_t *table = Ntk_NodeReadTable(node);
+  
+  Ntk_NodeForEachFanin(node, i, faninNode) {
+    Mvf_Function_t *tmpMvf;
+    st_lookup(nodeToMvfTable, faninNode, &tmpMvf); 
+    assert(tmpMvf);
+    array_insert(Mvf_Function_t *, faninMvfs, i, tmpMvf);
+  }
+  
+  resultMvf = Tbl_TableBuildMvfFromFanins(table, columnIndex,
+                                          faninMvfs, mddMgr);    
+  
+  /* Don't free the MVFs themselves, but just free the array. */
+  array_free(faninMvfs);
+
+  /* if the fanin node is no longer useful, remove its Mvfs */
+  Ntk_NodeForEachFanin(node, i, faninNode) {
+    st_lookup(faninNumberTable, faninNode, &faninNumber);
+    assert(faninNumber > 0);
+    faninNumber--;
+    st_insert(faninNumberTable, faninNode, (char *)faninNumber);
+
+    if (faninNumber <= 0) {
+      Mvf_Function_t *tmpMvf;
+      st_lookup(nodeToMvfTable, faninNode, &tmpMvf); 
+      Mvf_FunctionFree(tmpMvf);
+      st_insert(nodeToMvfTable, faninNode, NIL(char));
+    }
+  }
+
+  return resultMvf;
+}
+    
+      
+
+/**Function********************************************************************
+
+  Synopsis    [Builds MVF for a node that is a pseudo input.]
+
+  Description [Builds MVF for a node that is a pseudo input.  This node has a
+  single output and no inputs. Its table has several row entries.  We build an
+  MVF whose components correspond exactly to possible table outputs.]
+
+  SideEffects []
+
+  Comment [Although pseudo inputs, constants, and internal nodes all have
+  tables, a single procedure cannot be used to build their MVF.  A pseudo
+  input MVF is built in terms of its mddId, whereas a constant or internal is
+  not.  A constant or pseudo input doesn't have any inputs, whereas an
+  internal does.]
+  
+  SeeAlso     [Tbl_TableBuildMvfForNonDetConstant]
+
+******************************************************************************/
+static Mvf_Function_t *
+NodeBuildPseudoInputMvf(
+  Ntk_Node_t * node)
+{
+  mdd_manager  *mddMgr = Ntk_NetworkReadMddManager(Ntk_NodeReadNetwork(node));
+  int          mddId = Ntk_NodeReadMddId( node );
+  int          columnIndex = Ntk_NodeReadOutputIndex( node );
+  Tbl_Table_t  *table = Ntk_NodeReadTable( node );
+  Mvf_Function_t *mvf = Tbl_TableBuildNonDetConstantMvf(table, columnIndex,
+							mddId, mddMgr);
+
+  mdd_t *vMdd, *tMdd, *rMdd;
+  int lIndex, needProcess, i;
+
+  rMdd = mdd_zero(mddMgr);
+  needProcess = 0;
+  lIndex = 0;
+  for(i=0; i<mvf->num; i++) {
+    vMdd = array_fetch(mdd_t *, mvf, i);
+    if(mdd_equal(vMdd, rMdd)) {
+      needProcess = 1;
+    }
+    else {
+      lIndex = i;
+    }
+  }
+  if(needProcess) {
+    for(i=0; i<lIndex; i++) {
+      vMdd = array_fetch(mdd_t *, mvf, i);
+      tMdd = mdd_or(vMdd, rMdd, 1, 1);
+      mdd_free(rMdd);
+      rMdd = tMdd;
+    }
+    vMdd = array_fetch(mdd_t *, mvf, lIndex);
+    mdd_free(vMdd);
+    tMdd = mdd_not(rMdd);
+    mdd_free(rMdd);
+    array_insert(mdd_t *, mvf, lIndex, tMdd);
+  }
+  else {
+    mdd_free(rMdd);
+  }
+
+  return mvf;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the integers from a symbol table.]
+
+  Description [Prints the integers from a symbol table.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+PrintPartitionRecursively(vertex_t *vertex, st_table *vertexTable, int
+                          indent)
+{
+  int i;
+  lsList faninEdges;
+  lsGen gen;
+  vertex_t *faninVertex;
+  edge_t *faninEdge;
+  
+  if (st_is_member(vertexTable, (char *)vertex)) return;
+  st_insert(vertexTable, (char *)vertex, NIL(char));
+  for(i=0; i<= indent; i++) fprintf(vis_stdout," ");
+  fprintf(vis_stdout,"%s %d\n", Part_VertexReadName(vertex),
+          Part_VertexReadMddId(vertex)); 
+  faninEdges = g_get_in_edges(vertex);
+  if (lsLength(faninEdges) == 0) return;
+  lsForEachItem(faninEdges, gen, faninEdge){
+    faninVertex = g_e_source(faninEdge);
+    PrintPartitionRecursively(faninVertex, vertexTable,indent+2);
+  }
+}
+
Index: vis_dev/vis-2.3/src/part/partGroup.c
===================================================================
--- vis_dev/vis-2.3/src/part/partGroup.c	(revision 14)
+++ vis_dev/vis-2.3/src/part/partGroup.c	(revision 14)
@@ -0,0 +1,3330 @@
+/**CFile***********************************************************************
+
+  FileName    [partGroup.c]
+
+  PackageName [part]
+
+  Synopsis    [Routines for grouping vertices.]
+
+  Description [The first method groups vertices based on the hierachy of the
+  system.  Normally, the hierachy is formed in the early phase of the
+  design. We use this information to group latches. The method expects the
+  high level description languages to BLIF conversion utilities such as vl2mv
+  to preserve the original hierachy. The second method is explained in the
+  following paper.
+    H. Cho, G. D. Hachtel, E. Macii, B. Plessier, F. Somenzi," A
+    Structural Approach to State Space Decomposition for Approximate
+    Reachability Analysis," ICCD, pp.236-239, 1994. Traversal," EDAC.
+  This method groups vertices based on the latch dependency(relation between
+  latches) and the latch correlation(resemblance of latches in terms of the
+  support variables.]
+
+  Author      [Woohyuk Lee, Jae-Young Jang]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "partInt.h"
+
+static char rcsid[] UNUSED = "$Id: partGroup.c,v 1.51 2005/04/28 14:15:50 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static char * PartCreateDependencyMatrix(Part_SubsystemInfo_t *partSubInfo, st_table *ptrToIndex);
+static float * PartCreateCorrelationMatrixFromSupport(Part_SubsystemInfo_t *partSubInfo);
+static float * PartCreateCorrelationMatrixFromBDD(Part_SubsystemInfo_t *partSubInfo);
+static float PartVertexComputeCorrelation(int index1, int index2, array_t *arrayOfInputSupportTable, Part_SubsystemInfo_t *partSubInfo);
+static array_t * PartVertexComputeAgreement(mdd_manager *mddMgr, int index1, int index2, array_t *arrayOfBddArray);
+static float * PartCreateAffinityMatrix(char *arrayOfConnectivity, float *arrayOfCorrelation, Part_SubsystemInfo_t *partSubInfo);
+static array_t * PartGetConnectedComponent(float *arrayOfAffinity, Part_SubsystemInfo_t *partSubInfo, st_table *indexToPtr);
+static void PartFindCC(int *next, int *ccId, array_t *arrayOfCCIndex, float *arrayOfAffinity, array_t *arrayOfFrom, Part_SubsystemInfo_t *PartSubInfo);
+static array_t * PartBreakingAggregating(array_t *arrayOfInit, float *arrayOfAffinity, Part_SubsystemInfo_t *partSubInfo, st_table *ptrToIndex, char *arrayOfDependency);
+static array_t * PartBreakingBigConnectedComponent(array_t *arrayOfCC, array_t *ccCheck, array_t *arrayOfSeed, float *arrayOfAffinity, Part_SubsystemInfo_t *partSubInfo, st_table *ptrToIndex);
+static array_t * PartAggregating(array_t *arrayOfSmall, float *arrayOfAffinity, Part_SubsystemInfo_t *partSubInfo, st_table *ptrToIndex);
+static array_t * PartCreateSubSystemWithGroupIndex(Part_SubsystemInfo_t *partSubInfo, array_t *arrayOfLatchNames, array_t *arrayOfGroupIndex);
+static Ntk_Node_t * PartSelectCloseNode(Ntk_Node_t *seed, array_t *arrayOfCC, array_t *ccCheck, float *arrayOfAffinity, st_table *ptrToIndex);
+static int PartSelectCloseSeedIndex(Ntk_Node_t *variable, array_t *arrayOfSeed, float *arrayOfAffinity, st_table *ptrToIndex, array_t *seedFull, int bound);
+static Ntk_Node_t * PartSelectFarNode(Ntk_Node_t *seed, array_t *cc, array_t *ccCheck, float *arrayOfAffinity, st_table *ptrToIndex);
+static float * PartGetGroupMatrixRegular(array_t *arrayOfCluster, char *arrayOfGivenMatrix, st_table *ptrToIndex, int nVertices);
+static float * PartGetGroupMatrixSym(array_t *arrayOfCluster, float *arrayOfGivenMatrix, st_table *ptrToIndex);
+static int PartSelectCCIndexOfMinSupport(array_t *arrayOfSmall, array_t *ccCheck, Part_SubsystemInfo_t *partSubInfo);
+static Ntk_Node_t * PartSelectNodeOfMinSupport(array_t *cc, array_t *ccCheck, Part_SubsystemInfo_t *partSubInfo);
+static int PartSelectFarCCIndex(int seedIndex, array_t *arrayOfSmall, float *arrayOfGroupAff, Part_SubsystemInfo_t *partSubInfo, array_t *ccCheck);
+static int PartSelectCloseCCIndex(int seedIndex, array_t *arrayOfSmall, float *arrayOfGroupAff, array_t *ccCheck);
+static Part_Subsystem_t* PartCreateSingleSubSystem(array_t *arrayOfNodes, Ntk_Network_t *network);
+static array_t * PartReadLatchNameFromLatchInput(Ntk_Network_t *network, Ntk_Node_t *latchInput);
+static void PartArrayOfArrayFree(array_t *arrayOfMatrix);
+static float PartGetElementFromSymMatrix(float *matrix, int i, int j);
+static void PartPrintArrayArray(void *arrayOfMatrix, int nVertices, int type);
+static int strCompare(const void * name1, const void * name2);
+static int numCompare(const void * num1, const void * num2);
+static array_t *PartCreateSubsystemWithCTL(Part_SubsystemInfo_t *, array_t *, array_t *, boolean , boolean );
+static array_t *PartCreateSubsystemWithCtlAndLtl(Part_SubsystemInfo_t *, array_t *, array_t *, array_t *, boolean , boolean, boolean );
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [From the given latch data inputs, create array of
+  sub-partitions.]
+
+  Description [From the given latch data inputs, create array of sub-partitions
+  of vertices. Latch data inputs are given as "latchDataInputNames" and
+  includes subset of all latches in a system.  Since the vertices are defined
+  as the latch-input nodes, one may think of the process as grouping of
+  latches in the network.  "amc_sizeof_group" value may be set by the user by
+  using the set command from the vis shell. The function uses this value to
+  limit the number of vertices(latches) in a single group(subsystem). More
+  vertices in a subsystem implies its representation is closer to the exact
+  system.  When the value is not given by the user, the default value of 8
+  vertices(latches) is used. The routine uses hierachical grouping method.
+  That is, the latches in the same sub-processes(i.e. same .subckt in BLIF
+  format), are grouped together whenever possible.
+
+  Initial partition must be performed before executing this routine.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+array_t *
+Part_PartGroupVeriticesBasedOnHierarchy(
+  Ntk_Network_t *network,
+  array_t *latchDataInputNames)
+{
+  graph_t	*partition;
+  array_t	*arrayOfPartition = NIL(array_t);
+  array_t	*arrayOfGroups = NIL(array_t);
+  array_t	*arrayOfLatches = NIL(array_t);
+  array_t	*arrayOfLatchSort = NIL(array_t);
+  st_table	*vertexTable = NIL(st_table);
+  int		numOfVertex, reset;
+  int		i, j, k;
+  char		*numberOfVertexInGroup;
+  char		*flagValue;
+  char		*latchName, *name;
+  st_table	*latchDataInputNameTable;
+  Part_Subsystem_t *testSubsystem;
+
+  partition = Part_NetworkReadPartition(network);
+  if (partition == NIL(graph_t)) {
+    error_append("Network has no partition. Cannot create sub machines.");
+    return (NIL(array_t));
+  }
+
+  /*
+   * Convert graph of vertices into array of table of vertices.
+   */
+
+  numberOfVertexInGroup = Cmd_FlagReadByName("amc_sizeof_group");
+  if (numberOfVertexInGroup != NIL(char)) {
+    numOfVertex = atoi(numberOfVertexInGroup);
+    reset = atoi(numberOfVertexInGroup);
+  }
+  else {
+    /* default value */
+    numOfVertex = 8;
+    reset = 8;
+  }
+
+  latchDataInputNameTable = st_init_table(strcmp, st_strhash);
+
+  arrayForEachItem(char *, latchDataInputNames, i, name) {
+    st_insert(latchDataInputNameTable, (char *)name, (char *)NULL);
+  }
+
+  /*
+   * In the first phase, group latches by the processes.
+   * That is, group latches that are within same sub-circuit.
+   */
+
+  arrayOfGroups = array_alloc(array_t *, 0);
+
+  {
+    Ntk_Node_t  *latch;
+    lsGen	gen;
+    char	*groupName = util_strsav(" ");
+
+    arrayOfLatchSort = array_alloc(char *, 0);
+    Ntk_NetworkForEachLatch(network, gen, latch) {
+      Ntk_Node_t *latchInput = Ntk_LatchReadDataInput(latch);
+      char *latchInputName = Ntk_NodeReadName(latchInput);
+      vertex_t *vertex = Part_PartitionFindVertexByName(partition,
+							latchInputName);
+      if ((vertex != NIL(vertex_t)) &&
+	  (st_lookup(latchDataInputNameTable, latchInputName, NIL(char *)))) {
+	array_insert_last(char *, arrayOfLatchSort, Ntk_NodeReadName(latch));
+      }
+    }
+    array_sort(arrayOfLatchSort, strCompare);
+
+    arrayForEachItem(char *, arrayOfLatchSort, i, latchName) {
+      char *suffixLatchName, *currentGroupName;
+
+      suffixLatchName = util_strsav(latchName);
+
+      /* Extract out group name into the string "groupName" and leave
+	 rest in suffixLatchName. */
+
+      currentGroupName = strtok(suffixLatchName, ".");
+
+      if (strcmp(groupName, currentGroupName)) {
+	if (strcmp(groupName, " ")) {
+	  array_insert_last(array_t *, arrayOfGroups, arrayOfLatches);
+	}
+	FREE(groupName);
+	groupName = util_strsav(currentGroupName);
+	arrayOfLatches = array_alloc(char *, 0);
+      }
+      FREE(currentGroupName);
+      array_insert_last(char *, arrayOfLatches, latchName);
+    }
+    FREE(groupName);
+  }
+
+  array_free(arrayOfLatchSort);
+  st_free_table(latchDataInputNameTable);
+
+  /* Fill in the last arrayOfLatches */
+  array_insert_last(array_t *, arrayOfGroups, arrayOfLatches);
+
+  /*
+   * In the second phase, further break latch group into
+   * smaller group size according to the "amc_sizeof_group".
+   */
+
+  arrayOfPartition = array_alloc(Part_Subsystem_t *, 0);
+
+  arrayForEachItem(array_t *, arrayOfGroups, k, arrayOfLatches) {
+    char 	*latchName;
+    int		numOfLatches = array_n(arrayOfLatches);
+
+    arrayForEachItem(char *, arrayOfLatches, i, latchName) {
+
+      if (numOfVertex == reset)
+	vertexTable = st_init_table(strcmp, st_strhash);
+
+      st_insert(vertexTable, latchName, (char *)NULL);
+
+      if ((numOfVertex == 1) || (numOfLatches == i+1)) {
+	/* testSubsystem freed by calling function  */
+	testSubsystem = ALLOC(Part_Subsystem_t, 1);
+	testSubsystem->vertexNameTable = vertexTable;
+	testSubsystem->subsystemFanIn = NIL(array_t);
+	testSubsystem->subsystemFanOut = NIL(array_t);
+
+	array_insert_last(Part_Subsystem_t *, arrayOfPartition, testSubsystem);
+	numOfVertex = reset;
+      }
+      else
+	numOfVertex--;
+    } /* End of arrayForEachItem(arrayOfLatches) */
+  } /* End of arrayForEachItem(arrayOfGroups) */
+
+  /* Free arrayOfGroups, arrayOfLatches */
+  arrayForEachItem(array_t *, arrayOfGroups, i, arrayOfLatches) {
+    array_free(arrayOfLatches);
+  }
+  array_free(arrayOfGroups);
+
+  /*
+   * Currently this function is used only from amc package.
+   * When the function gets popular use parameter passing rather that this
+   * ugly method.
+   */
+  flagValue = Cmd_FlagReadByName("amc_use_MBM");
+  if (flagValue != NIL(char)) {
+    array_t	*latchNodeArray;
+    array_t	*faninNodeArray;
+    array_t	*faninLatchArray;
+
+    /*
+     * Fill in the subsystem dependencies using the latch dependencies.
+     */
+
+    arrayForEachItem(Part_Subsystem_t *, arrayOfPartition, i, testSubsystem) {
+      array_t		*fanInArray = array_alloc(int, 0);
+      st_table		*vertexTable = testSubsystem->vertexNameTable;
+      st_generator	*stGen;
+      char		*latchName;
+      Ntk_Node_t	*latchNode;
+
+      latchNodeArray = array_alloc(Ntk_Node_t *, 0);
+      faninLatchArray = array_alloc(Ntk_Node_t *, 0);
+
+      /* Convert table of latch names into array of latch nodes */
+      st_foreach_item(vertexTable, stGen, &latchName, NIL(char *)) {
+	latchNode = Ntk_NetworkFindNodeByName(network, latchName);
+	array_insert_last(Ntk_Node_t *, latchNodeArray, latchNode);
+      }
+
+      /* Find the transitive fanin nodes */
+      faninNodeArray = Ntk_NodeComputeCombinationalSupport(network,
+			latchNodeArray, FALSE);
+
+      /* Find the transitive fanin latches from the fanin nodes */
+      if (array_n(faninNodeArray) != 0) {
+	int x;
+	arrayForEachItem(Ntk_Node_t *, faninNodeArray, x, latchNode) {
+	  if (Ntk_NodeTestIsLatch(latchNode) == TRUE) {
+	    array_insert_last(Ntk_Node_t *, faninLatchArray, latchNode);
+	  }
+	}
+      }
+
+      /* Find the fanin subsystems */
+      if (array_n(faninLatchArray) != 0) {
+	Part_Subsystem_t *scanSubsystem;
+	int y;
+
+	arrayForEachItem(Part_Subsystem_t *, arrayOfPartition, j,
+		scanSubsystem) {
+	  /* Scan subsystems that aren't the currently considered subsytem */
+	  st_table 	*otherVertexTable = scanSubsystem->vertexNameTable;
+
+	  if (i != j) {
+	    arrayForEachItem(Ntk_Node_t *, faninLatchArray, y, latchNode) {
+	      char *latchName = Ntk_NodeReadName(latchNode);
+	      if (st_lookup(otherVertexTable, latchName, NIL(char *))) {
+		array_insert_last(int, fanInArray, j);
+		break;
+	      }
+	    } /* end of arrayForEachItem(Ntk_Node_t *) */
+	  } /* end of if (i != j) */
+	}
+      } /* end of if (array_n(faninLatchArray) != 0) */
+
+      /* Update fanInArray into the subsystem */
+      testSubsystem->subsystemFanIn = fanInArray;
+
+      array_free(latchNodeArray);
+      array_free(faninNodeArray);
+      array_free(faninLatchArray);
+    } /* end of arrayForEachItem(Part_Subsystem_t *) */
+  } /* end of if (!flagValue) */
+
+  /*
+   * Currently this function is used only from amc package.
+   * When the function gets popular use parameter passing rather that this
+   * ugly method.
+   */
+
+  flagValue = Cmd_FlagReadByName("amc_use_MBM");
+  if (flagValue != NIL(char)) {
+    st_table *fanOutDependencies = Ntk_NetworkComputeLatchDependencies(network);
+
+    /*
+     * Fill in the fanout dependencies of subsystems.
+     */
+    arrayForEachItem(Part_Subsystem_t *, arrayOfPartition, i, testSubsystem) {
+      array_t		*fanOutArray = array_alloc(int, 0);
+      st_table		*vertexTable = testSubsystem->vertexNameTable;
+      st_generator	*stGen;
+      char		*latchName;
+      st_table		*everyFanOuts = st_init_table(st_ptrcmp, st_ptrhash);
+
+      /*
+       * For the latches in this subsystem,
+       * find all latches that transitively fanouts from the latches
+       * inside this subsystem. Store it in a hash table, "everyFanOuts".
+       */
+      st_foreach_item(vertexTable, stGen, &latchName, NIL(char *)) {
+	Ntk_Node_t	*latchNode;
+	lsList		fanOutLatchList;
+	lsGen		gen;
+	lsGeneric	data;
+
+	latchNode = Ntk_NetworkFindNodeByName(network, latchName);
+	st_lookup(fanOutDependencies, latchNode, &fanOutLatchList);
+
+	/* Obtain all fanout latches coming from latches of this subsystem */
+	gen = lsStart(fanOutLatchList);
+	while (lsNext(gen, &data, LS_NH) == LS_OK) {
+	  st_insert(everyFanOuts, data, NULL);
+	}
+	(void) lsFinish(gen);
+	lsDestroy(fanOutLatchList, (void (*) (lsGeneric)) NULL);
+      }
+
+      /*
+       * Scan subsystems that aren't the currently considered subsytem.
+       */
+      {
+	Part_Subsystem_t *scanSubsystem;
+	arrayForEachItem(Part_Subsystem_t *, arrayOfPartition, j,
+		scanSubsystem) {
+	  st_table	*otherVertexTable = scanSubsystem->vertexNameTable;
+
+	  if (i != j) {
+	    st_generator	*stGen;
+	    Ntk_Node_t		*latchNode;
+
+	    st_foreach_item(everyFanOuts, stGen, &latchNode, NULL) {
+	      char *latchName = Ntk_NodeReadName(latchNode);
+	      if (st_lookup(otherVertexTable, latchName, NIL(char *))) {
+		array_insert_last(int, fanOutArray, j);
+		break;
+	      }
+	    } /* end of  */
+	  } /* end of if (i != j) */
+	} /* end of arrayForEachItem(Part_Subsystem_t *) */
+      }
+
+      st_free_table(everyFanOuts);
+
+      /* Update fanOutArray into the subsystem */
+      testSubsystem->subsystemFanOut = fanOutArray;
+    } /* end of arrayForEachItem(Part_Subsystem_t *) */
+
+    /* Free dependency hash table */
+    st_free_table(fanOutDependencies);
+  }
+
+  return(arrayOfPartition);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Create sub-systems based on latch relation]
+
+  Description [Create sub-systems based on latch dependency, connectivity,
+  correlation, and affinity. If arrayOfFunctionNames(latch data inputs) is
+  given, only those nodes are considered to make sub-systems. If arrayOfGroup-
+  Index(Ii) is given with arrayOfFunctionNames(Fi), Fi is put in Ii'th
+  sub-system.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+Part_PartCreateSubsystems(
+  Part_SubsystemInfo_t *subInfo,
+  array_t *arrayOfLatchNames,
+  array_t *arrayOfGroupIndex)
+{
+  if (subInfo->verbosity > 0) {
+    if (arrayOfLatchNames != NIL(array_t)) {
+      fprintf(vis_stdout, "Grouping: Array of latch data is given.\n");
+      fprintf(vis_stdout,
+	"Grouping: All latches related to the array will be grouped.\n");
+    } else if (Part_NetworkReadPartition(subInfo->network) == NIL(graph_t)) {
+      fprintf(vis_stdout, "Grouping: Network has no partition.\n");
+      fprintf(vis_stdout,
+	"Grouping: All latches in network will be grouped.\n");
+    } else {
+      fprintf(vis_stdout, "Grouping: Network has a partition.\n");
+      fprintf(vis_stdout,
+	"Grouping: All latches in partition will be grouped.\n");
+    }
+  }
+  return(PartCreateSubsystem(subInfo, arrayOfLatchNames, arrayOfGroupIndex));
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Create sub-partitions based on latch relation]
+
+  Description [Create sub-partition based on latch dependency, connectivity,
+  correlation, and affinity. The first sub-system includes latches in CTL
+  formula, and latches with strong affinity are put in next sub-system. If
+  dynamicIncrease is TRUE, the first sub-system which has stringest realtion
+  with given formula and the second sub-system with all other latches are
+  returned.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+Part_PartCreateSubsystemsWithCTL(
+  Part_SubsystemInfo_t *subInfo,
+  array_t *ctlArray,
+  array_t *fairArray,
+  boolean dynamicIncrease,
+  boolean dynamicAndDependency)
+{
+  if (subInfo->verbosity > 0 ){
+    fprintf(vis_stdout,"Grouping: All latches related to ");
+    fprintf(vis_stdout,"the CTL will be grouped.\n");
+  }
+  return (PartCreateSubsystemWithCTL(subInfo, ctlArray, fairArray,
+                             dynamicIncrease,dynamicAndDependency));
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Create sub-partitions based on latch relation]
+
+  Description [Create sub-partition based on latch dependency, connectivity,
+  correlation, and affinity. The first sub-system includes latches in CTL
+  formula, and latches with strong affinity are put in next sub-system. If
+  dynamicIncrease is TRUE, the first sub-system which has stringest realtion
+  with given formula and the second sub-system with all other latches are
+  returned.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+Part_PartCreateSubsystemsWithCtlAndLtl(
+  Part_SubsystemInfo_t *subInfo,
+  array_t *ctlArray,
+  array_t *ltlArray,
+  array_t *fairArray,
+  boolean dynamicIncrease,
+  boolean dynamicAndDependency,
+  boolean strictBound)
+{
+  if (subInfo->verbosity > 0 ){
+    fprintf(vis_stdout,"Grouping: All latches related to ");
+    fprintf(vis_stdout,"the CTL/LTL/fairness will be grouped.\n");
+  }
+  return (PartCreateSubsystemWithCtlAndLtl(subInfo, ctlArray, ltlArray,
+					   fairArray,
+					   dynamicIncrease,
+					   dynamicAndDependency,
+					   strictBound));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Read the table attached to a partitioned subsystem.]
+
+  SideEffects []
+
+******************************************************************************/
+st_table *
+Part_PartitionSubsystemReadVertexTable(
+  Part_Subsystem_t *partitionedSubsystem)
+{
+  return(partitionedSubsystem->vertexNameTable);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Read fan-in array attached to partitioned subsystem]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+Part_PartitionSubsystemReadFanIn(
+  Part_Subsystem_t *partitionedSubsystem)
+{
+  return(partitionedSubsystem->subsystemFanIn);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Read fan-out array attached to partitioned subsystem]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+Part_PartitionSubsystemReadFanOut(
+  Part_Subsystem_t *partitionedSubsystem)
+{
+  return(partitionedSubsystem->subsystemFanOut);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initialize info structure for partitioning subsystem]
+
+  SideEffects []
+
+  SeeAlso     [Part_SubsystemInfo]
+
+******************************************************************************/
+Part_SubsystemInfo_t *
+Part_PartitionSubsystemInfoInit(
+  Ntk_Network_t *network)
+{
+  Part_SubsystemInfo_t *partSubInfo;
+
+  partSubInfo = ALLOC(Part_SubsystemInfo_t, 1);
+
+ /*
+  * set values as defaults
+  */
+  partSubInfo->network = network;
+  partSubInfo->arrayOfVertex = NIL(array_t);
+  partSubInfo->numberOfVertex = 0;
+  partSubInfo->partBM = Part_BFix_v;
+  partSubInfo->con_factor = PART_SUB_CON_FACTOR;
+  partSubInfo->cor_factor = PART_SUB_COR_FACTOR;
+  partSubInfo->aff_factor = PART_SUB_AFF_FACTOR;
+  partSubInfo->threshold = 0.0;
+  partSubInfo->bound = 8;
+  partSubInfo->verbosity = 0;
+  partSubInfo->corMethod = Part_CorrelationDefault;
+  partSubInfo->dupLatchTable = st_init_table(strcmp, st_strhash);
+  partSubInfo->latchNameTable = st_init_table(strcmp, st_strhash);
+  return(partSubInfo);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Free info structure for partitioning subsystem]
+
+  SideEffects []
+
+  SeeAlso     [Part_SubsystemInfo]
+
+******************************************************************************/
+void
+Part_PartitionSubsystemInfoFree(
+  Part_SubsystemInfo_t *partSubInfo)
+{
+  st_generator	*stGen;
+  char		*latchInputName;
+  array_t	*latchNames;
+
+  array_free(partSubInfo->arrayOfVertex);
+  st_foreach_item(partSubInfo->dupLatchTable, stGen, &latchInputName,
+	&latchNames) {
+    array_free(latchNames);
+  }
+  st_free_table(partSubInfo->dupLatchTable);
+  st_free_table(partSubInfo->latchNameTable);
+  FREE(partSubInfo);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Free subsystem structure for partitioning subsystem]
+
+  SideEffects []
+
+  SeeAlso     [Part_Subsystem]
+
+******************************************************************************/
+void
+Part_PartitionSubsystemFree(
+  Part_Subsystem_t *partSubsystem)
+{
+  st_free_table(partSubsystem->vertexNameTable);
+  array_free(partSubsystem->subsystemFanIn);
+  array_free(partSubsystem->subsystemFanOut);
+  FREE(partSubsystem);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Set breaking method of subsystem info]
+
+  SideEffects []
+
+  SeeAlso     [Part_SubsystemInfo]
+
+******************************************************************************/
+void
+Part_PartitionSubsystemInfoSetBreakingMethod(
+  Part_SubsystemInfo_t *subInfo,
+  Part_BMethod bMethod)
+{
+  subInfo->partBM = bMethod;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Set bound of subsystem info]
+
+  SideEffects []
+
+  SeeAlso     [Part_SubsystemInfo]
+
+******************************************************************************/
+void
+Part_PartitionSubsystemInfoSetBound(
+  Part_SubsystemInfo_t *subInfo,
+  int bound)
+{
+  subInfo->bound = bound;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Set threshold of subsystem info]
+
+  SideEffects []
+
+  SeeAlso     [Part_SubsystemInfo]
+
+******************************************************************************/
+void
+Part_PartitionSubsystemInfoSetThreshold(
+  Part_SubsystemInfo_t *subInfo,
+  float threshold)
+{
+  subInfo->threshold = threshold;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Set verbosity of subsystem info]
+
+  SideEffects []
+
+  SeeAlso     [Part_SubsystemInfo]
+
+******************************************************************************/
+void
+Part_PartitionSubsystemInfoSetVerbosity(
+  Part_SubsystemInfo_t *subInfo,
+  int verbosity)
+{
+  subInfo->verbosity = verbosity;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Set method for correlation]
+
+  SideEffects []
+
+  SeeAlso     [Part_SubsystemInfo]
+
+******************************************************************************/
+void
+Part_PartitionSubsystemInfoSetCorrelationMethod(
+  Part_SubsystemInfo_t *subInfo,
+  Part_CMethod corMethod)
+{
+  subInfo->corMethod = corMethod;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Set affinity factor]
+
+  SideEffects []
+
+  SeeAlso     [Part_SubsystemInfo]
+
+******************************************************************************/
+void
+Part_PartitionSubsystemInfoSetAffinityFactor(
+  Part_SubsystemInfo_t *subInfo,
+  float affinity)
+{
+  subInfo->aff_factor = affinity;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Create a sub-system with given latch data input in arrayOfNodes]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Part_Subsystem_t*
+Part_PartCreateSingleSubSystem(
+  array_t *arrayOfNodes,
+  Ntk_Network_t *network)
+{
+  return PartCreateSingleSubSystem(arrayOfNodes, network);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Create an array of partitioned subsystems from array of latches]
+
+  Description [This is a main function to get subsystems. At first, look at
+  the circuit topology and next state functions, get the latch affinity.
+  Find the connected components to cluster latches which are stronly dependent
+  or correlated on each other.
+  After that, divide clusters bigger than the given bound and aggregate
+  smaller clusters. This function is called with network and partition graph.
+  If arrayOfFunctionNames are not NULL, this function generates sub-system with
+  those latch-data-inputs in that array. If arrayOfGroupIndex is not NILL and
+  size of this array is same as the size of arrayOfFunctionNames, this function
+  uses these two arrays as predefined grouping information and creates
+  sub-systems.]
+
+  SideEffects []
+
+  SeeAlso     [Part_SubsystemInfo]
+
+******************************************************************************/
+array_t *
+PartCreateSubsystem(
+  Part_SubsystemInfo_t *partSubInfo,
+  array_t *arrayOfLatchNames,
+  array_t *arrayOfGroupIndex)
+{
+  char		*arrayOfDependency = NIL(char);
+  float		*arrayOfCorrelation = NIL(float);
+  float		*arrayOfAffinity;
+  array_t	*arrayOfInit;
+  st_table	*indexToPtrInfo; /* index to pointer table */
+  st_table	*ptrToIndexInfo; /* pointer to index table */
+  array_t	*result;
+  Ntk_Node_t	*node;
+  char		*functionName;
+  char		*latchName;
+  lsList	vertexList;
+  lsGen		gen;
+  int		i;
+  vertex_t	*vertex;
+  array_t	*initArray;
+  array_t	*arrayOfVertex;
+  Ntk_Network_t	*network = partSubInfo->network;
+  graph_t	*partition = Part_NetworkReadPartition(network);
+  long		initialTime = 0;
+  long		finalTime;
+
+  if (partition == NIL(graph_t)) {
+    if (partSubInfo->corMethod == Part_CorrelationWithBDD) {
+       error_append("Network has no partition. Correlation ");
+       error_append("with MDD operation can not be used.\n");
+       return NIL(array_t);
+    }
+  }
+  if (arrayOfGroupIndex != NIL(array_t)) {
+    if (!arrayOfLatchNames) {
+      error_append("Latch name array is not given.\n");
+      result = NIL(array_t);
+    }
+    if (array_n(arrayOfLatchNames) != array_n(arrayOfGroupIndex)) {
+      error_append("Given function names and index have different size.\n");
+      result = NIL(array_t);
+    }
+  }
+
+  if (arrayOfLatchNames && arrayOfGroupIndex) {
+    result = PartCreateSubSystemWithGroupIndex(partSubInfo,
+		arrayOfLatchNames, arrayOfGroupIndex);
+    return result;
+  }
+
+  arrayOfVertex = array_alloc(Ntk_Node_t *, 0);
+
+  /*
+   * Convert graph vertices into array of array of vertices.
+   */
+  if (partSubInfo->verbosity > 2) {
+    fprintf(vis_stdout, "\nGroupting: List of latches\n");
+    fprintf(vis_stdout, "----------------------------\n");
+  }
+  if (arrayOfLatchNames != NIL(array_t)) {
+    Ntk_Node_t	*latchNode, *latchInputNode;
+    char	*otherLatchName;
+    array_t	*latchNameArray;
+
+    arrayForEachItem(char *, arrayOfLatchNames, i, latchName) {
+      latchNode = Ntk_NetworkFindNodeByName(network, latchName);
+      latchInputNode = Ntk_LatchReadDataInput(latchNode);
+      functionName = Ntk_NodeReadName(latchInputNode);
+      if (partSubInfo->verbosity > 2)
+	fprintf(vis_stdout, "%s\n", latchName);
+      if (st_lookup(partSubInfo->latchNameTable, functionName,
+		&otherLatchName)) {
+	if (st_lookup(partSubInfo->dupLatchTable, functionName,
+	    &latchNameArray)) {
+	  array_insert_last(char *, latchNameArray, latchName);
+	} else {
+	  latchNameArray = array_alloc(char *, 0);
+	  array_insert_last(char *, latchNameArray, otherLatchName);
+	  array_insert_last(char *, latchNameArray, latchName);
+	  st_insert(partSubInfo->dupLatchTable, (char *)functionName,
+		(char *)latchNameArray);
+	}
+	continue;
+      }
+      st_insert(partSubInfo->latchNameTable, (char *)functionName,
+	(char *)latchName);
+      array_insert_last(Ntk_Node_t *, arrayOfVertex, latchInputNode);
+    }
+  } else if (partition == NIL(graph_t)) {
+    Ntk_NetworkForEachNode(network, gen, node) {
+      if (Ntk_NodeTestIsLatchDataInput(node)) {
+	array_insert_last(Ntk_Node_t *, arrayOfVertex, node);
+	arrayOfLatchNames = PartReadLatchNameFromLatchInput(network, node);
+	functionName = Ntk_NodeReadName(node);
+	latchName = array_fetch(char *, arrayOfLatchNames, 0);
+	st_insert(partSubInfo->latchNameTable, (char *)functionName,
+		(char *)latchName);
+	if (array_n(arrayOfLatchNames) > 1) {
+	  st_insert(partSubInfo->dupLatchTable, (char *)functionName,
+		(char *)arrayOfLatchNames);
+	  if (partSubInfo->verbosity > 2) {
+	    char *nname;
+	    arrayForEachItem(char *, arrayOfLatchNames, i, nname) {
+	      fprintf(vis_stdout, "%s\n", nname);
+	    }
+	  }
+	} else {
+	  array_free(arrayOfLatchNames);
+	  if (partSubInfo->verbosity > 2)
+	    fprintf(vis_stdout, "%s\n", latchName);
+	}
+      }
+    } /* End of Ntk_NetworkForEachNode */
+  } else {
+    vertexList = g_get_vertices(partition);
+    lsForEachItem(vertexList, gen, vertex) {
+      char *nodeName = PartVertexReadName(vertex);
+      node = Ntk_NetworkFindNodeByName(network, nodeName);
+      if (Ntk_NodeTestIsLatchDataInput(node)) {
+	array_insert_last(Ntk_Node_t *, arrayOfVertex, node);
+	arrayOfLatchNames = PartReadLatchNameFromLatchInput(network, node);
+	functionName = Ntk_NodeReadName(node);
+	latchName = array_fetch(char *, arrayOfLatchNames, 0);
+	st_insert(partSubInfo->latchNameTable, (char *)functionName,
+		(char *)latchName);
+	if (array_n(arrayOfLatchNames) > 1) {
+	  st_insert(partSubInfo->dupLatchTable, (char *)functionName,
+		(char *)arrayOfLatchNames);
+	  if (partSubInfo->verbosity > 2) {
+	    char *nname;
+	    arrayForEachItem(char *, arrayOfLatchNames, i, nname) {
+	      fprintf(vis_stdout, "%s\n", nname);
+	    }
+	  }
+	} else {
+	  array_free(arrayOfLatchNames);
+	  if (partSubInfo->verbosity > 2)
+	    fprintf(vis_stdout, "%s\n", latchName);
+	}
+      }
+    }
+  }
+
+  if (partSubInfo->verbosity > 2) {
+    fprintf(vis_stdout, "Total # of latch data input = %d\n",
+      array_n(arrayOfVertex));
+  }
+  partSubInfo->arrayOfVertex = arrayOfVertex;
+  partSubInfo->numberOfVertex = array_n(arrayOfVertex);
+
+ /*
+  * table from index to pointer and pointer to index
+  */
+  indexToPtrInfo = st_init_table(st_numcmp, st_numhash);
+  ptrToIndexInfo = st_init_table(st_ptrcmp, st_ptrhash);
+
+  arrayForEachItem(Ntk_Node_t *, partSubInfo->arrayOfVertex, i, node) {
+    st_insert(indexToPtrInfo, (char *)(long)i, (char *)node);
+    st_insert(ptrToIndexInfo, (char *)node, (char *)(long)i);
+  }
+
+ /*
+  * get a dependency matrix
+  */
+  if (partSubInfo->aff_factor > 0.0) {
+    if (partSubInfo->verbosity > 0)
+      initialTime = util_cpu_time();
+    arrayOfDependency = PartCreateDependencyMatrix(partSubInfo, ptrToIndexInfo);
+    if (partSubInfo->verbosity > 0) {
+      finalTime = util_cpu_time();
+      fprintf(vis_stdout, "time for computing dependency = %g\n",
+	(double)(finalTime - initialTime) / 1000.0);
+    }
+  }
+
+ /*
+  * get a correlation matrix
+  */
+  if (partSubInfo->aff_factor != 1.0) {
+    if (partSubInfo->verbosity > 0)
+      initialTime = util_cpu_time();
+    if (partSubInfo->corMethod == Part_CorrelationWithBDD)
+      arrayOfCorrelation = PartCreateCorrelationMatrixFromBDD(partSubInfo);
+    else if ((partSubInfo->corMethod == Part_CorrelationWithSupport) ||
+  	     (partSubInfo->corMethod == Part_CorrelationDefault)) {
+      arrayOfCorrelation = PartCreateCorrelationMatrixFromSupport(partSubInfo);
+    }
+    if (partSubInfo->verbosity > 0) {
+      finalTime = util_cpu_time();
+      fprintf(vis_stdout, "time for computing correlation = %g\n",
+	(double)(finalTime - initialTime) / 1000.0);
+    }
+  }
+
+  if (partSubInfo->verbosity > 2) {
+    if (arrayOfDependency) {
+      fprintf(vis_stdout, "\nGrouping: Dependency\n");
+      fprintf(vis_stdout, "--------------------\n");
+      PartPrintArrayArray(arrayOfDependency, partSubInfo->numberOfVertex, 1);
+    }
+    if (arrayOfCorrelation) {
+      fprintf(vis_stdout, "\nGrouping: Correlation\n");
+      fprintf(vis_stdout, "---------------------\n");
+      PartPrintArrayArray(arrayOfCorrelation, partSubInfo->numberOfVertex, 0);
+    }
+ }
+
+ /*
+  * get an affinity matrix, arrayOfCorrelation is freed.
+  */
+  if (partSubInfo->verbosity > 0)
+    initialTime = util_cpu_time();
+  arrayOfAffinity = PartCreateAffinityMatrix(arrayOfDependency,
+			arrayOfCorrelation, partSubInfo);
+  FREE(arrayOfCorrelation);
+  if (partSubInfo->verbosity > 0) {
+    finalTime = util_cpu_time();
+    fprintf(vis_stdout, "time for computing affinity = %g\n",
+      (double)(finalTime - initialTime) / 1000.0);
+  }
+
+  if (partSubInfo->verbosity > 2) {
+    fprintf(vis_stdout, "\nGrouping: Affinity\n");
+    fprintf(vis_stdout, "------------------\n");
+    PartPrintArrayArray(arrayOfAffinity, partSubInfo->numberOfVertex, 0);
+  }
+
+ /*
+  * get an initial subsysytm by searching for connected component in
+  * vertex affinity matrix
+  */
+  if (partSubInfo->verbosity > 0)
+    initialTime = util_cpu_time();
+  arrayOfInit = PartGetConnectedComponent(arrayOfAffinity, partSubInfo,
+			indexToPtrInfo);
+  if (partSubInfo->verbosity > 0) {
+    finalTime = util_cpu_time();
+    fprintf(vis_stdout, "time for computing connected component = %g\n",
+      (double)(finalTime - initialTime) / 1000.0);
+  }
+
+  if (partSubInfo->verbosity > 2) {
+    fprintf(vis_stdout, "\nGrouping: Initial connected component size\n");
+    fprintf(vis_stdout, "------------------------------------------\n\n");
+    arrayForEachItem(array_t *, arrayOfInit, i, initArray) {
+      fprintf(vis_stdout, "%3d group: size = %d\n", i, array_n(initArray));
+    }
+  }
+
+ /*
+  * get a final subsystem by breaking big connected components and
+  * aggregating small connected components.
+  */
+  if (partSubInfo->verbosity > 0)
+    initialTime = util_cpu_time();
+  result = PartBreakingAggregating(arrayOfInit, arrayOfAffinity, partSubInfo,
+	   ptrToIndexInfo, arrayOfDependency);
+  if (partSubInfo->verbosity > 0) {
+    finalTime = util_cpu_time();
+    fprintf(vis_stdout, "time for breaking and aggregating = %g\n",
+      (double)(finalTime - initialTime) / 1000.0);
+  }
+
+  array_free(arrayOfInit);
+
+  if (partSubInfo->verbosity >= 2) {
+    Part_Subsystem_t *sub;
+    char *latchName;
+    st_generator *stGen;
+
+    fprintf(vis_stdout, "\nGrouping: List of subsytem latches\n");
+    fprintf(vis_stdout, "----------------------------------\n\n");
+    arrayForEachItem(Part_Subsystem_t *, result, i, sub) {
+      fprintf(vis_stdout, "[Subsystem %3d]\n", i);
+      st_foreach_item(sub->vertexNameTable, stGen, &latchName, NIL(char *)) {
+	fprintf(vis_stdout, "%s\n", latchName);
+      }
+      fprintf(vis_stdout, "\n");
+    }
+  }
+
+  if (partSubInfo->verbosity >= 1) {
+    (void)fprintf(vis_stdout, "\nGrouping: grouping options\n");
+    (void)fprintf(vis_stdout, "--------------------------\n\n");
+    (void)fprintf(vis_stdout, "Threshold          : %f\n",
+		partSubInfo->threshold);
+    (void)fprintf(vis_stdout, "bound              : %d\n",
+		partSubInfo->bound);
+    (void)fprintf(vis_stdout, "connectivity factor: %f\n",
+		partSubInfo->con_factor);
+    (void)fprintf(vis_stdout, "correlation factor : %f\n",
+		partSubInfo->cor_factor);
+    (void)fprintf(vis_stdout, "affinity factor    : %f\n",
+		partSubInfo->aff_factor);
+    (void)fprintf(vis_stdout, "\n");
+  }
+
+  st_free_table(indexToPtrInfo);
+  st_free_table(ptrToIndexInfo);
+  FREE(arrayOfDependency);
+  FREE(arrayOfAffinity);
+
+  return result;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Create an array of subsystems from properties]
+
+  Description [The first couple of sub-systems include nodes which are in
+  CTL formulae.  A node with biggest affinity is included in the next
+  sub-system until the number of nodes is less than bound. If dynamicIncrease
+  is FALSE, get all sub-systems with all support variables of CTL formula.
+  If TRUE, the first sub-system includes variables in CTL and the second
+  sub-system includes others.]
+
+  SideEffects []
+
+  SeeAlso     [Part_SubsystemInfo]
+
+******************************************************************************/
+static
+array_t *
+PartCreateSubsystemWithCTL( 
+  Part_SubsystemInfo_t *partSubInfo,
+  array_t *ctlArray,
+  array_t *fairArray,
+  boolean dynamicIncrease,
+  boolean dynamicAndDependency)
+{
+  return PartCreateSubsystemWithCtlAndLtl(partSubInfo, ctlArray, NIL(array_t),
+					  fairArray, dynamicIncrease,
+					  dynamicAndDependency, FALSE);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Create an array of subsystems from properties]
+
+  Description [The first couple of sub-systems include nodes which are
+  in CTL/LTL/fairness formulae.  A node with biggest affinity is
+  included in the next sub-system until the number of nodes is less
+  than bound. If dynamicIncrease is FALSE, get all sub-systems with
+  all support variables of CTL formula.  If TRUE, the first sub-system
+  includes variables in CTL and the second sub-system includes others.
+
+  When strictBound is FALSE, all the latches appearing in the formulae
+  are put into the first subsystem -- making it possibly larger than
+  the bound. Otherwise, no subsystem will have more than 'bound'
+  latches.]
+
+  SideEffects []
+
+  SeeAlso     [Part_SubsystemInfo]
+
+******************************************************************************/
+static
+array_t *
+PartCreateSubsystemWithCtlAndLtl(
+  Part_SubsystemInfo_t *partSubInfo,
+  array_t *ctlArray,
+  array_t *ltlArray,
+  array_t *fairArray,
+  boolean dynamicIncrease,
+  boolean dynamicAndDependency,
+  boolean strictBound)
+{
+  int i, j, index, maxSize, maxIndex, leftNodes, numSeed;
+  array_t *result = NIL(array_t);
+  Ntk_Network_t *network = partSubInfo->network;
+  lsList latchNodeList;
+  lsGen  gen;
+  char *arrayOfDependency = NIL(char);
+  float *arrayOfCorrelation = NIL(float);
+  float *arrayOfAffinity = NIL(float);
+  array_t *arrayTemp = NIL(array_t);
+  array_t *arrayOfVertex = NIL(array_t);
+  array_t *arrayOfLatchNames = NIL(array_t);
+  st_table *vertexToArrayOfLatchNames = NIL(st_table);
+  array_t *arrayOfLatchNodeName = NIL(array_t);
+  Ntk_Node_t *node = NIL(Ntk_Node_t);
+  float affinity;
+  char *name = NIL(char);
+  st_table *indexToPtrInfo = NIL(st_table);
+  st_table *ptrToIndexInfo = NIL(st_table);
+  array_t *check = NIL(array_t);
+  array_t *tempCheck = NIL(array_t);
+  array_t *tempCC = NIL(array_t);
+  st_generator *stGen = NIL(st_generator);
+  array_t *arrayOfSeed = NIL(array_t);
+  Ntk_Node_t *seedLast = NIL(Ntk_Node_t);
+  Ntk_Node_t *seedNext = NIL(Ntk_Node_t);
+  array_t *arrayOfBreak = NIL(array_t);
+  array_t *arrayOfNodes = NIL(array_t);
+  array_t *arrayOfIndex = NIL(array_t);
+  st_table *dataInputNodes = NIL(st_table);
+  Part_Subsystem_t *sub = NIL(Part_Subsystem_t);
+  int numIncluded;
+  float prevAffinity;
+
+  if (ctlArray == NIL(array_t) && ltlArray == NIL(array_t)){
+    return NIL(array_t);
+  }
+
+  /*
+   * arrayOfLatchNodeName  <--  COI latch names
+   */
+  latchNodeList = lsCreate();
+  PartGetLatchListFromCtlAndLtl(network, ctlArray, ltlArray,
+				fairArray, latchNodeList, FALSE);
+  arrayOfLatchNodeName = array_alloc(Ntk_Node_t *, 0);
+  lsForEachItem(latchNodeList, gen, node){
+    array_insert_last(char *, arrayOfLatchNodeName, Ntk_NodeReadName(node));
+  }
+  lsDestroy(latchNodeList, (void (*)(lsGeneric))0);
+
+  /*
+   * arrayOfVertex  <--  COI latch datainput nodes
+   */
+  array_sort(arrayOfLatchNodeName, strCompare);
+  arrayOfVertex = array_alloc(Ntk_Node_t *, 0);
+  vertexToArrayOfLatchNames = st_init_table(st_ptrcmp, st_ptrhash);
+  /* multiple latch may correspond to the same  dataInput */ 
+  arrayForEachItem(char *, arrayOfLatchNodeName, i, name){
+    node = Ntk_NetworkFindNodeByName(network, name);
+    node = Ntk_LatchReadDataInput(node);
+    if (!st_lookup(vertexToArrayOfLatchNames, node, &arrayOfLatchNames) ) {
+      arrayOfLatchNames = array_alloc(char *, 0);
+      array_insert_last(char *, arrayOfLatchNames, name);
+      st_insert(vertexToArrayOfLatchNames, node, arrayOfLatchNames);
+      
+      array_insert_last(Ntk_Node_t *, arrayOfVertex, node);
+    }else 
+      array_insert_last(char *, arrayOfLatchNames, name);
+  }
+
+  /*
+   * Print a list of latch names.
+   */
+  if (partSubInfo->verbosity >= 2){
+    fprintf(vis_stdout,"\nGroupting: List of latches\n");
+    fprintf(vis_stdout,"------------------------\n\n");
+    arrayForEachItem(char *, arrayOfLatchNodeName, i, name){
+      fprintf(vis_stdout,"%s\n", name);
+    }
+  }
+  array_free(arrayOfLatchNodeName);
+
+
+  /*
+   * dataInputNodes <-- formulae latch datainput nodes
+   */
+  latchNodeList = lsCreate();
+  PartGetLatchListFromCtlAndLtl(network, ctlArray, ltlArray,
+				fairArray, latchNodeList, TRUE);
+  dataInputNodes = st_init_table( st_ptrcmp, st_ptrhash );
+  lsForEachItem(latchNodeList, gen, node) {
+    Ntk_Node_t *dataInputNode = Ntk_LatchReadDataInput(node);
+    if (!st_is_member(dataInputNodes, (char *)dataInputNode))
+      st_insert(dataInputNodes, (char *)dataInputNode, NIL(char));
+  }
+  lsDestroy(latchNodeList, (void (*)(lsGeneric))0);
+
+
+ /*
+  * table from index to pointer and pointer to index
+  */
+  partSubInfo->arrayOfVertex = arrayOfVertex;
+  partSubInfo->numberOfVertex = array_n(arrayOfVertex);
+
+  indexToPtrInfo = st_init_table(st_numcmp, st_numhash);
+  ptrToIndexInfo = st_init_table(st_ptrcmp, st_ptrhash);
+
+  arrayForEachItem(Ntk_Node_t *, partSubInfo->arrayOfVertex, i, node){
+    st_insert(indexToPtrInfo, (char *)(long)i, (char *)node);
+    st_insert(ptrToIndexInfo, (char *)node, (char *)(long)i);
+  }
+
+  check = array_alloc(int, partSubInfo->numberOfVertex);
+  for(i=0;i<partSubInfo->numberOfVertex;i++){
+    array_insert(int, check, i, 0);
+  }
+
+
+  leftNodes = partSubInfo->numberOfVertex;
+  arrayOfIndex = array_alloc(int, st_count(dataInputNodes));
+  result = array_alloc(Part_Subsystem_t *, 0);
+
+
+  /* 
+   * If (1) number of formula nodes is smaller than bound, or (2)
+   * strictBound is FALSE, or (3) dynamicIncrease is TRUE, create a
+   * subsystem and put all formula nodes in the sub-system
+   */
+  if ( !strictBound || st_count(dataInputNodes) <= partSubInfo->bound 
+       || dynamicIncrease ) {
+    int numNodesInFirstSubsys;
+
+    if (!strictBound || st_count(dataInputNodes) <= partSubInfo->bound)
+      numNodesInFirstSubsys = st_count(dataInputNodes);
+    else 
+      numNodesInFirstSubsys = partSubInfo->bound;
+
+    arrayOfNodes = array_alloc(Ntk_Node_t *, st_count(dataInputNodes));
+    i=0;
+    st_foreach_item(dataInputNodes, stGen, &node, NULL) {
+      if (i == numNodesInFirstSubsys) break;
+      st_lookup_int(ptrToIndexInfo, node, &index);
+      array_insert(int, check, index, 1);
+      array_insert(int, arrayOfIndex, i, index);
+      array_insert(Ntk_Node_t *, arrayOfNodes, i++, node);
+    }
+    sub = PartCreateSingleSubSystem(arrayOfNodes, network);
+    leftNodes -= array_n(arrayOfNodes);
+    array_insert_last(Part_Subsystem_t *, result, sub);
+    array_free(arrayOfNodes);
+
+    if (dynamicIncrease) {
+      /* the second subsystem <-- remaining latches in dataInputTable
+       * the thrid  subsystem <-- other COI latches
+       */
+      if ( dynamicAndDependency ) {
+	if ( st_count(dataInputNodes) == numNodesInFirstSubsys )
+	  array_insert_last(Part_Subsystem_t *, result, NIL(Part_Subsystem_t));
+	else {
+	  arrayOfNodes = array_alloc(Ntk_Node_t *, 0);
+	  i=0;
+	  st_foreach_item(dataInputNodes, stGen, &node, NULL) {
+	    st_lookup_int(ptrToIndexInfo, node, &index);
+	    if (array_fetch(int, check, index)==0){
+	      array_insert(int, check, index, 1);
+	      array_insert(int, arrayOfIndex, i, index);
+	      array_insert_last(Ntk_Node_t *, arrayOfNodes, node);
+	    }
+	  }
+	  sub = PartCreateSingleSubSystem(arrayOfNodes, network);
+	  leftNodes -= array_n(arrayOfNodes);
+	  array_insert_last(Part_Subsystem_t *, result, sub);
+	  array_free(arrayOfNodes);
+	}
+      }
+      
+      if (leftNodes > 0){
+	arrayOfNodes = array_alloc(Ntk_Node_t *, 0);
+	arrayForEachItem(Ntk_Node_t *, partSubInfo->arrayOfVertex, i, node){
+          if (array_fetch(int, check, i)==0)
+            array_insert_last(Ntk_Node_t *, arrayOfNodes, node);
+        }
+        sub = PartCreateSingleSubSystem(arrayOfNodes, network);
+	array_free(arrayOfNodes);
+      }else{
+	sub = NIL(Part_Subsystem_t);
+      }
+      array_insert_last(Part_Subsystem_t *, result, sub);
+
+      array_free(check);
+      array_free(arrayOfIndex);
+      st_free_table(ptrToIndexInfo);
+      st_free_table(indexToPtrInfo);
+      st_free_table(dataInputNodes);
+      return result;
+    } /*if dynamicIncrease*/
+
+  }else {
+    /*
+     * If we don't want to put all formula nodes in the 1st subsystem,
+     * we need to break them into several pieces.
+     */
+  }
+
+  /*
+   * get a affinity matrix (dependency matrix, correlation matrix)
+   */
+  arrayOfDependency = PartCreateDependencyMatrix(partSubInfo, 
+						 ptrToIndexInfo);
+
+  if (partSubInfo->corMethod == Part_CorrelationWithBDD)
+    arrayOfCorrelation = PartCreateCorrelationMatrixFromBDD(partSubInfo);
+  else if ((partSubInfo->corMethod == Part_CorrelationWithSupport) ||
+	   (partSubInfo->corMethod == Part_CorrelationDefault))
+    arrayOfCorrelation = PartCreateCorrelationMatrixFromSupport(partSubInfo);
+
+  arrayOfAffinity = PartCreateAffinityMatrix(arrayOfDependency,
+					     arrayOfCorrelation, 
+					     partSubInfo);
+  
+  if (partSubInfo->verbosity > 2 ){
+    fprintf(vis_stdout,"\nGrouping: Dependency\n");
+    fprintf(vis_stdout,"--------------------\n");
+    PartPrintArrayArray(arrayOfDependency, partSubInfo->numberOfVertex, 1);
+    fprintf(vis_stdout,"\nGrouping: Correlation\n");
+    fprintf(vis_stdout,"---------------------\n");
+    PartPrintArrayArray(arrayOfCorrelation, partSubInfo->numberOfVertex, 0);
+    fprintf(vis_stdout,"\nGrouping: Affinity\n");
+    fprintf(vis_stdout,"------------------\n");
+    PartPrintArrayArray(arrayOfAffinity, partSubInfo->numberOfVertex, 0);
+  }
+  FREE(arrayOfDependency);
+  FREE(arrayOfCorrelation);
+
+
+  /* If number of formula nodes are bigger than bound, break down into
+   * bounded sized subsystems.
+   */
+  if (st_count(dataInputNodes) > partSubInfo->bound && strictBound ){
+    tempCheck = array_alloc(int, partSubInfo->numberOfVertex);
+    tempCC = array_alloc(Ntk_Node_t *, partSubInfo->numberOfVertex);
+    for(i=0; i<partSubInfo->numberOfVertex; i++){
+      array_insert(int, tempCheck, i, 1);
+      array_insert(Ntk_Node_t *, tempCC, i, (Ntk_Node_t *)0);
+    }
+    i = 0;
+    st_foreach_item(dataInputNodes, stGen, &node, NULL) {
+      st_lookup_int(ptrToIndexInfo, node, &index);
+      array_insert(int, arrayOfIndex, i++, index);
+      array_insert(int, check, index, 1);
+      array_insert(int, tempCheck, index, 0);
+      array_insert(Ntk_Node_t *, tempCC, index, node);
+    }
+
+    numSeed = (int) ceil((double)st_count(dataInputNodes)/(double)(partSubInfo->bound));
+    arrayOfSeed = array_alloc(Ntk_Node_t *, numSeed);
+    seedLast = PartSelectNodeOfMinSupport(tempCC,
+					  tempCheck, partSubInfo);
+    array_insert(Ntk_Node_t *, arrayOfSeed, 0, seedLast);
+    for (i=1; i< numSeed; i++){
+      seedNext = PartSelectFarNode(seedLast, tempCC, tempCheck,
+				   arrayOfAffinity, ptrToIndexInfo);
+      array_insert(Ntk_Node_t *, arrayOfSeed, i, seedNext);
+      seedLast = seedNext;
+    }
+
+   /*
+    * Break formula nodes, put into table and insert into final result
+    */
+    arrayOfBreak = PartBreakingBigConnectedComponent(tempCC, tempCheck,
+          arrayOfSeed, arrayOfAffinity, partSubInfo, ptrToIndexInfo);
+    array_free(tempCheck);
+    array_free(tempCC);
+    array_free(arrayOfSeed);
+
+    assert(array_n(arrayOfBreak) > 0);
+    maxSize = -1;
+    maxIndex = -1; /* don't care value to suppress warning */
+    arrayForEachItem(array_t *, arrayOfBreak, i, arrayOfNodes){
+      if (array_n(arrayOfNodes)>maxSize){
+        maxIndex = i;
+        maxSize = array_n(arrayOfNodes);
+      }
+    }
+    arrayOfNodes = array_fetch(array_t *, arrayOfBreak, maxIndex);
+    sub = PartCreateSingleSubSystem(arrayOfNodes, network);
+    leftNodes -= array_n(arrayOfNodes);
+    array_insert_last(Part_Subsystem_t *, result, sub);
+    arrayForEachItem(array_t *, arrayOfBreak, i, arrayOfNodes){
+      if (i != maxIndex){
+        sub = PartCreateSingleSubSystem(arrayOfNodes, network);
+        leftNodes -= array_n(arrayOfNodes);
+        array_insert_last(Part_Subsystem_t *, result, sub);
+      }
+    }
+    PartArrayOfArrayFree(arrayOfBreak);
+  }/* if (st_count(dataInputNodes) > partSubInfo->bound && strictBound)*/
+  st_free_table(dataInputNodes);
+
+
+  /*
+   * Create new affinity matrix. Now new affinity is defined from
+   * sub-system(s) created above to left nodes.
+   */
+  arrayTemp = NIL(array_t);
+
+  if (leftNodes > 0){
+    arrayTemp = array_alloc(float, partSubInfo->numberOfVertex);
+    arrayForEachItem(int, arrayOfIndex, i, index){
+      for(j=0;j<partSubInfo->numberOfVertex;j++){
+        affinity = PartGetElementFromSymMatrix(arrayOfAffinity,index,j);
+        if (i==0){
+          array_insert(float, arrayTemp, j, affinity);
+        } else {
+           prevAffinity = array_fetch(float, arrayTemp, j);
+           array_insert(float, arrayTemp, j, affinity + prevAffinity);
+        }
+      }
+    }
+ 
+    array_free(arrayOfIndex);
+    FREE(arrayOfAffinity);
+
+    if (partSubInfo->verbosity > 2 ){
+      fprintf(vis_stdout,"\nGrouping:: combinded affinity\n");
+      fprintf(vis_stdout,"------------------\n");
+      arrayForEachItem(float, arrayTemp, i, affinity){
+        fprintf(vis_stdout, "%.10f ", affinity);
+      }
+      fprintf(vis_stdout, "\n");
+    }
+  }else{
+    array_free(arrayOfIndex);
+    FREE(arrayOfAffinity);
+  }
+     
+  /*
+   * Create sub-system by choosing a nodes with biggest new affinity
+   */
+  while( leftNodes > 0 ){
+    numIncluded = 0;
+    arrayOfVertex = array_alloc(Ntk_Node_t *, 0);
+    while ((numIncluded < partSubInfo->bound) && (leftNodes > 0)){
+     /*
+      * The node with maximum affinity to formula nodes is included
+      * in next sub-system until number of nodes reaches to bound
+      */
+      prevAffinity = -1.0;
+      maxIndex = 0;
+      arrayForEachItem( float, arrayTemp, i, affinity){
+        if ( array_fetch(int, check, i) != 1 ){
+          if (affinity >= prevAffinity){
+            prevAffinity = affinity;
+            maxIndex = i;
+          }
+        }
+      }
+      st_lookup(indexToPtrInfo, (char *)(long)maxIndex, &node);
+      array_insert_last(Ntk_Node_t *, arrayOfVertex, node);
+      array_insert(int, check, maxIndex, 1);
+      numIncluded++;
+      leftNodes--;
+    }
+    sub = PartCreateSingleSubSystem(arrayOfVertex, network);
+    array_free(arrayOfVertex);
+    array_insert_last(Part_Subsystem_t *, result, sub);
+  }
+
+  array_free(check);
+  if (arrayTemp != NIL(array_t))
+    array_free(arrayTemp);
+  st_free_table(ptrToIndexInfo);
+  st_free_table(indexToPtrInfo);
+
+
+  if (partSubInfo->verbosity >= 2){
+    Part_Subsystem_t *sub;
+    char *latchName;
+    st_generator *stGen;
+
+    fprintf(vis_stdout,"\nGrouping: List of subsytem latches\n");
+    fprintf(vis_stdout,"----------------------------------\n\n");
+    arrayForEachItem(Part_Subsystem_t *, result, i, sub){
+      fprintf(vis_stdout,"[Subsystem %3d]\n",i);
+      st_foreach_item(sub->vertexNameTable, stGen, &latchName, NIL(char *) ){
+        fprintf(vis_stdout,"%s\n",latchName);
+      }
+      fprintf(vis_stdout,"\n");
+    }
+  }
+
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Create the vertex dependency matrix]
+
+  Description [vertex 1 depends on vertex 2, if the support of the function
+  attatched to vertex 1 contains vertex 2]
+
+  SideEffects []
+
+******************************************************************************/
+static char *
+PartCreateDependencyMatrix(
+  Part_SubsystemInfo_t *partSubInfo,
+  st_table *ptrToIndex)
+{
+  char		*result;
+  array_t	*arrayNodeFrom;
+  int		i, j, k;
+  Ntk_Node_t	*node, *latchInputNode;
+  array_t	*arrayOfSupport;
+  Ntk_Network_t	*network = partSubInfo->network;
+  int		index, size;
+
+  size = partSubInfo->numberOfVertex;
+  result = ALLOC(char, size * size);
+  (void)memset((void *)result, 0, sizeof(char) * size * size);
+
+  for (i = 0; i < partSubInfo->numberOfVertex; i++) {
+    node = array_fetch(Ntk_Node_t *, partSubInfo->arrayOfVertex, i);
+    arrayNodeFrom = array_alloc(Ntk_Node_t *, 1);
+    array_insert(Ntk_Node_t *, arrayNodeFrom, 0, node);
+    arrayOfSupport = Ntk_NodeComputeCombinationalSupport(network,
+							 arrayNodeFrom, 
+							 FALSE);
+    array_free(arrayNodeFrom);
+    arrayForEachItem(Ntk_Node_t *, arrayOfSupport, j, node) {
+      if (!Ntk_NodeTestIsLatch(node))
+	continue;
+      latchInputNode = Ntk_LatchReadDataInput(node);
+      if (st_lookup_int(ptrToIndex, (char *)latchInputNode, &k)) {
+	index = i * partSubInfo->numberOfVertex + k;
+	result[index] = 1;
+      } else {
+	fprintf(vis_stderr,
+		"** part error: can't find the latch input index.\n");
+      }
+    }
+    array_free(arrayOfSupport);
+  }
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Create the latch Correlation Matrix]
+
+  SideEffects []
+
+  SeeAlso     [Part_SubsystemInfo]
+******************************************************************************/
+static float *
+PartCreateCorrelationMatrixFromSupport(
+  Part_SubsystemInfo_t *partSubInfo)
+{
+  int i, j;
+  float *result;
+  float correlation;
+  array_t *arrayOfSupport;
+  st_table *tableOfSupport;
+  array_t *arrayOfSupportTable;
+  array_t *arrayNodeFrom;
+  Ntk_Node_t *nodeFrom, *node;
+  Ntk_Network_t *network = partSubInfo->network;
+  int index;
+
+  result = ALLOC(float,
+	 partSubInfo->numberOfVertex * (partSubInfo->numberOfVertex - 1) / 2);
+
+  arrayOfSupportTable = array_alloc(st_table *, partSubInfo->numberOfVertex);
+
+  for (i = 0; i < partSubInfo->numberOfVertex; i++) {
+    nodeFrom = array_fetch(Ntk_Node_t *, partSubInfo->arrayOfVertex, i);
+    arrayNodeFrom = array_alloc(Ntk_Node_t *, 1);
+    array_insert(Ntk_Node_t *, arrayNodeFrom, 0, nodeFrom);
+    arrayOfSupport = Ntk_NodeComputeCombinationalSupport(network,
+							 arrayNodeFrom, 
+							 FALSE);
+    array_free(arrayNodeFrom);
+    tableOfSupport = st_init_table(st_ptrcmp, st_ptrhash);
+    arrayForEachItem(Ntk_Node_t *, arrayOfSupport, j, node) {
+      st_insert(tableOfSupport, (char *)node, (char *)NULL);
+    }
+    array_free(arrayOfSupport);
+    array_insert(st_table *, arrayOfSupportTable, i, tableOfSupport);
+  }
+
+  for (i = 1; i < partSubInfo->numberOfVertex; i++) {
+    for (j = 0; j < i; j++) {
+      correlation = PartVertexComputeCorrelation(i, j, arrayOfSupportTable,
+			partSubInfo);
+      index = i * (i - 1) / 2 + j;
+      result[index] = correlation;
+    }
+  }/* end of for */
+
+  for (i = 0; i < partSubInfo->numberOfVertex; i++)
+    st_free_table(array_fetch(st_table *, arrayOfSupportTable, i));
+  array_free(arrayOfSupportTable);
+
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Create the latch Correlation Matrix]
+
+  SideEffects []
+
+  SeeAlso     [Part_SubsystemInfo]
+******************************************************************************/
+static float *
+PartCreateCorrelationMatrixFromBDD(
+  Part_SubsystemInfo_t *partSubInfo)
+{
+  int		i, j;
+  float		*result;
+  array_t	*agreeArray;
+  array_t	*arrayOfMddArray;
+  float		agreement;
+  float		correlation = 0.0;
+  char		*name;
+  Ntk_Node_t	*node;
+  Mvf_Function_t *mvf;
+  vertex_t	*vertex;
+  graph_t	*partition = Part_NetworkReadPartition(partSubInfo->network);
+  mdd_manager	*mddmgr = PartPartitionReadMddManager(partition);
+  int		index;
+
+  result = ALLOC(float,
+	 partSubInfo->numberOfVertex * (partSubInfo->numberOfVertex - 1) / 2);
+
+  arrayOfMddArray = array_alloc(array_t *, partSubInfo->numberOfVertex);
+  for (i = 0; i < partSubInfo->numberOfVertex; i++) {
+    node = array_fetch(Ntk_Node_t *, partSubInfo->arrayOfVertex, i);
+    name = Ntk_NodeReadName(node);
+    vertex = Part_PartitionFindVertexByName(partition, name);
+    mvf = Part_VertexReadFunction(vertex);
+    array_insert(array_t *, arrayOfMddArray, i, (array_t *)mvf);
+  }
+
+  for (i = 1; i < partSubInfo->numberOfVertex; i++) {
+    for (j = 0; j < i; j++) {
+      int k;
+      agreeArray = PartVertexComputeAgreement(mddmgr, i, j, arrayOfMddArray);
+      correlation = 0.0;
+      arrayForEachItem(float, agreeArray, k, agreement) {
+	correlation += (float)pow(1.0 - 4.0 * agreement * (1.0 - agreement),
+				    partSubInfo->cor_factor);
+      }
+      correlation /= (float)array_n(agreeArray);
+      array_free(agreeArray);
+      index = i * (i - 1) / 2 + j;
+      result[index] = correlation;
+    }
+  }/* end of for */
+
+  array_free(arrayOfMddArray);
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the latch Correlation between two vertices]
+
+  SideEffects []
+
+  SeeAlso     [Part_SubsystemInfo]
+******************************************************************************/
+static float
+PartVertexComputeCorrelation(
+  int index1,
+  int index2,
+  array_t *arrayOfInputSupportTable,
+  Part_SubsystemInfo_t *partSubInfo)
+{
+  st_generator *stGen;
+  st_table *inputSupportTable1;
+  st_table *inputSupportTable2;
+  int sameSupportCount;
+  float correlation;
+  int inputSupportCount;
+  Ntk_Node_t *node;
+
+  sameSupportCount = 0;
+  inputSupportTable1 = array_fetch(st_table *, arrayOfInputSupportTable,
+				index1);
+  inputSupportTable2 = array_fetch(st_table *, arrayOfInputSupportTable,
+				index2);
+
+  st_foreach_item(inputSupportTable1, stGen, &node, NULL) {
+    if (st_is_member(inputSupportTable2, node)) {
+      sameSupportCount++;
+    }
+  }
+
+  inputSupportCount = st_count(inputSupportTable1) +
+			st_count(inputSupportTable2) - sameSupportCount;
+  if (inputSupportCount != 0) {
+    correlation = (float)pow((double)sameSupportCount /
+			     (double)inputSupportCount,
+			     (double)partSubInfo->cor_factor);
+  } else {
+    correlation = 0.0;
+  }
+  return correlation;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the latch Correlation between two vertices]
+
+  SideEffects []
+
+  SeeAlso     [Part_SubsystemInfo]
+******************************************************************************/
+static array_t *
+PartVertexComputeAgreement(
+  mdd_manager *mddMgr,
+  int index1,
+  int index2,
+  array_t *arrayOfMddArray)
+{
+  int i, j;
+  float agreement;
+  mdd_t *mddFrom, *mddTo;
+  array_t *mddArrayFrom, *mddArrayTo;
+  array_t *agreeArray = array_alloc(float, 0);
+
+  mddArrayFrom = array_fetch(array_t *, arrayOfMddArray, index1);
+  mddArrayTo   = array_fetch(array_t *, arrayOfMddArray, index2);
+  arrayForEachItem(mdd_t *, mddArrayFrom, i, mddFrom) {
+    arrayForEachItem(mdd_t *, mddArrayTo, j, mddTo) {
+      agreement = bdd_correlation(mddFrom, mddTo);
+      array_insert_last(float, agreeArray, agreement);
+    }
+  }
+
+  return agreeArray;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Create the latch Affinity Matrix]
+
+  Description [Affinity is a convex function of connectivity and correlation.
+  For circuits which are more primary input sensitive, the latch
+  correlation seems to be more important, while for circuit which are more
+  state sensitive, the latch connectivity seems to be more important.The
+  aff_factor controls the weight of two sides. The bigger the aff_factor is,
+  the more weight is given to the latch connectivity.]
+
+  SideEffects [Each row element of arrayOfCorreletion is freed]
+
+  SeeAlso     [Part_SubsystemInfo]
+******************************************************************************/
+static float *
+PartCreateAffinityMatrix(
+  char *arrayOfDependency,
+  float *arrayOfCorrelation,
+  Part_SubsystemInfo_t *partSubInfo)
+{
+  float *result;
+  int i, j;
+  float dep1, dep2;
+  float connectivity = 0.0;
+  float correlation = 0.0;
+  float affinity;
+  int	index;
+
+  result = ALLOC(float,
+	 partSubInfo->numberOfVertex * (partSubInfo->numberOfVertex - 1) / 2);
+
+  for (i = 1; i < partSubInfo->numberOfVertex; i++) {
+    for (j = 0; j < i; j++) {
+      if (arrayOfDependency) {
+	dep1 = dep2 = 0.0;
+	index = i * partSubInfo->numberOfVertex + j;
+	if (arrayOfDependency[index] == 1)
+	dep1 = 1.0;
+	index = j * partSubInfo->numberOfVertex + i;
+	if (arrayOfDependency[index] == 1)
+	dep2 = 1.0;
+	connectivity = (dep1 + dep2 +
+			(partSubInfo->con_factor - 2) * dep1 * dep2) /
+			partSubInfo->con_factor;
+      } else
+	connectivity = 0.0;
+
+      if (arrayOfCorrelation)
+	correlation = PartGetElementFromSymMatrix(arrayOfCorrelation, i, j);
+      else
+	correlation = 0.0;
+
+     /*
+      * affinity is a convex function of connectivity and correlation
+      */
+      affinity = partSubInfo->aff_factor * connectivity +
+		(1.0 - partSubInfo->aff_factor) * correlation;
+      index = i * (i - 1) / 2 + j;
+      result[index] = affinity;
+    }
+  }
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Gets Conected Components of vertices]
+
+  Description [The affinity matrix is considered as graph, and higher value than
+  threshold is considered edge between two verticies. And connected components
+  are found by searching the graph]
+
+  SideEffects []
+
+  SeeAlso     []
+******************************************************************************/
+static array_t *
+PartGetConnectedComponent(
+  float *arrayOfAffinity,
+  Part_SubsystemInfo_t *partSubInfo,
+  st_table *indexToPtr)
+{
+  array_t  *arrayOfCCs; /* array of connected component */
+  array_t  *connectedComponent;
+  array_t  *arrayOfFrom;
+  array_t  *arrayOfCCIndex; /* keep ccId of each vertex */
+  float    affinity, affmax;
+  float   affsum, density, nonZeroCount;
+  int      next; /* serching connected component from this index */
+  int      ccId; /* each connected component gets its own ccId */
+  int      ccIndex;
+  int      i, size;
+  Ntk_Node_t *node;
+
+  next = 0;   /* keep the smallest index of vertex not included in CC */
+  ccId = 0;   /* give ccId to each CC */
+  affmax = 0.0;
+  affsum = 0.0;
+  nonZeroCount = 0;
+
+  arrayOfCCIndex = array_alloc(int, partSubInfo->numberOfVertex);
+ /*
+  * Initially, all vertecies are included in one component
+  */
+  for (i = 0; i < partSubInfo->numberOfVertex; i++) {
+    array_insert(int, arrayOfCCIndex, i, 0);
+  }
+ /*
+  * If the threshold is not defined, get an average of affinity in the matrix
+  * and a density. Threshold is assigned between average of affinity and
+  * the maximum value of affinity according to density. If the matrix is
+  * dense(sparse), threshold goes up(goes down).
+  */
+  if (partSubInfo->threshold == 0.0) {
+    size = partSubInfo->numberOfVertex * (partSubInfo->numberOfVertex - 1) / 2;
+    for (i = 0; i < size; i++) {
+      affinity = arrayOfAffinity[i];
+      if (affmax < affinity) {
+	affmax = affinity;
+      }
+      if (affinity > 0.0) {
+	nonZeroCount += 1.0;
+      }
+      affsum += affinity;
+    }
+    density = nonZeroCount / pow((double)partSubInfo->numberOfVertex, 2.0);
+    partSubInfo->threshold = (float)((affsum / nonZeroCount) +
+				(affmax - affsum / nonZeroCount) * density);
+  }
+
+ /*
+  * Get a connected component from the vertex which is pointed by 'next'
+  * with its index. The 'next' is updated during searching CC in the function
+  * PartFindCC
+  */
+  while (next < partSubInfo->numberOfVertex) {
+    ccId++;
+    array_insert(int, arrayOfCCIndex, next, ccId);
+    if (next == partSubInfo->numberOfVertex - 1) {
+      break;
+    }
+    arrayOfFrom = array_alloc(int, 1);
+    array_insert(int, arrayOfFrom, 0, next);
+    PartFindCC(&next, &ccId, arrayOfCCIndex, arrayOfAffinity, arrayOfFrom,
+		partSubInfo);
+  }
+
+ /*
+  * initialize arrayOfCCs, which is the result.
+  */
+  arrayOfCCs = array_alloc(array_t *, ccId);
+  for (i = 0; i < ccId; i++) {
+    connectedComponent = array_alloc(Ntk_Node_t *, 0);
+    array_insert(array_t *, arrayOfCCs, i, connectedComponent);
+  }
+
+ /*
+  * change index to vertex pointer and insert into each CC
+  */
+  arrayForEachItem(int, arrayOfCCIndex, i, ccIndex) {
+    st_lookup(indexToPtr, (char *)(long)i, &node);
+    connectedComponent = array_fetch(array_t *, arrayOfCCs, ccIndex-1);
+    array_insert_last(Ntk_Node_t *, connectedComponent, node);
+
+  }
+  array_free(arrayOfCCIndex);
+  return arrayOfCCs;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Get a conected component of vertices.]
+
+  SideEffects [The connected component is searched from 'arrayFrom' and
+  each vertex in that connected component gets the index of the current
+  connected component. And 'next' points the next possible vertex]
+
+  SeeAlso     []
+******************************************************************************/
+static void
+PartFindCC(
+  int *next,
+  int *ccId,
+  array_t *arrayOfCCIndex,
+  float *arrayOfAffinity,
+  array_t *arrayOfFrom,
+  Part_SubsystemInfo_t *partSubInfo)
+{
+  int i, j, from;
+  int arrayInd;
+  float connected;
+  array_t *arrayOfReached;
+
+ /*
+  * Update next in order to let next keep the smallest vertex index which
+  * is not traversed.
+  */
+  (*next)++;
+  while (1) {
+    if (*next == partSubInfo->numberOfVertex) {
+      array_free(arrayOfFrom);
+      return;
+    }
+    if (array_fetch(int, arrayOfCCIndex, *next) != 0) {
+      (*next)++;
+    } else {
+      break;
+    }
+  }
+
+  arrayOfReached = array_alloc(int, 0); /* Reached set from arrayOfFrom */
+
+  /*
+  * Find all vertecies which can be traversed from arrayOfFrom
+  * and update next
+  */
+  while (array_n(arrayOfFrom) > 0) {
+    arrayForEachItem(int, arrayOfFrom, i, from) {
+      for (j = 0; j < partSubInfo->numberOfVertex; j++) {
+	connected = PartGetElementFromSymMatrix(arrayOfAffinity, from, j);
+	arrayInd = array_fetch(int, arrayOfCCIndex, j);
+	if (connected > partSubInfo->threshold && arrayInd == 0) {
+	  array_insert_last(int, arrayOfReached, j);
+	  array_insert(int, arrayOfCCIndex, j, *ccId);
+	  if (*next == j) {
+	    (*next)++;
+	    while (1) {
+	      if (*next == partSubInfo->numberOfVertex) {
+		array_free(arrayOfReached);
+		array_free(arrayOfFrom);
+		return;
+	      }
+	      if (array_fetch(int, arrayOfCCIndex, *next) != 0) {
+		(*next)++;
+	      } else {
+		break;
+	      }
+	    }/* end of while */
+	  }/* end if */
+	}
+      }/* end for */
+    }/* end of arrayForEachItem(arrayOfFrom) */
+    array_free(arrayOfFrom);
+    arrayOfFrom = arrayOfReached;  /* Traverse with new reached set */
+    arrayOfReached = array_alloc(int, 0);
+  }/* end of while */
+  array_free(arrayOfFrom);
+  array_free(arrayOfReached);
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Gets an sub-partitions with bounded size]
+
+  Description [Break the connected component which has more verteices than
+  bound and aggregate the connected components which have less vertecies
+  than bound.]
+
+  SideEffects []
+
+  SeeAlso     []
+******************************************************************************/
+static array_t *
+PartBreakingAggregating(
+  array_t	*arrayOfInit,
+  float		*arrayOfAffinity,
+  Part_SubsystemInfo_t *partSubInfo,
+  st_table	*ptrToIndex,
+  char		*arrayOfDependency)
+{
+  array_t	*arrayOfAggregate;
+  array_t	*arrayOfSeed;
+  array_t	*arrayOfSmall;
+  array_t	*arrayOfBreak;
+  array_t	*arrayOfFinal;
+  array_t	*arrayOfCCVertex;
+  array_t	*arrayVertex;
+  array_t	*arrayOfNew;
+  array_t	*cc;
+  array_t	*ccCheck; /* check cc which is included in final result */
+  float		*groupDependency;
+  st_table	*tableOfCC;
+  float		groupDep;
+  int		i, j, k, l;
+  array_t	*arrayOfLatchNames;
+  char		*name;
+  Part_Subsystem_t *sub;
+  Part_Subsystem_t *subIn;
+  Part_Subsystem_t *subOut;
+  Ntk_Node_t	*seedlast, *seednext, *node;
+  char		*funcName;
+
+  arrayOfSmall = array_alloc(array_t *, 0);
+  arrayOfFinal = array_alloc(Part_Subsystem_t *, 0);
+  arrayOfCCVertex = array_alloc(array_t *, 0);
+
+  if (partSubInfo->bound == 0) {
+    partSubInfo->bound = partSubInfo->numberOfVertex / array_n(arrayOfInit);
+  }
+
+  arrayForEachItem(array_t *, arrayOfInit, i, cc) {
+    if (array_n(cc) > partSubInfo->bound) {
+     /*
+      * If cc has more vertecies than bound, calculate how many seeds are needed
+      * and get those seeds which are far away from each others
+      */
+      ccCheck = array_alloc(int, array_n(cc));
+      for (j = 0; j < array_n(cc); j++) {
+	array_insert(int, ccCheck, j, 0);
+      }
+
+     /*
+      * The first seed is the vertex which has the smallest support and
+      * choose the next vertex which is the farthest from last seed
+      */
+      arrayOfSeed = array_alloc(Ntk_Node_t *, 0);
+      seedlast = PartSelectNodeOfMinSupport(cc, ccCheck, partSubInfo);
+      array_insert_last(Ntk_Node_t *, arrayOfSeed, seedlast);
+      for (j = 1; j < ceil((double)array_n(cc) / (double)(partSubInfo->bound));
+	   j++) {
+	seednext = PartSelectFarNode(seedlast, cc, ccCheck, arrayOfAffinity,
+			ptrToIndex);
+	array_insert_last(Ntk_Node_t *, arrayOfSeed, seednext);
+	seedlast = seednext;
+      }
+     /*
+      * Break big CC, put into table and insert into final result
+      */
+      arrayOfBreak = PartBreakingBigConnectedComponent(cc, ccCheck,
+	    arrayOfSeed, arrayOfAffinity, partSubInfo, ptrToIndex);
+      array_free(ccCheck);
+      array_free(arrayOfSeed);
+
+      arrayForEachItem(array_t *, arrayOfBreak, j, arrayOfNew) {
+	if (array_n(arrayOfNew) == partSubInfo->bound) {
+	  tableOfCC = st_init_table(strcmp, st_strhash);
+	  arrayVertex = array_alloc(Ntk_Node_t *, array_n(arrayOfNew));
+	  arrayForEachItem(Ntk_Node_t *, arrayOfNew, k, node) {
+	    funcName = Ntk_NodeReadName(node);
+	    if (st_lookup(partSubInfo->dupLatchTable, funcName,
+		&arrayOfLatchNames)) {
+	      arrayForEachItem(char *, arrayOfLatchNames, l, name) {
+		st_insert(tableOfCC, (char *)name, (char *)NULL);
+	      }
+	    } else {
+	      if (st_lookup(partSubInfo->latchNameTable, (char *)funcName,
+			(char **)&name)) {
+		st_insert(tableOfCC, (char *)name, (char *)NULL);
+	      } else
+		error_append("can't find the latch name.");
+	    }
+	    array_insert(Ntk_Node_t *, arrayVertex, k, node);
+	  }
+	  sub = ALLOC(Part_Subsystem_t, 1);
+	  sub->vertexNameTable = tableOfCC;
+	  sub->subsystemFanIn = array_alloc(int, 0);
+	  sub->subsystemFanOut = array_alloc(int, 0);
+	  array_insert_last(Part_Subsystem_t *, arrayOfFinal, sub);
+	  array_insert_last(array_t *, arrayOfCCVertex, arrayVertex);
+	  array_free(arrayOfNew);
+	} else {
+	  array_insert_last(array_t *, arrayOfSmall, arrayOfNew);
+	}
+      }/* end of arrayForEachItem(arrayOfBreak) */
+      array_free(arrayOfBreak);
+      array_free(cc);
+    } else if (array_n(cc) < partSubInfo->bound) {
+     /*
+      * If cc has less nodes than bound, put into arrayOfSmall
+      */
+      array_insert_last(array_t *, arrayOfSmall, cc);
+    } else {
+     /*
+      * If cc has same number of verteices as bound, put into table and
+      * insert into final result
+      */
+      tableOfCC = st_init_table(strcmp, st_strhash);
+      arrayVertex = array_alloc(Ntk_Node_t *, array_n(cc));
+      arrayForEachItem(Ntk_Node_t *, cc, j, node) {
+	funcName = Ntk_NodeReadName(node);
+	if (st_lookup(partSubInfo->dupLatchTable, funcName,
+		&arrayOfLatchNames)) {
+	  arrayForEachItem(char *, arrayOfLatchNames, l, name) {
+	    st_insert(tableOfCC, (char *)name, (char *)NULL);
+	  }
+	} else {
+	  if (st_lookup(partSubInfo->latchNameTable, (char *)funcName,
+		(char **)&name)) {
+	    st_insert(tableOfCC, (char *)name, (char *)NULL);
+	  } else
+	    error_append("can't find the latch name.");
+	}
+	array_insert(Ntk_Node_t *, arrayVertex, j, node);
+      }
+      sub = ALLOC(Part_Subsystem_t, 1);
+      sub->vertexNameTable = tableOfCC;
+      sub->subsystemFanIn = array_alloc(int, 0);
+      sub->subsystemFanOut = array_alloc(int, 0);
+      array_insert_last(Part_Subsystem_t *, arrayOfFinal, sub);
+      array_insert_last(array_t *, arrayOfCCVertex, arrayVertex);
+      array_free(cc);
+    }
+  }
+
+ /*
+  * aggregate small cc, put into table and insert into final resault
+  */
+  arrayOfAggregate = PartAggregating(arrayOfSmall, arrayOfAffinity,
+			partSubInfo, ptrToIndex);
+
+  array_free(arrayOfSmall);
+
+  arrayForEachItem(array_t *, arrayOfAggregate, i, arrayOfNew) {
+    tableOfCC = st_init_table(strcmp, st_strhash);
+    arrayVertex = array_alloc(Ntk_Node_t *, array_n(arrayOfNew));
+    arrayForEachItem(Ntk_Node_t *, arrayOfNew, j, node) {
+      funcName = Ntk_NodeReadName(node);
+      if (st_lookup(partSubInfo->dupLatchTable, funcName,
+		    &arrayOfLatchNames)) {
+	arrayForEachItem(char *, arrayOfLatchNames, l, name) {
+	  st_insert(tableOfCC, (char *)name, (char *)NULL);
+	}
+      } else {
+	if (st_lookup(partSubInfo->latchNameTable, (char *)funcName,
+		(char **)&name)) {
+	  st_insert(tableOfCC, (char *)name, (char *)NULL);
+	} else
+	  error_append("can't find the latch name.");
+      }
+      array_insert(Ntk_Node_t *, arrayVertex, j, node);
+    }
+    sub = ALLOC(Part_Subsystem_t, 1);
+    sub->vertexNameTable = tableOfCC;
+    sub->subsystemFanIn = array_alloc(int, 0);
+    sub->subsystemFanOut = array_alloc(int, 0);
+    array_insert_last(Part_Subsystem_t *, arrayOfFinal, sub);
+    array_insert_last(array_t *, arrayOfCCVertex, arrayVertex);
+    array_free(arrayOfNew);
+  }/* end of arrayForEachItem(arrayOfAggregate) */
+
+  array_free(arrayOfAggregate);
+
+ /*
+  * Get group dependency, which is dependency between two subsystems from
+  * dependency between vertecies
+  */
+  groupDependency = PartGetGroupMatrixRegular(arrayOfCCVertex,
+			arrayOfDependency, ptrToIndex,
+			partSubInfo->numberOfVertex);
+
+  if (partSubInfo->verbosity >= 2) {
+    int index;
+    fprintf(vis_stdout, "\nGrouping: Group Dependency\n");
+    fprintf(vis_stdout, "--------------------------\n");
+    for (i = 0; i < array_n(arrayOfCCVertex); i++) {
+      for (j = 0; j < array_n(arrayOfCCVertex); j++) {
+	index = i * array_n(arrayOfCCVertex) + j;
+	fprintf(vis_stdout, "%4.3f ", groupDependency[index]);
+      }
+      fprintf(vis_stdout, "\n");
+    }
+  }
+
+  for (i = 0; i < array_n(arrayOfCCVertex); i++) {
+    subIn = array_fetch(Part_Subsystem_t *, arrayOfFinal, i);
+    for (j = 0; j < array_n(arrayOfCCVertex); j++) {
+      subOut = array_fetch(Part_Subsystem_t *, arrayOfFinal, j);
+      if (i != j) {
+	int	index;
+
+	index = i * array_n(arrayOfCCVertex) + j;
+	groupDep = groupDependency[index];
+	if (groupDep > 0.0) {
+	  array_insert_last(int, subIn ->subsystemFanIn, j);
+	  array_insert_last(int, subOut->subsystemFanOut, i);
+	}
+      }
+    }
+  }
+  PartArrayOfArrayFree(arrayOfCCVertex);
+  FREE(groupDependency);
+  return arrayOfFinal;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Create subsystems accoring to arrayOfGroupIndex]
+
+  Description [Each latch data input L(i) in array arrayOfLatchDataInputNamesi
+  is put in I(i)'th subsystem. I is arrayOfGroupIndex. Index should start from
+  0 to n as sequence.]
+
+  SideEffects []
+
+  SeeAlso     []
+******************************************************************************/
+static array_t *
+PartCreateSubSystemWithGroupIndex(
+  Part_SubsystemInfo_t *partSubInfo,
+  array_t *arrayOfLatchNames,
+  array_t *arrayOfGroupIndex)
+{
+  int		i, j;
+  array_t	*result;
+  char		*latchName;
+  array_t	*arrayOfGroupVertex;
+  array_t	*arrayOfVertex;
+  array_t	*arrayOfLatchDataInputNames;
+  Ntk_Node_t	*node, *latchNode, *latchInputNode;
+  Part_Subsystem_t *sub;
+  st_table	*groupIndexTable;
+  st_table	**faninIndexTable, **fanoutIndexTable;
+  char		*name;
+  array_t	*arrayOfSupport;
+  st_generator	*stGen;
+  int		nLatches;
+  int		nGroups = 0;
+  int		preIndex, newIndex;
+  long		index;
+  char		*otherLatchName;
+  array_t	*latchNameArray;
+
+  nLatches = array_n(arrayOfLatchNames);
+
+  /* reassign group index with counting the number of groups */
+  groupIndexTable = st_init_table(st_numcmp, st_numhash);
+  preIndex = -1;
+  arrayForEachItem(int, arrayOfGroupIndex, i, index) {
+    if (index == preIndex ||
+	st_lookup_int(groupIndexTable, (char *)index, &newIndex)) {
+      if (index != newIndex)
+	array_insert(int, arrayOfGroupIndex, i, newIndex);
+    } else {
+      st_insert(groupIndexTable, (char *)index, (char *)(long)nGroups);
+      newIndex = nGroups++;
+      if (index != newIndex)
+	array_insert(int, arrayOfGroupIndex, i, newIndex);
+    }
+    preIndex = (int) index;
+  }
+  st_free_table(groupIndexTable);
+
+  groupIndexTable = st_init_table(strcmp, st_strhash);
+  faninIndexTable = ALLOC(st_table *, nGroups);
+  fanoutIndexTable = ALLOC(st_table *, nGroups);
+  for (i = 0; i < nGroups; i++) {
+    faninIndexTable[i] = st_init_table(st_numcmp, st_numhash);
+    fanoutIndexTable[i] = st_init_table(st_numcmp, st_numhash);
+  }
+
+  /* makes an array of latch input names from latch names */
+  arrayOfLatchDataInputNames = array_alloc(char *, 0);
+  arrayForEachItem(char *, arrayOfLatchNames, i, latchName) {
+    latchNode = Ntk_NetworkFindNodeByName(partSubInfo->network, latchName);
+    latchInputNode = Ntk_LatchReadDataInput(latchNode);
+    name = Ntk_NodeReadName(latchInputNode);
+    array_insert_last(char *, arrayOfLatchDataInputNames, name);
+  }
+
+  result = array_alloc(Part_Subsystem_t *, nGroups);
+  arrayOfGroupVertex = array_alloc(array_t *, nGroups);
+
+  /* creates subsystems */
+  for (i = 0; i < nGroups; i++) {
+    sub = ALLOC(Part_Subsystem_t, 1);
+    sub->vertexNameTable = st_init_table(strcmp, st_strhash);
+    sub->subsystemFanIn = array_alloc(int, 0);
+    sub->subsystemFanOut = array_alloc(int, 0);
+    arrayOfVertex = array_alloc(Ntk_Node_t *, 0);
+    array_insert(Part_Subsystem_t *, result, i, sub);
+    array_insert(array_t *, arrayOfGroupVertex, i, arrayOfVertex);
+  }
+
+  /* makes group index table and fills in the vertex name table */
+  for (i = 0; i < nLatches; i++) {
+    index = (long) array_fetch(int, arrayOfGroupIndex, i);
+    name = array_fetch(char *, arrayOfLatchDataInputNames, i);
+    latchName = array_fetch(char *, arrayOfLatchNames, i);
+
+    sub = array_fetch(Part_Subsystem_t *, result, (int) index);
+    latchNode = Ntk_NetworkFindNodeByName(partSubInfo->network, latchName);
+    latchName = Ntk_NodeReadName(latchNode);
+    st_insert(sub->vertexNameTable, (char *)latchName, (char *)NULL);
+
+    if (st_lookup(partSubInfo->latchNameTable, name, &otherLatchName)) {
+      if (st_lookup(partSubInfo->dupLatchTable, name, &latchNameArray)) {
+	array_insert_last(char *, latchNameArray, latchName);
+      } else {
+	latchNameArray = array_alloc(char *, 0);
+	array_insert_last(char *, latchNameArray, otherLatchName);
+	array_insert_last(char *, latchNameArray, latchName);
+	st_insert(partSubInfo->dupLatchTable, name, latchNameArray);
+      }
+      continue;
+    }
+
+    st_insert(partSubInfo->latchNameTable, name, latchName);
+    st_insert(groupIndexTable, name, (char *)index);
+
+    arrayOfVertex = array_fetch(array_t *, arrayOfGroupVertex, (int)index);
+    node = Ntk_NetworkFindNodeByName(partSubInfo->network, name);
+    array_insert_last(Ntk_Node_t *, arrayOfVertex, node);
+  }
+
+  /* computes fanin and fanout table for each group */
+  for (i = 0; i < nGroups; i++) {
+    arrayOfVertex = array_fetch(array_t *, arrayOfGroupVertex, i);
+    arrayOfSupport = Ntk_NodeComputeCombinationalSupport(partSubInfo->network,
+	arrayOfVertex, FALSE);
+    arrayForEachItem(Ntk_Node_t *, arrayOfSupport, j, node) {
+      if (!Ntk_NodeTestIsLatch(node))
+	continue;
+      name = Ntk_NodeReadName(Ntk_LatchReadDataInput(node));
+      if (st_lookup(groupIndexTable, name, &index)) {
+	if (index == i)
+	  continue;
+	st_insert(faninIndexTable[i], (char *)index, NIL(char));
+	st_insert(fanoutIndexTable[index], (char *)(long)i, NIL(char));
+      }
+    }
+    array_free(arrayOfSupport);
+  }
+
+  /* makes fanin and fanout array for each subsystem */
+  for (i = 0; i < nGroups; i++) {
+    sub = array_fetch(Part_Subsystem_t *, result, i);
+    st_foreach_item(faninIndexTable[i], stGen, &index, NULL) {
+      array_insert_last(int, sub->subsystemFanIn, (int) index);
+    }
+    st_free_table(faninIndexTable[i]);
+    array_sort(sub->subsystemFanIn, numCompare);
+    st_foreach_item(fanoutIndexTable[i], stGen, &index, NULL) {
+      array_insert_last(int, sub->subsystemFanOut, (int) index);
+    }
+    st_free_table(fanoutIndexTable[i]);
+    array_sort(sub->subsystemFanOut, numCompare);
+  }
+
+  FREE(faninIndexTable);
+  FREE(fanoutIndexTable);
+  array_free(arrayOfLatchDataInputNames);
+  st_free_table(groupIndexTable);
+  PartArrayOfArrayFree(arrayOfGroupVertex);
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Gets bounded size blocks from big CC, Breaking]
+
+  Description [Gets bounded size blocks from big connected component]
+
+  SideEffects []
+
+  SeeAlso     []
+******************************************************************************/
+static array_t *
+PartBreakingBigConnectedComponent(
+  array_t *arrayOfCC,
+  array_t *ccCheck,
+  array_t *arrayOfSeed,
+  float *arrayOfAffinity,
+  Part_SubsystemInfo_t *partSubInfo,
+  st_table *ptrToIndex)
+{
+  array_t *result;    /* array of groups with the proper size */
+  array_t *resultRow; /* a group with the proper size */
+  array_t *arrayTemp;
+  array_t *seedFull;  /* array of seeds */
+  int i, count;
+  int totalCount;     /* how many vertixes are already computed */
+  int indexOfSeed;    /* index of the seed which is closest from the vertex */
+  Ntk_Node_t *seed, *variable, *pick;
+
+  result = array_alloc(array_t *, array_n(arrayOfSeed));
+
+  for (i = 0; i < array_n(arrayOfSeed); i++) {
+    arrayTemp = array_alloc(Ntk_Node_t *, 0);
+    seed = array_fetch(Ntk_Node_t *, arrayOfSeed, i);
+    array_insert_last(Ntk_Node_t *, arrayTemp, seed);
+    array_insert(array_t *, result, i, arrayTemp);
+  }
+
+  switch (partSubInfo->partBM) {
+   /*
+    * Breaking Static Round Robin Seed Choice
+    * Fixed order of seeds and each seed find the closest vertex
+    */
+    case Part_BSRR_s:
+      totalCount = array_n(arrayOfSeed);
+      arrayForEachItem(Ntk_Node_t *, arrayOfSeed, i, seed) {
+	count = 1;
+	resultRow = array_fetch(array_t *, result, i);
+	while ((count < partSubInfo->bound) &&
+	      (totalCount < array_n(arrayOfCC))) {
+	  pick = PartSelectCloseNode(seed, arrayOfCC, ccCheck,
+			arrayOfAffinity, ptrToIndex);
+	  array_insert_last(Ntk_Node_t *, resultRow, pick);
+	  count++;
+	  totalCount++;
+	  seed = pick;
+	}
+      }
+      break;
+   /*
+    * Breaking Fixed Order State Variable Choice
+    * Fixed order of vertecies and each vertex find the closest seed
+    */
+    case Part_BFix_v:
+     /*
+      * Fixed order of nodes and each node find the closest seed
+      */
+      seedFull = array_alloc(int, 0);
+      for (i = 0; i < array_n(arrayOfSeed); i++) {
+	array_insert_last(int, seedFull, 1);
+
+      }
+      arrayForEachItem(Ntk_Node_t *, arrayOfCC, i, variable) {
+	if (array_fetch(int, ccCheck, i) != 1) {
+	  indexOfSeed = PartSelectCloseSeedIndex(variable, arrayOfSeed,
+		arrayOfAffinity, ptrToIndex, seedFull, partSubInfo->bound);
+	  resultRow = array_fetch(array_t *, result, indexOfSeed);
+	  array_insert_last(Ntk_Node_t *, resultRow, variable);
+	  array_insert(int, ccCheck, i, 1);
+	}
+      }
+      array_free(seedFull);
+      break;
+    default:
+      break;
+  }
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets bounded size blocks from small connected components.]
+
+  Description [The small connected components are aggregated by 'Static
+  Round Robin Cluster Seed Algorithm(Fixed order of seed and each seed
+  choose the closest connected component)'.]
+
+  SideEffects []
+
+******************************************************************************/
+static array_t *
+PartAggregating(
+  array_t *arrayOfSmall,
+  float *arrayOfAffinity,
+  Part_SubsystemInfo_t *partSubInfo,
+  st_table *ptrToIndex)
+{
+  float *arrayOfGroupAff;
+  array_t *result;
+  array_t *arraySeed;
+  array_t *arraySeedIndex;
+  array_t *arrayTemp;
+  array_t *arrayRow;
+  array_t *cc;
+  array_t *ccCheck;
+  array_t *seed;
+  int i, j;
+  int count;  /* total number of vertices in all small connected components */
+  int pick, keepInd;
+  int seedLast, seedNew, seedIndex;
+  int numberOfSeed;
+  boolean isDone;
+  array_t *keep = array_alloc(int, 0);
+
+  count = 0;
+
+  arrayForEachItem(array_t *, arrayOfSmall, i, cc) {
+    count += array_n(cc);
+  }
+
+  numberOfSeed = (int) ceil((double)count/(double)partSubInfo->bound);
+
+  arrayOfGroupAff = PartGetGroupMatrixSym(arrayOfSmall, arrayOfAffinity,
+			ptrToIndex);
+
+  if (partSubInfo->verbosity >= 2) {
+    fprintf(vis_stdout, "\nGrouping: Group affinity of initial ");
+    fprintf(vis_stdout, "connected component\n");
+    fprintf(vis_stdout, "------------------------------------");
+    fprintf(vis_stdout, "-------------------\n");
+    PartPrintArrayArray(arrayOfGroupAff, array_n(arrayOfSmall), 0);
+  }
+
+  ccCheck = array_alloc(int, array_n(arrayOfSmall));
+  for (i = 0; i < array_n(arrayOfSmall); i++) {
+    array_insert(int, ccCheck, i, 0);
+  }
+
+ /*
+  * The first seed is the cc which has minmum support and the next
+  * is the farthest cc
+  */
+  seedLast = PartSelectCCIndexOfMinSupport(arrayOfSmall,
+	     ccCheck, partSubInfo);
+
+  result = array_alloc(array_t *, numberOfSeed);
+  arraySeed = array_alloc(array_t *, numberOfSeed);
+  arraySeedIndex = array_alloc(int, numberOfSeed);
+
+  for (i = 0; i < numberOfSeed; i++) {
+    seed = array_fetch(array_t *, arrayOfSmall, seedLast);
+    array_insert(array_t *, arraySeed, i, seed);
+    array_insert(int, arraySeedIndex, i, seedLast);
+    array_insert(array_t *, result, i, seed);
+    if (i<numberOfSeed-1) {
+      seedNew = PartSelectFarCCIndex(seedLast, arrayOfSmall, arrayOfGroupAff,
+			partSubInfo, ccCheck);
+      seedLast = seedNew;
+    }
+  }
+
+ /*
+  * Static Round Robin Cluster Seed: Fixed order of seed and each seed
+  * choose the closest connected component
+  */
+  isDone = FALSE;
+  count = array_n(arraySeed);
+  while ((!isDone) && count < array_n(arrayOfSmall)) {
+    isDone = TRUE;
+    arrayForEachItem(int, arraySeedIndex, i, seedIndex) {
+      arrayRow = array_fetch(array_t *, result, i);
+      pick = PartSelectCloseCCIndex(seedIndex, arrayOfSmall,
+	     arrayOfGroupAff, ccCheck);
+      count++;
+      /* check if not all cc is assigned */
+      if (pick != -1) {
+	arrayTemp = array_fetch(array_t *, arrayOfSmall, pick);
+	if (array_n(array_fetch(array_t *, arrayOfSmall, seedIndex)) +
+	    array_n(arrayTemp) <= partSubInfo->bound) {
+	  array_append(arrayRow, arrayTemp);
+	  array_free(arrayTemp);
+	  isDone = FALSE;
+	} else {
+	 /*
+	  * If pick cc is too big to be appended to seed, find new cc
+	  */
+	  array_insert_last(int, keep, pick);
+	  pick = PartSelectCloseCCIndex(seedIndex, arrayOfSmall,
+			arrayOfGroupAff, ccCheck);
+	  while (pick != -1) {
+	    arrayTemp = array_fetch(array_t *, arrayOfSmall, pick);
+	    if (array_n(array_fetch(array_t *, arrayOfSmall, seedIndex)) +
+		array_n(arrayTemp) <= partSubInfo->bound) {
+	      array_append(arrayRow, arrayTemp);
+	      array_free(arrayTemp);
+	      isDone = FALSE;
+	      break;
+	    } else {
+	      array_insert_last(int, keep, pick);
+	      pick = PartSelectCloseCCIndex(seedIndex, arrayOfSmall,
+			arrayOfGroupAff, ccCheck);
+	    }
+	  } /* end while */
+	  if (pick == -1) {
+	    count--;
+	  }
+	  arrayForEachItem(int, keep, j, keepInd) {
+	    array_insert(int, ccCheck, keepInd, 0);
+	  }
+	  array_free(keep);
+	  keep = array_alloc(int, 0);
+	} /* end if */
+      } else {
+	count--;
+      }/* end if */
+    }/* end arrayForEachItem */
+   /*
+    * If all seeds fail to find suitable cc and not all cc is assigned,
+    *  get a new seed.
+    */
+    if (count < array_n(arrayOfSmall) && isDone) {
+      seedIndex = PartSelectCCIndexOfMinSupport(arrayOfSmall,
+			ccCheck, partSubInfo);
+      count++;
+      seed = array_fetch(array_t *, arrayOfSmall, seedIndex);
+      array_insert_last(array_t *, arraySeed, seed);
+      array_insert_last(int, arraySeedIndex, seedIndex);
+      array_insert_last(array_t *, result, seed);
+      isDone = FALSE;
+    }
+  }
+  array_free(arraySeed);
+  array_free(arraySeedIndex);
+  array_free(keep);
+  array_free(ccCheck);
+  FREE(arrayOfGroupAff);
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Select the closest node from seed and return node pointer]
+
+  SideEffects [The Corresponding flag of ccCheck is set after selection]
+
+******************************************************************************/
+static Ntk_Node_t *
+PartSelectCloseNode(
+  Ntk_Node_t	*seed,
+  array_t	*arrayOfCC,
+  array_t	*ccCheck,
+  float		*arrayOfAffinity,
+  st_table	*ptrToIndex)
+{
+  int		i;
+  float		affinity;
+  float		big; /* The bigest value of affinity of vertecies*/
+  int		bigInd; /* the index of node with the biggest affinity */
+  int		col;
+  int		row;
+  Ntk_Node_t	*node, *pick;
+
+  big = -1.0;
+  bigInd = 0; /* to avoid warning */
+  pick = NIL(Ntk_Node_t);
+
+  st_lookup_int(ptrToIndex, (char *)seed, &row);
+
+  arrayForEachItem(Ntk_Node_t *, arrayOfCC, i, node) {
+    if (array_fetch(int, ccCheck, i) != 1) {
+      st_lookup_int(ptrToIndex, (char *)node, &col);
+      affinity = PartGetElementFromSymMatrix(arrayOfAffinity, row, col);
+      if (affinity > big) {
+	 big = affinity;
+	 pick = node;
+	 bigInd = i;
+      }
+    }
+  }
+  array_insert(int, ccCheck, bigInd, 1);
+  return pick;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Select the closest seed from node and return seed index]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+PartSelectCloseSeedIndex(
+  Ntk_Node_t	*variable,
+  array_t	*arrayOfSeed,
+  float		*arrayOfAffinity,
+  st_table	*ptrToIndex,
+  array_t	*seedFull,
+  int		bound)
+{
+  float		affinity;
+  int		i;
+  float		big;
+  int		pick, row, col;
+  Ntk_Node_t	*node;
+
+  big = -1.0;
+  pick = -1;
+
+  st_lookup_int(ptrToIndex, (char *)variable, &row);
+
+  arrayForEachItem(Ntk_Node_t *, arrayOfSeed, i, node) {
+    st_lookup_int(ptrToIndex, (char *)node, &col);
+    affinity = PartGetElementFromSymMatrix(arrayOfAffinity, row, col);
+    if (affinity > big && array_fetch(int, seedFull, i) < bound) {
+      big = affinity;
+      pick = i;
+    }
+  }
+  array_insert(int, seedFull, pick, array_fetch(int, seedFull, pick) + 1);
+  return pick;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Select the farthest node from seed and return node pointer]
+
+  SideEffects [The Corresponding flag of ccCheck is set after selection]
+
+******************************************************************************/
+static Ntk_Node_t *
+PartSelectFarNode(
+  Ntk_Node_t *seed,
+  array_t *cc,
+  array_t *ccCheck,
+  float *arrayOfAffinity,
+  st_table *ptrToIndex)
+{
+  float		affinity;
+  int		i;
+  float		small; /* the smallest affinity of vertecies */
+  int		smallInd; /* index of vertex with the smallest affinity */
+  int		col;
+  int		row;
+  Ntk_Node_t	*node, *pick;
+
+  small = (float)BIG_NUMBER;
+  smallInd = 0; /* to avoid warning */
+  pick = NIL(Ntk_Node_t);
+
+  st_lookup_int(ptrToIndex, (char *)seed, &row);
+  arrayForEachItem(Ntk_Node_t *, cc, i, node) {
+    if (array_fetch(int, ccCheck, i) != 1) {
+      st_lookup_int(ptrToIndex, (char *)node, &col);
+      affinity = PartGetElementFromSymMatrix(arrayOfAffinity, row, col);
+      if (affinity < small) {
+	 small = affinity;
+	 pick = node;
+	 smallInd = i;
+      }
+    }
+  }
+  array_insert(int, ccCheck, smallInd, 1);
+  return pick;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Get group matrix as regular matrix from given matrix
+  according to the given clusters]
+
+  Description [Get matrix relation between each cluster, the values
+  beetween
+  each cluster are added]
+
+  SideEffects []
+
+******************************************************************************/
+static float *
+PartGetGroupMatrixRegular(
+  array_t *arrayOfCluster,
+  char *arrayOfGivenMatrix,
+  st_table *ptrToIndex,
+  int nVertices)
+{
+  float		*arrayOfGroupMatrix;  /* final result */
+  array_t	*arrayClusterRow;
+  array_t	*arrayClusterCol;
+  float		subSum;
+  int		row, col, i, j, k, l;
+  Ntk_Node_t	*nodeRow, *nodeCol;
+  int		index, size;
+
+  size = array_n(arrayOfCluster);
+  arrayOfGroupMatrix = ALLOC(float, size * size);
+
+  arrayForEachItem(array_t *, arrayOfCluster, i, arrayClusterRow) {
+    arrayForEachItem(array_t *, arrayOfCluster, j, arrayClusterCol) {
+      if (i != j) {
+	subSum = 0.0;
+	arrayForEachItem(Ntk_Node_t *, arrayClusterRow, k, nodeRow) {
+	  st_lookup_int(ptrToIndex, (char *)nodeRow, &row);
+	  arrayForEachItem(Ntk_Node_t *, arrayClusterCol, l, nodeCol) {
+	    st_lookup_int(ptrToIndex, (char *)nodeCol, &col);
+	    index = row * nVertices + col;
+	    if (arrayOfGivenMatrix[index] == 1)
+	      subSum += 1.0;
+	  }
+	}
+	index = i * size + j;
+	arrayOfGroupMatrix[index] = subSum /
+		(float)(array_n(arrayClusterRow) * array_n(arrayClusterCol));
+      } else {
+	index = i * size + j;
+	arrayOfGroupMatrix[index] = 0.0;
+      }
+    }
+  }
+  return arrayOfGroupMatrix;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Get group matrix as symetric matrix from given matrix according
+  to the given clusters]
+
+  Description [Get matrix relation between each cluster, the values beetween
+  each cluster are added]
+
+  SideEffects []
+
+******************************************************************************/
+static float *
+PartGetGroupMatrixSym(
+  array_t  *arrayOfCluster,
+  float  *arrayOfGivenMatrix,
+  st_table *ptrToIndex)
+{
+  float		*arrayOfGroupMatrix;  /* final result */
+  array_t	*arrayClusterRow;
+  array_t	*arrayClusterCol;
+  float		subSum;
+  int		row, col, i, j, k, l;
+  Ntk_Node_t	*nodeRow, *nodeCol;
+  int		index, size;
+
+  size = array_n(arrayOfCluster);
+  arrayOfGroupMatrix = ALLOC(float, size * (size - 1) / 2);
+
+  for (i = 0; i < size; i++) {
+    arrayClusterRow = array_fetch(array_t *, arrayOfCluster, i);
+    for (j = 0; j < i; j++) {
+      arrayClusterCol = array_fetch(array_t *, arrayOfCluster, j);
+      if (i == j) {
+	index = i * (i - 1) / 2 + j;
+	arrayOfGroupMatrix[index] = 0.0;
+      } else {
+	subSum = 0.0;
+	arrayForEachItem(Ntk_Node_t *, arrayClusterRow, k, nodeRow) {
+	  st_lookup_int(ptrToIndex, (char *)nodeRow, &row);
+	  arrayForEachItem(Ntk_Node_t *, arrayClusterCol, l, nodeCol) {
+	    st_lookup_int(ptrToIndex, (char *)nodeCol, &col);
+	    subSum += PartGetElementFromSymMatrix(arrayOfGivenMatrix, row, col);
+	  }
+	}
+	index = i * (i - 1) / 2 + j;
+	arrayOfGroupMatrix[index] = subSum /
+		(float)((array_n(arrayClusterRow)) * array_n(arrayClusterCol));
+      }
+    }
+  }
+  return arrayOfGroupMatrix;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Select a connected component with minimum support variables]
+
+  SideEffects [The Corresponding flag of ccCheck is set after selection]
+
+******************************************************************************/
+static int
+PartSelectCCIndexOfMinSupport(
+  array_t *arrayOfSmall,
+  array_t *ccCheck,
+  Part_SubsystemInfo_t *partSubInfo)
+{
+  array_t	*cc;
+  array_t	*support;
+  int		i, count, minCount, minIndex;
+
+  minCount = BIG_NUMBER;
+  minIndex = -1;
+
+  for (i = 0; i < array_n(ccCheck); i++) {
+    if (array_fetch(int, ccCheck, i) != 1) {
+      cc = array_fetch(array_t *, arrayOfSmall, i);
+      support = Ntk_NodeComputeCombinationalSupport(
+	partSubInfo->network, cc, TRUE);
+      count = array_n(support);
+      array_free(support);
+      if (count < minCount) {
+	minIndex = i;
+	minCount = count;
+      }
+    }
+  }
+  if (minIndex != -1) {
+    array_insert(int, ccCheck, minIndex, 1);
+  }
+  return minIndex;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Select a node with minimum support variables in network node
+  set cc]
+
+  SideEffects [The Corresponding flag of ccCheck is set after selection]
+
+******************************************************************************/
+static Ntk_Node_t *
+PartSelectNodeOfMinSupport(
+  array_t *cc,
+  array_t *ccCheck,
+  Part_SubsystemInfo_t *partSubInfo)
+{
+  array_t	*support;
+  array_t	*nodeArray;
+  int		i, minInd, count, min;
+  Ntk_Node_t	*node;
+  Ntk_Node_t	*minNode = NIL(Ntk_Node_t);
+
+  if (array_n(cc) == 0) {
+    return NIL(Ntk_Node_t);
+  }
+
+  min = BIG_NUMBER;
+  minInd = 0; /* to avoid warning */
+  arrayForEachItem(Ntk_Node_t *, cc, i, node) {
+    if (array_fetch(int, ccCheck, i) != 1) {
+      nodeArray = array_alloc(Ntk_Node_t *, 1);
+      array_insert(Ntk_Node_t *, nodeArray, 0, node);
+      support = Ntk_NodeComputeCombinationalSupport(
+			partSubInfo->network, nodeArray, TRUE);
+      count = array_n(support);
+      if (count < min) {
+	minNode = node;
+	min = count;
+	minInd = i;
+      }
+      array_free(support);
+      array_free(nodeArray);
+    }
+  }
+  array_insert(int, ccCheck, minInd, 1);
+  return minNode;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Select an index of connected component from seed connected
+  component]
+
+  SideEffects [The Corresponding flag of ccCheck is set after selection]
+
+******************************************************************************/
+static int
+PartSelectFarCCIndex(
+  int seedIndex,
+  array_t *arrayOfSmall,
+  float *arrayOfGroupAff,
+  Part_SubsystemInfo_t *partSubInfo,
+  array_t *ccCheck)
+{
+  array_t *col;
+  int i;
+  float groupAff;
+  float min;
+  int minIndex;
+
+  min = (float)BIG_NUMBER;
+  minIndex = -1;
+
+  arrayForEachItem(array_t *, arrayOfSmall, i, col) {
+    if (array_fetch(int, ccCheck, i) != 1) {
+      groupAff = PartGetElementFromSymMatrix(arrayOfGroupAff, seedIndex, i);
+      if (groupAff < min) {
+	minIndex = i;
+	min = groupAff;
+      }
+    }
+  }
+  if (minIndex != -1) {
+    array_insert(int, ccCheck, minIndex, 1);
+  }
+  return minIndex;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Select an index of closest connected component from seed
+  connected component]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+PartSelectCloseCCIndex(
+  int seedIndex,
+  array_t *arrayOfSmall,
+  float *arrayOfGroupAff,
+  array_t *ccCheck)
+{
+  int i;
+  float groupAff;
+  float max;
+  int maxIndex;
+
+  max = -1.0;
+  maxIndex = -1;
+
+  for (i = 0; i < array_n(ccCheck); i++) {
+    if (array_fetch(int, ccCheck, i) != 1) {
+      groupAff = PartGetElementFromSymMatrix(arrayOfGroupAff, seedIndex, i);
+      if (groupAff > max) {
+	maxIndex = i;
+	max = groupAff;
+      }
+    }
+  }
+  if (maxIndex != -1) {
+    array_insert(int, ccCheck, maxIndex, 1);
+  }
+  return maxIndex;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Create a sub-system with given latch-data-input nodes]
+
+  SideEffects []
+
+  SeeAlso     []
+******************************************************************************/
+static Part_Subsystem_t*
+PartCreateSingleSubSystem(
+  array_t *arrayOfNodes,
+  Ntk_Network_t *network)
+{
+  int		i, j;
+  char		*name;
+  Ntk_Node_t	*node;
+  st_table	*vertexNameTable;
+  array_t	*arrayOfLatchNames;
+  Part_Subsystem_t *sub;
+
+  if (array_n(arrayOfNodes) == 0 || arrayOfNodes == NIL(array_t)) {
+    return NIL(Part_Subsystem_t);
+  }
+
+  vertexNameTable = st_init_table(strcmp, st_strhash);
+  arrayForEachItem(Ntk_Node_t *, arrayOfNodes, i, node) {
+    arrayOfLatchNames = PartReadLatchNameFromLatchInput(network, node);
+    arrayForEachItem(char *, arrayOfLatchNames, j, name) {
+      st_insert(vertexNameTable, (char *)name, (char *)NULL);
+    }
+    array_free(arrayOfLatchNames);
+  }
+  sub = ALLOC(Part_Subsystem_t, 1);
+  sub->vertexNameTable = vertexNameTable;
+  sub->subsystemFanIn = NIL(array_t);
+  sub->subsystemFanOut = NIL(array_t);
+
+  return sub;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Gets Latch Name from Latch Data Input]
+
+  SideEffects []
+
+  SeeAlso     []
+******************************************************************************/
+static array_t *
+PartReadLatchNameFromLatchInput(
+  Ntk_Network_t *network,
+  Ntk_Node_t *latchInput)
+{
+  lsGen		gen;
+  Ntk_Node_t	*latch, *temp1;
+  char		*latchName = NIL(char);
+  array_t	*arrayOfLatchNames;
+
+  arrayOfLatchNames = array_alloc(char *, 0);
+  Ntk_NetworkForEachLatch(network, gen, latch) {
+    temp1 = Ntk_LatchReadDataInput(latch);
+    if (temp1 == latchInput) {
+      latchName = Ntk_NodeReadName(latch);
+      array_insert_last(char *, arrayOfLatchNames, latchName);
+    }
+  } /* end of Ntk_NetworkForEachLatch */
+
+  return arrayOfLatchNames;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Free array of array]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+PartArrayOfArrayFree(
+  array_t *arrayOfMatrix)
+{
+  array_t *arrayRow;
+  int i;
+
+  arrayForEachItem(array_t *, arrayOfMatrix, i, arrayRow) {
+    array_free(arrayRow);
+  }
+  array_free(arrayOfMatrix);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Get matrix(i,j) from symetric matrix]
+
+  SideEffects []
+
+******************************************************************************/
+static float
+PartGetElementFromSymMatrix(
+  float *matrix,
+  int i,
+  int j)
+{
+  int index;
+
+  if (i == j)
+    return(0.0);
+  if (i < j) {
+    int tmp;
+
+    tmp = i;
+    i = j;
+    j = tmp;
+  }
+  index = i * (i - 1) / 2 + j;
+  return(matrix[index]);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Print array of array]
+
+  Description [If type is 0, arrayArray is float regular matrix. If type = 1,
+   arrayArray is char type symertic matrix.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+PartPrintArrayArray(
+  void *arrayArray,
+  int nVertices,
+  int type)
+{
+  int i, j;
+  float num;
+  int index;
+
+  if (type == 0) { /* numerical data * symetric matrix */
+    for (i = 0; i < nVertices; i++) {
+      for (j = 0; j < nVertices; j++) {
+	num = PartGetElementFromSymMatrix((float *)arrayArray, i, j);
+	fprintf(vis_stdout, "%4.3f ", num);
+      }
+      fprintf(vis_stdout, "\n");
+    }
+  } else if (type == 1) { /* char data & regular */
+    for (i = 0; i < nVertices; i++) {
+      for (j = 0; j < nVertices; j++) {
+	index = i * nVertices + j;
+	if (((char *)arrayArray)[index] == 1) {
+	  fprintf(vis_stdout, "1 ");
+	} else {
+	  fprintf(vis_stdout, "0 ");
+	}
+      }
+      fprintf(vis_stdout, "\n");
+    }
+  }
+  fprintf(vis_stdout, "\n");
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Compare procedure for string comparison.]
+
+  Description [Compare procedure for string comparison.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+strCompare(
+  const void *name1,
+  const void *name2)
+{
+    return(strcmp(*(char **)name1, *(char **)name2));
+} /* end of strCompare */
+
+/**Function********************************************************************
+
+  Synopsis    [Compare procedure for number comparison.]
+
+  Description [Compare procedure for number comparison.]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+numCompare(
+  const void *num1,
+  const void *num2)
+{
+    return(*(int *)num1 > *(int *)num2);
+} /* end of strCompare */
Index: vis_dev/vis-2.3/src/part/partInOut.c
===================================================================
--- vis_dev/vis-2.3/src/part/partInOut.c	(revision 14)
+++ vis_dev/vis-2.3/src/part/partInOut.c	(revision 14)
@@ -0,0 +1,656 @@
+/**CFile***********************************************************************
+
+  FileName    [partInOut.c]
+
+  PackageName [part]
+
+  Synopsis [Implements the partition of a network considering only the
+  functions at the combinational outputs in terms of the combinational
+  inputs.]
+
+  Description [This module creates a partition where each combinational output
+  is defined in terms of the combinational inputs. More specifically, for each
+  combinational output and for some combinational inputs, there is a vertex in
+  the partition (a combinational input doesn't appear if no combinational
+  output depends on it). There is an edge from combinational input x to
+  combinational output y if the multi-valued function (MVF) for y depends on
+  x. Every vertex in the graph has a vertex name and an MVF (for combinational
+  inputs, the MVF is the trivial variable function). In addition, each
+  combinational input has an MDD id; a combinational output may or may not
+  have an MDD id.]
+
+  SeeAlso     [partPart.c]
+
+  Author      [Abelardo Pardo, Balakrishna Kumthekar]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the
+  suitability of this software for any purpose.  It is presented on an AS IS
+  basis.]
+
+******************************************************************************/
+
+#include "partInt.h"
+
+static char rcsid[] UNUSED = "$Id: partInOut.c,v 1.15 2005/04/16 14:52:45 fabio Exp $";
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Creates the graph representing a set of Mvfs as functions of the
+  variables in the collective support of the specified Mvfs. A copy of the Mvf
+  function is stored in vertex.]
+
+  Description [The input nameToMvf is a table which provides the names and the
+  corresponding Mvfs functions.  The procedure works as follows. For each
+  function, a vertex in the graph is created. For each variable in the support
+  of a given MVF, a vertex is created (if one doesn't already exist), and an
+  edge is added from the that vertex to that MVF. The support of an MVF is
+  taken as the union of the support of its constituent MDDs. The table nameToId
+  is optional and can be NULL. It provides a map from the name of the MVF to
+  its mddId. leafTable provides the pair (mddId, name) for each variable in the
+  support of the MVFs. partName can be NULL in which case the name of the
+  partition would be "dummy".]
+
+  SideEffects []
+
+  SeeAlso     [Part_NetworkCreatePartition Part_NetworkCreatePartitionFromMvfs]
+
+******************************************************************************/
+graph_t *
+Part_CreatePartitionFromMvfs(
+  mdd_manager *manager,			     
+  st_table *nameToMvf,
+  st_table *nameToId,
+  st_table *leafTable,
+  char *partName)
+{
+    graph_t        *partition;
+    Mvf_Function_t *mddFunction;
+    vertex_t       *toVertex;
+    lsList         sinkList;
+    lsGen          gen;
+    st_table       *mddIdToNodeName;
+    st_generator   *stGen;
+    char           *str;
+    long            mddId;
+
+    /* Initialize variables */
+    mddIdToNodeName = leafTable;
+
+    /* Allocate the new partition to be returned */
+    partition = g_alloc();
+    if (partName) {
+	partition->user_data = 
+	    (gGeneric)PartPartitionInfoCreate(partName,manager,Part_InOut_c);
+    } /* End of if */
+    else {
+	partition->user_data = 
+	    (gGeneric)PartPartitionInfoCreate("dummy",manager,Part_InOut_c);
+    } /* End of if-then-else */
+
+    /* Create vertices for the functions in nameToMvf */
+    st_foreach_item(nameToMvf,stGen,&str,&mddFunction) {
+	toVertex = g_add_vertex(partition);
+
+	/* Update the look-up tables in the graph */
+	st_insert(PartPartitionReadNameToVertex(partition),str,toVertex);
+	if (nameToId) {
+	    if (st_lookup(nameToId, str, &mddId)) {
+		st_insert(PartPartitionReadMddIdToVertex(partition),
+			  (char *)mddId, toVertex);
+	    } /* End of if */
+	} /* End of if */
+
+	/* Fill in the fields of the data attached to the vertex */
+	toVertex->user_data = 
+	    (gGeneric)PartVertexInfoCreateSingle(str, 
+				            Mvf_FunctionDuplicate(mddFunction),
+					    mddId);
+    }
+  
+    /* Read the list of vertices on the graph */
+    sinkList = lsCopy(g_get_vertices(partition), (lsGeneric (*)(lsGeneric))0);
+
+    /* 
+     * For every function on every combinational output, compute the
+     * support and create vertices in the graph when needed 
+     */
+    lsForEachItem(sinkList, gen, toVertex) {
+	st_table *mddSupport; /* Support of the Mvf_Function */
+	st_generator *stGen;  /* To iterate over the MddIds of the support */
+	vertex_t *fromVertex; /* Holds the current vertex in the support */
+
+	/* Obtain an array of mdd_t * */
+	mddFunction = PartVertexReadFunction(toVertex);
+
+	/* Compute the support of the set of mdds*/
+	mddSupport = PartCreateFunctionSupportTable(mddFunction);
+
+	/* 
+	 * Create one edge (and one vertex if necessary) for every element
+	 * in mddSupport 
+	 */
+	st_foreach_item(mddSupport, stGen, &mddId, NULL) {
+	    char *name;
+
+	    /* Create vertex with the information if needed */
+	    if (st_lookup(PartPartitionReadMddIdToVertex(partition), 
+			  (char *)mddId, &fromVertex) == 0) {
+		fromVertex = g_add_vertex(partition);
+	
+		st_lookup(mddIdToNodeName, (char *)mddId, &name);
+
+		/* Update the look-up tables in the graph */
+		st_insert(PartPartitionReadNameToVertex(partition), 
+			  name, (char *)fromVertex);
+		st_insert(PartPartitionReadMddIdToVertex(partition),
+			  (char *)(long) mddId, (char *)fromVertex);
+	
+		/* Create vertex data */
+		fromVertex->user_data = 
+		    (gGeneric)PartVertexInfoCreateSingle(name,
+			      Mvf_FunctionCreateFromVariable(manager,mddId),
+							 mddId);
+	    } /* End of if */
+      
+	    /* 
+	     * Add the edge to the graph. Make sure a self loop is not added.
+	     * The self loop may be produced by a mdd that has in its support
+	     * the same variables that represent the mddId of the node.
+	     */
+	    if (fromVertex != toVertex) {
+		g_add_edge(fromVertex, toVertex);
+	    } /* End of if */
+	    
+	} /* End of st_foreach_item */
+    
+	/* Clean the support table */
+	st_free_table(mddSupport);
+    } /* End of lsForEachItem */
+
+    lsDestroy(sinkList, (void (*)(lsGeneric))0);
+
+    return partition;
+} /* End of Part_CreatePartitionFromMvfs */
+
+/**Function********************************************************************
+
+  Synopsis [Creates the graph representing the combinational outputs as
+  functions of the combinational inputs given as input a network and 
+  Mvf functions representing the combinational outputs. A copy of the 
+  Mvf function is stored in vertex.]
+
+  Description [The input nameToMvf is a table which provides the names
+  of the nodes and their corresponding Mvfs functions.
+  The procedure works as follows. For each combinational output,
+  a vertex in the graph is created. For each combinational input in the 
+  support of a given combinational output MVF, a vertex is created 
+  (if one doesn't already exist), and an edge is added 
+  from the combinational input to the combinational output. The support of 
+  an MVF is taken as the union of the support of its constituent MDDs.]
+
+  SideEffects []
+
+  SeeAlso     [Part_NetworkCreatePartition Part_CreatePartitionFromMvfs]
+
+******************************************************************************/
+graph_t *
+Part_NetworkCreatePartitionFromMvfs(
+  Ntk_Network_t *network,
+  st_table *nameToMvf)
+{
+    graph_t        *partition;
+    Ntk_Node_t     *node;
+    Mvf_Function_t *mddFunction;
+    vertex_t       *toVertex;
+    mdd_manager    *manager;
+    lsList         sinkList;
+    lsGen          gen;
+    st_table       *mddIdToNodeName;
+    st_generator   *stGen;
+    char           *ntkName;
+    char           *str;
+    long           mddId;
+
+    /* Initialize variables */
+    manager = Ntk_NetworkReadMddManager(network);
+    ntkName = Ntk_NetworkReadName(network);
+
+    /* Allocate the new partition to be returned */
+    partition = g_alloc();
+    partition->user_data = 
+	(gGeneric)PartPartitionInfoCreate(ntkName,manager,Part_InOut_c);
+
+    /* Create vertices for the functions in nameToMvf */
+    st_foreach_item(nameToMvf,stGen,&str,&mddFunction) {
+	node = Ntk_NetworkFindNodeByName(network,str);
+	if (node == NIL(Ntk_Node_t)) {
+	    fprintf(vis_stderr,"%s has no corresponding node in network \n",
+		    str);
+	    Part_PartitionFree(partition);
+	    return NIL(graph_t);
+	}
+	mddId = Ntk_NodeReadMddId(node);
+	toVertex = g_add_vertex(partition);
+
+	/* Update the look-up tables in the graph */
+	st_insert(PartPartitionReadNameToVertex(partition),str,
+		  (char *)toVertex);
+
+	if (mddId != NTK_UNASSIGNED_MDD_ID) {
+	    st_insert(PartPartitionReadMddIdToVertex(partition),
+		      (char *)(long) mddId, (char *)toVertex);
+	}
+
+	/* Fill in the fields of the data attached to the vertex */
+	toVertex->user_data = 
+	    (gGeneric)PartVertexInfoCreateSingle(str, 
+				            Mvf_FunctionDuplicate(mddFunction),
+					    mddId);
+    }
+
+    /* Create a table for all the combinational inputs */
+    mddIdToNodeName = st_init_table(st_numcmp, st_numhash);
+    Ntk_NetworkForEachCombInput(network, gen, node) {
+	st_insert(mddIdToNodeName, (char *) (long)Ntk_NodeReadMddId(node), 
+		  Ntk_NodeReadName(node));
+    }
+  
+    /* Read the list of vertices on the graph */
+    sinkList = lsCopy(g_get_vertices(partition), (lsGeneric (*)(lsGeneric))0);
+
+    /* 
+     * For every function on every combinational output, compute the
+     * support and create vertices in the graph when needed 
+     */
+    lsForEachItem(sinkList, gen, toVertex) {
+	st_table *mddSupport; /* Support of the Mvf_Function */
+	st_generator *stGen;  /* To iterate over the MddIds of the support */
+	vertex_t *fromVertex; /* Holds the current vertex in the support */
+
+	/* Obtain an array of mdd_t * */
+	mddFunction = PartVertexReadFunction(toVertex);
+
+	/* Compute the support of the set of mdds*/
+	mddSupport = PartCreateFunctionSupportTable(mddFunction);
+
+	/* 
+	 * Create one edge (and one vertex if necessary) for every element
+	 * in mddSupport 
+	 */
+	st_foreach_item(mddSupport, stGen, &mddId, NULL) {
+	    char *name;
+
+	    /* Create vertex with the information if needed */
+	    if (st_lookup(PartPartitionReadMddIdToVertex(partition), 
+			  (char *)mddId, &fromVertex) == 0) {
+		fromVertex = g_add_vertex(partition);
+	
+		st_lookup(mddIdToNodeName, (char *)mddId, &name);
+
+		/* Update the look-up tables in the graph */
+		st_insert(PartPartitionReadNameToVertex(partition), 
+			  name, (char *)fromVertex);
+		st_insert(PartPartitionReadMddIdToVertex(partition),
+			  (char *)(long) mddId, (char *)fromVertex);
+	
+		/* Create vertex data */
+		fromVertex->user_data = 
+		    (gGeneric)PartVertexInfoCreateSingle(name,
+			      Mvf_FunctionCreateFromVariable(manager,mddId),
+							 mddId);
+	    } /* End of if */
+      
+	    /* 
+	     * Add the edge to the graph. Make sure a self loop is not added.
+	     * The self loop may be produced by a mdd that has in its support
+	     * the same variables that represent the mddId of the node.
+	     */
+	    if (fromVertex != toVertex) {
+		g_add_edge(fromVertex, toVertex);
+	    } /* End of if */
+	    
+	} /* End of st_foreach_item */
+    
+	/* Clean the support table */
+	st_free_table(mddSupport);
+    } /* End of lsForEachItem */
+
+    st_free_table(mddIdToNodeName);
+    lsDestroy(sinkList, (void (*)(lsGeneric))0);
+
+    return partition;
+} /* End of Part_NetworkCreatePartitionFromMvfs */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Creates the graph representing the combinational outputs as
+  functions of the combinational inputs.]
+
+  Description [The procedure works as follows. It calls the function
+  Ntm_NetworkBuildMvfs with the combinational outputs as roots and the
+  combinational inputs as leaves to obtain the multi-valued functions for
+  every combinational output.  For each combinational output, a vertex in the
+  graph is created. For each combinational input in the support of a given
+  combinational output MVF, a vertex is created for the combinational input
+  (if one doesn't already exist), and an edge is added from the combinational
+  input to the combinational output. The support of an MVF is taken as the
+  union of the support of its constituent MDDs.]
+
+  SideEffects []
+
+  SeeAlso     [Part_NetworkCreatePartition]
+
+******************************************************************************/
+void
+PartPartitionInputsOutputs(
+  Ntk_Network_t *network,
+  graph_t *partition,
+  lsList  rootList,
+  lsList  leaveList,
+  mdd_t   *careSet)
+{
+  Ntk_Node_t     *node;            /* Pointer to iterate over nodes */
+  Mvf_Function_t *mddFunction;     /* Pointer to a MDD */
+  mdd_manager    *manager;         /* Mdd manager in the partition */
+  st_table       *tableOfLeaves;   /* To store the leaves of the graph */
+  st_table       *mddIdToNodeName; /* For quick lookup of node's name */
+  array_t        *arrayOfMvf;      /* To store the next state functions */
+  array_t        *arrayOfRoots;    /* To store the roots of the graph */
+  lsList         sinkList;         /* Vertices representing comb. outputs */
+  lsGen          gen;              /* To iterate over lists */
+  vertex_t       *toVertex;        /* Will hold the current function vertex */
+  int            i;                /* Index for loops */
+  long            mddId;            /* Will hold the mddId being processed */
+
+
+  manager = PartPartitionReadMddManager(partition);
+
+  /* Take the nodes in leaveList as the leaves */
+  tableOfLeaves = st_init_table(st_ptrcmp, st_ptrhash);
+  mddIdToNodeName = st_init_table(st_numcmp, st_numhash);
+  if (leaveList == (lsList)0) {
+    Ntk_NetworkForEachCombInput(network, gen, node) {
+      st_insert(tableOfLeaves, (char *)node, (char *) (long) (-1) );
+      st_insert(mddIdToNodeName, (char *) (long)Ntk_NodeReadMddId(node), 
+		Ntk_NodeReadName(node));
+    }
+  } /* End of then */ 
+  else {
+    lsForEachItem(leaveList, gen, node) {
+      st_insert(tableOfLeaves, (char *)node, (char *) (long) (-1) );
+      st_insert(mddIdToNodeName, (char *) (long)Ntk_NodeReadMddId(node), 
+		Ntk_NodeReadName(node));
+    }
+  } /* End of if-then-else */
+
+  /* Take the nodes in rootList as the roots */
+  if (rootList == (lsList)0) {
+    arrayOfRoots = array_alloc(Ntk_Node_t *, 
+			       Ntk_NetworkReadNumCombOutputs(network));
+    i = 0;
+    Ntk_NetworkForEachCombOutput(network, gen, node) {
+      array_insert(Ntk_Node_t *, arrayOfRoots, i++, node);
+    }
+  } /* End of then */ 
+  else {
+    arrayOfRoots = array_alloc(Ntk_Node_t *, lsLength(rootList));
+    i = 0;
+    lsForEachItem(rootList, gen, node) {
+      array_insert(Ntk_Node_t *, arrayOfRoots, i++, node);
+    }
+  } /* End of if-then-else */
+
+  /* Build the next state functions as a function of the inputs */
+  arrayOfMvf = Ntm_NetworkBuildMvfs(network, arrayOfRoots, tableOfLeaves, 
+				    careSet);
+
+  /* Create one vertex for every component of arrayOfMvf */
+  for (i=0; i < array_n(arrayOfRoots); i++) {
+    node = array_fetch(Ntk_Node_t *, arrayOfRoots, i);
+    
+    mddId = Ntk_NodeReadMddId(node);
+
+    /* obtain the function attached to the node */
+    mddFunction = array_fetch(Mvf_Function_t *, arrayOfMvf, i);
+    toVertex = g_add_vertex(partition);
+    
+    /* Update the look-up tables in the graph */
+    st_insert(PartPartitionReadNameToVertex(partition),
+	      Ntk_NodeReadName(node), (char *)toVertex);
+    if (mddId != NTK_UNASSIGNED_MDD_ID) {
+      st_insert(PartPartitionReadMddIdToVertex(partition),
+		(char *)(long) mddId, (char *)toVertex);
+    } /* End of if */
+    toVertex->user_data = 
+      (gGeneric)PartVertexInfoCreateSingle(Ntk_NodeReadName(node), 
+					   mddFunction, 
+					   mddId);
+  } /* End of for */
+  
+  /* Read the list of vertices on the graph */
+  sinkList = lsCopy(g_get_vertices(partition), (lsGeneric (*)(lsGeneric))0);
+
+  /* 
+   * For every function on every combinational output, compute the
+   * support and create vertices in the graph when needed 
+   */
+  lsForEachItem(sinkList, gen, toVertex) {
+    st_table     *mddSupport; /* To store the support of the Mvf_Function */
+    st_generator *stGen;      /* To iterate over the MddIds of the support */
+    vertex_t     *fromVertex; /* Will hold the current vertex in the support */
+
+    /* Obtain an array of mdd_t * */
+    mddFunction = PartVertexReadFunction(toVertex);
+
+    /* Compute the support of the set of mdds*/
+    mddSupport = PartCreateFunctionSupportTable(mddFunction);
+
+    /* 
+     * Create one edge (and one vertex if necessary) for every element
+     * in mddSupport 
+     */
+    st_foreach_item(mddSupport, stGen, &mddId, NULL) {
+      char *name;
+
+      /* Create vertex with the information if needed */
+      if (st_lookup(PartPartitionReadMddIdToVertex(partition), 
+		    (char *)mddId, &fromVertex) == 0) {
+	fromVertex = g_add_vertex(partition);
+	
+	st_lookup(mddIdToNodeName, (char *)mddId, &name);
+
+	/* Update the look-up tables in the graph */
+	st_insert(PartPartitionReadNameToVertex(partition), 
+		  name, (char *)fromVertex);
+	st_insert(PartPartitionReadMddIdToVertex(partition),
+		  (char *)(long) mddId, (char *)fromVertex);
+	
+	/* Create vertex data */
+	fromVertex->user_data = 
+	  (gGeneric)PartVertexInfoCreateSingle(name,
+					       Mvf_FunctionCreateFromVariable(manager,mddId),
+					       mddId);
+      } /* End of if */
+      
+      /* 
+       * Add the edge to the graph. Make sure a self loop is not added. The
+       * self loop may be produced by a mdd that has in its support the same
+       * variables that represent the mddId of the node.
+       */
+      if (fromVertex != toVertex) {
+	g_add_edge(fromVertex, toVertex);
+      } /* End of if */
+      
+    } /* End of st_foreach_item */
+    
+    /* Clean the support table */
+    st_free_table(mddSupport);
+  } /* End of lsForEachItem */
+  
+  /* Clean up */
+  st_free_table(mddIdToNodeName);
+  st_free_table(tableOfLeaves);
+  array_free(arrayOfRoots);
+  lsDestroy(sinkList, (void (*)(lsGeneric))0);
+  /* 
+   * The contents of this array (array of mdds) is not deallocated because the
+   * information has been transferred to the partition structure. All the
+   * functions are stored now as part of the vertex information.
+   */
+  array_free(arrayOfMvf);
+  
+} /* End of PartPartitionInputsOutputs */
+
+
+/**Function********************************************************************
+
+  Synopsis [Creates the graph representing the combinational outputs as
+  functions of the combinational inputs.]
+
+  Description [The procedure works as follows. It calls the function
+  Ntm_NetworkBuildMvfs with the combinational outputs as roots and the
+  combinational inputs as leaves to obtain the multi-valued functions for
+  every combinational output.  For each combinational output, a vertex in the
+  graph is created. For each combinational input in the support of a given
+  combinational output MVF, a vertex is created for the combinational input
+  (if one doesn't already exist), and an edge is added from the combinational
+  input to the combinational output. The support of an MVF is taken as the
+  union of the support of its constituent MDDs.]
+
+  SideEffects []
+
+  SeeAlso     [Part_NetworkCreatePartition]
+
+******************************************************************************/
+int
+PartPartitionInOutChangeRoots(
+  Ntk_Network_t *network,
+  graph_t *partition,
+  lsList  rootList,
+  int verbosity)
+{
+  Ntk_Node_t     *node;            /* Pointer to iterate over nodes */
+  mdd_manager    *manager;         /* Mdd manager in the partition */
+  lsList         newRootList;
+  lsList         vertexList;
+  lsGen          gen;              /* To iterate over lists */
+  vertex_t       *vertex;
+  char           *vertexName;
+  long           initialTime, finalTime;
+  st_table       *rootNodesTable = st_init_table(st_ptrcmp, st_ptrhash);
+  mdd_t          *careSet;
+
+  int prevNumOfLatchDataInput = 0;
+  int prevNumOfPrimaryOutput = 0;
+  int newNumOfLatchDataInput = 0;
+  int newNumOfPrimaryOutput = 0;
+  int overlapNumOfLatchDataInput = 0;
+  int overlapNumOfPrimaryOutPut = 0;
+
+  initialTime = util_cpu_time();
+
+  manager = PartPartitionReadMddManager(partition);
+  vertexList = g_get_vertices(partition);
+
+  lsForEachItem(vertexList, gen, vertex){
+    vertexName = PartVertexReadName(vertex);
+    node = Ntk_NetworkFindNodeByName(network, vertexName);
+    if (Ntk_NodeTestIsCombOutput(node)){
+      st_insert(rootNodesTable, (char *)node, (char *)(long)(-1));
+      if (Ntk_NodeTestIsLatchDataInput(node)){
+        prevNumOfLatchDataInput++;
+      }else if (Ntk_NodeTestIsPrimaryOutput(node)){
+        prevNumOfPrimaryOutput++;
+      }
+    }
+  }
+
+  newRootList = lsCreate();
+  lsForEachItem(rootList, gen, node){
+    if (!(st_is_member(rootNodesTable, (char *)node))){
+      lsNewEnd(newRootList, (lsGeneric)node, LS_NH);
+      if (Ntk_NodeTestIsLatchDataInput(node)){
+        newNumOfLatchDataInput++;
+      }else if (Ntk_NodeTestIsPrimaryOutput(node)){
+        newNumOfPrimaryOutput++;
+      }
+    }else{
+      if (Ntk_NodeTestIsLatchDataInput(node)){
+        overlapNumOfLatchDataInput++;
+      }else if (Ntk_NodeTestIsPrimaryOutput(node)){
+        overlapNumOfPrimaryOutPut++;
+      }
+    }
+  }
+
+  st_free_table(rootNodesTable);
+
+  if (lsLength(newRootList) > 0){
+    careSet = mdd_one(manager);
+    PartPartitionInputsOutputs(network, partition, newRootList, 
+                               (lsList)0, careSet);
+    mdd_free(careSet);
+  }
+
+  lsDestroy(newRootList, (void (*)(lsGeneric))0);
+
+  finalTime = util_cpu_time();
+
+  if (verbosity >= 2){
+    fprintf(vis_stdout, "PART: Partition is changed.\n");
+    fprintf(vis_stdout, "PART: Old - %d next state functions\n",
+            prevNumOfLatchDataInput);
+    fprintf(vis_stdout, "PART: Old - %d primary outputs\n",
+            prevNumOfPrimaryOutput);
+    fprintf(vis_stdout, "PART: New - %d next state functions\n",
+            prevNumOfLatchDataInput + newNumOfLatchDataInput);
+    fprintf(vis_stdout, "PART: New - %d primary outputs\n",
+            prevNumOfPrimaryOutput + newNumOfPrimaryOutput);
+    fprintf(vis_stdout, "PART: Partitioning time = %10ld\n",
+                    (finalTime - initialTime) / 1000);
+    Part_PartitionPrintStats(vis_stdout, partition, FALSE);
+  }
+
+  /*
+   * Is partition increased?
+   */
+  if (newNumOfLatchDataInput + newNumOfPrimaryOutput > 0){
+    return 1;
+  }else{
+    return 0;
+  } 
+} /* End of PartPartitionInOutChangeRoots */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/part/partInt.h
===================================================================
--- vis_dev/vis-2.3/src/part/partInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/part/partInt.h	(revision 14)
@@ -0,0 +1,406 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [partInt.h]
+
+  PackageName [part]
+
+  Synopsis [Internal data type definitions and macros to handle the
+  structures of the partition package.]
+
+  Author      [Abelardo Pardo]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+  Revision    [$Id: partInt.h,v 1.26 2005/04/16 06:14:54 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _PARTINT
+#define _PARTINT
+
+#include <string.h>
+#include <time.h>
+#include "ntm.h"
+#include "ord.h"
+#include "cmd.h"
+#include "part.h"
+#include "img.h"
+#include "mc.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+#define PART_SUB_CON_FACTOR 2 
+#define PART_SUB_COR_FACTOR 4
+#define PART_SUB_AFF_FACTOR 0.5 
+#define BIG_NUMBER 10000
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+/**Struct**********************************************************************
+
+  Synopsis    [Information stored in the graph representing the partition.]
+
+  Description [The information stored in the graph consists of the following
+  fields.  The name of the system from which the partition was obtained. For
+  example, if the system is of type Ntk_Network_t, the name stored here is a
+  copy of the network's name. The method used to obtain the partition. The
+  nameToVertex table provides a associative table to find a vertex in the
+  partition by giving a name. The mddIdToVertex table is another hash table to
+  find a vertex in the partition given a mddId..]
+
+  SeeAlso     [PartVertexInfo st Part_PartitionMethod]
+
+******************************************************************************/
+typedef struct PartPartitionInfo {
+  char *name;                         /* Name of the entity from which
+				       * the partition was obtained */
+  Part_PartitionMethod method;        /* Method used to create the partition */
+
+  mdd_manager *mddManager;            /* manager of mdds for the partition */
+  st_table *nameToVertex;             /* Table of name to vertex  */
+  st_table *mddIdToVertex;            /* Table of mddId to vertex */
+} PartPartitionInfo_t;
+
+/**Struct**********************************************************************
+
+  Synopsis    [Information stored in every vertex of the graph.]
+
+  Description [There are two types of vertices in a partition: single and
+  clustered.  A single vertex in the partition graph has a name, a multi-valued
+  function and eventually a MddId. A clustered vertex stores an array of
+  pointer to single vertices.  In general, a vertex does not need to have a
+  name attached to it. There could be different heuristics for partitioning the
+  system that could create <em>additional</em> vertices not related to the
+  system. In these situations this name will be empty.<p>
+
+  The type field stores the type of the vertex, single or clustered.  The mvf
+  field stores the multi-valued function associated with the vertex. The
+  vertices representing the variables in the support of this function
+  constitute the fanin of this vertex. The MddId is the identifier assigned to
+  the variable that this vertex represents (if any). Every vertex with no
+  fanout, in principle does not have any variable Id attached to it, but if
+  this information exists in the original system, it may be replicated here
+  also. The boolean field <tt>isClustered</tt> is used to mark the single nodes
+  that are already part of some clustered vertices, to avoid a single vertex
+  being part of more than one cluster.]
+
+  SeeAlso     [Part_VertexType PartPartitionInfo]
+
+******************************************************************************/
+typedef struct PartVertexInfo {
+  Part_VertexType type;      /* Type of vertex */
+  char *name;                /* Name of the unit (if the vertex corresponds to
+                              * a unit in the system. If the unit is created by
+                              * the partition package, this pointer is NULL).
+                              */
+  union {
+    Mvf_Function_t *mvf;     /* Multi-valued function attached to the vertex */
+    array_t *clusterMembers; /* Array of vertex_t * for the clustered vertex */
+  } functionality;
+  int mddId;                 /* Id of the variable attached to the vertex, if
+			      * any. */
+  boolean isClustered;       /* Boolean that determines if the vertex is part
+			      * of a clustered vertex.*/
+} PartVertexInfo_t;
+
+/**Struct**********************************************************************
+
+  Synopsis    [Information for cleating the sub-systems]
+
+  SeeAlso     [Part_PartitionSubsystemInfoInit 
+               PartBreakingBigConnectedComponent ]
+
+******************************************************************************/
+struct PartSubsystemInfo{
+  Ntk_Network_t  *network;       /* network */
+  array_t        *arrayOfVertex; /* Target vertices to be decomposed into
+                                  * sub-systems */ 
+  int            numberOfVertex; /* total number of vertices */
+  Part_BMethod   partBM;         /* Breaking method */
+  int            bound;          /* maximum number of vertices in 
+                                  * a sub-system */
+  float          threshold;      /* threshold value to determine if
+                                  * two vertices are connected or not */
+  float          con_factor;     /* weight factor to emphasize the mutual 
+                                  * over the single dependency between two 
+                                  * vertices */ 
+  float          cor_factor;     /* weight factor to lower the value
+                                  * of a pair of vertices which are
+                                  * only slightly correlated */
+  float          aff_factor;     /* weight factor to emphasize either 
+                                  * connectivity(aff_factor>0.5)  or 
+                                  * correlation(aff_factor<0.5). */  
+  int		 verbosity;
+  int            corMethod;      /* method for correlation
+                                  * 0 : use BDD correlation (default)
+                                  * 1 : use support */
+  st_table	*dupLatchTable;	 /* stores
+				  * (latchInputName, array of latchName) */
+  st_table	*latchNameTable; /* stores (latchInputName, latchName) */
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [Structure for each Sub-system]
+
+  SeeAlso     []
+
+******************************************************************************/
+struct PartSubsystem{
+  st_table *vertexNameTable; /* table containing names of latches in each
+				sub-system (not a map)*/  
+  array_t  *subsystemFanIn;  /* indices of sub-subsystems which are fanin
+                              * of current sub-system */ 
+  array_t  *subsystemFanOut; /* indices of sub-subsystems which are fanout 
+                              * of current sub-system */
+ 
+};
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**Macro***********************************************************************
+
+  Synopsis     [Internal macro to access the name of the partition.]
+
+  SideEffects  []
+
+  SeeAlso      [PartPartitionInfo]
+
+******************************************************************************/
+#define PartPartitionReadName(                            \
+  /* graph_t * */ pPtr /* Pointer to a graph structure */ \
+)                                                         \
+    ((PartPartitionInfo_t *)(pPtr)->user_data)->name
+
+/**Macro***********************************************************************
+
+  Synopsis [Internal macro to access the method used to create the partition.]
+
+  SideEffects  []
+
+  SeeAlso      [PartPartitionInfo]
+
+******************************************************************************/
+#define PartPartitionReadMethod(                          \
+  /* graph_t * */ pPtr /* Pointer to a graph structure */ \
+)                                                         \
+    ((PartPartitionInfo_t *)(pPtr)->user_data)->method
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Internal macro to access the MDD manager of the partition.]
+
+  SideEffects  []
+
+  SeeAlso      [PartPartitionInfo]
+
+******************************************************************************/
+#define PartPartitionReadMddManager(                      \
+  /* graph_t * */ pPtr /* Pointer to a graph structure */ \
+)                                                         \
+    ((PartPartitionInfo_t *)(pPtr)->user_data)->mddManager
+
+/**Macro***********************************************************************
+
+  Synopsis [Internal macro to access the nameToVertex field of the
+  partition.]
+
+  SideEffects  []
+
+  SeeAlso      [PartPartiotionInfo]
+
+******************************************************************************/
+#define PartPartitionReadNameToVertex(                    \
+  /* graph_t * */ pPtr /* Pointer to a graph structure */ \
+)                                                         \
+    ((PartPartitionInfo_t *)(pPtr)->user_data)->nameToVertex
+
+/**Macro***********************************************************************
+
+  Synopsis [Internal macro to access the mddIdToVertex field of the partition.]
+
+  SideEffects  []
+
+  SeeAlso      [PartPartitionInfo]
+
+******************************************************************************/
+#define PartPartitionReadMddIdToVertex(                   \
+  /* graph_t * */ pPtr /* Pointer to a graph structure */ \
+)                                                         \
+    ((PartPartitionInfo_t *)(pPtr)->user_data)->mddIdToVertex
+
+/**Macro***********************************************************************
+
+  Synopsis     [Internal macro to access the type of a vertex.]
+
+  SideEffects  []
+
+  SeeAlso      [PartVertexInfo]
+
+******************************************************************************/
+#define PartVertexReadType(                                                 \
+  /* vertex_t * */ vPtr /* Pointer to vertex in the graph data structure */ \
+)                                                                           \
+    ((PartVertexInfo_t *)(vPtr)->user_data)->type
+
+/**Macro***********************************************************************
+
+  Synopsis     [Internal macro to access the name of a vertex.]
+
+  SideEffects  []
+
+  SeeAlso      [PartVertexInfo]
+
+******************************************************************************/
+#define PartVertexReadName(                                                 \
+  /* vertex_t * */ vPtr /* Pointer to vertex in the graph data structure */ \
+)                                                                           \
+    ((PartVertexInfo_t *)(vPtr)->user_data)->name
+
+/**Macro***********************************************************************
+
+  Synopsis     [Internal macro to access the clusterMembers of a vertex.]
+
+  SideEffects  []
+
+  SeeAlso      [PartVertexInfo]]
+
+******************************************************************************/
+#define PartVertexReadClusterMembers(                                       \
+  /* vertex_t * */ vPtr /* Pointer to vertex in the graph data structure */ \
+)                                                                           \
+    ((PartVertexInfo_t *)(vPtr)->user_data)->functionality.clusterMembers
+
+
+/**Macro***********************************************************************
+
+  Synopsis [Internal macro to access the multi-valued function of a
+  vertex.]
+
+  SideEffects  []
+
+  SeeAlso      [PartVertexInfo]
+
+******************************************************************************/
+#define PartVertexReadFunction(                                             \
+  /* vertex_t * */ vPtr /* Pointer to vertex in the graph data structure */ \
+)                                                                           \
+    ((PartVertexInfo_t *)(vPtr)->user_data)->functionality.mvf
+
+/**Macro***********************************************************************
+
+  Synopsis [Internal macro to set the multi-valued function of a
+  vertex.]
+
+  SideEffects  []
+
+  SeeAlso      [PartVertexInfo]
+
+******************************************************************************/
+#define PartVertexSetFunction(                                          \
+  /* vertex_t * */       vPtr     /* Pointer to vertex in the graph */, \
+  /* Mvf_Function_t * */ function /* Function to store */               \
+)                                                                       \
+    ((PartVertexInfo_t *)(vPtr)->user_data)->functionality.mvf = (function)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Internal macro to access the mdd Id of a vertex.]
+
+  SideEffects  []
+
+  SeeAlso      [PartVertexInfo]
+
+******************************************************************************/
+#define PartVertexReadMddId(                                                \
+  /* vertex_t * */ vPtr /* Pointer to vertex in the graph data structure */ \
+)                                                                           \
+    ((PartVertexInfo_t *)(vPtr)->user_data)->mddId
+
+/**Macro***********************************************************************
+
+  Synopsis     [Internal macro to access the isClustered of a vertex.]
+
+  SideEffects  []
+
+  SeeAlso      [PartVertexInfo]
+
+******************************************************************************/
+#define PartVertexTestIsClustered(                                          \
+  /* vertex_t * */ vPtr /* Pointer to vertex in the graph data structure */ \
+)                                                                           \
+    ((PartVertexInfo_t *)(vPtr)->user_data)->isClustered
+
+/**Macro***********************************************************************
+
+  Synopsis     [Sets the isClustered field of a vertex.]
+
+  SideEffects  []
+
+  SeeAlso      [PartVertexInfo]
+
+******************************************************************************/
+#define PartVertexSetIsClustered(                                  \
+  /* vertex_t * */ vPtr  /* Pointer to vertex in the graph */,     \
+  /* boolean */    value /* Boolean representing IsClustered ?  */ \
+)                                                                  \
+    ((PartVertexInfo_t *)(vPtr)->user_data)->isClustered = (value)
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void partCreateBoundaryNames(Hrc_Node_t *hnode, st_table *tableOfFormalNames);
+EXTERN void PartPartitionBoundary(Ntk_Network_t *network, Hrc_Node_t *hnode, graph_t *partition, lsList rootList, lsList leaveList, mdd_t *careSet, int inTermsOfCombInputs);
+EXTERN void PartNameFree(lsGeneric name);
+EXTERN void PartPartitionFrontier(Ntk_Network_t *network, graph_t *partition, lsList rootList, lsList leaveList, mdd_t *careSet);
+EXTERN void PartUpdateFrontier(Ntk_Network_t *network, graph_t *partition, lsList rootList, lsList leaveList, mdd_t *careSet);
+EXTERN void PartPrintPartition(graph_t *partition);
+EXTERN array_t * PartCreateSubsystem(Part_SubsystemInfo_t *partSubInfo, array_t *arrayOfLatchNames, array_t *arrayOfGroupIndex);
+EXTERN void PartPartitionInputsOutputs(Ntk_Network_t *network, graph_t *partition, lsList rootList, lsList leaveList, mdd_t *careSet);
+EXTERN int PartPartitionInOutChangeRoots(Ntk_Network_t *network, graph_t *partition, lsList  rootList, int verbosity);
+EXTERN PartPartitionInfo_t * PartPartitionInfoCreate(char *name, mdd_manager *manager, Part_PartitionMethod method);
+EXTERN void PartPartitionInfoFree(gGeneric partitionInfo);
+EXTERN PartVertexInfo_t * PartVertexInfoCreateSingle(char *name, Mvf_Function_t *mvf, int mddId);
+EXTERN PartVertexInfo_t * PartVertexInfoCreateCluster(char *name, array_t *vertexArray);
+EXTERN void PartVertexInfoFree(gGeneric vertexInfo);
+EXTERN void PartPartitionSanityCheck(graph_t *partition, int intensity);
+EXTERN st_table * PartCreateFunctionSupportTable(Mvf_Function_t *mvf);
+EXTERN void PartPartitionCreateVertexFaninEdges(graph_t *partition, vertex_t *vertexPtr);
+EXTERN int PartPartitionPrint(FILE *fp, graph_t *partition);
+EXTERN int PartGetLatchInputListFromCTL(Ntk_Network_t *network, array_t *ctlArray, array_t *fairArray, lsList  latchInputList);
+EXTERN int PartGetLatchListFromCtlAndLtl(Ntk_Network_t *network, array_t *ctlArray, array_t *ltlArray, array_t *fairArray, lsList  latchInputList, boolean stopAtLatch);
+EXTERN int PartGetLatchInputListFromCtlAndLtl(Ntk_Network_t *network, array_t *ctlArray, array_t *ltlArray, array_t *fairArray, lsList  latchInputList, boolean stopAtLatch);
+EXTERN void PartPartitionPartial(Ntk_Network_t *network, graph_t *partition, lsList rootList, lsList leaveList, mdd_t *careSet, lsList nodeList, int inTermsOfCombInputs);
+EXTERN void PartPartitionTotal(Ntk_Network_t *network, graph_t *partition, lsList rootList, lsList leaveList, mdd_t *careSet, int inTermsOfLeaves);
+EXTERN void PartInsertBnvs(Ntk_Network_t *network, st_table *coiLatchTable, st_table *coiBnvTable);
+EXTERN void PartPartitionWithExistingBnvs(Ntk_Network_t *network, graph_t *partition, st_table *coiBnvTable, st_table *absLatchTable, st_table *absBnvTable);
+EXTERN void PartPartitionUpdateWithExistingBnvs(Ntk_Network_t *network, graph_t *partition, st_table *coiBnvTable, st_table *absLatchTable, st_table *absBnvTable);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _PARTINT */
+
+
+
+
Index: vis_dev/vis-2.3/src/part/partPart.c
===================================================================
--- vis_dev/vis-2.3/src/part/partPart.c	(revision 14)
+++ vis_dev/vis-2.3/src/part/partPart.c	(revision 14)
@@ -0,0 +1,1671 @@
+/**CFile************************************************************************
+
+  FileName    [partPart.c]
+
+  PackageName [part]
+
+  Synopsis [Routines to initialize the command <em>build_partition_mdds</em>,
+  create and delete internal data structures of the partition, and print
+  information about the partition.]
+
+  Author      [Abelardo Pardo]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "partInt.h"
+
+static char rcsid[] UNUSED = "$Id: partPart.c,v 1.45 2009/04/11 01:47:18 fabio Exp $";
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void PrintVertexDescription(FILE *fp, vertex_t *vertexPtr, int order);
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Deletes the graph created for the partition and all the information
+  attached to it.]
+
+  SideEffects []
+
+  SeeAlso     [PartPartitionInfoFree PartVertexInfoFree]
+
+******************************************************************************/
+void
+Part_PartitionFree(
+   graph_t *partition)
+{
+  /* Delete the graph information */
+  g_free(partition, PartPartitionInfoFree, PartVertexInfoFree,
+	 (void (*)(gGeneric))0);
+} /* End of Part_PartitionFree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Call-back function to free a partition.]
+
+  Description [This function will be stored in the network together with the
+  pointer to the structure. Whenever the network deletes the partitioning
+  information, this function is called and it will deallocate the partition and
+  the information attached to it.]
+
+  SideEffects []
+
+  SeeAlso     [Ntk_NetworkAddApplInfo]
+
+******************************************************************************/
+void
+Part_PartitionFreeCallback(
+   void *data)
+{
+  Part_PartitionFree((graph_t *) data);
+} /* End of Part_PartitionFreeCallback */
+
+/**Function********************************************************************
+
+  Synopsis    [Finds a vertex in the graph with a certain name.]
+
+  Description [Given a name, it returns a pointer to a vertex structure if
+  there is a vertex with that name in the partition. Otherwise it returns a
+  NULL pointer.]
+
+  SideEffects []
+
+  SeeAlso     [PartPartitionInfo]
+
+******************************************************************************/
+vertex_t *
+Part_PartitionFindVertexByName(
+  graph_t *partition,
+  char *name)
+{
+  vertex_t *result = NIL(vertex_t);
+  st_table *table = PartPartitionReadNameToVertex(partition);
+
+  if (table != NIL(st_table)) {
+    st_lookup(table, name, &result);
+  } /* End of if */
+
+  return result;
+} /* End of Part_PartitionFindVertexByName */
+
+/**Function********************************************************************
+
+  Synopsis    [Finds a vertex in the graph with a certain MddId.]
+
+  Description [Given a MddId, it returns a pointer to a vertex structure if
+  there is a vertex with that mddId in the partition. Otherwise it returns a
+  NULL pointer.]
+
+  SideEffects []
+
+  SeeAlso     [PartVertexInfo]
+
+******************************************************************************/
+vertex_t *
+Part_PartitionFindVertexByMddId(
+  graph_t *partition,
+  int mddId)
+{
+  vertex_t *result = NIL(vertex_t);
+  st_table *table = PartPartitionReadMddIdToVertex(partition);
+
+  if (table != NIL(st_table)) {
+    st_lookup(table, (char *)(long)mddId, &result);
+  } /* End of if */
+
+  return result;
+} /* End of Part_PartitionFindVertexByMddId */
+
+/**Function********************************************************************
+
+  Synopsis [Returns the name of the entity from which the partition
+  was created.]
+
+  SideEffects []
+
+  SeeAlso     [PartPartitionInfo]
+
+******************************************************************************/
+char *
+Part_PartitionReadName(
+   graph_t *partition)
+{
+  return PartPartitionReadName(partition);
+} /* End of Part_PartitionReadName */
+
+/**Function********************************************************************
+
+  Synopsis [Returns the method which was used to create the partition graph.]
+
+  SideEffects []
+
+  SeeAlso     [PartPartitionInfo]
+
+******************************************************************************/
+Part_PartitionMethod
+Part_PartitionReadMethod(
+  graph_t *partition)
+{
+  Part_PartitionMethod	method;
+
+  method = PartPartitionReadMethod(partition);
+  if (method == Part_Default_c)
+    method = Part_Frontier_c;
+  return(method);
+} /* End of Part_PartitionReadMethod */
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the partition method as a string.]
+
+  Description [Returns the method stored in the partition as a new
+  string. The caller of the function has the responsibility of freeing
+  the string. The possible values of the string are: "Inputs-Outputs",
+  "Total", "Partial" or "Frontier".]
+
+  SideEffects []
+
+  SeeAlso     [Part_PartitionPrintStats]
+
+******************************************************************************/
+char *
+Part_PartitionObtainMethodAsString(
+  graph_t *partition)
+{
+  char *resultString;
+
+  assert(partition != NIL(graph_t));
+
+  switch(PartPartitionReadMethod(partition)) {
+    case Part_Total_c:
+      resultString = util_strsav("Total");
+      break;
+    case Part_Partial_c:
+      resultString = util_strsav("Partial");
+      break;
+    case Part_InOut_c:
+      resultString = util_strsav("Inputs-Outputs");
+      break;
+    case Part_Frontier_c:
+    case Part_Default_c:
+      resultString = util_strsav("Frontier");
+      break;
+    case Part_Boundary_c:
+      resultString = util_strsav("Boundary");
+      break;
+    case Part_Fine_c:
+      resultString = util_strsav("Fine");
+      break;
+    default:
+      fail("Unexpected Partition method.");
+  }
+
+  return resultString;
+} /* End of Part_PartitionObtainMethodAsString */
+
+/**Function********************************************************************
+
+  Synopsis    [Function to read the manager attached to the partition.]
+
+  SideEffects []
+
+  SeeAlso     [PartPartitionInfo]
+
+******************************************************************************/
+mdd_manager *
+Part_PartitionReadMddManager(
+  graph_t *partition)
+{
+  return PartPartitionReadMddManager(partition);
+} /* End of Part_PartitionReadMddManager */
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the type of a vertex.]
+
+  SideEffects []
+
+  SeeAlso     [PartVertexInfo Part_VertexType]
+
+******************************************************************************/
+Part_VertexType
+Part_VertexReadType(
+  vertex_t *vertexPtr)
+{
+  return PartVertexReadType(vertexPtr);
+} /* End of Part_VertexReadType */
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the name attached to a vertex.]
+
+  SideEffects []
+
+  SeeAlso     [PartVertexInfo]
+
+******************************************************************************/
+char *
+Part_VertexReadName(
+  vertex_t *vertexPtr)
+{
+  return PartVertexReadName(vertexPtr);
+} /* End of Part_VertexReadName */
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the clusterMembers field  of a vertex.]
+
+  Description [This function does not make sure that the vertex is of clustered
+  type. It is the responsibility of the caller to guarantee that.]
+
+  SideEffects []
+
+  SeeAlso     [PartVertexInfo]
+
+******************************************************************************/
+array_t *
+Part_VertexReadClusterMembers(
+  vertex_t *vertexPtr)
+{
+  return PartVertexReadClusterMembers(vertexPtr);
+} /* End of Part_VertexReadClusterMembers */
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the multi-valued function attached to a vertex.]
+
+  Description [This function does not make sure that the vertex is of single
+  type.  It is the responsibility of the caller to guarantee that.]
+
+  SideEffects []
+
+  SeeAlso     [PartVertexInfo]
+
+******************************************************************************/
+Mvf_Function_t *
+Part_VertexReadFunction(
+  vertex_t *vertexPtr)
+{
+    return PartVertexReadFunction(vertexPtr);
+} /* End of Part_VertexReadFunction */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the multi-valued function of a vertex.]
+
+  SideEffects []
+
+  SeeAlso     [PartVertexInfo]
+
+******************************************************************************/
+void
+Part_VertexSetFunction(
+  vertex_t *vertexPtr,
+  Mvf_Function_t *mvf)
+{
+  assert(PartVertexReadType(vertexPtr) != Part_VertexCluster_c);
+
+  PartVertexSetFunction(vertexPtr, mvf);
+} /* End of Part_VertexSetFunction */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the MddId attached to a vertex.]
+
+  SideEffects []
+
+  SeeAlso     [PartVertexInfo]
+
+******************************************************************************/
+int
+Part_VertexReadMddId(
+  vertex_t *vertexPtr)
+{
+    return PartVertexReadMddId(vertexPtr);
+} /* End of Part_VertexReadMddId */
+
+/**Function********************************************************************
+
+  Synopsis    [Test of a vertex is member of a cluster.]
+
+  SideEffects []
+
+  SeeAlso     [PartVertexInfo Part_VertexReadType]
+
+******************************************************************************/
+boolean
+Part_VertexTestIsClustered(
+  vertex_t *vertexPtr)
+{
+  return PartVertexTestIsClustered(vertexPtr);
+} /* End of Part_VertexTestIsClustered */
+
+/**Function********************************************************************
+
+  Synopsis    [Executes the selected partitioning method.]
+
+  Description [Given a network, and a method, the function creates a partition
+  by using the specified method. This function may be called from any point in
+  the code to create a partition.  In particular, the command partition uses
+  this function to create the partition and store it in the network.<p>
+
+  The function receives two lists of pointers to network nodes, the roots and
+  the leaves. The function will create the partition of the subnetwork between
+  the root and the leave nodes. As a special case, if both lists are passed NIL
+  values, the root and leave lists default to combinational outputs and
+  combinational inputs respectively.
+
+  The parameter <tt>careSet</tt> specifies which minterms in the input space are
+  considered.
+
+  The <tt>nodes</tt> parameter is an optional list of nodes that may be
+  specified in case the <tt>partial</tt> method is used. It represents the set
+  of nodes in the network to be preserved when building the partition. The
+  boolean variable <tt>inTermsOfLeaves</tt> is valid only in the case of
+  the <tt>total</tt> method and provides the option of creating the functions
+  attached to the vertices in terms of the combinational inputs or in terms of
+  their immediate fanin.  Two additional parameters are provided to control the
+  verbosity and the intensity of the sanity check applied to the computation.<p>
+
+  This function is called by the command build_partition_mdds which has a
+  time-out option.  In the event of the execution time going over the time out,
+  the control is returned to the prompt and all the memory allocated by the
+  internal procedures is leaked.]
+
+  SideEffects []
+
+  SeeAlso     [part.h]
+
+******************************************************************************/
+graph_t *
+Part_NetworkCreatePartition(
+  Ntk_Network_t *network,
+  Hrc_Node_t *hnode,
+  char *name,
+  lsList rootList,
+  lsList leaveList,
+  mdd_t *careSet,
+  Part_PartitionMethod method,
+  lsList nodes,
+  boolean inTermsOfLeaves,
+  int verbose,
+  int sanityCheck)
+{
+  graph_t    *partition;
+  long       lap = 0;
+
+  if (verbose) {
+    lap = util_cpu_time();
+  } /* End of if */
+
+  /* Create the new graph to represent the partition */
+  partition = g_alloc();
+  partition->user_data =
+    (gGeneric)PartPartitionInfoCreate(name,
+				      Ntk_NetworkReadMddManager(network),
+				      method);
+
+  switch (method) {
+    case Part_Partial_c:
+      if (verbose) {
+	(void) fprintf(vis_stdout, "Partitioning the system by the Partial");
+	(void) fprintf(vis_stdout, " method\n");
+      } /* End of if */
+      PartPartitionPartial(network, partition, rootList, leaveList, careSet,
+			   nodes, inTermsOfLeaves);
+      break;
+    case Part_Boundary_c:
+      if (verbose) {
+	(void) fprintf(vis_stdout, "Partitioning the system by the Boundary");
+	(void) fprintf(vis_stdout, " method\n");
+      } /* End of if */
+      PartPartitionBoundary(network, hnode, partition, rootList, leaveList, careSet,
+			   inTermsOfLeaves);
+      break;
+    case Part_Total_c:
+      if (verbose) {
+	(void) fprintf(vis_stdout, "Partitioning the circuit by the Total");
+	(void) fprintf(vis_stdout, " method\n");
+      } /* End of if */
+      PartPartitionTotal(network, partition, rootList, leaveList, careSet,
+			 inTermsOfLeaves);
+      break;
+    case Part_Frontier_c:
+    case Part_Default_c:
+      if (verbose) {
+	(void) fprintf(vis_stdout, "Partitioning the circuit by the Frontier");
+	(void) fprintf(vis_stdout, " method\n");
+      } /* End of if */
+      PartPartitionFrontier(network, partition, rootList, leaveList, careSet);
+      break;
+    case Part_Fine_c:
+      if (verbose) {
+	(void) fprintf(vis_stdout, "Partitioning the circuit for the fine-grain");
+	(void) fprintf(vis_stdout, " method\n");
+      } /* End of if */
+      PartPartitionFineGrain(network, partition, careSet);
+      break;
+    case Part_InOut_c:
+      if (verbose) {
+	(void) fprintf(vis_stdout, "Partitioning the circuit by the");
+	(void) fprintf(vis_stdout, " Input-Output method\n");
+      } /* End of if */
+      PartPartitionInputsOutputs(network, partition, rootList,
+				 leaveList, careSet);
+      break;
+    default:
+      (void) fprintf(vis_stdout, "Partition method not implemented yet\n");
+      break;
+  }
+
+  if (sanityCheck >0) {
+    PartPartitionSanityCheck(partition, sanityCheck);
+  }
+
+  if (verbose) {
+    (void) fprintf(vis_stdout, "%.2f (secs) spent in partitioning.\n",
+		   (util_cpu_time() - lap)/1000.0);
+  } /* End of if */
+
+  return partition;
+} /* End of Part_NetworkCreatePartition */
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a duplicate of a partition.]
+
+  SideEffects []
+
+  SeeAlso     [PartVertexInfo, PartPartitionInfo]
+
+******************************************************************************/
+graph_t *
+Part_PartitionDuplicate(
+  graph_t *partition)
+{
+  graph_t          *result;
+  lsGen            gen;
+  vertex_t         *fromVertex;
+  vertex_t         *toVertex;
+  edge_t           *edgePtr;
+
+  result = g_alloc();
+  result->user_data =
+    (gGeneric)PartPartitionInfoCreate(PartPartitionReadName(partition),
+				      PartPartitionReadMddManager(partition),
+				      PartPartitionReadMethod(partition));
+  foreach_vertex(partition, gen, fromVertex) {
+    char *name;
+    int  mddId;
+
+    name = PartVertexReadName(fromVertex);
+    mddId = PartVertexReadMddId(fromVertex);
+    toVertex = g_add_vertex(result);
+
+    st_insert(PartPartitionReadNameToVertex(result), name, (char *)toVertex);
+
+    if (mddId != NTK_UNASSIGNED_MDD_ID) {
+      st_insert(PartPartitionReadMddIdToVertex(result), (char *)(long)mddId,
+		(char *)toVertex);
+    } /* End of if */
+
+    if (PartVertexReadType(fromVertex) == Part_VertexSingle_c) {
+      Mvf_Function_t *mdd;
+
+      mdd = Mvf_FunctionDuplicate(PartVertexReadFunction(fromVertex));
+      toVertex->user_data = (gGeneric)PartVertexInfoCreateSingle(name, mdd,
+								 mddId);
+    }
+    if (PartVertexReadType(fromVertex) == Part_VertexCluster_c) {
+      toVertex->user_data =
+	(gGeneric)PartVertexInfoCreateCluster(name, Part_VertexReadClusterMembers(fromVertex));
+    }
+  }
+
+  foreach_edge(partition, gen, edgePtr) {
+    vertex_t *fromVertexCopy;
+    vertex_t *toVertexCopy;
+
+    fromVertex = g_e_source(edgePtr);
+    toVertex = g_e_dest(edgePtr);
+
+    st_lookup(PartPartitionReadNameToVertex(result),
+	      PartVertexReadName(fromVertex), &fromVertexCopy);
+    st_lookup(PartPartitionReadNameToVertex(result),
+	      PartVertexReadName(toVertex), &toVertexCopy);
+
+    g_add_edge(fromVertexCopy, toVertexCopy);
+  }
+
+  return result;
+} /* End of Part_PartitionDuplicate */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Create reduced partition according to given CTL formulae]
+
+  Comments    [Combinational root and leave nodes are combinational support
+  nodes of given CTL properties.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+graph_t *
+Part_PartCreatePartitionWithCTL(
+  Hrc_Manager_t **hmgr,
+  Part_PartitionMethod method,
+  int verbose,
+  int sanityCheck,
+  boolean inTermsOfLeaves,
+  array_t *ctlArray,
+  array_t *fairArray)
+{
+  return Part_PartCreatePartitionWithCtlAndLtl(hmgr, method, verbose,
+					       sanityCheck, inTermsOfLeaves,
+					       ctlArray, NIL(array_t),
+					       fairArray);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Create reduced partition according to given CTL formulae]
+
+  Comments    [Combinational root and leave nodes are combinational support
+  nodes of given CTL properties.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+graph_t *
+Part_PartCreatePartitionWithCtlAndLtl(
+  Hrc_Manager_t **hmgr,
+  Part_PartitionMethod method,
+  int verbose,
+  int sanityCheck,
+  boolean inTermsOfLeaves,
+  array_t *ctlArray,
+  array_t *ltlArray,
+  array_t *fairArray)
+{
+  char          *modelName;
+  Hrc_Node_t    *currentNode;
+  graph_t       *partition;
+  lsList        latchInputList;
+  lsGen         gen;
+  Ntk_Node_t    *node;
+  Ntk_Network_t *network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+
+  latchInputList = lsCreate();
+  currentNode = Hrc_ManagerReadCurrentNode(*hmgr);
+  modelName = Hrc_NodeReadModelName(currentNode);
+
+  if (method != Part_InOut_c){
+    return NIL(graph_t);
+  }
+
+  PartGetLatchInputListFromCtlAndLtl(network, ctlArray, ltlArray, fairArray,
+				     latchInputList, FALSE);
+
+  Ntk_NetworkForEachCombOutput(network, gen, node){
+    if (Ntk_NodeTestIsLatchInitialInput(node)){
+      lsNewEnd(latchInputList, (lsGeneric)node, LS_NH);
+    }
+  }
+
+  /*
+   * Execute the partition algorithm. If rootList and leaveList are null,
+   * graph includes all network nodes
+   */
+  partition = Part_NetworkCreatePartition(network, currentNode, modelName,
+		 latchInputList, (lsList)0, NIL(mdd_t), method, (lsList)0,
+		 inTermsOfLeaves, verbose, sanityCheck);
+
+  lsDestroy(latchInputList, (void (*)(lsGeneric))0);
+  return partition;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Change partition to include new vertex in root list]
+
+  Comments    [Current partition in increased to include all next state
+  functions for all members in rootList.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Part_PartitionChangeRoots(
+  Ntk_Network_t *network,
+  graph_t *partition,
+  lsList  rootList,
+  int verbosity)
+{
+  if (Part_PartitionReadMethod(partition) != Part_InOut_c){
+    return 0;
+  }
+
+  return
+   PartPartitionInOutChangeRoots(network, partition, rootList, verbosity);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the partition attached to a network.]
+
+  SideEffects []
+
+  SeeAlso     [CommandBuildPartitionMdds]
+
+******************************************************************************/
+graph_t *
+Part_NetworkReadPartition(
+  Ntk_Network_t *network)
+{
+  return (graph_t *)Ntk_NetworkReadApplInfo(network, PART_NETWORK_APPL_KEY);
+} /* End of Part_NetworkReadPartition */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Adds a vertex to the partition representing a set of vertices.]
+
+  SideEffects []
+
+  SeeAlso     [PartVertexInfo]
+
+******************************************************************************/
+vertex_t *
+Part_PartitionCreateClusterVertex(
+  graph_t *partition,
+  char *name,
+  array_t *arrayOfVertices)
+{
+  vertex_t *newVertex;
+
+  newVertex = g_add_vertex(partition);
+  newVertex->user_data = (gGeneric)PartVertexInfoCreateCluster(name,
+							       arrayOfVertices);
+
+  return(newVertex);
+
+} /* End of Part_PartitionCreateClusterVertex */
+
+/**Function********************************************************************
+
+  Synopsis    [ Partition by adding vertices for the nodes in rootList
+  and leaveList.  A node in leaveList may already have a corresponding
+  vertex in the partition graph -- Only creating the new vertex if not exists.
+  Nodes in rootList should NOT have existing vertices in the partition graph.
+  (The caller should guarantee this)
+
+  This routine is for the use in the 'ltl' package. We assume the partition
+  method is Part_Frontier_c.]
+
+  SideEffects [partition might be changed.]
+
+  SeeAlso     [PartPartitionFrontier]
+
+******************************************************************************/
+void
+Part_UpdatePartitionFrontier(
+  Ntk_Network_t *network,
+  graph_t *partition,
+  lsList  rootList,
+  lsList  leaveList,
+  mdd_t   *careSet)
+{
+  PartUpdateFrontier(network, partition, rootList, leaveList, careSet);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Removes a cluster vertex from the partition.]
+
+  SideEffects []
+
+  SeeAlso     [PartVertexInfo]
+
+******************************************************************************/
+void
+Part_VertexInfoFreeCluster(
+  vertex_t *vertexPtr)
+{
+  if (PartVertexReadType(vertexPtr) == Part_VertexCluster_c) {
+    g_delete_vertex(vertexPtr, PartVertexInfoFree, (void (*)(gGeneric))0);
+  } /* End of then */
+  else {
+    (void) fprintf(vis_stderr, "Warning -- Inconsistent vertex deletion in");
+    (void) fprintf(vis_stderr, " partition package\n");
+  }
+} /* End of Part_VertexInfoFreeCluster */
+
+/**Function********************************************************************
+
+  Synopsis [Test if the functions attached to a set of vertices in the
+  partition are completely specified.]
+
+  Description [Given a set of vertices (roots) build their functions in terms
+  of a second set of vertices (leaves) and test if the functions are
+  completely specified.]
+
+  SideEffects []
+
+  SeeAlso     [Part_PartitionTestDeterministic]
+
+******************************************************************************/
+boolean
+Part_PartitionTestCompletelySp(
+  graph_t *partition,
+  array_t *roots,
+  st_table *leaves)
+{
+  array_t *mvfFunctions;
+  vertex_t *vertexPtr;
+  Mvf_Function_t *functionPtr;
+  boolean result = TRUE;
+  int i;
+  char *vertexName;
+
+  mvfFunctions = Part_PartitionCollapse(partition, roots, leaves, NIL(mdd_t));
+
+  arrayForEachItem(Mvf_Function_t *, mvfFunctions, i, functionPtr) {
+    vertexPtr = array_fetch(vertex_t *, roots, i);
+    vertexName = PartVertexReadName(vertexPtr);
+    if (!Mvf_FunctionTestIsCompletelySpecified(functionPtr)) {
+      error_append("Vertex ");
+      error_append(vertexName);
+      error_append(" is not completely specified\n");
+      result = FALSE;
+    } /* End of if */
+
+    /* We don't need the Mvf_Function any more, so we delete it */
+    Mvf_FunctionFree(functionPtr);
+  }
+
+  /* Clean up*/
+  array_free(mvfFunctions);
+
+  return result;
+} /* End of Part_PartitionTestCompletelySp */
+
+/**Function********************************************************************
+
+  Synopsis    [Test if the functions attached to a set of vertices in the
+  partition are deterministic.]
+
+  Description [Given a set of vertices (roots) build their functions in terms
+  of a second set of vertices (leaves) and test if the functions are
+  deterministic.]
+
+  SideEffects []
+
+  SeeAlso     [Part_PartitionTestCompletelySp]
+
+******************************************************************************/
+boolean
+Part_PartitionTestDeterministic(
+  graph_t *partition,
+  array_t *roots,
+  st_table *leaves)
+{
+  array_t *mvfFunctions;
+  vertex_t *vertexPtr;
+  Mvf_Function_t *functionPtr;
+  boolean result = TRUE;
+  int i;
+  char *vertexName;
+
+  mvfFunctions = Part_PartitionCollapse(partition, roots, leaves, NIL(mdd_t));
+
+  arrayForEachItem(Mvf_Function_t *, mvfFunctions, i, functionPtr) {
+    vertexPtr = array_fetch(vertex_t *, roots, i);
+    vertexName = PartVertexReadName(vertexPtr);
+    if (!Mvf_FunctionTestIsDeterministic(functionPtr)) {
+      error_append("Vertex ");
+      error_append(vertexName);
+      error_append(" is non-deterministic\n");
+      result = FALSE;
+    } /* End of if */
+
+    /* We don't need the Mvf_Function any more, so we delete it */
+    Mvf_FunctionFree(functionPtr);
+  }
+
+  /* Clean up*/
+  array_free(mvfFunctions);
+
+  return result;
+} /* End of Part_PartitionTestDeterministic */
+
+/**Function********************************************************************
+
+  Synopsis    [Create latch input nodes list from CTL properties and fairness
+  constraints]
+
+  Comments    []
+
+  SideEffects [latchInputList is changed]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Part_PartitionGetLatchInputListFromCTL(
+  Ntk_Network_t *network,
+  array_t *ctlArray,
+  array_t *fairArray,
+  lsList  latchInputList)
+{
+  return PartGetLatchInputListFromCTL( network, ctlArray, fairArray,
+				       latchInputList);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Create latch input nodes list from CTL properties and fairness
+  constraints]
+
+  Comments    []
+
+  SideEffects [latchInputList is changed]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Part_PartitionGetLatchInputListFromCtlAndLtl(
+  Ntk_Network_t *network,
+  array_t *ctlArray,
+  array_t *ltlArray,
+  array_t *fairArray,
+  lsList  latchInputList,
+  boolean stopAtLatch)
+{
+  return PartGetLatchInputListFromCtlAndLtl( network, ctlArray, ltlArray,
+					     fairArray,
+					     latchInputList, stopAtLatch);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Prints statistics about the partition DAG.]
+
+  Comments    [If the parameter printNodeNames is true, the function prints
+  names of the network nodes represented by vertices in the partition graph.]
+
+  SideEffects []
+
+  SeeAlso     [PartPartitionInfo]
+
+******************************************************************************/
+void
+Part_PartitionPrintStats(
+  FILE *fp,
+  graph_t *partition,
+  boolean printNodeNames)
+{
+  lsList vertexList = g_get_vertices(partition);
+  vertex_t *vertexPtr;
+  array_t *functions;
+  Mvf_Function_t* vertexFunction;
+  mdd_t *mddPtr;
+  lsGen gen;
+  char *methodName;
+  int numVertices = lsLength(vertexList);
+  int numSources;
+  int numSinks;
+  int i;
+
+  /* Obtain the method name as a string */
+  methodName = Part_PartitionObtainMethodAsString(partition);
+
+  /*
+   * Count the number of sources and sinks and at the same time store all the
+   * bdd_t of every vertex in a common array to compute the shared size.
+   */
+  numSources = 0;
+  numSinks = 0;
+  functions = array_alloc(mdd_t *, 0);
+  if (printNodeNames) {
+    (void) fprintf(fp, "Network nodes represented as vertices in the ");
+    (void) fprintf(fp, "partition:\n");
+  }
+  foreach_vertex(partition, gen, vertexPtr) {
+    if (lsLength(g_get_in_edges(vertexPtr)) == 0) {
+      numSources++;
+    } /* End of if */
+    if (lsLength(g_get_out_edges(vertexPtr)) == 0) {
+      numSinks++;
+    } /* End of if */
+    if (PartVertexReadType(vertexPtr) == Part_VertexSingle_c) {
+      if (printNodeNames) {
+	if (PartVertexReadName(vertexPtr) != NIL(char)) {
+	  (void) fprintf(fp, "%s\n", PartVertexReadName(vertexPtr));
+	}
+      }
+      vertexFunction = PartVertexReadFunction(vertexPtr);
+      if (vertexFunction != NIL(Mvf_Function_t)) {
+	Mvf_FunctionForEachComponent(vertexFunction, i, mddPtr) {
+	  array_insert_last(mdd_t *, functions, mddPtr);
+	}
+      } /* End of if */
+    } /* End of if */
+  } /* foreach_vertex*/
+
+  /* Print results */
+  (void)fprintf(fp, "Method %s, %d sinks, %d sources,", methodName, numSinks, numSources);
+  (void)fprintf(fp, " %d total vertices,", numVertices);
+  (void)fprintf(fp, " %ld mdd nodes\n", bdd_size_multiple(functions));
+
+  /* Clean up */
+  FREE(methodName);
+  array_free(functions);
+
+  return;
+} /* End of Part_PartitionPrintStats */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Initializes the information attached to the graph of the
+  partition.]
+
+  Description [Allocates the memory needed for the information attached to the
+  graph structure.]
+
+  SideEffects []
+
+  SeeAlso     [PartPartitionInfo PartPartitionInfoFree]
+
+******************************************************************************/
+PartPartitionInfo_t *
+PartPartitionInfoCreate(
+  char *name,
+  mdd_manager *manager,
+  Part_PartitionMethod method)
+{
+  PartPartitionInfo_t *recordPartition = ALLOC(PartPartitionInfo_t, 1);
+
+  recordPartition->name          = util_strsav(name);
+  recordPartition->method        = method;
+  recordPartition->mddManager    = manager;
+  recordPartition->nameToVertex  = st_init_table(strcmp,st_strhash);
+  recordPartition->mddIdToVertex = st_init_table(st_numcmp, st_numhash);
+
+  return recordPartition;
+} /* End of PartPartitionInfoCreate */
+
+/**Function********************************************************************
+
+  Synopsis [Deallocates the user information in the graph.]
+
+  Description [Deallocates the user information in the graph. Does not free the
+  MDD manager associated with the partition.]
+
+  SideEffects []
+
+  SeeAlso     [PartPartitionInfoCreate]
+
+******************************************************************************/
+void
+PartPartitionInfoFree(
+  gGeneric partitionInfo)
+{
+  if (((PartPartitionInfo_t *)partitionInfo)->name != NIL(char)) {
+    FREE(((PartPartitionInfo_t *)partitionInfo)->name);
+  }
+
+  st_free_table(((PartPartitionInfo_t *)partitionInfo)->nameToVertex);
+  st_free_table(((PartPartitionInfo_t *)partitionInfo)->mddIdToVertex);
+
+  FREE(partitionInfo);
+} /* End of PartPartitionInfoFree */
+
+/**Function********************************************************************
+
+  Synopsis [Initializes the information attached to a single vertex.]
+
+  SideEffects []
+
+  SeeAlso     [PartVertexInfo]
+
+******************************************************************************/
+PartVertexInfo_t *
+PartVertexInfoCreateSingle(
+  char *name,
+  Mvf_Function_t *mvf,
+  int mddId)
+{
+  PartVertexInfo_t *result;
+
+  result                    = ALLOC(PartVertexInfo_t, 1);
+  result->type              = Part_VertexSingle_c;
+  result->name              = util_strsav(name);
+  result->functionality.mvf = mvf;
+  result->mddId             = mddId;
+  result->isClustered       = 0;
+
+  return result;
+} /* End of PartVertexInfoCreateSingle */
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a cluster vertex in the partition.]
+
+  SideEffects []
+
+  SeeAlso     [PartVertexInfo]
+
+******************************************************************************/
+PartVertexInfo_t *
+PartVertexInfoCreateCluster(
+  char *name,
+  array_t *vertexArray)
+{
+  PartVertexInfo_t *result;
+  vertex_t *auxPtr;
+  int i;
+
+  /* Make sure all the nodes are simple nodes */
+  for(i = 0; i < array_n(vertexArray); i++) {
+    auxPtr = array_fetch(vertex_t *, vertexArray, i);
+    if (PartVertexReadType(auxPtr) == Part_VertexCluster_c) {
+      fail("Only one level of hierarchy allowed in the partition");
+    } /* End of if */
+    if (PartVertexTestIsClustered(auxPtr)) {
+      fail("Partition: Clustering vertex already member of another cluster");
+    } /* End of then */
+    else {
+      PartVertexSetIsClustered(auxPtr, 1);
+    }
+  } /* End of for */
+
+  result                               = ALLOC(PartVertexInfo_t, 1);
+  result->type                         = Part_VertexCluster_c;
+  result->name                         = util_strsav(name);
+  result->functionality.clusterMembers = array_dup(vertexArray);
+
+  result->mddId                        = NTK_UNASSIGNED_MDD_ID;
+  result->isClustered                  = 0;
+
+  return result;
+} /* End of PartVertexInfoCreateCluster */
+
+/**Function********************************************************************
+
+  Synopsis [Deallocates the user information attached to a vertex.]
+
+  SideEffects []
+
+  SeeAlso     [PartVertexInfo]
+
+******************************************************************************/
+void
+PartVertexInfoFree(
+  gGeneric vertexInfo
+   )
+{
+  if (((PartVertexInfo_t *)vertexInfo)->type == Part_VertexSingle_c) {
+    /* Free the function attached to the node if any */
+    if (((PartVertexInfo_t *)vertexInfo)->functionality.mvf !=
+	NIL(Mvf_Function_t)) {
+      Mvf_FunctionFree(((PartVertexInfo_t *)vertexInfo)->functionality.mvf);
+    } /* End of if */
+  } /* End of then */
+  else {
+    if (((PartVertexInfo_t *)vertexInfo)->functionality.clusterMembers !=
+	NIL(array_t)) {
+      array_free(((PartVertexInfo_t *)vertexInfo)->functionality.clusterMembers);
+    } /* End of if */
+  } /* End of if-then-else */
+
+  if (((PartVertexInfo_t *)vertexInfo)->name != NIL(char)) {
+    FREE(((PartVertexInfo_t *)vertexInfo)->name);
+  }
+
+  FREE(vertexInfo);
+} /* End of PartVertexInfoFree */
+
+/**Function********************************************************************
+
+  Synopsis [Verifies that the information in the nameToVertex table of
+  a graph is consistent.]
+
+  SideEffects []
+
+  SeeAlso     [PartPartitionInfo]
+
+******************************************************************************/
+void
+PartPartitionSanityCheck(
+  graph_t *partition,
+  int intensity)
+{
+  st_table *table;
+  lsList vertexList = g_get_vertices(partition);
+  lsGen lgen;
+  vertex_t *vertex, *rvertex;
+
+  /* Consistency in the nameToVertex table */
+  table = PartPartitionReadNameToVertex(partition);
+
+  /*
+   * The number of elements in the nameToVertex table and the number
+   * of vertices agrees
+   */
+  if (lsLength(g_get_vertices(partition)) != st_count(table)) {
+    (void) fprintf(vis_stderr, "Warning -- NameToVertex table incomplete in ");
+    (void) fprintf(vis_stderr, " graph\n");
+    if (intensity > 1) {
+      (void) fprintf(vis_stderr, "  %d vertices in the graph and %d entries",
+		     lsLength(g_get_vertices(partition)),
+		     st_count(table));
+      (void) fprintf(vis_stderr, " in the nameToVertex table\n");
+    } /* End of if */
+  } /* End of if */
+
+  lsForEachItem(vertexList, lgen, vertex) {
+    char *name = PartVertexReadName(vertex);
+    if (!st_lookup(table, name, &rvertex) ||
+	strcmp(PartVertexReadName(vertex),PartVertexReadName(rvertex)) != 0) {
+      (void) fprintf(vis_stderr, "Warning -- Inconsistency detected in");
+      (void) fprintf(vis_stderr, " the partition data-base\n");
+    }
+  }
+
+  /* Consistency in the mddIdToVertexTable */
+  table = PartPartitionReadMddIdToVertex(partition);
+  lsForEachItem(vertexList, lgen, vertex) {
+    int mddId = PartVertexReadMddId(vertex);
+    if((mddId != NTK_UNASSIGNED_MDD_ID) &&
+       (!st_lookup(table, (char *)(long)mddId, &rvertex) ||
+	PartVertexReadMddId(vertex) != PartVertexReadMddId(rvertex))) {
+      (void) fprintf(vis_stderr, "Warning -- Inconsistency detected in the");
+      (void) fprintf(vis_stderr, " partition data-base\n");
+    }
+  }
+
+  /*
+   * Make sure that the mdd Id NTK_UNASSIGNED_MDD_ID does not appear in the
+   * mddIdToVertex node.
+   */
+  table = PartPartitionReadMddIdToVertex(partition);
+  if (st_is_member(table, (char *) NTK_UNASSIGNED_MDD_ID)) {
+    (void) fprintf(vis_stderr, "Warning -- Inconsistency detected in the");
+    (void) fprintf(vis_stderr, " partition data-base\n");
+  } /* End of if */
+
+  /* Check the Mvfs in the vertices of the partition.*/
+  if (intensity > 1) {
+    lsForEachItem(vertexList, lgen, vertex) {
+      Mvf_Function_t *function = PartVertexReadFunction(vertex);
+      int i;
+
+      (void) fprintf(vis_stderr, "Vertex: %s, mddId: %d, Clustered: %c\n",
+		     PartVertexReadName(vertex),
+		     PartVertexReadMddId(vertex),
+		     (PartVertexReadType(vertex) == Part_VertexCluster_c)?'t':'f');
+      for(i = 0; i < Mvf_FunctionReadNumComponents(function); i ++) {
+	mdd_t *unit = Mvf_FunctionObtainComponent(function, i);
+	boolean x;
+
+	if (intensity > 2) {
+	  (void) fprintf(vis_stderr, "BDD_T: %lx, %lx\n",
+			 (unsigned long) bdd_get_node(unit, &x),
+			 (unsigned long) mdd_get_manager(unit));
+	}
+      } /* End of for */
+    }
+  } /* End of if */
+
+  /* ToDo: Check for redundant name in the list of vertices */
+} /* End of PartPartitionSanityCheck */
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the support of an array of mdds.]
+
+  Description [Computes the support of a multi-valued function. It is
+  just the union of the supports of every component of the function.]
+
+  Comment [The reason why is it returned in a table is because it's very likely
+  that questions such as, "is certain Id part of the support ?"  will happen.]
+
+  SideEffects []
+
+  SeeAlso     [PartVertexCreateFaninEdges]
+
+******************************************************************************/
+st_table *
+PartCreateFunctionSupportTable(
+  Mvf_Function_t *mvf)
+{
+  mdd_manager  *mddManager;        /* Manager for the MDDs */
+  array_t      *support;
+  st_table     *mddSupport = st_init_table(st_numcmp, st_numhash);
+  int          numComponents = Mvf_FunctionReadNumComponents(mvf);
+  int          j, k;
+  mdd_t        *unit;
+
+  assert(numComponents!= 0);
+
+  mddManager = Mvf_FunctionReadMddManager(mvf);
+
+  /*
+   * compute the support of an mdd as the union of supports of every
+   * function component
+   */
+  for(j = 0; j < numComponents; j++) {
+    unit = Mvf_FunctionReadComponent(mvf, j);
+    support = mdd_get_support(mddManager, unit);
+
+    /* For every element of its support */
+    for(k = 0; k < array_n(support); k++) {
+      st_insert(mddSupport, (char *)(long)array_fetch(int, support, k), (char *)0);
+    } /* End of for */
+    array_free(support);
+  } /* End of for */
+
+  return mddSupport;
+} /* End of PartCreateFunctionSupportTable */
+
+/**Function********************************************************************
+
+  Synopsis [Creates fanin edges of a vertex based on MDD support.]
+
+  Description [Computes the support of the function attached to a vertex and
+  adds to the graph the edges from the vertices representing those variables
+  to the given vertex.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+PartPartitionCreateVertexFaninEdges(
+  graph_t  *partition,
+  vertex_t *vertexPtr)
+{
+  vertex_t       *fromVertex;
+  Mvf_Function_t *vertexFunction;
+  st_table       *support;
+  st_table       *mddIdToVertex;
+  st_generator   *stGen;
+  long            mddId;
+
+  mddIdToVertex = PartPartitionReadMddIdToVertex(partition);
+  vertexFunction = PartVertexReadFunction(vertexPtr);
+  support = PartCreateFunctionSupportTable(vertexFunction);
+
+  /* Create the edges for every element in support */
+  st_foreach_item(support, stGen, &mddId, NULL) {
+    st_lookup(mddIdToVertex, (char *)mddId, &fromVertex);
+    /* Make sure no self loops are created */
+    if (fromVertex != vertexPtr) {
+      g_add_edge(fromVertex, vertexPtr);
+    } /* End of if */
+  }
+
+  st_free_table(support);
+} /* End of PartPartitionCreateVertexFaninEdges */
+
+/**Function********************************************************************
+
+  Synopsis [Prints information about the Partition through standard output.]
+
+  Description [ The format used for printing is <b>dot</b>, a tool for
+  graph visualization developed at AT&T. It can be obtained from <a
+  href="http://www.research.att.com/orgs/ssr/book/reuse">
+  http://www.research.att.com/orgs/ssr/book/reuse</a>. The function
+  receives as a parameter a file pointer in case the print wants to be
+  redirected. This function is used by the command routine
+  CommandPrintPartition.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+PartPartitionPrint(
+  FILE *fp,
+  graph_t *partition)
+{
+  lsGen      gen;           /* To iterate over edges */
+  edge_t     *edgePtr;      /* Will hold the edge being processed */
+  vertex_t   *fromVertex;   /* Will hold the vertex source of the edge */
+  vertex_t   *toVertex;     /* Will hold the destination of the edge */
+  st_table   *vertexToId;   /* To lookup the ordinal of a vertex */
+  time_t      now           = time(0);
+  struct tm  *nowStructPtr  = localtime(& now);
+  char       *nowTxt        = asctime(nowStructPtr);
+  char       *partitionName = PartPartitionReadName(partition);
+  int        vertexId;
+  int        clusterId;
+
+  /*
+   * Write out the header for the output file.
+   */
+
+  (void) fprintf(fp, "# %s\n", Vm_VisReadVersion());
+  (void) fprintf(fp, "# partition name: %s\n", partitionName);
+  (void) fprintf(fp, "# generated: %s", nowTxt);
+  (void) fprintf(fp, "#\n");
+
+  (void) fprintf(fp, "# Partition with %d vertices and %d edges\n",
+		 lsLength(g_get_vertices(partition)),
+		 lsLength(g_get_edges(partition)));
+
+  (void) fprintf(fp, "digraph \"%s\" {\n  rotate=90;\n", partitionName);
+  (void) fprintf(fp, "  margin=0.5;\n  label=\"%s\";\n", partitionName);
+  (void) fprintf(fp, "  size=\"10,7.5\";\n  ratio=\"fill\";\n");
+
+
+  vertexToId = st_init_table(st_ptrcmp, st_ptrhash);
+
+  vertexId = 0;
+  clusterId = 0;
+  foreach_vertex(partition, gen, fromVertex) {
+    if (PartVertexReadType(fromVertex) == Part_VertexCluster_c) {
+      array_t *members = PartVertexReadClusterMembers(fromVertex);
+      vertex_t *auxPtr;
+      int i;
+
+      (void) fprintf(fp, "  subgraph cluster%d {\n", clusterId++);
+      (void) fprintf(fp, "    label = \"%s\";\n",
+		     PartVertexReadName(fromVertex));
+      arrayForEachItem(vertex_t *, members, i, auxPtr) {
+	(void) fprintf(fp, "  ");
+	st_insert(vertexToId, (char *)auxPtr, (char *)(long)vertexId);
+	PrintVertexDescription(fp, auxPtr, vertexId++);
+      }
+      (void) fprintf(fp, "  }\n");
+    } /* End of then */
+    else if (!PartVertexTestIsClustered(fromVertex)) {
+      st_insert(vertexToId, (char *)fromVertex, (char *)(long)vertexId);
+      PrintVertexDescription(fp, fromVertex, vertexId++);
+    }
+
+  }
+
+  foreach_edge(partition, gen, edgePtr) {
+    fromVertex = g_e_source(edgePtr);
+    toVertex = g_e_dest(edgePtr);
+
+    st_lookup_int(vertexToId, (char *)fromVertex, &vertexId);
+    (void) fprintf(fp, "  node%d -> ", vertexId);
+
+    st_lookup_int(vertexToId, (char *)toVertex, &vertexId);
+    (void) fprintf(fp, "node%d;\n", vertexId);
+  } /* End of foreach_edge */
+
+  (void) fprintf(fp, "}\n");
+
+  st_free_table(vertexToId);
+
+  return 1;
+} /* End of PartPartitionPrint */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Create latch nodes list and leave nodes list form
+  CTL properties and fairness constraints]
+
+  Comments    []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+PartGetLatchInputListFromCTL(
+  Ntk_Network_t *network,
+  array_t *ctlArray,
+  array_t *fairArray,
+  lsList  latchInputList)
+{
+  return PartGetLatchInputListFromCtlAndLtl(network, ctlArray, NIL(array_t),
+					    fairArray, latchInputList,
+					    FALSE);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Create latch inputs list form properties and fairness
+  constraints]
+
+  Comments [Return all the Cone-Of-Influence nodes if stopAtLatch is
+  FALSE; otherwise, return only the nodes up to the immediate
+  support.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+PartGetLatchInputListFromCtlAndLtl(
+  Ntk_Network_t *network,
+  array_t *ctlArray,
+  array_t *ltlArray,
+  array_t *fairArray,
+  lsList  latchInputList,
+  boolean stopAtLatch)
+{
+  int i;
+  Ctlp_Formula_t  *ctlFormula;
+  Ctlsp_Formula_t *ltlFormula;
+  st_table *formulaNodes;
+  st_generator *stGen;
+  array_t *nodeArray;
+  array_t *formulaCombNodes;
+  Ntk_Node_t *node;
+
+
+  formulaNodes = st_init_table( st_ptrcmp, st_ptrhash );
+
+  if ( formulaNodes == NIL(st_table)){
+    return 0;
+  }
+
+ /*
+  * Extract nodes in CTL/LTL properties
+  */
+  if ( ctlArray != NIL(array_t)){
+    arrayForEachItem( Ctlp_Formula_t *, ctlArray, i, ctlFormula ) {
+      Mc_NodeTableAddCtlFormulaNodes( network, ctlFormula, formulaNodes );
+    }
+  }
+  if ( ltlArray != NIL(array_t)){
+    arrayForEachItem( Ctlsp_Formula_t *, ltlArray, i, ltlFormula ) {
+      Mc_NodeTableAddLtlFormulaNodes( network, ltlFormula, formulaNodes );
+    }
+  }
+
+ /*
+  * Extract nodes in fairness properties
+  */
+  if ( fairArray != NIL(array_t)){
+    arrayForEachItem( Ctlp_Formula_t *, fairArray, i, ctlFormula ) {
+      Mc_NodeTableAddCtlFormulaNodes( network, ctlFormula, formulaNodes );
+    }
+  }
+
+  nodeArray = array_alloc( Ntk_Node_t *, 0 );
+  st_foreach_item( formulaNodes, stGen, &node, NULL) {
+    array_insert_last( Ntk_Node_t *, nodeArray, node );
+  }
+
+  st_free_table( formulaNodes );
+
+ /*
+  * Get all combinational support nodes in network from formula nodes
+  */
+  formulaCombNodes = Ntk_NodeComputeCombinationalSupport( network,
+		     nodeArray, stopAtLatch );
+  array_free(nodeArray);
+ /*
+  * Root list includes latch data input nodes
+  */
+  arrayForEachItem( Ntk_Node_t *, formulaCombNodes, i, node ) {
+    if ( Ntk_NodeTestIsLatch( node ) ) {
+      Ntk_Node_t *tempNode = Ntk_LatchReadDataInput( node );
+      lsNewEnd(latchInputList, (lsGeneric)tempNode, LS_NH);
+    }
+  }
+
+  array_free(formulaCombNodes);
+
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Create latch nodes list form properties and fairness
+  constraints]
+
+  Comments [Return all the Cone-Of-Influence nodes if stopAtLatch is
+  FALSE; otherwise, return only the nodes up to the immediate
+  support.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+PartGetLatchListFromCtlAndLtl(
+  Ntk_Network_t *network,
+  array_t *ctlArray,
+  array_t *ltlArray,
+  array_t *fairArray,
+  lsList  latchInputList,
+  boolean stopAtLatch)
+{
+  int i;
+  Ctlp_Formula_t  *ctlFormula;
+  Ctlsp_Formula_t *ltlFormula;
+  st_table *formulaNodes;
+  st_generator *stGen;
+  array_t *nodeArray;
+  array_t *formulaCombNodes;
+  Ntk_Node_t *node;
+
+
+  formulaNodes = st_init_table( st_ptrcmp, st_ptrhash );
+
+  if ( formulaNodes == NIL(st_table)){
+    return 0;
+  }
+
+ /*
+  * Extract nodes in CTL/LTL properties
+  */
+  if ( ctlArray != NIL(array_t)){
+    arrayForEachItem( Ctlp_Formula_t *, ctlArray, i, ctlFormula ) {
+      Mc_NodeTableAddCtlFormulaNodes( network, ctlFormula, formulaNodes );
+    }
+  }
+  if ( ltlArray != NIL(array_t)){
+    arrayForEachItem( Ctlsp_Formula_t *, ltlArray, i, ltlFormula ) {
+      Mc_NodeTableAddLtlFormulaNodes( network, ltlFormula, formulaNodes );
+    }
+  }
+
+ /*
+  * Extract nodes in fairness properties
+  */
+  if ( fairArray != NIL(array_t)){
+    arrayForEachItem( Ctlp_Formula_t *, fairArray, i, ctlFormula ) {
+      Mc_NodeTableAddCtlFormulaNodes( network, ctlFormula, formulaNodes );
+    }
+  }
+
+  nodeArray = array_alloc( Ntk_Node_t *, 0 );
+  st_foreach_item( formulaNodes, stGen, &node, NULL) {
+    array_insert_last( Ntk_Node_t *, nodeArray, node );
+  }
+
+  st_free_table( formulaNodes );
+
+ /*
+  * Get all combinational support nodes in network from formula nodes
+  */
+  formulaCombNodes = Ntk_NodeComputeCombinationalSupport( network,
+		     nodeArray, stopAtLatch );
+  array_free(nodeArray);
+ /*
+  * Root list includes latch data input nodes
+  */
+  arrayForEachItem( Ntk_Node_t *, formulaCombNodes, i, node ) {
+    if ( Ntk_NodeTestIsLatch( node ) ) {
+      lsNewEnd(latchInputList, (lsGeneric)node, LS_NH);
+    }
+  }
+
+  array_free(formulaCombNodes);
+
+  return 1;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the declaration of a vertex in dot format.]
+
+  SideEffects []
+
+  SeeAlso     [Part_PartitionPrint]
+
+******************************************************************************/
+static void
+PrintVertexDescription(
+  FILE *fp,
+  vertex_t *vertexPtr,
+  int order)
+{
+  char *name = PartVertexReadName(vertexPtr);
+
+  (void) fprintf(fp, "  node%d [label=", order);
+  if (name != NIL(char)) {
+    (void) fprintf(fp, "\"%s\"", name);
+  }
+  else {
+    (void) fprintf(fp, "\"None\"");
+  }
+  (void) fprintf(fp, "]; \n");
+} /* End of PrintVertexDescription */
Index: vis_dev/vis-2.3/src/part/partPartial.c
===================================================================
--- vis_dev/vis-2.3/src/part/partPartial.c	(revision 14)
+++ vis_dev/vis-2.3/src/part/partPartial.c	(revision 14)
@@ -0,0 +1,325 @@
+/**CFile***********************************************************************
+
+  FileName    [partPartial.c]
+
+  PackageName [part]
+
+  Synopsis [Implements the partition of the network with respect to a
+  list of nodes provided by the user.]
+
+  Description [The network is composed of an arbitrary set of nodes, each of
+  them implementing some function. This partitioning method will produce a
+  graph representing the network in which the nodes specified in a list will be
+  preserved in the graph structure. Different heuristics will control the
+  structure of the rest of the partition.]
+
+  SeeAlso     [partInOut.c partTotal.c]
+
+  Author      [Sunil P Khatri]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "partInt.h"
+
+static char rcsid[] UNUSED = "$Id: partPartial.c,v 1.10 2005/04/16 14:52:45 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Implements the partition with respect to the given list of
+  nodes.]
+
+  SideEffects []
+
+  SeeAlso     [PartPartitionTotal PartPartitionInputsOutputs]
+
+******************************************************************************/
+void
+PartPartitionPartial(
+  Ntk_Network_t *network,
+  graph_t       *partition,
+  lsList        rootList,
+  lsList        leaveList,
+  mdd_t         *careSet,
+  lsList        nodeList,
+  int           inTermsOfCombInputs)
+{
+  Ntk_Node_t     *node;            /* Pointer to iterate over nodes */
+  Mvf_Function_t *mddFunction;     /* Pointer to a MDD */
+  mdd_manager    *manager;         /* Mdd manager in the partition */
+  st_table       *tableOfLeaves;   /* To store the leaves of the graph */
+  st_table       *mddIdToNodeName; /* For quick lookup of node's name */
+  array_t        *arrayOfMvf;      /* To store the next state functions */
+  array_t        *arrayOfRoots;    /* To store the roots of the graph */
+  lsList         sinkList;         /* Vertices representing comb. outputs */
+  lsGen          gen;              /* To iterate over lists */
+  vertex_t       *toVertex;        /* Will hold the current function vertex */
+  int            i;                /* Index for loops */
+  long           mddId;            /* Will hold the mddId being processed */
+  st_table       *mddSupport;      /* To store the support of the Mvf_Function */
+  st_generator   *stGen;           /* To iterate over the MddIds of the support */
+  vertex_t       *fromVertex;      /* Will hold the current vertex in the support */
+  char           *nodeName;
+  array_t        *singletonMvfArray;
+  array_t        *singletonArrayOfRoots;
+  array_t        *tmpArrayOfMvf;
+  Mvf_Function_t *nodeMvf;
+  lsList         sortedListOfNodes;     
+  array_t        *sortedArrayOfPartitionNodes;
+  array_t        *unsortedArrayOfPartitionNodes;
+  st_table       *tableOfPartitionNodes;
+  array_t        *validNodeArray;
+  array_t        *invalidNodeArray;
+  int            chars_printed;
+
+  assert(rootList == (lsList)0);
+  assert(leaveList == (lsList)0);
+  manager = PartPartitionReadMddManager(partition);
+  invalidNodeArray = array_alloc(char *, 0);
+  validNodeArray = array_alloc(char *, 0);
+  
+  /* check that nodes in nodeList are valid ones */
+  lsForEachItem(nodeList, gen, nodeName){
+    node = Ntk_NetworkFindNodeByName(network, nodeName);
+    if(node == NIL(Ntk_Node_t)){
+      array_insert_last(char *, invalidNodeArray, nodeName);
+    }
+    else{
+      array_insert_last(char *, validNodeArray, nodeName);      
+    }
+  }
+  if(array_n(invalidNodeArray) > 0){
+    fprintf(stdout, "The following node(s) are being ignored in the partition:\n");
+    chars_printed = 0;
+    for(i = 0; i < array_n(invalidNodeArray); i++){
+      fprintf(stdout, "%s ", array_fetch(char *, invalidNodeArray, i));
+      chars_printed += strlen(array_fetch(char *, invalidNodeArray, i));
+      if(chars_printed >60){
+	chars_printed = 0;
+	fprintf(stdout, "\n");
+      }
+    }
+    fprintf(stdout, "\nThey are either invalid names or have been swept away at \n");
+    fprintf(stdout, "the end of the flatten_network command. Use <flatten_network -s> \n");
+    fprintf(stdout, "to avoid performing a sweep after the flatten command, \n");	 
+  }
+  array_free(invalidNodeArray);
+  
+
+  /* Make the combinational input  nodes into leaves */
+  tableOfLeaves = st_init_table(st_ptrcmp, st_ptrhash);
+  mddIdToNodeName = st_init_table(st_numcmp, st_numhash);
+  Ntk_NetworkForEachCombInput(network, gen, node) {
+    st_insert(tableOfLeaves, (char *)node, (char *) (long) (-1) );
+    st_insert(mddIdToNodeName, (char *) (long)Ntk_NodeReadMddId(node), 
+	      Ntk_NodeReadName(node));
+  }
+  
+  /* create temporary array and table of partition nodes */
+  unsortedArrayOfPartitionNodes = array_alloc(Ntk_Node_t *, 0);  
+  tableOfPartitionNodes = st_init_table(st_ptrcmp, st_ptrhash);
+  for(i = 0; i < array_n(validNodeArray); i++){
+    nodeName = array_fetch(char *, validNodeArray, i);
+    node = Ntk_NetworkFindNodeByName(network, nodeName);
+    assert(!Ntk_NodeTestIsShadow(node));
+    /* make sure that the node is not a CI or CO */
+    if(!Ntk_NodeTestIsCombInput(node) && !Ntk_NodeTestIsCombOutput(node)){
+      array_insert_last(Ntk_Node_t *, unsortedArrayOfPartitionNodes, node);
+      st_insert(tableOfPartitionNodes, (char *) node, (char *) (long) (-1));
+    }
+  }
+  array_free(validNodeArray);
+
+  /* create sorted array of partition nodes */
+  sortedListOfNodes = Ntk_NetworkComputeTopologicalOrder(network, unsortedArrayOfPartitionNodes, tableOfLeaves);
+  sortedArrayOfPartitionNodes = array_alloc(Ntk_Node_t *, 0);  
+  lsForEachItem(sortedListOfNodes, gen, node){
+    /* sortedListOfNodes includes many internal nodes, need to filter them out */
+    if(st_is_member(tableOfPartitionNodes, (char *) node)){
+      array_insert_last(Ntk_Node_t *, sortedArrayOfPartitionNodes, node);      
+    }   
+  }
+  array_free(unsortedArrayOfPartitionNodes);
+  lsDestroy(sortedListOfNodes, (void (*)(lsGeneric))0);  
+  st_free_table(tableOfPartitionNodes);
+      
+
+  /* Create mvfs for nodes in sortedArrayOfPartitionNodes */
+  tmpArrayOfMvf = array_alloc(Mvf_Function_t *, 0);
+  for(i=0; i < array_n(sortedArrayOfPartitionNodes); i++){
+    node = array_fetch(Ntk_Node_t *, sortedArrayOfPartitionNodes, i);
+    singletonArrayOfRoots = array_alloc(Ntk_Node_t *, 0);
+    array_insert_last(Ntk_Node_t *, singletonArrayOfRoots, node);
+    singletonMvfArray = Ntm_NetworkBuildMvfs(network, singletonArrayOfRoots, 
+					     tableOfLeaves, careSet);
+    nodeMvf = array_fetch(Mvf_Function_t *, singletonMvfArray, 0);
+    array_insert_last(Mvf_Function_t *, tmpArrayOfMvf, nodeMvf);
+    array_free(singletonMvfArray);
+    array_free(singletonArrayOfRoots);
+
+    /* now create an mddId for this node, and make it a leaf */
+    if(inTermsOfCombInputs == 0){
+      if(Ntk_NodeReadMddId(node) == NTK_UNASSIGNED_MDD_ID){
+	Ord_NetworkAssignMddIdForNode(network, node);
+      }
+      st_insert(tableOfLeaves, (char *)node, (char *) (long) (-1) );    
+      st_insert(mddIdToNodeName, (char *) (long)Ntk_NodeReadMddId(node), 
+		Ntk_NodeReadName(node));
+    }
+  }
+
+  /* Make the combinational output nodes into roots */
+  arrayOfRoots = array_alloc(Ntk_Node_t *, 0);
+  Ntk_NetworkForEachCombOutput(network, gen, node) {
+    array_insert_last(Ntk_Node_t *, arrayOfRoots, node);
+  }
+
+  /* build mvfs of nodes in arrayOfMvf in terms of partition nodes and comb inputs */
+  arrayOfMvf = Ntm_NetworkBuildMvfs(network, arrayOfRoots, tableOfLeaves, 
+				    careSet);
+  array_append(arrayOfRoots, sortedArrayOfPartitionNodes);
+  array_append(arrayOfMvf, tmpArrayOfMvf);
+  array_free(sortedArrayOfPartitionNodes);
+  array_free(tmpArrayOfMvf);
+
+  /* Create one vertex for every component of arrayOfMvf */
+  for (i=0; i < array_n(arrayOfRoots); i++) {
+    node = array_fetch(Ntk_Node_t *, arrayOfRoots, i);
+    mddId = (long) Ntk_NodeReadMddId(node);
+
+    /* obtain the function attached to the node */
+    mddFunction = array_fetch(Mvf_Function_t *, arrayOfMvf, i);
+    toVertex = g_add_vertex(partition);
+    
+    /* Update the look-up tables in the graph */
+    st_insert(PartPartitionReadNameToVertex(partition),
+	      Ntk_NodeReadName(node), (char *)toVertex);
+    if (mddId != -1) {
+      st_insert(PartPartitionReadMddIdToVertex(partition),
+		(char *)mddId, (char *)toVertex);
+    } 
+    toVertex->user_data = 
+      (gGeneric)PartVertexInfoCreateSingle(Ntk_NodeReadName(node), 
+					   mddFunction, 
+					   (int) mddId);
+  } 
+  
+  /* Read the list of vertices on the graph */
+  sinkList = lsCopy(g_get_vertices(partition), (lsGeneric (*)(lsGeneric))0);
+
+  /* 
+   * For every function on every combinational output, compute the
+   * support and create vertices in the graph when needed 
+   */
+  lsForEachItem(sinkList, gen, toVertex) {
+    mddFunction = PartVertexReadFunction(toVertex);
+    mddSupport = PartCreateFunctionSupportTable(mddFunction);
+
+    /* 
+     * Create one edge (and one vertex if necessary) for every element
+     * in mddSupport 
+     */
+    st_foreach_item(mddSupport, stGen, &mddId, NULL) {
+      char *name;
+
+      /* Create vertex with the information if needed */
+      if (st_lookup(PartPartitionReadMddIdToVertex(partition), 
+		    (char *)mddId, &fromVertex) == 0) {
+	fromVertex = g_add_vertex(partition);
+	
+	st_lookup(mddIdToNodeName, (char *)mddId, &name);
+
+	/* Update the look-up tables in the graph */
+	st_insert(PartPartitionReadNameToVertex(partition), 
+		  name, (char *)fromVertex);
+	st_insert(PartPartitionReadMddIdToVertex(partition),
+		  (char *) mddId, (char *)fromVertex);
+	
+	/* Create vertex data */
+	fromVertex->user_data = 
+	  (gGeneric)PartVertexInfoCreateSingle(name,
+					       Mvf_FunctionCreateFromVariable(manager, (int) mddId),
+					       (int) mddId);
+      } 
+      
+      /* 
+       * Add the edge to the graph. Make sure a self loop is not added. The
+       * self loop may be produced by a mdd that has in its support the same
+       * variables that represent the mddId of the node.
+       */
+      if (fromVertex != toVertex) {
+	g_add_edge(fromVertex, toVertex);
+      } /* End of if */
+      
+    } /* End of st_foreach_item */
+    
+    /* Clean the support table */
+    st_free_table(mddSupport);
+  } /* End of lsForEachItem */
+  
+  /* Clean up */
+  st_free_table(mddIdToNodeName);
+  st_free_table(tableOfLeaves);
+  array_free(arrayOfRoots);
+  lsDestroy(sinkList, (void (*)(lsGeneric))0);
+  /* 
+   * The contents of this array (array of mdds) is not deallocated because the
+   * information has been transferred to the partition structure. All the
+   * functions are stored now as part of the vertex information.
+   */
+  array_free(arrayOfMvf);
+
+} /* End of PartPartitionPartial */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
Index: vis_dev/vis-2.3/src/part/partTotal.c
===================================================================
--- vis_dev/vis-2.3/src/part/partTotal.c	(revision 14)
+++ vis_dev/vis-2.3/src/part/partTotal.c	(revision 14)
@@ -0,0 +1,302 @@
+/**CFile***********************************************************************
+
+  FileName    [partTotal.c]
+
+  PackageName [part]
+
+  Synopsis [Implements the partition of the network replicating exactly the
+  network structure in the partition graph.]
+
+  Description [Implements the partition that replicates the structure of the
+  network.  Every node in the network will be represented in the partition by a
+  "single" vertex.]
+
+  SeeAlso     [part.h]
+
+  Author      [Abelardo Pardo]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "partInt.h"
+
+static char rcsid[] UNUSED = "$Id: partTotal.c,v 1.5 2005/04/16 06:14:54 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Implements the partition that replicates the structure of
+  the network.]
+
+  Description [The procedure receives a pointer to a network, a pointer to a
+  just created partition, and the lists of root and leave network nodes. <p>
+
+  The procedure proceeds as follows. It creates the necessary data to call the
+  function Ntm_NetworkBuildMdds.  The array of roots and table of leaves are
+  created in based to the parameters <tt>rootList<\tt> and <tt>leaveList<\tt>
+  respectively. For each root node, its mvf is computed as a function of its
+  inmediate fanin or the leaves, depending on the value of
+  <tt>inTermsOfLeaves<\tt>. Once this computation has finished, one vertex per
+  obtained function is added to the graph. Afterwards, for every vertex, the
+  support of its multi-valued function is computed and the pertinent vertices
+  created in the graph.]
+
+  SideEffects []
+
+  SeeAlso     [PartPartitionInputsOutputs]
+
+******************************************************************************/
+void
+PartPartitionTotal(
+  Ntk_Network_t *network,
+  graph_t       *partition,
+  lsList        rootList,
+  lsList        leaveList,
+  mdd_t         *careSet,
+  int           inTermsOfLeaves)
+{
+  Ntk_Node_t    *nodePtr;           /* Pointer to iterate over nodes */
+  lsList        nodeList;           /* list of network nodes */
+  lsGen         gen;                /* To iterate over lists */
+  array_t       *setOfFunctions;
+  array_t       *rootArray;
+  st_table      *tableOfLeaves;
+  vertex_t      *toVertex;
+  int           i;
+
+  /* Obtain the table of leaves of the partition */
+  tableOfLeaves = st_init_table(st_ptrcmp, st_ptrhash);
+  if (leaveList == (lsList)0) {
+    Ntk_NetworkForEachCombInput(network, gen, nodePtr) {
+      st_insert(tableOfLeaves, (char *)nodePtr, (char *) (long) (-1));
+    }
+  } /* End of then */ 
+  else {
+    lsForEachItem(leaveList, gen, nodePtr) {
+      st_insert(tableOfLeaves, (char *) nodePtr, (char *) (long) (-1));
+    }
+  } /* End of if-then-else */
+  
+  /* Obtain the list of nodes to obtain the partition from */
+  if (rootList == (lsList)0) {
+    nodeList = Ntk_NetworkReadNodes(network);
+  } /* End of then */ 
+  else {
+    array_t *temporaryRootArray;
+    st_table *resultTable;
+    st_generator *stgen;
+
+    /* Translate the root list to an array */
+    temporaryRootArray = array_alloc(Ntk_Node_t *, lsLength(rootList));
+    i = 0;
+    lsForEachItem(rootList, gen, nodePtr) {
+      array_insert(Ntk_Node_t *, temporaryRootArray, i++, nodePtr);
+    }
+
+    /* Obtain the intermediate nodes */
+    resultTable = Ntk_RegionFindNodes(temporaryRootArray, tableOfLeaves);
+    nodeList = lsCreate();
+    st_foreach_item(resultTable, stgen, (&nodePtr), NULL) {
+      lsNewBegin(nodeList, (lsGeneric)nodePtr, NIL(lsHandle));
+    }
+
+    /* Clean up */
+    st_free_table(resultTable);
+    array_free(temporaryRootArray);
+  } /* End of if-then-else */
+
+  rootArray = array_alloc(Ntk_Node_t *, 0);
+
+  /* Make sure every network node has an mdd Id assigned to it */
+  lsForEachItem(nodeList, gen, nodePtr) {
+
+    /* No need to assign mddIds to the shadow nodes */
+    if (Ntk_NodeTestIsShadow(nodePtr)) {
+      continue;
+    } /* End of if */
+
+    if (!inTermsOfLeaves || st_is_member(tableOfLeaves, (char *) nodePtr)) {
+      if (Ntk_NodeReadMddId(nodePtr) == NTK_UNASSIGNED_MDD_ID) {
+	Ord_NetworkAssignMddIdForNode(network, nodePtr);
+      } /* End of if */
+    } /* End of if */
+  } /* End of lsForEachItem */
+
+  /* 
+   * If the result has to be in terms of the combinational inputs, the
+   * mdd array for each vertex will be build all at once by
+   * specifying all the nodes are roots and the combinational inputs
+   * as leaves 
+   */
+  if (inTermsOfLeaves) {
+    lsForEachItem(nodeList, gen, nodePtr) {
+
+      /* Skip the shadow nodes */
+      if (Ntk_NodeTestIsShadow(nodePtr)) {
+	continue;
+      }
+
+      /* Insert the node as root */
+      array_insert_last(Ntk_Node_t *, rootArray, nodePtr);
+    } /* End of lsForEachItem */
+    
+    setOfFunctions = Ntm_NetworkBuildMvfs(network, rootArray, 
+					  tableOfLeaves, careSet);
+  } /* End of then */ 
+  else {
+    /* Compute every mdd array attached to the vertex in terms of its fanin */
+
+    array_t *parameterArray;
+    st_table *tmptableOfLeaves = st_init_table(st_ptrcmp, st_ptrhash);
+
+    setOfFunctions = array_alloc(Mvf_Function_t *, 0);
+
+    /* 
+     * This array will hold one node pointer as the parameter to build
+     * the mdd array for a node. The array rootArray will be used to
+     * create an array of node pointers. Therefore, at the end of this
+     * if-then-else, setOfFunctions will hold the array of mdd arrays
+     * and rootArray will hold the array with all the node pointers
+     * whose mdd array was computed.
+     */
+    parameterArray = array_alloc(Ntk_Node_t *, 1);
+
+    lsForEachItem(nodeList, gen, nodePtr) {
+
+      /* Skip the shadow nodes */
+      if (!Ntk_NodeTestIsShadow(nodePtr)) {
+	Ntk_Node_t *faninPtr;       /* Pointer to fanin node of current node */
+	array_t    *temporaryArray;
+
+	/* Create the array of nodes */
+	array_insert_last(Ntk_Node_t *, rootArray, nodePtr);
+	
+	/* This table is needed empty every beginning of iteration */
+	st_free_table(tmptableOfLeaves);
+	tmptableOfLeaves = st_init_table(st_ptrcmp, st_ptrhash);
+      
+	/* Prepare parameters to build the mdd array for the node */
+	array_insert(Ntk_Node_t *, parameterArray, 0, nodePtr);
+	Ntk_NodeForEachFanin(nodePtr, i, faninPtr) {
+	  st_insert(tmptableOfLeaves, (char *)faninPtr, (char *)(-1));
+	}
+
+	/* 
+	 * If the node is a combinational inputs, it has no fanins but the node
+	 * must appear in the table of leaves, otherwise the function
+	 * Ntm_NetworkBuildMdds aborts.  
+	 */
+	if (st_is_member(tableOfLeaves, (char *) nodePtr)) {
+	  st_insert(tmptableOfLeaves, (char *)nodePtr, (char *)(-1));
+	} /* End of if */
+	
+	temporaryArray = Ntm_NetworkBuildMvfs(network, parameterArray, 
+					      tmptableOfLeaves, careSet);
+	array_insert_last(Mvf_Function_t *, setOfFunctions, 
+			  array_fetch(Mvf_Function_t *, temporaryArray, 0));
+	
+	array_free(temporaryArray);
+      } /* End of if */
+    } /* End of lsForEachItem */
+    
+    array_free(parameterArray);
+    st_free_table(tmptableOfLeaves);
+  } /* End of if-then-else */
+
+  /* Partial Clean up */
+  st_free_table(tableOfLeaves);
+
+  assert(array_n(rootArray) == array_n(setOfFunctions));
+  
+  /* 
+   * The computation now uses two steps, the first one creates all the
+   * vertices of the partition and the second one all the edges of the
+   * partition. 
+   */
+
+  /* Create vertices */
+  arrayForEachItem(Ntk_Node_t *, rootArray, i, nodePtr) {
+    Mvf_Function_t *mvf  = array_fetch(Mvf_Function_t *, setOfFunctions, i);
+    char           *name = Ntk_NodeReadName(nodePtr);
+    int            mddId = Ntk_NodeReadMddId(nodePtr);
+
+    toVertex = g_add_vertex(partition);
+
+    /* Update the look-up tables in the partition */
+    st_insert(PartPartitionReadNameToVertex(partition),
+	      name, (char *)toVertex);
+    st_insert(PartPartitionReadMddIdToVertex(partition),
+	      (char *)(long) mddId, (char *)toVertex);
+
+    /* Create the information attached to the vertex */
+    toVertex->user_data = (gGeneric)PartVertexInfoCreateSingle(name, 
+							       mvf,
+							       mddId);
+  } /* End of arrayForEachItem */
+
+  /* Create the edges */
+  foreach_vertex(partition, gen, toVertex) {
+    nodePtr = Ntk_NetworkFindNodeByActualName(network, PartVertexReadName(toVertex));
+    if(!Ntk_NodeTestIsCombInput(nodePtr)) {
+      PartPartitionCreateVertexFaninEdges(partition, toVertex);
+    }
+  } /* End of foreach_vertex */
+
+  /* Clean up */
+  array_free(rootArray);
+  array_free(setOfFunctions);
+  if (rootList != (lsList)0) {
+    lsDestroy(nodeList, (void (*)(lsGeneric))0);
+  }
+} /* End of PartPartitionTotal */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
Index: vis_dev/vis-2.3/src/puresat/puresat.c
===================================================================
--- vis_dev/vis-2.3/src/puresat/puresat.c	(revision 14)
+++ vis_dev/vis-2.3/src/puresat/puresat.c	(revision 14)
@@ -0,0 +1,234 @@
+/**CFile***********************************************************************
+
+  FileName    [puresat.c]
+
+  PackageName [puresat]
+
+  Synopsis    [Abstraction refinement for large scale invariant checking.]
+
+  Description [This file contains the functions to check invariant properties
+  by the PureSAT abstraction refinement algorithm, which is entirely based on
+  SAT solver, the input of which could be either CNF or AIG. It has several
+  parts:
+
+  * Localization-reduction base Abstraction
+  * K-induction or interpolation to prove the truth of a property
+  * Bounded Model Checking to find bugs
+  * Incremental concretization based methods to verify abstract bugs
+  * Incremental SAT solver to improve efficiency
+  * UNSAT proof based method to obtain refinement
+  * AROSAT to bring in only necessary latches into unsat proofs
+  * Bridge abstraction to get compact coarse refinement
+  * Refinement minization to guarrantee minimal refinements
+  * Unsat proof-based refinement minimization to eliminate multiple candidate
+    by on SAT test
+  * Refinement prediction to decrease the number of refinement iterations
+  * Dynamic switching to redistribute computional resources to improve
+    efficiency
+  
+  For more information, please check the BMC'03, ICCAD'04, STTT'05 and TACAS'05
+  paper of Li et al., "A satisfiability-based appraoch to abstraction
+  refinement in model checking", " Abstraction in symbolic model checking
+  using satisfiability as the only decision procedure", "Efficient computation
+  of small abstraction refinements", and "Efficient abstraction refinement in
+  interpolation-based unbounded model checking"]
+  
+  Author      [Bing Li]
+
+  Copyright   [Copyright (c) 2004 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without
+  license or royalty fees, to use, copy, modify, and distribute this
+  software and its documentation for any purpose, provided that the
+  above copyright notice and the following two paragraphs appear in
+  all copies of this software.]
+
+******************************************************************************/
+
+#include "puresatInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+static jmp_buf timeOutEnv;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+static int CommandPureSatAbRf( Hrc_Manager_t ** hmgr,int  argc, char ** argv);
+static void TimeOutHandle(void);
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the puresat package. The added command is for
+  testing purpose only; the same algorithm can be activated by the
+  check_invariant command.]
+
+  Description [Initializes the puresat package. The added command is for
+  testing purpose only; the same algorithm can be activated by the
+  check_invariant command.]
+
+  SideEffects []
+
+  SeeAlso     [PureSat_End]
+
+******************************************************************************/
+void
+PureSat_Init(void)
+{
+  /*
+   * Add a command to the global command table.  By using the leading
+   * underscore, the command will be listed under "help -a" but not "help".
+   */
+  Cmd_CommandAdd("_puresat_test", CommandPureSatAbRf,  0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Ends the puresat package.]
+
+  Description [Ends the puresat package.]
+   
+  SideEffects []
+
+  SeeAlso     [PureSat_Init]
+
+******************************************************************************/
+void
+PureSat_End(void)
+{
+
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [time out function]
+
+  Description [time out function]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+static void
+TimeOutHandle()
+{
+  longjmp(timeOutEnv, 1);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Check invariant formulae with abstraction refinement method
+  PureSat.]
+
+  Description [Check invariant formulae with abstraction refinement method
+  PureSat.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/  
+static int
+CommandPureSatAbRf(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  Ntk_Network_t * network;
+  
+  FILE * ltlFile;
+  array_t * formulaArray;
+  boolean re;
+  int i;
+
+  PureSat_Manager_t *pm;
+  int timeOutPeriod;
+
+  pm = PureSatManagerAlloc();
+  timeOutPeriod = pm->timeOutPeriod;
+  PureSatCmdParse(argc, argv,pm);
+  network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+  fprintf(vis_stdout, "Num of latches is %d\n",Ntk_NetworkReadNumLatches(network));
+  if (network == NIL(Ntk_Network_t)) {
+      fprintf(vis_stderr,
+	      "No network, please read in the circuit, and init_verify\n");
+      return 1;
+  }
+ 
+  ltlFile = Cmd_FileOpen(pm->ltlFileName, "r", NIL(char *), 0);
+  if (ltlFile == NIL(FILE)) {
+    fprintf(vis_stdout,"Cannot open LTL file %s\n", pm->ltlFileName);
+    exit(1);
+  }
+  
+  formulaArray = Ctlsp_FileParseFormulaArray(ltlFile);
+  if(!array_n(formulaArray))
+    {fprintf(vis_stderr,"ltlfile doesn't contain any formula \n");
+    exit (1);}
+
+  /*timeout*/
+  if (timeOutPeriod > 0) {
+    (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
+    fprintf(vis_stdout, "signal\n");
+    (void) alarm(timeOutPeriod);
+    if (setjmp(timeOutEnv) > 0) {
+      (void) fprintf(vis_stdout,
+		     "# PURESAT: timeout occurred after %d seconds.\n", timeOutPeriod);
+      (void) fprintf(vis_stdout, "# PURESAT: data may be corrupted.\n");
+      alarm(0);
+      return 1;
+    }
+  }
+
+  for (i = 0; i < array_n(formulaArray); i++) {
+    Ctlsp_Formula_t *ltlFormula = array_fetch(Ctlsp_Formula_t *, formulaArray, i);
+    re = PureSatCheckInv_SSS(network,ltlFormula,pm);
+    if(re)
+      fprintf(vis_stdout,"formula #%d is true\n",i);
+    else
+      fprintf(vis_stdout,"formula #%d is False\n",i);
+  }
+  return 0;
+}
+
+
Index: vis_dev/vis-2.3/src/puresat/puresat.h
===================================================================
--- vis_dev/vis-2.3/src/puresat/puresat.h	(revision 14)
+++ vis_dev/vis-2.3/src/puresat/puresat.h	(revision 14)
@@ -0,0 +1,121 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [puresat.h]
+
+  PackageName [puresat]
+
+  Synopsis    [Abstraction refinement for large scale invariant checking.]
+
+  Description [Abstraction refinement for large scale invariant checking.]
+
+  Author      [Bing Li]
+
+  Copyright   [Copyright (c) 2004 The Regents of the Univ. of Colorado. All 
+  rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+  ]
+  
+******************************************************************************/
+
+#ifndef _PURESAT
+#define _PURESAT
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+
+#include "ntk.h"
+#include "st.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define DUMMY -10000
+
+#define  RTnodeSize   8
+#define  RTfSize      0
+#define  RTformula    1
+#define  RToriClsIdx  2
+#define  RTpivot      3
+#define  RTflag       4
+#define  RTIPnode     5
+#define  RTleft       6
+#define  RTright      7
+#define  RT_NULL      0
+#define  RT_BLOCK     1000
+#define  FORMULA_BLOCK 2000
+
+
+#define RT_VisitedMask  0x00000001
+#define RT_ResetVisitedMask  0xfffffffe
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+typedef  long        RTnode_t;
+
+struct ResolutionTreeManager{
+  RTnode_t * nArray; /*record of RTnodes*/
+  long       aSize;  /*current position for nArray*/
+  long       maxSize;/*max pos for nArray*/
+  long     * fArray; /*record of AigNodes -- AIg node pool*/
+  long       cpos;   /*current position for fArray;*/
+  long       maxpos; /*max position for fArray;*/
+  RTnode_t   root;
+};
+
+
+struct InterpolationManager{
+  struct ResolutionTree *root;
+  st_table * CoiTable;/*for EffIP*/
+};
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef  struct ResolutionTreeManager  RTManager_t;
+/*typedef  long        RTnode_t;*/
+typedef struct InterpolationManager IP_Manager_t;
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#define RT_fSize(node) (rm->nArray[node+RTfSize])
+/*#define RT_formula(node) ((long*)rm->nArray[node+RTformula])*/
+#define RT_formula(node) (rm->nArray[node+RTformula])
+#define RT_oriClsIdx(node) (rm->nArray[node+RToriClsIdx])
+#define RT_pivot(node) (rm->nArray[node+RTpivot])
+#define RT_flag(node) (rm->nArray[node+RTflag])
+#define RT_IPnode(node) (rm->nArray[node+RTIPnode])
+#define RT_left(node) (rm->nArray[node+RTleft])
+#define RT_right(node) (rm->nArray[node+RTright])
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void PureSat_Init(void);
+EXTERN void PureSat_End(void);
+EXTERN void PureSat_CheckInvariant(Ntk_Network_t *network, array_t
+				   *InvariantFormulaArray, int verbosity,
+				   int dbgLevel, FILE *dbgOUt, boolean printInputs,
+                                   boolean incremental, boolean sss, 
+				   boolean flatIP, int speed);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _PURESAT */
Index: vis_dev/vis-2.3/src/puresat/puresat.make
===================================================================
--- vis_dev/vis-2.3/src/puresat/puresat.make	(revision 14)
+++ vis_dev/vis-2.3/src/puresat/puresat.make	(revision 14)
@@ -0,0 +1,4 @@
+CSRC +=  puresatUtil.c puresatBMC.c puresatRefine.c puresat.c puresatMain.c puresatIPAbRf.c puresatAig.c puresatArosat.c puresatIPUtil.c puresatIPRefine.c puresatTFrame.c puresatFlatIP.c
+HEADERS += puresat.h puresatInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/puresat/puresatAig.c
===================================================================
--- vis_dev/vis-2.3/src/puresat/puresatAig.c	(revision 14)
+++ vis_dev/vis-2.3/src/puresat/puresatAig.c	(revision 14)
@@ -0,0 +1,1115 @@
+/**CFile***********************************************************************
+
+  FileName    [puresatAig.c]
+
+  PackageName [puresat]
+
+  Synopsis    [Abstraction refinement for large scale invariant checking.]
+
+  Description [This file contains the functions to check invariant properties
+  by the PureSAT abstraction refinement algorithm, which is entirely based on
+  SAT solver, the input of which could be either CNF or AIG. It has several
+  parts:
+
+  * Localization-reduction base Abstraction
+  * K-induction or interpolation to prove the truth of a property
+  * Bounded Model Checking to find bugs
+  * Incremental concretization based methods to verify abstract bugs
+  * Incremental SAT solver to improve efficiency
+  * UNSAT proof based method to obtain refinement
+  * AROSAT to bring in only necessary latches into unsat proofs
+  * Bridge abstraction to get compact coarse refinement
+  * Refinement minization to guarrantee minimal refinements
+  * Unsat proof-based refinement minimization to eliminate multiple candidate
+    by on SAT test
+  * Refinement prediction to decrease the number of refinement iterations
+  * Dynamic switching to redistribute computional resources to improve
+    efficiency
+
+  For more information, please check the BMC'03, ICCAD'04, STTT'05 and TACAS'05
+  paper of Li et al., "A satisfiability-based appraoch to abstraction
+  refinement in model checking", " Abstraction in symbolic model checking
+  using satisfiability as the only decision procedure", "Efficient computation
+  of small abstraction refinements", and "Efficient abstraction refinement in
+  interpolation-based unbounded model checking"]
+
+  Author      [Bing Li]
+
+  Copyright   [Copyright (c) 2004 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without
+  license or royalty fees, to use, copy, modify, and distribute this
+  software and its documentation for any purpose, provided that the
+  above copyright notice and the following two paragraphs appear in
+  all copies of this software.]
+
+******************************************************************************/
+#include "maigInt.h"
+#include "baig.h"
+#include "ntk.h"
+#include "puresatInt.h"
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [For AIG recovery--unconnect output for nodes eliminated]
+
+  Description [For AIG recovery--unconnect output for nodes eliminated]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void
+PureSat_unconnectOutput(
+   bAig_Manager_t *manager,
+   bAigEdge_t from,
+   bAigEdge_t to)
+{
+   bAigEdge_t cur, *pfan, *newfan;
+   int i, nfan,find=0;
+
+  from = bAig_NonInvertedEdge(from);
+  to = bAig_NonInvertedEdge(to);
+
+  pfan = (bAigEdge_t *)fanout(from);
+  nfan = nFanout(from);
+  newfan = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*(nfan));
+  for(i=0; i<nfan; i++) {
+    cur = pfan[i];
+    cur = cur >> 1;
+    cur = bAig_NonInvertedEdge(cur);
+    if(cur == to) {
+      find = 1;
+      memcpy(newfan, pfan, sizeof(bAigEdge_t)*i);
+      memcpy(&(newfan[i]), &(pfan[i+1]), sizeof(bAigEdge_t)*(nfan-i-1));
+      newfan[nfan-1] = 0;
+
+      fanout(from) = (bAigEdge_t)newfan;
+
+
+      free(pfan);
+      nFanout(from) = nfan-1;
+      break;
+    }
+  }
+  assert(find);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [for AIG generation---create connection between new and
+	      old aig nodes]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void
+PureSat_connectOutput(
+   bAig_Manager_t *manager,
+   bAigEdge_t from,
+   bAigEdge_t to,
+   int inputIndex)
+{
+  bAigEdge_t *pfan;
+  bAigEdge_t nfan;
+
+  to = bAig_NonInvertedEdge(to);
+  pfan = (bAigEdge_t *)fanout(from);
+  nfan = nFanout(from);
+  if(nfan == 0) pfan = malloc((sizeof(bAigEdge_t)*2));
+  else          pfan = realloc(pfan, sizeof(bAigEdge_t)*(nfan+2));
+  to += bAig_IsInverted(from);
+  to = to << 1;
+  to += inputIndex;
+  pfan[nfan++] = to;
+  pfan[nfan] = 0;
+  fanout(from) = (bAigEdge_t)pfan;
+  nFanout(from) = nfan;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Check whether a node has been created or not]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+bAigEdge_t
+PureSat_HashTableLookup(
+  bAig_Manager_t *manager,
+  bAigEdge_t  node1,
+  bAigEdge_t  node2)
+{
+  bAigEdge_t key = HashTableFunction(node1, node2);
+  bAigEdge_t node;
+
+  node = manager->HashTableArray[manager->class_][key];
+  if  (node == bAig_NULL) {
+    return bAig_NULL;
+  }
+  else{
+    while ( (rightChild(bAig_NonInvertedEdge(node)) != node2) ||
+	    (leftChild(bAig_NonInvertedEdge(node))  != node1)) {
+
+      if (next(bAig_NonInvertedEdge(node)) == bAig_NULL){
+	return(bAig_NULL);
+      }
+      node = next(bAig_NonInvertedEdge(node)); /* Get the next Node */
+    } /* While loop */
+    return(node);
+
+  } /* If Then Else */
+
+} /* End of HashTableLookup() */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Add one new node to hash table]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+int
+PureSat_HashTableAdd(
+  bAig_Manager_t   *manager,
+  bAigEdge_t  nodeIndexParent,
+  bAigEdge_t  nodeIndex1,
+  bAigEdge_t  nodeIndex2)
+{
+  bAigEdge_t key = HashTableFunction(nodeIndex1, nodeIndex2);
+  bAigEdge_t nodeIndex;
+  bAigEdge_t node;
+
+  nodeIndex = manager->HashTableArray[manager->class_][key];
+  if  (nodeIndex == bAig_NULL) {
+    manager->HashTableArray[manager->class_][key] = nodeIndexParent;
+    return TRUE;
+  }
+  else{
+    node = nodeIndex;
+    nodeIndex = next(bAig_NonInvertedEdge(nodeIndex));  /* Get the Node */
+    while (nodeIndex != bAig_NULL) {
+      node = nodeIndex;
+      nodeIndex = next(bAig_NonInvertedEdge(nodeIndex));
+    }
+    next(bAig_NonInvertedEdge(node)) = nodeIndexParent;
+    return TRUE;
+  }
+
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Create a node for AND operation]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+bAigEdge_t
+PureSat_CreateAndNode(
+   bAig_Manager_t  *manager,
+   bAigEdge_t node1,
+   bAigEdge_t node2)
+{
+
+  bAigEdge_t varIndex;
+  char       *name = NIL(char);
+  char       *node1Str = util_inttostr(node1);
+  char       *node2Str = util_inttostr(node2);
+  long class_ = manager->class_;
+
+  name = util_strcat4("Nd", node1Str,"_", node2Str);
+  while (st_lookup(manager->SymbolTableArray[class_], name, &varIndex)){
+    fprintf(vis_stdout, "Find redundant node at %ld %ld\n", node1, node2);
+    name = util_strcat3(name, node1Str, node2Str);
+  }
+  FREE(node1Str);
+  FREE(node2Str);
+  varIndex = bAig_CreateNode(manager, node1, node2);
+  if (varIndex == bAig_NULL){
+    FREE(name);
+    return (varIndex);
+  }
+  /* Insert the varaible in the Symbol Table */
+  st_insert(manager->SymbolTableArray[class_], name, (char*) (long) varIndex);
+  manager->nameList[bAigNodeID(varIndex)] = name;
+
+  return(varIndex);
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [And function for 2 aig nodes]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+bAigEdge_t
+PureSat_And2(
+   bAig_Manager_t *manager,
+   bAigEdge_t nodeIndex1,
+   bAigEdge_t nodeIndex2)
+{
+  bAigEdge_t newNodeIndex;
+
+    newNodeIndex = PureSat_CreateAndNode(manager, nodeIndex1, nodeIndex2) ;
+
+    PureSat_HashTableAdd(manager, newNodeIndex, nodeIndex1, nodeIndex2);
+    PureSat_connectOutput(manager, nodeIndex1, newNodeIndex, 0);
+    PureSat_connectOutput(manager, nodeIndex2, newNodeIndex, 1);
+
+  return newNodeIndex;
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [And function for 3 aig nodes]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+bAigEdge_t
+PureSat_And3(
+	   bAig_Manager_t *manager,
+	   bAigEdge_t l,
+	   bAigEdge_t r)
+{
+  int caseIndex, caseSig;
+  bAigEdge_t rl, rr;
+
+  rl = leftChild(r);
+  rr = rightChild(r);
+
+  caseIndex = 0; /* (a)(b c) */
+  if(bAigCompareNode(l, rl)) {
+    caseIndex = 1; /* (a)(a b) */
+  }
+  else if(bAigCompareNode(l, rr)) {
+    caseIndex = 2; /* (a)(b a) */
+  }
+
+  caseSig = 0;
+  if(bAig_IsInverted(l))  caseSig += 8;
+  if(bAig_IsInverted(rl)) caseSig += 4;
+  if(bAig_IsInverted(rr)) caseSig += 2;
+  if(bAig_IsInverted(r))  caseSig += 1;
+  if(caseIndex == 0) {
+    return(PureSat_And2(manager, l, r));
+  }
+  else if(caseIndex == 1) {
+    switch(caseSig) {
+	case 2 :
+	case 0 :
+	case 14 :
+	case 12 :
+      return(r);
+	case 10 :
+	case 8 :
+	case 6 :
+	case 4 :
+      return(bAig_Zero);
+	case 3 :
+	case 1 :
+	case 15 :
+	case 13 :
+      return(PureSat_And(manager, rl, bAig_Not(rr)));
+	case 11 :
+	case 9 :
+	case 7 :
+	case 5 :
+      return(l);
+    }
+  }
+  else if(caseIndex == 2) {
+    switch(caseSig) {
+	case 4 :
+	case 0 :
+	case 14 :
+	case 10 :
+      return(r);
+	case 12 :
+	case 8 :
+	case 6 :
+	case 2 :
+      return(bAig_Zero);
+	case 5 :
+	case 1 :
+	case 15 :
+	case 11 :
+      return(PureSat_And(manager, bAig_Not(rl), rr));
+	case 13 :
+	case 9 :
+	case 7 :
+	case 3 :
+      return(l);
+    }
+  }
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [And function for 4 aig nodes]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+bAigEdge_t
+PureSat_And4(
+	   bAig_Manager_t *manager,
+	   bAigEdge_t l,
+	   bAigEdge_t r)
+{
+  int caseIndex, caseSig;
+  bAigEdge_t ll, lr, rl, rr;
+  bAigEdge_t t1, t2;
+
+  ll = leftChild(l);
+  lr = rightChild(l);
+  rl = leftChild(r);
+  rr = rightChild(r);
+
+  if(bAigCompareNode(l, rl) ||
+     bAigCompareNode(l, rr)) {
+    return(PureSat_And3(manager, l, r));
+  }
+  else if(bAigCompareNode(r, ll) ||
+     bAigCompareNode(r, lr)) {
+    return(PureSat_And3(manager, r, l));
+  }
+
+  if(ll > lr+1) bAigSwap(ll, lr);
+  if(rl > rr+1) bAigSwap(rl, rr);
+
+  caseIndex = 0; /* (a b)(c d) */
+  if(bAigCompareNode(ll, rl)) {
+    if(bAigCompareNode(lr, rr)) {
+      caseIndex = 4; /* (a b) (a b) */
+    }
+    else {
+      caseIndex = 1; /* (a b) (a c) */
+      if(lr > rr+1) {
+	bAigSwap(ll, rl);
+	bAigSwap(lr, rr);
+	bAigSwap(l, r);
+      }
+    }
+  }
+  else if(bAigCompareNode(lr, rl)) {
+    caseIndex = 2; /* (b a)(a c) */
+  }
+  else if(bAigCompareNode(lr, rr)) {
+    caseIndex = 3; /* (b a)(c a) */
+    if(ll > rl+1) {
+      bAigSwap(ll, rl);
+      bAigSwap(lr, rr);
+      bAigSwap(l, r);
+    }
+  }
+  else if(bAigCompareNode(ll, rr)) {
+    /* (a b)(c a)  */
+    bAigSwap(ll, rl);
+    bAigSwap(lr, rr);
+    bAigSwap(l, r);
+    caseIndex = 2; /* (c a )(a b) because of c < b */
+  }
+
+  caseSig = 0;
+  if(bAig_IsInverted(ll)) caseSig += 32;
+  if(bAig_IsInverted(lr)) caseSig += 16;
+  if(bAig_IsInverted(l))  caseSig += 8;
+  if(bAig_IsInverted(rl)) caseSig += 4;
+  if(bAig_IsInverted(rr)) caseSig += 2;
+  if(bAig_IsInverted(r))  caseSig += 1;
+
+  if(caseIndex == 0) {
+    return(PureSat_And2(manager, l, r));
+  }
+  else if(caseIndex == 1) {
+    switch(caseSig) {
+	case 19 :
+	case 17 :
+	case 3 :
+	case 1 :
+	case 55 :
+	case 53 :
+	case 39 :
+	case 37 :
+      t1 = PureSat_And(manager, lr, bAig_Not(rr));
+      t2 = PureSat_And(manager, ll, t1);
+      return(t2);
+	case 18 :
+	case 16 :
+	case 2 :
+	case 0 :
+	case 54 :
+	case 52 :
+	case 38 :
+	case 36 :
+      t1 = PureSat_And(manager, lr, rr);
+      t2 = PureSat_And(manager, ll, t1);
+      return(t2);
+	case 26 :
+	case 24 :
+	case 10 :
+	case 8 :
+	case 62 :
+	case 60 :
+	case 46 :
+	case 44 :
+      t1 = PureSat_And(manager, bAig_Not(lr), rr);
+      t2 = PureSat_And(manager, ll, t1);
+      return(t2);
+	case 61 :
+	case 27 :
+	case 25 :
+	case 11 :
+	case 63 :
+	case 47 :
+	case 9 :
+	case 45 :
+      t1 = PureSat_And(manager, bAig_Not(lr), bAig_Not(rr));
+      t2 = PureSat_Or(manager, bAig_Not(ll), t1);
+      return(t2);
+	case 23 :
+	case 21 :
+	case 7 :
+	case 5 :
+	case 51 :
+	case 49 :
+	case 35 :
+	case 33 :
+      return(l);
+	case 30 :
+	case 28 :
+	case 14 :
+	case 12 :
+	case 58 :
+	case 56 :
+	case 42 :
+	case 40 :
+      return(r);
+	case 22 :
+	case 20 :
+	case 6 :
+	case 4 :
+	case 50 :
+	case 48 :
+	case 34 :
+	case 32 :
+      return(bAig_Zero);
+	case 31 :
+	case 29 :
+	case 15 :
+	case 13 :
+	case 59 :
+	case 57 :
+	case 43 :
+	case 41 :
+      t1 = PureSat_And2(manager, l, r);
+      return(t1);
+    }
+  }
+  else if(caseIndex == 2) {
+    switch(caseSig) {
+	case 35 :
+	case 33 :
+	case 3 :
+	case 1 :
+	case 55 :
+	case 53 :
+	case 23 :
+	case 21 :
+      t1 = PureSat_And(manager, lr, bAig_Not(rr));
+      t2 = PureSat_And(manager, ll, t1);
+      return(t2);
+	case 34 :
+	case 32 :
+	case 2 :
+	case 0 :
+	case 54 :
+	case 52 :
+	case 22 :
+	case 20 :
+      t1 = PureSat_And(manager, lr, rr);
+      t2 = PureSat_And(manager, ll, t1);
+      return(t2);
+	case 42 :
+	case 40 :
+	case 10 :
+	case 8 :
+	case 62 :
+	case 60 :
+	case 30 :
+	case 28 :
+      t1 = PureSat_And(manager, lr, rr);
+      t2 = PureSat_And(manager, bAig_Not(ll), t1);
+      return(t2);
+	case 43 :
+	case 41 :
+	case 11 :
+	case 9 :
+	case 63 :
+	case 61 :
+	case 31 :
+	case 29 :
+      t1 = PureSat_And(manager, bAig_Not(ll), bAig_Not(rr));
+      t2 = PureSat_Or(manager, bAig_Not(lr), t1);
+      return(t2);
+	case 39 :
+	case 37 :
+	case 7 :
+	case 5 :
+	case 51 :
+	case 49 :
+	case 19 :
+	case 17 :
+      return(l);
+	case 46 :
+	case 44 :
+	case 14 :
+	case 12 :
+	case 58 :
+	case 56 :
+	case 26 :
+	case 24 :
+      return(r);
+	case 38 :
+	case 36 :
+	case 6 :
+	case 4 :
+	case 50 :
+	case 48 :
+	case 18 :
+	case 16 :
+      return(bAig_Zero);
+	case 45 :
+	case 15 :
+	case 13 :
+	case 59 :
+	case 57 :
+	case 47 :
+	case 27 :
+	case 25 :
+      t1 = PureSat_And2(manager, l, r);
+      return(t1);
+    }
+  }
+  else if(caseIndex == 3) {
+    switch(caseSig) {
+	case 37 :
+	case 33 :
+	case 5 :
+	case 1 :
+	case 55 :
+	case 51 :
+	case 23 :
+	case 19 :
+      t1 = PureSat_And(manager, bAig_Not(rl), lr);
+      t2 = PureSat_And(manager, ll, t1);
+      return(t2);
+	case 36 :
+	case 32 :
+	case 4 :
+	case 0 :
+	case 54 :
+	case 50 :
+	case 22 :
+	case 18 :
+      t1 = PureSat_And(manager, rl, lr);
+      t2 = PureSat_And(manager, ll, t1);
+      return(t2);
+	case 44 :
+	case 40 :
+	case 12 :
+	case 8 :
+	case 62 :
+	case 58 :
+	case 30 :
+	case 26 :
+      t1 = PureSat_And(manager, rl, lr);
+      t2 = PureSat_And(manager, bAig_Not(ll), t1);
+      return(t2);
+	case 45 :
+	case 41 :
+	case 13 :
+	case 9 :
+	case 63 :
+	case 59 :
+	case 31 :
+	case 27 :
+      t1 = PureSat_And(manager, bAig_Not(ll), bAig_Not(rl));
+      t2 = PureSat_Or(manager, bAig_Not(lr), t1);
+      return(t2);
+	case 39 :
+	case 35 :
+	case 7 :
+	case 3 :
+	case 53 :
+	case 49 :
+	case 21 :
+	case 17 :
+      return(l);
+	case 46 :
+	case 42 :
+	case 14 :
+	case 10 :
+	case 60 :
+	case 56 :
+	case 28 :
+	case 24 :
+      return(r);
+	case 38 :
+	case 34 :
+	case 6 :
+	case 2 :
+	case 52 :
+	case 48 :
+	case 20 :
+	case 16 :
+      return(bAig_Zero);
+	case 47 :
+	case 43 :
+	case 15 :
+	case 11 :
+	case 61 :
+	case 57 :
+	case 29 :
+	case 25 :
+      t1 = PureSat_And2(manager, l, r);
+      return(t1);
+    }
+  }
+  else if(caseIndex == 4) {
+    switch(caseSig) {
+	case 22 :
+	case 20 :
+	case 6 :
+	case 4 :
+	case 50 :
+	case 48 :
+	case 34 :
+	case 32 :
+	case 2 :
+	case 16 :
+	case 52 :
+	case 1 :
+	case 8 :
+	case 19 :
+	case 26 :
+	case 37 :
+	case 44 :
+	case 38 :
+	case 55 :
+	case 62 :
+      return(bAig_Zero);
+	case 0 :
+	case 18 :
+	case 36 :
+	case 54 :
+	case 9 :
+	case 27 :
+	case 45 :
+	case 63 :
+	case 5 :
+	case 23 :
+	case 33 :
+	case 51 :
+	case 3 :
+	case 17 :
+	case 49 :
+	case 7 :
+	case 35 :
+	case 21 :
+	case 39 :
+	case 53 :
+      return(l);
+	case 40 :
+	case 58 :
+	case 12 :
+	case 30 :
+	case 24 :
+	case 10 :
+	case 14 :
+	case 56 :
+	case 28 :
+	case 42 :
+	case 60 :
+	case 46 :
+      return(r);
+	case 11 :
+	case 47 :
+	case 25 :
+	case 61 :
+      return(bAig_Not(ll));
+	case 41 :
+	case 59 :
+	case 13 :
+	case 31 :
+      return(bAig_Not(lr));
+	case 15 :
+      t1 = PureSat_And(manager, ll, bAig_Not(lr));
+      t2 = PureSat_And(manager, bAig_Not(ll), lr);
+      return(bAig_Not(PureSat_And2(manager, bAig_Not(t1), bAig_Not(t2))));
+	case 57 :
+      t1 = PureSat_And(manager, rl, bAig_Not(rr));
+      t2 = PureSat_And(manager, bAig_Not(rl), rr);
+      return(bAig_Not(PureSat_And2(manager, bAig_Not(t1), bAig_Not(t2))));
+	case 29 :
+      t1 = PureSat_And(manager, ll, lr);
+      t2 = PureSat_And(manager, bAig_Not(ll), bAig_Not(lr));
+      return((PureSat_And2(manager, bAig_Not(t1), bAig_Not(t2))));
+	case 43 :
+      t1 = PureSat_And(manager, rl, rr);
+      t2 = PureSat_And(manager, bAig_Not(rl), bAig_Not(rr));
+      return((PureSat_And2(manager, bAig_Not(t1), bAig_Not(t2))));
+    }
+  }
+  return(0);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [test whether two level minimization can be enabled--iff the two
+	       nodes are in the same timeframe]
+
+  Description [output, l,r,ll,lr,rl,rr must be in the same class to pass the test]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+int PureSat_Test2LevelMini(bAig_Manager_t *manager,
+			   bAigEdge_t l,
+			   bAigEdge_t r)
+{
+  int class_ = bAig_Class(l);
+  bAigEdge_t ll,lr,rl,rr;
+
+  if(!manager->test2LevelMini)
+    return 0;
+
+  if(class_!= bAig_Class(r) || class_ != manager->class_)
+    return 0;
+
+  ll = leftChild(l);
+  if(ll!=bAig_NULL && class_!=bAig_Class(ll))
+    return 0;
+  lr = rightChild(l);
+  if(lr!=bAig_NULL && class_!=bAig_Class(lr))
+    return 0;
+  rl = leftChild(r);
+  if(rl!=bAig_NULL && class_!=bAig_Class(rl))
+    return 0;
+  rr = rightChild(r);
+  if(rr!=bAig_NULL && class_!=bAig_Class(rr))
+    return 0;
+
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis [And function for two AIG nodes. The difference with
+	    bAigCreateAndNode is that here two level minimization
+	    is only allowed with the same timeframe, otherwise the
+	    global variable for interpolation generation may not be
+	    latch variables]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+bAigEdge_t
+PureSat_And(
+   bAig_Manager_t *manager,
+   bAigEdge_t nodeIndex1,
+   bAigEdge_t nodeIndex2)
+{
+
+  bAigEdge_t newNodeIndex;
+
+  nodeIndex1 = bAig_GetCanonical(manager, nodeIndex1);
+  nodeIndex2 = bAig_GetCanonical(manager, nodeIndex2);
+
+  newNodeIndex = nodeIndex1;     /* The left node has the smallest index */
+  if (bAig_NonInvertedEdge(nodeIndex1) > bAig_NonInvertedEdge(nodeIndex2)){
+    nodeIndex1 = nodeIndex2;
+    nodeIndex2 = newNodeIndex;
+  }
+
+  if ( nodeIndex2 == bAig_Zero ) {
+    return bAig_Zero;
+  }
+  if ( nodeIndex1 == bAig_Zero ) {
+    return bAig_Zero;
+  }
+  if ( nodeIndex2 == bAig_One ) {
+    return nodeIndex1;
+  }
+  if ( nodeIndex1 == bAig_One ) {
+    return nodeIndex2;
+  }
+  if ( nodeIndex1 == nodeIndex2 ) {
+    return nodeIndex1;
+  }
+  if ( nodeIndex1 == bAig_Not(nodeIndex2) ) {
+    return bAig_Zero;
+  }
+
+  /* Look for the new node in the Hash table */
+  newNodeIndex = PureSat_HashTableLookup(manager, nodeIndex1, nodeIndex2);
+
+
+  if (newNodeIndex == bAig_NULL){
+    if(!PureSat_Test2LevelMini(manager,nodeIndex1,nodeIndex2)){
+      newNodeIndex = PureSat_And2(manager, nodeIndex1, nodeIndex2);
+      return newNodeIndex;
+    }
+
+    if(bAigIsVar(manager, nodeIndex1) && bAigIsVar(manager, nodeIndex2))
+      newNodeIndex = PureSat_And2(manager, nodeIndex1, nodeIndex2);
+    else if(bAigIsVar(manager, nodeIndex1))
+      newNodeIndex = PureSat_And3(manager, nodeIndex1, nodeIndex2);
+    else if(bAigIsVar(manager, nodeIndex2))
+      newNodeIndex = PureSat_And3(manager, nodeIndex2, nodeIndex1);
+    else {
+      newNodeIndex = PureSat_And4(manager, nodeIndex1, nodeIndex2);
+    }
+  }
+
+  return newNodeIndex;
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [OR operation for two aig nodes]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+bAigEdge_t
+PureSat_Or(
+   bAig_Manager_t *manager,
+   bAigEdge_t nodeIndex1,
+   bAigEdge_t nodeIndex2)
+{
+  return ( bAig_Not(PureSat_And(manager,  bAig_Not(nodeIndex1),  bAig_Not(nodeIndex2))));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [XOR operation for two aig nodes]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+bAigEdge_t
+PureSat_Xor(
+   bAig_Manager_t *manager,
+   bAigEdge_t nodeIndex1,
+   bAigEdge_t nodeIndex2)
+{
+ return PureSat_Or(manager,
+	    PureSat_And(manager, nodeIndex1, bAig_Not(nodeIndex2)),
+	    PureSat_And(manager, bAig_Not(nodeIndex1),nodeIndex2)
+	);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [EQ operation for two aig nodes]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+bAigEdge_t
+PureSat_Eq(
+   bAig_Manager_t *manager,
+   bAigEdge_t nodeIndex1,
+   bAigEdge_t nodeIndex2)
+{
+ return bAig_Not(
+	    PureSat_Xor(manager, nodeIndex1, nodeIndex2)
+	    );
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [THEN operation for two aig nodes]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+bAigEdge_t
+PureSat_Then(
+   bAig_Manager_t *manager,
+   bAigEdge_t nodeIndex1,
+   bAigEdge_t nodeIndex2)
+{
+ return PureSat_Or(manager,
+		bAig_Not(nodeIndex1),
+		nodeIndex2);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Create variable AIG nodes]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+bAigEdge_t
+PureSat_CreateVarNode(
+   bAig_Manager_t  *manager,
+   nameType_t	   *name)
+{
+
+  bAigEdge_t varIndex;
+  int class_ = manager->class_;
+
+
+  if (!st_lookup(manager->SymbolTableArray[class_], name, &varIndex)){
+    varIndex = bAig_CreateNode(manager, bAig_NULL, bAig_NULL);
+    if (varIndex == bAig_NULL){
+      return (varIndex);
+    }
+    /* Insert the varaible in the Symbol Table */
+    st_insert(manager->SymbolTableArray[class_],
+	      name, (char*) (long) varIndex);
+    manager->nameList[bAigNodeID(varIndex)] = name;
+    return(varIndex);
+  }
+  else {
+    return (varIndex);
+  }
+}
Index: vis_dev/vis-2.3/src/puresat/puresatArosat.c
===================================================================
--- vis_dev/vis-2.3/src/puresat/puresatArosat.c	(revision 14)
+++ vis_dev/vis-2.3/src/puresat/puresatArosat.c	(revision 14)
@@ -0,0 +1,2236 @@
+/**CFile***********************************************************************
+
+  FileName    [puresatArosat.c]
+
+  PackageName [puresat]
+
+  Synopsis    [Abstraction refinement for large scale invariant checking.]
+
+  Description [This file contains the functions to check invariant properties
+  by the PureSAT abstraction refinement algorithm, which is entirely based on
+  SAT solver, the input of which could be either CNF or AIG. It has several
+  parts:
+
+  * Localization-reduction base Abstraction
+  * K-induction or interpolation to prove the truth of a property
+  * Bounded Model Checking to find bugs
+  * Incremental concretization based methods to verify abstract bugs
+  * Incremental SAT solver to improve efficiency
+  * UNSAT proof based method to obtain refinement
+  * AROSAT to bring in only necessary latches into unsat proofs
+  * Bridge abstraction to get compact coarse refinement
+  * Refinement minization to guarrantee minimal refinements
+  * Unsat proof-based refinement minimization to eliminate multiple candidate
+    by on SAT test
+  * Refinement prediction to decrease the number of refinement iterations
+  * Dynamic switching to redistribute computional resources to improve
+    efficiency
+
+  For more information, please check the BMC'03, ICCAD'04, STTT'05 and TACAS'05
+  paper of Li et al., "A satisfiability-based appraoch to abstraction
+  refinement in model checking", " Abstraction in symbolic model checking
+  using satisfiability as the only decision procedure", "Efficient computation
+  of small abstraction refinements", and "Efficient abstraction refinement in
+  interpolation-based unbounded model checking"]
+
+  Author      [Bing Li]
+
+  Copyright   [Copyright (c) 2004 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without
+  license or royalty fees, to use, copy, modify, and distribute this
+  software and its documentation for any purpose, provided that the
+  above copyright notice and the following two paragraphs appear in
+  all copies of this software.]
+
+******************************************************************************/
+
+#include "puresatInt.h"
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [comparing score for sorting]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+static int
+ScoreCompare(
+  const void * node1,
+  const void * node2)
+{
+int v1;
+int v2;
+int s1, s2;
+
+  v1 = *(int *)(node1);
+  v2 = *(int *)(node2);
+  s1 = *((int *)(node1) + 1);
+  s2 = *((int *)(node2) + 1);
+
+  if(s1 == s2) {
+    return(v1 > v2);
+  }
+  return(s1 < s2);
+}
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+typedef int (*ASIMPLY_FN)
+    (satManager_t *cm, satLevel_t *d, long v, long left, long right);
+
+
+ASIMPLY_FN ASImplicationFN[64]= {
+  AS_ImplyStop,                 /* 0    */
+  AS_ImplyConflict,             /* 1  */
+  AS_ImplyLeftForward,          /* 2  */
+  AS_ImplyLeftForward,          /* 3  */
+  AS_ImplyStop,                 /* 4  */
+  AS_ImplyConflict,             /* 5  */
+  AS_ImplyLeftForward,          /* 6  */
+  AS_ImplyLeftForward,          /* 7  */
+  AS_ImplySplit,                /* 8  */
+  AS_ImplyConflict,             /* 9  */
+  AS_ImplyLeftForward,          /* 10  */
+  AS_ImplyLeftForward,          /* 11  */
+  AS_ImplySplit,                /* 12  */
+  AS_ImplyConflict,             /* 13  */
+  AS_ImplyLeftForward,          /* 14  */
+  AS_ImplyLeftForward,          /* 15  */
+  AS_ImplyStop,                 /* 16  */
+  AS_ImplyConflict,             /* 17  */
+  AS_ImplyRightForward,         /* 18  */
+  AS_ImplyRightForward,         /* 19  */
+  AS_ImplyConflict,             /* 20  */
+  AS_ImplyStop,                 /* 21  */
+  AS_ImplyForwardOne,           /* 22  */
+  AS_ImplyForwardOne,           /* 23  */
+  AS_ImplyPropRight,            /* 24  */
+  AS_ImplyPropRightOne,         /* 25  */
+  AS_ImplyStop,                 /* 26  */
+  AS_ImplyStop,                 /* 27  */
+  AS_ImplyPropRight,            /* 28  */
+  AS_ImplyPropRightOne,         /* 29  */
+  AS_ImplyStop,                 /* 30  */
+  AS_ImplyStop,                 /* 31  */
+  AS_ImplySplit,                /* 32  */
+  AS_ImplyConflict,             /* 33  */
+  AS_ImplyRightForward,         /* 34  */
+  AS_ImplyRightForward,         /* 35  */
+  AS_ImplyPropLeft,             /* 36  */
+  AS_ImplyPropLeftOne,          /* 37  */
+  AS_ImplyStop,                 /* 38  */
+  AS_ImplyStop,                 /* 39  */
+  AS_ImplySplit,                /* 40  */
+  AS_ImplyPropLeftRight,        /* 41  */
+  AS_ImplyStop,                 /* 42  */
+  AS_ImplyStop,                 /* 43  */
+  AS_ImplySplit,                /* 44  */
+  AS_ImplyPropLeftRight,        /* 45  */
+  AS_ImplyStop,                 /* 46  */
+  AS_ImplyStop,                 /* 47  */
+  AS_ImplySplit,                /* 48  */
+  AS_ImplyConflict,             /* 49  */
+  AS_ImplyRightForward,         /* 50  */
+  AS_ImplyRightForward,         /* 51  */
+  AS_ImplyPropLeft,             /* 52  */
+  AS_ImplyPropLeftOne,          /* 53  */
+  AS_ImplyStop,                 /* 54  */
+  AS_ImplyStop,                 /* 55  */
+  AS_ImplySplit,                /* 56  */
+  AS_ImplyPropLeftRight,        /* 57  */
+  AS_ImplyStop,                 /* 58  */
+  AS_ImplyStop,                 /* 59  */
+  AS_ImplySplit,                /* 60  */
+  AS_ImplyPropLeftRight,        /* 61  */
+  AS_ImplyStop,                 /* 62  */
+  AS_ImplyStop,                 /* 63  */
+};
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [No further implcation when this function is called.]
+
+  Description [No further implcation when this function is called.
+		      0       0       0       1
+		      |       |       |       |
+		     ---     ---     ---     ---
+		     / \     / \     / \     / \
+		    0   X   X   0   0   0   1   1
+	      ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+int
+AS_ImplyStop(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	long left,
+	long right)
+{
+  return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [No further implcation when this function is called.]
+
+  Description [No further implcation when this function is called.
+	       and need split on output.
+		      0
+		      |
+		     ---
+		     / \
+		    X   X
+	      ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+AS_ImplySplit(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	long left,
+	long right)
+{
+  return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [The conflict happens.]
+
+  Description [The conflict happens when
+		      0       1       1       1       1
+		      |       |       |       |       |
+		     ---     ---     ---     ---     ---
+		     / \     / \     / \     / \     / \
+		    1   1   X   0   0   X   1   0   0   1
+	      ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+AS_ImplyConflict(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	long left,
+	long right)
+{
+  if(left != 2)	 {
+    d->conflict = SATnormalNode(v);
+  }
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [A value implied to output due to left child.]
+
+  Description [A value implied to output due to left child
+		      X       X
+		      |       |
+		     ---     ---
+		     / \     / \
+		    0   1   0   X
+	      ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+AS_ImplyLeftForward(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	long left,
+	long right)
+{
+  if(sat_ASImp(cm,d,v,0))
+    return(0);
+
+  v = SATnormalNode(v);
+  left = SATnormalNode(left);
+
+  SATvalue(v) = 0;
+  SATmakeImplied(v, d);
+  SATante(v) = left;
+
+  sat_Enqueue(cm->queue, v);
+  SATflags(v) |= InQueueMask;
+
+  SATflags(v) |= (SATflags(left) & ObjMask);
+
+  cm->each->nAigImplications++;
+
+  return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [A value implied to output due to right child.]
+
+  Description [A value implied to output due to right child
+		      X       X
+		      |       |
+		     ---     ---
+		     / \     / \
+		    1   0   X   0
+	      ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+AS_ImplyRightForward(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	long left,
+	long right)
+{
+
+  if(sat_ASImp(cm,d,v,0))
+    return(0);
+
+  v = SATnormalNode(v);
+  right = SATnormalNode(right);
+
+  SATvalue(v) = 0;
+  SATmakeImplied(v, d);
+  SATante(v) = right;
+
+  sat_Enqueue(cm->queue, v);
+  SATflags(v) |= InQueueMask;
+
+  SATflags(v) |= (SATflags(right) & ObjMask);
+  cm->each->nAigImplications++;
+
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [A value implied to output due to both child.]
+
+  Description [A value implied to output due to both child
+		      X
+		      |
+		     ---
+		     / \
+		    1   1
+	      ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+AS_ImplyForwardOne(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	long left,
+	long right)
+{
+
+  if(sat_ASImp(cm,d,v,1))
+    return(0);
+
+  v = SATnormalNode(v);
+  left = SATnormalNode(left);
+  right = SATnormalNode(right);
+
+  SATvalue(v) = 1;
+  SATmakeImplied(v, d);
+  SATante(v) = right;
+  SATante2(v) = left;
+
+  sat_Enqueue(cm->queue, v);
+  SATflags(v) |= InQueueMask;
+
+  SATflags(v) |= (SATflags(right) & ObjMask);
+  SATflags(v) |= (SATflags(left) & ObjMask);
+  cm->each->nAigImplications++;
+
+  return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [A value implied to right child due to both output and left.]
+
+  Description [A value implied to right child due to both output and left
+		      0
+		      |
+		     ---
+		     / \
+		    1   X
+	      ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+AS_ImplyPropRight(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	long left,
+	long right)
+{
+  int isInverted;
+
+  isInverted = SATisInverted(right);
+
+
+  if(sat_ASImp(cm,d,right, isInverted))
+    return(0);
+
+  v = SATnormalNode(v);
+  left = SATnormalNode(left);
+  right = SATnormalNode(right);
+
+  SATmakeImplied(right, d);
+  SATvalue(right) = isInverted;
+
+  SATante(right) = left;
+  SATante2(right) = v;
+
+  sat_Enqueue(cm->queue, right);
+  SATflags(right) |= InQueueMask;
+
+  SATflags(right) |= (SATflags(left) & ObjMask);
+  SATflags(right) |= (SATflags(v) & ObjMask);
+  cm->each->nAigImplications++;
+
+  return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [A value implied to right child due to both output and left.]
+
+  Description [A value implied to right child due to both output and left
+		      1
+		      |
+		     ---
+		     / \
+		    1   X
+	      ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+AS_ImplyPropRightOne(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	long left,
+	long right)
+{
+  int isInverted;
+
+
+  if(sat_ASImp(cm,d,right,!SATisInverted(right)))
+    return(0);
+
+  isInverted = SATisInverted(right);
+  v = SATnormalNode(v);
+  left = SATnormalNode(left);
+  right = SATnormalNode(right);
+
+  SATmakeImplied(right, d);
+
+  SATante(right) = v;
+
+  SATvalue(right) = !isInverted;
+
+  sat_Enqueue(cm->queue, right);
+  SATflags(right) |= InQueueMask;
+
+  SATflags(right) |= (SATflags(v) & ObjMask);
+  cm->each->nAigImplications++;
+
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [A value implied to left child due to both output and right.]
+
+  Description [A value implied to left child due to both output and right
+		      0
+		      |
+		     ---
+		     / \
+		    X   1
+	      ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+AS_ImplyPropLeft(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	long left,
+	long right)
+{
+  int isInverted;
+
+
+  if(sat_ASImp(cm,d,left,SATisInverted(left)))
+    return(0);
+
+  isInverted = SATisInverted(left);
+  v = SATnormalNode(v);
+  left = SATnormalNode(left);
+  right = SATnormalNode(right);
+
+  SATmakeImplied(left, d);
+
+  SATante(left) = v;
+  SATante2(left) = right;
+
+  SATvalue(left) = isInverted;
+
+  sat_Enqueue(cm->queue, left);
+  SATflags(left) |= InQueueMask;
+
+  SATflags(left) |= (SATflags(v) & ObjMask);
+  SATflags(left) |= (SATflags(right) & ObjMask);
+  cm->each->nAigImplications++;
+
+  return(0);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [A value implied to left child due to both output and right.]
+
+  Description [A value implied to left child due to both output and right
+		      1
+		      |
+		     ---
+		     / \
+		    X   1
+	      ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+AS_ImplyPropLeftOne(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	long left,
+	long right)
+{
+  int isInverted;
+
+
+  if(sat_ASImp(cm,d,left,!SATisInverted(left)))
+    return(0);
+
+  isInverted = SATisInverted(left);
+  v = SATnormalNode(v);
+  left = SATnormalNode(left);
+  right = SATnormalNode(right);
+
+  SATmakeImplied(left, d);
+
+  SATante(left) = v;
+
+  SATvalue(left) = !isInverted;
+
+  sat_Enqueue(cm->queue, left);
+  SATflags(left) |= InQueueMask;
+
+  SATflags(left) |= (SATflags(v) & ObjMask);
+  cm->each->nAigImplications++;
+
+  return(0);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [A value implied to left and right child due to output.]
+
+  Description [A value implied to left and right child due to output
+		      1
+		      |
+		     ---
+		     / \
+		    X   X
+	      ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+AS_ImplyPropLeftRight(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	long left,
+	long right)
+{
+  int isLeftInverted;
+  int isRightInverted;
+
+  int lImp=1,rImp=1;
+
+  if(left == right)	return 1;
+
+
+  if(sat_ASImp(cm,d,left,!SATisInverted(left)))
+    lImp = 0;
+  if(sat_ASImp(cm,d,right,!SATisInverted(right)))
+    rImp = 0;
+
+
+  isLeftInverted = SATisInverted(left);
+  isRightInverted = SATisInverted(right);
+
+  v = SATnormalNode(v);
+  left = SATnormalNode(left);
+  right = SATnormalNode(right);
+
+  if(lImp){
+    SATmakeImplied(left, d);
+    SATante(left) = v;
+    SATvalue(left) = !isLeftInverted;
+    sat_Enqueue(cm->queue, left);
+    SATflags(left) |= InQueueMask;
+    SATflags(left) |= (SATflags(v) & ObjMask);
+    cm->each->nAigImplications ++;
+  }
+
+  if(rImp){
+    SATmakeImplied(right, d);
+    SATante(right) = v;
+    SATvalue(right) = !isRightInverted;
+    sat_Enqueue(cm->queue, right);
+    SATflags(right) |= InQueueMask;
+    SATflags(right) |= (SATflags(v) & ObjMask);
+    cm->each->nAigImplications ++;
+  }
+
+  return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [erase previous assignments by arosat]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void
+AS_Undo(
+	satManager_t *cm,
+	satLevel_t *d)
+{
+satArray_t *implied, *satisfied;
+int size, i;
+long *space, v;
+ satVariable_t *var;
+ int dfs;
+
+  implied = d->implied;
+  space = implied->space;
+  size = implied->num;
+  for(i=0; i<size; i++, space++) {
+    v = *space;
+
+    SATvalue(v) = 2;
+    SATflags(v) &= ResetNewVisitedObjInQueueMask;
+    SATante(v) = 0;
+    SATante2(v) = 0;
+    SATlevel(v) = -1;
+
+
+    if(SATflags(SATnormalNode(v))&AssignedMask){
+      SATflags(SATnormalNode(v))&=ResetAssignedMask;
+      var=SATgetVariable(v);
+      dfs = var->scores[0]/SCOREUNIT;
+      cm->assignedArray[dfs]--;
+
+#if DBG
+      assert(cm->assignedArray[dfs]>=0);
+#endif
+    }
+
+  }
+
+  cm->implicatedSoFar -= size;
+
+  if(d->satisfied) {
+    satisfied = d->implied;
+    space = satisfied->space;
+    size = satisfied->num;
+    for(i=0; i<size; i++, space++) {
+      v = *space;
+
+      SATflags(v) &= ResetBDDSatisfiedMask;
+    }
+    d->satisfied->num = 0;
+  }
+  if(d->level > 0) {
+    if((cm->decisionHead[d->level-1]).currentVarPos < cm->currentVarPos)
+      cm->currentVarPos = (cm->decisionHead[d->level-1]).currentVarPos;
+  }
+  else
+    cm->currentVarPos = d->currentVarPos;
+
+  d->implied->num = 0;
+  d->currentVarPos = 0;
+
+  d->conflict = 0;
+
+
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [implication for cnf]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void
+AS_ImplyCNF(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	satArray_t *wl)
+{
+int size, i, j;
+long *space;
+long lit, *plit, *tplit;
+int dir;
+long nv, tv, *oplit, *wlit;
+int isInverted, value;
+int tsize, inverted;
+long cur, clit;
+satStatistics_t *stats;
+satOption_t *option;
+satQueue_t *Q;
+satVariable_t *var;
+
+ long tmpv;
+
+  size = wl->num;
+  space = wl->space;
+  Q = cm->queue;
+  stats = cm->each;
+  option = cm->option;
+  nv = 0;
+  wlit = 0;
+
+  for(i=0; i<size; i++) {
+    plit = (long*)space[i];
+
+    if(plit == 0 || *plit == 0) {
+      size--;
+      space[i] = space[size];
+      i--;
+      continue;
+    }
+
+    lit = *plit;
+    dir = SATgetDir(lit);
+    oplit = plit;
+
+    while(1) {
+      oplit += dir;
+      if(*oplit <=0) {
+	if(dir == 1) nv =- (*oplit);
+	if(dir == SATgetDir(lit)) {
+	  oplit = plit;
+	  dir = -dir;
+	  continue;
+	}
+
+	tv = SATgetNode(*wlit);
+
+	tmpv = tv;
+	isInverted = SATisInverted(tv);
+	tv = SATnormalNode(tv);
+	value = SATvalue(tv) ^ isInverted;
+	if(value == 0) {  /** conflict happens **/
+	  d->conflict = nv;
+	  wl->num = size;
+	  return;
+	}
+	else if(value > 1) { /** implication **/
+
+	  if(sat_ASImp(cm,d,tmpv,!isInverted))
+	    break;
+
+	  SATvalue(tv) = !isInverted;
+	  SATmakeImplied(tv, d);
+	  SATante(tv) = nv;
+
+	  if((SATflags(tv) & InQueueMask) == 0) {
+	    sat_Enqueue(Q, tv);
+	    SATflags(tv) |= InQueueMask;
+	  }
+
+	  stats->nCNFImplications++;
+
+	  /** to identify the objective dependent clause for incremental
+	  * SAT
+	  **/
+	  if(option->incTraceObjective == 1) {
+	    tsize = SATnumLits(nv);
+	    for(j=0, tplit=(long*)SATfirstLit(nv); j<tsize; j++, tplit++) {
+	      cur = SATgetNode(*tplit);
+	      cur = SATnormalNode(cur);
+	      if(SATflags(cur) & ObjMask) {
+		SATflags(tv) |= ObjMask;
+		break;
+	      }
+	    }
+	  }
+	}
+
+	break;
+      }
+
+      clit = *oplit;
+
+      tv = SATgetNode(clit);
+      inverted = SATisInverted(tv);
+      tv = SATnormalNode(tv);
+      value = SATvalue(tv) ^ inverted;
+
+      if(SATisWL(clit)) { /* found other watched literal */
+	wlit = oplit;
+	if(value == 1)	{
+	  break;
+	}
+	continue;
+      }
+
+      if(value == 0)
+	continue;
+
+      SATunsetWL(plit);
+
+      size--;
+      space[i] = space[size];
+      i--;
+
+      /** move watched literal */
+      var = SATgetVariable(tv);
+      SATsetWL(oplit, dir);
+
+      inverted = !inverted;
+      if(var->wl[inverted]) {
+	sat_ArrayInsert(var->wl[inverted], (long)oplit);
+      }
+      else {
+	var->wl[inverted] = sat_ArrayAlloc(4);
+	sat_ArrayInsert(var->wl[inverted], (long)oplit);
+      }
+
+      break;
+    }
+  }
+  wl->num = size;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [implication for aig node and cnf ]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+int
+AS_ImplyNode(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v)
+{
+long *fan, cur;
+int value;
+int i, size;
+long left, right;
+satVariable_t *var;
+satArray_t *wlArray;
+
+  value = SATvalue(v) ^ 1;
+  var = SATgetVariable(v);
+  wlArray = var->wl[value];
+
+  /** implcation on CNF **/
+  if(wlArray && wlArray->size) {
+    AS_ImplyCNF(cm, d, v, wlArray);
+  }
+
+  if(d->conflict)
+    return(0);
+
+  /** implication on AIG **/
+  fan = (long *)SATfanout(v);
+  size = SATnFanout(v);
+  for(i=0; i<size; i++, fan++) {
+    cur = *fan;
+    cur = cur >> 1;
+    cur = SATnormalNode(cur);
+    left = SATleftChild(cur);
+    right = SATrightChild(cur);
+    value = SATgetValue(left, right, cur);
+#if DBG
+
+    assert(SATflags(SATnormalNode(left))&CoiMask);
+    assert(SATflags(SATnormalNode(right))&CoiMask);
+#endif
+    (ASImplicationFN[value])(cm, d, cur, left, right);
+
+    if(d->conflict)
+      return(0);
+  }
+
+  left = SATleftChild(v);
+  right = SATrightChild(v);
+  value = SATgetValue(left, right, v);
+#if DBG
+
+  assert(left==bAig_NULL||SATflags(SATnormalNode(left))&CoiMask);
+  assert(right==bAig_NULL||SATflags(SATnormalNode(right))&CoiMask);
+#endif
+
+
+  (ASImplicationFN[value])(cm, d, v, left, right);
+
+  if(d->conflict)
+    return(0);
+
+
+  return(1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [The main procedure of implication propogation]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void
+AS_ImplicationMain(
+	satManager_t *cm,
+	satLevel_t *d)
+{
+satQueue_t *Q, *BDDQ;
+long v;
+
+  Q = cm->queue;
+  BDDQ = cm->BDDQueue;
+
+  while(1) {
+    v = sat_Dequeue(Q);
+    while(v && d->conflict == 0) {
+      AS_ImplyNode(cm, d, v);
+      SATflags(v) &= ResetInQueueMask;
+
+      v = sat_Dequeue(Q);
+    }
+
+    if(d->conflict)
+      break;
+
+    if(cm->option->BDDImplication) {
+      v = sat_Dequeue(Q);
+      while(v && d->conflict == 0) {
+	sat_ImplyBDD(cm, d, v);
+	SATflags(v) &= ResetInQueueMask;
+
+	v = sat_Dequeue(Q);
+      }
+    }
+
+    if(Q->size == 0 && BDDQ->size == 0)
+      break;
+  }
+
+  sat_CleanImplicationQueue(cm);
+  cm->implicatedSoFar += d->implied->num;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implication for assertation in one array]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void
+AS_ImplyArray(
+	satManager_t *cm,
+	satLevel_t *d,
+	satArray_t *arr)
+{
+int i, size;
+long v;
+int inverted, value;
+satQueue_t *Q;
+ satVariable_t *var;
+
+ int dfs;
+
+  if(arr == 0)	return;
+  if(cm->status)return;
+
+  size = arr->num;
+  Q = cm->queue;
+  for(i=0; i<size; i++) {
+    v = arr->space[i];
+    inverted = SATisInverted(v);
+    v = SATnormalNode(v);
+
+    value = !inverted;
+    if(SATvalue(v) < 2)	{
+      if(SATvalue(v) == value)	continue;
+      else {
+	cm->status = SAT_UNSAT;
+	d->conflict = v;
+
+	return;
+      }
+    }
+
+
+    var = SATgetVariable(v);
+    dfs = var->scores[0]/SCOREUNIT;
+    if(dfs==cm->LatchLevel){
+      if(!(SATflags(SATnormalNode(v))&AssignedMask)){
+	SATflags(SATnormalNode(v))|=AssignedMask;
+	cm->assignedArray[dfs]++;
+
+#if DBG
+	assert(cm->assignedArray[dfs]<=cm->numArray[dfs]);
+#endif
+	if(cm->assignedArray[dfs]==cm->numArray[dfs])
+	  sat_ASmergeLevel(cm);
+      }
+    }
+
+
+    SATvalue(v) = value;
+    SATmakeImplied(v, d);
+
+    if(cm->option->coreGeneration){
+      st_insert(cm->anteTable,(char *)SATnormalNode(v),(char *)SATnormalNode(v));
+    }
+
+    if((SATflags(v) & InQueueMask) == 0) {
+      sat_Enqueue(Q, v);
+      SATflags(v) |= InQueueMask;
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Preprocessing step for AROSAT]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void
+AS_PreProcessing(satManager_t *cm)
+{
+satLevel_t *d;
+
+
+  /** create implication queue **/
+  cm->queue = sat_CreateQueue(1024);
+  cm->BDDQueue = sat_CreateQueue(1024);
+  cm->unusedAigQueue = sat_CreateQueue(1024);
+
+  /**
+  create variable array : one can reduce size of variable array using
+  mapping. for fanout free internal node....
+  **/
+
+  if(cm->variableArray == 0) {
+    cm->variableArray = ALLOC(satVariable_t, cm->initNumVariables+1);
+    memset(cm->variableArray, 0,
+	    sizeof(satVariable_t) * (cm->initNumVariables+1));
+  }
+
+  cm->auxArray = sat_ArrayAlloc(1024);
+  cm->nonobjUnitLitArray = sat_ArrayAlloc(128);
+  cm->objUnitLitArray = sat_ArrayAlloc(128);
+
+
+
+  if(cm->option->AbRf == 0)
+    sat_CompactFanout(cm);
+
+
+  /*assign initial layer score to variables*/
+   sat_InitLayerScore(cm);
+
+  /** create decision stack **/
+  if(cm->decisionHeadSize == 0) {
+    cm->decisionHeadSize = 32;
+    cm->decisionHead = ALLOC(satLevel_t, cm->decisionHeadSize);
+    memset(cm->decisionHead, 0, sizeof(satLevel_t) * cm->decisionHeadSize);
+  }
+  cm->currentDecision = -1;
+
+  /** to avoid purify warning **/
+  SATvalue(2) = 2;
+  SATflags(0) = 0;
+
+  cm->initNodesArraySize = cm->nodesArraySize;
+  cm->beginConflict = cm->nodesArraySize;
+
+  /** incremental SAT.... **/
+  if(cm->option->incTraceObjective) {
+    sat_RestoreForwardedClauses(cm, 0);
+  }
+  else if(cm->option->incAll) {
+    sat_RestoreForwardedClauses(cm, 1);
+  }
+
+  if(cm->option->incTraceObjective) {
+    sat_MarkObjectiveFlagToArray(cm, cm->obj);
+    sat_MarkObjectiveFlagToArray(cm, cm->objCNF);
+  }
+
+
+  /** Level 0 decision.... **/
+  d = sat_AllocLevel(cm);
+
+  sat_ApplyForcedAssignmentMain(cm, d);
+
+  if(cm->status == SAT_UNSAT)
+    return;
+
+
+  if(cm->option->coreGeneration){
+    cm->rm = ALLOC(RTManager_t, 1);
+    memset(cm->rm,0,sizeof(RTManager_t));
+  }
+
+
+  AS_ImplyArray(cm, d, cm->auxObj);
+  AS_ImplyArray(cm, d, cm->obj);
+  AS_ImplyArray(cm,d,cm->assertArray);
+
+
+  AS_ImplicationMain(cm, d);
+  if(d->conflict) {
+    cm->status = SAT_UNSAT;
+  }
+
+  if(cm->status == 0) {
+    if(cm->option->incDistill) {
+      sat_IncrementalUsingDistill(cm);
+    }
+  }
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [backtrack procedure for arosat]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+void
+AS_Backtrack(
+	satManager_t *cm,
+	int level)
+{
+satLevel_t *d;
+
+
+  d = SATgetDecision(cm->currentDecision);
+  while(1) {
+    if(d->level <= level)
+      break;
+
+    AS_Undo(cm, d);
+    cm->currentDecision--;
+    if(cm->currentDecision == -1)
+      break;
+    d = SATgetDecision(cm->currentDecision);
+  }
+  return;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [procedure for updating score]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+void
+AS_UpdateScore(
+	satManager_t *cm)
+{
+satArray_t *one, *tmp;
+satArray_t *ordered;
+satVariable_t *var;
+int size, i;
+long v;
+int value;
+
+ int baseScore,realScore,newNum;
+
+  ordered = cm->orderedVariableArray;
+
+  one = sat_ArrayAlloc(ordered->num);
+  tmp = sat_ArrayAlloc(ordered->num);
+
+  size = ordered->num;
+  for(i=0; i<size; i++) {
+    v = ordered->space[i];
+
+    if(SATvalue(v) < 2 && SATlevel(v) == 0)
+      continue;
+
+    var = SATgetVariable(v);
+
+    baseScore =(var->scores[0]/SCOREUNIT)*SCOREUNIT;
+    realScore = var->scores[0]%SCOREUNIT;
+    newNum = var->litsCount[0] - var->lastLitsCount[0];
+    var->scores[0] =  baseScore + (realScore>>1) + newNum;
+    baseScore =(var->scores[1]/SCOREUNIT)*SCOREUNIT;
+    realScore = var->scores[1]%SCOREUNIT;
+    newNum = var->litsCount[1] - var->lastLitsCount[1];
+    var->scores[1] =  baseScore + (realScore>>1) + newNum;
+
+    var->lastLitsCount[0] = var->litsCount[0];
+    var->lastLitsCount[1] = var->litsCount[1];
+
+
+    if((var->scores[0] + var->scores[1]) < 1) {
+      sat_ArrayInsert(one, v);
+    }
+    else {
+      value = (var->scores[0] > var->scores[1]) ? var->scores[0] : var->scores[1];
+      sat_ArrayInsert(tmp, v);
+      sat_ArrayInsert(tmp, value);
+    }
+  }
+
+  qsort(tmp->space, (tmp->num)>>1, sizeof(long)*2, ScoreCompare);
+
+  ordered->num = 0;
+  size = tmp->num;
+  for(i=0; i<size; i++) {
+    v = tmp->space[i];
+    sat_ArrayInsert(ordered, v);
+    var = SATgetVariable(v);
+    var->pos = (i>>1);
+    i++;
+  }
+
+  size = one->num;
+  for(i=0; i<size; i++) {
+    v = one->space[i];
+    var = SATgetVariable(v);
+    var->pos = ordered->num;
+    sat_ArrayInsert(ordered, v);
+  }
+
+  sat_ArrayFree(one);
+  sat_ArrayFree(tmp);
+
+  cm->orderedVariableArray = ordered;
+  cm->currentVarPos = 0;
+
+  for(i=1; i<cm->currentDecision; i++) {
+    cm->decisionHead[i].currentVarPos = 0;
+  }
+
+  if(cm->option->verbose > 3)
+    sat_PrintScore(cm);
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Periodically executed operations]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void
+AS_PeriodicFunctions(satManager_t *cm)
+{
+satStatistics_t *stats;
+satOption_t *option;
+int nDecisions;
+int gap;
+
+  stats = cm->each;
+  option = cm->option;
+  nDecisions = stats->nDecisions-stats->nShrinkDecisions;
+  if(nDecisions && !(nDecisions % option->decisionAgeInterval)) {
+    if(option->decisionAgeRestart) {
+      gap = stats->nConflictCl-stats->nOldConflictCl;
+      if(gap > option->decisionAgeInterval>>2)  {
+
+	AS_UpdateScore(cm);
+
+	AS_Backtrack(cm, cm->lowestBacktrackLevel);
+	cm->currentTopConflict = cm->literals->last-1;
+	cm->currentTopConflictCount = 0;
+	cm->lowestBacktrackLevel = MAXINT;
+      }
+      stats->nOldConflictCl = stats->nConflictCl;
+    }
+    else {
+
+      AS_UpdateScore(cm);
+    }
+
+  }
+
+  if(stats->nBacktracks > option->nextClauseDeletion) {
+    option->nextClauseDeletion += option->clauseDeletionInterval;
+    sat_ClauseDeletion(cm);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Decision procedure]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+satLevel_t *
+AS_MakeDecision(satManager_t *cm)
+{
+satLevel_t *d;
+int value;
+long v;
+satStatistics_t *stats;
+
+  d = SATgetDecision(cm->currentDecision);
+
+  if(cm->queue->size)
+    return(d);
+
+  d = sat_AllocLevel(cm);
+
+  v = 0;
+  v = sat_DecisionBasedOnBDD(cm, d);
+
+  if(v == 0)
+    v = sat_DecisionBasedOnScore(cm, d);
+
+  if(v == 0)
+    return(0);
+
+
+  sat_ASDec(cm,d,v);
+
+  stats = cm->each;
+
+  stats->nDecisions++;
+
+  value = !(SATisInverted(v));
+  v = SATnormalNode(v);
+  d->decisionNode = v;
+
+
+    if((SATgetVariable(v)->RecVal)!=0){
+      if(SATgetVariable(v)->RecVal==-1)
+	value=0;
+      else{
+#if DBG
+	assert(SATgetVariable(v)->RecVal==1);
+#endif
+	value=1;
+      }
+
+    }
+
+
+  SATvalue(v) = value;
+
+  SATmakeImplied(v, d);
+#if DBG
+
+  assert(SATflags(v)&CoiMask);
+#endif
+
+  sat_Enqueue(cm->queue, v);
+  SATflags(v) |= InQueueMask;
+
+  return(d);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Find UIP for generating conflict clauses]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void
+AS_FindUIP(
+	satManager_t *cm,
+	satArray_t *clauseArray,
+	satLevel_t *d,
+	int *objectFlag,
+	int *bLevel,
+	long *fdaLit)
+{
+long conflicting;
+int nMarked, value;
+int first, i,j;
+long *space, v,left,right,inverted,result,*tmp;
+satArray_t *implied;
+satOption_t *option;
+RTnode_t  tmprt;
+int size = 0;
+long *lp, *tmpIP,ante,ante2,node;
+ RTManager_t * rm = cm->rm;
+
+  conflicting = d->conflict;
+  nMarked = 0;
+  option = cm->option;
+  if(option->incTraceObjective) *objectFlag = 0;
+  else                          *objectFlag = ObjMask;
+
+  (*objectFlag) |= (SATflags(conflicting) & ObjMask);
+
+  /* find seed from conflicting clause to find unique implication point.
+   * */
+  clauseArray->num = 0;
+  sat_MarkNodeInConflict(
+	  cm, d, &nMarked, objectFlag, bLevel, clauseArray);
+
+  /* Traverse implication graph backward */
+  first = 1;
+  implied = d->implied;
+  space = implied->space+implied->num-1;
+
+
+  if(cm->option->coreGeneration){
+    /*if last conflict is CNF*/
+    if(SATflags(conflicting)&IsCNFMask){
+      /*is conflict CNF*/
+      if(SATflags(conflicting)&IsConflictMask){
+	 if(!st_lookup(cm->RTreeTable,(char*)conflicting,&tmprt)){
+	    fprintf(vis_stderr,"RTree node of conflict cnf %ld is not in RTreeTable\n",ante);
+	    exit(0);
+	  }
+	  else{
+	    rm->root = tmprt;
+	  }
+      }
+      /*CNF but not conflict*/
+      else{
+	rm->root = RTCreateNode(rm);
+	RT_oriClsIdx(rm->root) = conflicting;
+	size = SATnumLits(conflicting);
+	RT_fSize(rm->root) = size;
+      }
+    }
+    /*if last conflict is AIG*/
+    else{
+      rm->root = RTCreateNode(rm);
+      node = SATnormalNode(conflicting);
+      left = SATleftChild(node);
+      right = SATrightChild(node);
+      result = PureSat_IdentifyConflict(cm,left,right,conflicting);
+      inverted = SATisInverted(left);
+      left = SATnormalNode(left);
+      left = inverted ? SATnot(left) : left;
+
+      inverted = SATisInverted(right);
+      right = SATnormalNode(right);
+      right = inverted ? SATnot(right) : right;
+
+      j = node;
+
+      if(result == 1){
+	tmp = ALLOC(long,3);
+	tmp[0] = left;
+	tmp[1] = SATnot(j);
+	size = 2;
+      }
+      else if(result == 2){
+	tmp = ALLOC(long,3);
+	tmp[0] = right;
+	tmp[1] = SATnot(j);
+	size = 2;
+      }
+      else if(result == 3){
+	tmp = ALLOC(long,4);
+	tmp[0] = SATnot(left);
+	tmp[1] = SATnot(right);
+	tmp[2] = j;
+	size = 3;
+      }
+      else{
+	fprintf(vis_stderr,"wrong returned result value, exit\n");
+	exit(0);
+      }
+
+      lp = tmp;
+      sat_BuildRT(cm,rm->root, lp, tmpIP,size,1);
+      FREE(tmp);
+    }
+  }
+
+
+  for(i=implied->num-1; i>=0; i--, space--) {
+    v = *space;
+    if(SATflags(v) & VisitedMask) {
+      SATflags(v) &= ResetVisitedMask;
+      --nMarked;
+
+      if(nMarked == 0 && (!first || i==0))  {
+	value = SATvalue(v);
+	*fdaLit = v^(!value);
+	sat_ArrayInsert(clauseArray, *fdaLit);
+	break;
+      }
+
+
+
+      if(cm->option->coreGeneration){
+	ante = SATante(v);
+	if(ante==0){
+	  if(!(st_lookup(cm->anteTable, (char *)SATnormalNode(v),&ante))){
+	    fprintf(vis_stderr,"ante = 0 and is not in anteTable %ld\n",v);
+	    exit(0);
+	  }
+	}
+
+	/*build non-leaf node*/
+	tmprt = RTCreateNode(rm);
+	RT_pivot(tmprt) = SATnormalNode(v);
+	RT_right(tmprt) = rm->root;
+	rm->root = tmprt;
+
+	if((SATflags(ante)&IsConflictMask)&&(SATflags(ante)&IsCNFMask)){
+	  if(!st_lookup(cm->RTreeTable,(char*)ante,&tmprt)){
+	    fprintf(vis_stderr,"RTree node of conflict cnf %ld is not in RTreeTable\n",ante);
+	    exit(0);
+	  }
+	  else{
+	    RT_left(rm->root) = tmprt;
+	  }
+	}
+	else{ /* if not conflict CNF*/
+	  /*left */
+	  tmprt = RTCreateNode(rm);
+	  RT_left(rm->root) = tmprt;
+	  /*left is AIG*/
+	  if(!(SATflags(ante) & IsCNFMask)){
+	    /*generate formula for left*/
+	    tmp = ALLOC(long,3);
+	    value = SATvalue(v);
+	    node = SATnormalNode(v);
+	    node = value==1?node:SATnot(node);
+	    tmp[0] = node;
+
+	    size = 1;
+	    if(ante != SATnormalNode(v)){
+	      value = SATvalue(ante);
+	      node = SATnormalNode(ante);
+	      node = value==1?SATnot(node):node;
+	      tmp[1] = node;
+	      size++;
+	      ante2 = SATante2(v);
+	      if(ante2){
+		value = SATvalue(ante2);
+		node = SATnormalNode(ante2);
+		node = value==1?SATnot(node):node;
+		tmp[2] = node;
+		size++;
+	      }
+	    }
+	    /*generate p1 and p2*/
+	    lp = tmp;
+	    sat_BuildRT(cm,tmprt,lp,tmpIP,size,1);
+	    FREE(tmp);
+	  }
+	  /* left is CNF*/
+	  else{
+	    RT_oriClsIdx(tmprt) = ante;
+	    //generate p1 and p2 for left
+	    lp = (long*)SATfirstLit(ante);
+	    size = SATnumLits(ante);
+	    RT_fSize(tmprt) = size;
+	  }
+	} /*else{  if not conflict CNF*/
+
+      }/*if(cm->option->coreGeneration){*/
+
+
+      sat_MarkNodeInImpliedNode(
+	      cm, d, v, &nMarked, objectFlag, bLevel, clauseArray);
+      /*Bing:Important for EffIP*/
+      first = 0;
+    }
+    /* first = 0;*/
+  }
+
+
+  /* Minimize conflict clause */
+  if(option->minimizeConflictClause)
+    sat_MinimizeConflictClause(cm, clauseArray);
+  else
+    sat_ResetFlagForClauseArray(cm, clauseArray);
+
+  return;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Conflict analysis procedure]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+int
+AS_ConflictAnalysis(
+	satManager_t *cm,
+	satLevel_t *d)
+{
+satStatistics_t *stats;
+satOption_t *option;
+satArray_t *clauseArray;
+int objectFlag;
+int bLevel;
+long fdaLit, learned, conflicting;
+int inverted;
+RTManager_t * rm = cm->rm;
+
+
+  conflicting = d->conflict;
+
+  if(d->level == 0) {
+      /** Bing : UNSAT core generation */
+    if(cm->option->coreGeneration)
+      sat_ConflictAnalysisForCoreGen(cm, d);
+    cm->currentDecision--;
+    return (-1);
+  }
+
+  stats = cm->each;
+  option = cm->option;
+
+
+  stats->nBacktracks++;
+
+  clauseArray = cm->auxArray;
+
+  bLevel = 0;
+  fdaLit = -1;
+  clauseArray->num = 0;
+
+  /*  Find Unique Implication Point */
+  AS_FindUIP(cm, clauseArray, d, &objectFlag, &bLevel, &fdaLit);
+  stats->nNonchonologicalBacktracks += (d->level - bLevel);
+
+
+  if(clauseArray->num == 0) {
+    sat_PrintImplicationGraph(cm, d);
+    sat_PrintNode(cm, conflicting);
+  }
+
+  /* If we could find UIP then it is critical error...
+  * at lease the decision node has to be detected as UIP.
+  */
+  if(fdaLit == -1) {
+    fprintf(vis_stdout, "%s ERROR : Illegal unit literal\n", cm->comment);
+    fflush(vis_stdout);
+    sat_PrintNode(cm, conflicting);
+    sat_PrintImplicationGraph(cm, d);
+    sat_PrintDotForConflict(cm, d, conflicting, 0);
+    exit(0);
+  }
+
+  if(bLevel && cm->lowestBacktrackLevel > bLevel)
+    cm->lowestBacktrackLevel = bLevel;
+
+
+  inverted = SATisInverted(fdaLit);
+  fdaLit = SATnormalNode(fdaLit);
+
+  if(option->verbose > 2) {
+    if(option->verbose > 4)
+      sat_PrintNode(cm, conflicting);
+    fprintf(vis_stdout, "conflict at %3d on %6ld  bLevel %d UnitLit ",
+	    d->level, conflicting, bLevel);
+    sat_PrintNodeAlone(cm, fdaLit);
+    fprintf(vis_stdout, "\n");
+  }
+
+  d->conflict = 0;
+
+  /* unit literal conflict clause */
+  if(clauseArray->num == 1) {
+    learned = sat_AddUnitConflictClause(cm, clauseArray, objectFlag);
+
+    stats->nUnitConflictCl++;
+    cm->currentTopConflict = cm->literals->last-1;
+    cm->currentTopConflictCount = 0;
+
+    AS_Backtrack(cm, 0);
+
+    d = SATgetDecision(cm->currentDecision);
+    cm->implicatedSoFar -= d->implied->num;
+    SATante(fdaLit) = 0;
+
+
+    if(!(SATflags(SATnormalNode(fdaLit))&AssignedMask)){
+      satVariable_t *var = SATgetVariable(fdaLit);
+      int dfs = var->scores[0]/SCOREUNIT;
+#if DBG
+      assert(dfs==cm->LatchLevel);
+#endif
+      SATflags(SATnormalNode(fdaLit))|=AssignedMask;
+      cm->assignedArray[dfs]++;
+      if(cm->assignedArray[dfs]==cm->numArray[dfs])
+	sat_ASmergeLevel(cm);
+    }
+
+
+    SATvalue(fdaLit) = inverted;
+    SATmakeImplied(fdaLit, d);
+
+    if((SATflags(fdaLit) & InQueueMask)  == 0) {
+      sat_Enqueue(cm->queue, fdaLit);
+      SATflags(fdaLit) |= InQueueMask;
+    }
+
+    clauseArray->num = 0;
+
+    if(option->incTraceObjective && objectFlag == 0)
+      sat_ArrayInsert(cm->nonobjUnitLitArray, SATnot(fdaLit));
+
+    if(option->incDistill && objectFlag)
+      sat_ArrayInsert(cm->objUnitLitArray, SATnot(fdaLit));
+
+    if(objectFlag)
+      SATflags(fdaLit) |= ObjMask;
+
+    /* Bing: UNSAT core generation */
+    if(cm->option->coreGeneration){
+
+      st_insert(cm->anteTable,(char*)SATnormalNode(fdaLit),(char*)learned);
+      st_insert(cm->RTreeTable, (char *)learned, (char *)rm->root);
+      RT_oriClsIdx(rm->root) = learned;
+    }
+
+    return(bLevel);
+  }
+
+  /* add conflict learned clause */
+  learned = sat_AddConflictClause(cm, clauseArray, objectFlag);
+
+  cm->currentTopConflict = cm->literals->last-1;
+  cm->currentTopConflictCount = 0;
+
+   /* Bing: UNSAT core generation */
+  if(cm->option->coreGeneration){
+   st_insert(cm->RTreeTable, (char *)learned, (char *)rm->root);
+   RT_oriClsIdx(rm->root) = learned;
+  }
+
+  if(option->verbose > 2) {
+    sat_PrintNode(cm, learned);
+    fflush(vis_stdout);
+  }
+
+
+  /* apply Deepest Variable Hike decision heuristic */
+  if(option->decisionHeuristic & DVH_DECISION)
+   sat_UpdateDVH(cm, d, clauseArray, bLevel, fdaLit);
+
+
+  /* Backtrack and failure driven assertion */
+  AS_Backtrack(cm, bLevel);
+
+  d = SATgetDecision(bLevel);
+  cm->implicatedSoFar -= d->implied->num;
+
+
+    if(!(SATflags(SATnormalNode(fdaLit))&AssignedMask)){
+      satVariable_t *var = SATgetVariable(fdaLit);
+      int dfs = var->scores[0]/SCOREUNIT;
+#if DBG
+      assert(dfs==cm->LatchLevel);
+#endif
+      SATflags(SATnormalNode(fdaLit))|=AssignedMask;
+      cm->assignedArray[dfs]++;
+      if(cm->assignedArray[dfs]==cm->numArray[dfs])
+	sat_ASmergeLevel(cm);
+    }
+
+
+  SATante(fdaLit) = learned;
+  SATvalue(fdaLit) = inverted;
+  SATmakeImplied(fdaLit, d);
+
+  if((SATflags(fdaLit) & InQueueMask)  == 0) {
+    sat_Enqueue(cm->queue, fdaLit);
+    SATflags(fdaLit) |= InQueueMask;
+  }
+
+  clauseArray->num = 0;
+  if(objectFlag)
+    SATflags(fdaLit) |= ObjMask;
+
+  return(bLevel);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Main solving procedure]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void
+AS_Solve(satManager_t *cm)
+{
+satLevel_t *d;
+satOption_t *option;
+satVariable_t *var;
+int level;
+
+  d = SATgetDecision(0);
+  cm->implicatedSoFar = d->implied->num;
+  cm->currentTopConflict = 0;
+
+  option = cm->option;
+  if(option->BDDMonolithic) {
+    sat_TryToBuildMonolithicBDD(cm);
+  }
+
+  if(cm->status == SAT_UNSAT) {
+    AS_Undo(cm, SATgetDecision(0));
+    return;
+  }
+
+  while(1) {
+    AS_PeriodicFunctions(cm);
+
+    if(cm->currentDecision == 0)
+      sat_BuildLevelZeroHyperImplicationGraph(cm);
+
+    d = AS_MakeDecision(cm);
+
+    if(d == 0)	{
+      cm->status = SAT_SAT;
+      return;
+    }
+
+    while(1) {
+      AS_ImplicationMain(cm, d);
+
+      if(d->conflict == 0)	{
+	if(cm->option->verbose > 2) {
+	  var = SATgetVariable(d->decisionNode);
+	  fprintf(vis_stdout, "decision at %3d on %6ld <- %ld score(%d %d) %d %ld implied %.3f %%\n",
+	    d->level, d->decisionNode, SATvalue(d->decisionNode),
+	    var->scores[0], var->scores[1],
+	    cm->each->nDecisions, d->implied->num,
+	    (double)cm->implicatedSoFar/(double)cm->initNumVariables * 100);
+	  fflush(vis_stdout);
+	}
+
+	break;
+      }
+	if(cm->option->verbose > 2) {
+	  var = SATgetVariable(d->decisionNode);
+	  fprintf(vis_stdout, "decision at %3d on %6ld <- %ld score(%d %d) %d %ld implied  %.3f %% Conflict\n",
+	    d->level, d->decisionNode, SATvalue(d->decisionNode),
+	    var->scores[0], var->scores[1],
+	    cm->each->nDecisions, d->implied->num,
+	    (double)cm->implicatedSoFar/(double)cm->initNumVariables * 100);
+	  fflush(vis_stdout);
+	}
+
+      level = AS_ConflictAnalysis(cm, d);
+
+      if(cm->currentDecision == -1) {
+	if(cm->option->incDistill) {
+	  sat_BuildTrieForDistill(cm);
+	}
+	AS_Undo(cm, SATgetDecision(0));
+	cm->status = SAT_UNSAT;
+	return;
+      }
+
+      d = SATgetDecision(cm->currentDecision);
+    }
+
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [The main procedure of AROSAT solver]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void AS_Main(satManager_t *cm)
+{
+long btime, etime;
+
+  btime = util_cpu_time();
+  AS_PreProcessing(cm);
+
+  if(cm->status == 0)
+    AS_Solve(cm);
+
+  /** Bing: UNSAT core generation **/
+  if(cm->option->coreGeneration && cm->status == SAT_UNSAT){
+
+    sat_GenerateCore_All(cm);
+  }
+
+  sat_PostProcessing(cm);
+
+  etime = util_cpu_time();
+  cm->each->satTime = (double)(etime - btime) / 1000.0 ;
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Create one layer for AROSAT]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+void PureSatCreateOneLayer(Ntk_Network_t *network,
+			   PureSat_Manager_t *pm,
+			   satManager_t *cm,
+			   array_t * latchArray,
+			   int layer)
+{
+  mAig_Manager_t * manager = Ntk_NetworkReadMAigManager(network);
+  st_table * node2MvfAigTable =(st_table *) Ntk_NetworkReadApplInfo(network,
+							 MVFAIG_NETWORK_APPL_KEY);
+  MvfAig_Function_t *mvfAig;
+  bAigTimeFrame_t * tf = manager->timeframeWOI;
+  mAigMvar_t lmVar;
+  mAigBvar_t bVar;
+  array_t *bVarList,*mVarList;
+  int i,j,k,lmAigId,index,index1;
+  char * name;
+  Ntk_Node_t * latch;
+  bAigEdge_t node,v, *li, *bli;
+  st_table *table = st_init_table(st_numcmp,st_numhash);
+
+  bVarList = mAigReadBinVarList(manager);
+  mVarList = mAigReadMulVarList(manager);
+
+  arrayForEachItem(char*,latchArray,i,name){
+
+    latch = Ntk_NetworkFindNodeByName(network,name);
+    st_lookup(node2MvfAigTable,latch,&mvfAig);
+    for(j=0;j<mvfAig->num;j++){
+      int retVal;
+      v = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(mvfAig,j));
+      if(v==bAig_Zero||v==bAig_One)
+	continue;
+      retVal = st_lookup(tf->li2index,(char *)v,&index);
+      assert(retVal);
+      for(k=1;k<=pm->Length;k++){
+	li = tf->latchInputs[k];
+	if(li[index]==bAig_Zero||li[index]==bAig_One)
+	  continue;
+	node = bAig_NonInvertedEdge(li[index]);
+	st_insert(table,(char*)node,(char*)(long)layer);
+
+      }
+    }
+
+    lmAigId = Ntk_NodeReadMAigId(latch);
+    lmVar = array_fetch(mAigMvar_t, mVarList,lmAigId);
+    for(j=0,index1=lmVar.bVars;j<lmVar.encodeLength;j++,index1++){
+      int retVal;
+      bVar = array_fetch(mAigBvar_t,bVarList,index1);
+      if(bVar.node==bAig_Zero||bVar.node==bAig_One)
+	continue;
+      retVal = st_lookup(tf->bli2index,(char *)bVar.node,&index);
+      assert(retVal);
+      for(k=1;k<=pm->Length;k++){
+	bli = tf->blatchInputs[k];
+	if(bli[index]==bAig_Zero||bli[index]==bAig_One)
+	  continue;
+	node = bAig_NonInvertedEdge(bli[index]);
+	st_insert(table,(char*)node,(char*)(long)layer);
+
+      }
+    }
+  }
+
+  st_insert(cm->layerTable,table,(char*)(long)layer);
+
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Create all the layers]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+void PureSatCreateLayer(Ntk_Network_t *network,
+			PureSat_Manager_t *pm,
+			satManager_t *cm,
+			array_t *absModel,
+			array_t *sufArray)
+{
+  int layer;
+  char* name;
+  int i,j,threshold;
+  array_t *tmpArray;
+
+  if(sufArray->num<4)
+    layer = 1;
+  else if(sufArray->num<6)
+    layer = 2;
+  else if(sufArray->num<10)
+    layer = 3;
+  else if(sufArray->num<20)
+    layer = 5;
+  else if(sufArray->num<50)
+    layer = 8;
+  else
+    layer = 10;
+
+  threshold = sufArray->num/layer;
+  layer = array_n(sufArray)/threshold;
+  layer = sufArray->num%threshold?layer+1:layer;
+
+  cm->LatchLevel = layer;
+  cm->OriLevel = layer;
+  cm->layerTable = st_init_table(st_ptrcmp,st_ptrhash);
+
+  layer = layer+1;
+  for(i=0;i<array_n(sufArray);i=i+threshold){
+    if(i==0)
+      tmpArray = array_dup(absModel);
+    else
+      tmpArray = array_alloc(char*,0);
+    layer = layer-1;
+    for(j=0;j<threshold;j++){
+      if(i+j>=array_n(sufArray))
+	break;
+      name = array_fetch(char*,sufArray,i+j);
+      array_insert_last(char*,tmpArray,name);
+
+    }
+    PureSatCreateOneLayer(network,pm,cm,tmpArray,layer);
+    array_free(tmpArray);
+  }
+  assert(layer==1);
+  cm->assignedArray = ALLOC(int,cm->LatchLevel+1);
+  cm->numArray = ALLOC(int,cm->LatchLevel+1);
+
+}
Index: vis_dev/vis-2.3/src/puresat/puresatBMC.c
===================================================================
--- vis_dev/vis-2.3/src/puresat/puresatBMC.c	(revision 14)
+++ vis_dev/vis-2.3/src/puresat/puresatBMC.c	(revision 14)
@@ -0,0 +1,1474 @@
+/**CFile***********************************************************************
+
+  FileName    [puresatMain.c]
+
+  PackageName [puresat]
+
+  Synopsis    [Abstraction refinement for large scale invariant checking.]
+
+  Description [This file contains the functions to check invariant properties
+  by the PureSAT abstraction refinement algorithm, which is entirely based on
+  SAT solver, the input of which could be either CNF or AIG. It has several
+  parts:
+
+  * Localization-reduction base Abstraction
+  * K-induction or interpolation to prove the truth of a property
+  * Bounded Model Checking to find bugs
+  * Incremental concretization based methods to verify abstract bugs
+  * Incremental SAT solver to improve efficiency
+  * UNSAT proof based method to obtain refinement
+  * AROSAT to bring in only necessary latches into unsat proofs
+  * Bridge abstraction to get compact coarse refinement
+  * Refinement minization to guarrantee minimal refinements
+  * Unsat proof-based refinement minimization to eliminate multiple candidate
+    by on SAT test
+  * Refinement prediction to decrease the number of refinement iterations
+  * Dynamic switching to redistribute computional resources to improve
+    efficiency
+  
+  For more information, please check the BMC'03, ICCAD'04, STTT'05 and TACAS'05
+  paper of Li et al., "A satisfiability-based appraoch to abstraction
+  refinement in model checking", " Abstraction in symbolic model checking
+  using satisfiability as the only decision procedure", "Efficient computation
+  of small abstraction refinements", and "Efficient abstraction refinement in
+  interpolation-based unbounded model checking"]
+  
+  Author      [Bing Li]
+
+  Copyright   [Copyright (c) 2004 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without
+  license or royalty fees, to use, copy, modify, and distribute this
+  software and its documentation for any purpose, provided that the
+  above copyright notice and the following two paragraphs appear in
+  all copies of this software.]
+
+******************************************************************************/
+#include "puresatInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Insert clauses of (Si!=Sj) for k-induction checking]
+
+  Description [Insert clauses of (Si!=Sj) for k-induction checking]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSatInsertNewClauseForSimplePath(array_t *vertexArray,
+					 Ntk_Network_t *network,
+					 int step1,
+					 int step2,
+					 BmcCnfClauses_t *cnfClauses,
+					 st_table *nodeToMvfAigTable)
+{
+  int i,j,k,mvfSize,index1,index2, cnfIndex;
+  Ntk_Node_t * latch;
+  MvfAig_Function_t *latchMvfAig;
+  bAigEdge_t * latchBAig;
+  array_t * tmpclause, *clauseArray, * clause, * clause1,*latchClause;
+  mAig_Manager_t    *manager = Ntk_NetworkReadMAigManager(network);
+  char * Name;
+  boolean nextLatch = FALSE;
+
+  latchClause = array_alloc(int,0);
+  arrayForEachItem(char *,vertexArray,j,Name)
+    {
+      nextLatch = FALSE;
+      clause = array_alloc(int,0); /*(-A + -A1 + -A2 + -A3)*/
+      clauseArray  = array_alloc(array_t *,0);/*(A + -A1)(A + -A2)(A + -A3)*/
+      latch = Ntk_NetworkFindNodeByName(network,Name);
+      latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+      if (latchMvfAig ==  NIL(MvfAig_Function_t)){
+	latchMvfAig = Bmc_NodeBuildMVF(network, latch);
+	array_free(latchMvfAig);
+	latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+      }
+      mvfSize   = array_n(latchMvfAig);
+      latchBAig = ALLOC(bAigEdge_t, mvfSize); 
+
+      for(i=0; i< mvfSize; i++){
+	latchBAig[i] = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(latchMvfAig, i));
+	}
+      for(i=0; i< mvfSize; i++){
+	if (latchBAig[i] == bAig_One)
+	  nextLatch=TRUE;break;   /* the clause is always true */
+      }
+
+      if(!nextLatch)
+	{
+	  for(i=0; i< mvfSize; i++){
+	    latchBAig[i] = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(latchMvfAig, i));
+	    index1 = BmcGenerateCnfFormulaForAigFunction(manager,latchBAig[i],step1,cnfClauses);
+	    index2 = BmcGenerateCnfFormulaForAigFunction(manager,latchBAig[i],step2,cnfClauses);
+	    
+	    cnfIndex = cnfClauses->cnfGlobalIndex++; 
+	    tmpclause  = array_alloc(int, 3);
+	    array_insert(int, tmpclause, 0, -index2);
+	    array_insert(int, tmpclause, 1, -index1);
+	    array_insert(int, tmpclause, 2,  cnfIndex);
+	    BmcCnfInsertClause(cnfClauses, tmpclause);
+	    array_free(tmpclause);
+	    
+	    tmpclause  = array_alloc(int, 2);
+	    array_insert(int, tmpclause, 0, index2);
+	    array_insert(int, tmpclause, 1, -cnfIndex);
+	    BmcCnfInsertClause(cnfClauses, tmpclause);
+	    array_free(tmpclause);
+	    
+	    tmpclause  = array_alloc(int, 2);
+	    array_insert(int, tmpclause, 0, index1);
+	    array_insert(int, tmpclause, 1, -cnfIndex);
+	    BmcCnfInsertClause(cnfClauses, tmpclause);
+	    array_free(tmpclause);
+	    
+	    /*(-A + A1 + A2 + A3)*/
+	    array_insert_last(int,clause,cnfIndex);
+	    /*(A + -A1)(A + -A2)(A + -A3)*/
+	    clause1 = array_alloc(int,0);/*(A + -A1/2/3)*/
+	    array_insert_last(int,clause1,-cnfIndex);
+	    array_insert_last(array_t *,clauseArray,clause1);
+	    
+	  }
+	 
+	  cnfIndex = cnfClauses->cnfGlobalIndex++; /*A*/
+	  /*(A + -A1)(A + -A2)(A + -A3)*/
+	  arrayForEachItem(array_t *,clauseArray,k,clause1)
+	    {
+	      array_insert_last(int,clause1,cnfIndex);
+	      BmcCnfInsertClause(cnfClauses,clause1);
+	      array_free(clause1);
+	    }
+	  array_free(clauseArray);
+	  
+	  /*(-A + A1 + A2 + A3)*/
+	  array_insert_last(int,clause,-cnfIndex);
+	  BmcCnfInsertClause(cnfClauses,clause);
+	  array_free(clause);
+	  
+	  /*(C + -A + -B)*/
+	  array_insert_last(int,latchClause,-cnfIndex);
+	}
+      FREE(latchBAig);
+    }
+  cnfIndex = cnfClauses->cnfGlobalIndex++; /* C*/
+  array_insert_last(int,latchClause,cnfIndex); /*(C + -A + -B)*/
+  BmcCnfInsertClause(cnfClauses,latchClause);
+  array_free(latchClause);
+  
+  /*(-C)*/
+  latchClause = array_alloc(int,0);
+  array_insert_last(int,latchClause,-cnfIndex);
+  BmcCnfInsertClause(cnfClauses,latchClause);
+  array_free(latchClause);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Insert clauses of (Si!=I) for k-induction checking]
+
+  Description [Insert clauses of (Si!=I) for k-induction checking]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSatInsertNewClauseForInit(array_t *vertexArray,
+			       Ntk_Network_t *network,
+			       int step1,
+			       int step2,
+			       BmcCnfClauses_t *cnfClauses,
+			       st_table *nodeToMvfAigTable)
+{
+  int i,j,k,mvfSize,index1=0,index2=0, cnfIndex;
+  Ntk_Node_t * latch, *latchInit;
+  MvfAig_Function_t *initMvfAig,*latchMvfAig;
+  bAigEdge_t * latchBAig,* initBAig;
+  array_t * tmpclause, *clauseArray, * clause, * clause1,*latchClause;
+  mAig_Manager_t    *manager = Ntk_NetworkReadMAigManager(network);
+  char * Name;
+  boolean nextLatch = FALSE;
+
+  latchClause = array_alloc(int,0);
+  arrayForEachItem(char *,vertexArray,j,Name)
+    {
+      nextLatch = FALSE;
+      clause = array_alloc(int,0); /*(-A + -A1 + -A2 + -A3)*/
+      clauseArray  = array_alloc(array_t *,0);/*(A + -A1)(A + -A2)(A + -A3)*/
+      latch = Ntk_NetworkFindNodeByName(network,Name);
+      latchInit  = Ntk_LatchReadInitialInput(latch);
+      latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+      if (latchMvfAig ==  NIL(MvfAig_Function_t)){
+	latchMvfAig = Bmc_NodeBuildMVF(network, latch);
+	array_free(latchMvfAig);
+	latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+      }
+      initMvfAig = Bmc_ReadMvfAig(latchInit, nodeToMvfAigTable);
+
+       
+      mvfSize   = array_n(latchMvfAig);
+      latchBAig = ALLOC(bAigEdge_t, mvfSize); 
+      initBAig  = ALLOC(bAigEdge_t, mvfSize);
+      /* printf("mvfSize = %d \n",mvfSize);*/
+
+      for(i=0; i< mvfSize; i++){
+	latchBAig[i] = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(latchMvfAig, i));
+	initBAig[i]  = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(initMvfAig,  i));
+	}
+      
+      for(i=0; i< mvfSize; i++){
+	if ((initBAig[i] == bAig_One) && (latchBAig[i] == bAig_One))
+	 {
+	   nextLatch=TRUE;
+	   break;   /* the clause is always true */
+	 }
+      }
+
+      
+      if(!nextLatch)
+	{
+	  for(i=0; i< mvfSize; i++){
+	    initBAig[i]  = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(initMvfAig,  i));
+	    latchBAig[i] = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(latchMvfAig, i));
+	    if(initBAig[i]==bAig_Zero ||latchBAig[i]==bAig_Zero)
+	      {
+		continue;
+	      }
+	    if(initBAig[i]!=bAig_One)
+	      {
+		index1 = BmcGenerateCnfFormulaForAigFunction(manager,initBAig[i],step1,cnfClauses);
+	      }
+	    if(latchBAig[i]!=bAig_One)
+	      {
+		index2 = BmcGenerateCnfFormulaForAigFunction(manager,latchBAig[i],step2,cnfClauses);
+	      }
+	    
+	    cnfIndex = cnfClauses->cnfGlobalIndex++;
+	    if (initBAig[i] == bAig_One){
+	      tmpclause  = array_alloc(int, 2);
+	      array_insert(int, tmpclause, 0, -index2);
+	      array_insert(int, tmpclause, 1, cnfIndex);
+	      BmcCnfInsertClause(cnfClauses, tmpclause);
+	      array_free(tmpclause); 
+	      
+	      tmpclause  = array_alloc(int, 2);
+	      array_insert(int, tmpclause, 0, index2);
+	      array_insert(int, tmpclause, 1, -cnfIndex);
+	      BmcCnfInsertClause(cnfClauses, tmpclause);
+	      array_free(tmpclause);       
+	      
+	    } else if (latchBAig[i] == bAig_One){
+	      tmpclause  = array_alloc(int, 2);
+	      array_insert(int, tmpclause, 0, -index1);
+	      array_insert(int, tmpclause, 1, cnfIndex);
+	      BmcCnfInsertClause(cnfClauses, tmpclause);
+	      array_free(tmpclause);
+	      
+ 	      tmpclause  = array_alloc(int, 2);
+	      array_insert(int, tmpclause, 0, index1);
+	      array_insert(int, tmpclause, 1, -cnfIndex);
+	      BmcCnfInsertClause(cnfClauses, tmpclause);
+	      array_free(tmpclause);
+	      
+	    } else {
+	    tmpclause  = array_alloc(int, 3);
+	    array_insert(int, tmpclause, 0, -index2);
+	    array_insert(int, tmpclause, 1, -index1);
+	    array_insert(int, tmpclause, 2,  cnfIndex);
+	    BmcCnfInsertClause(cnfClauses, tmpclause);
+	    array_free(tmpclause);
+	    
+	    tmpclause  = array_alloc(int, 2);
+	    array_insert(int, tmpclause, 0, index2);
+	    array_insert(int, tmpclause, 1, -cnfIndex);
+	    BmcCnfInsertClause(cnfClauses, tmpclause);
+	    array_free(tmpclause);
+	    
+	    tmpclause  = array_alloc(int, 2);
+	    array_insert(int, tmpclause, 0, index1);
+	    array_insert(int, tmpclause, 1, -cnfIndex);
+	    BmcCnfInsertClause(cnfClauses, tmpclause);
+	    array_free(tmpclause);
+	    }
+	    /*(-A + A1 + A2 + A3)*/
+	    array_insert_last(int,clause,cnfIndex);
+	    /*(A + -A1)(A + -A2)(A + -A3)*/
+	    clause1 = array_alloc(int,0);/*(A + -A1/2/3)*/
+	    array_insert_last(int,clause1,-cnfIndex);
+	    array_insert_last(array_t *,clauseArray,clause1);
+	    
+	  }/* for(i=0; i< mvfSize;*/
+	 
+	  cnfIndex = cnfClauses->cnfGlobalIndex++; /*A*/
+	  /*(A + -A1)(A + -A2)(A + -A3)*/
+	  arrayForEachItem(array_t *,clauseArray,k,clause1)
+	    {
+	      array_insert_last(int,clause1,cnfIndex);
+	      BmcCnfInsertClause(cnfClauses,clause1);
+	      array_free(clause1);
+	    }
+	  array_free(clauseArray);
+	  
+	  /*(-A + A1 + A2 + A3)*/
+	  array_insert_last(int,clause,-cnfIndex);
+	  BmcCnfInsertClause(cnfClauses,clause);
+	  array_free(clause);
+	  
+	  /*(C + -A + -B)*/
+	  array_insert_last(int,latchClause,-cnfIndex);
+	}/* if(!nextLatch)*/
+      FREE(latchBAig); 
+      FREE(initBAig);
+    }/*arrayForEach..*/
+  cnfIndex = cnfClauses->cnfGlobalIndex++; /* C*/
+  array_insert_last(int,latchClause,cnfIndex); /*(C + -A + -B)*/
+  BmcCnfInsertClause(cnfClauses,latchClause);
+  array_free(latchClause);
+  
+  /*(-C)*/
+  latchClause = array_alloc(int,0);
+  array_insert_last(int,latchClause,-cnfIndex);
+  BmcCnfInsertClause(cnfClauses,latchClause);
+  array_free(latchClause);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Insert clauses of initial states for k-induction checking]
+
+  Description [Insert clauses of initial states for k-induction checking]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void PureSatSetInitStatesForSimplePath(array_t * vertexArray,
+			  Ntk_Network_t *network,
+			  BmcCnfClauses_t *cnfClauses,
+			  st_table * nodeToMvfAigTable)
+{
+  mAig_Manager_t  *maigManager   = Ntk_NetworkReadMAigManager(network);
+  Ntk_Node_t         *latch, *latchInit;
+  MvfAig_Function_t  *initMvfAig, *latchMvfAig;
+  bAigEdge_t         *initBAig, *latchBAig;
+  int                i,j, mvfSize;
+  char               *nodeName;
+  
+  for(j=0;j<array_n(vertexArray);j++)
+    {
+      nodeName = array_fetch(char *,vertexArray,j);
+      latch = Ntk_NetworkFindNodeByName(network,nodeName);
+      latchInit  = Ntk_LatchReadInitialInput(latch);
+      initMvfAig = Bmc_ReadMvfAig(latchInit, nodeToMvfAigTable);
+      latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+      if (latchMvfAig ==  NIL(MvfAig_Function_t)){
+	latchMvfAig = Bmc_NodeBuildMVF(network, latch);
+	array_free(latchMvfAig);
+	latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+      }
+      
+      mvfSize   = array_n(initMvfAig);
+      initBAig  = ALLOC(bAigEdge_t, mvfSize);
+      latchBAig = ALLOC(bAigEdge_t, mvfSize);   
+      
+      for(i=0; i< mvfSize; i++){
+	latchBAig[i] = bAig_GetCanonical(maigManager,MvfAig_FunctionReadComponent(latchMvfAig, i));
+	initBAig[i]  = bAig_GetCanonical(maigManager,MvfAig_FunctionReadComponent(initMvfAig,  i));
+      }
+      BmcGenerateClausesFromStateTostate(maigManager, initBAig, latchBAig, mvfSize, -1, 0, cnfClauses, 0);
+      FREE(initBAig);
+      FREE(latchBAig);
+    } 
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [k-induction checking from SSS'00 FMCAD paper ]
+
+  Description [k-induction checking from SSS'00 FMCAD paper ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean PureSatExistASimplePath(Ntk_Network_t *network,
+			      PureSat_IncreSATManager_t * pism,
+			      array_t * vertexArray,
+			      bAigEdge_t property,
+			      PureSat_Manager_t * pm)
+{
+  mAig_Manager_t  *maigManager   = Ntk_NetworkReadMAigManager(network);
+  Ntk_Node_t         *latch, *latchData, *latchInit;
+  MvfAig_Function_t  *initMvfAig, *dataMvfAig, *latchMvfAig;
+  bAigEdge_t         *initBAig, *latchBAig, *dataBAig;
+  int                i,j, k, mvfSize,propertyIndex;
+  char               *nodeName;
+  array_t            * Pclause = array_alloc(int,0);
+  st_table           *nodeToMvfAigTable;
+  BmcCnfStates_t     *cnfstate1,*cnfstate2;
+  array_t            *supportLatches;
+  int                 status;
+  int beginPosition = pism->beginPosition;
+  int Length = pism->Length;
+  int oldLength = pism->oldLength;
+  BmcCnfClauses_t * cnfClauses = pism->cnfClauses;
+  satManager_t * cm = pism->cm;
+  
+  /* construct loopfree path;*/
+  nodeToMvfAigTable =(st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+  if (nodeToMvfAigTable == NIL(st_table)){
+    (void) fprintf(vis_stderr,"** bmc error: please run buid_partiton_maigs first");
+    exit(0);
+  }
+
+  for(j=beginPosition;j<array_n(vertexArray);j++){
+    nodeName = array_fetch(char *,vertexArray,j);
+    latch = Ntk_NetworkFindNodeByName(network,nodeName);
+    latchInit  = Ntk_LatchReadInitialInput(latch);
+    latchData  = Ntk_LatchReadDataInput(latch);
+    initMvfAig = Bmc_ReadMvfAig(latchInit, nodeToMvfAigTable);
+    dataMvfAig = Bmc_ReadMvfAig(latchData, nodeToMvfAigTable);
+    latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+   if (latchMvfAig ==  NIL(MvfAig_Function_t)){
+     latchMvfAig = Bmc_NodeBuildMVF(network, latch);
+     array_free(latchMvfAig);
+     latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+   }
+    
+    mvfSize   = array_n(initMvfAig);
+    initBAig  = ALLOC(bAigEdge_t, mvfSize);
+    dataBAig  = ALLOC(bAigEdge_t, mvfSize);
+    latchBAig = ALLOC(bAigEdge_t, mvfSize);
+    
+    for(i=0; i< mvfSize; i++){
+      dataBAig[i]  = bAig_GetCanonical(maigManager,MvfAig_FunctionReadComponent(dataMvfAig,  i));
+      latchBAig[i] = bAig_GetCanonical(maigManager,MvfAig_FunctionReadComponent(latchMvfAig, i));
+      initBAig[i]  = bAig_GetCanonical(maigManager,MvfAig_FunctionReadComponent(initMvfAig,  i));
+    }
+    
+    /* BmcGenerateClausesFromStateTostate(maigManager, initBAig, latchBAig, mvfSize, -1, 0, cnfClauses, 0);*/
+    for (k=0; k < oldLength; k++){
+      BmcGenerateClausesFromStateTostate(maigManager, dataBAig,latchBAig, mvfSize, k, k+1, cnfClauses, 0);
+    }
+    FREE(initBAig);
+    FREE(dataBAig);
+    FREE(latchBAig);
+  } /*st_foreach_item(vertexTable,*/
+
+  if(oldLength<Length){
+    for(j=0;j<array_n(vertexArray);j++){
+      nodeName = array_fetch(char *,vertexArray,j);
+      latch = Ntk_NetworkFindNodeByName(network,nodeName);
+      latchInit  = Ntk_LatchReadInitialInput(latch);
+      latchData  = Ntk_LatchReadDataInput(latch);
+      initMvfAig = Bmc_ReadMvfAig(latchInit, nodeToMvfAigTable);
+      dataMvfAig = Bmc_ReadMvfAig(latchData, nodeToMvfAigTable);
+      latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+    
+      mvfSize   = array_n(initMvfAig);
+      initBAig  = ALLOC(bAigEdge_t, mvfSize);
+      dataBAig  = ALLOC(bAigEdge_t, mvfSize);
+      latchBAig = ALLOC(bAigEdge_t, mvfSize);   
+      
+      for(i=0; i< mvfSize; i++){
+	dataBAig[i]  = bAig_GetCanonical(maigManager,MvfAig_FunctionReadComponent(dataMvfAig,  i));
+	latchBAig[i] = bAig_GetCanonical(maigManager,MvfAig_FunctionReadComponent(latchMvfAig, i));
+	initBAig[i]  = bAig_GetCanonical(maigManager,MvfAig_FunctionReadComponent(initMvfAig,  i));
+      }
+      
+      for (k=oldLength; k <Length; k++){
+	BmcGenerateClausesFromStateTostate(maigManager, dataBAig, latchBAig, mvfSize, k, k+1, cnfClauses, 0);
+      }
+      FREE(initBAig);
+      FREE(dataBAig);
+      FREE(latchBAig);
+    }
+  }/*if(oldLength!=0){*/
+
+  if(pm->verbosity>=1)
+    fprintf(vis_stdout,"forward simple path testing...\n");
+  cnfstate1 = BmcCnfClausesFreeze(cnfClauses);
+  
+  /*generate NODE(i)!=NODE(i+1)*/
+  for(i=1;i<Length;i++)
+    for(j=i+1;j<=Length;j++)
+      PureSatInsertNewClauseForSimplePath(vertexArray,network,i,j,cnfClauses,nodeToMvfAigTable); /*Si!=Sj*/
+  
+  cnfstate2 = BmcCnfClausesFreeze(cnfClauses);
+  supportLatches = PureSatGetImmediateSupportLatches(network, 0, vertexArray);
+  /*I(S0)*/
+  PureSatSetInitStatesForSimplePath(supportLatches/*vertexArray*/,network,cnfClauses,nodeToMvfAigTable);
+  /*generate all.!I(S(1...i)), the first constraint*/
+  for(i=1;i<=Length;i++)
+    PureSatInsertNewClauseForInit(supportLatches/*vertexArray*/,network,-1,i,cnfClauses,nodeToMvfAigTable);
+  array_free(supportLatches);
+
+  pism->propertyPos = cnfstate1->nextIndex;
+  PureSatReadClauses(pism,pm);
+  /*no incremental */
+  if(!pm->incre){
+    if(cm->savedConflictClauses)
+      sat_ArrayFree(cm->savedConflictClauses);
+    cm->savedConflictClauses = 0;
+  }
+  sat_Main(cm);
+  status = cm->status;
+  PureSatCleanSat(cm);
+  BmcCnfClausesRestore(cnfClauses, cnfstate1);
+
+  if(status == SAT_SAT)
+    {
+      if(pm->verbosity>=1)
+	fprintf(vis_stdout,"backward simple path testing...\n");
+      cnfstate2 = BmcCnfClausesFreeze(cnfClauses);
+      /*generate NODE(i)!=NODE(i+1)*/
+      for(i=1;i<Length;i++)
+	for(j=i+1;j<=Length;j++)
+	  PureSatInsertNewClauseForSimplePath(vertexArray,network,i,j,cnfClauses,nodeToMvfAigTable);
+      /*!P(S(i))*/
+      propertyIndex =  BmcGenerateCnfFormulaForAigFunction(maigManager,property, Length, cnfClauses);
+      array_insert_last(int, Pclause,propertyIndex);
+      BmcCnfInsertClause(cnfClauses, Pclause);
+      array_free(Pclause);
+      /*all.P(S(0,...i-1))*/
+      property = bAig_Not(property);
+      for(k=0; k <= Length-1; k++){
+	propertyIndex =  BmcGenerateCnfFormulaForAigFunction(maigManager,property,k, cnfClauses);
+	Pclause = array_alloc(int,0);
+	array_insert_last(int, Pclause, propertyIndex);
+	BmcCnfInsertClause(cnfClauses, Pclause);
+	array_free(Pclause);
+      }
+
+      pism->propertyPos = cnfstate2->nextIndex;
+      PureSatReadClauses(pism,pm);
+      /*no incremental */
+      if(!pm->incre){
+	if(cm->savedConflictClauses)
+	  sat_ArrayFree(cm->savedConflictClauses);
+	cm->savedConflictClauses = 0;
+      }
+      sat_Main(cm);
+      status = cm->status;
+      PureSatCleanSat(cm);
+      if(status == SAT_SAT)
+	{
+	  BmcCnfClausesRestore(cnfClauses, cnfstate1);
+	  FREE(cnfstate1);
+	  FREE(cnfstate2);
+	  return TRUE;
+	}
+    }
+  FREE(cnfstate1);
+  FREE(cnfstate2);
+  return  FALSE;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [checking the existence of a path of certain length]
+
+  Description [checking the existence of a path of certain length ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+boolean PureSatExistCE(Ntk_Network_t * network,
+		       PureSat_IncreSATManager_t * pism,
+		       BmcOption_t *options,
+		       array_t *vertexArray,
+		       bAigEdge_t property,
+		       PureSat_Manager_t * pm,
+		       int extractCexInfo)
+{
+  mAig_Manager_t  *manager   = Ntk_NetworkReadMAigManager(network);
+  Ntk_Node_t         *latch, *latchData, *latchInit;
+  MvfAig_Function_t  *initMvfAig, *dataMvfAig, *latchMvfAig;
+  bAigEdge_t         *initBAig, *latchBAig, *dataBAig;
+  int                i,j, k, mvfSize;
+  char               *nodeName;
+  array_t            *result;
+  array_t            *Pclause = array_alloc(int, 0);
+  FILE               *cnfFile;
+  st_table           *nodeToMvfAigTable;
+  BmcCnfStates_t    *cnfstate;
+  int beginPosition = pism->beginPosition;
+  int oldLength = pism->oldLength;
+  int Length = pism->Length;
+  BmcCnfClauses_t *cnfClauses = pism->cnfClauses;
+
+  double t2, t1 = util_cpu_ctime();
+
+  options->verbosityLevel = (Bmc_VerbosityLevel) pm->verbosity;
+  nodeToMvfAigTable =(st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+  if (nodeToMvfAigTable == NIL(st_table)){
+    (void) fprintf(vis_stderr,"** bmc error: please run buid_partiton_maigs first");
+    exit(0);
+  }
+
+
+#if 1
+ { 
+   array_t *supportLatches = PureSatGetImmediateSupportLatches(network, beginPosition, vertexArray);
+   arrayForEachItem(char *, supportLatches, j, nodeName) {
+     latch = Ntk_NetworkFindNodeByName(network, nodeName);
+    latchInit  = Ntk_LatchReadInitialInput(latch);
+    latchData  = Ntk_LatchReadDataInput(latch);
+    initMvfAig = Bmc_ReadMvfAig(latchInit, nodeToMvfAigTable);
+    dataMvfAig = Bmc_ReadMvfAig(latchData, nodeToMvfAigTable);
+    latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+    if (latchMvfAig ==  NIL(MvfAig_Function_t)){
+      latchMvfAig = Bmc_NodeBuildMVF(network, latch);
+      array_free(latchMvfAig);
+      latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+    }
+    
+    mvfSize   = array_n(initMvfAig);
+    initBAig  = ALLOC(bAigEdge_t, mvfSize);
+    dataBAig  = ALLOC(bAigEdge_t, mvfSize);
+    latchBAig = ALLOC(bAigEdge_t, mvfSize);   
+    
+    for(i=0; i< mvfSize; i++){
+      dataBAig[i]  = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(dataMvfAig,  i));
+      latchBAig[i] = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(latchMvfAig, i));
+      initBAig[i]  = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(initMvfAig,  i));
+    }
+    
+    BmcGenerateClausesFromStateTostate(manager, initBAig, latchBAig, mvfSize, -1, 0, cnfClauses, 0);
+    FREE(initBAig);
+    FREE(dataBAig);
+    FREE(latchBAig);
+  }    
+   array_free(supportLatches);
+ }
+
+  
+  for(j=beginPosition;j<array_n(vertexArray);j++){
+    nodeName = array_fetch(char *,vertexArray,j);
+    latch = Ntk_NetworkFindNodeByName(network,nodeName);
+    latchInit  = Ntk_LatchReadInitialInput(latch);
+    latchData  = Ntk_LatchReadDataInput(latch);
+    initMvfAig = Bmc_ReadMvfAig(latchInit, nodeToMvfAigTable);
+    dataMvfAig = Bmc_ReadMvfAig(latchData, nodeToMvfAigTable);
+    latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+   if (latchMvfAig ==  NIL(MvfAig_Function_t)){
+     latchMvfAig = Bmc_NodeBuildMVF(network, latch);
+     array_free(latchMvfAig);
+     latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+   }
+    
+    mvfSize   = array_n(initMvfAig);
+    initBAig  = ALLOC(bAigEdge_t, mvfSize);
+    dataBAig  = ALLOC(bAigEdge_t, mvfSize);
+    latchBAig = ALLOC(bAigEdge_t, mvfSize);   
+    
+    for(i=0; i< mvfSize; i++){
+      dataBAig[i]  = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(dataMvfAig,  i));
+      latchBAig[i] = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(latchMvfAig, i));
+      initBAig[i]  = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(initMvfAig,  i));
+    }
+    /* BmcGenerateClausesFromStateTostate(manager, initBAig, latchBAig, mvfSize, -1, 0, cnfClauses, 0);*/
+    for (k=0; k <oldLength; k++){
+      BmcGenerateClausesFromStateTostate(manager, dataBAig, latchBAig, mvfSize, k, k+1, cnfClauses, 0);
+    }
+    FREE(initBAig);
+    FREE(dataBAig);
+    FREE(latchBAig);
+  } /*st_foreach_item(vertexTable,*/
+#else
+  /*build TR for more latches*/
+  
+  for(j=beginPosition;j<array_n(vertexArray);j++){
+    nodeName = array_fetch(char *,vertexArray,j);
+    latch = Ntk_NetworkFindNodeByName(network,nodeName);
+    latchInit  = Ntk_LatchReadInitialInput(latch);
+    latchData  = Ntk_LatchReadDataInput(latch);
+    initMvfAig = Bmc_ReadMvfAig(latchInit, nodeToMvfAigTable);
+    dataMvfAig = Bmc_ReadMvfAig(latchData, nodeToMvfAigTable);
+    latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+   if (latchMvfAig ==  NIL(MvfAig_Function_t)){
+     latchMvfAig = Bmc_NodeBuildMVF(network, latch);
+     array_free(latchMvfAig);
+     latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+   }
+    
+    mvfSize   = array_n(initMvfAig);
+    initBAig  = ALLOC(bAigEdge_t, mvfSize);
+    dataBAig  = ALLOC(bAigEdge_t, mvfSize);
+    latchBAig = ALLOC(bAigEdge_t, mvfSize);   
+    
+    for(i=0; i< mvfSize; i++){
+      dataBAig[i]  = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(dataMvfAig,  i));
+      latchBAig[i] = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(latchMvfAig, i));
+      initBAig[i]  = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(initMvfAig,  i));
+    }
+    BmcGenerateClausesFromStateTostate(manager, initBAig, latchBAig, mvfSize, -1, 0, cnfClauses, 0);
+    for (k=0; k <oldLength; k++){
+      BmcGenerateClausesFromStateTostate(manager, dataBAig, latchBAig, mvfSize, k, k+1, cnfClauses, 0);
+    }
+    FREE(initBAig);
+    FREE(dataBAig);
+    FREE(latchBAig);
+  } /*st_foreach_item(vertexTable,*/
+#endif
+
+  /* for more length*/
+  if(oldLength<Length){
+    for(j=0;j<array_n(vertexArray);j++){
+      nodeName = array_fetch(char *,vertexArray,j);
+      latch = Ntk_NetworkFindNodeByName(network,nodeName);
+      latchInit  = Ntk_LatchReadInitialInput(latch);
+      latchData  = Ntk_LatchReadDataInput(latch);
+      initMvfAig = Bmc_ReadMvfAig(latchInit, nodeToMvfAigTable);
+      dataMvfAig = Bmc_ReadMvfAig(latchData, nodeToMvfAigTable);
+      latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+      if (latchMvfAig ==  NIL(MvfAig_Function_t)){
+	latchMvfAig = Bmc_NodeBuildMVF(network, latch);
+	array_free(latchMvfAig);
+	latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+      }
+    
+      mvfSize   = array_n(initMvfAig);
+      initBAig  = ALLOC(bAigEdge_t, mvfSize);
+      dataBAig  = ALLOC(bAigEdge_t, mvfSize);
+      latchBAig = ALLOC(bAigEdge_t, mvfSize);   
+      
+      for(i=0; i< mvfSize; i++){
+	dataBAig[i]  = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(dataMvfAig,  i));
+	latchBAig[i] = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(latchMvfAig, i));
+	initBAig[i]  = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(initMvfAig,  i));
+      }
+      
+      for (k=oldLength; k<Length; k++){
+	BmcGenerateClausesFromStateTostate(manager, dataBAig, latchBAig, mvfSize, k, k+1, cnfClauses, 0);
+      }
+      FREE(initBAig);
+      FREE(dataBAig);
+      FREE(latchBAig);
+    }
+  }
+  
+
+   k=Length;
+   cnfstate = BmcCnfClausesFreeze(cnfClauses);
+   /* for(k=0; k <= Length; k++){*/
+   array_insert_last(int, Pclause, BmcGenerateCnfFormulaForAigFunction(manager, property,k, cnfClauses));
+   /*    } */
+   BmcCnfInsertClause(cnfClauses, Pclause);
+   array_free(Pclause);
+   cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0); 
+   BmcWriteClauses(manager, cnfFile, cnfClauses, options);
+   (void) fclose(cnfFile);
+   result = BmcCheckSAT(options);
+   BmcCnfClausesRestore(cnfClauses, cnfstate);
+   FREE(cnfstate);
+   
+  t2 = util_cpu_ctime();
+  /*timeElapse_Sol += t2-t1;*/
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout, "timeElapse_sol_noIncre: += %g\n", (double)((t2-t1)/1000.0));
+
+  
+  if(extractCexInfo && pm->dbgLevel>=1 && result!=NIL(array_t)){
+    pm->result = array_dup(result);
+  }
+  
+  if(result!=NIL(array_t))
+    {
+      if(pm->verbosity>=2)
+	fprintf(vis_stdout, "find CEX\n");
+      array_free(result);
+      return TRUE;
+    }
+  else
+    {
+      if(pm->verbosity>=2)
+	fprintf(vis_stdout, "didn't find CEX\n");
+       return FALSE;
+    }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Incrementally checking the existence of a path of certain length]
+
+  Description [Incrementally checking the existence of a path of certain length ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+boolean PureSatIncreExistCE(Ntk_Network_t * network,
+		     PureSat_IncreSATManager_t *pism,
+		     array_t *vertexArray,
+		     bAigEdge_t property,
+		     PureSat_Manager_t * pm)
+{
+  mAig_Manager_t  *manager   = Ntk_NetworkReadMAigManager(network);
+  Ntk_Node_t         *latch, *latchData, *latchInit;
+  MvfAig_Function_t  *initMvfAig, *dataMvfAig, *latchMvfAig;
+  bAigEdge_t         *initBAig, *latchBAig, *dataBAig;
+  int                i,j, k, mvfSize;
+  int                status;
+  char               *nodeName;
+  array_t            *Pclause = array_alloc(int, 0);
+  st_table           *nodeToMvfAigTable;
+  BmcCnfStates_t    *cnfstate;
+  int beginPosition = pism->beginPosition;
+  int Length = pism->Length;
+  int oldLength = pism->oldLength;
+  BmcCnfClauses_t * cnfClauses = pism->cnfClauses;
+  satManager_t * cm = pism->cm;
+
+  nodeToMvfAigTable =(st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+  if (nodeToMvfAigTable == NIL(st_table)){
+    (void) fprintf(vis_stderr,"** bmc error: please run buid_partiton_maigs first");
+    exit(0);
+  }
+
+ { 
+   array_t *supportLatches = PureSatGetImmediateSupportLatches(network, beginPosition, vertexArray);
+   arrayForEachItem(char *, supportLatches, j, nodeName) {
+     latch = Ntk_NetworkFindNodeByName(network, nodeName);
+    latchInit  = Ntk_LatchReadInitialInput(latch);
+    latchData  = Ntk_LatchReadDataInput(latch);
+    initMvfAig = Bmc_ReadMvfAig(latchInit, nodeToMvfAigTable);
+    dataMvfAig = Bmc_ReadMvfAig(latchData, nodeToMvfAigTable);
+    latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+    if (latchMvfAig ==  NIL(MvfAig_Function_t)){
+      latchMvfAig = Bmc_NodeBuildMVF(network, latch);
+      array_free(latchMvfAig);
+      latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+    }
+    
+    mvfSize   = array_n(initMvfAig);
+    initBAig  = ALLOC(bAigEdge_t, mvfSize);
+    dataBAig  = ALLOC(bAigEdge_t, mvfSize);
+    latchBAig = ALLOC(bAigEdge_t, mvfSize);   
+    
+    for(i=0; i< mvfSize; i++){
+      dataBAig[i]  = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(dataMvfAig,  i));
+      latchBAig[i] = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(latchMvfAig, i));
+      initBAig[i]  = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(initMvfAig,  i));
+    }
+    
+    BmcGenerateClausesFromStateTostate(manager, initBAig, latchBAig, mvfSize, -1, 0, cnfClauses, 0);
+    FREE(initBAig);
+    FREE(dataBAig);
+    FREE(latchBAig);
+  }  
+   array_free(supportLatches);
+ }
+  
+  for(j=beginPosition;j<array_n(vertexArray);j++){
+    nodeName = array_fetch(char *,vertexArray,j);
+    latch = Ntk_NetworkFindNodeByName(network,nodeName);
+    latchInit  = Ntk_LatchReadInitialInput(latch);
+    latchData  = Ntk_LatchReadDataInput(latch);
+    initMvfAig = Bmc_ReadMvfAig(latchInit, nodeToMvfAigTable);
+    dataMvfAig = Bmc_ReadMvfAig(latchData, nodeToMvfAigTable);
+    latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+   if (latchMvfAig ==  NIL(MvfAig_Function_t)){
+     latchMvfAig = Bmc_NodeBuildMVF(network, latch);
+     array_free(latchMvfAig);
+     latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+   }
+    
+    mvfSize   = array_n(initMvfAig);
+    initBAig  = ALLOC(bAigEdge_t, mvfSize);
+    dataBAig  = ALLOC(bAigEdge_t, mvfSize);
+    latchBAig = ALLOC(bAigEdge_t, mvfSize);   
+    
+    for(i=0; i< mvfSize; i++){
+      dataBAig[i]  = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(dataMvfAig,  i));
+      latchBAig[i] = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(latchMvfAig, i));
+      initBAig[i]  = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(initMvfAig,  i));
+    }
+    BmcGenerateClausesFromStateTostate(manager, initBAig, latchBAig, mvfSize, -1, 0, cnfClauses, 0);
+    for (k=0; k <oldLength; k++){
+      BmcGenerateClausesFromStateTostate(manager, dataBAig, latchBAig, mvfSize, k, k+1, cnfClauses, 0);
+    }
+    FREE(initBAig);
+    FREE(dataBAig);
+    FREE(latchBAig);
+  }
+
+  /* for more length*/
+  if(oldLength<Length){
+    for(j=0;j<array_n(vertexArray);j++){
+      nodeName = array_fetch(char *,vertexArray,j);
+      latch = Ntk_NetworkFindNodeByName(network,nodeName);
+      latchInit  = Ntk_LatchReadInitialInput(latch);
+      latchData  = Ntk_LatchReadDataInput(latch);
+      initMvfAig = Bmc_ReadMvfAig(latchInit, nodeToMvfAigTable);
+      dataMvfAig = Bmc_ReadMvfAig(latchData, nodeToMvfAigTable);
+      latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+      if (latchMvfAig ==  NIL(MvfAig_Function_t)){
+	latchMvfAig = Bmc_NodeBuildMVF(network, latch);
+	array_free(latchMvfAig);
+	latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+      }
+    
+      mvfSize   = array_n(initMvfAig);
+      initBAig  = ALLOC(bAigEdge_t, mvfSize);
+      dataBAig  = ALLOC(bAigEdge_t, mvfSize);
+      latchBAig = ALLOC(bAigEdge_t, mvfSize);   
+      
+      for(i=0; i< mvfSize; i++){
+	dataBAig[i]  = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(dataMvfAig,  i));
+	latchBAig[i] = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(latchMvfAig, i));
+	initBAig[i]  = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(initMvfAig,  i));
+      }
+      
+      for (k=oldLength; k<Length; k++){
+	BmcGenerateClausesFromStateTostate(manager, dataBAig, latchBAig, mvfSize, k, k+1, cnfClauses, 0);
+      }
+      FREE(initBAig);
+      FREE(dataBAig);
+      FREE(latchBAig);
+    }
+  }
+
+   k=Length;
+   cnfstate = BmcCnfClausesFreeze(cnfClauses);
+   /* for(k=0; k <= Length; k++){*/
+   array_insert_last(int, Pclause, BmcGenerateCnfFormulaForAigFunction(manager, property,k, cnfClauses));
+   /*    }*/
+   BmcCnfInsertClause(cnfClauses, Pclause);
+   array_free(Pclause);
+   pism->propertyPos = cnfstate->nextIndex;
+   PureSatReadClauses(pism, pm);
+   
+   /*no incremental */
+  if(!pm->incre){
+    if(cm->savedConflictClauses)
+      sat_ArrayFree(cm->savedConflictClauses);
+    cm->savedConflictClauses = 0;
+  }
+   cm->status = 0;
+   sat_Main(cm);
+   status = cm->status;
+   PureSatCleanSat(cm);
+   BmcCnfClausesRestore(cnfClauses, cnfstate);
+   FREE(cnfstate);
+   if(status == SAT_SAT)
+     {
+       if(pm->verbosity>=1)
+	 fprintf(vis_stdout, "find CEX\n");
+       return TRUE;
+     }
+   else
+     {
+       if(pm->verbosity>=1)
+	 fprintf(vis_stdout, "didn't find CEX\n");
+       return FALSE;
+     }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Incrementally checking the existence of a path of certain length
+  used by incremental concretization. For more information of incremental
+  concretization, please check the BMC'03 and STTT'05
+  paper of Li et al., "A satisfiability-based appraoch to abstraction
+  refinement in model checking", and " Abstraction in symbolic model checking
+  using satisfiability as the only decision procedure"]
+
+  Description [Incrementally checking the existence of a path of certain length
+  used by incremental concretization. For more information of incremental
+  concretization, please check the BMC'03 and STTT'05
+  paper of Li et al., "A satisfiability-based appraoch to abstraction
+  refinement in model checking", and " Abstraction in symbolic model checking
+  using satisfiability as the only decision procedure"]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+boolean PureSatIncreExistCEForRefineOnAbs(Ntk_Network_t *network,
+				   PureSat_IncreSATManager_t *pism,
+				   array_t *vertexArray,
+				   bAigEdge_t property,
+				   boolean firstTime,
+				   PureSat_Manager_t * pm)
+
+{
+  mAig_Manager_t  *manager   = Ntk_NetworkReadMAigManager(network);
+  Ntk_Node_t         *latch, *latchData, *latchInit;
+  MvfAig_Function_t  *initMvfAig, *dataMvfAig, *latchMvfAig;
+  bAigEdge_t         *initBAig, *latchBAig, *dataBAig;
+  int                i,j, k, mvfSize, status;
+  char               *nodeName;
+  array_t            *Pclause = array_alloc(int, 0);
+  st_table           *nodeToMvfAigTable;
+  int beginPosition = pism->beginPosition;
+  int Length = pism->Length;
+  int oldLength = pism->oldLength;
+  BmcCnfClauses_t * cnfClauses = pism->cnfClauses;
+  satManager_t * cm = pism->cm;
+
+  nodeToMvfAigTable =(st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+  if (nodeToMvfAigTable == NIL(st_table)){
+    (void) fprintf(vis_stderr,"** bmc error: please run buid_partiton_maigs first");
+    exit(0);
+  }
+  
+ { 
+   array_t *supportLatches = PureSatGetImmediateSupportLatches(network, beginPosition, vertexArray);
+   arrayForEachItem(char *, supportLatches, j, nodeName) {
+     latch = Ntk_NetworkFindNodeByName(network, nodeName);
+    latchInit  = Ntk_LatchReadInitialInput(latch);
+    latchData  = Ntk_LatchReadDataInput(latch);
+    initMvfAig = Bmc_ReadMvfAig(latchInit, nodeToMvfAigTable);
+    dataMvfAig = Bmc_ReadMvfAig(latchData, nodeToMvfAigTable);
+    latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+    if (latchMvfAig ==  NIL(MvfAig_Function_t)){
+      latchMvfAig = Bmc_NodeBuildMVF(network, latch);
+      array_free(latchMvfAig);
+      latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+    }
+    
+    mvfSize   = array_n(initMvfAig);
+    initBAig  = ALLOC(bAigEdge_t, mvfSize);
+    dataBAig  = ALLOC(bAigEdge_t, mvfSize);
+    latchBAig = ALLOC(bAigEdge_t, mvfSize);   
+    
+    for(i=0; i< mvfSize; i++){
+      dataBAig[i]  = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(dataMvfAig,  i));
+      latchBAig[i] = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(latchMvfAig, i));
+      initBAig[i]  = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(initMvfAig,  i));
+    }
+    
+    BmcGenerateClausesFromStateTostate(manager, initBAig, latchBAig, mvfSize, -1, 0, cnfClauses, 0);
+    FREE(initBAig);
+    FREE(dataBAig);
+    FREE(latchBAig);
+  }  
+   array_free(supportLatches);
+ }
+
+  
+  for(j=beginPosition;j<array_n(vertexArray);j++){
+    nodeName = array_fetch(char *,vertexArray,j);
+    latch = Ntk_NetworkFindNodeByName(network,nodeName);
+    latchInit  = Ntk_LatchReadInitialInput(latch);
+    latchData  = Ntk_LatchReadDataInput(latch);
+    initMvfAig = Bmc_ReadMvfAig(latchInit, nodeToMvfAigTable);
+    dataMvfAig = Bmc_ReadMvfAig(latchData, nodeToMvfAigTable);
+    latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+   if (latchMvfAig ==  NIL(MvfAig_Function_t)){
+     latchMvfAig = Bmc_NodeBuildMVF(network, latch);
+     array_free(latchMvfAig);
+     latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+   }
+    
+    mvfSize   = array_n(initMvfAig);
+    initBAig  = ALLOC(bAigEdge_t, mvfSize);
+    dataBAig  = ALLOC(bAigEdge_t, mvfSize);
+    latchBAig = ALLOC(bAigEdge_t, mvfSize);   
+    
+    for(i=0; i< mvfSize; i++){
+      dataBAig[i]  = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(dataMvfAig,  i));
+      latchBAig[i] = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(latchMvfAig, i));
+      initBAig[i]  = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(initMvfAig,  i));
+    }
+    
+    /*BmcGenerateClausesFromStateTostate(manager, initBAig, latchBAig, mvfSize, -1, 0, cnfClauses, 0);*/
+    for (k=0; k <oldLength; k++){
+      BmcGenerateClausesFromStateTostate(manager, dataBAig, latchBAig, mvfSize, k, k+1, cnfClauses, 0);
+    }
+    FREE(initBAig);
+    FREE(dataBAig);
+    FREE(latchBAig);
+  }
+
+  /*for more length */
+  if(oldLength<Length){
+    for(j=0;j<array_n(vertexArray);j++){
+      nodeName = array_fetch(char *,vertexArray,j);
+      latch = Ntk_NetworkFindNodeByName(network,nodeName);
+      latchInit  = Ntk_LatchReadInitialInput(latch);
+      latchData  = Ntk_LatchReadDataInput(latch);
+      initMvfAig = Bmc_ReadMvfAig(latchInit, nodeToMvfAigTable);
+      dataMvfAig = Bmc_ReadMvfAig(latchData, nodeToMvfAigTable);
+      latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+      if (latchMvfAig ==  NIL(MvfAig_Function_t)){
+	latchMvfAig = Bmc_NodeBuildMVF(network, latch);
+	array_free(latchMvfAig);
+	latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+      }
+    
+      mvfSize   = array_n(initMvfAig);
+      initBAig  = ALLOC(bAigEdge_t, mvfSize);
+      dataBAig  = ALLOC(bAigEdge_t, mvfSize);
+      latchBAig = ALLOC(bAigEdge_t, mvfSize);   
+      
+      for(i=0; i< mvfSize; i++){
+	dataBAig[i]  = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(dataMvfAig,  i));
+	latchBAig[i] = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(latchMvfAig, i));
+	initBAig[i]  = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(initMvfAig,  i));
+      }
+      
+      for (k=oldLength; k<Length; k++){
+	BmcGenerateClausesFromStateTostate(manager, dataBAig, latchBAig, mvfSize, k, k+1, cnfClauses, 0);
+      }
+      FREE(initBAig);
+      FREE(dataBAig);
+      FREE(latchBAig);
+    }
+  }
+  
+ 
+  /*cnfstate = BmcCnfClausesFreeze(cnfClauses);*/
+  if(firstTime){
+    /* pism->propertyPos = cnfstate->nextIndex;*/
+    array_insert_last(int, Pclause, BmcGenerateCnfFormulaForAigFunction(manager,
+								 property,Length, cnfClauses));
+    BmcCnfInsertClause(cnfClauses, Pclause);
+    array_free(Pclause);
+  }
+  PureSatReadClauses(pism,pm);
+  sat_Main(cm);
+  if(pm->dbgLevel>=1 && cm->status==SAT_SAT){
+    pm->result = array_alloc(int, 0);
+    {
+      int size, value;
+      size = cm->initNumVariables * satNodeSize;
+      for(i=satNodeSize; i<=size; i+=satNodeSize) {
+	value = SATvalue(i);
+	if(value == 1) {
+	  array_insert_last(int, pm->result, SATnodeID(i));
+	}
+	else if(value == 0) {
+	  array_insert_last(int, pm->result, -(SATnodeID(i)));
+	}
+      }
+    }
+  }
+  status = cm->status;
+  PureSatCleanSat(cm);
+  /*FREE(cnfstate);*/
+  if(status == SAT_SAT)
+    {
+      if(pm->verbosity>=1)
+	fprintf(vis_stdout, "find CEX\n");
+      return TRUE;
+    }
+  else
+    {
+      if(pm->verbosity>=1)
+	fprintf(vis_stdout, "didn't find CEX\n");
+      return FALSE;
+    }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Building the path together with ClsidxToLatchTable for later use
+  by refinement extraction]
+
+  Description [Building the path together with ClsidxToLatchTable for later use
+  by refinement extraction]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void
+PureSatGenerateClausesFromStateTostateWithTable(
+   bAig_Manager_t  *manager,
+   bAigEdge_t      *fromAigArray,
+   bAigEdge_t      *toAigArray,
+   int             mvfSize, 
+   int             fromState,
+   int             toState,
+   BmcCnfClauses_t *cnfClauses,
+   int             outIndex,
+   st_table        *ClsidxToLatchTable,
+   char            *nodeName) 
+{
+  array_t    *clause, *tmpclause;
+  int        toIndex, fromIndex, cnfIndex;
+  int        i;
+  
+  toIndex =0;
+  fromIndex = 0;
+  
+  for(i=0; i< mvfSize; i++){
+    if ((fromAigArray[i] == bAig_One) && (toAigArray[i] == bAig_One)){
+      return;   /* the clause is always true */
+    }
+  }
+  clause  = array_alloc(int, 0);
+  for(i=0; i< mvfSize; i++){
+    if ((fromAigArray[i] != bAig_Zero) && (toAigArray[i] != bAig_Zero)){
+      if (toAigArray[i] != bAig_One){ 
+         toIndex = BmcGenerateCnfFormulaForAigFunction(manager,toAigArray[i],
+						       toState,cnfClauses);
+      }
+      if (fromAigArray[i] != bAig_One){ 
+         fromIndex = BmcGenerateCnfFormulaForAigFunction(manager,fromAigArray[i],
+							 fromState,cnfClauses);
+      }
+     cnfIndex = cnfClauses->cnfGlobalIndex++;  /* index of the output of the OR of T(from, to) */
+     if (toAigArray[i] == bAig_One){    
+       tmpclause  = array_alloc(int, 2);
+       array_insert(int, tmpclause, 0, -fromIndex);
+       array_insert(int, tmpclause, 1, cnfIndex);
+       BmcCnfInsertClause(cnfClauses, tmpclause);
+       st_insert(ClsidxToLatchTable,(char *)(long)(cnfClauses->noOfClauses-1),nodeName);
+       array_free(tmpclause); 
+
+       tmpclause  = array_alloc(int, 2);
+       array_insert(int, tmpclause, 0, fromIndex);
+       array_insert(int, tmpclause, 1, -cnfIndex);
+       BmcCnfInsertClause(cnfClauses, tmpclause);
+       st_insert(ClsidxToLatchTable,(char *)(long)(cnfClauses->noOfClauses-1),nodeName);
+       array_free(tmpclause);       
+
+     } else if (fromAigArray[i] == bAig_One){
+       tmpclause  = array_alloc(int, 2);
+       array_insert(int, tmpclause, 0, -toIndex);
+       array_insert(int, tmpclause, 1, cnfIndex);
+       BmcCnfInsertClause(cnfClauses, tmpclause);
+       st_insert(ClsidxToLatchTable,(char *)(long)(cnfClauses->noOfClauses-1),nodeName);
+       array_free(tmpclause);
+
+       tmpclause  = array_alloc(int, 2);
+       array_insert(int, tmpclause, 0, toIndex);
+       array_insert(int, tmpclause, 1, -cnfIndex);
+       BmcCnfInsertClause(cnfClauses, tmpclause);
+       st_insert(ClsidxToLatchTable,(char *)(long)(cnfClauses->noOfClauses-1),nodeName);
+       array_free(tmpclause);
+       
+     } else {
+       tmpclause  = array_alloc(int, 3);
+       array_insert(int, tmpclause, 0, -toIndex);
+       array_insert(int, tmpclause, 1, -fromIndex);
+       array_insert(int, tmpclause, 2,  cnfIndex);
+       BmcCnfInsertClause(cnfClauses, tmpclause);
+       st_insert(ClsidxToLatchTable,(char *)(long)(cnfClauses->noOfClauses-1),nodeName);
+       array_free(tmpclause);
+
+       tmpclause  = array_alloc(int, 2);
+       array_insert(int, tmpclause, 0, toIndex);
+       array_insert(int, tmpclause, 1, -cnfIndex);
+       BmcCnfInsertClause(cnfClauses, tmpclause);
+       st_insert(ClsidxToLatchTable,(char *)(long)(cnfClauses->noOfClauses-1),nodeName);
+       array_free(tmpclause);
+
+       tmpclause  = array_alloc(int, 2);
+       array_insert(int, tmpclause, 0, fromIndex);
+       array_insert(int, tmpclause, 1, -cnfIndex);
+       BmcCnfInsertClause(cnfClauses, tmpclause);
+       st_insert(ClsidxToLatchTable,(char *)(long)(cnfClauses->noOfClauses-1),nodeName);
+       array_free(tmpclause);
+     }
+     array_insert_last(int, clause, cnfIndex);
+    } /* if */
+      
+  } /* for i loop */
+  if (outIndex != 0 ){
+    array_insert_last(int, clause, -outIndex);
+  }
+  BmcCnfInsertClause(cnfClauses, clause);
+  array_free(clause);
+  
+  return;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Building the path with enhanced initail states]
+
+  Description [Building the path with enhanced initail states]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void
+PureSatGenerateClausesForPath_EnhanceInit(
+   Ntk_Network_t   *network,
+   int             from,
+   int             to,
+   PureSat_IncreSATManager_t * pism,
+   PureSat_Manager_t *  pm,
+   st_table        *nodeToMvfAigTable,
+   st_table        *CoiTable)
+{
+  mAig_Manager_t  *manager   = Ntk_NetworkReadMAigManager(network);
+  lsGen           gen;
+  
+  Ntk_Node_t         *latch, *latchData, *latchInit;
+  MvfAig_Function_t  *initMvfAig, *dataMvfAig, *latchMvfAig;
+  bAigEdge_t         *initBAig, *latchBAig, *dataBAig;
+  int        i,j, k, mvfSize;
+  array_t * vertexArray = array_alloc(char *,0);
+  char * nodeName;
+  BmcCnfClauses_t * cnfClauses = pism->cnfClauses;
+  st_table * ClsidxToLatchTable = pm->ClsidxToLatchTable;
+
+  if(from == 0){
+    if(pm->verbosity>=2)
+      fprintf(vis_stdout, "node in vertexArray: ");
+    Ntk_NetworkForEachLatch(network, gen, latch) { 
+      int tmp;
+      if (!st_lookup_int(CoiTable, latch, &tmp)){
+	continue;
+      }
+      nodeName = Ntk_NodeReadName(latch);
+      array_insert_last(char *,vertexArray,nodeName);
+      if(pm->verbosity>=2)
+	fprintf(vis_stdout, "%s  ",nodeName);
+    }
+    if(pm->verbosity>=2)
+      fprintf(vis_stdout, "\n");
+   }
+
+  if(from == 0){ 
+    array_t *supportLatches = PureSatGetImmediateSupportLatches(network, 0, vertexArray);
+    arrayForEachItem(char *, supportLatches, j, nodeName) {
+      latch = Ntk_NetworkFindNodeByName(network, nodeName);
+      latchInit  = Ntk_LatchReadInitialInput(latch);
+      latchData  = Ntk_LatchReadDataInput(latch);
+      initMvfAig = Bmc_ReadMvfAig(latchInit, nodeToMvfAigTable);
+      dataMvfAig = Bmc_ReadMvfAig(latchData, nodeToMvfAigTable);
+      latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+      if (latchMvfAig ==  NIL(MvfAig_Function_t)){
+	latchMvfAig = Bmc_NodeBuildMVF(network, latch);
+	array_free(latchMvfAig);
+	latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+      }
+      
+      mvfSize   = array_n(initMvfAig);
+      initBAig  = ALLOC(bAigEdge_t, mvfSize);
+      dataBAig  = ALLOC(bAigEdge_t, mvfSize);
+      latchBAig = ALLOC(bAigEdge_t, mvfSize);   
+      
+      for(i=0; i< mvfSize; i++){
+	dataBAig[i]  = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(dataMvfAig,  i));
+	latchBAig[i] = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(latchMvfAig, i));
+	initBAig[i]  = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(initMvfAig,  i));
+      }
+      
+      BmcGenerateClausesFromStateTostate(manager, initBAig, latchBAig, mvfSize, -1, 0, cnfClauses, 0);
+      FREE(initBAig);
+      FREE(dataBAig);
+      FREE(latchBAig);
+    }
+    array_free(supportLatches);
+    array_free(vertexArray);
+  }
+  
+  Ntk_NetworkForEachLatch(network, gen, latch) { 
+    int tmp;
+    if (!st_lookup_int(CoiTable, latch, &tmp)){
+      continue;
+    }
+    nodeName = Ntk_NodeReadName(latch);
+   latchInit  = Ntk_LatchReadInitialInput(latch);
+   latchData  = Ntk_LatchReadDataInput(latch);
+
+   /* Get the multi-valued function for each node*/
+   initMvfAig = Bmc_ReadMvfAig(latchInit, nodeToMvfAigTable);
+   if (initMvfAig ==  NIL(MvfAig_Function_t)){
+     (void) fprintf(vis_stdout, "No multi-valued function for this node %s \n", Ntk_NodeReadName(latchInit));
+     return;
+   } 
+   dataMvfAig = Bmc_ReadMvfAig(latchData, nodeToMvfAigTable);
+   if (dataMvfAig ==  NIL(MvfAig_Function_t)){
+     (void) fprintf(vis_stdout, "No multi-valued function for this node %s \n", Ntk_NodeReadName(latchData));
+     return;
+   }
+   latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+   if (latchMvfAig ==  NIL(MvfAig_Function_t)){
+     latchMvfAig = Bmc_NodeBuildMVF(network, latch);
+     array_free(latchMvfAig);
+     latchMvfAig = Bmc_ReadMvfAig(latch, nodeToMvfAigTable);
+   }
+      
+   mvfSize   = array_n(initMvfAig);
+   initBAig  = ALLOC(bAigEdge_t, mvfSize);
+   dataBAig  = ALLOC(bAigEdge_t, mvfSize);
+   latchBAig = ALLOC(bAigEdge_t, mvfSize);   
+
+   for(i=0; i< mvfSize; i++){
+     dataBAig[i]  = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(dataMvfAig,  i));
+     latchBAig[i] = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(latchMvfAig, i));
+     initBAig[i]  = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(initMvfAig,  i));
+   } 
+   /* Generate the CNF for the transition functions */   
+   for (k=from; k < to; k++){
+     PureSatGenerateClausesFromStateTostateWithTable(manager, dataBAig,latchBAig, mvfSize, k,
+						       k+1, cnfClauses,0,ClsidxToLatchTable, nodeName);
+   } /* for k state loop */
+   FREE(initBAig);
+   FREE(dataBAig);
+   FREE(latchBAig);
+  } /* ForEachLatch loop*/
+
+  return;
+}
Index: vis_dev/vis-2.3/src/puresat/puresatFlatIP.c
===================================================================
--- vis_dev/vis-2.3/src/puresat/puresatFlatIP.c	(revision 14)
+++ vis_dev/vis-2.3/src/puresat/puresatFlatIP.c	(revision 14)
@@ -0,0 +1,432 @@
+/**CFile***********************************************************************
+
+  FileName    [puresatFlatIP.c]
+
+  PackageName [puresat]
+
+  Synopsis    [Abstraction refinement for large scale invariant checking.]
+
+  Description [This file contains the functions to check invariant properties
+  by the PureSAT abstraction refinement algorithm, which is entirely based on
+  SAT solver, the input of which could be either CNF or AIG. It has several
+  parts:
+
+  * Localization-reduction base Abstraction
+  * K-induction or interpolation to prove the truth of a property
+  * Bounded Model Checking to find bugs
+  * Incremental concretization based methods to verify abstract bugs
+  * Incremental SAT solver to improve efficiency
+  * UNSAT proof based method to obtain refinement
+  * AROSAT to bring in only necessary latches into unsat proofs
+  * Bridge abstraction to get compact coarse refinement
+  * Refinement minization to guarrantee minimal refinements
+  * Unsat proof-based refinement minimization to eliminate multiple candidate
+    by on SAT test
+  * Refinement prediction to decrease the number of refinement iterations
+  * Dynamic switching to redistribute computional resources to improve
+    efficiency
+
+  For more information, please check the BMC'03, ICCAD'04, STTT'05 and TACAS'05
+  paper of Li et al., "A satisfiability-based appraoch to abstraction
+  refinement in model checking", " Abstraction in symbolic model checking
+  using satisfiability as the only decision procedure", "Efficient computation
+  of small abstraction refinements", and "Efficient abstraction refinement in
+  interpolation-based unbounded model checking"]
+
+  Author      [Bing Li]
+
+  Copyright   [Copyright (c) 2004 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without
+  license or royalty fees, to use, copy, modify, and distribute this
+  software and its documentation for any purpose, provided that the
+  above copyright notice and the following two paragraphs appear in
+  all copies of this software.]
+
+******************************************************************************/
+#include "maigInt.h"
+#include "puresatInt.h"
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Interpolation algorithm without abstraction refinement]
+
+  Description [Interpolation algorithm without abstraction refinement]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+boolean PureSatCheckInv_FlatIP(Ntk_Network_t * network,
+			       Ctlsp_Formula_t *ltlFormula,
+			       PureSat_Manager_t *pm)
+{
+  int NumofCurrentLatch=0,k;
+  bAig_Manager_t    *manager;
+  bAigEdge_t        property;
+  st_table * nodeToMvfAigTable;
+  double t1,t2,t0;
+  int first;
+  array_t           *previousResultArray;
+  BmcOption_t  *options = BmcOptionAlloc();
+  IP_Manager_t * ipm = IPManagerAlloc();
+  boolean firstTime;
+  int round=0, oldLength=0, nodes_in_coi=0;
+  st_table * tmpTable;
+  int oldPos1;
+  satManager_t * cm;
+  bAigEdge_t state, tmpState;
+  double tIP=0,tCon=0,tUnsat=0;
+  RTManager_t *rm;
+
+
+  pm->CoiTable = st_init_table(st_ptrcmp,st_ptrhash);
+  PureSatBmcGetCoiForLtlFormula(network, ltlFormula,pm->CoiTable);
+  ipm->CoiTable = pm->CoiTable;
+
+  options->printInputs = pm->printInputs;
+  options->dbgOut = pm->dbgOut;
+  pm->CoiTable = st_init_table(st_ptrcmp,st_ptrhash);
+  t0 = util_cpu_ctime();
+  NumofCurrentLatch=0;
+  t1 = util_cpu_ctime();
+  PureSatBmcGetCoiForLtlFormula_New(network, ltlFormula,pm->CoiTable);
+  t2 = util_cpu_ctime();
+
+  manager = Ntk_NetworkReadMAigManager(network);
+  if (manager == NIL(mAig_Manager_t)) {
+    (void) fprintf(vis_stdout, "** bmc error: run build_partition_maigs command first\n");
+    BmcOptionFree(options);
+    return 1;
+  }
+ nodeToMvfAigTable =(st_table *) Ntk_NetworkReadApplInfo(network,
+							 MVFAIG_NETWORK_APPL_KEY);
+
+ previousResultArray    = array_alloc(bAigEdge_t, 0);
+ first = 0;
+ manager->ipm = ipm;
+ t1 = util_cpu_ctime();
+ manager->test2LevelMini = 1;
+ bAig_PureSat_InitTimeFrame(network,manager,pm,0);
+ manager->test2LevelMini = 0;
+ if(pm->verbosity>=1) {
+   fprintf(vis_stdout,"after Init timeframe:\n");
+   PureSat_PrintAigStatus(manager);
+ }
+ manager->class_ = 1;
+ manager->test2LevelMini = 0;
+ property = PureSatCreatebAigOfPropFormula(network,
+	    manager, 0, ltlFormula, BMC_NO_INITIAL_STATES);
+ property = bAig_Not(property);
+ if(property==0)
+   return TRUE;
+ if(property==1)
+   return FALSE;
+ manager->assertArray = sat_ArrayAlloc(1);
+ sat_ArrayInsert(manager->assertArray,manager->InitState);
+ cm = PureSat_SatManagerAlloc(manager,pm,property,previousResultArray);
+ cm->option->coreGeneration = 0;
+ cm->option->IP = 0;
+ if(pm->verbosity>=1)
+   fprintf(vis_stdout,"test length 0\n");
+ sat_Main(cm);
+ manager->NodesArray = cm->nodesArray;
+ if(cm->status==SAT_SAT){
+   if(pm->dbgLevel == 1){
+     fprintf(vis_stdout,"find counter example of length 0\n");
+     BmcCirCUsPrintCounterExample(network, nodeToMvfAigTable, pm->CoiTable,
+				0, 0,options, BMC_NO_INITIAL_STATES);
+   }
+   if(pm->dbgLevel == 2){
+     BmcCirCUsPrintCounterExampleAiger(network, nodeToMvfAigTable, pm->CoiTable,
+				0, 0,options, BMC_NO_INITIAL_STATES);
+   }
+   return FALSE;
+ }
+ cm->option->coreGeneration = 1;
+ PureSat_SatFreeManager(cm);
+
+ manager->test2LevelMini = 1;
+ bAig_PureSat_ExpandTimeFrame(network, manager,pm,1, BMC_NO_INITIAL_STATES);
+  manager->class_ = 2;
+ manager->test2LevelMini = 0;
+ property = PureSatCreatebAigOfPropFormula(network,
+		manager, 1, ltlFormula, BMC_NO_INITIAL_STATES);
+ property = bAig_Not(property);
+ if(property==0)
+   return TRUE;
+ if(property==1)
+   return FALSE;
+ if(pm->verbosity>=1) {
+   fprintf(vis_stdout,"after Init timeframe:\n");
+   PureSat_PrintAigStatus(manager);
+ }
+ state = manager->InitState;
+
+
+ cm = PureSat_SatManagerAlloc(manager,pm,property,previousResultArray);
+ cm->option->coreGeneration = 0;
+ cm->option->IP = 0;
+ if(pm->verbosity>=1) {
+  fprintf(vis_stdout,"test length 1\n");
+ }
+ sat_Main(cm);
+ manager->NodesArray = cm->nodesArray;
+  if(cm->status==SAT_SAT){
+   if(pm->dbgLevel == 1){
+     fprintf(vis_stdout,"find counter example of length 1\n");
+     BmcCirCUsPrintCounterExample(network, nodeToMvfAigTable, pm->CoiTable,
+			1, 0,options, BMC_NO_INITIAL_STATES);
+   }
+   if(pm->dbgLevel == 2){
+     BmcCirCUsPrintCounterExampleAiger(network, nodeToMvfAigTable, pm->CoiTable,
+			1, 0,options, BMC_NO_INITIAL_STATES);
+   }
+   return FALSE;
+ }
+ cm->option->coreGeneration = 1;
+ PureSat_SatFreeManager(cm);
+
+ t2 = util_cpu_ctime();
+ if(pm->verbosity>=2)
+   fprintf(vis_stdout,"Time for testing Length 0 and 1: %g\n",(double)((t2-t1)/1000.0));
+
+ pm->Length = k;
+ k = 1;
+ PureSat_CleanMask(manager,ResetGlobalVarMask);
+ PureSat_MarkGlobalVar(manager,1);
+ while(1){
+   oldLength = k;
+   if(k==1)
+     k++;
+   else
+     k += round-1;
+   pm->Length = k;
+   if(pm->verbosity>=1)
+     fprintf(vis_stdout,"\nk = %d InitState = %ld\n",k,manager->InitState);
+   manager->test2LevelMini = 1;
+   bAig_PureSat_ExpandTimeFrame(network, manager,pm, k, BMC_NO_INITIAL_STATES);
+   manager->test2LevelMini = 0;
+   if(pm->verbosity>=1) {
+     fprintf(vis_stdout,"After expand TF\n");
+     PureSat_PrintAigStatus(manager);
+   }
+
+   /*build property aig nodes*/
+   manager->class_ = k+1;
+   property = PureSatCreatebAigOfPropFormula(network,
+	      manager, k, ltlFormula, BMC_NO_INITIAL_STATES);
+   property = bAig_Not(property);
+   if(property==0)
+     return TRUE;
+   if(property==1)
+     return FALSE;
+   oldPos1 = manager->nodesArraySize-bAigNodeSize;
+   if(pm->verbosity>=1) {
+     fprintf(vis_stdout,"After expanding TF and building property\n");
+     PureSat_PrintAigStatus(manager);
+   }
+   firstTime = TRUE;
+   round = 0;
+   state = manager->InitState;
+
+   while(1){
+     round++;
+     if(pm->verbosity>=1)
+       fprintf(vis_stdout,"round:%d for k = %d\n",round,k);
+     manager->assertArray = sat_ArrayAlloc(1);
+     if(state!=bAig_One)
+       sat_ArrayInsert(manager->assertArray,state);
+     cm = PureSat_SatManagerAlloc(manager,pm,property,previousResultArray);
+
+     if(cm->status==0){
+       if(pm->verbosity>=1)
+	 fprintf(vis_stdout,"normal COI:\n");
+       nodes_in_coi = PureSat_CountNodesInCoi(cm);
+       if(pm->verbosity>=2)
+	 fprintf(vis_stdout,"There are %d node in COI\n",nodes_in_coi);
+       t1 = util_cpu_ctime();
+       sat_Main(cm);
+       if(pm->verbosity>=2)
+	 sat_ReportStatistics(cm,cm->each);
+
+       rm = cm->rm;
+       t2 = util_cpu_ctime();
+       tUnsat = tUnsat+t2-t1;
+       if(pm->verbosity>=2)
+	 fprintf(vis_stdout,"time for Unsat:%g, Total:%g\n",
+		(double)((t2-t1)/1000.0),tUnsat/1000);
+       if(manager->NodesArray!=cm->nodesArray)
+	 /*cm->nodesArray may be reallocated */
+	 manager->NodesArray = cm->nodesArray;
+     }
+
+     if(cm->status == SAT_SAT){
+       /*SAT: first time->find bug, otherwise increase length*/
+       if(firstTime){
+	 if(pm->dbgLevel == 1){
+	   fprintf(vis_stdout,"found CEX of length %d\n",k);
+	   BmcCirCUsPrintCounterExample(network, nodeToMvfAigTable, pm->CoiTable,
+		      k, 0,options, BMC_NO_INITIAL_STATES);
+	 }
+	 if(pm->dbgLevel == 2){
+	   BmcCirCUsPrintCounterExampleAiger(network, nodeToMvfAigTable, pm->CoiTable,
+		      k, 0,options, BMC_NO_INITIAL_STATES);
+	 }
+	 sat_ArrayFree(manager->assertArray);
+	 manager->assertArray = 0;
+	 RT_Free(cm->rm);
+	 PureSat_SatFreeManager(cm);
+	 return FALSE;
+       }
+       /*find bogus bug, abort, increase length*/
+       else{
+	 /* BmcCirCUsPrintCounterExample(network, nodeToMvfAigTable, pm->CoiTable,
+				      k, 0,options, BMC_NO_INITIAL_STATES);*/
+	 if(pm->verbosity>=1)
+	   fprintf(vis_stdout,"find bogus bug at length k=%d,round=%d,increase length\n",k,round);
+
+	 sat_ArrayFree(manager->assertArray);
+	 RT_Free(cm->rm);
+	 PureSat_SatFreeManager(cm);
+	 break;
+       }
+     }
+     else{
+       /*UNSAT: get IP, add to init states, until reach convergence, which
+	 means property is true
+	 IP generation*/
+       assert(cm->currentDecision>=-1);
+       if(cm->currentDecision!=-1)
+	 sat_Backtrack(cm, -1);
+       /*get rid of Conflict Clauses*/
+       PureSat_ResetManager(manager,cm,0);
+
+       /*Generate interpolant and test convergence*/
+       if(cm->option->coreGeneration&&cm->status == SAT_UNSAT){
+	 manager->class_ = 1;
+	 t1 = util_cpu_ctime();
+	 tmpState = sat_GenerateFwdIP(manager,cm,cm->rm->root,1);
+	 manager->IPState = PureSat_MapIP(manager,tmpState,1,0);
+	 ResetRTree(rm);
+
+	 /*Wheneven there is baigNode generated, Reset_Manager is necessary,
+	   since NodeArray may be reallocated, # of Nodes changed*/
+	 PureSat_ResetManager(manager,cm,0);
+	 t2 = util_cpu_ctime();
+	 tIP = tIP+t2-t1;
+	 if(pm->verbosity>=2)
+	   fprintf(vis_stdout,"time for generating IP:%g, Total:%g\n",
+		  (double)((t2-t1)/1000.0),tIP/1000);
+	 if(pm->verbosity>=1){
+	   fprintf(vis_stdout,"After generate IP,%ld:\n",manager->IPState);
+	   PureSat_PrintAigStatus(manager);
+	 }
+	 manager->class_ = 2;
+	 t1 = util_cpu_ctime();
+	 RT_Free(cm->rm);
+	 if(pm->verbosity>=1)
+	   PureSat_PrintAigStatus(manager);
+
+	 PureSat_ResetManager(manager,cm,0);
+       }
+
+       t1 = util_cpu_ctime();
+
+       /*Convergence test for interpolation*/
+       if(PureSat_TestConvergeForIP(manager,pm,cm,state,manager->IPState)){
+	 t2 = util_cpu_ctime();
+	 tCon = tCon+t2-t1;
+	 if(pm->verbosity>=2)
+	   fprintf(vis_stdout,"time for generating Convergence:%g, Total:%g\n",
+		  (double)((t2-t1)/1000.0),tCon/1000);
+	 if(pm->verbosity>=1){
+	   fprintf(vis_stdout,"After test convergence:\n");
+	   PureSat_PrintAigStatus(manager);
+	 }
+	 fprintf(vis_stdout,"property is true\n");
+	 PureSat_SatFreeManager(cm);
+	 return TRUE;
+       }
+       else{
+	 t2 = util_cpu_ctime();
+	 tCon = tCon+t2-t1;
+	 if(pm->verbosity>=2)
+	   fprintf(vis_stdout,"time for generating Convergence:%g, Total:%g\n",
+		  (double)((t2-t1)/1000.0),tCon/1000);
+	 if(pm->verbosity>=1){
+	   fprintf(vis_stdout,"After test convergence:\n");
+	   PureSat_PrintAigStatus(manager);
+	 }
+	 manager->class_ = 0;
+	 state = PureSat_Or(manager,state,manager->IPState);
+	 PureSat_ResetManager(manager,cm,0);
+	 if(pm->verbosity>=1)
+	   fprintf(vis_stdout,"new InitState:%ld\n",state);
+       }
+     }/*else*/
+     sat_ArrayFree(manager->assertArray);
+     manager->assertArray = 0;
+     PureSat_SatFreeManager(cm);
+     firstTime = FALSE;
+   }/*inner While(1){*/
+ }/*outer While(1){*/
+ st_free_table(tmpTable);
+
+ sat_ArrayFree(manager->EqArray);
+ return TRUE;
+}
Index: vis_dev/vis-2.3/src/puresat/puresatIPAbRf.c
===================================================================
--- vis_dev/vis-2.3/src/puresat/puresatIPAbRf.c	(revision 14)
+++ vis_dev/vis-2.3/src/puresat/puresatIPAbRf.c	(revision 14)
@@ -0,0 +1,1182 @@
+/**CFile***********************************************************************
+
+  FileName    [puresatAbRf.c]
+
+  PackageName [puresat]
+
+  Synopsis    [Abstraction refinement for large scale invariant checking.]
+
+  Description [This file contains the functions to check invariant properties
+  by the PureSAT abstraction refinement algorithm, which is entirely based on
+  SAT solver, the input of which could be either CNF or AIG. It has several
+  parts:
+
+  * Localization-reduction base Abstraction
+  * K-induction or interpolation to prove the truth of a property
+  * Bounded Model Checking to find bugs
+  * Incremental concretization based methods to verify abstract bugs
+  * Incremental SAT solver to improve efficiency
+  * UNSAT proof based method to obtain refinement
+  * AROSAT to bring in only necessary latches into unsat proofs
+  * Bridge abstraction to get compact coarse refinement
+  * Refinement minization to guarrantee minimal refinements
+  * Unsat proof-based refinement minimization to eliminate multiple candidate
+    by on SAT test
+  * Refinement prediction to decrease the number of refinement iterations
+  * Dynamic switching to redistribute computional resources to improve
+    efficiency
+
+  For more information, please check the BMC'03, ICCAD'04, STTT'05 and TACAS'05
+  paper of Li et al., "A satisfiability-based appraoch to abstraction
+  refinement in model checking", " Abstraction in symbolic model checking
+  using satisfiability as the only decision procedure", "Efficient computation
+  of small abstraction refinements", and "Efficient abstraction refinement in
+  interpolation-based unbounded model checking"]
+
+  Author      [Bing Li]
+
+  Copyright   [Copyright (c) 2004 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without
+  license or royalty fees, to use, copy, modify, and distribute this
+  software and its documentation for any purpose, provided that the
+  above copyright notice and the following two paragraphs appear in
+  all copies of this software.]
+
+******************************************************************************/
+#include "maigInt.h"
+#include "puresatInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Interpolation test for concrete model]
+
+  Description [used by dynamic switching]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+boolean PureSatIPOnCon(Ntk_Network_t * network,
+		       Ctlsp_Formula_t *ltlFormula,
+		       PureSat_Manager_t *pm)
+{
+  int k;
+  bAig_Manager_t    *manager;
+  bAigEdge_t        property;
+  double t1,t2;
+  array_t           *previousResultArray=0;
+  boolean firstTime;
+  int round;
+  st_table * tmpTable;
+  int oldPos1,nodes_in_coi=0;
+  satManager_t * cm;
+  bAigEdge_t state, tmpState;
+  double tCon=0;
+  RTManager_t *rm;
+
+  manager = Ntk_NetworkReadMAigManager(network);
+
+  if(pm->verbosity>=1)
+    fprintf(vis_stdout,"go to concrete model\n");
+
+ k = pm->Length;
+ round = 1;
+ PureSat_CleanMask(manager,ResetGlobalVarMask);
+ PureSat_MarkGlobalVar(manager,1);
+ while(1){
+   k += round-1;
+   pm->Length = k;
+
+   if(pm->verbosity>=1)
+     fprintf(vis_stdout,"\nk = %d InitState = %ld\n",k,manager->InitState);
+   manager->test2LevelMini = 1;
+   t1 = util_cpu_ctime();
+   bAig_PureSat_ExpandTimeFrame(network, manager,pm, k, BMC_NO_INITIAL_STATES);
+   t2 = util_cpu_ctime();
+   pm->tExp += t2-t1;
+   if(pm->verbosity>=2)
+     fprintf(vis_stdout,"Expansion time:%g,total:%g\n",
+	    (double)((t2-t1)/1000.0),pm->tExp/1000);
+   manager->test2LevelMini = 0;
+   if(pm->verbosity>=1){
+     fprintf(vis_stdout,"After expand TF\n");
+     PureSat_PrintAigStatus(manager);
+   }
+   manager->class_ = k+1;
+   property = BmcCirCUsCreatebAigOfPropFormula(network,
+		     manager, k, ltlFormula, BMC_NO_INITIAL_STATES);
+   property = bAig_Not(property);
+   if(property==0){
+     return TRUE;
+   }
+   if(property==1){
+     return FALSE;
+   }
+   oldPos1 = manager->nodesArraySize-bAigNodeSize;
+   if(pm->verbosity>=1){
+     fprintf(vis_stdout,"After expanding TF and building property\n");
+     PureSat_PrintAigStatus(manager);
+   }
+   firstTime = TRUE;
+   round = 0;
+   state = manager->InitState;
+
+   while(1){
+     round++;
+     if(pm->verbosity>=1)
+       fprintf(vis_stdout,"round:%d for k = %d\n",round,k);
+     manager->assertArray = sat_ArrayAlloc(1);
+     if(state!=bAig_One)
+       sat_ArrayInsert(manager->assertArray,state);
+     cm = PureSat_SatManagerAlloc(manager,pm,property,previousResultArray);
+     cm->option->IP = 1;
+
+
+     if(cm->status==0){
+       if(pm->verbosity>=1)
+	 fprintf(vis_stdout,"normal COI:\n");
+       if(pm->verbosity>=1) {
+	 nodes_in_coi = PureSat_CountNodesInCoi(cm);
+	 fprintf(vis_stdout,"There are %d node in COI\n",nodes_in_coi);
+       }
+       t1 = util_cpu_ctime();
+       sat_Main(cm);
+
+       rm = cm->rm;
+       cm->option->IP = 0;
+       if(manager->NodesArray!=cm->nodesArray)
+	 /*cm->nodesArray may be reallocated */
+	 manager->NodesArray = cm->nodesArray;
+       t2 = util_cpu_ctime();
+       pm->tIPUnsat += t2 - t1;
+       if(pm->verbosity>=2)
+	 fprintf(vis_stdout,"time for Unsat:%g, total:%g\n",
+		(double)((t2-t1)/1000.0),pm->tIPUnsat/1000);
+     }
+
+     if(cm->status == SAT_SAT){
+       /*SAT: first time->find bug, otherwise increase length*/
+       if(firstTime){
+	 fprintf(vis_stdout,"found CEX of length %d\n",k);
+
+	 sat_ArrayFree(manager->assertArray);
+	 manager->assertArray = 0;
+	 RT_Free(cm->rm);
+	 PureSat_SatFreeManager(cm);
+	 return FALSE;
+       }
+       else{
+
+	 if(pm->verbosity>=1)
+	   fprintf(vis_stdout,"find bogus bug at length k=%d,round=%d,increase length\n",k,round);
+
+	 sat_ArrayFree(manager->assertArray);
+	 RT_Free(cm->rm);
+	 PureSat_SatFreeManager(cm);
+	 break;
+       }
+     }
+     else{
+       /*UNSAT: get IP, add to init states, until reach convergence, which
+       means property is true
+       Bing: IP generation*/
+       assert(cm->currentDecision>=-1);
+       if(cm->currentDecision!=-1)
+	 sat_Backtrack(cm, -1);
+       /*get rid of Conflict Clauses*/
+       PureSat_ResetManager(manager,cm,1);
+
+       if(cm->option->coreGeneration&&cm->status == SAT_UNSAT){
+	 manager->class_ = 1;
+	 t1 = util_cpu_ctime();
+	 tmpState = sat_GenerateFwdIP(manager,cm,cm->rm->root,1);
+	 manager->IPState = PureSat_MapIP(manager,tmpState,1,0);
+
+	 /*Wheneven there is baigNode generated, Reset_Manager is necessary,
+	   //since NodeArray may be reallocated, # of Nodes changed*/
+	 PureSat_ResetManager(manager,cm,0);
+	 t2 = util_cpu_ctime();
+	 pm->tIPGen += t2 -t1;
+	 if(pm->verbosity>=2)
+	   fprintf(vis_stdout,"time for generating and mapping IP:%g, total:%g\n",
+		  (double)((t2-t1)/1000.0),pm->tIPGen/1000);
+	 if(pm->verbosity>=1){
+	   fprintf(vis_stdout,"After generate IP,IP2:%ld,%ld:\n",manager->IPState,tmpState);
+	   PureSat_PrintAigStatus(manager);
+	 }
+	 manager->class_ = 2;
+
+	 t1 = util_cpu_ctime();
+
+	 RT_Free(cm->rm);
+	 if(pm->verbosity>=1)
+	   PureSat_PrintAigStatus(manager);
+       }
+
+       t1 = util_cpu_ctime();
+       if(PureSat_TestConvergeForIP(manager,pm,cm,state,manager->IPState)){
+	 t2 = util_cpu_ctime();
+	 tCon = tCon+t2-t1;
+	 if(pm->verbosity>=2)
+	   fprintf(vis_stdout,"time for generating Convergence:%g, Total:%g\n",
+		  (double)((t2-t1)/1000.0),tCon/1000);
+	 if(pm->verbosity>=1){
+	   fprintf(vis_stdout,"After test convergence:\n");
+	   PureSat_PrintAigStatus(manager);
+	 }
+	 fprintf(vis_stdout,"property is true\n");
+	 PureSat_SatFreeManager(cm);
+	 sat_ArrayFree(manager->assertArray);
+	 return TRUE;
+       }
+       else{
+	 t2 = util_cpu_ctime();
+	 pm->tIPCon += t2-t1;
+	 if(pm->verbosity>=2)
+	   fprintf(vis_stdout,"time for generating Convergence:%g, total:%g\n",
+		  (double)((t2-t1)/1000.0),pm->tIPCon/1000);
+	 if(pm->verbosity>=1){
+	   fprintf(vis_stdout,"After test convergence:\n");
+	   PureSat_PrintAigStatus(manager);
+	 }
+
+	 manager->class_ = 0;
+	 state = PureSat_Or(manager,state,manager->IPState);
+	 PureSat_ResetManager(manager,cm,0);
+	 if(pm->verbosity>=1)
+	   fprintf(vis_stdout,"new InitState:%ld\n",state);
+
+       }
+     }/*else*/
+     sat_ArrayFree(manager->assertArray);
+     manager->assertArray = 0;
+     PureSat_SatFreeManager(cm);
+     firstTime = FALSE;
+   }/*inner While(1){*/
+   /*sat_ArrayInsert(previousResultArray, bAig_Not(property)); */
+ }/*outer While(1){*/
+ st_free_table(tmpTable);
+
+ sat_ArrayFree(manager->EqArray);
+ return TRUE;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Using interpolation on abstractions]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+boolean PureSat_CheckAceByIP(Ntk_Network_t *network,
+			     PureSat_Manager_t * pm,
+			     PureSat_IncreSATManager_t *pism,
+			     array_t *vertexArray,
+			     int * k,
+			     Ctlsp_Formula_t *ltlFormula,
+			     bAigEdge_t * returnProp,
+			     array_t *previousResultArray)
+{
+  int oldPos;
+  boolean firstTime,fork=0,ExistACE;
+  int round,oldLength,coiCon,coiAbs;
+  bAigEdge_t property;
+  double t1,t2,t3,t4,t5, threshold_sw=0;
+  satManager_t * cm;
+  array_t *bVarList,*mVarList;
+  bAigEdge_t state, tmpState;
+  BmcOption_t  *options = BmcOptionAlloc();
+  bAig_Manager_t * manager = Ntk_NetworkReadMAigManager(network);
+
+  bVarList = mAigReadBinVarList(manager);
+  mVarList = mAigReadMulVarList(manager);
+  options->printInputs = TRUE;
+  options->verbosityLevel = BmcVerbosityMax_c;
+
+  assert(*k>=1);
+  manager->test2LevelMini = 1;
+  bAig_PureSat_ExpandTimeFrame(network, manager, pm,*k,
+			       BMC_NO_INITIAL_STATES);
+  manager->test2LevelMini = 0;
+  PureSat_CleanMask(manager,ResetVisibleVarMask);
+  PuresatMarkVisibleVar(network,vertexArray,pm,0,*k+1);
+  PureSat_CleanMask(manager,ResetGlobalVarMask);
+
+  PureSat_MarkGlobalVar_AbRf(manager,1);
+  oldLength = *k;
+
+  while(1){
+    if(fork){
+      oldLength = pm->Length;
+      (*k) += round-1;
+      pm->Length = *k;
+    }
+    fork=1;
+    if(pm->verbosity>=1)
+      fprintf(vis_stdout,"\nk = %d InitState = %ld\n",*k,manager->InitState);
+    manager->test2LevelMini = 1;
+    t1 = util_cpu_ctime();
+    bAig_PureSat_ExpandTimeFrame(network, manager, pm,*k,
+				 BMC_NO_INITIAL_STATES);
+    t2 = util_cpu_ctime();
+    pm->tExp += t2-t1;
+    if(pm->verbosity>=2)
+      fprintf(vis_stdout,"Expansion time:%g,total:%g\n",
+	     (double)((t2-t1)/1000.0),pm->tExp/1000);
+    manager->test2LevelMini = 0;
+    PureSat_CleanMask(manager,ResetVisibleVarMask);
+    PuresatMarkVisibleVar(network,vertexArray,pm,0,*k+1);
+    manager->class_ = *k+1;
+    property = PureSatCreatebAigOfPropFormula(network,
+		manager, *k, ltlFormula, BMC_NO_INITIAL_STATES);
+    property = bAig_Not(property);
+    *returnProp = property;
+    if(pm->verbosity>=1)
+      fprintf(vis_stdout,"property is %ld\n",property);
+    oldPos = manager->nodesArraySize-bAigNodeSize;
+    if(pm->verbosity>=1){
+      fprintf(vis_stdout,"After expanding TF and building property\n");
+      PureSat_PrintAigStatus(manager);
+    }
+    firstTime = TRUE;
+    round = 0;
+    state = manager->InitState;
+    /*for one length*/
+    while(1){
+      round++;
+      if(pm->verbosity>=1)
+	fprintf(vis_stdout,"round:%d for k = %d\n",round,*k);
+      manager->assertArray = sat_ArrayAlloc(1);
+      if(state!=bAig_One)
+	sat_ArrayInsert(manager->assertArray,state);
+      cm = PureSat_SatManagerAlloc_WOCOI(manager,pm,property,previousResultArray);
+      cm->option->IP = 1;
+      cm->option->AbRf = 1;
+
+
+      if(round == 1){
+	PureSat_ResetCoi(cm);
+	sat_SetConeOfInfluence(cm);
+	if(pm->verbosity>=1)
+	  fprintf(vis_stdout,"COI nodes if check concrete model:\n");
+	coiCon = PureSat_CountNodesInCoi(cm);
+	if(pm->verbosity>=1)
+	  fprintf(vis_stdout,"There are %d node in COI\n",coiCon);
+      }
+
+      t1 = util_cpu_ctime();
+
+      PureSatSetCOI(network,pm,cm,pm->vertexTable,0, *k,*k);
+      t2 = util_cpu_ctime();
+      pm->tPro += t2-t1;
+      if(pm->verbosity>=2)
+	fprintf(vis_stdout,"process time:%g,total:%g\n",
+	       (double)((t2-t1)/1000.0),pm->tPro/1000);
+      /*switch to concrete model*/
+      if(pm->verbosity>=1)
+	fprintf(vis_stdout,"normal COI:\n");
+      coiAbs = PureSat_CountNodesInCoi(cm);
+      if(round == 1){
+	if(pm->verbosity>=1)
+	  fprintf(vis_stdout,"Coi of abs divided by Coi of con: %g\n",
+		 (double)coiAbs/(double)coiCon);
+#if SWITCH_DA
+	if((double)coiAbs/(double)coiCon >= 0.68&&*k>=5){
+	  if(pm->switch_da == 0){
+	    if(pm->verbosity>=1)
+	      fprintf(vis_stdout,"Switch to DirAdd mode\n");
+	    pm->switch_da = 1;
+	  }
+	}
+#endif
+
+	if(pm->Switch)
+	  threshold_sw = 0.68;
+	else
+	  threshold_sw = 1.1;
+
+	if(((double)coiAbs/(double)coiCon) >= threshold_sw&&*k>=5){
+
+	  t3 = util_cpu_ctime();
+	  sat_ArrayFree(manager->assertArray);
+	  manager->assertArray = 0;
+	  if(pm->verbosity>=1)
+	    fprintf(vis_stdout,"Abs model is large, go to Concrete model\n");
+	  ExistACE = PureSatIPOnCon(network,ltlFormula,pm);
+	  PureSat_SatFreeManager(cm);
+	  t1 = util_cpu_ctime();
+	  if(pm->verbosity>=1)
+	    fprintf(vis_stdout,"Run on concrete model: %g\n",(double)((t1-t3)/1000.0));
+	  if(ExistACE){
+	    pm->returnVal = 1;
+	    return FALSE;
+	  }
+	  else{
+	    pm->returnVal = -1;
+	    return TRUE;
+	  }
+	}
+      }
+
+      PureSatKillPseudoGV(network,pm,pm->vertexTable,1,*k);
+      PureSat_ResetManager(manager,cm,0);
+      PureSatProcessFanout(cm);
+
+      t1 = util_cpu_ctime();
+      sat_Main(cm);
+      if(pm->verbosity>=2)
+	sat_ReportStatistics(cm,cm->each);
+      cm->option->IP = 0;
+      if(manager->NodesArray!=cm->nodesArray)
+	/*cm->nodesArray may be reallocated*/
+	manager->NodesArray = cm->nodesArray;
+      t2 = util_cpu_ctime();
+      pm->tIPUnsat += t2 - t1;
+      if(pm->verbosity>=2)
+	fprintf(vis_stdout,"time for Unsat:%g, total:%g\n",
+	       (double)((t2-t1)/1000.0),pm->tIPUnsat/1000);
+      t1 = util_cpu_ctime();
+      PureSatPostprocess(manager,cm,pm);
+      /*clean masks*/
+      sat_CleanDatabase(cm);
+
+      if(cm->status==SAT_UNSAT){
+	PureSatProcessDummy(manager,cm,cm->rm->root);
+	ResetRTree(cm->rm);
+      }
+      t2 = util_cpu_ctime();
+      pm->tPro += t2-t1;
+      if(pm->verbosity>=2)
+	fprintf(vis_stdout,"process time:%g,total:%g\n",
+	       (double)((t2-t1)/1000.0),pm->tPro/1000);
+
+      if(cm->status == SAT_SAT){
+	/*SAT: first time->find bug, otherwise increase length*/
+	if(firstTime){
+	  if(pm->verbosity>=1)
+	    fprintf(vis_stdout,"found abstract CEX of length %d\n",*k);
+
+
+	  PureSat_UnMarkGlobalVar(manager,1);
+	  RT_Free(cm->rm);
+	  PureSat_SatFreeManager(cm);
+	  sat_ArrayFree(manager->assertArray);
+	  return TRUE;
+       }
+	else{
+
+	  if(pm->verbosity>=1)
+	    fprintf(vis_stdout,"find bogus bug at length k=%d,round=%d,increase length\n",*k,round);
+	  sat_ArrayFree(manager->assertArray);
+	  RT_Free(cm->rm);
+	  PureSat_SatFreeManager(cm);
+	  break;
+	}
+      }
+     else{
+       /*UNSAT: get IP, add to init states, until reach convergence, which
+       //means property is true
+       //Bing: IP generation*/
+       assert(cm->currentDecision>=-1);
+       if(cm->currentDecision!=-1)
+	 sat_Backtrack(cm, -1);
+       PureSat_ResetManager(manager,cm,1);//get rid of Conflict Clauses
+       if(cm->option->coreGeneration&&cm->status == SAT_UNSAT){
+	 manager->class_ = 1;
+	 t1 = util_cpu_ctime();
+	 tmpState = sat_GenerateFwdIP(manager,cm,cm->rm->root,1);
+	 manager->IPState = PureSat_MapIP(manager,tmpState,1,0);
+
+	 /*Wheneven there is baigNode generated, Reset_Manager is necessary,
+	   //since NodeArray may be reallocated, # of Nodes changed*/
+	 PureSat_ResetManager(manager,cm,0);
+	 t2 = util_cpu_ctime();
+
+	 pm->tIPGen += t2 -t1;
+	 if(pm->verbosity>=2)
+	   fprintf(vis_stdout,"time for generating and mapping IP:%g, total:%g\n",
+		  (double)((t2-t1)/1000.0),pm->tIPGen/1000);
+	 if(pm->verbosity>=1){
+	   fprintf(vis_stdout,"After generate IP,%ld:\n",manager->IPState);
+	   PureSat_PrintAigStatus(manager);
+	 }
+	 manager->class_ = 2;
+	 if(pm->verbosity>=1)
+	   fprintf(vis_stdout,"After generate IP2:%ld\n",tmpState);
+	 t4 = util_cpu_ctime();
+	 RT_Free(cm->rm);
+	 t5 = util_cpu_ctime();
+	 pm->tGFree += (t5-t4);
+	 if(pm->verbosity>=2)
+	   fprintf(vis_stdout,"GFree time :%g\n",(t5-t4)/1000);
+	 if(pm->verbosity>=1)
+	   PureSat_PrintAigStatus(manager);
+	 }
+
+       t1 = util_cpu_ctime();
+       if(PureSat_TestConvergeForIP_AbRf(network,cm,pm,vertexArray,
+					 state,manager->IPState)){
+	 t2 = util_cpu_ctime();
+	 pm->tIPCon += t2-t1;
+	 if(pm->verbosity>=2)
+	   fprintf(vis_stdout,"time for generating Convergence:%g, total:%g\n",
+		  (double)((t2-t1)/1000.0),pm->tIPCon/1000);
+	 if(pm->verbosity>=1){
+	   fprintf(vis_stdout,"After test convergence:\n");
+	   PureSat_PrintAigStatus(manager);
+	 }
+	 fprintf(vis_stdout,"property is true\n");
+	 PureSat_SatFreeManager(cm);
+	 sat_ArrayFree(manager->assertArray);
+	 return FALSE;
+       }
+       else{
+	 t2 = util_cpu_ctime();
+	 pm->tIPCon += t2-t1;
+	 if(pm->verbosity>=2)
+	   fprintf(vis_stdout,"time for generating Convergence:%g, total:%g\n",
+		  (double)((t2-t1)/1000.0),pm->tIPCon/1000);
+	 if(pm->verbosity>=1){
+	   fprintf(vis_stdout,"After test convergence:\n");
+	   PureSat_PrintAigStatus(manager);
+	 }
+	 manager->class_ = 0;
+	 state = PureSat_Or(manager,state,manager->IPState);
+	 if(pm->verbosity>=1)
+	   fprintf(vis_stdout,"new InitState:%ld\n",state);
+       }
+     }/*else */
+     sat_ArrayFree(manager->assertArray);
+     PureSat_SatFreeManager(cm);
+     firstTime = FALSE;
+    }/*inner While(1){*/
+  }/*outer While(1){*/
+ return FALSE;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Main procedure of interpolation-based PureSat]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+boolean PureSatCheckInv_IP(Ntk_Network_t * network,
+			     Ctlsp_Formula_t *ltlFormula,
+			     PureSat_Manager_t *pm)
+{
+  lsGen     gen;
+  st_generator      *stGen;
+  int NumofCurrentLatch=0,Length=0,tmp=0,NumofLatch=0,i,j,k;
+  int addtoAbs,latchThreshHold;
+  int NumInSecondLevel=0;
+  array_t * visibleArray = array_alloc(char *,0);
+  array_t * invisibleArray = array_alloc(char *,0);
+  array_t * refinement= array_alloc(char *,0);
+  array_t * CoiArray = array_alloc(char *,0);
+  array_t * arrayRC = array_alloc(char *,0);
+  array_t *tmpRefinement = array_alloc(char *,0);
+  array_t *tmpRefinement1 = array_alloc(char *,0),*previousResultArray ;
+  char * nodeName;
+  Ntk_Node_t * node, *latch;
+  boolean ExistACE = FALSE,realRefine=TRUE;
+  boolean firstTime = TRUE;
+  bAig_Manager_t    *manager;
+  BmcOption_t * options;
+  bAigEdge_t   property;
+  st_table * nodeToMvfAigTable;
+  double t1,t2,t5, t0,t3,t4,t4total=0;
+  PureSat_IncreSATManager_t * pism1;
+  IP_Manager_t * ipm = IPManagerAlloc();
+  satManager_t *cm;
+  int * sccArray=NULL, orderCt, satStat=0;
+  st_table * tmpTable;
+
+
+  manager = Ntk_NetworkReadMAigManager(network);
+  if (manager == NIL(bAig_Manager_t)) {
+    (void) fprintf(vis_stdout,
+    "** bmc error: run build_partition_maigs command first\n");
+    return 1;
+  }
+  nodeToMvfAigTable =(st_table *) Ntk_NetworkReadApplInfo(network,
+							  MVFAIG_NETWORK_APPL_KEY);
+
+  pm->supportTable = st_init_table(st_ptrcmp,st_ptrhash);
+  pm->CoiTable = st_init_table(st_ptrcmp,st_ptrhash);
+  pm->oldCoiTable = st_init_table(st_ptrcmp,st_ptrhash);
+  pm->vertexTable = st_init_table(strcmp, st_strhash);
+  pism1 = PureSatIncreSATManagerAlloc(pm);
+  t0 = util_cpu_ctime();
+
+  options = BmcOptionAlloc();
+  options->verbosityLevel = BmcVerbosityMax_c;
+  options->printInputs = TRUE;
+
+  t1 = util_cpu_ctime();
+  previousResultArray    = array_alloc(bAigEdge_t, 0);
+  manager->class_ = 0;
+  manager->ipm = ipm;
+  manager->test2LevelMini = 1;
+  t3 = util_cpu_ctime();
+  bAig_PureSat_InitTimeFrame(network,manager,pm,0);
+  t5 = util_cpu_ctime();
+  pm->tExp += t5-t3;
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"Expansion time:%g,total:%g\n",
+	    (double)((t5-t3)/1000.0),pm->tExp/1000);
+  manager->test2LevelMini = 0;
+  if(pm->verbosity>=1){
+    fprintf(vis_stdout,"after Init timeframe:\n");
+    PureSat_PrintAigStatus(manager);
+  }
+  manager->class_ = 1;
+  property = PureSatCreatebAigOfPropFormula(network,
+    manager, 0, ltlFormula, BMC_NO_INITIAL_STATES);
+  property = bAig_Not(property);
+  if(pm->verbosity>=1)
+    fprintf(vis_stdout,"property is %ld\n",property);
+  if(property==0)
+    return TRUE;
+  if(property==1)
+    return FALSE;
+  manager->assertArray = sat_ArrayAlloc(1);
+  sat_ArrayInsert(manager->assertArray,manager->InitState);
+  cm = PureSat_SatManagerAlloc(manager,pm,property,previousResultArray);
+  sat_MarkTransitiveFaninForArray(cm, cm->assertArray, CoiMask);
+  cm->option->coreGeneration = 0;
+  cm->option->IP = 0;
+  if(pm->verbosity>=1)
+    fprintf(vis_stdout,"test length 0\n");
+  sat_Main(cm);
+  manager->NodesArray = cm->nodesArray;
+  if(cm->status==SAT_SAT){
+    fprintf(vis_stdout,"find counter example of length 0\n");
+    BmcCirCUsPrintCounterExample(network, nodeToMvfAigTable, pm->CoiTable,
+				 0, 0,options, BMC_NO_INITIAL_STATES);
+    return FALSE;
+  }
+  cm->option->coreGeneration = 1;
+  PureSat_SatFreeManager(cm);
+
+  manager->test2LevelMini = 1;
+  t3 = util_cpu_ctime();
+  bAig_PureSat_ExpandTimeFrame(network, manager,pm,1, BMC_NO_INITIAL_STATES);
+  t5 = util_cpu_ctime();
+  pm->tExp += t5-t3;
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"Expansion time:%g,total:%g\n",
+	    (double)((t5-t3)/1000.0),pm->tExp/1000);
+  manager->class_ = 2;
+  manager->test2LevelMini = 0;
+  property = PureSatCreatebAigOfPropFormula(network,
+    manager, 1, ltlFormula, BMC_NO_INITIAL_STATES);
+  property = bAig_Not(property);
+
+  if(pm->verbosity>=1)
+    fprintf(vis_stdout,"property is %ld\n",property);
+  if(property==0)
+    return TRUE;
+  if(property==1)
+    return FALSE;
+  manager->assertArray = sat_ArrayAlloc(1);
+  sat_ArrayInsert(manager->assertArray,manager->InitState);
+  cm = PureSat_SatManagerAlloc(manager,pm,property,previousResultArray);
+  sat_MarkTransitiveFaninForArray(cm, cm->assertArray, CoiMask);
+  cm->option->coreGeneration = 0;
+  cm->option->IP = 0;
+  if(pm->verbosity>=1)
+    fprintf(vis_stdout,"test length 1\n");
+  sat_Main(cm);
+  manager->NodesArray = cm->nodesArray;
+  if(cm->status==SAT_SAT){
+    fprintf(vis_stdout,"find counter example of length 1\n");
+    BmcCirCUsPrintCounterExample(network, nodeToMvfAigTable, pm->CoiTable,
+				 1, 0,options, BMC_NO_INITIAL_STATES);
+    return FALSE;
+  }
+  t2 = util_cpu_ctime();
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"Time for testing Length 0 and 1: %g\n",(double)((t2-t1)/1000.0));
+  cm->option->coreGeneration = 1;
+  PureSat_SatFreeManager(cm);
+  Length = 2;
+  pm->Length = Length;
+  pism1->Length = Length;
+
+  manager->test2LevelMini = 1;
+  t3 = util_cpu_ctime();
+  bAig_PureSat_ExpandTimeFrame(network, manager,pm,2, BMC_NO_INITIAL_STATES);
+  t5 = util_cpu_ctime();
+  pm->tExp += t5-t3;
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"Expansion time:%g,total:%g\n",
+	    (double)((t5-t3)/1000.0),pm->tExp/1000);
+  manager->class_ = 3;
+  manager->test2LevelMini = 0;
+  property = PureSatCreatebAigOfPropFormula(network,
+    manager, 2, ltlFormula, BMC_NO_INITIAL_STATES);
+  property = bAig_Not(property);
+  if(property==0)
+    return TRUE;
+  if(property==1)
+    return FALSE;
+
+  if(pm->verbosity>=1)
+    fprintf(vis_stdout,"property is %ld\n",property);
+  manager->test2LevelMini = 1;
+
+
+  NumofCurrentLatch=0;
+  t3 = util_cpu_ctime();
+  PureSatBmcGetCoiForLtlFormula_New(network, ltlFormula,pm->oldCoiTable);
+  t5 = util_cpu_ctime();
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"Compute NTK COI :%g\n",(t5-t3)/1000);
+
+  pm->CoiTable = st_copy(pm->oldCoiTable);
+
+  /*new COI computation*/
+  t3 = util_cpu_ctime();
+  tmpTable = PureSatGetAigCoi(network,pm,property);
+  st_foreach_item(tmpTable,stGen,&nodeName,NIL(char*)){
+    latch = Ntk_NetworkFindNodeByName(network,nodeName);
+#if 1
+    if(!st_lookup(pm->CoiTable,latch,NIL(char*)))
+      if(pm->verbosity>=2)
+	fprintf(vis_stdout,"%s is not in CoiTable\n",nodeName);
+#endif
+    st_insert(pm->CoiTable,latch,(char*)0);
+  }
+#if 1
+  st_foreach_item(pm->CoiTable,stGen,&latch,NIL(char*)){
+    nodeName = Ntk_NodeReadName(latch);
+    if(!st_lookup(tmpTable,nodeName,NIL(char*)))
+      if(pm->verbosity>=2)
+	fprintf(vis_stdout,"%s is not in Aig CoiTable\n",nodeName);
+  }
+#endif
+  st_free_table(tmpTable);
+  t5 = util_cpu_ctime();
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"Compute AIG COI :%g\n",(t5-t3)/1000);
+
+
+  t3 = util_cpu_ctime();
+  pm->vertexTable = PureSatCreateInitialAbstraction(network,
+		      ltlFormula,&NumofCurrentLatch,pm);
+  t5 = util_cpu_ctime();
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"the time to create init abs:%g\n",(t5-t3)/1000);
+  tmpTable = st_init_table(strcmp,st_strhash);
+  PureSatCreateInitAbsByAIG(manager,pm,property,tmpTable);
+  st_foreach_item(tmpTable,stGen,&nodeName,NIL(char*)){
+    if(!st_lookup(pm->vertexTable,nodeName,NIL(char*))){
+      st_insert(pm->vertexTable,nodeName,(char*)0);
+      if(pm->verbosity>=1)
+	fprintf(vis_stdout,"insert %s into init abs model\n",nodeName);
+    }
+  }
+  st_free_table(tmpTable);
+  t3 = util_cpu_ctime();
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"the time to create init AIG abs:%g\n",(t3-t5)/1000);
+
+  PureSatPreProcLatch(network,pm);
+  t5 = util_cpu_ctime();
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"the time to preproc:%g\n",(t5-t3)/1000);
+
+  /*put indentical latches of visible latch into abs*/
+  t3 = util_cpu_ctime();
+  PureSatGetIndenticalLatch(network,pm);
+  st_foreach_item(pm->vertexTable,stGen,&nodeName,NIL(char*))
+    array_insert_last(char*,visibleArray,nodeName);
+  PureSatAddIdenLatchToAbs(network,pm,visibleArray);
+  arrayForEachItem(char*,visibleArray,i,nodeName)
+    st_insert(pm->vertexTable,nodeName,(char*)0);
+  array_free(visibleArray);
+  visibleArray = array_alloc(char*,0);
+  t5 = util_cpu_ctime();
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"Merge identical latch:%g\n",(t5-t3)/1000);
+
+  NumofCurrentLatch = st_count(pm->vertexTable);
+
+  t3 = util_cpu_ctime();
+  pm->AbsTable = st_init_table(st_ptrcmp,st_ptrhash);
+
+  Ntk_NetworkForEachLatch(network, gen, node){
+    if (st_lookup_int(pm->CoiTable, (char *) node, &tmp)){
+      NumofLatch++;
+      nodeName = Ntk_NodeReadName(node);
+      if(st_lookup(pm->vertexTable,nodeName,NIL(char *)))
+	{
+	  array_insert_last(char *,visibleArray,nodeName);
+	  latch = Ntk_NetworkFindNodeByName(network,nodeName);
+	  PureSatComputeTableForLatch(network,pm->AbsTable,latch);
+	}
+      else
+	array_insert_last(char *,invisibleArray,nodeName);
+    }
+  }
+  t5 = util_cpu_ctime();
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"the time to cmpute abs table:%g\n",(t5-t3)/1000);
+  if(pm->verbosity>=1){
+    fprintf(vis_stdout,"visiblearray has %d latches\n",array_n(visibleArray));
+    fprintf(vis_stdout,"invisibleArray has %d latches\n",array_n(invisibleArray));
+  }
+  CoiArray = array_dup(visibleArray);
+  array_append(CoiArray,invisibleArray);
+
+  pm->nicTable = st_init_table(strcmp,st_strhash);
+  pm->niaTable = st_init_table(strcmp,st_strhash);
+  PureSatComputeNumGatesInCone(network,pm,CoiArray);
+  t3 = util_cpu_ctime();
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"the time to cmpute gates in cone:%g\n",(t3-t5)/1000);
+
+  /*Using DFS + Dir Cone in abs*/
+  pm->node2dfsTable = st_init_table(st_ptrcmp,st_ptrhash);
+
+
+  while(NumofCurrentLatch < NumofLatch)
+    {
+      t3 = util_cpu_ctime();
+      if(pm->verbosity>=1)
+	fprintf(vis_stdout,"Current Latches: %d, COI latches:%d,NEW Length:%d,\n",
+		NumofCurrentLatch,NumofLatch,pm->Length);
+      if(pm->verbosity>=2)
+	fprintf(vis_stdout,"General time: %g\n",(double)((t3-t0)/1000.0));
+      t1 = util_cpu_ctime();
+      tmpRefinement = array_alloc(char *,0);
+
+      memset(manager->ipm,0,sizeof(IP_Manager_t));
+      firstTime = TRUE;
+      pm->SufAbsTable = st_init_table(st_ptrcmp,st_ptrhash);
+      if(realRefine){
+	arrayForEachItem(char *,refinement,i,nodeName)
+	  {
+	    latch = Ntk_NetworkFindNodeByName(network,nodeName);
+	    PureSatComputeTableForLatch(network,pm->AbsTable,latch);
+	    st_insert(pm->vertexTable,nodeName,(char*)0);
+	  }
+	array_append(visibleArray,refinement);
+	array_free(invisibleArray);
+	invisibleArray = array_alloc(char *,0);
+	st_foreach_item(pm->CoiTable,stGen,&latch,&i)
+	  {
+	    nodeName = Ntk_NodeReadName(latch);
+	    if(!st_lookup(pm->vertexTable,nodeName,(char **)0)){
+	      array_insert_last(char *,invisibleArray,nodeName);
+	    }
+	  }
+	st_free_table(pm->node2dfsTable);
+	pm->node2dfsTable = st_init_table(st_ptrcmp,st_ptrhash);
+	arrayRC = PureSatComputeOrder_2(network,pm,visibleArray,invisibleArray,sccArray,&NumInSecondLevel);
+	t4 = util_cpu_ctime();
+	if(pm->verbosity>=2)
+	  fprintf(vis_stdout,"time for compute order: %g\n",(t4-t1)/1000);
+
+	if(pm->RefPredict){
+	  orderCt=0;
+	  if(array_n(pm->latchArray)>0){
+	    if(pm->verbosity>=1)
+	      fprintf(vis_stdout,"\n%d: Adding high RC value latch into abs model\n",orderCt++);
+	    PureSatAddIdenLatchToAbs(network,pm,pm->latchArray);
+	    NumofCurrentLatch+=array_n(pm->latchArray);
+	    arrayForEachItem(char *,pm->latchArray,i,nodeName){
+	      latch = Ntk_NetworkFindNodeByName(network,nodeName);
+	      PureSatComputeTableForLatch(network,pm->AbsTable,latch);
+	      st_insert(pm->vertexTable,nodeName,(char*)0);
+	    }
+	    array_append(visibleArray,pm->latchArray);
+	    array_free(pm->latchArray);
+	    array_free(invisibleArray);
+	    invisibleArray = array_alloc(char *,0);
+	    st_foreach_item(pm->CoiTable,stGen,&latch,&i)
+	      {
+		nodeName = Ntk_NodeReadName(latch);
+		if(!st_lookup(pm->vertexTable,nodeName,(char **)0)){
+		  array_insert_last(char *,invisibleArray,nodeName);
+		}
+	      }
+	    st_free_table(pm->node2dfsTable);
+	    pm->node2dfsTable = st_init_table(st_ptrcmp,st_ptrhash);
+	    arrayRC = PureSatComputeOrder_2(network,pm,visibleArray,invisibleArray,sccArray,&NumInSecondLevel);
+
+	  }
+	  array_free(pm->latchArray);
+	}
+
+	PureSat_CleanMask(manager,ResetVisibleVarMask);
+	PuresatMarkVisibleVar(network,visibleArray,pm,0,pm->Length);
+
+	addtoAbs =(int)((double)(array_n(CoiArray)-array_n(visibleArray))/(double)5)+1;
+	addtoAbs = addtoAbs >50 ? 50: addtoAbs;
+
+	array_free(invisibleArray);
+	invisibleArray = array_alloc(char *,0);
+	st_foreach_item(pm->CoiTable,stGen,&latch,&i)
+	  {
+	    nodeName = Ntk_NodeReadName(latch);
+	    if(!st_lookup(pm->vertexTable,nodeName,(char **)0)){
+	      array_insert_last(char *,invisibleArray,nodeName);
+	    }
+	  }
+	if(pm->verbosity>=1){
+	  fprintf(vis_stdout,"After adding high RC latches:\n");
+	  fprintf(vis_stdout,"visiblearray has %d latches\n",array_n(visibleArray));
+	  fprintf(vis_stdout,"invisibleArray has %d latches\n",array_n(invisibleArray));
+	}
+	t4 = util_cpu_ctime();
+	t4total += t4-t3;
+	if(pm->verbosity>=2)
+	  fprintf(vis_stdout,"compute and add high RC latch and recompute order:%g,total:%g\n",
+		 (t4-t3)/1000,(t4total/1000.0));
+
+	if(pm->verbosity>=1)
+	  fprintf(vis_stdout,"NumInSecondLevel is %d  ",NumInSecondLevel);
+	latchThreshHold = NumInSecondLevel;
+	if(pm->verbosity>=2){
+	  fprintf(vis_stdout,"New latchThreshHold is %d\n",latchThreshHold);
+	}
+	t2 = util_cpu_ctime();
+	if(pm->verbosity>=2){
+	  fprintf(vis_stdout,"Recompute Order: %g\n",(double)((t2-t1)/1000.0));
+	}
+	array_free(refinement);
+	refinement = array_alloc(char *,0);
+     }/* if(realRefine)*/
+
+     /* means no ref, just Length++.*/
+      realRefine =FALSE;
+      t1 = util_cpu_ctime();
+
+      ExistACE = PureSat_CheckAceByIP(network,pm,pism1, visibleArray,&Length,
+			      ltlFormula, &property,previousResultArray);
+      if(ExistACE)
+	{
+	  if(pm->returnVal == -1){
+	     PureSatIncreSATManagerFree(pm,pism1);
+	     /*PureSatManagerFree(pm);*/
+	     array_free(CoiArray);
+	     BmcOptionFree(options);
+	     return FALSE;
+	  }
+	  pm->Length = Length;
+	  pism1->Length = Length;
+	  t2 = util_cpu_ctime();
+	  pm->tIP += t2-t1;
+	  if(pm->verbosity>=2)
+	    fprintf(vis_stdout,"Solve on IP: %g, total: %g\n",
+		   (double)((t2-t1)/1000.0),(double)pm->tIP/1000.0);
+
+
+	  if(ExistACE)
+	    {
+	      int Con=0;
+	      if(pm->verbosity>=1)
+		fprintf(vis_stdout,"found Abstract Counterexample at length %d\n", pm->Length);
+	      realRefine = TRUE;
+
+	      /*incrementally check Concrete Model*/
+	      if(pm->verbosity>=1)
+		fprintf(vis_stdout,"Begin building a new abstract model\n");
+	      for(i=0;i<array_n(arrayRC);i=i+latchThreshHold)
+		{
+		  Con = 0;
+		  if(i>0)
+		    latchThreshHold = array_n(arrayRC)-latchThreshHold;
+		  for(j=0;j<latchThreshHold;j++)
+		    {
+		      if((i+j)<array_n(arrayRC))
+			{
+			  nodeName = array_fetch(char *,arrayRC,i+j);
+			  array_insert_last(char *,tmpRefinement,nodeName);
+			  if(pm->verbosity>=2)
+			    if(pm->verbosity>=2)
+			      fprintf(vis_stdout, "picking %s\n",nodeName);
+			  if((i+j)==(array_n(arrayRC)-1))
+			    Con = 1;
+			}
+		      else{
+			Con = 1;
+			break;
+		      }
+		    }/* for(j=0;*/
+		  tmpRefinement1=array_dup(visibleArray);
+		  array_append(tmpRefinement1,tmpRefinement);
+
+		  t1 = util_cpu_ctime();
+
+		  if(pm->verbosity>=2)
+		    satStat = 1;
+		  if(!PureSat_ConcretTest(network,pm,tmpRefinement1,property,previousResultArray,Con,satStat,1)){
+
+		    t2 = util_cpu_ctime();
+		    pm->tCon = pm->tCon+t2-t1;
+		    if(pm->verbosity>=2)
+		      fprintf(vis_stdout,"time for finding a sufficient set on model: %g, total:%g\n",
+			     (double)((t2-t1)/1000.0),(double)pm->tCon/1000.0);
+		    if((i+j)>=array_n(arrayRC)){
+		      fprintf(vis_stdout,"found real counterexamples\n");
+
+		      PureSatIncreSATManagerFree(pm, pism1);
+		      /*PureSatManagerFree(pm);*/
+		      array_free(CoiArray);
+		      BmcOptionFree(options);
+		      return FALSE;
+		    }
+		    /* else{
+		      ;
+		      }*/
+		  }
+		  else{
+		    t2 = util_cpu_ctime();
+		    pm->tCon = pm->tCon+t2-t1;
+		    if(pm->verbosity>=1)
+		      fprintf(vis_stdout,"found a sufficient model\n");
+		    if(pm->verbosity>=2)
+		      fprintf(vis_stdout,"time for finding a sufficient set on model: %g, total:%g\n",
+			     (double)((t2-t1)/1000.0),(double)pm->tCon/1000.0);
+		    firstTime = FALSE;
+		    arrayForEachItem(char *,tmpRefinement1,k,nodeName){
+		      node = Ntk_NetworkFindNodeByName(network, nodeName);
+		      if(!st_lookup(pm->SufAbsTable,(char *)node,NIL(char *)))
+			st_insert(pm->SufAbsTable,(char *)node, (char *)0);
+		      else{
+			fprintf(vis_stdout,"wrong in sufabstable \n");
+			exit(0);
+		      }
+		    }
+		    array_free(tmpRefinement1);
+		    break;
+		  }
+		  array_free(tmpRefinement1);
+		}
+
+	      t1 = util_cpu_ctime();
+
+#if 1
+	      if(pm->savedConCls){
+		sat_ArrayFree(pm->savedConCls);
+		pm->savedConCls = 0;
+	      }
+#endif
+#if SWITCH_DA
+	      refinement = PureSat_RefineOnAbs_DA(network,pm,property,previousResultArray,
+						  latchThreshHold,sccArray,tmpRefinement);
+#else
+	      refinement = PureSat_RefineOnAbs(network,pm,property,previousResultArray,
+					       latchThreshHold,sccArray,tmpRefinement);
+#endif
+	      array_free(tmpRefinement);
+	      t2 = util_cpu_ctime();
+	      pm->tRef = pm->tRef+t2-t1;
+	      if(pm->verbosity>=2)
+		fprintf(vis_stdout,"time for RefOnAbs: %g, total:%g\n",
+		       (t2-t1)/1000.0,pm->tRef/1000);
+	      st_free_table(pm->SufAbsTable);
+	      pm->SufAbsTable = 0;
+
+	      /*adjust parameters*/
+	      NumofCurrentLatch+=array_n(refinement);
+	      pm->Length++;
+	      pism1->Length++;
+	      Length++;
+	    }/* if(pism2->cm->status == SAT_SAT)*/
+	} /*if(ExistACE)*/
+      else /* if TRUE from IP*/
+	{
+	  t2 = util_cpu_ctime();
+	  pm->tIP = pm->tIP+t2-t1;
+	  if(pm->verbosity>=2)
+	    fprintf(vis_stdout,"Solve on IP: %g, total: %g\n",
+		   (t2-t1)/1000.0,pm->tIP/1000.0);
+	  fprintf(vis_stdout,"Convergence reached, exit\n");
+	  PureSatIncreSATManagerFree(pm,pism1);
+	  /*PureSatManagerFree(pm);*/
+	  array_free(CoiArray);
+	  BmcOptionFree(options);
+	  return TRUE;
+	}
+    }/* while(NumofCurrentLatch < NumofLatch)*/
+  /*st_free_table(AbsTable);*/
+
+  /*Now go to the concrete model*/
+  if(pm->verbosity>=1)
+    fprintf(vis_stdout,"reach concrete model\n");
+  array_append(visibleArray,refinement);
+  array_free(refinement);
+
+
+  ExistACE = PureSatIPOnCon(network,ltlFormula,pm);
+  ExistACE = !ExistACE;
+  PureSatIncreSATManagerFree(pm,pism1);
+  /*PureSatManagerFree(pm);*/
+  array_free(CoiArray);
+  BmcOptionFree(options);
+  if(ExistACE)
+    return FALSE;
+  else
+    return TRUE;
+}
Index: vis_dev/vis-2.3/src/puresat/puresatIPRefine.c
===================================================================
--- vis_dev/vis-2.3/src/puresat/puresatIPRefine.c	(revision 14)
+++ vis_dev/vis-2.3/src/puresat/puresatIPRefine.c	(revision 14)
@@ -0,0 +1,932 @@
+/**CFile***********************************************************************
+
+  FileName    [puresatIPRefine.c]
+
+  PackageName [puresat]
+
+  Synopsis    [Abstraction refinement for large scale invariant checking.]
+
+  Description [This file contains the functions to check invariant properties
+  by the PureSAT abstraction refinement algorithm, which is entirely based on
+  SAT solver, the input of which could be either CNF or AIG. It has several
+  parts:
+
+  * Localization-reduction base Abstraction
+  * K-induction or interpolation to prove the truth of a property
+  * Bounded Model Checking to find bugs
+  * Incremental concretization based methods to verify abstract bugs
+  * Incremental SAT solver to improve efficiency
+  * UNSAT proof based method to obtain refinement
+  * AROSAT to bring in only necessary latches into unsat proofs
+  * Bridge abstraction to get compact coarse refinement
+  * Refinement minization to guarrantee minimal refinements
+  * Unsat proof-based refinement minimization to eliminate multiple candidate
+    by on SAT test
+  * Refinement prediction to decrease the number of refinement iterations
+  * Dynamic switching to redistribute computional resources to improve
+    efficiency
+
+  For more information, please check the BMC'03, ICCAD'04, STTT'05 and TACAS'05
+  paper of Li et al., "A satisfiability-based appraoch to abstraction
+  refinement in model checking", " Abstraction in symbolic model checking
+  using satisfiability as the only decision procedure", "Efficient computation
+  of small abstraction refinements", and "Efficient abstraction refinement in
+  interpolation-based unbounded model checking"]
+
+  Author      [Bing Li]
+
+  Copyright   [Copyright (c) 2004 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without
+  license or royalty fees, to use, copy, modify, and distribute this
+  software and its documentation for any purpose, provided that the
+  above copyright notice and the following two paragraphs appear in
+  all copies of this software.]
+
+******************************************************************************/
+#include "puresatInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Generate sufficient set from unsat proof]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+#if UNSATCORE
+void PureSat_GetSufAbsFromCoreRecur(mAig_Manager_t *manager,
+				    satManager_t * cm,
+				    RTnode_t RTnode,
+				    st_table *ctTable,
+				    st_table *refineTable,
+				    FILE * fp)
+#else
+void PureSat_GetSufAbsFromCoreRecur(mAig_Manager_t *manager,
+				    satManager_t * cm,
+				    RTnode_t RTnode,
+				    st_table *ctTable,
+				    st_table *refineTable)
+#endif
+{
+  int i,ct;
+  bAigTimeFrame_t *tf = manager->timeframeWOI;
+  char *name;
+  bAigEdge_t v,*lp;
+  st_table *table;
+  st_generator *stgen;
+  RTManager_t * rm = cm->rm;
+
+  if(RT_flag(RTnode)&RT_VisitedMask)
+    return;
+
+  RT_flag(RTnode) |= RT_VisitedMask;
+  /*leaf*/
+  if(RT_pivot(RTnode)==0){
+#if DBG
+    assert(RT_oriClsIdx(RTnode)==0);
+#endif
+    if(RT_oriClsIdx(RTnode)!=0)
+      lp = (long*)SATfirstLit(RT_oriClsIdx(RTnode));
+    else
+
+      lp = RT_formula(RTnode) + cm->rm->fArray;
+    for(i=0;i<RT_fSize(RTnode);i++,lp++){
+      if(RT_oriClsIdx(RTnode)!=0)
+	v = SATgetNode(*lp);
+      else
+	v = *lp;
+      if(*lp<0)
+	continue;
+
+#if UNSATCORE
+      v = SATnormalNode(v);
+      fprintf(fp,"%d_%d ",v,SATclass(v));
+      if(SATflags(v)&DummyMask)
+	fprintf(fp,"DM ");
+      if(SATflags(v)&VisibleVarMask)
+	fprintf(fp,"Visible  ");
+      else
+	if(SATflags(v)&StateBitMask)
+	  fprintf(fp, "InvSV  ");
+
+#endif
+      v = SATnormalNode(v);
+      if((SATflags(v)&VisibleVarMask)){
+
+	if(SATclass(v)==0){
+	  if(!st_lookup(tf->idx2name,(char*)v,&name)&&
+	     !st_lookup(tf->MultiLatchTable,(char*)v,&table))
+	    continue;
+	}
+#if 1
+	/* at least 2 times to be choosen as a candidate*/
+	if(st_lookup(ctTable,(char*)v,&ct)){
+	  if(ct<0)
+	    continue;
+	  if(ct>=1){
+
+	    if(!st_lookup(tf->MultiLatchTable,(char*)v,&table)){
+	      int retVal = st_lookup(tf->idx2name,(char*)v,&name);
+	      assert(retVal);
+	      st_insert(refineTable,(char*)name,(char*)0);
+	      st_insert(ctTable,(char*)v,(char*)-1);
+
+	    }
+	    else{
+#ifdef TIMEFRAME_VERIFY_
+	      fprintf(vis_stdout,"%d is in MultiLatchTable: ",v);
+#endif
+	      st_foreach_item(table,stgen,(char**)&name,
+			      NIL(char*)){
+#ifdef TIMEFRAME_VERIFY_
+		fprintf(vis_stdout,"%s   ",name);
+#endif
+		st_insert(refineTable,(char*)name,(char*)0);
+	      }
+#ifdef TIMEFRAME_VERIFY_
+	      fprintf(vis_stdout,"\n");
+#endif
+	      st_insert(ctTable,(char*)v,(char*)-1);
+	    }
+	  }
+	}
+	else{
+	  ct=1;
+	  st_insert(ctTable,(char*)v,(char*)(long)ct);
+	}
+#else
+	retVal = st_lookup(tf->idx2name,(char*)v,(char**)&name);
+	assert(retVal);
+	st_insert(refineTable,(char*)name,(char*)0);
+
+#endif
+      }/* if(SATflags(v)&StateBitMask){*/
+    }
+#if UNSATCORE
+    fprintf(fp,"0\n");
+#endif
+  }
+  /*non leaf*/
+  else{
+    assert(RT_left(RTnode)!=RT_NULL&&RT_right(RTnode)!=RT_NULL);
+#if UNSATCORE
+    PureSat_GetSufAbsFromCoreRecur(manager,cm,RT_left(RTnode),
+				   ctTable,refineTable,fp);
+    PureSat_GetSufAbsFromCoreRecur(manager,cm,RT_right(RTnode),
+				   ctTable,refineTable,fp);
+#else
+    PureSat_GetSufAbsFromCoreRecur(manager,cm,RT_left(RTnode),
+				   ctTable,refineTable);
+    PureSat_GetSufAbsFromCoreRecur(manager,cm,RT_right(RTnode),
+				   ctTable,refineTable);
+#endif
+  }
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Generate sufficient set from unsat proof by bridge abstraction]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+//new pick latch
+#if UNSATCORE
+void PureSat_GetSufAbsFromCoreRecur_2side(mAig_Manager_t *manager,
+					  satManager_t * cm,
+					  RTnode_t RTnode,
+					  st_table *ctTable,
+					  st_table *refineTable,
+					  st_table *SufNameTable,
+					  FILE * fp)
+#else
+void PureSat_GetSufAbsFromCoreRecur_2side(mAig_Manager_t *manager,
+					  satManager_t * cm,
+					  RTnode_t RTnode,
+					  st_table *ctTable,
+					  st_table *refineTable,
+					  st_table *SufNameTable)
+#endif
+{
+  int i,j,find,find1,times;
+  bAigTimeFrame_t *tf = manager->timeframeWOI;
+  char *name,*name1;
+  bAigEdge_t v,v1,*lp,*lp1, *lp2, left,right;
+  st_table *table;
+  st_generator *stgen;
+  RTManager_t * rm = cm->rm;
+  long maxNode;
+
+  if(RT_flag(RTnode)&RT_VisitedMask)
+    return;
+
+  RT_flag(RTnode) |= RT_VisitedMask;
+
+  if(RT_pivot(RTnode)==0){
+#if DBG
+    assert(RT_oriClsIdx(RTnode)==0);
+#endif
+    if(RT_oriClsIdx(RTnode)!=0)
+      lp = (long*)SATfirstLit(RT_oriClsIdx(RTnode));
+    else
+
+      lp = RT_formula(RTnode) + cm->rm->fArray;
+    lp1 = lp;
+    (cm->line)++;
+    for(i=0;i<RT_fSize(RTnode);i++,lp++){
+      if(RT_oriClsIdx(RTnode)!=0)
+	v = SATgetNode(*lp);
+      else
+	v = *lp;
+      if(*lp<0)
+	continue;
+#if UNSATCORE
+      v = SATnormalNode(v);
+      fprintf(fp,"%d_%d ",v,SATclass(v));
+      if(SATflags(v)&DummyMask)
+	fprintf(fp,"DM ");
+      if(SATflags(v)&VisibleVarMask)
+	fprintf(fp,"Visible  ");
+      else
+	if(SATflags(v)&StateBitMask)
+	  fprintf(fp, "InvSV  ");
+
+#endif
+      v = SATnormalNode(v);
+#if LAI
+      /*mark every node in core for latch interface abs*/
+      flags(v) |= VisitedMask;
+#endif
+      if(SATflags(v)&VisibleVarMask){
+	if((SATclass(v)==0)&&
+	   (st_lookup(tf->idx2name,(char*)v,&name)==0)&&
+	   (st_lookup(tf->MultiLatchTable,(char*)v,&table)==0))
+	    continue;
+
+	lp2 = lp1;
+	left = SATnormalNode(leftChild(v));
+	right = SATnormalNode(rightChild(v));
+	//find largest node
+	maxNode = -1;
+	for(j=0;j<RT_fSize(RTnode);j++,lp2++){
+	  if(RT_oriClsIdx(RTnode)!=0)
+	    v1 = SATgetNode(*lp2);
+	  else
+	    v1 = *lp2;
+	  if(maxNode < SATnormalNode(v1))
+	    maxNode = SATnormalNode(v1);
+	}
+	if(maxNode == v){
+#if DBG
+	  lp2 = lp1;
+	  for(j=0;j<RT_fSize(RTnode);j++,lp2++){
+	    if(RT_oriClsIdx(RTnode)!=0)
+	      v1 = SATgetNode(*lp2);
+	    else
+	      v1 = *lp2;
+	    if(*lp2<0||SATnormalNode(v1)==v)
+	      continue;
+	    assert((SATnormalNode(v1) == SATnormalNode(leftChild(v)))||
+		   SATnormalNode(v1) == SATnormalNode(rightChild(v)));
+	  }
+#endif
+	  SATflags(v) |= Visited2Mask; /*left side*/
+	}
+	else{
+#if DBG
+	  lp2 = lp1;
+	  for(j=0;j<RT_fSize(RTnode);j++,lp2++){
+	    if(RT_oriClsIdx(RTnode)!=0)
+	      v1 = SATgetNode(*lp2);
+	    else
+	      v1 = *lp2;
+	    if(*lp2<0||SATnormalNode(v1)==maxNode)
+	      continue;
+	    assert((SATnormalNode(v1) == SATnormalNode(leftChild(maxNode)))||
+		   (SATnormalNode(v1) == SATnormalNode(rightChild(maxNode))));
+	  }
+#endif
+	  SATflags(v) |= Visited3Mask; /*right side*/
+#if THROUGHPICK
+	  /*pick latch due to split*/
+	    if(SATflags(v)&VPGVMask){
+	      if(SATclass(maxNode)<=1)
+		SATflags(v) |= NewMask; /*the same tf*/
+	      else
+		SATflags(v) |= Visited4Mask; /* larger tf*/
+	    }
+#endif
+	}
+
+      }
+
+#if THROUGHPICK
+      if((SATflags(v)&VisibleVarMask)&&
+	 (((SATflags(v)&Visited2Mask)&&(SATflags(v)&Visited3Mask))||
+	 ((SATflags(v)&Visited4Mask)&&(SATflags(v)&NewMask)))){
+#else
+      if((SATflags(v)&VisibleVarMask)&&
+	 ((SATflags(v)&Visited2Mask)&&(SATflags(v)&Visited3Mask))){
+#endif
+	times = 1;
+	if(!st_lookup(tf->MultiLatchTable,(char*)v,&table)){
+	  int retVal = st_lookup(tf->idx2name,(char*)v,&name);
+	  assert(retVal);
+
+	  if(st_lookup(refineTable,(char*)name,&times))
+	    times++;
+	  st_insert(refineTable,(char*)name,(char*)(long)times);
+	}
+
+	/*for iden latches, we only add one, which is enough*/
+	else{
+	  find = 0;
+	  find1 = 0;
+	  st_foreach_item(table,stgen,(char**)&name,
+			  NIL(char*)){
+	    if(st_lookup(refineTable,name,NIL(char*))){
+	      find = 1;
+	      break;
+	    }
+	    if(find1==0){
+	      if(st_lookup(SufNameTable,name, NIL(char*))){
+		name1 = name;
+		find1 = 1;
+	      }
+	    }
+	  }
+	  if(find==0){
+	    times = 1;
+	    if(st_lookup(refineTable,(char*)name1,&times))
+	      times++;
+	    st_insert(refineTable,(char*)name1,(char*)(long)times);
+
+	  }
+	}
+
+
+      }
+    }
+#if UNSATCORE
+   fprintf(fp,"0\n");
+#endif
+  }
+    /*non leaf*/
+  else{
+    assert(RT_left(RTnode)!=RT_NULL&&RT_right(RTnode)!=RT_NULL);
+#if UNSATCORE
+    PureSat_GetSufAbsFromCoreRecur_2side(manager,cm,RT_left(RTnode),
+				   ctTable,refineTable,SufNameTable,fp);
+    PureSat_GetSufAbsFromCoreRecur_2side(manager,cm,RT_right(RTnode),
+				   ctTable,refineTable,SufNameTable,fp);
+#else
+    PureSat_GetSufAbsFromCoreRecur_2side(manager,cm,RT_left(RTnode),
+				   ctTable,refineTable,SufNameTable);
+    PureSat_GetSufAbsFromCoreRecur_2side(manager,cm,RT_right(RTnode),
+				   ctTable,refineTable,SufNameTable);
+#endif
+  }
+  return;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generate sufficient set from unsat proof]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+array_t * PureSat_GetSufAbsFromCore(Ntk_Network_t *network,
+				    satManager_t * cm,
+				    PureSat_Manager_t *pm,
+				    bAigEdge_t property,
+				    st_table * SufAbsNameTable)
+{
+  array_t * refArray = array_alloc(char *,0);
+  char *name;
+  st_generator *stgen;
+  Ntk_Node_t *latch;
+  bAig_Manager_t * manager = Ntk_NetworkReadMAigManager(network);
+  st_table * ctTable = st_init_table(st_numcmp,st_numhash);
+  st_table * refineTable = st_init_table(strcmp,st_strhash);
+  int times;
+#if UNSATCORE
+  FILE * fp = fopen("unsatcore.txt","w");
+#endif
+#if LAI
+  st_table * refineTable1 = st_init_table(strcmp,st_strhash);
+
+#endif
+
+
+  PureSat_CleanMask(manager,ResetVisited1234NewMask);
+#if UNSATCORE
+  fprintf(fp,"p cnf %d line, # nodes:%d\n",
+	  cm->initNumVariables,cm->nodesArraySize);
+  cm->line = 0;
+  PureSat_GetSufAbsFromCoreRecur_2side(manager,cm,cm->rm->root,
+				 ctTable,refineTable,SufAbsNameTable,fp);
+  fprintf(fp,"total lines: %d\n",cm->line);
+#else
+  PureSat_GetSufAbsFromCoreRecur_2side(manager,cm,cm->rm->root,
+				 ctTable,refineTable,SufAbsNameTable);
+
+#endif
+  PureSat_CleanMask(manager,ResetVisited1234NewMask);
+
+#if LAI
+  ResetRTree(cm->rm);
+  PureSat_GetLIAForNode(manager,property);
+  PureSat_GetSufAbsByLIA(manager,cm,cm->rm->root,
+			refineTable1);
+#endif
+
+
+  st_foreach_item(refineTable,stgen,&name,&times){
+    latch = Ntk_NetworkFindNodeByName(network,name);
+
+    if(!st_lookup(pm->vertexTable,(char*)name,NIL(char*))&&
+      st_lookup(pm->SufAbsTable, (char*)latch,NIL(char*))){
+      array_insert_last(char *,refArray,name);
+      if(pm->verbosity>=2)
+	fprintf(vis_stdout,"ref cand:%s %d\n",name,times);
+    }
+  }
+
+#if LAI
+  st_foreach_item(refineTable1,stgen,(char**)&name,NIL(char*)){
+    latch = Ntk_NetworkFindNodeByName(network,name);
+    if(!st_lookup(pm->vertexTable,(char*)name,NIL(char*))&&
+       st_lookup(pm->CoiTable, (char*)latch,NIL(char*))){
+      if(pm->verbosity>=2)
+	fprintf(vis_stdout,"from LIA ref candidate:%s\n",name);
+
+    }
+  }
+#endif
+
+#if UNSATCORE
+  fclose(fp);
+#endif
+
+  st_free_table(ctTable);
+  st_free_table(refineTable);
+#if LAI
+  st_free_table(refineTable1);
+#endif
+  return refArray;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Main procedure of refinement computation]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+array_t *PureSat_RefineOnAbs(Ntk_Network_t *network,
+			     PureSat_Manager_t *pm,
+			     bAigEdge_t property,
+			     array_t *previousResultArray,
+			     int latchThreshHold,
+			     int * sccArray,
+			     array_t * sufArray)
+{
+  array_t * tmpRef,*tmpRef1,*tmpRef2,*tmpRef3;
+  array_t * tmpModel = array_alloc(char *,0),*tmpArray1,*tmpArray2;
+  satManager_t *cm;
+  mAig_Manager_t * manager = Ntk_NetworkReadMAigManager(network);
+  st_table *table;
+  char * name;
+  int i,j;
+  int NumInSecondLevel;
+  st_generator *stgen;
+  Ntk_Node_t *latch;
+  double t1,t2,t3,t4;
+  st_table * SufAbsNameTable = st_init_table(strcmp,st_strhash);
+  st_table * junkTable;
+  int noArosat = 1;
+
+
+  tmpRef = array_alloc(char *,0);
+  st_foreach_item(pm->SufAbsTable,stgen,&latch,NIL(char*)){
+    name = Ntk_NodeReadName(latch);
+    if(st_lookup(pm->vertexTable,name,NIL(char *)))
+      array_insert_last(char *,tmpModel,name);
+    array_insert_last(char *,tmpRef,name);
+    st_insert(SufAbsNameTable,name,(char *)0);
+
+  }
+
+  t1 = util_cpu_ctime();
+  manager->assertArray = sat_ArrayAlloc(1);
+  sat_ArrayInsert(manager->assertArray,manager->InitState);
+  cm = PureSat_SatManagerAlloc_WOCOI(manager,pm,property,previousResultArray);
+  if(pm->Arosat){
+    cm->option->decisionHeuristic &= RESET_LC;
+    cm->option->decisionHeuristic |= DVH_DECISION;
+    cm->option->arosat = 1;
+  }
+  cm->option->coreGeneration = 1;
+  cm->option->AbRf = 1;
+  cm->property = property;
+  cm->option->IP = 1;
+  PureSat_CleanMask(manager,ResetVisibleVarMask);
+  PuresatMarkVisibleVarWithVPGV(network,tmpRef,pm,0,pm->Length+1);
+  array_free(tmpRef);
+  t3 = util_cpu_ctime();
+  PureSatPreprocess(network,cm,pm,SufAbsNameTable,pm->Length);
+  t4 = util_cpu_ctime();
+  pm->tPro += t4-t3;
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"process time:%g,total:%g\n",
+	   (double)((t4-t3)/1000.0),pm->tPro/1000);
+
+  if(cm->option->arosat){
+    PureSatCreateLayer(network,pm,cm,tmpModel,sufArray);
+    cm->Length = pm->Length;
+    AS_Main(cm);
+    noArosat = 0;
+    st_foreach_item(cm->layerTable,stgen,&table,NIL(char*))
+      st_free_table(table);
+    st_free_table(cm->layerTable);
+    FREE(cm->assignedArray);
+    FREE(cm->numArray);
+  }
+  else
+    sat_Main(cm);
+
+  manager->NodesArray = cm->nodesArray;;
+  assert(cm->status==SAT_UNSAT);
+  t3 = util_cpu_ctime();
+  PureSatPostprocess(manager,cm,pm);
+  PureSatProcessDummy(manager,cm,cm->rm->root);
+  ResetRTree(cm->rm);
+  t4 = util_cpu_ctime();
+  pm->tPro += t4-t3;
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"process time:%g,total:%g\n",
+	   (double)((t4-t3)/1000.0),pm->tPro/1000);
+  t2 = util_cpu_ctime();
+  pm->tCoreGen += t2 - t1;
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"time for UNsat core generation:%g,total:%g\n",
+	   (double)(t2-t1)/1000.0,pm->tCoreGen/1000.0);
+
+  t1 = util_cpu_ctime();
+  tmpRef1 = PureSat_GetSufAbsFromCore(network,cm,pm,property,SufAbsNameTable);
+  t2 = util_cpu_ctime();
+
+  st_free_table(SufAbsNameTable);
+  RT_Free(cm->rm);
+  sat_ArrayFree(manager->assertArray);
+  PureSat_SatFreeManager(cm);
+
+  /*Get suff set*/
+  tmpRef2 = array_alloc(char *,0);
+  tmpRef3 = array_alloc(char *,0);
+  tmpArray1 = array_alloc(char *,0);
+  tmpArray2 = array_alloc(char *,0);
+
+  if(noArosat){
+    t1 = util_cpu_ctime();
+    if(array_n(tmpRef1)){
+      tmpRef = PureSatGenerateRCArray_2(network,pm,tmpRef1,
+					&NumInSecondLevel);
+      array_free(pm->latchArray);
+    }
+
+  }
+  else{
+    if(array_n(tmpRef1)){
+      tmpRef = PureSatGenerateRCArray_2(network,pm,tmpRef1,
+					&NumInSecondLevel);
+      array_free(pm->latchArray);
+    }
+    else
+      tmpRef = array_alloc(char*,0);
+#if NOREFMIN
+    if(pm->verbosity>=1){
+      fprintf(vis_stdout,"\n sufficient refinement candidates from CA\n");
+      arrayForEachItem(char *,tmpRef,i,name)
+	fprintf(vis_stdout,"%s\n",name);
+    }
+    PureSatAddIdenLatchToAbs(network,pm,tmpRef);
+    array_free(tmpRef1);
+    array_free(tmpModel);
+    return tmpRef;
+#endif
+  }
+
+
+  /*Ref Minimization
+    //try all the candidates*/
+  t1 = util_cpu_ctime();
+
+  if(pm->CoreRefMin && array_n(tmpRef)>=5){
+    if(pm->verbosity>=1)
+      fprintf(vis_stdout,"Core Ref Min\n");
+    junkTable = st_init_table(strcmp,st_strhash);
+    for(i=array_n(tmpRef)-1;i>=0;i--)
+      {
+	array_t * tmpA;
+	name = array_fetch(char *,tmpRef,i);
+	if(pm->verbosity>=1)
+	  fprintf(vis_stdout,"RefMin: testing %s\n",name);
+	tmpArray2 = PureSatRemove_char(tmpRef,i);
+	if(st_lookup(junkTable,name,NIL(char))){
+	  array_free(tmpRef);
+	  tmpRef = tmpArray2;
+	  if(pm->verbosity>=1)
+	    fprintf(vis_stdout,"%s is junk\n",name);
+	  continue;
+	}
+	tmpA = array_dup(tmpModel);
+	array_append(tmpA,tmpArray2);
+
+	t3 = util_cpu_time();
+	tmpArray1 = array_alloc(char*,0);
+	arrayForEachItem(char*,tmpA,j,name)
+	  if(!st_lookup(junkTable,name,NIL(char)))
+	    array_insert_last(char*,tmpArray1,name);
+	array_free(tmpA);
+
+	if(!PureSat_ConcretTest_Core(network,pm,tmpArray1,property,
+				     previousResultArray,junkTable)){
+	  /*then the candidate can' be deleted*/
+	  t4 = util_cpu_time();
+	  if(pm->verbosity>=2)
+	    fprintf(vis_stdout," %g\n",(t4-t3)/1000);
+	  array_free(tmpArray2);
+	}
+	else /*delete it*/
+	  {
+	    t4 = util_cpu_time();
+	    if(pm->verbosity>=2)
+	      fprintf(vis_stdout,"time: %g\n",(t4-t3)/1000);
+	    array_free(tmpRef);
+	    tmpRef = tmpArray2;
+	  }
+	array_free(tmpArray1);
+      }
+    st_free_table(junkTable);
+  }
+  else{
+    for(i=array_n(tmpRef)-1;i>=0;i--)
+      {
+	name = array_fetch(char *,tmpRef,i);
+
+	if(pm->verbosity>=1)
+	  fprintf(vis_stdout,"RefMin: testing %s\n",name);
+	tmpArray2 = PureSatRemove_char(tmpRef,i);
+	tmpArray1 = array_dup(tmpModel);
+	array_append(tmpArray1,tmpArray2);
+
+	t3 = util_cpu_time();
+	if(!PureSat_ConcretTest(network,pm,tmpArray1,property,
+				previousResultArray,0,0,0)){
+	  t4 = util_cpu_time();
+	  if(pm->verbosity>=2)
+	    fprintf(vis_stdout," %g\n",(t4-t3)/1000);
+	  array_free(tmpArray2);
+	}
+	else /*delete it*/
+	  {
+	    t4 = util_cpu_time();
+	    if(pm->verbosity>=2)
+	      fprintf(vis_stdout,"time: %g\n",(t4-t3)/1000);
+	    array_free(tmpRef);
+	    tmpRef = tmpArray2;
+	  }
+	array_free(tmpArray1);
+      }
+  }
+
+
+  t2 = util_cpu_ctime();
+  pm->tRefMin += t2 - t1;
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"\ntime for Ref Min: %g, total:%g\n",
+	   (t2-t1)/1000,pm->tRefMin/1000);
+  if(pm->verbosity>=1){
+    fprintf(vis_stdout,"\n sufficient refinement candidates from CA\n");
+    arrayForEachItem(char *,tmpRef,i,name)
+      fprintf(vis_stdout,"%s\n",name);
+  }
+  PureSatAddIdenLatchToAbs(network,pm,tmpRef);
+  array_free(tmpRef1);
+  array_free(tmpModel);
+  return tmpRef;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Refinement procedure without refinement minimization]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+array_t *PureSat_RefineOnAbs_DA(Ntk_Network_t *network,
+			     PureSat_Manager_t *pm,
+			     bAigEdge_t property,
+			     array_t *previousResultArray,
+			     int latchThreshHold,
+			     int * sccArray,
+			     array_t * sufArray)
+{
+  array_t * tmpRef,*tmpRef1,*tmpRef2,*tmpRef3; //= array_alloc(char *,0);
+  array_t * tmpModel = array_alloc(char *,0),*tmpArray1,*tmpArray2;
+  satManager_t *cm;
+  mAig_Manager_t * manager = Ntk_NetworkReadMAigManager(network);
+  st_table *table;
+  char * name;
+  int i;
+  int NumInSecondLevel;
+  st_generator *stgen;
+  Ntk_Node_t *latch;
+  double t1,t2,t3,t4;
+  st_table * SufAbsNameTable = st_init_table(strcmp,st_strhash);
+  int noArosat = 1;
+
+
+  tmpRef = array_alloc(char *,0);
+  st_foreach_item(pm->SufAbsTable,stgen,&latch,NIL(char*)){
+    name = Ntk_NodeReadName(latch);
+    if(st_lookup(pm->vertexTable,name,NIL(char *)))
+      array_insert_last(char *,tmpModel,name);
+    array_insert_last(char *,tmpRef,name);
+    st_insert(SufAbsNameTable,name,(char *)0);
+
+  }
+
+  t1 = util_cpu_ctime();
+  manager->assertArray = sat_ArrayAlloc(1);
+  sat_ArrayInsert(manager->assertArray,manager->InitState);
+  cm = PureSat_SatManagerAlloc_WOCOI(manager,pm,property,previousResultArray);
+#if AROSAT
+  cm->option->decisionHeuristic &= RESET_LC;
+  cm->option->decisionHeuristic |= DVH_DECISION;
+  cm->option->arosat = 1;
+#endif
+  cm->option->coreGeneration = 1;
+  cm->option->AbRf = 1;
+
+  cm->option->IP = 1;
+  cm->property = property;
+  PureSat_CleanMask(manager,ResetVisibleVarMask);
+  PuresatMarkVisibleVarWithVPGV(network,tmpRef,pm,0,pm->Length+1);
+  array_free(tmpRef);
+  t3 = util_cpu_ctime();
+  PureSatPreprocess(network,cm,pm,SufAbsNameTable,pm->Length);
+  t4 = util_cpu_ctime();
+  pm->tPro += t4-t3;
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"process time:%g,total:%g\n",
+	   (double)((t4-t3)/1000.0),pm->tPro/1000);
+#if DBG
+  PureSatCheckCoi(manager);
+#endif
+  if(cm->option->arosat){
+    PureSatCreateLayer(network,pm,cm,tmpModel,sufArray);
+    cm->Length = pm->Length;
+    AS_Main(cm);
+    noArosat = 0;
+    st_foreach_item(cm->layerTable,stgen,&table,NIL(char*))
+      st_free_table(table);
+    st_free_table(cm->layerTable);
+    FREE(cm->assignedArray);
+    FREE(cm->numArray);
+  }
+  else
+    sat_Main(cm);
+  manager->NodesArray = cm->nodesArray;;
+  assert(cm->status==SAT_UNSAT);
+  t3 = util_cpu_ctime();
+  PureSatPostprocess(manager,cm,pm);
+  PureSatProcessDummy(manager,cm,cm->rm->root);
+  ResetRTree(cm->rm);
+  t4 = util_cpu_ctime();
+  pm->tPro += t4-t3;
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"process time:%g,total:%g\n",
+	   (double)((t4-t3)/1000.0),pm->tPro/1000);
+  t2 = util_cpu_ctime();
+  pm->tCoreGen += t2 - t1;
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"time for UNsat core generation:%g,total:%g\n",
+	   (double)(t2-t1)/1000.0,pm->tCoreGen/1000.0);
+#if DBG
+  PureSat_CheckFanoutFanin(manager);
+#endif
+  t1 = util_cpu_ctime();
+  tmpRef1 = PureSat_GetSufAbsFromCore(network,cm,pm,property,SufAbsNameTable);
+  t2 = util_cpu_ctime();
+
+  st_free_table(SufAbsNameTable);
+  RT_Free(cm->rm);
+  sat_ArrayFree(manager->assertArray);
+  PureSat_SatFreeManager(cm);
+
+  /*Get suff set*/
+
+  tmpRef2 = array_alloc(char *,0);
+  tmpRef3 = array_alloc(char *,0);
+  tmpArray1 = array_alloc(char *,0);
+  tmpArray2 = array_alloc(char *,0);
+
+  if(noArosat){
+    t1 = util_cpu_ctime();
+    if(array_n(tmpRef1)){
+     tmpRef = PureSatGenerateRCArray_2(network,pm,tmpRef1,
+					&NumInSecondLevel);
+
+      array_free(pm->latchArray);
+    }
+  }
+  /*if arosat*/
+  else{
+    if(array_n(tmpRef1)){
+      tmpRef = PureSatGenerateRCArray_2(network,pm,tmpRef1,
+					&NumInSecondLevel);
+      array_free(pm->latchArray);
+    }
+    else
+      tmpRef = array_alloc(char*,0);
+
+    if(pm->verbosity>=1){
+      fprintf(vis_stdout,"\n sufficient refinement candidates from CA\n");
+      arrayForEachItem(char *,tmpRef,i,name)
+	fprintf(vis_stdout,"%s\n",name);
+    }
+    PureSatAddIdenLatchToAbs(network,pm,tmpRef);
+    array_free(tmpRef1);
+    array_free(tmpModel);
+    return tmpRef;
+  }
+}
Index: vis_dev/vis-2.3/src/puresat/puresatIPUtil.c
===================================================================
--- vis_dev/vis-2.3/src/puresat/puresatIPUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/puresat/puresatIPUtil.c	(revision 14)
@@ -0,0 +1,3916 @@
+/**CFile***********************************************************************
+
+  FileName    [puresatIPUtil.c]
+
+  PackageName [puresat]
+
+  Synopsis    [Abstraction refinement for large scale invariant checking.]
+
+  Description [This file contains the functions to check invariant properties
+  by the PureSAT abstraction refinement algorithm, which is entirely based on
+  SAT solver, the input of which could be either CNF or AIG. It has several
+  parts:
+
+  * Localization-reduction base Abstraction
+  * K-induction or interpolation to prove the truth of a property
+  * Bounded Model Checking to find bugs
+  * Incremental concretization based methods to verify abstract bugs
+  * Incremental SAT solver to improve efficiency
+  * UNSAT proof based method to obtain refinement
+  * AROSAT to bring in only necessary latches into unsat proofs
+  * Bridge abstraction to get compact coarse refinement
+  * Refinement minization to guarrantee minimal refinements
+  * Unsat proof-based refinement minimization to eliminate multiple candidate
+    by on SAT test
+  * Refinement prediction to decrease the number of refinement iterations
+  * Dynamic switching to redistribute computional resources to improve
+    efficiency
+
+  For more information, please check the BMC'03, ICCAD'04, STTT'05 and TACAS'05
+  paper of Li et al., "A satisfiability-based appraoch to abstraction
+  refinement in model checking", " Abstraction in symbolic model checking
+  using satisfiability as the only decision procedure", "Efficient computation
+  of small abstraction refinements", and "Efficient abstraction refinement in
+  interpolation-based unbounded model checking"]
+
+  Author      [Bing Li]
+
+  Copyright   [Copyright (c) 2004 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without
+  license or royalty fees, to use, copy, modify, and distribute this
+  software and its documentation for any purpose, provided that the
+  above copyright notice and the following two paragraphs appear in
+  all copies of this software.]
+
+******************************************************************************/
+
+#include "puresatInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+/**Function********************************************************************
+
+  Synopsis    [Comparison function for sorting]
+
+  Description [Comparison function for sorting]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+static int
+NodeIndexCompare(const void *x, const void *y)
+{
+int n1, n2;
+
+  n1 = *(int *)x;
+  n2 = *(int *)y;
+  return(n1 > n2);
+}
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+static int
+StringCheckIsInteger(
+  char *string,
+  int *value)
+{
+  char *ptr;
+  long l;
+
+  l = strtol (string, &ptr, 0) ;
+  if(*ptr != '\0')
+    return 0;
+  if ((l > MAXINT) || (l < -1 - MAXINT))
+    return 1 ;
+  *value = (int) l;
+  return 2 ;
+}
+
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Create a node for resolution tree]
+
+  Description [Create a node for resolution tree]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+RTnode_t RTCreateNode(RTManager_t * rm)
+{
+  RTnode_t node;
+
+  if(rm->nArray==0){
+    rm->nArray = ALLOC(long, RTnodeSize*RT_BLOCK);
+    rm->maxSize = RTnodeSize*RT_BLOCK;
+    rm->aSize = 0;
+  }
+
+  if(rm->maxSize<=rm->aSize+RTnodeSize){
+    rm->nArray = REALLOC(long, rm->nArray,rm->maxSize+RTnodeSize*RT_BLOCK);
+    if(rm->nArray == 0){
+      fprintf(vis_stdout,"memout when alloc %ld bytes\n",
+	     (rm->maxSize+RTnodeSize*RT_BLOCK)*4);
+      exit(0);
+    }
+    rm->maxSize = rm->maxSize+RTnodeSize*1000;
+  }
+  rm->aSize += RTnodeSize;
+  node = rm->aSize;
+
+  RT_fSize(node) = 0;
+  RT_formula(node) = 0;
+  RT_oriClsIdx(node) = 0;
+  RT_pivot(node) = 0;
+  RT_flag(node) = 0;
+  RT_IPnode(node) = -1;
+  RT_left(node) = 0;
+  RT_right(node) = 0;
+
+  if(rm->fArray==0){
+    rm->fArray = ALLOC(long,FORMULA_BLOCK);
+
+    rm->cpos = 0;
+    rm->maxpos = FORMULA_BLOCK;
+  }
+
+  return node;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Allocate an interpolation manager]
+
+  Description [Allocate an interpolation manager]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+IP_Manager_t * IPManagerAlloc()
+{
+  IP_Manager_t * ipm = ALLOC(IP_Manager_t, 1);
+  memset(ipm,0,sizeof(IP_Manager_t));
+  return ipm;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Free an interpolation manager]
+
+  Description [Free an interpolation manager]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+void IPManagerFree(IP_Manager_t *ipm)
+{
+  FREE(ipm);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Find the type of conflict, return the value to caller]
+
+  Description [
+
+
+	   0       1       1       1       1      1
+	   |       |       |       |       |      |
+	20---33,49--- 9,13---  17 ---  5  ---   1---
+	  / \     / \     / \     / \     / \    / \
+	 1   1   X   0   0   X   1   0   0   1  0   0
+
+   Bing note: For case 1, maybe solving conflict with both childern is
+   better, but in sat package, only conflict with left child is solved ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+
+int PureSat_IdentifyConflict(
+  satManager_t *cm,
+  long left,
+  bAigEdge_t right,
+  bAigEdge_t node)
+{
+  int result; /*1:left 2:right 3:both*/
+  int value = SATgetValue(left,right,node);
+  switch(value){
+  case 1:
+  case 5:
+  case 9:
+  case 13:
+    result = 1;
+    break;
+  case 17:
+  case 33:
+  case 49:
+    result = 2;
+    break;
+  case 20:
+    result = 3;
+    break;
+  default:
+    fprintf(vis_stdout,"can't identify the conflict, exit\n");
+    exit(0);
+  }
+
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Get COI for a network node]
+
+  Description [Get COI for a network node]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+void
+PureSatBmcGetCoiForNtkNode_New(
+  Ntk_Node_t  *node,
+  st_table    *CoiTable,
+  st_table    *visited)
+{
+  int        i;
+  Ntk_Node_t *faninNode;
+
+  if(node == NIL(Ntk_Node_t)){
+    return;
+  }
+
+
+  if (st_lookup_int(visited, (char *) node, NIL(int))){
+    return;
+  }
+  st_insert(visited, (char *) node, (char *) 0);
+
+  if(Ntk_NodeTestIsInput(node))
+    return;
+
+  if (Ntk_NodeTestIsLatch(node)){
+    st_insert(CoiTable, (char *) node, (char *)0);
+  }
+
+  Ntk_NodeForEachFanin(node, i, faninNode) {
+    PureSatBmcGetCoiForNtkNode_New(faninNode, CoiTable, visited);
+  }
+
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Recursively get COI nodes for a LTL formula]
+
+  Description [Recursively get COI nodes for a LTL formula]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void
+PureSatBmcGetCoiForLtlFormulaRecursive_New(
+  Ntk_Network_t   *network,
+  Ctlsp_Formula_t *formula,
+  st_table        *ltlCoiTable,
+  st_table        *visited)
+{
+  if (formula == NIL(Ctlsp_Formula_t)) {
+    return;
+  }
+  /* leaf node */
+  if (formula->type == Ctlsp_ID_c){
+    char       *name = Ctlsp_FormulaReadVariableName(formula);
+    Ntk_Node_t *node = Ntk_NetworkFindNodeByName(network, name);
+    int        tmp;
+
+    if (st_lookup_int(visited, (char *) node, &tmp)){
+      /* Node already visited */
+      return;
+    }
+    PureSatBmcGetCoiForNtkNode_New(node, ltlCoiTable, visited);
+    return;
+  }
+  PureSatBmcGetCoiForLtlFormulaRecursive_New(network, formula->left,  ltlCoiTable, visited);
+  PureSatBmcGetCoiForLtlFormulaRecursive_New(network, formula->right, ltlCoiTable, visited);
+
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Get COI nodes for a LTL formula]
+
+  Description [Get COI nodes for a LTL formula]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void
+PureSatBmcGetCoiForLtlFormula_New(
+  Ntk_Network_t   *network,
+  Ctlsp_Formula_t *formula,
+  st_table        *ltlCoiTable)
+{
+  st_table *visited = st_init_table(st_ptrcmp, st_ptrhash);
+
+  PureSatBmcGetCoiForLtlFormulaRecursive_New(network, formula, ltlCoiTable, visited);
+  st_free_table(visited);
+  return;
+} /* BmcGetCoiForLtlFormula() */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Mark transitive fanin for an aig node]
+
+  Description [Mark transitive fanin for an aig node]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+void PureSat_MarkTransitiveFaninForNode(
+	satManager_t *cm,
+	bAigEdge_t v,
+	unsigned int mask)
+{
+  if(v == bAig_NULL)	return;
+
+  v = SATnormalNode(v);
+
+  if(SATflags(v) & mask)	return;
+
+  SATflags(v) |= mask;
+  if(SATflags(v) & Visited3Mask) return;
+
+  PureSat_MarkTransitiveFaninForNode(cm, SATleftChild(v), mask);
+  PureSat_MarkTransitiveFaninForNode(cm, SATrightChild(v), mask);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Mark transitive fanin for an array of aig nodes]
+
+  Description [Mark transitive fanin for an array of aig nodes]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+void PureSat_MarkTransitiveFaninForArray(
+	satManager_t *cm,
+	satArray_t *arr,
+	unsigned int mask)
+{
+  int  i, size;
+  bAigEdge_t v;
+
+  if(arr == 0)	return;
+  size = arr->num;
+
+  for(i=0; i<size; i++) {
+    v = arr->space[i];
+    PureSat_MarkTransitiveFaninForNode(cm, v, mask);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Mark transitive fanin for an aig node]
+
+  Description [Mark transitive fanin for an aig node]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSat_MarkTransitiveFaninForNode2(
+	mAig_Manager_t *manager,
+	bAigEdge_t v,
+	unsigned int mask)
+{
+  if(v == bAig_NULL)	return;
+
+  v = SATnormalNode(v);
+
+  if(flags(v) & mask)	return;
+
+  flags(v) |= mask;
+  if(flags(v) & Visited3Mask) return;
+
+  PureSat_MarkTransitiveFaninForNode2(manager, leftChild(v), mask);
+  PureSat_MarkTransitiveFaninForNode2(manager, rightChild(v), mask);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Mark transitive fanin for an array of aig nodes]
+
+  Description [Mark transitive fanin for an array of aig nodes]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+void PureSat_MarkTransitiveFaninForArray2(
+	mAig_Manager_t *manager,
+	satArray_t *arr,
+	unsigned int mask)
+{
+bAigEdge_t v;
+int i, size;
+
+  if(arr == 0)	return;
+  size = arr->num;
+
+  for(i=0; i<size; i++) {
+    v = arr->space[i];
+    PureSat_MarkTransitiveFaninForNode2(manager, v, mask);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Mark transitive fanin for an array of aig nodes]
+
+  Description [Mark transitive fanin for an array of aig nodes]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+
+void PureSat_MarkTransitiveFaninForNode3(
+	mAig_Manager_t *manager,
+	bAigEdge_t v,
+	unsigned int mask)
+{
+  if(v == 2)	return;
+
+  v = SATnormalNode(v);
+
+  if(flags(v) & mask)	return;
+
+  flags(v) |= mask;
+
+  PureSat_MarkTransitiveFaninForNode3(manager, leftChild(v), mask);
+  PureSat_MarkTransitiveFaninForNode3(manager, rightChild(v), mask);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Mark transitive fanin for an array of aig nodes]
+
+  Description [Mark transitive fanin for an array of aig nodes]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSat_MarkTransitiveFaninForArray3(
+	mAig_Manager_t *manager,
+	satArray_t *arr,
+	unsigned int mask)
+{
+bAigEdge_t v;
+int i, size;
+
+  if(arr == 0)	return;
+  size = arr->num;
+
+  for(i=0; i<size; i++) {
+    v = arr->space[i];
+    PureSat_MarkTransitiveFaninForNode3(manager, v, mask);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Mark transitive fanin for an array of aig nodes]
+
+  Description [Mark transitive fanin for an array of aig nodes]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+void PureSat_MarkTransitiveFaninForNode4(
+	mAig_Manager_t *manager,
+	bAigEdge_t v,
+	unsigned int mask,
+	int bound)
+{
+  if(v == bAig_NULL)	return;
+
+  v = SATnormalNode(v);
+
+  if(flags(v) & mask)	return;
+
+  flags(v) |= mask;
+
+  if((flags(v)&StateBitMask)&&
+     !(flags(v)&VisibleVarMask)&&
+     (bAig_Class(v)>0)){
+
+    return;
+  }
+
+  PureSat_MarkTransitiveFaninForNode4(manager, leftChild(v), mask,bound);
+  PureSat_MarkTransitiveFaninForNode4(manager, rightChild(v), mask,bound);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Mark transitive fanin for an array of aig nodes]
+
+  Description [Mark transitive fanin for an array of aig nodes]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSat_MarkTransitiveFaninForArray4(
+	mAig_Manager_t *manager,
+	satArray_t *arr,
+	unsigned int mask,
+	int bound)
+{
+bAigEdge_t v;
+int i, size;
+
+  if(arr == 0)	return;
+  size = arr->num;
+
+  for(i=0; i<size; i++) {
+    v = arr->space[i];
+
+    v = SATnormalNode(v);
+    PureSat_MarkTransitiveFaninForNode4(manager,v,mask,bound);
+
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [clean a certain mask for all the aig nodes]
+
+  Description [clean a certain mask for all the aig nodes]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+
+void PureSat_CleanMask(mAig_Manager_t *manager,
+		       unsigned int mask)
+{
+  bAigEdge_t i;
+
+  for(i=bAigNodeSize; i<manager->nodesArraySize;i+=bAigNodeSize)
+    flags(i)&=mask;
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Set COI mask for SAT solver]
+
+  Description [Set COI mask for SAT solver]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+void PureSat_SetCOI(satManager_t *cm)
+{
+
+  PureSat_MarkTransitiveFaninForArray(cm, cm->auxObj, CoiMask);
+  PureSat_MarkTransitiveFaninForArray(cm, cm->obj, CoiMask);
+  PureSat_MarkTransitiveFaninForArray(cm, cm->assertArray, CoiMask);
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reset COI mask for all nodes]
+
+  Description [Reset COI mask for all nodes]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSat_ResetCoi(satManager_t *cm)
+{
+  bAigEdge_t i;
+  for(i=satNodeSize;i<cm->nodesArraySize;i+=satNodeSize){
+    if(SATflags(i) & CoiMask)
+      SATflags(i) &= ResetCoiMask;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Set COI for latch nodes]
+
+  Description [Set COI for latch nodes]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSatSetLatchCOI(Ntk_Network_t * network,
+			PureSat_Manager_t *pm,
+			satManager_t * cm,
+			/*deletable*/
+			st_table * AbsTable,
+			int from,
+			int to)
+{
+
+  mAig_Manager_t * manager = Ntk_NetworkReadMAigManager(network);
+
+  bAigTimeFrame_t *tf = manager->timeframeWOI;
+  int i,j;
+  bAigEdge_t *L0,*L1,*bL0,*bL1;
+  satArray_t * assert;
+  int nLatches = tf->nLatches, nbLatches = tf->nbLatches;
+
+  if(from>=to) return;
+
+  PureSat_ResetCoi(cm);
+
+  assert = sat_ArrayAlloc(1);
+  sat_ArrayInsert(assert,manager->InitState);
+  PureSat_MarkTransitiveFaninForArray3(manager,assert,CoiMask);
+  sat_ArrayFree(assert);
+
+  for(i=from; i<to; i++){
+    assert = sat_ArrayAlloc(1);
+
+    L0 = tf->latchInputs[i];
+    L1 = tf->latchInputs[i+1];
+    bL0 = tf->blatchInputs[i];
+    bL1 = tf->blatchInputs[i+1];
+
+    for(j=0;j<nLatches;j++){
+      if(L1[j]!=bAig_One&&L1[j]!=bAig_Zero){
+	if(flags(L1[j])&VisibleVarMask)
+	  sat_ArrayInsert(assert,L1[j]);
+      }
+      if(L0[j]!=bAig_One&&L0[j]!=bAig_Zero&&
+	 !(flags(L0[j])&VisibleVarMask))
+	flags(L0[j]) |= Visited3Mask;
+    }
+
+    for(j=0;j<nbLatches;j++){
+      if(bL1[j]!=bAig_One&&bL1[j]!=bAig_Zero){
+	if(flags(bL1[j])&VisibleVarMask)
+	  sat_ArrayInsert(assert,bL1[j]);
+      }
+      if(bL0[j]!=bAig_One&&bL0[j]!=bAig_Zero&&
+	 !(flags(bL0[j])&VisibleVarMask))
+	flags(bL0[j]) |= Visited3Mask;
+    }
+
+    PureSat_MarkTransitiveFaninForArray2(manager,assert,CoiMask);
+    sat_ArrayFree(assert);
+  }
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Set COI for latch nodes]
+
+  Description [Set COI for latch nodes]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+void PureSatSetLatchCOI2(Ntk_Network_t * network,
+			 PureSat_Manager_t *pm,
+			 satManager_t * cm,
+			 bAigEdge_t obj,
+			 int bound)
+{
+
+  mAig_Manager_t * manager = Ntk_NetworkReadMAigManager(network);
+  satArray_t * assert;
+
+  PureSat_ResetCoi(cm);
+
+  assert = sat_ArrayAlloc(1);
+  sat_ArrayInsert(assert,obj);
+  PureSat_MarkTransitiveFaninForArray4(manager,assert,CoiMask,bound);
+  PureSat_MarkTransitiveFaninForArray4(manager,cm->assertArray,CoiMask,bound);
+  sat_ArrayFree(assert);
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Set COI for form the SAT problem]
+
+  Description [Set COI for form the SAT problem]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSatSetCOI(Ntk_Network_t * network,
+		   PureSat_Manager_t *pm,
+		   satManager_t * cm,
+		   st_table * AbsTable,
+		   int from,
+		   int to,
+		   int bound)
+{
+  mAig_Manager_t * manager = Ntk_NetworkReadMAigManager(network);
+  bAigEdge_t property;
+
+  if(cm->obj->num>0){
+    property = cm->obj->space[0];
+    PureSatSetLatchCOI2(network,pm,cm,property,bound);
+  }
+  else{
+    PureSatSetLatchCOI(network,pm,cm,AbsTable,from,to);
+    PureSat_CleanMask(manager,ResetVisited3Mask);
+  }
+
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Build abstraction from concrete model]
+
+  Description [Build abstraction from concrete model]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSatAbstractLatch(bAig_Manager_t *manager,
+			  bAigEdge_t v,
+			  st_table * tmpTable)
+{
+  bAigEdge_t nv;
+
+  /*fanin: set left and right to bAig_NULL*/
+  nv = bAig_NonInvertedEdge(v);
+
+  if(leftChild(nv)!=bAig_NULL){
+    if(!(flags(leftChild(nv))&CoiMask))
+      flags(leftChild(nv)) |= Visited3Mask;
+    manager->NodesArray[nv+bAigLeft]=bAig_NULL;
+  }
+
+  if(rightChild(nv)!=bAig_NULL){
+    if(!(flags(rightChild(nv))&CoiMask))
+      flags(rightChild(nv)) |= Visited3Mask;
+    manager->NodesArray[nv+bAigRight]=bAig_NULL;
+  }
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Kill all pseudo global variables for one node for interpolation computation]
+
+  Description [Kill all pseudo global variables for one node for interpolation computation]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSatKillPseudoGVNode(bAig_Manager_t *manager,
+			     bAigEdge_t v,
+			     st_table * tmpTable)
+{
+  long size = nFanout(v),i,inv=0;
+  bAigEdge_t v1,v2,nv;
+  bAigEdge_t  * fan = (bAigEdge_t *)fanout(v),left;
+
+  /*fanin: set left and right to bAig_NULL*/
+  nv = bAig_NonInvertedEdge(v);
+  flags(nv) |= PGVMask;
+
+  if(leftChild(nv)!=bAig_NULL){
+    if(!(flags(leftChild(nv))&CoiMask))
+      flags(leftChild(nv)) |= Visited3Mask;
+    manager->NodesArray[nv+bAigLeft]=bAig_NULL;
+  }
+
+  if(rightChild(nv)!=bAig_NULL){
+    if(!(flags(rightChild(nv))&CoiMask))
+      flags(rightChild(nv)) |= Visited3Mask;
+    manager->NodesArray[nv+bAigRight]=bAig_NULL;
+  }
+
+
+  manager->class_ = 2;
+
+  /*fanout: connection to vars in next tf is disconnected, and a new pseudo var
+    is created, and used as a replacement*/
+  for(i=0;i<size;i++){
+    v1 = bAig_NonInvertedEdge(fan[i]>>1);
+    if(!(flags(v1)&CoiMask))
+      continue;
+    if(bAig_Class(v1)>1){
+      /*igonre invSV since its left and right will be processed to 2*/
+      if(!(flags(v1)&VisibleVarMask)&&(flags(v1)&StateBitMask))
+	continue;
+      /*if nonSV, create new Node as replacement*/
+      if(!st_lookup(tmpTable,(char*)nv,&v2)){
+	v2 = bAig_CreateNode(manager,bAig_NULL, bAig_NULL);
+
+	flags(v2) |= DummyMask;
+	st_insert(tmpTable,(char*)nv,(char*)v2);
+      }
+
+      left = 1;
+      if(bAig_IsInverted(fan[i]))
+	left = 0;
+      inv = bAig_IsInverted(fan[i]>>1)?1:0;
+      v2 = inv ? bAig_Not(v2) : v2;
+      if(left){
+#if DBG
+	assert(manager->NodesArray[v1+bAigLeft] != v2);
+#endif
+	manager->NodesArray[v1+bAigLeft] = v2;
+	PureSat_connectOutput(manager, v2, v1,0);
+	flags(v2) |= CoiMask;
+      }
+      else{
+#if DBG
+	assert(manager->NodesArray[v1+bAigRight] != v2);
+#endif
+	manager->NodesArray[v1+bAigRight] = v2;
+	PureSat_connectOutput(manager, v2, v1,1);
+	flags(v2) |= CoiMask;
+      }
+    }
+  }
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Kill all pseudo global variables for interpolation computation]
+
+  Description [Kill all pseudo global variables for interpolation computation]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSatKillPseudoGV(Ntk_Network_t * network,
+			 PureSat_Manager_t *pm,
+			 st_table * AbsTable,
+			 int from,
+			 int to)
+{
+  bAig_Manager_t * manager = Ntk_NetworkReadMAigManager(network);
+  bAigTimeFrame_t *tf = manager->timeframeWOI;
+  array_t *bVarList,*mVarList;
+  bAigEdge_t * li, *bli,node;
+  int i,j;
+  st_table * tmpTable, *DoneTable;
+
+
+  pm->oldPos = manager->nodesArraySize-bAigNodeSize;
+
+  bVarList = mAigReadBinVarList(manager);
+  mVarList = mAigReadMulVarList(manager);
+
+  if(from < 1)
+    from = 1;
+
+  if(to>pm->Length)
+    to=pm->Length;
+
+  li = tf->latchInputs[1];
+  bli = tf->blatchInputs[1];
+  for(j=0;j<tf->nLatches;j++)
+    flags(li[j])&=ResetPGVMask;
+  for(j=0;j<tf->nbLatches;j++)
+    flags(bli[j])&=ResetPGVMask;
+
+  for(i=from;i<=to;i++){
+    li = tf->latchInputs[i];
+    bli = tf->blatchInputs[i];
+    manager->class_ = i;
+    tmpTable = st_init_table(st_numcmp,st_numhash);
+    DoneTable = st_init_table(st_numcmp,st_numhash);
+
+    for(j=0; j<tf->nLatches; j++){
+      node = bAig_NonInvertedEdge(li[j]);
+      if(st_lookup(DoneTable,(char*)node,NIL(char*)))
+	continue;
+      st_insert(DoneTable,(char*)node,(char*)0);
+      if((flags(node)&StateBitMask)&&
+	 !(flags(node)&VisibleVarMask)&&
+	 (flags(node)&CoiMask)){
+	if(i==1)
+	  PureSatKillPseudoGVNode(manager,node,tmpTable);
+	else
+	  PureSatAbstractLatch(manager,node,tmpTable);
+      }
+    }
+
+    for(j=0; j<tf->nbLatches; j++){
+      node = bAig_NonInvertedEdge(bli[j]);
+      if(st_lookup(DoneTable,(char*)node,NIL(char*)))
+	continue;
+      st_insert(DoneTable,(char*)node,(char*)0);
+      if((flags(node)&StateBitMask)&&
+	 !(flags(node)&VisibleVarMask)&&
+	 (flags(node)&CoiMask)){
+	if(i==1)
+	  PureSatKillPseudoGVNode(manager,node,tmpTable);
+	else
+	  PureSatAbstractLatch(manager,node,tmpTable);
+      }
+    }
+    st_free_table(tmpTable);
+    st_free_table(DoneTable);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Count number of nodes in COI]
+
+  Description [Count number of nodes in COI]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+int PureSat_CountNodesInCoi(satManager_t* cm)
+{
+  int ct=0;
+  bAigEdge_t i;
+
+  for(i=satNodeSize;i<cm->nodesArraySize;i+=satNodeSize){
+    if(SATflags(i) & CoiMask){
+      ct++;
+
+    }
+  }
+  /*fprintf(vis_stdout,"There are %d node in COI\n",ct);*/
+  return ct;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Sanity check for one node for abstraction processsing]
+
+  Description [Sanity check for one node for abstraction processsing]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+void PureSat_Check(bAig_Manager_t *manager, bAigEdge_t v)
+{
+  bAigEdge_t *fan,*fan1,nfan1;
+  bAigEdge_t nfan,cur,child,tmpchild,v1,other,cur1;
+  int size,i,j,find=0,inver,left,left1;
+
+  nfan = nFanout(v);
+  fan = (bAigEdge_t *)fanout(v);
+  if(fan == 0){
+    assert(nfan==0);
+    return;
+  }
+
+  size = 0;
+
+  for(i=0; fan[i]!=0; i++){
+    size++;
+    cur = fan[i];
+    left = 1;
+    inver = 0;
+    if(SATisInverted(cur))
+      left = 0;
+    cur >>= 1;
+    if(SATisInverted(cur))
+      inver = 1;
+    cur = SATnormalNode(cur);
+    child = inver? SATnormalNode(v)+1:SATnormalNode(v);
+    if(left)
+      tmpchild = leftChild(cur);
+    else
+      tmpchild = rightChild(cur);
+    assert(tmpchild == child);
+
+    /*check the other child*/
+    find = 0;
+    other = left?rightChild(cur):leftChild(cur);
+    assert(other!=bAig_NULL);
+    v1 = SATnormalNode(other);
+    nfan1 = nFanout(v1);
+    fan1 = (bAigEdge_t *)fanout(v1);
+    assert(nfan1!=0&&fan1!=0);
+    for(j=0; fan1[j]!=0; j++){
+      cur1 = fan1[j];
+      left1 = 1;
+      if(SATisInverted(cur1))
+	left1 = 0;
+      assert(j<nfan1);
+      if((SATnormalNode(cur1>>1)==cur)&&(left1!=left)){
+	find = 1;
+
+	break;
+      }
+    }
+    assert(find);
+  }
+
+  assert(nfan==size);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sanity check for abstraction processsing]
+
+  Description [Sanity check for abstraction processsing]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+void PureSat_CheckFanoutFanin(bAig_Manager_t *manager)
+{
+  bAigEdge_t  i,v;
+
+  for(i=bAigNodeSize;i<manager->nodesArraySize;i+=bAigNodeSize){
+    v = i;
+    if((flags(v) & IsCNFMask))
+      continue;
+    PureSat_Check(manager,v);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Reset a sat manager]
+
+  Description [Reset a sat manager]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+/*1. eliminate concls, 2. free variableArray
+  3. adjust nodeArray(size and new nodes)*/
+void PureSat_ResetManager(mAig_Manager_t *manager,
+			  satManager_t *cm, int clean)
+{
+
+  int i;
+  satVariable_t var;
+  satLevel_t *d;
+
+  if(cm->variableArray) {
+    for(i=0; i<cm->initNumVariables; i++) {
+      var = cm->variableArray[i];
+      if(var.wl[0]) {
+	sat_ArrayFree(var.wl[0]);
+	var.wl[0] = 0;
+      }
+      if(var.wl[1]) {
+	sat_ArrayFree(var.wl[1]);
+	var.wl[1] = 0;
+      }
+    }
+    free(cm->variableArray);
+    cm->variableArray = 0;
+  }
+
+  if(cm->decisionHead) {
+    for(i=0; i<cm->decisionHeadSize; i++) {
+      d = &(cm->decisionHead[i]);
+      if(d->implied)
+	sat_ArrayFree(d->implied);
+      if(d->satisfied)
+	sat_ArrayFree(d->satisfied);
+    }
+    free(cm->decisionHead);
+    cm->decisionHead = 0;
+    cm->decisionHeadSize = 0;
+    cm->currentDecision = 0;
+  }
+
+  if(cm->literals){
+    sat_FreeLiteralsDB(cm->literals);
+    cm->literals=0;
+    sat_AllocLiteralsDB(cm);
+  }
+  if(cm->each){
+    FREE(cm->each);
+    cm->each = sat_InitStatistics();
+  }
+
+  if(cm->queue)		sat_FreeQueue(cm->queue);
+  if(cm->BDDQueue)	sat_FreeQueue(cm->BDDQueue);
+  if(cm->unusedAigQueue)sat_FreeQueue(cm->unusedAigQueue);
+  cm->queue = 0;
+  cm->BDDQueue = 0;
+  cm->unusedAigQueue = 0;
+
+
+  if(cm->nonobjUnitLitArray)   sat_ArrayFree(cm->nonobjUnitLitArray);
+  if(cm->objUnitLitArray)      sat_ArrayFree(cm->objUnitLitArray);
+  if(cm->orderedVariableArray) sat_ArrayFree(cm->orderedVariableArray);
+  if(cm->dormantConflictArray) sat_ArrayFree(cm->dormantConflictArray);
+  if(cm->shrinkArray)          sat_ArrayFree(cm->shrinkArray);
+
+  cm->nonobjUnitLitArray = 0;
+  cm->objUnitLitArray = 0;
+  cm->orderedVariableArray = 0;
+  cm->dormantConflictArray = 0;
+  cm->shrinkArray = 0;
+
+  /*change initNumVariable after cm->variableArray has been freed,
+    otherwise, initNumVariable may change*/
+  cm->nodesArray = manager->NodesArray;
+  cm->nodesArraySize = manager->nodesArraySize;
+  cm->initNodesArraySize = manager->nodesArraySize;
+  cm->maxNodesArraySize = manager->maxNodesArraySize;
+  cm->initNumVariables = (manager->nodesArraySize/bAigNodeSize)-1;
+  cm->initNumClauses = 0;
+  cm->initNumLiterals = 0;
+
+  cm->ipm = manager->ipm;
+  cm->assertArray = manager->assertArray;
+  cm->assertArray2 = manager->assertArray2;
+  cm->InitState = manager->InitState;
+  cm->CoiAssertArray = manager->CoiAssertArray;
+  cm->EqArray = manager->EqArray;
+
+  cm->currentVarPos = 0;
+  cm->currentTopConflict = 0;
+  cm->currentTopConflictCount = 0;
+  cm->lowestBacktrackLevel = 0;
+  cm->implicatedSoFar = 0;
+  //cm->status = 0;
+
+  if(clean){
+    for(i=bAigNodeSize;i<cm->nodesArraySize;i+=bAigNodeSize)
+      cm->nodesArray[i] = 2;
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Restore AIG to get rid of Dummy nodes]
+
+  Description [Restore AIG to get rid of Dummy nodes]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSat_RestoreAigForDummyNode(mAig_Manager_t *manager,
+				    int oldPosition)
+{
+
+  bAigEdge_t  i;
+
+  for(i=manager->nodesArraySize-bAigNodeSize;
+      i>oldPosition;i=i-bAigNodeSize){
+#if DBG
+    assert(leftChild(i)==bAig_NULL&&
+	   rightChild(i)==bAig_NULL);
+    assert(flags(i)&DummyMask);
+#endif
+    FREE(fanout(i));
+  }
+
+  manager->nodesArraySize = oldPosition+bAigNodeSize;
+
+  return;
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Process fanout nodes to generate abstraction]
+
+  Description [Process fanout nodes to generate abstraction]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+/*after this funct, all nodes' fanout, either COI or not
+  are in COI, not InvSV, and if this node is InvSV, not to a node in the next tf*/
+void PureSatProcessFanout(satManager_t * cm)
+{
+
+long bufSize, bufIndex;
+bAigEdge_t *buf,left,right,*fan,v,cur;
+int i, j;
+long size, tsize;
+
+int InvStateVar,l;
+
+
+  bufSize = 1024;
+  bufIndex = 0;
+  buf = malloc(sizeof(bAigEdge_t) * bufSize);
+  for(i=satNodeSize; i<cm->nodesArraySize; i+=satNodeSize) {
+    v = i;
+
+    if(!(SATflags(v) & CoiMask))
+      continue;
+
+    InvStateVar = 0;
+    if((SATflags(v)&StateBitMask)&&
+       !(SATflags(v)&VisibleVarMask))
+      InvStateVar = 1;
+
+    size = SATnFanout(v);
+    if(size >= bufSize) {
+      bufSize <<= 1;
+      if(size >= bufSize)
+	bufSize = size + 1;
+      buf = realloc(buf, sizeof(bAigEdge_t) * bufSize);
+    }
+
+    bufIndex = 0;
+    for(j=0, fan = SATfanout(v); j<size; j++) {
+      cur = fan[j];
+      cur >>= 1;
+      cur = SATnormalNode(cur);
+      /*Not in COI , pass */
+      if(!(SATflags(cur) & CoiMask))
+	continue;
+      /*cur is invisible var*/
+      left = SATleftChild(cur);
+      right = SATrightChild(cur);
+      if(left==bAig_NULL||right==bAig_NULL){
+#if DBG
+
+	assert(left==bAig_NULL&&right==bAig_NULL);
+	assert((SATflags(cur)&StateBitMask)&&
+	       !(SATflags(cur)&VisibleVarMask));
+#endif
+	continue;
+      }
+      /*v itself is InvStateVar and cur is not InvSV*/
+
+      if(SATflags(v)&PGVMask){
+
+	 if(SATclass(cur)>=2){
+	  l = SATisInverted(fan[j]) ? 0 : 1;
+	  if(l){
+#if DBG
+	    bAigEdge_t v1 = SATnormalNode(SATleftChild(cur));
+	    assert(v1!=v);
+	    assert(SATflags(v1)&DummyMask);
+#endif
+	  }
+	  else{
+#if DBG
+	    bAigEdge_t v1 = SATnormalNode(SATrightChild(cur));
+	    assert(v1!=v);
+	    assert(SATflags(v1)&DummyMask);
+#endif
+	  }
+	  continue;
+	}
+      }
+      buf[bufIndex++] = fan[j];
+    }
+
+    if(bufIndex > 0) {
+      tsize = bufIndex;
+      for(j=0, fan=SATfanout(v); j<size; j++) {
+	cur = fan[j];
+	cur >>= 1;
+	cur = SATnormalNode(cur);
+	if(!(SATflags(cur) & CoiMask))  {
+	  buf[bufIndex++] = fan[j];
+	  continue;
+	}
+
+	left = SATleftChild(cur);
+	right = SATrightChild(cur);
+
+	if(left==bAig_NULL||right==bAig_NULL){
+	  buf[bufIndex++] = fan[j];
+	  continue;
+	}
+
+
+	if(SATflags(v)&PGVMask){
+	  if(SATclass(cur)>=2){
+	    buf[bufIndex++] = fan[j];
+	    continue;
+	  }
+	}
+
+      }/*for(j=0, fan=SATfanout(v); j<size; j++) {*/
+      buf[bufIndex] = 0;
+      memcpy(fan, buf, sizeof(bAigEdge_t)*(size+1));
+      SATnFanout(v) = tsize;
+    }
+    else
+      SATnFanout(v) = 0;
+  }
+
+  free(buf);
+
+  for(i=satNodeSize; i<cm->nodesArraySize; i+=satNodeSize) {
+    v = i;
+    if(!(SATflags(v) & CoiMask))
+      continue;
+    fan = SATfanout(v);
+    size = SATnFanout(v);
+    qsort(fan, size, sizeof(bAigEdge_t), NodeIndexCompare);
+  }
+}
+/**Function********************************************************************
+
+  Synopsis    [Recover from abstractions]
+
+  Description [Recover from abstractions]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+long PureSatRecoverFanoutNode(satManager_t * cm,
+			      bAigEdge_t v)
+{
+  bAigEdge_t *fan,nfan,child,cur;
+  long i;
+  int left,inver;
+  int InvStateVar = 0;
+
+  if(!(SATflags(v)&VisibleVarMask)&&(SATflags(v)&StateBitMask))
+    InvStateVar = 1;
+
+  nfan = SATnFanout(v);
+
+  fan = SATfanout(v);
+  if(fan == 0)	return(0);
+
+  /*recover left and right children for latch nodes*/
+
+  for(i=nfan; fan[i]!=0; i++){
+    cur = fan[i];
+    if(!(SATflags(SATnormalNode(cur>>1))&CoiMask))
+      continue;
+    /*cur is InvSV*/
+    if((SATleftChild(SATnormalNode(cur>>1))==bAig_NULL)||
+       (SATrightChild(SATnormalNode(cur>>1))==bAig_NULL)){
+#if DBG
+      assert((SATflags(SATnormalNode(cur>>1))&StateBitMask)&&
+	     !(SATflags(SATnormalNode(cur>>1))&VisibleVarMask));
+#endif
+      left = 1;
+      inver = 0;
+      if(SATisInverted(cur))
+	left = 0;
+      cur >>= 1;
+      if(SATisInverted(cur))
+	inver = 1;
+      cur = SATnormalNode(cur);
+      child = inver? SATnormalNode(v)+1:SATnormalNode(v);
+      if(left)
+	SATleftChild(cur)=child;
+      else
+	SATrightChild(cur)=child;
+      continue;
+    }
+
+    /*v is InvSV, cur is not InvSV*/
+
+    if(SATflags(v)&PGVMask){
+
+      if(SATclass(SATnormalNode(cur>>1))>=2){
+	left = 1;
+	inver = 0;
+	if(SATisInverted(cur))
+	  left = 0;
+	cur >>= 1;
+	if(SATisInverted(cur))
+	  inver = 1;
+	cur = SATnormalNode(cur);
+	child = inver? SATnormalNode(v)+1:SATnormalNode(v);
+	if(left)
+	  SATleftChild(cur)=child;
+	else
+	  SATrightChild(cur)=child;
+      }
+    }
+  }
+  //recover all fanout
+  return(i);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Recover invisible state variable node]
+
+  Description [Recover invisible state variable node]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+PureSatRecoverISVNode(satManager_t *cm,
+		      bAigEdge_t v)
+{
+
+  bAigEdge_t size = SATnFanout(v),cur,node,child;
+  bAigEdge_t  * fan = SATfanout(v);
+  int inv,i,left;
+
+  for(i=0;i<size;i++){
+    cur = fan[i]>>1;
+    node = SATnormalNode(cur);
+    /*not in coi*/
+    if(!(SATflags(node)&CoiMask))
+      continue;
+    /*not invisible var*/
+    if(!((SATflags(node)&StateBitMask)&&
+	 !(SATflags(node)&VisibleVarMask)))
+      continue;
+
+    left=SATisInverted(fan[i])?0:1;
+    inv=SATisInverted(cur)?1:0;
+    child = inv?SATnormalNode(v)+1:SATnormalNode(v);
+    if(left)
+      SATleftChild(node) = child;
+    else
+      SATrightChild(node) = child;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Recover fanout of nodes]
+
+  Description [Recover fanout of nodes]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSatRecoverFanout(satManager_t * cm,
+			  PureSat_Manager_t *pm)
+{
+  bAigEdge_t i, v;
+
+  /*dummy node can't be recovered*/
+  for(i=satNodeSize; i<=pm->oldPos; i+=satNodeSize) {
+    v = i;
+    if(SATflags(v) & IsCNFMask)
+      continue;
+
+    if((SATflags(v)&CoiMask)){
+       SATnFanout(v) = PureSatRecoverFanoutNode(cm, v);
+       continue;
+    }
+    /*for some node not in coi, but a child of one coi(ISV) node*/
+    if(SATflags(v)&Visited3Mask){
+      PureSatRecoverISVNode(cm,v);
+      continue;
+    }
+  }
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [sanity check for one node for abstraction processing]
+
+  Description [sanity check for one node for abstraction processing]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSatCheckCoiNode(bAig_Manager_t * manager,
+			 bAigEdge_t node)
+{
+  int i;
+  long *fan;
+  long  nfan,child, cur;
+  int left,inv;
+
+  nfan = nFanout(node);
+  fan = (bAigEdge_t*)fanout(node);
+  if(fan==0) return;
+  /*check child*/
+  assert((leftChild(node)==bAig_NULL)||
+   (flags(leftChild(node))&CoiMask));
+  assert((rightChild(node)==bAig_NULL)||
+   (flags(rightChild(node))&CoiMask));
+  if((leftChild(node)==bAig_NULL)||(rightChild(node)==bAig_NULL))
+    assert((leftChild(node)==bAig_NULL)&&(rightChild(node)==bAig_NULL));
+  /*check fanout*/
+  for(i=0; i<nfan; i++){
+    cur = fan[i]>>1;
+    assert(flags(cur)&CoiMask);
+    left=SATisInverted(fan[i])?0:1;
+    inv=SATisInverted(cur)?1:0;
+    child = inv?SATnormalNode(node)+1:SATnormalNode(node);
+    if(left){
+     assert(child==leftChild(cur));
+    }
+    else{
+      assert(child==rightChild(cur));
+    }
+  }
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [sanity check for abstraction processing]
+
+  Description [sanity check for abstraction processing]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSatCheckCoi(bAig_Manager_t *manager)
+{
+  long i;
+  for(i=bAigNodeSize;i<manager->nodesArraySize;i+=bAigNodeSize){
+    if(flags(i) & IsCNFMask)
+      continue;
+    if(!(flags(i) & CoiMask))
+      continue;
+    PureSatCheckCoiNode(manager,i);
+  }
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Preprocess to form SAT instances]
+
+  Description [Preprocess to form SAT instances]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+void PureSatPreprocess(Ntk_Network_t * network,
+		       satManager_t *cm,
+		       PureSat_Manager_t *pm,
+		       st_table *vertexTable,
+		       int Length)
+
+{
+  bAig_Manager_t * manager = Ntk_NetworkReadMAigManager(network);
+
+  PureSatSetCOI(network,pm,cm,vertexTable,0, Length,Length);
+  /*for interpolation*/
+  PureSatKillPseudoGV(network,pm,vertexTable,1,Length);
+  PureSat_ResetManager(manager,cm,0);
+  /*for abstraction*/
+  PureSatProcessFanout(cm);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Recovery step after SAT solving]
+
+  Description [Recovery step after SAT solving]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+void PureSatPostprocess(bAig_Manager_t *manager,
+			satManager_t *cm,
+			PureSat_Manager_t *pm)
+{
+
+  PureSatRecoverFanout(cm,pm);
+  PureSat_RestoreAigForDummyNode(manager,pm->oldPos);
+  PureSat_CleanMask(manager,ResetVisited3Mask);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Convergence test for flat interpolation algorithm]
+
+  Description [Convergence test for flat interpolation algorithm]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+/*test if state1 contains state2*/
+int PureSat_TestConvergeForIP(mAig_Manager_t *manager,
+			      PureSat_Manager_t *pm,
+			      satManager_t *cm,
+			      bAigEdge_t state1,
+			      bAigEdge_t state2)
+{
+  satArray_t * tmp1,*tmp2,*tmp3, *tmp4,*tmp5, *tmp6, *tmp7;
+  int status, nodes_in_coi = 0;
+
+ if(state2 == bAig_Zero)
+    return 1;
+  if(state1 == bAig_One)
+    return 1;
+  if(state1 == bAig_Zero && state2 != bAig_Zero)
+    return 0;
+  if(state1 != bAig_One && state2 == bAig_One)
+    return 0;
+
+  if(pm->verbosity>=1)
+    fprintf(vis_stdout,"Test convergence:\n");
+  PureSat_ResetCoi(cm);
+  if(pm->verbosity>=1){
+    fprintf(vis_stdout,"after reset COI\n");
+    nodes_in_coi = PureSat_CountNodesInCoi(cm);
+    fprintf(vis_stdout,"There are %d node in COI\n",nodes_in_coi);
+  }
+  tmp1 = cm->obj;
+  tmp2 = cm->auxObj;
+  tmp3 = cm->assertion;
+  tmp4 = cm->assertArray;
+  //Bing:
+  tmp5 = cm->unitLits;
+  tmp6 = cm->pureLits;
+  tmp7 = cm->nonobjUnitLitArray;
+  cm->obj = 0;
+  cm->auxObj = 0;
+  cm->assertion = 0;
+  //cm->assertArray2 = 0;
+  cm->assertArray = sat_ArrayAlloc(1);
+  sat_ArrayInsert(cm->assertArray,SATnot(state1));
+  sat_ArrayInsert(cm->assertArray,state2);
+  sat_SetConeOfInfluence(cm);
+  if(pm->verbosity>=1){
+    fprintf(vis_stdout,"after add new init states:\n");
+    nodes_in_coi = PureSat_CountNodesInCoi(cm);
+    fprintf(vis_stdout,"There are %d node in COI\n",nodes_in_coi);
+  }
+  cm->option->coreGeneration = 0;
+  //cm->option->effIP = 0;
+  cm->option->IP = 0;
+  cm->status = 0;
+  sat_Main(cm);
+  if(manager->NodesArray!=cm->nodesArray)
+    /*cm->nodesArray may be reallocated*/
+    manager->NodesArray = cm->nodesArray;
+  cm->obj = tmp1;
+  cm->auxObj = tmp2;
+  cm->assertion = tmp3;
+  sat_ArrayFree(cm->assertArray);
+  cm->assertArray = tmp4;
+
+  cm->unitLits = tmp5;
+  cm->pureLits = tmp6;
+  cm->nonobjUnitLitArray = tmp7;
+
+  cm->option->coreGeneration = 1;
+
+  cm->option->IP = 1;
+  status = cm->status;
+#if DBG
+  assert(cm->currentDecision>=-1);
+#endif
+  if(cm->currentDecision!=-1)
+    sat_Backtrack(cm,-1);
+  cm->status = 0;
+
+  if(status == SAT_UNSAT)
+    /*state2 contains state1, reach convergence*/
+    return 1;
+  else
+    return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Convergence test for interpolation algorithm with abstraction
+	      refinement ]
+
+  Description [Convergence test for flat interpolation algorithmwith abstraction
+	      refinement ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+
+/*test if state1 contains state2 for abstract refinement*/
+int PureSat_TestConvergeForIP_AbRf(Ntk_Network_t *network,
+				   satManager_t *cm,
+				   PureSat_Manager_t *pm,
+				   array_t  * CoiArray,
+				   bAigEdge_t state1,
+				   bAigEdge_t state2)
+{
+  satArray_t * tmp1,*tmp2,*tmp3, *tmp4,*tmp5, *tmp6, *tmp7;
+  int status, nodes_in_coi = 0;
+  mAig_Manager_t * manager;
+
+
+  if(state2 == bAig_Zero)
+    return 1;
+  if(state1 == bAig_One)
+    return 1;
+  if(state1 == bAig_Zero && state2 != bAig_Zero)
+    return 0;
+  if(state1 != bAig_One && state2 == bAig_One)
+    return 0;
+
+
+  manager = Ntk_NetworkReadMAigManager(network);
+
+  if(pm->verbosity>=1)
+    fprintf(vis_stdout,"Test convergence:\n");
+  PureSat_ResetCoi(cm);
+  if(pm->verbosity>=1){
+    fprintf(vis_stdout,"after reset COI\n");
+    nodes_in_coi = PureSat_CountNodesInCoi(cm);
+    fprintf(vis_stdout,"There are %d node in COI\n",nodes_in_coi);
+  }
+  tmp1 = cm->obj;
+  tmp2 = cm->auxObj;
+  tmp3 = cm->assertion;
+  tmp4 = cm->assertArray;
+
+  tmp5 = cm->unitLits;
+  tmp6 = cm->pureLits;
+  tmp7 = cm->nonobjUnitLitArray;
+  cm->obj = 0;
+  cm->auxObj = 0;
+  cm->assertion = 0;
+  cm->unitLits = 0;
+  cm->pureLits = 0;
+  cm->nonobjUnitLitArray = 0;
+  cm->assertArray = sat_ArrayAlloc(1);
+  sat_ArrayInsert(cm->assertArray,SATnot(state1));
+  sat_ArrayInsert(cm->assertArray,state2);
+
+  sat_MarkTransitiveFaninForArray(cm, cm->assertArray, CoiMask);
+
+  if(pm->verbosity>=1){
+    fprintf(vis_stdout,"after add new init states:\n");
+    nodes_in_coi = PureSat_CountNodesInCoi(cm);
+    fprintf(vis_stdout,"There are %d node in COI\n",nodes_in_coi);
+  }
+  cm->option->coreGeneration = 0;
+  cm->status = 0;
+  cm->option->AbRf = 0;
+  sat_Main(cm);
+  cm->option->AbRf = 1;
+  if(manager->NodesArray!=cm->nodesArray)
+    /*cm->nodesArray may be reallocated*/
+    manager->NodesArray = cm->nodesArray;
+  sat_ArrayFree(cm->assertArray);
+  manager->assertArray = tmp4;
+  cm->obj = tmp1;
+  cm->auxObj = tmp2;
+  cm->assertion = tmp3;
+  cm->assertArray = tmp4;
+
+  cm->unitLits = tmp5;
+  cm->pureLits = tmp6;
+  cm->nonobjUnitLitArray = tmp7;
+  cm->option->coreGeneration = 1;
+  status = cm->status;
+  if(cm->currentDecision!=-1)
+    sat_Backtrack(cm,-1);
+  cm->status = 0;
+
+  if(status == SAT_UNSAT)
+    /*state2 contains state1, reach convergence*/
+    return 1;
+  else
+    return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Allocate a PureSAT Manager]
+
+  Description [Allocate a PureSAT Manager]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+satManager_t * PureSat_SatManagerAlloc(bAig_Manager_t *manager,
+				       PureSat_Manager_t *pm,
+				       bAigEdge_t     object,
+				       array_t        *auxObjectArray)
+{
+  satManager_t * cm;
+  satOption_t *option;
+  int i,size;
+  bAigEdge_t tv;
+
+  cm = ALLOC(satManager_t, 1);
+  memset(cm, 0, sizeof(satManager_t));
+  cm->nodesArraySize = manager->nodesArraySize;
+  cm->initNodesArraySize = manager->nodesArraySize;
+  cm->maxNodesArraySize = manager->maxNodesArraySize;
+  cm->nodesArray = manager->NodesArray;
+
+  cm->HashTable = manager->HashTable;
+  cm->literals = manager->literals;
+
+  cm->initNumVariables = (manager->nodesArraySize/bAigNodeSize)-1;
+  cm->initNumClauses = 0;
+  cm->initNumLiterals = 0;
+  cm->comment = ALLOC(char, 2);
+  cm->comment[0] = ' ';
+  cm->comment[1] = '\0';
+  cm->stdErr = vis_stderr;
+  cm->stdOut = vis_stdout;
+  cm->status = 0;
+  cm->orderedVariableArray = 0;
+  cm->unitLits = sat_ArrayAlloc(16);
+  cm->pureLits = sat_ArrayAlloc(16);
+  cm->option = 0;
+  cm->each = 0;
+  cm->decisionHead = 0;
+  cm->variableArray = 0;
+  cm->queue = 0;
+  cm->BDDQueue = 0;
+  cm->unusedAigQueue = 0;
+
+  cm->ipm = manager->ipm;
+  cm->assertArray = manager->assertArray;
+  cm->assertArray2 = manager->assertArray2;
+  cm->InitState = manager->InitState;
+  cm->CoiAssertArray = manager->CoiAssertArray;
+  cm->EqArray = manager->EqArray;
+
+  if(auxObjectArray) {
+    cm->auxObj = sat_ArrayAlloc(auxObjectArray->num+1);
+    size = auxObjectArray->num;
+    for(i=0; i<size; i++) {
+      tv = array_fetch(bAigEdge_t, auxObjectArray, i);
+      if(tv == 1)	continue;
+      else if(tv == 0) {
+	cm->status = SAT_UNSAT;
+	break;
+      }
+      sat_ArrayInsert(cm->auxObj, tv);
+    }
+  }
+  if(object == 0)      cm->status = SAT_UNSAT;
+  else if(object == 1) cm->status = SAT_SAT;
+
+
+  if(cm->status == 0) {
+    if(object!=-1){
+      cm->obj = sat_ArrayAlloc(1);
+      sat_ArrayInsert(cm->obj, object);
+    }
+    /* initialize option*/
+    option = sat_InitOption();
+
+    option->coreGeneration = 1;
+    option->ForceFinish = 1;
+
+    option->clauseDeletionHeuristic = 0;
+    option->includeLevelZeroLiteral = 1;
+    option->minimizeConflictClause = 0;
+    option->IP = 1;
+    option->RT = 1;
+    option->verbose = pm->verbosity;
+
+    cm->anteTable = st_init_table(st_numcmp,st_numhash);
+    cm->RTreeTable = st_init_table(st_ptrcmp,st_ptrhash);
+
+    cm->option = option;
+    cm->each = sat_InitStatistics();
+
+    BmcRestoreAssertion(manager,cm);
+
+    /* value reset..*/
+    sat_CleanDatabase(cm);
+
+    /* set cone of influence*/
+    sat_SetConeOfInfluence(cm);
+    sat_AllocLiteralsDB(cm);
+  }
+  return cm;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocate a PureSAT Manager without setting COI]
+
+  Description [Allocate a PureSAT Manager without setting COI]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+satManager_t * PureSat_SatManagerAlloc_WOCOI(mAig_Manager_t *manager,
+					     PureSat_Manager_t *pm,
+					     bAigEdge_t     object,
+					     array_t        *auxObjectArray)
+{
+  satManager_t * cm;
+  satOption_t *option;
+  int i,size;
+  bAigEdge_t tv;
+
+  cm = ALLOC(satManager_t, 1);
+  memset(cm, 0, sizeof(satManager_t));
+  cm->nodesArraySize = manager->nodesArraySize;
+  cm->initNodesArraySize = manager->nodesArraySize;
+  cm->maxNodesArraySize = manager->maxNodesArraySize;
+  cm->nodesArray = manager->NodesArray;
+
+  cm->HashTable = manager->HashTable;
+  cm->literals = manager->literals;
+
+  cm->initNumVariables = (manager->nodesArraySize/bAigNodeSize)-1;
+  cm->initNumClauses = 0;
+  cm->initNumLiterals = 0;
+  cm->comment = ALLOC(char, 2);
+  cm->comment[0] = ' ';
+  cm->comment[1] = '\0';
+  cm->stdErr = vis_stderr;
+  cm->stdOut = vis_stdout;
+  cm->status = 0;
+  cm->orderedVariableArray = 0;
+  cm->unitLits = sat_ArrayAlloc(16);
+  cm->pureLits = sat_ArrayAlloc(16);
+  cm->option = 0;
+  cm->each = 0;
+  cm->decisionHead = 0;
+  cm->variableArray = 0;
+  cm->queue = 0;
+  cm->BDDQueue = 0;
+  cm->unusedAigQueue = 0;
+
+  cm->ipm = manager->ipm;
+  cm->assertArray = manager->assertArray;
+  cm->assertArray2 = manager->assertArray2;
+  cm->InitState = manager->InitState;
+  cm->CoiAssertArray = manager->CoiAssertArray;
+  cm->EqArray = manager->EqArray;
+
+  if(auxObjectArray) {
+    cm->auxObj = sat_ArrayAlloc(auxObjectArray->num+1);
+    size = auxObjectArray->num;
+    for(i=0; i<size; i++) {
+      tv = array_fetch(bAigEdge_t, auxObjectArray, i);
+      if(tv == 1)	continue;
+      else if(tv == 0) {
+	cm->status = SAT_UNSAT;
+	break;
+      }
+      sat_ArrayInsert(cm->auxObj, tv);
+    }
+  }
+  if(object == 0)      cm->status = SAT_UNSAT;
+  else if(object == 1) cm->status = SAT_SAT;
+
+
+  if(cm->status == 0) {
+    if(object!=-1){
+      cm->obj = sat_ArrayAlloc(1);
+      sat_ArrayInsert(cm->obj, object);
+    }
+
+    option = sat_InitOption();
+    option->ForceFinish = 1;
+
+    option->coreGeneration = 1;
+    option->clauseDeletionHeuristic = 0;
+    option->includeLevelZeroLiteral = 1;
+    option->minimizeConflictClause = 0;
+    option->IP = 0;
+    option->RT = 1;
+    option->verbose = pm->verbosity;
+
+    cm->anteTable = st_init_table(st_numcmp,st_numhash);
+    cm->RTreeTable = st_init_table(st_ptrcmp,st_ptrhash);
+
+    cm->option = option;
+    cm->each = sat_InitStatistics();
+
+    BmcRestoreAssertion(manager,cm);
+
+    sat_CleanDatabase(cm);
+
+    /* WOCOI: NO set cone of influence*/
+    sat_AllocLiteralsDB(cm);
+  }
+  return cm;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Free a PureSAT manager]
+
+  Description [Free a PureSAT manager]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+void PureSat_SatFreeManager(satManager_t*cm)
+{
+satVariable_t var;
+satLevel_t *d;
+int i;
+
+
+  if(cm->option->coreGeneration){
+    st_free_table(cm->anteTable);
+    st_free_table(cm->RTreeTable);
+
+    cm->anteTable=0;
+    cm->RTreeTable=0;
+  }
+
+  /*timeframe, timeframeWOI,HashTable can't be freed*/
+
+  if(cm->option)	sat_FreeOption(cm->option);
+  if(cm->total)		sat_FreeStatistics(cm->total);
+  if(cm->each)		sat_FreeStatistics(cm->each);
+
+  if(cm->literals)	sat_FreeLiteralsDB(cm->literals);
+
+  cm->option=0;
+  cm->total=0;
+  cm->each=0;
+  cm->literals=0;
+
+  if(cm->decisionHead) {
+    for(i=0; i<cm->decisionHeadSize; i++) {
+      d = &(cm->decisionHead[i]);
+      if(d->implied)
+	sat_ArrayFree(d->implied);
+      if(d->satisfied)
+	sat_ArrayFree(d->satisfied);
+    }
+    free(cm->decisionHead);
+    cm->decisionHead = 0;
+    cm->decisionHeadSize = 0;
+  }
+
+  if(cm->queue)		sat_FreeQueue(cm->queue);
+  if(cm->BDDQueue)	sat_FreeQueue(cm->BDDQueue);
+  if(cm->unusedAigQueue)sat_FreeQueue(cm->unusedAigQueue);
+  cm->queue = 0;
+  cm->BDDQueue = 0;
+  cm->unusedAigQueue = 0;
+
+  if(cm->auxObj)               sat_ArrayFree(cm->auxObj);
+  if(cm->obj)                  sat_ArrayFree(cm->obj);
+  if(cm->unitLits)             sat_ArrayFree(cm->unitLits);
+  if(cm->pureLits)             sat_ArrayFree(cm->pureLits);
+  if(cm->assertion)            sat_ArrayFree(cm->assertion);
+  if(cm->auxArray)             sat_ArrayFree(cm->auxArray);
+  if(cm->nonobjUnitLitArray)   sat_ArrayFree(cm->nonobjUnitLitArray);
+  if(cm->objUnitLitArray)      sat_ArrayFree(cm->objUnitLitArray);
+  if(cm->orderedVariableArray) sat_ArrayFree(cm->orderedVariableArray);
+  if(cm->savedConflictClauses) sat_ArrayFree(cm->savedConflictClauses);
+
+  cm->auxObj = 0;
+  cm->obj = 0;
+  cm->unitLits = 0;
+  cm->pureLits = 0;
+  cm->assertion = 0;
+  cm->auxArray = 0;
+  cm->nonobjUnitLitArray = 0;
+  cm->objUnitLitArray = 0;
+  cm->orderedVariableArray = 0;
+
+  if(cm->variableArray) {
+    for(i=0; i<cm->initNumVariables; i++) {
+      var = cm->variableArray[i];
+      if(var.wl[0]) {
+	sat_ArrayFree(var.wl[0]);
+	var.wl[0] = 0;
+      }
+      if(var.wl[1]) {
+	sat_ArrayFree(var.wl[1]);
+	var.wl[1] = 0;
+      }
+    }
+    free(cm->variableArray);
+    cm->variableArray = 0;
+  }
+
+  if(cm->comment)	free(cm->comment);
+  cm->comment=0;
+
+  FREE(cm);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Print the status of AIG]
+
+  Description [Print the status of AIG]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+void PureSat_PrintAigStatus(mAig_Manager_t *manager)
+{
+  (void) fprintf(vis_stdout,"Maximum number of nodes: %ld\n",
+		 manager->maxNodesArraySize/bAigNodeSize);
+  (void) fprintf(vis_stdout,"Current number of nodes: %ld\n",
+		 manager->nodesArraySize/bAigNodeSize);
+  fprintf(vis_stdout,"Current Max Node Index: %ld\n\n",
+	  manager->nodesArraySize);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Mark global variables]
+
+  Description [Mark global variables]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSat_MarkGlobalVar(bAig_Manager_t *manager,
+			   int length)
+{
+  bAigTimeFrame_t * tf = manager->timeframeWOI;
+  bAigEdge_t * li,* bli,node;
+  int i;
+
+  li = tf->latchInputs[length];
+  bli = tf->blatchInputs[length];
+
+  for(i=0; i<tf->nLatches; i++){
+    node = bAig_NonInvertedEdge(li[i]);
+    manager->NodesArray[node+bAigFlags] |= IsGlobalVarMask;
+  }
+
+  for(i=0; i<tf->nbLatches; i++){
+    node = bAig_NonInvertedEdge(bli[i]);
+    manager->NodesArray[node+bAigFlags] |= IsGlobalVarMask;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [UnMark global variables]
+
+  Description [UnMark global variables]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSat_UnMarkGlobalVar(bAig_Manager_t *manager,
+			   int length)
+{
+  bAigTimeFrame_t * tf = manager->timeframeWOI;
+  bAigEdge_t * li,* bli,node;
+  int i;
+
+  li = tf->latchInputs[length];
+  bli = tf->blatchInputs[length];
+
+  for(i=0; i<tf->nLatches; i++){
+    node = bAig_NonInvertedEdge(li[i]);
+    manager->NodesArray[node+bAigFlags] &= ResetGlobalVarMask;
+  }
+
+  for(i=0; i<tf->nbLatches; i++){
+    node = bAig_NonInvertedEdge(bli[i]);
+    manager->NodesArray[node+bAigFlags] &= ResetGlobalVarMask;
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makr global variable for abstraction refinement]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSat_MarkGlobalVar_AbRf(bAig_Manager_t *manager,
+				int length)
+{
+  bAigTimeFrame_t * tf = manager->timeframeWOI;
+  bAigEdge_t * li,* bli,node;
+  int i;
+
+
+  li = tf->latchInputs[length];
+  bli = tf->blatchInputs[length];
+
+  for(i=0; i<tf->nLatches; i++){
+    node = bAig_NonInvertedEdge(li[i]);
+    if(flags(node)&VisibleVarMask)
+      manager->NodesArray[node+bAigFlags] |= IsGlobalVarMask;
+  }
+
+  for(i=0; i<tf->nbLatches; i++){
+    node = bAig_NonInvertedEdge(bli[i]);
+    if(flags(node)&VisibleVarMask)
+      manager->NodesArray[node+bAigFlags] |= IsGlobalVarMask;
+  }
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Mark visible variable and also mark visible pseudo global variable]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PuresatMarkVisibleVarWithVPGV(Ntk_Network_t *network,
+				  array_t * visibleArray,
+				  PureSat_Manager_t *pm,
+				  int from,
+				  int to)
+{
+
+  mAig_Manager_t * manager = Ntk_NetworkReadMAigManager(network);
+  st_table * node2MvfAigTable =(st_table *) Ntk_NetworkReadApplInfo(network,
+							 MVFAIG_NETWORK_APPL_KEY);
+  MvfAig_Function_t *mvfAig;
+  bAigTimeFrame_t * tf = manager->timeframeWOI;
+  mAigMvar_t lmVar;
+  mAigBvar_t bVar;
+  array_t *bVarList,*mVarList;
+  int i,j,k,lmAigId,index,index1;
+  char * name;
+  Ntk_Node_t * latch;
+  bAigEdge_t node,v, *li, *bli;
+
+  bVarList = mAigReadBinVarList(manager);
+  mVarList = mAigReadMulVarList(manager);
+
+  /*Although some SV in tf 0 are not marked as visiblevar,
+    //they actually visible since all SV of tf 0 are visible*/
+  if(from<0)
+    from=0;
+  if(to>pm->Length+1)
+    to=pm->Length+1;
+
+  /*clean VPGV mask*/
+  li = tf->latchInputs[1];
+  bli = tf->blatchInputs[1];
+  for(j=0;j<tf->nLatches;j++)
+    flags(li[j])&=ResetVPGVMask;
+  for(j=0;j<tf->nbLatches;j++)
+    flags(bli[j])&=ResetVPGVMask;
+
+  for(i=from;i<=to;i++){
+    li = tf->latchInputs[i];
+    bli = tf->blatchInputs[i];
+    arrayForEachItem(char *,visibleArray,k,name){
+      int retVal;
+      latch = Ntk_NetworkFindNodeByName(network,name);
+      st_lookup(node2MvfAigTable,latch,&mvfAig);
+      for(j=0;j<mvfAig->num;j++){
+	v = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(mvfAig,j));
+	if(v==bAig_Zero||v==bAig_One)
+	  continue;
+	retVal = st_lookup(tf->li2index,(char*)v,&index);
+	assert(retVal);
+	if(li[index]==bAig_Zero||li[index]==bAig_One)
+	  continue;
+	node = bAig_NonInvertedEdge(li[index]);
+	manager->NodesArray[node+bAigFlags] |= VisibleVarMask;
+	/*marking PGV*/
+	if(i==1){
+	  if(!st_lookup(pm->vertexTable,name,NIL(char*))){
+	    flags(node) |= VPGVMask;
+
+	  }
+	}
+      }
+
+
+      lmAigId = Ntk_NodeReadMAigId(latch);
+      lmVar = array_fetch(mAigMvar_t, mVarList,lmAigId);
+      for(j=0,index1=lmVar.bVars;j<lmVar.encodeLength;j++,index1++){
+	int retVal;
+	bVar = array_fetch(mAigBvar_t,bVarList,index1);
+	if(bVar.node==bAig_Zero||bVar.node==bAig_One)
+	  continue;
+	retVal = st_lookup(tf->bli2index,(char*)bVar.node,&index);
+	assert(retVal);
+	if(bli[index]==bAig_Zero||bli[index]==bAig_One)
+	  continue;
+	node = bAig_NonInvertedEdge(bli[index]);
+	manager->NodesArray[node+bAigFlags] |= VisibleVarMask;
+	/*marking PGV*/
+	if(i==1){
+	  if(!st_lookup(pm->vertexTable,name,NIL(char*)))
+	    flags(node) |= VPGVMask;
+	}
+      }
+    }
+  }
+  return;
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Mark visible latch variables]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PuresatMarkVisibleVar(Ntk_Network_t *network,
+			   array_t * visibleArray,
+			   PureSat_Manager_t *pm,
+			   int from,
+			   int to)
+{
+
+  mAig_Manager_t * manager = Ntk_NetworkReadMAigManager(network);
+  st_table * node2MvfAigTable =(st_table *) Ntk_NetworkReadApplInfo(network,
+							 MVFAIG_NETWORK_APPL_KEY);
+  MvfAig_Function_t *mvfAig;
+  bAigTimeFrame_t * tf = manager->timeframeWOI;
+  mAigMvar_t lmVar;
+  mAigBvar_t bVar;
+  array_t *bVarList,*mVarList;
+  int i,j,k,lmAigId,index,index1;
+  char * name;
+  Ntk_Node_t * latch;
+  bAigEdge_t node,v, *li, *bli;
+
+  bVarList = mAigReadBinVarList(manager);
+  mVarList = mAigReadMulVarList(manager);
+
+
+  if(from<0)
+    from=0;
+  if(to>pm->Length+1)
+    to=pm->Length+1;
+
+  for(i=from;i<=to;i++){
+    li = tf->latchInputs[i];
+    bli = tf->blatchInputs[i];
+    arrayForEachItem(char *,visibleArray,k,name){
+      latch = Ntk_NetworkFindNodeByName(network,name);
+      st_lookup(node2MvfAigTable,latch,&mvfAig);
+      /*multi val var*/
+      for(j=0;j<mvfAig->num;j++){
+	int retVal;
+	v = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(mvfAig,j));
+	if(v==bAig_Zero||v==bAig_One)
+	  continue;
+	retVal = st_lookup(tf->li2index,(char*)v,&index);
+	assert(retVal);
+	if(li[index]==bAig_Zero||li[index]==bAig_One)
+	  continue;
+	node = bAig_NonInvertedEdge(li[index]);
+	manager->NodesArray[node+bAigFlags] |= VisibleVarMask;
+      }
+
+      /*binary var*/
+      lmAigId = Ntk_NodeReadMAigId(latch);
+      lmVar = array_fetch(mAigMvar_t, mVarList,lmAigId);
+      for(j=0,index1=lmVar.bVars;j<lmVar.encodeLength;j++,index1++){
+	int retVal;
+	bVar = array_fetch(mAigBvar_t,bVarList,index1);
+	if(bVar.node==bAig_Zero||bVar.node==bAig_One)
+	  continue;
+	retVal = st_lookup(tf->bli2index,(char*)bVar.node,&index);
+	assert(retVal);
+	if(bli[index]==bAig_Zero||bli[index]==bAig_One)
+	  continue;
+	node = bAig_NonInvertedEdge(bli[index]);
+	manager->NodesArray[node+bAigFlags] |= VisibleVarMask;
+      }
+    }// arrayForEachItem(char *,visibleArray,k,name)
+  }
+
+  return;
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Recursively mapping interpolant from a timeframe to another timeframe]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+bAigEdge_t PureSat_MapIPRecur(mAig_Manager_t *manager,
+			 bAigEdge_t  node,
+			 st_table * tmpTable)
+{
+  bAigEdge_t v,result,left,right;
+  int isInverted;
+
+#if DBG
+  assert(node!=bAig_NULL);
+#endif
+  if(node == bAig_One || node == bAig_Zero){
+    return node;
+  }
+
+  if(st_lookup(tmpTable,(char *)bAig_NonInvertedEdge(node),&v)){
+    if(bAig_IsInverted(node))
+      result = bAig_Not(v);
+    else
+      result = v;
+
+    return result;
+  }
+
+  left = PureSat_MapIPRecur(manager,leftChild(node),tmpTable);
+  right = PureSat_MapIPRecur(manager,rightChild(node),tmpTable);
+
+  v = PureSat_And(manager,left,right);
+  isInverted = bAig_IsInverted(node);
+  result = isInverted ? bAig_Not(v) : v;
+  st_insert(tmpTable,(char *)bAig_NonInvertedEdge(node),(char *)v);
+
+  //fprintf(vis_stdout,"return %d->%d\n",node,result);
+  return result;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Maping interpolant from a timeframe to another timeframe]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+bAigEdge_t PureSat_MapIP(mAig_Manager_t *manager,
+			 bAigEdge_t node,
+			 int from,
+			 int to)
+{
+  bAigTimeFrame_t *tf = manager->timeframeWOI;
+  st_table *tmpTable = st_init_table(st_numcmp,st_numhash);
+  bAigEdge_t * L1,*L0,result,v1,v0;
+  int i;
+
+  if(node==bAig_One||node==bAig_Zero)
+    return node;
+
+  L1 = tf->latchInputs[from];
+  L0 = tf->latchInputs[to];
+  for(i=0;i<tf->nLatches;i++){
+   v1 = L1[i];
+   v0 = L0[i];
+   if(SATisInverted(v1)){
+     v1 = SATnot(v1);
+     v0 = SATnot(v0);
+   }
+   st_insert(tmpTable,(char*)v1,(char*)v0);
+
+  }
+  L1 = tf->blatchInputs[from];
+  L0 = tf->blatchInputs[to];
+  for(i=0;i<tf->nbLatches;i++){
+    v1 = L1[i];
+    v0 = L0[i];
+    if(SATisInverted(v1)){
+      v1 = SATnot(v1);
+      v0 = SATnot(v0);
+    }
+    st_insert(tmpTable,(char*)v1,(char*)v0);
+
+  }
+
+  manager->class_ = to;
+  result = PureSat_MapIPRecur(manager,node,tmpTable);
+
+  st_free_table(tmpTable);
+
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [process dummy nodes]
+
+  Description [In UNSAT core, there may be dummy nodes, but in manager,
+	       they don't exist any more. This funct is to mark them]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSatProcessDummy(bAig_Manager_t *manager,
+			 satManager_t *cm,
+			 RTnode_t  RTnode)
+{
+  int i;
+  bAigEdge_t *lp,node;
+  RTManager_t *rm = cm->rm;
+
+  if(RT_flag(RTnode)&RT_VisitedMask){
+    return;
+  }
+  RT_flag(RTnode) |= RT_VisitedMask;
+
+  if(RT_pivot(RTnode)==0){ /*leaf*/
+#if DBG
+    assert(RT_oriClsIdx(RTnode)==0);
+#endif
+    if(RT_oriClsIdx(RTnode))
+      lp = (long*)SATfirstLit(RT_oriClsIdx(RTnode));
+    else
+
+      lp = RT_formula(RTnode) + cm->rm->fArray;
+    for(i=0;i<RT_fSize(RTnode);i++,lp++){
+      assert(*lp>0);/* not processed yet*/
+      if(RT_oriClsIdx(RTnode))/*is CNF*/
+	node = SATgetNode(*lp);
+      else /*is AIG*/
+	node = *lp;
+      node = SATnormalNode(node);
+      if(node>=manager->nodesArraySize){
+#if DBG
+	assert(flags(node)&DummyMask);
+#endif
+	*lp = DUMMY;
+      }
+    }
+  } /*leaf*/
+
+  /*not leaf*/
+  else{
+    if(RT_pivot(RTnode)>=manager->nodesArraySize){
+      int class_ = bAig_Class(RT_pivot(RTnode));
+      RT_pivot(RTnode) = DUMMY+class_;
+    }
+    PureSatProcessDummy(manager,cm,RT_left(RTnode));
+    PureSatProcessDummy(manager,cm,RT_right(RTnode));
+  }
+
+  return ;
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Find an aig node from its name]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+bAigEdge_t
+PureSat_FindNodeByName(
+  bAig_Manager_t *manager,
+  nameType_t     *name,
+  int bound)
+{
+
+  bAigEdge_t node;
+
+  if (!st_lookup(manager->SymbolTableArray[bound], name, &node)){
+    node = bAig_NULL;
+  }
+
+  return bAig_GetCanonical(manager, node);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Create Aig for a ltl formula]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+bAigEdge_t
+PureSatCreatebAigOfPropFormula(
+    Ntk_Network_t *network,
+    bAig_Manager_t *manager,
+    int bound,
+    Ctlsp_Formula_t *ltl,
+    int withInitialState)
+{
+  int index;
+  bAigEdge_t result, left, right, *li;
+  bAigTimeFrame_t *timeframe;
+
+  if (ltl == NIL(Ctlsp_Formula_t))	return bAig_NULL;
+  if (ltl->type == Ctlsp_TRUE_c)	return bAig_One;
+  if (ltl->type == Ctlsp_FALSE_c)	return bAig_Zero;
+
+  assert(Ctlsp_isPropositionalFormula(ltl));
+
+  if(withInitialState) timeframe = manager->timeframe;
+  else	               timeframe = manager->timeframeWOI;
+
+  if (ltl->type == Ctlsp_ID_c){
+      char *nodeNameString  = Ctlsp_FormulaReadVariableName(ltl);
+      char *nodeValueString = Ctlsp_FormulaReadValueName(ltl);
+      Ntk_Node_t *node      = Ntk_NetworkFindNodeByName(network, nodeNameString);
+
+      Var_Variable_t *nodeVar;
+      int             nodeValue;
+
+      MvfAig_Function_t  *tmpMvfAig;
+      st_table           *nodeToMvfAigTable; /* maps each node to its mvfAig */
+
+      if (node == NIL(Ntk_Node_t)) {
+	char   *nameKey;
+	char   tmpName[100];
+
+	sprintf(tmpName, "%s_%d", nodeNameString, bound);
+	nameKey = util_strsav(tmpName);
+
+	result  = PureSat_FindNodeByName(manager, nameKey,bound);
+	if(result == bAig_NULL){
+	   result = PureSat_CreateVarNode(manager, nameKey);
+	} else {
+
+	  FREE(nameKey);
+	}
+	return result;
+      }
+
+      nodeToMvfAigTable = (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+      assert(nodeToMvfAigTable != NIL(st_table));
+
+      tmpMvfAig = Bmc_ReadMvfAig(node, nodeToMvfAigTable);
+      if (tmpMvfAig ==  NIL(MvfAig_Function_t)){
+	  tmpMvfAig = Bmc_NodeBuildMVF(network, node);
+	  array_free(tmpMvfAig);
+	  tmpMvfAig = Bmc_ReadMvfAig(node, nodeToMvfAigTable);
+      }
+
+      nodeVar = Ntk_NodeReadVariable(node);
+      if (Var_VariableTestIsSymbolic(nodeVar)) {
+	nodeValue = Var_VariableReadIndexFromSymbolicValue(nodeVar, nodeValueString);
+	if ( nodeValue == -1 ) {
+	  (void) fprintf(vis_stderr, "Value specified in RHS is not in domain of variable\n");
+	  (void) fprintf(vis_stderr,"%s = %s\n", nodeNameString, nodeValueString);
+	  return bAig_NULL;
+	}
+      }
+      else {
+	int check;
+	 check = StringCheckIsInteger(nodeValueString, &nodeValue);
+	 if( check == 0 ) {
+	  (void) fprintf(vis_stderr,"Illegal value in the RHS\n");
+	  (void) fprintf(vis_stderr,"%s = %s\n", nodeNameString, nodeValueString);
+	  return bAig_NULL;
+	 }
+	 if( check == 1 ) {
+	  (void) fprintf(vis_stderr,"Value in the RHS is out of range of int\n");
+	  (void) fprintf(vis_stderr,"%s = %s", nodeNameString, nodeValueString);
+	  return bAig_NULL;
+	 }
+	 if ( !(Var_VariableTestIsValueInRange(nodeVar, nodeValue))) {
+	  (void) fprintf(vis_stderr,"Value specified in RHS is not in domain of variable\n");
+	  (void) fprintf(vis_stderr,"%s = %s\n", nodeNameString, nodeValueString);
+	  return bAig_NULL;
+
+	 }
+      }
+      result = MvfAig_FunctionReadComponent(tmpMvfAig, nodeValue);
+      result = bAig_GetCanonical(manager, result);
+      if(st_lookup(timeframe->li2index, (char *)result, &index)) {
+	li = timeframe->latchInputs[bound];
+	result = bAig_GetCanonical(manager, li[index]);
+      }
+      else if(st_lookup(timeframe->o2index, (char *)result, &index)) {
+	li = timeframe->outputs[bound];
+	result = bAig_GetCanonical(manager, li[index]);
+
+      }
+      else if(st_lookup(timeframe->i2index, (char *)result, &index)) {
+	li = timeframe->internals[bound];
+	result = bAig_GetCanonical(manager, li[index]);
+
+      }
+      return result;
+  }
+
+  left = PureSatCreatebAigOfPropFormula(network, manager, bound, ltl->left, withInitialState);
+  if (left == bAig_NULL){
+    return bAig_NULL;
+  }
+  right = PureSatCreatebAigOfPropFormula(network, manager, bound, ltl->right, withInitialState);
+  if (right == bAig_NULL && ltl->type ==Ctlsp_NOT_c ){
+    return bAig_Not(left);
+  }
+  else if(right == bAig_NULL) {
+    return bAig_NULL;
+  }
+
+  switch(ltl->type) {
+
+    case Ctlsp_OR_c:
+      result = PureSat_Or(manager, left, right);
+      break;
+    case Ctlsp_AND_c:
+      result = PureSat_And(manager, left, right);
+      break;
+    case Ctlsp_THEN_c:
+      result = PureSat_Then(manager, left, right);
+      break;
+    case Ctlsp_EQ_c:
+      result = PureSat_Eq(manager, left, right);
+      break;
+    case Ctlsp_XOR_c:
+      result = PureSat_Xor(manager, left, right);
+      break;
+    default:
+      fail("Unexpected type");
+  }
+  return result;
+} /* BmcCirCUsCreatebAigOfPropFormula */
+
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Mark all node between from and to with obj mask]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+
+void PureSatMarkObj(bAig_Manager_t * manager,
+		    long from,
+		    long to)
+{
+  long v;
+
+  for(v=from;v<=to;v+=bAigNodeSize)
+    flags(v)|=ObjMask;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [procedure of concretization]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+boolean PureSat_ConcretTest(Ntk_Network_t *network,
+			    PureSat_Manager_t *pm,
+			    array_t *sufArray,
+			    bAigEdge_t property,
+			    array_t *previousResultArray,
+			    int Con,
+			    int satStat,
+			    int inc)
+{
+  mAig_Manager_t * manager = Ntk_NetworkReadMAigManager(network);
+  int status,i,nodes_in_coi=0;
+  satManager_t *cm;
+  char *name;
+  double t1,t2;
+  satArray_t *saved;
+  st_table * SufAbsNameTable = st_init_table(strcmp,st_strhash);
+  bAigEdge_t from,*lp;
+
+   arrayForEachItem(char *,sufArray,i,name){
+    st_insert(SufAbsNameTable,name,(char*)0);
+   }
+
+   manager->assertArray = sat_ArrayAlloc(1);
+  sat_ArrayInsert(manager->assertArray,manager->InitState);
+  cm = PureSat_SatManagerAlloc_WOCOI(manager,pm,property,previousResultArray);
+
+  cm->option->coreGeneration = 0;
+  cm->option->RT = 0;
+  cm->option->AbRf = 1;
+  if(inc){
+    cm->option->incTraceObjective = 1;
+    cm->savedConflictClauses = pm->savedConCls;
+    pm->savedConCls = 0;
+  }
+  t1 = util_cpu_ctime();
+  PureSat_CleanMask(manager,ResetVisibleVarMask);
+  PuresatMarkVisibleVar(network,sufArray,pm,0,pm->Length+1);
+  if(!Con){
+    from = manager->nodesArraySize;
+    PureSatSetCOI(network,pm,cm,SufAbsNameTable,0,pm->Length,pm->Length);
+    PureSatKillPseudoGV(network,pm,SufAbsNameTable,1,pm->Length);
+    if(inc){
+      PureSatMarkObj(manager,from,manager->nodesArraySize-bAigNodeSize);
+    }
+    PureSat_ResetManager(manager,cm,0);
+    PureSatProcessFanout(cm);
+  }
+  else{
+    sat_MarkTransitiveFaninForNode(cm,property,CoiMask);
+    sat_MarkTransitiveFaninForNode(cm,manager->InitState,CoiMask);
+    cm->option->AbRf = 0;
+  }
+  t2 = util_cpu_ctime();
+  pm->tPro += t2-t1;
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"process time:%g,total:%g\n",
+	   (double)((t2-t1)/1000.0),pm->tPro/1000);
+  if(pm->verbosity>=1){
+    nodes_in_coi = PureSat_CountNodesInCoi(cm);
+    fprintf(vis_stdout,"There are %d node in COI\n",nodes_in_coi);
+  }
+  st_free_table(SufAbsNameTable);
+  manager->assertArray2 = cm->assertArray2;
+  sat_Main(cm);
+  if(satStat)
+    sat_ReportStatistics(cm,cm->each);
+  cm->option->AbRf = 1;
+  manager->NodesArray = cm->nodesArray;
+  t1 = util_cpu_ctime();
+  if(!Con){
+    PureSatRecoverFanout(cm,pm);
+    PureSat_RestoreAigForDummyNode(manager,pm->oldPos);
+    PureSat_CleanMask(manager,ResetVisited3Mask);
+  }
+  /*record conflict*/
+  if(inc && cm->savedConflictClauses ){
+    if(!Con){
+      int num=0;
+      saved = cm->savedConflictClauses;
+      pm->savedConCls = sat_ArrayAlloc(1);
+      for(i=0, lp=saved->space; i<saved->num; i++, lp++){
+	sat_ArrayInsert(pm->savedConCls,*lp);
+	if(*lp<0)
+	  num++;
+      }
+      assert(num%2==0);
+      if(pm->verbosity>=2)
+	fprintf(vis_stdout,"record %d ConCls for incremental concretization\n",num/2);
+    }
+    else
+      pm->savedConCls = 0;
+    sat_ArrayFree(cm->savedConflictClauses);
+    cm->savedConflictClauses = 0;
+  }
+  t2 = util_cpu_ctime();
+  pm->tPro += t2-t1;
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"process time:%g,total:%g\n",
+	   (double)((t2-t1)/1000.0),pm->tPro/1000);
+  sat_ArrayFree(manager->assertArray);
+  status = cm->status;
+  cm->option->coreGeneration = 1;
+  PureSat_SatFreeManager(cm);
+  if(status == SAT_SAT){
+    if(pm->verbosity>=1)
+      fprintf(vis_stdout,"CEX exist\n");
+    return FALSE; /* cex exists*/
+  }
+  else{
+    if(pm->verbosity>=1)
+      fprintf(vis_stdout,"no CEX\n");
+    return TRUE;   /* no cex*/
+  }
+
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Concretization procedure for unsat proof-based refinement minimization]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+
+boolean PureSat_ConcretTest_Core(Ntk_Network_t *network,
+				 PureSat_Manager_t *pm,
+				 array_t *sufArray,
+				 bAigEdge_t property,
+				 array_t *previousResultArray,
+				 st_table * junkTable)
+{
+  mAig_Manager_t * manager = Ntk_NetworkReadMAigManager(network);
+  int status,i,nodes_in_coi=0;
+  satManager_t *cm;
+  char *name;
+  double t1,t2;
+  st_table * SufAbsNameTable = st_init_table(strcmp,st_strhash);
+  array_t * tmpRef1;
+  st_table *refTable = st_init_table(strcmp,st_strhash);
+
+  arrayForEachItem(char *,sufArray,i,name){
+    st_insert(SufAbsNameTable,name,(char*)0);
+  }
+
+  manager->assertArray = sat_ArrayAlloc(1);
+  sat_ArrayInsert(manager->assertArray,manager->InitState);
+  cm = PureSat_SatManagerAlloc_WOCOI(manager,pm,property,previousResultArray);
+  cm->option->coreGeneration = 1;
+  cm->option->AbRf = 1;
+  cm->option->IP = 1;
+  t1 = util_cpu_ctime();
+  PureSat_CleanMask(manager,ResetVisibleVarMask);
+  PuresatMarkVisibleVarWithVPGV(network,sufArray,pm,0,pm->Length+1);
+
+    PureSatSetCOI(network,pm,cm,SufAbsNameTable,0,pm->Length,pm->Length);
+    PureSatKillPseudoGV(network,pm,SufAbsNameTable,1,pm->Length);
+    PureSat_ResetManager(manager,cm,0);
+    PureSatProcessFanout(cm);
+
+  t2 = util_cpu_ctime();
+  pm->tPro += t2-t1;
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"process time:%g,total:%g\n",
+	   (double)((t2-t1)/1000.0),pm->tPro/1000);
+  if(pm->verbosity>=1){
+    nodes_in_coi = PureSat_CountNodesInCoi(cm);
+    fprintf(vis_stdout,"There are %d node in COI\n",nodes_in_coi);
+  }
+  manager->assertArray2 = cm->assertArray2;
+  sat_Main(cm);
+  manager->NodesArray = cm->nodesArray;
+  t1 = util_cpu_ctime();
+    PureSatRecoverFanout(cm,pm);
+    PureSat_RestoreAigForDummyNode(manager,pm->oldPos);
+    PureSat_CleanMask(manager,ResetVisited3Mask);
+    if(cm->status==SAT_UNSAT){
+      PureSatProcessDummy(manager,cm,cm->rm->root);
+      ResetRTree(cm->rm);
+    }
+  t2 = util_cpu_ctime();
+  pm->tPro += t2-t1;
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"process time:%g,total:%g\n",
+	   (double)((t2-t1)/1000.0),pm->tPro/1000);
+
+  if(cm->status==SAT_UNSAT){
+    tmpRef1 = PureSat_GetSufAbsFromCore(network,cm,pm,property,SufAbsNameTable);
+
+    arrayForEachItem(char*,tmpRef1,i,name)
+      st_insert(refTable,name,(char*)0);
+
+    arrayForEachItem(char*,sufArray,i,name){
+      if(!st_lookup(refTable,name,NIL(char*))&&
+	 !st_lookup(pm->vertexTable,name,NIL(char*))){
+	if(pm->verbosity>=2)
+	  fprintf(vis_stdout,"%s can be gotten rid of\n",name);
+	st_insert(junkTable,name,(char*)0);
+      }
+    }
+    array_free(tmpRef1);
+  }
+
+  st_free_table(SufAbsNameTable);
+  st_free_table(refTable);
+  RT_Free(cm->rm);
+  sat_ArrayFree(manager->assertArray);
+  status = cm->status;
+  cm->option->coreGeneration = 1;
+  PureSat_SatFreeManager(cm);
+  if(status == SAT_SAT){
+    if(pm->verbosity>=1)
+      fprintf(vis_stdout,"CEX exist\n");
+    return FALSE; // cex exists
+  }
+  else{
+    if(pm->verbosity>=1)
+      fprintf(vis_stdout,"no CEX\n");
+    return TRUE;   // no cex
+  }
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generate BFS ring for a network node]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+void PureSatGenerateRingForNode(Ntk_Network_t *network,
+				PureSat_Manager_t *pm,
+				Ntk_Node_t * node1,
+				array_t * ringArray,
+				int *dfs)
+{
+  Ntk_Node_t *node;
+  char *name;
+  int i;
+
+  if(PureSatNodeReadColor(node1) == dfsBlack_c)
+    return;
+  PureSatNodeSetColor(node1,dfsBlack_c);
+  if(Ntk_NodeTestIsLatch(node1)){
+    name = Ntk_NodeReadName(node1);
+    st_insert(pm->node2dfsTable,name,(char*)(long)(*dfs));
+    array_insert_last(char *,ringArray,name);
+    return;
+  }
+
+  Ntk_NodeForEachFanin(node1,i,node){
+    PureSatGenerateRingForNode(network,pm,node,ringArray,
+			       dfs);
+  }
+  return;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generate BFS ring for one array]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+array_t * PureSatGenerateRing(Ntk_Network_t *network,
+			      PureSat_Manager_t *pm,
+			      array_t * coreArray,
+			      int * dfs)
+{
+  array_t * ringArray = array_alloc(char *,0);
+  int i,j;
+  char *name;
+  Ntk_Node_t *node1,*node;
+
+  arrayForEachItem(char *,coreArray,i,name){
+    node1 = Ntk_NetworkFindNodeByName(network,name);
+    Ntk_NodeForEachFanin(node1,j,node){
+      PureSatGenerateRingForNode(network,pm,node,
+				 ringArray,dfs);
+    }
+  }
+  return ringArray;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generate the ring information for the whole circuit]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSatGenerateDfs(Ntk_Network_t *network,
+			PureSat_Manager_t *pm,
+			array_t * vertexArray)
+{
+
+  int dfs = 1,i,ct=0;
+  char *name;
+  Ntk_Node_t *node;
+  array_t * ringArray = array_alloc(char *,0);
+  array_t * coreArray;
+  lsGen gen;
+  st_generator * stgen;
+
+  Ntk_NetworkForEachNode( network, gen, node ) {
+    PureSatNodeSetColor( node, dfsWhite_c );
+  }
+
+  arrayForEachItem(char *,vertexArray,i,name){
+    st_insert(pm->node2dfsTable,name,(char*)(long)dfs);
+    node = Ntk_NetworkFindNodeByName(network,name);
+    PureSatNodeSetColor(node,dfsBlack_c);
+    ct++;
+  }
+
+  coreArray = array_dup(vertexArray);
+
+  while(coreArray->num>0){
+    dfs++;
+    ringArray = PureSatGenerateRing(network,pm,coreArray,
+				    &dfs);
+    arrayForEachItem(char*,ringArray,i,name){
+      st_insert(pm->node2dfsTable,name,(char*)(long)dfs);
+
+      ct++;
+    }
+    array_free(coreArray);
+    coreArray = ringArray;
+  }
+
+  st_foreach_item(pm->CoiTable,stgen,&node,NIL(char*)){
+    name = Ntk_NodeReadName(node);
+    if(!st_lookup(pm->node2dfsTable,name,NIL(char*))){
+      st_insert(pm->node2dfsTable,name,(char*)LARGEDFS);
+      if(pm->verbosity>=2)
+	fprintf(vis_stdout,"%s LARGEDFS is inserted into node2dfsTable\n",name);
+    }
+  }
+
+  return;
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Sort latch candidate based on BFS ring and RC information]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+array_t * PureSatComputeOrder_2(Ntk_Network_t *network,
+			      PureSat_Manager_t *pm,
+			      array_t * vertexArray,
+			      array_t * invisibleArray,
+			      int * sccArray,
+			      int * NumInSecondLevel)
+{
+
+  array_t * RCArray;
+
+  PureSatGenerateDfs(network,pm,vertexArray);
+  RCArray = PureSatGenerateRCArray_2(network,pm,invisibleArray,
+				   NumInSecondLevel);
+
+  return RCArray;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Some latches have the same aig node, add them all to
+  abstractions once one is added. ]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSatAddIdenLatchToAbs(Ntk_Network_t *network,
+			      PureSat_Manager_t *pm,
+			      array_t *nameArray)
+{
+  int i;
+  st_generator * stgen;
+  st_table* table;
+  char *name,*name1;
+  st_table *table1 = st_init_table(st_ptrcmp,st_ptrhash);
+  array_t * tmpArray = array_alloc(char*,0);
+
+  st_foreach_item(pm->vertexTable,stgen,&name,NIL(char*))
+    st_insert(table1,name,(char*)0);
+  arrayForEachItem(char*,nameArray,i,name)
+    st_insert(table1,name,(char*)0);
+
+  arrayForEachItem(char*,nameArray,i,name){
+
+    if(st_lookup(pm->IdenLatchTable,name,&table)){
+      st_foreach_item(table,stgen,&name1,NIL(char*)){
+	if(!st_lookup(table1,name1,NIL(char*))){
+	  st_insert(table1,name1,(char*)0);
+	  array_insert_last(char*,tmpArray,name1);
+	}
+      }
+    }
+  }
+
+  arrayForEachItem(char*,tmpArray,i,name){
+    array_insert_last(char*,nameArray,name);
+    if(pm->verbosity>=2)
+      fprintf(vis_stdout,"add %s to refineArray\n",name);
+  }
+
+  array_free(tmpArray);
+  st_free_table(table1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Create initial abstraction from aig]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+PureSatCreateInitAbsByAIG(bAig_Manager_t *manager,
+			  PureSat_Manager_t *pm,
+			  bAigEdge_t node,
+			  st_table * tmpTable)
+{
+  bAigTimeFrame_t * tf = manager->timeframeWOI;
+  char * name;
+  st_table * table;
+  st_generator * stgen;
+
+  if(node==bAig_NULL)
+    return;
+
+  node = bAig_NonInvertedEdge(node);
+
+  if(flags(node)&VisitedMask)
+    return;
+
+  flags(node) |= VisitedMask;
+
+
+  if(flags(node)&StateBitMask){
+    if(!st_lookup(tf->MultiLatchTable,(char*)node,&table)){
+      int retVal = st_lookup(tf->idx2name,(char*)node,&name);
+      assert(retVal);
+      if(!st_lookup(tmpTable,name,NIL(char*))){
+	st_insert(tmpTable,name,(char*)0);
+
+      }
+    }
+    else{
+      st_foreach_item(table,stgen,&name,NIL(char*)){
+	if(!st_lookup(tmpTable,name,NIL(char*))){
+	  st_insert(tmpTable,name,(char*)0);
+
+	}
+      }
+    }
+  }
+
+  if(flags(node)&StateBitMask)
+    return;
+
+  PureSatCreateInitAbsByAIG(manager,pm,leftChild(node),tmpTable);
+  PureSatCreateInitAbsByAIG(manager,pm,rightChild(node),tmpTable);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Get support latches for one aig node]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+void
+PureSat_GetLatchForNode(bAig_Manager_t *manager,
+			PureSat_Manager_t *pm,
+			bAigEdge_t node,
+			array_t * nameArray,
+			st_table *tmpTable,
+			int cut)
+{
+  bAigTimeFrame_t * tf = manager->timeframeWOI;
+  char * name;
+  st_table * table;
+  st_generator * stgen;
+
+  if(node==bAig_NULL)
+    return;
+
+  node = bAig_NonInvertedEdge(node);
+
+  if(flags(node)&VisitedMask)
+    return;
+
+  flags(node) |= VisitedMask;
+
+
+  if(flags(node)&StateBitMask){
+    if(!st_lookup(tf->MultiLatchTable,(char*)node,&table)){
+      int retVal = st_lookup(tf->idx2name,(char*)node,&name);
+      assert(retVal);
+      if(!st_lookup(tmpTable,name,NIL(char*))){
+	st_insert(tmpTable,name,(char*)0);
+	array_insert_last(char *,nameArray,name);
+	if(pm->verbosity>=2)
+	  fprintf(vis_stdout,"insert %s\n",name);
+      }
+    }
+    else{
+      st_foreach_item(table,stgen,&name,NIL(char*)){
+	if(!st_lookup(tmpTable,name,NIL(char*))){
+	  st_insert(tmpTable,name,(char*)0);
+	  array_insert_last(char *,nameArray,name);
+	  if(pm->verbosity>=2)
+	    fprintf(vis_stdout,"insert %s\n",name);
+	}
+      }
+    }
+  }
+
+  if(cut==2){
+    if(flags(node)&Visited2Mask)
+      return;
+  }
+  else{
+    if(cut==1){
+      if(flags(node)&Visited3Mask)
+	return;
+    }
+    else{
+      fprintf(vis_stdout,"wrong cut\n");
+      exit(0);
+    }
+  }
+
+  PureSat_GetLatchForNode(manager,pm,leftChild(node),nameArray,tmpTable,cut);
+  PureSat_GetLatchForNode(manager,pm,rightChild(node),nameArray,tmpTable,cut);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Get COI reduction based on aig, not ntk]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+st_table * PureSatGetAigCoi(Ntk_Network_t *network,
+			    PureSat_Manager_t *pm,
+			    bAigEdge_t property)
+{
+  bAig_Manager_t *manager;
+  st_table * node2MvfAigTable,*tmpTable;
+  array_t * nameArray,*nameArray1;
+  bAigTimeFrame_t *tf;
+  char * name;
+  Ntk_Node_t *latch;
+  MvfAig_Function_t *mvfAig;
+  mAigMvar_t lmVar;
+  mAigBvar_t bVar;
+  array_t *bVarList,*mVarList;
+  int i,j,lmAigId;
+  long index,index1;
+  bAigEdge_t v, *li, *bli;
+
+  manager = Ntk_NetworkReadMAigManager(network);
+  if (manager == NIL(mAig_Manager_t)) {
+    (void) fprintf(vis_stdout,
+		   "** bmc error: run build_partition_maigs command first\n");
+    exit(0);;
+  }
+  node2MvfAigTable =(st_table *) Ntk_NetworkReadApplInfo(network,
+				    MVFAIG_NETWORK_APPL_KEY);
+  tf = manager->timeframeWOI;
+
+  bVarList = mAigReadBinVarList(manager);
+  mVarList = mAigReadMulVarList(manager);
+
+  assert(manager->timeframeWOI->currentTimeframe>=2);
+  PureSat_CleanMask(manager,ResetVisitedMask);
+  PureSat_CleanMask(manager,ResetVisited2Mask);
+  PureSat_CleanMask(manager,ResetVisited3Mask);
+  li = tf->latchInputs[1];
+  for(i=0;i<tf->nLatches;i++)
+    flags(li[i])|=Visited3Mask;
+  li = tf->blatchInputs[1];
+  for(i=0;i<tf->nbLatches;i++)
+    flags(li[i])|=Visited3Mask;
+  li = tf->latchInputs[2];
+  for(i=0;i<tf->nLatches;i++)
+    flags(li[i])|=Visited2Mask;
+  li = tf->blatchInputs[2];
+  for(i=0;i<tf->nbLatches;i++)
+    flags(li[i])|=Visited2Mask;
+
+  nameArray = array_alloc(char *,0);
+  tmpTable = st_init_table(st_ptrcmp,st_ptrhash);
+  PureSat_GetLatchForNode(manager,pm,property,nameArray,tmpTable,2);
+  PureSat_CleanMask(manager,ResetVisitedMask);
+
+
+  li = tf->latchInputs[2];
+  bli = tf->blatchInputs[2];
+  while(nameArray->num>0){
+    nameArray1 = nameArray;
+    nameArray = array_alloc(char *,0);
+    arrayForEachItem(char*,nameArray1,i,name){
+      latch = Ntk_NetworkFindNodeByName(network,name);
+      st_lookup(node2MvfAigTable,latch,&mvfAig);
+      for(j=0;j<mvfAig->num;j++){
+	int retVal;
+	v = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(mvfAig,j));
+	if(v==bAig_Zero||v==bAig_One)
+	  continue;
+	retVal = st_lookup(tf->li2index,(char*)v,&index);
+	assert(retVal);
+	if(li[index]==bAig_Zero||li[index]==bAig_One)
+	  continue;
+	PureSat_GetLatchForNode(manager,pm,li[index],nameArray,tmpTable,1);
+      }
+
+
+      lmAigId = Ntk_NodeReadMAigId(latch);
+      lmVar = array_fetch(mAigMvar_t, mVarList,lmAigId);
+      for(j=0,index1=lmVar.bVars;j<lmVar.encodeLength;j++,index1++){
+	int retVal;
+	bVar = array_fetch(mAigBvar_t,bVarList,index1);
+	if(bVar.node==bAig_Zero||bVar.node==bAig_One)
+	  continue;
+	retVal = st_lookup(tf->bli2index,(char*)bVar.node,&index);
+	assert(retVal);
+	if(bli[index]==bAig_Zero||bli[index]==bAig_One)
+	  continue;
+	PureSat_GetLatchForNode(manager,pm,bli[index],nameArray,tmpTable,1);
+      }
+    }
+
+    array_free(nameArray1);
+  }
+
+  array_free(nameArray);
+  PureSat_CleanMask(manager,ResetVisitedMask);
+  PureSat_CleanMask(manager,ResetVisited2Mask);
+  PureSat_CleanMask(manager,ResetVisited3Mask);
+
+  return tmpTable;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [There are some latches whose DI is empty, put them
+  into abstraction will not add any burden to model checker]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+void PureSatPreProcLatch(Ntk_Network_t *network,
+			 PureSat_Manager_t *pm)
+{
+  st_generator * stgen;
+  bAig_Manager_t * manager = Ntk_NetworkReadMAigManager(network);
+  st_table * node2MvfAigTable =(st_table *) Ntk_NetworkReadApplInfo(network,
+							 MVFAIG_NETWORK_APPL_KEY);
+  bAigTimeFrame_t * tf = manager->timeframeWOI;
+  mAigMvar_t lmVar;
+  mAigBvar_t bVar;
+  array_t *bVarList,*mVarList;
+  int j,lmAigId,id,index1;
+  char * name;
+  Ntk_Node_t * latch;
+  bAigEdge_t v, **li, **bli;
+  MvfAig_Function_t *mvfAig;
+
+  bVarList = mAigReadBinVarList(manager);
+  mVarList = mAigReadMulVarList(manager);
+  li = tf->latchInputs;
+  bli = tf->blatchInputs;
+
+  st_foreach_item(pm->CoiTable,stgen,&latch,NIL(char*)){
+    int checkbin=1;
+    st_lookup(node2MvfAigTable,latch,&mvfAig);
+    for(j=0;j<mvfAig->num;j++){
+      int retVal;
+      v = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(mvfAig,j));
+      if(v==bAig_Zero||v==bAig_One)
+	continue;
+      retVal = st_lookup(tf->li2index,(char*)v,&id);
+      assert(retVal);
+      if(li[0][id]==li[1][id]&&li[1][id]==li[2][id]){
+	name = Ntk_NodeReadName(latch);
+	st_insert(pm->vertexTable,name,(char*)0);
+	if(pm->verbosity>=2)
+	  fprintf(vis_stdout,"preproc: add %s to abs\n",name);
+	checkbin = 0;
+	break;
+      }
+    }
+    if(checkbin){
+      lmAigId = Ntk_NodeReadMAigId(latch);
+      lmVar = array_fetch(mAigMvar_t, mVarList,lmAigId);
+      for(j=0,index1=lmVar.bVars;j<lmVar.encodeLength;j++,index1++){
+	int retVal;
+	bVar = array_fetch(mAigBvar_t,bVarList,index1);
+	if(bVar.node==bAig_Zero||bVar.node==bAig_One)
+	  continue;
+	retVal = st_lookup(tf->bli2index,(char*)bVar.node,&id);
+	assert(retVal);
+	if(bli[0][id]==bli[1][id]&&bli[1][id]==bli[2][id]){
+	  name = Ntk_NodeReadName(latch);
+	  st_insert(pm->vertexTable,name,(char*)0);
+	  if(pm->verbosity>=2)
+	    fprintf(vis_stdout,"preproc BINARY: add %s to abs\n",name);
+	  break;
+	}
+      }
+    }
+  }
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generate identical latch clusters]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSatGetIndenticalLatch(Ntk_Network_t *network,
+			       PureSat_Manager_t *pm)
+{
+  bAig_Manager_t *manager = Ntk_NetworkReadMAigManager(network);
+  bAigTimeFrame_t * tf = manager->timeframeWOI;
+  bAigEdge_t *li=tf->latchInputs[2],*bli = tf->blatchInputs[2];
+  int i;
+  bAigEdge_t v;
+  st_table *table;
+  st_generator *stgen,*stgen1;
+  char *name,*name1;
+  st_table *table2,*table1=st_init_table(st_ptrcmp,st_ptrhash);
+
+  pm->IdenLatchTable = st_init_table(st_ptrcmp,st_ptrhash);
+
+  for(i=0;i<tf->nLatches;i++){
+    v=bAig_NonInvertedEdge(li[i]);
+    if(!st_lookup(table1,(char*)v,NIL(char*))){
+      if(st_lookup(tf->MultiLatchTable,(char*)v,&table)){
+	int init=0;
+	st_foreach_item(table,stgen,&name,NIL(char*)){
+	  if(!st_lookup(pm->IdenLatchTable,name,&table2)){
+	    st_insert(pm->IdenLatchTable,name,table);
+	    if(pm->verbosity>=2)
+	      fprintf(vis_stdout,"%s and ",name);
+	    init = 1;
+	  }
+	  /*insert everything in table 2 into table
+	  name is already in another group, put everything of current group
+	  into that group*/
+	  else{
+	    st_foreach_item(table,stgen1,&name1,NIL(char*)){
+	      st_insert(table2,name1,(char*)0);
+	      st_insert(pm->IdenLatchTable,name1,table2);
+	      if(pm->verbosity>=2)
+		fprintf(vis_stdout,"%s and ",name1);
+	    }
+	    if(pm->verbosity>=2)
+	      fprintf(vis_stdout,"are the same\n");
+	    break;
+	  }
+	}
+	if(init){
+	  if(pm->verbosity>=2)
+	    fprintf(vis_stdout,"are the same\n");
+	}
+      }
+      st_insert(table1,(char*)v,(char*)0);
+    }
+  }
+
+
+  for(i=0;i<tf->nbLatches;i++){
+    v=bAig_NonInvertedEdge(bli[i]);
+    if(!st_lookup(table1,(char*)v,NIL(char*))){
+      if(st_lookup(tf->MultiLatchTable,(char*)v,&table)){
+	int init=0;
+	st_foreach_item(table,stgen,&name,NIL(char*)){
+
+	  if(!st_lookup(pm->IdenLatchTable,name,table2)){
+	    st_insert(pm->IdenLatchTable,name,table);
+	    if(pm->verbosity>=2)
+	      fprintf(vis_stdout,"%s and ",name);
+	    init = 1;
+	  }
+	  /*insert everything in table 2 into table
+	  name is already in another group, put everything of current group
+	  into that group*/
+	  else{
+	    st_foreach_item(table,stgen1,&name1,NIL(char*)){
+
+	      st_insert(table2,name1,(char*)0);
+	      st_insert(pm->IdenLatchTable,name1,table2);
+	      if(pm->verbosity>=2)
+		fprintf(vis_stdout,"%s and ",name1);
+	    }
+	    if(pm->verbosity>=2)
+	      fprintf(vis_stdout,"are the same\n");
+	    break;
+	  }
+	}
+	if(init){
+	  if(pm->verbosity>=2)
+	    fprintf(vis_stdout,"are the same\n");
+	}
+      }
+      st_insert(table1,(char*)v,(char*)0);
+    }
+  }
+
+  st_free_table(table1);
+}
Index: vis_dev/vis-2.3/src/puresat/puresatInt.h
===================================================================
--- vis_dev/vis-2.3/src/puresat/puresatInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/puresat/puresatInt.h	(revision 14)
@@ -0,0 +1,651 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [puresatInt.h]
+
+  PackageName [puresat]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Bing Li]
+
+  Copyright   [Copyright (c) 2004 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+  ]
+
+  Revision    [$Id: puresatInt.h,v 1.22 2009/04/11 18:26:31 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _PURESATINT
+#define _PURESATINT
+
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+
+#include "bmcInt.h"
+#include "mdd.h"
+#include "satInt.h"
+#include "sat.h"
+#include "puresat.h"
+#include "baig.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define NO_OP 0
+#define MAX_LENGTH 80
+
+
+#define RESTORE_AIG 0
+#define PR 0
+#define TESTIP 1
+/*#define TIMEFRAME_VERIFY_*/
+#define COI 0 /*must be zero*/
+#define UNSATCORE 0
+#define IP_PROCESS 1 /*MUST be one*/
+/*#define TWOLEVEL_MIN 1*/
+#define DBG 1
+#define LARGEDFS 10000
+#define LAI 0 /*latch interface abstraction*/
+#define COREREFMIN 0
+#define THROUGHPICK 1
+#define DIFABSCON 0 /*must be zero,diff abs and contst model*/
+#define INCRECON  1/*Incremental Concretization*/
+#define AROSAT 1
+#define NOREFMIN 0
+#define ADD_HIGHRC_LATCH 0
+#define INC 0
+#define SWITCH 0
+#define SWITCH_DA 0 /*switch to DirAdd*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+struct PureSatManager {
+  int Length;
+  int sameAbsCon;
+  satArray_t * savedConCls;
+  int returnVal;
+  satArray_t * AuxObj;
+  int switch_da;
+  boolean Arosat; /*enable Arosat*/
+  boolean CoreRefMin;/*enable unsat proof-based refinement minimization*/
+  boolean RefPredict; /*enable refinement prediction*/
+  boolean Switch; /* enable dynamic switching*/
+  st_table *latchToTableBaigNodes;
+  st_table *ClsidxToLatchTable;
+  st_table  *CoiTable;
+  st_table  *oldCoiTable;
+  st_table  *AbsTable;
+  st_table  *vertexTable;
+  st_table  *SufAbsTable;
+  st_table  *supportTable;
+  st_table  *IdenLatchTable;  /*store indentical latch*/
+
+  st_table  *node2dfsTable;
+
+  /*for dir cone in abs order*/
+  st_table *nicTable;/*num in cone*/
+  st_table *niaTable; /*num in abs*/
+  boolean incre;
+  boolean sss;
+  int verbosity;
+  char * ltlFileName;
+  int timeOutPeriod;
+  int oldPos;
+  int dbgLevel;
+  FILE *dbgOut;
+  boolean printInputs;
+  array_t * result;
+  double tIP; /*general IP time*/
+  double tIPUnsat; /*real and bogus Cex detection time*/
+  double tIPGen;  /*IP generation time*/
+  double tIPImply;/*IP verification time*/
+  double tIPCon;  /*IP convergence test time*/
+  double tRefMin; /*Refine minimization time*/
+  double tRef;    /*Refine time*/
+  double tCoreGen;/*Core generation time in refine*/
+  double tRefExtract;/*time for extracting ref candidates*/
+  double tCon;    /*Incremental concretization time*/
+  double tGFree;
+  double tPro; /*time for processing*/
+  double tExp; /*time for expandsion*/
+  array_t *latchArray;
+};
+
+struct PureSatIncreSATManager {
+  int beginPosition;
+  int Length;
+  int oldLength;
+  int propertyPos;
+  BmcCnfClauses_t *cnfClauses;
+  satArray_t *savedConCls;
+  satManager_t *cm;
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef enum {
+  dfsWhite_c,   /* unvisited node */
+  dfsGrey_c,    /* node on "stack" */
+  dfsBlack_c    /* node completely visited */
+} DfsColor;
+
+typedef struct PureSatManager PureSat_Manager_t;
+typedef struct PureSatIncreSATManager PureSat_IncreSATManager_t;
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void PureSatInsertNewClauseForSimplePath(array_t *vertexArray, Ntk_Network_t *network, int step1, int step2, BmcCnfClauses_t *cnfClauses, st_table *nodeToMvfAigTable);
+EXTERN void PureSatInsertNewClauseForInit(array_t *vertexArray, Ntk_Network_t *network, int step1, int step2, BmcCnfClauses_t *cnfClauses, st_table *nodeToMvfAigTable);
+EXTERN void PureSatSetInitStatesForSimplePath(array_t * vertexArray, Ntk_Network_t *network, BmcCnfClauses_t *cnfClauses, st_table * nodeToMvfAigTable);
+EXTERN boolean PureSatExistASimplePath(Ntk_Network_t *network, PureSat_IncreSATManager_t * pism, array_t * vertexArray, bAigEdge_t property, PureSat_Manager_t * pm);
+EXTERN boolean PureSatExistCE(Ntk_Network_t * network, PureSat_IncreSATManager_t * pism, BmcOption_t *options, array_t *vertexArray, bAigEdge_t property, PureSat_Manager_t * pm, int extractCexInfo);
+EXTERN boolean PureSatIncreExistCE(Ntk_Network_t * network, PureSat_IncreSATManager_t *pism, array_t *vertexArray, bAigEdge_t property, PureSat_Manager_t * pm);
+EXTERN boolean PureSatIncreExistCEForRefineOnAbs(Ntk_Network_t *network, PureSat_IncreSATManager_t *pism, array_t *vertexArray, bAigEdge_t property, boolean firstTime, PureSat_Manager_t * pm);
+EXTERN void PureSatGenerateClausesFromStateTostateWithTable(bAig_Manager_t *manager, bAigEdge_t *fromAigArray, bAigEdge_t *toAigArray, int mvfSize, int fromState, int toState, BmcCnfClauses_t *cnfClauses, int outIndex, st_table *ClsidxToLatchTable, char *nodeName);
+EXTERN void PureSatGenerateClausesForPath_EnhanceInit(Ntk_Network_t *network, int from, int to, PureSat_IncreSATManager_t * pism, PureSat_Manager_t * pm, st_table *nodeToMvfAigTable, st_table *CoiTable);
+EXTERN boolean PureSatCheckInv_SSS(Ntk_Network_t * network, Ctlsp_Formula_t *ltlFormula, PureSat_Manager_t *pm);
+
+EXTERN boolean PureSatCheckInv_FlatIP(Ntk_Network_t * network,
+				      Ctlsp_Formula_t *ltlFormula,
+				      PureSat_Manager_t *pm);
+EXTERN void PureSatCmdParse(int argc, char **argv, PureSat_Manager_t *pm);
+EXTERN array_t * PureSatRefineOnAbs(Ntk_Network_t *network, PureSat_Manager_t *pm, bAigEdge_t property, int latchThreshHold);
+EXTERN PureSat_Manager_t * PureSatManagerAlloc(void);
+EXTERN void PureSatManagerFree(PureSat_Manager_t * pm);
+EXTERN PureSat_IncreSATManager_t * PureSatIncreSATManagerAlloc(PureSat_Manager_t * pm);
+EXTERN void PureSatIncreSATManagerFree(PureSat_Manager_t *pm, PureSat_IncreSATManager_t * pism);
+EXTERN void PureSatBmcGetCoiForNtkNode(Ntk_Node_t *node, st_table *CoiTable, st_table *visited);
+EXTERN void PureSatBmcGetCoiForLtlFormulaRecursive(Ntk_Network_t *network, Ctlsp_Formula_t *formula, st_table *ltlCoiTable, st_table *visited);
+EXTERN DfsColor PureSatNodeReadColor(Ntk_Node_t * node);
+EXTERN void PureSatNodeSetColor(Ntk_Node_t * node, DfsColor color);
+EXTERN void PureSatNodeRecursivelyComputeTransitiveFaninNodes_AllNodes(Ntk_Node_t *node, int * NumofSupports, boolean stopAtLatches);
+EXTERN int PureSatNodeComputeCombinationalSupport_AllNodes(Ntk_Network_t *network, array_t * nodeArray, boolean stopAtLatches);
+EXTERN void PureSatGenerateSupportTable(Ntk_Network_t *network, PureSat_Manager_t *pm);
+EXTERN void PureSatBmcGetCoiForLtlFormula(Ntk_Network_t *network, Ctlsp_Formula_t *formula, st_table *ltlCoiTable);
+EXTERN void PureSatGetFormulaNodes(Ntk_Network_t *network, Ctlsp_Formula_t *F, array_t *formulaNodes);
+EXTERN void PureSatGetFaninLatches(Ntk_Node_t *node, st_table *visited, st_table *vertexTable);
+EXTERN st_table * PureSatCreateInitialAbstraction(Ntk_Network_t *network, Ctlsp_Formula_t *invFormula, int * Num, PureSat_Manager_t *pm);
+EXTERN void PureSatRecursivelyComputeTableForLatch(Ntk_Network_t * network, st_table *Table, Ntk_Node_t * node);
+EXTERN void PureSatComputeTableForLatch(Ntk_Network_t * network, st_table * Table, Ntk_Node_t * Latch);
+EXTERN void PureSatGetCoiForVisibleArray_Ring(Ntk_Network_t *network, array_t *visibleArray, int position, st_table *ltlCoiTable);
+EXTERN int NumInConeCompare(int *ptrX, int *ptrY);
+EXTERN int NumInConeCompare_Ring(int *ptrX, int *ptrY);
+EXTERN void PureSatRecursivelyComputeCorrelationforLatch(Ntk_Network_t *network, st_table *AbsTable, st_table * visited, Ntk_Node_t *node, int *count);
+EXTERN int PureSatComputeCorrelationforLatch(Ntk_Network_t * network, st_table * AbsTable, Ntk_Node_t *Latch);
+EXTERN array_t * PureSatGenerateRingFromAbs(Ntk_Network_t *network, PureSat_Manager_t *pm, array_t *invisibleArray, int * NumInSecondLevel);
+EXTERN void PureSatCleanSat(satManager_t * cm);
+EXTERN void PureSatReadClauses(PureSat_IncreSATManager_t * pism, PureSat_Manager_t * pm);
+EXTERN array_t * PureSatGetImmediateSupportLatches(Ntk_Network_t *network, int beginPosition, array_t *latchNameArray);
+EXTERN void PureSatWriteClausesToFile(PureSat_IncreSATManager_t * pism, mAig_Manager_t *maigManager, char *coreFile);
+EXTERN void PureSatWriteAllClausesToFile(PureSat_IncreSATManager_t * pism, char *coreFile);
+EXTERN array_t * PureSatGetLatchFromTable(Ntk_Network_t *network, PureSat_Manager_t * pm, char *coreFile);
+EXTERN array_t * PureSatRemove_char(array_t * array1, int i);
+
+EXTERN boolean PureSat_CheckAceByIP(Ntk_Network_t *network,
+			     PureSat_Manager_t * pm,
+			     PureSat_IncreSATManager_t *pism,
+			     array_t *vertexArray,
+			     int * k,
+			     Ctlsp_Formula_t *ltlFormula,
+			     bAigEdge_t * returnProp,
+				    array_t *previousResultArray);
+EXTERN boolean PureSatCheckInv_IP(Ntk_Network_t * network, Ctlsp_Formula_t *ltlFormula, PureSat_Manager_t *pm);
+EXTERN boolean PureSatIPOnCon(Ntk_Network_t * network, Ctlsp_Formula_t *ltlFormula,PureSat_Manager_t *pm);
+EXTERN array_t * PureSat_GetSufAbsFromCore(Ntk_Network_t *network,satManager_t * cm,PureSat_Manager_t *pm,bAigEdge_t property,st_table * SufAbsNameTable);
+EXTERN void PureSat_GetSufAbsFromCoreRecur(mAig_Manager_t *manager,satManager_t * cm,RTnode_t RTnode, st_table *ctTable, st_table *refineTable);
+EXTERN void PureSat_GetSufAbsFromCoreRecur_2side(mAig_Manager_t *manager,satManager_t * cm,RTnode_t RTnode,st_table *ctTable,st_table *refineTable,st_table *SufNameTable);
+EXTERN array_t *PureSat_RefineOnAbs(Ntk_Network_t *network,PureSat_Manager_t *pm,bAigEdge_t property,array_t *previousResultArray,int latchThreshHold,int * sccArray,array_t * sufArray);
+EXTERN RTnode_t RTCreateNode(RTManager_t * rm);
+EXTERN IP_Manager_t * IPManagerAlloc();
+EXTERN void IPManagerFree(IP_Manager_t *ipm);
+EXTERN int PureSat_IdentifyConflict(
+  satManager_t *cm,
+  long left,
+  bAigEdge_t right,
+  bAigEdge_t node);
+EXTERN void PureSatBmcGetCoiForNtkNode_New(
+  Ntk_Node_t  *node,
+  st_table    *CoiTable,
+  st_table    *visited);
+EXTERN void PureSatBmcGetCoiForLtlFormulaRecursive_New(
+  Ntk_Network_t   *network,
+  Ctlsp_Formula_t *formula,
+  st_table        *ltlCoiTable,
+  st_table        *visited);
+EXTERN void PureSatBmcGetCoiForLtlFormula_New(
+  Ntk_Network_t   *network,
+  Ctlsp_Formula_t *formula,
+  st_table        *ltlCoiTable);
+EXTERN void PureSat_MarkTransitiveFaninForNode(
+	satManager_t *cm,
+	bAigEdge_t v,
+	unsigned int mask);
+EXTERN void PureSat_MarkTransitiveFaninForArray(
+	satManager_t *cm,
+	satArray_t *arr,
+	unsigned int mask);
+EXTERN void PureSat_MarkTransitiveFaninForNode2(
+	mAig_Manager_t *manager,
+	bAigEdge_t v,
+	unsigned int mask);
+EXTERN void PureSat_MarkTransitiveFaninForArray2(
+	mAig_Manager_t *manager,
+	satArray_t *arr,
+	unsigned int mask);
+EXTERN void PureSat_MarkTransitiveFaninForNode3(
+	mAig_Manager_t *manager,
+	bAigEdge_t v,
+	unsigned int mask);
+EXTERN void PureSat_MarkTransitiveFaninForArray3(
+	mAig_Manager_t *manager,
+	satArray_t *arr,
+	unsigned int mask);
+EXTERN void PureSat_MarkTransitiveFaninForNode4(
+	mAig_Manager_t *manager,
+	bAigEdge_t v,
+	unsigned int mask,
+	int bound);
+EXTERN void PureSat_MarkTransitiveFaninForArray4(
+	mAig_Manager_t *manager,
+	satArray_t *arr,
+	unsigned int mask,
+	int bound);
+EXTERN void PureSat_CleanMask(mAig_Manager_t *manager,
+			      unsigned int mask);
+EXTERN void PureSat_ResetCoi(satManager_t *cm);
+EXTERN void PureSat_SetCOI(satManager_t *cm);
+EXTERN void PureSatSetLatchCOI(Ntk_Network_t * network,
+			       PureSat_Manager_t *pm,
+			       satManager_t * cm,
+			       st_table * AbsTable,
+			       int from,
+			       int to);
+EXTERN void PureSatSetLatchCOI2(Ntk_Network_t * network,
+				PureSat_Manager_t *pm,
+				satManager_t * cm,
+				bAigEdge_t obj,
+				int bound);
+EXTERN void PureSatSetCOI(Ntk_Network_t * network,
+			  PureSat_Manager_t *pm,
+			  satManager_t * cm,
+			  st_table * AbsTable,
+			  int from,
+			  int to,
+			  int bound);
+EXTERN void PureSatAbstractLatch(bAig_Manager_t *manager,
+			  bAigEdge_t v,
+			  st_table * tmpTable);
+EXTERN void PureSatKillPseudoGVNode(bAig_Manager_t *manager,
+				    bAigEdge_t v,
+				    st_table * tmpTable);
+EXTERN void PureSatKillPseudoGV(Ntk_Network_t * network,
+				PureSat_Manager_t *pm,
+				st_table * AbsTable,
+				int from,
+				int to);
+EXTERN int PureSat_CountNodesInCoi(satManager_t* cm);
+EXTERN void PureSat_ResetManager(mAig_Manager_t *manager,
+				 satManager_t *cm, int clean);
+EXTERN void PureSat_RestoreAigForDummyNode(mAig_Manager_t *manager,
+					   int oldPosition);
+EXTERN void PureSatProcessFanout(satManager_t * cm);
+EXTERN long PureSatRecoverFanoutNode(satManager_t * cm,
+				     bAigEdge_t v);
+EXTERN void PureSatRecoverISVNode(satManager_t *cm,
+			     bAigEdge_t v);
+EXTERN void PureSatRecoverFanout(satManager_t * cm,
+				 PureSat_Manager_t *pm);
+EXTERN void PureSatPreprocess(Ntk_Network_t * network,
+			      satManager_t *cm,
+			      PureSat_Manager_t *pm,
+			      st_table *vertexTable,
+			      int Length);
+EXTERN void PureSatPostprocess(bAig_Manager_t *manager,
+			       satManager_t *cm,
+			       PureSat_Manager_t *pm);
+/*EXTERN int PureSat_TestImply_AbRf(Ntk_Network_t *network,
+				  satManager_t *cm,
+				  PureSat_Manager_t *pm,
+				  st_table *vertexTable,
+				  bAigEdge_t state1,
+				  bAigEdge_t state2);*/
+EXTERN int PureSat_TestConvergeForIP(mAig_Manager_t *manager,
+				     PureSat_Manager_t *pm,
+				     satManager_t *cm,
+				     bAigEdge_t state1,
+				     bAigEdge_t state2);
+EXTERN int PureSat_TestConvergeForIP_AbRf(Ntk_Network_t *network,
+				   satManager_t *cm,
+				   PureSat_Manager_t *pm,
+				   array_t  * CoiArray,
+				   bAigEdge_t state1,
+					  bAigEdge_t state2);
+EXTERN satManager_t * PureSat_SatManagerAlloc(bAig_Manager_t *manager,
+					      PureSat_Manager_t *pm,
+					      bAigEdge_t     object,
+					      array_t        *auxObjectArray);
+EXTERN satManager_t * PureSat_SatManagerAlloc_WOCOI(mAig_Manager_t *manager,
+						    PureSat_Manager_t *pm,
+						    bAigEdge_t     object,
+						    array_t    *auxObjectArray);
+EXTERN void PureSat_SatFreeManager(satManager_t*cm);
+EXTERN void PureSat_PrintAigStatus(mAig_Manager_t *manager);
+EXTERN void PureSat_unconnectOutput(
+   bAig_Manager_t *manager,
+   bAigEdge_t from,
+   bAigEdge_t to);
+EXTERN void PureSat_MarkGlobalVar(bAig_Manager_t *manager,
+				  int length);
+EXTERN void PureSat_UnMarkGlobalVar(bAig_Manager_t *manager,
+				    int length);
+EXTERN void PureSat_MarkGlobalVar_AbRf(bAig_Manager_t *manager,
+				       int length);
+EXTERN void PuresatMarkVisibleVarWithVPGV(Ntk_Network_t *network,
+				  array_t * visibleArray,
+				  PureSat_Manager_t *pm,
+				  int from,
+					  int to);
+EXTERN void PuresatMarkVisibleVar(Ntk_Network_t *network,
+			   array_t * visibleArray,
+			   PureSat_Manager_t *pm,
+			   int from,
+				  int to);
+EXTERN bAigEdge_t PureSat_MapIPRecur(mAig_Manager_t *manager,
+			 bAigEdge_t  node,
+				     st_table * tmpTable);
+EXTERN bAigEdge_t PureSat_MapIP(mAig_Manager_t *manager,
+			 bAigEdge_t node,
+			 int from,
+				int to);
+EXTERN void PureSatProcessDummy(bAig_Manager_t *manager,
+			 satManager_t *cm,
+			 RTnode_t  RTnode);
+EXTERN bAigEdge_t
+PureSat_FindNodeByName(
+  bAig_Manager_t *manager,
+  nameType_t     *name,
+  int bound);
+EXTERN bAigEdge_t
+PureSatCreatebAigOfPropFormula(
+    Ntk_Network_t *network,
+    bAig_Manager_t *manager,
+    int bound,
+    Ctlsp_Formula_t *ltl,
+    int withInitialState);
+EXTERN void PureSatMarkObj(bAig_Manager_t * manager,
+		    long from,
+		    long to);
+EXTERN boolean PureSat_ConcretTest(Ntk_Network_t *network,
+			    PureSat_Manager_t *pm,
+			    array_t *sufArray,
+			    bAigEdge_t property,
+			    array_t *previousResultArray,
+			    int Con,
+			    int satStat,
+				   int inc);
+EXTERN boolean PureSat_ConcretTest_Core(Ntk_Network_t *network,
+				 PureSat_Manager_t *pm,
+				 array_t *sufArray,
+				 bAigEdge_t property,
+				 array_t *previousResultArray,
+					st_table * junkTable);
+EXTERN void PureSatGenerateRingForNode(Ntk_Network_t *network,
+				PureSat_Manager_t *pm,
+				Ntk_Node_t * node1,
+				array_t * ringArray,
+				//st_table * node2dfsTable,
+				       int *dfs);
+EXTERN array_t * PureSatGenerateRing(Ntk_Network_t *network,
+			      PureSat_Manager_t *pm,
+			      array_t * coreArray,
+			      //  st_table *node2dfsTable,
+				     int * dfs);
+EXTERN void PureSatGenerateDfs(Ntk_Network_t *network,
+			PureSat_Manager_t *pm,
+			       array_t * vertexArray);
+/*EXTERN array_t * PureSatGenerateRCArray(Ntk_Network_t *network,
+				 PureSat_Manager_t *pm,
+				 array_t *invisibleArray,
+				// st_table * node2dfsTable,
+				 int *sccArray,
+				 int *NumInSecondLevel);*/
+EXTERN void PureSatComputeNumGatesInAbsForNode(Ntk_Network_t * network,
+					PureSat_Manager_t * pm,
+					Ntk_Node_t * node,
+					st_table * visited,
+					int  * ct,
+					       int  * ct1);
+EXTERN void PureSatComputeNumGatesInAbs(Ntk_Network_t *network,
+				PureSat_Manager_t *pm,
+					array_t * invisibleArray);
+EXTERN void PureSatComputeNumGatesInConeForNode(Ntk_Network_t * network,
+				       PureSat_Manager_t * pm,
+				       Ntk_Node_t * node,
+				       st_table * visited,
+						int  * ct);
+EXTERN void PureSatComputeNumGatesInCone(Ntk_Network_t *network,
+				PureSat_Manager_t *pm,
+					 array_t * latchArray);
+EXTERN array_t * PureSatGenerateRCArray_2(Ntk_Network_t *network,
+				   PureSat_Manager_t *pm,
+				   array_t *invisibleArray,
+					  int *NumInSecondLevel);
+/*EXTERN array_t * PureSatComputeOrder(Ntk_Network_t *network,
+			      PureSat_Manager_t *pm,
+			      array_t * vertexArray,
+			      array_t * invisibleArray,
+			      int * sccArray,
+			      int * NumInSecondLevel);*/
+EXTERN array_t * PureSatComputeOrder_2(Ntk_Network_t *network,
+			      PureSat_Manager_t *pm,
+			      array_t * vertexArray,
+			      array_t * invisibleArray,
+			      int * sccArray,
+				       int * NumInSecondLevel);
+EXTERN void PureSatAddIdenLatchToAbs(Ntk_Network_t *network,
+			      PureSat_Manager_t *pm,
+				     array_t *nameArray);
+EXTERN void PureSatCreateInitAbsByAIG(bAig_Manager_t *manager,
+			  PureSat_Manager_t *pm,
+			  bAigEdge_t node,
+				 st_table * tmpTable);
+EXTERN void PureSat_GetLatchForNode(bAig_Manager_t *manager,
+			PureSat_Manager_t *pm,
+			bAigEdge_t node,
+			array_t * nameArray,
+			st_table *tmpTable,
+				    int cut);
+EXTERN st_table * PureSatGetAigCoi(Ntk_Network_t *network,
+			    PureSat_Manager_t *pm,
+				   bAigEdge_t property);
+EXTERN void PureSatPreProcLatch(Ntk_Network_t *network,
+				PureSat_Manager_t *pm);
+EXTERN void PureSatGetIndenticalLatch(Ntk_Network_t *network,
+				      PureSat_Manager_t *pm);
+EXTERN void PureSat_connectOutput(
+   bAig_Manager_t *manager,
+   bAigEdge_t from,
+   bAigEdge_t to,
+   int inputIndex);
+EXTERN bAigEdge_t
+PureSat_HashTableLookup(
+  bAig_Manager_t *manager,
+  bAigEdge_t  node1,
+  bAigEdge_t  node2);
+EXTERN int
+PureSat_HashTableAdd(
+  bAig_Manager_t   *manager,
+  bAigEdge_t  nodeIndexParent,
+  bAigEdge_t  nodeIndex1,
+  bAigEdge_t  nodeIndex2);
+EXTERN bAigEdge_t
+PureSat_CreateAndNode(
+   bAig_Manager_t  *manager,
+   bAigEdge_t node1,
+   bAigEdge_t node2);
+EXTERN bAigEdge_t
+PureSat_And2(
+   bAig_Manager_t *manager,
+   bAigEdge_t nodeIndex1,
+   bAigEdge_t nodeIndex2);
+EXTERN bAigEdge_t
+PureSat_And3(
+	   bAig_Manager_t *manager,
+	   bAigEdge_t l,
+	   bAigEdge_t r);
+EXTERN bAigEdge_t
+PureSat_And4(
+	   bAig_Manager_t *manager,
+	   bAigEdge_t l,
+	   bAigEdge_t r);
+EXTERN int PureSat_Test2LevelMini(bAig_Manager_t *manager,
+			   bAigEdge_t l,
+			   bAigEdge_t r);
+EXTERN bAigEdge_t
+PureSat_And(
+   bAig_Manager_t *manager,
+   bAigEdge_t nodeIndex1,
+   bAigEdge_t nodeIndex2);
+EXTERN bAigEdge_t
+PureSat_Or(
+   bAig_Manager_t *manager,
+   bAigEdge_t nodeIndex1,
+   bAigEdge_t nodeIndex2);
+EXTERN bAigEdge_t
+PureSat_Xor(
+   bAig_Manager_t *manager,
+   bAigEdge_t nodeIndex1,
+   bAigEdge_t nodeIndex2);
+EXTERN bAigEdge_t
+PureSat_Eq(
+   bAig_Manager_t *manager,
+   bAigEdge_t nodeIndex1,
+   bAigEdge_t nodeIndex2);
+EXTERN bAigEdge_t
+PureSat_Then(
+   bAig_Manager_t *manager,
+   bAigEdge_t nodeIndex1,
+   bAigEdge_t nodeIndex2);
+EXTERN bAigEdge_t
+PureSat_CreateVarNode(
+   bAig_Manager_t  *manager,
+   nameType_t	   *name);
+EXTERN int AS_ImplyStop( satManager_t *cm, satLevel_t *d, long v, long left, long right);
+EXTERN int AS_ImplySplit( satManager_t *cm, satLevel_t *d, long v, long left, long right);
+EXTERN int AS_ImplyConflict( satManager_t *cm, satLevel_t *d, long v, long left, long right);
+EXTERN int AS_ImplyLeftForward( satManager_t *cm, satLevel_t *d, long v, long left, long right);
+EXTERN int AS_ImplyRightForward( satManager_t *cm, satLevel_t *d, long v, long left, long right);
+EXTERN int AS_ImplyForwardOne( satManager_t *cm, satLevel_t *d, long v, long left, long right);
+EXTERN int AS_ImplyPropRight( satManager_t *cm, satLevel_t *d, long v, long left, long right);
+EXTERN int AS_ImplyPropRightOne( satManager_t *cm, satLevel_t *d, long v, long left, long right);
+EXTERN int AS_ImplyPropLeft( satManager_t *cm, satLevel_t *d, long v, long left, long right);
+EXTERN int AS_ImplyPropLeftOne( satManager_t *cm, satLevel_t *d, long v, long left, long right);
+EXTERN int AS_ImplyPropLeftRight( satManager_t *cm, satLevel_t *d, long v, long left, long right);
+EXTERN void
+AS_Undo(
+	satManager_t *cm,
+	satLevel_t *d);
+EXTERN void
+AS_ImplyCNF(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	satArray_t *wl);
+EXTERN int
+AS_ImplyNode(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v);
+
+EXTERN void AS_ImplicationMain(
+	satManager_t *cm,
+	satLevel_t *d);
+EXTERN void
+AS_ImplyArray(
+	satManager_t *cm,
+	satLevel_t *d,
+	satArray_t *arr);
+EXTERN void
+AS_PreProcessing(satManager_t *cm);
+EXTERN void
+AS_Backtrack(
+	satManager_t *cm,
+	int level);
+EXTERN void
+AS_UpdateScore(
+  satManager_t *cm);
+EXTERN void
+AS_PeriodicFunctions(satManager_t *cm);
+EXTERN satLevel_t *
+AS_MakeDecision(satManager_t *cm);
+EXTERN void
+AS_FindUIP(
+	satManager_t *cm,
+	satArray_t *clauseArray,
+	satLevel_t *d,
+	int *objectFlag,
+	int *bLevel,
+	long *fdaLit);
+EXTERN int
+AS_ConflictAnalysis(
+	satManager_t *cm,
+	satLevel_t *d);
+EXTERN void
+AS_Solve(satManager_t *cm);
+EXTERN void AS_Main(satManager_t *cm);
+EXTERN void PureSatCreateOneLayer(Ntk_Network_t *network,
+				  PureSat_Manager_t *pm,
+				  satManager_t *cm,
+				  array_t * latchArray,
+				  int layer);
+EXTERN void PureSatCreateLayer(Ntk_Network_t *network,
+			       PureSat_Manager_t *pm,
+			       satManager_t *cm,
+			       array_t *absModel,
+			       array_t *sufArray);
+EXTERN void bAig_PureSat_ExpandTimeFrame(
+	Ntk_Network_t *network,
+	mAig_Manager_t *manager,
+	PureSat_Manager_t *pm,
+	int bound,
+	int withInitialState);
+EXTERN bAigTimeFrame_t * bAig_PureSat_InitTimeFrame(
+	Ntk_Network_t *network,
+	mAig_Manager_t *manager,
+	PureSat_Manager_t *pm,
+	int withInitialState);
+EXTERN void PureSatCheckCoi(bAig_Manager_t *manager);
+EXTERN void PureSat_CheckFanoutFanin(bAig_Manager_t *manager);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /*_PURESATINT*/
Index: vis_dev/vis-2.3/src/puresat/puresatMain.c
===================================================================
--- vis_dev/vis-2.3/src/puresat/puresatMain.c	(revision 14)
+++ vis_dev/vis-2.3/src/puresat/puresatMain.c	(revision 14)
@@ -0,0 +1,652 @@
+/**CFile***********************************************************************
+
+  FileName    [puresatMain.c]
+
+  PackageName [puresat]
+
+  Synopsis    [Abstraction refinement for large scale invariant checking.]
+
+  Description [This file contains the functions to check invariant properties
+  by the PureSAT abstraction refinement algorithm, which is entirely based on
+  SAT solver, the input of which could be either CNF or AIG. It has several
+  parts:
+
+  * Localization-reduction base Abstraction
+  * K-induction or interpolation to prove the truth of a property
+  * Bounded Model Checking to find bugs
+  * Incremental concretization based methods to verify abstract bugs
+  * Incremental SAT solver to improve efficiency
+  * UNSAT proof based method to obtain refinement
+  * AROSAT to bring in only necessary latches into unsat proofs
+  * Bridge abstraction to get compact coarse refinement
+  * Refinement minization to guarrantee minimal refinements
+  * Unsat proof-based refinement minimization to eliminate multiple candidate
+    by on SAT test
+  * Refinement prediction to decrease the number of refinement iterations
+  * Dynamic switching to redistribute computional resources to improve
+    efficiency
+  
+  For more information, please check the BMC'03, ICCAD'04, STTT'05 and TACAS'05
+  paper of Li et al., "A satisfiability-based appraoch to abstraction
+  refinement in model checking", " Abstraction in symbolic model checking
+  using satisfiability as the only decision procedure", "Efficient computation
+  of small abstraction refinements", and "Efficient abstraction refinement in
+  interpolation-based unbounded model checking"]
+  
+  Author      [Bing Li]
+
+  Copyright   [Copyright (c) 2004 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without
+  license or royalty fees, to use, copy, modify, and distribute this
+  software and its documentation for any purpose, provided that the
+  above copyright notice and the following two paragraphs appear in
+  all copies of this software.]
+
+******************************************************************************/
+#include "puresatInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [PURESAT command interface function]
+
+  Description [PURESAT command interface function]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void
+PureSat_CheckInvariant(
+  Ntk_Network_t *network,
+  array_t *InvariantFormulaArray,
+  int verbosity,
+  int dbgLevel,
+  FILE *dbgOut,
+  boolean printInputs,
+  boolean incremental,
+  boolean sss,
+  boolean flatIP,
+  int speed)
+{
+  int result,i;
+  Ctlp_Formula_t  *invFormula;
+  Ctlsp_Formula_t *invFormula_sp;
+  PureSat_Manager_t * pm = PureSatManagerAlloc();
+
+  pm->incre = incremental;
+  pm->verbosity = verbosity;
+  pm->dbgLevel = dbgLevel;
+  pm->sss = sss;
+  pm->printInputs = printInputs;
+  pm->dbgOut = dbgOut;
+
+  switch(speed){
+  case 0:
+    break;
+  case 1:
+    pm->Switch = 0;
+    break;
+  case 2:
+    pm->Switch = 0;
+    pm->CoreRefMin = 0;
+    break;
+  case 3:
+    pm->Switch = 0;
+    pm->CoreRefMin = 0;
+    pm->RefPredict = 0;
+    break;
+  case 4:
+    pm->Switch = 0;
+    pm->CoreRefMin = 0;
+    pm->RefPredict = 0;
+    pm->Arosat = 0;
+    break;
+  default:
+    pm->Switch = 0;
+    pm->CoreRefMin = 0;
+    pm->RefPredict = 0;
+    pm->Arosat = 0;
+    break;
+  }
+    
+  arrayForEachItem(Ctlp_Formula_t *, InvariantFormulaArray, i, invFormula) {
+    /* if(Ctlsp_isCtlFormula(invFormula))*/
+    invFormula_sp = Ctlsp_CtlFormulaToCtlsp(invFormula);
+    if(sss)
+      /*SSS-base Puresat algorithm*/
+      result = PureSatCheckInv_SSS(network,invFormula_sp,pm);
+    else
+      if(flatIP)
+	/*Interpolation algorithm without abstraction refinement*/
+	result = PureSatCheckInv_FlatIP(network,invFormula_sp,pm);
+      else
+	/*Interpolation-based Puresat algorithm*/
+	result = PureSatCheckInv_IP(network,invFormula_sp,pm);
+    if(result){
+        (void) fprintf(vis_stdout, "# INV: formula passed --- ");
+        Ctlsp_FormulaPrint(vis_stdout, (invFormula_sp));
+        fprintf(vis_stdout, "\n");
+    }
+    else{
+      if(pm->dbgLevel != 2)
+      {
+        (void) fprintf(vis_stdout, "# INV: formula failed --- ");
+        Ctlsp_FormulaPrint(vis_stdout, (invFormula_sp));
+        fprintf(vis_stdout, "\n");
+      }
+    }
+  }
+  PureSatManagerFree(pm);
+}
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Main procedure of K-induction based PURESAT algorithm]
+
+  Description [Main procedure of K-induction based PURESAT algorithm]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+boolean PureSatCheckInv_SSS(Ntk_Network_t * network,
+			Ctlsp_Formula_t *ltlFormula,
+			PureSat_Manager_t *pm)
+{
+  lsGen     gen;
+  st_generator      *stGen;
+  int NumofCurrentLatch=0,Length=0,tmp=0,NumofLatch=0,i,j,k;
+  int addtoAbs=0,latchThreshHold=10000,RingPosition=0;
+  int oldLength=0, beginPosition=0;
+  int NumInSecondLevel =0;
+  array_t * visibleArray = array_alloc(char *,0);
+  array_t * invisibleArray = array_alloc(char *,0);
+  array_t * refinement = array_alloc(char*,0);
+  array_t * CoiArray,* ConClsArray;
+  array_t * arrayRC = NULL;
+  array_t *tmpRefinement;
+  array_t *tmpRefinement1;
+  char * nodeName;
+  Ntk_Node_t * node, *latch;
+  boolean ExistSimplePath = TRUE,ExistACE = FALSE;
+  boolean realRefine=TRUE;
+  boolean needSorting = FALSE, firstTime = TRUE;
+  mAig_Manager_t    *maigManager;
+  BmcOption_t * options;
+  BmcCnfStates_t    *cnfstate;
+  bAigEdge_t        property;
+  st_table * nodeToMvfAigTable;
+  double t1,t2, t0,t3;
+  long *space;
+  PureSat_IncreSATManager_t * pism1,*pism2;
+  satArray_t *saved;
+
+  pm->supportTable = st_init_table(st_ptrcmp,st_ptrhash);
+  pm->CoiTable = st_init_table(st_ptrcmp,st_ptrhash);
+  pm->vertexTable = st_init_table(strcmp, st_strhash);
+  pism1 = PureSatIncreSATManagerAlloc(pm);
+  pism2 = PureSatIncreSATManagerAlloc(pm);
+  t0 = util_cpu_ctime();
+
+  options = BmcOptionAlloc();
+  options->satInFile = BmcCreateTmpFile();
+  options->satOutFile = BmcCreateTmpFile();
+  NumofCurrentLatch=0;
+  t1 = util_cpu_ctime();
+  PureSatBmcGetCoiForLtlFormula(network, ltlFormula,pm->CoiTable);
+  PureSatGenerateSupportTable(network,pm);
+  t2 = util_cpu_ctime();
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"Generate DFS: %g\n",(double)((t2-t1)/1000.0));
+  
+  pm->vertexTable = (st_table *)PureSatCreateInitialAbstraction(network,ltlFormula,&NumofCurrentLatch,pm);
+ 
+  pm->AbsTable = st_init_table(st_ptrcmp,st_ptrhash);
+  
+  Ntk_NetworkForEachLatch(network, gen, node){
+    if (st_lookup_int(pm->CoiTable, node, &tmp)){
+      NumofLatch++;
+      nodeName = Ntk_NodeReadName(node);
+      if(st_lookup(pm->vertexTable,nodeName,NIL(char *)))
+	{
+	  array_insert_last(char *,visibleArray,nodeName);
+	  latch = Ntk_NetworkFindNodeByName(network,nodeName);
+	  PureSatComputeTableForLatch(network,pm->AbsTable,latch);
+	}
+      else
+	array_insert_last(char *,invisibleArray,nodeName);
+    }
+   }
+  if(pm->verbosity>=1){
+    fprintf(vis_stdout,"visiblearray has %d latches\n",array_n(visibleArray));
+    fprintf(vis_stdout,"invisibleArray has %d latches\n",array_n(invisibleArray));
+  }
+  CoiArray = array_dup(visibleArray);
+  array_append(CoiArray,invisibleArray);
+   
+  maigManager = Ntk_NetworkReadMAigManager(network);
+  if (maigManager == NIL(mAig_Manager_t)) {
+    (void) fprintf(vis_stdout, "** bmc error: run build_partition_maigs command first\n");
+    BmcOptionFree(options);
+    return 1;
+  }
+ nodeToMvfAigTable =(st_table *) Ntk_NetworkReadApplInfo(network,
+							 MVFAIG_NETWORK_APPL_KEY);
+  
+ /*build property clauses*/
+ if (Ctlsp_isPropositionalFormula(ltlFormula))
+   property = BmcCreateMaigOfPropFormula(network, maigManager, ltlFormula);
+ else
+   property = BmcCreateMaigOfPropFormula(network, maigManager, ltlFormula->left);
+ 
+ if (property == mAig_NULL){
+   fprintf(vis_stderr,"property = NULL\n");
+   exit(0);
+ }
+ 
+ property = bAig_Not(property);
+ 
+ while(NumofCurrentLatch < NumofLatch)
+   {
+     t3 = util_cpu_ctime();
+     if(pm->verbosity>=1)
+       fprintf(vis_stdout,"Current Latches: %d, COI latches:%d,NEW Length:%d,\n",
+	       NumofCurrentLatch,NumofLatch,pm->Length);
+     if(pm->verbosity>=2)
+       fprintf(vis_stdout,"General time: %g\n",(double)((t3-t0)/1000.0));
+     //tmpRefinement1 = array_alloc(char *,0);
+     firstTime = TRUE;
+     pm->SufAbsTable = st_init_table(st_ptrcmp,st_ptrhash);
+     if(realRefine){
+       arrayForEachItem(char *,refinement,i,nodeName)
+	 {
+	   latch = Ntk_NetworkFindNodeByName(network,nodeName);
+	   PureSatComputeTableForLatch(network,pm->AbsTable,latch);
+	 }
+       array_append(visibleArray,refinement);
+       latchThreshHold=(int)((double)(array_n(CoiArray)-array_n(visibleArray))/(double)4)+1;
+       
+       addtoAbs =(int)((double)(array_n(CoiArray)-array_n(visibleArray))/(double)5)+1;
+       addtoAbs = addtoAbs >50 ? 50: addtoAbs;
+       
+       array_free(invisibleArray);
+       invisibleArray = array_alloc(char *,0);
+       st_foreach_item_int(pm->CoiTable,stGen,&latch,&i)
+	 {
+	   nodeName = Ntk_NodeReadName(latch);
+	   if(!st_lookup(pm->vertexTable,nodeName,0))
+	     array_insert_last(char *,invisibleArray,nodeName);
+	 }
+       t1 = util_cpu_ctime();
+       PureSatGetCoiForVisibleArray_Ring(network, visibleArray,RingPosition, pm->CoiTable);
+       RingPosition = array_n(visibleArray);
+       arrayRC = PureSatGenerateRingFromAbs(network,pm,invisibleArray,&NumInSecondLevel);
+       if(pm->verbosity>=2){
+	 fprintf(vis_stdout,"NumInSecondLevel is %d  ",NumInSecondLevel);
+	 fprintf(vis_stdout,"latchThreshHold is %d\n",latchThreshHold);
+       }
+       latchThreshHold = (latchThreshHold <= NumInSecondLevel) ? latchThreshHold:NumInSecondLevel;
+       if(pm->verbosity>=2){
+	 fprintf(vis_stdout,"New latchThreshHold is %d\n",latchThreshHold);
+       }
+       t2 = util_cpu_ctime();
+       if(pm->verbosity>=2){
+	 fprintf(vis_stdout,"Generate Ring: %g\n",(double)((t2-t1)/1000.0));
+       }
+       array_free(refinement);
+     }/* if(realRefine)*/
+     
+     realRefine =FALSE; /* means no ref, just Length++.*/
+     t1 = util_cpu_ctime();
+     if((ExistSimplePath =
+	PureSatExistASimplePath(network,pism1,visibleArray,property,pm)))
+       {
+	 t2 = util_cpu_ctime();
+	 if(pm->verbosity>=2)
+	   fprintf(vis_stdout,"Solve on Simple Path: %g\n",(double)((t2-t1)/1000.0));
+	 pism1->oldLength = pm->Length;
+	 pism1->Length = pm->Length;
+	 pism1->beginPosition = array_n(visibleArray);
+	 if(pm->verbosity>=1)
+	   fprintf(vis_stdout, "Simple Path Exists, length = %d\n",pm->Length);
+	 
+	 /*check Abs Model*/
+	 t1 = util_cpu_ctime();
+	 ExistACE = PureSatIncreExistCE(network,pism2,visibleArray,property,pm);
+	 if(pm->verbosity>=2)
+	   fprintf(vis_stdout,"beginPosition2: %d, oldLength2 %d\n",pism2->beginPosition, pism2->oldLength);
+	 t2 = util_cpu_ctime();
+	 if(pm->verbosity>=2)
+	   fprintf(vis_stdout,"Solve on Abs model: %g\n",(double)((t2-t1)/1000.0));
+	 pism2->oldLength = pm->Length;
+	 pism2->Length = pm->Length;
+	 pism2->beginPosition = array_n(visibleArray);
+	 needSorting = FALSE;
+	 
+	 /*keep a record of previous position for refine's use*/
+	 oldLength = pism2->oldLength;
+	 beginPosition = pism2->beginPosition;
+	 
+	 /* while(ExistACE)
+	     loop until find sufficient set*/
+	 if(ExistACE)
+	   {
+	     if(pm->verbosity>=1)
+	       fprintf(vis_stdout,"found Abstract Counterexample at length %d\n", pm->Length);
+	     cnfstate = BmcCnfClausesFreeze(pism2->cnfClauses);
+	     pism2->propertyPos = cnfstate->nextIndex;
+	     
+	     /*store the conflict clauses*/
+	     ConClsArray = array_alloc(int,0);
+	     
+	     /*if incremental */
+	     if(pm->incre){
+	       if(pism2->cm->savedConflictClauses){
+		 saved = pism2->cm->savedConflictClauses;
+		 for(i=0, space=saved->space; i<saved->num; i++, space++){
+		   array_insert_last(int,ConClsArray,*space);
+		 }
+	       }
+	     }
+	     realRefine = TRUE;
+	     
+	     /*incrementally check Concrete Model*/
+	     tmpRefinement = array_alloc(char *,0);
+	     if(pm->verbosity>=2)
+	       fprintf(vis_stdout,"Begin building a new abstract model\n");
+	     for(i=0;i<array_n(arrayRC);i=i+latchThreshHold)
+	       {
+		 if(i>0)
+		   latchThreshHold = array_n(arrayRC)-latchThreshHold;
+		 for(j=0;j<latchThreshHold;j++)
+		   {
+		     if((i+j)<array_n(arrayRC))
+		       {
+			 nodeName = array_fetch(char *,arrayRC,i+j);
+			 array_insert_last(char *,tmpRefinement,nodeName);
+			 if(pm->verbosity>=2)
+			   fprintf(vis_stdout, "picking %s\n",nodeName);
+		       }
+		     else
+		       break;
+		   }/* for(j=0;*/
+		 tmpRefinement1=array_dup(visibleArray);
+		 array_append(tmpRefinement1,tmpRefinement);
+		 
+		 t1 = util_cpu_ctime();
+		 pism2->cm->option->incAll = 1;
+		 pism2->cm->option->incTraceObjective = 0;
+		 pism2->cm->option->incPreserveNonobjective = 0;
+		 if(PureSatIncreExistCEForRefineOnAbs(network,pism2,tmpRefinement1,property,firstTime,pm)) {
+		   t2 = util_cpu_ctime();
+		   if(pm->verbosity>=2)
+		     fprintf(vis_stdout,"time for finding a sufficient set on model: %g\n",(double)((t2-t1)/1000.0));
+		   if((i+j)>=array_n(arrayRC)){
+		     if(pm->verbosity>=1)
+		       fprintf(vis_stdout,"found real counterexamples\n");
+		     if(pm->dbgLevel>=1){
+		       options->printInputs = TRUE;
+		       BmcPrintCounterExample(network, nodeToMvfAigTable, pism2->cnfClauses,
+					      pm->result, pm->Length, pm->CoiTable, options, 
+					      NIL(array_t));
+		       array_free(pm->result);
+		       pm->result = NIL(array_t);
+		     }
+		     array_free(tmpRefinement1);
+		     array_free(tmpRefinement);
+		     BmcOptionFree(options);
+		     PureSatIncreSATManagerFree(pm,pism1);
+		     PureSatIncreSATManagerFree(pm,pism2);
+		     /*PureSatManagerFree(pm);*/
+		     array_free(CoiArray);
+		     array_free(visibleArray);
+		     return FALSE;
+		   }
+		   else{
+		     if(pm->result!=NIL(array_t)){
+		       array_free(pm->result);
+		       pm->result = NIL(array_t);
+		     }
+		   }
+		 }
+		 else{
+		   t2 = util_cpu_ctime();
+		   if(pm->verbosity>=1)
+		     fprintf(vis_stdout,"found a sufficient model\n");
+		   if(pm->verbosity>=2)
+		     fprintf(vis_stdout,"time for finding a sufficient set on model: %g\n",(double)((t2-t1)/1000.0));
+		   firstTime = FALSE;
+		   arrayForEachItem(char *,tmpRefinement1,k,nodeName){
+		     node = Ntk_NetworkFindNodeByName(network, nodeName);
+		     if(!st_lookup(pm->SufAbsTable,node,NIL(char *)))
+		       st_insert(pm->SufAbsTable,node, (char *)0);
+		     else{
+		       fprintf(vis_stderr,"wrong in sufabstable \n");
+		       exit(0);
+		     }
+		   }
+		   pism2->beginPosition = array_n(tmpRefinement1);
+		   pism2->oldLength = Length;
+		   array_free(tmpRefinement1);
+		   break;
+		 }
+		 pism2->beginPosition = array_n(tmpRefinement1);
+		 array_free(tmpRefinement1);
+		 pism2->oldLength = Length;
+	       } /*for(i=0;i<array_n(arrayRC)*/
+	     
+	     /*recover the conflict clauses and incremental SAT option*/
+	     pism2->cm->option->incAll = 0;
+	     pism2->cm->option->incTraceObjective = 1;
+	     pism2->cm->option->incPreserveNonobjective = 1;
+	     
+	     /*if incremental*/
+	     if(pm->incre){
+	       if(pism2->cm->savedConflictClauses)
+		 sat_ArrayFree(pism2->cm->savedConflictClauses);
+	       pism2->cm->savedConflictClauses = sat_ArrayAlloc(16);
+	       arrayForEachItem(int, ConClsArray,i,tmp)
+		 sat_ArrayInsert(pism2->cm->savedConflictClauses,tmp);
+	     }
+	     array_free(tmpRefinement);
+	     t1 = util_cpu_ctime();
+	     refinement = PureSatRefineOnAbs(network,pm,property,addtoAbs);
+	     t2 = util_cpu_ctime();
+	     if(pm->verbosity>=2)
+	       fprintf(vis_stdout,"time for RefOnAbs: %g\n",(double)((t2-t1)/1000.0));
+	     st_free_table(pm->SufAbsTable);
+	     pm->SufAbsTable = NIL(st_table);
+	     
+	     /*adjust parameters*/
+	     NumofCurrentLatch+=array_n(refinement);
+	     pm->Length++;
+	     pism1->Length++;
+	     pism2->Length++;
+	     BmcCnfClausesRestore(pism2->cnfClauses, cnfstate);
+	     pism2->beginPosition = beginPosition;
+	     pism2->oldLength = oldLength;
+	     FREE(cnfstate);
+	   }/* if(pism2->cm->status == SAT_SAT)*/
+	 else /*if(pism2->cm->status != SAT_SAT)*/
+	   {
+	     if(pm->verbosity>=1)
+	       fprintf(vis_stdout,"no Abstract Counterexample at length %d \n",pm->Length);
+	     pm->Length++;
+	     pism1->Length++;
+	     pism2->Length++;
+	     st_free_table(pm->SufAbsTable);
+	     pm->SufAbsTable = NIL(st_table);
+	   }
+       } /*if(ExistSimplePath)*/
+     else /* if no simple path*/
+       {
+	 t2 = util_cpu_ctime();
+	 if(pm->verbosity>=2)
+	   fprintf(vis_stdout,"Solve on Simple Path: %g\n",(double)((t2-t1)/1000.0));
+	 if(pm->verbosity>=1)
+	   fprintf(vis_stdout,"simple Path doesn't exist, exit\n");
+	 BmcOptionFree(options);
+	 PureSatIncreSATManagerFree(pm,pism1);
+	 PureSatIncreSATManagerFree(pm,pism2);
+	 PureSatManagerFree(pm);
+	 array_free(CoiArray);
+	 array_free(visibleArray);
+	 return TRUE;
+       }
+   }/* while(NumofCurrentLatch < NumofLatch)*/
+ /*st_free_table(AbsTable);*/
+ 
+ /*Now go to the concrete model*/
+ if(pm->verbosity>=1)
+   fprintf(vis_stdout,"reach concrete model\n");
+ array_append(visibleArray,refinement);
+ array_free(refinement);
+ while(PureSatExistASimplePath(network,pism1,visibleArray,property,pm))
+   {
+     pism1->oldLength = pism1->Length;
+     pism1->beginPosition = array_n(visibleArray);
+     if(PureSatExistCE(network,pism2,options,visibleArray,property,pm,1)) {
+       if(pm->verbosity>=1)
+	 fprintf(vis_stdout,"found real counterexample of length:%d\n",pm->Length);
+       if(pm->dbgLevel>=1){
+	 options->printInputs = TRUE;
+	 BmcPrintCounterExample(network, nodeToMvfAigTable, pism2->cnfClauses,
+				pm->result, pm->Length, pm->CoiTable, options, 
+				NIL(array_t));
+       }
+       BmcOptionFree(options);
+       PureSatIncreSATManagerFree(pm,pism1);
+       PureSatIncreSATManagerFree(pm,pism2);
+       /*PureSatManagerFree(pm);*/
+       array_free(CoiArray);
+       array_free(visibleArray);
+       return FALSE;
+     }
+     else
+       {
+	 pism2->oldLength = Length;
+	 pm->Length++;
+	 pism1->Length++;
+	 pism2->Length++;
+	 pism2->beginPosition = array_n(visibleArray);
+       }
+   }
+ 
+ BmcOptionFree(options);
+ PureSatIncreSATManagerFree(pm,pism1);
+ PureSatIncreSATManagerFree(pm,pism2);  
+ /*PureSatManagerFree(pm);*/
+ array_free(CoiArray);
+ array_free(visibleArray);
+ return TRUE;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [PURESAT command parser]
+
+  Description [PURESAT command parser]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+
+void PureSatCmdParse(int argc,
+		     char **argv,
+		     PureSat_Manager_t *pm)
+
+{
+  int c, incre;
+  
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "t:i:h:v:I:")) != EOF) {
+    switch(c) {
+      case 'i':
+	strcpy(pm->ltlFileName,util_strsav(util_optarg));
+        break;	
+      case 't' :
+	pm->timeOutPeriod = atoi(util_optarg);
+        break;	
+      case 'v':
+        pm->verbosity = atoi(util_optarg);
+        break;
+      case 'I':
+	incre = atoi(util_optarg);
+        pm->incre = (incre==0)? FALSE:TRUE;
+        break;
+      case 'h':
+	goto usage;
+      default:
+	goto usage;
+    }
+  }
+  return;
+ usage:
+  (void) fprintf(vis_stderr, "usage: abrf [-h][-i ltlfile][-t timeout]\n");
+  (void) fprintf(vis_stderr, "   -i \tName of LTL file.\n");
+  (void) fprintf(vis_stderr, "   -t \ttimeout.\n");
+  (void) fprintf(vis_stderr, "   -v \tverbosity for more information. \n");
+  (void) fprintf(vis_stderr, "   -I \tincremental SAT switch. \n");
+  (void) fprintf(vis_stderr, "\t\t0 for non-incremental, other values for incremental\n");
+  (void) fprintf(vis_stderr, "   -h \tprint the command usage\n");
+
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
Index: vis_dev/vis-2.3/src/puresat/puresatRefine.c
===================================================================
--- vis_dev/vis-2.3/src/puresat/puresatRefine.c	(revision 14)
+++ vis_dev/vis-2.3/src/puresat/puresatRefine.c	(revision 14)
@@ -0,0 +1,403 @@
+/**CFile***********************************************************************
+
+  FileName    [puresatRefine.c]
+
+  PackageName [puresat]
+
+  Synopsis    [Abstraction refinement for large scale invariant checking.]
+
+  Description [This file contains the functions to check invariant properties
+  by the PureSAT abstraction refinement algorithm, which is entirely based on
+  SAT solver, the input of which could be either CNF or AIG. It has several
+  parts:
+
+  * Localization-reduction base Abstraction
+  * K-induction or interpolation to prove the truth of a property
+  * Bounded Model Checking to find bugs
+  * Incremental concretization based methods to verify abstract bugs
+  * Incremental SAT solver to improve efficiency
+  * UNSAT proof based method to obtain refinement
+  * AROSAT to bring in only necessary latches into unsat proofs
+  * Bridge abstraction to get compact coarse refinement
+  * Refinement minization to guarrantee minimal refinements
+  * Unsat proof-based refinement minimization to eliminate multiple candidate
+    by on SAT test
+  * Refinement prediction to decrease the number of refinement iterations
+  * Dynamic switching to redistribute computional resources to improve
+    efficiency
+  
+  For more information, please check the BMC'03, ICCAD'04, STTT'05 and TACAS'05
+  paper of Li et al., "A satisfiability-based appraoch to abstraction
+  refinement in model checking", " Abstraction in symbolic model checking
+  using satisfiability as the only decision procedure", "Efficient computation
+  of small abstraction refinements", and "Efficient abstraction refinement in
+  interpolation-based unbounded model checking"]
+  
+  Author      [Bing Li]
+
+  Copyright   [Copyright (c) 2004 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without
+  license or royalty fees, to use, copy, modify, and distribute this
+  software and its documentation for any purpose, provided that the
+  above copyright notice and the following two paragraphs appear in
+  all copies of this software.]
+
+******************************************************************************/
+#include "puresatInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Refinement procedure of PURESAT algorithm]
+
+  Description [Refinement procedure of PURESAT algorithm]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+array_t * PureSatRefineOnAbs(Ntk_Network_t *network,
+		      PureSat_Manager_t *pm,
+		      bAigEdge_t  property,
+		      int latchThreshHold)
+{
+  mAig_Manager_t    *maigManager       = Ntk_NetworkReadMAigManager(network);
+  lsGen             gen;
+  Ntk_Node_t        *latch;
+  FILE              *fp, *fp1;
+  BmcOption_t       *options,*option2;
+  int        i,j,k,Length,beginPosition=0;
+  int        NumInSecondLevel=0;
+  array_t    * tmpRefinement,*tmpArray1,*tmpArray2;
+  array_t    *tmpModel,*tmpRefinement1;
+  /*st_table   * RefinementTable, *CandidateTable;*/
+  array_t    *Pclause, *tmpRefinement2, *tmpRefinement3, *oriSufArray;
+  char       buffer[1024],str[100];
+  char       *name, *coreFile, *tmpCoreFile, *coreFile1=(char *)0;
+  int         oldLength=0,oriCoreSize, CoreSize,weight;
+  st_table          *nodeToMvfAigTable;
+  BmcCnfStates_t    *cnfstate;
+  int             oldNumOfLatchInCore;
+  int             newNumOfLatchInCore,NumOfLatchInModel,round;
+  boolean     VarInCoreIsEnough = FALSE, LatchFromCore = FALSE;
+  boolean     firstTime = TRUE;
+  long t1,t2,t3,t4;
+  st_table * localSufAbsTable;
+  PureSat_IncreSATManager_t * pism = PureSatIncreSATManagerAlloc(pm);
+  satManager_t * cm = pism->cm;
+  BmcCnfClauses_t   * cnfClauses = pism->cnfClauses;
+  st_table *vertexTable = pm->vertexTable;
+  st_table *SufAbsTable = pm->SufAbsTable;
+  /*st_table *CoiTable = pm->CoiTable;*/
+  /*st_table *supportTable = pm->supportTable;*/
+  /* st_table *AbsTable = pm->AbsTable;*/
+    
+  t1 = util_cpu_ctime();
+
+  cm->option->clauseDeletionHeuristic = 0;
+  cm->option->incTraceObjective = 0;
+  pism->Length = pm->Length;
+  Length =  pm->Length;
+  coreFile = BmcCreateTmpFile();
+  tmpCoreFile = BmcCreateTmpFile();
+  strcpy(str,"coreFile: ");
+  strcat(str,coreFile);
+  strcat(str,", tmpCoreFile: ");
+  strcat(str,tmpCoreFile);
+  strcat(str,"\n");
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"%s",str);
+  nodeToMvfAigTable = (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+  if (nodeToMvfAigTable == NIL(st_table)){
+    (void) fprintf(vis_stderr, "** bmc error: please run buid_partiton_maigs first\n");
+    exit (0);
+  }
+  
+  option2 = BmcOptionAlloc();
+  option2->satInFile = BmcCreateTmpFile();
+  option2->satOutFile = BmcCreateTmpFile();
+  options = BmcOptionAlloc();
+  options->satInFile = BmcCreateTmpFile();
+  options->satOutFile = BmcCreateTmpFile();
+
+  newNumOfLatchInCore = 0;
+  NumOfLatchInModel = 0;
+  tmpModel = array_alloc(char *,0);
+  oriSufArray = array_alloc(char *,0);
+  Ntk_NetworkForEachLatch(network, gen, latch){
+    name = Ntk_NodeReadName(latch);
+    if(st_lookup(vertexTable,name,NIL(char *))){
+      array_insert_last(char *,tmpModel,name);
+      NumOfLatchInModel++;
+    }
+    else
+      if(st_lookup(SufAbsTable,latch,NIL(char *))){
+	newNumOfLatchInCore++;
+	array_insert_last(char *,oriSufArray,name);
+      }
+  }
+  
+  localSufAbsTable = st_copy(SufAbsTable);
+  //tmpRefinement2 = array_alloc(char *,0);
+  tmpRefinement3 = array_alloc(char *,0);
+  //tmpArray1 = array_alloc(char *,0);
+  //tmpArray2 = array_alloc(char *,0);
+  weight = (NumOfLatchInModel+newNumOfLatchInCore+1)*10000;
+  round=0;
+  
+  round++;
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"round: %d\n",round);
+  oldNumOfLatchInCore = newNumOfLatchInCore;
+  pm->ClsidxToLatchTable = st_init_table(st_numcmp,st_numhash);
+  PureSatGenerateClausesForPath_EnhanceInit(network,0,Length,pism,pm,nodeToMvfAigTable,localSufAbsTable);
+  Pclause = array_alloc(int,0);
+  array_insert_last(int, Pclause, BmcGenerateCnfFormulaForAigFunction(maigManager,property,
+								      Length, cnfClauses));
+  BmcCnfInsertClause(cnfClauses, Pclause);
+  array_free(Pclause);
+  CoreSize=cnfClauses->noOfClauses;
+  
+  oriCoreSize = CoreSize;
+  cm->option->coreGeneration = 1;
+  cm->fp = fopen(tmpCoreFile, "w");
+  if(pm->verbosity>=2)
+    PureSatWriteClausesToFile(pism,maigManager,coreFile1);
+  t1 = util_cpu_ctime();
+  PureSatReadClauses(pism,pm);
+  sat_Main(cm);
+  t2 = util_cpu_ctime();
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"time for SAT Solver(satMain): %g\n",(double)((t2-t1)/1000.0));
+  
+  fclose(cm->fp);
+  if(cm->status == SAT_SAT){
+    fprintf(vis_stderr,"This instance is supposed to be UNSAT, wrong and exit\n");
+    exit(0);
+  }
+  cm->stdOut = vis_stdout; 
+  cm->option->coreGeneration = 0;
+  
+  t2 = util_cpu_ctime();
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"time for satMain: %g\n",(double)((t2-t1)/1000.0));
+  CoreSize = cm->numOfClsInCore;
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"CoreSize:%d/OriCoreSize:%d\n", CoreSize,oriCoreSize);
+  
+  fp1 = fopen(coreFile, "w");
+  fp = fopen(tmpCoreFile, "r");
+  sprintf(buffer,"p cnf %d %d 0\n", cm->initNumVariables, cm->numOfClsInCore);
+  fputs(buffer, fp1);
+  while(fgets(buffer,1024,fp)){
+    fputs(buffer, fp1);
+  }
+  fclose(fp);
+  fclose(fp1);
+
+  //tmpRefinement1 = array_alloc(char *,0);
+  /* generate sufficient refinement */
+  st_free_table(localSufAbsTable);
+  localSufAbsTable = st_init_table(st_ptrcmp,st_ptrhash);  
+  t3 = util_cpu_ctime();
+  tmpRefinement1 = PureSatGetLatchFromTable(network,pm,coreFile);
+  t4 = util_cpu_ctime();
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"time for PureSatGetLatchFromTable: %g\n",(double)((t4-t3)/1000.0));
+  
+  if(array_n(tmpRefinement1)>array_n(oriSufArray)){
+    array_free(tmpRefinement1);
+    tmpRefinement1 = array_dup(oriSufArray);
+  }
+  else{
+    array_free(oriSufArray);
+    oriSufArray = array_dup(tmpRefinement1);
+  }
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"All latches picked from UNSAT Proof:\n");
+  arrayForEachItem(char *,tmpRefinement1,i,name){
+    if(pm->verbosity>=2)
+      fprintf(vis_stdout," %s  ",name);
+    latch = Ntk_NetworkFindNodeByName(network,name);
+    st_insert(localSufAbsTable,latch,(char *)0);
+  }
+  if(pm->verbosity>=2){
+    fprintf(vis_stdout,"\n");
+    fprintf(vis_stdout,"tmpModel: \n");
+  }
+  arrayForEachItem(char *,tmpModel,i,name){
+    if(pm->verbosity>=2)
+      fprintf(vis_stdout," %s  ",name);
+    latch = Ntk_NetworkFindNodeByName(network,name);
+    st_insert(localSufAbsTable,latch,(char *)0);
+  }
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"\n");
+  newNumOfLatchInCore = array_n(tmpRefinement1);
+  BmcCnfClausesFree(pism->cnfClauses);
+  
+  if(pm->verbosity>=2)
+    fprintf(vis_stdout,"newNumOfLatchInCore/oldNumOfLatchInCore=%f\n",(double)newNumOfLatchInCore/(double)oldNumOfLatchInCore);
+  
+  /* Add the refinement to vertexTable*/
+  arrayForEachItem(char *,tmpRefinement1,i,name){
+    st_insert(vertexTable, name,(char*)0);
+  }
+  
+  pism->cnfClauses = BmcCnfClausesAlloc();
+  cnfClauses = pism->cnfClauses;
+  if(array_n(tmpRefinement1)) 
+    {
+      tmpRefinement = PureSatGenerateRingFromAbs(network,pm,tmpRefinement1,&NumInSecondLevel);
+      /* latchThreshHold = (latchThreshHold <= NumInSecondLevel) ? latchThreshHold:NumInSecondLevel;*/
+      array_free(tmpRefinement1);
+      LatchFromCore = TRUE;
+      for(i=0;i<array_n(tmpRefinement);i=i+latchThreshHold)
+	{
+	  for(j=0;j<latchThreshHold;j++)
+	    {
+	      if((i+j)<array_n(tmpRefinement))
+		{
+		  name = array_fetch(char *,tmpRefinement,i+j);
+		  array_insert_last(char *,tmpRefinement3,name);
+		  if(pm->verbosity>=1)
+		    fprintf(vis_stdout, "picking %s\n",name);
+		}
+	      else
+		break;
+	    }
+	  tmpRefinement2=array_dup(tmpModel);
+	  array_append(tmpRefinement2,tmpRefinement3);
+	  if(!PureSatExistCE(network,pism,option2,tmpRefinement2,property,pm,0)){
+	    VarInCoreIsEnough = TRUE;
+	    array_free(tmpRefinement2);
+	    for(k=i+j;k<array_n(tmpRefinement);k++)
+	      {
+		name = array_fetch(char *,tmpRefinement,k);
+		if(st_lookup(vertexTable,name,NIL(char *))){
+		  st_delete(vertexTable,&name,NIL(char *));
+		}
+	      }
+	    break;
+	  }
+	  firstTime = FALSE;
+	  beginPosition = array_n(tmpRefinement2);
+	  array_free(tmpRefinement2);
+	  oldLength = Length;
+	} 
+      array_free(tmpRefinement);
+      tmpRefinement = array_dup(tmpRefinement3); /* now tmpRefinement1 contains the
+						   latches in Core*/
+      array_free(tmpRefinement3);
+      oldLength=0;
+      beginPosition=0;
+      BmcCnfClausesFree(pism->cnfClauses);
+      pism->cnfClauses = BmcCnfClausesAlloc();
+    }
+  
+#if 1
+  if(!VarInCoreIsEnough){
+    fprintf(vis_stderr,"this should never happen, wrong\n");
+    exit(0);
+  }
+#endif
+  
+  //tmpRefinement = array_dup(tmpRefinement1);
+  //array_free(tmpRefinement1);
+  
+# if 1
+  /*Refinement Minimization
+    try all the candidates*/
+  for(i=array_n(tmpRefinement)-1;i>=0;i--)
+    {
+      name = array_fetch(char *,tmpRefinement,i);
+      if(pm->verbosity>=1)
+	fprintf(vis_stdout,"RefMin: testing %s\n",name);
+      tmpArray2 = PureSatRemove_char(tmpRefinement,i);
+      tmpArray1 = array_dup(tmpModel);
+      array_append(tmpArray1,tmpArray2);
+      cnfstate = BmcCnfClausesFreeze(pism->cnfClauses);
+      if(PureSatExistCE(network,pism,option2,tmpArray1,property,pm,0))
+	array_free(tmpArray2);
+      else /*delete it*/
+	{
+	  /*   i--;*/
+	  name = array_fetch(char *, tmpRefinement,i);
+	  if(st_lookup(vertexTable, name,NIL(char *)))
+	    st_delete(vertexTable, &name, NIL(char *));
+	  else
+	    fprintf(vis_stderr," %s should be in vertexTable, Wrong!!!\n",name);
+	  array_free(tmpRefinement);
+	  tmpRefinement = tmpArray2;
+	}
+      array_free(tmpArray1);
+      BmcCnfClausesRestore(pism->cnfClauses, cnfstate);
+      FREE(cnfstate);
+    }
+  //BmcCnfClausesFree(pism->cnfClauses);
+#endif
+  
+  if(pm->verbosity>=1){
+    fprintf(vis_stdout,"\n sufficient refinement candidates from CA\n");
+    arrayForEachItem(char *,tmpRefinement,i,name)
+      fprintf(vis_stdout,"%s\n",name);
+  }
+  BmcOptionFree(option2);
+  BmcOptionFree(options);
+  unlink(coreFile);
+  unlink(tmpCoreFile);
+  FREE(coreFile);
+  FREE(tmpCoreFile);
+  array_free(oriSufArray);
+  st_free_table(pm->ClsidxToLatchTable);
+  pm->ClsidxToLatchTable = NIL(st_table);
+  PureSatIncreSATManagerFree(pm,pism);
+  return tmpRefinement;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
Index: vis_dev/vis-2.3/src/puresat/puresatTFrame.c
===================================================================
--- vis_dev/vis-2.3/src/puresat/puresatTFrame.c	(revision 14)
+++ vis_dev/vis-2.3/src/puresat/puresatTFrame.c	(revision 14)
@@ -0,0 +1,1242 @@
+/**CFile***********************************************************************
+
+  FileName    [puresatTFrame.c]
+
+  PackageName [puresat]
+
+  Synopsis    [Abstraction refinement for large scale invariant checking.]
+
+  Description [This file contains the functions to check invariant properties
+  by the PureSAT abstraction refinement algorithm, which is entirely based on
+  SAT solver, the input of which could be either CNF or AIG. It has several
+  parts:
+
+  * Localization-reduction base Abstraction
+  * K-induction or interpolation to prove the truth of a property
+  * Bounded Model Checking to find bugs
+  * Incremental concretization based methods to verify abstract bugs
+  * Incremental SAT solver to improve efficiency
+  * UNSAT proof based method to obtain refinement
+  * AROSAT to bring in only necessary latches into unsat proofs
+  * Bridge abstraction to get compact coarse refinement
+  * Refinement minization to guarrantee minimal refinements
+  * Unsat proof-based refinement minimization to eliminate multiple candidate
+    by on SAT test
+  * Refinement prediction to decrease the number of refinement iterations
+  * Dynamic switching to redistribute computional resources to improve
+    efficiency
+
+  For more information, please check the BMC'03, ICCAD'04, STTT'05 and TACAS'05
+  paper of Li et al., "A satisfiability-based appraoch to abstraction
+  refinement in model checking", " Abstraction in symbolic model checking
+  using satisfiability as the only decision procedure", "Efficient computation
+  of small abstraction refinements", and "Efficient abstraction refinement in
+  interpolation-based unbounded model checking"]
+
+  Author      [Bing Li]
+
+  Copyright   [Copyright (c) 2004 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without
+  license or royalty fees, to use, copy, modify, and distribute this
+  software and its documentation for any purpose, provided that the
+  above copyright notice and the following two paragraphs appear in
+  all copies of this software.]
+
+******************************************************************************/
+#include "puresatInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int nameCompare(const void * node1, const void * node2);
+static int NoOfBitEncode( int n);
+
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [build conncetion between binary variables and
+	       multi-valued variables]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+bAigEdge_t
+PureSat_CaseNew(mAig_Manager_t *manager,
+  bAigEdge_t      *arr,
+  array_t *       encodeList,
+  int             index)
+{
+  int encodeLen;
+  int i, count;
+  bAigEdge_t v;
+  bAigEdge_t    andResult1, andResult2, orResult, result;
+  bAigEdge_t    node1, node2;
+  array_t *newEncodeList;
+
+  encodeLen = array_n(encodeList);
+  if (encodeLen == 1)
+    return array_fetch(bAigEdge_t, encodeList, 0);
+  newEncodeList =  array_alloc(bAigEdge_t, 0);
+
+  v = arr[index];
+  count = 0;
+  for (i=0; i< (encodeLen/2); i++){
+    node1 = array_fetch(bAigEdge_t, encodeList, count++);
+    node2 = array_fetch(bAigEdge_t, encodeList, count++);
+
+     /*  performs ITE operator */
+    andResult1 = PureSat_And(manager, v,           node2);
+    andResult2 = PureSat_And(manager, bAig_Not(v), node1);
+    orResult   = PureSat_Or (manager, andResult1,  andResult2);
+    flags(andResult1) |= IsSystemMask;
+    flags(andResult2) |= IsSystemMask;
+    flags(orResult) |= IsSystemMask;
+
+    array_insert_last(bAigEdge_t, newEncodeList, orResult);
+  }
+
+  if(encodeLen%2){
+    node1 = array_fetch(bAigEdge_t, encodeList, count);
+    array_insert_last(bAigEdge_t, newEncodeList, node1);
+  }
+
+  result = PureSat_CaseNew(manager, arr, newEncodeList, index-1);
+  array_free(newEncodeList);
+  return(result);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Create new aig node in expanding timeframes with initial states]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+void PureSat_CreateNewNode(
+	mAig_Manager_t *manager,
+	st_table *node2MvfAigTable,
+	Ntk_Node_t *node,
+	bAigEdge_t *bli,
+	bAigEdge_t *li,
+	int *bindex,
+	int *index,
+	int withInitialState)
+{
+  int i, j, value, noBits;
+  bAigEdge_t *arr, v, tv;
+  MvfAig_Function_t  *mvfAig;
+  array_t *encodeList;
+  bAigEdge_t *ManagerNodesArray;
+  bAigTimeFrame_t *timeframe;
+
+
+  if(withInitialState)
+    timeframe = manager->timeframe;
+  else
+    timeframe = manager->timeframeWOI;
+
+  value = Var_VariableReadNumValues(Ntk_NodeReadVariable(node));
+  noBits = NoOfBitEncode(value);
+  arr = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*noBits);
+  mvfAig = 0;
+  st_lookup(node2MvfAigTable, (char *) node, &mvfAig);
+  for(i=0; i<noBits; i++) {
+    arr[i] = bAig_CreateNode(manager, bAig_NULL, bAig_NULL);
+    bli[(*bindex)++] = arr[i];
+
+    flags(arr[i]) |= IsSystemMask;
+  }
+
+  for(i=0; i<value; i++) {
+    v = MvfAig_FunctionReadComponent(mvfAig, i);
+
+    encodeList = array_alloc(bAigEdge_t, 0);
+    for(j=0; j<value; j++) {
+      if(j == i)array_insert_last(bAigEdge_t, encodeList, mAig_One);
+      else	array_insert_last(bAigEdge_t, encodeList, mAig_Zero);
+    }
+    tv = PureSat_CaseNew(manager, arr, encodeList, noBits-1);
+    li[(*index)++] = tv;
+
+    ManagerNodesArray = manager->NodesArray;
+
+    array_free(encodeList);
+    if(v == bAig_Zero){
+      flags(tv) |= StaticLearnMask;
+      if(timeframe->assertedArray == 0)
+	timeframe->assertedArray = array_alloc(bAigEdge_t, 0);
+      array_insert_last(bAigEdge_t, timeframe->assertedArray, bAig_Not(tv));
+    }
+    else if(v == bAig_One){
+      flags(tv) |= StaticLearnMask;
+      if(timeframe->assertedArray == 0)
+	timeframe->assertedArray = array_alloc(bAigEdge_t, 0);
+      array_insert_last(bAigEdge_t, timeframe->assertedArray, tv);
+    }
+  }
+  free(arr);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Build timeframed coi for each variable]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+bAigEdge_t
+PureSat_ExpandForEachCone(
+	mAig_Manager_t *manager,
+	bAigEdge_t v,
+	st_table *old2new)
+{
+  bAigEdge_t left, right, nv;
+
+  v = bAig_GetCanonical(manager, v);
+  if(v == bAig_One || v == bAig_Zero)	return(v);
+  if(v == bAig_NULL)	{
+      fprintf(vis_stdout, "current error\n");
+      return(v);
+  }
+
+
+  if(st_lookup(old2new, (char *)v, &nv))
+    return(nv);
+  if(st_lookup(old2new, (char *)bAig_Not(v), &nv))
+    return(bAig_Not(nv));
+
+  left = PureSat_ExpandForEachCone(manager, leftChild(v), old2new);
+  right = PureSat_ExpandForEachCone(manager, rightChild(v), old2new);
+
+  nv = PureSat_And(manager, left, right);
+
+  flags(nv) |= IsSystemMask;
+
+  if(bAig_IsInverted(v))	nv = bAig_Not(nv);
+  st_insert(old2new, (char *)v, (char *)nv);
+
+
+  return(nv);
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Initialize aig timeframes]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+bAigTimeFrame_t *
+bAig_PureSat_InitTimeFrame(
+	Ntk_Network_t *network,
+	mAig_Manager_t *manager,
+	PureSat_Manager_t *pm,
+	int withInitialState)
+{
+bAigTimeFrame_t *timeframe;
+array_t *latchArr, *inputArr, *outputArr;
+array_t *iindexArray;
+st_table   *li2index, *o2index, *i2index, *pi2index;
+st_table   *bli2index, *bpi2index;
+Ntk_Node_t *node, *latch;
+st_table   *node2MvfAigTable, *old2new;
+lsGen gen;
+int nLatches, nInputs, nOutputs, nInternals;
+int nbLatches, nbInputs;
+int i;
+int index, index1, mvfSize, lmvfSize;
+int bindex, tindex, tindex1;
+MvfAig_Function_t  *mvfAig, *tmpMvfAig, *lmvfAig;
+bAigEdge_t *li, *pre_li, *ori_li;
+bAigEdge_t *bli, *ori_bli;
+bAigEdge_t v, nv;
+mAigMvar_t mVar;
+mAigBvar_t bVar;
+array_t   *bVarList, *mVarList;
+int mAigId;
+int lmAigId;
+mAigMvar_t lmVar;
+mAigBvar_t lbVar;
+
+bAigEdge_t vi, tmpv1, tmpv2,tmpv3;
+char * name, *name1;
+int imvfSize;
+st_table *idx2name,*MultiLatchTable,*table;
+
+  manager->class_ = 1;
+
+  node2MvfAigTable =
+	(st_table *)Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+
+  timeframe = ALLOC(bAigTimeFrame_t, 1);
+  memset(timeframe, 0, sizeof(bAigTimeFrame_t));
+  if(withInitialState) manager->timeframe = timeframe;
+  else                 manager->timeframeWOI = timeframe;
+
+  latchArr = array_alloc(Ntk_Node_t *, 0);
+  inputArr = array_alloc(Ntk_Node_t *, 0);
+  outputArr = array_alloc(Ntk_Node_t *, 0);
+  timeframe->latchArr = latchArr;
+  timeframe->inputArr = inputArr;
+  timeframe->outputArr = outputArr;
+
+  li2index = st_init_table(st_ptrcmp, st_ptrhash);
+  o2index = st_init_table(st_ptrcmp, st_ptrhash);
+  i2index = st_init_table(st_ptrcmp, st_ptrhash);
+  pi2index = st_init_table(st_ptrcmp, st_ptrhash);
+
+  bli2index = st_init_table(st_ptrcmp, st_ptrhash);
+  bpi2index = st_init_table(st_ptrcmp, st_ptrhash);
+
+  idx2name = st_init_table(st_ptrcmp,st_ptrhash);
+  timeframe->idx2name = idx2name;
+  MultiLatchTable = st_init_table(st_ptrcmp,st_ptrhash);
+  timeframe->MultiLatchTable = MultiLatchTable;
+
+  timeframe->li2index = li2index;
+  timeframe->o2index = o2index;
+  timeframe->pi2index = pi2index;
+  timeframe->i2index = i2index;
+
+  timeframe->bli2index = bli2index;
+  timeframe->bpi2index = bpi2index;
+  /**
+   * count total number,
+   * insert into node array
+   * and make table for bAigEdge_t to index
+   **/
+
+  bVarList = mAigReadBinVarList(manager);
+  mVarList = mAigReadMulVarList(manager);
+
+  nLatches = 0;
+  nbLatches = 0;
+  Ntk_NetworkForEachLatch(network, gen, latch) {
+
+    name = Ntk_NodeReadName(latch);
+    array_insert_last(Ntk_Node_t *, latchArr, latch);
+    st_lookup(node2MvfAigTable, (char *)latch, &mvfAig);
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+      st_insert(li2index, (char *)v, (char *)(long)nLatches++);
+
+#ifdef TIMEFRAME_VERIFY_
+      fprintf(vis_stdout,"Latch:%s v-->idx:%d-->%d\n",name,v,nLatches-1);
+#endif
+    }
+
+
+    mAigId = Ntk_NodeReadMAigId(latch);
+    mVar = array_fetch(mAigMvar_t, mVarList, mAigId);
+    for(i=0, index1=mVar.bVars; i<mVar.encodeLength; i++) {
+      bVar = array_fetch(mAigBvar_t, bVarList, index1);
+      st_insert(bli2index, (char *)bVar.node, (char *)(long)nbLatches++);
+      index1++;
+    }
+  }
+  timeframe->nLatches = nLatches;
+  timeframe->nbLatches = nbLatches;
+
+  nOutputs = 0;
+  Ntk_NetworkForEachPrimaryOutput(network, gen, node) {
+    array_insert_last(Ntk_Node_t *, outputArr, node);
+    st_lookup(node2MvfAigTable, (char *)node, &mvfAig);
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+      st_insert(o2index, (char *)v, (char *)(long)nOutputs++);
+    }
+  }
+  timeframe->nOutputs = nOutputs;
+
+  timeframe->iindexArray = iindexArray = array_alloc(bAigEdge_t, 0);
+  nInternals = 0;
+  Ntk_NetworkForEachNode(network, gen, node) {
+    if(Ntk_NodeTestIsShadow(node))	continue;
+    if(Ntk_NodeTestIsCombInput(node))	continue;
+    if(Ntk_NodeTestIsCombOutput(node))continue;
+    if(!st_lookup(node2MvfAigTable, (char *)node, &mvfAig)) {
+      tmpMvfAig = Bmc_NodeBuildMVF(network, node);
+      array_free(tmpMvfAig);
+      mvfAig = Bmc_ReadMvfAig(node, node2MvfAigTable);
+    }
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+      if(!st_lookup(i2index, (char *)v, &index1)) {
+	array_insert_last(bAigEdge_t, iindexArray, v);
+	st_insert(i2index, (char *)v, (char *)(long)nInternals++);
+      }
+    }
+  }
+  timeframe->nInternals = nInternals;
+
+  nInputs = 0;
+  nbInputs = 0;
+  Ntk_NetworkForEachPrimaryInput(network, gen, node) {
+    array_insert_last(Ntk_Node_t *, inputArr, node);
+    if(!st_lookup(node2MvfAigTable, (char *)node, &mvfAig)) {
+      tmpMvfAig = Bmc_NodeBuildMVF(network, node);
+      array_free(tmpMvfAig);
+      mvfAig = Bmc_ReadMvfAig(node, node2MvfAigTable);
+    }
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+	st_insert(pi2index, (char *)v, (char *)(long)nInputs++);
+    }
+
+    mAigId = Ntk_NodeReadMAigId(node);
+    mVar = array_fetch(mAigMvar_t, mVarList, mAigId);
+    for(i=0, index1=mVar.bVars; i<mVar.encodeLength; i++) {
+      bVar = array_fetch(mAigBvar_t, bVarList, index1);
+      st_insert(bpi2index, (char *)bVar.node, (char *)(long)nbInputs++);
+      index1++;
+    }
+  }
+  Ntk_NetworkForEachPseudoInput(network, gen, node)  {
+    array_insert_last(Ntk_Node_t *, inputArr, node);
+    if(!st_lookup(node2MvfAigTable, (char *)node, &mvfAig)) {
+      tmpMvfAig = Bmc_NodeBuildMVF(network, node);
+      array_free(tmpMvfAig);
+      mvfAig = Bmc_ReadMvfAig(node, node2MvfAigTable);
+    }
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+	st_insert(pi2index, (char *)v, (char *)(long)nInputs++);
+    }
+
+    mAigId = Ntk_NodeReadMAigId(node);
+    mVar = array_fetch(mAigMvar_t, mVarList, mAigId);
+    for(i=0, index1=mVar.bVars; i<mVar.encodeLength; i++) {
+      bVar = array_fetch(mAigBvar_t, bVarList, index1);
+      st_insert(bpi2index, (char *)bVar.node, (char *)(long)nbInputs++);
+      index1++;
+    }
+  }
+  timeframe->nInputs = nInputs;
+  timeframe->nbInputs = nbInputs;
+
+  array_sort(inputArr, nameCompare);
+  array_sort(latchArr, nameCompare);
+  array_sort(outputArr, nameCompare);
+
+    /** make 0 index bAigEdge_t **/
+  manager->SymbolTableArray[0] = st_init_table(strcmp,st_strhash);
+  manager->HashTableArray[0] = ALLOC(bAigEdge_t, bAig_HashTableSize);
+  for (i=0; i<bAig_HashTableSize; i++)
+       manager->HashTableArray[0][i]= bAig_NULL;
+  manager->SymbolTableArray[1] = st_init_table(strcmp,st_strhash);
+  manager->HashTableArray[1] = ALLOC(bAigEdge_t, bAig_HashTableSize);
+  for (i=0; i<bAig_HashTableSize; i++)
+       manager->HashTableArray[1][i]= bAig_NULL;
+
+  old2new = st_init_table(st_ptrcmp, st_ptrhash);
+  bli = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nbInputs);
+  li = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nInputs);
+  index1 = index = 0;
+  bindex = 0;
+  Ntk_NetworkForEachPrimaryInput(network, gen, node) {
+
+    PureSat_CreateNewNode(manager, node2MvfAigTable, node, bli, li, &bindex, &index,withInitialState);
+
+    st_lookup(node2MvfAigTable, (char *) node, &mvfAig);
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+#ifdef TIMEFRAME_VERIFY_
+      fprintf(vis_stdout, "IN(%d) %s(%d) : %d -> %d\n", -1, Ntk_NodeReadName(node), i, v, li[index1]);
+#endif
+      st_insert(old2new, (char *)v, (char *)(li[index1++]));
+    }
+  }
+  Ntk_NetworkForEachPseudoInput(network, gen, node) {
+
+    PureSat_CreateNewNode(manager, node2MvfAigTable, node, bli, li, &bindex, &index,withInitialState);
+
+    st_lookup(node2MvfAigTable, (char *) node, &mvfAig);
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+#ifdef TIMEFRAME_VERIFY_
+      fprintf(vis_stdout, "PI(%d) %s(%d) : %d -> %d\n", -1, Ntk_NodeReadName(node), i, v, li[index1]);
+#endif
+      st_insert(old2new, (char *)v, (char *)(li[index1++]));
+    }
+  }
+
+  timeframe->blatchInputs = (bAigEdge_t **)malloc(sizeof(bAigEdge_t *)*(2));
+  bli = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nbLatches);
+  timeframe->blatchInputs[0] = bli;
+
+  timeframe->latchInputs = (bAigEdge_t **)malloc(sizeof(bAigEdge_t *)*(2));
+  li = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nLatches);
+  timeframe->latchInputs[0] = li;
+
+  ori_li = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nLatches);
+  ori_bli = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nbLatches);
+  timeframe->oriLatchInputs = ori_li;
+  timeframe->oribLatchInputs = ori_bli;
+
+  index1 = index = 0;
+  bindex = tindex = tindex1 = 0;
+
+  if(withInitialState == 0) {
+    manager->InitState = bAig_One;
+    Ntk_NetworkForEachLatch(network, gen, latch) {
+
+      manager->class_ = 0;
+
+      PureSat_CreateNewNode(manager, node2MvfAigTable, latch, bli, li, &bindex, &index,withInitialState);
+      node =  Ntk_LatchReadInitialInput(latch);
+      st_lookup(node2MvfAigTable,(char*)node,&tmpMvfAig);
+
+      st_lookup(node2MvfAigTable, (char *) latch, &mvfAig);
+      mvfSize = array_n(mvfAig);
+      imvfSize = array_n(tmpMvfAig);
+      if(mvfSize!=imvfSize){
+	fprintf(vis_stdout,"mvfSize:%d!=imvSize:%d, exit\n",mvfSize, imvfSize);
+	exit(0);
+      }
+      tmpv3=0;
+      for(i=0; i< mvfSize; i++){
+	bAigEdge_t tmpvvv;
+	tmpvvv = manager->InitState;
+	v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+	st_insert(old2new, (char *)v, (char *)(li[index1]));
+	flags(li[index1]) |= StateBitMask;
+#ifdef TIMEFRAME_VERIFY_
+	fprintf(vis_stdout, "LI(%d) %s(%d) : %d -> %d\n", 0, Ntk_NodeReadName(latch), i, v, li[index1]);
+#endif
+	ori_li[index1++] = v;
+	if(tmpv3!=SATnormalNode(li[index1-1])){
+
+	  vi = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(tmpMvfAig,i));
+
+	  if(vi == bAig_One){
+	    manager->InitState =
+	      PureSat_And(manager,manager->InitState,li[index1-1]);
+#ifdef TIMEFRAME_VERIFY_
+	    fprintf(vis_stdout,"%d AND %d = %d\n",li[index1-1],tmpvvv,manager->InitState);
+#endif
+	  }
+	  else if(vi == bAig_Zero){
+	    manager->InitState =
+	      PureSat_And(manager,manager->InitState,bAig_Not(li[index1-1]));
+#ifdef TIMEFRAME_VERIFY_
+	    fprintf(vis_stdout,"%d AND %d = %d\n",bAig_Not(li[index1-1]),tmpvvv,manager->InitState);
+#endif
+	  }
+	  else{
+	    tmpv1 = PureSat_ExpandForEachCone(manager,vi,old2new);
+	    tmpv2 = PureSat_Eq(manager,li[index1-1],tmpv1);
+	    manager->InitState = PureSat_And(manager,manager->InitState,tmpv2);
+#ifdef TIMEFRAME_VERIFY_
+
+	    fprintf(vis_stdout,"%d AND %d = %d, %d is EQ node for funct node %d<-->%d\n",
+		   tmpvvv,tmpv2,manager->InitState,tmpv2,tmpv1,li[index1-1] );
+#endif
+	  }
+	}
+	tmpv3 = SATnormalNode(li[index1-1]);
+      }
+
+      lmAigId = Ntk_NodeReadMAigId(latch);
+      lmVar = array_fetch(mAigMvar_t, mVarList, lmAigId);
+      for(i=0, tindex1=lmVar.bVars; i<lmVar.encodeLength; i++) {
+	lbVar = array_fetch(mAigBvar_t, bVarList, tindex1);
+	tindex1++;
+	v = bAig_GetCanonical(manager, lbVar.node);
+	flags(bli[tindex])|=StateBitMask;
+	ori_bli[tindex++] = v;
+      }
+
+    }
+
+#if DBG
+    assert(tindex==bindex&&index1==index);
+#endif
+  }
+
+  st_free_table(old2new);
+
+  manager->class_ = 1;
+
+  timeframe->binputs = (bAigEdge_t **)malloc(sizeof(bAigEdge_t *));
+  bli = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nbInputs);
+  timeframe->binputs[0] = bli;
+
+  timeframe->inputs = (bAigEdge_t **)malloc(sizeof(bAigEdge_t *));
+  li = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nInputs);
+  ori_li = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nInputs);
+  ori_bli = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nInputs);
+  timeframe->inputs[0] = li;
+  timeframe->oriInputs = ori_li;
+  timeframe->oribInputs = ori_bli;
+  index1 = index = 0;
+  tindex = bindex = tindex1 = 0;
+  Ntk_NetworkForEachPrimaryInput(network, gen, node) {
+
+    PureSat_CreateNewNode(manager, node2MvfAigTable, node, bli, li, &bindex, &index,withInitialState);
+
+    st_lookup(node2MvfAigTable, (char *) node, &mvfAig);
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+#ifdef TIMEFRAME_VERIFY_
+	fprintf(vis_stdout, "IN(%d) %s(%d) : %d -> %d\n", 0, Ntk_NodeReadName(node), i, v, li[index1]);
+#endif
+	ori_li[index1++] = v;
+    }
+    lmAigId = Ntk_NodeReadMAigId(node);
+    lmVar = array_fetch(mAigMvar_t, mVarList, lmAigId);
+    for(i=0, tindex1=lmVar.bVars; i<lmVar.encodeLength; i++) {
+      lbVar = array_fetch(mAigBvar_t, bVarList, tindex1);
+      tindex1++;
+      v = bAig_GetCanonical(manager, lbVar.node);
+      ori_bli[tindex++] = v;
+    }
+  }
+  Ntk_NetworkForEachPseudoInput(network, gen, node) {
+
+    PureSat_CreateNewNode(manager, node2MvfAigTable, node, bli, li, &bindex, &index,withInitialState);
+
+    st_lookup(node2MvfAigTable, (char *) node, &mvfAig);
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+#ifdef TIMEFRAME_VERIFY_
+	fprintf(vis_stdout, "PI(%d) %s(%d) : %d -> %d\n", 0, Ntk_NodeReadName(node), i, v, li[index1]);
+#endif
+	ori_li[index1++] = v;
+    }
+    lmAigId = Ntk_NodeReadMAigId(node);
+    lmVar = array_fetch(mAigMvar_t, mVarList, lmAigId);
+    for(i=0, tindex1=lmVar.bVars; i<lmVar.encodeLength; i++) {
+      lbVar = array_fetch(mAigBvar_t, bVarList, tindex1);
+      tindex1++;
+      v = bAig_GetCanonical(manager, lbVar.node);
+      ori_bli[tindex++] = v;
+    }
+  }
+
+    /** map node of previous timeframe into current timeframe **/
+  old2new = st_init_table(st_ptrcmp, st_ptrhash);
+
+  pre_li = timeframe->inputs[0];
+  ori_li = timeframe->oriInputs;
+
+  for(i=0; i<nInputs; i++){
+    st_insert(old2new, (char *)ori_li[i], (char *)pre_li[i]);
+
+    }
+  pre_li = timeframe->latchInputs[0];
+  ori_li = timeframe->oriLatchInputs;
+
+    for(i=0; i<nLatches; i++){
+    st_insert(old2new, (char *)ori_li[i], (char *)pre_li[i]);
+
+    }
+
+  pre_li = timeframe->binputs[0];
+  ori_li = timeframe->oribInputs;
+  for(i=0; i<nbInputs; i++){
+    st_insert(old2new, (char *)ori_li[i], (char *)pre_li[i]);
+
+  }
+  pre_li = timeframe->blatchInputs[0];
+  ori_li = timeframe->oribLatchInputs;
+
+  for(i=0; i<nbLatches; i++){
+    st_insert(old2new, (char *)ori_li[i], (char *)pre_li[i]);
+
+  }
+
+
+    /** create timeframe **/
+  li = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nLatches);
+  timeframe->latchInputs[1] = li;
+  bli = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nbLatches);
+  timeframe->blatchInputs[1] = bli;
+
+
+  bindex = index = 0;
+  Ntk_NetworkForEachLatch(network, gen, latch) {
+    char * name = Ntk_NodeReadName(latch);
+    node  = Ntk_LatchReadDataInput(latch);
+    mvfAig = lmvfAig = 0;
+    st_lookup(node2MvfAigTable, (char *)node, &mvfAig);
+    mvfSize = array_n(mvfAig);
+    st_lookup(node2MvfAigTable, (char *)latch, &lmvfAig);
+    lmvfSize = array_n(lmvfAig);
+    if(mvfSize != lmvfSize) {
+	fprintf(vis_stdout, "WARNING : the number of values of signals mismatched\n");
+	exit(0);
+    }
+
+    else {
+      for(i=0; i< mvfSize; i++){
+	v = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(mvfAig, i));
+
+	nv = PureSat_ExpandForEachCone(manager, v, old2new);
+	flags(nv) |= StateBitMask;
+	st_insert(old2new, (char *)v, (char *)nv);
+#ifdef TIMEFRAME_VERIFY_
+	fprintf(vis_stdout, "LI(%d) %s(%d) : %d -> %d\n",
+	      1, Ntk_NodeReadName(latch), i, v, nv);
+#endif
+	li[index++] = nv;
+	if(nv==bAig_Zero||nv==bAig_One)
+	  continue;
+	if(!st_lookup(idx2name,(char*)bAig_NonInvertedEdge(nv),(char**)&name1)){
+	  st_insert(idx2name,(char*)bAig_NonInvertedEdge(nv),(char*)name);
+#ifdef TIMEFRAME_VERIFY_
+	fprintf(vis_stdout,"idx2name:%d-->%s\n",bAig_NonInvertedEdge(nv),name);
+#endif
+	}
+	else{
+	  /*if they are not equal, resort to MultiLatchTable*/
+	  if(strcmp(name,name1)){
+	    if(st_lookup(MultiLatchTable,(char*)bAig_NonInvertedEdge(nv),&table)){
+#ifdef TIMEFRAME_VERIFY_
+	      fprintf(vis_stdout,"found entry In MultiLatchTable for %d,insert %s \n",
+		     bAig_NonInvertedEdge(nv),name);
+#endif
+	      st_insert(table,(char*)name,(char*)0);
+	    }
+	    else{
+	      table = st_init_table(strcmp,st_strhash);
+#ifdef TIMEFRAME_VERIFY_
+	      fprintf(vis_stdout,"NO entry In MultiLatchTable for %d,insert %s, %s \n",
+		     bAig_NonInvertedEdge(nv),name,name1);
+#endif
+	      st_insert(table,(char*)name1,(char*)0);
+	      st_insert(table,(char*)name,(char*)0);
+	      st_insert(MultiLatchTable,(char*)bAig_NonInvertedEdge(nv),(char*)table);
+	    }
+	  }
+	}
+
+      }
+    }
+
+
+    lmAigId = Ntk_NodeReadMAigId(node);
+    lmVar = array_fetch(mAigMvar_t, mVarList, lmAigId);
+    for(i=0, tindex=lmVar.bVars; i<lmVar.encodeLength; i++) {
+      lbVar = array_fetch(mAigBvar_t, bVarList, tindex);
+      v = bAig_GetCanonical(manager, lbVar.node);
+
+      nv = PureSat_ExpandForEachCone(manager, v, old2new);
+      flags(nv) |= StateBitMask;
+      st_insert(old2new, (char *)v, (char *)nv);
+#ifdef TIMEFRAME_VERIFY_
+	ffprintf(vis_stdout,vis_stdout, "BLI(%d) %s(%d) : %d -> %d\n",
+	      1, Ntk_NodeReadName(latch), i, v, nv);
+#endif
+      bli[bindex++] = nv;
+
+      tindex++;
+      if(nv==bAig_Zero||nv==bAig_One)
+	continue;
+      if(!st_lookup(idx2name,(char*)bAig_NonInvertedEdge(nv),(char**)&name1)){
+	st_insert(idx2name,(char*)bAig_NonInvertedEdge(nv),(char*)name);
+#ifdef TIMEFRAME_VERIFY_
+	fprintf(vis_stdout,"idx2name:%d-->%s\n",bAig_NonInvertedEdge(nv),name);
+#endif
+      }
+      else{
+	/*if they are not equal, resort to MultiLatchTable*/
+	if(strcmp(name,name1)){
+	  if(st_lookup(MultiLatchTable,(char*)bAig_NonInvertedEdge(nv),&table)){
+#ifdef TIMEFRAME_VERIFY_
+	    fprintf(vis_stdout,"found entry In MultiLatchTable for %d,insert %s \n",
+		   bAig_NonInvertedEdge(nv),name);
+#endif
+	    st_insert(table,(char*)name,(char*)0);
+	  }
+	  else{
+	    table = st_init_table(strcmp,st_strhash);
+#ifdef TIMEFRAME_VERIFY_
+	    fprintf(vis_stdout,"NO entry In MultiLatchTable for %d,insert %s, %s \n",
+		   bAig_NonInvertedEdge(nv),name,name1);
+#endif
+	    st_insert(table,(char*)name1,(char*)0);
+	    st_insert(table,(char*)name,(char*)0);
+	    st_insert(MultiLatchTable,(char*)bAig_NonInvertedEdge(nv),(char*)table);
+	  }
+	}
+      }
+    }/*for(i=0, tindex=lmVar.bVars; i<lmVar.en...*/
+  }/*Ntk_NetworkForEachLatch(network, gen, latch) {*/
+
+
+#ifdef TIMEFRAME_VERIFY_
+
+  fprintf(vis_stdout,"after build latches of TF 1\n");
+#endif
+
+
+  timeframe->outputs = (bAigEdge_t **)malloc(sizeof(bAigEdge_t *));
+  li = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nOutputs);
+  timeframe->outputs[0] = li;
+  index = 0;
+  Ntk_NetworkForEachPrimaryOutput(network, gen, node) {
+    st_lookup(node2MvfAigTable, (char *) node, &mvfAig);
+    mvfSize = array_n(mvfAig);
+    for(i=0; i< mvfSize; i++){
+      v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+
+      nv = PureSat_ExpandForEachCone(manager, v, old2new);
+      st_insert(old2new, (char *)v, (char *)nv);
+      li[index++] = nv;
+    }
+  }
+
+  index = 0;
+  timeframe->internals = (bAigEdge_t **)malloc(sizeof(bAigEdge_t *));
+  li = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nInternals);
+  timeframe->internals[0] = li;
+  for(i=0; i<array_n(iindexArray); i++) {
+    v = array_fetch(bAigEdge_t, iindexArray, i);
+
+    nv = PureSat_ExpandForEachCone(manager, v, old2new);
+    st_insert(old2new, (char *)v, (char *)nv);
+    li[i] = nv;
+  }
+
+  /*change the class of latch vars of tf */
+  st_free_table(old2new);
+
+  timeframe->currentTimeframe = 0;
+
+  return(timeframe);
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [build more aig timeframes]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+bAig_PureSat_ExpandTimeFrame(
+	Ntk_Network_t *network,
+	mAig_Manager_t *manager,
+	PureSat_Manager_t *pm,
+	int bound,
+	int withInitialState)
+{
+bAigTimeFrame_t *timeframe;
+int nLatches, nInputs, nOutputs, nInternals;
+int nbLatches, nbInputs;
+int i, j;
+int index, index1, bindex, tindex;
+int mvfSize, lmvfSize;
+int lmAigId;
+array_t *iindexArray;
+MvfAig_Function_t  *mvfAig, *lmvfAig;
+bAigEdge_t *li, *bli;
+bAigEdge_t *pre_li, *ori_li;
+bAigEdge_t v, nv;
+Ntk_Node_t *node, *latch;
+st_table   *node2MvfAigTable, *old2new;
+mAigMvar_t lmVar;
+mAigBvar_t lbVar;
+array_t   *bVarList, *mVarList;
+lsGen gen;
+
+st_table *idx2name, *table, *MultiLatchTable;
+char *name, *name1;
+
+
+  if(withInitialState) timeframe = manager->timeframe;
+  else                 timeframe = manager->timeframeWOI;
+
+  if(timeframe == 0)
+    timeframe = bAig_PureSat_InitTimeFrame(network, manager, pm,withInitialState);
+
+
+  idx2name = timeframe->idx2name;
+  MultiLatchTable = timeframe->MultiLatchTable;
+
+  node2MvfAigTable =
+	(st_table *)Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
+
+  nbLatches = timeframe->nbLatches;
+  nbInputs = timeframe->nbInputs;
+  nLatches = timeframe->nLatches;
+  nInputs = timeframe->nInputs;
+  nOutputs = timeframe->nOutputs;
+  nInternals = timeframe->nInternals;
+
+  iindexArray = timeframe->iindexArray;
+
+  if(bound > timeframe->currentTimeframe) {
+    timeframe->latchInputs = (bAigEdge_t **)
+	realloc(timeframe->latchInputs, sizeof(bAigEdge_t *)*(bound+2));
+    timeframe->inputs = (bAigEdge_t **)
+      realloc(timeframe->inputs, sizeof(bAigEdge_t *)*(bound+1));
+    timeframe->blatchInputs = (bAigEdge_t **)
+	realloc(timeframe->blatchInputs, sizeof(bAigEdge_t *)*(bound+2));
+    timeframe->binputs = (bAigEdge_t **)
+      realloc(timeframe->binputs, sizeof(bAigEdge_t *)*(bound+1));
+    timeframe->outputs = (bAigEdge_t **)
+      realloc(timeframe->outputs, sizeof(bAigEdge_t *)*(bound+1));
+    timeframe->internals = (bAigEdge_t **)
+      realloc(timeframe->internals, sizeof(bAigEdge_t *)*(bound+1));
+  }
+
+  bVarList = mAigReadBinVarList(manager);
+  mVarList = mAigReadMulVarList(manager);
+
+  for(j=timeframe->currentTimeframe+1; j<=bound; j++) {
+    manager->class_ = j+1;
+    if(j>=manager->NumOfTable){
+      manager->NumOfTable *= 2;
+      manager->SymbolTableArray = REALLOC(st_table *,
+		 manager->SymbolTableArray,manager->NumOfTable);
+      manager->HashTableArray = REALLOC(bAigEdge_t *,
+		 manager->HashTableArray,manager->NumOfTable);
+    }
+    manager->SymbolTableArray[manager->class_] = st_init_table(strcmp,st_strhash);
+    manager->HashTableArray[manager->class_] = ALLOC(bAigEdge_t, bAig_HashTableSize);
+    for (i=0; i<bAig_HashTableSize; i++)
+      manager->HashTableArray[manager->class_][i]= bAig_NULL;
+
+
+    /** create new primary input node **/
+    timeframe->inputs = (bAigEdge_t **)
+	realloc(timeframe->inputs, sizeof(bAigEdge_t *)*(j+1));
+    timeframe->binputs = (bAigEdge_t **)
+	realloc(timeframe->binputs, sizeof(bAigEdge_t *)*(j+1));
+    bli = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nbInputs);
+    timeframe->binputs[j] = bli;
+    li = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nInputs);
+    timeframe->inputs[j] = li;
+    index = 0;
+    index1 = 0;
+    bindex = 0;
+    Ntk_NetworkForEachPrimaryInput(network, gen, node) {
+
+      PureSat_CreateNewNode(manager, node2MvfAigTable, node, bli, li, &bindex, &index,withInitialState);
+
+      st_lookup(node2MvfAigTable, (char *) node, &mvfAig);
+      mvfSize = array_n(mvfAig);
+      for(i=0; i< mvfSize; i++){
+	v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+#ifdef TIMEFRAME_VERIFY_
+	fprintf(vis_stdout, "IN(%d) %s(%d) : %d -> %d\n", j, Ntk_NodeReadName(node), i, v, li[index1]);
+#endif
+	index1++;
+      }
+    }
+    Ntk_NetworkForEachPseudoInput(network, gen, node) {
+
+      PureSat_CreateNewNode(manager, node2MvfAigTable, node, bli, li,  &bindex, &index,withInitialState);
+
+      st_lookup(node2MvfAigTable, (char *) node, &mvfAig);
+      mvfSize = array_n(mvfAig);
+      for(i=0; i< mvfSize; i++){
+	v = bAig_GetCanonical(manager, MvfAig_FunctionReadComponent(mvfAig, i));
+#ifdef TIMEFRAME_VERIFY_
+	fprintf(vis_stdout, "PI(%d) %s(%d) : %d -> %d\n", j, Ntk_NodeReadName(node), i, v, li[index1]);
+#endif
+	index1++;
+      }
+    }
+
+    /** map previous time frame into current **/
+    old2new = st_init_table(st_ptrcmp, st_ptrhash);
+    pre_li = timeframe->inputs[j];
+    ori_li = timeframe->oriInputs;
+
+    for(i=0; i<nInputs; i++){
+      st_insert(old2new, (char *)ori_li[i], (char *)pre_li[i]);
+
+    }
+    pre_li = timeframe->latchInputs[j];
+    ori_li = timeframe->oriLatchInputs;
+
+    for(i=0; i<nLatches; i++){
+      st_insert(old2new, (char *)ori_li[i], (char *)pre_li[i]);
+
+    }
+
+    pre_li = timeframe->binputs[j];
+    ori_li = timeframe->oribInputs;
+
+    for(i=0; i<nbInputs; i++){
+      st_insert(old2new, (char *)ori_li[i], (char *)pre_li[i]);
+
+    }
+
+    pre_li = timeframe->blatchInputs[j];
+    ori_li = timeframe->oribLatchInputs;
+
+    for(i=0; i<nbLatches; i++){
+      st_insert(old2new, (char *)ori_li[i], (char *)pre_li[i]);
+
+    }
+
+
+    /** create new time frame **/
+    li = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nLatches);
+    bli = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nbLatches);
+    timeframe->latchInputs[j+1] = li;
+    timeframe->blatchInputs[j+1] = bli;
+    bindex = index = 0;
+    Ntk_NetworkForEachLatch(network, gen, latch) {
+      name = Ntk_NodeReadName(latch);
+
+      node  = Ntk_LatchReadDataInput(latch);
+      mvfAig = lmvfAig = 0;
+      st_lookup(node2MvfAigTable, (char *)node, &mvfAig);
+      mvfSize = array_n(mvfAig);
+      st_lookup(node2MvfAigTable, (char *)latch, &lmvfAig);
+      lmvfSize = array_n(lmvfAig);
+      if(mvfSize != lmvfSize) {
+	fprintf(vis_stdout, "WARNING : the number of values of signals mismatched\n");
+	fprintf(vis_stdout, "          %s(%d), %s(%d)\n",
+		Ntk_NodeReadName(node), mvfSize,
+		Ntk_NodeReadName(latch), lmvfSize);
+	exit(0);
+      }
+      else {
+	for(i=0; i< mvfSize; i++){
+	  v = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(mvfAig, i));
+	  nv = PureSat_ExpandForEachCone(manager, v, old2new);
+	  st_insert(old2new, (char *)v, (char *)nv);
+#ifdef TIMEFRAME_VERIFY_
+	  fprintf(vis_stdout, "LI(%d) %s(%d) : %d -> %d\n",
+		  j+1, Ntk_NodeReadName(latch), i, v, nv);
+#endif
+	  li[index++] = nv;
+	  flags(nv) |= StateBitMask;
+	  if(nv==bAig_Zero||nv==bAig_One)
+	    continue;
+
+	  if(!st_lookup(idx2name,(char*)bAig_NonInvertedEdge(nv),(char**)&name1)){
+	    st_insert(idx2name,(char*)bAig_NonInvertedEdge(nv),(char*)name);
+#ifdef TIMEFRAME_VERIFY_
+	    fprintf(vis_stdout,"idx2name:%d-->%s\n",bAig_NonInvertedEdge(nv),name);
+#endif
+	  }
+	  else{
+	    /*if they are not equal, resort to MultiLatchTable*/
+	    if(strcmp(name,name1)){
+	      if(st_lookup(MultiLatchTable,(char*)bAig_NonInvertedEdge(nv),&table)){
+#ifdef TIMEFRAME_VERIFY_
+		fprintf(vis_stdout,"found entry In MultiLatchTable for %d,insert %s \n",
+		       bAig_NonInvertedEdge(nv),name);
+#endif
+		st_insert(table,(char*)name,(char*)0);
+	      }
+	      else{
+		table = st_init_table(strcmp,st_strhash);
+#ifdef TIMEFRAME_VERIFY_
+		fprintf(vis_stdout,"NO entry In MultiLatchTable for %d,insert %s, %s \n",
+		       bAig_NonInvertedEdge(nv),name,name1);
+#endif
+		st_insert(table,(char*)name1,(char*)0);
+		st_insert(table,(char*)name,(char*)0);
+		st_insert(MultiLatchTable,(char*)bAig_NonInvertedEdge(nv),(char*)table);
+	      }
+	    }
+	  }
+
+	}/* for(i=0; i< mvfSize; i++){*/
+      }/*else {*/
+
+      lmAigId = Ntk_NodeReadMAigId(node);
+      lmVar = array_fetch(mAigMvar_t, mVarList, lmAigId);
+      for(i=0, tindex=lmVar.bVars; i<lmVar.encodeLength; i++) {
+	lbVar = array_fetch(mAigBvar_t, bVarList, tindex);
+	v = bAig_GetCanonical(manager, lbVar.node);
+	nv = PureSat_ExpandForEachCone(manager, v, old2new);
+	flags(nv) |= StateBitMask;
+	st_insert(old2new, (char *)v, (char *)nv);
+#ifdef TIMEFRAME_VERIFY_
+	fprintf(vis_stdout, "BLI(%d) %s(%d) : %d -> %d\n",
+	      j+1, Ntk_NodeReadName(latch), i, v, nv);
+#endif
+	bli[bindex++] = nv;
+	if(nv==bAig_Zero||nv==bAig_One)
+	  continue;
+
+	if(!st_lookup(idx2name,(char*)bAig_NonInvertedEdge(nv),(char**)&name1)){
+	  st_insert(idx2name,(char*)bAig_NonInvertedEdge(nv),(char*)name);
+#ifdef TIMEFRAME_VERIFY_
+	  fprintf(vis_stdout,"idx2name:%d-->%s\n",bAig_NonInvertedEdge(nv),name);
+#endif
+	}
+	else{
+	  /*if they are not equal, resort to MultiLatchTable*/
+	  if(strcmp(name,name1)){
+	    if(st_lookup(MultiLatchTable,(char*)bAig_NonInvertedEdge(nv),&table)){
+#ifdef TIMEFRAME_VERIFY_
+	      fprintf(vis_stdout,"found entry In MultiLatchTable for %d,insert %s \n",
+		     bAig_NonInvertedEdge(nv),name);
+#endif
+	      st_insert(table,(char*)name,(char*)0);
+	    }
+	    else{
+	      table = st_init_table(strcmp,st_strhash);
+#ifdef TIMEFRAME_VERIFY_
+	      fprintf(vis_stdout,"NO entry In MultiLatchTable for %d,insert %s, %s \n",
+		     bAig_NonInvertedEdge(nv),name,name1);
+#endif
+	      st_insert(table,(char*)name1,(char*)0);
+	      st_insert(table,(char*)name,(char*)0);
+	      st_insert(MultiLatchTable,(char*)bAig_NonInvertedEdge(nv),(char*)table);
+	    }
+	  }
+	}
+
+	tindex++;
+      }
+    }
+
+    li = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nOutputs);
+    timeframe->outputs[j] = li;
+    index = 0;
+    Ntk_NetworkForEachPrimaryOutput(network, gen, node) {
+      st_lookup(node2MvfAigTable, (char *)node, &mvfAig);
+      mvfSize = array_n(mvfAig);
+      for(i=0; i< mvfSize; i++){
+	v = bAig_GetCanonical(manager,MvfAig_FunctionReadComponent(mvfAig, i));
+	nv = PureSat_ExpandForEachCone(manager, v, old2new);
+	st_insert(old2new, (char *)v, (char *)nv);
+	li[index++] = nv;
+      }
+    }
+
+    li = (bAigEdge_t *)malloc(sizeof(bAigEdge_t)*nInternals);
+    timeframe->internals[j] = li;
+    for(i=0; i<array_n(iindexArray); i++) {
+      v = array_fetch(bAigEdge_t, iindexArray, i);
+      nv = PureSat_ExpandForEachCone(manager, v, old2new);
+      st_insert(old2new, (char *)v, (char *)nv);
+      li[i] = nv;
+    }
+    st_free_table(old2new);
+
+
+  }
+
+
+  timeframe->currentTimeframe = bound;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Name comparison function.]
+
+  Description [Name comparison function.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+nameCompare(
+  const void * node1,
+  const void * node2)
+{
+  char *name1, *name2;
+
+  name1 = Ntk_NodeReadName((Ntk_Node_t *)node1);
+  name2 = Ntk_NodeReadName((Ntk_Node_t *)node2);
+  return(strcmp(*(char**)name1, *(char **)name2));
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Compute number of encoding bits.]
+
+  Description [Compute number of encoding bits.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+NoOfBitEncode( int n)
+{
+  int i = 0;
+  int j = 1;
+
+  if (n < 2) return 1; /* Takes care of mv.values <= 1 */
+
+  while (j < n) {
+    j = j * 2;
+    i++;
+  }
+  return i;
+}
Index: vis_dev/vis-2.3/src/puresat/puresatUtil.c
===================================================================
--- vis_dev/vis-2.3/src/puresat/puresatUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/puresat/puresatUtil.c	(revision 14)
@@ -0,0 +1,1711 @@
+/**CFile***********************************************************************
+
+  FileName    [puresatUtil.c]
+
+  PackageName [puresat]
+
+  Synopsis    [Abstraction refinement for large scale invariant checking.]
+
+  Description [This file contains the functions to check invariant properties
+  by the PureSAT abstraction refinement algorithm, which is entirely based on
+  SAT solver, the input of which could be either CNF or AIG. It has several
+  parts:
+
+  * Localization-reduction base Abstraction
+  * K-induction or interpolation to prove the truth of a property
+  * Bounded Model Checking to find bugs
+  * Incremental concretization based methods to verify abstract bugs
+  * Incremental SAT solver to improve efficiency
+  * UNSAT proof based method to obtain refinement
+  * AROSAT to bring in only necessary latches into unsat proofs
+  * Bridge abstraction to get compact coarse refinement
+  * Refinement minization to guarrantee minimal refinements
+  * Unsat proof-based refinement minimization to eliminate multiple candidate
+    by on SAT test
+  * Refinement prediction to decrease the number of refinement iterations
+  * Dynamic switching to redistribute computional resources to improve
+    efficiency
+
+  For more information, please check the BMC'03, ICCAD'04, STTT'05 and TACAS'05
+  paper of Li et al., "A satisfiability-based appraoch to abstraction
+  refinement in model checking", " Abstraction in symbolic model checking
+  using satisfiability as the only decision procedure", "Efficient computation
+  of small abstraction refinements", and "Efficient abstraction refinement in
+  interpolation-based unbounded model checking"]
+
+  Author      [Bing Li]
+
+  Copyright   [Copyright (c) 2004 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without
+  license or royalty fees, to use, copy, modify, and distribute this
+  software and its documentation for any purpose, provided that the
+  above copyright notice and the following two paragraphs appear in
+  all copies of this software.]
+
+******************************************************************************/
+
+#include "puresatInt.h"
+#include "sat.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+static array_t *RCArray;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [time out function]
+
+  Description [time out function]
+
+  SideEffects []
+
+  SeeAlso     []
+
+*******************************************************************************/
+
+static int DfsLevel = 0;
+static array_t *NumInCone;
+static array_t *NumInAbs;
+static array_t *DfsArray;
+/*static array_t *RCArray;*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocate a puresat manager]
+
+  Description [Allocate a puresat manager]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+PureSat_Manager_t * PureSatManagerAlloc(void)
+{
+  PureSat_Manager_t * pm = ALLOC(PureSat_Manager_t,1);
+  memset(pm,0,sizeof(PureSat_Manager_t));
+  pm->incre = TRUE;
+  pm->ltlFileName = ALLOC(char,200);
+  pm->timeOutPeriod = 10000000;
+  pm->Arosat = TRUE;;
+  pm->CoreRefMin = TRUE;
+  pm->RefPredict = TRUE;
+  pm->Switch = TRUE;
+  return pm;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Free a puresat manager]
+
+  Description [Free a puresat manager]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+PureSatManagerFree(PureSat_Manager_t * pm){
+  if(pm->latchToTableBaigNodes)
+    st_free_table(pm->latchToTableBaigNodes);
+  if(pm->ClsidxToLatchTable)
+    st_free_table(pm->ClsidxToLatchTable);
+  if(pm->CoiTable)
+    st_free_table(pm->CoiTable);
+  if(pm->AbsTable)
+    st_free_table(pm->AbsTable);
+  if(pm->vertexTable)
+    st_free_table(pm->vertexTable);
+  if(pm->SufAbsTable)
+    st_free_table(pm->SufAbsTable);;
+  if(pm->supportTable)
+    st_free_table(pm->supportTable);
+  if(pm->node2dfsTable)
+    st_free_table(pm->node2dfsTable);
+  if(pm->result!=NIL(array_t))
+    array_free(pm->result);
+  FREE(pm->ltlFileName);
+  FREE(pm);
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Allocate a puresat incremental SAT manager]
+
+  Description [Allocate a puresat incremental SAT manager]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+PureSat_IncreSATManager_t * PureSatIncreSATManagerAlloc(PureSat_Manager_t * pm)
+{
+  PureSat_IncreSATManager_t * pism = ALLOC(PureSat_IncreSATManager_t,1);
+  pism->beginPosition = 0;
+  pism->Length = 0;
+  pism->oldLength = 0;
+  pism->propertyPos = 0;
+  memset(pism,0,sizeof(PureSat_IncreSATManager_t));
+  if(pm->sss){
+    pism->cnfClauses = BmcCnfClausesAlloc();
+    pism->cm = sat_InitManager(0);
+    pism->cm->comment = ALLOC(char, 2);
+    pism->cm->comment[0] = ' ';
+    pism->cm->comment[1] = '\0';
+
+    pism->cm->maxNodesArraySize = 1;
+    pism->cm->nodesArray = ALLOC(long, pism->cm->maxNodesArraySize );
+    pism->cm->nodesArraySize = satNodeSize;
+    pism->cm->stdErr = vis_stderr;
+    pism->cm->stdOut = vis_stdout;
+    pism->cm->unitLits = sat_ArrayAlloc(16);
+    pism->cm->pureLits = sat_ArrayAlloc(16);
+    pism->cm->each = sat_InitStatistics();
+    pism->cm->option = sat_InitOption();
+    pism->cm->option->ForceFinish = 1;
+    pism->cm->option->incTraceObjective = 1;
+    pism->cm->option->includeLevelZeroLiteral = 1;
+    pism->cm->option->minimizeConflictClause = 0;
+    pism->cm->option->SSS = 1;
+  }
+  return pism;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Free a puresat incremental SAT manager]
+
+  Description [Free a puresat incremental SAT manager]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void
+PureSatIncreSATManagerFree(PureSat_Manager_t *pm,
+			   PureSat_IncreSATManager_t * pism)
+{
+  if(pm->sss){
+    BmcCnfClausesFree(pism->cnfClauses);
+    FREE(pism->cm->nodesArray);
+    sat_ArrayFree(pism->cm->unitLits);
+    sat_ArrayFree(pism->cm->pureLits);
+    sat_FreeStatistics(pism->cm->each);
+    sat_FreeOption(pism->cm->option);
+    FREE(pism->cm);
+  }
+  FREE(pism);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Get the cone of influence for a network node]
+
+  Description [Get the cone of influence for a network node]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void
+PureSatBmcGetCoiForNtkNode(
+  Ntk_Node_t  *node,
+  st_table    *CoiTable,
+  st_table    *visited)
+{
+  int        i, j;
+  Ntk_Node_t *faninNode;
+
+  if(node == NIL(Ntk_Node_t)){
+    return;
+  }
+  if(Ntk_NodeTestIsLatch(node)){
+    DfsLevel++;
+    if (st_lookup_int(CoiTable, node, &j)&&j<=DfsLevel){
+      DfsLevel--;
+      return;
+    }
+  }
+
+  if (st_lookup_int(visited,  node, &j)&&j<=DfsLevel){
+    if(Ntk_NodeTestIsLatch(node))
+      DfsLevel--;
+    return;
+  }
+  st_insert(visited, node, (char *)(long)DfsLevel);
+  if (Ntk_NodeTestIsLatch(node)){
+    st_insert(CoiTable,  node, (char *)(long)DfsLevel);
+  }
+
+  if(Ntk_NodeTestIsInput(node))
+    {
+      return;
+    }
+
+  Ntk_NodeForEachFanin(node, i, faninNode) {
+    PureSatBmcGetCoiForNtkNode(faninNode, CoiTable, visited);
+  }
+  if(Ntk_NodeTestIsLatch(node))
+    DfsLevel--;
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Get the cone of influence for a ltl formula]
+
+  Description [Get the cone of influence for a ltl formula]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void
+PureSatBmcGetCoiForLtlFormulaRecursive(
+  Ntk_Network_t   *network,
+  Ctlsp_Formula_t *formula,
+  st_table        *ltlCoiTable,
+  st_table        *visited)
+{
+  if (formula == NIL(Ctlsp_Formula_t)) {
+    return;
+  }
+  /* leaf node */
+  if (formula->type == Ctlsp_ID_c){
+    char       *name = Ctlsp_FormulaReadVariableName(formula);
+    Ntk_Node_t *node = Ntk_NetworkFindNodeByName(network, name);
+    int        tmp;
+
+    if (st_lookup_int(visited, node, &tmp)){
+      /* Node already visited */
+      return;
+    }
+    PureSatBmcGetCoiForNtkNode(node, ltlCoiTable, visited);
+    return;
+  }
+  PureSatBmcGetCoiForLtlFormulaRecursive(network, formula->left,  ltlCoiTable, visited);
+  PureSatBmcGetCoiForLtlFormulaRecursive(network, formula->right, ltlCoiTable, visited);
+
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Get the color of a node]
+
+  Description [Get the color of a node]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DfsColor
+PureSatNodeReadColor(
+  Ntk_Node_t * node)
+{
+  return ((DfsColor) (long) Ntk_NodeReadUndef(node));
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Set the color of a node]
+
+  Description [Set the color of a node]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+PureSatNodeSetColor(
+  Ntk_Node_t * node,
+  DfsColor  color)
+{
+  Ntk_NodeSetUndef(node, (void *) (long) color);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Recursively compute the transitive fan in nodes of a node]
+
+  Description [Recursively compute the transitive fan in nodes of a node]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+PureSatNodeRecursivelyComputeTransitiveFaninNodes_AllNodes(
+  Ntk_Node_t *node,
+  int * NumofSupports,
+  boolean stopAtLatches)
+{
+  int i;
+  Ntk_Node_t * fanin;
+
+  /* test if we have already started processing this node */
+  if ( PureSatNodeReadColor( node ) == dfsBlack_c ) {
+	return;
+  }
+  PureSatNodeSetColor( node, dfsBlack_c );
+
+  /* if ( Ntk_NodeTestIsCombInput( node ) ) {
+  st_insert( resultTable, (char *) node, (char *) 0 );
+	 }*/
+
+  (*NumofSupports)++;
+
+  if ( Ntk_NodeTestIsInput(node) || ((stopAtLatches == TRUE)&&(Ntk_NodeTestIsLatch(node))) ) {
+	return;
+  }
+
+  Ntk_NodeForEachFanin( node, i, fanin ) {
+	PureSatNodeRecursivelyComputeTransitiveFaninNodes_AllNodes( fanin, NumofSupports, stopAtLatches );
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Get the number of combination support of a node]
+
+  Description [Get the number of combination support of a node]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+int
+PureSatNodeComputeCombinationalSupport_AllNodes(
+  Ntk_Network_t *network,
+  array_t * nodeArray,
+  boolean stopAtLatches )
+{
+  lsGen gen;
+  int i, NumofSupports=0;
+  Ntk_Node_t *node;
+
+  Ntk_NetworkForEachNode( network, gen, node ) {
+	PureSatNodeSetColor( node, dfsWhite_c );
+  }
+
+/* for each lacthes(node) in the nodeArray, compute the number of gates in
+   the cone of this latch, put the number in NumofSupports*/
+  arrayForEachItem( Ntk_Node_t *, nodeArray, i, node ) {
+    NumofSupports = 0;
+    PureSatNodeRecursivelyComputeTransitiveFaninNodes_AllNodes( node, &NumofSupports, stopAtLatches );
+  }
+
+  return NumofSupports;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Build a support table,each value associated with a latch is the
+	       number of gates in its cone of influence ]
+
+  Description [Build a support table,each value associated with a latch is the
+	       number of gates in its cone of influence ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+/*build a supportTable, each value associated with a latch is NumofGatesInCone*/
+void PureSatGenerateSupportTable(
+  Ntk_Network_t   *network,
+  PureSat_Manager_t *pm)
+{
+  array_t    *roots = array_alloc(Ntk_Node_t *,0); /*supports;*/
+  st_generator *stgen;
+  Ntk_Node_t *node,*DataNode=(Ntk_Node_t *)0;
+  int        count, NumofSupports;
+
+  st_foreach_item_int(pm->CoiTable, stgen, &node, &count) {
+    if (Ntk_NodeTestIsLatch(node))
+      DataNode = Ntk_LatchReadDataInput(node);
+    array_insert(Ntk_Node_t *, roots, 0, DataNode);
+    NumofSupports = PureSatNodeComputeCombinationalSupport_AllNodes(network, roots,FALSE);
+
+    st_insert(pm->supportTable,node, (char *)(long)NumofSupports);
+  }
+  array_free(roots);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Compute the cone of influence for a ltl formula]
+
+  Description [Compute the cone of influence for a ltl formula]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+PureSatBmcGetCoiForLtlFormula(
+  Ntk_Network_t   *network,
+  Ctlsp_Formula_t *formula,
+  st_table        *ltlCoiTable)
+{
+  st_table *visited = st_init_table(st_ptrcmp, st_ptrhash);
+
+  PureSatBmcGetCoiForLtlFormulaRecursive(network, formula, ltlCoiTable, visited);
+  st_free_table(visited);
+  return;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    []
+
+  Description [recursively compute the nodes in a ltl formula and put them in
+	       an array]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void
+PureSatGetFormulaNodes(
+  Ntk_Network_t *network,
+  Ctlsp_Formula_t *F,
+  array_t *formulaNodes)
+{
+
+  if (F == NIL(Ctlsp_Formula_t))
+    return;
+
+  if (Ctlsp_FormulaReadType(F) == Ctlsp_ID_c) {
+    char *nodeNameString = Ctlsp_FormulaReadVariableName(F);
+    Ntk_Node_t *node = Ntk_NetworkFindNodeByName(network, nodeNameString);
+    assert(node);
+    array_insert_last(Ntk_Node_t *, formulaNodes, node);
+    return;
+  }
+
+  PureSatGetFormulaNodes(network, Ctlsp_FormulaReadRightChild(F), formulaNodes);
+  PureSatGetFormulaNodes(network, Ctlsp_FormulaReadLeftChild(F),  formulaNodes);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Get direct fan in latches for a node]
+
+  Description [Get direct fan in latches for a node]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void
+PureSatGetFaninLatches(
+  Ntk_Node_t *node,
+  st_table *visited,
+  st_table *vertexTable)
+{
+  if (st_is_member(visited, node))
+    return;
+
+  st_insert(visited, node, (char *)0);
+
+  if (Ntk_NodeTestIsLatch(node))
+    st_insert(vertexTable, Ntk_NodeReadName(node), (char *)0);
+  else {
+    int i;
+    Ntk_Node_t *fanin;
+    Ntk_NodeForEachFanin(node, i, fanin) {
+      PureSatGetFaninLatches(fanin, visited, vertexTable);
+    }
+  }
+}
+/**Function********************************************************************
+
+  Synopsis    [Build a vertex table which stores all the latches in the
+  beginning abstract model]
+
+  Description [The table contains only those immediate fanin latches of the
+  given formula.]
+
+  SideEffects []
+
+  SeeAlso     []
+******************************************************************************/
+
+st_table *
+PureSatCreateInitialAbstraction(
+  Ntk_Network_t *network,
+  Ctlsp_Formula_t *invFormula,
+  int * Num,
+  PureSat_Manager_t *pm)
+{
+  array_t *formulaNodes = array_alloc(Ntk_Node_t *, 0);
+  Ntk_Node_t *node;
+  int i;
+
+  st_table *vertexTable = st_init_table(strcmp, st_strhash);
+  st_table *visited = st_init_table(st_ptrcmp, st_ptrhash);
+  *Num=0;
+
+  PureSatGetFormulaNodes(network, invFormula, formulaNodes);
+  arrayForEachItem(Ntk_Node_t *, formulaNodes, i, node) {
+    PureSatGetFaninLatches(node, visited, vertexTable);
+  }
+
+  st_free_table(visited);
+  array_free(formulaNodes);
+
+  if (1) {
+    st_generator *stgen;
+    char *nodeNameString;
+
+    if(pm->verbosity>=1)
+      fprintf(vis_stdout, "\n Create_InitialAbstraction() =\n");
+    st_foreach_item(vertexTable, stgen, &nodeNameString, 0) {
+      if(pm->verbosity>=1)
+	fprintf(vis_stdout, "%s\n", nodeNameString);
+      (*Num)++;
+    }
+    if(pm->verbosity>=1){
+      fprintf(vis_stdout, "\n");
+      fflush(vis_stdout);
+    }
+  }
+
+
+  return vertexTable;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Recursively get direct fan in gates of a node]
+
+  Description [Recursively get direct fan in gates of a node]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void
+PureSatRecursivelyComputeTableForLatch(Ntk_Network_t * network,
+				       st_table *Table,
+				       Ntk_Node_t * node)
+{
+  int i;
+  Ntk_Node_t * fanin;
+
+  //want input to be in the Table
+  if(Ntk_NodeTestIsLatch(node))
+    return;
+
+  if(!st_lookup(Table,node,NIL(char *)))
+    st_insert(Table,node, (char *)0);
+  else
+    return;
+
+   if ( Ntk_NodeTestIsCombInput(node)) {
+	return;
+  }
+
+  Ntk_NodeForEachFanin( node,i,fanin)
+   PureSatRecursivelyComputeTableForLatch(network,Table,fanin);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Get direct fan in gates of a node]
+
+  Description [Get direct fan in gates of a node]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+/* put all the gates of Abs model to the Table */
+void
+PureSatComputeTableForLatch(Ntk_Network_t * network,
+			    st_table * Table,
+			    Ntk_Node_t * Latch)
+{
+  Ntk_Node_t * fanin;
+  int i;
+
+  if(!Ntk_NodeTestIsLatch(Latch))
+    {
+      char * name = Ntk_NodeReadName(Latch);
+      fprintf(vis_stdout,"%s is not a latch!\n",name);
+      exit (0);
+    }
+
+  if(!st_lookup(Table,Latch,NIL(char *)))
+    {
+      st_insert(Table,Latch, (char *)0);
+      Ntk_NodeForEachFanin(Latch,i,fanin)
+	PureSatRecursivelyComputeTableForLatch(network,Table,fanin);
+    }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Take latches in visibleArray as the first level
+  compute the DFS level of each latch in ltlCoiTable]
+
+  Description [Take latches in visibleArray as the first level
+  compute the DFS level of each latch in ltlCoiTable]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void
+PureSatGetCoiForVisibleArray_Ring(
+  Ntk_Network_t   *network,
+  array_t *visibleArray,
+  int             position,
+  st_table        *ltlCoiTable)
+{
+  int i;
+  char * name;
+  Ntk_Node_t * node;
+
+  st_table *visited = st_init_table(st_ptrcmp, st_ptrhash);
+
+
+  for(i=position;i<array_n(visibleArray);i++){
+    name = array_fetch(char *,visibleArray,i);
+    node = Ntk_NetworkFindNodeByName(network,name);
+    DfsLevel = 0;
+    PureSatBmcGetCoiForNtkNode(node,ltlCoiTable, visited);
+  }
+  st_free_table(visited);
+  return;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compare function for quick sort]
+
+  Description [Compare function for quick sort]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+int
+NumInConeCompare(int *ptrX,
+		 int *ptrY)
+{
+  int a,b;
+  int c,d;
+  double e,f;
+  a = array_fetch(int,NumInCone,(int)*ptrX);
+  b = array_fetch(int,NumInCone,(int)*ptrY);
+  c = array_fetch(int,NumInAbs,(int)*ptrX);
+  d = array_fetch(int,NumInAbs,(int)*ptrY);
+  e = (double)c/(double)a;
+  f = (double)d/(double)b;
+  if(e > f)
+    return -1;
+  if( e < f)
+    return 1;
+  return 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compare function for quick sort]
+
+  Description [Compare function for quick sort]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+int
+NumInConeCompare_Ring(int *ptrX,
+		      int *ptrY)
+{
+  int a,b;
+  double c,d;
+  double e,f;
+  a = array_fetch(int,DfsArray,(int)*ptrX);
+  b = array_fetch(int,DfsArray,(int)*ptrY);
+  c = array_fetch(double,RCArray,(int)*ptrX);
+  d = array_fetch(double,RCArray,(int)*ptrY);
+  e = (double)((a)*1000000)-c;
+  f = (double)((b)*1000000)-d;
+  if(e > f)
+    return 1;
+  if( e < f)
+    return -1;
+  return 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Recursively compute the relative correlation of a latch.
+  For more information of Relative Correlation, please check the BMC'03 and STTT'05
+  paper of Li et al., "A satisfiability-based appraoch to abstraction
+  refinement in model checking", and " Abstraction in symbolic model checking
+  using satisfiability as the only decision procedure"]
+
+  Description [Recursively compute the relative correlation of a latch.
+  For more information of Relative Correlation, please check the BMC'03 and STTT'05
+  paper of Li et al., "A satisfiability-based appraoch to abstraction
+  refinement in model checking", and " Abstraction in symbolic model checking
+  using satisfiability as the only decision procedure"]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSatRecursivelyComputeCorrelationforLatch(Ntk_Network_t *network,
+						  st_table *AbsTable,
+						  st_table * visited,
+						  Ntk_Node_t *node,
+						  int *count)
+{
+  Ntk_Node_t * fanin;
+  int i;
+
+  if(!st_lookup(visited,node,NIL(char *)))
+  {
+    st_insert(visited,node,(char *)0);
+    if(st_lookup(AbsTable,node,NIL(char *)))
+      {
+	(*count)++;
+      }
+  }
+  else
+    return;
+
+  if(Ntk_NodeTestIsCombInput(node))
+    return;
+
+  Ntk_NodeForEachFanin(node,i,fanin)
+    PureSatRecursivelyComputeCorrelationforLatch(network,AbsTable,visited,fanin,count);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compute the relative correlation of a latch.
+  For more information of Relative Correlation, please check the BMC'03 and STTT'05
+  paper of Li et al., "A satisfiability-based appraoch to abstraction
+  refinement in model checking", and " Abstraction in symbolic model checking
+  using satisfiability as the only decision procedure"]
+
+  Description [Compute the relative correlation of a latch.
+  For more information of Relative Correlation, please check the BMC'03 and STTT'05
+  paper of Li et al., "A satisfiability-based appraoch to abstraction
+  refinement in model checking", and " Abstraction in symbolic model checking
+  using satisfiability as the only decision procedure"]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+int PureSatComputeCorrelationforLatch(Ntk_Network_t * network, st_table *
+			      AbsTable, Ntk_Node_t *Latch)
+{
+  int count =0,i;
+  Ntk_Node_t * fanin;
+
+  st_table *visited = st_init_table(st_ptrcmp,st_ptrhash);
+  Ntk_NodeForEachFanin(Latch,i,fanin)
+    PureSatRecursivelyComputeCorrelationforLatch(network,AbsTable,visited,fanin,&count);
+  st_free_table(visited);
+  return count*10000;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Generating the ring information needed for the computation of
+  the relative correlation of a latch. For more information of Relative
+  Correlation, please check the BMC'03 and STTT'05 paper of Li et al., "A
+  satisfiability-based appraoch to abstraction refinement in model checking",
+  and " Abstraction in symbolic model checking
+  using satisfiability as the only decision procedure]
+
+  Description [Generating the ring information needed for the computation of
+  the relative correlation of a latch. For more information of Relative
+  Correlation, please check the BMC'03 and STTT'05 paper of Li et al., "A
+  satisfiability-based appraoch to abstraction refinement in model checking",
+  and " Abstraction in symbolic model checking
+  using satisfiability as the only decision procedure"]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+array_t * PureSatGenerateRingFromAbs(Ntk_Network_t *network,
+				    PureSat_Manager_t *pm,
+				    array_t *invisibleArray,
+				    int * NumInSecondLevel)
+{
+  st_table *CoiTable = pm->CoiTable;
+  st_table *supportTable = pm->supportTable;
+  st_table *AbsTable= pm->AbsTable;
+
+  array_t * arrayRC = array_alloc(char *,array_n(invisibleArray)),* NumInConeArray = array_alloc(int,0),* NumInAbsArray = array_alloc(int,0);
+  array_t * tmpNumInCone = array_alloc(int,0),* tmpNumInAbs = array_alloc(int,0);
+  array_t * tmpDfsArray = array_alloc(int,0), *tmpRCArray = array_alloc(double,0);
+  array_t * tmpDfsArray1 = array_alloc(int,0), *tmpRCArray1 = array_alloc(double,0);
+  int numincone,i,j,dfs;
+  char *name;
+  double d1;
+
+  (*NumInSecondLevel) = 0;
+
+  for(i=0;i<array_n(invisibleArray);i++)
+   {
+     int tmp;
+     Ntk_Node_t *tmpnode;
+     name = array_fetch(char *,invisibleArray,i);
+     tmpnode = Ntk_NetworkFindNodeByName(network,name);
+     tmp = PureSatComputeCorrelationforLatch(network,AbsTable,tmpnode);
+     tmp = tmp/10000;
+
+     if(!st_lookup_int(CoiTable,tmpnode,&dfs)){
+       fprintf(vis_stderr,"not in Coitable,  Wrong");
+       exit(0);
+     }
+     if(!st_lookup_int(supportTable,tmpnode, &numincone)){
+       fprintf(vis_stderr,"not in supporttable,  Wrong");
+       exit(0);
+     }
+     d1 = (double)tmp/(double)numincone;
+     array_insert_last(double,tmpRCArray,d1);
+     array_insert_last(int,tmpDfsArray,dfs);
+
+   }
+
+
+  DfsArray = tmpDfsArray;
+  RCArray = tmpRCArray;
+   {
+     int tmpvalue;
+     double dvalue;
+     int nn = array_n(invisibleArray);
+     int *tay=ALLOC(int,nn);
+     for(j=0;j<nn;j++)
+       tay[j]=j;
+     qsort((void *)tay, nn, sizeof(int),
+	   (int (*)(const void *, const void *))NumInConeCompare_Ring);
+     for(i=0;i<nn;i++)
+       {
+	 char *str=ALLOC(char,100);
+	 name = array_fetch(char *,invisibleArray,tay[i]);
+	 strcpy(str,name);
+	 array_insert(char *,arrayRC,i,str);
+	 tmpvalue = array_fetch(int,tmpDfsArray,tay[i]);
+	 if(tmpvalue == 2)
+	   (*NumInSecondLevel)++;
+	 array_insert(int,tmpDfsArray1,i,tmpvalue);
+	 dvalue = array_fetch(double,tmpRCArray,tay[i]);
+	 array_insert(double,tmpRCArray1,i,dvalue);
+	 if(pm->verbosity>=2){
+	   int i1;
+	   double d1,d2;
+	   i1 = array_fetch(int,tmpDfsArray1,i)*1000000;
+	   d1 = array_fetch(double,tmpRCArray1,i);
+	   d2 = (double)array_fetch(int,tmpDfsArray1,i)*1000000 - d1;
+	   if(pm->verbosity>=1)
+	     fprintf(vis_stdout,"arrayRC %s: %d-%f = %f\n",name,i1,d1,d2);
+	   /* fprintf(vis_stdout,"arrayRC %s: %d-%f = %f\n",name,array_fetch(int,tmpDfsArray1,i)*1000000,array_fetch(double,tmpRCArray1,i),
+	      (double)array_fetch(int,tmpDfsArray1,i)*1000000-(double)array_fetch(double,tmpRCArray1,i));*/
+	 }
+       }
+     FREE(tay);
+   }
+   array_free(NumInConeArray);
+   array_free(NumInAbsArray);
+   array_free(tmpNumInCone);
+   array_free(tmpNumInAbs);
+   array_free(tmpDfsArray);
+   array_free(tmpRCArray);
+   array_free(tmpDfsArray1);
+   array_free(tmpRCArray1);
+   return arrayRC;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Clean the SAT solver after a SAT solving procedure is done]
+
+  Description [Clean the SAT solver after a SAT solving procedure is done]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSatCleanSat(satManager_t * cm)
+{
+  int i;
+  satVariable_t *var;
+  satLevel_t *d;
+
+  cm->nodesArraySize = satNodeSize;
+  sat_ArrayFree(cm->unitLits);
+  sat_ArrayFree(cm->pureLits);
+  cm->unitLits = sat_ArrayAlloc(16);
+  cm->pureLits = sat_ArrayAlloc(16);
+  memset(cm->each,0,sizeof(satStatistics_t));
+  cm->literals->last = cm->literals->begin+1;
+  cm->literals->initialSize = cm->literals->last;
+  cm->status = 0;
+  cm->currentVarPos = 0;
+  cm->currentTopConflict = 0;
+  cm->lowestBacktrackLevel = 0;
+  cm->implicatedSoFar = 0;
+  /*cm->decisionHead = ALLOC(satLevel_t, cm->decisionHeadSize);*/
+  memset(cm->decisionHead, 0, sizeof(satLevel_t) * cm->decisionHeadSize);
+  /* FREE(cm->variableArray);
+  cm->variableArray = 0;*/
+  if(cm->variableArray) {
+    for(i=0; i<=cm->initNumVariables; i++) {
+      var = &(cm->variableArray[i]);
+      if(var->wl[0]) {
+	sat_ArrayFree(var->wl[0]);
+	var->wl[0] = 0;
+      }
+      if(var->wl[1]) {
+	sat_ArrayFree(var->wl[1]);
+	var->wl[1] = 0;
+      }
+    }
+    free(cm->variableArray);
+    cm->variableArray = 0;
+  }
+
+  if(cm->decisionHead) {
+    for(i=0; i<cm->decisionHeadSize; i++) {
+      d = &(cm->decisionHead[i]);
+      if(d->implied)
+	sat_ArrayFree(d->implied);
+      if(d->satisfied)
+	sat_ArrayFree(d->satisfied);
+    }
+    free(cm->decisionHead);
+    cm->decisionHead = 0;
+    cm->decisionHeadSize = 0;
+  }
+
+  sat_FreeQueue(cm->queue);
+  cm->queue = 0;
+  sat_FreeQueue(cm->BDDQueue);
+  cm->BDDQueue = 0;
+  sat_FreeQueue(cm->unusedAigQueue);
+  cm->unusedAigQueue = 0;
+  sat_ArrayFree(cm->auxArray);
+  sat_ArrayFree(cm->nonobjUnitLitArray);
+  sat_ArrayFree(cm->objUnitLitArray);
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Read clauses from a puresat incremental SAT manager to the
+  CirCUs SAT solver]
+
+  Description [Read clauses from a puresat incremental SAT manager to the
+  CirCUs SAT solver]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSatReadClauses(PureSat_IncreSATManager_t * pism,
+			PureSat_Manager_t * pm)
+{
+  int i,node,nVar = pism->cnfClauses->cnfGlobalIndex - 1;
+  satManager_t * cm = pism->cm;
+  satArray_t * clauseArray;
+
+  cm->option->verbose = pm->verbosity;
+  cm->initNumVariables = nVar;
+  cm->variableArray = ALLOC(satVariable_t, cm->initNumVariables+1);
+  memset(cm->variableArray, 0, sizeof(satVariable_t) *
+	 (cm->initNumVariables+1));
+  if(cm->maxNodesArraySize <= (cm->initNumVariables+2)*satNodeSize){
+    cm->nodesArray = ALLOC(long, (cm->initNumVariables+2)*satNodeSize);
+    cm->maxNodesArraySize = (cm->initNumVariables+2)*satNodeSize;
+  }
+
+
+  if(pism->cm->option->coreGeneration){
+    pism->cm->dependenceTable = st_init_table(st_ptrcmp, st_ptrhash);
+
+    /*the tables stroes entry of (var_node_idx,cls_idx);*/
+    pism->cm->anteTable = st_init_table(st_numcmp, st_numhash);
+
+  }
+  sat_AllocLiteralsDB(cm);
+
+  for(i=1;i<=nVar;i++){
+    node = sat_CreateNode(cm,2,2);
+    SATflags(node) |= CoiMask;
+    SATvalue(node) = 2;
+    /*SATfanout(node) = 0;*/
+    cm->nodesArray[node+satFanout] = 0;
+    SATnFanout(node) = 0;
+  }
+
+  clauseArray = sat_ArrayAlloc(4096);
+  for(i=0; i<pism->cnfClauses->nextIndex;i++){
+    int k, cls_idx,v;
+    k = array_fetch(int,pism->cnfClauses->clauseArray,i);
+    if(k!=0){
+      int sign = 1;
+      if(k<0){
+	sign = 0;
+	k = -k;
+      }
+      v = k*satNodeSize + sign;
+      sat_ArrayInsert(clauseArray, v);
+    }
+    else{
+      if(clauseArray->num == 1) {
+	v = clauseArray->space[0];
+	sat_ArrayInsert(cm->unitLits, SATnot(v));
+	cls_idx = sat_AddUnitClause(cm, clauseArray);
+	if(pism->cm->option->coreGeneration){
+	  v = SATnormalNode(v);
+	  st_insert(pism->cm->anteTable,(char *)(long)v,(char *)(long)cls_idx);
+	}
+      }
+      else{
+	cls_idx = sat_AddClause(cm, clauseArray);
+      }
+      cm->initNumClauses++;
+      cm->initNumLiterals += clauseArray->num;
+      if(i>pism->propertyPos)
+	SATflags(cls_idx) |= ObjMask;
+      clauseArray->num = 0;
+    }
+  }
+  sat_ArrayFree(clauseArray);
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Get immediate latch supports for latches in latchNameArray]
+
+  Description [Get immediate latch supports for latches in latchNameArray]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+array_t * PureSatGetImmediateSupportLatches(
+  Ntk_Network_t *network,
+  int            beginPosition,
+  array_t       *latchNameArray)
+{
+  /* old support, form 0 to 'beginPosition'-1*/
+  array_t    *dataInputs, *supports;
+  /* new support, from 'beginPosition' to array_n(latchNameArray)-1*/
+  array_t    *dataInputs2, *supports2, *supportLatches2;
+  /* The result should be {new support}-{old support}*/
+  st_table   *oldSupportTable;
+  Ntk_Node_t *latch, *dataInput;
+  int        i;
+  char       *latchName;
+
+  dataInputs = array_alloc(Ntk_Node_t *, 0);
+  dataInputs2 = array_alloc(Ntk_Node_t *, 0);
+  arrayForEachItem(char *, latchNameArray, i, latchName) {
+    latch = Ntk_NetworkFindNodeByName(network, latchName);
+    assert(latch);
+    assert(Ntk_NodeTestIsLatch(latch));
+    dataInput = Ntk_LatchReadDataInput(latch);
+    if (i < beginPosition)
+      array_insert_last(Ntk_Node_t *, dataInputs, dataInput);
+    else
+      array_insert_last(Ntk_Node_t *, dataInputs2, dataInput);
+  }
+
+  supports = Ntk_NodeComputeCombinationalSupport(network, dataInputs, 1);
+  supports2 = Ntk_NodeComputeCombinationalSupport(network, dataInputs2, 1);
+  array_free(dataInputs);
+  array_free(dataInputs2);
+
+  oldSupportTable = st_init_table(st_ptrcmp, st_ptrhash);
+  arrayForEachItem(Ntk_Node_t *, supports, i, latch) {
+    st_insert(oldSupportTable, latch, NIL(char));
+  }
+  array_free(supports);
+
+  supportLatches2 = array_alloc(char *, 0);
+  arrayForEachItem(Ntk_Node_t *,  supports2, i, latch) {
+    if (Ntk_NodeTestIsLatch(latch) &&
+	!st_is_member(oldSupportTable,latch))
+      array_insert_last(char *, supportLatches2, Ntk_NodeReadName(latch));
+  }
+  array_free(supports2);
+
+  arrayForEachItem(char *, latchNameArray, i, latchName) {
+    if (i < beginPosition) continue;
+    latch = Ntk_NetworkFindNodeByName(network, latchName);
+    if (!st_is_member(oldSupportTable, latch))
+      array_insert_last(char *, supportLatches2, latchName);
+  }
+  st_free_table(oldSupportTable);
+
+  return supportLatches2;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Dump out clauses to a file]
+
+  Description [Dump out clauses to a file]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void PureSatWriteClausesToFile(PureSat_IncreSATManager_t * pism,
+			       mAig_Manager_t  *maigManager,
+			       char *coreFile)
+{
+
+  BmcCnfClauses_t *cnfClauses = pism->cnfClauses;
+  st_generator *stGen;
+  char         *name;
+  int          cnfIndex, i, k;
+  FILE *cnfFile;
+
+  coreFile = BmcCreateTmpFile();
+  cnfFile = fopen(coreFile,"w");
+
+  fprintf(vis_stdout, "coreFile is %s\n", coreFile);
+  fprintf(vis_stdout,
+	  "Number of Variables = %d Number of Clauses = %d\n",
+	  cnfClauses->cnfGlobalIndex-1,  cnfClauses->noOfClauses);
+
+
+  st_foreach_item_int(cnfClauses->cnfIndexTable, stGen, &name, &cnfIndex) {
+    fprintf(cnfFile, "c %s %d\n",name, cnfIndex);
+  }
+  (void) fprintf(cnfFile, "p cnf %d %d\n", cnfClauses->cnfGlobalIndex-1,
+		 cnfClauses->noOfClauses);
+  if (cnfClauses->clauseArray != NIL(array_t)) {
+    for (i = 0; i < cnfClauses->nextIndex; i++) {
+      k = array_fetch(int, cnfClauses->clauseArray, i);
+      (void) fprintf(cnfFile, "%d%c", k, (k == 0) ? '\n' : ' ');
+    }
+  }
+  fclose(cnfFile);
+  FREE(coreFile);
+  return;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Dump out all the clauses, including conflict clauses, to a file]
+
+  Description [Dump out all the clauses, including conflict clauses, to a file]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSatWriteAllClausesToFile(PureSat_IncreSATManager_t * pism,
+				  char *coreFile)
+{
+  satManager_t *cm = pism->cm;
+  char *tmpallcnfFile = BmcCreateTmpFile();
+  FILE *fp1 = fopen(coreFile,"r");
+  FILE *fp2 = fopen(tmpallcnfFile,"w");
+  char buffer[1024], buffer1[1024];
+  long *space;
+  int i, numOfConCls=0, numOfVar, sign,var;
+  satArray_t *saved = cm->savedConflictClauses;
+
+  for(i=0, space=saved->space; i<saved->num; i++,space++){
+    if(*space<0)
+      numOfConCls++;
+  }
+  if(numOfConCls%2!=0){
+    fprintf(vis_stdout,"should be times of 2\n");
+    exit(0);
+  }
+  numOfConCls/=2;
+
+  numOfConCls += cm->initNumClauses;
+  numOfVar = cm->initNumVariables;
+  i=0;
+  /*sprintf(buffer,"p cnf %d %d 0\n", numOfConCls, numOfVar);
+    fputs(buffer, fp2);*/
+  while(fgets(buffer,1024,fp1)){
+    if(strncmp(buffer,"c ",2)!=0){
+      if(strncmp(buffer,"p cnf ",6)==0){
+	sprintf(buffer1,"p cnf %d %d 0\n", numOfVar, numOfConCls);
+	fputs(buffer1, fp2);
+      }
+      else
+	fputs(buffer, fp2);
+    }
+  }
+
+  saved = cm->savedConflictClauses;
+
+  for(i=0, space=saved->space; i<saved->num; i++){
+    if(*space<0){
+      space++;
+      i++;
+      while(*space>0){
+	sign = !SATisInverted(*space);
+	var = SATnormalNode(*space);
+	if(sign == 0)
+	  var = -var;
+	fprintf(fp2,"%d ",var);
+	space++;
+	i++;
+      }
+      fprintf(fp2,"0\n");
+      space++;
+      i++;
+    }
+  }
+  fclose(fp1);
+  fclose(fp2);
+  FREE(tmpallcnfFile);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generate refinement latches from UNSAT proof]
+
+  Description [Generate refinement latches from UNSAT proof]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+array_t * PureSatGetLatchFromTable(Ntk_Network_t *network,
+				  PureSat_Manager_t * pm,
+				  char *coreFile)
+{
+  FILE *fp;
+  char buffer[1024],*nodeName;
+  int idx;
+  st_table * localTable = st_init_table(strcmp,st_strhash);
+  array_t * refinement = array_alloc(char *,0);
+  st_table *ClsidxToLatchTable = pm->ClsidxToLatchTable;
+  st_table *vertexTable = pm->vertexTable;
+
+  fp = fopen(coreFile,"r");
+  while(fgets(buffer,1024,fp)){
+    if(strncmp(buffer,"#clause index:",14)==0){
+      sscanf(buffer,"#clause index:%d\n",&idx);
+      if(st_lookup(ClsidxToLatchTable,(char *)(long)idx,&nodeName))
+	if(!st_lookup(vertexTable,nodeName,NIL(char *))&&!st_lookup(localTable,nodeName,NIL(char *)))
+	  {
+	    st_insert(localTable,nodeName,(char *)0);
+	    array_insert_last(char *,refinement,nodeName);
+	  }
+    }
+  }
+  st_free_table(localTable);
+  return refinement;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [remove the ith member of a certain array]
+
+  Description [remove the ith member of a certain array]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+array_t * PureSatRemove_char(array_t * array1, int i)
+{
+  int j;
+  char * str;
+  array_t * array2=array_alloc(char *,0);
+  assert(i<array_n(array1));
+  arrayForEachItem(char *,array1,j,str)
+    {
+      if(j!=i)
+	{
+
+	  array_insert_last(char *,array2,str);
+	}
+    }
+      return array2;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [For one node: count number of gates and how many of them are already in abstraction]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSatComputeNumGatesInAbsForNode(Ntk_Network_t * network,
+					PureSat_Manager_t * pm,
+					Ntk_Node_t * node,
+					st_table * visited,
+					int  * ct,
+					int  * ct1)
+{
+  int i;
+  Ntk_Node_t *fanin;
+
+
+  st_insert(visited,node,(char *)0);
+
+  (*ct1)++;
+  if(st_lookup(pm->AbsTable,node,NIL(char*)))
+    (*ct)++;
+
+  if(Ntk_NodeTestIsCombInput(node))
+    return;
+
+  Ntk_NodeForEachFanin(node,i,fanin){
+    if(!st_lookup(visited,(char *)fanin,NIL(char *))&&
+	!Ntk_NodeTestIsLatch(fanin))
+      PureSatComputeNumGatesInAbsForNode(network,pm,fanin,visited,ct,ct1);
+  }
+  return;
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [For nodes in one array: count number of gates and how many of
+  them are already in abstraction]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSatComputeNumGatesInAbs(Ntk_Network_t *network,
+				PureSat_Manager_t *pm,
+				array_t * invisibleArray)
+{
+  int i,ct,ct1,j;
+  char * name;
+  Ntk_Node_t * node,*fanin;
+  st_table * visited;
+
+
+  arrayForEachItem(char*,invisibleArray,i,name){
+    node = Ntk_NetworkFindNodeByName(network,name);
+    ct = 0;
+    ct1 = 0;
+    visited = st_init_table(st_ptrcmp,st_ptrhash);
+    st_insert(visited,node,(char *)0);
+
+    ct1++;
+
+    Ntk_NodeForEachFanin(node,j,fanin){
+      if(!st_lookup(visited,(char *)fanin,NIL(char *))&&
+	 !Ntk_NodeTestIsLatch(fanin))
+	PureSatComputeNumGatesInAbsForNode(network,pm,
+				      fanin,visited,&ct,&ct1);
+    }
+    st_insert(pm->niaTable,name,(char*)(long)ct);
+
+    st_free_table(visited);
+  }
+  return;
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [For one node: count how many nodes are in its cone]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSatComputeNumGatesInConeForNode(Ntk_Network_t * network,
+				       PureSat_Manager_t * pm,
+				       Ntk_Node_t * node,
+				       st_table * visited,
+				       int  * ct)
+{
+  int i;
+  Ntk_Node_t *fanin;
+
+
+  st_insert(visited,node,(char *)0);
+
+  (*ct)++;
+
+  if(Ntk_NodeTestIsCombInput(node))
+    return;
+
+  Ntk_NodeForEachFanin(node,i,fanin){
+    if(!st_lookup(visited,(char *)fanin,NIL(char *))&&
+       !Ntk_NodeTestIsLatch(fanin))
+      PureSatComputeNumGatesInConeForNode(network,pm,fanin,visited,ct);
+  }
+  return;
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [For each node in one array: count how many nodes are in its cone]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void PureSatComputeNumGatesInCone(Ntk_Network_t *network,
+				PureSat_Manager_t *pm,
+				array_t * latchArray)
+{
+  int i,ct,j;
+  char * name;
+  Ntk_Node_t * node,* fanin;
+  st_table * visited;
+
+
+  arrayForEachItem(char*,latchArray,i,name){
+    node = Ntk_NetworkFindNodeByName(network,name);
+    ct = 0;
+    visited = st_init_table(st_ptrcmp,st_ptrhash);
+    st_insert(visited,node,(char *)0);
+    ct++;
+
+    Ntk_NodeForEachFanin(node,j,fanin){
+      if(!st_lookup(visited,(char *)fanin,NIL(char *))&&
+	 !Ntk_NodeTestIsLatch(fanin))
+	PureSatComputeNumGatesInConeForNode(network,pm
+					    ,fanin,visited,&ct);
+    }
+    st_insert(pm->nicTable,name,(char*)(long)ct);
+
+    st_free_table(visited);
+  }
+  return;
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generate latch candidate array based on BFS ring and RC information]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+array_t * PureSatGenerateRCArray_2(Ntk_Network_t *network,
+				   PureSat_Manager_t *pm,
+				   array_t *invisibleArray,
+				   int *NumInSecondLevel)
+{
+  array_t * tmpRCArray = array_alloc(double,0);
+  array_t * tmpDfsArray = array_alloc(int,0);
+  array_t * arrayRC = array_alloc(char*,array_n(invisibleArray));
+  int i,j;
+  char * name;
+
+  if(pm->RefPredict)
+    pm->latchArray = array_alloc(char *,0);
+
+  PureSatComputeNumGatesInAbs(network,pm,invisibleArray);
+
+  for(i=0;i<array_n(invisibleArray);i++){
+    int nic,nia,dfs;
+    Ntk_Node_t *tmpnode;
+    int retVal;
+    name = array_fetch(char *,invisibleArray,i);
+    tmpnode = Ntk_NetworkFindNodeByName(network,name);
+    retVal = st_lookup(pm->node2dfsTable,name,&dfs);
+    assert(retVal);
+    array_insert_last(int,tmpDfsArray,dfs);
+    retVal = st_lookup(pm->nicTable,name,&nic);
+    assert(retVal);
+    retVal = st_lookup(pm->niaTable,name,&nia);
+    assert(retVal);
+    array_insert_last(double,tmpRCArray,
+		      (double)nia/(double)nic);
+  }
+
+
+  DfsArray = tmpDfsArray;
+  RCArray = tmpRCArray;
+  *NumInSecondLevel = 0;
+
+   {
+     int tmpvalue;
+     double rcvalue;
+     int nn = array_n(invisibleArray);
+     int *tay=ALLOC(int,nn);
+     for(j=0;j<nn;j++)
+       tay[j]=j;
+     qsort((void *)tay, nn, sizeof(int),
+	   (int (*)(const void *, const void *))NumInConeCompare_Ring);
+     for(i=0;i<nn;i++)
+       {
+	 name = array_fetch(char *,invisibleArray,tay[i]);
+	 array_insert(char *,arrayRC,i,name);
+	 tmpvalue = array_fetch(int,tmpDfsArray,tay[i]);
+	 if(tmpvalue == 2)
+	   (*NumInSecondLevel)++;
+	 rcvalue = array_fetch(double,tmpRCArray,tay[i]);
+	 if(pm->verbosity>=1)
+	   fprintf(vis_stdout,"arrayRC %s: %f-%f = %f\n",name,
+		   (double)tmpvalue*1000000,rcvalue,(double)tmpvalue*1000000-rcvalue);
+
+	 if(pm->RefPredict){
+	   if(rcvalue>=0.87&&tmpvalue==2){
+	     array_insert_last(char*,pm->latchArray,name);
+	     if(pm->verbosity>=1)
+	       fprintf(vis_stdout,"add %s into pm->latchArray\n",name);
+	   }
+	 }
+
+       }
+     FREE(tay);
+   }
+
+   array_free(DfsArray);
+   array_free(RCArray);
+
+   return arrayRC;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
Index: vis_dev/vis-2.3/src/res/res.c
===================================================================
--- vis_dev/vis-2.3/src/res/res.c	(revision 14)
+++ vis_dev/vis-2.3/src/res/res.c	(revision 14)
@@ -0,0 +1,2114 @@
+/**CFile***********************************************************************
+
+  FileName    [res.c]
+
+  PackageName [res]
+
+  Synopsis    [ The main file that incorporates procedures for residue
+		verification.]
+
+  Author      [ Kavita Ravi    <ravi@boulder.colorado.edu>,
+		Abelardo Pardo <abel@boulder.colorado.edu>]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "resInt.h"
+
+static char rcsid[] UNUSED = "$Id: res.c,v 1.55 2009/04/11 21:31:29 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+#define RES_VERIFY_NOTHING 0
+#define RES_VERIFY_DONE 1
+#define RES_VERIFY_IGNORE_PREV_RESULTS 2
+#define LOG2_FIRST_PRIME 8
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+static int PrimePool [] = { 5,   7,  9, 11, 13, 17,  19,  23,  29,
+			    31,  37,  41,  43,  47,  53,  59,  61,  67,  71,
+			    73,  79,  83,  89,  97, 101, 103, 107, 109, 113,
+			    127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
+			    179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
+			    233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
+			    283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
+			    353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
+			    419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
+			    467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
+			    547};
+static int PrimePoolSize = 100;    /* Number of elements of the array above */
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int ChoosePrimes(int numOutputs, int **pool, int numDirectVerify);
+static int ComputeMaxNumberOfOutputs(void);
+static void RestoreOldMddIds(Ntk_Network_t *network, st_table *table);
+static st_table * GeneratePointerMatchTableFromNameMatch(Ntk_Network_t *specNetwork, Ntk_Network_t *implNetwork, st_table *nameMatchTable);
+static st_table * GenerateDirectVerifyPointerTable(Ntk_Network_t *specNetwork, Ntk_Network_t *implNetwork, st_table *outputMatch, array_t *outputOrderArray, int numDirectVerify);
+static st_table * GenerateIdentityMatchTable(Ntk_Network_t *specNetwork, Ntk_Network_t *implNetwork, int inputOrOutput);
+static bdd_manager * Initializebdd_manager(Ntk_Network_t *specNetwork, Ntk_Network_t *implNetwork, int *initManagerHere);
+static int SetBasicResultInfo(Ntk_Network_t *specNetwork, Ntk_Network_t *implNetwork, int numDirectVerify);
+static void Cleanup(int error, Ntk_Network_t *specNetwork, Ntk_Network_t *implNetwork, int initManagerHere, int done, st_table *outputMatch, st_table *inputMatch, st_table *directVerifyMatch, st_table *oldSpecMddIdTable, st_table *oldImplMddIdTable, array_t *specLayerArray, array_t *implLayerArray);
+static st_table * SaveOldMddIds(Ntk_Network_t *network);
+static int DirectVerification(Ntk_Network_t *specNetwork, Ntk_Network_t *implNetwork, st_table *directVerifyMatch, st_table *inputMatch, st_table *outputMatch, array_t *outputOrderArray);
+static bdd_reorder_type_t DecodeDynMethod(char *dynMethodString);
+static int ResidueVerification(Ntk_Network_t *specNetwork, Ntk_Network_t *implNetwork, st_table *outputMatch, st_table *inputMatch, int numDirectVerify, array_t *specLayerArray, array_t *implLayerArray, array_t *outputArray);
+static void ExtractACubeOfDifference(bdd_manager *mgr, Ntk_Network_t *specNetwork, bdd_node *fn1, bdd_node *fn2);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis	[Performs direct and residue verification of a given network.]
+
+  Description	[ Performs direct and residue verification of a given network.
+  This function is the core routine for residue verification. The network
+  parameters are in a specific order: SPECIFICATION first, IMPLEMENTATION
+  second. The two networks are differentiated because the specification is the
+  only circuit which may store  previously computed results. Also all other
+  parameters are with reference to the specification. The next parameter is
+  the number  of outputs to directly verify.
+  The output order array gives the order of the outputs,
+  starting from the MSB. The output and input match table contain name matches
+  for the output and input. The key in this table belongs to the specification
+  and the value to the implementation. The procedure initializes  the manager,
+  computes maximum number of outputs that can be verified, sets basic result
+  information. It also sets up the match tables with pointers and saves the
+  old MDD Ids in a table. It then calls the direct verification procedure, if
+  there are any outputs to be verified. For residue verification, the procedure
+  calls the layering procedure on both networks and creates layers. It calls
+  the main residue verification procedure and updates the result structures.
+  Returns the value 0 on success. The procedure takes in as arguments the
+  specification network, the implementation network in that order, the number
+  of outputs that need to be directly verified, the order of all the outputs,
+  the table with outputs name matches of the spec. and the impl. and a similar
+  input name match table.]
+
+  SideEffects        [The residue Info structure gets updated.]
+
+******************************************************************************/
+int
+Res_NetworkResidueVerify(
+	 Ntk_Network_t *specNetwork,
+	 Ntk_Network_t *implNetwork,
+	 int numDirectVerify,
+	 array_t *outputOrderArray,
+	 st_table *outputNameMatch,
+	 st_table *inputNameMatch)
+{
+  Ntk_Node_t *nodePtr;           /* To iterate over nodes */
+  Ntk_Node_t *implNodePtr;       /* To iterate over nodes */
+  Res_ResidueInfo_t *resultSpec; /* Structure holding all the info */
+  Res_ResidueInfo_t *resultImpl; /* Structure holding all the info */
+  array_t *specLayerArray;       /* array containing the reverse
+				  * topological layers of the spec.
+				  */
+  array_t *implLayerArray;       /* array containing the reverse
+				  * topological layers of the impl.
+				  */
+  st_table *oldSpecMddIdTable;   /* Tables to store MDD IDs of the spec
+				  * if already assigned
+				  */
+  st_table *oldImplMddIdTable;   /* Tables to store MDD IDs of the impl.
+				  * if already assigned
+				  */
+
+  st_table *outputMatch;         /* Output match table with node
+				  * pointers, spec node pointer is
+				  * the key
+				  */
+  st_table *inputMatch;          /* Input match table with node
+				  * pointers, spec node pointer is
+				  * the key
+				  */
+
+  bdd_manager *ddManager;          /* Manager read from the network */
+  int initManagerHere;           /* Flag to indicate the network Mdd
+				  * managers initialized here
+				  */
+
+  lsGen listGen;                 /* To iterate over outputList */
+  long overallLap;               /* To measure overall execution time */
+  int maxNumberOfOutputs;        /* max number of outputs that can be
+				  * verified here
+				  * = product(100 primes)
+				  */
+  int numOutputs;                /* Store the number of outputs in spec.,
+				  * impl
+				  */
+  int done;                      /* flag to determine the status of
+				  * previous verification
+				  */
+  int error;                     /* error flag, set for cleanup, 1 failed,
+				  * 0 if successful
+				  */
+  int status;                    /* error status of residue verification */
+  int directVerifyStatus;        /* direct verification status, 1 if failed,
+				  * 0 if successful
+				  */
+  st_table *directVerifyMatch;   /* match table with pointers for the
+				  * directly verified outputs, spec pointer
+				  * is key
+				  */
+  char *name;                    /* variable to store name of node */
+  array_t *outputArray;          /* array to store output nodes */
+  array_t *ignoreOutputArray;    /* array to store outputs nodes to be
+				  * ignored
+				  */
+  int verbose;                   /* variable to read residue_verbosity value */
+  char *flagValue;               /* string to read flag values */
+  int i;                         /* Loop iterators */
+  int unassignedValue;           /* NTK_UNASSIGNED_MDD_ID value holder */
+
+  /* Initialize some variables to default values */
+
+  overallLap = 0;
+  initManagerHere = 0;
+  ddManager = NIL(bdd_manager);
+  done = RES_VERIFY_NOTHING;
+  error = 0;
+  status = 1;
+  verbose = 0;
+
+  unassignedValue =  NTK_UNASSIGNED_MDD_ID;
+  directVerifyStatus = 1;
+  directVerifyMatch = NIL(st_table);
+  specLayerArray = NIL(array_t);
+  implLayerArray = NIL(array_t);
+  outputArray = NIL(array_t);
+  ignoreOutputArray = NIL(array_t);
+  outputMatch = NIL(st_table);
+  inputMatch = NIL(st_table);
+  oldSpecMddIdTable = NIL(st_table);
+  oldImplMddIdTable = NIL(st_table);
+  resultSpec = NIL(Res_ResidueInfo_t);
+  resultImpl = NIL(Res_ResidueInfo_t);
+
+
+  /* Initialize global time values*/
+  Res_composeTime = 0;
+  Res_smartVarTime = 0;
+  Res_shuffleTime = 0;
+  Res_orderTime = 0;
+
+
+  /* Read verbosity value */
+  flagValue = Cmd_FlagReadByName("residue_verbosity");
+  if (flagValue != NIL(char)) {
+    verbose = atoi(flagValue);
+  }
+
+  /* Read the mdd Manager (or create it if necessary) */
+  ddManager = Initializebdd_manager(specNetwork, implNetwork, &initManagerHere);
+  if (ddManager == NIL(bdd_manager)) {
+    /* error, but nothing allocated, so no cleanup */
+    return 1;
+  }
+
+  /* Set up the correct maximum number of outputs */
+  maxNumberOfOutputs  = ComputeMaxNumberOfOutputs();
+  if (verbose >= 2) {
+    fprintf(vis_stdout, "The Maximum Number of outputs that can be");
+    fprintf(vis_stdout, " verified are %d.\n", maxNumberOfOutputs);
+  }
+
+  /* check number of outputs */
+  numOutputs = Ntk_NetworkReadNumCombOutputs(specNetwork);
+  /* Check if the circuit has too many outputs */
+  if (numOutputs >= maxNumberOfOutputs) {
+    error_append("Circuit with too many outputs.\n");
+    /* Clean up before you leave */
+    error = 1;
+    Cleanup(error, specNetwork, implNetwork, initManagerHere, done,
+	    outputMatch, inputMatch, directVerifyMatch, oldSpecMddIdTable,
+	    oldImplMddIdTable, specLayerArray, implLayerArray);
+    return 1;
+  } /* End of if */
+
+  /* Create result data structure for both the spec and the implementation */
+  done = SetBasicResultInfo(specNetwork, implNetwork, numDirectVerify);
+  if (done ==  RES_VERIFY_DONE) {/* same verification as previous time */
+    /* Clean up before you leave */
+    fprintf(vis_stdout, "Verification has been previously performed\n");
+    error = 0;
+    Cleanup(error, specNetwork, implNetwork, initManagerHere, done,
+	    outputMatch, inputMatch, directVerifyMatch, oldSpecMddIdTable,
+	    oldImplMddIdTable, specLayerArray, implLayerArray);
+    return 0; /* success */
+  } /* end of case RES_VERIFY_DONE */
+
+  /* if output match table does not exist, create one with matching names
+   * in the two networks. Insert with spec network node pointer as key
+   * in the outputMatch table. If match table does exist, convert name table
+   * to pointer table.
+   */
+  if(outputNameMatch == NIL(st_table)) {
+    outputMatch = GenerateIdentityMatchTable(specNetwork, implNetwork, PRIMARY_OUTPUTS);
+  } else {
+    outputMatch = GeneratePointerMatchTableFromNameMatch(specNetwork,
+							 implNetwork,outputNameMatch);
+    if (outputMatch == NIL(st_table)) {
+      error_append("Output pointer table is NULL\n");
+      /* Clean up before you leave */
+      error = 1;
+      Cleanup(error, specNetwork, implNetwork, initManagerHere, done,
+	      outputMatch, inputMatch, directVerifyMatch, oldSpecMddIdTable,
+	      oldImplMddIdTable, specLayerArray, implLayerArray);
+      return 1; /* error return */
+    }
+  }
+
+  /* if input match table does not exist, create one with matching names
+   * in the two networks. Insert with spec network node pointer as key
+   * in the inputMatch table. If match table does exist, convert name table
+   * to pointer table.
+   */
+  if(inputNameMatch == NIL(st_table)) {
+    inputMatch = GenerateIdentityMatchTable(specNetwork, implNetwork, PRIMARY_INPUTS);
+  } else {
+    inputMatch = GeneratePointerMatchTableFromNameMatch(specNetwork,
+							implNetwork,inputNameMatch);
+    if (inputMatch == NIL(st_table)) {
+      error_append("Input pointer table is NULL\n");
+      /* Clean up before you leave */
+      error = 1;
+      Cleanup(error, specNetwork, implNetwork, initManagerHere, done,
+	      outputMatch, inputMatch, directVerifyMatch, oldSpecMddIdTable,
+	      oldImplMddIdTable, specLayerArray, implLayerArray);
+      return 1; /* error return */
+    }
+  }
+
+  /* Save the old MDD IDs in a st_table */
+  oldSpecMddIdTable = SaveOldMddIds(specNetwork);
+  if (oldSpecMddIdTable == NIL(st_table)) {
+    error_append("Unable to save old Mdd Ids for spec\n");
+    /* Clean up before you leave */
+    error = 1;
+    Cleanup(error, specNetwork, implNetwork, initManagerHere, done,
+	    outputMatch, inputMatch, directVerifyMatch, oldSpecMddIdTable,
+	    oldImplMddIdTable, specLayerArray, implLayerArray);
+    return 1;
+  }
+
+  /* Save the old MDD IDs in a st_table */
+  oldImplMddIdTable = SaveOldMddIds(implNetwork);
+  if (oldImplMddIdTable == NIL(st_table)) {
+    error_append("Unable to save old Mdd Ids for impl\n");
+    /* Clean up before you leave */
+    error = 1;
+    Cleanup(error, specNetwork, implNetwork, initManagerHere, done,
+	    outputMatch, inputMatch, directVerifyMatch, oldSpecMddIdTable,
+	    oldImplMddIdTable, specLayerArray, implLayerArray);
+    return 1;
+  }
+
+  /* Initialize time to measure overall lap time */
+  overallLap = util_cpu_time();
+
+  /* Perform direct verification of the given outputs. */
+  if (numDirectVerify) {
+    /* generate output match table for outputs to be directly verified */
+    directVerifyMatch = GenerateDirectVerifyPointerTable(specNetwork,
+	 implNetwork, outputMatch, outputOrderArray, numDirectVerify);
+    if (directVerifyMatch == NIL(st_table)) {
+      error_append("Directly verify  pointer table is NULL\n");
+      /* Clean up before you leave */
+      error = 1;
+      Cleanup(error, specNetwork, implNetwork, initManagerHere, done,
+	      outputMatch, inputMatch, directVerifyMatch, oldSpecMddIdTable,
+	      oldImplMddIdTable, specLayerArray, implLayerArray);
+      return 1; /* error return */
+    }
+
+    /* perform direct verification of the outputs in the match table */
+    directVerifyStatus = DirectVerification(specNetwork, implNetwork,
+		    directVerifyMatch, inputMatch, outputMatch, outputOrderArray);
+    /* Direct verification error */
+    if (directVerifyStatus == 1) {
+      error_append("Direct Verification error\n");
+      /* Clean up before you leave */
+      error = 1;
+      Cleanup(error, specNetwork, implNetwork, initManagerHere, done,
+      outputMatch, inputMatch, directVerifyMatch, oldSpecMddIdTable,
+	      oldImplMddIdTable, specLayerArray, implLayerArray);
+      return 1; /* error return */
+    }
+
+    resultSpec = (Res_ResidueInfo_t *)Ntk_NetworkReadApplInfo(specNetwork,
+					    RES_NETWORK_APPL_KEY);
+    resultImpl = (Res_ResidueInfo_t *)Ntk_NetworkReadApplInfo(implNetwork,
+					    RES_NETWORK_APPL_KEY);
+    /* Direct verification failed */
+    if ((ResResidueInfoReadDirectVerificationSuccess(resultSpec) == RES_FAIL) &&
+	(ResResidueInfoReadDirectVerificationSuccess(resultImpl) == RES_FAIL)) {
+      ResResidueInfoSetSuccess(resultSpec, RES_FAIL);
+      ResResidueInfoSetSuccess(resultImpl, RES_FAIL);
+      /*  Clean up before you leave */
+      error = 0;
+      Cleanup(error, specNetwork, implNetwork, initManagerHere, done,
+      outputMatch, inputMatch, directVerifyMatch, oldSpecMddIdTable,
+	      oldImplMddIdTable, specLayerArray, implLayerArray);
+      return 0;
+    } else if (numDirectVerify == numOutputs) {
+      if ((ResResidueInfoReadDirectVerificationSuccess(resultSpec) == RES_PASS) &&
+	  (ResResidueInfoReadDirectVerificationSuccess(resultImpl) == RES_PASS)) {
+	/* if all outputs are directly verified */
+	ResResidueInfoSetSuccess(resultSpec, RES_PASS);
+	ResResidueInfoSetSuccess(resultImpl, RES_PASS);
+      }
+    } /* end of else */
+
+
+  } /* Direct Verification, done and successful */
+
+  (void) fprintf(vis_stdout, "Total Direct Verification Time = %.3f (secs).\n",
+		 (util_cpu_time() - overallLap)/1000.0);
+
+  if (verbose >= 1) {
+    util_print_cpu_stats(vis_stdout);
+  }
+
+
+  /* RESIDUE VERIFICATION starts here */
+
+  if (numOutputs - numDirectVerify) { /* if residue verification required */
+    /* reset all Ids after direct verification as residue verification
+     * assigns new Ids.
+     */
+    Ntk_NetworkForEachNode(specNetwork, listGen, nodePtr) {
+      Ntk_NodeSetMddId(nodePtr, unassignedValue);
+    }
+    Ntk_NetworkForEachNode(implNetwork, listGen, nodePtr) {
+      Ntk_NodeSetMddId(nodePtr, unassignedValue);
+    }
+
+    /* check if directly verified outputs are to be involved in residue
+     * verification
+     */
+    flagValue = Cmd_FlagReadByName("residue_ignore_direct_verified_outputs");
+    if (flagValue != NIL(char)) {
+      if ((strcmp(flagValue, "1") == 0) && (numDirectVerify)) {
+	ignoreOutputArray = array_alloc(Ntk_Node_t *, numDirectVerify);
+      }
+    }
+    if (ignoreOutputArray == NIL(array_t)) {
+      /* fill the output array with all output nodes */
+      outputArray = array_alloc(Ntk_Node_t *, array_n(outputOrderArray));
+      arrayForEachItem(char *, outputOrderArray, i, name) {
+	nodePtr = Ntk_NetworkFindNodeByName(specNetwork, name);
+	st_lookup(outputMatch, (char *)nodePtr, &implNodePtr);
+	array_insert(Ntk_Node_t *, outputArray, i, implNodePtr);
+      }
+    } else {
+      outputArray = array_alloc(Ntk_Node_t *, array_n(outputOrderArray)-numDirectVerify);
+      /* fill the output array with nodes not directly verified */
+      for (i = 0; i < (array_n(outputOrderArray) - numDirectVerify); i++) {
+	name = array_fetch(char *, outputOrderArray, i);
+	nodePtr = Ntk_NetworkFindNodeByName(specNetwork, name);
+	st_lookup(outputMatch, (char *)nodePtr, &implNodePtr);
+	array_insert(Ntk_Node_t *, outputArray, i, implNodePtr);
+      }
+      /* fill ignore array with outputs directly verified. */
+      for (i = (array_n(outputOrderArray) - numDirectVerify); i < array_n(outputOrderArray); i++) {
+	name = array_fetch(char *, outputOrderArray, i);
+	nodePtr = Ntk_NetworkFindNodeByName(specNetwork, name);
+	st_lookup(outputMatch, (char *)nodePtr, &implNodePtr);
+	array_insert(Ntk_Node_t *, ignoreOutputArray, (i-array_n(outputOrderArray)+numDirectVerify) , implNodePtr);
+      }
+    }
+
+
+    /* Compute the layers to be used for function composition */
+    implLayerArray = ResComputeCompositionLayers(implNetwork, outputArray, ignoreOutputArray);
+
+    /* create the output array for the spec. */
+    if (ignoreOutputArray == NIL(array_t)) {
+      /* fill the output array with all output nodes */
+      arrayForEachItem(char *, outputOrderArray, i, name) {
+	nodePtr = Ntk_NetworkFindNodeByName(specNetwork, name);
+	array_insert(Ntk_Node_t *, outputArray, i, nodePtr);
+      }
+    } else {
+      /* fill the output array with nodes not directly verified */
+      for (i = 0; i < (array_n(outputOrderArray) - numDirectVerify); i++) {
+	name = array_fetch(char *, outputOrderArray, i);
+	nodePtr = Ntk_NetworkFindNodeByName(specNetwork, name);
+	array_insert(Ntk_Node_t *, outputArray, i, nodePtr);
+      }
+      /* fill ignore array with outputs directly verified. */
+      for (i = (array_n(outputOrderArray) - numDirectVerify); i < array_n(outputOrderArray); i++) {
+	name = array_fetch(char *, outputOrderArray, i);
+	nodePtr = Ntk_NetworkFindNodeByName(specNetwork, name);
+	array_insert(Ntk_Node_t *, ignoreOutputArray, (i-array_n(outputOrderArray)+numDirectVerify), nodePtr);
+      }
+    }
+
+    /* Compute the layers to be used for function composition */
+    specLayerArray = ResComputeCompositionLayers(specNetwork, outputArray, ignoreOutputArray);
+
+    /* print the array */
+    if (verbose >=3) {
+      ResLayerPrintInfo(specNetwork, specLayerArray);
+      ResLayerPrintInfo(implNetwork, implLayerArray);
+    }
+
+    /* free the ignore array */
+    if (ignoreOutputArray != NIL(array_t)) {
+      array_free(ignoreOutputArray);
+    }
+
+    /* Perform residue verification on the spec. and impl. */
+    status = ResidueVerification(specNetwork, implNetwork, outputMatch, inputMatch, numDirectVerify, specLayerArray, implLayerArray, outputArray);
+
+    /* free output array */
+    array_free(outputArray);
+
+    if (status) {
+      error_append("Residue Verification error\n");
+      /* Clean up before you leave */
+      error = 1;
+      Cleanup(error, specNetwork, implNetwork, initManagerHere, done,
+	      outputMatch, inputMatch, directVerifyMatch, oldSpecMddIdTable,
+	      oldImplMddIdTable, specLayerArray, implLayerArray);
+      return 1; /* error return */
+    }
+
+
+    resultSpec = (Res_ResidueInfo_t *)Ntk_NetworkReadApplInfo(specNetwork,
+					      RES_NETWORK_APPL_KEY);
+    resultImpl = (Res_ResidueInfo_t *)Ntk_NetworkReadApplInfo(implNetwork,
+					    RES_NETWORK_APPL_KEY);
+    /* Print success message and info */
+    if ((ResResidueInfoReadSuccess(resultSpec) == RES_FAIL) &&
+	(ResResidueInfoReadSuccess(resultImpl) == RES_FAIL)) {
+      /* Clean up before you leave */
+      error = 0;
+	    Cleanup(error, specNetwork, implNetwork, initManagerHere, done,
+	      outputMatch, inputMatch, directVerifyMatch, oldSpecMddIdTable,
+	      oldImplMddIdTable, specLayerArray, implLayerArray);
+      return 0;
+    }
+
+    if(verbose >= 2) {
+      (void) fprintf(vis_stdout, "Total Compose Time = %3f(secs).\n",
+		     Res_composeTime/1000.0);
+      (void) fprintf(vis_stdout, "Total Order Time = %3f(secs).\n",
+		     Res_orderTime/1000.0);
+      (void) fprintf(vis_stdout, "Total Shuffle Time = %3f(secs).\n",
+		     Res_shuffleTime/1000.0);
+
+      (void) fprintf(vis_stdout, "Total Smart Var Time = %3f(secs).\n",
+		     Res_smartVarTime/1000.0);
+    }
+
+
+  } /* end of residue verification */
+
+  /* Print success message and info */
+  if ((ResResidueInfoReadSuccess(resultSpec) == RES_PASS) &&
+      (ResResidueInfoReadSuccess(resultImpl) == RES_PASS))
+    (void) fprintf(vis_stdout, "Verification of %s and %s successful.\n",
+		   Res_ResidueInfoReadName(resultSpec),
+		   Res_ResidueInfoReadName(resultImpl));
+
+
+  if (verbose >= 1) {
+    fprintf(vis_stdout, "Specification:\n");
+    (void) Res_ResidueInfoPrint(resultSpec);
+    fprintf(vis_stdout, "Implementation:\n");
+    (void) Res_ResidueInfoPrint(resultImpl);
+  }
+  if (verbose >= 1) {
+    util_print_cpu_stats(vis_stdout);
+  }
+
+  (void) fprintf(vis_stdout, "Total Time = %.3f (secs).\n",
+		 (util_cpu_time() - overallLap)/1000.0);
+
+  /* no error */
+  error = 0;
+  Cleanup(error, specNetwork, implNetwork, initManagerHere, done,
+	  outputMatch, inputMatch, directVerifyMatch, oldSpecMddIdTable,
+	  oldImplMddIdTable, specLayerArray, implLayerArray);
+
+  /* End of clean up */
+
+  return 0;
+} /* End of Res_NetworkResidueVerify */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Chooses the primes to process a circuit with those many outputs.]
+
+  Description [Chooses the primes to process a circuit with those many
+  outputs. It returns an allocated array of primes selected from PrimePool. The
+  number of primes required should exceed the quotient from dividing 2^number
+  of outputs by 2^number of directly verified outputs. If there are no directly
+  verified outputs, the first prime chosen is 2^LOG2_FIRST_PRIME. The procedure
+  is passed the following parameters: number of outputs, the array of primes
+  (to be filled) and the number of directly verified outputs.]
+
+  SideEffects [Fills the primes array.]
+
+  See Also    [Res_NetworkResidueVerify]
+
+******************************************************************************/
+static int
+ChoosePrimes(int numOutputs,
+	     int **pool,
+	     int numDirectVerify)
+{
+  double accumulator = 0.0;
+  int i,max, index = 0;
+  double factor = log10((double)2.0);
+
+  assert(*pool == NIL(int));
+
+  if (numDirectVerify) {
+    accumulator = (double)numDirectVerify;
+  } else {
+    /* make first prime 2^LOG2_FIRST_PRIME */
+    if (numOutputs >= LOG2_FIRST_PRIME) {
+      accumulator = (double)LOG2_FIRST_PRIME;
+    } else {
+      accumulator = (double)numOutputs;
+    }
+  }
+
+  /* step through primes till their product exceeds the max value of outputs */
+  max = 0;
+  while (accumulator < ((double)numOutputs)) {
+    accumulator += log10((double)PrimePool[max])/factor;
+    max++;
+  }
+
+  index = 0;
+  /* if no direct verification, then set the first prime to be 2^LOG2_FIRST_PRIME */
+  if (!numDirectVerify) {
+    *pool = ALLOC(int, max+1);
+    if (numOutputs >= LOG2_FIRST_PRIME) {
+      (*pool)[index++] = (int)pow((double)2.0, (double)LOG2_FIRST_PRIME);
+    } else {
+      (*pool)[index++] = (int)pow((double)2.0, (double)numOutputs);
+    }
+  } else {
+    *pool = ALLOC(int, max);
+  }
+
+  /* fill the array with other primes */
+  for(i=0; i < max; i++) {
+   (*pool)[index++] = PrimePool[i];
+  }
+
+  return index;
+} /* End of ChoosePrimes */
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the maximum number of outputs a circuit may have in order
+  to be processed with the array PrimePool.]
+
+  Description [Computes the maximum number of outputs a circuit may have in
+  order to be processed with the array PrimePool. This is the product of all
+  the primes in the Prime Pool Table.]
+
+  SideEffects [Updates the static variable maxNumberOfOutputs.]
+
+  SeeAlso     [Res_NetworkResidueVerify]
+
+******************************************************************************/
+static int
+ComputeMaxNumberOfOutputs(void)
+{
+  int i;
+  double result = 0;
+  int maxNumberOfOutputs;
+
+  result = LOG2_FIRST_PRIME;
+  for(i = 0; i < PrimePoolSize; i++) {
+    result += log10((double)PrimePool[i]);
+  } /* End of for */
+
+  maxNumberOfOutputs = (int) (result/log10((double) 2.0)) - 1;
+
+  return (maxNumberOfOutputs);
+} /* End of ComputeMaxNumberOfOutputs */
+
+
+/**Function********************************************************************
+
+  Synopsis    [A procedure restore  MDD Ids from an st table.]
+
+  Description [A procedure restore MDD Ids from an st table. This is to leave
+  the network in the state it was in before residue verification was
+  called. The procedure's parameters are the network whose IDs need to be
+  restored and a table to restore from.]
+
+  SideEffects [The mdd Ids of the network change.]
+
+  SeeAlso     [Res_NetworkResidueVerify SaveOldMddIds]
+
+******************************************************************************/
+static void
+RestoreOldMddIds(Ntk_Network_t *network,
+		 st_table *table)
+{
+  lsGen listGen;
+  Ntk_Node_t *nodePtr;
+  int value;
+  if (table != NULL) {
+    Ntk_NetworkForEachNode(network, listGen, nodePtr) {
+      if(st_lookup_int(table, (char *)nodePtr, &value)) {
+	Ntk_NodeSetMddId(nodePtr, value);
+      } else {
+	error_append("Node");
+	error_append(Ntk_NetworkReadName(network));
+	error_append("should have been in the table.\n");
+	(void) lsFinish(listGen);
+      }
+    }
+  }
+} /* End of RestoreOldMddIds */
+
+
+/**Function********************************************************************
+
+  Synopsis [Procedure to generate a match Table with node pointers from a match
+  table with names.]
+
+  Description [Procedure to generate a match Table with node pointers from a
+  match table with names.The name match table will have pairs of names which
+  may be from the spec or the impl. So for each unique pair there are two
+  entries in the name match table. The pointer match table is constructed with
+  the spec. node pointer as the key. If the node pointer for a name isn't found
+  in either network, return NIL (error). The procedure takes in the parameters:
+  spec., impl and a name match table and returns a pointer match table
+  corresponding to the names.]
+
+  SideEffects   []
+
+  SeeAlso            [Res_NetworkResidueVerify]
+
+******************************************************************************/
+static st_table *
+GeneratePointerMatchTableFromNameMatch(
+		       Ntk_Network_t *specNetwork,
+		       Ntk_Network_t *implNetwork,
+		       st_table *nameMatchTable)
+{
+  st_table *pointerMatch;
+  Ntk_Node_t *nodePtr, *implNodePtr;
+  st_generator *stGen;
+  char *key, *value;
+
+  pointerMatch = st_init_table( st_ptrcmp, st_ptrhash);
+  st_foreach_item(nameMatchTable, stGen, &key, &value) {
+    /* find node in spec */
+    nodePtr = Ntk_NetworkFindNodeByName(specNetwork, key);
+    if (nodePtr == NIL(Ntk_Node_t)) {
+      /* if node not in spec, find in impl */
+      implNodePtr = Ntk_NetworkFindNodeByName(implNetwork, key);
+      nodePtr = Ntk_NetworkFindNodeByName(specNetwork, value);
+    } else {
+      implNodePtr = Ntk_NetworkFindNodeByName(implNetwork,value);
+    }
+    if ((nodePtr == NIL(Ntk_Node_t)) || (implNodePtr == NIL(Ntk_Node_t))) {
+      /* error */
+      error_append("Nodes not found by the keys in match table.\n");
+      st_free_gen(stGen);
+      return NIL(st_table);
+    }
+    st_insert(pointerMatch, (char *)nodePtr, (char *)implNodePtr);
+  } /* end of st_foreach_item */
+
+  return(pointerMatch);
+} /* End of GeneratePointerMatchTableFromNameMatch */
+
+
+/**Function********************************************************************
+
+  Synopsis [Generates a pointer match table for the directly verified outputs.]
+
+  Description [Generates a pointer match table for the directly verified
+  outputs. Returns NIL if a node isn't found, else returns the table.The
+  procedure takes as arguments the spec., the impl., the output match table
+  with pointers, the output order array and the number of directly verified
+  outputs.]
+
+  SideEffects   []
+
+  SeeAlso            [Res_NetworkResidueVerify]
+
+******************************************************************************/
+static st_table *
+GenerateDirectVerifyPointerTable(Ntk_Network_t *specNetwork,
+				 Ntk_Network_t *implNetwork,
+				 st_table *outputMatch,
+				 array_t *outputOrderArray,
+				 int numDirectVerify)
+
+{
+  char *specName;
+  int i;
+  Ntk_Node_t *nodePtr, *implNodePtr;
+  st_table *directVerifyMatch;
+
+  directVerifyMatch = st_init_table(st_ptrcmp, st_ptrhash);
+  for (i = 0; i < numDirectVerify; i++) {
+    specName = array_fetch(char *, outputOrderArray, array_n(outputOrderArray) - 1 - i);
+    nodePtr = Ntk_NetworkFindNodeByName(specNetwork, specName);
+    st_lookup(outputMatch, (char *)nodePtr, &implNodePtr);
+    if ((nodePtr == NIL(Ntk_Node_t)) || (implNodePtr == NIL(Ntk_Node_t))) {
+      error_append("Couldn't find nodes to directly verify\n");
+      st_free_table(directVerifyMatch);
+      return NIL(st_table);
+    }
+    st_insert(directVerifyMatch, (char *)nodePtr, (char *)implNodePtr);
+  }
+  return (directVerifyMatch);
+} /* End of GenerateDirectVerifyPointerTable */
+
+
+/**Function********************************************************************
+
+  Synopsis [ A procedure to generate a pointer Match table with from
+  nodes with identical names.]
+
+  Description [A procedure to generate a pointer Match table with from nodes
+  with identical names. This procedure does it for either the inputs or outputs
+  depending on the flag. Returns NULL if the impl. does not have a node
+  corresponding to the spec. The procedure takes as arguments the spec., the
+  impl. and the flag specifying whether the pointer match table is to be built
+  for the output or the input.]
+
+  SideEffects   []
+
+  SeeAlso            [Res_NetworkResidueVerify]
+
+******************************************************************************/
+static st_table *
+GenerateIdentityMatchTable(Ntk_Network_t *specNetwork,
+			   Ntk_Network_t *implNetwork,
+			   int inputOrOutput)
+{
+  Ntk_Node_t *nodePtr, *implNodePtr;
+  st_table *matchTable;
+  lsGen listGen;
+  char *name;
+
+  matchTable = st_init_table(st_ptrcmp, st_ptrhash);
+  if (matchTable == NULL) return(NIL(st_table));
+
+  if (inputOrOutput == PRIMARY_INPUTS) {
+    Ntk_NetworkForEachCombInput(specNetwork, listGen, nodePtr) {
+      name = Ntk_NodeReadName(nodePtr);
+      implNodePtr = Ntk_NetworkFindNodeByName(implNetwork, name);
+      if (implNodePtr == NIL(Ntk_Node_t)) {
+	error_append(name);
+	error_append(" node does not have corresponding node in impl.");
+	st_free_table(matchTable);
+	return (NIL(st_table));
+      }
+      st_insert(matchTable, (char *)nodePtr, (char *)implNodePtr);
+    }
+  } else if (inputOrOutput == PRIMARY_OUTPUTS) {
+    Ntk_NetworkForEachCombOutput(specNetwork, listGen, nodePtr) {
+      name = Ntk_NodeReadName(nodePtr);
+      implNodePtr = Ntk_NetworkFindNodeByName(implNetwork,name);
+      if (implNodePtr == NIL(Ntk_Node_t)) {
+	error_append(name);
+	error_append(" node does not have corresponding node in impl.");
+	st_free_table(matchTable);
+	return (NIL(st_table));
+      }
+      st_insert(matchTable, (char *)nodePtr, (char *)implNodePtr);
+    }
+  }
+  return (matchTable);
+} /* End of GenerateIdentityMatchTable */
+
+/**Function********************************************************************
+
+  Synopsis    [Initialize bdd_managers for the networks.]
+
+  Description [Initialize bdd_managers for the networks. If both managers are
+  NIL , initialize a DD Manager here and set it in both networks. If the
+  manager is not NIL, then they have to be the same. If different, keep the
+  spec network manager. Return a flag if managers are initialized here. The
+  procedure takes as arguments the spec., the impl. and the flag specifying
+  whether the the manager was initialized here (to be filled).]
+
+  SideEffects [Network manager values might change.]
+
+  SeeAlso     [Res_NetworkResidueVerify]
+
+******************************************************************************/
+static bdd_manager *
+Initializebdd_manager(Ntk_Network_t *specNetwork,
+		    Ntk_Network_t *implNetwork,
+		    int *initManagerHere)
+{
+  bdd_manager *ddManager;
+
+  /* Read the mdd Manager (or create it if necessary) */
+  ddManager = (bdd_manager *)Ntk_NetworkReadMddManager(specNetwork);
+
+  /* To set the spec manager the same as the impl. manager, either
+   * both are nil, or the impl manager is freed and set to the
+   * spec manager
+   */
+  if(ddManager != (bdd_manager *)Ntk_NetworkReadMddManager(implNetwork)) {
+    if ((bdd_manager *)Ntk_NetworkReadMddManager(implNetwork) != NIL(bdd_manager)) {
+      /* unacceptable if the impl. manager is different from NIl or
+       * from the spec manager
+       */
+      mdd_quit(Ntk_NetworkReadMddManager(implNetwork));
+    }
+    Ntk_NetworkSetMddManager(implNetwork, (mdd_manager *)ddManager);
+  }
+
+  /* if the spec. manager is NIL, then network initialize manager */
+  if (ddManager ==  NIL(bdd_manager)) {
+    /* flag to say that manager is verified here */
+    *initManagerHere = 1;
+    ddManager = (bdd_manager *)Ntk_NetworkInitializeMddManager(specNetwork);
+    Ntk_NetworkSetMddManager(implNetwork, (mdd_manager *)ddManager);
+  }
+  return (ddManager);
+} /* End of Initializebdd_manager */
+
+/**Function********************************************************************
+
+  Synopsis [Create the basic result structures for both the specification and
+  implementation.]
+
+  Description [Create the basic result structures for both the specification
+  and implementation. This procedure returns a flag that specifies if the
+  previous verification was a success. If previous information is to be used
+  only the condition that either the same spec and impl were verified before,
+  is allowed. If the previous verification had the same number of directly
+  verified outputs and the verification was a success, a success is returned.
+  The impl. result will be overwritten in any case. Returns a flag that
+  indicates if verification is to be done. The procedure records the number of
+  outputs, inputs, directly verified outputs, spec and impl name. Adds the
+  result structure as a hook to the network. The procedure takes as arguments
+  the spec., the impl. and the number of directly verified outputs.]
+
+  SideEffects [Changes the result structure in the 2 networks.]
+
+  SeeAlso [Res_NetworkResidueVerify]
+
+******************************************************************************/
+static int
+SetBasicResultInfo (Ntk_Network_t *specNetwork,
+		    Ntk_Network_t *implNetwork,
+		    int numDirectVerify)
+{
+  int numInputs;
+  int numOutputs;
+  char *specName;
+  char *implName;
+  Res_ResidueInfo_t *resultSpec;
+  Res_ResidueInfo_t *resultImpl;
+
+  /* if previous verification to be considered, make sure the
+   *  verification was with the same spec network and the number
+   *  of directly verified outputs are the same.
+   */
+  resultSpec = (Res_ResidueInfo_t *)Ntk_NetworkReadApplInfo(specNetwork,
+						    RES_NETWORK_APPL_KEY);
+
+  if (resultSpec != NIL(Res_ResidueInfo_t)) {
+    if ((strcmp(ResResidueInfoReadNameVerifiedAgainst(resultSpec),
+	      Ntk_NetworkReadName(implNetwork)) == 0) &&
+	(ResResidueInfoReadNumDirectVerifiedOutputs(resultSpec) ==
+						 numDirectVerify) &&
+	(ResResidueInfoReadSuccess(resultSpec) == RES_PASS)) {
+      /* if already verified then done, return success (0) */
+      return RES_VERIFY_DONE;
+    }
+    /* if the above conditions are not satisfied, attempt
+     * verification again
+     */
+    Ntk_NetworkFreeApplInfo(specNetwork, RES_NETWORK_APPL_KEY );
+  }
+
+
+  /* create result structure */
+  resultSpec = (Res_ResidueInfo_t *)
+    ResNetworkResidueInfoReadOrCreate(specNetwork);
+  /* add hook to network */
+  Ntk_NetworkAddApplInfo(specNetwork, RES_NETWORK_APPL_KEY,
+		 (Ntk_ApplInfoFreeFn) Res_ResidueInfoFreeCallback,
+		 (void *)resultSpec);
+
+  /* number of outputs */
+  numOutputs = Ntk_NetworkReadNumCombOutputs(specNetwork);
+  ResResidueInfoSetNumOutputs(resultSpec, numOutputs);
+  /* number of Inputs */
+  numInputs = Ntk_NetworkReadNumCombInputs(specNetwork);
+  ResResidueInfoSetNumInputs(resultSpec, numInputs);
+  /* impl name */
+  implName = util_strsav(Ntk_NetworkReadName(implNetwork));
+  ResResidueInfoSetNameVerifiedAgainst(resultSpec, implName);
+  /* number of directly verified outputs */
+  ResResidueInfoSetNumDirectVerifiedOutputs(resultSpec, numDirectVerify);
+
+  /*
+   * Assumption: The implementation residue information is invalid even
+   * if it does exist and will be overwritten
+   */
+  resultImpl = (Res_ResidueInfo_t *)Ntk_NetworkReadApplInfo(implNetwork,
+					RES_NETWORK_APPL_KEY);
+  /* free existing structure */
+  if (resultImpl != NIL(Res_ResidueInfo_t)) {
+    Ntk_NetworkFreeApplInfo(implNetwork,RES_NETWORK_APPL_KEY);
+  }
+
+  /* create a new structure for the implementation network */
+  resultImpl = (Res_ResidueInfo_t *)
+    ResNetworkResidueInfoReadOrCreate(implNetwork);
+  Ntk_NetworkAddApplInfo(implNetwork, RES_NETWORK_APPL_KEY,
+		(Ntk_ApplInfoFreeFn) Res_ResidueInfoFreeCallback,
+		(void *)resultImpl);
+
+
+  /*
+   * Get some information about the network  and initialize the residue
+   * information for the implementation network.
+   */
+
+  /* number of outputs */
+  assert (numOutputs == Ntk_NetworkReadNumCombOutputs(implNetwork));
+  ResResidueInfoSetNumOutputs(resultImpl, numOutputs);
+  /* number of Inputs */
+  assert (numInputs == Ntk_NetworkReadNumCombInputs(implNetwork));
+  ResResidueInfoSetNumInputs(resultImpl, numInputs);
+  /* spec name */
+  specName = util_strsav(Ntk_NetworkReadName(specNetwork));
+  ResResidueInfoSetNameVerifiedAgainst(resultImpl, specName);
+  /* number of directly verified outputs */
+  ResResidueInfoSetNumDirectVerifiedOutputs(resultImpl, numDirectVerify);
+
+  return RES_VERIFY_IGNORE_PREV_RESULTS;
+} /* End of SetBasicResultInfo */
+
+/**Function********************************************************************
+
+  Synopsis [Cleanup procedure to free all data structures allocated here.]
+
+  Description [Cleanup procedure to free all data structures allocated here.
+  Quit manager if created here. Quit result data structures if created here.
+  The check against RES_VERIFY_NOTHING is to check if the cleanup is called
+  before the result structures were allocated. The arguments to this procedure
+  are an error flag staying if this cleanup is under an error condition, the
+  spec network, impl. network, a flag that says if the manager was initialized
+  here, a flag that indicates if this verification has already been performed,
+  an output pointer match table, an input pointer match table, a directly
+  verified output pointer match table, a table that contains saved mdds for the
+  spec. and the impl., and the layer structures for the spec. and the impl.]
+
+  SideEffects [All data structures allocated in the Res_NetworkResidueVerify
+  procedure will be freed here.]
+
+  SeeAlso     [Res_NetworkResidueVerify]
+
+******************************************************************************/
+static void
+Cleanup(int error,
+	Ntk_Network_t *specNetwork,
+	Ntk_Network_t *implNetwork,
+	int initManagerHere,
+	int done,
+	st_table *outputMatch,
+	st_table *inputMatch,
+	st_table *directVerifyMatch,
+	st_table *oldSpecMddIdTable,
+	st_table *oldImplMddIdTable,
+	array_t *specLayerArray,
+	array_t *implLayerArray)
+{
+  bdd_manager *ddManager;
+
+  if (initManagerHere) {
+    ddManager = (bdd_manager *)Ntk_NetworkReadMddManager(specNetwork);
+    if (ddManager != NIL(bdd_manager)) {
+      mdd_quit(ddManager);
+      Ntk_NetworkSetMddManager(specNetwork, NIL(mdd_manager));
+      Ntk_NetworkSetMddManager(implNetwork, NIL(mdd_manager));
+    }
+  }
+
+  if (done != RES_VERIFY_NOTHING) {  /* if result structure allocated */
+    if (error) { /* on error free results */
+      if (done == RES_VERIFY_IGNORE_PREV_RESULTS) {
+	/* if spec result was created here */
+	Ntk_NetworkFreeApplInfo(specNetwork,RES_NETWORK_APPL_KEY);
+      }
+      Ntk_NetworkFreeApplInfo(implNetwork,RES_NETWORK_APPL_KEY);
+    }
+  }
+  if (outputMatch != NIL(st_table)) {
+    st_free_table(outputMatch);
+  }
+  if (inputMatch != NIL(st_table)) {
+    st_free_table(inputMatch);
+  }
+  if (directVerifyMatch != NIL(st_table)) {
+    st_free_table(directVerifyMatch);
+  }
+
+  if (oldSpecMddIdTable != NIL(st_table)) {
+    RestoreOldMddIds(specNetwork, oldSpecMddIdTable);
+    st_free_table(oldSpecMddIdTable);
+  }
+  if (oldImplMddIdTable != NIL(st_table)) {
+    RestoreOldMddIds(implNetwork, oldImplMddIdTable);
+    st_free_table(oldImplMddIdTable);
+  }
+  if (specLayerArray != NULL) {
+    ResLayerArrayFree(specLayerArray);
+  }
+  if (implLayerArray != NULL) {
+    ResLayerArrayFree(implLayerArray);
+  }
+  return;
+} /* End of Cleanup */
+
+
+/**Function********************************************************************
+
+  Synopsis [Save mdd ids for each node.]
+
+  Description [Save old mdd ids for each node and returns a table with the
+  nodes and the Ids.]
+
+  SideEffects   []
+
+  SeeAlso [Res_NetworkResidueVerify RestoreOldMddIds]
+
+******************************************************************************/
+static st_table *
+SaveOldMddIds(Ntk_Network_t *network)
+{
+  st_table *oldMddIdTable;
+  Ntk_Node_t *nodePtr;
+  lsGen listGen;             /* To iterate over outputList */
+
+  oldMddIdTable = st_init_table(st_ptrcmp, st_ptrhash);
+  if (oldMddIdTable == NULL) return NIL(st_table);
+
+  Ntk_NetworkForEachNode(network, listGen, nodePtr) {
+    st_insert(oldMddIdTable, (char *)nodePtr,
+	      (char *)(long)Ntk_NodeReadMddId(nodePtr));
+  }
+  return(oldMddIdTable);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Perform direct verification of the given outputs.]
+
+  Description [Perform direct verification of the given outputs. If error,
+  returns 1, if successful returns 0. The directVerifyMatch table contains the
+  node pointer matches for the outputs to be directly verified. The procedure
+  first checks if the input variables are ordered.  If not ordered, it orders
+  the variables. builds two array with corresponding nodes to be directly
+  verified and a permutation array for the correspondence of the inputs.  The
+  outputs arrays are ordered starting with the LSB. For each of these nodes in
+  the array, the bdd is built and compared. Since the primary input variables
+  in the spec and the impl may have different mdd ids, a step of bdd permute is
+  performed on the impl bdd to represent it in terms of the spec PI
+  variables. The resultant Bdds are checked to see if they are identical.  The
+  result structure is updated. The parameters to this procedure are the spec.
+  and the impl. network, the match table of the pointers of the directly
+  verified outputs, the tables with the input and output pointer matches and
+  the order array of the outputs.]
+
+  SideEffects   [Result Structure is updated.]
+
+  SeeAlso     [Res_NetworkResidueVerify]
+
+******************************************************************************/
+static int
+DirectVerification(Ntk_Network_t *specNetwork,
+		   Ntk_Network_t *implNetwork,
+		   st_table *directVerifyMatch,
+		   st_table *inputMatch,
+		   st_table *outputMatch,
+		   array_t *outputOrderArray)
+{
+
+    Ntk_Node_t *nodePtr, *implNodePtr;         /* node variables */
+    long startTime, endTime, directVerifyTime; /* to measure elapsed time */
+    long lapTimeSpec, lapTimeImpl;             /* to measure elapsed time */
+    bdd_node *specBDD, *implBDD, *permutedBDD;   /* bdds of direct verified outputs */
+    lsGen listGen;                             /* To iterate over outputList */
+    int *permut;                              /* permutation array to store
+					       * correspondence of inputs
+					       */
+    int specMddId, implMddId;
+    Ntk_Node_t **specArray, **implArray;      /* arrays to store the
+					       * corresponding nodes of the
+					       * spec. and the impl.
+					       */
+    st_generator *stGen;
+    lsList dummy;				/* dummy list fed to the ord
+						 * package.
+						 */
+    char *key, *value;				/* variables to read values
+						 * from the st_table
+						 */
+    int index, i;				/* iterators */
+    char *name;					/* variable to read node name */
+    int numOutputs;				/* total number of outputs of
+						 * the spec.(impl).
+						 */
+    bdd_manager *ddManager;			/* the bdd manager */
+    bdd_reorder_type_t oldDynMethod, dynMethod = BDD_REORDER_SAME;
+						/* dynamic reordering methods */
+    int dynStatus = 0;				/* original status of the manager
+						 * w. r. t. dynamic reordering
+						 */
+    boolean dyn;				/* current dynamic reordering
+						 * status
+						 */
+    int verbose;				/* verbosity level */
+    char  *flagValue;				/* string to hold "Set" variable
+						 * value
+						 */
+    Res_ResidueInfo_t *resultSpec;		/* result structure for the
+						 * spec.
+						 */
+    Res_ResidueInfo_t *resultImpl;		/* result structure for the
+						 * impl.
+						 */
+    int specSize, implSize;			/* sizes of bdds */
+    mdd_t *fnMddT;				/* mdd_t structure to calculate sizes */
+
+
+    /* Initializations */
+    dummy = (lsList)0;
+    lapTimeSpec = 0;
+    lapTimeImpl = 0;
+    dyn = FALSE;
+    verbose = 0;
+
+    /* read verbosity value */
+    flagValue = Cmd_FlagReadByName("residue_verbosity");
+    if (flagValue != NIL(char)) {
+      verbose = atoi(flagValue);
+    }
+
+    /* read if dynamic ordering is required */
+    flagValue = Cmd_FlagReadByName("residue_autodyn_direct_verif");
+    if (flagValue != NIL(char)) {
+      dyn = (strcmp(flagValue, "1") == 0) ? TRUE : FALSE;
+    }
+    /* read method for dynamic reordering */
+    if (dyn == TRUE) {
+      flagValue = Cmd_FlagReadByName("residue_direct_dyn_method");
+      if (flagValue != NULL) {
+	dynMethod = DecodeDynMethod(flagValue);
+      } else {
+	dynMethod = BDD_REORDER_SAME;
+      }
+    }
+
+    /* read manager from network */
+    ddManager = (bdd_manager *)Ntk_NetworkReadMddManager(specNetwork);
+    /* save old values for dynamic reordering */
+    if (dyn == TRUE) {
+      dynStatus = bdd_reordering_status(ddManager, &oldDynMethod);
+      bdd_dynamic_reordering(ddManager, dynMethod, BDD_REORDER_VERBOSITY_DEFAULT);
+    }
+
+    /* find total time elapsed */
+    directVerifyTime = util_cpu_time();
+
+    /* find number of outputs to be directly verified */
+    numOutputs = st_count(directVerifyMatch);
+
+    /*
+     * Order primary input variables in the network to build the BDDs for
+     * outputs to be directly verified.
+     */
+    if (Ord_NetworkTestAreVariablesOrdered(specNetwork,
+					   Ord_InputAndLatch_c) == FALSE) {
+      /* order the variables in the network since not done */
+      startTime = util_cpu_time();
+      Ord_NetworkOrderVariables(specNetwork, Ord_RootsByDefault_c,
+		      Ord_NodesByDefault_c, FALSE, Ord_InputAndLatch_c,
+		      Ord_Unassigned_c, dummy, 0);
+
+      endTime = util_cpu_time();
+      lapTimeSpec += endTime - startTime;
+
+      startTime = endTime;
+      Ord_NetworkOrderVariables(implNetwork, Ord_RootsByDefault_c,
+		      Ord_NodesByDefault_c, FALSE, Ord_InputAndLatch_c,
+		      Ord_Unassigned_c, dummy, 0);
+      lapTimeImpl += endTime - startTime;
+
+    } else {
+      /* if order is not specified, assume the same order for spec.
+       * and implementation
+       */
+      Ntk_NetworkForEachCombInput(specNetwork, listGen, nodePtr) {
+	assert(Ntk_NodeReadMddId(nodePtr) != NTK_UNASSIGNED_MDD_ID);
+	st_lookup(inputMatch, (char *)nodePtr, &implNodePtr);
+	Ntk_NodeSetMddId(implNodePtr, Ntk_NodeReadMddId(nodePtr));
+      }
+    }
+
+    if (verbose >= 5) {
+      Ntk_NetworkForEachCombInput(specNetwork, listGen, nodePtr) {
+	specMddId = Ntk_NodeReadMddId(nodePtr);
+	if (specMddId != NTK_UNASSIGNED_MDD_ID) {
+	  fprintf(vis_stdout, "%s ", Ntk_NodeReadName(nodePtr));
+	}
+      }
+      fprintf(vis_stdout, "\n");
+      Ntk_NetworkForEachCombInput(specNetwork, listGen, nodePtr) {
+	specMddId = Ntk_NodeReadMddId(nodePtr);
+	if (specMddId != NTK_UNASSIGNED_MDD_ID) {
+	  fprintf(vis_stdout, "%d ", specMddId);
+	}
+      }
+      fprintf(vis_stdout, "\n");
+    }
+
+    /* build arrays of corresponding nodes to be directly verified */
+    specArray = ALLOC(Ntk_Node_t *, numOutputs);
+    implArray = ALLOC(Ntk_Node_t *, numOutputs);
+    index = 0;
+    /* Order array starting from the LSB, so direct verification is performed
+     * starting from the inputs.
+     */
+    for (i = 0; i < array_n(outputOrderArray); i++) {
+      name = array_fetch(char *, outputOrderArray, array_n(outputOrderArray)-1-i);
+      nodePtr = Ntk_NetworkFindNodeByName(specNetwork, name);
+      /* find node in direct verify match table */
+      if (st_lookup(directVerifyMatch, (char *)nodePtr, (char **)&value)) {
+	specArray[index] = (Ntk_Node_t *)nodePtr;
+	implArray[index] = (Ntk_Node_t *)value;
+	index++;
+      }
+    }
+    /* number of outputs in the arrays should be as many entries as the match
+     * table.
+     */
+    assert(numOutputs == index);
+
+    /* Create a permutation array for the specMddId and implMddId input nodes */
+    permut = ALLOC(int, bdd_num_vars(ddManager));
+    for (i= 0; (unsigned) i < bdd_num_vars(ddManager); i++) {
+      permut[i] = i;
+    }
+    st_foreach_item(inputMatch, stGen, &key, &value) {
+      nodePtr = (Ntk_Node_t *)key;
+      implNodePtr = (Ntk_Node_t *)value;
+      if ((nodePtr == NIL(Ntk_Node_t)) || (implNodePtr == NIL(Ntk_Node_t))){
+	error_append("Input match values do not return");
+	error_append("valid node pointers.\n");
+	/* Clean up */
+	FREE(permut);
+	FREE(specArray);
+	FREE(implArray);
+	st_free_gen(stGen);
+	return 1;
+      }
+      /* create the array with the impl. vars to be composed with spec. vars. */
+      specMddId = Ntk_NodeReadMddId(nodePtr);
+      implMddId = Ntk_NodeReadMddId(implNodePtr);
+      /* there should be no node with NTK_UNASSIGNED_MDD_ID due to the
+       * ordering above
+       */
+      assert(specMddId != NTK_UNASSIGNED_MDD_ID);
+      assert(implMddId != NTK_UNASSIGNED_MDD_ID);
+      permut[implMddId] = specMddId;
+
+    } /* end of input match */
+
+    /*
+     * Build BDDs for each output to be directly verified and check
+     * for identical BDDs in spec. and impl.
+     */
+    for (i = 0; i < numOutputs; i++) {
+      /* build the spec BDD */
+      startTime = util_cpu_time();
+      specBDD = BuildBDDforNode(specNetwork, specArray[i], PRIMARY_INPUTS);
+      if (specBDD == NIL(bdd_node)) {
+	error_append("Unable to build spec. BDD for the direct verification output");
+	error_append(Ntk_NodeReadName(specArray[i]));
+	error_append(".\n");
+	/* Clean up */
+	FREE(permut);
+	FREE(specArray);
+	FREE(implArray);
+	return 1; /* error status */
+      } /* end of if spec BDD is NIL */
+      endTime = util_cpu_time();
+      lapTimeSpec += endTime - startTime;
+
+      /* build the impl BDD */
+      startTime = endTime;
+      implBDD = BuildBDDforNode(implNetwork, implArray[i], PRIMARY_INPUTS);
+      if (implBDD == NIL(bdd_node)) {
+	error_append("Unable to build spec. BDD for the direct verification output");
+	error_append(Ntk_NodeReadName(implArray[i]));
+	error_append(".\n");
+	/* Clean up */
+	bdd_recursive_deref(ddManager, specBDD);
+	FREE(permut);
+	FREE(specArray);
+	FREE(implArray);
+	return 1; /* error status */
+      } /* end of if spec BDD is NIL */
+      endTime = util_cpu_time();
+      lapTimeImpl += endTime - startTime;
+
+      /* call bdd permute to compose the impl variables with the spec
+       * variables.
+       */
+      startTime = endTime;
+      bdd_ref(permutedBDD = bdd_bdd_permute(ddManager, implBDD, permut));
+      bdd_recursive_deref(ddManager, implBDD);
+      endTime = util_cpu_time();
+      lapTimeSpec += (endTime - startTime)/2;
+      lapTimeImpl += (endTime - startTime)/2;
+      implBDD = permutedBDD;
+      if (implBDD == NIL(bdd_node)) {
+	error_append("Permuting the impl bdd in terms of spec bdd vars failed\n");
+	/* Clean up */
+	bdd_recursive_deref(ddManager, specBDD);
+	FREE(permut);
+	FREE(specArray);
+	FREE(implArray);
+	return 1; /* error status */
+      }
+
+      /* compare the bdds */
+      if(specBDD != implBDD)  {
+	/* error since spec and impl are not the same */
+	/* update result structure */
+	if (verbose >= 2) {
+	  (void)fprintf(vis_stdout, "Vector where the two networks differ :\n");
+	  (void)fprintf(vis_stdout, "Specification Input Names :\n");
+	  ExtractACubeOfDifference(ddManager, specNetwork, specBDD, implBDD);
+	}
+	resultSpec = (Res_ResidueInfo_t *)Ntk_NetworkReadApplInfo(specNetwork,
+					  RES_NETWORK_APPL_KEY);
+	resultImpl = (Res_ResidueInfo_t *)Ntk_NetworkReadApplInfo(implNetwork,
+					  RES_NETWORK_APPL_KEY);
+	ResResidueInfoSetDirectVerificationSuccess(resultSpec, RES_FAIL);
+	ResResidueInfoSetDirectVerificationSuccess(resultImpl, RES_FAIL);
+	(void) fprintf(vis_stdout, "%.2f (secs) spent in failed direct verification.\n",
+		       (util_cpu_time() - directVerifyTime)/1000.0);
+	fprintf(vis_stdout, "Residue Direct Verification failed at output node ");
+	fprintf(vis_stdout, "%s", Ntk_NodeReadName(specArray[i]));
+	fprintf(vis_stdout, " of the spec.\n");
+	fprintf(vis_stdout, "Spec. did not match Impl.\n");
+	/* Clean up */
+	/* free the bdds just created */
+	bdd_recursive_deref(ddManager, specBDD);
+	bdd_recursive_deref(ddManager, implBDD);
+	FREE(permut);
+	FREE(specArray);
+	FREE(implArray);
+	return 0;
+      } /* end if spec BDD != impl BDD */
+
+      /* if the bdds are equal, print some information */
+      if (verbose >= 2) {
+	fprintf(vis_stdout, "%d out of %d ", i + 1 ,numOutputs);
+	fprintf(vis_stdout, "direct verification outputs done.\n");
+      }
+      if (verbose >= 3) {
+	fprintf(vis_stdout, "%s(spec)/%s(impl) output verified. \n",
+		Ntk_NodeReadName(specArray[i]), Ntk_NodeReadName(implArray[i]));
+	bdd_ref(specBDD);
+	fnMddT = bdd_construct_bdd_t(ddManager, specBDD);
+	specSize = bdd_size(fnMddT);
+	bdd_free(fnMddT);
+	bdd_ref(implBDD);
+	fnMddT = bdd_construct_bdd_t(ddManager, implBDD);
+	implSize = bdd_size(fnMddT);
+	bdd_free(fnMddT);
+	fprintf(vis_stdout, "Size of %s(spec) = %d, Size of %s(impl) = %d\n",
+	 Ntk_NodeReadName(specArray[i]) ,specSize, Ntk_NodeReadName(implArray[i]), implSize);
+	fprintf(vis_stdout, "%.3f spec time elapsed, %.3f impl. time elapsed.\n", lapTimeSpec/1000.0,
+		lapTimeImpl/1000.0);
+      }
+      /* free the bdds just created */
+      bdd_recursive_deref(ddManager, specBDD);
+      bdd_recursive_deref(ddManager, implBDD);
+
+    } /* end of for-loop that iterates through the nodes to be directly
+       * verified.
+       */
+
+    FREE(permut);
+    FREE(specArray);
+    FREE(implArray);
+
+    /* set direct verification success info */
+    /* update result structure */
+    resultSpec = (Res_ResidueInfo_t *)Ntk_NetworkReadApplInfo(specNetwork,
+							RES_NETWORK_APPL_KEY);
+    resultImpl = (Res_ResidueInfo_t *)Ntk_NetworkReadApplInfo(implNetwork,
+							RES_NETWORK_APPL_KEY);
+    ResResidueInfoSetDirectVerificationSuccess(resultSpec, RES_PASS);
+    ResResidueInfoSetCpuDirectVerif(resultSpec, (float) lapTimeSpec);
+    ResResidueInfoSetDirectVerificationSuccess(resultImpl, RES_PASS);
+    ResResidueInfoSetCpuDirectVerif(resultImpl, (float) lapTimeImpl);
+
+    /* Print success message */
+    fprintf(vis_stdout, "Residue Direct Verification successful.\n");
+
+    /* Print Time taken for direct verification */
+    if (verbose >= 1) {
+      (void) fprintf(vis_stdout, "%.2f (secs) spent in Direct verification.\n",
+		       (util_cpu_time() - directVerifyTime)/1000.0);
+    }
+
+    /* Print which outputs were directly verified and time spent for
+     * the spec and the impl
+     */
+    if (verbose >= 2) {
+      fprintf(vis_stdout, "Time taken to build spec. BDD = %.3f\n",
+	      ResResidueInfoReadCpuDirectVerif(resultSpec)/1000.0);
+      fprintf(vis_stdout, "Time taken to build impl. BDD = %.3f\n",
+	      ResResidueInfoReadCpuDirectVerif(resultImpl)/1000.0);
+      st_foreach_item(directVerifyMatch, stGen, &key, &value) {
+	fprintf(vis_stdout, "%s ", Ntk_NodeReadName((Ntk_Node_t *)key));
+      }
+      fprintf(vis_stdout, "verified successfully.\n");
+    }
+
+    /* Print order of variables of this verification */
+    if (verbose >= 3) {
+      Ord_NetworkPrintVariableOrder(vis_stdout, specNetwork,
+      Ord_InputAndLatch_c);
+      Ord_NetworkPrintVariableOrder(vis_stdout, implNetwork,
+      Ord_InputAndLatch_c);
+    }
+
+    /* restore the old values for dynamic reordering */
+    if(dyn == TRUE) {
+      bdd_dynamic_reordering(ddManager, oldDynMethod, BDD_REORDER_VERBOSITY_DEFAULT);
+      if (!dynStatus) {
+	bdd_dynamic_reordering_disable(ddManager);
+      }
+    }
+
+    return 0; /* direct verification success */
+} /* End of Direct Verification */
+
+
+/**Function********************************************************************
+
+  Synopsis [Decode the option of reordering.]
+
+  Description [Decode the option of reordering. Returns the dynMethod value.]
+
+  SideEffects   []
+
+******************************************************************************/
+static bdd_reorder_type_t
+DecodeDynMethod(char *dynMethodString)
+{
+  bdd_reorder_type_t dynMethod;
+
+  /* Translate reordering string to specifying method */
+  if (dynMethodString == NIL(char)) {
+    dynMethod = BDD_REORDER_SIFT;
+  } else if (strcmp(dynMethodString, "same") == 0) {
+    dynMethod = BDD_REORDER_SAME;
+  } else if (strcmp(dynMethodString, "none") == 0) {
+    dynMethod = BDD_REORDER_NONE;
+  } else if (strcmp(dynMethodString, "random") == 0) {
+    dynMethod = BDD_REORDER_RANDOM;
+  } else if (strcmp(dynMethodString, "randompivot") == 0) {
+    dynMethod = BDD_REORDER_RANDOM_PIVOT;
+  } else if (strcmp(dynMethodString, "sift") == 0) {
+    dynMethod = BDD_REORDER_SIFT;
+  } else if (strcmp(dynMethodString, "siftconverge") == 0) {
+    dynMethod = BDD_REORDER_SIFT_CONVERGE;
+  } else if (strcmp(dynMethodString, "symmsift") == 0) {
+    dynMethod = BDD_REORDER_SYMM_SIFT;
+  } else if (strcmp(dynMethodString, "symmsiftconverge") == 0) {
+    dynMethod = BDD_REORDER_SYMM_SIFT_CONV;
+  } else if (strcmp(dynMethodString, "window2") == 0) {
+    dynMethod = BDD_REORDER_WINDOW2;
+  } else if (strcmp(dynMethodString, "window3") == 0) {
+    dynMethod = BDD_REORDER_WINDOW3;
+  } else if (strcmp(dynMethodString, "window4") == 0) {
+    dynMethod = BDD_REORDER_WINDOW4;
+  } else if (strcmp(dynMethodString, "window2converge") == 0) {
+    dynMethod = BDD_REORDER_WINDOW2_CONV;
+  } else if (strcmp(dynMethodString, "window3converge") == 0) {
+    dynMethod = BDD_REORDER_WINDOW3_CONV;
+  } else if (strcmp(dynMethodString, "window4converge") == 0) {
+    dynMethod = BDD_REORDER_WINDOW4_CONV;
+  } else if (strcmp(dynMethodString, "groupsift") == 0) {
+    dynMethod = BDD_REORDER_GROUP_SIFT;
+  } else if (strcmp(dynMethodString, "groupsiftconverge") == 0) {
+    dynMethod = BDD_REORDER_GROUP_SIFT_CONV;
+  } else if (strcmp(dynMethodString, "anneal") == 0) {
+    dynMethod = BDD_REORDER_ANNEALING;
+  } else if (strcmp(dynMethodString, "genetic") == 0) {
+    dynMethod = BDD_REORDER_GENETIC;
+  } else if (strcmp(dynMethodString, "linear") == 0) {
+    dynMethod = BDD_REORDER_LINEAR;
+  } else if (strcmp(dynMethodString, "linearconverge") == 0) {
+    dynMethod = BDD_REORDER_LINEAR_CONVERGE;
+  } else if (strcmp(dynMethodString, "exact") == 0) {
+    dynMethod = BDD_REORDER_EXACT;
+  } else {
+    dynMethod = BDD_REORDER_SIFT;
+  }
+  return dynMethod;
+} /* End of DecodeDynMethod */
+
+
+
+/**Function********************************************************************
+
+  Synopsis  [Main Function to perform residue verification.]
+
+  Description [Main Function to perform residue verification.  The network
+  parameters are in a specific order: SPECIFICATION first, IMPLEMENTATION
+  second.  All other parameters store values of the specification. The
+  procedure first turns off dynamic reordering unless specified otherwise. The
+  array of required primes are computed and the cudd manager is
+  initialized. The main loop iterates over the primes. The residue ADD is
+  constructed for as many variables as POs with respect to each prime.  Then
+  calls a procedure which composes the networks (in layers) into the residue
+  ADD. The final ADD is compared for both the spec and the impl.  A sub-routine
+  composes the network into the residue ADD depending on the composition
+  method.  The final ADDs for the specification and the implementation are
+  checked against each other. The procedure returns 0 if it were unable to
+  complete for some reason, like memory failure, incomplete networks, etc.  The
+  procedure returns 0 if successful in building the BDDs of the two
+  circuits. The parameters to this procedure are spec. network, impl. network,
+  output pointer match table, input pointer match table, number of directly
+  verified outputs, layer structure of the spec. and the impl. and an array of
+  nodes with outputs for residue verification.]
+
+  SideEffects   []
+
+******************************************************************************/
+static int
+ResidueVerification(Ntk_Network_t *specNetwork,
+		    Ntk_Network_t *implNetwork,
+		    st_table *outputMatch,
+		    st_table *inputMatch,
+		    int numDirectVerify,
+		    array_t *specLayerArray,
+		    array_t *implLayerArray,
+		    array_t *outputArray)
+{
+  int numOutputs;                 /* number of outputs in the networks */
+  int actualOutputs;                 /* number of outputs in the networks */
+  int msbId;		          /* stores the top Id available */
+  int msbLsb;                     /* 1 means Msb on top */
+
+  Ntk_Node_t *nodePtr, *implNodePtr; /* variables to store nodes in networks */
+
+  Res_ResidueInfo_t *resultSpec;   /* spec. result structure */
+  Res_ResidueInfo_t *resultImpl;   /* impl. result structure */
+
+  int verbose;                     /* verbosity value */
+  char *flagValue;                 /* string to store flag values */
+  int i;                           /* iterating index */
+
+  lsGen listGen;                   /* list generator for looping over nodes
+				    * in a network.
+				    */
+  st_generator *stGen;	   /* generator to step through st_table */
+  char *key, *value;		   /* variables to read in st-table values */
+  long overallLap;	/* to measure elapsed time */
+  long lap;	/* to measure elapsed time */
+  int primeIndex;	/* index to iterate over prime array */
+  bdd_manager *ddManager;      /* Manager read from the network */
+  bdd_node *implADD, *specADD, *tmpDd; /* final ADDs after composition */
+  int specSize, implSize;		/* sizes of bdds */
+  int specMddId, implMddId;  /* id variables for nodes */
+  bdd_node *residueDd;	/* residue ADD (n x m) */
+  int *permut;	/* array to permute impl ADD variables to spec.
+				 * ADD variables.
+				 */
+  int numOfPrimes;	/* Number of primes needed for verification */
+  int *primeTable;	/* array to store primes needed for current
+				 * verification
+				 */
+  bdd_reorder_type_t oldDynMethod, dynMethod; /* dynamic reordering
+					       * methods
+					       */
+  int dynStatus;		/* Status of manager w.r.t. original
+				 * reordering
+				 */
+  boolean dyn;		/* flag to indicate dynamic reordering
+				 * is turned on.
+				 */
+  mdd_t *fnMddT;	        /* mdd_t structure to calculate sizes */
+  int unassignedValue;          /* NTK_UNASSIGNED_MDD_ID value holder */
+  array_t *implOutputArray;     /* array of output nodes of the impl.in consideration
+				 * for composition
+				 */
+
+  /* Initialization */
+  verbose = 0;
+  unassignedValue =  NTK_UNASSIGNED_MDD_ID;
+  numOfPrimes = 0;
+  msbLsb = 1; /* default value msb is on top */
+  primeTable = NULL;
+  overallLap = util_cpu_time();
+  dyn = FALSE; /* default dynamic reordering disabled */
+  permut = NULL;
+
+  /* specify if the top var of the residue ADD is the MSB/LSB */
+  flagValue = Cmd_FlagReadByName("residue_top_var");
+  if (flagValue != NIL(char) && strcmp(flagValue,"lsb") == 0) {
+    msbLsb = 0;
+  } else {
+    msbLsb = 1;
+  }
+
+  /* initialize number of outputs */
+  actualOutputs = Ntk_NetworkReadNumCombOutputs(specNetwork);
+
+  /* Read the mdd Manager (or create it if necessary) */
+  ddManager = (bdd_manager *)Ntk_NetworkReadMddManager(specNetwork);
+    /* save old dynamic reordering values */
+  dynStatus = bdd_reordering_status(ddManager, &oldDynMethod);
+
+  /* read verbosity value */
+  flagValue = Cmd_FlagReadByName("residue_verbosity");
+  if (flagValue != NIL(char)) {
+    verbose = atoi(flagValue);
+  }
+
+  /* read if dynamic ordering is required */
+  flagValue = Cmd_FlagReadByName("residue_autodyn_residue_verif");
+  if (flagValue != NIL(char)) {
+    dyn = (strcmp(flagValue,"1")==0) ? TRUE : FALSE;
+  }
+  /* read method of dynamic reordering */
+  if (dyn == TRUE) {
+    flagValue = Cmd_FlagReadByName("residue_residue_dyn_method");
+    if ( flagValue != NULL) {
+      dynMethod = DecodeDynMethod(flagValue);
+    } else {
+      dynMethod = BDD_REORDER_SAME;
+    }
+    /* update manager with dynamic reordering and the method */
+    bdd_dynamic_reordering(ddManager, dynMethod, BDD_REORDER_VERBOSITY_DEFAULT);
+  } else {
+    /* unless specified, TURN REORDERING OFF for residue verification */
+    bdd_dynamic_reordering_disable(ddManager);
+  }
+
+  /*
+   * Choose the set of primes that will be used, primeTable is allocated
+   * here.
+   */
+  numOfPrimes = ChoosePrimes(actualOutputs,  &primeTable, numDirectVerify);
+
+  /* get result structures */
+  resultSpec = (Res_ResidueInfo_t *)Ntk_NetworkReadApplInfo(specNetwork,
+						    RES_NETWORK_APPL_KEY);
+  resultImpl = (Res_ResidueInfo_t *)Ntk_NetworkReadApplInfo(implNetwork,
+						    RES_NETWORK_APPL_KEY);
+
+  /* update result with primes info */
+  if ((resultSpec  != NIL(Res_ResidueInfo_t)) && (resultImpl != NIL(Res_ResidueInfo_t))) {
+    ResResidueInfoAllocatePrimeInfoArray(resultSpec, numOfPrimes, primeTable);
+    ResResidueInfoAllocatePrimeInfoArray(resultImpl, numOfPrimes, primeTable);
+    ResResidueInfoSetNumOfPrimes(resultSpec, numOfPrimes);
+    ResResidueInfoSetNumOfPrimes(resultImpl, numOfPrimes);
+  } else {
+    /* error - the result structure should be there */
+    error_append("Result structures are missing\n");
+    FREE(primeTable);
+    return 1;
+  }
+
+  /* Print the list of primes depending on the verbosity level*/
+  if (verbose >= 0) {
+    (void) fprintf(vis_stdout, "List of Primes used: ");
+    for(i=0; i<numOfPrimes; i++) {
+      (void) fprintf(vis_stdout, "%d ", primeTable[i]);
+    }
+    (void) fprintf(vis_stdout, "\n");
+  } /* End of if */
+
+  /* form impl Output Array */
+  implOutputArray = array_alloc(Ntk_Node_t *, array_n(outputArray));
+  arrayForEachItem(Ntk_Node_t *, outputArray, i, nodePtr) {
+    st_lookup(outputMatch, (char *)nodePtr, &implNodePtr);
+    array_insert(Ntk_Node_t *, implOutputArray, i, implNodePtr);
+  }
+
+  /* number of outputs in consideration */
+  numOutputs = array_n(outputArray);
+
+
+  /* Main Loop in which the verification is done for each prime. */
+  for(primeIndex = 0; primeIndex < numOfPrimes; primeIndex++) {
+    int currentPrime;
+
+    /* Read current prime from table */
+    currentPrime = primeTable[primeIndex];
+    if (verbose >=2)
+      (void) fprintf(vis_stdout, "Processing prime %d:\n", currentPrime);
+
+    /* update the mdd manager with the first set of output variables */
+    MddCreateVariables((mdd_manager *)ddManager, numOutputs-bdd_num_vars(ddManager));
+
+
+    /* Obtain the residue bdd for the given prime, assume top id is
+     * always 0i.e. msbId = 0;
+     */
+    msbId = 0;
+    bdd_ref(residueDd = bdd_add_residue(ddManager, numOutputs, currentPrime,
+					 msbLsb, msbId));
+
+    /*	Set the output Id. Needs to be set each time because it gets
+     * cleared each time.
+     */
+    arrayForEachItem(Ntk_Node_t *, outputArray, i , nodePtr) {
+      st_lookup(outputMatch, (char *)nodePtr, &implNodePtr);
+      if (msbLsb == 1) {
+	Ntk_NodeSetMddId(nodePtr, i);
+	Ntk_NodeSetMddId(implNodePtr, i);
+      } else {
+	Ntk_NodeSetMddId(nodePtr, numOutputs - i);
+	Ntk_NodeSetMddId(implNodePtr, numOutputs - i);
+      }
+    }
+
+
+    /* Set the cpu usage lap */
+    lap = util_cpu_time();
+
+    if (verbose >= 1) {
+      fprintf(vis_stdout, "Specification being built\n");
+    }
+    /* the actual composition of the spec. network into the residue ADD
+     * is done here. The composed ADD return is referenced
+     */
+    specADD = ComposeLayersIntoResidue(specNetwork, specLayerArray, residueDd, outputArray);
+    if (specADD == NIL(bdd_node)) {
+      error_append("Composition of spec. failed.\n");
+      /* Clean up before you leave */
+      array_free(implOutputArray);
+      FREE(primeTable);
+      bdd_recursive_deref(ddManager, residueDd);
+      return 1; /* error return */
+    }
+
+    /* Store the information in the result structure of the spec.*/
+    bdd_ref(specADD);
+    fnMddT = bdd_construct_bdd_t(ddManager, specADD);
+    specSize = bdd_size(fnMddT);
+    bdd_free(fnMddT);
+    ResResidueInfoSetPerPrimeInfo(resultSpec, primeIndex, currentPrime,
+				  (util_cpu_time() - lap)/1000.0, specSize, specADD);
+    /* Print info regarding this prime if pertinent */
+    if (verbose >=3) {
+      (void) fprintf(vis_stdout, "%.2f (secs) spent in composing prime\n",
+		     ResResidueInfoReadPerPrimeInfo(resultSpec, primeIndex)->cpuTime);
+      (void) fprintf(vis_stdout, "Composed Dd with %d nodes\n", specSize);
+    }
+
+    /* Set the cpu usage lap */
+    lap = util_cpu_time();
+
+    /*
+     * the actual composition of the impl. network into the residue ADD
+     * is done here. The composed ADD return is referenced
+     */
+    if (verbose >= 1) {
+      fprintf(vis_stdout, "Implementation being built\n");
+    }
+    implADD = ComposeLayersIntoResidue(implNetwork, implLayerArray, residueDd, implOutputArray);
+
+    bdd_recursive_deref(ddManager, residueDd);
+    if (implADD == NIL(bdd_node)) {
+      error_append("Composition of spec. failed.\n");
+      /* Clean up before you leave */
+      bdd_recursive_deref(ddManager, specADD);
+      array_free(implOutputArray);
+      FREE(primeTable);
+      return 1; /* error return */
+    }
+
+    /* Create a permutation array for the specMddId and implMddId input nodes */
+    permut = ALLOC(int, bdd_num_vars(ddManager));
+    for (i= 0; (unsigned) i < bdd_num_vars(ddManager); i++) {
+      permut[i] = i;
+    }
+    st_foreach_item(inputMatch, stGen, &key, &value) {
+      nodePtr = (Ntk_Node_t *)key;
+      implNodePtr = (Ntk_Node_t *)value;
+      if ((nodePtr == NIL(Ntk_Node_t)) || (implNodePtr == NIL(Ntk_Node_t))){
+	error_append("Input match values do not return");
+	error_append("valid node pointers.\n");
+	/* Clean up */
+	FREE(permut);
+	FREE(primeTable);
+	array_free(implOutputArray);
+	bdd_recursive_deref(ddManager, specADD);
+	bdd_recursive_deref(ddManager, implADD);
+	st_free_gen(stGen);
+	return 1;
+      }
+      /* create the array with the impl. vars to be composed with spec. vars. */
+      specMddId = Ntk_NodeReadMddId(nodePtr);
+      implMddId = Ntk_NodeReadMddId(implNodePtr);
+
+      /* there should be no node with NTK_UNASSIGNED_MDD_ID due to the
+       * ordering above
+       */
+
+#if 0
+      if (Ntk_NodeReadNumFanouts(nodePtr) != 0) {
+	assert(specMddId != NTK_UNASSIGNED_MDD_ID);
+      }
+      if (Ntk_NodeReadNumFanouts(implNodePtr) != 0) {
+	assert(implMddId != NTK_UNASSIGNED_MDD_ID);
+      }
+#endif
+
+      if ((specMddId != NTK_UNASSIGNED_MDD_ID) &&
+	  (implMddId != NTK_UNASSIGNED_MDD_ID)) {
+	permut[implMddId] = specMddId;
+      } else {
+	assert(specMddId == implMddId);
+      }
+
+    } /* end of st_foreach_item */
+
+    /* permute the variables so that the impl variables are replaced by
+     * spec. variables
+     */
+    bdd_ref(tmpDd = bdd_add_permute(ddManager, implADD, permut));
+    bdd_recursive_deref(ddManager, implADD);
+    FREE(permut);
+    implADD = tmpDd;
+    if(implADD == NIL(bdd_node)) { /* error */
+      error_append("Last composition failed,");
+      error_append("Cannot compose spec. ADD PI vars into Impl. ADD.\n");
+      FREE(primeTable);
+      array_free(implOutputArray);
+      return 1; /* error return */
+    }
+
+    if (verbose > 0) {
+      (void) fprintf(vis_stdout, "%.2f (secs) spent in residue verification.\n",
+		     (util_cpu_time() - overallLap)/1000.0);
+    }
+
+    /* Store the information in the result structure of the impl.*/
+    bdd_ref(implADD);
+    fnMddT = bdd_construct_bdd_t(ddManager, implADD);
+    implSize = bdd_size(fnMddT);
+    bdd_free(fnMddT);
+    ResResidueInfoSetPerPrimeInfo(resultImpl, primeIndex, currentPrime,
+	 (util_cpu_time() - lap)/1000.0, implSize, implADD);
+    /* Print info regarding this prime if pertinent */
+    if (verbose >=3) {
+      (void) fprintf(vis_stdout, "%.2f (secs) spent in composing prime\n",
+		     ResResidueInfoReadPerPrimeInfo(resultImpl, primeIndex)->cpuTime);
+      (void) fprintf(vis_stdout, "Composed Dd with %d nodes\n", implSize);
+    }
+
+
+    /* Compare the Spec and the Impl composed Dds */
+    if (ResResidueInfoReadPerPrimeInfo(resultSpec, primeIndex)->residueDd !=
+	ResResidueInfoReadPerPrimeInfo(resultImpl, primeIndex)->residueDd) {
+      ResResidueInfoSetSuccess(resultSpec, RES_FAIL);
+      ResResidueInfoSetSuccess(resultImpl, RES_FAIL);
+      (void) fprintf(vis_stdout, "Verification of %s and %s failed.\n",
+		     Res_ResidueInfoReadName(resultSpec),
+		     Res_ResidueInfoReadName(resultImpl));
+      (void)fprintf(vis_stdout,"The composed ADDs with residue are not the same.\n");
+      (void)fprintf(vis_stdout,"Verification failed at prime %d.\n", currentPrime);
+      if (verbose >= 2) {
+	(void)fprintf(vis_stdout, "Vector where the two networks differ :\n");
+	(void)fprintf(vis_stdout, "Specification Input Names :\n");
+	ExtractACubeOfDifference(ddManager, specNetwork, specADD, implADD);
+      }
+
+      /* Clean up before you leave */
+      bdd_recursive_deref(ddManager, ResResidueInfoReadPerPrimeInfo(resultSpec, primeIndex)->residueDd);
+      ResResidueInfoSetPerPrimeDd(resultSpec, primeIndex, NIL(bdd_node));
+
+      bdd_recursive_deref(ddManager, ResResidueInfoReadPerPrimeInfo(resultImpl, primeIndex)->residueDd);
+      ResResidueInfoSetPerPrimeDd(resultImpl, primeIndex, NIL(bdd_node));
+      array_free(implOutputArray);
+      FREE(primeTable);
+      return 0;
+    } else {
+
+      /* free the result Dd*/
+      bdd_recursive_deref(ddManager, ResResidueInfoReadPerPrimeInfo(resultSpec, primeIndex)->residueDd);
+      ResResidueInfoSetPerPrimeDd(resultSpec, primeIndex, NIL(bdd_node));
+
+      bdd_recursive_deref(ddManager, ResResidueInfoReadPerPrimeInfo(resultImpl, primeIndex)->residueDd);
+      ResResidueInfoSetPerPrimeDd(resultImpl, primeIndex, NIL(bdd_node));
+    }
+
+
+    /* reset node Ids of primary inputs */
+    Ntk_NetworkForEachCombInput(specNetwork, listGen, nodePtr) {
+      Ntk_NodeSetMddId(nodePtr, unassignedValue);
+    }
+    Ntk_NetworkForEachCombInput(implNetwork, listGen, nodePtr) {
+      Ntk_NodeSetMddId(nodePtr, unassignedValue);
+    }
+
+
+  } /* End of the main for-loop	*/
+  FREE(primeTable);
+  array_free(implOutputArray);
+
+  /* restore old dynamic reordering values */
+  bdd_dynamic_reordering(ddManager, oldDynMethod, BDD_REORDER_VERBOSITY_DEFAULT);
+  if (!dynStatus) {
+    bdd_dynamic_reordering_disable(ddManager);
+  }
+
+  /* set pass flag if residue verification success and direct verification
+   * success.
+   */
+  if (((numDirectVerify) &&
+       (ResResidueInfoReadDirectVerificationSuccess(resultSpec) == RES_PASS)) ||
+       (ResResidueInfoReadDirectVerificationSuccess(resultSpec) != RES_FAIL)) {
+    ResResidueInfoSetSuccess(resultSpec, RES_PASS);
+  }
+  if (((numDirectVerify) &&
+       (ResResidueInfoReadDirectVerificationSuccess(resultImpl) == RES_PASS)) ||
+      (ResResidueInfoReadDirectVerificationSuccess(resultImpl) != RES_FAIL)) {
+    ResResidueInfoSetSuccess(resultImpl, RES_PASS);
+  }
+  return 0;
+} /* End of ResidueVerification */
+
+/**Function********************************************************************
+
+  Synopsis [ Prints out a cube in the XOR of the 2 Bdds]
+
+  Description [ ]
+  value]
+
+  SideEffects   [.]
+
+  SeeAlso            []
+
+******************************************************************************/
+static void
+ExtractACubeOfDifference(bdd_manager *mgr,
+			 Ntk_Network_t *specNetwork,
+			 bdd_node *fn1,
+			 bdd_node *fn2)
+{
+  bdd_t *fnMddT, *fnMddT1;	/* mdd_t structure to calculate sizes */
+  bdd_t *fnMddT2, *fnMddT3;	/* mdd_t structure to calculate sizes */
+  bdd_gen *gen;
+  array_t *cube, *namesArray;
+  lsGen listGen;
+  int i, literal;
+  Ntk_Node_t *nodePtr;
+
+  /* make bdd_ts of the two functions */
+  bdd_ref(fn2);
+  fnMddT = bdd_construct_bdd_t(mgr, fn2);
+  bdd_ref(fn1);
+  fnMddT1 = bdd_construct_bdd_t(mgr, fn1);
+  fnMddT2 = bdd_not(fnMddT1);
+  /* extracts some cubes in the intersection of fn1' and fn2 */
+  fnMddT3 = bdd_intersects(fnMddT, fnMddT2);
+  /* check not zero */
+  if (bdd_is_tautology(fnMddT3, 0)) {
+    bdd_free(fnMddT3);
+    bdd_free(fnMddT2);
+    /* extracts some cubes in the intersection of fn2' and fn1 */
+    fnMddT2 = bdd_not(fnMddT);
+    fnMddT3 = bdd_intersects(fnMddT1, fnMddT2);
+  }
+  assert(!bdd_is_tautology(fnMddT3, 0));
+  bdd_free(fnMddT);
+  bdd_free(fnMddT1);
+  bdd_free(fnMddT2);
+
+  /* pick a cube from the xor of fn1 and fn2 */
+  gen = bdd_first_cube(fnMddT3, &cube);
+  bdd_free(fnMddT3);
+
+  /* store the names to be printed out later */
+  namesArray = array_alloc(char *, array_n(cube));
+  Ntk_NetworkForEachCombInput(specNetwork, listGen, nodePtr) {
+    array_insert(char *, namesArray , Ntk_NodeReadMddId(nodePtr),  Ntk_NodeReadName(nodePtr));
+  }
+
+  /* print out the cube */
+  arrayForEachItem(int, cube, i, literal) {
+    if (literal != 2) {
+      (void) fprintf(vis_stdout, "%s ", array_fetch(char *, namesArray, i));
+    }
+  }
+  fprintf(vis_stdout, "\n");
+  arrayForEachItem(int, cube, i, literal) {
+    if (literal != 2) {
+      (void) fprintf(vis_stdout, "%1d", literal);
+    }
+  }
+  fprintf(vis_stdout, "\n");
+  array_free(namesArray);
+  bdd_gen_free(gen);
+  return;
+}
Index: vis_dev/vis-2.3/src/res/res.h
===================================================================
--- vis_dev/vis-2.3/src/res/res.h	(revision 14)
+++ vis_dev/vis-2.3/src/res/res.h	(revision 14)
@@ -0,0 +1,135 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [res.h]
+
+  PackageName [res]
+
+  Synopsis    [Combinational verification by residue arithmetic.]
+
+  Description [This package implements residue verification between two
+  networks. The method used is based on residue arithmetic and the
+  Chinese Remainder theorem. Verification is performed by interpreting
+  the outputs of the circuits as integers and verifying the residues
+  of the outputs with respect to a set of moduli. The choice of moduli
+  is directed by the Chinese Remainder Theorem in order to prove
+  equivalence of the two circuits. This method works well with
+  multipliers and possibly other arithmetic circuits (due to its
+  dependence on residue arithmetic).  Discretion should be exercised
+  in applying this method to general combinational circuits. Residue
+  verification is provided with vis-cu ONLY. It reads both blif and
+  blif-mv files. However, it does NOT support multi-valued
+  variables. Residue verification is primarily for combinational
+  verification, but may be applied to sequential circuits with the
+  same state encoding. The latch outputs are then considered to be
+  combinational inputs of the circuits and the latch inputs and reset
+  are considered to be combinational outputs of the circuits. This
+  package provides some combinational verification also. Some/all of
+  the outputs of the circuit may be verified directly (without using
+  residues). In using both direct and residue verification,
+  verification of arithmetic circuits may become easier. ]
+
+  Author      [Kavita Ravi    <ravi@boulder.colorado.edu> and
+	       Abelardo Pardo <abel@boulder.colorado.edu>]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+  Revision    [$Id: res.h,v 1.22 2002/09/08 23:53:32 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _RES
+#define _RES
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "io.h"
+#include "ord.h"
+#include "ntm.h"
+#include "cmd.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define RES_NETWORK_APPL_KEY "Res_NetworkApplKey"
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [Information for every prime used in the verification.]
+
+******************************************************************************/
+typedef struct PerPrimeInfo {
+  int primeNumber;
+  float cpuTime;
+  int bddSize;
+  bdd_node *residueDd;
+}PerPrimeInfo_t;
+
+
+/**Struct**********************************************************************
+
+  Synopsis [Structure holding the information related to the residual
+  verification.]
+
+******************************************************************************/
+typedef struct Res_ResidueInfo {
+  char  *networkName;                /* Name of the circuit verified */
+  char  *networkNameVerifiedAgainst; /* Name of the circuit verified Against*/
+  int   numInputs;                   /* Number of inputs*/
+  int   numOutputs;                  /* Number of outputs */
+  int   numDirectVerifiedOutputs;
+  float cpuDirectVerif;              /* Cpu time spent in direct 
+				      * verification */ 
+  int   numOfPrimes;                 /* Number of Primes needed for the 
+				      * verification */
+  PerPrimeInfo_t *primeInfoArray;    /* Information stored per prime */
+  int successDirectVerification;     /* Outcome of the direct verification */
+  int success;                       /* Outcome of the verification */
+  bdd_manager *ddManager;		     /* Manager required to free the residue BDDs */
+}Res_ResidueInfo_t;
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN int Res_NetworkResidueVerify(Ntk_Network_t *specNetwork, Ntk_Network_t *implNetwork, int numDirectVerify, array_t *outputOrderArray, st_table *outputNameMatch, st_table *inputNameMatch);
+EXTERN void Res_Init(void);
+EXTERN void Res_End(void);
+EXTERN void Res_ResidueInfoFree(Res_ResidueInfo_t *residue);
+EXTERN void Res_ResidueInfoFreeCallback(void *data);
+EXTERN Res_ResidueInfo_t * Res_NetworkReadResidueInfo(Ntk_Network_t *network);
+EXTERN char * Res_ResidueInfoReadName(Res_ResidueInfo_t *residuePtr);
+EXTERN int Res_ResidueInfoReadNumInputs(Res_ResidueInfo_t *residuePtr);
+EXTERN int Res_ResidueInfoReadNumOutputs(Res_ResidueInfo_t *residuePtr);
+EXTERN int Res_ResidueInfoReadNumDirectVerifiedOutputs(Res_ResidueInfo_t *residuePtr);
+EXTERN int Res_ResidueInfoReadCpuDirectVerif(Res_ResidueInfo_t *residuePtr);
+EXTERN int Res_ResidueInfoReadNumOfPrimes(Res_ResidueInfo_t *residuePtr);
+EXTERN int Res_ResidueInfoReadSuccess(Res_ResidueInfo_t *residuePtr);
+EXTERN void Res_ResidueInfoPrint(Res_ResidueInfo_t *result);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _RES */
Index: vis_dev/vis-2.3/src/res/res.make
===================================================================
--- vis_dev/vis-2.3/src/res/res.make	(revision 14)
+++ vis_dev/vis-2.3/src/res/res.make	(revision 14)
@@ -0,0 +1,5 @@
+CSRC += resLayer.c resCompose.c resSmartVarUse.c res.c resCmd.c \
+resRes.c
+HEADERS += res.h resInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/res/resCmd.c
===================================================================
--- vis_dev/vis-2.3/src/res/resCmd.c	(revision 14)
+++ vis_dev/vis-2.3/src/res/resCmd.c	(revision 14)
@@ -0,0 +1,1127 @@
+/**CFile***********************************************************************
+
+  FileName    [resCmd.c]
+
+  PackageName [res]
+
+  Synopsis [Implements the different commands related to the residue
+  verification.]
+
+  Description [This file provides the wrapper functions for the commands
+  involving the residue verification. The command res_verify receives at least
+  one file describing an implementation and optionally a second one describing
+  a specification of a circuit and a set of different options and calls the
+  procedure to perform residue verification in the two systems. For more
+  detailed information about the command res_verify, see also CommandResVerify]
+
+  Author      [Kavita Ravi    <ravi@duke.colorado.edu> and
+	       Abelardo Pardo <abel@duke.colorado.edu>]
+	       
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "resInt.h" 
+
+static char rcsid[] UNUSED = "$Id: resCmd.c,v 1.58 2010/04/10 00:38:26 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+static jmp_buf timeOutEnv;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandResVerify(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static void TimeOutHandle(void);
+static st_table * ReadMatchingPairs(char *fileName, Ntk_Network_t *ntk1, Ntk_Network_t *ntk2);
+static array_t * ReadOutputOrder(char *fileName, Ntk_Network_t *ntk1);
+static array_t * GenerateDefaultOutputOrder(Ntk_Network_t *specNetwork);
+static int CheckForMultiValueNode(Ntk_Network_t *network);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Initializes the Residue Verification package.]
+
+  SideEffects []
+
+  SeeAlso     [Tst_End]
+
+******************************************************************************/
+void
+Res_Init(void)
+{
+  Cmd_CommandAdd("res_verify", CommandResVerify, /* doesn't changes_network */ 0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Ends the residue verification package.]
+
+  SideEffects []
+
+  SeeAlso     [Tst_Init]
+
+******************************************************************************/
+void
+Res_End(void)
+{
+  /*
+   * For example, free any global memory (if any) which the test package is
+   * responsible for.
+   */
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the res_verify command.]
+
+  CommandName [res_verify]
+
+  CommandSynopsis [Verifies a combinational circuit using residue
+  arithmetic.]
+
+  CommandArguments [\[-b\] \[-d &lt;n&gt;\]
+  \[-h\] -i &lt;filename&gt; \[-m &lt;filename&gt;\] \[-n
+  &lt;filename&gt;\] {-o &lt;filename&gt; | -O} \[-s &lt;filename&gt;\] \[-t
+  &lt;timeOut&gt;\] ]
+  
+  CommandDescription [This command performs residue verification between two
+  networks. The method used is based on residue arithmetic and the Chinese
+  Remainder theorem; it is
+  described in [1\] ftp://vlsi.colorado.edu/pub/fmcad96.ps.
+  Verification is performed
+  by interpreting the outputs of the circuits  as integers
+  and verifying the residues of the outputs  with respect to a set of
+  moduli. The choice of moduli is directed  by the Chinese Remainder Theorem in order
+  to prove equivalence of the two circuits. This method works well with multipliers
+  and possibly other arithmetic circuits (due to its  dependence on residue
+  arithmetic).
+  For the same reason, it is necessary to specify an output order
+  which determines how the outputs are interpreted as integers.
+  Discretion should be exercised in applying this method to general combinational
+  circuits.
+
+  <p>
+  Residue verification is available only if vis is linked with the cu
+  BDD package. (This is the default.) It reads both
+  blif and blif-mv files. However, it does NOT support multi-valued
+  variables. Residue verification is primarily for combinational
+  verification, but may be applied to sequential circuits with the
+  same state encoding. The latch outputs are then considered to be combinational inputs of the
+  circuits and the latch inputs and reset are considered to be combinational
+  outputs of the circuits. 
+  
+  <p>
+  There are two ways to perform residue verification in this package. As a first option, two
+  files describing two networks, the specification and the implementation, (in
+  the same format, blif or blif-mv, see option -b) are given in the command
+  line; the procedure
+  tries to verify the equivalence of the combinational outputs as functions of
+  the combinational inputs.
+
+  <p>
+
+  <code>
+  vis> res_verify -o network.order -i network1.blif -s network2.blif <br>
+  </code>
+
+  <p>
+
+  In this case both networks are read in, flattened and the verification is
+  performed between the combinational outputs of both networks. The <tt>-i</tt>
+  option denotes the implementation file and the <tt>-s</tt> option denotes
+  the specification file. The -o option specifies
+  the order of outputs for the circuits (See Command Options below for detailed
+  explanation).
+  
+
+  <p> 
+  A second way to perform the verification is as follows. The specification
+  network is taken from a hierarchy  already read into VIS.  Then the <tt>res_verify </tt>
+  command compares that specification against an implementation network obtained from
+  the file in the command line. Any previous verification, performed with the
+  specification, can be used towards the
+  next verification task only if the same implementation circuit is being verified
+  against and the same number of outputs have been  directly verified with sucess
+  in the previous attempt. The typical sequence of commands given to perform such
+  task would be:
+
+  <p>
+  <code> 
+  vis> read_blifmv network1.mv <br>
+  vis> flatten_hierarchy  <br>
+  vis> res_verify -o network.order -i network2.mv <br>
+  </code>
+
+  <p>
+  
+  If the hierarchy has been read but no flattened network exists at the current
+  node, the command will return without doing anything.
+
+  If one of the networks used is the one in the current node in the hierarchy,
+  then the information regarding the verification process will be stored in
+  that network.
+
+  <p>
+  <B> Note: </b>
+  It is important to keep the specification distinct from the implementation
+  because most  parameters specified for the <tt> res_verify </tt> command
+  are with respect to the specification. For example, the output order 
+  is specified with respect to the specification.
+  The file that is read in first in the second format, is considered to be the specification. 
+
+  <p>
+  There is an option to directly verify some outputs by building the
+  BDDs for the corresponding outputs of the 2 circuits. In that case,
+  if the user wants to use an initial ordering, the only way to do it is
+  the second method and reading in the network, one may specify the initial
+  order using static order.
+
+  <p> 
+  The command does not repeat residue verification if the same
+  specification-implementation pair have been 
+  verified with success and the same number of directly verified
+  outputs have been verified in the previous attempt.
+
+  <p>
+  <b> Relevant flags to be set using the set command: </b> <p>
+  <dl> 
+  <dt> <b> residue_verbosity </b>
+  <dd> Default is 0, turns on verbosity to the desired level between 0 and 5. 
+
+  <dt> <b> residue_ignore_direct_verified_outputs </b>
+  <dd> Default 0 (FALSE). If 1, then ignores directly verified outputs
+  during residue verification. 
+
+  <dt> <b> residue_top_var </b>
+  <dd> Default "msb". The 2 possible values are "msb" and lsb"; this puts
+  the most/least significant bit near the top or bottom of the residue decision diagram.
+  
+  <dt> <b> residue_autodyn_residue_verif </b>
+  <dd> Default 0 (FALSE). If 1, turns on dynamic reordering during residue
+  verification.
+  
+  <dt> <b> residue_residue_dyn_method </b>
+  <dd> Default "groupsift". Specifies the method for dynamic reordering during
+  residue verification. Other methods supported are "same" (same as before),
+  "none", "random", "randompivot", "sift", "siftconverge", "symmsiftconverge",
+  "symmsift", "window2", "window3", "window4", "window2converge",
+  "window3converge", "window4converge", "groupsift", "groupsiftconverge",
+  "anneal", "genetic", "linear", "linearconverge", "exact". 
+
+  <dt> <b> residue_autodyn_direct_verif </b>
+    <dd> Default 0 (FALSE). If 1, turns on dynamic reordering during direct
+  verification.
+  
+  <dt> <b> residue_direct_dyn_method </b>
+  <dd> Default "groupsift". Specifies the method for dynamic reordering during
+  direct verification. Other methods supported are "same" (same as before),
+  "none", "random", "randompivot", "sift", "siftconverge", "symmsiftconverge",
+  "symmsift", "window2", "window3", "window4", "window2converge",
+  "window3converge", "window4converge", "groupsift", "groupsiftconverge",
+  "anneal", "genetic", "linear", "linearconverge", "exact".
+  
+  <dt> <b> residue_layer_schedule </b>
+  <dd> Default "alap". This is a flag to specify the layering strategy of the
+  networks. The 2 options are "asap" (as soon as possible) and "alap" (as
+  late as possible).
+
+  <dt> <b> residue_layer_size </b>
+  <dd> Default largest layer size in network. Specifies the maximum layer
+  size  that can be composed in (relevant for vector composition only).
+  
+  <dt> <b> residue_composition_method </b>
+  <dd> Default "vector". Specifies the composition method to be used in
+  composing the network into the residue ADD. The options are "vector",
+  "onegate", "preimage" and "superG".
+  <p>
+  </dl>
+  
+  <b> Command Options: </b> <br>
+
+  <dl>
+
+  <dt> -b 
+  <dd> If this option is specified, the specification and the implementation
+  files read  are considered to be in blif-mv format. Default is blif
+  format. <p>
+
+  <dt> -d n
+  <dd> This option specifies the number of outputs to be directly verified.
+  That is, for <tt> n </tt> least significant outputs of the circuit, this command
+  performs like comb_verify.
+  The actual outputs are read off the output order array.
+  Since the output order array is specified starting with the MSB, the number of
+  directly verified outputs will be a chunk of the bottom part of the output order array.
+  The option "-d all" sets the number of directly verified outputs to the
+  number of combinational outputs in the circuit i.e., all outputs are directly
+  verified.
+  The direct verification for small BDD sizes is faster and overall reduces
+  the number of primes to be used in residue verification. In general,
+  one output is checked at a time against the corresponding output of the
+  other network and consequently , this method may be fast and use less memory
+  resources.<br>
+  IMPORTANT: It is possible to specify an initial order for the direct
+  verification. This is done by reading in the specification file and using
+  static_order to specify the initial order. The implementation will get
+  the same order as the specification. When specifying the initial order,
+  one must be careful not to specify the -s option in the res_verify command.
+  The -s option reads in the specification file again and the initial order
+  is lost.  <p> 
+  
+  <dt> -h 
+  <dd> Print the command usage.<p> 
+
+  <dt> -i &lt;filename&gt; 
+  <dd> Implementation network to perform verification against. The file must be
+  in blif format unless <tt>-b</tt> is specified, in which case the file is
+  taken to be in blif-mv format. The blif format is the default.<p>
+
+  <dt> -m &lt;filename&gt; 
+  <dd> Optional file name specifying the matching pair of output names between
+  the two networks. If not specified, it is assumed that all outputs have
+  identical names. This option is useful when verifying two circuits whose
+  output names do not match. The file will give pairs of the form <tt>name1
+  name2</tt> to be considered as corresponding  outputs in the verification
+  process. In each pair, <tt> name1 </tt> may belong to the specification
+  and <tt> name2 </tt> to the implementation or vice-versa. The matching
+  procedure is not capable of dealing with some
+  special situations. For example, when two outputs, one of each network have the same
+  name, they must correspond to the same output. Partial orders may not be specified. <p> 
+
+  <dt> -n &lt;filename&gt; 
+  <dd> Optional file name specifying the matching pair of input names between
+  the two networks. If not specified, it is assumed that all inputs have
+  identical names. This option is useful when verifying two circuits whose
+  input  names do not match. The file will give pairs of the form <tt>name1
+  name2</tt> to be considered as corresponding  inputs in the verification
+  process. In each pair, <tt> name1 </tt> may belong to the specification
+  and <tt> name2 </tt> to the implementation or vice-versa. The matching
+  procedure is not capable of dealing with some
+  special situations. For example, when two inputs, one of each network have the same
+  name, they must correspond to the same input. Partial orders may not be specified. <p> 
+
+  <dt> -o &lt;filename&gt;
+  <dd> Required file  specifying output order, starting with the MSB.
+  The file must be a list of output names separated by spaces. 
+  The list must belong to the specification network and must contain a
+  full order i.e., must contain all the combinational output names.  It is advisable to use
+  the -o option as far as possible to specify the order
+  of the outputs.See also -O option.<p> 
+
+  <dt> -O
+  <dd> This option specifies whether the <code> res_verify </code> command should
+  generate a default
+  order for the outputs. If the -o option is not used, this option must be specified.
+  The default order generated is random and is NOT the same as the input files.
+  The set of outputs for the output order may be generated by using the print_network
+  command to write the network into a file and extract the node name from the  lines containing the word
+  "comb-output". The set of outputs can then be ordered as required.  <br>
+  It is advisable to use the -o option as far as possible to specify the order
+  of the outputs. The -o option overrides the -O option. See also -o option.<p>
+  
+  <dt> -s &lt;filename&gt; 
+  <dd> Specification network. This network will be taken as the specification
+  of the circuit. The result of the computation will be stored in this network.
+  If this network is not provided, the current node of the
+  hierarchy will be taken. The file must contain a blif description of a
+  circuit unless the option <tt>-b</tt> is specified, in which case the file is
+  considered in blif-mv format. If two networks are specified in the
+  command line, both of them must have the same format, either blif or
+  blif-mv. The blif format is the default.<p>
+
+  <dt> -t &lt;timeOut &gt;
+
+  <dd> Execution time in seconds allowed for verification before aborting.  The
+  default is no limit.<p>
+
+  </dl>
+  ]
+
+  SideEffects [It registers the information about the verification in the
+  specification if this is the current node in the hierarchy manager.]
+
+  SeeAlso            [Res_NetworkResidueVerify]
+
+******************************************************************************/
+static int
+CommandResVerify(Hrc_Manager_t ** hmgr,
+		 int  argc,
+		 char ** argv)
+{
+  static int           timeOutPeriod; /* CPU seconds allowed */
+  static array_t       *outputOrderArray;   /* required to specify the outputs
+				       * starting with MSB first */
+  static Hrc_Manager_t *implHmgr;     /* Auxiliary hierarchy manager */
+  static Hrc_Manager_t *specHmgr;     /* Auxiliary hierarchy manager */
+  static Hrc_Node_t    *currentNode;  /* node in the hierarchy */
+  static Ntk_Network_t *specNetwork;  /* spec network */
+  static Ntk_Network_t *implNetwork;  /* implementation network */
+  static st_table      *inputMatch;   /* List of pairs of input name match */
+  static st_table      *outputMatch;  /* List of pairs of output name match */
+  int                  outputsToVerifyDirectly; /* number of outputs to
+						 * directly verify
+						 */
+  int                  c;             /* To process the command line options */
+  /* Flush previous verification if any */
+  int                  success;       /* Outcome of the verification */
+  int                  status;        /* Status of the call to the function */
+  char                 *specFileName;  /* File to read the specification from */
+  char                 *impFileName;  /* File to read the implementation from */
+  char                 *fileMatchOut; /* File specifying the output matching */
+  char                 *fileMatchIn;  /* File specifying the input matching */
+  char                 *fileOutputOrder; /*file name that contains the order of
+					   outputs starting with MSB */
+  boolean              isInBlifMv;    /* Format to be read in */
+  st_generator         *stGen;        /* generator to step through the table */
+  char                 *key, *value;  /* variables for the st_table */
+  int i;
+  int defaultOutputOrder;             /* flag to indicate default order to
+				       * be taken, if no output order file
+				       * is specified
+				       */
+  char                 *strptr;       /* variable to hold return value
+				       * of strtol
+				       */
+  int                  allFlag;
+  
+  if (bdd_get_package_name() != CUDD) {
+    fprintf(vis_stdout, "** res error: Residue Verification is available with the CUDD package only.\n");
+    return 0;
+  }
+  /* Default values for some variables */
+  timeOutPeriod = 0;
+  allFlag = 1;
+  outputsToVerifyDirectly = 0;
+  outputOrderArray = NIL(array_t);
+  implHmgr = NIL(Hrc_Manager_t);
+  specHmgr = NIL(Hrc_Manager_t);
+  currentNode = NIL(Hrc_Node_t);
+  specNetwork = NIL(Ntk_Network_t);
+  implNetwork = NIL(Ntk_Network_t);
+  inputMatch = NIL(st_table);
+  outputMatch = NIL(st_table);
+  impFileName = NIL(char);
+  specFileName = NIL(char);
+  isInBlifMv = FALSE;
+  fileMatchOut = NIL(char);
+  fileMatchIn = NIL(char);
+  status = 1;
+  fileOutputOrder = NIL(char);
+  defaultOutputOrder = 0;
+  
+  /*
+   * Parse command line options.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "bd:hi:m:n:o:Os:t:")) != EOF) {
+    switch(c) {
+    case 'b':
+      isInBlifMv = TRUE;
+      break;
+    case 'd':
+      /* number of outputs to verify directly */
+      /*      outputsToVerifyDirectly = atoi(util_optarg); */
+      outputsToVerifyDirectly = (int)strtol(util_optarg, &strptr, 0);
+      allFlag = strcmp(util_optarg, "all");
+      break;
+    case 'h':
+      goto usage;
+    case 'i':
+      impFileName = util_optarg;
+      break;
+    case 'm':
+      fileMatchOut = util_optarg;
+      break;
+    case 'n':
+      fileMatchIn = util_optarg;
+      break;
+    case 'o':
+      fileOutputOrder = util_optarg;
+      break;
+    case 'O':
+      defaultOutputOrder = 1;
+      break;
+    case 's':
+      specFileName = util_optarg;
+      break;
+    case 't':
+      timeOutPeriod = atoi(util_optarg);
+      break;
+    default:
+      goto usage;
+    }
+  }
+
+  /* Obtain the Specification network either from file or hierarchy manager */
+  if (specFileName != NIL(char)) {
+
+    /* Read blif or blif-mv depending on the flag */
+    error_init();
+    if (isInBlifMv) {
+      FILE *fp; /* Used to read from files */
+
+      /* Open the file */
+      fp = Cmd_FileOpen(specFileName, "r", NIL(char *), TRUE);
+      if (fp != NULL) {
+	specHmgr = Io_BlifMvRead(fp, NIL(Hrc_Manager_t),
+				 0, /* No Cannonical */
+				 0, /* No incremental */
+				 0  /* No verbosity */);
+	fclose(fp);
+      } else {
+	fprintf(vis_stderr, "** res error: Specification file required(may not exist in path)\n");
+	goto usage;
+      }
+
+    } /* End of then */ 
+    else {
+      specHmgr = Io_BlifRead(specFileName, 0 /* No verbosity */);
+    } /* End of if-then-else */
+
+    /* Check if the read has been performed correctly */
+    if (specHmgr == NIL(Hrc_Manager_t)) {
+      (void) fprintf(vis_stderr, "%s", error_string());
+      (void) fprintf(vis_stderr, "Cannot read blif file %s.\n", impFileName);
+      goto cleanup;
+    }
+    
+    /* Hierarchy manager successfully created */
+    error_init();
+    currentNode = Hrc_ManagerReadCurrentNode(specHmgr);
+    specNetwork = Ntk_HrcNodeConvertToNetwork(currentNode, TRUE, (lsList)0);
+    if (specNetwork == NIL(Ntk_Network_t)) {
+      (void) fprintf(vis_stderr, "%s", error_string());
+      (void) fprintf(vis_stderr, "Cannot perform flatten_hierarchy.\n");
+      goto cleanup;
+    }
+  } else {
+    /* Check if any circuit has been read in */
+    currentNode = Hrc_ManagerReadCurrentNode(*hmgr);
+    if (currentNode == NIL(Hrc_Node_t)) {
+      (void) fprintf(vis_stderr, "The hierarchy manager is empty. ");
+      (void) fprintf(vis_stderr, "Read in design.\n");
+      goto cleanup;
+    }
+
+    /* Check if the network has been created with flatten_hierarchy */
+    specNetwork = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+    if (specNetwork == NIL(Ntk_Network_t)) {
+      goto cleanup;
+    } /* End of if */
+  }
+
+  /* Obtain the implementation network from file */
+  if (impFileName != NIL(char)) {
+
+    /* Read blif or blif-mv depending on the flag */
+    error_init();
+    if (isInBlifMv) {
+      FILE *fp; /* Used to read from files */
+
+      /* Open the file */
+      fp = Cmd_FileOpen(impFileName, "r", NIL(char *), TRUE);
+
+      if (fp != NULL) {
+	implHmgr = Io_BlifMvRead(fp, NIL(Hrc_Manager_t),
+				 0, /* No Cannonical */
+				 0, /* No incremental */
+				 0  /* No verbosity */);
+	fclose(fp);
+      } else {
+	fprintf(vis_stderr, "** res error: Implementation file required(may not exist in path)\n");
+	goto usage;
+      }
+
+    }  else { /* End of then */
+      implHmgr = Io_BlifRead(impFileName, 0 /* No verbosity */);
+    } /* End of if-then-else */
+
+    /* Check if the read has been performed correctly */
+    if (implHmgr == NIL(Hrc_Manager_t)) {
+      (void) fprintf(vis_stderr, "%s", error_string());
+      (void) fprintf(vis_stderr, "Cannot read blif file %s.\n", impFileName);
+      goto cleanup;
+    }
+    
+    /* Hierarchy manager successfully created */
+    error_init();
+    currentNode = Hrc_ManagerReadCurrentNode(implHmgr);
+    implNetwork = Ntk_HrcNodeConvertToNetwork(currentNode, TRUE, NULL);
+    if (implNetwork == NIL(Ntk_Network_t)) {
+      (void) fprintf(vis_stderr, "%s", error_string());
+      (void) fprintf(vis_stderr, "Cannot perform flatten_hierarchy.\n");
+      goto cleanup;
+    }
+  }
+  else {
+    /* The option -1 has not been provided in the command line */
+    goto usage;
+  }
+  /* At this point both networks have been built */
+
+  /* Check that no node in the two network is multi-valued */
+  if (CheckForMultiValueNode(specNetwork)) {
+    fprintf(vis_stderr, "** res error: Specification has multivalued network\n");
+    fprintf(vis_stderr, "** res error: Residue verification does not support multi-valued variables, variables have to be binary.\n");
+    goto cleanup;
+  }
+  if (CheckForMultiValueNode(implNetwork)) {
+    fprintf(vis_stderr, "** res error: Implementation has multivalued network\n");
+    fprintf(vis_stderr, "** res error: Residue verification does not support multi-valued variables, variables have to be binary.\n");
+    goto cleanup;
+  }
+  
+  /* Check that both networks have the same number of inputs and outputs */
+  if ((Ntk_NetworkReadNumCombInputs(implNetwork) != 
+       Ntk_NetworkReadNumCombInputs(specNetwork)) ||
+      (Ntk_NetworkReadNumCombOutputs(implNetwork) != 
+       Ntk_NetworkReadNumCombOutputs(specNetwork))) {
+
+    (void) fprintf(vis_stderr, "** res error: Networks do not have equal number of inputs ");
+    (void) fprintf(vis_stderr, "or outputs\n");
+    goto cleanup;
+  } /* End of if */  
+
+  /* Check if there has been some name matching file provided for outputs. */
+  if (fileMatchOut != NIL(char)) {
+    outputMatch = ReadMatchingPairs(fileMatchOut, implNetwork, specNetwork);
+    if (outputMatch == NIL(st_table)) {
+      (void) fprintf(vis_stderr, "** res error: Error reading Output match file ");
+      (void) fprintf(vis_stderr, "%s\n", fileMatchOut);
+      goto cleanup;
+    } /* End of if */
+  } /* End of if */
+
+  /* Check if there has been some name matching file provided for inputs. */
+  if (fileMatchIn != NIL(char)) {
+    inputMatch = ReadMatchingPairs(fileMatchIn, implNetwork, specNetwork);
+    if (inputMatch == NIL(st_table)) {
+      (void) fprintf(vis_stderr, "** res error: Error reading Input match file ");
+      (void) fprintf(vis_stderr, "%s\n", fileMatchIn);
+      /* Clean up */
+      goto cleanup;
+    } /* End of if */
+  } /* End of if */
+
+  /* Transfer names of outputs starting with MSB from the file to an
+   * array_t
+   */
+  if (fileOutputOrder != NIL(char)) {
+    outputOrderArray = ReadOutputOrder(fileOutputOrder, specNetwork);
+  } else if (defaultOutputOrder) {
+    outputOrderArray = GenerateDefaultOutputOrder(specNetwork);
+  }
+    
+  if (outputOrderArray == NIL(array_t)) {
+    /* Clean up */
+    fprintf(vis_stderr, "** res error: Output order(msb first) required for residue method.\n");
+    goto usage;
+  } else if  (array_n(outputOrderArray) != Ntk_NetworkReadNumCombOutputs(specNetwork)) {
+    fprintf(vis_stderr, "** res error: Number of Outputs seem to be %d\n", Ntk_NetworkReadNumCombOutputs(specNetwork));
+    fprintf(vis_stderr, "** res error: The output order seems to contain %d outputs\n", array_n(outputOrderArray));
+    fprintf(vis_stderr, "** res error: Partial Orders or mismatch in the above two numbers is not allowed in the -o option\n");
+    goto usage;
+  }
+  /* Start the timer before calling the verifyer */
+  if (timeOutPeriod > 0) {
+    (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
+    (void) alarm(timeOutPeriod);
+
+    /* The second time setjmp is called, it returns here !!*/
+    if (setjmp(timeOutEnv) > 0) {
+      (void) fprintf(vis_stdout, "Residue Verification timeout occurred after%d seconds.\n", 
+		     timeOutPeriod);
+      alarm(0);
+
+      /* Note that there is a huge memory leak here. */
+      goto cleanup;
+    } /* End of if */
+  }
+
+  /* number of outputs to directly verify should be less than the
+   * number of outputs for the circuit. If all flag set, number of
+   * directly verified circuit, set it to number of combinational
+   * outputs.
+   */
+  if (allFlag == 0) {
+    outputsToVerifyDirectly = Ntk_NetworkReadNumCombOutputs(specNetwork);
+  }
+  if (outputsToVerifyDirectly > Ntk_NetworkReadNumCombOutputs(specNetwork)) {
+    fprintf(vis_stderr, "** res error: More outputs to directly verify than that exist in the circuit\n");
+    goto usage;
+  }
+    
+  error_init();
+
+
+  /* main procedure for residue verification */
+  status = Res_NetworkResidueVerify(specNetwork,
+				    implNetwork,
+				    outputsToVerifyDirectly,
+				    outputOrderArray,
+				    outputMatch,
+				    inputMatch);
+    
+  /* Deactivate the alarm */
+  alarm(0);
+  
+  /* If the computation succeded store the result in specNetwork */
+  if (status == 0) {
+    Res_ResidueInfo_t *residueInfo;
+
+    residueInfo = (Res_ResidueInfo_t *) Ntk_NetworkReadApplInfo(specNetwork, 
+								RES_NETWORK_APPL_KEY);
+
+    /* Print out the error string in case success is false */
+    success = Res_ResidueInfoReadSuccess(residueInfo);
+    switch (success) {
+    case FALSE:
+      (void) fprintf(vis_stdout, "Residue Verification failed !\n");
+      break;
+    case TRUE:
+      (void) fprintf(vis_stdout, "Residue Verification successful\n");
+      break;
+    default:
+      (void) fprintf(vis_stderr, "** res error: Residue Verification unable to produce ");
+      (void) fprintf(vis_stderr, "result\n");
+      break;
+    }
+  } else {
+    (void) fprintf(vis_stderr, "%s", error_string());
+  }
+
+  /* Clean up */
+  error_cleanup();
+  goto cleanup;
+  
+    /* update with all functions */
+usage:
+  (void) fprintf(vis_stderr, "usage: res_verify [-b]  ");
+  (void) fprintf(vis_stderr, "[-d n] [-h] -i impl file\n       ");
+  (void) fprintf(vis_stderr, "[-m file] [-n file] -o file [-s spec file] ");
+  (void) fprintf(vis_stderr, "[-t secs]\n");
+  (void) fprintf(vis_stderr, "   -b        The file format to be read is ");
+  (void) fprintf(vis_stderr, "blif-mv (default is blif)\n");
+  (void) fprintf(vis_stderr, "   -d n      Number of outputs to verify ");
+  (void) fprintf(vis_stderr, "directly\n");
+  (void) fprintf(vis_stderr, "   -h        Print the usage of the command\n");
+  (void) fprintf(vis_stderr, "   -i impl   Implementation file (required)\n");
+  (void) fprintf(vis_stderr, "   -m file   File specifying the matching pair ");
+  (void) fprintf(vis_stderr, "of names for the outputs\n");
+  (void) fprintf(vis_stderr, "   -n file   File specifying the matching pair");
+  (void) fprintf(vis_stderr, " of names for the inputs\n");
+  (void) fprintf(vis_stderr, "   -o        Output order starting with MSB (required or -O required)\n");
+  (void) fprintf(vis_stderr, "   -O        Default output order (required or -o required)\n");
+  (void) fprintf(vis_stderr, "   -s file   Specification File\n");
+  (void) fprintf(vis_stderr, "   -t secs   Seconds allowed for computation\n");
+
+  
+  /* Clean up */
+cleanup:
+  if ((specFileName == NIL(char)) && (specHmgr != NIL(Hrc_Manager_t))) {
+    int zerorefcountbdds;
+    bdd_manager *ddManager;
+    Hrc_ManagerFree(specHmgr);
+    if (specNetwork != NIL(Ntk_Network_t)) {
+      ddManager = (bdd_manager *)Ntk_NetworkReadMddManager(specNetwork);
+      if (ddManager != NIL(bdd_manager)) {
+	zerorefcountbdds = bdd_check_zero_ref((bdd_manager *)Ntk_NetworkReadMddManager(specNetwork));
+	if (zerorefcountbdds) {
+	  fprintf(vis_stdout, "Number of Nodes with non zero ref count are %d\n", zerorefcountbdds);
+	  fprintf(vis_stdout, "Size of DD manager = %d\n", bdd_num_vars(ddManager));
+	}
+      }
+    }
+    Ntk_NetworkFree(specNetwork);
+  }
+  if (implHmgr != NIL(Hrc_Manager_t)) {
+    Hrc_ManagerFree(implHmgr);
+    /* dont free manager if not set here */
+    if ((specNetwork != NIL(Ntk_Network_t)) &&
+	((bdd_manager *)Ntk_NetworkReadMddManager(specNetwork) != NIL(bdd_manager))) {
+      Ntk_NetworkSetMddManager(implNetwork, NIL(bdd_manager));
+    }
+    Ntk_NetworkFree(implNetwork);
+  }
+  if (outputMatch != NIL(st_table)) {
+    st_foreach_item(outputMatch, stGen, &key, &value) {
+      /* free only the key, cos the value appears as a key also */
+      FREE(key);
+    }
+    st_free_table(outputMatch);
+  } /* End of if */
+  if (inputMatch != NIL(st_table)) {
+    st_foreach_item(inputMatch, stGen, &key, &value) {
+      /* free only the key, cos the value appears as a key also */
+      FREE(key);
+    }
+    st_free_table(inputMatch);
+  }
+  if (outputOrderArray != NIL(array_t)) {
+    char * name;
+    arrayForEachItem(char *, outputOrderArray, i, name) {
+      FREE(name);
+    }
+    array_free(outputOrderArray);
+  }    
+  return status;
+}  /* End of CommandResVerify */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Handle the timeout signal.]
+
+  Description [This function is called when the time out occurs. In principle
+  it could do something smarter, but so far it just transfers control to the
+  point in the code where setjmp was called.]
+
+  SideEffects [This function gains control at any point in the middle of the
+  computation, therefore the memory allocated so far leaks.]
+
+******************************************************************************/
+static void
+TimeOutHandle(void)
+{
+  longjmp(timeOutEnv, 1);
+} /* End of TimeOutHandle */
+
+/**Function********************************************************************
+
+  Synopsis           [Builds a table with the pairs of names given in a file.]
+
+  Description [Given a file, it opens the and reads lines of the form <tt>name1
+  name2</tt> and stores the pairs (name1, name2) and (name2, name1) in a table
+  that returns as result.]
+  
+  SideEffects        []
+  
+  SeeAlso            [CommandResVerify]
+
+******************************************************************************/
+static st_table *
+ReadMatchingPairs(char *fileName,
+		  Ntk_Network_t *ntk1,
+		  Ntk_Network_t *ntk2)
+{
+  st_table *result = NIL(st_table);
+  int check;
+  char name1[80], name2[80]; /* Note the size of buffer is used in fscanf */
+  char *ptr1, *ptr2;
+  FILE *fp;
+#if HAVE_MKSTEMP && HAVE_CLOSE
+  int  fd;
+#else
+  char buffer[512];
+#endif
+  char *realFileName, *blifMvFileName, *visDirectoryName;
+  char command[512];
+  int cmdStatus;
+  
+  fp = Cmd_FileOpen(fileName, "r", &realFileName, 1 /* silent */);
+  
+  if (fp == NIL(FILE)) {
+    FREE(realFileName);
+    (void) fprintf(vis_stderr, "** res error: Cannot open %s to read.\n", fileName);
+    return result;
+  } /* End of if */
+  
+  if (fp != stdin){
+    (void)fclose(fp);
+  }  
+
+#if HAVE_MKSTEMP && HAVE_CLOSE
+  blifMvFileName = util_strsav("/tmp/vis.XXXXXX");
+  fd = mkstemp(blifMvFileName);
+  if (fd == -1){
+#else
+  blifMvFileName = util_strsav(tmpnam(buffer));
+  if (blifMvFileName == NIL(char)){
+#endif
+    FREE(realFileName);
+    (void)fprintf(vis_stderr,"** res error: Could not create temporary file. ");
+    (void)fprintf(vis_stderr,"** res error: Clean up /tmp an try again.\n");
+    return NIL(st_table);
+  }
+#if HAVE_MKSTEMP && HAVE_CLOSE
+  close(fd);
+#endif
+   /* Invoking an awk script */
+  visDirectoryName = Vm_VisObtainLibrary();
+  (void)sprintf(command,"sed 's/^\\./@/g' %s | sed 's/\\./$/g' | sed 's/^@/\\./g' | sed 's/{/</g' | sed 's/}/>/g'| sed 's/(/<</g' | sed 's/)/>>/g' > %s", realFileName, blifMvFileName);
+  /* the following is missing two new sed processings 
+  (void)sprintf(command,"sed 's/^\\./@/g' %s | sed 's/\\./$/g' | sed 's/^@/\\./g' | sed 's/{/</g' | sed 's/}/>/g'| %s -f %s/ioBlifToMv.nawk > %s", realFileName, NAWK, visDirectoryName, blifMvFileName);
+  */
+  cmdStatus = system(command);
+  FREE(visDirectoryName);
+  FREE(realFileName);
+  if (cmdStatus != 0) {
+    return NIL(st_table);
+  }
+
+  fp = Cmd_FileOpen(blifMvFileName, "r", NIL(char *), 1);
+  assert(fp != NIL(FILE));
+
+
+  result = st_init_table(st_ptrcmp, st_ptrhash);
+  while (!feof(fp)) {
+    check = fscanf(fp, "%80s %80s", name1, name2);
+    if (check != 2 && check != EOF) {
+      st_free_table(result);
+      result = NIL(st_table);
+      return result;
+    } /* End of if */
+    
+    if (Ntk_NetworkFindNodeByName(ntk1, name1) == NIL(Ntk_Node_t) &&
+	Ntk_NetworkFindNodeByName(ntk2, name1) == NIL(Ntk_Node_t)) {
+      (void) fprintf(vis_stderr, "** res error: While reading matching file. ");
+      (void) fprintf(vis_stderr, "** res error: Node %s not found in any of the networks.\n", 
+		     name1);
+      st_free_table(result);
+      result = NIL(st_table);
+      return result;
+    }
+    
+    if (Ntk_NetworkFindNodeByName(ntk1, name2) == NIL(Ntk_Node_t) &&
+	Ntk_NetworkFindNodeByName(ntk2, name2) == NIL(Ntk_Node_t)) {
+      (void) fprintf(vis_stderr, "** res error: While reading matching file. ");
+      (void) fprintf(vis_stderr, "** res error: Node %s not found in any of the networks.\n", 
+		     name2);
+      st_free_table(result);
+      result = NIL(st_table);
+      return result;
+    }
+
+    ptr1 = util_strsav(name1);
+    ptr2 = util_strsav(name2);
+    st_insert(result, ptr1, ptr2);
+    st_insert(result, ptr2, ptr1);
+  } /* End of while */
+  
+  fclose(fp);
+#if HAVE_UNLINK
+  unlink(blifMvFileName);
+#endif
+  FREE(blifMvFileName);
+
+  return result;
+} /* End of ReadMatchingPairs */
+
+/**Function********************************************************************
+  
+  Synopsis           [Builds an array with the names given in a file.]
+
+  Description [Given a file, it opens the and reads lines of the form <tt>name1
+  and stores the name1 in an array that returns as result.]
+
+  SideEffects        []
+
+  SeeAlso            [CommandResVerify]
+
+******************************************************************************/
+static array_t *
+ReadOutputOrder(char *fileName,
+		Ntk_Network_t *ntk1)
+{
+  FILE *fp;
+#if HAVE_MKSTEMP && HAVE_CLOSE
+  int  fd;
+#else
+  char buffer[512];
+#endif
+  array_t *result = NIL(array_t);
+  int check;
+  char name1[80]; /* Note the size of buffer is used in fscanf */
+  char *ptr1;
+  char *realFileName, *blifMvFileName, *visDirectoryName;
+  char command[512];
+  int cmdStatus;
+  
+  fp = Cmd_FileOpen(fileName, "r", &realFileName, 1 /* silent */);
+  
+  if (fp == NIL(FILE)) {
+    FREE(realFileName);
+    (void) fprintf(vis_stderr, "** res error: Cannot open %s to read.\n", fileName);
+    return result;
+  } /* End of if */
+
+  if (fp != stdin){
+    (void)fclose(fp);
+  }  
+
+#if HAVE_MKSTEMP && HAVE_CLOSE
+  blifMvFileName = util_strsav("/tmp/vis.XXXXXX");
+  fd = mkstemp(blifMvFileName);
+  if (fd == -1){
+#else
+  blifMvFileName = util_strsav(tmpnam(buffer));
+  if (blifMvFileName == NIL(char)){
+#endif
+    FREE(realFileName);
+    (void)fprintf(vis_stderr,"** res error: Could not create temporary file. ");
+    (void)fprintf(vis_stderr,"** res error: Clean up /tmp an try again.\n");
+    return NIL(array_t);
+  }
+#if HAVE_MKSTEMP && HAVE_CLOSE
+  close(fd);
+#endif
+  /* Invoking an awk script */
+  visDirectoryName = Vm_VisObtainLibrary();
+  (void)sprintf(command,"sed 's/^\\./@/g' %s | sed 's/\\./$/g' | sed 's/^@/\\./g' | sed 's/{/</g' | sed 's/}/>/g'| sed 's/(/<</g' | sed 's/)/>>/g' > %s", realFileName, blifMvFileName);
+  /* the following is missing two new sed processings 
+  (void)sprintf(command,"sed 's/^\\./@/g' %s | sed 's/\\./$/g' | sed 's/^@/\\./g' | sed 's/{/</g' | sed 's/}/>/g'| %s -f %s/ioBlifToMv.nawk > %s", realFileName, NAWK, visDirectoryName, blifMvFileName);
+  */
+  cmdStatus = system(command);
+  FREE(visDirectoryName);
+  FREE(realFileName);
+  if (cmdStatus != 0) {
+    return NIL(array_t);
+  }
+
+  fp = Cmd_FileOpen(blifMvFileName, "r", NIL(char *), 1);
+  assert(fp != NIL(FILE));
+  
+  result = array_alloc(char *, 0);
+  while (!feof(fp)) {
+    check = fscanf(fp, "%80s", name1);
+    if (check != EOF) {
+      if (check != 1) {
+	array_free(result);
+	result = NIL(array_t);
+	return result;
+      } /* End of if */
+      
+      if (Ntk_NetworkFindNodeByName(ntk1, name1) == NIL(Ntk_Node_t)) {
+	(void) fprintf(vis_stderr, "** res error: While reading output order file. ");
+	(void) fprintf(vis_stderr, "** res error: Node %s not found in the network.\n", 
+		       name1);
+	array_free(result);
+	result = NIL(array_t);
+	return result;
+      }
+      ptr1 = util_strsav(name1);
+      array_insert_last(char *, result, ptr1);
+    }
+  } /* End of while */
+#ifdef DEBUG
+  arrayForEachItem(char *,result, i, ptr1) {
+    fprintf(vis_stdout, "%s\n", ptr1);
+  }
+#endif  
+
+  fclose(fp);
+#if HAVE_UNLINK
+  unlink(blifMvFileName);
+#endif
+  FREE(blifMvFileName);
+
+  return result;
+} /* End of ReadMatchingPairs */
+
+
+/**Function********************************************************************
+  
+  Synopsis           [Generates a default output order .]
+
+  Description        [This order is as provided in the file]
+
+  SideEffects        []
+
+  SeeAlso            [CommandResVerify]
+
+******************************************************************************/
+static array_t *
+GenerateDefaultOutputOrder(Ntk_Network_t *specNetwork)
+{
+  array_t *outputOrderArray;
+  lsGen listGen;
+  Ntk_Node_t *nodePtr;
+  char *name, *ptr1;
+  int i;
+
+  i = 0;
+  outputOrderArray = array_alloc(char *,
+				 Ntk_NetworkReadNumCombOutputs(specNetwork));
+  Ntk_NetworkForEachCombOutput(specNetwork, listGen, nodePtr) {
+    name = Ntk_NodeReadName(nodePtr);
+    ptr1 = util_strsav(name);
+    array_insert(char *, outputOrderArray, i, ptr1);
+    i++;
+  }
+  return outputOrderArray;
+}
+
+/**Function********************************************************************
+  
+  Synopsis           [Checks if the network contains any multi-valued node .]
+
+  Description        [Checks if the network contains any multi-valued node.
+  Returns 0, if none exist and 1 if there are any]
+
+  SideEffects        []
+
+  SeeAlso            [CommandResVerify]
+
+******************************************************************************/
+static int
+CheckForMultiValueNode(Ntk_Network_t *network)
+{
+  lsGen listGen;
+  Ntk_Node_t *nodePtr;
+  Var_Variable_t * var;
+  
+  Ntk_NetworkForEachNode(network, listGen, nodePtr) {
+    var = Ntk_NodeReadVariable(nodePtr);
+    if ((Var_VariableReadNumValues(var) > 2) ||
+	(!Var_VariableTestIsEnumerative(var))) {
+      return 1;
+    }
+  }
+  return 0;
+}
Index: vis_dev/vis-2.3/src/res/resCompose.c
===================================================================
--- vis_dev/vis-2.3/src/res/resCompose.c	(revision 14)
+++ vis_dev/vis-2.3/src/res/resCompose.c	(revision 14)
@@ -0,0 +1,1234 @@
+/**CFile***********************************************************************
+
+  FileName    [resCompose.c]
+
+  PackageName [res]
+
+  Synopsis [This file contains all relevant procedures for the composition of
+  the nodes of the circuit into the residue Add.]
+
+  Author      [Kavita Ravi    <ravi@boulder.colorado.edu> and
+	       Abelardo Pardo <abel@boulder.colorado.edu>]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "resInt.h"
+
+static char rcsid[] UNUSED = "$Id: resCompose.c,v 1.30 2005/04/18 05:00:14 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+long Res_composeTime;
+long Res_shuffleTime;
+long Res_smartVarTime;
+long Res_orderTime;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void UpdateUnassignedNodesWithNewIds(lsList orderList, array_t *newIdArray);
+static lsList CreateNodeAndFaninOrderList(array_t *currentLayer);
+static lsList ListAppend(Ntk_Node_t *nodePtr, lsList newList, lsList faninList);
+static int IdCompare(const void *obj1, const void *obj2);
+static int IdListCompare(lsGeneric item1, lsGeneric item2);
+static lsList CreateFaninVarSetList(array_t *currentLayer, st_table *faninTable);
+static bdd_node * ComposeLayer(bdd_manager *ddManager, bdd_node *residueDd, array_t *currentLayer, bdd_node **functionArray);
+static Mvf_Function_t * NodeBuildConstantMvf(Ntk_Node_t * node, mdd_manager *mddMgr);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+ 
+/**Function********************************************************************
+
+  Synopsis [Return a referenced BDD for the function of a node.]
+
+  Description [Return a referenced BDD for the function of a node. This
+  procedure uses the Ntm call but frees the rest of the MDD structure and
+  returns the bdd only. The arguments to this function are the network to which
+  this node belongs, the node whose bdd is required and the type of fanin
+  support its BDDs need to be in terms of.]
+
+  SideEffects   []
+
+  SeeAlso            [Res_NetworkResidueVerify]
+
+******************************************************************************/
+bdd_node *
+BuildBDDforNode(Ntk_Network_t *network,
+		Ntk_Node_t *nodePtr,
+		int fanin)
+{
+  bdd_node *function;
+  st_table *leaves;
+  array_t *mvfArray;
+  Mvf_Function_t *nodeFunction;
+  Ntk_Node_t *faninNodePtr;
+  lsGen netGen;
+  array_t *root;
+  int j;
+  mdd_manager *mddMgr;
+
+  /* if it is a constant, build the mvf for it */
+  if( Ntk_NodeTestIsConstant(nodePtr) == 1) {
+    mddMgr = (mdd_manager *)Ntk_NetworkReadMddManager(network);
+    nodeFunction = NodeBuildConstantMvf(nodePtr, mddMgr);
+  } else if (Ntk_NodeTestIsCombInput(nodePtr)) {
+    /* the Bdd for a latch input is itself */
+    mddMgr = (mdd_manager *)Ntk_NetworkReadMddManager(network);
+    nodeFunction = Mvf_FunctionCreateFromVariable(mddMgr, Ntk_NodeReadMddId(nodePtr));
+  } else {
+
+    /* Set the root to build the Mvf */
+    root = array_alloc(Ntk_Node_t *, 1);
+    array_insert(Ntk_Node_t *, root, 0, nodePtr);
+    
+    /* Set the leaves depending on the fanin flag*/
+    leaves = st_init_table(st_ptrcmp, st_ptrhash);
+    if (fanin == IMMEDIATE_FANIN) {
+      Ntk_NodeForEachFanin(nodePtr, j, faninNodePtr) {
+	st_insert(leaves, (char *)faninNodePtr, (char *)NTM_UNUSED);
+      }
+    } else if (fanin == PRIMARY_INPUTS) {
+      Ntk_NetworkForEachCombInput(network, netGen, nodePtr) {
+	st_insert(leaves, (char *)nodePtr, (char *)NTM_UNUSED);
+      }
+    }
+	
+    /* Effectively compute the function (We are not using don't cares)*/
+    mvfArray = Ntm_NetworkBuildMvfs(network, root, leaves, NIL(mdd_t));
+    st_free_table(leaves);
+    array_free(root);
+    
+    nodeFunction = array_fetch(Mvf_Function_t *, mvfArray, 0);
+    /* since we built the MDD for only one root */
+    array_free(mvfArray);
+  } /* end of else if not a latch output */
+  /* 
+   * The function above returned a Mvf_Function_t, but since we are 
+   * working with binary nodes (so far), we do not need the Mvf 
+   * representation, therefore we only keep one single Bdd and deallocate
+   * all the memory attached to the rest of the Mvf.
+   */
+  function = (bdd_node *)bdd_extract_node_as_is(Mvf_FunctionReadComponent(nodeFunction, 1));
+  if (function != NULL) {
+    bdd_ref(function);
+  }
+  
+  /* Clean up */
+  Mvf_FunctionFree(nodeFunction);
+  return (function);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Procedure to compose the network into the residue ADD.]
+
+  Description [Procedure to compose the network into the residue ADD.  Assume
+  here that the output nodes are labeled with the same ids as the vars in the
+  initial residue dd. The variable manager has to be initialized for smart
+  variable allocation. First the variable manager is updated with the output
+  node Ids. Starting from the last layer, the nodes in each layer are ordered
+  with their fanins such that the nodes being composed in are always above
+  their fanin. This list is given to the variable manager to update the Ids in
+  use, provide available Ids for the unassigned nodes and allocate new
+  variables in both the variable and Dd manager. The variable manager then
+  marks all the node and fanin ids in use and returns an id array for the
+  unassigned nodes, reusing the ids whenever possible. It is also responsible
+  for creating an inverse permutation array with the current layer nodes and
+  their fanins in the order of the list and nodes unrelated at the bottom. The
+  unassigned nodes are updated with the ID array. The inverse permutation array
+  is fed to a CUDD procedure that moves the Ids to the required levels. Once
+  this order is achieved, composition is performed depending on the method
+  specified. Since the variable allocation procedure assumes that nodes with
+  unassigned IDs need to be filled with the holes closest to them, the ID on
+  each node is cleared after composition. This also makes it cleaner. The
+  variable manager is freed at the end of the procedure. The result of the
+  composition is the new residue Dd and is used for composition of the next
+  layer. The procedure returns the residue Dd in terms of the primary
+  inputs. The arguments to this function are the network to which the layers
+  belong, the layer array structure and the residue DD into which the circuit
+  needs to be composed into.This assumes that the residue DD has as many
+  variables as the number of outputs and the Ids of the variables starts with
+  0.]
+
+  SideEffects []
+
+  SeeAlso     [ResidueVerification]
+
+******************************************************************************/
+bdd_node *
+ComposeLayersIntoResidue(Ntk_Network_t *network, 
+			 array_t *layerArray, 
+			 bdd_node *residueDd,
+			 array_t *outputArray)
+{
+  bdd_manager *ddManager;                 /* Dd Manager */
+  bdd_node *newResidueDd = NIL(bdd_node); /* final composed Dd */
+  bdd_node *currentDd;                   /* local copy of residue Dd to
+					  * perform composition
+					  */
+  lsList outputList, orderList;          /* output and layer+fanin node
+					  * list fed to the ordering procedure
+					  */
+  lsHandle nodeHandle;                   /* handle for node list */ 
+  int *invPermArray;                     /* inverse permutation array
+					  * for the Dd manager
+					  */
+  array_t *newIdArray;                   /* array with new Ids to be
+					  * assigned to each node
+					  */
+  Ntk_Node_t *nodePtr;                   /* variable to store node pointer */
+  array_t *currentLayer;                 /* current layer of nodes */
+  int numNodes;                          /* number of nodes in current layer */
+  bdd_node **functionArray;              /* array of Adds of the current nodes
+					  * in terms of their fanin
+					  */
+					  
+  bdd_node *functionBdd;                 /* Bdds of current layer nodes */
+  char *flagValue;                       /* string that stores flag values */
+  int verbose;                           /* verbosity level */
+  int j, k;                              /* iterators */
+  int layerIndex, nodeIndex;             /* iterators */
+  long tempTime, thisComposeTime;        /* local time measurement variables */
+  long thisSmartVarTime, thisOrderTime;  /* local time measurement variables */
+  long thisShuffleTime;                  /* local time measurement variables */
+  int unassignedValue;                   /* NTK_UNASSIGNED_MDD_ID value holder */
+  
+  /* initialize local time measurement variables */
+  tempTime = 0;
+  thisSmartVarTime = 0;
+  thisOrderTime = 0;
+  thisShuffleTime = 0;
+  thisComposeTime = 0;
+  unassignedValue =  NTK_UNASSIGNED_MDD_ID;
+  
+  /* make a local copy of the residue Dd to compose the network into */
+  bdd_ref(currentDd = residueDd);
+  
+  /* read verbosity flag */
+  verbose = 0;
+  flagValue = Cmd_FlagReadByName("residue_verbosity");
+  if (flagValue != NIL(char)) {
+    verbose = atoi(flagValue);
+  }
+  
+  ddManager = (bdd_manager *)Ntk_NetworkReadMddManager(network);
+  /* initialize the variable manager that keeps track of what variables
+   * are in use in residue verification.
+   */
+  ResResidueInitializeVariableManager(bdd_num_vars(ddManager));
+  
+  /* assume the pos are labeled before they come here each time */
+  outputList = lsCreate();
+
+  /* outputs do not need to be ordered as the node ids are already
+   * assigned. Here this list is created just so that the variable
+   * manager can be updated
+   */
+
+  arrayForEachItem(Ntk_Node_t *, outputArray, j, nodePtr) {
+    lsNewEnd(outputList, (lsGeneric)nodePtr, (lsHandle *)&nodeHandle);
+  }
+  
+  newIdArray = array_alloc(int, 0);
+  tempTime = util_cpu_time();
+  /* update the variable manager with the output node ids */
+  invPermArray = ResResidueVarAllocate(ddManager, outputList, newIdArray);
+  if (invPermArray == NIL(int)) {
+    error_append("Unable to update variable manager\n");
+    array_free(newIdArray);
+    ResResidueFreeVariableManager();
+    return NULL;
+  } /* end of error */
+  thisSmartVarTime += util_cpu_time() - tempTime;
+  FREE(invPermArray);
+  array_free(newIdArray);
+  lsDestroy(outputList, (void (*)(lsGeneric))0);
+
+  /* start the main loop for composition of layers into the residue Add */
+  for(layerIndex = 0; layerIndex < array_n(layerArray); layerIndex++) {
+    /* fetch each layer */
+    currentLayer = ResLayerFetchIthLayer(layerArray, layerIndex);
+    numNodes = ResLayerNumNodes(currentLayer);
+    if (verbose >= 3) {
+      fprintf(vis_stdout, "Layer %d being composed", layerIndex);
+      fprintf(vis_stdout, " with %d nodes\n", numNodes);
+    }
+
+    /* create the order of the nodes in the layer and their fanin
+     * for composition
+     */
+    tempTime = util_cpu_time();
+    orderList = CreateNodeAndFaninOrderList(currentLayer);
+    thisOrderTime +=  util_cpu_time() - tempTime;
+
+    /* assign new Ids if required and create the corresponding variables
+     * in the manager
+     */
+    newIdArray = array_alloc(int, 0);
+    tempTime = util_cpu_time();
+    invPermArray = ResResidueVarAllocate(ddManager, orderList, newIdArray);
+    if (invPermArray == NIL(int)) {
+      error_append("Unable to update variable manager\n");
+      bdd_recursive_deref(ddManager, currentDd);
+      array_free(newIdArray);
+      ResResidueFreeVariableManager();
+      return NULL;
+    } /* end of error */
+    thisSmartVarTime += util_cpu_time() - tempTime;
+
+    /* assign Ids to unassigned fanin nodes */
+    if (array_n(newIdArray)) {
+      UpdateUnassignedNodesWithNewIds(orderList, newIdArray);
+    }
+    array_free(newIdArray);
+    lsDestroy(orderList, (void (*)(lsGeneric))0);
+    
+    /* shuffle the IDs */
+    tempTime = util_cpu_time();
+    (void) bdd_shuffle_heap(ddManager, invPermArray);
+    thisShuffleTime += util_cpu_time() - tempTime;
+    FREE(invPermArray);
+    
+    /* array initialized for dd nodes of the current layer */
+    tempTime = util_cpu_time();
+    functionArray = ALLOC(bdd_node *, numNodes);
+    LayerForEachNode(currentLayer, nodeIndex, nodePtr) {
+
+      /* build the BDD for the function of each node */
+      functionBdd = BuildBDDforNode(network, nodePtr, IMMEDIATE_FANIN);
+      if (functionBdd == NULL) { /* error */
+	error_append("Unable to build function for node ");
+	error_append(Ntk_NodeReadName(nodePtr));
+	error_append("\n");
+	for (k = 0; k < nodeIndex; k++) {
+	  bdd_recursive_deref(ddManager, functionArray[k]);
+	}
+	FREE(functionArray);
+	bdd_recursive_deref(ddManager, currentDd);
+	ResResidueFreeVariableManager();
+	return NULL;
+      } /* end of error */
+
+      /* Convert to ADD */
+      bdd_ref(functionArray[nodeIndex] = bdd_bdd_to_add(ddManager, functionBdd));
+      bdd_recursive_deref(ddManager, functionBdd);
+      if (functionArray[nodeIndex] == NULL) { /* error */
+	error_append("Unable to build add from bdd for node ");
+	error_append(Ntk_NodeReadName(nodePtr));
+	error_append("\n");
+	for (k = 0; k < nodeIndex; k++) {
+	  bdd_recursive_deref(ddManager, functionArray[k]);
+	}
+	FREE(functionArray);
+	bdd_recursive_deref(ddManager, currentDd);
+	ResResidueFreeVariableManager();
+	return NULL;
+      } /* end of error */
+    } /* end of iterating over each node in a layer */
+    /* compose the array into the residue ADD */
+
+    /* Perform the actual composition of current layer */
+    tempTime = util_cpu_time();
+    newResidueDd = ComposeLayer(ddManager, currentDd,  currentLayer, functionArray);
+    thisComposeTime += util_cpu_time() - tempTime;
+    /* free old residue Dd */
+    bdd_recursive_deref(ddManager, currentDd);
+    if (newResidueDd == NULL) { /* error */
+      error_append("Unable to do composition for layer\n");
+      for (k = 0; k < numNodes; k++) {
+	bdd_recursive_deref(ddManager, functionArray[k]);
+      }
+      FREE(functionArray);
+      ResResidueFreeVariableManager();
+      return NULL;
+    } /* end of error */
+    currentDd = newResidueDd;
+    if (verbose >= 3) {
+      mdd_t *fnMddT;
+      int size;
+      bdd_ref(currentDd);
+      fnMddT = bdd_construct_bdd_t(ddManager, currentDd);
+      size = bdd_size(fnMddT);
+      bdd_free(fnMddT);
+      fprintf(vis_stdout, "Layer %d has %d nodes\n", layerIndex,
+	      size);
+    }
+    
+    /* free function array */
+    for (j = 0; j < numNodes; j++) {
+      bdd_recursive_deref(ddManager, functionArray[j]);
+    }
+    FREE(functionArray);
+    
+    /*  free ids of nodes just composed */
+    ResResidueVarDeallocate(currentLayer);
+    /* reset node Ids of the composed layer */
+    LayerForEachNode(currentLayer, j, nodePtr) {
+      if (!Ntk_NodeTestIsCombInput(nodePtr)) {
+	Ntk_NodeSetMddId(nodePtr, unassignedValue);
+      }
+    }
+  } /* end of iterating over the layers */
+
+  /* free the variable manager */
+  ResResidueFreeVariableManager();
+  if (verbose >= 1) {
+    (void) fprintf(vis_stdout, "ADD Compose Time = %.3f\n",(thisComposeTime)/1000.0);
+    (void) fprintf(vis_stdout, "Smart variable allocation time = %.3f\n", (thisSmartVarTime)/1000.0);
+    (void) fprintf(vis_stdout, "Shuffle time = %.3f\n", (thisShuffleTime)/1000.0);
+    (void) fprintf(vis_stdout, "Order time = %.3f\n", (thisOrderTime)/1000.0);
+  }
+  /* update global time variables */
+  Res_composeTime += thisComposeTime;
+  Res_smartVarTime += thisSmartVarTime;
+  Res_shuffleTime += thisShuffleTime;
+  Res_orderTime += thisOrderTime;
+
+  /* return the composed residue Dd in terms of the primary inputs */
+  return(newResidueDd);
+  
+} /* End of ComposeLayersIntoResidue */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis  [Updates unassigned nodes in list with mdd ids in the array.]
+
+  Description [Updates unassigned nodes in list with mdd ids in the array. The
+  procedure steps through all nodes in a list and assigns them an id from the
+  array. The parameters to this procedure are the list of nodes, some of which
+  may not have assigned IDs and the array containing new Ids ready to be
+  assigned to the nodes.]
+  
+  SideEffects   []
+
+  SeeAlso            [ComposeLayersIntoResidue]
+
+******************************************************************************/
+static void
+UpdateUnassignedNodesWithNewIds(lsList orderList,   
+				array_t *newIdArray) 
+{
+  int i, id;
+  lsGen listGen;
+  Ntk_Node_t *nodePtr;
+  char *flagValue;
+  int verbose;
+  
+  verbose = 0;
+  flagValue = Cmd_FlagReadByName("residue_verbosity");
+  if (flagValue != NIL(char)) {
+    verbose = atoi(flagValue);
+  }
+
+  /* step through each item in the list to find nodes with unassigned Ids */
+  i = 0;
+  lsForEachItem(orderList, listGen, nodePtr) {
+    if (Ntk_NodeReadMddId(nodePtr) == NTK_UNASSIGNED_MDD_ID) {
+      id = array_fetch(int, newIdArray, i);
+      Ntk_NodeSetMddId(nodePtr, id);
+      i++;
+      if (verbose >= 4) {
+	fprintf(vis_stdout, "Id %d being assigned to node %s\n", id,
+		Ntk_NodeReadName(nodePtr));
+      }
+    }
+  }
+  assert(i == array_n(newIdArray));
+  return;
+} /* End of UpdateUnassignedNodesWithNewIds */
+
+
+/**Function********************************************************************
+
+  Synopsis  [Creates a list of the nodes of layer and the fanin nodes
+  of the layer.]
+
+  Description [Creates a list of the nodes of a layer and the order in which
+  they should appear in the dd manager for the composition process.  The main
+  idea is to be as efficient in composition as possible. This requires nodes
+  with overlapping support to be together, nodes being above their fanins in
+  the dd order (to perform fewer ITE calls) and nodes being composed in at the
+  top of the DD. This requires shuffling of the nodes in the layer to the top
+  and their fanins below them.  Shuffling is done by sifting and is an
+  expensive operation. Hence the motivation to keep the shuffles to as few as
+  possible. So we start with layer where the nodes are sorted according to
+  their level in the dd manager. It is a greedy heuristic that tries to
+  minimize the sifting.  Next the nodes with overlapping support are brought
+  together. Finally the fanin Nodes are sorted according to their levels too
+  and inserted below the last (in the order) node of their fanout. The
+  procedure returns the final sorted list of the nodes in the layer and their
+  fanin. Note: It is assumed that the current layer has Ids assigned to
+  it. This implies that the Primary outputs need special assignment of Ids and
+  every other node automatically gets assigned Ids since they appear in the
+  transitive fanin of some output. The function takes as an argument the layer
+  to be ordered.]
+  
+  SideEffects   []
+
+  SeeAlso            [ComposeLayersIntoResidue]
+
+******************************************************************************/
+static lsList
+CreateNodeAndFaninOrderList(array_t *currentLayer) 
+{
+  st_table *faninTable;       /* table to store fanin */
+  lsList layerList;           /* list of nodes in layer */
+  lsList faninVarSetList;     /* list of support corresponding to layer
+			       * nodes.
+			       */
+  lsList newList;             /* ordered list of nodes and fanins */
+  lsGen listGen;              /* generator to step through list */
+  lsGen layerGen, faninGen;   /* generators to step through lists */
+  int totalFanins;/* variable to store total number of fanins
+			       * of this layer
+			       */
+  int intersect;              /* number of elements in the intersection
+			       * of support.
+			       */
+  int i, j, faninIndex;       /* iterators */
+  Ntk_Node_t *nodePtr;        /* node pointer variables */
+  Ntk_Node_t *faninNodePtr;   /* node pointer variables */
+  Ntk_Node_t *nextNodePtr;    /* node pointer variables */
+  lsHandle nodeHandle;        /* handle for ls procedure */
+  lsHandle varSetHandle;      /* handle for ls procedure */
+  lsHandle newNodeHandle;     /* handle for ls procedure */
+  lsHandle maxIntersectNodeHandle;   /* handle for ls procedure */
+  lsHandle maxIntersectVarSetHandle; /* handle for ls procedure */
+  var_set_t *currVarSet;      /* support of current node */
+  var_set_t *varSetIntersect; /* intersection of support between 2 nodes */
+  var_set_t *nextVarSet;      /* support of next node */
+  array_t *faninArray;        /* array of fanin of a node read from network */
+  lsList faninList;           /* list of fanins of current layer */
+  int nodeIndex;              /* iterator */
+  int verbose;                /* verbosity level */
+  char *flagValue;            /* string to read flag value */
+  
+  verbose = 0;
+  flagValue = Cmd_FlagReadByName("residue_verbosity");
+  if (flagValue != NIL(char)) {
+    verbose = atoi(flagValue);
+  }
+
+  /* sort current layer by position in the dd manager for least number
+   * of shuffles
+   */
+  LayerSort(currentLayer, IdCompare);
+  /* create a list to be able to order the list and later manipulation */
+  layerList = lsCreate();
+  if (verbose >= 4) {
+    fprintf(vis_stdout, "Nodes in this layer are: ");
+  }
+  LayerForEachNode(currentLayer, i, nodePtr) {
+    lsNewEnd(layerList, (lsGeneric)nodePtr, (lsHandle *)&nodeHandle);
+    if (verbose >= 4) {
+      fprintf(vis_stdout, "%s ",Ntk_NodeReadName(nodePtr));
+    }
+  }
+  if (verbose >= 4) {
+    fprintf(vis_stdout, "\n");
+  }
+
+  /* insert all fanins in a table with a unique index. This is to identify
+   * each fanin as a support variable
+   */
+  faninIndex = 0;
+  faninTable = st_init_table(st_ptrcmp, st_ptrhash);
+
+  LayerForEachNode(currentLayer, nodeIndex, nodePtr) {
+    Ntk_NodeForEachFanin(nodePtr, j, faninNodePtr) {
+      /* here constants are omitted, so that they are not assigned an
+       * Id. The other case to be avoided is when the node in consideration
+       * is a latch output i.e. a combinational input. Hence it is not
+       * desirable that the latch data input and latch initial input
+       * be considered as its fanin.
+       */
+      if ((!st_is_member(faninTable, (char *)faninNodePtr)) &&
+	(!(Ntk_NodeTestIsConstant(faninNodePtr) ||
+	(Ntk_NodeTestIsLatch(nodePtr) &&
+	 (Ntk_NodeTestIsLatchDataInput(faninNodePtr) ||
+	  Ntk_NodeTestIsLatchInitialInput(faninNodePtr)))))) {
+	st_insert(faninTable, (char *)faninNodePtr,
+		  (char *)(long)faninIndex);
+	faninIndex++;
+      }
+    }
+  }
+  /* keep a count of the total number of fanins to this layer */
+  totalFanins = faninIndex;
+  
+  /* Create fanin var set for each node */
+  faninVarSetList = CreateFaninVarSetList(currentLayer, faninTable);
+  st_free_table(faninTable);
+
+  /* Main sorting part: Like Insertion Sort*/
+  /* initialize to first item from both layer and fanin lists */
+  /* starting here, find the list element in the list with max overlap
+   * with this element. Here each node in the layer is brought up
+   * neighbor
+   */
+  (void) lsFirstItem(faninVarSetList, &currVarSet, &varSetHandle);
+  (void) lsFirstItem(layerList, &nodePtr, &nodeHandle);
+  (void) lsRemoveItem(nodeHandle, &nodePtr);
+  (void) lsRemoveItem(varSetHandle, &currVarSet);
+  
+  /* insert first item in new list */
+  newList = lsCreate();
+  lsNewEnd(newList, (lsGeneric)nodePtr, (lsHandle *)&newNodeHandle);
+  
+  /* create var set for checking overlap of support */
+  varSetIntersect = var_set_new(totalFanins);
+  /* done when all the nodes in the layerList have been transferred
+   * to new list. In each iteration of this list, the node with max
+   * support overlap with the current node is taken out of the list
+   * and added to the new list. Its corresponding var set is also
+   * removed, the current var set is freed and the new var set is
+   * set to the current var set. The var set list has to be manipulated
+   * simultaneously to keep the correspondence between the node list
+   * and its support list.
+   */
+  while(lsLength(newList) != ResLayerNumNodes(currentLayer)) { /* while not done */
+    /* create generators to step through list */
+    faninGen = lsStart(faninVarSetList);
+    layerGen = lsStart(layerList);
+    /* initialize */
+    intersect = 0;
+    maxIntersectNodeHandle = NULL;
+    maxIntersectVarSetHandle = NULL;
+    while (lsNext(layerGen, &nextNodePtr, &nodeHandle) != LS_NOMORE) {
+      /* clear result var set */
+      var_set_clear(varSetIntersect);
+      /* position var set corresponding to node in layer list */
+      lsNext(faninGen, &nextVarSet, &varSetHandle);
+      /* get support overlap */
+      varSetIntersect = var_set_and(varSetIntersect, currVarSet, nextVarSet);
+      /* check if current overlap is larger than current max */
+      if (var_set_n_elts(varSetIntersect) > intersect) {
+	/* record current position */
+	intersect = var_set_n_elts(varSetIntersect);
+	maxIntersectNodeHandle = nodeHandle;
+	maxIntersectVarSetHandle = varSetHandle;
+      }
+    } /* end of iterating over layer list */
+
+    /* destroy Generator */
+    (void) lsFinish(layerGen);
+    (void) lsFinish(faninGen);
+    /* free current var set */
+    var_set_free(currVarSet);
+    /* process differently if there was overlap and if there wasn't */
+    if (maxIntersectNodeHandle == NULL) {
+      /* support overlap was zero with the rest of the nodes */
+      /* set current item to first in the lists */
+      (void) lsFirstItem(faninVarSetList, &nextVarSet, &maxIntersectVarSetHandle);
+      (void) lsFirstItem(layerList, &nextNodePtr, &maxIntersectNodeHandle);
+    }
+    
+    /* remove max support overlap item from the lists */
+    (void) lsRemoveItem(maxIntersectNodeHandle, &nextNodePtr);
+    (void) lsRemoveItem(maxIntersectVarSetHandle, &nextVarSet);
+    
+    /* add node to the new list */
+    lsNewEnd(newList, (lsGeneric)nextNodePtr, (lsHandle *)&newNodeHandle);
+    /* move current item to the new item */
+    currVarSet = nextVarSet;
+
+  }
+  /* Clean up */
+  var_set_free(varSetIntersect);
+  var_set_free(currVarSet);
+  lsDestroy(faninVarSetList, (void (*)(lsGeneric))0);
+  lsDestroy(layerList, (void (*)(lsGeneric))0);
+  /* end of sorting part */
+  
+  /* insert nodes in new order in the current layer */
+  i = 0;
+  lsForEachItem(newList, listGen, nodePtr) {
+    LayerAddNodeAtIthPosition(currentLayer, i, nodePtr);
+    i++;
+  }
+  assert(lsLength(newList) == array_n(currentLayer));
+
+  /* keep track of running update of the fanins included */
+  faninTable = st_init_table(st_ptrcmp, st_ptrhash);
+  /* insert fanin nodes after the last node in the order */
+  nodeIndex = ResLayerNumNodes(currentLayer)-1;
+  /* while nodes exist that have to be processed and all fanins haven't
+   * been processed, repeat
+   */
+  while ((nodeIndex >= 0) || (st_count(faninTable) != totalFanins)) {
+    nodePtr = LayerFetchIthNode(currentLayer, nodeIndex);
+    faninArray = Ntk_NodeReadFanins(nodePtr);
+    /* create a fanin list to append to the nodeList */
+    faninList = lsCreate();
+    arrayForEachItem(Ntk_Node_t *, faninArray, i, faninNodePtr) {
+      /* only include those fanins that haven't appeared yet. Also
+       * exclude the cases where the node is a constant and it is
+       * a latch data/initial input. You don't want to compose a
+       * latch output i.e. a combinational input with the latch input.
+       */
+      if ((!st_is_member(faninTable, (char *)faninNodePtr)) &&
+	  (!(Ntk_NodeTestIsConstant(faninNodePtr) ||
+	     (Ntk_NodeTestIsLatch(nodePtr) &&
+	      (Ntk_NodeTestIsLatchDataInput(faninNodePtr) ||
+	       Ntk_NodeTestIsLatchInitialInput(faninNodePtr)))))) {
+	lsNewEnd(faninList, (lsGeneric)faninNodePtr, (lsHandle *)&nodeHandle);
+	st_insert(faninTable, (char *)faninNodePtr, NIL(char));
+	/* done when all fanins have been processed */
+	if (st_count(faninTable) == totalFanins) break;
+      }
+    }
+    /* if list is not empty add fanin behind the node */
+    if (lsLength(faninList)) { 
+      /* sort fanins by their level in the ddmanager */
+      lsSort(faninList, IdListCompare);
+      /* append the fanin list to the node list */
+      newList = ListAppend(nodePtr, newList, faninList);
+    }
+    lsDestroy(faninList, (void (*)(lsGeneric))0);
+    nodeIndex--;
+
+  } /* end of while fanin nodes need to be processed and nodes
+     * are present in layer */
+  st_free_table(faninTable);
+  assert(lsLength(newList) == (array_n(currentLayer) + totalFanins));
+
+  return(newList);
+} /* End of CreateNodeAndFaninOrderList */
+
+
+/**Function********************************************************************
+
+  Synopsis  [Procedure to add fanin nodes below a particular node.]
+
+  Description [ Procedure to add fanin nodes below a particular node.  Finds
+  the node in the list after which fanin list is to be added.  Adds nodes in
+  the fanin list to the new list. This procedure takes as arguments the nodePtr
+  after which the fanins are to be inserted, the collated list where the fanins
+  should be inserted and a list of fanins. The updated list is returned.]
+
+  SideEffects   [New list is added to.]
+
+  SeeAlso            [CreateNodeAndFaninOrderList]
+
+******************************************************************************/
+static lsList
+ListAppend(Ntk_Node_t *nodePtr, 
+	   lsList newList,      
+	   lsList faninList)    
+{
+  lsGen layerGen, newGen, faninGen;
+  Ntk_Node_t *currNodePtr, *faninNodePtr;
+  lsHandle nodeHandle, faninNodeHandle;
+  lsStatus status;
+  
+  layerGen = lsEnd(newList);
+  /* find the spot to insert fanin List */
+  while(lsPrev(layerGen, &currNodePtr, &nodeHandle) != LS_NOMORE) {
+    if (nodePtr == currNodePtr) {
+      /* when spot found, insert fanin list */
+      newGen = lsGenHandle(nodeHandle, &currNodePtr, LS_AFTER);
+      lsForEachItem(faninList, faninGen, faninNodePtr) {
+	status = lsInAfter(newGen, (lsGeneric)faninNodePtr, (lsHandle *)&faninNodeHandle);
+	if (status != LS_OK) {
+	  error_append("Something wrong with fanin list to be appended\n");
+	  status = lsFinish(layerGen);
+	  status = lsFinish(newGen);
+	  status = lsFinish(faninGen);
+	  return NULL;
+	}
+      } /* end of iterating through the fanin list */
+      /* done as fanin list has been inserted */
+      lsFinish(newGen);
+      break;
+    } /* end of if node found  in the list */
+  } /* end of stepping through the new list */
+  
+  /* Clean up generators */
+  lsFinish(layerGen);
+  
+  /* return modified list */
+  return (newList);
+}/* End of ListAppend */
+    
+
+/**Function********************************************************************
+
+  Synopsis  [ Compares the Ids of 2 nodes.]
+
+  Description [Compares the Ids of 2 nodes. It is a procedure fed to array
+  sort.]
+  
+  SideEffects   []
+
+  SeeAlso            [CreateNodeAndFaninOrderList]
+
+******************************************************************************/
+static int
+IdCompare(const void *obj1,
+	  const void *obj2)
+{
+  Ntk_Node_t *nodePtr1, *nodePtr2;
+  int id1 , id2;
+  int level1, level2;
+  Ntk_Network_t *network;
+  bdd_manager *ddManager;
+  
+  nodePtr1 = *(Ntk_Node_t **)obj1;
+  nodePtr2 = *(Ntk_Node_t **)obj2;
+  id1 = Ntk_NodeReadMddId((Ntk_Node_t *)nodePtr1);
+  id2 = Ntk_NodeReadMddId((Ntk_Node_t *)nodePtr2);
+  /* if unassigned Ids return the value before reading the
+   * position . If equal return -1.
+   */
+  if ((id1 == NTK_UNASSIGNED_MDD_ID) || (id2 == NTK_UNASSIGNED_MDD_ID)) {
+    if (id1 == NTK_UNASSIGNED_MDD_ID) {
+      return -1;
+    } else {
+      return 1;
+    }
+  }
+
+  network = Ntk_NodeReadNetwork(nodePtr1);
+  ddManager = (bdd_manager *)Ntk_NetworkReadMddManager(network);
+  level1 = bdd_get_level_from_id(ddManager, id1);
+  level2 = bdd_get_level_from_id(ddManager, id2);
+  if (level1 > level2) {
+    return 1;
+  } else if (level1 == level2) {
+    return 0;
+  } else {
+    return -1;
+  }
+} /* End of IdCompare */
+
+/**Function********************************************************************
+
+  Synopsis  [Compares the Ids of 2 nodes.]
+
+  Description [Compares the Ids of 2 nodes. it is fed to s list sort routine. ]
+  
+  SideEffects   []
+
+  SeeAlso            [CreateNodeAndFaninOrderList]
+
+******************************************************************************/
+static int
+IdListCompare(lsGeneric item1,
+	      lsGeneric item2)
+{
+  Ntk_Node_t *nodePtr1, *nodePtr2;
+  int id1 , id2;
+  int level1, level2;
+  Ntk_Network_t *network;
+  bdd_manager *ddManager;
+
+  
+  nodePtr1 = (Ntk_Node_t *)item1;
+  nodePtr2 = (Ntk_Node_t *)item2;
+  id1 = Ntk_NodeReadMddId((Ntk_Node_t *)nodePtr1);
+  id2 = Ntk_NodeReadMddId((Ntk_Node_t *)nodePtr2);
+  /* if unassigned Ids return the value before reading the
+   * position . If equal return -1.
+   */
+  if ((id1 == NTK_UNASSIGNED_MDD_ID) || (id2 == NTK_UNASSIGNED_MDD_ID)) {
+    if (id1 == NTK_UNASSIGNED_MDD_ID) {
+      return -1;
+    } else {
+      return 1;
+    }
+  }
+  network = Ntk_NodeReadNetwork(nodePtr1);
+  ddManager = (bdd_manager *)Ntk_NetworkReadMddManager(network);
+  level1 = bdd_get_level_from_id(ddManager, id1);
+  level2 = bdd_get_level_from_id(ddManager, id2);
+  if (level1 > level2) {
+    return 1;
+  } else if (level1 == level2) {
+    return 0;
+  } else {
+    return -1;
+  }
+} /* End of IdListCompare */
+
+
+/**Function********************************************************************
+
+  Synopsis  [Creates a list of var set of support for each node in layer.]
+
+  Description [ Creates a list of var set of support for each node in layer.
+  For each node in the layer, create a var set of support based on the fanin
+  index stored in the fanin table. Returns a list of var sets. Takes as
+  arguments the current layer whose support sets need to be formed and a table
+  with the fanin and their unique IDs.]
+  
+  SideEffects   []
+
+  SeeAlso            [CreateNodeAndFaninOrderList]
+
+******************************************************************************/
+static lsList
+CreateFaninVarSetList(array_t *currentLayer, 
+		      st_table *faninTable)  
+{
+  Ntk_Node_t *nodePtr, *faninNodePtr;  /* variables to store nodes */
+  array_t *faninArray;                 /* array of fanin of nodes */
+  lsList faninVarSetList;              /* list of var set representing
+					* support of nodes in layer
+					*/
+  var_set_t *currVarSet;               /* var set indicating current
+					* node support
+					*/
+  lsHandle varSetHandle;               /* handle for ls procedure */
+  int totalFanins;                     /* total number of fanins of this
+					* layer.
+					*/
+  int i, j, faninIndex;                /* iterators */
+
+
+  
+  totalFanins = (int)st_count(faninTable);
+  faninVarSetList = lsCreate();
+  /* create var-set of support for each node in this layer */
+  arrayForEachItem(Ntk_Node_t *, currentLayer, i, nodePtr) {
+    faninArray = Ntk_NodeReadFanins(nodePtr);
+    currVarSet = var_set_new(totalFanins);
+    /* if the above node is a constant, the var set will be empty
+     * also if it a latch output(comb. input), then the var set will
+     * be empty.
+     */
+    arrayForEachItem(Ntk_Node_t *, faninArray, j, faninNodePtr) {
+      /* process only those fanins in the table, i.e. no constants
+       * no latch inputs (combinational outputs) are fanins to this array
+       */
+      if (st_lookup_int(faninTable, (char *)faninNodePtr, &faninIndex)) {
+	/* these aren't supposed to be here */
+	assert(!((Ntk_NodeTestIsConstant(faninNodePtr) ||
+		  (Ntk_NodeTestIsLatch(nodePtr) &&
+		   (Ntk_NodeTestIsLatchDataInput(faninNodePtr) ||
+		    Ntk_NodeTestIsLatchInitialInput(faninNodePtr))))));
+	/* set the bit in the support according to the index the fanin
+	 * was assigned
+	 */
+	var_set_set_elt(currVarSet, faninIndex);
+      } /* end of if is in the fanin table (has no constants and no
+	 * latch data or initial input.
+	 */
+    } /* end of if present in fanin table */
+    /* insert var set in fanin var set list */
+    lsNewEnd(faninVarSetList, (lsGeneric)currVarSet, (lsHandle *)&varSetHandle);
+  }
+  return (faninVarSetList);
+} /* End of CreateFaninVarSetList */
+
+/**Function********************************************************************
+
+  Synopsis [Procedure that does the actual composition of a layer into the
+  residue add.]
+
+  Description [ Procedure that does the actual composition of a layer into the
+  residue add depending on the method specified. Note for vector composition,
+  this procedure assumes that currentLayer is sorted according to the levels
+  and according to common support. This is done in
+  CreateNodeAndFaninOrderList. The procedure takes as arguments the DD manager,
+  the residue DD, the current layer that needs to be composed in and the array
+  of the function BDDs of the nodes to be composed in (in 1-to-1 correspondence
+  with the current layer. The procedure returns the composed Dd.]
+  
+  SideEffects   []
+
+  SeeAlso            [ComposeLayersIntoResidue]
+
+******************************************************************************/
+static bdd_node *
+ComposeLayer(bdd_manager *ddManager,    
+	     bdd_node *residueDd,       
+	     array_t *currentLayer,   
+	     bdd_node **functionArray)  
+{
+  Ntk_Node_t *nodePtr;          /* variable to store nodes */
+  char *flagValue;              /* string to read flag value */
+  ResCompositionMethod method;  /* type of composition to be performed */
+  int i, j, layerIndex;                     /* iterators */
+  int nodeId;                   /* current node id */
+  bdd_node **composeVector;       /* vector required for composition */
+  bdd_node *new_ = NIL(bdd_node), *andDd,*yDd, *nodeReln, *currentDd; /* temporary Dds */
+  int maxLayerSize;             /* max size of layers */
+  int first, last;              /* first and last positions of the array */
+  
+  /* read the type of composition to be performed, default is vector
+   * composition.
+   */
+  flagValue = Cmd_FlagReadByName("residue_composition_method");
+  if (flagValue == NIL(char)) {
+    method = ResDefaultComposeMethod_c;
+  } else if (strcmp(flagValue, "vector") == 0) {
+      method = ResVector_c;
+  } else if (strcmp(flagValue, "onegate") == 0) {
+    method =  ResOneGateAtATime_c;
+  } else if (strcmp(flagValue, "preimage") == 0) {
+    method = ResPreimageComputation_c;
+  } else if (strcmp(flagValue, "superG") == 0) {
+    method = ResSuperG_c;
+  } else {
+    fprintf(vis_stderr, 
+	    "** res warning: Unknown composition method, %s, resorting to default.\n", 
+	    flagValue);
+    method = ResDefaultComposeMethod_c;
+  } 
+
+  switch(method) {
+
+  case ResVector_c:
+  case ResSuperG_c:
+    {
+      /* read the flag for maximum value of layer size */
+      flagValue = Cmd_FlagReadByName("residue_layer_size");
+      if (flagValue == NIL(char)) {
+	maxLayerSize = ResLayerNumNodes(currentLayer);  
+      } else {
+	maxLayerSize = atoi(flagValue);
+      }
+      /* if max layer size is within 5 nodes of the length of the
+       * size of the array, resize it to the size of the array
+       */
+      if (maxLayerSize + 5 >= ResLayerNumNodes(currentLayer)) {
+	maxLayerSize = ResLayerNumNodes(currentLayer);
+      }
+
+      /* initialize a vector with projection functions */
+      composeVector = ALLOC(bdd_node *, bdd_num_vars(ddManager));
+      for(i = 0; (unsigned) i < bdd_num_vars(ddManager); i++) {
+	bdd_ref(composeVector[i] = bdd_add_ith_var(ddManager, i));
+	if (composeVector[i] == NIL(bdd_node)) { /* error */
+	  error_append("Something wrong in obtaining projection functions");
+	  for(j = 0; j < i; j++) {
+	    bdd_recursive_deref(ddManager, composeVector[j]);
+	  }
+	  return NIL(bdd_node);
+	} /* end of if error */
+      }
+      /* break this layer up into sub-layers to ease composition
+       * process. Hence the composition will be performed for several
+       * subarrays.
+       */
+      /* start at the end of the layer */
+      layerIndex = ResLayerNumNodes(currentLayer);
+      /* make a local copy */
+      bdd_ref(currentDd = residueDd);
+      do {
+	/* extract sublayers in the size of maxLayerSize starting from the
+	 * end of the layer or a smaller sub-layer (leftover) in the end
+	 */
+
+	/* record last+1 position of the sub-layer in the current layer */
+	last = layerIndex;
+
+	/* record the position of the beginning of this sub-layer */ 
+	first = (last < maxLayerSize) ? 0 : (last - maxLayerSize);
+
+	/* iterate through the layer to find the sublayer */
+	while(layerIndex  > first) { /* extract sub-layer */
+	  layerIndex--;
+	  nodePtr = LayerFetchIthNode(currentLayer, layerIndex);
+	  nodeId = Ntk_NodeReadMddId(nodePtr);
+	  bdd_recursive_deref(ddManager, composeVector[nodeId]);
+	  /* plug in the functions of the nodes in the layer instead of
+	   * the projection functions
+	   */
+	  bdd_ref(composeVector[nodeId] = functionArray[layerIndex]);
+	}
+
+	/* perform composition */
+	if (method == ResVector_c) {
+	  bdd_ref(new_ = bdd_add_vector_compose(ddManager, currentDd, composeVector));
+	} else {
+	  bdd_ref(new_ = bdd_add_nonsim_compose(ddManager, currentDd, composeVector));
+	}
+
+	/* free old copy and use new to compose in the next sub-layer, if any */
+	bdd_recursive_deref(ddManager, currentDd);
+	currentDd = new_;
+	
+	if (new_ == NULL) { /* error */
+	  error_append("NULL Dd returned on vector or superG compose\n");
+	  break;
+	} /* end of error */
+
+	/* undo the compose vector changes for this sub-array to
+	 * prepare it for the next subarray. Replace the function of
+	 * nodes with the projection functions
+	 */
+	for (i = first; i < last; i++) {
+	  nodePtr = LayerFetchIthNode(currentLayer, i);
+	  nodeId = Ntk_NodeReadMddId(nodePtr);
+	  bdd_recursive_deref(ddManager, composeVector[nodeId]);
+	  bdd_ref(composeVector[nodeId] = bdd_add_ith_var(ddManager, nodeId));
+	}
+      } while(layerIndex  > 0);
+
+      /* clean up */
+      for(i = 0; (unsigned) i < bdd_num_vars(ddManager); i++) {
+	bdd_recursive_deref(ddManager, composeVector[i]);
+      }
+      FREE(composeVector);
+      break;
+    } /* end of cases: ResVector_c, ResSuperG_c */
+  case ResOneGateAtATime_c:
+    {
+      /* duplicate  as current Dd gets freed later */
+      bdd_ref(currentDd = residueDd);
+      /* compose the nodes in one at a time */
+      LayerForEachNode(currentLayer, i, nodePtr) {
+	nodeId = Ntk_NodeReadMddId(nodePtr);
+	bdd_ref(new_ = bdd_add_compose(ddManager, currentDd, functionArray[i],
+				       nodeId));
+	bdd_recursive_deref(ddManager, currentDd);
+	if (new_ == NULL) { /* error */
+	  error_append("NULL Dd returned on single gate compose, node: ");
+	  error_append(Ntk_NodeReadName(nodePtr));
+	  error_append("\n");
+	  return NULL;
+	} /* end of error */
+	currentDd = new_;
+      }
+      break;
+    } /* end of case Res_OneGateAtATime_c */
+  case ResPreimageComputation_c:
+    {
+      /* duplicate  as current Dd gets freed later */
+      bdd_ref(currentDd = residueDd);
+      /* form the y_i \equiv f_i(x) relation, this would be wrong
+       * if the node appeared again in the circuit. But here it is
+       * correct due to the one time rule
+       */
+      LayerForEachNode(currentLayer, i, nodePtr) {
+	nodeId = Ntk_NodeReadMddId(nodePtr);
+	/* find the var for this node */
+	bdd_ref(yDd = bdd_add_ith_var(ddManager, nodeId));
+	if (yDd == NULL) { /* error */
+	  error_append("Null Dd returned on preimage compose- y_i stage. ");
+	  error_append("Node: ");
+	  error_append(Ntk_NodeReadName(nodePtr));
+	  bdd_recursive_deref(ddManager, currentDd);
+	  error_append("\n");
+	  return NULL;
+	} /* end of error */
+	/* construct the relation */
+	bdd_ref(nodeReln = bdd_add_apply(ddManager, bdd_add_xnor, yDd, functionArray[i]));
+
+	if (nodeReln == NULL) { /* error */
+	  error_append("Null Dd returned on preimage compose - node reln stage");
+	  error_append("Node: ");
+	  error_append(Ntk_NodeReadName(nodePtr));
+	  bdd_recursive_deref(ddManager, yDd);
+	  bdd_recursive_deref(ddManager, currentDd);
+	  error_append("\n");
+	  return NULL;
+	} /* end of error */
+	/* perform the and of the and-abstract */
+	bdd_ref(andDd = bdd_add_apply(ddManager, bdd_add_times, currentDd, nodeReln));
+	bdd_recursive_deref(ddManager, currentDd);
+	bdd_recursive_deref(ddManager, nodeReln);
+	if (andDd == NULL) { /* error */
+	  error_append("Null Dd returned on preimage compose - and dd stage");
+	  error_append("Node: ");
+	  error_append(Ntk_NodeReadName(nodePtr));
+	  error_append("\n");
+	  bdd_recursive_deref(ddManager, yDd);
+	  return NULL;
+	} /* end of error */
+	/* perform the abstract of the and-abstract */
+	bdd_ref(new_ = bdd_add_exist_abstract(ddManager, andDd, yDd));
+	bdd_recursive_deref(ddManager, andDd);
+	bdd_recursive_deref(ddManager, yDd);
+	if (new_ == NULL) { /* error */
+	  error_append("Null Dd returned on preimage compose - and dd stage");
+	  error_append("Node: ");
+	  error_append((char *)Ntk_NodeReadName(nodePtr));
+	  error_append("\n");
+	  return NULL;
+	} /* end of error */
+	currentDd = new_;
+      }
+      break;
+    } /* end of case Res_PreimageComputation_c */
+  } /* end of switch(method) */
+  
+  /* return the new composed Dd */
+  return new_;
+} /* End of ComposeLayersIntoResidue */
+ 
+
+/**Function********************************************************************
+
+  Synopsis [Builds MVF for a node with no inputs, and only one row in its
+  table.]
+
+  Description [Builds MVF for a constant, then node should be a constant,
+  combinational node.  In this case, an MVF is built with a single component
+  (indexed by the value of node) is one, and all other components are zero.]
+
+  SideEffects []
+
+******************************************************************************/
+static Mvf_Function_t *
+NodeBuildConstantMvf(
+  Ntk_Node_t * node,
+  mdd_manager *mddMgr)
+{
+  int             value        = 0; /* initialized to stop lint complaining */
+  mdd_t          *oneMdd       = mdd_one(mddMgr);
+  Var_Variable_t *variable     = Ntk_NodeReadVariable(node);
+  int             numVarValues = Var_VariableReadNumValues(variable);
+  Mvf_Function_t *mvf          = Mvf_FunctionAlloc(mddMgr, numVarValues);
+  int          outputIndex = Ntk_NodeReadOutputIndex(node);
+  Tbl_Table_t *table       = Ntk_NodeReadTable(node);
+
+  assert(Ntk_NodeTestIsConstant(node));
+  value = Tbl_TableReadConstValue(table, outputIndex);
+  assert(value != -1);
+  
+  Mvf_FunctionAddMintermsToComponent(mvf, value, oneMdd);
+  mdd_free(oneMdd);
+  return mvf;
+}
Index: vis_dev/vis-2.3/src/res/resInt.h
===================================================================
--- vis_dev/vis-2.3/src/res/resInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/res/resInt.h	(revision 14)
@@ -0,0 +1,524 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [resInt.h]
+
+  PackageName [res]
+
+  Synopsis    [Internal declarations of the residue package.]
+
+  Author      [Kavita Ravi    <ravi@boulder.colorado.edu> and
+	       Abelardo Pardo <abel@boulder.colorado.edu>]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+  Revision    [$Id: resInt.h,v 1.31 2002/09/08 23:55:58 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _RESINT
+#define _RESINT
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "res.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define RES_NOT_VERIFIED -1  /* constant to indicate verification not taken
+			      * place
+			      */
+#define RES_PASS 1           /* constant to indicate verification success */
+#define RES_FAIL 0           /* constant to indicate verification failure */
+#define ResDefaultComposeMethod_c ResVector_c 
+#define ResDefaultScheduleLayerMethod_c ResLayerAlap_c
+
+#define IMMEDIATE_FANIN 1 /* Static flag to indicate that the BDD/MDD has to
+ 			   * be built in terms  of immediate fanin 
+			   */
+
+
+#define PRIMARY_INPUTS 2  /* Static flag to indicate PIs
+                           * used to indicate that the BDD/MDD has to be
+                           * built in terms  of primary inputs
+                           * also used to flag the building of input
+                           * match tables
+                           */
+
+#define PRIMARY_OUTPUTS 3 /* Static flag to indicate PIs
+                           * also used to flag the building of input
+                           * match tables
+			   */
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/**Enum************************************************************************
+
+  Synopsis [Different methods to compute the layers for functional
+  compositions.]
+
+  SeeAlso     [ResComputeCompositionLayers]
+
+******************************************************************************/
+typedef enum {
+  ResLayerAsap_c,
+  ResLayerAlap_c
+} ResLayerScheduleMethod;
+
+/**Enum************************************************************************
+
+  Synopsis    [Different composition methods.]
+
+  SeeAlso     [ComposeLayersIntoResidue]
+
+******************************************************************************/
+typedef enum { 
+  ResVector_c,    /* Compose when fanout gates have been composed */
+  ResOneGateAtATime_c, /* Compose one gate at a time */
+  ResPreimageComputation_c, /* Treat the compositions like 
+			      * partitioned transition relation */
+  ResSuperG_c        /* new cudd vector compose that creates a super G */
+} ResCompositionMethod;
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+/* variables to measure times of different components of residue verification*/
+extern long Res_composeTime;
+extern long Res_shuffleTime;
+extern long Res_smartVarTime;
+extern long Res_orderTime;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**Macro***********************************************************************
+
+  Synopsis     [Macro to fetch the i-th layer in the layer Array.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define ResLayerFetchIthLayer(layerArray, i) \
+    array_fetch(array_t *, layerArray, i)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Macro to determine number of nodes in current layer]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define ResLayerNumNodes(layer) \
+    array_n(layer)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterate through each node in a layer.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define LayerForEachNode(layer, i, nodePtr) \
+    arrayForEachItem(Ntk_Node_t *, layer, i, nodePtr)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Add node in the i-th position in the layer.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define LayerAddNodeAtIthPosition(layer, i, nodePtr) \
+   array_insert(Ntk_Node_t *, layer, i, nodePtr)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Add node at the end of the layer.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define LayerAddNodeAtEnd(layer, nodePtr) \
+    array_insert_last(Ntk_Node_t *, layer, nodePtr)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Fetch the i-th node in the layer.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define LayerFetchIthNode(layer, i) \
+    array_fetch(Ntk_Node_t *, layer, i)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Sort the layer nodes according to the given function.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define LayerSort(layer, func) \
+              array_sort(layer, func)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Free current layer.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define LayerFree(layer)  \
+              array_free(layer)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Create an empty layer.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define LayerCreateEmptyLayer() \
+            array_alloc(Ntk_Node_t *, 0)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Macro to read the network name field of Res_ResidueInfo.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define ResResidueInfoReadNetworkName(rPtr) \
+  (rPtr)->networkName
+
+/**Macro***********************************************************************
+
+  Synopsis     [Macro to read the name of the circuit that has been
+  verified against.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define ResResidueInfoReadNameVerifiedAgainst(rPtr) \
+  (rPtr)->networkNameVerifiedAgainst
+
+/**Macro***********************************************************************
+
+  Synopsis     [Macro to set the name filed of Res_ResidueInfo]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define ResResidueInfoSetNetworkName(rPtr, value) \
+  (rPtr)->networkName = (value)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Macro to set the name field of the circuit that this one
+  has been verified against.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define ResResidueInfoSetNameVerifiedAgainst(rPtr, value) \
+  (rPtr)->networkNameVerifiedAgainst = (value)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Macro to read the numInputs field of Res_ResidueInfo]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define ResResidueInfoReadNumInputs(rPtr) \
+  (rPtr)->numInputs
+
+/**Macro***********************************************************************
+
+  Synopsis     [Macro to set the numInputs field of Res_ResidueInfo]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define ResResidueInfoSetNumInputs(rPtr, value) \
+  (rPtr)->numInputs = (value)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Macro to read the numOutputs field of Res_ResidueInfo.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define ResResidueInfoReadNumOutputs(rPtr) \
+  (rPtr)->numOutputs
+
+/**Macro***********************************************************************
+
+  Synopsis     [Macro to set the numOutputs field of Res_ResidueInfo.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define ResResidueInfoSetNumOutputs(rPtr, value) \
+  (rPtr)->numOutputs = (value)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the numDirectVerifiedOutputs field of
+  Res_ResidueInfo.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define ResResidueInfoReadNumDirectVerifiedOutputs(rPtr) \
+  (rPtr)->numDirectVerifiedOutputs
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the numDirectVerifiedOutputs field of
+  Res_ResidueInfo.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define ResResidueInfoSetNumDirectVerifiedOutputs(rPtr, value) \
+  (rPtr)->numDirectVerifiedOutputs = (value)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the cpuDirectVerif field of
+  Res_ResidueInfo.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define ResResidueInfoReadCpuDirectVerif(rPtr) \
+  (rPtr)->cpuDirectVerif
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the cpuDirectVerif field of
+  Res_ResidueInfo.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define ResResidueInfoSetCpuDirectVerif(rPtr, value) \
+  (rPtr)->cpuDirectVerif = (value)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the numOfPrimes field of Res_ResidueInfo.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define ResResidueInfoReadNumOfPrimes(rPtr) \
+  (rPtr)->numOfPrimes
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the numOfPrimes field of Res_ResidueInfo.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define ResResidueInfoSetNumOfPrimes(rPtr, value) \
+  (rPtr)->numOfPrimes = (value)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the success field of Res_ResidueInfo.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define ResResidueInfoReadSuccess(rPtr) \
+  ((Res_ResidueInfo_t *)rPtr)->success
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the direct verification success field of 
+  Res_ResidueInfo.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define ResResidueInfoReadDirectVerificationSuccess(rPtr) \
+  (rPtr)->successDirectVerification
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read the success field of Res_ResidueInfo.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define ResNetworkReadResidueInfo(network) \
+  (Res_ResidueInfo_t *)Ntk_NetworkReadApplInfo(network,RES_NETWORK_APPL_KEY);
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the success field of Res_ResidueInfo.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define ResResidueInfoSetSuccess(rPtr, value) \
+  ((Res_ResidueInfo_t *)rPtr)->success = (value)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set the direct verification success field of
+  Res_ResidueInfo.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define ResResidueInfoSetDirectVerificationSuccess(rPtr, value) \
+  ((Res_ResidueInfo_t *)rPtr)->successDirectVerification = (value)
+
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to read one entry of the PerPrimeInfo array of
+  Res_ResidueInfo.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define ResResidueInfoReadPerPrimeInfo(rPtr, i) \
+  (&((rPtr)->primeInfoArray[(i)]))
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set one entry of the PerPrimeInfo array of
+  Res_ResidueInfo.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define ResResidueInfoSetPerPrimeInfo(rPtr, idx, num, time, size, dd) \
+  ((rPtr)->primeInfoArray)[(idx)].primeNumber = (num); \
+  ((rPtr)->primeInfoArray)[(idx)].cpuTime = (time); \
+  ((rPtr)->primeInfoArray)[(idx)].bddSize = (size); \
+  ((rPtr)->primeInfoArray)[(idx)].residueDd = (dd)
+
+/**Macro***********************************************************************
+
+  Synopsis [Macro to set DdNodeof the  entry of the PerPrimeInfo array of
+  Res_ResidueInfo.]
+
+  SideEffects  []
+
+  SeeAlso      [Res_ResidueInfo]
+
+******************************************************************************/
+#define ResResidueInfoSetPerPrimeDd(rPtr, idx, dd) \
+  ((rPtr)->primeInfoArray)[(idx)].residueDd = (dd)
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN bdd_node * BuildBDDforNode(Ntk_Network_t *network, Ntk_Node_t *nodePtr, int fanin);
+EXTERN bdd_node * ComposeLayersIntoResidue(Ntk_Network_t *network, array_t *layerArray, bdd_node *residueDd, array_t *outputArray);
+EXTERN array_t * ResComputeCompositionLayers(Ntk_Network_t *network, array_t *outputArray, array_t *ignoreArray);
+EXTERN void ResLayerPrintInfo(Ntk_Network_t *network, array_t *layerArray);
+EXTERN void ResLayerArrayFree(array_t *layerArray);
+EXTERN Res_ResidueInfo_t * ResNetworkResidueInfoReadOrCreate(Ntk_Network_t *network);
+EXTERN Res_ResidueInfo_t * ResResidueInfoAllocate(char *name);
+EXTERN void ResResidueInfoAllocatePrimeInfoArray(Res_ResidueInfo_t *residueInfo, int numOfPrimes, int *tableOfPrimes);
+EXTERN void MddCreateVariables(mdd_manager *mgr, int numVarsToBeAdded);
+EXTERN int * ResResidueVarAllocate(bdd_manager *ddManager, lsList orderList, array_t *newIdArray);
+EXTERN void ResResidueVarDeallocate(array_t *currentLayer);
+EXTERN void ResResidueFreeVariableManager(void);
+EXTERN void ResResidueInitializeVariableManager(int numOfVars);
+EXTERN int * ResResidueVarUseAllocate(int howManyVars, boolean recicleVarIds, int consecutive);
+EXTERN void ResResidueVarUseDeallocate(int *varPool, int size);
+EXTERN int ResResidueVarHighestIndex(void);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _RESINT */
Index: vis_dev/vis-2.3/src/res/resLayer.c
===================================================================
--- vis_dev/vis-2.3/src/res/resLayer.c	(revision 14)
+++ vis_dev/vis-2.3/src/res/resLayer.c	(revision 14)
@@ -0,0 +1,759 @@
+/**CFile***********************************************************************
+
+  FileName    [resLayer.c]
+
+  PackageName [res]
+
+  Synopsis    [This file is responsible for computing the "layers" in a circuit
+  depending on the method]
+
+  Author      [Kavita Ravi    <ravi@boulder.colorado.edu> and
+	       Abelardo Pardo <abel@boulder.colorado.edu>]
+	       
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "resInt.h"
+
+static char rcsid[] UNUSED = "$Id: resLayer.c,v 1.36 2005/04/16 07:31:03 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static array_t * ComputeCompositionLayersAsap(Ntk_Network_t *network, array_t *outputArray, array_t *ignoreArray);
+static array_t * ComputeCompositionLayersAlap(Ntk_Network_t *network, array_t *outputArray, array_t *ignoreArray);
+static int ComputeAlapLabelling(Ntk_Network_t *network, st_table *nodeLabelling);
+static void ComputeAlapLabellingRecur(Ntk_Node_t *node, st_table *nodeLabelling);
+static st_table * ComputeTransitiveFanin(array_t *outputArray);
+static void ComputeTransitiveFaninRecur(Ntk_Node_t *nodePtr, st_table *faninTable);
+static void RecursiveDecrementFanoutCount(Ntk_Node_t *nodePtr, st_table *fanoutCountTable, st_table *visitedTable);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Computes the layers of nodes of the network that represent the order
+  for composition.]
+
+  Description [ Computes the layers of nodes of the network that represent the
+  order for composition. When composing an ADD with nodes in the circuit
+  starting with the primary outputs, several nodes in the network can be
+  composed at the same time producing "layers" in the network. When a node is
+  in the layer and it is composed with its fanin nodes, the original node does
+  not belong to the ADD any more, and its fanin nodes become now part of the
+  ADD.  There are several ways to produce this cut, we provide two such
+  methods.  This procedure reads the flag <tt>residue_layers<\tt> and calls the
+  pertinent function. The procedure takes as arguments the network whose layers
+  need to be formed, the set of outputs that need to be considered and the set
+  of outputs that can be ignored. The procedure returns an array of layers]
+
+  SideEffects []
+
+  SeeAlso [ComputeCompositionLayersAsap ComputeCompositionLayersAlap]
+
+******************************************************************************/
+array_t *
+ResComputeCompositionLayers(Ntk_Network_t *network, 
+			    array_t *outputArray,   
+			    array_t *ignoreArray)   
+{
+  ResLayerScheduleMethod layerMethod; /* read from the set value */
+  array_t *result;  /* Result obtained from procedure */
+  char *flagValue;  /* To store the value read from the flag */
+
+  /* Read the value from the flag */
+  flagValue = Cmd_FlagReadByName("residue_layer_schedule");
+  if (flagValue == NIL(char)) {
+    layerMethod = ResDefaultScheduleLayerMethod_c;
+  } 
+  else {
+    if (strcmp(flagValue, "asap") == 0) {
+      layerMethod = ResLayerAsap_c;
+    }
+    else if (strcmp(flagValue, "alap") == 0) {
+      layerMethod = ResLayerAlap_c;
+    }
+    else {
+      (void) fprintf(vis_stderr, "** res error: Unknown method to compute layers.");
+      (void) fprintf(vis_stderr, "** res error: Assuming default method.\n");
+      layerMethod = ResDefaultScheduleLayerMethod_c;
+    }
+  }
+
+  /* Call the pertinent procedure */
+  switch (layerMethod) {
+  case ResLayerAlap_c: {
+      result = ComputeCompositionLayersAlap(network, outputArray, ignoreArray);
+      break;
+      }
+  case ResLayerAsap_c: {
+      result = ComputeCompositionLayersAsap(network, outputArray, ignoreArray);
+      break;
+      }
+  default: {
+      (void) fprintf(vis_stdout, "** res warning: Layer computation method not implemented.");
+      (void) fprintf(vis_stdout, "** res warning: Executing default method.\n");
+      result = ComputeCompositionLayersAlap(network, outputArray, ignoreArray);
+      break;
+    }
+  }
+
+  return result;
+} /* End of ResComputeCompositionLayers */
+
+
+/**Function********************************************************************
+
+  Synopsis [Prints out the different layers in the circuit.]
+
+  Description [Prints the nodes in various layers starting with the output
+  along with their layer numbers. The procedure also counts the number of new
+  variables that the current layer brings in. The procedure takes the network
+  whose layers are to be printed and the layer array structure.]
+  
+  SideEffects        []
+
+  SeeAlso            [Res_NetworkResidueVerify]
+
+******************************************************************************/
+void
+ResLayerPrintInfo(Ntk_Network_t *network, 
+		  array_t *layerArray)
+{
+
+  Ntk_Node_t   *nodePtr, *faninNodePtr; /* Node being processed */
+  st_table *faninTable;                 /* Current nodes */
+  int layerIndex, newVars;              /* index of the layer being processed */
+  int i,j;                              /* For array traversal */
+  array_t *currentLayer;                /* layer info */
+
+  /* keep track of all nodes that have appeared in the support */
+  faninTable = st_init_table(st_ptrcmp, st_ptrhash);
+  /* Loop over the number of elements in layerArray */
+  for (layerIndex = 0; layerIndex < array_n(layerArray); layerIndex++) {
+    /* reset new variables in the support of this array */
+    newVars = 0;
+    
+    (void) fprintf(vis_stdout, "Layer %d: ", layerIndex);
+
+    /* Access the layer info */
+    currentLayer = ResLayerFetchIthLayer(layerArray, layerIndex);  
+
+    /* Print the nodes in a layer that are not PIs */
+    LayerForEachNode(currentLayer, i, nodePtr) {
+      (void) fprintf(vis_stdout, "%s ", Ntk_NodeReadName(nodePtr));
+
+      /* store fanin nodes in the table, keep count */
+      Ntk_NodeForEachFanin(nodePtr, j, faninNodePtr) {
+	if (!st_is_member(faninTable, (char *)faninNodePtr)) {
+	  if (!((Ntk_NodeTestIsLatch(nodePtr) &&
+		    (Ntk_NodeTestIsLatchDataInput(faninNodePtr) ||
+		     Ntk_NodeTestIsLatchInitialInput(faninNodePtr))) ||
+		Ntk_NodeTestIsConstant(faninNodePtr))) {
+	    
+	    st_insert(faninTable, (char *)faninNodePtr, NIL(char));
+	    newVars++;
+	  }
+	}
+      }
+    }
+
+    (void) fprintf(vis_stdout,": SUPPORT = %d", newVars);
+    (void) fprintf(vis_stdout, "\n");
+
+    
+  } /* End of for every layer */
+
+  /* Clean up */
+  st_free_table(faninTable);
+  return;
+} /* End of ResLayerPrintInfo */
+
+
+/**Function********************************************************************
+
+  Synopsis [Free the layer information computed for each network.]
+
+  Description [Free the layer information computed for each network. Takes the
+  layer structure to be freed as the argument.]
+  
+  SideEffects   []
+
+  SeeAlso            [Res_NetworkResidueVerify]
+
+******************************************************************************/
+void
+ResLayerArrayFree(array_t *layerArray)
+{
+  int i, end;
+  array_t *currentLayer;
+
+  i = 0;
+  end = array_n(layerArray);
+  for (i =0; i < end ; i++) {
+    currentLayer = ResLayerFetchIthLayer(layerArray, i);
+    LayerFree(currentLayer);
+  }
+  array_free(layerArray);
+} /* End of ResLayerArrayFree */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Computes the layers of nodes of the network based on the "as soon
+  as possible" heuristic.]
+
+  Description [Computes the layers of nodes of the network based on the "as
+  soon as possible" heuristic. When composing an Add with nodes starting from
+  the primary outputs, to the primary inputs, several nodes in the network are
+  candidates for composition simultaneously producing what we decided to call
+  "layers". This procedure schedules the composition of the nodes as soon as
+  possible under the "One-Time Rule" restriction. The One-Time Rule states that
+  a node may be composed into the ADD only when all its fanouts have been
+  composed in. The "as soon as possible" schedule is such that a node n is
+  composed with its fanin nodes f1,...,fn AS SOON AS all its fanouts have been
+  composed. The procedure returns an array of layers. Each node appears in only
+  one layer. The procedure takes as arguments the network whose layers are
+  required, the outputs to be considered and the outputs to be ignored.]
+
+  SideEffects        []
+
+  SeeAlso            [Res_NetworkResidueVerify ComputeCompositionLayersAlap]
+
+******************************************************************************/
+static array_t *
+ComputeCompositionLayersAsap(Ntk_Network_t *network, 
+			     array_t *outputArray,   
+			     array_t *ignoreArray)
+{
+  Ntk_Node_t *nodePtr, *faninNodePtr; /* variables to store node pointers */
+  int i, j, k;                        /* iterators */
+  st_generator *stGen;                /* generator to step through st_table */
+  char *key;                          /* values to read from st_table */
+  lsGen listGen;                      /* list generator to step through nodes */
+  array_t *currentLayer, *nextLayer;  /* array of nodes belonging to a layer */
+  array_t *layerArray;                /* array of layers */
+  st_table *fanoutCountTable;         /* table to store fanout counts of each
+				       * node
+				       */
+  int fanoutCount;                    /* variable to store fanout count of a
+				       * node
+				       */
+  int value;                          /* to read value off the st_table */
+  st_table *visitedTable;             /* table to store visited nodes */
+  
+  /* create a fanout count table starting with all nodes except PIs,
+   * constant node or a shadow node for any node but a latch(counts as
+   * comb output).
+   */
+  fanoutCountTable = st_init_table(st_ptrcmp, st_ptrhash); 
+  Ntk_NetworkForEachNode(network, listGen, nodePtr) {
+    /* does not nodes like PIs, shadow nodes, constants, undefined
+     * nodes to compute the fanouts, since they do not have to be
+     * composed into the circuit.
+     */
+    if ((Ntk_NodeTestIsCombOutput(nodePtr)) ||
+	 (!(Ntk_NodeTestIsCombInput(nodePtr) ||
+	  Ntk_NodeTestIsConstant(nodePtr) ||
+	  Ntk_NodeTestIsUndefined(nodePtr) ||  
+	  Ntk_NodeTestIsShadow(nodePtr)))) {
+      st_insert(fanoutCountTable, (char *)nodePtr, 
+		(char *)(long)Ntk_NodeReadNumFanouts(nodePtr));
+    }
+  }
+  
+  /* take out outputs in directly verified table, if so desired */
+  /* Assume ignore table has node pointers , reduce fanout count of
+   * transitive fanin of these nodes
+   */
+  if (ignoreArray != NULL) {
+    visitedTable = st_init_table(st_ptrcmp, st_ptrhash);
+    arrayForEachItem(Ntk_Node_t *, ignoreArray, i, nodePtr) {
+      /* each key is an output node */
+      RecursiveDecrementFanoutCount(nodePtr, fanoutCountTable, visitedTable);
+    }
+    st_free_table(visitedTable);
+
+    /* remove all nodes that are primary inputs and those with fanout
+     * count 0 providing they are not primary outputs/ or latch inputs
+     * or latch initial values.
+     */
+    st_foreach_item_int(fanoutCountTable, stGen, &key, &value) {
+      fanoutCount = value;
+      nodePtr = (Ntk_Node_t *)key;
+      assert(fanoutCount >= -1);
+      if ((!Ntk_NodeTestIsCombOutput(nodePtr))
+	  && (fanoutCount <= 0)) {
+	/* delete the item corresponding to fanoutCount i.e. value */
+	st_delete_int(fanoutCountTable, (char **)&key, &value);
+      }
+    }
+    /* remove all outputs that belong to ignore outputs */
+    arrayForEachItem(Ntk_Node_t *, ignoreArray, i, nodePtr) {
+      st_delete_int(fanoutCountTable, &nodePtr, &value);
+    }
+  }  
+
+  /* start preparing the layer array */
+  layerArray = array_alloc(array_t *, 0); 
+  currentLayer = LayerCreateEmptyLayer();
+
+  /*  outputs form the first layer */
+  Ntk_NetworkForEachCombOutput(network, listGen, nodePtr) {
+    if (st_lookup_int(fanoutCountTable, (char *)nodePtr, &fanoutCount)) {
+      /* insert all outputs that aren't to be ignored in the first layer of the
+       * layer array
+       */
+      LayerAddNodeAtEnd(currentLayer, nodePtr);
+    }
+  }
+
+  /* if current layer is not empty */
+  while (ResLayerNumNodes(currentLayer) ) {
+    /* insert current layer into layer array */
+    array_insert_last(array_t *, layerArray, currentLayer);
+    nextLayer = LayerCreateEmptyLayer();
+    LayerForEachNode(currentLayer, i, nodePtr) {
+      Ntk_NodeForEachFanin(nodePtr, j, faninNodePtr) {
+	/* do not want to get the fanin for latch outputs */
+	if(!(Ntk_NodeTestIsConstant(nodePtr) ||
+	     (Ntk_NodeTestIsLatch(nodePtr) &&
+	     (Ntk_NodeTestIsLatchDataInput(faninNodePtr) ||
+	      Ntk_NodeTestIsLatchInitialInput(faninNodePtr))))) {
+	  if (!st_lookup_int(fanoutCountTable, (char *)faninNodePtr,
+			     &fanoutCount)) {
+	    /* maybe it is a PI or constant node */
+	    if (!(Ntk_NodeTestIsCombInput(faninNodePtr) ||
+		  Ntk_NodeTestIsConstant(faninNodePtr) ||
+		  Ntk_NodeTestIsUndefined(faninNodePtr) ||
+		  Ntk_NodeTestIsShadow(faninNodePtr))) {
+	      error_append("Fanin node %s should have been in table");
+	      error_append(Ntk_NodeReadName(faninNodePtr));
+	      /* Cleanup */
+	      arrayForEachItem(array_t *, layerArray, k, currentLayer) {
+		LayerFree(currentLayer);
+	      }
+	      array_free(layerArray);
+	      return NIL(array_t);
+	    } /* node is neither PI nor constant */
+	  } else { /* node is found in table */
+	    fanoutCount--;
+	    /* decrement fanout count, will go into a later layer */
+	    if (fanoutCount == 0) {
+	      /*
+	       * it is ready to be put in the array,
+	       * since its fanout count is 1
+	       */
+	      LayerAddNodeAtEnd(nextLayer, faninNodePtr);
+	    } else if (fanoutCount > 0) {
+		/* insert new decremented value in table */
+	      st_insert(fanoutCountTable, (char *)faninNodePtr,
+			(char *)(long)fanoutCount);
+
+	    } /* end of nodes fanout count larger than 1 */
+	  } /* end of fanin node found in fanout count table */
+	} /* do not want to get the fanin for latch outputs */
+      } /* end of iteration through all the fanin nodes of current node */
+    } /* end of iteration through all the nodes of current layer */
+    /* the fanout count ensures unique entry of elements ????*/
+    currentLayer = nextLayer;
+  } /* end of while some nodes in current layer */  
+  
+  /* the loop always exits with an empty array */
+  LayerFree(currentLayer);
+  st_free_table(fanoutCountTable);
+  if (array_n(layerArray) == 0) {
+    array_free(layerArray);
+    layerArray = NIL(array_t);
+  }
+
+  return (layerArray);
+  
+} /* End of ComputeCompositionLayersAsap */
+
+/**Function**********************************************************************
+
+  Synopsis [ Computes the layers of nodes of the network based on the "as late
+  as possible" heuristic.]
+
+  Description [ Computes the layers of nodes of the network based on the "as
+  late as possible" heuristic. When composing an Add with nodes starting from
+  the primary outputs, to the primary inputs, several nodes in the network are
+  candidates for composition simultaneously producing what we decided to call
+  "layers". This procedure schedules the composition of the nodes as late as
+  possible under the "One-Time Rule" restriction. The One-Time Rule states that
+  a node may be composed into the ADD only when all its fanouts have been
+  composed in. This procedure schedules the composition of the nodes as "late"
+  as possible i.e. only when no further composition can be done without
+  composing the node in question. The order of composition is computed by
+  labeling every node with its maximum distance from the primary inputs. The
+  nodes are then scheduled starting with those with the larger depth and
+  descending until reaching the inputs. Note that with this heuristic we still
+  guarantee that every node appears in one single layer, therefore, it is only
+  composed once. This is not "strictly as late as possible" as the symmetric
+  opposite of the as soon as possible technique. But this scheduling has the
+  additional win of taking advantage of the varying depths of the different
+  paths in the circuit and scheduling the nodes evenly. The procedure takes as
+  arguments the network whose layers are required, the outputs to be considered
+  and the outputs to be ignored.]
+
+  SideEffects []
+
+  SeeAlso            [ResComputeCompositionLayers ComputeCompositionLayersAsap]
+
+  ******************************************************************************/
+static array_t *
+ComputeCompositionLayersAlap(Ntk_Network_t *network,
+			     array_t *outputArray,  
+			     array_t *ignoreArray)
+{
+  Ntk_Node_t *nodePtr;	     /* node being processed  */
+  array_t *layerArray;       /* array of layers */
+  array_t *currentLayer;     /* layer of nodes */
+  st_table *nodeLabelling;   /* labeling of a node, its farthest distance
+			      * from the primary input
+			      */
+  int numLayers;             /* Number of Layers */
+  int layerIndex;            /* index of a layer (from the primary output */
+  int arrayIndex;            /* iterator */
+  st_generator *stGen;       /* generator to step through table */
+  char *key;                 /* values to read from table */
+  int value;                 /* integer value to read from the table */
+
+  /* Initialize the labeling table */
+  nodeLabelling = ComputeTransitiveFanin(outputArray);
+
+  /* Compute the labeling of the nodes */
+  numLayers = ComputeAlapLabelling(network, nodeLabelling);
+
+  /* Create the layerArray structure */
+  layerArray = array_alloc(array_t *, numLayers);
+  /* initialize layers */
+  for (layerIndex = 0; layerIndex < numLayers; layerIndex++) {
+    currentLayer = LayerCreateEmptyLayer();
+    array_insert(array_t *, layerArray, layerIndex, currentLayer);
+  } /* end of for */
+
+  /* insert elements of the st_table in the layers */
+  st_foreach_item_int(nodeLabelling, stGen, &key, &value) {
+    layerIndex = value;
+    nodePtr = (Ntk_Node_t *)key;
+    /* don't put PIs or comb inputs or constants or undefined
+     * nodes in layer array
+     */
+    if ((Ntk_NodeTestIsCombOutput(nodePtr)) ||
+	((layerIndex > 0) &&
+	 !(Ntk_NodeTestIsCombInput(nodePtr) ||
+	   Ntk_NodeTestIsConstant(nodePtr) ||
+	   Ntk_NodeTestIsUndefined(nodePtr) ||
+	   Ntk_NodeTestIsShadow(nodePtr)))) {
+      /* the layers are arranged in reverse order of their farthest
+       * distance from the node. Hence each node is inserted into
+       * the numLayers-1-layerIndex. Nodes with layerIndex should be
+       * put in the last array since they are probably constants
+       * at the primary outputs or latch initial value. LayerIndex
+       * could be 0 for primary outputs if it does not appear in the
+       * transitive fanin of the comb inputs. 
+       */
+      if (layerIndex == 0) {
+	arrayIndex = 0;
+	assert(Ntk_NodeTestIsCombOutput(nodePtr) == 1);
+      } else {
+	arrayIndex = numLayers - layerIndex;
+      }
+      currentLayer = array_fetch(array_t *, layerArray, arrayIndex);
+      LayerAddNodeAtEnd(currentLayer, nodePtr);
+    }
+  }
+  /* Clean up */
+  st_free_table(nodeLabelling);
+
+  
+  return layerArray;
+} /* End of ComputeCompositionLayersAlap */
+
+
+/**Function*********************************************************************
+
+  Synopsis [ Procedure to label each node with its maximum distance from the
+  primary inputs.]
+
+  Description [The procedure processes iteratively every input. For each of
+  them, it labels recursively its transitive output keeping always the larger
+  depth value. The procedure accepts as arguments the network that need to be
+  labeled and a table with the labeling of nodes to be filled) and returns the
+  maximum layer size.]
+
+  SideEffects        [It modifies the st_table passed as parameter.]
+
+  SeeAlso [ComputeCompositionLayersAlap ComputeAlapLabellingRecur]
+
+  ******************************************************************************/
+static int
+ComputeAlapLabelling(Ntk_Network_t *network, 
+		     st_table *nodeLabelling)
+{
+  Ntk_Node_t *nodePtr; /* Node being processed */
+  lsGen gen;           /* For list traversal */
+  int numLayers;       /* To return as result */
+  int outputDepth;     /* Depth of the output being processed */
+
+  assert(nodeLabelling != NIL(st_table));
+
+  /* For primary inputs in the table (those not in the table
+   * are in the transitive fanin of the ignored outputs only
+   */
+  Ntk_NetworkForEachCombInput(network, gen, nodePtr) {
+    /* do it for fanouts that are in table only */
+    if (st_is_member(nodeLabelling, (char *)nodePtr)) {
+      ComputeAlapLabellingRecur(nodePtr, nodeLabelling);
+    }
+  }
+
+  /* Compute the number of layers */
+  numLayers = 0;
+  Ntk_NetworkForEachCombOutput(network, gen, nodePtr) {
+    /* only those outputs not be to be ignored */
+    if (st_lookup_int(nodeLabelling, (char *)nodePtr, &outputDepth)) {
+      if (outputDepth > numLayers ) {
+	numLayers = outputDepth;
+      } /* End of if */
+    }
+  }
+  
+  return numLayers;
+} /* End of ComputeAlapLabelling */
+
+/**Function*********************************************************************
+
+  Synopsis [Recursive procedure to label every node with its maximum depth
+  from the primary inputs.]
+
+  Description [It labels every node with the current depth and
+  proceeds recursively through the fanouts. The procedure accepts as
+  its arguments the node it is currently recurring on and the table
+  with labeling of the nodes(max distance from the PIs) which gets
+  updated.]
+
+  SideEffects        [It modifies the st_table passed as parameter]
+
+  SeeAlso            [ComputeAlapLabelling]
+
+  ******************************************************************************/
+static void
+ComputeAlapLabellingRecur(Ntk_Node_t *node,
+			  st_table *nodeLabelling)
+{
+  Ntk_Node_t *fanoutPtr;
+  int nodeDepth;
+  int fanoutDepth;
+  int i;
+
+  /* Trivial case */
+  if (Ntk_NodeReadNumFanouts(node) == 0) {
+    return;
+  } /* End of if */
+
+  /* Look up information for the current node */
+  st_lookup_int(nodeLabelling, (char *)node, &nodeDepth);
+  
+  /* Iterate over its fanouts */
+  Ntk_NodeForEachFanout(node, i, fanoutPtr) {
+    /* Do not process as soon as an input is found beyond an output */
+    if (!((Ntk_NodeTestIsLatchDataInput(node) ||
+           Ntk_NodeTestIsLatchInitialInput(node)) &&
+	  Ntk_NodeTestIsLatch(fanoutPtr))) {
+      if (st_is_member(nodeLabelling, (char *)fanoutPtr)) {
+	/* Look up information for the fanout */
+	st_lookup_int(nodeLabelling, (char *)fanoutPtr, &fanoutDepth);
+	/* If the fanout depth needs to be modified, do so, and recur */
+	if (nodeDepth >= fanoutDepth) {
+	  st_insert(nodeLabelling, (char *)fanoutPtr, 
+		    (char *)(long)(nodeDepth + 1));
+	  ComputeAlapLabellingRecur(fanoutPtr, nodeLabelling);
+	} /* End of if */
+      } /* End of if */
+    } /* End of if */
+  } /* End of for each fanout */
+
+  return;
+} /* End of ComputeAlapLabellingRecur */
+
+
+/**Function*********************************************************************
+
+  Synopsis    [Procedure that computes the transitive fanin of a set
+  of nodes in an array.]
+
+  Description [[Procedure that computes the transitive fanin of a set
+  of nodes in an array. The procedure puts the nodes themselves into the
+  array too.The procedure takes as arguments the array whose transitive
+  fanin need to be computed and returns an st_table with the fanin.]
+  
+  SideEffects []
+
+  SeeAlso     [ComputeCompositionLayersAlap ComputeTransitiveFaninRecur]
+
+  *****************************************************************************/
+static st_table *
+ComputeTransitiveFanin(array_t *outputArray)
+{
+  Ntk_Node_t *nodePtr;
+  st_table * faninTable;
+  int i;
+  
+  faninTable = st_init_table(st_ptrcmp, st_ptrhash);
+  arrayForEachItem(Ntk_Node_t *, outputArray, i, nodePtr) {
+    ComputeTransitiveFaninRecur(nodePtr, faninTable);
+  }
+  return faninTable;
+} /* End of ComputeTransitiveFanin */
+
+/**Function*********************************************************************
+
+  Synopsis    [Recursive procedure to compute the transitive fanin of
+  a node.]
+  
+  Description [ Recursive procedure to compute the transitive fanin of a
+  node. After computing the transitive fanin, the node itself goes into the
+  table. The procedure takes in as arguments the node it is recurring on and
+  the table of fanin encountered.]
+  
+  SideEffects []
+
+  SeeAlso     [ComputeTransitiveFanin]
+
+  *****************************************************************************/
+static void
+ComputeTransitiveFaninRecur(Ntk_Node_t *nodePtr,  
+			    st_table *faninTable)
+{
+  Ntk_Node_t *faninNodePtr;
+  int i;
+
+  if (st_lookup(faninTable, (char *)nodePtr, NIL(char *))) {
+    return;
+  }
+
+
+  /* recur on fanin nodes */
+  Ntk_NodeForEachFanin(nodePtr, i, faninNodePtr) {
+    /* Test this case cos other comb inputs have no fanins */
+    if (!((Ntk_NodeTestIsLatchDataInput(faninNodePtr) ||
+	   Ntk_NodeTestIsLatchInitialInput(faninNodePtr)) &&
+	  Ntk_NodeTestIsLatch(nodePtr))) {
+      ComputeTransitiveFaninRecur(faninNodePtr, faninTable);
+    } /* end of if */
+  } /* iterate over all fanins */
+  
+  st_insert(faninTable, (char *)nodePtr, NIL(char));
+  return;
+
+} /* End of ComputeTransitiveFaninRecur */
+
+/**Function*********************************************************************
+
+  Synopsis    [Function to decrement fanout count]
+  
+  Description [Recursive procedure that reduces the fanout count of the
+  current node and recurs on its fanin. Stops when Pis or constant nodes are
+  hit which have no fanins. The procedure takes in as arguments the current it
+  is recurring on and the table with nodes and their fanout counts.]
+  
+  SideEffects []
+
+  SeeAlso     [ComputeCompositionLayersAsap]
+
+  *****************************************************************************/
+static void
+RecursiveDecrementFanoutCount(Ntk_Node_t *nodePtr, 
+			      st_table *fanoutCountTable,
+			      st_table *visitedTable)
+{
+  Ntk_Node_t *faninNodePtr;
+  int i, fanoutCount;
+
+  /* the following kinds of nodes will not be in the table. */
+  if ((!Ntk_NodeTestIsCombOutput(nodePtr)) && 
+       (Ntk_NodeTestIsCombInput(nodePtr) ||
+	Ntk_NodeTestIsUndefined(nodePtr)||
+	Ntk_NodeTestIsConstant(nodePtr) ||
+	Ntk_NodeTestIsShadow(nodePtr))) {
+    return;
+  }
+  /* all nodes called here should exist in table */
+  if (!st_lookup_int(fanoutCountTable, (char *)nodePtr, &fanoutCount)){
+    error_append("Node ");
+    error_append(Ntk_NodeReadName(nodePtr));
+    error_append(" should have been in table\n");
+    return;
+  }
+
+  fanoutCount--;
+  /* reduce fanout count of node */
+  st_insert(fanoutCountTable, (char *)nodePtr, (char *)(long)fanoutCount);
+  /* if this node is visited, decrement its fanout but do not proceed
+   * any further (i.e. do not proceed with its fanins
+   */
+  if (st_is_member(visitedTable, (char *)nodePtr)) {
+    return;
+  } else {
+    st_insert(visitedTable, (char *)nodePtr, NIL(char));
+
+    /* 
+     * recur with fanin nodes except nodes with no fanins (that arent in table)
+     * and latch outputs 
+     */
+    Ntk_NodeForEachFanin(nodePtr, i, faninNodePtr) {
+      /* may be a redundant test, since it will pop out in the first line of
+       * the procedure anyways. 
+       */
+      if (!(Ntk_NodeTestIsConstant(faninNodePtr) ||
+	  ((Ntk_NodeTestIsLatchDataInput(faninNodePtr) ||
+	    Ntk_NodeTestIsLatchInitialInput(faninNodePtr)) &&
+	   Ntk_NodeTestIsLatch(nodePtr)))) {
+	RecursiveDecrementFanoutCount(faninNodePtr, fanoutCountTable, visitedTable);
+      } 
+    } /* end of iterating over fanins */
+  } /* end of else if not visited */
+  return;
+} /* End of RecursiveDecrementFanoutCount */
Index: vis_dev/vis-2.3/src/res/resRes.c
===================================================================
--- vis_dev/vis-2.3/src/res/resRes.c	(revision 14)
+++ vis_dev/vis-2.3/src/res/resRes.c	(revision 14)
@@ -0,0 +1,392 @@
+/**CFile***********************************************************************
+
+  FileName    [resRes.c]
+
+  PackageName [res]
+
+  Synopsis    [Data manipulation routines of the Res_ResidueInfo structure.]
+
+  SeeAlso     [Res_ResidueInfo]
+
+  Author      [Kavita Ravi    <ravi@boulder.colorado.edu> and
+	       Abelardo Pardo <abel@boulder.colorado.edu>]
+	       
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "resInt.h" 
+
+static char rcsid[] UNUSED = "$Id: resRes.c,v 1.18 2002/08/26 05:53:31 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Frees the structure storing the information related to the
+  residual verification.]
+
+  SideEffects []
+
+  SeeAlso [Res_ResidualInfo]
+
+******************************************************************************/
+void
+Res_ResidueInfoFree(Res_ResidueInfo_t *residue)
+{
+  int i;
+  /* Deallocate the information in the primeInfoArray, if any */
+  if (residue->primeInfoArray != NIL(PerPrimeInfo_t)) {
+
+    
+    for (i = 0; i < residue->numOfPrimes; i++) {
+      if ((residue->primeInfoArray[i]).residueDd != NIL(bdd_node)) {
+	bdd_recursive_deref(residue->ddManager, (residue->primeInfoArray[i]).residueDd);
+      }
+    }
+    FREE(residue->primeInfoArray);
+  } /* End of if */
+
+  FREE(residue->networkName);
+  FREE(residue->networkNameVerifiedAgainst);
+  FREE(residue);
+  return;
+} /* End of Res_ResidueInfoFree */
+
+/**Function********************************************************************
+
+  Synopsis  [Call-back function to free the residue information.]
+
+  Description [A pointer to this function will be stored in the network
+  together with the pointer to the structure. Whenever the network needs to
+  deallocate the residue information this function is called.]
+
+  SideEffects  []
+
+  SeeAlso  [Ntk_NetworkAddApplInfo]
+
+******************************************************************************/
+void
+Res_ResidueInfoFreeCallback(void *data)
+{
+  Res_ResidueInfoFree((Res_ResidueInfo_t *) data);
+  ResResidueFreeVariableManager();
+} /* End of Res_ResidueInfoFreeCallback */
+
+/**Function********************************************************************
+
+  Synopsis           [Reads the residue information  attached to a network.]
+
+  SideEffects        []
+
+  SeeAlso            [CommandResVerify]
+
+******************************************************************************/
+Res_ResidueInfo_t *
+Res_NetworkReadResidueInfo(Ntk_Network_t *network)
+{
+  return (Res_ResidueInfo_t *)Ntk_NetworkReadApplInfo(network, RES_NETWORK_APPL_KEY);
+} /* End of Res_NetworkReadResidueInfo */
+
+/**Function********************************************************************
+
+  Synopsis [External function to read the name field of Res_ResidueInfo.]
+
+  SideEffects        []
+
+  SeeAlso            [CommandResVerify]
+
+******************************************************************************/
+char *
+Res_ResidueInfoReadName(Res_ResidueInfo_t *residuePtr)
+{
+  return (char *)(ResResidueInfoReadNetworkName(residuePtr));
+} /* End of Res_ResidueInfoReadName */
+
+/**Function********************************************************************
+
+  Synopsis [External function to read the number of inputs in Res_ResidueInfo.]
+
+  SideEffects        []
+
+  SeeAlso            [CommandResVerify]
+  
+
+******************************************************************************/
+int
+Res_ResidueInfoReadNumInputs(Res_ResidueInfo_t *residuePtr)
+{
+  return ResResidueInfoReadNumInputs(residuePtr);
+} /* End of Res_ResidueInfoReadNumInputs */
+
+/**Function********************************************************************
+
+  Synopsis [External function to read the number of outputs in
+  Res_ResidueInfo.]
+
+  SideEffects        []
+
+  SeeAlso            [CommandResVerify]
+  
+******************************************************************************/
+int
+Res_ResidueInfoReadNumOutputs(Res_ResidueInfo_t *residuePtr)
+{
+  return ResResidueInfoReadNumOutputs(residuePtr);
+} /* End of Res_ResidueInfoReadNumOutputs */
+
+/**Function********************************************************************
+
+  Synopsis [External function to read the number of directly verified outputs in
+  Res_ResidueInfo.]
+
+  SideEffects        []
+
+  SeeAlso            [CommandResVerify]
+
+******************************************************************************/
+int
+Res_ResidueInfoReadNumDirectVerifiedOutputs(Res_ResidueInfo_t *residuePtr)
+{
+  return ResResidueInfoReadNumDirectVerifiedOutputs(residuePtr);
+} /* End of Res_ResidueInfoReadNumDirectVerifiedOutputs */
+
+/**Function********************************************************************
+
+  Synopsis [External function to read the cpu seconds spent in directly
+  verifying outputs in Res_ResidueInfo.]
+
+  SideEffects        []
+
+  SeeAlso            [CommandResVerify]
+
+******************************************************************************/
+int
+Res_ResidueInfoReadCpuDirectVerif(Res_ResidueInfo_t *residuePtr)
+{
+  return (int) ResResidueInfoReadCpuDirectVerif(residuePtr);
+} /* End of Res_ResidueInfoReadCpuDirectVerif */
+
+/**Function********************************************************************
+
+  Synopsis [External function to read the number of primes in Res_ResidueInfo.]
+
+  SideEffects        []
+
+  SeeAlso            [CommandResVerify]
+
+******************************************************************************/
+int
+Res_ResidueInfoReadNumOfPrimes(Res_ResidueInfo_t *residuePtr)
+{
+  return ResResidueInfoReadNumOfPrimes(residuePtr);
+} /* End of Res_ResidueInfoReadNumOfPrimes */
+
+/**Function********************************************************************
+
+  Synopsis [External function to read the success field in Res_ResidueInfo.]
+
+  SideEffects        []
+
+  SeeAlso            [CommandResVerify]
+
+******************************************************************************/
+int
+Res_ResidueInfoReadSuccess(Res_ResidueInfo_t *residuePtr)
+{
+  return ResResidueInfoReadSuccess(residuePtr);
+} /* End of Res_ResidueInfoReadNumOfPrimes */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis           [Wrapper procedure to create a result data structure.]
+
+  SideEffects        []
+
+******************************************************************************/
+Res_ResidueInfo_t *
+ResNetworkResidueInfoReadOrCreate(Ntk_Network_t *network)
+{
+  Res_ResidueInfo_t *result;
+
+  assert(network != NIL(Ntk_Network_t));
+
+  result = (Res_ResidueInfo_t *)Ntk_NetworkReadApplInfo(network,
+							RES_NETWORK_APPL_KEY);
+  if (result == NIL(Res_ResidueInfo_t)) {
+    result = ResResidueInfoAllocate(Ntk_NetworkReadName(network));
+    result->ddManager = (bdd_manager *)Ntk_NetworkReadMddManager(network);
+  } /* End of if */
+
+  return result;
+} /* End of ResNetworkResidueInfoReadOrCreate*/
+
+
+/**Function********************************************************************
+
+  Synopsis           [Function that allocates the Res_ResidueInfo_t.]
+
+  Description [Only the name field is initialized. The field primeInfoArray it
+  is initialized to NIL. In a later phase, that field may be initialized with
+  the array of the correct size by means of Res_ResidueAllocatePrimeInfo.]
+
+  SideEffects        []
+
+  SeeAlso            [ResResidueAllocatePrimeInfo]
+
+******************************************************************************/
+Res_ResidueInfo_t *
+ResResidueInfoAllocate(char *name)
+{
+  Res_ResidueInfo_t *result = ALLOC(Res_ResidueInfo_t, 1);
+
+  result->networkName = util_strsav(name);
+  result->networkNameVerifiedAgainst = NULL;
+  result->numInputs = 0;
+  result->numOutputs = 0;
+  result->numDirectVerifiedOutputs = 0;
+  result->cpuDirectVerif = 0.0;
+  result->numOfPrimes = 0;
+  result->primeInfoArray = NIL(PerPrimeInfo_t);
+  result->success = RES_NOT_VERIFIED;
+  result->successDirectVerification = RES_NOT_VERIFIED;
+  result->ddManager = NIL(bdd_manager);
+  return result;
+} /* End of ResResidueInfoAllocate */
+
+/**Function********************************************************************
+
+  Synopsis [Allocates the array primeInfoArray inside the Res_ResidueInfo_t.]
+
+  SideEffects  []
+
+  SeeAlso  [Res_ResidueAllocate]
+
+******************************************************************************/
+void
+ResResidueInfoAllocatePrimeInfoArray(Res_ResidueInfo_t *residueInfo,
+				     int numOfPrimes,
+				     int *tableOfPrimes)
+{
+  int i;
+
+  residueInfo->primeInfoArray = ALLOC(PerPrimeInfo_t, numOfPrimes);
+
+  for (i = 0; i < numOfPrimes; i++) {
+    ResResidueInfoSetPerPrimeInfo(residueInfo, i, tableOfPrimes[i], 0, 0, 
+				  NIL(bdd_node));
+  }
+
+  return;
+} /* End of ResResidualAllocatePrimeInfoArray */
+
+/**Function********************************************************************
+
+  Synopsis [Prints the residue and primeInfoArray information.]
+
+  SideEffects  []
+
+  SeeAlso  [Res_ResidueAllocate]
+
+******************************************************************************/
+void
+Res_ResidueInfoPrint(Res_ResidueInfo_t *result)
+{
+
+  int i;
+
+  if (result->success) { 
+    fprintf(vis_stdout, "The circuit %s was successfully verified against %s.\n", 
+	    (char *)result->networkName, (char *)result->networkNameVerifiedAgainst);
+    fprintf(vis_stdout, "The circuit has %d inputs and %d outputs ", result->numInputs,
+	   result->numOutputs);
+    fprintf(vis_stdout, "of which %d were directly verified.\n", 
+	                                   result->numDirectVerifiedOutputs);
+   
+    if (result->numDirectVerifiedOutputs) {
+      fprintf(vis_stdout, "Direct verification took %.3f seconds\n", 
+	                                         result->cpuDirectVerif/1000.0);
+    }
+    
+    if (result->numOfPrimes) {
+      fprintf(vis_stdout, "In residue verification using %d primes, \n", 
+	                                     result->numOfPrimes);
+      fprintf(vis_stdout, "Primes: ");
+      for (i = 0; i < result->numOfPrimes; i++) {
+	
+	fprintf(vis_stdout, "%d ", result->primeInfoArray[i].primeNumber);
+      }
+      fprintf(vis_stdout, "\n");
+      fprintf(vis_stdout, "Times: ");
+      for (i = 0; i < result->numOfPrimes; i++) {
+	
+	fprintf(vis_stdout, "%.2f ", result->primeInfoArray[i].cpuTime);
+      }
+      fprintf(vis_stdout, "\n");
+    }
+  }
+
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/res/resSmartVarUse.c
===================================================================
--- vis_dev/vis-2.3/src/res/resSmartVarUse.c	(revision 14)
+++ vis_dev/vis-2.3/src/res/resSmartVarUse.c	(revision 14)
@@ -0,0 +1,555 @@
+/**CFile***********************************************************************
+
+  FileName    [resSmartVarUse.c]
+
+  PackageName [res]
+
+  Synopsis [This file provides functions to handle Dd variables in the
+  composition phase of the residue verification.]
+
+  Description [When composing a residue bdd from outputs to inputs, in
+  principle, every node used on that composition should have a unique
+  variable Id. However, the number of nodes may be too big for the
+  manager to handle. The functions in this file keep track of the
+  variables in use during residue verification. In certain sense,
+  these functions are the interface of some kind of manager, handling
+  the requirements of variables. That is why there are some static
+  variables defined in this file.]
+
+  Author      [Kavita Ravi    <ravi@boulder.colorado.edu> and 
+               Abelardo Pardo <abel@boulder.colorado.edu>]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "resInt.h" 
+#include "var_set.h"
+
+static char rcsid[] UNUSED = "$Id: resSmartVarUse.c,v 1.15 2002/09/08 23:56:11 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define DEFAULT_NUMBER_OF_VARIABLES (sizeof(int)*16)
+#define ELEMENTS_PER_WORD (sizeof(int)<<3)
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+static var_set_t *idSet = NIL(var_set_t);
+static int numVarsInUse = 0;
+
+/*--------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+/* based on the fact that var set word size = ELEMENTS_PER_WORD */
+#define MaxSizeOfSet(set) ((set)->n_words * ELEMENTS_PER_WORD)
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static var_set_t * InitializeVariableManager(int numOfVars);
+static void ResizeVariableManager(int newSize);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [This procedure calls the mdd_create_variables in order to create 
+  mvar_list field of the hook.]
+  
+  Description [ This procedure calls the mdd_create_variables in order to
+  create mvar_list field of the hook. IMPORTANT: The mdd_create_variables
+  procedure creates the variables in succession. So if new variables are
+  required that are not in succession, those will not be created and hence
+  cannot be used. This procedure takes as arguments the DD manager and the
+  number of variables that need to be added to the manager.]
+
+  SideEffects   [It modifies the manager->hook->mdd field.]
+
+  SeeAlso            [Res_NetworkResidueVerify]
+
+******************************************************************************/
+void
+MddCreateVariables(mdd_manager *mgr,     
+		   int numVarsToBeAdded) 
+{
+    array_t *mvar_values;
+    array_t *mvar_names = NIL(array_t);
+    array_t *mvar_strides = NIL(array_t);
+    int i, two_values;
+
+    if (numVarsToBeAdded <= 0) return;
+    
+    /* Create 2 mvar values 0,1 */
+    mvar_values = array_alloc(int, numVarsToBeAdded);    
+
+    /* Assume we create only Bdd variables here */
+    two_values = 2;
+    for(i = 0; i < numVarsToBeAdded; i++) {
+      array_insert(int, mvar_values, i, two_values);
+    }
+
+    /* creates the mdd variables and updates the mvar_list field */
+    mdd_create_variables(mgr, mvar_values, mvar_names, mvar_strides);
+    
+    array_free(mvar_values);
+
+} /* End of MddCreateVariables */
+
+/**Function********************************************************************
+
+  Synopsis [Manages the id assignment to the nodes in a smart way.]
+ 
+  Description [Manages the id assignment to the nodes in a smart way.  This
+  procedure is responsible for keeping track of which ids are in use during the
+  composition process. It is also responsible for allocating new Ids to nodes
+  with unassigned ids. The procedure reuses ids not in use to fill the new
+  requirements. it is also responsible for creating new variables in the
+  bdd_manager if required. The procedure returns a list of new Ids that can be
+  used to assign to the nodes. It also returns the inverse permutation array
+  that is used by the manager to shuffle the ids.  Assume that for each
+  composition idSet starts with empty set. The procedure accepts the following
+  parameters: the DD manager, an ordered list of nodes and their fanins and an
+  array to fill in the new Ids to be assigned to the unassigned nodes.]
+
+  SideEffects        []
+
+  SeeAlso            [ResResidueVarDeallocate]
+
+******************************************************************************/
+int *
+ResResidueVarAllocate(bdd_manager *ddManager,  
+			 lsList orderList,   
+                         array_t *newIdArray)
+{
+  lsGen listGen;             /* generator to step through a list of nodes */
+  Ntk_Node_t *nodePtr;       /* variable to store node pointer */
+  int nodeId;                /* mdd id of a node */
+  char *flagValue;           /* string to store flag value */
+  int newVarsRequired;       /* number of new variables required by layer */
+  int verbose;               /* verbosity value */
+  var_set_t *assignedSet;    /* var_set of assigned  Ids in this layer */
+  var_set_t *idsNotInList;   /* set of assigned Ids not in layer or fanin */
+  var_set_t *notAssignedSet; /* var_set of Ids not in this layer */
+  int *invPermArray;         /* inverse permutation array for shuffle */
+  int invPermIndex, newIdIndex;  /* iterators */
+  int i, j, id;              /* iterators */
+  int holes;                  /* number of holes filled so far */
+  int lastDdId;              /* last variable in dd manager before expansion */
+  int numberOfFreeVars;      /* number of free variables */
+
+  /* read verbosity flag */
+  verbose = 0;
+  flagValue = Cmd_FlagReadByName("residue_verbosity");
+  if (flagValue != NIL(char)) {
+    verbose = atoi(flagValue);
+  }
+  /* no work required */
+  if (!lsLength(orderList)) {
+    error_append("Something wrong order list is empty \n");
+    return NIL(int);
+  }
+
+  /* if manager not yet initialized, initialize here */
+  if (idSet == NIL(var_set_t)) {
+    ResResidueInitializeVariableManager(lsLength(orderList));
+  }
+
+  /* number of nodes with unassigned Ids */
+  newVarsRequired = 0;
+
+  /* for output nodes list, ids are assigned, just set them in the
+   * var set
+   */
+  if (var_set_is_empty(idSet)) {
+    invPermArray = ALLOC(int, bdd_num_vars(ddManager));
+    for (i = 0; (unsigned) i < bdd_num_vars(ddManager); i++) {
+      invPermArray[i] = bdd_get_id_from_level(ddManager, i);
+    }  
+    invPermIndex = 0;
+    lsForEachItem(orderList, listGen, nodePtr) {
+      nodeId = Ntk_NodeReadMddId(nodePtr);
+      assert(nodeId != NTK_UNASSIGNED_MDD_ID);
+      /* mark output node mdd id as in use */
+      var_set_set_elt(idSet, nodeId);
+      /* increase number of variables in use */
+      numVarsInUse++;
+      invPermArray[invPermIndex] = nodeId;
+      invPermArray[nodeId] = invPermIndex;
+      invPermIndex++;
+    }
+    return(invPermArray);
+  }
+
+  /* create a set for already assigned Ids */
+  assignedSet = var_set_new(MaxSizeOfSet(idSet));
+
+  /* for each item in the list, check against the set if Id
+   * is assigned. Also create a set to isolate assigned Ids
+   * that are not in the list. If unassigned Id, increment
+   * new variables
+   */
+  lsForEachItem(orderList, listGen, nodePtr) {
+    nodeId = Ntk_NodeReadMddId(nodePtr);
+    if (nodeId != NTK_UNASSIGNED_MDD_ID) {
+      assert(var_set_get_elt(idSet, nodeId) == 1);
+      /* create a var set with assigned ids in list */
+      var_set_set_elt(assignedSet, nodeId);
+    } else {
+      newVarsRequired++;
+    }
+  }
+  
+  /* find out from the set, the assigned Ids which are not in
+   * this list
+   */
+  idsNotInList = var_set_new(MaxSizeOfSet(idSet));
+  
+  /* do the operation idSet - assignedSet */
+  notAssignedSet = var_set_new(MaxSizeOfSet(idSet));
+  notAssignedSet = var_set_not(notAssignedSet, assignedSet);
+  idsNotInList = var_set_and(idsNotInList, notAssignedSet, idSet);
+  var_set_free(assignedSet);
+  var_set_free(notAssignedSet);
+  
+  
+  /* initialize return value */
+  if (newVarsRequired) {
+    
+    if (verbose >= 3) {
+      fprintf(vis_stdout, "Number of new variables to be assigned = %d\n",
+	      newVarsRequired);
+    }
+    /* compute number of free variables available in the manager */
+    numberOfFreeVars = MaxSizeOfSet(idSet) - numVarsInUse;
+
+    /* if too few free variables available, resize manager */
+    if (numberOfFreeVars < newVarsRequired) {
+      ResizeVariableManager(numVarsInUse + newVarsRequired);
+    }
+
+    invPermArray = ALLOC(int, bdd_num_vars(ddManager));
+    /* fill the inverse permutation array */
+    for (i = 0; (unsigned) i < bdd_num_vars(ddManager); i++) {
+      invPermArray[i] = bdd_get_id_from_level(ddManager, i);
+    }
+    /* create the array of new ids ; assign them starting from the
+     * top(in position) available ID
+     */
+    /* number of available ids in the variable manager */
+    holes = 0;
+    /* There could be two cases here: the number of new vars required
+     * are filled by holes or new variables are required in the DD
+     * manager to fill the requirement
+     */
+    
+    /* assign as many new Ids as required by the list */
+    for (i = 0; ((unsigned) i < bdd_num_vars(ddManager)) && (holes < newVarsRequired); i++) {
+      /* done when holes fill the new variable requirements or when
+       * new variables are needed in the ddManager
+       */
+      if (!var_set_get_elt(idSet, invPermArray[i])) {
+	/* the number of holes filled above are the variables that exist in
+	 * the ddManager and are not in use
+	 */
+        array_insert_last(int , newIdArray, invPermArray[i]);
+	holes++;
+      }
+    }
+    FREE(invPermArray);
+    if (verbose >= 4) {
+      if (holes) {
+	fprintf(vis_stdout, "Holes filled are ids:");
+	arrayForEachItem(int, newIdArray, i, nodeId) {
+	  fprintf(vis_stdout, "%d ", nodeId);
+	}
+	fprintf(vis_stdout, "\n");
+      }
+    }
+
+    
+    /* newVarsRequired-holes is the number of variables to be added to the
+     * mdd manager
+     */
+    if (holes < newVarsRequired) {
+      lastDdId = bdd_num_vars(ddManager);
+      /* create mdd variables, dirty stuff needed to add to the mvar_list */
+      MddCreateVariables((mdd_manager *)ddManager, newVarsRequired - holes);
+      
+      /* since all the variables were created in the end, use the ids
+       * starting at the size of the manager
+       */
+      for(i = 0; i < (newVarsRequired-holes); i++) {
+        array_insert_last(int, newIdArray, lastDdId+i);
+      }
+      if (verbose >= 4) {
+	fprintf(vis_stdout, "New dd ids assigned are: ");
+	for(i = 0; i < (newVarsRequired-holes); i++) {
+	  fprintf(vis_stdout, "%d ", array_fetch(int, newIdArray, holes+i));
+	} 
+	fprintf(vis_stdout, "\n");
+      }
+    } /* end of new vars needed to be assigned in the manager */
+  } /* end of new vars need to be assigned to nodes */
+
+  /* Create Inverse Permutation Array for the DD Manager */
+  
+  /* create inverse permutation array with nodes in list */ 
+  invPermArray = ALLOC(int, bdd_num_vars(ddManager));
+  invPermIndex = 0;
+  newIdIndex = 0;
+  if (verbose >= 4) {
+    fprintf(vis_stdout, "Final order to shuffle heap is:\n");
+  }
+  lsForEachItem(orderList, listGen, nodePtr) {
+    /* for nodes with assigned ids, get id from node */
+    nodeId = Ntk_NodeReadMddId(nodePtr);
+    if (nodeId == NTK_UNASSIGNED_MDD_ID) {
+      /* for nodes with unassigned ids, get id from array */
+      nodeId = array_fetch(int, newIdArray, newIdIndex);
+      /* update var set with teh new ids added */
+      var_set_set_elt(idSet, nodeId);
+      numVarsInUse++;
+      newIdIndex++;
+    }
+    invPermArray[invPermIndex] = nodeId;
+    if (verbose >= 4) {
+      fprintf(vis_stdout, "%d ", nodeId);
+    }
+    invPermIndex++;
+  }
+  /* all new ids been accounted for */
+  assert(newIdIndex == array_n(newIdArray));
+
+  /* push nodes  not in list with assigned Ids below those in list */
+  /* fill inv Perm array with Ids that are not in the list
+   * and not in the idsNotInList. These are ids in the
+   * ddManager that are not in idSet. 
+   */
+  /* if the number of ids in use in residue verification is less
+   * than that in the manager
+   */
+  if (((unsigned) invPermIndex < bdd_num_vars(ddManager)) ||
+      (!var_set_is_empty(idsNotInList))) {
+
+    /* collect the ids that are not in use in residue verification */
+    for (j = 0; (unsigned) j < bdd_num_vars(ddManager); j++) {
+      /* if not idSet, it means that it is not in use by
+       * residue verification, hence add to the end of invpermArray.
+       * Get id from the invPermArray that was filled in the
+       * above lines(where invPermArray was copied in the manager).
+       * Nodes already in the list will not get added since idSet
+       * was updated as the list was read. The id is read from the
+       * invPermArray so as to not disturb the relative order of
+       * the ids not in use and those in the manager. The check
+       * has the additional clause on the id <
+       * MaxSizeOfSet(idsNotInList)since idsNotInList was created
+       * before the additional variables were added to the manager.
+       */
+      id = bdd_get_id_from_level(ddManager, j);
+      if ((!var_set_get_elt(idSet, id)) ||
+	   (((unsigned) id < MaxSizeOfSet(idsNotInList)) &&
+	    (var_set_get_elt(idsNotInList, id)))) {
+	/* add to the inverse permutation array */
+	invPermArray[invPermIndex] = id;
+	if (verbose >= 4) {
+	  fprintf(vis_stdout, "%d ", id);
+	}
+	invPermIndex++;
+      } /* end of if not in idSet */
+    } /* end of iterating through the ids in the dd manager */
+  } /* end of if */ 
+  if (verbose >= 4) {
+    fprintf(vis_stdout, "\n");
+  }
+
+  var_set_free(idsNotInList);
+  assert(invPermIndex == bdd_num_vars(ddManager));
+  
+  return(invPermArray);
+}/* End of ResResidueVarAllocate */
+
+/**Function********************************************************************
+
+  Synopsis           [Frees the indices of the nodes in the array.]
+
+  Description        [Frees the indices of the nodes in the array. Decrements
+  the static variable numVarsInUse.]
+  
+  SideEffects        [Modifies the manager accordingly.]
+
+  SeeAlso            [ResResidueVarAllocate]
+
+******************************************************************************/
+void
+ResResidueVarDeallocate(array_t *currentLayer)
+{
+  int i=0;
+  int nodeId;
+  Ntk_Node_t *nodePtr;
+  
+  LayerForEachNode(currentLayer, i, nodePtr) {
+    nodeId = Ntk_NodeReadMddId(nodePtr);
+    var_set_clear_elt(idSet, nodeId);
+    numVarsInUse--;
+  }
+
+  return;
+} /* End of Res_ResidueVarUseDeallocate */
+
+/**Function********************************************************************
+
+  Synopsis           [Deallocates the variable manager.]
+
+  Description [ Deallocates the variable manager. Resets the static variable
+  - numVarsInUse.]
+
+  SideEffects        [Modifies the idSet accordingly.]
+
+  SeeAlso            [ResResidueInitializeVariableManager]
+
+
+******************************************************************************/
+void
+ResResidueFreeVariableManager(void)
+{
+
+  if (idSet == NIL(var_set_t)) {
+    return;
+  } /* End of if */
+
+  numVarsInUse = 0;
+  var_set_free(idSet);
+
+  idSet = NIL(var_set_t);
+
+  return;
+} /* End of ResResidueFreeVariableManager */
+
+/**Function********************************************************************
+
+  Synopsis [Initialize the variable manager with some variables.]
+
+  SideEffects        []
+
+  SeeAlso            [ResResidueFreeVariableManager]
+
+******************************************************************************/
+void
+ResResidueInitializeVariableManager(int numOfVars)
+{
+  idSet = InitializeVariableManager(numOfVars);
+  return;
+} /* End of ResResidueInitializeVariableManager */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Initializes the manager with an empty var_set.]
+
+  Description [Initializes the manager with an empty var_set. Default
+  initialization if passed 0 parameter.]
+  
+  SideEffects [Creates a var_set for variables]
+
+  SeeAlso            [Res_ResidueSmartVarUseAllocate]
+
+******************************************************************************/
+static var_set_t *
+InitializeVariableManager(int numOfVars)
+{
+  if (numOfVars != 0) {
+    if (numOfVars % ELEMENTS_PER_WORD != 0) {
+      /* round up to the next word length */
+      numOfVars = ((numOfVars/ELEMENTS_PER_WORD)+1)*ELEMENTS_PER_WORD;
+    } 
+  } else {
+    numOfVars = DEFAULT_NUMBER_OF_VARIABLES;
+  }
+
+  /* default value of number of words = 2 */
+  return var_set_new(numOfVars);
+
+} /* End of InitializeVariableManager */
+
+/**Function********************************************************************
+
+  Synopsis    [Resizes the variable manager.]
+
+  Description [ Resizes the size of the variable manager by calling
+  InitializeVariableManager with a larger size. Copies the old manager values
+  in idSet]
+  
+  SideEffects [Re-allocates memory for the manager]
+
+  SeeAlso [Res_ResidueSmartVarUseAllocate InitializeVariableManager]
+
+******************************************************************************/
+static void
+ResizeVariableManager(int newSize)
+{
+  var_set_t *newSet;
+  int i;
+
+  /* resize only if the new size is larger than the previous size */
+  assert(newSize > MaxSizeOfSet(idSet));
+
+  /* create a new set with the new size */
+  newSet = InitializeVariableManager(newSize);
+  
+  for (i=0; i < idSet->n_words; i++) {
+    newSet->data[i] |= idSet->data[i];
+  }
+  /* free the old id set, not using ResResidueFreeVariableManager()
+   * because it resets the numVarsInUse
+   */
+  var_set_free(idSet);
+
+  idSet = newSet;
+  return;
+} /* End of ResizeVariableManager */
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/restr/restr.h
===================================================================
--- vis_dev/vis-2.3/src/restr/restr.h	(revision 14)
+++ vis_dev/vis-2.3/src/restr/restr.h	(revision 14)
@@ -0,0 +1,72 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [restr.h]
+
+  PackageName [restr]
+
+  Synopsis    [STG restructuring package.]
+
+  Description [This package provides the capability to restructure a
+  state transition graph (STG).]
+
+  Author      [Balakrishna Kumthekar <kumtheka@colorado.edu>]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+
+******************************************************************************/
+
+#ifndef _RESTR
+#define _RESTR
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "ntm.h"
+#include "fsm.h"
+#include "part.h"
+#include "io.h"
+#include "ord.h"
+#include "mdd.h"
+#include "util.h"
+#include "synth.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void Restr_Init(void);
+EXTERN void Restr_End(void);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _RESTR */
Index: vis_dev/vis-2.3/src/restr/restr.make
===================================================================
--- vis_dev/vis-2.3/src/restr/restr.make	(revision 14)
+++ vis_dev/vis-2.3/src/restr/restr.make	(revision 14)
@@ -0,0 +1,6 @@
+CSRC += restrCProj.c restrCmd.c restrDebug.c restrFaninout.c restrHammingD.c \
+	restrRestructure.c restrUtil.c
+
+HEADERS += restr.h restrInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/restr/restrCProj.c
===================================================================
--- vis_dev/vis-2.3/src/restr/restrCProj.c	(revision 14)
+++ vis_dev/vis-2.3/src/restr/restrCProj.c	(revision 14)
@@ -0,0 +1,215 @@
+/**CFile***********************************************************************
+
+  FileName    [restrCProj.c]
+
+  PackageName [restr]
+
+  Synopsis [This file contains functions that implement the STG restructuring
+  based on compatible projection.]
+
+  Description [This file contains functions that implement the STG
+  restructuring based on compatible projection.  Please refer to "A symbolic
+  algorithm for low power sequential synthesis," ISLPED 97, for more details.]
+
+  SeeAlso     [restrHammingD.c restrFaninout.c]
+
+  Author      [Balakrishna Kumthekar]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "restrInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [This routine implements the STG restructuring based on compatible
+  projection.]
+
+  Description [This routine implements the STG restructuring based on
+  compatible projection. The BDD for the monolithic transition relation of the
+  restructured STG is returned.
+
+  Please refer to "A Symbolic Algorithm for Low-Power Sequential Synthesis,"
+  ISLPED 97. for more details.
+
+  <tt>equivRel</tt> is the BDD of the equivalnece relation of the FSM,
+  <tt>originalTR</tt> is the monolithic transition relation, <tt>initBdd</tt>
+  is the BDD for the initial state, <tt>piVars</tt> are the BDD variables for
+  primary inputs, <tt>nVars are the numbers of state variables and <tt>nPi</tt>
+  are the number of primary inputs. <tt>outBdd</tt> is an array of BDDs for the
+  primary outputs of the sequential circuit.]
+
+  SideEffects [<tt>outBdds</tt> and <tt>newInit</tt> are changed to reflect the
+  restructured STG.]
+
+  SeeAlso     [RestrSelectLeastHammingDStates RestrMinimizeFsmByFaninFanout]
+
+******************************************************************************/
+bdd_node *
+RestrMinimizeFsmByCProj(
+  bdd_manager 	*ddManager,
+  bdd_node 	*equivRel,
+  bdd_node 	*originalTR,
+  bdd_node 	*initBdd,
+  bdd_node	**xVars,
+  bdd_node	**yVars,
+  bdd_node	**uVars,
+  bdd_node	**vVars,
+  bdd_node      **piVars,
+  int		nVars,
+  int           nPi,
+  array_t       **outBdds,
+  bdd_node      **newInit)
+
+{
+  bdd_node *resultYV, *temp, *temp1, *temp2;
+  bdd_node *result, *resultXU;
+  bdd_node *xCube, *yCube;
+  bdd_node *oneInitState;
+  array_t *newOutBdds;
+  int i;
+
+  /* Select one state from the set of initial states. This is redundant in case
+     of circuits described in blif format.*/
+  oneInitState = bdd_bdd_pick_one_minterm(ddManager,initBdd,xVars,nVars);
+  bdd_ref(oneInitState);
+
+  temp = bdd_bdd_swap_variables(ddManager,oneInitState,xVars,vVars,nVars);
+  bdd_ref(temp);
+  bdd_recursive_deref(ddManager,oneInitState);
+
+  /* Select a representative for each equivalence class. The vVars encode the
+   * representative for each class. resultYV has yVars and vVars in its
+   * support. equivRel is a function of yVars and vVars.
+   */
+  resultYV = bdd_bdd_cprojection(ddManager, equivRel, temp);
+  bdd_ref(resultYV);
+  bdd_recursive_deref(ddManager,temp);
+
+  temp = bdd_bdd_swap_variables(ddManager,resultYV,yVars,xVars,nVars);
+  bdd_ref(temp);
+  resultXU = bdd_bdd_swap_variables(ddManager,temp,vVars,uVars,nVars);
+  bdd_ref(resultXU);
+  bdd_recursive_deref(ddManager, temp);
+
+  /* Change the initBdd accordingly
+   * initBdd^{new} = [\exists_x (initBdd(x) * result(x,u))]_{u=x}
+   */
+  xCube = bdd_bdd_compute_cube(ddManager,xVars,NIL(int),nVars);
+  bdd_ref(xCube);
+  bdd_ref(temp1 = bdd_bdd_and_abstract(ddManager,initBdd,resultXU,
+				       xCube));
+  bdd_ref(*newInit = bdd_bdd_swap_variables(ddManager,temp1,uVars,
+					    xVars,nVars));
+  bdd_recursive_deref(ddManager,temp1);
+
+  /* compute the new TR.
+   * TR^{new}(x,w,y) = 
+   *    [\exists_{xy}(result(x,u) * TR(x,w,y) * result(y,v))]_{u=x,v=y}
+   * result is the new restructured/minimized TR.
+   */
+  bdd_ref(yCube = bdd_bdd_compute_cube(ddManager,yVars,NIL(int),nVars));
+  bdd_ref(temp = bdd_bdd_and_abstract(ddManager,resultYV,originalTR,yCube));
+  bdd_recursive_deref(ddManager,resultYV);
+  bdd_recursive_deref(ddManager,yCube);
+
+  bdd_ref(result = bdd_bdd_and_abstract(ddManager,temp,resultXU,xCube));
+  bdd_recursive_deref(ddManager,temp);
+
+  bdd_ref(temp = bdd_bdd_swap_variables(ddManager,result,uVars,
+					xVars,nVars));
+  bdd_recursive_deref(ddManager,result);
+  bdd_ref(result = bdd_bdd_swap_variables(ddManager,temp,vVars,
+					  yVars,nVars));
+  bdd_recursive_deref(ddManager,temp);
+
+  /* Change the outputs accordingly
+   * lambda^{new}_i(x,w) = [\exists_x (lambda_i(x,w) * result(x,u))]_{u=x}
+   *
+   * lambda_i(x,w) is the ith primary output.
+   */
+  newOutBdds = array_alloc(bdd_node *,0);
+  arrayForEachItem(bdd_node *,*outBdds,i,temp) {
+    temp1 = bdd_bdd_and_abstract(ddManager,temp,resultXU,xCube);
+    bdd_ref(temp1);
+    temp2 = bdd_bdd_swap_variables(ddManager,temp1,uVars,xVars,nVars);
+    bdd_ref(temp2);
+    bdd_recursive_deref(ddManager,temp1);
+    array_insert_last(bdd_node *,newOutBdds,temp2);
+  }
+  bdd_recursive_deref(ddManager, xCube);
+  bdd_recursive_deref(ddManager,resultXU);
+
+#ifdef RESTR_DIAG
+  {
+    int flag1,flag2;
+
+    (void) fprintf(vis_stdout,"Old transition relation ...\n");
+    flag1 = RestrTestIsDeterministic(ddManager,originalTR,initBdd,
+				     xVars,yVars,nVars);
+    (void) fprintf(vis_stdout,"New transition relation ...\n");
+    flag2 = RestrTestIsDeterministic(ddManager,result,*newInit,
+				     xVars,yVars,nVars);
+  }
+#endif
+  
+  /* Delete the old array */
+  arrayForEachItem(bdd_node *,*outBdds,i,temp) {
+    bdd_recursive_deref(ddManager,temp);
+  }
+  array_free(*outBdds);
+  *outBdds = newOutBdds;
+  
+  return result;
+
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
Index: vis_dev/vis-2.3/src/restr/restrCmd.c
===================================================================
--- vis_dev/vis-2.3/src/restr/restrCmd.c	(revision 14)
+++ vis_dev/vis-2.3/src/restr/restrCmd.c	(revision 14)
@@ -0,0 +1,904 @@
+/**CFile***********************************************************************
+
+  FileName    [restrCmd.c]
+
+  PackageName [restr]
+
+  Synopsis    [Command interface for the restr package.]
+
+  Author      [Balakrishna Kumthekar <kumtheka@colorado.edu>]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "restrInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+static jmp_buf timeOutEnv;
+int restrCreatedPart;
+int restrCreatedFsm;
+boolean restrVerbose;
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandRestructureFsm(Hrc_Manager_t **hmgr, int argc, char **argv);
+static void TimeOutHandle(void);
+static st_table * readInputProbabilities(Ntk_Network_t *network, FILE *fp);
+static void CleanUp(Ntk_Network_t *network1, st_table *inputProb, char *outOrderFileName, char *dumpFileName, char *prefix, int varOrdered, int restrCreatedPart, int restrCreatedFsm, char *probFile);
+static enum st_retval stCountFree(char *key, char *value, char *arg);
+static int IsPartitionValid(Ntk_Network_t *network, graph_t *partition);
+static int TestIsNetworkMultipleValued(Ntk_Network_t *network);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [This function initializes the restr package.]
+
+  SideEffects [None]
+
+  SeeAlso     [Restr_End]
+
+******************************************************************************/
+void
+Restr_Init(void)
+{
+  Cmd_CommandAdd("restruct_fsm", CommandRestructureFsm, 0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [This function ends the restr package.]
+
+  SideEffects [None]
+
+  SeeAlso     [Restr_Init]
+
+******************************************************************************/
+void
+Restr_End(void)
+{
+
+} /* End of Restr_End */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Implements the <tt>restruct_fsm</tt> command.]
+
+  Description [This command implements an State Transition Graph (STG)
+  restructuring algorithm that exploits the existence of equivalent
+  states to decrease power dissipation, not necessarily by collapsing
+  the equivalence states, but by redirecting transitions in the
+  graph. This algorithm is based on the monolithic transition relation. The
+  complexity of the algorithm in general increases with an increase in
+  the size of the state transition graph, which depends on the number
+  of state variables and primary inputs. For more details see, "A
+  Symbolic Algorithm for Low-Power Sequential Synthesis", ISLPED 97.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+  CommandName [restruct_fsm]
+
+  CommandSynopsis [Restructre the STG of a finite state machine to
+  reduce power dissipation.]
+
+  CommandArguments [\[-D &lt;fileHead&gt;\] \[-d &lt;divMethod&gt;\] \[-E\]
+  \[-F &lt;factMethod&gt;\] \[-f &lt;probFile&gt;\] \[-h\] \[-N\] \[-o
+  &lt;orderFile&gt;\] \[-p &lt;string&gt;\] \[-s &lt;restrMethod&gt;\] \[-t
+  &lt;seconds&gt;\] \[-v\]]
+
+  CommandDescription [This command implements an STG restructuring
+  algorithm that exploits the existence of equivalent states to
+  decrease power dissipation, not necessarily by collapsing the
+  equivalence states, but by redirecting transitions in the state
+  transition graph (STG). This algorithm is based on monolithic
+  transition relation. The complexity of the algorithm in general
+  increases with an increase in the size of the STG. The number of
+  states and edges in the STG are exponential in the number of state
+  variables and primary inputs. The memory utilization is not
+  necessarily exponential due to symbolic representation of the
+  STG. For more details see, "A Symbolic Algorithm for Low-Power
+  Sequential Synthesis", ISLPED 97.
+
+  This command works only if VIS is compiled with CUDD package. The
+  algorithm can handle circuits described in both BLIF and BLIF-MV
+  format. However, multi-valued variables are not supported. Also, the
+  final synthesized circuit (network implementation of the restructured
+  STG) is available only in BLIF format. The sequential circuit should
+  have a single initial state.
+
+  A network should have been created for the circuit and its primary
+  inputs and state variables assigned BDD ids prior to the invocation
+  of this command. A network can be created by the command
+  <tt>flatten_hierarchy</tt> and command <tt>static_order</tt> assigns
+  BDD ids to the input and state variables. The command proceeds by
+  creating BDDs for the outputs and next state functions. An FSM data
+  structure is then created on which subsequent operations are
+  performed. After the STG is restructured a new circuit is
+  synthesized by symbolic factorization based on Zero-Suppressed
+  Decision Diagrams (ZDDs). The final synthesized circuit is a file in
+  BLIF format with ".ml.blif" as the extension.
+
+  <p>
+  The typical command flow in vis is the following: <br><br>
+  <code>
+  vis> read_blif foo.blif <br>
+  vis> flatten_hierarchy <br>
+  vis> static_order <br>
+  vis> dynamic_var_ordering -e sift <br>
+  vis> restruct_fsm
+  </code>
+
+  <p>
+
+  In the above case example, the final synthesized circuit is
+  MODEL.ml.blif if the name of the design in foo.blif is MODEL.
+  <br><br>
+  <b> Command options: </b> <br>
+
+  <dl>
+
+  <dt> -A 
+  <dd> Allow realignment (during symbolic factorization) of ZDDs
+  after BDD reordering and vice versa.  This option is effective
+  when only one of the BDD or ZDD variable reordering is enabled. <p>
+
+  <dt> -D &lt;fileHead&gt;
+  <dd> Specify the output file name for synthesized circuit. File extension
+  is not necessary. By default, the model name of the circuit is used. For 
+  example, -D foobar, will result in foobar.ml.blif <p>
+
+  <dt> -d &lt;divMethod&gt; 
+  <dd> Choose a divisor. See <tt>synthesize_network</tt> for more details.<p>
+
+  <dt> -E
+  <dd> Print the number of equivalence classes in the FSM. <p>
+
+  <dt> -F &lt;probFile&gt;
+  <dd> File with primary input probabilities, one per line. 
+  <tt>input_name</tt> &lt;probability&gt; <p>
+
+  <dt> -f &lt;factMethod&gt; 
+  <dd> Choose a method for factorization. See <tt>synthesize_network</tt> for
+  more details.<p>
+
+  <dt> -h
+  <dd> Print command usage. <p>
+
+  <dt> -i &lt;string&gt;
+  <dd> Specify the prefix to be used to generate names for internal 
+  nodes during synthesis. By default, the prefix is "_n". <p>
+
+  <dt> -N
+  <dd> Expand the reachable set R to include those states which are equivalent 
+  to R but not reachable. The default is not to include such states. <p>
+
+  <dt> -o &lt;orderFile&gt;
+  <dd> File to output BDD variable ordering after the restructured 
+  circuit is synthesized. <p>
+
+  <dt> -R &lt;value&gt;
+  <dd> Allow reordering in BDD and/or ZDD variables during symbolic 
+  factorization stage. <p>
+  0 : (default) No reordering neither in BDD nor in ZDD. <p>
+  1 : Allows reordering only in BDD, not in ZDD. <p>
+  2 : Allows reordering only in ZDD, not in BDD. <p>
+  3 : Allows reordering both in BDD and in ZDD. <p>
+
+  <dt> -s &lt;heuristic&gt; 
+  
+  <dd> Heuristic to perform restructuring. Consider a fragment of an
+  STG containing states A,B and C and an edge from A to B. Let B and C
+  be equivalent. Since B and C are equivalent, it is possible to
+  change the transition between A and B to A and C. In the more
+  general case, the choice can be driven by different cost
+  constraints. The following are the heuristics: <br>
+
+  <dd> ham : Hamming distance based heuristic. An edge is chosen that reduces
+  the Hamming distance (or state bit transitions) between the states.<br>
+
+  <dd> fanin : Fanin oriented heuristic. A representative from the equivalence
+  class is chosen that reduces the total average state bit switching on the
+  incoming edges. <br> 
+
+  <dd> faninout : Fanin-Fanout oriented heuristic. A representative from the
+  equivalence class is chosen that reduces the total average state bit
+  switching on the incoming as well as outgoing edges. <br>
+
+  <dd> cproj : A simple C-Projection. A representative from the
+  equivalence class is chosen which is closest to the initial
+  state. The distance d(x,y) is defined as:
+  <br><br>
+  \sum_{i=0}^{N-1}(|x_i - y_i| \cdot 2^{N-i-1}).<p>
+
+  <dt> -T
+  <dd> Try to share more nodes during symbolic factorization. Existing
+  divisors are checked for potential reuse before extracting divisors from the
+  current boolean function.<p>
+
+  <dt> -t &lt;seconds&gt;
+  <dd> Time in seconds allowed to complete the command. If the computation time
+  goes above that limit, the process is aborted.  The default is no limit.<p>
+
+  <dt> -v
+  <dd> Turn on verbosity. <p>
+
+  <dt> See also command : synthesize_network <p>
+
+  </dl>
+  ]
+
+  SideEffects [Package specific information is stored in the network and
+  cleared at the end.]
+
+  SeeAlso []
+
+******************************************************************************/
+static int
+CommandRestructureFsm(
+  Hrc_Manager_t **hmgr,
+  int argc,
+  char **argv)
+{
+  graph_t *partition = NIL(graph_t);
+  Fsm_Fsm_t *fsm = NIL(Fsm_Fsm_t);
+  Ntk_Network_t *network1 = NIL(Ntk_Network_t);
+  Hrc_Node_t *currentNode = NIL(Hrc_Node_t);
+  lsList dummy = (lsList) 0;
+  char *modelName,*str;
+  int timeOutPeriod;
+  boolean status;
+  int c;
+  long initialTime, finalTime;
+  RestructureHeuristic heuristic;
+  boolean equivClasses, nonReachEquiv;
+  boolean eqvMethod;
+  int varOrdered;
+  char *outOrderFileName,*blifName;
+  char *dumpFileName,*probFile;
+  int reorder,trySharing,realign;
+  FILE *fp;
+  st_table *inputProb = NULL;
+
+    /* Synthesis related options */
+  Synth_InfoData_t *synthInfo;
+  int factoring, divisor;
+  char *prefix;
+  
+  if (bdd_get_package_name() != CUDD) {
+    (void) fprintf(vis_stderr,
+		   "** restr error: The restr package can be used only with CUDD package\n");
+    (void) fprintf(vis_stderr,"** restr error: Please link with CUDD package\n");
+    return 0;
+  }
+	
+  /* These are the default values. */
+  timeOutPeriod   = 0;  
+  status          = FALSE;
+  restrVerbose	  = 0;
+  equivClasses    = 0;
+  nonReachEquiv   = 0;
+  eqvMethod       = 0;
+  heuristic	  = RestrHammingD_c;
+  fp 		  = NIL(FILE);
+  outOrderFileName = NIL(char);
+  dumpFileName = NIL(char);
+  probFile = NIL(char);
+  restrCreatedPart = 0;
+  restrCreatedFsm = 0;
+  varOrdered = 0;
+
+  /* Synthesis related default values */
+  factoring = 0;
+  divisor = 1;
+  prefix = NIL(char);
+  reorder = 0;
+  trySharing = 0;
+  realign = 0;
+
+  util_getopt_reset();
+
+  while((c = util_getopt(argc, argv, "f:d:i:EeNvD:o:t:s:F:R:TAh")) != EOF) {
+    switch(c) {
+    case 'f':
+      factoring = atoi(util_optarg);
+      break;
+    case 'd':
+      divisor = atoi(util_optarg);
+      break;
+    case 'i':
+      prefix = util_strsav(util_optarg);
+      break;
+    case 'E':
+      equivClasses = 1;
+      break;
+    case 'e':
+      eqvMethod = 1;
+      break;
+    case 'N':
+      nonReachEquiv = 1;
+      break;
+    case 'v':
+      restrVerbose = 1;
+      break;
+    case 'D':
+      dumpFileName = util_strsav(util_optarg);
+      break;
+    case 'o':
+      outOrderFileName = util_strsav(util_optarg);
+      /* Check if the file specified to dump variable order already exists */
+      fp = Cmd_FileOpen(outOrderFileName,"r",NIL(char *),1);
+      if (fp) {
+	(void) fprintf(vis_stderr,"** restr error: Output order file %s already exists.\n",
+		       outOrderFileName);
+	(void) fprintf(vis_stderr,"** restr error: Please specify another name.\n");
+	fclose(fp);
+	FREE(outOrderFileName);
+	goto endgame;
+      }
+      break;
+    case 't':
+      timeOutPeriod = atoi(util_optarg);
+      break;
+    case 's':
+      str = util_strsav(util_optarg);
+      if (strcmp(str,"ham") == 0) {
+	heuristic = RestrHammingD_c;
+      } else if (strcmp(str,"fanin") == 0) {
+	heuristic = RestrFanin_c;
+      } else if (strcmp(str,"faninout") == 0) {
+	heuristic = RestrFaninFanout_c;
+      } else if (strcmp(str,"cproj") == 0) {
+	heuristic = RestrCProjection_c;
+      } else {
+	(void) fprintf(vis_stderr,"** restr warning: Invalid option %s\n",str);
+	(void) fprintf(vis_stderr,"** restr warning: Using Hamming distance heuristic\n\n");
+	heuristic = RestrHammingD_c;
+      }
+      FREE(str);
+      break;
+    case 'F':
+      probFile = util_strsav(util_optarg);
+      fp = Cmd_FileOpen(probFile,"r",NIL(char *),1);
+      if (!fp) {
+	fprintf(vis_stderr,"** restr warning: Cannot open %s \n",probFile);
+	fprintf(vis_stderr,"** restr warning: Assuming equi probable primary inputs\n");
+	FREE(probFile);
+	probFile = NIL(char);
+      } else {
+	fclose(fp);
+      }
+      break;
+    case 'R':
+      /* Option to enable/disable reordering during synthesis
+         (factorization) stage */
+      reorder = atoi(util_optarg);
+      break;
+    case 'T':
+      /* During factorization maximize sharing of nodes */
+      trySharing = 1;
+      break;
+    case 'A':
+      /* Realign ZDD variables after BDD variable reordering and vice
+         versa */
+      realign = 1;
+      break;
+    case 'h':
+      goto usage;
+    default:
+      goto usage;
+    }
+  }
+
+  if(Hrc_ManagerReadCurrentNode(*hmgr) == NIL(Hrc_Node_t)) {
+    (void) fprintf(vis_stderr,"** restr error: The hierarchy manager is empty.");
+    (void) fprintf(vis_stderr," Read in design.\n");
+    goto endgame;
+  }
+
+  network1 = (Ntk_Network_t *) 
+    Hrc_NodeReadApplInfo(Hrc_ManagerReadCurrentNode(*hmgr), 
+			 NTK_HRC_NODE_APPL_KEY);
+
+  if(network1 == NIL(Ntk_Network_t)) {
+    (void) fprintf(vis_stderr,"** restr error: There is no network. ");
+    (void) fprintf(vis_stderr,"Use flatten_hierarchy.\n");
+    goto endgame;
+  }
+
+  if(!Ntk_NetworkReadNumLatches(network1)) {
+    (void) fprintf(vis_stderr,"**restr error: No latches present in the ");
+    (void) fprintf(vis_stderr,"current network.\n");
+    (void) fprintf(vis_stderr,"** restr error: This algorithm does not apply.\n");
+    goto endgame;
+  }
+
+  /* Check if the current network has signals with multiple values. */
+  if (TestIsNetworkMultipleValued(network1)) {
+    (void) fprintf(vis_stderr,"** restr error: Circuit has multiple valued variables.\n");
+    (void) fprintf(vis_stderr,"** restr error: This algorithm applies to boolean signals only.\n");
+    goto endgame;
+  }
+
+  if(Ntk_NetworkReadNumPrimaryInputs(network1) !=
+     Ntk_NetworkReadNumInputs(network1)) {
+    (void) fprintf(vis_stderr,"** restr error: Pseudo inputs present in the network.\n");
+    (void) fprintf(vis_stderr,"** restr error: This algorithm does not apply.\n");
+    goto endgame;
+  }
+
+  if (!dumpFileName)
+    dumpFileName = util_strsav(Ntk_NetworkReadName(network1));
+  /* Check if the output blif file already exists */
+  blifName = util_strcat3(dumpFileName,".ml.blif","");
+  fp = Cmd_FileOpen(blifName,"r",NIL(char *),1);
+  if (fp) {
+    (void) fprintf(vis_stderr,"** restr error: Output blif file %s already exists.\n",
+		   blifName);
+    (void) fprintf(vis_stderr,"** restr error: Please specify another name.\n");
+    fclose(fp);
+    FREE(blifName);
+    goto endgame;
+  }
+  FREE(blifName);
+
+
+  /* Check if the network has the variables ordered */
+  if (Ord_NetworkTestAreVariablesOrdered(network1, Ord_InputAndLatch_c) == 
+      FALSE) {
+    Ord_NetworkOrderVariables(network1,Ord_RootsByDefault_c,
+			      Ord_NodesByDefault_c, FALSE,
+			      Ord_InputAndLatch_c,Ord_Unassigned_c,
+			      dummy,0);
+    varOrdered = 1;
+  }
+
+  /* If primary input probabilities are specified, read them */
+  if (probFile) {
+    fp = Cmd_FileOpen(probFile,"r",NIL(char *),1);
+    inputProb = readInputProbabilities(network1,fp);
+    fclose(fp);
+    FREE(probFile);
+    fp = NIL(FILE);
+  }
+
+  /* Check if there is an FSM already attached to the network */
+  fsm = (Fsm_Fsm_t *) Ntk_NetworkReadApplInfo(network1, 
+					      FSM_NETWORK_APPL_KEY);
+  if (fsm == NIL(Fsm_Fsm_t)) {
+    partition = (graph_t *) Ntk_NetworkReadApplInfo(network1,
+						    PART_NETWORK_APPL_KEY);
+    /* If there is none then create one. */
+    if (partition == NIL(graph_t) ||
+	(!IsPartitionValid(network1,partition))) {
+      currentNode = Hrc_ManagerReadCurrentNode(*hmgr);
+      modelName = Hrc_NodeReadModelName(currentNode);
+      partition = Part_NetworkCreatePartition(network1, currentNode,
+					      modelName, (lsList) 0, 
+					      (lsList) 0, NIL(mdd_t), 
+					      Part_InOut_c, (lsList) 0, 
+					      FALSE, FALSE, TRUE);
+ 
+      Ntk_NetworkAddApplInfo(network1, RESTR_PART_NETWORK_APPL_KEY,
+			     (Ntk_ApplInfoFreeFn) Part_PartitionFreeCallback,
+			     (void *) partition);
+      restrCreatedPart = 1;
+    }
+    fsm = Fsm_FsmCreateFromNetworkWithPartition(network1, 
+						Part_PartitionDuplicate(partition));
+    if (fsm == NIL(Fsm_Fsm_t)) {
+      (void) fprintf(vis_stderr,"** restr error: Could not create ");
+      (void) fprintf(vis_stderr,"an Fsm\n");
+      goto endgame;
+    }
+    Ntk_NetworkAddApplInfo(network1, RESTR_FSM_NETWORK_APPL_KEY,
+			   (Ntk_ApplInfoFreeFn) Fsm_FsmFreeCallback,
+			   (void *) fsm);
+    restrCreatedFsm = 1;
+  } else {
+    partition = (graph_t *) Fsm_FsmReadPartition(fsm);
+
+    if (partition == NIL(graph_t) || 
+	(!IsPartitionValid(network1,partition))) {
+      currentNode = Hrc_ManagerReadCurrentNode(*hmgr);
+      modelName = Hrc_NodeReadModelName(currentNode);
+      partition = Part_NetworkCreatePartition(network1, currentNode,
+					      modelName, (lsList) 0, 
+					      (lsList) 0, NIL(mdd_t), 
+					      Part_InOut_c, (lsList) 0, 
+					      FALSE, FALSE, TRUE);
+      Ntk_NetworkAddApplInfo(network1, RESTR_PART_NETWORK_APPL_KEY,
+			     (Ntk_ApplInfoFreeFn) Part_PartitionFreeCallback,
+			     (void *) partition);
+      restrCreatedPart = 1;
+
+      fsm = Fsm_FsmCreateFromNetworkWithPartition(network1, 
+						  Part_PartitionDuplicate(partition));
+      if (fsm == NIL(Fsm_Fsm_t)) {
+	(void) fprintf(vis_stderr,"** restr error: Could not create ");
+	(void) fprintf(vis_stderr,"an Fsm\n");
+	goto endgame;
+      }
+      Ntk_NetworkAddApplInfo(network1, RESTR_FSM_NETWORK_APPL_KEY,
+			     (Ntk_ApplInfoFreeFn) Fsm_FsmFreeCallback,
+			     (void *) fsm);
+      restrCreatedFsm = 1;
+    }
+  }
+
+  /* Start the timer before calling restruct. */
+  if (timeOutPeriod > 0){
+    (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
+    (void) alarm(timeOutPeriod);
+    if (setjmp(timeOutEnv) > 0) {
+      (void) fprintf(vis_stderr, "** restr warning: Timeout occurred after ");
+      (void) fprintf(vis_stderr, "%d seconds.\n", timeOutPeriod);
+      alarm(0);
+      goto endgame;
+    }
+  }
+
+  /* Prepare the data structure for the synthesis package */
+  synthInfo = Synth_InitializeInfo(factoring,divisor,0,
+				   reorder,trySharing,realign,
+				   dumpFileName,prefix,0);
+
+  initialTime = util_cpu_time();
+  status = RestrCommandRestructureFsm(fsm, heuristic,outOrderFileName,
+				      equivClasses,nonReachEquiv,
+				      eqvMethod,inputProb,synthInfo);
+  finalTime = util_cpu_time();
+  if(status) {
+    (void) fprintf(vis_stdout, "%-20s%10ld\n", "RESTR: analysis time =",
+		   (finalTime-initialTime)/1000);
+
+  }
+  else {
+    (void) fprintf(vis_stdout, "** restr error: Could not restructure successfully.\n");
+  }
+    
+  if (synthInfo)
+    Synth_FreeInfo(synthInfo);
+
+    /* Clean up */
+  CleanUp(network1,inputProb,outOrderFileName,dumpFileName,prefix,
+	  varOrdered,restrCreatedPart,restrCreatedFsm,probFile);
+
+  alarm(0);
+  return 0;  /* normal exit */
+
+endgame:
+  /* Clean up */
+  CleanUp(network1,inputProb,outOrderFileName,dumpFileName,prefix,
+	  varOrdered,restrCreatedPart,restrCreatedFsm,probFile);
+    
+  return 1; /* Error exit */
+
+usage:
+  if (outOrderFileName)
+    FREE(outOrderFileName);
+  if (dumpFileName)
+    FREE(dumpFileName);
+  if (prefix)
+    FREE(prefix);
+  if (probFile)
+    FREE(probFile);
+
+  (void) fprintf(vis_stderr, "\nusage: Also see help restruct_fsm for more details.\n\n");
+  (void) fprintf(vis_stderr, "    -A      \t\tAllow realignment--during symbolic factorization--of BDD\n");
+  (void) fprintf(vis_stderr, "            \t\tand ZDD variables after reordering.\n\n");
+  (void) fprintf(vis_stderr, "    -D <fileHead>\tOutput file name for synthesized circuit.\n");
+  (void) fprintf(vis_stderr, "            \t\tDefault: model_name.ml.blif\n\n");
+  (void) fprintf(vis_stderr, "    -d <divMethod>\tChoose a divisor during synthesis. See\n");
+  (void) fprintf(vis_stderr, "            \t\tsynthesize_network command for more details.\n");
+  (void) fprintf(vis_stderr, "            \t\t0 : Fast divisor\n");
+  (void) fprintf(vis_stderr, "            \t\t1 : Least occuring literal divisor (default)\n");
+  (void) fprintf(vis_stderr, "            \t\t2 : Most occuring literal divisor\n");
+  (void) fprintf(vis_stderr, "            \t\t3 : Level-0 kernel divisor\n\n");
+  (void) fprintf(vis_stderr, "    -E      \t\tPrint the number of equivalence classes in the STG.\n\n");
+  (void) fprintf(vis_stderr, "    -F <probFile>\tInput file with PI probabilities, one per line.\n\n");
+  (void) fprintf(vis_stderr, "    -f <factMethod>\tChoose a factorization method. See synthesize_network\n");
+  (void) fprintf(vis_stderr, "            \t\tfor more details.\n");
+  (void) fprintf(vis_stderr, "            \t\t0 : Simple factoring (default)\n");
+  (void) fprintf(vis_stderr, "            \t\t1 : Generic factoring\n\n");
+  (void) fprintf(vis_stderr, "    -h      \t\tPrint command usage.\n\n");
+  (void) fprintf(vis_stderr, "    -i <name>\t\tPrefix to be used to generate names for internal\n");
+  (void) fprintf(vis_stderr, "            \t\tnodes during synthesis. Default: \"_n\"\n\n");
+  (void) fprintf(vis_stderr, "    -N      \t\tExpand the reachable set R to include those states\n");
+  (void) fprintf(vis_stderr, "            \t\twhich are equivalent to R but unreachable.\n");
+  (void) fprintf(vis_stderr, "            \t\tThe default is not to include.\n\n");
+  (void) fprintf(vis_stderr, "    -o <orderFile>\tFile to output BDD variable order at the end.\n\n");
+  (void) fprintf(vis_stderr, "    -R <value>\t\tSet reordering (0-3)\n");
+  (void) fprintf(vis_stderr, "            \t\t0 : no reordering (default)\n");
+  (void) fprintf(vis_stderr, "            \t\t1 : reordering in only BDD\n");
+  (void) fprintf(vis_stderr, "            \t\t2 : reordering on only ZDD\n");
+  (void) fprintf(vis_stderr, "            \t\t3 : reordering on both\n\n");
+  (void) fprintf(vis_stderr, "    -s <heuristic>\tHeuristic to perform restructuring.\n");
+  (void) fprintf(vis_stderr, "            \t\tType help restruct_fsm for more details on each option.\n");
+  (void) fprintf(vis_stderr, "            \t\tham : Hamming distance based heuristic. (Default)\n");
+  (void) fprintf(vis_stderr, "            \t\tfanin : Fanin oriented heuristic.\n");
+  (void) fprintf(vis_stderr, "            \t\tfaninout : Fanin-Fanout oriented heuristic.\n");
+  (void) fprintf(vis_stderr, "            \t\tcproj : C-Projection based heuristic.\n\n");
+  (void) fprintf(vis_stderr, "    -T      \t\tTry to share mode nodes during symbolic factorization.\n\n");
+  (void) fprintf(vis_stderr, "    -t <seconds>\tTime in seconds to complete the command. The command\n");
+  (void) fprintf(vis_stderr, "            \t\tis aborted if computation time goes above this limit.\n\n");
+  (void) fprintf(vis_stderr, "    -v      \t\tTurn on verbosity.\n");
+
+
+  return 1;    /* error exit */
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Handle function for timeout.]
+
+  Description [This function is called when the time out occurs.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+TimeOutHandle(void)
+{
+  longjmp(timeOutEnv, 1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the input probabilities of primary inputs.]
+
+  Description [Reads the input probabilities of primary inputs.]
+
+  SideEffects [None]
+  
+  SeeAlso []
+
+******************************************************************************/
+static st_table *
+readInputProbabilities(
+  Ntk_Network_t *network,
+  FILE *fp)
+
+{
+  Ntk_Node_t *node;
+  char name[MAX_NAME_LEN];
+  double value;
+  double *valuePtr;
+  st_table *inputProb;
+
+  inputProb = st_init_table(st_numcmp,st_numhash);
+
+  while (fscanf(fp, "%s %lf\n", name, &value) != EOF) {
+    node = Ntk_NetworkFindNodeByName(network,name);
+    if (node == NIL(Ntk_Node_t)) {
+      (void) fprintf(vis_stderr,"** restr error: No node by name %s in the network\n",name);
+      (void) fprintf(vis_stderr,"** restr error: Aborting.\n");
+      st_foreach(inputProb,stCountFree,NIL(char));
+      st_free_table(inputProb);
+      return NULL;
+    }
+    if (!Ntk_NodeTestIsPrimaryInput(node)) {
+      fprintf(vis_stderr,"** restr warning: <%s> is not a primary input.\n",name);
+      fprintf(vis_stderr,"** restr warning: Assuming equiprobable primary inputs\n");
+      st_foreach(inputProb,stCountFree,NIL(char));
+      st_free_table(inputProb);
+      return NULL;
+    }
+    valuePtr = ALLOC(double,1);
+    if (value > 1.0) {
+      (void) fprintf(vis_stderr,"** restr warning: %s has prob. value greater than 1: %g\n",
+		     name,value);
+      (void) fprintf(vis_stderr,"** restr warning: Assuming a prob. value of 0.5\n");
+      *valuePtr = 0.5;
+    } else {
+      *valuePtr = value;
+    }
+    st_insert(inputProb,(char *)(long)Ntk_NodeReadMddId(node),(char *)valuePtr);
+  }
+
+  return inputProb;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Free memory at the end of the task.]
+
+  Description [Free memory at the end of the task.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static void
+CleanUp(
+  Ntk_Network_t *network1,
+  st_table *inputProb,
+  char *outOrderFileName,
+  char *dumpFileName,
+  char *prefix,
+  int varOrdered,
+  int restrCreatedPart,
+  int restrCreatedFsm,
+  char *probFile)
+{
+  Ntk_Node_t *node;
+  lsGen gen;
+
+  if (inputProb) {
+    st_foreach(inputProb,stCountFree,NIL(char));
+    st_free_table(inputProb);
+  }
+    
+  if (outOrderFileName)
+    FREE(outOrderFileName);
+  if (dumpFileName)
+    FREE(dumpFileName);
+  if (prefix)
+    FREE(prefix);
+  if (probFile)
+    FREE(probFile);
+
+  /* Set the mdd id's for all the primary inputs, latches and next
+   * state nodes to UNASSIGNED if it was specifically set in this
+   * routine.
+   */
+  if (varOrdered) {
+    Ntk_NetworkForEachPrimaryInput(network1,gen,node) {
+      Ntk_NodeSetMddId(node,NTK_UNASSIGNED_MDD_ID);
+    }
+    Ntk_NetworkForEachLatch(network1,gen,node) {
+      Ntk_Node_t *shadow;
+      shadow = Ntk_NodeReadShadow(node);
+      Ntk_NodeSetMddId(node,NTK_UNASSIGNED_MDD_ID);    
+      Ntk_NodeSetMddId(shadow,NTK_UNASSIGNED_MDD_ID);    
+    }
+  }
+  /* Delete the partition hooked to the network if it was created in
+   * this routine.
+   */
+  if (restrCreatedPart) {
+    Ntk_NetworkFreeApplInfo(network1,RESTR_PART_NETWORK_APPL_KEY);
+  }
+  /* Delete the FSM hooked to the network if it was created in
+   * this routine.
+   */
+  if (restrCreatedFsm) {
+    Ntk_NetworkFreeApplInfo(network1,RESTR_FSM_NETWORK_APPL_KEY);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Procedure to delete values stored in an st_table.]
+
+  Description [Procedure to delete values stored in an st_table.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static enum st_retval
+stCountFree(
+  char *key,
+  char *value,
+  char *arg)
+{
+  double	*d;
+  
+  d = (double *)value;
+  FREE(d);
+  return(ST_CONTINUE);
+  
+} /* end of stCountfree */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether partition is valid.]
+
+  Description [Checks whether partition is valid. The condition is that the
+  given partition should have a vertex for each combinational output (PO and
+  NS) and combinational input (PI and PS) of the network.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static int
+IsPartitionValid(Ntk_Network_t *network,
+		 graph_t *partition)
+{
+  Ntk_Node_t *node;
+  lsGen gen;
+  char *name;
+
+  Ntk_NetworkForEachCombOutput(network, gen, node) {
+    name = Ntk_NodeReadName(node);
+    if(Part_PartitionFindVertexByName(partition, name) == NIL(vertex_t)) {
+      return(0);
+    }
+  }
+  Ntk_NetworkForEachCombInput(network, gen, node) {
+    name = Ntk_NodeReadName(node);
+    if(Part_PartitionFindVertexByName(partition, name) == NIL(vertex_t)) {
+      return(0);
+    }
+  }
+
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether the network has multiple valued signals.]
+
+  Description [Checks whether the network has multiple valued
+  signals. Returns 1 if true, else 0.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static int
+TestIsNetworkMultipleValued(Ntk_Network_t *network)
+{
+  Ntk_Node_t *node;
+  lsGen gen;
+  Var_Variable_t *var;
+  int numValues;
+
+  Ntk_NetworkForEachNode(network,gen,node) {
+    var = Ntk_NodeReadVariable(node);
+    numValues = Var_VariableReadNumValues(var);
+    if (numValues > 2)
+      return 1;
+  }
+  return 0;
+}
Index: vis_dev/vis-2.3/src/restr/restrDebug.c
===================================================================
--- vis_dev/vis-2.3/src/restr/restrDebug.c	(revision 14)
+++ vis_dev/vis-2.3/src/restr/restrDebug.c	(revision 14)
@@ -0,0 +1,456 @@
+/**CFile***********************************************************************
+
+ FileName    [restrDebug.c]
+
+ PackageName [restr]
+
+ Synopsis    [Utility functions to aid in debugging.]
+
+ Description [Utility functions to aid in debugging.]
+
+ SeeAlso     [restrUtil.c]
+
+ Author      [Balakrishna Kumthekar <kumtheka@colorado.edu>]
+
+ Copyright   [This file was created at the University of Colorado at
+ Boulder.  The University of Colorado at Boulder makes no warranty
+ about the suitability of this software for any purpose.  It is
+ presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "restrInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Print names of network nodes given their id.]
+
+  SideEffects [Print names of network nodes given their id.]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+RestrNamePrintByMddId(
+  Ntk_Network_t *network,
+  array_t 	*array)
+
+{
+  char *name;
+  int i,id;
+
+  arrayForEachItem(int, array, i, id) {
+    name = Ntk_NodeReadName(Ntk_NetworkFindNodeByMddId(network,id));
+    fprintf(vis_stdout, "%s\n",name);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis [Interface function to bdd_print_minterm given an mvf array.]
+
+  SideEffects [Interface function to bdd_print_minterm given an mvf array.]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+RestrPrintMvfArray(
+  mdd_manager	 *ddManager,
+  Mvf_Function_t *mvfArray,
+  array_t	 *nodeArray,
+  array_t	 *idArray)
+{
+  int i;
+  mdd_t *tempMdd;
+  Mvf_Function_t *mvf;
+  Ntk_Node_t	*node;
+
+  for(i=0;i<array_n(mvfArray);i++){
+    mvf = array_fetch(Mvf_Function_t *, mvfArray, i);
+    tempMdd = array_fetch(mdd_t *, mvf, 1);
+    if(!(nodeArray == NIL(array_t))) {
+      node = array_fetch(Ntk_Node_t *, nodeArray, i);
+      fprintf(vis_stdout, "%s ", Ntk_NodeReadName(node));
+    }
+    if(!(idArray == NIL(array_t))) {
+      fprintf(vis_stdout, " %d", array_fetch(int,idArray,i));
+    }
+    fprintf(vis_stdout, "\n");
+    bdd_print_minterm(tempMdd);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis [Prints the variable names of all variables in the manager.]
+
+  SideEffects [Prints the variable names of all variables in the manager]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+RestrPrintAllVarNames(
+  bdd_manager	*ddManager)
+{
+  int size, i;
+  mvar_type var;
+  size = bdd_num_vars((bdd_manager *)ddManager);
+  for(i=0;i<size;i++) {
+    var = mdd_get_var_by_id(ddManager,i);
+    fprintf(vis_stdout," %s",var.name);
+  }
+  fprintf(vis_stdout,"\n");
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Print minterms in the onset given a bdd_node *.]
+
+  SideEffects [Print minterms in the onset given a bdd_node *.]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+RestrPrintBddNode(
+  bdd_manager *manager,
+  bdd_node *ddNode)
+{
+    bdd_t *mdd;
+    bdd_node *temp;
+    bdd_ref(temp = ddNode);
+    mdd = bdd_construct_bdd_t(manager,temp);
+    bdd_print_minterm(mdd);
+    bdd_free(mdd);
+    return;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Perform token simulations to check functional equivalence of two
+  STGs.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+RestrVerifyFsmEquivBySimulation(
+  bdd_manager *ddManager,
+  bdd_node *oldTr,
+  bdd_node *newTr,
+  array_t *outBdds1,
+  array_t *outBdds2,
+  bdd_node *initBdd1,
+  bdd_node *initBdd2,
+  bdd_node **xVars,
+  bdd_node **yVars,
+  bdd_node **piVars,
+  int nVars,
+  int nPi)
+{
+  int **sim, N = 11;
+  int i,j,numOut1,numOut2;
+  bdd_node *lambda1,*lambda2;
+  bdd_node **lVars;
+  bdd_node *present1,*present2,*next1,*next2;
+  bdd_node *out1,*out2;
+  bdd_node *input,*inputPre1,*inputPre2;
+
+  sim = ALLOC(int *,N);
+  for (i = 0; i < N; i++) {
+    sim[i] = ALLOC(int,nPi);
+    for (j = 0; j < nPi; j++) {
+      sim[i][j] = 0;
+    }
+  }
+  
+  numOut1 = array_n(outBdds1);
+  numOut2 = array_n(outBdds2);
+  assert(numOut1 == numOut2);
+
+  /* New variables to compute output relation */
+  lVars = ALLOC(bdd_node *,numOut1);
+  for (i = 0; i < numOut1; i++) {
+    bdd_ref(lVars[i] = bdd_bdd_new_var(ddManager));
+  }
+
+  bdd_ref(lambda1 = bdd_read_one(ddManager));
+  bdd_ref(lambda2 = bdd_read_one(ddManager));
+  for (i = 0; i < numOut1; i++) {
+    bdd_node *temp,*outRel;
+    bdd_ref(outRel = bdd_bdd_xnor(ddManager,lVars[i],
+				  array_fetch(bdd_node *,outBdds1,i)));
+    bdd_ref(temp = bdd_bdd_and(ddManager,lambda1,outRel));
+    bdd_recursive_deref(ddManager,outRel);
+    bdd_recursive_deref(ddManager,lambda1);
+    lambda1 = temp;
+
+    bdd_ref(outRel = bdd_bdd_xnor(ddManager,lVars[i],
+				  array_fetch(bdd_node *,outBdds2,i)));
+    bdd_ref(temp = bdd_bdd_and(ddManager,lambda2,outRel));
+    bdd_recursive_deref(ddManager,outRel);
+    bdd_recursive_deref(ddManager,lambda2);
+    lambda2 = temp;
+  }
+
+  bdd_ref(present1 = initBdd1);
+  bdd_ref(present2 = initBdd2);
+  /* Simulate the patterns */
+  for (i = 0; i < N; i++) {
+    bdd_node *temp1;
+
+    bdd_ref(input = bdd_bdd_compute_cube(ddManager,piVars,sim[i],nPi));
+
+    /* Compute next state and outputs for machine 1 */
+    bdd_ref(inputPre1 = bdd_bdd_and(ddManager,input,present1));
+    bdd_ref(temp1 = bdd_bdd_cofactor(ddManager,oldTr,inputPre1));
+    bdd_ref(next1 = bdd_bdd_swap_variables(ddManager,temp1,yVars,xVars,nVars));
+    bdd_recursive_deref(ddManager,temp1);
+    bdd_recursive_deref(ddManager,present1);
+    present1 = next1;
+    bdd_ref(out1 = bdd_bdd_cofactor(ddManager,lambda1,inputPre1));
+    bdd_recursive_deref(ddManager,inputPre1);
+
+    /* Compute next state and outputs for machine 2 */
+    bdd_ref(inputPre2 = bdd_bdd_and(ddManager,input,present2));
+    bdd_ref(temp1 = bdd_bdd_cofactor(ddManager,newTr,inputPre2));
+    bdd_ref(next2 = bdd_bdd_swap_variables(ddManager,temp1,yVars,xVars,nVars));
+    bdd_recursive_deref(ddManager,temp1);
+    bdd_recursive_deref(ddManager,present2);
+    present2 = next2;
+    bdd_ref(out2 = bdd_bdd_cofactor(ddManager,lambda2,inputPre2));
+    bdd_recursive_deref(ddManager,inputPre2);
+    
+    bdd_recursive_deref(ddManager,input);
+
+    if (out1 != out2) {
+      (void) fprintf(vis_stdout,"Unequal outputs at i = %d\n",i);
+    }
+    bdd_recursive_deref(ddManager,out1);
+    bdd_recursive_deref(ddManager,out2);
+  }
+
+  bdd_recursive_deref(ddManager,present1);
+  bdd_recursive_deref(ddManager,present2);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Test if the given relation is an equivalence relation.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+RestrTestIsEquivRelation(
+  bdd_manager *ddManager,
+  bdd_node *rel,
+  bdd_node **xVars,
+  bdd_node **yVars,
+  bdd_node **uVars,
+  bdd_node **vVars,
+  int nVars)
+{
+  
+  bdd_node *one,*reflex;
+  bdd_node *Rxy,*Rvy,*Ruy,*Rux;
+  bdd_node *left,*result,*uCube;
+  bdd_node **compose;
+  int numVars,i;
+
+  numVars = bdd_num_vars(ddManager);
+  one = bdd_read_one(ddManager);
+  
+  /* rel is interms of xVars and uVars */
+  /* Test if rel is reflexive: R(x,x) == 1 */
+  compose = ALLOC(bdd_node *,numVars);
+  for (i = 0; i < numVars; i++) {
+    compose[i] = bdd_bdd_ith_var(ddManager,i);
+  }
+  for (i = 0; i < nVars; i++) {
+    int index;
+    index = bdd_node_read_index(uVars[i]);
+    compose[index] = xVars[i];
+  }
+  bdd_ref(reflex = bdd_bdd_vector_compose(ddManager,rel,compose));
+  if (reflex != one) {
+    (void) fprintf(vis_stdout,"Relation is not reflexive.\n");
+  } else {
+    (void) fprintf(vis_stdout,"Relation IS reflexive.\n");
+  }
+  bdd_recursive_deref(ddManager,reflex);
+  FREE(compose);
+
+  /* Test if rel is symmetric: R(x,u) == R(u,x) */
+  bdd_ref(Rxy = bdd_bdd_swap_variables(ddManager,rel,uVars,yVars,nVars));
+  bdd_ref(Rvy = bdd_bdd_swap_variables(ddManager,Rxy,xVars,vVars,nVars));
+  bdd_ref(Ruy = bdd_bdd_swap_variables(ddManager,Rvy,vVars,uVars,nVars));
+  bdd_ref(Rux = bdd_bdd_swap_variables(ddManager,Ruy,yVars,xVars,nVars));
+  bdd_recursive_deref(ddManager,Rvy);
+  if (Rux != rel) {
+    (void) fprintf(vis_stdout,"Relation is not symmetric.\n");
+  } else {
+    (void) fprintf(vis_stdout,"Relation IS symmetric.\n");
+  }
+  bdd_recursive_deref(ddManager,Rux);
+  
+  /* Test if rel is transitive: (\exists_u R(x,u) * R(u,y)) ==> R(x,y) */
+  bdd_ref(uCube = bdd_bdd_compute_cube(ddManager,uVars,NIL(int),nVars));
+  bdd_ref(left = bdd_bdd_and_abstract(ddManager,rel,Ruy,uCube));
+  bdd_recursive_deref(ddManager,Ruy);
+  bdd_recursive_deref(ddManager,uCube);
+  bdd_ref(result = bdd_bdd_ite(ddManager,left,Rxy,one));
+  bdd_recursive_deref(ddManager,Rxy);
+  bdd_recursive_deref(ddManager,left);
+  if (result != one) {
+    (void) fprintf(vis_stdout,"Relation is not transitive.\n");
+  } else {
+    (void) fprintf(vis_stdout,"Relation IS transitive.\n");
+  }
+  bdd_recursive_deref(ddManager,result);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Print the names of an array of BDD variables.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+RestrPrintVarArrayNames(
+  bdd_manager *ddManager,
+  bdd_node **xVars,
+  int nVars)
+{
+  int index, i;
+  mvar_type var;
+
+  for(i=0;i<nVars;i++) {
+    index = bdd_node_read_index(xVars[i]);
+    var = mdd_get_var_by_id(ddManager,index);
+    fprintf(vis_stdout," %s",var.name);
+  }
+  fprintf(vis_stdout,"\n");
+}
+
+/**Function********************************************************************
+
+  Synopsis [Print an array of character strings.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+RestrPrintNameArray(array_t *nameArray)
+{
+  int i;
+  char *str;
+  arrayForEachItem(char *,nameArray,i,str) {
+    (void) fprintf(vis_stdout,"%s\n",str);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis [Test if the given relation is deterministic.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+RestrTestIsDeterministic(
+  bdd_manager *ddManager,
+  bdd_node *tr,
+  bdd_node *initBdd,
+  bdd_node **xVars,
+  bdd_node **yVars,
+  int nVars)
+{
+  bdd_node *cproj2,*ref;
+  int flag;
+
+  bdd_ref(ref = bdd_bdd_swap_variables(ddManager,initBdd,xVars,
+				       yVars,nVars));
+  bdd_ref(cproj2 = bdd_bdd_cprojection(ddManager,tr,ref));
+  if (cproj2 != tr) {
+    bdd_node *newEdges;
+    (void) fprintf(vis_stdout,"** restr diag: Relation is non-deterministic\n");
+    /* Let's find out the newly added edges */
+    bdd_ref(newEdges = bdd_bdd_and(ddManager,tr,
+				   bdd_not_bdd_node(cproj2)));
+    (void) fprintf(vis_stdout,"** restr diag: New edges are:\n");
+    RestrPrintBddNode(ddManager,newEdges);
+    bdd_recursive_deref(ddManager,newEdges);
+    flag = 0;
+  } else {
+    (void) fprintf(vis_stdout,"** restr diag: Relation IS deterministic\n");
+    flag = 1;
+  }
+  bdd_recursive_deref(ddManager,cproj2);
+  bdd_recursive_deref(ddManager,ref);
+  
+  return flag;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
Index: vis_dev/vis-2.3/src/restr/restrFaninout.c
===================================================================
--- vis_dev/vis-2.3/src/restr/restrFaninout.c	(revision 14)
+++ vis_dev/vis-2.3/src/restr/restrFaninout.c	(revision 14)
@@ -0,0 +1,406 @@
+/**CFile***********************************************************************
+
+  FileName    [restrFaninout.c]
+
+  PackageName [restr]
+
+  Synopsis [Routines in this file implement the Fanin and Fanin-Fanout oriented
+  restructuring heuristics.]
+
+  Description [Routines in the file implement the Fanin oriented and
+  Fanin-Fanout oriented restructuring heuristics.
+
+  Please refer to "A symbolic algorithm for low power sequential synthesis,"
+  ISLPED 97, for more details.]
+
+  SeeAlso     [restrHammingD.c restrCProj.c]
+
+  Author      [Balakrishna Kumthekar <kumtheka@colorado.edu>]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "restrInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [This routine implements the Fanin oriented and Fanin-Fanout
+  oriented restructuring heuristics. Returns the BDD of the restructured STG.]
+
+  Description [This routine implements the Fanin oriented and Fanin-Fanout
+  oriented restructuring heuristics. Returns the BDD of the restructured STG.
+
+  <tt>equivRel</tt> is the state equivalence relation of the
+  fsm. <tt>oldTR</tt> if the state transition relation.  <tt>addPTR</tt> is the
+  0-1 ADD of the augmented transition relation. <tt>possessedProbMatrix</tt> is
+  the weighted graph representing the augmented transition relation. The edge
+  weights are the prob. of transition of that edge. <tt>stateProbs</tt> is an
+  ADD representing the steady state probabilities of the fsm. <tt>piVars</tt>
+  are the BDD variables for primary inputs. <tt>heuristic</tt> takes on two
+  values: RestrFanin_c and RestrFaninFanout_c.
+
+  Please refer to "A Symbolic Algorithm for Low-Power Sequential
+  Synthesis", ISLPED 97 for more details.]
+
+  SideEffects [<tt>addPtr</tt> and <tt>possessedProbMatrix</tt> are
+  dereferenced in this routine. <tt>outBdds</tt> and <tt>newInit</tt> are
+  changed to reflect the restructured STG.]
+
+  SeeAlso     [RestrMinimizeFsmByCProj RestrSelectLeastHammingDStates]
+******************************************************************************/
+bdd_node *
+RestrMinimizeFsmByFaninFanout(
+  bdd_manager *ddManager,
+  bdd_node *equivRel,
+  bdd_node *oldTR,
+  bdd_node **addPTR,
+  bdd_node **possessedProbMatrix,
+  bdd_node *initBdd,
+  bdd_node *reachable,
+  bdd_node *stateProbs,
+  bdd_node **piVars,
+  bdd_node **xVars,
+  bdd_node **yVars,
+  bdd_node **uVars,
+  bdd_node **vVars,
+  int nVars,
+  int nPi,
+  RestructureHeuristic heuristic,
+  array_t **outBdds,
+  bdd_node **newInit)
+{
+  bdd_node *temp1, *temp2, *temp3;
+  bdd_node *xCube, *yCube;
+  bdd_node *Rxy,*Rxv;
+  bdd_node *RxvgtRxy, *RxveqRxy; /* These are BDDs */
+  bdd_node **xAddVars,**yAddVars,**vAddVars;
+  bdd_node *priority, *result, *matrix;
+  bdd_node *newEquivRel;
+  bdd_node *oneInitState;
+  bdd_node *hammingWeight;
+  bdd_node *lhs, *rhs;
+  bdd_node *bddCProj;
+  bdd_node *bddCProjvy, *addCProjvy;
+  bdd_node *newCProjvy, *newCProjux;
+  bdd_node *zeroProbs, *zeroProbFactor;
+  bdd_node *weight;
+
+  array_t *newOutBdds;
+  int i, index;
+
+  /* Collect the ADD variables for futre use */
+  xAddVars = ALLOC(bdd_node *,nVars);
+  yAddVars = ALLOC(bdd_node *,nVars);
+  vAddVars = ALLOC(bdd_node *,nVars);
+
+  for(i = 0; i < nVars; i++) {
+    index = bdd_node_read_index(yVars[i]);
+    bdd_ref(yAddVars[i] = bdd_add_ith_var(ddManager,index));
+    index = bdd_node_read_index(vVars[i]);
+    bdd_ref(vAddVars[i] = bdd_add_ith_var(ddManager,index));
+    index = bdd_node_read_index(xVars[i]);
+    bdd_ref(xAddVars[i] = bdd_add_ith_var(ddManager,index));
+  }
+
+  /* Restrict the equivalence relation only to the reachable states */
+  /* temp1 = R(v) */
+  bdd_ref(temp1 = bdd_bdd_swap_variables(ddManager,reachable,xVars,
+					 vVars,nVars));
+  /* temp2 = R(y) */
+  bdd_ref(temp2 = bdd_bdd_swap_variables(ddManager,reachable,xVars,
+					 yVars,nVars));
+  /* temp3 = R(v) * R(y) */
+  bdd_ref(temp3 = bdd_bdd_and(ddManager,temp1,temp2));
+  bdd_recursive_deref(ddManager,temp1);
+  bdd_recursive_deref(ddManager,temp2);
+  /* newEquivRel(v,y) = E(v,y) * R(v) * R(y) */
+  bdd_ref(newEquivRel = bdd_bdd_and(ddManager,equivRel,temp3));
+  bdd_recursive_deref(ddManager,temp3);
+
+  /* Select one state from the set of initial states */
+  oneInitState = bdd_bdd_pick_one_minterm(ddManager,initBdd,xVars,nVars);
+  bdd_ref(oneInitState);
+
+  /* Initially an arbitrary choice of a 'nominal representative' for each
+     equivalence class is made--using compatible projection--with the initial
+     state as the reference vertex. bddCProj is as the name indicates, in terms
+     of y and x. bddCProj refers to $\Psi(x,y)$ in the ISLPED 97 reference. */
+
+  bdd_ref(temp1 = bdd_bdd_swap_variables(ddManager,oneInitState,xVars,
+					 vVars,nVars));
+  bdd_recursive_deref(ddManager,oneInitState);
+  bdd_ref(bddCProjvy = bdd_bdd_cprojection(ddManager, newEquivRel, temp1));
+  bdd_recursive_deref(ddManager,newEquivRel);
+  bdd_recursive_deref(ddManager,temp1);
+  bdd_ref(bddCProj = bdd_bdd_swap_variables(ddManager,bddCProjvy,vVars,
+					    xVars,nVars));
+  bdd_ref(addCProjvy = bdd_bdd_to_add(ddManager,bddCProjvy));
+  bdd_recursive_deref(ddManager,bddCProjvy);
+
+  /* Let's compute the weight matrix */
+  /* hammingWeight equal (nVars - HD(x,y)) */
+  bdd_ref(temp1 = bdd_add_const(ddManager,(double)nVars));
+  bdd_ref(temp2 = bdd_add_hamming(ddManager,xVars,yVars,nVars));
+  bdd_ref(hammingWeight = bdd_add_apply(ddManager,bdd_add_minus,
+					temp1,temp2));
+  bdd_recursive_deref(ddManager,temp1);
+  bdd_recursive_deref(ddManager,temp2);
+
+  /* temp1 = possessedProbMatrix * (nVars - HD(x,y)) */
+  bdd_ref(temp1 = bdd_add_apply(ddManager,bdd_add_times,hammingWeight,
+				*possessedProbMatrix));
+  bdd_recursive_deref(ddManager,*possessedProbMatrix);
+
+  /* matrix = possessedProbMatrix * (nVars - HD(x,y)) * stateProbs */
+  bdd_ref(matrix = bdd_add_apply(ddManager,bdd_add_times,temp1,
+				 stateProbs));
+  bdd_recursive_deref(ddManager,temp1);
+
+  /* Compute the contribution of the edges that have a state with zero
+   * probability as its source node. The contribution is measured in terms
+   * of the hamming distance between the end points of the edge.
+   * The total weight on any edge is the sum of "matrix" as computed
+   * above and "zeroProbFactor" as computed below.
+   */
+  bdd_ref(temp1 = bdd_add_bdd_strict_threshold(ddManager,stateProbs,0.0));
+  bdd_ref(temp2 = bdd_not_bdd_node(temp1));
+  bdd_recursive_deref(ddManager,temp1);
+  /* zeroProbs evaluates to 1 for those states which have zero steady state
+   * probability. zeroProbs is a 0-1 ADD.
+   */
+  bdd_ref(zeroProbs = bdd_bdd_to_add(ddManager,temp2));
+  bdd_recursive_deref(ddManager,temp2);
+
+  /* temp1 = (1 - HD(x,y)/nVars) */
+  bdd_ref(temp2 = bdd_add_const(ddManager,(double)nVars));
+  bdd_ref(temp1 = bdd_add_apply(ddManager,bdd_add_divide,hammingWeight,
+				temp2));
+  bdd_recursive_deref(ddManager,temp2);
+  bdd_recursive_deref(ddManager,hammingWeight);
+
+  /* temp2 = (1 - HD(x,y)/nVars) * zeroProbs(x) */
+  bdd_ref(temp2 = bdd_add_apply(ddManager,bdd_add_times,temp1,zeroProbs));
+  bdd_recursive_deref(ddManager,temp1);
+  bdd_recursive_deref(ddManager,zeroProbs);
+
+  /* zeroProbFactor = (1 - HD(x,y)/nVars) * zeroProbs(x) * addPTR */
+  bdd_ref(zeroProbFactor = bdd_add_apply(ddManager,bdd_add_times,
+					 *addPTR,temp2));
+  bdd_recursive_deref(ddManager,*addPTR);
+  bdd_recursive_deref(ddManager,temp2);
+
+  /* Total edge weight = matrix + zeroProbFactor */
+  bdd_ref(weight = bdd_add_apply(ddManager,bdd_add_plus,matrix,
+				 zeroProbFactor));
+  bdd_recursive_deref(ddManager,matrix);
+  bdd_recursive_deref(ddManager,zeroProbFactor);
+    
+  /* lhs = Abs(x) (weight(x,y)*CProj(v,y)) */
+  bdd_ref(temp1 = bdd_add_apply(ddManager,bdd_add_times,weight,
+				addCProjvy));
+  bdd_ref(temp3 = bdd_add_compute_cube(ddManager,xAddVars,NIL(int),nVars));
+  bdd_ref(lhs = bdd_add_exist_abstract(ddManager,temp1,temp3));
+  bdd_recursive_deref(ddManager,temp1);
+  bdd_recursive_deref(ddManager,temp3);
+
+  /* Now lhs is a function of x and y */
+  bdd_ref(temp1 = bdd_add_swap_variables(ddManager,lhs,vAddVars,xAddVars,
+					 nVars));
+  bdd_recursive_deref(ddManager,lhs);
+  lhs = temp1;
+
+  if (heuristic == RestrFaninFanout_c) {
+    /* let's compute the rhs */
+    bdd_ref(temp1 = bdd_add_swap_variables(ddManager,addCProjvy,yAddVars,
+					   xAddVars, nVars));
+    bdd_recursive_deref(ddManager,addCProjvy);
+    bdd_ref(rhs = bdd_add_apply(ddManager,bdd_add_times,weight,temp1));
+    bdd_recursive_deref(ddManager,temp1);
+    bdd_recursive_deref(ddManager,weight);
+    temp1 = rhs;
+    bdd_ref(temp3 = bdd_add_compute_cube(ddManager,yAddVars,NIL(int),nVars));
+    bdd_ref(rhs = bdd_add_exist_abstract(ddManager,temp1,temp3));
+    bdd_recursive_deref(ddManager,temp1);
+    bdd_recursive_deref(ddManager,temp3);
+
+    /* rhs is now a function of x and y */
+    bdd_ref(temp1 = bdd_add_swap_variables(ddManager,rhs,xAddVars,
+					   yAddVars,nVars));
+    bdd_recursive_deref(ddManager,rhs);
+    bdd_ref(rhs = bdd_add_swap_variables(ddManager,temp1,vAddVars,
+					 xAddVars,nVars));
+    bdd_recursive_deref(ddManager,temp1);
+
+    /* take the average of lhs and rhs */
+    bdd_ref(temp1 = bdd_add_apply(ddManager,bdd_add_plus,lhs,rhs));
+    bdd_recursive_deref(ddManager,lhs);
+    bdd_recursive_deref(ddManager,rhs);
+    bdd_ref(temp2 = bdd_add_const(ddManager,(double)2.0));
+    bdd_ref(Rxy = bdd_add_apply(ddManager,bdd_add_divide,temp1,temp2));
+    bdd_recursive_deref(ddManager,temp1);
+    bdd_recursive_deref(ddManager,temp2);  
+  }
+  else {
+    bdd_recursive_deref(ddManager,weight);
+    bdd_recursive_deref(ddManager,addCProjvy);
+    Rxy = lhs;
+  }
+
+  /* Rxv = Rxy(x,v) */
+  bdd_ref(Rxv = bdd_add_swap_variables(ddManager,Rxy,yAddVars,vAddVars,
+				       nVars));
+  /* RxvgtRxy(x,v,y) = Rxv(x,v) > Rxy(x,y) */
+  bdd_ref(temp1 = bdd_add_apply(ddManager,RestrAddMaximum,Rxv,Rxy));
+  bdd_ref(RxvgtRxy = bdd_add_bdd_threshold(ddManager,temp1,(double) 1.0));
+  bdd_recursive_deref(ddManager,temp1);
+
+  /* RxveqRxy(x,v,y) = Rxz(x,v) == Rxy(x,y) */
+  bdd_ref(temp1 = bdd_add_apply(ddManager,RestrAddEqual,Rxv,Rxy));
+  bdd_ref(RxveqRxy = bdd_add_bdd_threshold(ddManager,temp1,(double) 1.0));
+  bdd_recursive_deref(ddManager,temp1);
+  bdd_recursive_deref(ddManager,Rxv);
+  bdd_recursive_deref(ddManager,Rxy);
+
+  /* temp1 is the tie-break function. (RxveqRxy . temp1 = temp2)*/
+  bdd_ref(temp1 = bdd_dxygtdxz(ddManager,nVars,xVars,yVars,vVars));
+  bdd_ref(temp2 = bdd_bdd_and(ddManager,RxveqRxy,temp1));
+  bdd_recursive_deref(ddManager,temp1);
+  bdd_recursive_deref(ddManager,RxveqRxy);
+
+  bdd_ref(priority = bdd_bdd_or(ddManager,temp2,RxvgtRxy));
+  bdd_recursive_deref(ddManager,RxvgtRxy);
+  bdd_recursive_deref(ddManager,temp2);
+
+  /* temp1 represents the pair (oldrepresentative,newprepresentative) in terms
+   of x and y respectively */
+  bdd_ref(temp1 = bdd_priority_select(ddManager,bddCProj,xVars,
+				      yVars,vVars,priority,nVars,NULL));
+  bdd_recursive_deref(ddManager,priority);
+
+  bdd_ref(xCube = bdd_bdd_compute_cube(ddManager,xVars,NIL(int),nVars));
+  bdd_ref(yCube = bdd_bdd_compute_cube(ddManager,yVars,NIL(int),nVars));
+
+  /* newCProjvy is in terms of v,y */
+  /* v represents the new representative of equivalent states */
+
+  bdd_ref(temp2 = bdd_bdd_swap_variables(ddManager,temp1,yVars,vVars,
+					 nVars));
+  bdd_recursive_deref(ddManager,temp1);
+  bdd_ref(newCProjvy = bdd_bdd_and_abstract(ddManager,bddCProj,temp2,
+					    xCube));
+  bdd_recursive_deref(ddManager,bddCProj);
+  bdd_recursive_deref(ddManager,temp2);
+
+  bdd_ref(temp1 = bdd_bdd_swap_variables(ddManager,newCProjvy,yVars,
+					 xVars,nVars));
+  bdd_ref(newCProjux = bdd_bdd_swap_variables(ddManager,temp1,vVars,
+					      uVars,nVars));
+  bdd_recursive_deref(ddManager,temp1);
+
+  /* Change the output functions accordingly */
+  newOutBdds = array_alloc(bdd_node *,0);
+  arrayForEachItem(bdd_node *,*outBdds,i,temp3) {
+    bdd_ref(temp1 = bdd_bdd_and_abstract(ddManager,temp3,newCProjux,
+					 xCube));
+    bdd_ref(temp2 = bdd_bdd_swap_variables(ddManager,temp1,uVars,xVars,
+					   nVars));
+    bdd_recursive_deref(ddManager,temp1);
+    bdd_recursive_deref(ddManager,temp3);
+    array_insert_last(bdd_node *,newOutBdds,temp2);
+  }
+  array_free(*outBdds);
+  *outBdds = newOutBdds;
+
+  /* Change the initBdd accordingly */
+  bdd_ref(temp1 = bdd_bdd_and_abstract(ddManager,initBdd,newCProjux,xCube));
+  bdd_ref(*newInit = bdd_bdd_swap_variables(ddManager,temp1,uVars,xVars,
+					    nVars));
+  bdd_recursive_deref(ddManager,temp1);
+
+  /* Compute the new transition relation w.r.t the new CProjection function.
+   * result = newCProjux * oldTR(x,y) * newCProjvy 
+   */
+  bdd_ref(temp1 = bdd_bdd_and(ddManager,xCube,yCube));
+  bdd_recursive_deref(ddManager,xCube);
+  bdd_recursive_deref(ddManager,yCube);
+  bdd_ref(temp2 = bdd_bdd_and(ddManager,newCProjux,oldTR));
+  bdd_recursive_deref(ddManager,newCProjux);
+  bdd_ref(temp3 = bdd_bdd_and(ddManager,temp2,newCProjvy));
+  bdd_recursive_deref(ddManager,newCProjvy);
+  bdd_recursive_deref(ddManager,temp2);
+  bdd_ref(result = bdd_bdd_exist_abstract(ddManager,temp3,temp1));
+  bdd_recursive_deref(ddManager,temp1);
+  bdd_recursive_deref(ddManager,temp3);
+
+  bdd_ref(temp1 = bdd_bdd_swap_variables(ddManager,result,uVars,xVars,
+					 nVars));
+  bdd_ref(temp2 = bdd_bdd_swap_variables(ddManager,temp1,vVars,yVars,
+					 nVars));
+  bdd_recursive_deref(ddManager,temp1);
+  bdd_recursive_deref(ddManager,result);
+  result = temp2;
+
+  /* Clean up */
+  for(i = 0; i < nVars; i++) {
+    bdd_recursive_deref(ddManager,yAddVars[i]);
+    bdd_recursive_deref(ddManager,vAddVars[i]);
+    bdd_recursive_deref(ddManager,xAddVars[i]);
+  }
+  FREE(yAddVars);
+  FREE(vAddVars);
+  FREE(xAddVars);
+  
+  /* Return the restructred STG */
+  return result;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
Index: vis_dev/vis-2.3/src/restr/restrHammingD.c
===================================================================
--- vis_dev/vis-2.3/src/restr/restrHammingD.c	(revision 14)
+++ vis_dev/vis-2.3/src/restr/restrHammingD.c	(revision 14)
@@ -0,0 +1,373 @@
+/**CFile***********************************************************************
+
+  FileName    [restrHammingD.c]
+
+  PackageName [restr]
+
+  Synopsis [The function in this file implements the Hamming distance heuristic
+  to restructure the STG.]
+
+  Description [The function in this file implements the Hamming distance
+  heuristic to restructure the STG. Please refer to "A symbolic algorithm for
+  low power sequential synthesis," ISLPED 97, for more details.]
+
+  SeeAlso     [restrFaninout.c restrCProj.c]
+
+  Author      [Balakrishna Kumthekar <kumtheka@colorado.edu>]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "restrInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static bdd_node * restrHxygthxz(bdd_manager *dd, int N, bdd_node **x, bdd_node **y, bdd_node **z);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [This procedure implements the Hamming distance heuristic to
+  restructure the STG. Returns the BDD of the restructured STG.]
+
+  Description [This procedure implements the Hamming distance heuristic to
+  restructure the STG. A priority function based on hamming distance is used to
+  select destination state. oldTR is a BDD representing the transition relation
+  of an FSM. pTR is the augmented transition relation. Both pTR and oldTR are
+  functions of xVars and yVars. vVars are auxillary variables used inside this
+  procedure. The three sets of variables, xVars, yVars and vVars are of length
+  nVars. nPi are the number of primary input variables in the FSM.
+
+  This heuristic selects a destination state such that the number of bit
+  changes per state transition is minimized.  In order to do that the following
+  function is utilized.
+
+  H(x,y,v) = 1 if HD(x,y) < HD(x,v)
+           = 0 otherwise
+
+  where HD(x,y) is the hamming distance between states encoded by x and
+  y. However, H(x,y,v) is not a priority function. To break the tie, relative
+  proximity function is used. H(x,y,v) and the relative proximity function are
+  used to defined a composite priority functioin.
+
+  Please refer to "A symbolic algorithm for low power sequential synthesis,"
+  ISLPED 97, for more details.]
+
+  SideEffects [None]
+
+  SeeAlso [RestrMinimizeFsmByCProj RestrMinimizeFsmByFaninFanout
+  bdd_priority_select]
+
+******************************************************************************/
+bdd_node *
+RestrSelectLeastHammingDStates(
+  bdd_manager	*dd,
+  bdd_node	*oldTR,
+  bdd_node 	*pTR,
+  bdd_node	**xVars,
+  bdd_node	**yVars,
+  bdd_node	**vVars,
+  int		  nVars,
+  int		  nPi)
+{
+  bdd_node *result;
+  bdd_node *temp1,*Pi;
+  double oldSize,newSize;
+  int twice = 0;
+
+  /* restrHxygthxz is a function that returns 1 if HD(x,y) > HD(x,z) */
+  bdd_ref(Pi = restrHxygthxz(dd,nVars,xVars,yVars,vVars));
+  result = bdd_priority_select(dd,pTR,xVars,yVars,vVars,
+			       Pi,nVars,NULL);
+  bdd_recursive_deref(dd,Pi);
+  if(! result) {
+    return NIL(bdd_node);
+  }
+  bdd_ref(result);
+
+  oldSize = bdd_count_minterm(dd,oldTR,2*nVars+nPi);
+  newSize = bdd_count_minterm(dd,result,2*nVars+nPi);
+
+  /* As restrHxygthxz is not a priority function, result might still be
+     non-deterministic. Hence use the tie breaker bdd_dxygtdxz to make the
+     "result" deterministic */
+
+  if(newSize > oldSize) {
+    temp1 = bdd_priority_select(dd,result,xVars,yVars,vVars,
+				NIL(bdd_node),nVars,bdd_dxygtdxz);
+    if(! temp1) {
+      return NIL(bdd_node);
+    } 
+    bdd_ref(temp1);
+    bdd_recursive_deref(dd,result);
+    result = temp1;
+    twice = 1;
+  }
+  if (twice) {
+    newSize = bdd_count_minterm(dd,result,2*nVars+nPi);
+    assert(oldSize == newSize);
+  }
+
+  if(result == oldTR) {
+    fprintf(vis_stdout,"** restr info: HammingD heuristic produces no restructuring.\n");
+  }
+
+  return result;
+
+#if 0
+  /* Compute a priority function that looks like:
+   * \Pi_H(x,y,z) = H(x,y,z) \vee (\neg H(x,z,y) \wedge \Pi_{RP}(x,y,z))
+   *
+   * where H(x,y,z) = 1 if HD(x,y) < HD(x,z) and 0 otherwise;
+   * Here z variables are vVars.
+   */
+
+  /* Observe that below I am computing H(x,z,y) */
+  bdd_ref(Hxyz = restrHxygthxz(dd,nVars,xVars,vVars,yVars));
+  bdd_ref(Hxzy = bdd_bdd_swap_variables(dd,Hxyz,yVars,vVars,nVars));
+  bdd_ref(piRP = bdd_dxygtdxz(dd,nVars,xVars,yVars,vVars));
+
+  bdd_ref(Pi = bdd_bdd_ite(dd,Hxyz,bdd_not_bdd_node(Hxzy),piRP));
+  bdd_recursive_deref(dd,Hxzy);
+  bdd_recursive_deref(dd,piRP);
+  bdd_recursive_deref(dd,Hxyz);
+
+  /* Compute \Pi_H(x,z,y) and use priority select formulation */
+  bdd_ref(temp = bdd_bdd_swap_variables(dd,Pi,yVars,vVars,nVars));
+  bdd_recursive_deref(dd,Pi);
+  Pi = temp;
+  result = bdd_priority_select(dd,pTR,xVars,yVars,vVars,
+			       Pi,nVars,NULL);
+  if(! result) {
+    return NIL(bdd_node);
+  }
+  bdd_ref(result);
+#endif
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Returns a BDD F(x,y,z) such that F(x,y,z) equals 1 when HD(x,y) >
+  HD(x,z), and 0 otherwise. Returns the BDD if successful else NULL.]
+
+  Description [This function generates a BDD for the function HD(x,y) >
+  HD(x,z). x,y, and z are N-bit numbers, x[0],x[1] ... x[N-1], y[0], y[1]
+  ... y[N-1] and z[0], z[1] ... z[N-1]. Hamming distance is defined as the
+  number of bits differing in a given pair of encodings (X,Y). The BDD is built
+  bottom-up.]
+
+  SideEffects [None]
+
+  SeeAlso     [bdd_priority_select bdd_add_hamming]
+
+******************************************************************************/
+static bdd_node *
+restrHxygthxz(
+  bdd_manager *dd, 
+  int N,         
+  bdd_node **x,    
+  bdd_node **y,    
+  bdd_node **z)    
+{
+  bdd_node **dEqualToINodes, **tempDEqualToINodes;
+  bdd_node *z1, *z2, *z3, *z4, *y1, *y2;
+  bdd_node *one, *zero;
+  bdd_node *temp;
+  bdd_node *result;
+  int i, j, m;
+  int fromIndex, toIndex;
+
+  dEqualToINodes = ALLOC(bdd_node *, 2*N+1);
+  tempDEqualToINodes = ALLOC(bdd_node *, 2*N+1);
+
+  one = bdd_read_one(dd);
+  zero = bdd_not_bdd_node(one);
+
+  for(i = 0; i <= N; i++) {
+    dEqualToINodes[i] = zero;
+    bdd_ref(dEqualToINodes[i]);
+    tempDEqualToINodes[i] = zero;
+    bdd_ref(tempDEqualToINodes[i]);
+  }
+  for(i = N+1; i < 2*N+1; i++) {
+    dEqualToINodes[i] = one;
+    bdd_ref(dEqualToINodes[i]);
+    tempDEqualToINodes[i] = one;
+    bdd_ref(tempDEqualToINodes[i]);
+  }
+
+  /* Loop to build the rest of the BDD */
+  for(i = N-1; i >= 0; i--) {
+    fromIndex = N - restrMin(N-i-1,i);
+    toIndex = restrMin(N-i,i) + N;
+
+    for(j = fromIndex;j <= toIndex; j++) {
+      z1 = bdd_bdd_ite(dd,z[i],tempDEqualToINodes[j],
+		       tempDEqualToINodes[j-1]);
+      if(! z1){
+	goto endgame;
+      }
+      bdd_ref(z1);
+ 
+      z2 = bdd_bdd_ite(dd,z[i],tempDEqualToINodes[j+1],
+		       tempDEqualToINodes[j]);
+      if(! z2){
+	bdd_recursive_deref(dd,z1);
+	goto endgame;
+      }
+      bdd_ref(z2);
+ 
+      z3 = bdd_bdd_ite(dd,z[i],tempDEqualToINodes[j],
+		       tempDEqualToINodes[j+1]);
+      if(! z3){
+	bdd_recursive_deref(dd,z1);
+	bdd_recursive_deref(dd,z2);
+	goto endgame;
+      }
+      bdd_ref(z3);
+ 
+      z4 = bdd_bdd_ite(dd,z[i],tempDEqualToINodes[j-1],
+		       tempDEqualToINodes[j]);
+      if(! z4){
+	bdd_recursive_deref(dd,z1);
+	bdd_recursive_deref(dd,z2);
+	bdd_recursive_deref(dd,z3);
+	goto endgame;
+      }
+      bdd_ref(z4);
+ 
+      y1 = bdd_bdd_ite(dd,y[i],z1,z2);
+      if(! y1){
+	bdd_recursive_deref(dd,z1);
+	bdd_recursive_deref(dd,z2);
+	bdd_recursive_deref(dd,z3);
+	bdd_recursive_deref(dd,z4);
+	goto endgame;
+      }
+      bdd_ref(y1);
+ 
+      y2 = bdd_bdd_ite(dd,y[i],z3,z4);
+      if(! y2){
+	bdd_recursive_deref(dd,z1);
+	bdd_recursive_deref(dd,z2);
+	bdd_recursive_deref(dd,z3);
+	bdd_recursive_deref(dd,z4);
+	bdd_recursive_deref(dd,y1);
+	goto endgame;
+      }
+      bdd_ref(y2);
+ 
+      bdd_recursive_deref(dd,z1);
+      bdd_recursive_deref(dd,z2);
+      bdd_recursive_deref(dd,z3);
+      bdd_recursive_deref(dd,z4);
+ 
+      temp = bdd_bdd_ite(dd,x[i],y1,y2);
+      if(! temp){
+	bdd_recursive_deref(dd,y1);
+	bdd_recursive_deref(dd,y2);
+	goto endgame;
+      }
+      bdd_ref(temp);
+      dEqualToINodes[j] = temp;
+      bdd_recursive_deref(dd,y1);
+      bdd_recursive_deref(dd,y2);
+    }
+
+    for(j = 0; j < 2*N+1; j++) {
+      if(tempDEqualToINodes[j]) {
+	bdd_recursive_deref(dd,tempDEqualToINodes[j]);
+      }
+      tempDEqualToINodes[j] = dEqualToINodes[j]; 
+      if(tempDEqualToINodes[j]) {
+	bdd_ref(tempDEqualToINodes[j]);
+      }
+      if(dEqualToINodes[j] &&
+	 j >= fromIndex && j <= toIndex) {
+	bdd_recursive_deref(dd,dEqualToINodes[j]);
+	/* To be safe */
+	dEqualToINodes[j] = NIL(bdd_node);
+      }
+    }
+  }
+  /* Clean up */
+  for(j = 0; j < N; j++) {
+    if(tempDEqualToINodes[j]) {
+      bdd_recursive_deref(dd,tempDEqualToINodes[j]);
+    }
+  }
+  for(j = N+1; j < 2*N+1; j++) {
+    if(tempDEqualToINodes[j]) {
+      bdd_recursive_deref(dd,tempDEqualToINodes[j]);
+    }
+  }
+
+  result = tempDEqualToINodes[N];
+  bdd_deref(result);
+
+  FREE(dEqualToINodes);
+  FREE(tempDEqualToINodes);
+
+  return result;
+
+endgame:
+  for(m = 0; m < 2*N+1; m++) {
+    if(tempDEqualToINodes[m]) {
+      bdd_recursive_deref(dd,tempDEqualToINodes[m]);
+    }
+  }
+  for(m = fromIndex; m < j; m++) {
+    bdd_recursive_deref(dd,dEqualToINodes[m]);
+  }
+  FREE(dEqualToINodes);
+  FREE(tempDEqualToINodes);
+
+  return NULL;
+}
+
Index: vis_dev/vis-2.3/src/restr/restrInt.h
===================================================================
--- vis_dev/vis-2.3/src/restr/restrInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/restr/restrInt.h	(revision 14)
@@ -0,0 +1,154 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [restrInt.h]
+
+  PackageName [restr]
+
+  Synopsis [Internal declarations for state transition graph (STG)
+  restructuring package.]
+
+  Author      [Balakrishna Kumthekar <kumtheka@colorado.edu>]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#ifndef _RESTRINT
+#define _RESTRINT
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "restr.h"
+#include "st.h"
+#include "mark.h"
+#include <string.h>
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+/**Enum************************************************************************
+
+  Synopsis [Different heuristics to perform the restructuring of state
+  transition graph.]
+
+  SeeAlso     []
+
+******************************************************************************/
+typedef enum {
+  RestrHammingD_c,
+  RestrFanin_c,
+  RestrFaninFanout_c,
+  RestrCProjection_c
+} RestructureHeuristic;
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**Macro***********************************************************************
+
+  Synopsis [Definition of a key to store a partition created solely for
+  internal use.]
+
+  SideEffects  [None]
+
+  SeeAlso      []
+
+******************************************************************************/
+#define RESTR_PART_NETWORK_APPL_KEY "Restr_PartNetworkApplKey"
+
+
+/**Macro***********************************************************************
+
+  Synopsis [Definition of a key to store an FSM created solely for internal
+  use.]
+
+  SideEffects  [None]
+
+  SeeAlso      []
+
+******************************************************************************/
+#define RESTR_FSM_NETWORK_APPL_KEY "Restr_FsmNetworkApplKey"
+
+
+/**Macro***********************************************************************
+
+  Synopsis [Returns the maximum value of the arguments.]
+
+  SideEffects  [None]
+
+  SeeAlso      []
+
+******************************************************************************/
+#define restrMax(x,y)	(((y) > (x)) ? (y) : (x))
+
+
+/**Macro***********************************************************************
+
+  Synopsis [Returns the minimum value of the arguments.]
+
+  SideEffects  [None]
+
+  SeeAlso      []
+
+******************************************************************************/
+#define restrMin(x,y)	(((y) > (x)) ? (x) : (y))
+
+#define MAX_NAME_LEN 256
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN bdd_node * RestrMinimizeFsmByCProj(bdd_manager *ddManager, bdd_node *equivRel, bdd_node *originalTR, bdd_node *initBdd, bdd_node **xVars, bdd_node **yVars, bdd_node **uVars, bdd_node **vVars, bdd_node **piVars, int nVars, int nPi, array_t **outBdds, bdd_node **newInit);
+EXTERN void RestrNamePrintByMddId(Ntk_Network_t *network, array_t *array);
+EXTERN void RestrPrintMvfArray(mdd_manager *ddManager, Mvf_Function_t *mvfArray, array_t *nodeArray, array_t *idArray);
+EXTERN void RestrPrintAllVarNames(bdd_manager *ddManager);
+EXTERN void RestrPrintBddNode(bdd_manager *manager, bdd_node *ddNode);
+EXTERN void RestrVerifyFsmEquivBySimulation(bdd_manager *ddManager, bdd_node *oldTr, bdd_node *newTr, array_t *outBdds1, array_t *outBdds2, bdd_node *initBdd1, bdd_node *initBdd2, bdd_node **xVars, bdd_node **yVars, bdd_node **piVars, int nVars, int nPi);
+EXTERN void RestrTestIsEquivRelation(bdd_manager *ddManager, bdd_node *rel, bdd_node **xVars, bdd_node **yVars, bdd_node **uVars, bdd_node **vVars, int nVars);
+EXTERN void RestrPrintVarArrayNames(bdd_manager *ddManager, bdd_node **xVars, int nVars);
+EXTERN void RestrPrintNameArray(array_t *nameArray);
+EXTERN int RestrTestIsDeterministic(bdd_manager *ddManager, bdd_node *tr, bdd_node *initBdd, bdd_node **xVars, bdd_node **yVars, int nVars);
+EXTERN bdd_node * RestrMinimizeFsmByFaninFanout(bdd_manager *ddManager, bdd_node *equivRel, bdd_node *oldTR, bdd_node **addPTR, bdd_node **possessedProbMatrix, bdd_node *initBdd, bdd_node *reachable, bdd_node *stateProbs, bdd_node **piVars, bdd_node **xVars, bdd_node **yVars, bdd_node **uVars, bdd_node **vVars, int nVars, int nPi, RestructureHeuristic heuristic, array_t **outBdds, bdd_node **newInit);
+EXTERN bdd_node * RestrSelectLeastHammingDStates(bdd_manager *dd, bdd_node *oldTR, bdd_node *pTR, bdd_node **xVars, bdd_node **yVars, bdd_node **vVars, int nVars, int nPi);
+EXTERN int RestrCommandRestructureFsm(Fsm_Fsm_t *fsm, RestructureHeuristic heuristic, char *orderFileName, boolean equivClasses, boolean nonReachEquiv, boolean eqvMethod, st_table *inputProb, Synth_InfoData_t *synthInfo);
+EXTERN array_t * RestrGetOutputArray(Ntk_Network_t *network);
+EXTERN bdd_node * RestrCreateProductOutput(bdd_manager *ddManager, array_t *funArray, bdd_node **xVars, bdd_node **yVars, int nVars);
+EXTERN array_t * RestrComputeTRWithIds(bdd_manager *ddManager, array_t *nextBdds, bdd_node **xVars, bdd_node **yVars, bdd_node **uVars, bdd_node **vVars, int nVars);
+EXTERN bdd_node * RestrGetEquivRelation(bdd_manager *mgr, bdd_node *Lambda, bdd_node *tranRelation, bdd_node **xVars, bdd_node **yVars, bdd_node **uVars, bdd_node **vVars, bdd_node **piVars, int nVars, int nPi, boolean restrVerbose);
+EXTERN bdd_node * RestrComputeEquivRelationUsingCofactors(bdd_manager *mgr, bdd_node *Lambda, bdd_node *TR, bdd_node **xVars, bdd_node **yVars, bdd_node **uVars, bdd_node **vVars, bdd_node **piVars, int nVars, int nPi, boolean restrVerbose);
+EXTERN bdd_node * RestrComputeTrWithGhostEdges(bdd_manager *mgr, bdd_node **yVars, bdd_node **vVars, bdd_node *tr, bdd_node *equivRelation, int nVars);
+EXTERN bdd_node * RestrAddMaximum(bdd_manager *ddManager, bdd_node **f, bdd_node **g);
+EXTERN bdd_node * RestrAddEqual(bdd_manager *ddManager, bdd_node **f, bdd_node **g);
+EXTERN bdd_node ** RestrBddNodeArrayFromIdArray(bdd_manager *ddManager, array_t *idArray);
+EXTERN double RestrAverageBitChange(bdd_manager *manager, bdd_node *probTR, bdd_node **xVars, bdd_node **yVars, int nVars);
+EXTERN array_t * RestrCreateNewStateVars(Ntk_Network_t *network, bdd_manager *ddManager, bdd_node **xVars, bdd_node **yVars);
+EXTERN void RestrSetInitialOrder(Ntk_Network_t *network, bdd_manager *ddManager);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _RESTRINT */
Index: vis_dev/vis-2.3/src/restr/restrRestructure.c
===================================================================
--- vis_dev/vis-2.3/src/restr/restrRestructure.c	(revision 14)
+++ vis_dev/vis-2.3/src/restr/restrRestructure.c	(revision 14)
@@ -0,0 +1,1279 @@
+/**CFile***********************************************************************
+
+  FileName    [restrRestructure.c]
+
+  PackageName [restr]
+
+  Synopsis [This file contains a main procedure that restructures an STG and
+  transforms it into a new multilevel circuit.]
+
+  Description [This file contains a main procedure that restructures an STG and
+  transforms it into a new multilevel circuit. 
+
+  Please refer to "A symbolic algorithm for low power sequential synthesis,"
+  ISLPED 97, for more details.]
+
+  SeeAlso     [restrHammingD.c restrFaninout.c restrCProj.c]
+
+  Author      [Balakrishna Kumthekar <kumtheka@colorado.edu>]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "restrInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+extern int restrCreatedPart;
+extern int restrCreatedFsm;
+extern boolean restrVerbose;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static array_t * BuildFunctions(graph_t *partition, array_t *rootNames);
+static bdd_node ** AddPowerSolve(bdd_manager *mgr, bdd_node *bddTr, bdd_node *init, bdd_node **x, bdd_node **y, bdd_node **pi, st_table *inputProb, int nVars, int nPi);
+static bdd_node * PerformRestructure(bdd_manager *ddManager, bdd_node *prunedTR, bdd_node *equivRel, bdd_node *reachable, bdd_node *initBdd, bdd_node **piVars, bdd_node **xVars, bdd_node **yVars, bdd_node **uVars, bdd_node **vVars, st_table *inputProb, int nVars, int nPi, RestructureHeuristic heuristic, boolean equivClasses, array_t **outBdds, bdd_node **newInit, bdd_node **stateProbs);
+static st_table * CreateNameToMvfTable(bdd_manager *ddManager, array_t *outBdds, array_t *nextBdds, array_t *outputArray, array_t *tranFunArray);
+static st_table * CreateCareTable(Ntk_Network_t *network, mdd_t *reachMdd);
+static enum st_retval StMvfFree(char *key, char *value, char *arg);
+static void CountEquivalentClasses(bdd_manager *ddManager, bdd_node *equivRel, bdd_node *initBdd, bdd_node **xVars, bdd_node **uVars, int nVars);
+static array_t * GetBddArrayFromMvfArray(array_t *mvfArray);
+static bdd_node * DoMarkovPowerAnalysis(bdd_manager *ddManager, bdd_node *prunedTR, bdd_node *initBdd, bdd_node **piVars, bdd_node **xVars, bdd_node **yVars, st_table *inputProb, int nVars, int nPi);
+static array_t * ExtractTransitionFuns(bdd_manager *ddManager, bdd_node *finalTR, bdd_node **yVars, int nVars);
+static array_t * GetBddArrayFromNameArray(Fsm_Fsm_t *fsm, array_t *nameArray);
+static void ExpandReachableSet(bdd_manager *ddManager, bdd_node **reachable, bdd_node *equivRel, bdd_node **xVars, bdd_node **uVars, int nVars);
+static graph_t * CreateNewPartition(Ntk_Network_t *network, bdd_manager *ddManager, array_t *outBdds, array_t *nextBdds, array_t *outputArray, array_t *tranFunArray);
+static Fsm_Fsm_t * CreateNewFsm(Ntk_Network_t *network, graph_t *partition, bdd_manager *ddManager, bdd_node *finalTR, bdd_node *initBdd, bdd_node *reachable, bdd_node *stateProbs, bdd_node **xVars, bdd_node **yVars, bdd_node **piVars, st_table *inputProb, int nVars, int nPi);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [This function performs the complete task of STG restructuring and
+  logic implementation.]
+
+  Description [The STG restructuring process proceeds as follows: First a state
+  equivalence relation E(x,y) is derived from the current STG of the finite
+  state machine. If the parameter <tt>nonReachEquiv</tt> is set E(x,y) is used
+  to extend the set of reachable states R(x) to include those states equivalent
+  to R(x) but unreachable. This sometimes provides extra flexibility when
+  choosing an edge. To perform the restructuring transformation, edges are
+  first added (clearly driven by E(x,y)) to the original STG and then
+  undesirable edges are removed, in such a way that the functional behavior of
+  the machine is not affected. We say that the original STG is transformed into
+  an <tt>augmented</tt> STG.
+
+  The steady state probabilities of the STG are computed using Markovian
+  analysis. The edges of the augmented STG are then labeled by a cost function
+  which depends on the absolute transition probability and hamming distance
+  between the ends of the edge. After the appropriate <tt>heuristic</tt> is
+  applied, the new (restructured) STG is then translated in to a multi-level
+  boolean network.
+
+  <tt>heuristic</tt> takes on four options: ham: Hamming distance based
+  heuristic is used, fanin: Fanin oriented heuristic, faninout: Fanin-Fanout
+  oriented heuristic, cproj: C-Projection. For more information please refer to
+  "A symbolic algorithm for low power sequential synthesis," ISLPED 97.
+
+  <tt>equivClasses</tt> prints the number of equivalent classes in the STG.
+
+  <tt>inputProb</tt> is optional. If not specified, equiprobabale primary
+  inputs are assumed. Else, the table contains the pair, (PI_name,prob), where
+  <tt>prob</tt> is the probability of the PI signal being 1.
+
+  <tt>synthInfo</tt> specifies synthesis specific options. For more information
+  look at synth.h]
+
+  The BDD variable order at the end of the algorithm is dumped into
+  <tt>orderFileName</tt>.
+
+  SideEffects [Network partition and FSM data structure are hooked to the
+  network if necessary. They are however, cleared at the end of this
+  procedure.]
+
+  SeeAlso     [Synth_InitializeInfo]
+
+******************************************************************************/
+int
+RestrCommandRestructureFsm(
+  Fsm_Fsm_t *fsm,			   
+  RestructureHeuristic heuristic,
+  char *orderFileName,
+  boolean equivClasses,
+  boolean nonReachEquiv,
+  boolean eqvMethod,
+  st_table *inputProb,
+  Synth_InfoData_t *synthInfo)
+{
+
+  graph_t *partition;
+  Ntk_Network_t *network1;
+  bdd_manager *ddManager;
+
+  array_t *outputArray, *tranFunArray;
+  array_t *outBdds, *nextBdds;
+  array_t *tranRelationPair;
+  array_t *newStateVars;
+
+  st_table *careTable;
+
+  int i;
+  int nVars, nPi;
+  int noRestruct = 0;
+  boolean status;
+
+  bdd_node *Lambda, *productTranRel, *prunedTR, *initialTR;
+  bdd_node *equivRel;
+  bdd_node *stateProbs;
+  bdd_node *finalTR = NIL(bdd_node);
+  bdd_node **xVars,**yVars,**uVars,**vVars;
+  bdd_node **piVars;
+  bdd_node *ddTemp, *reachable, *initBdd;
+  bdd_node *newInit;
+
+  mdd_t *reachStates, *mddTemp;
+  mdd_t *careMdd;
+
+  FILE *outFile;
+
+  network1 = Fsm_FsmReadNetwork(fsm);
+  ddManager = (bdd_manager *)Ntk_NetworkReadMddManager(network1);
+
+  /* Get the bdd_node for primary, present and next state variables.*/
+  piVars = RestrBddNodeArrayFromIdArray(ddManager, 
+					Fsm_FsmReadInputVars(fsm));
+  xVars = RestrBddNodeArrayFromIdArray(ddManager, 
+				       Fsm_FsmReadPresentStateVars(fsm));
+  yVars = RestrBddNodeArrayFromIdArray(ddManager,
+				       Fsm_FsmReadNextStateVars(fsm));
+  /* Create new state variables for duplicate machine. */
+  newStateVars = RestrCreateNewStateVars(network1, ddManager,xVars,yVars);
+  uVars = RestrBddNodeArrayFromIdArray(ddManager,
+				       array_fetch(array_t *, 
+						   newStateVars, 0));
+  vVars = RestrBddNodeArrayFromIdArray(ddManager,
+				       array_fetch(array_t *, 
+						   newStateVars, 1));
+
+  /* Free memory: Delete the id array for new state variables.*/
+  array_free(array_fetch(array_t *,newStateVars,0));
+  array_free(array_fetch(array_t *,newStateVars,1));
+  array_free(newStateVars);
+
+  /* outputArray is the list of primary outputs. It is my responsibility to
+  free it later. Both outputArray and tranFunArray are char * arrays.  Get the
+  BDDs for output functions and transition functions.  Duplicate functions are
+  returned.*/
+
+  /* tranFunArray should not be freed */
+  outputArray = RestrGetOutputArray(network1);
+  tranFunArray = Fsm_FsmReadNextStateFunctionNames(fsm);
+  outBdds = GetBddArrayFromNameArray(fsm,outputArray);
+  nextBdds = GetBddArrayFromNameArray(fsm,tranFunArray);
+
+  nVars = array_n(Fsm_FsmReadNextStateVars(fsm));
+  nPi = array_n(Fsm_FsmReadInputVars(fsm));
+
+  /* Compute Lambda = AND (out1 xnor out1$NTK2) and Transition relation.
+   out1$NTK2 is the corresponding primary output (of output1) in the duplicate
+   machine.*/
+  if (restrVerbose) {
+    fprintf(vis_stdout,"** restr info: Computing product output ... ");
+  }
+  Lambda = RestrCreateProductOutput(ddManager,outBdds,xVars, uVars, nVars);
+  if (restrVerbose) {
+    fprintf(vis_stdout,"Done.\n");
+  }
+
+  if (restrVerbose) {
+    fprintf(vis_stdout,"** restr info: Computing TR of product machine ... ");
+  }
+  /* Compute the transition relation for both the single FSM and the product
+     machine.  tranRelationPair[0] is the TR of single FSM and
+     tranRelationPair[1] is the TR of product machine.  
+     TR(x,w,y) = \prod_{i=0}^{i=n-1} (y_i \equiv f_i(w,x))
+     productTR(x,u,w,y,v) = TR(x,w,y) * TR(u,w,v) */
+  tranRelationPair = RestrComputeTRWithIds(ddManager,nextBdds,xVars, yVars,
+					   uVars,vVars,nVars);
+  if (restrVerbose) {
+    fprintf(vis_stdout,"Done.\n");
+  }
+
+  productTranRel = array_fetch(bdd_node *,tranRelationPair,1);
+
+  /* Compute the state equivalence relation for the FSM */
+  /* The support of equivRel is xVars and uVars. */
+  if (restrVerbose) {
+    fprintf(vis_stdout,"** restr info: Computing the equivalence relation ... ");
+  }
+
+  if (eqvMethod) {
+    equivRel = RestrComputeEquivRelationUsingCofactors(ddManager,Lambda,
+						       productTranRel,
+						       xVars, yVars, uVars,
+						       vVars, piVars,
+						       nVars, nPi,
+						       restrVerbose);
+    bdd_recursive_deref(ddManager,Lambda);
+  } else {
+    equivRel = RestrGetEquivRelation(ddManager,Lambda,productTranRel,
+				     xVars,yVars,uVars,vVars,
+				     piVars,nVars,nPi,restrVerbose);
+    bdd_recursive_deref(ddManager,Lambda);
+  }
+  if (restrVerbose) {
+    fprintf(vis_stdout,"Done.\n");
+  }
+  /* Delete the product transition relation, as we no longer need it. */
+  bdd_recursive_deref(ddManager,productTranRel);
+
+  /* Compute the initial states */
+  mddTemp = Fsm_FsmComputeInitialStates(fsm);
+  initBdd = bdd_extract_node_as_is(mddTemp);
+  bdd_ref(initBdd);
+  mdd_free(mddTemp);
+
+  /* Compute the reachable states. */
+  reachStates = Fsm_FsmComputeReachableStates(fsm,0,0,0,0,0,0,1000,
+					      Fsm_Rch_Default_c,0,0,
+					      NIL(array_t),FALSE, NIL(array_t));
+
+  reachable = bdd_extract_node_as_is(reachStates);
+  bdd_ref(reachable);
+  mdd_free(reachStates);
+
+  /* Check to see if there are any usable equivalence classes */
+  if (bdd_count_minterm(ddManager,equivRel,2*nVars) == pow(2.0,nVars)) {
+    fprintf(vis_stdout,"** restr info: Number of equivalence classes equals ");
+    fprintf(vis_stdout,"number of possible states. \n");
+    fprintf(vis_stdout,"** restr info: Restructuring will not help.\n");
+    fprintf(vis_stdout,"** restr info: Proceeding with synthesis.\n");
+    bdd_recursive_deref(ddManager,equivRel);
+    /* Do not perform restructuring */
+    noRestruct = 1;
+  }
+
+  /* Expand the reachable set R(x) to include those states which are equivalent
+   to R(x) but unreachable. */
+  if(nonReachEquiv && !noRestruct) {
+    ExpandReachableSet(ddManager,&reachable,equivRel,xVars,uVars,nVars);
+  }
+
+  if (noRestruct) {
+    /* Only synthesize the network */
+    bdd_recursive_deref(ddManager,equivRel);
+    bdd_recursive_deref(ddManager,
+			array_fetch(bdd_node *,tranRelationPair,0));
+    array_free(tranRelationPair);
+  } else {
+    /* Constrain the original TR */
+    initialTR = array_fetch(bdd_node *, tranRelationPair, 0);
+    /* bdd_ref(prunedTR = bdd_bdd_and(ddManager,initialTR,reachable)); */
+    bdd_ref(prunedTR = initialTR);
+    bdd_recursive_deref(ddManager,initialTR);
+    array_free(tranRelationPair);
+
+    finalTR = PerformRestructure(ddManager,prunedTR,equivRel,reachable,
+				   initBdd,piVars,xVars,yVars,uVars,
+				   vVars,inputProb,nVars,nPi,heuristic,
+				   equivClasses,&outBdds,&newInit,
+				   &stateProbs);
+    /* equivRel is dereferenced in the above procedure */
+    if (prunedTR == finalTR) {
+      fprintf(vis_stdout,"** restr info: Restructuring produces no changes. \n");
+      fprintf(vis_stdout,"** restr info: Proceeding with synthesis. \n");
+      bdd_recursive_deref(ddManager,stateProbs);
+      noRestruct = 1;
+    }
+
+    bdd_recursive_deref(ddManager,prunedTR);
+    bdd_recursive_deref(ddManager,initBdd);
+
+    /* reachable can be deleted after computing the new reachable states.  Also
+     need to perform markov analysis to find final bit change. */
+    initBdd = newInit;
+    if (!noRestruct) {
+      arrayForEachItem(bdd_node *, nextBdds, i, ddTemp) {
+	bdd_recursive_deref(ddManager,ddTemp);
+      }
+      array_free(nextBdds);
+      nextBdds = ExtractTransitionFuns(ddManager,finalTR,yVars,nVars);
+    }
+  }
+
+  /* Create a partition for the new view of the fsm/network */
+  if (!noRestruct) {
+    partition = CreateNewPartition(network1,ddManager,outBdds,nextBdds,
+				   outputArray,tranFunArray);
+    array_free(outBdds);
+    array_free(nextBdds);
+    /* Create the FSM and perform markov ananlysis */
+    /* finalTR, stateProbs and reachabale are deleted in CreateNewFsm */
+    fsm = CreateNewFsm(network1,partition,ddManager,finalTR,initBdd,
+		       reachable,stateProbs,xVars,yVars,piVars,
+		       inputProb,nVars,nPi);
+  } else {
+    /* Remove the outBdds, nextBdds */
+    arrayForEachItem(bdd_node *, outBdds, i, ddTemp) {
+      bdd_recursive_deref(ddManager,ddTemp);
+    }
+    arrayForEachItem(bdd_node *, nextBdds, i, ddTemp) {
+      bdd_recursive_deref(ddManager,ddTemp);
+    }
+    array_free(outBdds);
+    array_free(nextBdds);
+  }
+
+  /* First create the care table for next state and primary output
+   functions. */
+  careMdd = Fsm_FsmComputeReachableStates(fsm,0,0,0,0,0,0,1000,
+					  Fsm_Rch_Default_c,0,0,
+					  NIL(array_t),FALSE, NIL(array_t));
+
+  careTable = CreateCareTable(network1,careMdd);
+
+  /* Synthesize the restructured FSM */
+  status = Synth_SynthesizeFsm(fsm,careTable,synthInfo,0);
+
+  /* Clean up */
+  if (!noRestruct) {
+    Ntk_NetworkFreeApplInfo(network1,RESTR_PART_NETWORK_APPL_KEY);
+    Ntk_NetworkFreeApplInfo(network1,RESTR_FSM_NETWORK_APPL_KEY);
+  }
+  mdd_free(careMdd);
+  st_free_table(careTable);
+
+  /* Dump the current BDD variable order, for future use. */
+  if(orderFileName) {
+    outFile = fopen(orderFileName,"w");
+    if(outFile) {
+      int size = array_n(mdd_ret_mvar_list(ddManager));
+      int index;
+      mvar_type var;
+      for(i = 0; i < size;i++) {
+	index = bdd_get_id_from_level(ddManager,i);
+	var = mdd_get_var_by_id(ddManager,index);
+	fprintf(outFile,"%s\n",var.name);
+      }
+      fclose(outFile);
+    } else {
+      fprintf(vis_stderr,"** restr error: Cannot open %s .\n",orderFileName);
+    }
+  }
+
+  /* Clean up */
+  for(i = 0; i < nVars; i++) {
+    bdd_recursive_deref(ddManager,xVars[i]);
+    bdd_recursive_deref(ddManager,yVars[i]);
+    bdd_recursive_deref(ddManager,uVars[i]);
+    bdd_recursive_deref(ddManager,vVars[i]);
+  }
+  for(i = 0 ; i < nPi; i++) {
+    bdd_recursive_deref(ddManager,piVars[i]);
+  }
+  FREE(xVars);
+  FREE(yVars);
+  FREE(uVars);
+  FREE(vVars);
+  FREE(piVars);
+
+  array_free(outputArray);
+
+  return (status);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Returns an array of Mvfs given node names.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static array_t *
+BuildFunctions(
+  graph_t *partition,
+  array_t *rootNames)
+{
+  char *name;
+  vertex_t *vertexPtr;
+  Mvf_Function_t *mvf1;
+  int i;
+  array_t *result;
+
+  result = array_alloc(Mvf_Function_t *,0);
+  arrayForEachItem(char *,rootNames,i,name) {
+    vertexPtr = Part_PartitionFindVertexByName(partition,name);
+    mvf1 = Mvf_FunctionDuplicate(Part_VertexReadFunction(vertexPtr));
+    array_insert(Mvf_Function_t *,result,i,mvf1);
+  }
+
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Performs markovian analysis.]
+
+  Description [Returns a pair of ADDs. The ADD for steady state
+  probabilities is at index 0 and the one-step transition probability
+  is returned in index 1. bddTr is the BDD of the transition relation
+  representing the STG. init is an ADD of initial probability vector.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static bdd_node **
+AddPowerSolve(
+  bdd_manager 	*mgr,
+  bdd_node 	*bddTr,   	 
+  bdd_node 	*init, 	 
+  bdd_node 	**x,
+  bdd_node 	**y,
+  bdd_node 	**pi,
+  st_table      *inputProb,
+  int 		 nVars,
+  int		 nPi)
+{
+  bdd_node 	*temp1, *temp, *q, *Correction;
+  bdd_node        **result, *tr;
+  bdd_node        **xAddVars, **yAddVars;
+  bdd_node 	*initG, *NewG;
+  bdd_node 	*inputCube,*xCube; 
+  bdd_node	*newTr, *probMatrix;
+  int 	  	iter = 0;
+  int 		i;
+  double        max,relTol = 0.0001;
+  
+  /* Initialize variables */
+  result = ALLOC(bdd_node *, 2);
+  xAddVars = ALLOC(bdd_node *, nVars);
+  yAddVars = ALLOC(bdd_node *, nVars);
+  for (i = 0; i < nVars; i++) {
+    bdd_ref(xAddVars[i] = bdd_add_ith_var(mgr, bdd_node_read_index(x[i])));
+    bdd_ref(yAddVars[i] = bdd_add_ith_var(mgr, bdd_node_read_index(y[i])));
+  }
+  bdd_ref(tr = bdd_bdd_to_add(mgr, bddTr));
+  
+  /* Create the input cube for abstraction */
+  bdd_ref(temp1 = bdd_bdd_compute_cube(mgr, pi, NIL(int), nPi));
+  bdd_ref(inputCube = bdd_bdd_to_add(mgr, temp1));
+  bdd_recursive_deref(mgr, temp1);
+
+  /* Compute the one-step transition probability matrix. */
+  if (inputProb) {
+    bdd_ref(probMatrix = Mark_addInProb(mgr,tr,inputCube,inputProb));
+    bdd_recursive_deref(mgr,inputCube);
+    bdd_recursive_deref(mgr,tr);
+  }
+  else {
+    bdd_ref(Correction = bdd_add_const(mgr,(1.0/(double)(1 << nPi))));
+    bdd_ref(q = bdd_add_exist_abstract(mgr,tr,inputCube));
+    bdd_recursive_deref(mgr,inputCube);
+    bdd_recursive_deref(mgr,tr);
+    /* apply correction to the transition relation matrix and print it */
+    bdd_ref(probMatrix = bdd_add_apply(mgr, bdd_add_times, q, Correction));
+    bdd_recursive_deref(mgr,Correction);
+    bdd_recursive_deref(mgr,q);
+  }
+  result[1] = probMatrix;
+
+  /* Prepare the initial prob. vector. and the transition prob. matrix. */
+  initG = bdd_add_swap_variables(mgr,init,xAddVars,yAddVars,nVars);
+  bdd_ref(initG);
+  /* Put transition prob. matrix in appropriate form (transpose). */
+  newTr = bdd_add_swap_variables(mgr,probMatrix,xAddVars,yAddVars,nVars);
+  bdd_ref(newTr);
+
+  /* Calculate the x-cube for abstraction */
+  bdd_ref(xCube = bdd_add_compute_cube(mgr,xAddVars,NIL(int),nVars));
+
+  /* Loop until convergence */
+  do {
+    iter++;
+    bdd_ref(temp = bdd_add_matrix_multiply(mgr,newTr,initG,yAddVars,nVars));
+    bdd_ref(temp1 = bdd_add_exist_abstract(mgr,temp,xCube));
+    bdd_ref(NewG = bdd_add_apply(mgr,bdd_add_divide,temp,temp1));
+    bdd_recursive_deref(mgr,temp);
+    bdd_recursive_deref(mgr,temp1);
+    temp = NewG; 
+    bdd_ref(q = bdd_add_swap_variables(mgr,temp,xAddVars,yAddVars,nVars));
+    max = bdd_add_value(bdd_add_find_max(mgr,initG));
+
+    if(bdd_equal_sup_norm(mgr,q,initG,relTol*max,0)) {
+      bdd_recursive_deref(mgr,initG);
+      bdd_recursive_deref(mgr,q);
+      bdd_recursive_deref(mgr,xCube);
+      bdd_recursive_deref(mgr,newTr);
+
+      bdd_ref(temp1 = bdd_add_apply(mgr,bdd_add_times,probMatrix,temp));
+      if (restrVerbose) {
+	fprintf(vis_stdout,"** restr info: Average state bit change = %f\n",
+		RestrAverageBitChange(mgr,temp1,x,y,nVars));
+      }
+      
+      bdd_recursive_deref(mgr,temp1);
+      for(i = 0;i < nVars; i++) {
+        bdd_recursive_deref(mgr,xAddVars[i]);
+        bdd_recursive_deref(mgr,yAddVars[i]);
+      }
+      FREE(xAddVars);
+      FREE(yAddVars);
+      result[0] = temp;
+      return result;
+    }
+    bdd_recursive_deref(mgr,initG);
+    bdd_recursive_deref(mgr,temp);
+    initG = q;
+
+  } while (1);
+
+} /* end of AddPowerSolve */
+
+/**Function********************************************************************
+
+  Synopsis [This routine performs the preprocessing steps of markovian analysis
+  and the augmented STG computation. After the preprocessing steps the core
+  restructuring steps are performed. Returns the BDD of the restructured STG.]
+
+  SideEffects [<tt>outBdds</tt>, <tt>newInit</tt> are changed to
+  reflect the restructured finite state machine. Steady state
+  probabilities are returned in <tt>stateProbs</tt>]
+
+  SeeAlso     []
+
+******************************************************************************/
+static bdd_node *
+PerformRestructure(
+  bdd_manager *ddManager,
+  bdd_node *prunedTR,
+  bdd_node *equivRel,
+  bdd_node *reachable,
+  bdd_node *initBdd,
+  bdd_node **piVars,
+  bdd_node **xVars,
+  bdd_node **yVars,
+  bdd_node **uVars,
+  bdd_node **vVars,
+  st_table *inputProb,
+  int nVars,
+  int nPi,
+  RestructureHeuristic heuristic,
+  boolean equivClasses,
+  array_t **outBdds,
+  bdd_node **newInit,
+  bdd_node **stateProbs)
+{
+  /* equivRel is a function of uVars and xVars */
+  /* prunedTR is a funciton of xVars, piVars and yVars */
+
+  bdd_node *possessedProbMatrix;
+  bdd_node *possessedTR = NIL(bdd_node);
+  bdd_node *addPTR;
+  bdd_node *finalTR;
+  bdd_node *ddTemp;
+  bdd_node *localStateProbs = NIL(bdd_node);
+
+  if(equivClasses) {
+    CountEquivalentClasses(ddManager,equivRel,initBdd,xVars,uVars,nVars);
+  }
+
+  /* Change the support of equivRel */
+  bdd_ref(ddTemp = bdd_bdd_swap_variables(ddManager,equivRel,xVars,yVars,
+					  nVars));
+  bdd_recursive_deref(ddManager,equivRel);
+  bdd_ref(equivRel = bdd_bdd_swap_variables(ddManager,ddTemp,uVars,vVars,
+					    nVars));
+  bdd_recursive_deref(ddManager, ddTemp);
+
+  /* The support of possessedTR is xVars and yVars and inputs.
+   * If there exists an edge between x and y, and y == v, then
+   * the following function adds an edge between x and v. These new
+   * edges are referred to as ghost edges.
+   */
+  
+  if (heuristic != RestrCProjection_c) {
+    possessedTR = RestrComputeTrWithGhostEdges(ddManager, yVars, vVars, 
+					       prunedTR, equivRel, nVars);
+  }
+
+  /* stateProbs will not be used in the case of CProj and hammingD methods.  We
+   can still compute the stateProbs to find the initial average bit change on
+   the state lines. */
+  *stateProbs = DoMarkovPowerAnalysis(ddManager,prunedTR,
+				      initBdd,piVars,xVars, 
+				      yVars,inputProb,nVars,nPi);
+    
+  if (!(heuristic == RestrCProjection_c || heuristic == RestrHammingD_c)) {
+    bdd_node *temp, *cube;
+
+    bdd_ref(cube = bdd_bdd_compute_cube(ddManager,piVars,NIL(int),nPi));
+    bdd_ref(temp = bdd_bdd_exist_abstract(ddManager,possessedTR,cube));
+    bdd_ref(addPTR = bdd_bdd_to_add(ddManager,temp));
+    bdd_recursive_deref(ddManager,temp);
+
+    bdd_ref(temp = bdd_bdd_to_add(ddManager, possessedTR));
+    bdd_recursive_deref(ddManager, possessedTR);
+
+    /* possessedProbMatrix is a weighted augmented STG where the weights are
+       the transition probabilities */
+    if (inputProb) {
+      bdd_ref(possessedProbMatrix = Mark_addInProb(ddManager,temp,cube,
+						   inputProb));
+    } else {
+      /* Assume equi probable primary inputs */
+      bdd_node *q, *Correction;
+      bdd_node *inputCube;
+
+      bdd_ref(inputCube = bdd_bdd_to_add(ddManager,cube));
+      bdd_ref(Correction = bdd_add_const(ddManager,
+					 (1.0/(double)(1 << nPi))));
+      bdd_ref(q = bdd_add_exist_abstract(ddManager,temp,inputCube));
+      bdd_ref(possessedProbMatrix = bdd_add_apply(ddManager,
+						  bdd_add_times,
+						  q, Correction));
+      bdd_recursive_deref(ddManager,Correction);
+      bdd_recursive_deref(ddManager,q);
+      bdd_recursive_deref(ddManager,inputCube);
+    }
+    bdd_recursive_deref(ddManager,cube);
+    bdd_recursive_deref(ddManager,temp);
+    localStateProbs = *stateProbs;
+  }
+
+  switch(heuristic) {
+  case RestrCProjection_c:
+    finalTR = RestrMinimizeFsmByCProj(ddManager,equivRel,
+				      prunedTR,initBdd,
+				      xVars,yVars,uVars,vVars,piVars,
+				      nVars,nPi,outBdds,newInit);
+    break;
+  case RestrFanin_c:
+  case RestrFaninFanout_c:
+    ddTemp = bdd_read_background(ddManager);
+    bdd_set_background(ddManager, 
+		       bdd_read_plus_infinity(ddManager));
+
+    /* addPTR and possessedProbMatrix are deleted in the following 
+     * procedure. */
+    finalTR = RestrMinimizeFsmByFaninFanout(ddManager,equivRel, prunedTR, 
+					    &addPTR,&possessedProbMatrix,initBdd,
+					    reachable,localStateProbs,piVars,xVars,
+					    yVars, uVars,vVars,
+					    nVars, nPi,heuristic,outBdds,newInit);
+
+    /* Replace the original background value */
+    bdd_set_background(ddManager,ddTemp);
+    break; 
+  case RestrHammingD_c: 
+  default : 
+    
+    /* BALA, testing ... */
+    /* Remove the edges out of the initial state. */
+    {
+/*       bdd_node *outEdges; */
+
+/*       bdd_ref(outEdges = bdd_bdd_and(ddManager,prunedTR,initBdd)); */
+/*       bdd_ref(adjustedTR = bdd_bdd_and(ddManager,prunedTR, */
+/* 				       bdd_not_bdd_node(outEdges))); */
+/*       finalTR = RestrSelectLeastHammingDStates(ddManager,adjustedTR, */
+/* 					       possessedTR,xVars, */
+/* 					       yVars,vVars,nVars,nPi); */
+      
+      finalTR = RestrSelectLeastHammingDStates(ddManager,prunedTR,
+					       possessedTR,xVars,
+					       yVars,vVars,nVars,nPi);
+      bdd_recursive_deref(ddManager,possessedTR);
+      bdd_ref(*newInit = initBdd);
+      break;
+    }
+  }
+
+  bdd_recursive_deref(ddManager,equivRel);
+  return finalTR;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Returns a table of (rootNames,rootMvfs). The parameters
+  <tt>outBdds</tt> and <tt>nextBdds</tt> aare arrays of bdd_node *.
+  <tt>outputArray</tt> and <tt>tranFunArray</tt> are arrays of strings and are
+  in one-to-one correspondence with <tt>outBdds</tt> and <tt>nextBdds</tt>.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static st_table *
+CreateNameToMvfTable(
+  bdd_manager *ddManager,		   
+  array_t *outBdds,
+  array_t *nextBdds,
+  array_t *outputArray,
+  array_t *tranFunArray)
+{
+  st_table *nameToMvf;
+  bdd_node *ddTemp;
+  int i;
+
+  /* Initialize variables */
+  nameToMvf = st_init_table(strcmp, st_strhash);
+
+  arrayForEachItem(bdd_node *, outBdds, i, ddTemp) {
+    bdd_node *temp;
+    mdd_t *regular, *complement;
+    Mvf_Function_t *mvf;
+    char *name;
+
+    bdd_ref(temp = bdd_not_bdd_node(ddTemp));
+
+    regular = bdd_construct_bdd_t(ddManager,ddTemp);
+    complement = bdd_construct_bdd_t(ddManager,temp);
+
+    mvf = (Mvf_Function_t *)array_alloc(mdd_t *, 0);
+    array_insert(mdd_t *, mvf, 0, complement);
+    array_insert(mdd_t *, mvf, 1, regular);
+
+    name = array_fetch(char *, outputArray, i);
+    st_insert(nameToMvf,name,(char *)mvf);
+  }
+
+  arrayForEachItem(bdd_node *, nextBdds, i, ddTemp) {
+    bdd_node *temp;
+    mdd_t *regular, *complement;
+    Mvf_Function_t *mvf;
+    char *name;
+
+    bdd_ref(temp = bdd_not_bdd_node(ddTemp));
+
+    regular = bdd_construct_bdd_t(ddManager,ddTemp);
+    complement = bdd_construct_bdd_t(ddManager,temp);
+
+    mvf = (Mvf_Function_t *)array_alloc(mdd_t *, 0);
+    array_insert(mdd_t *, mvf, 0, complement);
+    array_insert(mdd_t *, mvf, 1, regular);
+
+    name = array_fetch(char *, tranFunArray, i);
+    st_insert(nameToMvf,name,(char *)mvf);
+  }
+
+  return nameToMvf;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Create a (name,mdd_t*) table.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static st_table *
+CreateCareTable(
+  Ntk_Network_t *network,
+  mdd_t *reachMdd)
+{
+  lsGen gen;
+  Ntk_Node_t *node;
+  st_table *careTable;
+
+  careTable = st_init_table(strcmp, st_strhash);
+  Ntk_NetworkForEachPrimaryOutput(network, gen, node) {
+    char *name;
+    name = Ntk_NodeReadName(node);
+    st_insert(careTable,name,(char *)reachMdd);
+  }
+  Ntk_NetworkForEachLatch(network,gen,node){
+    char *name;
+    name = Ntk_NodeReadName(Ntk_LatchReadDataInput(node));
+    st_insert(careTable,name,(char *)reachMdd);
+  }
+
+  return careTable;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Routine to free members of an st_table.]
+
+  SideEffects [None]
+
+  SeeAlso []
+******************************************************************************/
+static enum st_retval
+StMvfFree(
+  char *key,
+  char *value,
+  char *arg)
+{
+  /* This will free the memory associated with the array also */
+  Mvf_FunctionFree((Mvf_Function_t *)value);
+  
+  return(ST_CONTINUE);
+  
+} /* end of StMvfFree */
+
+
+/**Function********************************************************************
+
+  Synopsis [Routine to count number of equivalence classes in a relation.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+CountEquivalentClasses(
+  bdd_manager *ddManager,
+  bdd_node *equivRel,
+  bdd_node *initBdd,
+  bdd_node **xVars,
+  bdd_node **uVars,
+  int nVars)
+{
+  bdd_node *resultXU,*uCube;
+  bdd_node *oneInitState,*classes;
+
+  oneInitState = bdd_bdd_pick_one_minterm(ddManager,initBdd,xVars,nVars);
+  bdd_ref(oneInitState);
+
+  bdd_ref(resultXU = bdd_bdd_cprojection(ddManager,equivRel,oneInitState));
+  bdd_recursive_deref(ddManager,oneInitState);
+
+#ifdef RESTR_DIAG
+  {
+    /* The following is valid only when equivRel is the equivalence relation on
+       the complete set of states.*/
+    bdd_node *xCube,*tautology;
+    bdd_node *one;
+    one = bdd_read_one(ddManager);
+    bdd_ref(xCube = bdd_bdd_compute_cube(ddManager,xVars,NIL(int),nVars));
+    bdd_ref(tautology = bdd_bdd_exist_abstract(ddManager,resultXU,xCube));
+    assert(tautology == one);
+    bdd_recursive_deref(ddManager,tautology);
+    bdd_recursive_deref(ddManager,xCube);
+  }
+#endif
+
+#ifdef RESTR_DIAG
+  {
+    bdd_node *uCube,*zero,*classes;
+    bdd_node *oneClass,*temp,*rep;
+    int i;
+
+    zero = bdd_not_bdd_node(bdd_read_one(ddManager));
+    /* Extract the classes */
+    bdd_ref(uCube = bdd_bdd_compute_cube(ddManager,uVars,NIL(int),nVars));
+    bdd_ref(classes = bdd_bdd_exist_abstract(ddManager,resultXU,uCube));
+    bdd_recursive_deref(ddManager,uCube);
+    
+    i = 0;
+    (void) fprintf(vis_stdout,"\n** restr diag: EQUIVALENT CLASSES:\n");
+    while (classes != zero) {
+      i++;
+      bdd_ref(rep = bdd_bdd_pick_one_minterm(ddManager,classes,
+					     xVars,nVars));
+      (void) fprintf(vis_stdout,"** restr diag: Class %d\n",i);
+      (void) fprintf(vis_stdout,"** restr diag: Class representative:\n");
+      RestrPrintBddNode(ddManager,rep);
+
+      /* Extract the complete class now */
+      bdd_ref(temp = bdd_bdd_cofactor(ddManager,resultXU,rep));
+      bdd_ref(oneClass = bdd_bdd_swap_variables(ddManager,temp,uVars,
+						xVars,nVars));
+      bdd_recursive_deref(ddManager,temp);
+      (void) fprintf(vis_stdout,"** restr diag: Class members:\n");
+      RestrPrintBddNode(ddManager,oneClass);
+      bdd_recursive_deref(ddManager,oneClass);
+
+      /* Remove rep from classes */
+      bdd_ref(temp = bdd_bdd_and(ddManager,classes,bdd_not_bdd_node(rep)));
+      bdd_recursive_deref(ddManager,rep);
+      bdd_recursive_deref(ddManager,classes);
+      classes = temp;
+    }
+    (void) fprintf(vis_stdout,"** restr diag: Number of classes = %d\n",i);
+  }
+#endif
+
+  /* Compute uCube and extract the u variables from resultXU */
+  bdd_ref(uCube = bdd_bdd_compute_cube(ddManager,uVars,NIL(int),nVars));
+  bdd_ref(classes = bdd_bdd_exist_abstract(ddManager,resultXU,uCube));
+  bdd_recursive_deref(ddManager,uCube);
+  bdd_recursive_deref(ddManager,resultXU);
+
+  fprintf(vis_stdout, "** restr info: Number of Equivalence Classes = %g\n",
+	  bdd_count_minterm(ddManager,classes,nVars));
+  
+  bdd_recursive_deref(ddManager,classes);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Convert an array of Mvf_Function_t * to an array of bdd_node *]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static array_t *
+GetBddArrayFromMvfArray(array_t *mvfArray)
+{
+  int 	  i;
+  array_t *bddArray;
+  Mvf_Function_t *mvf;
+
+  bddArray = array_alloc(bdd_node *,0);
+
+  arrayForEachItem(Mvf_Function_t *, mvfArray,i,mvf) {
+    mdd_t     *mddTemp;
+    bdd_node    *ddNode;
+
+    mddTemp = array_fetch(mdd_t *, mvf, 1);
+    ddNode = bdd_extract_node_as_is(mddTemp);
+    bdd_ref(ddNode);
+
+    array_insert_last(bdd_node *, bddArray, ddNode);
+  }
+  return bddArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Perform markovian analysis. The ADD for steady state probabilities
+  of the STG is returned.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static bdd_node *
+DoMarkovPowerAnalysis(
+  bdd_manager *ddManager,
+  bdd_node *prunedTR,
+  bdd_node *initBdd,
+  bdd_node **piVars,
+  bdd_node **xVars,
+  bdd_node **yVars,
+  st_table *inputProb,
+  int nVars,
+  int nPi)
+{
+  bdd_node **result, *stateProbs;
+  bdd_node *init;
+  
+  bdd_ref(init = bdd_bdd_to_add(ddManager,initBdd));
+  if (restrVerbose) 
+    (void) fprintf(vis_stdout,"** restr info: Initial average state bit change:\n");
+
+  result = AddPowerSolve(ddManager,prunedTR,init,xVars,yVars,
+			      piVars,inputProb,nVars,nPi);
+  
+  bdd_recursive_deref(ddManager,result[1]);
+  stateProbs = result[0];
+  bdd_recursive_deref(ddManager,init);
+  FREE(result);
+  
+  return stateProbs;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Given a relation R(X,Y) returns the array of functions y_i=f(X).]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static array_t *
+ExtractTransitionFuns(
+  bdd_manager	*ddManager,
+  bdd_node	*finalTR,
+  bdd_node	**yVars,
+  int		nVars)
+{
+  bdd_node	*completeCube, *extractCube;
+  bdd_node	*fun, *tranFun;
+  array_t	*allTranFuns;
+  int		i;
+
+  allTranFuns = array_alloc(bdd_node *,0);
+
+  completeCube = bdd_bdd_compute_cube(ddManager,yVars,NIL(int),nVars);
+  bdd_ref(completeCube);
+
+  for(i = 0;i < nVars; i++) {
+    extractCube = bdd_bdd_cofactor(ddManager,completeCube,yVars[i]);
+    bdd_ref(extractCube);
+    fun = bdd_bdd_exist_abstract(ddManager,finalTR,extractCube);
+    bdd_ref(fun);
+    bdd_recursive_deref(ddManager,extractCube);
+    tranFun = bdd_bdd_cofactor(ddManager,fun,yVars[i]);
+    bdd_ref(tranFun);
+
+#ifdef RESTR_DIAG
+    {
+      /* The following is to test if there are multiple edges out of a state
+         with the same input label: in short to check if the relation is
+         deterministic or not. */
+
+      bdd_node *yBar,*yNot,*inter;
+      bdd_ref(yNot = bdd_not_bdd_node(yVars[i]));
+      bdd_ref(yBar = bdd_bdd_cofactor(ddManager,fun,yNot));
+      bdd_recursive_deref(ddManager,yNot);
+      bdd_ref(inter = bdd_bdd_and(ddManager,yBar,tranFun));
+      yNot = bdd_not_bdd_node(bdd_read_one(ddManager));
+      assert(inter == yNot);
+      bdd_recursive_deref(ddManager,inter);
+      bdd_recursive_deref(ddManager,yBar);
+    }
+#endif
+
+    bdd_recursive_deref(ddManager,fun);
+    array_insert_last(bdd_node *,allTranFuns,tranFun);
+  }
+
+  bdd_recursive_deref(ddManager,completeCube);
+  return allTranFuns;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Returns an array of BDDs given the node names of a network.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+static array_t *
+GetBddArrayFromNameArray(
+  Fsm_Fsm_t *fsm,
+  array_t *nameArray)
+{
+  graph_t *partition;
+  array_t *bdds,*mvfs;
+  
+  partition = Fsm_FsmReadPartition(fsm);
+  mvfs = BuildFunctions(partition,nameArray);
+  bdds = GetBddArrayFromMvfArray(mvfs);
+  Mvf_FunctionArrayFree(mvfs);
+
+  return bdds;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Expand the reachable set R(x) to include those states which are
+  equivalent to R(x) but potentially not reachable.]
+
+  SideEffects [<tt>reachable</tt> is updated.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+ExpandReachableSet(
+  bdd_manager *ddManager,
+  bdd_node **reachable,
+  bdd_node *equivRel,
+  bdd_node **xVars,
+  bdd_node **uVars,
+  int nVars)
+{
+  bdd_node *xcube,*potUnReach,*extReach;
+  bdd_node *temp1;
+
+  bdd_ref(xcube = bdd_bdd_compute_cube(ddManager,xVars,NIL(int),nVars));
+  /* potUnReach = \exists_x (E(x,u) * R(x)) */
+  bdd_ref(potUnReach = bdd_bdd_and_abstract(ddManager,*reachable,
+					    equivRel,xcube));
+  bdd_recursive_deref(ddManager,xcube);
+  /* temp1(x) = potUnReach(u) */
+  bdd_ref(temp1 = bdd_bdd_swap_variables(ddManager,potUnReach,uVars,
+					 xVars,nVars));
+  bdd_recursive_deref(ddManager,potUnReach);
+  /* extReach(x) = R(x) + potUnReach(x) */
+  bdd_ref(extReach = bdd_bdd_or(ddManager,*reachable,temp1));
+  bdd_recursive_deref(ddManager,temp1);
+  bdd_recursive_deref(ddManager,*reachable);
+  *reachable = extReach;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Create a partition for the new view of the fsm/network]
+
+  SideEffects [The new view is attached to the network.]
+
+  SeeAlso     [CreateNewFsm]
+
+******************************************************************************/
+static graph_t *
+CreateNewPartition(
+  Ntk_Network_t *network,		   
+  bdd_manager *ddManager,
+  array_t *outBdds,
+  array_t *nextBdds,
+  array_t *outputArray,
+  array_t *tranFunArray)
+{
+  st_table *nameToMvf;
+  graph_t *partition;
+
+  /* Create a table of next state and output Mvfs with their names as key to
+     the table. This table is used to create a partition for the network. */
+  nameToMvf = CreateNameToMvfTable(ddManager,outBdds,nextBdds,
+				   outputArray,tranFunArray);
+  /* Delete the old partition and old fsm as we dont need it any more */
+  if (restrCreatedPart) {
+    Ntk_NetworkFreeApplInfo(network,RESTR_PART_NETWORK_APPL_KEY);
+    restrCreatedPart = 0;
+  }
+  if (restrCreatedFsm) {
+    Ntk_NetworkFreeApplInfo(network,RESTR_FSM_NETWORK_APPL_KEY);
+    restrCreatedFsm = 0;
+  }
+
+  /* Create a new partition from the new root functions */
+  partition = Part_NetworkCreatePartitionFromMvfs(network,nameToMvf);
+  Ntk_NetworkAddApplInfo(network, RESTR_PART_NETWORK_APPL_KEY,
+			 (Ntk_ApplInfoFreeFn) Part_PartitionFreeCallback,
+			 (void *) partition);
+  st_foreach(nameToMvf,StMvfFree,NIL(char));
+  st_free_table(nameToMvf);
+
+  return partition;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Create the FSM data structure for the restructured STG and perform
+  markov analysis to estimate the final state average bit change.]
+
+  SideEffects [<tt>reachable,initBdd,stateProbs,finalTR</tt> are dereferenced in this
+  function.]
+
+  SeeAlso     [CreateNewPatition]
+
+******************************************************************************/
+static Fsm_Fsm_t *
+CreateNewFsm(
+  Ntk_Network_t *network,
+  graph_t *partition,
+  bdd_manager *ddManager,
+  bdd_node *finalTR,
+  bdd_node *initBdd,
+  bdd_node *reachable,
+  bdd_node *stateProbs,
+  bdd_node **xVars,
+  bdd_node **yVars,
+  bdd_node **piVars,
+  st_table *inputProb,
+  int nVars,
+  int nPi)
+{
+  Fsm_Fsm_t *fsm;
+  mdd_t *reachStates;
+  mdd_t *mddTemp;
+  bdd_node *ddTemp;
+  bdd_node **markovResult;
+
+  /* Create a new Fsm for the restructured network. */
+  fsm = Fsm_FsmCreateFromNetworkWithPartition(network,
+					      Part_PartitionDuplicate(partition));
+  assert(fsm != NIL(Fsm_Fsm_t));
+  Ntk_NetworkAddApplInfo(network, RESTR_FSM_NETWORK_APPL_KEY,
+			 (Ntk_ApplInfoFreeFn) Fsm_FsmFreeCallback,
+			 (void *) fsm);	
+  /* We need to update the initial states as the
+     Fsm_FsmCreateFromNetworkWithPartition will pick up old initial state from
+     the network. Fsm_FsmSetInitialStates deletes old inital states. */
+  mddTemp = bdd_construct_bdd_t(ddManager,initBdd);
+  Fsm_FsmSetInitialStates(fsm,mddTemp);
+
+  /* Compute the new reachable states */
+  reachStates = Fsm_FsmComputeReachableStates(fsm,0,0,0,0,0,0,1000,
+					      Fsm_Rch_Default_c,0,0,
+					      NIL(array_t),FALSE, NIL(array_t));
+
+  bdd_recursive_deref(ddManager,reachable);
+  reachable = bdd_extract_node_as_is(reachStates);
+  bdd_ref(reachable);
+  mdd_free(reachStates);
+	
+  /* Constrain the transition relation */
+  bdd_ref(ddTemp = bdd_bdd_constrain(ddManager,finalTR,reachable));
+  bdd_recursive_deref(ddManager,finalTR);
+  finalTR = ddTemp;
+
+  /* Use the state probs. of the original STG as the initial guess to compute
+     the state probs. of the restructured STG. */
+  if (restrVerbose)
+    (void) fprintf(vis_stdout,"** restr info: Final average state bit change:\n");
+
+  markovResult = AddPowerSolve(ddManager, finalTR, stateProbs, xVars,
+				    yVars,piVars,inputProb,nVars,nPi);
+  bdd_recursive_deref(ddManager, markovResult[0]);
+  bdd_recursive_deref(ddManager, markovResult[1]);
+  FREE(markovResult);
+	
+  bdd_recursive_deref(ddManager,stateProbs);
+  bdd_recursive_deref(ddManager,finalTR);
+  bdd_recursive_deref(ddManager,reachable);
+
+  return fsm;
+}
Index: vis_dev/vis-2.3/src/restr/restrUtil.c
===================================================================
--- vis_dev/vis-2.3/src/restr/restrUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/restr/restrUtil.c	(revision 14)
@@ -0,0 +1,813 @@
+/**CFile***********************************************************************
+
+ FileName    [restrUtil.c]
+
+ PackageName [restr]
+
+ Synopsis    [Support functions used in the package.]
+
+ Description [Support functions used in the package.]
+
+ SeeAlso     [restrDebug.c]
+
+ Author      [Balakrishna Kumthekar <kumtheka@colorado.edu>]
+
+ Copyright [This file was created at the University of Colorado at
+ Boulder.  The University of Colorado at Boulder makes no warranty
+ about the suitability of this software for any purpose.  It is
+ presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "restrInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Returns the primary output node array for the given network.]
+
+  Description [Returns the primary output node array for the given network.]
+
+  SideEffects [None]
+
+  SeeAlso     [RestrGetNextStateArray]
+
+******************************************************************************/
+array_t *
+RestrGetOutputArray(Ntk_Network_t *network)
+{
+    lsGen		 gen;
+    Ntk_Node_t	*node;
+    array_t	*outputArray;
+
+    outputArray = array_alloc(char *, 0);
+    Ntk_NetworkForEachPrimaryOutput(network, gen, node) {
+	array_insert_last(char *, outputArray, Ntk_NodeReadName(node));
+    }
+
+    return outputArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Computes the product 
+  \prod_{i=0}^{i=n-1} funArray_{i}(x) \equiv funArray_{i}(y)]
+
+  Description [Computes the product 
+  \prod_{i=0}^{i=n-1} funArray_{i}(x) \equiv funArray_{i}(y).
+  
+  funArray is an array of BDDs and each has xVars in its
+  support. nVars is the number of xVars and yVars.]
+
+  SideEffects [None]
+
+  SeeAlso     [RestrComputeTRWithIds]
+
+******************************************************************************/
+bdd_node *
+RestrCreateProductOutput(
+  bdd_manager	*ddManager,
+  array_t	*funArray,
+  bdd_node	**xVars,
+  bdd_node	**yVars,
+  int		nVars)
+{
+  bdd_node	*ddtemp, *ddtemp1;
+  bdd_node	*fn, *result;
+  int 		i, num = array_n(funArray);
+
+  bdd_ref(result = bdd_read_one(ddManager));
+
+  for(i = 0; i < num; i++) {
+
+    ddtemp = array_fetch(bdd_node *, funArray, i);;
+
+    ddtemp1 = bdd_bdd_swap_variables(ddManager,ddtemp,xVars,yVars,nVars);
+    bdd_ref(ddtemp1);
+    fn = bdd_bdd_xnor(ddManager,ddtemp1,ddtemp);
+    bdd_ref(fn);
+    bdd_recursive_deref(ddManager,ddtemp1);
+    ddtemp1 = bdd_bdd_and(ddManager,result,fn);
+    bdd_ref(ddtemp1);
+    bdd_recursive_deref(ddManager,fn);
+    bdd_recursive_deref(ddManager,result);
+    result = ddtemp1;
+  }
+
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis [The function computes the following relations:
+  \prod_{i=0}^{i=n-1} (y_i \equiv f_i(x)) and 
+  \prod_{i=0}^{i=n-1} (y_i \equiv f_i(x)) \wedge (v_i \equiv f_i(u)) and 
+  returns them in an array.]
+
+  Description [The function computes the following relations:
+  \prod_{i=0}^{i=n-1} (y_i \equiv f_i(x)) and 
+  \prod_{i=0}^{i=n-1} (y_i \equiv f_i(x)) \wedge (v_i \equiv f_i(u)) and 
+  returns them in an array.
+  
+  nextBdds is an array of nVar BDDs and has xVars in its
+  support. xVars, yVars, uVars and vVars are arrays of BDD variables.]
+
+  SideEffects [None]
+
+  SeeAlso     [RestrCreateProductOutput]
+
+******************************************************************************/
+array_t *
+RestrComputeTRWithIds(
+  bdd_manager	*ddManager,
+  array_t	*nextBdds,
+  bdd_node	**xVars,
+  bdd_node	**yVars,
+  bdd_node	**uVars,
+  bdd_node	**vVars,
+  int		nVars)
+{
+  bdd_node	*ddtemp1, *ddtemp2;
+  bdd_node	*oldTR, *fn;
+  array_t 	*composite;
+  int 		 i;
+
+
+  /* First compute oldTR(x,y) = \prod_{i=0}^{i=n-1} (y_i \equiv f_i(x)) */
+  bdd_ref(oldTR = bdd_read_one(ddManager));
+
+  for(i = 0; i < nVars; i++) {
+    ddtemp2  = array_fetch(bdd_node *, nextBdds, i);
+
+    fn = bdd_bdd_xnor(ddManager,ddtemp2,yVars[i]);
+    bdd_ref(fn);
+    ddtemp1 = bdd_bdd_and(ddManager,oldTR,fn);
+    bdd_ref(ddtemp1);
+    bdd_recursive_deref(ddManager,fn);
+    bdd_recursive_deref(ddManager,oldTR);
+    oldTR = ddtemp1;
+  }
+  
+  /* fn(u,v) = oldTR(x-->u,y-->v) */
+  ddtemp2 = bdd_bdd_swap_variables(ddManager,oldTR,xVars,uVars,nVars);
+  bdd_ref(ddtemp2);
+  fn = bdd_bdd_swap_variables(ddManager,ddtemp2,yVars,vVars,nVars);
+  bdd_ref(fn);
+  bdd_recursive_deref(ddManager,ddtemp2);
+  ddtemp1 = bdd_bdd_and(ddManager,fn,oldTR);
+  bdd_ref(ddtemp1);
+  bdd_recursive_deref(ddManager,fn);
+
+  /* Return both the relations */
+  composite = array_alloc(bdd_node *,0);
+  array_insert_last(bdd_node *,composite,oldTR);
+  array_insert_last(bdd_node *,composite,ddtemp1);
+
+  return composite;
+}
+
+/**Function********************************************************************
+
+  Synopsis [This function returns the state equivalence relation for an FSM.]
+
+  Description [This function returns the state equivalence relation
+  for an FSM. Lambda is the primary output relation and TR is the
+  state transition relation of the product machine. Lambda has xVars,
+  uVars and piVars in its support. TR has piVars, xVars,yVars,uVars
+  and vVars in its support. nPi is the number of piVars and nVars is
+  the number of xVars. xVars, yVars, uVars and vVars are all of the
+  same size, i.e., nVars. The returned BDD is a function of xVars and
+  uVars.
+
+  For more information on the algorithm, please refer to "Dont care
+  minimization of multi-level sequential logic networks", ICCAD 90.]
+
+  SideEffects [None]
+
+  SeeAlso     [RestrComputeEquivRelationUsingCofactors]
+
+******************************************************************************/
+bdd_node *
+RestrGetEquivRelation(
+  bdd_manager   	*mgr,
+  bdd_node        *Lambda,
+  bdd_node        *tranRelation,
+  bdd_node	**xVars,
+  bdd_node	**yVars,
+  bdd_node	**uVars,
+  bdd_node	**vVars,
+  bdd_node	**piVars,
+  int		  nVars,
+  int		  nPi,
+  boolean restrVerbose)
+
+{
+    bdd_node *initialEsp, *espK;
+    bdd_node *espKPlusOne;
+    bdd_node *inputCube, *nextCube;
+    bdd_node **allPreVars, **allNexVars;
+    bdd_node *temp;
+    int i,depth;
+
+    allPreVars = ALLOC(bdd_node *, 2*nVars);
+    allNexVars = ALLOC(bdd_node *, 2*nVars);
+    for(i = 0; i < nVars;i++) {
+	allPreVars[i] = xVars[i];
+	allNexVars[i] = yVars[i];
+    } 
+    for(i = 0; i < nVars;i++) {
+	allPreVars[i+nVars] = uVars[i];
+	allNexVars[i+nVars] = vVars[i];
+    } 
+
+    nextCube = bdd_bdd_compute_cube(mgr,allNexVars,NIL(int),2*nVars);
+    bdd_ref(nextCube);
+
+    inputCube = bdd_bdd_compute_cube(mgr,piVars,NIL(int),nPi);
+    bdd_ref(inputCube);
+
+    initialEsp = bdd_bdd_univ_abstract(mgr,Lambda,inputCube);
+    bdd_ref(initialEsp);
+
+    espK = bdd_bdd_swap_variables(mgr,initialEsp,allPreVars,
+				 allNexVars,2*nVars);
+    bdd_ref(espK);
+    
+    depth = 0;
+    do {
+	bdd_node *image, *temp1;
+	image = bdd_bdd_and_abstract(mgr,tranRelation, espK, nextCube);
+	bdd_ref(image);
+
+	temp1 = bdd_bdd_univ_abstract(mgr,image,inputCube);
+	bdd_ref(temp1);
+	bdd_recursive_deref(mgr,image);
+
+	espKPlusOne = bdd_bdd_and(mgr,temp1,initialEsp);
+	bdd_ref(espKPlusOne);
+	bdd_recursive_deref(mgr,temp1);
+	temp1 = bdd_bdd_swap_variables(mgr,espKPlusOne,allPreVars,
+				     allNexVars,2*nVars);
+	bdd_ref(temp1);
+	bdd_recursive_deref(mgr,espKPlusOne);
+	espKPlusOne = temp1;
+	
+	if (espKPlusOne == espK) {
+	  break;
+	}
+	bdd_recursive_deref(mgr,espK);
+	espK = espKPlusOne;
+	depth++;
+    } while (1);
+
+    if (restrVerbose)
+      (void) fprintf(vis_stdout,"** restr info: EQ. relation computation depth = %d\n",
+		     depth);
+
+    bdd_recursive_deref(mgr,espKPlusOne);
+    bdd_recursive_deref(mgr,initialEsp);
+    bdd_recursive_deref(mgr,inputCube);
+    bdd_recursive_deref(mgr,nextCube);
+
+    bdd_ref(temp = bdd_bdd_swap_variables(mgr,espK,allNexVars,
+					  allPreVars,2*nVars));
+    bdd_recursive_deref(mgr,espK);
+    espK = temp;
+
+    FREE(allPreVars);
+    FREE(allNexVars);
+
+    return espK;
+}
+
+/**Function********************************************************************
+
+  Synopsis [This function returns the state equivalence relation for an FSM.]
+
+  Description [This function returns the state equivalence relation
+  for an FSM. Lambda is the primary output relation and TR is the
+  state transition relation of the product machine. Lambda has xVars,
+  uVars and piVars in its support. TR has piVars, xVars,yVars,uVars
+  and vVars in its support. nPi is the number of piVars and nVars is
+  the number of xVars. xVars, yVars, uVars and vVars are all of the
+  same size, i.e., nVars. The returned BDD is a function of xVars and
+  uVars.
+
+  For more information on the algorithm, please refer to "Extending Equivalence
+  Class Computation to Large FSMs", ICCD 96.]
+
+  SideEffects []
+
+  SeeAlso     [RestrGetEquivRelation]
+
+******************************************************************************/
+bdd_node *
+RestrComputeEquivRelationUsingCofactors(
+  bdd_manager  	*mgr,
+  bdd_node      *Lambda,
+  bdd_node      *TR,
+  bdd_node	**xVars,
+  bdd_node	**yVars,
+  bdd_node	**uVars,
+  bdd_node	**vVars,
+  bdd_node	**piVars,
+  int		  nVars,
+  int		  nPi,
+  boolean         restrVerbose)
+
+{
+  bdd_node *espKxu, *espKyv, *espKPlusOne, *espKMinusOne;
+  bdd_node *espKCofKMinusOne;
+  bdd_node *inputCube, *nextCube;
+  bdd_node *tranRelation;
+  bdd_node *newTran;
+  bdd_node **allPreVars, **allNexVars;
+  int i,depth;
+
+  bdd_ref(tranRelation = TR);
+
+  allPreVars = ALLOC(bdd_node *, 2*nVars);
+  allNexVars = ALLOC(bdd_node *, 2*nVars);
+  for(i = 0; i < nVars;i++) {
+    allPreVars[i] = xVars[i];
+    allNexVars[i] = yVars[i];
+  } 
+  for(i = 0; i < nVars;i++) {
+    allPreVars[i+nVars] = uVars[i];
+    allNexVars[i+nVars] = vVars[i];
+  } 
+
+  /* nextCube is a cube of yVars and vVars */
+  nextCube = bdd_bdd_compute_cube(mgr,allNexVars,NIL(int),2*nVars);
+  bdd_ref(nextCube);
+
+  /* inputCube is a cube of piVars */
+  inputCube = bdd_bdd_compute_cube(mgr,piVars,NIL(int),nPi);
+  bdd_ref(inputCube);
+
+  /* espKxu = \forall_{piVars} Lambda */
+  espKxu = bdd_bdd_univ_abstract(mgr,Lambda,inputCube);
+  bdd_ref(espKxu);
+
+  espKyv = bdd_bdd_swap_variables(mgr,espKxu,allPreVars,
+				  allNexVars,2*nVars);
+  bdd_ref(espKyv);
+  bdd_ref(espKMinusOne = bdd_read_one(mgr));
+  bdd_ref(espKPlusOne = bdd_read_one(mgr));
+
+  /* The following loop is essentially the following:
+   * E_{k+1} = E_k \wedge (\forall_x(func)) where
+   * func = \exists_{yv} ((TR \downarrow E_k) \wedge (E_k \downarrow E_{k-1}))
+   */
+  depth = 0;
+  while (1) {
+    bdd_node *image, *temp1;
+	
+    bdd_recursive_deref(mgr, espKPlusOne);
+    bdd_ref(espKCofKMinusOne = bdd_bdd_constrain(mgr, espKyv, 
+						 espKMinusOne));
+    bdd_recursive_deref(mgr, espKMinusOne);
+    bdd_ref(espKMinusOne = espKyv);
+
+    bdd_ref(newTran = bdd_bdd_constrain(mgr, tranRelation, espKxu));
+
+    image = bdd_bdd_and_abstract(mgr,newTran, espKCofKMinusOne, nextCube);
+    bdd_ref(image);
+    bdd_recursive_deref(mgr, newTran);
+    bdd_recursive_deref(mgr, espKCofKMinusOne);
+
+    temp1 = bdd_bdd_univ_abstract(mgr,image,inputCube);
+    bdd_ref(temp1);
+    bdd_recursive_deref(mgr,image);
+    espKPlusOne = bdd_bdd_and(mgr,temp1,espKxu);
+    bdd_ref(espKPlusOne);
+    bdd_recursive_deref(mgr,temp1);
+
+    if (espKPlusOne == espKxu) {
+      bdd_recursive_deref(mgr,espKMinusOne);
+      bdd_recursive_deref(mgr,espKxu);
+      bdd_recursive_deref(mgr,espKyv);
+      bdd_recursive_deref(mgr,tranRelation);
+      bdd_recursive_deref(mgr,inputCube);
+      bdd_recursive_deref(mgr,nextCube);
+      FREE(allPreVars);
+      FREE(allNexVars);
+      if (restrVerbose) {
+	(void) fprintf(vis_stdout,"** restr info: EQ. relation computation depth = %d\n",
+		       depth);
+      }
+      return espKPlusOne;
+    }
+
+    bdd_recursive_deref(mgr, espKxu);
+    bdd_ref(espKxu = espKPlusOne);
+    bdd_recursive_deref(mgr, espKyv);
+    espKyv = bdd_bdd_swap_variables(mgr,espKxu,allPreVars,
+				    allNexVars,2*nVars);
+    bdd_ref(espKyv);
+	
+    depth++;
+  }
+
+}
+
+/**Function********************************************************************
+
+  Synopsis [Returns the BDD for the augmented tr.]
+
+  Description [Returns the BDD for the augmented tr. The procedure of
+  augmentation is as follows: If there exists a pair (x,y) in tr and a
+  pair (y,v) in equivRelation, then the augmented tr has an additional
+  pair (x,v) added to it. The newly added edges are called 'ghost
+  edges'. Moreover, tr is a function of xVars and yVars, while
+  equivRelation is a function of yVars and vVars. nVars is the size of
+  yVars and vVars each. The returned BDD has the same support
+  variables as tr.
+
+  The boolean formulation is:
+
+  T^a(x,y) = \exists_z E(y,z) \wedge T(x,z)]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+bdd_node *
+RestrComputeTrWithGhostEdges(
+  bdd_manager *mgr,
+  bdd_node **yVars,
+  bdd_node **vVars,
+  bdd_node *tr,
+  bdd_node *equivRelation,
+  int nVars)
+{
+  bdd_node *abstractCube;
+  bdd_node *temp;
+  bdd_node *ghostTR;
+
+  abstractCube = bdd_bdd_compute_cube(mgr,yVars,NIL(int),nVars);
+  bdd_ref(abstractCube);
+
+  temp = bdd_bdd_and_abstract(mgr,tr,equivRelation,abstractCube);
+  bdd_ref(temp);
+  bdd_recursive_deref(mgr,abstractCube);
+
+  ghostTR = bdd_bdd_swap_variables(mgr,temp,vVars,yVars,nVars);
+  bdd_ref(ghostTR);
+  bdd_recursive_deref(mgr,temp);
+
+  return ghostTR;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Returns a 0-1 ADD containing minterms such that the
+  discriminant for those minterms in f is greater than that in g.]
+
+  Description [Returns a 0-1 ADD containing minterms such that the
+  discriminant for those minterms in f is greater than that in g.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddAddApply.c]
+******************************************************************************/
+bdd_node *
+RestrAddMaximum(
+  bdd_manager *ddManager,
+  bdd_node **f,
+  bdd_node **g)
+{
+  bdd_node *plusInf;
+  bdd_node *zero, *one;
+
+  zero = bdd_read_zero(ddManager);
+  one = bdd_read_one(ddManager);
+  plusInf = bdd_read_plus_infinity(ddManager);
+
+  if(*g == plusInf) {
+    return zero;
+  }
+
+  if(bdd_is_constant(*f) && bdd_is_constant(*g)) {
+    if(bdd_add_value(*f) > bdd_add_value(*g)) {
+      return one;
+    } else {
+      return zero;
+    }
+  }
+  return NULL;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns a 0-1 ADD containing minterms such that the
+  discriminant for those minterms in f is equal to that in g.]
+
+  Description [Returns a 0-1 ADD containing minterms such that the
+  discriminant for those minterms in f is equal to that in g.]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddAddApply.c]
+
+******************************************************************************/
+bdd_node *
+RestrAddEqual(
+  bdd_manager *ddManager,
+  bdd_node **f,
+  bdd_node **g)
+{
+  bdd_node *zero, *one;
+
+  zero = bdd_read_zero(ddManager);
+  one = bdd_read_one(ddManager);
+
+  if(*f == *g) {
+    return one;
+  }
+
+  if(bdd_is_constant(*f) && bdd_is_constant(*g)) {
+      return zero;
+  }
+  return NULL;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Given an array of BDD ids, return the array of
+  corresponding BDDs.]
+
+  Description [Given an array of BDD ids, return the array of
+  corresponding BDDs.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+bdd_node **
+RestrBddNodeArrayFromIdArray(
+  bdd_manager	*ddManager,
+  array_t	*idArray)
+{
+  bdd_node **xvars;
+  int i,id;
+  int nvars = array_n(idArray);
+
+  xvars = ALLOC(bdd_node *, nvars);
+  if (xvars == NULL)
+    return NULL;
+
+  for(i = 0; i < nvars; i++) {
+    id = array_fetch(int,idArray,i);
+    xvars[i] = bdd_bdd_ith_var(ddManager,id);
+    bdd_ref(xvars[i]);
+  }
+  return xvars;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Calculate the average bit change in the STG.]
+
+  Description [Calculate the average bit change in the STG. probTR is an ADD
+  representing the absolute transition probability matrix of the STG.
+  xVars and yVars are the present and next state variables respectively. nVars
+  is the number of state variables. 
+
+  average bit change = (\exists^+_x(probTr * HD(x,y))). ]
+
+  SideEffects [None]
+
+  SeeAlso []
+******************************************************************************/
+double 
+RestrAverageBitChange(
+  bdd_manager *manager,
+  bdd_node *probTR,
+  bdd_node **xVars,
+  bdd_node **yVars,
+  int nVars)
+{
+  bdd_node *diff, *cube, *PA, *QA;
+  bdd_node **vars;
+  double Mean;
+  int i;
+
+  vars = ALLOC(bdd_node *,2*nVars);
+  for (i = 0; i < nVars; i++) {
+    vars[i] = bdd_add_ith_var(manager,bdd_node_read_index(xVars[i]));
+    bdd_ref(vars[i]);
+  }
+  for (i = nVars; i < 2*nVars; i++) {
+    vars[i] = bdd_add_ith_var(manager,bdd_node_read_index(yVars[i-nVars]));
+    bdd_ref(vars[i]);
+  }
+
+  cube = bdd_add_compute_cube(manager,vars,NIL(int),2*nVars);
+  bdd_ref(cube);
+
+  /* Calculate the Hamming distance ADD. This ADD represents the hamming
+   * distance between two vectors represented by xVars and yVars.
+   */
+  bdd_ref(diff = bdd_add_hamming(manager,xVars,yVars,nVars));
+  bdd_ref(PA = bdd_add_apply(manager,bdd_add_times,probTR,diff));
+  bdd_recursive_deref(manager,diff);
+  
+  /* And now add and abstract all the variables.*/
+  bdd_ref(QA = bdd_add_exist_abstract(manager,PA,cube));
+  bdd_recursive_deref(manager,PA);
+  bdd_recursive_deref(manager,cube);
+  Mean = (double)bdd_add_value(QA);
+  bdd_recursive_deref(manager,QA); 
+
+  for (i = 0; i < 2*nVars; i++) {
+    bdd_recursive_deref(manager,vars[i]);
+  }
+  FREE(vars);
+  return Mean;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Create an extra set of auxillary BDD variables--corresponding to
+  present and next state variables of the network--required during
+  restructuring.]
+
+  SideEffects [None]
+
+  SeeAlso     []
+
+******************************************************************************/
+array_t *
+RestrCreateNewStateVars(
+  Ntk_Network_t *network,
+  bdd_manager *ddManager,
+  bdd_node **xVars,
+  bdd_node **yVars)
+
+{
+  Ntk_Node_t *node1;
+  char *name, *name1;
+  array_t *varValues;
+  array_t *nameArray;
+  int i,id,index;
+  int nVars = Ntk_NetworkReadNumLatches(network);
+
+  array_t *uVarIds, *vVarIds;
+  array_t *result;
+
+  varValues = array_alloc(int, 0);
+  nameArray = array_alloc(char *,0);    
+  uVarIds = array_alloc(int, 0);
+  vVarIds = array_alloc(int, 0);
+  result = array_alloc(array_t *, 0);
+
+  id = bdd_num_vars(ddManager);
+
+  for (i = 0; i < nVars; i++) {
+    index = bdd_node_read_index(yVars[i]);
+    node1 = Ntk_NetworkFindNodeByMddId(network,index);
+    name = Ntk_NodeReadName(node1);
+    name1 = util_strcat3(name,"$NTK2","");
+    array_insert_last(int,varValues,2);
+    array_insert_last(char *,nameArray,name1);
+    array_insert_last(int, vVarIds, id);
+    id++;
+
+    index = bdd_node_read_index(xVars[i]);
+    node1 = Ntk_NetworkFindNodeByMddId(network,index);
+    name = Ntk_NodeReadName(node1);
+    name1 = util_strcat3(name,"$NTK2","");
+    array_insert_last(int,varValues,2);
+    array_insert_last(char *,nameArray,name1);
+    array_insert_last(int, uVarIds, id);
+    id++;
+
+  }
+  mdd_create_variables(ddManager,varValues,nameArray,NIL(array_t));
+
+  arrayForEachItem(char *,nameArray,i,name) {
+    FREE(name);
+  }
+  array_free(nameArray);
+  array_free(varValues);
+
+  array_insert_last(array_t *, result, uVarIds);
+  array_insert_last(array_t *, result, vVarIds);
+
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [In the absence of initial order of the variables, this
+  function assings MDD Ids to the input, present state and next state
+  variables.]
+
+  Description [In the absence of initial order of the variables, this
+  function assigns MDD Ids to the input, present state and next state
+  variables.
+
+  This procedure is NOT currently used and is here for future purposes.]
+
+  SideEffects [The BDD manager is changed accordingly.]
+
+  SeeAlso []
+******************************************************************************/
+void
+RestrSetInitialOrder(
+  Ntk_Network_t *network,
+  bdd_manager	*ddManager)
+
+{
+  Ntk_Node_t *node, *node1;
+  lsGen	gen;
+  char *name;
+  array_t	*varValues;
+  array_t	*nameArray;
+  int		id;
+
+  varValues = array_alloc(int,0);
+  nameArray = array_alloc(char *,0);
+
+  id = 0;
+  Ntk_NetworkForEachLatch(network,gen,node) {
+    node1 = Ntk_NodeReadShadow(node);
+    name = util_strsav(Ntk_NodeReadName(node1));
+    Ntk_NodeSetMddId(node1,id);
+    array_insert_last(int,varValues,2);
+    array_insert_last(char *,nameArray,name);
+    id++;
+
+    name = util_strsav(Ntk_NodeReadName(node));
+    Ntk_NodeSetMddId(node,id);
+    array_insert_last(int,varValues,2);
+    array_insert_last(char *,nameArray,name);
+    id++;
+  }
+
+  Ntk_NetworkForEachPrimaryInput(network,gen,node) {
+    name = util_strsav(Ntk_NodeReadName(node));
+    Ntk_NodeSetMddId(node,id);
+    array_insert_last(int,varValues,2);
+    array_insert_last(char *,nameArray,name);
+    id++;
+  }
+
+  mdd_create_variables(ddManager,varValues,nameArray,NIL(array_t));
+
+  id = 0;
+  arrayForEachItem(char *, nameArray, id, name) {
+    FREE(name);
+  }
+  array_free(nameArray);
+  array_free(varValues);
+
+}
+
Index: vis_dev/vis-2.3/src/rst/rst.c
===================================================================
--- vis_dev/vis-2.3/src/rst/rst.c	(revision 14)
+++ vis_dev/vis-2.3/src/rst/rst.c	(revision 14)
@@ -0,0 +1,769 @@
+/**CFile***********************************************************************
+
+  FileName    [rst.c]
+
+  PackageName [rst]
+
+  Synopsis    [utilities for restructuring hierarchy ]
+
+  Author      [Sriram Rajamani , with many thanks to Yuji Kuimoto]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "rstInt.h"
+
+static char rcsid[] UNUSED = "$Id: rst.c,v 1.6 2005/04/16 07:33:12 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+  int            verbose = 0;              /* default value */
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandCollapseChild(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the test package.]
+
+  SideEffects []
+
+  SeeAlso     [Rst_End]
+
+******************************************************************************/
+void
+Rst_Init(void)
+{
+  /*
+   * Add a command to the global command table.  By using the leading
+   * underscore, the command will be listed under "help -a" but not "help".
+   */
+  Cmd_CommandAdd("collapse_child", CommandCollapseChild,
+		 /* doesn't changes_network */ 0);
+  Cmd_CommandAdd("decompose_child", Rst_CommandGroupComponents,
+		 /* doesn't changes_network */ 0);
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Ends the test package.]
+
+  SideEffects []
+
+  SeeAlso     [Rst_Init]
+
+******************************************************************************/
+void
+Rst_End(void)
+{
+  /*
+   * For example, free any global memory (if any) which the test package is
+   * responsible for.
+   */
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the collapse_child command.]
+
+  CommandName [collapse_child]
+
+  CommandSynopsis [Collapses a parent (which is the current node)
+and a given child node into the parent]
+
+  CommandArguments [\[-h\] \[-v\] &lt;child_instance_name&gt;]
+  
+  CommandDescription [This command collapses the given child into the current
+  node. After this command, the number of children of the
+  current node will decrease by one. The variables in
+  the child node will be renamed to reflect their
+  original name.  For example, if the
+  current node is named "foo" and it has two children,
+  "bar1" and "bar2", then after<p>
+
+        collapse_child bar1<p>
+
+  is executed, the name of any variable occuring in bar1,
+  say "xvar" will be renamed "bar1$xvar". The new parent
+  will have only the single child "bar2" (which can be
+  seen by typing "ls").
+  <p>
+
+  The user can use "cd" to traverse a hierarchy, go to a particular
+  node. When the user uses "write_blif" from a particular node, vis will write
+  the circuit in this node out. However, the user might want to do synthesis
+  on the entire circuit in the hierarchy. In that case, the hierarchy can be
+  collapsed into a single node, by repeatedly using this command. <p>
+
+  Examples:<p>
+    collapse_child P1<p>
+    Collapse P1 into the current node.<p>
+
+  Command options:<p>  
+  <dl>
+  <dt> -h
+  <dd> Print the command usage.
+  </dl>
+
+  <dt> -v
+  <dd> Verbose mode.
+  </dl>
+  ]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandCollapseChild(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int            c;
+  Hrc_Node_t  *parent, *child;
+  boolean retVal;
+
+  verbose = 0;
+  
+  /*
+   * Parse command line options.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "vh")) != EOF) {
+    switch(c) {
+      case 'v':
+        verbose = 1;
+        break;
+      case 'h':
+        goto usage;
+      default:
+        goto usage;
+    }
+  }
+
+  
+  if(argc < 2){
+    goto usage;
+  }
+
+
+  parent =   Hrc_ManagerReadCurrentNode(*hmgr);
+  if (parent == NULL) {
+    fprintf(vis_stderr, "Can't find parent node \n");
+    return(1);
+  }
+
+  if (argc - util_optind == 0) {
+    (void) fprintf(vis_stderr, "Child node name not provided\n");
+    goto usage;
+  }
+  else if (argc - util_optind > 1) {
+    (void) fprintf(vis_stderr, "too many arguments\n");
+    goto usage;
+  }
+  
+
+  if(verbose)
+    (void)fprintf(vis_stdout, "Collapsing child : %s\n", argv[util_optind]);
+  
+  child =   Hrc_ManagerFindNodeByPathName(*hmgr, argv[util_optind],TRUE);
+  if (child == NULL) {
+    fprintf(vis_stderr, "Can't find child node %s\n", argv[util_optind]);
+    return(1);
+  }  
+
+  retVal = RstCollapseNode( *hmgr, parent, child);
+  return(retVal);
+  
+
+  usage:
+  (void) fprintf(vis_stdout,
+                 "The collapse_child command collapses the child node into the current node.\n");
+  (void) fprintf(vis_stderr,
+                 "usage: collapse_child [-h] [-v] <child instance name>\n");
+  (void) fprintf(vis_stderr, "   -h\t\tprint the command usage\n");
+  (void) fprintf(vis_stderr, "   -v\t\tverbose\n");
+  return 1;		/* error exit */
+}
+
+/**Function********************************************************************
+
+
+  Synopsis           [Given node1 and node2 where node1 is a parent of node2,
+                      this function collapses node2 into node1]
+
+  Description        [optional]
+
+  SideEffects        [node2 will be deleted from the hierarchy and banished into
+                      thin air. Current node will be set to new parent]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+
+int RstCollapseNode(
+  Hrc_Manager_t *hmgr,
+  Hrc_Node_t    *parent,
+  Hrc_Node_t    *child
+  )
+{
+  boolean foundChild;
+  st_generator *gen; /*XXX -  Do I need to initialize this */
+  char *curChildName, *newModelName, *parentModelName, *parentInstanceName, *suffixModelName;
+  Hrc_Node_t *curChild, *newNode, *root;
+  Hrc_Model_t *parentModelPtr, *childModelPtr, *newModelPtr;
+  array_t *actualInputArray, *actualOutputArray, *formalInputArray, *formalOutputArray;
+  st_table *parentVarTable, *childVarTable;
+  int i;
+  Var_Variable_t *var, *newVar;
+  boolean retVal;
+    
+  /* set current node to parent */
+  Hrc_ManagerSetCurrentNode(hmgr, parent);
+
+  /* get root node */
+  root = Hrc_ManagerReadRootNode(hmgr);
+  
+  /* check if the child is really our child */
+  foundChild = FALSE;
+  Hrc_NodeForEachChild ( parent, gen, curChildName, curChild){
+    if(curChild == child) foundChild = TRUE;
+  }
+
+  if(!foundChild) {
+      fprintf(vis_stdout, "Collapse called with bad child\n");
+      return(-1);
+  }
+
+  /* get masternodes for parent and child */
+  parentModelPtr     =
+      Hrc_ManagerFindModelByName(hmgr,Hrc_NodeReadModelName(parent));
+  assert(parentModelPtr != NULL);
+
+  childModelPtr     =
+      Hrc_ManagerFindModelByName(hmgr,Hrc_NodeReadModelName(child));
+  assert(childModelPtr != NULL);
+ 
+
+  /* create a new model by concatenating names of parent and child */
+  suffixModelName = util_strcat3( Hrc_ModelReadName(parentModelPtr),
+                               "#",Hrc_ModelReadName(childModelPtr));
+  newModelName = util_strcat3( Hrc_NodeReadInstanceName(child),
+                               "#",suffixModelName);
+  FREE(suffixModelName);
+  assert(newModelName != 0);
+
+  newModelPtr = Hrc_ManagerFindModelByName(hmgr, newModelName);
+  if(newModelPtr != NULL){
+    fprintf(vis_stdout, "Warning: rst has detected an existing model with name %s\n",
+           newModelName);
+    fprintf(vis_stdout, "If you have collapsed another instance of this child model\n");
+    fprintf(vis_stdout, "into another instance of this parent previously this is \n");
+    fprintf(vis_stdout, "normal and collapse_child will function correctly.\n");
+    fprintf(vis_stdout, "Otherwise, you have a name conflict that rst cannot handle\n");
+  }
+  else {
+    newModelPtr = Hrc_ModelAlloc(hmgr, newModelName);
+    
+    if(verbose){
+      fprintf(vis_stdout, "Adding child components to new model\n");
+    }
+    childVarTable = RstAddChildComponentsToNewModel(hmgr,child, parent, newModelPtr);
+    
+    actualInputArray = Hrc_NodeReadActualInputs(child);
+    actualOutputArray = Hrc_NodeReadActualOutputs(child);
+    formalInputArray = Hrc_NodeReadFormalInputs(child);
+    formalOutputArray = Hrc_NodeReadFormalOutputs(child);
+    
+    assert(array_n(actualInputArray) == array_n(formalInputArray));
+    assert(array_n(actualOutputArray) == array_n(formalOutputArray));
+    
+    parentVarTable =  st_init_table(st_ptrcmp,st_ptrhash);
+    
+    for (  i = 0; i < array_n(formalInputArray); i++) {
+      /* get the modified child var */
+      var = array_fetch(Var_Variable_t *, formalInputArray, i);
+      retVal = st_lookup(childVarTable, (char *)var, &newVar);
+      assert(retVal);
+      var = array_fetch(Var_Variable_t *, actualInputArray, i);
+      st_insert(parentVarTable, (char *) var, (char *) newVar);
+    }
+    
+    for (  i = 0; i < array_n(formalOutputArray); i++) {
+      /* get the modified child var */
+      var  = array_fetch(Var_Variable_t *, formalOutputArray, i);
+      retVal = st_lookup(childVarTable, (char *)var, &newVar);
+      assert(retVal);
+      var = array_fetch(Var_Variable_t *, actualOutputArray, i);
+      st_insert(parentVarTable, (char *) var, (char *) newVar);
+    }
+    
+    if(verbose){
+      fprintf(vis_stdout, "Adding parent components to new model\n");
+    }
+    
+    RstAddParentComponentsToNewModel(hmgr, parent, newModelPtr,
+                                     parentVarTable, child);
+    st_free_table(childVarTable);
+    st_free_table(parentVarTable);
+  }
+  
+  if(verbose)
+    fprintf(vis_stdout, "Creating new model hierarchy.\n");
+
+  parentInstanceName = Hrc_NodeReadInstanceName(parent);
+  if(verbose)
+    fprintf(vis_stdout, "Retaining old parent's instance name %s\n",
+            parentInstanceName);
+    
+    newNode = Hrc_ModelCreateHierarchy(hmgr, newModelPtr,parentInstanceName);
+                                     
+  
+  if(verbose)
+    fprintf(vis_stdout, "Replacing old hierarchy tree with new tree.\n");
+  retVal = Hrc_TreeReplace(parent,newNode);
+  assert(retVal);
+
+  Hrc_ManagerSetCurrentNode(hmgr,newNode);
+
+  if(root == parent){
+    if(verbose){
+      fprintf(vis_stdout, "Current parent IS the root...\n");
+      fprintf(vis_stdout, "Deleting old root model\n");
+    }
+    
+    parentModelName =  util_strsav(Hrc_ModelReadName(parentModelPtr));
+    Hrc_ModelDelete(hmgr, parentModelName);
+    FREE(parentModelName);
+  }
+  
+  
+  FREE(newModelName);
+  return(0);
+}
+
+/**Function********************************************************************
+
+
+  Synopsis           [Add Child's components - latches,tables,vars to new model]
+
+  Description        [optional]
+
+  SideEffects        [none]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+
+st_table * RstAddChildComponentsToNewModel(
+  Hrc_Manager_t *hmgr,
+  Hrc_Node_t    *child,
+  Hrc_Node_t    *parent,
+  Hrc_Model_t   *newModelPtr
+  )
+{
+  Hrc_Node_t *newMaster, *grandChild;
+  st_generator *gen; 
+  int i,index;
+  Tbl_Table_t *tbl,*newTbl, *resetTbl, *newResetTbl;
+  Var_Variable_t *var, *newVar ,  *newLatchInput, *newLatchOutput, *parentVar;
+  char *latchName, *varName, *newVarName, *grandChildInstName, *newSubcktName;
+  Hrc_Latch_t *latch, *newLatch;
+  st_table *childVarToNewVar;
+  array_t *actualInputArray, *newActualInputArray;
+  array_t *actualOutputArray, *newActualOutputArray;
+  boolean retVal;
+
+  newMaster = Hrc_ModelReadMasterNode(newModelPtr);
+  
+  childVarToNewVar = st_init_table(st_ptrcmp,st_ptrhash);
+  /* Add all Child's variables to the new model after prefixing child name */
+  Hrc_NodeForEachVariable(child, gen, varName, var){
+    if( Var_VariableTestIsPI(var) || Var_VariableTestIsPO(var)){
+      parentVar = Hrc_VariableFindActualFromFormal(child, var, parent);
+      assert(parentVar != NULL);
+      newVarName = util_strsav(Var_VariableReadName(parentVar));
+      assert(newVarName != NULL);
+    }
+    else{
+    newVarName = util_strcat3(Hrc_NodeReadInstanceName(child), "$",
+                              Var_VariableReadName(var));
+    assert(newVarName != NULL);
+    }
+
+    newVar = Hrc_NodeFindVariableByName(newMaster, newVarName);
+    if (newVar != NULL){
+      assert (Var_VariableTestIsPI(var) || Var_VariableTestIsPO(var));
+    }
+
+    if(newVar == NULL)
+      {
+        newVar = Var_VariableDup(var,newMaster);
+        retVal = Var_VariableChangeName(newVar,newVarName);
+        assert(retVal);
+        Var_VariableResetAllTypes(newVar);
+      }
+    
+    FREE(newVarName);
+    st_insert(childVarToNewVar, (char *)var, (char *)newVar);
+  }
+
+  /* Add all Child's tables to new model */
+  Hrc_NodeForEachNameTable(child, i, tbl){
+    /* copy the table */
+    newTbl = Tbl_TableHardDup(tbl);
+
+    /* Muck with its vars */
+    Tbl_TableForEachInputVar(newTbl, index, var){
+      retVal = st_lookup(childVarToNewVar, (char *)var, &newVar);
+      assert(retVal);
+      Tbl_TableSubstituteVar(newTbl,var,newVar);
+    }
+    Tbl_TableForEachOutputVar(newTbl, index, var){
+      retVal = st_lookup(childVarToNewVar, (char *)var, &newVar);
+      assert(retVal);
+      Tbl_TableSubstituteVar(newTbl,var,newVar);
+    }
+
+    /* add it in! */
+    Hrc_NodeAddNameTable(newMaster, newTbl);
+  }
+
+  /* Add all Child's latches to the new model */
+  Hrc_NodeForEachLatch( child, gen, latchName, latch){
+
+    /* muck with the variables */
+    retVal = st_lookup(childVarToNewVar, (char *)Hrc_LatchReadInput(latch),
+                       &(newLatchInput));
+    assert(retVal);
+    Var_VariableSetNS(newLatchInput);
+    retVal = st_lookup(childVarToNewVar, (char *)Hrc_LatchReadOutput(latch),
+                       &(newLatchOutput));
+    Var_VariableSetPS(newLatchOutput);
+    assert(retVal);
+
+    /* get new latch */
+    newLatch = Hrc_LatchCreate(newModelPtr, newLatchInput, newLatchOutput);
+    assert(newLatch != NULL);
+
+    /* copy reset table */
+    resetTbl = Hrc_LatchReadResetTable(latch);
+    assert(resetTbl != NULL);
+    newResetTbl = Tbl_TableSoftDup(resetTbl);
+    
+    /* muck with reset table vars */
+    Tbl_TableForEachInputVar(newResetTbl, index, var){
+      retVal = st_lookup(childVarToNewVar, (char *)var, &newVar);
+      assert(retVal);
+      Tbl_TableSubstituteVar(newResetTbl,var,newVar);
+    }
+    Tbl_TableForEachOutputVar(newResetTbl, index, var){
+      retVal = st_lookup(childVarToNewVar, (char *)var, &newVar);
+      assert(retVal);
+      Tbl_TableSubstituteVar(newResetTbl,var,newVar);
+    }
+
+    /* Add table to latch */
+    retVal = Hrc_LatchSetResetTable(newLatch,newResetTbl);
+    assert(retVal);
+    
+    /* add it in! */
+    Hrc_NodeAddLatch(newMaster, newLatch);
+  }
+
+  /* add all Child's sub circuits  to master */
+  Hrc_NodeForEachChild(child, gen, grandChildInstName, grandChild) {
+
+    actualInputArray = Hrc_NodeReadActualInputs(grandChild);
+    actualOutputArray = Hrc_NodeReadActualOutputs(grandChild);
+
+    newActualInputArray = array_alloc(Var_Variable_t *, 0);
+    newActualOutputArray = array_alloc(Var_Variable_t *, 0);
+
+    /* same story - var mucking */
+    for ( i = 0; i < array_n(actualInputArray); i++){
+      var = array_fetch(Var_Variable_t *, actualInputArray, i);
+      assert(var != NULL);
+      retVal = st_lookup(childVarToNewVar, (char *)var, &newVar);
+      assert(retVal);
+      Var_VariableSetSI(newVar);
+      array_insert_last(Var_Variable_t *, newActualInputArray, newVar);
+    }
+
+    for ( i = 0; i < array_n(actualOutputArray); i++){
+      var = array_fetch(Var_Variable_t *, actualOutputArray, i);
+      assert(var != NULL);
+      retVal = st_lookup(childVarToNewVar, (char *)var, &newVar);
+      assert(retVal);
+      Var_VariableSetSO(newVar);
+      array_insert_last(Var_Variable_t *, newActualOutputArray, newVar);
+    }
+
+    
+    /* add subcircuit to model */
+    newSubcktName = util_strcat3(Hrc_NodeReadInstanceName(child), "$",
+                                 Hrc_NodeReadInstanceName(grandChild));
+    Hrc_ModelAddSubckt(newModelPtr,
+                       Hrc_ManagerFindModelByName(hmgr,Hrc_NodeReadModelName(grandChild)),
+                       newSubcktName,
+                       newActualInputArray, newActualOutputArray);
+    FREE(newSubcktName);
+  }
+
+  return(childVarToNewVar);
+}
+/**Function********************************************************************
+
+
+  Synopsis           [Add parents componets to new model]
+
+  Description        [optional]
+
+  SideEffects        [none]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+
+
+int RstAddParentComponentsToNewModel(
+  Hrc_Manager_t *hmgr,
+  Hrc_Node_t   *parent,
+  Hrc_Model_t   *newModelPtr,
+  st_table      *parentVarTable,
+  Hrc_Node_t   *child
+  )
+{
+  Hrc_Node_t *newMaster, *curChild;
+  st_generator *gen; 
+  int i,index;
+
+  Tbl_Table_t *tbl,*newTbl, *resetTbl, *newResetTbl;
+  Var_Variable_t *var, *newVar ,  *newLatchInput, *newLatchOutput ;
+  char *latchName, *varName, *curChildInstName;
+  Hrc_Latch_t *latch, *newLatch;
+  array_t *actualInputArray, *newActualInputArray;
+  array_t *actualOutputArray, *newActualOutputArray;
+  int pFanout;
+  boolean retVal;
+
+  newMaster = Hrc_ModelReadMasterNode(newModelPtr);
+
+  /* Add all Parent's variables to the new model.
+     If a parent variable is an interface to the child, it
+     will change and get merged with the child's correspoinding
+     interface variable */
+  
+  Hrc_NodeForEachVariable(parent, gen, varName, var){
+    if(st_lookup(parentVarTable, (char *) var, &newVar) == 0){
+      /* not an interface to child - copy it */
+      newVar = Var_VariableDup(var,newMaster);
+      assert(newVar != NULL);
+      Var_VariableResetAllTypes(newVar);
+      st_insert(parentVarTable, (char *)var, (char *)newVar);
+    }
+    else {
+      /* interface variable. Have to increment the number of
+         fanouts */
+      pFanout = Var_VariableReadNumFanoutTables(var);
+      while(pFanout){
+        Var_VariableIncrementNumFanoutTables(newVar);
+        pFanout--;
+      }
+    }
+  }
+  
+
+  /* Add all Parent's tables to new model */
+  Hrc_NodeForEachNameTable(parent, i, tbl){
+    /* copy the table */
+    newTbl = Tbl_TableHardDup(tbl);
+    /* Muck with its vars */
+    Tbl_TableForEachInputVar(newTbl, index, var){
+      retVal = st_lookup(parentVarTable, (char *)var, &newVar);
+      assert(retVal);
+      Tbl_TableSubstituteVar(newTbl,var,newVar);
+    }
+
+    Tbl_TableForEachOutputVar(newTbl, index, var){
+      retVal = st_lookup(parentVarTable, (char *)var, &newVar);
+      assert(retVal);
+      Tbl_TableSubstituteVar(newTbl,var,newVar);
+    }
+
+    /* add it in! */
+    Hrc_NodeAddNameTable(newMaster, newTbl);
+  }
+
+  /* Add all Parent's latches to the new model */
+  Hrc_NodeForEachLatch( parent, gen, latchName, latch){
+    /* muck with the variables */
+    retVal = st_lookup(parentVarTable, (char *)Hrc_LatchReadInput(latch),
+                       &(newLatchInput));
+    assert(retVal);
+    Var_VariableSetNS(newLatchInput);
+    retVal = st_lookup(parentVarTable, (char *)Hrc_LatchReadOutput(latch),
+                       &(newLatchOutput));
+    assert(retVal);
+    Var_VariableSetPS(newLatchOutput);
+
+    /* get new latch */
+    newLatch = Hrc_LatchCreate(newModelPtr, newLatchInput, newLatchOutput);
+    assert(newLatch != NULL);
+
+    /* copy reset table */
+    resetTbl = Hrc_LatchReadResetTable(latch);
+    assert(resetTbl != NULL);
+    newResetTbl = Tbl_TableSoftDup(resetTbl);
+    
+    /* muck with reset table vars */
+    Tbl_TableForEachInputVar(newResetTbl, index, var){
+      retVal = st_lookup(parentVarTable, (char *)var, &newVar);
+      assert(retVal);
+      Tbl_TableSubstituteVar(newResetTbl,var,newVar);
+    }
+    Tbl_TableForEachOutputVar(newResetTbl, index, var){
+      retVal = st_lookup(parentVarTable, (char *)var, &newVar);
+      assert(retVal);
+      Tbl_TableSubstituteVar(newResetTbl,var,newVar);
+    }
+
+    /* add table to latch */
+    retVal = Hrc_LatchSetResetTable(newLatch,newResetTbl);
+    assert(retVal);
+    
+    /* add it in! */
+    Hrc_NodeAddLatch(newMaster, newLatch);
+  }
+
+  /* add all Parent's sub circuits  to master except "the" child's */
+  Hrc_NodeForEachChild(parent, gen, curChildInstName, curChild) {
+    /* do nothing for "the" child */
+    if(curChild == child){
+      continue;
+    }
+    actualInputArray = Hrc_NodeReadActualInputs(curChild);
+    actualOutputArray = Hrc_NodeReadActualOutputs(curChild);
+
+    newActualInputArray = array_alloc(Var_Variable_t *, 0);
+    newActualOutputArray = array_alloc(Var_Variable_t *, 0);
+
+    /* same story - var mucking */
+    for ( i = 0; i < array_n(actualInputArray); i++){
+      var = array_fetch(Var_Variable_t *, actualInputArray, i);
+      retVal = st_lookup(parentVarTable, (char *)var, &newVar);
+      assert(retVal);
+      Var_VariableSetSI(newVar);
+      array_insert_last(Var_Variable_t *, newActualInputArray, newVar);
+    }
+
+    for ( i = 0; i < array_n(actualOutputArray); i++){
+      var = array_fetch(Var_Variable_t *, actualOutputArray, i);
+      retVal = st_lookup(parentVarTable, (char *)var, &newVar);
+      assert(retVal);
+      Var_VariableSetSO(newVar);
+      array_insert_last(Var_Variable_t *, newActualOutputArray, newVar);
+    }
+
+    /* add subcircuit to model */
+    Hrc_ModelAddSubckt(newModelPtr,
+                       Hrc_ManagerFindModelByName(hmgr,Hrc_NodeReadModelName(curChild)),
+                       Hrc_NodeReadInstanceName(curChild),
+                       newActualInputArray, newActualOutputArray);
+  }
+
+  /* add all formal inputs */
+  Hrc_NodeForEachFormalInput( parent, i, var){
+      retVal = st_lookup(parentVarTable, (char *)var, &newVar);
+      assert(retVal);
+      retVal = Hrc_NodeAddFormalInput(newMaster, newVar);
+      Var_VariableSetPI(newVar);
+      assert(retVal);
+  }
+
+  /* add all formal outputs */  
+  Hrc_NodeForEachFormalOutput( parent, i, var){
+      retVal = st_lookup(parentVarTable, (char *)var, &newVar);
+      assert(retVal);
+      retVal = Hrc_NodeAddFormalOutput(newMaster, newVar);
+      Var_VariableSetPO(newVar);
+      assert(retVal);
+  }
+
+  return(0);
+}
+
+#ifdef COLLAPSE_DEBUG
+int printVarTable( st_table *varTable)
+{
+  st_generator *gen;
+  Var_Variable_t *var, *newVar;
+  
+  st_foreach_item( varTable, gen, (char **) &var, (char **)&newVar){
+    printf("address: %u : %15s -> %15s \n", (unsigned)var, Var_VariableReadName(var),
+           Var_VariableReadName(newVar));
+  }
+
+  return(0);
+}
+#endif
+
Index: vis_dev/vis-2.3/src/rst/rst.h
===================================================================
--- vis_dev/vis-2.3/src/rst/rst.h	(revision 14)
+++ vis_dev/vis-2.3/src/rst/rst.h	(revision 14)
@@ -0,0 +1,89 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [rst.h]
+
+  PackageName [rst]
+
+  Synopsis    [Restructuring package for restructuring the hierarchy]
+
+  Description [This package provides the capability to restructure the user's
+               hierarchy. Currently only collapsing adjacent nodes is
+               provided. Parititioning FSMs is expected to be provided in the
+               future] 
+
+  Author      [Desmond A. Kirkpatrick and Sriram Rajamani (with many thanks to Yuji Kukimoto)]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+
+******************************************************************************/
+
+#ifndef _RST
+#define _RST
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "hrc.h"
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void Rst_Init(void);
+EXTERN void Rst_End(void);
+EXTERN array_t* Rst_VartoVarLookup(array_t* VarArray, st_table* VartoVarOne, st_table* VartoVarTwo);
+EXTERN array_t* Rst_GetNamesUntilNextOption(array_t* nameArray, int argc, char **argv);
+EXTERN array_t* Rst_LoadNameArrayFromFile(array_t* nameArray, FILE* fp);
+EXTERN Hrc_Model_t* Rst_GroupRestructureModel(Hrc_Manager_t* Hmgr, Hrc_Model_t* ParentModel, array_t* GroupArray);
+EXTERN Hrc_Node_t* Rst_GroupRestructureNode(Hrc_Manager_t* Hmgr, Hrc_Node_t* CurNode, array_t* GroupArray);
+EXTERN Hrc_Model_t* Rst_GroupGroupCombLogic(Hrc_Manager_t* Hmgr, Hrc_Model_t* CurModel);
+EXTERN Hrc_Model_t* Rst_GroupGroupLatches(Hrc_Manager_t* Hmgr, Hrc_Model_t* CurModel);
+EXTERN int Rst_CommandGroupComponents(Hrc_Manager_t** Hmgr, int argc, char ** argv);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _RST */
Index: vis_dev/vis-2.3/src/rst/rst.make
===================================================================
--- vis_dev/vis-2.3/src/rst/rst.make	(revision 14)
+++ vis_dev/vis-2.3/src/rst/rst.make	(revision 14)
@@ -0,0 +1,4 @@
+CSRC += rst.c rstGroup.c
+HEADERS += rst.h rstInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/rst/rstGroup.c
===================================================================
--- vis_dev/vis-2.3/src/rst/rstGroup.c	(revision 14)
+++ vis_dev/vis-2.3/src/rst/rstGroup.c	(revision 14)
@@ -0,0 +1,1589 @@
+/**CFile***********************************************************************
+
+  FileName    [rstGroup.c]
+
+  PackageName [rst]
+
+  Synopsis    [rst package partitioning code with user interface.]
+
+  Author      [Desmond A. Kirkpatrick]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include <stdio.h>
+#include "rstInt.h"
+#include "cmd.h"
+#include "varInt.h"
+
+static char rcsid[] UNUSED = "$Id: rstGroup.c,v 1.9 2005/05/16 06:22:35 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*
+#define RST_GROUP_DEBUG 1
+*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#define Rst_VarForEachVarInArray( \
+  /* array_t* */          array,  \
+  /* int, local */        i,      \
+  /* Var_Variable_t* */   var     \
+)                                 \
+arrayForEachItem(Var_Variable_t*, array, i, var)
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Resets number of fanout tables.]
+
+  Description [This should be moved to the Var package.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+/*
+  This was moved to VAR package by Yuji on 11/8 and renamed to
+  Var_VariableResetNumFanoutTables()
+  
+  void
+Var_VariableResetNumFanout(
+  Var_Variable_t* var)
+{
+  var->numFanoutTables = 0;
+}
+*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Duplicates a table and substitutes its variables.]
+
+  Description [Duplicates a table and substitutes its input and output
+  variables with variables given in an st_table.  This is a common
+  operation when copying tables to new Nodes during hierarchy
+  restructuring operations.  VartoVar table MUST contain new variables
+  for each variable in Table.  Returns a pointer to new table.
+
+  This should be moved to the Tbl package. ]
+
+  SideEffects [Creates new table and potentially modifies variable
+  types of variables in st_table.]
+
+  SeeAlso     []
+
+******************************************************************************/
+Tbl_Table_t*
+Tbl_TableDupAndSubstVars(
+  Tbl_Table_t* Table,
+  st_table* VartoVar)
+{
+  int tblIndx, retVal;
+  Var_Variable_t *var, *newVar;
+  Tbl_Table_t* newTbl = Tbl_TableHardDup(Table);
+  
+  Tbl_TableForEachInputVar(newTbl, tblIndx, var) {
+    retVal = st_lookup(VartoVar, (char*) var, &newVar);
+    assert(retVal);
+    Tbl_TableSubstituteVar(newTbl, var, newVar);
+    Var_VariableIncrementNumFanoutTables(newVar);
+  }
+  Tbl_TableForEachOutputVar(newTbl, tblIndx, var) {
+    retVal = st_lookup(VartoVar, (char*) var,&newVar);
+    assert(retVal);
+    Tbl_TableSubstituteVar(newTbl, var, newVar);
+  }
+  return newTbl;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Translates a set of variables given one or two st_tables.]
+
+  Description [Given an array of variables, this function looks up the
+  variable in table VartoVarOne and finds a new variable to translate
+  to.  If VartoVarTwo exist, it repeats this operation.  It returns an
+  array of new (translated) variables.
+
+  Is this a good Var package utility? ]
+
+  SideEffects [Creates new array_t of variables.]
+
+  SeeAlso     []
+
+******************************************************************************/
+array_t*
+Rst_VartoVarLookup(
+  array_t* VarArray,
+  st_table* VartoVarOne,
+  st_table* VartoVarTwo)
+{
+  int i, retVal;
+  Var_Variable_t *var, *newVar, *tmpVar;
+  array_t* newVarArray = array_alloc(Var_Variable_t*, array_n(VarArray));
+
+  Rst_VarForEachVarInArray(VarArray, i, var) {
+    retVal = st_lookup(VartoVarOne, (char*) var, &newVar);
+    assert(retVal);
+    if (VartoVarTwo) {
+      tmpVar = newVar;
+      retVal = st_lookup(VartoVarTwo, (char*) tmpVar, &newVar);
+    }
+    assert(retVal);
+    array_insert(Var_Variable_t*, newVarArray, i, newVar);
+  }
+  return newVarArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Grabs non-option strings off command line.]
+
+  Description [While running getopt, this function can be used to
+  parse strings between options off the command line.  This is useful
+  for options with multiple arguments or arguments that can be
+  specified anywhere with respect to option flags.
+
+  Perhaps this belongs in the Cmd package. ]
+
+  SideEffects [Creates new array_t of allocated char*s.
+               Presumes that getopt has been reset and is running.
+               MODIFIES util_optind!!!]
+
+  SeeAlso     [util_getopt, Rst_CommandGroupComponents]
+
+******************************************************************************/
+array_t*
+Rst_GetNamesUntilNextOption(
+  array_t* nameArray,
+  int argc,
+  char **argv)
+{
+  char* name;
+
+  while ((util_optind < argc) && (*argv[util_optind] != '-')) {
+    name = util_strcat3(argv[util_optind], "", "");
+    array_insert_last(char*, nameArray, name);
+    util_optind++;
+  }
+  return nameArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Reads an array of strings from a file.]
+
+  Description [Returns an array of strings read from an open file.]
+
+  SideEffects [Returns allocated char*s in nameArray which must be
+  preallocated.  fp must have been opened.]
+
+  SeeAlso     []
+
+******************************************************************************/
+array_t*
+Rst_LoadNameArrayFromFile(
+  array_t* nameArray,
+  FILE* fp)
+{
+  char* name;
+  char buffer[1024];
+
+  while (fscanf(fp, "%s", buffer) != EOF) {
+    name = util_strcat3(buffer, "", "");
+    array_insert_last(char*, nameArray, name);
+  }
+  return nameArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a Group from user specified components]
+
+  Description [Treating all components which PRODUCE variables (ie,
+  outputs of Tables, Latches, Subcircuits) as in the group specified by a
+  list of variables, this function builds a group and all the tables
+  associated.  Specifically, it derives the input and output
+  variables, as well as simple tables to list the contained
+  components.  A Group can then be transformed into a model via
+  RstGroupBuildModel.  Note that a special kind of group for the
+  remainder of the Node being partitioned is created using
+  RstCreateParentGroup.  This routine is called by
+  Rst_GroupRestructureNode.
+
+  NUMBER ONE RULE OF GROUPS: GROUP COMPONENTS are tracked by their
+  OUTPUT VARS ]
+
+  SideEffects [Allocates a Rst_Group_t.]
+
+  SeeAlso     [RstGroupBuildModel, RstCreateParentGroup, Rst_GroupRestructureNode]
+
+******************************************************************************/
+Rst_Group_t*
+RstGroupComponents(
+  Hrc_Model_t* CurModel,
+  char* NewName,
+  array_t* VarGroup,
+  array_t* Subcircuits)
+{
+  int i, j, tblIndx;
+  long inGroup;  
+  char* latchName, *subcktName;
+  Hrc_Latch_t* latch;
+  Hrc_Subckt_t* subckt;
+  Hrc_Node_t* curMaster;
+  st_generator* sgen;
+  Tbl_Table_t* tbl;
+  Var_Variable_t* var = NIL(Var_Variable_t);
+  array_t* subOutputs;
+  Rst_Group_t* group = RstGroupAlloc(NewName);
+
+  curMaster = Hrc_ModelReadMasterNode(CurModel);
+
+  /* Make sure there is something to group */
+  i=0;
+  if (VarGroup) {
+    i += array_n(VarGroup);
+  }
+  if (Subcircuits) {
+    i += array_n(Subcircuits);
+  }
+  if (i == 0) {
+    return 0;
+  }
+
+  /* Determine Input/Output Formal list from implied partitioning */
+
+  if (VarGroup) {
+    /* Store group variables (ie outputs of tables/latches) in hash
+       table */
+    Rst_VarForEachVarInArray(VarGroup, i, var) {
+      if ((var) && (! Var_VariableTestIsPI(var))) {
+        st_insert(group->Vars, (char*) var, (char*) (long) 1);
+      } else if ((var) && (Var_VariableTestIsPI(var))) {
+        (void) fprintf(vis_stderr,
+                       "Warning: can't group a PI: %s\n",
+                       Var_VariableReadName(var));
+      }
+    }
+  }
+
+  if (Subcircuits) {
+    /* Store Subckt in group Subcircuits hashtable.
+       Store output vars of all group Subckts in var hash table */
+    for (i = 0; i < array_n(Subcircuits); i++) {
+      subckt = array_fetch(Hrc_Subckt_t*, Subcircuits, i);
+      st_insert(group->Subcircuits, (char*) subckt, (char*) (long) 1);
+      Rst_VarForEachVarInArray(Hrc_SubcktReadActualOutputVars(subckt),
+                               j, var) {
+        if (! st_lookup(group->Vars, (char*) var, &inGroup)) {
+          st_insert(group->Vars, (char*) var, (char*) (long) 1);
+        }
+      }
+    }
+  }
+
+  /* Table and Latch outputs which are group vars become members of the group
+   */
+  
+  Hrc_NodeForEachLatch(curMaster, sgen, latchName, latch) {
+    if (st_lookup(group->Vars, (char*) Hrc_LatchReadOutput(latch), &inGroup)) {
+      st_insert(group->Latches, (char*) latch, (char*) (long) 1);
+    }
+  }
+  
+  Hrc_NodeForEachNameTable(curMaster, tblIndx, tbl) {
+    Tbl_TableForEachOutputVar(tbl, j, var) {
+      inGroup = 0;
+      if (st_lookup(group->Vars, (char*) var, &inGroup)) {
+        st_insert(group->Tables, (char*) tbl, (char*) (long) 1);
+        break;
+      }
+    }
+    /* FIXME: Table Splitting here */
+    
+    if ((inGroup)  && (Tbl_TableReadNumOutputs(tbl) > 1)) {
+      (void) fprintf(vis_stderr,
+                     "WARNING: multi-output table %s moved to group %s\n",
+                     Var_VariableReadName(var), group->name);
+    }
+  }
+  /* If outputs of a subckt are in a group, the subckt moves
+     into the group */
+  
+  Hrc_ModelForEachSubckt(CurModel, sgen, subcktName, subckt) {
+    Var_Variable_t* outVar = NIL(Var_Variable_t); /* initialize to pacify */
+    if (! st_lookup(group->Subcircuits, (char*) subckt, &inGroup)) {
+      subOutputs = Hrc_SubcktReadActualOutputVars(subckt);
+      Rst_VarForEachVarInArray(subOutputs, i, outVar) {
+        if (st_lookup(group->Vars, (char*) outVar, &inGroup)) {
+          break;
+        }
+      }
+      if (i < array_n(subOutputs)) {
+        Rst_VarForEachVarInArray(subOutputs, j, var) {
+          if (! st_lookup(group->Vars, (char*) var, &inGroup)) {
+            st_insert(group->Vars, (char*) var, (char*) (long) 1);
+          }
+        }
+        st_insert(group->Subcircuits, (char*) subckt, (char*) (long) 1);
+        (void) fprintf(vis_stderr,
+                       "Warning: instance %s becomes member of group %s",
+                       subcktName, group->name);
+        (void) fprintf(vis_stderr, " because of output variable %s\n",
+                       Var_VariableReadName(outVar));
+      }
+    }
+  }
+  
+  /* Group Outputs: Scan parent outputs for group vars. Scan non-group
+     component (Subcircuits/Latches/Tables) inputs for group vars */
+
+  Hrc_NodeForEachFormalOutput(curMaster, i, var) {
+    if ((st_lookup(group->Vars, (char*) var, &inGroup)) &&
+        (! st_lookup(group->Outputs, (char*) var, &inGroup))) {
+      st_insert(group->Outputs, (char*) var, (char*) (long) 1);
+    }
+  }
+
+  Hrc_ModelForEachSubckt(CurModel, sgen, subcktName, subckt) {
+    if (! st_lookup(group->Subcircuits, (char*) subckt, &inGroup)) {
+      Rst_VarForEachVarInArray(Hrc_SubcktReadActualInputVars(subckt), i, var) {
+        if ((st_lookup(group->Vars, (char*) var, &inGroup)) &&
+            (! st_lookup(group->Outputs, (char*) var, &inGroup))) {
+            st_insert(group->Outputs, (char*) var, (char*) (long) 1);
+        }
+      }
+    }
+  }
+  Hrc_NodeForEachLatch(curMaster, sgen, latchName, latch) {
+    if (! st_lookup(group->Latches, (char*) latch, &inGroup)) {
+      var = Hrc_LatchReadInput(latch);
+      if ((st_lookup(group->Vars, (char*) var, &inGroup)) &&
+          (! st_lookup(group->Outputs, (char*) var, &inGroup))) {
+        st_insert(group->Outputs, (char*) var, (char*) (long) 1);
+      }
+    }
+  }
+  Hrc_NodeForEachNameTable(curMaster, i, tbl) {
+    if (! st_lookup(group->Tables, (char*) tbl, &inGroup)) {
+      Tbl_TableForEachInputVar(tbl, j, var) {
+        if ((st_lookup(group->Vars, (char*) var, &inGroup)) &&
+            (! st_lookup(group->Outputs, (char*) var, &inGroup))) {
+          st_insert(group->Outputs, (char*) var, (char*) (long) 1);
+        }
+      }
+    }
+  }
+  
+  /* Group Inputs:  Scan group subcomponent inputs for non-group vars */
+
+  /* Formal inputs are never vars of a group.  Thus, they are always
+     non-group vars when are inputs to group subcomponents, and are
+     caught by the code below*/
+  
+  Hrc_ModelForEachSubckt(CurModel, sgen, subcktName, subckt) {
+    if (st_lookup(group->Subcircuits, (char*) subckt, &inGroup)) {
+      Rst_VarForEachVarInArray(Hrc_SubcktReadActualInputVars(subckt), i, var) {
+        if ((! st_lookup(group->Vars, (char*) var, &inGroup)) &&
+            (! st_lookup(group->Inputs, (char*) var, &inGroup))) {
+          st_insert(group->Inputs, (char*) var, (char*) (long) 1);
+        }
+      }
+    }
+  }
+  Hrc_NodeForEachLatch(curMaster, sgen, latchName, latch) {
+    if (st_lookup(group->Latches, (char*) latch, &inGroup)) {
+      var = Hrc_LatchReadInput(latch);
+      if ((! st_lookup(group->Vars, (char*) var, &inGroup)) &&
+          (! st_lookup(group->Inputs, (char*) var, &inGroup))) {
+        st_insert(group->Inputs, (char*) var, (char*) (long) 1);
+      }
+      /* Reset table here */
+      tbl = Hrc_LatchReadResetTable(latch);
+      Tbl_TableForEachInputVar(tbl, j, var) {
+        if (! st_lookup(group->Vars, (char*) var, &inGroup))
+          st_insert(group->Vars, (char*) var, (char*) (long) 1);
+      }
+    }
+  }
+  Hrc_NodeForEachNameTable(curMaster, tblIndx, tbl) {
+    if (st_lookup(group->Tables, (char*) tbl, &inGroup)) {
+      Tbl_TableForEachInputVar(tbl, j, var) {
+        if ((! st_lookup(group->Vars, (char*) var, &inGroup)) &&
+            (! st_lookup(group->Inputs, (char*) var, &inGroup))) {
+          st_insert(group->Inputs, (char*) var, (char*) (long) 1);
+        }
+      }
+    }
+  }
+
+  return group;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Takes a Group partitioning of a Node and builds a new
+  Model reflecting that partition.]
+
+  Description [Called by the main routine Rst_CommandGroupComponents,
+  this routine builds the models corresponding to each group in
+  GroupArray, builds a new Node instantiating these models as
+  subckts.  Note that one can build a Group using RstGroupComponents]
+
+  SideEffects [Allocates a new Hrc_Model_t.]
+
+  SeeAlso     [RstGroupComponents, RstGroupBuildModel, RstCreateParentGroup,
+  Rst_CommandGroupComponents, Rst_GroupRestructureNode]
+
+******************************************************************************/
+Hrc_Model_t*
+Rst_GroupRestructureModel(
+  Hrc_Manager_t* Hmgr,
+  Hrc_Model_t* ParentModel,
+  array_t* GroupArray)
+{
+  int i, j;
+  char *newModelName;
+  st_generator *sgen;
+  Var_Variable_t *var, *newVar;
+  Hrc_Model_t *newModel, *newParentModel;
+  Hrc_Node_t *newMaster;
+  Rst_Group_t *group, *parentGroup;
+  st_table *varForwPtr;
+  array_t *newModelArray, *newMasterArray, *newNodeArray;
+
+  for (i = 0; i < array_n(GroupArray); i++) {
+    group = array_fetch(Rst_Group_t*, GroupArray, i);
+#ifdef RST_GROUP_DEBUG
+    RstGroupPrint(group);
+#endif
+  }
+  /* Check group components for disjointness */
+
+  if (RstGroupDisjointCheck(GroupArray))
+    return 0;
+
+  /* Construct a level of hierarchy for each group */
+
+  newModelArray = array_alloc(Hrc_Model_t*, array_n(GroupArray));
+  newMasterArray = array_alloc(Hrc_Node_t*, array_n(GroupArray));
+  newNodeArray = array_alloc(Hrc_Node_t*, array_n(GroupArray));
+  
+  for (i = 0; i < array_n(GroupArray); i++) {
+    group = array_fetch(Rst_Group_t*, GroupArray, i);
+    newModel = RstGroupBuildModel(Hmgr, group);
+    if (! newModel) {
+      return 0;
+    }
+    newMaster = Hrc_ModelReadMasterNode(newModel);
+    array_insert(Hrc_Model_t*, newModelArray, i, newModel);
+    array_insert(Hrc_Node_t*, newMasterArray, i, newMaster);
+  }
+
+  /* Build the new parent hierarchy */
+  
+  newModelName = RstGroupNewParentName(Hrc_ModelReadName(ParentModel));
+  parentGroup = RstCreateParentGroup(Hmgr, ParentModel, newModelName,
+                                      GroupArray);
+  FREE(newModelName);
+  if (! parentGroup) {
+    return 0;
+  }
+#ifdef RST_GROUP_DEBUG
+  RstGroupPrint(parentGroup);
+#endif
+  newParentModel = RstGroupBuildModel(Hmgr, parentGroup);
+
+  /* Computing actuals:  Group IO vars USED to be in the old parent.
+     1) lookup what the new IO vars used to be in the old parent
+     2) In the old parent, find the correspond new parent vars
+     */
+  
+  /* Build Table: Parent to New Parent Vars, by reversing back pointers */
+
+  varForwPtr = st_init_table(st_ptrcmp, st_ptrhash);
+  st_foreach_item(parentGroup->VarBackPtr, sgen, &newVar, &var) {
+    st_insert(varForwPtr, (char*) var, (char*) newVar);
+  }
+
+  /* Free parent group now */
+  RstGroupFree(parentGroup); parentGroup = 0;
+  
+  /* Instantiate groups as subckts */
+
+  for (i = 0; i < array_n(GroupArray); i++) {
+    array_t* actualInputArray, *actualOutputArray;
+
+    group = array_fetch(Rst_Group_t*, GroupArray, i);
+    newModel = array_fetch(Hrc_Model_t*, newModelArray, i);
+    newMaster = Hrc_ModelReadMasterNode(newModel);
+
+    actualInputArray =
+      Rst_VartoVarLookup(Hrc_NodeReadFormalInputs(newMaster),
+                         group->VarBackPtr, varForwPtr);
+    actualOutputArray =
+      Rst_VartoVarLookup(Hrc_NodeReadFormalOutputs(newMaster),
+                         group->VarBackPtr, varForwPtr);
+
+    Hrc_ModelAddSubckt(newParentModel, newModel, group->name, 
+                       actualInputArray, actualOutputArray);
+    Rst_VarForEachVarInArray(actualInputArray, j, var) {
+      Var_VariableSetSI(var);
+    }
+    Rst_VarForEachVarInArray(actualOutputArray, j, var) {
+      Var_VariableSetSO(var);
+    }
+  }
+  array_free(newModelArray);
+  array_free(newMasterArray);
+  array_free(newNodeArray);
+
+  st_free_table(varForwPtr);
+  return newParentModel;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Takes a Group partitioning of a Node and replaces Node
+  with the partitioned Node.]
+
+  Description [Called by the main routine Rst_CommandGroupComponents,
+  this routine builds the models corresponding to each group in
+  GroupArray, builds a new Node instantiating these models as
+  subckts.  Note that one can build a Group using RstGroupComponents]
+
+  SideEffects [Allocates a new Hrc_Node_t and replaces the CurNode with it.]
+
+  SeeAlso     [RstGroupComponents, RstGroupBuildModel, RstCreateParentGroup,
+  Rst_CommandGroupComponents]
+
+******************************************************************************/
+Hrc_Node_t*
+Rst_GroupRestructureNode(
+  Hrc_Manager_t* Hmgr,
+  Hrc_Node_t* CurNode,
+  array_t* GroupArray)
+{
+  int retVal;
+#ifdef RST_GROUP_DEBUG
+  st_generator* sgen;
+  char* childName;
+  Hrc_Node_t *child;
+#endif  
+  Hrc_Model_t *newParentModel;
+  Hrc_Node_t *newNode = 0;
+  Hrc_Model_t* CurModel=
+    Hrc_ManagerFindModelByName(Hmgr, Hrc_NodeReadModelName(CurNode));
+
+  newParentModel = Rst_GroupRestructureModel(Hmgr, CurModel, GroupArray);
+  if (newParentModel) {
+
+    newNode = Hrc_ModelCreateHierarchy(Hmgr, newParentModel,
+                                       Hrc_NodeReadInstanceName(CurNode));
+
+#ifdef RST_GROUP_DEBUG
+    (void) fprintf(vis_stderr, "Checking New Node\n");
+    assert(Hrc_NodeCheckVariableConsistency(newNode));
+    (void) fprintf(vis_stderr, "Checking Subcircuits\n");
+    Hrc_NodeForEachChild(newNode, sgen, childName, child) {
+      assert(Hrc_NodeCheckVariableConsistency(child));
+    }
+#endif
+  
+    retVal = Hrc_TreeReplace(CurNode, newNode);
+    assert(retVal);
+    Hrc_ManagerSetCurrentNode(Hmgr, newNode);
+  }
+  return newNode;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a model of the combinational portion of a Node.]
+
+  Description [Finds the combinational logic of a Model and groups it into
+  a new Model.]
+
+  SideEffects [Allocates a new Hrc_Model_t.]
+
+  SeeAlso     [RstGroupComponents, Rst_GroupRestructureNode]
+
+******************************************************************************/
+Hrc_Model_t*
+Rst_GroupGroupCombLogic(
+  Hrc_Manager_t* Hmgr,
+  Hrc_Model_t* CurModel)
+{
+  long inGroup;
+  int tblIndx, varIndx;
+  Var_Variable_t *var;
+  Tbl_Table_t* tbl;
+  array_t* varArray = array_alloc(Var_Variable_t*, 0);
+  Rst_Group_t *group;
+  st_table *tableOutputs = st_init_table(st_ptrcmp, st_ptrhash);
+  Hrc_Node_t *curMaster;
+  Hrc_Model_t* newModel;
+
+  /* Perhaps this is better done with the NameTables so that we drop
+     subckts from inclusion */
+
+  curMaster = Hrc_ModelReadMasterNode(CurModel);
+
+  Hrc_NodeForEachNameTable(curMaster, tblIndx, tbl) {
+    Tbl_TableForEachOutputVar(tbl, varIndx, var) {
+      if (! st_lookup(tableOutputs, (char*) var, &inGroup)) {
+        st_insert(tableOutputs, (char*) var, (char*) (long) 1);
+        array_insert_last(Var_Variable_t*, varArray, var);
+      }
+    }
+  }
+  st_free_table(tableOutputs);
+  group = RstGroupComponents(CurModel,
+                              util_strcat3(Hrc_ModelReadName(CurModel),
+                                           "_comb", ""),
+                              varArray, NULL);
+  array_free(varArray);
+
+  if (group) {
+    array_t *groupArray = array_alloc(Rst_Group_t*, 1);
+    array_insert_last(Rst_Group_t*, groupArray, group);
+    newModel = Rst_GroupRestructureModel(Hmgr, CurModel, groupArray);
+    array_free(groupArray);
+    return newModel;
+  }
+  return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a model of the latch portion of a Node.]
+
+  Description [Finds the latches of a Model and groups them into a new Model.]
+
+  SideEffects [Allocates a new Hrc_Model_t.]
+
+  SeeAlso     [RstGroupComponents, Rst_GroupRestructureNode]
+
+******************************************************************************/
+Hrc_Model_t*
+Rst_GroupGroupLatches(
+  Hrc_Manager_t* Hmgr,
+  Hrc_Model_t* CurModel)
+{
+  char *latchName;
+  st_generator *sgen;
+  Hrc_Latch_t *latch;
+  array_t* varArray = array_alloc(Var_Variable_t*, 0);
+  Rst_Group_t *group;
+  Hrc_Node_t* curMaster = Hrc_ModelReadMasterNode(CurModel);
+  Hrc_Model_t* newModel;
+
+  Hrc_NodeForEachLatch(curMaster, sgen, latchName, latch) {
+    array_insert_last(Var_Variable_t*, varArray, Hrc_LatchReadOutput(latch));
+  }
+  
+  group = RstGroupComponents(CurModel,
+                              util_strcat3(Hrc_ModelReadName(CurModel),
+                                           "_latch", ""),
+                              varArray, NULL);
+  array_free(varArray);
+
+  if (group) {
+    array_t *groupArray = array_alloc(Rst_Group_t*, 1);
+    array_insert_last(Rst_Group_t*, groupArray, group);
+    newModel = Rst_GroupRestructureModel(Hmgr, CurModel, groupArray);
+    array_free(groupArray);
+    return newModel;
+  }
+  return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis [This function is the command-line interface for the user
+  to specify groups into which to partition the components of the
+  current level of hierarchy.]
+
+  CommandName [decompose_child]
+
+  CommandSynopsis [Partitions Node components into child nodes. ]
+
+  CommandArguments[-n  &lt;groupname&gt; \[-f &lt;filename&gt;\]
+  \[-c\] \[-v\] \[-t\] \[-l\] \[&lt;components&gt;\]]
+  
+  CommandDescription [This command partitions the current Node into
+  several new children nodes according to user-specified groups.
+
+  The user may specify several groups by name \[-n\] sequentially on
+  the command line.  Within each group a list of components (either
+  variables or child nodes) can be placed.  The flags \[-c\] \[-v\]
+  toggle whether element names are interpreted as child instances or
+  variables (default is instances \[-c\]).  Element names can be
+  loaded from a file as well using the \[-f\] flag. <p>
+
+  By specifying a variable to be grouped, any object (e.g., Table,
+  Latch, Child) that PRODUCES that variable is included in the newly
+  created child node for that group.<p>
+
+
+  Command options:<p>  
+
+  <dl>
+  <dt> -n &lt;groupname&gt;
+  <dd> Define new group
+  </dl>
+
+  <dl>
+  <dt> -f &lt;filename&gt;
+  <dd> Load names from file
+  </dl>
+  <dl>
+
+  <dt> -c 
+  <dd> Interpret names that follow as child instances to group
+  </dl>
+
+  <dt> -v
+  <dd> Interpret names that follow as variables
+  </dl>
+
+  <dt> -l
+  <dd> Include all latch output nodes (and therefore latches) in group
+  </dl>
+
+  <dt> -t
+  <dd> Include all combinational tables in group.
+  </dl>
+
+  Examples:<p>
+             decompose_child -n c1 -v G1 G2 -n c2 IA IB<p>
+
+             Place variables G1 and G2 into a new child node c1 and
+             child nodes IA and IB into a new child node c2.<p>
+
+  Example:<p>
+  decompose_child -n ckt_inst child1 -f myinstances -v var1 -n latch_inst -l <p>
+
+  This groups the subckts child1 and those listed in the file myinstances,
+  as well as the variable var1 into a subckt called 'ckt_inst'. It
+  also groups all the latches into a subckt called 'latch_inst'.]
+
+  SideEffects [Replaces current Node with a new Node containing
+  children representing the partition.]
+
+******************************************************************************/
+int
+Rst_CommandGroupComponents(
+  Hrc_Manager_t** Hmgr,
+  int  argc,
+  char ** argv)
+{
+  enum { SUBCKT_GROUP, VAR_GROUP } readType = SUBCKT_GROUP;
+  int c, i, retVal, tblIndx;
+  st_generator *sgen;
+  Rst_Group_t* group;
+  Var_Variable_t* var;
+  Hrc_Subckt_t* child;
+  char *fileName, *varName, *childName, *latchName;
+  char* groupName = 0;
+  array_t *vars = 0, *children = 0;
+  Hrc_Latch_t* latch;
+  Tbl_Table_t* tbl;
+  array_t* nameArray = 0;
+  array_t* groupArray = array_alloc(Rst_Group_t*, 1);
+  Hrc_Node_t* curNode = Hrc_ManagerReadCurrentNode(*Hmgr);
+  Hrc_Node_t* curMaster;
+  FILE* fp;
+  Hrc_Model_t* CurModel;
+  
+  if (! curNode) {
+    /* No node has been read in. The only sane thing we
+       support is the -h option */
+    array_free(groupArray); groupArray = 0;
+    util_getopt_reset();
+    if ((c = util_getopt(argc,argv,"h")) !=  EOF) {
+      goto usage;
+    }
+    (void) fprintf(vis_stderr, "ERROR: no current Node\n");
+    return 1;
+  }
+
+  CurModel=
+      Hrc_ManagerFindModelByName(Hrc_NodeReadManager(curNode),
+                                 Hrc_NodeReadModelName(curNode));
+  curMaster = Hrc_ModelReadMasterNode(CurModel);
+
+  /* This command processing loop is conceptually simple, but almost
+    'goto' like and needs explanation.  The command line is a sequence
+    of groups between which are specified component names to group.
+
+    A group is started with a Naming operation '-n'. We get a list of
+    component names to group either from the command line or from a
+    file.  Names can be anywhere on the command line (except between
+    -n/-f and their argument).  The names are interpreted as Variables
+    or Children depending on the last -v or -c flag.  Children is the
+    default setting on entry.
+
+    After every option, we can read more names off command line, so we
+    drop into this mode after completing a -n <name> or -f <file>
+    operation.  This means we always drop into the outer 'default'.
+
+     The goal is to collect a set of Variable and Child names for each
+     Group Name specified.  */
+  
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "n:f:cvtlh")) != EOF) {
+    switch(c) {
+        case 'n':               /* expects a Name arg */
+        case 'f':               /* expects a filename arg */
+          switch(c) {
+              case 'n':         /* Name a new group */
+                if (groupName != NULL) {
+                  group = RstGroupComponents(CurModel, groupName,
+                                              vars, children);
+                  array_free(vars); vars = 0;
+                  array_free(children); children = 0;
+                  FREE(groupName);
+                  if (group) {
+                    array_insert_last(Rst_Group_t*, groupArray, group);
+                  } else {
+                    (void) fprintf(vis_stderr,
+                                   "Warning: Incomplete group %s -- ignored\n",
+                                   groupName);
+                    RstGroupFree(group); group = 0;
+                  }
+                }
+                vars = array_alloc(Var_Variable_t*, 0);
+                children = array_alloc(Hrc_Subckt_t*, 0);
+                groupName = util_strcat3(argv[util_optind -1], "","");
+                break;
+              case 'f':         /* Read component names from file */
+                fileName = argv[util_optind - 1];
+                fp = Cmd_FileOpen(util_optarg, "r", &fileName, 1);
+                if (fp == NIL(FILE)) {
+                  (void) fprintf(vis_stderr,
+                                 "Could not open file %s\n", fileName);
+                  return 1;
+                }
+                nameArray = array_alloc(char*, 0);
+                Rst_LoadNameArrayFromFile(nameArray, fp);
+                fclose(fp);
+                break;
+          }
+          /* WE ALWAYS DROP IN HERE ON EVERY FLAG */
+        default:
+          if (! groupName && (c != 'h')) {
+            (void) fprintf(vis_stderr, "ERROR: Group not defined yet\n");
+            goto usage;
+          }
+          if (! nameArray) nameArray = array_alloc(char*, 0);
+          switch(c) {
+              case 'n':
+              case 'f':
+                break;
+              case 'c': readType = SUBCKT_GROUP; break;
+              case 'v': readType = VAR_GROUP; break;
+              case 'l':
+                /* Put latch ouput vars into group*/
+                Hrc_NodeForEachLatch(curMaster, sgen, latchName, latch) {
+                  var = Hrc_LatchReadOutput(latch);
+                  array_insert_last(Var_Variable_t*, vars, var);
+                }
+                break;
+              case 't':
+                /* Put table ouput vars into group*/
+                Hrc_NodeForEachNameTable(curMaster, tblIndx, tbl) {
+                  Tbl_TableForEachOutputVar(tbl, i, var) {
+                      array_insert_last(Var_Variable_t*, vars, var);
+                  }
+                }
+                break;
+              default: goto usage;
+          }
+          /* Grab any more names off the command line, appending if
+             possible to nameArray */
+          
+          Rst_GetNamesUntilNextOption(nameArray, argc, argv);
+
+          /* We store names read as either variable names or child names */
+          
+          switch(readType) {
+              case VAR_GROUP:
+                for (i=0; i < array_n(nameArray); i++) {
+                  varName = array_fetch(char*, nameArray, i);
+                  var = Hrc_NodeFindVariableByName(curMaster, varName);
+                  if (var) {
+                    array_insert_last(Var_Variable_t*, vars, var);
+                  } else {
+                    (void) fprintf(vis_stderr, "Could not find variable %s\n",
+                                   varName);
+                  }
+                }
+                break;
+              case SUBCKT_GROUP:
+                for (i=0; i < array_n(nameArray); i++) {
+                  childName = array_fetch(char*, nameArray, i);
+                  retVal = st_lookup(Hrc_ModelReadSubcktTable(CurModel),
+                                     childName, &child);
+                  if (retVal) {
+                    array_insert_last(Hrc_Subckt_t*, children, child);
+                  } else {
+                    (void) fprintf(vis_stderr, "Could not find instance %s\n",
+                                   childName);
+                  }
+                }
+                break;
+              default:          /* Unreached */
+                break;
+          }
+          break;
+    }
+    for (i=0; i < array_n(nameArray); i++) {
+      varName = array_fetch(char*, nameArray, i);
+      FREE(varName);
+    }
+    array_free(nameArray); nameArray = 0;
+  }
+  if (groupName) {
+    group = RstGroupComponents(CurModel, groupName, vars, children);
+    if (group) 
+      array_insert_last(Rst_Group_t*, groupArray, group);
+    else
+      (void) fprintf(vis_stderr, "Incomplete group %s\n", groupName);
+    array_free(vars); vars = 0;
+    array_free(children); children = 0;
+    FREE(groupName);
+  }
+
+  if (array_n(groupArray) > 0) {
+    Rst_GroupRestructureNode(*Hmgr, curNode, groupArray);
+    for (i=0; i < array_n(groupArray); i++) {
+      group = array_fetch(Rst_Group_t*, groupArray, i);
+      RstGroupFree(group);
+    }
+    array_free(groupArray); groupArray = 0;
+  } else {
+    (void) fprintf(vis_stderr, "ERROR: no groups defined\n");
+    array_free(groupArray);
+    return 1;
+  }
+  return 0;                     /* normal exit */
+
+usage:
+   if (vars) array_free(vars); vars = 0;
+   if (children) array_free(children); children = 0;
+  FREE(groupName); groupName = 0;
+  array_free(nameArray); nameArray = 0;
+  array_free(groupArray);
+  (void) fprintf(vis_stderr, "usage: decompose_child -n <groupname>");
+  (void) fprintf(vis_stderr, " [-f <filename>] [-c] [-v] [<names>] [-t] [-l] [-h] \n");
+  (void) fprintf(vis_stderr, "   -n\t\tName of new child group \n");
+  (void) fprintf(vis_stderr, "   -f\t\tLoad names from file \n");
+  (void) fprintf(vis_stderr, "   -c\t\tGroup by children toggle (default)\n");
+  (void) fprintf(vis_stderr, "   -v\t\tGroup by variable toggle \n");
+  (void) fprintf(vis_stderr, "   -l\t\tGroup latches\n");
+  (void) fprintf(vis_stderr, "   -t\t\tGroup combinational logic tables \n");
+  (void) fprintf(vis_stderr, "   -h\t\thelp \n");
+  return 1;                     /* error exit */
+
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates a group.]
+
+  Description [Initializes all tables for collecting components of a
+  group for node partitioning.  The VarBackPtr table stores pointers
+  from newly allocated variables to their original variables in the
+  Node being partitioned.]
+
+  SideEffects [Creates a new Rst_Group_t.]
+
+  SeeAlso     [RstGroupFree, RstGroupPrint]
+
+******************************************************************************/
+Rst_Group_t*
+RstGroupAlloc(char* Name)
+{
+  Rst_Group_t* group = ALLOC(Rst_Group_t, 1);
+
+  group->Vars = st_init_table(st_ptrcmp, st_ptrhash);
+  group->Latches = st_init_table(st_ptrcmp, st_ptrhash);
+  group->Tables = st_init_table(st_ptrcmp, st_ptrhash);
+  group->Subcircuits = st_init_table(st_ptrcmp, st_ptrhash);
+  group->Inputs = st_init_table(st_ptrcmp, st_ptrhash);
+  group->Outputs = st_init_table(st_ptrcmp, st_ptrhash);
+  group->VarBackPtr = st_init_table(st_ptrcmp, st_ptrhash);
+  group->name = ALLOC(char, strlen(Name) + 1);
+  strcpy(group->name, Name);
+  return group;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a group.]
+
+  Description [Frees all tables associated with a group.
+  Frees the name stored with the group.]
+
+  SideEffects []
+
+  SeeAlso     [RstGroupAlloc, RstGroupPrint]
+
+******************************************************************************/
+void
+RstGroupFree(Rst_Group_t* Group)
+{
+  st_free_table(Group->Vars);
+  st_free_table(Group->Latches);
+  st_free_table(Group->Tables);
+  st_free_table(Group->Subcircuits);
+  st_free_table(Group->Inputs);
+  st_free_table(Group->Outputs);
+  st_free_table(Group->VarBackPtr);
+  FREE(Group->name);
+  FREE(Group);                  /* Watch for dangling references  */
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a new name for the node being partitioned.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+char*
+RstGroupNewParentName(
+  char* Name)
+{
+  char* newName = util_strcat3(Name, "_N", "");
+  return newName;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the tables of a group for debug purposes.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+RstGroupPrint(
+  Rst_Group_t* group)
+{
+  st_generator* sgen;
+  Var_Variable_t* var;
+  Hrc_Subckt_t* subckt;
+  Hrc_Latch_t* latch;
+  
+  printf("GROUP: %s\n\tInputs:\t", group->name);
+  st_foreach_item(group->Inputs, sgen, &var, NIL(char *)) {
+    printf("%s ", Var_VariableReadName(var));
+  }
+  printf("\n\tOutputs:\t");
+  st_foreach_item(group->Outputs, sgen, &var, NIL(char *)) {
+    printf("%s ", Var_VariableReadName(var));
+  }
+  printf("\n\tSubcircuits:\t");
+  st_foreach_item(group->Subcircuits, sgen, &subckt, NIL(char *)) {
+    printf("%s ", Hrc_SubcktReadInstanceName(subckt));
+  }
+  printf("\n\tLatches:\t");
+  st_foreach_item(group->Latches, sgen, &latch, NIL(char *)) {
+    printf("%s ", Var_VariableReadName(Hrc_LatchReadOutput(latch)));
+  }
+  printf("\n\tVars:\t");
+  st_foreach_item(group->Vars, sgen, &var, NIL(char *)) {
+    printf("%s ", Var_VariableReadName(var));
+  }
+  printf("\n");
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Makes sure groups are disjoint.]
+
+  Description [Checks that each Variable, Table, Latch, and Subcircuit
+  is assigned to one and only one group.]
+
+  SideEffects []
+
+  SeeAlso     [Rst_GroupBuildModel]
+
+******************************************************************************/
+int
+RstGroupDisjointCheck(
+  array_t* GroupArray)
+{
+  int i, j, retVal;
+  st_generator *sgen;
+  Hrc_Subckt_t* subckt;
+  Rst_Group_t* group1, *group2;
+  Hrc_Latch_t* latch;
+  Tbl_Table_t* tbl;
+  Var_Variable_t* var;
+
+  for (i = 0; i < array_n(GroupArray); i++) {
+      group1 = array_fetch(Rst_Group_t*, GroupArray, i);
+    for (j = i + 1; j < array_n(GroupArray); j++) {
+      group2 = array_fetch(Rst_Group_t*, GroupArray, j);
+      
+      st_foreach_item(group1->Subcircuits, sgen, &subckt, NULL) {
+        retVal = st_lookup(group2->Subcircuits, (char*) subckt, NIL(char *));
+        if (retVal) {
+          (void) fprintf(vis_stderr,
+                         "ERROR: component %s assigned to groups %s and %s\n",
+                         Hrc_SubcktReadInstanceName(subckt),
+                         group1->name, group2->name);
+          return 1;
+        }
+      }
+      st_foreach_item(group1->Vars, sgen, &var, NULL) {
+        retVal = st_lookup(group2->Vars, (char*) var, NIL(char *));
+        if (retVal) {
+          (void) fprintf(vis_stderr,
+                         "ERROR: var %s assigned to groups %s and %s\n",
+                         Var_VariableReadName(var),
+                         group1->name, group2->name);
+          return 1;
+        }
+      }
+      st_foreach_item(group1->Tables, sgen, &tbl, NULL) {
+        retVal = st_lookup(group2->Tables, (char*) tbl, NIL(char *));
+        if (retVal) {
+          (void) fprintf(vis_stderr,
+                         "ERROR: table assigned to groups %s and %s\n",
+                         group1->name, group2->name);
+          return 1;
+        }
+      }
+      st_foreach_item(group1->Latches, sgen, &latch, NULL) {
+        retVal = st_lookup(group2->Latches, (char*) latch, NIL(char *));
+        if (retVal) {
+          (void) fprintf(vis_stderr,
+                         "ERROR: latch %s assigned to groups %s and %s\n",
+                         Var_VariableReadName(Hrc_LatchReadOutput(latch)),
+                         group1->name, group2->name);
+          return 1;
+        }
+      }
+    }
+  }
+  return 0;
+} 
+
+/**Function********************************************************************
+
+  Synopsis    [Creates the Parent Group.]
+
+  Description [Creates a special Group representing components of a
+  Node "left behind" by a partitioning of it's components into groups.
+  This takes special care because Vars have to remain in the parent if
+  they are on the interface of a Group or connect remaining components
+  of the Parent.]
+
+  SideEffects [Allocates a new Rst_Group_t]
+
+  SeeAlso     [RstGroupComponents, RstGroupBuildModel, Rst_GroupRestructureNode]
+
+******************************************************************************/
+Rst_Group_t*
+RstCreateParentGroup(
+  Hrc_Manager_t* Hmgr,
+  Hrc_Model_t* ParentModel,
+  char* NewModelName,
+  array_t* GroupArray)
+{
+  int i, j, tblIndx, varIndx;
+  long inGroup;  
+  char *latchName, *subcktName, *varName;
+  st_generator* sgen;
+  Var_Variable_t* var;
+  Tbl_Table_t* tbl;
+  Hrc_Latch_t* latch;
+  Hrc_Subckt_t *subckt;
+  Hrc_Node_t *parentMaster;
+  Rst_Group_t *group, *parentGroup;
+  array_t* subOutputs;
+
+  /* Build a parent group */
+
+  parentGroup = RstGroupAlloc(NewModelName);
+  parentMaster = Hrc_ModelReadMasterNode(ParentModel);
+
+  /* IO of latches of parent group are parent group vars */
+  
+  Hrc_NodeForEachLatch(parentMaster, sgen, latchName, latch) {
+    for (i = 0; i < array_n(GroupArray); i++) {
+      group = array_fetch(Rst_Group_t*, GroupArray, i);
+      if (st_lookup(group->Latches, (char*) latch, &inGroup)) {
+        break;
+      }
+    }
+    if (i >= array_n(GroupArray)) {
+      st_insert(parentGroup->Latches, (char*) latch, (char*) (long) 1);
+      var = Hrc_LatchReadInput(latch);
+      if (! st_lookup(parentGroup->Vars, (char*) var, &inGroup)) {
+        st_insert(parentGroup->Vars, (char*) var, (char*) (long) 1);
+      }
+      var = Hrc_LatchReadOutput(latch);
+      if (! st_lookup(parentGroup->Vars, (char*) var, &inGroup)) {
+        st_insert(parentGroup->Vars, (char*) var, (char*) (long) 1);
+      }
+    }
+  }
+
+  /* IO of parent group tables (that stay in parent) are parent group vars */
+  
+  Hrc_NodeForEachNameTable(parentMaster, tblIndx, tbl) {
+    for (i = 0; i < array_n(GroupArray); i++) {
+      group = array_fetch(Rst_Group_t*, GroupArray, i);
+      if (st_lookup(group->Tables, (char*) tbl, &inGroup)) {
+        break;
+      }
+    }
+    if (i >= array_n(GroupArray)) {
+      /* Table stays in parent */
+      st_insert(parentGroup->Tables, (char*) tbl, (char*) (long) 1);
+      Tbl_TableForEachInputVar(tbl, varIndx, var) {
+        if (! st_lookup(parentGroup->Vars, (char*) var, &inGroup)) {
+          st_insert(parentGroup->Vars, (char*) var, (char*) (long) 1);
+        }
+      }
+      Tbl_TableForEachOutputVar(tbl, varIndx, var) {
+        if (! st_lookup(parentGroup->Vars, (char*) var, &inGroup)) {
+          st_insert(parentGroup->Vars, (char*) var, (char*) (long) 1);
+        }
+      }
+    }
+  }
+  
+  /* IO of groups are group Vars of the parent.  Note that inputs are
+   never group vars of a group EXCEPT in the case of the parent group */
+  
+  Hrc_NodeForEachVariable(parentMaster, sgen, varName, var) {
+    if (! st_lookup(parentGroup->Vars, (char*) var, &inGroup)) {
+      for (i = 0; i < array_n(GroupArray); i++) {
+        group = array_fetch(Rst_Group_t*, GroupArray, i);
+        if ((st_lookup(group->Inputs, (char*) var, &inGroup)) ||
+            (st_lookup(group->Outputs, (char*) var, &inGroup))) {
+          break;
+        }
+      }
+      if (i < array_n(GroupArray)) {
+        st_insert(parentGroup->Vars, (char*) var, (char*) (long) 1);
+      }
+    }
+  }
+
+  /* All formal IO of old parent remains part of the parent group */
+  
+  Hrc_NodeForEachFormalInput(parentMaster, i, var)
+    st_insert(parentGroup->Inputs, (char*) var, (char*) (long) 1);
+
+  Hrc_NodeForEachFormalOutput(parentMaster, i, var)
+    st_insert(parentGroup->Outputs, (char*) var, (char*) (long) 1);
+
+  /* Outputs of subckts of parent group are parent group vars
+   We do this last to catch this possible dangling input scenario*/
+  
+  Hrc_ModelForEachSubckt(ParentModel, sgen, subcktName, subckt) {
+    for (i = 0; i < array_n(GroupArray); i++) {
+      group = array_fetch(Rst_Group_t*, GroupArray, i);
+      if (st_lookup(group->Subcircuits, (char*) subckt, &inGroup)) {
+        break;
+      }
+    }
+    if (i >= array_n(GroupArray)) {
+      st_insert(parentGroup->Subcircuits, (char*) subckt, (char*) (long) 1);
+      subOutputs = Hrc_SubcktReadActualOutputVars(subckt);
+      Rst_VarForEachVarInArray(subOutputs, j, var) {
+        if (! st_lookup(parentGroup->Vars, (char*) var, &inGroup)) {
+          st_insert(parentGroup->Vars, (char*) var, (char*) (long) 1);
+        }
+      }
+      /* FIXME: Possible bug: inputs are caught because they are
+         outputs of other components.  But a dangling input (ie, one
+         with no connection to anything) might get dropped. But adding
+         an input var might cause it's driving component to be
+         incorporated!  We opt for a warning here.  */
+      /* FIXME: Hack-using same array */
+      subOutputs = Hrc_SubcktReadActualInputVars(subckt); 
+      Rst_VarForEachVarInArray(subOutputs, j, var) {
+        if ((! st_lookup(parentGroup->Vars, (char*) var, &inGroup)) &&
+            (! st_lookup(parentGroup->Inputs, (char*) var, &inGroup))) {
+          (void) fprintf(vis_stderr,
+                         "Warning: subcircuit %s has input variable %s ",
+                         subcktName, Var_VariableReadName(var));
+          (void) fprintf(vis_stderr, "that has no driver in parent %s\n",
+                         parentGroup->name);
+        }
+      }
+    }
+  }
+  return parentGroup;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Debug routine for printing a Model.]
+
+  Description [Prints the IO and Vars of a new Model]
+
+  SideEffects []
+
+  SeeAlso     [RstGroupBuildModel]
+
+******************************************************************************/
+void
+RstModelPrint(
+  Hrc_Model_t* newModel)
+{
+  Hrc_Node_t* newMaster;
+  int i;
+  st_generator* sgen;
+  char* varName;
+  Var_Variable_t* var;
+
+  /* Print out new model  */
+  printf("Model %s\n", Hrc_ModelReadName(newModel));
+  newMaster = Hrc_ModelReadMasterNode(newModel);
+  printf("\tInputs :\t");
+  Rst_VarForEachVarInArray(Hrc_NodeReadFormalInputs(newMaster), i, var) {
+    printf("%s ", Var_VariableReadName(var));
+  }
+  printf("\n\tOutputs:\t");
+  Rst_VarForEachVarInArray(Hrc_NodeReadFormalOutputs(newMaster), i, var) {
+    printf("%s ", Var_VariableReadName(var));
+  }
+  printf("\n\tVars:\t");
+  Hrc_NodeForEachVariable(Hrc_ModelReadMasterNode(newModel),
+                          sgen, varName, var) {
+    printf("%s ", Var_VariableReadName(var));
+  }
+  printf("\n");
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Builds a Model from a Group.]
+
+  Description [Uses the tables of a group to replicate the portion of
+  a Node' structure contained by a Groups.  Duplicates Variables,
+  Tables, Latches, and Subcircuit Instances to create a Model reflecting
+  the structure of the Group.]
+
+  SideEffects [Allocates a new Hrc_Model_t.]
+
+  SeeAlso     [RstGroupComponents, Rst_GroupRestructureNode,
+  Rst_CommandGroupComponents]
+
+******************************************************************************/
+Hrc_Model_t*
+RstGroupBuildModel(
+  Hrc_Manager_t* Hmgr,
+  Rst_Group_t* Group)
+{
+  long inGroup;  
+  int retVal, i;
+  st_generator* sgen;
+  Var_Variable_t* var, *newVar, *newLatchInput, *newLatchOutput;
+  Tbl_Table_t* tbl, *newTbl;
+  Hrc_Latch_t* latch, *newLatch;
+  st_table* varForwPtr;
+  Hrc_Node_t* newMaster;
+  Hrc_Subckt_t *subckt;
+  Hrc_Model_t* subcktModel;
+  Hrc_Model_t* newModel = Hrc_ModelAlloc(Hmgr, Group->name);
+  array_t* actualInputArray, *actualOutputArray;
+
+  if (! newModel) {
+    (void) fprintf(vis_stderr, "ERROR: could not create Model %s\n",
+                   Group->name);
+    return 0;
+  }
+  
+  newMaster = Hrc_ModelReadMasterNode(newModel);
+  assert(newMaster);
+
+  varForwPtr = st_init_table(st_ptrcmp, st_ptrhash);
+  /* Add group's Variables: Inputs, Outputs */
+  st_foreach_item(Group->Inputs, sgen, &var, &inGroup) {
+    if (! st_lookup(varForwPtr, (char*) var, &newVar)) {
+      newVar = Var_VariableDup(var, newMaster);
+      Var_VariableResetAllTypes(newVar);
+      Var_VariableResetNumFanoutTables(newVar);
+      Hrc_NodeAddFormalInput(newMaster, newVar);
+      Var_VariableSetPI(newVar);
+      st_insert(Group->VarBackPtr, (char*) newVar, (char*) var);
+      st_insert(varForwPtr, (char*) var, (char*) newVar);
+    }
+  }
+  st_foreach_item(Group->Outputs, sgen, &var, &inGroup) {
+    if (! st_lookup(varForwPtr, (char*) var, &newVar)) {
+      newVar = Var_VariableDup(var, newMaster);
+      Var_VariableResetAllTypes(newVar);
+      Var_VariableResetNumFanoutTables(newVar);
+      Hrc_NodeAddFormalOutput(newMaster, newVar);
+      Var_VariableSetPO(newVar);
+      st_insert(Group->VarBackPtr, (char*) newVar, (char*) var);
+      st_insert(varForwPtr, (char*) var, (char*) newVar);
+    }
+  }
+  st_foreach_item(Group->Vars, sgen, &var, &inGroup) {
+    if (! st_lookup(varForwPtr, (char*) var, &newVar)) {
+      newVar = Var_VariableDup(var, newMaster);
+      Var_VariableResetAllTypes(newVar);
+      Var_VariableResetNumFanoutTables(newVar);
+      st_insert(Group->VarBackPtr, (char*) newVar, (char*) var);
+      st_insert(varForwPtr, (char*) var, (char*) newVar);
+    }
+  }
+      
+  /* Add group's Tables */
+  st_foreach_item(Group->Tables, sgen, &tbl, &inGroup) {
+    Hrc_NodeAddNameTable(newMaster, Tbl_TableDupAndSubstVars(tbl, varForwPtr));
+  }
+
+  /* Add group's Latches */
+  st_foreach_item(Group->Latches, sgen, &latch, &inGroup) {
+    retVal = st_lookup(varForwPtr, (char*) Hrc_LatchReadInput(latch),
+                       &newLatchInput);
+    assert(retVal);
+    retVal = st_lookup(varForwPtr, (char*) Hrc_LatchReadOutput(latch),
+                       &newLatchOutput);
+    assert(retVal);
+    
+    newLatch = Hrc_LatchCreate(newModel, newLatchInput, newLatchOutput);
+    assert(newLatch != NULL);
+    Var_VariableSetNS(newLatchInput);
+    Var_VariableSetPS(newLatchOutput);
+    
+    /* Duplicate and attach Reset Table */
+    tbl = Hrc_LatchReadResetTable(latch);
+    newTbl = Tbl_TableDupAndSubstVars(tbl, varForwPtr);
+    /* HACK: For some reason, we don't count latches in fanout count  */
+    retVal = Hrc_LatchSetResetTable(newLatch, newTbl);
+/*    newTbl = Hrc_LatchReadResetTable(latch); */
+    assert(retVal);
+    Tbl_TableForEachInputVar(tbl, i, var) {
+      retVal = st_lookup(varForwPtr, (char*) var, &newVar);
+      assert(retVal);
+      Var_VariableResetAllTypes(newVar);
+      Var_VariableResetNumFanoutTables(newVar);
+    }
+    Hrc_NodeAddLatch(newMaster, newLatch);
+  }
+
+  /* Add group's Subckts */
+  
+  st_foreach_item(Group->Subcircuits, sgen, &subckt, &inGroup) {
+    actualInputArray =
+      Rst_VartoVarLookup(Hrc_SubcktReadActualInputVars(subckt),
+                         varForwPtr, 0);
+    actualOutputArray =
+      Rst_VartoVarLookup(Hrc_SubcktReadActualOutputVars(subckt),
+                         varForwPtr, 0);
+    subcktModel = Hrc_SubcktReadModel(subckt);
+    Hrc_ModelAddSubckt(newModel, subcktModel,
+                       Hrc_SubcktReadInstanceName(subckt),
+                       actualInputArray, actualOutputArray);
+    Rst_VarForEachVarInArray(actualInputArray, i, var) {
+      Var_VariableSetSI(var);
+    }
+    Rst_VarForEachVarInArray(actualOutputArray, i, var) {
+      Var_VariableSetSO(var);
+    }
+  }
+
+  st_free_table(varForwPtr);
+
+#ifdef RST_GROUP_DEBUG
+  RstModelPrint(newModel);
+#endif
+  return newModel;
+}
+
+/* Overrides for Emacs so that we follow VIS tabbing style.
+ * Must remain at end of file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 2
+ * c-indent-level: 2
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -2
+ * c-argdecl-indent: 2
+ * c-comment-only-line-offset: 0
+ * c-label-offset: -4
+ * c-continued-statement-offset: 2
+ * c-continued-brace-offset: 0
+ * End: */
Index: vis_dev/vis-2.3/src/rst/rstInt.h
===================================================================
--- vis_dev/vis-2.3/src/rst/rstInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/rst/rstInt.h	(revision 14)
@@ -0,0 +1,104 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [rstInt.h]
+
+  PackageName [rst]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Sriram Rajamani (with many thanks to Yuji Kukimoto)]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#ifndef _RSTINT
+#define _RSTINT
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "rst.h"
+#include "cmd.h"
+#include <string.h>
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+typedef struct Rst_Group {
+  st_table *Vars,               /* Non-input Variables assigned to group */
+    *Subcircuits,               /* Subcircuits assigned / have group outputs */
+    *Latches,                   /* Latch output must be in group */
+    *Tables,                    /* Table output(s) must be in group */
+    *Inputs,                    /* Derived Inputs*/
+    *Outputs,                   /* Derived Outputs */
+    *VarBackPtr;                /* Table to original vars */
+  char* name;                   /* New model/instance name */
+} Rst_Group_t;
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN int RstCollapseNode(Hrc_Manager_t *hmgr, Hrc_Node_t *parent, Hrc_Node_t *child);
+EXTERN st_table * RstAddChildComponentsToNewModel(Hrc_Manager_t *hmgr, Hrc_Node_t *child, Hrc_Node_t *parent, Hrc_Model_t *newModelPtr);
+EXTERN int RstAddParentComponentsToNewModel(Hrc_Manager_t *hmgr, Hrc_Node_t *parent, Hrc_Model_t *newModelPtr, st_table *parentVarTable, Hrc_Node_t *child);
+EXTERN void Var_VariableResetNumFanout(Var_Variable_t* var);
+EXTERN Tbl_Table_t* Tbl_TableDupAndSubstVars(Tbl_Table_t* Table, st_table* VartoVar);
+EXTERN Rst_Group_t* RstGroupComponents(Hrc_Model_t* CurModel, char* NewName, array_t* VarGroup, array_t* Subcircuits);
+EXTERN Rst_Group_t* RstGroupAlloc(char* Name);
+EXTERN void RstGroupFree(Rst_Group_t* Group);
+EXTERN char* RstGroupNewParentName(char* Name);
+EXTERN void RstGroupPrint(Rst_Group_t* group);
+EXTERN int RstGroupDisjointCheck(array_t* GroupArray);
+EXTERN Rst_Group_t* RstCreateParentGroup(Hrc_Manager_t* Hmgr, Hrc_Model_t* ParentModel, char* NewModelName, array_t* GroupArray);
+EXTERN void RstModelPrint(Hrc_Model_t* newModel);
+EXTERN Hrc_Model_t* RstGroupBuildModel(Hrc_Manager_t* Hmgr, Rst_Group_t* Group);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _RSTINT */
+
+
Index: vis_dev/vis-2.3/src/rt/rt.h
===================================================================
--- vis_dev/vis-2.3/src/rt/rt.h	(revision 14)
+++ vis_dev/vis-2.3/src/rt/rt.h	(revision 14)
@@ -0,0 +1,77 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [rt.h]
+
+  PackageName [rt]
+
+  Synopsis    [Regression test]
+
+  Description [Manage regression test and make latex table to see the difference.]
+
+  Author      [HoonSang Jin]
+
+  Comment     [Documentation under construction]
+  
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: rt.h,v 1.4 2002/09/09 00:01:16 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _RT
+#define _RT
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "ctlp.h"
+#include "mcInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void Rt_Init(void);
+EXTERN void Rt_End(void);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _RT */
Index: vis_dev/vis-2.3/src/rt/rt.make
===================================================================
--- vis_dev/vis-2.3/src/rt/rt.make	(revision 14)
+++ vis_dev/vis-2.3/src/rt/rt.make	(revision 14)
@@ -0,0 +1,4 @@
+CSRC += rtMain.c
+HEADERS += rt.h rtInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/rt/rtInt.h
===================================================================
--- vis_dev/vis-2.3/src/rt/rtInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/rt/rtInt.h	(revision 14)
@@ -0,0 +1,220 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [rtInt.h]
+
+  PackageName [rt]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [HoonSang Jin]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: rtInt.h,v 1.4 2002/09/19 21:44:06 jinh Exp $]
+
+******************************************************************************/
+
+#ifndef _RTINT
+#define _RTINT
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "rt.h"
+#include <string.h>
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+struct RtConfig {
+  char *configurationFile;
+  char *designDirectory;
+  char *referenceVis;
+  char *referenceVisNickName;
+  char *referenceVisOptionFile;
+  char *referenceOutDirectory;
+  int  bRefRun;
+  char *newVis;
+  char *newVisNickName;
+  char *newVisOptionFile;
+  char *newOutDirectory;
+  int  bNewRun;
+  char *refCommandTemplate;
+  char *newCommandTemplate;
+  char *designList;
+  int bRefOnly;
+  int bCompareCounterExample;
+  int bFinalResultOnly;
+  int bDefaultInitCommand;
+  int bDontRemoveTempFile;
+  char *resultForCounterExample;
+  char *resultForPerformance;
+  char *scriptFile;
+  array_t *compareItemArr;
+  array_t *designListArr;
+  array_t *refCommandTemplateArr;
+  array_t *newCommandTemplateArr;
+  st_table *keyWordTable;
+};
+
+struct RtDesignList {
+  char *designDirectory;
+  char *designNickName;
+  char *blifFile;
+  char *ctlFile;
+  char *invFile;
+  char *leFile;
+  char *fairFile;
+  char *hintFile;
+  char *ordFile;
+  char *ltlFile;
+  int coreDumped;
+  int refRunFail;
+  int newRunFail;
+  int bIsMv;
+  array_t *resultForCommandArr1;
+  array_t *resultForCommandArr2;
+};
+
+struct RtCommandResult {
+  char *command;
+  int error;
+  array_t *compareItemArr;
+  array_t *resultForProperty;
+  int  bTimeOut;
+};
+
+struct RtCompareItem {
+  char *itemName;
+  char *itemNickName;
+  char *value;
+};
+
+struct RtResultProperty {
+  int  index;
+  char *failOrPass;
+  int  lengthOfBasic;
+  int  lengthOfStem;
+  int  lengthOfCycle;
+  int  lengthOfInv;
+  int  lengthOfCounterExample;
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef struct RtDesignList RtDesignLists_t;
+typedef struct RtCommandResult RtCommandResults_t;
+typedef struct RtCompareItem RtCompareItems_t;
+typedef struct RtConfig RtConfigs_t;
+typedef struct RtResultProperty RtResultPropertys_t;
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _RTINT */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/rt/rtMain.c
===================================================================
--- vis_dev/vis-2.3/src/rt/rtMain.c	(revision 14)
+++ vis_dev/vis-2.3/src/rt/rtMain.c	(revision 14)
@@ -0,0 +1,3309 @@
+/**CFile***********************************************************************
+
+  FileName    [rtMain.c]
+
+  PackageName [rt]
+
+  Synopsis    [Regression Test]
+
+  Description  [ This  file contains  the  functions for  regression test.  The
+command 'regression_test' will read a  description of the regression test to be
+performed from the  argument file, and will then carry  out the test.  Finally,
+it will produce a LaTeX file with a set of tables summarizing the results.
+
+  The regression_test command can be  used to compare two different versions of
+vis, or two different scripts on the same version of vis, or even two different
+scripts  on  two  different   versions  of  vis.   regression_test  spawns  the
+version(s) of vis  to be used for the experiments as  child processes.  It does
+no  other computation  except setting  up the  experiments, starting  the child
+processes, waiting for their termination, and collecting the results.
+
+ ]
+
+  Author [HoonSang Jin]
+
+  Copyright   [Copyright (c) 2001-2002 The Regents of the Univ. of Colorado.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF COLORADO BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  COLORADO HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF COLORADO SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF COLORADO HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "rtInt.h"
+#include "rt.h"
+#include "ntm.h"
+#include "part.h"
+#include <errno.h>
+#include <math.h>
+
+static char rcsid[] UNUSED = "$Id: rtMain.c,v 1.36 2010/04/10 00:38:42 fabio Exp $";
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandRt( Hrc_Manager_t **hmgr, int argc, char **argv);
+static RtConfigs_t * Rt_ReadConfigFile(char *filename);
+static char * Rt_SplitLine( char * command, int * argc, char *** argv);
+static int Rt_CompareResult(RtConfigs_t *config, RtDesignLists_t *designList, int refOnly);
+static int Rt_WriteBatchCommand(RtConfigs_t *config, RtDesignLists_t *designList);
+static int Rt_ExecuteVis(RtConfigs_t *config, RtDesignLists_t *designList, int refAndNew, FILE *scriptOut);
+static int Rt_WriteResult(RtConfigs_t *config, int size);
+static void Rt_FreeRtConfig(RtConfigs_t * config);
+static void Rt_FreeCommandResult(RtCommandResults_t *result);
+static void Rt_FreeCompareItem(RtCompareItems_t *item);
+static void Rt_FreeResultProperty(RtResultPropertys_t *prop);
+static void Rt_FreeDesignList(RtDesignLists_t *list);
+static void Rt_FreeArgv(int  argc,  char ** argv);
+static int Rt_ReadDesignListFile(RtConfigs_t * config);
+static int Rt_ReadCommandTemplate(RtConfigs_t * config);
+static int RtCheckInputFileAvailability( RtConfigs_t *config, RtDesignLists_t *designList, int withWarning);
+static void Rt_RemoveUnderscore(char *name, char *newName);
+static int Rt_IsNum(char *tmp);
+static int Rt_SetBooleanValue(char *str, char *option);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Initialize mc package]
+
+  SideEffects []
+
+******************************************************************************/
+
+
+/**Function********************************************************************
+
+  Synopsis [Initialize rt package]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Rt_Init(void)
+{
+  Cmd_CommandAdd("regression_test", CommandRt, /* doesn't changes_network */ 0);
+}
+
+/**Function********************************************************************
+
+  Synopsis [End rt package]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Rt_End(void)
+{
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Compare two different execution of vis and make a set of
+               tables summarizing results.]
+
+  CommandName [regression_test]
+
+  CommandSynopsis [perform regression test with the information given
+                   in arguments file]
+
+  CommandArguments [ \[-s &lt;script_file_name&gt;\] ]
+
+  CommandDescription  [
+  Invokes two set of execution of vis to compare the performance and to check
+sanity of each execution. Then make a set of tables summarizing results,
+such as CPU sec, memoty usage and fail/pass of model_check, etc.. This
+command will read a description of the regression test to be performed
+from the argument file, which is configuartion file. Besides the configuration
+file, one needs to prepare two template files and a design list. We now
+describe these in turn. As running example we shall use a regression test
+that compares check_invariant with and without guided search.
+<p>The configuration file for our example is shown below, delimited by
+lines of dashes (which are not part of the file). The order in which the
+lines appear in the file is immaterial. A line beginning with '#' is a
+comment, and is ignored by regression_test.
+<br>----------------------------------------------------------------------
+<br>DesignDirectory : /projects/development/hsv/vis/Regression
+<br>DesignList : ./DesignListInv
+<br>ReferenceVis : /usr/local/vis/i686-o/vis-cu
+<br>ReferenceVisNickName : BFS
+<br>ReferenceOutputDir : ./result_inv_bfs
+<br>RefCommandTemplate : ./TemplateRefInv
+<br>bRefRun : FALSE
+<br>NewVis : /usr/local/vis/i686-o/vis-cu
+<br>NewVisNickName : GS
+<br>NewOutputDir : ./result_inv_gs
+<br>bNewRun : FALSE
+<br>NewCommandTemplate : ./TemplateNewInv
+<br>bCompareCounterExample : TRUE
+<br>bDefaultInitCommand : FALSE
+<br>ResultForPerformance : ./BFSvsGS.tex
+<br>CompareItem : cpu : elapse:
+<br>CompareItem : mem : Memory in use:
+<br>CompareItem : bdd : Peak number of live nodes:
+<br>----------------------------------------------------------------------
+<br>&nbsp;
+<p>Each line defines a parameter of the regression test.
+<p>* DesignDirectory gives the path to the directory where the input files
+are stored. In this case, we are using the central repository under ~hsv/vis/Regression.
+It's typically a good idea to store the results of regression tests in
+a separate place from the input files. In our examples, the results are
+stored in the current directory.
+<p>&nbsp;* DesignList gives the name of the file containing the list of
+test cases to run. Each line consists of several white space-separated
+fields describing the files making up the test case. The first field is
+a path to the files relative to DesignDirectory. The second field is the
+test case name. The remaining fields are file names. More on this later,
+when we talk about the design list file in detail.
+<p>&nbsp;* ReferenceVis and NewVis give paths to the two versions of vis
+to be compared in the regression test. They can be the same, as in this
+case in which both are the "nightly build."
+<p>&nbsp;* ReferenceVisNickName and NewVisNickName are two identifiers
+that are used in the LaTeX tables to refer to the two versions that are
+compared. Short mnemonics are preferable. Avoid using underscores, because
+they currently cause trouble with LaTeX.
+<p>&nbsp;* ReferenceOutputDir and NewOutputDir give the names of the directories
+in which the results of the runs will be stored. In each of these directories,
+vis_reg will create a directory for each test case. The names of these
+directories are the test case names taken from the design list. Therefore,
+these names must be unique.
+<p>&nbsp;* RefCommandTemplate and NewCommandTemplate are the templates
+from which vis_reg produces the scripts used to run the test cases. The
+mechanism used to derive the scripts from the templates and the design
+list is described in detail when we talk about the template files. The
+two templates can be the same file.
+<p>&nbsp;* bRefRun and bNewRun are flags that tell vis_reg which of the
+two sets of experiments should be run (if any). If one set of results has
+been already computed, the corresponding flag should be set to FALSE. If
+both flags are FALSE, vis_reg simply regenerates the
+summary table.
+<p>&nbsp;* bCompareCounterExample is a flag that instructs vis_reg to scan
+the output files for counterexamples and record their lengths. For each
+counterexample, stem and cycle length are found. If this flag is set to
+FALSE, counterexamples are not analyzed and the corresponding table is
+not produced.
+<p>&nbsp;* bDefaultInitCommand is a flag that, if set to TRUE, instructs
+vis_reg to generate a default set of commands to initialize each vis run.
+This option allows one to save some time in preparing the templates, at
+the expense of some flexibility.
+<p>&nbsp;* ResultForPerformance is the name of the LaTeX file to which
+vis_reg writes the summary of the experiments. Its format is described
+in detail later.
+<p>&nbsp;* CompareItem specifies one item to be monitored in the experiments.
+Multiple CompareItem lines may appear in the configuration file. Each one
+consists of two items: an identifier, and a pattern. The identifier is
+used in the table to denote the item, whereas the pattern is used to extract
+from the output files the information to be put in the tables.
+<p>&nbsp;In our example, we declare
+<p>&nbsp;CompareItem : mem : Memory in use:
+<p>We instruct regression_test to search for a line beginning with "Memory
+in use:" in each section of the output file. The token immediately following
+the occurrence of the pattern is the data item to be put in the table under
+"mem." so that the resulting LaTeX table contains data on the memmory usage.
+<p>&nbsp;Since the output file is divided into sections delimited by strings
+"CommandBegin" and "CommandEnd." (See below.), each section is searched
+for the patterns specified by the CompareItem declarations. If the pattern
+is matched, the item appears in the table for that section.
+<p>&nbsp;To run the regression_test we need configuration file, template
+file and design list. In case of template file, we need a two template
+files, since we want to compare two different run of vis. The syntax of
+the two templates is identical. We describe the template for "new," but
+all we say applies to "ref" as well. The "new" template for our example
+is shown below.
+<br>----------------------------------------------------------------------
+<p>echo CommandBegin init
+<br>read_model
+<br>flt
+<br>order_vars
+<br>part
+<br>time
+<br>print_bdd_stats
+<br>echo CommandEnd init
+<br>echo CommandBegin ci
+<br>set hd_frontier_approx_threshold 3500
+<br>ci -t 3600 -g $HintFile $InvFile
+<br>time
+<br>print_bdd_stats
+<br>echo CommandEnd ci
+<br>echo CommandBegin ci_cex
+<br>ci -d 1 -i -t 3600 -g $HintFile $InvFile
+<br>time
+<br>print_bdd_stats
+<br>echo CommandEnd ci_cex
+<br>----------------------------------------------------------------------
+<p>Before proceeding to its discussion, it is instructive to examine the
+script that regression_test produces from it for one test case. regression_test
+relies on vis's shell variables and aliases to customize the script. The
+script consists of a preamble in which variables and aliases are defined,
+followed by one or more sections, each corresponding to a major step in
+the experiment. Statistics will be collected for each step separately.
+Our example has three sections, whose names are "init," "ci," and "ci_cex."
+The names of the sections are arbitrary, except that the automatically
+generated initialization section is always called "init."
+<br>----------------------------------------------------------------------
+<p>set vis_stdout ./result_inv_gs/am2901/am2901.out
+<br>set vis_stderr ./result_inv_gs/am2901/am2901.err
+<br>set BlifFile /projects/development/hsv/vis/Regression/Am2901/am2901.mv
+<br>set OrdFile /projects/development/hsv/vis/Regression/Am2901/am2901.ord
+<br>set InvFile /projects/development/hsv/vis/Regression/Am2901/am2901.inv
+<br>set HintFile /projects/development/hsv/vis/Regression/Am2901/am2901.hint
+<br>alias read_model "rlmv $BlifFile"
+<br>alias set_fairness " "
+<br>alias order_vars "so -s input_and_latch $OrdFile"
+<br>echo CommandBegin init
+<br>read_model
+<br>flt
+<br>order_vars
+<br>part
+<br>time
+<br>print_bdd_stats
+<br>echo CommandEnd init
+<br>echo CommandBegin ci
+<br>set hd_frontier_approx_threshold 3500
+<br>ci -t 3600 -g $HintFile $InvFile
+<br>time
+<br>print_bdd_stats
+<br>echo CommandEnd ci
+<br>echo CommandBegin ci_cex
+<br>ci -d 1 -i -t 3600 -g $HintFile $InvFile
+<br>time
+<br>print_bdd_stats
+<br>echo CommandEnd ci_cex
+<br>quit
+<br>----------------------------------------------------------------------
+<p>The variables and the aliases are defined by vis_reg by examining the
+fields of the test case description in the design file. regression_test
+uses file extensions to identify file types. (E.g., .ord indicates an order
+file in "input_and_latch" format.) A full list of extensions is given below.
+<p>regression_test defines variables for all the file types actually available
+for the experiment, and only for those. It also defines three aliases that
+provide some flexibility in mixing different experiments in the same batch.
+<p>For instance, "read_model" is defined as either
+<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; read_blif_mv $BlifFile
+<p>or
+<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; read_blif $BlifFile
+<p>depending on whether the design list specifies a .mv file or a .blif
+file as model file.
+<p>The definition of "order_vars" takes into account whether an order file
+is available or not. Finally, the definition of "set_fairness" depends
+on whether a .fair file is available. This allows one to mix model checking
+experiments for which no fairness condition is specified to experiments
+that do require fairness conditions.
+<p>When bDefaultInitCommand is FALSE, the script is simply the preamble,
+followed by the unchanged template, follows by the "quit" command, which
+is always automatically added.
+<p>When bDefaultInitCommand is TRUE, regression_test also adds an automatically
+generated "init" section between the preamble and the template. This default
+section is equivalent to
+<p>echo CommandBegin init
+<br>read_model
+<br>flt
+<br>order_vars
+<br>part
+<br>time
+<br>print_bdd_stats
+<br>echo CommandEnd init
+<p>Notice that one has no control over dynamic reordering during the initialization
+phase if bDefaultInitCommand is TRUE.
+<p>The template should refer to the defined aliases and variables to tailor
+itself to each test case. Notice, however, that one is not forced to use
+"order_vars." If one wants to always use vis's static ordering algorithm,
+(s)he can simply use "so" instead of "order_vars." Likewise, one can decide
+to always ignore fairness constraints by not including "set_fairness."
+<p>On the other hand, it is usually a bad idea to explicitly include commands
+like
+<p>read_blif_mv
+<br>read_blif
+<br>so -s input_and_latch
+<br>read_fairness
+<p>in the templates, because they limit the range of test cases to which
+they can be applied.
+<p>As we said, the templates, and hence the scripts, are divided in sections.
+Each section begins and ends with an "echo" command. These commands write
+delimiters to the output file, which are used by vis_reg to define the
+scope of the pattern searches. It is important that the tag specified in
+corresponding pairs of CommandBegin and CommandEnd be the same.
+<p>The calls to "print_bdd_stats" are typically used to add to the output
+files the information requested by the CompareItem declarations. It is
+a good idea to specify timeouts for potentially expensive steps.
+<p>The design list file has one line for each test case. A master design
+list is in ~hsv/vis/Regression/DesignList. Specific design lists can be
+obtained by commenting out or deleting lines from this master list. One
+can also create an entirely new list according to the following rules.
+<p>Lines starting with '#' are interpreted as comments and are skipped,
+as in all files read by vis_reg.
+<p>A test case is a named collection of related files that can be used
+to run one or more experiments. As mentioned before, each line consists
+of white space-separated fields. The first is a (relative) path, while
+the second is the collection name. The remaining fields specify the files
+in the collection.
+<p>The smallest collection will specify one .mv or one .blif file. This
+file is called the "model file," and should always appear in the third
+field of the line. If the model file is the only file specified, one can
+run reachability analysis, but not much more. Vis_reg understands the file
+extensions shown in the following table. For each extension, the variable
+bound to the file name and a short explanation are given.
+<p>.mv $BlifFile model file to be read with rlmv
+<br>.blif $BlifFile model file to be read with rl
+<br>.ord $OrdFIle order file to be read with so -s input_and_latch
+<br>.inv $InvFile invariant file to be read with ci
+<br>.ctl $CtlFile property file to be read with mc
+<br>.fair $FairFile fairness file to be read with rf
+<br>.hint $HintFile hint file to be read with the -g option of mc, ci,
+and rch
+<p>Only one file of each type can appear in the collection defining one
+test case. If multiple property files, or different order files are available
+for one model file, one has to create two test cases for that model. Different
+models, on the other hand, can share property files, order files, and so
+on. The master design list provides examples for both these situations.
+<p>It is not possible to specify both a .mv file and a .blif file for one
+test case. There must be exactly one model file per test case.
+<p>As was mentioned before, it is important that the name of a test case
+be unique in the entire batch used for a regression test. On the other
+hand, several test cases may share the same directory, and often do when
+they have some files in common.
+<p>The result summary created by regression_test is a LaTeX file consisting
+of several tables. There is one table with performance stats for each section
+of the output file. In addition, there is an optional counterexample comparison
+table that summarizes PASS/FAIL information for the properties and the
+length of counterexamples. For each failing property, the length of the
+stem and the length of the cycle (if applicable) are reported.
+<p>Each performance table consists of one column for the test case name,
+followed by as many groups of three columns as there are CompareItem declarations
+applicable to the section that the table summarizes.
+<p>Each group of three columns gives the data for the reference run, the
+data for the new run, and the improvement. Vis_reg regards smaller as better.
+Hence, the improvement is positive if the CPU time, memory occupation,
+and so on, have decreased from the reference run to the new run. The improvement
+is computed as
+<p>(value(ref) - value(new)) / value(ref) * 100.
+<p>Notice that this formula tends to make "new" look bad. for instance,
+if new is twice as fast as ref, the improvement is 50%. If ref is twice
+as fast, however, the "improvement" is -100%.
+<p>The results of each test case are stored in a separate directory, whose
+name is obtained by concatenating ReferenceOutputDir (or NewOutputDir)
+with the test case name. Each directory stores three files, whose names
+are given by the test case name concatenated with .src, .out, and .err.
+<p>* test_case_name.src stores the script used to run vis.
+<br>* test_case_name.out stores what vis writes to vis_stdout.
+<br>* test_case_name.err stores what vis writes to vis_stderr.
+<p>One has to be careful, because vis_reg will overwrite these results
+directories without warning if run twice with the same ReferenceOutputDir
+or NewOutputDir and bRefRun or bNewRun set to TRUE.
+<p>With '-s' option, you can create c-shell script file to be able to run
+experiments in shell. We add this option to solve the problem that are
+happened when your template file contains child-process by system call.
+]
+
+  Comment [
+  * One cannot compare the number of iterations to convergence with BFS
+  to those of HD or GS, because the first is reported as "FSM depth,"
+  while the other two are reported as "computation depth."  <p>
+
+  * Tables are split so that the number of rows is not too large.
+  However, tables may be too wide.  All "CompareItem" items found in
+  one section are put in the same table.  <p>
+
+  * Currently, under Linux, the datasize limit is not enforced (not
+  systematically enforced?) for the child processes spawned by
+  vis_reg.  One has to monitor experiments that may produce very large
+  processes, because there is a concrete risk of thrashing the machine
+  on which the regression test is run.  <p>
+
+  * One cannot create experiments that read two different property
+  files, or two different invariant files, or that perform equivalence
+  checking.  (That would require two model files.)  <p>
+
+]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandRt(
+  Hrc_Manager_t **hmgr,
+  int argc,
+  char **argv)
+{
+  char *configurationFile;
+  char *scriptFile;
+  RtConfigs_t *config;
+  RtDesignLists_t *designList;
+  array_t *designArr;
+  int i;
+  FILE *scriptOut;
+  int c;
+  error_init();
+
+  if(argc < 2) {
+     fprintf(vis_stdout, "Error : ConfigurationFile is missed\n");
+     return(1);
+  }
+
+  util_getopt_reset();
+  scriptFile = 0;
+  scriptOut = 0;
+  while ((c = util_getopt(argc, argv, "s:h")) != EOF) {
+    switch(c) {
+    case 's':
+      scriptFile = util_strsav(util_optarg);
+      break;
+    case 'h':
+      (void) fprintf(vis_stderr, "usage: regression_test [-h] [-s scriptfile] configuration_file\n");
+      (void) fprintf(vis_stderr, "    -h \tprint help information\n");
+      (void) fprintf(vis_stderr, "    -s <scriptfile>\n");
+      (void) fprintf(vis_stderr, "       \tgenerate shell script file for regression_test\n");
+      return 0;
+    default:
+      (void) fprintf(vis_stderr, "usage: regression_test [-h] [-s scriptfile] configuration_file\n");
+      (void) fprintf(vis_stderr, "    -h \tprint help information\n");
+      (void) fprintf(vis_stderr, "    -s <scriptfile>\n");
+      (void) fprintf(vis_stderr, "       \tgenerate shell script file for regression_test\n");
+      return 0;
+    }
+  }
+  if(scriptFile) {
+    if(!(scriptOut = fopen(scriptFile, "w"))) {
+      fprintf(vis_stdout, "Error : Can't open script file '%s'\n", scriptFile);
+      return(1);
+    }
+  }
+
+  configurationFile = argv[util_optind];
+  config = Rt_ReadConfigFile(configurationFile);
+  if(config == 0)			return(1);
+
+  config->scriptFile = scriptFile;
+  if(Rt_ReadDesignListFile(config))	{
+    Rt_FreeRtConfig(config);
+    return(1);
+  }
+  if(Rt_ReadCommandTemplate(config))	{
+    Rt_FreeRtConfig(config);
+    return(1);
+  }
+
+
+  designArr = config->designListArr;
+  for(i=0; i<array_n(designArr); i++) {
+    designList = array_fetch(RtDesignLists_t *, designArr, i);
+
+    /** 
+     * One have to use reserved words in their template file, such as
+     * $OrdFile, $BlifFile, etc.. 
+     * Somehow your template file contains the reserved words that are
+     * not provied in desigl list, then skip the design.
+     **/
+    if(RtCheckInputFileAvailability(config, designList, 1)) {
+       fprintf(vis_stdout, "Skip the design '%s' ..(%d/%d)\n", designList->designNickName, i+1, array_n(designArr));
+       continue;
+    }
+    /** 
+     * Create result directory structure and script file that are used
+     * to run individual experiments. Each directory, whose
+     * name is obtained by concatenating ReferenceOutputDir(or NewOutputDir)
+     * with the test case name, contains test_case_name.src after
+     * executing this function.
+     **/
+    if(Rt_WriteBatchCommand(config, designList)) {
+       fprintf(vis_stdout, "ERROR : can't write script for design '%s'\n", designList->designNickName);
+       continue;
+    }
+    /** 
+     * Run vis using the executable that is obtained ReferenceVis of
+     * configuration file
+     **/
+    if(Rt_ExecuteVis(config, designList, 1, scriptOut)) {
+       fprintf(vis_stdout, "ERROR : can't execute '%s' for design '%s'\n", config->referenceVisNickName, designList->designNickName);
+    }
+    /** 
+     * Run vis using the executable that is obtained NewVis of
+     * configuration file
+     **/
+    if(Rt_ExecuteVis(config, designList, 2, scriptOut)) {
+       fprintf(vis_stdout, "ERROR : can't execute '%s' for design '%s'\n", config->newVisNickName, designList->designNickName);
+    }
+    /** 
+     * After running two set of experimental results, read the log file
+     * of each run and compare the results.
+     **/
+    if(Rt_CompareResult(config, designList, config->bRefOnly)) {
+       fprintf(vis_stdout, "ERROR : can't compare result for design '%s'\n", designList->designNickName);
+    }
+    fprintf(vis_stdout, "%s complete.. (%d/%d)\n", designList->designNickName, i+1, array_n(designArr));
+
+    /** 
+     * Write a LaTeX file summarizing the results, after running each
+     * design, so that one can see the results before finishing the
+     * whole experiments.
+     **/
+    if(config->scriptFile == 0) {
+      if(config->bRefRun || config->bNewRun)
+        Rt_WriteResult(config, i+1);
+    }
+  }
+
+  /** 
+   * Write a LateX file summarizing the results. 
+   **/
+  if(config->scriptFile == 0)
+    if(Rt_WriteResult(config, array_n(designArr)))	return(1);
+  alarm(0);
+
+  Rt_FreeRtConfig(config);
+  if(scriptOut)	fclose(scriptOut);
+  return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Check whether the used file in template file is available
+               or not. ]
+
+  Description [ 
+      One have to use reserved words in their template file, such as
+     $OrdFile, $BlifFile,  $InvFile, $CtlFile, $FairFile, $HintFile and
+     $LeFile. Somehow your template file contains the reserved words that are
+     not provied in design list, then skip the design.
+     ]
+
+  Comment []
+
+  SideEffects []
+
+******************************************************************************/
+static int
+RtCheckInputFileAvailability(
+  RtConfigs_t *config, 
+  RtDesignLists_t *designList,
+  int withWarning)
+{
+  st_table *keyTable;
+  st_generator *gen;
+  int errorFlag;
+  char *keyWord;
+
+  keyTable = config->keyWordTable;
+  if(keyTable == 0)	return(0);
+  errorFlag = 0;
+  st_foreach_item(keyTable, gen, &keyWord, NIL(char *)) {
+    if(!strcasecmp(keyWord, "$CtlFile") && !designList->ctlFile) {
+      if(withWarning)
+      fprintf(vis_stdout, "WARNING : Template contains the '$CtlFile', but not in design list\n");
+      errorFlag = 1;
+    }
+    else if(!strcasecmp(keyWord, "$OrdFile") && !designList->ordFile) {
+      if(withWarning)
+      fprintf(vis_stdout, "WARNING : Template contains the '$OrdFile', but not in design list\n");
+      errorFlag = 1;
+    }
+    else if(!strcasecmp(keyWord, "$InvFile")&& !designList->invFile) {
+      if(withWarning)
+      fprintf(vis_stdout, "WARNING : Template contains the '$InvFile', but not in design list\n");
+      errorFlag = 1;
+    }
+    else if(!strcasecmp(keyWord, "$FairFile")&& !designList->fairFile) {
+      if(withWarning)
+      fprintf(vis_stdout, "WARNING : Template contains the '$FairFile', but not in design list\n");
+      errorFlag = 1;
+    }
+    else if(!strcasecmp(keyWord, "$LeFile")&& !designList->leFile) {
+      if(withWarning)
+      fprintf(vis_stdout, "WARNING : Template contains the '$LeFile', but not in design list\n");
+      errorFlag = 1;
+    }
+    else if(!strcasecmp(keyWord, "$LtlFile")&& !designList->ltlFile) {
+      if(withWarning)
+      fprintf(vis_stdout, "WARNING : Template contains the '$LtlFile', but not in design list\n");
+      errorFlag = 1;
+    }
+    else if(!strcasecmp(keyWord, "$HintFile")&& !designList->hintFile) {
+      if(withWarning)
+      fprintf(vis_stdout, "WARNING : Template contains the '$HintFile', but not in design list\n");
+      errorFlag = 1;
+    }
+  }
+  if(errorFlag == 1) 	return(1);
+  else			return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Write LaTeX file summarizing results.]
+
+  Description [ The  result summary created by regression_test  is a LaTeX file
+consisting of  several tables.  There is  one table with  performance stats for
+each  section  of  the  output   file.   In  addition,  there  is  an  optional
+counterexample comparison  table that summarizes PASS/FAIL  information for the
+properties and the  length of counterexamples.  For each  failing property, the
+length of the stem and the length of the cycle (if applicable) are reported.
+
+Each performance table consists of one  column for the test case name, followed
+by  as many  groups  of three  columns  as there  are CompareItem  declarations
+applicable to the section that the table summarizes.  ]
+
+  Comment []
+
+  SideEffects []
+
+******************************************************************************/
+static int
+Rt_WriteResult(RtConfigs_t *config, int size)
+{
+  FILE *fout;
+  array_t *cResultArr, *cResultArr2;
+  array_t *cResultArrSample, *cItemArrSample, *cItemArrSampleMax;
+  array_t *cItemArr, *cItemArr2, *designArr;
+  array_t *pArr, *pArr2, *pArrSample;
+  RtCommandResults_t *cResult, *cResult2, *cResultSample;
+  RtCompareItems_t *cItem, *cItem2, *cItemSample;
+  RtDesignLists_t *designList;
+  RtResultPropertys_t *rProp, *rProp2;
+  int i, j, k, first_flag;
+  int property_flag;
+  int lineNo, estLineNo, errorFlag;
+  char newName[1024], endStr[10];
+  char newNName[1024], refNName[1024];
+  char newTimeout[1024], refTimeout[1024];
+  double value1, value2;
+  int lastFailedIndex;
+  array_t *cResultArrMax;
+  array_t *cItemArrMax;
+  double *resultArr;
+  double totalNum;
+  double gap;
+
+  pArrSample = 0;
+  if(!(fout = fopen(config->resultForPerformance, "w"))) {
+    fprintf(vis_stdout, "Error : Can't open result file '%s'\n", config->resultForPerformance);
+    return(1);
+  }
+  designArr = config->designListArr;
+
+  /** Check whether both runs contain the same set of item, since we
+   * compare two experiments.
+   **/
+  cItemArrSample = 0;
+  cResultArrSample = NIL(array_t);
+  for(k=0; k<array_n(designArr) && k<size; k++) {
+    designList = array_fetch(RtDesignLists_t *, designArr, k);
+    cResultArrSample = designList->resultForCommandArr1;
+    errorFlag = 0;
+    if(cResultArrSample)	{
+      for(i=0; i<array_n(cResultArrSample); i++) {
+        cResult = array_fetch(RtCommandResults_t *, cResultArrSample, i);
+        cItemArrSample = cResult->compareItemArr;
+	if(cItemArrSample == NIL(array_t)) {
+	  errorFlag = 1;
+	  break;
+	}
+      }
+    }
+    if(errorFlag == 0)	break;
+  }
+  if(cResultArrSample == NIL(array_t)) {
+     fprintf(fout, "ERROR : Can't find any output for your design list\n");
+     fclose(fout);
+     return(1);
+  }
+
+  /** Write performance table header **/
+  fprintf(fout, "\\documentclass[plain]{article}\n");
+  fprintf(fout, "\\usepackage{lscape}\n");
+  fprintf(fout, "\\begin{document}\n");
+  fprintf(fout, "\\setlength{\\oddsidemargin}{-0.5in}\n");
+  /**
+  fprintf(fout, "\\landscape\n");
+  **/
+
+  for(i=0; i<array_n(cResultArrSample); i++) {
+
+    fprintf(fout, "\\begin{table}\n");
+    cResult = array_fetch(RtCommandResults_t *, cResultArrSample, i);
+    cItemArrSample = cResult->compareItemArr;
+ 
+    cItemArrSampleMax = cItemArrSample;
+    for(k=0; k<array_n(designArr) && k<size; k++) {
+      designList = array_fetch(RtDesignLists_t *, designArr, k);
+      cResultArr = designList->resultForCommandArr1;
+      if(cResultArr)	{
+          if(array_n(cResultArr) > i) 
+              cResult = array_fetch(RtCommandResults_t *, cResultArr, i);
+          else
+	      cResult = 0;
+          if(!cResult)	continue;
+          cItemArrSample = cResult->compareItemArr;
+	  if(cItemArrSample && array_n(cItemArrSample) > array_n(cItemArrSampleMax)) {
+	    cItemArrSampleMax = cItemArrSample;
+	  }
+      }
+    }
+    cItemArrSample = cItemArrSampleMax;
+    if(cItemArrSample == 0) {
+       fprintf(fout, "ERROR : Can't find any output for your design list\n");
+       fclose(fout);
+       return(1);
+    }
+      
+    cResult = array_fetch(RtCommandResults_t *, cResultArrSample, i);
+    Rt_RemoveUnderscore(cResult->command, newName);
+    Rt_RemoveUnderscore(config->referenceVisNickName, refNName);
+    Rt_RemoveUnderscore(config->newVisNickName, newNName);
+    fprintf(fout, "\\caption{Performance Comparison Table of %s for %s(ref) and %s(new)}\n",
+        newName, refNName, newNName);
+    fprintf(fout, "\\begin{center}\n");
+    fprintf(fout, "\\begin{tabular}{|c||");
+    for(j=0; j<array_n(cItemArrSample); j++) {
+      fprintf(fout, "c|c|c|");
+    }
+    fprintf(fout, "} \\hline \n");
+    fprintf(fout, " &");
+    Rt_RemoveUnderscore(cResult->command, newName);
+    fprintf(fout, "\\multicolumn{%d}{c|}{%s} ", array_n(cItemArrSample)*3, newName);
+    fprintf(fout, "\\\\ \\cline{2-%d}\n", array_n(cItemArrSample)*3+1);
+  
+    fprintf(fout, " &");
+    for(j=0; j<array_n(cItemArrSample); j++) {
+      cItem = array_fetch(RtCompareItems_t *, cItemArrSample, j);
+      if(j+1 == array_n(cItemArrSample)) 
+        fprintf(fout, "\\multicolumn{3}{c|}{%s}", cItem->itemNickName);
+      else 
+        fprintf(fout, "\\multicolumn{3}{c|}{%s} &", cItem->itemNickName);
+    }
+    fprintf(fout, "\\\\ \\cline{2-%d}\n",array_n(cItemArrSample)*3+1);
+  
+    fprintf(fout, "Design &");
+    for(j=0; j<array_n(cItemArrSample); j++) {
+      if(j+1 == array_n(cItemArrSample)) 
+        fprintf(fout, "ref & new & (\\%%)");
+      else 
+        fprintf(fout, "ref & new & (\\%%) &");
+    }
+    fprintf(fout, "\\\\ \\hline \\hline\n");
+  
+    lineNo = 0;
+    for(k=0; k<array_n(designArr) && k<size ; k++) {
+      lineNo++;
+  
+      /** 
+       * If the result table have more than 31 line then split the
+       * table.
+       **/
+      if(lineNo == 31) {
+        fprintf(fout, "\\end{tabular}\n");
+        fprintf(fout, "\\end{center}\n");
+        fprintf(fout, "\\end{table}\n");
+        fprintf(fout, "\\clearpage\n");
+  
+        fprintf(fout, "\\begin{table}\n");
+        cResult = array_fetch(RtCommandResults_t *, cResultArrSample, i);
+        cItemArrSample = cResult->compareItemArr;
+        Rt_RemoveUnderscore(cResult->command, newName);
+        Rt_RemoveUnderscore(config->referenceVisNickName, refNName);
+        Rt_RemoveUnderscore(config->newVisNickName, newNName);
+        fprintf(fout, "\\caption{Performance Comparison Table of %s for %s(ref) and %s(new)}\n",
+            newName, refNName, newNName);
+        fprintf(fout, "\\begin{center}\n");
+        fprintf(fout, "\\begin{tabular}{|c||");
+        for(j=0; j<array_n(cItemArrSample); j++) {
+          fprintf(fout, "c|c|c|");
+        }
+        fprintf(fout, "} \\hline \n");
+        fprintf(fout, " &");
+        Rt_RemoveUnderscore(cResult->command, newName);
+        fprintf(fout, "\\multicolumn{%d}{c|}{%s} ", array_n(cItemArrSample)*3, newName);
+        fprintf(fout, "\\\\ \\cline{2-%d}\n", array_n(cItemArrSample)*3+1);
+      
+        fprintf(fout, " &");
+        for(j=0; j<array_n(cItemArrSample); j++) {
+          cItem = array_fetch(RtCompareItems_t *, cItemArrSample, j);
+          if(j+1 == array_n(cItemArrSample)) 
+            fprintf(fout, "\\multicolumn{3}{c|}{%s}", cItem->itemNickName);
+          else 
+            fprintf(fout, "\\multicolumn{3}{c|}{%s} &", cItem->itemNickName);
+        }
+        fprintf(fout, "\\\\ \\cline{2-%d}\n",array_n(cItemArrSample)*3+1);
+      
+        fprintf(fout, "Design &");
+        for(j=0; j<array_n(cItemArrSample); j++) {
+          if(j+1 == array_n(cItemArrSample)) 
+            fprintf(fout, "ref & new & (\\%%)");
+          else 
+            fprintf(fout, "ref & new & (\\%%) &");
+        }
+        fprintf(fout, "\\\\ \\hline \\hline\n");
+      
+        lineNo = 1;
+      }
+      designList = array_fetch(RtDesignLists_t *, designArr, k);
+      strcpy(newTimeout, "-");
+      strcpy(refTimeout, "-");
+      if(RtCheckInputFileAvailability(config, designList, 0)) {
+        continue;
+      }
+      cResultArr = designList->resultForCommandArr1;
+      cResultArr2 = designList->resultForCommandArr2;
+      Rt_RemoveUnderscore(designList->designNickName, newName);
+      fprintf(fout, "%s\t&", newName);
+      if(cResultArr && array_n(cResultArr) > i)
+        cResult = array_fetch(RtCommandResults_t *, cResultArr, i);
+      else 
+        cResult = 0;
+  
+      if(cResultArr2 && array_n(cResultArr2) > i)
+        cResult2 = array_fetch(RtCommandResults_t *, cResultArr2, i);
+      else 
+        cResult2 = 0;
+  
+      if(cResult && cResult->bTimeOut) 	 {
+        strcpy(refTimeout, "TimeOut");
+      }
+      if(cResult2 && cResult2->bTimeOut) {
+        strcpy(newTimeout, "TimeOut");
+      }
+  
+      if(cResult)
+        cItemArr = cResult->compareItemArr;
+      else
+        cItemArr = 0;
+      if(cResult2)
+        cItemArr2 = cResult2->compareItemArr;
+      else
+        cItemArr2 = 0;
+  
+      if(cItemArr == 0 && cItemArr2 == 0)	{
+        fprintf(vis_stdout, "Warning : no result for design '%s'\n", designList->designNickName);
+        for(j=0; j<array_n(cItemArrSample); j++) {
+          if(j+1 == array_n(cItemArrSample)) 
+            fprintf(fout, " %s\t& %s\t& -\t", refTimeout, newTimeout);
+	  else 
+            fprintf(fout, " %s\t& %s\t& -\t&", refTimeout, newTimeout);
+        }
+        fprintf(fout, "\\\\ \\hline\n");
+        continue;
+      }
+      else if(cItemArr && cItemArr2) {
+        if(array_n(cItemArr) != array_n(cItemArr2)) {
+	  fprintf(vis_stdout, "Warning : Can't make table for the compare item,\n");
+	  fprintf(vis_stdout, "           since they are different for '%s'\n", designList->designNickName);
+	  fprintf(vis_stdout, "           Please check your template file again.\n");
+	  for(j=0; j<array_n(cItemArrSample); j++) {
+	    if(j+1 == array_n(cItemArrSample)) 
+	      fprintf(fout, " %s\t& %s\t& -\t", refTimeout, newTimeout);
+	    else 
+	      fprintf(fout, " %s\t& %s\t& -\t&", refTimeout, newTimeout);
+	  }
+	  fprintf(fout, "\\\\ \\hline\n");
+	  continue;
+        }
+      }
+      if(cItemArr)	cItemArrSample = cItemArr;
+      else		cItemArrSample = cItemArr2;
+      for(j=0; j<array_n(cItemArrSample); j++) {
+        if(cItemArr) 
+          cItem = array_fetch(RtCompareItems_t *, cItemArr, j);
+        else
+	  cItem = 0;
+        if(cItemArr2) 
+          cItem2 = array_fetch(RtCompareItems_t *, cItemArr2, j);
+        else
+          cItem2 = 0;
+    
+        if(cItem) 	sscanf(cItem->value, "%lf", &value1);
+        if(cItem2) 	sscanf(cItem2->value, "%lf", &value2);
+  
+        endStr[0] = '\0';
+        if(j+1 != array_n(cItemArrSample))	{
+	  endStr[0] = '&';
+	  endStr[1] = '\0';
+        }
+        if(cItem2 && cItem) {
+          fprintf(fout, "%s\t& %s\t& %.2f\t%s", cItem->value, cItem2->value, (value1-value2)/value1*100, endStr);
+        }
+        else if(cItem)  {
+          fprintf(fout, "%s\t& %s\t& -\t%s", cItem->value, newTimeout, endStr);
+        }
+        else if(cItem2)  {
+          fprintf(fout, "%s\t& %s\t& -\t%s", refTimeout, cItem2->value, endStr);
+        }
+      }
+      fprintf(fout, "\\\\ \\hline\n");
+    }
+    fprintf(fout, "\\end{tabular}\n");
+    fprintf(fout, "\\end{center}\n");
+    fprintf(fout, "\\end{table}\n");
+    fprintf(fout, "\\clearpage\n");
+  }
+
+  property_flag = 0;
+  for(k=0; k<array_n(designArr) && k<size; k++) {
+    designList = array_fetch(RtDesignLists_t *, designArr, k);
+    cResultArr = designList->resultForCommandArr1;
+    if(cResultArr)	 {
+      for(i=0; i<array_n(cResultArr); i++) {
+        cResult = array_fetch(RtCommandResults_t *, cResultArr, i);
+        pArr = cResult->resultForProperty;
+        if(pArr && array_n(pArr) > 0)	{
+          property_flag = 1;
+	  break;
+        }
+      }
+    }
+    cResultArr = designList->resultForCommandArr2;
+    if(cResultArr)	 {
+      for(i=0; i<array_n(cResultArr); i++) {
+        cResult = array_fetch(RtCommandResults_t *, cResultArr, i);
+        pArr = cResult->resultForProperty;
+        if(pArr && array_n(pArr) > 0)	{
+          property_flag = 1;
+	  break;
+        }
+      }
+    }
+    if(property_flag)	break;
+  }
+
+  /** 
+   * Write the property comparison table in case of model checking
+   * verification
+   **/
+  if(property_flag == 1) {
+    fprintf(fout, "\\begin{table}\n");
+    Rt_RemoveUnderscore(config->referenceVisNickName, refNName);
+    Rt_RemoveUnderscore(config->newVisNickName, newNName);
+    fprintf(fout, "\\caption{Property Comparison Table for %s(ref) \
+    and %s(new)}\n", refNName, newNName);
+    fprintf(fout, "\\begin{center}\n");
+    fprintf(fout, "\\begin{tabular}{|c||c|c||c|c|c||c|c|c||c|} \\hline\n");
+    fprintf(fout, " & & & \\multicolumn{3}{c||}{ Property(ref) } & \\multicolumn{3}{c||}{ Property(new) } & \\multicolumn{1}{c|}{ Remark }\\\\ \\cline{4-10}\n");
+    fprintf(fout, "Design & command & index & F or P & cex len & line len  & F or P & cex len  & line len& \\\\ \\hline\n");
+  
+    lineNo = 0;
+    for(k=0; k<array_n(designArr) && k<size; k++) {
+      designList = array_fetch(RtDesignLists_t *, designArr, k);
+      if(RtCheckInputFileAvailability(config, designList, 0)) {
+        continue;
+      }
+      cResultArr = designList->resultForCommandArr1;
+      cResultArr2 = designList->resultForCommandArr2;
+      if(cResultArr == 0 && cResultArr2 == 0) {
+        fprintf(vis_stdout, "ERROR : '%s' didn't run properly\n", designList->designNickName);
+        continue;
+      }
+      else if(cResultArr == 0 ) {
+        cResultArrSample = cResultArr2;
+      }
+      else if(cResultArr2 == 0 ) {
+        cResultArrSample = cResultArr;
+      }
+      else {
+        cResultArrSample = cResultArr;
+      }
+  
+      strcpy(refTimeout, "-");
+      strcpy(newTimeout, "-");
+  
+      first_flag = 0;
+      for(i=0; i<array_n(cResultArrSample); i++) {
+        if(cResultArr && array_n(cResultArr) > i)
+          cResult = array_fetch(RtCommandResults_t *, cResultArr, i);
+        else
+          cResult = 0;
+        if(cResultArr2 && array_n(cResultArr2) > i)
+          cResult2 = array_fetch(RtCommandResults_t *, cResultArr2, i);
+        else 
+          cResult2 = 0;
+  
+        if(cResult == 0 && cResult2 == 0)	continue;
+  
+        if(cResult && cResult->bTimeOut) 	 {
+          strcpy(refTimeout, "TimeOut");
+        }
+        if(cResult2 && cResult2->bTimeOut) {
+          strcpy(newTimeout, "TimeOut");
+        }
+  
+        else if((cResult && !cResult->resultForProperty) &&
+                (cResult2 && !cResult2->resultForProperty))	continue;
+  
+        if(cResult)
+          pArr = cResult->resultForProperty;
+        else
+          pArr = 0;
+        if(cResult2)
+          pArr2 = cResult2->resultForProperty;
+        else
+          pArr2 = 0;
+  
+        if((!pArr || array_n(pArr) < 1) && (!pArr2 || array_n(pArr2) < 1)) {
+          continue;
+        }
+        else if(pArr && array_n(pArr) >= 1) {
+          pArrSample = pArr;
+        }
+        else if(pArr2 && array_n(pArr2) >= 1) {
+          pArrSample = pArr2;
+        }
+  
+        estLineNo = 0;
+        lastFailedIndex = -1;
+        for(j=0; j<array_n(pArrSample); j++) {
+          if(pArr && array_n(pArr) > j) 
+            rProp = array_fetch(RtResultPropertys_t *, pArr, j);
+          else
+            rProp = 0;
+          if(pArr2 && array_n(pArr2) > j) 
+            rProp2 = array_fetch(RtResultPropertys_t *, pArr2, j);
+          else
+            rProp2 = 0;
+  
+          if((rProp && !strncasecmp(rProp->failOrPass, "pass", 4)) && 
+	      (rProp2 && !strncasecmp(rProp2->failOrPass, "pass", 4))) {
+          }
+	  else {
+	    estLineNo++;
+	    lastFailedIndex = j;
+          }
+  
+        }
+  
+      /** 
+       * If the result table have more than 40 line then split the
+       * table.
+       **/
+        if(lineNo + estLineNo > 40) {
+          fprintf(fout, "\\hline\n");
+          fprintf(fout, "\\end{tabular}\n");
+          fprintf(fout, "\\end{center}\n");
+          fprintf(fout, "\\end{table}\n");
+	  fprintf(fout, "\\clearpage\n");
+	  fprintf(fout, "\\begin{table}\n");
+	  Rt_RemoveUnderscore(config->referenceVisNickName, refNName);
+	  Rt_RemoveUnderscore(config->newVisNickName, newNName);
+	  fprintf(fout, "\\caption{Property Comparison Table for \
+	  %s(ref) and %s(new)}\n", refNName, newNName);
+	  fprintf(fout, "\\begin{center}\n");
+          fprintf(fout, "\\begin{tabular}{|c||c|c||c|c|c||c|c|c||c|} \\hline\n");
+          fprintf(fout, " & & & \\multicolumn{3}{c||}{ Property(ref) } & \\multicolumn{3}{c||}{ Property(new) } & \\multicolumn{1}{c|}{ Remark }\\\\ \\cline{4-10}\n");
+          fprintf(fout, "Design & command & index & F or P & cex len & line len  & F or P & cex len  & line len& \\\\ \\hline\n");
+	  lineNo = 0;
+        }
+          
+        Rt_RemoveUnderscore(designList->designNickName, newName);
+        if(first_flag==0) {
+          fprintf(fout, "%s &", newName);
+	  first_flag = 1;
+        }
+        else
+          fprintf(fout, " &");
+  
+        for(j=0; j<array_n(pArrSample); j++) {
+  
+          lineNo++;
+          if(pArr && array_n(pArr) > j) 
+            rProp = array_fetch(RtResultPropertys_t *, pArr, j);
+          else
+            rProp = 0;
+          if(pArr2 && array_n(pArr2) > j) 
+            rProp2 = array_fetch(RtResultPropertys_t *, pArr2, j);
+          else
+            rProp2 = 0;
+	    
+          if(rProp && !strncasecmp(rProp->failOrPass, "pass", 4) && 
+	     rProp2 && !strncasecmp(rProp2->failOrPass, "pass", 4)) {
+	    if(j==0 && estLineNo == 0) {
+	      if(cResult)
+                 Rt_RemoveUnderscore(cResult->command, newName);
+	      else 
+                 Rt_RemoveUnderscore(cResult2->command, newName);
+              fprintf(fout, " %s & [%d] & passed & passed & - & passed & passed & - & \\\\ ", newName, rProp->index+1);
+	      if(j+1 == array_n(pArrSample) && i+1 == array_n(cResultArrSample)) 
+	        fprintf(fout, " \\hline\n");
+	      else if(j+1 == array_n(pArrSample))
+	        fprintf(fout, " \\cline{2-10}\n");
+	      else if(lastFailedIndex <= j && i+1 == array_n(cResultArrSample))   
+	        fprintf(fout, " \\hline\n");
+	      else if(lastFailedIndex <= j)   
+	        fprintf(fout, " \\cline{2-10}\n");
+              else 
+	        fprintf(fout, " \\cline{4-10}\n");
+	    }
+	    else {
+	      lineNo--;
+	    }
+	    continue;
+	  }
+  
+    
+          if(first_flag==1) {
+	    if(cResult) {
+              Rt_RemoveUnderscore(cResult->command, newName);
+              fprintf(fout, " %s & ", newName);
+            }
+	    else if(cResult2) {
+              Rt_RemoveUnderscore(cResult2->command, newName);
+              fprintf(fout, " %s & ", newName);
+            }
+	    first_flag = 2;
+          }
+	  else {
+            fprintf(fout, " & & ");
+          }
+  
+          if(rProp) {
+            if(rProp->lengthOfInv != -1) 
+              fprintf(fout, " [%d] & %s & (%d,-) & %d &", rProp->index+1, rProp->failOrPass, rProp->lengthOfInv, rProp->lengthOfCounterExample);
+	    else if(rProp->lengthOfStem == -1 && rProp->lengthOfCycle == -1)
+              fprintf(fout, " [%d] & %s & - & - &", rProp->index+1, rProp->failOrPass);
+	    else 
+              fprintf(fout, " [%d] & %s & (%d,%d) & %d & ", rProp->index+1, rProp->failOrPass, rProp->lengthOfStem, rProp->lengthOfCycle,rProp->lengthOfCounterExample );
+          }
+	  else {
+	    if(rProp2)
+              fprintf(fout, " [%d] & %s & %s & - & ", rProp2->index+1, refTimeout, refTimeout);
+	    else 
+              fprintf(fout, " & %s & %s & - & ", refTimeout, refTimeout);
+	  }
+  
+          if(rProp2) {
+            if(rProp2->lengthOfInv != -1) 
+              fprintf(fout, " %s & (%d,-) & %d ", rProp2->failOrPass,
+	      rProp2->lengthOfInv,rProp2->lengthOfCounterExample );
+	    else if(rProp2->lengthOfStem == -1 && rProp2->lengthOfCycle == -1)
+              fprintf(fout, " %s & - & - ", rProp2->failOrPass);
+	    else 
+              fprintf(fout, " %s & (%d,%d) & %d ", rProp2->failOrPass,
+	      rProp2->lengthOfStem, rProp2->lengthOfCycle, rProp2->lengthOfCounterExample);
+	  }
+	  else {
+            fprintf(fout, " %s & %s & - ", newTimeout, newTimeout);
+	  }
+  
+          endStr[0] = '\0';
+	  if(rProp2 && rProp) {
+	     if(rProp->failOrPass == 0 && rProp2->failOrPass)
+	       strcpy(endStr, "Check");
+	     else if(rProp->failOrPass && rProp2->failOrPass == 0)
+	       strcpy(endStr, "Check");
+	     if(rProp->failOrPass == 0 && rProp2->failOrPass == 0)
+	       strcpy(endStr, "Check");
+	     if(strcmp(rProp->failOrPass, rProp2->failOrPass))
+	       strcpy(endStr, "Check");
+	     else if(rProp->lengthOfStem != rProp2->lengthOfStem) 
+	       strcpy(endStr, "Check");
+             else if(rProp->lengthOfCycle != rProp2->lengthOfCycle)
+	       strcpy(endStr, "Check");
+             else if(rProp->lengthOfInv != rProp2->lengthOfInv)
+	       strcpy(endStr, "Check");
+	  }
+	  else {
+	    strcpy(endStr, "Check");
+	  }
+	  if(j+1 == array_n(pArrSample) && i+1 == array_n(cResultArrSample)) 
+	    fprintf(fout, " & %s \\\\ \\hline\n",endStr);
+	  else if(j+1 == array_n(pArrSample))
+	    fprintf(fout, " & %s \\\\ \\cline{2-10}\n",endStr);
+	  else if(lastFailedIndex <= j && i+1 == array_n(cResultArrSample))   
+	    fprintf(fout, " & %s \\\\ \\hline\n", endStr);
+	  else if(lastFailedIndex <= j)   
+	    fprintf(fout, " & %s \\\\ \\cline{2-10}\n", endStr);
+          else 
+	    fprintf(fout, " & %s \\\\ \\cline{4-10}\n",endStr);
+        }
+      }
+    }
+  
+    fprintf(fout, "\\end{tabular}\n");
+    fprintf(fout, "\\end{center}\n");
+    fprintf(fout, "\\end{table}\n");
+    fprintf(fout, "\\clearpage\n");
+  }
+
+
+  /** 
+   * Write the summary of comparison
+   **/
+  fprintf(fout, "\\begin{table}\n");
+  Rt_RemoveUnderscore(config->referenceVisNickName, refNName);
+  Rt_RemoveUnderscore(config->newVisNickName, newNName);
+  fprintf(fout, "\\caption{Summary for %s(ref) and %s(new)}\n", refNName, newNName);
+  fprintf(fout, "\\begin{center}\n");
+  fprintf(fout, "\\begin{tabular}{|c|c||c|c|c|c||r|r|} \\hline\n");
+  fprintf(fout, " command & item & \\multicolumn{4}{c||}{ %s } & \\multicolumn{2}{c|}{ geo-mean } \\\\ \\cline{3-8}\n", newNName);
+  fprintf(fout, " & & win & lose & tie & NA & ref & new \\\\ \\hline \\hline\n");
+
+  cResultArrMax = 0;
+  for(k=0; k<array_n(designArr) && k<size; k++) {
+    designList = array_fetch(RtDesignLists_t *, designArr, k);
+    cResultArr = designList->resultForCommandArr1;
+    if(cResultArrMax == 0)	cResultArrMax = cResultArr;
+    else if(cResultArr && array_n(cResultArr) > array_n(cResultArrMax)) {
+       cResultArrMax = cResultArr;
+    }
+  }
+
+  resultArr = ALLOC(double, 6); 
+  for(i=0; i<array_n(cResultArrMax); i++) {
+    cResultSample = array_fetch(RtCommandResults_t *, cResultArrMax, i);
+    fprintf(fout, " %s & ", cResultSample->command);
+    first_flag = 1;
+
+    cItemArrMax = 0;
+    for(k=0; k<array_n(designArr) && k<size; k++) {
+      designList = array_fetch(RtDesignLists_t *, designArr, k);
+      cResultArr = designList->resultForCommandArr1;
+      if(cResultArr)	{
+          if(array_n(cResultArr) > i) 
+              cResult = array_fetch(RtCommandResults_t *, cResultArr, i);
+          else
+	      continue;
+          cItemArrSample = cResult->compareItemArr;
+          if(cItemArrMax == 0)	cItemArrMax = cItemArrSample;
+	  else if(cItemArrSample && array_n(cItemArrSample) > array_n(cItemArrMax)) {
+	    cItemArrMax = cItemArrSample;
+	  }
+      }
+    }
+
+    for(j=0; j<6; j++)	resultArr[j] = 0.0;
+    resultArr[4] = 1.0;
+    resultArr[5] = 1.0;
+
+    for(j=0; j<array_n(cItemArrMax); j++) {
+      for(k=0; k<6; k++)	resultArr[k] = 0.0;
+      resultArr[4] = 1.0;
+      resultArr[5] = 1.0;
+
+      cItemSample = array_fetch(RtCompareItems_t *, cItemArrMax, j);
+      if(first_flag) {
+        fprintf(fout, "%s &\n", cItemSample->itemNickName);
+        first_flag = 0;
+      }
+      else {
+        fprintf(fout, " & %s &\n", cItemSample->itemNickName);
+      }
+
+      for(k=0; k<array_n(designArr) && k<size; k++) {
+        designList = array_fetch(RtDesignLists_t *, designArr, k);
+	if(designList->resultForCommandArr1 == 0 ||
+	   designList->resultForCommandArr2 == 0) {
+	   resultArr[3] = resultArr[3] + 1.0;
+	   continue;
+        }
+	if(array_n(designList->resultForCommandArr1) <= i ||
+	   array_n(designList->resultForCommandArr2) <= i) {
+	   resultArr[3] = resultArr[3] + 1.0;
+	   continue;
+        }
+        cResult = array_fetch(RtCommandResults_t *, designList->resultForCommandArr1, i);
+        cResult2 = array_fetch(RtCommandResults_t *, designList->resultForCommandArr2, i);
+	if(cResult == 0 || cResult2 == 0) {
+	   resultArr[3] = resultArr[3] + 1.0;
+	   continue;
+        }
+	if(cResult->compareItemArr == 0 ||
+	   cResult2->compareItemArr == 0) {
+	   resultArr[3] = resultArr[3] + 1.0;
+	   continue;
+        }
+	if(array_n(cResult->compareItemArr) <= j ||
+	   array_n(cResult2->compareItemArr) <= j) {
+	   resultArr[3] = resultArr[3] + 1.0;
+	   continue;
+        }
+        cItem = array_fetch(RtCompareItems_t *, cResult->compareItemArr, j);
+        cItem2 = array_fetch(RtCompareItems_t *, cResult2->compareItemArr, j);
+	if(cItem == 0 || cItem2 == 0) {
+	   resultArr[3] = resultArr[3] + 1.0;
+	   continue;
+        }
+
+	value1 = atof(cItem->value);
+	value2 = atof(cItem2->value);
+	if(value1 > value2)	gap = value2;
+	else			gap = value1;
+	gap = gap * 0.02;
+	if(gap < 1.0)	gap = 1.0;
+
+	if(value1 > value2 + gap)	resultArr[0] = resultArr[0] + 1.0; /** new win **/
+	else if(value1+gap < value2)	resultArr[1] = resultArr[1] + 1.0; /** ref win **/
+	else 				resultArr[2] += 1.0; /** tie **/
+      }
+      totalNum = resultArr[0] + resultArr[1] + resultArr[2];
+      totalNum = 1.0/totalNum;
+      for(k=0; k<array_n(designArr) && k<size; k++) {
+        designList = array_fetch(RtDesignLists_t *, designArr, k);
+	if(designList->resultForCommandArr1 == 0 ||
+	   designList->resultForCommandArr2 == 0) {
+	   continue;
+        }
+	if(array_n(designList->resultForCommandArr1) <= i ||
+	   array_n(designList->resultForCommandArr2) <= i) {
+	   continue;
+        }
+        cResult = array_fetch(RtCommandResults_t *, designList->resultForCommandArr1, i);
+        cResult2 = array_fetch(RtCommandResults_t *, designList->resultForCommandArr2, i);
+	if(cResult == 0 || cResult2 == 0) {
+	   continue;
+        }
+	if(cResult->compareItemArr == 0 ||
+	   cResult2->compareItemArr == 0) {
+	   continue;
+        }
+	if(array_n(cResult->compareItemArr) <= j ||
+	   array_n(cResult2->compareItemArr) <= j) {
+	   continue;
+        }
+        cItem = array_fetch(RtCompareItems_t *, cResult->compareItemArr, j);
+        cItem2 = array_fetch(RtCompareItems_t *, cResult2->compareItemArr, j);
+	if(cItem == 0 || cItem2 == 0) {
+	   continue;
+        }
+
+	value1 = atof(cItem->value);
+	value2 = atof(cItem2->value);
+	if(value1 == 0.0)	value1 = 1.0;
+	else 			value1 = pow(value1, totalNum);
+	if(value2 == 0.0)	value2 = 1.0;
+	else 			value2 = pow(value2, totalNum);
+
+	resultArr[4] *= value1;
+	resultArr[5] *= value2;
+      }
+
+      if(array_n(cItemArrMax) == j+1 ) {
+        fprintf(fout, " %d & %d & %d & %d & %.3f & %.3f \\\\ \\hline\n", 
+                    (int)resultArr[0], (int)resultArr[1], (int)resultArr[2],
+		    (int)resultArr[3], resultArr[4], resultArr[5]);
+      }
+      else {
+        fprintf(fout, " %d & %d & %d & %d & %.3f & %.3f \\\\ \\cline{2-8}\n", 
+                    (int)resultArr[0], (int)resultArr[1], (int)resultArr[2],
+		    (int)resultArr[3], resultArr[4], resultArr[5]);
+      }
+    }
+  }
+  free(resultArr);
+  fprintf(fout, "\\end{tabular}\n");
+  fprintf(fout, "\\end{center}\n");
+  fprintf(fout, "\\end{table}\n");
+
+  fprintf(fout, "\\begin{itemize}\n");
+  Rt_RemoveUnderscore(config->configurationFile, newName);
+  fprintf(fout, "\\item configuration file : %s\n", newName);
+  Rt_RemoveUnderscore(config->designDirectory, newName);
+  fprintf(fout, "\\item design directory : %s\n", newName);
+  Rt_RemoveUnderscore(config->designList, newName);
+  fprintf(fout, "\\item design list : %s\n", newName);
+  Rt_RemoveUnderscore(config->referenceOutDirectory, newName);
+  fprintf(fout, "\\item reference output dir : %s\n", newName);
+  Rt_RemoveUnderscore(config->referenceVis, newName);
+  fprintf(fout, "\\item reference executable : %s\n", newName);
+  Rt_RemoveUnderscore(config->refCommandTemplate, newName);
+  fprintf(fout, "\\item reference template : %s\n", newName);
+  Rt_RemoveUnderscore(config->newOutDirectory, newName);
+  fprintf(fout, "\\item new output dir : %s\n", newName);
+  Rt_RemoveUnderscore(config->newVis, newName);
+  fprintf(fout, "\\item new executable : %s\n", newName);
+  Rt_RemoveUnderscore(config->newCommandTemplate, newName);
+  fprintf(fout, "\\item new template : %s\n", newName);
+  fprintf(fout, "\\end{itemize}\n");
+  fprintf(fout, "\\clearpage\n");
+
+  fprintf(fout, "\\end{document}\n");
+  fclose(fout);
+  fprintf(vis_stdout, "'%s' file was generated as result of regression_test\n", 
+               config->resultForPerformance);
+  return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Remove underscopre from the string. ]
+
+  Description [Remove underscore from the given string, since LaTeX consider
+               underscore as subscript keyword. ]
+
+  Comment []
+
+  SideEffects []
+
+******************************************************************************/
+static void
+Rt_RemoveUnderscore(char *name, 
+                    char *newName)
+{
+int i, index ;
+
+  index = 0;
+  for(i=0; name[i] != '\0'; i++) {
+    if(name[i] == '_') {
+      newName[index++] = '\\';
+    }
+    newName[index++] = name[i];
+  }
+  newName[index] = '\0';
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Read the log file of both runs, and then store the information
+               in the internal data structure. ]
+
+  Description [Read the log file of runs, Current version supports
+    reachability analysis, CTL model checking and invariant checking.
+    If that is not the case, it may read the log file without errors
+    except the couterexample trace.]
+
+  Comment []
+
+  SideEffects []
+
+******************************************************************************/
+static int
+Rt_CompareResult(RtConfigs_t *config,
+                 RtDesignLists_t *designList,
+		 int refOnly)
+{
+  FILE *fin1, *fin2;
+  char filename1[1024], filename2[1024];
+  char line[1024], *next;
+  RtCompareItems_t *item, *newItem;
+  RtResultPropertys_t *rProperty;
+  RtCommandResults_t *cResult;
+  int argc;
+  char **argv;
+  int i, len;
+  int propertyIndex;
+  int formulaSummary, commandBeginFlag;
+  int basicLength, stemLength, cycleLength;
+  int propertyIndexSummary, pIndex;
+  int invCheckFlag;
+  int nLine, countLineFlag;
+  array_t *itemArr;
+
+  propertyIndex = -1;
+  basicLength = 0;
+  stemLength = 0;
+  cycleLength = 0;
+  invCheckFlag = 0;
+  propertyIndexSummary = 0;
+
+  sprintf(filename1, "%s/%s/%s.out", config->referenceOutDirectory, 
+  		                     designList->designNickName, 
+  		                     designList->designNickName); 
+  if(!(fin1 = fopen(filename1, "r"))) {
+    fprintf(vis_stdout, "Error : Can't open result file '%s'\n", filename1);
+    return(1);
+  }
+
+  fin2 = 0;
+  if(!refOnly) {
+    sprintf(filename2, "%s/%s/%s.out", config->newOutDirectory, 
+  		                     designList->designNickName, 
+  		                     designList->designNickName); 
+    if(!(fin2 = fopen(filename2, "r"))) {
+      fprintf(vis_stdout, "Error : Can't open result file '%s'\n", filename2);
+      return(1);
+    }
+  }
+
+  /** 
+   * Compile the log file based on keywords, such as CommandEnd,
+   * CommandBegin, # MC: formula, etc,. If timeout case is detected the
+   * fill the data structure with 'TimeOut'.
+   **/
+  itemArr = config->compareItemArr;
+  cResult = 0;
+  formulaSummary = 0;
+  commandBeginFlag = 0;
+  nLine = 0;
+  countLineFlag = 0;
+  rProperty = 0;
+  while(fgets(line, 1024, fin1)) {
+    if(countLineFlag) 	nLine++;
+    if(line[0] == '\n')	continue;
+    if(!strncasecmp(line, "CommandEnd", 10)) {
+      if(rProperty && countLineFlag)	{
+	rProperty->lengthOfCounterExample = nLine;
+	if(rProperty->lengthOfBasic > -1) {
+	  if(rProperty->lengthOfStem > -1)
+	    rProperty->lengthOfStem = rProperty->lengthOfStem+rProperty->lengthOfBasic-1;
+	  else
+	    rProperty->lengthOfStem = rProperty->lengthOfBasic;
+	}
+      }
+      countLineFlag = 0;
+      nLine = 0;
+      rProperty = 0;
+      commandBeginFlag = 0;
+    }
+    else if(!strncasecmp(line, "CommandBegin", 12)) {
+      propertyIndex = -1;
+      rProperty = 0;
+      formulaSummary = 0;
+      commandBeginFlag = 1;
+      Rt_SplitLine(line, &argc, &argv);
+      if(designList->resultForCommandArr1 == 0)
+        designList->resultForCommandArr1= array_alloc(RtCommandResults_t *, 0);
+      cResult = ALLOC(RtCommandResults_t, 1);
+      cResult->resultForProperty = 0;
+      cResult->compareItemArr = 0;
+      cResult->command = strdup(argv[1]);
+      cResult->bTimeOut = 0;
+      array_insert_last(RtCommandResults_t *, designList->resultForCommandArr1,
+      cResult);
+      Rt_FreeArgv(argc, argv);
+      continue;
+    }
+    else if(!strncasecmp(line, "** cmd error", 12)) {
+      if(cResult)
+        cResult->error = 1;
+      fprintf(vis_stdout, "ERROR : Command error was found in the output '%s'\n",
+      designList->designNickName);
+      continue;
+    }
+    else if(!strncasecmp(line, "# MC: formula", 13) && !formulaSummary) {
+      if(rProperty && countLineFlag)	{
+	rProperty->lengthOfCounterExample = nLine;
+	if(rProperty->lengthOfBasic > -1) {
+	  if(rProperty->lengthOfStem > -1)
+	    rProperty->lengthOfStem = rProperty->lengthOfStem+rProperty->lengthOfBasic-1;
+	  else
+	    rProperty->lengthOfStem = rProperty->lengthOfBasic;
+	}
+      }
+      countLineFlag = 0;
+      nLine = 0;
+      propertyIndex++;
+      Rt_SplitLine(&line[13], &argc, &argv);
+      rProperty = ALLOC(RtResultPropertys_t, 1);
+      rProperty->lengthOfBasic = -1;
+      rProperty->lengthOfStem = -1;
+      rProperty->lengthOfCycle = -1;
+      rProperty->lengthOfInv = -1;
+      rProperty->lengthOfCounterExample = -1;
+      rProperty->index = propertyIndex;
+      rProperty->failOrPass = strdup(argv[0]);
+      if(cResult->resultForProperty == 0)
+        cResult->resultForProperty = array_alloc(RtResultPropertys_t *, 0);
+      array_insert_last(RtResultPropertys_t *,cResult->resultForProperty, rProperty); 
+      basicLength = 1;
+      stemLength = 0;
+      cycleLength = 0;
+      invCheckFlag = 0;
+      Rt_FreeArgv(argc, argv);
+      continue;
+    }
+    else if((!strncasecmp(line, "# AMC: formula", 14) ||
+	     !strncasecmp(line, "# IMC: formula", 14) ||
+	     !strncasecmp(line, "# BMC: formula", 14) ||
+	     !strncasecmp(line, "# ABS: formula", 14)) && !formulaSummary) {
+      if(rProperty && countLineFlag)	{
+	rProperty->lengthOfCounterExample = nLine;
+	if(rProperty->lengthOfBasic > -1) {
+	  if(rProperty->lengthOfStem > -1)
+	    rProperty->lengthOfStem = rProperty->lengthOfStem+rProperty->lengthOfBasic-1;
+	  else
+	    rProperty->lengthOfStem = rProperty->lengthOfBasic;
+	}
+      }
+      countLineFlag = 0;
+      nLine = 0;
+      propertyIndex++;
+      Rt_SplitLine(&line[14], &argc, &argv);
+      rProperty = ALLOC(RtResultPropertys_t, 1);
+      rProperty->lengthOfBasic = -1;
+      rProperty->lengthOfStem = -1;
+      rProperty->lengthOfCycle = -1;
+      rProperty->lengthOfInv = -1;
+      rProperty->lengthOfCounterExample = -1; 
+      rProperty->index = propertyIndex;
+      rProperty->failOrPass = strdup(argv[0]);
+      if(cResult->resultForProperty == 0)
+        cResult->resultForProperty = array_alloc(RtResultPropertys_t *, 0);
+      array_insert_last(RtResultPropertys_t *,cResult->resultForProperty, rProperty); 
+      basicLength = 1;
+      stemLength = 0;
+      cycleLength = 0;
+      invCheckFlag = 0;
+      Rt_FreeArgv(argc, argv);
+      continue;
+    }
+    else if(!strncasecmp(line, "# LTL_MC: formula", 17) && !formulaSummary) {
+      if(rProperty && countLineFlag)	{
+	rProperty->lengthOfCounterExample = nLine;
+	if(rProperty->lengthOfBasic > -1) {
+	  if(rProperty->lengthOfStem > -1)
+	    rProperty->lengthOfStem = rProperty->lengthOfStem+rProperty->lengthOfBasic-1;
+	  else
+	    rProperty->lengthOfStem = rProperty->lengthOfBasic;
+	}
+      }
+      countLineFlag = 0;
+      nLine = 0;
+      propertyIndex++;
+      Rt_SplitLine(&line[17], &argc, &argv);
+      rProperty = ALLOC(RtResultPropertys_t, 1);
+      rProperty->lengthOfBasic = -1;
+      rProperty->lengthOfStem = -1;
+      rProperty->lengthOfCycle = -1;
+      rProperty->lengthOfInv = -1;
+      rProperty->lengthOfCounterExample = -1;
+      rProperty->index = propertyIndex;
+      rProperty->failOrPass = strdup(argv[0]);
+      if(cResult->resultForProperty == 0)
+        cResult->resultForProperty = array_alloc(RtResultPropertys_t *, 0);
+      array_insert_last(RtResultPropertys_t *,cResult->resultForProperty, rProperty); 
+      basicLength = 1;
+      stemLength = 0;
+      cycleLength = 0;
+      invCheckFlag = 0;
+      Rt_FreeArgv(argc, argv);
+      continue;
+    }
+    else if(!strncasecmp(line, "--Fair path stem:", 17)) {
+      basicLength = 0;
+      stemLength = 1;
+      cycleLength = 0;
+      rProperty->lengthOfInv = -1;
+      continue;
+    }
+    else if(!strncasecmp(line, "--Fair path cycle:", 18)) {
+      basicLength = 0;
+      stemLength = 0;
+      cycleLength = 1;
+      rProperty->lengthOfInv = -1;
+      continue;
+    }
+    else if(!strncasecmp(line, "# LTL_MC: fair cycle:", 21)) {
+      basicLength = 0;
+      stemLength = 0;
+      cycleLength = 1;
+      rProperty->lengthOfInv = -1;
+      continue;
+    }
+    else if(!strncasecmp(line, "--State ", 8)) {
+      if(rProperty == 0) {
+	fprintf(stdout, "ERROR : The counterexample followed without keyword\n");
+	continue;
+      }
+      Rt_SplitLine(&line[8], &argc, &argv);
+      len = strlen(argv[0]);
+      if(argv[0][len-1] == ':') argv[0][len-1] = '\0';
+      if(basicLength) 		rProperty->lengthOfBasic = atoi(argv[0]);
+      else if(stemLength) 	rProperty->lengthOfStem = atoi(argv[0]);
+      else if(cycleLength)	rProperty->lengthOfCycle = atoi(argv[0]);
+      else if(invCheckFlag)	rProperty->lengthOfInv = atoi(argv[0]);
+
+      if(stemLength || cycleLength)	rProperty->lengthOfInv = -1;
+      Rt_FreeArgv(argc, argv);
+      if(countLineFlag == 0)	countLineFlag = 1;
+      continue;
+    }
+    else if(!strncasecmp(line, "--Goes to state ", 16)) {
+      if(rProperty == 0) {
+	fprintf(stdout, "ERROR : The counterexample followed without keyword\n");
+	continue;
+      }
+      Rt_SplitLine(&line[16], &argc, &argv);
+      len = strlen(argv[0]);
+      if(argv[0][len-1] == ':') argv[0][len-1] = '\0';
+      if(basicLength) 		rProperty->lengthOfBasic = atoi(argv[0]);
+      else if(stemLength) 	rProperty->lengthOfStem = atoi(argv[0]);
+      else if(cycleLength)	rProperty->lengthOfCycle = atoi(argv[0]);
+      else if(invCheckFlag)	rProperty->lengthOfInv = atoi(argv[0]);
+
+      if(stemLength || cycleLength)	rProperty->lengthOfInv = -1;
+      Rt_FreeArgv(argc, argv);
+      continue;
+    }
+    else if(!strncasecmp(line, "# INV: formula", 14)  && formulaSummary) {
+      invCheckFlag = 1;
+      basicLength = 0;
+      Rt_SplitLine(&line[14], &argc, &argv);
+      if(cResult->resultForProperty == 0)
+        cResult->resultForProperty = array_alloc(RtResultPropertys_t *, 0);
+      if(array_n(cResult->resultForProperty) >= propertyIndexSummary) {
+          rProperty = array_fetch(RtResultPropertys_t *, cResult->resultForProperty,
+	  propertyIndexSummary-1); 
+	  if(!rProperty) {
+            rProperty = ALLOC(RtResultPropertys_t, 1);
+            array_insert(RtResultPropertys_t *,cResult->resultForProperty,
+	    propertyIndexSummary-1, rProperty); 
+	    rProperty->lengthOfStem = -1;
+	    rProperty->lengthOfCycle = -1;
+	    rProperty->lengthOfInv = -1;
+	    rProperty->lengthOfCounterExample = -1; 
+	    rProperty->index = propertyIndexSummary;
+	  }
+	  if(rProperty->index != propertyIndexSummary) {
+	      fprintf(vis_stdout, "Error when compiling log file \n");
+	  }
+      }
+      else {
+          rProperty = ALLOC(RtResultPropertys_t, 1);
+          array_insert(RtResultPropertys_t *,cResult->resultForProperty,
+	  propertyIndexSummary-1, rProperty); 
+	  rProperty->lengthOfStem = -1;
+	  rProperty->lengthOfCycle = -1;
+	  rProperty->lengthOfInv = -1;
+	  rProperty->lengthOfCounterExample = -1; 
+	  rProperty->index = propertyIndexSummary;
+      }
+      if(argv[0][0] == 'f' || argv[0][0] == 'p')
+        rProperty->failOrPass = strdup(argv[0]);
+      else
+        rProperty->failOrPass = strdup(argv[1]);
+      basicLength = 0;
+      stemLength = 0;
+      cycleLength = 0;
+      Rt_FreeArgv(argc, argv);
+      propertyIndexSummary++;
+      continue;
+    }
+    else if(!strncasecmp(line, "# INV: formula", 14)  && !formulaSummary) {
+      invCheckFlag = 1;
+      if(rProperty && countLineFlag)	rProperty->lengthOfCounterExample = nLine;
+      countLineFlag = 0;
+      nLine = 0;
+      Rt_SplitLine(&line[14], &argc, &argv);
+      if(Rt_IsNum(argv[0])) {
+	  if(cResult->resultForProperty == 0)
+	    cResult->resultForProperty = array_alloc(RtResultPropertys_t *, 0);
+          pIndex = atoi(argv[0]);
+	  if(array_n(cResult->resultForProperty) > pIndex) {
+	      rProperty = array_fetch(RtResultPropertys_t *,
+	      cResult->resultForProperty, pIndex-1); 
+	      if(!rProperty) {
+		  rProperty = ALLOC(RtResultPropertys_t, 1);
+		  array_insert(RtResultPropertys_t *,cResult->resultForProperty,
+		  pIndex-1, rProperty); 
+		  rProperty->lengthOfStem = -1;
+		  rProperty->lengthOfCycle = -1;
+		  rProperty->lengthOfInv = -1;
+	  	  rProperty->lengthOfCounterExample = -1; 
+		  rProperty->index = pIndex;
+	      }
+	      if(rProperty->index != pIndex) {
+		  fprintf(vis_stdout, "Error when compiling log file \n");
+	      }
+	  }
+	  else {
+	      rProperty = ALLOC(RtResultPropertys_t, 1);
+	      array_insert(RtResultPropertys_t *,cResult->resultForProperty,
+	      pIndex-1, rProperty); 
+	      rProperty->lengthOfStem = -1;
+	      rProperty->lengthOfCycle = -1;
+	      rProperty->lengthOfInv = -1;
+	      rProperty->lengthOfCounterExample = -1; 
+	      rProperty->index = pIndex;
+	  }
+	  if(argv[1][0] == 'f' || argv[1][0] == 'p')
+	    rProperty->failOrPass = strdup(argv[1]);
+	  else
+	    rProperty->failOrPass = strdup(argv[2]);
+	  basicLength = 0;
+	  stemLength = 0;
+	  cycleLength = 0;
+	  Rt_FreeArgv(argc, argv);
+      }
+      continue;
+    }
+    else if(!strncasecmp(line, "# INV: Summary", 14)) {
+      if(rProperty && countLineFlag)	rProperty->lengthOfCounterExample = nLine;
+      countLineFlag = 0;
+      nLine = 0;
+      formulaSummary = 1;
+      propertyIndexSummary = 1;
+      continue;
+    }
+    next = strstr(line, "timeout");
+    if(next == 0) 
+        next = strstr(line, "Timeout");
+    if(next) {
+        if(!strncasecmp(next, "timeout occurred after", 22)) {
+	    cResult->bTimeOut = 1;
+	}
+	else if(!strncasecmp(next, "timeout after", 14)) {
+	    cResult->bTimeOut = 1;
+	}
+    }
+    for(i=0; i<array_n(itemArr); i++) {
+      item = array_fetch(RtCompareItems_t *, itemArr, i);
+      len = strlen(item->itemName);
+      if(!strncasecmp(item->itemName, line, len)) {
+        newItem = ALLOC(RtCompareItems_t, 1);
+	newItem->itemNickName = strdup(item->itemNickName);
+	newItem->itemName = 0;
+	newItem->value = 0;
+	Rt_SplitLine(&line[len], &argc, &argv);
+	newItem->value = strdup(argv[0]);
+	if(cResult->compareItemArr == 0)
+	  cResult->compareItemArr = array_alloc(RtCompareItems_t *, 0);
+	array_insert_last(RtCompareItems_t *, cResult->compareItemArr, newItem);
+        Rt_FreeArgv(argc, argv);
+	break;
+      }
+    }
+  }
+  if(commandBeginFlag == 1) {
+    if(cResult->resultForProperty && array_n(cResult->resultForProperty) == 0) 
+      cResult->resultForProperty = 0;
+    cResult->compareItemArr = 0;
+  }
+
+  cResult = 0;
+  commandBeginFlag = 0;
+  nLine = 0;
+  countLineFlag = 0;
+  rProperty = 0;
+  while(fgets(line, 1024, fin2)) {
+    if(countLineFlag) nLine++;
+    if(line[0] == '\n')	continue;
+    if(!strncasecmp(line, "CommandEnd", 10)) {
+      if(rProperty && countLineFlag)	{
+	rProperty->lengthOfCounterExample = nLine;
+	if(rProperty->lengthOfBasic > -1) {
+	  if(rProperty->lengthOfStem > -1)
+	    rProperty->lengthOfStem = rProperty->lengthOfStem+rProperty->lengthOfBasic-1;
+	  else
+	    rProperty->lengthOfStem = rProperty->lengthOfBasic;
+	}
+      }
+      countLineFlag = 0;
+      rProperty = 0;
+      nLine = 0;
+      commandBeginFlag = 0;
+    }
+    else if(!strncasecmp(line, "CommandBegin", 12)) {
+      propertyIndex = -1;
+      rProperty = 0;
+      formulaSummary = 0;
+      commandBeginFlag = 1;
+      Rt_SplitLine(line, &argc, &argv);
+      if(designList->resultForCommandArr2 == 0)
+        designList->resultForCommandArr2= array_alloc(RtCommandResults_t *, 0);
+      cResult = ALLOC(RtCommandResults_t, 1);
+      cResult->resultForProperty = 0;
+      cResult->compareItemArr = 0;
+      cResult->bTimeOut = 0;
+      cResult->command = strdup(argv[1]);
+      array_insert_last(RtCommandResults_t *, designList->resultForCommandArr2,
+      cResult);
+      Rt_FreeArgv(argc, argv);
+      continue;
+    }
+    else if(!strncasecmp(line, "** cmd error", 12)) {
+      if(cResult)
+        cResult->error = 1;
+      fprintf(vis_stdout, "ERROR : Command error was found in the output '%s'\n",
+      designList->designNickName);
+      continue;
+    }
+    else if(!strncasecmp(line, "# MC: formula", 13) && !formulaSummary) {
+      if(rProperty && countLineFlag)	{
+	rProperty->lengthOfCounterExample = nLine;
+	if(rProperty->lengthOfBasic > -1) {
+	  if(rProperty->lengthOfStem > -1)
+	    rProperty->lengthOfStem = rProperty->lengthOfStem+rProperty->lengthOfBasic-1;
+	  else
+	    rProperty->lengthOfStem = rProperty->lengthOfBasic;
+	}
+      }
+      countLineFlag = 0;
+      nLine = 0;
+      propertyIndex++;
+      Rt_SplitLine(&line[13], &argc, &argv);
+      rProperty = ALLOC(RtResultPropertys_t, 1);
+      rProperty->lengthOfBasic = -1;
+      rProperty->lengthOfStem = -1;
+      rProperty->lengthOfCycle = -1;
+      rProperty->lengthOfInv = -1;
+      rProperty->lengthOfCounterExample = -1; 
+      rProperty->index = propertyIndex;
+      rProperty->failOrPass = strdup(argv[0]);
+      if(cResult->resultForProperty == 0)
+        cResult->resultForProperty = array_alloc(RtResultPropertys_t *, 0);
+      array_insert_last(RtResultPropertys_t *,cResult->resultForProperty, rProperty); 
+      basicLength = 1;
+      stemLength = 0;
+      cycleLength = 0;
+      invCheckFlag = 0;
+      Rt_FreeArgv(argc, argv);
+      continue;
+    }
+    else if((!strncasecmp(line, "# AMC: formula", 14) ||
+	     !strncasecmp(line, "# IMC: formula", 14) ||
+	     !strncasecmp(line, "# BMC: formula", 14) ||
+	     !strncasecmp(line, "# ABS: formula", 14)) && !formulaSummary) {
+      if(rProperty && countLineFlag)	{
+	rProperty->lengthOfCounterExample = nLine;
+	if(rProperty->lengthOfBasic > -1) {
+	  if(rProperty->lengthOfStem > -1)
+	    rProperty->lengthOfStem = rProperty->lengthOfStem+rProperty->lengthOfBasic-1;
+	  else
+	    rProperty->lengthOfStem = rProperty->lengthOfBasic;
+	}
+      }
+      countLineFlag = 0;
+      nLine = 0;
+      propertyIndex++;
+      Rt_SplitLine(&line[14], &argc, &argv);
+      rProperty = ALLOC(RtResultPropertys_t, 1);
+      rProperty->lengthOfBasic = -1;
+      rProperty->lengthOfStem = -1;
+      rProperty->lengthOfCycle = -1;
+      rProperty->lengthOfInv = -1;
+      rProperty->lengthOfCounterExample = -1; 
+      rProperty->index = propertyIndex;
+      rProperty->failOrPass = strdup(argv[0]);
+      if(cResult->resultForProperty == 0)
+        cResult->resultForProperty = array_alloc(RtResultPropertys_t *, 0);
+      array_insert_last(RtResultPropertys_t *,cResult->resultForProperty, rProperty); 
+      basicLength = 1;
+      stemLength = 0;
+      cycleLength = 0;
+      invCheckFlag = 0;
+      Rt_FreeArgv(argc, argv);
+      continue;
+    }
+    else if(!strncasecmp(line, "# LTL_MC: formula", 17) && !formulaSummary) {
+      if(rProperty && countLineFlag)	{
+	rProperty->lengthOfCounterExample = nLine;
+	if(rProperty->lengthOfBasic > -1) {
+	  if(rProperty->lengthOfStem > -1)
+	    rProperty->lengthOfStem = rProperty->lengthOfStem+rProperty->lengthOfBasic-1;
+	  else
+	    rProperty->lengthOfStem = rProperty->lengthOfBasic;
+	}
+      }
+      countLineFlag = 0;
+      nLine = 0;
+      propertyIndex++;
+      Rt_SplitLine(&line[17], &argc, &argv);
+      rProperty = ALLOC(RtResultPropertys_t, 1);
+      rProperty->lengthOfBasic = -1;
+      rProperty->lengthOfStem = -1;
+      rProperty->lengthOfCycle = -1;
+      rProperty->lengthOfInv = -1;
+      rProperty->lengthOfCounterExample = -1; 
+      rProperty->index = propertyIndex;
+      rProperty->failOrPass = strdup(argv[0]);
+      if(cResult->resultForProperty == 0)
+        cResult->resultForProperty = array_alloc(RtResultPropertys_t *, 0);
+      array_insert_last(RtResultPropertys_t *,cResult->resultForProperty, rProperty); 
+      basicLength = 1;
+      stemLength = 0;
+      cycleLength = 0;
+      invCheckFlag = 0;
+      Rt_FreeArgv(argc, argv);
+      continue;
+    }
+    else if(!strncasecmp(line, "--Fair path stem:", 17)) {
+      basicLength = 0;
+      stemLength = 1;
+      cycleLength = 0;
+      rProperty->lengthOfInv = -1;
+      continue;
+    }
+    else if(!strncasecmp(line, "--Fair path cycle:", 18)) {
+      basicLength = 0;
+      stemLength = 0;
+      cycleLength = 1;
+      rProperty->lengthOfInv = -1;
+      continue;
+    }
+    else if(!strncasecmp(line, "# LTL_MC: fair cycle:", 21)) {
+      basicLength = 0;
+      stemLength = 0;
+      cycleLength = 1;
+      rProperty->lengthOfInv = -1;
+      continue;
+    }
+    else if(!strncasecmp(line, "--State ", 8)) {
+      if(rProperty == 0) {
+	fprintf(stdout, "ERROR : The counterexample followed without keyword\n");
+	continue;
+      }
+      Rt_SplitLine(&line[8], &argc, &argv);
+      len = strlen(argv[0]);
+      if(argv[0][len-1] == ':') argv[0][len-1] = '\0';
+      if(basicLength) 		rProperty->lengthOfBasic = atoi(argv[0]);
+      else if(stemLength) 		rProperty->lengthOfStem = atoi(argv[0]);
+      else if(cycleLength)	rProperty->lengthOfCycle = atoi(argv[0]);
+      else if(invCheckFlag)	rProperty->lengthOfInv = atoi(argv[0]);
+      if(stemLength || cycleLength)	rProperty->lengthOfInv = -1;
+      if(countLineFlag == 0)	countLineFlag = 1;
+      Rt_FreeArgv(argc, argv);
+      continue;
+    }
+    else if(!strncasecmp(line, "--Goes to state ", 16)) {
+      if(rProperty == 0) {
+	fprintf(stdout, "ERROR : The counterexample followed without keyword\n");
+	continue;
+      }
+      Rt_SplitLine(&line[16], &argc, &argv);
+      len = strlen(argv[0]);
+      if(argv[0][len-1] == ':') argv[0][len-1] = '\0';
+      if(basicLength) 		rProperty->lengthOfBasic = atoi(argv[0]);
+      else if(stemLength) 	rProperty->lengthOfStem = atoi(argv[0]);
+      else if(cycleLength)	rProperty->lengthOfCycle = atoi(argv[0]);
+      else if(invCheckFlag)	rProperty->lengthOfInv = atoi(argv[0]);
+      if(stemLength || cycleLength)	rProperty->lengthOfInv = -1;
+
+      Rt_FreeArgv(argc, argv);
+      continue;
+    }
+    else if(!strncasecmp(line, "# INV: formula", 14)  && formulaSummary) {
+      Rt_SplitLine(&line[14], &argc, &argv);
+      invCheckFlag = 1;
+      if(cResult->resultForProperty == 0)
+        cResult->resultForProperty = array_alloc(RtResultPropertys_t *, 0);
+      if(array_n(cResult->resultForProperty) >= propertyIndexSummary) {
+          rProperty = array_fetch(RtResultPropertys_t *, cResult->resultForProperty,
+	  propertyIndexSummary-1); 
+	  if(!rProperty) {
+            rProperty = ALLOC(RtResultPropertys_t, 1);
+            array_insert(RtResultPropertys_t *,cResult->resultForProperty,
+	    propertyIndexSummary-1, rProperty); 
+	    rProperty->lengthOfStem = -1;
+	    rProperty->lengthOfCycle = -1;
+	    rProperty->lengthOfInv = -1;
+	    rProperty->lengthOfCounterExample = -1;
+	    rProperty->index = propertyIndexSummary;
+	  }
+	  if(rProperty->index != propertyIndexSummary) {
+	      fprintf(vis_stdout, "Error when compiling log file \n");
+	  }
+      }
+      else {
+          rProperty = ALLOC(RtResultPropertys_t, 1);
+          array_insert(RtResultPropertys_t *,cResult->resultForProperty,
+	  propertyIndexSummary-1, rProperty); 
+	  rProperty->lengthOfStem = -1;
+	  rProperty->lengthOfCycle = -1;
+	  rProperty->lengthOfInv = -1;
+	  rProperty->lengthOfCounterExample = -1;
+	  rProperty->index = propertyIndexSummary;
+      }
+      if(argv[0][0] == 'f' || argv[0][0] == 'p')
+        rProperty->failOrPass = strdup(argv[0]);
+      else
+        rProperty->failOrPass = strdup(argv[1]);
+      stemLength = 0;
+      cycleLength = 0;
+      Rt_FreeArgv(argc, argv);
+      propertyIndexSummary++;
+      continue;
+    }
+    else if(!strncasecmp(line, "# INV: formula", 14)  && !formulaSummary) {
+      invCheckFlag = 1;
+      if(rProperty && countLineFlag)	rProperty->lengthOfCounterExample = nLine;
+      countLineFlag = 0;
+      nLine = 0;
+      Rt_SplitLine(&line[14], &argc, &argv);
+      if(Rt_IsNum(argv[0])) {
+	  if(cResult->resultForProperty == 0)
+	    cResult->resultForProperty = array_alloc(RtResultPropertys_t *, 0);
+          pIndex = atoi(argv[0]);
+	  if(array_n(cResult->resultForProperty) > pIndex) {
+	      rProperty = array_fetch(RtResultPropertys_t *,
+	      cResult->resultForProperty, pIndex-1); 
+	      if(!rProperty) {
+		  rProperty = ALLOC(RtResultPropertys_t, 1);
+		  array_insert(RtResultPropertys_t *,cResult->resultForProperty,
+		  pIndex-1, rProperty); 
+		  rProperty->lengthOfStem = -1;
+		  rProperty->lengthOfCycle = -1;
+		  rProperty->lengthOfInv = -1;
+	          rProperty->lengthOfCounterExample = -1;
+		  rProperty->index = pIndex;
+	      }
+	      if(rProperty->index != pIndex) {
+		  fprintf(vis_stdout, "Error when compiling log file \n");
+	      }
+	  }
+	  else {
+	      rProperty = ALLOC(RtResultPropertys_t, 1);
+	      array_insert(RtResultPropertys_t *,cResult->resultForProperty,
+	      pIndex-1, rProperty); 
+	      rProperty->lengthOfStem = -1;
+	      rProperty->lengthOfCycle = -1;
+	      rProperty->lengthOfInv = -1;
+	      rProperty->lengthOfCounterExample = -1;
+	      rProperty->index = pIndex;
+	  }
+	  if(argv[1][0] == 'f' || argv[1][0] == 'p')
+	    rProperty->failOrPass = strdup(argv[1]);
+	  else
+	    rProperty->failOrPass = strdup(argv[2]);
+	  stemLength = 0;
+	  cycleLength = 0;
+	  Rt_FreeArgv(argc, argv);
+      }
+      continue;
+    }
+    else if(!strncasecmp(line, "# INV: Summary", 14)) {
+      if(rProperty && countLineFlag)	rProperty->lengthOfCounterExample = nLine;
+      countLineFlag = 0;
+      nLine = 0;
+      formulaSummary = 1;
+      propertyIndexSummary = 1;
+      continue;
+    }
+
+    next = strstr(line, "timeout");
+    if(next == 0) 
+        next = strstr(line, "Timeout");
+    if(next) {
+        if(!strncasecmp(next, "timeout occurred after", 22)) {
+	    cResult->bTimeOut = 1;
+	}
+	else if(!strncasecmp(next, "timeout after", 14)) {
+	    cResult->bTimeOut = 1;
+	}
+    }
+    for(i=0; i<array_n(itemArr); i++) {
+      item = array_fetch(RtCompareItems_t *, itemArr, i);
+      len = strlen(item->itemName);
+      if(!strncasecmp(item->itemName, line, len)) {
+        newItem = ALLOC(RtCompareItems_t, 1);
+	newItem->itemNickName = strdup(item->itemNickName);
+	newItem->itemName = 0;
+	newItem->value = 0;
+	Rt_SplitLine(&line[len], &argc, &argv);
+	newItem->value = strdup(argv[0]);
+	if(cResult->compareItemArr == 0)
+	  cResult->compareItemArr = array_alloc(RtCompareItems_t *, 0);
+	array_insert_last(RtCompareItems_t *, cResult->compareItemArr, newItem);
+        Rt_FreeArgv(argc, argv);
+	break;
+      }
+    }
+  }
+  if(commandBeginFlag == 1) {
+    if(cResult->resultForProperty && array_n(cResult->resultForProperty) == 0) 
+      cResult->resultForProperty = 0;
+    cResult->compareItemArr = 0;
+  }
+
+  fclose(fin1);
+  fclose(fin2);
+  return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Check whether given string is digit or not.]
+
+  Description [ ]
+
+  Comment []
+
+  SideEffects []
+
+******************************************************************************/
+static int
+Rt_IsNum(char *tmp)
+{
+  int i, len;
+
+  len = strlen(tmp);
+  for(i=0; i<len; i++) {
+    if(!isdigit((int)tmp[i]))return(0);
+  }
+  return(1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Exceute experiments based on 'ReferenceVis' and 'NewVis'. ]
+
+  Description [ ]
+
+  Comment []
+
+  SideEffects []
+
+******************************************************************************/
+static int
+Rt_ExecuteVis(RtConfigs_t *config,
+              RtDesignLists_t *designList,
+              int refAndNew, FILE *scriptOut)
+{
+  char temp[1024];
+  char dir[1024];
+  char exe[1024];
+  char name[1024];
+  char srcFile[1024];
+  char outFile[1024];
+
+
+  if(refAndNew == 1 && !config->bRefRun)return(0);
+  if(refAndNew == 2 && !config->bNewRun)return(0);
+
+  if(refAndNew == 1) {
+    sprintf(dir, "%s/%s", config->referenceOutDirectory, designList->designNickName);  
+    sprintf(exe, "%s", config->referenceVis);  
+    sprintf(name, "%s", designList->designNickName);  
+  }
+  if(refAndNew == 2) {
+    sprintf(dir, "%s/%s", config->newOutDirectory, designList->designNickName);  
+    sprintf(exe, "%s", config->newVis);  
+    sprintf(name, "%s", designList->designNickName);  
+  }
+  sprintf(srcFile, "%s/%s.src", dir, name);
+  sprintf(outFile, "%s/%s.out", dir, name);
+
+  if(scriptOut) {
+  /**
+    sprintf(temp, "%s -x -f %s/%s.src >& %s/%s.out", exe, dir, name, dir, name);
+    **/
+    sprintf(temp, "%s -x -f %s.src >& %s.out", exe, name, name);
+    fprintf(scriptOut, "echo %s begin\n", designList->designNickName);
+    fprintf(scriptOut, "cd %s\n", dir);
+    fprintf(scriptOut, "%s\n", temp);
+    fprintf(scriptOut, "cd ../../\n");
+  }
+  else {
+    sprintf(temp, "%s -x -f %s/%s.src > %s/%s.out", exe, dir, name, dir, name);
+    if (system(temp))
+      return(1);
+  }
+  /**
+    sprintf(temp, "%s -x -f %s/%s.src", exe, dir, name);
+   **/
+
+  return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Write the script file for VIS execution. ]
+
+  Description [ Wirte  the batch script for experiments.  The variables and the
+aliases are defined by examining the fields of the test case description in the
+design file.   It uses TemplateFile  to make a  script. So The  template should
+refer  to the  defined aliases  and  variables to  tailor itself  to each  test
+case. ]
+
+  Comment []
+
+  SideEffects []
+
+******************************************************************************/
+static int
+Rt_WriteBatchCommand(RtConfigs_t *config, 
+                     RtDesignLists_t *designList)
+{
+  FILE *fout1;
+  FILE *fout2;
+  char filename1[1024];
+  char filename2[1024];
+  char refDir[1024];
+  char temp[1024];
+  int i;
+  RtCommandResults_t *cTemplate;
+  array_t *cTemplateArrOld;
+  array_t *cTemplateArrNew;
+  
+  fout1 = fout2 = 0;
+  if(config->bRefRun) {
+    sprintf(temp, "\\mkdir -p %s/%s", config->referenceOutDirectory, 
+                                   designList->designNickName);
+    if (system(temp))
+      return(1);
+  }
+  if(config->bNewRun) {
+    sprintf(temp, "\\mkdir -p %s/%s", config->newOutDirectory, 
+                                   designList->designNickName);
+    if (system(temp))
+      return(1);
+  }
+
+  if(config->bRefRun) {
+    sprintf(filename1, "%s/%s/%s.src", config->referenceOutDirectory, 
+  				     designList->designNickName,
+  				     designList->designNickName);
+    if(!(fout1 = fopen(filename1, "w"))) {
+      fprintf(vis_stdout, "Error : Can't open command script file '%s'\n", filename1);
+      return(0);
+    }
+  }
+  if(config->bNewRun) {
+    sprintf(filename2, "%s/%s/%s.src", config->newOutDirectory, 
+  				     designList->designNickName,
+  				     designList->designNickName);
+    if(!(fout2 = fopen(filename2, "w"))) {
+      fprintf(vis_stdout, "Error : Can't open command script file '%s'\n", filename2);
+      fclose(fout1);
+      return(0);
+    }
+  }
+
+  cTemplateArrOld = config->refCommandTemplateArr;
+  cTemplateArrNew = config->newCommandTemplateArr;
+  sprintf(refDir, "%s/%s", config->designDirectory, designList->designDirectory);
+
+  if(config->bRefRun) {
+  /**
+    fprintf(fout1, "set vis_stdout %s/%s/%s.out\n", 
+       config->referenceOutDirectory, designList->designNickName, designList->designNickName);
+    fprintf(fout1, "set vis_stderr %s/%s/%s.out\n", 
+       config->referenceOutDirectory, designList->designNickName, designList->designNickName);
+   **/
+    fprintf(fout1, "set BaseName %s\n", designList->designNickName);
+  }
+  if(config->bNewRun) {
+  /**
+    fprintf(fout2, "set vis_stdout %s/%s/%s.out\n", 
+       config->newOutDirectory, designList->designNickName, designList->designNickName);
+    fprintf(fout2, "set vis_stderr %s/%s/%s.out\n", 
+       config->newOutDirectory, designList->designNickName, designList->designNickName);
+   **/
+    fprintf(fout2, "set BaseName %s\n", designList->designNickName);
+  }
+
+  if(designList->blifFile) {
+    if(config->bRefRun)
+    fprintf(fout1, "set BlifFile %s/%s\n", refDir, designList->blifFile);
+    if(config->bNewRun)
+    fprintf(fout2, "set BlifFile %s/%s\n", refDir, designList->blifFile);
+  }
+  if(designList->ordFile) {
+    if(config->bRefRun)
+    fprintf(fout1, "set OrdFile %s/%s\n", refDir, designList->ordFile);
+    if(config->bNewRun)
+    fprintf(fout2, "set OrdFile %s/%s\n", refDir, designList->ordFile);
+  }
+  if(designList->ctlFile) {
+    if(config->bRefRun)
+    fprintf(fout1, "set CtlFile %s/%s\n", refDir, designList->ctlFile);
+    if(config->bNewRun)
+    fprintf(fout2, "set CtlFile %s/%s\n", refDir, designList->ctlFile);
+  }
+  if(designList->invFile) {
+    if(config->bRefRun)
+    fprintf(fout1, "set InvFile %s/%s\n", refDir, designList->invFile);
+    if(config->bNewRun)
+    fprintf(fout2, "set InvFile %s/%s\n", refDir, designList->invFile);
+  }
+  if(designList->leFile) {
+    if(config->bRefRun)
+    fprintf(fout1, "set LeFile %s/%s\n", refDir, designList->leFile);
+    if(config->bNewRun)
+    fprintf(fout2, "set LeFile %s/%s\n", refDir, designList->leFile);
+  }
+  if(designList->ltlFile) {
+    if(config->bRefRun)
+    fprintf(fout1, "set LtlFile %s/%s\n", refDir, designList->ltlFile);
+    if(config->bNewRun)
+    fprintf(fout2, "set LtlFile %s/%s\n", refDir, designList->ltlFile);
+  }
+  if(designList->fairFile) {
+    if(config->bRefRun)
+    fprintf(fout1, "set FairFile %s/%s\n", refDir, designList->fairFile);
+    if(config->bNewRun)
+    fprintf(fout2, "set FairFile %s/%s\n", refDir, designList->fairFile);
+  }
+  if(designList->hintFile) {
+    if(config->bRefRun)
+    fprintf(fout1, "set HintFile %s/%s\n", refDir, designList->hintFile);
+    if(config->bNewRun)
+    fprintf(fout2, "set HintFile %s/%s\n", refDir, designList->hintFile);
+  }
+
+  if(config->bRefRun) {
+    if(designList->fairFile)
+      fprintf(fout1, "set fairOption \"-F%s/%s\"\n", refDir, designList->fairFile);
+    else
+      fprintf(fout1, "set fairOption \" \"\n");
+  }
+  if(config->bNewRun) {
+    if(designList->fairFile)
+      fprintf(fout2, "set fairOption \"-F%s/%s\"\n", refDir, designList->fairFile);
+    else
+      fprintf(fout2, "set fairOption \" \"\n");
+  }
+
+
+  if(config->bDefaultInitCommand) {
+    if(config->bRefRun) {
+      fprintf(fout1, "echo CommandBegin init\n");
+      if(designList->ordFile) {
+        if(designList->bIsMv)
+           fprintf(fout1, "rlmv $BlifFile\n");
+        else
+	   fprintf(fout1, "read_blif $BlifFile\n");
+        fprintf(fout1, "flatten_hierarchy\n");
+        fprintf(fout1, "static_order -s partial $OrdFile\n");
+        fprintf(fout1, "build_partition_mdds\n");
+        if(designList->fairFile)
+          fprintf(fout1, "rf $FairFile\n");
+      }
+      else {
+        if(designList->bIsMv)
+           fprintf(fout1, "rlmv $BlifFile\n");
+        else
+	   fprintf(fout1, "read_blif $BlifFile\n");
+        fprintf(fout1, "echo init\n");
+        fprintf(fout1, "init\n");
+        if(designList->fairFile)
+          fprintf(fout1, "rf $FairFile\n");
+      }
+      fprintf(fout1, "time\n");
+      fprintf(fout1, "print_bdd_stats\n");
+      fprintf(fout1, "echo CommandEnd init\n");
+    }
+    if(config->bNewRun) {
+      fprintf(fout2, "echo CommandBegin init\n");
+      if(designList->ordFile) {
+        if(designList->bIsMv)
+           fprintf(fout2, "rlmv $BlifFile\n");
+        else
+	   fprintf(fout2, "read_blif $BlifFile\n");
+        fprintf(fout2, "flatten_hierarchy\n");
+        fprintf(fout2, "static_order -s partial $OrdFile\n");
+        fprintf(fout2, "build_partition_mdds\n");
+        if(designList->fairFile)
+          fprintf(fout2, "rf $FairFile\n");
+      }
+      else {
+        if(designList->bIsMv)
+           fprintf(fout2, "rlmv $BlifFile\n");
+        else
+	   fprintf(fout2, "read_blif $BlifFile\n");
+        fprintf(fout2, "echo init\n");
+        fprintf(fout2, "init\n");
+        if(designList->fairFile)
+          fprintf(fout2, "rf $FairFile\n");
+      }
+      fprintf(fout2, "time\n");
+      fprintf(fout2, "print_bdd_stats\n");
+      fprintf(fout2, "echo CommandEnd init\n");
+    } 
+  }
+  else {
+    /** 
+     * Alias read_model, set_fairness and order_vars  based on 
+     * whether the design list specifies a .mv file or a .blif file 
+     * as model file.
+     **/
+    if(config->bRefRun) {
+      if(designList->bIsMv)
+        fprintf(fout1, "alias read_model \"rlmv $BlifFile\"\n");
+      else
+	fprintf(fout1, "alias read_model \"read_blif $BlifFile\"\n");
+      if(designList->fairFile)	
+        fprintf(fout1, "alias set_fairness \"read_fairness $FairFile\"\n");
+      else
+        fprintf(fout1, "alias set_fairness \" \"\n");
+      if(designList->ordFile)	
+        fprintf(fout1, "alias order_vars \"so -s input_and_latch $OrdFile\"\n");
+      else
+        fprintf(fout1, "alias order_vars \"so\"\n");
+    }
+    if(config->bNewRun) {
+      if(designList->bIsMv)
+        fprintf(fout2, "alias read_model \"rlmv $BlifFile\"\n");
+      else
+	fprintf(fout2, "alias read_model \"read_blif $BlifFile\"\n");
+      if(designList->fairFile)	
+        fprintf(fout2, "alias set_fairness \"read_fairness $FairFile\"\n");
+      else
+        fprintf(fout2, "alias set_fairness \" \"\n");
+      if(designList->ordFile)	
+        fprintf(fout2, "alias order_vars \"so -s input_and_latch $OrdFile\"\n");
+      else
+        fprintf(fout2, "alias order_vars \"so\"\n");
+    } 
+  }
+
+  if(config->bRefRun) {
+    for(i=0; i<array_n(cTemplateArrOld); i++) {
+      cTemplate = array_fetch(RtCommandResults_t *, cTemplateArrOld, i);
+      fprintf(fout1, "%s\n", cTemplate->command);
+    }
+    fprintf(fout1, "quit\n");
+    fclose(fout1);
+  }
+  if(config->bNewRun) {
+    for(i=0; i<array_n(cTemplateArrNew); i++) {
+      cTemplate = array_fetch(RtCommandResults_t *, cTemplateArrNew, i);
+      fprintf(fout2, "%s\n", cTemplate->command);
+    }
+    fprintf(fout2, "quit\n");
+    fclose(fout2);
+  }
+
+  return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Read command template and check whether it contains illegal command and alias. ]
+
+  Description [ When read the template,  if we meet the string followed by '$',
+then check whether  that string is reserved  word or not. If the  string is not
+reserved work then we consider that as a variable.]
+
+  Comment []
+
+  SideEffects []
+
+******************************************************************************/
+
+static int
+Rt_ReadCommandTemplate(RtConfigs_t * config)
+{
+  FILE	*fin;
+  char line[1024];
+  char *filename;
+  char temp[1024];
+  int i;
+  RtCommandResults_t *cResult;
+  int argc;
+  char **argv;
+  char *next, *tmp;
+
+  if(config->bRefRun) {
+  filename = config->refCommandTemplate;
+  if(!(fin = fopen(filename, "r"))) {
+    fprintf(vis_stdout, "Error : Can't open command template file '%s' for reference\n", filename);
+    return(1);
+  }
+
+  if(config->keyWordTable == 0)
+    config->keyWordTable = st_init_table(strcmp, st_strhash);
+  config->refCommandTemplateArr = array_alloc(RtCommandResults_t *, 0);
+  while(fgets(line, 1024, fin)) {
+    if(line[0] == '#')	continue;
+    cResult = ALLOC(RtCommandResults_t, 1);
+    cResult->resultForProperty = 0;
+    cResult->compareItemArr = 0;
+    cResult->command = 0;
+    Rt_SplitLine(line, &argc, &argv);
+    temp[0] = '\0';
+    for(i=0; i<argc; i++) {
+      strcat(temp, argv[i]); 
+      if(i+1 != argc) strcat(temp, " ");
+      if(argv[i][0] == '$') {
+	 if(!st_lookup(config->keyWordTable, argv[i], &tmp)) {
+	    next = strdup(argv[i]);
+            st_insert(config->keyWordTable, next, next);
+	 }
+      }
+    }
+    Rt_FreeArgv(argc, argv);
+    cResult->command = strdup(temp);
+    array_insert_last(RtCommandResults_t *, config->refCommandTemplateArr, cResult);
+
+  }
+  fclose(fin);
+  }
+
+  if(config->bNewRun) {
+  filename = config->newCommandTemplate;
+  if(!(fin = fopen(filename, "r"))) {
+    fprintf(vis_stdout, "Error : Can't open command template file '%s' for new\n", filename);
+    return(1);
+  }
+  if(config->keyWordTable == 0)
+    config->keyWordTable = st_init_table(strcmp, st_strhash);
+  config->newCommandTemplateArr = array_alloc(RtCommandResults_t *, 0);
+  while(fgets(line, 1024, fin)) {
+    if(line[0] == '#')	continue;
+    cResult = ALLOC(RtCommandResults_t, 1);
+    cResult->resultForProperty = 0;
+    cResult->compareItemArr = 0;
+    cResult->command = 0;
+    Rt_SplitLine(line, &argc, &argv);
+    temp[0] = '\0';
+    for(i=0; i<argc; i++) {
+      strcat(temp, argv[i]); 
+      if(i+1 != argc) strcat(temp, " ");
+      if(argv[i][0] == '$') {
+	 if(!st_lookup(config->keyWordTable, argv[i], &tmp)) {
+	    next = strdup(argv[i]);
+            st_insert(config->keyWordTable, next, next);
+	 }
+      }
+    }
+    Rt_FreeArgv(argc, argv);
+    cResult->command = strdup(temp);
+    array_insert_last(RtCommandResults_t *, config->newCommandTemplateArr, cResult);
+  }
+  fclose(fin);
+  }
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Read the design list. ]
+
+  Description [  To specify the  type of file,  we use extension of  file name,
+such  as .mv,  .blif,  .ord, .inv,  .ctl,  .fair, .ltl  and  .hint.  Each  line
+consists  of white  space-separated fields.   The first  is a  (relative) path,
+while the second is the  collection name.  The smallest collection will specify
+one .mv  or one .blif file with  path and collection name.  Lines starting with
+'#' are interpreted as comments and are skipped, as in all files read]
+
+  Comment []
+
+  SideEffects []
+
+******************************************************************************/
+static int
+Rt_ReadDesignListFile(RtConfigs_t * config)
+{
+  FILE	*fin;
+  char line[1024];
+  char *filename, *str;
+  char suffix[1024];
+  int i, j, index, bDot, strLen;
+  RtDesignLists_t *designList;
+  int argc;
+  char **argv;
+
+  filename = config->designList;
+
+  if(!(fin = fopen(filename, "r"))) {
+    fprintf(vis_stdout, "Error : Can't open design list file '%s'\n", filename);
+    return(1);
+  }
+
+  config->designListArr = array_alloc(RtDesignLists_t *, 0);
+  while(fgets(line, 1024, fin)) {
+    if(line[0] == '#')	continue;
+    if(line[0] == '\n')	continue;
+    Rt_SplitLine(line, &argc, &argv);
+    designList = ALLOC(RtDesignLists_t, 1);
+    designList->designDirectory = strdup(argv[0]);
+    designList->designNickName = strdup(argv[1]);
+    designList->blifFile = strdup(argv[2]);
+    designList->leFile = 0;
+    designList->ltlFile = 0;
+    designList->ordFile = 0;
+    designList->hintFile = 0;
+    designList->ctlFile = 0;
+    designList->invFile = 0;
+    designList->fairFile = 0;
+    designList->resultForCommandArr1 = 0;
+    designList->resultForCommandArr2 = 0;
+
+    str = argv[2];
+    index = bDot = 0;
+    strLen = strlen(str);
+    for(j=strLen; j>=0; j--) {
+      if(str[j] == '.') {	
+        bDot = 1; 
+        break;
+      }
+    }
+    if(bDot==0) {
+      fprintf(vis_stdout, "Error : Missing blif or mv file in design list '%s'\n",
+      designList->designNickName);
+      Rt_FreeArgv(argc, argv);
+      free(designList);
+      continue;
+    }
+    else {
+      j++;
+      for(;str[j] != '\0'; j++) {
+	suffix[index++] = str[j];
+      }
+    }
+    suffix[index] = '\0';
+
+    if(!strcasecmp(suffix, "blif")) 
+      designList->bIsMv = 0;
+    else if(!strcasecmp(suffix, "mv")) 
+      designList->bIsMv = 1;
+    else {
+      fprintf(vis_stdout, "Error : Missing blif or mv file in design list '%s'\n",
+      designList->designNickName);
+      Rt_FreeArgv(argc, argv);
+      free(designList);
+      continue;
+    }
+
+    for(i=3; i<argc; i++) {
+      str = argv[i];
+      index = bDot = 0;
+      strLen = strlen(str);
+      for(j=strLen; j>=0; j--) {
+        if(str[j] == '.') {	
+          bDot = 1; 
+          break;
+        }
+      }
+      if(bDot==0) {
+        fprintf(vis_stdout, "Error : Illegal suffix of file '%s' in design list '%s'\n", 
+	  argv[i], designList->designNickName);
+        Rt_FreeArgv(argc, argv);
+        free(designList);
+        continue;
+      }
+      else {
+        j++;
+        for(;str[j] != '\0'; j++) {
+	  suffix[index++] = str[j];
+        }
+      }
+      suffix[index] = '\0';
+      if(!strcasecmp(suffix, "ctl")) 
+        designList->ctlFile = strdup(argv[i]);
+      else if(!strcasecmp(suffix, "fair")) 
+        designList->fairFile = strdup(argv[i]);
+      else if(!strcasecmp(suffix, "inv")) 
+        designList->invFile = strdup(argv[i]);
+      else if(!strcasecmp(suffix, "le")) 
+        designList->leFile = strdup(argv[i]);
+      else if(!strcasecmp(suffix, "ltl")) 
+        designList->ltlFile = strdup(argv[i]);
+      else if(!strcasecmp(suffix, "ord")) 
+        designList->ordFile = strdup(argv[i]);
+      else if(!strcasecmp(suffix, "hint")) 
+        designList->hintFile = strdup(argv[i]);
+      else {
+        fprintf(vis_stdout, "Illegal suffix of file '%s'\n", argv[i]);
+        Rt_FreeArgv(argc, argv);
+	fclose(fin);
+	return(1);
+      }
+    }
+    array_insert_last(RtDesignLists_t *, config->designListArr, designList);
+    Rt_FreeArgv(argc, argv);
+  }
+
+  fclose(fin);
+  return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Read Configuration file ]
+
+  Description [Read each line of Configuration file and fill the data
+  structure.  A line beginning with '#' is a comment. ]
+
+  Comment []
+
+  SideEffects []
+
+******************************************************************************/
+static RtConfigs_t *
+Rt_ReadConfigFile(char *filename)
+{
+  FILE	*fin;
+  char line[1024];
+  char temp[1024];
+  RtConfigs_t *config;
+  int i, argc;
+  int errorFlag;
+  char **argv;
+  RtCompareItems_t *cItem;
+
+  if(!(fin = fopen(filename, "r"))) {
+    fprintf(vis_stdout, "Error : Can't open configuration file '%s'\n", filename);
+    return(0);
+  }
+
+  config = ALLOC(RtConfigs_t, 1);
+  memset(config, 0, sizeof(RtConfigs_t));
+  config->configurationFile = strdup(filename);
+  config->compareItemArr = 0;
+  config->bRefOnly = 0;
+  config->keyWordTable = 0;
+  config->bRefRun = -1;
+  config->bNewRun = -1;
+  while(fgets(line, 1024, fin)) {
+    if(line[0] == '#')	continue;
+    if(line[0] == '\n')	continue;
+    Rt_SplitLine(line, &argc, &argv);
+    if(argv[0][0] == '\n')	continue;
+    if(argc < 3)	continue;
+    if(argv[2] == 0)	continue;
+    if(!strcasecmp("DesignDirectory", argv[0])) {
+      config->designDirectory = strdup(argv[2]);
+    }
+    else if(!strcasecmp("ReferenceVis", argv[0])) {
+      config->referenceVis = strdup(argv[2]);
+    }
+    else if(!strcasecmp("ReferenceVisNickName", argv[0])) {
+      config->referenceVisNickName = strdup(argv[2]);
+    }
+    else if(!strcasecmp("ReferenceVisOptionFile", argv[0])) {
+      config->referenceVisOptionFile = strdup(argv[2]);
+    }
+    else if(!strcasecmp("ReferenceOutputDir", argv[0])) {
+      config->referenceOutDirectory = strdup(argv[2]);
+    }
+    else if(!strcasecmp("bRefRun", argv[0])) {
+      config->bRefRun = Rt_SetBooleanValue(argv[2], argv[0]);
+    }
+    else if(!strcasecmp("NewVis", argv[0])) {
+      config->newVis = strdup(argv[2]);
+    }
+    else if(!strcasecmp("NewVisNickName", argv[0])) {
+      config->newVisNickName = strdup(argv[2]);
+    }
+    else if(!strcasecmp("NewVisOptionFile", argv[0])) {
+      config->newVisOptionFile = strdup(argv[2]);
+    }
+    else if(!strcasecmp("NewOutputDir", argv[0])) {
+      config->newOutDirectory = strdup(argv[2]);
+    }
+    else if(!strcasecmp("bNewRun", argv[0])) {
+      config->bNewRun = Rt_SetBooleanValue(argv[2], argv[0]);
+    }
+    else if(!strcasecmp("NewCommandTemplate", argv[0])) {
+      config->newCommandTemplate = strdup(argv[2]);
+    }
+    else if(!strcasecmp("RefCommandTemplate", argv[0])) {
+      config->refCommandTemplate = strdup(argv[2]);
+    }
+    else if(!strcasecmp("DesignList", argv[0])) {
+      config->designList = strdup(argv[2]);
+    }
+    else if(!strcasecmp("bCompareCounterExample", argv[0])) {
+      config->bCompareCounterExample = Rt_SetBooleanValue(argv[2], argv[0]);
+    }
+    else if(!strcasecmp("bFinalResultOnly", argv[0])) {
+      config->bFinalResultOnly = Rt_SetBooleanValue(argv[2], argv[0]);
+    }
+    else if(!strcasecmp("bDontRemoveTempFile", argv[0])) {
+      config->bDontRemoveTempFile = Rt_SetBooleanValue(argv[2], argv[0]);
+    }
+    else if(!strcasecmp("bDefaultInitCommand", argv[0])) {
+      config->bDefaultInitCommand = Rt_SetBooleanValue(argv[2], argv[0]);
+    }
+    else if(!strcasecmp("ResultForPerformance", argv[0])) {
+      config->resultForPerformance = strdup(argv[2]);
+    }
+    else if(!strcasecmp("ResultForCounterExample", argv[0])) {
+      config->resultForCounterExample = strdup(argv[2]);
+    }
+    else if(!strcasecmp("CompareItem", argv[0])) {
+      cItem = ALLOC(RtCompareItems_t, 1);
+      cItem->itemNickName = strdup(argv[2]);
+      temp[0] = '\0';
+      for(i=4; i<argc; i++) {
+        strcat(temp, argv[i]);
+        if(i+1 != argc) strcat(temp, " ");
+      }
+      cItem->itemName = strdup(temp);
+      cItem->value = 0;
+      if(!config->compareItemArr)
+        config->compareItemArr = array_alloc(RtCompareItems_t *, 0);
+      array_insert_last(RtCompareItems_t *, config->compareItemArr, cItem);
+    }
+    else {
+      fprintf(vis_stdout, "Unknown option '%s' in configuration file\n", argv[0]);
+      free(config);
+      Rt_FreeArgv(argc, argv);
+      fclose(fin);
+      return(0);
+    }
+    Rt_FreeArgv(argc, argv);
+  }
+  fclose(fin);
+
+  errorFlag = 0;
+  if(config->designDirectory == 0) {
+    fprintf(stdout, "DesignDirectory is not specified in configuration file '%s'\n",
+		filename);
+    errorFlag = 1;
+  }
+  if(config->referenceVis == 0) {
+    fprintf(stdout, "ReferenceVis is not specified in configuration file '%s'\n",
+		filename);
+    errorFlag = 1;
+  }
+  if(config->referenceVisNickName == 0) {
+    fprintf(stdout, "ReferenceVisNickName is not specified in configuration file '%s'\n",
+		filename);
+    errorFlag = 1;
+  }
+  if(config->referenceOutDirectory == 0) {
+    fprintf(stdout, "ReferenceOutDirectory is not specified in configuration file '%s'\n",
+		filename);
+    errorFlag = 1;
+  }
+  if(config->newVis == 0) {
+    fprintf(stdout, "NewVis is not specified in configuration file '%s'\n",
+		filename);
+    errorFlag = 1;
+  }
+  if(config->newVisNickName == 0) {
+    fprintf(stdout, "NewVisNickName is not specified in configuration file '%s'\n",
+		filename);
+    errorFlag = 1;
+  }
+  if(config->newOutDirectory == 0) {
+    fprintf(stdout, "NewOutDirectory is not specified in configuration file '%s'\n",
+		filename);
+    errorFlag = 1;
+  }
+  if(config->bRefRun == -1) {
+    fprintf(stdout, "bRefRun is not specified in configuration file '%s'\n",
+		filename);
+    errorFlag = 1;
+  }
+  if(config->bNewRun == -1) {
+    fprintf(stdout, "bNewRun is not specified in configuration file '%s'\n",
+		filename);
+    errorFlag = 1;
+  }
+  if(config->designList == 0) {
+    fprintf(stdout, "DesignList is not specified in configuration file '%s'\n",
+		filename);
+    errorFlag = 1;
+  }
+  if(config->newCommandTemplate == 0) {
+    fprintf(stdout, "NewCommandTemplate is not specified in configuration file '%s'\n",
+		filename);
+    errorFlag = 1;
+  }
+  if(config->refCommandTemplate == 0) {
+    fprintf(stdout, "RefCommandTemplate is not specified in configuration file '%s'\n",
+		filename);
+    errorFlag = 1;
+  }
+
+  if(config->compareItemArr == 0 || array_n(config->compareItemArr) == 0) {
+    fprintf(stdout, "CompareItem is not specified in configuration file '%s'\n",
+		filename);
+    errorFlag = 1;
+  }
+
+  if(errorFlag) {
+    free(config);
+    return(0);
+  }
+  
+  return(config);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return 1 if the string contains 'TURE', otherwise return 0. ]
+
+  Description [ ]
+
+  Comment []
+
+  SideEffects []
+
+******************************************************************************/
+static int
+Rt_SetBooleanValue(char *str, char *option)
+{
+
+  if(!strcmp("TRUE", str) || !strcmp("1", str))
+    return(1);
+  else if(!strcmp("FALSE", str) || !strcmp("0", str))
+    return(0);
+  else {
+    fprintf(vis_stdout, "Warning : Illegal argement for '%s'\n", option);
+    fprintf(vis_stdout, "          Set with default '%s : TURE'\n", option);
+    return(1);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Split line with respect to whitespace, '#' and ';', and save
+  individual strings in array named 'argv'. ]
+
+  Description [ ]
+
+  Comment []
+
+  SideEffects []
+
+******************************************************************************/
+static char *
+Rt_SplitLine(
+  char * command,
+  int * argc,
+  char *** argv)
+{
+  register char *p, *start, c;
+  register int i, j;
+  register char *new_arg;
+  array_t *argv_array;
+  int single_quote, double_quote;
+
+  argv_array = array_alloc(char *, 5);
+
+  p = command;
+  for(;;) {
+    /* skip leading white space */
+    while (isspace((int)(*p))) {
+      p++;
+    }
+
+    /* skip until end of this token */
+    single_quote = double_quote = 0;
+    for(start = p; (c = *p) != '\0'; p++) {
+      if (c == ';' || c == '#' || isspace((int)c)) {
+        if (! single_quote && ! double_quote) {
+          break;
+        }
+      }
+      if (c == '\'') {
+        single_quote = ! single_quote;
+      }
+      if (c == '"') {
+        double_quote = ! double_quote;
+      }
+    }
+    if (single_quote || double_quote) {
+      (void) fprintf(vis_stderr, "** cmd warning: ignoring unbalanced quote ...\n");
+    }
+    if (start == p) break;
+
+    new_arg = ALLOC(char, p - start + 1);
+    j = 0;
+    for(i = 0; i < p - start; i++) {
+      c = start[i];
+      if ((c != '\'') && (c != '\"')) {
+        new_arg[j++] = isspace((int)c) ? ' ' : start[i];
+      }
+    }
+    new_arg[j] = '\0';
+    array_insert_last(char *, argv_array, new_arg);
+  }
+
+  *argc = array_n(argv_array);
+  *argv = array_data(char *, argv_array);
+  array_free(argv_array);
+  if (*p == ';') {
+    p++;
+  }
+  else if (*p == '#') {
+    for(; *p != 0; p++) ;		/* skip to end of line */
+  }
+  return p;
+}    
+
+
+static void
+Rt_FreeRtConfig(RtConfigs_t * config)
+{
+  int i;
+  RtDesignLists_t *list;
+  array_t *itemArr, *designArr, *resultArr;
+  st_table *table;
+  RtCompareItems_t *item;
+  RtCommandResults_t *result;
+  st_generator *gen;
+  char *keyWord;
+
+
+  if(config == 0)	return;
+  
+  if(config->designDirectory)		free(config->designDirectory);
+  if(config->designList)		free(config->designList);
+  if(config->scriptFile)		free(config->scriptFile);
+  if(config->resultForCounterExample)	free(config->resultForCounterExample);
+  if(config->resultForPerformance)	free(config->resultForPerformance);
+
+  if(config->referenceVis)		free(config->referenceVis);
+  if(config->referenceVisNickName)	free(config->referenceVisNickName);
+  if(config->referenceVisOptionFile)	free(config->referenceVisOptionFile);
+  if(config->referenceOutDirectory)	free(config->referenceOutDirectory);
+  if(config->refCommandTemplate)	free(config->refCommandTemplate);
+
+  if(config->newVis)			free(config->newVis);
+  if(config->newVisNickName)		free(config->newVisNickName);
+  if(config->newVisOptionFile)		free(config->newVisOptionFile);
+  if(config->newOutDirectory)		free(config->newOutDirectory);
+  if(config->newCommandTemplate)	free(config->newCommandTemplate);
+
+  itemArr = config->compareItemArr;
+  if(itemArr) {
+    for(i=0; i<array_n(itemArr); i++) {
+      item = array_fetch(RtCompareItems_t *, itemArr, i);
+      Rt_FreeCompareItem(item);
+    }
+    array_free(itemArr);
+  }
+
+  designArr = config->designListArr;
+  if(designArr) {
+    for(i=0; i<array_n(designArr); i++) {
+      list = array_fetch(RtDesignLists_t *, designArr, i);
+      Rt_FreeDesignList(list);
+    }
+    array_free(designArr);
+  }
+
+  resultArr = config->refCommandTemplateArr;
+  if(resultArr) {
+    for(i=0; i<array_n(resultArr); i++) {
+      result = array_fetch(RtCommandResults_t *, resultArr, i);
+      Rt_FreeCommandResult(result);
+    }
+    array_free(resultArr);
+  }
+
+  resultArr = config->newCommandTemplateArr;
+  if(resultArr) {
+    for(i=0; i<array_n(resultArr); i++) {
+      result = array_fetch(RtCommandResults_t *, resultArr, i);
+      Rt_FreeCommandResult(result);
+    }
+    array_free(resultArr);
+  }
+
+  if(config->keyWordTable) {
+    table = config->keyWordTable;
+    st_foreach_item(table, gen, &keyWord, NIL(char *)) {
+      free(keyWord);
+    }
+    st_free_table(table);
+  }
+
+}
+
+static void
+Rt_FreeDesignList(RtDesignLists_t *list)
+{
+  array_t *resultArr;
+  RtCommandResults_t *result;
+  int i;
+
+  if(list == 0)	return;
+
+  if(list->designDirectory)	free(list->designDirectory);
+  if(list->designNickName)	free(list->designNickName);
+  if(list->blifFile)	free(list->blifFile);
+  if(list->ctlFile)	free(list->ctlFile);
+  if(list->invFile)	free(list->invFile);
+  if(list->leFile)	free(list->leFile);
+  if(list->fairFile)	free(list->fairFile);
+  if(list->hintFile)	free(list->hintFile);
+  if(list->ordFile)	free(list->ordFile);
+  if(list->ltlFile)	free(list->ltlFile);
+
+  resultArr = list->resultForCommandArr1;
+  if(resultArr) {
+    for(i=0; i<array_n(resultArr); i++) {
+      result = array_fetch(RtCommandResults_t *, resultArr, i);
+      Rt_FreeCommandResult(result);
+    }
+    array_free(resultArr);
+  }
+  resultArr = list->resultForCommandArr2;
+  if(resultArr) {
+    for(i=0; i<array_n(resultArr); i++) {
+      result = array_fetch(RtCommandResults_t *, resultArr, i);
+      Rt_FreeCommandResult(result);
+    }
+    array_free(resultArr);
+  }
+
+  free(list);
+}
+
+static void
+Rt_FreeCommandResult(RtCommandResults_t *result)
+{
+  array_t *itemArr;
+  array_t *propArr;
+  RtCompareItems_t *item;
+  RtResultPropertys_t *prop;
+  int i;
+
+  if(result == 0)	return;
+  
+  if(result->command)	free(result->command);
+
+  itemArr = result->compareItemArr;
+  if(itemArr) {
+    for(i=0; i<array_n(itemArr); i++) {
+      item = array_fetch(RtCompareItems_t *, itemArr, i);
+      Rt_FreeCompareItem(item);
+    }
+    array_free(itemArr);
+  }
+			  
+  propArr = result->resultForProperty;
+  if(propArr) {
+    for(i=0; i<array_n(propArr); i++) {
+      prop = array_fetch(RtResultPropertys_t *, propArr, i);
+      Rt_FreeResultProperty(prop);
+    }
+    array_free(propArr);
+  }
+}
+
+static void
+Rt_FreeCompareItem(RtCompareItems_t *item)
+{
+  if(item == 0)	return;
+
+  if(item->itemName)	free(item->itemName);
+  if(item->itemNickName)free(item->itemNickName);
+  if(item->value)	free(item->value);
+  free(item);
+}
+
+static void
+Rt_FreeResultProperty(RtResultPropertys_t *prop)
+{
+
+  if(prop == 0)	return;
+
+  if(prop->failOrPass)	free(prop->failOrPass);
+  free(prop);
+}
+
+static void
+Rt_FreeArgv(int  argc,  char ** argv)
+{
+  int i;
+
+  for(i = 0; i < argc; i++) {
+    FREE(argv[i]);
+  }
+  FREE(argv);
+}
Index: vis_dev/vis-2.3/src/sat/sat.h
===================================================================
--- vis_dev/vis-2.3/src/sat/sat.h	(revision 14)
+++ vis_dev/vis-2.3/src/sat/sat.h	(revision 14)
@@ -0,0 +1,1052 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [sat.h]
+
+  PackageName [sat]
+
+  Synopsis    []
+
+  Description [Internal data structures of the sat package.]
+
+  SeeAlso     []
+
+  Author      [HoonSang Jin ]
+
+  Copyright [ This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+  Revision    [$Id: sat.h,v 1.30 2009/04/12 00:14:11 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _SAT
+#define _SAT
+
+#include "util.h"
+#include "array.h"
+#include "st.h"
+#include "heap.h"
+#include "cudd.h"
+#include "stdio.h"
+/*Bing*/
+#include "puresat.h"
+//#include "satInt.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define  bbAigValue     0   /* Index of value. */  
+#define  bbAigFlags     1   /* Index of flag for this node.*/
+#define  bbAigLeft      2   /* Index of the left child */ 
+#define  bbAigRight     3   /* Index of the right child */ 
+#define  bbAigNFanout   4   /* Index of number of fanout.*/
+#define  bbAigFanout    5   /* Index of fanout pointer for this node.*/
+#define  bbAigCanonical 6   /* Index of canonical node for this node.*/
+#define  bbAigNext      7   /* Index of dummy for this node.*/
+/*Bing:*/
+#define  bAigClass     8
+
+
+/**
+ * Mask bit for each flags
+ **/
+/**
+ *                      1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
+ *  |_| | | | | | | | | | | | | | | | | | | | | |
+ *   |  | | | | | | | | | | | | | | | | | | | | |
+ *   |  | | | | | | | | | | | | | | | | | | | | InCoreMask
+ *   |  | | | | | | | | | | | | | | | | | | | IsFrontierClause
+ *   |  | | | | | | | | | | | | | | | | | | IsBlockingClause
+ *   |  | | | | | | | | | | | | | | | | | Visited2
+ *   |  | | | | | | | | | | | | | | | | CanonicalBit
+ *   |  | | | | | | | | | | | | | | | IsSystem
+ *   |  | | | | | | | | | | | | | | IsConflict
+ *   |  | | | | | | | | | | | | | InUse
+ *   |  | | | | | | | | | | | | InQueue
+ *   |  | | | | | | | | | | | LeafNode
+ *   |  | | | | | | | | | | BDDSatisfied 
+ *   |  | | | | | | | | | StaticLearn
+ *   |  | | | | | | | | NonObj 
+ *   |  | | | | | | | Obj
+ *   |  | | | | | | New
+ *   |  | | | | | Visited
+ *   |  | | | | Coi
+ *   |  | | | IsCone
+ *   |  | | StateBit
+ *   |  | IsBDD    
+ *   |  IsCNF      
+ *   HValue
+ **/
+
+/*#define PreserveMask           0x0032681e*/
+/*Bing*/
+#define PreserveMask           0xff3a681e
+
+#define HValueMask             0x00000003
+#define ResetHValueMask        0xfffffffc
+
+/**
+ * If this mask bit is marked then the node is CNF node.
+ **/
+#define IsCNFMask              0x00000004
+#define ResetIsCNFMask         0xfffffffb
+
+/**
+ * If this mask bit is marked then the node is BDD node.
+ **/
+#define IsBDDMask              0x00000008
+#define ResetIsBDDMask         0xfffffff7
+
+
+/**
+ * If this mask bit is marked then the node is state variable.
+ **/
+#define StateBitMask           0x00000010
+#define ResetStateBitMask      0xffffffef
+
+/**
+ * If this mask bit is marked then the node is transitive fanin of
+ * certain variable.
+ **/
+#define IsConeMask             0x00000020
+#define ResetIsConeMask        0xffffffdf
+
+/**
+ * If this mask bit is marked then the node is under cone of influence of root
+ * node. To be implied by BCP this flag bit has to be set.
+ **/
+#define CoiMask                0x00000040
+#define ResetCoiMask           0xffffffbf
+
+/**
+ * If this mask bit is marked then the node is visited.
+ **/
+#define VisitedMask            0x00000080
+#define ResetVisitedMask       0xffffff7f
+
+/**
+ * If this mask bit is marked then the node is visited.
+ * It can be used like a VisitedMask.
+ **/
+#define NewMask                0x00000100
+#define ResetNewMask           0xfffffeff
+
+/**
+ * If this mask bit is marked then the node is object dependent.
+ * It is used to identify object dependent conflict clause while
+ * applying incremental SAT.
+ **/
+#define ObjMask                0x00000200
+#define ResetObjMask           0xfffffdff
+
+/**
+ * If this mask bit is marked then the node is object independent.
+ * It is used to identify object independent conflict clause while
+ * applying incremental SAT.
+ **/
+#define NonobjMask             0x00000400
+#define ResetNonobjMask        0xfffffbff
+
+
+/**
+ * If this mask bit is marked then the value of node is fixed by static 
+ * learning.
+ **/
+#define StaticLearnMask        0x00000400
+#define ResetStaticLearnMask   0xfffffbff
+
+/**
+ * If this mask bit is marked then the BDD node is satisfied by partial
+ * or full assignment on support variables. 
+ * This flag bit is used for BDD node only, which means that IsBDDMask
+ * has to be set.
+ **/
+#define BDDSatisfiedMask       0x00000800
+#define ResetBDDSatisfiedMask  0xfffff7ff
+
+/**
+ * If this mask bit is marked then the node is support variable of 
+ * BDD node.
+ **/
+#define LeafNodeMask           0x00001000
+#define ResetLeafNodeMask      0xffffefff
+
+/**
+ * If this mask bit is marked then the node is in implication queue. 
+ * To avoid to put same node multiple times, it is set when the node is
+ * in the queue.
+ **/
+#define InQueueMask            0x00002000
+#define ResetInQueueMask       0xffffdfff
+
+/**
+ * If this mask bit is marked then the clause is in use.
+ * This flag bit can be set for CNF node only.
+ **/
+#define InUseMask              0x00004000
+#define ResetInUseMask         0xffffbfff
+
+/**
+ * If this mask bit is marked then the clause is conflict clause.
+ * This flag bit can be set for CNF node only.
+ **/
+#define IsConflictMask         0x00008000
+#define ResetIsConflictMask    0xffff7fff
+
+/**
+ * If this mask bit is marked then the node is part of original model.
+ * For example, BMC instance can be classified into system part and
+ * property part.
+ **/
+#define IsSystemMask           0x00010000
+#define ResetIsSystemMask      0xfffeffff
+
+/**
+ * If AIG nodes are identified as equivalent node, then they are merged
+ * into one of them. This mask bit is used identified the representative
+ * of those equivalent nodes.
+ **/
+#define CanonicalBitMask       0x00020000
+/**
+#define ResetCanonicalBitMask  0xfffdffff
+**/
+#define ResetCanonicalBitMask  ~0x00020000L
+
+/**
+ * If this mask bit is marked then the node is visited.
+ * It can be used like a VisitedMask.
+ **/
+#define Visited2Mask           0x00040000
+#define ResetVisited2Mask      0xfffbffff
+
+/**
+ * If this mask bit is marked then the clause is blocking clause
+ **/
+#define IsBlockingMask         0x00100000
+#define ResetIsBlockingMask    0xffefffff
+
+#define IsFrontierMask         0x00200000
+#define ResetIsFrontierMask    0xffdfffff
+
+#define InCoreMask             0x00400000
+#define ResetInCoreMask        0xffbfffff
+
+#define ResetNewVisitedObjMask 0xfffffc7f
+#define ResetNewVisitedObjInQueueMask 0xffffdc7f
+#define ResetNewVisitedMask    0xfffffe7f
+
+
+/*Bing: for interpolation*/
+#define VisibleVarMask         0x01000000
+#define ResetVisibleVarMask    0xfeffffff
+#define DummyMask              0x02000000
+#define ResetDummyMask         0xfdffffff
+#define Visited3Mask           0x04000000
+#define ResetVisited3Mask      0xfbffffff
+#define IsGlobalVarMask        0x08000000
+#define ResetGlobalVarMask     0xf7ffffff
+#define Visited4Mask           0x10000000
+#define ResetVisited4Mask      0xefffffff
+#define AssignedMask           0x20000000
+#define ResetAssignedMask      0xdfffffff
+/*pseudo global var*/
+
+#define PGVMask                0x40000000
+#define ResetPGVMask           0xbfffffff
+/*visible pseudo global var*/
+#define VPGVMask               0x00080000
+#define ResetVPGVMask          0xfff7ffff
+#define ResetVisited1234NewMask 0xebfbfe7f
+
+
+#define SAT_UNSAT 1
+#define SAT_SAT 2
+#define SAT_BACKTRACK 3
+#define SAT_BDD_UNSAT 4
+#define SAT_BDD_SAT 5
+#define SAT_BDD_BACKTRACK 6
+
+/*#define SATnodeID(node) ((node) >> 3)*/
+/*Bing:*/
+#define SATnodeID(node) (SATnormalNode(node)/satNodeSize)
+
+#define SATvalue(node) (cm->nodesArray[((node) &(~0x1L)) +satValue]) 
+
+
+/* For AIG */
+#define  satValue       bbAigValue     /* Index of value. */  
+#define  satFlags       bbAigFlags     /* Index of flag for this node.*/
+#define  satLeft        bbAigLeft      /* Index of the left child */ 
+#define  satRight       bbAigRight     /* Index of the right child */ 
+#define  satNFanout     bbAigNFanout  
+#define  satFanout      bbAigFanout    
+#define  satCanonical   bbAigCanonical     /* Index of the right child */ 
+#define  satNext        bbAigNext     /* Index of the right child */ 
+
+/*Bing: for interpolation*/
+#define  satClass       bAigClass /* equals the timeframes it is in*/
+
+#define satNumLits  bbAigLeft
+#define satFirstLit bbAigRight
+#define satNumConflict    bbAigNext
+#define satConflictUsage  bbAigFanout
+
+/*#define satNodeSize 8*/
+/*Bing*/
+#define satNodeSize 12
+
+
+#define LATEST_CONFLICT_DECISION 0x1
+#define DVH_DECISION 0x2
+
+#define SATInvertBit 0x1
+/*Bing*/
+#define SATclass(node) (cm->nodesArray[SATnormalNode(node)+satClass])
+/*
+#define SATnext(node) (cm->nodesArray[node+satNext]) 
+
+
+#define SATcanonical(node) (cm->nodesArray[node+satCanonical]) 
+
+#define SATleftChild(node) (cm->nodesArray[node+satLeft]) 
+
+#define SATrightChild(node) (cm->nodesArray[node+satRight]) 
+
+#define SATfanout(node) ((long *)(cm->nodesArray[node+satFanout])) 
+
+#define SATnFanout(node) (cm->nodesArray[node+satNFanout]) 
+*/
+/*Bing*/
+#define SATnext(node) (cm->nodesArray[SATnormalNode(node)+satNext]) 
+
+#define SATflags(node) (cm->nodesArray[SATnormalNode(node)+satFlags]) 
+
+#define SATcanonical(node) (cm->nodesArray[SATnormalNode(node)+satCanonical]) 
+
+#define SATleftChild(node) (cm->nodesArray[SATnormalNode(node)+satLeft]) 
+
+#define SATrightChild(node) (cm->nodesArray[SATnormalNode(node)+satRight]) 
+
+#define SATfanout(node) ((long *)(cm->nodesArray[SATnormalNode(node)+satFanout])) 
+
+#define SATnFanout(node) (cm->nodesArray[SATnormalNode(node)+satNFanout])
+
+#define SATgetVariable(node) (&(cm->variableArray[SATnodeID(node)]))
+
+
+#define SATflags(node) (cm->nodesArray[SATnormalNode(node)+satFlags]) 
+
+
+#define SATgetNode(lit)  (lit >> 2)
+
+#define SATgetDir(lit) ((lit&0x03) - 2)
+
+#define SATisWL(lit) (lit&0x03)
+
+#define SATunsetWL(plit) ((*plit) = (*plit) & (0x0fffffffc))
+
+#define SATsetWL(plit, dir) ((*plit) = (*plit) + dir + 2)
+
+#define SATsetInUse(node)  (SATflags(node) |= InUseMask)
+
+#define SATreadInUse(node)  (SATflags(node) & InUseMask)
+
+#define SATresetInUse(node)  (SATflags(node) &= ResetInUseMask)
+
+#define SATgetValueChar(value) (value==0 ? '0' : (value==1 ? '1' : 'x'))
+
+
+#define SATnumConflict(node) (cm->nodesArray[node+satNumConflict]) 
+
+#define SATconflictUsage(node) (cm->nodesArray[node+satConflictUsage])
+
+
+#define SATlevel(node)(\
+cm->variableArray[SATnodeID(node)].level\
+)
+
+#define SATante(node)(\
+cm->variableArray[SATnodeID(node)].antecedent\
+)
+
+#define SATante2(node)(\
+cm->variableArray[SATnodeID(node)].antecedent2\
+)
+
+#define SATgetValue(left, right, v)     \
+  ( ((SATvalue(SATnormalNode(left)) ^ SATisInverted(left)) << 4) | \
+    ((SATvalue(SATnormalNode(right)) ^ SATisInverted(right)) << 2) | \
+    (SATvalue(v)))
+
+#define SATmakeImplied(v, d)                              \
+    ( sat_ArrayInsert(d->implied, v),     \
+      SATlevel(v) = d->level)
+
+
+#define SATgetDecision(level) (&(cm->decisionHead[level]))
+
+/*#define SATflags(node) (cm->nodesArray[node+satFlags])*/
+
+#define SATnormalNode(node) ((node) & (~0x1L))
+
+#define SATnot(node) ((node) ^ SATInvertBit)
+
+#define SATisInverted(node) ((node) & (SATInvertBit))
+
+#define SATnumLits(node) (cm->nodesArray[node+satNumLits]) 
+
+#define SATfirstLit(node) (cm->nodesArray[node+satFirstLit])
+
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef struct satManagerStruct 	satManager_t;
+typedef struct satInterfaceStruct 	satInterface_t;
+typedef struct satStatisticsStruct 	satStatistics_t;
+typedef struct satOptionStruct 		satOption_t;
+typedef struct satQueueStruct 		satQueue_t;
+typedef struct satArrayStruct 		satArray_t;
+typedef struct satLiteralDBStruct 	satLiteralDB_t;
+typedef struct satLevelStruct 		satLevel_t;
+typedef struct satVariableStruct 	satVariable_t;
+typedef struct satTrieStruct 		satTrie_t;
+
+typedef struct satLinearHeadStruct 	satLinearHead_t;
+typedef struct satLinearVarStruct 	satLinearVar_t;
+typedef struct satLinearElemStruct 	satLinearElem_t;
+typedef struct satLinearClusterStruct 	satLinearCluster_t;
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [A struct for manager for CirCUs.]
+
+******************************************************************************/
+struct satManagerStruct {
+    struct satOptionStruct *option; 
+    struct satTimeFrameStruct *timeframe;
+    struct satTimeFrameStruct *timeframeWOI;
+    struct satLiteralDBStruct *literals;
+
+    struct satStatisticsStruct *total; /* to gather statistics on set of SAT runs.*/
+    struct satStatisticsStruct *each;  /* to save statistics of one SAT run. */
+
+    struct satQueueStruct *queue;  /* implication queue. */
+    struct satQueueStruct *BDDQueue; /* implication queue for BDD */
+    struct satQueueStruct *unusedAigQueue; /* queue for unused AIG for CNF. */
+
+    long *nodesArray;
+    long *HashTable;
+    long nodesArraySize;
+    long maxNodesArraySize; /* These 4 fields are used as in bAigManager_t.
+                             * We copy it to isolate code of CirCUs from 
+                             * baig package. When one build a interface
+                             * for CirCUs you have to copy back these
+                             * fields to bAig_Manager_t structure after
+			     * SAT solving. */
+
+    long beginConflict;   /* to save the beginning of conflict learned clauses. */
+    long initNodesArraySize; /* to save the initial AIG structure size.*/
+
+    struct satVariableStruct *variableArray; /* the array of satVariable_t. */
+
+    /* These 7 arrays are the array of AIG nodes.
+    * If the AIG node is inverted then it will be asserted to be '0'.
+    * Otherwise it is asserted to be '1'. */
+    struct satArrayStruct *auxObj;    /* the array of auxiliary objectives  */
+    struct satArrayStruct *obj;       /* the array of objective literal */
+    struct satArrayStruct *objCNF;    /* the array of objective clause */
+    struct satArrayStruct *assertion; /* the array of assertion */
+                                 /* it is now used to save static learned node. */
+    struct satArrayStruct *unitLits;  /* the array of unit literals for CNF */
+    struct satArrayStruct *pureLits;  /* the array of pure literals for CNF */
+    struct satArrayStruct *nonobjUnitLitArray; 
+                 /* to save unit objective independent conflict clauses
+                 * it is for incremental SAT. */
+    struct satArrayStruct *objUnitLitArray;
+                 /* to save unit objective dependent conflict clauses
+                 * it is for incremental SAT. */
+    
+    
+    struct satLevelStruct *decisionHead; /* the array of satLevel_t. */
+    int decisionHeadSize;                /* the size of *decisionHead.*/
+    int currentDecision;                 
+                 /* to represent the current decision level */
+
+    struct satArrayStruct *assignByBDD;
+    struct satArrayStruct *orderedVariableArray;
+                 /* the array of AIG nodes that are the variables.
+                 * It is for score based decision heuristic. */
+    int currentVarPos;
+                 /* to represent the index of orderedVariableArray that
+                 * is not assigned yet. */
+
+    struct satArrayStruct *savedConflictClauses;
+                 /* to save the conflict clauses that can be forwarded
+                 * when we apply incremental SAT */
+    struct satArrayStruct *trieArray;
+                 /* to save the trie to apply distillation method
+                 * when we apply incremental SAT */
+    struct satArrayStruct *auxArray;
+                 /* Can be used to save arbitrary array */
+
+    long *currentTopConflict;    
+                 /* to save current top clause 
+                 * based on the definition of BerkMin */
+    int currentTopConflictCount;
+
+    int lowestBacktrackLevel;
+                 /* to save lowest backtrack level */
+    char *comment;
+
+    int initNumVariables; /* the number of initial variables. */
+    int initNumClauses;   /* the number of initial clauses. */
+    int initNumLiterals;  /* the number of initial literals. */
+    int implicatedSoFar; /* the number of implied node so far, which sum of all implied nodes. */
+
+    FILE *stdErr;
+    FILE *stdOut;
+
+    int status; /* the status of SAT solving result
+                * SAT_BACKTRACK, SAT_SAT, SAT_UNSAT. */
+    
+    struct satArrayStruct *dormantConflictArray;
+    struct satArrayStruct *shrinkArray;
+    int shrinkEnable;
+    int shrinkSize;
+    int forceLatestConflictDecision;
+    DdManager *mgr;
+
+    struct satArrayStruct *frontier;
+    struct satArrayStruct *reached;
+    long frontierNodesBegin;
+    long frontierNodesEnd;
+    struct satArrayStruct *clauseIndexInCore;
+
+  
+    /* BING : for conflcit core generation */
+    st_table * dependenceTable;
+    st_table *anteTable;
+    struct satArrayStruct * dependenceArray;
+    int numOfClsInCore;
+    FILE *fp, *fp2;
+
+  /*Bing:*/
+  IP_Manager_t * ipm;
+  st_table * RTreeTable;/* ConClsIdx->RT ptr */
+
+  satArray_t * assertArray, *assertArray2, *CoiAssertArray, *EqArray;
+  int class_;
+  long InitState, IPState, property;
+  satArray_t * tmpArray;
+  st_table * table;
+  int test;
+  RTManager_t * rm;
+  /*for AROSAT*/
+  st_table * layerTable;
+  int OriLevel, LatchLevel;
+  int *numArray,*assignedArray;
+  int currentLevel;
+  int Length;
+  int line;
+  
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [A struct to interface CirCUs and application.
+               One can freely add a field based on his need.]
+
+******************************************************************************/
+struct satInterfaceStruct {
+    struct satStatisticsStruct *total;
+    struct satArrayStruct *nonobjUnitLitArray;
+    struct satArrayStruct *objUnitLitArray;
+    struct satArrayStruct *savedConflictClauses;
+    struct satArrayStruct *trieArray;
+    int status;
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [A struct to gather CirCUs statistics ]
+
+******************************************************************************/
+struct satStatisticsStruct {
+    int nBacktracks;                /* the number of backtracks */
+    int nNonchonologicalBacktracks; /* the sum of backtrack levels */
+    int nDecisions;                 /* the number of decisions */
+    int nDVHDecisions;              /* the number of decisions by DVH */
+    int nVSIDSDecisions;            /* the number of decisions by VSIDS */
+    int nShrinkDecisions;           
+    int nLatestConflictDecisions;   /* the number of decisions by current top clause */
+    int maxDecisionLevel;           /* the maximum decision level */
+    int nLowScoreDecisions;         /* the number of decision without sufficient information. */
+
+    int nCNFImplications;           /* the number of implication done by CNF */
+    int nAigImplications;           /* the number of implication done by AIG */
+    int nBDDImplications;           /* the number of implication done by BDD */
+    int nHyperImplications;
+
+    int nUnitConflictCl;            /* the number of unit conflict clauses */
+    int nOldConflictCl;  
+    int nConflictCl;                /* the number of conflict clauses   */
+    int nConflictLit;               /* the sum of literals in conflict clauses  */
+    int nObjConflictCl;             /* the number of object dependent conflict clauses   */
+    int nObjConflictLit;            /* the sum of literals in object dependent conflict clauses  */
+    int nNonobjConflictCl;          /* the number of object independent conflict clauses  */ 
+    int nNonobjConflictLit;          /* the sum of literals in object dependent conflict clauses  */
+    int nInitObjConflictCl;         /* the number of conflict clauses  forwarded from previous run */
+    int nInitObjConflictLit;        /* the sum of literals in conflict clauses forwarded from previous run */
+    int nInitNonobjConflictCl;
+    int nInitNonobjConflictLit;
+    int nDistillObjConflictCl;
+    int nDistillObjConflictLit;
+    int nDistillNonobjConflictCl;
+    int nDistillNonobjConflictLit;
+    int nDeletedCl;                 /* the number of conflict clauses deleted */
+    int nDeletedLit;                /* the sum of literals in conflict clauses deleted */
+    int nBlockingCl;                 /* the number of blocking clauses deleted */
+    int nBlockingLit;                /* the sum of literals in blocking clauses deleted */
+    int nDeletedButUncompacted;
+    double satTime;
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [A struct to set option for CirCUs statistics ]
+
+******************************************************************************/
+struct satOptionStruct {
+    int verbose;
+    int decisionHeuristic;      /* to select decision heuristic */
+    int decisionAgeInterval;    /* to set aging interval */
+    int decisionAgeRestart;     /* to turn on/off restart after aging */
+
+    int clauseDeletionHeuristic; /* to select clause deletion heuristic */
+    int clauseDeletionInterval;  /* to set clause deletion interval */
+    int nextClauseDeletion;
+
+    int incTraceObjective;       /* to turn on/off incremental SAT by trace objective */
+    int incDistill;              /* to turn on/off incremental SAT by distillation */
+    int incAll;
+    int incNumObjLitsLimit;      /* to limit the number literals in objective dependent cluases that can be forwarded by incremental SAT */
+    int incNumNonobjLitsLimit;   /* to limit the number literals in objective independent cluases that can be forwarded by incremental SAT */
+    int incPreserveNonobjective; /* to keep the objective independent clause while apply clause deletion */
+
+    int aig2BDDOn;               /* convert AIG into BDD when it is advantageous */
+    int BDDRecondition;          /* extract clause from BDDs by prime implication generation */
+    int BDDMonolithic;           /* build monolithic BDD for clauses */
+    int BDDDPLL;                 /* combine BDD and DPLL procedure */
+    int BDDImplication;          /* apply BDD based implication */
+
+    int includeLevelZeroLiteral; /* do add literals implied in level zero When append conflict learned clause  */
+    int minimizeConflictClause;  /* apply conflict clause minimization procedure */
+    int shrinkConflictClause;    /* apply conflict shrinking method done by JeruSAT */
+    int unrelevance;             /* set the unrelevance of conflict clause when applying clause deletion  */
+    int minLitsLimit;            /* If the number of literals in clause less than this value then keep it when applying clause deletion  */
+    int maxLitsLimit;            /* If the number of literals in clause more than this value then delete it when applying clause deletion */
+
+    int latestUsage;
+    int obsoleteUsage;
+    int latestUnrelevance;
+    int obsoleteUnrelevance;
+    int latestRate;
+
+    int restartInterval;
+
+    int memoryLimit;
+    int timeoutLimit;
+
+    int minConflictForDecision;         /* to avoid too small clause when deciding current top clause */
+    int maxConflictForDecision;         /* to avoid too large clause when deciding current top clause */
+    int skipSatisfiedClauseForDecision; /* to skip satified clause when deciding current top clause */
+
+    int maxLimitOfClausesForMonolithicBDD;
+    int maxLimitOfVariablesForMonolithicBDD;
+    int maxLimitOfCutSizeForMonolithicBDD;
+
+    int maxLimitOfClausesForBDDDPLL;
+    int maxLimitOfVariablesForBDDDPLL;
+    int maxLimitOfCutSizeForBDDDPLL;
+
+    int maxLimitOfVariablesForBDD;
+
+    int interfaceCNF;            /* to write CNF instead of running CirCUs */
+    int cnfPrefix;
+    int runOtherSolver;          /* run other CNF solver after writing CNF */
+    char *otherSolverName;       /* specify the SAT solver name */
+
+    int newConflictAnalysis;
+    int checkNonobjForwarding;
+
+    char *outFilename;
+    struct satArrayStruct *forcedAssignArr;
+
+  
+    char * unsatCoreFileName;
+  
+    int allSatMode;
+    int useStrongConflictAnalysis; /* triggering strong conflict analysis */
+  
+    /* Bing: UNSAT core generation */
+    int coreGeneration;
+  /*Bing*/
+  int IP;
+  int SSS;
+
+  int arosat;
+  int AbRf;
+  int RT;
+  int ForceFinish;
+};
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [A struct for queue]
+
+******************************************************************************/
+struct satQueueStruct {
+    long max;         /* max size of queue */
+    long size;        /* the number of current entries */
+    long front;       /* front index of entries */
+    long rear;        /* rear index of entries */
+    long *array;      /* the location to save entries */
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [A struct for array]
+
+******************************************************************************/
+struct satArrayStruct {
+    long *space;     /* the location to save entries */
+    long num;        /* the number of entries */
+    long size;       /* the size of space */
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [A struct to save lterals]
+
+******************************************************************************/
+struct satLiteralDBStruct {
+  long *begin;       /* the begin pointer of literal database */
+  long *last;        /* the pointer of last literal */
+  long *end;         /* the end pointer of literal database */
+  long *initialSize; /* the pointer of last literals that is given as input */
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [A struct for decision level]
+
+******************************************************************************/
+struct satLevelStruct {
+  int level;          /* decision level  */
+  long decisionNode;   /* decision node of this level  */
+  long conflict;       /* the conflict that happens from implication  */
+  struct satArrayStruct *implied;  /* the array of implied nodes  */
+  struct satArrayStruct *satisfied; /* the array of satisfied BDD nodes  */
+  int currentVarPos;                /* the index of decision node in orderedVariableArray  */
+  int nConflict;
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [A struct for variable]
+
+******************************************************************************/
+struct satVariableStruct {
+  int level;            /* the decision level that make implication on this variable */
+  int scores[2];        /* score for both phase   */           
+  int litsCount[2];     /* the location to save literal count */
+  int lastLitsCount[2]; /* last literal count */
+  int conflictLits[2];  /* literal count of literals in conflict clause */
+  long antecedent;      /* antecedent */
+  long antecedent2;     /* antecedent */
+  int pos;              /* position in orderedVariableArray */
+  int depth;            /* depth of variable in implication graph */
+  struct satArrayStruct *wl[2]; /* watched literal list */
+  
+  /*Bing: for AROSAT*/
+  int RecVal;  /*1 for one, -1 for zero, 0 for not recorded*/
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [A struct for trie]
+
+******************************************************************************/
+struct satTrieStruct {
+  long id;                           /* node id */
+  struct satArrayStruct *child[2];  /* childrun */
+  int depth;                        /* depth from root */
+};
+
+struct satLinearElemStruct {
+  double pos;
+  int order;
+  int num;
+  struct satArrayStruct *support;
+  long node; 
+  DdNode *bdd;
+  int flag;
+  int to;
+  struct satLinearElemStruct *next;
+};
+
+struct satLinearVarStruct {
+  double pos;
+  int order;
+  int from;
+  int to;
+  struct satArrayStruct *clauses;
+  long node;
+  DdNode *bdd;
+  int bQuantified;
+  struct satLinearVarStruct *next;
+};
+
+struct satLinearHeadStruct {
+  DdManager *mgr;
+  struct satLinearElemStruct *elemHead;
+  struct satLinearVarStruct *varHead;
+  int nVars;
+  int nCls;
+  int bddLimit;
+  int bddAndLimit;
+  long *id2edge;
+  int *edge2id;
+  int *edge2vid;
+  Heap_t *heap;
+  struct satArrayStruct *elemArray;
+  struct satArrayStruct *varArray;
+  struct satArrayStruct *clausesArray;
+  struct satArrayStruct *variablesArray;
+  struct satArrayStruct *latestClusterArray;
+  struct satArrayStruct *deadArray;
+  int reordering;
+};
+
+struct satLinearClusterStruct {
+  struct satLinearElemStruct *elem1;
+  struct satLinearElemStruct *elem2;
+  int flag;
+  int cost;
+  int overlap;
+  struct satArrayStruct *deadArray;
+};
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+EXTERN satManager_t * sat_InitManager(satInterface_t *interface);
+EXTERN satArray_t * sat_ArrayAlloc(long number);
+EXTERN satStatistics_t * sat_InitStatistics(void);
+EXTERN satOption_t * sat_InitOption(void);
+EXTERN satArray_t * sat_ReadForcedAssignment( char *filename);
+EXTERN int sat_GetNumberOfInitialClauses(satManager_t *cm);
+EXTERN int sat_GetNumberOfInitialVariables(satManager_t *cm);
+EXTERN satLevel_t * sat_AllocLevel( satManager_t *cm);
+EXTERN int sat_ConflictAnalysis( satManager_t *cm, satLevel_t *d); 
+EXTERN int sat_StrongConflictAnalysis( satManager_t *cm, satLevel_t *d); 
+EXTERN void sat_CombineStatistics(satManager_t *cm);
+EXTERN long sat_GetClauseFromLit( satManager_t *cm, long *lit);
+EXTERN long sat_DecisionBasedOnBDD( satManager_t *cm, satLevel_t *d);
+EXTERN long sat_DecisionBasedOnLatestConflict( satManager_t *cm, satLevel_t *d);
+EXTERN long sat_DecisionBasedOnScore( satManager_t *cm, satLevel_t *d);
+EXTERN void sat_CheckDecisonVariableArray( satManager_t *cm);
+EXTERN void sat_FreeManager(satManager_t *cm);
+EXTERN void sat_ArrayInsert(satArray_t *array, long datum);
+EXTERN void sat_SetIncrementalOption(satOption_t *option, int incFlag);
+EXTERN void sat_RestoreFanout(satManager_t *cm);
+EXTERN int sat_GetFanoutSize( satManager_t *cm, long v);
+EXTERN void sat_CleanLevel(satLevel_t *d);
+EXTERN void sat_CleanDatabase(satManager_t *cm);
+EXTERN void sat_SetConeOfInfluence(satManager_t *cm);
+EXTERN void sat_BuildTrieForDistill(satManager_t *cm) ;
+EXTERN void sat_AllocLiteralsDB(satManager_t *cm) ;
+EXTERN void sat_ArrayFree(satArray_t *array);
+EXTERN void sat_PrintScore(satManager_t *cm);
+EXTERN void sat_PutAssignmentValueMain( satManager_t *cm, satLevel_t *d, satArray_t *arr);
+EXTERN void sat_Main(satManager_t *cm);
+EXTERN void sat_FindUIP( satManager_t *cm, satArray_t *clauseArray, satLevel_t *d, int *objectFlag, int *bLevel, long *fdaLit);
+EXTERN void sat_FindUIPWithRT( satManager_t *cm, satArray_t *clauseArray, satLevel_t *d, int *objectFlag, int *bLevel, long *fdaLit);
+EXTERN void sat_MarkNodeInConflictClauseObjConservative( satManager_t *cm, satLevel_t *d, int *nMarked, int *oFlag, int *bLevel, satArray_t *clauseArray);
+EXTERN void sat_PrintImplicationGraph( satManager_t *cm, satLevel_t *d);
+EXTERN void sat_PrintNodeAlone(satManager_t *cm, long v);
+EXTERN void sat_PrintNode( satManager_t *cm, long v);
+EXTERN void sat_Backtrack( satManager_t *cm, int level);
+EXTERN void sat_PrintDotForConflict( satManager_t *cm, satLevel_t *d, long conflict, int includePreviousLevel);
+EXTERN long sat_AddUnitConflictClause( satManager_t *cm, satArray_t *clauseArray, int objectFlag);
+EXTERN void sat_Enqueue(satQueue_t *Q, long v);
+EXTERN long sat_AddConflictClause( satManager_t *cm, satArray_t *clauseArray, int objectFlag);
+EXTERN long sat_AddConflictClauseWithoutScoring( satManager_t *cm, satArray_t *clauseArray, int objectFlag);
+EXTERN void sat_UpdateDVH( satManager_t *cm, satLevel_t *d, satArray_t *clauseArray, int bLevel, long unitLit);
+EXTERN void sat_FindUIPForCoreGen( satManager_t *cm, satArray_t *clauseArray, satLevel_t *d, int *objectFlag, int *bLevel, long *fdaLit);
+EXTERN void sat_FindUIPForCoreGenWithRT( satManager_t *cm, satArray_t *clauseArray, satLevel_t *d, int *objectFlag, int *bLevel, long *fdaLit);
+EXTERN void sat_MarkNodeInConflict( satManager_t *cm, satLevel_t *d, int *nMarked, int *objectFlag, int *bLevel, satArray_t *clauseArray);
+EXTERN void sat_MarkNodeInImpliedNode( satManager_t *cm, satLevel_t *d, long v, int *nMarked, int *objectFlag, int *bLevel, satArray_t *clauseArray);
+EXTERN void sat_MinimizeConflictClause( satManager_t *cm, satArray_t *clauseArray);
+EXTERN void sat_ResetFlagForClauseArray( satManager_t *cm, satArray_t *clauseArray); 
+EXTERN void sat_ImplyCNF( satManager_t *cm, satLevel_t *d, long v, satArray_t *wl); 
+EXTERN int sat_ImplyNode( satManager_t *cm, satLevel_t *d, long v);
+EXTERN void sat_ImplicationMain( satManager_t *cm, satLevel_t *d);
+EXTERN void sat_CleanImplicationQueue( satManager_t *cm);
+EXTERN void sat_ImplyArray( satManager_t *cm, satLevel_t *d, satArray_t *arr);
+EXTERN void sat_ImplyBDD( satManager_t *cm, satLevel_t *d, long v);
+EXTERN void sat_BuildLevelZeroHyperImplicationGraph( satManager_t *cm);
+EXTERN void sat_PreProcessing(satManager_t *cm);
+EXTERN void sat_MarkObjectiveFlagToArray( satManager_t *cm, satArray_t *objArr);
+EXTERN void sat_PostProcessing(satManager_t *cm);
+EXTERN void sat_Solve(satManager_t *cm);
+EXTERN void sat_PeriodicFunctions(satManager_t *cm);
+EXTERN void sat_CNFMain(satOption_t *option, char *filename);
+EXTERN int sat_PrintSatisfyingAssignment(satManager_t *cm);
+EXTERN void sat_Verify(satManager_t *cm);
+EXTERN long sat_Dequeue( satQueue_t * Q );
+EXTERN long sat_CreateNode( satManager_t *cm, long left, long right);
+EXTERN int sat_EnlargeLiteralDB(satManager_t *cm);
+EXTERN void sat_AddWL( satManager_t *cm, long c, int index, int dir);
+EXTERN long sat_AddConflictClause( satManager_t *cm, satArray_t *clauseArray, int objectFlag);
+EXTERN long sat_AddUnitConflictClause( satManager_t *cm, satArray_t *clauseArray, int objectFlag);
+EXTERN void sat_FreeQueue( satQueue_t *Q );
+EXTERN void sat_ClauseDeletion(satManager_t *cm);
+EXTERN void sat_FreeLiteralsDB(satLiteralDB_t *literals);
+EXTERN void sat_CompactFanout(satManager_t *cm);
+EXTERN void sat_MarkTransitiveFaninForArray( satManager_t *cm, satArray_t *arr, unsigned int mask);
+EXTERN void sat_MarkTransitiveFaninForNode( satManager_t *cm, long v, unsigned int mask);
+EXTERN void sat_UnmarkTransitiveFaninForArray( satManager_t *cm, satArray_t *arr, unsigned int mask, unsigned int resetMask);
+EXTERN void sat_FreeInterface(satInterface_t *interface);
+EXTERN void sat_FreeOption(satOption_t * option);
+EXTERN void sat_FreeStatistics(satStatistics_t * stats);
+EXTERN int sat_ConflictAnalysisForCoreGen( satManager_t *cm, satLevel_t *d);
+EXTERN void sat_MarkNodeInConflictClauseNoObj( satManager_t *cm, satLevel_t *d, int *nMarked, int *oFlag, int *bLevel, satArray_t *clauseArray);
+EXTERN void sat_MarkNodeInImpliedNodeNoObj( satManager_t *cm, satLevel_t *d, long v, int *nMarked, int *oFlag, int *bLevel, satArray_t *clauseArray);
+EXTERN void sat_MarkNodeSub( satManager_t *cm, long v, int *nMarked, int *bLevel, satLevel_t *d, satArray_t *clauseArray); 
+EXTERN void sat_MarkNodeInImpliedNodeObjConservative( satManager_t *cm, satLevel_t *d, long v, int *nMarked, int *oFlag, int *bLevel, satArray_t *clauseArray);
+EXTERN void sat_Undo(  satManager_t *cm, satLevel_t *d); 
+EXTERN void sat_InitScore(satManager_t *cm);
+EXTERN void sat_SaveNonobjClauses(satManager_t *cm);
+EXTERN void sat_SaveAllClauses(satManager_t *cm);
+EXTERN void sat_RestoreForwardedClauses(satManager_t *cm, int objectFlag);
+EXTERN void sat_ApplyForcedAssignmentMain( satManager_t *cm, satLevel_t *d);
+EXTERN int sat_ApplyForcedAssigment( satManager_t *cm, satArray_t *arr, satLevel_t *d);
+EXTERN long sat_AddUnitClause( satManager_t *cm, satArray_t *clauseArray);
+EXTERN long sat_AddClauseIncremental( satManager_t *cm, satArray_t *clauseArray, int objectFlag, int fromDistill);
+EXTERN long sat_AddClause( satManager_t *cm, satArray_t *clauseArray);
+EXTERN long sat_AddBlockingClause( satManager_t *cm, satArray_t *clauseArray);
+EXTERN void sat_CompactClauses(satManager_t *cm);
+EXTERN void sat_UnmarkTransitiveFaninForNode( satManager_t *cm, long v, unsigned int mask, unsigned int resetMask) ;
+EXTERN void sat_IncrementalUsingDistill(satManager_t *cm);
+EXTERN void sat_UpdateScore( satManager_t *cm);
+EXTERN int sat_ReadCNF(satManager_t *cm, char *filename);
+EXTERN void sat_ReportStatistics( satManager_t *cm, satStatistics_t *stats); 
+EXTERN void sat_DeleteClause( satManager_t *cm, long v);
+EXTERN int sat_MemUsage(satManager_t *cm);
+EXTERN long sat_GetCanonical(satManager_t *cm, long v);
+EXTERN void sat_PrintClauseLitsForCore(satManager_t * cm, long concl, FILE *fp);
+EXTERN void sat_PrintClauseLits(satManager_t * cm, long concl);
+EXTERN void sat_GenerateCoreRecur(satManager_t * cm, long concl, FILE *fp, int * count);
+EXTERN void sat_GetDependence(satManager_t * cm, long concl, satArray_t* dep);
+EXTERN void sat_GenerateCore(satManager_t * cm);
+EXTERN void sat_PrintUnitLiteralClauses( satManager_t *cm, satArray_t *arr, FILE *fout);
+EXTERN void sat_CountUnitLiteralClauses( satManager_t *cm, satArray_t *arr, int *nCl);
+EXTERN void sat_WriteCNFWithPointer(satManager_t *cm, FILE *fout);
+EXTERN void sat_WriteCNF(satManager_t *cm, char *filename);
+EXTERN void sat_PrintUnitLiteralClauses( satManager_t *cm, satArray_t *arr, FILE *fout);
+EXTERN void sat_CountUnitLiteralClauses( satManager_t *cm, satArray_t *arr, int *nCl);
+EXTERN void sat_WriteCNFWithPartialAssignment(satManager_t *cm, char *filename);
+EXTERN void sat_TrieBasedImplication( satManager_t *cm, satArray_t *trieArray, int depth);
+EXTERN void sat_FreeTrie(satManager_t *cm, satArray_t *arr);
+EXTERN satLevel_t * sat_DecisionBasedOnTrie( satManager_t *cm, long v, int value);
+EXTERN void sat_TrieBasedImplication( satManager_t *cm, satArray_t *trieArray, int depth);
+EXTERN void sat_ConflictAnalysisOnTrie( satManager_t *cm, satLevel_t *d);
+EXTERN void sat_BuildTrie( satManager_t *cm, satArray_t *trieArray, long *plit, int depth);
+EXTERN void sat_FreeTrie(satManager_t *cm, satArray_t *arr);
+EXTERN void sat_PrintFlag(satManager_t *cm, long v);
+EXTERN void sat_PrintLiteral(satManager_t *cm, long lit);
+EXTERN void sat_CheckFlagsOnConflict(satManager_t *cm);
+EXTERN void sat_PrintDotForConflict( satManager_t *cm, satLevel_t *d, long conflict, int includePreviousLevel);
+EXTERN void sat_PrintDotForImplicationGraph( satManager_t *cm, satLevel_t *d, satArray_t *root, int includePreviousLevel);
+EXTERN void sat_PrintDotForWholeGraph( satManager_t *cm, satLevel_t *d, int includePreviousLevel) ;
+EXTERN void sat_PrintDotForImplicationGraph( satManager_t *cm, satLevel_t *d, satArray_t *root, int includePreviousLevel);
+EXTERN void sat_CheckNonobjConflictClause( satManager_t *cm, long v);
+EXTERN void sat_CheckNonobjUnitClause( satManager_t *cm);
+EXTERN void sat_CheckInitialCondition( satManager_t *cm);
+EXTERN void sat_PrintClauseArray( satManager_t *cm, satArray_t *clauseArray);
+EXTERN void sat_CheckConflictClause( satManager_t *cm, satArray_t *clauseArray) ;
+EXTERN void sat_ImplyUnitPureLitsWithAnte(satManager_t * cm, satLevel_t *d);
+EXTERN long sat_DecisionBasedOnShrink( satManager_t *cm);
+EXTERN void sat_CheckOrderedVariableArray(satManager_t *cm);
+EXTERN void sat_GetConflictAsConflictClause( satManager_t *cm, satArray_t *clauseArray);
+EXTERN void sat_CheckForwardedClauses(satManager_t *cm);
+EXTERN void sat_TryToBuildMonolithicBDD(satManager_t *cm);
+EXTERN void sat_FindUIPAndNonUIP( satManager_t *cm, satArray_t *clauseArray, satLevel_t *d, int *objectFlag, int *bLevel, long *fdaLit);
+EXTERN long sat_AddConflictClauseNoScoreUpdate( satManager_t *cm, satArray_t *clauseArray, int objectFlag);
+EXTERN void sat_ClauseDeletionLatestActivity(satManager_t *cm);
+EXTERN int sat_ConflictAnalysisUsingAuxImplication( satManager_t *cm, satArray_t *clauseArray); 
+EXTERN int sat_AddConflictClauseAndBacktrack( satManager_t *cm, satArray_t *clauseArray, satLevel_t *d, long fdaLit, int bLevel, int objectFlag, int strongFlag);
+EXTERN void sat_RestoreBlockingClauses(satManager_t *cm);
+EXTERN void sat_RestoreFrontierClauses(satManager_t *cm);
+EXTERN void sat_CollectBlockingClause(satManager_t *cm);
+EXTERN void sat_PreProcessingForMixed(satManager_t *cm);
+EXTERN satLevel_t * sat_MakeDecision(satManager_t *cm);
+EXTERN satLevel_t * sat_AllocLevel( satManager_t *cm);
+EXTERN int sat_AddConflictClauseWithNoScoreAndBacktrack( satManager_t *cm, satArray_t *clauseArray, satLevel_t *d, long fdaLit, int bLevel, int objectFlag, int strongFlag);
+EXTERN void sat_InitScoreForMixed(satManager_t *cm);
+EXTERN satArray_t *sat_ArrayDuplicate(satArray_t *old);
+EXTERN int sat_ConflictAnalysisWithBlockingClause( satManager_t *cm, satLevel_t *d);
+EXTERN int sat_ConflictAnalysisForLifting( satManager_t *cm, satLevel_t *d);
+EXTERN int sat_AddConflictClauseAndBacktrackForLifting( satManager_t *cm, satArray_t *clauseArray, satLevel_t *d, long fdaLit, int bLevel, int objectFlag, int strongFlag);
+EXTERN void sat_PreProcessingForMixedNoCompact(satManager_t *cm);
+EXTERN int sat_CNFMainWithArray( satOption_t *option, satArray_t *cnfArray, int unsatCoreFlag, satArray_t *coreArray, st_table *mappedTable);
+EXTERN int sat_WriteCNFFromArray(satArray_t *cnfArray, char *filename);
+EXTERN int sat_ReadCNFFromArray( satManager_t *cm, satArray_t *cnfArray, st_table *mappedTable);
+EXTERN void sat_RestoreClauses(satManager_t *cm, satArray_t *cnfArray);
+EXTERN satQueue_t * sat_CreateQueue( long MaxElements );
+
+
+
+/*Bing: for AROSAT*/
+EXTERN void sat_ASUpdateScore(satManager_t *cm);
+EXTERN void sat_ASmergeLevel(satManager_t *cm);
+EXTERN int sat_CE_CNF(satManager_t *cm,satLevel_t *d,
+	       int v,satArray_t *wl);
+EXTERN int sat_CE(satManager_t *cm,satLevel_t *d,
+	   long v,int dfs,int value);
+EXTERN int sat_ASDec(satManager_t *cm,satLevel_t *d,long v);
+EXTERN int sat_ASImp(satManager_t *cm,satLevel_t *d,long v,int value);
+
+/**AutomaticEnd**************************************************************/
+
+#endif /* _SAT */
+
+
Index: vis_dev/vis-2.3/src/sat/sat.make
===================================================================
--- vis_dev/vis-2.3/src/sat/sat.make	(revision 14)
+++ vis_dev/vis-2.3/src/sat/sat.make	(revision 14)
@@ -0,0 +1,6 @@
+CSRC += satConflict.c satImplication.c satMain.c \
+        satUtil.c satDecision.c satInc.c satDebug.c\
+        satInterface.c satBDD.c satCore.c
+HEADERS += sat.h satInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/sat/satBDD.c
===================================================================
--- vis_dev/vis-2.3/src/sat/satBDD.c	(revision 14)
+++ vis_dev/vis-2.3/src/sat/satBDD.c	(revision 14)
@@ -0,0 +1,1432 @@
+/**CFile***********************************************************************
+
+  FileName    [satBDD.c]
+
+  PackageName [sat]
+
+  Synopsis    [Routines for using BDD.]
+
+  Author      [HoonSang Jin]
+
+  Copyright [ This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+
+******************************************************************************/
+
+#include "satInt.h"
+#ifdef BDDcu
+#include "cuddInt.h"
+#endif
+
+static char rcsid[] UNUSED = "$Id: satBDD.c,v 1.30 2009/04/11 18:26:37 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#ifdef BDDcu
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int heapCostCompare(const void *c1, const void *c2);
+static int sat_ConvertCNF2BDD(satManager_t *cm, DdManager *mgr, int conflictFlag);
+static void sat_FreeLinearHead(satLinearHead_t *head);
+static int linearVarCompare(const void * node1, const void * node2);
+static int linearElemCompare(const void * node1, const void * node2);
+static void sat_GetArrangementByForce(satManager_t *cm, satLinearHead_t *head);
+static int sat_PrintCutProfile(satManager_t *cm, satLinearHead_t *head, char *baseName, int printFlag);
+static int sat_ClusteringElementMain(satManager_t *cm, satLinearHead_t *head);
+static void sat_ComputeVariableRange(satManager_t *cm, satLinearHead_t *head);
+static void sat_InitClusteringElement(satManager_t *cm, satLinearHead_t *head);
+static void sat_PrintSupportVariable(satLinearHead_t *head, satLinearElem_t *e1);
+static void sat_ClusteringGetCandidate(satManager_t *cm, satLinearHead_t *head);
+static DdNode *sat_SmoothWithDeadVariable(DdManager *mgr, satArray_t *deadArray, DdNode *bdd1, DdNode *bdd2, int bddAndLimit);
+static int sat_ClusteringElement(satManager_t *cm, satLinearHead_t *head);
+static void sat_FreeCluster(DdManager *mgr, satLinearCluster_t *clu);
+static void sat_CheckDeadNode(satLinearHead_t *head, satLinearCluster_t *clu);
+
+/**AutomaticEnd***************************************************************/
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+#ifdef BDDcu
+
+/**Function********************************************************************
+
+  Synopsis    [Build monolithic BDD.]
+
+  Description [Try to build a monolithic BDD from the set of clauses.
+	       If it is succeeded then we can conclude whether given CNF is
+	       satisfiable of not.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_TryToBuildMonolithicBDD(satManager_t *cm)
+{
+DdManager *mgr;
+int nVariables, flag;
+
+  nVariables = cm->initNumVariables - cm->implicatedSoFar;
+
+  if(nVariables
+	  > cm->option->maxLimitOfVariablesForMonolithicBDD)	return;
+
+  mgr = Cudd_Init((unsigned int)(nVariables+1), 0, CUDD_UNIQUE_SLOTS,
+		   CUDD_CACHE_SLOTS, getSoftDataLimit() / 10 * 9);
+  cm->mgr = mgr;
+  flag = sat_ConvertCNF2BDD(cm, mgr, 0);
+
+  Cudd_Quit(mgr);
+  cm->mgr = 0;
+
+  if(flag == SAT_BDD_UNSAT)
+    cm->status = SAT_UNSAT;
+
+  return;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Apply cofactoring to the set of BDDs.]
+
+  Description [Apply cofactoring to the set of BDDs.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+DdNode *
+sat_CofactorBDDArray(
+	satLinearHead_t *head,
+	DdManager *mgr,
+	DdNode *l1,
+	satArray_t *satArr)
+{
+int i, vid, inverted;
+long v;
+DdNode *bdd, *result, *nresult;
+satLinearVar_t *var;
+
+  result = l1;
+  cuddRef(result);
+  for(i=0; i<satArr->num; i++) {
+    v = satArr->space[i];
+    inverted = SATisInverted(v);
+    v = SATnormalNode(v);
+    vid = head->edge2vid[SATnodeID(v)];
+    var = &(head->varHead[vid]);
+    bdd = inverted ? Cudd_Not(var->bdd) : var->bdd;
+
+    nresult = Cudd_bddConstrain(mgr, result, bdd);
+    cuddRef(nresult);
+    Cudd_RecursiveDeref(mgr, result);
+    result = nresult;
+  }
+  return(result);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Extract satisfying assignment from BDD.]
+
+  Description [Since we quantify the variables if they are isolated,
+	       the resulting BDD is ONE or ZERO. If BDD is ONE then the satisfying
+	       assignments are extracted from the set of BDDs saved during clustering.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_ExtractAssignmentFromBDD(
+	satLinearHead_t *head,
+	DdManager *mgr,
+	satArray_t *arr,
+	DdNode *cube)
+{
+DdNode *C, *T, *E, *zero;
+
+  C = Cudd_Regular(cube);
+  zero = Cudd_Not(DD_ONE(mgr));
+  if (!cuddIsConstant(C)) {
+    while (!cuddIsConstant(C)) {
+      T = cuddT(C);
+      E = cuddE(C);
+      if (Cudd_IsComplement(cube)) {
+	T = Cudd_Not(T);
+	E = Cudd_Not(E);
+      }
+      if (T == zero)  { /** T == 0 **/
+	  sat_ArrayInsert(arr, ((head->id2edge[C->index]) + 1));
+	  cube = E;
+      }
+      else {                   /** E == 0 **/
+	  sat_ArrayInsert(arr, (head->id2edge[C->index]));
+	  cube = T;
+      }
+      C = Cudd_Regular(cube);
+    }
+  }
+  return;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Create  satLinearHead_t structure.]
+
+  Description [Build initial data structure for linear arrangement and clustering.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+satLinearHead_t *
+sat_CreateLinearHead(
+	satManager_t *cm,
+	int conflictFlag)
+{
+satLinearHead_t *head;
+satLinearElem_t *elem;
+satLinearVar_t *lvar;
+satArray_t *cArray, *vArray;
+int nVars, nCls, varId;
+int j, size, satisfied, inverted;
+int value;
+long v, *plit, i;
+int elemIndex, varIndex;
+int clauseLimit;
+
+  nVars = 0;
+  nCls = 0;
+  cArray = sat_ArrayAlloc(1024);
+  vArray = sat_ArrayAlloc(1024);
+  for(i=satNodeSize; i<cm->initNodesArraySize; i+=satNodeSize) {
+    if(!(SATflags(i) & IsCNFMask))	continue;
+    if(SATreadInUse(i) == 0)	continue;
+  /**  CONSIDER conflict clause...   **/
+    size = SATnumLits(i);
+    satisfied = 0;
+    plit = (long *)SATfirstLit(i);
+    for(j=0; j<size; j++, plit++) {
+      v = SATgetNode(*plit);
+      inverted = SATisInverted(v);
+      v = SATnormalNode(v);
+      value = SATvalue(v) ^ inverted;
+      if(value == 1) {
+	satisfied = 1;
+	break;
+      }
+    }
+    if(satisfied)	continue;
+
+    nCls++;
+    SATflags(i) |= VisitedMask;
+    sat_ArrayInsert(cArray, i);
+
+    plit = (long *)SATfirstLit(i);
+    for(j=0; j<size; j++, plit++) {
+      v = SATgetNode(*plit);
+      v = SATnormalNode(v);
+      if(SATvalue(v) < 2)	continue;
+      if(!(SATflags(v) & VisitedMask)) {
+	nVars++;
+	SATflags(v) |= VisitedMask;
+	sat_ArrayInsert(vArray, v);
+      }
+    }
+  }
+
+  if(conflictFlag)
+    clauseLimit = cm->option->maxLimitOfClausesForBDDDPLL;
+  else
+    clauseLimit = cm->option->maxLimitOfClausesForMonolithicBDD;
+
+  if(nCls > clauseLimit) {
+    if(nVars > 100) {
+      for(i=0; i<cArray->num; i++) {
+	v = cArray->space[i];
+	SATflags(v) &= ResetVisitedMask;
+      }
+      sat_ArrayFree(cArray);
+      for(i=0; i<vArray->num; i++) {
+	v = vArray->space[i];
+	SATflags(v) &= ResetVisitedMask;
+      }
+      sat_ArrayFree(vArray);
+      return(0);
+    }
+  }
+
+  if(cm->option->verbose > 1) {
+    fprintf(cm->stdOut, "NOTICE : Apply BDD based method at level %d with %d vars %d cls\n", cm->currentDecision, nVars, nCls);
+    fflush(cm->stdOut);
+  }
+  head = ALLOC(satLinearHead_t, 1);
+  memset(head, 0, sizeof(satLinearHead_t));
+  head->clausesArray = cArray;
+  head->variablesArray = vArray;
+  head->reordering = 1;
+  head->nVars = nVars;
+  head->nCls = nCls;
+  head->bddLimit = 5000;
+  head->bddAndLimit = 10000;
+
+  head->elemHead = ALLOC(satLinearElem_t, nCls);
+  memset(head->elemHead, 0, sizeof(satLinearElem_t)*nCls);
+  head->varHead = ALLOC(satLinearVar_t, nVars);
+  memset(head->varHead, 0, sizeof(satLinearVar_t)*nVars);
+
+  head->elemArray = sat_ArrayAlloc(nCls);
+  head->varArray = sat_ArrayAlloc(nVars);
+  head->latestClusterArray = sat_ArrayAlloc(32);
+  head->deadArray = sat_ArrayAlloc(nVars);
+
+  head->id2edge = ALLOC(long, nVars+1);
+  head->edge2id = ALLOC(int, cm->initNumVariables+1);
+  head->edge2vid = ALLOC(int, cm->initNumVariables+1);
+
+  varIndex = 0;
+  for(i=0; i<vArray->num; i++) {
+    v = vArray->space[i];
+    SATflags(v) &= ResetVisitedMask;
+    lvar = &(head->varHead[varIndex]);
+    head->edge2vid[SATnodeID(v)] = varIndex;
+    sat_ArrayInsert(head->varArray, (long)lvar);
+    lvar->order = varIndex++;
+    lvar->node = v;
+    lvar->bQuantified = 1;
+    lvar->clauses = sat_ArrayAlloc(4);
+  }
+
+  elemIndex = 0;
+  for(i=0; i<cArray->num; i++) {
+    v = cArray->space[i];
+    SATflags(v) &= ResetVisitedMask;
+    elem = &(head->elemHead[elemIndex]);
+    sat_ArrayInsert(head->elemArray, (long)elem);
+    elem->node = v;
+    elem->order = elemIndex++;
+
+    size = SATnumLits(v);
+    elem->support = sat_ArrayAlloc(size);
+    plit = (long *)SATfirstLit(v);
+    for(j=0; j<size; j++, plit++) {
+      v = SATgetNode(*plit);
+      inverted = SATisInverted(v);
+      v = SATnormalNode(v);
+      value = SATvalue(v) ^ inverted;
+      if(value == 0)	{
+	continue;
+      }
+      varId = head->edge2vid[SATnodeID(v)];
+      lvar = &(head->varHead[varId]);
+
+      sat_ArrayInsert(lvar->clauses, (long)elem);
+      if(inverted)	lvar = (satLinearVar_t *)SATnot((unsigned long)lvar);
+      sat_ArrayInsert(elem->support, (long)lvar);
+    }
+  }
+  return(head);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Create  satLinearCluster_t  for each clutering candidate]
+
+  Description [Create  satLinearCluster_t  for each clutering candidate]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+satLinearCluster_t *
+sat_CreateCluster(
+	satLinearHead_t *head,
+	satLinearElem_t *e1,
+	satLinearElem_t *e2,
+	int flagIndex,
+	int *idArr)
+{
+satLinearCluster_t *clu;
+satLinearVar_t *var;
+satArray_t *support, *deadArray;
+int from, to, nDead;
+int nv, bddid;
+int overlap, bddsize, j;
+
+  memset(idArr, 0, sizeof(int)*(head->nVars));
+  clu = ALLOC(satLinearCluster_t, 1);
+  clu->elem1 = e1;
+  clu->elem2 = e2;
+  clu->deadArray = 0;
+  from = e1->order;
+  to = e2->order;
+  nDead = 0;
+  support = e1->support;
+  for(j=0; j<support->num; j++) {
+    var = (satLinearVar_t *)support->space[j];
+    var = (satLinearVar_t *)SATnormalNode((unsigned long)var);
+    nv = var->node;
+    bddid = head->edge2id[SATnodeID(nv)];
+    idArr[bddid] = 1;
+
+    if(var->bQuantified && from <= var->from && var->to <= to) {
+      nDead++;
+      if(clu->deadArray == 0) {
+	deadArray = sat_ArrayAlloc(2);
+	clu->deadArray = deadArray;
+      }
+      else
+	deadArray = clu->deadArray;
+      sat_ArrayInsert(deadArray, (long)var);
+    }
+  }
+
+  overlap = 0;
+  support = e2->support;
+  for(j=0; j<support->num; j++) {
+    var = (satLinearVar_t *)support->space[j];
+    var = (satLinearVar_t *)SATnormalNode((unsigned long)var);
+    nv = var->node;
+    bddid = head->edge2id[SATnodeID(nv)];
+    if(idArr[bddid]) {
+      if(from <= var->from && var->to <= to);
+      else
+	overlap++;
+    }
+    else {
+      if(var->bQuantified && from <= var->from && var->to <= to) {
+	nDead++;
+	if(clu->deadArray == 0) {
+	  deadArray = sat_ArrayAlloc(2);
+	  clu->deadArray = deadArray;
+	}
+	else
+	  deadArray = clu->deadArray;
+	sat_ArrayInsert(deadArray, (long)var);
+      }
+    }
+  }
+
+  bddsize = Cudd_DagSize(e1->bdd) + Cudd_DagSize(e2->bdd);
+  clu->overlap = overlap;
+  clu->cost = (nDead<<7) + (overlap*(1024/bddsize)) + 10000/bddsize;
+  clu->flag = flagIndex;
+
+  return(clu);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Print support variables of element(clause).]
+
+  Description [Print support variables of element(clause).]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+sat_PrintSupportVariable(
+	satLinearHead_t *head,
+	satLinearElem_t *e1)
+{
+satArray_t *support;
+satLinearVar_t *var;
+int j;
+long nv;
+
+
+  support = e1->support;
+  for(j=0; j<support->num; j++) {
+    var = (satLinearVar_t *)support->space[j];
+    var = (satLinearVar_t *)SATnormalNode((unsigned long)var);
+    nv = var->node;
+/**    bddid = head->edge2id[SATnodeID(nv)]; **/
+    fprintf(stdout, " %ld", nv);
+  }
+  fprintf(stdout, "\n");
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Compare function for heapify]
+
+  Description [Compare function for heapify]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+heapCostCompare(const void *c1, const void *c2)
+{
+satLinearCluster_t *clu1, *clu2;
+
+  clu1 = (satLinearCluster_t *)c1;
+  clu2 = (satLinearCluster_t *)c2;
+  return(clu1->cost < clu2->cost);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Create initial clustering candidates]
+
+  Description [Create initial clustering candidates]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+sat_ClusteringGetCandidate(
+	satManager_t *cm,
+	satLinearHead_t *head)
+{
+int i, *idArr;
+satArray_t *eArr;
+satLinearElem_t *e1, *e2;
+satLinearCluster_t *clu;
+
+  eArr = head->elemArray;
+  head->heap = Heap_HeapInitCompare(eArr->num+2, heapCostCompare);
+
+  idArr = ALLOC(int, head->nVars);
+  for(i=0; i<eArr->num; i++) {
+
+    e1 = (satLinearElem_t *)eArr->space[i];
+    if(i == eArr->num-1)
+      continue;
+    else
+      e2 = (satLinearElem_t *)eArr->space[i+1];
+
+    e1->flag = 1;
+    e2->flag = 1;
+    clu = sat_CreateCluster(head, e1, e2, 1, idArr);
+
+    Heap_HeapInsertCompare(head->heap, (void *)clu, (long)clu);
+  }
+
+  free(idArr);
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Apply existential qunatification for cluster.]
+
+  Description [Apply existential qunatification for cluster.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static DdNode *
+sat_SmoothWithDeadVariable(
+	DdManager *mgr,
+	satArray_t *deadArray,
+	DdNode *bdd1,
+	DdNode *bdd2,
+	int bddAndLimit)
+{
+satLinearVar_t *var;
+DdNode *cube, *ncube;
+DdNode *result;
+int i;
+
+
+  cube = DD_ONE(mgr);
+  cuddRef(cube);
+  for(i=0; i<deadArray->num; i++) {
+    var = (satLinearVar_t *)deadArray->space[i];
+    ncube = Cudd_bddAnd(mgr,cube,var->bdd);
+    if(ncube == NULL) {
+      Cudd_RecursiveDeref(mgr, cube);
+      return(NULL);
+    }
+    cuddRef(ncube);
+    Cudd_RecursiveDeref(mgr, cube);
+    cube = ncube;
+  }
+
+
+  result = Cudd_bddAndAbstractLimit(
+	      mgr,bdd1,bdd2,cube,bddAndLimit);
+  if(result == NULL) {
+    Cudd_RecursiveDeref(mgr, cube);
+    return(NULL);
+  }
+  cuddRef(result);
+  Cudd_RecursiveDeref(mgr, cube);
+  cuddDeref(result);
+
+  return(result);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Apply clustering.]
+
+  Description [Apply clustering.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+sat_ClusteringElement(
+	satManager_t *cm,
+	satLinearHead_t *head)
+{
+int modified, total, size;
+int found, i, vid, index;
+long v;
+int *idArr, *idSupport;
+int limit, nElem;
+satLinearElem_t *e1, *e2;
+satLinearVar_t *lvar;
+satLinearCluster_t *clu, *tclu;
+satArray_t *support, *deadArray;
+satArray_t *neArr, *eArr;
+DdManager *mgr;
+DdNode *result, *zero;
+Heap_t *heap;
+long dummy;
+
+  heap = head->heap;
+  modified = 0;
+
+  idArr = ALLOC(int, head->nVars);
+
+  mgr = head->mgr;
+  eArr = head->elemArray;
+  /**
+  if(eArr->num <= 5 && head->reordering)
+    Cudd_ReduceHeap(mgr,mgr->autoMethod,10);
+    **/
+
+  zero = Cudd_Not(DD_ONE(mgr));
+  limit = ((eArr->num)>>1);
+  nElem = eArr->num;
+
+  if(cm->option->verbose > 3)
+    fprintf(cm->stdOut, " ------- %d element\n", nElem);
+
+  while(Heap_HeapExtractMin(heap, &clu, &dummy)) {
+    if(modified > limit) {
+      sat_FreeCluster(mgr, clu);
+      continue;
+    }
+    e1 = clu->elem1;
+    e2 = clu->elem2;
+    if(e1->flag == 0 || e2->flag == 0) {
+      sat_FreeCluster(mgr, clu);
+      continue;
+    }
+    if(e1->flag > clu->flag || e2->flag > clu->flag) {
+      sat_FreeCluster(mgr, clu);
+      continue;
+    }
+    deadArray = clu->deadArray;
+    if(deadArray) {
+      cuddRef(e1->bdd);
+      cuddRef(e2->bdd);
+      result = sat_SmoothWithDeadVariable(
+	      mgr, deadArray, e1->bdd, e2->bdd, head->bddAndLimit);
+      if(result)
+	cuddRef(result);
+      Cudd_RecursiveDeref(mgr, e1->bdd);
+      Cudd_RecursiveDeref(mgr, e2->bdd);
+      for(i=0; i<deadArray->num; i++) {
+	lvar = (satLinearVar_t *)deadArray->space[i];
+	sat_ArrayInsert(head->deadArray, (long)lvar);
+      }
+    }
+    else {
+      result = Cudd_bddAndLimit(mgr,e1->bdd,e2->bdd,head->bddAndLimit);
+      if(result)
+	cuddRef(result);
+    }
+
+    total = Cudd_ReadKeys(mgr) - Cudd_ReadDead(mgr);
+    if(total > 100000 && head->reordering) {
+      head->reordering = 0;
+      Cudd_AutodynDisable(mgr);
+    }
+
+    if(result) {
+	/**  CONSIDER the case that result is DD_ZERO... **/
+      nElem--;
+      if(cm->option->verbose > 3) {
+	fprintf(cm->stdOut, " (%4d %4d) %4d(%3d, %3ld): %d X %d = %d\n",
+	      e1->order, e2->order,
+	      clu->cost, clu->overlap, deadArray ? deadArray->num : 0,
+	      Cudd_DagSize(e1->bdd), Cudd_DagSize(e2->bdd),
+	      Cudd_DagSize(result));
+	sat_PrintSupportVariable(head, e1);
+	sat_PrintSupportVariable(head, e2);
+	if(deadArray) {
+	for(i=0; i<deadArray->num; i++) {
+	  lvar = (satLinearVar_t *)deadArray->space[i];
+	  fprintf(cm->stdOut, "%ld ", lvar->node);
+	}
+	}
+	fprintf(cm->stdOut, "\n");
+      }
+      modified++;
+      e1->flag += 1;
+      e2->flag = 0;
+
+      if(nElem < 50) {
+	sat_ArrayInsert(head->latestClusterArray, (long)(e1->bdd));
+	cuddRef(e1->bdd);
+	sat_ArrayInsert(head->latestClusterArray, (long)(e2->bdd));
+	cuddRef(e2->bdd);
+      }
+
+      Cudd_RecursiveDeref(mgr, e1->bdd);
+      Cudd_RecursiveDeref(mgr, e2->bdd);
+      e1->bdd = result;
+      e2->bdd = 0;
+      sat_ArrayFree(e1->support);
+      e1->support = 0;
+      support = e2->support;
+      for(i=0; i<support->num; i++) {
+	lvar = (satLinearVar_t *)support->space[i];
+	if(lvar->to == e2->order)
+	  lvar->to = e1->order;
+	if(lvar->from == e2->order)
+	  lvar->from = e1->order;
+      }
+      sat_ArrayFree(e2->support);
+      e2->support = 0;
+
+      size = (unsigned int)Cudd_ReadSize(mgr);
+      idSupport = Cudd_SupportIndex(mgr,result);
+      e1->support = support = sat_ArrayAlloc(10);
+      for (i = 0; i < size; i++) {
+	if(idSupport[i]) {
+	  v = head->id2edge[i];
+	  vid = head->edge2vid[SATnodeID(v)];
+	  lvar = &(head->varHead[vid]);
+	  sat_ArrayInsert(support, (long)lvar);
+	  /**
+	  if(lvar->to == e2->order)
+	    lvar->to = e1->order;
+	  if(lvar->from == e2->order)
+	    lvar->from = e1->order;
+	    **/
+	}
+      }
+      free(idSupport);
+
+      found = 0;
+      for(i=e1->order-1; i>=0; i--)  {
+	e2 = (satLinearElem_t *)eArr->space[i];
+	if(e2->flag)	{
+	  found = 1;
+	  break;
+	}
+      }
+      if(found) {
+	tclu = sat_CreateCluster(head, e2, e1, e1->flag, idArr);
+	Heap_HeapInsertCompare(head->heap, (void *)tclu, (long)tclu);
+      }
+
+      found = 0;
+      for(i=e1->order+1; i<eArr->num; i++)  {
+	e2 = (satLinearElem_t *)eArr->space[i];
+	if(e2->flag)	{
+	  found = 1;
+	  break;
+	}
+      }
+      if(found) {
+	tclu = sat_CreateCluster(head, e1, e2, e1->flag, idArr);
+	Heap_HeapInsertCompare(head->heap, (void *)tclu, (long)tclu);
+      }
+    }
+    sat_FreeCluster(mgr, clu);
+  }
+
+  Heap_HeapFree(heap);
+  head->heap = 0;
+
+  free(idArr);
+
+  if(modified) {
+    eArr = head->elemArray;
+    neArr = sat_ArrayAlloc(eArr->num);
+    index = 0;
+    for(i=0; i<eArr->num; i++) {
+      e1 = (satLinearElem_t *)eArr->space[i];
+      if(e1->flag == 0)	continue;
+
+      e1->order = index++;
+      sat_ArrayInsert(neArr, (long)e1);
+    }
+    sat_ArrayFree(eArr);
+    head->elemArray = neArr;
+  }
+
+  if(head->elemArray->num == 1)
+    modified = 0;
+
+  return(modified);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Free satLinearCluster_t]
+
+  Description [Free satLinearCluster_t]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+sat_FreeCluster(DdManager *mgr, satLinearCluster_t *clu)
+{
+satArray_t *deadArray;
+
+  deadArray = clu->deadArray;
+  if(deadArray) {
+    sat_ArrayFree(deadArray);
+  }
+  free(clu);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sanity check for dead node]
+
+  Description [Sanity check for dead node]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+sat_CheckDeadNode(
+	satLinearHead_t *head,
+	satLinearCluster_t *clu)
+{
+satArray_t *deadArray, *eArr;
+satArray_t *support;
+satLinearVar_t *var, *tvar;
+satLinearElem_t *elem;
+int i, j, k;
+
+
+  if(clu->deadArray) {
+    deadArray = clu->deadArray;
+    for(i=0; i<deadArray->num; i++) {
+      var = (satLinearVar_t *)deadArray->space[i];
+      eArr = head->elemArray;
+      for(j=0; j<var->from; j++) {
+	elem = (satLinearElem_t *)eArr->space[j];
+	if(elem->flag == 0)	continue;
+	support = elem->support;
+	for(k=0; k<support->num; k++) {
+	  tvar = (satLinearVar_t *)support->space[k];
+	  tvar = (satLinearVar_t *)SATnormalNode((unsigned long)tvar);
+	  if(var == tvar) {
+	    fprintf(stdout, "Error : wrong variable range\n");
+	  }
+	}
+      }
+      for(j=var->to+1; j<eArr->num; j++) {
+	elem = (satLinearElem_t *)eArr->space[j];
+	if(elem->flag == 0)	continue;
+	support = elem->support;
+	for(k=0; k<support->num; k++) {
+	  tvar = (satLinearVar_t *)support->space[k];
+	  tvar = (satLinearVar_t *)SATnormalNode((unsigned long)tvar);
+	  if(var == tvar) {
+	    fprintf(stdout, "Error : wrong variable range\n");
+	  }
+	}
+      }
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Convert CNF into BDD.]
+
+  Description [First, the force based clauses arrangement is applied to get
+	       a min max -cut arrangement of clauses.
+	       Then apply the iterative clustering algorithm to get a monolithic
+	       BDD.]
+
+  SideEffects []
+
+  SeeAlso     [sat_TryToBuildMonolithicBDD]
+
+******************************************************************************/
+static int
+sat_ConvertCNF2BDD(
+	satManager_t *cm,
+	DdManager *mgr,
+	int conflictFlag)
+{
+satLinearHead_t *head;
+DdNode *result, *cube;
+DdNode *l1, *l2;
+DdNode *nl1, *nl2;
+satArray_t *satArr, *arr;
+int limitCut;
+int flag, length;
+int cut, i;
+
+  head = sat_CreateLinearHead(cm, conflictFlag);
+
+  if(head == 0)	return(0);
+
+  head->mgr = mgr;
+
+  sat_GetArrangementByForce(cm, head);
+
+  if(cm->option->verbose > 3)
+    cut = sat_PrintCutProfile(cm, head, "final", 1);
+  else
+    cut = sat_PrintCutProfile(cm, head, "final", 0);
+
+  if(conflictFlag)
+    limitCut = cm->option->maxLimitOfCutSizeForBDDDPLL;
+  else
+    limitCut = cm->option->maxLimitOfCutSizeForMonolithicBDD;
+  if(cut > limitCut) {
+    sat_FreeLinearHead(head);
+    return(SAT_BDD_BACKTRACK);
+  }
+
+  flag = sat_ClusteringElementMain(cm, head);
+
+  if(flag == SAT_BDD_SAT) {
+    arr = head->latestClusterArray;
+    satArr = sat_ArrayAlloc(16);
+    for(i=arr->num-1; i>=0; i--) {
+      l1 = (DdNode *)arr->space[i];
+      i--;
+      l2 = (DdNode *)arr->space[i];
+      nl1 = sat_CofactorBDDArray(head, mgr, l1, satArr);
+      nl2 = sat_CofactorBDDArray(head, mgr, l2, satArr);
+      result = Cudd_bddAndLimit(mgr, nl1, nl2, head->bddAndLimit);
+      cuddRef(result);
+      Cudd_RecursiveDeref(mgr, nl1);
+      Cudd_RecursiveDeref(mgr, nl2);
+      cube = Cudd_LargestCube(mgr, result, &length);
+      cuddRef(cube);
+      sat_ExtractAssignmentFromBDD(head, mgr, satArr, cube);
+      Cudd_RecursiveDeref(mgr, cube);
+      Cudd_RecursiveDeref(mgr, result);
+    }
+    cm->assignByBDD = satArr;
+  }
+  sat_FreeLinearHead(head);
+
+  return(flag);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Free  satLinearHead_t structure.]
+
+  Description [Free  satLinearHead_t structure.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+sat_FreeLinearHead(satLinearHead_t *head)
+{
+satLinearElem_t *elem;
+satLinearVar_t *var;
+satArray_t *eArr, *vArr, *arr;
+satArray_t *support, *clauses;
+DdNode *bdd;
+int i;
+
+  eArr = head->elemArray;
+  if(eArr) {
+    for(i=0; i<eArr->num; i++) {
+      elem = (satLinearElem_t *)(eArr->space[i]);
+      support = elem->support;
+      if(support)
+	sat_ArrayFree(support);
+      if(elem->bdd)
+	Cudd_RecursiveDeref(head->mgr, elem->bdd);
+    }
+  }
+  vArr = head->varArray;
+  if(vArr) {
+    for(i=0; i<vArr->num; i++) {
+      var = (satLinearVar_t *)vArr->space[i];
+      clauses = var->clauses;
+      if(clauses)
+	sat_ArrayFree(clauses);
+      if(var->bdd)
+	Cudd_RecursiveDeref(head->mgr, var->bdd);
+    }
+  }
+
+  if(head->variablesArray)
+    sat_ArrayFree(head->variablesArray);
+  if(head->clausesArray)
+    sat_ArrayFree(head->clausesArray);
+
+  if(head->elemHead)
+    free(head->elemHead);
+  if(head->varHead)
+    free(head->varHead);
+  if(head->id2edge)
+    free(head->id2edge);
+  if(head->edge2id)
+    free(head->edge2id);
+  if(head->edge2vid)
+    free(head->edge2vid);
+
+  if(head->latestClusterArray)	{
+    arr = head->latestClusterArray;
+    for(i=0; i<arr->num; i++) {
+      bdd = (DdNode *)arr->space[i];
+      Cudd_RecursiveDeref(head->mgr, bdd);
+    }
+    sat_ArrayFree(arr);
+    head->latestClusterArray = 0;
+  }
+
+  if(head->deadArray)
+    free(head->deadArray);
+  free(head);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Variable comparing function for sorting.]
+
+  Description [Variable comparing function for sorting.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+linearVarCompare(
+  const void * node1,
+  const void * node2)
+{
+  satLinearVar_t *d1;
+  satLinearVar_t *d2;
+
+  d1 = *(satLinearVar_t **)(node1);
+  d2 = *(satLinearVar_t **)(node2);
+
+  return (d1->pos > d2->pos);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Element comparing function for sorting.]
+
+  Description [Element comparing function for sorting.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+linearElemCompare(
+  const void * node1,
+  const void * node2)
+{
+  satLinearElem_t *d1;
+  satLinearElem_t *d2;
+
+  d1 = *(satLinearElem_t **)(node1);
+  d2 = *(satLinearElem_t **)(node2);
+
+  return (d1->pos > d2->pos);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Generate linear arrangement by force relaxation.]
+
+  Description [Generate linear arrangement by force relaxation.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+sat_GetArrangementByForce(
+	satManager_t *cm,
+	satLinearHead_t *head)
+{
+int iteration;
+double prespan, span;
+int from, to, sum;
+int i, j, inverted;
+satLinearElem_t *elem;
+satLinearVar_t *var;
+satArray_t *eArr, *vArr;
+satArray_t *support, *clauses;
+
+  iteration = 0;
+  prespan = MAXINT;
+  eArr = head->elemArray;
+  vArr = head->varArray;
+  while(1) {
+    iteration++;
+    if(iteration > 200)	break;
+
+    span = 0;
+    for(i=0; i<eArr->num; i++) {
+      elem = (satLinearElem_t *)(eArr->space[i]);
+      support = elem->support;
+      sum = 0;
+      from = MAXINT;
+      to = -1;
+      for(j=0; j<support->num; j++) {
+	var = (satLinearVar_t *)(support->space[j]);
+	inverted = SATisInverted((unsigned long)var);
+	var = (satLinearVar_t *)SATnormalNode((unsigned long)var);
+	sum += var->order;
+	if(var->order < from)	from = var->order;
+	if(to < var->order)	to = var->order;
+      }
+      if(from != MAXINT && to != -1)
+	span += (double)(to - from);
+      elem->pos = sum / (double)(support->num);
+    }
+
+    if(iteration > 2 && (prespan * 0.9999) < span)
+      break;
+    prespan = span;
+
+    qsort(eArr->space, eArr->num, sizeof(satLinearElem_t *), linearElemCompare);
+    for(i=0; i<eArr->num; i++) {
+      elem = (satLinearElem_t *)eArr->space[i];
+      elem->order = i;
+    }
+
+    for(i=0; i<vArr->num; i++) {
+      var = (satLinearVar_t *)vArr->space[i];
+      clauses = var->clauses;
+      sum = 0;
+      for(j=0; j<clauses->num; j++) {
+	elem = (satLinearElem_t *)clauses->space[j];
+	sum += elem->order;
+      }
+      var->pos = sum / (double)(clauses->num);
+    }
+
+    qsort(vArr->space, vArr->num, sizeof(satLinearVar_t *), linearVarCompare);
+    for(i=0; i<vArr->num; i++) {
+      var = (satLinearVar_t *)vArr->space[i];
+      var->order = i;
+    }
+  }
+  if(cm->option->verbose > 3)
+    fprintf(cm->stdOut, "NOTICE : %d iteration for force based arrangement\n", iteration);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Print profile of cur from linear arrangement.]
+
+  Description [Print profile of cur from linear arrangement.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+sat_PrintCutProfile(
+	satManager_t *cm,
+	satLinearHead_t *head,
+	char *baseName,
+	int printFlag)
+{
+st_table *cutTable;
+st_generator *gen;
+FILE *fout = NIL(FILE);
+int i, j, cut, sum;
+int to, from;
+char filename[1024];
+satArray_t *support, *clauses, *eArr, *vArr;
+satLinearElem_t *elem;
+satLinearVar_t *var;
+double span;
+
+  eArr = head->elemArray;
+  span = 0;
+  for(i=0; i<eArr->num; i++) {
+    elem = (satLinearElem_t *)eArr->space[i];
+    support = elem->support;
+    sum = 0;
+    to = -1;
+    from = MAXINT;
+    for(j=0; j<support->num; j++) {
+      var = (satLinearVar_t *)support->space[j];
+      var = (satLinearVar_t *)SATnormalNode((unsigned long)var);
+      sum += var->order;
+      if(to < var->order)	to = var->order;
+      if(var->order < from)	from = var->order;
+    }
+    elem->to = to;
+    if(from != MAXINT && to != -1)
+      span += (double)(to - from);
+  }
+
+  cut = 0;
+  if(printFlag) {
+    sprintf(filename, "%s.data", baseName);
+    fout = fopen(filename, "w");
+  }
+  cutTable = st_init_table(st_ptrcmp, st_ptrhash);
+  vArr = head->varArray;
+  for(i=0; i<vArr->num; i++) {
+    var = (satLinearVar_t *)vArr->space[i];
+    clauses = var->clauses;
+    for(j=0; j<clauses->num; j++) {
+      elem = (satLinearElem_t *)clauses->space[j];
+      st_insert(cutTable, (char *)elem, (char *)elem);
+    }
+    st_foreach_item(cutTable, gen, &elem, &elem) {
+      if(elem->to <= i)
+	st_delete(cutTable, &elem, NIL(char *));
+    }
+    if(cut < cutTable->num_entries)
+      cut = cutTable->num_entries;
+    if(printFlag)
+      fprintf(fout, "%d %d\n", i, cutTable->num_entries);
+  }
+  st_free_table(cutTable);
+
+  if(printFlag) {
+    fclose(fout);
+    sprintf(filename, "%s.gnu", baseName);
+    fout = fopen(filename, "w");
+    fprintf(fout, "set terminal postscript \n");
+    fprintf(fout, "set output \"%s.ps\"\n", baseName);
+    fprintf(fout, "set title \"profile of live variable span %f cut %d\"\n",
+	    span, cut);
+    fprintf(fout, "plot \"%s.data\" using 1:2 title \"%s\" with lines\n", baseName, "cut");
+    fclose(fout);
+  }
+
+  return cut;
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Clustering on linear arrangement.]
+
+  Description [Clustering on linear arrangement.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+sat_ClusteringElementMain(
+	satManager_t *cm,
+	satLinearHead_t *head)
+{
+int modified;
+satLinearElem_t *elem;
+DdNode *one;
+
+  Cudd_AutodynEnable(head->mgr, CUDD_REORDER_SIFT);
+
+  sat_InitClusteringElement(cm, head);
+
+  while(1) {
+    sat_ComputeVariableRange(cm, head);
+    sat_ClusteringGetCandidate(cm, head);
+    modified = sat_ClusteringElement(cm, head);
+    if(modified == 0)	break;
+  }
+
+  if(head->elemArray->num == 1) {
+    one = DD_ONE(head->mgr);
+    elem = (satLinearElem_t *)(head->elemArray->space[0]);
+    if(elem->bdd == one)		return(SAT_BDD_SAT);
+    else if(elem->bdd == Cudd_Not(one))	return(SAT_BDD_UNSAT);
+    else				return(SAT_BDD_BACKTRACK);
+  }
+  else {
+    return(SAT_BDD_BACKTRACK);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Compute the range of variables.]
+
+  Description [Compute the range of variables.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+sat_ComputeVariableRange(
+	satManager_t *cm,
+	satLinearHead_t *head)
+{
+satArray_t *support, *vArr, *eArr;
+satLinearElem_t *elem;
+satLinearVar_t *var;
+int i, j;
+
+  vArr = head->varArray;
+  eArr = head->elemArray;
+
+  for(i=0; i<vArr->num; i++) {
+    var = (satLinearVar_t *)vArr->space[i];
+    var->from = MAXINT;
+    var->to = -1;
+  }
+
+  for(i=0; i<eArr->num; i++) {
+    elem = (satLinearElem_t *)eArr->space[i];
+    support = elem->support;
+    for(j=0; j<support->num; j++) {
+      var = (satLinearVar_t *)support->space[j];
+      var = (satLinearVar_t *)SATnormalNode((unsigned long)var);
+      if(elem->order < var->from)	var->from = elem->order;
+      if(var->to < elem->order)		var->to = elem->order;
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Preparation for the clutering.]
+
+  Description [Preparation for the clutering.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+sat_InitClusteringElement(
+	satManager_t *cm,
+	satLinearHead_t *head)
+{
+DdNode *sum, *nsum, *one;
+DdManager *mgr;
+satLinearElem_t *elem;
+satLinearVar_t *var;
+satArray_t *support, *vArr, *eArr;
+int i, j, index;
+long nv;
+int inverted;
+
+  mgr = head->mgr;
+  vArr = head->varArray;
+  eArr = head->elemArray;
+  index = 0;
+  one = DD_ONE(mgr);
+
+  for(i=0; i<vArr->num; i++) {
+    var = (satLinearVar_t *)vArr->space[i];
+    nv = var->node;
+    head->id2edge[index] = nv;
+    head->edge2id[SATnodeID(nv)] = index;
+    var->bdd = cuddUniqueInter(mgr,index,one,Cudd_Not(one));
+    cuddRef(var->bdd);
+    index++;
+  }
+
+  for(i=0; i<eArr->num; i++) {
+    elem = (satLinearElem_t *)eArr->space[i];
+    support = elem->support;
+    sum = Cudd_Not(one);
+    cuddRef(sum);
+    for(j=0; j<support->num; j++) {
+      var = (satLinearVar_t *)support->space[j];
+      inverted = SATisInverted((unsigned long)var);
+      var = (satLinearVar_t *)SATnormalNode((unsigned long)var);
+      nsum = Cudd_bddAnd(mgr,Cudd_Not(sum),
+			     (inverted ? var->bdd : Cudd_Not(var->bdd)));
+      nsum = Cudd_Not(nsum);
+      cuddRef(nsum);
+
+      Cudd_RecursiveDeref(mgr,sum);
+      sum = nsum;
+    }
+    elem->bdd = sum;
+  }
+}
+
+#endif
+#ifndef BDDcu
+/**Function********************************************************************
+
+  Synopsis    [Build monolithic BDD.]
+
+  Description [Try to build a monolithic BDD from the set of clauses.
+	       If it is succeeded then we can conclude whether given CNF is
+	       satisfiable of not.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_TryToBuildMonolithicBDD(satManager_t *cm)
+{
+  fprintf(stderr, "Warning : This feature is only availabe with CUDD package\n");
+  return;
+}
+#endif
Index: vis_dev/vis-2.3/src/sat/satConflict.c
===================================================================
--- vis_dev/vis-2.3/src/sat/satConflict.c	(revision 14)
+++ vis_dev/vis-2.3/src/sat/satConflict.c	(revision 14)
@@ -0,0 +1,2633 @@
+/**CFile***********************************************************************
+
+  FileName    [satConflict.c]
+
+  PackageName [sat]
+
+  Synopsis    [Routines for sat conflict analysism and unsat proof generation
+  for both CNF format and AIG format]
+
+  Author      [HoonSang Jin,  Bing Li]
+
+  Copyright [ This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+
+******************************************************************************/
+
+#include "satInt.h"
+#include "puresatInt.h"
+
+static char rcsid[] UNUSED = "$Id: satConflict.c,v 1.31 2009/04/11 18:26:37 fabio Exp $";
+
+static	satManager_t *SATcm;
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int levelCompare( const void * node1, const void * node2);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Conflict Analysis]
+
+  Description [ Conflict Analysis]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+int
+sat_ConflictAnalysis(
+	satManager_t *cm,
+	satLevel_t *d)
+{
+satStatistics_t *stats;
+satOption_t *option;
+satArray_t *clauseArray;
+int objectFlag;
+int bLevel;
+long fdaLit, conflicting;
+
+
+  conflicting = d->conflict;
+
+  if(d->level == 0) {
+      /** Bing : UNSAT core generation */
+    if(cm->option->coreGeneration)
+      sat_ConflictAnalysisForCoreGen(cm, d);
+    cm->currentDecision--;
+    return (-1);
+  }
+
+  stats = cm->each;
+  option = cm->option;
+
+
+  stats->nBacktracks++;
+
+  clauseArray = cm->auxArray;
+
+  bLevel = 0;
+  fdaLit = -1;
+  clauseArray->num = 0;
+
+  /*  Find Unique Implication Point */
+
+  if(option->RT)
+    sat_FindUIPWithRT(cm, clauseArray, d, &objectFlag, &bLevel, &fdaLit);
+  else
+    sat_FindUIP(cm, clauseArray, d, &objectFlag, &bLevel, &fdaLit);
+  stats->nNonchonologicalBacktracks += (d->level - bLevel);
+
+
+  if(clauseArray->num == 0) {
+    sat_PrintImplicationGraph(cm, d);
+    sat_PrintNode(cm, conflicting);
+  }
+
+  /* If we could find UIP then it is critical error...
+  * at lease the decision node has to be detected as UIP.
+  */
+  if(fdaLit == -1) {
+    fprintf(cm->stdOut, "%s ERROR : Illegal unit literal\n", cm->comment);
+    fflush(cm->stdOut);
+    sat_PrintNode(cm, conflicting);
+    sat_PrintImplicationGraph(cm, d);
+    sat_PrintDotForConflict(cm, d, conflicting, 0);
+    exit(0);
+  }
+
+  if(bLevel && cm->lowestBacktrackLevel > bLevel)
+    cm->lowestBacktrackLevel = bLevel;
+
+  bLevel = sat_AddConflictClauseAndBacktrack(
+	  cm, clauseArray, d, fdaLit, bLevel, objectFlag, 0);
+
+  return(bLevel);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Conflict Analysis for lifting instance]
+
+  Description [ Conflict Analysis for lifting instance]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+int
+sat_ConflictAnalysisForLifting(
+	satManager_t *cm,
+	satLevel_t *d)
+{
+satStatistics_t *stats;
+satOption_t *option;
+satArray_t *clauseArray;
+int objectFlag;
+int bLevel;
+long fdaLit, conflicting;
+
+
+  conflicting = d->conflict;
+
+  if(d->level == 0) {
+    cm->currentDecision--;
+    return (-1);
+  }
+
+  stats = cm->each;
+  option = cm->option;
+
+
+  stats->nBacktracks++;
+
+  clauseArray = cm->auxArray;
+
+  bLevel = 0;
+  fdaLit = -1;
+  clauseArray->num = 0;
+
+  /*  Find Unique Implication Point */
+  sat_FindUIP(cm, clauseArray, d, &objectFlag, &bLevel, &fdaLit);
+  stats->nNonchonologicalBacktracks += (d->level - bLevel);
+
+
+  if(clauseArray->num == 0) {
+    sat_PrintImplicationGraph(cm, d);
+    sat_PrintNode(cm, conflicting);
+  }
+
+  /* If we could find UIP then it is critical error...
+  * at lease the decision node has to be detected as UIP.
+  */
+  if(fdaLit == -1) {
+    fprintf(cm->stdOut, "%s ERROR : Illegal unit literal\n", cm->comment);
+    fflush(cm->stdOut);
+    sat_PrintNode(cm, conflicting);
+    sat_PrintImplicationGraph(cm, d);
+    sat_PrintDotForConflict(cm, d, conflicting, 0);
+    exit(0);
+  }
+
+  if(bLevel && cm->lowestBacktrackLevel > bLevel)
+    cm->lowestBacktrackLevel = bLevel;
+
+  bLevel = sat_AddConflictClauseAndBacktrackForLifting(
+	  cm, clauseArray, d, fdaLit, bLevel, objectFlag, 0);
+
+  return(bLevel);
+}
+/**Function********************************************************************
+
+  Synopsis    [ Conflict Analysis on blocking clause]
+
+  Description [ Conflict Analysis on blocking clause]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+int
+sat_ConflictAnalysisWithBlockingClause(
+	satManager_t *cm,
+	satLevel_t *d)
+{
+satStatistics_t *stats;
+satOption_t *option;
+satArray_t *clauseArray;
+int objectFlag;
+int bLevel;
+long fdaLit, conflicting;
+
+
+  conflicting = d->conflict;
+
+  if(d->level == 0) {
+    cm->currentDecision--;
+    return (-1);
+  }
+
+  stats = cm->each;
+  option = cm->option;
+
+
+  stats->nBacktracks++;
+
+  clauseArray = cm->auxArray;
+
+  bLevel = 0;
+  fdaLit = -1;
+  clauseArray->num = 0;
+
+  /*  Find Unique Implication Point */
+  sat_FindUIP(cm, clauseArray, d, &objectFlag, &bLevel, &fdaLit);
+  stats->nNonchonologicalBacktracks += (d->level - bLevel);
+
+
+  if(clauseArray->num == 0) {
+    sat_PrintImplicationGraph(cm, d);
+    sat_PrintNode(cm, conflicting);
+  }
+
+  /* If we could find UIP then it is critical error...
+  * at lease the decision node has to be detected as UIP.
+  */
+  if(fdaLit == -1) {
+    fprintf(cm->stdOut, "%s ERROR : Illegal unit literal\n", cm->comment);
+    fflush(cm->stdOut);
+    sat_PrintNode(cm, conflicting);
+    sat_PrintImplicationGraph(cm, d);
+    sat_PrintDotForConflict(cm, d, conflicting, 0);
+    exit(0);
+  }
+
+  if(bLevel && cm->lowestBacktrackLevel > bLevel)
+    cm->lowestBacktrackLevel = bLevel;
+
+  bLevel = sat_AddConflictClauseWithNoScoreAndBacktrack(
+	  cm, clauseArray, d, fdaLit, bLevel, objectFlag, 0);
+
+  return(bLevel);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Strong Conflict Analysis.]
+
+  Description [ Strong Conflict Analysis.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_StrongConflictAnalysis(
+	satManager_t *cm,
+	satLevel_t *d)
+{
+satStatistics_t *stats;
+satOption_t *option;
+satArray_t *clauseArray;
+int objectFlag;
+int bLevel;
+long fdaLit, conflicting;
+
+
+  conflicting = d->conflict;
+
+  if(d->level == 0) {
+      /** Bing : UNSAT core generation */
+    if(cm->option->coreGeneration)
+      sat_ConflictAnalysisForCoreGen(cm, d);
+    cm->currentDecision--;
+    return (-1);
+  }
+
+  stats = cm->each;
+  option = cm->option;
+
+
+  stats->nBacktracks++;
+
+  if(SATflags(conflicting) & IsCNFMask) {
+    SATnumConflict(conflicting) += 1;
+  }
+
+  clauseArray = cm->auxArray;
+
+  bLevel = 0;
+  fdaLit = -1;
+  clauseArray->num = 0;
+
+  /*  Find Unique Implication Point */
+  sat_FindUIPAndNonUIP(cm, clauseArray, d, &objectFlag, &bLevel, &fdaLit);
+  stats->nNonchonologicalBacktracks += (d->level - bLevel);
+
+
+  if(clauseArray->num == 0) {
+    sat_PrintImplicationGraph(cm, d);
+    sat_PrintNode(cm, conflicting);
+  }
+
+  /* If we could find UIP then it is critical error...
+  * at lease the decision node has to be detected as UIP.
+  */
+  if(fdaLit == -1) {
+    fprintf(cm->stdOut, "%s ERROR : Illegal unit literal\n", cm->comment);
+    fflush(cm->stdOut);
+    sat_PrintNode(cm, conflicting);
+    sat_PrintImplicationGraph(cm, d);
+    sat_PrintDotForConflict(cm, d, conflicting, 0);
+    exit(0);
+  }
+
+  if(bLevel && cm->lowestBacktrackLevel > bLevel)
+    cm->lowestBacktrackLevel = bLevel;
+
+  bLevel = sat_AddConflictClauseAndBacktrack(
+	  cm, clauseArray, d, fdaLit, bLevel, objectFlag, 1);
+
+  return(bLevel);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Add conflict clause and backtrack.]
+
+  Description [ Add conflict clause and backtrack.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_AddConflictClauseAndBacktrack(
+	satManager_t *cm,
+	satArray_t *clauseArray,
+	satLevel_t *d,
+	long fdaLit,
+	int bLevel,
+	int objectFlag,
+	int strongFlag)
+{
+int inverted;
+long conflicting, learned;
+satOption_t *option;
+satStatistics_t *stats;
+satArray_t *nClauseArray;
+
+ RTManager_t * rm = cm->rm;
+
+  option = cm->option;
+  stats = cm->each;
+
+  inverted = SATisInverted(fdaLit);
+  fdaLit = SATnormalNode(fdaLit);
+
+  conflicting = d->conflict;
+
+  if(option->verbose > 2) {
+    if(option->verbose > 4)
+      sat_PrintNode(cm, conflicting);
+    fprintf(cm->stdOut, "conflict at %3d on %6ld  bLevel %d UnitLit ",
+	    d->level, conflicting, bLevel);
+    sat_PrintNodeAlone(cm, fdaLit);
+    fprintf(cm->stdOut, "\n");
+  }
+
+  d->conflict = 0;
+
+  /* unit literal conflict clause */
+  if(clauseArray->num == 1) {
+    learned = sat_AddUnitConflictClause(cm, clauseArray, objectFlag);
+    stats->nUnitConflictCl++;
+    cm->currentTopConflict = cm->literals->last-1;
+    cm->currentTopConflictCount = 0;
+
+    sat_Backtrack(cm, 0);
+
+    if(SATlevel(fdaLit) == 0) {
+      if(cm->option->coreGeneration){
+	if(cm->option->RT){
+	  st_insert(cm->anteTable,(char*)SATnormalNode(fdaLit),(char*)learned);
+
+	  st_insert(cm->RTreeTable, (char *)learned, (char *)rm->root);
+	  RT_oriClsIdx(rm->root) = learned;
+	}
+	else{
+	  st_insert(cm->anteTable,(char*)SATnormalNode(fdaLit),(char*)learned);
+	  st_insert(cm->dependenceTable, (char *)learned, (char *)cm->dependenceArray);
+	}
+      }
+      cm->currentDecision = -1;
+      return (-1);
+    }
+
+    d = SATgetDecision(cm->currentDecision);
+    cm->implicatedSoFar -= d->implied->num;
+    SATante(fdaLit) = 0;
+
+    SATvalue(fdaLit) = inverted;
+    SATmakeImplied(fdaLit, d);
+
+    if((SATflags(fdaLit) & InQueueMask)  == 0) {
+      sat_Enqueue(cm->queue, fdaLit);
+      SATflags(fdaLit) |= InQueueMask;
+    }
+
+    clauseArray->num = 0;
+
+    if(option->incTraceObjective && objectFlag == 0)
+      sat_ArrayInsert(cm->nonobjUnitLitArray, SATnot(fdaLit));
+
+    if(option->incDistill && objectFlag)
+      sat_ArrayInsert(cm->objUnitLitArray, SATnot(fdaLit));
+
+    if(objectFlag)
+      SATflags(fdaLit) |= ObjMask;
+
+    /* Bing: UNSAT core generation */
+    if(cm->option->coreGeneration){
+      if(cm->option->RT){
+	st_insert(cm->anteTable,(char*)SATnormalNode(fdaLit),(char*)learned);
+
+	st_insert(cm->RTreeTable, (char *)learned, (char *)rm->root);
+	RT_oriClsIdx(rm->root) = learned;
+	 }
+      else{
+	st_insert(cm->anteTable,(char*)SATnormalNode(fdaLit),(char*)learned);
+	st_insert(cm->dependenceTable, (char *)learned, (char *)cm->dependenceArray);
+      }
+    }
+    return(bLevel);
+  }
+
+  if(strongFlag && (SATnumConflict(conflicting) % 5) == 0 &&
+	  clauseArray->num > 4) {
+    nClauseArray = sat_ArrayAlloc(clauseArray->num);
+    memcpy(nClauseArray->space, clauseArray->space, sizeof(long)*clauseArray->num);
+    nClauseArray->num = clauseArray->num;
+    clauseArray->num = 0;
+    bLevel = sat_ConflictAnalysisUsingAuxImplication(cm, nClauseArray);
+    sat_ArrayFree(nClauseArray);
+  }
+  else {
+    /* add conflict learned clause */
+    learned = sat_AddConflictClause(cm, clauseArray, objectFlag);
+    cm->currentTopConflict = cm->literals->last-1;
+    cm->currentTopConflictCount = 0;
+
+     /* Bing: UNSAT core generation */
+    if(cm->option->coreGeneration){
+
+      if(cm->option->RT){
+	st_insert(cm->RTreeTable, (char *)learned, (char *)rm->root);
+	RT_oriClsIdx(rm->root) = learned;
+	}
+      else{
+	st_insert(cm->dependenceTable, (char *)learned, (char *)cm->dependenceArray);
+      }
+    }
+
+    if(option->verbose > 2) {
+      sat_PrintNode(cm, learned);
+      fflush(cm->stdOut);
+    }
+
+
+    /* apply Deepest Variable Hike decision heuristic */
+    if(option->decisionHeuristic & DVH_DECISION)
+      sat_UpdateDVH(cm, d, clauseArray, bLevel, fdaLit);
+
+    /* Backtrack and failure driven assertion */
+    sat_Backtrack(cm, bLevel);
+
+    d = SATgetDecision(bLevel);
+    cm->implicatedSoFar -= d->implied->num;
+
+    SATante(fdaLit) = learned;
+    SATvalue(fdaLit) = inverted;
+    SATmakeImplied(fdaLit, d);
+
+    if((SATflags(fdaLit) & InQueueMask)  == 0) {
+      sat_Enqueue(cm->queue, fdaLit);
+      SATflags(fdaLit) |= InQueueMask;
+    }
+
+    clauseArray->num = 0;
+    if(objectFlag)
+      SATflags(fdaLit) |= ObjMask;
+
+  }
+
+  return(bLevel);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Add conflict clause and backtrack.]
+
+  Description [ Add conflict clause and backtrack.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_AddConflictClauseAndBacktrackForLifting(
+	satManager_t *cm,
+	satArray_t *clauseArray,
+	satLevel_t *d,
+	long fdaLit,
+	int bLevel,
+	int objectFlag,
+	int strongFlag)
+{
+int inverted;
+long conflicting, learned;
+satOption_t *option;
+satStatistics_t *stats;
+satArray_t *nClauseArray;
+
+  option = cm->option;
+  stats = cm->each;
+
+  inverted = SATisInverted(fdaLit);
+  fdaLit = SATnormalNode(fdaLit);
+
+  conflicting = d->conflict;
+
+  if(option->verbose > 2) {
+    if(option->verbose > 4)
+      sat_PrintNode(cm, conflicting);
+    fprintf(cm->stdOut, "conflict at %3d on %6ld  bLevel %d UnitLit ",
+	    d->level, conflicting, bLevel);
+    sat_PrintNodeAlone(cm, fdaLit);
+    fprintf(cm->stdOut, "\n");
+  }
+
+  d->conflict = 0;
+
+  /* unit literal conflict clause */
+  if(clauseArray->num == 1) {
+    learned = sat_AddUnitConflictClause(cm, clauseArray, objectFlag);
+    stats->nUnitConflictCl++;
+    cm->currentTopConflict = cm->literals->last-1;
+    cm->currentTopConflictCount = 0;
+
+    sat_Backtrack(cm, 0);
+
+    if(SATlevel(fdaLit) == 0) {
+      if(cm->option->coreGeneration){
+	st_insert(cm->anteTable,(char*)SATnormalNode(fdaLit),(char*)learned);
+	st_insert(cm->dependenceTable, (char *)learned, (char *)cm->dependenceArray);
+      }
+      cm->currentDecision = -1;
+      return (-1);
+    }
+
+    d = SATgetDecision(cm->currentDecision);
+    cm->implicatedSoFar -= d->implied->num;
+    SATante(fdaLit) = 0;
+
+    SATvalue(fdaLit) = inverted;
+    SATmakeImplied(fdaLit, d);
+
+    if((SATflags(fdaLit) & InQueueMask)  == 0) {
+      sat_Enqueue(cm->queue, fdaLit);
+      SATflags(fdaLit) |= InQueueMask;
+    }
+
+    clauseArray->num = 0;
+
+    if(option->incTraceObjective && objectFlag == 0)
+      sat_ArrayInsert(cm->nonobjUnitLitArray, SATnot(fdaLit));
+
+    if(option->incDistill && objectFlag)
+      sat_ArrayInsert(cm->objUnitLitArray, SATnot(fdaLit));
+
+    if(objectFlag)
+      SATflags(fdaLit) |= ObjMask;
+
+    /* Bing: UNSAT core generation */
+    if(cm->option->coreGeneration){
+      st_insert(cm->anteTable,(char*)SATnormalNode(fdaLit),(char*)learned);
+      st_insert(cm->dependenceTable, (char *)learned, (char *)cm->dependenceArray);
+    }
+    return(0);
+  }
+
+  if(strongFlag && (SATnumConflict(conflicting) % 5) == 0 &&
+	  clauseArray->num > 4) {
+    nClauseArray = sat_ArrayAlloc(clauseArray->num);
+    memcpy(nClauseArray->space, clauseArray->space, sizeof(long)*clauseArray->num);
+    nClauseArray->num = clauseArray->num;
+    clauseArray->num = 0;
+    bLevel = sat_ConflictAnalysisUsingAuxImplication(cm, nClauseArray);
+    sat_ArrayFree(nClauseArray);
+  }
+  else {
+    /* add conflict learned clause */
+    learned = sat_AddConflictClause(cm, clauseArray, objectFlag);
+    cm->currentTopConflict = cm->literals->last-1;
+    cm->currentTopConflictCount = 0;
+
+     /* Bing: UNSAT core generation */
+    if(cm->option->coreGeneration){
+      st_insert(cm->dependenceTable, (char *)learned, (char *)cm->dependenceArray);
+    }
+
+    if(option->verbose > 2) {
+      sat_PrintNode(cm, learned);
+      fflush(cm->stdOut);
+    }
+
+
+    /* apply Deepest Variable Hike decision heuristic */
+    /**
+    if(option->decisionHeuristic & DVH_DECISION)
+      sat_UpdateDVH(cm, d, clauseArray, bLevel, fdaLit);
+      **/
+
+    /* Backtrack and failure driven assertion */
+    sat_Backtrack(cm, bLevel);
+
+    d = SATgetDecision(bLevel);
+    cm->implicatedSoFar -= d->implied->num;
+
+    SATante(fdaLit) = learned;
+    SATvalue(fdaLit) = inverted;
+    SATmakeImplied(fdaLit, d);
+
+    if((SATflags(fdaLit) & InQueueMask)  == 0) {
+      sat_Enqueue(cm->queue, fdaLit);
+      SATflags(fdaLit) |= InQueueMask;
+    }
+
+    clauseArray->num = 0;
+    if(objectFlag)
+      SATflags(fdaLit) |= ObjMask;
+
+  }
+
+  return(bLevel);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Add conflict clause with no score update and backtrack.]
+
+  Description [ Add conflict clause with no score update and backtrack.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_AddConflictClauseWithNoScoreAndBacktrack(
+	satManager_t *cm,
+	satArray_t *clauseArray,
+	satLevel_t *d,
+	long fdaLit,
+	int bLevel,
+	int objectFlag,
+	int strongFlag)
+{
+int inverted;
+long conflicting, learned;
+satOption_t *option;
+satStatistics_t *stats;
+satArray_t *nClauseArray;
+
+  option = cm->option;
+  stats = cm->each;
+
+  inverted = SATisInverted(fdaLit);
+  fdaLit = SATnormalNode(fdaLit);
+
+  conflicting = d->conflict;
+
+  if(option->verbose > 2) {
+    if(option->verbose > 4)
+      sat_PrintNode(cm, conflicting);
+    fprintf(cm->stdOut, "conflict at %3d on %6ld  bLevel %d UnitLit ",
+	    d->level, conflicting, bLevel);
+    sat_PrintNodeAlone(cm, fdaLit);
+    fprintf(cm->stdOut, "\n");
+  }
+
+  d->conflict = 0;
+
+  /* unit literal conflict clause */
+  if(clauseArray->num == 1) {
+    learned = sat_AddUnitConflictClause(cm, clauseArray, objectFlag);
+    stats->nUnitConflictCl++;
+    cm->currentTopConflict = cm->literals->last-1;
+    cm->currentTopConflictCount = 0;
+
+    sat_Backtrack(cm, 0);
+
+    if(SATlevel(fdaLit) == 0) {
+      if(cm->option->coreGeneration){
+	st_insert(cm->anteTable,(char*)SATnormalNode(fdaLit),(char*)learned);
+	st_insert(cm->dependenceTable, (char *)learned, (char *)cm->dependenceArray);
+      }
+      cm->currentDecision = -1;
+      return (-1);
+    }
+
+    d = SATgetDecision(cm->currentDecision);
+    cm->implicatedSoFar -= d->implied->num;
+    SATante(fdaLit) = 0;
+
+    SATvalue(fdaLit) = inverted;
+    SATmakeImplied(fdaLit, d);
+
+    if((SATflags(fdaLit) & InQueueMask)  == 0) {
+      sat_Enqueue(cm->queue, fdaLit);
+      SATflags(fdaLit) |= InQueueMask;
+    }
+
+    clauseArray->num = 0;
+
+    if(option->incTraceObjective && objectFlag == 0)
+      sat_ArrayInsert(cm->nonobjUnitLitArray, SATnot(fdaLit));
+
+    if(option->incDistill && objectFlag)
+      sat_ArrayInsert(cm->objUnitLitArray, SATnot(fdaLit));
+
+    if(objectFlag)
+      SATflags(fdaLit) |= ObjMask;
+
+    /* Bing: UNSAT core generation */
+    if(cm->option->coreGeneration){
+      st_insert(cm->anteTable,(char*)SATnormalNode(fdaLit),(char*)learned);
+      st_insert(cm->dependenceTable, (char *)learned, (char *)cm->dependenceArray);
+    }
+    return(bLevel);
+  }
+
+  if(strongFlag && (SATnumConflict(conflicting) % 5) == 0 &&
+	  clauseArray->num > 4) {
+    nClauseArray = sat_ArrayAlloc(clauseArray->num);
+    memcpy(nClauseArray->space, clauseArray->space, sizeof(long)*clauseArray->num);
+    nClauseArray->num = clauseArray->num;
+    clauseArray->num = 0;
+    bLevel = sat_ConflictAnalysisUsingAuxImplication(cm, nClauseArray);
+    sat_ArrayFree(nClauseArray);
+  }
+  else {
+    /* add conflict learned clause */
+    learned = sat_AddConflictClauseNoScoreUpdate(cm, clauseArray, objectFlag);
+    cm->currentTopConflict = cm->literals->last-1;
+    cm->currentTopConflictCount = 0;
+
+     /* Bing: UNSAT core generation */
+    if(cm->option->coreGeneration){
+      st_insert(cm->dependenceTable, (char *)learned, (char *)cm->dependenceArray);
+    }
+
+    if(option->verbose > 2) {
+      sat_PrintNode(cm, learned);
+      fflush(cm->stdOut);
+    }
+
+
+    /* apply Deepest Variable Hike decision heuristic */
+    if(option->decisionHeuristic & DVH_DECISION)
+      sat_UpdateDVH(cm, d, clauseArray, bLevel, fdaLit);
+
+    /* Backtrack and failure driven assertion */
+    sat_Backtrack(cm, bLevel);
+
+    d = SATgetDecision(bLevel);
+    cm->implicatedSoFar -= d->implied->num;
+
+    SATante(fdaLit) = learned;
+    SATvalue(fdaLit) = inverted;
+    SATmakeImplied(fdaLit, d);
+
+    if((SATflags(fdaLit) & InQueueMask)  == 0) {
+      sat_Enqueue(cm->queue, fdaLit);
+      SATflags(fdaLit) |= InQueueMask;
+    }
+
+    clauseArray->num = 0;
+    if(objectFlag)
+      SATflags(fdaLit) |= ObjMask;
+
+  }
+
+  return(bLevel);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Minimize conflict clause by rebuilding implication graph.]
+
+  Description [ Minimize conflict clause by rebuilding implication graph.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_ConflictAnalysisUsingAuxImplication(
+	satManager_t *cm,
+	satArray_t *clauseArray)
+{
+int tLevel, level, bLevel;
+int i, size;
+int value, tvalue;
+int minConflict, maxConflict;
+long v, tv, conflicting;
+satLevel_t *d;
+satArray_t *nClauseArray;
+double aMean, hMean, gMean;
+int objectFlag;
+long fdaLit;
+
+  SATcm = cm;
+  qsort(clauseArray->space, clauseArray->num, sizeof(int), levelCompare);
+  tLevel = cm->currentDecision;
+
+  tv = clauseArray->space[0];
+  v = SATnormalNode(tv);
+  level = SATlevel(v);
+  minConflict = cm->decisionHead[level].nConflict;
+  tv = clauseArray->space[clauseArray->num-1];
+  v = SATnormalNode(tv);
+  level = SATlevel(v);
+  maxConflict = cm->decisionHead[level].nConflict;
+
+  aMean = hMean = 0;
+
+  for(i=0; i<clauseArray->num; i++) {
+    tv = clauseArray->space[i];
+    v = SATnormalNode(tv);
+    level = SATlevel(v);
+    if(level < tLevel) tLevel = level;
+    aMean = aMean + (double)level;
+    hMean = hMean + 1.0/(double)level;
+  }
+  aMean = aMean/(double)clauseArray->num;
+  hMean = (double)clauseArray->num/hMean;
+  gMean = sqrt(aMean*hMean);
+
+  sat_Backtrack(cm, tLevel-1);
+
+  size = clauseArray->num;
+
+  for(i=0; i<size; i++) {
+    tv = clauseArray->space[i];
+    value = !SATisInverted(tv);
+    v = SATnormalNode(tv);
+    tvalue = SATvalue(v);
+
+    if(tvalue != 2)	{
+	/**
+      if(tvalue != value) {
+	fprintf(stdout, "ERROR : Inconsitent value is implied\n");
+	sat_ReportStatistics(cm, cm->each);
+      }
+      **/
+      continue;
+    }
+    d = sat_AllocLevel(cm);
+
+    SATvalue(v) = value;
+    SATmakeImplied(v, d);
+    d->decisionNode = v;
+    d->nConflict = cm->each->nConflictCl;
+    if((SATflags(v) & InQueueMask) == 0) {
+      sat_Enqueue(cm->queue, v);
+      SATflags(v) |= InQueueMask;
+    }
+    sat_ImplicationMain(cm, d);
+
+    if(d->conflict) {
+      conflicting = d->conflict;
+      break;
+    }
+  }
+
+  if(d->conflict) {
+    nClauseArray = cm->auxArray;
+    bLevel = 0;
+    fdaLit = -1;
+    nClauseArray->num = 0;
+    sat_FindUIP(cm, nClauseArray, d, &objectFlag, &bLevel, &fdaLit);
+
+    /**
+    fprintf(stdout, "tLevel %d gLevel %.1lf  %ld -> %ld min %d max %d\n",
+	    tLevel, gMean, clauseArray->num, nClauseArray->num,
+	    minConflict, maxConflict);
+	    **/
+
+    bLevel = sat_AddConflictClauseAndBacktrack(
+	    cm, nClauseArray, d, fdaLit, bLevel, objectFlag, 0);
+
+
+  }
+  else {
+    bLevel = cm->currentDecision;
+  }
+  return(bLevel);
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Conflict Analysis that is used for UNSAT core generation.]
+
+  Description [ Conflict Analysis that is used for UNSAT core generation.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_ConflictAnalysisForCoreGen(
+	satManager_t *cm,
+	satLevel_t *d)
+{
+satStatistics_t *stats;
+satOption_t *option;
+satArray_t *clauseArray;
+int objectFlag;
+int bLevel;
+long fdaLit, learned, conflicting;
+int inverted;
+
+RTManager_t * rm = cm->rm;
+
+  if(d->level != 0) {
+    fprintf(stdout, "ERROR : Can't use this function at higher than level 0\n");
+    return(0);
+  }
+
+  conflicting = d->conflict;
+
+  stats = cm->each;
+  option = cm->option;
+
+  stats->nBacktracks++;
+
+  clauseArray = cm->auxArray;
+
+  bLevel = 0;
+  fdaLit = -1;
+  clauseArray->num = 0;
+
+  /* Find Unique Implication Point */
+
+  if(option->RT)
+    sat_FindUIPForCoreGenWithRT(cm, clauseArray, d, &objectFlag, &bLevel,&fdaLit);
+  else
+    sat_FindUIPForCoreGen(cm, clauseArray, d, &objectFlag, &bLevel, &fdaLit);
+
+  if(fdaLit < 0 )
+    fprintf(stdout, "ERROR : critical\n");
+
+  inverted = SATisInverted(fdaLit);
+  fdaLit = SATnormalNode(fdaLit);
+
+  d->conflict = 0;
+
+  assert(clauseArray->num == 1);
+  learned = sat_AddUnitConflictClause(cm, clauseArray, objectFlag);
+
+  SATante(fdaLit) = 0;
+
+  clauseArray->num = 0;
+
+  /* Bing: UNSAT core generation */
+  if(cm->option->coreGeneration){
+    st_insert(cm->anteTable,(char*)(long)SATnormalNode(fdaLit),(char*)(long)learned);
+    if(option->RT){
+      st_insert(cm->RTreeTable, (char *)learned, (char *)rm->root);
+      RT_oriClsIdx(rm->root) = learned;
+    }
+    else
+      st_insert(cm->dependenceTable, (char *)(long)learned, (char *)(long)cm->dependenceArray);
+  }
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Find Unique implication point]
+
+  Description [ After finding unique implication point, the backtrack level
+		and failure driven assertion are identified. ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_FindUIP(
+	satManager_t *cm,
+	satArray_t *clauseArray,
+	satLevel_t *d,
+	int *objectFlag,
+	int *bLevel,
+	long *fdaLit)
+{
+long conflicting;
+int nMarked, value;
+int first, i;
+long *space, v;
+satArray_t *implied;
+satOption_t *option;
+
+  conflicting = d->conflict;
+  nMarked = 0;
+  option = cm->option;
+  if(option->incTraceObjective) *objectFlag = 0;
+  else                          *objectFlag = ObjMask;
+
+  (*objectFlag) |= (SATflags(conflicting) & ObjMask);
+
+  /* find seed from conflicting clause to find unique implication point.
+   * */
+  clauseArray->num = 0;
+
+  if(SATflags(conflicting) & IsCNFMask)
+    SATconflictUsage(conflicting)++;
+
+  sat_MarkNodeInConflict(
+	  cm, d, &nMarked, objectFlag, bLevel, clauseArray);
+
+  /* Traverse implication graph backward */
+  first = 1;
+  implied = d->implied;
+  space = implied->space+implied->num-1;
+  /* Bing:  UNSAT core generation */
+  if(cm->option->coreGeneration){
+    cm->dependenceArray = sat_ArrayAlloc(1);
+    sat_ArrayInsert(cm->dependenceArray,conflicting);
+  }
+
+  for(i=implied->num-1; i>=0; i--, space--) {
+    v = *space;
+    if(SATflags(v) & VisitedMask) {
+      SATflags(v) &= ResetVisitedMask;
+      --nMarked;
+
+      if(nMarked == 0 && (!first || i==0))  {
+	value = SATvalue(v);
+	*fdaLit = v^(!value);
+	sat_ArrayInsert(clauseArray, *fdaLit);
+	break;
+      }
+
+      /* Bing: UNSAT core genration */
+      if(cm->option->coreGeneration){
+	int ante = SATante(v);
+	if(ante!=0 && !(SATflags(ante) & IsCNFMask)){
+	  printf("node %d is not CNF\n", ante);
+	  exit(0);
+	}
+	if(ante==0){
+	  if(!st_lookup(cm->anteTable, (char *)SATnormalNode(v), &ante)){
+	    printf("ante = 0 and is not in anteTable %ld\n",v);
+	    exit(0);
+	  }
+	}
+	sat_ArrayInsert(cm->dependenceArray,ante);
+      }
+
+      sat_MarkNodeInImpliedNode(
+	      cm, d, v, &nMarked, objectFlag, bLevel, clauseArray);
+    }
+    first = 0;
+  }
+
+
+  /* Minimize conflict clause */
+  if(option->minimizeConflictClause)
+    sat_MinimizeConflictClause(cm, clauseArray);
+  else
+    sat_ResetFlagForClauseArray(cm, clauseArray);
+
+  return;
+}
+/**Function********************************************************************
+
+  Synopsis    [find UIP with resolution generation]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+void
+sat_FindUIPWithRT(
+	satManager_t *cm,
+	satArray_t *clauseArray,
+	satLevel_t *d,
+	int *objectFlag,
+	int *bLevel,
+	long *fdaLit)
+{
+long conflicting;
+int nMarked, value;
+int first, i,j;
+long *space, v,left,right,inverted,result,*tmp;
+satArray_t *implied;
+satOption_t *option;
+RTnode_t  tmprt;
+int size = 0;
+long *lp,*tmpIP,ante,ante2,node;
+ RTManager_t * rm = cm->rm;
+
+  conflicting = d->conflict;
+  nMarked = 0;
+  option = cm->option;
+  if(option->incTraceObjective) *objectFlag = 0;
+  else                          *objectFlag = ObjMask;
+
+  (*objectFlag) |= (SATflags(conflicting) & ObjMask);
+
+  /* find seed from conflicting clause to find unique implication point.
+   * */
+  clauseArray->num = 0;
+  sat_MarkNodeInConflict(
+	  cm, d, &nMarked, objectFlag, bLevel, clauseArray);
+
+  /* Traverse implication graph backward */
+  first = 1;
+  implied = d->implied;
+  space = implied->space+implied->num-1;
+
+
+  if(cm->option->coreGeneration){
+    /*if last conflict is CNF*/
+    if(SATflags(conflicting)&IsCNFMask){
+      /*is conflict CNF*/
+      if(SATflags(conflicting)&IsConflictMask){
+	 if(!st_lookup(cm->RTreeTable,(char*)conflicting,&tmprt)){
+	    printf("RTree node of conflict cnf %ld is not in RTreeTable\n",ante);
+	    exit(0);
+	  }
+	  else{
+	    rm->root = tmprt;
+#if PR
+	    printf("Get formula for CONFLICT CLAUSE:%d\n",ante);
+#endif
+	  }
+      }
+      /*CNF but not conflict*/
+      else{
+	rm->root = RTCreateNode(rm);
+
+	size = SATnumLits(conflicting);
+	RT_fSize(rm->root) = size;
+	lp = (long*)SATfirstLit(conflicting);
+	sat_BuildRT(cm,rm->root, lp, tmpIP,size,0);
+      }
+    }
+    /*if last conflict is AIG*/
+    else{
+      rm->root = RTCreateNode(rm);
+      node = SATnormalNode(conflicting);
+      left = SATleftChild(node);
+      right = SATrightChild(node);
+      result = PureSat_IdentifyConflict(cm,left,right,conflicting);
+      inverted = SATisInverted(left);
+      left = SATnormalNode(left);
+      left = inverted ? SATnot(left) : left;
+
+      inverted = SATisInverted(right);
+      right = SATnormalNode(right);
+      right = inverted ? SATnot(right) : right;
+
+      j = node;
+
+      if(result == 1){
+	tmp = ALLOC(long,3);
+	tmp[0] = left;
+	tmp[1] = SATnot(j);
+	size = 2;
+      }
+      else if(result == 2){
+	tmp = ALLOC(long,3);
+	tmp[0] = right;
+	tmp[1] = SATnot(j);
+	size = 2;
+      }
+      else if(result == 3){
+	tmp = ALLOC(long,4);
+	tmp[0] = SATnot(left);
+	tmp[1] = SATnot(right);
+	tmp[2] = j;
+	size = 3;
+      }
+      else{
+	printf("wrong returned result value, exit\n");
+	exit(0);
+      }
+
+      lp = tmp;
+      sat_BuildRT(cm,rm->root, lp, tmpIP,size,1);
+      FREE(tmp);
+    }
+  }
+
+
+  for(i=implied->num-1; i>=0; i--, space--) {
+    v = *space;
+    if(SATflags(v) & VisitedMask) {
+      SATflags(v) &= ResetVisitedMask;
+      --nMarked;
+
+      if(nMarked == 0 && (!first || i==0))  {
+	value = SATvalue(v);
+	*fdaLit = v^(!value);
+	sat_ArrayInsert(clauseArray, *fdaLit);
+	break;
+      }
+
+
+      if(cm->option->coreGeneration){
+	ante = SATante(v);
+	if(ante==0){
+	  if(!(st_lookup(cm->anteTable, (char *)SATnormalNode(v),&ante))){
+	    printf("ante = 0 and is not in anteTable %ld\n",v);
+	    exit(0);
+	  }
+	}
+
+	/*build non-leaf node*/
+	tmprt = RTCreateNode(rm);
+	RT_pivot(tmprt) = SATnormalNode(v);
+	RT_right(tmprt) = rm->root;
+	rm->root = tmprt;
+
+	if((SATflags(ante)&IsConflictMask)&&(SATflags(ante)&IsCNFMask)){
+	  if(!st_lookup(cm->RTreeTable,(char*)ante,&tmprt)){
+	    printf("RTree node of conflict cnf %ld is not in RTreeTable\n",ante);
+	    exit(0);
+	  }
+	  else{
+	    RT_left(rm->root) = tmprt;
+#if PR
+	    printf("Get formula for CONFLICT CLAUSE:%d\n",ante);
+#endif
+	  }
+	}
+	else{ /* if not conflict CNF*/
+	  /*left  */
+	  tmprt = RTCreateNode(rm);
+	  RT_left(rm->root) = tmprt;
+	  /*left is AIG*/
+	  if(!(SATflags(ante) & IsCNFMask)){
+	    /*generate formula for left*/
+	    tmp = ALLOC(long,3);
+	    value = SATvalue(v);
+	    node = SATnormalNode(v);
+	    node = value==1?node:SATnot(node);
+	    tmp[0] = node;
+
+	    size = 1;
+	    if(ante != SATnormalNode(v)){
+	      value = SATvalue(ante);
+	      node = SATnormalNode(ante);
+	      node = value==1?SATnot(node):node;
+	      tmp[1] = node;
+	      size++;
+	      ante2 = SATante2(v);
+	      if(ante2){
+		value = SATvalue(ante2);
+		node = SATnormalNode(ante2);
+		node = value==1?SATnot(node):node;
+		tmp[2] = node;
+		size++;
+	      }
+	    }
+
+	    lp = tmp;
+	    sat_BuildRT(cm,tmprt,lp,tmpIP,size,1);
+	    FREE(tmp);
+	  }
+	  /* left is CNF*/
+	  else{
+
+	    lp = (long*)SATfirstLit(ante);
+	    size = SATnumLits(ante);
+	    RT_fSize(tmprt) = size;
+	    sat_BuildRT(cm,tmprt, lp, tmpIP,size,0);
+	  }
+	} /*else{ // if not conflict CNF*/
+
+      }/*if(cm->option->coreGeneration){*/
+
+
+      sat_MarkNodeInImpliedNode(
+	      cm, d, v, &nMarked, objectFlag, bLevel, clauseArray);
+    }
+    first = 0;
+  }
+
+
+  /* Minimize conflict clause */
+  if(option->minimizeConflictClause)
+    sat_MinimizeConflictClause(cm, clauseArray);
+  else
+    sat_ResetFlagForClauseArray(cm, clauseArray);
+
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Find Unique implication point and find cut to generate additional conflict clause]
+
+  Description [ After finding unique implication point, the backtrack level
+		and failure driven assertion are identified. ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_FindUIPAndNonUIP(
+	satManager_t *cm,
+	satArray_t *clauseArray,
+	satLevel_t *d,
+	int *objectFlag,
+	int *bLevel,
+	long *fdaLit)
+{
+long conflicting;
+int nMarked, value;
+int first, i, j;
+int size, oSize;
+int depth, maxSize;
+long *space, v, nv, maxV;
+long ante, ante2;
+long learned;
+long *plit;
+satArray_t *implied;
+satArray_t *nClauseArray;
+satOption_t *option;
+int tLevel, inverted, lBacktrace, uBacktrace;
+int minLimit, markLimit, tObjectFlag;
+int inserted;
+long tFdaLit;
+
+/** HSJIN : Need to be update to make it consider UNSAT core generation **/
+  conflicting = d->conflict;
+  nMarked = 0;
+  option = cm->option;
+  if(option->incTraceObjective) *objectFlag = 0;
+  else                          *objectFlag = ObjMask;
+
+  (*objectFlag) |= (SATflags(conflicting) & ObjMask);
+
+  /* find seed from conflicting clause to find unique implication point.
+   * */
+  clauseArray->num = 0;
+
+  if(SATflags(conflicting) & IsCNFMask)
+    SATconflictUsage(conflicting)++;
+
+  sat_MarkNodeInConflict(
+	  cm, d, &nMarked, objectFlag, bLevel, clauseArray);
+
+  /* Traverse implication graph backward */
+  first = 1;
+  implied = d->implied;
+  space = implied->space+implied->num-1;
+  maxSize = 0;
+  maxV = 0;
+  /* Bing:  UNSAT core generation */
+  if(cm->option->coreGeneration){
+    cm->dependenceArray = sat_ArrayAlloc(1);
+    sat_ArrayInsert(cm->dependenceArray,conflicting);
+  }
+
+  for(i=implied->num-1; i>=0; i--, space--) {
+    v = *space;
+    if(SATflags(v) & VisitedMask) {
+      SATflags(v) &= ResetVisitedMask;
+      --nMarked;
+
+      depth = cm->variableArray[SATnodeID(v)].depth;
+      if(nMarked == 0 && (!first || i==0))  {
+	value = SATvalue(v);
+	*fdaLit = v^(!value);
+	sat_ArrayInsert(clauseArray, *fdaLit);
+	break;
+      }
+
+      ante = SATante(v);
+      /* Bing: UNSAT core genration */
+      if(cm->option->coreGeneration){
+	if(ante!=0 && !(SATflags(ante) & IsCNFMask)){
+	  printf("node %ld is not CNF\n", ante);
+	  exit(0);
+	}
+	if(ante==0){
+	  if(!st_lookup(cm->anteTable, (char *)SATnormalNode(v), &ante)){
+	    printf("ante = 0 and is not in anteTable %ld\n",v);
+	    exit(0);
+	  }
+	}
+	sat_ArrayInsert(cm->dependenceArray,ante);
+      }
+
+      /**
+      sat_MarkNodeInImpliedNode(
+	      cm, d, v, &nMarked, objectFlag, bLevel, clauseArray);
+	      **/
+
+      if(SATflags(ante) & IsCNFMask) {
+	SATconflictUsage(ante)++;
+	size = SATnumLits(ante);
+	oSize = clauseArray->num;
+	for(j=0, plit=(long*)SATfirstLit(ante); j<size; j++, plit++) {
+	  nv = SATgetNode(*plit);
+	  if(SATnormalNode(nv) != v)	{
+	    sat_MarkNodeSub(cm, nv, &nMarked, bLevel, d, clauseArray);
+	    if(cm->variableArray[SATnodeID(nv)].depth <= depth) {
+	      cm->variableArray[SATnodeID(nv)].depth = depth+1;
+	    }
+	  }
+	}
+	oSize = clauseArray->num-oSize;
+	if(oSize > maxSize) {
+	  maxSize = oSize;
+	  maxV = v;
+	}
+      }
+      else {
+	sat_MarkNodeSub(cm, ante, &nMarked, bLevel, d, clauseArray);
+	ante2 = SATante2(v);
+	if(ante2)
+	  sat_MarkNodeSub(cm, ante2, &nMarked, bLevel, d, clauseArray);
+      }
+
+    }
+    first = 0;
+  }
+
+  /* Minimize conflict clause */
+  if(option->minimizeConflictClause)
+    sat_MinimizeConflictClause(cm, clauseArray);
+  else
+    sat_ResetFlagForClauseArray(cm, clauseArray);
+
+  if(maxSize > clauseArray->num/4 && maxSize > 5) {
+    nClauseArray = sat_ArrayAlloc(clauseArray->num);
+
+    nMarked = 0;
+    tLevel = 0;
+    tObjectFlag |= (SATflags(conflicting) & ObjMask);
+
+    sat_MarkNodeInConflict(
+	  cm, d, &nMarked, &tObjectFlag, &tLevel, nClauseArray);
+
+    /* Traverse implication graph backward */
+    first = 1;
+    implied = d->implied;
+    space = implied->space+implied->num-1;
+    for(i=implied->num-1; i>=0; i--, space--) {
+      v = *space;
+      if(v == maxV) {
+	if(SATflags(v) & VisitedMask) {
+	  SATflags(v) &= ResetVisitedMask;
+	  --nMarked;
+	  value = SATvalue(v);
+	  sat_ArrayInsert(nClauseArray, v^(!value));
+	}
+	continue;
+      }
+
+      if(SATflags(v) & VisitedMask) {
+	SATflags(v) &= ResetVisitedMask;
+	--nMarked;
+
+	if(nMarked == 0 && (!first || i == 0))  {
+	  value = SATvalue(v);
+	  tFdaLit = v^(!value);
+	  sat_ArrayInsert(nClauseArray, tFdaLit);
+	  break;
+	}
+
+	ante= SATante(v);
+	inverted = SATisInverted(ante);
+	ante= SATnormalNode(ante);
+
+	if(SATflags(ante) & IsCNFMask) {
+	  size = SATnumLits(ante);
+	  for(j=0, plit=(long*)SATfirstLit(ante); j<size; j++, plit++) {
+	    nv = SATgetNode(*plit);
+	    if(SATnormalNode(nv) != v)
+	      sat_MarkNodeSub(cm, nv, &nMarked, &tLevel, d, nClauseArray);
+	  }
+	}
+	else {
+	  sat_MarkNodeSub(cm, ante, &nMarked, &tLevel, d, nClauseArray);
+	  ante2 = SATante2(v);
+	  if(ante2)
+	    sat_MarkNodeSub(cm, ante2, &nMarked, &tLevel, d, nClauseArray);
+	}
+      }
+      first = 0;
+    }
+    sat_MinimizeConflictClause(cm, nClauseArray);
+
+    inserted = 0;
+    if(clauseArray->num*4/5 > nClauseArray->num) {
+      learned = sat_AddConflictClauseNoScoreUpdate(cm, nClauseArray, tObjectFlag);
+      inserted = 1;
+    }
+    sat_ArrayFree(nClauseArray);
+  }
+  if( inserted == 0 &&
+      depth > 20) {
+    nClauseArray = sat_ArrayAlloc(clauseArray->num);
+
+    lBacktrace = depth/3;
+    uBacktrace = depth*2/3;
+
+    /** HSJIN : depth, lBacktrace and uBacktrace may affect to
+     * performance **/
+    markLimit = 1;
+    minLimit = 1000;
+    while(1){
+      nMarked = 0;
+      tLevel = 0;
+      depth = 0;
+      nClauseArray->num = 0;
+      markLimit++;
+      if(markLimit > 3)	break;
+      if(minLimit != 1000 && minLimit > 3)
+	break;
+      tObjectFlag |= (SATflags(conflicting) & ObjMask);
+
+      sat_MarkNodeInConflict(
+	    cm, d, &nMarked, &tObjectFlag, &tLevel, nClauseArray);
+
+      first = 1;
+      implied = d->implied;
+      space = implied->space+implied->num-1;
+      for(i=implied->num-1; i>=0; i--, space--) {
+	v = *space;
+	if(uBacktrace < depth) {
+	  sat_ResetFlagForClauseArray(cm, nClauseArray);
+	  nClauseArray->num = 0;
+	  for(; i>=0; i--, space--) {
+	    v = *space;
+	    if(SATflags(v) & VisitedMask) {
+	      SATflags(v) &= ResetVisitedMask;
+	      --nMarked;
+	      if(nMarked == 0)
+		break;
+	    }
+	  }
+	  break;
+	}
+	if(nMarked < minLimit)
+	  minLimit = nMarked;
+	if(depth > lBacktrace && nMarked < markLimit) {
+	  for(; i>=0; i--, space--) {
+	    v = *space;
+	    if(SATflags(v) & VisitedMask) {
+	      SATflags(v) &= ResetVisitedMask;
+	      --nMarked;
+	      value = SATvalue(v);
+	      sat_ArrayInsert(nClauseArray, v^(!value));
+	      if(nMarked == 0)
+		break;
+	    }
+	  }
+	}
+
+	if(SATflags(v) & VisitedMask) {
+	  depth = cm->variableArray[SATnodeID(v)].depth;
+
+	  SATflags(v) &= ResetVisitedMask;
+	  --nMarked;
+
+	  if(nMarked == 0 && (!first || i == 0))  {
+	    value = SATvalue(v);
+	    tFdaLit = v^(!value);
+	    sat_ArrayInsert(nClauseArray, tFdaLit);
+	    break;
+	  }
+
+	  ante= SATante(v);
+	  inverted = SATisInverted(ante);
+	  ante= SATnormalNode(ante);
+
+	  if(SATflags(ante) & IsCNFMask) {
+	    size = SATnumLits(ante);
+	    for(j=0, plit=(long*)SATfirstLit(ante); j<size; j++, plit++) {
+	      nv = SATgetNode(*plit);
+	      if(SATnormalNode(nv) != v)
+		sat_MarkNodeSub(cm, nv, &nMarked, &tLevel, d, nClauseArray);
+	    }
+	  }
+	  else {
+	    sat_MarkNodeSub(cm, ante, &nMarked, &tLevel, d, nClauseArray);
+	    ante2 = SATante2(v);
+	    if(ante2)
+	      sat_MarkNodeSub(cm, ante2, &nMarked, &tLevel, d, nClauseArray);
+	  }
+	}
+	first = 0;
+      }
+      if(nClauseArray->num == 0)
+	continue;
+      sat_MinimizeConflictClause(cm, nClauseArray);
+
+      if(clauseArray->num*4/5 > nClauseArray->num) {
+
+	learned = sat_AddConflictClauseNoScoreUpdate(cm, nClauseArray, tObjectFlag);
+	break;
+      }
+    }
+    sat_ArrayFree(nClauseArray);
+  }
+
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ UIP Analysis that is used for UNSAT core generation.]
+
+  Description [ UIP Analysis that is used for UNSAT core generation.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_FindUIPForCoreGen(
+	satManager_t *cm,
+	satArray_t *clauseArray,
+	satLevel_t *d,
+	int *objectFlag,
+	int *bLevel,
+	long *fdaLit)
+{
+long conflicting;
+int nMarked, value;
+long v;
+int first, i;
+long *space;
+satArray_t *implied;
+satOption_t *option;
+
+  conflicting = d->conflict;
+  nMarked = 0;
+  option = cm->option;
+  if(option->incTraceObjective) *objectFlag = 0;
+  else                          *objectFlag = ObjMask;
+
+  (*objectFlag) |= (SATflags(conflicting) & ObjMask);
+
+  /*  find seed from conflicting clause to find unique implication point. */
+  clauseArray->num = 0;
+  sat_MarkNodeInConflict(
+	  cm, d, &nMarked, objectFlag, bLevel, clauseArray);
+
+  /* Traverse implication graph backward */
+  first = 1;
+  implied = d->implied;
+  space = implied->space+implied->num-1;
+  /* Bing: UNSAT core generation */
+  if(cm->option->coreGeneration){
+    cm->dependenceArray = sat_ArrayAlloc(1);
+    sat_ArrayInsert(cm->dependenceArray,conflicting);
+  }
+
+  for(i=implied->num-1; i>=0; i--, space--) {
+    v = *space;
+    if(SATflags(v) & VisitedMask) {
+      SATflags(v) &= ResetVisitedMask;
+      --nMarked;
+
+      if(nMarked == 0 && (!first || i==0))  {
+	value = SATvalue(v);
+	*fdaLit = v^(!value);
+	sat_ArrayInsert(clauseArray, *fdaLit);
+	break;
+      }
+
+
+       /* Bing: UNSAT core generation */
+      if(cm->option->coreGeneration){
+	int ante = SATante(v);
+	if(ante!=0 && !(SATflags(ante) & IsCNFMask)){
+	  printf("node %d is not CNF\n", ante);
+	  exit(0);
+	}
+	if(ante==0){
+	  if(!st_lookup(cm->anteTable, (char *)SATnormalNode(v), &ante)){
+	    printf("ante = 0 and is not in anteTable %ld\n",v);
+	    exit(0);
+	  }
+	}
+	sat_ArrayInsert(cm->dependenceArray,ante);
+      }
+
+
+      sat_MarkNodeInImpliedNode(
+	      cm, d, v, &nMarked, objectFlag, bLevel, clauseArray);
+    }
+    first = 0;
+  }
+
+  sat_ResetFlagForClauseArray(cm, clauseArray);
+
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [find UIP with resolution generation]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+void
+sat_FindUIPForCoreGenWithRT(
+	satManager_t *cm,
+	satArray_t *clauseArray,
+	satLevel_t *d,
+	int *objectFlag,
+	int *bLevel,
+	long *fdaLit)
+{
+long conflicting;
+int nMarked, value;
+ long v,left,right,inverted,result;
+int first, i,size=0;
+long *space,*tmp;
+satArray_t *implied;
+satOption_t *option;
+RTnode_t tmprt;
+long  *lp, *tmpIP,ante,ante2,node,j;
+ RTManager_t * rm = cm->rm;
+
+  conflicting = d->conflict;
+  nMarked = 0;
+  option = cm->option;
+  if(option->incTraceObjective) *objectFlag = 0;
+  else                          *objectFlag = ObjMask;
+
+  (*objectFlag) |= (SATflags(conflicting) & ObjMask);
+
+  /*  find seed from conflicting clause to find unique implication point. */
+  clauseArray->num = 0;
+  sat_MarkNodeInConflict(
+	  cm, d, &nMarked, objectFlag, bLevel, clauseArray);
+
+  /* Traverse implication graph backward */
+  first = 1;
+  implied = d->implied;
+  space = implied->space+implied->num-1;
+
+
+  if(cm->option->coreGeneration){
+    /*if last conflict is CNF*/
+    if(SATflags(conflicting)&IsCNFMask){
+      /*is conflict CNF*/
+      if(SATflags(conflicting)&IsConflictMask){
+	 if(!st_lookup(cm->RTreeTable,(char*)conflicting,&tmprt)){
+	    printf("RTree node of conflict cnf %ld is not in RTreeTable\n",ante);
+	    exit(0);
+	  }
+	  else{
+	    rm->root = tmprt;
+#if PR
+	    printf("Get formula for CONFLICT CLAUSE:%d\n",ante);
+#endif
+	  }
+      }
+      /*CNF but not conflict*/
+      else{
+	rm->root = RTCreateNode(rm);
+
+	size = SATnumLits(conflicting);
+	RT_fSize(rm->root) = size;
+	lp = (long*)SATfirstLit(conflicting);
+	sat_BuildRT(cm,rm->root, lp, tmpIP,size,0);
+      }
+    }
+    /*if last conflict is AIG*/
+    else{
+      rm->root = RTCreateNode(rm);
+      node = SATnormalNode(conflicting);
+      left = SATleftChild(node);
+      right = SATrightChild(node);
+      result = PureSat_IdentifyConflict(cm,left,right,conflicting);
+      inverted = SATisInverted(left);
+      left = SATnormalNode(left);
+      left = inverted ? SATnot(left) : left;
+
+      inverted = SATisInverted(right);
+      right = SATnormalNode(right);
+      right = inverted ? SATnot(right) : right;
+
+      j = node;
+
+      if(result == 1){
+	tmp = ALLOC(long,3);
+	tmp[0] = left;
+	tmp[1] = SATnot(j);
+	size = 2;
+      }
+      else if(result == 2){
+	tmp = ALLOC(long,3);
+	tmp[0] = right;
+	tmp[1] = SATnot(j);
+	size = 2;
+      }
+      else if(result == 3){
+	tmp = ALLOC(long,4);
+	tmp[0] = SATnot(left);
+	tmp[1] = SATnot(right);
+	tmp[2] = j;
+	size = 3;
+      }
+      else{
+	printf("wrong returned result value, exit\n");
+	exit(0);
+      }
+
+      lp = tmp;
+      sat_BuildRT(cm,rm->root, lp, tmpIP,size,1);
+      FREE(tmp);
+    }
+  }
+
+
+
+  for(i=implied->num-1; i>=0; i--, space--) {
+    v = *space;
+    if(SATflags(v) & VisitedMask) {
+      SATflags(v) &= ResetVisitedMask;
+      --nMarked;
+
+      if(nMarked == 0 && (!first || i==0))  {
+	value = SATvalue(v);
+	*fdaLit = v^(!value);
+	sat_ArrayInsert(clauseArray, *fdaLit);
+	break;
+      }
+
+
+      if(cm->option->coreGeneration){
+	ante = SATante(v);
+	if(ante==0){
+	  if(!(st_lookup(cm->anteTable, (char *)SATnormalNode(v),&ante))){
+	    printf("ante = 0 and is not in anteTable %ld\n",v);
+	    exit(0);
+	  }
+	}
+
+	/*build non-leaf node*/
+	tmprt = RTCreateNode(rm);
+	RT_pivot(tmprt) = SATnormalNode(v);
+	RT_right(tmprt) = rm->root;
+	rm->root = tmprt;
+
+	if((SATflags(ante)&IsConflictMask)&&(SATflags(ante)&IsCNFMask)){
+	  if(!st_lookup(cm->RTreeTable,(char*)ante,&tmprt)){
+	    printf("RTree node of conflict cnf %ld is not in RTreeTable\n",ante);
+	    exit(0);
+	  }
+	  else{
+	    RT_left(rm->root) = tmprt;
+#if PR
+	    printf("Get formula for CONFLICT CLAUSE:%d\n",ante);
+#endif
+	  }
+	}
+	else{ /* if not conflict CNF*/
+	  /*left */
+	  tmprt = RTCreateNode(rm);
+	  RT_left(rm->root) = tmprt;
+	  /*left is AIG*/
+	  if(!(SATflags(ante) & IsCNFMask)){
+	    /*generate formula for left*/
+	    tmp = ALLOC(long,3);
+	    value = SATvalue(v);
+	    node = SATnormalNode(v);
+	    node = value==1?node:SATnot(node);
+	    tmp[0] = node;
+
+	    size = 1;
+	    if(ante != SATnormalNode(v)){
+	      value = SATvalue(ante);
+	      node = SATnormalNode(ante);
+	      node = value==1?SATnot(node):node;
+	      tmp[1] = node;
+	      size++;
+	      ante2 = SATante2(v);
+	      if(ante2){
+		value = SATvalue(ante2);
+		node = SATnormalNode(ante2);
+		node = value==1?SATnot(node):node;
+		tmp[2] = node;
+		size++;
+	      }
+	    }
+
+	    lp = tmp;
+	    sat_BuildRT(cm,tmprt,lp,tmpIP,size,1);
+	    FREE(tmp);
+	  }
+	  /* left is CNF*/
+	  else{
+
+	    lp = (long*)SATfirstLit(ante);
+	    size = SATnumLits(ante);
+	    RT_fSize(tmprt) = size;
+	    sat_BuildRT(cm,tmprt, lp, tmpIP,size,0);
+	  }
+	} /*else{ // if not conflict CNF*/
+
+      }/*if(cm->option->coreGeneration){*/
+
+
+      sat_MarkNodeInImpliedNode(
+	      cm, d, v, &nMarked, objectFlag, bLevel, clauseArray);
+    }
+    first = 0;
+  }
+
+  sat_ResetFlagForClauseArray(cm, clauseArray);
+
+  return;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Minimize the literals of conflict clause]
+
+  Description [ If the literal can be implied by other literals in
+		conflict clause then we can delete it from conflict clause.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_MinimizeConflictClause(
+	satManager_t *cm,
+	satArray_t *clauseArray)
+{
+int i, j, size, all, tsize;
+int inverted;
+long v, tv;
+long ante, ante2;
+long *plit;
+satArray_t *newArray;
+satVariable_t *var;
+
+  size = clauseArray->num;
+  newArray = sat_ArrayAlloc(size);
+  for(i=0; i<size; i++) {
+    v = clauseArray->space[i];
+    inverted = SATisInverted(v);
+    v = SATnormalNode(v);
+
+    ante = SATante(v);
+    ante = SATnormalNode(ante);
+    if(SATflags(ante) & IsCNFMask) {
+      tsize = SATnumLits(ante);
+      all = 1;
+      for(j=0, plit=(long*)SATfirstLit(ante); j<tsize; j++, plit++) {
+	tv = SATgetNode(*plit);
+	tv = SATnormalNode(tv);
+	if(tv == v)	continue;
+	if(!(SATflags(tv) & NewMask)) {
+	  all = 0;
+	  break;
+	}
+      }
+      if(all) {
+	var = SATgetVariable(v);
+	if(inverted)	(var->litsCount[1])++;
+	else		(var->litsCount[0])++;
+	continue;
+      }
+    }
+    else {
+      if(SATflags(ante) & NewMask) {
+	ante2 = SATante2(v);
+	ante2 = SATnormalNode(ante2);
+	if((ante2==0) || (SATflags(ante2) & NewMask)) {
+	  var = SATgetVariable(v);
+	  if(inverted)	(var->litsCount[1])++;
+	  else		(var->litsCount[0])++;
+	  continue;
+	}
+      }
+    }
+    sat_ArrayInsert(newArray, v^inverted);
+  }
+  sat_ResetFlagForClauseArray(cm, clauseArray);
+  memcpy(clauseArray->space, newArray->space, sizeof(long)*(newArray->num));
+  clauseArray->num = newArray->num;
+  sat_ArrayFree(newArray);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Reset flags that are used to indentify conflict clause]
+
+  Description [ Reset flags that are used to indentify conflict clause]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_ResetFlagForClauseArray(
+	satManager_t *cm,
+	satArray_t *clauseArray)
+{
+int size, i;
+long v;
+
+  size = clauseArray->num;
+  for(i=0; i<size; i++) {
+    v = clauseArray->space[i];
+    v = SATnormalNode(v);
+    SATflags(v) &= ResetNewVisitedMask;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Find seed for unique implication point analysis
+		from conflicting clause]
+
+  Description [ Find seed for unique implication point analysis
+		from conflicting clause]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_MarkNodeInConflict(
+	satManager_t *cm,
+	satLevel_t *d,
+	int *nMarked,
+	int *objectFlag,
+	int *bLevel,
+	satArray_t *clauseArray)
+{
+satOption_t *option;
+
+  option = cm->option;
+  if(option->incTraceObjective == 0) {
+    sat_MarkNodeInConflictClauseNoObj(
+	cm, d, nMarked, objectFlag, bLevel, clauseArray);
+  }
+  else if(option->incTraceObjective == 1) { /* conservative */
+    sat_MarkNodeInConflictClauseObjConservative(
+	cm, d, nMarked, objectFlag, bLevel, clauseArray);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Traverse the antecedent to find unique implication point]
+
+  Description [ Traverse the antecedent to find unique implication point]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_MarkNodeInImpliedNode(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	int *nMarked,
+	int *objectFlag,
+	int *bLevel,
+	satArray_t *clauseArray)
+{
+satOption_t *option;
+
+  option = cm->option;
+  if(option->incTraceObjective == 0) {
+    sat_MarkNodeInImpliedNodeNoObj(
+	cm, d, v, nMarked, objectFlag, bLevel, clauseArray);
+  }
+  else if(option->incTraceObjective == 1) { /* conservative */
+    sat_MarkNodeInImpliedNodeObjConservative(
+	cm, d, v, nMarked, objectFlag, bLevel, clauseArray);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ If the node is implied in current level then mark it,
+		otherwise add it to conflict clause]
+
+  Description [ If the node is implied in current level then mark it,
+		otherwise add it to conflict clause]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_MarkNodeSub(
+	satManager_t *cm,
+	long v,
+	int *nMarked,
+	int *bLevel,
+	satLevel_t *d,
+	satArray_t *clauseArray)
+{
+satLevel_t *td;
+satOption_t *option;
+int value;
+
+  v = SATnormalNode(v);
+
+  td = SATgetDecision(SATlevel(v));
+  if(d == td) {
+    if(!(SATflags(v) & VisitedMask)) {
+      (*nMarked)++;
+      SATflags(v) |= VisitedMask;
+    }
+  }
+  else if(td->level < d->level) {
+    if(!(SATflags(v) & NewMask)) {
+      option = cm->option;
+      if((td->level != 0) ||
+	 (td->level == 0 && option->includeLevelZeroLiteral)) {
+	SATflags(v) |= NewMask;
+	value = SATvalue(v);
+	sat_ArrayInsert(clauseArray, v^(!value));
+	if(*bLevel < td->level)
+	  *bLevel = td->level;
+      }
+    }
+  }
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Traverse the antecedent to find unique implication point]
+
+  Description [ Traverse the antecedent to find unique implication point]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_MarkNodeInImpliedNodeNoObj(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	int *nMarked,
+	int *oFlag,
+	int *bLevel,
+	satArray_t *clauseArray)
+{
+long ante, ante2, nv;
+int inverted, size, i;
+long *plit;
+satOption_t *option;
+
+  ante= SATante(v);
+  /* Bing: UNSAT core generation */
+  if(cm->option->coreGeneration){
+    if(ante==0){
+      if(!(st_lookup(cm->anteTable, (char *)(long)SATnormalNode(v), &ante))){
+	printf("ante = 0 and is not in anteTable %ld\n",v);
+	exit(0);
+      }
+    }
+  }
+  inverted = SATisInverted(ante);
+  ante= SATnormalNode(ante);
+
+  option = cm->option;
+  if(SATflags(ante) & IsCNFMask) {
+    SATconflictUsage(ante)++;
+    size = SATnumLits(ante);
+    for(i=0, plit=(long*)SATfirstLit(ante); i<size; i++, plit++) {
+      nv = SATgetNode(*plit);
+      if((int)(SATnormalNode(nv)) == v)	continue;
+      sat_MarkNodeSub(cm, nv, nMarked, bLevel, d, clauseArray);
+    }
+  }
+  else {
+    /*Bing: very inmportant for level zero conflict analysis*/
+    if(ante != SATnormalNode(v))
+      sat_MarkNodeSub(cm, ante, nMarked, bLevel, d, clauseArray);
+
+    ante2 = SATante2(v);
+    if(ante2)
+      sat_MarkNodeSub(cm, ante2, nMarked, bLevel, d, clauseArray);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Traverse the antecedent to find unique implication point]
+
+  Description [ Traverse the antecedent to find unique implication point]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_MarkNodeInImpliedNodeObjConservative(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	int *nMarked,
+	int *oFlag,
+	int *bLevel,
+	satArray_t *clauseArray)
+{
+long ante, ante2, nv;
+int inverted, size, i;
+int objectFlag;
+long *plit;
+satOption_t *option;
+
+  ante= SATante(v);
+  /* Bing: UNSAT core generation */
+  if(cm->option->coreGeneration){
+    if(ante==0){
+      if(!(st_lookup(cm->anteTable, (char *)SATnormalNode(v), &ante))){
+	printf("ante = 0 and is not in anteTable %ld\n",v);
+	exit(0);
+      }
+    }
+  }
+  inverted = SATisInverted(ante);
+  ante= SATnormalNode(ante);
+
+  objectFlag = 0;
+  option = cm->option;
+  if(SATflags(ante) & IsCNFMask) {
+    SATconflictUsage(ante)++;
+    size = SATnumLits(ante);
+    for(i=0, plit=(long*)SATfirstLit(ante); i<size; i++, plit++) {
+      nv = SATgetNode(*plit);
+      nv = SATnormalNode(nv);
+      if(nv == v)	continue;
+      sat_MarkNodeSub(cm, nv, nMarked, bLevel, d, clauseArray);
+    }
+    objectFlag |= SATflags(ante) & ObjMask;
+  }
+  else {
+    /*Bing: very inmportant for level zero conflict analysis*/
+    if(ante != SATnormalNode(v))
+      sat_MarkNodeSub(cm, ante, nMarked, bLevel, d, clauseArray);
+
+    ante2 = SATante2(v);
+    if(ante2) {
+      ante2 = SATnormalNode(ante2);
+      sat_MarkNodeSub(cm, ante2, nMarked, bLevel, d, clauseArray);
+    }
+  }
+  *oFlag |= objectFlag;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Find seed for unique implication point analysis
+		from conflicting clause]
+
+  Description [ Find seed for unique implication point analysis
+		from conflicting clause]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_MarkNodeInConflictClauseNoObj(
+	satManager_t *cm,
+	satLevel_t *d,
+	int *nMarked,
+	int *oFlag,
+	int *bLevel,
+	satArray_t *clauseArray)
+{
+long conflict, left, right, nv;
+int inverted, size, value, i;
+long *plit;
+satOption_t *option;
+
+  conflict = d->conflict;
+  inverted = SATisInverted(conflict);
+  conflict = SATnormalNode(conflict);
+
+  option = cm->option;
+  if(SATflags(conflict) & IsCNFMask) {
+    size = SATnumLits(conflict);
+    for(i=0, plit=(long*)SATfirstLit(conflict); i<size; i++, plit++) {
+      nv = SATgetNode(*plit);
+      sat_MarkNodeSub(cm, nv, nMarked, bLevel, d, clauseArray);
+    }
+  }
+  else {
+    value = SATvalue(conflict);
+    if(value == 1) {
+      sat_MarkNodeSub(cm, conflict, nMarked, bLevel, d, clauseArray);
+
+      left = SATleftChild(conflict);
+      inverted = SATisInverted(left);
+      left = SATnormalNode(left);
+      value = SATvalue(left) ^ inverted;
+      if(value == 0) {
+	sat_MarkNodeSub(cm, left, nMarked, bLevel, d, clauseArray);
+	return;
+      }
+
+      right = SATrightChild(conflict);
+      inverted = SATisInverted(right);
+      right = SATnormalNode(right);
+      value = SATvalue(right) ^ inverted;
+      if(value == 0) {
+	sat_MarkNodeSub(cm, right, nMarked, bLevel, d, clauseArray);
+	return;
+      }
+    }
+    else if(value == 0) {
+      left = SATleftChild(conflict);
+      right = SATrightChild(conflict);
+      sat_MarkNodeSub(cm, conflict, nMarked, bLevel, d, clauseArray);
+      sat_MarkNodeSub(cm, left, nMarked, bLevel, d, clauseArray);
+      sat_MarkNodeSub(cm, right, nMarked, bLevel, d, clauseArray);
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Find seed for unique implication point analysis
+		from conflicting clause]
+
+  Description [ Find seed for unique implication point analysis
+		from conflicting clause]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_MarkNodeInConflictClauseObjConservative(
+	satManager_t *cm,
+	satLevel_t *d,
+	int *nMarked,
+	int *oFlag,
+	int *bLevel,
+	satArray_t *clauseArray)
+{
+long conflict, left, right, nv;
+int inverted, size, value, i;
+long *plit;
+satOption_t *option;
+
+  conflict = d->conflict;
+  inverted = SATisInverted(conflict);
+  conflict = SATnormalNode(conflict);
+
+  option = cm->option;
+  if(SATflags(conflict) & IsCNFMask) {
+    size = SATnumLits(conflict);
+    for(i=0, plit=(long*)SATfirstLit(conflict); i<size; i++, plit++) {
+      nv = SATgetNode(*plit);
+      *oFlag |= (SATflags(nv) & ObjMask);
+      sat_MarkNodeSub(cm, nv, nMarked, bLevel, d, clauseArray);
+    }
+  }
+  else {
+    value = SATvalue(conflict);
+    if(value == 1) {
+      *oFlag |= (SATflags(conflict) & ObjMask);
+      sat_MarkNodeSub(cm, conflict, nMarked, bLevel, d, clauseArray);
+
+      left = SATleftChild(conflict);
+      inverted = SATisInverted(left);
+      left = SATnormalNode(left);
+      value = SATvalue(left) ^ inverted;
+      if(value == 0) {
+	*oFlag |= (SATflags(left) & ObjMask);
+	sat_MarkNodeSub(cm, left, nMarked, bLevel, d, clauseArray);
+	return;
+      }
+
+      right = SATrightChild(conflict);
+      inverted = SATisInverted(right);
+      right = SATnormalNode(right);
+      value = SATvalue(right) ^ inverted;
+      if(value == 0) {
+	*oFlag |= (SATflags(right) & ObjMask);
+	sat_MarkNodeSub(cm, right, nMarked, bLevel, d, clauseArray);
+	return;
+      }
+    }
+    else if(value == 0) {
+      *oFlag |= (SATflags(conflict) & ObjMask);
+
+      left = SATleftChild(conflict);
+      inverted = SATisInverted(left);
+      left = SATnormalNode(left);
+      *oFlag |= (SATflags(left) & ObjMask);
+
+      right = SATrightChild(conflict);
+      inverted = SATisInverted(right);
+      right = SATnormalNode(right);
+      *oFlag |= (SATflags(right) & ObjMask);
+
+      sat_MarkNodeSub(cm, conflict, nMarked, bLevel, d, clauseArray);
+      sat_MarkNodeSub(cm, left, nMarked, bLevel, d, clauseArray);
+      sat_MarkNodeSub(cm, right, nMarked, bLevel, d, clauseArray);
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Backtrack to given decision level ]
+
+  Description [ Backtrack to given decision level ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_Backtrack(
+	satManager_t *cm,
+	int level)
+{
+satLevel_t *d;
+
+/*Bing*/
+ if(cm->option->ForceFinish == 0)
+   if(level < 0)	return;
+
+  d = SATgetDecision(cm->currentDecision);
+  while(1) {
+    if(d->level <= level)
+      break;
+
+    sat_Undo(cm, d);
+    cm->currentDecision--;
+    if(cm->currentDecision == -1)
+      break;
+    d = SATgetDecision(cm->currentDecision);
+  }
+  return;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Undo implication]
+
+  Description [ Undo implication]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_Undo(
+	satManager_t *cm,
+	satLevel_t *d)
+{
+satArray_t *implied, *satisfied;
+satVariable_t *var;
+int size, i;
+long *space, v;
+
+  implied = d->implied;
+  space = implied->space;
+  size = implied->num;
+  for(i=0; i<size; i++, space++) {
+    v = *space;
+
+    SATvalue(v) = 2;
+    SATflags(v) &= ResetNewVisitedObjInQueueMask;
+    var = &(cm->variableArray[SATnodeID(v)]);
+    var->antecedent = 0;
+    var->antecedent2 = 0;
+    var->level = -1;
+    var->depth = 0;
+  }
+
+  cm->implicatedSoFar -= size;
+
+  if(d->satisfied) {
+    satisfied = d->implied;
+    space = satisfied->space;
+    size = satisfied->num;
+    for(i=0; i<size; i++, space++) {
+      v = *space;
+
+      SATflags(v) &= ResetBDDSatisfiedMask;
+    }
+    d->satisfied->num = 0;
+  }
+  if(d->level > 0) {
+    if((cm->decisionHead[d->level-1]).currentVarPos < cm->currentVarPos)
+      cm->currentVarPos = (cm->decisionHead[d->level-1]).currentVarPos;
+  }
+  else
+    cm->currentVarPos = d->currentVarPos;
+
+  d->implied->num = 0;
+  d->currentVarPos = 0;
+  d->conflict = 0;
+
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Compare decision level of variable ]
+
+  Description [ Compare decision level of variable ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+static int
+levelCompare(
+  const void * node1,
+  const void * node2)
+{
+  long v1, v2;
+  int l1, l2;
+
+  v1 = *(int *)(node1);
+  v2 = *(int *)(node2);
+  l1 = SATcm->variableArray[SATnodeID(v1)].level;
+  l2 = SATcm->variableArray[SATnodeID(v2)].level;
+
+  if(l1 == l2)	return(v1 > v2);
+  return (l1 > l2);
+}
Index: vis_dev/vis-2.3/src/sat/satCore.c
===================================================================
--- vis_dev/vis-2.3/src/sat/satCore.c	(revision 14)
+++ vis_dev/vis-2.3/src/sat/satCore.c	(revision 14)
@@ -0,0 +1,1855 @@
+/**CFile***********************************************************************
+
+  FileName    [satCore.c]
+
+  PackageName [sat]
+
+  Synopsis    [Routines for UNSAT core generation,both CNF-based and Aig-based
+	      UNSAT core generetions are available]
+
+  Author      [Bing Li]
+
+  Copyright [ This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+
+******************************************************************************/
+
+#include "satInt.h"
+#include "puresatInt.h"
+
+static char rcsid[] UNUSED = "$Id: satCore.c,v 1.20 2009/04/12 00:14:11 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define CONFLICT 1
+#define NO_CONFLICT 2
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int
+ScoreCompare(
+  const void * node1,
+  const void * node2)
+{
+int v1;
+int v2;
+int s1, s2;
+
+  v1 = *(int *)(node1);
+  v2 = *(int *)(node2);
+  s1 = *((int *)(node1) + 1);
+  s2 = *((int *)(node2) + 1);
+
+  if(s1 == s2) {
+    return(v1 > v2);
+  }
+  return(s1 < s2);
+}
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Print literals of given clauses]
+
+  Description [Print literals of given clauses]
+
+  SideEffects [ ]
+
+  SeeAlso     [ ]
+
+******************************************************************************/
+
+void
+sat_PrintClauseLits(satManager_t * cm,
+		       long concl)
+{
+  long i, node, var_idx,*lit;
+
+  for(i=0, lit = (long*)SATfirstLit(concl); i<SATnumLits(concl);i++, lit++){
+    node = SATgetNode(*lit);
+    var_idx = SATnodeID(node);
+    if(SATisInverted(node))
+      fprintf(vis_stdout,"%ld ", -var_idx);
+    else
+      fprintf(vis_stdout,"%ld ",var_idx);
+  }
+  fprintf(vis_stdout,"0\n");
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Print literals of given clauses to a certain file for UNSAT
+	       core generation]
+
+  Description [Print literals of given clauses to a certain file for UNSAT
+	       core generation]
+
+  SideEffects [ ]
+
+  SeeAlso     [ ]
+
+******************************************************************************/
+
+void
+sat_PrintClauseLitsForCore(satManager_t * cm,
+		       long concl,
+		       FILE *fp)
+{
+  long i, node, var_idx,*lit, cls_idx;
+
+  lit = (long*)SATfirstLit(concl);
+  cls_idx = -(*(lit-1));
+
+  if(fp) {
+    /** cls_idx -= cm->numOfVar * satNodeSize; **/
+    cls_idx -= cm->initNumVariables * satNodeSize;
+    /**cls idx starts from 0 **/
+    cls_idx = cls_idx/satNodeSize - 1;
+    fprintf(fp,"#clause index:%ld\n",cls_idx);
+    for(i=0, lit = (long*)SATfirstLit(concl); i<SATnumLits(concl);i++, lit++){
+      node = SATgetNode(*lit);
+      var_idx = SATnodeID(node);
+      if(SATisInverted(node))
+	fprintf(fp, "%ld ", -var_idx);
+      else
+	fprintf(fp, "%ld ",var_idx);
+    }
+    fprintf(fp, "0\n");
+  }
+  else {
+    if(cm->clauseIndexInCore == 0)
+      cm->clauseIndexInCore = sat_ArrayAlloc(1024);
+    sat_ArrayInsert(cm->clauseIndexInCore, cls_idx);
+  }
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Recursively generate the UNSAT core]
+
+  Description [Recursively generate the UNSAT core]
+
+  SideEffects [ ]
+
+  SeeAlso     [ ]
+
+******************************************************************************/
+
+void
+sat_GenerateCoreRecur(satManager_t * cm,
+		 long concl,
+		 FILE *fp,
+		 int * count)
+{
+  int j;
+  long tmp;
+  satArray_t * dep;
+
+  if(!(SATflags(concl)&NewMask)){
+    SATflags(concl)|=NewMask;
+    /** Not Conflict **/
+    if(!(SATflags(concl)& IsConflictMask)){
+      (*count)++;
+      sat_PrintClauseLitsForCore(cm,concl,fp);
+    }
+    /** is CONFLICT **/
+    else{
+      if(!st_lookup(cm->dependenceTable,(char *)concl, &dep)){
+	fprintf(cm->stdOut,"%ld is not in depe table\n",concl);
+	exit(0);
+      }
+      else{
+	for(j=0;j<dep->num; j++){
+	  tmp = dep->space[j];
+	  sat_GenerateCoreRecur(cm, tmp, fp, count);
+	}
+      }
+    }
+  }/**  if(!(SATflags(concl)&NewMask)){ **/
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generate dependence clauses for the conflict]
+
+  Description [Generate dependence clauses for the conflict]
+
+  SideEffects [ ]
+
+  SeeAlso     [ ]
+
+******************************************************************************/
+
+void
+sat_GetDependence(satManager_t * cm, long concl, satArray_t* dep)
+{
+long node, *lit, ante;
+int i;
+
+  for(i=0, lit = (long*)SATfirstLit(concl); i<SATnumLits(concl);i++, lit++){
+    node = SATgetNode(*lit);
+    node = SATnormalNode(node);
+    ante = SATante(node);
+    if(ante==0){
+      if(!st_lookup(cm->anteTable, (char *)node, &ante)){
+	fprintf(vis_stdout,"ante = 0 and is not in anteTable %ld\n",node);
+	exit(0);
+      }
+    }
+    if(!(SATflags(ante)&NewMask)){
+      SATflags(ante)|=NewMask;
+      sat_ArrayInsert(dep,ante);
+      sat_GetDependence(cm,ante,dep);
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Conflict Core Generation]
+
+  Description [Conflict Core Generation]
+
+  SideEffects [ ]
+
+  SeeAlso     [ ]
+
+******************************************************************************/
+
+void
+sat_GenerateCore(satManager_t * cm)
+{
+  int j, tmp,value;
+  long *lit, node, concl, i;
+  satArray_t * dep;
+  FILE *fp = cm->fp;
+  int  count, inverted;
+  st_generator *stGen;
+  satArray_t* tmpdep = sat_ArrayAlloc(1);
+  satLevel_t * d;
+
+  cm->status = 0;
+  count = 0;
+  d = SATgetDecision(0);
+  for(i=satNodeSize; i<cm->nodesArraySize; i+=satNodeSize){
+    node = i;
+    if((SATflags(node)&IsCNFMask)&&(SATnumLits(node)==1)){
+      lit = (long*)SATfirstLit(node);
+      tmp = SATgetNode(*lit);
+      inverted = SATisInverted(tmp);
+      tmp = SATnormalNode(tmp);
+
+
+      value = !inverted;
+      if(SATvalue(tmp) < 2)	{
+	if(SATvalue(tmp) == value)	continue;
+	else {
+	  cm->status = SAT_UNSAT;
+	  d->conflict = node;
+	  break;
+	}
+      }
+
+      SATvalue(tmp) = !inverted;
+      SATmakeImplied(tmp, d);
+      SATante(tmp) = node;
+      if((SATflags(tmp) & InQueueMask) == 0) {
+	sat_Enqueue(cm->queue, tmp);
+	SATflags(tmp) |= InQueueMask;
+      }
+      /** sat_ArrayInsert(unitArray, tmp); **/
+    }
+  }
+
+  sat_ImplicationMain(cm, d);
+  if(d->conflict == 0) {
+    fprintf(vis_stderr,"There should be a conflict\n");
+    exit(0);
+  }
+  /** Last Conflict Cls **/
+  concl = d->conflict;
+  sat_ArrayInsert(tmpdep,concl);
+  SATflags(concl)|=NewMask;
+  /** sat_ArrayInsert(arr,cl); **/
+  if(!(SATflags(concl)&IsConflictMask)){
+    count++;
+    sat_PrintClauseLitsForCore(cm,concl,fp);
+  }
+
+  sat_GetDependence(cm, concl, tmpdep);
+  for(i=satNodeSize;i<cm->nodesArraySize;i+=satNodeSize){
+    SATflags(i)&=ResetNewMask;
+  }
+
+  for(i=0;i<tmpdep->num;i++){
+    concl = tmpdep->space[i];
+    if(!(SATflags(concl)&NewMask)){
+      SATflags(concl)|=NewMask;
+      /** is CONFLICT **/
+      if((SATflags(concl)&IsConflictMask)){
+	if(!st_lookup(cm->dependenceTable,(char *)concl,&dep)){
+	  fprintf(cm->stdOut,"%ld is conflict but not in depe table\n",concl);
+	  exit(0);
+	}
+	else{
+	  for(j=0;j<dep->num; j++){
+	    tmp = dep->space[j];
+	    sat_GenerateCoreRecur(cm, tmp, fp, &count);
+	  }
+	}
+      }
+      /**not CONFLICT **/
+      else{
+	count++;
+	sat_PrintClauseLitsForCore(cm,concl,fp);
+      }
+    }
+  }
+  /**fclose(fp); **/
+  cm->numOfClsInCore = count;
+
+  for(i=satNodeSize;i<cm->nodesArraySize;i+=satNodeSize){
+    SATflags(i)&=ResetNewMask;
+  }
+  st_foreach_item(cm->dependenceTable, stGen,&node, &dep)
+    sat_ArrayFree(dep);
+  sat_ArrayFree(tmpdep);
+  sat_Undo(cm,d);
+  st_free_table(cm->dependenceTable);
+  st_free_table(cm->anteTable);
+  cm->status = SAT_UNSAT;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Implication propogation from assertations in an array ]
+
+  Description [This funct is only for AIG assertation]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_ImplyArrayWithAnte(
+	satManager_t *cm,
+	satLevel_t *d,
+	satArray_t *arr)
+{
+int i, size;
+bAigEdge_t v;
+int inverted, value;
+satQueue_t *Q;
+
+  if(arr == 0)	return;
+  if(cm->status)return;
+
+  size = arr->num;
+  Q = cm->queue;
+  for(i=0; i<size; i++) {
+    v = arr->space[i];
+    inverted = SATisInverted(v);
+    v = SATnormalNode(v);
+
+    value = !inverted;
+    if(SATvalue(v) < 2)	{
+      if(SATvalue(v) == value)	continue;
+      else {
+	cm->status = SAT_UNSAT;
+	d->conflict = v;
+	return;
+      }
+    }
+
+    SATvalue(v) = value;
+    SATmakeImplied(v, d);
+    SATante(v) = SATnormalNode(v);
+
+    if((SATflags(v) & InQueueMask) == 0) {
+      sat_Enqueue(Q, v);
+      SATflags(v) |= InQueueMask;
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Force implication to pure and unit literals and set antecedence
+	      of them]
+
+  Description [Force implication to pure and unit literals and set antecedence
+	      of them]
+
+  SideEffects [ ]
+
+  SeeAlso     [ ]
+
+******************************************************************************/
+void
+sat_ImplyUnitPureLitsWithAnte(satManager_t * cm, satLevel_t *d)
+{
+  int tmp, inverted;
+  long node, *lit, i;
+
+  for(i=satNodeSize; i<cm->nodesArraySize; i+=satNodeSize){
+    node = i;
+    if((SATflags(node)&IsCNFMask)&&(SATnumLits(node)==1)){
+      int value;
+      lit = (long*)SATfirstLit(node);
+      tmp = SATgetNode(*lit);
+      inverted = SATisInverted(tmp);
+      tmp = SATnormalNode(tmp);
+
+      value = !inverted;
+      if(SATvalue(tmp) < 2)	{
+	if(SATvalue(tmp) == value)	continue;
+	else {
+	  cm->status = SAT_UNSAT;
+	  d->conflict = node;
+	  break;
+	}
+      }
+
+      SATvalue(tmp) = !inverted;
+      SATmakeImplied(tmp, d);
+      SATante(tmp) = node;
+      if((SATflags(tmp) & InQueueMask) == 0) {
+	sat_Enqueue(cm->queue, tmp);
+	SATflags(tmp) |= InQueueMask;
+      }
+    }
+  }
+
+  if(cm->status == SAT_UNSAT)
+    return;
+
+  sat_ImplyArray(cm, d, cm->pureLits);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Build an node for resolution tree]
+
+  Description [tmpIP, lp,size must be prepared
+	       Get formula for leaf nodes]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_BuildRT(
+  satManager_t * cm,
+  RTnode_t root,
+  long *lp,
+  long *tmpIP,
+  int size,
+  boolean NotCNF)
+{
+  int i;
+  long tmpnode;
+  RTManager_t *rm = cm->rm;
+
+  RT_formula(root) = rm->cpos;
+
+  RT_fSize(root) = size;
+
+
+  if(rm->maxpos<=rm->cpos+size+1){
+    rm->fArray = REALLOC(long,rm->fArray,rm->maxpos+FORMULA_BLOCK);
+    rm->maxpos = rm->maxpos+FORMULA_BLOCK;
+  }
+
+  for(i=0;i<size;i++,lp++){
+    if(NotCNF)
+      tmpnode = *lp;
+    else
+      tmpnode = SATgetNode(*lp);
+    rm->fArray[rm->cpos] = tmpnode;
+    rm->cpos++;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Generate interpolation forwardly]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+bAigEdge_t sat_GenerateFwdIP(bAig_Manager_t* manager,
+			     satManager_t *cm,
+			     RTnode_t  RTnode,
+			     int cut)
+{
+  int i;
+  long node, node1, left, right, result, *lp, *lp1;
+  int IPTrue=0, local=1, first=0, second=0, allDummy=1;
+  RTManager_t * rm = cm->rm;
+
+  manager->class_ = cut;
+  if(RT_flag(RTnode)&RT_VisitedMask){
+#if DBG
+    assert(RT_IPnode(RTnode)!=-1);
+#endif
+
+    return RT_IPnode(RTnode);
+  }
+#if DBG
+  assert(RT_IPnode(RTnode)==-1);
+#endif
+  RT_flag(RTnode) |= RT_VisitedMask;
+
+  if(RT_pivot(RTnode)==0){ /*leaf*/
+
+#if DBG
+    assert(RT_left(RTnode)==RT_NULL&&RT_right(RTnode)==RT_NULL);
+#endif
+
+#if DBG
+    assert(RT_oriClsIdx(RTnode)==0);
+#endif
+    if(RT_oriClsIdx(RTnode))
+      lp = (long*)SATfirstLit(RT_oriClsIdx(RTnode));
+    else
+
+      lp = RT_formula(RTnode) + cm->rm->fArray;
+    lp1 = lp;
+    for(i=0;i<RT_fSize(RTnode);i++,lp++){
+      if(*lp == DUMMY)
+	continue;
+      else{
+	allDummy = 0;
+#if DBG
+	assert(*lp>0);
+#endif
+      }
+      if(RT_oriClsIdx(RTnode))/*is CNF*/
+	node = SATgetNode(*lp);
+      else /*is AIG*/
+	node = *lp;
+
+      node = SATnormalNode(node);
+      if(SATflags(node)&IsGlobalVarMask)
+	continue;
+
+      if(SATclass(node)>cut){
+	IPTrue = 1;
+#if DBG
+	second = 1;
+#else
+	break;
+#endif
+      }
+#if DBG
+      else{
+	first = 1;
+      }
+#endif
+    }
+
+#if DBG
+    assert(!allDummy);
+    assert(!(first&&second));
+#endif
+
+
+    if(IPTrue){
+      RT_IPnode(RTnode) = bAig_One;
+      return bAig_One;
+    }
+
+    lp = lp1;
+    result = bAig_Zero;
+    for(i=0;i<RT_fSize(RTnode);i++,lp++){
+      if(RT_oriClsIdx(RTnode))/*is CNF*/
+	node = SATgetNode(*lp);
+      else /*is AIG*/
+	node = *lp;
+      node1 = SATnormalNode(node);
+      if(flags(node1)&IsGlobalVarMask){
+	result = PureSat_Or(manager,result,node);
+	cm->nodesArray = manager->NodesArray;
+      }
+    }
+
+    RT_IPnode(RTnode) = result;
+    return result;
+  } /*leaf*/
+
+  /*not leaf*/
+  else{
+
+#if DBG
+    assert(RT_left(RTnode)!=RT_NULL&&RT_right(RTnode)!=RT_NULL);
+#endif
+    left = sat_GenerateFwdIP(manager,cm,RT_left(RTnode),cut);
+    right = sat_GenerateFwdIP(manager,cm,RT_right(RTnode),cut);
+    if(RT_pivot(RTnode)<0){
+      int class_;
+      class_ = RT_pivot(RTnode)-DUMMY;
+#if DBG
+      assert(class_>0);
+#endif
+      if(class_>cut)
+	local=0;
+    }
+    else{
+      node = SATnormalNode(RT_pivot(RTnode));
+      if((SATflags(node)&IsGlobalVarMask)||
+	 (SATclass(node)>cut))
+	local = 0;
+    }
+    if(local==0){
+      result = PureSat_And(manager,left,right);
+
+    }
+    else{
+      result = PureSat_Or(manager,left,right);
+
+    }
+  }/* else{ not leaf*/
+
+  cm->nodesArray = manager->NodesArray;
+  RT_IPnode(RTnode) = result;
+  return result;
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generate interpolation backwardly]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+bAigEdge_t sat_GenerateBwdIP(bAig_Manager_t* manager,
+			     satManager_t *cm,
+			     RTnode_t RTnode,
+			     int cut)
+{
+  int i;
+  long node,node1, left, right, result, *lp, *lp1;
+  int IPTrue=0, local=1, allGV=1;
+  RTManager_t * rm = cm->rm;
+
+  manager->class_ = cut;
+
+  if(RT_flag(RTnode)&RT_VisitedMask){
+#if DBG
+    assert(RT_IPnode(RTnode)!=-1);
+#endif
+
+    return RT_IPnode(RTnode);
+  }
+#if DBG
+  assert(RT_IPnode(RTnode)==-1);
+#endif
+  RT_flag(RTnode) |= RT_VisitedMask;
+
+  if(RT_pivot(RTnode)==0){ /*leaf*/
+
+#if DBG
+    assert(RT_left(RTnode)==RT_NULL&&RT_right(RTnode)==RT_NULL);
+    assert(RT_oriClsIdx(RTnode)==0);
+#endif
+    result = bAig_Zero;
+    if(RT_oriClsIdx(RTnode))
+      lp = (long*)SATfirstLit(RT_oriClsIdx(RTnode));
+    else
+
+      lp = RT_formula(RTnode) + cm->rm->fArray;
+    lp1 = lp;
+    for(i=0;i<RT_fSize(RTnode);i++,lp++){
+      if(*lp == DUMMY)
+	continue;
+      else{
+	assert(*lp>0);
+      }
+      if(RT_oriClsIdx(RTnode))/*is CNF*/
+	node = SATgetNode(*lp);
+      else /*is AIG*/
+	node = *lp;
+      node = SATnormalNode(node);
+      if(SATflags(node)&IsGlobalVarMask)
+	continue;
+      else
+	allGV = 0;
+
+      if(SATclass(node)<=cut){
+	  IPTrue = 1;
+	  break;
+      }
+    }
+
+    if(IPTrue||allGV){
+      RT_IPnode(RTnode) = bAig_One;
+      return bAig_One;
+    }
+
+    lp = lp1;
+    for(i=0;i<RT_fSize(RTnode);i++,lp++){
+      if(RT_oriClsIdx(RTnode))/*is CNF*/
+	node = SATgetNode(*lp);
+      else /*is AIG*/
+	node = *lp;
+      node1 = SATnormalNode(node);
+      if(SATflags(node1)&IsGlobalVarMask){
+	result = PureSat_Or(manager,result,node);
+	cm->nodesArray = manager->NodesArray;
+      }
+    }
+    RT_IPnode(RTnode)  = result;
+    return result;
+  } /*leaf*/
+
+  /*not leaf*/
+  else{
+
+#if DBG
+    assert(RT_left(RTnode)!=RT_NULL&&RT_right(RTnode)!=RT_NULL);
+#endif
+    left = sat_GenerateBwdIP(manager,cm,RT_left(RTnode),cut);
+    right = sat_GenerateBwdIP(manager,cm,RT_right(RTnode),cut);
+    if(RT_pivot(RTnode)<0){
+      int class_;
+      class_ = RT_pivot(RTnode)-DUMMY;
+#if DBG
+      assert(class_>0);
+#endif
+      if(class_<=cut)
+	local=0;
+    }
+    else{
+      node = SATnormalNode(RT_pivot(RTnode));
+
+      if((SATflags(node)&IsGlobalVarMask)||
+	 (SATclass(node)<=cut))
+	local = 0;
+    }
+    if(local==0){
+      result = PureSat_And(manager,left,right);
+
+    }
+    else{
+      result = PureSat_Or(manager,left,right);
+
+    }
+  }/* else{ not leaf*/
+
+  cm->nodesArray = manager->NodesArray;
+  RT_IPnode(RTnode) = result;
+  return result;
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Reset resolution tree]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void ResetRTree(RTManager_t *rm)
+{
+  int i;
+  for(i=RTnodeSize;i<=rm->aSize;i+=RTnodeSize){
+    RT_IPnode(i) = -1;
+    RT_flag(i) &= RT_ResetVisitedMask;
+  }
+
+  return;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Free a resolution tree]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+RT_Free(RTManager_t *rm)
+{
+  FREE(rm->nArray);
+  FREE(rm->fArray);
+  FREE(rm);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Mark nodes in layer associated with property]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_MarkLayerProperty(satManager_t *cm,
+		      long v,
+		      int layer)
+{
+  satVariable_t *var = SATgetVariable(v);
+
+  if((v==bAig_NULL))
+    return;
+
+  if(!(SATflags(v)&CoiMask)){
+
+    return;
+  }
+
+  /*already assigned score*/
+  if(SATflags(v)&Visited2Mask){
+
+    return;
+  }
+
+  var->scores[0] = SCOREUNIT*layer;
+  var->scores[1] = SCOREUNIT*layer;
+  SATflags(v) |= Visited2Mask;
+
+
+  if((SATflags(v)&StateBitMask)&&
+     (SATclass(v)<=cm->Length)){
+
+    return;
+  }
+
+  sat_MarkLayerProperty(cm,SATleftChild(v),layer);
+  sat_MarkLayerProperty(cm,SATrightChild(v),layer);
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Mark nodes in layers associated normal visible latches]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void sat_MarkLayer(satManager_t *cm,
+		   long v,
+		   int layer)
+{
+  satVariable_t *var = SATgetVariable(v);
+
+  if((v==bAig_NULL))
+    return;
+
+  if(!(SATflags(v)&CoiMask)){
+
+    return;
+  }
+
+  /*already assigned score*/
+  if(SATflags(v)&Visited2Mask){
+
+    return;
+  }
+
+  var->scores[0] = SCOREUNIT*layer;
+  var->scores[1] = SCOREUNIT*layer;
+  SATflags(v) |= Visited2Mask;
+
+
+  if((SATflags(v)&StateBitMask)){
+
+    return;
+  }
+
+  sat_MarkLayer(cm,SATleftChild(v),layer);
+  sat_MarkLayer(cm,SATrightChild(v),layer);
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Mark nodes in layers associated with initial states]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+void sat_MarkLayerInitState(satManager_t *cm,
+			    long v,
+			    int layer)
+{
+  satVariable_t *var = SATgetVariable(v);
+
+  if((v==bAig_NULL))
+    return;
+
+  if(!(SATflags(v)&CoiMask)){
+
+    return;
+  }
+
+  /*already assigned score*/
+  if(SATflags(v)&Visited2Mask){
+
+    return;
+  }
+
+  var->scores[0] = SCOREUNIT*layer;
+  var->scores[1] = SCOREUNIT*layer;
+  SATflags(v) |= Visited2Mask;
+
+
+  /*if((SATflags(v)&StateBitMask)){
+    fprintf(vis_stderr,"%d ISV return\n",SATnormalNode(v));
+    return;
+    }*/
+
+  sat_MarkLayerInitState(cm,SATleftChild(v),layer);
+  sat_MarkLayerInitState(cm,SATrightChild(v),layer);
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Mark nodes in layers of a certain latch aig nodes]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void sat_MarkLayerLatch(satManager_t *cm,
+			long v,
+			int layer)
+{
+  satVariable_t *var = SATgetVariable(v);
+
+  if((v==bAig_NULL))
+    return;
+
+  if(!(SATflags(v)&CoiMask)){
+
+    return;
+  }
+
+  /*not assigned score yet*/
+  if(!(SATflags(v)&Visited2Mask)){
+    var->scores[0] = SCOREUNIT*layer;
+    var->scores[1] = SCOREUNIT*layer;
+    SATflags(v) |= Visited2Mask;
+
+  }
+  sat_MarkLayer(cm,SATleftChild(v),layer);
+  sat_MarkLayer(cm,SATrightChild(v),layer);
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [layer score initialization]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void sat_InitLayerScore(satManager_t * cm){
+  int i,j,k,layer;
+  long v;
+  st_table *table;
+  st_generator * stgen, *stgen1;
+  satVariable_t *var;
+
+  int objExist;
+  int inverted;
+  long *plit, nv;
+  int size;
+  int count0, count1;
+  satArray_t *ordered, *newOrdered;
+  array_t * layerArray = array_alloc(st_table *,cm->LatchLevel+1);
+
+  for(k=1;k<=cm->LatchLevel;k++){
+      cm->assignedArray[k]=0;
+      cm->numArray[k]=0;
+  }
+
+  cm->currentLevel = cm->LatchLevel;
+
+  for(i=satNodeSize;i<cm->nodesArraySize;i+=satNodeSize){
+    SATflags(i)&=ResetVisited2Mask;
+  }
+
+
+  sat_MarkLayerInitState(cm,cm->InitState,cm->LatchLevel);
+
+  sat_MarkLayerProperty(cm,cm->property,cm->LatchLevel);
+
+
+  st_foreach_item(cm->layerTable,stgen,&table,&layer)
+    array_insert(st_table *,layerArray,layer,table);
+
+  for(i=cm->LatchLevel;i>=1;i--){
+    table = array_fetch(st_table*,layerArray,i);
+    st_foreach_item(table,stgen1,&v,NIL(char*)){
+      sat_MarkLayerLatch(cm,v,i);
+
+    }
+  }
+
+  array_free(layerArray);
+
+  for(i=bAigNodeSize;i<cm->nodesArraySize;i+=bAigNodeSize){
+    if(SATflags(i)&Visited2Mask){
+      int layer;
+      SATflags(i)&=ResetVisited2Mask;
+      var = SATgetVariable(i);
+#if DBG
+      assert(var->scores[0]%SCOREUNIT==0);
+#endif
+      layer = var->scores[0]/SCOREUNIT;
+      cm->numArray[layer]++;
+    }
+  }
+
+  if(cm->option->verbose >= 2){
+    for(i=1;i<=cm->LatchLevel;i++){
+      fprintf(vis_stdout,"Level %d:%d\n",i,cm->numArray[i]);
+    }
+  }
+
+
+  ordered = cm->orderedVariableArray;
+  if(ordered == 0)
+    ordered = sat_ArrayAlloc(cm->initNumVariables);
+  else
+    ordered->num = 0;
+  cm->orderedVariableArray = ordered;
+
+  objExist = 0;
+
+
+  for(i=satNodeSize; i<cm->nodesArraySize; i+=satNodeSize) {
+    v = i;
+    if((SATflags(v) & IsBDDMask)) {
+      continue;
+    }
+    if((SATflags(v) & IsCNFMask)) {
+      size = SATnumLits(v);
+      plit = (long*)SATfirstLit(v);
+      for(j=0; j<size; j++, plit++) {
+	nv = SATgetNode(*plit);
+	inverted = !(SATisInverted(nv));
+	nv = SATnormalNode(nv);
+	var = SATgetVariable(nv);
+	var->litsCount[inverted]++;
+      }
+      continue;
+    }
+    if(!(SATflags(v) & CoiMask))	continue;
+    if(!(SATflags(v) & VisitedMask) && objExist)	continue;
+
+    if(SATvalue(v) != 2 && SATlevel(v) == 0)	continue;
+
+    count0 = count1 = SATnFanout(v);
+    if(count0 == 0 && SATleftChild(v) == 2 && SATrightChild(v) == 2) {
+      count0 = 0;
+      count1 = 0;
+    }
+    else if(SATleftChild(v) != 2) {
+      count0 += 2;
+      count1++;
+    }
+    else {
+      count0 += 3;
+      count1 += 3;
+    }
+
+    var = SATgetVariable(v);
+    var->litsCount[0] += count0;
+    var->litsCount[1] += count1;
+
+    sat_ArrayInsert(ordered, v);
+  }
+
+  for(i=0; i<cm->unitLits->num; i++) {
+    v = cm->unitLits->space[i];
+    v = SATnormalNode(v);
+    SATflags(v) |= NewMask;
+  }
+  if(cm->assertion) {
+    for(i=0; i<cm->assertion->num; i++) {
+      v = cm->assertion->space[i];
+      v = SATnormalNode(v);
+      SATflags(v) |= NewMask;
+    }
+  }
+
+  newOrdered = sat_ArrayAlloc((ordered->num) * 2);
+  size = ordered->num;
+  for(i=0; i<size; i++) {
+    v = ordered->space[i];
+    var = SATgetVariable(v);
+    var->lastLitsCount[0] = var->litsCount[0];
+    var->lastLitsCount[1] = var->litsCount[1];
+    var->scores[0] += var->lastLitsCount[0];
+    var->scores[1] += var->lastLitsCount[1];
+
+    if(SATflags(v) & NewMask);
+    else if(var->scores[0] == 0 && var->scores[1] == 0 && !(SATflags(v) & NewMask)) {
+      sat_ArrayInsert(cm->pureLits, (v));
+    }
+    else if(var->scores[0] == 0 && !(SATflags(v) & NewMask)) {
+      sat_ArrayInsert(cm->pureLits, (v));
+    }
+    else if(var->scores[1] == 0 && !(SATflags(v) & NewMask)) {
+      sat_ArrayInsert(cm->pureLits, SATnot(v));
+    }
+    else {
+      sat_ArrayInsert(newOrdered, v);
+      sat_ArrayInsert(newOrdered, (var->scores[0] > var->scores[1]) ? var->scores[0] : var->scores[1]);
+    }
+  }
+
+  for(i=0; i<cm->unitLits->num; i++) {
+    v = cm->unitLits->space[i];
+    v = SATnormalNode(v);
+    SATflags(v) &= ResetNewMask;
+  }
+  if(cm->assertion) {
+    for(i=0; i<cm->assertion->num; i++) {
+      v = cm->assertion->space[i];
+      v = SATnormalNode(v);
+      SATflags(v) &= ResetNewMask;
+    }
+  }
+
+  cm->orderedVariableArray = ordered;
+  size = newOrdered->num;
+  qsort(newOrdered->space, size>>1, sizeof(long)*2, ScoreCompare);
+
+  cm->currentVarPos = 0;
+  ordered->num = 0;
+  for(i=0; i<size; i++) {
+    v = newOrdered->space[i];
+    var = SATgetVariable(v);
+    var->pos = (i>>1);
+    sat_ArrayInsert(ordered, v);
+    i++;
+  }
+
+  sat_ArrayFree(newOrdered);
+
+  if(cm->option->verbose > 3)
+    sat_PrintScore(cm);
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Generate unsat proof in the form of resolution graph]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+void
+sat_GenerateCore_All(satManager_t * cm)
+{
+  int i,j,value;
+  long *lit, ante, node, tmp1;
+  int  count, inverted;
+  satLevel_t * d;
+  satArray_t *clauseArray = sat_ArrayAlloc(1);
+  int objectFlag;
+
+  long conflicting, ante2;
+  int nMarked,first;
+  long v,left,right,result,*lp,*tmpIP;
+  long *space,*tmp;
+  satArray_t *implied;
+  RTnode_t  tmprt;
+  int size = 0, *bLevel;
+  long *fdaLit=ALLOC(long,1);
+  boolean endnow;
+  RTManager_t * rm = cm->rm;
+
+  cm->status = 0;
+  count = 0;
+  d = SATgetDecision(0);
+  sat_ImplyArrayWithAnte(cm,d,cm->obj);
+  sat_ImplyArrayWithAnte(cm,d,cm->auxObj);
+  sat_ImplyArrayWithAnte(cm,d,cm->assertArray);
+
+
+
+  if(cm->status==0){
+  for(i=satNodeSize; i<cm->nodesArraySize; i+=satNodeSize){
+    node = i;
+    if((SATflags(node)&IsCNFMask)&&(SATnumLits(node)==1)){
+      lit = (long*)SATfirstLit(node);
+      tmp1 = SATgetNode(*lit);
+      inverted = SATisInverted(tmp1);
+      tmp1 = SATnormalNode(tmp1);
+
+
+      value = !inverted;
+      if(SATvalue(tmp1) < 2)	{
+	if(SATvalue(tmp1) == value)	continue;
+	else {
+	  cm->status = SAT_UNSAT;
+	  d->conflict = node;
+	  break;
+	}
+      }
+
+      SATvalue(tmp1) = !inverted;
+      SATmakeImplied(tmp1, d);
+      SATante(tmp1) = node;
+      if((SATflags(tmp1) & InQueueMask) == 0) {
+	sat_Enqueue(cm->queue, tmp1);
+	SATflags(tmp1) |= InQueueMask;
+      }
+
+    }
+  }
+  }
+
+
+  if(cm->status==0){
+    sat_ImplicationMain(cm, d);
+  }
+
+  if(d->conflict == 0) {
+    fprintf(vis_stderr,"There should be a conflict\n");
+    exit(0);
+  }
+
+  conflicting = d->conflict;
+  nMarked = 0;
+
+  sat_MarkNodeInConflict(
+	  cm, d, &nMarked, &objectFlag, bLevel, clauseArray);
+  /* Traverse implication graph backward*/
+  first = 1;
+  implied = d->implied;
+  space = implied->space+implied->num-1;
+
+
+
+  if(cm->option->coreGeneration){
+    /*if last conflict is CNF*/
+    if(SATflags(conflicting)&IsCNFMask){
+      /*is conflict CNF*/
+      if(SATflags(conflicting)&IsConflictMask){
+	 if(!st_lookup(cm->RTreeTable,(char*)conflicting,&tmprt)){
+	    fprintf(vis_stderr,"RTree node of conflict cnf %ld is not in RTreeTable\n",ante);
+	    exit(0);
+	  }
+	  else{
+	    rm->root = tmprt;
+#if PR
+	    fprintf(vis_stdout,"Get formula for CONFLICT CLAUSE:%d\n",ante);
+#endif
+	  }
+      }
+      /*CNF but not conflict*/
+      else{
+	rm->root = RTCreateNode(rm);
+
+	size = SATnumLits(conflicting);
+	RT_fSize(rm->root) = size;
+	lp = (long*)SATfirstLit(conflicting);
+	sat_BuildRT(cm,rm->root, lp, tmpIP,size,0);
+      }
+    }
+    /*if last conflict is AIG*/
+    else{
+      rm->root = RTCreateNode(rm);
+      node = SATnormalNode(conflicting);
+      left = SATleftChild(node);
+      right = SATrightChild(node);
+      result = PureSat_IdentifyConflict(cm,left,right,conflicting);
+      inverted = SATisInverted(left);
+      left = SATnormalNode(left);
+      left = inverted ? SATnot(left) : left;
+
+      inverted = SATisInverted(right);
+      right = SATnormalNode(right);
+      right = inverted ? SATnot(right) : right;
+
+      j = node;
+
+      if(result == 1){
+	tmp = ALLOC(long,3);
+	tmp[0] = left;
+	tmp[1] = SATnot(j);
+	size = 2;
+      }
+      else if(result == 2){
+	tmp = ALLOC(long,3);
+	tmp[0] = right;
+	tmp[1] = SATnot(j);
+	size = 2;
+      }
+      else if(result == 3){
+	tmp = ALLOC(long,4);
+	tmp[0] = SATnot(left);
+	tmp[1] = SATnot(right);
+	tmp[2] = j;
+	size = 3;
+      }
+      else{
+	fprintf(vis_stderr,"wrong returned result value, exit\n");
+	exit(0);
+      }
+
+      lp = tmp;
+      sat_BuildRT(cm,rm->root, lp, tmpIP,size,1);
+      FREE(tmp);
+    }
+  }
+
+
+  endnow = FALSE;
+  for(i=implied->num-1; i>=0; i--, space--) {
+    if(endnow)
+      break;
+    v = *space;
+    if(SATflags(v) & VisitedMask) {
+      SATflags(v) &= ResetVisitedMask;
+      --nMarked;
+
+      if(nMarked == 0 && (!first || i==0))  {
+	/*value = SATvalue(v);*/
+	*fdaLit = v^(!value);
+	sat_ArrayInsert(clauseArray, *fdaLit);
+	/*break;*/
+	endnow = TRUE;
+      }
+
+
+      if(cm->option->coreGeneration){
+	ante = SATante(v);
+	if(ante==0){
+	  if(!(st_lookup(cm->anteTable, (char *)SATnormalNode(v),&ante))){
+	    fprintf(vis_stderr,"ante = 0 and is not in anteTable %ld\n",v);
+	    exit(0);
+	  }
+	}
+
+	/*build non-leaf node*/
+	tmprt = RTCreateNode(rm);
+	RT_pivot(tmprt) = SATnormalNode(v);
+	RT_right(tmprt) = rm->root;
+	rm->root = tmprt;
+
+	if((SATflags(ante)&IsConflictMask)&&(SATflags(ante)&IsCNFMask)){
+	  if(!st_lookup(cm->RTreeTable,(char*)ante,&tmprt)){
+	    fprintf(vis_stderr,"RTree node of conflict cnf %ld is not in RTreeTable\n",ante);
+	    exit(0);
+	  }
+	  else{
+	    RT_left(rm->root) = tmprt;
+#if PR
+	    fprintf(vis_stdout,"Get formula for CONFLICT CLAUSE:%d\n",ante);
+#endif
+	  }
+	}
+	else{ /* if not conflict CNF*/
+	  /*left*/
+	  tmprt = RTCreateNode(rm);
+	  RT_left(rm->root) = tmprt;
+	  /*left is AIG*/
+	  if(!(SATflags(ante) & IsCNFMask)){
+	    /*generate formula for left*/
+	    tmp = ALLOC(long,3);
+	    value = SATvalue(v);
+	    node = SATnormalNode(v);
+	    node = value==1?node:SATnot(node);
+	    tmp[0] = node;
+
+	    size = 1;
+	    if(ante != SATnormalNode(v)){
+	      value = SATvalue(ante);
+	      node = SATnormalNode(ante);
+	      node = value==1?SATnot(node):node;
+	      tmp[1] = node;
+	      size++;
+	      ante2 = SATante2(v);
+	      if(ante2){
+		value = SATvalue(ante2);
+		node = SATnormalNode(ante2);
+		node = value==1?SATnot(node):node;
+		tmp[2] = node;
+		size++;
+	      }
+	    }
+
+	    lp = tmp;
+	    sat_BuildRT(cm,tmprt,lp,tmpIP,size,1);
+	    FREE(tmp);
+	  }
+	  /* left is CNF*/
+	  else{
+
+	    lp = (long*)SATfirstLit(ante);
+	    size = SATnumLits(ante);
+	    RT_fSize(tmprt) = size;
+	    sat_BuildRT(cm,tmprt, lp, tmpIP,size,0);
+	  }
+	} /*else{ // if not conflict CNF*/
+
+      }/*if(cm->option->coreGeneration){*/
+
+      sat_MarkNodeInImpliedNode(
+	cm, d, v, &nMarked, &objectFlag, bLevel, clauseArray);
+    }/*if(SATflags(v) & VisitedMask) {*/
+    first = 0;
+  }/*for(i=implied->num-1; i>=*/
+
+
+  if(cm->option->verbose >= 2)
+    fprintf(vis_stdout,"total # of RTree node:%ld\n",rm->aSize/RTnodeSize);
+
+  sat_ArrayFree(clauseArray);
+  FREE(fdaLit);
+  if(cm->option->arosat)
+    AS_Undo(cm,d);
+  else
+    sat_Undo(cm,d);
+  cm->status = SAT_UNSAT;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Merge level for Arosat]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+void sat_ASmergeLevel(satManager_t *cm)
+{
+  int base;
+  long v;
+  satVariable_t *var;
+  int *assignedArray = cm->assignedArray;
+  int * numArray = cm->numArray,level=0;
+
+  if(cm->option->verbose >= 2)
+    fprintf(vis_stdout,"MERGE LEVEL\n");
+  while(cm->LatchLevel>0){
+  if(cm->option->verbose >= 2)
+    fprintf(vis_stdout,"Merge level %d and %d\n",cm->LatchLevel, cm->LatchLevel-1);
+    level++;
+    cm->LatchLevel--;
+    if(cm->numArray[cm->LatchLevel]>0)
+      break;
+  }
+  if(cm->option->verbose >= 2)
+    fprintf(vis_stdout,"After Merge,Latch level:%d\n",cm->LatchLevel);
+#if DBG
+  assert(cm->LatchLevel>0);
+#endif
+
+  for(v=satNodeSize;v<cm->initNodesArraySize;v+=satNodeSize){
+    if(!SATflags(v)&CoiMask)
+      continue;
+    var = SATgetVariable(v);
+    base = var->scores[0]/SCOREUNIT;
+    if(base==cm->LatchLevel+level){
+      var->scores[0] = cm->LatchLevel*SCOREUNIT + var->scores[0]%SCOREUNIT;
+      var->scores[1] = cm->LatchLevel*SCOREUNIT + var->scores[1]%SCOREUNIT;
+    }
+  }
+  assignedArray[cm->LatchLevel]+=assignedArray[cm->LatchLevel+level];
+  numArray[cm->LatchLevel]+=numArray[cm->LatchLevel+level];
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [CNF based conflict enforcing]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+int sat_CE_CNF(
+	satManager_t *cm,
+	satLevel_t *d,
+	int v,
+	satArray_t *wl)
+{
+  long size, i, *space;
+  long lit, *plit, dir;
+  long nv, tv, *oplit, *wlit;
+  int isInverted, value;
+  long inverted, clit;
+  satStatistics_t *stats;
+  satOption_t *option;
+  satQueue_t *Q;
+
+  size = wl->num;
+  space = wl->space;
+  Q = cm->queue;
+  stats = cm->each;
+  option = cm->option;
+
+  for(i=0; i<size; i++) {
+    plit = (long*)space[i];
+
+    if(plit == 0 || *plit == 0) {
+
+      continue;
+    }
+
+    lit = *plit;
+    dir = SATgetDir(lit);
+    oplit = plit;
+
+    while(1) {
+      oplit += dir;
+      if(*oplit <=0) {
+	if(dir == 1) nv =- (*oplit);
+	if(dir == SATgetDir(lit)) {
+	  oplit = plit;
+	  dir = -dir;
+	  continue;
+	}
+
+	tv = SATgetNode(*wlit);
+	isInverted = SATisInverted(tv);
+	tv = SATnormalNode(tv);
+	value = SATvalue(tv) ^ isInverted;
+	if(value == 0) {  /* conflict happens*/
+
+	  return CONFLICT;
+	}
+	else if(value > 1) { /* implication*/
+	  /*implication can only be made on the other wl*/
+
+	  break;
+	}
+
+	break;
+      }
+
+      clit = *oplit;
+
+      tv = SATgetNode(clit);
+      inverted = SATisInverted(tv);
+      tv = SATnormalNode(tv);
+      value = SATvalue(tv) ^ inverted;
+
+      if(SATisWL(clit)) { /* found other watched literal*/
+	wlit = oplit;
+	/*a little diff from zchaff, if otherwl==1, break*/
+	if(value == 1)	{
+	  break;
+	}
+	/*since it is otherwl, it can't be zero. Here it is unknow*/
+	continue;
+      }
+
+      if(value == 0)
+	continue;
+
+      /*now it is 1 or unknow*/
+      break;
+    }/*while(1)*/
+  }/*for*/
+  return NO_CONFLICT;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Conflict enforcing]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_CE(satManager_t *cm,
+	    satLevel_t *d,
+	    long v,
+	    int dfs,
+	    int value)
+{
+  long value1,*fan;
+  long cur, i, size;
+  long left, right;
+  satVariable_t *var;
+  satArray_t *wlArray;
+
+  long enforce=0;
+
+  v = SATnormalNode(v);
+
+  var = SATgetVariable(v);
+
+  wlArray = var->wl[value^1];
+
+  /*need recovery*/
+  SATvalue(v) = value;
+
+  /* implcation on CNF*/
+  if(wlArray && wlArray->size) {
+    if(sat_CE_CNF(cm, d, v, wlArray)==CONFLICT){
+      enforce = 1;
+    }
+  }
+
+  /*need recovery*/
+  SATvalue(v) = value;
+
+  if(enforce==0){
+    /* implication on AIG*/
+    fan = SATfanout(v);
+    size = SATnFanout(v);
+    for(i=0; i<size; i++, fan++) {
+      cur = *fan;
+      cur = cur >> 1;
+      cur = SATnormalNode(cur);
+      left = SATleftChild(cur);
+      right = SATrightChild(cur);
+      value1 = SATgetValue(left, right, cur);
+      if(value1==1||value1==5||value1==9||value1==13||value1==17
+	 ||value1==20||value1==33||value1==49){
+	/*fprintf(vis_stdout,"AIG Output enforce\n");*/
+	enforce=1;
+	break;
+      }
+    }
+  }
+
+  if(enforce==0){
+    left = SATleftChild(v);
+    right = SATrightChild(v);
+    if(left!=2&&right!=2){
+      value1 = SATgetValue(left, right, v);
+      if(value1==1||value1==5||value1==9||value1==13||value1==17
+	 ||value1==20||value1==33||value1==49){
+	/*fprintf(vis_stdout,"AIG Children enforce\n");*/
+	enforce=1;
+      }
+    }
+  }
+
+
+  SATvalue(v)=2;
+
+  return enforce;
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Decision procedure for Arosat]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+
+int sat_ASDec(satManager_t *cm,
+	      satLevel_t *d,
+	      long v)
+{
+  int dfs;
+  int *numArray,*assignedArray;
+  satVariable_t *var=SATgetVariable(v);
+
+  assignedArray = cm->assignedArray;
+  numArray = cm->numArray;
+
+  v = SATnormalNode(v);
+  dfs = var->scores[0]/SCOREUNIT;
+
+#if DBG
+
+  assert(dfs==cm->LatchLevel);
+  assert(!(SATflags(SATnormalNode(v)) & InQueueMask));
+  assert(SATvalue(SATnormalNode(v))==2);
+#endif
+  if(!(SATflags(SATnormalNode(v))&AssignedMask)){
+    SATflags(SATnormalNode(v))|=AssignedMask;
+    assignedArray[dfs]++;
+    /* if(dfs==cm->OriLevel)
+    //  fprintf(vis_stdout,"Assign Level %d: %d dfs=%d assArray[%d]=%d\n",
+    //     d->level,v,dfs,dfs,cm->assignedArray[dfs]);*/
+
+    if(cm->assignedArray[dfs]==cm->numArray[dfs])
+      sat_ASmergeLevel(cm);
+    /*fprintf(vis_stdout,"Decisionlevel:%d: %d dfs=%d,assArray[%d]=%d, numArray[%d]=%d\n",
+      //      d->level,v,dfs,dfs,assignedArray[dfs],dfs,numArray[dfs]);*/
+  }
+  return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Implication procedure for Arosat]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_ASImp(satManager_t *cm,
+	  satLevel_t *d,
+	  long v,
+	  int value)
+{
+  int dfs;
+  long tmpv;
+  int *numArray,*assignedArray;
+  satVariable_t *var=SATgetVariable(v);
+
+  assignedArray = cm->assignedArray;
+  numArray = cm->numArray;
+
+  v = SATnormalNode(v);
+
+#if DBG
+  assert(SATvalue(v)==2);
+#endif
+  dfs = var->scores[0]/SCOREUNIT;
+
+
+  if(dfs==cm->LatchLevel){
+    if(!(SATflags(SATnormalNode(v))&AssignedMask)){
+
+      SATflags(SATnormalNode(v))|=AssignedMask;
+      assignedArray[dfs]++;
+
+#if DBG
+      assert(assignedArray[dfs]<=numArray[dfs]);
+#endif
+      if(cm->assignedArray[dfs]==cm->numArray[dfs])
+	sat_ASmergeLevel(cm);
+
+    }
+
+    return 0;
+  }
+  else{
+    /*if conflict enforcing*/
+    if(sat_CE(cm,d,v,dfs,value)){
+
+      if(!(SATflags(SATnormalNode(v))&AssignedMask)){
+	SATflags(SATnormalNode(v))|=AssignedMask;
+	assignedArray[dfs]++;
+
+#if DBG
+	assert(assignedArray[dfs]<=numArray[dfs]);
+#endif
+
+      }
+
+      return 0;
+    }
+    /*else implication is prohibited*/
+    else{
+
+#if DBG
+      assert(value==0||value==1);
+#endif
+      if(value==0)
+	tmpv = -1;
+      else
+	tmpv = 1;
+      SATgetVariable(v)->RecVal = tmpv;
+
+      return 1;
+    }
+  }
+  return 0;
+}
Index: vis_dev/vis-2.3/src/sat/satDebug.c
===================================================================
--- vis_dev/vis-2.3/src/sat/satDebug.c	(revision 14)
+++ vis_dev/vis-2.3/src/sat/satDebug.c	(revision 14)
@@ -0,0 +1,921 @@
+/**CFile***********************************************************************
+
+  FileName    [satDebug.c]
+
+  PackageName [sat]
+
+  Synopsis    [Routines for various debug function.]
+
+  Author      [HoonSang Jin]
+
+  Copyright [ This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+
+******************************************************************************/
+
+#include "satInt.h"
+
+static char rcsid[] UNUSED = "$Id: satDebug.c,v 1.14 2009/04/11 18:26:37 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+static int numCompareInt(const void *x, const void *y);
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Print node infomation]
+
+  Description [ Print node infomation]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_PrintNode(
+	satManager_t *cm,
+	long v)
+{
+int inverted, i, size;
+long ante, cur, *fan, *plit;
+satVariable_t *var;
+satArray_t *wl;
+
+  inverted = SATisInverted(v);
+  v = SATnormalNode(v);
+  if(SATflags(v) & IsCNFMask) {
+    size = SATnumLits(v);
+    fprintf(cm->stdOut, "CNF %6ld (%4ld) U(%ld)", v, SATnumConflict(v), SATconflictUsage(v));
+    sat_PrintFlag(cm, v);
+    fprintf(cm->stdOut, "    ");
+    for(i=0, plit = (long*)SATfirstLit(v); i<size; i++, plit++) {
+      if(i!=0 && i%5 == 0)
+	fprintf(cm->stdOut, "\n    ");
+      sat_PrintLiteral(cm, *plit);
+    }
+    fprintf(cm->stdOut, "\n");
+  }
+  else if(SATflags(v) & IsBDDMask) {
+  }
+  else {
+    fprintf(cm->stdOut, "AIG ");
+    sat_PrintFlag(cm, SATnormalNode(v));
+    fprintf(cm->stdOut, "    ");
+    sat_PrintNodeAlone(cm, v);
+    sat_PrintNodeAlone(cm, SATleftChild(v));
+    sat_PrintNodeAlone(cm, SATrightChild(v));
+    fprintf(cm->stdOut, "\n");
+    size = SATnFanout(v);
+    fprintf(cm->stdOut, "%4d ", size);
+    for(i=0, fan=SATfanout(v); i<size; i++, fan++) {
+      cur = (*fan) >>1;
+      fprintf(cm->stdOut, "%6ld ", cur);
+    }
+    fprintf(cm->stdOut, "\n");
+
+    fprintf(cm->stdOut, "  canonocal : %ld\n", sat_GetCanonical(cm, v));
+    if(cm->variableArray && SATvalue(v) < 2) {
+      ante = SATante(v);
+      if(SATflags(ante) & IsCNFMask) {
+	fprintf(cm->stdOut, "  ante CNF  : %ld\n", SATante(v));
+      }
+      else{
+	fprintf(cm->stdOut, "  ante      : %ld\n", SATante(v));
+	fprintf(cm->stdOut, "  ante2     : %ld\n", SATante2(v));
+      }
+    }
+
+    if(cm->variableArray) {
+    var = SATgetVariable(v);
+    wl = var->wl[0];
+    if(wl && wl->num) {
+      fprintf(cm->stdOut, "  0 wl : ");
+      for(i=0; i<wl->num; i++) {
+	plit = (long *)(wl->space[i]);
+	if(plit == 0)	continue;
+	fprintf(cm->stdOut, "%ld", (*plit)>>2);
+	while(1) {
+	  plit++;
+	  if(*plit < 0)	break;
+	}
+	fprintf(cm->stdOut, "(%ld) ", -(*plit));
+      }
+      fprintf(cm->stdOut, "\n");
+    }
+    wl = var->wl[1];
+    if(wl && wl->num) {
+      fprintf(cm->stdOut, "  1 wl : ");
+      for(i=0; i<wl->num; i++) {
+	plit = (long *)(wl->space[i]);
+	if(plit == 0)	continue;
+	fprintf(cm->stdOut, "%ld", (*plit)>>2);
+	while(1) {
+	  plit++;
+	  if(*plit < 0)	break;
+	}
+	fprintf(cm->stdOut, "(%ld) ", -(*plit));
+      }
+      fprintf(cm->stdOut, "\n");
+    }
+    }
+  }
+  fflush(cm->stdOut);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Print flag infomation]
+
+  Description [ Print flag infomation]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_PrintFlag(satManager_t *cm, long v)
+{
+int flag;
+
+  flag = SATflags(SATnormalNode(v));
+  fprintf(cm->stdOut, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
+	  (flag & CoiMask)           ? 'C' : ' ',
+	  (flag & VisitedMask)       ? 'V' : ' ',
+	  (flag & NewMask)           ? 'N' : ' ',
+	  (flag & InQueueMask)       ? 'Q' : ' ',
+	  (flag & ObjMask)           ? 'o' : ' ',
+	  (flag & NonobjMask)        ? 'n' : ' ',
+	  (flag & IsSystemMask)      ? 'S' : ' ',
+	  (flag & IsConflictMask)    ? 'c' : ' ',
+	  (flag & InUseMask)         ? 'U' : ' ',
+	  (flag & StaticLearnMask)   ? 's' : ' ',
+	  (flag & StateBitMask)      ? 'T' : ' ',
+	  (flag & IsBlockingMask)    ? 'B' : ' ',
+	  (flag & IsFrontierMask)    ? 'F' : ' ',
+	  (flag & LeafNodeMask)      ? 'L' : ' ');
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Print node infomation in the form of (id'@level = value)]
+
+  Description [ Print node infomation in the form of (id'@level = value)]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_PrintNodeAlone(satManager_t *cm, long v)
+{
+int value, level, inverted;
+
+  inverted = SATisInverted(v);
+  v = SATnormalNode(v);
+  value = SATvalue(v);
+  level = value>1 ? -1 : (cm->variableArray ? SATlevel(v) : -1);
+  fprintf(cm->stdOut, "%6ld%c@%d=%c%c ",
+	  v, inverted ? '\'' : ' ', level,
+	  SATgetValueChar(value),
+	  (SATflags(v)&ObjMask) ? '*' : ' ');
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Print literal information.]
+
+  Description [ Print literal information.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_PrintLiteral(satManager_t *cm, long lit)
+{
+int value, level, inverted;
+long v;
+
+  v = SATgetNode(lit);
+  inverted = SATisInverted(v);
+  v = SATnormalNode(v);
+  value = SATvalue(v);
+  level = value>1 ? -1 : SATlevel(v);
+  fprintf(cm->stdOut, "%6ld%c@%d=%c%c ",
+	  v, inverted ? '\'' : ' ', level, SATgetValueChar(value),
+	  SATisWL(lit) ? '*' : ' ');
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Print implication graph ]
+
+  Description [ Print implication graph.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_PrintImplicationGraph(
+	satManager_t *cm,
+	satLevel_t *d)
+{
+long ante, ante2, v;
+int i;
+satArray_t *implied;
+
+  fprintf(cm->stdOut, "++++++++++++++++++++++++++++++++\n");
+  fprintf(cm->stdOut, "* Level %d %ld->%ld\n",
+		d->level, d->decisionNode, SATvalue(d->decisionNode));
+  fprintf(cm->stdOut, "++++++++++++++++++++++++++++++++\n");
+
+  implied = d->implied;
+  for(i=0; i<implied->num; i++) {
+    v = implied->space[i];
+    ante = SATante(v);
+    if(SATflags(ante) & IsCNFMask) {
+      sat_PrintNodeAlone(cm, v);
+      fprintf(cm->stdOut, "<= %6ld %c(%cCNF)\n",
+	      ante, (SATflags(ante) & ObjMask) ? '*' : ' ',
+	      (SATflags(ante) & IsConflictMask) ? 'c' : ' ');
+      sat_PrintNode(cm, ante);
+    }
+    else if(SATflags(ante) & IsBDDMask) {
+    }
+    else {
+      sat_PrintNodeAlone(cm, v);
+      fprintf(cm->stdOut, "<= ");
+      sat_PrintNodeAlone(cm, ante);
+      ante2 = SATante2(v);
+      if(ante2)
+	sat_PrintNodeAlone(cm, ante2);
+      fprintf(cm->stdOut, "\n");
+    }
+  }
+  fflush(cm->stdOut);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Check flags then is used for conflict analysis. ]
+
+  Description [ Check flags then is used for conflict analysis.
+		After conflict analysis, these flags has to be reset ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_CheckFlagsOnConflict(satManager_t *cm)
+{
+long i;
+
+  for(i=satNodeSize; i<cm->nodesArraySize; i+=satNodeSize) {
+    if(!(SATflags(i) & CoiMask))
+      continue;
+
+    if(SATflags(i) & VisitedMask || SATflags(i) & NewMask) {
+      fprintf(cm->stdOut, "%s ERROR : %ld has flag\n",
+	      cm->comment, i);
+      sat_PrintNode(cm, i);
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Print score]
+
+  Description [ Print score]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_PrintScore(satManager_t *cm)
+{
+int i;
+long v;
+satArray_t *ordered;
+satVariable_t *var;
+
+  fprintf(cm->stdOut, "------------Print Score-----------\n");
+  ordered = cm->orderedVariableArray;
+  for(i=0; i<ordered->num; i++) {
+    v = ordered->space[i];
+    var = SATgetVariable(v);
+    fprintf(cm->stdOut, "%5ld : %3d %3d\n", v, var->scores[0], var->scores[1]);
+  }
+  fflush(cm->stdOut);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Print dot file of implication graph]
+
+  Description [ Print dot file of implication graph ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_PrintDotForConflict(
+	satManager_t *cm,
+	satLevel_t *d,
+	long conflict,
+	int includePreviousLevel)
+{
+satArray_t *root;
+long left, right, nv;
+int inverted, size, value, i;
+long *plit;
+satOption_t *option;
+
+  root = sat_ArrayAlloc(8);
+
+  conflict = d->conflict;
+  inverted = SATisInverted(conflict);
+  conflict = SATnormalNode(conflict);
+
+  option = cm->option;
+  if(SATflags(conflict) & IsCNFMask) {
+    size = SATnumLits(conflict);
+    for(i=0, plit=(long*)SATfirstLit(conflict); i<size; i++, plit++) {
+      nv = SATgetNode(*plit);
+      if(d->level == SATlevel(nv))
+	sat_ArrayInsert(root, nv);
+    }
+  }
+  else {
+    value = SATvalue(conflict);
+    if(value == 1) {
+      if(d->level == SATlevel(conflict))
+	sat_ArrayInsert(root, conflict);
+
+      left = SATleftChild(conflict);
+      inverted = SATisInverted(left);
+      left = SATnormalNode(left);
+      value = SATvalue(left) ^ inverted;
+      if(value == 0) {
+	if(d->level == SATlevel(left))
+	  sat_ArrayInsert(root, left);
+      }
+      else {
+	right = SATrightChild(conflict);
+	inverted = SATisInverted(right);
+	right = SATnormalNode(right);
+	value = SATvalue(right) ^ inverted;
+	if(value == 0) {
+	  if(d->level == SATlevel(right))
+	    sat_ArrayInsert(root, right);
+	}
+      }
+    }
+    else if(value == 0) {
+      left = SATleftChild(conflict);
+      right = SATrightChild(conflict);
+      if(d->level == SATlevel(conflict))
+	sat_ArrayInsert(root, conflict);
+      if(d->level == SATlevel(left))
+	sat_ArrayInsert(root, left);
+      if(d->level == SATlevel(right))
+	sat_ArrayInsert(root, right);
+    }
+  }
+
+  sat_PrintDotForImplicationGraph(cm, d, root, includePreviousLevel);
+  sat_ArrayFree(root);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Print dot file of whole implication graph]
+
+  Description [ Print dot file of whole implication graph ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_PrintDotForWholeGraph(
+	satManager_t *cm,
+	satLevel_t *d,
+	int includePreviousLevel)
+{
+satArray_t *root, *implied;
+int v, i;
+
+  root = sat_ArrayAlloc(8);
+  implied = d->implied;
+  for(i=implied->num-1; i>=0; i--) {
+    v = implied->space[i];
+    sat_ArrayInsert(root, v);
+  }
+  sat_PrintDotForImplicationGraph(cm, d, root, includePreviousLevel);
+  sat_ArrayFree(root);
+}
+/**Function********************************************************************
+
+  Synopsis    [ Print dot file of implication graph]
+
+  Description [ Print dot file of implication graph ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_PrintDotForImplicationGraph(
+	satManager_t *cm,
+	satLevel_t *d,
+	satArray_t *root,
+	int includePreviousLevel)
+{
+char name[1024];
+long v, nv, *plit, lit;
+int i, j, size;
+int inverted;
+long ante, ante2;
+st_table *table;
+FILE *fp;
+satArray_t *implied;
+
+
+  for(i=0; i<root->num; i++) {
+    v = root->space[i];
+    v  = SATnormalNode(v);
+    SATflags(v) |= VisitedMask;
+  }
+
+  sprintf(name, "%d_%ld_%d_%d.dot",
+	  d->level, d->decisionNode, cm->each->nDecisions, includePreviousLevel);
+  fp = fopen(name, "w");
+
+  fprintf(fp, "digraph \"AndInv\" {\n  rotate=90;\n");
+  fprintf(fp, "  margin=0.5;\n  label=\"AndInv\";\n");
+  fprintf(fp, "  size=\"10,7.5\";\n  ratio=\"fill\";\n");
+
+  table = st_init_table(st_numcmp, st_numhash);
+  implied = d->implied;
+  for(i=implied->num-1; i>=0; i--) {
+    v = implied->space[i];
+    if(!(SATflags(v) & VisitedMask)) continue;
+    if((SATflags(v) & NewMask)) continue;
+
+    st_insert(table, (char *)(long)v, (char *)(long)v);
+
+    ante = SATante(v);
+    if(SATflags(ante) & IsCNFMask) {
+      size = SATnumLits(ante);
+      for(j=0, plit=(long *)SATfirstLit(ante); j<size; j++) {
+	lit = plit[j];
+	nv = SATgetNode(lit);
+	inverted = SATisInverted(nv);
+	nv = SATnormalNode(nv);
+	if(nv == v)	continue;
+
+	st_insert(table, (char *)nv, (char *)nv);
+	if(SATlevel(nv) == d->level) {
+	  fprintf(fp,"%ld.%d -> %ld.%d [color = red];\n",
+		  nv, SATlevel(nv), v, SATlevel(v));
+	  SATflags(nv) |= VisitedMask;
+	}
+	else if(includePreviousLevel) {
+	  fprintf(fp,"%ld.%d -> %ld.%d [color = black];\n",
+		  nv, SATlevel(nv), v, SATlevel(v));
+	}
+      }
+    }
+    else {
+      fprintf(fp,"%ld.%d  [label=\"%ld.%d \"];\n", v, SATlevel(v), v, SATlevel(v));
+      ante2 = SATnormalNode(SATante2(v));
+      if(ante2) {
+	st_insert(table, (char *)ante2, (char *)ante2);
+	if(SATlevel(ante2) == d->level) {
+	  fprintf(fp,"%ld.%d -> %ld.%d [color = red];\n", ante2, SATlevel(ante2), v, SATlevel(v));
+	  SATflags(ante2) |= VisitedMask;
+	}
+	else if(includePreviousLevel && SATlevel(ante2)>=0) {
+	  fprintf(fp,"%ld.%d -> %ld.%d [color = black];\n", ante2, SATlevel(ante2), v, SATlevel(v));
+	}
+      }
+
+      if(ante) {
+	st_insert(table, (char *)ante, (char *)ante);
+	if(SATlevel(ante) == d->level) {
+	  fprintf(fp,"%ld.%d -> %ld.%d [color = red];\n", ante, SATlevel(ante), v, SATlevel(v));
+	  SATflags(ante) |= VisitedMask;
+	}
+	else if(includePreviousLevel && SATlevel(ante)>=0) {
+	  fprintf(fp,"%ld.%d -> %ld.%d [color = black];\n", ante, SATlevel(ante), v, SATlevel(v));
+	}
+      }
+    }
+    SATflags(v) |= NewMask;
+  }
+  fprintf(fp, "}\n");
+  fclose(fp);
+
+  for(i=implied->num-1; i>=0; i--) {
+    v = implied->space[i];
+    SATflags(v) &= ResetNewVisitedMask;
+  }
+  for(i=0; i<root->num; i++) {
+    v = root->space[i];
+    SATflags(v) &= ResetVisitedMask;
+  }
+
+  st_free_table(table);
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Check whether the given conflict clauses are
+		objective independent ]
+
+  Description [ Check whether the given conflict clauses are
+		objective independent ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_CheckNonobjConflictClause(
+	satManager_t *cm,
+	long v)
+{
+int i, size, inverted;
+long *plit, nv;
+satLevel_t *d;
+
+  d = 0;
+  size = SATnumLits(v);
+  for(i=0, plit = (long*)SATfirstLit(v); i<size; i++, plit++) {
+    nv = SATgetNode(*plit);
+    inverted = SATisInverted(nv);
+    nv = SATnormalNode(nv);
+
+    d = sat_AllocLevel(cm);
+    d->decisionNode = nv;
+
+    SATvalue(nv) = inverted;
+    SATmakeImplied(nv, d);
+
+    sat_Enqueue(cm->queue, nv);
+    SATflags(nv) |= InQueueMask;
+
+    sat_ImplicationMain(cm, d);
+    if(d->conflict)	break;
+  }
+
+  if(d->conflict == 0) {
+    fprintf(cm->stdOut, "%s ERROR : %ld does not result in conflict\n",
+	    cm->comment, v);
+    sat_PrintNode(cm, v);
+  }
+  sat_Backtrack(cm, -1);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Check whether the given conflict clauses are
+		objective independent ]
+
+  Description [ Check whether the given conflict clauses are
+		objective independent ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_CheckNonobjUnitClause(
+	satManager_t *cm)
+{
+int v, i;
+int inverted;
+satLevel_t *d;
+satArray_t *arr;
+
+  arr = cm->nonobjUnitLitArray;
+
+  for(i=0; i<arr->num; i++) {
+    v = arr->space[i];
+    inverted = SATisInverted(v);
+    v = SATnormalNode(v);
+
+    d = sat_AllocLevel(cm);
+    d->decisionNode = v;
+
+    SATvalue(v) = inverted;
+    SATmakeImplied(v, d);
+
+    sat_Enqueue(cm->queue, v);
+    SATflags(v) |= InQueueMask;
+
+    sat_ImplicationMain(cm, d);
+    if(d->conflict == 0) {
+      fprintf(cm->stdOut, "%s ERROR : %d unit literal does not result in conflict\n",
+	    cm->comment, v);
+    }
+    sat_Backtrack(cm, -1);
+
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Check initial condition of SAT solving ]
+
+  Description [ Check initial condition of SAT solving ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_CheckInitialCondition(
+	satManager_t *cm)
+{
+long i;
+
+  for(i=satNodeSize; i<cm->nodesArraySize; i+=satNodeSize) {
+    if(!(SATflags(i) & CoiMask))
+      continue;
+
+    if(SATvalue(i) != 2) {
+      fprintf(cm->stdOut, "%s ERROR : %ld has value %ld\n",
+	      cm->comment, i, SATvalue(i));
+    }
+    if(SATflags(i) & VisitedMask || SATflags(i) & NewMask) {
+      fprintf(cm->stdOut, "%s ERROR : %ld has flag\n",
+	      cm->comment, i);
+      sat_PrintNode(cm, i);
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Check whether inverse assignment of literals
+		in conflict clause create conflict]
+
+  Description [ Check whether inverse assignment of literals
+		in conflict clause create conflict]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_CheckConflictClause(
+	satManager_t *cm,
+	satArray_t *clauseArray)
+{
+satArray_t *decisionArray;
+satLevel_t *d;
+int i, value, inverted;
+long v;
+int conflictFlag, tvalue;
+
+  decisionArray = sat_ArrayAlloc(cm->currentDecision);
+  for(i=1; i<=cm->currentDecision; i++) {
+    v = cm->decisionHead[i].decisionNode;
+    value = SATvalue(v);
+    sat_ArrayInsert(decisionArray, v^(!value));
+  }
+
+  sat_Backtrack(cm, 0);
+
+  conflictFlag = 0;
+  for(i=0; i<clauseArray->num; i++) {
+    v = clauseArray->space[i];
+    inverted = SATisInverted(v);
+    v = SATnormalNode(v);
+
+    d = sat_AllocLevel(cm);
+    d->decisionNode = v;
+
+    value = !inverted;
+    tvalue = SATvalue(v);
+    if(tvalue < 2 && tvalue !=  value) {
+      fprintf(cm->stdOut, "ERROR : Early conflict condition detect\n");
+      break;
+    }
+    SATvalue(v) = value;
+    SATmakeImplied(v, d);
+
+    sat_Enqueue(cm->queue, v);
+    SATflags(v) |= InQueueMask;
+
+    sat_ImplicationMain(cm, d);
+
+    if(d->conflict) {
+      conflictFlag = 1;
+      break;
+    }
+  }
+
+  if(conflictFlag == 0) {
+    fprintf(cm->stdOut, "ERROR : Wrong conflict clause\n");
+    sat_PrintClauseArray(cm, clauseArray);
+  }
+
+  sat_Backtrack(cm, 0);
+
+  conflictFlag = 0;
+  for(i=0; i<decisionArray->num; i++) {
+    v = decisionArray->space[i];
+    inverted = SATisInverted(v);
+    v = SATnormalNode(v);
+
+    d = sat_AllocLevel(cm);
+    d->decisionNode = v;
+
+    value = !inverted;
+    SATvalue(v) = value;
+    SATmakeImplied(v, d);
+
+    sat_Enqueue(cm->queue, v);
+    SATflags(v) |= InQueueMask;
+
+    sat_ImplicationMain(cm, d);
+    if(d->conflict) {
+      conflictFlag = 1;
+    }
+  }
+  if(conflictFlag == 0) {
+    fprintf(cm->stdOut, "ERROR : Can't produce conflict\n");
+    exit(0);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Print clause array ]
+
+  Description [ Print clause array ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_PrintClauseArray(
+	satManager_t *cm,
+	satArray_t *clauseArray)
+{
+int i, inverted;
+long v;
+
+  fprintf(cm->stdOut, "    ");
+  for(i=0; i<clauseArray->num; i++) {
+    v = clauseArray->space[i];
+    inverted = SATisInverted(v);
+    v = SATnormalNode(v);
+    if(i!=0 && i%5 == 0)
+      fprintf(cm->stdOut, "\n    ");
+    sat_PrintNodeAlone(cm, v);
+  }
+  fprintf(cm->stdOut, "\n");
+  fflush(cm->stdOut);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Print profile of the number of conflict on each clause]
+
+  Description [ Print profile of the number of conflict on each clause]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_PrintProfileForNumConflict(satManager_t *cm)
+{
+char filename[1024];
+FILE *fout;
+int i, index;
+satArray_t *arr;
+long count;
+long total, part;
+long v;
+long maxValue;
+
+
+  sprintf(filename, "nConflict.dat");
+  fout = fopen(filename, "w");
+  index = 1;
+  maxValue = 0;
+  arr = sat_ArrayAlloc(1024);
+  for(v=satNodeSize; v<cm->nodesArraySize; v+=satNodeSize) {
+    if(!(SATflags(v) & IsCNFMask))	continue;
+    if(SATnumConflict(v) == 0)	continue;
+    if(SATnumConflict(v) > maxValue)
+      maxValue = SATnumConflict(v);
+    sat_ArrayInsert(arr, SATnumConflict(v));
+  }
+
+  qsort(arr->space, arr->num, sizeof(int), numCompareInt);
+  total = 0;
+  part = 0;
+  for(i=0; i<arr->num; i++) {
+    count = arr->space[i];
+    if(count == 0)	continue;
+    total += count;
+    if(count > 1) {
+      part += count;
+    }
+    fprintf(fout, "%d %ld\n", i, count);
+  }
+  index = i;
+  sat_ArrayFree(arr);
+  fclose(fout);
+
+
+  sprintf(filename, "nConflict.gp");
+  fout = fopen(filename, "w");
+  fprintf(fout, "set xlabel \"Conflict Index\"\n");
+  fprintf(fout, "set ylabel \"Number of Conflicting %ld/%ld\"\n", part, total);
+  fprintf(fout, "set nokey\n");
+  fprintf(fout, "set size square 0.8,1\n");
+  fprintf(fout, "set xrange [0:%d]\n", index+1);
+  fprintf(fout, "set yrange [0:%ld]\n", maxValue+1);
+  fprintf(fout, "set grid\n");
+  fprintf(fout, "set border 3 linewidth 0.5\n");
+  fprintf(fout, "set xtics nomirror\n");
+  fprintf(fout, "set ytics nomirror\n");
+  fprintf(fout, "set mxtics 2\n");
+  fprintf(fout, "set mytics 2\n");
+  fprintf(fout, "set pointsize 2\n");
+  fprintf(fout, "set terminal postscript eps enhanced color solid \"Times-Roman\" 24\n");
+  fprintf(fout, "set output \"nConflict.eps\"\n");
+  fprintf(fout, "plot \"nConflict.dat\" using 1:2 with line linetype 3\n");
+  fclose(fout);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Compare integer number]
+
+  Description [ Compare integer number]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+numCompareInt(const void *x, const void *y)
+{
+long n1, n2;
+
+  n1 = *(int *)x;
+  n2 = *(int *)y;
+  return(n1 > n2);
+}
Index: vis_dev/vis-2.3/src/sat/satDecision.c
===================================================================
--- vis_dev/vis-2.3/src/sat/satDecision.c	(revision 14)
+++ vis_dev/vis-2.3/src/sat/satDecision.c	(revision 14)
@@ -0,0 +1,974 @@
+/**CFile***********************************************************************
+
+  FileName    [satDecision.c]
+
+  PackageName [sat]
+
+  Synopsis    [Routines for various decision heuristics.]
+
+  Author      [HoonSang Jin]
+
+  Copyright [ This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+
+******************************************************************************/
+
+#include "satInt.h"
+
+static char rcsid[] UNUSED = "$Id: satDecision.c,v 1.28 2009/04/11 18:26:37 fabio Exp $";
+static	satManager_t *SatCm;
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int ScoreCompare(const void * node1, const void * node2);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Select decision variable]
+
+  Description [ Select decision variable]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+satLevel_t *
+sat_MakeDecision(satManager_t *cm)
+{
+satLevel_t *d;
+int value;
+long v;
+satStatistics_t *stats;
+
+  d = SATgetDecision(cm->currentDecision);
+
+  if(cm->queue->size)
+    return(d);
+
+  d = sat_AllocLevel(cm);
+
+  v = 0;
+  v = sat_DecisionBasedOnBDD(cm, d);
+
+  if(v == 0)
+    v = sat_DecisionBasedOnLatestConflict(cm, d);
+
+  if(v == 0)
+    v = sat_DecisionBasedOnScore(cm, d);
+
+  if(v == 0)
+    return(0);
+
+
+  stats = cm->each;
+
+  stats->nDecisions++;
+
+  value = !(SATisInverted(v));
+  v = SATnormalNode(v);
+  d->decisionNode = v;
+  d->nConflict = cm->each->nConflictCl;
+
+  SATvalue(v) = value;
+  /**
+  if(cm->option->verbose > 1) {
+    var = SATgetVariable(v);
+    fprintf(cm->stdOut, "decision at %3d on %6d <- %d score(%d %d) %d\n",
+	    d->level, v, value, var->scores[0], var->scores[1],
+	    cm->each->nDecisions);
+    fflush(cm->stdOut);
+  }
+  **/
+  SATmakeImplied(v, d);
+
+  sat_Enqueue(cm->queue, v);
+  SATflags(v) |= InQueueMask;
+
+  return(d);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Decision making based on current top clause ]
+
+  Description [ Decision making based on current top clause ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+long
+sat_DecisionBasedOnLatestConflict(
+	satManager_t *cm,
+	satLevel_t *d)
+{
+satOption_t *option;
+satStatistics_t *stats;
+satLiteralDB_t *literals;
+satVariable_t *var;
+int size, limit;
+long *plit, *tplit;
+long v, lit, tv, maxV;
+int tsize, count;
+int inverted, value;
+int i, j, satisfied;
+int tmpScore, maxScore;
+
+  option = cm->option;
+  stats = cm->each;
+
+  if(!(option->decisionHeuristic & LATEST_CONFLICT_DECISION))
+    return(0);
+
+  /** CONSIDER
+  if(stats->nConflictCl < option->minConflictForDecision)
+    return(0);
+
+  **/
+
+
+  if(cm->currentTopConflict == 0)
+    return(0);
+
+  literals = cm->literals;
+  size = literals->last - literals->begin;
+
+  limit = MAXINT;
+  if(option->maxConflictForDecision > 0)
+    limit = option->maxConflictForDecision;
+
+  count = cm->currentTopConflictCount;
+  tv = -(*(cm->currentTopConflict));
+  tsize = SATnumLits(tv);
+  tplit = (long*)SATfirstLit(tv);
+  plit = tplit + tsize;
+
+  for(i=plit-literals->begin; i>=0; i--, plit--) {
+/**  for(plit =literals->last-1, i=literals->last - literals->begin; i>=0; i--, plit--) { */
+    if(count > limit)	break;
+
+    lit = *plit;
+    if(lit < 0) {
+      tv = -lit;
+
+      if(!(SATflags(tv) & IsConflictMask))
+	return(0);
+
+      if(plit < (long*)SATfirstLit(tv))
+	continue;
+
+      count++;
+
+      if(option->skipSatisfiedClauseForDecision) {
+	tsize = SATnumLits(tv);
+	tplit = (long *)SATfirstLit(tv);
+	satisfied = 0;
+	maxScore = -1;
+	maxV = 0;
+	for(j=0; j<tsize; j++, tplit++) {
+	  v = SATgetNode(*tplit);
+	  inverted = SATisInverted(v);
+	  v = SATnormalNode(v);
+	  value = SATvalue(v) ^ inverted;
+	  if(value == 1) {
+	    satisfied = 1;
+	    break;
+	  }
+	  else if(value == 0) {
+	    continue;
+	  }
+	  var = SATgetVariable(v);
+	  tmpScore = (var->scores[0] >= var->scores[1]) ? var->scores[0] : var->scores[1];
+	  if(tmpScore > maxScore) {
+	    maxScore = tmpScore;
+	    maxV = v;
+	  }
+	}
+	if(satisfied) {
+	  i = i - tsize - 1;
+	  plit = plit - tsize -1;
+	}
+	else {
+	  var = SATgetVariable(maxV);
+	  value = (var->scores[0] >= var->scores[1]) ? 0 : 1;
+
+	  cm->currentTopConflict = (long*)SATfirstLit(tv) + SATnumLits(tv);
+	  cm->currentTopConflictCount = count;
+
+	  stats = cm->each;
+	  stats->nLatestConflictDecisions++;
+	  return(maxV ^ !value);
+	}
+      }
+      continue;
+    }
+    else if(lit == 0)
+      continue;
+
+    v = SATgetNode(lit);
+    inverted = SATisInverted(v);
+    v = SATnormalNode(v);
+    value = SATvalue(v) ^ inverted;
+
+    if(value >= 2) {
+      var = SATgetVariable(v);
+      value = (var->conflictLits[0] >= var->conflictLits[1]) ? 0 : 1;
+
+      cm->currentTopConflict = (long*)SATfirstLit(tv) + SATnumLits(tv);
+      cm->currentTopConflictCount = count;
+
+      stats = cm->each;
+      stats->nLatestConflictDecisions++;
+      return(v ^ !value);
+    }
+  }
+  return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Check decision variable to check correctness of currentVarPos,
+		since currentVarPos has to point lowest variable that are
+		not implied.]
+
+  Description [ Check decision variable to check correctness of currentVarPos,
+		since currentVarPos has to point lowest variable that are
+		not implied.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_CheckDecisonVariableArray(
+	satManager_t *cm)
+{
+satArray_t *orderedVariableArray;
+int size, i;
+long v;
+
+  orderedVariableArray = cm->orderedVariableArray;
+  size = orderedVariableArray->num;
+  for(i=0; i<cm->currentVarPos; i++) {
+    v = orderedVariableArray->space[i];
+    if(SATvalue(v) > 1)	{
+      fprintf(stdout, " ERROR : wrong current variable pos %d at %d\n",
+	      cm->currentVarPos, i);
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Decision making based on score based heuristic ]
+
+  Description [ Decision making based on score based heuristic ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+long
+sat_DecisionBasedOnScore(
+	satManager_t *cm,
+	satLevel_t *d)
+{
+int size, i;
+long v;
+int value;
+satVariable_t *var;
+satArray_t *orderedVariableArray;
+satStatistics_t *stats;
+satOption_t *option;
+
+
+  option = cm->option;
+  orderedVariableArray = cm->orderedVariableArray;
+  size = orderedVariableArray->num;
+
+  for(i=cm->currentVarPos; i<size; i++) {
+    v = orderedVariableArray->space[i];
+    if(SATvalue(v) < 2)	continue;
+
+    var = SATgetVariable(v);
+    value = (var->scores[0] >= var->scores[1]) ? 0 : 1;
+
+    stats = cm->each;
+    if((var->scores[0]+var->scores[1]) < 1) {
+      stats->nLowScoreDecisions++;
+    }
+
+
+    if((option->decisionHeuristic & DVH_DECISION))
+      stats->nDVHDecisions++;
+    else
+      stats->nVSIDSDecisions++;
+
+    cm->currentVarPos = i;
+    d->currentVarPos = i;
+
+    return(v ^ !value);
+  }
+
+  return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Take care of decision by BDD based mathod ]
+
+  Description [ Take care of decision by BDD based mathod ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+long
+sat_DecisionBasedOnBDD(
+	satManager_t *cm,
+	satLevel_t *d)
+{
+satArray_t *arr;
+long nv, v;
+
+  if(cm->assignByBDD == 0)
+    return(0);
+
+  arr = cm->assignByBDD;
+  if(arr->num == 0)
+    return(0);
+
+  /**
+  for(i=0; i<arr->num; i++) {
+    v = arr->space[i];
+    nv = SATnormalNode(v);
+    if(SATvalue(nv) > 1)
+      return(v);
+  }
+  **/
+
+  while(arr->num) {
+    v = arr->space[arr->num-1];
+    nv = SATnormalNode(v);
+    arr->num--;
+    if(SATvalue(nv) > 1)
+      return(v);
+  }
+  return(0);
+}
+
+
+long
+sat_DecisionBasedOnShrink(
+	satManager_t *cm)
+{
+satArray_t *arr;
+long nv, v;
+
+  if(cm->shrinkArray == 0)
+    return(0);
+
+  arr = cm->shrinkArray;
+  if(arr->num == 0)
+    return(0);
+
+  while(arr->num) {
+    v = arr->space[arr->num-1];
+    nv = SATnormalNode(v);
+    arr->num--;
+    if(SATvalue(nv) > 1)
+      return(v);
+  }
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Update the score of variables ]
+
+  Description [ Update the score of variables ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_UpdateScore(
+	satManager_t *cm)
+{
+satArray_t *one, *tmp;
+satArray_t *ordered;
+satVariable_t *var;
+int size, i;
+long v;
+int value;
+
+  ordered = cm->orderedVariableArray;
+
+  one = sat_ArrayAlloc(ordered->num);
+  tmp = sat_ArrayAlloc(ordered->num);
+
+  size = ordered->num;
+  for(i=0; i<size; i++) {
+    v = ordered->space[i];
+
+    if(SATvalue(v) < 2 && SATlevel(v) == 0)
+      continue;
+
+    var = SATgetVariable(v);
+    var->scores[0] = (var->scores[0]>>1) + var->litsCount[0] - var->lastLitsCount[0];
+    var->scores[1] = (var->scores[1]>>1) + var->litsCount[1] - var->lastLitsCount[1];
+    var->lastLitsCount[0] = var->litsCount[0];
+    var->lastLitsCount[1] = var->litsCount[1];
+
+
+    if((var->scores[0] + var->scores[1]) < 1) {
+      sat_ArrayInsert(one, v);
+    }
+    else {
+      value = (var->scores[0] > var->scores[1]) ? var->scores[0] : var->scores[1];
+      sat_ArrayInsert(tmp, v);
+      sat_ArrayInsert(tmp, value);
+    }
+  }
+
+  SatCm = cm;
+  qsort(tmp->space, (tmp->num)>>1, sizeof(long)*2, ScoreCompare);
+
+  ordered->num = 0;
+  size = tmp->num;
+  for(i=0; i<size; i++) {
+    v = tmp->space[i];
+    sat_ArrayInsert(ordered, v);
+    var = SATgetVariable(v);
+    var->pos = (i>>1);
+    i++;
+  }
+
+  size = one->num;
+  for(i=0; i<size; i++) {
+    v = one->space[i];
+    var = SATgetVariable(v);
+    var->pos = ordered->num;
+    sat_ArrayInsert(ordered, v);
+  }
+
+  sat_ArrayFree(one);
+  sat_ArrayFree(tmp);
+
+  cm->orderedVariableArray = ordered;
+  cm->currentVarPos = 0;
+
+  for(i=1; i<cm->currentDecision; i++) {
+    cm->decisionHead[i].currentVarPos = 0;
+  }
+
+  if(cm->option->verbose > 3)
+    sat_PrintScore(cm);
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Update the score of variables by deepest variable hike]
+
+  Description [ Update the score of variables by deepest variable hike]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_UpdateDVH(
+	satManager_t *cm,
+	satLevel_t *d,
+	satArray_t *clauseArray,
+	int bLevel,
+	long unitLit)
+{
+satArray_t *ordered;
+satLevel_t *td;
+satVariable_t *var, *tvar, *ttvar;
+int score, tscore, ttscore;
+int value;
+long v;
+int gap, i, insert;
+
+
+  ordered = cm->orderedVariableArray;
+
+  unitLit = SATnormalNode(unitLit);
+  gap = cm->currentDecision - bLevel;
+  td = SATgetDecision(bLevel+1);
+
+  if(gap <= 1) {
+      /** CONSIDER .... */
+  }
+  var = SATgetVariable(unitLit);
+  tvar = SATgetVariable(td->decisionNode);
+
+  score = (var->scores[1] > var->scores[0]) ? var->scores[1] : var->scores[0];
+  tscore = (tvar->scores[1] > tvar->scores[0]) ? tvar->scores[1] : tvar->scores[0];
+
+  if(score >= tscore)	{
+    return;
+  }
+
+  tscore += 1;
+
+  value = SATvalue(unitLit);
+  if(value == 0)var->scores[1] = tscore;
+  else		var->scores[0] = tscore;
+
+  ordered = cm->orderedVariableArray;
+  insert = 0;
+  for(i=var->pos; i>=1; i--) {
+    v = ordered->space[i-1];
+    ttvar = SATgetVariable(v);
+    ttscore = (ttvar->scores[1] > ttvar->scores[0]) ? ttvar->scores[1] : ttvar->scores[0];
+    if(tscore > ttscore && i>1) {
+      ttvar->pos = i;
+      ordered->space[i] = v;
+      continue;
+    }
+
+    var->pos = i;
+    ordered->space[i] = unitLit;
+    insert = 1;
+    break;
+  }
+
+  if(insert == 0) {
+    var->pos = i;
+    ordered->space[0] = unitLit;
+  }
+
+  for(i=d->level; i>0; i--) {
+    td = SATgetDecision(i);
+    if(td->currentVarPos < var->pos)
+      break;
+    td->currentVarPos = var->pos;
+  }
+  cm->currentVarPos = td->currentVarPos;
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Check correctness of variable order ]
+
+  Description [ Check correctness of variable order ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_CheckOrderedVariableArray(satManager_t *cm)
+{
+satArray_t *ordered;
+satVariable_t *var;
+int i;
+long v;
+
+  ordered = cm->orderedVariableArray;
+  for(i=0; i<ordered->num; i++) {
+    v = ordered->space[i];
+    var = SATgetVariable(v);
+    if(i != var->pos) {
+      fprintf(cm->stdOut, "Error : wrong variable position %d %d in ordered array\n", i, var->pos);
+
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Generate initial score ]
+
+  Description [ Generate initial score ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_InitScore(satManager_t *cm)
+{
+int objExist;
+int j, inverted;
+long *plit, v, nv, i;
+int size;
+int count0, count1;
+satArray_t *ordered, *newOrdered;
+satVariable_t *var;
+
+  ordered = cm->orderedVariableArray;
+  if(ordered == 0)
+    ordered = sat_ArrayAlloc(cm->initNumVariables);
+  else
+    ordered->num = 0;
+  cm->orderedVariableArray = ordered;
+
+  objExist = 0;
+  /**
+  if(cm->obj && cm->obj->num) {
+    sat_MarkTransitiveFaninForArray(cm, cm->obj, VisitedMask);
+    objExist = 1;
+  }
+  **/
+
+
+  for(i=satNodeSize; i<cm->nodesArraySize; i+=satNodeSize) {
+    v = i;
+    if((SATflags(v) & IsBDDMask)) {
+      continue;
+    }
+    if((SATflags(v) & IsCNFMask)) {
+      size = SATnumLits(v);
+      plit = (long*)SATfirstLit(v);
+      for(j=0; j<size; j++, plit++) {
+	nv = SATgetNode(*plit);
+	inverted = !(SATisInverted(nv));
+	nv = SATnormalNode(nv);
+	var = SATgetVariable(nv);
+	var->litsCount[inverted]++;
+      }
+      continue;
+    }
+    if(!(SATflags(v) & CoiMask))	continue;
+    if(!(SATflags(v) & VisitedMask) && objExist)	continue;
+
+    if(SATvalue(v) != 2 && SATlevel(v) == 0)	continue;
+
+    count0 = count1 = SATnFanout(v);
+    if(count0 == 0 && SATleftChild(v) == 2 && SATrightChild(v) == 2) {
+      count0 = 0;
+      count1 = 0;
+    }
+    else if(SATleftChild(v) != 2) {
+      count0 += 2;
+      count1++;
+    }
+    else {
+      count0 += 3;
+      count1 += 3;
+    }
+
+    var = SATgetVariable(v);
+    var->litsCount[0] += count0;
+    var->litsCount[1] += count1;
+
+    sat_ArrayInsert(ordered, v);
+  }
+
+  //Bing:
+  if(cm->unitLits){
+    for(i=0; i<cm->unitLits->num; i++) {
+      v = cm->unitLits->space[i];
+      v = SATnormalNode(v);
+      SATflags(v) |= NewMask;
+    }
+  }
+
+  if(cm->assertion) {
+    for(i=0; i<cm->assertion->num; i++) {
+      v = cm->assertion->space[i];
+      v = SATnormalNode(v);
+      SATflags(v) |= NewMask;
+    }
+  }
+
+  newOrdered = sat_ArrayAlloc((ordered->num) * 2);
+  size = ordered->num;
+  for(i=0; i<size; i++) {
+    v = ordered->space[i];
+    var = SATgetVariable(v);
+    var->scores[0] = var->lastLitsCount[0] = var->litsCount[0];
+    var->scores[1] = var->lastLitsCount[1] = var->litsCount[1];
+
+    if(SATflags(v) & NewMask);
+    else if(var->scores[0] == 0 && var->scores[1] == 0 && !(SATflags(v) & NewMask)) {
+      sat_ArrayInsert(cm->pureLits, (v));
+    }
+    else if(var->scores[0] == 0 && !(SATflags(v) & NewMask)) {
+      sat_ArrayInsert(cm->pureLits, (v));
+    }
+    else if(var->scores[1] == 0 && !(SATflags(v) & NewMask)) {
+      sat_ArrayInsert(cm->pureLits, SATnot(v));
+    }
+    else {
+      sat_ArrayInsert(newOrdered, v);
+      sat_ArrayInsert(newOrdered, (var->scores[0] > var->scores[1]) ? var->scores[0] : var->scores[1]);
+    }
+  }
+
+  //Bing:
+  if(cm->unitLits){
+    for(i=0; i<cm->unitLits->num; i++) {
+      v = cm->unitLits->space[i];
+      v = SATnormalNode(v);
+      SATflags(v) &= ResetNewMask;
+    }
+  }
+
+  if(cm->assertion) {
+    for(i=0; i<cm->assertion->num; i++) {
+      v = cm->assertion->space[i];
+      v = SATnormalNode(v);
+      SATflags(v) &= ResetNewMask;
+    }
+  }
+
+  cm->orderedVariableArray = ordered;
+  size = newOrdered->num;
+  qsort(newOrdered->space, size>>1, sizeof(long)*2, ScoreCompare);
+
+  cm->currentVarPos = 0;
+  ordered->num = 0;
+  for(i=0; i<size; i++) {
+    v = newOrdered->space[i];
+    var = SATgetVariable(v);
+    var->pos = (i>>1);
+    sat_ArrayInsert(ordered, v);
+    i++;
+  }
+
+  sat_ArrayFree(newOrdered);
+
+  /**
+  if(cm->obj && cm->obj->num) {
+    sat_UnmarkTransitiveFaninForArray(
+	    cm, cm->obj, VisitedMask, ResetVisitedMask);
+  }
+  **/
+
+  if(cm->option->verbose > 3)
+    sat_PrintScore(cm);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Generate initial score for CNF and AIG ]
+
+  Description [ Generate initial score for CNF and AIG]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_InitScoreForMixed(satManager_t *cm)
+{
+int j, inverted;
+long *plit, v, nv, i;
+int size;
+int count0, count1;
+satArray_t *ordered, *newOrdered;
+satVariable_t *var;
+
+  ordered = cm->orderedVariableArray;
+  if(ordered == 0)
+    ordered = sat_ArrayAlloc(cm->initNumVariables);
+  else
+    ordered->num = 0;
+  cm->orderedVariableArray = ordered;
+
+  /**
+  objExist = 0;
+  if(cm->obj && cm->obj->num) {
+    sat_MarkTransitiveFaninForArray(cm, cm->obj, VisitedMask);
+    objExist = 1;
+  }
+  **/
+
+
+  for(i=satNodeSize; i<cm->nodesArraySize; i+=satNodeSize) {
+    v = i;
+    if((SATflags(v) & IsBDDMask)) {
+      continue;
+    }
+    if((SATflags(v) & IsCNFMask)) {
+      size = SATnumLits(v);
+      plit =(long*) SATfirstLit(v);
+      for(j=0; j<size; j++, plit++) {
+	nv = SATgetNode(*plit);
+	inverted = !(SATisInverted(nv));
+	nv = SATnormalNode(nv);
+	var = SATgetVariable(nv);
+	var->litsCount[inverted]++;
+      }
+      continue;
+    }
+    if(!(SATflags(v) & CoiMask))	continue;
+    /**
+    if(!(SATflags(v) & VisitedMask) && objExist)	continue;
+    **/
+
+    if(SATvalue(v) != 2 && SATlevel(v) == 0)	continue;
+
+    count0 = count1 = SATnFanout(v);
+    if(count0 == 0 && SATleftChild(v) == 2 && SATrightChild(v) == 2) {
+      count0 = 0;
+      count1 = 0;
+    }
+    else if(SATleftChild(v) != 2) {
+      count0 += 2;
+      count1++;
+    }
+    else {
+      count0 += 3;
+      count1 += 3;
+    }
+
+    var = SATgetVariable(v);
+    var->litsCount[0] += count0;
+    var->litsCount[1] += count1;
+
+    sat_ArrayInsert(ordered, v);
+  }
+
+  for(i=0; i<cm->unitLits->num; i++) {
+    v = cm->unitLits->space[i];
+    v = SATnormalNode(v);
+    SATflags(v) |= NewMask;
+  }
+  if(cm->assertion) {
+    for(i=0; i<cm->assertion->num; i++) {
+      v = cm->assertion->space[i];
+      v = SATnormalNode(v);
+      SATflags(v) |= NewMask;
+    }
+  }
+
+  newOrdered = sat_ArrayAlloc((ordered->num) * 2);
+  size = ordered->num;
+  for(i=0; i<size; i++) {
+    v = ordered->space[i];
+    var = SATgetVariable(v);
+    var->scores[0] = var->lastLitsCount[0] = var->litsCount[0];
+    var->scores[1] = var->lastLitsCount[1] = var->litsCount[1];
+
+    if(SATflags(v) & NewMask);
+    else if(var->scores[0] == 0 && var->scores[1] == 0 && !(SATflags(v) & NewMask)) {
+      sat_ArrayInsert(cm->pureLits, (v));
+    }
+    else if(var->scores[0] == 0 && !(SATflags(v) & NewMask)) {
+      sat_ArrayInsert(cm->pureLits, (v));
+    }
+    else if(var->scores[1] == 0 && !(SATflags(v) & NewMask)) {
+      sat_ArrayInsert(cm->pureLits, SATnot(v));
+    }
+    else {
+      sat_ArrayInsert(newOrdered, v);
+      sat_ArrayInsert(newOrdered, (var->scores[0] > var->scores[1]) ? var->scores[0] : var->scores[1]);
+    }
+  }
+
+  for(i=0; i<cm->unitLits->num; i++) {
+    v = cm->unitLits->space[i];
+    v = SATnormalNode(v);
+    SATflags(v) &= ResetNewMask;
+  }
+  if(cm->assertion) {
+    for(i=0; i<cm->assertion->num; i++) {
+      v = cm->assertion->space[i];
+      v = SATnormalNode(v);
+      SATflags(v) &= ResetNewMask;
+    }
+  }
+
+  cm->orderedVariableArray = ordered;
+  size = newOrdered->num;
+  qsort(newOrdered->space, size>>1, sizeof(long)*2, ScoreCompare);
+
+  cm->currentVarPos = 0;
+  ordered->num = 0;
+  for(i=0; i<size; i++) {
+    v = newOrdered->space[i];
+    var = SATgetVariable(v);
+    var->pos = (i>>1);
+    sat_ArrayInsert(ordered, v);
+    i++;
+  }
+
+  sat_ArrayFree(newOrdered);
+
+  /**
+  if(cm->obj && cm->obj->num) {
+    sat_UnmarkTransitiveFaninForArray(
+	    cm, cm->obj, VisitedMask, ResetVisitedMask);
+  }
+  **/
+
+  if(cm->option->verbose > 3)
+    sat_PrintScore(cm);
+
+}
+/**Function********************************************************************
+
+  Synopsis    [ Compare score to sort variable array]
+
+  Description [ Compare score to sort variable array]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+ScoreCompare(
+  const void * node1,
+  const void * node2)
+{
+int v1;
+int v2;
+int s1, s2;
+
+  v1 = *(int *)(node1);
+  v2 = *(int *)(node2);
+  s1 = *((int *)(node1) + 1);
+  s2 = *((int *)(node2) + 1);
+  /**
+  var1 = SatCm->variableArray[SATnodeID(v1)];
+  var2 = SatCm->variableArray[SATnodeID(v2)];
+  s1 = (var1.scores[0] > var1.scores[1]) ? var1.scores[0] : var1.scores[1];
+  s2 = (var2.scores[0] > var2.scores[1]) ? var2.scores[0] : var2.scores[1];
+  **/
+  if(s1 == s2) {
+    return(v1 > v2);
+  }
+  return(s1 < s2);
+}
Index: vis_dev/vis-2.3/src/sat/satImplication.c
===================================================================
--- vis_dev/vis-2.3/src/sat/satImplication.c	(revision 14)
+++ vis_dev/vis-2.3/src/sat/satImplication.c	(revision 14)
@@ -0,0 +1,1031 @@
+/**CFile***********************************************************************
+
+  FileName    [satImplication.c]
+
+  PackageName [sat]
+
+  Synopsis    [Routines for BCP.]
+
+  Author      [HoonSang Jin]
+
+  Copyright [ This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+
+******************************************************************************/
+
+#include "satInt.h"
+#include "baig.h"
+
+static char rcsid[] UNUSED = "$Id: satImplication.c,v 1.10 2009/04/11 18:26:37 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+typedef int (*IMPLY_FN)
+    (satManager_t *cm, satLevel_t *d, long v, long left, long right);
+
+
+IMPLY_FN satImplicationFN[64]= {
+  sat_ImplyStop,                 /* 0    */
+  sat_ImplyConflict,             /* 1  */
+  sat_ImplyLeftForward,          /* 2  */
+  sat_ImplyLeftForward,          /* 3  */
+  sat_ImplyStop,                 /* 4  */
+  sat_ImplyConflict,             /* 5  */
+  sat_ImplyLeftForward,          /* 6  */
+  sat_ImplyLeftForward,          /* 7  */
+  sat_ImplySplit,                /* 8  */
+  sat_ImplyConflict,             /* 9  */
+  sat_ImplyLeftForward,          /* 10  */
+  sat_ImplyLeftForward,          /* 11  */
+  sat_ImplySplit,                /* 12  */
+  sat_ImplyConflict,             /* 13  */
+  sat_ImplyLeftForward,          /* 14  */
+  sat_ImplyLeftForward,          /* 15  */
+  sat_ImplyStop,                 /* 16  */
+  sat_ImplyConflict,             /* 17  */
+  sat_ImplyRightForward,         /* 18  */
+  sat_ImplyRightForward,         /* 19  */
+  sat_ImplyConflict,             /* 20  */
+  sat_ImplyStop,                 /* 21  */
+  sat_ImplyForwardOne,           /* 22  */
+  sat_ImplyForwardOne,           /* 23  */
+  sat_ImplyPropRight,            /* 24  */
+  sat_ImplyPropRightOne,         /* 25  */
+  sat_ImplyStop,                 /* 26  */
+  sat_ImplyStop,                 /* 27  */
+  sat_ImplyPropRight,            /* 28  */
+  sat_ImplyPropRightOne,         /* 29  */
+  sat_ImplyStop,                 /* 30  */
+  sat_ImplyStop,                 /* 31  */
+  sat_ImplySplit,                /* 32  */
+  sat_ImplyConflict,             /* 33  */
+  sat_ImplyRightForward,         /* 34  */
+  sat_ImplyRightForward,         /* 35  */
+  sat_ImplyPropLeft,             /* 36  */
+  sat_ImplyPropLeftOne,          /* 37  */
+  sat_ImplyStop,                 /* 38  */
+  sat_ImplyStop,                 /* 39  */
+  sat_ImplySplit,                /* 40  */
+  sat_ImplyPropLeftRight,        /* 41  */
+  sat_ImplyStop,                 /* 42  */
+  sat_ImplyStop,                 /* 43  */
+  sat_ImplySplit,                /* 44  */
+  sat_ImplyPropLeftRight,        /* 45  */
+  sat_ImplyStop,                 /* 46  */
+  sat_ImplyStop,                 /* 47  */
+  sat_ImplySplit,                /* 48  */
+  sat_ImplyConflict,             /* 49  */
+  sat_ImplyRightForward,         /* 50  */
+  sat_ImplyRightForward,         /* 51  */
+  sat_ImplyPropLeft,             /* 52  */
+  sat_ImplyPropLeftOne,          /* 53  */
+  sat_ImplyStop,                 /* 54  */
+  sat_ImplyStop,                 /* 55  */
+  sat_ImplySplit,                /* 56  */
+  sat_ImplyPropLeftRight,        /* 57  */
+  sat_ImplyStop,                 /* 58  */
+  sat_ImplyStop,                 /* 59  */
+  sat_ImplySplit,                /* 60  */
+  sat_ImplyPropLeftRight,        /* 61  */
+  sat_ImplyStop,                 /* 62  */
+  sat_ImplyStop,                 /* 63  */
+};
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [No further implcation when this function is called.]
+
+  Description [No further implcation when this function is called.
+		      0       0       0       1
+		      |       |       |       |
+		     ---     ---     ---     ---
+		     / \     / \     / \     / \
+		    0   X   X   0   0   0   1   1
+	      ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+
+int
+sat_ImplyStop(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	long left,
+	long right)
+{
+  return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [No further implcation when this function is called.]
+
+  Description [No further implcation when this function is called.
+	       and need split on output.
+		      0
+		      |
+		     ---
+		     / \
+		    X   X
+	      ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_ImplySplit(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	long left,
+	long right)
+{
+  return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [The conflict happens.]
+
+  Description [The conflict happens when
+		      0       1       1       1       1
+		      |       |       |       |       |
+		     ---     ---     ---     ---     ---
+		     / \     / \     / \     / \     / \
+		    1   1   X   0   0   X   1   0   0   1
+	      ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_ImplyConflict(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	long left,
+	long right)
+{
+  if(left != 2)	 {
+    d->conflict = SATnormalNode(v);
+  }
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [A value implied to output due to left child.]
+
+  Description [A value implied to output due to left child
+		      X       X
+		      |       |
+		     ---     ---
+		     / \     / \
+		    0   1   0   X
+	      ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_ImplyLeftForward(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	long left,
+	long right)
+{
+
+  v = SATnormalNode(v);
+  left = SATnormalNode(left);
+
+  SATvalue(v) = 0;
+  SATmakeImplied(v, d);
+  SATante(v) = left;
+
+  sat_Enqueue(cm->queue, v);
+  SATflags(v) |= InQueueMask;
+
+  SATflags(v) |= (SATflags(left) & ObjMask);
+
+  cm->each->nAigImplications++;
+  return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [A value implied to output due to right child.]
+
+  Description [A value implied to output due to right child
+		      X       X
+		      |       |
+		     ---     ---
+		     / \     / \
+		    1   0   X   0
+	      ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_ImplyRightForward(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	long left,
+	long right)
+{
+  v = SATnormalNode(v);
+  right = SATnormalNode(right);
+
+  SATvalue(v) = 0;
+  SATmakeImplied(v, d);
+  SATante(v) = right;
+
+  sat_Enqueue(cm->queue, v);
+  SATflags(v) |= InQueueMask;
+
+  SATflags(v) |= (SATflags(right) & ObjMask);
+  cm->each->nAigImplications++;
+
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [A value implied to output due to both child.]
+
+  Description [A value implied to output due to both child
+		      X
+		      |
+		     ---
+		     / \
+		    1   1
+	      ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_ImplyForwardOne(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	long left,
+	long right)
+{
+  v = SATnormalNode(v);
+  left = SATnormalNode(left);
+  right = SATnormalNode(right);
+
+  SATvalue(v) = 1;
+  SATmakeImplied(v, d);
+  SATante(v) = right;
+  SATante2(v) = left;
+
+  sat_Enqueue(cm->queue, v);
+  SATflags(v) |= InQueueMask;
+
+  SATflags(v) |= (SATflags(right) & ObjMask);
+  SATflags(v) |= (SATflags(left) & ObjMask);
+  cm->each->nAigImplications++;
+
+  return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [A value implied to right child due to both output and left.]
+
+  Description [A value implied to right child due to both output and left
+		      0
+		      |
+		     ---
+		     / \
+		    1   X
+	      ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_ImplyPropRight(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	long left,
+	long right)
+{
+  int isInverted;
+
+  isInverted = SATisInverted(right);
+  v = SATnormalNode(v);
+  left = SATnormalNode(left);
+  right = SATnormalNode(right);
+
+  SATmakeImplied(right, d);
+  SATvalue(right) = isInverted;
+
+  SATante(right) = left;
+  SATante2(right) = v;
+
+  sat_Enqueue(cm->queue, right);
+  SATflags(right) |= InQueueMask;
+
+  SATflags(right) |= (SATflags(left) & ObjMask);
+  SATflags(right) |= (SATflags(v) & ObjMask);
+  cm->each->nAigImplications++;
+  return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [A value implied to right child due to both output and left.]
+
+  Description [A value implied to right child due to both output and left
+		      1
+		      |
+		     ---
+		     / \
+		    1   X
+	      ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_ImplyPropRightOne(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	long left,
+	long right)
+{
+  int isInverted;
+
+  isInverted = SATisInverted(right);
+  v = SATnormalNode(v);
+  left = SATnormalNode(left);
+  right = SATnormalNode(right);
+
+  SATmakeImplied(right, d);
+
+  SATante(right) = v;
+
+  SATvalue(right) = !isInverted;
+
+  sat_Enqueue(cm->queue, right);
+  SATflags(right) |= InQueueMask;
+
+  SATflags(right) |= (SATflags(v) & ObjMask);
+  cm->each->nAigImplications++;
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [A value implied to left child due to both output and right.]
+
+  Description [A value implied to left child due to both output and right
+		      0
+		      |
+		     ---
+		     / \
+		    X   1
+	      ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_ImplyPropLeft(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	long left,
+	long right)
+{
+  int isInverted;
+
+  isInverted = SATisInverted(left);
+  v = SATnormalNode(v);
+  left = SATnormalNode(left);
+  right = SATnormalNode(right);
+
+  SATmakeImplied(left, d);
+
+  SATante(left) = v;
+  SATante2(left) = right;
+
+  SATvalue(left) = isInverted;
+
+  sat_Enqueue(cm->queue, left);
+  SATflags(left) |= InQueueMask;
+
+  SATflags(left) |= (SATflags(v) & ObjMask);
+  SATflags(left) |= (SATflags(right) & ObjMask);
+  cm->each->nAigImplications++;
+  return(0);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [A value implied to left child due to both output and right.]
+
+  Description [A value implied to left child due to both output and right
+		      1
+		      |
+		     ---
+		     / \
+		    X   1
+	      ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_ImplyPropLeftOne(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	long left,
+	long right)
+{
+  int isInverted;
+
+  isInverted = SATisInverted(left);
+  v = SATnormalNode(v);
+  left = SATnormalNode(left);
+  right = SATnormalNode(right);
+
+  SATmakeImplied(left, d);
+
+  SATante(left) = v;
+
+  SATvalue(left) = !isInverted;
+
+  sat_Enqueue(cm->queue, left);
+  SATflags(left) |= InQueueMask;
+
+  SATflags(left) |= (SATflags(v) & ObjMask);
+  cm->each->nAigImplications++;
+  return(0);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [A value implied to left and right child due to output.]
+
+  Description [A value implied to left and right child due to output
+		      1
+		      |
+		     ---
+		     / \
+		    X   X
+	      ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_ImplyPropLeftRight(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	long left,
+	long right)
+{
+  int isLeftInverted;
+  int isRightInverted;
+
+  if(left == right)	return 1;
+
+  isLeftInverted = SATisInverted(left);
+  isRightInverted = SATisInverted(right);
+
+  v = SATnormalNode(v);
+  left = SATnormalNode(left);
+  right = SATnormalNode(right);
+
+  SATmakeImplied(left, d);
+  SATmakeImplied(right, d);
+
+  SATante(left) = v;
+  SATante(right) = v;
+
+  SATvalue(left) = !isLeftInverted;
+  SATvalue(right) = !isRightInverted;
+
+  sat_Enqueue(cm->queue, left);
+  SATflags(left) |= InQueueMask;
+
+  sat_Enqueue(cm->queue, right);
+  SATflags(right) |= InQueueMask;
+
+  SATflags(left) |= (SATflags(v) & ObjMask);
+  SATflags(right) |= (SATflags(v) & ObjMask);
+  cm->each->nAigImplications += 2;
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Implication based on clause.]
+
+  Description [Implication based two watched literal scheme ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_ImplyCNF(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v,
+	satArray_t *wl)
+{
+int size, i, j;
+long *space;
+long lit, *plit, *tplit;
+int dir;
+long nv, tv, *oplit, *wlit;
+int isInverted, value;
+int tsize, inverted;
+long cur, clit;
+satStatistics_t *stats;
+satOption_t *option;
+satQueue_t *Q;
+satVariable_t *var;
+
+  size = wl->num;
+  space = wl->space;
+  Q = cm->queue;
+  stats = cm->each;
+  option = cm->option;
+  nv = 0;
+  wlit = 0;
+
+  for(i=0; i<size; i++) {
+    plit = (long*)space[i];
+
+    if(plit == 0 || *plit == 0) {
+      size--;
+      space[i] = space[size];
+      i--;
+      continue;
+    }
+
+    lit = *plit;
+    dir = SATgetDir(lit);
+    oplit = plit;
+
+    while(1) {
+      oplit += dir;
+      if(*oplit <=0) {
+	if(dir == 1) nv =- (*oplit);
+	if(dir == SATgetDir(lit)) {
+	  oplit = plit;
+	  dir = -dir;
+	  continue;
+	}
+
+	tv = SATgetNode(*wlit);
+	isInverted = SATisInverted(tv);
+	tv = SATnormalNode(tv);
+	value = SATvalue(tv) ^ isInverted;
+	if(value == 0) {  /** conflict happens **/
+	  d->conflict = nv;
+	  wl->num = size;
+	  return;
+	}
+	else if(value > 1) { /** implication **/
+	  SATvalue(tv) = !isInverted;
+	  SATmakeImplied(tv, d);
+	  SATante(tv) = nv;
+
+	  if((SATflags(tv) & InQueueMask) == 0) {
+	    sat_Enqueue(Q, tv);
+	    SATflags(tv) |= InQueueMask;
+	  }
+
+	  stats->nCNFImplications++;
+
+	  /** to identify the objective dependent clause for incremental
+	  * SAT
+	  **/
+	  if(option->incTraceObjective == 1) {
+	    tsize = SATnumLits(nv);
+	    for(j=0, tplit=(long*)SATfirstLit(nv); j<tsize; j++, tplit++) {
+	      cur = SATgetNode(*tplit);
+	      cur = SATnormalNode(cur);
+	      if(SATflags(cur) & ObjMask) {
+		SATflags(tv) |= ObjMask;
+		break;
+	      }
+	    }
+	  }
+	}
+
+	break;
+      }
+
+      clit = *oplit;
+
+      tv = SATgetNode(clit);
+      inverted = SATisInverted(tv);
+      tv = SATnormalNode(tv);
+      value = SATvalue(tv) ^ inverted;
+
+      if(SATisWL(clit)) { /* found other watched literal */
+	wlit = oplit;
+	if(value == 1)	{
+	  break;
+	}
+	continue;
+      }
+
+      if(value == 0)
+	continue;
+
+      SATunsetWL(plit);
+
+      size--;
+      space[i] = space[size];
+      i--;
+
+      /** move watched literal */
+      var = SATgetVariable(tv);
+      SATsetWL(oplit, dir);
+
+      inverted = !inverted;
+      if(var->wl[inverted]) {
+	sat_ArrayInsert(var->wl[inverted], (long)oplit);
+      }
+      else {
+	var->wl[inverted] = sat_ArrayAlloc(4);
+	sat_ArrayInsert(var->wl[inverted], (long)oplit);
+      }
+
+      break;
+    }
+  }
+  wl->num = size;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Apply implication on node. If the conflict happens then
+	       return 0, otherwise return 1]
+
+  Description [Apply implication on node.
+	       Since the node can be part of AIG and CNF and BDD,
+	       the implications on three representation are applied]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_ImplyNode(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v)
+{
+long *fan, cur;
+int value;
+int i, size;
+long left, right;
+satVariable_t *var;
+satArray_t *wlArray;
+
+  value = SATvalue(v) ^ 1;
+  var = SATgetVariable(v);
+  wlArray = var->wl[value];
+
+  /** implcation on CNF **/
+  if(wlArray && wlArray->size) {
+    sat_ImplyCNF(cm, d, v, wlArray);
+  }
+
+  if(d->conflict)
+    return(0);
+
+  /** implication on AIG **/
+  fan = (long *)SATfanout(v);
+  size = SATnFanout(v);
+  for(i=0; i<size; i++, fan++) {
+    cur = *fan;
+    cur = cur >> 1;
+    cur = SATnormalNode(cur);
+    left = SATleftChild(cur);
+    right = SATrightChild(cur);
+    value = SATgetValue(left, right, cur);
+
+    (satImplicationFN[value])(cm, d, cur, left, right);
+
+    if(d->conflict)
+      return(0);
+  }
+
+  left = SATleftChild(v);
+  right = SATrightChild(v);
+  value = SATgetValue(left, right, v);
+
+  (satImplicationFN[value])(cm, d, v, left, right);
+
+  if(d->conflict)
+    return(0);
+
+
+  return(1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Apply implication until the implication queue is empty. ]
+
+  Description [ Apply implication until the implication queue is empty.
+	       Since the node can be part of AIG and CNF and BDD,
+	       the implications on three representation are applied]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_ImplicationMain(
+	satManager_t *cm,
+	satLevel_t *d)
+{
+satQueue_t *Q, *BDDQ;
+long v;
+
+  Q = cm->queue;
+  BDDQ = cm->BDDQueue;
+
+  while(1) {
+    v = sat_Dequeue(Q);
+    while(v && d->conflict == 0) {
+      sat_ImplyNode(cm, d, v);
+      SATflags(v) &= ResetInQueueMask;
+
+      v = sat_Dequeue(Q);
+    }
+
+    if(d->conflict)
+      break;
+
+    if(cm->option->BDDImplication) {
+      v = sat_Dequeue(Q);
+      while(v && d->conflict == 0) {
+	sat_ImplyBDD(cm, d, v);
+	SATflags(v) &= ResetInQueueMask;
+
+	v = sat_Dequeue(Q);
+      }
+    }
+
+    if(Q->size == 0 && BDDQ->size == 0)
+      break;
+  }
+
+  sat_CleanImplicationQueue(cm);
+  cm->implicatedSoFar += d->implied->num;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [Clean implication queue. ]
+
+  Description [Clean implication queue. ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_CleanImplicationQueue(
+	satManager_t *cm)
+{
+satQueue_t *Q;
+ int i;
+ bAigEdge_t v;
+
+  Q = cm->queue;
+
+  if(Q->size <=0)	return;
+
+  //Bing: important, can't be zero, since some var's value,which are now in
+  //implication queue will be erased. This may lead to not being able to
+  //identify conflict
+  if(cm->option->AbRf || cm->option->IP || cm->option->arosat){
+    if(Q->front <= Q->rear) {
+      for(i=Q->front; i<=Q->rear; i++) {
+	v = Q->array[i];
+	SATflags(v) &= ResetInQueueMask;
+      }
+    }
+    else {
+      for(i=Q->front; i<Q->max; i++) {
+	v = Q->array[i];
+	SATflags(v) &= ResetInQueueMask;
+      }
+      for(i=0; i<Q->rear; i++) {
+	v = Q->array[i];
+	SATflags(v) &= ResetInQueueMask;
+      }
+    }
+  }
+#if 0
+  if(Q->front <= Q->rear) {
+    for(i=Q->front; i<=Q->rear; i++) {
+      v = Q->array[i];
+      SATflags(v) &= ResetInQueueMask;
+      SATante(v) = 0;
+      SATante2(v) = 0;
+      SATvalue(v) = 2;
+    }
+  }
+  else {
+    for(i=Q->front; i<Q->max; i++) {
+      v = Q->array[i];
+      SATflags(v) &= ResetInQueueMask;
+      SATante(v) = 0;
+      SATante2(v) = 0;
+      SATvalue(v) = 2;
+    }
+    for(i=0; i<Q->rear; i++) {
+      v = Q->array[i];
+      SATflags(v) &= ResetInQueueMask;
+      SATante(v) = 0;
+      SATante2(v) = 0;
+      SATvalue(v) = 2;
+    }
+  }
+#endif
+
+  Q->size = 0;
+  Q->front = 1;
+  Q->rear = 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Add nodes in array into implication queue. ]
+
+  Description [Add nodes in array into implication queue. ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_ImplyArray(
+	satManager_t *cm,
+	satLevel_t *d,
+	satArray_t *arr)
+{
+int i, size;
+long v;
+int inverted, value;
+satQueue_t *Q;
+
+  if(arr == 0)	return;
+  if(cm->status)return;
+
+  size = arr->num;
+  Q = cm->queue;
+  for(i=0; i<size; i++) {
+    v = arr->space[i];
+    inverted = SATisInverted(v);
+    v = SATnormalNode(v);
+
+    value = !inverted;
+    if(SATvalue(v) < 2)	{
+      if(SATvalue(v) == value)	continue;
+      else {
+	cm->status = SAT_UNSAT;
+	d->conflict = v;
+	//Bing:
+	return;
+      }
+    }
+
+    SATvalue(v) = value;
+    SATmakeImplied(v, d);
+    //Bing:
+    cm->each->nCNFImplications++;
+    if(cm->option->coreGeneration && cm->option->IP){
+      st_insert(cm->anteTable,(char *)SATnormalNode(v),(char *)SATnormalNode(v));
+    }
+
+    if((SATflags(v) & InQueueMask) == 0) {
+      sat_Enqueue(Q, v);
+      SATflags(v) |= InQueueMask;
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Apply implication on  BDD node. ]
+
+  Description [Apply implication on  BDD node. ]
+
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_ImplyBDD(
+	satManager_t *cm,
+	satLevel_t *d,
+	long v)
+{
+    /** CONSIDER ... **/
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Build level zero hyper implication graph. ]
+
+  Description [Build level zero hyper implication graph. ]
+
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_BuildLevelZeroHyperImplicationGraph(
+	satManager_t *cm)
+{
+    /** CONSIDER...  **/
+}
Index: vis_dev/vis-2.3/src/sat/satInc.c
===================================================================
--- vis_dev/vis-2.3/src/sat/satInc.c	(revision 14)
+++ vis_dev/vis-2.3/src/sat/satInc.c	(revision 14)
@@ -0,0 +1,754 @@
+/**CFile***********************************************************************
+
+  FileName    [satInc.c]
+
+  PackageName [sat]
+
+  Synopsis    [Routines for sat incremental function.]
+
+  Author      [HoonSang Jin]
+
+  Copyright [ This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+
+******************************************************************************/
+
+#include "satInt.h"
+
+static char rcsid[] UNUSED = "$Id: satInc.c,v 1.16 2009/04/11 18:26:37 fabio Exp $";
+static satManager_t *SatCm;
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int ScoreDistillCompare(const void *x, const void *y);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Apply distillation method to find
+		the clauses that can be forwarded]
+
+  Description [ Apply distillation method to find
+		the clauses that can be forwarded]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_IncrementalUsingDistill(satManager_t *cm)
+{
+  sat_TrieBasedImplication(cm, cm->trieArray, 1);
+  sat_FreeTrie(cm, cm->trieArray);
+  cm->trieArray = 0;
+  fprintf(cm->stdOut, "%s %d conflicts are forwarded from distillation,\n",
+	  cm->comment,
+	  cm->each->nDistillObjConflictCl + cm->each->nDistillNonobjConflictCl);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Make decision based on trie when applying distillation ]
+
+  Description [ Make decision based on trie when applying distillation ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+satLevel_t *
+sat_DecisionBasedOnTrie(
+	satManager_t *cm,
+	long v,
+	int value)
+{
+satLevel_t *d;
+
+  d = sat_AllocLevel(cm);
+  d->decisionNode = v;
+
+  SATvalue(v) = value;
+  SATmakeImplied(v, d);
+
+  sat_Enqueue(cm->queue, v);
+  SATflags(v) |= InQueueMask;
+
+  return(d);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Apply implication based on trie]
+
+  Description [ Apply implication based on trie]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_TrieBasedImplication(
+	satManager_t *cm,
+	satArray_t *trieArray,
+	int depth)
+{
+int i;
+satTrie_t *t;
+satLevel_t *d;
+satArray_t *tArray;
+
+  if(trieArray == 0)	return;
+
+  for(i=0; i<trieArray->num; i++) {
+    t = (satTrie_t *)(trieArray->space[i]);
+    if(SATvalue(t->id) < 2)	continue;
+
+    tArray = t->child[0];
+    if(tArray) {
+      d = sat_DecisionBasedOnTrie(cm, t->id, 0);
+      sat_ImplicationMain(cm, d);
+      if(d->conflict) {
+	sat_ConflictAnalysisOnTrie(cm, d);
+      }
+      else if(cm->status == 0) {
+	sat_TrieBasedImplication(cm, tArray, depth+1);
+      }
+      sat_Backtrack(cm, depth-1);
+    }
+
+    tArray = t->child[1];
+    if(tArray && cm->status == 0) {
+      d = sat_DecisionBasedOnTrie(cm, t->id, 1);
+      sat_ImplicationMain(cm, d);
+      if(d->conflict) {
+	sat_ConflictAnalysisOnTrie(cm, d);
+      }
+      else if(cm->status == 0) {
+	sat_TrieBasedImplication(cm, tArray, depth+1);
+      }
+      sat_Backtrack(cm, depth-1);
+    }
+
+    if(cm->status == SAT_BACKTRACK && depth == 1) {
+      cm->status = 0;
+      d = SATgetDecision(0);
+      sat_ImplyArray(cm, d, cm->nonobjUnitLitArray);
+      sat_ImplyArray(cm, d, cm->objUnitLitArray);
+      sat_MarkObjectiveFlagToArray(cm, cm->objUnitLitArray);
+      sat_ImplicationMain(cm, d);
+      if(d->conflict) {
+	cm->status = SAT_UNSAT;
+	return;
+      }
+      i--;
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Conflict analysis based on trie]
+
+  Description [  Conflict analysis based on trie]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_ConflictAnalysisOnTrie(
+	satManager_t *cm,
+	satLevel_t *d)
+{
+int bLevel;
+long v, learned, unitLit;
+int objectFlag;
+satArray_t *clauseArray;
+satStatistics_t *stats;
+
+  bLevel = 0;
+  unitLit = -1;
+  clauseArray = cm->auxArray;
+  sat_FindUIP(cm, clauseArray, d, &objectFlag, &bLevel, &unitLit);
+
+  if(clauseArray->num > (int)(cm->currentDecision*2)) {
+    sat_GetConflictAsConflictClause(cm, clauseArray);
+  }
+
+  if(clauseArray->num == 1) {
+    cm->status = SAT_BACKTRACK;
+    v = clauseArray->space[0];
+    if(objectFlag)
+      sat_ArrayInsert(cm->objUnitLitArray, SATnot(v));
+    else
+      sat_ArrayInsert(cm->nonobjUnitLitArray, SATnot(v));
+  }
+  else {
+    learned = sat_AddClauseIncremental(cm, clauseArray, objectFlag, 1);
+  }
+
+  stats = cm->each;
+  if(objectFlag) {
+    stats->nInitObjConflictCl++;
+    stats->nInitObjConflictLit += clauseArray->num;
+    stats->nObjConflictCl++;
+    stats->nObjConflictLit += clauseArray->num;
+    stats->nDistillObjConflictCl++;
+    stats->nDistillObjConflictLit += clauseArray->num;
+  }
+  else {
+    stats->nInitNonobjConflictCl++;
+    stats->nInitNonobjConflictLit += clauseArray->num;
+    stats->nObjConflictCl++;
+    stats->nObjConflictLit += clauseArray->num;
+    stats->nDistillNonobjConflictCl++;
+    stats->nDistillNonobjConflictLit += clauseArray->num;
+  }
+  stats->nConflictCl++;
+  stats->nConflictLit += clauseArray->num;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Get conflict clauses from the decision variables]
+
+  Description [ When applying distillation,
+		get conflict clauses from the decision variables
+		to create conflict clause ]
+
+  SideEffects [ ]
+
+  SeeAlso     [ ]
+
+******************************************************************************/
+void
+sat_GetConflictAsConflictClause(
+	satManager_t *cm,
+	satArray_t *clauseArray)
+{
+int i;
+satLevel_t *d;
+
+  clauseArray->num = 0;
+  for(i=1; i<=cm->currentDecision; i++) {
+    d = SATgetDecision(i);
+    sat_ArrayInsert(clauseArray,
+	    (d->decisionNode)^(!(SATvalue(d->decisionNode))));
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Restore conflict clauses to use them for current run]
+
+  Description [ Restore conflict clauses to use them for current run]
+
+  SideEffects [ ]
+
+  SeeAlso     [ sat_SaveNonobjClauses sat_SaveAllClauses ]
+
+******************************************************************************/
+void
+sat_RestoreForwardedClauses(satManager_t *cm, int objectFlag)
+{
+int i, size;
+int total;
+long *space, c, *start;
+satArray_t *saved;
+satArray_t *clause;
+//Bing
+ int NotCoi = 0, ct=0;
+
+
+  if(cm->option->checkNonobjForwarding) {
+    sat_CheckForwardedClauses(cm);
+  }
+
+  saved = cm->savedConflictClauses;
+  if(saved == 0)
+    return;
+
+  clause = sat_ArrayAlloc(50);
+
+  total = 0;
+  for(i=0, space=saved->space; i<saved->num; i++, space++){
+    if(*space < 0) {
+      space++;
+      i++;
+      start = space;
+      size = 0;
+      clause->num = 0;
+      //Bing:
+      NotCoi = 0;
+      while(*space > 0) {
+	sat_ArrayInsert(clause, SATnot((*space)));
+	//Bing:
+	if(!(SATflags(*space)&CoiMask)){
+	  NotCoi = 1;
+	}
+	size++;
+	i++;
+	space++;
+      }
+
+
+      //Bing:
+      if(cm->option->AbRf){
+	if(!NotCoi){
+	  c = sat_AddClauseIncremental(cm, clause, objectFlag, 0);
+	  total++;
+	}
+	else
+	  ct++;
+      }
+      else{
+	c = sat_AddClauseIncremental(cm, clause, objectFlag, 0);
+	total++;
+      }
+    }
+  }
+  sat_ArrayFree(clause);
+  sat_ArrayFree(saved);
+  cm->savedConflictClauses = 0;
+
+/**  fprintf(cm->stdOut, "%s %d clauses are forwarded by reststoring
+     non-objective\n", cm->comment, total) ; **/
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Check whether the given conflict clauses can be forwared ]
+
+  Description [ Check whether the given conflict clauses can be forwared ]
+
+  SideEffects [ ]
+
+  SeeAlso     [ ]
+
+******************************************************************************/
+void
+sat_CheckForwardedClauses(satManager_t *cm)
+{
+long *space, *start;
+long nv;
+int size, i;
+int total;
+int conflictFlag, inverted;
+int j, value, level;
+satLevel_t *d;
+satArray_t *saved;
+satArray_t *clause;
+
+  d = 0;
+  saved = cm->savedConflictClauses;
+  if(saved == 0)
+    return;
+
+  clause = sat_ArrayAlloc(50);
+
+  total = 0;
+  for(i=0, space=saved->space; i<saved->num; i++, space++){
+    if(*space < 0) {
+      start = space;
+      space++;
+      i++;
+      size = 0;
+      clause->num = 0;
+      conflictFlag = 0;
+      while(*space > 0) {
+	sat_ArrayInsert(clause, SATnot((*space)));
+	if(conflictFlag == 0) {
+	  nv = *space;
+	  inverted = (SATisInverted(nv));
+	  nv = SATnormalNode(nv);
+
+	  d = sat_AllocLevel(cm);
+	  d->decisionNode = nv;
+	  SATvalue(nv) = inverted;
+	  SATmakeImplied(nv, d);
+
+	  sat_Enqueue(cm->queue, nv);
+	  SATflags(nv) |= InQueueMask;
+
+	  sat_ImplicationMain(cm, d);
+	  if(d->conflict)	conflictFlag = 1;
+	}
+	size++;
+	i++;
+	space++;
+      }
+
+      if(d->conflict == 0) {
+	fprintf(cm->stdOut, "%s ERROR : %ld does not result in conflict\n",
+	    cm->comment, *start);
+	for(j=0; j<clause->num; j++) {
+	  nv = clause->space[j];
+	  inverted = SATisInverted(nv);
+	  nv = SATnormalNode(nv);
+	  value = SATvalue(nv);
+	  level = value>1 ? -1 : SATlevel(nv);
+	  fprintf(cm->stdOut, "%6ld%c@%d=%c%c ",
+		  nv, inverted ? '\'' : ' ', level, SATgetValueChar(value),
+		  ' ');
+	}
+	fprintf(cm->stdOut, "\n");
+      }
+      sat_Backtrack(cm, -1);
+
+      total++;
+    }
+  }
+  sat_ArrayFree(clause);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Save objective independent conflict clauses]
+
+  Description [ When applying incremental SAT, one has to save objective
+		independent conflict clause  They are restored by
+		sat_RestoreForwardedClauses ]
+
+  SideEffects [ ]
+
+  SeeAlso     [ sat_RestoreForwardedClauses ]
+
+******************************************************************************/
+void
+sat_SaveNonobjClauses(satManager_t *cm)
+{
+int limit, total, passed;
+int size, j;
+long *plit, nv, v, i;
+satArray_t *savedArray;
+
+  savedArray = sat_ArrayAlloc(1024);
+
+  total = passed = 0;
+  limit = cm->option->incNumNonobjLitsLimit;
+  for(i=cm->beginConflict; i<cm->nodesArraySize; i+= satNodeSize) {
+    if(SATreadInUse(i) == 0)		continue;
+    if(!(SATflags(i) & NonobjMask))	{
+      continue;
+    }
+    size = SATnumLits(i);
+    if(size > limit) {
+      total++;
+    }
+    else {
+      total++;
+      passed++;
+      plit = (long*)SATfirstLit(i);
+      nv = (*(plit-1));
+      sat_ArrayInsert(savedArray, nv);
+      for(j=0; j<size; j++, plit++) {
+	v = SATgetNode(*plit);
+	sat_ArrayInsert(savedArray, v);
+      }
+      sat_ArrayInsert(savedArray, nv);
+    }
+  }
+  if(cm->option->verbose > 1) {
+    fprintf(cm->stdOut, "%s %d NonObjective Clauses forwarded out of %d\n",
+	    cm->comment, passed, total);
+  }
+  cm->savedConflictClauses = savedArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Save all conflict clauses]
+
+  Description [ When applying incremental SAT for BMC,
+		one can forward all the clauses
+		They are restored by sat_RestoreForwardedClauses ]
+
+  SideEffects [ ]
+
+  SeeAlso     [ sat_RestoreForwardedClauses ]
+
+******************************************************************************/
+void
+sat_SaveAllClauses(satManager_t *cm)
+{
+int limit, total, passed;
+int size, j;
+long *plit, nv, v, i;
+satArray_t *savedArray;
+
+  savedArray = sat_ArrayAlloc(1024);
+
+  total = passed = 0;
+  limit = cm->option->incNumNonobjLitsLimit;
+  for(i=cm->beginConflict; i<cm->nodesArraySize; i+= satNodeSize) {
+    if(SATreadInUse(i) == 0)		continue;
+    size = SATnumLits(i);
+    total++;
+    plit = (long*)SATfirstLit(i);
+    nv = (*(plit-1));
+    sat_ArrayInsert(savedArray, nv);
+    for(j=0; j<size; j++, plit++) {
+      v = SATgetNode(*plit);
+      sat_ArrayInsert(savedArray, v);
+    }
+    sat_ArrayInsert(savedArray, nv);
+  }
+  /**
+  if(cm->option->verbose > 1) {
+    fprintf(cm->stdOut, "%s %d clauses are forwarded\n",
+	    cm->comment, total);
+  }
+  **/
+  cm->savedConflictClauses = savedArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Build Trie with objective dependent conflict clauses]
+
+  Description [ When applying incremental SAT based on distillation
+		build Trie with objective dependent conflict clauses.]
+
+  SideEffects [ ]
+
+  SeeAlso     [ sat_BuildTrie ]
+
+******************************************************************************/
+void
+sat_BuildTrieForDistill(satManager_t *cm)
+{
+int limit, nCl, nLit;
+int j, n;
+int size, inverted;
+long v, *plit, i;
+int findFlag;
+satVariable_t *var;
+satArray_t *trieArray;
+satArray_t *unitArray;
+satTrie_t *t;
+
+  size = cm->initNumVariables * satNodeSize;
+  for(i=satNodeSize; i<size; i+= satNodeSize) {
+    var = SATgetVariable(i);
+    var->scores[0] = 0;
+    var->scores[1] = 0;
+  }
+
+  nCl = nLit = 0;
+  limit = cm->option->incNumObjLitsLimit;
+  for(i=cm->beginConflict; i<cm->nodesArraySize; i+= satNodeSize) {
+    if(SATreadInUse(i) == 0)		continue;
+    if(SATflags(i) & NonobjMask)	continue;
+
+    size = SATnumLits(i);
+    if(size > limit)	continue;
+    n = 0;
+    for(j=0, plit = (long*)SATfirstLit(i); j<size; j++, plit++) {
+      v = SATgetNode(*plit);
+      inverted = SATisInverted(v);
+      v = SATnormalNode(v);
+      var = SATgetVariable(v);
+      var->scores[inverted] += 1;
+      if(SATvalue(v) < 2)	continue;
+      n++;
+    }
+    if(n > 0) {
+      nCl++;
+      nLit += n;
+    }
+  }
+  if(cm->option->verbose > 1) {
+    fprintf(cm->stdOut, "%s Candidates for Distill %d clauses %d literals\n",
+	    cm->comment, nCl, nLit);
+  }
+
+  trieArray = sat_ArrayAlloc(64);
+  cm->trieArray = trieArray;
+  unitArray = cm->objUnitLitArray;
+  if(unitArray) {
+    for(i=0; i<unitArray->num; i++) {
+      v = unitArray->space[i];
+      inverted = SATisInverted(v);
+      v = SATnormalNode(v);
+
+      findFlag = 0;
+      for(j=0;  j<trieArray->num; j++) {
+	t = (satTrie_t *)(trieArray->space[j]);
+	if(t->id == v) {
+	  if(t->child[inverted] == 0)
+	    t->child[inverted] = sat_ArrayAlloc(2);
+	  findFlag = 1;
+	}
+      }
+
+      if(findFlag == 0) {
+	t = ALLOC(satTrie_t, 1);
+	memset(t, 0, sizeof(satTrie_t));
+	t->id = v;
+	if(t->child[inverted] == 0)
+	  t->child[inverted] = sat_ArrayAlloc(2);
+	sat_ArrayInsert(trieArray, (long)t);
+      }
+    }
+  }
+
+  for(i=cm->beginConflict; i<cm->nodesArraySize; i+=satNodeSize) {
+    if(SATreadInUse(i) == 0)		continue;
+    if(SATflags(i) & NonobjMask)	continue;
+
+    size = SATnumLits(i);
+    if(size > limit)	continue;
+
+    plit = (long*)SATfirstLit(i);
+    SatCm = cm;
+    qsort(plit, size, sizeof(long), ScoreDistillCompare);
+    sat_BuildTrie(cm, trieArray, plit, 1);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Build Trie with objective dependent conflict clauses]
+
+  Description [ When applying incremental SAT based on distillation
+		build Trie with objective dependent conflict clauses.]
+
+  SideEffects [ ]
+
+  SeeAlso     [ sat_BuildTrieForDistill ]
+
+******************************************************************************/
+void
+sat_BuildTrie(
+	satManager_t *cm,
+	satArray_t *trieArray,
+	long *plit,
+	int depth)
+{
+int i, inverted;
+long v;
+satTrie_t *t;
+
+  while(1) {
+    if(*plit <= 0)	return;
+    v = SATgetNode(*plit);
+    inverted = SATisInverted(v);
+    v = SATnormalNode(v);
+    if(SATvalue(v) < 2)plit++;
+    else		break;
+  }
+
+  for(i=0; i<trieArray->num; i++) {
+    t = (satTrie_t *)(trieArray->space[i]);
+    if(t->id == v) {
+      if(t->child[inverted] == 0)
+	t->child[inverted] = sat_ArrayAlloc(2);
+      plit++;
+      sat_BuildTrie(cm, t->child[inverted], plit, depth+1);
+      return;
+    }
+  }
+
+  t = ALLOC(satTrie_t, 1);
+  memset(t, 0, sizeof(satTrie_t));
+  t->id = v;
+  t->depth = depth;
+  sat_ArrayInsert(trieArray, (long)t);
+
+  if(t->child[inverted] == 0)
+    t->child[inverted] = sat_ArrayAlloc(2);
+  plit++;
+  sat_BuildTrie(cm, t->child[inverted], plit, depth+1);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Free trie structure ]
+
+  Description [ Free trie structure ]
+
+  SideEffects [ ]
+
+  SeeAlso     [ sat_BuildTrieForDistill ]
+
+******************************************************************************/
+void
+sat_FreeTrie(satManager_t *cm, satArray_t *arr)
+{
+int i;
+satTrie_t *t;
+
+  if(arr == 0)	return;
+
+  for(i=0; i<arr->num; i++) {
+    t = (satTrie_t *)(arr->space[i]);
+    if(t->child[0]) {
+      sat_FreeTrie(cm, t->child[0]);
+      sat_ArrayFree(t->child[0]);
+    }
+    if(t->child[1]) {
+      sat_FreeTrie(cm, t->child[1]);
+      sat_ArrayFree(t->child[1]);
+    }
+    free(t);
+  }
+
+}
+/**Function********************************************************************
+
+  Synopsis    [ sort variable order based on occurrence to build Trie ]
+
+  Description [ sort variable order based on occurrence to build Trie ]
+
+  SideEffects [ ]
+
+  SeeAlso     [ sat_BuildTrieForDistill ]
+
+******************************************************************************/
+static int
+ScoreDistillCompare(const void *x, const void *y)
+{
+int n1, n2;
+int i1, i2;
+satVariable_t  v1, v2;
+
+  n1 = *(int *)x;
+  n2 = *(int *)y;
+  n1 >>= 2;
+  n2 >>= 2;
+  i1 = SATisInverted(n1);
+  n1 = SATnormalNode(n1);
+  i2 = SATisInverted(n2);
+  n2 = SATnormalNode(n2);
+  v1 = SatCm->variableArray[SATnodeID(n1)];
+  v2 = SatCm->variableArray[SATnodeID(n2)];
+
+  if(v1.scores[i1] == v2.scores[i2]) {
+    return(n1 > n2);
+  }
+  return(v1.scores[i1] < v2.scores[i2]);
+}
Index: vis_dev/vis-2.3/src/sat/satInt.h
===================================================================
--- vis_dev/vis-2.3/src/sat/satInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/sat/satInt.h	(revision 14)
@@ -0,0 +1,112 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [satInt.h]
+
+  PackageName [sat]
+
+  Synopsis    []
+
+  Description [Internal data structures of the sat package.]
+
+  SeeAlso     []
+
+  Author      [HoonSang Jin ]
+
+  Copyright [ This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+  Revision    [$Id: satInt.h,v 1.19 2009/04/11 18:26:37 fabio Exp $]
+
+******************************************************************************/
+
+
+#ifndef _SATINT
+#define _SATINT
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "baig.h"
+#include "sat.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define LATEST_ACTIVITY_DELETION 0x1
+#define MAX_UNRELEVANCE_DELETION 0x2
+#define SIMPLE_LATEST_DELETION   0x4
+
+/*Bing:*/
+#define RESET_LC 0xfffffffe
+#define RESET_DVH  0xfffffffd
+#define SCOREUNIT 100000
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [sat option]
+
+  Description []
+
+******************************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN satLevel_t * sat_GetDecision( satManager_t *cm, int level);
+EXTERN satArray_t * sat_ArrayAlloc(long number);
+EXTERN int sat_ImplyStop( satManager_t *cm, satLevel_t *d, long v, long left, long right);
+EXTERN int sat_ImplySplit( satManager_t *cm, satLevel_t *d, long v, long left, long right);
+EXTERN int sat_ImplyConflict( satManager_t *cm, satLevel_t *d, long v, long left, long right);
+EXTERN int sat_ImplyLeftForward( satManager_t *cm, satLevel_t *d, long v, long left, long right);
+EXTERN int sat_ImplyRightForward( satManager_t *cm, satLevel_t *d, long v, long left, long right);
+EXTERN int sat_ImplyForwardOne( satManager_t *cm, satLevel_t *d, long v, long left, long right);
+EXTERN int sat_ImplyPropRight( satManager_t *cm, satLevel_t *d, long v, long left, long right);
+EXTERN int sat_ImplyPropRightOne( satManager_t *cm, satLevel_t *d, long v, long left, long right);
+EXTERN int sat_ImplyPropLeft( satManager_t *cm, satLevel_t *d, long v, long left, long right);
+EXTERN int sat_ImplyPropLeftOne( satManager_t *cm, satLevel_t *d, long v, long left, long right);
+EXTERN int sat_ImplyPropLeftRight( satManager_t *cm, satLevel_t *d, long v, long left, long right);
+EXTERN satQueue_t * sat_CreateQueue( long MaxElements );
+EXTERN satStatistics_t * sat_InitStatistics(void);
+EXTERN int  sat_BacktrackWithAdditionalTest( satManager_t *cm, int level);
+EXTERN satLinearHead_t * sat_CreateLinearHead( satManager_t *cm, int flag);
+EXTERN satLinearCluster_t * sat_CreateCluster( satLinearHead_t *head, satLinearElem_t *e1, satLinearElem_t *e2, int flagIndex, int *idArr);
+EXTERN void sat_ExtractAssignmentFromBDD( satLinearHead_t *head, DdManager *mgr, satArray_t *arr, DdNode *cube);
+EXTERN DdNode *sat_CofactorBDDArray( satLinearHead_t *head, DdManager *mgr, DdNode *l1, satArray_t *satArr);
+EXTERN char * sat_RemoveSpace(char *line);
+EXTERN char * sat_CopyWord(char *lp, char *word);
+EXTERN satLinearHead_t * sat_CreateHeadForUIP(satManager_t *cm);
+EXTERN DdNode * sat_BuildBDDForClause( satManager_t *cm, satLinearHead_t *head, long v, int includeLevel, satArray_t *arr);
+EXTERN int  sat_GetUIPFromGivenBDD(satLinearHead_t *head, DdManager *mgr, DdNode *total, satArray_t *arr);
+EXTERN void RT_Free(RTManager_t *rm);
+EXTERN void ResetRTree(RTManager_t *rm);
+EXTERN bAigEdge_t sat_GenerateFwdIP(bAig_Manager_t* manager, satManager_t *cm, RTnode_t  RTnode, int cut);
+EXTERN void sat_BuildRT(satManager_t * cm, RTnode_t root, long *lp, long *tmpIP, int size, boolean NotCNF);
+EXTERN void sat_GenerateCore_All(satManager_t * cm);
+EXTERN void sat_InitLayerScore(satManager_t * cm);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _SATINT */
Index: vis_dev/vis-2.3/src/sat/satInterface.c
===================================================================
--- vis_dev/vis-2.3/src/sat/satInterface.c	(revision 14)
+++ vis_dev/vis-2.3/src/sat/satInterface.c	(revision 14)
@@ -0,0 +1,727 @@
+/**CFile***********************************************************************
+
+  FileName    [satInterface.c]
+
+  PackageName [sat]
+
+  Synopsis    [Routines for various decision heuristics.]
+
+  Author      [HoonSang Jin]
+
+  Copyright [ This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+
+******************************************************************************/
+
+#include "satInt.h"
+
+static char rcsid[] UNUSED = "$Id: satInterface.c,v 1.20 2009/04/11 18:26:37 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Set option for unsat core generation]
+
+  Description [Set option for unsat core generation]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void sat_SetOptionForUP(satManager_t * cm)
+{
+  cm->option->includeLevelZeroLiteral = 1;
+  cm->option->minimizeConflictClause = 0;
+  cm->option->clauseDeletionHeuristic = 0;
+  cm->dependenceTable = st_init_table(st_ptrcmp, st_ptrhash);
+  cm->anteTable = st_init_table(st_numcmp, st_numhash);
+  cm->fp = fopen(cm->option->unsatCoreFileName, "w");
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Read CNF]
+
+  Description [Read CNF]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_ReadCNF(satManager_t *cm, char *filename)
+{
+FILE *fin;
+satArray_t *clauseArray;
+char line[16384], word[1024], *lp;
+int nVar, nCl, nArg;
+int i, id, sign;
+long v;
+int begin;
+ long cls_idx;
+
+  if(!(fin = fopen(filename, "r"))) {
+    fprintf(cm->stdOut, "%s ERROR : Can't open CNF file %s\n",
+	    cm->comment, filename);
+    return(0);
+  }
+
+  //Bing: for unsat core
+  if(cm->option->coreGeneration)
+    sat_SetOptionForUP(cm);
+
+  begin = 0;
+  clauseArray = sat_ArrayAlloc(1024);
+  while(fgets(line, 16384, fin)) {
+    lp = sat_RemoveSpace(line);
+    if(lp[0] == '\n')	continue;
+    if(lp[0] == '#')	continue;
+    if(lp[0] == 'c')	continue;
+    if(lp[0] == 'p') {
+      nArg = sscanf(line, "p cnf %d %d", &nVar, &nCl);
+      if(nArg < 2) {
+	fprintf(cm->stdErr, "ERROR : Unable to read the number of variables and clauses from CNF file %s\n", filename);
+	fclose(fin);
+	sat_ArrayFree(clauseArray);
+	return(0);
+      }
+      begin = 1;
+
+      for(i=1; i<=nVar; i++) {
+	v = sat_CreateNode(cm, 2, 2);
+	SATflags(v) |= CoiMask;
+	SATvalue(v) = 2;
+      }
+
+      cm->initNumVariables = nVar;
+      cm->variableArray = ALLOC(satVariable_t, cm->initNumVariables+1);
+      memset(cm->variableArray, 0, sizeof(satVariable_t) * (cm->initNumVariables+1));
+      continue;
+    }
+    else if(begin == 0)	continue;
+
+    clauseArray->num = 0;
+    while(1) {
+      lp = sat_RemoveSpace(lp);
+      lp = sat_CopyWord(lp, word);
+
+      if(strlen(word)) {
+	id = atoi(word);
+	sign = 1;
+
+	if(id != 0) {
+	  if(id < 0) {
+	    id = -id;
+	    sign = 0;
+	  }
+	  sat_ArrayInsert(clauseArray, (id*satNodeSize + sign));
+	}
+	else {
+	  if(clauseArray->num == 1) {
+	    v = clauseArray->space[0];
+	    sat_ArrayInsert(cm->unitLits, SATnot(v));
+	    cm->initNumClauses++;
+	    cm->initNumLiterals += clauseArray->num;
+	    //Bing: for unsat core
+	    if(cm->option->coreGeneration){
+	      cls_idx = sat_AddUnitClause(cm, clauseArray);
+	      if(cm->option->coreGeneration){
+		v = SATnormalNode(v);
+		st_insert(cm->anteTable,(char *)v,(char *)cls_idx);
+	      }
+	    }
+	  }
+	  else {
+	    sat_AddClause(cm, clauseArray);
+	    cm->initNumClauses++;
+	    cm->initNumLiterals += clauseArray->num;
+	  }
+	  break;
+	}
+      }
+    }
+  }
+  if(cm->initNumClauses == 0) {
+    fprintf(cm->stdOut, "%s ERROR : CNF is not valid\n", cm->comment);
+    return(0);
+  }
+
+  if(cm->initNumClauses != nCl) {
+    fprintf(cm->stdOut, "%s WARNING : wrong number of clauses\n", cm->comment);
+  }
+
+  fclose(fin);
+  sat_ArrayFree(clauseArray);
+
+  return(1);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Read CNF from Array]
+
+  Description [Read CNF from Array]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_ReadCNFFromArray(
+	satManager_t *cm,
+	satArray_t *cnfArray,
+	st_table *mappedTable)
+{
+satArray_t *clauseArray;
+int nVar, nCl;
+int i;
+long tv, v, c, *space;
+
+  if(cnfArray == 0) {
+    fprintf(cm->stdOut, "%s ERROR : Can't find CNF array \n", cm->comment);
+    return(0);
+  }
+
+  nVar = 0;
+  nCl = 0;
+  for(i=1; i<cnfArray->num; i++) {
+    v = cnfArray->space[i];
+    if(v <= 0)	nCl++;
+    else {
+      v = SATnormalNode(v);
+      if(v > nVar)	nVar = v;
+    }
+  }
+  nVar = nVar / satNodeSize;
+  for(i=1; i<=nVar; i++) {
+    v = sat_CreateNode(cm, 2, 2);
+    SATflags(v) |= CoiMask;
+    SATvalue(v) = 2;
+  }
+
+  cm->initNumVariables = nVar;
+  cm->variableArray = ALLOC(satVariable_t, cm->initNumVariables+1);
+  memset(cm->variableArray, 0, sizeof(satVariable_t) * (cm->initNumVariables+1));
+
+  clauseArray = sat_ArrayAlloc(1024);
+  for(i=0, space=cnfArray->space; i<cnfArray->num; i++, space++){
+    if(*space <= 0) {
+      space++;
+      i++;
+      if(i>=cnfArray->num)
+	break;
+      clauseArray->num = 0;
+      while(*space > 0) {
+	v = (*space);
+	sat_ArrayInsert(clauseArray, SATnot(v));
+	i++;
+	space++;
+      }
+
+      /**
+       * If clause is blocking clause then it has clause index in it.
+       **/
+      tv = *space;
+
+      if(clauseArray->num > 1)
+	c = sat_AddClause(cm, clauseArray);
+      else {
+	c = sat_AddUnitClause(cm, clauseArray);
+	if(cm->option->coreGeneration) {
+	  st_insert(cm->anteTable,(char *)(long)(SATnormalNode(v)),(char *)(long)c);
+	}
+      }
+      if(clauseArray->num == 1)
+	sat_ArrayInsert(cm->unitLits, (v));
+
+      if(tv < -1) { /* this is blocking clause */
+	st_insert(mappedTable, (char *)c, (char *)(-tv));
+      }
+
+      cm->initNumClauses++;
+      cm->initNumLiterals += clauseArray->num;
+      i--;
+      space--;
+    }
+  }
+  sat_ArrayFree(clauseArray);
+
+
+  return(1);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Write CNF from Array]
+
+  Description [Write CNF from Array]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_WriteCNFFromArray(satArray_t *cnfArray, char *filename)
+{
+FILE *fin;
+int nVar, nCl;
+int i ;
+long v, *space;
+
+  if(cnfArray == 0) {
+    fprintf(stdout, "ERROR : Can't find CNF array \n");
+    return(0);
+  }
+
+  if(!(fin=fopen(filename, "w"))) {
+    fprintf(stdout, "ERROR : Can't find file %s\n", filename);
+    return(0);
+  }
+
+  nVar = 0;
+  nCl = 0;
+  for(i=1; i<cnfArray->num; i++) {
+    v = cnfArray->space[i];
+    if(v <= 0)	nCl++;
+    else {
+      v = SATnormalNode(v);
+      if(v > nVar)	nVar = v;
+    }
+  }
+  nVar = nVar / satNodeSize;
+
+  fprintf(fin, "p cnf %d %d\n", nVar, nCl);
+
+  for(i=0, space=cnfArray->space; i<cnfArray->num; i++, space++){
+    if(*space <= 0) {
+      space++;
+      i++;
+      if(i>=cnfArray->num)
+	break;
+
+      while(*space > 0) {
+	v = (*space);
+	if(SATisInverted(v))	v = -(SATnodeID(v));
+	else			v = SATnodeID(v);
+	fprintf(fin, "%ld ", v);
+	i++;
+	space++;
+      }
+      fprintf(fin, "0\n");
+
+      i--;
+      space--;
+    }
+  }
+  fclose(fin);
+
+  return(1);
+}
+/**Function********************************************************************
+
+  Synopsis    [Copy word from lp to word]
+
+  Description [Copy word from lp to word and lp moved to next word.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+char *
+sat_CopyWord(char *lp, char *word)
+{
+char *wp;
+
+  for(wp = word; ; lp++, wp++) {
+    if((*lp == ' ') || (*lp == '\t') || (*lp == '\n'))	break;
+    *wp = *lp;
+  }
+  *wp = '\0';
+  return(lp);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [skip space and return the beginning of word ]
+
+  Description [skip space and return the beginning of word ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+char *
+sat_RemoveSpace(char *line)
+{
+int i;
+
+  for(i=0; ; i++) {
+    if(line[i] == ' ')		continue;
+    else if(line[i] == '\t')	continue;
+    return(&(line[i]));
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Write CNF file under partial assignment]
+
+  Description [Write CNF file under partial assignment.
+		If a literal in a clause is satisfied then the clause is
+		ignored. If a literal in a clause is unsatisfied then the
+		literal is ignored.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_WriteCNFWithPartialAssignment(satManager_t *cm, char *filename)
+{
+int nVars, nCls, j;
+int size, satisfied;
+int inverted, value;
+long *plit, v, tv, tsize, i;
+FILE *fout;
+
+  nVars = 0;
+  nCls = 0;
+  tsize = (cm->beginConflict == 0) ? cm->nodesArraySize : cm->beginConflict;
+  for(i=satNodeSize; i<tsize; i+=satNodeSize) {
+    if(SATleftChild(i) == 2 && SATrightChild(i) == 2)	continue;
+    if(!(SATflags(i) & IsCNFMask))	{
+      if(!(SATflags(i) & CoiMask))	continue;
+      fprintf(cm->stdOut, "Warning : current implementation can't take care of AIG node\n");
+      continue;
+    }
+    if(SATreadInUse(i) == 0)	continue;
+
+    size = SATnumLits(i);
+    satisfied = 0;
+    plit = (long *)SATfirstLit(i);
+    for(j=0; j<size; j++, plit++) {
+      v = SATgetNode(*plit);
+      inverted = SATisInverted(v);
+      v = SATnormalNode(v);
+      value = SATvalue(v) ^ inverted;
+      if(value == 1) {
+	satisfied = 1;
+	break;
+      }
+      if(v > nVars)	nVars = v;
+    }
+    if(satisfied)	continue;
+
+    nCls++;
+  }
+  nVars /= satNodeSize;
+
+  if(!(fout = fopen(filename, "w"))) {
+    fprintf(cm->stdOut, "%s ERROR : Can't open file %s\n",
+	    cm->comment, filename);
+    exit(0);
+  }
+
+  fprintf(fout, "p cnf %d %d\n", nVars, nCls);
+  tsize = (cm->beginConflict == 0) ? cm->nodesArraySize : cm->beginConflict;
+  for(i=satNodeSize; i<tsize; i+=satNodeSize) {
+    if(SATleftChild(i) == 2 && SATrightChild(i) == 2)	continue;
+    if(!(SATflags(i) & IsCNFMask))	{
+      if(!(SATflags(i) & CoiMask))	continue;
+      continue;
+    }
+    if(SATreadInUse(i) == 0)	continue;
+
+    satisfied = 0;
+    size = SATnumLits(i);
+    plit = (long *)SATfirstLit(i);
+    for(j=0; j<size; j++, plit++) {
+      v = SATgetNode(*plit);
+      inverted = SATisInverted(v);
+      v = SATnormalNode(v);
+      value = SATvalue(v) ^ inverted;
+      if(value == 1) {
+	satisfied = 1;
+	break;
+      }
+    }
+    if(satisfied)	continue;
+
+    plit = (long *)SATfirstLit(i);
+    for(j=0; j<size; j++, plit++) {
+      v = SATgetNode(*plit);
+      inverted = SATisInverted(v);
+      v = SATnormalNode(v);
+      value = SATvalue(v) ^ inverted;
+      if(value < 2) {
+	continue;
+      }
+      tv = SATnodeID(v);
+      fprintf(fout, "%ld ", inverted ? -tv : tv);
+    }
+    fprintf(fout, "0\n");
+  }
+  fclose(fout);
+}
+/**Function********************************************************************
+
+  Synopsis    [ Write CNF ]
+
+  Description [ Write CNF ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_WriteCNF(satManager_t *cm, char *filename)
+{
+FILE *fout;
+long i, tv, *plit, size, j;
+int csize, inverted;
+int nVar, nCl;
+long left, right;
+
+  if(!(fout = fopen(filename, "w"))) {
+    fprintf(cm->stdOut, "%s ERROR : Can't open file %s\n",
+	    cm->comment, filename);
+    exit(0);
+  }
+
+  nVar = cm->initNumVariables;
+  nCl = 0;
+  size = (cm->beginConflict == 0) ? cm->nodesArraySize : cm->beginConflict;
+  for(i=satNodeSize; i<size; i+=satNodeSize) {
+    if(SATleftChild(i) == 2 && SATrightChild(i) == 2)	continue;
+    if(SATflags(i) & IsCNFMask) {
+      if(SATreadInUse(i) == 0)	continue;
+      nCl++;
+      continue;
+    }
+    if(!(SATflags(i) & CoiMask))	continue;
+    nCl += 3;
+  }
+  sat_CountUnitLiteralClauses(cm, cm->assertion, &nCl);
+  sat_CountUnitLiteralClauses(cm, cm->unitLits, &nCl);
+  sat_CountUnitLiteralClauses(cm, cm->auxObj, &nCl);
+  sat_CountUnitLiteralClauses(cm, cm->obj, &nCl);
+
+  fprintf(fout, "p cnf %d %d\n", nVar, nCl);
+
+  sat_PrintUnitLiteralClauses(cm, cm->assertion, fout);
+  sat_PrintUnitLiteralClauses(cm, cm->unitLits, fout);
+  sat_PrintUnitLiteralClauses(cm, cm->auxObj, fout);
+  sat_PrintUnitLiteralClauses(cm, cm->obj, fout);
+
+  size = (cm->beginConflict == 0) ? cm->nodesArraySize : cm->beginConflict;
+  for(i=satNodeSize; i<size; i+=satNodeSize) {
+    if(SATleftChild(i) == 2 && SATrightChild(i) == 2)	continue;
+    if(SATflags(i) & IsCNFMask) {
+      csize = SATnumLits(i);
+      plit = (long*)SATfirstLit(i);
+      for(j=0; j<csize; j++, plit++) {
+	 tv = SATgetNode(*plit);
+	 inverted = SATisInverted(tv);
+	 tv = SATnormalNode(tv);
+	 tv = SATnodeID(tv);
+	 fprintf(fout, "%ld ", inverted ? -tv : tv);
+      }
+      fprintf(fout, "0\n");
+      continue;
+    }
+    if(!(SATflags(i) & CoiMask))	continue;
+
+
+    left = SATleftChild(i);
+    inverted = SATisInverted(left);
+    left = SATnormalNode(left);
+    left = SATnodeID(left);
+    left = inverted ? -left : left;
+
+    right = SATrightChild(i);
+    inverted = SATisInverted(right);
+    right = SATnormalNode(right);
+    right = SATnodeID(right);
+    right = inverted ? -right : right;
+
+    j = SATnodeID(i);
+
+    fprintf(fout, "%ld %ld %ld 0\n", -left, -right, j);
+    fprintf(fout, "%ld %ld 0\n", left, -j);
+    fprintf(fout, "%ld %ld 0\n", right, -j);
+  }
+
+  fclose(fout);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Write CNF ]
+
+  Description [ Write CNF ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_WriteCNFWithPointer(satManager_t *cm, FILE *fout)
+{
+long i, j, size, tv, *plit;
+int csize, inverted;
+int nVar, nCl;
+long left, right;
+
+  nVar = cm->initNumVariables;
+  nCl = 0;
+  size = (cm->beginConflict == 0) ? cm->nodesArraySize : cm->beginConflict;
+  for(i=satNodeSize; i<size; i+=satNodeSize) {
+    if(SATleftChild(i) == 2 && SATrightChild(i) == 2)	continue;
+    if(SATflags(i) & IsCNFMask) {
+      if(SATreadInUse(i) == 0)	continue;
+      nCl++;
+      continue;
+    }
+    if(!(SATflags(i) & CoiMask))	continue;
+    nCl += 3;
+  }
+  sat_CountUnitLiteralClauses(cm, cm->assertion, &nCl);
+  sat_CountUnitLiteralClauses(cm, cm->unitLits, &nCl);
+  sat_CountUnitLiteralClauses(cm, cm->auxObj, &nCl);
+  sat_CountUnitLiteralClauses(cm, cm->obj, &nCl);
+
+  fprintf(fout, "p cnf %d %d\n", nVar, nCl);
+
+  sat_PrintUnitLiteralClauses(cm, cm->assertion, fout);
+  sat_PrintUnitLiteralClauses(cm, cm->unitLits, fout);
+  sat_PrintUnitLiteralClauses(cm, cm->auxObj, fout);
+  sat_PrintUnitLiteralClauses(cm, cm->obj, fout);
+
+  size = (cm->beginConflict == 0) ? cm->nodesArraySize : cm->beginConflict;
+  for(i=satNodeSize; i<size; i+=satNodeSize) {
+    if(SATleftChild(i) == 2 && SATrightChild(i) == 2)	continue;
+    if(SATflags(i) & IsCNFMask) {
+      csize = SATnumLits(i);
+      plit = (long*)SATfirstLit(i);
+      for(j=0; j<csize; j++, plit++) {
+	 tv = SATgetNode(*plit);
+	 inverted = SATisInverted(tv);
+	 tv = SATnormalNode(tv);
+	 tv = SATnodeID(tv);
+	 fprintf(fout, "%ld ", inverted ? -tv : tv);
+      }
+      fprintf(fout, "0\n");
+      continue;
+    }
+    if(!(SATflags(i) & CoiMask))	continue;
+
+
+    left = SATleftChild(i);
+    inverted = SATisInverted(left);
+    left = SATnormalNode(left);
+    left = SATnodeID(left);
+    left = inverted ? -left : left;
+
+    right = SATrightChild(i);
+    inverted = SATisInverted(right);
+    right = SATnormalNode(right);
+    right = SATnodeID(right);
+    right = inverted ? -right : right;
+
+    j = SATnodeID(i);
+
+    fprintf(fout, "%ld %ld %ld 0\n", -left, -right, j);
+    fprintf(fout, "%ld %ld 0\n", left, -j);
+    fprintf(fout, "%ld %ld 0\n", right, -j);
+  }
+
+}
+/**Function********************************************************************
+
+  Synopsis    [ Count the number of unit literal clauses ]
+
+  Description [ Count the number of unit literal clauses ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_CountUnitLiteralClauses(
+	satManager_t *cm,
+	satArray_t *arr,
+	int *nCl)
+{
+int i, count;
+long v;
+
+  if(arr == 0)	return;
+  count = 0;
+  for(i=0; i<arr->num; i++) {
+    v = arr->space[i];
+    if(v == 1)	count++;
+  }
+
+  *nCl += arr->num - count;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Print unit literal clauses ]
+
+  Description [ Print unit literal clauses ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_PrintUnitLiteralClauses(
+	satManager_t *cm,
+	satArray_t *arr,
+	FILE *fout)
+{
+int i, inverted;
+long v;
+
+  if(arr == 0)	return;
+  for(i=0; i<arr->num; i++) {
+    v = arr->space[i];
+    if(v == 1)	continue;
+    inverted = SATisInverted(v);
+    v = SATnormalNode(v);
+    v = SATnodeID(v);
+    fprintf(fout, "%ld 0\n", inverted ? -v : v);
+  }
+}
Index: vis_dev/vis-2.3/src/sat/satMain.c
===================================================================
--- vis_dev/vis-2.3/src/sat/satMain.c	(revision 14)
+++ vis_dev/vis-2.3/src/sat/satMain.c	(revision 14)
@@ -0,0 +1,909 @@
+/**CFile***********************************************************************
+
+  FileName    [satMain.c]
+
+  PackageName [sat]
+
+  Synopsis    [Routines for sat main function.]
+
+  Author      [HoonSang Jin]
+
+  Copyright [ This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+
+******************************************************************************/
+
+#include "satInt.h"
+
+static char rcsid[] UNUSED = "$Id: satMain.c,v 1.30 2009/04/11 18:26:37 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Pre-processing to run CirCUs ]
+
+  Description [ Pre-processing to run CirCUs ]
+
+  SideEffects [ One has to run sat_PostProcessing after running CirCUs]
+
+  SeeAlso     [ sat_PostProcessing ]
+
+******************************************************************************/
+void
+sat_PreProcessing(satManager_t *cm)
+{
+satLevel_t *d;
+
+
+  /** create implication queue **/
+  cm->queue = sat_CreateQueue(1024);
+  cm->BDDQueue = sat_CreateQueue(1024);
+  cm->unusedAigQueue = sat_CreateQueue(1024);
+
+  /**
+  create variable array : one can reduce size of variable array using
+  mapping. for fanout free internal node....
+  **/
+
+  if(cm->variableArray == 0) {
+    cm->variableArray = ALLOC(satVariable_t, cm->initNumVariables+1);
+    memset(cm->variableArray, 0,
+	    sizeof(satVariable_t) * (cm->initNumVariables+1));
+  }
+
+  cm->auxArray = sat_ArrayAlloc(1024);
+  cm->nonobjUnitLitArray = sat_ArrayAlloc(128);
+  cm->objUnitLitArray = sat_ArrayAlloc(128);
+
+  /** compact fanout of AIG node **/
+  //sat_CompactFanout(cm);
+
+  //Bing:
+  if(cm->option->AbRf == 0)
+    sat_CompactFanout(cm);
+
+  /** Initial score **/
+  sat_InitScore(cm);
+
+  /** create decision stack **/
+  if(cm->decisionHeadSize == 0) {
+    cm->decisionHeadSize = 32;
+    cm->decisionHead = ALLOC(satLevel_t, cm->decisionHeadSize);
+    memset(cm->decisionHead, 0, sizeof(satLevel_t) * cm->decisionHeadSize);
+  }
+  cm->currentDecision = -1;
+
+  /** to avoid purify warning **/
+  SATvalue(2) = 2;
+  SATflags(0) = 0;
+
+  cm->initNodesArraySize = cm->nodesArraySize;
+  cm->beginConflict = cm->nodesArraySize;
+
+  /** incremental SAT.... **/
+  if(cm->option->incTraceObjective) {
+    sat_RestoreForwardedClauses(cm, 0);
+  }
+  else if(cm->option->incAll) {
+    sat_RestoreForwardedClauses(cm, 1);
+  }
+
+  if(cm->option->incTraceObjective) {
+    sat_MarkObjectiveFlagToArray(cm, cm->obj);
+    sat_MarkObjectiveFlagToArray(cm, cm->objCNF);
+  }
+
+
+  /** Level 0 decision.... **/
+  d = sat_AllocLevel(cm);
+
+  sat_ApplyForcedAssignmentMain(cm, d);
+
+  if(cm->status == SAT_UNSAT)
+    return;
+
+
+  //Bing:
+  if(cm->option->coreGeneration && cm->option->IP){
+    cm->rm = ALLOC(RTManager_t, 1);
+    memset(cm->rm,0,sizeof(RTManager_t));
+  }
+  //Bing
+  if(!(cm->option->SSS==1 && cm->option->coreGeneration==1))
+    sat_ImplyArray(cm, d, cm->pureLits);
+
+  sat_ImplyArray(cm,d,cm->assertArray);
+  sat_ImplyArray(cm, d, cm->assertion);
+  sat_ImplyArray(cm, d, cm->unitLits);
+  sat_ImplyArray(cm, d, cm->auxObj);
+  sat_ImplyArray(cm, d, cm->nonobjUnitLitArray);
+  sat_ImplyArray(cm, d, cm->obj);
+
+  sat_ImplicationMain(cm, d);
+  if(d->conflict) {
+    cm->status = SAT_UNSAT;
+  }
+
+  if(cm->status == 0) {
+    if(cm->option->incDistill) {
+      sat_IncrementalUsingDistill(cm);
+    }
+  }
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Pre-processing to run CirCUs with AIG and CNF]
+
+  Description [ Pre-processing to run CirCUs with AIG and CNF]
+
+  SideEffects [ One has to run sat_PostProcessing for AllSat enumeration after running CirCUs]
+
+  SeeAlso     [ sat_PostProcessing ]
+
+******************************************************************************/
+void
+sat_PreProcessingForMixed(satManager_t *cm)
+{
+satLevel_t *d;
+
+
+  /** create implication queue **/
+  cm->queue = sat_CreateQueue(1024);
+  cm->BDDQueue = sat_CreateQueue(1024);
+  cm->unusedAigQueue = sat_CreateQueue(1024);
+
+  /**
+  create variable array : one can reduce size of variable array using
+  mapping. for fanout free internal node....
+  **/
+
+  if(cm->variableArray == 0) {
+    cm->variableArray = ALLOC(satVariable_t, cm->initNumVariables+1);
+    memset(cm->variableArray, 0,
+	    sizeof(satVariable_t) * (cm->initNumVariables+1));
+  }
+
+  cm->auxArray = sat_ArrayAlloc(1024);
+  cm->nonobjUnitLitArray = sat_ArrayAlloc(128);
+  cm->objUnitLitArray = sat_ArrayAlloc(128);
+
+  /** compact fanout of AIG node **/
+  sat_CompactFanout(cm);
+
+  cm->initNodesArraySize = cm->nodesArraySize;
+  cm->beginConflict = cm->nodesArraySize;
+
+  if(cm->option->allSatMode) {
+    sat_RestoreFrontierClauses(cm);
+    sat_RestoreBlockingClauses(cm);
+  }
+
+  /** Initial score **/
+  sat_InitScoreForMixed(cm);
+
+  /** create decision stack **/
+  if(cm->decisionHeadSize == 0) {
+    cm->decisionHeadSize = 32;
+    cm->decisionHead = ALLOC(satLevel_t, cm->decisionHeadSize);
+    memset(cm->decisionHead, 0, sizeof(satLevel_t) * cm->decisionHeadSize);
+  }
+  cm->currentDecision = -1;
+
+  /** to avoid purify warning **/
+  SATvalue(2) = 2;
+  SATflags(0) = 0;
+
+  /** incremental SAT.... **/
+  if(cm->option->incTraceObjective) {
+    sat_RestoreForwardedClauses(cm, 0);
+  }
+  else if(cm->option->incAll) {
+    sat_RestoreForwardedClauses(cm, 1);
+  }
+
+  if(cm->option->incTraceObjective) {
+    sat_MarkObjectiveFlagToArray(cm, cm->obj);
+    sat_MarkObjectiveFlagToArray(cm, cm->objCNF);
+  }
+
+  /** Level 0 decision.... **/
+  d = sat_AllocLevel(cm);
+
+  sat_ApplyForcedAssignmentMain(cm, d);
+
+  if(cm->status == SAT_UNSAT)
+    return;
+
+  sat_ImplyArray(cm, d, cm->assertion);
+  sat_ImplyArray(cm, d, cm->unitLits);
+  sat_ImplyArray(cm, d, cm->pureLits);
+  sat_ImplyArray(cm, d, cm->auxObj);
+  sat_ImplyArray(cm, d, cm->nonobjUnitLitArray);
+  sat_ImplyArray(cm, d, cm->obj);
+
+  sat_ImplicationMain(cm, d);
+  if(d->conflict) {
+    cm->status = SAT_UNSAT;
+  }
+
+  if(cm->status == 0) {
+    if(cm->option->incDistill) {
+      sat_IncrementalUsingDistill(cm);
+    }
+  }
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Pre-processing to run CirCUs with AIG and CNF]
+
+  Description [ Pre-processing to run CirCUs with AIG and CNF]
+
+  SideEffects [ One has to run sat_PostProcessing for AllSat enumeration after running CirCUs]
+
+  SeeAlso     [ sat_PostProcessing ]
+
+******************************************************************************/
+void
+sat_PreProcessingForMixedNoCompact(satManager_t *cm)
+{
+satLevel_t *d;
+
+
+  /** create implication queue **/
+  cm->queue = sat_CreateQueue(1024);
+  cm->BDDQueue = sat_CreateQueue(1024);
+  cm->unusedAigQueue = sat_CreateQueue(1024);
+
+  /**
+  create variable array : one can reduce size of variable array using
+  mapping. for fanout free internal node....
+  **/
+
+  if(cm->variableArray == 0) {
+    cm->variableArray = ALLOC(satVariable_t, cm->initNumVariables+1);
+    memset(cm->variableArray, 0,
+	    sizeof(satVariable_t) * (cm->initNumVariables+1));
+  }
+
+  if(cm->auxArray == 0)
+    cm->auxArray = sat_ArrayAlloc(1024);
+  if(cm->nonobjUnitLitArray == 0)
+    cm->nonobjUnitLitArray = sat_ArrayAlloc(128);
+  if(cm->objUnitLitArray == 0)
+    cm->objUnitLitArray = sat_ArrayAlloc(128);
+
+  /** compact fanout of AIG node
+  sat_CompactFanout(cm);
+  **/
+
+  cm->initNodesArraySize = cm->nodesArraySize;
+  cm->beginConflict = cm->nodesArraySize;
+
+  if(cm->option->allSatMode) {
+    sat_RestoreFrontierClauses(cm);
+    sat_RestoreBlockingClauses(cm);
+  }
+
+  /** Initial score **/
+  sat_InitScoreForMixed(cm);
+
+  /** create decision stack **/
+  if(cm->decisionHeadSize == 0) {
+    cm->decisionHeadSize = 32;
+    cm->decisionHead = ALLOC(satLevel_t, cm->decisionHeadSize);
+    memset(cm->decisionHead, 0, sizeof(satLevel_t) * cm->decisionHeadSize);
+  }
+  cm->currentDecision = -1;
+
+  /** to avoid purify warning **/
+  SATvalue(2) = 2;
+  SATflags(0) = 0;
+
+  /** incremental SAT.... **/
+  if(cm->option->incTraceObjective) {
+    sat_RestoreForwardedClauses(cm, 0);
+  }
+  else if(cm->option->incAll) {
+    sat_RestoreForwardedClauses(cm, 1);
+  }
+
+  if(cm->option->incTraceObjective) {
+    sat_MarkObjectiveFlagToArray(cm, cm->obj);
+    sat_MarkObjectiveFlagToArray(cm, cm->objCNF);
+  }
+
+  /** Level 0 decision.... **/
+  d = sat_AllocLevel(cm);
+
+  sat_ApplyForcedAssignmentMain(cm, d);
+
+  if(cm->status == SAT_UNSAT)
+    return;
+
+  sat_ImplyArray(cm, d, cm->assertion);
+  sat_ImplyArray(cm, d, cm->unitLits);
+  sat_ImplyArray(cm, d, cm->pureLits);
+  sat_ImplyArray(cm, d, cm->auxObj);
+  sat_ImplyArray(cm, d, cm->nonobjUnitLitArray);
+  sat_ImplyArray(cm, d, cm->obj);
+
+  sat_ImplicationMain(cm, d);
+  if(d->conflict) {
+    cm->status = SAT_UNSAT;
+  }
+
+  if(cm->status == 0) {
+    if(cm->option->incDistill) {
+      sat_IncrementalUsingDistill(cm);
+    }
+  }
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Mark objective flag to given AIG node or CNF clauses]
+
+  Description [ To use incremental SAT algorithm based on trace objective,
+		the objective has to be identified before starting the
+		SAT process.]
+
+  SideEffects [ One has to run sat_PostProcessing after running CirCUs]
+
+  SeeAlso     [ sat_PostProcessing ]
+
+******************************************************************************/
+void
+sat_MarkObjectiveFlagToArray(
+	satManager_t *cm,
+	satArray_t *objArr)
+{
+int i;
+long v;
+
+  if(objArr == 0)	return;
+
+  for(i=0; i<objArr->num; i++) {
+    v = objArr->space[i];
+    v = SATnormalNode(v);
+    SATflags(v) |= ObjMask;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Post-processing after running CirCUs]
+
+  Description [ Post-processing after running CirCUs]
+
+  SideEffects [ ]
+
+  SeeAlso     [ sat_PreProcessing ]
+
+******************************************************************************/
+void
+sat_PostProcessing(satManager_t *cm)
+{
+
+  sat_Verify(cm);
+
+  if(cm->option->incTraceObjective) {
+    sat_SaveNonobjClauses(cm);
+  }
+
+  if(cm->option->incAll) {
+    sat_SaveAllClauses(cm);
+  }
+
+  if(cm->option->allSatMode) {
+    sat_CollectBlockingClause(cm);
+  }
+
+  //Bing:
+  //sat_RestoreFanout(cm);
+  if(cm->option->AbRf == 0)
+    sat_RestoreFanout(cm);
+
+  if(cm->mgr) {
+#ifdef BDDcu
+    Cudd_Quit(cm->mgr);
+#endif
+    cm->mgr = 0;
+  }
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ main function for SAT solving]
+
+  Description [ main function for SAT solving]
+
+  SideEffects [ ]
+
+  SeeAlso     [ ]
+
+******************************************************************************/
+void
+sat_Main(satManager_t *cm)
+{
+long btime, etime;
+
+  btime = util_cpu_time();
+  sat_PreProcessing(cm);
+
+  if(cm->status == 0)
+    sat_Solve(cm);
+
+  /** Bing: UNSAT core generation **/
+  if(cm->option->coreGeneration && cm->status == SAT_UNSAT){
+    //Bing
+    if(cm->option->RT)
+      sat_GenerateCore_All(cm);
+    else
+      sat_GenerateCore(cm);
+  }
+
+  sat_PostProcessing(cm);
+
+  etime = util_cpu_time();
+  cm->each->satTime = (double)(etime - btime) / 1000.0 ;
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ DPLL procedure for SAT solving]
+
+  Description [ DPLL procedure for SAT solving]
+
+  SideEffects [ ]
+
+  SeeAlso     [ sat_Main ]
+
+******************************************************************************/
+
+void
+sat_Solve(satManager_t *cm)
+{
+satLevel_t *d;
+satOption_t *option;
+satVariable_t *var;
+int level;
+
+  d = SATgetDecision(0);
+  cm->implicatedSoFar = d->implied->num;
+  cm->currentTopConflict = 0;
+
+  option = cm->option;
+  if(option->BDDMonolithic) {
+    sat_TryToBuildMonolithicBDD(cm);
+  }
+
+  if(cm->status == SAT_UNSAT) {
+    sat_Undo(cm, SATgetDecision(0));
+    return;
+  }
+
+  while(1) {
+    sat_PeriodicFunctions(cm);
+
+    if(cm->currentDecision == 0)
+      sat_BuildLevelZeroHyperImplicationGraph(cm);
+
+    d = sat_MakeDecision(cm);
+
+    if(d == 0)	{
+      cm->status = SAT_SAT;
+      return;
+    }
+
+    while(1) {
+      sat_ImplicationMain(cm, d);
+
+      if(d->conflict == 0)	{
+	if(cm->option->verbose > 2) {
+	  var = SATgetVariable(d->decisionNode);
+	  fprintf(cm->stdOut, "decision at %3d on %6ld <- %ld score(%d %d) %d %ld implied %.3f %%\n",
+	    d->level, d->decisionNode, SATvalue(d->decisionNode),
+	    var->scores[0], var->scores[1],
+	    cm->each->nDecisions, d->implied->num,
+	    (double)cm->implicatedSoFar/(double)cm->initNumVariables * 100);
+	  fflush(cm->stdOut);
+	}
+
+	break;
+      }
+
+	if(cm->option->verbose > 2) {
+	  var = SATgetVariable(d->decisionNode);
+	  fprintf(cm->stdOut, "decision at %3d on %6ld <- %ld score(%d %d) %d %ld implied  %.3f %% Conflict\n",
+	    d->level, d->decisionNode, SATvalue(d->decisionNode),
+	    var->scores[0], var->scores[1],
+	    cm->each->nDecisions, d->implied->num,
+	    (double)cm->implicatedSoFar/(double)cm->initNumVariables * 100);
+	  fflush(cm->stdOut);
+	}
+
+      if(cm->option->useStrongConflictAnalysis)
+	level = sat_StrongConflictAnalysis(cm, d);
+      else
+	level = sat_ConflictAnalysis(cm, d);
+
+      if(cm->currentDecision == -1) {
+	if(cm->option->incDistill) {
+	  sat_BuildTrieForDistill(cm);
+	}
+	sat_Undo(cm, SATgetDecision(0));
+	cm->status = SAT_UNSAT;
+	return;
+      }
+
+      d = SATgetDecision(cm->currentDecision);
+    }
+
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Periodic functions for SAT solving]
+
+  Description [ Periodically, score aging and conflict clause deletion
+		are invoked ]
+
+  SideEffects [ ]
+
+  SeeAlso     [ sat_Solve ]
+
+******************************************************************************/
+void
+sat_PeriodicFunctions(satManager_t *cm)
+{
+satStatistics_t *stats;
+satOption_t *option;
+int nDecisions;
+int gap;
+
+  /** need to review restart mechanism **/
+  stats = cm->each;
+  option = cm->option;
+  nDecisions = stats->nDecisions-stats->nShrinkDecisions;
+  if(nDecisions && !(nDecisions % option->decisionAgeInterval)) {
+    if(option->decisionAgeRestart) {
+      gap = stats->nConflictCl-stats->nOldConflictCl;
+      if(gap > option->decisionAgeInterval>>2)  {
+	sat_UpdateScore(cm);
+	sat_Backtrack(cm, cm->lowestBacktrackLevel);
+	cm->currentTopConflict = cm->literals->last-1;
+	cm->currentTopConflictCount = 0;
+	cm->lowestBacktrackLevel = MAXINT;
+      }
+      stats->nOldConflictCl = stats->nConflictCl;
+    }
+    else {
+      sat_UpdateScore(cm);
+    }
+
+  }
+
+  if(option->clauseDeletionHeuristic & LATEST_ACTIVITY_DELETION &&
+	  stats->nBacktracks > option->nextClauseDeletion &&
+     cm->implicatedSoFar > cm->initNumVariables/3) {
+    option->nextClauseDeletion += option->clauseDeletionInterval;
+    sat_ClauseDeletionLatestActivity(cm);
+  }
+  else if(option->clauseDeletionHeuristic & MAX_UNRELEVANCE_DELETION &&
+	  stats->nBacktracks > option->nextClauseDeletion) {
+    option->nextClauseDeletion += option->clauseDeletionInterval;
+    sat_ClauseDeletion(cm);
+  }
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Interface function for pure CNF based SAT solver]
+
+  Description [ Interface function for pure CNF based SAT solver ]
+
+  SideEffects [ ]
+
+  SeeAlso     [ sat_Main ]
+
+******************************************************************************/
+void
+sat_CNFMain(satOption_t *option, char *filename)
+{
+satManager_t *cm;
+int maxSize;
+
+  cm = sat_InitManager(0);
+  cm->comment = ALLOC(char, 2);
+  cm->comment[0] = ' ';
+  cm->comment[1] = '\0';
+  if(option->outFilename) {
+    if(!(cm->stdOut = fopen(option->outFilename, "w"))) {
+      fprintf(stdout, "ERROR : Can't open file %s\n", option->outFilename);
+      cm->stdOut = stdout;
+      cm->stdErr = stderr;
+    }
+    else {
+      cm->stdErr = cm->stdOut;
+    }
+  }
+  else {
+    cm->stdOut = stdout;
+    cm->stdErr = stderr;
+  }
+
+  cm->option = option;
+  cm->each = sat_InitStatistics();
+
+  cm->unitLits = sat_ArrayAlloc(16);
+  cm->pureLits = sat_ArrayAlloc(16);
+
+  maxSize = 1024 << 8;
+  cm->nodesArray = ALLOC(long, maxSize);
+  cm->maxNodesArraySize = maxSize;
+  cm->nodesArraySize = satNodeSize;
+
+  sat_AllocLiteralsDB(cm);
+
+  if(!sat_ReadCNF(cm, filename)) {
+    sat_FreeManager(cm);
+    return;
+  }
+
+  /** trigerring strong conflict analysis **/
+  if(cm->option->coreGeneration==0)
+    cm->option->useStrongConflictAnalysis = 1;
+
+  sat_Main(cm);
+
+  //Bing:change
+  //unsat core
+  if(cm->option->coreGeneration)
+    fclose(cm->fp);
+
+  if(cm->status == SAT_UNSAT) {
+    if(cm->option->forcedAssignArr)
+      fprintf(cm->stdOut, "%s UNSAT under given assignment\n",
+	      cm->comment);
+    fprintf(cm->stdOut, "%s UNSATISFIABLE\n", cm->comment);
+    fflush(cm->stdOut);
+    sat_ReportStatistics(cm, cm->each);
+    sat_FreeManager(cm);
+  }
+  else if(cm->status == SAT_SAT) {
+    fprintf(cm->stdOut, "%s SATISFIABLE\n", cm->comment);
+    fflush(cm->stdOut);
+    sat_PrintSatisfyingAssignment(cm);
+    sat_ReportStatistics(cm, cm->each);
+    sat_FreeManager(cm);
+  }
+  if(cm->stdOut != stdout)
+    fclose(cm->stdOut);
+  if(cm->stdErr != stderr && cm->stdErr != cm->stdOut)
+    fclose(cm->stdErr);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Interface function for pure CNF based SAT solver from array of CNF]
+
+  Description [ Interface function for pure CNF based SAT solver  from array of CNF]
+
+  SideEffects [ ]
+
+  SeeAlso     [ sat_Main ]
+
+******************************************************************************/
+int
+sat_CNFMainWithArray(
+	satOption_t *option,
+	satArray_t *cnfArray,
+	int unsatCoreFlag,
+	satArray_t *coreArray,
+	st_table *mappedTable)
+{
+satManager_t *cm;
+int maxSize;
+int flag;
+int i;
+long v;
+
+  cm = sat_InitManager(0);
+  cm->comment = ALLOC(char, 2);
+  cm->comment[0] = ' ';
+  cm->comment[1] = '\0';
+  if(option->outFilename) {
+    if(!(cm->stdOut = fopen(option->outFilename, "w"))) {
+      fprintf(stdout, "ERROR : Can't open file %s\n", option->outFilename);
+      cm->stdOut = stdout;
+      cm->stdErr = stderr;
+    }
+    else {
+      cm->stdErr = cm->stdOut;
+    }
+  }
+  else {
+    cm->stdOut = stdout;
+    cm->stdErr = stderr;
+  }
+
+  cm->option = option;
+  cm->each = sat_InitStatistics();
+
+  cm->unitLits = sat_ArrayAlloc(16);
+  cm->pureLits = sat_ArrayAlloc(16);
+
+  maxSize = 1024 << 8;
+  cm->nodesArray = ALLOC(long, maxSize);
+  cm->maxNodesArraySize = maxSize;
+  cm->nodesArraySize = satNodeSize;
+
+  sat_AllocLiteralsDB(cm);
+
+  if(unsatCoreFlag) {
+    cm->option->useStrongConflictAnalysis = 0;
+    cm->option->coreGeneration = 1;
+    cm->dependenceTable = st_init_table(st_ptrcmp, st_ptrhash);
+    cm->anteTable = st_init_table(st_numcmp, st_numhash);
+  }
+
+  if(!sat_ReadCNFFromArray(cm, cnfArray, mappedTable)) {
+    sat_FreeManager(cm);
+    return(SAT_UNSAT);
+  }
+
+  sat_Main(cm);
+
+  if(cm->status == SAT_UNSAT) {
+    if(cm->option->forcedAssignArr)
+      fprintf(cm->stdOut, "%s UNSAT under given assignment\n",
+	      cm->comment);
+    fprintf(cm->stdOut, "%s UNSATISFIABLE\n", cm->comment);
+    fflush(cm->stdOut);
+    sat_ReportStatistics(cm, cm->each);
+    flag = SAT_UNSAT;
+
+    if(unsatCoreFlag) {
+      for(i=0; i<cm->clauseIndexInCore->num; i++) {
+	v = cm->clauseIndexInCore->space[i];
+	sat_ArrayInsert(coreArray, v);
+      }
+    }
+  }
+  else if(cm->status == SAT_SAT) {
+    fprintf(cm->stdOut, "%s SATISFIABLE\n", cm->comment);
+    fflush(cm->stdOut);
+    sat_PrintSatisfyingAssignment(cm);
+    sat_ReportStatistics(cm, cm->each);
+    flag = SAT_SAT;
+  }
+  if(cm->stdOut != stdout)
+    fclose(cm->stdOut);
+  if(cm->stdErr != stderr && cm->stdErr != cm->stdOut)
+    fclose(cm->stdErr);
+
+  sat_FreeManager(cm);
+
+  return(flag);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Print satisfying assignment]
+
+  Description [ Print satisfying assignment ]
+
+  SideEffects [ ]
+
+  SeeAlso     [ sat_CNFMain ]
+
+******************************************************************************/
+int
+sat_PrintSatisfyingAssignment(satManager_t *cm)
+{
+int i, size, index, value;
+
+  index = 0;
+  size = cm->initNumVariables * satNodeSize;
+  for(i=satNodeSize; i<=size; i+=satNodeSize) {
+    if(!(SATflags(i) & CoiMask))	continue;
+    index ++;
+    value = SATvalue(i);
+    if(value == 1) {
+      fprintf(cm->stdOut, "%ld ", SATnodeID(i));
+    }
+    else if(value == 0) {
+      fprintf(cm->stdOut, "%ld ", -(SATnodeID(i)));
+    }
+    else {
+      fprintf(cm->stdOut, "\n%s ERROR : unassigned variable %d\n", cm->comment, i);
+      fflush(cm->stdOut);
+      return(0);
+    }
+
+    if(((index % 10) == 0) && (i+satNodeSize <= size))
+      fprintf(cm->stdOut, "\n ");
+  }
+  fprintf(cm->stdOut, "\n");
+  return(1);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Verify satisfying assignment]
+
+  Description [ Verify satisfying assignment when the instance is satisfiable]
+
+  SideEffects [ ]
+
+  SeeAlso     [ sat_Main ]
+
+******************************************************************************/
+void
+sat_Verify(satManager_t *cm)
+{
+int value, size, i;
+int v, flag;
+satArray_t *arr;
+satLevel_t *d;
+
+  if(cm->status != SAT_SAT)	return;
+
+  size = cm->initNumVariables * satNodeSize;
+  arr = sat_ArrayAlloc(cm->initNumVariables);
+  for(i=satNodeSize; i<=size; i+=satNodeSize) {
+    if(!(SATflags(i) & CoiMask))
+      continue;
+    value = SATvalue(i);
+    if(value > 1) {
+      fprintf(cm->stdOut, "%s ERROR : unassigned variable %d\n", cm->comment, i);
+      fflush(cm->stdOut);
+    }
+    else {
+      v = value ? i : SATnot(i);
+      sat_ArrayInsert(arr, v);
+    }
+  }
+
+  sat_Backtrack(cm, -1);
+
+  d = sat_AllocLevel(cm);
+  flag = sat_ApplyForcedAssigment(cm, arr, d);
+  sat_ArrayFree(arr);
+  if(flag == 1) {
+    fprintf(cm->stdOut,
+	   "%s ERROR : Wrong satisfying assignment\n", cm->comment);
+    fflush(cm->stdOut);
+    exit(0);
+  }
+}
Index: vis_dev/vis-2.3/src/sat/satUtil.c
===================================================================
--- vis_dev/vis-2.3/src/sat/satUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/sat/satUtil.c	(revision 14)
@@ -0,0 +1,3204 @@
+/**CFile***********************************************************************
+
+  FileName    [satUtil.c]
+
+  PackageName [sat]
+
+  Synopsis    [Routines for various utility function.]
+
+  Author      [HoonSang Jin]
+
+  Copyright [ This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+
+******************************************************************************/
+
+#include "satInt.h"
+
+static char rcsid[] UNUSED = "$Id: satUtil.c,v 1.37 2009/04/11 18:26:37 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int NodeIndexCompare(const void *x, const void *y);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Add conflict clause into clause database]
+
+  Description [ Add conflict clause into clause database]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+long
+sat_AddConflictClause(
+	satManager_t *cm,
+	satArray_t *clauseArray,
+	int objectFlag)
+{
+satStatistics_t *stats;
+satLiteralDB_t *literals;
+satVariable_t *var;
+long v, c;
+int inverted;
+long *last;
+long *space;
+int i, size;
+int maxLevel, maxIndex;
+int value, level;
+int otherWLIndex;
+
+  literals = cm->literals;
+
+  while(literals->last + clauseArray->num + 2 >= literals->end) {
+    if(!sat_EnlargeLiteralDB(cm)) {
+      fprintf(cm->stdErr, "%s ERROR : Cannot alloc memory for LiteralDB\n",
+	      cm->comment);
+      exit(0);
+    }
+  }
+
+  c = 0;
+  if(cm->unusedAigQueue)
+    c = sat_Dequeue(cm->unusedAigQueue);
+  if(c == 0)
+    c = sat_CreateNode(cm, 2, 2);
+
+
+  last = literals->last;
+  *(last) = (-c);
+  last++;
+
+  /**
+  SATfirstLit(c) = (int)last;
+  **/
+  (cm->nodesArray[c+satFirstLit]) = (long)last;
+  SATnumLits(c) = clauseArray->num;
+  SATflags(c) |= IsCNFMask;
+  SATsetInUse(c);
+  SATnumConflict(c) = 0;
+
+  size = clauseArray->num;
+  space = clauseArray->space;
+  for(i=0; i<size; i++, space++) {
+    v = *space;
+    inverted = !SATisInverted(v);
+    v = SATnormalNode(v);
+
+    *(last) = ((v^inverted) << 2);
+    last++;
+
+    var = SATgetVariable(v);
+
+    if(inverted){
+      (var->litsCount[0])++;
+      (var->conflictLits[0])++;
+    }
+    else	{
+      (var->litsCount[1])++;
+      (var->conflictLits[1])++;
+    }
+  }
+  *(last) = (-c);
+  last++;
+
+  literals->last = last;
+
+  maxLevel = -1;
+  maxIndex = -1;
+  otherWLIndex = -1;
+  space = clauseArray->space;
+  for(i=0; i<size; i++, space++) {
+    v = *space;
+    inverted = SATisInverted(v);
+    v = SATnormalNode(v);
+    value = SATvalue(v);
+    if(value == 2) {
+      sat_AddWL(cm, c, i, 1);
+      otherWLIndex = i;
+      break;
+    }
+    else {
+      level = SATlevel(v);
+      if(level > maxLevel) {
+	maxLevel = level;
+	maxIndex = i;
+      }
+    }
+  }
+  if(i >= size) {
+    sat_AddWL(cm, c, maxIndex, 1);
+    otherWLIndex = maxIndex;
+  }
+
+  maxLevel = -1;
+  maxIndex = -1;
+  space = clauseArray->space+size-1;
+  for(i=size-1; i>=0; i--, space--) {
+    v = *space;
+    inverted = SATisInverted(v);
+    v = SATnormalNode(v);
+    value = SATvalue(v);
+    if(i != otherWLIndex) {
+      if(value == 2) {
+	sat_AddWL(cm, c, i, -1);
+	break;
+      }
+      else {
+	level = SATlevel(v);
+	if(level > maxLevel) {
+	  maxLevel = level;
+	  maxIndex = i;
+	}
+      }
+    }
+  }
+  if(i < 0)
+    sat_AddWL(cm, c, maxIndex, -1);
+
+
+  SATflags(c) |= IsConflictMask;
+
+  stats = cm->each;
+  stats->nConflictCl++;
+  stats->nConflictLit += clauseArray->num;
+  if(objectFlag) {
+    stats->nObjConflictCl++;
+    stats->nObjConflictLit += clauseArray->num;
+    SATflags(c) |= ObjMask;
+  }
+  else {
+    stats->nNonobjConflictCl++;
+    stats->nNonobjConflictLit += clauseArray->num;
+    SATflags(c) |= NonobjMask;
+  }
+
+
+  return(c);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Add conflict clause into clause database without updating score]
+
+  Description [ Add conflict clause into clause database without updating score]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+long
+sat_AddConflictClauseNoScoreUpdate(
+	satManager_t *cm,
+	satArray_t *clauseArray,
+	int objectFlag)
+{
+satStatistics_t *stats;
+satLiteralDB_t *literals;
+satVariable_t *var;
+long v, c;
+int inverted;
+long *last;
+long *space;
+int i, size;
+int maxLevel, maxIndex;
+int value, level;
+int otherWLIndex;
+
+  literals = cm->literals;
+
+  while(literals->last + clauseArray->num + 2 >= literals->end) {
+    if(!sat_EnlargeLiteralDB(cm)) {
+      fprintf(cm->stdErr, "%s ERROR : Cannot alloc memory for LiteralDB\n",
+	      cm->comment);
+      exit(0);
+    }
+  }
+
+  c = 0;
+  if(cm->unusedAigQueue)
+    c = sat_Dequeue(cm->unusedAigQueue);
+  if(c == 0)
+    c = sat_CreateNode(cm, 2, 2);
+
+
+  last = literals->last;
+  *(last) = (-c);
+  last++;
+
+  /**
+  SATfirstLit(c) = (int)last;
+  **/
+  (cm->nodesArray[c+satFirstLit]) = (long)last;
+  SATnumLits(c) = clauseArray->num;
+  SATflags(c) |= IsCNFMask;
+  SATsetInUse(c);
+  SATnumConflict(c) = 0;
+
+  size = clauseArray->num;
+  space = clauseArray->space;
+  for(i=0; i<size; i++, space++) {
+    v = *space;
+    inverted = !SATisInverted(v);
+    v = SATnormalNode(v);
+
+    *(last) = ((v^inverted) << 2);
+    last++;
+
+    var = SATgetVariable(v);
+
+    if(inverted){
+      (var->litsCount[0])++;
+      (var->conflictLits[0])++;
+    }
+    else	{
+      (var->litsCount[1])++;
+      (var->conflictLits[1])++;
+    }
+  }
+  *(last) = (-c);
+  last++;
+
+  literals->last = last;
+
+  maxLevel = -1;
+  maxIndex = -1;
+  otherWLIndex = -1;
+  space = clauseArray->space;
+  for(i=0; i<size; i++, space++) {
+    v = *space;
+    inverted = SATisInverted(v);
+    v = SATnormalNode(v);
+    value = SATvalue(v);
+    if(value == 2) {
+      sat_AddWL(cm, c, i, 1);
+      otherWLIndex = i;
+      break;
+    }
+    else {
+      level = SATlevel(v);
+      if(level > maxLevel) {
+	maxLevel = level;
+	maxIndex = i;
+      }
+    }
+  }
+  if(i >= size) {
+    sat_AddWL(cm, c, maxIndex, 1);
+    otherWLIndex = maxIndex;
+  }
+
+  maxLevel = -1;
+  maxIndex = -1;
+  space = clauseArray->space+size-1;
+  for(i=size-1; i>=0; i--, space--) {
+    v = *space;
+    inverted = SATisInverted(v);
+    v = SATnormalNode(v);
+    value = SATvalue(v);
+    if(i != otherWLIndex) {
+      if(value == 2) {
+	sat_AddWL(cm, c, i, -1);
+	break;
+      }
+      else {
+	level = SATlevel(v);
+	if(level > maxLevel) {
+	  maxLevel = level;
+	  maxIndex = i;
+	}
+      }
+    }
+  }
+  if(i < 0)
+    sat_AddWL(cm, c, maxIndex, -1);
+
+
+  SATflags(c) |= IsConflictMask;
+
+  stats = cm->each;
+  stats->nConflictCl++;
+  stats->nConflictLit += clauseArray->num;
+  if(objectFlag) {
+    stats->nObjConflictCl++;
+    stats->nObjConflictLit += clauseArray->num;
+    SATflags(c) |= ObjMask;
+  }
+  else {
+    stats->nNonobjConflictCl++;
+    stats->nNonobjConflictLit += clauseArray->num;
+    SATflags(c) |= NonobjMask;
+  }
+
+
+  return(c);
+}
+/**Function********************************************************************
+
+  Synopsis    [ Add unit conflict clause into clause database]
+
+  Description [ Add unit conflict clause into clause database]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+long
+sat_AddUnitConflictClause(
+	satManager_t *cm,
+	satArray_t *clauseArray,
+	int objectFlag)
+{
+satLiteralDB_t *literals;
+satStatistics_t *stats;
+long c, v;
+int inverted;
+long *last, *space;
+int i, size;
+
+  literals = cm->literals;
+
+  while(literals->last + clauseArray->num + 2 >= literals->end) {
+    if(!sat_EnlargeLiteralDB(cm)) {
+      fprintf(cm->stdErr, "%s ERROR : Cannot alloc memory for LiteralDB\n",
+	      cm->comment);
+      exit(0);
+    }
+  }
+
+  c = 0;
+  if(cm->unusedAigQueue)
+    c = sat_Dequeue(cm->unusedAigQueue);
+  if(c == 0)
+    c = sat_CreateNode(cm, 2, 2);
+
+
+  last = literals->last;
+  *(last) = (-c);
+  last++;
+
+  /**
+  SATfirstLit(c) = (int)last;
+  **/
+  (cm->nodesArray[c+satFirstLit]) = (long)last;
+  SATnumLits(c) = clauseArray->num;
+  SATflags(c) |= IsCNFMask;
+  SATsetInUse(c);
+  SATnumConflict(c) = 0;
+
+  size = clauseArray->num;
+  space = clauseArray->space;
+  for(i=0; i<size; i++, space++) {
+    v = *space;
+    inverted = !SATisInverted(v);
+    v = SATnormalNode(v);
+
+    *(last) = ((v^inverted) << 2);
+    last++;
+  }
+  *(last) = (-c);
+  last++;
+
+  literals->last = last;
+
+  SATflags(c) |= IsConflictMask;
+  stats = cm->each;
+  stats->nConflictCl++;
+  stats->nConflictLit += clauseArray->num;
+  if(objectFlag) {
+    stats->nObjConflictCl++;
+    stats->nObjConflictLit += clauseArray->num;
+    SATflags(c) |= ObjMask;
+  }
+  else {
+    stats->nNonobjConflictCl++;
+    stats->nNonobjConflictLit += clauseArray->num;
+    SATflags(c) |= NonobjMask;
+  }
+
+  return(c);
+}
+/**Function********************************************************************
+
+  Synopsis    [ Add unit blocking clause into clause database]
+
+  Description [ Add unit blocking clause into clause database]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+long
+sat_AddUnitBlockingClause(
+	satManager_t *cm,
+	satArray_t *clauseArray)
+{
+satLiteralDB_t *literals;
+satStatistics_t *stats;
+long c, v;
+int inverted;
+long *last, *space;
+int i, size;
+
+  literals = cm->literals;
+  stats = cm->each;
+
+  while(literals->last + clauseArray->num + 2 >= literals->end) {
+    if(!sat_EnlargeLiteralDB(cm)) {
+      fprintf(cm->stdErr, "%s ERROR : Cannot alloc memory for LiteralDB\n",
+	      cm->comment);
+      exit(0);
+    }
+  }
+
+  c = 0;
+  if(cm->unusedAigQueue)
+    c = sat_Dequeue(cm->unusedAigQueue);
+  if(c == 0)
+    c = sat_CreateNode(cm, 2, 2);
+
+
+  last = literals->last;
+  *(last) = (-c);
+  last++;
+
+  /**
+  SATfirstLit(c) = (int)last;
+  **/
+  (cm->nodesArray[c+satFirstLit]) = (long)last;
+  SATnumLits(c) = clauseArray->num;
+  SATflags(c) |= IsCNFMask;
+  SATsetInUse(c);
+  SATnumConflict(c) = 0;
+
+  size = clauseArray->num;
+  space = clauseArray->space;
+  for(i=0; i<size; i++, space++) {
+    v = *space;
+    inverted = !SATisInverted(v);
+    v = SATnormalNode(v);
+
+    *(last) = ((v^inverted) << 2);
+    last++;
+  }
+  *(last) = (-c);
+  last++;
+
+  literals->last = last;
+
+  SATflags(c) |= IsBlockingMask;
+
+  stats = cm->each;
+  stats->nBlockingCl++;
+  stats->nBlockingLit += clauseArray->num;
+  return(c);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Add unit conflict clause into clause database]
+
+  Description [ Add unit conflict clause into clause database]
+
+  SideEffects [ UNSAT Core generation]
+
+  SeeAlso     []
+
+******************************************************************************/
+long
+sat_AddUnitClause(
+	satManager_t *cm,
+	satArray_t *clauseArray)
+{
+satLiteralDB_t *literals;
+long c = 0, v;
+int inverted;
+long *last, *space;
+int i, size;
+
+  literals = cm->literals;
+
+  while(literals->last + clauseArray->num + 2 >= literals->end) {
+    if(!sat_EnlargeLiteralDB(cm)) {
+      fprintf(cm->stdErr, "%s ERROR : Cannot alloc memory for LiteralDB\n",
+	      cm->comment);
+      exit(0);
+    }
+  }
+
+
+  c = 0;
+  if(cm->unusedAigQueue)
+    c = sat_Dequeue(cm->unusedAigQueue);
+  if(c == 0)
+    c = sat_CreateNode(cm, 2, 2);
+
+
+  last = literals->last;
+  *(last) = (-c);
+  last++;
+
+  /**
+  SATfirstLit(c) = (int)last;
+  **/
+  (cm->nodesArray[c+satFirstLit]) = (long)last;
+  SATnumLits(c) = clauseArray->num;
+  SATflags(c) |= IsCNFMask;
+  SATsetInUse(c);
+  SATnumConflict(c) = 0;
+
+  size = clauseArray->num;
+  space = clauseArray->space;
+  for(i=0; i<size; i++, space++) {
+    v = *space;
+    inverted = !SATisInverted(v);
+    v = SATnormalNode(v);
+
+    *(last) = ((v^inverted) << 2);
+    last++;
+  }
+  *(last) = (-c);
+  last++;
+
+  literals->last = last;
+
+  return(c);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Add conflict clause into clause database]
+
+  Description [ Add conflict clause into clause database]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+long
+sat_AddClauseIncremental(
+	satManager_t *cm,
+	satArray_t *clauseArray,
+	int objectFlag,
+	int fromDistill)
+{
+satLiteralDB_t *literals;
+satStatistics_t *stats;
+satVariable_t *var;
+long c, v;
+int inverted;
+long *last, *space;
+int i, size;
+int maxLevel, maxIndex;
+int value, level;
+int otherWLIndex;
+
+  literals = cm->literals;
+  stats = cm->each;
+
+  while(literals->last + clauseArray->num + 2 >= literals->end) {
+    if(!sat_EnlargeLiteralDB(cm)) {
+      fprintf(cm->stdErr, "%s ERROR : Cannot alloc memory for LiteralDB\n",
+	      cm->comment);
+      exit(0);
+    }
+  }
+
+  c = 0;
+  if(cm->unusedAigQueue)
+    c = sat_Dequeue(cm->unusedAigQueue);
+  if(c == 0)
+    c = sat_CreateNode(cm, 2, 2);
+
+  last = literals->last;
+  *(last) = (-c);
+  last++;
+
+
+  /**
+  SATfirstLit(c) = (int)last;
+  **/
+  (cm->nodesArray[c+satFirstLit]) = (long)last;
+  SATnumLits(c) = clauseArray->num;
+  SATflags(c) |= IsCNFMask;
+  SATsetInUse(c);
+  SATnumConflict(c) = 0;
+
+  size = clauseArray->num;
+  space = clauseArray->space;
+  for(i=0; i<size; i++, space++) {
+    v = *space;
+    inverted = !SATisInverted(v);
+    v = SATnormalNode(v);
+
+    *(last) = ((v^inverted) << 2);
+    last++;
+
+    var = SATgetVariable(v);
+    if(inverted){
+      if(fromDistill)
+	(var->litsCount[0])++;
+      (var->conflictLits[0])++;
+    }
+    else	{
+      if(fromDistill)
+	(var->litsCount[1])++;
+      (var->conflictLits[1])++;
+    }
+  }
+  *(last) = (-c);
+  last++;
+
+  literals->last = last;
+
+
+  /* Bing: UNSAT core generation */
+ if(clauseArray->num>1){
+  maxLevel = -1;
+  maxIndex = -1;
+  otherWLIndex = -1;
+  space = clauseArray->space;
+  for(i=0; i<size; i++, space++) {
+    v = *space;
+    inverted = SATisInverted(v);
+    v = SATnormalNode(v);
+    value = SATvalue(v);
+    if(value == 2) {
+      sat_AddWL(cm, c, i, 1);
+      otherWLIndex = i;
+      break;
+    }
+    else {
+      level = SATlevel(v);
+      if(level > maxLevel) {
+	maxLevel = level;
+	maxIndex = i;
+      }
+    }
+  }
+  if(i >= size) {
+    sat_AddWL(cm, c, maxIndex, 1);
+    otherWLIndex = maxIndex;
+  }
+
+  maxLevel = -1;
+  maxIndex = -1;
+  space = clauseArray->space+size-1;
+  for(i=size-1; i>=0; i--, space--) {
+    v = *space;
+    inverted = SATisInverted(v);
+    v = SATnormalNode(v);
+    value = SATvalue(v);
+    if(i != otherWLIndex) {
+      if(value == 2) {
+	sat_AddWL(cm, c, i, -1);
+	break;
+      }
+      else {
+	level = SATlevel(v);
+	if(level > maxLevel) {
+	  maxLevel = level;
+	  maxIndex = i;
+	}
+      }
+    }
+  }
+  if(i < 0)
+    sat_AddWL(cm, c, maxIndex, -1);
+ }
+
+  if(objectFlag)SATflags(c) |= ObjMask;
+  else		SATflags(c) |= NonobjMask;
+  /*SATflags(c) |= IsConflictMask;*/
+  //Bing:change??
+  if(!cm->option->coreGeneration)
+    SATflags(c) |= IsConflictMask;
+
+  if(objectFlag) {
+    stats->nInitObjConflictCl++;
+    stats->nInitObjConflictLit += clauseArray->num;
+    stats->nObjConflictCl++;
+    stats->nObjConflictLit += clauseArray->num;
+  }
+  else {
+    stats->nInitNonobjConflictCl++;
+    stats->nInitNonobjConflictLit += clauseArray->num;
+    stats->nObjConflictCl++;
+    stats->nObjConflictLit += clauseArray->num;
+  }
+  stats->nConflictCl++;
+  stats->nConflictLit += clauseArray->num;
+
+  return(c);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Add clause into clause database]
+
+  Description [ Add clause into clause database]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+long
+sat_AddClause(
+	satManager_t *cm,
+	satArray_t *clauseArray)
+{
+satLiteralDB_t *literals;
+long c, v;
+int inverted;
+long *last, *space;
+int i, size;
+int maxLevel, maxIndex;
+int value, level;
+int otherWLIndex;
+
+  literals = cm->literals;
+
+  while(literals->last + clauseArray->num + 2 >= literals->end) {
+    if(!sat_EnlargeLiteralDB(cm)) {
+      fprintf(cm->stdErr, "%s ERROR : Cannot alloc memory for LiteralDB\n",
+	      cm->comment);
+      exit(0);
+    }
+  }
+  c = 0;
+  if(cm->unusedAigQueue)
+    c = sat_Dequeue(cm->unusedAigQueue);
+  if(c == 0)
+    c = sat_CreateNode(cm, 2, 2);
+
+  last = literals->last;
+  *(last) = (-c);
+  last++;
+
+  /**
+  SATfirstLit(c) = (int)last;
+  **/
+  (cm->nodesArray[c+satFirstLit]) = (long)last;
+  SATnumLits(c) = clauseArray->num;
+  SATflags(c) |= IsCNFMask;
+  SATsetInUse(c);
+  SATnumConflict(c) = 0;
+
+  size = clauseArray->num;
+  space = clauseArray->space;
+  for(i=0; i<size; i++, space++) {
+    v = *space;
+    inverted = !SATisInverted(v);
+    v = SATnormalNode(v);
+
+    *(last) = ((v^inverted) << 2);
+    last++;
+  }
+  *(last) = (-c);
+  last++;
+
+  literals->last = last;
+
+  maxLevel = -1;
+  maxIndex = -1;
+  otherWLIndex = -1;
+  space = clauseArray->space;
+  for(i=0; i<size; i++, space++) {
+    v = *space;
+    inverted = SATisInverted(v);
+    v = SATnormalNode(v);
+    value = SATvalue(v);
+    if(value == 2) {
+      sat_AddWL(cm, c, i, 1);
+      otherWLIndex = i;
+      break;
+    }
+    else {
+      level = SATlevel(v);
+      if(level > maxLevel) {
+	maxLevel = level;
+	maxIndex = i;
+      }
+    }
+  }
+  if(i >= size) {
+    sat_AddWL(cm, c, maxIndex, 1);
+    otherWLIndex = maxIndex;
+  }
+
+  maxLevel = -1;
+  maxIndex = -1;
+  space = clauseArray->space+size-1;
+  for(i=size-1; i>=0; i--, space--) {
+    v = *space;
+    inverted = SATisInverted(v);
+    v = SATnormalNode(v);
+    value = SATvalue(v);
+    if(i != otherWLIndex) {
+      if(value == 2) {
+	sat_AddWL(cm, c, i, -1);
+	break;
+      }
+      else {
+	level = SATlevel(v);
+	if(level > maxLevel) {
+	  maxLevel = level;
+	  maxIndex = i;
+	}
+      }
+    }
+  }
+  if(i < 0)
+    sat_AddWL(cm, c, maxIndex, -1);
+
+
+  return(c);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Add clause into clause database]
+
+  Description [ Add clause into clause database]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+long
+sat_AddBlockingClause(
+	satManager_t *cm,
+	satArray_t *clauseArray)
+{
+satLiteralDB_t *literals;
+satStatistics_t *stats;
+long c, v;
+int inverted;
+long *last, *space;
+int i, size;
+int maxLevel, maxIndex;
+int value, level;
+int otherWLIndex;
+
+  literals = cm->literals;
+  stats = cm->each;
+
+  while(literals->last + clauseArray->num + 2 >= literals->end) {
+    if(!sat_EnlargeLiteralDB(cm)) {
+      fprintf(cm->stdErr, "%s ERROR : Cannot alloc memory for LiteralDB\n",
+	      cm->comment);
+      exit(0);
+    }
+  }
+
+  if(clauseArray->num == 1)
+    return(sat_AddUnitBlockingClause(cm, clauseArray));
+
+  c = 0;
+  if(cm->unusedAigQueue)
+    c = sat_Dequeue(cm->unusedAigQueue);
+  if(c == 0)
+    c = sat_CreateNode(cm, 2, 2);
+
+  last = literals->last;
+  *(last) = (-c);
+  last++;
+
+  /**
+  SATfirstLit(c) = (int)last;
+  **/
+  (cm->nodesArray[c+satFirstLit]) = (long)last;
+  SATnumLits(c) = clauseArray->num;
+  SATflags(c) |= IsCNFMask;
+  SATsetInUse(c);
+  SATnumConflict(c) = 0;
+
+  size = clauseArray->num;
+  space = clauseArray->space;
+  for(i=0; i<size; i++, space++) {
+    v = *space;
+    inverted = !SATisInverted(v);
+    v = SATnormalNode(v);
+
+    *(last) = ((v^inverted) << 2);
+    last++;
+  }
+  *(last) = (-c);
+  last++;
+
+  literals->last = last;
+
+  maxLevel = -1;
+  maxIndex = -1;
+  otherWLIndex = -1;
+  space = clauseArray->space;
+  for(i=0; i<size; i++, space++) {
+    v = *space;
+    inverted = SATisInverted(v);
+    v = SATnormalNode(v);
+    value = SATvalue(v);
+    if(value == 2) {
+      sat_AddWL(cm, c, i, 1);
+      otherWLIndex = i;
+      break;
+    }
+    else {
+      level = SATlevel(v);
+      if(level > maxLevel) {
+	maxLevel = level;
+	maxIndex = i;
+      }
+    }
+  }
+  if(i >= size) {
+    sat_AddWL(cm, c, maxIndex, 1);
+    otherWLIndex = maxIndex;
+  }
+
+  maxLevel = -1;
+  maxIndex = -1;
+  space = clauseArray->space+size-1;
+  for(i=size-1; i>=0; i--, space--) {
+    v = *space;
+    inverted = SATisInverted(v);
+    v = SATnormalNode(v);
+    value = SATvalue(v);
+    if(i != otherWLIndex) {
+      if(value == 2) {
+	sat_AddWL(cm, c, i, -1);
+	break;
+      }
+      else {
+	level = SATlevel(v);
+	if(level > maxLevel) {
+	  maxLevel = level;
+	  maxIndex = i;
+	}
+      }
+    }
+  }
+  if(i < 0)
+    sat_AddWL(cm, c, maxIndex, -1);
+
+  SATflags(c) |= IsBlockingMask;
+
+  stats = cm->each;
+  stats->nBlockingCl++;
+  stats->nBlockingLit += clauseArray->num;
+
+  return(c);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Make literal watched ]
+
+  Description [ Make literal watched ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_AddWL(
+	satManager_t *cm,
+	long c,
+	int index,
+	int dir)
+{
+long *plit, v;
+int inverted;
+satVariable_t *var;
+
+  plit = (long*)SATfirstLit(c) + index;
+  v = SATgetNode(*plit);
+  inverted = !SATisInverted(v);
+  v = SATnormalNode(v);
+  var = SATgetVariable(v);
+
+  if(var->wl[inverted] == 0)
+    var->wl[inverted] = sat_ArrayAlloc(4);
+  sat_ArrayInsert(var->wl[inverted], (long)plit);
+  SATsetWL(plit, dir);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Allocate array ]
+
+  Description [ Allocate array ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+satArray_t *
+sat_ArrayAlloc(long number)
+{
+satArray_t *array;
+
+  array = ALLOC(satArray_t, 1);
+  if (array) {
+    array->num = 0;
+    array->size = number;
+    array->space = ALLOC(long, number);
+    if (array->space) {
+      return array;
+    }
+  }
+  //Bing: To avoid segmentation fault
+  if(array==0 || (number>0&&array->space==0)){
+    printf("can't alloc mem, exit\n");
+    exit(0);
+  }
+  return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Duplicate array ]
+
+  Description [ Duplicate array ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+satArray_t *
+sat_ArrayDuplicate(satArray_t *old)
+{
+satArray_t *array;
+
+  array = (satArray_t *)malloc(sizeof(satArray_t));
+  if (array) {
+    array->num = old->num;
+    array->size = old->num;
+    array->space = (long *)malloc(sizeof(long) * old->num);
+    memcpy(array->space, old->space, sizeof(long)*old->num);
+    if (array->space) {
+      return array;
+    }
+  }
+  return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Insert entries to array ]
+
+  Description [ Insert entries to array ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_ArrayInsert(satArray_t *array, long datum)
+{
+  if(array->num < array->size) {
+    array->space[array->num++] = datum;
+  }
+  else {
+    array->size <<= 1;
+    array->space = REALLOC(long, array->space, array->size);
+    if(array->space == 0) {
+      fprintf(stdout, "ERROR : Can't allocate memory in sat_ArrayInsert\n");
+      exit(0);
+    }
+    array->space[array->num++] = datum;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Free array ]
+
+  Description [ Free array ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_ArrayFree(satArray_t *array)
+{
+  free(array->space);
+  free(array);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Create queue ]
+
+  Description [ Create queue ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+satQueue_t *
+sat_CreateQueue( long MaxElements )
+{
+satQueue_t *Q;
+
+  Q = ALLOC(satQueue_t, 1);
+  if( Q == NULL )
+    fprintf(stderr, "Out of space!!!\n" );
+
+  Q->array = ALLOC(long, MaxElements );
+  if( Q->array == NULL )
+    fprintf(stderr, "Out of space!!!\n" );
+  Q->max = MaxElements;
+  Q->size = 0;
+  Q->front = 1;
+  Q->rear = 0;
+  return Q;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Free queue ]
+
+  Description [ Free queue ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_FreeQueue( satQueue_t *Q )
+{
+  if( Q != NULL ) {
+    free( Q->array );
+    free( Q );
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Enqueue node ]
+
+  Description [ Enqueue node ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_Enqueue(satQueue_t *Q, long v)
+{
+  long *arr, *oarr;
+  long rear;
+
+  if(Q->size < Q->max) {
+    Q->size++;
+    rear = Q->rear;
+    rear = (++(rear) == Q->max) ? 0 : rear;
+    Q->array[rear] = v;
+    Q->rear = rear;
+  }
+  else {
+    arr = ALLOC(long, Q->size * 2 );
+    if(arr == NULL )
+       fprintf(stderr, "Out of space!!!\n" );
+    oarr = Q->array;
+    if(Q->front > Q->rear) {
+       memcpy(&(arr[1]), &(oarr[Q->front]),
+	       sizeof(long) *(Q->max-Q->front));
+       memcpy(&(arr[Q->size-Q->front+1]), &(oarr[0]),
+	       sizeof(long) *(Q->rear+1));
+    }
+    else if(Q->front < Q->rear) {
+       memcpy(&(arr[1]), &(oarr[Q->front]), sizeof(long) *(Q->size));
+    }
+    free(oarr);
+    Q->array = arr;
+    Q->front = 1;
+    Q->rear = Q->size;
+    Q->max *= 2;
+
+    Q->size++;
+    rear = Q->rear;
+    rear = (++(rear) == Q->max) ? 0 : rear;
+    Q->array[rear] = v;
+    Q->rear = rear;
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Dequeue ]
+
+  Description [ Dequeue ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+long
+sat_Dequeue( satQueue_t * Q )
+{
+  long front;
+  long v;
+
+  if(Q->size > 0) {
+    Q->size--;
+    front = Q->front;
+    v = Q->array[front];
+    Q->front = (++(front) == Q->max) ? 0 : front;
+    return v;
+  }
+  else
+    return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Allocate decision level ]
+
+  Description [ Allocate decision level ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+satLevel_t *
+sat_AllocLevel(
+	satManager_t *cm)
+{
+satStatistics_t *stats;
+satLevel_t *d;
+satArray_t *implied;
+int size;
+
+  if(cm->decisionHeadSize == 0) {
+    size = cm->currentDecision+2;
+    cm->decisionHeadSize = size;
+    cm->decisionHead = REALLOC(satLevel_t, cm->decisionHead, size);
+    memset(cm->decisionHead, 0, sizeof(satLevel_t) * size);
+  }
+
+  if(cm->currentDecision+1 >= cm->decisionHeadSize) {
+    size = cm->decisionHeadSize;
+    cm->decisionHeadSize <<=1;
+    cm->decisionHead = REALLOC(satLevel_t, cm->decisionHead,
+			       cm->decisionHeadSize);
+    memset(cm->decisionHead+size, 0, sizeof(satLevel_t) * size);
+  }
+
+  cm->currentDecision++;
+  d = &(cm->decisionHead[cm->currentDecision]);
+  implied = d->implied;
+  memset(d, 0, sizeof(satLevel_t));
+  d->implied = implied;
+  if(d->implied == 0){
+    d->implied = sat_ArrayAlloc(64);
+    //Bing: avoid seg fault
+    if(d->implied == 0){
+      printf("out of mem, exit\n");
+      exit(0);
+    }
+  }
+
+  d->level = cm->currentDecision;
+  d->conflict = 0;
+
+  stats = cm->each;
+  if(stats->maxDecisionLevel < d->level)
+    stats->maxDecisionLevel = d->level;
+
+  return(d);
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Clean decision level when backtracking ]
+
+  Description [ Clean decision level when backtracking ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_CleanLevel(
+	satLevel_t *d)
+{
+  if(d->implied)
+    d->implied->num = 0;
+  if(d->satisfied)
+    d->satisfied->num = 0;
+  d->currentVarPos = 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Delete conflict clauses ]
+
+  Description [ Delete conflict clauses ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_ClauseDeletion(satManager_t *cm)
+{
+satLiteralDB_t *literals;
+satOption_t *option;
+long v, *plit, nv, lit;
+int size, n0, n1x, deleteFlag;
+int unrelevance;
+int inverted, i;
+int value;
+double ratio;
+
+/**
+LATEST_ACTIVITY_DELETION
+MAX_UNRELEVANCE_DELETION
+SIMPLE_LATEST_DELETION
+**/
+
+  option = cm->option;
+  if(option->clauseDeletionHeuristic == 0)	return;
+
+  literals = cm->literals;
+  for(v=cm->beginConflict; v<cm->nodesArraySize; v+=satNodeSize) {
+    if(!(SATflags(v) & IsCNFMask))	continue;
+    if(SATreadInUse(v) == 0)		continue;
+
+    if(option->incPreserveNonobjective && (SATflags(v) & NonobjMask))
+      continue;
+
+    size = SATnumLits(v);
+    if(size < option->minLitsLimit)	continue;
+
+    plit = (long*)SATfirstLit(v);
+
+    unrelevance = option->unrelevance;
+    if(option->clauseDeletionHeuristic & SIMPLE_LATEST_DELETION) {
+      ratio = (double)(plit-literals->initialSize)/
+	  (double)(literals->last-literals->initialSize);
+      if(ratio > 0.8)	unrelevance <<= 3;
+    }
+    if(!(option->clauseDeletionHeuristic & MAX_UNRELEVANCE_DELETION)) {
+      unrelevance = MAXINT;
+    }
+
+    n0 = n1x = 0;
+    deleteFlag = 0;
+    for(i=0; i<size; i++, plit++) {
+      lit = *plit;
+      nv = SATgetNode(lit);
+      inverted = SATisInverted(nv);
+      nv = SATnormalNode(nv);
+      value = SATvalue(nv) ^ inverted;
+
+      if(value == 0)	n0++;
+      else if(value == 1) {
+	n1x++;
+	if(SATlevel(nv) == 0 && cm->option->coreGeneration == 0)
+	  deleteFlag = 1;
+      }
+      else	n1x++;
+
+      if(deleteFlag) {
+	sat_DeleteClause(cm, v);
+	sat_Enqueue(cm->unusedAigQueue, v);
+	break;
+      }
+      if((size > option->maxLitsLimit) && (n1x > 1)) {
+	sat_DeleteClause(cm, v);
+	sat_Enqueue(cm->unusedAigQueue, v);
+	break;
+      }
+      if(n1x > unrelevance) {
+	sat_DeleteClause(cm, v);
+	sat_Enqueue(cm->unusedAigQueue, v);
+	break;
+      }
+    }
+
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Delete conflict clauses ]
+
+  Description [ Delete conflict clauses ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_DeleteClause(
+	satManager_t *cm,
+	long v)
+{
+satStatistics_t *stats;
+int size, i;
+long nv, *plit;
+
+  stats = cm->each;
+  size = SATnumLits(v);
+  stats->nDeletedCl++;
+  stats->nDeletedLit += size;
+
+/**  SATresetInUse(v); **/
+  SATflags(v) = 0;
+  SATflags(v) |= IsCNFMask;
+
+  for(i=0, plit=(long*)SATfirstLit(v); i<size; i++, plit++) {
+    nv = SATgetNode(*plit);
+    *plit = 0;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Compact clause database ]
+
+  Description [ Compact clause database ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_CompactClauses(satManager_t *cm)
+{
+satLiteralDB_t *literals;
+long *plit, v, lit;
+int i, size, index;
+int inverted;
+satVariable_t *var;
+
+  literals = cm->literals;
+  size = literals->last - literals->begin;
+
+  plit = literals->begin;
+  index = literals->initialSize-literals->begin;
+  for(i=literals->initialSize-literals->begin; i<size; i++) {
+    if(i < 2) {
+      plit[index] = plit[i];
+      index++;
+      continue;
+    }
+
+    if(plit[i-1] == 0 && plit[i] < 0)	continue;
+    else if(plit[i-1] == 0 && plit[i] == 0)	continue;
+    else if(plit[i-1] < 0 && plit[i] == 0)	continue;
+    else if(plit[i-1] < 0 && plit[i] < 0 && plit[i+1] == 0)	continue;
+    else {
+      plit[index] = plit[i];
+      index++;
+    }
+  }
+
+  literals->last = literals->begin + index;
+  for(v=satNodeSize; v<cm->beginConflict; v+=satNodeSize) {
+    if(SATflags(v) & IsCNFMask)	continue;
+    var = SATgetVariable(v);
+    if(var->wl[0]) var->wl[0]->num = 0;
+    if(var->wl[1]) var->wl[1]->num = 0;
+  }
+
+  size = literals->last - literals->begin;
+  plit = literals->begin;
+  for(i=0; i<size; i++) {
+    lit = plit[i];
+    if(lit > 0 && SATisWL(lit)) {
+      v = SATgetNode(lit);
+      inverted = !(SATisInverted(v));
+      v = SATnormalNode(v);
+      var = SATgetVariable(v);
+      if(var->wl[inverted] == 0)
+	var->wl[inverted] = sat_ArrayAlloc(4);
+      sat_ArrayInsert(var->wl[inverted], (long)(&(plit[i])));
+    }
+
+    if(lit <= 0) {
+      v = -lit;
+      /**
+      SATfirstLit(v) = (int)(&(plit[i]) - SATnumLits(v));
+      **/
+      (cm->nodesArray[v+satFirstLit]) = (long)(&(plit[i]) - SATnumLits(v));
+    }
+  }
+
+  plit = literals->last - 1;
+  cm->currentTopConflict = plit;
+  cm->currentTopConflictCount = 0;
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Enlarge clause database ]
+
+  Description [ Enlarge clause database ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_EnlargeLiteralDB(satManager_t *cm)
+{
+satLiteralDB_t *literals;
+int nLiveConflictCl, nLiveConflictLit;
+double ratio, growRatio;
+double memUsage;
+long *oldBegin, *oldEnd;
+long newSize, oldSize;
+int offset, index, size;
+int i, j, nodesSize;
+long tv;
+int arrSize;
+satVariable_t *var;
+satArray_t *wl;
+satStatistics_t *stats;
+satOption_t *option;
+
+
+  literals = cm->literals;
+  option = cm->option;
+  stats = cm->each;
+
+  size = literals->last - literals->begin;
+  nLiveConflictCl = cm->initNumClauses + stats->nConflictCl + stats->nBlockingCl - stats->nDeletedCl;
+  nLiveConflictLit = cm->initNumLiterals + stats->nBlockingLit +
+		     stats->nConflictLit - stats->nDeletedLit ;
+  ratio = (double)(nLiveConflictLit + (nLiveConflictCl << 1)) /
+	  (double)(size);
+
+  if(ratio < 0.8) {
+    sat_CompactClauses(cm);
+    return(1);
+  }
+
+  memUsage = (double)sat_MemUsage(cm);
+  growRatio = 1.0;
+  if(memUsage < (double)option->memoryLimit/4.0)	growRatio = 2.0;
+  else if(memUsage < (double)option->memoryLimit/2.0)	growRatio = 1.5;
+  else if(memUsage < (double)option->memoryLimit*0.8)	growRatio = 1.2;
+
+  if(growRatio < 1.5) {
+    if(ratio < 0.9) {
+      sat_CompactClauses(cm);
+      return(1);
+    }
+  }
+
+  oldBegin = literals->begin;
+  oldEnd = literals->end;
+  oldSize = literals->last - literals->begin;
+  newSize = oldSize * (int)growRatio;
+
+  literals->begin = REALLOC(long, oldBegin, newSize);
+  literals->last = literals->begin + oldSize;
+  literals->end = literals->begin + newSize;
+
+  offset = literals->begin - oldBegin;
+  nodesSize = cm->nodesArraySize;
+  for(i=satNodeSize; i<nodesSize; i+= satNodeSize) {
+    tv = i;
+    if(SATflags(tv) & IsCNFMask) {
+      if(SATreadInUse(tv))
+	(cm->nodesArray[tv+satFirstLit]) = (long)((long*)(SATfirstLit(tv)) + offset);
+      /**
+	SATfirstLit(tv) = (int)((int*)(SATfirstLit(tv)) + offset);
+	**/
+    }
+    else if(SATflags(tv) & IsBDDMask) {
+      (cm->nodesArray[tv+satFirstLit]) = (long)((long*)(SATfirstLit(tv)) + offset);
+	/**
+      SATfirstLit(tv) = (int)((int*)(SATfirstLit(tv)) + offset);
+      **/
+    }
+    else {
+      var = SATgetVariable(tv);
+      wl = var->wl[0];
+      if(wl) {
+	arrSize = wl->num;
+	for(j=0, index=0; j<arrSize; j++) {
+	  if(wl->space[j] == 0)	continue;
+	  wl->space[j] = (long)(((long*)(wl->space[j])) + offset);
+	}
+      }
+      wl = var->wl[1];
+      if(wl) {
+	arrSize = wl->num;
+	for(j=0, index=0; j<arrSize; j++) {
+	  if(wl->space[j] == 0)	continue;
+	  wl->space[j] = (long)(((long*)(wl->space[j])) + offset);
+	}
+      }
+    }
+  }
+  literals->initialSize = literals->initialSize + offset;
+  cm->currentTopConflict += offset;
+
+  return(1);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Allocate clause database ]
+
+  Description [ Allocate clause database ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_AllocLiteralsDB(satManager_t *cm)
+{
+satLiteralDB_t *literals;
+int size;
+
+  literals = cm->literals;
+  if(literals)	return;
+
+  literals = ALLOC(satLiteralDB_t, 1);
+  cm->literals = literals;
+
+  size = 1024 * 1024;
+  literals->begin = ALLOC(long, size);
+  *(literals->begin) = 0;
+  literals->last = literals->begin + 1;
+  literals->end = literals->begin + size;
+  /** CONSIDER... **/
+  literals->initialSize = literals->last;
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Free clause database ]
+
+  Description [ Free clause database ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_FreeLiteralsDB(satLiteralDB_t *literals)
+{
+
+  if(literals == 0)	return;
+  free(literals->begin);
+  literals->begin = 0;
+  free(literals);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ clean value and flag of node ]
+
+  Description [ clean value and flag of node ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_CleanDatabase(satManager_t *cm)
+{
+long v, i;
+
+  for(i=satNodeSize; i<cm->nodesArraySize; i+=satNodeSize) {
+    v = i;
+    SATvalue(v) = 2;
+    SATflags(v) &= PreserveMask;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Compact fanout of AIG node ]
+
+  Description [ Compact fanout of AIG node ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_CompactFanout(satManager_t *cm)
+{
+int bufSize, bufIndex;
+long *buf, *fan;
+long i, v, cur;
+int j, size, tsize;
+
+  bufSize = 1024;
+  bufIndex = 0;
+  buf = ALLOC(long, bufSize);
+  for(i=satNodeSize; i<cm->nodesArraySize; i+=satNodeSize) {
+    v = i;
+
+    if(!(SATflags(v) & CoiMask))
+      continue;
+
+    size = SATnFanout(v);
+    if(size >= bufSize) {
+      bufSize <<= 1;
+      if(size >= bufSize)
+	bufSize = size + 1;
+      buf = REALLOC(long, buf, bufSize);
+    }
+
+    bufIndex = 0;
+    for(j=0, fan = SATfanout(v); j<size; j++) {
+      cur = fan[j];
+      cur >>= 1;
+      cur = SATnormalNode(cur);
+      if(!(SATflags(cur) & CoiMask))
+	continue;
+      buf[bufIndex++] = fan[j];
+    }
+
+    if(bufIndex > 0) {
+      tsize = bufIndex;
+      for(j=0, fan=SATfanout(v); j<size; j++) {
+	cur = fan[j];
+	cur >>= 1;
+	cur = SATnormalNode(cur);
+	if(!(SATflags(cur) & CoiMask))  {
+	  buf[bufIndex++] = fan[j];
+	  continue;
+	}
+      }
+      buf[bufIndex] = 0;
+      memcpy(fan, buf, sizeof(long)*(size+1));
+      SATnFanout(v) = tsize;
+    }
+    else {
+      SATnFanout(v) = 0;
+    }
+  }
+
+  free(buf);
+
+  for(i=satNodeSize; i<cm->nodesArraySize; i+=satNodeSize) {
+    v = i;
+    if(!(SATflags(v) & CoiMask))
+      continue;
+    fan = SATfanout(v);
+    size = SATnFanout(v);
+    qsort(fan, size, sizeof(long), NodeIndexCompare);
+  }
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Restore fanout of AIG node ]
+
+  Description [ Restore fanout of AIG node ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_RestoreFanout(satManager_t *cm)
+{
+long i, v;
+
+  for(i=satNodeSize; i<cm->nodesArraySize; i+=satNodeSize) {
+    v = i;
+    if((SATflags(v) & IsCNFMask))
+      continue;
+    SATnFanout(v) = sat_GetFanoutSize(cm, v);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Get fanout size of AIG node ]
+
+  Description [ Get fanout size of AIG node ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_GetFanoutSize(
+	satManager_t *cm,
+	long v)
+{
+long *fan;
+int i;
+
+  fan = SATfanout(v);
+  if(fan == 0)	return(0);
+
+  for(i=0; fan[i]!=0; i++);
+  return(i);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Mark transitive fanin of given array of node ]
+
+  Description [ Mark transitive fanin of given array of node ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_MarkTransitiveFaninForArray(
+	satManager_t *cm,
+	satArray_t *arr,
+	unsigned int mask)
+{
+long v;
+int i, size;
+
+  if(arr == 0)	return;
+  size = arr->num;
+
+  for(i=0; i<size; i++) {
+    v = arr->space[i];
+    sat_MarkTransitiveFaninForNode(cm, v, mask);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Mark transitive fanin of given node ]
+
+  Description [ Mark transitive fanin of given node ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_MarkTransitiveFaninForNode(
+	satManager_t *cm,
+	long v,
+	unsigned int mask)
+{
+  if(v == 2)	return;
+
+  v = SATnormalNode(v);
+
+  if(SATflags(v) & mask)	return;
+
+  SATflags(v) |= mask;
+
+  sat_MarkTransitiveFaninForNode(cm, SATleftChild(v), mask);
+  sat_MarkTransitiveFaninForNode(cm, SATrightChild(v), mask);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Unmark transitive fanin of given array of node ]
+
+  Description [ Unmark transitive fanin of given array of node ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_UnmarkTransitiveFaninForArray(
+	satManager_t *cm,
+	satArray_t *arr,
+	unsigned int mask,
+	unsigned int resetMask)
+{
+long v;
+int i, size;
+
+  size = arr->num;
+
+  for(i=0; i<size; i++) {
+    v = arr->space[i];
+    sat_UnmarkTransitiveFaninForNode(cm, v, mask, resetMask);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Unmark transitive fanin of given node ]
+
+  Description [ Unmark transitive fanin of given node ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_UnmarkTransitiveFaninForNode(
+	satManager_t *cm,
+	long v,
+	unsigned int mask,
+	unsigned int resetMask)
+{
+  if(v == 2)	return;
+
+  v = SATnormalNode(v);
+
+  if(!(SATflags(v) & mask))	return;
+
+  SATflags(v) &= resetMask;
+  sat_UnmarkTransitiveFaninForNode(cm, SATleftChild(v), mask, resetMask);
+  sat_UnmarkTransitiveFaninForNode(cm, SATrightChild(v), mask, resetMask);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Set COIMask ]
+
+  Description [ Set COIMask. The COIMask of flags of node has be set to
+		apply implication on it ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_SetConeOfInfluence(satManager_t *cm)
+{
+  sat_MarkTransitiveFaninForArray(cm, cm->assertion, CoiMask);
+  sat_MarkTransitiveFaninForArray(cm, cm->auxObj, CoiMask);
+  sat_MarkTransitiveFaninForArray(cm, cm->obj, CoiMask);
+  //Bing:
+  sat_MarkTransitiveFaninForArray(cm, cm->assertArray, CoiMask);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Allocate manager for SAT solving]
+
+  Description [  Allocate manager for SAT solving]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+satManager_t *
+sat_InitManager(satInterface_t *interface)
+{
+satManager_t *cm;
+
+  cm = ALLOC(satManager_t, 1);
+  memset(cm, 0, sizeof(satManager_t));
+
+  if(interface) {
+    cm->total = interface->total;
+    cm->nonobjUnitLitArray = interface->nonobjUnitLitArray;
+    cm->savedConflictClauses = interface->savedConflictClauses;
+    cm->trieArray = interface->trieArray;
+    cm->objUnitLitArray = sat_ArrayAlloc(8);
+  }
+  else {
+    cm->total = sat_InitStatistics();
+    cm->objUnitLitArray = sat_ArrayAlloc(8);
+    cm->nonobjUnitLitArray = sat_ArrayAlloc(8);
+  }
+
+  return(cm);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Free manager after SAT solving]
+
+  Description [ Free manager after SAT solving]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_FreeManager(satManager_t *cm)
+{
+satVariable_t *var;
+satLevel_t *d;
+int i;
+
+  if(cm->option)	sat_FreeOption(cm->option);
+  if(cm->total)		sat_FreeStatistics(cm->total);
+  if(cm->each)		sat_FreeStatistics(cm->each);
+
+  if(cm->literals)	sat_FreeLiteralsDB(cm->literals);
+
+  if(cm->decisionHead) {
+    for(i=0; i<cm->decisionHeadSize; i++) {
+      d = &(cm->decisionHead[i]);
+      if(d->implied)
+	sat_ArrayFree(d->implied);
+      if(d->satisfied)
+	sat_ArrayFree(d->satisfied);
+    }
+    free(cm->decisionHead);
+    cm->decisionHead = 0;
+    cm->decisionHeadSize = 0;
+  }
+
+  if(cm->queue)		sat_FreeQueue(cm->queue);
+  if(cm->BDDQueue)	sat_FreeQueue(cm->BDDQueue);
+  if(cm->unusedAigQueue)sat_FreeQueue(cm->unusedAigQueue);
+  cm->queue = 0;
+  cm->BDDQueue = 0;
+  cm->unusedAigQueue = 0;
+
+  if(cm->auxObj)               sat_ArrayFree(cm->auxObj);
+  if(cm->obj)                  sat_ArrayFree(cm->obj);
+  if(cm->unitLits)             sat_ArrayFree(cm->unitLits);
+  if(cm->pureLits)             sat_ArrayFree(cm->pureLits);
+  if(cm->assertion)            sat_ArrayFree(cm->assertion);
+  if(cm->auxArray)             sat_ArrayFree(cm->auxArray);
+  if(cm->nonobjUnitLitArray)   sat_ArrayFree(cm->nonobjUnitLitArray);
+  if(cm->objUnitLitArray)      sat_ArrayFree(cm->objUnitLitArray);
+  if(cm->orderedVariableArray) sat_ArrayFree(cm->orderedVariableArray);
+  if(cm->clauseIndexInCore)    sat_ArrayFree(cm->clauseIndexInCore);
+  cm->auxObj = 0;
+  cm->obj = 0;
+  cm->unitLits = 0;
+  cm->pureLits = 0;
+  cm->assertion = 0;
+  cm->auxArray = 0;
+  cm->nonobjUnitLitArray = 0;
+  cm->objUnitLitArray = 0;
+  cm->orderedVariableArray = 0;
+
+  if(cm->variableArray) {
+    for(i=0; i<=cm->initNumVariables; i++) {
+      var = &(cm->variableArray[i]);
+      if(var->wl[0]) {
+	sat_ArrayFree(var->wl[0]);
+	var->wl[0] = 0;
+      }
+      if(var->wl[1]) {
+	sat_ArrayFree(var->wl[1]);
+	var->wl[1] = 0;
+      }
+    }
+    free(cm->variableArray);
+    cm->variableArray = 0;
+  }
+
+
+  if(cm->comment)	free(cm->comment);
+
+  if(cm->nodesArray)    free(cm->nodesArray);
+  free(cm);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Free option after SAT solving]
+
+  Description [ Free option after SAT solving]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_FreeOption(satOption_t * option)
+{
+  if(option)
+    free(option);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Free statistic after SAT solving]
+
+  Description [ Free statistic after SAT solving]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_FreeStatistics(satStatistics_t * stats)
+{
+  if(stats)
+    free(stats);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Allocate option]
+
+  Description [ Allocate option ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+satOption_t *
+sat_InitOption()
+{
+satOption_t *option;
+
+  option = ALLOC(satOption_t, 1);
+  memset(option, 0, sizeof(satOption_t));
+
+  option->decisionHeuristic |= LATEST_CONFLICT_DECISION;
+/**
+  option->decisionHeuristic |= DVH_DECISION;
+**/
+  option->decisionAgeInterval = 0xff;
+  option->decisionAgeRestart = 1;
+  option->minConflictForDecision = 50;
+  option->maxConflictForDecision = 10000;
+  option->skipSatisfiedClauseForDecision = 0;
+
+
+  /**
+  option->clauseDeletionHeuristic |= MAX_UNRELEVANCE_DELETION;
+  option->clauseDeletionHeuristic |= SIMPLE_LATEST_DELETION;
+  **/
+  option->clauseDeletionHeuristic |= LATEST_ACTIVITY_DELETION;
+  option->clauseDeletionInterval = 2500;
+  option->nextClauseDeletion = option->clauseDeletionInterval*5;
+  option->unrelevance = 20;
+  option->minLitsLimit = 20;
+  option->maxLitsLimit = 1000;
+
+  option->latestUnrelevance = 45;
+  option->obsoleteUnrelevance = 20;//6
+  option->latestUsage = 100;
+  option->obsoleteUsage = 2;
+  option->latestRate = 16;
+
+  option->incNumObjLitsLimit = 20; /** 50 **/
+  option->incNumNonobjLitsLimit = 50;
+
+  option->incPreserveNonobjective = 1;
+  option->minimizeConflictClause = 1;
+
+
+  option->BDDMonolithic = 0;
+  option->BDDDPLL = 0;
+  option->maxLimitOfVariablesForMonolithicBDD = 2000;
+  option->maxLimitOfClausesForMonolithicBDD = 20000;
+  option->maxLimitOfCutSizeForMonolithicBDD = 2000;
+
+  option->maxLimitOfVariablesForBDDDPLL = 200;
+  option->maxLimitOfClausesForBDDDPLL = 2000;
+  option->maxLimitOfCutSizeForBDDDPLL = 500;
+
+  option->maxLimitOfVariablesForBDD = 50;
+
+  option->memoryLimit = 1024 * 1024 * 1024;
+
+  return(option);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Report statistics]
+
+  Description [ Report statistics]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_ReportStatistics(
+	satManager_t *cm,
+	satStatistics_t *stats)
+{
+satOption_t *option;
+
+  option = cm->option;
+  fprintf(cm->stdOut, "%s Number of decisions %d\n",
+	      cm->comment, stats->nDecisions);
+  if(option->decisionHeuristic & DVH_DECISION) {
+    fprintf(cm->stdOut, "%s Number of DVH decisions %d\n",
+	      cm->comment, stats->nDVHDecisions);
+  }
+  if(option->decisionHeuristic & LATEST_CONFLICT_DECISION) {
+    fprintf(cm->stdOut, "%s Number of latest conflict decisions %d\n",
+	      cm->comment, stats->nLatestConflictDecisions);
+  }
+  fprintf(cm->stdOut, "%s Number of backtracks %d\n",
+	      cm->comment, stats->nBacktracks);
+
+  fprintf(cm->stdOut, "%s Number of CNF implications %d\n",
+	      cm->comment, stats->nCNFImplications);
+  fprintf(cm->stdOut, "%s Number of Aig implications %d\n",
+	      cm->comment, stats->nAigImplications);
+  fprintf(cm->stdOut, "%s Number of BDD implications %d\n",
+	      cm->comment, stats->nBDDImplications);
+
+  fprintf(cm->stdOut, "%s Number of unit conflict clauses %d\n",
+	      cm->comment, stats->nUnitConflictCl);
+  fprintf(cm->stdOut, "%s Number of conflict clauses %d\n",
+	      cm->comment, stats->nConflictCl);
+  fprintf(cm->stdOut, "%s Number of conflict literals %d\n",
+	      cm->comment, stats->nConflictLit);
+  fprintf(cm->stdOut, "%s Number of deleted clauses %d\n",
+	      cm->comment, stats->nDeletedCl);
+  fprintf(cm->stdOut, "%s Number of deleted literals %d\n",
+	      cm->comment, stats->nDeletedLit);
+
+  if(option->incTraceObjective + option->incDistill) {
+    fprintf(cm->stdOut, "%s Number of init object conflict clauses %d\n",
+	      cm->comment, stats->nInitObjConflictCl);
+    fprintf(cm->stdOut, "%s Number of init object conflict literals %d\n",
+	      cm->comment, stats->nInitObjConflictLit);
+    fprintf(cm->stdOut, "%s Number of init non-object conflict clauses %d\n",
+	      cm->comment, stats->nInitNonobjConflictCl);
+    fprintf(cm->stdOut, "%s Number of init non-object conflict literals %d\n",
+	      cm->comment, stats->nInitNonobjConflictLit);
+    fprintf(cm->stdOut, "%s Number of object conflict clauses %d\n",
+	      cm->comment, stats->nObjConflictCl);
+    fprintf(cm->stdOut, "%s Number of object conflict literals %d\n",
+	      cm->comment, stats->nObjConflictLit);
+    fprintf(cm->stdOut, "%s Number of non-object conflict clauses %d\n",
+	      cm->comment, stats->nNonobjConflictCl);
+    fprintf(cm->stdOut, "%s Number of non-object conflict literals %d\n",
+	      cm->comment, stats->nNonobjConflictLit);
+  }
+  if(option->incDistill) {
+    fprintf(cm->stdOut, "%s Number of distill object conflict clauses %d\n",
+	      cm->comment, stats->nDistillObjConflictCl);
+    fprintf(cm->stdOut, "%s Number of distill object conflict literals %d\n",
+	      cm->comment, stats->nDistillObjConflictLit);
+    fprintf(cm->stdOut, "%s Number of distill non-object conflict clauses %d\n",
+	      cm->comment, stats->nDistillNonobjConflictCl);
+    fprintf(cm->stdOut, "%s Number of distill non-object conflict literals %d\n",
+	      cm->comment, stats->nDistillNonobjConflictLit);
+  }
+  if(option->allSatMode) {
+    fprintf(cm->stdOut, "%s Number of blocking clauses %d\n",
+	      cm->comment, stats->nBlockingCl);
+    fprintf(cm->stdOut, "%s Number of blocking literals %d\n",
+	      cm->comment, stats->nBlockingLit);
+  }
+
+  fprintf(cm->stdOut, "%s Maximum decision level %d\n",
+	      cm->comment, stats->maxDecisionLevel);
+  fprintf(cm->stdOut, "%s Number of low score decisions %d\n",
+	      cm->comment, stats->nLowScoreDecisions);
+  fprintf(cm->stdOut, "%s Total nonchronological backtracks %d\n",
+	      cm->comment, stats->nNonchonologicalBacktracks);
+  fprintf(cm->stdOut, "%s Total run time %10g\n", cm->comment, stats->satTime);
+  fflush(cm->stdOut);
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Allocate statistics]
+
+  Description [ Allocate statistics]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+satStatistics_t *
+sat_InitStatistics(void)
+{
+satStatistics_t *stats;
+
+  stats = ALLOC(satStatistics_t, 1);
+  memset(stats, 0, sizeof(satStatistics_t));
+
+  return(stats);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Set incremental option ]
+
+  Description [ Set incremental option ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_SetIncrementalOption(satOption_t *option, int incFlag)
+{
+  if(incFlag == 0) return;
+
+  if(incFlag == 1)  { /* TraceObjective */
+    option->incTraceObjective = 1;
+  }
+  else if(incFlag == 2)  { /* Distill */
+    option->incDistill = 1;
+  }
+  else if(incFlag == 3)  { /* TraceObjective & Distill */
+    option->incTraceObjective = 1;
+    option->incDistill = 1;
+  }
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Restore blocking clauses]
+
+  Description [ Restore blocking clauses]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_RestoreBlockingClauses(satManager_t *cm)
+{
+long *space, *start;
+long c, v;
+int i;
+satArray_t *reached;
+satArray_t *clause;
+satArray_t *unitLits;
+
+  reached = cm->reached;
+  if(reached == 0)
+    return;
+
+  unitLits = cm->unitLits;
+  if(unitLits == 0)
+    unitLits = cm->unitLits = sat_ArrayAlloc(16);
+
+  clause = sat_ArrayAlloc(50);
+
+  for(i=0, space=reached->space; i<reached->num; i++, space++){
+    if(*space <= 0) {
+      space++;
+      i++;
+      if(i>=reached->num)
+	break;
+      start = space;
+      clause->num = 0;
+      while(*space > 0) {
+	v = (*space);
+	sat_ArrayInsert(clause, SATnot(v));
+	i++;
+	space++;
+      }
+
+      c = sat_AddBlockingClause(cm, clause);
+
+      /**
+	fprintf(stdout, "NOTICE : forwarded blocking clause\n");
+	sat_PrintNode(cm, c);
+	**/
+
+      if(clause->num == 1)
+	sat_ArrayInsert(unitLits, (v));
+      i--;
+      space--;
+    }
+  }
+  sat_ArrayFree(clause);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Restore Frontier clauses]
+
+  Description [ Restore Frontier clauses]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_RestoreFrontierClauses(satManager_t *cm)
+{
+long *space, *start;
+long c, v;
+int i;
+satArray_t *frontier;
+satArray_t *clause;
+satArray_t *unitLits;
+
+  frontier = cm->frontier;
+  cm->frontierNodesEnd = cm->nodesArraySize;
+  if(frontier == 0)
+    return;
+
+  unitLits = cm->unitLits;
+  if(unitLits == 0)
+    unitLits = cm->unitLits = sat_ArrayAlloc(16);
+
+  clause = sat_ArrayAlloc(50);
+
+  for(i=0, space=frontier->space; i<frontier->num; i++, space++){
+    if(*space <= 0) {
+      space++;
+      i++;
+      if(i>=frontier->num)
+	break;
+      start = space;
+      clause->num = 0;
+      while(*space > 0) {
+	v = (*space);
+	sat_ArrayInsert(clause, SATnot(v));
+	i++;
+	space++;
+      }
+
+      c = sat_AddClause(cm, clause);
+
+      /**
+      sat_PrintNode(cm, c);
+      **/
+
+      cm->initNumClauses++;
+      cm->initNumLiterals += clause->num;
+      if(clause->num == 1)
+	sat_ArrayInsert(unitLits, (v));
+
+      i--;
+      space--;
+    }
+  }
+  sat_ArrayFree(clause);
+  cm->frontierNodesEnd = cm->nodesArraySize;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Restore clauses]
+
+  Description [ Restore clauses]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_RestoreClauses(satManager_t *cm, satArray_t *cnfArray)
+{
+long *space, *start;
+long c, v;
+int i;
+satArray_t *clause;
+satArray_t *unitLits;
+
+
+  unitLits = cm->unitLits;
+  if(unitLits == 0)
+    unitLits = cm->unitLits = sat_ArrayAlloc(16);
+
+  clause = sat_ArrayAlloc(50);
+
+  for(i=0, space=cnfArray->space; i<cnfArray->num; i++, space++){
+    if(*space <= 0) {
+      space++;
+      i++;
+      if(i>=cnfArray->num)
+	break;
+      start = space;
+      clause->num = 0;
+      while(*space > 0) {
+	v = (*space);
+	sat_ArrayInsert(clause, SATnot(v));
+	i++;
+	space++;
+      }
+
+      if(clause->num == 1) {
+	sat_ArrayInsert(unitLits, (v));
+      }
+      else {
+	c = sat_AddClause(cm, clause);
+      }
+
+      cm->initNumClauses++;
+      cm->initNumLiterals += clause->num;
+
+      i--;
+      space--;
+    }
+  }
+  sat_ArrayFree(clause);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Collect blocking clauses]
+
+  Description [ Collect blocking clauses]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_CollectBlockingClause(satManager_t *cm)
+{
+satArray_t *reached, *frontier;
+long i, v, tv, *plit;
+int j, size;
+int inverted, num;
+int nReachs, nFrontiers;
+
+  if(cm->reached == 0)	cm->reached = sat_ArrayAlloc(1024);
+  if(cm->frontier == 0) cm->frontier = sat_ArrayAlloc(1024);
+
+  frontier = cm->frontier;
+  reached = cm->reached;
+
+  frontier->num = 0;
+  reached->num = 0;
+  sat_ArrayInsert(frontier, 0);
+  sat_ArrayInsert(reached, 0);
+  nReachs = nFrontiers = 0;
+
+  for(i=cm->beginConflict; i<cm->nodesArraySize; i+=satNodeSize) {
+    if(!(SATflags(i) & IsBlockingMask))
+      continue;
+
+    if(SATreadInUse(i) == 0)		continue;
+
+    if((SATflags(i) & IsFrontierMask)) {
+
+      /**
+      fprintf(stdout, "Frontier processed\n");
+      sat_PrintNode(cm, i);
+      **/
+      plit = (long*)SATfirstLit(i);
+      size = SATnumLits(i);
+      num = frontier->num;
+      for(j=0; j<size; j++, plit++) {
+	v = SATgetNode(*plit);
+	inverted = SATisInverted(v);
+	tv = SATnormalNode(v);
+	sat_ArrayInsert(frontier, v);
+      }
+      nFrontiers++;
+      sat_ArrayInsert(frontier, 0);
+    }
+
+    plit = (long*)SATfirstLit(i);
+    size = SATnumLits(i);
+    for(j=0; j<size; j++, plit++) {
+      v = SATgetNode(*plit);
+      sat_ArrayInsert(reached, v);
+    }
+    sat_ArrayInsert(reached, 0);
+    nReachs ++;
+  }
+
+
+
+  cm->frontier = frontier;
+  cm->reached = reached;
+  fprintf(stdout, "NOTICE : %d frontier are collected\n", nFrontiers);
+  fprintf(stdout, "NOTICE : %d blocking clauses are collected\n", nReachs);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Free interface]
+
+  Description [ Free interface]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_FreeInterface(satInterface_t *interface)
+{
+  if(interface == 0)	return;
+
+  if(interface->total)
+    free(interface->total);
+  if(interface->nonobjUnitLitArray)
+    sat_ArrayFree(interface->nonobjUnitLitArray);
+  if(interface->objUnitLitArray)
+    sat_ArrayFree(interface->objUnitLitArray);
+  if(interface->savedConflictClauses)
+    free(interface->savedConflictClauses);
+  free(interface);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Create AIG node ]
+
+  Description [ Create AIG node,
+		This function is identical with bAig_CreateNode,
+		We have this function here to isolate this package from baig]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+long
+sat_CreateNode(
+	satManager_t *cm,
+	long left,
+	long right)
+{
+long newNode;
+
+  newNode = cm->nodesArraySize;
+  //Bing: to deal with the case that cm->maxNodesArraySize is not multiple of
+  // satNodeSize
+  cm->nodesArraySize += satNodeSize;
+
+  if(cm->nodesArraySize >= cm->maxNodesArraySize) {
+    cm->maxNodesArraySize = 2* cm->maxNodesArraySize;
+    cm->nodesArray = REALLOC(long, cm->nodesArray, cm->maxNodesArraySize);
+  }
+  cm->nodesArray[newNode + satRight] = right;
+  cm->nodesArray[newNode + satLeft] = left;
+
+  //cm->nodesArraySize += satNodeSize;
+
+  SATflags(newNode) = 0;
+  SATnext(newNode) = 2;
+  SATnFanout(newNode) = 0;
+  /**
+  SATfanout(newNode) = 0;
+  **/
+  (cm->nodesArray[newNode+satFanout]) = 0;
+  //Bing:
+  SATvalue(newNode) = 2;
+
+  return(newNode);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Usage of memory ]
+
+  Description [ Usage of memory ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_MemUsage(satManager_t *cm)
+{
+satLiteralDB_t *literals;
+satStatistics_t *stats;
+int aigSize, cnfSize, watchedSize;
+
+  literals = cm->literals;
+  stats = cm->each;
+  aigSize = sizeof(int) * cm->maxNodesArraySize;
+  cnfSize = sizeof(int) * (literals->end - literals->begin);
+  watchedSize = sizeof(int) * 2 *
+		 (stats->nConflictCl - stats->nDeletedCl);
+  return(aigSize + cnfSize + watchedSize);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Get canonical node ]
+
+  Description [ Get canonical node ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+long
+sat_GetCanonical(satManager_t *cm, long v)
+{
+long nv;
+int inverted;
+
+  if(v == 2)	return(2);
+
+  while(!(SATflags(SATnormalNode(v))) & CanonicalBitMask) {
+    inverted = SATisInverted(v);
+    v = SATnormalNode(v);
+    nv = SATcanonical(v);
+    if(inverted)
+      nv = SATnot(nv);
+    v = nv;
+  }
+  return(v);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Combine statistics of several runs]
+
+  Description [ Combine statistics of several runs]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_CombineStatistics(satManager_t *cm)
+{
+    /* CONSIDER ... */
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Get the number of initial clauses ]
+
+  Description [ Get the number of initial clauses.
+		This function works properly only CNF sat case]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_GetNumberOfInitialClauses(satManager_t *cm)
+{
+  return(cm->initNumClauses);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Get the number of initial variables ]
+
+  Description [ Get the number of initial variables.
+		This function works properly only CNF sat case]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_GetNumberOfInitialVariables(satManager_t *cm)
+{
+  return(cm->initNumVariables);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Read forced assignments.]
+
+  Description [ Read forced assignments.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+satArray_t *
+sat_ReadForcedAssignment(
+	char *filename)
+{
+FILE *fin;
+char line[102400], word[1024];
+char *lp;
+satArray_t *arr;
+long v;
+
+  if(!(fin = fopen(filename, "r"))) {
+    fprintf(stdout, "ERROR : Can't open file %s\n", filename);
+    return(0);
+  }
+
+  arr = sat_ArrayAlloc(64);
+  while(fgets(line, 102400, fin)) {
+    lp = sat_RemoveSpace(line);
+    if(lp[0] == '\n')	continue;
+    while(1) {
+      lp = sat_RemoveSpace(lp);
+      lp = sat_CopyWord(lp, word);
+      if(strlen(word)) {
+	v = atoi(word);
+	v *= satNodeSize;
+	if(v < 0)	v = SATnot(-v);
+	sat_ArrayInsert(arr, v);
+      }
+      else {
+	break;
+      }
+    }
+  }
+  fclose(fin);
+
+  return(arr);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Apply forced assignments.]
+
+  Description [ Apply forced assignments.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+sat_ApplyForcedAssigment(
+	satManager_t *cm,
+	satArray_t *arr,
+	satLevel_t *d)
+{
+long v;
+int i, inverted, errorFlag;
+
+  errorFlag = 0;
+  for(i=0; i<arr->num; i++) {
+    v = arr->space[i];
+    inverted = SATisInverted(v);
+    v = SATnormalNode(v);
+
+    SATvalue(v) = !inverted;
+    SATmakeImplied(v, d);
+    sat_Enqueue(cm->queue, v);
+    SATflags(v) |= InQueueMask;
+    sat_ImplicationMain(cm, d);
+    if(d->conflict) {
+      fprintf(cm->stdOut,
+	      "%s WARNING : conflict happens at level %d while applying forced assignments\n", cm->comment, d->level);
+      errorFlag = 1;
+      break;
+    }
+  }
+  if(errorFlag)
+    return(SAT_UNSAT);
+  else
+    return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Apply forced assignments.]
+
+  Description [ Apply forced assignments.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_ApplyForcedAssignmentMain(
+	satManager_t *cm,
+	satLevel_t *d)
+{
+satArray_t *forcedArr;
+int flag;
+
+  forcedArr = cm->option->forcedAssignArr;
+  flag = 0;
+  if(forcedArr) {
+    flag = sat_ApplyForcedAssigment(cm, forcedArr, d);
+  }
+
+  if(flag == SAT_UNSAT) {
+    cm->status = SAT_UNSAT;
+    return;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Put assignments.]
+
+  Description [ Put assignments.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_PutAssignmentValueMain(
+	satManager_t *cm,
+	satLevel_t *d,
+	satArray_t *arr)
+{
+long v;
+int i;
+int inverted;
+
+  if(arr == 0)	return;
+
+  if(cm->variableArray == 0) {
+    cm->variableArray = ALLOC(satVariable_t, cm->initNumVariables+1);
+    memset(cm->variableArray, 0,
+	    sizeof(satVariable_t) * (cm->initNumVariables+1));
+  }
+
+  for(i=0; i<arr->num; i++) {
+    v = arr->space[i];
+    inverted = SATisInverted(v);
+    v = SATnormalNode(v);
+
+    SATvalue(v) = !inverted;
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Clause deletion heuristic based on usage of conflict clause ]
+
+  Description [ Clause deletion heuristic based on usage of conflict clause ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+sat_ClauseDeletionLatestActivity(satManager_t *cm)
+{
+satLiteralDB_t *literals;
+satOption_t *option;
+long nv, v, *plit, *clit;
+long usage, totalConflictCl;
+long index, lit;
+
+int size, n0, n1x, deleteFlag;
+int unrelevance;
+int usedLimit;
+int inverted, i;
+int value;
+int nLatestCl;
+int nDeletedCl;
+double ratio;
+
+/**
+ LATEST_ACTIVITY_DELETION
+ MAX_UNRELEVANCE_DELETION
+ SIMPLE_LATEST_DELETION
+**/
+
+  option = cm->option;
+  if(option->clauseDeletionHeuristic == 0)	return;
+
+  totalConflictCl = (cm->nodesArraySize - cm->beginConflict)/satNodeSize;
+  nDeletedCl = cm->each->nDeletedCl;
+  nLatestCl = totalConflictCl/option->latestRate;
+  literals = cm->literals;
+  index = 0;
+  for(clit = literals->last-1; clit > literals->begin; clit--){
+    if(*clit == 0)
+      continue;
+    if(index >= totalConflictCl)
+      break;
+    v = -(*clit);
+
+    plit = (long*)SATfirstLit(v);
+    clit = plit - 1;
+    index++;
+
+    if(nLatestCl > 0) {
+      nLatestCl--;
+      unrelevance = option->latestUnrelevance;
+    }
+    else {
+      unrelevance = option->obsoleteUnrelevance;
+    }
+
+    if(!(SATflags(v) & IsConflictMask)) continue;
+    if((SATflags(v) & IsFrontierMask))	continue;
+
+    if(option->incPreserveNonobjective && (SATflags(v) & NonobjMask))
+      continue;
+
+    usage = SATconflictUsage(v);
+    SATconflictUsage(v) = usage/2;
+    size = SATnumLits(v);
+//    if(size < option->minLitsLimit)	continue;
+    if(size < unrelevance)
+      continue;
+
+    usedLimit = option->obsoleteUsage +
+	(option->latestUsage-option->obsoleteUsage)*index/totalConflictCl;
+    if(usage > usedLimit)
+      continue;
+
+
+    n0 = n1x = 0;
+    deleteFlag = 0;
+    for(i=0; i<size; i++, plit++) {
+      lit = *plit;
+      nv = SATgetNode(lit);
+      inverted = SATisInverted(nv);
+      nv = SATnormalNode(nv);
+      value = SATvalue(nv) ^ inverted;
+
+      if(value == 0)	n0++;
+      else if(value == 1) {
+	n1x++;
+	if(SATlevel(nv) == 0)	deleteFlag = 1;
+      }
+      else	n1x++;
+
+      if(deleteFlag) {
+	sat_DeleteClause(cm, v);
+	sat_Enqueue(cm->unusedAigQueue, v);
+	break;
+      }
+      if((size > option->maxLitsLimit) && (n1x > 1)) {
+	sat_DeleteClause(cm, v);
+	sat_Enqueue(cm->unusedAigQueue, v);
+	break;
+      }
+      if(n1x > unrelevance) {
+	sat_DeleteClause(cm, v);
+	sat_Enqueue(cm->unusedAigQueue, v);
+	break;
+      }
+    }
+
+  }
+
+  cm->each->nDeletedButUncompacted += cm->each->nDeletedCl - nDeletedCl;
+  ratio = (double)cm->each->nDeletedButUncompacted/
+	  (double)(cm->each->nConflictCl-cm->each->nDeletedCl);
+
+  if(ratio> 0.2) {
+    sat_CompactClauses(cm);
+    cm->each->nDeletedButUncompacted = 0;
+  }
+
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Find a clause index from literal pointer.]
+
+  Description [ Find a clause index from literal pointer.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+long
+sat_GetClauseFromLit(
+	satManager_t *cm,
+	long *lit)
+{
+  while(*lit > 0) {
+    lit++;
+  }
+  return(-(*lit));
+}
+/**Function********************************************************************
+
+  Synopsis    [ Compare node index to sort ]
+
+  Description [ Compare node index to sort ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+NodeIndexCompare(const void *x, const void *y)
+{
+long n1, n2;
+
+  n1 = *(long *)x;
+  n2 = *(long *)y;
+  return(n1 > n2);
+}
Index: vis_dev/vis-2.3/src/sim/sim.h
===================================================================
--- vis_dev/vis-2.3/src/sim/sim.h	(revision 14)
+++ vis_dev/vis-2.3/src/sim/sim.h	(revision 14)
@@ -0,0 +1,137 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [sim.h]
+
+  PackageName [sim]
+
+  Synopsis    [Simulation of a flattened network.]
+
+  Description [The sim package provides functions for simulation. It also
+  provides the "simulate" command in the VIS environment. The simulate command
+  performs a simulation of a network or a part of a network.
+  <p>
+  sim conceives simulation through three operations:
+  <p>
+  1- Build simulation vectors.
+  <p>
+  2- Simulate.
+  <p>
+  3- Print the result.
+  <p>
+  Exported functions make it possible to build an internal data-structure, and
+  perform the three operations given above. Simulation vectors may be provided
+  by the user. Using exported functions, it is also possible to generate
+  simulation vectors randomly or reading it from a file. Low level functions
+  are also available that evaluate, for example, a network node using a
+  simulation vector. An example of a simulation vectors file may be generated
+  using the simulate command with random-vectors-generation option, in VIS.
+  <p>
+  WARNING : In order to improve the speed of simulation, it is assumed that
+  each combinational output function is completely specified, and that each
+  simulation vector specifies a minterm over the combinational inputs this
+  assumption is not checked. Incorrect results may be produced if this
+  assumption is violated.]
+
+  Author      [Shaker Sarwary and Tom Shiple]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: sim.h,v 1.5 2002/09/08 23:33:35 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _SIM
+#define _SIM
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "ntk.h"
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/* Sim main Data structure type */
+
+typedef struct SimSimStruct Sim_Sim_t;
+
+/**Enum************************************************************************
+
+  Synopsis    [Pseudo-inputs source.]
+
+  Description [Pseudo-inputs source. There are 4 possible source :
+  ---> undefined : If input vectors are read from a file, then user must
+  specify the pseudo-inputs. If vectors are generated randomly, then
+  pseudo-inputs are chosen randomly.
+  ---> user : Pseudo-inputs are specified in the input vectors file.
+  ---> random : Pseudo-inputs are generated randomly. If vectors are read from
+  a file, this option cannot be used.
+  ---> first : The first value of pseudo-input in the array of value of the
+  variable is chosen. If vectors are read from a file, this option cannot be used.
+
+******************************************************************************/
+typedef enum {
+  Sim_Undef_c,
+  Sim_User_c,
+  Sim_Random_c,
+  Sim_First_c
+} Sim_PseudoSrc;
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void Sim_SimPrint(Sim_Sim_t * sim, FILE * of, boolean printMode, int printInputsFlag, int printOutputsFlag, int printPseudoInputsFlag, int printStatesFlag);
+EXTERN Sim_Sim_t * Sim_FileParseDeclaration(Ntk_Network_t * network, FILE * fp, char * inputFile, boolean verbose);
+EXTERN int Sim_FileParseVectors(FILE * fp, Sim_Sim_t * sim, int num);
+EXTERN void Sim_Init(void);
+EXTERN void Sim_End(void);
+EXTERN Sim_Sim_t * Sim_SimCreate(Ntk_Network_t * network, st_table * nodeToMvfTable, char * inputFile, int lineNumber, array_t * nodesArray, int currentStateHead, int internalPartitionHead, int nextStateHead, int outputHead, array_t * initState, array_t * vectorArray, boolean verbose);
+EXTERN void Sim_SimReset(Sim_Sim_t * sim);
+EXTERN void Sim_SimFree(Sim_Sim_t * sim);
+EXTERN array_t * Sim_NetworkCreateNodesArray(Ntk_Network_t * network, int * currentStateHead, int * internalPartitionHead, int * nextStateHead, int * outputHead);
+EXTERN void Sim_SimGenerateRandomVectors(Sim_Sim_t * sim, int numberVector, Sim_PseudoSrc pseudoInputSource);
+EXTERN void Sim_SimGenerateRandomInitState(Sim_Sim_t * sim);
+EXTERN void Sim_SimSimulate(Sim_Sim_t * sim);
+EXTERN int Sim_nodeToMvfTableEvaluateNode(st_table * nodeToMvfTable, Ntk_Node_t * node, mdd_t * vectorMdd);
+EXTERN array_t * Sim_nodeToMvfTableEvaluateNodesArray(st_table * nodeToMvfTable, array_t * nodesArray, mdd_t * vectorMdd);
+EXTERN mdd_t * Sim_RandomSimulate(Ntk_Network_t * network, int num, boolean verbose);
+EXTERN Ntk_Network_t * Sim_SimReadNetwork(Sim_Sim_t * sim);
+EXTERN st_table * Sim_SimReadNodeToMvfTable(Sim_Sim_t * sim);
+EXTERN char * Sim_SimReadInputFile(Sim_Sim_t * sim);
+EXTERN int Sim_SimReadLineNumber(Sim_Sim_t * sim);
+EXTERN array_t * Sim_SimReadNodesArray(Sim_Sim_t * sim);
+EXTERN int Sim_SimReadCurrentStateHead(Sim_Sim_t * sim);
+EXTERN int Sim_SimReadNextStateHead(Sim_Sim_t * sim);
+EXTERN int Sim_SimReadOutputHead(Sim_Sim_t * sim);
+EXTERN array_t * Sim_SimReadInitState(Sim_Sim_t * sim);
+EXTERN array_t * Sim_SimReadVectorArray(Sim_Sim_t * sim);
+EXTERN boolean Sim_SimTestIsVerbose(Sim_Sim_t * sim);
+EXTERN st_table * Sim_NetworkBuildNodeToMvfTable(Ntk_Network_t *network, array_t *nodesArray, int internalPartitionHead, int nextStateHead);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _SIM */
+
+
Index: vis_dev/vis-2.3/src/sim/sim.make
===================================================================
--- vis_dev/vis-2.3/src/sim/sim.make	(revision 14)
+++ vis_dev/vis-2.3/src/sim/sim.make	(revision 14)
@@ -0,0 +1,4 @@
+CSRC += simIo.c simMain.c simSim.c simUtil.c
+HEADERS += sim.h simInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/sim/simInt.h
===================================================================
--- vis_dev/vis-2.3/src/sim/simInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/sim/simInt.h	(revision 14)
@@ -0,0 +1,215 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [simInt.h]
+
+  PackageName [sim]
+
+  Synopsis    [sim package internal declarations file.]
+  
+  Author      [Shaker Sarwary and Tom Shiple]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: simInt.h,v 1.4 2005/05/10 15:50:43 hhkim Exp $]
+
+******************************************************************************/
+
+#ifndef _SIMINT
+#define _SIMINT
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "cmd.h"
+#include "ntm.h"
+#include "ord.h"
+#include "part.h"
+#include "sim.h"
+#include <string.h>
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+#define SIMPACKET_SIZE    1000
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [SIM main structure.]
+
+******************************************************************************/
+
+struct SimSimStruct {
+  Ntk_Network_t *network;          /* Pointer to the network */
+  st_table      *nodeToMvfTable;   /* MDDs of functions to be simulated */
+  char          *inputFile;        /* simulation file name */
+  int            lineNumber;       /* Current line parsed in InputFile */
+  array_t       *nodesArray;       /* Ordered nodes corresponding to the inputs,
+                                      current-states, next-states and outputs */
+  int            currentStateHead; /* Position of the first currentState in nodesArray */
+  int            internalPartitionHead; /* Position of the first internal partition node 
+                                        in nodesArray */
+  int            nextStateHead;    /* Position of the first nextState in nodesArray */
+  int            outputHead;       /* Position of the first output in nodesArray */
+  array_t       *initState;        /* Initial state */
+  array_t       *vectorArray;      /* Array of array representing the
+                                      simulation vectors according to the
+                                      nodesArray order */
+  boolean        verbose;
+};
+  
+  
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void SimSimInitializeCurrentState(Sim_Sim_t * sim);
+EXTERN boolean SimRandomSimulateAndPrint(Ntk_Network_t * network, int num, char * outputFile, Sim_PseudoSrc pseudoInputSource, int printInputsFlag, int printOutputsFlag, int printPseudoInputsFlag, int printStatesFlag, boolean verbose);
+EXTERN boolean SimFileSimulateAndPrint(Ntk_Network_t * network, int num, char * inputFile, char * outputFile, Sim_PseudoSrc pseudoInputSource, int printInputsFlag, int printOutputsFlag, int printPseudoInputsFlag, int printStatesFlag, boolean verbose);
+EXTERN int SimNodeReadValueCode(Ntk_Node_t * node, char * value);
+EXTERN boolean SimTestPartInTermsOfCI(Sim_Sim_t *sim);
+EXTERN char * SimInteger2ASCII(int number);
+EXTERN void SimStringPrint(FILE * fp, char * string, int len);
+EXTERN array_t * SimSimInitDataFormat(Sim_Sim_t * sim);
+EXTERN void SimSimVectorFillCurrentState(Sim_Sim_t * sim, int n);
+EXTERN int SimNodeComputeRandomValue(Ntk_Node_t * node, Sim_PseudoSrc pseudoInputSource);
+EXTERN mdd_t * SimSimVectorBuildMdd(Sim_Sim_t * sim, array_t * vector, array_t * partitionVector);
+EXTERN void SimAppendErrorMsg(char * str1, char * str2, char * str3);
+EXTERN int SimComputeRandomInteger(void);
+EXTERN void SimNodesArrayBuildRootsAndLeaves(Ntk_Network_t *network, array_t * nodesArray, int internalPartitionHead, int nextStateHead, array_t ** roots, array_t ** leaves);
+EXTERN st_table * SimNodesArrayBuildNodeToMvfTable(array_t * nodesArray, int internalPartitionHead, array_t * mvfArray);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _SIMINT */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/sim/simIo.c
===================================================================
--- vis_dev/vis-2.3/src/sim/simIo.c	(revision 14)
+++ vis_dev/vis-2.3/src/sim/simIo.c	(revision 14)
@@ -0,0 +1,906 @@
+/**CFile***********************************************************************
+
+  FileName    [simIo.c]
+
+  PackageName [sim]
+
+  Synopsis    [Routines to read and write simulation vectors.]
+
+  Author      [Shaker Sarwary, Tom Shiple and Rajeev Ranjan]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+#include "simInt.h"
+
+static char rcsid[] UNUSED = "$Id: simIo.c,v 1.5 2005/05/10 15:50:43 hhkim Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*
+ * Maximum permissible length of a line in the simulation file.
+ */
+#define MAX_LINE_LENGTH 500000
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static array_t * SimObtainInputsArray(Sim_Sim_t * sim);
+static void FreeArrays(array_t *array1, array_t *array2, array_t *array3, array_t *array4);
+static array_t * BufferBuildInputsNodeArray(char * buffer, Ntk_Network_t * network);
+static array_t * BufferBuildLatchesNodeArray(char * buffer, Ntk_Network_t * network);
+static array_t * BufferBuildOutputsNodeArray(char * buffer, Ntk_Network_t * network);
+static array_t * BufferBuildValuesArray(char * buffer, array_t * nodesArray);
+static void SimAddVector(Sim_Sim_t * sim, array_t * vector);
+static void BufferSkipWhiteSpace(char * buffer, int * position);
+static char * BufferObtainStringAtPosition(char * buffer, int * position);
+static void PrintValue(array_t *nodesArray, array_t *vector, int vectorIndex, int strSize, FILE *file);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Print the simulation vectors contained in a SimSimStruct.]
+
+  Description [Print the simulation vectors contained in a SimSimStruct. If
+  printMode is 0, then only vectors are printed, else the header is also
+  printed(.inputs, .outputs ...). printInputsFlag,
+  printPseudoInputsFlag, printOutputsFlag, and printStatesFlag control
+  the printing of primary inputs, pseudo inputs, primary outputs and
+  state variables respectively. A value of 1 of these flags indicate
+  printing is enabled, and value 0 indicates otherwise.  This function writes
+  warnings into error_string. The printed file is accepted as input file in sim.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Sim_SimPrint(
+  Sim_Sim_t       * sim,
+  FILE            * of,
+  boolean         printMode,
+  int             printInputsFlag,
+  int             printOutputsFlag,
+  int             printPseudoInputsFlag,
+  int             printStatesFlag
+  )
+
+{
+  int             i, j;
+  char           *str;
+  array_t        *vector = NIL(array_t);
+  array_t        *formatArray;
+  Ntk_Node_t     *node;
+  Var_Variable_t *var;
+  int             index;
+  int             strSize     = 0;
+  int             numNodes    = array_n(sim->nodesArray);  
+  int             inputWidth  = sim->currentStateHead;
+
+  if(sim->verbose) {
+    (void) printf("Printing %d vectors...\n", array_n(sim->vectorArray));
+  }
+  
+  formatArray = SimSimInitDataFormat(sim);
+  
+  if (printMode) {
+    (void) fprintf(of, "# %s\n", Vm_VisReadVersion());
+    (void) fprintf(of, "# Network: %s\n", Ntk_NetworkReadName(sim->network));
+
+    if (sim->inputFile != NIL(char)) {
+      (void) fprintf(of, "# Input Vectors File: %s\n", sim->inputFile);
+    }
+    else {
+      (void) fprintf(of, "# Simulation vectors have been randomly generated\n");
+    }
+    (void) fprintf(of, "\n\n");
+    (void) fprintf(of, ".inputs  ");
+    for (i = 0; i < inputWidth; i++) {
+      node = array_fetch(Ntk_Node_t *, sim->nodesArray, i);
+      (void) fprintf(of, "%s ", Ntk_NodeReadName(node));
+    }
+    (void) fprintf(of, "\n");
+    (void) fprintf(of, ".latches ");
+    for (i = sim->currentStateHead; i < sim->internalPartitionHead; i++) {
+      node = array_fetch(Ntk_Node_t *, sim->nodesArray, i);
+      (void) fprintf(of, "%s ", Ntk_NodeReadName(node));
+    }
+    (void) fprintf(of, "\n");
+
+    (void) fprintf(of, ".outputs ");
+    for (i = sim->outputHead; i < numNodes; i++) {
+      node = array_fetch(Ntk_Node_t *, sim->nodesArray, i);
+      (void) fprintf(of, "%s ", Ntk_NodeReadName(node));
+    }
+    (void) fprintf(of, "\n");
+
+    /* Reset State is the current state of the first vector */
+    (void) fprintf(of, ".initial ");
+    vector = array_fetch(array_t *, sim->vectorArray, 0);
+    for (i = sim->currentStateHead; i < sim->internalPartitionHead; i++) {
+      if(i >= array_n(vector)) {/* If currentState is not specified '*' is printed */
+        (void) fprintf(of, "* ");
+      }
+      else {
+        node = array_fetch(Ntk_Node_t *, sim->nodesArray, i);
+        var = Ntk_NodeReadVariable(node);
+        index = array_fetch(int, vector, i);
+        if (Var_VariableTestIsSymbolic(var)) {
+          (void) fprintf(of, "%s ", Var_VariableReadSymbolicValueFromIndex(var, index));
+        }
+        else { /* Binary or enumerative type */
+          str = SimInteger2ASCII(index);
+          (void) fprintf(of, "%s ", str);
+          FREE(str);
+        }
+      }
+    }
+    
+    (void) fprintf(of, "\n\n.start_vectors");
+
+    (void) fprintf(of, "\n\n");
+
+    /*
+     * Print the order of variables for which values
+     * are printed in the next lines.
+     */
+    
+    (void) fprintf(of, "# ");
+    /*
+     * If either printInputsFlag or printPseudoInputsFlag is zero, we
+     * cannot use the output as the input for simulation. Print a
+     * warning message regarding that.
+     */
+    if ((printInputsFlag == 0) || (printPseudoInputsFlag == 0)){
+      (void) fprintf(vis_stderr,"Warning - print flag of some inputs is set to zero.\n");
+      (void) fprintf(vis_stderr,"Hence the output file you specified cannot be used as an input\n");
+      (void) fprintf(vis_stderr,"file for a subsequent simulation run.\n");
+    }
+      
+    if (printInputsFlag || printPseudoInputsFlag){
+      for (i = 0; i < inputWidth; i++) {
+        node = array_fetch(Ntk_Node_t *, sim->nodesArray, i);
+        if (Ntk_NodeTestIsPrimaryInput(node)){
+          if (printInputsFlag){
+            (void) fprintf(of, "%s ", Ntk_NodeReadName(node));
+          }
+        }
+        else{
+          if (printPseudoInputsFlag){
+            (void) fprintf(of, "%s ", Ntk_NodeReadName(node));
+          }
+        }
+      }
+      (void) fprintf(of, "; ");
+    }
+    
+    if (printStatesFlag) {
+      for (i = sim->currentStateHead; i < sim->internalPartitionHead; i++) {
+        node = array_fetch(Ntk_Node_t *, sim->nodesArray, i);
+        (void) fprintf(of, "%s ", Ntk_NodeReadName(node));
+      }
+      (void) fprintf(of, "; ");      
+    }
+    if (printOutputsFlag){
+      for (i = sim->outputHead; i < numNodes; i++) {
+        node = array_fetch(Ntk_Node_t *, sim->nodesArray, i);
+        (void) fprintf(of, "%s ", Ntk_NodeReadName(node));
+      }
+      (void) fprintf(of, "\n\n");
+    }
+  }
+  
+  for (i = 0; i < array_n(sim->vectorArray); i++) {
+    vector = array_fetch(array_t *, sim->vectorArray, i);
+    if ((printInputsFlag) || (printPseudoInputsFlag)){
+      for (j = 0; j < sim->currentStateHead; j++) {
+        strSize = array_fetch(int, formatArray, j);
+        node = array_fetch(Ntk_Node_t *, sim->nodesArray, j);
+        if (Ntk_NodeTestIsPrimaryInput(node)){
+          if(printInputsFlag){
+            PrintValue(sim->nodesArray, vector, j, strSize, of);
+          }
+        }
+        else {
+          if (printPseudoInputsFlag){
+            PrintValue(sim->nodesArray, vector, j, strSize, of);
+          }
+        }
+      }
+    }
+    if (printStatesFlag){
+      (void) fprintf(of,"; ");
+      for (j = sim->currentStateHead; j < sim->internalPartitionHead; j++){
+        strSize = array_fetch(int, formatArray, j);
+        node = array_fetch(Ntk_Node_t *, sim->nodesArray, j);
+        PrintValue(sim->nodesArray, vector, j, strSize, of);
+      }
+    }
+    if (printOutputsFlag){
+      (void) fprintf(of,"; ");
+      for (j = sim->outputHead; j < numNodes; j++){
+        strSize = array_fetch(int, formatArray, j);
+        node = array_fetch(Ntk_Node_t *, sim->nodesArray, j);
+        PrintValue(sim->nodesArray, vector, j, strSize, of);
+      }
+    }
+    (void) fprintf(of, "\n");
+  }
+  if (printStatesFlag){
+    /*
+     * Need to print the final state on a separate line.
+     */
+    (void) fprintf(of,"# Final State : ");
+    for (j = sim->currentStateHead; j < sim->internalPartitionHead; j++){
+      strSize = array_fetch(int, formatArray, j);
+      node = array_fetch(Ntk_Node_t *, sim->nodesArray, j);
+      PrintValue(sim->nodesArray, vector, j, strSize, of);
+    }
+    (void) fprintf(of, "\n");
+  }
+  array_free(formatArray);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis [Parses the header of the simulation vectors file containing
+  declarations, and builds a SimSimStruct.]
+
+  Description [Parses the header of the simulation vectors file containing
+  declarations, and builds a SimSimStruct. nodeToMvfTable providing MDDs of
+  primary outputs and next-state functions is also built. verbose is here for
+  initialization of sim structure. The header of a simulation-vectors file
+  contains .inputs, .latches, .outputs, and .initial fields. If a variable is
+  found for which there doesn't exist a corresponding node in the network, or
+  a value is found that does not belong to the domain of its specific
+  variable, then an error message is written in error_string, the allocated
+  memory is freed, and the function returns NULL. The simulation file must
+  contain each category of declaration in a line(Two ".inputs" is not allowed
+  in the same file). initial-state declaration must be written after the
+  latches declaration. The function returns the initialized sim structure.]
+
+  SideEffects []
+
+******************************************************************************/
+Sim_Sim_t *
+Sim_FileParseDeclaration(
+  Ntk_Network_t * network,
+  FILE          * fp,
+  char          * inputFile,
+  boolean         verbose)
+{
+  int            i;
+  Ntk_Node_t    *node;
+  char           buffer[MAX_LINE_LENGTH];
+  char          *buffer2;
+  int            currentStateHead;
+  int            internalPartitionHead;
+  int            nextStateHead;
+  int            outputHead;
+  st_table      *nodeToMvfTable;
+  array_t       *nodesArray;
+  int            lineNumber              = 0;
+  array_t       *inputsArray             = NIL(array_t);
+  array_t       *latchesArray            = NIL(array_t);
+  array_t       *internalPartitionArray  = NIL(array_t);
+  array_t       *outputsArray            = NIL(array_t);
+  array_t       *initState               = NIL(array_t);
+  Sim_Sim_t     *sim                     = NIL(Sim_Sim_t);
+  graph_t       *partition;
+  vertex_t      *vertex;
+  array_t       *dfsarray;
+
+  internalPartitionArray = array_alloc(Ntk_Node_t *, 0);
+
+  /* Add internal partition nodes */
+  partition = Part_NetworkReadPartition(network);
+  dfsarray = g_dfs(partition);
+  for(i=0; i< array_n(dfsarray); i++){
+    vertex = array_fetch(vertex_t *, dfsarray, i);
+    node = Ntk_NetworkFindNodeByName(network, Part_VertexReadName(vertex));
+    if(!(Ntk_NodeTestIsCombInput(node) || Ntk_NodeTestIsCombOutput(node))){
+      array_insert_last(Ntk_Node_t *, internalPartitionArray, node);
+    }
+  }
+  array_free(dfsarray);
+
+  while (fgets(buffer, MAX_LINE_LENGTH -1, fp) != NULL) {
+    int position = 0;
+    lineNumber++;
+
+    /* Every line must end by '\n' */
+    if (buffer[strlen(buffer) -1] != '\n') {
+      SimAppendErrorMsg("Simulate: Line ",
+                       SimInteger2ASCII(lineNumber), "istoolong!\n");
+      FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray);
+      return(sim);
+    }
+    
+  
+    /* Eliminate spaces */
+    BufferSkipWhiteSpace(buffer, &position);
+    /* buffer2 will contain buffer without space in the begining */
+    buffer2 = buffer + position;
+    /* Avoid comment and empty lines */
+    if (buffer[position] != '#' && buffer[position] != '\n') {
+      if (!strncmp(buffer2, ".inputs", 7)) {
+        inputsArray = BufferBuildInputsNodeArray(buffer2 + 7, network);
+        if (inputsArray == NIL(array_t)) {
+          SimAppendErrorMsg("Simulate: Error line ",
+                           SimInteger2ASCII(lineNumber), ".\n");
+          FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray);
+          return(sim);
+        }
+      }
+      else if (!strncmp(buffer2, ".latches", 8)) {
+        latchesArray = BufferBuildLatchesNodeArray(buffer2 + 8, network);
+        if (latchesArray == NIL(array_t)) {
+          SimAppendErrorMsg("Simulate: Error line ",
+                           SimInteger2ASCII(lineNumber), ".\n");
+          FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray);
+          return(sim);
+        }
+      }
+      else if (!strncmp(buffer2, ".outputs", 8)) {
+        outputsArray = BufferBuildOutputsNodeArray(buffer2 + 8, network);
+        if (outputsArray == NIL(array_t)) {
+          SimAppendErrorMsg("Simulate: Error line ", SimInteger2ASCII(lineNumber),
+                           ".\n");
+          FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray);
+          return(sim);
+        }
+      }
+      else if (!strncmp(buffer2, ".initial", 8)) {
+        /* Error if latches are not  already read before initial-state */
+        if (latchesArray == NIL(array_t)) {
+          error_append("Simulate: Latches must be declared before initial state declaration.\n");
+          FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray);
+          return(sim);
+        }
+        initState = BufferBuildValuesArray(buffer2 + 8, latchesArray);
+        if (initState == NIL(array_t)) {
+          SimAppendErrorMsg("Simulate: Error line ",
+                           SimInteger2ASCII(lineNumber), ".\n");
+          FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray);
+          return(sim);
+        }
+      }
+      else if (!strncmp(buffer2, ".start_vectors", 14)) {
+        /* Verification of the declarations */
+        if (inputsArray == NIL(array_t)) {
+          error_append("Simulate: Input file is missing inputs declaration.\n");
+          FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray);
+          return(sim);
+        }
+          
+        currentStateHead = array_n(inputsArray);
+          
+        nodesArray = array_dup(inputsArray);
+        array_free(inputsArray);
+        inputsArray = NIL(array_t);
+        if(latchesArray == NIL(array_t)) {
+          /* Verify if actually there is no latch in the network */
+          if (Ntk_NetworkReadNumLatches(network) > 0) {
+            error_append("Simulate: Input file is missing latches declaration.\n");
+            FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray);
+            return(0);
+          }
+          else {
+	    internalPartitionHead = currentStateHead;
+            nextStateHead = internalPartitionHead + array_n(internalPartitionArray);
+            outputHead = nextStateHead;
+          }
+        }
+        else {
+          internalPartitionHead = currentStateHead + array_n(latchesArray);
+          nextStateHead = internalPartitionHead + array_n(internalPartitionArray);
+          outputHead = nextStateHead + array_n(latchesArray);
+          /* Add current states node */
+          array_append(nodesArray, latchesArray);
+	  array_append(nodesArray, internalPartitionArray);
+	  array_free(internalPartitionArray);
+          /* Add next state node as data-input of current-state node */
+          for(i = 0; i < array_n(latchesArray); i++) {
+            node = array_fetch(Ntk_Node_t *, latchesArray, i);
+            node = Ntk_LatchReadDataInput(node);
+            array_insert_last(Ntk_Node_t *, nodesArray, node);
+          }
+          array_free(latchesArray);
+        }
+        if (outputsArray != NIL(array_t)) {
+          array_append(nodesArray, outputsArray);
+          array_free(outputsArray);
+        }
+        /* Building nodeToMvfTable */
+        nodeToMvfTable = Sim_NetworkBuildNodeToMvfTable(network, nodesArray,
+						       internalPartitionHead,
+                                                       nextStateHead);
+        sim = Sim_SimCreate(network, nodeToMvfTable, inputFile, lineNumber,
+                            nodesArray, currentStateHead, internalPartitionHead, 
+			    nextStateHead, outputHead, initState, NULL, verbose);
+
+        return(sim); /* Normal end */
+      }
+      
+      /* Unknown string in the declaration part */
+      else {
+        SimAppendErrorMsg("Simulate: Syntax error in the declaration line: ",
+                         SimInteger2ASCII(lineNumber),
+                         " or missing .start_vectors statement.\n") ;
+        FreeArrays(inputsArray, latchesArray, outputsArray, internalPartitionArray);
+        return(sim);
+      }
+    }
+  }
+  array_free(internalPartitionArray);
+  return(sim);  
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Parses the vectors of a simulation vectors file.]
+
+  Description [Parses the vectors of a simulation vectors file. This function
+  should be called after Sim_FileParseDeclaration. Reads lines from first line
+  after ".start_vectors" statement. Fills the vectorArray field of sim. If
+  this field is already set, it will be lost. Only "num" vectors are read(even
+  if the number of vectors in the file is greater than this number). If num is
+  0, then all vectors in the file are read.  If value is found that does not
+  belong to the domain of its specific variable, then an error message is
+  written in error_string, and the function returns 0. The function returns 1
+  if it normally ends and no EOF is detected. It returns 2 otherwise(normal
+  end and EOF).]
+
+  SideEffects []
+
+  SeeAlso     [Sim_FileParseDeclaration, Sim_SimReset]
+
+******************************************************************************/
+int
+Sim_FileParseVectors(
+  FILE      * fp,
+  Sim_Sim_t  * sim,
+  int         num)
+{
+  char           buffer[MAX_LINE_LENGTH];
+  char          *buffer2;
+  array_t       *vectorArray;
+  int            numberVector            = 0;
+  array_t       *inputsArray             = SimObtainInputsArray(sim);
+
+  sim->vectorArray = array_alloc(array_t *, 0);
+  
+  while (fgets(buffer, MAX_LINE_LENGTH -1, fp) != NULL) {
+    int position = 0;
+    (sim->lineNumber)++;
+
+    /* Every line must end by '\n' */
+    if (buffer[strlen(buffer) -1] != '\n') {
+      SimAppendErrorMsg("Simulate: Line ", SimInteger2ASCII(sim->lineNumber),
+                       " is too long!\n");
+      array_free(inputsArray);
+      return(0);
+    }
+    
+    /* Eliminate spaces */
+    BufferSkipWhiteSpace(buffer, &position);
+    /* buffer2 will contain buffer without space in the begining */
+    buffer2 = buffer + position;
+    /* Avoid comment and empty lines */
+    if (buffer[position] != '#' && buffer[position] != '\n') {
+      /* Read only "num" vectors */
+      if (numberVector >= num && num != 0) {
+        array_free(inputsArray);
+        return(1); /* Normal end before EOF */
+      }
+      vectorArray = BufferBuildValuesArray(buffer2, inputsArray);
+      if (vectorArray == NIL(array_t)) {
+        SimAppendErrorMsg("Simulate: Error line ",
+                         SimInteger2ASCII(sim->lineNumber), ".\n");
+        array_free(inputsArray);
+        return(0);
+      }
+      numberVector++;
+      SimAddVector(sim, vectorArray);
+    }
+  }
+  array_free(inputsArray);
+  return(2); /* End of file */
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Returns a new array containing the input nodes.]
+
+  Description [Returns a new array containing the input nodes. If there is no
+  inputs node in sim structure, then an empty array is returned.]
+  
+  SideEffects []
+
+******************************************************************************/
+static array_t *
+SimObtainInputsArray(
+  Sim_Sim_t * sim)
+{
+  int          i;
+  Ntk_Node_t * node;
+  array_t    * inputsArray = array_alloc(Ntk_Node_t *, 0);
+
+  for (i = 0; i < sim->currentStateHead; i++) {
+    node = array_fetch(Ntk_Node_t *, sim->nodesArray, i);
+    array_insert_last(Ntk_Node_t *, inputsArray, node);
+  }
+  return(inputsArray);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees arrays.]
+
+  Description [Frees array. Verifies if array is non NULL.]
+  
+  SideEffects []
+
+******************************************************************************/
+static void
+FreeArrays(
+  array_t *array1,
+  array_t *array2,
+  array_t *array3,
+  array_t *array4)
+{
+  if (array1 != NIL(array_t)) {
+    array_free(array1);
+  }
+  if (array2 != NIL(array_t)) {
+    array_free(array2);
+  }
+  if (array3 != NIL(array_t)) {
+    array_free(array3);
+  }
+  if (array4 != NIL(array_t)) {
+    array_free(array4);
+  }
+}
+  
+
+/**Function********************************************************************
+
+  Synopsis    [Builds an array of nodes corresponding to the name of inputs
+  read in the buffer.]
+
+  Description [Builds an array of nodes corresponding to the name of inputs
+  read in the buffer. If the name does not correspond to any input node in the
+  network, or the number of values is not correct, then an error message is
+  written in error_string, and NULL is returned.]
+  
+  SideEffects []
+
+******************************************************************************/
+static array_t *
+BufferBuildInputsNodeArray(
+  char * buffer,
+  Ntk_Network_t * network)
+{
+  char       *str;
+  Ntk_Node_t *node;
+  int         position = 0;
+  array_t    *array    = array_alloc(Ntk_Node_t *, 0);
+    
+  while((str = BufferObtainStringAtPosition(buffer, &position)) != NULL) {
+    node = Ntk_NetworkFindNodeByActualName(network, str);
+    if (node == NIL(Ntk_Node_t) || !Ntk_NodeTestIsInput(node)) {
+      SimAppendErrorMsg("Simulate: ", str, " is not a valid input name.\n");
+      array_free(array);
+      FREE(str);
+      return(NIL(array_t));
+    }
+    FREE(str);
+    array_insert_last(Ntk_Node_t *, array, node);
+  }
+  /* Verification of number of values */
+  if (array_n(array) != Ntk_NetworkReadNumInputs(network)) {
+    error_append("Simulate: All inputs and pseudo-inputs must be specified.\n");
+    array_free(array);
+    return(NIL(array_t));
+  }
+  return(array);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds an array of nodes corresponding to the name of latches
+  read in the buffer.]
+
+  Description [Builds an array of nodes corresponding to the name of latches
+  read in the buffer. If the name does not correspond to any latch node in the
+  network, or the number of values is not correct, then an error message is
+  written in error_string, and NULL is returned.]
+  
+  SideEffects []
+
+******************************************************************************/
+static array_t *
+BufferBuildLatchesNodeArray(
+  char * buffer,
+  Ntk_Network_t * network)
+{
+  char       *str;
+  Ntk_Node_t *node;
+  int         position = 0;
+  array_t    *array    = array_alloc(Ntk_Node_t *, 0);
+    
+  while ((str = BufferObtainStringAtPosition(buffer, &position)) != NULL) {
+    node = Ntk_NetworkFindNodeByActualName(network, str);
+    if (node == NIL(Ntk_Node_t) || !Ntk_NodeTestIsLatch(node)) {
+      SimAppendErrorMsg("Simulate: ", str, " is not a valid latch name\n");
+      array_free(array);
+      FREE(str);
+      return(NIL(array_t));
+    }
+    FREE(str);
+    array_insert_last(Ntk_Node_t *, array, node);
+  }
+  /* Verification of number of items */
+  if (array_n(array) != Ntk_NetworkReadNumLatches(network)) {
+    error_append("Simulate: All latches must be specified.\n");
+    array_free(array);
+    return(NIL(array_t));
+  }
+  return(array);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Builds an array of nodes corresponding to the name of outputs
+  read in the buffer.]
+
+  Description [Builds an array of nodes corresponding to the name of outputs
+  read in the buffer. If the name does not correspond to any output node in the
+  network, then an error message is written in error_string, and NULL is
+  returned. The number of outputs may be incomplete.]
+  
+  SideEffects []
+
+******************************************************************************/
+static array_t *
+BufferBuildOutputsNodeArray(
+  char * buffer,
+  Ntk_Network_t * network)
+{
+  char       *str;
+  Ntk_Node_t *node;
+  int         position = 0;
+  array_t    *array    = array_alloc(Ntk_Node_t *, 0);
+    
+  while((str = BufferObtainStringAtPosition(buffer, &position)) != NULL) {
+    node = Ntk_NetworkFindNodeByActualName(network, str);
+    if (node == NIL(Ntk_Node_t) || !Ntk_NodeTestIsPrimaryOutput(node)) {
+      SimAppendErrorMsg("Simulate: ", str, " is not a valid output name\n");
+      FREE(str);
+      array_free(array);
+      return(NIL(array_t));
+    }
+    FREE(str);
+    array_insert_last(Ntk_Node_t *, array, node);
+  }
+  return(array);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Builds an array of integers representing the code of strings
+  contained in the buffer.]
+
+  Description [Builds an array of integers representing the code of strings
+  contained in the buffer. The code is 1 or 0, if the value is equal "1" or
+  "0" and the variable is a binary variable. For a symbolic variable it is
+  equal to the index of the value of the variable. The code is equal to the
+  value of a variable if the variable has an enumerative type. If a wrong
+  value is detected, then an error message is written in error_string and NULL
+  is returned. This function verifies also if the number of values is equal to
+  the number of nodes in the nodesArray. If it is not, it returns NULL.]
+  
+  SideEffects []
+
+******************************************************************************/
+static array_t *
+BufferBuildValuesArray(
+  char * buffer,
+  array_t * nodesArray)
+{
+  char       *str;
+  Ntk_Node_t *node;
+  int         index;
+  int         i         = 0;
+  int         arraySize = array_n(nodesArray);
+  int         position  = 0;
+  array_t    *array     = array_alloc(int, 0);
+    
+  while((str = BufferObtainStringAtPosition(buffer, &position)) != NULL) {
+    if (i >= arraySize) {
+      SimAppendErrorMsg("Simulate: Too many values(", str, " invalid value).\n");
+      array_free(array);
+      FREE(str);
+      return(NIL(array_t));
+    }  
+    node = array_fetch(Ntk_Node_t *, nodesArray, i);
+    i++;
+    index = SimNodeReadValueCode(node, str);
+    if (index == -1) {
+      SimAppendErrorMsg("Simulate: ", str, ": invalid value.\n");
+      array_free(array);
+      FREE(str);
+      return(NIL(array_t));
+    }
+
+    FREE(str);
+    array_insert_last(int, array, index);
+  }
+  
+  /* Verification of number of items */
+  if (array_n(array) != array_n(nodesArray)) {
+    error_append("Simulate: incomplete number of values.\n");
+    array_free(array);
+    return(NIL(array_t));
+  }
+  return(array);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Add a vector to the array of vectors of a sim.]
+
+  Description [Add a vector to the array of vectors of a sim. It is an error
+  to call this function with a NULL sim or a sim that does not have a vectors
+  array.]
+  
+  SideEffects []
+
+******************************************************************************/
+static void
+SimAddVector(
+  Sim_Sim_t * sim,
+  array_t * vector)
+{
+  array_insert_last(array_t *, sim->vectorArray, vector);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [skip over white space in a string.]
+
+  Description [skip over white space in a string. set position to the first
+  character different from ' ' and '\t'.]
+  
+  SideEffects []
+
+******************************************************************************/
+static void
+BufferSkipWhiteSpace(
+  char * buffer,
+  int * position)
+{
+  for (; buffer[*position] == ' ' || buffer[*position] == '\t'; (*position)++);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a string read in a buffer at the given position.]
+
+  Description [Returns a string read in a buffer at the given position. The
+  end of string is detected by ' ', '\t', ';' or '\n'. Eliminates the Space in
+  the begining of the buffer. Returns NULL if an empty string has been found
+  before ';' or '\n'.]
+  
+  SideEffects []
+
+******************************************************************************/
+static char *
+BufferObtainStringAtPosition(
+  char * buffer,
+  int * position)
+{
+  char *str;
+  int   strPosition;
+  int   len;
+  
+  /* Traverse Space */
+  BufferSkipWhiteSpace(buffer, position);
+
+  strPosition = *position;
+  for (;buffer[*position] != ' ' && buffer[*position] != '\t' &&
+            buffer[*position] != ';'  && buffer[*position] != '\n'; (*position)++);
+
+  if (strPosition == *position) {
+    return(NIL(char));
+  }
+  len = *position - strPosition + 1;
+  str = ALLOC(char, len);
+  strncpy(str, buffer + strPosition, len - 1);
+  str[len-1] = '\0';
+  return(str);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the value of a particular variable for a given
+  simulation vector.]
+
+  Description [Prints the value of a particular variable for a given
+  simulation vector. The variable is obtained from the node at the
+  vectorIndex position of the nodesArray. The value is obtained from
+  the vectorIndex position of the vector. strSize is used for
+  formatting. If the number of elements in the vector is less than the
+  vectorIndex, a * is printed instead.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+PrintValue(array_t *nodesArray, array_t *vector, int vectorIndex,
+           int strSize, FILE *file)
+{
+  int index;
+  Var_Variable_t *var;
+  char *str;
+  Ntk_Node_t *node;
+  
+  if (array_n(vector) > vectorIndex) {
+    node = array_fetch(Ntk_Node_t *, nodesArray, vectorIndex);
+    var = Ntk_NodeReadVariable(node);
+    index = array_fetch(int, vector, vectorIndex);
+    if (Var_VariableTestIsSymbolic(var)) {
+      SimStringPrint(file, Var_VariableReadSymbolicValueFromIndex(var, index),
+                     strSize);
+    }
+    else { /* Binary or enumerative type */
+      str = SimInteger2ASCII(index);
+      SimStringPrint(file, str, strSize);
+      FREE(str);
+    }
+  }
+  else {
+    error_append("Warning: Value is missing in vector.\n");
+    SimStringPrint(file, "*", strSize);
+  }
+}
Index: vis_dev/vis-2.3/src/sim/simMain.c
===================================================================
--- vis_dev/vis-2.3/src/sim/simMain.c	(revision 14)
+++ vis_dev/vis-2.3/src/sim/simMain.c	(revision 14)
@@ -0,0 +1,1483 @@
+/**CFile***********************************************************************
+
+  FileName    [simMain.c]
+
+  PackageName [sim]
+
+  Synopsis    [simulation of a Network.]
+
+  Description [simulation of a Network. This file contains simulate command and
+  main simulation functions.]
+  
+  Author      [Shaker Sarwary, Tom Shiple and Rajeev Ranjan]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+#include "simInt.h"
+
+static char rcsid[] UNUSED = "$Id: simMain.c,v 1.19 2005/04/23 14:31:51 jinh Exp $";
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandSimulate(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static int EvaluateBinaryFunction(mdd_t * functionMdd, mdd_t * vectorMdd);
+static int NodeLexCmp(const void *node1, const void *node2);
+static mdd_t * StatesMddFromVector(Sim_Sim_t * sim, mdd_manager *mddManager);
+static void GenerateInitState(Sim_Sim_t * sim, boolean random);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the sim package.]
+
+  SideEffects []
+
+  SeeAlso     [Sim_End]
+
+******************************************************************************/
+void
+Sim_Init(void)
+{
+  Cmd_CommandAdd("simulate", CommandSimulate, /* doesn't changes_network */ 0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Ends the sim package.]
+
+  SideEffects []
+
+  SeeAlso     [Sim_Init]
+
+******************************************************************************/
+void
+Sim_End(void)
+{
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates and initializes the SimSimStruct struct.]
+
+  Description [Allocates and initializes the SimSimStruct struct. Internally,
+  sim deals with nodes of a network instead the name(string) of a variable,
+  and with integers representing the value of a variable instead the value as
+  a string. nodeToMvfTable provides MDDs of primary outputs and next-state
+  functions. External function is provided by sim package that builds
+  nodeToMvfTable from network and nodesArray. inputFile is the name of the file
+  containing the simulation vectors. lineNumber is the current line number
+  while parsing inputFile, it is used to print error messages. nodesArray is
+  an array of network nodes of every inputs, current and next state, and
+  partial outputs. Only outputs contained in nodesArray are
+  simulated. currentStateHead, nextStateHead, outputHead are the index of
+  first current state, next state, and output, in nodesArray. initState is an
+  array of values representing initial state according to the current state
+  order in nodesArray. vectorArray is an array of array of values representing
+  vectors to be simulated. if verbose is TRUE, then messages like begin of
+  simulation procedure and printing procedure as well as the cpu-time spent
+  while simulation are directed to vis_stdout.]
+
+  SideEffects []
+
+******************************************************************************/
+Sim_Sim_t *
+Sim_SimCreate(
+  Ntk_Network_t * network,
+  st_table      * nodeToMvfTable,
+  char          * inputFile,
+  int             lineNumber,
+  array_t       * nodesArray,
+  int             currentStateHead,
+  int             internalPartitionHead,
+  int             nextStateHead,
+  int             outputHead,
+  array_t       * initState,
+  array_t       * vectorArray,
+  boolean         verbose)
+{
+  Sim_Sim_t *sim         = ALLOC(Sim_Sim_t, 1);
+  
+  sim->network           = network;
+  sim->nodeToMvfTable    = nodeToMvfTable;
+  sim->inputFile         = inputFile;
+  sim->lineNumber        = lineNumber;
+  sim->nodesArray        = nodesArray;
+  sim->currentStateHead  = currentStateHead;
+  sim->internalPartitionHead  = internalPartitionHead,
+  sim->nextStateHead     = nextStateHead;
+  sim->outputHead        = outputHead;
+  sim->initState         = initState;
+  sim->vectorArray       = vectorArray;
+  sim->verbose           = verbose;
+  
+  return(sim);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Resets the sim structure.]
+
+  Description [Resets the sim structure. Frees the vectors, and makes it equal
+  to NULL. Sets also the initState as the nextState of last vector in
+  vectorArray. sim->vectorArray must be != NULL, and contain valid vectors.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Sim_SimReset(
+  Sim_Sim_t * sim)
+{
+  int       i, value;
+  array_t  *lastVector;
+
+  assert(sim->initState != NIL(array_t));
+  
+  /* Reset initState */
+
+  if (sim->initState != NIL(array_t)) {
+    array_free(sim->initState);
+  }
+  
+  sim->initState = array_alloc(int, 0);
+  lastVector = array_fetch_last(array_t *,sim->vectorArray);
+  for (i = sim->nextStateHead; i < sim->outputHead; i++) {
+    value = array_fetch(int, lastVector, i);
+    array_insert_last(int, sim->initState, value);
+  }
+
+  /* Free vectorArray */
+  for (i = 0; i < array_n(sim->vectorArray); i++) {/* Free Vectors */
+    array_t *vector = array_fetch(array_t *, sim->vectorArray, i);
+    array_free(vector);
+  }
+  array_free(sim->vectorArray);
+  sim->vectorArray = NIL(array_t);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a sim Structure.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Sim_SimFree(
+  Sim_Sim_t * sim)
+{
+  int             i;
+  array_t        *vector;
+  Ntk_Node_t     *node;
+  Mvf_Function_t *mvFunction;
+  st_generator   *stGen;
+
+  if (sim->nodesArray != NULL) {
+    array_free(sim->nodesArray);
+  }
+  if (sim->initState != NIL(array_t)) {
+    array_free(sim->initState);
+  }
+
+  if (sim->vectorArray != NIL(array_t)) {
+    for (i = 0; i < array_n(sim->vectorArray); i++) {
+      vector = array_fetch(array_t *, sim->vectorArray, i);
+      array_free(vector);
+    }
+    array_free(sim->vectorArray);
+  }
+  if(sim->nodeToMvfTable != NIL(st_table)) {
+    st_foreach_item(sim->nodeToMvfTable, stGen, &node, &mvFunction) {
+      Mvf_FunctionFree(mvFunction);
+    }
+  }
+  st_free_table(sim->nodeToMvfTable);
+  FREE(sim);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates and initializes an array of nodes of every input,
+  current-state, next-state, output.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+Sim_NetworkCreateNodesArray(
+  Ntk_Network_t * network,
+  int           * currentStateHead,
+  int           * internalPartitionHead,
+  int           * nextStateHead,
+  int           * outputHead)
+{
+  int            i;
+  lsGen          inputGen;
+  lsGen          latchGen;
+  lsGen          outputGen;  
+  Ntk_Node_t    *node;
+  array_t       *nodesArray = array_alloc(Ntk_Node_t *, 0);
+  graph_t       *partition;
+  vertex_t      *vertex;
+  array_t *dfsarray;
+
+  /* Input Nodes */
+
+  { 
+	array_t *tmpArray= array_alloc(Ntk_Node_t *, 0);
+    Ntk_NetworkForEachInput(network, inputGen, node) {
+	  array_insert_last(Ntk_Node_t *, tmpArray, node);
+	}
+	array_sort(tmpArray, NodeLexCmp);
+	array_append(nodesArray, tmpArray);
+	array_free(tmpArray);
+  }
+  
+  
+  *currentStateHead = array_n(nodesArray);  /* Initialize currentStateHead */
+
+  /* Adding latches */
+  
+  {
+	array_t *tmpArray= array_alloc(Ntk_Node_t *, 0);
+    Ntk_NetworkForEachLatch(network, latchGen, node) {
+  	  array_insert_last(Ntk_Node_t *, tmpArray, node);
+	}
+	array_sort(tmpArray, NodeLexCmp);
+	array_append(nodesArray, tmpArray);
+	array_free(tmpArray);
+  }
+  
+  *internalPartitionHead = array_n(nodesArray);  /* Initialize internalPartitionHead */
+
+  /* Add internal partition nodes */
+
+  partition = Part_NetworkReadPartition(network);
+  dfsarray = g_dfs(partition);
+  for(i=0; i< array_n(dfsarray); i++){
+    vertex = array_fetch(vertex_t *, dfsarray, i);
+    node = Ntk_NetworkFindNodeByName(network, Part_VertexReadName(vertex));
+    if(!(Ntk_NodeTestIsCombInput(node) || Ntk_NodeTestIsCombOutput(node))){
+      array_insert_last(Ntk_Node_t *, nodesArray, node);
+    }
+  }
+  array_free(dfsarray);
+  
+  *nextStateHead = array_n(nodesArray);  /* Initialize nextStateHead */
+
+  /* Add data-input of latches as next state node */
+
+  for (i = *currentStateHead; i < *internalPartitionHead; i++) {
+    node = array_fetch(Ntk_Node_t *, nodesArray, i);
+    node = Ntk_LatchReadDataInput(node);
+    array_insert_last(Ntk_Node_t *, nodesArray, node);
+  }
+  
+  *outputHead = array_n(nodesArray);  /* Initialize outputHead */
+  
+          
+  /* Adding outputs */
+  
+  {
+	array_t *tmpArray= array_alloc(Ntk_Node_t *, 0);
+    Ntk_NetworkForEachPrimaryOutput(network, outputGen, node) {
+      array_insert_last(Ntk_Node_t *, tmpArray, node);
+	}
+	array_sort(tmpArray, NodeLexCmp);
+	array_append(nodesArray, tmpArray);
+	array_free(tmpArray);
+  }
+
+  return(nodesArray);
+}  
+
+/**Function********************************************************************
+
+  Synopsis    [Generates random simulation vectors.]
+
+  Description [Generates numberVector random simulation vectors.
+  sim->vectorArray is re-initialized by this function.  If sim->vectorArray
+  already contains vectors, they will be lost and cause a memory leak.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Sim_SimGenerateRandomVectors(
+  Sim_Sim_t    * sim,
+  int            numberVector,
+  Sim_PseudoSrc  pseudoInputSource)
+{
+  int            i;
+  int            j;
+  array_t       *vector;
+  array_t       *vectorArray = array_alloc(array_t *, 0);
+  array_t       *nodesArray  = sim->nodesArray;
+
+
+  /* Initialization with empty vectors */
+  for (j = 0; j < numberVector; j++) {
+    vector = array_alloc(int, 0);
+    array_insert_last(array_t *, vectorArray, vector);
+  } 
+
+  /* For every input node */
+  for (i = 0; i < sim->currentStateHead; i++) {
+    Ntk_Node_t *node = array_fetch(Ntk_Node_t *, nodesArray, i);
+
+    /* For every vector */
+    for (j = 0; j < numberVector; j++) {
+      int value = SimNodeComputeRandomValue(node, pseudoInputSource);
+      
+      vector = array_fetch(array_t *, vectorArray, j);
+      /* vector is empty => array_insert_last is convenient */
+      array_insert_last(int, vector, value);
+    }
+  }
+
+  sim->vectorArray = vectorArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Generates a random initial state.]
+
+  Description [Generates a random initial state, using the primary and pseudo
+  input values in the first input vector of the sim structure. sim->initState
+  is reset by this function.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+Sim_SimGenerateRandomInitState(
+  Sim_Sim_t * sim)
+{
+  GenerateInitState(sim, TRUE);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Does a simulation on a sim structure.]
+
+  Description [Does a simulation on a sim structure. The sim structure must
+  previously be initialized by valid vectors. If vectors are not valid, bad
+  evaluations should be expected. There are two kinds of invalid vectors :
+  <p>
+  1- The vector is incomplete : f = a+b+c, and vector = not(a) (a = 0)
+  <p>
+  2- The vector is not in the domain of the function : F_red = a.b, F_blue =
+  a.c, vector = not(a).]
+  
+  SideEffects []
+
+******************************************************************************/
+void
+Sim_SimSimulate(
+  Sim_Sim_t * sim)
+{
+  Ntk_Node_t    *node;
+  array_t       *vector;
+  array_t       *partitionVector;
+  int            i, j;
+  int            value;
+  mdd_t         *vectorMdd;
+  int            numberVector = array_n(sim->vectorArray);
+  
+  if(sim->verbose) {
+    (void) fprintf(vis_stdout, "Simulating %d vectors ...\n", numberVector);
+    fflush(vis_stdout);
+  }
+
+  /* Initialization with initState */
+  SimSimInitializeCurrentState(sim);
+
+  /*
+  for (j = sim->internalPartitionHead; j < sim->nextStateHead; j++) {
+    node =  array_fetch(Ntk_Node_t *, sim->nodesArray, j);
+    fprintf(stdout, "%s \t", Ntk_NodeReadName(node));
+  }
+  if(sim->internalPartitionHead < sim->nextStateHead){
+    fprintf(stdout, "\n");
+  }
+  */
+  
+  for (i = 0; i < numberVector; i++) { /* For every vector */
+    if (i > 0) {         /* Put the current-state = last-next-state */
+      SimSimVectorFillCurrentState(sim, i);
+    }
+    else {
+      SimSimInitializeCurrentState(sim);
+    }
+
+    vector = array_fetch(array_t *, sim->vectorArray, i);
+
+    /* partitionVector represents the values of the internal nodes
+       of the partition, induced by the values of the vector array.
+    */
+
+    partitionVector = array_alloc(int, 0);
+    
+    /* simulate internal nodes first. As these internal nodes are 
+       simulated, the vectorMdd is updated to reflect the newly computed
+       values
+    */
+
+    for (j = sim->internalPartitionHead; j < sim->nextStateHead; j++) {
+      vectorMdd = SimSimVectorBuildMdd(sim, vector, partitionVector);
+      node =  array_fetch(Ntk_Node_t *, sim->nodesArray, j);
+      value = Sim_nodeToMvfTableEvaluateNode(sim->nodeToMvfTable, node, vectorMdd);
+      array_insert(int, partitionVector, j - sim->internalPartitionHead, value);
+      mdd_free(vectorMdd);
+    }
+    /*
+    if(sim->internalPartitionHead < sim->nextStateHead){
+      fprintf(stdout, "\n");
+    }
+    */
+    /* simulate the rest of the nodes */
+    vectorMdd = SimSimVectorBuildMdd(sim, vector, partitionVector);
+    array_free(partitionVector);
+
+    for (j = sim->nextStateHead; j < array_n(sim->nodesArray); j++) {
+      node =  array_fetch(Ntk_Node_t *, sim->nodesArray, j);
+      value = Sim_nodeToMvfTableEvaluateNode(sim->nodeToMvfTable, node, vectorMdd);
+      array_insert(int, vector, j, value);
+    }
+
+    mdd_free(vectorMdd);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Evaluates the function of a node on a minterm.]
+
+  Description [Evaluates the function of a node on a minterm. This node must
+  have an entry in nodeToMvfTable. The node may represent a binary or
+  multi-valued function. The result is returned as an integer. If the node
+  represents a binary function, 0 or 1 will be returned.
+  <p>
+  NOTE : WE ASSUME THAT THE FUNCTION IS COMPLETELY SPECIFIED. WE ASSUME ALSO
+  THAT THE VECTOR IS "COMPLETE". AS A CONSEQUENCE, IF THE VECTOR IS NOT IN THE
+  ONSET OF ONE OF THE FIRST n-1 VALUES OF THE FUNCTION, THEN IT IS ASSUMED
+  THAT THE FUNCTION TAKES ITS LAST VALUE ON THIS VECTOR.]
+
+  SideEffects []
+
+  SeeAlso     [Sim_nodeToMvfTableEvaluateNodesArray]
+
+******************************************************************************/
+int
+Sim_nodeToMvfTableEvaluateNode(
+  st_table   * nodeToMvfTable,
+  Ntk_Node_t * node,
+  mdd_t      * vectorMdd)
+{
+  int             i;
+  Mvf_Function_t *mvFunction = NIL(Mvf_Function_t);
+
+  (void) st_lookup(nodeToMvfTable, (char *) node,  &mvFunction);
+
+  /*
+   * For a binary function the array contains 2 MDDs for off-set and
+   * on-set, with the indices 0 or 1.
+   */
+
+  for (i = 0; i < Mvf_FunctionReadNumComponents(mvFunction) - 1; i++) {
+    if (EvaluateBinaryFunction(Mvf_FunctionReadComponent(mvFunction, i),
+                               vectorMdd) == 1) {
+      return(i);
+    }
+  }
+  /* Return last value without evaluation */
+  return(i);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Evaluates every node of an array on a minterm.]
+
+  Description [Evaluates every node of an array on a minterm. The input values
+  are given by an MDD. Nodes, to be evaluated, must have an entry in
+  nodeToMvfTable. The nodes may represent a binary or multi-valued
+  function. The result is returned as an array of integers. If a node
+  represents a binary function, the integer is equal to either 0 or 1.
+  <p>
+  NOTE : WE ASSUME THAT THE FUNCTION IS COMPLETELY SPECIFIED. WE ASSUME ALSO
+  THAT THE VECTOR IS "COMPLETE". AS A CONSEQUENCE, IF THE VECTOR IS NOT IN THE
+  ONSET OF ONE OF THE FIRST n-1 VALUES OF THE FUNCTION, THEN IT IS ASSUMED
+  THAT THE FUNCTION TAKES ITS LAST VALUE ON THIS VECTOR.]
+
+  SideEffects []
+
+  SeeAlso     [Sim_nodeToMvfTableEvaluateNode]
+
+******************************************************************************/
+array_t *
+Sim_nodeToMvfTableEvaluateNodesArray(
+  st_table  * nodeToMvfTable,
+  array_t   * nodesArray,
+  mdd_t     * vectorMdd)
+{
+  int          i, value;
+  Ntk_Node_t  *node;
+  array_t     *resultArray = array_alloc(int, 0);
+
+  for (i = 0; i < array_n(nodesArray); i++) {
+    node  = array_fetch(Ntk_Node_t *, nodesArray, i);
+    value = Sim_nodeToMvfTableEvaluateNode(nodeToMvfTable, node, vectorMdd);
+    array_insert(int, resultArray, i, value);
+  }
+  return(resultArray);
+}
+  
+/**Function********************************************************************
+
+  Synopsis [Generates random vectors, performs simulation.]
+
+  Devscription [Generates num random vectors, performs
+  simulation. These vectors form only one thread of
+  simulation. Returns an mdd_t of simulated states.]
+  
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+Sim_RandomSimulate(
+  Ntk_Network_t * network,
+  int             num,
+  boolean         verbose)
+{
+  int        numRemainingVector;
+  st_table  *nodeToMvfTable;
+  Sim_Sim_t *sim;
+  int        currentStateHead    = 0;
+  int        internalPartitionHead    = 0;
+  int        nextStateHead       = 0;  
+  int        outputHead          = 0;
+  int firstTime = 1;
+  mdd_t *states, *simStates;
+  mdd_manager *mddManager = Ntk_NetworkReadMddManager(network);
+  Sim_PseudoSrc pseudoInputSource = Sim_Random_c;
+  array_t   *nodesArray          = Sim_NetworkCreateNodesArray(network,
+                                             &currentStateHead, &internalPartitionHead, 
+                                             &nextStateHead, &outputHead); 
+
+  /* Building nodeToMvfTable */
+  nodeToMvfTable = Sim_NetworkBuildNodeToMvfTable(network, nodesArray,
+						  internalPartitionHead,
+                                                  nextStateHead);
+    
+  sim = Sim_SimCreate(network, nodeToMvfTable, NULL, 0, nodesArray,
+                      currentStateHead, internalPartitionHead, nextStateHead, outputHead, 
+		      NULL, NULL, verbose);
+
+  /* If partition method was partial/boundary, and -i was used, then dont simulate*/
+  if(SimTestPartInTermsOfCI(sim)){
+    fprintf(stdout, "The partition contains internal nodes, and all partition functions are \n");
+    fprintf(stdout, "in terms of combinational inputs - quitting. Re-create the partition \n");
+    fprintf(stdout, "without the -i option and then re-run simulatate.\n");
+    Sim_SimFree(sim);
+    return(0);
+  }
+  
+  /* Simulation by packet */  
+  simStates = mdd_zero(mddManager);
+  numRemainingVector = num;
+  do {
+    mdd_t *tmp;
+    /* Number of vectors to be simulated in current pass. */
+    num = (numRemainingVector > SIMPACKET_SIZE)
+        ? SIMPACKET_SIZE
+        :  numRemainingVector;
+
+    Sim_SimGenerateRandomVectors(sim, num, pseudoInputSource);
+
+    /*
+     * Random init state generation. This must follow generation of input
+     * vectors, because init state depends on inputs.
+     */
+    if (firstTime) {
+      GenerateInitState(sim, FALSE);
+    }
+    
+    /* SIMULATION */
+    Sim_SimSimulate(sim);
+    
+    /* Print simulation vectors. On first pass, file must be created. */
+    states = StatesMddFromVector(sim, mddManager);
+    tmp = mdd_or(states, simStates, 1, 1);
+    mdd_free(states);
+    mdd_free(simStates);
+    simStates = tmp;
+    firstTime = 0;
+    
+    /* Reset Vectors */
+    Sim_SimReset(sim);
+
+    numRemainingVector -= num;
+  } while(numRemainingVector > 0);
+
+  Sim_SimFree(sim);
+  return(simStates);
+} /* end of Sim_RandomSimulate */
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the current state of the first vector in vectorArray using
+  initState.]
+
+  Description [Sets the current state of the first vector in vectorArray using
+  initState. vectorArray must contain already the inputs value(AND only the
+  inputs value). It is an error to call this function with a sim structure
+  that contains a wrong vectorArray or a wrong initState.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+SimSimInitializeCurrentState(
+  Sim_Sim_t * sim)
+{
+  int       i, value;
+  
+  /* Get the first vector from vectorArray */
+  array_t  *vector = array_fetch(array_t *, sim->vectorArray, 0);
+  
+  for (i = 0; i < array_n(sim->initState); i++) {
+    value = array_fetch(int, sim->initState, i);
+    array_insert_last(int, vector, value);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis [Generates random vectors, performs simulation, and prints the
+  result.]
+
+  Devscription [Generates num random vectors, performs simulation, and prints
+  the result. Returns 1 if function ends normally, else returns 0. If
+  statesPrint is 1, then current and next state are also printed, else it is
+  not. See Sim_SimInitialize for further information about arguments.]
+  
+  SideEffects []
+
+******************************************************************************/
+boolean
+SimRandomSimulateAndPrint(
+  Ntk_Network_t * network,
+  int             num,
+  char          * outputFile,
+  Sim_PseudoSrc   pseudoInputSource,
+  int             printInputsFlag,
+  int             printOutputsFlag,
+  int             printPseudoInputsFlag,
+  int             printStatesFlag,
+  boolean         verbose)
+{
+  int        numRemainingVector;
+  FILE      *outFile;
+  st_table  *nodeToMvfTable;
+  Sim_Sim_t *sim;
+  int        firstTime           = 1;
+  int        currentStateHead    = 0;
+  int        internalPartitionHead    = 0;
+  int        nextStateHead       = 0;  
+  int        outputHead          = 0;  
+  array_t   *nodesArray          = Sim_NetworkCreateNodesArray(network,
+                                             &currentStateHead, &internalPartitionHead, 
+                                             &nextStateHead, &outputHead); 
+
+  /* Building nodeToMvfTable */
+  nodeToMvfTable = Sim_NetworkBuildNodeToMvfTable(network, nodesArray,
+						  internalPartitionHead,
+                                                  nextStateHead);
+    
+  sim = Sim_SimCreate(network, nodeToMvfTable, NULL, 0, nodesArray,
+                      currentStateHead, internalPartitionHead, nextStateHead, outputHead, 
+		      NULL, NULL, verbose);
+
+  /* If partition method was partial/boundary, and -i was used, then dont simulate*/
+  if(SimTestPartInTermsOfCI(sim)){
+    fprintf(stdout, "The partition contains internal nodes, and all partition functions are \n");
+    fprintf(stdout, "in terms of combinational inputs - quitting. Re-create the partition \n");
+    fprintf(stdout, "without the -i option and then re-run simulatate.\n");
+    Sim_SimFree(sim);
+    return(0);
+  }
+  
+  if (outputFile == NIL(char)) {
+    outFile = vis_stdout;
+  }
+  else {
+    outFile = Cmd_FileOpen(outputFile, "w", NIL(char *), 0);
+    if (outFile == NIL(FILE)){
+      return(0);
+    }
+  }
+
+  /* Simulation by packet */  
+  numRemainingVector = num;
+  do {
+
+    /* Number of vectors to be simulated in current pass. */
+    num = (numRemainingVector > SIMPACKET_SIZE)
+        ? SIMPACKET_SIZE
+        :  numRemainingVector;
+
+    Sim_SimGenerateRandomVectors(sim, num, pseudoInputSource);
+
+    /*
+     * Random init state generation. This must follow generation of input
+     * vectors, because init state depends on inputs.
+     */
+    if (firstTime) {
+      Sim_SimGenerateRandomInitState(sim);
+    }
+    
+    /* SIMULATION */
+    Sim_SimSimulate(sim);
+    
+    /* Print simulation vectors. On first pass, file must be created. */
+    Sim_SimPrint(sim, outFile, firstTime, printInputsFlag,
+                 printOutputsFlag, printPseudoInputsFlag,
+                 printStatesFlag);
+    firstTime = 0;
+
+    /* Reset Vectors */
+    Sim_SimReset(sim);
+
+    numRemainingVector -= num;
+  } while(numRemainingVector > 0);
+
+  if (outputFile != NIL(char)) {
+    fclose(outFile);
+  }
+  Sim_SimFree(sim);
+  return(1);
+}
+
+/**Function********************************************************************
+  
+  Synopsis    [Parses the simulation vectors file, builds a SimSimStruct,
+  simulate and prints the result into the output file.]
+
+  Description [Parses the simulation vectors file, builds a SimSimStruct,
+  simulate and prints the result into the output file. The header of a
+  simulation-vectors file contains .inputs, .pseudo-inputs, .latches,
+  .outputs, and .initial fields and ends with .start_vectors. If a variable is
+  found for which there doesn't exist a corresponding node in the network, or
+  a value is found that does not belong to the domain of its specific
+  variable, then an error message is writen in error_string, the partial
+  simStruct is freed, and the function returns 0. The simulation file must
+  contain each category of declaration in a line(Two ".inputs" is not allowed
+  in the same file). initial-state declaration must be writen after the
+  latches declaration. Vectors are simulated by "packet": When SIMPACKET_SIZE
+  vectors are read, they are simulated and the result is printed. Only "num"
+  vectors are read and simulated(even if the number of vectors in the file is
+  greater than this number). If num is 0, then all vectors in the file are
+  simulated. The function returns 1 if it ends normally, else returns 0.]
+  
+  SideEffects []
+
+******************************************************************************/
+boolean
+SimFileSimulateAndPrint(
+  Ntk_Network_t * network,
+  int             num,
+  char          * inputFile,
+  char          * outputFile,
+  Sim_PseudoSrc   pseudoInputSource,
+  int             printInputsFlag,
+  int             printOutputsFlag,
+  int             printPseudoInputsFlag,
+  int             printStatesFlag,
+  boolean         verbose)
+{
+  int        numRemainingVector, packet;
+  int        ioStatus;
+  FILE      *outFile;
+  int        printFlag  = 1;
+  FILE      *inFile     = Cmd_FileOpen(inputFile, "r", NIL(char *), 0);
+  Sim_Sim_t *sim        = Sim_FileParseDeclaration(network, inFile, inputFile, verbose);
+
+  if (sim == NIL(Sim_Sim_t)) {
+    return(0);
+  }
+
+  /* If partition method was partial/boundary, and -i was used, then dont simulate*/
+  if(SimTestPartInTermsOfCI(sim)){
+    fprintf(stdout, "The partition contains internal nodes, and all partition functions are \n");
+    fprintf(stdout, "in terms of combinational inputs - quitting. Re-create the partition \n");
+    fprintf(stdout, "without the -i option and then re-run simulatate.\n");
+    Sim_SimFree(sim);
+    return(0);
+  }
+
+  if (outputFile == NIL(char)) {
+    outFile    = vis_stdout;
+  }
+  else {
+    outFile    = Cmd_FileOpen(outputFile, "w", NIL(char *), 0);
+    if (outFile == NIL(FILE)){
+      return(0);
+    }
+  }
+  
+  /* Simulation by packet */  
+  numRemainingVector = num;
+  do {
+
+    /********** Number of vectors to be simulated in current pass **********/
+    /* num == 0 => simulate all vectors of the file => packet = SIMPACKET_SIZE */
+    if (numRemainingVector > SIMPACKET_SIZE || num == 0) {
+      packet = SIMPACKET_SIZE;
+    }
+    else {
+      packet = numRemainingVector;
+    }
+
+    ioStatus = Sim_FileParseVectors(inFile, sim, numRemainingVector);
+    if (ioStatus == 0) { /* Error case */
+      Sim_SimFree(sim);
+      fclose(inFile);
+      if (outputFile != NIL(char)) {
+        fclose(outFile);
+      }
+      return(0);
+    }
+      
+
+    /*************************** SIMULATION  ****************************/
+
+    Sim_SimSimulate(sim);
+    
+    /******************* Print Simulation Vectors **********************/
+
+    Sim_SimPrint(sim, outFile, printFlag, printInputsFlag,
+                 printOutputsFlag, printPseudoInputsFlag,
+                 printStatesFlag);
+    printFlag = 0;
+
+    Sim_SimReset(sim);
+    numRemainingVector -= packet;
+  } while(ioStatus != 2 && (num == 0 || numRemainingVector > 0));
+
+  Sim_SimFree(sim);
+  fclose(inFile);
+  if (outputFile != NIL(char)) {
+    fclose(outFile);
+  }
+  return(1);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [implement the simulate command.]
+
+  CommandName [simulate]
+
+  CommandSynopsis [simulate the flattened network]
+
+  CommandArguments [\[ -I &lt;0/1&gt; \] \[ -O &lt;0/1&gt; \] \[ -P
+  &lt;0/1&gt; \] \[ -S &lt;0/1&gt; \] \[ -h \]  \[ -i &lt;vectors_file&gt; \] \[ -n &lt;vectors_number&gt; \] \[ -o
+  &lt;output_file&gt; \] \[ -p &lt;0|1&gt; \]
+  \[ -v \]]
+
+  CommandDescription [Simulates a network with a set of input
+  vectors. Before calling this command, the user should create a partition
+  (using the command <tt>build_partition_mdds</tt>). The simulation
+  vectors can be provided by  the user (using -i vectors_file), or
+  generated randomly. <p>
+
+  Command options:<p>
+
+  <dl>
+  <dt>-I &lt;0/1&gt;
+
+  <dd>This option controls the printing the
+  primary input variables. 0 implies printing is disabled, enabled
+  otherwise. The default value is 1. The output file generated with
+  this flag set to 0 may not be used as input file for simulation (if
+  there are some primary inputs to the system).
+
+  <dt>-O &lt;0/1&gt;
+
+  <dd>This option controls the printing the
+  primary output variables. 0 implies printing is disabled, enabled
+  otherwise. The default value is 1.
+
+  <dt>-P &lt;0/1&gt;
+  <dd> This option controls the printing the
+  pseudo input variables. 0 implies printing is disabled, enabled
+  otherwise. The default value is 1. The output file generated with
+  this flag set to 0 may not be used as input file for simulation (if
+  there are some pseudo-inputs to the system).
+
+
+  <dt>-S &lt;0/1&gt;
+  <dd> This option controls the printing the
+  state variables. 0 implies printing is disabled, enabled
+  otherwise. The default value is 1.
+
+  <dt>-h
+  <dd>Print a help message that details all options.
+
+
+  <dt> -i &lt;vectors_file&gt;
+  <dd>Give the simulation vector file name. If this option
+  is not used, vectors are generated randomly.
+
+  <dt>-n &lt;N&gt;
+  <dd> Simulate N vectors. This option should be used if vectors_file
+  is not specified. If a vectors_file is given, and if there are more than N
+  vectors in the file, only the first N vectors are simulated.
+
+  <dt>-o &lt;output_file&gt;
+  <dd> Give the name of a file where the simulation result
+  should be written. If this option is not used, the simulation result is
+  directed to standard output.
+
+  <dt>-p &lt;0|1|2&gt;
+  <dd> This option is available only with random vector
+  generation mode, and affects how values for pseudo-inputs (non-deterministic
+  constants) are generated.
+
+  0: pseudo-inputs are treated by user.
+  
+  1: pseudo-inputs are treated randomly.
+
+  2: pseudo-inputs are treated by choosing the first possibility.
+
+  <dt>-v
+  <dd>  Enable verbose mode. Prints CPU time usage.
+  </dl>
+
+  The vectors_file  has two main parts:
+  <dl>
+  <dt>Declarations:
+  <dd>
+
+  <dl>
+  <dt>Inputs list:
+  <dd> Gives an ordering of the primary and pseudo
+  inputs. Every input must be reported in this field.
+
+  <dt>Latches list:
+  <dd> Gives an ordering of the latches. Every latch must
+  be reported in this field.
+
+  <dt>Outputs list:
+  <dd> Gives an ordering of the outputs. This list may be
+  incomplete. Simulation is performed only on outputs present in this list.
+  
+  <dt>Initial state:
+  <dd> Value of an initial state. This value is given
+  with respect to the latch ordering.
+
+  </dl>
+
+  <dt>Simulation Vectors:
+  <dd>One vector per line according to the given
+  order of inputs.
+
+  <dt>Final State:
+  <dd>Prints the value of state variables after the last simulation
+  vector is applied.
+  </dl>
+
+  An example of a simulation vectors file is:
+
+  <ul>
+
+  # ----> Declarations<p>
+  .inputs   X1  X2 <br>
+  .latches  L1  L2 <br>
+  .outputs  O <br>
+  .initial green  0 <br>
+  .start_vectors <br>
+  # ----> Vectors <br>
+  0  1 <br>
+  1  0 <br>
+  1  1 <br>
+
+  </ul>
+
+  Note the keywords: .inputs, .latches, .outputs, .initial, .start_vectors. A
+  line started by a '#' is a comment line.<p> The simulation result is printed
+  either in a file (using -o output_file) or to standard output. It has
+  the same format as vectors_file with additional fields for latches and
+  outputs. Here is the result of simulation on last vectors_file example:
+
+  <ul>
+
+  .inputs   X1  X2 <br>
+  .latches  L1  L2 <br>
+  .outputs  O <br>
+  .initial green  0 <br>
+  .start_vectors <br>
+  #input;  current_state;  output <br>
+  0 1   ;  green  0     ;  0 <br>
+  1 0   ;  blue   0     ;  1 <br>
+  1 1   ;  red    1     ;  1 <br>
+  #Final State : green 1
+  </ul>
+
+  Note that each input line has been extended by its simulation result with
+  current states and outputs listed in order.
+  The output_file can be read by simulate as vectors_file (latches and
+  outputs values are ignored). When starting simulation a good trick
+  is to run simulate with random vectors generation mode; the resulting
+  can be used as a template to write a vectors_file. For example, executing "simulate -n 1
+  -o foo.output" will generate a representative file.<p>]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandSimulate(
+  Hrc_Manager_t ** hmgr,
+  int              argc,
+  char          ** argv)
+{
+  int            c;
+  unsigned int   i;
+  long           startTime        = 0;
+  long           endTime          = 0;
+  long           cpuTime          = 0;
+  int            numberVector      = 0;
+  FILE          *inputFp           = NIL(FILE);
+  Sim_PseudoSrc  pseudoInputSource = Sim_Undef_c;          /* default */
+  boolean        verbose           = FALSE;                /* default */
+  char          *inputFile         = NIL(char);
+  char          *outputFile        = NIL(char);
+  Ntk_Network_t *network           = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
+  int printInputsFlag = 1; /*default*/
+  int printOutputsFlag = 1;/*default*/
+  int printPseudoInputsFlag = 1;/*default*/
+  int printStatesFlag = 1;/*default*/
+  
+  /*
+   * Parse command line options.
+   */
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "I:O:P:S:hvi:o:n:p:s")) != EOF) {
+    switch(c) {
+      case 'I':
+        printInputsFlag = atoi(util_optarg);
+        break;
+      case 'O':
+        printOutputsFlag = atoi(util_optarg);
+        break;
+      case 'P':
+        printPseudoInputsFlag = atoi(util_optarg);
+        break;
+      case 'S':
+        printStatesFlag = atoi(util_optarg);
+        break;
+      case 'h':
+        goto usage;
+      case 'i':
+        inputFile = util_optarg;
+        break;
+      case 'n':
+        for (i = 0; i < strlen(util_optarg); i++) {
+          if (!isdigit((int)util_optarg[i])) {
+            goto usage;
+          }
+        }
+        numberVector = atoi(util_optarg);
+        break;
+      case 'o':
+        outputFile = util_optarg;        
+        break;
+      case 'p':
+        if (!strcmp("0", util_optarg)) {
+          pseudoInputSource = Sim_User_c;
+        }
+        else if (!strcmp("1", util_optarg)) {
+          pseudoInputSource = Sim_Random_c;
+        }
+        else if (!strcmp("2", util_optarg)) {
+          pseudoInputSource = Sim_First_c;
+        }
+        else {
+          goto usage;
+        }
+        break;
+      case 'v':
+        verbose = 1;
+        break;
+      default:
+        goto usage;
+    }
+  }
+
+  if (network == NIL(Ntk_Network_t)) {
+    return 1;
+  }
+
+  if (Ord_NetworkTestAreVariablesOrdered(network,Ord_InputAndLatch_c) == FALSE){
+    (void) fprintf(vis_stdout, "The MDD variables have not been ordered. Use static_order.\n");
+    return 1;
+  }
+
+  if (Part_NetworkReadPartition(network) == NIL(graph_t)) {
+    (void) fprintf(vis_stderr, "Network has not been partitioned. Use build_partition_mdds.\n");
+    return 1;
+  }
+  
+  /** Initialization for random values generation **/
+  util_srandom(SimComputeRandomInteger());
+
+  /* Parameters verification */
+
+  if (numberVector <= 0 && inputFile == NIL(char)) {
+    (void) fprintf(vis_stderr, "Simulate: specify an input file with -i or use -n option to set\n");
+    (void) fprintf(vis_stderr, "the number of vectors randomly generated\n");
+    return(1);
+  }
+  if (pseudoInputSource == Sim_User_c && inputFile == NIL(char)) {
+    (void) fprintf(vis_stderr, "Simulate: '-p 0' option and random vectors\n");
+    (void) fprintf(vis_stderr, "           generation are incompatible\n");
+    return(1);
+  }
+  if ((pseudoInputSource != Sim_Undef_c) && inputFile != NIL(char)) {
+    (void) fprintf(vis_stderr, "Simulate: '-p' option is available only if vectors\n");
+    (void) fprintf(vis_stderr, "           are generated randomly.\n");
+    return(1);
+  }
+
+  if (numberVector == 0 && inputFile == NIL(char)) {
+    (void) fprintf(vis_stderr, "Simulate: number of vectors not specified.\nUsing 10 random vectors\n");
+    numberVector = 10;
+  }
+  if (inputFile != NIL(char)) {
+    inputFp = Cmd_FileOpen(inputFile, "r", NIL(char *), 0);
+    if (inputFp == NIL(FILE)) {
+      return (1);
+    }
+  }
+
+  /* CPU-Time print with verbose option */
+  if (verbose) {
+    startTime = util_cpu_time();
+  }
+
+  
+  /************** Random Vectors generation **************/
+  error_init();
+
+  if (inputFile == NIL(char)) {
+    if (SimRandomSimulateAndPrint(network, numberVector, outputFile,
+                                  pseudoInputSource, printInputsFlag,
+                                  printOutputsFlag,
+                                  printPseudoInputsFlag, 
+                                  printStatesFlag,
+                                  verbose) == 0) {
+      (void) fprintf(vis_stdout, "%s", error_string());      
+      return (1);
+    }
+  }
+  
+/************* Read vectors from a file ***************/
+  
+  else {
+    if (SimFileSimulateAndPrint(network, numberVector, inputFile, outputFile,
+                                pseudoInputSource, printInputsFlag,
+                                printOutputsFlag, printPseudoInputsFlag,
+                                printStatesFlag, verbose) == 0) {
+      (void) fprintf(vis_stdout, "%s", error_string());      
+      return(1);
+    }
+  }
+  
+  if (verbose) {
+    endTime = util_cpu_time();
+    cpuTime = endTime - startTime;    
+    (void) fprintf(vis_stdout, "====> Simulation time: %d ms\n", (int)cpuTime);
+  }
+
+  return 0;		/* normal exit */
+
+  usage:
+  (void) fprintf(vis_stderr, "usage: simulate [-I <0/1>][-O <0/1>][-P <0/1>][-S <0/1>][-h][-i vectors_file]\n");
+  (void) fprintf(vis_stderr, "                [-n number-vectors][-o output_file][-p <0/1/2>] [-v]\n");
+
+  (void) fprintf(vis_stderr, "    -I <0/1>\t\tControls printing of primary input variables\n");
+  (void) fprintf(vis_stderr, "            \t\t(0:no print, 1:print, default is 1)\n");
+  (void) fprintf(vis_stderr, "    -O <0/1>\t\tControls printing of output variables\n");
+  (void) fprintf(vis_stderr, "            \t\t(0:no print, 1:print, default is 1)\n");
+  (void) fprintf(vis_stderr, "    -P <0/1>\t\tControls printing of pseudo input variables\n");
+  (void) fprintf(vis_stderr, "            \t\t(0:no print, 1:print, default is 1)\n");
+  (void) fprintf(vis_stderr, "    -S <0/1>\t\tControls printing of state variables\n");
+  (void) fprintf(vis_stderr, "            \t\t(0:no print, 1:print, default is 1)\n");
+  (void) fprintf(vis_stderr, "    -h \tPrints this usage message.\n");
+  (void) fprintf(vis_stderr, "    -i <vectors_file>\tThe input file containing simulation vectors.\n");
+  (void) fprintf(vis_stderr, "                   \tIf not specified, N vectors are generated randomly.\n");
+  (void) fprintf(vis_stderr, "                   \tN is given by the option '-n'.\n");
+  (void) fprintf(vis_stderr, "    -n <N>\t\tWith this option, only the first N vectors\n");
+  (void) fprintf(vis_stderr, "          \t\twill be simulated. If '-i' option is not used,\n");
+  (void) fprintf(vis_stderr, "           \t\tN is the number of random vectors.\n");
+  (void) fprintf(vis_stderr, "    -o <output_file>\tThe output file. If not specified, the output\n");
+  (void) fprintf(vis_stderr, "                    \twill be directed to stdout.\n");
+  (void) fprintf(vis_stderr, "    -p <0|1|2>\t\tIf 0 : non-deterministic cases are treated\n");
+  (void) fprintf(vis_stderr, "              \t\tas specified by user.\n");
+  (void) fprintf(vis_stderr, "              \t\tIf 1: non-deterministic cases are treated randomly.\n");
+  (void) fprintf(vis_stderr, "              \t\tIf 2: non-deterministic cases are treated by\n");
+  (void) fprintf(vis_stderr, "              \t\tchoosing the first possibility.\n");
+  (void) fprintf(vis_stderr, "    -v \tVerbose. Print CPU time usage.\n");
+
+  return 1;		/* error exit */
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Evaluates a binary-valued function.]
+
+  Description [Evaluates a binary-valued function on a vector given by its MDD
+  representation. Returns 1 (0) if the result of the evaluation is equal to
+  one (zero), otherwise returns -1.]
+
+  SideEffects []
+
+  SeeAlso     [Sim_nodeToMvfTableEvaluateNode]
+
+******************************************************************************/
+static int
+EvaluateBinaryFunction(
+  mdd_t * functionMdd,
+  mdd_t * vectorMdd)
+{
+  mdd_t       * result = mdd_cofactor_minterm(functionMdd, vectorMdd);
+
+  if (mdd_is_tautology(result, 1)) {
+    mdd_free(result);
+    return (1);
+  }
+  else if (mdd_is_tautology(result, 0)) {
+    mdd_free(result);
+    return (0);
+  }
+  else {
+    mdd_free(result);
+    return (-1);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compare two nodes based on the lexigraphic order of their names.]
+
+  SeeAlso     []
+
+  SideEffects     []
+
+******************************************************************************/
+static int
+NodeLexCmp(
+  const void *node1,
+  const void *node2)
+{
+  char *name1 = Ntk_NodeReadName(*(Ntk_Node_t **)node1);
+  char *name2 = Ntk_NodeReadName(*(Ntk_Node_t **)node2);
+
+  return strcmp(name1, name2);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Builds an mdd of simulated states from the array of values.]
+
+  Description [Builds an mdd of simulated states from the array of values in the sim structure.]
+
+  SideEffects []
+
+******************************************************************************/
+static mdd_t *
+StatesMddFromVector(
+  Sim_Sim_t       * sim,
+  mdd_manager *mddManager
+  )
+
+{
+  int             i, j;
+  array_t        *vector;
+  Ntk_Node_t     *node;
+  mdd_t *state, *simStates, *tmp, *mddLiteral;
+  int value;
+  array_t *valueArray;
+  int mddId;
+
+  /* start with zero */
+  simStates = mdd_zero(mddManager);
+  valueArray = array_alloc(int, 1);
+  for (i = 0; i < array_n(sim->vectorArray); i++) {
+      /* add every state in the vector */
+    vector = array_fetch(array_t *, sim->vectorArray, i);
+    state = mdd_one(mddManager);
+    for (j = sim->currentStateHead; j < sim->internalPartitionHead; j++){
+      /* Build the state */
+      node = array_fetch(Ntk_Node_t *, sim->nodesArray, j);
+      mddId = Ntk_NodeReadMddId(node);
+      value = array_fetch(int, vector, j);
+      array_insert(int, valueArray, 0, value);
+      mddLiteral = mdd_literal(mddManager, mddId, valueArray);
+      
+      tmp = mdd_and(state, mddLiteral, 1, 1);
+      mdd_free(state);
+      mdd_free(mddLiteral);
+      state = tmp;
+    }
+
+    tmp = mdd_or(simStates, state, 1, 1);
+    mdd_free(simStates);
+    mdd_free(state);
+    simStates = tmp;
+
+  }
+  array_free(valueArray);
+  return simStates;
+} /* end of StatesMddFromVector */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Generates the initial state.]
+
+  Description [Generates the initial state, input values in the first
+  input vector of the sim structure. sim->initState is reset by this
+  function.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+GenerateInitState(
+  Sim_Sim_t * sim, boolean random)
+{
+  int            i;
+  array_t       *mvfArray;
+  array_t       *initState   = array_alloc(int, 0);
+  array_t       *nodesArray  = sim->nodesArray;
+  array_t       *vectorArray = sim->vectorArray;
+  array_t       *firstVector = array_fetch(array_t *, vectorArray, 0);
+  st_table      *leaves      = st_init_table(st_ptrcmp, st_ptrhash);
+  int            numLatches  = sim->internalPartitionHead - sim->currentStateHead;
+  array_t       *rootArray   = array_alloc(Ntk_Node_t *, numLatches);
+  
+  /* Free old initState */
+  if (sim->initState != NIL(array_t)) {
+    array_free(sim->initState);
+  }
+  sim->initState = initState;
+
+  /*
+   * Load a symbol table with the initial values of the primary and pseudo
+   * inputs.
+   */
+  for (i = 0; i < sim->currentStateHead; i++) {
+    Ntk_Node_t *node  = array_fetch(Ntk_Node_t *, nodesArray, i);
+    if (random) {
+      int         value = array_fetch(int, firstVector, i); 
+      st_insert(leaves, (char *) node, (char *) (long) value);
+    } else {
+      st_insert(leaves, (char *) node, (char *) (long) NTM_UNUSED);
+    }
+  }
+  
+  /*
+   * Create an array containing the initialization function for all the
+   * latches. This array has the same order as the simulation vector.
+   */
+  for (i = sim->currentStateHead; i < sim->internalPartitionHead; i++) {
+    Ntk_Node_t     *latch      = array_fetch(Ntk_Node_t *, nodesArray, i);
+    Ntk_Node_t     *initNode   = Ntk_LatchReadInitialInput(latch);
+    
+    array_insert_last(Ntk_Node_t *, rootArray, initNode);
+  }
+
+  /*
+   * Build the MVFs for the initialization functions, using the initial input
+   * values.
+   */
+  mvfArray = Ntm_NetworkBuildMvfs(sim->network, rootArray, leaves, NIL(mdd_t));
+  array_free(rootArray);
+  st_free_table(leaves);
+
+  /*
+   * Get the initial value of each latch from the MVF of the corresponding
+   * initialization function.  Since the initialization functions are in terms
+   * of primary and pseudo input values, and we have completely specified
+   * values for all inputs, each initialization function should have evaluated
+   * to a constant (i.e. exactly one non-zero component, and that component is
+   * the tautology.
+   */
+  for (i = 0; i < numLatches; i++) {
+    int             j;
+    int             value = 0;  /* initialized to avoid lint complaint */
+    Mvf_Function_t *initMvf;
+    mdd_t          *component;
+    int             numNonZero = 0;
+    
+    initMvf = array_fetch(Mvf_Function_t *, mvfArray, i);
+    Mvf_FunctionForEachComponent(initMvf, j, component) { 
+      if (!mdd_is_tautology(component, 0)) {
+        assert(mdd_is_tautology(component, 1));
+        numNonZero++;
+        value = j;
+      }
+    }
+
+    assert(numNonZero == 1);
+    array_insert_last(int, initState, value);
+  }
+
+  Mvf_FunctionArrayFree(mvfArray);
+  return;
+} /* end of GenerateInitState */
+
Index: vis_dev/vis-2.3/src/sim/simSim.c
===================================================================
--- vis_dev/vis-2.3/src/sim/simSim.c	(revision 14)
+++ vis_dev/vis-2.3/src/sim/simSim.c	(revision 14)
@@ -0,0 +1,271 @@
+/**CFile***********************************************************************
+
+  FileName    [simSim.c]
+
+  PackageName [sim]
+
+  Synopsis    [Routines to manipulate simstructure.]
+
+  Author      [Shaker Sarwary and Tom Shiple]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+#include "simInt.h"
+
+static char rcsid[] UNUSED = "$Id: simSim.c,v 1.2 1997/02/12 23:03:57 hsv Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the network pointed by the sim structure.]
+
+  Description [Returns the network pointed by the sim structure. It is an
+  error to call this function with a NULL or a wrong sim structure. The user
+  should not free the returned network.]
+
+  SideEffects []
+
+******************************************************************************/
+Ntk_Network_t *
+Sim_SimReadNetwork(
+  Sim_Sim_t * sim)
+{
+  return (sim->network);
+}
+/**Function********************************************************************
+
+  Synopsis    [Returns nodeToMvfTable of the sim structure.]
+
+  Description [Returns nodeToMvfTable of the sim structure. It is an error to
+  call this function with a NULL or wrong sim structure. The user should not
+  change or free the returned structure.]
+
+  SideEffects []
+
+******************************************************************************/
+st_table *
+Sim_SimReadNodeToMvfTable(
+  Sim_Sim_t * sim)
+{
+  return (sim->nodeToMvfTable);
+}
+/**Function********************************************************************
+
+  Synopsis    [Returns the name of the input file of a sim.]
+
+  Description [Returns the name of the input file of a sim. It is an error to
+  call this function with a NULL or wrong sim structure. The user should not free
+  the returned string.]
+
+  SideEffects []
+
+******************************************************************************/
+char *
+Sim_SimReadInputFile(
+  Sim_Sim_t * sim)
+{
+  return (sim->inputFile);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of line already read by the parser in input file.]
+
+  Description [Returns the number of line already read by the parser in input
+  file. It is an error to call this function with a NULL or wrong sim structure.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+Sim_SimReadLineNumber(
+  Sim_Sim_t * sim)
+{
+  return (sim->lineNumber);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns nodesArray of the sim structure.]
+
+  Description [Returns nodesArray of the sim structure. It is an error to call
+  this function with a NULL or wrong sim structure.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+Sim_SimReadNodesArray(
+  Sim_Sim_t * sim)
+{
+  return (sim->nodesArray);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the index of the first current-state in nodesArray of
+  the sim structure.]
+
+  Description [Returns the index of the first current-state in nodesArray of
+  the sim structure. It is an error to call this function with a NULL or wrong
+  sim structure.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+Sim_SimReadCurrentStateHead(
+  Sim_Sim_t * sim)
+{
+  return (sim->currentStateHead);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the index of the first next-state in nodesArray of
+  the sim structure.]
+
+  Description [Returns the index of the first next-state in nodesArray of
+  the sim structure. It is an error to call this function with a NULL or wrong
+  sim structure.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+Sim_SimReadNextStateHead(
+  Sim_Sim_t * sim)
+{
+  return (sim->nextStateHead);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Returns the index of the first output in nodesArray of the sim
+  structure.]
+
+  Description [Returns the index of the first output in nodesArray of the sim
+  structure. It is an error to call this function with a NULL or wrong sim
+  structure.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+Sim_SimReadOutputHead(
+  Sim_Sim_t * sim)
+{
+  return (sim->outputHead);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Returns the initial state of the sim structure.]
+
+  Description [Returns the initial state of the sim structure. It is an error
+  to call this function with a NULL or wrong sim structure.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+Sim_SimReadInitState(
+  Sim_Sim_t * sim)
+{
+  return (sim->initState);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Returns the array of simulation vectors of the sim structure.]
+
+  Description [Returns the array of simulation vectors of the sim
+  structure. It is an error to call this function with a NULL or wrong sim
+  structure. The user should not free this array.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+Sim_SimReadVectorArray(
+  Sim_Sim_t * sim)
+{
+  return (sim->vectorArray);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Returns 1 if verbose status of the sim structure is true.]
+
+  Description [Returns 1 if verbose status of the sim structure is true. It is
+  an error to call this function with a NULL or wrong sim structure.]
+
+  SideEffects []
+
+******************************************************************************/
+boolean
+Sim_SimTestIsVerbose(
+  Sim_Sim_t * sim)
+{
+  return (sim->verbose);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/sim/simUtil.c
===================================================================
--- vis_dev/vis-2.3/src/sim/simUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/sim/simUtil.c	(revision 14)
@@ -0,0 +1,604 @@
+/**CFile***********************************************************************
+
+  FileName    [simUtil.c]
+
+  PackageName [sim]
+
+  Synopsis    [Basic useful functions for the sim package.]
+
+  Author      [Shaker Sarwary and Tom Shiple]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "simInt.h"
+#include <sys/time.h>
+
+static char rcsid[] UNUSED = "$Id: simUtil.c,v 1.8 2005/04/26 19:10:09 jinh Exp $";
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Builds a table mapping a node to a Mvf_Function.]
+
+  Description [Builds a table mapping a node to a Mvf_Function. nodesArray
+  should contain every nodes for which a Mvf_Function is requested. Returns an
+  empty table if nodesArray doesn't contain any node.]
+
+  SideEffects []
+
+******************************************************************************/
+st_table *
+Sim_NetworkBuildNodeToMvfTable(
+  Ntk_Network_t *network,
+  array_t       *nodesArray,
+  int            internalPartitionHead,
+  int            nextStateHead)
+{
+  array_t   *rootsName;
+  array_t   *leavesMddId;
+  array_t   *mvfArray;
+  st_table  *nodeToMvfTable;
+
+  SimNodesArrayBuildRootsAndLeaves(network, nodesArray, internalPartitionHead, nextStateHead, &rootsName, &leavesMddId);
+  mvfArray = Part_PartitionBuildFunctions(Part_NetworkReadPartition(network),
+                                          rootsName, leavesMddId, NIL(mdd_t));
+
+  array_free(leavesMddId);
+  array_free(rootsName);
+  nodeToMvfTable = SimNodesArrayBuildNodeToMvfTable(nodesArray, internalPartitionHead, mvfArray);
+  array_free(mvfArray);
+  return(nodeToMvfTable);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+  
+/**Function********************************************************************
+
+  Synopsis    [Returns the integer code of the value of a variable associated
+  to a node.]
+
+  Description [Returns the integer code of the value of a variable associated
+  to a node. If the value does not belong to the domain of the variable, then
+  -1 is returned. It is an error to call this function with a NULL node.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+SimNodeReadValueCode(
+  Ntk_Node_t * node,
+  char       * value)
+{
+  int             index;
+  Var_Variable_t *var = Ntk_NodeReadVariable(node);
+
+  if (Var_VariableTestIsSymbolic(var)) {
+    return(Var_VariableReadIndexFromSymbolicValue(var, value));
+  }
+
+  /* Enumerative or binary variable */
+  else {
+    index = atoi(value);
+    if (index >= Var_VariableReadNumValues(var) || index < 0) {
+      return(-1);
+    }
+    else {
+      return(index);
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis [Tests if the partition is in terms of CIs alone, in case internal
+  partition nodes are present.]
+
+  Description [ Returns 1 if internal nodes are present and the partition is in
+  terms of only combinational inputs (and constants)]
+
+  SideEffects []
+
+******************************************************************************/
+boolean
+SimTestPartInTermsOfCI(
+  Sim_Sim_t *sim
+  )
+{
+  int j, k, value, mddId;
+  Ntk_Node_t *node, *supportNode;
+  Mvf_Function_t *mvFunction;
+  array_t *mddIdArray;
+  
+  /* if there are no internal nodes, return FALSE. This allows
+     simulation to proceed when partition method inout is used.
+     */
+  if(sim->internalPartitionHead == sim->nextStateHead){
+    return FALSE;
+  }
+  
+  for (j = sim->nextStateHead; j < array_n(sim->nodesArray); j++) {
+    node =  array_fetch(Ntk_Node_t *, sim->nodesArray, j);
+    (void) st_lookup(sim->nodeToMvfTable, (char *) node, &mvFunction); 
+    mddIdArray = Mvf_FunctionComputeSupport(mvFunction,
+		            Ntk_NetworkReadMddManager(sim->network), &value);
+    if(mddIdArray != NIL(array_t)){
+      for(k = 0; k < array_n(mddIdArray); k++){
+	mddId = array_fetch(int, mddIdArray, k);
+	supportNode = Ntk_NetworkFindNodeByMddId(sim->network, mddId);
+	if(!Ntk_NodeTestIsCombInput(supportNode)){
+	  array_free(mddIdArray);
+	  return FALSE;
+	}
+      }
+      array_free(mddIdArray);
+    }/* if array not nil */
+  }/* for all nodes */
+  
+  return TRUE;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Converts integer to string of ASCII characters.]
+
+  Description [Converts integer to string of ASCII characters. It is the
+  responsibility of the user to free the returned string.]
+
+  SideEffects []
+
+******************************************************************************/
+char *
+SimInteger2ASCII(
+  int  number)
+{
+  char * str = ALLOC(char, 21);
+
+  (void) sprintf(str, "%d", number);
+  return(str);
+}
+  
+
+/**Function********************************************************************
+
+  Synopsis    [Print a string according to a given format.]
+
+  Description [Print a string according to a given format. The output file
+  must be valid. The string is formated according to len. If len > strlen(string),
+  then blanks are added]
+
+  SideEffects []
+
+******************************************************************************/
+void
+SimStringPrint(
+  FILE * fp,
+  char * string,
+  int  len)
+{
+  int i;
+  
+  fprintf(fp, "%s", string);
+  for(i = strlen(string); i < len; i++) {
+    fprintf(fp, " ");
+  }
+  fprintf(fp, " ");
+}
+  
+/**Function********************************************************************
+
+  Synopsis    [Returns an integer array that will contain the size of the
+  largest value of a node in the nodesArray.]
+
+  Description [Returns an integer array that will contain the size of the
+  largest value of a node in the nodesArray. It is the responsibility of the
+  user to free the returned array.]
+
+  SideEffects []
+
+******************************************************************************/
+array_t *
+SimSimInitDataFormat(
+  Sim_Sim_t * sim)
+{
+  int           i, j;
+  int           size;
+  int           maxSize;
+  int           numValue;
+  boolean       symbolic;
+  Ntk_Node_t   *node;
+  Var_Variable_t *var;
+  array_t      *formatArray = array_alloc(int, 0);
+  
+  for (j = 0; j < array_n(sim->nodesArray); j++) {
+    node     = array_fetch(Ntk_Node_t *, sim->nodesArray, j);
+    var      = Ntk_NodeReadVariable(node);
+    symbolic = Var_VariableTestIsSymbolic(var);
+    numValue = Var_VariableReadNumValues(var);
+    maxSize = 0;
+    if (symbolic) {
+      for (i = 0; i < numValue; i++) {
+        size = strlen(Var_VariableReadSymbolicValueFromIndex(var, i));
+        if (size > maxSize) {
+          maxSize = size;
+        }
+      }
+    }
+    else { /* Binary or enumertive type */
+      while(numValue != 0) {
+        maxSize++;
+        numValue = numValue/10;
+      }
+    }
+    array_insert_last(int, formatArray, maxSize);
+  }
+  return(formatArray);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Does a copy of the nextState values to the currentState of the
+  next simulation vector.]
+
+  Description [Does a copy of the nextState values to the currentState of the
+  next simulation vector. The current vector must contain the nextState
+  values. The next vector must not contain already a currentState value.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+SimSimVectorFillCurrentState(
+  Sim_Sim_t * sim /* sim data-structure */,
+  int  n /* index of nextState in the vectorArray */)
+{
+  int          i;
+  array_t     *currentVector  = array_fetch(array_t *, sim->vectorArray, n-1);
+  array_t     *nextVector     = array_fetch(array_t *, sim->vectorArray, n);
+  
+  for (i = sim->nextStateHead; i < sim->outputHead; i++) {
+    /* We assume nextVector contains only the inputs : insert_last is convenient */
+    int value = array_fetch(int, currentVector, i);
+    array_insert_last(int, nextVector, value);
+  }
+}
+ 
+/**Function********************************************************************
+
+  Synopsis [Returns a random value for a multi-valued variable.]
+
+  Description [Returns a random value for a multi-valued variable.  If the
+  node is of type pseudo-input, then 1) if pseudoInputSource is Sim_First_c,
+  then the first value of the first row is used, else 2) a random row of the
+  table is chosen, and within this row, a random value in the output entry is
+  chosen (this is not exactly random, because a value could appear in more
+  than one row). If the node in not a pseudo-input, then a random value from
+  the domain of the node's variable is chosen. The encoded value is returned.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+SimNodeComputeRandomValue(
+  Ntk_Node_t * node,
+  Sim_PseudoSrc  pseudoInputSource)
+{
+  int value = 0; /* initialize so that lint doesn't complain */ 
+
+  if (Ntk_NodeTestIsPseudoInput(node)) {
+    Tbl_Entry_t *entry;
+    int          rowNum;
+    int          colNum;
+    int          rowChoice;
+    Tbl_Table_t *table     = Ntk_NodeReadTable(node);
+    int          outIndex  = Ntk_NodeReadOutputIndex(node);
+
+    /* Decide which row to take value from. */
+    if (pseudoInputSource == Sim_First_c) {
+      rowChoice = 0;
+    }
+    else {
+      int numRows = Tbl_TableReadNumRows(table);
+      rowChoice = ((int) util_random()) % numRows;
+    }
+    
+    Tbl_TableForEachOutputEntry(table, rowNum, colNum, entry) {
+      if ((colNum == outIndex) && (rowNum == rowChoice)) {
+        Tbl_Range_t *range;
+        lsGen        lsGen;
+        int          tempValue;
+        int          entryChoice;
+        int          i = 0;
+
+        /* We are now in rowChoice. Decide which value of entry to take. */
+        if (pseudoInputSource == Sim_First_c) {
+          entryChoice = 0;
+        }
+        else {
+          int numValues = Tbl_EntryReadNumValues(entry);
+          entryChoice = ((int) util_random()) % numValues;
+        }
+    
+        Tbl_EntryForEachValue(entry, tempValue, lsGen, range) {
+          if(entryChoice == i) {
+            value = tempValue;
+            /*
+             * We could break out of the two FOR loops to avoid unnecessary
+             * work. However, the inner loop has an lsGen that must be freed
+             * if the loop is broken early, and I couldn't get lsFinish to be
+             * called correctly.  Also, the table shouldn't be big to worry
+             * about it.
+             */
+          }
+          i++;
+        }
+      }
+    }
+  }
+  else {
+    Var_Variable_t *var = Ntk_NodeReadVariable(node);
+
+    value = ((int) util_random()) % Var_VariableReadNumValues(var);
+  }
+
+  return value;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Builds the mdd of a simulation vector.]
+
+  Description [Builds the mdd of a simulation vector from an array of
+  integers. The length of this array should be equal to the number of
+  combinational inputs in the sim structure. The ith integer of this array
+  gives the value of the ith node in the sim structure's nodesArray.]
+
+  SideEffects []
+
+******************************************************************************/
+mdd_t *
+SimSimVectorBuildMdd(
+  Sim_Sim_t * sim,
+  array_t * vector,
+  array_t * partitionVector)
+{
+  int            i;
+  int            value;
+  mdd_t         *mddMinterm;
+  Ntk_Node_t    *node;
+  mdd_t         *literalMdd;
+  mdd_t         *tmpMdd;
+  Ntk_Network_t *network = sim->network;
+  mdd_manager   *mddManager = Ntk_NetworkReadMddManager(network);
+
+  mddMinterm = mdd_one(mddManager);
+  for(i = 0; i < sim->internalPartitionHead; i++) { /* For every combinational input */
+
+    node     = array_fetch(Ntk_Node_t *, sim->nodesArray, i);
+    value    = array_fetch(int, vector, i);
+
+    /* LiteralMdd will represent the mdd of  "Node-variable = value" */
+    literalMdd = mdd_eq_c(mddManager, Ntk_NodeReadMddId(node), value);
+    tmpMdd = mdd_and(literalMdd, mddMinterm, 1, 1);
+    mdd_free(mddMinterm);
+    mdd_free(literalMdd);
+    mddMinterm = tmpMdd;
+  }
+
+  for(i = 0; i < array_n(partitionVector); i++) { /* For every internal Partition node */
+
+    node     = array_fetch(Ntk_Node_t *, sim->nodesArray, i + sim->internalPartitionHead);
+    value    = array_fetch(int, partitionVector, i);
+
+    /* LiteralMdd will represent the mdd of  "Node-variable = value" */
+    literalMdd = mdd_eq_c(mddManager, Ntk_NodeReadMddId(node), value);
+    tmpMdd = mdd_and(literalMdd, mddMinterm, 1, 1);
+    mdd_free(mddMinterm);
+    mdd_free(literalMdd);
+    mddMinterm = tmpMdd;
+  }
+
+  return(mddMinterm);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Write an error message to error_string.]
+
+  Description [Write an error message to error_string. The message will be
+  written as ("%s%s%s", str1, str2, str3).]
+
+  SideEffects []
+
+******************************************************************************/
+void
+SimAppendErrorMsg(
+  char * str1,
+  char * str2,
+  char * str3)
+{
+  error_append(str1);
+  error_append(str2);
+  error_append(str3);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a random value.]
+
+  Description [Returns a random value. Uses gettimeofday system function.]
+
+  SideEffects []
+
+******************************************************************************/
+int
+SimComputeRandomInteger(void)
+{
+  struct timeval tp;
+  struct timezone tzp;
+
+  if ((int) gettimeofday(&tp,&tzp) == -1) {
+    fprintf (vis_stderr, "sim : Error while calling gettimeofday.\n");
+    exit(-1);
+  }
+  return((int) (tp.tv_sec));
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Builds an array of MddId of primary inputs, pseudo inputs, and
+  current states, and an array of name of next states and outputs.]
+
+  Description [Builds an array of MddId of leaves of a network : primary
+  inputs, pseudo inputs, and current states, and an array of name of roots:
+  next states and outputs. These arrays are returned through the parameteres
+  leaves and roots. We suppose that every primary inputs, pseudo inputs, and
+  current states has an MDD Id.]
+
+  SideEffects []
+
+******************************************************************************/
+void
+SimNodesArrayBuildRootsAndLeaves(
+  Ntk_Network_t *network,				 
+  array_t *  nodesArray,
+  int        internalPartitionHead,
+  int        nextStateHead,
+  array_t ** roots,
+  array_t ** leaves)
+{
+  int         i;
+  Ntk_Node_t *node;
+
+  *roots  = array_alloc(char *, 0);
+  *leaves = array_alloc(int, 0);
+
+  for(i = 0; i < nextStateHead; i++) {
+    node = array_fetch(Ntk_Node_t *, nodesArray, i);
+    array_insert_last(int, *leaves, Ntk_NodeReadMddId(node));
+  }
+
+  for(i = internalPartitionHead; i < array_n(nodesArray); i++) {
+    node = array_fetch(Ntk_Node_t *, nodesArray, i);
+    array_insert_last(char *, *roots, Ntk_NodeReadName(node));
+  }
+
+}
+
+/**Function********************************************************************
+
+  Synopsis [Builds a table mapping a node to its Mvf_Function.]
+
+  Description [Builds a table mapping a node to its Mvf_Function. mvfArray is
+  an array of Mvf_Function.]
+
+  SideEffects []
+
+******************************************************************************/
+st_table *
+SimNodesArrayBuildNodeToMvfTable(
+  array_t  * nodesArray,
+  int        internalPartitionHead,
+  array_t  * mvfArray)
+{
+  int         i;
+  Ntk_Node_t *node;
+  array_t    *mvf;
+  st_table   *nodeToMvfTable = st_init_table(st_ptrcmp, st_ptrhash);
+  
+  for(i = internalPartitionHead; i < array_n(nodesArray); i++) {
+    node = array_fetch(Ntk_Node_t *, nodesArray, i);
+    mvf  = array_fetch(Mvf_Function_t *, mvfArray, i - internalPartitionHead);
+    st_insert(nodeToMvfTable, (char *) node, (char *) mvf);
+  }
+  return(nodeToMvfTable);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+  
+  
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/spfd/spfd.h
===================================================================
--- vis_dev/vis-2.3/src/spfd/spfd.h	(revision 14)
+++ vis_dev/vis-2.3/src/spfd/spfd.h	(revision 14)
@@ -0,0 +1,88 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [spfd.h]
+
+  PackageName [spfd]
+
+  Synopsis [SPFD-based wire removal and replacement algorithm for
+  logic optimization of combinational circuits mapped to FPGAs.]
+
+  Description [This package implements wire removal and replacement
+  based logic optimization for combinational circuits mapped to
+  FPGAs. SPFDs (see the reference below) are used to represent
+  flexibilities in the Boolean network. This package provides two
+  commands: (1) spfd_pilo, a placement independent logic optimization
+  technique.  2. spfd_pdlo: A combined logic and placement
+  optimization technique. spfd_pdlo requires the package 
+  <a href="http://www.eecg.toronto.edu/~vaughn/vpr/vpr.html">VPR</a>.
+  Please contact Balakrishna Kumthekar at kumtheka@avanticorp.com to
+  obtaining a patch for VPR to work with VIS.
+
+  <p>
+  S. Yamashita, H. Sawada, and A. Nagoya. A new method to express
+  functional permissibilities for LUT based FPGAs and its
+  applications. In International Conference on Computer Aided Design,
+  pages 254-261, 1996.
+
+  <p>
+  Subarnarekha Sinha and Robert K. Brayton. Implementation and use of
+  SPFDs in optimizaing Boolean networks. In International Conference
+  on Computer Aided Design, 1998.
+
+  <p>
+  Balakrishna Kumthekar and Fabio Somenzi. Power and delay reduction
+  via simultaneous logic and placement optimization in FPGAs.
+  In Design, Automation and Test in Europe, 2000.]
+
+  SeeAlso     [spfdInt.h]
+
+  Author      [Balakrishna Kumthekar]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#ifndef _SPFD
+#define _SPFD
+
+#include "vm.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void Spfd_Init(void);
+EXTERN void Spfd_End(void);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _SPFD */
Index: vis_dev/vis-2.3/src/spfd/spfd.make
===================================================================
--- vis_dev/vis-2.3/src/spfd/spfd.make	(revision 14)
+++ vis_dev/vis-2.3/src/spfd/spfd.make	(revision 14)
@@ -0,0 +1,7 @@
+CSRC += spfdAPI.c spfdClean.c spfdCmd.c \
+	spfdCommon.c spfdOpt.c spfdProg.c \
+	spfdReg.c spfdSpfd.c spfdUtil.c
+
+HEADERS += spfdInt.h spfd.h
+
+DEPENDENCYFILES += $(CSRC)
Index: vis_dev/vis-2.3/src/spfd/spfdAPI.c
===================================================================
--- vis_dev/vis-2.3/src/spfd/spfdAPI.c	(revision 14)
+++ vis_dev/vis-2.3/src/spfd/spfdAPI.c	(revision 14)
@@ -0,0 +1,603 @@
+/**CFile***********************************************************************
+
+  FileName    [spfdAPI.c]
+
+  PackageName [spfd]
+
+  Synopsis [Routines to read, delete and update data structures used
+  in the package.]
+
+  Description [Routines to read, delete and update data structures used
+  in the package.]
+
+  SeeAlso     [spfdUtil.c spfdClean.c]
+
+  Author      [Balakrishna Kumthekar]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "spfdInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+extern int sfpdVerbose; 
+extern float alpha; 
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis           [Returns whether the node is locked.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+boolean
+SpfdNodeReadLocked(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *node)
+{
+  st_table *nodeToData = applData->nodeToData;
+  SpfdNodeData_t *nodeData;
+
+  st_lookup(nodeToData,(char *)node,&nodeData);
+  
+  return nodeData->locked;
+  
+} /* End of SpfdNodeReadLocked */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Read the auxillary BDD id associated with the node.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+int
+SpfdNodeReadAuxId(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *node)
+{
+  st_table *nodeToData = applData->nodeToData;
+  SpfdNodeData_t *nodeData;
+
+  st_lookup(nodeToData,(char *)node,&nodeData);
+  
+  return nodeData->auxId;
+  
+} /* End of SpfdNodeReadAuxId */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Set the auxillary BDD id for the node]
+
+  SideEffects        [None]
+
+******************************************************************************/
+void
+SpfdNodeSetAuxId(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *node,
+  int auxId)
+{
+  st_table *nodeToData = applData->nodeToData;
+  SpfdNodeData_t *nodeData;
+
+  st_lookup(nodeToData,(char *)node,&nodeData);
+  nodeData->auxId = auxId;
+
+} /* End of SpfdNodeSetAuxId */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Read the node's spfd.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+bdd_node *
+SpfdNodeReadSpfd(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *node)
+{
+  st_table *nodeToData = applData->nodeToData;
+  SpfdNodeData_t *nodeData;
+
+  st_lookup(nodeToData,(char *)node,&nodeData);
+  
+  return nodeData->spfd;
+  
+} /* End of SpfdNodeReadSpfd */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Free the BDD representing the spfd of the node.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+void
+SpfdNodeDeleteSpfd(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *node)
+{
+  st_table *nodeToData = applData->nodeToData;
+  SpfdNodeData_t *nodeData;
+
+  st_lookup(nodeToData,(char *)node,&nodeData);
+
+  if (nodeData->spfd)
+    bdd_recursive_deref(applData->ddManager,nodeData->spfd);
+  nodeData->spfd = NIL(bdd_node);
+  
+  return;
+  
+} /* End of SpfdNodeDeleteSpfd */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Set the node's spfd]
+
+  SideEffects        [None]
+
+******************************************************************************/
+void
+SpfdNodeSetSpfd(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *node,
+  bdd_node *spfd)
+{
+  st_table *nodeToData = applData->nodeToData;
+  SpfdNodeData_t *nodeData;
+
+  st_lookup(nodeToData,(char *)node,&nodeData);
+
+  if (nodeData->spfd) {
+    (void) fprintf(vis_stdout,
+		   "** spfd warning: <%s: set spfd> Possible memory leak.\n",
+		   Ntk_NodeReadName(node));
+  }
+  nodeData->spfd = spfd;
+  
+} /* End of SpfdNodeSetSpfd */
+
+
+/**Function********************************************************************
+
+  Synopsis [Read the array of BDD variables (parameters) associated
+  with the spfd of the node.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+bdd_node **
+SpfdNodeReadParameters(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *node)
+{
+  st_table *nodeToData = applData->nodeToData;
+  SpfdNodeData_t *nodeData;
+
+  st_lookup(nodeToData,(char *)node,&nodeData);
+
+  return nodeData->parameters;
+  
+} /* End of SpfdNodeReadParameters */
+
+
+/**Function********************************************************************
+
+  Synopsis [Free the array of BDD variables (parameters) associated
+  with the spfd of the node.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+void
+SpfdNodeDeleteParameters(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *node)
+{
+  st_table *nodeToData = applData->nodeToData;
+  SpfdNodeData_t *nodeData;
+
+  st_lookup(nodeToData,(char *)node,&nodeData);
+
+  if (nodeData->parameters)
+    FREE(nodeData->parameters);
+
+  nodeData->parameters = NIL(bdd_node *);
+  nodeData->numParams = 0;
+  
+  return;
+  
+} /* End of SpfdNodeDeleteParameters */
+
+
+/**Function********************************************************************
+
+  Synopsis [Set the array of BDD variables (parameters) associated
+  with the spfd of the node.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+void
+SpfdNodeSetParameters(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *node,
+  bdd_node **parameters,
+  int numParams)
+{
+  st_table *nodeToData = applData->nodeToData;
+  SpfdNodeData_t *nodeData;
+
+  st_lookup(nodeToData,(char *)node,&nodeData);
+
+  if (nodeData->parameters) {
+    (void) fprintf(vis_stdout,
+		   "** spfd warning: <%s: set parameters> Possible memory leak.\n",
+		   Ntk_NodeReadName(node));
+  }
+
+  nodeData->parameters = parameters;
+  nodeData->numParams = numParams;
+  
+} /* End of SpfdNodeSetParameters */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Read the sorted array of fanin nodes.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+array_t *
+SpfdNodeReadFaninOrder(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *node)
+{
+  st_table *nodeToData = applData->nodeToData;
+  SpfdNodeData_t *nodeData;
+
+  st_lookup(nodeToData,(char *)node,&nodeData);
+  
+  return nodeData->faninOrder;
+  
+} /* End of SpfdNodeReadFaninOrder */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Delete the sorted array of fanin nodes.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+void
+SpfdNodeDeleteFaninOrder(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *node)
+{
+  st_table *nodeToData = applData->nodeToData;
+  SpfdNodeData_t *nodeData;
+
+  st_lookup(nodeToData,(char *)node,&nodeData);
+
+  if (nodeData->faninOrder)
+    array_free(nodeData->faninOrder);
+
+  nodeData->faninOrder = NIL(array_t);
+  
+  return;
+  
+} /* End of SpfdNodeDeleteFaninOrder */
+
+
+/**Function********************************************************************
+
+  Synopsis [Set the array faninOrder required during SPFD computation.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+void
+SpfdNodeSetFaninOrder(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *node,
+  array_t *faninOrder)
+{
+  st_table *nodeToData = applData->nodeToData;
+  SpfdNodeData_t *nodeData;
+
+  st_lookup(nodeToData,(char *)node,&nodeData);
+  if (nodeData->faninOrder) {
+    (void) fprintf(vis_stdout,
+                   "** spfd warning: <%s: set fanin order> Possible memory leak.\n",
+		   Ntk_NodeReadName(node));
+  }
+  nodeData->faninOrder = faninOrder;
+
+} /* End of SpfdNodeSetFaninOrder */
+
+/**Function********************************************************************
+
+  Synopsis [Read the global BDD of the node. The global BDD is derived
+  from the node's spfd.]
+
+  SideEffects        [SpfdNodeDeleteGlobalAlternative]
+
+******************************************************************************/
+bdd_node *
+SpfdNodeReadGlobalAlternative(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *node)
+{
+  st_table *nodeToData = applData->nodeToData;
+  SpfdNodeData_t *nodeData;
+
+  st_lookup(nodeToData,(char *)node,&nodeData);
+  
+  return nodeData->alternative;
+  
+} /* End of SpfdNodeReadGlobalAlternative */
+
+
+/**Function********************************************************************
+
+  Synopsis [Delete the global BDD of the node. The global BDD is
+  derived from the node's spfd.]
+
+  SideEffects [None]
+
+  SeeAlso            [SpfdNodeReadGlobalAlternative]
+
+******************************************************************************/
+void
+SpfdNodeDeleteGlobalAlternative(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *node)
+{
+  st_table *nodeToData = applData->nodeToData;
+  SpfdNodeData_t *nodeData;
+
+  st_lookup(nodeToData,(char *)node,&nodeData);
+
+  if (nodeData->alternative)
+    bdd_recursive_deref(applData->ddManager,nodeData->alternative);
+
+  nodeData->alternative = NIL(bdd_node);
+  
+  return;
+  
+} /* End of SpfdNodeDeleteGlobalAlternative */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Set the BDD as the node's global BDD.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+void
+SpfdNodeSetGlobalAlternative(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *node,
+  bdd_node *alternative)
+{
+  st_table *nodeToData = applData->nodeToData;
+  SpfdNodeData_t *nodeData;
+
+  st_lookup(nodeToData,(char *)node,&nodeData);
+  if (nodeData->alternative) {
+    (void) fprintf(vis_stdout,
+		   "** spfd warning: <%s: set global alternative>"
+		   " Possible memory leak.\n",
+		   Ntk_NodeReadName(node));
+  }
+  nodeData->alternative = alternative;
+  
+} /* End of SpfdNodeSetGlobalAlternative */
+
+
+/**Function********************************************************************
+
+  Synopsis [Read the local BDD, which is in terms of the node's
+  immediate fanin.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+bdd_node *
+SpfdNodeReadLocalAlt(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *node)
+{
+  st_table *nodeToData = applData->nodeToData;
+  SpfdNodeData_t *nodeData;
+
+  st_lookup(nodeToData,(char *)node,&nodeData);
+
+  return nodeData->localAlt;
+  
+} /* End of SpfdNodeReadLocalAlt */
+
+
+/**Function********************************************************************
+
+  Synopsis [Delete the local BDD, which is in terms of the node's
+  immediate fanin.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+void
+SpfdNodeDeleteLocalAlt(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *node)
+{
+  st_table *nodeToData = applData->nodeToData;
+  SpfdNodeData_t *nodeData;
+
+  st_lookup(nodeToData,(char *)node,&nodeData);
+
+  if (nodeData->localAlt)
+    bdd_recursive_deref(applData->ddManager,nodeData->localAlt);
+
+  nodeData->localAlt = NIL(bdd_node);
+  
+  return;
+  
+} /* End of SpfdNodeDeleteLocalAlt */
+
+ 
+/**Function********************************************************************
+
+  Synopsis [Set localAlt as the local BDD. localAlt is in terms of the
+  node's immediate fanin.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+void
+SpfdNodeSetLocalAlt(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *node,
+  bdd_node *localAlt)
+{
+  st_table *nodeToData = applData->nodeToData;
+  SpfdNodeData_t *nodeData;
+
+  st_lookup(nodeToData,(char *)node,&nodeData);
+  if (nodeData->localAlt) {
+    (void) fprintf(vis_stdout,
+		   "** spfd warning: <%s: set local alt> Possible memory leak.\n",
+		   Ntk_NodeReadName(node));
+  }
+  nodeData->localAlt = localAlt;
+  
+} /* End of SpfdNodeSetLocalAlt */
+  
+
+/**Function********************************************************************
+
+  Synopsis           [Set the node as locked.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+void
+SpfdNodeSetLocked(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *node,
+  boolean locked)
+{
+  st_table *nodeToData = applData->nodeToData;
+  SpfdNodeData_t *nodeData;
+
+  st_lookup(nodeToData,(char *)node,&nodeData);
+
+  nodeData->locked = locked;
+  
+} /* End of SpfdNodeSetLocked */
+
+
+/**Function********************************************************************
+
+  Synopsis [Read the number of parameters associated with the node's
+  SPFD.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+int
+SpfdNodeReadNumParams(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *node)
+{
+  st_table *nodeToData = applData->nodeToData;
+  SpfdNodeData_t *nodeData;
+
+  st_lookup(nodeToData,(char *)node,&nodeData);
+
+  return nodeData->numParams;
+  
+} /* End of SpfdNodeReadNumParams */
+
+/**Function********************************************************************
+
+  Synopsis [This is used to get the index of the source of the net
+  data structure used in VPR.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+int
+SpfdNodeReadNetIndex(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *node)
+{
+  SpfdPlaceData_t *placeData;
+  int index = -1;
+  
+  placeData = applData->placeData;
+  st_lookup(placeData->nodeToNetIndex,(char *)node,&index);
+
+  return index;
+  
+} /* End of SpfdNodeReadNetIndex */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
Index: vis_dev/vis-2.3/src/spfd/spfdClean.c
===================================================================
--- vis_dev/vis-2.3/src/spfd/spfdClean.c	(revision 14)
+++ vis_dev/vis-2.3/src/spfd/spfdClean.c	(revision 14)
@@ -0,0 +1,330 @@
+/**CFile***********************************************************************
+
+  FileName    [spfdClean.c]
+
+  PackageName [spfd]
+
+  Synopsis [Routines to free memory when not needed.]
+
+  Description [Routines to free memory when not needed.]
+
+  SeeAlso     [spfdAPI.c spfdUtil.c]
+
+  Author      [Balakrishna Kumthekar]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "spfdInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+extern int sfpdVerbose;
+extern float alpha;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static enum st_retval NodeDataFree(char *key, char *value, char *arg);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Routine to free the application data structure attached by
+  this package to network. Certain fields of the SpfdApplData_t are
+  freed earlier.]
+
+  SideEffects [None]
+
+******************************************************************************/
+void
+SpfdApplFreeCallback(void *data)
+{
+  SpfdApplData_t *applData = (SpfdApplData_t *)data;
+  st_table *nodeToData = applData->nodeToData;
+  bdd_manager *mgr = applData->ddManager;
+  
+  if (applData->currWireTable)
+    st_free_table(applData->currWireTable);
+  
+  if (applData->currReplaceTable)
+    st_free_table(applData->currReplaceTable);
+  
+  if (applData->wiresRemoved)
+    st_free_table(applData->wiresRemoved);
+
+  if (applData->nodesRemoved) {
+    st_free_table(applData->nodesRemoved);
+  }
+  
+  if (nodeToData) {
+    st_foreach(nodeToData,NodeDataFree,(char *)mgr);
+    st_free_table(nodeToData);
+  }
+
+  /* The data private to placeData is assumed to be deleted elsewhere */
+  if (applData->placeData)
+    FREE(applData->placeData);
+
+  /* The rest of the fields are deleted once elsewhere. */
+  
+  FREE(applData);
+  
+  return;
+
+} /* End of SpfdApplFreeCallback */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Free BDDs stored in a st_table.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+enum st_retval
+SpfdStBddFree(
+  char *key,
+  char *value,
+  char *arg)
+{
+  bdd_recursive_deref((bdd_manager *)arg,(bdd_node *)value);
+  
+  return (ST_CONTINUE);
+
+} /* End of SpfdStBddFree */
+
+
+/**Function********************************************************************
+
+  Synopsis [This function frees the table stored as 'value' in an st_table and
+  returns ST_DELETE so that memory allocated for 'key' is also freed. In the
+  end the table is 'cleaned' but not 'freed.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+enum st_retval
+SpfdStTableClean(
+  char *key,
+  char *value,
+  char *arg)
+{
+  st_free_table((st_table *)value);
+
+  return (ST_DELETE);
+} /* End of SpfdStTableClean */
+
+
+/**Function********************************************************************
+
+  Synopsis [Release those ids that will no longer be necessary, also
+  delete global and local BDDs. After an alternate implementation at
+  'regNode' is found, BDDs (local function, global function, BDD
+  variable ID and auxillary BDD ID) at its fanin may no longer be
+  necessary. nodeTable stores the pair <node,count>. 'count'
+  indicates how may times the BDDs at that node will be accessed. Such
+  BDDs are freed when appropriate, i.e., 'count' = 0.]
+
+  SideEffects [None]
+
+******************************************************************************/
+void
+SpfdReleaseAndCleanNodeData(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *regNode,
+  st_table *nodeTable)
+{
+  int k;
+  Ntk_Node_t *fanin;
+  st_table *inUseVars = applData->currInUseVars;
+  st_table *regionNodes = applData->currRegionNodes;
+  st_table *currBddReq = applData->currBddReq;
+  bdd_manager *ddManager = applData->ddManager;
+  char *dummy;
+
+  Ntk_NodeForEachFanin(regNode,k,fanin) {
+    int *count;
+    if (st_lookup(nodeTable,(char *)fanin,&count)) {
+      (*count)--;
+      if (*count == 0) {
+	int tempAuxId;
+	int dummyInt;
+	
+	/* Free the auxId */
+	tempAuxId = SpfdNodeReadAuxId(applData,fanin);
+	if (st_delete(inUseVars,&tempAuxId,&dummy))
+	  SpfdNodeSetAuxId(applData,fanin,-1);
+	    
+	if (st_lookup_int(regionNodes,(char *)fanin,&dummyInt)) {
+	  /* If it is an internal node also delete the alternative function */
+	  if (!dummyInt) 
+	    SpfdNodeDeleteGlobalAlternative(applData,fanin);
+	  /* If this is a region node delete the global Bdd */
+	  if(st_delete(currBddReq,&fanin,&dummy))
+	    bdd_recursive_deref(ddManager,(bdd_node *)dummy);
+	} else {
+	  if(st_delete(currBddReq,&fanin,&dummy))
+	    bdd_recursive_deref(ddManager,(bdd_node *)dummy);
+	}
+	if (st_delete(nodeTable, &fanin, &count))
+	   FREE(count);
+      } /* End of *count == 0 */
+    } /* st_lookup  */
+  } /* Ntk_NodeForEachFanin */
+
+  return;
+  
+} /* End of SpfdReleaseAndCleanNodeData */
+
+
+/**Function********************************************************************
+
+  Synopsis [Release those alternate PI ids that are no longer
+  necessary. This is necessary as we resuse the BDD variable IDs.]
+
+  SideEffects [None]
+
+******************************************************************************/
+void
+SpfdReleaseAlternatePiIds(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *regNode,
+  st_table *nodeTable)
+{
+  int k;
+  Ntk_Node_t *fanin;
+  st_table *inUseVars = applData->currInUseVars;
+  st_table *piAltVars = applData->currPiAltVars;
+        
+  Ntk_NodeForEachFanin(regNode,k,fanin) {
+    int *count;
+    if (st_lookup(nodeTable,(char *)fanin,&count)) {
+      /* Do not delete the count. It is done in the final clean up
+	 in SpfdReleaseAndCleanNodeDate. */
+      if (*count == 1) {
+	long tempId, tempAltId;
+	tempId = Ntk_NodeReadMddId(fanin);
+	if (st_lookup(piAltVars,(char *)(long)tempId,&tempAltId)) {
+	  st_delete(inUseVars,&tempAltId,NIL(char *));
+	  st_delete(piAltVars,&tempId,NIL(char *));
+	}
+      }
+    }
+  }
+
+  return;
+  
+} /* End of SpfdReleaseAlternatePiIds */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Return auxillay BDD ids to the pool.]
+
+  SideEffects [None]
+
+******************************************************************************/
+  void
+SpfdCleanUpAuxIds(SpfdApplData_t *applData)
+{
+  st_table *regionNodes = applData->currRegionNodes;
+  st_generator *stGen;
+  char *dummy;
+  Ntk_Node_t *regNode,*fanin;
+  int i;
+  
+  /* Release the auxIds */
+  st_foreach_item(regionNodes,stGen,&regNode,&dummy) {
+    Ntk_NodeForEachFanin(regNode,i,fanin) {
+      SpfdNodeSetAuxId(applData,fanin,-1);
+    }
+  }
+
+  /* Free the table storing the currently used BDD IDs for PI
+     auxillary variables. */
+  st_free_table(applData->currPiAltVars);
+  applData->currPiAltVars = NIL(st_table);
+  
+  return;
+} /* End of SpfdCleanUpAuxIds */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis           [Free SpfdNodeData_t]
+
+  SideEffects        [None]
+
+******************************************************************************/
+static enum st_retval
+NodeDataFree(
+  char *key,
+  char *value,
+  char *arg)
+{
+  SpfdNodeData_t *data;
+  bdd_manager *ddManager = (bdd_manager *)arg;
+
+  data = (SpfdNodeData_t *)value;
+
+  if (data) {
+    if (data->spfd)
+      bdd_recursive_deref(ddManager,data->spfd);
+    if (data->alternative)
+      bdd_recursive_deref(ddManager,data->alternative);
+    if (data->faninOrder)
+      array_free(data->faninOrder);
+    if (data->parameters)
+      FREE(data->parameters);
+    if (data->localAlt)
+      bdd_recursive_deref(ddManager,data->localAlt);
+    FREE(data);
+  }
+    
+  return (ST_CONTINUE);
+
+} /* End of NodeDataFree */
+
Index: vis_dev/vis-2.3/src/spfd/spfdCmd.c
===================================================================
--- vis_dev/vis-2.3/src/spfd/spfdCmd.c	(revision 14)
+++ vis_dev/vis-2.3/src/spfd/spfdCmd.c	(revision 14)
@@ -0,0 +1,1097 @@
+/**CFile***********************************************************************
+
+  FileName    [spfdCmd.c]
+
+  PackageName [spfd]
+
+  Synopsis [Interface functions for commands spfd_pilo and spfd_pdlo.]
+
+  Description [Interface functions for commands spfd_pilo and spfd_pdlo.]
+
+  SeeAlso     [spfdOpt.c]
+
+  Author      [Balakrishna Kumthekar]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "spfdInt.h"
+
+static char rcsid[] UNUSED = "$Id: spfdCmd.c,v 1.28 2002/09/09 01:04:28 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+static jmp_buf timeOutEnv; /* time out */
+int spfdCreatedPart; /* Whether network BDDs were created in the package */
+int spfdVerbose; /* verbosity */
+float spfdAlpha; /* spfdAlpha * load + (1-spfdAlpha) * topDepth, is used to order
+                fanin nodes during SPFD computation */
+boolean spfdPerfSim; /* Perform simulation */
+boolean spfdNtkChanged; /* TRUE if network changes structurally or functionally */
+boolean spfdReprogNoWire; /* If TRUE, no functional changes are performed
+                         unless required by structural changes */
+int spfdWiresAdded, spfdNumWiresRem; /* Number of wires added and removed */
+int spfdSortNodes; /* Method to sort nodes */
+int spfdMethod; /* Optimization method */
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandSpfdNetworkOptimize(Hrc_Manager_t **hmgr, int argc, char **argv);
+static int CommandSpfdPlaceOptimize(Hrc_Manager_t **hmgr, int argc, char **argv);
+static void TimeOutHandle(void);
+static int TestIsNetworkMultipleValued(Ntk_Network_t *network);
+static int SpfdSimultaneousPlacementAndLogicOpt(Ntk_Network_t *network, char *netFile, char *archFile, char *placeFile, char *routeFile, char *netOutFile, int regionDepth);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [This function initializes the spfd package.]
+
+  SideEffects [None]
+
+  SeeAlso     [Spfd_End]
+
+******************************************************************************/
+void
+Spfd_Init(void)
+{
+  Cmd_CommandAdd("spfd_pilo", CommandSpfdNetworkOptimize, 1);
+  Cmd_CommandAdd("spfd_pdlo", CommandSpfdPlaceOptimize, 1);
+
+} /* End of Spfd_Init */
+
+/**Function********************************************************************
+
+  Synopsis    [This function ends the spfd package.]
+
+  SideEffects [None]
+
+  SeeAlso     [Spfd_Init]
+
+******************************************************************************/
+void
+Spfd_End(void)
+{
+
+} /* End of Spfd_End */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+   Synopsis [Implements SPFD-based placement independent logic
+   optimization command, spfd_pilo, for combinational circuits mapped
+   to LUT-based FPGAs.]
+
+   CommandName [spfd_pilo]
+
+   CommandSynopsis [Perform SPFD-based placement independent logic
+   optimization.]
+
+   CommandArguments [\[-a &lt;\[0,1\]&gt;\] \[-D &lt;depth&gt;\] \[-f
+   &lt;file&gt;\] \[-h\] \[-i &lt;freq&gt;\] \[-p &lt;percent&gt;\]
+   \[-r\] \[-S &lt;n&gt;\] \[-t &lt;sec&gt;\] \[-v &lt;n&gt;\]
+   \[-w &lt;file&gt;\] ]
+
+   CommandDescription [This command performs SPFD-based wire
+   removal/replacement and reprogramming of combinational circuits
+   mapped to LUT-based FPGAs to reduce the number of wires and nodes
+   in the circuit. The flexibilities in the circuit are represented by
+   SPFDs. The following references explain in detail the theory behind
+   SPFDs.
+
+   <p>S. Yamashita, H. Sawada, and A. Nagoya. A new method to express
+   functional permissibilities for LUT based FPGAs and its
+   applications. In International Conference on Computer Aided Design,
+   pages 254-261, 1996.
+
+   <p>Subarnarekha Sinha and Robert K. Brayton. Implementation and use of
+   SPFDs in optimizaing Boolean networks. In International Conference
+   on Computer Aided Design, 1998.
+
+   <p> Instead of computing the flexibilities for every node in the
+   network at once, the algorithm computes the flexibilities for one
+   cluster at a time. Working with clusters allows us to avoid the BDD
+   explosion problem and hence, handle large circuits. The SPFDs are
+   computed for the cluster and the cluster nodes are reprogrammed
+   based on the flexibility derived. Switching activity is used to
+   drive the choice of alternate function to be implemented at the
+   node. In the absence of switching activity information, the
+   function that can reduce support of the node can be chosen (not
+   implemented). Currently, an arbitrary choice is made from the
+   flexibilities provided by SPFDs. (-S 0, -S 2, and -S 4)
+
+   <p>
+   Before calling this command a network should be created for the
+   design (use flatten_hierarchy) and MDD ids for every node in the
+   network should be created (static_order -o all -n append, for
+   example). Dynamic variable ordering (dvo -e sift) can be enabled 
+   to reduce BDD sizes.
+
+   <p>Command options:<p>
+
+   <dl>
+
+   <dt> -a &lt;alpha&gt;
+   <dd> A convex combination of switched
+   capacitance (switching activity * fanout count, SWC) and topological
+   depth is used to sort the fanin nodes during SPFD computation. alpha
+   is between 0 and 1.0. The cost function is alpha*SWC +
+   (1.0-alpha)*topDepth. The default value is 0.5. <p>
+
+   <dt> -D &lt;depth&gt;
+   <dd> A cluster is computed which includes nodes within the specified
+   'depth'. The default value is 1.<p>
+
+   <dt> -f &lt;file&gt;
+   <dd> File with simulation vectors.  The file
+   format is as below. The format is simple but strict and hence, few
+   checks are made.
+   <p> .i <code>c n d o e p f q g r h s i t j u k a l b m</code><br>
+    .s <br>
+    0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 1 1 1 1 ; <br>
+    0 1 1 0 0 0 0 1 0 1 1 0 1 1 1 1 0 0 0 0 1 ; <br>
+    0 0 1 0 0 0 0 1 0 1 0 0 0 1 0 1 0 0 0 0 1 ; <br>
+    0 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 0 1 0 0 1 ; <br>
+
+   <p>The .i statement specifies the primary inputs of the network. The
+   patterns start after .s key word. Each vector is a space separated list of
+   bits and ends in a semi-colon. The length of any vector should be equal 
+   to the number of signals specified in the .i statement. A line starting 
+   with # is a comment.  <p>
+
+   <dt> -h
+   <dd> Print usage. <p>
+
+   <dt> -i &lt;freq&gt;
+   <dd> Number of iterations after which to update node switching
+   activity. This is valid only if patterns are provided in a file 
+   using -f option. The default value is every 5 iterations. <p>
+
+   <dt> -m &lt;n&gt;
+   <dd> Heuristics to optimize a selected node. <br>
+   <code>0</code>: Reduce the selected node's support. <br>
+   <code>1</code>: Reprogram the selected node.<br>
+   <code>2</code>: Reprogram the selected node's fanin nodes.
+   (default)<br>
+   <code>3</code>: Reduce the selected node's fanout wires. <p>
+   
+   <dt> -p &lt;percent&gt;
+   <dd> The percentage of vectors, specified via <code>-f</code>
+   option, used to perform simulation (to update switching activity)
+   during logic optimization. The default value is 10%. <p>
+
+   <dt> -r
+   <dd> Do not reprogram LUTs if no structural changes have been
+   performed with in the cluster, i.e., if no nodes or wires have been
+   removed do not change the local implementation of LUTs even if
+   alternate implementations are availabe from SPFD information. The
+   default is to reprogram. <p>
+
+   <dt> -S &lt;n&gt;
+   <dd> Method used to sort nodes. The nodes are then optimized in
+   that order.<br>
+   <code>0</code>: Random node is chosen. (default) <br>
+   <code>1</code>: If switching activity is available, node with
+   maximum SWC is chosen.  <br>
+   <code>2</code>: Node with maximum fanout is chosen. <br>
+   <code>3</code>: If switching activity is available, node with
+   minimum SWC is chosen. <br>
+   <code>4</code>: Node with minimum fanout is chosen. <p>
+
+   <dt> -t &lt;sec&gt;
+   <dd> Time in seconds allowed to complete the command. If the
+   computation time goes above that limit, the process is aborted.
+   The default is no limit.<p>
+   
+   <dt> -v &lt;n&gt;
+   <dd> Verbosity level. Default value is 0.<p>
+
+   <dt> -w &lt;file&gt;
+   <dd> File to output final optimized circuit. <p> ]
+   </dl>
+  
+   <p> <b>Relevant flags to be set by the set command:</b> <p>
+   <dl>
+   <dt> <b>spfd_repl_rem</b>
+   <dd> If <b>no</b>, the logic optimization performs only wire
+   removal. If <b>yes</b>, both wire replacement and removal are performed.
+   </dl>
+  
+   SideEffects [The network is changed to reflect the wires/nodes
+   removed or replaced. The internal function of the nodes is also
+   changed. The partition attached to the network is changed
+   accordingly.]
+
+******************************************************************************/
+static int
+CommandSpfdNetworkOptimize(
+  Hrc_Manager_t **hmgr,
+  int argc,
+  char **argv)
+{
+
+  Ntk_Network_t *network = NIL(Ntk_Network_t);
+  graph_t *simPart;
+  int status,percent,frequency,regionDepth;
+  int c;
+  long timeOutPeriod,initialTime,finalTime;
+  char *simFile,*writeFile;
+  char endPtr[128];
+  FILE *fp = NIL(FILE);
+  
+  /* These are the default values. */
+  spfdCreatedPart = 0; /* Do not create a new partition */
+  timeOutPeriod   = 0;  
+  simFile = NIL(char);  /* File containing simulation vectors */
+  spfdVerbose = 0; /* verbosity */
+  regionDepth = 1; /* Depth of cluster */
+  percent = 10; /* Percent of total vectors to be simulated during opt. */
+  frequency = 5; /* Perform simulation every frequency iterations */
+  spfdSortNodes = RANDOM; /* Choose a random node for optimization */
+  spfdMethod = 2;
+  spfdAlpha = 0.5; 
+  writeFile = NIL(char); /* File to output final optimized ckt. */
+  spfdNtkChanged = FALSE; 
+  spfdReprogNoWire = TRUE;
+  spfdWiresAdded = 0;
+  spfdNumWiresRem = 0;
+  spfdPerfSim = FALSE; /* Default */
+  
+  if (bdd_get_package_name() != CUDD) {
+    (void) fprintf(vis_stderr,
+		   "** spfd error: The spfd package can be used "
+		   "only with CUDD package\n");
+    (void) fprintf(vis_stderr,
+		   "** spfd error: Please link with CUDD package\n");
+    return 0;
+  }
+	
+  util_getopt_reset();
+
+  while((c = util_getopt(argc, argv, "a:D:f:hi:m:p:rS:t:v:w:")) != EOF) {
+    switch(c) {
+    case 'a':
+      spfdAlpha = (float) strtod(util_optarg,(char **)&endPtr);
+      if (!strcmp(util_optarg,endPtr)) {
+	(void) fprintf(vis_stdout,
+		       "** spfd warning: Invalid value <%s> specified for -a\n",
+		       util_optarg);
+	(void) fprintf(vis_stdout,"** spfd warning: Assuming 0.5.\n");
+	spfdAlpha = 0.5;
+      } else if (spfdAlpha > 1.0 || spfdAlpha < 0.0) {
+	(void) fprintf(vis_stdout,
+		       "** spfd warning: Value for -a <%f> not in [0,1]\n",
+		       spfdAlpha);
+	(void) fprintf(vis_stdout,"** spfd warning: Assuming 0.5.\n");
+	spfdAlpha = 0.5;
+      }
+      break;
+    case 'D':
+      regionDepth = atoi(util_optarg);
+      break;
+    case 'f': 
+      if (!util_optarg) {
+	(void) fprintf(vis_stderr,
+		       "** spfd error: Simulation file not specified.\n");
+	goto usage;
+      } else {
+	simFile = util_strsav(util_optarg);
+	if ((fp = Cmd_FileOpen(simFile,"r",NIL(char *),1)) == NIL(FILE)) {
+	  (void) fprintf(vis_stderr,
+			 "** spfd error: Could not open %s for reading.\n",
+			 simFile);
+	  goto endgame;
+	} else {
+	  fclose(fp);
+	}
+	spfdPerfSim = TRUE;
+      }
+      break;
+    case 'h':
+      goto usage;
+    case 'i':
+      frequency = atoi(util_optarg);
+      break;
+    case 'm':
+      spfdMethod = atoi(util_optarg);
+      if (spfdMethod > 3 || spfdMethod < 0) {
+	(void) fprintf(vis_stderr, "** spfd warning: -m has invalid argument\n");
+	(void) fprintf(vis_stderr, "** spfd warning: Using 2 instead.\n");
+      }
+      break;
+    case 'p':
+      percent = atoi(util_optarg);
+      if (percent > 100 || percent < 0) {
+	(void) fprintf(vis_stderr,
+		       "** spfd warning: -p <%d> has invalid argument.\n",
+		       percent);
+	(void) fprintf(vis_stderr,
+		       "** spfd warning: Using 10%% instead.\n");
+      }
+      break;
+    case 'r':
+      spfdReprogNoWire = FALSE;
+      break;
+    case 'S':
+      spfdSortNodes = atoi(util_optarg);
+      if (spfdSortNodes > 4 || spfdSortNodes < 0) {
+	(void) fprintf(vis_stderr,
+		       "** spfd warning: -S <%d> has invalid argument.\n",
+		       spfdSortNodes);
+	(void) fprintf(vis_stderr,
+		       "** spfd warning: Using 0 (random) instead.\n");
+      }
+      break;
+    case 't':
+      timeOutPeriod = atoi(util_optarg);
+      break;
+    case 'v':
+      spfdVerbose = atoi(util_optarg);
+      break;
+    case 'w':
+      writeFile = util_strsav(util_optarg);
+      if ((fp = Cmd_FileOpen(writeFile,"w",NIL(char *),1)) == NIL(FILE)) {
+	(void) fprintf(vis_stderr,
+		       "** spfd error: Could not open %s for writing.\n",
+		       writeFile);
+	goto endgame;
+      } else {
+	fclose(fp);
+      }
+      break;
+    default:
+      goto usage;
+    }
+  }
+
+  if(Hrc_ManagerReadCurrentNode(*hmgr) == NIL(Hrc_Node_t)) {
+    (void) fprintf(vis_stderr,"** spfd error: The hierarchy manager is empty."
+		   " Read in design.\n");
+    goto endgame;
+  }
+
+  network = (Ntk_Network_t *) 
+    Hrc_NodeReadApplInfo(Hrc_ManagerReadCurrentNode(*hmgr), 
+			 NTK_HRC_NODE_APPL_KEY);
+
+  if(network == NIL(Ntk_Network_t)) {
+    (void) fprintf(vis_stderr,"** spfd error: There is no network. ");
+    (void) fprintf(vis_stderr,"Use flatten_hierarchy.\n");
+    goto endgame;
+  }
+    
+  /* Check if the current network has signals with multiple values. */
+  if (TestIsNetworkMultipleValued(network)) {
+    (void) fprintf(vis_stderr,"** spfd error: Circuit has multiple "
+		   "valued variables.\n");
+    (void) fprintf(vis_stderr,"** spfd error: The algorithm currently "
+		   "supports only Boolean valued variables.\n");
+    goto endgame;
+  }
+
+  if(Ntk_NetworkReadNumPrimaryInputs(network) !=
+     Ntk_NetworkReadNumInputs(network)) {
+    (void) fprintf(vis_stderr,"** spfd error: Pseudo inputs present "
+		   "in the network.\n");
+    (void) fprintf(vis_stderr,"** spfd error: The algorithm does not apply.\n");
+    goto endgame;
+  }
+
+  if(Ntk_NetworkReadNumLatches(network) > 0) {
+    (void) fprintf(vis_stderr,"** spfd error: Sequential circuit.\n");
+    (void) fprintf(vis_stderr,"** spfd error: The command is only for combinational circuits.\n");
+    goto endgame;
+  }
+  
+  /* Access a 'total' partition */
+  simPart = (graph_t *) Ntk_NetworkReadApplInfo(network,PART_NETWORK_APPL_KEY);
+  if (simPart == NIL(graph_t) || 
+      (Part_PartitionReadMethod(simPart) != Part_Total_c)) {
+    simPart = Part_NetworkCreatePartition(network, 
+					  NIL(Hrc_Node_t),
+					  "dummy", (lsList) 0, 
+					  (lsList) 0, NIL(mdd_t),
+					  Part_Total_c,
+					  (lsList) 0, 
+					  FALSE, FALSE, TRUE);
+    if (simPart == NIL(graph_t)) {
+      (void) fprintf(vis_stderr,"** spfd error: Could not create partition.\n");
+      goto endgame;
+    }
+    Ntk_NetworkAddApplInfo(network,PART_NETWORK_APPL_KEY,
+			   (Ntk_ApplInfoFreeFn)Part_PartitionFreeCallback,
+			   (void *)simPart);
+    spfdCreatedPart = 1; /* Using new partition */
+    (void) fprintf(vis_stdout,
+		   "** spfd info: A new partition created.\n");
+  }
+
+  /* Start the timer.*/
+  if (timeOutPeriod > 0){
+    (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
+    (void) alarm(timeOutPeriod);
+    if (setjmp(timeOutEnv) > 0) {
+      (void) fprintf(vis_stderr, "** spfd warning: Timeout occurred after ");
+      (void) fprintf(vis_stderr, "%ld seconds.\n", timeOutPeriod);
+      alarm(0);
+      goto endgame;
+    }
+  }
+
+  initialTime = util_cpu_time();
+
+  if (!spfdPerfSim) {
+    (void) fprintf(vis_stdout,
+		   "** spfd info: Simulation vectors not specified.\n");
+    if (spfdSortNodes == MAXSWCAP) {
+      (void) fprintf(vis_stdout,
+		     "** spfd info: Using method -S 2 instead of -S 1\n");
+      spfdSortNodes = MAXFANOUT;
+    } else if (spfdSortNodes == MINSWCAP) {
+      (void) fprintf(vis_stdout,
+		     "** spfd info: Using method -S 4 instead of -S 3\n");      
+      spfdSortNodes = MINFANOUT;
+    }
+  }
+  status = SpfdNetworkOptimize(network,simFile,percent,frequency,regionDepth);
+
+  finalTime = util_cpu_time();
+  if(status) {
+    (void) fprintf(vis_stdout, "%-20s%10ld\n", "** spfd info: analysis time =",
+		   (finalTime-initialTime)/1000);
+  }
+  else {
+    (void) fprintf(vis_stdout, "** spfd error: Optimization failed.\n");
+  }
+
+  if (writeFile) {
+    SpfdNetworkWriteBlifFile(network,writeFile);
+    FREE(writeFile);
+  }
+
+  if (simFile)
+    FREE(simFile);
+
+  if (spfdCreatedPart)
+    Ntk_NetworkFreeApplInfo(network,PART_NETWORK_APPL_KEY);
+  
+  alarm(0);
+  return 0;  /* normal exit */
+
+endgame:
+  /* Clean up */
+  if (simFile)
+    FREE(simFile);
+
+  if (writeFile)
+    FREE(writeFile);
+
+  if (spfdCreatedPart)
+    Ntk_NetworkFreeApplInfo(network,PART_NETWORK_APPL_KEY);
+  
+  return 1; /* Error exit */
+
+usage:
+
+  (void) fprintf(vis_stderr, "\nusage: Also see \'help spfd_pilo\' for more details.\n\n");
+  (void) fprintf(vis_stderr, "    -a <alpha>\t\t<alpha> should be between 0.0 and 1.0\n");
+  (void) fprintf(vis_stderr, "             \t\talpha*(SA*numFanout) + (1.0-alpha)*top_depth is used\n");
+  (void) fprintf(vis_stderr, "             \t\tto order nodes during SPFD computation.\n");
+  (void) fprintf(vis_stderr, "             \t\tSA is the switching activity of the node.\n");
+  (void) fprintf(vis_stderr, "             \t\tThe default value is 0.5.\n\n");
+  (void) fprintf(vis_stderr, "    -D <depth>\t\tCollect nodes that are within the specified depth.\n");
+  (void) fprintf(vis_stderr, "            \t\tfrom the node being optimized.\n");
+  (void) fprintf(vis_stderr, "            \t\tThe default is 1.\n\n");
+  (void) fprintf(vis_stderr, "    -f <filename>\tFile containing simulation vectors.\n");
+  (void) fprintf(vis_stderr, "               \t\tSee help for the format.\n\n"); 
+  (void) fprintf(vis_stderr, "    -h      \t\tCommand usage.\n\n");
+  (void) fprintf(vis_stderr, "    -i <freq> \t\tPerform internal simulations after \n");
+  (void) fprintf(vis_stderr, "            \t\tevery <freq> iterations.\n");
+  (void) fprintf(vis_stderr, "            \t\tDefault is 5.\n\n");
+  (void) fprintf(vis_stderr, "    -m <n> \t\tHeuristics to optimize a selected node:\n");
+  (void) fprintf(vis_stderr, "           \t\t0: Reduce the selected node's support.\n");
+  (void) fprintf(vis_stderr, "           \t\t1: Reprogram the selected node.\n");
+  (void) fprintf(vis_stderr, "           \t\t2: Reprogram the selected node's fanin nodes. (default)\n");
+  (void) fprintf(vis_stderr, "           \t\t3: Reduce the selected node's fanout wires.\n\n");
+  (void) fprintf(vis_stderr, "    -p <percent>\tPercent of total pattern vectors that\n");
+  (void) fprintf(vis_stderr, "            \t\tshould be used during internal simulations.\n");
+  (void) fprintf(vis_stderr, "            \t\tDefault is 10%%.\n\n");
+  (void) fprintf(vis_stderr, "    -r      \t\tDo not reprogram internal nodes if the network\n");
+  (void) fprintf(vis_stderr, "            \t\thas not changed structurally.\n");
+  (void) fprintf(vis_stderr, "            \t\tBy default, reprogram.\n\n");
+  (void) fprintf(vis_stderr, "    -S <value> \t\tHeuristic to select nodes for optimization.\n");
+  (void) fprintf(vis_stderr, "            \t\t0. Random node. (default) \n");
+  (void) fprintf(vis_stderr, "            \t\t1. Node with max. SA*numFanout.\n");
+  (void) fprintf(vis_stderr, "            \t\t2. Node with max. fanout.\n");
+  (void) fprintf(vis_stderr, "            \t\t3. Node with min. SA*numFanout.\n");
+  (void) fprintf(vis_stderr, "            \t\t4. Node with min. fanout.\n\n");
+  (void) fprintf(vis_stderr, "    -t <N>  \t\tTime (s) limit for the command.\n\n");
+  (void) fprintf(vis_stderr, "    -v <N>  \t\tVerbosity level.\n\n");  
+  (void) fprintf(vis_stderr, "    -w <filename>\tFile to output final optimized circuit.\n\n");
+  (void) fprintf(vis_stderr, "set options: \n");
+  (void) fprintf(vis_stderr, "\tspfd_repl_rem <yes|no>\n");
+  (void) fprintf(vis_stderr, "\t\tReplace and remove wires simultaneously?\n");
+  return 1;    /* error exit */
+
+} /* End of CommandSpfdNetworkOptimize */
+
+
+/**Function********************************************************************
+
+   Synopsis [Implements SPFD-based simultaneous placement and logic
+   optimization command, spfd_pdlo, for combinational circuits mapped
+   to LUT-based FPGAs.]
+
+   CommandName [spfd_pdlo]
+
+   CommandSynopsis [Perform SPFD-based simultaneous placement and
+   logic optimization.]
+
+   CommandArguments [\[-D &lt;depth&gt;\] \[-h\] \[-n &lt;file&gt;\]
+   \[-r\] \[-t &lt;sec&gt;\] \[-v &lt;n&gt;\] \[-w &lt;file&gt;\]
+   net_file arch_file place_file route_file]
+
+   CommandDescription [This command performs SPFD-based combined logic
+   and placement optimization of combinational circuits mapped to
+   LUT-based FPGAs to improve circuit area and speed. The
+   flexibilities in the circuit are represented by SPFDs. The
+   following references explain in detail the theory behind SPFDs.
+
+   <p>S. Yamashita, H. Sawada, and A. Nagoya. A new method to express
+   functional permissibilities for LUT based FPGAs and its
+   applications. In International Conference on Computer Aided Design,
+   pages 254-261, 1996.
+
+   <p>Subarnarekha Sinha and Robert K. Brayton. Implementation and use of
+   SPFDs in optimizaing Boolean networks. In International Conference
+   on Computer Aided Design, 1998.
+
+   <p>The command implements a technique that tightly links the logic
+   and placement optimization steps. The algorithm is based on
+   simulated annealing. Two types of moves, directed towards global
+   reduction in the cost function (total wire length), are accepted by
+   the simulated annealing algorithm: (1) wire removal/replacement,
+   and (2) swapping of a pair of blocks in the FPGA. Feedback from
+   placement is valuable in making an informed choice of a target wire
+   during logic optimization moves. The logic optimization steps
+   performed are similar to those of spfd_pilo, except that the
+   placement information is now used instead of the fanout count.
+   More information on this technique can be found in :
+
+   <p>Balakrishna Kumthekar and Fabio Somenzi. Power and delay reduction
+   via simultaneous logic and placement optimization in FPGAs.  In Design,
+   Automation and Test in Europe, 2000.
+
+   <p>The command produces a placement file which is used by VPR for
+   routing.
+  
+   <p>This command can be used only if VIS is linked with VPR 4.22
+   (Versatile Place and Route), the FPGA place and route tool <a
+   href="http://www.eecg.toronto.edu/~vaughn/vpr/vpr.html"> VPR</a>,
+   from the University of Toronto.  Please follow the instructions
+   provided in the release notes to use VPR with VIS.  You can also
+   contact kumtheka@avanticorp.com if you need more help.
+
+   <p>Before calling this command a network should be created for the
+   design (use flatten_hierarchy) and MDD ids for every node in the
+   network should be created (static_order -o all -n append). Dynamic
+   variable ordering (dvo -e sift) can be enabled to reduce BDD sizes.
+   
+   <p>Command options:<p>
+
+   <dl>
+
+   <dt> -D &lt;depth&gt;
+   <dd> A cluster is computed which includes nodes within the specified
+   'depth'. The default value is 1.<p>
+
+   <dt> -n &lt;file&gt;
+   <dd> File to output the optimized circuit in VPR's .net format.<p>
+
+   <dt> -r
+   <dd> Do not reprogram LUTs if no structural changes have been
+   performed with in the cluster, i.e., if no nodes or wires have been
+   removed do not change the local implementation of LUTs even if
+   alternate implementations are availabe from SPFD information. The
+   default is to reprogram. <p>
+
+   <dt> -t &lt;sec&gt;
+   <dd> Time in seconds allowed to complete the command. If the
+   computation time goes above that limit, the process is is aborted.
+   The default is no limit.<p>
+   
+   <dt> -v &lt;n&gt;
+   <dd> Verbosity level.<p>
+
+   <dt> -w &lt;file&gt;
+   <dd> File to output final optimized circuit. <p>
+   </dl>
+  
+   <p> <b>The following is needed by VPR:</b> <p>
+   <dl>
+   <dt> <b>net_file</b>
+   <dd> The description of the circuit in the .net format. Logic
+   optimization uses the circuit described in .BLIF format whereas VPR
+   needs the same circuit described in .net format. VPack (which comes
+   with VPR) converts a .BLIF format into a .net format. <p>
+
+   <dt> <b>arch_file</b>
+   <dd> Architecture description file for FPGAs. More information can be
+   found in VPR's manual. <p>
+
+   <dt> <b>place_file</b>
+   <dd> File to dump placement information. <p>
+
+   <dt> <b>route_file</b>
+   <dd> File to dump routing information. <p>
+
+   <p> <b>Relevant flags to be set by the set command:</b> <p>
+   <dl>
+   <dt> <b>spfd_pdlo_logic_move_freq</b> "r1 m1 r2 m2 ..."
+   <dd> Perform m1 logic moves whenever the rate of acceptance during
+   simulated annealing is greater than or equal to r1, and so on. r1,
+   r2, r3 ... should be monotonically decreasing, else the results would
+   be unpredictable. 0 <= ri <= 1.0. For example:
+
+   <p> <code>set spfd_pdlo_logic_move_freq "0.8 0 0.5 5 0.2 10"</code><p>
+
+   In the above logic schedule, zero logic moves per temperature will
+   be performed when the rate of acceptance is above 0.8, 5 logic
+   moves between 0.8 and 0.5, 10 moves between 0.5 and 0.2. As no
+   value is specified for acceptance rate close to 0.0, by default, 1
+   logic move per temperature will be performed. In this example it
+   will be 1 logic move between 0.2 and 0.0.
+   The quotes around the schedule are necessary.<p>
+
+   <dt> <b>spfd_repl_rem</b>
+   <dd> If <b>no</b>, the logic optimization performs only wire
+   removal. If <b>yes</b>, both wire replacement and removal are performed. <p>
+
+   <dt> <b>spfd_pdlo_timing</b>
+   <dd> If set, use timing driven method to remove or replace wires on the
+   critical path. If not set, use bounding box of the wires as the
+   cost function.<p>
+
+   <dt> <b>spfd_pdlo_timing_nodeorwire</b>
+   <dd> Remove/replace all the wires belonging to the most critical
+   net. If not set, attempt to remove/replace only the most critical
+   wire. <p>
+
+   <dt> <b>spfd_pdlo_out_crit_nets_first</b>
+   <dd> Output the circuit in VPR's .net format with the nets
+   appearing in the increasing order of their slack. If not set, the
+   initial net order specified in the original circuit's .net file is
+   used. The file is specified with <code>-n</code> option. This
+   variable is valid only if <b>spfd_pdlo_timing</b> is set. <p>
+
+   <dt> <b>spfd_pdlo_remap_clb_array</b>
+   <dd> During logic optimization, due to the removal of nodes in the
+   network, the current size of FPGA might be bigger than it is
+   necessary. In such cases, if this variable is set, the size of the
+   FPGA is reduced to fit the current logic network. <p>
+
+   </dl>
+
+   <p> <b>Relevant flags that are options to VPR:</b>
+   <p> For detailed information on the following options please refer to
+   the manual that accompanies VPR source distribution.
+   <p>
+   <dl>
+   <dt><b> vpr_nodisp</b>
+   <dt><b>vpr_fix_pins</b>
+   <dt><b>vpr_nx</b>
+   <dt><b>vpr_ny</b>
+   <dt><b>vpr_fast</b>
+   <dt><b>vpr_init_t</b>
+   <dt><b>vpr_alpha_t</b>
+   <dt><b>vpr_exit_t</b>
+   <dt><b>vpr_inner_num</b>
+   <dt><b>vpr_seet</b>
+   <dt><b>vpr_place_cost_exp</b>
+   <dt><b>vpr_place_chan_width</b>
+   </dl> ]
+
+   SideEffects [The network is changed to reflect the wires/nodes
+   removed or replaced. The internal function of the nodes is also
+   changed. The partition attached to the network is changed
+   accordingly.]
+   
+******************************************************************************/
+static int
+CommandSpfdPlaceOptimize(
+  Hrc_Manager_t **hmgr,
+  int argc,
+  char **argv)
+{
+
+#ifndef USE_VPR
+  (void) fprintf(vis_stdout,"** spfd info: This command requires VPR "
+  		 "(Versatile Place and Route)\n");
+  (void) fprintf(vis_stdout,"** spfd info: See \'help spfd_pdlo\' for more "
+		 "information\n");
+  (void) fprintf(vis_stdout,"** spfd info: on how to compile VIS with VPR.\n");
+  (void) fprintf(vis_stdout,"** spfd info: Exiting calmly ...\n");
+  return 0;
+#else
+  
+  Ntk_Network_t *network;
+  graph_t *simPart;
+  int status,regionDepth;
+  int c;
+  long timeOutPeriod,initialTime,finalTime;
+  char *writeFile;
+  char *netFile,*archFile,*placeFile,*routeFile;
+  char *netOutFile;
+  FILE *fp = NIL(FILE);
+
+
+  /* These are the default values. */
+  spfdCreatedPart = 0; /* Do not create a new partition */
+  timeOutPeriod   = 0;  
+  spfdVerbose = 0; /* verbosity */
+  regionDepth = 1; /* Depth of cluster */
+  writeFile = NIL(char); /* File to output final optimized ckt. */
+  spfdNtkChanged = FALSE;
+  spfdReprogNoWire = TRUE;
+  netFile = archFile = NIL(char); /* Circuit specified in VPR's .net
+                                     format and FPGA architecture file */
+  placeFile = routeFile = NIL(char); /* File to store placement and
+                                        routing information */
+  spfdWiresAdded = 0;
+  spfdNumWiresRem = 0;
+  netOutFile = NIL(char); /* File to output the optimized circuit in
+                             .net format */
+  status = FALSE;
+  
+  if (bdd_get_package_name() != CUDD) {
+    (void) fprintf(vis_stderr,
+		   "** spfd error: The spfd package can be used "
+		   "only with CUDD package\n");
+    (void) fprintf(vis_stderr,
+		   "** spfd error: Please link with CUDD package\n");
+    return 0;
+  }
+
+  util_getopt_reset();
+  while((c = util_getopt(argc, argv, "D:hn:rt:v:w:")) != EOF) {
+    switch(c) {
+    case 'D':
+      regionDepth = atoi(util_optarg);
+      break;
+    case 'h':
+      goto usage;
+    case 'n':
+      netOutFile = util_strsav(util_optarg);
+      break;      
+    case 'r':
+      spfdReprogNoWire = FALSE;
+      break;
+    case 't':
+      timeOutPeriod = atoi(util_optarg);
+      break;
+    case 'v':
+      spfdVerbose = atoi(util_optarg);
+      break;
+    case 'w':
+      writeFile = util_strsav(util_optarg);
+      if ((fp = Cmd_FileOpen(writeFile,"w",NIL(char *),1)) == NIL(FILE)) {
+	(void) fprintf(vis_stderr,
+		       "** spfd error: Could not open %s for writing.\n",
+		       writeFile);
+	goto endgame;
+      } else {
+	fclose(fp);
+      }
+      break;
+    default:
+      goto usage;
+    }
+  }
+
+  /* netFile, archFile, and placeFile are essential. The user can
+     specify /dev/null for routeFile if they don't want to store the
+     routing information */
+  if (argc < 5 || argc < util_optind+4)
+    goto usage;
+
+  /* Get the net, architecture, place and route file names */
+  netFile = argv[util_optind];
+  archFile = argv[util_optind+1];
+  placeFile = argv[util_optind+2];
+  routeFile = argv[util_optind+3];
+
+  if(Hrc_ManagerReadCurrentNode(*hmgr) == NIL(Hrc_Node_t)) {
+    (void) fprintf(vis_stderr,"** spfd error: The hierarchy manager is empty. "
+		   "Read in design.\n");
+    goto endgame;
+  }
+
+  network = (Ntk_Network_t *) 
+    Hrc_NodeReadApplInfo(Hrc_ManagerReadCurrentNode(*hmgr), 
+			 NTK_HRC_NODE_APPL_KEY);
+
+  if(network == NIL(Ntk_Network_t)) {
+    (void) fprintf(vis_stderr,"** spfd error: There is no network. ");
+    (void) fprintf(vis_stderr,"Use flatten_hierarchy.\n");
+    goto endgame;
+  }
+
+  /* Check if the current network has signals with multiple values. */
+  if (TestIsNetworkMultipleValued(network)) {
+    (void) fprintf(vis_stderr,"** spfd error: Circuit has multiple "
+		   "valued variables.\n");
+    (void) fprintf(vis_stderr,"** spfd error: The algorithm applies "
+		   "to Boolean variables only.\n");
+    goto endgame;
+  }
+
+  if(Ntk_NetworkReadNumPrimaryInputs(network) !=
+     Ntk_NetworkReadNumInputs(network)) {
+    (void) fprintf(vis_stderr,"** spfd error: Pseudo inputs present "
+		   "in the network.\n");
+    (void) fprintf(vis_stderr,"** spfd error: The algorithm does not apply.\n");
+    goto endgame;
+  }
+
+  /* Access a 'total' partition */
+  simPart = (graph_t *) Ntk_NetworkReadApplInfo(network, 
+						PART_NETWORK_APPL_KEY);
+  if (simPart == NIL(graph_t) || 
+      (Part_PartitionReadMethod(simPart) != Part_Total_c)) {
+    simPart = Part_NetworkCreatePartition(network, 
+					  NIL(Hrc_Node_t),
+					  "dummy", (lsList) 0, 
+					  (lsList) 0, NIL(mdd_t),
+					  Part_Total_c,
+					  (lsList) 0, 
+					  FALSE, FALSE, TRUE);
+    if (simPart == NIL(graph_t)) {
+      (void) fprintf(vis_stderr,"** spfd error: Could not create partition.\n");
+      goto endgame;
+    }
+    Ntk_NetworkAddApplInfo(network,PART_NETWORK_APPL_KEY,
+			   (Ntk_ApplInfoFreeFn)Part_PartitionFreeCallback,
+			   (void *)simPart);
+    spfdCreatedPart = 1; /* Using new partition */
+    (void) fprintf(vis_stdout,
+		   "** spfd info: A new partition created.\n");
+  }
+
+  /* Start the timer.*/
+  if (timeOutPeriod > 0){
+    (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
+    (void) alarm(timeOutPeriod);
+    if (setjmp(timeOutEnv) > 0) {
+      (void) fprintf(vis_stderr, "** spfd warning: Timeout occurred after ");
+      (void) fprintf(vis_stderr, "%ld seconds.\n", timeOutPeriod);
+      alarm(0);
+      goto endgame;
+    }
+  }
+
+  initialTime = util_cpu_time();
+
+  /* Call the optimization routine. */
+  status = SpfdSimultaneousPlacementAndLogicOpt(network,netFile,archFile,
+						placeFile,routeFile,netOutFile,
+						regionDepth);
+  
+  finalTime = util_cpu_time();
+  if(status) {
+    (void) fprintf(vis_stdout, "%-20s%10ld\n", "** spfd info: analysis time =",
+		   (finalTime-initialTime)/1000);
+  }
+  else {
+    (void) fprintf(vis_stdout, "** spfd error: Optimization failed.\n");
+  }
+
+  if (writeFile) {
+    SpfdNetworkWriteBlifFile(network,writeFile);
+    FREE(writeFile);
+  }
+
+  if (netOutFile) {
+    FREE(netOutFile);
+  }
+
+  if (spfdCreatedPart)
+    Ntk_NetworkFreeApplInfo(network,PART_NETWORK_APPL_KEY);
+  
+  alarm(0);
+  return 0;  /* normal exit */
+
+endgame:
+  /* Clean up */
+  if (writeFile)
+    FREE(writeFile);
+
+  if (netOutFile) {
+    FREE(netOutFile);
+  }
+  
+  if (spfdCreatedPart)
+    Ntk_NetworkFreeApplInfo(network,PART_NETWORK_APPL_KEY);
+  
+  return 1; /* Error exit */
+
+usage:
+
+  (void) fprintf(vis_stderr, "\nusage: Also see \'help spfd_pdlo\' for more details.\n\n");
+  (void) fprintf(vis_stderr, "spfd_pdlo [options] net_file arch_file place_file route_file\n\n");
+  (void) fprintf(vis_stderr, "    -D <depth>\t\tConsider region upto <depth>.\n\n");
+  (void) fprintf(vis_stderr, "    -h      \t\tCommand usage.\n\n");
+  (void) fprintf(vis_stderr, "    -n <filename>\tFile to output optimized\n");
+  (void) fprintf(vis_stderr, "            \t\tcircuit in .net format.\n\n");
+  (void) fprintf(vis_stderr, "    -r      \t\tDo not reprogram internal nodes if there are no\n");
+  (void) fprintf(vis_stderr, "            \t\tstructural changes in the network.\n\n");
+  (void) fprintf(vis_stderr, "    -t <N>  \t\tTime (s) limit for the command.\n\n");  
+  (void) fprintf(vis_stderr, "    -v <N>  \t\tVerbosity level.\n\n");
+  (void) fprintf(vis_stderr, "    -w <filename>\tFile to output final optimized circuit.\n\n");
+  (void) fprintf(vis_stderr, "set options: \n");
+  (void) fprintf(vis_stderr, "\tspfd_pdlo_logic_move_freq \"r1 m1 r2 m2 ...\"\n");
+  (void) fprintf(vis_stderr, "\t\tPerform m1 logic moves per temperature whenever the rate\n");
+  (void) fprintf(vis_stderr, "\t\tof acceptance during simulated annealing is greater than\n");
+  (void) fprintf(vis_stderr, "\t\tor equal to r1, and so on. r1 > r2 > r3 ... \n");
+  (void) fprintf(vis_stderr, "\t\tand 0 <= ri <= 1.0.\n\n");
+  (void) fprintf(vis_stderr, "\tspfd_repl_rem <yes|no>\n");
+  (void) fprintf(vis_stderr, "\t\tPerform both wire replacement and removal?\n\n");
+  (void) fprintf(vis_stderr, "\tspfd_pdlo_timing\n");
+  (void) fprintf(vis_stderr, "\t\tUse timing driven method.\n");
+  (void) fprintf(vis_stderr, "\t\tIf not set, Bounding box method is used.\n\n");
+  (void) fprintf(vis_stderr, "\tspfd_pdlo_timing_nodeorwire\n");
+  (void) fprintf(vis_stderr, "\t\tProcess the fanouts of the most tcritical node. If not set,\n");
+  (void) fprintf(vis_stderr, "\t\tprocess only the wires on the critical path.\n\n");
+  (void) fprintf(vis_stderr, "\tspfd_pdlo_out_crit_nets_first\n");
+  (void) fprintf(vis_stderr, "\t\tOutput the circuit in VPR\'s .net format with\n");
+  (void) fprintf(vis_stderr, "\t\tnets appearing in the increasing order of their slack.\n");
+  (void) fprintf(vis_stderr, "\t\tIf not set, the initial net order specified in the original\n");
+  (void) fprintf(vis_stderr, "\t\tcircuit\'s .net file is used. The file specified in -n option\n");
+  (void) fprintf(vis_stderr, "\t\tis used. This option is valid only if spfd_pdlo_timing is set.\n\n");
+  (void) fprintf(vis_stderr, "\tspfd_pdlo_remap_clb_array\n");
+  (void) fprintf(vis_stderr, "\t\tReduce the size of FPGA if necessary during\n");
+  (void) fprintf(vis_stderr, "\t\tlogic optimization.\n\n");
+  (void) fprintf(vis_stderr, "set options for VPR: Please see VPR's manual for more information.\n");
+  (void) fprintf(vis_stderr, "    vpr_nodisp\n");
+  (void) fprintf(vis_stderr, "    vpr_fix_pins\n");
+  (void) fprintf(vis_stderr, "    vpr_nx\n");
+  (void) fprintf(vis_stderr, "    vpr_ny\n");
+  (void) fprintf(vis_stderr, "    vpr_fast\n");
+  (void) fprintf(vis_stderr, "    vpr_init_t\n");
+  (void) fprintf(vis_stderr, "    vpr_alpha_t \n");
+  (void) fprintf(vis_stderr, "    vpr_exit_t\n");
+  (void) fprintf(vis_stderr, "    vpr_inner_num\n");
+  (void) fprintf(vis_stderr, "    vpr_seed\n");
+  (void) fprintf(vis_stderr, "    vpr_place_cost_exp\n");
+  (void) fprintf(vis_stderr, "    vpr_place_chan_width\n");
+  return 1;    /* error exit */
+#endif /* ifdef USE_VPR */
+
+} /* End of CommandSpfdPlaceOptimize */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Handle function for timeout.]
+
+  Description [This function is called when the time out occurs.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+TimeOutHandle(void)
+{
+  longjmp(timeOutEnv, 1);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether the network has multiple valued signals.]
+
+  Description [Checks whether the network has multiple valued
+  signals. Returns 1 if true, else 0.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static int
+TestIsNetworkMultipleValued(Ntk_Network_t *network)
+{
+  Ntk_Node_t *node;
+  lsGen gen;
+  Var_Variable_t *var;
+  int numValues;
+
+  Ntk_NetworkForEachNode(network,gen,node) {
+    var = Ntk_NodeReadVariable(node);
+    numValues = Var_VariableReadNumValues(var);
+    if (numValues > 2)
+      return 1;
+  }
+  return 0;
+}
+
+#ifndef USE_VPR
+/**Function********************************************************************
+ 
+  Synopsis [Dummy function]
+
+  SideEffects [None]
+
+******************************************************************************/
+static int 
+SpfdSimultaneousPlacementAndLogicOpt(
+  Ntk_Network_t *network,
+  char *netFile,
+  char *archFile,
+  char *placeFile,
+  char *routeFile,
+  char *netOutFile,
+  int regionDepth)
+{
+  return 0;
+}
+#endif
Index: vis_dev/vis-2.3/src/spfd/spfdCommon.c
===================================================================
--- vis_dev/vis-2.3/src/spfd/spfdCommon.c	(revision 14)
+++ vis_dev/vis-2.3/src/spfd/spfdCommon.c	(revision 14)
@@ -0,0 +1,557 @@
+/**CFile***********************************************************************
+
+  FileName    [spfdCommon.c]
+
+  PackageName [spfd]
+
+  Synopsis [Essential routines required during SPFD computation.]
+
+  Description [Essential routines required during SPFD computation.]
+
+  SeeAlso     [spfdSpfd.c]
+
+  Author      [Balakrishna Kumthekar]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "spfdInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static bdd_node * NodeComputeGeneralProbability(Ntk_Network_t *network, bdd_manager *ddManager, Ntk_Node_t *regNode, bdd_node *result);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis [Compute SPFDs for the nodes in regionArray, i.e., the
+  cluster. regionArray is sorted in the increasing order of
+  topological depth.]
+
+  SideEffects [None]
+
+******************************************************************************/
+void
+SpfdRegionComputeSinglePairSpfd(
+  Ntk_Network_t *network,
+  SpfdApplData_t *applData,
+  array_t *regionArray)
+{
+  Ntk_Node_t *node,*fanin,*fanout;
+  int i,j,bound,maxFanin;
+  long id;
+  int numNodes,numFanin;
+  boolean isPi,boundOrPO;
+  st_table *nodeCountTable = NIL(st_table);
+  st_table *regionNodes = applData->currRegionNodes;
+  st_table *inUseVars = applData->currInUseVars;
+  bdd_manager *ddManager = applData->ddManager;
+  bdd_node **tempVars,*spfd,*localAlt;
+  
+  numFanin = -1; /* To keep compiler happy. */
+  /* Delete node spfds when not needed */
+  nodeCountTable = st_init_table(st_ptrcmp,st_ptrhash);
+  arrayForEachItem(Ntk_Node_t *,regionArray,j,node) {
+    int num = 0;
+    Ntk_NodeForEachFanin(node,i,fanin) {
+      /* spfds for boundary nodes, PI, PO are not derived from their
+	 fanouts. */
+      if (st_lookup(regionNodes,(char *)fanin,&bound) &&
+	  !bound &&
+	  !Ntk_NodeTestIsPrimaryInput(fanin) &&
+	  !Ntk_NodeTestIsPrimaryOutput(fanin)) {
+	num++;
+      }
+    }
+    if (num) {
+      int *count;
+      count = ALLOC(int,1);
+      *count = num;
+      st_insert(nodeCountTable,(char *)node,(char *)count);
+    }
+  }
+
+  /* Allocate temporary variables that MIGHT BE required during the
+     computation of SCCs. We will allocate maxFanin temporary
+     variables. */
+  maxFanin = -1;
+  arrayForEachItem(Ntk_Node_t *,regionArray,i,node) {
+    numFanin = Ntk_NodeReadNumFanins(node);
+    if (numFanin > maxFanin)
+      maxFanin = numFanin;
+  }
+  tempVars = SpfdAllocateTemporaryVariables(ddManager,inUseVars,maxFanin);
+  
+  /* Compute spfd and localAlt for all the nodes in the region. */
+  numNodes = array_n(regionArray);
+  for (i = numNodes-1; i >= 0; i--) {
+    node = array_fetch(Ntk_Node_t *,regionArray,i);
+    st_lookup(regionNodes,(char *)node,&bound);
+
+    /* Is it a boundary node or is it primary output? For such nodes,
+       we dont not derive SPFDs from their fanouts. Their SPFDs are
+       derived from their current function impelementation */
+    boundOrPO = (bound || Ntk_NodeTestIsPrimaryOutput(node));
+    isPi = Ntk_NodeTestIsPrimaryInput(node);
+    
+    if (isPi) {
+      spfd = NIL(bdd_node);
+    } else if (boundOrPO) {
+      spfd = SpfdNodeComputeSpfdFromOnAndOffSet(applData,node,
+						  NIL(bdd_node),
+						  NIL(bdd_node));
+    } else { /* Internal node */
+      spfd = SpfdNodeComputeSpfdFromFanouts(applData,node);
+    }
+    /* Set node's spfd */
+    SpfdNodeSetSpfd(applData,node,spfd);
+    /* Set node's localAlt */
+    if (isPi) {
+      SpfdNodeSetLocalAlt(applData,node,NIL(bdd_node));
+    } else if (boundOrPO) {
+      bdd_ref(localAlt = SpfdNodeReadLocalBdd(network,node));
+      SpfdNodeSetLocalAlt(applData,node,localAlt);
+    } else { /* Internal node */
+      int numSCC;
+      st_table *SCC;
+      SCC = SpfdNodeComputeSCCs(applData,node,tempVars);
+      numSCC = st_count(SCC);
+      if (numSCC == 0) {
+	bdd_node *logicZero;
+	if (spfdVerbose > 1)
+	  (void) fprintf(vis_stdout,
+			 "** spfd info: node %s is redundant.\n",
+			 Ntk_NodeReadName(node));
+	/* Set the localAlt to empty. */
+	bdd_ref(logicZero = bdd_read_logic_zero(ddManager));
+	SpfdNodeSetLocalAlt(applData,node,logicZero);
+      } else {
+	/* Reduce the spfd to a single pair. SCC components are dereferenced in
+           the function. The localAlt is also set to one of the components of
+           the single pair */
+	SpfdNodeReduceSCCToSinglePair(applData,node,SCC);
+      }
+      st_free_table(SCC);
+    }
+    /* Clean nodeCountTable if the present node is an internal node. */
+    if (!bound &&
+	!Ntk_NodeTestIsPrimaryInput(node) &&
+	!Ntk_NodeTestIsPrimaryOutput(node)) {
+      Ntk_NodeForEachFanout(node,j,fanout) {
+	int *count;
+	if (st_lookup(nodeCountTable,(char *)fanout,&count)) {
+	  (*count)--;
+	  if (*count == 0) {
+	    st_delete(nodeCountTable,&fanout,&count);
+	    SpfdNodeDeleteSpfd(applData,fanout);
+	    FREE(count);
+	  }
+	}
+      }
+    }
+  }
+
+  /* Some of the internal nodes' spfd might not be deleted via
+     nodeCountTable. Delete them explicitly. SPFD of the first node is
+     needed. It will be deleted later in the calling function. */
+  for (i = 1; i < numNodes; i++) {
+    node = array_fetch(Ntk_Node_t *,regionArray,i);
+    SpfdNodeDeleteSpfd(applData,node);
+  }
+  /* Delete the fanin order arrays for region nodes */
+  arrayForEachItem(Ntk_Node_t *,regionArray,i,node) {
+    SpfdNodeDeleteFaninOrder(applData,node);
+  }
+  for (i = 0; i < numFanin; i++) {
+    id = (long) bdd_node_read_index(tempVars[i]);
+    st_delete(inUseVars,&id,NIL(char *));
+  }
+  FREE(tempVars);
+
+  /* Assert that nodeCountTable is empty */
+  assert(st_count(nodeCountTable) == 0);
+  st_free_table(nodeCountTable);
+
+  return;
+
+} /* End of SpfdRegionComputeSinglePairSpfd */
+
+
+/**Function********************************************************************
+
+  Synopsis [Collapse the SCCs in a node's SPFD into a binary SPFD by
+  appropriately choosing a binary value associated with each of the
+  SCCs. This function is used only when signal probabilites are known,
+  i.e, only when vector simulation is performed. 'result' is the
+  characteristic function of the set of SCCs combined with the
+  parameters. For example, if {(E1_i,E0_i)} is the set of bipartite SCCs,
+
+  result(Y,P) = \sum (p_i*E1_i + \bar{p}_i*E0_i). This function computes
+  assignments to p_i such that the 'result' has lower switching
+  activity than the previous implementation at regNode.]
+
+  SideEffects [None]
+
+******************************************************************************/
+bdd_node *
+SpfdNodeComputeOptParams(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *regNode,
+  bdd_node *result,
+  bdd_node **parameters,
+  int numIsfs)
+{
+  bdd_manager *ddManager = applData->ddManager;
+  Ntk_Network_t *network = Ntk_NodeReadNetwork(regNode);
+  bdd_node *genProb,*offGenProb;
+  bdd_node *diff,*maxDiff,*optComb;
+  bdd_node *ddTemp,*prevSwitching,*newSwitching;
+  float prob,switching;
+  
+  /* Compute the new node probability in terms of parameters introduced */
+  genProb = NodeComputeGeneralProbability(network,ddManager,regNode,result);
+  bdd_ref(offGenProb = bdd_add_apply(ddManager,bdd_add_minus,
+				     bdd_read_one(ddManager),genProb));
+  bdd_ref(newSwitching = bdd_add_apply(ddManager,bdd_add_times,
+				       genProb,offGenProb));
+  bdd_recursive_deref(ddManager,genProb);
+  bdd_recursive_deref(ddManager,offGenProb);
+  
+  /* Compute the previous power dissipated */
+  ddTemp = SpfdNodeReadLocalBdd(network,regNode);
+  prob = Truesim_BddNodeComputeProbability(network,ddTemp);
+  switching = prob*(1.0-prob);
+  bdd_ref(prevSwitching = bdd_add_const(ddManager,switching));
+
+  /* Find the combination of parameters that give max power savings,
+     i.e. max(prevPowerAdd - newPowerAdd) */
+  bdd_ref(diff = bdd_add_apply(ddManager,bdd_add_minus,prevSwitching,
+			       newSwitching));
+  bdd_recursive_deref(ddManager,prevSwitching);
+  bdd_recursive_deref(ddManager,newSwitching);
+
+  /* Find the max. difference */
+  bdd_ref(maxDiff = bdd_add_find_max(ddManager,diff));
+
+  if (bdd_add_value(maxDiff) <= 0.0) {
+    bdd_recursive_deref(ddManager,diff);
+    bdd_recursive_deref(ddManager,maxDiff);
+
+    optComb = NIL(bdd_node);
+  } else {
+    /* Find minterms with max. difference */
+    bdd_ref(optComb = bdd_add_apply(ddManager,SpfdAddEqual,maxDiff,diff));
+    bdd_recursive_deref(ddManager,maxDiff);
+    bdd_recursive_deref(ddManager,diff);
+
+    /* optComb (an ADD) can be a cube, i.e., more than one
+       minterm. Pick a minterm. Convert optComb to a BDD */
+    bdd_ref(maxDiff = bdd_add_bdd_threshold(ddManager,optComb,(double) 1.0));
+    bdd_recursive_deref(ddManager,optComb);
+    optComb = maxDiff;
+
+    /* Pick one cube */
+    bdd_ref(maxDiff = bdd_bdd_pick_one_minterm(ddManager,optComb,parameters,
+					       numIsfs));
+    bdd_recursive_deref(ddManager,optComb);
+    optComb = maxDiff;
+  }
+
+  return optComb;
+  
+} /* End of SpfdNodeComputeOptParams */
+
+
+/**Function********************************************************************
+
+  Synopsis [Reduce the set of SCCs in a SPFD to a single SCC, i.e, to
+  reduce to a binary SPFD. ]
+
+  SideEffects [None]
+
+******************************************************************************/
+void
+SpfdNodeReduceSCCToSinglePair(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *regNode,
+  st_table *SCC)
+{
+  Ntk_Network_t *network = Ntk_NodeReadNetwork(regNode);
+  st_table *inUseVars = applData->currInUseVars;
+  bdd_manager *ddManager = applData->ddManager;
+  bdd_node **parameters;
+  bdd_node *bdd1,*bdd0,*result,*spfd;
+  bdd_node *optComb;
+  st_generator *stGen;
+  int numIsfs;
+  int i;
+  long lid;
+
+  numIsfs = st_count(SCC);
+  /* Allocate numIsfs binary valued parameters, one for each SCC. */
+  parameters = SpfdComputeParameters(applData,SCC);
+
+  /* Compute the general form representation for the local alternate
+     function */
+  bdd_ref(result = bdd_read_logic_zero(ddManager));
+  i = 0;
+  st_foreach_item(SCC,stGen,&bdd1,&bdd0) {
+    bdd_node *ddTemp,*ddTemp2;
+    bdd_ref(ddTemp = bdd_bdd_ite(ddManager,parameters[i],bdd1,bdd0));
+    bdd_recursive_deref(ddManager,bdd1);
+    bdd_recursive_deref(ddManager,bdd0);
+    bdd_ref(ddTemp2 = bdd_bdd_or(ddManager,ddTemp,result));
+    bdd_recursive_deref(ddManager,ddTemp);
+    bdd_recursive_deref(ddManager,result);
+    result = ddTemp2;
+    i++;
+  }
+
+  if (!spfdPerfSim) { /* No switching activity info. available */
+    /* Choose one combination of parameters */
+    bdd_ref(optComb = bdd_bdd_compute_cube(ddManager,parameters,
+					   NIL(int),numIsfs));
+  } else {
+    /* Compute the combination of parameters that reduce switching */
+    optComb = SpfdNodeComputeOptParams(applData,regNode,result,
+				       parameters,numIsfs);
+  }
+
+  if (optComb) { /* If such a combination exists */
+    bdd_node *E1y,*E0y; /* BDDs for the care ON-set and care OFF-set,
+			   respectively,  of the optimal ISF found in the
+			   previous step. */
+    bdd_node *imgOptComb;
+    bdd_node **notParams;
+    int size,i,id;
+
+    /* Compute the lhs (care ON-set) of the ISF */
+    bdd_ref(E1y = bdd_bdd_cofactor(ddManager,result,optComb));
+    /* Compute the rhs (care OFF-set) of the ISF */
+    size = bdd_num_vars(ddManager);
+    notParams = ALLOC(bdd_node *,size);
+    for (i = 0; i < size; i++) {
+      bdd_ref(notParams[i] = bdd_bdd_ith_var(ddManager,i));
+    }
+    for (i = 0; i < numIsfs; i++) {
+      id = bdd_node_read_index(parameters[i]);
+      bdd_recursive_deref(ddManager,notParams[id]);
+      bdd_ref(notParams[id] = bdd_not_bdd_node(parameters[i]));
+    }
+    bdd_ref(imgOptComb = bdd_bdd_vector_compose(ddManager,optComb,notParams));
+    bdd_recursive_deref(ddManager,optComb);
+    bdd_ref(E0y = bdd_bdd_cofactor(ddManager,result,imgOptComb));
+    bdd_recursive_deref(ddManager,result);
+    bdd_recursive_deref(ddManager,imgOptComb);
+
+    /* Compute the spfd of E1y and E0y */
+    spfd = SpfdNodeComputeSpfdFromOnAndOffSet(applData,regNode,E1y,E0y);
+    SpfdNodeDeleteSpfd(applData,regNode);
+    SpfdNodeSetSpfd(applData,regNode,spfd);
+
+    /* Set E1y as the localAlt */
+    SpfdNodeSetLocalAlt(applData,regNode,E1y);
+    bdd_recursive_deref(ddManager,E0y);
+    
+    /* Free notParams */
+    for (i = 0; i < size; i++) {
+      bdd_recursive_deref(ddManager,notParams[i]);
+    }
+    FREE(notParams);
+  } else { /* Compute alternate spfd from local function */
+    bdd_node *bdd1,*bdd0;
+    bdd_recursive_deref(ddManager,result);
+
+    /* Set localAlt Bdd */
+    bdd_ref(bdd1 = SpfdNodeReadLocalBdd(network,regNode));
+    bdd_ref(bdd0 = bdd_not_bdd_node(bdd1));
+
+    /* Set the new spfd */
+    spfd = SpfdNodeComputeSpfdFromOnAndOffSet(applData,regNode,bdd1,bdd0);
+    SpfdNodeDeleteSpfd(applData,regNode);
+    SpfdNodeSetSpfd(applData,regNode,spfd);
+
+    /* Set bdd1 as the localAlt */
+    SpfdNodeSetLocalAlt(applData,regNode,bdd1);
+    bdd_recursive_deref(ddManager,bdd0);
+  }
+
+  /* Free the parameters */
+  for (i = 0; i < numIsfs; i++) {
+    lid = (long) bdd_node_read_index(parameters[i]);
+    st_delete(inUseVars,&lid,NIL(char *));
+  }
+  FREE(parameters);
+  
+  return;
+  
+} /* End of SpfdNodeReduceSCCToSinglePair */
+
+
+/**Function********************************************************************
+
+  Synopsis [Global BDDs are required during the computation of SPFDs
+  for cluster members. We compute them once and use it when
+  needed. Also, these BDDs are removed when they are no longer
+  required. Gloabl BDDs are required for all nodes in the cluster and
+  their respective fanin nodes.]
+
+  SideEffects [None]
+
+******************************************************************************/
+void
+SpfdComputeRequiredGlobalBdds(
+  Ntk_Network_t *network,
+  SpfdApplData_t *applData)
+{
+  st_table *regionNodes,*rootTable,*leavesTable;
+  st_table *currBddReq;
+  array_t *rootArray,*nodeMvfs;
+  st_generator *stGen;
+  Ntk_Node_t *node,*fanin;
+  char *dummy;
+  int i;
+  lsGen gen;
+  bdd_t *mddOne;
+  bdd_node *bdd1;
+  bdd_manager *ddManager = applData->ddManager;
+  mddOne = bdd_one(ddManager);
+
+  /* Collect cluster nodes and also their fanin nodes */
+  regionNodes = applData->currRegionNodes;
+  rootTable = st_init_table(st_ptrcmp,st_ptrhash);
+  st_foreach_item(regionNodes,stGen,&node,&dummy) {
+    Ntk_NodeForEachFanin(node,i,fanin) {
+      st_insert(rootTable,(char *)fanin,(char *)-1);
+    }
+  }
+
+  /* Convert rootTable to rootArray for use by Ntm_NetworkBuildMvfs */
+  rootArray = array_alloc(Ntk_Node_t *,0);
+  st_foreach_item(rootTable,stGen,&node,&dummy) {
+    array_insert_last(Ntk_Node_t *,rootArray,node);
+  }
+  st_free_table(rootTable);
+  
+  /* Collect the leaf nodes in the network. */
+  leavesTable = st_init_table(st_ptrcmp, st_ptrhash);
+  Ntk_NetworkForEachCombInput(network,gen,node) {
+    st_insert(leavesTable,(char *)node,(char *) -1);
+  }
+
+  /* Compute the Mvfs for the nodes in rootArray */
+  nodeMvfs = Ntm_NetworkBuildMvfs(network,rootArray,leavesTable,mddOne);
+  bdd_free(mddOne);
+  st_free_table(leavesTable);
+  
+  /* Extract the BDDs and put them in currBddReq */
+  currBddReq = applData->currBddReq = st_init_table(st_ptrcmp,st_ptrhash);
+  arrayForEachItem(Ntk_Node_t *,rootArray,i,node) {
+    Mvf_Function_t *mvf;
+    mvf = array_fetch(Mvf_Function_t *,nodeMvfs,i);
+    bdd1 = bdd_extract_node_as_is(array_fetch(bdd_t *,mvf,1));
+    bdd_ref(bdd1);
+    st_insert(currBddReq,(char *)node,(char *)bdd1);
+  }
+  array_free(rootArray);
+  Mvf_FunctionArrayFree(nodeMvfs);
+
+  return;
+
+} /* End of SpfdComputeRequiredGlobalBdds */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis [Returns the ADD representing the signal probability of
+  regNode. 'result' is the BDD which has in support the variables in
+  the fanin of regNode.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static bdd_node *
+NodeComputeGeneralProbability(
+  Ntk_Network_t *network,
+  bdd_manager *ddManager,
+  Ntk_Node_t *regNode,
+  bdd_node *result)
+{
+  int size,k,id;
+  bdd_node **onArray,**offArray;
+  bdd_node *resultAdd,*genProb;
+  Ntk_Node_t *fanin;
+  float prob;
+  
+  size = bdd_num_vars(ddManager);
+  onArray = ALLOC(bdd_node *,size);
+  offArray = ALLOC(bdd_node *,size);
+  for (k = 0; k < size; k++) {
+    bdd_ref(onArray[k] = bdd_add_ith_var(ddManager,k));
+    bdd_ref(offArray[k] = bdd_add_ite(ddManager,onArray[k],
+				      bdd_read_zero(ddManager),
+				      bdd_read_one(ddManager)));
+  }
+  
+  Ntk_NodeForEachFanin(regNode,k,fanin) {
+    id = Ntk_NodeReadMddId(fanin);
+    bdd_recursive_deref(ddManager,onArray[id]);
+    bdd_recursive_deref(ddManager,offArray[id]);
+    prob = Truesim_NetworkReadNodeProbability(network,fanin);
+    bdd_ref(onArray[id] = bdd_add_const(ddManager,prob));
+    bdd_ref(offArray[id] = bdd_add_const(ddManager,1.0-prob));
+  }
+
+  bdd_ref(resultAdd = bdd_bdd_to_add(ddManager,result));
+  genProb = (bdd_node *)bdd_add_general_vector_compose(ddManager,resultAdd,
+						      onArray,offArray);
+  bdd_ref(genProb);
+  bdd_recursive_deref(ddManager,resultAdd);
+
+  return genProb;
+  
+} /* End of NodeComputeGeneralProbability */
Index: vis_dev/vis-2.3/src/spfd/spfdInt.h
===================================================================
--- vis_dev/vis-2.3/src/spfd/spfdInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/spfd/spfdInt.h	(revision 14)
@@ -0,0 +1,248 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [spfdInt.h]
+
+  PackageName [spfd]
+
+  Synopsis    [Internal data structures for the spfd package.]
+
+  Description [Internal data structures for the spfd package.]
+
+  SeeAlso     [spfd.h]
+
+  Author      [Balakrishna Kumthekar] 
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#ifndef _SPFDINT
+#define _SPFDINT
+
+#include "part.h"
+#include "ntm.h"
+#include "cmd.h"
+#include "spfd.h"
+#include "truesim.h"
+#include <string.h>
+
+#ifdef USE_VPR
+#include "vpr.h"
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define SPFD_NETWORK_APPL_KEY "Spfd_NetworkApplKey"
+/* Methods to sort nodes during logic optimization. */
+#define RANDOM 0 /* Choose a network node randomly */
+#define MAXSWCAP 1 /* Choose the node that has the maximum switched capacitance.
+		      Switched capacitance is the product of the node's output
+		      capacitance (approximated by the fanout count) and the
+		      average switching acitivity (switching probability). */
+#define MAXFANOUT 2 /* Choose the node with maximum fanout */
+#define MINSWCAP 3 /* Choose the node with minimum switched capacitance */
+#define MINFANOUT 4 /* Choose the node with minimum fanout */
+
+/* Methods of optimizing the selected node */
+#define REDUCE_FANIN_WIRES 0 /* Fanin wires of the selected node are selected
+				one at a time to attempt to remove it. */
+#define OPTIMIZE_MAX_NODE 1 /* Compute a suitable alternate implementation at
+			       the selected node. */
+#define OPTIMIZE_FANIN_NODES 2 /* Compute a suitable alternate implementation at
+			       the fanin nodes of the selected node. */
+#define REDUCE_FANOUT_WIRES 3 /* Attempt to remove fanout wires of the
+				 selected node. */
+
+/* Used during random value generation */
+#define MODULUS1 2147483563
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis [Data structure used during simultaneous logic and
+  placement optimization.]
+
+  Description [Data structure used during simultaneous logic and
+  placement optimization. This data structure stores information
+  extracted from the data structures in VPR.]
+
+  SeeAlso     [SpfdNodeData_t]
+
+******************************************************************************/
+typedef struct SpfdPlaceData_t {
+  st_table *nodeToNetIndex; /* Table to store the index of net in nets[] (VPR)*/
+  st_table *wireDelayTable; /* Table to store wire delays */
+  st_table *nodeDelayTable; /* Table to store node delays */
+  st_table *wireSeen; /* Wires processed. Used only in timing-based method */
+} SpfdPlaceData_t;
+
+
+/**Struct**********************************************************************
+
+  Synopsis [The package application data structure.]
+
+  Description [The package application data structure. This data
+  structure is hooked to the network for easy access.]
+
+  SeeAlso     [SpfdPlaceData_t SpfdNodeData_t]
+
+******************************************************************************/
+typedef struct SpfdApplData_t {
+  bdd_manager *ddManager; /* BDD manager */
+  bdd_node *currXCube; /* BDD of cube of primary inputs that are in the
+			  transitive fanin of the network region under
+			  optimization.   */
+  st_table *nodeToData; /* Table of node and SpfdNodeData_t */
+  st_table *currRegionNodes; /* internal and boundary nodes of the region.
+				The region under consideration includes nodes
+				(upto a user specified depth) in the
+				transitive fanout of the selected node. */
+  st_table *currBddReq; /* BDDs of the nodes in the current region */
+  st_table *currInUseVars; /* BDD variable IDs currently in use. This is
+			      necessary because we reuse previously allocated
+			      BDD IDs. */
+  st_table *currPiAltVars; /* Extra (auxillary variables) BDD variable IDs
+			      for PIs in the transitive fanin of the region */
+  st_table *currWireTable; /* Table to store wires that can be removed */
+  st_table *currReplaceTable; /* Table to store wires that can be replaced */
+  st_table *wiresRemoved; /* Table to store wires that have been removed */
+  st_table *nodesRemoved; /* Table to store nodes that can be removed */
+  SpfdPlaceData_t *placeData; /* Struct to store placement data */
+} SpfdApplData_t;
+
+
+/**Struct**********************************************************************
+
+  Synopsis [Data structure to store additional information in a node.]
+
+  Description [Data structure to store additional information in a
+  node. The information stored is derived while computing SPFDs in the
+  network.]
+
+  SeeAlso     [SpfdPlaceData_t]
+
+******************************************************************************/
+typedef struct SpfdNodeData_t {
+  bdd_node *spfd; /* Node SPFD */
+  bdd_node *localAlt; /* An alternate function (implementation) chosen from
+			 the node's SPFD */
+  bdd_node *alternative; /* localAlt in terms of primary inputs */
+  bdd_node **parameters; /* Binary parameters used during SPFD computation*/
+  int numParams; /* size of parameters */
+  array_t *faninOrder; /* Order of fanin nodes. The SPFDs for fanin nodes are
+			  assigned according to this order. */
+  int auxId; /* Two sets of variables are required to represent
+                SPFDs. mddId of the node is one, and auxId is the
+                other. */
+  boolean locked; /* Set to TRUE after the node is optimized */
+} SpfdNodeData_t;
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+extern int spfdCreatedPart; /* Whether network BDDs were created in the package */
+extern int spfdVerbose; /* verbosity */
+extern float spfdAlpha; /* spfdAlpha * load + (1-spfdAlpha) * topDepth, is used to order
+                fanin nodes during SPFD computation */
+extern boolean spfdPerfSim; /* Perform simulation */
+extern boolean spfdNtkChanged; /* TRUE if network changes structurally or functionally */
+extern boolean spfdReprogNoWire; /* If TRUE, no functional changes are performed
+                         unless required by structural changes */
+extern int spfdWiresAdded, spfdNumWiresRem; /* Number of wires added and removed */
+extern int spfdSortNodes; /* Method to sort nodes */
+extern int spfdMethod; /* Optimization method */
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN boolean SpfdNodeReadLocked(SpfdApplData_t *applData, Ntk_Node_t *node);
+EXTERN int SpfdNodeReadAuxId(SpfdApplData_t *applData, Ntk_Node_t *node);
+EXTERN void SpfdNodeSetAuxId(SpfdApplData_t *applData, Ntk_Node_t *node, int auxId);
+EXTERN bdd_node * SpfdNodeReadSpfd(SpfdApplData_t *applData, Ntk_Node_t *node);
+EXTERN void SpfdNodeDeleteSpfd(SpfdApplData_t *applData, Ntk_Node_t *node);
+EXTERN void SpfdNodeSetSpfd(SpfdApplData_t *applData, Ntk_Node_t *node, bdd_node *spfd);
+EXTERN bdd_node ** SpfdNodeReadParameters(SpfdApplData_t *applData, Ntk_Node_t *node);
+EXTERN void SpfdNodeDeleteParameters(SpfdApplData_t *applData, Ntk_Node_t *node);
+EXTERN void SpfdNodeSetParameters(SpfdApplData_t *applData, Ntk_Node_t *node, bdd_node **parameters, int numParams);
+EXTERN array_t * SpfdNodeReadFaninOrder(SpfdApplData_t *applData, Ntk_Node_t *node);
+EXTERN void SpfdNodeDeleteFaninOrder(SpfdApplData_t *applData, Ntk_Node_t *node);
+EXTERN void SpfdNodeSetFaninOrder(SpfdApplData_t *applData, Ntk_Node_t *node, array_t *faninOrder);
+EXTERN bdd_node * SpfdNodeReadGlobalAlternative(SpfdApplData_t *applData, Ntk_Node_t *node);
+EXTERN void SpfdNodeDeleteGlobalAlternative(SpfdApplData_t *applData, Ntk_Node_t *node);
+EXTERN void SpfdNodeSetGlobalAlternative(SpfdApplData_t *applData, Ntk_Node_t *node, bdd_node *alternative);
+EXTERN bdd_node * SpfdNodeReadLocalAlt(SpfdApplData_t *applData, Ntk_Node_t *node);
+EXTERN void SpfdNodeDeleteLocalAlt(SpfdApplData_t *applData, Ntk_Node_t *node);
+EXTERN void SpfdNodeSetLocalAlt(SpfdApplData_t *applData, Ntk_Node_t *node, bdd_node *localAlt);
+EXTERN void SpfdNodeSetLocked(SpfdApplData_t *applData, Ntk_Node_t *node, boolean locked);
+EXTERN int SpfdNodeReadNumParams(SpfdApplData_t *applData, Ntk_Node_t *node);
+EXTERN int SpfdNodeReadNetIndex(SpfdApplData_t *applData, Ntk_Node_t *node);
+EXTERN void SpfdApplFreeCallback(void *data);
+EXTERN enum st_retval SpfdStBddFree(char *key, char *value, char *arg);
+EXTERN enum st_retval SpfdStTableClean(char *key, char *value, char *arg);
+EXTERN void SpfdReleaseAndCleanNodeData(SpfdApplData_t *applData, Ntk_Node_t *regNode, st_table *nodeTable);
+EXTERN void SpfdReleaseAlternatePiIds(SpfdApplData_t *applData, Ntk_Node_t *regNode, st_table *nodeTable);
+EXTERN void SpfdCleanUpAuxIds(SpfdApplData_t *applData);
+EXTERN void SpfdRegionComputeSinglePairSpfd(Ntk_Network_t *network, SpfdApplData_t *applData, array_t *regionArray);
+EXTERN bdd_node * SpfdNodeComputeOptParams(SpfdApplData_t *applData, Ntk_Node_t *regNode, bdd_node *result, bdd_node **parameters, int numIsfs);
+EXTERN void SpfdNodeReduceSCCToSinglePair(SpfdApplData_t *applData, Ntk_Node_t *regNode, st_table *SCC);
+EXTERN void SpfdComputeRequiredGlobalBdds(Ntk_Network_t *network, SpfdApplData_t *applData);
+EXTERN int SpfdNetworkOptimize(Ntk_Network_t *network, char *simFile, int percent, int frequency, int regionDepth);
+EXTERN void SpfdProcessFanoutWires(Ntk_Network_t *network, Ntk_Node_t *maxNode, int regionDepth, boolean replRem);
+EXTERN Ntk_Node_t * SpfdCheckIfWireIsRedundantOrReplaceable(Ntk_Network_t *network, SpfdApplData_t *applData, Ntk_Node_t *from, Ntk_Node_t *to, array_t *replaceArray);
+EXTERN Ntk_Node_t * SpfdTestIfNodeGlobalFuncSatisfiesWireSpfd(Ntk_Network_t *network, array_t *replaceArray, Ntk_Node_t *from, Ntk_Node_t *to, bdd_node *wireSpfd);
+EXTERN void SpfdOptimizeFaninWires(Ntk_Network_t *network, Ntk_Node_t *maxNode, int regionDepth, boolean replRem);
+EXTERN void SpfdOptimizeFanoutWires(Ntk_Network_t *network, Ntk_Node_t *maxNode, int regionDepth, boolean replRem);
+EXTERN void SpfdOptimizeFaninNodes(Ntk_Network_t *network, Ntk_Node_t *maxNode, int regionDepth);
+EXTERN void SpfdOptimizeWire(Ntk_Network_t *network, Ntk_Node_t *maxNode, Ntk_Node_t *ntkNode, int regionDepth, boolean replRem);
+EXTERN void SpfdOptimizeNode(Ntk_Network_t *network, Ntk_Node_t *ntkNode, int regionDepth);
+EXTERN void SpfdReprogramRegionNodes(Ntk_Network_t *network, SpfdApplData_t *applData, array_t *regionArray);
+EXTERN void SpfdReprogramNode(Ntk_Network_t *network, SpfdApplData_t *applData, Ntk_Node_t *regNode);
+EXTERN void SpfdNetworkRemoveWire(Ntk_Network_t *network, Ntk_Node_t *from, Ntk_Node_t *to);
+EXTERN void SpfdNetworkAddWire(Ntk_Network_t *network, Ntk_Node_t *from, Ntk_Node_t *to);
+EXTERN array_t * SpfdNodeComputeFanoutRegion(SpfdApplData_t *applData, Ntk_Node_t *startNode, int regionDepth);
+EXTERN array_t * SpfdNodeComputeTFIUntilDepth(Ntk_Node_t *startNode, int regionDepth);
+EXTERN void SpfdNodesInTFO(Ntk_Network_t *network, Ntk_Node_t *node, st_table *tfoNodes);
+EXTERN bdd_node * SpfdNodeComputeSpfdFromOnAndOffSet(SpfdApplData_t *applData, Ntk_Node_t *regNode, bdd_node *bdd1, bdd_node *bdd0);
+EXTERN bdd_node * SpfdNodeComputeSpfdFromFanouts(SpfdApplData_t *applData, Ntk_Node_t *from);
+EXTERN st_table * SpfdNodeComputeSCCs(SpfdApplData_t *applData, Ntk_Node_t *regNode, bdd_node **tempVars);
+EXTERN SpfdApplData_t * SpfdInitializeApplData(Ntk_Network_t *network);
+EXTERN bdd_node ** SpfdComputeParameters(SpfdApplData_t *applData, st_table *SCC);
+EXTERN bdd_node ** SpfdAllocateTemporaryVariables(bdd_manager *ddManager, st_table *inUseVars, int num);
+EXTERN void SpfdAllocateOrReuseAuxVariables(Ntk_Network_t *network, SpfdApplData_t *applData);
+EXTERN void SpfdOrderFaninOfRegionNodes(Ntk_Network_t *network, SpfdApplData_t *applData, int (*compareFunc)(const void *, const void *));
+EXTERN int SpfdSwitchedCapAndDepthCompare(const void *obj1, const void *obj2);
+EXTERN int SpfdFanoutCountAndDepthCompare(const void *obj1, const void *obj2);
+EXTERN int SpfdDepthCompare(const void *obj1, const void *obj2);
+EXTERN int SpfdDescendDepthCompare(const void *obj1, const void *obj2);
+EXTERN void SpfdMddCreateVariables(mdd_manager *mgr, int numVarsToBeAdded, int level);
+EXTERN bdd_node * SpfdAddEqual(bdd_manager *ddManager, bdd_node **f, bdd_node **g);
+EXTERN int SpfdNetworkWriteBlifFile(Ntk_Network_t *network, char *fileName);
+EXTERN bdd_node * SpfdComputeNodeArrayRelation(SpfdApplData_t *applData, st_table *currBddReq, array_t *nodeBdds, array_t *nodeArray, boolean useMddIds, int *piSwap);
+EXTERN bdd_node * SpfdSwapPiAndAltPi(SpfdApplData_t *applData, bdd_node *fun);
+EXTERN bdd_node * SpfdNodeReadLocalBdd(Ntk_Network_t *network, Ntk_Node_t *node);
+EXTERN array_t * SpfdFetchInternalPatternArray(array_t *patternArray, int percent, double randomValue);
+EXTERN Ntk_Node_t * SpfdFindNode(Ntk_Network_t *network, array_t *nodeArray);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _SPFDINT */
Index: vis_dev/vis-2.3/src/spfd/spfdOpt.c
===================================================================
--- vis_dev/vis-2.3/src/spfd/spfdOpt.c	(revision 14)
+++ vis_dev/vis-2.3/src/spfd/spfdOpt.c	(revision 14)
@@ -0,0 +1,1317 @@
+/**CFile***********************************************************************
+
+  FileName    [spfdOpt.c]
+
+  PackageName [spfd]
+
+  Synopsis [Routines that implement spfd_pilo.]
+
+  Description [Routines that implement spfd_pilo.]
+
+  SeeAlso     [spfdCmd.c spfdReg.c spfdProg.c]
+
+  Author      [Balakrishna Kumthekar]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "spfdInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CompareConvexFanoutCountAndDepth(const void *obj1, const void *obj2);
+static int CompareConvexSwitchedCapAndDepth(const void *obj1, const void *obj2);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis [Optimize the network by performing wire/node removal, wire
+  replacement and LUT reprogramming to reduce the number of wires and
+  nodes and the overall switching activity of the circuit.]
+
+  Description [Optimize the network by performing wire/node removal,
+  wire replacement and LUT reprogramming to reduce the number of wires
+  and nodes and the overall switching activity of the circuit. The
+  algorithm iteratively selects a node, 'maxNode', (based on the
+  heuristic selected) and examines all the fanout/fanin wires to determine
+  if any one them can be removed or replaced by another wire. For each
+  wire selected, fanout cluster if computed up to a depth
+  'regionDepth'. SPFD are computed only for these cluster nodes. Any
+  wire, internal to the cluster, that has an empty SPFD is
+  removed. Cluster nodes are then reprogrammed by choosing an
+  alternative implementation derived from the node SPFD.
+
+  After the cluster nodes are optimized, 'maxNode' is locked and is not
+  optimized in future iterations. The algorithm ends when there are no
+  more nodes to be optimized.
+
+  The argument 'simFile' (if not NULL) specifies the vectors used to
+  simulate the circuit in order to compute circuit node switching
+  activity. Vector simulations are performed every 'frequency'
+  iterations. 'regionDepth' specifies the depth of the cluster from
+  the 'maxNode'.]
+  
+  SideEffects [None]
+
+******************************************************************************/
+int
+SpfdNetworkOptimize(
+  Ntk_Network_t *network,
+  char *simFile,
+  int percent,
+  int frequency,
+  int regionDepth)
+{
+  SpfdApplData_t *applData;
+  Ntk_Node_t *node,*maxNode;
+  int stop,iter,status;
+  float randomValue;
+  array_t *nodeArray;
+  lsGen gen;
+  st_generator *stGen;
+  char *dummy;
+  boolean replRem;
+  array_t *inputArray,*patternArray,*intPatternArray;
+  char *optName;
+  
+  /* To keep the compiler happy */
+  inputArray = patternArray = intPatternArray = NIL(array_t);
+
+  /* Check if both wire removal and replacement are to be done */
+  optName = Cmd_FlagReadByName("spfd_repl_rem");
+  if (optName && (strcmp(optName,"yes") == 0)) {
+    replRem = TRUE;
+  } else {
+    replRem = FALSE;
+  }
+
+  /* First initialize the simulation package. This will also levelize
+     the nodes in the network. The level info is stored in local data
+     structure of 'truesim' package'. This is needed even if we do not
+     perform vector simulation. */
+  Truesim_InitializeSimulation(network,NIL(char),0,-1,0,NIL(st_table));
+  if (spfdPerfSim) { /* Perform simulation? */
+    /* Array of primary input nodes */
+    inputArray = array_alloc(Ntk_Node_t *,0);
+    /* Array of simulation vectors */
+    patternArray = array_alloc(char *,0);
+    status = Truesim_ReadSimulationVectors(network,simFile,
+					   inputArray,patternArray);
+    /* Error while reading simulation vectors */
+    if (!status) {
+      array_free(inputArray);
+      array_free(patternArray);
+      (void) fprintf(vis_stdout, "** spfd error: Error reading simulation"
+		     " vector file. \n");
+      return 0;
+    }
+    Truesim_ZeroDelayPatternSimulate(network,inputArray,patternArray);
+
+    /* Select a random start for the set of internal simulation
+       vectors. We simulate only a portion of vectors (during
+       optimization iterations) to get a coarse estimate of circuit
+       node switching activities. */
+    randomValue = ((double)util_random()/(double)(MODULUS1 - 2));
+    if (randomValue > (double) (1.0 - ((double)percent)/((double)100)))
+      randomValue = (1.0 - ((double)percent)/((double)100))/2.0;
+    /* Partial set of simulation vectors */
+    intPatternArray = SpfdFetchInternalPatternArray(patternArray,percent,
+						    randomValue);
+  }
+  
+  /* Initialize the package application data structure */
+  applData = SpfdInitializeApplData(network);
+  iter = 1;
+
+  do {
+    if (spfdVerbose > 2) {
+      (void) fprintf(vis_stdout, "** spfd info: Iteration %d\n",iter);
+    }
+    nodeArray = array_alloc(Ntk_Node_t *,0);
+
+    /* Collect circuit nodes, later needed to be sorted. Only the
+       internal nodes will be sorted.*/
+    switch (spfdMethod) {
+    case REDUCE_FANIN_WIRES:
+    case OPTIMIZE_MAX_NODE:
+      Ntk_NetworkForEachNode(network,gen,node) {
+	if (!Ntk_NodeTestIsPrimaryOutput(node) &&
+	    !Ntk_NodeTestIsPrimaryInput(node) &&
+	    !SpfdNodeReadLocked(applData,node)) 
+	  array_insert_last(Ntk_Node_t *,nodeArray,node);
+      }
+      break;
+    case OPTIMIZE_FANIN_NODES:
+      Ntk_NetworkForEachNode(network,gen,node) {
+	if (!Ntk_NodeTestIsPrimaryInput(node) &&
+	    !SpfdNodeReadLocked(applData,node)) 
+	  array_insert_last(Ntk_Node_t *,nodeArray,node);
+      }
+      break;
+    case REDUCE_FANOUT_WIRES:
+      Ntk_NetworkForEachNode(network,gen,node) {
+	if (!SpfdNodeReadLocked(applData,node)) 
+	  array_insert_last(Ntk_Node_t *,nodeArray,node);
+      }
+      break;
+    }
+    
+    /* Find the node with max. fanout/switched cap., or a random node */
+    maxNode = SpfdFindNode(network,nodeArray);
+    if (!maxNode)
+      stop = 1;
+    else 
+      stop = 0;
+    array_free(nodeArray);
+    
+    /* Optimize. */
+    if (!stop) {
+      switch (spfdMethod) {
+      case REDUCE_FANIN_WIRES:
+	SpfdOptimizeFaninWires(network,maxNode,regionDepth,replRem);
+	break;
+      case OPTIMIZE_MAX_NODE:
+	SpfdOptimizeNode(network,maxNode,regionDepth);
+	break;
+      case OPTIMIZE_FANIN_NODES:
+	SpfdOptimizeFaninNodes(network,maxNode,regionDepth);
+	break;
+      case REDUCE_FANOUT_WIRES:
+	SpfdOptimizeFanoutWires(network,maxNode,regionDepth,replRem);
+	break;
+      }
+      /* If the network has changed (structurally), update the depth
+	 information to reflect the change in the network.*/
+      if (spfdNtkChanged) {
+	Truesim_NetworkUpdateNodeTopologicalDepth(network);
+	spfdNtkChanged = FALSE;
+      }
+      if (spfdPerfSim && (iter % frequency == 0)) {
+	Truesim_ZeroDelayPatternSimulate(network,inputArray,intPatternArray);
+      }
+    }
+    iter++;
+  } while (!stop);
+  
+  if (spfdPerfSim) {
+    /* End simulation; free memory */
+    Truesim_QuitSimulation(network);
+    array_free(inputArray);
+    array_free(patternArray);
+  }
+  
+  /* Print the number of wires removed and delete the sinkTable. */
+  fprintf(vis_stdout,"** spfd info: # of wires removed = %d\n",
+	  spfdNumWiresRem - spfdWiresAdded);
+  fprintf(vis_stdout,"** spfd info: # of nodes removed = %d\n",
+	  st_count(applData->nodesRemoved));
+
+  /* Free the memory for each node */
+  st_foreach_item(applData->nodesRemoved,stGen,&node,&dummy) {
+    if (node) Ntk_NodeFree(node);
+  }
+  
+  return 1;
+  
+} /* End of SpfdNetworkOptimize */
+
+#if 0
+/**Function********************************************************************
+
+  Synopsis [Optimize the cluster of nodes in the fanout of each fanout
+  wire of maxNode. The cluster is formed of those nodes that are
+  within 'regionDepth' of the fanout wire. Both wire removal and
+  replacement are performed if 'replRem' is true.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+void
+SpfdProcessFanoutWires(
+  Ntk_Network_t *network,
+  Ntk_Node_t *maxNode,
+  int regionDepth,
+  boolean replRem)
+{
+  SpfdApplData_t *applData;
+  array_t *fanoutArray,*replArray;
+  st_table *wiresRemoved,*sinkTable;
+  st_generator *stGen;
+  Ntk_Node_t *ntkNode,*tempNode,*replNode;
+  int i,num;
+
+  /* Package application data structure */
+  applData = Ntk_NetworkReadApplInfo(network,SPFD_NETWORK_APPL_KEY);
+
+  fanoutArray = array_dup(Ntk_NodeReadFanouts(maxNode));
+  for (i = array_n(fanoutArray) - 1; i >=0; i--) {
+    ntkNode = array_fetch(Ntk_Node_t *,fanoutArray,i);
+    
+    /* Skip POs */
+    if (Ntk_NodeTestIsPrimaryOutput(ntkNode))
+      continue;
+
+    /* Could be removed during an earlier iteration */
+    if (!st_lookup(applData->nodesRemoved,(char *)ntkNode,NIL(char *))) {
+      array_t *regionArray;
+  
+      /* regionArray is an array of nodes sorted according to their depth. */
+      regionArray = SpfdNodeComputeFanoutRegion(applData,ntkNode,regionDepth);
+
+      /* Analyze region's BDD requirements */
+      SpfdComputeRequiredGlobalBdds(network,applData);
+
+      /* Analyze auxilarry BDD ID requirements */
+      SpfdAllocateOrReuseAuxVariables(network,applData);
+
+      /* Order the fanin of internal and boundary nodes */
+      if (spfdPerfSim) {
+	SpfdOrderFaninOfRegionNodes(network,applData,
+				    SpfdSwitchedCapAndDepthCompare);
+      } else {
+	SpfdOrderFaninOfRegionNodes(network,applData,
+				    SpfdFanoutCountAndDepthCompare);
+      }
+    
+      /* Set the spfds for nodes in the region. The spfds are reduced to a
+	 single pair and the localAlt is set to one of the components of the
+	 single pair SPFD. */
+      SpfdRegionComputeSinglePairSpfd(network,applData,regionArray);
+
+      /* Now check if the spfd of wire maxNode --> ntkNode is
+         empty. Remove the spfd of ntkNode as it was not deleted in
+         SpfdRegionComputeSinglePairSpfd */
+      /* Compute array of potential candidates for replacement */
+      if (replRem)
+	replArray = SpfdNodeComputeTFIUntilDepth(ntkNode,regionDepth);
+      else
+	replArray = NIL(array_t);
+      replNode = SpfdCheckIfWireIsRedundantOrReplaceable(network,applData,
+							 maxNode,ntkNode,
+							 replArray);
+      /* No longer needed. */
+      SpfdNodeDeleteSpfd(applData,ntkNode);
+      if (replArray)
+	array_free(replArray);
+      
+      /* Check to see if wires have been found to be
+         redundant/replaceable. If no wires are to be
+         removed/replaced, then decide whether or not to reprogram. */
+      if (st_count(applData->currWireTable) == 0 &&
+	  st_count(applData->currReplaceTable) == 0 &&
+	  !spfdReprogNoWire) {
+	/* In this case just clean up currBddReq, localAlt
+           and globalAlt. */
+	st_table *currBddReq;
+	st_generator *stGen;
+	Ntk_Node_t *regNode;
+	bdd_node *bdd1;
+	bdd_manager *ddManager;
+	int j;
+
+	ddManager = applData->ddManager;
+	currBddReq = applData->currBddReq;
+	
+	/* Clean up currBddReq */
+	st_foreach_item(currBddReq,stGen,(char **)&regNode,(char **)&bdd1) {
+	  bdd_recursive_deref(ddManager,bdd1);
+	}
+	st_free_table(currBddReq);
+	applData->currBddReq = NIL(st_table);
+
+	/* Clean up localAlt and globalAlt of region nodes */
+	arrayForEachItem(Ntk_Node_t *,regionArray,j,regNode) {
+	  SpfdNodeDeleteGlobalAlternative(applData,regNode);
+	  SpfdNodeDeleteLocalAlt(applData,regNode);
+	}
+      } else {
+	/* Now reprogram the nodes in the region. */
+	SpfdReprogramRegionNodes(network,applData,regionArray);
+      }
+
+      /* In this subroutine we have only a single wire
+	 replaced. Delete just that data */
+      if (replNode) {
+	SpfdNodeDeleteGlobalAlternative(applData,replNode);
+	SpfdNodeSetAuxId(applData,replNode,-1);
+	st_delete(applData->currReplaceTable,(char **)&ntkNode,
+		  (char **)&sinkTable);
+	st_free_table(sinkTable);
+	
+	/* A small caveat: sometimes a wire added can be later
+	   removed. Check if the replNode --> ntkNode still exists. If
+	   not set replNode to NULL. */
+	wiresRemoved = applData->wiresRemoved;
+	if (st_lookup(wiresRemoved,(char *)replNode,(char **)&sinkTable) &&
+	    st_lookup(sinkTable,(char *)ntkNode,NIL(char *))) {
+	  /* Reduce the number of wires added and delete
+	     replNode->ntkNode from wiresRemoved table */
+	  spfdWiresAdded--;
+	  st_delete(sinkTable,(char **)&ntkNode,NIL(char *));
+	  if (st_count(sinkTable) < 1) {
+	    st_delete(wiresRemoved,(char **)&replNode,(char **)&sinkTable);
+	    st_free_table(sinkTable);
+	  }
+	  replNode = NIL(Ntk_Node_t);
+	}
+      }
+      
+      /* Clean up auxIds and piAltVars*/
+      SpfdCleanUpAuxIds(applData);
+      
+      /* Free stuff used only for the current iteration */
+      if (applData->currXCube) {
+	bdd_recursive_deref(applData->ddManager,applData->currXCube);
+	applData->currXCube = NIL(bdd_node);
+      }
+      if (applData->currRegionNodes) {
+	st_free_table(applData->currRegionNodes);
+	applData->currRegionNodes = NIL(st_table);
+      }
+      if (applData->currInUseVars) {
+	st_free_table(applData->currInUseVars);
+	applData->currInUseVars = NIL(st_table);
+      }
+
+      num = st_count(applData->currWireTable);
+      assert(num == 0);
+
+      num = st_count(applData->currReplaceTable);
+      assert(num == 0);
+      
+      /* Update the total number of wires removed */
+      wiresRemoved = applData->wiresRemoved;
+      if (st_count(wiresRemoved) > 0) {
+	st_foreach_item(wiresRemoved,stGen,(char **)&tempNode,
+			(char **)&sinkTable){
+	  spfdNumWiresRem += st_count(sinkTable);
+	}
+	
+	/* free the wiresRemoved contents */
+	st_foreach(wiresRemoved,SpfdStTableClean,NIL(char));
+      }
+      
+      /* Free regionArray (cluster) */
+      array_free(regionArray);
+    }
+  }
+  array_free(fanoutArray);
+  
+  /* Lock the node */
+  SpfdNodeSetLocked(applData,maxNode,TRUE);
+  
+} /* End of SpfdProcessFanoutWires */
+#endif
+
+/**Function********************************************************************
+
+  Synopsis [Checks if the SPFD for 'from' --> 'to' is empty. If yes,
+  the wire is removed. If not, nodes in 'replaceArray' are examined to
+  check for replacability. If a node is found, that node is returned.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+Ntk_Node_t *
+SpfdCheckIfWireIsRedundantOrReplaceable(
+  Ntk_Network_t *network,
+  SpfdApplData_t *applData,
+  Ntk_Node_t *from,
+  Ntk_Node_t *to,
+  array_t *replaceArray)
+{
+  bdd_manager *ddManager = applData->ddManager;
+  bdd_node *result,*ddTemp,*ddTemp2,*var,*varAux;
+  bdd_node *toSpfd,*wireSpfd,*logicZero;
+  int i,index;
+  Ntk_Node_t *fanin,*tempNode,*replNode;
+  st_table *wireTable = applData->currWireTable;
+  st_table *wiresRemoved = applData->wiresRemoved;
+  st_table *sinkTable;
+
+  /* Possible replacement node */
+  replNode = NIL(Ntk_Node_t);
+  logicZero = bdd_read_logic_zero(ddManager);
+
+  /* Check if this wire has already been removed. */
+  if (!(st_lookup(wiresRemoved,(char *)from,&sinkTable) &&
+      st_lookup(sinkTable,(char *)to,&tempNode))) {
+  
+    bdd_ref(result = bdd_read_one(ddManager));
+
+    /* Compute the characteristic function of pairs of minterms cannot
+       be distinguished any fanin of 'to'. Let f_i be the ith fanin of
+       'to'. We compute result = \prod f_i == f'_i, where f_i != from */
+    Ntk_NodeForEachFanin(to,i,fanin) {
+      var = bdd_bdd_ith_var(ddManager,Ntk_NodeReadMddId(fanin));
+      index = SpfdNodeReadAuxId(applData,fanin);
+      varAux = bdd_bdd_ith_var(ddManager,index);
+      
+      if (fanin != from) {
+	bdd_ref(ddTemp = bdd_bdd_xnor(ddManager,var,varAux)); /* XNOR */
+	bdd_ref(ddTemp2 = bdd_bdd_and(ddManager,result,ddTemp));
+	bdd_recursive_deref(ddManager,result);
+	bdd_recursive_deref(ddManager,ddTemp);
+	result = ddTemp2;
+      }
+    }
+    /* Finally put in f_i == f_i', where f_i = from) */
+    var = bdd_bdd_ith_var(ddManager,Ntk_NodeReadMddId(from));
+    index = SpfdNodeReadAuxId(applData,from);
+    varAux = bdd_bdd_ith_var(ddManager,index);
+    bdd_ref(ddTemp = bdd_bdd_xor(ddManager,var,varAux));
+    bdd_ref(ddTemp2 = bdd_bdd_and(ddManager,result,ddTemp));
+    bdd_recursive_deref(ddManager,result);
+    bdd_recursive_deref(ddManager,ddTemp);
+    result = ddTemp2;
+
+    /* Compute AND of result and the SPFD of 'to'. */
+    toSpfd = SpfdNodeReadSpfd(applData,to);
+    if (toSpfd == NIL(bdd_node)) {
+      (void) fprintf(vis_stderr,
+		     "** spfd error: Spfd expected but not found.\n");
+      exit(0);
+    }
+    bdd_ref(wireSpfd = bdd_bdd_and(ddManager,toSpfd,result));
+    bdd_recursive_deref(ddManager,result);
+
+    if (wireSpfd == logicZero) { /* Can the wire be removed? */
+      if (spfdVerbose > 1)
+	(void) fprintf(vis_stdout,
+		       "** spfd info: Target wire %s --> %s has empty spfd.\n",
+		       Ntk_NodeReadName(from),Ntk_NodeReadName(to));
+
+      /* Insert the wire into wireTable */
+      if (st_lookup(wireTable,(char *)from,&sinkTable)) {
+	st_insert(sinkTable,(char *)to,(char *)to);
+      } else {
+	sinkTable = st_init_table(st_ptrcmp,st_ptrhash);
+	st_insert(sinkTable,(char *)to,(char *)to);
+	st_insert(wireTable,(char *)from,(char *)sinkTable);
+      }
+      bdd_recursive_deref(ddManager,wireSpfd);
+    } else if (replaceArray != NIL(array_t)) {
+      /* Try for replacement. Exit after finding the first one. Here the
+         assumption is that the nodes are sorted according to some
+         criterion. */
+      replNode = SpfdTestIfNodeGlobalFuncSatisfiesWireSpfd(network,replaceArray,
+							   from,to,wireSpfd);
+      bdd_recursive_deref(ddManager,wireSpfd);
+    } else {
+      bdd_recursive_deref(ddManager,wireSpfd);
+    }
+  }
+  
+  return replNode;
+  
+} /* End of SpfdCheckIfWireIsRedundantOrReplaceable */
+
+
+/**Function********************************************************************
+
+  Synopsis [Checks if the global functions implemented by nodes in
+  'replaceArray' satisfy the SPFD, 'wireSpfd' of 'from' --> 'to'.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+Ntk_Node_t *
+SpfdTestIfNodeGlobalFuncSatisfiesWireSpfd(
+  Ntk_Network_t *network,
+  array_t *replaceArray,
+  Ntk_Node_t *from,
+  Ntk_Node_t *to,
+  bdd_node *wireSpfd)
+{
+  SpfdApplData_t *applData;
+  bdd_manager *ddManager;
+  st_table *leavesTable,*inUseVars,*replaceTable;
+  st_table *sinkTable,*currBddReq;
+  bdd_t *mddOne;
+  lsGen gen;
+  Ntk_Node_t *fanin,*node,*replNode;
+  Ntk_Node_t *foundNode;
+  array_t *nodeMvfs,*nodeBdds;
+  bdd_node *bdd1,*xCube,*yVar;
+  bdd_node **tempVars,**firstCompose,**secondCompose;
+  bdd_node *step1,*step2,*step3,*step4,*step5;
+  bdd_node *logicZero;
+  int i,j,size,replId,id,auxId;
+  
+  applData = (SpfdApplData_t *) Ntk_NetworkReadApplInfo(network,
+							SPFD_NETWORK_APPL_KEY);
+  ddManager = applData->ddManager;
+  inUseVars = applData->currInUseVars;
+  replaceTable = applData->currReplaceTable;
+  currBddReq = applData->currBddReq;
+  
+  mddOne = bdd_one(ddManager);
+  logicZero = bdd_read_logic_zero(ddManager);
+  
+  /* Collect the leaf nodes of the network. */
+  leavesTable = st_init_table(st_ptrcmp, st_ptrhash);
+  Ntk_NetworkForEachCombInput(network,gen,node) {
+    st_insert(leavesTable,(char *)node,(char *) -1);
+  }
+
+  /* Compute the global MVFs of the nodes in replaceArray */
+  nodeMvfs = Ntm_NetworkBuildMvfs(network,replaceArray,leavesTable,mddOne);
+  bdd_free(mddOne);
+  st_free_table(leavesTable);
+
+  /* Collect node global Bdds */
+  nodeBdds = array_alloc(bdd_node *,0);
+  arrayForEachItem(Ntk_Node_t *,replaceArray,i,node) {
+    Mvf_Function_t *mvf;
+    mvf = array_fetch(Mvf_Function_t *,nodeMvfs,i);
+    bdd1 = bdd_extract_node_as_is(array_fetch(bdd_t *,mvf,1));
+    bdd_ref(bdd1);
+    array_insert_last(bdd_node *,nodeBdds,bdd1);
+  }
+  Mvf_FunctionArrayFree(nodeMvfs);
+
+  /* Now check one at a time if global function satisfies wireSpfd */
+  foundNode = NIL(Ntk_Node_t);
+  xCube = applData->currXCube;
+  arrayForEachItem(Ntk_Node_t *,nodeBdds,i,bdd1) {
+    int idAllocated;
+
+    idAllocated = 0;
+    replNode = array_fetch(Ntk_Node_t *,replaceArray,i);
+    replId = Ntk_NodeReadMddId(replNode);
+    /* Check if replId is already in use. This is possible is outside
+       the cluster. */
+    if (st_lookup(inUseVars,(char *)(long)replId,NIL(char *))) {
+      /* Allocate yVar and yAuxVar for replNode */
+      tempVars = SpfdAllocateTemporaryVariables(ddManager,inUseVars,1);
+      yVar = tempVars[0];
+      idAllocated = 1;
+      FREE(tempVars);
+    } else { /* replId not in use */
+      yVar = bdd_bdd_ith_var(ddManager,replId);
+    }
+
+    /* Now perform the following steps, using two compositions. */
+    /* 1. step1 = yVar == bdd1
+       2. step2 = wireSpfd(Y,Y') --> wireSpfd(x,Y')
+       3. step3 = \exists_x step1 * step2
+       4. step4 = step3(yVar,Y') --> step3(yVar,x)
+       5. step5 = \exists_x step1 * step4
+
+       If step5 == logicZero, then replNode is a candidate */
+
+    /* Prepare compose arrays for the above steps */
+    size = bdd_num_vars(ddManager);
+    firstCompose = ALLOC(bdd_node *,size);
+    secondCompose = ALLOC(bdd_node *,size);
+    for (j = 0; j < size; j++) {
+      firstCompose[j] = bdd_bdd_ith_var(ddManager,j);
+      secondCompose[j] = bdd_bdd_ith_var(ddManager,j);
+    }
+
+    Ntk_NodeForEachFanin(to,j,fanin) {
+      id = Ntk_NodeReadMddId(fanin);
+      auxId = SpfdNodeReadAuxId(applData,fanin);
+      st_lookup(currBddReq,(char *)fanin,(char **)&firstCompose[id]);
+      secondCompose[auxId] = firstCompose[id];
+    }
+
+    bdd_ref(step1 = bdd_bdd_xnor(ddManager,yVar,bdd1));
+    bdd_ref(step2 = bdd_bdd_vector_compose(ddManager,wireSpfd,firstCompose));
+    FREE(firstCompose);
+    bdd_ref(step3 = bdd_bdd_and_abstract(ddManager,step1,step2,xCube));
+    bdd_recursive_deref(ddManager,step2);
+    bdd_ref(step4 = bdd_bdd_vector_compose(ddManager,step3,secondCompose));
+    bdd_recursive_deref(ddManager,step3);
+    FREE(secondCompose);
+    bdd_ref(step5 = bdd_bdd_and_abstract(ddManager,step1,step4,xCube));
+    bdd_recursive_deref(ddManager,step4);
+    bdd_recursive_deref(ddManager,step1);
+
+    /* Now if step5 is zero, then return replNode as the candidate. I will use
+       the globalAlt field of the node to store the global BDD. This way I
+       don't have to recompute the global BDD later.  */
+    if (step5 == logicZero) {
+      bdd_recursive_deref(ddManager,step5);
+      bdd_ref(bdd1);
+      SpfdNodeSetGlobalAlternative(applData,replNode,bdd1);
+
+      /* Allocate an auxId for this node. It will be needed during
+         reprogramming. */
+      if (idAllocated) {
+	auxId = bdd_node_read_index(yVar);
+      } else {
+	tempVars = SpfdAllocateTemporaryVariables(ddManager,inUseVars,1);
+	auxId = bdd_node_read_index(tempVars[0]);
+	FREE(tempVars);
+      }
+      SpfdNodeSetAuxId(applData,replNode,auxId);
+      st_insert(inUseVars,(char *)(long)replId,(char *)-1);
+      st_insert(inUseVars,(char *)(long)auxId,(char *)-1);
+      
+      /* Insert information in replaceTable */
+      if (st_lookup(replaceTable,(char *)to,&sinkTable)) {
+	st_insert(sinkTable,(char *)from,(char *)replNode);
+      } else {
+	sinkTable = st_init_table(st_ptrcmp,st_ptrhash);
+	st_insert(sinkTable,(char *)from,(char *)replNode);
+	st_insert(replaceTable,(char *)to,(char *)sinkTable);
+      }
+      foundNode = replNode;
+      break;
+    } else {
+      bdd_recursive_deref(ddManager,step5);
+      /* release the id */
+      if (idAllocated) {
+	id = bdd_node_read_index(yVar);
+	st_delete(inUseVars, &id, NIL(char *));
+      }
+    }
+  }
+
+  /* Free the nodeBdds */
+  arrayForEachItem(bdd_node *,nodeBdds,i,bdd1) {
+    bdd_recursive_deref(ddManager,bdd1);
+  }
+  array_free(nodeBdds);
+
+  return foundNode;
+} /* End of SpfdTestIfNodeGlobalFuncSatisfiesWireSpfd */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Try to remove/replace the fanin wires of maxNode.]
+
+  SideEffects        [None]
+
+  SeeAlso            [SpfdOptimizeFanoutWires]
+
+******************************************************************************/
+void
+SpfdOptimizeFaninWires(
+  Ntk_Network_t *network,
+  Ntk_Node_t *maxNode,
+  int regionDepth,
+  boolean replRem)
+{
+  SpfdApplData_t *applData;
+  array_t *faninArray;
+  Ntk_Node_t *ntkNode,*fanout;
+  char *dummy;
+  int i,j;
+
+  applData = (SpfdApplData_t *) Ntk_NetworkReadApplInfo(network,
+							SPFD_NETWORK_APPL_KEY);
+  
+  /* replace/remove the fanin wire of maxNode one at a time. The fanin
+     node with higher switched capacitance will be optimized first. */
+  faninArray = array_dup(Ntk_NodeReadFanins(maxNode));
+  if (spfdPerfSim)
+    array_sort(faninArray,CompareConvexSwitchedCapAndDepth);
+  else
+    array_sort(faninArray,CompareConvexFanoutCountAndDepth);
+
+  for (i = array_n(faninArray) - 1; i >=0; i--) {
+    boolean skip;
+    ntkNode = array_fetch(Ntk_Node_t *,faninArray,i);
+    if (!st_lookup(applData->nodesRemoved,(char *)ntkNode,(char **)&dummy)) {
+      skip = TRUE;
+      /* Check if the current fanin node is still in the support of
+         maxNode. */
+      Ntk_NodeForEachFanout(ntkNode,j,fanout) {
+	if (fanout == maxNode) {
+	  skip = FALSE;
+	  break;
+	}
+      }
+    } else {
+      skip = TRUE;
+    }
+    if (!skip)
+      SpfdOptimizeWire(network,ntkNode,maxNode,regionDepth,replRem);
+  }
+  array_free(faninArray);
+
+  /* Lock the node */
+  SpfdNodeSetLocked(applData,maxNode,TRUE);
+  
+  return ;
+  
+} /* End of SpfdOptimizeFaninWires */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Try to remove/replace the fanout wires of maxNode.]
+
+  SideEffects        [None]
+
+  SeeAlso            [SpfdOptimizeFaninWires]
+
+******************************************************************************/
+void
+SpfdOptimizeFanoutWires(
+  Ntk_Network_t *network,
+  Ntk_Node_t *maxNode,
+  int regionDepth,
+  boolean replRem)
+{
+  SpfdApplData_t *applData;
+  array_t *fanoutArray;
+  Ntk_Node_t *ntkNode,*fanout;
+  int i,j;
+  
+  applData = (SpfdApplData_t *) Ntk_NetworkReadApplInfo(network,
+							SPFD_NETWORK_APPL_KEY);
+
+  /* replace/remove the fanout wires of maxNode one at a time. The fanout
+     node with higher switched capacitance will be optimized first. */
+  fanoutArray = array_dup(Ntk_NodeReadFanouts(maxNode));
+  if (spfdPerfSim)
+    array_sort(fanoutArray,CompareConvexSwitchedCapAndDepth);
+  else
+    array_sort(fanoutArray,CompareConvexFanoutCountAndDepth);
+
+
+  for (i = array_n(fanoutArray) - 1; i >=0; i--) {
+    boolean skip;
+    ntkNode = array_fetch(Ntk_Node_t *,fanoutArray,i);
+    skip = TRUE;
+    /* Check if the maxNode is still in the support of fanout. */
+    Ntk_NodeForEachFanout(maxNode,j,fanout) {
+      if (fanout == ntkNode) {
+	skip = FALSE;
+	break;
+      }
+    }
+    if (!skip)    
+      SpfdOptimizeWire(network,maxNode,ntkNode,regionDepth,replRem);
+  }
+  array_free(fanoutArray);
+
+  /* Lock the node */
+  SpfdNodeSetLocked(applData,maxNode,TRUE);
+  
+  return ;
+  
+} /* End of SpfdOptimizeFanoutWires */
+
+
+/**Function********************************************************************
+
+  Synopsis           [Optimize all the fanin nodes of maxNode.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+void
+SpfdOptimizeFaninNodes(
+  Ntk_Network_t *network,
+  Ntk_Node_t *maxNode,
+  int regionDepth)
+{
+  SpfdApplData_t *applData;
+  array_t *faninArray;
+  Ntk_Node_t *ntkNode;
+  char *dummy;
+  int i;
+
+  applData = (SpfdApplData_t *) Ntk_NetworkReadApplInfo(network,
+							SPFD_NETWORK_APPL_KEY);
+
+  /* Optimize fanin nodes one at a time. The fanin node with higher
+     switched capacitance will be optimized first. */
+  faninArray = array_dup(Ntk_NodeReadFanins(maxNode));
+  if (spfdPerfSim)
+    array_sort(faninArray,CompareConvexSwitchedCapAndDepth);
+  else
+    array_sort(faninArray,CompareConvexFanoutCountAndDepth);
+
+  for (i = array_n(faninArray) - 1; i >=0; i--) {
+    boolean skip = FALSE;
+    ntkNode = array_fetch(Ntk_Node_t *,faninArray,i);
+    if (st_lookup(applData->nodesRemoved,(char *)ntkNode,(char **)&dummy)) {
+      skip = TRUE;
+    }
+    if (!skip)
+      SpfdOptimizeNode(network,ntkNode,regionDepth);
+  }
+  array_free(faninArray);
+
+  /* Lock the node */
+  SpfdNodeSetLocked(applData,maxNode,TRUE);
+  
+  return ;
+  
+} /* End of SpfdOptimizeFaninNodes */
+
+
+/**Function********************************************************************
+
+  Synopsis [Optimize the cluster of nodes in the fanout the wire
+  maxNode --> ntkNode. The cluster is formed of those nodes that are
+  within 'regionDepth' of this wire. Both wire removal and replacement
+  are performed if 'replRem' is true.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+void
+SpfdOptimizeWire(
+  Ntk_Network_t *network,
+  Ntk_Node_t *maxNode,
+  Ntk_Node_t *ntkNode,
+  int regionDepth,
+  boolean replRem)
+{
+  SpfdApplData_t *applData;
+  array_t *replArray;
+  st_table *wiresRemoved,*sinkTable;
+  st_generator *stGen;
+  Ntk_Node_t *tempNode,*replNode;
+  array_t *regionArray;
+  int num;
+
+  /* Package application data structure */
+  applData = (SpfdApplData_t *) Ntk_NetworkReadApplInfo(network,
+							SPFD_NETWORK_APPL_KEY);
+
+  /* Skip POs */
+  if (Ntk_NodeTestIsPrimaryOutput(ntkNode))
+    return;
+  
+  /* regionArray is an array of nodes sorted according to their depth. */
+  regionArray = SpfdNodeComputeFanoutRegion(applData,ntkNode,regionDepth);
+
+  /* Analyze region's BDD requirements */
+  SpfdComputeRequiredGlobalBdds(network,applData);
+  
+  /* Analyze auxilarry BDD ID requirements */
+  SpfdAllocateOrReuseAuxVariables(network,applData);
+  
+  /* Order the fanin of internal and boundary nodes */
+  if (spfdPerfSim) {
+    SpfdOrderFaninOfRegionNodes(network,applData,
+				SpfdSwitchedCapAndDepthCompare);
+  } else {
+    SpfdOrderFaninOfRegionNodes(network,applData,
+				SpfdFanoutCountAndDepthCompare);
+  }
+    
+  /* Set the spfds for nodes in the region. The spfds are reduced to a
+     single pair and the localAlt is set to one of the components of the
+     single pair SPFD. */
+  SpfdRegionComputeSinglePairSpfd(network,applData,regionArray);
+  
+  /* Now check if the spfd of wire maxNode --> ntkNode is
+     empty. Remove the spfd of ntkNode as it was not deleted in
+     SpfdRegionComputeSinglePairSpfd */
+  /* Compute array of potential candidates for replacement */
+  if (replRem)
+    replArray = SpfdNodeComputeTFIUntilDepth(ntkNode,regionDepth);
+  else
+    replArray = NIL(array_t);
+  replNode = SpfdCheckIfWireIsRedundantOrReplaceable(network,applData,
+						     maxNode,ntkNode,
+						     replArray);
+  /* SPFD of ntkNode is no longer needed. */
+  SpfdNodeDeleteSpfd(applData,ntkNode);
+  if (replArray)
+    array_free(replArray);
+      
+  /* Check to see if wires have been found to be
+     redundant/replaceable. If no wires are to be
+     removed/replaced, then decide whether or not to reprogram. */
+  if (st_count(applData->currWireTable) == 0 &&
+      st_count(applData->currReplaceTable) == 0 &&
+      !spfdReprogNoWire) {
+    /* In this case just clean up currBddReq, localAlt
+       and globalAlt. */
+    st_table *currBddReq;
+    st_generator *stGen;
+    Ntk_Node_t *regNode;
+    bdd_node *bdd1;
+    bdd_manager *ddManager;
+    int j;
+    
+    ddManager = applData->ddManager;
+    currBddReq = applData->currBddReq;
+    
+    /* Clean up currBddReq */
+    st_foreach_item(currBddReq,stGen,&regNode,&bdd1) {
+      bdd_recursive_deref(ddManager,bdd1);
+    }
+    st_free_table(currBddReq);
+    applData->currBddReq = NIL(st_table);
+    
+    /* Clean up localAlt and globalAlt of region nodes */
+    arrayForEachItem(Ntk_Node_t *,regionArray,j,regNode) {
+      SpfdNodeDeleteGlobalAlternative(applData,regNode);
+      SpfdNodeDeleteLocalAlt(applData,regNode);
+    }
+  } else {
+    /* Now reprogram the nodes in the region. */
+    SpfdReprogramRegionNodes(network,applData,regionArray);
+  }
+  
+  /* In this subroutine we have only a single wire
+     replaced. Delete just that data */
+  if (replNode) {
+    SpfdNodeDeleteGlobalAlternative(applData,replNode);
+    SpfdNodeSetAuxId(applData,replNode,-1);
+    st_delete(applData->currReplaceTable,&ntkNode,
+	      &sinkTable);
+    st_free_table(sinkTable);
+    
+    /* A small caveat: sometimes a wire added can be later
+       removed. Check if the replNode --> ntkNode still exists. If
+       not set replNode to NULL. */
+    wiresRemoved = applData->wiresRemoved;
+    if (st_lookup(wiresRemoved,(char *)replNode,&sinkTable) &&
+	st_lookup(sinkTable,(char *)ntkNode,NIL(char *))) {
+      /* Reduce the number of wires added and delete
+	 replNode->ntkNode from wiresRemoved table */
+      spfdWiresAdded--;
+      st_delete(sinkTable,&ntkNode,NIL(char *));
+      if (st_count(sinkTable) < 1) {
+	st_delete(wiresRemoved,&replNode,&sinkTable);
+	st_free_table(sinkTable);
+      }
+      replNode = NIL(Ntk_Node_t);
+    }
+  }
+      
+  /* Clean up auxIds and piAltVars*/
+  SpfdCleanUpAuxIds(applData);
+  
+  /* Free stuff used only for the current wire */
+  if (applData->currXCube) {
+    bdd_recursive_deref(applData->ddManager,applData->currXCube);
+    applData->currXCube = NIL(bdd_node);
+  }
+  if (applData->currRegionNodes) {
+    st_free_table(applData->currRegionNodes);
+    applData->currRegionNodes = NIL(st_table);
+  }
+  if (applData->currInUseVars) {
+    st_free_table(applData->currInUseVars);
+    applData->currInUseVars = NIL(st_table);
+  }
+  
+  num = st_count(applData->currWireTable);
+  assert(num == 0);
+  
+  num = st_count(applData->currReplaceTable);
+  assert(num == 0);
+  
+  /* Update the total number of wires removed. */
+  wiresRemoved = applData->wiresRemoved;
+  if (st_count(wiresRemoved) > 0) {
+    st_foreach_item(wiresRemoved,stGen,&tempNode,
+		    &sinkTable){
+      spfdNumWiresRem += st_count(sinkTable);
+    }
+    
+    /* free the wiresRemoved contents */
+    st_foreach(wiresRemoved,SpfdStTableClean,NIL(char));
+  }
+  
+  /* Free regionArray (cluster) */
+  array_free(regionArray);
+  
+  return ;
+  
+} /* End of SpfdOptimizeWire */
+
+
+/**Function********************************************************************
+
+  Synopsis [Optimize the ntkNode. This is done by computing its SPFD
+  derived from the output cluster. The cluster is formed of those
+  nodes that are within 'regionDepth' in the fanout of ntkNode. Both
+  wire removal and replacement are performed if 'replRem' is true.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+void
+SpfdOptimizeNode(
+  Ntk_Network_t *network,
+  Ntk_Node_t *ntkNode,
+  int regionDepth)
+{
+  SpfdApplData_t *applData;
+  st_table *wiresRemoved,*sinkTable;
+  st_generator *stGen;
+  Ntk_Node_t *tempNode;
+  array_t *regionArray;
+  int num;
+
+  /* Package application data structure */
+  applData = (SpfdApplData_t *) Ntk_NetworkReadApplInfo(network,
+							SPFD_NETWORK_APPL_KEY);
+
+  /* Skip POs */
+  if (Ntk_NodeTestIsPrimaryOutput(ntkNode))
+    return;
+  
+  /* regionArray is an array of nodes sorted according to their depth. */
+  regionArray = SpfdNodeComputeFanoutRegion(applData,ntkNode,regionDepth);
+
+  /* Analyze region's BDD requirements */
+  SpfdComputeRequiredGlobalBdds(network,applData);
+  
+  /* Analyze auxilarry BDD ID requirements */
+  SpfdAllocateOrReuseAuxVariables(network,applData);
+  
+  /* Order the fanin of internal and boundary nodes */
+  if (spfdPerfSim) {
+    SpfdOrderFaninOfRegionNodes(network,applData,
+				SpfdSwitchedCapAndDepthCompare);
+  } else {
+    SpfdOrderFaninOfRegionNodes(network,applData,
+				SpfdFanoutCountAndDepthCompare);
+  }
+    
+  /* Set the spfds for nodes in the region. The spfds are reduced to a
+     single pair and the localAlt is set to one of the components of the
+     single pair SPFD. */
+  SpfdRegionComputeSinglePairSpfd(network,applData,regionArray);
+  
+  /* Remove the spfd of ntkNode as it was not deleted in
+     SpfdRegionComputeSinglePairSpfd */
+
+  /* SPFD of ntkNode is no longer needed. */
+  SpfdNodeDeleteSpfd(applData,ntkNode);
+      
+  /* Check to see if wires have been found to be
+     redundant/replaceable. If no wires are to be
+     removed/replaced, then decide whether or not to reprogram. */
+  if (st_count(applData->currWireTable) == 0 &&
+      !spfdReprogNoWire) {
+    /* In this case just clean up currBddReq, localAlt and
+       globalAlt. */
+    st_table *currBddReq;
+    st_generator *stGen;
+    Ntk_Node_t *regNode;
+    bdd_node *bdd1;
+    bdd_manager *ddManager;
+    int j;
+    
+    ddManager = applData->ddManager;
+    currBddReq = applData->currBddReq;
+    
+    /* Clean up currBddReq */
+    st_foreach_item(currBddReq,stGen,&regNode,&bdd1) {
+      bdd_recursive_deref(ddManager,bdd1);
+    }
+    st_free_table(currBddReq);
+    applData->currBddReq = NIL(st_table);
+    
+    /* Clean up localAlt and globalAlt of region nodes */
+    arrayForEachItem(Ntk_Node_t *,regionArray,j,regNode) {
+      SpfdNodeDeleteGlobalAlternative(applData,regNode);
+      SpfdNodeDeleteLocalAlt(applData,regNode);
+    }
+  } else {
+    /* Now reprogram the nodes in the region. */
+    SpfdReprogramRegionNodes(network,applData,regionArray);
+  }
+  
+  /* Clean up auxIds and piAltVars*/
+  SpfdCleanUpAuxIds(applData);
+  
+  /* Free stuff used only for the current wire */
+  if (applData->currXCube) {
+    bdd_recursive_deref(applData->ddManager,applData->currXCube);
+    applData->currXCube = NIL(bdd_node);
+  }
+  if (applData->currRegionNodes) {
+    st_free_table(applData->currRegionNodes);
+    applData->currRegionNodes = NIL(st_table);
+  }
+  if (applData->currInUseVars) {
+    st_free_table(applData->currInUseVars);
+    applData->currInUseVars = NIL(st_table);
+  }
+  
+  num = st_count(applData->currWireTable);
+  assert(num == 0);
+  
+  num = st_count(applData->currReplaceTable);
+  assert(num == 0);
+  
+  /* Update the total number of wires removed */
+  wiresRemoved = applData->wiresRemoved;
+  if (st_count(wiresRemoved) > 0) {
+    st_foreach_item(wiresRemoved,stGen,&tempNode,
+		    &sinkTable){
+      spfdNumWiresRem += st_count(sinkTable);
+    }
+    
+    /* free the wiresRemoved contents */
+    st_foreach(wiresRemoved,SpfdStTableClean,NIL(char));
+  }
+  
+  /* Free regionArray (cluster) */
+  array_free(regionArray);
+  
+  /* Lock the node */
+  SpfdNodeSetLocked(applData,ntkNode,TRUE);
+
+  return ;
+  
+} /* End of SpfdOptimizeNode */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis [Compare the convex combination of fanout count and the 
+  node's topological depth.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+static int
+CompareConvexFanoutCountAndDepth(
+  const void *obj1,
+  const void *obj2)
+{
+  Ntk_Node_t *node1,*node2;
+  Ntk_Network_t *network;
+  float weight1,weight2;
+  float load1,load2;
+  int depth1,depth2;
+  
+  node1 = *(Ntk_Node_t **)obj1;
+  node2 = *(Ntk_Node_t **)obj2;
+  assert(Ntk_NodeReadNetwork(node1) == Ntk_NodeReadNetwork(node2));
+  network = Ntk_NodeReadNetwork(node1);
+
+  if (Ntk_NodeTestIsPrimaryOutput(node1) ||
+      Ntk_NodeTestIsPrimaryInput(node1)) {
+    weight1 = -1.0;
+  } else {
+    load1 = Ntk_NodeReadNumFanouts(node1);
+    depth1 = Truesim_NetworkReadNodeDepth(network,node1);
+    weight1 = spfdAlpha * load1 + (1.0-spfdAlpha)*depth1;
+  }
+
+  if (Ntk_NodeTestIsPrimaryOutput(node2) ||
+      Ntk_NodeTestIsPrimaryInput(node2)) {
+    weight2 = -1.0;
+  } else {
+    load2 = Ntk_NodeReadNumFanouts(node2);
+    depth2 = Truesim_NetworkReadNodeDepth(network,node2);
+    weight2 = spfdAlpha * load2 + (1.0-spfdAlpha)*depth2;
+  }
+  
+  if (weight1 > weight2)
+    return -1;
+  else if (weight1 == weight2)
+    return 0;
+  else
+    return 1;
+
+} /* End of CompareConvexFanoutCountAndDepth */
+
+
+/**Function********************************************************************
+
+  Synopsis [Compare the convex combination of switched capacitance and
+  topological depth of two nodes.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+static int
+CompareConvexSwitchedCapAndDepth(
+  const void *obj1,
+  const void *obj2)
+{
+  Ntk_Node_t *node1,*node2;
+  Ntk_Network_t *network;
+  float weight1,weight2;
+  float switch1,switch2;
+  float load1,load2;
+  int depth1,depth2;
+  
+  node1 = *(Ntk_Node_t **)obj1;
+  node2 = *(Ntk_Node_t **)obj2;
+  assert(Ntk_NodeReadNetwork(node1) == Ntk_NodeReadNetwork(node2));
+  network = Ntk_NodeReadNetwork(node1);
+
+  if (Ntk_NodeTestIsPrimaryOutput(node1) ||
+      Ntk_NodeTestIsPrimaryInput(node1)) {
+    weight1 = -1.0;
+  } else {
+    switch1 = Truesim_NetworkReadNodeSwitchingProb(network,node1);
+    load1 = Truesim_NetworkReadNodeLoad(network,node1);
+    depth1 = Truesim_NetworkReadNodeDepth(network,node1);
+    weight1 = spfdAlpha * load1 * switch1 + (1.0-spfdAlpha)*depth1;
+  }
+
+  if (Ntk_NodeTestIsPrimaryOutput(node2) ||
+      Ntk_NodeTestIsPrimaryInput(node2)) {
+    weight2 = -1.0;
+  } else {
+    switch2 = Truesim_NetworkReadNodeSwitchingProb(network,node2);
+    load2 = Truesim_NetworkReadNodeLoad(network,node2);
+    depth2 = Truesim_NetworkReadNodeDepth(network,node2);
+    weight2 = spfdAlpha * load2 * switch2 + (1.0-spfdAlpha)*depth2;
+  }
+  
+  if (weight1 > weight2)
+    return -1;
+  else if (weight1 == weight2)
+    return 0;
+  else
+    return 1;
+
+} /* End of CompareConvexSwitchedCapAndDepth */
Index: vis_dev/vis-2.3/src/spfd/spfdProg.c
===================================================================
--- vis_dev/vis-2.3/src/spfd/spfdProg.c	(revision 14)
+++ vis_dev/vis-2.3/src/spfd/spfdProg.c	(revision 14)
@@ -0,0 +1,752 @@
+/**CFile***********************************************************************
+
+  FileName    [spfdProg.c]
+
+  PackageName [spfd]
+
+  Synopsis [Routines that perform reprogramming of LUTs (nodes) in the
+  circuit.]
+
+  Description [Routines that perform reprogramming of LUTs (nodes) in the
+  circuit. Wire removal/addition operations are also performed.]
+
+  SeeAlso     [spfdOpt.c spfdSpfd.c]
+
+  Author      [Balakrishna Kumthekar]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "spfdInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static Tbl_Table_t * BuildNewTable(Ntk_Network_t *network, Ntk_Node_t *ntkNode, mdd_t *mddFunc);
+static void TableAddCube(Tbl_Table_t *table, array_t *faninIdArray, array_t *cube, int value);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis [Reprogram the nodes in the 'regionArray' based on an
+  alternate implementation selected from the SPFDs. The cluster nodes
+  are reprogrammed in the increasing order of their topological
+  depth. When a node is being reprogrammed all of its fanin have
+  either been reprogrammed or have retained their original
+  implementation.]
+
+  SideEffects [None]
+
+******************************************************************************/
+void
+SpfdReprogramRegionNodes(
+  Ntk_Network_t *network,
+  SpfdApplData_t *applData,
+  array_t *regionArray)
+{
+  st_table *nodeCountTable,*sinkTable;
+  st_table *regionNodes = applData->currRegionNodes;
+  st_table *currBddReq = applData->currBddReq;
+  st_table *wireTable = applData->currWireTable;
+  st_table *replaceTable = applData->currReplaceTable;
+  bdd_manager *ddManager = applData->ddManager;
+  Ntk_Node_t *fanout,*regNode,*fanin,*newFanin;
+  bdd_node *bdd1,*localAlt,*globalAlt;
+  bdd_node *ddTemp,*relNew,*relOld,*encRel;
+  bdd_node *xCube;
+  char *dummy;
+  st_generator *stGen;
+  int bound,i,j,k,piSwap;
+  int *count;
+  array_t *faninBdds,*faninNodes,*nodeArray;
+
+  /* Cube of primary inputs. */
+  xCube = applData->currXCube;
+  /* Analyze the region to find out how many times the
+     alternative/global function of an individual region node will be
+     used. This count will be used to remove those functions when no
+     longer needed, hence avoid memory peaks. */
+  nodeCountTable = st_init_table(st_ptrcmp,st_ptrhash);
+  st_foreach_item(currBddReq,stGen,&regNode,&bdd1) {
+    count = ALLOC(int,1);
+    *count = 0;
+    Ntk_NodeForEachFanout(regNode,k,fanout) {
+      if (st_lookup(regionNodes,(char *)fanout,&dummy))
+	(*count)++;
+    }
+    /* The global function implemented by regNode is used count number
+       of times */
+    assert(*count);
+    st_insert(nodeCountTable,(char *)regNode,(char *)count);
+  }
+
+  /* Reprogram region nodes */
+  arrayForEachItem(Ntk_Node_t *,regionArray,i,regNode) {
+    int numFanin;
+    boolean reenc,replaced;
+    bdd_node **orgVars,**auxVars,*orgCube;
+
+    /* Skip, if it is a PI. */
+    if (Ntk_NodeTestIsPrimaryInput(regNode))
+      continue;
+    
+    /* Determine if the localAlt really needs to be re-encoded. This
+       is true if any of the fanin nodes have been reprogrammed. If
+       any fanin node of 'regNode' has a non NULL globalAlt, then it
+       means that fanin node has been reprogrammed. */
+    faninBdds = array_alloc(bdd_node *,0);
+    faninNodes = array_alloc(Ntk_Node_t *,0);
+    reenc = FALSE;
+    replaced = FALSE;
+    if (SpfdNodeReadLocalAlt(applData,regNode) !=
+	bdd_read_logic_zero(ddManager)) {
+      Ntk_NodeForEachFanin(regNode,j,fanin) {
+
+	/* If a particular wire is redundant/replaced, make the sink node
+	   independent of that node. */
+	if (!(st_lookup(wireTable,(char *)fanin,&sinkTable) &&
+	      st_lookup(sinkTable,(char *)regNode,&dummy))) {
+	  /* If not removed, is it replaced? */
+	  if (!(st_lookup(replaceTable,(char *)regNode,&sinkTable) &&
+		st_lookup(sinkTable,(char *)fanin,&newFanin))) {
+	    globalAlt = SpfdNodeReadGlobalAlternative(applData,fanin);
+	    if (globalAlt) { /* Reprogrammed? */
+	      array_insert_last(bdd_node *,faninBdds,globalAlt);
+	      array_insert_last(Ntk_Node_t *,faninNodes,fanin);
+	      reenc = TRUE;
+	    } else { /* No. So use the original global function */
+	      st_lookup(currBddReq,(char *)fanin,&ddTemp);
+	      array_insert_last(bdd_node *,faninBdds,ddTemp);
+	      array_insert_last(Ntk_Node_t *,faninNodes,fanin);
+	    }
+	  } else {
+	    /* The wire fanin --> regNode has been replaced by newFanin -->
+               regNode */
+	    globalAlt = SpfdNodeReadGlobalAlternative(applData,newFanin);
+	    assert(globalAlt);
+	    array_insert_last(bdd_node *,faninBdds,globalAlt);
+	    array_insert_last(Ntk_Node_t *,faninNodes,newFanin);
+	    reenc = TRUE;
+	    replaced = TRUE;
+	  }
+	} else {
+	  reenc = TRUE;
+	}
+      }
+    }
+      
+    if (reenc) { /* Reencode the localAlt */
+      /* Compute the encoding relation */
+      relNew = SpfdComputeNodeArrayRelation(applData,NIL(st_table),
+					      faninBdds,faninNodes,
+					      FALSE,&piSwap);
+      array_free(faninBdds);
+      array_free(faninNodes);
+      relOld = SpfdComputeNodeArrayRelation(applData,currBddReq,NIL(array_t),
+					      Ntk_NodeReadFanins(regNode),
+					      TRUE,&piSwap);
+      bdd_ref(encRel = bdd_bdd_and_abstract(ddManager,relNew,relOld,xCube));
+      bdd_recursive_deref(ddManager,relNew);
+      bdd_recursive_deref(ddManager,relOld);
+
+      if (piSwap) { /* If we have used alternate PI ids */
+	ddTemp = SpfdSwapPiAndAltPi(applData,encRel);
+	bdd_recursive_deref(ddManager,encRel);
+	encRel = ddTemp;
+      }
+      /* Now encRel is in terms of Y, Y'. Y variables are the node's
+         mdd ids. Y' are the auxIds of regNode's fanin nodes. One of
+         these fanin nodes could be a new node replacing an old node. */
+      /* Prepare variables for swapping and abstraction */
+      numFanin = Ntk_NodeReadNumFanins(regNode);
+      orgVars = ALLOC(bdd_node *,numFanin);
+      auxVars = ALLOC(bdd_node *,numFanin);
+      Ntk_NodeForEachFanin(regNode,k,fanin) {
+	orgVars[k] = bdd_bdd_ith_var(ddManager,Ntk_NodeReadMddId(fanin));
+	auxVars[k] = bdd_bdd_ith_var(ddManager,
+				     SpfdNodeReadAuxId(applData,fanin));
+      }
+      bdd_ref(orgCube = bdd_bdd_compute_cube(ddManager,orgVars,
+					     NIL(int),numFanin));
+
+      /* Re-encode the localAlt function. ddTemp is in terms of Y' */
+      localAlt = SpfdNodeReadLocalAlt(applData,regNode);
+      bdd_ref(ddTemp = bdd_bdd_and_abstract(ddManager,localAlt,encRel,orgCube));
+      SpfdNodeDeleteLocalAlt(applData,regNode);
+      bdd_recursive_deref(ddManager,encRel);
+      bdd_recursive_deref(ddManager,orgCube);
+
+      /* Check if the wire is replaced. Pay attention to auxVars and
+	 orgVars. */
+      /* Small caveat: Only here it is possible that the orgVar of
+         newFanin is already being used as auxId by one of the nodes
+         in the region. The situation can be as below: */
+      /* 12 -> 19, 15->24, 133->15, 18->23. During swapping, 133 will
+         be replace by 15. This will create a problem because 15->24
+         has not been done yet! A consolation is that the intersection
+         between the 'from' set and the 'two' set is only ONE. */
+      /* To avoid this problem, we do two step swap to be sure. */
+      if (replaced) {
+	bdd_node **secOrgVars,**secAuxVars;
+	int auxId,orgId,index;
+	
+	FREE(orgVars);
+	FREE(auxVars);
+	orgVars = ALLOC(bdd_node *,numFanin-1);
+	auxVars = ALLOC(bdd_node *,numFanin-1);
+	secOrgVars = ALLOC(bdd_node *,1);
+	secAuxVars = ALLOC(bdd_node *,1);
+	index = 0;
+	Ntk_NodeForEachFanin(regNode,k,fanin) {
+	  if (st_lookup(replaceTable,(char *)regNode,&sinkTable) &&
+	      st_lookup(sinkTable,(char *)fanin,&newFanin)) {
+	    orgId = Ntk_NodeReadMddId(newFanin);
+	    auxId = SpfdNodeReadAuxId(applData,newFanin);
+	    secOrgVars[0] = bdd_bdd_ith_var(ddManager,orgId);
+	    secAuxVars[0] = bdd_bdd_ith_var(ddManager,auxId);
+	  } else {
+	    orgId = Ntk_NodeReadMddId(fanin);
+	    auxId = SpfdNodeReadAuxId(applData,fanin);
+	    orgVars[index] = bdd_bdd_ith_var(ddManager,orgId);
+	    auxVars[index] = bdd_bdd_ith_var(ddManager,auxId);
+	    index++;
+	  }
+	}
+	bdd_ref(localAlt = bdd_bdd_swap_variables(ddManager,ddTemp,auxVars,
+						  orgVars,index));
+	bdd_recursive_deref(ddManager,ddTemp);
+	bdd_ref(ddTemp = bdd_bdd_swap_variables(ddManager,localAlt,
+						secAuxVars,secOrgVars,1));
+	bdd_recursive_deref(ddManager,localAlt);
+	localAlt = ddTemp;
+	FREE(secOrgVars);
+	FREE(secAuxVars);
+      } else {
+	bdd_ref(localAlt = bdd_bdd_swap_variables(ddManager,ddTemp,auxVars,
+						  orgVars,numFanin));
+	bdd_recursive_deref(ddManager,ddTemp);
+      }
+      FREE(orgVars);
+      FREE(auxVars);
+
+      SpfdNodeSetLocalAlt(applData,regNode,localAlt);
+    } else {
+      array_free(faninBdds);
+      array_free(faninNodes);
+    }
+
+    /* Compute the global function (only if it is needed, i.e, it is
+       present in the nodeCountTable) implemented by the alternate
+       function, localAlt, chosen from the SPFD. */
+    localAlt = SpfdNodeReadLocalAlt(applData,regNode);
+    if (st_lookup(nodeCountTable,(char *)regNode,&count) &&
+	!Ntk_NodeTestIsPrimaryInput(regNode) &&
+	!Ntk_NodeTestIsPrimaryOutput(regNode)) {
+      int size,id;
+      bdd_node **composeBdds;
+      
+      size = bdd_num_vars(ddManager);;
+      composeBdds = ALLOC(bdd_node *,size);
+      for (k = 0; k < size; k++) {
+	composeBdds[k] = bdd_bdd_ith_var(ddManager,k);
+      }
+
+      /* Here I don't have to worry about checking if a wire is redundant. The
+         localAlt of the node already is independent of source node of that
+         wire and so composing with the source node does not matter. But I do
+         need to check for wire replacement. */
+      Ntk_NodeForEachFanin(regNode,k,fanin) {
+	if (st_lookup(replaceTable,(char *)regNode,&sinkTable) &&
+	    st_lookup(sinkTable,(char *)fanin,&newFanin)) {
+	  id = Ntk_NodeReadMddId(newFanin);
+	  globalAlt = SpfdNodeReadGlobalAlternative(applData,newFanin);
+	  composeBdds[id] = globalAlt;
+	} else {
+	  id = Ntk_NodeReadMddId(fanin);
+	  globalAlt = SpfdNodeReadGlobalAlternative(applData,fanin);
+	  if (globalAlt) {
+	    composeBdds[id] = globalAlt;
+	  } else {
+	    st_lookup(currBddReq,(char *)fanin,(char **)&composeBdds[id]);
+	  }	  
+	}
+      }
+      localAlt = SpfdNodeReadLocalAlt(applData,regNode);
+      bdd_ref(globalAlt = bdd_bdd_vector_compose(ddManager,localAlt,
+						 composeBdds));
+      SpfdNodeSetGlobalAlternative(applData,regNode,globalAlt);
+      FREE(composeBdds);
+    }
+
+    /* Delete the global BDDs of fanin nodes if unnecessary */
+    Ntk_NodeForEachFanin(regNode,k,fanin) {
+      int *count;
+      if (st_lookup(nodeCountTable,(char *)fanin,&count)) {
+	(*count)--;
+	if (*count == 0) {
+	  st_delete(currBddReq,&fanin,&bdd1);
+	  bdd_recursive_deref(ddManager,bdd1);
+	  SpfdNodeDeleteGlobalAlternative(applData,fanin);
+	  st_delete(nodeCountTable,&fanin,&count);
+	  FREE(count);
+	}
+      }
+    }
+
+    /* Finally, delete the redundant wires */
+    nodeArray = array_dup(Ntk_NodeReadFanins(regNode));
+    arrayForEachItem(Ntk_Node_t *,nodeArray,j,fanin) {
+      /* If a particular wire is redundant, make the sink node independent of
+         the source node. */
+      if (st_lookup(wireTable,(char *)fanin,&sinkTable) &&
+	  st_lookup(sinkTable,(char *)regNode,&dummy)) {
+	/* remove the wire from the wireTable */
+	st_delete(sinkTable,&regNode,&dummy);
+	if (st_count(sinkTable) == 0) {
+	  st_delete(wireTable,&fanin,&sinkTable);
+	  st_free_table(sinkTable);
+	}
+	SpfdNetworkRemoveWire(network,fanin,regNode);
+      } else if (st_lookup(replaceTable,(char *)regNode,&sinkTable) &&
+		 st_lookup(sinkTable,(char *)fanin,&newFanin)) {
+	/* In this case I do not clean replaceTable as was done for
+           wireTable. The table is needed later. */
+	/* Add the new wire first and then remove the old wire. This
+           way the source node of the new wire will not be deleted if
+           it initially had a fanout of 1 and was in the TFI of the
+           old wire. newsource --> fanin --> regNode. If 'fanin' has
+           only one fanout then its entire TFI will be deleted, hence,
+           possibly deleteing newsource from the network. */
+	SpfdNetworkAddWire(network,newFanin,regNode);
+	SpfdNetworkRemoveWire(network,fanin,regNode);
+      }
+    }
+    array_free(nodeArray);
+    
+    /* Reprogram the node's table data structure. */
+    localAlt = SpfdNodeReadLocalAlt(applData,regNode);
+    SpfdReprogramNode(network,applData,regNode);
+    SpfdNodeDeleteLocalAlt(applData,regNode);
+  }
+
+  /* nodeCountTable need not be empty at this time as some wire may be 
+     removed and the count is not reduced appropriately in nodeCountTable. 
+     So, delete them explicitly. Defensive programming. */
+  st_foreach_item(nodeCountTable,stGen,&regNode,&count) {
+    st_delete(currBddReq,&regNode,&bdd1);
+    bdd_recursive_deref(ddManager,bdd1);
+    SpfdNodeDeleteGlobalAlternative(applData,regNode);
+    FREE(count);
+  }
+  st_free_table(nodeCountTable);
+  
+  /* Just reusing variable bound */
+  bound = st_count(currBddReq);
+  assert(bound == 0);
+  st_free_table(applData->currBddReq);
+  applData->currBddReq = NIL(st_table);
+  
+  return;
+} /* End of SpfdReprogramRegionNodes */
+
+
+/**Function********************************************************************
+
+  Synopsis [Update the regNode's Table data structure based on the
+  alternate implementation chosen for it in SpfdReprogramRegionNodes.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+void
+SpfdReprogramNode(
+  Ntk_Network_t *network,
+  SpfdApplData_t *applData,
+  Ntk_Node_t *regNode)
+{
+  bdd_node *localAlt;
+  bdd_node *bdd1,*bdd0;
+  bdd_manager *ddManager = applData->ddManager;
+  graph_t *partition = (graph_t *) Ntk_NetworkReadApplInfo(
+    network,PART_NETWORK_APPL_KEY);
+  Tbl_Table_t *table;
+  vertex_t *vertexPtr;
+  Mvf_Function_t *mvf;
+  mdd_t *tempMdd;
+    
+  /* Extract old local function from the partition */
+  vertexPtr = Part_PartitionFindVertexByMddId(partition,
+					      Ntk_NodeReadMddId(regNode));
+  mvf = Part_VertexReadFunction(vertexPtr);
+  /* First delete the old mvf */
+  Mvf_FunctionFree(mvf);
+  
+  /* Steps to reprogram the node.  1. Delete the old table associated with
+   * this node. The table can be deleted because in BLIF format tables have
+   * only a single output unlike BLIF-MV.  2. Create a new table and set it
+   * in the node.  3. Update the new local function in the partition */
+  table = Ntk_NodeReadTable(regNode);
+  Tbl_TableFree(table);
+      
+  bdd_ref(localAlt = SpfdNodeReadLocalAlt(applData,regNode));
+
+  /* If pattern simulation is performed, update node's static
+     probability and transition probability */
+  if (spfdPerfSim) {
+    float prob;
+    prob = Truesim_BddNodeComputeProbability(network,localAlt);
+    Truesim_NetworkSetNodeStaticProb(network,regNode,prob);
+    Truesim_NetworkSetNodeSwitchingProb(network,regNode,2*prob*(1-prob));
+  }
+  
+  /* Create the new table */
+  tempMdd = bdd_construct_bdd_t(ddManager,localAlt);
+  table = BuildNewTable(network,regNode,tempMdd);
+  Ntk_NodeSetTable(regNode,table);
+  mdd_free(tempMdd);
+      
+  /* Compute the node's new MVF and set it in the partition. */
+  mvf = array_alloc(bdd_t *,2);
+  bdd_ref(bdd1 = SpfdNodeReadLocalAlt(applData,regNode));
+  bdd_ref(bdd0 = bdd_not_bdd_node(bdd1));
+  array_insert(bdd_t *,mvf,0,bdd_construct_bdd_t(ddManager,bdd0));
+  array_insert(bdd_t *,mvf,1,bdd_construct_bdd_t(ddManager,bdd1));
+  Part_VertexSetFunction(vertexPtr,mvf);
+
+  return;
+} /* End of SpfdReprogramNode */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Remove the wire from --> to.]
+
+  SideEffects [None]
+
+******************************************************************************/
+void
+SpfdNetworkRemoveWire(
+  Ntk_Network_t *network,
+  Ntk_Node_t *from,
+  Ntk_Node_t *to)
+{
+  SpfdApplData_t *applData;
+  st_table *wiresRemoved;
+  st_table *sinkTable;
+  array_t *oldFanouts,*oldFanins;
+  array_t *newFanouts,*newFanins;
+  int i;
+  Ntk_Node_t *ntkNode;
+
+  applData = (SpfdApplData_t *) Ntk_NetworkReadApplInfo(network,
+							SPFD_NETWORK_APPL_KEY);
+  wiresRemoved = applData->wiresRemoved;
+  
+  assert(network == Ntk_NodeReadNetwork(from));
+  assert(network == Ntk_NodeReadNetwork(to));
+
+  oldFanouts = Ntk_NodeReadFanouts(from);
+  oldFanins = Ntk_NodeReadFanins(to);
+
+  newFanouts = array_alloc(Ntk_Node_t *,0);
+  newFanins = array_alloc(Ntk_Node_t *,0);
+
+  /* Remove 'from' from the fanins of 'to' */
+  if (spfdVerbose > 1)
+    (void) fprintf(vis_stdout,"** spfd info: Wire ");
+  arrayForEachItem(Ntk_Node_t *,oldFanins,i,ntkNode) {
+    if (ntkNode != from) {
+      array_insert_last(Ntk_Node_t *,newFanins,ntkNode);
+    } else {
+      if (spfdVerbose > 1)
+	(void) fprintf(vis_stdout,"%s --> ",Ntk_NodeReadName(from));
+    }
+  }
+  /* Remove 'to' from the fanouts of 'from' */
+  arrayForEachItem(Ntk_Node_t *,oldFanouts,i,ntkNode) {
+    if (ntkNode != to) {
+      array_insert_last(Ntk_Node_t *,newFanouts,ntkNode);
+    } else {
+      if (spfdVerbose > 1)
+	(void) fprintf(vis_stdout,"%s removed.\n",Ntk_NodeReadName(to));
+    }
+  }
+  
+  /* Insert this wire in the wiresRemoved table */
+  if (st_lookup(wiresRemoved,(char *)from,&sinkTable)) {
+    st_insert(sinkTable,(char *)to,(char *)to);
+  } else {
+    sinkTable = st_init_table(st_ptrcmp,st_ptrhash);
+    st_insert(sinkTable,(char *)to,(char *)to);
+    st_insert(wiresRemoved,(char *)from,(char *)sinkTable);
+  }
+  
+  /* Set the new arrays */
+  Ntk_NodeSetFanins(to,newFanins);
+  Ntk_NodeSetFanouts(from,newFanouts);
+
+  /* The fanin cone is redundant if 'from' had only a single fanout and it is
+     not a primary output. */
+  if (array_n(newFanouts) == 0 &&
+      !Ntk_NodeTestIsPrimaryOutput(from)) {
+    array_t *faninArray;
+    boolean check;
+    faninArray = array_dup(Ntk_NodeReadFanins(from));
+    arrayForEachItem(Ntk_Node_t *,faninArray,i,ntkNode) {
+      SpfdNetworkRemoveWire(network,ntkNode,from);
+      /* Register the wire removed */
+      if (st_lookup(wiresRemoved,(char *)ntkNode,&sinkTable)) {
+	st_insert(sinkTable,(char *)from,(char *)from);
+      } else {
+	sinkTable = st_init_table(st_ptrcmp,st_ptrhash);
+	st_insert(sinkTable,(char *)from,(char *)from);
+	st_insert(wiresRemoved,(char *)ntkNode,(char *)sinkTable);
+      }
+    }
+    array_free(faninArray);
+    check = Ntk_NodeRemoveFromNetwork(network,from,0,1,0);
+    assert(check);
+    if (spfdVerbose > 1)
+      (void) fprintf(vis_stdout,"** spfd info: Node %s removed.\n",
+		     Ntk_NodeReadName(from));    
+    st_insert(applData->nodesRemoved,(char *)from,(char *)0);
+  }
+
+  spfdNtkChanged = TRUE;
+  
+  return;
+  
+} /* End of SpfdNetworkRemoveWire */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Add a wire from --> to]
+
+  SideEffects [None]
+
+******************************************************************************/
+void
+SpfdNetworkAddWire(
+  Ntk_Network_t *network,
+  Ntk_Node_t *from,
+  Ntk_Node_t *to)
+{
+  array_t *oldFanouts,*oldFanins;
+
+  assert(network == Ntk_NodeReadNetwork(from));
+  assert(network == Ntk_NodeReadNetwork(to));
+
+  oldFanouts = Ntk_NodeReadFanouts(from);
+  oldFanins = Ntk_NodeReadFanins(to);
+
+  array_insert_last(Ntk_Node_t *,oldFanouts,to);
+  array_insert_last(Ntk_Node_t *,oldFanins,from);
+
+  if (spfdVerbose > 1)
+    (void) fprintf(vis_stdout,"** spfd info: Wire %s --> %s added\n",
+		   Ntk_NodeReadName(from),Ntk_NodeReadName(to));
+  spfdWiresAdded++;
+  
+  spfdNtkChanged = TRUE;
+  
+  return;
+  
+} /* End of SpfdNetworkAddWire */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Update the Table data structure of ntkNode. See tbl
+  package for more details on the Table data structure.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+static Tbl_Table_t *
+BuildNewTable(
+  Ntk_Network_t *network,
+  Ntk_Node_t *ntkNode,
+  mdd_t *mddFunc)
+{
+  bdd_manager *ddManager = Ntk_NetworkReadMddManager(network);
+  SpfdApplData_t *applData;
+  st_table *wiresRemoved;
+  Tbl_Table_t *table;
+  Tbl_Entry_t *entry;
+  int i,id,index;
+  Ntk_Node_t *loopNode;
+  Var_Variable_t *var;
+  array_t *faninIdArray,*cube,*nodeArray;
+  st_table *faninTable;
+  bdd_gen *ddGen;
+
+  applData = (SpfdApplData_t *) Ntk_NetworkReadApplInfo(network,
+							SPFD_NETWORK_APPL_KEY);
+  wiresRemoved = applData->wiresRemoved;
+
+  /* Allocaet a Table data structure */
+  table = Tbl_TableAlloc();
+
+  /* Find the true support. */
+  faninIdArray = mdd_get_support(ddManager,mddFunc);
+  faninTable = st_init_table(st_numcmp,st_numhash);
+  arrayForEachItem(int,faninIdArray,i,id) {
+    st_insert(faninTable,(char *)(long)id,(char *)(long)id);
+  }
+  array_free(faninIdArray);
+  
+  /* Delete wires that are not in the support of ntkNode. Collect
+     valid fanin ids in the same order as already present in the
+     node's original Table data structure. */
+  faninIdArray = array_alloc(int,0);
+  nodeArray = array_dup(Ntk_NodeReadFanins(ntkNode));
+  index = 0;
+  arrayForEachItem(Ntk_Node_t *,nodeArray,i,loopNode) {
+    id = Ntk_NodeReadMddId(loopNode);
+    if (!st_lookup(faninTable,(char *)(long)id,&id)) {
+      st_table *sinkTable;
+
+      if (spfdVerbose > 2)
+	(void) fprintf(vis_stdout,
+		       "** spfd info: removing wire in BuildNewTable.\n");
+      SpfdNetworkRemoveWire(network,loopNode,ntkNode);
+      /* Insert the wire removed for the purpose of statistics */
+      if (st_lookup(wiresRemoved,(char *)loopNode,&sinkTable)) {
+	st_insert(sinkTable,(char *)ntkNode,(char *)ntkNode);
+      } else {
+	sinkTable = st_init_table(st_ptrcmp,st_ptrhash);
+	st_insert(sinkTable,(char *)ntkNode,(char *)ntkNode);
+	st_insert(wiresRemoved,(char *)loopNode,(char *)sinkTable);
+      }
+    } else {
+      var = Ntk_NodeReadVariable(loopNode); 
+      array_insert_last(int,faninIdArray,id);
+      Tbl_TableSetVar(table,index,var,0);
+      index++;
+    }
+  }
+  array_free(nodeArray);
+  st_free_table(faninTable);
+  
+  /* Set the output variable */
+  var = Ntk_NodeReadVariable(ntkNode);
+  Tbl_TableSetVar(table,0,var,1/*output flag*/);
+
+  /* Set the defaults field to 0 */
+  entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+  Tbl_EntrySetValue(entry,0,0);
+  Tbl_TableDefaultSetEntry(table,entry,0/*output index */);
+
+  /* Add rows for each cube in the function */
+  /* cube is an array of int ids. The length of cube is the size of
+     the manager */
+  ddGen = bdd_first_cube(mddFunc,&cube);
+  /* If the function is zero, just add the zero cube */
+  if (bdd_gen_read_status(ddGen) == bdd_EMPTY) {
+    array_t *zeroCube;
+    int size;
+
+    size = bdd_num_vars(ddManager);
+    zeroCube = array_alloc(int,0);
+    for (i = 0; i < size; i++) {
+      array_insert_last(int,zeroCube,2);
+    }
+    TableAddCube(table,faninIdArray,zeroCube,0);
+    array_free(zeroCube);
+  } else {
+    do {
+      TableAddCube(table,faninIdArray,cube,1);
+    } while (bdd_next_cube(ddGen,&cube));
+  }  
+  bdd_gen_free(ddGen);
+
+  array_free(faninIdArray);
+
+  return table;
+} /* End of BuildNewTable */
+
+
+/**Function********************************************************************
+
+  Synopsis [convert a cube into a row entry of the Table. See tbl
+  package for more details.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+static void
+TableAddCube(
+  Tbl_Table_t *table,
+  array_t *faninIdArray,
+  array_t *cube,
+  int value)
+{
+  int rowIndex,colIndex,numFanins;
+  int mddId,phase;
+  Tbl_Entry_t *entry;
+
+  numFanins = Tbl_TableReadNumInputs(table);
+
+  /* Fill in the entries for the just added row */
+  rowIndex = Tbl_TableAddRow(table);
+  for (colIndex = 0; colIndex < numFanins; colIndex++) {
+    entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+    mddId = array_fetch(int,faninIdArray,colIndex);
+    phase = array_fetch(int,cube,mddId);
+    if (phase == 2) {
+      Tbl_EntrySetValue(entry,0,1);
+    } else {
+      Tbl_EntrySetValue(entry,phase,phase);
+    }
+    Tbl_TableSetEntry(table,entry,rowIndex,colIndex,0/*input flag*/);
+  }
+  /* Add an entry in the output column */
+  entry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+  Tbl_EntrySetValue(entry,value,value);
+  Tbl_TableSetEntry(table,entry,rowIndex,0,1/*output flag*/);
+
+} /* End of TableAddCube */
Index: vis_dev/vis-2.3/src/spfd/spfdReg.c
===================================================================
--- vis_dev/vis-2.3/src/spfd/spfdReg.c	(revision 14)
+++ vis_dev/vis-2.3/src/spfd/spfdReg.c	(revision 14)
@@ -0,0 +1,244 @@
+/**CFile***********************************************************************
+
+  FileName    [spfdReg.c]
+
+  PackageName [spfd]
+
+  Synopsis [Routines to compute a cluster of nodes for optimization.]
+
+  Description [Routines to compute a cluster of nodes for optimization.]
+
+  SeeAlso     [spfdOpt.c]
+
+  Author      [Balakrishna Kumthekar]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "spfdInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis [Find a cluster of nodes that are within regionDepth of
+  startNode.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+array_t *
+SpfdNodeComputeFanoutRegion(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *startNode,
+  int regionDepth)
+{
+  Ntk_Node_t *fanout,*ntkNode;
+  st_table *reached;
+  st_generator *stGen;
+  array_t *regionArray,*from,*new_;
+  int bound,i,j,k;
+
+  reached = st_init_table(st_ptrcmp,st_ptrhash);
+  if (Ntk_NodeTestIsPrimaryOutput(startNode)) {
+    st_insert(reached,(char *)startNode,(char *)1);
+  } else {
+    /* Sort the fanout array of startNode according to depth */
+    from = array_dup(Ntk_NodeReadFanouts(startNode));
+    array_sort(from,SpfdDepthCompare);
+    /* Put fanoutArray into reached */
+    arrayForEachItem(Ntk_Node_t *,from,i,fanout) {
+      if (!Ntk_NodeTestIsPrimaryOutput(fanout)) {
+	bound = 0;
+      } else {
+	bound = 1;
+      }
+      st_insert(reached,(char *)fanout,(char *)(long)bound);
+    }
+
+    /* Proceed for depth regionDepth */
+    for (i = 0; i < regionDepth; i++) {
+      new_ = array_alloc(Ntk_Node_t *,0);
+      arrayForEachItem(Ntk_Node_t *,from,j,ntkNode) {
+	st_lookup(reached,(char *)ntkNode,&bound);
+	if (!bound) {
+	  Ntk_NodeForEachFanout(ntkNode,k,fanout) {
+	    if (!st_lookup(reached,(char *)fanout,&bound)) {
+	      if (Ntk_NodeTestIsPrimaryOutput(fanout) ||
+		  Ntk_NodeReadNumFanouts(fanout) < 1 || /* Just to be safe */
+		  i == regionDepth - 1) {
+		bound = 1;
+	      } else {
+		bound = 0;
+	      }
+	      st_insert(reached,(char *)fanout,(char *)(long)bound);
+	      array_insert_last(Ntk_Node_t *,new_,fanout);
+	    }
+	  }
+	}
+      }
+      array_free(from);
+      from = new_;
+      array_sort(from,SpfdDepthCompare);
+    }
+    array_free(from);
+  
+    /* Finally make the startNode an internal node */
+    st_insert(reached,(char *)startNode,(char *)0);
+  }  
+
+  /* Put the nodes in reached according to their depth */
+  regionArray = array_alloc(Ntk_Node_t *,0);
+  st_foreach_item_int(reached,stGen,&fanout,&bound) {
+    array_insert_last(Ntk_Node_t *,regionArray,fanout);
+  }
+  array_sort(regionArray,SpfdDepthCompare);
+
+  if (applData->currRegionNodes) {
+    (void) fprintf(vis_stdout,
+		   "** spfd warning: Possible memory leak.\n");
+  }
+  applData->currRegionNodes = reached;
+  
+  return regionArray;
+  
+} /* End of SpfdNodeComputeFanoutRegion */
+
+
+/**Function********************************************************************
+
+  Synopsis [The returned array contains the nodes in TFI of startNode,
+  except the immediate fanin of startNode.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+array_t *
+SpfdNodeComputeTFIUntilDepth(
+  Ntk_Node_t *startNode,
+  int regionDepth)
+{
+  Ntk_Node_t *fanin,*ntkNode;
+  st_table *reached,*faninTable;
+  st_generator *stGen;
+  array_t *regionArray,*from,*new_;
+  char *dummy;
+  int i,j,k;
+
+  /* Make sure that startNode is not a PI to start with. */
+
+  if (Ntk_NodeTestIsPrimaryInput(startNode))
+    return NIL(array_t);
+
+  reached = st_init_table(st_ptrcmp,st_ptrhash);
+  faninTable = st_init_table(st_ptrcmp,st_ptrhash);
+  
+  /* Put the fanin array of startNode in faninTable */
+  from = array_dup(Ntk_NodeReadFanins(startNode));
+  arrayForEachItem(Ntk_Node_t *,from,i,ntkNode) {
+    st_insert(faninTable,(char *)ntkNode,(char *)1);
+  }
+
+  /* Proceed for depth regionDepth */
+  for (i = 0; i < regionDepth; i++) {
+    new_ = array_alloc(Ntk_Node_t *,0);
+    arrayForEachItem(Ntk_Node_t *,from,j,ntkNode) {
+      Ntk_NodeForEachFanin(ntkNode,k,fanin) {
+	if (!st_lookup(reached,(char *)fanin,&dummy) &&
+	    !st_lookup(faninTable,(char *)fanin,&dummy)) {
+	  st_insert(reached,(char *)fanin,(char *)1);
+	  array_insert_last(Ntk_Node_t *,new_,fanin);
+	}
+      }
+    }
+    array_free(from);
+    from = new_;
+  }
+  array_free(from);
+  st_free_table(faninTable);
+  
+  /* Put the nodes in reached according to their depth */
+  regionArray = array_alloc(Ntk_Node_t *,0);
+  st_foreach_item(reached,stGen,&ntkNode,&dummy) {
+    array_insert_last(Ntk_Node_t *,regionArray,ntkNode);
+  }
+  array_sort(regionArray,SpfdDepthCompare);
+
+  st_free_table(reached);
+  return regionArray;
+  
+} /* End of SpfdNodeComputeTFIUntilDepth */
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns in tfoNodes, the nodes in the transitive fanout of
+  node.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+void
+SpfdNodesInTFO(
+  Ntk_Network_t *network,
+  Ntk_Node_t *node,
+  st_table *tfoNodes)
+{
+  int i;
+  Ntk_Node_t *fanout;
+  
+  st_insert(tfoNodes,(char *)node,(char *)0);
+  Ntk_NodeForEachFanout(node,i,fanout) {
+    SpfdNodesInTFO(network,fanout,tfoNodes);
+  }
+
+  return;
+} /* End of SpfdNodesInTFO */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
Index: vis_dev/vis-2.3/src/spfd/spfdSpfd.c
===================================================================
--- vis_dev/vis-2.3/src/spfd/spfdSpfd.c	(revision 14)
+++ vis_dev/vis-2.3/src/spfd/spfdSpfd.c	(revision 14)
@@ -0,0 +1,486 @@
+/**CFile***********************************************************************
+
+  FileName    [spfdSpfd.c]
+
+  PackageName [spfd]
+
+  Synopsis [Routines to perform SPFD computation.]
+
+  Description [Routines to perform SPFD computation.]
+
+  SeeAlso     [spfdProg.c]
+
+  Author      [Balakrishna Kumthekar]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "spfdInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static bdd_node * ComputeAuxRel(SpfdApplData_t *applData, bdd_node *faninRel, Ntk_Node_t *from, int piSwap);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Given two functions represented by bdd1 and bdd0, compute
+  its SPFD.]
+
+  SideEffects [None]
+
+******************************************************************************/
+bdd_node *
+SpfdNodeComputeSpfdFromOnAndOffSet(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *regNode,
+  bdd_node *bdd1,
+  bdd_node *bdd0)
+{
+  bdd_manager *ddManager = applData->ddManager;
+  int numFanin = Ntk_NodeReadNumFanins(regNode);
+  bdd_node **yVars,**yAuxVars;
+  bdd_node *ddTemp,*rel,*spfd;
+  Ntk_Node_t *fanin;
+  int j,clean;
+
+  /* If bdd1 and bdd0 are not specified, replace bdd1 and bdd0 by the
+     node's local ON-set and OFF-set respectively */
+  clean = 0;
+  if (bdd1 == NIL(bdd_node) ||
+      bdd0 == NIL(bdd_node)) {
+    Ntk_Network_t *network;
+    network = Ntk_NodeReadNetwork(regNode);
+    bdd_ref(bdd1 = SpfdNodeReadLocalBdd(network,regNode));
+    bdd_ref(bdd0 = bdd_not_bdd_node(bdd1));
+    /* Delete bdd1 and bdd0 at the end.*/
+    clean = 1;
+  }
+  
+  /* Array of variables for swapping */
+  numFanin = Ntk_NodeReadNumFanins(regNode);
+  yVars = ALLOC(bdd_node *,numFanin);
+  yAuxVars = ALLOC(bdd_node *,numFanin);
+  Ntk_NodeForEachFanin(regNode,j,fanin) {
+    yVars[j] = bdd_bdd_ith_var(ddManager,Ntk_NodeReadMddId(fanin));
+    yAuxVars[j] = bdd_bdd_ith_var(ddManager,
+				  SpfdNodeReadAuxId(applData,fanin));
+  }
+
+  /* spfd is bdd1(y) * bdd0(y') + bdd1(y') * bdd0(y) */
+  bdd_ref(ddTemp = bdd_bdd_swap_variables(ddManager,bdd0,
+					  yVars,yAuxVars,numFanin));
+  bdd_ref(rel = bdd_bdd_and(ddManager,bdd1,ddTemp));
+  bdd_recursive_deref(ddManager,ddTemp);
+      
+  bdd_ref(ddTemp = bdd_bdd_swap_variables(ddManager,rel,
+					  yVars,yAuxVars,numFanin));
+  bdd_ref(spfd = bdd_bdd_or(ddManager,rel,ddTemp));
+  bdd_recursive_deref(ddManager,rel);
+  bdd_recursive_deref(ddManager,ddTemp);
+  FREE(yVars);
+  FREE(yAuxVars);
+
+  if (clean) {
+    bdd_recursive_deref(ddManager,bdd1);
+    bdd_recursive_deref(ddManager,bdd0);
+  }
+  return spfd;
+} /* End of SpfdNodeComputeSpfdFromOnAndOffSet */
+
+
+/**Function********************************************************************
+
+  Synopsis [Compute the SPFD of 'from', as the union of SPFDs of its
+  fanout wires.]
+
+  SideEffects [None]
+
+******************************************************************************/
+bdd_node *
+SpfdNodeComputeSpfdFromFanouts(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *from)
+{
+  bdd_manager *ddManager = applData->ddManager;
+  st_table *currBddReq;
+  st_table *wireTable,*wiresRemoved;
+  array_t *ordArray;
+  bdd_node *result,*var,*varAux,*ddTemp,*ddTemp2;
+  bdd_node *wireSpfd,*toSpfd,*fromSpfd,*xCube;
+  bdd_node *step1,*faninRel,*faninRelAux,*inter,*final;
+  bdd_node **firstCompose,**secondCompose;
+  bdd_node *logicZero;
+  Ntk_Node_t *fanin,*to;
+  int index,i,j;
+  int size,piSwap;
+
+
+  if (Ntk_NodeReadNumFanouts(from) < 1) {
+    (void) fprintf(vis_stdout,
+		   "** spfd error: Node %s has no fanouts.\n",
+		   Ntk_NodeReadName(from));
+    return NIL(bdd_node);
+  }
+  currBddReq = applData->currBddReq;
+  xCube = applData->currXCube;
+  logicZero = bdd_read_logic_zero(ddManager);
+
+  /* Compute the characteristic function of the fanin relation:
+   faninRel = \prod y_i == f_i(X) */
+  faninRel = SpfdComputeNodeArrayRelation(applData,currBddReq,NIL(array_t),
+					  Ntk_NodeReadFanins(from),
+					  TRUE,&piSwap);
+  
+  /* Convert faninRel(y,pi) to faninRel(\hat{y},pi) */
+  faninRelAux = ComputeAuxRel(applData,faninRel,from,piSwap);
+    
+  /* Compute SPFD wire by wire according to the order specified for
+     each fanout node. */
+  wireTable = applData->currWireTable;
+  wiresRemoved = applData->wiresRemoved;
+  bdd_ref(fromSpfd = logicZero);
+  Ntk_NodeForEachFanout(from,j,to) {
+
+    bdd_ref(result = bdd_read_one(ddManager));
+    ordArray = SpfdNodeReadFaninOrder(applData,to);
+    arrayForEachItem(Ntk_Node_t *,ordArray,i,fanin) {
+      var = bdd_bdd_ith_var(ddManager,Ntk_NodeReadMddId(fanin));
+      index = SpfdNodeReadAuxId(applData,fanin);
+      varAux = bdd_bdd_ith_var(ddManager,index);
+	
+      if (fanin != from) {
+	/* XNOR */
+	bdd_ref(ddTemp = bdd_bdd_xnor(ddManager,var,varAux));
+      } else {
+	/* XOR */
+	bdd_ref(ddTemp = bdd_bdd_xor(ddManager,var,varAux));
+      }
+      bdd_ref(ddTemp2 = bdd_bdd_and(ddManager,result,ddTemp));
+      bdd_recursive_deref(ddManager,result);
+      bdd_recursive_deref(ddManager,ddTemp);
+      result = ddTemp2;
+	
+      if (fanin == from)
+	break;
+    }
+      
+    /* Compute AND of result and the SPFD of 'to'. */
+    toSpfd = SpfdNodeReadSpfd(applData,to);
+    if (toSpfd == NIL(bdd_node)) {
+      (void) fprintf(vis_stderr,
+		     "** spfd error: Spfd expected but not found.\n");
+      (void) fprintf(vis_stderr, "To node:\n");
+      Ntk_NodePrint(vis_stderr, to, TRUE, TRUE);
+      (void) fprintf(vis_stderr, "From node:\n");
+      Ntk_NodePrint(vis_stderr, from, TRUE, TRUE);
+      fflush(vis_stderr);
+      assert(0);
+    }
+    bdd_ref(wireSpfd = bdd_bdd_and(ddManager,toSpfd,result));
+    bdd_recursive_deref(ddManager,result);
+
+    /* Convert wireSpfd from fanout space to fanin space */
+    /* Prepare the vectors for composition */
+    size = bdd_num_vars(ddManager);
+    firstCompose = ALLOC(bdd_node *,size);
+    secondCompose = ALLOC(bdd_node *,size);
+    for (i = 0; i < size; i++) {
+      firstCompose[i] = bdd_bdd_ith_var(ddManager,i);
+      secondCompose[i] = bdd_bdd_ith_var(ddManager,i);
+    }
+      
+    arrayForEachItem(Ntk_Node_t *,ordArray,i,fanin) {
+      int id,auxId;
+	
+      id = Ntk_NodeReadMddId(fanin);
+      auxId = SpfdNodeReadAuxId(applData,fanin);
+      st_lookup(currBddReq,(char *)fanin,(char **)&firstCompose[id]);
+      secondCompose[auxId] = firstCompose[id];
+    }
+      
+    /* Perform the steps of compose --> existential abstraction twice */
+    bdd_ref(step1 = bdd_bdd_vector_compose(ddManager,wireSpfd,firstCompose));
+    bdd_recursive_deref(ddManager,wireSpfd);
+    FREE(firstCompose);
+    bdd_ref(inter = bdd_bdd_and_abstract(ddManager,faninRel,step1,xCube));
+    bdd_recursive_deref(ddManager,step1);
+    
+    /* The second of compose --> existential abstraction steps */
+    bdd_ref(ddTemp = bdd_bdd_vector_compose(ddManager,inter,secondCompose));
+    bdd_recursive_deref(ddManager,inter);
+    FREE(secondCompose);
+    bdd_ref(final = bdd_bdd_and_abstract(ddManager,faninRelAux,
+					 ddTemp,xCube));
+    bdd_recursive_deref(ddManager,ddTemp);
+
+    /* Now 'final' is in the fanin space */
+    if (final == logicZero) {
+      st_table *sinkTable;
+      Ntk_Node_t *tempNode;
+      boolean add;
+
+      /* Check if this wire has already been removed. If yes, skip */
+      add = TRUE;
+      if (st_lookup(wiresRemoved,(char *)from,&sinkTable) &&
+	  st_lookup(sinkTable,(char *)to,&tempNode)) {
+	add = FALSE;
+      }
+
+      if (add) {
+        if (spfdVerbose > 2)
+	  (void) fprintf(vis_stdout,
+			 "** spfd info: wire %s --> %s has empty spfd.\n",
+			 Ntk_NodeReadName(from),Ntk_NodeReadName(to));
+	
+	/* Add to the wireTable */
+	if (st_lookup(wireTable,(char *)from,&sinkTable)) {
+	  st_insert(sinkTable,(char *)to,(char *)to);
+	} else {
+	  sinkTable = st_init_table(st_ptrcmp,st_ptrhash);
+	  st_insert(sinkTable,(char *)to,(char *)to);
+	  st_insert(wireTable,(char *)from,(char *)sinkTable);
+	}
+      }
+    }
+    
+    bdd_ref(ddTemp = bdd_bdd_or(ddManager,fromSpfd,final));
+    bdd_recursive_deref(ddManager,fromSpfd);
+    bdd_recursive_deref(ddManager,final);
+    
+    fromSpfd = ddTemp;
+  }
+  bdd_recursive_deref(ddManager,faninRel);
+  bdd_recursive_deref(ddManager,faninRelAux);
+    
+  /* Swap variables for fromSpfd if necessary */
+  if (piSwap) { /* If we have used alternate PI ids */
+    ddTemp = SpfdSwapPiAndAltPi(applData,fromSpfd);
+    bdd_recursive_deref(ddManager,fromSpfd);
+    fromSpfd = ddTemp;
+  }
+  
+  return fromSpfd;
+  
+} /* End of SpfdNodeComputeSpfdFromFanouts */
+
+
+/**Function********************************************************************
+
+  Synopsis [Compute the strongly connected components in the SPFD of
+  regNode. 'tempVars' are extra variables required during this
+  computation. For detailed description please refer to:
+
+  Subarnarekha Sinha and Robert K. Brayton. Implementation and use of
+  SPFDs in optimizaing Boolean networks. In International Conference
+  on Computer Aided Design, 1998.]
+
+  SideEffects [None]
+
+******************************************************************************/
+st_table *
+SpfdNodeComputeSCCs(
+  SpfdApplData_t *applData,
+  Ntk_Node_t *regNode,
+  bdd_node **tempVars)
+{
+  bdd_manager *ddManager = applData->ddManager;
+  st_table *inUseVars = applData->currInUseVars;
+  Ntk_Node_t *fanin;
+  st_table *SCC;
+  bdd_node *spfd,*spfd2,*auxCube;
+  bdd_node *ddTemp1,*ddTemp2,*logicZero,*faninCube;
+  bdd_node *Ny,*E1y,*E0y;
+  bdd_node *from,*To,*new_,*reached;
+  bdd_node **faninVars,**auxVars;
+  int i,numFanin,varsAllocated;
+
+  numFanin = Ntk_NodeReadNumFanins(regNode);
+  SCC = st_init_table(st_ptrcmp,st_ptrhash);
+  spfd = SpfdNodeReadSpfd(applData,regNode);
+  logicZero = bdd_read_logic_zero(ddManager);
+
+  if (spfd == logicZero)
+    return SCC;
+  
+  varsAllocated = 0;
+  /* Allocate variables if necessary */
+  if (tempVars == NIL(bdd_node *)) {
+    tempVars = SpfdAllocateTemporaryVariables(ddManager,inUseVars,numFanin);
+    varsAllocated = 1;
+  }
+  
+  faninVars = ALLOC(bdd_node *,numFanin);
+  auxVars = ALLOC(bdd_node *,numFanin);
+  Ntk_NodeForEachFanin(regNode,i,fanin) {
+    faninVars[i] = bdd_bdd_ith_var(ddManager,Ntk_NodeReadMddId(fanin));
+    auxVars[i] = bdd_bdd_ith_var(ddManager,
+				 SpfdNodeReadAuxId(applData,fanin));
+  }
+
+  bdd_ref(auxCube = bdd_bdd_compute_cube(ddManager,auxVars,
+					 NIL(int),numFanin));
+  /* Compute spfd2 = \exists_{\hat{y}} spfd(y,\hat{y}) *
+     spfd(\hat{y},\tilde{y}) */
+  bdd_ref(ddTemp1 = bdd_bdd_swap_variables(ddManager,spfd,faninVars,
+					   auxVars,numFanin));
+  bdd_ref(ddTemp2 = bdd_bdd_swap_variables(ddManager,ddTemp1,faninVars,
+					   tempVars,numFanin));
+  bdd_recursive_deref(ddManager,ddTemp1);
+  bdd_ref(spfd2 = bdd_bdd_and_abstract(ddManager,spfd,ddTemp2,auxCube));
+  bdd_recursive_deref(ddManager,ddTemp2);
+
+  /* SCC computation */
+  bdd_ref(faninCube = bdd_bdd_compute_cube(ddManager,faninVars,
+					   NIL(int),numFanin));
+  /* Compute N(y) = \exists_{\hat{y}} spfd(y,\hat{y}) */
+  bdd_ref(Ny = bdd_bdd_exist_abstract(ddManager,spfd,auxCube));
+  bdd_recursive_deref(ddManager,auxCube);
+
+  while (Ny != logicZero) {
+    /* To compute E1(y) perform the fixpoint image computation */
+    bdd_ref(from = bdd_bdd_pick_one_minterm(ddManager,Ny,faninVars,numFanin));
+    bdd_ref(reached = from);
+    do {
+      bdd_ref(ddTemp1 = bdd_bdd_and_abstract(ddManager,spfd2,from,faninCube));
+      bdd_recursive_deref(ddManager,from);
+      bdd_ref(To = bdd_bdd_swap_variables(ddManager,ddTemp1,tempVars,
+					  faninVars,numFanin));
+      bdd_recursive_deref(ddManager,ddTemp1);
+      bdd_ref(new_ = bdd_bdd_and(ddManager,To,bdd_not_bdd_node(reached)));
+      bdd_recursive_deref(ddManager,To);
+      bdd_ref(ddTemp1 = bdd_bdd_or(ddManager,reached,new_));
+      bdd_recursive_deref(ddManager,reached);
+      reached = ddTemp1;
+      from = new_;
+    } while (new_ != logicZero);
+
+    E1y = reached;
+    
+    /* E_0(y) = \exists_{\hat{y}} spfd(y,\hat{y}) * E_1(y) */
+    bdd_ref(ddTemp1 = bdd_bdd_and_abstract(ddManager,spfd,E1y,faninCube));
+    bdd_ref(E0y = bdd_bdd_swap_variables(ddManager,ddTemp1,auxVars,
+					 faninVars,numFanin));
+    bdd_recursive_deref(ddManager,ddTemp1);
+    
+    /* Update Ny: Ny = Ny * (E1y + E0y)' */
+    bdd_ref(ddTemp1 = bdd_bdd_or(ddManager,E1y,E0y));
+    bdd_ref(ddTemp2 = bdd_bdd_and(ddManager,Ny,bdd_not_bdd_node(ddTemp1)));
+    bdd_recursive_deref(ddManager,ddTemp1);
+    bdd_recursive_deref(ddManager,Ny);
+    Ny = ddTemp2;
+
+    /* Store E1y and E0y in an st_table */
+    st_insert(SCC,(char *)E1y,(char *)E0y);
+  }
+  bdd_recursive_deref(ddManager,faninCube);
+  bdd_recursive_deref(ddManager,Ny);
+  
+  FREE(auxVars);
+  FREE(faninVars);
+
+  if (varsAllocated) {
+    long id;
+    for (i = 0; i < numFanin; i++) {
+      id = (long) bdd_node_read_index(tempVars[i]);
+      st_delete(inUseVars,&id,NIL(char *));
+    }
+    FREE(tempVars);
+  }
+  
+  return SCC;
+
+} /* End of SpfdNodeComputeSCCs */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Convert faninRel which is interms of Y, to Y', the
+  auxillary variables.]
+
+  SideEffects [None]
+
+******************************************************************************/
+static bdd_node *
+ComputeAuxRel(
+  SpfdApplData_t *applData,
+  bdd_node *faninRel,
+  Ntk_Node_t *from,
+  int piSwap)
+{
+  bdd_node **fromVars,**toVars;
+  int numFi = Ntk_NodeReadNumFanins(from);
+  int k,altId;
+  Ntk_Node_t *fanin;
+  bdd_node *faninRelAux;
+  st_table *piAltVars;
+  bdd_manager *ddManager = applData->ddManager;
+  
+  piAltVars = applData->currPiAltVars;
+  
+  /* Collect variables for swapping. */
+  fromVars = ALLOC(bdd_node *,numFi);
+  toVars = ALLOC(bdd_node *,numFi);
+  Ntk_NodeForEachFanin(from,k,fanin) {
+    int id = Ntk_NodeReadMddId(fanin);
+    if (piSwap && st_lookup(piAltVars,(char *)(long)id,&altId)) {
+      fromVars[k] = bdd_bdd_ith_var(ddManager,altId);
+    } else {
+      fromVars[k] = bdd_bdd_ith_var(ddManager,id);
+    }
+    toVars[k] = bdd_bdd_ith_var(ddManager,SpfdNodeReadAuxId(applData,fanin));
+  }
+  bdd_ref(faninRelAux = bdd_bdd_swap_variables(ddManager,faninRel,fromVars,
+					       toVars,numFi));
+  FREE(fromVars);
+  FREE(toVars);
+
+  return faninRelAux;
+  
+} /* End of ComputeAuxRel */
Index: vis_dev/vis-2.3/src/spfd/spfdUtil.c
===================================================================
--- vis_dev/vis-2.3/src/spfd/spfdUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/spfd/spfdUtil.c	(revision 14)
@@ -0,0 +1,1045 @@
+/**CFile***********************************************************************
+
+  FileName    [spfdUtil.c]
+
+  PackageName [spfd]
+
+  Synopsis [Utility routines for the spfd package.]
+
+  Description [Utility routines for the spfd package.]
+
+  SeeAlso     [spfdAPI.c]
+
+  Author      [Balakrishna Kumthekar]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "spfdInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Initialize the application data structure of the package.]
+
+  SideEffects [None]
+
+******************************************************************************/
+SpfdApplData_t *
+SpfdInitializeApplData(
+  Ntk_Network_t *network)
+{
+  SpfdApplData_t *applData;
+  SpfdNodeData_t *data;
+  st_table *nodeToData;
+  lsGen gen;
+  Ntk_Node_t *node;
+  
+  applData = ALLOC(SpfdApplData_t, 1);
+
+  Ntk_NetworkAddApplInfo(network, SPFD_NETWORK_APPL_KEY,
+			 (Ntk_ApplInfoFreeFn) SpfdApplFreeCallback,
+			 (void *) applData);
+
+  nodeToData = applData->nodeToData = st_init_table(st_ptrcmp, st_ptrhash);
+  applData->ddManager = Ntk_NetworkReadMddManager(network);
+  applData->currXCube = NIL(bdd_node);
+  applData->currRegionNodes = NIL(st_table);
+  applData->currBddReq = NIL(st_table);
+  applData->currInUseVars = NIL(st_table);
+  applData->currPiAltVars = NIL(st_table);
+  /* Will be freed when the application quits */
+  applData->currWireTable = st_init_table(st_ptrcmp,st_ptrhash);
+  applData->currReplaceTable = st_init_table(st_ptrcmp,st_ptrhash);  
+  applData->wiresRemoved = st_init_table(st_ptrcmp,st_ptrhash);
+  applData->nodesRemoved = st_init_table(st_ptrcmp,st_ptrhash);
+  applData->placeData = NIL(SpfdPlaceData_t);
+
+  Ntk_NetworkForEachNode(network,gen,node) {
+    data = ALLOC(SpfdNodeData_t,1);
+    data->spfd = NIL(bdd_node);
+    data->localAlt = NIL(bdd_node);
+    data->alternative = NIL(bdd_node);
+    data->faninOrder = NIL(array_t);
+    data->parameters = NIL(bdd_node *);
+    data->numParams = 0;
+    data->auxId = -1;
+    data->locked = FALSE;
+    
+    st_insert(nodeToData,(char *)node,(char *)data);
+  }
+
+  return applData;
+
+} /* End of SpfdInitializeApplData */
+
+
+/**Function********************************************************************
+
+  Synopsis [Given a set of 'num' (st_count(SCC)) pairs of functions,
+  compute 'num' binary variables and allocate BDD ids to those
+  variables such that their level is above all the variables in the
+  support of the functions in SCC.]
+
+  SideEffects [None]
+
+******************************************************************************/
+bdd_node **
+SpfdComputeParameters(
+  SpfdApplData_t *applData,
+  st_table *SCC)
+{
+  bdd_manager *ddManager = applData->ddManager;
+  st_table *inUseVars = applData->currInUseVars;
+  int id,i,minLevel,size,used;
+  int index,numIsfs;
+  char *dummy;
+  st_generator *stGen;
+  bdd_node *bdd1,*bdd0;
+  bdd_node **parameters;
+
+  minLevel = bdd_num_vars(ddManager);
+  /* Find the topmost level among the SCC components SCC(Y,P) */
+  st_foreach_item(SCC,stGen,&bdd1,&bdd0) {
+    int level1,level0,tempInt;
+    level1 = bdd_get_level_from_id(ddManager,bdd_node_read_index(bdd1));
+    level0 = bdd_get_level_from_id(ddManager,bdd_node_read_index(bdd0));
+    tempInt = (level1 < level0) ? level1 : level0;
+    minLevel = (minLevel < tempInt) ? minLevel : tempInt;
+  }
+
+  numIsfs = st_count(SCC);
+  size = bdd_num_vars(ddManager);
+  used = st_count(inUseVars);
+  
+  /* Allocate required number of new variables above minLevel */
+  if (size - used < numIsfs) {
+    SpfdMddCreateVariables(ddManager,(numIsfs)-(size-used),minLevel);
+  }
+
+  /* Assign the parameters */
+  size = bdd_num_vars(ddManager);
+  index = numIsfs;
+  parameters = ALLOC(bdd_node *,numIsfs);
+  /* Assign the parameter variables */
+  for (i = 0; i < size; i++) {
+    if (index == 0)
+      break;
+    id = bdd_get_id_from_level(ddManager,i);
+    if (!st_lookup(inUseVars,(char *)(long)id,(char **)&dummy)) {
+      parameters[numIsfs-index] = bdd_bdd_ith_var(ddManager,id);
+      st_insert(inUseVars,(char *)(long)id,(char *)-1);
+      index--;
+    }
+  }
+
+  return parameters;
+} /* End of SpfdComputeParameters */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocate num of BDD variables.]
+
+  SideEffects [None]
+
+******************************************************************************/
+bdd_node **
+SpfdAllocateTemporaryVariables(
+  bdd_manager *ddManager,
+  st_table *inUseVars,
+  int num)
+{
+  int size,used,i,index,id;
+  char *dummy;
+  bdd_node **tempVars;
+
+  tempVars = ALLOC(bdd_node *,num);
+  size = bdd_num_vars(ddManager);
+  used = st_count(inUseVars);
+  if (size - used < num) {
+    /* Create variables at the end */
+    SpfdMddCreateVariables(ddManager,num-(size-used),size);
+  }
+  size = bdd_num_vars(ddManager);
+  index = num;
+  /* Assign the temporary variables */
+  for (i = size-1; i >= 0; i--) {
+    if (index == 0)
+      break;
+    id = bdd_get_id_from_level(ddManager,i);
+    if (!st_lookup(inUseVars,(char *)(long)id,(char **)&dummy)) {
+      tempVars[num-index] = bdd_bdd_ith_var(ddManager,id);
+      st_insert(inUseVars,(char *)(long)id,(char *)-1);
+      index--;
+    }
+  }
+
+  return tempVars;
+} /* End of SpfdAllocateTemporaryVariables */
+
+
+/**Function********************************************************************
+
+  Synopsis [Recyle existing BDD variables or allocate new ones.]
+
+  SideEffects [The BDD manager is changed accordingly to reflect the
+  addition of new variables.]
+
+******************************************************************************/
+void
+SpfdAllocateOrReuseAuxVariables(
+  Ntk_Network_t *network,
+  SpfdApplData_t *applData)
+{
+  st_table *currBddReq = applData->currBddReq;
+  bdd_manager *ddManager = applData->ddManager;
+  bdd_node *bdd1,*piSupport;
+  int numBdds,piSize,regSize,size,newVars;
+  int level,regNumVars;
+  int numPiAlt,index;
+  int *piIds;
+  Ntk_Node_t *node;
+  st_generator *stGen;
+  st_table *inUseVars,*nodeToData,*piAltVars;
+  lsGen gen;
+
+  numBdds = st_count(currBddReq);
+  
+  /* Check if any region nodes are PIs */
+  piAltVars = st_init_table(st_numcmp,st_numhash);
+  numPiAlt = 0;
+  st_foreach_item(currBddReq,stGen,&node,&bdd1) {
+    if (Ntk_NodeTestIsPrimaryInput(node)) {
+      int id = Ntk_NodeReadMddId(node);
+      st_insert(piAltVars,(char *)(long)id,(char *)(long)id);
+      numPiAlt++;
+    }
+  }
+
+  /* Put the variable ids in piSupport in inUseVars */
+  inUseVars = st_init_table(st_numcmp,st_numhash);
+
+  /* To be on the safe side we do not reuse PI bdd ids */
+  piSize = Ntk_NetworkReadNumPrimaryInputs(network);
+  piIds = ALLOC(int,piSize);
+  index = 0;
+  Ntk_NetworkForEachPrimaryInput(network,gen,node) {
+    int id;
+    id = Ntk_NodeReadMddId(node);
+    st_insert(inUseVars,(char *)(long)id,(char *)-1);
+    piIds[index] = id;
+    index++;
+  }
+  bdd_ref(piSupport = bdd_indices_to_cube(ddManager,piIds,piSize));
+  FREE(piIds);
+  
+  if (applData->currXCube) {
+    (void) fprintf(vis_stdout,
+		   "** spfd warning: Possible memory leak.\n");
+  }
+  applData->currXCube = piSupport;
+
+  regSize = numBdds;
+  size = bdd_num_vars(ddManager);
+  regNumVars = 2*regSize+piSize+numPiAlt;
+  if (size < regNumVars) {
+    newVars = regNumVars - size;
+    SpfdMddCreateVariables(ddManager,newVars,0);
+  } 
+  
+  /* Put the BDD ids of regionNodes and their immediate fanin in inUseVars */
+  st_foreach_item(currBddReq,stGen,&node,NIL(char *)) {
+    st_insert(inUseVars,(char *)(long)Ntk_NodeReadMddId(node),(char *)-1);
+  }
+   
+  /* Assign auxillary ids to region nodes and their immediate fanin.  */
+  nodeToData = applData->nodeToData;
+  level = 0;
+  size = bdd_num_vars(ddManager);
+  st_foreach_item(currBddReq,stGen,&node,NIL(char *)) {
+    int id;
+    while (level < size) {
+      id = bdd_get_id_from_level(ddManager,level);
+      if (!st_lookup(inUseVars,(char *)(long)id,NIL(char *))) {
+	SpfdNodeData_t *nodeData;
+	st_lookup(nodeToData,(char *)node,&nodeData);
+	nodeData->auxId = id;
+	st_insert(inUseVars,(char *)(long)id,(char *)-1);
+	level++;
+	break;
+      }
+      level++;
+    }
+  }
+
+  /* Assign alternate ids (these are in addition to auxIds) to those nodes in
+     currBddReq which are PIs */
+  st_foreach_item(currBddReq,stGen,&node,NIL(char *)) {
+    if (Ntk_NodeTestIsPrimaryInput(node)) {
+      int nodeId = Ntk_NodeReadMddId(node);
+      while (level < size) {
+	int id = bdd_get_id_from_level(ddManager,level);
+	if (!st_lookup(inUseVars,(char *)(long)id,NIL(char *))) {
+	  st_insert(piAltVars,(char *)(long)nodeId,(char *)(long)id);
+	  st_insert(inUseVars,(char *)(long)id,(char *)-1);
+	  level++;
+	  break;
+	}
+	level++;
+      }
+    }
+  }
+
+  if (applData->currInUseVars) {
+    (void) fprintf(vis_stdout,
+		   "** spfd warning: Possible memory leak.\n");
+  }
+  applData->currInUseVars = inUseVars;
+
+  if (applData->currPiAltVars) {
+    (void) fprintf(vis_stdout,
+		   "** spfd warning: Possible memory leak.\n");
+  }
+  applData->currPiAltVars = piAltVars;
+
+  return;
+  
+} /* End of SpfdAllocateOrReuseAuxVariables */
+
+
+/**Function********************************************************************
+
+  Synopsis [Fanin nodes of each cluster node is ordered according to
+  the 'compareFunc'. The fanin nodes need to be ordered during SPFD
+  computation.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+void
+SpfdOrderFaninOfRegionNodes(
+  Ntk_Network_t *network,
+  SpfdApplData_t *applData,
+  int (*compareFunc)(const void *, const void *))
+{
+  SpfdNodeData_t *nodeData;
+  st_table *nodeToData = applData->nodeToData;
+  st_table *regionNodes = applData->currRegionNodes;
+  st_generator *stGen;
+  Ntk_Node_t *regNode,*fanin;
+  int i,bound;
+  boolean found;
+  
+  st_foreach_item(regionNodes,stGen,&regNode,NIL(char *)) {
+    array_t *tempArray;
+    /* Atleast one fanin of regNode should be in regionNodes */
+    found = FALSE;
+    Ntk_NodeForEachFanin(regNode,i,fanin) {
+      if (st_lookup(regionNodes,(char *)fanin,&bound) &&
+	  !bound &&
+	  !Ntk_NodeTestIsPrimaryInput(fanin) &&
+	  !Ntk_NodeTestIsPrimaryOutput(fanin)) {
+	found = TRUE;
+	break;
+      }
+    }
+    if (found) {
+      tempArray = array_dup(Ntk_NodeReadFanins(regNode));
+      array_sort(tempArray,compareFunc);
+      st_lookup(nodeToData,(char *)regNode,&nodeData);
+      if (nodeData->faninOrder) {
+	(void) fprintf(vis_stdout,
+		       "** spfd warning: Possible memory leak.\n");
+      }
+      nodeData->faninOrder = tempArray;
+    }
+  }
+
+  return;
+} /* End of SpfdOrderFaninOfRegionNodes */
+
+
+/**Function********************************************************************
+
+  Synopsis [Compare the convex combination of switched capacitance and
+  topological depth of two nodes.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+int
+SpfdSwitchedCapAndDepthCompare(
+  const void *obj1,
+  const void *obj2)
+{
+  SpfdApplData_t *applData;
+  st_table *regionNodes;
+  Ntk_Node_t *node1,*node2;
+  Ntk_Network_t *network;
+  float weight1,weight2;
+  float switch1,switch2;
+  float load1,load2;
+  int depth1,depth2;
+  int status;
+  int dummy;
+  
+  node1 = *(Ntk_Node_t **)obj1;
+  node2 = *(Ntk_Node_t **)obj2;
+  assert(Ntk_NodeReadNetwork(node1) == Ntk_NodeReadNetwork(node2));
+  network = Ntk_NodeReadNetwork(node1);
+  applData = (SpfdApplData_t *) Ntk_NetworkReadApplInfo(network,
+							SPFD_NETWORK_APPL_KEY);
+  regionNodes = applData->currRegionNodes;
+
+  status = st_lookup(regionNodes,(char *)node1,&dummy);
+  if (!status || dummy ||
+      Ntk_NodeTestIsPrimaryOutput(node1) ||
+      Ntk_NodeTestIsPrimaryInput(node1)) {
+    weight1 = -1.0;
+  } else {
+    switch1 = Truesim_NetworkReadNodeSwitchingProb(network,node1);
+    load1 = Truesim_NetworkReadNodeLoad(network,node1);
+    depth1 = Truesim_NetworkReadNodeDepth(network,node1);
+    weight1 = spfdAlpha * load1 * switch1 + (1.0-spfdAlpha)*depth1;
+  }
+
+  status = st_lookup(regionNodes,(char *)node2,&dummy);
+  if (!status || dummy ||
+      Ntk_NodeTestIsPrimaryOutput(node2) ||
+      Ntk_NodeTestIsPrimaryInput(node2)) {
+    weight2 = -1.0;
+  } else {
+    switch2 = Truesim_NetworkReadNodeSwitchingProb(network,node2);
+    load2 = Truesim_NetworkReadNodeLoad(network,node2);
+    depth2 = Truesim_NetworkReadNodeDepth(network,node2);
+    weight2 = spfdAlpha * load2 * switch2 + (1.0-spfdAlpha)*depth2;
+  }
+  
+  if (weight1 > weight2)
+    return -1;
+  else if (weight1 == weight2)
+    return 0;
+  else
+    return 1;
+
+} /* End of SpfdSwitchedCapAndDepthCompare */
+
+
+/**Function********************************************************************
+
+  Synopsis [Compare the convex combination of fanout count and the 
+  node's topological depth.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+int
+SpfdFanoutCountAndDepthCompare(
+  const void *obj1,
+  const void *obj2)
+{
+  SpfdApplData_t *applData;
+  st_table *regionNodes;
+  Ntk_Node_t *node1,*node2;
+  Ntk_Network_t *network;
+  float weight1,weight2;
+  float load1,load2;
+  int depth1,depth2;
+  int status;
+  int dummy;
+  
+  node1 = *(Ntk_Node_t **)obj1;
+  node2 = *(Ntk_Node_t **)obj2;
+  assert(Ntk_NodeReadNetwork(node1) == Ntk_NodeReadNetwork(node2));
+  network = Ntk_NodeReadNetwork(node1);
+  applData = (SpfdApplData_t *) Ntk_NetworkReadApplInfo(network,
+							SPFD_NETWORK_APPL_KEY);
+  regionNodes = applData->currRegionNodes;
+
+  status = st_lookup(regionNodes,(char *)node1,&dummy);
+  if (!status || dummy ||
+      Ntk_NodeTestIsPrimaryOutput(node1) ||
+      Ntk_NodeTestIsPrimaryInput(node1)) {
+    weight1 = -1.0;
+  } else {
+    load1 = Ntk_NodeReadNumFanouts(node1);
+    depth1 = Truesim_NetworkReadNodeDepth(network,node1);
+    weight1 = spfdAlpha * load1 + (1.0-spfdAlpha)*depth1;
+  }
+
+  status = st_lookup(regionNodes,(char *)node2,&dummy);
+  if (!status || dummy ||
+      Ntk_NodeTestIsPrimaryOutput(node2) ||
+      Ntk_NodeTestIsPrimaryInput(node2)) {
+    weight2 = -1.0;
+  } else {
+    load2 = Ntk_NodeReadNumFanouts(node2);
+    depth2 = Truesim_NetworkReadNodeDepth(network,node2);
+    weight2 = spfdAlpha * load2 + (1.0-spfdAlpha)*depth2;
+  }
+
+  if (weight1 > weight2)
+    return -1;
+  else if (weight1 == weight2)
+    return 0;
+  else
+    return 1;
+
+} /* End of SpfdFanoutContAndDepthCompare */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compare the topological depth of two nodes.]
+
+  SideEffects [None]
+
+******************************************************************************/
+int
+SpfdDepthCompare(
+  const void *obj1,
+  const void *obj2)
+{
+  Ntk_Network_t *network;
+  Ntk_Node_t *node1 = *(Ntk_Node_t **)obj1;
+  Ntk_Node_t *node2 = *(Ntk_Node_t **)obj2;
+  int depth1,depth2;
+  
+  assert(Ntk_NodeReadNetwork(node1) == Ntk_NodeReadNetwork(node2));
+  network = Ntk_NodeReadNetwork(node1);
+
+  depth1 = Truesim_NetworkReadNodeDepth(network,node1);
+  depth2 = Truesim_NetworkReadNodeDepth(network,node2);
+
+  if (depth1 < depth2)
+    return -1;
+  else if (depth1 == depth2)
+    return 0;
+  else
+    return 1;
+  
+} /* End of SpfdDepthCompare */
+
+
+/**Function********************************************************************
+
+  Synopsis [Same as SpfdDepthCompare, but the nodes will be sorted in
+  descending order when used by qsort.]
+
+  SideEffects [None]
+
+******************************************************************************/
+int
+SpfdDescendDepthCompare(
+  const void *obj1,
+  const void *obj2)
+{
+  Ntk_Network_t *network;
+  Ntk_Node_t *node1 = *(Ntk_Node_t **)obj1;
+  Ntk_Node_t *node2 = *(Ntk_Node_t **)obj2;
+  int depth1,depth2;
+  
+  assert(Ntk_NodeReadNetwork(node1) == Ntk_NodeReadNetwork(node2));
+  network = Ntk_NodeReadNetwork(node1);
+
+  depth1 = Truesim_NetworkReadNodeDepth(network,node1);
+  depth2 = Truesim_NetworkReadNodeDepth(network,node2);
+
+  if (depth1 > depth2)
+    return -1;
+  else if (depth1 == depth2)
+    return 0;
+  else
+    return 1;
+  
+} /* End of SpfdDescendDepthCompare */
+
+
+/**Function********************************************************************
+
+  Synopsis [This procedure calls the mdd_create_variables in order to create 
+  new variables.]
+  
+  Description [ This procedure calls the mdd_create_variables in order to
+  create new variables. IMPORTANT: The mdd_create_variables
+  procedure creates the variables in succession. So if new variables are
+  required that are not in succession, those will not be created and hence
+  cannot be used. This procedure takes as arguments the DD manager and the
+  number of variables that need to be added to the manager.]
+
+  SideEffects [It modifies the manager->hook->mdd field.]
+
+  SeeAlso []
+
+******************************************************************************/
+void
+SpfdMddCreateVariables(mdd_manager *mgr,     
+		   int numVarsToBeAdded,
+		   int level)
+{
+    array_t *mvar_values;
+    array_t *mvar_names = NIL(array_t);
+    array_t *mvar_strides = NIL(array_t);
+    int i,two_values,idBeforeLevel,size;
+
+    if (level > (size = bdd_num_vars(mgr)))
+      level = size;
+    if (level <= 0)
+      idBeforeLevel = bdd_get_id_from_level(mgr,0);
+    else
+      idBeforeLevel = bdd_get_id_from_level(mgr,level-1);
+
+    if (numVarsToBeAdded <= 0) return;
+    
+    /* Create 2 mvar values 0,1 */
+    mvar_values = array_alloc(int, numVarsToBeAdded);    
+
+    /* Assume we create only Bdd variables here */
+    two_values = 2;
+    for(i = 0; i < numVarsToBeAdded; i++) {
+      array_insert(int, mvar_values, i, two_values);
+    }
+
+    /* creates the mdd variables and updates the mvar_list field */
+    mdd_create_variables_after(mgr, idBeforeLevel,mvar_values, 
+    			       mvar_names, mvar_strides);
+    
+    array_free(mvar_values);
+
+} /* End of SpfdMddCreateVariables */
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns a BDD containing minterms such that the discriminant for
+  those minterms in f is equal to that in g.]
+
+  Description [Returns a BDD containing minterms such that the discriminant for
+  those minterms in f is equal to that in g. Used in bdd_add_apply().]
+
+  SideEffects [None]
+
+  SeeAlso     [cuddAddApply.c]
+
+******************************************************************************/
+bdd_node *
+SpfdAddEqual(
+  bdd_manager *ddManager,
+  bdd_node **f,
+  bdd_node **g)
+{
+  bdd_node *zero, *one;
+
+  zero = bdd_read_zero(ddManager);
+  one = bdd_read_one(ddManager);
+
+  if(*f == *g) {
+    return one;
+  }
+
+  if(bdd_is_constant(*f) && bdd_is_constant(*g)) {
+      return zero;
+  }
+  return NULL;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [Print the network in BLIF format to fileName.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+int
+SpfdNetworkWriteBlifFile(
+  Ntk_Network_t *network,
+  char *fileName)
+{
+  lsGen gen;
+  Ntk_Node_t *node;
+  FILE *fp;
+  int nameLen;
+  char *name;
+  
+  if ((fp = Cmd_FileOpen(fileName,"w",NIL(char *),1)) == NIL(FILE)) {
+    (void) fprintf(vis_stderr,
+		   "** spfd error: Could not open %s for writing.\n",
+		   fileName);
+    return 0;
+  }
+
+  (void) fprintf(fp,".model %s\n",Ntk_NetworkReadName(network));
+  (void) fprintf(fp,".inputs ");
+  nameLen = 0;
+  Ntk_NetworkForEachPrimaryInput(network,gen,node) {
+    name = Ntk_NodeReadName(node);
+    (void) fprintf(fp,"%s ",name);
+    nameLen += (strlen(name));
+    if (nameLen > 65) {
+      (void) fprintf(fp,"\\\n");
+      nameLen = 0;
+    }
+  }
+  (void) fprintf(fp,"\n");
+
+  nameLen = 0;
+  (void) fprintf(fp,".outputs ");
+  Ntk_NetworkForEachPrimaryOutput(network,gen,node) {
+    name = Ntk_NodeReadName(node);
+    (void) fprintf(fp,"%s ",name);
+    nameLen += (strlen(name));
+    if (nameLen > 65) {
+      (void) fprintf(fp,"\\\n");
+      nameLen = 0;
+    }    
+  }
+  (void) fprintf(fp,"\n");
+  
+  Ntk_NetworkForEachNode(network,gen,node) {
+    if (!Ntk_NodeTestIsPrimaryInput(node)) {
+      if (Ntk_NodeReadNumFanins(node) > 0 ||
+	  Ntk_NodeReadNumFanouts(node) > 0) {
+	Tbl_TableWriteBlifToFile(Ntk_NodeReadTable(node),fp);
+      } else if (Ntk_NodeTestIsPrimaryOutput(node)) {
+	/* Sometimes output node can be redundant. Very unlikely,
+	   but output it anyway because we cannot skip primary
+	   outputs of a network. */
+	(void) fprintf(fp,".names %s\n",Ntk_NodeReadName(node));
+      }
+    }
+  }
+
+  (void) fprintf(fp,".end\n");
+
+  fclose(fp);
+  
+  return 1;
+  
+} /* End of SpfdNetworkWriteBlifFile */
+
+
+/**Function********************************************************************
+
+  Synopsis [Compute the relation of the functions specified in either
+  nodeBdds and currBddReq. If 'useMddIds' is TRUE use node (from
+  nodeArray) MDD ids else use node aux Ids. Return value of 'piSwap' is
+  used in the calling function only when 'useMddIds' is TRUE. ]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+bdd_node *
+SpfdComputeNodeArrayRelation(
+  SpfdApplData_t *applData,
+  st_table *currBddReq,
+  array_t *nodeBdds,
+  array_t *nodeArray,
+  boolean useMddIds,
+  int *piSwap)
+{
+  bdd_manager *ddManager = applData->ddManager;
+  st_table *piAltVars = applData->currPiAltVars;
+  Ntk_Node_t *node;
+  array_t *idArray;
+  bdd_node *ddTemp,*ddTemp2,*result;
+  bdd_node *bdd1,*var;
+  int j,id;
+
+  *piSwap = 0;
+
+  if (currBddReq) {
+    nodeBdds = array_alloc(bdd_node *,0);
+    arrayForEachItem(Ntk_Node_t *,nodeArray,j,node) {
+      st_lookup(currBddReq,(char *)node,&bdd1);
+      array_insert_last(bdd_node *,nodeBdds,bdd1);
+    }
+  }
+  idArray = array_alloc(int,0);
+  if (useMddIds) { /* Use node MDD Ids or alternate Ids for PIs */
+    int altId;
+    arrayForEachItem(Ntk_Node_t *,nodeArray,j,node) {
+      id = Ntk_NodeReadMddId(node);
+      if (Ntk_NodeTestIsPrimaryInput(node)) {
+	st_lookup(piAltVars,(char *)(long)id,&altId);
+	array_insert_last(int,idArray,altId);
+	*piSwap = 1;
+      } else {
+	array_insert_last(int,idArray,id);
+      }
+    }
+  } else { /* Use node Aux Ids */
+    arrayForEachItem(Ntk_Node_t *,nodeArray,j,node) {
+      array_insert_last(int,idArray,SpfdNodeReadAuxId(applData,node));
+    }    
+  }
+  bdd_ref(result = bdd_not_bdd_node(bdd_read_logic_zero(ddManager)));
+  arrayForEachItem(Ntk_Node_t *,nodeArray,j,node) {
+    bdd1 = array_fetch(bdd_node *,nodeBdds,j);
+    var = bdd_bdd_ith_var(ddManager,array_fetch(int,idArray,j));
+    bdd_ref(ddTemp = bdd_bdd_xnor(ddManager,var,bdd1));
+    bdd_ref(ddTemp2 = bdd_bdd_and(ddManager,ddTemp,result));
+    bdd_recursive_deref(ddManager,result);
+    bdd_recursive_deref(ddManager,ddTemp);
+    result = ddTemp2;
+  }
+
+  if (currBddReq)
+    array_free(nodeBdds);
+  array_free(idArray);
+  
+  return result;
+
+} /* End of SpfdComputeNodeArrayRelation */
+
+
+/**Function********************************************************************
+
+  Synopsis [Swap the BDD variables of primary inputs and it's
+  auxillary BDD ids.]
+
+  SideEffects [None]
+
+******************************************************************************/
+bdd_node *
+SpfdSwapPiAndAltPi(
+  SpfdApplData_t *applData,
+  bdd_node *fun)
+{
+  bdd_manager *ddManager = applData->ddManager;
+  bdd_node **fromVars;
+  bdd_node **toVars;
+  bdd_node *ddTemp;
+  st_table *piAltVars = applData->currPiAltVars;
+  st_generator *stGen;
+  int i,num = st_count(piAltVars);
+  int id,altId;
+      
+  fromVars = ALLOC(bdd_node *,num);
+  toVars = ALLOC(bdd_node *,num);
+  i = 0;
+  st_foreach_item_int(piAltVars,stGen,&id,&altId) {
+    fromVars[i] = bdd_bdd_ith_var(ddManager,altId);
+    toVars[i] = bdd_bdd_ith_var(ddManager,id);
+    i++;
+  }
+  bdd_ref(ddTemp = bdd_bdd_swap_variables(ddManager,fun,fromVars,toVars,num));
+
+  FREE(fromVars);
+  FREE(toVars);
+  
+  return ddTemp;
+} /* End of SpfdSwapPiAndAltPi */
+
+
+/**Function********************************************************************
+
+  Synopsis [The node's BDD is returned as it is without increasing the
+  reference count.]
+
+  SideEffects [None]
+
+******************************************************************************/
+bdd_node *
+SpfdNodeReadLocalBdd(
+  Ntk_Network_t *network,
+  Ntk_Node_t *node)
+{
+  vertex_t *vertexPtr;
+  Mvf_Function_t *mvf;
+  graph_t *partition =
+    (graph_t *) Ntk_NetworkReadApplInfo(network,PART_NETWORK_APPL_KEY);
+  bdd_node *bdd1;
+    
+  vertexPtr = Part_PartitionFindVertexByMddId(partition,
+					      Ntk_NodeReadMddId(node));
+  mvf = Part_VertexReadFunction(vertexPtr);
+  bdd1 = bdd_extract_node_as_is(array_fetch(bdd_t *,mvf,1));
+
+  return bdd1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [Extract 'percent'\% vectors from the patternArray.]
+
+  SideEffects        [None]
+
+******************************************************************************/
+array_t *
+SpfdFetchInternalPatternArray(
+  array_t *patternArray,
+  int percent,
+  double randomValue)
+{
+  array_t *returnArray;
+  int numVectors,start,end,i;
+
+  /* For internal simulations use 1/10th of the total input pattern vectors */
+  numVectors = array_n(patternArray);
+
+  start = (int)(randomValue*(double)numVectors);
+  end = start + (int)(numVectors*percent/100); 
+  
+  returnArray = array_alloc(char *,0);
+  if (end == start) {
+    array_insert_last(char *,returnArray,
+		      array_fetch(char *,patternArray,start));
+    return returnArray;
+  }
+
+  /* Allocate end - start + 1 size of returnArray */
+  for (i = start; i < end; i++) {
+    array_insert_last(char *,returnArray,
+		      array_fetch(char *,patternArray,i));
+  }
+
+  return returnArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis [Selects a random node or according to fanout count or
+  switched capacitance.]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+Ntk_Node_t *
+SpfdFindNode(
+  Ntk_Network_t *network,
+  array_t *nodeArray)
+{
+  Ntk_Node_t *node1,*maxNode = NIL(Ntk_Node_t);
+  int i;
+
+  if (!array_n(nodeArray))
+    return maxNode;
+  
+  if (spfdSortNodes == RANDOM) {
+    int index,num;
+    float randomValue;
+    
+    num = array_n(nodeArray);
+    if (num < 5) {
+      index = 0;
+    } else {
+      randomValue = ((double)util_random()/(double)(MODULUS1 - 2));
+      index = (int) (randomValue * (double)num);
+    }
+    maxNode = array_fetch(Ntk_Node_t *,nodeArray,index);
+  } else if (spfdSortNodes == MAXSWCAP) {
+    float swc1,maxSwc;
+    float switch1,load1;
+    
+    maxSwc = 0.0;
+    arrayForEachItem(Ntk_Node_t *,nodeArray,i,node1) {
+      switch1 = Truesim_NetworkReadNodeSwitchingProb(network,node1);
+      load1 = Truesim_NetworkReadNodeLoad(network,node1);
+      swc1 = load1 * switch1;
+      
+      if (swc1 > maxSwc) {
+	maxNode = node1;
+	maxSwc = swc1;
+      }
+    }
+  } else if (spfdSortNodes == MINSWCAP) {
+    float swc1,maxSwc;
+    float switch1,load1;
+    
+    maxSwc = MAXINT;
+    arrayForEachItem(Ntk_Node_t *,nodeArray,i,node1) {
+      switch1 = Truesim_NetworkReadNodeSwitchingProb(network,node1);
+      load1 = Truesim_NetworkReadNodeLoad(network,node1);
+      swc1 = load1 * switch1;
+      
+      if (swc1 < maxSwc) {
+	maxNode = node1;
+	maxSwc = swc1;
+      }
+    }
+  } else if (spfdSortNodes == MAXFANOUT) {
+    int numFanout,maxFanout;
+    
+    maxFanout = 0;
+    arrayForEachItem(Ntk_Node_t *,nodeArray,i,node1) {
+      numFanout = Ntk_NodeReadNumFanouts(node1);
+      if (numFanout > maxFanout) {
+	maxNode = node1;
+	maxFanout = numFanout;
+      }
+    }
+  } else if (spfdSortNodes == MINFANOUT) {
+    int numFanout,minFanout;
+    
+    minFanout = MAXINT;
+    arrayForEachItem(Ntk_Node_t *,nodeArray,i,node1) {
+      numFanout = Ntk_NodeReadNumFanouts(node1);
+      if (numFanout < minFanout) {
+	maxNode = node1;
+	minFanout = numFanout;
+      }
+    }
+  }
+  
+  return maxNode;
+  
+} /* End of SpfdFindNode */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
Index: vis_dev/vis-2.3/src/synth/synth.c
===================================================================
--- vis_dev/vis-2.3/src/synth/synth.c	(revision 14)
+++ vis_dev/vis-2.3/src/synth/synth.c	(revision 14)
@@ -0,0 +1,682 @@
+/**CFile***********************************************************************
+
+  FileName    [synth.c]
+
+  PackageName [synth]
+
+  Synopsis    [Commands for synthesize_network.]
+
+  Description [External procedures included in this module:
+		<ul>
+		<li> Synth_Init()
+		<li> Synth_End()
+		</ul>
+	Static procedures included in this module:
+		<ul>
+		<li> CommandSynthesizeNetwork()
+		<li> TimeOutHandle()
+		</ul> ]
+
+  Author      [Balakrishna Kumthekar, In-Ho Moon]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "synthInt.h"
+
+static char rcsid[] UNUSED = "$Id: synth.c,v 1.60 2005/05/16 06:22:00 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+extern	int		VerifyTreeMode;
+
+static	jmp_buf		timeOutEnv;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandSynthesizeNetwork(Hrc_Manager_t **hmgr, int argc, char **argv);
+static void TimeOutHandle(void);
+static int TestIsNetworkMultipleValued(Ntk_Network_t *network);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [This function initializes the synth package.]
+
+  Description [This function initializes the synth package.]
+
+  SideEffects [Installs the synthesize_network command.]
+
+  SeeAlso     [Synth_End()]
+
+******************************************************************************/
+void
+Synth_Init(void)
+{
+  Cmd_CommandAdd("synthesize_network", CommandSynthesizeNetwork, 0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [This function ends the synth package.]
+
+  Description [This function ends the synth package.]
+
+  SideEffects [none]
+
+  SeeAlso     [Synth_Init()]
+
+******************************************************************************/
+void
+Synth_End(void)
+{
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Implements the synthesize_network command.]
+
+  Description [This function synthesizes a network to have as few
+  literals as possible and outputs a blif file and an equation file.
+  Those files are the results of the synthesis. By default, the names
+  of the files are model_name.ml.blif and model_name.eq unless users
+  specify the model_name explicitly using -o option. But, when the
+  output blif file is read in sis, it may have slightly different
+  number of literals. This problem will be fixed in the later version.
+  Currently, this command can be used only with CUDD package.
+
+  Designs described in BLIF or BLIF-MV format can be synthesized by
+  this command. However, multiple valued variables are not
+  supported. Hence, signals in the designs described in BLIF-MV need
+  to be restricted to binary values.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+  CommandName [synthesize_network]
+
+  CommandSynopsis [Synthesizes a network using ZDD factorization method.]
+
+  CommandArguments [\[-d &lt;divisor&gt;\] \[-e\] \[-f &lt;factoringMethod&gt;\]
+  \[-h\] \[-i &lt;prefix&gt;\] \[-o &lt;fileHead&gt;\]
+  \[-r &lt;reachMethod&gt;\]
+  \[-t &lt;timeOut&gt;\] \[-v\] \[-A\] \[-O &lt;outputOrdering&gt;\]
+  \[-R &lt;reorder&gt;\] \[-T\]]
+
+  CommandDescription [This command synthesizes a network to have as few
+  literals as possible and outputs a blif file and an equation file.  Those
+  files are the results of the synthesis. By default, the names of the files
+  are model_name.ml.blif and model_name.eq unless users specify the model_name
+  explicitly using -o option. But, when the output blif file is read in sis, it
+  may have slightly different number of literals. This problem will be fixed in
+  the later version.  Currently, this command can be used only with CUDD
+  package.
+
+  Designs described in BLIF or BLIF-MV format can be synthesized by this
+  command. However, multiple valued variables are not supported. Hence, signals
+  in the designs described in BLIF-MV need to be restricted to binary values.
+
+  There are 4 divisor functions to find a good divisor of a function. Neither
+  of them consistently generates the best result. And, there are 2 factoring
+  methods: simple factoring and generic factoring. Also, neither of two always
+  does better than the other.  <p>
+
+  Command options:<p>
+
+  <dl>
+
+  <dt> -d &lt;divisor&gt;
+  <dd> Choose a divisor.<p>
+  <dd>
+  0 : Fast divisor. We find a divisor on a ZDD graph. As soon as any
+  shared node(variable) is found, the variable is returned as a divisor.
+  <p>
+
+  1 : (default) Least occuring literal divisor. If a variable occurs the least
+  frequently(but, should be more than one) in cubes, it returns the
+  variable as a divisor. <p>
+
+  2 : Most occuring literal divisor. If a variable occurs the most frequently
+  in cubes, it returns the variable as a divisor. <p>
+
+  3 : Level-0 divisor. It finds a divisor that is a level-0 cokernel.
+  <p>
+
+  <dt> -e
+  <dd> Dump the synthesized circuit in equation format also. Default is 
+  not to.  <p>
+
+  <dt> -f &lt;factoringMethod&gt;
+  <dd> Choose a factoring method.<p>
+  <dd>
+  0 : (default) Simple factoring. This method uses a simple recursion. First,
+  it finds a proper divisor of a function, then divide the function by the
+  divisor, then it gets a quotient and a remainder. And, it does the
+  same thing recursively for each divisor, quotient, and
+  remainder. <p>
+
+  1 : Generic factoring. This method is quite similar to the simple
+  factoring, but it does more in terms of considering cube-free and
+  common divisor and literal factoring. But, it does not always generate
+  better results than the simple factoring does. <p>
+
+  <dt> -h
+  <dd> Print the command usage. <p>
+
+  <dt> -i &lt;prefix&gt;
+  <dd> Specify the prefix of internal node names. By default, the prefix
+  is "_n". <p>
+
+  <dt> -o &lt;fileHead&gt;
+  <dd> Specify the output file name (without extension). By default, the model
+  name in a blif file is used. <p>
+
+  <dt> -r &lt;reachMethod&gt;
+  <dd> If the network is sequential, then use unreachable states as dont cares
+  in the optimization. By default no reachability analysis is performed. See
+  -A option of command compute_reach for more details. The various options
+  are:<p>
+  <dd>
+  0 : Do not use dont cares (default). <p>
+
+  1 : Use normal breadth first search method for reachability analysis. <p>
+
+  2 : Use high density traversal method for reachablity analysis. <p>
+
+  3 : Use approximate unreachable states(a subset of actual unreachable states)
+  as dont cares. <p>
+
+  <dt> -t &lt;timeOut&gt;
+  <dd> Time in seconds allowed to perform synthesize_network.  The default is
+  no limit.<p>
+
+  <dt> -v
+  <dd> Print debug information. <p>
+
+  <dt> -A
+  <dd> Allow realignment to ZDD/BDD after BDD/ZDD reordering, respectively.
+  This option is effective when only one reordering in BDD or ZDD is enabled.
+
+  <dt> -O &lt;outputOrdering&gt;
+  <dd> Choose an output ordering method. <p>
+  <dd>
+  0 : No ordering. <p>
+
+  1 : (default) Use support variable set of output functions. <p>
+
+  2 : Use BDD size of output functions. <p>
+
+  <dt> -R &lt;reorder&gt;
+  <dd> Allow reordering in BDD and/or ZDD. <p>
+  <dd>
+  0 or n : (default) No reordering neither in BDD nor in ZDD. <p>
+
+  1 or b : Allows reordering only in BDD, not in ZDD. <p>
+
+  2 or z : Allows reordering only in ZDD, not in BDD. <p>
+
+  3 or a : Allows reordering both in BDD and in ZDD. <p>
+
+  <dt> -T
+  <dd> Try to share more nodes during symbolic factorization. Existing
+  divisors are checked for potential reuse before extracting divisors from the
+  current boolean function.<p>
+
+  <\dl>
+  ]
+
+******************************************************************************/
+static int
+CommandSynthesizeNetwork(Hrc_Manager_t **hmgr,
+			 int argc,
+			 char **argv)
+{
+  Ntk_Network_t *network1;
+  Ntk_Node_t *node;
+  bdd_manager *ddManager;
+  int timeOutPeriod;
+  int createdMgr;
+  int factoring, divisor;
+  int unreachDC, verbosity;
+  int result, varOrdered;
+  long initialTime, finalTime;
+  char *filehead,*filename;
+  char *prefix;
+  FILE *fp;
+  int c;
+  lsList dummy = (lsList) 0;
+  lsGen gen;
+  Synth_InfoData_t *synthInfo;
+  char *reorder = NIL(char);
+  int reordering;
+  int trySharing;
+  int realign;
+  int outputOrdering;
+  boolean eqn;
+
+  if (bdd_get_package_name() != CUDD) {
+    (void) fprintf(vis_stderr,
+ "** synth error: synthesize_network can be used only with the CUDD package\n");
+    (void) fprintf(vis_stderr,
+		   "** synth error: Please link with CUDD package\n");
+    return 1;
+  }
+
+  /* To keep the Alpha compilers happy. */
+  network1 = NIL(Ntk_Network_t);
+  node = NIL(Ntk_Node_t);
+  ddManager = NIL(bdd_manager);
+  synthInfo = NIL(Synth_InfoData_t);
+
+  /* These are the default values. */
+  timeOutPeriod   = 0;
+  createdMgr      = 0;
+  factoring       = 0; /* Simple factoring algorithm. */
+  divisor         = 1; /* Quick divisor */
+  unreachDC       = 0; /* Do not use unreachable states as DCs */
+  filehead        = NIL(char);
+  filename        = NIL(char);
+  prefix          = NIL(char);
+  fp              = NIL(FILE);
+  reordering      = 0;
+  trySharing      = 0;
+  realign         = 0;
+  verbosity       = 0;
+  varOrdered      = 0;
+  outputOrdering  = 0;
+  eqn             = 0;
+  util_getopt_reset();
+
+  while((c = util_getopt(argc, argv, "d:ef:hi:o:r:t:vAO:R:TV:")) != EOF) {
+    switch(c) {
+    case 'd':
+      divisor = atoi(util_optarg);
+      if (divisor < 0 || divisor > 3)
+	goto usage;
+      break;
+    case 'e':
+      eqn = 1;
+      break;
+    case 'f':
+      factoring = atoi(util_optarg);
+      if (factoring < 0 || factoring > 1)
+	goto usage;
+      break;
+    case 'h':
+      goto usage;
+    case 'i':
+      prefix = util_strsav(util_optarg);
+      break;
+    case 'o':
+      filehead = util_strsav(util_optarg);
+      break;
+    case 'r':
+      unreachDC = atoi(util_optarg);
+      break;
+    case 't':
+      timeOutPeriod = atoi(util_optarg);
+      break;
+    case 'v':
+      verbosity = 1;
+      break;
+    case 'A':
+      realign = 1;
+      break;
+    case 'O':
+      outputOrdering = atoi(util_optarg);
+      if (outputOrdering < 0 || outputOrdering > 2)
+	goto usage;
+      SynthSetOutputOrdering(outputOrdering);
+      break;
+    case 'R':
+      reorder = util_strsav(util_optarg);
+      if (reorder[0] == '0' || reorder[0] == 'n')
+	reordering = 0;
+      else if (reorder[0] == '1' || reorder[0] == 'b')
+	reordering = 1;
+      else if (reorder[0] == '2' || reorder[0] == 'z')
+	reordering = 2;
+      else if (reorder[0] == '3' || reorder[0] == 'a')
+	reordering = 3;
+      else
+	goto usage;
+      break;
+    case 'T':
+      trySharing = 1;
+      break;
+    case 'V':
+      VerifyTreeMode = atoi(util_optarg);
+      break;
+    default:
+      if (util_optarg)
+	(void) fprintf(vis_stderr,
+			"** synth error: Unknown option %s\n",util_optarg);
+      else
+	(void) fprintf(vis_stderr,"** synth error: Unknown option ?\n");
+      goto usage;
+    }
+  }
+
+  if(Hrc_ManagerReadCurrentNode(*hmgr) == NIL(Hrc_Node_t)) {
+    (void)fprintf(vis_stderr,"** synth error: The hierarchy manager is empty.");
+    (void)fprintf(vis_stderr,"** synth error: Read in design.\n");
+    goto endgame;
+  }
+
+  network1 = (Ntk_Network_t *) 
+    Hrc_NodeReadApplInfo(Hrc_ManagerReadCurrentNode(*hmgr), 
+			 NTK_HRC_NODE_APPL_KEY);
+
+  if(network1 == NIL(Ntk_Network_t)) {
+    (void) fprintf(vis_stderr, "** synth error: There is no network. ");
+    (void) fprintf(vis_stderr,"** synth error:Use flatten_hierarchy.\n");
+    goto endgame;
+  }
+
+  /* Check if the current network has signals with multiple values. */
+  if (TestIsNetworkMultipleValued(network1)) {
+    (void) fprintf(vis_stderr,
+		   "** synth error: Circuit has multiple valued variables.\n");
+    (void) fprintf(vis_stderr,
+	"** synth error: This command works with boolean signals only.\n");
+    goto endgame;
+  }
+
+  if (!filehead)
+    filehead = util_strsav(Ntk_NetworkReadName(network1));
+
+  /* Check if the output equation file already exists */
+  if (eqn) {
+    filename = util_strcat3(filehead,".eq","");
+    fp = Cmd_FileOpen(filename,"r",NIL(char *),1);
+    if (fp) {
+      (void) fprintf(vis_stderr,
+		"** synth error: Output equation file %s already exists.\n",
+		filename);
+      (void) fprintf(vis_stderr,
+		"** synth error: Please specify another name.\n");
+      fclose(fp);
+      FREE(filename);
+      goto endgame;
+    }
+    FREE(filename);
+  }
+  /* Check if the output blif file already exists */
+  filename = util_strcat3(filehead,".ml.blif","");
+  fp = Cmd_FileOpen(filename,"r",NIL(char *),1);
+  if (fp) {
+    (void) fprintf(vis_stderr,
+		   "** synth error: Output blif file %s already exists.\n",
+		   filename);
+    (void) fprintf(vis_stderr,"** synth error: Please specify another name.\n");
+    fclose(fp);
+    FREE(filename);
+    goto endgame;
+  }
+  FREE(filename);
+
+  if(Ntk_NetworkReadNumPrimaryInputs(network1) !=
+     Ntk_NetworkReadNumInputs(network1)) {
+    (void) fprintf(vis_stderr,
+		   "** synth error: Pseudo inputs present in the network.\n");
+    (void) fprintf(vis_stderr,
+		   "** synth error: Cannot synthesize the network\n");
+    goto endgame;
+  }
+
+  ddManager = (bdd_manager *) Ntk_NetworkReadMddManager(network1);
+  if (ddManager == NIL(bdd_manager)) {
+    ddManager = (bdd_manager *)Ntk_NetworkInitializeMddManager(network1);
+    if (ddManager == NIL(bdd_manager)) {
+      (void) fprintf(vis_stderr,
+		     "** synth error: Could not create Mdd Manager\n");
+      goto endgame;
+    }
+    createdMgr = 1;
+  }
+
+  /* Check if the network has the variables ordered.
+   * For combinational synthesis we are only interested in the primary 
+   * input variables. But for sequential synthesis we need primary inputs,
+   * present state variables and next state variables (to use in 
+   * reachability analysis and use the unreachable states as dont cares).
+   */
+
+  if (Ord_NetworkTestAreVariablesOrdered(network1, Ord_InputAndLatch_c) == 
+      FALSE) {
+    Ord_NetworkOrderVariables(network1,Ord_RootsByDefault_c,
+			      Ord_NodesByDefault_c, FALSE,
+			      Ord_InputAndLatch_c,Ord_Unassigned_c,
+			      dummy,0);
+    varOrdered = 1;
+  }
+    
+  /* Start the timer. */
+  if (timeOutPeriod > 0){
+    (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
+    (void) alarm(timeOutPeriod);
+    if (setjmp(timeOutEnv) > 0) {
+      (void) fprintf(vis_stderr, "** synth warning: Timeout occurred after ");
+      (void) fprintf(vis_stderr, "%d seconds.\n", timeOutPeriod);
+      alarm(0);
+      goto endgame;
+    }
+  }
+
+  synthInfo = Synth_InitializeInfo(factoring,divisor,unreachDC,
+				   reordering,trySharing,realign,
+				   filehead,prefix,eqn);
+  if (!synthInfo)
+    goto endgame;
+
+  /* Synthesize.*/
+  initialTime = util_cpu_time();
+
+  result = Synth_SynthesizeNetwork(network1,NIL(graph_t), 
+				   NIL(st_table),synthInfo,
+				   verbosity);
+
+  finalTime = util_cpu_time();
+
+  if (result) {
+    (void) fprintf(vis_stdout, "%-20s%10ld\n", "analysis time =",
+		   (finalTime-initialTime)/1000);
+  } else {
+    (void) fprintf(vis_stdout, "** synth error: Could not synthesize.\n");
+  }
+
+  /* Set the mdd id's for all the nodes to unassigned if it
+   * was specifically set in this routine.
+   */
+  if (varOrdered) {
+    Ntk_NetworkForEachPrimaryInput(network1,gen,node) {
+      Ntk_NodeSetMddId(node,NTK_UNASSIGNED_MDD_ID);
+    }
+    Ntk_NetworkForEachLatch(network1,gen,node) {
+      Ntk_Node_t *shadow;
+      shadow = Ntk_NodeReadShadow(node);
+      Ntk_NodeSetMddId(node,NTK_UNASSIGNED_MDD_ID);    
+      Ntk_NodeSetMddId(shadow,NTK_UNASSIGNED_MDD_ID);    
+    }
+  }
+
+  if (createdMgr) {
+    mdd_quit((mdd_manager *)ddManager);
+    Ntk_NetworkSetMddManager(network1,NIL(mdd_manager));
+  }
+
+  if (reorder)
+    FREE(reorder);
+  if (filehead)
+    FREE(filehead);
+  if (prefix)
+    FREE(prefix);
+
+  if (synthInfo)
+    Synth_FreeInfo(synthInfo);
+
+  alarm(0);
+  return 0;  /* normal exit */
+
+ endgame:
+  if (varOrdered) {
+    Ntk_NetworkForEachNode(network1,gen,node) {
+      Ntk_NodeSetMddId(node,NTK_UNASSIGNED_MDD_ID);
+    }
+  }
+
+  if (createdMgr) {
+    mdd_quit((mdd_manager *)ddManager);
+    Ntk_NetworkSetMddManager(network1,NIL(mdd_manager));
+  }
+
+  if (reorder)
+    FREE(reorder);
+  if(filehead)
+    FREE(filehead);
+  if(prefix)
+    FREE(prefix);
+
+  if (synthInfo)
+    Synth_FreeInfo(synthInfo);
+
+  return 1;
+
+ usage:
+  (void) fprintf(vis_stderr, "usage: synthesize_network [-d divisor] [-e] [-f factoringMethod] [-h] [-i prefix] [-o fileHead] [-r reachMethod] [-t timeOut] [-v] [-A] [-O outputOrdering] [-R reorder] [-T]\n");
+  (void) fprintf(vis_stderr, "   -d n\t\tChoose a divisor function (0-4)\n");
+  (void) fprintf(vis_stderr, "   \t\t\t0: Fast divisor\n");
+  (void) fprintf(vis_stderr,
+		 "   \t\t\t1: Least occuring literal divisor (default)\n");
+  (void) fprintf(vis_stderr, "   \t\t\t2: Most occuring literal divisor\n");
+  (void) fprintf(vis_stderr, "   \t\t\t3: Level-0 kernel divisor\n");
+  (void) fprintf(vis_stderr, "   -e n\t\tOutput equation format file\n");
+  (void) fprintf(vis_stderr, "   -f n\t\tChoose a factoring method(0-1)\n");
+  (void) fprintf(vis_stderr, "   \t\t\t0: Simple factoring (default)\n");
+  (void) fprintf(vis_stderr, "   \t\t\t1: Generic factoring\n");
+  (void) fprintf(vis_stderr, "   -h\t\tPrint the command usage\n");
+  (void) fprintf(vis_stderr, "   -i prefix\tPrefix of internal node names.\n");
+  (void) fprintf(vis_stderr,
+		 "   -o name\tName of output file (without extension)\n");
+  (void) fprintf(vis_stderr,
+		 "   -r n\t\tUse unreachable states for sequential circuits\n");
+  (void) fprintf(vis_stderr, "   \t\tas dont cares(0-3)\n");
+  (void) fprintf(vis_stderr,
+	 "   \t\t\t0: Do not use unreachable states (default).\n");
+  (void) fprintf(vis_stderr,
+	 "   \t\t\t1: Use normal BFS method for reachability analysis.\n");
+  (void) fprintf(vis_stderr,
+	 "   \t\t\t2: Use high density method for reachability analysis.\n");
+  (void) fprintf(vis_stderr,
+	 "   \t\t\t3: Use approximate unreachable states as dont cares.\n");
+  (void) fprintf(vis_stderr, "   -t time\tTime out period (in seconds)\n");
+  (void) fprintf(vis_stderr, "   -v \t\tVerbosity On.\n");
+  (void) fprintf(vis_stderr,
+		 "   -A \t\tAllow realignment after BDD/ZDD reordering.\n");
+  (void) fprintf(vis_stderr,
+		 "   -O n\t\tChoose an output ordering method(0-2)\n");
+  (void) fprintf(vis_stderr, "   \t\t\t0: no ordering\n");
+  (void) fprintf(vis_stderr, "   \t\t\t1: support variable set (default)\n");
+  (void) fprintf(vis_stderr, "   \t\t\t2: BDD size\n");
+  (void) fprintf(vis_stderr, "   -R n\t\tSet reordering (0-3)\n");
+  (void) fprintf(vis_stderr, "   \t\t\t0 or n: no reordering (default)\n");
+  (void) fprintf(vis_stderr, "   \t\t\t1 or b: reordering in only BDD\n");
+  (void) fprintf(vis_stderr, "   \t\t\t2 or z: reordering on only ZDD\n");
+  (void) fprintf(vis_stderr, "   \t\t\t3 or a: reordering on both\n");
+  (void) fprintf(vis_stderr, "   -T \t\tTry to share mode nodes.\n");
+  return 1;    /* error exit */
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Handler for timeout.]
+
+  Description [This function is called when a time out occurs.]
+
+  SideEffects []
+
+  SeeAlso []
+
+******************************************************************************/
+static void
+TimeOutHandle(void)
+{
+  longjmp(timeOutEnv, 1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether the network has multiple valued signals.]
+
+  Description [Checks whether the network has multiple valued
+  signals. Returns 1 if true, else 0.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static int
+TestIsNetworkMultipleValued(Ntk_Network_t *network)
+{
+  Ntk_Node_t *node;
+  lsGen gen;
+  Var_Variable_t *var;
+  int numValues;
+
+  Ntk_NetworkForEachNode(network,gen,node) {
+    var = Ntk_NodeReadVariable(node);
+    numValues = Var_VariableReadNumValues(var);
+    if (numValues > 2) {
+      lsFinish(gen);
+      return 1;
+    }
+  }
+  return 0;
+}
Index: vis_dev/vis-2.3/src/synth/synth.h
===================================================================
--- vis_dev/vis-2.3/src/synth/synth.h	(revision 14)
+++ vis_dev/vis-2.3/src/synth/synth.h	(revision 14)
@@ -0,0 +1,80 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [synth.h]
+
+  PackageName [synth]
+
+  Synopsis    [Symbolic synthesis package.]
+
+  Description []
+
+  Author      [In-Ho Moon, Balakrishna Kumthekar]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+  Revision    [$Id: synth.h,v 1.14 2005/05/11 20:16:47 hhhan Exp $]
+
+******************************************************************************/
+
+#ifndef _SYNTH
+#define _SYNTH
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "fsm.h"
+#include "part.h"
+#include "st.h"
+#include "util.h"
+#include "bdd.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+typedef struct SynthInfoDataStruct Synth_InfoData_t;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void Synth_Init(void);
+EXTERN void Synth_End(void);
+EXTERN bdd_node * Synth_ZddQuickDivisor(bdd_manager *dd, bdd_node *f);
+EXTERN bdd_node * Synth_ZddLeastDivisor(bdd_manager *dd, bdd_node *f);
+EXTERN bdd_node * Synth_ZddMostDivisor(bdd_manager *dd, bdd_node *f);
+EXTERN bdd_node * Synth_ZddLevelZeroDivisor(bdd_manager *dd, bdd_node *f);
+EXTERN bdd_node * Synth_ZddCommonDivisor(bdd_manager *dd, bdd_node *f);
+EXTERN bdd_node * Synth_ZddLpDivisor(bdd_manager *dd, bdd_node *f);
+EXTERN Synth_InfoData_t * Synth_InitializeInfo(int factoring, int divisor, int unreachDC, int reordering, int trySharing, int realign, char *filehead, char *prefix, boolean eqn);
+EXTERN void Synth_FreeInfo(Synth_InfoData_t *synthInfo);
+EXTERN int Synth_SynthesizeNetwork(Ntk_Network_t *network, graph_t *partition, st_table *careTable, Synth_InfoData_t *synthInfo, int verbosity);
+EXTERN int Synth_SynthesizeFsm(Fsm_Fsm_t *fsm, st_table *careTable, Synth_InfoData_t *synthInfo, int verbosity);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _SYNTH */
Index: vis_dev/vis-2.3/src/synth/synth.make
===================================================================
--- vis_dev/vis-2.3/src/synth/synth.make	(revision 14)
+++ vis_dev/vis-2.3/src/synth/synth.make	(revision 14)
@@ -0,0 +1,5 @@
+CSRC += synth.c synthCount.c synthDiv.c synthFactor.c synthGen.c \
+	synthOpt.c synthSimple.c synthSynth.c synthUtil.c synthWrite.c
+HEADERS += synth.h synthInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/synth/synthCount.c
===================================================================
--- vis_dev/vis-2.3/src/synth/synthCount.c	(revision 14)
+++ vis_dev/vis-2.3/src/synth/synthCount.c	(revision 14)
@@ -0,0 +1,357 @@
+/**CFile***********************************************************************
+
+  FileName    [synthCount.c]
+
+  PackageName [synth]
+
+  Synopsis    [Literal counting functions.]
+
+  Author      [In-Ho Moon, Balakrishna Kumthekar]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "synthInt.h"
+
+static char rcsid[] UNUSED = "$Id: synthCount.c,v 1.14 1998/08/31 19:22:12 mooni Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CountMultiLevelFactor(bdd_manager *dd, MlTree *top, MlTree *tree, int ref);
+static int GetLiteralCount(bdd_manager *dd, bdd_node *node, int nLiterals);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Counts the number of literals of a MlTree.]
+
+  Description [Counts the number of literals of a MlTree. The argument
+  ref controls whether to count shared literals or non-shared. If ref is
+  1, it counts shared literals.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+SynthCountMlLiteral(bdd_manager *dd,
+		    MlTree *tree,
+		    int ref)
+{
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  int		count = 0;
+
+  if (tree->top || tree->shared) {
+    if (ref && tree->ref) {
+      if (tree->node != zero && tree->node != one)
+	count = 1;
+      return(count);
+    }
+    count += CountMultiLevelFactor(dd, tree, tree, ref);
+  }
+
+  if (tree->leaf)
+    return(count);
+
+  if (tree->q_ref == 0)
+    count += SynthCountMlLiteral(dd, tree->q, ref);
+  if (tree->d_ref == 0)
+    count += SynthCountMlLiteral(dd, tree->d, ref);
+  if (tree->r_ref == 0)
+    count += SynthCountMlLiteral(dd, tree->r, ref);
+
+  return(count);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Makes a bit string for representing the support of a node.]
+
+  Description [Makes a bit string for representing the support of a node.
+  It returns the number of support variables of the ZDD node. The
+  argument mask is given by caller, which is array of unsigned integer.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+SynthGetSupportMask(bdd_manager *dd,
+		    bdd_node *node,
+		    unsigned int *mask)
+{
+  int		i, pos, count;
+  int		word, size;
+  int		bit, bit_mask;
+  int		*support;
+  int		zddSize = bdd_num_zdd_vars(dd);
+
+  count = 0;
+  word = sizeof(int) * 8;
+  size = zddSize / word + 1;
+
+  support = ALLOC(int, zddSize);
+  (void)memset((void *)support, 0, sizeof(int) * zddSize);
+  (void)memset((void *)mask, 0, size * sizeof(int));
+  SynthZddSupportStep(bdd_regular(node), support);
+  SynthZddClearFlag(bdd_regular(node));
+  for (i = 0; i < zddSize; i++) {
+    if (support[i]) {
+      pos = i / word;
+      bit = i % word;
+      bit_mask = 01 << bit;
+      mask[pos] |= bit_mask;
+      count++;
+    }
+  }
+  FREE(support);
+  return(count);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the number of support variables of a node.]
+
+  Description [Returns the number of support variables of a node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+SynthGetSupportCount(bdd_manager *dd,
+		     bdd_node *node)
+{
+  int		i, count;
+  int		*support;
+  int		zddSize = bdd_num_zdd_vars(dd);
+
+  count = 0;
+  support = ALLOC(int, zddSize);
+  (void)memset((void *)support, 0, sizeof(int) * zddSize);
+  SynthZddSupportStep(bdd_regular(node), support);
+  SynthZddClearFlag(bdd_regular(node));
+  for (i = 0; i < zddSize; i++) {
+    if (support[i])
+      count++;
+  }
+  FREE(support);
+  return(count);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Finds the support of f.]
+
+  Description [Finds the support of f. Performs a DFS from f. Whenever a node
+  is visited, the variable of the node is accumulated in support, and the
+  the node is marked not to be visited again. Uses the LSB of the next pointer
+  as visited flag.]
+
+  SideEffects [Once this function is called, SynthZddClearFlag() should
+  be called right after.]
+
+  SeeAlso     [SynthZddClearFlag]
+
+******************************************************************************/
+void
+SynthZddSupportStep(bdd_node *f, int *support)
+{
+  if (bdd_is_constant(f) || bdd_is_complement(bdd_read_next(f))) {
+    return;
+  }
+
+  support[bdd_node_read_index(f)] = 1;
+  SynthZddSupportStep(bdd_bdd_T(f),support);
+  SynthZddSupportStep(bdd_regular(bdd_bdd_E(f)),support);
+  /* Mark as visited. */
+  bdd_set_next(f, bdd_not_bdd_node(bdd_read_next(f)));
+  return;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Performs a DFS from f, clearing the LSB of the next pointers.]
+
+  Description [Performs a DFS from f, clearing the LSB of the next pointers.]
+
+  SideEffects []
+
+  SeeAlso     [SynthZddSupportStep]
+
+******************************************************************************/
+void
+SynthZddClearFlag(bdd_node *f)
+{
+  bdd_node *temp;
+
+  temp = bdd_read_next(f);
+
+  if (!bdd_is_complement(temp)) {
+    return;
+  }
+  /* Clear visited flag. */
+  bdd_set_next(f, bdd_regular(temp));
+  if (bdd_is_constant(f)) {
+    return;
+  }
+  SynthZddClearFlag(bdd_bdd_T(f));
+  SynthZddClearFlag(bdd_regular(bdd_bdd_E(f)));
+  return;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Counts the number of literals in a ZDD cover.]
+
+  Description [Counts the number of literals in a ZDD cover.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+SynthGetLiteralCount(bdd_manager *dd,
+		     bdd_node *node)
+{
+  return(GetLiteralCount(dd, node, 0));
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Counts the number of literals of a MlTree.]
+
+  Description [Counts the number of literals of a MlTree.]
+
+  SideEffects []
+
+  SeeAlso     [SynthCountMlLiteral]
+
+******************************************************************************/
+static int
+CountMultiLevelFactor(bdd_manager *dd,
+		      MlTree *top,
+		      MlTree *tree,
+		      int ref)
+{
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  bdd_node	*f;
+  int		i, *support;
+  int		count = 0;
+  int		sizeZ = bdd_num_zdd_vars(dd);
+
+  if (ref && tree != top && tree->shared)
+    return(1);
+
+  f = tree->node;
+  if (f == one || f == zero)
+    return(0);
+
+  if (tree->leaf) {
+    support = ALLOC(int, sizeZ);
+    if (!support)
+      return(0);
+    (void)memset((void *)support, 0, sizeof(int) * sizeZ);
+    SynthZddSupportStep(bdd_regular(tree->node), support);
+    SynthZddClearFlag(bdd_regular(tree->node));
+    for (i = 0; i < sizeZ; i++) {
+      if (support[i])
+	count++;
+    }
+    FREE(support);
+    return(count);
+  }
+
+  count += CountMultiLevelFactor(dd, top, tree->q, ref);
+  count += CountMultiLevelFactor(dd, top, tree->d, ref);
+  count += CountMultiLevelFactor(dd, top, tree->r, ref);
+
+  return(count);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Recursive procedure of SynthGetLiteralCount.]
+
+  Description [Recursive procedure of SynthGetLiteralCount. Counts the
+  number of literals in a ZDD cover. The argument nLiterals is the
+  number of literals currently counted.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+GetLiteralCount(bdd_manager *dd,
+		bdd_node *node,
+		int nLiterals)
+{
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  int		count = 0;
+
+  if (node == zero)
+    return(0);
+  if (node == one)
+    return(nLiterals);
+
+  count = GetLiteralCount(dd, bdd_bdd_T(node), nLiterals + 1);
+  count += GetLiteralCount(dd, bdd_bdd_E(node), nLiterals);
+
+  return(count);
+}
Index: vis_dev/vis-2.3/src/synth/synthDiv.c
===================================================================
--- vis_dev/vis-2.3/src/synth/synthDiv.c	(revision 14)
+++ vis_dev/vis-2.3/src/synth/synthDiv.c	(revision 14)
@@ -0,0 +1,1091 @@
+/**CFile***********************************************************************
+
+  FileName    [synthDiv.c]
+
+  PackageName [synth]
+
+  Synopsis    [Divisor functions.]
+
+  Author      [In-Ho Moon, Balakrishna Kumthekar]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "synthInt.h"
+
+static char rcsid[] UNUSED = "$Id: synthDiv.c,v 1.25 2002/09/10 05:50:52 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define	MAX_COUNT	100000000 /* just chosen for a very large number */
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [Structure of one BFS item to count variable occurrences.]
+
+  Description [Structure of one BFS item to count variable occurrences.]
+
+  SeeAlso     []
+
+******************************************************************************/
+typedef	struct	bfs_item {
+  int			reach; /* number of path from top node */
+  int			count; /* number of path to constant 1 */
+  bdd_node		*node; /* ZDD node */
+  struct bfs_item	*next;
+} BfsItem;
+
+/**Struct**********************************************************************
+
+  Synopsis    [Structure for BFS operation to count variable occurrences.]
+
+  Description [Structure for BFS operation to count variable occurrences.]
+
+  SeeAlso     []
+
+******************************************************************************/
+typedef	struct	bfs_list {
+  struct bfs_item	*item;
+  int			child; /* 1 : T, 0 : E */
+  struct bfs_list	*next;
+} BfsList;
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int FindQuickDivisor(bdd_node *f, bdd_node *one, int *v);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Finds a divisor that occurs in more than one cube of the ZDD
+  graph.]
+
+  Description [Finds a divisor that occurs in more than one cube of the ZDD
+  graph. This is done in a greedy manner. It returns a ZDD node.]
+
+  SideEffects []
+
+  SeeAlso     [Synth_ZddLeastDivisor Synth_ZddMostDivisor
+  Synth_ZddLevelZeroDivisor Synth_ZddCommonDivisor Synth_ZddLpDivisor]
+
+******************************************************************************/
+bdd_node *
+Synth_ZddQuickDivisor(bdd_manager *dd,
+		      bdd_node *f)
+{
+  bdd_node	*res;
+
+  if (bdd_get_package_name() != CUDD) {
+    (void)fprintf(vis_stderr,
+      "** synth error: Synthesis package can be used only with CUDD package\n");
+    (void)fprintf(vis_stderr,"** synth error: Please link with CUDD package\n");
+    return NIL(bdd_node);
+  }
+
+  do {
+    bdd_set_reordered_field(dd, 0);
+    res = SynthZddQuickDivisor(dd, f);
+  } while (bdd_read_reordered_field(dd) == 1);
+  return(res);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Finds a divisor that occurs the least frequently (but more
+  than once) in the cubes of a cover.]
+
+  Description [Finds a divisor that occurs the least frequently (but more
+  than once) in the cubes of a cover. It returns a ZDD node.]
+
+  SideEffects []
+
+  SeeAlso     [Synth_ZddQuickDivisor Synth_ZddMostDivisor
+  Synth_ZddLevelZeroDivisor Synth_ZddCommonDivisor Synth_ZddLpDivisor]
+
+******************************************************************************/
+bdd_node *
+Synth_ZddLeastDivisor(bdd_manager *dd,
+		      bdd_node *f)
+{
+  bdd_node	*res;
+
+  if (bdd_get_package_name() != CUDD) {
+    (void)fprintf(vis_stderr,
+      "** synth error: Synthesis package can be used only with CUDD package\n");
+    (void)fprintf(vis_stderr,"** synth error: Please link with CUDD package\n");
+    return NIL(bdd_node);
+  }
+
+  do {
+    bdd_set_reordered_field(dd, 0);
+    res = SynthZddLeastDivisor(dd, f);
+  } while (bdd_read_reordered_field(dd) == 1);
+  return(res);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Finds a divisor that occurs the most frequently in the cubes
+  of a cover.]
+
+  Description [Finds a divisor that occurs the most frequently in the cubes
+  of a cover. It returns a ZDD node.]
+
+  SideEffects []
+
+  SeeAlso     [Synth_ZddQuickDivisor Synth_ZddLeastDivisor
+  Synth_ZddLevelZeroDivisor Synth_ZddCommonDivisor Synth_ZddLpDivisor]
+
+******************************************************************************/
+bdd_node *
+Synth_ZddMostDivisor(bdd_manager *dd,
+		     bdd_node *f)
+{
+  bdd_node	*res;
+
+  if (bdd_get_package_name() != CUDD) {
+    (void)fprintf(vis_stderr,
+      "** synth error: Synthesis package can be used only with CUDD package\n");
+    (void)fprintf(vis_stderr,"** synth error: Please link with CUDD package\n");
+    return NIL(bdd_node);
+  }
+
+  do {
+    bdd_set_reordered_field(dd, 0);
+    res = SynthZddMostDivisor(dd, f);
+  } while (bdd_read_reordered_field(dd) == 1);
+  return(res);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds a divisor that is a level-0 cokernel.]
+
+  Description [Finds a divisor that is a level-0 cokernel. It returns a
+  ZDD node.]
+
+  SideEffects []
+
+  SeeAlso     [Synth_ZddQuickDivisor Synth_ZddLeastDivisor
+  Synth_ZddMostDivisor Synth_ZddCommonDivisor Synth_ZddLpDivisor]
+
+******************************************************************************/
+bdd_node *
+Synth_ZddLevelZeroDivisor(bdd_manager *dd,
+			  bdd_node *f)
+{
+  bdd_node	*res;
+
+  if (bdd_get_package_name() != CUDD) {
+    (void)fprintf(vis_stderr,
+      "** synth error: Synthesis package can be used only with CUDD package\n");
+    (void)fprintf(vis_stderr,"** synth error: Please link with CUDD package\n");
+    return NIL(bdd_node);
+  }
+
+  do {
+    bdd_set_reordered_field(dd, 0);
+    res = SynthZddLevelZeroDivisor(dd, f);
+  } while (bdd_read_reordered_field(dd) == 1);
+  return(res);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Find a divisor whose literals occur in all cubes.]
+
+  Description [Find a divisor whose literals occur in all cubes. It
+  returns a ZDD node.]
+
+  SideEffects []
+
+  SeeAlso     [Synth_ZddQuickDivisor Synth_ZddMostDivisor
+  Synth_ZddLeastDivisor Synth_ZddLevelZeroDivisor Synth_ZddLpDivisor]
+
+******************************************************************************/
+bdd_node *
+Synth_ZddCommonDivisor(bdd_manager *dd,
+		       bdd_node *f)
+{
+  bdd_node	*res;
+
+  if (bdd_get_package_name() != CUDD) {
+    (void)fprintf(vis_stderr,
+      "** synth error: Synthesis package can be used only with CUDD package\n");
+    (void)fprintf(vis_stderr,"** synth error: Please link with CUDD package\n");
+    return NIL(bdd_node);
+  }
+
+  do {
+    bdd_set_reordered_field(dd, 0);
+    res = SynthZddCommonDivisor(dd, f);
+  } while (bdd_read_reordered_field(dd) == 1);
+  return(res);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Find a good divisor for low power.]
+
+  Description [Find a good divisor for low power. It returns a ZDD
+  node.]
+
+  SideEffects []
+
+  SeeAlso     [Synth_ZddQuickDivisor Synth_ZddMostDivisor
+  Synth_ZddLeastDivisor Synth_ZddLevelZeroDivisor Synth_ZddCommonDivisor]
+******************************************************************************/
+bdd_node *
+Synth_ZddLpDivisor(bdd_manager *dd,
+		   bdd_node *f)
+{
+  bdd_node	*res;
+
+  if (bdd_get_package_name() != CUDD) {
+    (void)fprintf(vis_stderr,
+      "** synth error: Synthesis package can be used only with CUDD package\n");
+    (void)fprintf(vis_stderr,"** synth error: Please link with CUDD package\n");
+    return NIL(bdd_node);
+  }
+
+  do {
+    bdd_set_reordered_field(dd, 0);
+    res = SynthZddLpDivisor(dd, f);
+  } while (bdd_read_reordered_field(dd) == 1);
+  return(res);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive steps of Synth_ZddQuickDivisor.]
+
+  Description [Performs the recursive steps of Synth_ZddQuickDivisor.
+  When FindQuickDivisor fails to find a literal, the function uses as
+  backup strategy finding the literal that occurs the least. The reason
+  is the following. If a node has more than one parent, then it is
+  guaranteed to appear in more than one cube. However, the converse is not
+  true.]
+
+  SideEffects []
+
+  SeeAlso     [SynthZddLeastDivisor SynthZddMostDivisor
+  SynthZddLevelZeroDivisor SynthZddCommonDivisor SynthZddLpDivisor]
+
+******************************************************************************/
+bdd_node *
+SynthZddQuickDivisor(bdd_manager *dd,
+		     bdd_node *f)
+{
+  int		i, v;
+  int		nvars;
+  int		*count;
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  bdd_node	*divisor, *node;
+  bdd_node	*tmp;
+  int		min_count;
+
+  if (f == one || f == zero)
+    return(f);
+
+  /* Search for a literal appearing in at least two cubes. */
+  v = -1;
+  FindQuickDivisor(f, one, &v);
+  SynthZddClearFlag(f);
+
+  if (v == -1) {
+    /* Quick divisor not found by looking at the ZDD graph.
+     * Find the literal that occurs the least among those occuring
+     * at least twice.
+     */
+    min_count = MAX_COUNT;
+    nvars = bdd_num_zdd_vars(dd);
+    count = ALLOC(int, nvars);
+    (void)memset((void *)count, 0, sizeof(int) * nvars);
+    SynthCountLiteralOccurrence(dd, f, count);
+    for (i = 0; i < nvars; i++) {
+      if (count[i] > 1 && count[i] < min_count) {
+	v = i;
+	min_count = count[i];
+      }
+    }
+    FREE(count);
+    if (v == -1) {
+      /* All literal appear exactly once. We are done. */
+      return(f);
+    }
+  }
+
+  /* Obtain the literal divisor from its index and divide f. */
+  node = bdd_zdd_get_node(dd, v, one, zero);
+  if (!node)
+    return(NULL);
+  bdd_ref(node);
+
+  tmp = (* SynthGetZddDivideRecurFunc())(dd, f, node);
+  if (!tmp) {
+    bdd_recursive_deref_zdd(dd,node);
+    return(NULL);
+  }
+  bdd_ref(tmp);
+  bdd_recursive_deref_zdd(dd, node);
+
+  /* Recur on the quotient to make sure that all literals appear once. */
+  divisor = SynthZddQuickDivisor(dd, tmp);
+  if (!divisor) {
+    bdd_recursive_deref_zdd(dd,tmp);
+    return(NULL);
+  }
+  bdd_ref(divisor);
+  bdd_recursive_deref_zdd(dd, tmp);
+
+  bdd_deref(divisor);
+  return(divisor);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive steps of Synth_ZddLeastDivisor.]
+
+  Description [Performs the recursive steps of Synth_ZddLeastDivisor.]
+
+  SideEffects []
+
+  SeeAlso     [SynthZddQuickDivisor SynthZddMostDivisor
+  SynthZddLevelZeroDivisor SynthZddCommonDivisor SynthZddLpDivisor]
+
+******************************************************************************/
+bdd_node *
+SynthZddLeastDivisor(bdd_manager *dd,
+		     bdd_node *f)
+{
+  int		i, v;
+  int		nvars, min_count;
+  int		*count;
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  bdd_node	*divisor, *node;
+  bdd_node	*tmp1;
+
+  if (f == one || f == zero)
+    return(f);
+
+  /* Find the literal that occurs the least among those occuring at
+   * least twice.
+   */
+  v = -1;
+  min_count = MAX_COUNT;
+  nvars = bdd_num_zdd_vars(dd);
+  count = ALLOC(int, nvars);
+  (void)memset((void *)count, 0, sizeof(int) * nvars);
+  SynthCountLiteralOccurrence(dd, f, count);
+  for (i = 0; i < nvars; i++) {
+    if (count[i] > 1 && count[i] < min_count) {
+      v = i;
+      min_count = count[i];
+    }
+  }
+  FREE(count);
+
+  if (v == -1) {
+    /* All literal appear exactly once. We are done. */
+    return(f);
+  }
+
+  /* Obtain the literal divisor from its index and divide f. */
+  node = bdd_zdd_get_node(dd, v, one, zero);
+  if (!node) {
+    return(NULL);
+  }
+  bdd_ref(node);
+
+  tmp1 = (* SynthGetZddDivideRecurFunc())(dd, f, node);
+  if (!tmp1) {
+    bdd_recursive_deref_zdd(dd, node);
+    return(NULL);
+  }
+  bdd_ref(tmp1);
+  bdd_recursive_deref_zdd(dd, node);
+
+  /* Recur on the quotient to make sure that all literals appear once. */
+  divisor = SynthZddLeastDivisor(dd, tmp1);
+  if (!divisor) {
+    bdd_recursive_deref_zdd(dd, tmp1);
+    return(NULL);
+  }
+  bdd_ref(divisor);
+  bdd_recursive_deref_zdd(dd, tmp1);
+
+  bdd_deref(divisor);
+  return(divisor);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive steps of Synth_ZddMostDivisor.]
+
+  Description [Performs the recursive steps of Synth_ZddMostDivisor.]
+
+  SideEffects []
+
+  SeeAlso     [SynthZddQuickDivisor SynthZddLeastDivisor
+  SynthZddLevelZeroDivisor SynthZddCommonDivisor SynthZddLpDivisor]
+
+******************************************************************************/
+bdd_node *
+SynthZddMostDivisor(bdd_manager *dd,
+		    bdd_node *f)
+{
+  int		i, v;
+  int		nvars, max_count;
+  int		*count;
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  bdd_node	*divisor, *node;
+  bdd_node	*tmp1;
+
+  if (f == one || f == zero)
+    return(f);
+
+  /* Find the literal that occurs the most. */
+  v = -1;
+  max_count = 1;
+  nvars = bdd_num_zdd_vars(dd);
+  count = ALLOC(int, nvars);
+  (void)memset((void *)count, 0, sizeof(int) * nvars);
+  SynthCountLiteralOccurrence(dd, f, count);
+  for (i = 0; i < nvars; i++) {
+    if (count[i] > max_count) {
+      v = i;
+      max_count = count[i];
+    }
+  }
+
+  FREE(count);
+
+  if (v == -1) {
+    /* All literal appear exactly once. We are done. */
+    return(f);
+  }
+
+  /* Obtain the literal divisor from its index and divide f. */
+  node = bdd_zdd_get_node(dd, v, one, zero);
+  if (!node)
+    return(NULL);
+  bdd_ref(node);
+
+  tmp1 = (* SynthGetZddDivideRecurFunc())(dd, f, node);
+  if (!tmp1) {
+    bdd_recursive_deref_zdd(dd, node);
+    return(NULL);
+  }
+  bdd_ref(tmp1);
+  bdd_recursive_deref_zdd(dd, node);
+
+  /* Recur on the quotient to make sure that all literals appear once. */
+  divisor = SynthZddMostDivisor(dd, tmp1);
+  if (!divisor) {
+    bdd_recursive_deref_zdd(dd, tmp1);
+    return(NULL);
+  }
+  bdd_ref(divisor);
+  bdd_recursive_deref_zdd(dd, tmp1);
+
+  bdd_deref(divisor);
+  return(divisor);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive steps of Synth_ZddLevelZeroDivisor.]
+
+  Description [Performs the recursive steps of Synth_ZddLevelZeroDivisor.]
+
+  SideEffects []
+
+  SeeAlso     [SynthZddQuickDivisor SynthZddLeastDivisor
+  SynthZddMostDivisor SynthZddCommonDivisor SynthZddLpDivisor]
+
+******************************************************************************/
+bdd_node *
+SynthZddLevelZeroDivisor(bdd_manager *dd,
+			 bdd_node *f)
+{
+  int		i, v;
+  int		nvars, max_count;
+  int		*count;
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  bdd_node	*divisor, *node;
+  bdd_node	*tmp1, *tmp2;
+
+  if (f == one || f == zero)
+    return(f);
+
+  /* Find the literal that occurs the most. */
+  v = -1;
+  max_count = 1;
+  nvars = bdd_num_zdd_vars(dd);
+  count = ALLOC(int, nvars);
+  (void)memset((void *)count, 0, sizeof(int) * nvars);
+  SynthCountLiteralOccurrence(dd, f, count);
+  for (i = 0; i < nvars; i++) {
+    if (count[i] > max_count) {
+      v = i;
+      max_count = count[i];
+    }
+  }
+
+  FREE(count);
+
+  if (v == -1) {
+    /* All literal appear exactly once. We are done. */
+    return(f);
+  }
+
+  /* Obtain the literal divisor from its index and divide f. */
+  node = bdd_zdd_get_node(dd, v, one, zero);
+  if (!node)
+    return(NULL);
+  bdd_ref(node);
+
+  tmp1 = (* SynthGetZddDivideRecurFunc())(dd, f, node);
+  if (!tmp1) {
+    bdd_recursive_deref_zdd(dd, node);
+    return(NULL);
+  }
+  bdd_ref(tmp1);
+  bdd_recursive_deref_zdd(dd, node);
+
+  /* Factor out all literals appearing in all cubes. */
+  tmp2 = SynthMakeCubeFree(dd, tmp1);
+  if (!tmp2) {
+    bdd_recursive_deref_zdd(dd, tmp1);
+    return(NULL);
+  }
+  bdd_ref(tmp2);
+  bdd_recursive_deref_zdd(dd, tmp1);
+
+  /* Recur on the quotient to make sure that all literals appear once. */
+  divisor = SynthZddLevelZeroDivisor(dd, tmp2);
+  if (!divisor) {
+    bdd_recursive_deref_zdd(dd, tmp2);
+    return(NULL);
+  }
+  bdd_ref(divisor);
+  bdd_recursive_deref_zdd(dd, tmp2);
+
+  bdd_deref(divisor);
+  return(divisor);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [The internal function of Synth_ZddCommonDivisor.]
+
+  Description [The internal function of Synth_ZddCommonDivisor.]
+
+  SideEffects []
+
+  SeeAlso     [SynthZddQuickDivisor SynthZddLeastDivisor
+  SynthZddMostDivisor SynthZddLevelZeroDivisor SynthZddLpDivisor]
+
+******************************************************************************/
+bdd_node *
+SynthZddCommonDivisor(bdd_manager *dd,
+		      bdd_node *f)
+{
+  int		i;
+  int		nvars;
+  int		*count;
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  bdd_node	*divisor, *node, *tmp;
+  int		nCubes;
+
+  divisor = (bdd_node *)NULL;	/* NULL means no such divisor exists */
+  if (f == one || f == zero)
+    return(divisor);
+
+  nCubes = bdd_zdd_count(dd, f);
+  if (nCubes == 1)
+    return(divisor);
+
+  /* Find the literals that appear exactly as many times as there
+   * are cubes. These literals appear in all cubes, hence in the
+   * common divisor. Their product is accumulated in divisor. */
+  nvars = bdd_num_zdd_vars(dd);
+  count = ALLOC(int, nvars);
+  (void)memset((void *)count, 0, sizeof(int) * nvars);
+  SynthCountLiteralOccurrence(dd, f, count);
+  for (i = 0; i < nvars; i++) {
+    if (count[i] == nCubes) {
+      node = bdd_zdd_get_node(dd, i, one, zero);
+      if (!node) {
+	FREE(count);
+	return(NULL);
+      }
+      bdd_ref(node);
+      if (!divisor) {
+	divisor = node;
+	continue;
+      }
+      tmp = divisor;
+      divisor = (* SynthGetZddProductRecurFunc())(dd, divisor, node);
+      if (!divisor) {
+	bdd_recursive_deref_zdd(dd, tmp);
+	bdd_recursive_deref_zdd(dd, node);
+	FREE(count);
+	return(NULL);
+      }
+      bdd_ref(divisor);
+      bdd_recursive_deref_zdd(dd, tmp);
+      bdd_recursive_deref_zdd(dd, node);
+    }
+  }
+  FREE(count);
+
+  if (divisor)
+    bdd_deref(divisor);
+  return(divisor);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Performs the recursive steps of Synth_ZddLpDivisor.]
+
+  Description [Performs the recursive steps of Synth_ZddLpDivisor.]
+
+  SideEffects []
+
+  SeeAlso     [SynthZddQuickDivisor SynthZddLeastDivisor
+  SynthZddMostDivisor SynthZddLevelZeroDivisor SynthZddCommonDivisor]
+
+******************************************************************************/
+bdd_node *
+SynthZddLpDivisor(bdd_manager *dd,
+		  bdd_node *f)
+{
+  int		i, v;
+  int		nvars, min_count, min_pos = 0;
+  int		*count;
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  bdd_node	*divisor, *node;
+  bdd_node	*tmp1;
+
+  if (f == one || f == zero)
+    return(f);
+
+  /* Find the literal that occurs the least among those occuring at
+   * least twice.
+   */
+  v = -1;
+  min_count = MAX_COUNT;
+  nvars = bdd_num_zdd_vars(dd);
+  count = ALLOC(int, nvars);
+  (void)memset((void *)count, 0, sizeof(int) * nvars);
+
+  SynthCountLiteralOccurrence(dd, f, count);
+  for (i = 0; i < nvars; i++) {
+    if (count[i] > 1 && count[i] < min_count) {
+      v = i;
+      min_count = count[i];
+      min_pos = i;
+    }
+  }
+  if (v == -1) {
+    /* All literal appear exactly once. We are done. */
+    FREE(count);
+    return(f);
+  }
+
+  /* Among the literals with minimum count, find a good one. */
+  v = SynthFindDivisorForLowPower(count, nvars, min_count, min_pos);
+
+  FREE(count);
+
+  if (v == -1) {
+    return(f);
+  }
+
+  /* Obtain the literal divisor from its index and divide f. */
+  node = bdd_zdd_get_node(dd, v, one, zero);
+  if (!node)
+    return(NULL);
+  bdd_ref(node);
+
+  tmp1 = (* SynthGetZddDivideRecurFunc())(dd, f, node);
+  if (!tmp1) {
+    bdd_recursive_deref_zdd(dd, node);
+    return(NULL);
+  }
+  bdd_ref(tmp1);
+  bdd_recursive_deref_zdd(dd, node);
+
+  /* Recur on the quotient to make sure that all literals appear once. */
+  divisor = SynthZddLpDivisor(dd, tmp1);
+  if (!divisor) {
+    bdd_recursive_deref_zdd(dd, tmp1);
+    return(NULL);
+  }
+  bdd_ref(divisor);
+  bdd_recursive_deref_zdd(dd, tmp1);
+
+  bdd_deref(divisor);
+  return(divisor);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Counts the number of occurrences of each variable.]
+
+  Description [Counts the number of occurrences of each variable.
+  First, we count the number of paths to the top node for each node from
+  top to bottom. Let this number be C_t. Initially, C_t of the top node
+  is 1, and C_t of a node is the sum of C_t's of all predecessors of the
+  node. Second, we count the number of paths to the constant one node from
+  bottom to top. Let this number be C_1. Initially, C_1 of the constant one
+  node is 1 and C_1 of the constant zero node is 0, and C_1 of a node is the
+  sum of C_1's of two successors of the node. Third, we count the number of
+  occurrences of variables using the C_t's and C_1's of each node. Here, let
+  C_m of a node be C_t of the node times C_1 of then child of the node.
+  The number of occurrences of a variable is determined by summing C_m of all
+  nodes that belongs to the variable in the ZDD. The argument count is
+  passed by caller, and it is an array of integer to store the number of
+  occurrence for each variable, and the size of the array is the number
+  of ZDD variables.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthCountLiteralOccurrence(bdd_manager *dd,
+			    bdd_node *f,
+			    int *count)
+{
+  BfsItem	**level, *item, *cur_item, *next_item, *last_item;
+  BfsList	*list, *pre_list, *cur_list, *next_list, *last_list;
+  BfsList	*new_list, *save_last_list;
+  int		cur_level, next_level, start_level, last_level;
+  int		exist;
+  bdd_node	*zero = bdd_read_zero(dd);
+  bdd_node	*one = bdd_read_one(dd);
+  int		i, ct, ce;
+  bdd_node	*node;
+  int		lv, *index, id;
+  int		sizeZ = bdd_num_zdd_vars(dd);
+
+  if (bdd_is_constant(f))
+    return;
+
+  level = ALLOC(BfsItem *, sizeZ);
+  (void)memset((void *)level, 0, sizeof(BfsItem *) * sizeZ);
+  index = ALLOC(int, sizeZ);
+  (void)memset((void *)index, 0, sizeof(int) * sizeZ);
+
+  /* Initialize BFS by entering f in the queue. */
+  item = ALLOC(BfsItem, 1);
+  (void)memset((void *)item, 0, sizeof(BfsItem));
+  item->node = f;
+  item->reach = 1;
+  lv = bdd_read_zdd_level(dd,bdd_node_read_index(f));
+  level[lv] = item;
+  index[lv] = bdd_node_read_index(f);
+  start_level = last_level = lv;
+
+  if (!bdd_is_constant(bdd_bdd_T(f))) {
+    list = ALLOC(BfsList, 1);
+    (void)memset((void *)list, 0, sizeof(BfsList));
+    list->item = item;
+    list->child = 1;
+    last_list = list;
+  } else
+    list = last_list = (BfsList *)NULL;
+  if (!bdd_is_constant(bdd_bdd_E(f))) {
+    last_list = ALLOC(BfsList, 1);
+    (void)memset((void *)last_list, 0, sizeof(BfsList));
+    last_list->item = item;
+    last_list->child = 0;
+    if (list)
+      list->next = last_list;
+    else
+      list = last_list;
+  }
+
+  /* Perform the BFS. */
+  while (list) {
+    cur_level = sizeZ;
+    cur_list = list;
+    while (cur_list) {
+      if (cur_list->child)
+	id = bdd_node_read_index(bdd_bdd_T(cur_list->item->node));
+      else
+	id = bdd_node_read_index(bdd_bdd_E(cur_list->item->node));
+      next_level = bdd_read_zdd_level(dd,id);
+      cur_level = (cur_level < next_level) ? cur_level : next_level;
+      cur_list = cur_list->next;
+    }
+    last_level = cur_level;
+    save_last_list = last_list;
+
+    pre_list = (BfsList *)NULL;
+    cur_list = list;
+    while (cur_list) {
+      if (cur_list->child)
+	id = bdd_node_read_index(bdd_bdd_T(cur_list->item->node));
+      else
+	id = bdd_node_read_index(bdd_bdd_E(cur_list->item->node));
+      next_level = bdd_read_zdd_level(dd,id);
+
+      if (next_level != cur_level) {
+	pre_list = cur_list;
+	cur_list = cur_list->next;
+	continue;
+      }
+
+      if (cur_list->child)
+	node = bdd_bdd_T(cur_list->item->node);
+      else
+	node = bdd_bdd_E(cur_list->item->node);
+
+      exist = 0;
+      last_item = level[cur_level];
+      while (last_item) {
+	if (node == last_item->node) {
+	  last_item->reach += cur_list->item->reach;
+	  exist = 1;
+	  break;
+	}
+	if (last_item->next)
+	  last_item = last_item->next;
+	else
+	  break;
+      }
+
+      if (exist == 0) {
+	item = ALLOC(BfsItem, 1);
+	(void)memset((void *)item, 0, sizeof(BfsItem));
+	item->node = node;
+	item->reach = cur_list->item->reach;
+	if (last_item)
+	  last_item->next = item;
+	else {
+	  level[cur_level] = item;
+	  index[cur_level] = id;
+	}
+
+	if (!bdd_is_constant(bdd_bdd_T(node))) {
+	  new_list = ALLOC(BfsList, 1);
+	  (void)memset((void *)new_list, 0, sizeof(BfsList));
+	  new_list->item = item;
+	  new_list->child = 1;
+	  last_list->next = new_list;
+	  last_list = new_list;
+	}
+	if (!bdd_is_constant(bdd_bdd_E(node))) {
+	  new_list = ALLOC(BfsList, 1);
+	  (void)memset((void *)new_list, 0, sizeof(BfsList));
+	  new_list->item = item;
+	  new_list->child = 0;
+	  last_list->next = new_list;
+	  last_list = new_list;
+	}
+      }
+
+      next_list = cur_list->next;
+      if (cur_list == list && cur_list == last_list) {
+	FREE(cur_list);
+	list = next_list;
+      } else if (cur_list == list) {
+	FREE(cur_list);
+	pre_list = (BfsList *)NULL;
+	if (list == save_last_list) {
+	  list = next_list;
+	  next_list = (BfsList *)NULL;
+	} else
+	  list = next_list;
+      } else if (cur_list == last_list) {
+	if (pre_list)
+	  pre_list->next = cur_list->next;
+	FREE(cur_list);
+	last_list = pre_list;
+      } else {
+	if (pre_list)
+	  pre_list->next = cur_list->next;
+	if (cur_list == save_last_list) {
+	  FREE(cur_list);
+	  next_list = (BfsList *)NULL;
+	} else
+	  FREE(cur_list);
+      }
+
+      cur_list = next_list;
+    }
+  }
+
+  /* Compute the number of paths to the constant 1 for each node in
+   * bottom up fashion. Update the occurrence count of the variables.
+   */
+  for (i = last_level; i >= start_level; i--) {
+    item = level[i];
+    while (item) {
+      ct = ce = 0;
+      if (bdd_bdd_T(item->node) == one)
+	ct = 1;
+      else {
+	node = bdd_bdd_T(item->node);
+	next_level = bdd_read_zdd_level(dd, bdd_node_read_index(node));
+	cur_item = level[next_level];
+	while (cur_item) {
+	  if (cur_item->node == node) {
+	    ct = cur_item->count;
+	    break;
+	  }
+	  cur_item = cur_item->next;
+	}
+      }
+      if (bdd_bdd_E(item->node) != zero) {
+	node = bdd_bdd_E(item->node);
+	next_level = bdd_read_zdd_level(dd,
+					bdd_node_read_index(node));
+	cur_item = level[next_level];
+	while (cur_item) {
+	  if (cur_item->node == node) {
+	    ce = cur_item->count;
+	    break;
+	  }
+	  cur_item = cur_item->next;
+	}
+      }
+      item->count = ct + ce;
+      count[index[i]] += ct * item->reach;
+      item = item->next;
+    }
+  }
+
+  /* Clean up. */
+  for (i = last_level; i >= start_level; i--) {
+    item = level[i];
+    while (item) {
+      next_item = item->next;
+      FREE(item);
+      item = next_item;
+    }
+  }
+
+  FREE(level);
+  FREE(index);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Finds a ZDD node that is referred by more than one parent
+  node in a function.]
+
+  Description [Finds a ZDD node that is referred by more than one parent
+  node in a function. Performs a DFS from f. Whenever a node is visited,
+  the node is marked. When a node is visited, if the node is already marked,
+  it returns the index of the node. Uses the LSB of the next pointer as
+  visited flag. This function returns the number of path to constant 1 from
+  the node, and return value -1 means already found.]
+
+  SideEffects [Once this function is called, SynthZddClearFlag() should
+  be called right after.];
+
+  SeeAlso     [SynthZddClearFlag]
+
+******************************************************************************/
+static int
+FindQuickDivisor(bdd_node *f,
+		 bdd_node *one,
+		 int *v)
+{
+  int		c, ct, ce;
+  bdd_node	*temp = bdd_read_next(f);
+
+  if (bdd_is_constant(f)) {
+    if (f == one)
+      return(1);
+    else
+      return(0);
+  }
+
+  if (bdd_is_complement(temp)) { /* already visited */
+    *v = bdd_node_read_index(f);
+    return(-1);
+  }
+  /* mark as visited */
+  bdd_set_next(f, bdd_not_bdd_node(temp));
+
+  ct = FindQuickDivisor(bdd_bdd_T(f), one, v);
+  if (ct == -1) /* already found */
+    return(-1);
+  else if (ct > 1) {
+    *v = bdd_node_read_index(f);
+    return(-1);
+  }
+
+  ce = FindQuickDivisor(bdd_bdd_E(f), one, v);
+  if (ce == -1) /* already found */
+    return(-1);
+
+  /* Add the number of path to constant 1 from two children nodes. */
+  c = ct + ce;
+  return(c);
+}
Index: vis_dev/vis-2.3/src/synth/synthFactor.c
===================================================================
--- vis_dev/vis-2.3/src/synth/synthFactor.c	(revision 14)
+++ vis_dev/vis-2.3/src/synth/synthFactor.c	(revision 14)
@@ -0,0 +1,1966 @@
+/**CFile***********************************************************************
+
+  FileName    [synthFactor.c]
+
+  PackageName [synth]
+
+  Synopsis    [Multilevel optimization functions.]
+
+  Author      [In-Ho Moon, Balakrishna Kumthekar]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "synthInt.h"
+
+static char rcsid[] UNUSED = "$Id: synthFactor.c,v 1.49 2005/04/23 14:37:51 jinh Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [Structure of a linked list to keep the sizes of trees.]
+
+  Description [Structure of a linked list to keep the sizes of trees.
+  The size is in terms of number of literals of a tree. This is used for
+  fast insertion of a tree into the multi-level tree list.]
+
+  SeeAlso     []
+
+******************************************************************************/
+typedef struct ml_size_list {
+    int			size;	/* the number of literals */
+    char		*string; /* string of the size to put into st_table */
+    struct ml_size_list	*next;
+} MlSizeList;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+static	bdd_node	*(* ZddProductFunc)(bdd_manager *, bdd_node *, bdd_node *) = bdd_zdd_product;
+static	bdd_node	*(* ZddProductRecurFunc)(bdd_manager *, bdd_node *, bdd_node *) = bdd_zdd_product_recur;
+static	bdd_node	*(* ZddDivideFunc)(bdd_manager *, bdd_node *, bdd_node *) = bdd_zdd_weak_div;
+static	bdd_node	*(* ZddDivideRecurFunc)(bdd_manager *, bdd_node *, bdd_node *) = bdd_zdd_weak_div_recur;
+static	bdd_node	*(* ZddDivisorFunc)(bdd_manager *, bdd_node *) = Synth_ZddQuickDivisor;
+static	int		NumTree;
+static	int		ResolveConflictMode = 0;
+static	st_table	*HeadListTable, *TailListTable;
+static	MlTree		*MlTreeHead;
+static	MlSizeList	*MlSizeHead;
+
+int		UseMtree = 1;
+int		UseCommonDivisor = 1;
+int		TryNodeSharing = 0;
+int		Resubstitution = 1;
+int		RemainderComplement = 0;
+int             noMemoryFlag = 0;
+int		VerifyTreeMode = 0;
+		/*
+		** 0 : nothing
+		** 1 : incrementally
+		** 2 : recursively after each factorization
+		** 3 : 2 & dump blif file with bdds
+		*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static MlTree * ResolveConflictNode(bdd_manager *dd, st_table *table, MlTree *tree1, MlTree *tree2, int comp_flag, int verbosity);
+static void DeleteMlTree(bdd_manager *dd, st_table *table, MlTree *kill_tree, MlTree *live_tree, int deref, int comp_flag);
+static void UnlinkMlTree(MlTree *kill_tree);
+static void DeleteMlSizeList(MlTree *tree);
+static int InsertMlTable(st_table *table, bdd_node *node, MlTree *tree);
+static bdd_node	* MakeComplementOfZddCover(bdd_manager *dd, bdd_node *node, int verbosity);
+static char * GetIntString(int v);
+static void VerifyTreeList(void);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the variable ZddProductFunc.]
+
+  Description [Returns the variable ZddProductFunc.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bdd_node	*
+(* SynthGetZddProductFunc(void))(bdd_manager *, bdd_node *, bdd_node *)
+{
+    return(ZddProductFunc);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the variable ZddProductRecurFunc.]
+
+  Description [Returns the variable ZddProductRecurFunc.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bdd_node	*
+(* SynthGetZddProductRecurFunc(void))(bdd_manager *, bdd_node *, bdd_node *)
+{
+    return(ZddProductRecurFunc);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the variable ZddDivideFunc.]
+
+  Description [Returns the variable ZddDivideFunc.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bdd_node	*
+(* SynthGetZddDivideFunc(void))(bdd_manager *, bdd_node *, bdd_node *)
+{
+    return(ZddDivideFunc);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the variable ZddDivideRecurFunc.]
+
+  Description [Returns the variable ZddDivideRecurFunc.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bdd_node	*
+(* SynthGetZddDivideRecurFunc(void))(bdd_manager *, bdd_node *, bdd_node *)
+{
+    return(ZddDivideRecurFunc);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the variable ZddDivisorFunc.]
+
+  Description [Returns the variable ZddDivisorFunc.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bdd_node	*
+(* SynthGetZddDivisorFunc(void))(bdd_manager *, bdd_node *)
+{
+    return(ZddDivisorFunc);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Sets the variable ZddDivisorFunc.]
+
+  Description [Sets the variable ZddDivisorFunc.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthSetZddDivisorFunc(int mode)
+{
+  if (mode == 0)
+    ZddDivisorFunc = Synth_ZddQuickDivisor;
+  else if (mode == 1)
+    ZddDivisorFunc = Synth_ZddLeastDivisor;
+  else if (mode == 2)
+    ZddDivisorFunc = Synth_ZddMostDivisor;
+  else
+    ZddDivisorFunc = Synth_ZddLevelZeroDivisor;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Sets the first n characters of string to spaces.]
+
+  Description [Sets the first n characters of string to spaces. n should
+  be less than max.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthGetSpaceString(char *string,
+		    int n,
+		    int max)
+{
+  int	i;
+
+  if (n >= max - 1)
+    n = max - 2;
+
+  for (i = 0; i < n; i++)
+    string[i] = ' ';
+  string[n] = '\0';
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Looks up the node-tree table to see if the node exists.]
+
+  Description [Looks up the node-tree table to see if the node exists.
+  If node exists in node-tree table, it returns the tree. Otherwise it
+  returns NULL. If the tree is a candidate, the tree is changed to
+  regular one.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+MlTree	*
+SynthLookupMlTable(st_table *table,
+		   bdd_manager *dd,
+		   bdd_node *node,
+		   int candidate,
+		   int verbosity)
+{
+  MlTree	*tree, *m_tree;
+  int		flag;
+
+  flag = st_lookup(table, (char *)node, &tree);
+  if (flag) {
+    if (MlTree_Regular(tree)->candidate) {
+      m_tree = MlTree_Regular(tree);
+      if (candidate) {
+        if (!SynthUseCandidate(table, dd, m_tree, verbosity)) {
+	  return(NULL);
+        }
+      }
+    }
+    if (candidate)
+      SynthSetSharedFlag(dd, tree);
+    return(tree);
+  }
+
+  return((MlTree *)NULL);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Makes a candidate tree node a real node.]
+
+  Description [Makes a candidate tree node a real node. If successful,
+  it returns 1, otherwise it returns 0. A candidate is a extra tree that
+  keeps a function of 'quotient * divisor'. This candidate can be a
+  regular tree when it is shared.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+SynthUseCandidate(st_table *table,
+		  bdd_manager *dd,
+		  MlTree *m_tree,
+		  int verbosity)
+{
+  MlTree	*parent, *c_tree, *tmp_tree;
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  int		ref;
+  int		comp_flag;
+
+  m_tree = MlTree_Regular(m_tree);
+  if (!m_tree->r) {
+    (void) fprintf(vis_stdout,
+		   "** synth fatal: Internal error in synthesize_network.\n");
+    (void) fprintf(vis_stdout,
+		 "** synth fatal: Please report this bug to VIS developers.\n");
+    return (0);
+  }
+  parent = m_tree->r;
+  m_tree->r = (MlTree *)NULL;
+  m_tree->candidate = 0;
+  c_tree = SynthFindOrCreateMlTree(table, dd, zero, 1, 0, &ref, verbosity);
+  if (!c_tree)
+    return (0);
+  if (MlTree_IsComplement(c_tree)) {
+    c_tree = MlTree_Regular(c_tree);
+    m_tree->r_comp = 1;
+  }
+  tmp_tree = c_tree;
+  c_tree = SynthCheckAndMakeComplement(dd, table, c_tree,
+				       &comp_flag, verbosity);
+  if (!c_tree)
+    return (0);
+  else if (c_tree != tmp_tree) {
+    if (comp_flag)
+	m_tree->r_comp = 1;
+    ref = 1;
+  }
+  m_tree->r = c_tree;
+  m_tree->r_ref = ref;
+  parent->q = m_tree;
+  parent->q_ref = 0;
+  parent->q_comp = 0;
+  c_tree = SynthFindOrCreateMlTree(table, dd, one, 1, 0, &ref, verbosity);
+  if (!c_tree)
+    return (0);
+  if (MlTree_IsComplement(c_tree)) {
+    c_tree = MlTree_Regular(c_tree);
+    parent->d_comp = 1;
+  } else
+    parent->d_comp = 0;
+  parent->d = c_tree;
+  parent->d_ref = ref;
+  m_tree->id = NumTree;
+  NumTree++;
+  if (verbosity > 1)
+    (void)fprintf(vis_stdout, "** synth info: Used candidate %d.\n",
+		  m_tree->id);
+  if (VerifyTreeMode) {
+    SynthVerifyTree(dd, parent, 0);
+    SynthVerifyTree(dd, m_tree, 0);
+    SynthVerifyMlTable(dd, table);
+  }
+  return(1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Looks up the node-tree table first; if f is found, it returns the
+  existing tree, otherwise it creates a new tree.]
+
+  Description [Looks up the node-tree table first, if f is found, it
+  returns the existing tree, otherwise it creates a new tree. The
+  return value of this function will be NULL only when reordering
+  takes place or memory allocation fails in InsertMlTable.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+MlTree	*
+SynthFindOrCreateMlTree(st_table *table,
+			bdd_manager *dd,
+			bdd_node *f,
+			int leaf,
+			int candidate,
+			int *ref,
+			int verbosity)
+{
+  MlTree	*tree;
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+
+  tree = SynthLookupMlTable(table, dd, f, 1, verbosity);
+  if (tree) {
+    if (MlTree_Regular(tree)->candidate) {
+      if (!SynthUseCandidate(table, dd, tree, verbosity)) {
+        return(NULL);
+      }
+      SynthSetSharedFlag(dd, tree);
+    }
+    *ref = 1;
+    return(tree);
+  } else if (bdd_read_reordered_field(dd) || noMemoryFlag == 1)
+    return(NULL);
+
+  tree = ALLOC(MlTree, 1);
+  if (!tree) {
+    noMemoryFlag = 1;
+    return(NULL);
+  }
+  (void)memset((void *)tree, 0, sizeof(MlTree));
+  tree->node = f;
+  bdd_ref(f);
+  tree->leaf = leaf;
+  if (bdd_bdd_T(f) == one && bdd_bdd_E(f) == zero)
+    tree->pi = 1;
+  if (candidate)
+    tree->candidate = 1;
+  if (!tree->candidate) {
+    tree->id = NumTree;
+    NumTree++;
+  }
+  if (!InsertMlTable(table, f, tree)) {
+    bdd_recursive_deref_zdd(dd, f);
+    FREE(tree);
+    return NULL;
+  }
+  *ref = 0;
+
+  return(tree);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes global variables and tables for factorization.]
+
+  Description [Initializes global variables and tables for factorization.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthInitMlTable(void)
+{
+  NumTree = 1;
+  MlTreeHead = NIL(MlTree);
+  MlSizeHead = NIL(MlSizeList);
+  HeadListTable = st_init_table(strcmp, st_strhash);
+  TailListTable = st_init_table(strcmp, st_strhash);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Dereferences each node of the node-tree table.]
+
+  Description [Dereferences each node of the node-tree table.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthClearMlTable(bdd_manager *dd,
+		  st_table *table)
+{
+  st_generator	*gen;
+  bdd_node		*k;
+  MlTree		*r;
+  MlSizeList		*l, *next;
+
+  st_foreach_item(table, gen, (&k), (&r)) {
+    bdd_recursive_deref_zdd(dd, k);
+    if (!MlTree_IsComplement(r))
+      SynthFreeMlTree(r, 0);
+  }
+
+  NumTree = 1;
+  MlTreeHead = NIL(MlTree);
+
+  st_free_table(HeadListTable);
+  st_free_table(TailListTable);
+  HeadListTable = TailListTable = NIL(st_table);
+
+  l = MlSizeHead;
+  while (l) {
+    next = l->next;
+    FREE(l->string);
+    FREE(l);
+    l = next;
+  }
+  MlSizeHead = NIL(MlSizeList);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Puts a new tree into MlTree list.]
+
+  Description [Puts a new tree into MlTree list. This tree list is used
+  for sharing. Basically MlTree is a linked list sorted by the number of
+  literals of trees and the head tree has the largest literals. Just to
+  increase insertion time, MlSizeList and HeadListTable and TailListTable
+  are used. MlSizeList tells what sizes of trees exist in MlTree list,
+  and since many trees with same number of literals may exist,
+  HeadListTable and TailListTable keep first and last tree with a given
+  number of literals.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthPutMlTreeInList(bdd_manager *dd,
+		     MlTree *tree,
+		     int candidate)
+{
+  int		i;
+  int		word, size;
+  unsigned int	*mask;
+  int		top;
+  MlTree	*last;
+  MlSizeList	*list, *pre_list, *new_list;
+
+  word = sizeof(int) * 8;
+  size = bdd_num_zdd_vars(dd) / word + 1;
+
+  if (candidate) {
+    tree->nLiterals = tree->q->nLiterals + tree->d->nLiterals;
+
+    mask = ALLOC(unsigned int, size);
+    for (i = 0; i < size; i++)
+      mask[i] = tree->q->support[i] | tree->d->support[i];
+    tree->support = mask;
+  } else {
+    if (tree->nLiterals == 0) {
+      top = tree->top;
+      tree->top = 1;
+      tree->nLiterals = SynthCountMlLiteral(dd, tree, 0);
+      tree->top = top;
+    }
+
+    if (!tree->support) {
+      mask = ALLOC(unsigned int, size);
+      (void)memset((void *)mask, 0, size * sizeof(int));
+      SynthGetSupportMask(dd, tree->node, mask);
+      tree->support = mask;
+    }
+  }
+
+  if ((!MlTreeHead) || (tree->nLiterals > MlTreeHead->nLiterals)) {
+    tree->next = MlTreeHead;
+    MlTreeHead = tree;
+
+    list = ALLOC(MlSizeList, 1);
+    list->size = tree->nLiterals;
+    list->string = GetIntString(list->size);
+    list->next = MlSizeHead;
+    MlSizeHead = list;
+
+    st_insert(HeadListTable, list->string, (char *)tree);
+    st_insert(TailListTable, list->string, (char *)tree);
+  } else {
+    pre_list = NIL(MlSizeList);
+    list = MlSizeHead;
+    while (list) {
+      if (tree->nLiterals == list->size) {
+	if (list == MlSizeHead) {
+	  tree->next = MlTreeHead;
+	  MlTreeHead = tree;
+	  st_insert(HeadListTable, list->string, (char *)tree);
+	} else {
+	  st_lookup(TailListTable, list->string, (&last));
+	  tree->next = last->next;
+	  last->next = tree;
+	  st_insert(TailListTable, list->string, (char *)tree);
+	}
+	break;
+      } else if (tree->nLiterals > list->size) {
+	st_lookup(TailListTable, pre_list->string, (&last));
+	tree->next = last->next;
+	last->next = tree;
+
+	new_list = ALLOC(MlSizeList, 1);
+	new_list->size = tree->nLiterals;
+	new_list->string = GetIntString(new_list->size);
+	new_list->next = list;
+	pre_list->next = new_list;
+
+	st_insert(HeadListTable, new_list->string, (char *)tree);
+	st_insert(TailListTable, new_list->string, (char *)tree);
+	break;
+      } else if (!list->next) {
+	st_lookup(TailListTable, list->string, (&last));
+	tree->next = NIL(MlTree);
+	last->next = tree;
+
+	new_list = ALLOC(MlSizeList, 1);
+	new_list->size = tree->nLiterals;
+	new_list->string = GetIntString(new_list->size);
+	new_list->next = NIL(MlSizeList);
+	list->next = new_list;
+
+	st_insert(HeadListTable, new_list->string, (char *)tree);
+	st_insert(TailListTable, new_list->string, (char *)tree);
+	break;
+      }
+      pre_list = list;
+      list = list->next;
+    }
+  }
+
+  if (VerifyTreeMode)
+    VerifyTreeList();
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns first tree that has the given size in list.]
+
+  Description [Returns first tree that has the given size in tree list, if
+  the given size exists in size list. Otherwise it returns NULL.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+MlTree	*
+SynthGetHeadTreeOfSize(int size)
+{
+  MlTree	*head;
+  MlSizeList	*list;
+
+  list = MlSizeHead;
+  while (list) {
+    if (size == list->size) {
+      st_lookup(HeadListTable, list->string, (&head));
+      return(head);
+    } else if (size > list->size)
+      return(NULL);
+    list = list->next;
+  }
+  return(NULL);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Makes complement node of a tree if it does not exist.]
+
+  Description [Makes complement node of a tree if it does not exist.
+  If successful, it returns the same tree or another tree which already
+  has the complemented node. In the latter case, it is called a conflict
+  and the two trees are merged into the other tree, this is called
+  resolution. If not successful, it returns NULL. If the complement
+  already exists, the tree is just returned.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+MlTree	*
+SynthCheckAndMakeComplement(bdd_manager *dd,
+			    st_table *table,
+			    MlTree *tree,
+			    int *comp_flag,
+			    int verbosity)
+{
+  bdd_node	*c;
+  MlTree	*c_tree, *new_;
+
+  if (MlTree_IsComplement(tree))
+    return(tree);
+
+  *comp_flag = 0;
+  if (!tree->complement) {
+    c = MakeComplementOfZddCover(dd, tree->node, verbosity);
+    if (!c)
+      return(NULL);
+    bdd_ref(c);
+    c_tree = SynthLookupMlTable(table, dd, (char *)c, 0, verbosity);
+    if (c_tree) {
+      MlTree *m_tree = MlTree_Regular(c_tree);
+      if (MlTree_Regular(tree)->candidate &&
+	  MlTree_Regular(c_tree)->candidate) {
+	/*
+	**       tree     m_tree
+	**         |\      /|
+	**         |   \/   |
+	**         | /    \ |
+	**         q        d
+	**/
+
+	if (ResolveConflictMode == 0 || c_tree == m_tree ||
+	    tree->nLiterals <= m_tree->nLiterals) {
+	  /* throw away m_tree and assign c to tree->complement */
+	  UnlinkMlTree(m_tree);
+	  bdd_recursive_deref_zdd(dd, m_tree->node);
+	  bdd_recursive_deref_zdd(dd, m_tree->complement);
+	  st_delete(table, (char **)(&m_tree->node), NIL(char *));
+	  st_delete(table, (char **)(&m_tree->complement), NIL(char *));
+	  if (m_tree->support)
+	    FREE(m_tree->support);
+	  FREE(m_tree);
+	  tree->complement = c;
+	  if (!InsertMlTable(table, c, MlTree_Not(tree))) {
+	    tree->complement = NIL(bdd_node);
+	    bdd_recursive_deref_zdd(dd, c);
+	    return(NULL);
+	  }
+	} else if (c_tree != m_tree) {
+	  /* takes m_tree's contents and throws away m_tree */
+	  UnlinkMlTree(tree);
+	  UnlinkMlTree(m_tree);
+	  bdd_recursive_deref_zdd(dd, tree->node);
+	  st_delete(table, (char **)(&tree->node), NIL(char *));
+	  if (tree->support)
+	    FREE(tree->support);
+	  memcpy(tree, m_tree, sizeof(MlTree));
+	  FREE(m_tree);
+	  tree->complement = c;
+	  if (!InsertMlTable(table, tree->node, tree)) 
+	    return(NULL);
+	  if (!InsertMlTable(table, tree->complement, MlTree_Not(tree))) 
+	    return(NULL);
+	} else { /* It never happens at this time,
+		  * the case(c_tree == m_tree) is already taken care of.
+		  * But, it should be implemented to improve
+		  * in the future.
+		  */
+	}
+	if (VerifyTreeMode) {
+	  SynthVerifyTree(dd, tree, 0);
+	  SynthVerifyMlTable(dd, table);
+	}
+	return(tree);
+      } else if (MlTree_Regular(tree)->candidate) {
+	/*
+	**       tree     m_tree
+	**         |\      /|\
+	**         |   \/   |   \
+	**         | /    \ |      \
+	**         q        d        r
+	**/
+
+	if (tree->r == m_tree) {
+	  if (c_tree == m_tree)
+	    *comp_flag = 1;
+	  else
+	    *comp_flag = 0;
+
+	  if (ResolveConflictMode == 0 || c_tree == m_tree ||
+	      m_tree->nLiterals <= tree->nLiterals) {
+	    /* throw away tree and returns m_tree */
+	    bdd_recursive_deref_zdd(dd, c);
+	    UnlinkMlTree(tree);
+	    bdd_recursive_deref_zdd(dd, tree->node);
+	    st_delete(table, (char **)(&m_tree->node), NIL(char *));
+	    if (tree->support)
+	      FREE(tree->support);
+	    FREE(tree);
+	  } else if (c_tree != m_tree) {
+	    /*
+	    **      tree->complement = m_tree->complement
+	    **
+	    **       tree     m_tree
+	    **         |\      /|\
+	    **         |   \/   |   \
+	    **         | /    \ |      \
+	    **         q        d        r
+	    **/
+
+	    MlTree	*r_tree, *tmp_tree;
+	    int		r_comp;
+	    int		ref;
+	    bdd_node	*zero = bdd_read_zero(dd);
+
+	    /* takes tree's contents and throw away tree and m_tree->r */
+
+	    bdd_recursive_deref_zdd(dd, c);
+	    r_tree = SynthFindOrCreateMlTree(table, dd, zero, 1, 0, &ref,
+					     verbosity);
+	    if (!r_tree)
+	      return(NULL);
+	    if (MlTree_IsComplement(r_tree)) {
+	      r_tree = MlTree_Regular(r_tree);
+	      m_tree->r_comp = 1;
+	    }
+	    tmp_tree = r_tree;
+	    r_tree = SynthCheckAndMakeComplement(dd, table, r_tree,
+						 &r_comp, verbosity);
+	    if (!r_tree)
+	      return(NULL);
+	    else if (r_tree != tmp_tree) {
+	      if (r_comp)
+		m_tree->r_comp = 1;
+	      ref = 1;
+	    }
+	    tree->r = r_tree;
+	    tree->r_ref = ref;
+	    tree->id = m_tree->id;
+	    tree->candidate = 0;
+
+	    bdd_recursive_deref_zdd(dd, m_tree->node);
+	    bdd_recursive_deref_zdd(dd, m_tree->complement);
+	    st_delete(table, (char **)(&m_tree->node), NIL(char *));
+	    st_delete(table, (char **)(&m_tree->complement), NIL(char *));
+	    UnlinkMlTree(m_tree);
+	    if (m_tree->support)
+	      FREE(m_tree->support);
+	    ref = m_tree->r_ref;
+	    r_tree = m_tree->r;
+	    memcpy(m_tree, tree, sizeof(MlTree));
+	    FREE(tree);
+	    SynthPutMlTreeInList(dd, m_tree, 0);
+
+	    if (ref) {
+	      if (r_tree->shared)
+		DeleteMlTree(dd, table, r_tree, NULL, 1, 0);
+	    } else
+	      DeleteMlTree(dd, table, r_tree, NULL, 1, 0);
+	  } else { /* It never happens at this time,
+		    * the case(c_tree == m_tree) is already taken care of.
+		    * But, it should be implemented to improve
+		    * in the future.
+		    */
+	  }
+	  if (VerifyTreeMode) {
+	    SynthVerifyTree(dd, m_tree, 0);
+	    SynthVerifyMlTable(dd, table);
+	  }
+	  return(m_tree);
+	}
+	if (!SynthUseCandidate(table, dd, tree, verbosity)) {
+	  bdd_recursive_deref_zdd(dd, c);
+	  return(NULL);
+	}
+	SynthSetSharedFlag(dd, tree);
+      } else if (MlTree_Regular(c_tree)->candidate) {
+	if (m_tree->r == tree) {
+	  /*
+	  **      m_tree     tree
+	  **         |\      /|\
+	  **         |   \/   |   \
+	  **         | /    \ |      \
+	  **         q        d        r
+	  **/
+
+	  if (ResolveConflictMode == 0 || c_tree == m_tree ||
+	      tree->nLiterals <= m_tree->nLiterals) {
+	    /* throw away m_tree and assign c to tree->complement */
+	    UnlinkMlTree(m_tree);
+	    bdd_recursive_deref_zdd(dd, m_tree->node);
+	    bdd_recursive_deref_zdd(dd, m_tree->complement);
+	    st_delete(table, (char **)(&m_tree->node), NIL(char *));
+	    st_delete(table, (char **)(&m_tree->complement), NIL(char *));
+	    if (m_tree->support)
+	      FREE(m_tree->support);
+	    FREE(m_tree);
+	    tree->complement = c;
+	    if (!InsertMlTable(table, c, MlTree_Not(tree))) {
+	      tree->complement = NIL(bdd_node);
+	      bdd_recursive_deref_zdd(dd, c);
+	      return(NULL);
+	    }
+	  } else if (c_tree != m_tree) {
+	    /*
+	    **      tree->complement = m_tree->complement
+	    **
+	    **      m_tree     tree
+	    **         |\      /|\
+	    **         |   \/   |   \
+	    **         | /    \ |      \
+	    **         q        d        r
+	    **/
+
+	    MlTree	*r_tree, *tmp_tree;
+	    int		r_comp;
+	    int		ref;
+	    bdd_node	*zero = bdd_read_zero(dd);
+
+	    /* takes m_tree's contents and throw away m_tree and tree->r */
+
+	    bdd_recursive_deref_zdd(dd, c);
+	    r_tree = SynthFindOrCreateMlTree(table, dd, zero, 1, 0, &ref,
+					     verbosity);
+	    if (!r_tree)
+	      return(NULL);
+	    if (MlTree_IsComplement(r_tree)) {
+	      r_tree = MlTree_Regular(r_tree);
+	      m_tree->r_comp = 1;
+	    }
+	    tmp_tree = r_tree;
+	    r_tree = SynthCheckAndMakeComplement(dd, table, r_tree,
+						 &r_comp, verbosity);
+	    if (!r_tree)
+	      return(NULL);
+	    else if (r_tree != tmp_tree) {
+	      if (r_comp)
+		m_tree->r_comp = 1;
+	      ref = 1;
+	    }
+	    m_tree->r = r_tree;
+	    m_tree->r_ref = ref;
+	    m_tree->id = tree->id;
+	    m_tree->candidate = 0;
+
+	    bdd_recursive_deref_zdd(dd, tree->node);
+	    st_delete(table, (char **)(&tree->node), NIL(char *));
+	    UnlinkMlTree(tree);
+	    if (tree->support)
+	      FREE(tree->support);
+	    ref = tree->r_ref;
+	    r_tree = tree->r;
+	    memcpy(tree, m_tree, sizeof(MlTree));
+	    FREE(m_tree);
+	    SynthPutMlTreeInList(dd, tree, 0);
+
+	    if (ref) {
+	      if (r_tree->shared)
+		DeleteMlTree(dd, table, r_tree, NULL, 1, 0);
+	    } else
+	      DeleteMlTree(dd, table, r_tree, NULL, 1, 0);
+	  } else { /* It never happens at this time,
+		    * the case(c_tree == m_tree) is already taken care of.
+		    * But, it should be implemented to improve
+		    * in the future.
+		    */
+	    /*
+	    **      tree->complement = m_tree->node
+	    **
+	    **      m_tree     tree
+	    **         |\      /|\
+	    **         |   \/   |   \
+	    **         | /    \ |      \
+	    **         q        d        r
+	    **/
+	  }
+	  return(tree);
+	}
+	if (!SynthUseCandidate(table, dd, m_tree, verbosity)) {
+	  bdd_recursive_deref_zdd(dd, c);
+	  return(NULL);
+	}
+	SynthSetSharedFlag(dd, m_tree);
+      }
+
+      bdd_recursive_deref_zdd(dd, c);
+      if (c_tree == m_tree)
+	*comp_flag = 1;
+      else
+	*comp_flag = 0;
+
+      if (verbosity)
+	(void) fprintf(vis_stdout, "** synth warning: Duplicate entry ...\n");
+      new_ = ResolveConflictNode(dd, table, c_tree, tree, *comp_flag, verbosity);
+      if (verbosity)
+	(void) fprintf(vis_stdout, "** synth info: Conflict was resolved.\n");
+      if (VerifyTreeMode) {
+	SynthVerifyTree(dd, new_, 0);
+	SynthVerifyMlTable(dd, table);
+      }
+      return(new_);
+    } else if (bdd_read_reordered_field(dd) || noMemoryFlag == 1) {
+      bdd_recursive_deref_zdd(dd, c);
+      return(NULL);
+    }
+    tree->complement = c;
+    if (!InsertMlTable(table, c, MlTree_Not(tree))) {
+      tree->complement = NIL(bdd_node);
+      bdd_recursive_deref_zdd(dd, c);
+      return NULL;
+    }
+  }
+  return(tree);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Sets the shared field of tree to 1.]
+
+  Description [Sets the shared field of tree to 1.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthSetSharedFlag(bdd_manager *dd,
+		   MlTree *tree)
+{
+  MlTree	*t;
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+
+  t = MlTree_Regular(tree);
+  if (t->node == zero || t->node == one)
+    return;
+  if (t->pi == 0)
+    t->shared = 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Factorizes leaf nodes of MlTree.]
+
+  Description [Factorizes leaf nodes of MlTree. A leaf node of MlTree
+  can not be factorized by itself. This function tries to factorize
+  among all leaf nodes. A leaf node can be divided by another leaf
+  node. If successful, it returns 0, otherwise it returns 1 due to lack
+  of memory.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+SynthPostFactoring(bdd_manager *dd,
+		   st_table *table,
+		   MlTree *(* factoring_func)(bdd_manager *, st_table *,
+					      bdd_node *, int, int *, MlTree *,
+					      int, MlTree *, int),
+		   int verbosity)
+{
+  MlTree	*cur, *candy;
+  int		ref;
+  bdd_node	*q;
+  bdd_node	*zero = bdd_read_zero(dd);
+
+  if (VerifyTreeMode) {
+    SynthVerifyMlTable(dd, table);
+    VerifyTreeList();
+  }
+
+  cur = MlTreeHead;
+  while (cur) {
+    if (cur->leaf) {
+      if (cur->nLiterals < 2)
+	break;
+      candy = cur->next;
+      while (candy) {
+	if (candy->nLiterals == 1)
+	  break;
+	else if (candy->leaf == 0 ||
+		 candy->nLiterals == cur->nLiterals) {
+	  candy = candy->next;
+	  continue;
+	}
+
+	q = (* ZddDivideFunc)(dd, cur->node, candy->node);
+	if (!q)
+	  return(1);
+	bdd_ref(q);
+	/* Even though we deref q, it still exists as a
+	 * pointer and beyond this point, we use it only to
+	 * check if it is zero or not.
+	 */
+	bdd_recursive_deref_zdd(dd,q);
+	if (q != zero) {
+	  (void) (* factoring_func)(dd, table, cur->node,
+				    0, &ref, candy, 0, cur, verbosity);
+	  if (VerifyTreeMode) {
+	    SynthVerifyTree(dd, cur, 0);
+	    SynthVerifyMlTable(dd, table);
+	    VerifyTreeList();
+	  }
+	  if (bdd_read_reordered_field(dd) || noMemoryFlag == 1)
+	    return(1);
+
+	  SynthSetSharedFlag(dd, candy);
+	  break;
+	} else {
+	  q = (* ZddDivideFunc)(dd, cur->node, 
+				candy->complement);
+	  if (!q)
+	    return(1);
+	  bdd_ref(q);
+	  /* Even though we deref q, it still exists as a
+	   * pointer and beyond this point, we use it only
+	   * to check if it is zero or not.
+	   */
+	  bdd_recursive_deref_zdd(dd,q);
+	  if (q != zero) {
+	    (void) (* factoring_func)(dd, table, cur->node, 0,
+				      &ref, candy, 1, cur, verbosity);
+	    if (VerifyTreeMode) {
+	      SynthVerifyTree(dd, cur, 0);
+	      SynthVerifyMlTable(dd, table);
+	      VerifyTreeList();
+	    }
+	    if (bdd_read_reordered_field(dd) || noMemoryFlag == 1 )
+	      return(1);
+	    SynthSetSharedFlag(dd, candy);
+	    break;
+	  }
+	}
+	candy = candy->next;
+      }
+    }
+    cur = cur->next;
+  }
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Updates the ref field of all parent nodes whose one child
+  is top.]
+
+  Description [Updates the ref field of all parent nodes whose one child
+  is top.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthUpdateRefOfParent(MlTree *top)
+{
+  MlTree	*cur;
+
+  cur = MlTreeHead;
+  while (cur) {
+    if (cur->q == top)
+      cur->q_ref = 1;
+    else if (cur->d == top)
+      cur->d_ref = 1;
+    else if (cur->r == top)
+      cur->r_ref = 1;
+    cur = cur->next;
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Verifies whether in a tree everything is correct.]
+
+  Description [Verifies whether in a tree everything is correct.
+  Used for debugging. The argument flag is used to control verifying
+  recursively.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthVerifyTree(bdd_manager *dd,
+		MlTree *tree,
+		int flag)
+{
+  bdd_node	*node, *comp;
+  bdd_node	*q, *d, *r, *f, *m;
+  int		bdd_diff;
+
+  if (flag && !tree->leaf) {
+    if (!tree->q_ref)
+      SynthVerifyTree(dd, tree->q, flag);
+    if (!tree->d_ref)
+      SynthVerifyTree(dd, tree->d, flag);
+    if (!tree->r_ref)
+      SynthVerifyTree(dd, tree->r, flag);
+  }
+
+  node = bdd_make_bdd_from_zdd_cover(dd, tree->node);
+  if (!node)
+    return;
+  bdd_ref(node);
+  if (tree->complement) {
+    comp = bdd_make_bdd_from_zdd_cover(dd, tree->complement);
+    if (!comp) {
+      bdd_recursive_deref(dd, node);
+      return;
+    }
+    bdd_ref(comp);
+    
+    if (node != bdd_not_bdd_node(comp)) {
+      (void) fprintf(vis_stdout,
+	"** synth error: Invalid complement node in tree [%d].\n", tree->id);
+    }
+    
+    bdd_recursive_deref(dd, comp);
+  }
+
+  if (tree->leaf) {
+    if (tree->q) {
+      (void) fprintf(vis_stdout,
+	     "** synth error: q exists in leaf tree [%d].\n", tree->id);
+    }
+    if (tree->d) {
+      (void) fprintf(vis_stdout,
+	     "** synth error: d exists in leaf tree [%d].\n", tree->id);
+    }
+    if (tree->r) {
+      (void) fprintf(vis_stdout,
+	     "** synth error: r exists in leaf tree [%d].\n", tree->id);
+    }
+    if (tree->q_ref) {
+      (void) fprintf(vis_stdout,
+	     "** synth error: q_ref = 1 in leaf tree [%d].\n", tree->id);
+    }
+    if (tree->d_ref) {
+      (void) fprintf(vis_stdout,
+	     "** synth error: d_ref = 1 in leaf tree [%d].\n", tree->id);
+    }
+    if (tree->r_ref) {
+      (void) fprintf(vis_stdout,
+	     "** synth error: r_ref = 1 in leaf tree [%d].\n", tree->id);
+    }
+    if (tree->q_comp) {
+      (void) fprintf(vis_stdout,
+	     "** synth error: q_comp = 1 in leaf tree [%d].\n", tree->id);
+    }
+    if (tree->d_comp) {
+      (void) fprintf(vis_stdout,
+	     "** synth error: d_comp = 1 in leaf tree [%d].\n", tree->id);
+    }
+    if (tree->r_comp) {
+      (void) fprintf(vis_stdout,
+	     "** synth error: r_comp = 1 in leaf tree [%d].\n", tree->id);
+    }
+    bdd_recursive_deref(dd, node);
+    return;
+  }
+  else {
+    if (tree->pi) {
+      (void) fprintf(vis_stdout,
+	     "** synth error: pi = 1 in non-leaf tree [%d].\n", tree->id);
+    }
+  }
+
+  if (!tree->q) {
+    (void) fprintf(vis_stdout,
+		   "** synth error: no q in tree [%d].\n", tree->id);
+    bdd_recursive_deref(dd, node);
+    return;
+  }
+  if (tree->q_comp)
+    q = bdd_make_bdd_from_zdd_cover(dd, tree->q->complement);
+  else
+    q = bdd_make_bdd_from_zdd_cover(dd, tree->q->node);
+  if (!q) {
+    (void) fprintf(vis_stdout,
+		   "** synth error: no q node in tree [%d].\n", tree->id);
+    bdd_recursive_deref(dd, node);
+    return;
+  }
+  bdd_ref(q);
+  if (!tree->d) {
+    (void) fprintf(vis_stdout,
+		   "** synth error: no d in tree [%d].\n", tree->id);
+    bdd_recursive_deref(dd, node);
+    bdd_recursive_deref(dd, q);
+    return;
+  }
+  if (tree->d_comp)
+    d = bdd_make_bdd_from_zdd_cover(dd, tree->d->complement);
+  else
+    d = bdd_make_bdd_from_zdd_cover(dd, tree->d->node);
+  if (!d) {
+    (void) fprintf(vis_stdout,
+		   "** synth error: no d node in tree [%d].\n", tree->id);
+    bdd_recursive_deref(dd, node);
+    bdd_recursive_deref(dd, q);
+    return;
+  }
+  bdd_ref(d);
+  if (!tree->candidate) {
+    if (!tree->r) {
+      (void) fprintf(vis_stdout,
+		     "** synth error: no r in tree [%d].\n", tree->id);
+      bdd_recursive_deref(dd, node);
+      bdd_recursive_deref(dd, q);
+      bdd_recursive_deref(dd, d);
+      return;
+    }
+    if (tree->r_comp)
+      r = bdd_make_bdd_from_zdd_cover(dd, tree->r->complement);
+    else
+      r = bdd_make_bdd_from_zdd_cover(dd, tree->r->node);
+    if (!r) {
+      (void) fprintf(vis_stdout,
+		     "** synth error: no r node in tree [%d].\n", tree->id);
+      bdd_recursive_deref(dd, node);
+      bdd_recursive_deref(dd, q);
+      bdd_recursive_deref(dd, d);
+      return;
+    }
+    bdd_ref(r);
+    
+    m = bdd_bdd_and(dd, q, d);
+    if (!m) {
+      bdd_recursive_deref(dd, node);
+      bdd_recursive_deref(dd, q);
+      bdd_recursive_deref(dd, d);
+      bdd_recursive_deref(dd, r);
+      return;
+    }
+    bdd_ref(m);
+    bdd_recursive_deref(dd, q);
+    bdd_recursive_deref(dd, d);
+    f = bdd_bdd_or(dd, m, r);
+    if (!f) {
+      bdd_recursive_deref(dd, node);
+      bdd_recursive_deref(dd, r);
+      bdd_recursive_deref(dd, m);
+      return;
+    }
+    bdd_ref(f);
+    bdd_recursive_deref(dd, r);
+    bdd_recursive_deref(dd, m);
+  } else {
+    f = bdd_bdd_and(dd, q, d);
+    if (!f) {
+      bdd_recursive_deref(dd, node);
+      bdd_recursive_deref(dd, q);
+      bdd_recursive_deref(dd, d);
+      return;
+    }
+    bdd_ref(f);
+    bdd_recursive_deref(dd, q);
+    bdd_recursive_deref(dd, d);
+  }
+  if (!f) {
+    bdd_recursive_deref(dd, node);
+    return;
+  }
+
+  if (f == node)
+    bdd_diff = 0;
+  else
+    bdd_diff = 1;
+
+  bdd_recursive_deref(dd, f);
+  bdd_recursive_deref(dd, node);
+
+  if (tree->comp)
+    node = tree->complement;
+  else
+    node = tree->node;
+  if (tree->q_comp)
+    q = tree->q->complement;
+  else
+    q = tree->q->node;
+  if (tree->d_comp)
+    d = tree->d->complement;
+  else
+    d = tree->d->node;
+  if (!tree->candidate) {
+    if (tree->r_comp)
+      r = tree->r->complement;
+    else
+      r = tree->r->node;
+    m = (* SynthGetZddProductFunc())(dd, d, q);
+    if (!m)
+      return;
+    bdd_ref(m);
+    f = bdd_zdd_union(dd, m, r);
+    if (!f) {
+      bdd_recursive_deref_zdd(dd, m);
+      return;
+    }
+    bdd_ref(f);
+    bdd_recursive_deref_zdd(dd, m);
+  } else {
+    f = (* SynthGetZddProductFunc())(dd, d, q);
+    if (!f)
+      return;
+    bdd_ref(f);
+  }
+  if (f != node) {
+    if (bdd_diff) {
+      (void) fprintf(vis_stdout,
+	     "** synth error: BDD & ZDD f != qd+r in tree [%d - 0x%lx].\n",
+	     tree->id, (unsigned long)tree);
+    }
+    else {
+      (void) fprintf(vis_stdout,
+		     "Warning : ZDD f != qd+r in tree [%d - 0x%lx].\n",
+		     tree->id, (unsigned long)tree);
+    }
+  }
+  else if (bdd_diff) {
+    (void) fprintf(vis_stdout,
+		   "** synth error: BDD f != qd+r in tree [%d - 0x%lx].\n",
+		   tree->id, (unsigned long)tree);
+  }
+  bdd_recursive_deref_zdd(dd, f);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Verifies the node-tree table to see whether everything is
+  correct.]
+
+  Description [Verifies the node-tree table to see whether everything is
+  correct. Used for debugging]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthVerifyMlTable(bdd_manager *dd,
+		   st_table *table)
+{
+  st_generator	*gen;
+  bdd_node		*node;
+  MlTree		*tree, *reg;
+
+  st_foreach_item(table, gen, (&node), (&tree)) {
+    reg = MlTree_Regular(tree);
+    if ((reg == tree && node != reg->node) ||
+	(reg != tree && node != reg->complement)) {
+      (void) fprintf(vis_stdout,
+		     "** synth error: wrong node in tree [%d].\n", reg->id);
+    }
+    tree = reg;
+    if (tree->id >= NumTree) {
+      (void) fprintf(vis_stdout,
+		     "** synth error: wrong id in tree [%d].\n", tree->id);
+    }
+    if (!tree->leaf) {
+      if (!tree->d) {
+	(void) fprintf(vis_stdout,
+	       "** synth error: d doesn't exist in tree [%d].\n", tree->id);
+      }
+      if (!tree->q) {
+	(void) fprintf(vis_stdout,
+	       "** synth error: q doesn't exist in tree [%d].\n", tree->id);
+      }
+      if (!tree->r && !tree->candidate) {
+	(void) fprintf(vis_stdout,
+	       "** synth error: r doesn't exist in tree [%d].\n", tree->id);
+      }
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Prints all tree lists.]
+
+  Description [Prints all tree lists. Used for debugging.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthPrintTreeList(MlTree *list)
+{
+  MlTree *cur = list;
+  if (!cur)
+    cur = MlTreeHead;
+  while (cur) {
+    printf("%d (%d) - %d [0x%lx]\n", cur->id, cur->nLiterals,
+	   cur->leaf, (unsigned long)cur);
+    cur = cur->next;
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Prints all leaf tree lists.]
+
+  Description [Prints all leaf tree lists. Used for debugging.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthPrintLeafList(MlTree *list)
+{
+  MlTree *cur = list;
+  if (!cur)
+    cur = MlTreeHead;
+  while (cur) {
+    if (cur->leaf)
+      printf("%d (%d) [0x%lx]\n", cur->id, cur->nLiterals, (unsigned long)cur);
+    cur = cur->next;
+  }
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis [Resolves the conflict nodes that can be merged.]
+
+  Description [Resolves the conflict nodes that can be merged. One tree
+  has a regular node, the other tree has the complement of the node.
+  This case is called conflict. And these two trees are merged into one,
+  and this is called resolution. It happens because by default the
+  complement of remainder is not computed since it is very expensive.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static MlTree *
+ResolveConflictNode(bdd_manager *dd,
+		    st_table *table,
+		    MlTree *tree1,
+		    MlTree *tree2,
+		    int comp_flag,
+		    int verbosity)
+{
+  MlTree	*live_tree, *kill_tree;
+
+  if (MlTree_IsComplement(tree1))
+    tree1 = MlTree_Regular(tree1);
+  if (MlTree_IsComplement(tree2))
+    tree2 = MlTree_Regular(tree2);
+
+  if (verbosity) {
+    if (tree1->complement || tree2->complement)
+      (void) fprintf(vis_stdout, "** synth warning: real conflict.\n");
+  }
+
+  if (ResolveConflictMode == 0) {
+    live_tree = tree1;
+    kill_tree = tree2;
+  } else {
+    if (tree1->nLiterals > tree2->nLiterals) {
+      live_tree = tree2;
+      kill_tree = tree1;
+    } else {
+      live_tree = tree1;
+      kill_tree = tree2;
+    }
+  }
+
+  if (!live_tree->complement) {
+    if (comp_flag)
+      live_tree->complement = kill_tree->node;
+    else
+      live_tree->complement = kill_tree->complement;
+    bdd_ref(live_tree->complement);
+    bdd_recursive_deref_zdd(dd, kill_tree->node);
+    st_delete(table, (char **)(&kill_tree->node), NIL(char *));
+    if (kill_tree->complement) {
+	bdd_recursive_deref_zdd(dd, kill_tree->complement);
+	st_delete(table, (char **)(&kill_tree->complement), NIL(char *));
+    }
+    st_insert(table, (char *)live_tree->complement,
+	      (char *)MlTree_Not(live_tree));
+  } else {
+    bdd_recursive_deref_zdd(dd, kill_tree->node);
+    st_delete(table, (char **)(&kill_tree->node), NIL(char *));
+    if (kill_tree->complement) {
+	bdd_recursive_deref_zdd(dd, kill_tree->complement);
+	st_delete(table, (char **)(&kill_tree->complement), NIL(char *));
+    }
+  }
+
+  DeleteMlTree(dd, table, kill_tree, live_tree, 0, comp_flag);
+  SynthSetSharedFlag(dd, live_tree);
+
+  if (VerifyTreeMode) {
+    SynthVerifyTree(dd, live_tree, 0);
+    SynthVerifyMlTable(dd, table);
+    VerifyTreeList();
+  }
+
+  return(live_tree);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Deletes the tree nodes due to conflict.]
+
+  Description [Deletes the tree nodes due to conflict.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+DeleteMlTree(bdd_manager *dd,
+	     st_table *table,
+	     MlTree *kill_tree,
+	     MlTree *live_tree,
+	     int deref,
+	     int comp_flag)
+{
+  MlTree	*cur, *pre, *next;
+  int		ref;
+
+  if (kill_tree->shared && deref) {
+    ref = 0;
+    cur = MlTreeHead;
+    while (cur) {
+      if (cur == kill_tree) {
+	cur = cur->next;
+	continue;
+      }
+      if (cur->q == kill_tree)
+	ref++;
+      else if (cur->d == kill_tree)
+	ref++;
+      else if (cur->r == kill_tree)
+	ref++;
+      cur = cur->next;
+    }
+
+    if (ref == 1)
+      kill_tree->shared = 0;
+    return;
+  }
+
+  DeleteMlSizeList(kill_tree);
+
+  if (kill_tree->id == NumTree - 1)
+    NumTree--;
+  if (deref) {
+    bdd_recursive_deref_zdd(dd, kill_tree->node);
+    st_delete(table, (char **)(&kill_tree->node), NIL(char *));
+    if (kill_tree->complement) {
+	bdd_recursive_deref_zdd(dd, kill_tree->complement);
+	st_delete(table, (char **)(&kill_tree->complement), NIL(char *));
+    }
+  }
+  pre = NIL(MlTree);
+  cur = MlTreeHead;
+  while (cur) {
+    if (cur == kill_tree) {
+      next = cur->next;
+      if (pre)
+	pre->next = next;
+      else
+	MlTreeHead = next;
+      cur = next;
+      if (!live_tree)
+	break;
+    } else {
+      if (live_tree) {
+	if (cur->q == kill_tree) {
+	  if (comp_flag)
+	    cur->q_comp ^= 01;
+	  cur->q = live_tree;
+	  cur->q_ref = 1;
+	  if (VerifyTreeMode)
+	    SynthVerifyTree(dd, cur, 0);
+	} else if (cur->d == kill_tree) {
+	  if (comp_flag)
+	    cur->d_comp ^= 01;
+	  cur->d = live_tree;
+	  cur->d_ref = 1;
+	  if (VerifyTreeMode)
+	    SynthVerifyTree(dd, cur, 0);
+	} else if (cur->r == kill_tree) {
+	  if (comp_flag)
+	    cur->r_comp ^= 01;
+	  cur->r = live_tree;
+	  cur->r_ref = 1;
+	  if (VerifyTreeMode)
+	    SynthVerifyTree(dd, cur, 0);
+	}
+      }
+      pre = cur;
+      cur = cur->next;
+    }
+  }
+
+  if (kill_tree->leaf == 0) {
+    if (kill_tree->q_ref) {
+      if (kill_tree->q->shared)
+	DeleteMlTree(dd, table, kill_tree->q, NULL, 1, 0);
+    } else
+      DeleteMlTree(dd, table, kill_tree->q, NULL, 1, 0);
+    if (kill_tree->d_ref) {
+      if (kill_tree->d->shared)
+	DeleteMlTree(dd, table, kill_tree->d, NULL, 1, 0);
+    } else
+      DeleteMlTree(dd, table, kill_tree->d, NULL, 1, 0);
+    if (kill_tree->r_ref) {
+      if (kill_tree->r->shared)
+	DeleteMlTree(dd, table, kill_tree->r, NULL, 1, 0);
+    } else
+      DeleteMlTree(dd, table, kill_tree->r, NULL, 1, 0);
+  }
+
+  if (kill_tree->support)
+    FREE(kill_tree->support);
+  FREE(kill_tree);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Unlinks a tree from the list.]
+
+  Description [Unlinks a tree from the list.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+UnlinkMlTree(MlTree *kill_tree)
+{
+  MlTree	*cur, *pre;
+
+  DeleteMlSizeList(kill_tree);
+
+  pre = (MlTree *)NULL;
+  cur = MlTreeHead;
+  while (cur) {
+    if (cur == kill_tree) {
+	if (pre)
+	  pre->next = cur->next;
+	else
+	  MlTreeHead = cur->next;
+	break;
+    }
+    pre = cur;
+    cur = cur->next;
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Deletes a tree from the size list.]
+
+  Description [Deletes a tree from the size list.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+DeleteMlSizeList(MlTree *tree)
+{
+  MlTree	*head, *tail, *cur, *pre;
+  MlSizeList	*list, *pre_list;
+  int		size;
+
+  size = tree->nLiterals;
+  pre_list = NIL(MlSizeList);
+  list = MlSizeHead;
+  while (list) {
+    if (size == list->size) {
+      st_lookup(HeadListTable, list->string, (&head));
+      st_lookup(TailListTable, list->string, (&tail));
+      if (head == tail) {
+	assert(tree == head);
+	if (pre_list)
+	  pre_list->next = list->next;
+	else
+	  MlSizeHead = list->next;
+	st_delete(HeadListTable, (char **)&list->string, NIL(char *));
+	st_delete(TailListTable, (char **)&list->string, NIL(char *));
+	FREE(list->string);
+	FREE(list);
+      } else {
+	pre = NIL(MlTree);
+	cur = head;
+	while (cur) {
+	  if (cur == tree) {
+	    if (cur == head) {
+	      st_delete(HeadListTable, (char **)&list->string, NIL(char *));
+	      st_insert(HeadListTable, list->string, (char *)cur->next);
+	    } else if (cur == tail) {
+	      st_delete(TailListTable, (char **)&list->string, NIL(char *));
+	      st_insert(TailListTable, list->string, (char *)pre);
+	    }
+	    break;
+	  }
+	  pre = cur;
+	  cur = cur->next;
+	}
+      }
+      break;
+    } else if (size > list->size)
+      break;
+    pre_list = list;
+    list = list->next;
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Inserts a new node-tree pair into the node-tree table.]
+
+  Description [Inserts a new node-tree pair into the node-tree table.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+InsertMlTable(st_table *table,
+	      bdd_node *node,
+	      MlTree *tree)
+{
+  int		flag;
+
+  flag = st_insert(table, (char *)node, (char *)tree);
+  if (flag == ST_OUT_OF_MEM) {
+    (void) fprintf(vis_stdout,"** synth error: Out of Memory.\n");
+    noMemoryFlag = 1;
+    return (0);
+  } else if (flag == 1)
+    (void) fprintf(vis_stdout, "** synth warning: Duplicate entry.\n");
+  return(1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Makes the complement of a ZDD node.]
+
+  Description [Makes the complement of a ZDD node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static bdd_node	*
+MakeComplementOfZddCover(bdd_manager *dd,
+			 bdd_node *node,
+			 int verbosity)
+{
+  bdd_node	*comp;
+
+  if (verbosity > 1) {
+    (void) fprintf(vis_stdout,"*****\n");
+    SynthPrintZddTreeMessage(dd, node, "R : ");
+  }
+
+  comp = bdd_zdd_complement(dd, node);
+  if (!comp)
+    return(NULL);
+
+  if (verbosity > 1) {
+    SynthPrintZddTreeMessage(dd, comp, "C : ");
+    (void) fprintf(vis_stdout,"*****\n");
+  }
+
+  return(comp);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns a string containing a given integer value.]
+
+  Description [Returns a string containing a given integer value.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static	char *
+GetIntString(int v)
+{
+  char	string[12];
+  char	*ret;
+
+  sprintf(string, "%d", v);
+  ret = (char *)ALLOC(char, strlen(string) + 1);
+  strcpy(ret, string);
+  return(ret);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Verify all tree lists to see whether all is correct.]
+
+  Description [Verify all tree lists to see whether all is correct.
+  Used for debugging.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+VerifyTreeList(void)
+{
+  int		count;
+  MlTree	*cur, *candy;
+
+  cur = MlTreeHead;
+  while (cur) {
+    count = 0;
+    candy = cur->next;
+    if (candy && candy->nLiterals > cur->nLiterals) {
+      (void) fprintf(vis_stdout,
+	     "** synth error: predecessor[%d]'s size < successor[%d]'s size.\n",
+		     cur->id, candy->id);
+    }
+    while (candy) {
+      if (cur->id != 0) {
+	if (candy->id == cur->id && candy != cur) {
+	  (void) fprintf(vis_stdout,
+		 "** synth error: same id already exists [%d].\n", cur->id);
+	  break;
+	}
+      }
+      if (candy == cur) {
+	if (count > 0) {
+	  (void) fprintf(vis_stdout,
+		 "** synth error: same address already exists [%d - 0x%lx].\n",
+			 cur->id, (unsigned long)cur);
+	  break;
+	}
+	count++;
+      }
+      candy = candy->next;
+    }
+    cur = cur->next;
+  }
+}
Index: vis_dev/vis-2.3/src/synth/synthGen.c
===================================================================
--- vis_dev/vis-2.3/src/synth/synthGen.c	(revision 14)
+++ vis_dev/vis-2.3/src/synth/synthGen.c	(revision 14)
@@ -0,0 +1,1340 @@
+/**CFile***********************************************************************
+
+  FileName    [synthGen.c]
+
+  PackageName [synth]
+
+  Synopsis    [Generic multilevel factorization method.]
+
+  Description []
+
+  Author      [In-Ho Moon, Balakrishna Kumthekar]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "synthInt.h"
+
+static char rcsid[] UNUSED = "$Id: synthGen.c,v 1.36 2005/05/11 20:17:21 hhhan Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+extern	int		UseMtree;
+extern	int		UseCommonDivisor;
+extern	int		TryNodeSharing;
+extern	int		Resubstitution;
+extern	int		RemainderComplement;
+extern  int             noMemoryFlag;
+extern  int             VerifyTreeMode;
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static MlTree * LiteralFactoringTree(bdd_manager *dd, st_table *table, bdd_node *f, bdd_node *c, int level, int *ref, MlTree *bring, int verbosity);
+static bdd_node * BestLiteral(bdd_manager *dd, bdd_node *f, bdd_node *c);
+static int IsCubeFree(bdd_manager *dd, bdd_node *f);
+static bdd_node * CommonCube(bdd_manager *dd, bdd_node *f);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Factorizes a function using a generic method.]
+
+  Description [Factorizes a function using a generic method. This
+  algorithm came from the book "Logic Synthesis and Verification Algorithms"
+  by Gary Hachtel and Fabio Somenzi. The argument table consists of a pair of
+  bdd_node and MlTree, f is to be factorized, level is the depth of
+  MlTree from top, ref returns 1 if new MlTree is created for f,
+  otherwise returns 0, comp_d_tree is usually NULL except when post
+  factoring takes place(here post factoring is case to factorize a leaf
+  node by another leaf node and a leaf node is a node in which there is
+  no divisor), comp_d_tree is a tree which is going to be used as a
+  divisor and comp_d_flag is used to indicate which node is going to be
+  used as a divisor between regular node and complement node, bring is
+  usually NULL except post factoring: when we update an already existing
+  tree by further factorization, we pass this tree to reuse it.]
+
+  SideEffects []
+
+  SeeAlso     [SynthSimpleFactorTree]
+
+******************************************************************************/
+MlTree *
+SynthGenericFactorTree(bdd_manager *dd,
+		       st_table *table,
+		       bdd_node *f,
+		       int level,
+		       int *ref,
+		       MlTree *comp_d_tree,
+		       int comp_d_flag,
+		       MlTree *bring,
+		       int verbosity)
+{
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  bdd_node	*d, *q, *r, *m, *c;
+  MlTree	*tree, *q_tree, *d_tree, *r_tree;
+  int		q_ref, d_ref, r_ref;
+  int		ncubes;
+  bdd_node	*tmp;
+  char		message[80];
+  char		space[80];
+  MlTree	*comp_q_tree = (MlTree *)NULL;
+  MlTree	*comp_r_tree = (MlTree *)NULL;
+  int		found;
+  MlTree	*tmp_tree;
+  int		comp_flag;
+
+  if (verbosity > 1) {
+    SynthGetSpaceString(space, level * 2, 80);
+    sprintf(message, "%s[%d] in : ", space, level);
+    SynthPrintZddTreeMessage(dd, f, message);
+    sprintf(message, "%s[%d]out : ", space, level);
+  }
+
+  if (bring)
+    tree = (MlTree *)NULL;
+  else {
+    tree = SynthLookupMlTable(table, dd, f, 1, verbosity);
+    /* tree could be NULL because of reordering, or a failure to
+     * allocate memory or just that f was not in the cache.
+     * So, we would like return NULL ONLY in the case of 
+     * reordering or failure to allocate memory. 
+     */
+    if (bdd_read_reordered_field(dd) || noMemoryFlag == 1)
+      return(NULL);
+  }
+  if (tree) {
+    if (verbosity > 1)
+      SynthPrintMlTreeMessage(dd, tree, message);
+    *ref = 1;
+    return(tree);
+  }
+
+  if (f == one || f == zero) {
+    tree = SynthFindOrCreateMlTree(table, dd, f, 1, 0, ref, verbosity);
+    if (!tree)
+      return(NULL);
+    tmp_tree = tree;
+    tree = SynthCheckAndMakeComplement(dd, table, tree, &comp_flag, verbosity);
+    if (!tree) {
+      if (*ref == 0)
+	SynthFreeMlTree(MlTree_Regular(tmp_tree), 1);
+      return(NULL);
+    } else if (tree != tmp_tree) {
+      *ref = 1;
+      if (comp_flag)
+	tree = MlTree_Not(tree);
+    }
+    if (verbosity > 1)
+      SynthPrintMlTreeMessage(dd, tree, message);
+    return(tree);
+  }
+
+  d_tree = (MlTree *)NULL;
+  if (comp_d_tree) {
+    if (comp_d_flag)
+      d = comp_d_tree->complement;
+    else
+      d = comp_d_tree->node;
+    if (!d)
+      return((MlTree *)NULL);
+    bdd_ref(d);
+  } else {
+    found = 0;
+    d = (* SynthGetZddDivisorFunc())(dd, f);
+    if (!d)
+      return(NULL);
+    bdd_ref(d);
+    if (TryNodeSharing) {
+      /* Here, we don't need to call bdd_ref. */
+      d = SynthFindBiggerDivisorInList(dd, table, f, d, &found,
+				       &comp_d_flag, &comp_d_tree, verbosity);
+      if (!d)
+	return(NULL);
+    }
+    if (UseCommonDivisor && found == 0) {
+      tree = SynthGetFactorTreeWithCommonDivisor(dd, table,
+		 SynthGenericFactorTree, f, d, level, ref, verbosity);
+      if (tree)
+	return(tree);
+      if (bdd_read_reordered_field(dd) || noMemoryFlag == 1) {
+	bdd_recursive_deref_zdd(dd, d);
+	return(NULL);
+      }
+    }
+  }
+  if (d == f) {
+    tree = SynthFindOrCreateMlTree(table, dd, f, 1, 0, ref, verbosity);
+    if (!tree) {
+      bdd_recursive_deref_zdd(dd, d);
+      return(NULL);
+    }
+    if (verbosity > 1)
+      SynthPrintMlTreeMessage(dd, tree, message);
+    tmp_tree = tree;
+    tree = SynthCheckAndMakeComplement(dd, table, tree, &comp_flag, verbosity);
+    if (!tree) {
+      bdd_recursive_deref_zdd(dd, d);
+      return(NULL);
+    } else if (tree == tmp_tree) {
+      if (*ref == 0)
+	SynthPutMlTreeInList(dd, tree, 0);
+    } else {
+      *ref = 1;
+      if (comp_flag)
+	tree = MlTree_Not(tree);
+    }
+    bdd_recursive_deref_zdd(dd, d);
+    return(tree);
+  }
+  if (!comp_d_tree) {
+    if (st_lookup(table, (char *)d, &d_tree)) {
+      SynthSetSharedFlag(dd, d_tree);
+      if (MlTree_Regular(d_tree)->candidate) {
+	if (!SynthUseCandidate(table, dd, d_tree, verbosity)) {
+	  bdd_recursive_deref_zdd(dd, d);
+	  return(NULL);
+	}
+      }
+      if (MlTree_IsComplement(d_tree)) {
+	d_tree = MlTree_Regular(d_tree);
+	comp_d_tree = d_tree;
+	comp_d_flag = 1;
+	d_tree = (MlTree *)NULL;
+      }
+      else
+	comp_d_flag = 0;
+    }
+  } else {
+    if (!comp_d_flag)
+      d_tree = comp_d_tree;
+  }
+
+  q = (* SynthGetZddDivideFunc())(dd, f, d);
+  if (!q) {
+    bdd_recursive_deref_zdd(dd, d);
+    return(NULL);
+  }
+  bdd_ref(q);
+  if (comp_d_tree && q == zero) {
+    bdd_recursive_deref_zdd(dd, d);
+    bdd_recursive_deref_zdd(dd, q);
+    return((MlTree *)NULL);
+  }
+  if (q == one) {
+    bdd_recursive_deref_zdd(dd, q);
+    tree = SynthPostFactorTree(dd, table, f, q, d, bring,
+		       comp_d_tree, comp_d_flag, message, ref, verbosity);
+    bdd_recursive_deref_zdd(dd, d);
+    return(tree);
+  }
+
+  ncubes = bdd_zdd_count(dd, q);
+  if (ncubes == 1) {
+    if (d_tree || comp_d_tree) {
+      m = (* SynthGetZddProductFunc())(dd, q, d);
+      if (!m) {
+	bdd_recursive_deref_zdd(dd, d);
+	bdd_recursive_deref_zdd(dd, q);
+	return(NULL);
+      }
+      bdd_ref(m);
+      bdd_recursive_deref_zdd(dd, d);
+      r = bdd_zdd_diff(dd, f, m);
+      bdd_recursive_deref_zdd(dd, m);
+      if (!r) {
+	bdd_recursive_deref_zdd(dd, q);
+	return(NULL);
+      }
+      bdd_ref(r);
+      bdd_recursive_deref_zdd(dd,r);
+      if (r == zero) {
+	if (!d_tree)
+	  d_tree = comp_d_tree;
+	d_ref = 1;
+	q_tree = (MlTree *)NULL;
+	if (st_lookup(table, (char *)q, &q_tree)) {
+	  SynthSetSharedFlag(dd, q_tree);
+	  if (MlTree_Regular(q_tree)->candidate) {
+	    if (!SynthUseCandidate(table, dd, q_tree, verbosity)) {
+	      bdd_recursive_deref_zdd(dd, q);
+	      return(NULL);
+	    }
+	  }
+	  if (MlTree_IsComplement(q_tree)) {
+	    q_tree = MlTree_Regular(q_tree);
+	    comp_q_tree = q_tree;
+	  }
+	  q_ref = 1;
+	} else {
+	  q_tree = SynthFindOrCreateMlTree(table, dd, q, 1,
+					   0, &q_ref, verbosity);
+	  if (!q_tree) {
+	    bdd_recursive_deref_zdd(dd, q);
+	    return(NULL);
+	  }
+	  if (MlTree_IsComplement(q_tree)) {
+	    comp_q_tree = MlTree_Regular(q_tree);
+	    q_tree = comp_q_tree;
+	  }
+	  tmp_tree = q_tree;
+	  q_tree = SynthCheckAndMakeComplement(dd, table, q_tree, &comp_flag,
+					       verbosity);
+	  if (!q_tree) {
+	    bdd_recursive_deref_zdd(dd, q);
+	    return(NULL);
+	  } else if (q_tree == tmp_tree) {
+	    if (q_ref == 0)
+	      SynthPutMlTreeInList(dd, q_tree, 0);
+	  } else {
+	    if (comp_flag)
+	      comp_q_tree = q_tree;
+	    q_ref = 1;
+	  }
+	}
+	bdd_recursive_deref_zdd(dd, q);
+
+	if (bring) {
+	  tree = bring;
+	  tree->leaf = 0;
+	  tree->q = q_tree;
+	  tree->d = d_tree;
+	  tree->r = SynthFindOrCreateMlTree(table, dd, zero, 
+					    1, 0, &r_ref, verbosity);
+	  if (!tree->r)
+	    return(NULL);
+	  if (MlTree_IsComplement(tree->r)) {
+	    tree->r = MlTree_Regular(tree->r);
+	    tree->r_comp = 1;
+	  }
+	  if (comp_q_tree)
+	    tree->q_comp = 1;
+	  if (comp_d_flag)
+	    tree->d_comp = 1;
+	  tree->q_ref = q_ref;
+	  tree->d_ref = d_ref;
+	  tree->r_ref = r_ref;
+	  if (verbosity > 1)
+	    SynthPrintMlTreeMessage(dd, tree, message);
+	  if (VerifyTreeMode) {
+	    SynthVerifyTree(dd, tree, 0);
+	    SynthVerifyMlTable(dd, table);
+	  }
+	  return(tree);
+	}
+
+	tree = SynthFindOrCreateMlTree(table, dd, f, 0, 0, ref, verbosity);
+	if (!tree)
+	  return(NULL);
+	if (*ref)
+	  (void) fprintf(vis_stdout,
+			 "** synth warning: May be duplicate.\n");
+	tree->q = q_tree;
+	tree->d = d_tree;
+	tree->r = SynthFindOrCreateMlTree(table, dd, zero, 1, 
+					  0, &r_ref, verbosity);
+	if (!tree->r)
+	  return(NULL);
+	if (MlTree_IsComplement(tree->r)) {
+	  tree->r = MlTree_Regular(tree->r);
+	  tree->r_comp = 1;
+	}
+	if (comp_q_tree)
+	  tree->q_comp = 1;
+	if (comp_d_flag)
+	  tree->d_comp = 1;
+	tree->q_ref = q_ref;
+	tree->d_ref = d_ref;
+	tree->r_ref = r_ref;
+	if (verbosity > 1)
+	  SynthPrintMlTreeMessage(dd, tree, message);
+	SynthPutMlTreeInList(dd, tree, 0);
+	if (VerifyTreeMode) {
+	  SynthVerifyTree(dd, tree, 0);
+	  SynthVerifyMlTable(dd, table);
+	}
+	return(tree);
+      }
+    } else
+      bdd_recursive_deref_zdd(dd, d);
+
+    tree = LiteralFactoringTree(dd, table, f, q, level + 1, ref, 
+				bring, verbosity);
+    if (!tree) {
+      bdd_recursive_deref_zdd(dd, q);
+      return(NULL);
+    }
+    tmp_tree = tree;
+    tree = SynthCheckAndMakeComplement(dd, table, tree, &comp_flag, verbosity);
+    if (!tree) {
+      bdd_recursive_deref_zdd(dd, q);
+      return(NULL);
+    } else if (tree != tmp_tree) {
+      *ref = 1;
+      if (comp_flag)
+	tree = MlTree_Not(tree);
+    }
+    bdd_recursive_deref_zdd(dd, q);
+
+    if (verbosity > 1)
+      SynthPrintMlTreeMessage(dd, tree, message);
+    return(tree);
+  }
+  bdd_recursive_deref_zdd(dd, d);
+
+  d_tree = comp_d_tree = (MlTree *)NULL;
+
+  tmp = q;
+  q = SynthMakeCubeFree(dd, q);
+  if (!q) {
+    bdd_recursive_deref_zdd(dd,tmp);
+    return(NULL);
+  }
+  bdd_ref(q);
+  bdd_recursive_deref_zdd(dd,tmp);
+
+  q_tree = (MlTree *)NULL;
+  if (st_lookup(table, (char *)q, &q_tree)) {
+    SynthSetSharedFlag(dd, q_tree);
+    if (MlTree_Regular(q_tree)->candidate) {
+      if (!SynthUseCandidate(table, dd, q_tree, verbosity)) {
+	bdd_recursive_deref_zdd(dd, q);
+	return(NULL);
+      }
+    }
+    if (MlTree_IsComplement(q_tree)) {
+      q_tree = MlTree_Regular(q_tree);
+      comp_q_tree = q_tree;
+      q_tree = (MlTree *)NULL;
+    }
+  }
+
+  d = (* SynthGetZddDivideFunc())(dd, f, q);
+  if (!d) {
+    bdd_recursive_deref_zdd(dd, q);
+    return(NULL);
+  }
+  bdd_ref(d);
+  d_tree = (MlTree *)NULL;
+  if (st_lookup(table, (char *)d, &d_tree)) {
+    SynthSetSharedFlag(dd, d_tree);
+    if (MlTree_Regular(d_tree)->candidate) {
+      if (!SynthUseCandidate(table, dd, d_tree, verbosity)) {
+	bdd_recursive_deref_zdd(dd, d);
+	bdd_recursive_deref_zdd(dd, q);
+	return(NULL);
+      }
+    }
+    if (MlTree_IsComplement(d_tree)) {
+      d_tree = MlTree_Regular(d_tree);
+      comp_d_tree = d_tree;
+      d_tree = (MlTree *)NULL;
+    }
+  }
+
+  m = (* SynthGetZddProductFunc())(dd, d, q);
+  if (!m) {
+    bdd_recursive_deref_zdd(dd, d);
+    bdd_recursive_deref_zdd(dd, q);
+    return(NULL);
+  }
+  bdd_ref(m);
+  r = bdd_zdd_diff(dd, f, m);
+  if (!r) {
+    bdd_recursive_deref_zdd(dd, d);
+    bdd_recursive_deref_zdd(dd, q);
+    bdd_recursive_deref_zdd(dd, m);
+    return(NULL);
+  }
+  bdd_ref(r);
+
+  r_tree = (MlTree *)NULL;
+  if (st_lookup(table, (char *)r, &r_tree)) {
+    SynthSetSharedFlag(dd, r_tree);
+    if (MlTree_Regular(r_tree)->candidate) {
+      if (!SynthUseCandidate(table, dd, r_tree, verbosity)) {
+	bdd_recursive_deref_zdd(dd, d);
+	bdd_recursive_deref_zdd(dd, q);
+	bdd_recursive_deref_zdd(dd, m);
+	bdd_recursive_deref_zdd(dd, r);
+	return(NULL);
+      }
+    }
+    if (MlTree_IsComplement(r_tree)) {
+      r_tree = MlTree_Regular(r_tree);
+      comp_r_tree = r_tree;
+      r_tree = (MlTree *)NULL;
+    }
+  }
+
+  if (IsCubeFree(dd, d)) {
+    tree = SynthFactorTreeRecur(dd, table, SynthGenericFactorTree,
+				f, q, d, r, m, q_tree, d_tree, r_tree,
+				comp_q_tree, comp_d_tree, comp_r_tree,
+				bring, level, space, message, ref, verbosity);
+    bdd_recursive_deref_zdd(dd, d);
+    bdd_recursive_deref_zdd(dd, q);
+    bdd_recursive_deref_zdd(dd, m);
+    bdd_recursive_deref_zdd(dd, r);
+    return(tree);
+  }
+
+  bdd_recursive_deref_zdd(dd, q);
+  bdd_recursive_deref_zdd(dd, r);
+
+  c = CommonCube(dd, d);
+  if (!c) {
+    bdd_recursive_deref_zdd(dd, d);
+    return(NULL);
+  }
+  bdd_ref(c);
+  bdd_recursive_deref_zdd(dd, d);
+  tree = LiteralFactoringTree(dd, table, f, c, level + 1,
+			      ref, bring, verbosity);
+  if (!tree) {
+    bdd_recursive_deref_zdd(dd, c);
+    return(NULL);
+  }
+  tmp_tree = tree;
+  tree = SynthCheckAndMakeComplement(dd, table, tree, &comp_flag, verbosity);
+  if (!tree) {
+    bdd_recursive_deref_zdd(dd, c);
+    if (*ref == 0)
+      SynthFreeMlTree(MlTree_Regular(tree), 1);
+    return(NULL);
+  } else if (tree != tmp_tree) {
+    *ref = 1;
+    if (comp_flag)
+      tree = MlTree_Not(tree);
+  }
+  bdd_recursive_deref_zdd(dd, c);
+
+  if (verbosity > 1)
+    SynthPrintMlTreeMessage(dd, tree, message);
+  if (VerifyTreeMode) {
+    SynthVerifyTree(dd, tree, 0);
+    SynthVerifyMlTable(dd, table);
+  }
+  return(tree);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Makes a node cube-free.]
+
+  Description [Makes a node cube-free. Eliminates the literals that appear
+  in all the cubes.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+bdd_node *
+SynthMakeCubeFree(bdd_manager *dd,
+		  bdd_node *f)
+{
+  int		i, v;
+  int		nvars, max_count, max_pos = 0;
+  int		*count;
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  bdd_node	*divisor, *node;
+  bdd_node	*tmp1, *tmp2;
+  int		ncubes;
+
+  if (f == one || f == zero)
+    return(f);
+
+  /* Compare the number of occurrences of each literal to the number of
+   * cubes in the cover. If no literal appears more than once, or if no
+   * literal appears in all cubes, f is already cube-free.
+   */
+  ncubes = bdd_zdd_count(dd, f);
+  v = -1;
+  max_count = 1;
+  nvars = bdd_num_zdd_vars(dd);
+  count = ALLOC(int, nvars);
+  (void)memset((void *)count, 0, sizeof(int) * nvars);
+  SynthCountLiteralOccurrence(dd, f, count);
+  for (i = 0; i < nvars; i++) {
+    if (count[i] > max_count) {
+      v = i;
+      max_count = count[i];
+      max_pos = i;
+    }
+  }
+  if (v == -1 || max_count < ncubes) {
+    FREE(count);
+    return(f);
+  }
+
+  /* Divide the cover by the first literal appearing in all cubes. */
+  node = bdd_zdd_get_node(dd, v, one, zero);
+  if (!node) {
+    FREE(count);
+    return(NULL);
+  }
+  bdd_ref(node);
+  divisor = (* SynthGetZddDivideFunc())(dd, f, node);
+  if (!divisor) {
+    bdd_recursive_deref_zdd(dd, node);
+    FREE(count);
+    return(NULL);
+  }
+  bdd_ref(divisor);
+  bdd_recursive_deref_zdd(dd, node);
+
+  /* Divide the cover by the remaining literals appearing in all cubes. */
+  for (i = max_pos + 1; i < nvars; i++) {
+    if (count[i] == max_count) {
+      tmp1 = divisor;
+      tmp2 = bdd_zdd_get_node(dd, i, one, zero);
+      if (!tmp2) {
+	FREE(count);
+	bdd_recursive_deref_zdd(dd, tmp1);
+	return(NULL);
+      }
+      bdd_ref(tmp2);
+      divisor = (* SynthGetZddDivideFunc())(dd, divisor, tmp2);
+      if (!divisor) {
+	FREE(count);
+	bdd_recursive_deref_zdd(dd, tmp1);
+	bdd_recursive_deref_zdd(dd, tmp2);
+	return(NULL);
+      }
+      bdd_ref(divisor);
+      bdd_recursive_deref_zdd(dd, tmp1);
+      bdd_recursive_deref_zdd(dd, tmp2);
+    }
+  }
+  FREE(count);
+  bdd_deref(divisor);
+  return(divisor);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Factorizes a node using literal factoring.]
+
+  Description [Factorizes a node using literal factoring.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static MlTree *
+LiteralFactoringTree(bdd_manager *dd,
+		     st_table *table,
+		     bdd_node *f,
+		     bdd_node *c,
+		     int level,
+		     int *ref,
+		     MlTree *bring,
+		     int verbosity)
+{
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  bdd_node	*l, *q, *r;
+  bdd_node	*m;
+  char		message[80];
+  char		space[80];
+  MlTree	*tree, *q_tree, *d_tree, *r_tree;
+  int		q_ref, d_ref, r_ref, m_ref;
+  char		comp_mess[120];
+  MlTree	*comp_q_tree = (MlTree *)NULL;
+  MlTree	*comp_d_tree = (MlTree *)NULL;
+  MlTree	*comp_r_tree = (MlTree *)NULL;
+  MlTree	*m_tree;
+  int		q_tree_exist, r_tree_exist;
+  MlTree	*tmp_tree;
+  int		comp_flag;
+
+  if (verbosity > 1) {
+    SynthGetSpaceString(space, level * 2, 80);
+    sprintf(message, "%s[%d] in : ", space, level);
+    SynthPrintZddTreeMessage(dd, f, message);
+    sprintf(message, "%s[%d]out : ", space, level);
+  }
+
+  l = BestLiteral(dd, f, c);
+  if (!l)
+    return(NULL);
+  bdd_ref(l);
+  d_tree = (MlTree *)NULL;
+  if (st_lookup(table, (char *)l, &d_tree)) {
+    SynthSetSharedFlag(dd, d_tree);
+    if (MlTree_Regular(d_tree)->candidate) {
+      if (!SynthUseCandidate(table, dd, d_tree, verbosity)) {
+	bdd_recursive_deref_zdd(dd, l);
+	return(NULL);
+      }
+    }
+    if (MlTree_IsComplement(d_tree)) {
+      d_tree = MlTree_Regular(d_tree);
+      comp_d_tree = d_tree;
+      d_tree = (MlTree *)NULL;
+    }
+  }
+  q = (* SynthGetZddDivideFunc())(dd, f, l);
+  if (!q) {
+    bdd_recursive_deref_zdd(dd, l);
+    return(NULL);
+  }
+  bdd_ref(q);
+  q_tree = (MlTree *)NULL;
+  if (st_lookup(table, (char *)q, &q_tree)) {
+    SynthSetSharedFlag(dd, q_tree);
+    if (MlTree_Regular(q_tree)->candidate) {
+      if (!SynthUseCandidate(table, dd, q_tree, verbosity)) {
+	bdd_recursive_deref_zdd(dd, l);
+	bdd_recursive_deref_zdd(dd, q);
+	return(NULL);
+      }
+    }
+    if (MlTree_IsComplement(q_tree)) {
+      q_tree = MlTree_Regular(q_tree);
+      comp_q_tree = q_tree;
+      q_tree = (MlTree *)NULL;
+    }
+  }
+
+  m = (* SynthGetZddProductFunc())(dd, l, q);
+  if (!m) {
+    bdd_recursive_deref_zdd(dd, l);
+    bdd_recursive_deref_zdd(dd, q);
+    return(NULL);
+  }
+  bdd_ref(m);
+  r = bdd_zdd_diff(dd, f, m);
+  if (!r) {
+    bdd_recursive_deref_zdd(dd, l);
+    bdd_recursive_deref_zdd(dd, q);
+    bdd_recursive_deref_zdd(dd, m);
+    return(NULL);
+  }
+  bdd_ref(r);
+
+  r_tree = (MlTree *)NULL;
+  if (st_lookup(table, (char *)r, &r_tree)) {
+    SynthSetSharedFlag(dd, r_tree);
+    if (MlTree_Regular(r_tree)->candidate) {
+      if (!SynthUseCandidate(table, dd, r_tree, verbosity)) {
+	bdd_recursive_deref_zdd(dd, l);
+	bdd_recursive_deref_zdd(dd, q);
+	bdd_recursive_deref_zdd(dd, m);
+	bdd_recursive_deref_zdd(dd, r);
+	return(NULL);
+      }
+    }
+    if (MlTree_IsComplement(r_tree)) {
+      r_tree = MlTree_Regular(r_tree);
+      comp_r_tree = r_tree;
+      r_tree = (MlTree *)NULL;
+    }
+  }
+
+  if (verbosity > 1)
+    (void) fprintf(vis_stdout,"%s[%d] quotient\n",
+		   space, level);
+  q_tree_exist = 0;
+  if (q_tree) {
+    q_ref = 1;
+    q_tree_exist = 1;
+  } else if (comp_q_tree) {
+    q_tree = comp_q_tree;
+    q_ref = 1;
+    if (verbosity > 1) {
+      sprintf(comp_mess, "%s\t(C) : ", space);
+      SynthPrintZddTreeMessage(dd, q, comp_mess);
+    }
+  } else {
+    q_tree = SynthGenericFactorTree(dd, table, q, level + 1, &q_ref,
+				    NULL, 0, NULL, verbosity);
+    if (!q_tree) {
+      bdd_recursive_deref_zdd(dd, l);
+      bdd_recursive_deref_zdd(dd, q);
+      bdd_recursive_deref_zdd(dd, m);
+      bdd_recursive_deref_zdd(dd, r);
+      return(NULL);
+    }
+    if (MlTree_IsComplement(q_tree)) {
+      q_tree = MlTree_Regular(q_tree);
+      comp_q_tree = q_tree;
+    } else
+      bdd_ref(q_tree->node);
+  }
+  tmp_tree = q_tree;
+  q_tree = SynthCheckAndMakeComplement(dd, table, q_tree, &comp_flag,
+				       verbosity);
+  if (!q_tree) {
+    bdd_recursive_deref_zdd(dd, l);
+    bdd_recursive_deref_zdd(dd, q);
+    bdd_recursive_deref_zdd(dd, m);
+    bdd_recursive_deref_zdd(dd, r);
+    if (comp_q_tree != q_tree)
+      bdd_recursive_deref_zdd(dd, tmp_tree->node);
+    if (q_ref == 0)
+      SynthFreeMlTree(MlTree_Regular(tmp_tree), 1);
+    return(NULL);
+  }
+  if (q_tree != tmp_tree) {
+    if (comp_flag)
+      comp_q_tree = q_tree;
+    q_ref = 1;
+  }
+
+  if (verbosity > 1)
+    (void) fprintf(vis_stdout,"%s[%d] literal\n", space, level);
+  if (d_tree) {
+    d_ref = 1;
+    if (verbosity > 1) {
+      sprintf(comp_mess, "%s\t(R) : ", space);
+      SynthPrintZddTreeMessage(dd, l, comp_mess);
+    }
+  } else if (comp_d_tree) {
+    d_tree = comp_d_tree;
+    d_ref = 1;
+    if (verbosity > 1) {
+      sprintf(comp_mess, "%s\t(C) : ", space);
+      SynthPrintZddTreeMessage(dd, l, comp_mess);
+    }
+  } else {
+    d_tree = SynthFindOrCreateMlTree(table, dd, l, 1, 0, &d_ref, verbosity);
+    if (!d_tree) {
+      bdd_recursive_deref_zdd(dd, l);
+      bdd_recursive_deref_zdd(dd, q);
+      bdd_recursive_deref_zdd(dd, m);
+      bdd_recursive_deref_zdd(dd, r);
+      if (comp_q_tree != q_tree)
+	bdd_recursive_deref_zdd(dd, q_tree->node);
+      if (q_ref == 0)
+	SynthFreeMlTree(MlTree_Regular(q_tree), 1);
+      return(NULL);
+    }
+    if (MlTree_IsComplement(d_tree)) {
+      comp_d_tree = MlTree_Regular(d_tree);
+      d_tree = comp_d_tree;
+    }
+    if (verbosity > 1) {
+      sprintf(comp_mess, "%s\t : ", space);
+      SynthPrintZddTreeMessage(dd, l, comp_mess);
+    }
+    tmp_tree = d_tree;
+    d_tree = SynthCheckAndMakeComplement(dd, table, d_tree, &comp_flag,
+					 verbosity);
+    if (!d_tree) {
+      bdd_recursive_deref_zdd(dd, l);
+      bdd_recursive_deref_zdd(dd, q);
+      bdd_recursive_deref_zdd(dd, m);
+      bdd_recursive_deref_zdd(dd, r);
+      if (comp_q_tree != q_tree)
+	bdd_recursive_deref_zdd(dd, q_tree->node);
+      if (q_ref == 0)
+	SynthFreeMlTree(MlTree_Regular(q_tree), 1);
+      if (d_ref == 0)
+	SynthFreeMlTree(MlTree_Regular(d_tree), 1);
+      return(NULL);
+    } else if (d_tree == tmp_tree) {
+      if (d_ref == 0)
+	SynthPutMlTreeInList(dd, d_tree, 0);
+    } else {
+      if (comp_flag)
+	comp_d_tree = d_tree;
+      d_ref = 1;
+    }
+  }
+
+  m_tree = (MlTree *)NULL;
+  m_ref = 0;
+  if (UseMtree && m != f) {
+    m_tree = SynthFindOrCreateMlTree(table, dd, m, 0, 1, &m_ref, verbosity);
+    if (!m_tree) {
+      bdd_recursive_deref_zdd(dd, l);
+      bdd_recursive_deref_zdd(dd, q);
+      bdd_recursive_deref_zdd(dd, m);
+      bdd_recursive_deref_zdd(dd, r);
+      if (comp_q_tree != q_tree)
+	bdd_recursive_deref_zdd(dd, q_tree->node);
+      if (q_ref == 0)
+	SynthFreeMlTree(MlTree_Regular(q_tree), 1);
+      if (d_ref == 0)
+	SynthFreeMlTree(MlTree_Regular(d_tree), 1);
+      return(NULL);
+    }
+    if (m_ref == 0) {
+      m_tree->q = q_tree;
+      m_tree->d = d_tree;
+      m_tree->r = (MlTree *)NULL;
+      if (comp_q_tree)
+	m_tree->q_comp = 1;
+      if (comp_d_tree)
+	m_tree->d_comp = 1;
+      m_tree->q_ref = q_ref;
+      m_tree->d_ref = d_ref;
+      m_tree->r_ref = 0;
+
+      tmp_tree = m_tree;
+      m_tree = SynthCheckAndMakeComplement(dd, table, m_tree, &comp_flag,
+					   verbosity);
+      if (!m_tree) {
+	bdd_recursive_deref_zdd(dd, l);
+	bdd_recursive_deref_zdd(dd, q);
+	bdd_recursive_deref_zdd(dd, m);
+	bdd_recursive_deref_zdd(dd, r);
+	if (comp_q_tree != q_tree)
+	  bdd_recursive_deref_zdd(dd, q_tree->node);
+	if (q_ref == 0)
+	  SynthFreeMlTree(MlTree_Regular(q_tree), 1);
+	if (d_ref == 0)
+	  SynthFreeMlTree(MlTree_Regular(d_tree), 1);
+	return(NULL);
+      } else if (m_tree == tmp_tree)
+	SynthPutMlTreeInList(dd, m_tree, 1);
+      else {
+	if (m_tree->candidate)
+	  SynthPutMlTreeInList(dd, m_tree, 1);
+	else
+	  m_tree = NIL(MlTree);
+      }
+      if (m_tree && VerifyTreeMode) {
+	SynthVerifyTree(dd, m_tree, 0);
+	SynthVerifyMlTable(dd, table);
+      }
+    }
+  }
+  bdd_recursive_deref_zdd(dd, m);
+
+  if (verbosity > 1)
+    (void) fprintf(vis_stdout, "%s[%d] remainder\n", space, level);
+  r_tree_exist = 0;
+  if (r_tree) {
+    r_ref = 1;
+    r_tree_exist = 1;
+  } else if (comp_r_tree) {
+    r_tree = comp_r_tree;
+    r_ref = 1;
+    if (verbosity > 1) {
+      sprintf(comp_mess, "%s\t(C) : ", space);
+      SynthPrintZddTreeMessage(dd, r, comp_mess);
+    }
+  } else if (comp_d_tree) {
+    r_tree = SynthGenericFactorTree(dd, table, r, level + 1, &r_ref,
+				    NULL, 0, NULL, verbosity);
+    if (!r_tree) {
+      bdd_recursive_deref_zdd(dd, l);
+      bdd_recursive_deref_zdd(dd, q);
+      bdd_recursive_deref_zdd(dd, r);
+      if (comp_q_tree != q_tree)
+	bdd_recursive_deref_zdd(dd, q_tree->node);
+      if (q_ref == 0)
+	SynthFreeMlTree(MlTree_Regular(q_tree), 1);
+      if (d_ref == 0)
+	SynthFreeMlTree(MlTree_Regular(d_tree), 1);
+      if (m_tree && m_ref == 0)
+	SynthFreeMlTree(MlTree_Regular(m_tree), 1);
+      return(NULL);
+    }
+    if (MlTree_IsComplement(r_tree)) {
+      r_tree = MlTree_Regular(r_tree);
+      comp_r_tree = r_tree;
+    } else
+      bdd_ref(r_tree->node);
+  } else {
+    if (Resubstitution) {
+      r_tree = SynthGenericFactorTree(dd, table, r, level + 1, 
+				      &r_ref, d_tree, 1, NULL, verbosity);
+      if (!r_tree && (bdd_read_reordered_field(dd) || noMemoryFlag)) {
+	bdd_recursive_deref_zdd(dd, l);
+	bdd_recursive_deref_zdd(dd, q);
+	bdd_recursive_deref_zdd(dd, r);
+	if (comp_q_tree != q_tree)
+	  bdd_recursive_deref_zdd(dd, q_tree->node);
+	if (q_ref == 0)
+	  SynthFreeMlTree(MlTree_Regular(q_tree), 1);
+	if (d_ref == 0)
+	  SynthFreeMlTree(MlTree_Regular(d_tree), 1);
+	if (m_tree && m_ref == 0)
+	  SynthFreeMlTree(MlTree_Regular(m_tree), 1);
+	return(NULL);
+      }
+    }
+    if (!r_tree) {
+      r_tree = SynthGenericFactorTree(dd, table, r, level + 1, 
+				      &r_ref, NULL, 0, NULL, verbosity);
+      if (!r_tree) {
+	bdd_recursive_deref_zdd(dd, l);
+	bdd_recursive_deref_zdd(dd, q);
+	bdd_recursive_deref_zdd(dd, r);
+	if (comp_q_tree != q_tree)
+	  bdd_recursive_deref_zdd(dd, q_tree->node);
+	if (q_ref == 0)
+	  SynthFreeMlTree(MlTree_Regular(q_tree), 1);
+	if (d_ref == 0)
+	  SynthFreeMlTree(MlTree_Regular(d_tree), 1);
+	if (m_tree && m_ref == 0)
+	  SynthFreeMlTree(MlTree_Regular(m_tree), 1);
+	return(NULL);
+      }
+    } else {
+      if (r != one && r != zero)
+	SynthSetSharedFlag(dd, d_tree);
+    }
+    if (MlTree_IsComplement(r_tree)) {
+      r_tree = MlTree_Regular(r_tree);
+      comp_r_tree = r_tree;
+    } else
+      bdd_ref(r_tree->node);
+  }
+  if (RemainderComplement) {
+    tmp_tree = r_tree;
+    r_tree = SynthCheckAndMakeComplement(dd, table, r_tree, &comp_flag,
+					 verbosity);
+    if (!r_tree) {
+      bdd_recursive_deref_zdd(dd, l);
+      bdd_recursive_deref_zdd(dd, q);
+      bdd_recursive_deref_zdd(dd, r);
+      if (comp_q_tree != q_tree)
+	bdd_recursive_deref_zdd(dd, q_tree->node);
+      if (comp_r_tree != r_tree)
+	bdd_recursive_deref_zdd(dd, r_tree->node);
+      if (q_ref == 0)
+	SynthFreeMlTree(MlTree_Regular(q_tree), 1);
+      if (d_ref == 0)
+	SynthFreeMlTree(MlTree_Regular(d_tree), 1);
+      if (r_ref == 0)
+	SynthFreeMlTree(MlTree_Regular(r_tree), 1);
+      if (m_tree && m_ref == 0)
+	SynthFreeMlTree(MlTree_Regular(m_tree), 1);
+      return(NULL);
+    }
+    if (r_tree != tmp_tree) {
+      if (comp_flag)
+	comp_r_tree = r_tree;
+      r_ref = 1;
+    }
+  }
+
+  bdd_recursive_deref_zdd(dd, l);
+  bdd_recursive_deref_zdd(dd, q);
+  bdd_recursive_deref_zdd(dd, r);
+  if ((!q_tree_exist) && (!comp_q_tree))
+    bdd_recursive_deref_zdd(dd, q_tree->node);
+  if ((!r_tree_exist) && (!comp_r_tree))
+    bdd_recursive_deref_zdd(dd, r_tree->node);
+
+  if (bring) {
+    tree = bring;
+    tree->leaf = 0;
+    tree->q = q_tree;
+    tree->d = d_tree;
+    tree->r = r_tree;
+    if (comp_q_tree)
+      tree->q_comp = 1;
+    if (comp_d_tree)
+      tree->d_comp = 1;
+    if (comp_r_tree)
+      tree->r_comp = 1;
+    tree->q_ref = q_ref;
+    tree->d_ref = d_ref;
+    tree->r_ref = r_ref;
+    if (UseMtree && m_tree && m_ref == 0) {
+      MlTree_Regular(m_tree)->r = tree;
+      if (m_tree->r->id == 0) {
+	assert(0);
+	/*
+	if (!SynthUseCandidate(table, dd, m_tree, verbosity)) {
+	  SynthFreeMlTree(MlTree_Regular(m_tree), 1);
+	  return(NULL);
+	}
+	*/
+      }
+    }
+    if (verbosity > 1)
+      SynthPrintMlTreeMessage(dd, tree, message);
+    if (VerifyTreeMode) {
+      SynthVerifyTree(dd, tree, 0);
+      SynthVerifyMlTable(dd, table);
+    }
+    return(tree);
+  }
+
+  tree = SynthFindOrCreateMlTree(table, dd, f, 0, 0, ref, verbosity);
+  if (!tree) {
+    if (q_ref == 0)
+      SynthFreeMlTree(MlTree_Regular(q_tree), 1);
+    if (d_ref == 0)
+      SynthFreeMlTree(MlTree_Regular(d_tree), 1);
+    if (r_ref == 0)
+      SynthFreeMlTree(MlTree_Regular(r_tree), 1);
+    if (m_tree && m_ref == 0)
+      SynthFreeMlTree(MlTree_Regular(m_tree), 1);
+    return(NULL);
+  }
+  if (*ref == 1)
+    (void) fprintf(vis_stdout, "** synth warning: May be duplicate.\n");
+  tree->q = q_tree;
+  tree->d = d_tree;
+  tree->r = r_tree;
+  if (comp_q_tree)
+    tree->q_comp = 1;
+  if (comp_d_tree)
+    tree->d_comp = 1;
+  if (comp_r_tree)
+    tree->r_comp = 1;
+  tree->q_ref = q_ref;
+  tree->d_ref = d_ref;
+  tree->r_ref = r_ref;
+  if (UseMtree && m_tree && m_ref == 0) {
+    MlTree_Regular(m_tree)->r = tree;
+    if (m_tree->r->id == 0) {
+      assert(0);
+      /*
+      if (!SynthUseCandidate(table, dd, m_tree, verbosity)) {
+	SynthFreeMlTree(MlTree_Regular(tree), 1);
+	SynthFreeMlTree(MlTree_Regular(m_tree), 1);
+	return(NULL);
+      }
+      */
+    }
+  }
+  if (verbosity > 1)
+    SynthPrintMlTreeMessage(dd, tree, message);
+  SynthPutMlTreeInList(dd, tree, 0);
+  if (VerifyTreeMode) {
+    SynthVerifyTree(dd, tree, 0);
+    SynthVerifyMlTable(dd, table);
+  }
+  return(tree);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Selects a literal which occurs in the largest number of
+  cubes.]
+
+  Description [Selects a literal which occurs in the largest number of
+  cubes.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static bdd_node *
+BestLiteral(bdd_manager *dd,
+	    bdd_node *f,
+	    bdd_node *c)
+{
+  int		i, v;
+  int		nvars, max_count;
+  int		*count_f, *count_c;
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  bdd_node	*node;
+
+  v = -1;
+  max_count = 0;
+  nvars = bdd_num_zdd_vars(dd);
+  count_f = ALLOC(int, nvars);
+  (void)memset((void *)count_f, 0, sizeof(int) * nvars);
+  SynthCountLiteralOccurrence(dd, f, count_f);
+  count_c = ALLOC(int, nvars);
+  (void)memset((void *)count_c, 0, sizeof(int) * nvars);
+  SynthCountLiteralOccurrence(dd, c, count_c);
+
+  for (i = 0; i < nvars; i++) {
+    if (count_c[i]) {
+      if (count_f[i] > max_count) {
+	v = i;
+	max_count = count_f[i];
+      }
+    }
+  }
+
+  if (v == -1) {
+    FREE(count_f);
+    FREE(count_c);
+    return(zero);
+  }
+
+  node = bdd_zdd_get_node(dd, v, one, zero);
+  if (!node) {
+    FREE(count_f);
+    FREE(count_c);
+    return(NULL);
+  }
+  FREE(count_f);
+  FREE(count_c);
+  return(node);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Checks if a node is cube-free.]
+
+  Description [Checks if a node is cube-free.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+IsCubeFree(bdd_manager *dd,
+	   bdd_node *f)
+{
+  int		i, v;
+  int		nvars, max_count;
+  int		*count;
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  int		ncubes;
+
+  if (f == one || f == zero)
+    return(1);
+
+  ncubes = bdd_zdd_count(dd, f);
+  v = -1;
+  max_count = 1;
+  nvars = bdd_num_zdd_vars(dd);
+  count = ALLOC(int, nvars);
+  (void)memset((void *)count, 0, sizeof(int) * nvars);
+  SynthCountLiteralOccurrence(dd, f, count);
+  for (i = 0; i < nvars; i++) {
+    if (count[i] > max_count) {
+      v = i;
+      max_count = count[i];
+    }
+  }
+  FREE(count);
+
+  if (v == -1 || max_count < ncubes)
+    return(1);
+
+  return(0);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Returns the largest common cube.]
+
+  Description [Returns the largest common cube.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static bdd_node *
+CommonCube(bdd_manager *dd,
+	   bdd_node *f)
+{
+  int		i, v;
+  int		nvars, max_count, max_pos = 0;
+  int		*count;
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  bdd_node	*node;
+  bdd_node	*tmp1, *tmp2;
+  int		ncubes;
+
+  if (f == one || f == zero) {
+    return(f);
+  }
+
+  ncubes = bdd_zdd_count(dd, f);
+  v = -1;
+  max_count = 1;
+  nvars = bdd_num_zdd_vars(dd);
+  count = ALLOC(int, nvars);
+  (void)memset((void *)count, 0, sizeof(int) * nvars);
+  SynthCountLiteralOccurrence(dd, f, count);
+  for (i = 0; i < nvars; i++) {
+    if (count[i] > max_count) {
+      v = i;
+      max_count = count[i];
+      max_pos = i;
+    }
+  }
+  if (v == -1 || max_count < ncubes) {
+    FREE(count);
+    return(zero);
+  }
+
+  node = bdd_zdd_get_node(dd, v, one, zero);
+  if (!node) {
+    FREE(count);
+    return(NULL);
+  }
+  bdd_ref(node);
+  for (i = max_pos + 1; i < nvars; i++) {
+    if (count[i] == max_count) {
+      tmp1 = node;
+      tmp2 = bdd_zdd_get_node(dd, i, one, zero);
+      if (!tmp2) {
+	FREE(count);
+	bdd_recursive_deref_zdd(dd, tmp1);
+	return(NULL);
+      }
+      bdd_ref(tmp2);
+      node = (* SynthGetZddProductFunc())(dd, node, tmp2);
+      if (!node) {
+	FREE(count);
+	bdd_recursive_deref_zdd(dd, tmp1);
+	bdd_recursive_deref_zdd(dd, tmp2);
+	return(NULL);
+      }
+      bdd_ref(node);
+      bdd_recursive_deref_zdd(dd, tmp1);
+      bdd_recursive_deref_zdd(dd, tmp2);
+    }
+  }
+  FREE(count);
+  bdd_deref(node);
+  return(node);
+}
Index: vis_dev/vis-2.3/src/synth/synthInt.h
===================================================================
--- vis_dev/vis-2.3/src/synth/synthInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/synth/synthInt.h	(revision 14)
@@ -0,0 +1,224 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [synthInt.h]
+
+  PackageName [synth]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [In-Ho Moon, Balakrishna Kumthekar]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+  Revision    [$Id: synthInt.h,v 1.36 2005/05/13 08:47:48 hhhan Exp $]
+
+******************************************************************************/
+
+#ifndef _SYNTHINT
+#define _SYNTHINT
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "synth.h"
+#include "ntm.h"
+#include "ntk.h"
+#include "ord.h"
+#include <string.h>
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [Structure holding the synthesis command options.]
+
+  Description [Structure holding the synthesis command options.]
+
+  SeeAlso     []
+
+******************************************************************************/
+struct SynthInfoDataStruct {
+  int factoring; /* factoring method */
+  int divisor; /* divisor method */
+  int unreachDC; /* use unreachable states as don't cares */
+  int reordering; /* allow reordering in BDD and/or ZDD */
+  int trySharing; /* try to share more nodes */
+  int realign; /* allow realignment to ZDD/BDD after BDD/ZDD reordering */
+  char *filehead; /* output file name */
+  char *prefix; /* prefix of internal node names */
+  boolean eqn; /* if true, output synthesized circuit in equation format too */
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [Structure representing multi-level logic by quotient, divisor,
+  and remainder.]
+
+  Description [Structure representing multi-level logic by quotient,
+  divisor, and remainder. In spite of the name this is a graph
+  structure, not a tree.  Each node of the graph has 3 children:
+  quotient, divisor, and remainder. The purpose of the field
+  complement is to have both phases in a tree, so if the field 'comp'
+  is set to 1, then the field 'complement' is taken instead of the
+  field 'node'. When an output function is the same as either another
+  output function or the complement of another function, the tree of
+  the output function is made by copying the tree of the other
+  function, then the field 'ref' of this tree is set to 1. The fields
+  'q(d,r)_ref' tell each child tree was newly created or already
+  existing, and the fields 'q(d,r)_comp' tell whether each child tree
+  is complemented or not.  To increase sharing, every time a function
+  is factored, a tree representing quotient * divisor is made if the
+  tree does not exist, and the field 'candidate' of this tree is set
+  to 1.]
+
+  SeeAlso     []
+
+******************************************************************************/
+typedef	struct	ml_tree	{
+    bdd_node		*node; /* a ZDD */
+    bdd_node		*complement; /* complement ZDD of node */
+    struct ml_tree	*q; /* quotient */
+    struct ml_tree	*d; /* divisor */
+    struct ml_tree	*r; /* remainder */
+    unsigned int	*support; /* a set of support of node */
+    int			nLiterals; /* number of literals of this ml_tree */
+    unsigned short	id; /* id of this ml_tree */
+    unsigned 		leaf: 1; /* set to 1 when this ml_tree is leaf */
+    unsigned 		pi: 1; /* set to 1 if node is primary input */
+    unsigned 		ref: 1; /* set to 1 if this ml_tree is made by
+                                 * copying an existing tree */
+    unsigned 		q_ref: 1; /* set to 1 if q is already existing tree */
+    unsigned 		d_ref: 1; /* set to 1 if d is already existing tree */
+    unsigned 		r_ref: 1; /* set to 1 if r is already existing tree */
+    unsigned		top: 1; /* set to 1 if this ml_tree is a primary
+                                 * output or next state function */
+    unsigned		comp: 1; /* take complement of ml_tree if 1 */
+    unsigned 		q_comp: 1; /* take complement of q as quotient if 1 */
+    unsigned 		d_comp: 1; /* take complement of d as divisor if 1 */
+    unsigned 		r_comp: 1; /* take complement of r as remainder if 1 */
+    unsigned		shared: 1; /* set to 1 if this ml_tree has more than
+    				    * one assendent */
+    unsigned		candidate: 1;
+    unsigned 		flag: 1;
+    unsigned		dummy: 2;
+    struct ml_tree	*next;
+} MlTree;
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#define	MlTree_Not(tree)             ((MlTree *)((long)(tree) ^ 01))
+#define	MlTree_IsComplement(tree)    ((long)(tree) & 01)
+#define	MlTree_Regular(tree)         ((MlTree *)((long)(tree) & ~01))
+
+#define MAX_EQ_LEN	4096
+#define MAX_NAME_LEN	256
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN int SynthCountMlLiteral(bdd_manager *dd, MlTree *tree, int ref);
+EXTERN void SynthZddSupportStep(bdd_node *f, int *support);
+EXTERN void SynthZddClearFlag(bdd_node *f);
+EXTERN int SynthGetLiteralCount(bdd_manager *dd, bdd_node *node);
+EXTERN bdd_node	* SynthZddQuickDivisor(bdd_manager *dd, bdd_node *f);
+EXTERN bdd_node	* SynthZddLeastDivisor(bdd_manager *dd, bdd_node *f);
+EXTERN bdd_node	* SynthZddMostDivisor(bdd_manager *dd, bdd_node *f);
+EXTERN bdd_node	* SynthZddLevelZeroDivisor(bdd_manager *dd, bdd_node *f);
+EXTERN bdd_node	* SynthZddCommonDivisor(bdd_manager *dd, bdd_node *f);
+EXTERN bdd_node	* SynthZddLpDivisor(bdd_manager *dd, bdd_node *f);
+EXTERN void SynthCountLiteralOccurrence(bdd_manager *dd, bdd_node *f, int *count);
+EXTERN bdd_node * (* SynthGetZddProductFunc(void)) (bdd_manager *, bdd_node *, bdd_node *);
+EXTERN bdd_node * (* SynthGetZddProductRecurFunc(void)) (bdd_manager *, bdd_node *, bdd_node *);
+EXTERN bdd_node * (* SynthGetZddDivideFunc(void)) (bdd_manager *, bdd_node *, bdd_node *);
+EXTERN bdd_node * (* SynthGetZddDivideRecurFunc(void)) (bdd_manager *, bdd_node *, bdd_node *);
+EXTERN  void SynthSetZddDivisorFunc(int mode);
+EXTERN bdd_node * (* SynthGetZddDivisorFunc(void)) (bdd_manager *, bdd_node *);
+EXTERN void SynthGetSpaceString(char *string, int n, int max);
+EXTERN MlTree	* SynthLookupMlTable(st_table *table, bdd_manager *dd, bdd_node *node, int candidate, int verbosity);
+EXTERN int SynthUseCandidate(st_table *table, bdd_manager *dd, MlTree *m_tree, int verbosity);
+EXTERN MlTree	* SynthFindOrCreateMlTree(st_table *table, bdd_manager *dd, bdd_node *f, int leaf, int candidate, int *ref, int verbosity);
+EXTERN void SynthInitMlTable(void);
+EXTERN void SynthClearMlTable(bdd_manager *dd, st_table *table);
+EXTERN void SynthPutMlTreeInList(bdd_manager *dd, MlTree *tree, int candidate);
+EXTERN MlTree * SynthGetHeadTreeOfSize(int size);
+EXTERN int SynthGetSupportMask(bdd_manager *dd, bdd_node *node, unsigned int *mask);
+EXTERN int SynthGetSupportCount(bdd_manager *dd, bdd_node *node);
+EXTERN MlTree	* SynthCheckAndMakeComplement(bdd_manager *dd, st_table *table, MlTree *tree, int *comp_flag, int verbosity);
+EXTERN void SynthSetSharedFlag(bdd_manager *dd, MlTree *tree);
+EXTERN int SynthPostFactoring(bdd_manager *dd, st_table *table, MlTree *(* factoring_func)(bdd_manager *, st_table *, bdd_node *, int, int *, MlTree *, int, MlTree *, int), int verbosity);
+EXTERN void SynthUpdateRefOfParent(MlTree *top);
+EXTERN void SynthVerifyTree(bdd_manager *dd, MlTree *tree, int flag);
+EXTERN void SynthVerifyMlTable(bdd_manager *dd, st_table *table);
+EXTERN void SynthPrintTreeList(MlTree *list);
+EXTERN void SynthPrintLeafList(MlTree *list);
+EXTERN MlTree * SynthGenericFactorTree(bdd_manager *dd, st_table *table, bdd_node *f, int level, int *ref, MlTree *comp_d_tree, int comp_d_flag, MlTree *bring, int verbosity);
+EXTERN bdd_node	* SynthMakeCubeFree(bdd_manager *dd, bdd_node *f);
+EXTERN void SynthMultiLevelOptimize(Ntk_Network_t *network, bdd_node **combOutBdds, bdd_node **combUpperBdds, char **combOutNames, int *initStates, Synth_InfoData_t *synthInfo, int verbosity);
+EXTERN void SynthSetUseFuncDivisor(int mode);
+EXTERN void SynthSetOutputOrdering(int mode);
+EXTERN void SynthSetCostFactors(float supp, float prob);
+EXTERN void SynthSetSupportCount(int *count);
+EXTERN void SynthSetProbability(float *prob);
+EXTERN  int SynthFindDivisorForLowPower(int *count, int nvars, int min_count, int min_pos);
+EXTERN char * SynthGetIthOutputName(int i);
+EXTERN int SynthIsSubsetOfSupport(int size, unsigned int *mask1, unsigned int *mask2);
+EXTERN MlTree * SynthSimpleFactorTree(bdd_manager *dd, st_table *table, bdd_node *f, int level, int *ref, MlTree *comp_d_tree, int comp_d_flag, MlTree *bring, int verbosity);
+EXTERN bdd_node * SynthFindBiggerDivisorInList(bdd_manager *dd, st_table *table, bdd_node *f, bdd_node *d, int *found, int *comp_d_flag, MlTree **comp_d_tree, int verbosity);
+EXTERN MlTree * SynthGetFactorTreeWithCommonDivisor(bdd_manager *dd, st_table *table, MlTree *(* factoring_func)(bdd_manager *, st_table *, bdd_node *, int, int *, MlTree *, int, MlTree *, int), bdd_node *f, bdd_node *d, int level, int *ref, int verbosity);
+EXTERN MlTree * SynthPostFactorTree(bdd_manager *dd, st_table *table, bdd_node *f, bdd_node *q, bdd_node *d, MlTree *bring, MlTree *comp_d_tree, int comp_d_flag, char *message, int *ref, int verbosity);
+EXTERN MlTree * SynthFactorTreeRecur(bdd_manager *dd, st_table *table, MlTree *(* factoring_func)(bdd_manager *, st_table *, bdd_node *, int, int *, MlTree *, int, MlTree *, int), bdd_node *f, bdd_node *q, bdd_node *d, bdd_node *r, bdd_node *m, MlTree *q_tree, MlTree *d_tree, MlTree *r_tree, MlTree *comp_q_tree, MlTree *comp_d_tree, MlTree *comp_r_tree, MlTree *bring, int level, char *space, char *message, int *ref, int verbosity);
+EXTERN void SynthPrintZddTree(bdd_manager *dd, bdd_node *f);
+EXTERN void SynthPrintZddTreeMessage(bdd_manager *dd, bdd_node *f, char *mess);
+EXTERN void SynthPrintMlTreeMessage(bdd_manager *dd, MlTree *tree, char *mess);
+EXTERN void SynthFreeMlTree(MlTree *tree, int flag);
+EXTERN void SynthPrintMlTreeWithName(Ntk_Network_t *net, bdd_manager *dd, MlTree *tree, char *mess);
+EXTERN int SynthGetChildMlTreeWithName(Ntk_Network_t *net, bdd_manager *dd, MlTree *tree, char *eq);
+EXTERN int SynthGetChildTreeWithName(Ntk_Network_t *net, bdd_manager *dd, bdd_node *f, char *eq);
+EXTERN int SynthGetPrimaryNodeName(Ntk_Network_t *net, bdd_node *node, char *name);
+EXTERN void SynthGetPrimaryIndexName(Ntk_Network_t *net, int index, char *name);
+EXTERN void SynthPrintZddCoverWithName(Ntk_Network_t *net, bdd_manager *dd, bdd_node *node);
+EXTERN  void SynthMakeComplementString(char *eq);
+EXTERN  int SynthStringCompare(char **a, char **b);
+EXTERN  void SynthWriteBlifFile(Ntk_Network_t *net, bdd_manager *dd, MlTree **tree, char *filename, int no, bdd_node **ofuncs, int *initStates, int ml_mode, int verbosity);
+EXTERN void SynthWriteEqnHeader(FILE *fout, Ntk_Network_t *net, bdd_manager *dd);
+EXTERN void SynthWriteEqn(FILE *fout, Ntk_Network_t *net, bdd_manager *dd, MlTree *tree, bdd_node **ofuncs, char *func_name, int ref);
+EXTERN void SynthSetInternalNodePrefix(char *prefix);
+EXTERN void SynthSetupNodeNameTable(Ntk_Network_t *net);
+EXTERN void SynthFreeNodeNameTable(void);
+EXTERN void SynthGetInternalNodeName(char *name, int id);
+EXTERN void SynthDumpBlif(Ntk_Network_t *net, bdd_manager *dd, int no, bdd_node **ofuncs, char **onames, int *initStates, char *model);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _SYNTHINT */
Index: vis_dev/vis-2.3/src/synth/synthOpt.c
===================================================================
--- vis_dev/vis-2.3/src/synth/synthOpt.c	(revision 14)
+++ vis_dev/vis-2.3/src/synth/synthOpt.c	(revision 14)
@@ -0,0 +1,978 @@
+/**CFile***********************************************************************
+
+  FileName    [synthOpt.c]
+
+  PackageName [synth]
+
+  Synopsis    [Multilevel optimization functions.]
+
+  Author      [In-Ho Moon, Balakrishna Kumthekar]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "synthInt.h"
+
+static char rcsid[] UNUSED = "$Id: synthOpt.c,v 1.53 2005/05/11 20:18:25 hhhan Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+int	OutputOrdering = 1; /*
+			    ** 0 : just use VIS's order
+			    ** 1 : smaller first in terms of support
+			    ** 2 : smaller first in terms of bdd size
+			    */
+
+static	int	UseFuncDivisor = 1;
+static	float	SuppFactor = 10.0;
+static	float	ProbFactor = 10.0;
+static	int	*SupportCount;
+static	float	*Probability;
+static	char	**outputNames;
+
+extern	int	TryNodeSharing;
+extern	int	noMemoryFlag;
+extern	int	VerifyTreeMode;
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void GetOutputOrder(bdd_manager *dd, bdd_node **ofuncs, int no, int *order, int verbosity);
+static int IsSubsetOfSupportForOneWord(unsigned int mask1, unsigned int mask2);
+static int IsNullSupport(int size, unsigned int *mask);
+static void PrintSupportMask(int n, int size, unsigned int *mask);
+static int GetNumberOfSupport(int n, int size, unsigned int *mask);
+static int factorizeNetwork(Ntk_Network_t *net, bdd_manager *dd, bdd_node **ofuncs, MlTree **tree, int no, int *out_order, st_table *table, char **combOutNames, int divisor, MlTree *(* factoring_func)(bdd_manager *, st_table *, bdd_node *, int, int *, MlTree *, int, MlTree *, int), int verbosity);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Optimizes a network by factorizing.]
+
+  Description [Optimizes a network by factorizing.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthMultiLevelOptimize(Ntk_Network_t *network,
+			bdd_node **combOutBdds,
+			bdd_node **combUpperBdds,
+			char **combOutNames,
+			int *initStates,
+			Synth_InfoData_t *synthInfo,
+			int verbosity)
+{
+  bdd_manager		*dd = (bdd_manager *)Ntk_NetworkReadMddManager(network);
+  bdd_node		*top;
+  bdd_node		**ofuncs;
+  int			i, no;
+  int			factoring, divisor;
+  char			*filename;
+  char			*filehead;
+  MlTree		**tree;
+  bdd_node		*zdd_I;
+  st_table		*table;
+  int			nml, tml;
+  int			*out_order;
+  FILE			*feqn;
+  MlTree		*(* factoring_func)(bdd_manager *, st_table *,
+					    bdd_node *, int, int *, MlTree *,
+					    int, MlTree *, int);
+  int			autoDyn, autoDynZ;
+  bdd_reorder_type_t	method, methodZ;
+  int			error;
+
+  factoring = synthInfo->factoring;
+  divisor = synthInfo->divisor;
+  filehead = synthInfo->filehead;
+  TryNodeSharing = synthInfo->trySharing;
+  SynthSetInternalNodePrefix(synthInfo->prefix);
+
+  /* Save reordering status and set reordering mode specific to
+   * synthesis.
+   */
+  autoDyn = bdd_reordering_status(dd, &method);
+  autoDynZ = bdd_reordering_zdd_status(dd, &methodZ);
+
+  switch (synthInfo->reordering) {
+  case 0 :
+    bdd_dynamic_reordering_disable(dd);
+    bdd_dynamic_reordering_zdd_disable(dd);
+    break;
+  case 1 :
+    bdd_dynamic_reordering(dd, method, BDD_REORDER_VERBOSITY_DEFAULT);
+    bdd_dynamic_reordering_zdd_disable(dd);
+    break;
+  case 2 :
+    bdd_dynamic_reordering_disable(dd);
+    bdd_dynamic_reordering_zdd(dd, methodZ, BDD_REORDER_VERBOSITY_DEFAULT);
+    break;
+  case 3 :
+    bdd_dynamic_reordering(dd, method, BDD_REORDER_VERBOSITY_DEFAULT);
+    bdd_dynamic_reordering_zdd(dd, methodZ, BDD_REORDER_VERBOSITY_DEFAULT);
+    break;
+  default :
+    bdd_dynamic_reordering_disable(dd);
+    bdd_dynamic_reordering_zdd_disable(dd);
+    break;
+  }
+
+  if (factoring == 0)
+    factoring_func = SynthSimpleFactorTree;
+  else
+    factoring_func = SynthGenericFactorTree;
+
+  /* outputNames is a static global variable for this file. */
+  outputNames = combOutNames;
+
+  /* Initialize the node-tree table and other factoring-related variables.
+   * The table contains pairs of a ZDD node and the corresponding multi-level
+   * tree.
+   */
+  table = st_init_table(st_ptrcmp, st_ptrhash);
+  SynthInitMlTable();
+
+  /* Create ZDD variables for the positive and negative literals. */
+  bdd_zdd_vars_from_bdd_vars(dd, 2);
+
+  /* Since we currently support only blif files, the number of
+   * functions to synthesize should not include the initial
+   * inputs of latches in case of sequential ckts.
+   */
+  no = Ntk_NetworkReadNumCombOutputs(network) -
+    Ntk_NetworkReadNumLatches(network);
+
+  /* Compute two-level covers for all the functions to be synthesized. */
+  ofuncs = ALLOC(bdd_node *, no);
+  for (i = 0; i < no; i++) {
+    if (verbosity) {
+      (void)fprintf(vis_stdout, "** synth info: Synthesizing output [%d(%s)]\n",
+		    i, combOutNames[i]);
+    }
+    bdd_ref(top = bdd_zdd_isop(dd, combOutBdds[i], combUpperBdds[i],
+			       &zdd_I));
+    bdd_ref(zdd_I);
+    bdd_recursive_deref(dd, top);
+    ofuncs[i] = zdd_I;
+  }
+
+  if (VerifyTreeMode == 2)
+    SynthDumpBlif(network, dd, no, ofuncs, combOutNames, initStates, filehead);
+
+  /* Initialize array of factoring trees and determine the order in
+   * which the functions will be processed. Then proceed to factor.
+   */
+  tree = ALLOC(MlTree *, no);
+  (void)memset((void *)tree, 0, no * sizeof(MlTree *));
+  out_order = ALLOC(int, no);
+  GetOutputOrder(dd, ofuncs, no, out_order, verbosity);
+  error = factorizeNetwork(network, dd, ofuncs, tree, no, out_order,
+		   table, combOutNames, divisor, factoring_func, verbosity);
+  FREE(out_order);
+
+  if (error) {
+    (void)fprintf(vis_stderr,
+		  "** synth error: synthesize_network has finished abnormally");
+    if (noMemoryFlag)
+      (void)fprintf(vis_stderr, " due to lack of memory\n");
+    else
+      (void)fprintf(vis_stderr, " for some reason\n");
+    goto cleanup;
+  }
+
+  /* Count total number of literals in multi-level network. */
+  tml = 0;
+  for (i = 0; i < no; i++) {
+    if (tree[i]) {
+      nml = SynthCountMlLiteral(dd, tree[i], 1);
+      tml += nml;
+    }
+  }
+  (void)fprintf(vis_stdout,
+		"** synth info: Total number of literals = %d\n", tml);
+
+  /* Write network in eqn and blif formats. */
+  SynthSetupNodeNameTable(network);
+  filename = ALLOC(char, strlen(filehead) + 9);
+  if (synthInfo->eqn) {
+    sprintf(filename, "%s.eqn", filehead);
+    feqn = Cmd_FileOpen(filename, "w", NIL(char *), 0);
+    if (feqn) {
+      fprintf(feqn, "** synth info: Total number of literals = %d\n", tml);
+      SynthWriteEqnHeader(feqn, network, dd);
+      for (i = 0; i < no; i++) {
+	if (tree[i])
+	  SynthWriteEqn(feqn, network, dd, tree[i], ofuncs, combOutNames[i], 1);
+      }
+      fclose(feqn);
+    } else {
+      (void)fprintf(vis_stdout,
+		    "** synth error: Error in opening file [%s]\n", filename);
+    }
+  }
+  sprintf(filename, "%s.ml.blif", filehead);
+  SynthWriteBlifFile(network, dd, tree, filename, no, ofuncs, initStates,
+		     0, verbosity);
+  FREE(filename);
+  SynthFreeNodeNameTable();
+
+ cleanup:
+  /* Clean up. */
+  for (i = 0; i < no; i++) {
+    if (!tree[i])
+      continue;
+    bdd_recursive_deref_zdd(dd, tree[i]->node);
+    /* frees some trees not in node-tree table */
+    if (tree[i]->ref)
+      SynthFreeMlTree(tree[i], 0);
+  }
+
+  SynthClearMlTable(dd, table);
+  st_free_table(table);
+  FREE(tree);
+
+  for (i = 0; i < no; i++) {
+    if (!ofuncs[i])
+      continue;
+    bdd_recursive_deref_zdd(dd, ofuncs[i]);
+  }
+
+  FREE(ofuncs);
+
+  /* Restore reordering status. */
+  if (autoDyn)
+    bdd_dynamic_reordering(dd, method, BDD_REORDER_VERBOSITY_DEFAULT);
+  else
+    bdd_dynamic_reordering_disable(dd);
+  if (autoDynZ)
+    bdd_dynamic_reordering_zdd(dd, methodZ, BDD_REORDER_VERBOSITY_DEFAULT);
+  else
+    bdd_dynamic_reordering_zdd_disable(dd);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Sets the optional variable UseFuncDivisor.]
+
+  Description [Sets the optional variable UseFuncDivisor. Currently
+  UseFuncDivisor has always the initial value of 1, this is because it
+  seems does better almost always than 0.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthSetUseFuncDivisor(int mode)
+{
+  UseFuncDivisor = mode;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Sets the optional variable OutputOrdering.]
+
+  Description [Sets the optional variable OutputOrdering.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthSetOutputOrdering(int mode)
+{
+  OutputOrdering = mode;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Sets the cost factors to get a divisor for low power.]
+
+  Description [Sets the cost factors to get a divisor for low power.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthSetCostFactors(float supp,
+		    float prob)
+{
+  SuppFactor = supp;
+  ProbFactor = prob;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Sets the variable SupportCount.]
+
+  Description [Sets the variable SupportCount.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthSetSupportCount(int *count)
+{
+  SupportCount = count;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Sets the variable Probability.]
+
+  Description [Sets the variable Probability.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthSetProbability(float *prob)
+{
+  Probability = prob;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Finds a good divisor for low power.]
+
+  Description [Finds a good divisor for low power.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+SynthFindDivisorForLowPower(int	*count,
+			    int	nvars,
+			    int	min_count,
+			    int	min_pos)
+{
+  int	i, v;
+  float	cost, best;
+
+  if ((!SupportCount) || (!Probability))
+    return(-1);
+
+  v = min_pos;
+  if (SuppFactor == 0.0 && ProbFactor == 0.0)
+    best = (float)SupportCount[min_pos] * Probability[min_pos];
+  else {
+    best = (float)SupportCount[min_pos] * SuppFactor +
+      Probability[min_pos] * ProbFactor;
+  }
+
+  for (i = min_pos + 1; i < nvars; i++) {
+    if (count[i] == min_count) {
+      if (SuppFactor == 0.0 && ProbFactor == 0.0)
+	cost = (float)SupportCount[i] * Probability[i];
+      else {
+	cost = (float)SupportCount[i] * SuppFactor +
+	  Probability[i] * ProbFactor;
+      }
+      if (cost > best) {
+	best = cost;
+	v = i;
+      }
+    }
+  }
+
+  return(v);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the i-th output name.]
+
+  Description [Returns the i-th output name.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+char *
+SynthGetIthOutputName(int i)
+{
+  return outputNames[i];
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether one support set is a subset of the other
+  support set.]
+
+  Description [Checks whether one support set is a subset of the other
+  support set. A support set is represented by a bit-vector. If the
+  index 0 variable of a unique table is in the support of a function,
+  then the MSB bit is set to 1. In general, for the variable of index
+  i, the i-th bit from the MSB is set to 1. The argument size means
+  the number of words (word = sizeof(int)). If the sets are the same,
+  SynthIsSubsetOfSupport returns 2. If the first set is a subset of
+  the second, it returns 1, otherwise it returns 0.]
+
+  SideEffects []
+
+  SeeAlso     [IsSubsetOfSupportForOneWord IsNullSupport]
+
+******************************************************************************/
+int
+SynthIsSubsetOfSupport(int size,
+		       unsigned int *mask1,
+		       unsigned int *mask2)
+{
+  int	i, tmp, flag = 0;
+
+  if (!mask2)
+    return(1);
+
+  if (IsNullSupport(size, mask1) && IsNullSupport(size, mask2))
+    return(0);
+  else if (IsNullSupport(size, mask1))
+    return(0);
+  else if (IsNullSupport(size, mask2))
+    return(1);
+
+  for (i = 0; i < size; i++) {
+    tmp = IsSubsetOfSupportForOneWord(mask1[i], mask2[i]);
+    if (tmp == 0)
+      return(0);
+    flag |= tmp;
+  }
+
+  return(flag);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [This function orders the output functions. With this
+  output ordering, the lowest indexed output function is factorized
+  first.]
+
+  Description [This function orders the output functions. With this
+  output ordering, the lowest indexed output function is factorized
+  first. If OutputOrder is 0, the output order is just the same as the
+  order VIS has. If OutputOrder is 1, the smallest function (in terms
+  of the number of support variables) will be placed first in the
+  order. In case of tie, the function with the smaller BDD is placed
+  before the other in the order. If OutputOrder is 2, the smallest
+  function in terms of BDD size is first.]
+
+  SideEffects []
+
+  SeeAlso     [SynthMultiLevelOptimize]
+
+******************************************************************************/
+static void
+GetOutputOrder(bdd_manager *dd,
+	       bdd_node **ofuncs,
+	       int no,
+	       int *order,
+	       int verbosity)
+{
+  int		i, j, k, flag;
+  int		*support, *bddsize;
+  int		size;
+  unsigned int	**mask;
+  int		word, sizeZ;
+  int		pos, bit, bit_mask;
+  int		insert_flag, s1, s2;
+
+  if (no == 1) {
+    order[0] = 0;
+    return;
+  }
+
+  if (OutputOrdering == 0) {
+    for (i = 0; i < no; i++)
+      order[i] = i;
+    return;
+  }
+
+  bddsize = ALLOC(int, no);
+  if (OutputOrdering == 2) {
+    for (i = 0; i < no; i++) {
+      if (!ofuncs[i]) {
+	order[i] = i;
+	bddsize[i] = 0;
+	continue;
+      }
+
+      bddsize[i] = bdd_node_size(ofuncs[i]);
+
+      /* Insert i-th output at the right place in the order. */
+      for (j = 0; j < i; j++) {
+	if (bddsize[i] < bddsize[order[j]]) {
+	  for (k = i; k > j; k--)
+	    order[k] = order[k - 1];
+	  order[j] = i;
+	  break;
+	}
+      }
+
+      if (j == i)
+	order[i] = i;
+    }
+
+    if (verbosity) {
+      fprintf(vis_stdout, "output order :");
+      for (i = 0; i < no; i++)
+	fprintf(vis_stdout, " %d", order[i]);
+      fprintf(vis_stdout, "\n");
+      if (verbosity > 1) {
+	for (i = 0; i < no; i++)
+	  fprintf(vis_stdout, "%d - %d", i, bddsize[i]);
+      }
+    }
+
+    FREE(bddsize);
+    return;
+  }
+
+  /* Here OutputOrdering should be 1. */
+  mask = ALLOC(unsigned int *, no);
+  sizeZ = bdd_num_zdd_vars(dd);
+  support = ALLOC(int, sizeZ);
+  word = sizeof(int) * 8;
+  size = sizeZ / word + 1;
+
+  for (i = 0; i < no; i++) {
+    if (!ofuncs[i]) {
+      mask[i] = (unsigned int *)NULL;
+      order[i] = i;
+      bddsize[i] = 0;
+      continue;
+    }
+
+    mask[i] = ALLOC(unsigned int, size);
+    (void)memset((void *)mask[i], 0, size * sizeof(int));
+    (void)memset((void *)support, 0, sizeof(int) * sizeZ);
+    SynthZddSupportStep(bdd_regular(ofuncs[i]), support);
+    SynthZddClearFlag(bdd_regular(ofuncs[i]));
+    /* Pack the support array into a bit vector. */
+    for (j = 0; j < sizeZ; j++) {
+      if (support[j]) {
+	pos = j / word;
+	bit = j % word;
+	bit_mask = 01 << bit;
+	mask[i][pos] |= bit_mask;
+      }
+    }
+    bddsize[i] = bdd_node_size(ofuncs[i]);
+
+    for (j = 0; j < i; j++) {
+      insert_flag = 0;
+      flag = SynthIsSubsetOfSupport(size, mask[i], mask[order[j]]);
+      if (flag == 1)
+	insert_flag = 1;
+      else if (flag == 2) {
+	s1 = GetNumberOfSupport(sizeZ, size, mask[i]);
+	s2 = GetNumberOfSupport(sizeZ, size, mask[order[j]]);
+	if (s1 < s2 || (s1 == s2 && bddsize[i] < bddsize[order[j]]))
+	  insert_flag = 1;
+      }
+      if (insert_flag) {
+	for (k = i; k > j; k--)
+	  order[k] = order[k - 1];
+	order[j] = i;
+	break;
+      }
+    }
+
+    if (j == i)
+      order[i] = i;
+  }
+  FREE(support);
+  FREE(bddsize);
+
+  if (verbosity) {
+    fprintf(vis_stdout, "output order :");
+    for (i = 0; i < no; i++)
+      fprintf(vis_stdout, " %d", order[i]);
+    fprintf(vis_stdout, "\n");
+    if (verbosity > 1) {
+      for (i = 0; i < no; i++) {
+	if (mask[i])
+	  PrintSupportMask(sizeZ, size, mask[i]);
+      }
+    }
+  }
+
+  for (i = 0; i < no; i++) {
+    if (mask[i])
+      FREE(mask[i]);
+  }
+  FREE(mask);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Checks whether a set of support for one word is subset of the
+  other set of support for one word.]
+
+  Description [Checks whether a set of support for one word is subset of
+  the other set of support for one word. SynthIsSubsetOfSupport() calls
+  this function for each word.]
+
+  SideEffects []
+
+  SeeAlso     [SynthIsSubsetOfSupport]
+
+******************************************************************************/
+static int
+IsSubsetOfSupportForOneWord(unsigned int mask1,
+			    unsigned int mask2)
+{
+  unsigned int	tmp;
+
+  if (mask1 == mask2)
+    return(2);
+
+  tmp = mask1 | mask2;
+  if (tmp != mask2)
+    return(0);
+  return(1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Checks if a support set is empty.]
+
+  Description [Checks if a support set is empty.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+IsNullSupport(int size,
+	      unsigned int *mask)
+{
+  int	i;
+
+  for (i = 0; i < size; i++) {
+    if (mask[i] != 0)
+      return(0);
+  }
+  return(1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Prints the support of a function.]
+
+  Description [Prints the support of a function. The argument n is the
+  number of variables and size is the number of word and mask is the
+  array of support mask. The first line shows column index by modulo 10
+  and the next line shows which variables are support by printing 1.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+PrintSupportMask(int n,
+		 int size,
+		 unsigned int *mask)
+{
+  int	i, j, pos, last;
+  char	*support;
+  char	*mark;
+  int	bit;
+
+  support = ALLOC(char,n);
+  mark = ALLOC(char,n);
+
+  pos = 0;
+  for (i = 0; i < size; i++) {
+    if (i == (size - 1))
+      last = n % 32;
+    else
+      last = 32;
+    bit = 01;
+    for (j = 0; j < last; j++) {
+      sprintf(&mark[pos], "%d", pos % 10);
+      if (mask[i] & bit)
+	support[pos] = '1';
+      else
+	support[pos] = '0';
+      pos++;
+      bit = bit << 1;
+    }
+  }
+  mark[pos] = support[pos] = '\0';
+
+  fprintf(vis_stdout, "%s\n", mark);
+  fprintf(vis_stdout, "%s\n", support);
+
+  FREE(support);
+  FREE(mark);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns the number of support variables of a function.]
+
+  Description [Returns the number of support variables of a function.]
+
+  SideEffects [none]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+GetNumberOfSupport(int n,
+		   int size,
+		   unsigned int *mask)
+{
+  int	i, j, last;
+  int	bit;
+  int	count;
+
+  count = 0;
+  for (i = 0; i < size; i++) {
+    if (i == (size - 1))
+      last = n % 32;
+    else
+      last = 32;
+    bit = 01;
+    for (j = 0; j < last; j++) {
+      if (mask[i] & bit)
+	count++;
+      bit = bit << 1;
+    }
+  }
+  return(count);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Factorizes a network.]
+
+  Description [Factorizes a network. If successful, it returns 0,
+  otherwise it returns 1 due to lack of memory.] 
+
+  SideEffects []
+
+  SeeAlso     [SynthMultiLevelOptimize]
+
+******************************************************************************/
+static int
+factorizeNetwork(Ntk_Network_t *net,
+		 bdd_manager *dd,
+		 bdd_node **ofuncs,
+		 MlTree **tree,
+		 int no,
+		 int *out_order,
+		 st_table *table,
+		 char **combOutNames,
+		 int divisor,
+		 MlTree *(* factoring_func)(bdd_manager *, st_table *,
+					    bdd_node *, int, int *, MlTree *,
+					    int, MlTree *, int),
+		 int verbosity)
+{
+  int		i, j, k;
+  int		ref;
+  int		nml;
+  MlTree	*tmp_tree;
+  int		flag;
+  int		comp_flag;
+
+  SynthSetZddDivisorFunc(divisor); /* set static variable in synthFactor.c */
+
+  for (k = 0; k < no; k++) {
+    i = out_order[k];
+    if (!ofuncs[i]) {
+      tree[i] = NULL;
+      continue;
+    }
+    if (verbosity)
+      SynthPrintZddCoverWithName(net, dd, ofuncs[i]);
+
+    tree[i] = (MlTree *)NULL;
+    ref = 0;
+    if (ofuncs[i] == bdd_read_one(dd) || ofuncs[i] == bdd_read_zero(dd)) {
+      tree[i] = SynthFindOrCreateMlTree(table, dd, ofuncs[i], 1, 0,
+					&ref, verbosity);
+      if (!tree[i])
+	return(1);
+    } else {
+      tree[i] = SynthLookupMlTable(table, dd, ofuncs[i], 1, verbosity);
+      if (tree[i]) {
+	if (MlTree_IsComplement(tree[i]) || tree[i]->top)
+	  ref = 1;
+	else
+	  SynthUpdateRefOfParent(tree[i]);
+      }
+      else if (UseFuncDivisor) {
+	/* Try to divide by existing functions. The smaller
+	 * functions are factored first to increase the probability
+	 * of success of this step. Both phases of the divisor are
+	 * tried.
+	 */
+	for (j = k - 1; j >= 0; j--) {
+	  tree[i] = (* factoring_func)(dd, table, ofuncs[i], 0, &ref,
+				       tree[out_order[j]], 0, NULL, verbosity);
+	  if (tree[i]) {
+	    SynthSetSharedFlag(dd, tree[out_order[j]]);
+	    break;
+	  } else if (noMemoryFlag == 1)
+	    return(1);
+	  else {
+	    tree[i] = (* factoring_func)(dd, table, ofuncs[i], 0,
+				 &ref, tree[out_order[j]], 1, NULL, verbosity);
+	    if (tree[i]) {
+	      SynthSetSharedFlag(dd, tree[out_order[j]]);
+	      break;
+	    } else if (noMemoryFlag == 1)
+	      return(1);
+	  }
+	}
+      }
+    }
+    /* Division by other functions did not work. Find a brand-new
+     * factorization.
+     */
+    if (!tree[i]) {
+      tree[i] = (* factoring_func)(dd, table, ofuncs[i], 0,
+				   &ref, NULL, 0, NULL, verbosity);
+      if (!tree[i])
+	return(1);
+    }
+    /* Compute the complement ZDD node of ofuncs[i], if not exist.
+     * This is to increase sharing.
+     */
+    tmp_tree = tree[i];
+    tree[i] = SynthCheckAndMakeComplement(dd, table, tree[i], &comp_flag,
+					  verbosity);
+    if (!tree[i])
+      return(1);
+    else if (tree[i] != tmp_tree) {
+      ref = 1;
+      if (comp_flag)
+	tree[i] = MlTree_Not(tree[i]);
+    }
+
+    /* When the tree already exists, create a new tree and copy all
+     * contents, and set the field 'ref' to 1. This is for the
+     * purpose of avoiding duplicate literal counting.
+     */
+    if (ref) {
+      int	comp_flag;
+
+      comp_flag = 0;
+      if (MlTree_IsComplement(tree[i])) {
+	tree[i] = MlTree_Not(tree[i]);
+	comp_flag = 1;
+      }
+      tmp_tree = ALLOC(MlTree, sizeof(MlTree));
+      memcpy((void *)tmp_tree, (void *)tree[i], sizeof(MlTree));
+      tree[i] = tmp_tree;
+      tree[i]->ref = 1;
+      tree[i]->comp = comp_flag;
+    }
+    tree[i]->top = 1;
+    bdd_ref(tree[i]->node);
+
+    nml = SynthCountMlLiteral(dd, tree[i], 1);
+
+    if (verbosity) {
+      SynthPrintMlTreeWithName(net, dd, tree[i], "result : ");
+      fprintf(vis_stdout, "**** %d (#literal = %d) ****\n", i, nml);
+      if (verbosity > 1)
+	SynthWriteEqn(stdout, net, dd, tree[i], ofuncs, combOutNames[i], 1);
+    }
+
+    if (VerifyTreeMode) {
+      SynthVerifyTree(dd, tree[i], 1);
+      SynthVerifyMlTable(dd, table);
+    }
+  }
+
+  flag = SynthPostFactoring(dd, table, factoring_func, verbosity);
+
+  if (VerifyTreeMode) {
+    bdd_node *tmp;
+
+    for (i = 0; i < no; i++) {
+      if (tree[i]->comp)
+	tmp = tree[i]->complement;
+      else
+	tmp = tree[i]->node;
+      if (tmp != ofuncs[i]) {
+	(void) fprintf(vis_stdout,
+		       "** synth error: Different zdds in [%s].\n",
+		       combOutNames[i]);
+      }
+      SynthVerifyTree(dd, tree[i], 1);
+    }
+  }
+
+  return(flag);
+}
Index: vis_dev/vis-2.3/src/synth/synthSimple.c
===================================================================
--- vis_dev/vis-2.3/src/synth/synthSimple.c	(revision 14)
+++ vis_dev/vis-2.3/src/synth/synthSimple.c	(revision 14)
@@ -0,0 +1,1191 @@
+/**CFile***********************************************************************
+
+  FileName    [synthSimple.c]
+
+  PackageName [synth]
+
+  Synopsis    [Simple factorization method.]
+
+  Description []
+
+  Author      [In-Ho Moon, Balakrishna Kumthekar]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "synthInt.h"
+
+static char rcsid[] UNUSED = "$Id: synthSimple.c,v 1.36 2005/04/23 14:37:51 jinh Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+extern	int	CompMode;
+extern	int	UseMtree;
+extern	int	UseCommonDivisor;
+extern	int	TryNodeSharing;
+extern	int	Resubstitution;
+extern	int	RemainderComplement;
+extern	int	noMemoryFlag;
+extern	int	VerifyTreeMode;
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CountZddLeafLiterals(bdd_manager *dd, bdd_node *node);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Factorizes a function using a simple method.]
+
+  Description [Factorizes a function using a simple method. Here simple
+  refers that this algorithm tries to factorize just recursively. First
+  it finds a divisor, then finds quotient and remainder, and then recurs
+  for each.  The argument table consists of a pair of bdd_node and MlTree,
+  f is to be factorized, level is the depth of MlTree from top, ref returns 1
+  if new MlTree is created for f, otherwise returns 0, comp_d_tree is usually
+  NULL except when post factoring takes place(here post factoring is the
+  case to factorize a leaf node by another leaf node and a leaf node is a node
+  in which there is no divisor), comp_d_tree is a tree which is going to be
+  used as a divisor and comp_d_flag is used to indicate which node is going
+  to be used as a divisor between regular node and complement node, bring is
+  usually NULL except post factoring: when we update an already existing
+  tree by further factorization, we pass this tree to reuse it.]
+
+  SideEffects []
+
+  SeeAlso     [SynthGenericFactorTree]
+
+******************************************************************************/
+MlTree *
+SynthSimpleFactorTree(bdd_manager *dd,
+		      st_table *table,
+		      bdd_node *f,
+		      int level,
+		      int *ref,
+		      MlTree *comp_d_tree,
+		      int comp_d_flag,
+		      MlTree *bring,
+		      int verbosity)
+{
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  bdd_node	*d, *q, *r, *m;
+  MlTree	*tree, *q_tree, *d_tree, *r_tree;
+  char		message[120];
+  char		space[100];
+  MlTree	*comp_q_tree = (MlTree *)NULL;
+  MlTree	*comp_r_tree = (MlTree *)NULL;
+  int		found;
+  MlTree	*tmp_tree;
+  int		comp_flag;
+
+  if (verbosity > 1) {
+    SynthGetSpaceString(space, level * 2, 80);
+    sprintf(message, "%s[%d] in : ", space, level);
+    SynthPrintZddTreeMessage(dd, f, message);
+    sprintf(message, "%s[%d]out : ", space, level);
+  }
+
+  if (bring)
+    tree = (MlTree *)NULL;
+  else {
+    tree = SynthLookupMlTable(table, dd, f, 1, verbosity);
+    /* tree could be NULL because of reordering, or a failure to
+     * allocate memory or just that f was not in the cache.
+     * So, we would like return NULL ONLY in the case of 
+     * reordering or failure to allocate memory. 
+     */
+    if (bdd_read_reordered_field(dd) || noMemoryFlag == 1)
+      return(NULL);
+  }
+  if (tree) {
+    if (verbosity > 1)
+      SynthPrintMlTreeMessage(dd, tree, message);
+    *ref = 1;
+    return(tree);
+  }
+
+  if (f == one || f == zero) {
+    tree = SynthFindOrCreateMlTree(table, dd, f, 1, 0, ref, verbosity);
+    if (!tree)
+      return(NULL);
+    tmp_tree = tree;
+    tree = SynthCheckAndMakeComplement(dd, table, tree, &comp_flag, verbosity);
+    if (!tree) {
+      if (*ref == 0)
+	SynthFreeMlTree(MlTree_Regular(tmp_tree), 1);
+      return(NULL);
+    } else if (tree != tmp_tree) {
+      *ref = 1;
+      if (comp_flag)
+	tree = MlTree_Not(tree);
+    }
+    if (verbosity > 1)
+      SynthPrintMlTreeMessage(dd, tree, message);
+    return(tree);
+  }
+
+  d_tree = (MlTree *)NULL;
+  if (comp_d_tree) {
+    if (comp_d_flag)
+      d = comp_d_tree->complement;
+    else
+      d = comp_d_tree->node;
+    if (!d)
+      return((MlTree *)NULL);
+    bdd_ref(d);
+  } else {
+    found = 0;
+    d = (* SynthGetZddDivisorFunc())(dd, f);
+    if (!d)
+      return(NULL);
+    bdd_ref(d);
+    if (TryNodeSharing) {
+      /* Here, we don't need to call bdd_ref. */
+      d = SynthFindBiggerDivisorInList(dd, table, f, d, &found,
+				       &comp_d_flag, &comp_d_tree, verbosity);
+      if (!d)
+	return(NULL);
+    }
+    if (UseCommonDivisor && found == 0) {
+      tree = SynthGetFactorTreeWithCommonDivisor(dd, table,
+			 SynthSimpleFactorTree, f, d, level, ref, verbosity);
+      if (tree)
+	return(tree);
+      if (bdd_read_reordered_field(dd) || noMemoryFlag == 1)
+	return(NULL);
+    }
+  }
+  if (d == f) {
+    tree = SynthFindOrCreateMlTree(table, dd, f, 1, 0, ref, verbosity);
+    if (!tree) {
+      bdd_recursive_deref_zdd(dd, d);
+      return(NULL);
+    }
+    if (verbosity > 1)
+      SynthPrintMlTreeMessage(dd, tree, message);
+    tmp_tree = tree;
+    tree = SynthCheckAndMakeComplement(dd, table, tree, &comp_flag, verbosity);
+    if (!tree) {
+      bdd_recursive_deref_zdd(dd, d);
+      return(NULL);
+    } else if (tree == tmp_tree) {
+      if (*ref == 0)
+	SynthPutMlTreeInList(dd, tree, 0);
+    } else {
+      *ref = 1;
+      if (comp_flag)
+	tree = MlTree_Not(tree);
+    }
+    bdd_recursive_deref_zdd(dd, d);
+    return(tree);
+  }
+  if (!comp_d_tree) {
+    if (st_lookup(table, (char *)d, &d_tree)) {
+      SynthSetSharedFlag(dd, d_tree);
+      if (MlTree_Regular(d_tree)->candidate) {
+	if (!SynthUseCandidate(table, dd, d_tree, verbosity)) {
+	  bdd_recursive_deref_zdd(dd, d);
+	  return(NULL);
+	}
+      }
+      if (MlTree_IsComplement(d_tree)) {
+	d_tree = MlTree_Regular(d_tree);
+	comp_d_tree = d_tree;
+	d_tree = (MlTree *)NULL;
+      }
+    }
+  } else {
+    if (!comp_d_flag)
+      d_tree = comp_d_tree;
+  }
+
+  q = (* SynthGetZddDivideFunc())(dd, f, d);
+  if (!q) {
+    bdd_recursive_deref_zdd(dd, d);
+    return(NULL);
+  }
+  bdd_ref(q);
+  if (comp_d_tree && q == zero) {
+    bdd_recursive_deref_zdd(dd, d);
+    bdd_recursive_deref_zdd(dd, q);
+    return((MlTree *)NULL);
+  }
+  if (q == one) {
+    bdd_recursive_deref_zdd(dd, q);
+    tree = SynthPostFactorTree(dd, table, f, q, d, bring,
+		       comp_d_tree, comp_d_flag, message, ref, verbosity);
+    bdd_recursive_deref_zdd(dd, d);
+    return(tree);
+  }
+
+  if (comp_d_tree && d_tree == comp_d_tree)
+    comp_d_tree = (MlTree *)NULL;
+
+  q_tree = (MlTree *)NULL;
+  if (st_lookup(table, (char *)q, &q_tree)) {
+    SynthSetSharedFlag(dd, q_tree);
+    if (MlTree_Regular(q_tree)->candidate) {
+      if (!SynthUseCandidate(table, dd, q_tree, verbosity)) {
+	bdd_recursive_deref_zdd(dd, d);
+	bdd_recursive_deref_zdd(dd, q);
+	return(NULL);
+      }
+    }
+    if (MlTree_IsComplement(q_tree)) {
+      q_tree = MlTree_Regular(q_tree);
+      comp_q_tree = q_tree;
+      q_tree = (MlTree *)NULL;
+    }
+  }
+
+  m = (* SynthGetZddProductFunc())(dd, d, q);
+  if (!m) {
+    bdd_recursive_deref_zdd(dd, d);
+    bdd_recursive_deref_zdd(dd, q);
+    return(NULL);
+  }
+  bdd_ref(m);
+  r = bdd_zdd_diff(dd, f, m);
+  if (!r) {
+    bdd_recursive_deref_zdd(dd, d);
+    bdd_recursive_deref_zdd(dd, q);
+    bdd_recursive_deref_zdd(dd, m);
+    return(NULL);
+  }
+  bdd_ref(r);
+
+  r_tree = (MlTree *)NULL;
+  if (st_lookup(table, (char *)r, &r_tree)) {
+    SynthSetSharedFlag(dd, r_tree);
+    if (MlTree_Regular(r_tree)->candidate) {
+      if (!SynthUseCandidate(table, dd, r_tree, verbosity)) {
+	bdd_recursive_deref_zdd(dd, d);
+	bdd_recursive_deref_zdd(dd, q);
+	bdd_recursive_deref_zdd(dd, m);
+	bdd_recursive_deref_zdd(dd, r);
+	return(NULL);
+      }
+    }
+    if (MlTree_IsComplement(r_tree)) {
+      r_tree = MlTree_Regular(r_tree);
+      comp_r_tree = r_tree;
+      r_tree = (MlTree *)NULL;
+    }
+  }
+
+  tree = SynthFactorTreeRecur(dd, table, SynthSimpleFactorTree,
+			      f, q, d, r, m, q_tree, d_tree, r_tree,
+			      comp_q_tree, comp_d_tree, comp_r_tree,
+			      bring, level, space, message, ref, verbosity);
+  bdd_recursive_deref_zdd(dd, d);
+  bdd_recursive_deref_zdd(dd, q);
+  bdd_recursive_deref_zdd(dd, m);
+  bdd_recursive_deref_zdd(dd, r);
+
+  if (VerifyTreeMode) {
+    SynthVerifyTree(dd, tree, 0);
+    SynthVerifyMlTable(dd, table);
+  }
+
+  return(tree);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Finds a bigger divisor in divisor list.]
+
+  Description [Finds a bigger divisor in divisor list.]
+
+  SideEffects []
+
+  SeeAlso     [SynthSimpleFactorTree SynthGenericFactorTree]
+
+******************************************************************************/
+bdd_node *
+SynthFindBiggerDivisorInList(bdd_manager *dd,
+			     st_table *table,
+			     bdd_node *f,
+			     bdd_node *d,
+			     int *found,
+			     int *comp_d_flag,
+			     MlTree **comp_d_tree,
+			     int verbosity)
+{
+  bdd_node	*zero = bdd_read_zero(dd);
+  int		size, nSupports;
+  unsigned int	*support;
+  int		flag;
+  int		nL, nLiterals;
+  bdd_node	*candy;
+  MlTree	*cur;
+  bdd_node	*q;
+
+  nSupports = SynthGetSupportCount(dd, d);
+  size = bdd_num_zdd_vars(dd) / (sizeof(unsigned int) * 8) + 1;
+  support = ALLOC(unsigned int, size);
+  SynthGetSupportMask(dd, f, support);
+  flag = 0;
+  cur = SynthGetHeadTreeOfSize(SynthGetLiteralCount(dd, f) - 1);
+  nLiterals = CountZddLeafLiterals(dd, d);
+  if (nLiterals == -1) {
+    noMemoryFlag = 1;
+    FREE(support);
+    bdd_recursive_deref_zdd(dd, d);
+    return(NULL);
+  }
+
+  while (cur) {
+    if (cur->nLiterals < nSupports)
+      break;
+    nL = CountZddLeafLiterals(dd, cur->node);
+
+    if ((!SynthIsSubsetOfSupport(size, cur->support, support)) ||
+	nL < nLiterals) {
+      flag = 0;
+      cur = cur->next;
+      continue;
+    }
+
+    if (flag)
+      candy = cur->complement;
+    else
+      candy = cur->node;
+    q = (* SynthGetZddDivideFunc())(dd, f, candy);
+    if (!q) {
+      FREE(support);
+      bdd_recursive_deref_zdd(dd, d);
+      return(NULL);
+    }
+    bdd_ref(q);
+    bdd_recursive_deref_zdd(dd, q);
+    if (q != zero) {
+      if (MlTree_Regular(cur)->candidate) {
+	if (!SynthUseCandidate(table, dd, cur, verbosity)) {
+	  FREE(support);
+	  bdd_recursive_deref_zdd(dd, d);
+	  return(NULL);
+	}
+      }
+      *found = 1;
+      *comp_d_flag = flag;
+      *comp_d_tree = cur;
+      bdd_recursive_deref_zdd(dd, d);
+      d = candy;
+      bdd_ref(d);
+      break;
+    }
+    if (flag == 0 && cur->complement)
+      flag = 1;
+    else {
+      cur = cur->next;
+      flag = 0;
+    }
+  }
+
+  FREE(support);
+  return(d);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Factorizes a function with a common divisor if it exists.]
+
+  Description [Factorizes a function with a common divisor if it exists.]
+
+  SideEffects []
+
+  SeeAlso     [SynthSimpleFactorTree SynthGenericFactorTree]
+
+******************************************************************************/
+MlTree *
+SynthGetFactorTreeWithCommonDivisor(bdd_manager *dd,
+				    st_table *table,
+				    MlTree *(* factoring_func)(bdd_manager *,
+							       st_table *,
+							       bdd_node *, int,
+							       int *, MlTree *,
+							       int, MlTree *,
+							       int),
+				    bdd_node *f,
+				    bdd_node *d,
+				    int level,
+				    int *ref,
+				    int verbosity)
+{
+  bdd_node	*zero = bdd_read_zero(dd);
+  bdd_node	*cd;
+  bdd_node	*q;
+  MlTree	*tree, *q_tree, *d_tree, *r_tree;
+  int		q_ref, d_ref, r_ref;
+  MlTree	*comp_q_tree = (MlTree *)NULL;
+  MlTree	*comp_d_tree = (MlTree *)NULL;
+  MlTree	*comp_r_tree = (MlTree *)NULL;
+  int		q_tree_exist;
+  MlTree	*tmp_tree;
+  char		message[120];
+  char		space[100];
+  char		comp_mess[120];
+  int		comp_flag;
+
+  q_ref = d_ref = r_ref = 0;
+
+  if (verbosity > 1) {
+    SynthGetSpaceString(space, level * 2, 80);
+    sprintf(message, "%s[%d]out : ", space, level);
+  }
+
+  cd = SynthZddCommonDivisor(dd, f);
+  if (cd) {
+    bdd_recursive_deref_zdd(dd, d);
+    d = cd;
+    bdd_ref(d);
+    q = (* SynthGetZddDivideFunc())(dd, f, d);
+    if (!q) {
+      bdd_recursive_deref_zdd(dd, d);
+      return(NULL);
+    }
+    bdd_ref(q);
+
+    d_tree = (MlTree *)NULL;
+    if (st_lookup(table, (char *)d, &d_tree)) {
+      SynthSetSharedFlag(dd, d_tree);
+      if (MlTree_Regular(d_tree)->candidate) {
+	if (!SynthUseCandidate(table, dd, d_tree, verbosity)) {
+	  bdd_recursive_deref_zdd(dd, d);
+	  bdd_recursive_deref_zdd(dd, q);
+	  return(NULL);
+	}
+      }
+      if (MlTree_IsComplement(d_tree)) {
+	d_tree = MlTree_Regular(d_tree);
+	comp_d_tree = d_tree;
+      }
+      d_ref = 1;
+    } else {
+      d_tree = SynthFindOrCreateMlTree(table, dd, d, 1, 0, &d_ref, verbosity);
+      if (!d_tree) {
+	bdd_recursive_deref_zdd(dd, d);
+	bdd_recursive_deref_zdd(dd, q);
+	return(NULL);
+      }
+      if (MlTree_IsComplement(d_tree)) {
+	d_tree = MlTree_Regular(d_tree);
+	comp_d_tree = d_tree;
+      }
+      tmp_tree = d_tree;
+      d_tree = SynthCheckAndMakeComplement(dd, table, d_tree, &comp_flag,
+					   verbosity);
+      if (!d_tree) {
+	bdd_recursive_deref_zdd(dd, d);
+	bdd_recursive_deref_zdd(dd, q);
+	return(NULL);
+      } else if (d_tree == tmp_tree) {
+	if (d_ref == 0)
+	  SynthPutMlTreeInList(dd, d_tree, 0);
+      } else {
+	if (comp_flag)
+	  comp_d_tree = d_tree;
+	d_ref = 1;
+      }
+    }
+
+    q_tree = (MlTree *)NULL;
+    if (st_lookup(table, (char *)q, &q_tree)) {
+      SynthSetSharedFlag(dd, q_tree);
+      if (MlTree_Regular(q_tree)->candidate) {
+	if (!SynthUseCandidate(table, dd, q_tree, verbosity)) {
+	  bdd_recursive_deref_zdd(dd, d);
+	  bdd_recursive_deref_zdd(dd, q);
+	  return(NULL);
+	}
+      }
+      if (MlTree_IsComplement(q_tree)) {
+	q_tree = MlTree_Regular(q_tree);
+	comp_q_tree = q_tree;
+	q_tree = (MlTree *)NULL;
+      }
+    }
+
+    if (verbosity > 1)
+      (void) fprintf(vis_stdout,"%s[%d] quotient\n", space, level);
+    q_tree_exist = 0;
+    if (q_tree) {
+      q_ref = 1;
+      q_tree_exist = 1;
+    } else if (comp_q_tree) {
+      q_tree = comp_q_tree;
+      q_ref = 1;
+      if (verbosity > 1) {
+	sprintf(comp_mess, "%s\t(C) : ", space);
+	SynthPrintZddTreeMessage(dd, q, comp_mess);
+      }
+    } else {
+      q_tree = (* factoring_func)(dd, table, q, level + 1,&q_ref,
+				  NULL, 0, NULL, verbosity);
+      if (!q_tree) {
+	bdd_recursive_deref_zdd(dd, d);
+	bdd_recursive_deref_zdd(dd, q);
+	return(NULL);
+      }
+      if (MlTree_IsComplement(q_tree)) {
+	q_tree = MlTree_Regular(q_tree);
+	comp_q_tree = q_tree;
+      } else
+	bdd_ref(q_tree->node);
+    }
+    tmp_tree = q_tree;
+    q_tree = SynthCheckAndMakeComplement(dd, table, q_tree, &comp_flag,
+					 verbosity);
+    if (!q_tree) {
+      bdd_recursive_deref_zdd(dd, d);
+      bdd_recursive_deref_zdd(dd, q);
+      if (comp_q_tree != q_tree)
+	bdd_recursive_deref_zdd(dd, q_tree->node);
+      return(NULL);
+    } else if (q_tree != tmp_tree) {
+      if (comp_flag)
+	comp_q_tree = q_tree;
+      q_ref = 1;
+    }
+
+    r_tree = SynthFindOrCreateMlTree(table, dd, zero, 1, 0, &r_ref, verbosity);
+    if (!r_tree) {
+      bdd_recursive_deref_zdd(dd, d);
+      bdd_recursive_deref_zdd(dd, q);
+      if (comp_q_tree != q_tree)
+	bdd_recursive_deref_zdd(dd, q_tree->node);
+      return(NULL);
+    }
+    if (MlTree_IsComplement(r_tree)) {
+      r_tree = MlTree_Regular(r_tree);
+      comp_r_tree = r_tree;
+    }
+    tmp_tree = r_tree;
+    r_tree = SynthCheckAndMakeComplement(dd, table, r_tree, &comp_flag,
+					 verbosity);
+    if (!r_tree) {
+      bdd_recursive_deref_zdd(dd, d);
+      bdd_recursive_deref_zdd(dd, q);
+      if (comp_q_tree != q_tree)
+	bdd_recursive_deref_zdd(dd, q_tree->node);
+      return(NULL);
+    } else if (r_tree != tmp_tree) {
+      if (comp_flag)
+	comp_r_tree = r_tree;
+      r_ref = 1;
+    }
+
+    bdd_recursive_deref_zdd(dd, q);
+    bdd_recursive_deref_zdd(dd, d);
+    if ((!q_tree_exist) && (!comp_q_tree))
+      bdd_recursive_deref_zdd(dd, q_tree->node);
+
+    tree = SynthFindOrCreateMlTree(table, dd, f, 0, 0, ref, verbosity);
+    if (!tree)
+      return(NULL);
+    if (*ref == 1)
+      (void) fprintf(vis_stdout, "** synth warning: May be duplicate.\n");
+    tree->q = q_tree;
+    tree->d = d_tree;
+    tree->r = r_tree;
+    if (comp_q_tree)
+      tree->q_comp = 1;
+    if (comp_d_tree)
+      tree->d_comp = 1;
+    if (comp_r_tree)
+      tree->r_comp = 1;
+    tree->q_ref = q_ref;
+    tree->d_ref = d_ref;
+    tree->r_ref = r_ref;
+    if (verbosity > 1)
+      SynthPrintMlTreeMessage(dd, tree, message);
+    SynthPutMlTreeInList(dd, tree, 0);
+    if (VerifyTreeMode) {
+      SynthVerifyTree(dd, tree, 0);
+      SynthVerifyMlTable(dd, table);
+    }
+    return(tree);
+  } else if (bdd_read_reordered_field(dd) || noMemoryFlag == 1)
+    bdd_recursive_deref_zdd(dd, d);
+  return(NULL);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Try to factorize between leaf trees.]
+
+  Description [Try to factorize between leaf trees.]
+
+  SideEffects []
+
+  SeeAlso     [SynthSimpleFactorTree SynthGenericFactorTree]
+
+******************************************************************************/
+MlTree *
+SynthPostFactorTree(bdd_manager *dd,
+		    st_table *table,
+		    bdd_node *f,
+		    bdd_node *q,
+		    bdd_node *d,
+		    MlTree *bring,
+		    MlTree *comp_d_tree,
+		    int comp_d_flag,
+		    char *message,
+		    int *ref,
+		    int verbosity)
+{
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*r;
+  MlTree	*tree, *r_tree, *tmp_tree;
+  int		q_ref, r_ref;
+  MlTree	*comp_r_tree = (MlTree *)NULL;
+  int		comp_flag;
+
+  q_ref = r_ref = 0;
+
+  r = bdd_zdd_diff(dd, f, d);
+  if (!r)
+    return(NULL);
+  bdd_ref(r);
+  r_tree = (MlTree *)NULL;
+  if (st_lookup(table, (char *)r, &r_tree)) {
+    SynthSetSharedFlag(dd, r_tree);
+    if (MlTree_Regular(r_tree)->candidate) {
+      if (!SynthUseCandidate(table, dd, r_tree, verbosity)) {
+	bdd_recursive_deref_zdd(dd, r);
+	return(NULL);
+      }
+    }
+    if (MlTree_IsComplement(r_tree)) {
+      r_tree = MlTree_Regular(r_tree);
+      comp_r_tree = r_tree;
+    }
+    r_ref = 1;
+  } else {
+    r_tree = SynthFindOrCreateMlTree(table, dd, r, 1, 0, &r_ref, verbosity);
+    if (!r_tree) {
+      bdd_recursive_deref_zdd(dd, r);
+      return(NULL);
+    }
+    if (MlTree_IsComplement(r_tree)) {
+      comp_r_tree = MlTree_Regular(r_tree);
+      r_tree = comp_r_tree;
+    }
+    tmp_tree = r_tree;
+    r_tree = SynthCheckAndMakeComplement(dd, table, r_tree, &comp_flag,
+					 verbosity);
+    if (!r_tree) {
+      bdd_recursive_deref_zdd(dd, r);
+      return(NULL);
+    } else if (r_tree == tmp_tree) {
+      if (r_ref == 0)
+	SynthPutMlTreeInList(dd, r_tree, 0);
+    } else {
+      if (comp_flag)
+	comp_r_tree = r_tree;
+      r_ref = 1;
+    }
+  }
+  bdd_recursive_deref_zdd(dd, r);
+
+  if (bring)
+    tree = bring;
+  else {
+    tree = SynthFindOrCreateMlTree(table, dd, f, 0, 0, ref, verbosity);
+    if (!tree)
+      return(NULL);
+    if (*ref)
+      (void)fprintf(vis_stdout, "** synth warning: May be duplicate.\n");
+  }
+  tree->q = SynthFindOrCreateMlTree(table, dd, one, 1, 0, &q_ref, verbosity);
+  if (!tree->q)
+    return(NULL);
+  if (MlTree_IsComplement(tree->q)) {
+    tree->q = MlTree_Regular(tree->q);
+    tree->q_comp = 1;
+  }
+  tree->d = comp_d_tree;
+  tree->r = r_tree;
+  tree->d_comp = comp_d_flag;
+  if (comp_r_tree)
+    tree->r_comp = 1;
+  tree->q_ref = q_ref;
+  tree->d_ref = 1;
+  tree->r_ref = r_ref;
+  if (verbosity > 1)
+    SynthPrintMlTreeMessage(dd, tree, message);
+  if (bring)
+    bring->leaf = 0;
+  else
+    SynthPutMlTreeInList(dd, tree, 0);
+  if (VerifyTreeMode) {
+    SynthVerifyTree(dd, tree, 0);
+    SynthVerifyMlTable(dd, table);
+  }
+  return(tree);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Recursive procedure of SynthSimpleFactorTree and
+  SynthGenericFactorTree.]
+
+  Description [Recursive procedure of SynthSimpleFactorTree and
+  SynthGenericFactorTree.]
+
+  SideEffects []
+
+  SeeAlso     [SynthSimpleFactorTree SynthGenericFactorTree]
+
+******************************************************************************/
+MlTree *
+SynthFactorTreeRecur(bdd_manager *dd,
+		     st_table *table,
+		     MlTree *(* factoring_func)(bdd_manager *, st_table *,
+						bdd_node *, int, int *,
+						MlTree *, int, MlTree *, int),
+		     bdd_node *f,
+		     bdd_node *q,
+		     bdd_node *d,
+		     bdd_node *r,
+		     bdd_node *m,
+		     MlTree *q_tree,
+		     MlTree *d_tree,
+		     MlTree *r_tree,
+		     MlTree *comp_q_tree,
+		     MlTree *comp_d_tree,
+		     MlTree *comp_r_tree,
+		     MlTree *bring,
+		     int level,
+		     char *space,
+		     char *message,
+		     int *ref,
+		     int verbosity)
+{
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  int		q_tree_exist, d_tree_exist, r_tree_exist;
+  MlTree	*m_tree;
+  MlTree	*tree, *tmp_tree;
+  int		q_ref, d_ref, r_ref, m_ref;
+  char		comp_mess[120];
+  int		comp_flag;
+
+  q_ref = d_ref = r_ref = 0;
+
+  if (verbosity > 1)
+    (void) fprintf(vis_stdout,"%s[%d] quotient\n", space, level);
+  q_tree_exist = 0;
+  if (q_tree) {
+    q_ref = 1;
+    q_tree_exist = 1;
+  } else if (comp_q_tree) {
+    q_tree = comp_q_tree;
+    q_ref = 1;
+    if (verbosity > 1) {
+      sprintf(comp_mess, "%s\t(C) : ", space);
+      SynthPrintZddTreeMessage(dd, q, comp_mess);
+    }
+  } else {
+    q_tree = (* factoring_func)(dd, table, q, level + 1,
+				&q_ref, NULL, 0, NULL, verbosity);
+    if (!q_tree)
+      return(NULL);
+    if (MlTree_IsComplement(q_tree)) {
+      q_tree = MlTree_Regular(q_tree);
+      comp_q_tree = q_tree;
+    } else
+      bdd_ref(q_tree->node);
+  }
+  tmp_tree = q_tree;
+  q_tree = SynthCheckAndMakeComplement(dd, table, q_tree, &comp_flag,
+				       verbosity);
+  if (!q_tree) {
+    if (comp_q_tree != tmp_tree)
+      bdd_recursive_deref_zdd(dd, tmp_tree->node);
+    if (q_ref == 0)
+      SynthFreeMlTree(MlTree_Regular(tmp_tree), 1);
+    return(NULL);
+  } else if (q_tree != tmp_tree) {
+    if (comp_flag)
+      comp_q_tree = q_tree;
+    q_ref = 1;
+  }
+
+  if (verbosity > 1)
+    (void)fprintf(vis_stdout,"%s[%d] divisor\n", space, level);
+  d_tree_exist = 0;
+  if (d_tree) {
+    d_ref = 1;
+    d_tree_exist = 1;
+  } else if (comp_d_tree) {
+    d_tree = comp_d_tree;
+    d_ref = 1;
+    if (verbosity > 1) {
+      sprintf(comp_mess, "%s\t(C) : ", space);
+      SynthPrintZddTreeMessage(dd, d, comp_mess);
+    }
+  } else {
+    d_tree = (* factoring_func)(dd, table, d, level + 1, &d_ref,
+				NULL, 0, NULL, verbosity);
+    if (!d_tree) {
+      if (comp_q_tree != q_tree)
+	bdd_recursive_deref_zdd(dd, q_tree->node);
+      if (q_ref == 0)
+	SynthFreeMlTree(MlTree_Regular(q_tree), 1);
+      return(NULL);
+    }
+    if (MlTree_IsComplement(d_tree)) {
+      d_tree = MlTree_Regular(d_tree);
+      comp_d_tree = d_tree;
+    } else
+      bdd_ref(d_tree->node);
+  }
+  tmp_tree = d_tree;
+  d_tree = SynthCheckAndMakeComplement(dd, table, d_tree, &comp_flag,
+				       verbosity);
+  if (!d_tree) {
+    if (comp_q_tree != q_tree)
+      bdd_recursive_deref_zdd(dd, q_tree->node);
+    if (comp_d_tree != tmp_tree)
+      bdd_recursive_deref_zdd(dd, tmp_tree->node);
+    if (q_ref == 0)
+      SynthFreeMlTree(MlTree_Regular(q_tree), 1);
+    if (d_ref == 0)
+      SynthFreeMlTree(MlTree_Regular(tmp_tree), 1);
+    return(NULL);
+  } else if (d_tree != tmp_tree) {
+    if (comp_flag)
+      comp_d_tree = d_tree;
+    d_ref = 1;
+  }
+
+  m_tree = (MlTree *)NULL;
+  m_ref = 0;
+  if (UseMtree && m != f) {
+    m_tree = SynthFindOrCreateMlTree(table, dd, m, 0, 1, &m_ref, verbosity);
+    if (!m_tree) {
+      if (comp_q_tree != q_tree)
+	bdd_recursive_deref_zdd(dd, q_tree->node);
+      if (comp_d_tree != d_tree)
+	bdd_recursive_deref_zdd(dd, d_tree->node);
+      if (q_ref == 0)
+	SynthFreeMlTree(MlTree_Regular(q_tree), 1);
+      if (d_ref == 0)
+	SynthFreeMlTree(MlTree_Regular(d_tree), 1);
+      return(NULL);
+    }
+    if (m_ref == 0) {
+      m_tree->q = q_tree;
+      m_tree->d = d_tree;
+      m_tree->r = (MlTree *)NULL;
+      if (comp_q_tree)
+	m_tree->q_comp = 1;
+      if (comp_d_tree)
+	m_tree->d_comp = 1;
+      m_tree->q_ref = q_ref;
+      m_tree->d_ref = d_ref;
+      m_tree->r_ref = 0;
+
+      tmp_tree = m_tree;
+      m_tree = SynthCheckAndMakeComplement(dd, table, m_tree, &comp_flag,
+					   verbosity);
+      if (!m_tree) {
+	if (comp_q_tree != q_tree)
+	  bdd_recursive_deref_zdd(dd, q_tree->node);
+	if (comp_d_tree != d_tree)
+	  bdd_recursive_deref_zdd(dd, d_tree->node);
+	if (q_ref == 0)
+	  SynthFreeMlTree(MlTree_Regular(q_tree), 1);
+	if (d_ref == 0)
+	  SynthFreeMlTree(MlTree_Regular(d_tree), 1);
+	return(NULL);
+      } else if (m_tree == tmp_tree)
+	SynthPutMlTreeInList(dd, m_tree, 1);
+      else {
+	if (m_tree->candidate)
+	  SynthPutMlTreeInList(dd, m_tree, 1);
+	else
+	  m_tree = NIL(MlTree);
+      }
+      if (m_tree && VerifyTreeMode) {
+	SynthVerifyTree(dd, m_tree, 0);
+	SynthVerifyMlTable(dd, table);
+      }
+    }
+  }
+
+  if (verbosity > 1)
+    (void)fprintf(vis_stdout,"%s[%d] remainder\n", space, level);
+  r_tree_exist = 0;
+  if (r_tree) {
+    r_ref = 1;
+    r_tree_exist = 1;
+  } else if (comp_r_tree) {
+    r_tree = comp_r_tree;
+    r_ref = 1;
+    if (verbosity > 1) {
+      sprintf(comp_mess, "%s\t(C) : ", space);
+      SynthPrintZddTreeMessage(dd, r, comp_mess);
+    }
+  } else if (comp_d_tree) {
+    r_tree = (* factoring_func)(dd, table, r, level + 1,
+				&r_ref, NULL, 0, NULL, verbosity);
+    if (!r_tree) {
+      if (comp_q_tree != q_tree)
+	bdd_recursive_deref_zdd(dd, q_tree->node);
+      if (comp_d_tree != d_tree)
+	bdd_recursive_deref_zdd(dd, d_tree->node);
+      if (q_ref == 0)
+	SynthFreeMlTree(MlTree_Regular(q_tree), 1);
+      if (d_ref == 0)
+	SynthFreeMlTree(MlTree_Regular(d_tree), 1);
+      if (m_tree && m_ref == 0)
+	SynthFreeMlTree(MlTree_Regular(m_tree), 1);
+      return(NULL);
+    }
+    if (MlTree_IsComplement(r_tree)) {
+      r_tree = MlTree_Regular(r_tree);
+      comp_r_tree = r_tree;
+    } else
+      bdd_ref(r_tree->node);
+  } else {
+    if (Resubstitution) {
+      r_tree = (* factoring_func)(dd, table, r, level + 1,
+				  &r_ref, d_tree, 1, NULL, verbosity);
+      if (!r_tree && (bdd_read_reordered_field(dd) || noMemoryFlag == 1)) {
+	if (comp_q_tree != q_tree)
+	  bdd_recursive_deref_zdd(dd, q_tree->node);
+	if (comp_d_tree != d_tree)
+	  bdd_recursive_deref_zdd(dd, d_tree->node);
+	if (q_ref == 0)
+	  SynthFreeMlTree(MlTree_Regular(q_tree), 1);
+	if (d_ref == 0)
+	  SynthFreeMlTree(MlTree_Regular(d_tree), 1);
+	if (m_tree && m_ref == 0)
+	  SynthFreeMlTree(MlTree_Regular(m_tree), 1);
+	return(NULL);
+      }
+    }
+    if (!r_tree) {
+      r_tree = (* factoring_func)(dd, table, r, level + 1,
+				  &r_ref, NULL, 0, NULL, verbosity);
+      if (!r_tree) {
+	if (comp_q_tree != q_tree)
+	  bdd_recursive_deref_zdd(dd, q_tree->node);
+	if (comp_d_tree != d_tree)
+	  bdd_recursive_deref_zdd(dd, d_tree->node);
+	if (q_ref == 0)
+	  SynthFreeMlTree(MlTree_Regular(q_tree), 1);
+	if (d_ref == 0)
+	  SynthFreeMlTree(MlTree_Regular(d_tree), 1);
+	if (m_tree && m_ref == 0)
+	  SynthFreeMlTree(MlTree_Regular(m_tree), 1);
+	return(NULL);
+      }
+    } else {
+      if (r != one && r != zero)
+	SynthSetSharedFlag(dd, d_tree);
+    }
+    if (MlTree_IsComplement(r_tree)) {
+      r_tree = MlTree_Regular(r_tree);
+      comp_r_tree = r_tree;
+    } else
+      bdd_ref(r_tree->node);
+  }
+  if (RemainderComplement) {
+    tmp_tree = r_tree;
+    r_tree = SynthCheckAndMakeComplement(dd, table, r_tree, &comp_flag,
+					 verbosity);
+    if (!r_tree) {
+      if (comp_q_tree != q_tree)
+	bdd_recursive_deref_zdd(dd, q_tree->node);
+      if (comp_d_tree != d_tree)
+	bdd_recursive_deref_zdd(dd, d_tree->node);
+      if (comp_r_tree != tmp_tree)
+	bdd_recursive_deref_zdd(dd, tmp_tree->node);
+      if (q_ref == 0)
+	SynthFreeMlTree(MlTree_Regular(q_tree), 1);
+      if (d_ref == 0)
+	SynthFreeMlTree(MlTree_Regular(d_tree), 1);
+      if (r_ref == 0)
+	SynthFreeMlTree(MlTree_Regular(tmp_tree), 1);
+      if (m_tree && m_ref == 0)
+	SynthFreeMlTree(MlTree_Regular(m_tree), 1);
+      return(NULL);
+    } else if (r_tree != tmp_tree) {
+      if (comp_flag)
+	comp_r_tree = r_tree;
+      r_ref = 1;
+    }
+  }
+
+  if ((!q_tree_exist) && (!comp_q_tree))
+    bdd_recursive_deref_zdd(dd, q_tree->node);
+  if ((!d_tree_exist) && (!comp_d_tree))
+    bdd_recursive_deref_zdd(dd, d_tree->node);
+  if ((!r_tree_exist) && (!comp_r_tree))
+    bdd_recursive_deref_zdd(dd, r_tree->node);
+
+  if (bring) {
+    tree = bring;
+    tree->leaf = 0;
+    tree->q = q_tree;
+    tree->d = d_tree;
+    tree->r = r_tree;
+    if (comp_q_tree)
+      tree->q_comp = 1;
+    if (comp_d_tree)
+      tree->d_comp = 1;
+    if (comp_r_tree)
+      tree->r_comp = 1;
+    tree->q_ref = q_ref;
+    tree->d_ref = d_ref;
+    tree->r_ref = r_ref;
+    if (UseMtree && m_tree && m_ref == 0) {
+      MlTree_Regular(m_tree)->r = tree;
+      if (m_tree->r->id == 0) {
+	assert(0);
+	/*
+	if (!SynthUseCandidate(table, dd, m_tree, verbosity)) {
+	  SynthFreeMlTree(MlTree_Regular(m_tree), 1);
+	  return(NULL);
+	}
+	*/
+      }
+    }
+    if (verbosity > 1)
+      SynthPrintMlTreeMessage(dd, tree, message);
+    if (VerifyTreeMode) {
+      SynthVerifyTree(dd, tree, 0);
+      SynthVerifyMlTable(dd, table);
+    }
+    return(tree);
+  }
+
+  tree = SynthFindOrCreateMlTree(table, dd, f, 0, 0, ref, verbosity);
+  if (!tree) {
+    if (q_ref == 0)
+      SynthFreeMlTree(MlTree_Regular(q_tree), 1);
+    if (d_ref == 0)
+      SynthFreeMlTree(MlTree_Regular(d_tree), 1);
+    if (r_ref == 0)
+      SynthFreeMlTree(MlTree_Regular(r_tree), 1);
+    if (m_tree && m_ref == 0)
+      SynthFreeMlTree(MlTree_Regular(m_tree), 1);
+    return(NULL);
+  }
+  if (*ref == 1)
+    (void)fprintf(vis_stdout, "** synth warning: May be duplicate.\n");
+  tree->q = q_tree;
+  tree->d = d_tree;
+  tree->r = r_tree;
+  if (comp_q_tree)
+    tree->q_comp = 1;
+  if (comp_d_tree)
+    tree->d_comp = 1;
+  if (comp_r_tree)
+    tree->r_comp = 1;
+  tree->q_ref = q_ref;
+  tree->d_ref = d_ref;
+  tree->r_ref = r_ref;
+  if (UseMtree && m_tree && m_ref == 0) {
+    MlTree_Regular(m_tree)->r = tree;
+    if (m_tree->r->id == 0) {
+      assert(0);
+      /*
+      if (!SynthUseCandidate(table, dd, m_tree, verbosity)) {
+	SynthFreeMlTree(MlTree_Regular(tree), 1);
+	SynthFreeMlTree(MlTree_Regular(m_tree), 1);
+	return(NULL);
+      }
+      */
+    }
+  }
+  if (verbosity > 1)
+    SynthPrintMlTreeMessage(dd, tree, message);
+  SynthPutMlTreeInList(dd, tree, 0);
+  if (VerifyTreeMode) {
+    SynthVerifyTree(dd, tree, 0);
+    SynthVerifyMlTable(dd, table);
+  }
+  return(tree);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Counts the number of literals of a leaf node.]
+
+  Description [Counts the number of literals of a leaf node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+CountZddLeafLiterals(bdd_manager *dd,
+		     bdd_node *node)
+{
+  int	i, *support;
+  int	count = 0;
+  int	sizeZ = bdd_num_zdd_vars(dd);
+
+  support = ALLOC(int, sizeZ);
+  if (!support)
+    return(-1);
+  (void)memset((void *)support, 0, sizeof(int) * sizeZ);
+  SynthZddSupportStep(bdd_regular(node), support);
+  SynthZddClearFlag(bdd_regular(node));
+  for (i = 0; i < sizeZ; i++) {
+    if (support[i])
+      count++;
+  }
+  FREE(support);
+  return(count);
+}
Index: vis_dev/vis-2.3/src/synth/synthSynth.c
===================================================================
--- vis_dev/vis-2.3/src/synth/synthSynth.c	(revision 14)
+++ vis_dev/vis-2.3/src/synth/synthSynth.c	(revision 14)
@@ -0,0 +1,770 @@
+/**CFile***********************************************************************
+
+  FileName    [synthSynth.c]
+
+  PackageName [synth]
+
+  Synopsis    [Synthesis Algorithms]
+
+  Description [This file contains main routines that implement symbolic
+  factorization algorithms.]
+
+  SeeAlso     [synthDiv.c synthFactor.c synthGen.c synthOpt.c synthSimple.c]
+
+  Author      [Balakrishna Kumthekar, In-Ho Moon]
+
+  Copyright   [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty
+  about the suitability of this software for any purpose.  It is
+  presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "synthInt.h"
+
+static char rcsid[] UNUSED = "$Id: synthSynth.c,v 1.47 2005/04/23 14:37:51 jinh Exp $";
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int synthesizeNetwork(Ntk_Network_t *network, graph_t *partition, Fsm_Fsm_t *fsm, st_table *careBddTable, Synth_InfoData_t *synthInfo, int verbosity);
+static int IsPartitionValid(Ntk_Network_t *network, graph_t *partition);
+static array_t * GetCombOutputNameArray(Ntk_Network_t *network);
+static array_t * GetCombInputIdArray(Ntk_Network_t *network);
+static bdd_node ** GetBddArray(Mvf_Function_t *combMvfs);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Initialize the info data structure.]
+
+  Description [Initialize the info data structure. See the documentation for
+  CommandSynthesizeNetwork for the meaning of the various fields.]
+
+  SideEffects [None]
+
+  SeeAlso [Synth_FreeInfo]
+
+******************************************************************************/
+Synth_InfoData_t *
+Synth_InitializeInfo(int factoring,
+		     int divisor,
+		     int unreachDC,
+		     int reordering,
+		     int trySharing,
+		     int realign,
+		     char *filehead,
+		     char *prefix,
+		     boolean eqn)
+{
+
+  Synth_InfoData_t *synthInfo;
+
+  synthInfo = ALLOC(Synth_InfoData_t, 1);
+  if (!synthInfo) {
+    (void) fprintf(vis_stderr,
+		   "** synth error: Could not initialize info structure.\n");
+    return NIL(Synth_InfoData_t);
+  }
+  synthInfo->factoring = factoring;
+  synthInfo->divisor = divisor;
+  synthInfo->unreachDC = unreachDC;
+  synthInfo->reordering = reordering;
+  synthInfo->trySharing = trySharing;
+  synthInfo->realign = realign;
+  synthInfo->filehead = filehead;
+  synthInfo->prefix = prefix;
+  synthInfo->eqn = eqn;
+  return synthInfo;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Free info data.]
+
+  Description [Free Info data.]
+
+  SideEffects [None]
+
+  SeeAlso [Synth_InitializeInfo]
+
+******************************************************************************/
+void
+Synth_FreeInfo(Synth_InfoData_t *synthInfo)
+{
+  FREE(synthInfo);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Synthesize a network.]
+
+  Description [Synthesize a network. Here a major assumption is that, if the
+  network is sequential, and an FSM is already hooked to the network, then the
+  partition field of the FSM and that of the network are isomorphic.]
+
+  SideEffects [If an FSM (in case of a sequential design) or the circuit
+  partition does not already exist in the network, they are created and hooked
+  to the network. However, they are freed at the end of this procedure. ]
+
+  SeeAlso [Synth_SynthesizeFsm]
+
+******************************************************************************/
+int
+Synth_SynthesizeNetwork(Ntk_Network_t *network,
+			graph_t *partition,
+			st_table *careTable,
+			Synth_InfoData_t *synthInfo,
+			int verbosity)
+{
+  graph_t *newPartition = NIL(graph_t);
+  Fsm_Fsm_t *fsm = NIL(Fsm_Fsm_t);
+  st_table *careBddTable;
+  int status;
+  int createdPart = 0;
+  int createdFsm = 0;
+  int ntkIsSeq = 1;
+
+  if (bdd_get_package_name() != CUDD) {
+    (void) fprintf(vis_stderr,
+  "** synth error: The synthesis package can be used only with CUDD package\n");
+    (void) fprintf(vis_stderr,
+		   "** synth error: Please link with the CUDD package\n");
+    return 0;
+  }
+  if (partition == NIL(graph_t)) {
+    newPartition = (graph_t *) Ntk_NetworkReadApplInfo(network, 
+						       PART_NETWORK_APPL_KEY);
+    createdPart = 0; /* Using partition of the network. */
+    if (newPartition == NIL(graph_t) || 
+	(!IsPartitionValid(network,newPartition))) {
+      newPartition = Part_NetworkCreatePartition(network, 
+						 NIL(Hrc_Node_t),
+						 "dummy", (lsList) 0, 
+						 (lsList) 0, NIL(mdd_t),
+						 Part_InOut_c,
+						 (lsList) 0, 
+						 FALSE, FALSE, TRUE);
+      if (newPartition == NIL(graph_t)) {
+	(void) fprintf(vis_stderr,"** synth error: Could not create an InOut");
+	(void) fprintf(vis_stderr,"partition.\n");
+	return 0;
+      }
+      createdPart = 1; /* Using new partition */
+    }
+  } else {
+    if (IsPartitionValid(network,partition)) {
+      newPartition = partition;
+      createdPart = 2; /* Using the partition provided. */
+    } else {
+      newPartition = Part_NetworkCreatePartition(network, 
+						 NIL(Hrc_Node_t),
+						 "dummy", (lsList) 0, 
+						 (lsList) 0, NIL(mdd_t),
+						 Part_InOut_c,
+						 (lsList) 0, 
+						 FALSE, FALSE, TRUE);
+      if (newPartition == NIL(graph_t)) {
+	(void) fprintf(vis_stderr,"** synth error: Could not create an InOut");
+	(void) fprintf(vis_stderr,"partition.\n");
+	return 0;
+      }
+      createdPart = 1;    
+    }
+  }
+
+
+  if(!Ntk_NetworkReadNumLatches(network)) {
+    (void) fprintf(vis_stdout, "** synth info: No latches present in the ");
+    (void) fprintf(vis_stdout, "current network.\n");
+    (void) fprintf(vis_stdout,
+		   "** synth info: Proceeding with combinational synthesis.\n");
+    ntkIsSeq = 0;
+  }
+
+  if (ntkIsSeq) {
+    switch (createdPart) {
+    case 0:
+      /* Check if there is already an Fsm attached to 
+       * the network.
+       */
+      fsm = (Fsm_Fsm_t *) Ntk_NetworkReadApplInfo(network, 
+						  FSM_NETWORK_APPL_KEY);
+      if (fsm == NIL(Fsm_Fsm_t)) {
+	fsm = Fsm_FsmCreateFromNetworkWithPartition(network, 
+						    NIL(graph_t));
+	if (fsm == NIL(Fsm_Fsm_t)) {
+	  (void) fprintf(vis_stderr,"** synth error: Could not create ");
+	  (void) fprintf(vis_stderr,"an Fsm\n");
+	  goto endgame;
+	}
+	createdFsm = 1;
+      } else {
+	createdFsm = 0;
+      }
+      break;
+    case 1:
+    case 2:
+      fsm = Fsm_FsmCreateFromNetworkWithPartition(network,
+				  Part_PartitionDuplicate(newPartition));
+
+      if (fsm == NIL(Fsm_Fsm_t)) {
+	(void) fprintf(vis_stderr,"** synth error: Could not create ");
+	(void) fprintf(vis_stderr,"an Fsm\n");
+	goto endgame;
+      }
+      createdFsm = 1;
+      break;
+    }
+  }
+
+  careBddTable = NIL(st_table);
+  if (careTable != NIL(st_table)) {
+    mdd_t *mddTemp;
+    bdd_node *ddNode;
+    char *name;
+    st_generator *stGen;
+
+    careBddTable = st_init_table(strcmp, st_strhash);
+    st_foreach_item(careTable,stGen,&name,&mddTemp) {
+      ddNode = bdd_extract_node_as_is(mddTemp);
+      st_insert(careBddTable,name,(char *)ddNode);
+    }
+  }
+  if (fsm)
+    status = synthesizeNetwork(network, newPartition,
+			       fsm, careBddTable, synthInfo,
+			       verbosity);
+  else
+    status = synthesizeNetwork(network,newPartition,
+			       NIL(Fsm_Fsm_t), careBddTable,
+			       synthInfo, verbosity);
+
+  if (careBddTable)
+    st_free_table(careBddTable);
+  if (createdPart == 1)
+    Part_PartitionFree(newPartition);
+  if (createdFsm == 1)
+    Fsm_FsmFree(fsm);
+
+  return status;
+
+ endgame:
+  if (createdPart == 1)
+    Part_PartitionFree(newPartition);
+  if (createdFsm == 1)
+    Fsm_FsmFree(fsm);
+
+  return 0;
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Synthesize an FSM.]
+
+  Description [Synthesize an FSM. This procedure can be used if the default FSM
+  attached to the network is different from the one that needs to be
+  synthesized.]
+
+  SideEffects [None]
+
+  SeeAlso [Synth_SynthesizeNetwork]
+
+******************************************************************************/
+int
+Synth_SynthesizeFsm(Fsm_Fsm_t *fsm,
+		    st_table *careTable,
+		    Synth_InfoData_t *synthInfo,
+		    int verbosity)
+{
+  Ntk_Network_t *network;
+  graph_t *partition;
+  st_table *careBddTable;
+  int status;
+
+  network = Fsm_FsmReadNetwork(fsm);
+  partition = Fsm_FsmReadPartition(fsm);
+
+  careBddTable = NIL(st_table);
+  if (careTable != NIL(st_table)) {
+    mdd_t *mddTemp;
+    bdd_node *ddNode;
+    char *name;
+    st_generator *stGen;
+
+    careBddTable = st_init_table(strcmp, st_strhash);
+    st_foreach_item(careTable,stGen,&name,&mddTemp) {
+      ddNode = bdd_extract_node_as_is(mddTemp);
+      st_insert(careBddTable,name,(char *)ddNode);
+    }
+  }
+    
+  status = synthesizeNetwork(network,partition,fsm,careBddTable,synthInfo,
+			     verbosity);
+  if (careBddTable)
+    st_free_table(careBddTable);
+
+  return status;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Core function of Synth_SynthesizeNetwork.]
+
+  Description [Core function of Synth_SynthesizeNetwork and
+  Synth_SynthesizeFsm.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static int
+synthesizeNetwork(Ntk_Network_t *network,
+		  graph_t *partition,
+		  Fsm_Fsm_t *fsm,
+		  st_table *careBddTable,
+		  Synth_InfoData_t *synthInfo,
+		  int verbosity)
+{
+  bdd_manager *ddManager = (bdd_manager *) Ntk_NetworkReadMddManager(network);
+  int i, numOut;
+  int *initStates = NIL(int);
+  Mvf_Function_t *combMvfs;
+  array_t *inputIds, *combOutNamesArray;
+  bdd_node **combOutBdds, *ddTemp;
+  bdd_node *unReachable = NIL(bdd_node), *reachable = NIL(bdd_node);
+  bdd_node **combUpperBdds;
+  bdd_node *initBdd = NIL(bdd_node), *temp;
+  char **combOutNames;
+  char *str;
+  int realign_bdd, realign_zdd;
+  Fsm_RchType_t reachMethod;
+
+  /* Save current values of realignment flags. */
+  realign_zdd = bdd_zdd_realignment_enabled(ddManager);
+  realign_bdd = bdd_realignment_enabled(ddManager);
+
+  if (synthInfo->reordering == 1) {
+    if (synthInfo->realign)
+      bdd_zdd_realign_enable(ddManager);
+    else
+      bdd_zdd_realign_disable(ddManager);
+    bdd_realign_disable(ddManager);
+  } else if (synthInfo->reordering == 2) {
+    bdd_zdd_realign_disable(ddManager);
+    if (synthInfo->realign)
+      bdd_realign_enable(ddManager);
+    else
+      bdd_realign_disable(ddManager);
+  } else {
+    bdd_zdd_realign_disable(ddManager);
+    bdd_realign_disable(ddManager);
+  }
+
+  /* Get the names of the combinational outputs, i.e, next state functions
+   * as well as primary outputs. In VIS even latch initial inputs are
+   * considered combinational outputs. Since, we support only blif files,
+   * latch initial inputs are not present in combOutNamesArray.
+   */
+  combOutNamesArray = GetCombOutputNameArray(network);
+  if (combOutNamesArray == NIL(array_t)) {
+    if (realign_zdd == 1)
+      bdd_zdd_realign_enable(ddManager);
+    else
+      bdd_zdd_realign_disable(ddManager);
+    if (realign_bdd == 1)
+      bdd_realign_enable(ddManager);
+    else
+      bdd_realign_disable(ddManager);
+    return 0;
+  }
+  /* Get the array of combinational inputs, i.e., primary inputs, 
+   * present state variables.
+   */
+  inputIds = GetCombInputIdArray(network);
+  if (inputIds == NIL(array_t)) {
+    array_free(combOutNamesArray);
+    /* Restore values of realignment flags. */
+    if (realign_zdd == 1)
+      bdd_zdd_realign_enable(ddManager);
+    else
+      bdd_zdd_realign_disable(ddManager);
+    if (realign_bdd == 1)
+      bdd_realign_enable(ddManager);
+    else
+      bdd_realign_disable(ddManager);
+    return 0;
+  }
+  /* Compute the Bdds */
+  combMvfs = Part_PartitionBuildFunctions(partition,combOutNamesArray,
+					  inputIds,NIL(mdd_t));
+  combOutBdds = (bdd_node **) GetBddArray(combMvfs);
+  if (combOutBdds == NIL(bdd_node *)) {
+    array_free(combOutNamesArray);
+    array_free(inputIds);
+    Mvf_FunctionArrayFree(combMvfs);
+    if (realign_zdd == 1)
+      bdd_zdd_realign_enable(ddManager);
+    else
+      bdd_zdd_realign_disable(ddManager);
+    if (realign_bdd == 1)
+      bdd_realign_enable(ddManager);
+    else
+      bdd_realign_disable(ddManager);
+    return 0;
+  }
+  Mvf_FunctionArrayFree(combMvfs);
+
+  numOut = array_n(combOutNamesArray); 
+  combOutNames = ALLOC(char *, numOut);
+  if (combOutNames == NIL(char *)) {
+    (void) fprintf(vis_stderr,"** synth error: Could not allocate memory\n");
+    array_free(combOutNamesArray);
+    array_free(inputIds);
+
+    for (i = 0; i < numOut; i++) {
+      bdd_recursive_deref(ddManager,combOutBdds[i]);
+    }
+    FREE(combOutBdds);
+    if (realign_zdd == 1)
+      bdd_zdd_realign_enable(ddManager);
+    else
+      bdd_zdd_realign_disable(ddManager);
+    if (realign_bdd == 1)
+      bdd_realign_enable(ddManager);
+    else
+      bdd_realign_disable(ddManager);
+    return 0;
+  }
+  arrayForEachItem(char *, combOutNamesArray, i, str) {
+    combOutNames[i] = str;
+  }
+  array_free(combOutNamesArray);
+
+
+  combUpperBdds = ALLOC(bdd_node *,numOut);
+  /* Initialize the upper bound to be the lower bound */
+  for (i = 0; i < numOut; i++) {
+    bdd_ref(combUpperBdds[i] = combOutBdds[i]);
+  }
+
+  if (fsm) {
+    mdd_t *initMdd;
+    /* Duplicate copy of initial States is returned */
+    initMdd = Fsm_FsmComputeInitialStates(fsm);
+    initBdd = (bdd_node *)bdd_extract_node_as_is(initMdd);
+    bdd_ref(initBdd);
+    mdd_free(initMdd);
+
+    if (synthInfo->unreachDC) {
+      mdd_t *reachStates;
+
+      (void) fprintf(vis_stdout,
+		     "** synth info: Using unreachable states as dont cares\n");
+      if (synthInfo->unreachDC == 1) {
+	reachMethod = Fsm_Rch_Bfs_c;
+      } else if (synthInfo->unreachDC == 2) {
+	reachMethod = Fsm_Rch_Hd_c;
+      } else if (synthInfo->unreachDC == 3) {
+	reachMethod = Fsm_Rch_Oa_c;
+      } else {
+	reachMethod = Fsm_Rch_Default_c;
+      }
+      reachStates = Fsm_FsmComputeReachableStates(fsm,0,0,0,0,
+						  0,0,1000,reachMethod,
+						  0,0,NIL(array_t), FALSE,
+						  NIL(array_t));
+      reachable = (bdd_node *)bdd_extract_node_as_is(reachStates);
+      bdd_ref(reachable);
+      unReachable = bdd_not_bdd_node(reachable);
+      bdd_ref(unReachable);
+      mdd_free(reachStates);
+    }
+  }
+
+  if (careBddTable == NIL(st_table)) {
+    if (fsm && synthInfo->unreachDC) {
+      /* Upper bound = LowerBould + DC */
+      for (i = 0; i < numOut; i++) {
+	bdd_recursive_deref(ddManager,combUpperBdds[i]);
+	combUpperBdds[i] = bdd_bdd_or(ddManager,combOutBdds[i],
+				      unReachable);
+	bdd_ref(combUpperBdds[i]);
+      }
+      
+      /* LowerBound = OutputFuns . Care */
+      bdd_recursive_deref(ddManager,unReachable);
+      for (i = 0; i < numOut; i++) {
+	bdd_node *temp;
+	temp = bdd_bdd_and(ddManager,combOutBdds[i],reachable);
+	bdd_ref(temp);
+	bdd_recursive_deref(ddManager,combOutBdds[i]);
+	combOutBdds[i] = temp;
+      }
+      bdd_recursive_deref(ddManager,reachable);
+    }
+  } else { /* Use the cares supplied. */
+    if (fsm && synthInfo->unreachDC) {
+      bdd_recursive_deref(ddManager,unReachable);
+    }
+    for (i = 0; i < numOut; i++) {
+      bdd_node *dontCare,*care;
+
+      if (st_lookup(careBddTable,combOutNames[i],&ddTemp) == 1) {
+	if (fsm && synthInfo->unreachDC) {
+	  bdd_ref(care = bdd_bdd_or(ddManager,ddTemp,reachable));
+	} else {
+	  bdd_ref(care = ddTemp);
+	}
+	bdd_ref(dontCare = bdd_not_bdd_node(care));
+	
+	/* Update the upper bound for each combinational output */
+	bdd_recursive_deref(ddManager,combUpperBdds[i]);
+	combUpperBdds[i] = bdd_bdd_or(ddManager,combOutBdds[i],dontCare);
+	bdd_ref(combUpperBdds[i]);
+	bdd_recursive_deref(ddManager,dontCare);
+	
+	/* Update the lower bound */
+	bdd_ref(temp = bdd_bdd_and(ddManager,combOutBdds[i],care));
+	bdd_recursive_deref(ddManager,combOutBdds[i]);
+	bdd_recursive_deref(ddManager,care);
+	combOutBdds[i]=temp;
+      }
+    }
+  }
+
+  if (fsm) {
+    bdd_t *bddVar, *bddTInit, *bddTtemp;
+    int id, i = 0;
+    lsGen gen;
+    Ntk_Node_t *node;
+    bdd_node *logicZero = bdd_read_logic_zero(ddManager);
+
+    bddTInit = bdd_construct_bdd_t(ddManager,initBdd);
+    initStates = ALLOC(int, Ntk_NetworkReadNumLatches(network));
+    Ntk_NetworkForEachLatch(network,gen,node) {
+      id = Ntk_NodeReadMddId(node);
+      bddVar = bdd_get_variable(ddManager,id);
+      bddTtemp = bdd_cofactor(bddTInit, bddVar);
+      if (bdd_extract_node_as_is(bddTtemp) == logicZero) 
+	initStates[i] = 0;
+      else
+	initStates[i] = 1;
+      i++;
+      bdd_free(bddVar);
+      bdd_free(bddTtemp);
+    }
+    /* This will free initBdd too. So, no need to deref it again.  */
+    bdd_free(bddTInit);
+  }
+
+  SynthMultiLevelOptimize(network,combOutBdds,combUpperBdds,
+			  combOutNames, initStates,synthInfo,
+			  verbosity);
+
+  /* Clean up. */
+  if (fsm) {
+    FREE(initStates);
+  }
+  for (i = 0; i < numOut; i++) {
+    bdd_recursive_deref(ddManager,combUpperBdds[i]);
+    bdd_recursive_deref(ddManager,combOutBdds[i]);
+  }
+  FREE(combOutNames);
+  FREE(combOutBdds);
+  FREE(combUpperBdds);
+  array_free(inputIds);
+  if (realign_zdd == 1)
+    bdd_zdd_realign_enable(ddManager);
+  else
+    bdd_zdd_realign_disable(ddManager);
+  if (realign_bdd == 1)
+    bdd_realign_enable(ddManager);
+  else
+    bdd_realign_disable(ddManager);
+  return(1);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether partition is valid.]
+
+  Description [Checks whether partition is valid. The condition is that the
+  given partition should have a vertex for each combinational output (PO and
+  NS) and combinational input (PI and PS) of the network. This is necessary to
+  completely synthesize the network.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static int
+IsPartitionValid(Ntk_Network_t *network,
+		 graph_t *partition)
+{
+  Ntk_Node_t *node;
+  lsGen gen;
+  char *name;
+
+  Ntk_NetworkForEachCombOutput(network, gen, node) {
+    name = Ntk_NodeReadName(node);
+    if(Part_PartitionFindVertexByName(partition, name) == NIL(vertex_t)) {
+      return(0);
+    }
+  }
+  Ntk_NetworkForEachCombInput(network, gen, node) {
+    name = Ntk_NodeReadName(node);
+    if(Part_PartitionFindVertexByName(partition, name) == NIL(vertex_t)) {
+      return(0);
+    }
+  }
+
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns an array containing all combinational output names.]
+
+  Description [Returns an array containing all combinational output names.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static array_t *
+GetCombOutputNameArray(Ntk_Network_t *network)
+{
+  array_t *outputFunNames;
+  lsGen gen;
+  Ntk_Node_t *node;
+    
+  outputFunNames = array_alloc(char *, 0);
+  if (outputFunNames == NIL(array_t)) {
+    (void) fprintf(vis_stderr,"** synth error: Could not allocate space ");
+    (void) fprintf(vis_stderr,"for the names of combinational outputs\n");
+    return NIL(array_t);
+  }
+  Ntk_NetworkForEachCombOutput(network, gen, node){
+    if (Ntk_NodeTestIsLatchInitialInput(node))
+      continue;
+    array_insert_last(char *, outputFunNames, 
+		      Ntk_NodeReadName(node));
+  }
+  return outputFunNames;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns an array containing mdd-ids of all combinational inputs.]
+
+  Description [Returns an array containing mdd-ids of all combinational inputs.]
+
+  SideEffects []
+
+  SeeAlso []
+
+******************************************************************************/
+static array_t *
+GetCombInputIdArray(Ntk_Network_t *network)
+{
+  array_t *inputIds;
+  lsGen gen;
+  Ntk_Node_t *node;
+    
+  inputIds = array_alloc(int, 0);
+  if (inputIds == NIL(array_t)) {
+    (void) fprintf(vis_stderr,"** synth error: Could not allocate space ");
+    (void) fprintf(vis_stderr,"for an array of ids of comb. inputs\n");
+    return NIL(array_t);
+  }
+  Ntk_NetworkForEachCombInput(network, gen, node){
+    array_insert_last(int, inputIds, Ntk_NodeReadMddId(node));
+  }
+  return inputIds;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns array of bdds of combinational outputs.]
+
+  Description [Returns array of bdds of combinational outputs.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static bdd_node **
+GetBddArray(Mvf_Function_t *combMvfs)
+{
+  bdd_node **bddArray;
+  Mvf_Function_t *mvf;
+  int i;
+
+  bddArray = ALLOC(bdd_node *,array_n(combMvfs));
+  if (bddArray == NIL(bdd_node *)) {
+    (void) fprintf(vis_stderr,"** synth error: Could not allocate space ");
+    (void) fprintf(vis_stderr,"for an array of Bdd nodes.\n");
+    return NIL(bdd_node *);
+  }
+  arrayForEachItem(Mvf_Function_t *, combMvfs, i, mvf) {
+    mdd_t *mddTemp;
+
+    mddTemp = array_fetch(mdd_t *, mvf, 1);
+    bddArray[i] = (bdd_node *) bdd_extract_node_as_is(mddTemp);
+    bdd_ref(bddArray[i]);
+  }
+  return bddArray;
+}
+
Index: vis_dev/vis-2.3/src/synth/synthUtil.c
===================================================================
--- vis_dev/vis-2.3/src/synth/synthUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/synth/synthUtil.c	(revision 14)
@@ -0,0 +1,797 @@
+/**CFile***********************************************************************
+
+  FileName    [synthUtil.c]
+
+  PackageName [synth]
+
+  Synopsis    [Functions to get or to print some information.]
+
+  Author      [In-Ho Moon, Balakrishna Kumthekar]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "synthInt.h"
+
+static char rcsid[] UNUSED = "$Id: synthUtil.c,v 1.13 1998/08/19 22:51:49 mooni Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int GetChildTree(bdd_manager *dd, bdd_node *f, char *eq);
+static int GetChildMlTree(bdd_manager *dd, MlTree *tree, char *eq);
+static bdd_node	* FindNodeWithIndex(bdd_node *node, int index);
+static void GetZddCoverWithNameRecur(Ntk_Network_t *net, bdd_manager *dd, bdd_node *node, char *cover);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the equation form of a node with internal names.]
+
+  Description [Prints the equation form of a node with internal names.
+  If the string length is bigger than MAX_EQ_LEN, the string is truncated.]
+
+  SideEffects []
+
+  SeeAlso     [SynthPrintZddTreeMessage]
+
+******************************************************************************/
+void
+SynthPrintZddTree(bdd_manager *dd,
+		  bdd_node *f)
+{
+  char	eq[MAX_EQ_LEN];
+
+  GetChildTree(dd, f, eq);
+  fprintf(vis_stdout, "%s\n", eq);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the equation form of a node with internal names,
+  preceded by a message.]
+
+  Description [Prints the equation form of a node with internal names,
+  preceded by a message. If the string length is bigger than MAX_EQ_LEN,
+  the string is truncated.]
+
+  SideEffects []
+
+  SeeAlso     [SynthPrintMlTreeMessage]
+
+******************************************************************************/
+void
+SynthPrintZddTreeMessage(bdd_manager *dd,
+			 bdd_node *f,
+			 char *mess)
+{
+  char	eq[MAX_EQ_LEN];
+
+  GetChildTree(dd, f, eq);
+  fprintf(vis_stdout, "%s%s\n", mess, eq);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the equation form of a tree with internal names,
+  preceded by a message.]
+
+  Description [Prints the equation form of a tree with internal names,
+  preceded by a message. If the string length is bigger than MAX_EQ_LEN,
+  the string is truncated.]
+
+  SideEffects []
+
+  SeeAlso     [SynthPrintZddTreeMessage SynthPrintMlTreeWithName]
+
+******************************************************************************/
+void
+SynthPrintMlTreeMessage(bdd_manager *dd,
+			MlTree *tree,
+			char *mess)
+{
+  char	eq[MAX_EQ_LEN];
+
+  if (MlTree_IsComplement(tree)) {
+    tree = MlTree_Regular(tree);
+    GetChildMlTree(dd, tree, eq);
+    (void) fprintf(vis_stdout, "%s%s'\n", mess, eq);
+  } else {
+    GetChildMlTree(dd, tree, eq);
+    (void) fprintf(vis_stdout, "%s%s\n", mess, eq);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a multi-level tree recursively.]
+
+  Description [Frees a multi-level tree recursively. If the argument flag
+  is set to 0, it does not free recursively.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthFreeMlTree(MlTree *tree,
+		int flag)
+{
+  if (!tree)
+    return;
+
+  if (tree->ref) {
+    FREE(tree);
+    return;
+  }
+
+  if (tree->support)
+    FREE(tree->support);
+
+  if (flag && tree->leaf == 0) {
+    if (tree->q_ref == 0)
+      SynthFreeMlTree(tree->q, flag);
+    if (tree->d_ref == 0)
+      SynthFreeMlTree(tree->d, flag);
+    if (tree->r_ref == 0)
+      SynthFreeMlTree(tree->r, flag);
+  }
+
+  FREE(tree);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the equation form of a tree with original names
+  and preceded by a message.]
+
+  Description [Prints the equation form of a tree with original names
+  and preceded by a message. If the string length is bigger than
+  MAX_EQ_LEN, the string is truncated.]
+
+  SideEffects []
+
+  SeeAlso     [SynthPrintMlTreeMessage]
+
+******************************************************************************/
+void
+SynthPrintMlTreeWithName(Ntk_Network_t *net,
+			 bdd_manager *dd,
+			 MlTree *tree,
+			 char *mess)
+{
+  char	eq[MAX_EQ_LEN];
+
+  SynthGetChildMlTreeWithName(net, dd, tree, eq);
+  fprintf(vis_stdout, "%s%s\n", mess, eq);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the equation form of a tree with original names.]
+
+  Description [Gets the equation form of a tree with original names.]
+
+  SideEffects []
+
+  SeeAlso     [SynthGetChildMlTree]
+
+******************************************************************************/
+int
+SynthGetChildMlTreeWithName(Ntk_Network_t *net,
+			    bdd_manager *dd,
+			    MlTree *tree,
+			    char *eq)
+{
+  char		q_eq[MAX_EQ_LEN];
+  char		d_eq[MAX_EQ_LEN];
+  char		r_eq[MAX_EQ_LEN];
+  char		qd_eq[MAX_EQ_LEN];
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  bdd_node	*f;
+  int		flag;
+
+  f = tree->node;
+  if (tree->leaf) {
+    flag = SynthGetChildTreeWithName(net, dd, f, eq);
+    return(flag);
+  }
+
+  if (f == one) {
+    sprintf(eq, "one");
+    return(0);
+  } else if (f == zero) {
+    sprintf(eq, "zero");
+    return(0);
+  }
+
+  flag = SynthGetChildMlTreeWithName(net, dd, tree->q, q_eq);
+  if (tree->q_comp)
+    SynthMakeComplementString(q_eq);
+  if (flag)
+    return(1);
+  flag = SynthGetChildMlTreeWithName(net, dd, tree->d, d_eq);
+  if (tree->d_comp)
+    SynthMakeComplementString(d_eq);
+  if (flag)
+    return(1);
+  flag = SynthGetChildMlTreeWithName(net, dd, tree->r, r_eq);
+  if (tree->r_comp)
+    SynthMakeComplementString(r_eq);
+  if (flag)
+    return(1);
+
+  if (strcmp(q_eq, "one") == 0)
+    sprintf(qd_eq, "%s", d_eq);
+  else if (strcmp(q_eq, "zero") == 0)
+    sprintf(qd_eq, "zero");
+  else if (strcmp(d_eq, "one") == 0)
+    sprintf(qd_eq, "%s", q_eq);
+  else if (strcmp(d_eq, "zero") == 0)
+    sprintf(qd_eq, "zero");
+  else {
+    if (strlen(q_eq) + strlen(d_eq) + 1 > MAX_EQ_LEN) {
+      sprintf(eq, "%s", q_eq);
+      if (strlen(eq) == MAX_EQ_LEN - 1) {
+	eq[MAX_EQ_LEN - 2] = '#'; /* truncated */
+	eq[MAX_EQ_LEN - 1] = '\0';
+      } else {
+	eq[strlen(eq)] = '#'; /* truncated */
+	eq[strlen(eq) + 1] = '\0';
+      }
+      return(1);
+    }
+    sprintf(qd_eq, "%s%s", q_eq, d_eq);
+  }
+
+  if (strcmp(r_eq, "zero") == 0)
+    sprintf(eq, "%s", qd_eq);
+  else {
+    if (strlen(qd_eq) + strlen(r_eq) + 1 > MAX_EQ_LEN) {
+      sprintf(eq, "%s", qd_eq);
+      if (strlen(eq) == MAX_EQ_LEN - 1) {
+	eq[MAX_EQ_LEN - 2] = '#'; /* truncated */
+	eq[MAX_EQ_LEN - 1] = '\0';
+      } else {
+	eq[strlen(eq)] = '#'; /* truncated */
+	eq[strlen(eq) + 1] = '\0';
+      }
+      return(1);
+    }
+    sprintf(eq, "(%s + %s)", qd_eq, r_eq);
+  }
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the equation form of a tree which is a leaf node with
+  original names.]
+
+  Description [Gets the equation form of a tree which is a leaf node with
+  original names.]
+
+  SideEffects []
+
+  SeeAlso     [SynthGetChildTree]
+
+******************************************************************************/
+int
+SynthGetChildTreeWithName(Ntk_Network_t *net,
+			  bdd_manager *dd,
+			  bdd_node *f,
+			  char *eq)
+{
+  char		left[MAX_EQ_LEN];
+  char		right[MAX_EQ_LEN];
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  int		id, comp;
+  char		name[MAX_NAME_LEN];
+  int		flag;
+
+  if (f == one) {
+    sprintf(eq, "one");
+    return(0);
+  } else if (f == zero) {
+    sprintf(eq, "zero");
+    return(0);
+  }
+
+  flag = SynthGetChildTreeWithName(net, dd, bdd_bdd_T(f), left);
+  if (flag)
+    return(1);
+  flag = SynthGetChildTreeWithName(net, dd, bdd_bdd_E(f), right);
+  if (flag)
+    return(1);
+
+  id = bdd_node_read_index(f);
+  comp = id & 0x1;
+  id = id >> 1;
+
+  sprintf(name, "%s", Ntk_NodeReadName(Ntk_NetworkFindNodeByMddId(net, id)));
+
+  if (comp)
+    strcat(name, "'");
+
+  if (strcmp(left, "one") == 0) {
+    if (strcmp(right, "zero") == 0)
+      sprintf(eq, "%s", name);
+    else {
+      if (strlen(right) + strlen(name) + 6 > MAX_EQ_LEN) {
+	sprintf(eq, "%s", right);
+	if (strlen(eq) == MAX_EQ_LEN - 1) {
+	  eq[MAX_EQ_LEN - 2] = '#'; /* truncated */
+	  eq[MAX_EQ_LEN - 1] = '\0';
+	} else {
+	  eq[strlen(eq)] = '#'; /* truncated */
+	  eq[strlen(eq) + 1] = '\0';
+	}
+	return(1);
+      }
+      sprintf(eq, "(%s + %s)", name, right);
+    }
+  } else {
+    if (strcmp(right, "zero") == 0) {
+      if (strlen(left) + strlen(name) + 1 > MAX_EQ_LEN) {
+	sprintf(eq, "%s", left);
+	if (strlen(eq) == MAX_EQ_LEN - 1) {
+	  eq[MAX_EQ_LEN - 2] = '#'; /* truncated */
+	  eq[MAX_EQ_LEN - 1] = '\0';
+	} else {
+	  eq[strlen(eq)] = '#'; /* truncated */
+	  eq[strlen(eq) + 1] = '\0';
+	}
+	return(1);
+      }
+      sprintf(eq, "%s%s", name, left);
+    } else {
+      if (strlen(right) + strlen(left) + strlen(name) + 6 >
+	  MAX_EQ_LEN) {
+	sprintf(eq, "%s", right);
+	if (strlen(eq) == MAX_EQ_LEN - 1) {
+	  eq[MAX_EQ_LEN - 2] = '#'; /* truncated */
+	  eq[MAX_EQ_LEN - 1] = '\0';
+	} else {
+	  eq[strlen(eq)] = '#'; /* truncated */
+	  eq[strlen(eq) + 1] = '\0';
+	}
+	return(1);
+      }
+      sprintf(eq, "(%s%s + %s)", name, left, right);
+    }
+  }
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the original name of a primary node.]
+
+  Description [Gets the original name of a primary node. Return value
+  shows polarity; 0 means positive variable and 1 means negative.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+SynthGetPrimaryNodeName(Ntk_Network_t *net,
+			bdd_node *node,
+			char *name)
+{
+  int	id;
+  int	comp;
+  char	*ntk_name;
+
+  id = bdd_node_read_index(node);
+  comp = id % 2;
+  id = id >> 1;
+
+  ntk_name = Ntk_NodeReadName(Ntk_NetworkFindNodeByMddId(net, id));
+  sprintf(name, "%s", ntk_name);
+
+  return(comp);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the original name of a primary node with index.]
+
+  Description [Gets the original name of a primary node with index.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthGetPrimaryIndexName(Ntk_Network_t *net,
+			 int index,
+			 char *name)
+{
+  int	id;
+
+  id = index >> 1;
+  sprintf(name, "%s", Ntk_NodeReadName(Ntk_NetworkFindNodeByMddId(net, id)));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the equation form of a ZDD cover with original names.]
+
+  Description [Prints the equation form of a ZDD cover with original names.
+  If the string length is bigger than MAX_EQ_LEN, the string is truncated.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthPrintZddCoverWithName(Ntk_Network_t *net,
+			   bdd_manager *dd,
+			   bdd_node *node)
+{
+  char cover[MAX_EQ_LEN];
+
+  fprintf(vis_stdout, "cover =");
+  cover[0] = '\0';
+  GetZddCoverWithNameRecur(net, dd, node, cover);
+  fprintf(vis_stdout, "\n");
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Makes the complement name of a node name.]
+
+  Description [Makes the complement name of a node name.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthMakeComplementString(char *eq)
+{
+  int	len;
+
+  if (strcmp(eq, "zero") == 0) {
+    sprintf(eq, "one");
+    return;
+  } else if (strcmp(eq, "one") == 0) {
+    sprintf(eq, "zero");
+    return;
+  }
+  len = strlen(eq);
+  if (eq[len - 1] == '\'')
+    eq[len - 1] = '\0';
+  else {
+    if (len == MAX_EQ_LEN - 1) {
+      eq[len - 2] = '#'; /* truncated */
+      eq[len - 1] = '\'';
+    } else
+      strcat(eq, "'");
+  }
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Gets an equation form of a ZDD node.]
+
+  Description [Gets an equation form of a ZDD node. Returns 1 if
+  eq string is truncated, otherwise normally returns 0.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+GetChildTree(bdd_manager *dd,
+	     bdd_node *f,
+	     char *eq)
+{
+  char		left[MAX_EQ_LEN];
+  char		right[MAX_EQ_LEN];
+  char		tmp[MAX_NAME_LEN];
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  int		flag; /* truncated */
+
+  if (f == one) {
+    sprintf(eq, "one");
+    return(0);
+  } else if (f == zero) {
+    sprintf(eq, "zero");
+    return(0);
+  }
+
+  flag = GetChildTree(dd, bdd_bdd_T(f), left);
+  if (flag)
+    return(1);
+  flag = GetChildTree(dd, bdd_bdd_E(f), right);
+  if (flag)
+    return(1);
+
+  sprintf(tmp, "v%d", bdd_node_read_index(f));
+  if (strcmp(left, "one") == 0) {
+    if (strcmp(right, "zero") == 0)
+      sprintf(eq, "%s", tmp);
+    else {
+      if (strlen(right) + strlen(tmp) + 6 > MAX_EQ_LEN) {
+	sprintf(eq, "%s", right);
+	if (strlen(eq) == MAX_EQ_LEN - 1) {
+	  eq[MAX_EQ_LEN - 2] = '#'; /* truncated */
+	  eq[MAX_EQ_LEN - 1] = '\0';
+	} else {
+	  eq[strlen(eq)] = '#'; /* truncated */
+	  eq[strlen(eq) + 1] = '\0';
+	}
+	return(1);
+      }
+      sprintf(eq, "(%s + %s)", tmp, right);
+    }
+  } else {
+    if (strcmp(right, "zero") == 0) {
+      if (strlen(left) + strlen(tmp) + 1 > MAX_EQ_LEN) {
+	sprintf(eq, "%s", left);
+	if (strlen(eq) == MAX_EQ_LEN - 1) {
+	  eq[MAX_EQ_LEN - 2] = '#'; /* truncated */
+	  eq[MAX_EQ_LEN - 1] = '\0';
+	} else {
+	  eq[strlen(eq)] = '#'; /* truncated */
+	  eq[strlen(eq) + 1] = '\0';
+	}
+	return(1);
+      }
+      sprintf(eq, "%s%s", tmp, left);
+    } else {
+      if (strlen(right) + strlen(left) + strlen(tmp) + 6 > MAX_EQ_LEN) {
+	sprintf(eq, "%s", right);
+	if (strlen(eq) == MAX_EQ_LEN - 1) {
+	  eq[MAX_EQ_LEN - 2] = '#'; /* truncated */
+	  eq[MAX_EQ_LEN - 1] = '\0';
+	} else {
+	  eq[strlen(eq)] = '#'; /* truncated */
+	  eq[strlen(eq) + 1] = '\0';
+	}
+	return(1);
+      }
+      sprintf(eq, "(%s%s + %s)", tmp, left, right);
+    }
+  }
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the equation form of a tree with internal name.]
+
+  Description [Gets the equation form of a tree with internal name. Returns
+  1 if eq string is truncated, otherwise normally returns 0.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+GetChildMlTree(bdd_manager *dd,
+	       MlTree *tree,
+	       char *eq)
+{
+  char		q_eq[MAX_EQ_LEN];
+  char		d_eq[MAX_EQ_LEN];
+  char		r_eq[MAX_EQ_LEN];
+  char		qd_eq[MAX_EQ_LEN];
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  bdd_node	*f;
+  int		flag;
+
+  f = tree->node;
+  if (tree->leaf) {
+    flag = GetChildTree(dd, f, eq);
+    return(flag);
+  }
+
+  if (f == one) {
+    sprintf(eq, "one");
+    return(0);
+  } else if (f == zero) {
+    sprintf(eq, "zero");
+    return(0);
+  }
+
+  flag = GetChildMlTree(dd, tree->q, q_eq);
+  if (tree->q_comp)
+    SynthMakeComplementString(q_eq);
+  if (flag)
+    return(1);
+  flag = GetChildMlTree(dd, tree->d, d_eq);
+  if (tree->d_comp)
+    SynthMakeComplementString(d_eq);
+  if (flag)
+    return(1);
+  flag = GetChildMlTree(dd, tree->r, r_eq);
+  if (tree->r_comp)
+    SynthMakeComplementString(r_eq);
+  if (flag)
+    return(1);
+
+  if (strcmp(q_eq, "one") == 0)
+    sprintf(qd_eq, "%s", d_eq);
+  else if (strcmp(q_eq, "zero") == 0)
+    sprintf(qd_eq, "zero");
+  else if (strcmp(d_eq, "one") == 0)
+    sprintf(qd_eq, "%s", q_eq);
+  else if (strcmp(d_eq, "zero") == 0)
+    sprintf(qd_eq, "zero");
+  else {
+    if (strlen(q_eq) + strlen(d_eq) + 1 > MAX_EQ_LEN) {
+      sprintf(eq, "%s", q_eq);
+      if (strlen(eq) == MAX_EQ_LEN - 1) {
+	eq[MAX_EQ_LEN - 2] = '#'; /* truncated */
+	eq[MAX_EQ_LEN - 1] = '\0';
+      } else {
+	eq[strlen(eq)] = '#'; /* truncated */
+	eq[strlen(eq) + 1] = '\0';
+      }
+      return(1);
+    }
+    sprintf(qd_eq, "%s%s", q_eq, d_eq);
+  }
+
+  if (strcmp(r_eq, "zero") == 0)
+    sprintf(eq, "%s", qd_eq);
+  else {
+    if (strlen(qd_eq) + strlen(r_eq) + 1 > MAX_EQ_LEN) {
+      sprintf(eq, "%s", qd_eq);
+      if (strlen(eq) == MAX_EQ_LEN - 1) {
+	eq[MAX_EQ_LEN - 2] = '#'; /* truncated */
+	eq[MAX_EQ_LEN - 1] = '\0';
+      } else {
+	eq[strlen(eq)] = '#'; /* truncated */
+	eq[strlen(eq) + 1] = '\0';
+      }
+      return(1);
+    }
+    sprintf(eq, "(%s + %s)", qd_eq, r_eq);
+  }
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Finds a node that has the given index.]
+
+  Description [Finds a node that has the given index among the descendants
+  of the given node (this node included). If there exists a node with
+  the index, the node is returned, otherwise returns NULL.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static bdd_node	*
+FindNodeWithIndex(bdd_node *node,
+		  int index)
+{
+  bdd_node	*tmp;
+
+  if (bdd_is_constant(node))
+    return(NULL);
+  if (bdd_node_read_index(node) == index)
+    return(node);
+
+  tmp = FindNodeWithIndex(bdd_bdd_T(node), index);
+  if (tmp)
+    return(tmp);
+  return(FindNodeWithIndex(bdd_bdd_E(node), index));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the equation form of a ZDD cover with original names.]
+
+  Description [Gets an equation form of a ZDD cover with original names.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+GetZddCoverWithNameRecur(Ntk_Network_t *net,
+			 bdd_manager *dd,
+			 bdd_node *node,
+			 char *cover)
+{
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  int		len, index;
+  char		name[MAX_NAME_LEN], *varName;
+
+  if (node == zero)
+    return;
+
+  if (node == one) {
+    fprintf(vis_stdout, " + %s", cover);
+    return;
+  }
+
+  len = strlen(cover);
+  index = bdd_node_read_index(node);
+  varName = Ntk_NodeReadName(Ntk_NetworkFindNodeByMddId(net, index / 2));
+  if (index % 2 == 0)
+    sprintf(name, "%s", varName);
+  else
+    sprintf(name, "%s'", varName);
+  strcat(cover, name);
+  GetZddCoverWithNameRecur(net, dd, bdd_bdd_T(node), cover);
+  cover[len] = '\0';
+  GetZddCoverWithNameRecur(net, dd, bdd_bdd_E(node), cover);
+  cover[len] = '\0';
+}
+
+
Index: vis_dev/vis-2.3/src/synth/synthWrite.c
===================================================================
--- vis_dev/vis-2.3/src/synth/synthWrite.c	(revision 14)
+++ vis_dev/vis-2.3/src/synth/synthWrite.c	(revision 14)
@@ -0,0 +1,1962 @@
+/**CFile***********************************************************************
+
+  FileName    [synthWrite.c]
+
+  PackageName [synth]
+
+  Synopsis    [Functions to write blif file and equation file.]
+
+  Description []
+
+  Author      [In-Ho Moon, Balakrishna Kumthekar]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "synthInt.h"
+
+static char rcsid[] UNUSED = "$Id: synthWrite.c,v 1.43 2005/05/11 20:18:39 hhhan Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [Type to store a line of the truth table of a node.
+  The entire truth table is implemented as a linked list of
+  objects of this type.]
+
+  Description []
+
+  SeeAlso     []
+
+******************************************************************************/
+typedef struct TruthTableLine {
+  char *values;    /* string of 1, 0, and - */
+  struct TruthTableLine *next; /* pointer to next table line */
+} TruthTableLine;
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+static	char		*DefaultPrefix = "_n";
+static	char		*InternalNodePrefix;
+static	st_table	*NodeNameTable; /* to keep all node names for
+					 * primary input, primary output 
+					 * latch input and output
+					 */
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void WriteMlBlif(Ntk_Network_t *net, bdd_manager *dd, MlTree *tree, FILE *fout, int no, bdd_node **ofuncs, int *oflags, int top_flag, int verbosity);
+static void WriteLeafMlBlif(Ntk_Network_t *net, bdd_manager *dd, MlTree *tree, FILE *fout, int no, bdd_node **ofuncs, int *oflags, int top_flag, int verbosity);
+static void WriteBlifBinary(bdd_manager *dd, bdd_node *node, char *name, FILE *fout, int *support);
+static void WriteEqnOfTree(FILE *fout, Ntk_Network_t *net, bdd_manager *dd, MlTree *tree, bdd_node **ofuncs);
+static int GetEqnOfTree(Ntk_Network_t *net, bdd_manager *dd, MlTree *top, MlTree *tree, char *eq, bdd_node **ofuncs);
+static void WriteMlTreeBlif(FILE *fout, Ntk_Network_t *net, bdd_manager *dd, MlTree *tree, bdd_node **ofuncs, int no, char *func_name, int ref);
+static void WriteMultiLevelBlif(FILE *fout, Ntk_Network_t *net, bdd_manager *dd, MlTree *tree, bdd_node **ofuncs, int no);
+static TruthTableLine * GetMultiLevelBlifRecur(Ntk_Network_t *net, bdd_manager *dd, MlTree *top, MlTree *tree, bdd_node **ofuncs, int no, st_table *table, int ni);
+static int GetMultiLevelNodes(Ntk_Network_t *net, bdd_manager *dd, MlTree *top, MlTree *tree, bdd_node **ofuncs, int no, st_table *table, int ni);
+static int GetLeafNodes(Ntk_Network_t *net, bdd_manager *dd, MlTree *tree, bdd_node **ofuncs, int no, st_table *table, int ni);
+static TruthTableLine * GetTautologyLine(int ni);
+static TruthTableLine * GetLeafLines(Ntk_Network_t *net, bdd_manager *dd, MlTree *tree, bdd_node **ofuncs, int no, st_table *table, int ni);
+static TruthTableLine * GetBlifBinary(TruthTableLine *line, bdd_manager *dd, bdd_node *node, char *values, int *support, int ni);
+static TruthTableLine * GetComplementOneLine(TruthTableLine *line, int ni, int flag);
+static TruthTableLine * GetComplementLines(TruthTableLine *lines, int ni, int flag);
+static TruthTableLine * GetAndLines(TruthTableLine *line1, TruthTableLine *line2, int ni, int flag);
+static bdd_node	* GetDdNodeOfMlTree(MlTree *tree, int comp);
+static int GetMlTreeName(Ntk_Network_t *net, bdd_node **ofuncs, MlTree *tree, char *name);
+static char ** GetAllVarNameArray(bdd_manager *dd);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compares two strings to see which one is first in
+  alphabetic order.]
+
+  Description [Compares two strings to see which one is first in
+  alphabetic order.]
+
+  SideEffects []
+
+  SeeAlso     [qsort]
+
+******************************************************************************/
+int
+SynthStringCompare(char **a,
+		   char **b)
+{
+  char	*pa, *pb;
+
+  pa = *a;
+  pb = *b;
+
+  if (*pa == '\0') {
+    if (*pb == '\0')
+      return(0);
+    else
+      return(-1);
+  } else if (*pb == '\0')
+    return(1);
+  while (*pa != '\0' && *pb != '\0') {
+    if (*pa > *pb)
+      return(1);
+    if (*pa < *pb)
+      return(-1);
+    pa++;
+    pb++;
+    if (*pa == '\0') {
+      if (*pb == '\0')
+	return(0);
+      else
+	return(-1);
+    } else if (*pb == '\0')
+      return(1);
+  }
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Write a blif file of the factorized network.]
+
+  Description [Write a blif file of the factorized network. There are 2
+  ways of writing a blif file depending on argument ml_mode. If
+  ml_mode is 0, then the resulting blif file will be based on the
+  factorized multi level tree that has 3 children; quotient, divisor,
+  and remainder. If ml_mode is 1, then the resulting blif file will be
+  generated as follows. All top nodes and all nodes that are shared will
+  be output nodes of .names in blif file. By default, ml_mode is 0.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthWriteBlifFile(Ntk_Network_t *net,
+		   bdd_manager *dd,
+		   MlTree **tree,
+		   char *filename,
+		   int no,
+		   bdd_node **ofuncs,
+		   int *initStates,
+		   int ml_mode,
+		   int verbosity)
+{
+  FILE		*fout;
+  int		i, j;
+  int		*oflags;
+  char		out_name[MAX_NAME_LEN], name[MAX_NAME_LEN];
+  lsGen		gen;
+  Ntk_Node_t	*node;
+  char		**sorted_name;
+  int		ni, po;
+  int		polarity;
+
+  fout = Cmd_FileOpen(filename, "w", NIL(char *), 0);
+  if (!fout) {
+    (void)fprintf(vis_stdout,
+		  "** synth error: Error in opening file [%s]\n", filename);
+    return;
+  }
+
+  fprintf(fout, ".model %s\n", Ntk_NetworkReadName(net));
+  fprintf(fout, ".inputs");
+
+  /* Write list of primary inputs sorted lexicographically. */
+  ni = Ntk_NetworkReadNumPrimaryInputs(net);
+  sorted_name = ALLOC(char *, ni * sizeof(char *));
+  i = 0;
+  Ntk_NetworkForEachPrimaryInput(net, gen, node) {
+    sorted_name[i++] = Ntk_NodeReadName(node);
+  }
+  qsort(sorted_name, ni, sizeof(char *),
+	(int (*)(const void *, const void *)) SynthStringCompare);
+  for (i = 0; i < ni; i++)
+    fprintf(fout," %s", sorted_name[i]);
+  FREE(sorted_name);
+
+  fprintf(fout, "\n");
+  fprintf(fout, ".outputs");
+
+  /* Write list of primary outputs sorted lexicographically. */
+  po = Ntk_NetworkReadNumPrimaryOutputs(net);
+  sorted_name = ALLOC(char *, po * sizeof(char *));
+  i = 0;
+  Ntk_NetworkForEachPrimaryOutput(net, gen, node) {
+    sorted_name[i++] = Ntk_NodeReadName(node);
+  }
+  qsort(sorted_name, po, sizeof(char *),
+	(int (*)(const void *, const void *))SynthStringCompare);
+  for (i = 0; i < po; i++)
+    fprintf(fout," %s", sorted_name[i]);
+  FREE(sorted_name);
+  fprintf(fout, "\n");
+
+  /* Print list of latches. */
+  i = 0;
+  Ntk_NetworkForEachLatch(net, gen, node) {
+    fprintf(fout,".latch %s", Ntk_NodeReadName(Ntk_LatchReadDataInput(node)));
+    fprintf(fout, " %s", Ntk_NodeReadName(node));
+    fprintf(fout, " %d\n", initStates[i]);
+    i++;
+  }
+
+  oflags = ALLOC(int, no);
+  (void)memset((void *)oflags, 0, no * sizeof(int));
+  for (i = 0; i < no; i++) {
+    if (!tree[i])
+      continue;
+    if (bdd_is_constant(tree[i]->node)) {
+      if (tree[i]->comp) {
+	for (j = 0; j < no; j++) {
+	  if (tree[i]->complement == ofuncs[j] && oflags[j] == 0) {
+	    sprintf(out_name, "%s", SynthGetIthOutputName(j));
+	    break;
+	  }
+	}
+      } else {
+	for (j = 0; j < no; j++) {
+	  if (tree[i]->node == ofuncs[j] && oflags[j] == 0) {
+	    sprintf(out_name, "%s", SynthGetIthOutputName(j));
+	    break;
+	  }
+	}
+      }
+      if (j == no)
+	SynthGetInternalNodeName(out_name, tree[i]->id);
+      else {
+	if (oflags[j])
+	  continue;
+	else
+	  oflags[j] = 1;
+      }
+      fprintf(fout, "\n.names %s\n", out_name);
+      if (tree[i]->node == bdd_read_one(dd)) {
+	if (tree[i]->comp)
+	  fprintf(fout, "0\n");
+	else
+	  fprintf(fout, "1\n");
+      } else {
+	if (tree[i]->comp)
+	  fprintf(fout, "1\n");
+	else
+	  fprintf(fout, "0\n");
+      }
+      continue;
+    } else if (tree[i]->ref) {
+      for (j = 0; j < no; j++) {
+	if ((((tree[i]->comp == 0 && tree[i]->node == ofuncs[j]) ||
+	      (tree[i]->comp && tree[i]->complement == ofuncs[j]))) &&
+	    oflags[j] == 0) {
+	  sprintf(out_name, "%s", SynthGetIthOutputName(j));
+	  break;
+	}
+      }
+      if (j == no)
+	SynthGetInternalNodeName(out_name, tree[i]->id);
+      else {
+	if (oflags[j])
+	  continue;
+	else
+	  oflags[j] = 1;
+      }
+      polarity = GetMlTreeName(net, ofuncs, tree[i], name);
+      if (strcmp(out_name, name) == 0)
+	SynthGetPrimaryNodeName(net, tree[i]->node, name);
+      fprintf(fout, "\n.names %s %s\n", name, out_name);
+      if (polarity == 0) {
+	if (tree[i]->comp)
+	  fprintf(fout, "0 1\n");
+	else
+	  fprintf(fout, "1 1\n");
+      } else {
+	if (tree[i]->comp)
+	  fprintf(fout, "1 1\n");
+	else
+	  fprintf(fout, "0 1\n");
+      }
+      continue;
+    }
+    if (ml_mode == 0) {
+      if (tree[i]->pi) {
+	tree[i]->pi = 0;
+	WriteMlBlif(net, dd, tree[i], fout, no, ofuncs, oflags, 1, verbosity);
+	tree[i]->pi = 1;
+      } else {
+	WriteMlBlif(net, dd, tree[i], fout, no, ofuncs, oflags, 1, verbosity);
+      }
+    } else {
+      for (j = 0; j < no; j++) {
+	if (tree[i]->node == ofuncs[j]) {
+	  if (oflags[j])
+	    continue;
+	  else
+	    oflags[j] = 1;
+	  sprintf(out_name, "%s", SynthGetIthOutputName(j));
+	  break;
+	}
+      }
+      if (j == no)
+	SynthGetInternalNodeName(out_name, tree[i]->id);
+      if (tree[i]->pi) {
+	tree[i]->pi = 0;
+	WriteMlTreeBlif(fout, net, dd, tree[i], ofuncs, no, out_name, 1);
+	tree[i]->pi = 1;
+      } else {
+	WriteMlTreeBlif(fout, net, dd, tree[i], ofuncs, no, out_name, 1);
+      }
+    }
+  }
+  FREE(oflags);
+
+  fprintf(fout, "\n.end\n");
+  fclose(fout);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes header of equation format for a network.]
+
+  Description [Writes header of equation format for a network.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthWriteEqnHeader(FILE *fout,
+		  Ntk_Network_t *net,
+		  bdd_manager *dd)
+{
+  int		i;
+  lsGen		gen;
+  Ntk_Node_t	*node;
+  char		**sorted_name;
+  int		ni, po;
+
+  /* Write list of primary inputs sorted lexicographically. */
+  ni = Ntk_NetworkReadNumPrimaryInputs(net);
+  sorted_name = ALLOC(char *, ni * sizeof(char *));
+  i = 0;
+  Ntk_NetworkForEachPrimaryInput(net, gen, node) {
+    sorted_name[i++] = Ntk_NodeReadName(node);
+  }
+  qsort(sorted_name, ni, sizeof(char *),
+	(int (*)(const void *, const void *))SynthStringCompare);
+  fprintf(fout, "INORDER");
+  for (i = 0; i < ni; i++)
+    fprintf(fout," %s", sorted_name[i]);
+  fprintf(fout, "\n");
+  FREE(sorted_name);
+
+  /* Write list of primary outputs sorted lexicographically. */
+  po = Ntk_NetworkReadNumPrimaryOutputs(net);
+  sorted_name = ALLOC(char *, po * sizeof(char *));
+  i = 0;
+  Ntk_NetworkForEachPrimaryOutput(net, gen, node) {
+    sorted_name[i++] = Ntk_NodeReadName(node);
+  }
+  qsort(sorted_name, po, sizeof(char *),
+	(int (*)(const void *, const void *))SynthStringCompare);
+  fprintf(fout, "OUTORDER");
+  for (i = 0; i < po; i++)
+    fprintf(fout," %s", sorted_name[i]);
+  fprintf(fout, "\n");
+  FREE(sorted_name);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes an equation of a factorized tree.]
+
+  Description [Writes an equation of a factorized tree.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthWriteEqn(FILE *fout,
+	      Ntk_Network_t *net,
+	      bdd_manager *dd,
+	      MlTree *tree,
+	      bdd_node **ofuncs,
+	      char *func_name,
+	      int ref)
+{
+  char	name[MAX_NAME_LEN];
+  int	polarity = 0;
+
+  if (tree->top || tree->shared) {
+    if (ref) {
+      /* If tree is shared we print the name of the original function
+       * unless it is a constant.
+       */
+      if (tree->ref) {
+	if (tree->node == bdd_read_zero(dd))
+	  sprintf(name, "zero");
+	else if (tree->node == bdd_read_one(dd))
+	  sprintf(name, "one");
+	else
+	  polarity = GetMlTreeName(net, ofuncs, tree, name);
+	if (polarity == 0) {
+	  if (tree->comp)
+	    SynthMakeComplementString(name);
+	} else {
+	  if (!tree->comp)
+	    SynthMakeComplementString(name);
+	}
+	fprintf(fout, "%s = %s\n", func_name, name);
+	return;
+      }
+    }
+    WriteEqnOfTree(fout, net, dd, tree, ofuncs);
+  }
+
+  if (tree->leaf) {
+    return;
+  }
+
+  if (tree->q_ref == 0)
+    SynthWriteEqn(fout, net, dd, tree->q, ofuncs, NULL, ref);
+  if (tree->d_ref == 0)
+    SynthWriteEqn(fout, net, dd, tree->d, ofuncs, NULL, ref);
+  if (tree->r_ref == 0)
+    SynthWriteEqn(fout, net, dd, tree->r, ofuncs, NULL, ref);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Set the prefix of internal node name.]
+
+  Description [Set the prefix of internal node name.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthSetInternalNodePrefix(char *prefix)
+{
+  if (prefix)
+    InternalNodePrefix = prefix;
+  else
+    InternalNodePrefix = DefaultPrefix;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Creates a st_table to keep all node names for primary
+  input, primary output, latch input and output nodes.]
+
+  Description [Creates a st_table to keep all node names for primary
+  input, primary output, latch input and output nodes. This table is used
+  when we make internal node names, to see if there is a same name.]
+
+  SideEffects []
+
+  SeeAlso     [SynthFreeNodeNameTable SynthGetInternalNodeName]
+
+******************************************************************************/
+void
+SynthSetupNodeNameTable(Ntk_Network_t *net)
+{
+  lsGen		gen;
+  Ntk_Node_t	*node;
+
+  if (NodeNameTable) {
+    (void)fprintf(vis_stdout,
+	"** synth warning: table already exists in SynthSetupNodeNameTable.\n");
+    st_free_table(NodeNameTable);
+  }
+
+  NodeNameTable = st_init_table(strcmp, st_strhash);
+
+  /* Register all primary input node names. */
+  Ntk_NetworkForEachPrimaryInput(net, gen, node) {
+    st_insert(NodeNameTable, Ntk_NodeReadName(node), (char *)NULL);
+  }
+
+  /* Register all primary output node names. */
+  Ntk_NetworkForEachPrimaryOutput(net, gen, node) {
+    st_insert(NodeNameTable, Ntk_NodeReadName(node), (char *)NULL);
+  }
+
+  /* Register all latch input and output node names. */
+  Ntk_NetworkForEachLatch(net, gen, node) {
+    st_insert(NodeNameTable, Ntk_NodeReadName(Ntk_LatchReadDataInput(node)),
+    	      (char *)NULL);
+    st_insert(NodeNameTable, Ntk_NodeReadName(node), (char *)NULL);
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Frees the st_table named NodeNameTable.]
+
+  Description [Frees the st_table named NodeNameTable.]
+
+  SideEffects []
+
+  SeeAlso     [SynthSetupNodeNameTable SynthGetInternalNodeName]
+
+******************************************************************************/
+void
+SynthFreeNodeNameTable(void)
+{
+  st_free_table(NodeNameTable);
+  NodeNameTable = NIL(st_table);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a proper internal node name.]
+
+  Description [Returns a proper internal node name. Internal node name
+  is made by "prefix+id". If NodeNameTable exists, fist lookup the table
+  to see if the name already exists. If it exists, another prefix
+  "_synth_" is used. Then, whenever a same name exists, extra prefix "_"
+  is used.]
+
+  SideEffects []
+
+  SeeAlso     [SynthSetupNodeNameTable SynthFreeNodeNameTable]
+
+******************************************************************************/
+void
+SynthGetInternalNodeName(char *name, int id)
+{
+  sprintf(name, "%s%d", InternalNodePrefix, id);
+  if (NodeNameTable) {
+    if (st_lookup(NodeNameTable, name, NIL(char *))) {
+      int	pos;
+
+      sprintf(name, "_synth_%s%d", InternalNodePrefix, id);
+      pos = 7; /* _synth_ */
+      while (st_lookup(NodeNameTable, name, NIL(char *))) {
+	sprintf(&name[pos], "_%s%d", InternalNodePrefix, id);
+	pos++;
+      }
+    }
+  } else {
+    (void)fprintf(vis_stdout,
+    		  "** synth warning: skipping internal node name checking.\n");
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Dumps Bdds of all output nodes.]
+
+  Description [Dumps Bdds of all output nodes. just for debug]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+SynthDumpBlif(Ntk_Network_t *net,
+	      bdd_manager *dd,
+	      int no,
+	      bdd_node **ofuncs,
+	      char **onames,
+	      int *initStates,
+	      char *model)
+{
+  int		size;
+  bdd_node	**bdds;
+  FILE		*fout;
+  char		**inames;
+  char		filename[MAX_NAME_LEN];
+  int		i;
+  lsGen		gen;
+  Ntk_Node_t	*node;
+  char		**sorted_name;
+  int		ni, po;
+
+  sprintf(filename, "%s.debug.blif", model);
+  fout = fopen(filename, "w");
+  if (!fout) {
+    (void)fprintf(vis_stderr,
+		  "** synth error: Can't open the file %s.\n", filename);
+    return;
+  }
+
+  fprintf(fout, ".model %s\n", model);
+  fprintf(fout, ".inputs");
+
+  /* Write list of primary inputs sorted lexicographically. */
+  ni = Ntk_NetworkReadNumPrimaryInputs(net);
+  sorted_name = ALLOC(char *, ni * sizeof(char *));
+  i = 0;
+  Ntk_NetworkForEachPrimaryInput(net, gen, node) {
+    sorted_name[i++] = Ntk_NodeReadName(node);
+  }
+  qsort(sorted_name, ni, sizeof(char *),
+	(int (*)(const void *, const void *))SynthStringCompare);
+  for (i = 0; i < ni; i++)
+    fprintf(fout," %s", sorted_name[i]);
+  FREE(sorted_name);
+
+  fprintf(fout, "\n");
+  fprintf(fout, ".outputs");
+
+  /* Write list of primary outputs sorted lexicographically. */
+  po = Ntk_NetworkReadNumPrimaryOutputs(net);
+  sorted_name = ALLOC(char *, po * sizeof(char *));
+  i = 0;
+  Ntk_NetworkForEachPrimaryOutput(net, gen, node) {
+    sorted_name[i++] = Ntk_NodeReadName(node);
+  }
+  qsort(sorted_name, po, sizeof(char *),
+	(int (*)(const void *, const void *))SynthStringCompare);
+  for (i = 0; i < po; i++)
+    fprintf(fout," %s", sorted_name[i]);
+  FREE(sorted_name);
+  fprintf(fout, "\n");
+
+  /* Print list of latches. */
+  i = 0;
+  Ntk_NetworkForEachLatch(net, gen, node) {
+    fprintf(fout,".latch %s", Ntk_NodeReadName(Ntk_LatchReadDataInput(node)));
+    fprintf(fout, " %s", Ntk_NodeReadName(node));
+    fprintf(fout, " %d\n", initStates[i]);
+    i++;
+  }
+
+  bdds = ALLOC(bdd_node *, no);
+
+  for (i = 0; i < no; i++) {
+    bdds[i] = bdd_make_bdd_from_zdd_cover(dd, ofuncs[i]);
+    bdd_ref(bdds[i]);
+  }
+
+  inames = GetAllVarNameArray(dd);
+  if (!inames) {
+    for (i = 0; i < no; i++)
+      bdd_recursive_deref(dd, bdds[i]);
+    FREE(bdds);
+    fclose(fout);
+    (void)fprintf(vis_stderr, "** synth error: Out of memory.\n");
+    return;
+  }
+
+  bdd_dump_blif_body(dd, no, bdds, inames, onames, fout);
+  fprintf(fout, ".end\n");
+
+  size = bdd_num_vars(dd);
+  for (i = 0; i < size; i++)
+    FREE(inames[i]);
+  FREE(inames);
+
+  for (i = 0; i < no; i++)
+    bdd_recursive_deref(dd, bdds[i]);
+
+  FREE(bdds);
+  fclose(fout);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Writes a part of a blif file for each output function.]
+
+  Description [Writes a part of a blif file for each output function.
+  The resulting blif file will be based on the factorized multi level tree
+  that has 3 children: quotient, divisor, and remainder.]
+
+  SideEffects []
+
+  SeeAlso     [WriteMlTreeBlif]
+
+******************************************************************************/
+static void
+WriteMlBlif(Ntk_Network_t *net,
+	    bdd_manager *dd,
+	    MlTree *tree,
+	    FILE *fout,
+	    int no,
+	    bdd_node **ofuncs,
+	    int *oflags,
+	    int top_flag,
+	    int verbosity)
+{
+  int		i;
+  char		name[MAX_NAME_LEN], q_name[MAX_NAME_LEN];
+  char		d_name[MAX_NAME_LEN], r_name[MAX_NAME_LEN];
+  char		eq[MAX_EQ_LEN];
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  char		q, d, r;
+  int		comp;
+
+  if (tree->leaf) {
+    WriteLeafMlBlif(net, dd, tree, fout, no, ofuncs, oflags, top_flag,
+		    verbosity);
+    return;
+  }
+
+  if (!tree->ref) {
+    if (!tree->q_ref)
+      WriteMlBlif(net, dd, tree->q, fout, no, ofuncs, oflags, 0, verbosity);
+    if (!tree->d_ref)
+      WriteMlBlif(net, dd, tree->d, fout, no, ofuncs, oflags, 0, verbosity);
+    if (!tree->r_ref)
+      WriteMlBlif(net, dd, tree->r, fout, no, ofuncs, oflags, 0, verbosity);
+  }
+
+  for (i = 0; i < no; i++) {
+    if (tree->node == ofuncs[i]) {
+      if (top_flag == 0)
+	return;
+
+      if (oflags[i])
+	continue;
+      else
+	oflags[i] = 1;
+      sprintf(name, "%s",  SynthGetIthOutputName(i));
+      break;
+    }
+  }
+  if (i == no)
+    SynthGetInternalNodeName(name, tree->id);
+
+  fprintf(fout, "\n");
+  if (verbosity > 2) {
+    SynthGetChildMlTreeWithName(net, dd, tree, eq);
+    (void)fprintf(fout, "# %s\n", eq);
+  }
+
+  if (tree->q->pi) {
+    comp = SynthGetPrimaryNodeName(net, tree->q->node, q_name);
+
+    if (comp)
+      q = '0';
+    else
+      q = '1';
+    if (tree->q_comp) {
+      if (q == '0')
+	q = '1';
+      else
+	q = '0';
+    }
+  } else {
+    for (i = 0; i < no; i++) {
+      if (tree->q->node == ofuncs[i]) {
+	sprintf(q_name, "%s",  SynthGetIthOutputName(i));
+	break;
+      }
+    }
+    if (i == no)
+      SynthGetInternalNodeName(q_name, tree->q->id);
+    if (tree->q_comp)
+      q = '0';
+    else
+      q = '1';
+  }
+  if (tree->d->pi) {
+    comp = SynthGetPrimaryNodeName(net, tree->d->node, d_name);
+
+    if (comp)
+      d = '0';
+    else
+      d = '1';
+    if (tree->d_comp) {
+      if (d == '0')
+	d = '1';
+      else
+	d = '0';
+    }
+  } else {
+    for (i = 0; i < no; i++) {
+      if (tree->d->node == ofuncs[i]) {
+	sprintf(d_name, "%s", SynthGetIthOutputName(i));
+	break;
+      }
+    }
+    if (i == no)
+      SynthGetInternalNodeName(d_name, tree->d->id);
+    if (tree->d_comp)
+      d = '0';
+    else
+      d = '1';
+  }
+  if (tree->r->pi) {
+    comp = SynthGetPrimaryNodeName(net, tree->r->node, r_name);
+
+    if (comp)
+      r = '0';
+    else
+      r = '1';
+    if (tree->r_comp) {
+      if (r == '0')
+	r = '1';
+      else
+	r = '0';
+    }
+  } else {
+    for (i = 0; i < no; i++) {
+      if (tree->r->node == ofuncs[i]) {
+	sprintf(r_name, "%s", SynthGetIthOutputName(i));
+	break;
+      }
+    }
+    if (i == no)
+      SynthGetInternalNodeName(r_name, tree->r->id);
+    if (tree->r_comp)
+      r = '0';
+    else
+      r = '1';
+  }
+
+  if (GetDdNodeOfMlTree(tree->q, tree->q_comp) == zero ||
+      GetDdNodeOfMlTree(tree->d, tree->d_comp) == zero) {
+    if (GetDdNodeOfMlTree(tree->r, tree->r_comp) == one) {
+      fprintf(fout, ".names %s\n", name);
+      fprintf(fout, "1\n");
+    } else if (GetDdNodeOfMlTree(tree->r, tree->r_comp) == zero) {
+      fprintf(fout, ".names %s\n", name);
+      fprintf(fout, "0\n");
+    } else {
+      fprintf(fout, ".names %s %s\n", r_name, name);
+      fprintf(fout, "%c 1\n", r);
+    }
+  } else if (GetDdNodeOfMlTree(tree->q, tree->q_comp) == one) {
+    if (GetDdNodeOfMlTree(tree->d, tree->d_comp) == one) {
+      fprintf(fout, ".names %s\n", name);
+      fprintf(fout, "1\n");
+    } else if (GetDdNodeOfMlTree(tree->d, tree->d_comp) == zero) {
+      if (GetDdNodeOfMlTree(tree->r, tree->r_comp) == one) {
+	fprintf(fout, ".names %s\n", name);
+	fprintf(fout, "1\n");
+      } else if (GetDdNodeOfMlTree(tree->r, tree->r_comp) == zero) {
+	fprintf(fout, ".names %s\n", name);
+	fprintf(fout, "0\n");
+      } else {
+	fprintf(fout, ".names %s %s\n", r_name, name);
+	fprintf(fout, "%c 1\n", r);
+      }
+    } else {
+      if (GetDdNodeOfMlTree(tree->r, tree->r_comp) == one) {
+	fprintf(fout, ".names %s\n", name);
+	fprintf(fout, "1\n");
+      } else if (GetDdNodeOfMlTree(tree->r, tree->r_comp) == zero) {
+	fprintf(fout, ".names %s %s\n", d_name, name);
+	fprintf(fout, "%c 1\n", d);
+      } else {
+	fprintf(fout, ".names %s %s %s\n", d_name, r_name,
+		name);
+	fprintf(fout, "%c- 1\n", d);
+	fprintf(fout, "-%c 1\n", r);
+      }
+    }
+  } else if (GetDdNodeOfMlTree(tree->d, tree->d_comp) == one) {
+    if (GetDdNodeOfMlTree(tree->q, tree->q_comp) == one) {
+      fprintf(fout, ".names %s\n", name);
+      fprintf(fout, "1\n");
+    } else if (GetDdNodeOfMlTree(tree->q, tree->q_comp) == zero) {
+      if (GetDdNodeOfMlTree(tree->r, tree->r_comp) == one) {
+	fprintf(fout, ".names %s\n", name);
+	fprintf(fout, "1\n");
+      } else if (GetDdNodeOfMlTree(tree->r, tree->r_comp) == zero) {
+	fprintf(fout, ".names %s\n", name);
+	fprintf(fout, "0\n");
+      } else {
+	fprintf(fout, ".names %s %s\n", r_name, name);
+	fprintf(fout, "%c 1\n", r);
+      }
+    } else {
+      if (GetDdNodeOfMlTree(tree->r, tree->r_comp) == one) {
+	fprintf(fout, ".names %s\n", name);
+	fprintf(fout, "1\n");
+      } else if (GetDdNodeOfMlTree(tree->r, tree->r_comp) == zero) {
+	fprintf(fout, ".names %s %s\n", q_name, name);
+	fprintf(fout, "%c 1\n", q);
+      } else {
+	fprintf(fout, ".names %s %s %s\n", q_name, r_name, name);
+	fprintf(fout, "%c- 1\n", q);
+	fprintf(fout, "-%c 1\n", r);
+      }
+    }
+  } else {
+    if (GetDdNodeOfMlTree(tree->r, tree->r_comp) == one) {
+      fprintf(fout, ".names %s\n", name);
+      fprintf(fout, "1\n");
+    } else if (GetDdNodeOfMlTree(tree->r, tree->r_comp) == zero) {
+      fprintf(fout, ".names %s %s %s\n", q_name, d_name, name);
+      fprintf(fout, "%c%c 1\n", q, d);
+    } else {
+      fprintf(fout, ".names %s %s %s %s\n", q_name, d_name, r_name, name);
+      fprintf(fout, "%c%c- 1\n", q, d);
+      fprintf(fout, "--%c 1\n", r);
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Writes a .names block in blif file for each tree that is a leaf
+  node.]
+
+  Description [Writes a .names block in blif file for each tree that is a leaf
+  node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+WriteLeafMlBlif(Ntk_Network_t *net,
+		bdd_manager *dd,
+		MlTree *tree,
+		FILE *fout,
+		int no,
+		bdd_node **ofuncs,
+		int *oflags,
+		int top_flag,
+		int verbosity)
+{
+  int		i, count, *support;
+  char		name[MAX_EQ_LEN];
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  char		out_name[MAX_NAME_LEN];
+  bdd_node	*node;
+  Ntk_Node_t	*ntk_node;
+  int		sizeZ;
+
+  sizeZ = bdd_num_zdd_vars(dd);
+
+  if (tree->node == one || tree->node == zero || tree->pi)
+    return;
+
+  if (tree->comp)
+    node = tree->complement;
+  else
+    node = tree->node;
+  for (i = 0; i < no; i++) {
+    if (node == ofuncs[i]) {
+      if (top_flag == 0)
+	return;
+
+      if (oflags[i])
+	continue;
+      else
+	oflags[i] = 1;
+      sprintf(out_name, "%s", SynthGetIthOutputName(i));
+      break;
+    }
+  }
+  if (i == no)
+    SynthGetInternalNodeName(out_name, tree->id);
+  else {
+    ntk_node = Ntk_NetworkFindNodeByName(net, out_name);
+    if (Ntk_NodeTestIsLatch(ntk_node))
+      return;
+  }
+
+  fprintf(fout, "\n");
+  if (verbosity > 2) {
+    SynthGetChildMlTreeWithName(net, dd, tree, name);
+    fprintf(fout, "# %s\n", name);
+  }
+  fprintf(fout, ".names ");
+
+  support = ALLOC(int, sizeZ);
+  if (!support)
+    return;
+  (void)memset((void *)support, 0, sizeof(int) * sizeZ);
+  SynthZddSupportStep(bdd_regular(node), support);
+  SynthZddClearFlag(bdd_regular(node));
+  count = 0;
+  for (i = 0; i < sizeZ; i++) {
+    if (support[i]) {
+      SynthGetPrimaryIndexName(net, i, name);
+      fprintf(fout, "%s ", name);
+      if (i % 2 == 0) {
+	support[i] = count;
+	i++;
+	if (support[i])
+	  support[i] = count;
+      } else {
+	support[i] = count;
+      }
+      count++;
+    }
+  }
+  fprintf(fout, "%s\n", out_name);
+
+  for (i = 0; i < count; i++)
+    name[i] = '-';
+  name[count] = '\0';
+  WriteBlifBinary(dd, node, name, fout, support);
+  FREE(support);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes all cubes of the node in .name block.]
+
+  Description [Writes all cubes of the node in .name block. This can be done
+  by finding all paths to the constant 1 node from the node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+WriteBlifBinary(bdd_manager *dd,
+		bdd_node *node,
+		char *name,
+		FILE *fout,
+		int *support)
+{
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  int		id = bdd_node_read_index(node);
+
+  if (node == zero)
+    return;
+
+  if (node == one) {
+    fprintf(fout, "%s 1\n", name);
+    return;
+  }
+
+  if (id % 2 == 0)
+    name[support[id]] = '1';
+  else
+    name[support[id]] = '0';
+  WriteBlifBinary(dd, bdd_bdd_T(node), name, fout, support);
+  name[support[id]] = '-';
+  WriteBlifBinary(dd, bdd_bdd_E(node), name, fout, support);
+  name[support[id]] = '-';
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes multi level equations of a tree.]
+
+  Description [Writes multi level equations of a tree.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+WriteEqnOfTree(FILE *fout,
+	       Ntk_Network_t *net,
+	       bdd_manager *dd,
+	       MlTree *tree,
+	       bdd_node **ofuncs)
+{
+  char	eq[MAX_EQ_LEN];
+  char	name[MAX_NAME_LEN];
+  int	polarity = 0;
+
+  polarity = GetMlTreeName(net, ofuncs, tree, name);
+  eq[0] = '\0';
+  GetEqnOfTree(net, dd, tree, tree, eq, ofuncs);
+  if (polarity)
+    SynthMakeComplementString(eq);
+  fprintf(fout, "%s = %s\n", name, eq);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets multi level equations of a tree.]
+
+  Description [Gets multi level equations of a tree.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+GetEqnOfTree(Ntk_Network_t *net,
+	     bdd_manager *dd,
+	     MlTree *top,
+	     MlTree *tree,
+	     char *eq,
+	     bdd_node **ofuncs)
+{
+  char		q_eq[MAX_EQ_LEN];
+  char		d_eq[MAX_EQ_LEN];
+  char		r_eq[MAX_EQ_LEN];
+  char		qd_eq[MAX_EQ_LEN];
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  bdd_node	*f;
+  int		flag;
+  int		polarity = 0;
+
+  if (tree != top && tree->shared) {
+    polarity = GetMlTreeName(net, ofuncs, tree, eq);
+    if (polarity)
+      SynthMakeComplementString(eq);
+    return(0);
+  }
+
+  f = tree->node;
+  if (tree->leaf) {
+    flag = SynthGetChildTreeWithName(net, dd, f, eq);
+    return(flag);
+  }
+
+  if (f == one) {
+    sprintf(eq, "one");
+    return(0);
+  } else if (f == zero) {
+    sprintf(eq, "zero");
+    return(0);
+  }
+
+  q_eq[0] = d_eq[0] = r_eq[0] = '\0';
+  flag = GetEqnOfTree(net, dd, top, tree->q, q_eq, ofuncs);
+  if (tree->q_comp)
+    SynthMakeComplementString(q_eq);
+  if (flag)
+    return(1);
+  if (GetDdNodeOfMlTree(tree->d, tree->d_comp) == one)
+    d_eq[0] = '\0';
+  else {
+    flag = GetEqnOfTree(net, dd, top, tree->d, d_eq, ofuncs);
+    if (tree->d_comp)
+      SynthMakeComplementString(d_eq);
+    if (flag)
+      return(1);
+  }
+  flag = GetEqnOfTree(net, dd, top, tree->r, r_eq, ofuncs);
+  if (tree->r_comp)
+    SynthMakeComplementString(r_eq);
+  if (flag)
+    return(1);
+
+  if (strcmp(q_eq, "one") == 0)
+    sprintf(qd_eq, "%s", d_eq);
+  else if (strcmp(q_eq, "zero") == 0)
+    sprintf(qd_eq, "zero");
+  else if (strcmp(d_eq, "one") == 0)
+    sprintf(qd_eq, "%s", q_eq);
+  else if (strcmp(d_eq, "zero") == 0)
+    sprintf(qd_eq, "zero");
+  else {
+    if (strlen(q_eq) + strlen(d_eq) + 1 > MAX_EQ_LEN) {
+      sprintf(eq, "%s", q_eq);
+      if (strlen(eq) == MAX_EQ_LEN - 1) {
+	eq[MAX_EQ_LEN - 2] = '#'; /* truncated */
+	eq[MAX_EQ_LEN - 1] = '\0';
+      } else {
+	eq[strlen(eq)] = '#'; /* truncated */
+	eq[strlen(eq) + 1] = '\0';
+      }
+      return(1);
+    }
+    sprintf(qd_eq, "%s %s", q_eq, d_eq);
+  }
+
+  if (strcmp(r_eq, "zero") == 0)
+    sprintf(eq, "%s", qd_eq);
+  else {
+    if (strlen(qd_eq) + strlen(r_eq) + 1 > MAX_EQ_LEN) {
+      sprintf(eq, "%s", qd_eq);
+      if (strlen(eq) == MAX_EQ_LEN - 1) {
+	eq[MAX_EQ_LEN - 2] = '#'; /* truncated */
+	eq[MAX_EQ_LEN - 1] = '\0';
+      } else {
+	eq[strlen(eq)] = '#'; /* truncated */
+	eq[strlen(eq) + 1] = '\0';
+      }
+      return(1);
+    }
+    sprintf(eq, "(%s + %s)", qd_eq, r_eq);
+  }
+  return(0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes a part of a blif file for each output function.]
+
+  Description [Writes a part of a blif file for each output function.
+  All top nodes and all nodes that are shared will be output nodes of
+  .names in blif file.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+WriteMlTreeBlif(FILE *fout,
+		Ntk_Network_t *net,
+		bdd_manager *dd,
+		MlTree *tree,
+		bdd_node **ofuncs,
+		int no,
+		char *func_name,
+		int ref)
+{
+  char	name[MAX_NAME_LEN];
+  int	polarity = 0;
+
+  if (tree->top || tree->shared) {
+    if (ref) {
+      if (tree->ref) {
+	polarity = GetMlTreeName(net, ofuncs, tree, name);
+	fprintf(fout, "\n.names %s %s\n", name, func_name);
+	if (polarity == 0) {
+	  if (tree->comp)
+	    fprintf(fout, "0 1\n");
+	  else
+	    fprintf(fout, "1 1\n");
+	} else {
+	  if (tree->comp)
+	    fprintf(fout, "1 1\n");
+	  else
+	    fprintf(fout, "0 1\n");
+	}
+	return;
+      }
+    }
+    WriteMultiLevelBlif(fout, net, dd, tree, ofuncs, no);
+  }
+
+  if (tree->leaf)
+    return;
+
+  if (tree->q_ref == 0)
+    WriteMlTreeBlif(fout, net, dd, tree->q, ofuncs, no, NULL, ref);
+  if (tree->d_ref == 0)
+    WriteMlTreeBlif(fout, net, dd, tree->d, ofuncs, no, NULL, ref);
+  if (tree->r_ref == 0)
+    WriteMlTreeBlif(fout, net, dd, tree->r, ofuncs, no, NULL, ref);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Writes a .names block in blif file for each tree that is a
+  top node or a shared node.]
+
+  Description [Writes a .names block in blif file for each tree that is a
+  top node or a shared node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+WriteMultiLevelBlif(FILE *fout,
+		    Ntk_Network_t *net,
+		    bdd_manager *dd,
+		    MlTree *tree,
+		    bdd_node **ofuncs,
+		    int no)
+{
+  int			i, ni;
+  char			name[MAX_NAME_LEN];
+  TruthTableLine	*lines, *cur, *next;
+  st_table		*table;
+  char			**sorted_name, *key;
+  st_generator		*gen;
+  int			pos;
+  Ntk_Node_t		*ntk_node;
+  int			polarity = 0;
+
+  polarity = GetMlTreeName(net, ofuncs, tree, name);
+  for (i = 0; i < no; i++) {
+    if (tree->node == ofuncs[i]) {
+      ntk_node = Ntk_NetworkFindNodeByName(net, name);
+      if (Ntk_NodeTestIsLatch(ntk_node))
+	return;
+    }
+  }
+
+  table = st_init_table(strcmp, st_strhash);
+  ni = 0;
+  ni = GetMultiLevelNodes(net, dd, tree, tree, ofuncs, no, table, ni);
+  sorted_name = ALLOC(char *, ni * sizeof(char *));
+  i = 0;
+  st_foreach_item_int(table, gen, (char **)&key, &pos) {
+    sorted_name[i] = key;
+    i++;
+  }
+  qsort(sorted_name, ni, sizeof(char *),
+	(int (*)(const void *, const void *))SynthStringCompare);
+  for (i = 0; i < ni; i++) {
+    st_insert(table, (char *)sorted_name[i], (char *)(long)i);
+  }
+  lines = GetMultiLevelBlifRecur(net, dd, tree, tree, ofuncs, no, table, ni);
+  fprintf(fout, "\n.names");
+  for (i = 0; i < ni; i++)
+    fprintf(fout, " %s", sorted_name[i]);
+  fprintf(fout, " %s\n", name);
+  cur = lines;
+  while (cur) {
+    next = cur->next;
+    if (polarity == 0)
+      fprintf(fout, "%s 1\n", cur->values);
+    else
+      fprintf(fout, "%s 0\n", cur->values);
+    FREE(cur->values);
+    FREE(cur);
+    cur = next;
+  }
+  st_free_table(table);
+  for (i = 0; i < ni; i++)
+    FREE(sorted_name[i]);
+  FREE(sorted_name);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets all cube list of a .name block.]
+
+  Description [Gets all cube list of a .name block.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static TruthTableLine *
+GetMultiLevelBlifRecur(Ntk_Network_t *net,
+		       bdd_manager *dd,
+		       MlTree *top,
+		       MlTree *tree,
+		       bdd_node **ofuncs,
+		       int no,
+		       st_table *table,
+		       int ni)
+{
+  bdd_node		*one = bdd_read_one(dd);
+  bdd_node		*zero = bdd_read_zero(dd);
+  bdd_node		*f;
+  TruthTableLine	*line;
+  TruthTableLine	*cur, *q_line, *d_line, *r_line;
+  int			pos;
+  char			name[MAX_NAME_LEN];
+  int			polarity = 0;
+
+  line = (TruthTableLine *)NULL;
+
+  if (tree != top && tree->shared) {
+    polarity = GetMlTreeName(net, ofuncs, tree, name);
+    line = GetTautologyLine(ni);
+    if (st_lookup_int(table, (char *)name, (int *)(&pos))) {
+      if (polarity == 0)
+	line->values[pos] = '1';
+      else
+	line->values[pos] = '0';
+    }
+    return(line);
+  }
+
+  f = tree->node;
+  if (tree->leaf) {
+    line = GetLeafLines(net, dd, tree, ofuncs, no, table, ni);
+    return(line);
+  }
+
+  if (f == one || f == zero)
+    return(line);
+
+  q_line = GetMultiLevelBlifRecur(net, dd, top, tree->q, ofuncs,
+				  no, table, ni);
+  if (q_line && tree->q_comp)
+    q_line = GetComplementLines(q_line, ni, 1);
+  if (GetDdNodeOfMlTree(tree->d, tree->d_comp) == one)
+    d_line = (TruthTableLine *)NULL;
+  else {
+    d_line = GetMultiLevelBlifRecur(net, dd, top, tree->d, ofuncs, no,
+				    table, ni);
+    if (d_line && tree->d_comp)
+      d_line = GetComplementLines(d_line, ni, 1);
+  }
+  if (q_line && d_line)
+    line = GetAndLines(q_line, d_line, ni, 1);
+  else if (q_line)
+    line = q_line;
+  else if (d_line)
+    line = d_line;
+  r_line = GetMultiLevelBlifRecur(net, dd, top, tree->r, ofuncs, no, table, ni);
+  if (r_line && tree->r_comp)
+    r_line = GetComplementLines(r_line, ni, 1);
+  if (r_line) {
+    cur = line;
+    while (cur) {
+      if (!cur->next) {
+	cur->next = r_line;
+	break;
+      }
+      cur = cur->next;
+    }
+  }
+
+  return(line);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Get the names of all input nodes of .name block for an output
+  tree.]
+
+  Description [Get the names of all input nodes of .name block for an output
+  tree.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+GetMultiLevelNodes(Ntk_Network_t *net,
+		   bdd_manager *dd,
+		   MlTree *top,
+		   MlTree *tree,
+		   bdd_node **ofuncs,
+		   int no,
+		   st_table *table,
+		   int ni)
+{
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  bdd_node	*f;
+  char		name[MAX_NAME_LEN], *st_name;
+  int		pos;
+
+  if (tree != top && tree->shared) {
+    (void) GetMlTreeName(net, ofuncs, tree, name);
+    if (!st_lookup_int(table, (char *)name, (int *)(&pos))) {
+      st_name = ALLOC(char, strlen(name) + 1);
+      strcpy(st_name, name);
+      st_insert(table, (char *)st_name, (char *)(long)ni);
+      ni++;
+    }
+    return(ni);
+  }
+
+  f = tree->node;
+  if (tree->leaf) {
+    ni = GetLeafNodes(net, dd, tree, ofuncs, no, table, ni);
+    return(ni);
+  }
+
+  if (f == one || f == zero)
+    return(ni);
+
+  ni = GetMultiLevelNodes(net, dd, top, tree->q, ofuncs, no, table, ni);
+  if (GetDdNodeOfMlTree(tree->d, tree->d_comp) != one)
+    ni = GetMultiLevelNodes(net, dd, top, tree->d, ofuncs, no, table, ni);
+  ni = GetMultiLevelNodes(net, dd, top, tree->r, ofuncs, no, table, ni);
+
+  return(ni);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Get the names of all input nodes of a tree which is a leaf
+  node.]
+
+  Description [Get the names of all input nodes of a tree which is a leaf
+  node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+GetLeafNodes(Ntk_Network_t *net,
+	     bdd_manager *dd,
+	     MlTree *tree,
+	     bdd_node **ofuncs,
+	     int no,
+	     st_table *table,
+	     int ni)
+{
+  int		i, *support;
+  char		name[MAX_NAME_LEN], *st_name;
+  bdd_node	*one = bdd_read_one(dd);
+  bdd_node	*zero = bdd_read_zero(dd);
+  bdd_node	*node;
+  int		pos, sizeZ = bdd_num_zdd_vars(dd);
+
+  if (tree->node == one || tree->node == zero)
+    return(ni);
+
+  if (tree->comp)
+    node = tree->complement;
+  else
+    node = tree->node;
+
+  support = ALLOC(int, sizeZ);
+  if (!support)
+    return(ni);
+  (void)memset((void *)support, 0, sizeof(int) * sizeZ);
+  SynthZddSupportStep(bdd_regular(node), support);
+  SynthZddClearFlag(bdd_regular(node));
+  for (i = 0; i < sizeZ; i++) {
+    if (support[i]) {
+      SynthGetPrimaryIndexName(net, i, name);
+      if (!st_lookup_int(table, (char *)name, (int *)(&pos))) {
+	st_name = ALLOC(char, strlen(name) + 1);
+	strcpy(st_name, name);
+	st_insert(table, (char *)st_name, (char *)(long)ni);
+	ni++;
+      }
+    }
+  }
+  FREE(support);
+  return(ni);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets a tautologous TruthTableLine.]
+
+  Description [Gets a tautologous TruthTableLine.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static TruthTableLine *
+GetTautologyLine(int ni)
+{
+  int			i;
+  TruthTableLine	*line;
+
+  line = ALLOC(TruthTableLine, 1);
+  (void)memset((void *)line, 0, sizeof(TruthTableLine));
+  line->values = (char *)malloc(ni + 1);
+  for (i = 0; i < ni; i++)
+    line->values[i] = '-';
+  line->values[ni] = '\0';
+  return(line);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets a list of TruthTableLine for a tree which is a leaf node.]
+
+  Description [Gets a list of TruthTableLine for a tree which is a leaf node.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static TruthTableLine *
+GetLeafLines(Ntk_Network_t *net,
+	     bdd_manager *dd,
+	     MlTree *tree,
+	     bdd_node **ofuncs,
+	     int no,
+	     st_table *table,
+	     int ni)
+{
+  int			i, *support;
+  char			values[MAX_EQ_LEN];
+  bdd_node		*one = bdd_read_one(dd);
+  bdd_node		*zero = bdd_read_zero(dd);
+  bdd_node		*node;
+  TruthTableLine	*line;
+  int			pos, sizeZ = bdd_num_zdd_vars(dd);
+  char			name[MAX_NAME_LEN];
+
+  line = (TruthTableLine *)NULL;
+
+  if (tree->node == one || tree->node == zero)
+    return(line);
+
+  if (tree->comp)
+    node = tree->complement;
+  else
+    node = tree->node;
+
+  support = ALLOC(int, sizeZ);
+  if (!support)
+    return(line);
+  (void)memset((void *)support, 0, sizeof(int) * sizeZ);
+  SynthZddSupportStep(bdd_regular(node), support);
+  SynthZddClearFlag(bdd_regular(node));
+  for (i = 0; i < sizeZ; i++) {
+    if (support[i]) {
+      SynthGetPrimaryIndexName(net, i, name);
+      if (!st_lookup_int(table, (char *)name, (int *)(&pos))) {
+	fprintf(vis_stdout,
+		"** synth error: Failed to find %s in hash.\n", name);
+      }
+      support[i] = pos;
+    }
+  }
+
+  for (i = 0; i < ni; i++)
+    values[i] = '-';
+  values[ni] = '\0';
+  line = GetBlifBinary(line, dd, node, values, support, ni);
+  FREE(support);
+  return(line);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Gets a list of TruthTableLine for a tree which is a leaf node.]
+
+  Description [Gets a list of TruthTableLine for a tree which is a leaf node.]
+
+  SideEffects []
+
+  SeeAlso     [GetLeafLines]
+
+******************************************************************************/
+static TruthTableLine *
+GetBlifBinary(TruthTableLine *line,
+	      bdd_manager *dd,
+	      bdd_node *node,
+	      char *values,
+	      int *support,
+	      int ni)
+{
+  bdd_node		*one = bdd_read_one(dd);
+  bdd_node		*zero = bdd_read_zero(dd);
+  TruthTableLine	*new_, *cur;
+  int			id = bdd_node_read_index(node);
+
+  if (node == zero)
+    return(line);
+
+  if (node == one) {
+    new_ = ALLOC(TruthTableLine, 1);
+    (void)memset((void *)new_, 0, sizeof(TruthTableLine));
+    new_->values = ALLOC(char,ni+1);
+    strcpy(new_->values, values);
+    if (line) {
+      cur = line;
+      while (cur->next)
+	cur = cur->next;
+      cur->next = new_;
+    } else
+      line = new_;
+    return(line);
+  }
+
+  if (id % 2 == 0)
+    values[support[id]] = '1';
+  else
+    values[support[id]] = '0';
+  line = GetBlifBinary(line, dd, bdd_bdd_T(node), values, support, ni);
+  values[support[id]] = '-';
+  line = GetBlifBinary(line, dd, bdd_bdd_E(node), values, support, ni);
+  values[support[id]] = '-';
+  return(line);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the complemented TruthTableLine only for the first one.]
+
+  Description [Returns the complemented TruthTableLine only for the first one.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static TruthTableLine *
+GetComplementOneLine(TruthTableLine *line,
+		     int ni,
+		     int flag)
+{
+  int			i;
+  TruthTableLine	*new_line, *start, *last;
+
+  start = last = (TruthTableLine *)NULL;
+
+  for (i = 0; i < ni; i++) {
+    if (line->values[i] != '-') {
+      new_line = GetTautologyLine(ni);
+      if (line->values[i] == '1')
+	new_line->values[i] = '0';
+      else
+	new_line->values[i] = '1';
+      if (last) {
+	last->next = new_line;
+	last = new_line;
+      } else
+	start = last = new_line;
+    }
+  }
+
+  if (flag) {
+    FREE(line->values);
+    FREE(line);
+  }
+
+  return(start);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the complemented TruthTableLine.]
+
+  Description [Returns the complemented TruthTableLine.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static TruthTableLine *
+GetComplementLines(TruthTableLine *lines,
+		   int ni,
+		   int flag)
+{
+  TruthTableLine	*first, *cur, *next;
+
+  if (!lines)
+    return(lines);
+
+  first = lines;
+  cur = first->next;
+  first = GetComplementOneLine(first, ni, flag);
+  while (cur) {
+    next = cur->next;
+    cur = GetComplementOneLine(cur, ni, flag);
+    first = GetAndLines(first, cur, ni, flag);
+    cur = next;
+  }
+  return(first);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the result of Boolean AND for two TruthTableLine.]
+
+  Description [Returns the result of Boolean AND for two TruthTableLine.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static TruthTableLine *
+GetAndLines(TruthTableLine *line1,
+	    TruthTableLine *line2,
+	    int ni,
+	    int flag)
+{
+  int			i;
+  TruthTableLine	*cur1, *cur2, *next1, *next2;
+  TruthTableLine	*start, *last;
+  TruthTableLine	*new_line;
+
+  start = last = (TruthTableLine *)NULL;
+
+  cur1 = line1;
+  while (cur1) {
+    next1 = cur1->next;
+    cur2 = line2;
+    while (cur2) {
+      new_line = GetTautologyLine(ni);
+      strcpy(new_line->values, cur1->values);
+      for (i = 0; i < ni; i++) {
+	if (cur2->values[i] != '-')
+	  new_line->values[i] = cur2->values[i];
+      }
+      if (last) {
+	last->next = new_line;
+	last = new_line;
+      } else {
+	start = last = new_line;
+      }
+      cur2 = cur2->next;
+    }
+    if (flag) {
+      FREE(cur1->values);
+      FREE(cur1);
+    }
+    cur1 = next1;
+  }
+
+  if (flag) {
+    cur2 = line2;
+    while (cur2) {
+      next2 = cur2->next;
+      FREE(cur2->values);
+      FREE(cur2);
+      cur2 = next2;
+    }
+  }
+
+  return(start);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the node or the complement node of a tree.]
+
+  Description [Returns the node or the complement node of a tree.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static bdd_node	*
+GetDdNodeOfMlTree(MlTree *tree,
+		  int comp)
+{
+  if (comp)
+    return(tree->complement);
+  return(tree->node);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the node name of a tree.]
+
+  Description [Gets the node name of a tree. Return value shows polarity;
+  0 means positive node and 1 means negative.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+GetMlTreeName(Ntk_Network_t *net,
+	      bdd_node **ofuncs,
+	      MlTree *tree,
+	      char *name)
+{
+  int	i, no;
+  int	polarity = 0; /* positive */
+
+  no = Ntk_NetworkReadNumCombOutputs(net) - Ntk_NetworkReadNumLatches(net);
+  for (i = 0; i < no; i++) {
+    if (tree->node == ofuncs[i]) {
+      sprintf(name, "%s", SynthGetIthOutputName(i));
+      break;
+    }
+  }
+  if (i == no) {
+    if (tree->pi)
+      polarity = SynthGetPrimaryNodeName(net, tree->node, name);
+    else
+      SynthGetInternalNodeName(name, tree->id);
+  }
+
+  return(polarity);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Gets the original name of a tree.]
+
+  Description [Gets the original name of a tree.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static char **
+GetAllVarNameArray(bdd_manager *dd)
+{
+  int		size, i, j;
+  mvar_type	var;
+  char		**nameArray, *name;
+
+  size = bdd_num_vars(dd);
+  nameArray = ALLOC(char *, size);
+  if (!nameArray)
+    return(NIL(char *));
+
+  for (i = 0; i < size; i++) {
+    var = mdd_get_var_by_id(dd, i);
+    name = ALLOC(char, strlen(var.name) + 1);
+    if (!name) {
+      for (j = 0; j < i; j++)
+	FREE(nameArray[j]);
+      FREE(nameArray);
+      return(NIL(char *));
+    }
+    strcpy(name, var.name);
+    nameArray[i] = name;
+  }
+  
+  return(nameArray);
+}
Index: vis_dev/vis-2.3/src/tbl/tbl.h
===================================================================
--- vis_dev/vis-2.3/src/tbl/tbl.h	(revision 14)
+++ vis_dev/vis-2.3/src/tbl/tbl.h	(revision 14)
@@ -0,0 +1,370 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [tbl.h]
+
+  PackageName [tbl]
+
+  Synopsis    [Routines for manipulating a multi-valued relation representation.]
+
+  Description [A Tbl_Table_t is a data structure that contains all the
+  information found in the blif_mv tables (refer to blif_mv document), and
+  represents a multivalued function or group of functions.
+  This can be thought of as a table with inputs and outputs, and the
+  entries in this table describe how the inputs are related to the outputs.
+
+  The entries in a table may be of two types: they are either a list of ranges
+  that contain values that an entry may take, or are set equal to some other
+  entry in the table. Notice that blif_mv files also have the complement
+  construct, which is absent in the table struct. There are functions for
+  complementing, and canonicalizing a  list of ranges]
+
+  SeeAlso     [tblInt.h, ntk.h]
+
+  Author      [ Gitanjali M. Swamy]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: tbl.h,v 1.15 2009/04/11 02:01:29 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _TBL
+#define _TBL
+#include "mvf.h"
+#include "mvfaig.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef enum {
+  Tbl_EntryEqual_c,
+  Tbl_EntryNormal_c,
+  Tbl_EntryUniverse_c,
+  Tbl_EntryUnassigned_c
+} Tbl_EntryType_t;
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef struct TblEntryStruct Tbl_Entry_t;
+typedef struct TblTableStruct Tbl_Table_t;
+typedef struct TblDataStruct Tbl_Data_t;
+typedef struct TblRowStruct Tbl_Row_t;
+typedef struct TblRangeStruct Tbl_Range_t;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**Macro***********************************************************************
+
+  Synopsis     [ Generates all entries of  the table.  ]
+
+  Description  [ This is an iterator that generates all entries
+		 of the  table in smallest column first, smallest row first
+		 and input first order. This must be
+		 supplied with int colNum, rowNum,i (flag to indicate output
+		 or input,  and Tbl_Entry_t * entry]
+
+  SideEffects  [ ]
+
+  SeeAlso      [ Tbl_TableForeachOutputEntry]
+
+******************************************************************************/
+#define Tbl_TableForEachEntry(                                               \
+/* Tbl_Table_t * */ table   /* The table to iterate over */,                 \
+/* int          */ rowNum  /* The row number            */,                  \
+/* int          */ colNum  /* The column number         */,                  \
+/* int          */  i       /* The input output flag     */,                 \
+/* Tbl_Entry_t * */ entry   /* The table entry */                            \
+)                                                                            \
+for(rowNum=0;rowNum<Tbl_TableReadNumRows(table); rowNum++)\
+ for(i=0; i<2; i++)\
+ for(colNum=0; \
+    ((colNum< Tbl_TableReadNumVars(table,i))\
+     &&(entry=Tbl_TableReadEntry(table,rowNum,colNum,i))); colNum++)
+
+/**Macro***********************************************************************
+
+  Synopsis     [ Generates all input entries of  the table.  ]
+
+  Description  [ This is an iterator that generates all input entries
+		 of the  table in smallest column first, smallest row first
+		 order. This must be supplied with int colNum, rowNum,
+		 Tbl_Row_t *row, and Tbl_Entry_t * entry]
+
+  SideEffects  [ ]
+
+  SeeAlso      [ Tbl_TableForeachOutputEntry]
+
+******************************************************************************/
+#define Tbl_TableForEachInputEntry(                                          \
+/* Tbl_Table_t * */ table   /* The table to iterate over */,                 \
+/* int           */ rowNum  /* The row number            */,                 \
+/* int           */ colNum  /* The column number         */,                 \
+/* Tbl_Entry_t * */ entry   /* The table entry */                            \
+)                                                                            \
+ for(rowNum=0;rowNum<Tbl_TableReadNumRows(table); rowNum++)\
+ for(colNum=0; \
+    ((colNum< Tbl_TableReadNumVars(table,0))\
+     &&(entry=Tbl_TableReadEntry(table,rowNum,colNum,0))); colNum++)
+
+/**Macro***********************************************************************
+
+  Synopsis     [ Generates all output entries of  the table.  ]
+
+  Description  [ This is an iterator that generates all entries
+		 of the  table in smallest column first, smallest row first.
+		 This must be supplied with int colNum, rowNum, Tbl_Row_t *row, and
+		 Tbl_Entry_t * entry]
+
+  SideEffects  [ ]
+
+  SeeAlso      [ Tbl_TableForEachInputEntry]
+
+******************************************************************************/
+#define Tbl_TableForEachOutputEntry(                                         \
+/* Tbl_Table_t * */ table   /* The table to iterate over */,                 \
+/* int           */ rowNum  /* The row number            */,                 \
+/* int           */ colNum  /* The column number         */,                 \
+/* Tbl_Entry_t * */ entry   /* The table entry */                            \
+)                                                                            \
+ for(rowNum=0;rowNum<Tbl_TableReadNumRows(table); rowNum++)\
+ for(colNum=0; \
+    ((colNum< Tbl_TableReadNumVars(table,1))\
+     &&(entry=Tbl_TableReadEntry(table,rowNum,colNum,1))); colNum++)
+
+/**Macro***********************************************************************
+
+  Synopsis     [ Generates all default entries in the table ]
+
+  Description  [ Given a table this iterates over all its default entries]
+
+  SideEffects  [ ]
+
+  SeeAlso      [ ]
+
+******************************************************************************/
+#define Tbl_TableForEachDefaultEntry(                                        \
+/* Tbl_Table_t * */ table   /* The table to iterate over */,                 \
+/* Tbl_Entry_t * */ entry   /* The table entry */,                           \
+/* int           */ index   /* The default entry index */                    \
+)                                                                            \
+ arrayForEachItem( Tbl_Entry_t*,Tbl_TableReadDefaults(table),index,entry)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Generates all input Var_Variable_t* associated with the table]
+
+  Description  [Given a table, this function iterates over all its input
+  Var_Variable_t*. This macro also provides the column number associated
+  with the var, and must be supplied with int index, and Var_Variable_t* var.]
+
+  SideEffects  []
+
+  SeeAlso      []
+
+******************************************************************************/
+#define Tbl_TableForEachInputVar(                                            \
+/* Tbl_Table_t * */ table   /* The table to iterate over */,                 \
+/* int           */ index   /* The var index */,                             \
+/* Var_Variable_t **/ var   /* The table var */                              \
+)                                                                            \
+ arrayForEachItem( Var_Variable_t*,Tbl_TableReadInputVars(table),index,var)
+
+/**Macro***********************************************************************
+
+  Synopsis     [Generates all output Var_Variable_t* associated with the table]
+
+  Description  [Given a table, this function iterates over all its output
+  Var_Variable_t*. This macro also provides the column number associated
+  with the var, and must be supplied with int index, and Var_Variable_t* var.]
+
+  SideEffects  []
+
+  SeeAlso      []
+
+******************************************************************************/
+#define Tbl_TableForEachOutputVar(                                           \
+/* Tbl_Table_t * */ table   /* The table to iterate over */,                 \
+/* int           */ index   /* The var index */,                             \
+/* Var_Variable_t **/ var   /* The table var */                              \
+)                                                                            \
+ arrayForEachItem( Var_Variable_t*,Tbl_TableReadOutputVars(table),index,var)
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [ Generates all items  in the output of a row of a  table ]
+
+  Description  [ Given a row number , this item iterates over all its output
+  entries.It provides the colnum and the entry at each iteration]
+
+  SideEffects  [ ]
+
+  SeeAlso      []
+
+******************************************************************************/
+#define Tbl_RowForEachOutputEntry(                                           \
+/* Tbl_Table_t * */ table   /* The table to iterate over */,                 \
+/* int           */ rowNum  /* The row number            */,                 \
+/* Tbl_Entry_t * */ entry   /* The table entry */,                           \
+/* int           */ colNum  /* The column number         */                  \
+)                                                                            \
+ for(colNum=0; \
+    ((colNum< Tbl_TableReadNumVars(table,1))\
+     &&(entry=Tbl_TableReadEntry(table,rowNum,colNum,1))); colNum++)
+
+/**Macro***********************************************************************
+
+  Synopsis     [ Generates all items  in the input of a row of a  table ]
+
+  Description  [ Given a row number, this item iterates over all its input
+  entries. It provides the colnum and the entry at each iteration]
+
+  SideEffects  [ ]
+
+  SeeAlso      []
+
+******************************************************************************/
+#define Tbl_RowForEachInputEntry(                                            \
+/* Tbl_Table_t * */ table   /* The table to iterate over */,                 \
+/* int           */ rowNum  /* The row number            */,                 \
+/* Tbl_Entry_t * */ entry   /* The table entry */,                           \
+/* int           */ colNum  /* The column number         */                  \
+)                                                                            \
+ for(colNum=0; \
+    ((colNum< Tbl_TableReadNumVars(table,0))\
+     &&(entry=Tbl_TableReadEntry(table,rowNum,colNum,0))); colNum++)
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Iterates over all the values in a Tbl_Entry_t]
+
+  Description  [Given a Tbl_Entry_t, this function iterates over all
+  values in the entry. This function has to supplied an int value, an
+  lsGen gen, and a Tbl_Range_t * range;]
+
+  SideEffects []
+
+  SeeAlso      []
+
+******************************************************************************/
+#define Tbl_EntryForEachValue(                                               \
+/* Tbl_Entry_t * */ entry   /* The table entry to iterate on */,             \
+/* int           */ value   /* The value at given iteration   */,            \
+/* lsGen         */ gen     /* The generator         */,                     \
+/* Tbl_Range_t * */ range   /* The range for each item  */                   \
+)                                                                            \
+ lsForEachItem(Tbl_EntryReadList(entry), gen, range)\
+ for(value=Tbl_RangeBegin(range); value<= Tbl_RangeEnd(range); value++)
+
+#include "var.h"
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN MvfAig_Function_t * Tbl_TableBuildNonDetConstantMvfAig(Tbl_Table_t *table, int outIndex, int mAigId, mAig_Manager_t *manager);
+EXTERN MvfAig_Function_t * Tbl_TableBuildMvfAigFromFanins(Tbl_Table_t * table, int outIndex, array_t * faninArray, mAig_Manager_t *manager);
+EXTERN Tbl_Entry_t* Tbl_EntryAlloc(Tbl_EntryType_t type);
+EXTERN void Tbl_EntryFree(Tbl_Entry_t * entry);
+EXTERN Tbl_Entry_t * Tbl_EntryDup(Tbl_Entry_t *entry);
+EXTERN void Tbl_EntrySetValue(Tbl_Entry_t * entry, int val1, int val2);
+EXTERN Tbl_Entry_t* Tbl_EntryMerge(Tbl_Entry_t* entry1, Tbl_Entry_t* entry2);
+EXTERN void Tbl_EntryComplement(Tbl_Entry_t * entry, int min, int max);
+EXTERN void Tbl_EntrySetEqual(Tbl_Entry_t * entry, int varCol);
+EXTERN boolean Tbl_EntryCheckRange(Tbl_Entry_t * entry, int val1, int val2);
+EXTERN boolean Tbl_EntryIsEqual(Tbl_Entry_t *entry);
+EXTERN Var_Variable_t* Tbl_EntryReadActualVar(Tbl_Table_t *table, Tbl_Entry_t *entry);
+EXTERN Var_Variable_t* Tbl_EntryReadVar(Tbl_Table_t *table, Tbl_Entry_t *entry);
+EXTERN int Tbl_EntryReadVarIndex(Tbl_Entry_t * entry);
+EXTERN int Tbl_EntryReadNumValues(Tbl_Entry_t * entry);
+EXTERN boolean Tbl_EntryTestEqualEntry(Tbl_Entry_t * entrya, Tbl_Entry_t * entryb);
+EXTERN boolean Tbl_EntryTestIntersectEntry(Tbl_Entry_t * entrya, Tbl_Entry_t * entryb);
+EXTERN lsList Tbl_EntryReadList(Tbl_Entry_t * entry);
+EXTERN Tbl_EntryType_t Tbl_EntryReadType(Tbl_Entry_t *entry);
+EXTERN int Tbl_RangeBegin(Tbl_Range_t *range);
+EXTERN int Tbl_RangeEnd(Tbl_Range_t *range);
+EXTERN Tbl_Table_t* Tbl_TableCollapse(Tbl_Table_t* table1, Tbl_Table_t* table2, int index);
+EXTERN Tbl_Table_t * Tbl_TableInvertBinaryInputColumn(Tbl_Table_t *table, int index);
+EXTERN void Tbl_Init(void);
+EXTERN void Tbl_End(void);
+EXTERN Tbl_Table_t* Tbl_TableAlloc(void);
+EXTERN void Tbl_TableFree(Tbl_Table_t * table);
+EXTERN Tbl_Table_t * Tbl_TableSoftDup(Tbl_Table_t * table);
+EXTERN Tbl_Table_t * Tbl_TableHardDup(Tbl_Table_t * table);
+EXTERN boolean Tbl_TableDefaultSetEntry(Tbl_Table_t *table, Tbl_Entry_t *entry, int index);
+EXTERN Tbl_Entry_t* Tbl_TableDefaultReadEntry(Tbl_Table_t *table, int index);
+EXTERN int Tbl_TableAddRow(Tbl_Table_t * table);
+EXTERN int Tbl_TableAddColumn(Tbl_Table_t * table, Var_Variable_t * var, int flag);
+EXTERN Tbl_Table_t * Tbl_TableRowDelete(Tbl_Table_t *originalTable, int rowNumToDelete, array_t *freeArray);
+EXTERN Var_Variable_t* Tbl_TableReadIndexVar(Tbl_Table_t * table, int index, int flag);
+EXTERN Tbl_Entry_t * Tbl_TableReadEntry(Tbl_Table_t * table, int rowNum, int colNum, int flag);
+EXTERN boolean Tbl_TableSetEntry(Tbl_Table_t * table, Tbl_Entry_t * newEntry, int i, int j, int flag);
+EXTERN boolean Tbl_TableSetEntryDc(Tbl_Table_t * table, int i, int j, int flag);
+EXTERN void Tbl_TableAddEntryRange(Tbl_Table_t * table, int i, int j, int val1, int val2, int flag);
+EXTERN void Tbl_TableComplementEntry(Tbl_Table_t * table, int i, int j, int flag);
+EXTERN void Tbl_TableSetEquality(Tbl_Table_t * table, int i, int j, int flag, Var_Variable_t * var);
+EXTERN boolean Tbl_TableEntryIsDc(Tbl_Table_t * table, int i, int j, int flag);
+EXTERN boolean Tbl_TableTestIsConstant(Tbl_Table_t * table, int outputColumnId);
+EXTERN boolean Tbl_TableTestIsNonDeterministicConstant(Tbl_Table_t * table, int outputColumnId);
+EXTERN int Tbl_TableTestIsDeterministic(Tbl_Table_t * table);
+EXTERN boolean Tbl_TableTestIsOutputSpaceComplete(Tbl_Table_t *table, mdd_manager *mddMgr);
+EXTERN array_t * Tbl_TableComputeMvfAndInputDependenciesOfOutput(Tbl_Table_t *table, mdd_manager *mddMgr, int outIndex, int *value);
+EXTERN Tbl_Table_t* Tbl_TableCreateTrueSupportTableForOutput(Tbl_Table_t *table, Mvf_Function_t *outMvf, mdd_manager *mddMgr, int offset, int outIndex, array_t *varMap);
+EXTERN boolean Tbl_TableSwapRows(Tbl_Table_t * table, int i, int j);
+EXTERN boolean Tbl_TableSwapColumns(Tbl_Table_t * table, int i, int j, int flag);
+EXTERN void Tbl_TableCanonicalize(Tbl_Table_t * table);
+EXTERN boolean Tbl_TableRowDominatesRow(Tbl_Table_t *table, int rowa, int rowb, array_t *rowValArray);
+EXTERN boolean Tbl_TableColDominatesCol(Tbl_Table_t *table, int cola, int colb, int flag, Tbl_Row_t *colValArray);
+EXTERN boolean Tbl_TablesAreIdentical(Tbl_Table_t *tablea, Tbl_Table_t *tableb, int a, int b);
+EXTERN mdd_t * Tbl_TableRowToMdd(Tbl_Table_t * table, mdd_manager * manager, int i, array_t * svArray);
+EXTERN Mvf_Function_t * Tbl_TableBuildNonDetConstantMvf(Tbl_Table_t * table, int outIndex, int mddId, mdd_manager * mddMgr);
+EXTERN Mvf_Function_t * Tbl_TableBuildMvfFromFanins(Tbl_Table_t * table, int outIndex, array_t * faninArray, mdd_manager * mddMgr);
+EXTERN int Tbl_TableReadConstValue(Tbl_Table_t * table, int outputColumnId);
+EXTERN Tbl_Table_t * Tbl_MddToTable(mdd_t * mdd, mdd_manager * manager, st_table * idtoVar, array_t * inputids);
+EXTERN boolean Tbl_TableSubstituteVar(Tbl_Table_t * table, Var_Variable_t * oldVar, Var_Variable_t * newVar);
+EXTERN void Tbl_TableSetVar(Tbl_Table_t * table, int i, Var_Variable_t * sv, int flag);
+EXTERN array_t * Tbl_TableSplit(Tbl_Table_t * table);
+EXTERN int Tbl_TableReadNumInputs(Tbl_Table_t * table);
+EXTERN int Tbl_TableReadNumOutputs(Tbl_Table_t * table);
+EXTERN int Tbl_TableReadNumVars(Tbl_Table_t *table, int flag);
+EXTERN int Tbl_TableReadNumRows(Tbl_Table_t * table);
+EXTERN int Tbl_TableReadVarIndex(Tbl_Table_t * table, Var_Variable_t * var, int flag);
+EXTERN void Tbl_TablePrintStats(Tbl_Table_t *table, FILE *fp);
+EXTERN void Tbl_TableWriteBlifMvToFileSpecial(Tbl_Table_t *table, int flag, FILE *fp);
+EXTERN void Tbl_TableWriteBlifMvToFile(Tbl_Table_t *table, int flag, FILE *fp);
+EXTERN void Tbl_TableWriteSmvToFile(Tbl_Table_t *table, int flag, FILE *fp);
+EXTERN void Tbl_TableWriteBlifToFile(Tbl_Table_t *table, FILE *fp);
+EXTERN array_t* Tbl_TableReadDefaults(Tbl_Table_t * table);
+EXTERN array_t* Tbl_TableReadInputVars(Tbl_Table_t * table);
+EXTERN array_t* Tbl_TableReadOutputVars(Tbl_Table_t * table);
+EXTERN boolean Tbl_RowInputIntersect(Tbl_Table_t * table, int a, int b);
+EXTERN boolean Tbl_RowOutputIntersect(Tbl_Table_t * table, int a, int b);
+EXTERN boolean Tbl_TableIsIdentity(Tbl_Table_t *table);
+EXTERN boolean Tbl_TableIsInverter(Tbl_Table_t *table);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /*_TBL */
Index: vis_dev/vis-2.3/src/tbl/tbl.make
===================================================================
--- vis_dev/vis-2.3/src/tbl/tbl.make	(revision 14)
+++ vis_dev/vis-2.3/src/tbl/tbl.make	(revision 14)
@@ -0,0 +1,4 @@
+CSRC += tblEntryUtil.c tblTest.c tblUtil.c tblSweep.c tblAigUtil.c tblAigEntryUtil.c tblIdentity.c
+HEADERS += tbl.h tblInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/tbl/tblAigEntryUtil.c
===================================================================
--- vis_dev/vis-2.3/src/tbl/tblAigEntryUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/tbl/tblAigEntryUtil.c	(revision 14)
@@ -0,0 +1,117 @@
+/**CFile***********************************************************************
+
+  FileName    [tblAigEntryUtil.c]
+
+  PackageName [tbl]
+
+  Synopsis    []
+
+  Description [Defines functions to manuplate table Entry using And/Inverter graph]
+
+  SeeAlso     [tblUtil.c, tblAigUtil.c]
+
+  Author      [Mohammad Awedh]
+
+  Copyright   []
+
+******************************************************************************/
+
+#include "tblInt.h"
+#include "baig.h"
+
+static char rcsid[] UNUSED = "$Id: tblAigEntryUtil.c,v 1.4 2005/04/17 14:37:23 awedh Exp $";
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the mAigEdge_t for a table entry]
+
+  Description [Given an array of constituent mAigEdge_t, and a table entry, this returns
+  an mAig for the entry. The array of mAigEdge_t's must contain an mAigEdge_t for value i in
+  position i, for all values i.]
+
+  SideEffects []
+
+  SeeAlso     []
+[Done]
+******************************************************************************/
+mAigEdge_t
+TblEntryNormalConstructAig(
+    mAig_Manager_t *manager,
+    Tbl_Entry_t    *entry,
+    array_t        *mAigArray)
+{
+  lsGen gen;
+  Tbl_Range_t *range;
+  int i;
+  mAigEdge_t result, temp, x;
+    
+  result = mAig_Zero;
+  lsForEachItem(entry->EntryData.listOfRanges, gen, range) {
+    for (i=range->begin; i< (range->end +1); i++) {
+      temp = result;
+      x = MvfAig_FunctionReadComponent(mAigArray,i);
+      result = mAig_Or(manager, temp, x);
+    }
+  }
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the mAigEdge_t for a table entry]
+
+  Description [Given an array of constituent mAigEdge_t, and a table entry, this returns
+  an mAig for the entry. The array of mAigEdge_t's must contain an mAigEdge_t for value i in
+  position i, for all values i.]
+
+  SideEffects []
+
+  SeeAlso     []
+[Done]
+******************************************************************************/
+mAigEdge_t 
+TblEntryEqualConstructMAig(
+    mAig_Manager_t    * manager,
+    Tbl_Entry_t       * entry,
+    MvfAig_Function_t * mAigArray,
+    MvfAig_Function_t * mEigArray)
+{
+  lsGen        gen;
+  Tbl_Range_t *range;
+  int          i;
+  mAigEdge_t   result, temp, x;
+
+  assert(entry->type == Tbl_EntryNormal_c);
+  result = mAig_Zero;
+  lsForEachItem(entry->EntryData.listOfRanges, gen, range) {
+    for (i=range->begin; i< (range->end +1); i++) {
+      temp = result;
+      x = MvfAig_FunctionReadComponent(mAigArray,i);
+      result = mAig_Or(manager, temp, x);
+      temp = result;
+      x = MvfAig_FunctionReadComponent(mAigArray,i);
+      result = mAig_Or(manager, temp, x);
+    }
+  }
+  return result;
+}
+
+
+
Index: vis_dev/vis-2.3/src/tbl/tblAigUtil.c
===================================================================
--- vis_dev/vis-2.3/src/tbl/tblAigUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/tbl/tblAigUtil.c	(revision 14)
@@ -0,0 +1,245 @@
+/**CFile***********************************************************************
+
+  FileName    [ tblAigUtil.c ]
+
+  PackageName [ tbl ]
+
+  Synopsis    []
+
+  Description []
+
+  SeeAlso     [ tbl.h, tblEntryUtil.c, tblAigEntryUtil, tblUtil.c ]
+
+  Author      [Mohammad Awedh ]
+
+  Copyright   []
+
+******************************************************************************/
+#include "tblInt.h"
+#include "baig.h"
+
+static char rcsid[] UNUSED = "$Id: tblAigUtil.c,v 1.3 2005/04/17 14:37:23 awedh Exp $";
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Compute the Mvf_Function_t for a non-deterministic constant.]
+
+  Description [Given a Tbl_Table_t, an integer for the  table output value
+  index, an integer MAigId, and an mAig Manager, this function builds the
+  MvfAig_Function_t associated with the output. The table cannot have
+  any inputs; the function fails if it does. The output cannot be equal to
+  another output, because this would make the table a relation, and that is
+  not permissible. If this occurs, the function will fail on an assert
+  statement.]
+
+  SideEffects [ Table must have no inputs.]
+
+  SeeAlso     []
+[Done]
+******************************************************************************/
+MvfAig_Function_t *
+Tbl_TableBuildNonDetConstantMvfAig(
+  Tbl_Table_t       *table,
+  int                outIndex,
+  int                mAigId,
+  mAig_Manager_t    *manager)
+{
+
+  lsGen gen;
+  Tbl_Entry_t       *entry;
+  Tbl_Range_t       *range;
+  int value,         rowNum, colNum;
+  mAigEdge_t         x;
+  MvfAig_Function_t *function;
+  
+  assert(Tbl_TableReadNumInputs(table) ==0);
+
+  value = Var_VariableReadNumValues(Tbl_TableReadIndexVar(table, outIndex, 1));
+  function = MvfAig_FunctionAlloc(value);  
+  Tbl_TableForEachOutputEntry(table,rowNum,colNum,entry) {
+    if (colNum == outIndex) {
+      assert(entry->type == Tbl_EntryNormal_c);
+      Tbl_EntryForEachValue(entry,value,gen,range) {
+        x = mAig_EquC(manager, mAigId, value);
+        MvfAig_FunctionAddMintermsToComponent(manager, function, value, x);
+      }
+    }
+  }
+  return function;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compute the Mvf_Function_t for a table output in terms of fanins]
+
+  Description [Given a Tbl_Table_t, an integer for the  table output value
+  index, an array of fanin mAigEdge_t* , and an mAigManager, this function builds the
+  MvfAig_Function_t associated with the output. The output cannot be equal to
+  another output, because this would make the table a relation, and that is
+  not permissible.  For each row, the function will build the mAigEdge_t for the inputs
+  using their MvfAig_Function_t's and AND them together. If the input is of the
+  type equal, it will build the equivalent set mAig (see See Also) and AND it in.
+  If the input of the type Tbl_EntryUniverse_c, this input will be set tomAig_One.] 
+
+  SideEffects [ ]
+
+  SeeAlso     [ MvfAig_FunctionComputeEquivalentSet, TblEntryNormalConstructAig]
+[Done]
+******************************************************************************/
+MvfAig_Function_t *
+Tbl_TableBuildMvfAigFromFanins(
+  Tbl_Table_t * table,
+  int outIndex,
+  array_t * faninArray,
+  mAig_Manager_t *manager)
+{
+
+  lsGen gen;
+  Tbl_Entry_t *entry, *equalEntry, *inputEntry;
+  Tbl_Range_t *range;
+  int         value, rowNum, colNum, rowColNum, i;
+  mAigEdge_t  x, result, temp;
+  MvfAig_Function_t *function, *mvf1, *mvf2;
+  
+
+  x = mAig_NULL;
+  value = Var_VariableReadNumValues(Tbl_TableReadIndexVar(table,outIndex,1));
+  function = MvfAig_FunctionAlloc(value);
+  
+  Tbl_TableForEachOutputEntry(table,rowNum,colNum,entry) {
+    if (colNum == outIndex) {
+      if (entry->type == Tbl_EntryNormal_c) {
+        result = mAig_One;
+        Tbl_RowForEachInputEntry(table,rowNum,inputEntry,rowColNum) {
+          if (inputEntry->type == Tbl_EntryNormal_c) {
+            mvf1 = array_fetch(MvfAig_Function_t*,faninArray,rowColNum);
+            x = TblEntryNormalConstructAig(manager, inputEntry, mvf1);
+          }
+          else if (inputEntry->type == Tbl_EntryUniverse_c) {
+            x = mAig_One;
+          }
+          else if (inputEntry->type == Tbl_EntryEqual_c) {
+            value =Tbl_EntryReadVarIndex(inputEntry);
+            mvf1 = array_fetch(MvfAig_Function_t*,faninArray,rowColNum);
+            mvf2 = array_fetch(MvfAig_Function_t*,faninArray,value);
+            x = MvfAig_FunctionsComputeEquivalentSet(manager, mvf1,mvf2);
+          }
+          temp = result;
+          result = mAig_And(manager, x,temp);
+        }
+        /* add the result to each value of the output */
+        Tbl_EntryForEachValue(entry,value,gen,range) {  
+          MvfAig_FunctionAddMintermsToComponent(manager, function, value,result);
+        }
+        
+      } /* output is not Normal */
+      else  if (entry->type == Tbl_EntryEqual_c) {
+        value = Tbl_EntryReadVarIndex(entry);
+        if (value == -1) {
+        fail("Failure: Not equal to any input var in this table\n");
+        }
+                  
+        /* must be equal to an input */
+        
+        equalEntry = Tbl_TableReadEntry(table,rowNum,value,0);
+        result = mAig_One;
+        Tbl_RowForEachInputEntry(table,rowNum,inputEntry,rowColNum) {
+          if (inputEntry->type == Tbl_EntryNormal_c) {
+            /* Don't include this input if the output is set be equal to it
+	     */
+            if ( inputEntry == equalEntry){
+              continue;
+            }
+            mvf1 = array_fetch(MvfAig_Function_t*,faninArray,rowColNum);
+            x = TblEntryNormalConstructAig(manager, inputEntry, mvf1);
+          }
+          else if (inputEntry->type == Tbl_EntryUniverse_c) {
+            x = mAig_One;
+          }
+          else if (inputEntry->type == Tbl_EntryEqual_c) {
+            value =Tbl_EntryReadVarIndex(inputEntry);
+            mvf1 = array_fetch(MvfAig_Function_t*,faninArray,rowColNum);
+            mvf2 = array_fetch(MvfAig_Function_t*,faninArray,value);
+            x = MvfAig_FunctionsComputeEquivalentSet(manager, mvf1,mvf2);
+          }
+          temp = result;
+          result = mAig_And(manager, x, temp);
+        }
+
+        temp = result;
+        rowColNum = Tbl_EntryReadVarIndex(entry);
+        mvf1 = array_fetch(MvfAig_Function_t*, faninArray, rowColNum);        
+
+        if (equalEntry->type == Tbl_EntryNormal_c) {
+          /* add the result to each value of the equal input */
+          Tbl_EntryForEachValue(equalEntry, value, gen, range) { 
+            x = MvfAig_FunctionReadComponent(mvf1, value);
+            result = mAig_And(manager, temp, x);
+            MvfAig_FunctionAddMintermsToComponent(manager, function, value, result);
+	  }
+        }else { /* Add Minterms for all vlaues */
+          value = Var_VariableReadNumValues(Tbl_EntryReadActualVar(table, equalEntry));
+          for(i=0; i< value; i++) {
+            x = MvfAig_FunctionReadComponent(mvf1,i);
+            result = mAig_And(manager, temp, x);
+            MvfAig_FunctionAddMintermsToComponent(manager, function, i,result);
+          }
+	}
+      }  
+    }
+  }
+
+  /* accounting for the defaults */
+  entry = Tbl_TableDefaultReadEntry(table,outIndex);
+  if (entry != NIL(Tbl_Entry_t)) {  
+    temp = MvfAig_FunctionComputeDomain(manager, function);
+    result = mAig_Not(temp);
+
+    if (entry->type == Tbl_EntryNormal_c) {    
+      Tbl_EntryForEachValue(entry,value,gen,range) {
+        MvfAig_FunctionAddMintermsToComponent(manager, function, value, result);
+      }
+    }
+    else {
+      value = Tbl_EntryReadVarIndex(entry);
+      if (value == -1) {
+        fail("Failure: Not equal to any input var in this table\n");
+      }
+      mvf1 = array_fetch(MvfAig_Function_t*, faninArray, value);
+      
+      MvfAig_FunctionForEachComponent(mvf1, i, x) {
+        temp = mAig_And(manager, x, result);
+        MvfAig_FunctionAddMintermsToComponent(manager, function, i ,temp);
+      }
+    }
+    
+  }
+        
+  return function;  
+}
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/tbl/tblEntryUtil.c
===================================================================
--- vis_dev/vis-2.3/src/tbl/tblEntryUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/tbl/tblEntryUtil.c	(revision 14)
@@ -0,0 +1,1280 @@
+/**CFile***********************************************************************
+
+  FileName    [tblEntryUtil.c]
+
+  PackageName [tbl]
+
+  Synopsis    [This package describes functions used to manipulate the
+               Tbl_Entry_t ,Tbl_Row_t and Tbl_Range_t structs]
+
+  Description []
+
+  SeeAlso     [tblUtil.c]
+
+  Author      [Gitanjali M. Swamy]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "tblInt.h"
+
+static char rcsid[] UNUSED = "$Id: tblEntryUtil.c,v 1.16 2009/04/11 02:01:29 fabio Exp $";
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int RangeCompare(lsGeneric entry1, lsGeneric entry2);
+static void EntryCanonicalize(Tbl_Entry_t * entry);
+static void EntryComplement(Tbl_Entry_t * entry, int min, int max);
+
+/**AutomaticEnd***************************************************************/
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [This function allocates space for a table entry.]
+
+  Description [This function allocates space for a table entry and must be passed
+               the type of the entry (Tbl_EntryEqual_c or Tbl_EntryNormal_c) as a parameter]
+
+  SideEffects []
+
+  SeeAlso     [TblEntryFree]
+
+******************************************************************************/
+Tbl_Entry_t*
+Tbl_EntryAlloc(
+  Tbl_EntryType_t  type)
+{
+  Tbl_Entry_t *entry;
+
+  entry = ALLOC(Tbl_Entry_t,1);
+  entry->type = type;
+  if (type == Tbl_EntryEqual_c) {
+    entry->EntryData.var = -1;
+  }
+  else if (type == Tbl_EntryNormal_c) {
+    entry->EntryData.listOfRanges = lsCreate();
+  }
+  return entry;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [This frees a given Tbl_Entry_t]
+
+  Description [This function frees the memory associated with a Tbl_Entry_t that
+               is given as input]
+
+  SideEffects [ The Var_Variable_t must be freed by the user]
+
+  SeeAlso     [TblEntryAlloc]
+
+******************************************************************************/
+void
+Tbl_EntryFree(
+  Tbl_Entry_t * entry)
+{
+  if (entry->type == Tbl_EntryNormal_c) {
+    lsDestroy(entry->EntryData.listOfRanges,(void (*)(lsGeneric))TblRangeFree);
+  }
+
+  FREE(entry);
+  entry = NIL(Tbl_Entry_t);
+}
+/**Function********************************************************************
+
+  Synopsis    [Duplicate a Tbl_Entry_t ]
+
+  Description [Given a Tbl_Entry_t, this function duplicates it. The new
+  entry does not belong to any table.]
+
+  SideEffects [Warning: For an entry of type Tbl_EntryEqual_c, this will
+  merely duplicate the column number of the equal type with no consistancy
+  checks. It is inadvisable to use this if you do not ensure that the
+  column variable corresponding to this id is what it is indeed equal to]
+
+  SeeAlso     [Tbl_TableSetEntry]
+
+******************************************************************************/
+Tbl_Entry_t *
+Tbl_EntryDup(
+  Tbl_Entry_t *entry)
+{
+  Tbl_Entry_t *newEntry;
+  lsGen gen;
+  Tbl_Range_t *range;
+
+  assert(entry != NIL(Tbl_Entry_t));
+  assert(entry->type != Tbl_EntryUnassigned_c);
+
+  newEntry = Tbl_EntryAlloc(entry->type);
+  newEntry->ioType = entry->ioType;
+  newEntry->varColNum = entry->varColNum;
+  
+  if (entry->type == Tbl_EntryNormal_c) {
+    lsForEachItem(entry->EntryData.listOfRanges, gen, range) {
+      Tbl_Range_t *newRange = ALLOC(Tbl_Range_t,1);
+      newRange->begin = range->begin;
+      newRange->end = range->end;
+      lsNewEnd(newEntry->EntryData.listOfRanges,(lsGeneric)newRange,LS_NH);     
+ 
+    }
+  }
+  else if (entry->type == Tbl_EntryEqual_c) {
+    newEntry->EntryData.var = entry->EntryData.var;
+  }
+  return newEntry;
+}
+        
+
+/**Function********************************************************************
+
+  Synopsis    [Set value of entry to range val1-val2]
+
+  Description [Given an entry and a range designated by val1-val2, this function
+                sets the entry value to val1-val2. If the entry was already set
+                then it adds the value to the end, and also canonicalizes the list]
+
+  SideEffects [If the entry was already set then it adds the value to the end]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Tbl_EntrySetValue(
+  Tbl_Entry_t *  entry,
+  int  val1,
+  int  val2)
+{
+  Tbl_Range_t *range;
+
+  assert(val2 >= val1);
+  assert(val1 >= 0);
+
+  entry->type = Tbl_EntryNormal_c;
+  range  = ALLOC(Tbl_Range_t,1);
+  range->begin = val1;
+  range->end = val2;
+  lsNewEnd(entry->EntryData.listOfRanges,(lsGeneric)range,LS_NH);
+  EntryCanonicalize(entry);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Given two Tbl_Entry_t's this function merges them into one.]
+
+  Description [Given two Tbl_entry_t* and b , this function  returns new
+  Tbl_Entry_t* that is the union of them.]
+
+  SideEffects [Both Tbl_Entries must be of the type Tbl_EntryNormal_c]
+
+  SeeAlso     []
+
+******************************************************************************/
+Tbl_Entry_t*
+Tbl_EntryMerge(
+    Tbl_Entry_t* entry1,
+    Tbl_Entry_t* entry2)
+{
+  lsGen gen, gen2,newGen;
+  Tbl_Range_t *range, *newRange;
+  Tbl_Entry_t *newEntry;
+    
+  if ((entry1->type == Tbl_EntryEqual_c)||(entry2->type ==
+                                            Tbl_EntryEqual_c)) {
+    return NIL(Tbl_Entry_t);
+  }
+
+  if ((entry1->type == Tbl_EntryUnassigned_c)||(entry2->type ==
+                                                 Tbl_EntryUnassigned_c)) {
+    return NIL(Tbl_Entry_t);
+  }
+
+  newEntry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+  newGen = lsStart(newEntry->EntryData.listOfRanges);
+  lsForEachItem(entry1->EntryData.listOfRanges, gen, range) {
+    newRange = ALLOC(Tbl_Range_t,1);
+    newRange->begin = range->begin;
+    newRange->end = range->end;
+    lsInAfter(newGen,(lsGeneric)newRange,LS_NH);
+  }
+  lsForEachItem(entry2->EntryData.listOfRanges, gen2, range) {
+    newRange = ALLOC(Tbl_Range_t,1);
+    newRange->begin = range->begin;
+    newRange->end = range->end;
+    lsInAfter(newGen,(lsGeneric)newRange,LS_NH);
+  }
+  EntryCanonicalize(newEntry);
+  lsFinish(newGen);
+  return newEntry;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Complement the entry]
+
+  Description [Given an entry, and the associated minimum and maximum values of
+  the entry, this function  complements it]
+
+  SideEffects [Old entry is lost]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Tbl_EntryComplement(
+  Tbl_Entry_t *  entry,
+  int min,
+  int max)
+{
+  EntryComplement(entry, min, max);
+  EntryCanonicalize(entry);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets entry equal to given Var]
+
+  Description [Given an Entry and an int, this sets the entry equal
+              to the column varCol. The Var must be part of the table]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Tbl_EntrySetEqual(
+  Tbl_Entry_t *  entry,
+/*  Var_Variable_t *  var*/
+  int varCol)
+{
+  entry->type=Tbl_EntryEqual_c;
+  entry->EntryData.var = varCol;   
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Check if values in entry data are from val1-val2
+               alone.]
+
+  Description [Given an entry and a range val1-val2, then this function
+               returns a 1 if every value in the entry  is
+               in the range val1-val2.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+Tbl_EntryCheckRange(
+  Tbl_Entry_t *  entry,
+  int  val1,
+  int  val2)
+{
+  lsGen gen;
+  lsGeneric data;
+  Tbl_Range_t *range;
+  
+  gen = lsStart(entry->EntryData.listOfRanges);
+  while (lsNext(gen, &data, LS_NH) == LS_OK) {
+    range = (Tbl_Range_t*)data;
+    if (range->begin < val1) {
+      lsFinish(gen);
+      return FALSE;
+    }
+    if (range->end > val2) {
+      lsFinish(gen);      
+      return FALSE;
+    }
+  }
+  lsFinish(gen);  
+  return TRUE;
+}
+
+/**Function********************************************************************
+
+  Synopsis     [Test if entry is of type equal]
+
+  Description  [optional]
+
+  SideEffects  [required]
+
+  SeeAlso      [optional]
+
+******************************************************************************/
+boolean Tbl_EntryIsEqual(
+  Tbl_Entry_t *entry)
+{
+  return (entry->type==Tbl_EntryEqual_c);
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [return the actual variable associated with an entry]
+
+  Description [Given an entry and a table, this function will return the
+  actual Var_Variable_t in the table associated with this entry]
+
+  SideEffects []
+
+  SeeAlso     [Tbl_EntryReadVar]
+
+******************************************************************************/
+Var_Variable_t*
+Tbl_EntryReadActualVar(
+    Tbl_Table_t *table,
+    Tbl_Entry_t *entry)
+{
+  array_t *carray;
+
+  if (entry->ioType==0) {
+    carray = table->inputNames;
+  }
+  else if (entry->ioType==1) {
+    carray = table->outputNames;
+  }
+  else return NIL(Var_Variable_t);         
+    
+  return (array_fetch(Var_Variable_t*,carray,entry->varColNum));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [return the equal variable associated with an entry]
+
+  Description [Given an entry and a table, this function will return the
+  Equal Var_Variable_t in the table associated with this entry]
+
+  SideEffects []
+
+  SeeAlso     [Tbl_EntryReadActualVar]
+
+******************************************************************************/
+Var_Variable_t*
+Tbl_EntryReadVar(
+    Tbl_Table_t *table,
+    Tbl_Entry_t *entry)
+{
+  array_t *carray;
+  
+  carray = table->inputNames;
+  if (array_n(carray) < Tbl_EntryReadVarIndex(entry)) {
+    fail(" FAIL: equal to output not supported\n");
+  }
+  return (array_fetch(Var_Variable_t*,carray,Tbl_EntryReadVarIndex(entry)));
+}
+
+/**Function********************************************************************
+
+  Synopsis    [This function returns  the index associated with the entry. The
+   entry must be of the type equal]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Tbl_EntryReadVarIndex(
+  Tbl_Entry_t * entry)
+{
+  assert(entry->type == Tbl_EntryEqual_c);
+  return (entry->EntryData.var);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return Num of values in an entry]
+
+  Description [Given a Tbl_Entry_t, this function will return the number of
+  values that the variable in the entry actually takes. Note that the possible
+  number of values might be much larger]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Tbl_EntryReadNumValues(
+  Tbl_Entry_t * entry)
+{
+  lsGen gen;
+  int numOfValues;
+  Tbl_Range_t *range;
+
+  numOfValues = 0;
+  assert(entry->type == Tbl_EntryNormal_c);    
+  lsForEachItem(entry->EntryData.listOfRanges, gen, range) {
+    numOfValues = numOfValues + (range->end - range->begin + 1);
+  }
+  return (numOfValues);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Compare two entries]
+
+  Description [Given two  Tbl_Entry_t, this function will compare them to
+  see if they are equal. Both the entries must be canonical, and of the
+  type Tbl_EntryNormal_c]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+Tbl_EntryTestEqualEntry(
+  Tbl_Entry_t * entrya,
+  Tbl_Entry_t * entryb)
+{
+  lsGen gena;
+  lsGen genb;  
+  Tbl_Range_t *rangea;
+  Tbl_Range_t *rangeb;
+  lsGeneric data;
+
+  assert(entrya->type == Tbl_EntryNormal_c);
+  assert(entryb->type == Tbl_EntryNormal_c);
+
+  if (lsLength(entrya->EntryData.listOfRanges) != \
+      lsLength(entryb->EntryData.listOfRanges))   {
+    return FALSE;
+  }
+
+  genb = lsStart(entryb->EntryData.listOfRanges);  
+  lsForEachItem(entrya->EntryData.listOfRanges, gena, rangea) {
+    if (lsNext(genb, &data,LS_NH) == LS_OK) {
+      rangeb = (Tbl_Range_t*)data;                        
+      if (rangea->begin != rangeb->begin) {
+	lsFinish(gena);
+	lsFinish(genb);
+	return FALSE;
+      }
+      if (rangea->end != rangeb->end){
+	lsFinish(gena);
+	lsFinish(genb);
+	return FALSE;
+      }
+    }
+    else {
+      return FALSE;
+    }
+  }
+  return TRUE;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Compare two entries to see if they intersect ]
+
+  Description [Given two  Tbl_Entry_t, this function will compare them to
+  see if they intersect. Both the entires must be canonical, and of the
+  type Tbl_EntryNormal_c. The function moves over both lists of ranges, and
+  checks to see if the begin of any range if less that or equal to the ]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+Tbl_EntryTestIntersectEntry(
+  Tbl_Entry_t * entrya,
+  Tbl_Entry_t * entryb)
+{
+  lsGen gena;
+  lsGen genb;  
+  lsGeneric dataa;
+  lsGeneric datab;  
+  boolean checka, checkb;
+  Tbl_Range_t *rangea = NIL(Tbl_Range_t);
+  Tbl_Range_t *rangeb = NIL(Tbl_Range_t);
+
+  assert(entrya->type == Tbl_EntryNormal_c);
+  assert(entryb->type == Tbl_EntryNormal_c);
+
+  gena = lsStart(entrya->EntryData.listOfRanges);
+  genb = lsStart(entryb->EntryData.listOfRanges);
+
+  checka = TRUE;
+  checkb = TRUE;  
+  while((checka)||(checkb)) {
+    if (checka) {
+      if (lsNext(gena, &dataa,LS_NH) == LS_OK) {
+        rangea = (Tbl_Range_t*)dataa;
+      }
+      else {
+        lsFinish(gena);
+        lsFinish(genb);        
+        return FALSE;
+      }
+    }
+
+    if (checkb) {
+      if (lsNext(genb, &datab,LS_NH) == LS_OK) {
+        rangeb = (Tbl_Range_t*)datab;
+      }
+      else {
+        lsFinish(gena);
+        lsFinish(genb);        
+        return FALSE;
+      }  
+    }
+
+    if ((rangea->begin <= rangeb->end) &&(rangeb->begin <= rangea->end)) {      
+      lsFinish(gena);
+      lsFinish(genb);
+      return TRUE;
+    }
+    else if (rangea->end < rangeb->begin){
+      checka = TRUE;
+      checkb = FALSE;
+    }
+    else {
+      checka = FALSE;
+      checkb = TRUE;
+    }    
+  }
+  lsFinish(gena);
+  lsFinish(genb);  
+  return FALSE;    
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return lsList of values in an entry]
+
+  Description []
+
+  SideEffects [This list is NOT to be modified. The user is encouraged not
+  to use this function. It is exported so as to make the macros for iteration over
+  items in the entry possible. The user should use these macros for accessing data.
+  The macros that can be used are mentioned in the SeeAlso list]
+
+  SeeAlso     [Tbl_EntryForEachValue]
+
+******************************************************************************/
+lsList
+Tbl_EntryReadList(
+  Tbl_Entry_t * entry)
+{
+  return (entry->EntryData.listOfRanges);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Return the type of the given entry]
+
+  Description [Given a Tbl_Entry_t, this function returns its type,
+  either Tbl_EntryEqual_c or Tbl_EntryNormal_c.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Tbl_EntryType_t
+Tbl_EntryReadType(
+  Tbl_Entry_t *entry)
+{
+  return (entry->type);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the mdd_t* for a table entry]
+
+  Description [Given an array of constituent mdd_t*, and a table entry, this returns
+  an mdd for the entry. The array of mdd_t's must contain an mdd_t for value i in
+  position i, for all values i.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+mdd_t *
+TblEntryNormalConstructMdd(
+    mdd_manager *manager,
+    Tbl_Entry_t * entry,
+    array_t * mddArray)
+{
+  lsGen gen;
+  Tbl_Range_t *range;
+  int i;
+  mdd_t *result, *temp, *x;
+    
+  result = mdd_zero(manager);
+  lsForEachItem(entry->EntryData.listOfRanges, gen, range) {
+    for (i=range->begin; i< (range->end +1); i++) {
+      temp = result;
+      x = Mvf_FunctionObtainComponent(mddArray,i);
+      result = mdd_or(temp, x,1,1);
+      mdd_free(temp);
+      mdd_free(x);
+    }
+  }
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the mdd_t* for a table entry]
+
+  Description [Given an array of constituent mdd_t*, and a table entry, this returns
+  an mdd for the entry. The array of mdd_t's must contain an mdd_t for value i in
+  position i, for all values i.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+mdd_t *
+TblEntryEqualConstructMdd(
+    mdd_manager *manager,
+    Tbl_Entry_t * entry,
+    Mvf_Function_t * mddArray,
+    Mvf_Function_t * mddEArray)
+{
+  lsGen gen;
+  Tbl_Range_t *range;
+  int i;
+  mdd_t *result, *temp, *x;
+
+  assert(entry->type == Tbl_EntryNormal_c);
+  result = mdd_zero(manager);
+  lsForEachItem(entry->EntryData.listOfRanges, gen, range) {
+    for (i=range->begin; i< (range->end +1); i++) {
+      temp = result;
+      x = Mvf_FunctionObtainComponent(mddArray,i);
+      result = mdd_or(temp, x,1,1);
+      mdd_free(temp);
+      temp = result;
+      x = Mvf_FunctionObtainComponent(mddEArray,i);
+      result = mdd_or(temp, x,1,1);
+      mdd_free(temp);
+    }
+  }
+  return result;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [print an entry in symbolic form.]
+
+  Description [Given a Tbl_Entry_t , a fileptr and a table, this function prints
+  it in blif_mv format. This function accounts for variables with symbolic values]
+
+  SideEffects []
+
+  SeeAlso     [Tbl_TableWriteBlif]
+
+******************************************************************************/
+void
+TblEntryWriteBlifMv(
+    Tbl_Table_t *table,
+    Tbl_Entry_t *entry,
+    FILE *fp)
+{
+  lsGen gen;
+  Tbl_Range_t *range;
+  Var_Variable_t *var;
+  boolean test, testParen;
+  int i, itemNum, length;
+    
+  var = Tbl_EntryReadActualVar(table,entry);
+  test = Var_VariableTestIsSymbolic(var);
+  testParen = TRUE;
+  
+  if (entry != NIL(Tbl_Entry_t)) {
+    if (entry->type == Tbl_EntryNormal_c) {
+      length = lsLength(entry->EntryData.listOfRanges);
+      
+      if (length == 1){
+        var = Tbl_EntryReadActualVar(table,entry);
+        lsForEachItem(entry->EntryData.listOfRanges, gen, range) {
+          if ((range->begin ==0)&&(range->end == Var_VariableReadNumValues(var)-1)){
+            fprintf(fp,"-");
+          lsFinish(gen);            
+            return;
+          }
+        }
+      }
+      
+      itemNum = 1;
+      if (length ==1) {
+        testParen = FALSE;
+      }
+      
+      lsForEachItem(entry->EntryData.listOfRanges, gen, range) {
+        if (itemNum ==1) {
+          if (testParen) {
+              fprintf(fp,"(");
+          }
+        }
+          
+        if (itemNum < length) {
+          if (test == FALSE) {
+            if (range->end != range->begin) {
+              fprintf(fp,"{%d-%d},", range->begin, range->end);
+            }
+            else {
+              fprintf(fp,"%d,", range->end);
+            }
+          }
+          else {
+            if (range->end != range->begin) {
+                fprintf(fp,"(%s,",Var_VariableReadSymbolicValueFromIndex(var,range->begin));
+                for (i= range->begin+1; i < range->end ; i++) {
+                fprintf(fp,"%s,",Var_VariableReadSymbolicValueFromIndex(var,i));
+              }
+                        
+              fprintf(fp,"%s),",Var_VariableReadSymbolicValueFromIndex(var,range->end));
+            }
+            else {
+              fprintf(fp,"%s,",Var_VariableReadSymbolicValueFromIndex(var,range->end));
+            }
+          }
+        }
+        else {
+          if (test == FALSE) {
+            if (range->end != range->begin)
+              fprintf(fp,"{%d-%d}", range->begin, range->end);
+            else fprintf(fp,"%d", range->end);
+          }
+          else {
+            if (range->end != range->begin) {
+                fprintf(fp,"(%s,",Var_VariableReadSymbolicValueFromIndex(var,range->begin));
+                for (i= range->begin+1; i < range->end ; i++) {
+                fprintf(fp,"%s,",Var_VariableReadSymbolicValueFromIndex(var,i));
+              }
+                        
+              fprintf(fp,"%s)",Var_VariableReadSymbolicValueFromIndex(var,range->end));
+            }
+            else {
+              fprintf(fp,"%s",Var_VariableReadSymbolicValueFromIndex(var,range->end));
+            }
+          }   
+        }
+      itemNum++;        
+      }
+      if (testParen) {      
+        fprintf(fp,")");
+      }
+    }
+    else if (entry->type == Tbl_EntryEqual_c) {
+      fprintf(fp,"=%s", Var_VariableReadName(Tbl_EntryReadVar(table,entry)));
+    }
+  }
+  else printf("NIL Entry ");
+}
+
+/**Function********************************************************************
+ 
+  Synopsis    [print an entry in symbolic form.]
+
+  Description [Given a Tbl_Entry_t , a fileptr and a table, this function prints
+  it in smv format. This function accounts for variables with symbolic values]
+
+  SideEffects []
+
+  SeeAlso     [Tbl_TableWriteBlif, Tbl_TableWriteBlifMv]
+
+******************************************************************************/
+void
+TblEntryWriteSmv(
+    Tbl_Table_t *table,
+    Tbl_Entry_t *entry,
+    boolean varnameflag,
+    FILE *fp)
+{
+  lsGen gen;
+  Tbl_Range_t *range;
+  Var_Variable_t *var;
+  boolean symbolic, testParen;
+  int i, itemNum, length;
+    
+  var = Tbl_EntryReadActualVar(table,entry);
+  symbolic = Var_VariableTestIsSymbolic(var);
+  testParen = TRUE;
+  
+  if (entry != NIL(Tbl_Entry_t)) {
+    if (entry->type == Tbl_EntryNormal_c) {
+      length = lsLength(entry->EntryData.listOfRanges);
+      
+      if (length == 1){
+        var = Tbl_EntryReadActualVar(table,entry);
+        lsForEachItem(entry->EntryData.listOfRanges, gen, range) {
+          if ((range->begin ==0)&&(range->end == Var_VariableReadNumValues(var)-1)){
+            fprintf(fp,"1"); /* A don't-care is always true */
+          lsFinish(gen);            
+            return;
+          }
+        }
+      }
+      
+      if (!varnameflag) {
+	fprintf(fp,"(");
+	Io_SmvPrintVar(fp,var);
+      }
+      itemNum = 1;
+      if (length ==1) {
+        testParen = FALSE;
+      }
+      
+      lsForEachItem(entry->EntryData.listOfRanges, gen, range) {
+	if (!varnameflag) {
+	  if (itemNum ==1) {
+	    if (testParen) {
+              fprintf(fp," IN {");
+	    } else {
+	      fprintf(fp, "=");
+	    }
+	  }
+	}
+	
+        if (itemNum < length) {
+          if (symbolic == FALSE) {
+            if (range->end != range->begin) {
+	      for (i= range->begin; i < range->end ; i++)
+                fprintf(fp,"%d,",i);
+            }
+	    fprintf(fp,"%d,", range->end);
+          }
+          else {
+            if (range->end != range->begin) {
+                fprintf(fp,"%s,",Var_VariableReadSymbolicValueFromIndex(var,range->begin));
+                for (i= range->begin+1; i < range->end ; i++) {
+		  fprintf(fp,"%s,",Var_VariableReadSymbolicValueFromIndex(var,i));
+		}
+                        
+		fprintf(fp,"%s,",Var_VariableReadSymbolicValueFromIndex(var,range->end));
+            }
+            else {
+              fprintf(fp,"%s,",Var_VariableReadSymbolicValueFromIndex(var,range->end));
+            }
+          }
+        }
+        else {
+          if (symbolic == FALSE) {
+            if (range->end != range->begin) {
+	      for (i= range->begin; i < range->end ; i++)
+                fprintf(fp,"%d,",i);
+	    }
+            fprintf(fp,"%d", range->end);
+          }
+          else {
+            if (range->end != range->begin) {
+                fprintf(fp,"%s,",Var_VariableReadSymbolicValueFromIndex(var,range->begin));
+                for (i= range->begin+1; i < range->end ; i++) {
+                fprintf(fp,"%s,",Var_VariableReadSymbolicValueFromIndex(var,i));
+              }
+                        
+              fprintf(fp,"%s",Var_VariableReadSymbolicValueFromIndex(var,range->end));
+            }
+            else {
+              fprintf(fp,"%s",Var_VariableReadSymbolicValueFromIndex(var,range->end));
+            }
+          }   
+        }
+      itemNum++;        
+      }
+      if (testParen) {      
+        fprintf(fp,"} ");
+      }
+      if (!varnameflag) {
+	fprintf(fp, ") ");
+      }
+    }
+    else if (entry->type == Tbl_EntryEqual_c) {
+      if (!varnameflag) {
+	Io_SmvPrintVar(fp, var);
+	fprintf(fp,"=");
+      }
+      Io_SmvPrintVar(fp, Tbl_EntryReadVar(table,entry));
+    }
+  }
+  else printf("NIL Entry ");
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [print an entry in blif form.]
+
+  Description [Given a Tbl_Entry_t , a fileptr and a table, this function prints
+  it in blif format.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+TblEntryWriteBlif(
+    Tbl_Table_t *table,
+    Tbl_Entry_t *entry,
+    FILE *fp)
+{
+  lsGen gen;
+  Tbl_Range_t *range;
+  Var_Variable_t *var;
+  boolean test;
+  int i, itemNum, length;
+    
+  var = Tbl_EntryReadActualVar(table,entry);
+  test = Var_VariableTestIsSymbolic(var);
+  if (entry != NIL(Tbl_Entry_t)) {
+    if (entry->type == Tbl_EntryNormal_c) {
+      length = lsLength(entry->EntryData.listOfRanges);      
+      if (length == 1){
+        var = Tbl_EntryReadActualVar(table,entry);
+        lsForEachItem(entry->EntryData.listOfRanges, gen, range) {
+          if ((range->begin ==0)&&(range->end == Var_VariableReadNumValues(var)-1)){
+            fprintf(fp,"-");
+          lsFinish(gen);            
+            return;
+          }
+        }
+      }
+
+      length = lsLength(entry->EntryData.listOfRanges);
+      itemNum = 1;
+      lsForEachItem(entry->EntryData.listOfRanges, gen, range) {
+        if (itemNum < length) {
+          if (test == FALSE) {
+            if (range->end != range->begin) {
+              fprintf(fp,"{%d-%d},", range->begin, range->end);
+            }
+            else {
+              fprintf(fp,"%d,", range->end);
+            }
+          }
+          else {
+            if (range->end != range->begin) {
+              for (i= range->begin; i < range->end ; i++) {
+                fprintf(fp,"%s,",Var_VariableReadSymbolicValueFromIndex(var,i));
+              }
+                        
+              fprintf(fp,"%s",Var_VariableReadSymbolicValueFromIndex(var,range->end));
+            }
+            else {
+              fprintf(fp,"%s,",Var_VariableReadSymbolicValueFromIndex(var,range->end));
+            }
+          }
+        }
+        else {
+          if (test == FALSE) {
+            if (range->end != range->begin)
+              fprintf(fp,"{%d-%d}", range->begin, range->end);
+            else fprintf(fp,"%d", range->end);
+          }
+          else {
+            if (range->end != range->begin) {
+              for (i= range->begin; i < range->end ; i++) {
+                fprintf(fp,"%s,",Var_VariableReadSymbolicValueFromIndex(var,i));
+              }
+                        
+              fprintf(fp,"%s",Var_VariableReadSymbolicValueFromIndex(var,range->end));
+            }
+            else {
+              fprintf(fp,"%s",Var_VariableReadSymbolicValueFromIndex(var,range->end));
+            }   
+          }
+        }
+        itemNum++;        
+      }
+    }
+    else if (entry->type == Tbl_EntryEqual_c) {
+      fprintf(fp," =%s ",Var_VariableReadName(Tbl_EntryReadVar(table,entry)));
+    }
+  }
+  else printf("NIL Entry ");
+}
+
+/**Function********************************************************************
+
+  Synopsis    [This frees a given Tbl_Entry_t]
+
+  Description [This function frees the memory assocated with a Tbl_Entry_t that
+               is given as input]
+
+  SideEffects [ The Var_Variable_t must be freed by the user]
+
+  SeeAlso     [TblEntryAlloc]
+
+******************************************************************************/
+void
+TblRangeFree(
+  Tbl_Range_t * range)
+{
+  FREE(range);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [return the begin value of a Tbl_Range_t]
+
+  Description []
+
+  SideEffects [The user is encouraged not
+  to use this function. It is exported so as to make the macros for iteration over
+  items in the table possible. The user should use these macros for accessing data.
+  The macros that can be used are mentioned in the SeeAlso list]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Tbl_RangeBegin(
+  Tbl_Range_t *range)
+{
+  return(range->begin);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [return the end value of a Tbl_Range_t]
+
+  Description []
+
+  SideEffects [The user is encouraged not
+  to use this function. It is exported so as to make the macros for iteration over
+  items in the table possible. The user should use these macros for accessing data.
+  The macros that can be used are mentioned in the SeeAlso list]
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Tbl_RangeEnd(
+  Tbl_Range_t *range)
+{
+  return(range->end);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [A function for comparing 2 ranges]
+
+  Description [This function return a -1 if range1 is subset of
+               range2, a 1 if range1 is a superset of range2, and 0 if
+               neither statement is true]
+
+  SideEffects []
+
+  SeeAlso     [EntryCanonicalize]
+
+******************************************************************************/
+static int
+RangeCompare(
+  lsGeneric entry1,
+  lsGeneric entry2)
+{
+  Tbl_Range_t * range1 = (Tbl_Range_t *) entry1;
+  Tbl_Range_t * range2 = (Tbl_Range_t *) entry2;
+  int value = 0;
+
+  if (range1->begin > range2->begin) {
+    value = 1;
+  }
+  else if (range1->begin < range2->begin) {
+    value = -1;
+  }
+  else if (range1->begin == range2->begin) {
+    if (range1->end > range2->end) {
+      value = 1;
+    }
+    else if (range1->end <  range2->end) {
+      value = -1;
+    }
+  }
+  return value;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Canonicalize a table entry]
+
+  Description [Given a table entry, this canonicalizes the lsList of
+               ranges by sorting and merging the ranges. If the entry
+               is of Tbl_EntryEqual_c type, it returns without making
+               any changes. Note that the gen in the list package has
+               positions in between prev and next items, and hence
+               after each deletion its position has to be re-adjusted.
+
+               This function iterates over the entire list of ranges
+               and checks to see if two sucessive ranges overlap. If
+               they do, this function creates a larger list containing
+               bothe ranges, adds it to the list and subtracts the
+               other two.]
+
+  SideEffects [The old table list of ranges is lost]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+EntryCanonicalize(
+  Tbl_Entry_t *  entry)
+{
+  lsGen gen;
+  Tbl_Range_t *range, *newRange, *nextRange;
+  lsGeneric data;
+
+  if (entry->type == Tbl_EntryEqual_c) {
+    return;
+  }
+
+  if (entry->type == Tbl_EntryUnassigned_c) {
+    return;
+  }
+
+  if (lsLength(entry->EntryData.listOfRanges)  > 1) {
+    lsSort(entry->EntryData.listOfRanges,RangeCompare);
+    lsForEachItem(entry->EntryData.listOfRanges, gen, range) {
+      if (lsNext(gen, &data,LS_NH) == LS_OK) {
+	nextRange = (Tbl_Range_t*)data;
+	if (nextRange->begin < (range->end + 2)) {
+	  if (nextRange->end > range->end) {
+	    newRange = ALLOC(Tbl_Range_t,1);
+	    newRange->begin = range->begin;
+	    newRange->end = nextRange->end;
+	    lsInAfter(gen,(lsGeneric)newRange,LS_NH);
+	    lsDelBefore(gen,(lsGeneric*)nextRange);
+	    TblRangeFree(nextRange);
+	    lsDelBefore(gen,(lsGeneric*)range);
+	    TblRangeFree(range);
+	  }
+	  else {
+	    lsDelBefore(gen,(lsGeneric*)nextRange);
+	    TblRangeFree(nextRange);
+	    if (lsPrev(gen,&data,LS_NH)!= LS_OK) {
+              (void) lsFinish(gen);
+	    }
+	  }
+	}
+	else {
+	  lsPrev(gen,&data,LS_NH);
+	}
+      }
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Complement the entry of a table]
+
+  Description [Given a table entry, this complement the entry by
+               getting the complement list of ranges. Note that the
+               list must be canonical.  The list that is returned is
+               canonical by construction. Notice that the min and max
+               values for the Var_Variable_t associated with the entry
+               must be provided.]
+               
+  SideEffects [The old table list of ranges is lost.]
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+EntryComplement(
+  Tbl_Entry_t *  entry,
+  int min,
+  int max)
+{
+  lsGen gen, newGen;
+  Tbl_Range_t *range, *newRange, *nextRange;
+  lsList newRangeList;
+  int listMin, listMax;
+  lsGeneric data;
+    
+  if (entry->type == Tbl_EntryEqual_c) {
+    return;
+  }
+
+  if (entry->type == Tbl_EntryUnassigned_c) {
+    return;
+  }
+
+  listMin = max;
+  listMax = min;
+  newRangeList = lsCreate();
+  newGen = lsStart(newRangeList);
+  lsForEachItem(entry->EntryData.listOfRanges, gen, range) {
+    if (lsNext(gen, &data, LS_NH) == LS_OK) {
+      nextRange = (Tbl_Range_t*)data;
+      newRange = ALLOC(Tbl_Range_t,1);
+      newRange->begin = range->end +1;
+      newRange->end = nextRange->begin -1;
+      lsInAfter(newGen,(lsGeneric)newRange,LS_NH);
+      lsPrev(gen, &data, LS_NH);
+    }      
+    if (listMin > range->begin) listMin = range->begin;
+    if (listMax < range->end) listMax = range->end;
+  }
+  lsFinish(newGen);
+  if (min < listMin) {
+    newRange = ALLOC(Tbl_Range_t,1);
+    newRange->begin = min;
+    newRange->end = listMin -1;
+    lsNewBegin(newRangeList,(lsGeneric)newRange,LS_NH);
+  }
+  if (listMax < max) {
+    newRange = ALLOC(Tbl_Range_t,1);
+    newRange->begin = listMax +1;
+    newRange->end = max;
+    lsNewEnd(newRangeList,(lsGeneric)newRange,LS_NH);
+  }
+  lsDestroy(entry->EntryData.listOfRanges,(void (*)(lsGeneric))TblRangeFree);
+  entry->EntryData.listOfRanges = newRangeList;
+}
Index: vis_dev/vis-2.3/src/tbl/tblIdentity.c
===================================================================
--- vis_dev/vis-2.3/src/tbl/tblIdentity.c	(revision 14)
+++ vis_dev/vis-2.3/src/tbl/tblIdentity.c	(revision 14)
@@ -0,0 +1,294 @@
+/**CFile***********************************************************************
+
+  FileName    [tblIdentity.c]
+
+  PackageName [tbl]
+
+  Synopsis    [Functions used to detect special types of table.  Used, for
+	       instance, in network sweeping.]
+
+  SeeAlso     [tbl.h]
+
+  Author      [Fabio Somenzi]
+
+  Copyright   [Copyright (c) 2009, 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 "tblInt.h"
+
+static char rcsid[] UNUSED = "$Id: tblIdentity.c,v 1.1 2009/04/11 07:10:15 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+/**Function********************************************************************
+
+  Synopsis[Check whether a table describes an identity function.]
+
+  Description [This function checks whether a table describes an
+  identity.  An identity table has exactly one input and one output
+  variable, which takes the same value as the input.]
+
+  SideEffects []
+
+  SeeAlso []
+
+******************************************************************************/
+boolean
+Tbl_TableIsIdentity(
+  Tbl_Table_t *table
+  )
+{
+  Var_Variable_t *invar = NIL(Var_Variable_t), *outvar = NIL(Var_Variable_t);
+  Var_Variable_t *var;
+  int colNum, rowNum;
+  Tbl_Entry_t *inputEntry, *outputEntry, *defaultEntry, *cumulative;
+  boolean result;
+#if 0
+  Mvf_Function_t *outMvf, *inMvf, *identMvf;
+  array_t *mvarValues;
+  array_t *inMvfArray;
+  Tbl_Table_t *ident;
+#endif
+
+  if (Tbl_TableReadNumInputs(table) != 1) return FALSE;
+  if (Tbl_TableReadNumOutputs(table) != 1) return FALSE;
+
+  Tbl_TableForEachInputVar(table,colNum,var) {
+    invar = var;
+  }
+
+  Tbl_TableForEachOutputVar(table,colNum,var) {
+    outvar = var;
+  }
+
+  if (!Var_VariablesTestHaveSameDomain(invar,outvar)) return FALSE;
+
+  /* We test the following condition.  If a table specifies a value
+   * for all inputs and all rows are consistent with the identity,
+   * then the table is an identity.  A normal default declaration is
+   * treated as a row whose input and output parts equal the default
+   * value.  An equality default declaration is treated like a row
+   * with equality output entry and don't care input entry.
+   * Completeness and nondeterminism are implicitly tested by this
+   * criterion.
+   */
+  defaultEntry = Tbl_TableDefaultReadEntry(table, 0);
+  if (defaultEntry == NIL(Tbl_Entry_t)) {
+    cumulative = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+  } else if (Tbl_EntryIsEqual(defaultEntry)) {
+    cumulative = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+    Tbl_EntrySetValue(cumulative, 0, Var_VariableReadNumValues(invar) - 1);
+  } else {
+    if (Tbl_EntryReadNumValues(defaultEntry) != 1) return FALSE;
+    cumulative = Tbl_EntryDup(defaultEntry);
+  }
+  Tbl_TableForEachOutputEntry(table, rowNum, colNum, outputEntry) {
+    Tbl_Entry_t *tmpEntry;
+    assert(colNum == 0);
+    inputEntry = Tbl_TableReadEntry(table, rowNum, 0, 0);
+    assert(!Tbl_EntryIsEqual(inputEntry));
+    if (!Tbl_EntryIsEqual(outputEntry)) {
+      if (Tbl_EntryReadNumValues(outputEntry) != 1 ||
+	  !Tbl_EntryTestEqualEntry(outputEntry,inputEntry)) {
+	Tbl_EntryFree(cumulative);
+	return FALSE;
+      }
+    }
+    tmpEntry = Tbl_EntryMerge(cumulative, inputEntry);
+    Tbl_EntryFree(cumulative);
+    cumulative = tmpEntry;
+  }
+  result = Tbl_EntryReadNumValues(cumulative) ==
+    Var_VariableReadNumValues(invar);
+  Tbl_EntryFree(cumulative);
+  return result;
+
+#if 0
+
+  /* Use the MVF sledgehammer.  Only proceed if an mdd manager was
+   * passed as argument.
+   */
+
+  if (mddMgr == NIL(mdd_manager)) return FALSE;
+
+  /* Create MDD variables for the table inputs. */
+  mdd_restart(mddMgr);
+  mvarValues = array_alloc(int, 1);
+  array_insert_last(int, mvarValues, Var_VariableReadNumValues(invar));
+  mdd_create_variables(mddMgr, mvarValues, NIL(array_t), NIL(array_t));
+  array_free(mvarValues);
+
+  /*
+   * Construct an MVF for each table input. The MVF for column i is the MVF
+   * for MDD variable i.
+   */
+  inMvf = Mvf_FunctionCreateFromVariable(mddMgr, 0);
+  inMvfArray = array_alloc(Mvf_Function_t *, 1);
+  array_insert_last(Mvf_Function_t *, inMvfArray, inMvf);
+
+  outMvf = Tbl_TableBuildMvfFromFanins(table, 0, inMvfArray, mddMgr);
+
+  /* Build a reference identity.  This can be sped up quite a bit, but
+     we are practicing using the tbl package. */
+  ident = Tbl_TableAlloc();
+  colNum = Tbl_TableAddColumn(ident,invar,0);
+  assert(colNum == 1);
+  colNum = Tbl_TableAddColumn(ident,outvar,1);
+  assert(colNum == 1);
+  rowNum = Tbl_TableAddRow(ident);
+  assert(rowNum == 0);
+  inputEntry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+  Tbl_EntrySetValue(inputEntry, 0, Var_VariableReadNumValues(invar)-1);
+  Tbl_TableSetEntry(ident,inputEntry, 0, 0, 0);
+  outputEntry = Tbl_EntryAlloc(Tbl_EntryEqual_c);
+  Tbl_EntrySetEqual(outputEntry, 0);
+  Tbl_TableSetEntry(ident,outputEntry, 0, 0, 1);
+
+  identMvf = Tbl_TableBuildMvfFromFanins(ident, 0, inMvfArray, mddMgr);
+  Mvf_FunctionArrayFree(inMvfArray);
+  Tbl_TableFree(ident);
+  result = Mvf_FunctionTestIsEqualToFunction(outMvf, identMvf);
+  Mvf_FunctionFree(outMvf);
+  Mvf_FunctionFree(identMvf);
+  return result;
+#endif
+
+} /* Tbl_TableIsIdentity */
+
+
+/**Function********************************************************************
+
+  Synopsis[Check whether a table describes an inverter.]
+
+  Description [This function checks whether a table describes an
+  inverter.  An inverter table has exactly one binary input and one
+  binary output variable, which takes the opposite value as the
+  input.]
+
+  SideEffects []
+
+  SeeAlso []
+
+******************************************************************************/
+boolean
+Tbl_TableIsInverter(
+  Tbl_Table_t *table
+  )
+{
+  Var_Variable_t *invar = NIL(Var_Variable_t), *outvar = NIL(Var_Variable_t);
+  Var_Variable_t *var;
+  int colNum, rowNum;
+  Tbl_Entry_t *inputEntry, *outputEntry, *defaultEntry, *cumulative;
+  boolean result;
+
+  if (Tbl_TableReadNumInputs(table) != 1) return FALSE;
+  if (Tbl_TableReadNumOutputs(table) != 1) return FALSE;
+
+  Tbl_TableForEachInputVar(table,colNum,var) {
+    invar = var;
+  }
+  if (Var_VariableReadNumValues(invar) != 2 ||
+      Var_VariableTestIsSymbolic(invar)) return FALSE;
+
+  Tbl_TableForEachOutputVar(table,colNum,var) {
+    outvar = var;
+  }
+  if (Var_VariableReadNumValues(outvar) != 2 ||
+      Var_VariableTestIsSymbolic(outvar)) return FALSE;
+
+  defaultEntry = Tbl_TableDefaultReadEntry(table, 0);
+  if (defaultEntry == NIL(Tbl_Entry_t)) {
+    cumulative = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+  } else if (Tbl_EntryIsEqual(defaultEntry)) {
+    return FALSE;
+  } else {
+    if (Tbl_EntryReadNumValues(defaultEntry) != 1)
+      return FALSE;
+    cumulative = Tbl_EntryDup(defaultEntry);
+    Tbl_EntryComplement(cumulative, 0, 1);
+  }
+  Tbl_TableForEachOutputEntry(table, rowNum, colNum, outputEntry) {
+    Tbl_Entry_t *tmpEntry;
+    assert(colNum == 0);
+    if (Tbl_EntryIsEqual(outputEntry)) {
+      Tbl_EntryFree(cumulative);
+      return FALSE;
+    }
+
+    inputEntry = Tbl_TableReadEntry(table, rowNum, 0, 0);
+    assert(!Tbl_EntryIsEqual(inputEntry));
+    if (Tbl_EntryReadNumValues(outputEntry) != 1 ||
+	Tbl_EntryTestIntersectEntry(outputEntry,inputEntry)) {
+      Tbl_EntryFree(cumulative);
+      return FALSE;
+    }
+    tmpEntry = Tbl_EntryMerge(cumulative, inputEntry);
+    Tbl_EntryFree(cumulative);
+    cumulative = tmpEntry;
+  }
+  result = Tbl_EntryReadNumValues(cumulative) == 2;
+  Tbl_EntryFree(cumulative);
+  return result;
+
+} /* Tbl_TableIsInverter */
Index: vis_dev/vis-2.3/src/tbl/tblInt.h
===================================================================
--- vis_dev/vis-2.3/src/tbl/tblInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/tbl/tblInt.h	(revision 14)
@@ -0,0 +1,265 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [tblInt.h]
+
+  PackageName [tbl]
+
+  Synopsis    [Include the internals of the table package]
+
+  Description [Describes the internal structs in the table package. The
+  Tbl_Table_t data structure consists of an array of inputs, and array of
+  outputs and a data struct (Tbl_Data_t). This data struct is shared between
+  tables that are duplicated (using soft dup). The data struct contains a
+  reference count to indicate the number of tables that share it. If a
+  free is called, the data struct reference count is decremented and only
+  if this drops to 0 is the struct actually freed. The Tbl_Data_t also
+  contains an array of default values, and an array of Tbl_Row_t's to
+  represent the actual data. The Tbl_row_t consists of two arrays (inputs and
+  outputs), which contain Tbl_Entry_t's (representing entries in a table.]
+
+  SeeAlso     [tbl.h]
+
+  Author      [Gitanjali M. Swamy]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: tblInt.h,v 1.11 2009/04/11 02:01:29 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _TBLINT
+#define _TBLINT
+
+#include "tbl.h"
+#include "cmd.h"
+#include "io.h"
+#include <string.h>
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**Struct*************************************************************
+
+  Synopsis	[ This is basic blif_mv table data structure ]
+
+  Description	[ This datastructure consists of struct with 3 fields; an
+  array of inputs, an array of ouputs and a Tbl_Data_t for the actual
+  table data.]
+
+  SeeAlso	[ TblEntryStruct TblRowStruct TblDataStruct]
+**********************************************************************/
+struct TblTableStruct {
+    array_t * inputNames; /* An array of the Var_Variable_ts corresponding to
+                               the inputs to the table */
+    array_t * outputNames; /* An array of Var_Variable_ts corresponding to
+                                the outputs of the table */
+    Tbl_Data_t * data; /* A Tbl_Data_t that represents actual data in the table  */ 
+};
+
+/**Struct*************************************************************
+
+  Synopsis	[ This is the struct used to represent each row in the table]
+
+  Description	[ There are 2 fields in this struct; a row array and a column
+                  array.]
+
+  SeeAlso	[ TblStruct TblEntryStruct ]
+  
+**********************************************************************/
+
+struct TblRowStruct {
+    array_t * inputs; /* An array of inputs */
+    array_t * outputs; /* An array of outputs */
+};
+
+/**Struct**********************************************************************
+
+  Synopsis    [Struct used to represent table data]
+
+  Description [This struct has three fields; a reference count that is used
+  for memory management, an array of default values, and an array of Tbl_Row_t's
+  that represents the actual table data. Each Tbl_Row_t within this data array
+  has an input part and an output part; each of these is an array of Tbl_Entry_t's.]
+
+  SeeAlso     [ TblEntryStruct TblTableStruct TblRowStruct]
+
+******************************************************************************/
+
+struct TblDataStruct {
+    int refCount; /* a reference count to indicate how many duplicates exist
+                   */
+    array_t *defaults; /* An array with the defaults */  
+    array_t *actualData;
+};
+
+
+/**Struct*************************************************************
+
+  Synopsis	[ This struct represents a range]
+
+  Description	[ This struct represents a range and has 2 fields;
+                  the beginning and the end. The data within a Tbl_Entry_t
+                  is represented as a linked list of such ranges (if the entry
+                  is of type Tbl_EntryNormal_c.]
+
+  SeeAlso	[ TblRangeAlloc TblRangeFree ]
+  
+**********************************************************************/
+
+struct TblRangeStruct {
+    int begin; /* The beginning of the range */
+    int end; /* The end of the range */
+};
+    
+/**Struct*************************************************************
+
+  Synopsis	[ This is the struct used to represent each entry in the table ]
+
+  Description	[ This struct has 4 fields; an enumerated  type, an integer to
+  indicate if it is an input or output, an integer for the  column number, and
+  a union with either a list of ranges or a var (this depends on the type of
+  the struct.]
+
+  SeeAlso	[ TblRowStruct TblTableStruct TblDataStruct]
+  
+**********************************************************************/
+
+struct TblEntryStruct {
+    Tbl_EntryType_t type; /* Type of the table entry. This may be one of 2 types;
+                  either equal  or normal*/
+    int ioType; /* to indicate whether its input or output */
+    int varColNum; /* corresponding Var_Variable_t column number */
+    union{
+        int var; /* This indicates the related column  if the entry is
+                           of the type equal */
+        lsList  listOfRanges; /* This indicates the contents of the table
+                                  entry if its type is normal */
+    }EntryData;
+};
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [return refcount associated with table]
+
+  Description  [This functions returns the number of tables that share data
+  with the given table. This count is used for memory management.]
+
+  SideEffects  []
+
+  SeeAlso      []
+
+******************************************************************************/
+#define TblTableReadRefCount(                                                \
+/* Tbl_Table_t * */ table   /* The table to iterate over */                  \
+)                                                                            \
+table->data->refCount
+
+/**Macro***********************************************************************
+
+  Synopsis    [Return the data array associated with a table.]
+
+  Description []
+
+  SideEffects [This array is NOT to be modified. The user is encouraged not
+  to use this function. It is exported so as to make the macros for iteration over
+  items in the table possible. The user should use these macros for accessing data.
+  The macros that can be used are mentioned in the SeeAlso list]
+
+  SeeAlso     [Tbl_TableForEachEntry Tbl_TableForEachInputEntry Tbl_TableForEachOutputEntry
+  Tbl_TableForEachInputVar Tbl_TableForEachOutputVar Tbl_TableForEachDefault]
+
+******************************************************************************/
+#define TblTableReadData(                                                    \
+/* Tbl_Table_t * */ table   /* The table to iterate over */                  \
+)                                                                            \
+table->data->actualData
+
+/**Macro***********************************************************************
+
+  Synopsis    [Return the defaults array associated with a table.]
+
+  Description []
+
+  SideEffects [This array is NOT to be modified. The user is encouraged not
+  to use this function. It is exported so as to make the macros for iteration over
+  items in the table possible. The user should use these macros for accessing data.
+  The macros that can be used are mentioned in the SeeAlso list]
+
+  SeeAlso     [Tbl_TableForEachEntry Tbl_TableForEachInputEntry Tbl_TableForEachOutputEntry
+  Tbl_TableForEachInputVar Tbl_TableForEachOutputVar Tbl_TableForEachDefault]
+
+******************************************************************************/
+#define TblTableReadDefaults(                                                \
+/* Tbl_Table_t * */ table   /* The table to iterate over */                  \
+)                                                                            \
+ table->data->defaults
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [ Generates all rows on the table ]
+
+  Description  [ Given a table this iterates over all its rows in smallest colum
+n
+                 first order.]
+
+  SideEffects  [ ]
+
+  SeeAlso      [ ]
+
+******************************************************************************/
+#define TblTableForEachRow(                                                  \
+/* Tbl_Table_t * */ table   /* The table to iterate over */,                 \
+/* Tbl_Row_t *  */  row    /* The current row */,                            \
+/* int          */ rowNum  /* The row number  */                             \
+)                                                                            \
+ for(rowNum=0; (rowNum <array_n(TblTableReadData(table)))\
+                   &&(row = array_fetch(Tbl_Row_t*,(TblTableReadData(table)),rowNum));rowNum++)
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN mAigEdge_t TblEntryNormalConstructAig(mAig_Manager_t *manager, Tbl_Entry_t *entry, array_t *mAigArray);
+EXTERN mAigEdge_t TblEntryEqualConstructMAig(mAig_Manager_t * manager, Tbl_Entry_t * entry, MvfAig_Function_t * mAigArray, MvfAig_Function_t * mEigArray);
+EXTERN mdd_t * TblEntryNormalConstructMdd(mdd_manager *manager, Tbl_Entry_t * entry, array_t * mddArray);
+EXTERN mdd_t * TblEntryEqualConstructMdd(mdd_manager *manager, Tbl_Entry_t * entry, Mvf_Function_t * mddArray, Mvf_Function_t * mddEArray);
+EXTERN void TblEntryWriteBlifMv(Tbl_Table_t *table, Tbl_Entry_t *entry, FILE *fp);
+EXTERN void TblEntryWriteSmv(Tbl_Table_t *table, Tbl_Entry_t *entry, boolean varnameflag, FILE *fp);
+EXTERN void TblEntryWriteBlif(Tbl_Table_t *table, Tbl_Entry_t *entry, FILE *fp);
+EXTERN void TblRangeFree(Tbl_Range_t * range);
+EXTERN boolean TblTableDeleteLastRow(Tbl_Table_t* table);
+EXTERN void TblTableSetRow(Tbl_Table_t *table, Tbl_Row_t *row, int i);
+EXTERN array_t* TblRowReadOutputs(Tbl_Row_t * row);
+EXTERN array_t* TblRowReadInputs(Tbl_Row_t * row);
+EXTERN Tbl_Row_t* TblTableReadRow(Tbl_Table_t *table, int rowNum);
+EXTERN Tbl_Row_t* TblRowAlloc(void);
+EXTERN Tbl_Row_t* TblRowDup(Tbl_Row_t * row);
+EXTERN void TblRowSetEntry(Tbl_Row_t *row, Tbl_Entry_t * entry, int i, int flag);
+EXTERN void TblRowFree(Tbl_Row_t *row);
+EXTERN Tbl_Entry_t* TblRowReadEntry(Tbl_Row_t *row, int i, int flag);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _TBLINT */
Index: vis_dev/vis-2.3/src/tbl/tblSweep.c
===================================================================
--- vis_dev/vis-2.3/src/tbl/tblSweep.c	(revision 14)
+++ vis_dev/vis-2.3/src/tbl/tblSweep.c	(revision 14)
@@ -0,0 +1,503 @@
+/**CFile***********************************************************************
+
+  FileName    [ tblSweep.c ]
+
+  PackageName [ tbl ]
+
+  Synopsis    [Functions to support network sweeping.]
+
+  SeeAlso     [ tbl.h, tblEntryUtil.c ]
+
+  Author      [ Gitanjali M. Swamy ]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+#include "tblInt.h"
+
+static char rcsid[] UNUSED = "$Id: tblSweep.c,v 1.12 2009/04/11 18:26:45 fabio Exp $";
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void SetAdjustedEntry(Tbl_Table_t *table, Tbl_Entry_t *entry, int index, int rownum, int colnum, boolean flag);
+static void SetEntry(Tbl_Table_t *newTable, Tbl_Entry_t *entry1, Tbl_Entry_t *entry2, int rownum, int colnum, int index, boolean flag);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [return the result of collapsing table2 into table1]
+
+  Description [Given two Tbl_Table_t table1 and table2, this function
+	       will collapse table2 into the table1. It will remove
+	       the column corresponding to the var associated with the
+	       first table. Currently, the second table must a
+	       constant table. This function checks every row to
+	       confirm that the entry corresponding to the variable of
+	       table2 does indeed take the constant value. If this
+	       condition is satisfied it copies the entire row (minus
+	       the column corresponding to the constant variable) into
+	       a new resultant table. This condition can be easily
+	       checked if the corresponding entry is of type
+	       Tbl_EntryNormal_c, using
+	       Tbl_EntryTestIntersectEntry. Otherwise its an involved
+	       process that entails tracing the entire sequence of
+	       equal entries until we encounter a Tbl_EntryNormal_c
+	       entry.]
+
+  SideEffects  [required]
+
+  SeeAlso      [optional]
+
+******************************************************************************/
+Tbl_Table_t*
+Tbl_TableCollapse(Tbl_Table_t* table1, Tbl_Table_t* table2,int index)
+{
+  int rownum, realRowNum, colnum,eqcolnum,count,check;
+  Var_Variable_t *var;
+  Tbl_Table_t *newTable;
+  Tbl_Entry_t *entry1, *entry2;
+  Tbl_Entry_t *testEntry;
+
+  if (Tbl_TableReadNumOutputs(table2)==1){
+    newTable = Tbl_TableAlloc();
+
+    if (Tbl_TableReadNumRows(table2) !=0) {
+      entry2 = Tbl_TableReadEntry(table2,0,0,1);
+    }
+    else {
+      entry2 = Tbl_TableDefaultReadEntry(table2,0);
+    }
+    /* add every input column except collapsing input */
+    for(colnum=0;colnum < Tbl_TableReadNumInputs(table1); colnum++) {
+      if (colnum != index) {
+	var = Tbl_TableReadIndexVar(table1,colnum,0);
+	Tbl_TableAddColumn(newTable,var,0);
+      }
+    }
+    for(colnum=0;colnum < Tbl_TableReadNumOutputs(table1); colnum++) {
+      var = Tbl_TableReadIndexVar(table1,colnum,1);
+      Tbl_TableAddColumn(newTable,var,1);
+    }
+    /*     (void) Tbl_TableAddRow(newTable); */
+
+
+    realRowNum =0;
+    eqcolnum = index;
+
+    /* row by row, check if var has given constant value */
+    for(rownum=0; rownum< Tbl_TableReadNumRows(table1); rownum++) {
+      testEntry = Tbl_TableReadEntry(table1,rownum,index,0);
+      assert(entry2->type == Tbl_EntryNormal_c);
+
+      /* input column by column */
+      if (testEntry->type == Tbl_EntryNormal_c){
+	if (Tbl_EntryTestIntersectEntry(testEntry,entry2)){
+	  (void) Tbl_TableAddRow(newTable);
+
+	  for(colnum=0;colnum < Tbl_TableReadNumInputs(table1); colnum++) {
+	    entry1= Tbl_TableReadEntry(table1,rownum,colnum,0);
+	    SetEntry(newTable,entry1,entry2,realRowNum,colnum,index,0);
+	  }
+
+	  /* do outputs */
+	  for(colnum=0;colnum < Tbl_TableReadNumOutputs(table1); colnum++) {
+	    entry1= Tbl_TableReadEntry(table1,rownum,colnum,1);
+	    SetEntry(newTable,entry1,entry2,realRowNum,colnum,index,1);
+	  }
+	  realRowNum++;
+	}
+      }
+      else if (testEntry->type == Tbl_EntryEqual_c){
+	count = 0;
+	check = 0;
+	while(count<= Tbl_TableReadNumInputs(table1)){
+
+	  /* Find out the column the entry equal to
+	   * and set that column entry to constant value if
+	   * its is of type Equal. This gets propagated by the while count
+	   * loop until you find a non-equal entry, and then it checks
+	   * for an intersection. If no intersection, then it
+	   * nullifies the row. Alas, there was no easier way */
+	  if (testEntry->type == Tbl_EntryNormal_c){
+	    if (Tbl_EntryTestIntersectEntry(testEntry,entry2)){
+	      check = 1;
+	    }
+	    count = Tbl_TableReadNumInputs(table1)+1;
+	  }
+	  else {
+	    eqcolnum = Tbl_EntryReadVarIndex(testEntry);
+	    testEntry = Tbl_TableReadEntry(table1,rownum,eqcolnum,0);
+	  }
+	  if (count == Tbl_TableReadNumInputs(table1)){
+	    check = 1;
+	  }
+	  count ++;
+	}
+
+	if (check == 1) {
+	  (void) Tbl_TableAddRow(newTable);
+	  count = 0;
+	  eqcolnum = index;
+	  testEntry = Tbl_TableReadEntry(table1,rownum,index,0);
+	  while(count<= Tbl_TableReadNumInputs(table1)){
+	    if (testEntry->type == Tbl_EntryNormal_c){
+	      SetEntry(newTable,entry2,entry2,realRowNum,eqcolnum,index,0);
+	      count = Tbl_TableReadNumInputs(table1)+1 ;
+	    }
+	    else {
+	    eqcolnum = Tbl_EntryReadVarIndex(testEntry);
+	    testEntry = Tbl_TableReadEntry(table1,rownum,eqcolnum,0);
+	    count ++;
+	  }
+	  }
+	  /* end of while */
+	  /* fill in zero entries */
+	  for(colnum=0;colnum < Tbl_TableReadNumInputs(table1); colnum++) {
+	    entry1= Tbl_TableReadEntry(table1,rownum,colnum,0);
+	    SetAdjustedEntry(newTable,Tbl_EntryDup(entry1),index,rownum,colnum,0);
+	  }
+	  /* do outputs */
+	  for(colnum=0;colnum < Tbl_TableReadNumOutputs(table1); colnum++) {
+	    entry1= Tbl_TableReadEntry(table1,rownum,colnum,1);
+	    SetEntry(newTable,entry1,entry2,realRowNum,colnum,index,1);
+
+	  }
+	}
+	  realRowNum++;
+      }
+    }
+    Tbl_TableForEachDefaultEntry(table1,entry1,colnum) {
+      entry2 = NIL(Tbl_Entry_t);
+
+      if (entry1 != NIL(Tbl_Entry_t)) {
+	if (entry1->type != Tbl_EntryEqual_c) {
+	  entry2 = Tbl_EntryDup(entry1);
+	}
+	else{
+	  eqcolnum = Tbl_EntryReadVarIndex(entry1);
+	  if ( eqcolnum < index) {
+	    entry2 = Tbl_EntryDup(entry1);
+	  }
+	  else {
+	    if ( eqcolnum > index) {
+	      entry2 = Tbl_EntryDup(entry1);
+	      Tbl_EntrySetEqual(entry2, eqcolnum -1);
+	    }
+	    else {
+	      entry2 = Tbl_EntryDup(Tbl_TableReadEntry(table2,0,0,1));
+	    }
+	  }
+	}
+      }
+      (void) Tbl_TableDefaultSetEntry(newTable,entry2,colnum);
+    }
+    return newTable;
+  }
+  else {
+    fail("The table is not constant\n");
+    return NIL(Tbl_Table_t);  /* not reached */
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Inverts a binary input column in a table.]
+
+  Description [Inverts a binary input column in a table.  It has no
+  effect if the variable associated to the given index is not binary
+  or is symbolic.  In some uncommon cases that are tricky to handle,
+  it goves up ad returns a NULL pointer.  Otherwise it returns a
+  modified table.]
+
+  SideEffects [none]
+
+  SeeAlso     [Tbl_TableIsInverter]
+
+******************************************************************************/
+Tbl_Table_t *
+Tbl_TableInvertBinaryInputColumn(
+  Tbl_Table_t *table,
+  int index
+  )
+{
+  int rowNum, colNum;
+  Tbl_Entry_t *entry;
+  Tbl_Table_t *newTable;
+  Var_Variable_t *var;
+
+  var = Tbl_TableReadIndexVar(table, index, 0);
+  if (Var_VariableReadNumValues(var) != 2 ||
+      Var_VariableTestIsSymbolic(var)) return NIL(Tbl_Table_t);
+
+  /* Check default entries.  We give up if any variable points to the column
+   * to be complemented, because it's a rare case and it does not seem worth
+   * the effort.
+   */
+  Tbl_TableForEachDefaultEntry(table, entry, colNum) {
+    if (entry != NIL(Tbl_Entry_t) && Tbl_EntryIsEqual(entry)) {
+      int eqColNum = Tbl_EntryReadVarIndex(entry);
+      if (eqColNum == index) {
+	return NIL(Tbl_Table_t);
+      }
+    }
+  }
+
+  newTable = Tbl_TableHardDup(table);
+
+  Tbl_TableForEachInputVar(table, colNum, var) {
+    Tbl_TableSetVar(newTable, colNum, var, 0);
+  }
+
+  Tbl_TableForEachOutputVar(table, colNum, var) {
+    Tbl_TableSetVar(newTable, colNum, var, 1);
+  }
+
+  /* Get rid of equal entries in the output part that point to the
+   * column to be negated.  We do not currently deal with equal
+   * entries in the input part.  If we find one, we give up.
+   */
+  Tbl_TableForEachOutputEntry(newTable, rowNum, colNum, entry) {
+    if (Tbl_EntryIsEqual(entry)) {
+      int eqColNum = Tbl_EntryReadVarIndex(entry);
+      if (eqColNum == index) {
+	Tbl_Entry_t *eqEntry = Tbl_TableReadEntry(newTable, rowNum, index, 0);
+	if (Tbl_EntryIsEqual(eqEntry) ||
+	    Tbl_EntryReadNumValues(eqEntry) == 0) {
+	  /* Tricky case: we give up. */
+	  Tbl_TableFree(newTable);
+	  return NIL(Tbl_Table_t);
+	} else if (Tbl_EntryReadNumValues(eqEntry) == 1) {
+	  /* Downgrade the equality to a constant value. */
+	  Tbl_Entry_t *entry2 = Tbl_EntryDup(eqEntry);
+	  Tbl_TableSetEntry(newTable, entry2, rowNum, colNum, 1);
+	} else {
+	  int i, j;
+	  Tbl_Entry_t *entry2;
+	  i = Tbl_TableAddRow(newTable);
+	  Tbl_RowForEachInputEntry(newTable, rowNum, entry2, j) {
+	    if (j == index) {
+	      Tbl_Entry_t *entry3 = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+	      Tbl_Entry_t *entry4 = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+	      Tbl_EntrySetValue(entry3, 0, 0);
+	      Tbl_EntrySetValue(entry4, 1, 1);
+	      Tbl_TableSetEntry(newTable, entry3, rowNum, j, 0);
+	      Tbl_TableSetEntry(newTable, entry4, i, j, 0);
+	    } else {
+	      Tbl_TableSetEntry(newTable, Tbl_EntryDup(entry2), i, j, 0);
+	    }
+	  }
+	  Tbl_RowForEachOutputEntry(newTable, rowNum, entry2, j) {
+	    if (Tbl_EntryIsEqual(entry2) &&
+		Tbl_EntryReadVarIndex(entry) == index) {
+	      Tbl_Entry_t *entry3 = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+	      Tbl_Entry_t *entry4 = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+	      Tbl_EntrySetValue(entry3, 0, 0);
+	      Tbl_EntrySetValue(entry4, 1, 1);
+	      Tbl_TableSetEntry(newTable, entry3, rowNum, j, 1);
+	      Tbl_TableSetEntry(newTable, entry4, i, j, 1);
+	    } else {
+	      Tbl_TableSetEntry(newTable, Tbl_EntryDup(entry2), i, j, 1);
+	    }
+	  }
+	  continue;
+	}
+      }
+    }
+  }
+
+  Tbl_TableForEachInputEntry(newTable, rowNum, colNum, entry) {
+    if (Tbl_EntryIsEqual(entry)) {
+      if (colNum == index) {
+	Tbl_TableFree(newTable);
+	return NIL(Tbl_Table_t);
+      } else {
+	int eqColNum = Tbl_EntryReadVarIndex(entry);
+	if (eqColNum == index) {
+	  Tbl_TableFree(newTable);
+	  return NIL(Tbl_Table_t);
+	}
+      }
+    } else if (colNum == index) {
+      if (Tbl_EntryReadNumValues(entry) == 1) {
+	Tbl_EntryComplement(entry, 0, 1);
+      }
+    }
+  }
+
+  return newTable;
+
+} /* Tbl_TableInvertBinaryInputColumn */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis           [Remove last row from table]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+boolean
+TblTableDeleteLastRow(
+  Tbl_Table_t* table)
+{
+  array_t *dataArray;
+  Tbl_Row_t *row;
+  int rowNum;
+
+  dataArray = array_dup(TblTableReadData(table));
+  array_free(TblTableReadData(table));
+  TblTableReadData(table)= array_alloc(Tbl_Row_t*,0);
+  for(rowNum=0; rowNum < (array_n(dataArray)-1); rowNum++) {
+    row = array_fetch(Tbl_Row_t*,dataArray,rowNum);
+    array_insert_last(Tbl_Row_t*,TblTableReadData(table),row);
+  }
+  return TRUE;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis           [Set entry correctly]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+
+******************************************************************************/
+static void SetAdjustedEntry(
+  Tbl_Table_t *table,
+  Tbl_Entry_t *entry,
+  int index,
+  int rownum,
+  int colnum,
+  boolean flag)
+{
+  Tbl_Entry_t *newEntry;
+
+  if (flag ==0) {
+    if (colnum < index) {
+      /* should free if necessary */
+      newEntry = Tbl_TableReadEntry(table,rownum,colnum,0);
+      if (newEntry==NIL(Tbl_Entry_t)) {
+	Tbl_TableSetEntry(table,entry,rownum,colnum,0);
+      }
+      else {
+	Tbl_EntryFree(entry);
+      }
+    }
+    else if (colnum > index) {
+      /* should free if necessary */
+      newEntry = Tbl_TableReadEntry(table,rownum,colnum-1,0);
+      if (newEntry==NIL(Tbl_Entry_t)) {
+	Tbl_TableSetEntry(table,entry,rownum,colnum-1,0);
+      }
+      else {
+	Tbl_EntryFree(entry);
+      }
+    }
+    else {
+      Tbl_EntryFree(entry);
+    }
+  }
+  else {
+    newEntry = Tbl_TableReadEntry(table,rownum,colnum,1);
+    if (newEntry== NIL(Tbl_Entry_t)) {
+      Tbl_TableSetEntry(table,entry,rownum,colnum,1);
+    }
+    else {
+      Tbl_EntryFree(newEntry);
+      Tbl_TableSetEntry(table,entry,rownum,colnum,1);
+
+      }
+    }
+}
+
+/**Function********************************************************************
+
+  Synopsis           [Set entry correctly]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+
+******************************************************************************/
+static void SetEntry(
+Tbl_Table_t *newTable,
+Tbl_Entry_t *entry1,
+Tbl_Entry_t *entry2,
+int rownum,
+int colnum,
+int index,
+boolean flag)
+{
+  int varcolnum;
+  Tbl_Entry_t *newEntry;
+
+
+  if (entry1->type == Tbl_EntryNormal_c) {
+    SetAdjustedEntry(newTable,Tbl_EntryDup(entry1),index,rownum,colnum, flag);
+  }
+  else {
+    /* its of type equal */
+    varcolnum = Tbl_EntryReadVarIndex(entry1);
+    if (varcolnum < index) {
+      SetAdjustedEntry(newTable,Tbl_EntryDup(entry1),index,rownum,colnum, flag);
+    }
+    else {
+      if (varcolnum > index) {
+	newEntry = Tbl_EntryDup(entry1);
+	Tbl_EntrySetEqual(newEntry,varcolnum-1);
+	SetAdjustedEntry(newTable,newEntry,index,rownum,colnum,flag);
+
+      }
+      else {
+	SetAdjustedEntry(newTable,Tbl_EntryDup(entry2),index,rownum,colnum, flag);
+      }
+    }
+  }
+}
Index: vis_dev/vis-2.3/src/tbl/tblTest.c
===================================================================
--- vis_dev/vis-2.3/src/tbl/tblTest.c	(revision 14)
+++ vis_dev/vis-2.3/src/tbl/tblTest.c	(revision 14)
@@ -0,0 +1,306 @@
+/**CFile***********************************************************************
+
+  FileName    [ tblTest.c ]
+
+  PackageName [ tbl ]
+
+  Synopsis    [ This package is used to manipulate the table data structure ]
+
+  Description [ The table data structure is used to store the information
+               contained in the blif_mv table. This structure supports all
+               constructs in blif_mv including  the recursive constructs.
+               This is consistent with the previous version of this data-
+               structure.]
+
+  SeeAlso     [ tbl.h, tblEntryUtil.c ]
+
+  Author      [ Gitanjali M. Swamy ]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+#include "tblInt.h"
+
+static char rcsid[] UNUSED = "$Id: tblTest.c,v 1.12 2009/04/11 02:01:29 fabio Exp $";
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandTableTest(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+static void TestTblPrint(Tbl_Table_t *table);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Initializes the table (Tbl) package.]
+
+  SideEffects []
+
+  SeeAlso     [Ntm_End]
+
+******************************************************************************/
+void
+Tbl_Init(void)
+{
+  Cmd_CommandAdd("_tbl_test", CommandTableTest, /* doesn't changes_network */0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Ends the table (Tbl) package]
+
+  SideEffects []
+
+  SeeAlso     [Ntm_Init]
+
+******************************************************************************/
+void
+Tbl_End(void)
+{
+}
+
+/**Function********************************************************************
+
+  Synopsis    [com function for testing]
+
+  Description [This is an internal function, whose purpose is to help
+  the developer test code. It is not fixed in function.]
+
+  SideEffects []
+
+  CommandName [_tbl_test]
+  CommandSynopsis [test the functionality of the tbl package.]
+  CommandArguments [\[-h\] \[-v\]]
+  CommandDescription [Tests the functionality of the tbl package.<p>
+  Command options:<p>
+  <dl><dt> -h
+  <dd> Print the command usage.
+  </dl>
+  <dl><dt> -v
+  <dd> Verbose mode.
+  </dl>]
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+CommandTableTest(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int c;
+  Tbl_Table_t *table;
+  int i;
+  Hrc_Node_t * node;
+  boolean verbose UNUSED = FALSE;              /* default */
+  
+  /*
+   * Parse the command line.
+   */
+
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "vh")) != EOF) {
+    switch (c) {
+      case 'v':
+        verbose = 1;
+        break;
+      case 'h':
+	goto usage;
+      default:
+        goto usage;
+    }
+  }
+  
+  node = Hrc_ManagerReadRootNode(*hmgr);
+  if (node == NIL(Hrc_Node_t)) {
+    (void) fprintf(vis_stdout, "No file has been read in. Use read_blif_mv.\n");
+    return 1;
+  }
+    
+  Hrc_NodeForEachNameTable(node,i,table) {
+    if (i>0) {
+      fprintf(vis_stdout, "---------------------------\n") ;
+      Tbl_TableWriteBlifMvToFile (table, 0, vis_stdout) ;
+        
+      fprintf(vis_stdout, "---------------------------\n") ;
+      
+    }
+    
+/*    TestTblPrint(table);    */
+  }
+    
+  return 0;
+  
+  usage:
+  (void) fprintf(vis_stderr, "usage: _tbl_test [-h] [-v]\n");
+  (void) fprintf(vis_stderr, "   -h        print the command usage\n");  
+  (void) fprintf(vis_stderr, "   -v        verbose\n");
+  return 1;             /* error exit */
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Test Table  code]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void TestTblPrint(
+  Tbl_Table_t *table)
+{
+/*  array_t *check; */
+  mdd_manager    *mddMgr; 
+  Tbl_Table_t *newTable;
+  int             i;
+/* int j, offset; */  
+/*   Mvf_Function_t *outMvf; */
+/*   Var_Variable_t *var; */
+/*   int             colNum; */
+/*   array_t        *faninMvfArray; */
+/*   array_t        *mvarValues; */
+/*   array_t        *totalSupportArray; */
+/*   int             numInputs; */
+  
+/*  int rowNumi, rowNumj; */
+/*  Tbl_Row_t *rowi, *rowj; */
+/*   boolean check; */
+
+  Tbl_TableWriteBlifMvToFile(table,0,vis_stdout);
+  mddMgr = mdd_init_empty();
+  for(i=0; i < Tbl_TableReadNumOutputs(table); i++){
+    if (Tbl_TableTestIsOutputSpaceComplete(table, mddMgr) ) {
+      newTable =
+          Tbl_TableCreateTrueSupportTableForOutput(table,NIL(Mvf_Function_t), mddMgr,0,i,NIL(array_t));
+      printf(" NEW table for %d \n", i);
+      Tbl_TableWriteBlifMvToFile(newTable,0,vis_stdout);
+      printf("\n");
+    }
+    
+  }
+  mdd_quit(mddMgr);
+
+/*   Tbl_TableWriteBlifMvToFile(table,0,vis_stdout);
+ *  printf(" Test 1\n");  
+ *  mddMgr = mdd_init_empty();
+ *  for(i=0; i < Tbl_TableReadNumOutputs(table); i++){
+ *   newTable =
+ *       Tbl_TableCreateTrueSupportTableForOutput(table,NIL(Mvf_Function_t), mddMgr,0,i,NIL(array_t));
+ *   printf(" NEW table for %d \n", i);
+ *   Tbl_TableWriteBlifMvToFile(newTable,0,vis_stdout);
+ *   printf("\n");    
+ * }
+ *    mdd_quit(mddMgr);
+ *
+ *  printf(" Test 2\n");
+ *
+ *  mddMgr = mdd_init_empty();
+ *  for(i=0; i < Tbl_TableReadNumOutputs(table); i++){
+ *  mvarValues        = array_alloc(int, 0);
+ *  numInputs         = Tbl_TableReadNumInputs(table );
+ *  totalSupportArray = array_alloc(int, 0);
+ *  faninMvfArray     = array_alloc(Mvf_Function_t *, 0);
+ *
+ *  Tbl_TableForEachInputVar(table, colNum, var) {
+ *    array_insert_last(int, mvarValues, Var_VariableReadNumValues(var));
+ *  }
+ *  offset = array_n(mdd_ret_mvar_list(mddMgr));    
+ *  mdd_create_variables(mddMgr,mvarValues, NIL(array_t), NIL(array_t));
+ *  array_free(mvarValues);
+ *
+ *  for (j = 0; j < numInputs; j++) {
+ *    Mvf_Function_t *faninMvf = Mvf_FunctionCreateFromVariable(mddMgr, (j+offset));
+ *    array_insert_last(Mvf_Function_t *, faninMvfArray, faninMvf);
+ *  }
+ *
+ *  outMvf = Tbl_TableBuildMvfFromFanins(table, i, faninMvfArray, mddMgr);
+ *  Mvf_FunctionArrayFree(faninMvfArray);
+ *   newTable =
+ *       Tbl_TableCreateTrueSupportTableForOutput(table,outMvf, mddMgr,offset,i,NIL(array_t));  
+ *   printf(" NEW table for %d \n", i);
+ *   Tbl_TableWriteBlifMvToFile(newTable,0,vis_stdout);
+ *   printf("\n");    
+ * }
+ *    mdd_quit(mddMgr);
+ */  
+  /* testing hard and soft dups */
+   
+/*   newTable = Tbl_TableHardDup(table);
+ *  printf(" NEW table Hard\n");
+ *  Tbl_TableWriteBlifMvToFile(newTable,0,vis_stdout);
+ *  Tbl_TableSetEntryDc(newTable,Tbl_TableReadNumRows(table)-1,\
+ *                      Tbl_TableReadNumInputs(table)-1, 0);
+ *  printf(" NEW table Hard Modify\n");
+ *  Tbl_TableWriteBlifMvToFile(newTable,0,vis_stdout);
+ *  printf(" Old  table Hard Modify \n" );
+ *  Tbl_TableWriteBlifMvToFile(table,0,vis_stdout);
+ *  Tbl_TableFree(newTable); 
+ * 
+ *  newTable = Tbl_TableSoftDup(table);
+ *  printf(" NEW table Soft\n");
+ *  Tbl_TableWriteBlifMvToFile(table,0,vis_stdout);  
+ *  printf(" NEW table Soft\n");
+ *  Tbl_TableWriteBlifMvToFile(newTable,0,vis_stdout);
+ *  Tbl_TableSetEntryDc(newTable,Tbl_TableReadNumRows(table)-1,\
+ *                      Tbl_TableReadNumInputs(table)-1, 0);
+ *  printf(" NEW table Soft Modify\n");
+ *  Tbl_TableWriteBlifMvToFile(newTable,0,vis_stdout);
+ *  printf(" Old  table Soft Modify \n" );
+ *  Tbl_TableWriteBlifMvToFile(table,0,vis_stdout);
+ *  Tbl_TableFree(newTable);
+ *   Tbl_TableFree(table);
+ */
+
+  /* testing row intersect */
+  
+/*   TblTableForEachRow(table,rowi,rowNumi) {
+ *     TblTableForEachRow(table,rowj,rowNumj) {
+ *       check = Tbl_RowInputIntersect(table,rowNumi, rowNumj);
+ *       printf("Rows %d and %d intersect = %d\n",rowNumi, rowNumj, check);
+ *     }
+ * }
+ */
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/tbl/tblUtil.c
===================================================================
--- vis_dev/vis-2.3/src/tbl/tblUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/tbl/tblUtil.c	(revision 14)
@@ -0,0 +1,3454 @@
+/**CFile***********************************************************************
+
+  FileName    [ tblUtil.c ]
+
+  PackageName [ tbl ]
+
+  Synopsis    [ This package is used to manipulate the table data structure ]
+
+  Description [ The table data structure is used to store the information
+               contained in the blif_mv table. This structure supports all
+               constructs in blif_mv including  the recursive constructs.
+               This is consistent with the previous version of this data-
+               structure. Note that the table package is in no way concerned
+               with the semantics of the table constructed; it makes no
+               interpretation on the correctness of a table (i.e. does
+               it represent valid hardware)]
+
+  SeeAlso     [ tbl.h, tblEntryUtil.c ]
+
+  Author      [ Gitanjali M. Swamy ]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+#include "tblInt.h"
+
+static char rcsid[] UNUSED = "$Id: tblUtil.c,v 1.19 2009/04/11 02:01:29 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/* Structure used to sort table inputs. */
+typedef struct varOrdStruct {
+  int id;			/* input column number */
+  int rank;			/* low-ranked columns should go first */
+} Var_Ord_t;
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int TableEntryComputeHashVal(Tbl_Table_t *table, Tbl_Entry_t *entry);
+static array_t* TableCreatIntArray(int size);
+static char* TableObtainSignature(Tbl_Table_t * table, int outputColumn);
+static int varCompare(const void *x, const void *y);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function***********************************************************
+
+  Synopsis	[ Allocate a new table. ]
+
+  Description	[ This functions allocates memory for and returns a new table ]
+
+  SideEffects	[ ]
+
+  SeeAlso	[ Tbl_Free ]
+**********************************************************************/
+Tbl_Table_t*
+Tbl_TableAlloc(void)
+{
+  Tbl_Table_t * table;
+
+  table = ALLOC(Tbl_Table_t,1);
+  table->inputNames = array_alloc(Var_Variable_t*,0);
+  table->outputNames = array_alloc(Var_Variable_t*,0);
+  table->data = ALLOC(Tbl_Data_t,1);  
+  TblTableReadDefaults(table) = array_alloc(Tbl_Entry_t*,0);
+  TblTableReadRefCount(table) = 1;
+  TblTableReadData(table) = array_alloc(Tbl_Row_t*,0);
+  return table;
+}
+
+
+/**Function***********************************************************
+  Synopsis	[ Free a table. ]
+
+  Description	[ Given a table, this routine decreases the table refcount. If
+  the refCount == 1 then it also frees it, i.e. it  also frees each and every
+  Tbl_Entry_t entry in the table ]
+
+  SideEffects	[ Does not free the Vars associated with the table. This is
+                  the responsibility of the user.]
+
+  SeeAlso	[ Tbl_Alloc ]
+**********************************************************************/
+void
+Tbl_TableFree(
+  Tbl_Table_t *  table /* The table to be freed */)
+{
+  int i,j,k;
+  Tbl_Row_t * row;
+  Tbl_Entry_t *entry;
+    
+    
+  if (table != NIL(Tbl_Table_t)) {
+    if (TblTableReadRefCount(table) < 2) {
+  Tbl_TableForEachEntry(table,j,i,k,entry) {
+      if (entry != NIL(Tbl_Entry_t)) {
+        Tbl_EntryFree(entry);
+      }
+    }                        
+    TblTableForEachRow(table,row,i){
+      array_free(row->inputs);
+      array_free(row->outputs);
+      FREE(row);
+    }
+    Tbl_TableForEachDefaultEntry(table,entry,i) {
+      if (entry != NIL(Tbl_Entry_t)) {
+        Tbl_EntryFree(entry);
+      }
+    }            
+    array_free(TblTableReadDefaults(table));
+    array_free(TblTableReadData(table));
+    FREE(table->data);
+  
+    }
+  else {
+    TblTableReadRefCount(table)--;;
+  }
+    array_free(table->inputNames);
+    array_free(table->outputNames);
+    FREE(table);
+  }
+}   
+
+/**Function***********************************************************
+
+  Synopsis	[ Soft Duplicate a table. ]
+
+  Description	[ This routines increases the refcounts of the table. ]
+
+  SideEffects	[ Do not modify the soft duplicate tables's entries; it
+  will modify the original table. For this use Tbl_TableHardDup]
+
+  SeeAlso	[ Tbl_TableFree Tbl_TableHardDup]
+**********************************************************************/
+Tbl_Table_t *
+Tbl_TableSoftDup(
+  Tbl_Table_t *  table /* The table to be duplicated */)
+{
+  Tbl_Table_t *tabledup;
+
+  assert(TblTableReadRefCount(table) >0);
+  tabledup = ALLOC(Tbl_Table_t,1);
+  tabledup->data = table->data;
+
+  tabledup->inputNames = array_dup(table->inputNames);
+  tabledup->outputNames = array_dup(table->outputNames);
+  
+  TblTableReadRefCount(table) ++;
+  return tabledup;
+}
+
+/**Function***********************************************************
+
+  Synopsis	[ Duplicate a table. ]
+
+  Description	[ This routines creates a duplicate of table. However 
+                  table entries are copied, but not Vars.  ]
+
+  SideEffects	[  ]
+
+  SeeAlso	[ Tbl_TableFree Tbl_TableSoftDup]
+**********************************************************************/
+Tbl_Table_t *
+Tbl_TableHardDup(
+  Tbl_Table_t *  table /* The table to be duplicated */)
+{
+  Tbl_Table_t * tabledup;
+  int i;
+  Tbl_Entry_t *newEntry, *entry;
+  Var_Variable_t *var;
+  Tbl_Row_t *row;
+
+  tabledup = Tbl_TableAlloc();
+
+  Tbl_TableForEachInputVar(table,i,var){
+    Tbl_TableAddColumn(tabledup,var,0);
+  }
+
+  Tbl_TableForEachOutputVar(table,i,var){
+    Tbl_TableAddColumn(tabledup,var,1);
+  }  
+
+  Tbl_TableForEachDefaultEntry(table,entry,i) {
+    if (entry != NIL(Tbl_Entry_t)) {
+      newEntry = Tbl_EntryDup(entry);
+    }
+    else {
+      newEntry = NIL(Tbl_Entry_t);
+    }
+    (void) Tbl_TableDefaultSetEntry(tabledup,newEntry,i);
+  }
+
+  TblTableForEachRow(table,row,i){
+    TblTableSetRow(tabledup,TblRowDup(row),i);
+  }
+  
+  return tabledup;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Set the default value at given index]
+
+  Description [Given a Tbl_Table_t, a default Tbl_Entry_t and an index, this
+  sets the value of the default at this index to the entry. If the value of the
+  index is larger than the default array size, this return a 0, else it
+  sets the value and returns a 1.]
+
+  SideEffects []
+
+  SeeAlso     [Tbl_TableDefaultReadEntry]
+
+******************************************************************************/
+boolean
+Tbl_TableDefaultSetEntry(
+    Tbl_Table_t *table,
+    Tbl_Entry_t *entry,
+    int index)
+{
+  if (TblTableReadRefCount(table) > 1) {
+    printf(" WARNING: You are modifying more than one table by re-setting this entry\n");
+  }
+  
+  if (array_n(TblTableReadDefaults(table)) < index) {
+    return FALSE; 
+  }
+  
+  if (entry != NIL(Tbl_Entry_t)) {
+    entry->ioType = 1;
+    entry->varColNum = index;
+    /* debug */
+    if (entry->type == Tbl_EntryEqual_c)
+    assert(Tbl_EntryReadVarIndex(entry) < Tbl_TableReadNumInputs(table));    
+  }
+  
+  
+  array_insert(Tbl_Entry_t*, TblTableReadDefaults(table),index,entry);
+  return TRUE;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Read the default value at given index]
+
+  Description [Given a Tbl_Table_t and an index, this
+  reads  the value of the default entry, and returns it.
+  If the index is larger than the array size, it returns a
+  NIL entry]
+
+  SideEffects []
+
+  SeeAlso     [Tbl_TableDefaultSetEntry]
+
+******************************************************************************/
+Tbl_Entry_t*
+Tbl_TableDefaultReadEntry(
+    Tbl_Table_t *table,
+    int index)
+{
+  if (array_n(TblTableReadDefaults(table)) < index) {
+    return NIL(Tbl_Entry_t); 
+  }
+
+  return (array_fetch(Tbl_Entry_t*, TblTableReadDefaults(table),index));
+}
+
+    
+/**Function***********************************************************
+
+  Synopsis	[ Add an empty row (logically inert) to table. ]
+
+  Description	[ Given a table this function adds an empty row at the end of
+                  the table. It return the index of the row it creates]
+
+  SideEffects	[ Table has changed, and the one new row needs to be filled in ]
+
+  SeeAlso	[ optional ]
+**********************************************************************/
+int 
+Tbl_TableAddRow(
+  Tbl_Table_t *  table)
+{
+  Tbl_Row_t * row;
+  int i;
+
+  if (table != NIL(Tbl_Table_t)) {
+  if (TblTableReadRefCount(table) > 1) {
+    printf(" WARNING: You are modifying more than one table by adding this row\n");
+  }    
+      row = ALLOC(Tbl_Row_t,1);
+      row->inputs = array_alloc(Tbl_Entry_t*,0);
+      for (i=0; i < array_n(table->inputNames); i++) {
+        array_insert_last(Tbl_Entry_t*,row->inputs, NIL(Tbl_Entry_t)); 
+      }
+      
+
+      row->outputs = array_alloc(Tbl_Entry_t*,0);
+      for (i=0; i < array_n(table->outputNames); i++) {
+        array_insert_last(Tbl_Entry_t*,row->outputs, NIL(Tbl_Entry_t)); 
+      }
+                        
+      array_insert_last(Tbl_Row_t*, TblTableReadData(table),row);
+      return ( array_n(TblTableReadData(table)) -1);
+    }
+  else return -1;
+}  
+
+/**Function***********************************************************
+
+  Synopsis	[ Add an empty column with the given Var ]
+
+  Description [ Given a table this function adds an empty column at
+                the end of all columns, associates this column with a
+                Var_Variable_t (Var).  It returns the number of (input
+                or output) columns in the table. If the operation
+                fails, the program is exited.  It must also be
+                supplied with a flag to indicate whether an input or
+                output entry is being read.  It is the users
+                responsibility to ensure that the same var is not
+                already present; the table package is not concerned
+                with the semantics of the table.]
+
+  SideEffects	[  ]
+
+  SeeAlso	[ optional ]
+**********************************************************************/
+int
+Tbl_TableAddColumn(
+  Tbl_Table_t *  table /* the table */,
+  Var_Variable_t *  var /* the Var being added */,
+  int  flag /* This flag is set to 0 if it is an input and 1 if it is and output
+ */)
+{
+  int i, index;
+  Tbl_Row_t *row;
+  array_t *carray;
+  
+  assert(table !=NIL(Tbl_Table_t));
+  assert((flag==0)||(flag ==1));
+  if (TblTableReadRefCount(table) > 1) {
+    printf(" WARNING: You may be modifying more than one table by adding this column\n");
+  }  
+  index = 0;
+  for (i=0; i< array_n(TblTableReadData(table)); i++) {
+    row = array_fetch(Tbl_Row_t*,TblTableReadData(table),i);
+    if (flag==0) {
+      carray = row->inputs; 
+    }
+    else {
+      carray = row->outputs; 
+    }
+  
+    array_insert_last(Tbl_Entry_t*,carray,NIL(Tbl_Entry_t));
+  
+  }
+  if (flag==0) {
+    array_insert_last(Var_Variable_t*, table->inputNames, var);
+    index = array_n(table->inputNames);
+  }
+  else {
+      array_insert_last(Var_Variable_t*, table->outputNames, var);
+      index = array_n(table->outputNames);      
+      array_insert_last(Tbl_Entry_t*,
+                        TblTableReadDefaults(table),NIL(Tbl_Entry_t));
+    }
+
+  return index;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Deletes specified row of table]
+
+  Description [Deletes a specified row of the table. It creates a new table, 
+               and copies all but the the specified row into the new table, 
+	       and points the original table pointer to the new table. The 
+	       original table is freed]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Tbl_Table_t *
+Tbl_TableRowDelete(
+   Tbl_Table_t *originalTable,
+   int rowNumToDelete,
+   array_t *freeArray		 
+   )
+{
+    Tbl_Table_t *newTable;
+    int i, rownum, newRowNum, numInputs, numOutputs;
+    Var_Variable_t *var, *newVar;
+    Tbl_Row_t *row UNUSED;
+    Tbl_Entry_t *newEntry, *origEntry, *entry, *dupEntry;
+
+    newTable = Tbl_TableAlloc();
+    Tbl_TableForEachInputVar(originalTable, i, var){
+	newVar = Var_VariableDup(var, NIL(Hrc_Node_t));
+	array_insert_last(Var_Variable_t *, freeArray, newVar);
+	(void) Tbl_TableAddColumn(newTable, newVar, 0);
+    }
+    Tbl_TableForEachOutputVar(originalTable, i, var){
+	newVar = Var_VariableDup(var, NIL(Hrc_Node_t));
+	array_insert_last(Var_Variable_t *, freeArray, newVar);
+	(void) Tbl_TableAddColumn(newTable, newVar, 1);
+    }
+    for(i = 0; i < Tbl_TableReadNumOutputs(originalTable); i++){
+ 	entry = Tbl_TableDefaultReadEntry(originalTable, i);
+ 	if(entry != NIL(Tbl_Entry_t)){
+	    dupEntry = Tbl_EntryDup(entry);
+	    Tbl_TableDefaultSetEntry(newTable, dupEntry, i);
+ 	}
+    }
+    numInputs = Tbl_TableReadNumInputs(originalTable);
+    numOutputs = Tbl_TableReadNumOutputs(originalTable);
+    TblTableForEachRow(originalTable, row, rownum){
+	if(rownum != rowNumToDelete){
+	    newRowNum = Tbl_TableAddRow(newTable);
+	    for(i = 0; i < numInputs; i++){
+		origEntry = Tbl_TableReadEntry(originalTable, rownum, i, 0);
+		newEntry = Tbl_EntryDup(origEntry);
+		Tbl_TableSetEntry(newTable, newEntry, newRowNum, i, 0);
+	    }
+	    for(i = 0; i < numOutputs; i++){
+		origEntry = Tbl_TableReadEntry(originalTable, rownum, i, 1);
+		newEntry = Tbl_EntryDup(origEntry);
+		Tbl_TableSetEntry(newTable, newEntry, newRowNum, i, 1);
+	    }
+	}
+    }
+    Tbl_TableFree(originalTable);
+    return newTable;
+}
+
+/**Function***********************************************************
+
+  Synopsis	[ Find the Var of the variable (column) associated
+                 with the given index. ]
+
+  Description	[ Given an index , this functions returns the
+                  Var of the column that is represented by. If any of the
+                  input data is incorrect it exits the program.
+                  It must also be supplied with a flag to indicate whether
+                  an input or output entry is being read.]
+
+  SideEffects	[  ]
+
+  SeeAlso	[ optional ]
+**********************************************************************/
+Var_Variable_t*
+Tbl_TableReadIndexVar(
+  Tbl_Table_t *  table,
+  int index,
+  int  flag /* Set to 0 if it is an input Var and 1 if it an output Var */
+)
+{
+  array_t *carray;
+
+  assert(table !=NIL(Tbl_Table_t));
+  assert((flag==0)||(flag ==1));
+  
+  if (flag==0) {
+    carray = table->inputNames;
+  }
+  else {
+    carray = table->outputNames;
+  }
+            
+  return (array_fetch(Var_Variable_t*,carray,index));
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Returns  the entry in row i, input/output  column j,   ]
+
+  Description [ This function returns the table entry at row i and column j.
+                The item is of the Tbl_Entry_t. The flag indicates whether it
+                is an input (flag = 0)  or and output (flag =1) item.
+                If any of the input data is incorrect it exits the program]
+
+  SideEffects [  ]
+
+  SeeAlso     [ optional ]
+
+******************************************************************************/
+Tbl_Entry_t *
+Tbl_TableReadEntry(
+  Tbl_Table_t *  table ,
+  int  rowNum,
+  int  colNum,
+  int  flag )
+{
+  Tbl_Row_t *row;
+  Tbl_Entry_t *entry;
+    
+
+  assert(table !=NIL(Tbl_Table_t));
+  assert((flag==0)||(flag ==1));
+  
+  row = TblTableReadRow(table,rowNum);
+  entry = TblRowReadEntry(row,colNum,flag);
+    
+  return entry;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Sets   the entry in row i, input/output  column j to
+  given entry   ]
+
+  Description [ This function sets the table entry at row i and column j
+                to given Tbl_Entry_t. The flag indicates whether it
+                is an input or and output item. If any of the input data is
+                incorrect it return a FALSE]
+
+  SideEffects [ Old Value is lost ]
+
+  SeeAlso     [ optional ]
+
+******************************************************************************/
+boolean 
+Tbl_TableSetEntry(
+  Tbl_Table_t *  table /* The Table to be examined */,
+  Tbl_Entry_t * newEntry,
+  int  i /* Row Id */,
+  int  j /* Column Id */,
+  int  flag /* flag indicating whether it is an input or output */)
+{
+  Tbl_Row_t *row;
+  Tbl_Entry_t *entry;
+
+  assert(table !=NIL(Tbl_Table_t));
+  assert((flag==0)||(flag ==1));
+  if (TblTableReadRefCount(table) > 1) {
+    printf(" WARNING: You are modifying more than one table by  re-setting this entry\n");
+  }
+
+  entry = Tbl_TableReadEntry(table ,i,j,flag);
+ if (entry != NIL(Tbl_Entry_t)) {
+   Tbl_EntryFree(entry);
+  }
+
+  row = TblTableReadRow(table,i);
+
+  newEntry->ioType = flag;
+  newEntry->varColNum = j;
+  TblRowSetEntry(row,newEntry,j,flag);
+  
+  return TRUE;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Sets the entry in row i,  column j, to a don't care.  ]
+
+  Description [ This function sets the table entry at row i and column j.
+                The item is of the Tbl_Entry_t. The flag indicates whether it
+                is an input or and output item. If any of the input data is
+                incorrect it exits the program]
+
+  SideEffects [ ]
+
+  SeeAlso     [ Tbl_EntrySetValue ]
+
+******************************************************************************/
+boolean
+Tbl_TableSetEntryDc(
+  Tbl_Table_t *  table,
+  int  i,
+  int  j,
+  int  flag)
+{
+  array_t *ioarray;
+  int range;
+  Tbl_Entry_t *entry;
+
+  assert(table !=NIL(Tbl_Table_t));
+  assert((flag==0)||(flag ==1));
+  if (TblTableReadRefCount(table) > 1) {
+    printf(" WARNING: You are modifying more than one table by re-setting this entry\n");
+  }
+  
+  if (flag==0) {
+    ioarray = table->inputNames;
+  }
+  else {
+    ioarray = table->outputNames;
+  }
+
+  range = Var_VariableReadNumValues(array_fetch(Var_Variable_t*,ioarray,j));
+  entry = Tbl_TableReadEntry(table,i,j,flag);
+  Tbl_EntrySetValue(entry,0,range-1);
+  return TRUE;
+}
+/**Function********************************************************************
+
+  Synopsis    [ Adds the range val1-val2 to the union in row i, column j. ]
+
+  Description [ This function when supplied with row i,col j, a table
+                and a range specified by integers val1 and val2, will
+                add range val1-val2 to the i,j th entry in the
+                table. It must also be supplied with a flag to
+                indicate whether an input or output entry is being
+                read.]
+
+  SideEffects [ ]
+
+  SeeAlso     [ ]
+
+******************************************************************************/
+void
+Tbl_TableAddEntryRange(
+  Tbl_Table_t *  table,
+  int  i,
+  int  j,
+  int  val1,
+  int  val2,
+  int  flag)
+{
+  Tbl_Entry_t *entry;
+
+  if (TblTableReadRefCount(table) > 1) {
+    printf(" WARNING: You are modifying more than one table by changing the re-setting this entry\n");
+  }
+  
+  entry = Tbl_TableReadEntry(table,i,j,flag);
+  Tbl_EntrySetValue(entry,val1,val2);
+    
+}
+  
+/**Function********************************************************************
+
+  Synopsis    [ Complements the constant or union in row i,
+                 input/output column j.  ]
+
+  Description [ This function whether supplied with row i,col j, a table will
+                complement the i,j th entry in the table. It must also be supplied with a
+                 flag to indicate whether an input or output entry is being read.]
+
+  SideEffects [ ]
+
+  SeeAlso     [ optional ]
+
+******************************************************************************/
+void
+Tbl_TableComplementEntry(
+  Tbl_Table_t *  table,
+  int  i,
+  int  j,
+  int  flag)
+{
+  Tbl_Entry_t *entry;
+    
+  entry = Tbl_TableReadEntry(table,i,j,flag);
+  Tbl_EntryComplement(entry,0,(Var_VariableReadNumValues(Tbl_EntryReadActualVar(table, entry))) -1 );
+
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Sets the io entry row i, output column j to be 
+                  equal to the given Var.  ]
+
+  Description [ This function sets the entry in row i and column j to be
+  equal to the entry  specified by the given var]
+
+  SideEffects [ ]
+
+  SeeAlso     [ ]
+
+******************************************************************************/
+void
+Tbl_TableSetEquality(
+  Tbl_Table_t *  table,
+  int  i,
+  int  j,
+  int flag,
+  Var_Variable_t *  var)
+{
+  Tbl_Entry_t *entry;
+  int index,check;
+  Var_Variable_t *tblVar;
+
+  check =0;
+  entry = Tbl_TableReadEntry(table,i,j,flag);
+  Tbl_TableForEachInputVar(table, index,tblVar) {
+    if (tblVar == var) {
+      Tbl_EntrySetEqual(entry,index);
+      check =1;
+      break;
+    }
+  }
+  
+  if (check == 0) {
+    printf(" WARNING: Output Equal Another Output not supported, no change made\n ");
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Returns 1 if the entry in row i, input/output column j 
+               is a don't care.  ]
+
+  Description [ This function returns 1 if the entry in row i and col j is
+  a DC, 0 if it isn't and -1 if it does not exist. It must also be supplied with a
+  flag to indicate whether an input or output entry is being read.]
+
+  SideEffects [ ]
+
+  SeeAlso     [ optional ]
+
+******************************************************************************/
+boolean
+Tbl_TableEntryIsDc(
+  Tbl_Table_t *  table,
+  int  i,
+  int  j,
+  int flag)
+{
+  Tbl_Range_t *range;
+  Tbl_Entry_t *entry;
+  lsGen gen;
+  Var_Variable_t *var;
+  
+  assert(table !=NIL(Tbl_Table_t));
+
+  entry = Tbl_TableReadEntry(table,i,j,flag);
+
+    if (lsLength(entry->EntryData.listOfRanges) == 1){
+      var = Tbl_EntryReadActualVar(table,entry);
+      lsForEachItem(entry->EntryData.listOfRanges, gen, range) {
+        if ((range->begin ==0)&&(range->end ==
+                                 Var_VariableReadNumValues(var)-1)){
+          lsFinish(gen);
+          return TRUE;
+        }
+      }
+    }
+  return FALSE;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Returns TRUE if the output designated by outputColumnId is a constant. ]
+
+  Description [ Returns TRUE if the table has no inputs, and exactly one row,
+  and the output entry in row 0 and column outputColumnId is of type normal
+  and takes exactly one value. Note that this test is conservative, because it
+  does not take into account Boolean redundancies. It merely checks for one of
+  the following conditions 1) the table has no inputs and a constant output 2)
+  the table has only - inputs in the one row and the output is constant
+  3) the table is empty and the default value for the output is constant and
+  4) the table output has the same constant value for all inputs]
+
+  SideEffects [ ]
+
+  SeeAlso     [ Tbl_TableTestIsNonDeterministicConstant ]
+
+******************************************************************************/
+boolean
+Tbl_TableTestIsConstant(
+  Tbl_Table_t *  table,
+  int            outputColumnId)
+{
+  int colNum, rowNum;
+  boolean check;
+  Tbl_Entry_t *entry;
+  Var_Variable_t *var;
+  Tbl_Range_t *range;
+  lsGen gen;
+  int value, constant,count;
+  
+  
+  assert(table !=NIL(Tbl_Table_t));
+  assert((outputColumnId >= 0) && (outputColumnId <
+                                   Tbl_TableReadNumOutputs(table)));
+
+  if (Tbl_TableReadNumRows(table) == 1) {  
+    if (array_n(table->inputNames) == 0) {
+      entry = Tbl_TableReadEntry(table, 0, outputColumnId, 1);
+      if (entry->type == Tbl_EntryNormal_c) {
+        if (Tbl_EntryReadNumValues(entry) == 1) {
+          return TRUE;
+        }
+      }
+    }
+    else {
+      check = TRUE;
+      Tbl_TableForEachInputEntry(table,rowNum,colNum,entry) {
+        if (entry->type != Tbl_EntryNormal_c) {
+          return FALSE;
+        }
+        if (check == TRUE) {
+          check = FALSE;
+          if (lsLength(entry->EntryData.listOfRanges) == 1){
+            var = Tbl_EntryReadActualVar(table,entry);
+            lsForEachItem(entry->EntryData.listOfRanges, gen, range) {
+              if ((range->begin ==0)&&(range->end ==
+                                       Var_VariableReadNumValues(var)-1)){
+                check = TRUE;
+              }
+            }
+          }
+        }
+      }
+      
+      if (check) {
+        entry = Tbl_TableReadEntry(table,0,outputColumnId,1);
+        if (entry->type != Tbl_EntryNormal_c) {
+          return FALSE;
+        }            
+        if (Tbl_EntryReadNumValues(entry) == 1) {
+          return TRUE;
+        }
+      }
+    }
+  }
+  else if (Tbl_TableReadNumRows(table) == 0) {
+    entry = Tbl_TableDefaultReadEntry(table,outputColumnId);
+    if (entry->type != Tbl_EntryNormal_c) {
+      return FALSE;
+    }    
+    if (Tbl_EntryReadNumValues(entry) == 1) {
+      return TRUE;
+    }
+  }
+  else {
+    entry = Tbl_TableDefaultReadEntry(table,outputColumnId);    
+    if (entry == NIL(Tbl_Entry_t)){
+      constant = -1;      
+      Tbl_TableForEachOutputEntry(table,rowNum,colNum,entry) {
+        if (colNum == outputColumnId) {
+          if (entry->type != Tbl_EntryNormal_c){
+            return FALSE;
+          }          
+          count = 1;
+          Tbl_EntryForEachValue(entry,value,gen,range) {
+            lsStatus status;
+            if (count > 1) {
+              status = lsFinish(gen); 
+              assert(status == LS_OK);  
+              return FALSE;
+            }
+            else {
+              if (constant != -1) {
+                if (constant != value) {
+                  status = lsFinish(gen);
+                  assert(status == LS_OK); 
+                  return FALSE;
+                }
+              }
+              else {
+                constant = value;
+              }
+            }
+            count ++;        
+          }
+        }
+      }
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Returns TRUE if the output designated by outputColumnId is a
+  nondeterministic constant. ]
+
+  Description [ Returns TRUE if the table has no inputs, and the output
+  referred to by outputColumnId is not a constant. ]
+
+  SideEffects [ ]
+
+  SeeAlso     [ Tbl_TableTestIsConstant ]
+
+******************************************************************************/
+boolean
+Tbl_TableTestIsNonDeterministicConstant(
+  Tbl_Table_t *  table,
+  int            outputColumnId)
+{
+  assert(table !=NIL(Tbl_Table_t));
+  
+  if (array_n(table->inputNames) == 0) {
+    if (!Tbl_TableTestIsConstant(table, outputColumnId)) {
+      return TRUE;
+    }
+  }
+  
+  return FALSE;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Returns TRUE if the table is deterministic. ]
+
+  Description [ This implements a sufficient but not necessary check for
+  determinism. It intersects every pair of inputs rows and compares the
+  outputs to see if they are identical.]
+
+  SideEffects [ ]
+
+  SeeAlso     [ optional ]
+
+******************************************************************************/
+int
+Tbl_TableTestIsDeterministic(
+  Tbl_Table_t *  table)
+{
+
+/* intersect every pair of input rows and
+   then compare outputs if they're not same --- */
+/* Sunil Khatri is implementing this */
+  return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis           [Test if given table has a completely specified output space]
+
+  Description        [Given a table, this function will check if the given
+  output has a completely specified output space, i.e. each output combination
+  is present in the table. If this function is called on a table with inputs,
+  it fails and exits. ]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+******************************************************************************/
+boolean
+Tbl_TableTestIsOutputSpaceComplete(
+  Tbl_Table_t *table,
+  mdd_manager *mddMgr)
+{
+  int i, offset,rowNum,colNum,oldRowNum;
+  boolean check;
+  Mvf_Function_t *mvf;
+  mdd_t *temp, *result, *function, *x;
+  Var_Variable_t *var;
+  Tbl_Entry_t *entry;
+  array_t        *faninMvfArray ;
+  array_t        *mvarValues ;
+  int             numOutputs;
+  
+  if (Tbl_TableReadNumInputs(table) != 0) {
+    return FALSE;
+  }
+
+  x = NIL(mdd_t);
+  faninMvfArray     = array_alloc(Mvf_Function_t *, 0);
+  mvarValues        = array_alloc(int, 0);
+  numOutputs         = Tbl_TableReadNumOutputs(table );
+
+  
+  /* Add mdd's for new table input variables. */
+  Tbl_TableForEachOutputVar(table, colNum, var) {
+    array_insert_last(int, mvarValues, Var_VariableReadNumValues(var));
+  }
+  offset = array_n(mdd_ret_mvar_list(mddMgr));    
+  mdd_create_variables(mddMgr,mvarValues, NIL(array_t), NIL(array_t));
+  array_free(mvarValues);
+
+  /*
+   * Construct an MVF for each table input. The MVF for column i is the MVF
+   * for MDD variable i.
+   */
+  for (i = 0; i < numOutputs; i++) {
+    Mvf_Function_t *faninMvf = Mvf_FunctionCreateFromVariable(mddMgr, (i+offset));
+    array_insert_last(Mvf_Function_t *, faninMvfArray, faninMvf);
+  }
+  /* Compute the MVF of the outputs */
+
+/* iterate over output part and compute all mvf's of rows */
+/* add to total */
+  function = mdd_zero(mddMgr);
+  oldRowNum = -1;
+  result = mdd_zero(mddMgr);  
+  Tbl_TableForEachOutputEntry(table,rowNum,colNum,entry) {    
+    if (rowNum != oldRowNum) {
+      temp =function;
+      function = mdd_or(temp,result, 1,1);
+      mdd_free(temp);
+      mdd_free(result);        
+      result = mdd_one(mddMgr);
+    }
+    if (entry->type == Tbl_EntryNormal_c) {
+      mvf = array_fetch(Mvf_Function_t*,faninMvfArray,colNum);
+      x = TblEntryNormalConstructMdd(mddMgr,entry,mvf);          
+    }
+    else  if (entry->type == Tbl_EntryEqual_c) {
+      printf("Failure: output equal to another output construct not supported\n");
+      assert(FALSE);
+    }
+    temp = result;
+    result = mdd_and(x,temp,1,1);
+    mdd_free(x);
+    mdd_free(temp);
+    oldRowNum = rowNum;
+  }
+  temp =function;
+  function = mdd_or(temp,result, 1,1);
+  mdd_free(temp);
+  mdd_free(result);        
+
+  check = mdd_is_tautology(function,1);
+  mdd_free(function);
+  
+  for (i=0;i < array_n(faninMvfArray); i++){
+    Mvf_FunctionFree(array_fetch(Mvf_Function_t *,faninMvfArray,i));
+  }
+  array_free(faninMvfArray);
+  return check;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Computes the inputs in the true support of a given output of a
+  table.]
+
+  Description [Computes the inputs in the true support of a given output of a
+  table.  This is done by building the MVF for the output in terms of the MVFs
+  of the inputs, where each input is treated as a free variable. Next the
+  function  Mvf_FunctionComputeSupport is called on the mvf.
+  The support is returned as an array of integers corresponding
+  to the input columns in the true support. This function must also be
+  supplied with an mdd_manager. If
+  the output is a constant, then this function returns a NIL(array_t), and
+  puts the constant value in the int *value that is passed in.]
+
+  SideEffects [It is the user's responsibility to free the mdd_manager
+  supplied, (use mdd_quit)]
+
+  SeeAlso     [Tbl_TableBuildMvfFromFanins]
+
+******************************************************************************/
+array_t *
+Tbl_TableComputeMvfAndInputDependenciesOfOutput(
+  Tbl_Table_t *table,
+  mdd_manager  *mddMgr,  
+  int          outIndex,
+  int *value)
+{
+  int             i, offset;
+  Mvf_Function_t *outMvf;
+  Var_Variable_t *var;
+  int             colNum;
+  array_t        *faninMvfArray     = array_alloc(Mvf_Function_t *, 0);
+  array_t        *mvarValues        = array_alloc(int, 0);
+  array_t        *totalSupportArray = array_alloc(int, 0);
+  int             numInputs         = Tbl_TableReadNumInputs(table );
+  
+  /* Add mdd's for new table input variables. */
+  Tbl_TableForEachInputVar(table, colNum, var) {
+    array_insert_last(int, mvarValues, Var_VariableReadNumValues(var));
+  }
+  offset = array_n(mdd_ret_mvar_list(mddMgr));    
+  mdd_create_variables(mddMgr,mvarValues, NIL(array_t), NIL(array_t));
+  array_free(mvarValues);
+
+  /*
+   * Construct an MVF for each table input. The MVF for column i is the MVF
+   * for MDD variable i.
+   */
+  for (i = 0; i < numInputs; i++) {
+    Mvf_Function_t *faninMvf = Mvf_FunctionCreateFromVariable(mddMgr, (i+offset));
+    array_insert_last(Mvf_Function_t *, faninMvfArray, faninMvf);
+  }
+  /* Compute the MVF of the output indexed by outIndex. */
+  outMvf = Tbl_TableBuildMvfFromFanins(table, outIndex, faninMvfArray, mddMgr);
+  Mvf_FunctionArrayFree(faninMvfArray);
+
+
+  totalSupportArray 
+      = Mvf_FunctionComputeSupport(outMvf,mddMgr,value);
+  
+  Mvf_FunctionFree(outMvf);  
+  return totalSupportArray;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [Given an output column (and maybe its mvf)
+  return a table with the true support inputs of the given output.]
+
+  Description        [If a NIL(Mvf_Function_t) is supplied as input to this function
+  , it uses Tbl_TableComputeMvfAndInputDependenciesOfOutput to compute the
+  true support of the given output (outIndex), and then creates a
+  new table for this output with only the true inputs. 
+  Given a non-nil Mvf of the table output, this function
+  uses   Mvf_FunctionComputeSupport to compute the true support of
+  the given output (index), and then creates a new table for this output
+  with only the true inputs. It returns the new table for the output of given
+  index. If the output is a constant, then this function returns a constant
+  table. If a non-nil mvf is supplied, then the function must also be
+  supplied with an int offset, such that for mddid 
+  of column j is  (j+offset) in the mvf supplied.]
+
+  SideEffects        [Variables may be added to the mdd manager]
+
+  SeeAlso            [Tbl_TableComputeMvfAndInputDependenciesOfOutput]
+
+******************************************************************************/
+Tbl_Table_t*
+Tbl_TableCreateTrueSupportTableForOutput(
+  Tbl_Table_t *table,
+  Mvf_Function_t *outMvf,
+  mdd_manager *mddMgr,
+  int offset,  
+  int outIndex,
+  array_t *varMap /* maps input column to mdd id */
+  )
+{
+  array_t *support;
+  Tbl_Table_t * newTable;
+  int i, inputId, rowNum, colNum, newColNum, newEqColNum, value, eqColNum;
+  Tbl_Entry_t *newEntry, *entry;
+  Var_Variable_t *var;
+  Tbl_Row_t *row UNUSED;
+  st_table *supLookup;
+
+  newTable = Tbl_TableAlloc();  
+  /* compute dependancies and put in a hash table */
+
+  if (outMvf != NIL(Mvf_Function_t)) {
+    support =
+        Mvf_FunctionComputeSupport(outMvf,mddMgr,&value);
+  }
+  else {
+    offset = array_n(mdd_ret_mvar_list(mddMgr));
+    support =
+        Tbl_TableComputeMvfAndInputDependenciesOfOutput(table,mddMgr,outIndex,&value);
+  }
+  
+  if(support == NIL(array_t)) {
+    /* create a constant table */
+    var = Tbl_TableReadIndexVar(table,outIndex,1);
+    Tbl_TableAddColumn(newTable,var,1);
+    i  = Tbl_TableAddRow(newTable);
+    newEntry = Tbl_EntryAlloc(Tbl_EntryNormal_c);
+    Tbl_TableSetEntry(newTable, newEntry, 0, 0, 1);
+    Tbl_TableAddEntryRange(newTable,0,0,value,value,1);
+    newEntry = NIL(Tbl_Entry_t);    
+    (void) Tbl_TableDefaultSetEntry(newTable,newEntry,0);
+    return newTable;
+  }
+
+  supLookup = st_init_table(st_numcmp, st_numhash);
+
+  arrayForEachItem(int, support, i, inputId) {
+    st_insert(supLookup,(char*)((long)(inputId - offset)),(char*)((long)i));
+  }
+  array_free(support);
+
+  /* Account for multiple columns mapping to the same MDD variable.
+   * There are two reasons why there may be fewer variables in the MVF
+   * than there are input columns in a table:
+   * 1. Multiple columns are tied to the same Var_Variable_t and hence
+   *    get the same MDD variable.
+   * 2. Variables that are in the apparent support of the table are not
+   *    in the true support of the MVF.
+   * The first reason is captured by varMap, the second by supLookup.
+   * Now we merge the two and replace supLookup with the resulting table.
+   */
+  if (varMap != NIL(array_t)) {
+    int mapped;
+    int nCol = 0;
+    Var_Ord_t *varArray = ALLOC(Var_Ord_t, array_n(varMap));
+    arrayForEachItem(int, varMap, i, mapped) {
+      int position;
+      if (st_lookup_int(supLookup, (char*)(long) mapped, &position) == 1) {
+	varArray[nCol].id = i;
+	varArray[nCol].rank = position;
+	nCol++;
+      }
+    }
+    qsort((void *)varArray, nCol, sizeof(Var_Ord_t), varCompare);
+    st_free_table(supLookup);
+    supLookup = st_init_table(st_numcmp, st_numhash);
+    for (i=0; i < nCol; i++) {
+      st_insert(supLookup, (char*)((long)varArray[i].id), (char*)((long)i));
+    }
+    FREE(varArray);
+  }
+
+  /* foreach input var check if in true support and then insert */
+  Tbl_TableForEachInputVar(table,i,var){
+    if (st_lookup_int(supLookup, (char*)(long) i, &newColNum) == 1) {
+      Tbl_TableAddColumn(newTable,var,0);
+    }
+  }
+
+  /* insert only specified output */
+  Tbl_TableForEachOutputVar(table,i,var){
+    if (i == outIndex) {    
+      Tbl_TableAddColumn(newTable,var,1);
+    }  
+  }
+
+  /* add rows to this table */
+
+  TblTableForEachRow(table, row, rowNum){
+    i = Tbl_TableAddRow(newTable);
+  }
+
+  for (rowNum =0; rowNum < Tbl_TableReadNumRows(table); rowNum++ ) {
+    for (colNum =0; colNum < Tbl_TableReadNumInputs(table); colNum++) {
+      if (st_lookup_int(supLookup, (char*)(long) colNum, &newColNum) == 1) {
+        entry = Tbl_TableReadEntry(table,rowNum, colNum, 0);
+        newEntry = Tbl_EntryDup(entry);              
+        if (Tbl_EntryIsEqual(entry)) {
+          eqColNum = Tbl_EntryReadVarIndex(entry);
+          if (st_lookup_int(supLookup,(char*)(long)eqColNum,&newEqColNum) == 0) {
+            fail("Entry Equal Var not in True Support\n");
+          }
+          else {
+            Tbl_EntrySetEqual(newEntry,newEqColNum);
+          }
+        }
+        Tbl_TableSetEntry(newTable, newEntry, rowNum, newColNum, 0);      
+      }
+    }
+  }
+
+
+  for (rowNum =0; rowNum < Tbl_TableReadNumRows(table); rowNum++ ) {
+    entry = Tbl_TableReadEntry(table,rowNum, outIndex, 1);
+    newEntry = Tbl_EntryDup(entry);
+    if (entry->type == Tbl_EntryEqual_c) {
+      eqColNum = Tbl_EntryReadVarIndex(entry);
+      if (st_lookup_int(supLookup,(char*)(long)eqColNum,&newEqColNum) == 0) {
+	fail("Entry Equal Var not in True Support\n");
+      }
+      else {
+	Tbl_EntrySetEqual(newEntry,newEqColNum);
+      }
+    }
+    Tbl_TableSetEntry(newTable, newEntry, rowNum, 0, 1);
+  }
+  st_free_table(supLookup);
+
+
+  Tbl_TableForEachDefaultEntry(table,entry,i) {
+    if (i==outIndex) {        
+      if (entry != NIL(Tbl_Entry_t)) {
+        if (entry->type != Tbl_EntryEqual_c) {
+          newEntry = Tbl_EntryDup(entry);
+        }
+        else{
+          eqColNum =
+	    Tbl_TableReadVarIndex(newTable,Tbl_EntryReadVar(table,entry),0);
+          if (eqColNum != -1) {
+	    newEntry = Tbl_EntryDup(entry);
+	    Tbl_EntrySetEqual(newEntry,eqColNum);
+	  }
+	  else {
+	    newEntry = NIL(Tbl_Entry_t);
+	  }
+        }
+      }
+      else {
+        newEntry = NIL(Tbl_Entry_t);
+      }
+      (void) Tbl_TableDefaultSetEntry(newTable,newEntry,0);
+    }
+  }
+
+  return newTable;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Swap rows i and j.  ]
+
+  Description [ This function swaps rows i and j and return true if
+  successful. It exits the program if data is incorrectly supplied.]
+
+  SideEffects [ ]
+
+  SeeAlso     [ optional ]
+
+******************************************************************************/
+boolean
+Tbl_TableSwapRows(
+  Tbl_Table_t *  table,
+  int  i,
+  int  j)
+{
+  Tbl_Row_t *rowi, *rowj;
+    
+  assert(table !=NIL(Tbl_Table_t));
+  if (TblTableReadRefCount(table) > 1) {
+    printf(" WARNING: You are modifying more than one table by swapping these rows\n");
+  }
+  
+  rowi = TblTableReadRow(table,i);
+  rowj = TblTableReadRow(table,j);
+  TblTableSetRow(table,rowi,j);
+  TblTableSetRow(table,rowj,i);
+
+  return TRUE;
+}
+  
+
+/**Function********************************************************************
+
+  Synopsis    [ Swap input/output columns i and j.  ]
+
+  Description [ This functions swaps columns i and j and return true if sucessfull.
+                It must also be supplied with a flag to indicate whether an input
+                or output entry is being read.]]
+
+  SideEffects [ ]
+
+  SeeAlso     [ optional ]
+
+******************************************************************************/
+boolean
+Tbl_TableSwapColumns(
+  Tbl_Table_t *  table,
+  int  i,
+  int  j,
+  int  flag)
+{
+  int k, rowNum,colNum,flag2;
+  Tbl_Row_t *row UNUSED;
+  Tbl_Entry_t *coli, *colj, *entry;
+  array_t *rowArray;
+  Var_Variable_t *vari, *varj;
+    
+  assert(table !=NIL(Tbl_Table_t));
+  assert((flag==0)||(flag ==1));
+  if (TblTableReadRefCount(table) > 1) {
+    printf(" WARNING: You are modifying more than one table by swapping rows\n");
+  }
+  
+  TblTableForEachRow(table,row,k) {
+    coli = Tbl_EntryDup(Tbl_TableReadEntry(table,k,i,flag));
+    colj = Tbl_EntryDup(Tbl_TableReadEntry(table,k,j,flag));    
+
+    Tbl_TableSetEntry(table,coli,k,j,flag);
+    Tbl_TableSetEntry(table,colj,k,i,flag);
+  }
+
+  if (flag == 0) {
+    rowArray = table->inputNames;
+  }
+  else {
+    rowArray = table->outputNames;
+  }
+
+  vari = array_fetch(Var_Variable_t*,rowArray,i);
+  varj = array_fetch(Var_Variable_t*,rowArray,j);
+  array_insert(Var_Variable_t*,rowArray,i,varj);
+  array_insert(Var_Variable_t*,rowArray,j,vari);
+
+  /* Correct Equal entries */
+  Tbl_TableForEachEntry(table,rowNum,colNum,flag2,entry) {
+    if (entry->type == Tbl_EntryEqual_c) {
+      if (Tbl_EntryReadVarIndex(entry)==i){
+        Tbl_EntrySetEqual(entry,j);
+      }
+      else if (Tbl_EntryReadVarIndex(entry)==j){
+        Tbl_EntrySetEqual(entry,i);
+      }      
+    }
+  }
+
+  
+  Tbl_TableForEachDefaultEntry(table,entry,colNum) {
+    if (entry != NIL(Tbl_Entry_t)) {
+    if (entry->type == Tbl_EntryEqual_c) {
+      if (Tbl_EntryReadVarIndex(entry)==i){
+        Tbl_EntrySetEqual(entry,j);
+      }
+      else if (Tbl_EntryReadVarIndex(entry)==j){
+        Tbl_EntrySetEqual(entry,i);
+      }      
+    }
+    }    
+    }
+  
+  return TRUE;
+}
+      
+/**Function******************************************************************
+
+   Synopsis    [ Semi-canonicalize a table]
+
+   Description [ Given a table (Tbl_Table_t), this function will return the
+   semi-canonical form of  the table by ordering the rows and columns.The canonicaliztion
+  process, assigns a linear order to the table rows an columns, based on the
+  value of their entries. For a table with binary valued entries, this value
+  is exactly the number of 1's in the row or column. Once this linear
+  order is assigned, the rows and columns of the table are swapped so as to
+  order rows and columns with higher value at the beginning of the
+  corresponding row or column order. It is called semi-canonicalization
+  because two tables representing the same logic function need not have the
+  same canonical form. ]
+
+   SideEffects [ The original table is destroyed. The user must duplicate a table
+   before canonicalizing, to preserve it.]
+
+   SeeAlso     [ ]
+
+****************************************************************************/
+void
+Tbl_TableCanonicalize(
+    Tbl_Table_t * table)
+{
+  int numRows, numInputs, numOutputs, rowNum, colNum;
+  array_t *rowValArray;
+  Tbl_Row_t *colVal;
+  int i, val1,val2;
+  
+
+  numRows = Tbl_TableReadNumRows(table);
+  numInputs = Tbl_TableReadNumInputs(table);
+  numOutputs = Tbl_TableReadNumOutputs(table);
+  
+  rowValArray = TableCreatIntArray(numRows);
+  colVal = ALLOC(Tbl_Row_t,1);
+  colVal->inputs= TableCreatIntArray(numInputs);
+  colVal->outputs= TableCreatIntArray(numOutputs);
+
+  for(i=0; i< numRows; i++) {
+    for(rowNum=0; rowNum< numRows-1; rowNum++) {
+      if (Tbl_TableRowDominatesRow(table,rowNum,rowNum+1,rowValArray)) {
+        Tbl_TableSwapRows(table,rowNum,rowNum+1);
+        val1 = array_fetch(int,rowValArray,rowNum);
+        val2 =array_fetch(int,rowValArray,rowNum+1);
+        array_insert(int,rowValArray,rowNum,val2);
+        array_insert(int,rowValArray,rowNum+1,val1);
+      }
+    }
+  }
+
+  for(i=0; i< numInputs; i++) {  
+    for(colNum=0; colNum< numInputs-1; colNum++) {
+      if (Tbl_TableColDominatesCol(table,colNum,colNum+1,0,colVal)) {
+        Tbl_TableSwapColumns(table,colNum,colNum+1,0);
+        val1 = array_fetch(int,TblRowReadInputs(colVal),colNum);
+        val2 = array_fetch(int,TblRowReadInputs(colVal),colNum+1);
+        array_insert(int,TblRowReadInputs(colVal),colNum,val2);
+        array_insert(int,TblRowReadInputs(colVal),colNum+1,val1);
+      }
+    }
+  }
+
+  for(i=0; i< numOutputs; i++) {  
+    for(colNum=0; colNum< numOutputs-1; colNum++) {
+      if (Tbl_TableColDominatesCol(table,colNum,colNum+1,1,colVal)) {
+        Tbl_TableSwapColumns(table,colNum,colNum+1,1);
+        val1 = array_fetch(int,TblRowReadOutputs(colVal),colNum);
+        val2 = array_fetch(int,TblRowReadOutputs(colVal),colNum+1);
+        array_insert(int,TblRowReadOutputs(colVal),colNum,val2);
+        array_insert(int,TblRowReadOutputs(colVal),colNum+1,val1);        
+      }
+    }
+  }
+  TblRowFree(colVal); 
+  array_free(rowValArray);
+}
+/**Function********************************************************************
+
+  Synopsis    [To determine if one row dominates another]
+
+  Description [Given a table and two row number rowa and rowb, this function
+  returns a TRUE if rowa dominates rowb and FALSE otherwise]
+
+  SideEffects []
+
+  SeeAlso     [Tbl_TableColDominatesCol]
+
+******************************************************************************/
+boolean
+Tbl_TableRowDominatesRow(
+  Tbl_Table_t *table,
+  int rowa,
+  int rowb,
+  array_t *rowValArray)  
+{
+  int valuea, valueb, totala, totalb;
+  Tbl_Entry_t *entrya, *entryb;
+  int colNum;
+
+  
+
+  valuea = array_fetch(int,rowValArray,rowa);
+  totala = valuea;
+  
+  if (valuea == -1) {
+    totala =0;    
+    Tbl_RowForEachInputEntry(table,rowa,entrya,colNum) {
+      valuea = TableEntryComputeHashVal(table,entrya);
+      totala = valuea + totala;      
+    }
+    Tbl_RowForEachOutputEntry(table,rowa,entrya,colNum) {
+      valuea = TableEntryComputeHashVal(table,entrya);
+      totala = valuea + totala;      
+    }        
+    array_insert(int, rowValArray,rowa,totala);
+  }
+
+  valueb = array_fetch(int,rowValArray,rowb);
+  totalb = valueb;
+  
+  if (valueb == -1) {
+    totalb =0;    
+    Tbl_RowForEachInputEntry(table,rowb,entryb,colNum) {
+      valueb = TableEntryComputeHashVal(table,entryb);
+      totalb = valueb + totalb;      
+    }
+    Tbl_RowForEachOutputEntry(table,rowb,entryb,colNum) {
+      valueb = TableEntryComputeHashVal(table,entryb);
+      totalb = valueb + totalb;      
+    }        
+    array_insert(int, rowValArray,rowb,totalb);
+  }  
+  
+  if (totala < totalb ) {
+    return FALSE;
+  }
+  else {
+    return TRUE;
+  }
+}  
+
+/**Function********************************************************************
+
+  Synopsis    [To determine if one Col dominates another]
+
+  Description [Given a table, two integers for column number cola colb, and a
+  flag set to 0 to indicate input and 1 for  output this function
+  returns a TRUE if Cola dominates Colb and FALSE otherwise]
+
+  SideEffects []
+
+  SeeAlso     [Tbl_TableRowDominatesRow]
+
+******************************************************************************/
+boolean
+Tbl_TableColDominatesCol(
+  Tbl_Table_t *table,
+  int cola,
+  int colb,
+  int flag,
+  Tbl_Row_t *colValArray)  
+{
+
+  int valuea, valueb, totala, totalb;
+  Tbl_Entry_t *entrya, *entryb;
+  int colNum, rowNum;
+  
+  if (flag == 0) {
+    valuea = array_fetch(int,TblRowReadInputs(colValArray),cola);
+  }
+  else {
+    valuea = array_fetch(int,TblRowReadOutputs(colValArray),cola);
+  }
+
+  totala = valuea;
+  if (valuea == -1) {
+  totala =0;
+    if (flag ==0) {
+      Tbl_TableForEachInputEntry(table,rowNum,colNum,entrya){
+        if (colNum == cola) {
+          valuea = TableEntryComputeHashVal(table,entrya);
+          totala = valuea + totala;      
+        }
+      }
+    array_insert(int, TblRowReadInputs(colValArray),cola,totala);      
+    }
+    else if (flag ==1) {
+      Tbl_TableForEachOutputEntry(table,rowNum,colNum,entrya){
+        if (colNum == cola) {    
+          valuea = TableEntryComputeHashVal(table,entrya);
+          totala = valuea + totala;      
+        }
+      }
+    array_insert(int, TblRowReadOutputs(colValArray),cola,totala);      
+    }
+  }
+
+  if (flag ==0) {
+    valueb = array_fetch(int,TblRowReadInputs(colValArray),colb);
+  }
+  else {
+    valueb = array_fetch(int,TblRowReadOutputs(colValArray),colb);
+  }
+  
+  totalb = valueb;  
+  if (valueb == -1) {
+  totalb =0;  
+    if (flag ==0) {
+      Tbl_TableForEachInputEntry(table,rowNum,colNum,entryb){
+        if (colNum == colb) {
+          valueb = TableEntryComputeHashVal(table,entryb);
+          totalb = valueb + totalb;      
+        }
+      }
+    array_insert(int, TblRowReadInputs(colValArray),colb,totalb);      
+    }
+    else if (flag ==1) {
+      Tbl_TableForEachOutputEntry(table,rowNum,colNum,entryb){
+        if (colNum == colb) {    
+          valuea = TableEntryComputeHashVal(table,entryb);
+          totalb = valueb + totalb;      
+        }
+      }
+    array_insert(int, TblRowReadOutputs(colValArray),colb,totalb);      
+    }
+  }
+  
+  if (totala < totalb ) {
+    return FALSE;
+  }
+  else {
+    return TRUE;
+  }
+}
+
+/**Function******************************************************************
+
+   Synopsis    [ Compare two tables.]
+
+   Description [ Given two Tbl_Table_t's tablea and tableb, this function will
+   compare the two tables to determine if they are the same. It returns a TRUE
+   if they are and a FALSE if not.]
+
+   SideEffects [ ]
+
+   SeeAlso     [ ]
+
+****************************************************************************/
+boolean
+Tbl_TablesAreIdentical(
+    Tbl_Table_t *tablea,
+    Tbl_Table_t *tableb,
+    int a,
+    int b)
+{
+  char *signaturea;
+  char *signatureb;
+
+  signaturea = TableObtainSignature(tablea, a);
+  signatureb = TableObtainSignature(tableb, b);  
+  if (strcmp(signaturea, signatureb) == 0) {
+    FREE(signaturea);
+    FREE(signatureb);    
+    return TRUE;
+  }
+  FREE(signaturea);
+  FREE(signatureb);    
+  return FALSE;
+}
+
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Returns an mdd for a table row  ]
+
+  Description [ Given a row id i, a table, an mdd manager and an array of arrays
+  of mdd_t*, this function returns the mdd for the corresponding row.
+  The array of arrays of mdd_t* gives the onsets for different values of the
+  multivalued var of each column.]
+
+  SideEffects [ ]
+
+  SeeAlso     [ ]
+
+******************************************************************************/
+mdd_t *
+Tbl_TableRowToMdd(
+  Tbl_Table_t *  table,
+  mdd_manager *  manager,
+  int  i,
+  array_t *  svArray /* array of array of mdd_t to be used */)
+{
+  mdd_t *result, *finalResult, *temp;
+  int j,k;
+  Tbl_Entry_t *entry;
+  Mvf_Function_t *mvf1, *mvf2;
+    
+
+  result = NIL(mdd_t);
+  finalResult = mdd_one(manager);
+    
+  Tbl_RowForEachInputEntry(table,i,entry,j) {
+    if ((entry->type) == Tbl_EntryNormal_c) {
+      mvf1 = array_fetch(Mvf_Function_t*,svArray,j);
+      result = TblEntryNormalConstructMdd(manager,entry,mvf1);
+    }
+    else if ((entry->type == Tbl_EntryEqual_c)) {
+      k = Tbl_EntryReadVarIndex(entry);
+      mvf1 = array_fetch(Mvf_Function_t*,svArray,j);
+      mvf2 = array_fetch(Mvf_Function_t*,svArray,k);
+      result = Mvf_FunctionsComputeEquivalentSet(mvf1,mvf2);
+    }
+    else if (entry->type == Tbl_EntryUnassigned_c) {
+      return NIL(mdd_t);
+    }
+        
+    temp = finalResult;
+    finalResult = mdd_and(temp,result,1,1);
+    mdd_free(temp);
+    mdd_free(result);
+  }
+    
+  Tbl_RowForEachOutputEntry(table,i,entry,j) {
+    if ((entry->type) == Tbl_EntryNormal_c) {
+      mvf1 = array_fetch(Mvf_Function_t*,svArray,j);
+      result = TblEntryNormalConstructMdd(manager,entry,mvf1);
+    }
+    else if ((entry->type == Tbl_EntryEqual_c)) {
+      k = Tbl_EntryReadVarIndex(entry);
+      mvf1 = array_fetch(Mvf_Function_t*,svArray,j);
+      mvf2 = array_fetch(Mvf_Function_t*,svArray,k);
+      result = Mvf_FunctionsComputeEquivalentSet(mvf1,mvf2);
+    }
+    else if (entry->type == Tbl_EntryUnassigned_c) {
+      return NIL(mdd_t);
+    }
+    
+    temp = finalResult;
+    finalResult = mdd_and(temp,result,1,1);
+    mdd_free(temp);
+    mdd_free(result);
+  }
+  return finalResult;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compute the Mvf_Function_t for a non-deterministic constant.]
+
+  Description [Given a Tbl_Table_t, an integer for the  table output value
+  index, an integer MddId, and an mdd Manager, this function builds the
+  Mvf_Function_t associated with the output. The table cannot have
+  any inputs; the function fails if it does. The output cannot be equal to
+  another output, because this would make the table a relation, and that is
+  not permissible. If this occurs, the function will fail on an assert
+  statement.]
+
+  SideEffects [ Table must have no inputs.]
+
+  SeeAlso     []
+
+******************************************************************************/
+Mvf_Function_t *
+Tbl_TableBuildNonDetConstantMvf(
+  Tbl_Table_t * table,
+  int outIndex,
+  int mddId,
+  mdd_manager *  mddMgr)
+{
+
+  lsGen gen;
+  Tbl_Entry_t *entry;
+  Tbl_Range_t *range;
+  int value, rowNum, colNum;
+  mdd_t *x;
+  Mvf_Function_t *function;
+  
+  assert(Tbl_TableReadNumInputs(table) ==0);
+
+  value = Var_VariableReadNumValues(Tbl_TableReadIndexVar(table,outIndex,1));
+  function = Mvf_FunctionAlloc(mddMgr,value);
+  
+  Tbl_TableForEachOutputEntry(table,rowNum,colNum,entry) {
+    if (colNum == outIndex) {
+      assert(entry->type == Tbl_EntryNormal_c);
+      Tbl_EntryForEachValue(entry,value,gen,range) {
+        x = mdd_eq_c(mddMgr,mddId,value);
+        Mvf_FunctionAddMintermsToComponent(function, value,x);
+        mdd_free(x);
+      }
+    }
+  }
+  return function;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Compute the Mvf_Function_t for a table output in terms of fanins]
+
+  Description [Given a Tbl_Table_t, an integer for the  table output value
+  index, an array of fanin mdd_t* , and an mdd Manager, this function builds the
+  Mvf_Function_t associated with the output. The output cannot be equal to
+  another output, because this would make the table a relation, and that is
+  not permissible.  For each row, the function will build the mdd_t for the inputs
+  using their Mvf_Function_t's and AND them together. If the input is of the
+  type equal, it will build the equivalent set Mdd (see See Also) and AND it in.]
+
+  SideEffects [ ]
+
+  SeeAlso     [ Mvf_FunctionComputeEquivalentSet, TblEntryNormalConstructMdd]
+
+******************************************************************************/
+Mvf_Function_t *
+Tbl_TableBuildMvfFromFanins(
+  Tbl_Table_t * table,
+  int outIndex,
+  array_t * faninArray,
+  mdd_manager *  mddMgr)
+{
+
+  lsGen gen;
+  Tbl_Entry_t *entry, *entry2,*inputEntry;
+  Tbl_Range_t *range;
+  int value, rowNum, colNum, rowColNum, i;
+  mdd_t *x, *result, *temp;
+  Mvf_Function_t *function, *mvf1, *mvf2;
+  
+
+  x = NIL(mdd_t);
+  value = Var_VariableReadNumValues(Tbl_TableReadIndexVar(table,outIndex,1));
+  function = Mvf_FunctionAlloc(mddMgr,value);
+  
+  Tbl_TableForEachOutputEntry(table,rowNum,colNum,entry) {
+    if (colNum == outIndex) {
+      if (entry->type == Tbl_EntryNormal_c) {
+        result = mdd_one(mddMgr);
+        Tbl_RowForEachInputEntry(table,rowNum,inputEntry,rowColNum) {
+          if (inputEntry->type == Tbl_EntryNormal_c) {
+            mvf1 = array_fetch(Mvf_Function_t*,faninArray,rowColNum);
+            x = TblEntryNormalConstructMdd(mddMgr,inputEntry,mvf1);
+          }
+          else if (inputEntry->type == Tbl_EntryEqual_c) {
+            value =Tbl_EntryReadVarIndex(inputEntry);
+            mvf1 = array_fetch(Mvf_Function_t*,faninArray,rowColNum);
+            mvf2 = array_fetch(Mvf_Function_t*,faninArray,value);
+            x = Mvf_FunctionsComputeEquivalentSet(mvf1,mvf2);
+          }
+          temp = result;
+          result = mdd_and(x,temp,1,1);
+          mdd_free(temp);
+          mdd_free(x);
+        }
+        Tbl_EntryForEachValue(entry,value,gen,range) {  
+          Mvf_FunctionAddMintermsToComponent(function, value,result);
+        }
+        mdd_free(result);
+      }
+      else  if (entry->type == Tbl_EntryEqual_c) {
+        value = Tbl_EntryReadVarIndex(entry);
+        if (value == -1) {
+        fail("Failure: Not equal to any input var in this table\n");
+        }
+        
+          
+        /* must be equal to an input */
+        
+        entry2 = Tbl_TableReadEntry(table,rowNum,value,0);
+        result = mdd_one(mddMgr);
+        Tbl_RowForEachInputEntry(table,rowNum,inputEntry,rowColNum) {
+          if (inputEntry->type == Tbl_EntryNormal_c) {
+            mvf1 = array_fetch(Mvf_Function_t*,faninArray,rowColNum);
+            x = TblEntryNormalConstructMdd(mddMgr,inputEntry,mvf1);
+          }
+          else if (inputEntry->type == Tbl_EntryEqual_c) {
+            value =Tbl_EntryReadVarIndex(inputEntry);
+            mvf1 = array_fetch(Mvf_Function_t*,faninArray,rowColNum);
+            mvf2 = array_fetch(Mvf_Function_t*,faninArray,value);
+            x = Mvf_FunctionsComputeEquivalentSet(mvf1,mvf2);
+          }
+          temp = result;
+          result = mdd_and(x,temp,1,1);
+          mdd_free(temp);
+          mdd_free(x);
+        }
+
+        rowColNum = Tbl_EntryReadVarIndex(entry);
+        mvf1 = array_fetch(Mvf_Function_t*,faninArray,rowColNum);        
+        value = Var_VariableReadNumValues(Tbl_EntryReadActualVar(table,entry2));
+        temp = result;
+
+        for(i=0; i< value; i++) {
+          x = Mvf_FunctionReadComponent(mvf1,i);
+          result = mdd_and(temp,x,1,1);
+          Mvf_FunctionAddMintermsToComponent(function, i,result);
+          mdd_free(result);
+        }
+        mdd_free(temp);
+      }  
+    }
+  }
+
+  /* accounting for the defaults */
+  entry = Tbl_TableDefaultReadEntry(table,outIndex);
+  if (entry != NIL(Tbl_Entry_t)) {  
+    temp = Mvf_FunctionComputeDomain(function);
+    result = mdd_not(temp);
+    mdd_free(temp);
+
+    if (entry->type == Tbl_EntryNormal_c) {    
+      Tbl_EntryForEachValue(entry,value,gen,range) {
+        Mvf_FunctionAddMintermsToComponent(function, value,result);
+      }
+    }
+    else {
+      value = Tbl_EntryReadVarIndex(entry);
+      if (value == -1) {
+        fail("Failure: Not equal to any input var in this table\n");
+      }
+      mvf1 = array_fetch(Mvf_Function_t*,faninArray,value);
+      
+      Mvf_FunctionForEachComponent(mvf1,i,x) {
+        temp = mdd_and(x,result,1,1);
+        Mvf_FunctionAddMintermsToComponent(function, i ,temp);
+        mdd_free(temp);
+      }
+    }
+    
+    mdd_free(result);    
+  }
+        
+  return function;  
+}
+
+  
+        
+/**Function********************************************************************
+
+  Synopsis    [ Return the constant value associated with an output]
+
+  Description [ Given a table that has no inputs and an output column index,
+  this function returns the constant value associated with the output. It returns
+  a -1 if the value is not a constant. Note that this test is conservative, because it
+  does not take into account Boolean redundancies. It merely checks for one of
+  the following conditions 1) the table has no inputs and a constant output 2)
+  the table has only - inputs in the one row and the output is constant
+  3) the table is empty and the default value for the output is constant and
+  4) the table output has the same constant value for all inputs]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Tbl_TableReadConstValue(
+  Tbl_Table_t * table,
+  int outputColumnId)
+{
+  int colNum, rowNum;
+  boolean check;
+  Tbl_Entry_t *entry;
+  Var_Variable_t *var;
+  Tbl_Range_t *range;
+  lsGen gen;
+  int value, constant,count;
+  
+
+  constant = -1;
+  assert(table !=NIL(Tbl_Table_t));
+  assert((outputColumnId >= 0) && (outputColumnId <
+                                   Tbl_TableReadNumOutputs(table)));
+
+  if (Tbl_TableReadNumRows(table) == 1) {  
+    if (array_n(table->inputNames) == 0) {
+      entry = Tbl_TableReadEntry(table, 0, outputColumnId, 1);
+      if (entry->type == Tbl_EntryNormal_c) {
+        if (Tbl_EntryReadNumValues(entry) == 1) {
+          Tbl_EntryForEachValue(entry,value,gen,range) {
+            constant = value;
+          }
+          return constant;
+        }
+      }
+    }
+    else {
+      check = TRUE;
+      Tbl_TableForEachInputEntry(table,rowNum,colNum,entry) {
+        if (entry->type != Tbl_EntryNormal_c) {
+          return -1;
+        }
+        if (check == TRUE) {
+          check = -1;
+          if (lsLength(entry->EntryData.listOfRanges) == 1){
+            var = Tbl_EntryReadActualVar(table,entry);
+            lsForEachItem(entry->EntryData.listOfRanges, gen, range) {
+              if ((range->begin ==0)&&(range->end ==
+                                       Var_VariableReadNumValues(var)-1)){
+                check = TRUE;
+              }
+            }
+          }
+        }
+      }
+      
+      if (check) {
+        entry = Tbl_TableReadEntry(table,0,outputColumnId,1);
+        if (entry->type != Tbl_EntryNormal_c) {
+          return -1;
+        }            
+        if (Tbl_EntryReadNumValues(entry) == 1) {
+          Tbl_EntryForEachValue(entry,value,gen,range) {
+            constant = value;
+          }
+          return constant;
+        }
+      }
+    }
+  }
+  else if (Tbl_TableReadNumRows(table) == 0) {
+    entry = Tbl_TableDefaultReadEntry(table,outputColumnId);
+    if (entry->type != Tbl_EntryNormal_c) {
+      return -1;
+    }    
+    if (Tbl_EntryReadNumValues(entry) == 1) {
+      Tbl_EntryForEachValue(entry,value,gen,range) {
+        constant = value;
+      }
+      return constant;      
+    }
+  }
+  else {
+    entry = Tbl_TableDefaultReadEntry(table,outputColumnId);    
+    if (entry == NIL(Tbl_Entry_t)){
+      constant = -1;
+      Tbl_TableForEachOutputEntry(table,rowNum,colNum,entry) {
+        if (colNum == outputColumnId) {
+          count = 1;
+        if (entry->type != Tbl_EntryNormal_c){
+          return -1;
+        }          
+          Tbl_EntryForEachValue(entry,value,gen,range) {
+            lsStatus status;
+            if (count > 1) {
+              status = lsFinish(gen); 
+              assert(status == LS_OK);
+              return -1;
+            }
+            else {
+              if (constant != -1) {
+                if (constant != value) {
+                  status = lsFinish(gen); 
+                  assert(status == LS_OK); 
+                  return -1;
+                }
+              }
+              else {
+                constant = value;
+              }
+            }
+            count ++;        
+          }
+        }
+      }
+      return constant;
+    }
+  }
+  
+  return -1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Returns a table for an mdd ]
+
+  Description [ ]
+
+  SideEffects [ ]
+
+  SeeAlso     [ ]
+
+******************************************************************************/
+Tbl_Table_t *
+Tbl_MddToTable(
+  mdd_t *  mdd,
+  mdd_manager *  manager,
+  st_table *  idtoVar,
+  array_t * inputids)
+{
+/**Fix*******Gitanjali***********************************************************/
+  /* use foreach cube */
+  printf("Not implemented as yet, contact gms@ic\n");
+  return NIL(Tbl_Table_t);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [ Substitute the oldVar with the newVar. 
+                Return TRUE if successful.  ]
+
+  Description [ Given a table and Var_variable_t's oldVar and newVar, it replaces
+  the oldVar with the newVar in the table. It returns true if sucessful and false
+  otherwise.]
+
+  SideEffects [ The oldVar is not freed, it is the user's responsibility ]
+
+  SeeAlso     [ ]
+
+******************************************************************************/
+boolean
+Tbl_TableSubstituteVar(
+  Tbl_Table_t *  table,
+  Var_Variable_t *  oldVar,
+  Var_Variable_t *  newVar)
+{
+  int i,k;
+  int flag;
+  Var_Variable_t *var;
+
+
+  k = -1;
+  flag =0;
+  var = NIL(Var_Variable_t);
+
+  if (!Var_VariablesTestHaveSameDomain(oldVar,newVar)) return FALSE;
+
+  if (table != NIL(Tbl_Table_t)) {
+    Tbl_TableForEachInputVar(table,i,var) {
+      if (var == oldVar) {
+        k = i;
+        i = Tbl_TableReadNumInputs(table);
+        flag = 0;
+      }
+    }
+    if (k == -1) {
+      Tbl_TableForEachOutputVar(table,i,var) {
+        if (var == oldVar) {
+          k = i;
+          i = Tbl_TableReadNumOutputs(table);
+          flag = 1;
+        }
+      }
+    }
+    if (k != -1) {
+      Tbl_TableSetVar(table,k,newVar,flag);
+      /* traverse all the entries of the table and change all the references
+      to the old variable in the equal-to construct to the new variable */
+      /* The above no longer has to be done as the entry refers to an
+         index rather than the var */
+      return TRUE;
+    }
+    else {
+      return FALSE;
+    }
+  }
+  return FALSE;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Set the var in given column to given var]
+
+  Description [Given a table, an index and a new var for the index, this
+  function sets the var in the table ]
+
+  SideEffects [The previously set var is lost]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Tbl_TableSetVar(
+  Tbl_Table_t * table,
+  int i,
+  Var_Variable_t * sv,
+  int flag)
+{
+  array_t *svarray;
+  
+  if (flag==0){
+    svarray = Tbl_TableReadInputVars(table);
+  }
+  else {
+    svarray = Tbl_TableReadOutputVars(table);
+  }
+  
+  array_insert(Var_Variable_t*,svarray,i,sv);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Split a multi-output table into a set of single output tables.  ]
+
+  Description [ Given a deterministic multi-output table this function splits
+  it into an array of single-output tables.]
+
+  SideEffects [ Determinism is required for this to be sucessful.
+                The user is responsible for freeing the original table]
+
+  SeeAlso     [ ]
+
+******************************************************************************/
+array_t *
+Tbl_TableSplit(
+  Tbl_Table_t *  table)
+{
+  int i,j, rowNum, colNum;
+  array_t *resArray;
+  Tbl_Table_t *newtable;
+  Var_Variable_t *output, *input;
+  Tbl_Entry_t *entry, *newEntry;
+    
+
+  resArray = array_alloc(Tbl_Table_t*,0);
+    
+  Tbl_TableForEachOutputVar(table,i,output) {
+    newtable = Tbl_TableAlloc();
+    Tbl_TableAddColumn(newtable,output,1);
+    Tbl_TableForEachInputVar(table,colNum,input) {
+      Tbl_TableAddColumn(newtable,input,0);
+    }
+    for (rowNum =0; rowNum < Tbl_TableReadNumRows(table); rowNum++) {
+      (void) Tbl_TableAddRow(newtable);
+    }
+    
+    Tbl_TableForEachEntry(table,rowNum,colNum,j,entry) {
+      if (j==0) {
+        newEntry = Tbl_EntryDup(entry);
+        Tbl_TableSetEntry(newtable,newEntry,rowNum,colNum,0);
+      }
+      else {
+        if (colNum ==i) {
+          newEntry = Tbl_EntryDup(entry);
+          Tbl_TableSetEntry(newtable,newEntry,rowNum,0,1);
+        }
+      }
+    }
+    entry = Tbl_TableDefaultReadEntry(table,i);
+    if (entry != NIL(Tbl_Entry_t)) {
+      newEntry = Tbl_EntryDup(entry);
+      Tbl_TableDefaultSetEntry(newtable,newEntry,0);
+    }
+    
+    array_insert_last(Tbl_Table_t*,resArray,newtable);
+  }
+  return resArray;
+}
+  
+
+/**Function********************************************************************
+
+  Synopsis    [ Return the number of inputs.  ]
+
+  Description [ ]
+
+  SideEffects [ ]
+
+  SeeAlso     [ ]
+
+******************************************************************************/
+int 
+Tbl_TableReadNumInputs(
+    Tbl_Table_t * table)
+{
+  return(array_n(table->inputNames));
+    
+}
+  
+
+/**Function********************************************************************
+
+  Synopsis    [ Return the number of outputs.  ]
+
+  Description [ ]
+
+  SideEffects [ ]
+
+  SeeAlso     [ ]
+
+******************************************************************************/
+int
+Tbl_TableReadNumOutputs(
+  Tbl_Table_t *  table)
+{
+  return(array_n(table->outputNames));
+}
+  
+/**Function********************************************************************
+
+  Synopsis    [return the number of input/output Vars]
+
+  Description [Given a table and a flag set to 0 for input and 1 for output
+  this function returns the number of inputs or outputs.]
+
+  SideEffects []
+
+  SeeAlso     [Tbl_TableReadNumInputs Tbl_TableReadNumOutputs]
+
+******************************************************************************/
+int
+Tbl_TableReadNumVars(
+  Tbl_Table_t *table,
+  int flag)
+{
+  if (flag==0) {
+    return Tbl_TableReadNumInputs(table);
+  }
+  else {
+    return Tbl_TableReadNumOutputs(table);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [ Return the number of rows.  ]
+
+  Description [ ]
+
+  SideEffects [ ]
+
+  SeeAlso     [ ]
+
+******************************************************************************/
+int
+Tbl_TableReadNumRows(
+  Tbl_Table_t *  table)
+{
+  return(array_n(TblTableReadData(table)));
+}
+  
+/**Function***********************************************************
+
+  Synopsis	[ Find the index of the variable (column) associated
+                 with the given Var. ]
+
+  Description	[ Given a Var_Variable_t, this functions returns the
+                  index of the column that is represented by. The function 
+                  returns -1 if the var does not belong to the table.
+                  It must also be supplied with a flag to indicate whether
+                  an input or output entry is being read.]
+
+  SideEffects	[  ]
+
+  SeeAlso	[ optional ]
+**********************************************************************/
+int
+Tbl_TableReadVarIndex(
+  Tbl_Table_t *  table,
+  Var_Variable_t *  var,
+  int  flag /* Set to 0 if it is an input Var and 1 if it an output Var */
+)
+{
+  int i;
+  array_t *carray;
+  Var_Variable_t *aVar;
+
+  assert(table !=NIL(Tbl_Table_t));
+  assert((flag==0)||(flag ==1));  
+  
+  if (flag==0) {
+    carray = table->inputNames; 
+  }
+  else {
+    carray = table->outputNames; 
+  }
+            
+  for (i=0; i< array_n(carray);i++) {
+    aVar = array_fetch(Var_Variable_t*,carray,i);
+    if (var==aVar) {
+      return i;
+    }
+  }
+  return -1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Print table statistics]
+
+  Description [ Prints the following information to the file: number of input
+  columns, number of output columns, number of rows, name and cardinality of
+  domain, of each input column, name and cardinality of domain, of each
+  output, percentage of mxn entries with non-DC information (gives measure of
+  sparsity)]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Tbl_TablePrintStats(
+  Tbl_Table_t *table,
+    FILE *fp)
+{
+  int rowNum, colNum,i,dc, total;
+  Tbl_Entry_t *entry;
+  Var_Variable_t *var;
+  lsGen gen;
+  Tbl_Range_t *range;
+
+  fprintf(fp,"Table Stats\n");   
+  fprintf(fp,"Number of  Inputs           = %d\n",Tbl_TableReadNumInputs(table));
+  
+  fprintf(fp,"Inputs                      :"); 
+  Tbl_TableForEachInputVar(table,colNum,var){
+    fprintf(fp,"%s ",Var_VariableReadName(var));
+  }
+  fprintf(fp,"\n");
+  fprintf(fp,"Values                      :");
+  
+  Tbl_TableForEachInputVar(table,colNum,var){
+    fprintf(fp,"%d ",Var_VariableReadNumValues(var));
+  }
+  fprintf(fp,"\n");  
+  
+  fprintf(fp,"Number of  Outputs          = %d\n",Tbl_TableReadNumOutputs(table));
+  
+  fprintf(fp,"Outputs                     :");
+  
+  Tbl_TableForEachOutputVar(table,colNum,var){
+    fprintf(fp,"%s ",Var_VariableReadName(var));
+  }
+  fprintf(fp,"\n");
+  fprintf(fp,"Values                      :");
+  Tbl_TableForEachOutputVar(table,colNum,var){
+    fprintf(fp,"%d ",Var_VariableReadNumValues(var));
+  }
+  fprintf(fp,"\n");    
+  fprintf(fp,"Number of  Rows             = %d\n",Tbl_TableReadNumRows(table));
+
+  dc = 0;
+  total =0;
+  Tbl_TableForEachEntry(table,rowNum,colNum,i,entry) {
+    total++;
+    if(entry->type == Tbl_EntryNormal_c) {    
+      if (lsLength(entry->EntryData.listOfRanges) == 1){
+        var = Tbl_EntryReadActualVar(table,entry);
+        lsForEachItem(entry->EntryData.listOfRanges, gen, range) {
+          if ((range->begin ==0)&&(range->end == Var_VariableReadNumValues(var)-1)){
+            dc++;
+          }
+        }
+      }
+    }
+  }
+  if (total > 0) {
+    i = 100 *dc/total;
+  }
+  else {
+    i = 0;
+  }
+  
+  fprintf(fp,"# Don't Care entries        = %d\n",dc);
+  fprintf(fp,"Percent Don't Care entries  = %d\n",i);    
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Print table to file specified by fp in blif mv format. Appends 
+               the chars "_bufin" to the end of the output variables.]
+
+  Description [Given a table and file ptr, this function will print this table
+  in blif_mv form to a file specified by the ptr. If stdout is specified this
+  table will print it to stdout.It must also be supplied with a
+  flag to indicate the nature of the table. If this flag is a 0, it indicates
+  that the table is of the type .table if it is a 1, then it indicates that
+  the table is of the type .reset.]
+
+  SideEffects []
+
+  SeeAlso     [TblEntryPrint TblEntryWriteBlif Tbl_TablePrintl]
+
+******************************************************************************/
+void
+Tbl_TableWriteBlifMvToFileSpecial(
+    Tbl_Table_t *table,
+    int flag,
+    FILE *fp)
+{
+  int rowNum, colNum,i;
+  Tbl_Entry_t *entry;
+  Var_Variable_t *var;
+    
+
+  if (flag ==0) {
+    fprintf(fp,".table "); 
+  }
+  else {
+    fprintf(fp,".reset ");
+  }
+    
+  Tbl_TableForEachInputVar(table,colNum,var){
+    fprintf(fp,"%s ",Var_VariableReadName(var));
+  }
+  fprintf(fp,"->"); 
+  Tbl_TableForEachOutputVar(table,colNum,var){
+    fprintf(fp,"%s_bufin ",Var_VariableReadName(var));
+  }
+  fprintf(fp,"\n");
+
+  if ((array_fetch(Tbl_Entry_t*, TblTableReadDefaults(table),0)) != NIL(Tbl_Entry_t)) {
+    fprintf(fp,".default ");
+    Tbl_TableForEachDefaultEntry(table,entry,colNum) {
+      TblEntryWriteBlifMv(table,entry,fp);
+      fprintf(fp," ");
+    }
+    fprintf(fp,"\n");
+  }
+
+   Tbl_TableForEachEntry(table, rowNum,colNum,i,entry) { 
+    TblEntryWriteBlifMv(table,entry,fp);
+    fprintf(fp," ");    
+    if ((colNum == (Tbl_TableReadNumOutputs(table) -1))&&(i==1)) {
+      fprintf(fp,"\n");
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Print table to file specified by fp in blif-mv format]
+
+  Description [Given a table and file ptr, this function will print this table
+  in blif_mv form to a file specified by the ptr. If stdout is specified this
+  table will print it to stdout. It must also be supplied with a
+  flag to indicate the nature of the table. If this flag is a 0, it indicates
+  that the table is of the type .table.  If it is a 1, then it indicates that
+  the table is of the type .reset.  Finally, if flag is 2, the table should
+  be printed without header.]
+
+  SideEffects []
+
+  SeeAlso     [TblEntryPrint TblEntryWriteBlif Tbl_TablePrintl]
+
+******************************************************************************/
+void
+Tbl_TableWriteBlifMvToFile(
+    Tbl_Table_t *table,
+    int flag,
+    FILE *fp)
+{
+  int rowNum, colNum,i;
+  Tbl_Entry_t *entry;
+  Var_Variable_t *var;
+    
+
+  if (flag == 0) {
+    fprintf(fp,".table "); 
+  }
+  else if (flag == 1) {
+    fprintf(fp,".reset ");
+  }
+
+  if (flag < 2) {
+    Tbl_TableForEachInputVar(table,colNum,var){
+      fprintf(fp,"%s ",Var_VariableReadName(var));
+    }
+    fprintf(fp,"->"); 
+    Tbl_TableForEachOutputVar(table,colNum,var){
+      fprintf(fp," %s",Var_VariableReadName(var));
+    }
+    fprintf(fp,"\n");
+  }
+
+  if ((array_fetch(Tbl_Entry_t*, TblTableReadDefaults(table),0)) != NIL(Tbl_Entry_t)) {
+    fprintf(fp,".default");
+    Tbl_TableForEachDefaultEntry(table,entry,colNum) {
+      fprintf(fp," ");
+      TblEntryWriteBlifMv(table,entry,fp);
+    }
+    fprintf(fp,"\n");
+  }
+
+   Tbl_TableForEachEntry(table,rowNum,colNum,i,entry) { 
+    TblEntryWriteBlifMv(table,entry,fp);
+    if ((colNum == (Tbl_TableReadNumOutputs(table) -1))&&(i==1)) {
+      fprintf(fp,"\n");
+    } else {
+      fprintf(fp," ");    
+    }
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Print table to file specified by fp in smv format]
+
+  Description [Given a table and file ptr, this function will print
+  this table in smv form to a file specified by the ptr. If stdout is
+  specified this table will print it to stdout.It must also be
+  supplied with a flag to indicate the nature of the table. If this
+  flag is a 0, it indicates that the table is of the type .table if it
+  is a 1, then it indicates that the table is of the type .reset.]
+
+  SideEffects []
+
+  SeeAlso     [TblEntryPrint TblEntryWriteBlif Tbl_TablePrintl]
+
+******************************************************************************/
+void
+Tbl_TableWriteSmvToFile(
+    Tbl_Table_t *table,
+    int flag,
+    FILE *fp)
+{
+  int rowNum, colNum,i;
+  Tbl_Entry_t *entry;
+  Var_Variable_t *var;
+
+  if (flag ==0) { 
+    fprintf(fp,"\n-- Table for ");
+  }
+  else {
+    fprintf(fp,"\n-- Reset table for ");
+  }
+  Tbl_TableForEachInputVar(table,colNum,var){
+    fprintf(fp,"%s ",Var_VariableReadName(var));
+  }
+  fprintf(fp,"->"); 
+  Tbl_TableForEachOutputVar(table,colNum,var){
+    fprintf(fp,"%s ",Var_VariableReadName(var));
+  }
+  fprintf(fp,"\n");
+
+  if (flag ==0) { 
+
+    fprintf(fp, "INVAR\n( ");
+
+    Tbl_TableForEachEntry(table, rowNum,colNum,i,entry) { 
+      TblEntryWriteSmv(table,entry,0,fp);
+      if ((colNum == (Tbl_TableReadNumOutputs(table) -1))&&(i==1)) {
+	if(rowNum < Tbl_TableReadNumRows(table) -1) {
+	    fprintf(fp,") |\n( ");
+	}
+      } else {
+	fprintf(fp,"& ");    
+      }
+    }
+    
+    if ((array_fetch(Tbl_Entry_t*, TblTableReadDefaults(table),0)) != NIL(Tbl_Entry_t)) {
+      fprintf(fp,") |\n( ");
+   
+      if (Tbl_TableReadNumInputs(table) > 0) {
+	fprintf(fp,"!( (");
+      }
+      Tbl_TableForEachInputEntry(table, rowNum,colNum,entry) { 
+	TblEntryWriteSmv(table,entry,0,fp);
+	if (colNum == (Tbl_TableReadNumInputs(table) -1)) {
+	  if(rowNum < Tbl_TableReadNumRows(table) -1) {
+	    fprintf(fp,") | ( ");
+	  }
+	} else {
+	  fprintf(fp,"& ");    
+	}
+      }
+      if (Tbl_TableReadNumInputs(table) > 0) {
+	fprintf(fp,") ) & ");
+      }
+      
+      Tbl_TableForEachDefaultEntry(table,entry,colNum) {
+	TblEntryWriteSmv(table,entry,0,fp);
+	if (colNum < (Tbl_TableReadNumOutputs(table) -1)) {
+	  fprintf(fp,"& ");    
+	}
+      }
+    }
+    fprintf(fp,")\n");
+
+  } else {
+
+    fprintf(fp,"case\n");
+
+    Tbl_TableForEachEntry(table, rowNum,colNum,i,entry) { 
+      TblEntryWriteSmv(table,entry,i,fp);
+      if ((colNum == (Tbl_TableReadNumInputs(table) -1))&&(i==0)) {
+	fprintf(fp,": ");
+      } else if ((colNum == (Tbl_TableReadNumOutputs(table) -1))&&(i==1)) {
+	fprintf(fp,";\n");    
+      } else {
+	fprintf(fp,"& ");    
+      }
+    }
+    
+    if ((array_fetch(Tbl_Entry_t*, TblTableReadDefaults(table),0)) != NIL(Tbl_Entry_t)) {
+      fprintf(fp,"1 : ");
+      
+      Tbl_TableForEachDefaultEntry(table,entry,colNum) {
+	TblEntryWriteSmv(table,entry,1,fp);
+      }
+      fprintf(fp,";\n");
+    }
+
+    fprintf(fp,"esac;\n");
+  }
+    
+}
+
+ 
+
+/**Function********************************************************************
+
+  Synopsis    [Writes out a table to a named blif file]
+
+  Description [Writes out blif files corresponding to the table given.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Tbl_TableWriteBlifToFile(
+  Tbl_Table_t *table,
+  FILE *fp    
+    )
+{		      
+  int numInputs, numOutputs, numRows, colnum, i, j;
+  Var_Variable_t *var;
+  Tbl_Entry_t *entry;
+  lsGen gen;
+  Tbl_Range_t *range;
+  int value, flag;
+
+
+  fprintf(fp,".names ");     
+  for (colnum=0; colnum < Tbl_TableReadNumInputs(table); colnum++) {
+    var = Tbl_TableReadIndexVar(table, colnum, 0);
+    fprintf(fp,"%s ",Var_VariableReadName(var));
+  }
+  for (colnum=0; colnum < Tbl_TableReadNumOutputs(table); colnum++) {
+    var = Tbl_TableReadIndexVar(table, colnum, 1);
+    fprintf(fp,"%s ",Var_VariableReadName(var));
+  }
+  fprintf(fp,"\n");
+
+
+  numInputs = Tbl_TableReadNumInputs(table);
+  numOutputs = Tbl_TableReadNumOutputs(table);
+  numRows = Tbl_TableReadNumRows(table);
+
+
+  for (i=0; i < numRows; i++) {
+    flag =1;
+  
+    if (numOutputs == 1) {
+      entry =  Tbl_TableReadEntry(table, i, 0, 1);
+      if (Tbl_EntryReadNumValues(entry) ==1 ){
+        Tbl_EntryForEachValue(entry,value,gen,range){
+          if (value ==0) {
+            flag = 0;
+          }
+        }
+      }
+    }
+    if (flag ==1) {      
+      for(j = 0; j < numInputs; j++){
+        entry = Tbl_TableReadEntry(table, i, j, 0);
+        TblEntryWriteBlif(table,entry,fp);
+      }
+      fprintf(fp," ");
+    
+      for(j = 0; j < numOutputs; j++){
+        entry = Tbl_TableReadEntry(table, i, j, 1);
+        TblEntryWriteBlif(table,entry,fp);
+      }
+      fprintf(fp,"\n");      
+    }
+  }
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Return the defaults array associated with a table.]
+
+  Description []
+
+  SideEffects [This array is NOT to be modified. The user is encouraged not
+  to use this function. It is exported so as to make the macros for iteration over
+  items in the table possible. The user should use these macros for accessing data.
+  The macros that can be used are mentioned in the SeeAlso list]
+
+  SeeAlso     [Tbl_TableForEachEntry Tbl_TableForEachInputEntry Tbl_TableForEachOutputEntry
+  Tbl_TableForEachInputVar Tbl_TableForEachOutputVar Tbl_TableForEachDefault]
+
+******************************************************************************/
+array_t*
+Tbl_TableReadDefaults(
+    Tbl_Table_t * table)
+{
+  return (table->data->defaults);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return the input Var_Variable_t  array associated with a table.]
+
+  Description []
+
+  SideEffects [This array is NOT to be modified. The user is encouraged not
+  to use this function. It is exported so as to make the macros for iteration over
+  items in the table possible. The user should use these macros for accessing data.
+  The macros that can be used are mentioned in the SeeAlso list]
+
+  SeeAlso     [Tbl_TableForEachEntry Tbl_TableForEachInputEntry Tbl_TableForEachOutputEntry
+  Tbl_TableForEachInputVar Tbl_TableForEachOutputVar Tbl_TableForEachDefault]
+
+******************************************************************************/
+array_t*
+Tbl_TableReadInputVars(
+    Tbl_Table_t * table)
+{
+  return (table->inputNames);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return the output Var_Variable_t  array associated with a table.]
+
+  Description []
+
+  SideEffects [This array is NOT to be modified. The user is encouraged not
+  to use this function. It is exported so as to make the macros for iteration over
+  items in the table possible. The user should use these macros for accessing data.
+  The macros that can be used are mentioned in the SeeAlso list]
+
+  SeeAlso     [Tbl_TableForEachEntry Tbl_TableForEachInputEntry Tbl_TableForEachOutputEntry
+  Tbl_TableForEachInputVar Tbl_TableForEachOutputVar Tbl_TableForEachDefault]
+
+******************************************************************************/
+array_t*
+Tbl_TableReadOutputVars(
+    Tbl_Table_t * table)
+{
+  return (table->outputNames);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks to see if the input parts of two rows intersect]
+
+  Description [Given two rows, this function checks to see if their input parts
+  intersect, returns a 0 if they don't, and 1 if they do]
+
+  SideEffects []
+
+  SeeAlso     [Tbl_TableIsDet]
+
+******************************************************************************/
+boolean
+Tbl_RowInputIntersect(
+  Tbl_Table_t * table,
+  int a,
+  int b)
+{
+  int colNum, check;
+  Tbl_Entry_t *entrya, *entryb;
+  Tbl_Row_t *rowb;
+  
+  check = FALSE;
+  rowb = TblTableReadRow(table,b);
+  
+  Tbl_RowForEachInputEntry(table,a, entrya, colNum){
+    entryb = TblRowReadEntry(rowb,colNum,0);
+    check = Tbl_EntryTestIntersectEntry(entrya,entryb);
+
+    if (check == FALSE) {
+      return FALSE;
+    }    
+  }
+  return TRUE;    
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks to see if the output parts of two rows intersect]
+
+  Description [Given two rows, this function checks to see if their output parts
+  intersect, returns a 0 if they don't, and 1 if they do]
+
+  SideEffects []
+
+  SeeAlso     [Tbl_TableIsDet]
+
+******************************************************************************/
+boolean
+Tbl_RowOutputIntersect(
+  Tbl_Table_t * table,
+  int a,
+  int b)
+{
+  int colNum, check;
+  Tbl_Entry_t *entrya, *entryb;
+  Tbl_Row_t *rowb;
+  
+  check = FALSE;
+  rowb = TblTableReadRow(table,b);
+  
+  Tbl_RowForEachOutputEntry(table,a, entrya, colNum){
+    entryb = TblRowReadEntry(rowb,colNum,1);
+    check = Tbl_EntryTestIntersectEntry(entrya,entryb);
+
+    if (check == FALSE) {
+      return FALSE;
+    }    
+  }
+  return TRUE;    
+
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis    [Set a Row]
+
+  Description [Given a table, a row and an index , this function sets the row
+  in the table]
+
+  SideEffects [ The previously set  row is lost ]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+TblTableSetRow(
+  Tbl_Table_t *table,
+  Tbl_Row_t *row,
+  int i)
+{
+  array_insert(Tbl_Row_t*, TblTableReadData(table),i,row);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return the output array associated with a row.]
+
+  Description []
+
+  SideEffects [This array is NOT to be modified. The user is encouraged not
+  to use this function. It is exported so as to make the macros for iteration over
+  items in the table possible. The user should use these macros for accessing data.
+  The macros that can be used are mentioned in the SeeAlso list]
+
+  SeeAlso     [Tbl_TableForEachEntry Tbl_TableForEachInputEntry Tbl_TableForEachOutputEntry
+  Tbl_TableForEachInputVar Tbl_TableForEachOutputVar Tbl_TableForEachDefault]
+
+******************************************************************************/
+array_t*
+TblRowReadOutputs(
+    Tbl_Row_t * row)
+{
+  return (row->outputs);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Return the input array associated with a row.]
+
+  Description []
+
+  SideEffects [This array is NOT to be modified. The user is encouraged not
+  to use this function. It is exported so as to make the macros for iteration over
+  items in the table possible. The user should use these macros for accessing data.
+  The macros that can be used are mentioned in the SeeAlso list]
+
+  SeeAlso     [Tbl_TableForEachEntry Tbl_TableForEachInputEntry Tbl_TableForEachOutputEntry
+  Tbl_TableForEachInputVar Tbl_TableForEachOutputVar Tbl_TableForEachDefault]
+
+******************************************************************************/
+array_t*
+TblRowReadInputs(
+    Tbl_Row_t * row)
+{
+  return (row->inputs);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Read a table row]
+
+  Description [Given a table and an integer rowNum, this return the rowNumth
+  Tbl_Row_t]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Tbl_Row_t*
+TblTableReadRow(
+  Tbl_Table_t *table,
+  int rowNum)
+{
+  return(array_fetch(Tbl_Row_t*,TblTableReadData(table),rowNum));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Allocate space for a row]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Tbl_Row_t*
+TblRowAlloc(void)
+{
+  Tbl_Row_t *row;
+
+  row = ALLOC(Tbl_Row_t,1);
+  row->inputs = array_alloc(Tbl_Entry_t*,0);
+  row->outputs = array_alloc(Tbl_Entry_t*,0);
+
+  return row;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Duplicate a table row]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Tbl_Row_t*
+TblRowDup(
+  Tbl_Row_t * row)
+{
+  Tbl_Row_t *newrow;
+  Tbl_Entry_t *newEntry, *entry;
+  int i;
+
+  newrow = TblRowAlloc();
+
+  for (i=0; i < array_n(row->inputs); i++){
+    entry = array_fetch(Tbl_Entry_t*,row->inputs,i);
+    if (entry != NIL(Tbl_Entry_t)) {
+      newEntry= Tbl_EntryDup(entry);
+    }
+    else {
+      newEntry = NIL(Tbl_Entry_t);
+    }
+    TblRowSetEntry(newrow,newEntry,i,0);
+  }
+
+  for (i=0; i < array_n(row->outputs); i++){
+    entry = array_fetch(Tbl_Entry_t*,row->outputs,i);    
+    if (entry != NIL(Tbl_Entry_t)) {
+      newEntry = Tbl_EntryDup(entry);
+    }
+    else {
+      newEntry = NIL(Tbl_Entry_t);
+    }      
+    TblRowSetEntry(newrow,newEntry,i,1);
+  }
+  return newrow;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the entry in the given row at the given index]
+
+  Description [Given a row, an entry , a flag set to 0 to indicate input and
+  1 for output, and an index, this function sets the
+  entry in the row at the index.]
+
+  SideEffects [The previous entry item at the index is lost]
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+TblRowSetEntry(
+  Tbl_Row_t *row,
+  Tbl_Entry_t * entry,
+  int i,
+  int flag)
+{
+  array_t *carray;
+  
+  if (flag ==0) {
+    carray = TblRowReadInputs(row);
+  }
+  else {
+    carray = TblRowReadOutputs(row);
+  }
+    
+  if (i < array_n(carray)){
+    array_insert(Tbl_Entry_t*,carray,i,entry);
+  }
+  else {
+    array_insert_last(Tbl_Entry_t*,carray,entry);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Free a Tbl_Row_t]
+
+  Description [Given a Tbl_Row_t, this function frees all memory associated
+  with it. ]
+
+  SideEffects []
+
+  SeeAlso     [TblRowAlloc]
+
+******************************************************************************/
+void
+TblRowFree(
+  Tbl_Row_t *row)
+{
+  assert(row != NIL(Tbl_Row_t));
+  array_free(row->inputs);
+  array_free(row->outputs);
+  FREE(row);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Read the specified index entry in the given row]
+
+  Description [Given a Tbl_Row_t* and an integer i, this function returns the
+  Tbl_Entry_t* at the ith position in the row.It must also be supplied with a
+  flag to indicate whether an input or output entry is being read.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Tbl_Entry_t*
+TblRowReadEntry(
+    Tbl_Row_t *row,
+    int i,
+    int flag)
+{
+  
+  if (flag==0) {
+    return(array_fetch(Tbl_Entry_t*,TblRowReadInputs(row),i));
+  }
+  else {
+    return(array_fetch(Tbl_Entry_t*, TblRowReadOutputs(row),i));
+  }
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [To compute a hash value for a table entry]
+
+  Description [Given a Tbl_Table_t *table, and a Tbl_Entry_t *entry, this function
+  computes the hash value for the corresponding entry]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+TableEntryComputeHashVal(
+  Tbl_Table_t *table,
+  Tbl_Entry_t *entry)
+{
+  int numRows, numCols;
+  lsGen gen;
+  int value;
+  Tbl_Range_t *range;
+  int total;
+
+  numRows = Tbl_TableReadNumRows(table);
+  numCols = Tbl_TableReadNumInputs(table) + Tbl_TableReadNumOutputs(table) + numRows+1;
+  total = 0;
+
+  if(entry->type == Tbl_EntryNormal_c) {
+    Tbl_EntryForEachValue(entry,value,gen,range) {
+      total = total + (int) pow(numCols,value);
+    }
+  }
+  else if(entry->type == Tbl_EntryEqual_c) {
+    value = Var_VariableReadNumValues(Tbl_EntryReadActualVar(table,entry));
+    total = total + (int) pow(numCols,value);
+  }
+  
+  return total;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Create a array of size entries, each intialized to -1]
+
+  Description [Given an integer size, this function returns an array of size
+  that has all entries intialized to -1]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static array_t*
+TableCreatIntArray(
+  int size)
+{
+  array_t *result;
+  int i;
+  
+  result = array_alloc(int,0);
+  for (i=0; i < size; i++) {
+    array_insert_last(int,result,-1);
+  }
+  return result;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis           [Get table signature as a string]
+
+  Description        [optional]
+
+  SideEffects        [required]
+
+  SeeAlso            [optional]
+
+
+******************************************************************************/
+static char*
+TableObtainSignature(Tbl_Table_t * table,
+                     int outputColumn)
+{
+  char *                signature;
+  char *                sig;            /* Signature under construction */
+
+  int                   row;            /* locations in the table */
+  int                   column;
+
+  Tbl_Entry_t *         entry;          /* Entry at row, column */
+
+  int                   value;          /* Value of an entry */
+  lsGen                 gen;            /* For Tbl_EntryForEachValue */
+  Tbl_Range_t *         range;
+
+  int                   varIndex;       /* Index of the column of this variable */
+
+  /*
+   * TODO: This is unsafe!
+   */
+
+  signature = ALLOC( char, 10000 );
+  sig = signature;
+
+  for ( row = Tbl_TableReadNumRows( table ) ; --row >=0 ; ) {
+
+    /*
+     * Print each of the inputs in this row
+     */
+
+    Tbl_RowForEachInputEntry( table, row, entry, column ) {
+
+      switch ( Tbl_EntryReadType( entry ) ) {
+
+        /*
+         * An equality entry ("this column is equal to that column")
+         */
+
+      case Tbl_EntryEqual_c:
+
+        /*
+         * Find the column index, first assuming it's an input
+         */
+
+        varIndex = Tbl_EntryReadVarIndex(entry);
+
+        sprintf( sig, "=%d", varIndex );
+        sig += strlen( sig );
+        break;
+
+        /*
+         * A normal range entry - print a comma-separated list of values
+         */
+
+      case Tbl_EntryNormal_c:
+        Tbl_EntryForEachValue( entry, value, gen, range ) {
+          sprintf(sig, "%d,", value );
+          sig += strlen( sig );
+        }
+        break;
+
+        /*
+         * Unassigned -- append a "?"
+         */
+
+      case Tbl_EntryUnassigned_c:
+        sig[0] = '?';
+        sig++;
+        break;
+        /*
+         * None of the Above -- we're in trouble
+         */
+
+      default:
+        assert(0);
+        break;
+
+      }
+      
+      /*
+       * Separate entries with spaces
+       */
+      
+      sig[0] = ' ';
+      sig++;
+
+    }
+
+    /*
+     * Print the output column's entry
+     */
+
+    entry = Tbl_TableReadEntry( table, row, outputColumn, 1 );
+
+    switch ( Tbl_EntryReadType( entry ) ) {
+
+      /*
+       * An equality entry ("this column is equal to that column")
+       */
+
+    case Tbl_EntryEqual_c:
+
+      /*
+       * Find the column index, first assuming it's an input
+       */
+
+      varIndex = Tbl_EntryReadVarIndex(entry);
+
+      sprintf( sig, "=%d", varIndex );
+      sig += strlen( sig );
+      break;
+      
+      /*
+       * A normal range entry - print a comma-separated list of values
+       */
+      
+    case Tbl_EntryNormal_c:
+      Tbl_EntryForEachValue( entry, value, gen, range ) {
+        sprintf(sig, "%d,", value );
+        sig += strlen( sig );
+      }
+      break;
+      
+      /*
+       * Unassigned -- append a "?"
+       */
+      
+    case Tbl_EntryUnassigned_c:
+      sig[0] = '?';
+      sig++;
+      break;
+      
+      /*
+       * None of the Above -- we're in trouble
+       */
+      
+    default:
+      assert(0);
+      break;
+      
+    }
+
+    /*
+     * Separate rows with newlines
+     */
+
+    sig[0] = '\n';
+    sig++;
+
+  }
+
+  /*
+   * Terminate the signature string
+   */
+
+  sig[0] = '\0';
+
+  return signature;
+}     
+
+
+/**Function***********************************************************
+
+  Synopsis [Comparison function for qsort.]
+
+  Description [This function is used by qsort to order table inputs
+  according to the MDD variable order in the support of the MVF.]
+
+  SideEffects [none]
+
+  SeeAlso [Tbl_TableCreateTrueSupportTableForOutput]
+
+**********************************************************************/
+static int
+varCompare(const void *x, const void *y)
+{
+  Var_Ord_t *a = (Var_Ord_t *) x;
+  Var_Ord_t *b = (Var_Ord_t *) y;
+  return(a->rank - b->rank);
+}
Index: vis_dev/vis-2.3/src/truesim/truesim.h
===================================================================
--- vis_dev/vis-2.3/src/truesim/truesim.h	(revision 14)
+++ vis_dev/vis-2.3/src/truesim/truesim.h	(revision 14)
@@ -0,0 +1,91 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [truesim.h]
+
+  PackageName [truesim]
+
+  Synopsis    [Exported functions and data structures for the truesim package.]
+
+  Description [Exported functions and data structures for the truesim
+  package. This package provides procedures to perform pattern based
+  zero delay and levelized two-pass event-driven simulation of
+  circuits described in BLIF format. Pattern vectors to be simulated
+  can either be provided or can be generated using user-specified
+  primary input probabilities. Only combinational circuits are
+  supported at this time.]
+
+  SeeAlso     [truesimInt.h]
+
+  Author      [Balakrishna Kumthekar]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#ifndef _TRUESIM
+#define _TRUESIM
+
+#include "part.h"
+#include "cmd.h"
+#include "util.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void Truesim_Init(void);
+EXTERN void Truesim_End(void);
+EXTERN int Truesim_RealDelayPatternSimulate(Ntk_Network_t *network, array_t *inputArray, array_t *patternArray);
+EXTERN void Truesim_InitializeSimulation(Ntk_Network_t *network, char *delayFile, boolean truedelay, int header, int verbose, st_table *nodeDelayTable);
+EXTERN void Truesim_QuitSimulation(Ntk_Network_t *network);
+EXTERN void Truesim_NetworkUpdateNodeTopologicalDepth(Ntk_Network_t *network);
+EXTERN void Truesim_ReadInputProbabilities(Ntk_Network_t *network, char *probFile, array_t *inputArray, array_t *probArray);
+EXTERN void Truesim_GeneratePrimaryInputProbs(Ntk_Network_t *network, char *probFile);
+EXTERN int Truesim_ReadSimulationVectors(Ntk_Network_t *network, char *simFile, array_t *inputArray, array_t *patternArray);
+EXTERN array_t * Truesim_GenerateRandomVectors(Ntk_Network_t *network, array_t *probArray, array_t *patternArray, int numInputs, int N);
+EXTERN void Truesim_DumpSimulationVectors(Ntk_Network_t *network, array_t *inputArray, array_t *patternArray, char *outFile);
+EXTERN array_t * Truesim_NetworkComputeNodeDepths(Ntk_Network_t *network);
+EXTERN int Truesim_NetworkReadNodeDepth(Ntk_Network_t *network, Ntk_Node_t *node);
+EXTERN float Truesim_NetworkReadNodeProbability(Ntk_Network_t *network, Ntk_Node_t *node);
+EXTERN float Truesim_NetworkReadNodeSwitchingProb(Ntk_Network_t *network, Ntk_Node_t *node);
+EXTERN float Truesim_NetworkReadNodeLoad(Ntk_Network_t *network, Ntk_Node_t *node);
+EXTERN float Truesim_NetworkReadNodeDelay(Ntk_Network_t *network, Ntk_Node_t *node);
+EXTERN boolean Truesim_NetworkSetNodeLoad(Ntk_Network_t *network, Ntk_Node_t *node, float load);
+EXTERN boolean Truesim_NetworkSetNodeDelay(Ntk_Network_t *network, Ntk_Node_t *node, float delay);
+EXTERN boolean Truesim_NetworkSetNodeStaticProb(Ntk_Network_t *network, Ntk_Node_t *node, float prob);
+EXTERN boolean Truesim_NetworkSetNodeSwitchingProb(Ntk_Network_t *network, Ntk_Node_t *node, float switching);
+EXTERN float Truesim_BddNodeComputeProbability(Ntk_Network_t *network, bdd_node *func);
+EXTERN int Truesim_ZeroDelayPatternSimulate(Ntk_Network_t *network, array_t *inputArray, array_t *patternArray);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _TRUESIM */
Index: vis_dev/vis-2.3/src/truesim/truesim.make
===================================================================
--- vis_dev/vis-2.3/src/truesim/truesim.make	(revision 14)
+++ vis_dev/vis-2.3/src/truesim/truesim.make	(revision 14)
@@ -0,0 +1,7 @@
+CSRC += truesimCmd.c truesimMain.c truesimSim.c truesimUtil.c \
+	truesimZero.c
+
+HEADERS += truesim.h truesimInt.h
+
+DEPENDENCYFILES = $(CSRC)
+
Index: vis_dev/vis-2.3/src/truesim/truesimCmd.c
===================================================================
--- vis_dev/vis-2.3/src/truesim/truesimCmd.c	(revision 14)
+++ vis_dev/vis-2.3/src/truesim/truesimCmd.c	(revision 14)
@@ -0,0 +1,620 @@
+/**CFile***********************************************************************
+
+  FileName    [truesimCmd.c]
+
+  PackageName [truesim]
+
+  Synopsis    [Command interface for the truesim package.]
+
+  Description [Command interface for the truesim package. This package
+  implements delay-based simulation of a combinational circuit in addition
+  to zero-delay simulation. The 'sim' package does zero-delay simulation,
+  but handles both combinational and sequential circuits. This package
+  can take as input circuits described in BLIF format only.
+
+  In delay-based simulation each node of the network has a certain
+  amount of propagation delay through it. The delay and load for each node
+  of the circuit can be specified by the user. In the absence of delay
+  values, the fanout count of the node is assumed to be the delay. In
+  this implementation the delay values do not have units. For example,
+  a node with 2 fanouts has a delay of 2, an node with fanout 4 has
+  delay of 4, etc. Primary outputs are assumed to have a delay of 1,
+  unlesss specfied otherwise. Load values are used by other
+  applications to compute power dissipation (by using the node switching
+  information via simulation.)
+
+  Boolean vectors can be specified for the primary inputs of the circuit.
+  Alternatively, bit vectors can also be generated randomly. The bit
+  vectors are applied to the circuit one at a time. The effects of one
+  pattern (a bit-vector for the primary inputs) are propagated through
+  the circuit and subsequent patterns are applied only after all the
+  signals in the circuit have settled.]
+
+  Author      [Balakrishna Kumthekar <kumtheka@colorado.edu>]
+
+  Copyright [This file was created at the University of Colorado at
+  Boulder.  The University of Colorado at Boulder makes no warranty about
+  the suitability of this software for any purpose.  It is presented on
+  an AS IS basis.]
+
+******************************************************************************/
+
+#include "truesimInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define DEFAULT_NUM_PATTERNS 1000
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+static jmp_buf timeOutEnv;
+
+/* Global variable used within truesim package */
+int createdPart;
+int truesimRptHeader;
+int truesimVerbose;
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandTruesim(Hrc_Manager_t **hmgr, int argc, char **argv);
+static void TimeOutHandle(void);
+static int TestIsNetworkMultipleValued(Ntk_Network_t *network);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [This function initializes the truesim package.]
+
+  SideEffects [None]
+
+  SeeAlso     [Truesim_End]
+
+******************************************************************************/
+void
+Truesim_Init(void)
+{
+  Cmd_CommandAdd("truesim", CommandTruesim, 0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [This function ends the truesim package.]
+
+  SideEffects [None]
+
+  SeeAlso     [Truesim_Init]
+
+******************************************************************************/
+void
+Truesim_End(void)
+{
+
+} /* End of Truesim_End */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the truesim command.]
+
+  CommandName [truesim]
+
+  CommandSynopsis [Simulate the flattened network]
+
+  CommandArguments [\[ -D &lt;filename&gt; \] \[ -d \] 
+  \[ -f &lt;filename&gt; \] \[ -g &lt;filename&gt; \] \[ -h \]  
+  \[ -n &lt;N&gt; \] \[ -p &lt;filename&gt; \] \[ -r &lt;N&gt; \] 
+  \[ -t &lt;time&gt; \] \[ -v &lt;N&gt; \]]
+
+  CommandDescription [Simulates a network with a set of input
+  vectors. Before calling this command, the user should create a partition
+  (using the command <tt>build_partition_mdds</tt>). The simulation
+  vectors can be provided by the user (using -f vectors_file), or
+  generated randomly. <p>
+
+  Command options:<p>
+
+  <dl>
+  <dt>-D &lt;filename&gt;
+  <dd> File to dump randomly generated vectors. Primary input
+  probability file SHOULD be specified with -p option.
+
+
+  <dt>-d 
+  <dd>Perform event-driven true delay simulation. The fanout count of
+  the nodes is used as an estimate for the node delay. Primary inputs
+  are assumed to have arrival times of zero.
+
+
+  <dt>-f &lt;filename&gt; 
+  <dd> File containing simulation vectors. The format is simple but
+  strict and hence, few checks are made. The file format is as below:
+
+  <p>.i <code>c n d o e p f q g r h s i t j u k a l b m</code><br>
+  .s <br>
+  0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 1 1 1 1 ; <br>
+  0 1 1 0 0 0 0 1 0 1 1 0 1 1 1 1 0 0 0 0 1 ; <br>
+  0 0 1 0 0 0 0 1 0 1 0 0 0 1 0 1 0 0 0 0 1 ; <br>
+  0 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 0 1 0 0 1 ; <br>
+
+  <p> The .i statement specifies the primary inputs of the network. The
+  patterns start after .s key word. Each vector is a space separated list
+  of bits and ends in a semi-colon. The length of any vector should be
+  equal to the number of signals specified in the .i statement. A line
+  starting with # is a comment. <p>
+
+
+  <dt>-g &lt;filename&gt; 
+  <dd> File to output random probabilities for primary inputs. Use this
+  option ONLY to produce a vector of signal probabilities for primary
+  inputs. This option does not proceed with simulation.
+
+
+  <dt>-h
+  <dd>Print a help message that details all options.
+
+
+  <dt> -n &lt;N&gt;
+  <dd> Number of patterns to simulate. The default is 1000. Use this
+  option ONLY with -p option.
+
+
+  <dt>-p &lt;filename&gt;
+  <dd> File containing primary input probabilities. The format is as
+  shown below:
+
+  <p> 
+  PI_Name1 0.67 <br>
+  PI_Name2 0.45 <br>
+
+
+  <dt>-r &lt;N&gt; 
+  <dd> Print PI/PO names after every N patterns simulated, for better
+  readability of simulation output. This option is effective only when
+  the verbosity flag is on.
+
+  <dt>-T &lt;filename&gt;
+  <dd> File containing node delay and load values. The file format is
+  as shown below:
+
+  <p>
+  node1 delay1 load1 <br>
+  node2 delay2 load2 <br>
+
+  <p> The delay vaues are assumed as specified in a common unit. The same
+  is true for load values too.
+
+  
+  <dt>-t &lt;time&gt;
+  <dd> Time in seconds allowed to finish the simulation.  The default
+  is no limit.
+
+
+  <dt>-v &lt;N&gt;
+  <dd>  Specify verbosity level, N.
+  </dl> <p>]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandTruesim(
+  Hrc_Manager_t **hmgr,
+  int argc,
+  char **argv)
+{
+  Ntk_Network_t *network = NIL(Ntk_Network_t);
+  graph_t *partition;
+  boolean trueDelay;
+  int genVectors,N,status;
+  int c; /* For scanning command line arguments */
+  long timeOutPeriod,initialTime,finalTime;
+  char *probFile,*simFile,*probGenFile,*dumpFile;
+  char *delayFile;
+  FILE *fp = NIL(FILE);;
+  
+  /* These are the default values. */
+  createdPart = 0; /* =1 when partiton is created by the command */
+  trueDelay = FALSE; /* Use zero-delay simulation by default */
+  timeOutPeriod   = 0; /* Unlimited time */ 
+  genVectors = -1; /* Do not generate bit-vectors for simulation */
+  N = -1; /* Number of patterns to simulate */
+  probFile = NIL(char); /* File with probability values for PI */
+  simFile = NIL(char); /* Simulation bit-vector file */
+  probGenFile = NIL(char); /* File with prob. values for PI; used during
+  			    * bit-vector generation */
+  dumpFile = NIL(char); /* File to dump generated bit-vectors */
+  delayFile = NIL(char); /* File with delay vaules for nodes of the
+  			  * circuit */
+  truesimVerbose = 0; /* Verbosity level */
+  truesimRptHeader = -1; /* Print PI/PO names while printing simulation
+  		      * results */
+
+  if (bdd_get_package_name() != CUDD) {
+    (void) fprintf(vis_stderr,
+		   "** truesim error: The truesim package can be used only with CUDD package\n");
+    (void) fprintf(vis_stderr,
+		   "** truesim error: Please link with CUDD package\n");
+    return 0;
+  }
+	
+  util_getopt_reset();
+
+  while((c = util_getopt(argc, argv, "D:df:g:hn:p:r:T:t:v:")) != EOF) {
+    switch(c) {
+    case 'D':
+      if (!util_optarg) {
+	(void) fprintf(vis_stderr,
+		       "** truesim error: File to output pattern vectors not specified.\n");
+	goto usage;
+      }
+      dumpFile = util_strsav(util_optarg);
+      break;
+    case 'd':
+      trueDelay = TRUE;
+      break;
+    case 'f': 
+      if (!util_optarg) {
+	(void) fprintf(vis_stderr,
+		       "** truesim error: Simulation file not specified.\n");
+	goto usage;
+      } else {
+	simFile = util_strsav(util_optarg);
+	if ((fp = Cmd_FileOpen(simFile,"r",NIL(char *),1)) == NIL(FILE)) {
+	  (void) fprintf(vis_stderr,
+			 "** truesim error: Could not open %s for reading.\n",
+			 simFile);
+	  goto endgame;
+	} else {
+	  fclose(fp);
+	}
+	/* Stop generation of vectors, in case -p is also used with -f */
+	N = -1;
+	genVectors = 0;
+	if (probFile) {
+	  FREE(probFile);
+	  probFile = NIL(char);
+	}
+      }
+      break;
+    case 'g': 
+      if (!util_optarg) {
+	(void) fprintf(vis_stderr,
+		       "** truesim error: File to output input probs. not specified.\n");
+	goto usage;
+      }
+      probGenFile = util_strsav(util_optarg);
+      break;
+    case 'h':
+      goto usage;
+    case 'n':
+      if (genVectors != 0) {
+	N = atoi(util_optarg);
+	genVectors = 1;
+      } else {
+	(void) fprintf(vis_stderr,
+		       "** truesim warning: Simulation file already specified.\n");
+	(void) fprintf(vis_stderr,
+		       "** truesim warning: Ignoring -n option.\n");
+      }
+      break;
+    case 'p': 
+      if (genVectors != 0) {
+	if (!util_optarg) {
+	  (void) fprintf(vis_stderr,
+			 "** truesim error: Probability file not specified.\n");
+	  goto usage;
+	} else {
+	  probFile = util_strsav(util_optarg);
+	  if ((fp = Cmd_FileOpen(probFile,"r",NIL(char *),1)) == NIL(FILE)) {
+	    (void) fprintf(vis_stderr,
+			   "** truesim error: Could not open %s for reading.\n",
+			   probFile);
+	    goto endgame;
+	  } else {
+	    fclose(fp);
+	  }
+	}
+	genVectors = 1;
+      } else {
+	(void) fprintf(vis_stderr,
+		       "** truesim warning: Simulation file already specified.\n");
+	(void) fprintf(vis_stderr,
+		       "** truesim warning: Ignoring -p option.\n");
+      }
+      break;
+    case 'r':
+      truesimRptHeader = atoi(util_optarg);
+      break;
+    case 'T': 
+      if (!util_optarg) {
+	(void) fprintf(vis_stderr,
+		       "** truesim error: Delay file not specified.\n");
+	goto usage;
+      } else {
+	delayFile = util_strsav(util_optarg);
+	if ((fp = Cmd_FileOpen(delayFile,"r",NIL(char *),1)) == NIL(FILE)) {
+	  (void) fprintf(vis_stderr,
+			 "** truesim error: Could not open %s for reading.\n",
+			 delayFile);
+	  goto endgame;
+	} else {
+	  fclose(fp);
+	}
+      }
+      break;
+    case 't':
+      timeOutPeriod = atoi(util_optarg);
+      break;
+    case 'v':
+      truesimVerbose = atoi(util_optarg);
+      break;
+    default:
+      goto usage;
+    }
+  }
+
+  if(Hrc_ManagerReadCurrentNode(*hmgr) == NIL(Hrc_Node_t)) {
+    (void) fprintf(vis_stderr,"** truesim error: The hierarchy manager is empty.");
+    (void) fprintf(vis_stderr," Read in design.\n");
+    goto endgame;
+  }
+
+  network = (Ntk_Network_t *) 
+    Hrc_NodeReadApplInfo(Hrc_ManagerReadCurrentNode(*hmgr), 
+			 NTK_HRC_NODE_APPL_KEY);
+
+  if(network == NIL(Ntk_Network_t)) {
+    (void) fprintf(vis_stderr,"** truesim error: There is no network. ");
+    (void) fprintf(vis_stderr,"Use flatten_hierarchy.\n");
+    goto endgame;
+  }
+
+  /* Check if the current network has signals with multiple values. */
+  if (TestIsNetworkMultipleValued(network)) {
+    (void) fprintf(vis_stderr,"** truesim error: Circuit has multiple valued variables.\n");
+    (void) fprintf(vis_stderr,"** truesim error: This algorithm applies to boolean signals only.\n");
+    goto endgame;
+  }
+
+  if(Ntk_NetworkReadNumPrimaryInputs(network) !=
+     Ntk_NetworkReadNumInputs(network)) {
+    (void) fprintf(vis_stderr,"** truesim error: This algorithm applies only for circuits descrbied in BLIF format.\n");
+    goto endgame;
+  }
+
+  /* Generate a file with random values for primary inputs and return. No
+     simulation is performed. */
+  if (probGenFile) {
+    Truesim_GeneratePrimaryInputProbs(network,probGenFile);
+    FREE(probGenFile);
+    if (probFile)
+      FREE(probFile);
+    if (simFile)
+      FREE(simFile);
+    if (dumpFile)
+      FREE(dumpFile);
+    if (delayFile)
+      FREE(delayFile);
+    return 0;
+  }
+
+  /* Make sure that we either generate random vectors or we are
+     supplied with simulation vectors */
+  if (genVectors == -1) {
+    (void) fprintf(vis_stderr,
+		   "** truesim error: Neither simulation vector file nor ");
+    (void) fprintf(vis_stderr,
+		   "PI probabilities provided.\n");
+    (void) fprintf(vis_stderr,
+		   "** truesim error: No simulation will be performed.\n");
+    goto endgame;
+  }
+
+  if (dumpFile && !genVectors) {
+    if (!simFile) {
+      (void) fprintf(vis_stderr,
+		     "** truesim error: PI probability file not specified.\n");
+      (void) fprintf(vis_stderr, 
+		     "** truesim error: Use -p option.\n");
+      (void) fprintf(vis_stderr,
+		     "** truesim error: No simulation will be performed.\n");
+      goto endgame;
+    } else {
+      (void) fprintf(vis_stderr,
+      		     "** truesim warning: Simulation file %s specified.\n",
+		     simFile);
+      (void) fprintf(vis_stderr,
+      		     "** truesim warning: Ignoring dump file %s\n",dumpFile);
+    }
+  }
+  
+  /* Make sure N is specified or a default value is used */
+  if (N == -1 && genVectors == 1) {
+    (void) fprintf(vis_stderr,
+		   "** truesim warning: Number of patterns to be simulated is not specified.\n");
+    (void) fprintf(vis_stderr,
+		   "Assuming N = 1000 patterns to be simulated.\n");
+    N = DEFAULT_NUM_PATTERNS;
+  }
+
+  /* Access a 'total' partition */
+  partition = (graph_t *) Ntk_NetworkReadApplInfo(network, 
+						  PART_NETWORK_APPL_KEY);
+  createdPart = 0; /* Using partition of the network. */
+  if (partition == NIL(graph_t) || 
+      (Part_PartitionReadMethod(partition) != Part_Total_c)) {
+    partition = Part_NetworkCreatePartition(network, 
+					    NIL(Hrc_Node_t),
+					    "dummy", (lsList) 0, 
+					    (lsList) 0, NIL(mdd_t),
+					    Part_Total_c,
+					    (lsList) 0, 
+					    FALSE, FALSE, TRUE);
+    if (partition == NIL(graph_t)) {
+      (void) fprintf(vis_stderr,"** truesim error: Could not create a partition.\n");
+      goto endgame;
+    }
+    Ntk_NetworkAddApplInfo(network,PART_NETWORK_APPL_KEY,
+			   (Ntk_ApplInfoFreeFn)Part_PartitionFreeCallback,
+			   (void *)partition);
+    createdPart = 1; /* Using new partition */
+  }
+
+  /* Start the timer.*/
+  if (timeOutPeriod > 0){
+    (void) signal(SIGALRM, (void(*)(int))TimeOutHandle);
+    (void) alarm(timeOutPeriod);
+    if (setjmp(timeOutEnv) > 0) {
+      (void) fprintf(vis_stderr, "** truesim warning: Timeout occurred after ");
+      (void) fprintf(vis_stderr, "%ld seconds.\n", timeOutPeriod);
+      alarm(0);
+      goto endgame;
+    }
+  }
+
+  initialTime = util_cpu_time();
+  status = TruesimSimulateNetwork(network,simFile,probFile,delayFile,
+				  dumpFile,trueDelay,genVectors,N);
+  finalTime = util_cpu_time();
+  if(status) {
+    (void) fprintf(vis_stdout, "%-20s%10ld\n", "** truesim info: analysis time =",
+		   (finalTime-initialTime)/1000);
+  }
+  else {
+    (void) fprintf(vis_stdout, "** truesim error: Simulation was not successful.\n");
+  }
+
+  alarm(0);
+  /* Clean up */
+  if (probGenFile)
+    FREE(probGenFile);
+  if (probFile)
+    FREE(probFile);
+  if (simFile)
+    FREE(simFile);
+  if (dumpFile)
+    FREE(dumpFile);
+  if (delayFile)
+    FREE(delayFile);
+  return 0;  /* normal exit */
+
+endgame:
+  /* Clean up */
+  if (probGenFile)
+    FREE(probGenFile);
+  if (probFile)
+    FREE(probFile);
+  if (simFile)
+    FREE(simFile);
+  if (dumpFile)
+    FREE(dumpFile);
+  if (delayFile)
+    FREE(delayFile);
+  
+  if (createdPart)
+    Ntk_NetworkFreeApplInfo(network,PART_NETWORK_APPL_KEY);
+  
+  return 1; /* Error exit */
+
+usage:
+
+  (void) fprintf(vis_stderr, "\nusage: Also see 'help truesim' for more details.\n\n");
+  (void) fprintf(vis_stderr, "    -D <filename>\tFile to dump randomly generated pattern vectors.\n");
+  (void) fprintf(vis_stderr, "            \t\tPrimary input probability file SHOULD be specified with \n");
+  (void) fprintf(vis_stderr, "            \t\t-p option.\n\n");
+  (void) fprintf(vis_stderr, "    -d      \t\tPerform true delay simulation.\n\n");
+  (void) fprintf(vis_stderr, "    -f <filename>\tFile containing simulation vectors.\n\n");
+  (void) fprintf(vis_stderr, "    -g <filename>\tFile to output random probabilities for PI \n");
+  (void) fprintf(vis_stderr, "            \t\tUse this option ONLY to produce a vector of \n");
+  (void) fprintf(vis_stderr, "            \t\tprobability values for PI. No simulation is performed. \n\n");
+  (void) fprintf(vis_stderr, "    -h      \t\tCommand usage.\n\n");
+  (void) fprintf(vis_stderr, "    -n <N>  \t\tNumber of patterns to simulate. Default is 1000.\n");
+  (void) fprintf(vis_stderr, "            \t\tShould ONLY be used with -p option.\n\n");
+  (void) fprintf(vis_stderr, "    -p <filename>\tFile containing PI probabilities.\n");
+  (void) fprintf(vis_stderr, "            \t\tSee help for file format.\n\n");
+  (void) fprintf(vis_stderr, "    -r <N>  \t\tPrint the node name header ever N iterations.\n");
+  (void) fprintf(vis_stderr, "            \t\tThis is effective only when verbosity flag is on.\n\n");
+  (void) fprintf(vis_stderr, "    -T <filename>\tFile containing node delay and load values.\n");
+  (void) fprintf(vis_stderr, "            \t\tSee help for file format.\n\n");
+  (void) fprintf(vis_stderr, "    -t <time> \t\tTime in seconds allowed to finish the simulation.\n\n");
+  (void) fprintf(vis_stderr, "    -v <N>  \t\tVerbosity level.\n");
+
+  return 1;    /* error exit */
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Handle function for timeout.]
+
+  Description [This function is called when the time out occurs.]
+
+  SideEffects []
+
+******************************************************************************/
+static void
+TimeOutHandle(void)
+{
+  longjmp(timeOutEnv, 1);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks whether the network has multiple valued signals.]
+
+  Description [Checks whether the network has multiple valued
+  signals. Returns 1 if true, else 0.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static int
+TestIsNetworkMultipleValued(Ntk_Network_t *network)
+{
+  Ntk_Node_t *node;
+  lsGen gen;
+  Var_Variable_t *var;
+  int numValues;
+
+  Ntk_NetworkForEachNode(network,gen,node) {
+    var = Ntk_NodeReadVariable(node);
+    numValues = Var_VariableReadNumValues(var);
+    if (numValues > 2)
+      return 1;
+  }
+  return 0;
+}
Index: vis_dev/vis-2.3/src/truesim/truesimInt.h
===================================================================
--- vis_dev/vis-2.3/src/truesim/truesimInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/truesim/truesimInt.h	(revision 14)
@@ -0,0 +1,288 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [truesimInt.h]
+
+  PackageName [truesim]
+
+  Synopsis    [Internal data structures for the truesim package.]
+
+  Description [Internal data structures for the truesim package.]
+
+  SeeAlso     [truesim.h]
+
+  Author      [Balakrishna Kumthekar]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#ifndef _TRUESIMINT
+#define _TRUESIMINT
+
+#include "truesim.h"
+#include <string.h>
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define TRUESIM_NETWORK_APPL_KEY "Truesim_NetworkApplKey"
+#define TRUESIM_ERROR_VALUE -1
+
+/* Different types of event. */
+#define SIM_EVENT_0   0
+#define SIM_EVENT_1   1
+/* Threshold events are book-keeping events. They are not 
+ * simulation events */
+#define THRESHOLD_1   2 
+#define THRESHOLD_2   3    
+#define THRESHOLD_3   4
+#define THRESHOLD_I   5
+#define SIM_EVENT_C   6 /* Even to describe cancellation of a previously
+			 * scheduled event */
+
+/* Constant used during random number generation */
+#define MODULUS1 2147483563 /* Borrowed from util package */
+
+
+/* Basic wheel parameters for the event queue. */
+#define LOG_HOR_LEN         3
+#define LOG_WHEEL_SIZE      10
+#define MAX_TIME            2147483647 /* 2^32 -1  */
+
+/* Derived wheel parameters */
+#define HOR_LEN   (1 << LOG_HOR_LEN) /* # of time 'ticks' in
+				      * each slot of the time wheel. */
+#define WHEEL_SIZE  (1 << LOG_WHEEL_SIZE) /* # slots in the wheel */
+#define PERIOD  (HOR_LEN * WHEEL_SIZE) /* # time ticks in the wheel */
+#define HALF_PERIOD  (PERIOD / 2)
+
+/* # events to allocate at a time. */
+#define MEM_CHUNK 1023
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [Structure to store simulation events.]
+
+  Description [Structure to store simulation events. The Event structure is
+  used only for real-delay simulation.]
+
+  SeeAlso     [EventQueue]
+
+******************************************************************************/
+typedef struct Event {
+  long type; /* One of the events defined above */
+  long time; /* time to simulate the event */
+  Ntk_Node_t *gate; /* node that needs to be simulated */
+  struct Event *horizontal; /* Pointer to other events in queue */
+  struct Event *vertical;
+  struct Event *bottom;
+} Event;
+
+
+/**Struct**********************************************************************
+
+  Synopsis    [Event queue.]
+
+  Description [Event queue. The event queue is a converging list data structure
+  used to access simulation events as the time progresses. It is based on the
+  concept of circular buffer (time wheel). Each slot in the wheel
+  represents a range of time values, i.e., a time interval.
+  Since there are events for different times in the same list, the list
+  is kept sorted. Each element in the list is itself a vertical list of
+  events. Events in the vertical list are all scheduled to be simulated at
+  a given time within the time interval mapped by the slot. The following 
+  shows the converging list data structure.
+
+  wheel      Vertial lists
+    |             |
+    v             v
+   -------      _____   _____  
+   |slot 0| --> |   |-->|   |-->         <---- Horizontal list
+   -------      -----   -----
+                  |       |
+                  v       v
+                -----  
+                |   |
+                ----- 
+                  |  
+                  v 
+	          .
+		  . 
+		  . 
+   -------      _____   _____  
+   |slot 1| --> |   |-->|   |-->         <---- Horizontal list
+   -------      -----   -----
+                  |       |
+                  v       v
+                -----   ----- 
+                |   |-->|   |-->
+                -----   -----
+                  |       |
+                  v       v
+	          .       .
+		  .       .
+		  .       .
+
+  All the horizontal lists point to an event, 'Threshold1', th1.
+  Event 'th1' points to a list of events that do not fit in the current time
+  interval represented by the wheel. Event 'thi' is the last event,
+  i.e., event at time infinity.
+
+  The events th1, th2, th3 and thi are 'control events' and not simulation
+  events. They help in managing event queue. For more info. please refer
+  to InitQueue in truesimMain.c.
+
+  freeList and nextFre aid in memory management.]
+
+  SeeAlso     [Event]
+
+******************************************************************************/
+typedef struct EventQueue {
+  Event *th1,*th2,*th3,*thi;
+  Event **wheel;
+  Event *current;
+  long time; /* Current time */
+  Event **freeList;
+  Event *nextFree;
+} EventQueue;
+
+
+/**Struct**********************************************************************
+
+  Synopsis [Structure to handle simulation needs of the network. This
+  data structure needs to be initialized for each node in the network.]
+
+  Description [Structure to handle simulation needs of the network. This
+  data structure needs to be initialized for each node in the network.]
+
+  SeeAlso     [Event]
+
+******************************************************************************/
+typedef struct TrueSim_t {
+  int depth; /* Node's topological depth */
+  float delay; /* Node delay */
+  char value; /* Node output value */
+  float prob; /* Prob. of being 1 */
+  float switching; /* Number of switchings */
+  float load; /* Load at the output of the node */
+  Event *event; /* Pointer back to the event. In the ideal case this should be
+		 * a member of the Ntk_Node_t data structure. */
+} TrueSim_t;
+
+
+/**Struct**********************************************************************
+
+  Synopsis [Data structure for the truesim package.]
+
+  Description [Data structure for the truesim package. It holds information
+  that remains unchanged during a given simulation run.]
+
+  SeeAlso     [TrueSim_t]
+
+******************************************************************************/
+typedef struct TruesimInfoStruct {
+  boolean trueDelay; /* TRUE for true delay simulation, FALSE for zero delay */
+  int repeatHeader; /* Print PI/PO names along with their values during
+		     * simulation */
+  int truesimVerbose; /* Verbosity level */
+  array_t *depthArray; /* Sorted array (according to top. depth) of array of
+			* network nodes */
+  st_table *nodeToSimTable; /* node --> TrueSim_t table */
+}Truesim_Info_t;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**Macro***********************************************************************
+
+   Synopsis     [Given a time, the macro returns the slot in the time wheel.]
+
+   SideEffects  [None]
+
+   SeeAlso      [TYPE, TIME, NEXT_HOR, NEXT_VER]
+
+******************************************************************************/
+
+#define WHEEL_POS(t)	(((t) >> LOG_HOR_LEN) & ((1 << LOG_WHEEL_SIZE) - 1))
+
+
+/**Macro***********************************************************************
+
+  Synopsis     [Allocate a new event or reuse a free event form the freelist.]
+
+  SideEffects  [nextFree is changed.]
+
+  SeeAlso      []
+
+******************************************************************************/
+
+#define EVENT_ALLOC(queue,new) \
+  if ((queue)->nextFree == NIL(Event)) { \
+       NewPage(queue); \
+  } \
+  new = (queue)->nextFree; \
+  (queue)->nextFree = (queue)->nextFree->horizontal
+
+/**Macro***********************************************************************
+
+  Synopsis     [Return memory associated with an event to the freeList.]
+
+  SideEffects  [nextFree is updated.]
+
+  SeeAlso      []
+
+******************************************************************************/
+
+#define EVENT_FREE(queue,old) \
+(old)->horizontal = (queue)->nextFree; \
+(queue)->nextFree = (old);
+
+/* Various macros to get details of an event */
+#define TYPE(_event) (_event)->type
+#define TIME(_event) (_event)->time
+#define NEXT_HOR(_event) (_event)->horizontal
+#define NEXT_VER(_event) (_event)->vertical
+#define NEXT_BOT(_event) (_event)->bottom
+#define GATE(_event) (_event)->gate
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void TruesimEndSimulation(void *data);
+EXTERN int TruesimSimulateNetwork(Ntk_Network_t *network, char *simFile, char *probFile, char *delayFile, char *dumpFile, boolean trueDelay, int genVectors, int N);
+EXTERN char TruesimEvaluateNode(Ntk_Node_t *node, graph_t *partition, bdd_manager *ddManager, st_table *nodeToSimTable);
+EXTERN st_table * TruesimNetworkReadSimTable(Ntk_Network_t *network);
+EXTERN array_t * TruesimNetworkReadDepthArray(Ntk_Network_t *network);
+EXTERN void TruesimInitializeActivityFields(Ntk_Network_t *network, st_table *nodeToSimTable);
+EXTERN bdd_t * TruesimComputeFaninMinterm(bdd_manager *ddManager, Ntk_Node_t *node, st_table *nodeToSimTable);
+EXTERN void TruesimPrintNameHeader(Ntk_Network_t *network);
+EXTERN void TruesimPrintNetworkNodeLogicState(Ntk_Network_t *network);
+EXTERN void TruesimReadDelayFile(Ntk_Network_t *network, char *delayFile, st_table *nodeToSimTable);
+EXTERN void TruesimWarmUpPatternSimulate(Ntk_Network_t *network, array_t *inputArray, char *vector);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _TRUESIMINT */
Index: vis_dev/vis-2.3/src/truesim/truesimMain.c
===================================================================
--- vis_dev/vis-2.3/src/truesim/truesimMain.c	(revision 14)
+++ vis_dev/vis-2.3/src/truesim/truesimMain.c	(revision 14)
@@ -0,0 +1,907 @@
+/**CFile***********************************************************************
+
+  FileName    [truesimMain.c]
+
+  PackageName [truesim]
+
+  Synopsis    [Routines to perform full delay simulation.]
+
+  Descriptin [Routines to perform full delay simulation. The main routine
+  implements a levelized two-pass event driven simulator.]
+
+  Author      [Balakrishna Kumthekar]
+
+  Copyright   [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "truesimInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+static long numEvents;
+
+extern int truesimVerbose;
+extern int truesimRptHeader;
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void InsertInputEvents(st_table *nodeToSimTable, EventQueue *queue, array_t *inputArray, char *vector);
+static void SinglePatternSimulate(Ntk_Network_t *network, EventQueue *queue);
+static void HouseKeeping(EventQueue *queue, Event *threshevent);
+static void InsertFanouts(Ntk_Node_t *node, st_table *fanoutTable);
+static void PerformSecondPass(Ntk_Network_t *network, EventQueue *queue, st_table *fanoutTable);
+static void ScheduleEvent(EventQueue *queue, Ntk_Node_t *node, TrueSim_t *sim, char value);
+static void RescheduleEvent(EventQueue *queue, Ntk_Node_t *node, TrueSim_t *sim, char value);
+static void CancelEvent(EventQueue *queue, TrueSim_t *sim);
+static void InsertInBin(Event **wheel, Event *event);
+static EventQueue * InitQueue(void);
+static void NewPage(EventQueue *queue);
+static enum st_retval stTrueSimFree(char *key, char *value, char *arg);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [This routine performs real delay pattern simulation.]
+
+  Description [This routine performs real delay pattern simulation. inputArray
+  is an array of PI names. patternArray is a character array of pattern
+  vectors. Pattern vectors are 0-1 bit-vectors whose length is equal to the
+  number of primary inputs of the circuit. The length of inpuArray and
+  patternArray should be equal.
+  
+  Successive patterns are applied to the circuit after the changes due
+  to a previous pattern vector settle down. ]
+
+  SideEffects [Simulation data structure associated with each network node is
+  changed.]
+
+  SeeAlso [Truesim_ZeroDelayPatternSimulate]
+
+******************************************************************************/
+int
+Truesim_RealDelayPatternSimulate(
+  Ntk_Network_t *network,
+  array_t *inputArray,
+  array_t *patternArray)
+{
+  Ntk_Node_t *node;
+  int numVectors = array_n(patternArray);
+  int i;
+  EventQueue *queue;
+  st_table *nodeToSimTable = TruesimNetworkReadSimTable(network);
+  lsGen gen;
+
+  if (nodeToSimTable == NIL(st_table)) {
+    (void) fprintf(vis_stderr,
+		   "** truesim error: Simulation structures not initialized\n");
+    (void) fprintf(vis_stderr,
+		   "** truesim error: Call Truesim_InitializeSimulation before ");
+    (void) fprintf(vis_stderr,"calling this function.\n");
+    return -1;
+  }
+
+  /* Initialize the converging list data structure */
+  queue = InitQueue();
+
+  /* Initialize node simulation data structures */
+  TruesimInitializeActivityFields(network,nodeToSimTable);
+
+  /* Warmup simulation. Simulate the first vector to initialize internal nodes
+     in the network. */
+  TruesimWarmUpPatternSimulate(network,inputArray,
+			       array_fetch(char *,patternArray,0));
+  
+  /* Performs simulation of all the vectors */
+  for (i = 1; i < numVectors; i++) {
+    char *stimulus;
+    stimulus = array_fetch(char *,patternArray,i);
+    InsertInputEvents(nodeToSimTable,queue,inputArray,stimulus);
+    SinglePatternSimulate(network,queue);
+
+    if (truesimVerbose) {
+      if (truesimRptHeader != -1) {
+	if (i % truesimRptHeader == 0) 
+	  TruesimPrintNameHeader(network);
+      }
+      TruesimPrintNetworkNodeLogicState(network);
+    }
+  }
+
+  /* Free the queue */
+  if (queue != NIL(EventQueue)) {
+    while (queue->freeList != NIL(Event *)) {
+      Event **next;
+      next = (Event **) queue->freeList[0];
+      FREE(queue->freeList);
+      queue->freeList = next;
+    }
+    FREE(queue->wheel);
+    FREE(queue);
+  }
+  
+  /* Update the statistics for each node */
+  Ntk_NetworkForEachNode(network,gen,node) {
+    TrueSim_t *sim;
+    if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
+      (void) fprintf(vis_stderr,
+		     "** truesim fatal:In Truesim_RealDelayPatternSimulate\n");
+      (void) fprintf(vis_stderr,"        Sim. structure missing for %s\n",
+		     Ntk_NodeReadName(node));
+      
+      assert(0);
+    }
+    /* Get the switching probability and the signal probability */
+    sim->switching /= ((float) array_n(patternArray));
+    sim->prob /= ((float) array_n(patternArray));
+  }
+
+  return 1;
+
+} /* End of Truesim_RealDelayPatternSimulate */
+
+
+/**Function********************************************************************
+
+  Synopsis [Initialize the info structure associated with truesim package.]
+
+  Description [Initialize the info structure associated with truesim
+  package. Every 'header' number of patterns simulated, a line
+  containing PI and PO names are output. In the absence of delay value
+  for a node (from nodeDelayTable or the delayFile), the fanout
+  count is used as the default delay value. Arrival times for PI are
+  assumed to be 0.
+
+  Simulation assumes that each node in the network has a local bdd associated
+  with it in the partition. This can be ensured by using 'total' as the
+  partition method.]
+
+  SideEffects [The info data structure is hooked to the network.]
+
+  SeeAlso [Truesim_QuitSimulation]
+
+******************************************************************************/
+void
+Truesim_InitializeSimulation(
+  Ntk_Network_t *network,
+  char *delayFile,
+  boolean truedelay,
+  int header,
+  int verbose,
+  st_table *nodeDelayTable)
+{
+  Truesim_Info_t *simInfo;
+  st_table *nodeToSimTable;
+  lsGen gen;
+  Ntk_Node_t *node;
+  TrueSim_t *sim;
+  float delay,load;
+  float *delayPtr;
+
+  delay = -1.0; /* To keep the compiler happy */
+  /* Allocate the Truesim_Info_t * structure */
+  simInfo = ALLOC(Truesim_Info_t,1);
+  Ntk_NetworkAddApplInfo(network,TRUESIM_NETWORK_APPL_KEY,
+			 (Ntk_ApplInfoFreeFn)TruesimEndSimulation,
+			 (void *)simInfo);
+  simInfo->depthArray = NIL(array_t);
+  simInfo->nodeToSimTable = NIL(st_table);
+
+  /* Allocate simulation structure for each node in the network and
+     put it in a table.*/
+  nodeToSimTable = st_init_table(st_ptrcmp,st_ptrhash);
+
+  if (delayFile) {
+    TruesimReadDelayFile(network,delayFile,nodeToSimTable);
+  } else { /* Read from nodeDelayTable */
+    Ntk_NetworkForEachNode(network,gen,node) {
+      sim = ALLOC(TrueSim_t,1);
+      /* I assume inputs to have zero delay. */
+      if (Ntk_NodeTestIsPrimaryInput(node)) {
+	delay = 0;
+      }
+      if (nodeDelayTable == NIL(st_table) ||
+	  !st_lookup(nodeDelayTable,(char *)node,&delayPtr)) {
+	if (Ntk_NodeTestIsPrimaryInput(node)) {
+	  load = (float) Ntk_NodeReadNumFanouts(node);
+	} else if (Ntk_NodeTestIsPrimaryOutput(node)){
+	  /* Sometimes primary outputs can fanout to other internal nodes */
+	  load = (float) Ntk_NodeReadNumFanouts(node);
+	  load = load ? load : 1.0;
+	  delay = load;
+	} else {
+	  delay = load = (float) Ntk_NodeReadNumFanouts(node);
+	}
+      } else { /* if you do find it */
+	delay = load = *delayPtr;
+      }
+      sim->delay = delay;
+      sim->load = load;
+      st_insert(nodeToSimTable, (char *)node, (char *)sim);
+    }
+  }
+  
+  /* Set the global variables truesimRptHeader, truesimVerbose */
+  simInfo->trueDelay = truedelay;
+  simInfo->repeatHeader = truesimRptHeader = header;
+  simInfo->truesimVerbose = truesimVerbose = verbose;
+  simInfo->nodeToSimTable = nodeToSimTable;
+  
+  /* Fill in depth field for each node */
+  Truesim_NetworkUpdateNodeTopologicalDepth(network);
+
+  return;
+} /* End of Truesim_InitializeSimulation */
+
+
+/**Function********************************************************************
+
+  Synopsis [Free the truesim info data structure.]
+
+  SideEffects [The info data structure attached to the network is freed.]
+
+  SeeAlso [optional]
+
+******************************************************************************/
+void
+Truesim_QuitSimulation(Ntk_Network_t *network)
+{
+  Ntk_NetworkFreeApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
+  
+} /* End of Truesim_QuitSimulation */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+   Synopsis           [Free memory associated with Truesim_Info_t]
+   
+   SideEffects        [None]
+   
+   SeeAlso            [Truesim_QuitSimulation]
+
+******************************************************************************/
+void
+TruesimEndSimulation(void *data)
+{
+  st_table *nodeToSimTable;
+  array_t *depthArray,*tempArray;
+  Truesim_Info_t *dataBody;
+  int i;
+  
+  nodeToSimTable = ((Truesim_Info_t *)data)->nodeToSimTable;
+  depthArray = ((Truesim_Info_t *)data)->depthArray;
+  
+  if (nodeToSimTable) {
+    st_foreach(nodeToSimTable,stTrueSimFree,NIL(char));
+    st_free_table(nodeToSimTable);
+  }
+
+  arrayForEachItem(array_t *,depthArray,i,tempArray) {
+    array_free(tempArray);
+  }
+  array_free(depthArray);
+  
+  dataBody = (Truesim_Info_t *)data;
+  FREE(dataBody);
+  
+} /* End of TruesimEndSimulation */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+   Synopsis [Insert input events, i.e., PI events.]
+
+   SideEffects [None]
+
+   SeeAlso []
+
+******************************************************************************/
+static void
+InsertInputEvents(
+  st_table *nodeToSimTable,
+  EventQueue *queue,		  
+  array_t *inputArray,
+  char *vector)
+{
+  Ntk_Node_t *node;
+  TrueSim_t *sim;
+  int i;
+  char prev;
+
+  arrayForEachItem(Ntk_Node_t *,inputArray,i,node) {
+    if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
+      (void) fprintf(vis_stderr,"** truesim fatal: In InsertInputEvents\n");
+      (void) fprintf(vis_stderr,"        Sim. structure missing for %s\n",
+		     Ntk_NodeReadName(node));
+      assert(0);
+    }
+    prev = sim->value;
+    if (prev != vector[i]) {
+      ScheduleEvent(queue,node,sim,vector[i]);
+    }
+  }
+  
+} /* End of InsertInputEvents */
+
+
+/**Function********************************************************************
+
+  Synopsis [Simulate all the events in the queue.]
+
+  Description [Simulate all the events in the queue.]
+
+  SideEffects [Events are freed when the events are executed.]
+
+  SeeAlso [optional]
+
+******************************************************************************/
+static void
+SinglePatternSimulate(
+  Ntk_Network_t *network,		      
+  EventQueue *queue)
+{
+  Event *currentEvent;
+  Event **wheel;
+  long currbin,halfPeriodBin;
+  Ntk_Node_t *gate;  /* Node being simulated/evaluated */
+  st_table *fanoutTable; /* Nodes in the fanout */
+  st_table *nodeToSimTable = TruesimNetworkReadSimTable(network);
+  TrueSim_t *simInfo;
+  long eventType;
+
+  /* No events to start with */
+  if (numEvents == 0)
+    return;
+
+  wheel = queue->wheel;
+  halfPeriodBin = WHEEL_POS(HALF_PERIOD - 1);
+
+  currbin = 0;
+
+  /* Find the first sim, th2, th3 event */ 
+  /* Events th2 and th3 are control events. They help in housekeeping of the
+     event queue. When a th2 event is reached, the time ranges for each slot in
+     the wheel is increased. The threshold events are different from the
+     simulation events in that they are not related to simulation. They help in
+     the timely update of the wheel. */
+  do {
+    fanoutTable = st_init_table(st_ptrcmp,st_ptrhash);
+
+    do { /* examine each bin */
+      currentEvent = wheel[currbin];
+      eventType = TYPE(currentEvent);	
+
+      switch (eventType) {
+      case SIM_EVENT_C :
+        /* Simply cancel the event as this is a cancel event */
+	wheel[currbin] = NEXT_VER(currentEvent); 
+	/* free current event and obtain next */
+	EVENT_FREE(queue, currentEvent);
+	numEvents--;
+	break;
+      case SIM_EVENT_0 : 	
+	wheel[currbin] = NEXT_VER(currentEvent); 
+	queue->time = TIME(currentEvent);
+	gate = GATE(currentEvent); 
+	if (!st_lookup(nodeToSimTable,(char *)gate,&simInfo)) {
+	  (void) fprintf(vis_stderr,"** truesim fatal: In case SIM_EVENT_0\n");
+	  (void) fprintf(vis_stderr,"        Sim. structure missing for %s\n",
+			 Ntk_NodeReadName(gate));
+
+	  assert(0);
+	}
+	(simInfo->switching)++;
+	simInfo->value = '0';
+	/* Collect the fanouts that may need to be scheduled. This is used for
+           the second pass */
+	InsertFanouts(gate,fanoutTable);
+	/* free current event and obtain next */
+	EVENT_FREE(queue, currentEvent);
+	simInfo->event = NIL(Event);
+	numEvents--;
+	break;
+      case SIM_EVENT_1 : 	
+	wheel[currbin] = NEXT_VER(currentEvent); 
+	queue->time = TIME(currentEvent);
+	gate = GATE(currentEvent);
+	if (!st_lookup(nodeToSimTable,(char *)gate,&simInfo)) {
+	  (void) fprintf(vis_stderr,"** truesim fatal: In case SIM_EVENT_1\n");
+	  (void) fprintf(vis_stderr,"        Sim. structure missing for %s\n",
+			 Ntk_NodeReadName(gate));
+	  assert(0);
+	}
+	(simInfo->switching)++;
+	simInfo->value = '1';
+	(simInfo->prob)++;
+	/* Collect the fanouts that may need to be scheduled. This is used for
+           the second pass */
+	InsertFanouts(gate,fanoutTable);				
+	/* free current event and obtain next */
+	EVENT_FREE(queue, currentEvent);
+	simInfo->event = NIL(Event);
+	numEvents--;
+	break;
+      case THRESHOLD_1 : 	
+	currbin++; 
+	currbin &= ((1 << LOG_WHEEL_SIZE) - 1);
+	break;
+      case THRESHOLD_2 : 	
+	HouseKeeping(queue, currentEvent);
+	currbin = halfPeriodBin + 1;
+	break;
+      case THRESHOLD_3 : 	
+	HouseKeeping(queue, currentEvent);
+	currbin = 0;
+	break;
+      default:
+	(void) fprintf(vis_stderr,"** truesim fatal: Unknown event %ld\n",
+		       eventType);
+	assert(0);
+      } 
+    } while (NEXT_BOT(currentEvent) != currentEvent);
+
+    if (truesimVerbose > 2) {
+      (void) fprintf(vis_stdout,"Simulation time tick %ld",queue->time);
+      TruesimPrintNetworkNodeLogicState(network);
+    }
+    
+    /* We are finished processing a vertical list. A vertical list has events
+       scheduled for the same time. Now perform the second pass of the
+       simulation. */
+    PerformSecondPass(network,queue,fanoutTable);
+    st_free_table(fanoutTable);
+  } while (numEvents > 0);
+
+  /* End of simulation for one pattern */
+  /* Reset the queue */
+  queue->current = NIL(Event);
+  queue->time = 0;
+  TIME(queue->th1) = PERIOD - 1;
+  TIME(queue->th2) = PERIOD - 1;
+  TIME(queue->th3) = PERIOD - 1;
+
+} /* End of SinglePatternSimulate */
+
+
+/**Function********************************************************************
+
+  Synopsis [This function is called when control events (th1,th2 and th3) are
+  encountered. The time frame represented in the queue is increased by half and
+  the time stamps on the control events are updated to reflect the same. Events
+  earlier beyond th1 are bow brought into the wheel.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static void
+HouseKeeping(
+  EventQueue *queue,
+  Event *threshevent)
+{
+  Event **wheel;
+  Event *event, *threshold1;
+  Event *temp;
+  long threshold1_time;
+
+  wheel = queue->wheel;
+
+  /* add T/2 to all threshold events */
+  threshold1 = queue->th1;
+  TIME(threshold1) += HALF_PERIOD;
+  TIME(queue->th2) += HALF_PERIOD;
+  TIME(queue->th3) += HALF_PERIOD;
+
+  threshold1_time = TIME(threshold1);
+  event = NEXT_HOR(threshold1);
+  while(TIME(event) <= threshold1_time) {
+    NEXT_HOR(threshold1) = NEXT_HOR(event);
+    temp = event;
+    while (NEXT_BOT(temp) != temp) {
+      InsertInBin(wheel,temp);
+      temp = NEXT_VER(temp);
+    }
+    InsertInBin(wheel,temp);
+    event = NEXT_HOR(threshold1);
+  }
+
+} /* End of HouseKeeping */
+
+
+/**Function********************************************************************
+
+  Synopsis [Insert fanouts of currently simulated node into a table.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static void
+InsertFanouts(
+  Ntk_Node_t *node,
+  st_table *fanoutTable)
+{
+  int i;
+  Ntk_Node_t *fanout;
+  
+  Ntk_NodeForEachFanout(node,i,fanout) {
+    st_insert(fanoutTable,(char *)fanout,(char *)0);
+  }
+
+} /* End of InsertFanouts */
+
+
+/**Function********************************************************************
+
+  Synopsis [Fanouts of currently simulated events are scheduled to be simulated
+  at a later time.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static void
+PerformSecondPass(
+  Ntk_Network_t *network,
+  EventQueue *queue,
+  st_table *fanoutTable)
+{
+  bdd_manager *ddManager = Ntk_NetworkReadMddManager(network);
+  graph_t *partition = Part_NetworkReadPartition(network);
+  st_table *nodeToSimTable = TruesimNetworkReadSimTable(network);
+  st_generator *stGen;
+  Ntk_Node_t *node,*dummy;
+  char next,prev;
+
+  st_foreach_item(fanoutTable,stGen,&node,&dummy) {
+    TrueSim_t *sim;
+
+    /* Lookup the simtable to extract the sim struct for the gate. */
+    if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
+      (void) fprintf(vis_stderr,"** truesim fatal: In PerformSecondPass\n");
+      (void) fprintf(vis_stderr,"        Sim. structure missing for %s\n",
+		     Ntk_NodeReadName(node));
+      assert(0);
+    }
+
+    next = TruesimEvaluateNode(node,partition,ddManager,
+			       nodeToSimTable);
+    prev = sim->value;
+    if (prev != next) {
+      /* Check if an event already exists. If true, then reschedule the event */
+      if (sim->event) {
+	RescheduleEvent(queue,node,sim,next);
+      } else {
+	ScheduleEvent(queue,node,sim,next);
+      }
+    } else {
+      /* Check if an event already exists. If true, then cancel that event */
+      if (sim->event)
+	CancelEvent(queue,sim);
+    }
+  }
+
+} /* End of PerformSecondPass */
+
+
+/**Function********************************************************************
+
+  Synopsis [Schedule an event.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static void
+ScheduleEvent(
+  EventQueue *queue,
+  Ntk_Node_t *node,
+  TrueSim_t *sim,
+  char value)
+{
+  Event *event;
+
+  EVENT_ALLOC(queue, event);
+  TIME(event) = queue->time + (long) sim->delay;
+  GATE(event) = node;
+  TYPE(event) = (value == '1') ? SIM_EVENT_1 : SIM_EVENT_0;
+  NEXT_HOR(event) = NIL(Event);
+  NEXT_VER(event) = NIL(Event);
+  NEXT_BOT(event) = NIL(Event);
+
+  InsertInBin(queue->wheel, event);
+
+  /* Cross pointer to the event, in case of cancellation or rescheduling */
+  sim->event = event;
+  numEvents++;
+
+} /* End of ScheduleEvent */
+
+
+/**Function********************************************************************
+
+  Synopsis [Reschedule an event.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static void
+RescheduleEvent(
+  EventQueue *queue,
+  Ntk_Node_t *node,
+  TrueSim_t *sim,
+  char value)
+{
+  Event *event;
+
+  event = sim->event;
+  TYPE(event) = SIM_EVENT_C;
+
+  ScheduleEvent(queue,node,sim,value);
+
+} /* End of RescheduleEvent */
+
+
+/**Function********************************************************************
+
+  Synopsis [Cancel an event.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static void
+CancelEvent(
+  EventQueue *queue,
+  TrueSim_t *sim)
+{
+  Event *event;
+
+  event = sim->event;
+  TYPE(event) = SIM_EVENT_C;
+
+  sim->event = NIL(Event);
+
+} /* End of CancelEvent */
+
+
+/**Function********************************************************************
+
+   Synopsis [Insert newly scheduled events to the event queue.]
+
+   Description [Insert newly scheduled events to the event queue. The time
+   stamp of the event is used to access the slot in the event table. If events
+   already exist at the event's time stamp, this event is inserted in a
+   vertical list.]
+
+   SideEffects [Event queue is updated]
+
+   SeeAlso [InsertInputEvents]
+
+******************************************************************************/
+static void
+InsertInBin(
+  Event **wheel,
+  Event *event)
+{
+  Event *prev,*curr;
+  long  pos;
+
+  pos = WHEEL_POS(TIME(event)); 
+
+  if (TIME(wheel[pos]) >= TIME(event)) { /* to insert as first element */
+    if (TIME(wheel[pos]) > TIME(event)) {
+      NEXT_BOT(event) = event;
+      NEXT_HOR(event) = wheel[pos];
+      NEXT_VER(event) = wheel[pos];
+      wheel[pos] = event;
+
+    } else {
+      NEXT_VER(event) = wheel[pos];
+      NEXT_BOT(event) = NEXT_BOT(NEXT_VER(event));
+      NEXT_HOR(event) = NEXT_HOR(wheel[pos]);
+      wheel[pos] = event;
+
+    }
+  } else {
+    prev = curr = wheel[pos];
+
+    /* Assumption : the last element in the converging list always has
+       a time greater than event. This is true by construction. */
+    while(TIME(curr) < TIME(event)) {
+      prev = curr;
+      curr = NEXT_HOR(curr);
+    }
+
+    if (TIME(curr) == TIME(event)) {
+      NEXT_VER(event) = curr;
+      NEXT_BOT(event) = NEXT_BOT(NEXT_VER(event));
+      NEXT_HOR(event) = NEXT_HOR(curr);
+      NEXT_HOR(prev) = event;
+      NEXT_VER(NEXT_BOT(prev)) = event;
+    } else {
+      NEXT_BOT(event) = event;
+      NEXT_HOR(event) = curr;
+      NEXT_VER(event) = curr;
+      NEXT_HOR(prev) = event;
+      NEXT_VER(NEXT_BOT(prev)) = event;
+    }
+  }	
+
+} /* End of InsertInBin */
+
+
+/**Function********************************************************************
+
+  Synopsis [Initialize the queue.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static EventQueue *
+InitQueue(void)
+{
+  EventQueue *queue; 
+  Event **wheel,*threshold; 
+  int i;
+
+  queue = ALLOC(EventQueue, 1); 
+  queue->wheel = ALLOC(Event *, WHEEL_SIZE); 
+  queue->current = NIL(Event);
+  queue->time = 0;
+  queue->freeList = NIL(Event *);
+  queue->nextFree = NIL(Event);;
+
+  /* Allocate control events, th1, th2 and th3 and thi (infinity)*/
+  EVENT_ALLOC(queue, threshold);
+  queue->thi = threshold;
+  TYPE(threshold)  = THRESHOLD_I;
+  TIME(threshold) = MAX_TIME;
+  NEXT_HOR(threshold) = NIL(Event);
+  NEXT_VER(threshold) = NIL(Event);
+  NEXT_BOT(threshold) = threshold;
+
+  EVENT_ALLOC(queue, threshold);
+  queue->th1 = threshold;
+  TYPE(threshold)  = THRESHOLD_1;
+  TIME(threshold) = PERIOD -1;
+  NEXT_HOR(threshold) = queue->thi;
+  NEXT_VER(threshold) = queue->thi;
+  NEXT_BOT(threshold) = threshold;
+
+  EVENT_ALLOC(queue, threshold);
+  queue->th2 = threshold;
+  TYPE(threshold)  = THRESHOLD_2;
+  TIME(threshold) = PERIOD -1;
+  NEXT_HOR(threshold) = queue->th1;
+  NEXT_VER(threshold) = queue->th1;
+  NEXT_BOT(threshold) = threshold;
+
+  EVENT_ALLOC(queue, threshold);
+  queue->th3 = threshold;
+  TYPE(threshold)  = THRESHOLD_3;
+  TIME(threshold) = PERIOD-1;
+  NEXT_HOR(threshold) = queue->th1;
+  NEXT_VER(threshold) = queue->th1;
+  NEXT_BOT(threshold) = threshold;
+
+  wheel = queue->wheel;
+  threshold = queue->th1;
+  for (i = 0; i < WHEEL_SIZE; i++) {
+    wheel[i] = threshold;
+  }
+
+  wheel[WHEEL_POS(HALF_PERIOD - 1)] =  queue->th2;
+  wheel[WHEEL_POS(PERIOD - 1)] =  queue->th3;
+
+  return (queue);
+
+} /* End of InitQueue */
+
+
+/**Function********************************************************************
+
+  Synopsis [Increase memory for the freeList.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static void
+NewPage(EventQueue *queue)
+{
+  Event **mem,*list;
+  int i;
+
+  mem = (Event **) ALLOC(char,MEM_CHUNK * sizeof(Event) + sizeof(Event *));
+
+  mem[0] = (Event *) queue->freeList;
+  queue->freeList = mem;
+
+  list = (Event *) &mem[1];
+
+  i = 0;
+  do {
+    list[i].horizontal = &list[i + 1];
+  } while (++i < MEM_CHUNK -1);
+
+  list[MEM_CHUNK - 1].horizontal = NIL(Event);
+
+  queue->nextFree = list;
+
+} /* End of NewPage */
+
+
+/**Function********************************************************************
+
+  Synopsis [Free Truesim_t data structure stored in an st_table.]
+
+  SideEffects [None]
+
+  SeeAlso [None]
+
+******************************************************************************/
+static enum st_retval
+stTrueSimFree(
+  char *key,
+  char *value,
+  char *arg)
+{
+  TrueSim_t *sim;
+  sim = (TrueSim_t *)value;
+
+  if (sim)
+    FREE(sim);
+
+  return (ST_CONTINUE);
+} /* End of stTrueSimFree */
+
Index: vis_dev/vis-2.3/src/truesim/truesimSim.c
===================================================================
--- vis_dev/vis-2.3/src/truesim/truesimSim.c	(revision 14)
+++ vis_dev/vis-2.3/src/truesim/truesimSim.c	(revision 14)
@@ -0,0 +1,155 @@
+/**CFile***********************************************************************
+
+  FileName    [truesimSim.c]
+
+  PackageName [truesim]
+
+  Synopsis    [Top-level routine to perform simulation.]
+
+  Author      [Balakrishna Kumthekar]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "truesimInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/* Global variable from truesimCmd.c. */
+extern int truesimRptHeader;
+extern int truesimVerbose;
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis           [Entry routine to perform network simulation.]
+
+  Description        [Entry routine to perform network simulation.
+  simFile provides bit-vectors for simulation. In the absence of
+  simFile, probFile provides the primary input probabilites using with
+  random bit-vector patterns are generated. delayFile has the
+  <delay,load> pair for each node in the circuit. If simFile is not
+  specified and random vectors are generated, those vectors are dumped
+  to dumpFile. If genVectors is 0, no vectors are generated.
+  
+  Some of the arguments are redundant, but they are kept here for
+  historical reasons.]
+
+  SideEffects        [required]
+
+******************************************************************************/
+int
+TruesimSimulateNetwork(
+  Ntk_Network_t *network,
+  char *simFile,
+  char *probFile,
+  char *delayFile,
+  char *dumpFile,
+  boolean trueDelay,
+  int genVectors,
+  int N)
+{
+  array_t *inputArray,*patternArray;
+  int i,status;
+  char *str;
+  
+  /* inputArray stores the names of primary input nodes and patternArray stores
+     the simulation vectors as char strings. One could use bit packing, but
+     this is fast and simple. */
+  inputArray = array_alloc(Ntk_Node_t *,0);
+  patternArray = array_alloc(char *,0);
+
+  if (genVectors == 0) { /* Read simulation file */
+    Truesim_ReadSimulationVectors(network,simFile,inputArray,patternArray);
+  } else { /* Generate random vectors */
+    array_t *probArray;
+    int numInputs;
+    
+    probArray = array_alloc(float,0);
+    Truesim_ReadInputProbabilities(network,probFile,inputArray,probArray);
+
+    if(array_n(probArray) == 0) {
+      array_free(inputArray);
+      array_free(patternArray);
+      array_free(probArray);
+      return 0;
+    }
+    numInputs = array_n(inputArray);
+    Truesim_GenerateRandomVectors(network,probArray,patternArray,
+				  numInputs,N);
+    array_free(probArray);
+
+    /* Output pattern vectors */
+    if (dumpFile) {
+      Truesim_DumpSimulationVectors(network,inputArray,patternArray,dumpFile);
+    }
+  }
+
+  /* Initialize the simulation data structures */
+  Truesim_InitializeSimulation(network,delayFile,trueDelay,truesimRptHeader,
+			       truesimVerbose,NIL(st_table));
+
+  /* Now perform true delay simulation or zero delay simulation
+     according to 'trueDelay' */  
+  if (trueDelay) { /* Perform event driven simulation */
+    status = Truesim_RealDelayPatternSimulate(network,inputArray,patternArray);
+  } else { /* Perform zero-delay simulation */
+    status = Truesim_ZeroDelayPatternSimulate(network,inputArray,patternArray);
+  }
+
+  /* End the simulation */
+  Truesim_QuitSimulation(network);
+
+  /* Free the space used to store the input nodes */
+  array_free(inputArray);
+  /* Free the pattern vectors */
+  arrayForEachItem(char *, patternArray,i,str) {
+    FREE(str);
+  }
+  array_free(patternArray);
+
+  return status;
+
+} /* End of TruesimSimulateNetwork */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
Index: vis_dev/vis-2.3/src/truesim/truesimUtil.c
===================================================================
--- vis_dev/vis-2.3/src/truesim/truesimUtil.c	(revision 14)
+++ vis_dev/vis-2.3/src/truesim/truesimUtil.c	(revision 14)
@@ -0,0 +1,1509 @@
+/**CFile***********************************************************************
+
+  FileName    [truesimUtil.c]
+
+  PackageName [truesim]
+
+  Synopsis    [Utility functions for the truesim package.]
+
+  Description [Utility functions for the truesim package. Various
+  functions include: to compute the topological depth of a node in
+  a network, file IO for reading and dumping bit-vector patterns for
+  simulation, generating random patterns, and API for accessing
+  simulation information for nodes in the network.]
+
+  Author      [Balakrishna Kumthekar]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "truesimInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define MAX_LENGTH 20000 /* Max. length of a string while reading a file */
+#define UNASSIGNED_DEPTH -1 /* Unassigned depth for a node */
+#define TOKENS " \t\n" /* For parsing delay-load file */
+#define DEFAULT_PROB 0.5
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+extern int truesimVerbose;
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void GetInputs(char *buffer, Ntk_Network_t *network, array_t *inputArray);
+static void GetPatternVectors(FILE *fp, int vecLen, array_t *patternArray);
+static long NodeComputeDepth(Ntk_Node_t * node);
+static long NodeReadDepth(Ntk_Node_t * node);
+static void NodeSetDepth(Ntk_Node_t * node, long depth);
+static enum st_retval stFloatFree(char *key, char *value, char *arg);
+static float computeProbabilityRecur(Ntk_Network_t *network, st_table *nodeToSimTable, st_table *seenTable, bdd_node *bddNode);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+   Synopsis [Update topological depth of nodes in the network. This
+   can be used when the network changes structurally.]
+   
+   SideEffects [None]
+   
+   SeeAlso [Truesim_NetworkComputeNodeDepths]
+
+******************************************************************************/
+void
+Truesim_NetworkUpdateNodeTopologicalDepth(
+  Ntk_Network_t *network)
+{
+  array_t *depthArray,*levelArray;
+  Ntk_Node_t *node;
+  st_table *nodeToSimTable;
+  Truesim_Info_t *simInfo;
+  int i,j;
+  
+  simInfo = (Truesim_Info_t *)
+    Ntk_NetworkReadApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
+  nodeToSimTable = simInfo->nodeToSimTable;
+  depthArray = simInfo->depthArray;
+
+  if (depthArray) {
+    arrayForEachItem(array_t *,depthArray,i,levelArray) {
+      array_free(levelArray);
+    }
+    array_free(depthArray);
+  }
+  
+  depthArray = Truesim_NetworkComputeNodeDepths(network);
+  simInfo->depthArray = depthArray;
+  arrayForEachItem(array_t *,depthArray,i,levelArray) {
+    arrayForEachItem(Ntk_Node_t *,levelArray,j,node) {
+      TrueSim_t *sim;
+      st_lookup(nodeToSimTable,(char *)node,&sim);
+      sim->depth = i;
+    }
+  }
+
+  return;
+} /* End of Truesim_NetworkUpdateNodeTopologicalDepth */
+
+
+/**Function********************************************************************
+
+  Synopsis [Reads the input probabilities of primary inputs from a given file.]
+
+  SideEffects [inputArray and probArray are updated.]
+  
+  SeeAlso [Truesim_GeneratePrimaryInputProbs]
+
+******************************************************************************/
+void
+Truesim_ReadInputProbabilities(
+  Ntk_Network_t *network,
+  char *probFile,
+  array_t *inputArray,
+  array_t *probArray)
+{
+  char str[MAX_LENGTH];
+  float prob;
+  FILE *fp;
+  Ntk_Node_t *node;
+
+  if(probFile == 0 || probFile[0] == '\0') {
+    (void) fprintf(vis_stderr,
+		   "** truesim warning: Probability file was not specified.\n");
+    return;    
+  }
+  /* Read the probabilities. */
+  if ((fp = Cmd_FileOpen(probFile,"r",NIL(char *),1)) == NIL(FILE)) {
+    lsGen gen;
+    (void) fprintf(vis_stderr,
+		   "** truesim warning: Could not open %s for reading.\n", probFile);
+    (void) fprintf(vis_stderr,
+		   "** truesim warning: Using probability as 0.5 for all inputs.\n");
+    Ntk_NetworkForEachPrimaryInput(network,gen,node) {
+      array_insert_last(float,probArray,DEFAULT_PROB);
+      array_insert_last(Ntk_Node_t *,inputArray,node);      
+    }
+  } else {
+    while (fscanf(fp,"%s %f\n",str,&prob) != EOF) {
+      node = Ntk_NetworkFindNodeByName(network,str);
+      if (!node || !Ntk_NodeTestIsPrimaryInput(node)) {
+	(void) fprintf(vis_stderr,
+		       "** truesim warning: No PI with name %s. Ignored.\n",str);
+      } else {
+	if (prob > 1.0 || prob < 0.0) {
+	  (void) fprintf(vis_stderr,
+			 "** truesim warning: %s has invalid prob. %f\n",
+			 str,prob);
+	  (void) fprintf(vis_stderr,
+			"** truesim warning: Assuming 0.5 instead\n");
+	  prob = DEFAULT_PROB;
+	}
+	array_insert_last(float,probArray,prob);
+	array_insert_last(Ntk_Node_t *,inputArray,node);
+      }
+    }
+    fclose(fp);
+  }
+} /* End of Truesim_ReadInputProbabilities */
+
+
+/**Function********************************************************************
+
+  Synopsis [Generate random probabilities for PI. The probabilites are written
+  to probFile.]
+
+  SideEffects [The probabilites are written to probFile.]
+
+  SeeAlso [Truesim_ReadInputProbabilities, Truesim_GenerateRandomVectors]
+
+******************************************************************************/
+void
+Truesim_GeneratePrimaryInputProbs(
+  Ntk_Network_t *network,
+  char *probFile)
+{
+  FILE *fp;
+  Ntk_Node_t *node;
+  lsGen gen;
+
+  if ((fp = Cmd_FileOpen(probFile,"w",NIL(char *),1)) == NIL(FILE)) {
+    fprintf(vis_stderr,"** truesim error: Cannot open %s for writing\n",probFile);
+    return;
+  }
+  Ntk_NetworkForEachPrimaryInput(network,gen,node) {
+    fprintf(fp,"%s %f\n",
+	    Ntk_NodeReadName(node),
+	    ((double)util_random()/(double)(MODULUS1 - 2)));
+  }
+  fclose(fp);
+
+} /* End of Truesim_GeneratePrimaryInputProbs */
+
+
+/**Function********************************************************************
+
+  Synopsis [Read simulation vectors from simFile.]
+
+  Description [Read simulation vectors from simFile. The input file looks 
+  like below:
+
+  .i c n d o e p f q g r h s i t j u k a l b m
+  .s
+  0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 1 1 1 1 ;
+  0 1 1 0 0 0 0 1 0 1 1 0 1 1 1 1 0 0 0 0 1 ;
+  0 0 1 0 0 0 0 1 0 1 0 0 0 1 0 1 0 0 0 0 1 ;
+  0 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 0 1 0 0 1 ;
+
+  The .i statement specifies the primary inputs of the network. The patterns
+  start after .s key word. Each vector is a space separated list of bits and
+  ends in a semi-colon. The length of any vector should be equal to the number
+  of signals specified in the .i statement. A line starting with # is a
+  comment. The format is simple but strict and so few checks are performed.
+  
+  inputArray is the array of Ntk_Node_t for primary inputs. patternArray
+  is the array of bit-vectors to be simulated.]
+
+  SideEffects [inputArray and patternArray are updated.]
+
+  SeeAlso [Truesim_ReadInputProbabilities]
+
+******************************************************************************/
+int
+Truesim_ReadSimulationVectors(
+  Ntk_Network_t *network,
+  char *simFile,
+  array_t *inputArray,
+  array_t *patternArray)
+{
+
+  char buffer[MAX_LENGTH];
+  FILE *fp;
+  boolean readInputs;
+  
+  fp = Cmd_FileOpen(simFile,"r",NIL(char *),1);
+  if (fp == NIL(FILE)) {
+    (void) fprintf(vis_stderr,
+		   "** truesim error: Cannot open %s for reading sim. vectors.\n",
+		   simFile);
+    return 0;
+  }
+
+  readInputs = TRUE;
+  while (fgets(buffer,MAX_LENGTH - 1,fp) != NULL) {
+    if (buffer[0] == '#' || buffer[0] == '\n') 
+      continue;
+    if (buffer[0] == '.' && buffer[1] == 'i') {
+      if (!readInputs) {
+	(void) fprintf(vis_stderr,
+		       "** spfd error: .i statement encountered earlier.\n");
+	fclose(fp);
+	return 0;
+      }
+      GetInputs(buffer,network,inputArray);
+      readInputs = FALSE;
+    } else if (buffer[0] == '.' && buffer[1] == 's') {
+	int vecLen = array_n(inputArray);
+	if (!vecLen) {
+	  /* Error reading pattern file. */
+	  fclose(fp);
+	  return 0;
+	}
+	GetPatternVectors(fp,vecLen,patternArray);
+	break;
+    } else {
+      (void) fprintf(vis_stdout,
+		     "** spfd warning: Skipping %s\n",buffer);
+    }
+  } /* End of while */
+  fclose(fp);
+
+  return 1;
+} /* End of Truesim_ReadSimulationVectors */
+
+
+/**Function********************************************************************
+
+  Synopsis [Generate random vectors. ]
+
+  Description [Generate random vectors. probArray specifies the signal
+  probabilities for PIs of the network. patternArray stores the individual
+  vectors. numInputs is the number of primary inputs in the network. 'N'
+  patterns are generated.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+array_t *
+Truesim_GenerateRandomVectors(
+  Ntk_Network_t *network,
+  array_t *probArray,
+  array_t *patternArray,
+  int numInputs,
+  int N)
+{
+  char *strPtr;
+  float prob;
+  double randomValue;
+  int i,j;
+
+  /* We generate N+1 vectors as the first one is an initialization vector */
+  for (i = 0; i <= N; i++) {
+    strPtr = ALLOC(char,numInputs+1);
+    strPtr[numInputs] = '\0';
+    for (j = 0; j < numInputs; j++) {
+      prob = array_fetch(float,probArray,j);
+      randomValue = ((double)util_random()/(double)(MODULUS1 - 2));
+      if ((double) prob < randomValue)
+	strPtr[j] = '0';
+      else 
+        strPtr[j] = '1';
+    }
+    array_insert_last(char *,patternArray,strPtr);
+  }
+  return patternArray;
+} /* End of Truesim_GenerateRandomVectors */
+
+
+/**Function********************************************************************
+
+  Synopsis [Output vectors to outFile.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+void
+Truesim_DumpSimulationVectors(
+  Ntk_Network_t *network,			  
+  array_t *inputArray,
+  array_t *patternArray,
+  char *outFile)
+{
+  FILE *fp;
+  int i; unsigned int j;
+  char *str;
+  Ntk_Node_t *node;
+  
+  if ((fp = Cmd_FileOpen(outFile,"w",NIL(char *),1)) == NIL(FILE)) {
+    fprintf(vis_stderr,
+	    "** truesim error: Could not open %s for writing\n",outFile);
+    return;
+  }
+  /* Print the intput array */
+  fprintf(fp,".i ");
+  arrayForEachItem(Ntk_Node_t *,inputArray,i,node) {
+    fprintf(fp,"%s ",Ntk_NodeReadName(node));
+  }
+  fprintf(fp,"\n");
+
+  /* Print the pattern vectors */
+  fprintf(fp,".s\n");
+  arrayForEachItem(char *,patternArray,i,str) {
+    for (j = 0; j < strlen(str); j++)
+      fprintf(fp,"%c ",str[j]);
+    fprintf(fp,";\n");
+  }
+  fclose(fp);
+} /* End of Truesim_DumpSimulationVectors */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the depth of each node in the network.]
+
+  Description [Computes the depth of each node in the network. The
+  depth of a node is defined inductively: PI and nodes with no
+  inputs, have depth 0. Otherwise, the depth of a node is 1 more than
+  the maximum depth over the node's fanins.  Intuitively, the depth of
+  a node is the length of the longest (backward) path from the node to
+  a latch, primary input, pseudo input, or constant.
+
+  The returned array is an array of array_t * of nodes. For ex.
+
+  (n1,n2) (n4,n7,n9) (n3,n8) (n6,n5). 
+  
+  Nodes, n1 and n2 have depth of 0, n4,n7, and n9 have a depth of 1, and
+  so on. ]
+
+  SideEffects [Uses undef field of Ntk_Node_t.]
+
+  SeeAlso     []
+
+******************************************************************************/
+array_t *
+Truesim_NetworkComputeNodeDepths(
+  Ntk_Network_t *network)
+{
+  lsList rootList;
+  lsGen       gen;
+  Ntk_Node_t *node;
+  long maxDepth;
+  int i;
+  array_t *tempArray,*depthArray;
+  long noDepthCount = 0;
+
+  rootList = Ntk_NetworkReadPrimaryOutputs(network);
+  
+  /* Initialize the depth of each node to unassigned.  */
+  Ntk_NetworkForEachNode(network, gen, node) {
+    NodeSetDepth(node, UNASSIGNED_DEPTH);
+  }
+
+  /* Start the recursive computation from each root.  */
+  lsForEachItem(rootList, gen, node) {
+    (void) NodeComputeDepth(node);
+  }
+
+  /* Now segregate the nodes according to their depth */
+  /* Find the maximum depth */
+  maxDepth = UNASSIGNED_DEPTH;
+  lsForEachItem(rootList,gen,node) {
+    long depth = NodeReadDepth(node);
+    if (depth > maxDepth)
+      maxDepth = depth;
+  }
+  /* Put the nodes in an array according to their depths. */
+  depthArray = array_alloc(array_t *, maxDepth+1);
+  for (i = 0; i < maxDepth+1; i++) {
+    tempArray = array_alloc(Ntk_Node_t *, 0);
+    array_insert_last(array_t *,depthArray,tempArray);
+  }
+  Ntk_NetworkForEachNode(network,gen,node) {
+    long depth = NodeReadDepth(node);
+    array_t *temp = NIL(array_t);
+
+    if (depth != UNASSIGNED_DEPTH) {
+      temp = array_fetch(array_t *,depthArray,depth);
+      array_insert_last(Ntk_Node_t *,temp,node);
+    }else
+      noDepthCount++;
+  }
+  if (noDepthCount > 0)
+    fprintf(vis_stderr, "Truesim Warning: %ld nodes have no computed depth.\n",
+	    noDepthCount);
+
+  return depthArray;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns topological depth of a node.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+int
+Truesim_NetworkReadNodeDepth(
+  Ntk_Network_t *network,
+  Ntk_Node_t *node)
+{
+  Truesim_Info_t *simInfo;
+  st_table *nodeToSimTable;
+  TrueSim_t *sim;
+  
+  simInfo = (Truesim_Info_t *)
+    Ntk_NetworkReadApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
+  nodeToSimTable = simInfo->nodeToSimTable;
+
+  if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
+    return TRUESIM_ERROR_VALUE;
+  } else {
+    return sim->depth;
+  }
+  
+} /* End of Truesim_NetworkReadNodeDepth */
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns a node's signal probability.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+float
+Truesim_NetworkReadNodeProbability(
+  Ntk_Network_t *network,
+  Ntk_Node_t *node)
+{
+  Truesim_Info_t *simInfo;
+  st_table *nodeToSimTable;
+  TrueSim_t *sim;
+  
+  simInfo = (Truesim_Info_t *)
+    Ntk_NetworkReadApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
+  nodeToSimTable = simInfo->nodeToSimTable;
+
+  if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
+    return (float) TRUESIM_ERROR_VALUE;
+  } else {
+    return sim->prob;
+  }
+  
+} /* End of Truesim_NetworkReadNodeProbability */
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns a node's switching probability.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+float
+Truesim_NetworkReadNodeSwitchingProb(
+  Ntk_Network_t *network,
+  Ntk_Node_t *node)
+{
+  Truesim_Info_t *simInfo;
+  st_table *nodeToSimTable;
+  TrueSim_t *sim;
+  
+  simInfo = (Truesim_Info_t *)
+    Ntk_NetworkReadApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
+  nodeToSimTable = simInfo->nodeToSimTable;
+
+  if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
+    return (float) TRUESIM_ERROR_VALUE;
+  } else {
+    return sim->switching;
+  }
+  
+} /* End of Truesim_NetworkReadNodeSwitchingProb */
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns a node's load.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+float
+Truesim_NetworkReadNodeLoad(
+  Ntk_Network_t *network,
+  Ntk_Node_t *node)
+{
+  Truesim_Info_t *simInfo;
+  st_table *nodeToSimTable;
+  TrueSim_t *sim;
+  
+  simInfo = (Truesim_Info_t *)
+    Ntk_NetworkReadApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
+  nodeToSimTable = simInfo->nodeToSimTable;
+
+  if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
+    return (float) TRUESIM_ERROR_VALUE;
+  } else {
+    return sim->load;
+  }
+  
+} /* End of Truesim_NetworkReadNodeLoad */
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns a node's delay.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+float
+Truesim_NetworkReadNodeDelay(
+  Ntk_Network_t *network,
+  Ntk_Node_t *node)
+{
+  Truesim_Info_t *simInfo;
+  st_table *nodeToSimTable;
+  TrueSim_t *sim;
+  
+  simInfo = (Truesim_Info_t *)
+    Ntk_NetworkReadApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
+  nodeToSimTable = simInfo->nodeToSimTable;
+
+  if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
+    return (float) TRUESIM_ERROR_VALUE;
+  } else {
+    return sim->delay;
+  }
+  
+} /* End of Truesim_NetworkReadNodeDelay */
+
+
+/**Function********************************************************************
+
+  Synopsis [Set a node's load.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+boolean
+Truesim_NetworkSetNodeLoad(
+  Ntk_Network_t *network,
+  Ntk_Node_t *node,
+  float load)
+{
+  Truesim_Info_t *simInfo;
+  st_table *nodeToSimTable;
+  TrueSim_t *sim;
+  
+  simInfo = (Truesim_Info_t *)
+    Ntk_NetworkReadApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
+  if (!simInfo)
+    goto error;
+  
+  nodeToSimTable = simInfo->nodeToSimTable;
+  if (!nodeToSimTable)
+    goto error;
+  
+  if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
+    goto error;
+  } else {
+    sim->load = load;
+  }
+  return TRUE;
+
+ error:
+  (void) fprintf(vis_stderr,
+		 "** truesim error: Network not initialized for simulation.\n");
+  (void) fprintf(vis_stderr,
+		 "** truesim error: Call Truesim_InitializeSimulation.\n");
+  return FALSE;
+  
+} /* End of Truesim_NetworkSetNodeLoad */
+
+
+/**Function********************************************************************
+
+  Synopsis [Set a node's delay.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+boolean
+Truesim_NetworkSetNodeDelay(
+  Ntk_Network_t *network,
+  Ntk_Node_t *node,
+  float delay)
+{
+  Truesim_Info_t *simInfo;
+  st_table *nodeToSimTable;
+  TrueSim_t *sim;
+  
+  simInfo = (Truesim_Info_t *)
+    Ntk_NetworkReadApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
+  if (!simInfo)
+    goto error;
+  
+  nodeToSimTable = simInfo->nodeToSimTable;
+  if (!nodeToSimTable)
+    goto error;
+  
+  if (!st_lookup(nodeToSimTable,node,&sim)) {
+    goto error;
+  } else {
+    sim->delay = delay;
+  }
+  return TRUE;
+
+ error:
+  (void) fprintf(vis_stderr,
+		 "** truesim error: Network not initialized for simulation.\n");
+  (void) fprintf(vis_stderr,
+		 "** truesim error: Call Truesim_InitializeSimulation.\n");
+  return FALSE;
+  
+} /* End of Truesim_NetworkSetNodeDelay */
+
+
+/**Function********************************************************************
+
+  Synopsis [Set a node's static probability.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+boolean
+Truesim_NetworkSetNodeStaticProb(
+  Ntk_Network_t *network,
+  Ntk_Node_t *node,
+  float prob)
+{
+  Truesim_Info_t *simInfo;
+  st_table *nodeToSimTable;
+  TrueSim_t *sim;
+  
+  simInfo = (Truesim_Info_t *)
+    Ntk_NetworkReadApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
+  if (!simInfo)
+    goto error;
+  
+  nodeToSimTable = simInfo->nodeToSimTable;
+  if (!nodeToSimTable)
+    goto error;
+  
+  if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
+    goto error;
+  } else {
+    sim->prob = prob;
+  }
+  return TRUE;
+
+ error:
+  (void) fprintf(vis_stderr,
+		 "** truesim error: Network not initialized for simulation.\n");
+  (void) fprintf(vis_stderr,
+		 "** truesim error: Call Truesim_InitializeSimulation.\n");
+  return FALSE;
+  
+} /* End of Truesim_NetworkSetNodeStaticProb */
+
+
+/**Function********************************************************************
+
+  Synopsis [Set a node's switching (transition) probability.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+boolean
+Truesim_NetworkSetNodeSwitchingProb(
+  Ntk_Network_t *network,
+  Ntk_Node_t *node,
+  float switching)
+{
+  Truesim_Info_t *simInfo;
+  st_table *nodeToSimTable;
+  TrueSim_t *sim;
+  
+  simInfo = (Truesim_Info_t *)
+    Ntk_NetworkReadApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
+  if (!simInfo)
+    goto error;
+  
+  nodeToSimTable = simInfo->nodeToSimTable;
+  if (!nodeToSimTable)
+    goto error;
+  
+  if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
+    goto error;
+  } else {
+    sim->switching = switching;
+  }
+  return TRUE;
+
+ error:
+  (void) fprintf(vis_stderr,
+		 "** truesim error: Network not initialized for simulation.\n");
+  (void) fprintf(vis_stderr,
+		 "** truesim error: Call Truesim_InitializeSimulation.\n");
+  return FALSE;
+  
+} /* End of Truesim_NetworkSetNodeSwitchingProb */
+
+
+/**Function********************************************************************
+
+  Synopsis [Given a BDD of a network node, compute it's probability. This
+  function assumes that the variables in the support of the BDD belong to the
+  network and those corresponding nodes have their signal probabilites set.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+float
+Truesim_BddNodeComputeProbability(
+  Ntk_Network_t *network,
+  bdd_node *func)
+{
+  bdd_manager *ddManager = Ntk_NetworkReadMddManager(network);
+  Truesim_Info_t *simInfo;
+  st_table *nodeToSimTable;
+  float prob,*dummy;
+  st_table *table;
+  bdd_node *one,*zero;
+  
+  simInfo = (Truesim_Info_t *)
+    Ntk_NetworkReadApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
+  nodeToSimTable = simInfo->nodeToSimTable;
+
+  one = bdd_read_one(ddManager);
+  zero = bdd_read_logic_zero(ddManager);
+  
+  if (func == zero)
+    return 0.0;
+  if (func == one)
+    return 1.0;
+
+  table = st_init_table(st_ptrcmp,st_ptrhash);
+  dummy = ALLOC(float,1);
+  *dummy = 1.0;
+  st_insert(table,(char *)one,(char *)dummy);
+
+  prob = computeProbabilityRecur(network,nodeToSimTable,table,func);
+  st_foreach(table,stFloatFree,NIL(char));
+  st_free_table(table);
+
+  return prob;
+  
+} /* End of Truesim_BddNodeComputeProbability */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis [Evaluate a node given the state of its fanin.]
+
+  Description [Evaluate a node given the state of its fanin. For
+  example, if the function at 'node' is y = a + b and node 'a' has
+  a value '0' and node 'b' has value '1', (due to propagation of
+  bit-vectors during simulation), we evaluate the node 'y' to have a
+  value '1'. ]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+char 
+TruesimEvaluateNode(
+  Ntk_Node_t *node,
+  graph_t *partition,
+  bdd_manager *ddManager,
+  st_table *nodeToSimTable)
+{
+  bdd_t *faninBdd,*nodeBdd,*tempBdd;
+  vertex_t *vertex;
+  Mvf_Function_t *nodeMvf;
+  char next;
+  
+  /* Compute the cube for the fanin of node. For ex. if y = a + b, and a =
+  '1' and b = '0', the cube faninBdd is ab' */
+  faninBdd = TruesimComputeFaninMinterm(ddManager,node,nodeToSimTable);
+  vertex = Part_PartitionFindVertexByMddId(partition,
+					   Ntk_NodeReadMddId(node));
+  nodeMvf = Part_VertexReadFunction(vertex);
+  nodeBdd = array_fetch(bdd_t *,nodeMvf,1);
+
+  /* Evaluate the node */
+  tempBdd = bdd_cofactor(nodeBdd,faninBdd);
+  next = bdd_is_tautology(tempBdd,TRUE) ? '1' : '0';
+
+  bdd_free(tempBdd);
+  bdd_free(faninBdd);
+  
+  return next;
+  
+} /* End of TruesimEvaluateNode */
+
+
+/**Function********************************************************************
+
+  Synopsis [Read the node to simulation structure table.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+st_table *
+TruesimNetworkReadSimTable(
+  Ntk_Network_t *network)
+{
+  Truesim_Info_t *simInfo;
+
+  simInfo = (Truesim_Info_t *)
+    Ntk_NetworkReadApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
+
+  return simInfo->nodeToSimTable;
+  
+} /* End of TruesimNetworkReadSimTable */
+
+
+/**Function********************************************************************
+
+  Synopsis [Read the depthArray of the network.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+array_t *
+TruesimNetworkReadDepthArray(Ntk_Network_t *network)
+{
+  Truesim_Info_t *simInfo;
+
+  simInfo = (Truesim_Info_t *)
+    Ntk_NetworkReadApplInfo(network,TRUESIM_NETWORK_APPL_KEY);
+  return simInfo->depthArray;
+  
+}
+
+
+/**Function********************************************************************
+
+  Synopsis [Initialize the Truesim_t structure for each node in the network.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+void
+TruesimInitializeActivityFields(
+  Ntk_Network_t *network,			 
+  st_table *nodeToSimTable)
+{
+  Ntk_Node_t *node;
+  lsGen gen;
+
+  Ntk_NetworkForEachNode(network,gen,node) {
+    TrueSim_t *sim;
+    if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
+      (void) fprintf(vis_stderr,"** truesim fatal: In TruesimInitializeActitivyFields\n");
+      assert(0);
+    }
+    sim->value = '0';
+    sim->prob = 0.0;
+    sim->switching = 0.0;
+    sim->event = NIL(Event);
+  }
+} /* End of TruesimInitializeActivityFields */
+
+
+/**Function********************************************************************
+
+  Synopsis [Returns a BDD minterm for a node based on the state of the
+  node's fanin.]
+
+  Description [[Returns a BDD minterm for a node based on the state of
+  the node's fanin. For ex. if y = a + b, and a = '1' and b = '0',
+  the minterm is the BDD of ab'.  ] 
+  
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+bdd_t *
+TruesimComputeFaninMinterm(
+  bdd_manager *ddManager,
+  Ntk_Node_t *node,
+  st_table *nodeToSimTable)
+{
+  int numFanin = Ntk_NodeReadNumFanins(node);
+  int *phase;
+  bdd_node **vars,*temp;
+  Ntk_Node_t *fanin;
+  TrueSim_t *sim;
+  int i;
+
+  vars = ALLOC(bdd_node *,numFanin);
+  phase = ALLOC(int,numFanin);
+  Ntk_NodeForEachFanin(node,i,fanin) {
+    int id;
+
+    if (!st_lookup(nodeToSimTable,(char *)fanin,&sim)) {
+      (void) fprintf(vis_stderr,"** truesim fatal: In TruesimComputeFaninMinterm\n");      
+      assert(0);
+    }
+    id = Ntk_NodeReadMddId(fanin);
+    vars[i] = bdd_bdd_ith_var(ddManager,id);
+    phase[i] = (sim->value == '1') ? 1:0;
+  }
+  temp = bdd_bdd_compute_cube(ddManager,vars,phase,numFanin);
+  bdd_ref(temp);
+
+  FREE(phase);
+  FREE(vars);
+
+  return (bdd_construct_bdd_t(ddManager,temp));
+
+} /* End of TruesimComputeFaninMinterm */
+
+
+/**Function********************************************************************
+
+  Synopsis [Print PI/PO names for better readability of simulation output.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+void
+TruesimPrintNameHeader(Ntk_Network_t *network)
+{
+  lsGen gen;
+  Ntk_Node_t *node;
+
+  /* Print PIs first */
+  Ntk_NetworkForEachPrimaryInput(network,gen,node) {
+    (void) fprintf(vis_stdout,"%s ",Ntk_NodeReadName(node));
+  }
+
+  if (truesimVerbose > 3) {
+    (void) fprintf(vis_stdout," -- ");
+    /* Print internal nodes next */
+    Ntk_NetworkForEachNode(network,gen,node) {
+      if (!Ntk_NodeTestIsPrimaryInput(node) &&
+	  !Ntk_NodeTestIsPrimaryOutput(node)) {
+	(void) fprintf(vis_stdout,"%s ",Ntk_NodeReadName(node));
+      }
+    }
+  }
+  
+  /* Print POs last */
+  (void) fprintf(vis_stdout," -- ");
+  Ntk_NetworkForEachPrimaryOutput(network,gen,node) {
+    (void) fprintf(vis_stdout,"%s ",Ntk_NodeReadName(node));
+  }
+  (void) fprintf(vis_stdout,"\n");
+
+  return ;
+  
+} /* End of TruesimPrintNameHeader  */
+
+
+/**Function********************************************************************
+
+  Synopsis [Print the logic state of network nodes.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+void
+TruesimPrintNetworkNodeLogicState(Ntk_Network_t *network)
+{
+  st_table *nodeToSimTable;
+  TrueSim_t *sim;
+  lsGen gen;
+  Ntk_Node_t *node;
+
+  nodeToSimTable = TruesimNetworkReadSimTable(network);
+
+  /* Print PIs first */
+  Ntk_NetworkForEachPrimaryInput(network,gen,node) {
+    if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
+      (void) fprintf(vis_stderr,
+		     "** truesim fatal: In TruesimPrintNetworkNodeLogicState\n");
+      assert(0);
+    }
+    (void) fprintf(vis_stdout,"%c ",sim->value);
+  }
+
+  if (truesimVerbose > 3) {
+    (void) fprintf(vis_stdout," -- ");
+    /* Print internal nodes next */
+    Ntk_NetworkForEachNode(network,gen,node) {
+      if (!Ntk_NodeTestIsPrimaryInput(node) &&
+	  !Ntk_NodeTestIsPrimaryOutput(node)) {
+	if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
+	  (void) fprintf(vis_stderr,
+			 "** truesim fatal: In TruesimPrintNetworkNodeLogicState\n");
+	  assert(0);
+	}
+	(void) fprintf(vis_stdout,"%c ",sim->value);
+      }
+    }
+  }
+
+  /* Print POs last */
+  (void) fprintf(vis_stdout," -- ");
+  Ntk_NetworkForEachPrimaryOutput(network,gen,node) {
+    if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
+      (void) fprintf(vis_stderr,
+		     "** truesim fatal: In TruesimPrintNetworkNodeLogicState\n");
+      assert(0);
+    }
+    (void) fprintf(vis_stdout,"%c ",sim->value);
+  }
+  (void) fprintf(vis_stdout,"\n");
+
+  return ;
+  
+} /* End of TruesimPrintNodeLogicState  */
+
+
+/**Function********************************************************************
+
+  Synopsis [Read delay and load values from a given file. The format is
+  
+  nodeName delay load
+  
+  The format is strict and few checks are performed. A line starting
+  with # is considered a comment. Delay and load values are specified
+  one per line.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+void
+TruesimReadDelayFile(
+  Ntk_Network_t *network,
+  char *delayFile,
+  st_table *nodeToSimTable)
+{
+  char buffer[MAX_LENGTH], *ptr;
+  FILE *fp;
+  lsGen gen;
+  TrueSim_t *sim;
+  Ntk_Node_t *node;
+
+  fp = Cmd_FileOpen(delayFile,"r",NIL(char *),1);
+  while (fgets(buffer,MAX_LENGTH - 1,fp) != NULL) {
+    if (buffer[0] == '#' || buffer[0] == '\n') 
+      continue;
+    if (truesimVerbose > 10) {
+      (void) fprintf(vis_stdout,"%s",buffer);
+    }
+    ptr = strtok(buffer,TOKENS);
+    node = Ntk_NetworkFindNodeByName(network,ptr);
+    if (!node) {
+      (void) fprintf(vis_stderr, "** truesim warning: %s not in the network\n",
+		     ptr);
+      (void) fprintf(vis_stderr, "** truesim warning: Values ignored ...\n");
+      continue;
+    }
+    sim = ALLOC(TrueSim_t,1);
+    ptr = strtok(NIL(char),TOKENS);
+    if (ptr) {
+      sim->delay = atof(ptr);
+    }
+    ptr = strtok(NIL(char),TOKENS);
+    if (ptr) {
+      sim->load = atof(ptr);
+    }
+    st_insert(nodeToSimTable, (char *)node, (char *)sim);
+    if (truesimVerbose > 10) {
+      (void) fprintf(vis_stdout,"%s %f %f\n",Ntk_NodeReadName(node),
+		     sim->delay,sim->load);
+    }
+  }
+
+  /* Now check that all the nodes have load and delay values. If a
+     node delay/load value is not initialized, set it to default. */
+
+  Ntk_NetworkForEachNode(network,gen,node) {
+    if (!st_lookup(nodeToSimTable,(char *)node, &sim)) {
+      sim = ALLOC(TrueSim_t,1);
+      sim->delay = 1.0;
+      sim->load = 0.0;
+      st_insert(nodeToSimTable, (char *)node, (char *)sim);
+    }
+    if (sim->delay == 0.0)
+      sim->delay = 1.0;
+    /* if (Ntk_NodeTestIsPrimaryInput(node))
+       sim->delay = 0.0; */
+  }
+  fclose(fp);
+  return;
+} /* End of TruesimReadDelayFile */
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Read PI names from the string.]
+
+  Description [Read PI names from the string. This function is called
+  in Truesim_ReadSimulationVectors. ] 
+
+  SideEffects [Primary input nodes are returned in inputArray.]
+
+  SeeAlso [GetPatternVectors]
+
+******************************************************************************/
+static void
+GetInputs(
+  char *buffer,
+  Ntk_Network_t *network,
+  array_t *inputArray)
+{
+  char internalBuf[MAX_LENGTH];
+  long i,index;
+  Ntk_Node_t *node;
+
+  index = 2;
+  while (buffer[index] != '\0') {
+    if (buffer[index] == ' ' ||
+	buffer[index] == '\t' ||
+	buffer[index] == '\n') {
+      index++;
+      continue;
+    }
+    i = 0;
+    while (buffer[index] != ' ' && buffer[index] != '\t'
+	   && buffer[index] != '\n') {
+      internalBuf[i] = buffer[index];
+      i++;
+      index++;
+    } /* End of while */
+    if (i > 0); {
+      internalBuf[i] = '\0';
+      node = Ntk_NetworkFindNodeByName(network,internalBuf);
+      if (node)
+      	array_insert_last(Ntk_Node_t *,inputArray,node);
+      else {
+	(void) fprintf(vis_stderr,
+	               "** truesim error: %s not found in the circuit.\n", 
+		       internalBuf);
+      }
+      index++;
+    }
+  } /* End of while */
+} /* End of GetInputs */
+
+
+/**Function********************************************************************
+
+  Synopsis [Read the pattern vectors from the simulation file.]
+
+  Description [Read the pattern vectors from the simulation file. This
+  function is called in Truesim_ReadSimulationVectors. The length of the
+  vectors specified in the file should be of vecLen.]
+
+  SideEffects [The bit-vectors are returned in patternArray.]
+
+  SeeAlso [GetInputs]
+
+******************************************************************************/
+static void
+GetPatternVectors(
+  FILE *fp,
+  int vecLen,
+  array_t *patternArray)
+{
+  char buffer[MAX_LENGTH];
+  char internalBuf[MAX_LENGTH];
+  char *str;
+  int index,i,j;
+  boolean skip;
+
+  while (fgets(buffer,MAX_LENGTH - 1,fp) != NULL) {
+    index = i = 0;
+    if (buffer[0] == '\n' ||
+	buffer[0] == '#')
+      continue;
+    while (buffer[index] != '\0') {
+      if (buffer[index] == ' ' ||
+	  buffer[index] == ';' ||
+	  buffer[index] == '\n') {
+	index++;
+	continue;
+      }
+      internalBuf[i] = buffer[index];
+      i++;
+      index++;
+    }
+    if (i > 0) {
+      internalBuf[i] = '\0';
+      /* Ascertain that internalBuf has only '0's and '1's. */
+      skip = FALSE;      j = 0;
+      while (internalBuf[j] != '\0') {
+	if ((internalBuf[j] != '0') && (internalBuf[j] != '1')) {
+	  skip = TRUE;
+	  break;
+	}
+	j++;
+      }
+      if (skip) {
+	(void) fprintf(vis_stdout,
+		       "** spfd warning: Invalid vector < %s > is ignored.\n",
+		       internalBuf);
+      } else if ((unsigned) vecLen != strlen(internalBuf)) {
+	(void) fprintf(vis_stdout,
+		       "** spfd warning: Length < %ld > of < %s > incorrect.\n",
+		       (long) strlen(internalBuf), internalBuf);
+	(void) fprintf(vis_stdout,
+		       "** spfd warning: Ignoring < %s > .\n",internalBuf);
+      } else {
+	str = util_strsav(internalBuf);
+	array_insert_last(char *,patternArray,str);
+      }
+    }
+  }
+} /* End of GetPatternVectors */
+
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the depth of a node.]
+
+  SideEffects [Changes the undef field of the node.]
+
+  SeeAlso     [NetworkComputeNodeDepths]
+
+******************************************************************************/
+
+/**Function********************************************************************
+
+  Synopsis    [Computes the depth of a node.]
+
+  SideEffects [Changes the undef field of the node.]
+
+  SeeAlso     [NetworkComputeNodeDepths]
+
+******************************************************************************/
+static long
+NodeComputeDepth(
+  Ntk_Node_t * node)
+{
+  long depth = NodeReadDepth(node);
+
+  /* If the node's depth has already been computed (i.e. it's not
+   unassigned), then just return it below.  If it's unassigned, then
+   recursively compute it.  */
+  if (depth == UNASSIGNED_DEPTH) {
+    if (Ntk_NodeTestIsCombInput(node) || Ntk_NodeTestIsConstant(node)) {
+      /* PI and nodes with no fanins, get depth 0. This is the
+        terminal case of recursion.  */
+      depth = 0;
+    } else {
+      int i;
+      Ntk_Node_t *fanin;
+      /* Compute the depth of each fanin node in the support of node,
+        and maintain the maximum.  We start depth at 0 for max
+        calculation.  */
+      depth = 0;
+      Ntk_NodeForEachFanin(node, i, fanin) {  
+        long faninDepth = NodeComputeDepth(fanin);
+
+        depth = (depth > faninDepth) ? depth:faninDepth;
+      }
+      
+      /* The depth of node is one more than the max depths of its
+       fanins.  */
+      depth++;
+    }
+
+    /* Store the depth.  */
+    NodeSetDepth(node, depth);
+  }
+  
+  return depth;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Reads the depth of a node.]
+
+  SideEffects [None]
+
+  SeeAlso     [NodeSetDepth] 
+
+******************************************************************************/
+static long
+NodeReadDepth(
+  Ntk_Node_t * node)
+{
+  return ((long) Ntk_NodeReadUndef(node));
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the depth of a node.]
+
+  SideEffects [Changes the undef field of the node.]
+
+  SeeAlso     [NodeReadDepth]
+
+******************************************************************************/
+static void
+NodeSetDepth(
+  Ntk_Node_t * node,
+  long depth)
+{
+  Ntk_NodeSetUndef(node, (void *) depth);
+}
+
+/**Function********************************************************************
+
+  Synopsis [Free float pointed in an st_table.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static enum st_retval
+stFloatFree(
+  char *key,
+  char *value,
+  char *arg)
+{
+  float *dummy;
+  dummy = (float *)value;
+
+  if (dummy)
+    FREE(dummy);
+
+  return (ST_CONTINUE);
+
+} /* End of stFloatFree */
+
+
+/**Function********************************************************************
+
+  Synopsis [Recursive function of Truesim_BddNodeComputeProbability]
+
+  Description [Compute the probability of a function represented by
+  ADD. For example, Probability of a Boolean function f being 1 is given
+  as follows:
+  
+  Prob(f(x) == 1) = Prob(x) * Prob(f_x) + (1.0 - Prob(x)) * Prob(f_x') 
+  
+  The probability values for the support of f is stored in
+  nodeToSimTable. ]
+
+  SideEffects [None]
+
+  SeeAlso [Truesim_BddNodeComputeProbability]
+
+******************************************************************************/
+static float
+computeProbabilityRecur(
+  Ntk_Network_t *network,
+  st_table *nodeToSimTable,
+  st_table *seenTable,
+  bdd_node *bddNode)
+{
+  float value,*probability,*dummy;
+  float valueL,valueR;
+  Ntk_Node_t *networkNode;
+  TrueSim_t *sim;
+  bdd_node *N,*Nv,*Nnv;
+
+  N = bdd_regular(bddNode);
+
+  if (st_lookup(seenTable,(char *)N,&dummy)) {
+    return ((N != bddNode) ? 1.0 - *dummy : *dummy);
+  }
+  
+  Nv = bdd_bdd_T(N);
+  Nnv = bdd_bdd_E(N);
+
+  /* Recur on the children */
+  valueR = computeProbabilityRecur(network,nodeToSimTable,seenTable,Nv);
+  valueL = computeProbabilityRecur(network,nodeToSimTable,seenTable,Nnv);
+
+  networkNode = Ntk_NetworkFindNodeByMddId(network,bdd_node_read_index(N));
+  if (st_lookup(nodeToSimTable,(char *)networkNode,&sim)) {
+    value = sim->prob;
+    probability = ALLOC(float,1);
+    *probability = value * valueR + (1.0 - value) * valueL;
+  } else {
+    fprintf(vis_stderr,
+	    "** truesim error: Could not find prob. for node %s\n",
+	    Ntk_NodeReadName(networkNode));
+    return (float) TRUESIM_ERROR_VALUE;
+  }
+
+  st_insert(seenTable,(char *)N,(char *)probability);
+
+  return ((N != bddNode) ? 1.0 - *probability : *probability);
+
+} /* End of computeProbabilityRecur */
Index: vis_dev/vis-2.3/src/truesim/truesimZero.c
===================================================================
--- vis_dev/vis-2.3/src/truesim/truesimZero.c	(revision 14)
+++ vis_dev/vis-2.3/src/truesim/truesimZero.c	(revision 14)
@@ -0,0 +1,257 @@
+/**CFile***********************************************************************
+
+  FileName    [truesimZero.c]
+
+  PackageName [truesim]
+
+  Synopsis    [Routines to perform zero-delay vector simulation.]
+
+  Author      [Balakrishna KumthekarK] <kumtheka@colorado.edu>]
+
+  Copyright [This file was created at the University of Colorado at Boulder.
+  The University of Colorado at Boulder makes no warranty about the suitability
+  of this software for any purpose.  It is presented on an AS IS basis.]
+
+******************************************************************************/
+
+#include "truesimInt.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/* Global variables used in truesim package. */
+extern int truesimVerbose;
+extern int truesimRptHeader;
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static void SetInputValues(array_t *inputArray, char *vector, st_table *nodeToSimTable);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis [This function performs BDD based zero-delay vector simulation.]
+
+  Description [This function performs BDD based zero-delay vector
+  simulation. The nodes in the network are simulated according to their
+  topological depth. ]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+int
+Truesim_ZeroDelayPatternSimulate(
+  Ntk_Network_t *network,
+  array_t *inputArray,
+  array_t *patternArray)
+{
+  graph_t *partition;
+  TrueSim_t *sim;
+  st_table *nodeToSimTable;
+  Ntk_Node_t *node;
+  array_t *depthArray;
+  bdd_manager *ddManager = Ntk_NetworkReadMddManager(network);
+  lsGen gen;
+  char prev,next;
+  long numVectors = array_n(patternArray);
+  int maxDepth;
+  int i,j,k;
+  
+  nodeToSimTable = TruesimNetworkReadSimTable(network);
+  if (nodeToSimTable == NIL(st_table)) {
+    (void) fprintf(vis_stderr,
+		   "** truesim error: Simulation structures not initialized\n");
+    (void) fprintf(vis_stderr,
+		   "** truesim error: Call Truesim_InitializeSimulation before ");
+    (void) fprintf(vis_stderr,"calling this function.\n");
+    return -1;
+  }
+
+  depthArray = TruesimNetworkReadDepthArray(network);
+  maxDepth = array_n(depthArray);
+  
+  partition = Part_NetworkReadPartition(network);
+
+  /* Initialize the prob and switching fields of the simulation structure for
+     each node in the network. */
+  TruesimInitializeActivityFields(network,nodeToSimTable);
+
+  /* Warm up simulation */
+  TruesimWarmUpPatternSimulate(network,inputArray,
+				  array_fetch(char *,patternArray,0));
+
+  for (i = 1; i < numVectors; i++) {
+    char *vector;
+    vector = array_fetch(char *,patternArray,i);
+    /* Set the input nodes to the input pattern vector. Do not update
+       the switching field of the sim structure if it is the first
+       vector */
+    SetInputValues(inputArray,vector,nodeToSimTable);
+    for (j = 1; j < maxDepth; j++) {
+      array_t *nodeList;
+      
+      nodeList = array_fetch(array_t *,depthArray,j);
+      arrayForEachItem(Ntk_Node_t *,nodeList,k,node) {
+	TrueSim_t *sim;
+
+	st_lookup(nodeToSimTable,(char *)node,&sim);
+	next =  TruesimEvaluateNode(node,partition,ddManager,
+				    nodeToSimTable);
+	if (i != 0) {
+	  prev = sim->value;
+	  if (prev != next)
+	    (sim->switching)++;
+	}
+	sim->value = next;
+	if (next == '1')
+	  (sim->prob)++;
+      }
+    }
+    if (truesimVerbose) {
+      if (truesimRptHeader != -1) {
+	if (i % truesimRptHeader == 0) 
+	  TruesimPrintNameHeader(network);
+      }
+      TruesimPrintNetworkNodeLogicState(network);
+    }
+  }
+
+  /* Update the statistics for each node */
+  Ntk_NetworkForEachNode(network,gen,node) {
+    if (!st_lookup(nodeToSimTable,(char *)node,&sim)) {
+      (void) fprintf(vis_stderr,
+		     "** truesim fatal: In Truesim_ZeroDelayPatternSimulate\n");
+      assert(0);
+    }
+    sim->switching /= ((float) array_n(patternArray));
+    sim->prob /= ((float) array_n(patternArray));
+  }
+
+  return 1;
+
+} /* End of Truesim_ZeroDelayPatternSimulate */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis [Simulates a single pattern to initialize initial state of network
+  nodes.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+void
+TruesimWarmUpPatternSimulate(
+  Ntk_Network_t *network,
+  array_t *inputArray,
+  char *vector)
+{
+  graph_t *partition;
+  st_table *nodeToSimTable;
+  array_t *depthArray;
+  Ntk_Node_t *node;
+  bdd_manager *ddManager = Ntk_NetworkReadMddManager(network);
+  long maxDepth;
+  int j,k;
+  
+  nodeToSimTable = TruesimNetworkReadSimTable(network);
+
+  depthArray = TruesimNetworkReadDepthArray(network);
+  maxDepth = array_n(depthArray);
+  
+  partition = Part_NetworkReadPartition(network);
+  /* Set the input nodes to the input pattern vector. Do not update
+     the switching field of the sim structure if it is the first
+     vector */
+  SetInputValues(inputArray,vector,nodeToSimTable);
+  for (j = 1; j < maxDepth; j++) {
+    array_t *nodeList;
+    
+    nodeList = array_fetch(array_t *,depthArray,j);
+    arrayForEachItem(Ntk_Node_t *,nodeList,k,node) {
+      TrueSim_t *sim;
+      
+      st_lookup(nodeToSimTable,(char *)node,&sim);
+      sim->value =  TruesimEvaluateNode(node,partition,ddManager,
+					nodeToSimTable);
+    }
+  }
+
+  /* Print network status */
+  if (truesimVerbose) {
+    TruesimPrintNameHeader(network);
+    TruesimPrintNetworkNodeLogicState(network);
+  }
+
+  return ;
+
+} /* End of TruesimWarmUpPatternSimulate */
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+/**Function********************************************************************
+
+  Synopsis [Initialize the vector pattern for PI.]
+
+  Description [Initialize the vector pattern for PI.]
+
+  SideEffects [None]
+
+  SeeAlso []
+
+******************************************************************************/
+static void
+SetInputValues(
+  array_t *inputArray,
+  char *vector,
+  st_table *nodeToSimTable)
+{
+  Ntk_Node_t *node;
+  TrueSim_t *sim;
+  int i;
+  char prev;
+
+  arrayForEachItem(Ntk_Node_t *,inputArray,i,node) {
+    st_lookup(nodeToSimTable,(char *)node,&sim);
+    prev = sim->value;
+    if (prev != vector[i])
+      (sim->switching)++;
+    sim->value = vector[i];
+    if (vector[i] == '1')
+      (sim->prob)++;
+  }
+} /* End of SetInputValues */
+
Index: vis_dev/vis-2.3/src/tst/tst.c
===================================================================
--- vis_dev/vis-2.3/src/tst/tst.c	(revision 14)
+++ vis_dev/vis-2.3/src/tst/tst.c	(revision 14)
@@ -0,0 +1,187 @@
+/**CFile***********************************************************************
+
+  FileName    [tst.c]
+
+  PackageName [tst]
+
+  Synopsis    [Test package initialization, ending, and the command test.]
+
+  Author      [Originated from SIS.]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "tstInt.h"
+
+static char rcsid[] UNUSED = "$Id: tst.c,v 1.6 2002/09/10 06:14:37 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int CommandTest(Hrc_Manager_t ** hmgr, int argc, char ** argv);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Initializes the test package.]
+
+  SideEffects []
+
+  SeeAlso     [Tst_End]
+
+******************************************************************************/
+void
+Tst_Init(void)
+{
+  /*
+   * Add a command to the global command table.  By using the leading
+   * underscore, the command will be listed under "help -a" but not "help".
+   */
+  Cmd_CommandAdd("_tst_test", CommandTest, /* doesn't changes_network */ 0);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Ends the test package.]
+
+  SideEffects []
+
+  SeeAlso     [Tst_Init]
+
+******************************************************************************/
+void
+Tst_End(void)
+{
+  /*
+   * For example, free any global memory (if any) which the test package is
+   * responsible for.
+   */
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Implements the _tst_test command.]
+
+  CommandName [_tst_test]
+
+  CommandSynopsis [template for implementing commands]
+
+  CommandArguments [\[-h\] \[-v\]]
+  
+  CommandDescription [This command does nothing useful.  It merely serves as a
+  template for the implementation of new commands.<p>
+
+  Command options:<p>  
+
+  <dl>
+  <dt> -h
+  <dd> Print the command usage.
+  </dl>
+
+  <dt> -v
+  <dd> Verbose mode.
+  </dl>
+  ]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+CommandTest(
+  Hrc_Manager_t ** hmgr,
+  int  argc,
+  char ** argv)
+{
+  int            c;
+  int            verbose = 0;              /* default value */
+
+  /*
+   * Parse command line options.
+   */
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "vh")) != EOF) {
+    switch(c) {
+      case 'v':
+        verbose = 1;
+        break;
+      case 'h':
+        goto usage;
+      default:
+        goto usage;
+    }
+  }
+
+  if (verbose) {
+    (void) fprintf(vis_stdout, "The _tst_test command does nothing useful.\n");
+  }
+
+  return 0;		/* normal exit */
+
+  usage:
+  (void) fprintf(vis_stderr, "usage: _tst_test [-h] [-v]\n");
+  (void) fprintf(vis_stderr, "   -h\t\tprint the command usage\n");
+  (void) fprintf(vis_stderr, "   -v\t\tverbose\n");
+  return 1;		/* error exit */
+}
+
+
+
+
Index: vis_dev/vis-2.3/src/tst/tst.h
===================================================================
--- vis_dev/vis-2.3/src/tst/tst.h	(revision 14)
+++ vis_dev/vis-2.3/src/tst/tst.h	(revision 14)
@@ -0,0 +1,82 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [tst.h]
+
+  PackageName [tst]
+
+  Synopsis    [Test package illustrating VIS conventions.]
+
+  Description [This is a test package illustrating how to create a package in
+  VIS. It shows how to create commands, and illustrates naming conventions.]
+
+  Author      [Originated from SIS.]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: tst.h,v 1.2 2002/09/09 00:12:06 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _TST
+#define _TST
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "vm.h"
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void Tst_Init(void);
+EXTERN void Tst_End(void);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _TST */
Index: vis_dev/vis-2.3/src/tst/tst.make
===================================================================
--- vis_dev/vis-2.3/src/tst/tst.make	(revision 14)
+++ vis_dev/vis-2.3/src/tst/tst.make	(revision 14)
@@ -0,0 +1,4 @@
+CSRC += tst.c
+HEADERS += tst.h tstInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/tst/tstInt.h
===================================================================
--- vis_dev/vis-2.3/src/tst/tstInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/tst/tstInt.h	(revision 14)
@@ -0,0 +1,81 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [tstInt.h]
+
+  PackageName [tst]
+
+  Synopsis    [Internal declarations.]
+
+  Author      [Originated from SIS.]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: tstInt.h,v 1.2 2001/03/12 22:28:37 jinh Exp $]
+
+******************************************************************************/
+
+#ifndef _TSTINT
+#define _TSTINT
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include "tst.h"
+#include "cmd.h"
+#include <string.h>
+
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Structure declarations                                                    */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _TSTINT */
+
+
Index: vis_dev/vis-2.3/src/var/var.h
===================================================================
--- vis_dev/vis-2.3/src/var/var.h	(revision 14)
+++ vis_dev/vis-2.3/src/var/var.h	(revision 14)
@@ -0,0 +1,149 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [var.h]
+
+  PackageName [var]
+
+  Synopsis    [Multi-valued variables.]
+
+  Description [This package contains the data structure for multi-valued
+  variables. For each variable in a BLIF-MV network, this structure is
+  created. The information contained in this structure for a variable is
+  the name, the type (PI,PO,PS,NS etc), the range size, the list of symbolic
+  value names if any, and the encoding of a variable. Any variable can be
+  categorized either to an enumerative variable or a symbolic variable. 
+  Enumerative variables are variables which take values from [0,...,n-1\],
+  where n is the range of the variable, while symbolic variables are
+  variables which take symbolic values (e.g., [red,blue,green\]). ]
+
+  SeeAlso     []
+
+  Author      [Yuji Kukimoto]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: var.h,v 1.3 1998/05/19 22:04:27 hsv Exp $]
+
+******************************************************************************/
+
+#ifndef _VAR
+#define _VAR
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+typedef struct VarVariableStruct Var_Variable_t;
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+#include "hrc.h"
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN boolean Var_VariableAddRangeInfo(Var_Variable_t * var, int numValues, array_t * symValArray);
+EXTERN boolean Var_VariableExpandRange(Var_Variable_t *var, int numValues);
+EXTERN boolean Var_VariableReduceRange(Var_Variable_t *var, int numValues);
+EXTERN Var_Variable_t * Var_VariableAlloc(Hrc_Node_t *hnode, char *name);
+EXTERN void Var_VariableFree(Var_Variable_t *var);
+EXTERN Var_Variable_t * Var_VariableDup(Var_Variable_t *var, Hrc_Node_t *hnode);
+EXTERN char * Var_VariableReadName(Var_Variable_t *var);
+EXTERN boolean Var_VariableTestIsPI(Var_Variable_t *var);
+EXTERN boolean Var_VariableTestIsPO(Var_Variable_t *var);
+EXTERN boolean Var_VariableTestIsPS(Var_Variable_t *var);
+EXTERN boolean Var_VariableTestIsNS(Var_Variable_t *var);
+EXTERN boolean Var_VariableTestIsSI(Var_Variable_t *var);
+EXTERN boolean Var_VariableTestIsSO(Var_Variable_t *var);
+EXTERN boolean Var_VariableTestIsSymbolic(Var_Variable_t *var);
+EXTERN boolean Var_VariableTestIsEnumerative(Var_Variable_t *var);
+EXTERN boolean Var_VariableTestIsValueInRange(Var_Variable_t *var, int value);
+EXTERN int Var_VariableReadNumValues(Var_Variable_t *var);
+EXTERN int Var_VariableReadNumFanoutTables(Var_Variable_t *var);
+EXTERN void Var_VariableIncrementNumFanoutTables(Var_Variable_t *var);
+EXTERN void Var_VariableResetNumFanoutTables(Var_Variable_t* var);
+EXTERN char * Var_VariableReadSymbolicValueFromIndex(Var_Variable_t *var, int i);
+EXTERN int Var_VariableReadIndexFromSymbolicValue(Var_Variable_t *var, char *symbolicValue);
+EXTERN Hrc_Node_t * Var_VariableReadHnode(Var_Variable_t *var);
+EXTERN char * Var_VariableReadTypeIdentifier(Var_Variable_t *var);
+EXTERN void * Var_VariableReadUndef(Var_Variable_t *var);
+EXTERN boolean Var_VariableChangeName(Var_Variable_t *var, char *name);
+EXTERN int Var_VariableSetPI(Var_Variable_t *var);
+EXTERN int Var_VariableSetPO(Var_Variable_t *var);
+EXTERN int Var_VariableSetPS(Var_Variable_t *var);
+EXTERN int Var_VariableSetNS(Var_Variable_t *var);
+EXTERN int Var_VariableSetSI(Var_Variable_t *var);
+EXTERN int Var_VariableSetSO(Var_Variable_t *var);
+EXTERN int Var_VariableResetPI(Var_Variable_t *var);
+EXTERN int Var_VariableResetPO(Var_Variable_t *var);
+EXTERN int Var_VariableResetPS(Var_Variable_t *var);
+EXTERN int Var_VariableResetNS(Var_Variable_t *var);
+EXTERN int Var_VariableResetSI(Var_Variable_t *var);
+EXTERN int Var_VariableResetSO(Var_Variable_t *var);
+EXTERN void Var_VariableResetAllTypes(Var_Variable_t *var);
+EXTERN void Var_VariableSetTypeIdentifier(Var_Variable_t *var, char *typeIdentifier);
+EXTERN boolean Var_VariablesTestIdentical(Var_Variable_t *var1, Var_Variable_t *var2);
+EXTERN boolean Var_VariablesTestHaveSameDomain(Var_Variable_t *var1, Var_Variable_t *var2);
+EXTERN boolean Var_VariableTestTypeConsistency(Var_Variable_t *var);
+EXTERN boolean Var_VariablesTestHaveSameTypeIdentifier(Var_Variable_t *var1, Var_Variable_t *var2);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _VAR */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: vis_dev/vis-2.3/src/var/var.make
===================================================================
--- vis_dev/vis-2.3/src/var/var.make	(revision 14)
+++ vis_dev/vis-2.3/src/var/var.make	(revision 14)
@@ -0,0 +1,4 @@
+CSRC += varVariable.c
+HEADERS += var.h varInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/var/varInt.h
===================================================================
--- vis_dev/vis-2.3/src/var/varInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/var/varInt.h	(revision 14)
@@ -0,0 +1,109 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [varInt.h]
+
+  PackageName [var]
+
+  Synopsis    [Internal declarations for the multi-valued variable package.]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [Yuji Kukimoto]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: varInt.h,v 1.2 1998/05/19 22:04:27 hsv Exp $]
+
+******************************************************************************/
+
+#ifndef _VARINT
+#define _VARINT
+
+#include "var.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+#define VarPI (01)
+#define VarPO (02)
+#define VarPS (04)
+#define VarNS (010)
+#define VarSI (020)
+#define VarSO (040)
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+/**Struct**********************************************************************
+
+  Synopsis    [A multi-valued variable.]
+
+  Description [A multi-valued variable.]
+
+******************************************************************************/
+struct VarVariableStruct {
+  char  *name;	            /* name of variable */
+  Hrc_Node_t  *hnode;       /* hnode to which variable belongs  */
+  int type;                 /* type of variable, PI/PO/PS/NS/SI/SO
+                               (SI for subcircuit input and SO for subcircuit output)
+                               six Boolean flags are stored in a single int var
+                               Slot assignments in the int data structure are
+                               from LSB, PI, PO, PS, NS, SI, SO */
+  int  numValues;           /* number of values in domain */
+  array_t  *indexToValue;   /* int -> char *: used only for symbolic variables */
+  st_table  *valueToIndex;  /* char * -> int: used only for symbolic variables */
+  int numFanoutTables;      /* number of normal tables (\neq reset tables)
+                               in which the variable appears as an input
+                               Used by write_blif  */
+  char  *typeIdentifier;    /* type identifier associated with variable */
+                            /* (use w/ the blif-mv .type statement) */
+
+  void  *undef;             /* for programmer's usage */
+};
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _VARINT */
Index: vis_dev/vis-2.3/src/var/varVariable.c
===================================================================
--- vis_dev/vis-2.3/src/var/varVariable.c	(revision 14)
+++ vis_dev/vis-2.3/src/var/varVariable.c	(revision 14)
@@ -0,0 +1,1344 @@
+/**CFile***********************************************************************
+
+  FileName    [varVariable.c]
+
+  PackageName [var]
+
+  Synopsis    [Routines to access the MV-variable data structure.]
+
+  Description []
+
+  SeeAlso     []
+
+  Author      [Yuji Kukimoto]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "varInt.h"
+
+static char rcsid[] UNUSED = "$Id: varVariable.c,v 1.6 2009/01/18 01:58:09 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations                                                         */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int _VarVariableSetType(Var_Variable_t *var, int type);
+static int _VarVariableResetType(Var_Variable_t *var, int type);
+static char * _VarTypeDecode(int type);
+static array_t * _VarStringArrayDup(array_t *array);
+static void _VarStringArrayFree(array_t *array);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Adds range/symbolic value information to a variable.]
+
+  Description [Adds range/symbolic value information to a variable. This
+  function is typically called when a .mv construct is encountered for
+  a variable which is already defined by either .inputs or .outputs.
+  The arguments of this function are a pointer to a variable, the number
+  of values the variable can take, and an array of symbolic value names
+  stored as character strings. If the variable is an enumerative variable,
+  then the last argument should be set to NIL(array_t). It is the user's
+  responsibility to free the array and its strings since the function
+  creates a copy of the strings internally. Returns 1 if success.
+  Otherwise returns 0.]
+
+  SideEffects []
+
+  SeeAlso     [Var_VariableAlloc Var_VariableFree]
+
+******************************************************************************/
+
+boolean
+Var_VariableAddRangeInfo(
+  Var_Variable_t * var,
+  int numValues,
+  array_t * symValArray)
+{
+  int i;
+  char *symValue;
+  st_table *valueToIndex;
+
+  if (var->indexToValue != NIL(array_t) || var->numValues != 2){
+    error_append("Error: The range of variable ");
+    error_append(var->name);
+    error_append(" has been already set.\n");
+    return 0;
+  }
+
+  if (symValArray != NIL(array_t)){
+    if (numValues != array_n(symValArray)){
+      error_append("Error: Mismatch of range and # of symbolic values.\n");
+      return 0;
+    }
+    valueToIndex = st_init_table(strcmp,st_strhash);
+    var->indexToValue = _VarStringArrayDup(symValArray);
+    for (i=0; i < numValues; i++) {
+      symValue = array_fetch(char *,var->indexToValue,i);
+      if (st_insert(valueToIndex,symValue,(char *)((long)i))) {
+        error_append("Error: Invalid argument for Var_VariableAddRangeInfo().\n");
+        error_append("- Symbolic value ");
+        error_append(symValue);
+        error_append(" is redefined.\n");
+        st_free_table(valueToIndex);
+        return 0;
+      }
+    }
+    var->valueToIndex = valueToIndex;
+  }
+  var->numValues = numValues;
+  return 1;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Expands the range of a variable.]
+
+  Description [Expands the range of a variable. Designed for the table 
+  determinization routine.]
+
+  SideEffects []
+
+  SeeAlso     [Var_VariableReduceRange]
+
+******************************************************************************/
+boolean
+Var_VariableExpandRange(
+  Var_Variable_t *var,
+  int numValues)
+{
+  if (numValues <= var->numValues){
+    error_append("Error: A range can only be expanded.\n");
+    return 0;
+  }
+  if (var->indexToValue != NIL(array_t)){
+    int i;
+    char *dummyName;
+
+    for (i=var->numValues; i < numValues; i++){
+      /* put empty strings for expanded range */
+      dummyName = ALLOC(char,1);
+      *dummyName = '\0';
+      array_insert_last(char *,var->indexToValue,dummyName);
+    }
+  }
+  var->numValues = numValues;
+  return 1;
+} 
+
+/**Function********************************************************************
+
+  Synopsis    [Reduces the range of a variable.]
+
+  Description [Reduces the range of a variable. Designed for Abstraction. If
+  numValues is greater than the current range of var, then 
+  Var_VariableExpandRange will be called and returned.]
+
+  SideEffects []
+
+  SeeAlso     [Var_VariableExpandRange]
+
+******************************************************************************/
+boolean
+Var_VariableReduceRange(
+  Var_Variable_t *var,
+  int numValues)
+{
+  if(numValues > var->numValues){
+    return Var_VariableExpandRange(var,numValues);
+  }
+  else if (var->indexToValue != NIL(array_t)){
+    error_append("Error: Cannot reduce the range of a symbolic variable.\n");
+    return 0;
+  }
+
+  var->numValues = numValues;
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Allocates a new variable.]
+
+  Description [Allocates a new variable. This function is typically
+  invoked when a .inputs or a .outputs is encountered in the parser.
+  The arguments of this function are a pointer to the hnode to which
+  a new variable belongs to and a name of the variable. The name string
+  is copied for internal use. The user is responsible for freeing
+  the original string. The new variable is set to a binary variable
+  without any symbolic value definition, i.e. it is defined as a binary
+  enumerative variable. The user can update this range information
+  by calling Var_VariableAddRangeInfo(). Returns a pointer to
+  the variable if success. Otherwise, NIL(Var_Variable_t) is returned. ]
+
+  SideEffects []
+
+  SeeAlso     [Var_VariableAddRangeInfo Var_VariableFree]
+
+******************************************************************************/
+
+Var_Variable_t *
+Var_VariableAlloc(
+  Hrc_Node_t *hnode, 
+  char *name)
+{
+  Var_Variable_t *var;
+
+  var = ALLOC(Var_Variable_t,1);
+  var->name = util_strsav(name);
+  var->hnode = hnode;
+  if (hnode != NIL(Hrc_Node_t)){
+    if ( Hrc_NodeAddVariable(hnode,var) == 0 ){
+      Var_VariableFree(var);
+      return NIL(Var_Variable_t);
+    }
+  }
+  var->type = 0;
+  /* assume that this is a Boolean variable w/o symbolic value definition */
+  var->numValues = 2;
+  var->numFanoutTables = 0;
+  var->indexToValue = NIL(array_t);
+  var->valueToIndex = NIL(st_table);
+  var->typeIdentifier = NIL(char);
+  var->undef = NIL(void);
+  return var;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees a variable.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     [Var_VariableAlloc]
+
+******************************************************************************/
+void
+Var_VariableFree(Var_Variable_t *var)
+{
+  if (var->hnode != NIL(Hrc_Node_t)){
+    Hrc_NodeDeleteVariable(var->hnode,var);
+  }
+  FREE(var->name);
+  if (var->indexToValue != NIL(array_t)){
+    _VarStringArrayFree(var->indexToValue);
+  }
+  if (var->valueToIndex != NIL(st_table)){
+    st_free_table(var->valueToIndex);
+  }
+  if (var->typeIdentifier != NIL(char)){
+    FREE(var->typeIdentifier);
+  }
+  FREE(var);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Duplicates a variable. ]
+
+  Description [Duplicates a variable. The second argument hnode is a new hnode
+  to which a duplicated variable belongs.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Var_Variable_t *
+Var_VariableDup(
+  Var_Variable_t *var,
+  Hrc_Node_t *hnode)
+{
+  Var_Variable_t *varDup;
+
+  varDup = Var_VariableAlloc(hnode,var->name);
+  varDup->type = var->type;
+  varDup->hnode = hnode;
+  varDup->numFanoutTables = var->numFanoutTables;
+  if (Var_VariableAddRangeInfo(varDup,var->numValues,var->indexToValue) == 0){
+    return NIL(Var_Variable_t);
+  }
+  if (var->typeIdentifier != NIL(char)){
+    varDup->typeIdentifier = util_strsav(var->typeIdentifier);
+  }
+  return varDup;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a pointer to the name of a variable.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+char *
+Var_VariableReadName(Var_Variable_t *var)
+{
+  return var->name;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if a variable is a primary input. Otherwise returns 0.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     [Var_VariableSetPI]
+
+******************************************************************************/
+boolean
+Var_VariableTestIsPI(Var_Variable_t *var)
+{
+  return (((var->type) & VarPI) ? 1:0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if a variable is a primary output. Otherwise returns 0.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     [Var_VariableSetPO]
+
+******************************************************************************/
+boolean
+Var_VariableTestIsPO(Var_Variable_t *var)
+{
+  return (((var->type) & VarPO) ? 1:0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if a variable is a present state variable. Otherwise returns 0.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     [Var_VariableSetPS]
+
+******************************************************************************/
+boolean
+Var_VariableTestIsPS(Var_Variable_t *var)
+{
+  return (((var->type) & VarPS) ? 1:0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if a variable is a next state variable. Otherwise returns 0.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     [Var_VariableSetNS]
+
+******************************************************************************/
+boolean
+Var_VariableTestIsNS(Var_Variable_t *var)
+{
+  return (((var->type) & VarNS) ? 1:0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if a variable is a subcircuit input. Otherwise returns 0.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     [Var_VariableSetSI]
+
+******************************************************************************/
+boolean
+Var_VariableTestIsSI(Var_Variable_t *var)
+{
+  return (((var->type) & VarSI) ? 1:0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if a variable is a subcircuit output. Otherwise returns 0.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     [Var_VariableSetSO]
+
+******************************************************************************/
+boolean
+Var_VariableTestIsSO(Var_Variable_t *var)
+{
+  return (((var->type) & VarSO) ? 1:0);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if the value type of a variable is symbolic and 0
+  otherwise.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     [Var_VariableTestIsEnumerative]
+
+******************************************************************************/
+boolean
+Var_VariableTestIsSymbolic(Var_Variable_t *var)
+{
+  if (var->indexToValue != NIL(array_t)){
+    return 1;
+  }
+  return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if the value type of a variable is enumerative and 0
+  otherwise.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     [Var_VariableTestIsSymbolic]
+
+******************************************************************************/
+boolean
+Var_VariableTestIsEnumerative(Var_Variable_t *var)
+{
+  if (var->indexToValue == NIL(array_t)){
+    return 1;
+  }
+  return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if a variable is enumerative *and* a value is
+  in the range of the variable. Returns 0 otherwise.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+Var_VariableTestIsValueInRange(
+  Var_Variable_t *var,
+  int value)
+{
+  if (var->indexToValue != NIL(array_t)){
+    return 0;
+  }
+  if (value >= 0 && value < var->numValues){
+    return 1;
+  }
+  return 0;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of values a variable can take.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Var_VariableReadNumValues(Var_Variable_t *var)
+{
+  return var->numValues;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the number of fanout tables.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Var_VariableReadNumFanoutTables(Var_Variable_t *var)
+{
+  return var->numFanoutTables;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Increments the number of fanout tables.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Var_VariableIncrementNumFanoutTables(Var_Variable_t *var)
+{
+  (var->numFanoutTables)++;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Resets the number of fanout tables.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Var_VariableResetNumFanoutTables(
+  Var_Variable_t* var)
+{
+  var->numFanoutTables = 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the name of the symbolic value associated with an integer index.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+char *
+Var_VariableReadSymbolicValueFromIndex(
+  Var_Variable_t *var,
+  int i)
+{
+  assert(var->indexToValue != NIL(array_t));
+  return array_fetch(char *,var->indexToValue,i);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the integer index associated with the name of a symbolic value.]
+
+  Description [Returns the integer index associated with a symbolic value. If
+  a given symbolic name is not valid, the routine returns -1.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+int
+Var_VariableReadIndexFromSymbolicValue(
+  Var_Variable_t *var,
+  char *symbolicValue)
+{
+  int  isFound;
+  int  index;
+
+  assert(var->valueToIndex != NIL(st_table));
+  isFound = st_lookup_int(var->valueToIndex,symbolicValue,&index);
+  return( isFound ? index : -1);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the hnode to which a variable belongs.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+Hrc_Node_t *
+Var_VariableReadHnode(Var_Variable_t *var)
+{
+  return var->hnode;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a pointer to the type identifier of a variable.]
+
+  Description [Reads the type identifier for the variable.  Type identifiers are
+  defined in blif-mv using the .type statement. 
+  Example: .type color red white blue 
+           .mv flag_colors type=color]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+char *
+Var_VariableReadTypeIdentifier(Var_Variable_t *var)
+{
+  return var->typeIdentifier;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns a pointer to the user field of a variable.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void *
+Var_VariableReadUndef(Var_Variable_t *var)
+{
+  return var->undef;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Changes the name of a variable.]
+
+  Description [Changes the name of a variable. Returns 1 if success, otherwise
+  returns 0.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+Var_VariableChangeName(
+  Var_Variable_t *var,
+  char *name)
+{
+  if (var->hnode != NIL(Hrc_Node_t)){
+    if (Hrc_NodeDeleteVariable(var->hnode,var) == 0){
+      /* this variable should have been in the hnode */
+      return 0;
+    }
+  }
+  FREE(var->name);
+  var->name = util_strsav(name); 
+  if (var->hnode != NIL(Hrc_Node_t)){
+    if (Hrc_NodeAddVariable(var->hnode,var) == 0){
+      /* there is a node with the new name in the hnode already */
+      return 0;
+    }
+  }
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the PI-field of a variable.]
+
+  Description [Sets the PI-field of a variable. Returns 1 upon success. 
+  Returns 0 if the variable is
+  already set as a PI. Returns -1 if a type error occurs. This function is used when 
+  a variable is defined in .inputs *and* the variable is already declared
+  in .mv. ]
+
+  SideEffects []
+
+  SeeAlso     [Var_VariableTestIsPI]
+
+******************************************************************************/
+int
+Var_VariableSetPI(Var_Variable_t *var)
+{
+  return _VarVariableSetType(var,VarPI);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the PO-field of a variable.]
+
+  Description [Sets the PO-field of a variable. Returns 1 upon success.
+  Returns 0 if the variable is
+  already set as a PO. Returns -1 if a type error occurs. This function is used when
+  a variable is defined in .outputs *and* the variable is already declared
+  in .mv. ]
+
+  SideEffects []
+
+  SeeAlso     [Var_VariableTestIsPO]
+
+******************************************************************************/
+int
+Var_VariableSetPO(Var_Variable_t *var)
+{
+  return _VarVariableSetType(var,VarPO);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the PS-field of a variable.]
+
+  Description [Sets the PS-field of a variable. Returns 1 upon success.
+  Returns 0 if the variable is
+  already set as a PS. Returns -1 if a type error occurs. This function is used when
+  a variable is defined in .latch *and* the variable is already declared
+  in .mv. ]
+
+  SideEffects []
+
+  SeeAlso     [Var_VariableTestIsPS]
+
+******************************************************************************/
+int
+Var_VariableSetPS(Var_Variable_t *var)
+{
+  return _VarVariableSetType(var,VarPS);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the NS-field of a variable.]
+
+  Description [Sets the NS-field of a variable. Returns 1 upon success.
+  Returns 0 if the variable is
+  already set as an NS. Returns -1 if a type error occurs. This function is used when
+  a variable is defined in .latch *and* the variable is already declared
+  in .mv. ]
+
+  SideEffects []
+
+  SeeAlso     [Var_VariableTestIsNS]
+
+******************************************************************************/
+int
+Var_VariableSetNS(Var_Variable_t *var)
+{
+  return _VarVariableSetType(var,VarNS);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the SI-field of a variable.]
+
+  Description [Sets the SI-field of a variable. Returns 1 upon success.
+  Returns 0 if the variable is
+  already set as an SI. Returns -1 if a type error occurs.]
+
+  SideEffects []
+
+  SeeAlso     [Var_VariableTestIsSI]
+
+******************************************************************************/
+int
+Var_VariableSetSI(Var_Variable_t *var)
+{
+  return _VarVariableSetType(var,VarSI);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the SO-field of a variable.]
+
+  Description [Sets the SO-field of a variable. Returns 1 upon success.
+  Returns 0 if the variable is
+  already set as an SO. Returns -1 if a type error occurs.]
+
+  SideEffects []
+
+  SeeAlso     [Var_VariableTestIsSO]
+
+******************************************************************************/
+int
+Var_VariableSetSO(Var_Variable_t *var)
+{
+  return _VarVariableSetType(var,VarSO);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Resets the PI-field of a variable.]
+
+  Description [Resets the PI-field of a variable. Returns 1 upon success. 
+  Returns 0 if the variable is not set to PI.
+  ]
+
+  SideEffects []
+
+  SeeAlso     [Var_VariableTestIsPI]
+
+******************************************************************************/
+int
+Var_VariableResetPI(Var_Variable_t *var)
+{
+  return _VarVariableResetType(var,VarPI);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Resets the PO-field of a variable.]
+
+  Description [Resets the PO-field of a variable. Returns 1 upon success.
+  Returns 0 if the variable is not set to PO.
+  ]
+
+  SideEffects []
+
+  SeeAlso     [Var_VariableTestIsPO]
+
+******************************************************************************/
+int
+Var_VariableResetPO(Var_Variable_t *var)
+{
+  return _VarVariableResetType(var,VarPO);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Resets the PS-field of a variable.]
+
+  Description [Resets the PS-field of a variable. Returns 1 upon success.
+  Returns 0 if the variable is not set to PS.
+  ]
+
+  SideEffects []
+
+  SeeAlso     [Var_VariableTestIsPS]
+
+******************************************************************************/
+int
+Var_VariableResetPS(Var_Variable_t *var)
+{
+  return _VarVariableResetType(var,VarPS);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Resets the NS-field of a variable.]
+
+  Description [Resets the NS-field of a variable. Returns 1 upon success.
+  Returns 0 if the variable is not set to NS.
+  ]
+
+  SideEffects []
+
+  SeeAlso     [Var_VariableTestIsNS]
+
+******************************************************************************/
+int
+Var_VariableResetNS(Var_Variable_t *var)
+{
+  return _VarVariableResetType(var,VarNS);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Resets the SI-field of a variable.]
+
+  Description [Resets the SI-field of a variable. Returns 1 upon success.
+  Returns 0 if the variable is not set to SI.
+  ]
+
+  SideEffects []
+
+  SeeAlso     [Var_VariableTestIsSI]
+
+******************************************************************************/
+int
+Var_VariableResetSI(Var_Variable_t *var)
+{
+  return _VarVariableResetType(var,VarSI);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Resets the SO-field of a variable.]
+
+  Description [Resets the SO-field of a variable. Returns 1 upon success.
+  Returns 0 if the variable is not set to SO.
+  ]
+
+  SideEffects []
+
+  SeeAlso     [Var_VariableTestIsSO]
+
+******************************************************************************/
+int
+Var_VariableResetSO(Var_Variable_t *var)
+{
+  return _VarVariableResetType(var,VarSO);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Resets all the types of a variable.]
+
+  Description [Resets all the types of a variable.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Var_VariableResetAllTypes(Var_Variable_t *var)
+{
+  var->type = 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the type identifier for the variable.]
+
+  Description [Sets the type identifier for the variable.  Type identifiers are
+  defined in blif-mv using the .type statement.  
+  Example: .type color red white blue
+           .mv flag_colors type=color]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+void
+Var_VariableSetTypeIdentifier(
+  Var_Variable_t *var,
+  char *typeIdentifier)
+{
+  if (var->typeIdentifier != NIL(char)){
+    FREE(var->typeIdentifier);
+  }
+  var->typeIdentifier = util_strsav(typeIdentifier);
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Given two variables, checks to see if the two variables refer
+  to the identical signal once a hierarchy is flattened out. Returns 1 if 
+  they are identical. Otherwise returns 0. If the two variables do not
+  belong to the same hierarchy manager, it also returns 0 with an error
+  message sent to error_string.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+Var_VariablesTestIdentical(
+  Var_Variable_t *var1, 
+  Var_Variable_t *var2)
+{
+  Hrc_Manager_t *hmgr1, *hmgr2;
+  Hrc_Node_t *hnode1, *hnode2, *rootNode;
+  Var_Variable_t *varCanonical1, *varCanonical2;
+
+  hnode1 = Var_VariableReadHnode(var1);
+  hnode2 = Var_VariableReadHnode(var2);
+  hmgr1 = Hrc_NodeReadManager(hnode1);
+  hmgr2 = Hrc_NodeReadManager(hnode2);
+
+  if (hmgr1 != hmgr2){
+    error_append("Error: Variables ");
+    error_append(Var_VariableReadName(var1));
+    error_append(" and ");
+    error_append(Var_VariableReadName(var2));
+    error_append(" are not under the same manager.\n");
+    return 0;
+  }
+  /* if two variables reside in the same hnode */
+  if (hnode1 == hnode2){
+    if (var1 == var2){
+      return 1;
+    }
+    return 0;
+  }
+
+  /* otherwise */
+  rootNode = Hrc_ManagerReadRootNode(hmgr1);
+ 
+  varCanonical1 = Hrc_VariableFindActualFromFormal(hnode1,var1,rootNode);
+  varCanonical2 = Hrc_VariableFindActualFromFormal(hnode2,var2,rootNode);
+  if (varCanonical1 == varCanonical2){
+    return 1;
+  }
+  return 0;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Checks to see if two variables are defined over the same domain.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+Var_VariablesTestHaveSameDomain(
+  Var_Variable_t *var1, 
+  Var_Variable_t *var2)
+{
+  array_t *indexToValue1, *indexToValue2;
+  char *value1, *value2;
+  int i;
+
+  if (var1->numValues != var2->numValues)
+    return 0;
+  indexToValue1 = var1->indexToValue;
+  indexToValue2 = var2->indexToValue;
+  if (indexToValue1 == NIL(array_t) || indexToValue2 == NIL(array_t))
+    return 1;
+  for (i=0; i < array_n(indexToValue1); i++){
+    value1 = array_fetch(char *,indexToValue1,i);
+    value2 = array_fetch(char *,indexToValue2,i);
+    if (strcmp(value1,value2)){
+      return 0;    
+    }
+  }
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Checks to see if there is no type violation. Returns 1 if
+  no violation exists. Otherwise returns 0.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+Var_VariableTestTypeConsistency(Var_Variable_t *var)
+{
+  /* checking PI/PO */
+  if ((var->type & 03) == 03){
+    error_append("Error: Variable ");
+    error_append(Var_VariableReadName(var));
+    error_append(" is of type PI/PO.\n");
+    return 0;
+  }
+  /* checking PI/PS */
+  if ((var->type & 05) == 05){
+    error_append("Error: Variable ");
+    error_append(Var_VariableReadName(var));
+    error_append(" is of type PI/PS.\n");
+    return 0;
+  }
+  /* checking PI/SO */
+  if ((var->type & 041) == 041){
+    error_append("Error: Variable ");
+    error_append(Var_VariableReadName(var));
+    error_append(" is of type PI/SO.\n");
+    return 0;
+  }
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Checks to see if two variables have the same type identifier]
+
+  Description [Returns 1 if var1 and var2 have the same type identifier,
+  0 otherwise.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+boolean
+Var_VariablesTestHaveSameTypeIdentifier(
+  Var_Variable_t *var1,
+  Var_Variable_t *var2)
+{
+  if (var1->typeIdentifier == NIL(char) && var2->typeIdentifier == NIL(char)){
+    return 1;
+  }
+  if (var1->typeIdentifier == NIL(char) || var2->typeIdentifier == NIL(char)){
+    return 0;
+  }
+  if (strcmp(var1->typeIdentifier,var2->typeIdentifier) == 0 ){
+    return 1;
+  }
+  return 0;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Sets the type field of a variable. Returns 0 if the variable is
+  already set as a given type. If the variable is newly set to the type, it 
+  returns 1. If a type violation occurs after this setting, -1 is returned.
+  Type can be set either VarPI, VarPO, VarPS, VarNS, VarSI and VarSO.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+_VarVariableSetType(Var_Variable_t *var,int type)
+{
+/*
+  if (var->type & type){
+    error_append("Warning: Variable ");
+    error_append(Var_VariableReadName(var));
+    error_append(" is already set to ");
+    error_append(_VarTypeDecode(type));
+    error_append(".\n");
+     return 0;
+  }
+*/
+  var->type |= type;
+  if (Var_VariableTestTypeConsistency(var) == 0){
+     return -1;
+  }
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Resets the type field of a variable. Returns 0 if the variable is
+  not set as a given type, i.e. there is no need for resetting the type. 
+  Otherwise, returns 1. 
+  Type can be set either VarPI, VarPO, VarPS, VarNS, VarSI and VarSO.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static int
+_VarVariableResetType(Var_Variable_t *var,int type)
+{
+/*
+  if (var->type & type){
+    error_append("Warning: Variable ");
+    error_append(Var_VariableReadName(var));
+    error_append(" is already set to ");
+    error_append(_VarTypeDecode(type));
+    error_append(".\n");
+     return 0;
+  }
+*/
+  if ((var->type & type) == 0){
+    return 0;
+  }
+  var->type &= ~type;
+  return 1;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the character string corresponding to a type encoded
+               in an integer. Note that SI and SO are filtered out.]
+
+  Description []
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static char *
+_VarTypeDecode(int type)
+{
+  /* suppress information on SI/SO for simplicity */
+  type &= 017;
+  switch(type){
+    case 00:
+      return "Internal";
+    case 01: 
+      return "PI";
+    case 02: 
+      return "PO";
+    case 03: 
+      error_append("Error: Strange type PI/PO.\n");
+      return "PI/PO";
+    case 04: 
+      return "PS";
+    case 05:
+      error_append("Error: Strange type PI/PS.\n");
+      return "PI/PS";
+    case 06:
+      return "PO/PS";
+    case 07:
+      error_append("Error: Strange type PI/PO/PS.\n");
+      return "PI/PO/PS";
+    case 010: 
+      return "NS";
+    case 011:
+      return "PI/NS";
+    case 012:
+      return "PO/NS";
+    case 013:
+      error_append("Error: Strange type PI/PO/NS.\n");
+      return "PI/PO/NS";
+    case 014:
+      return "PS/NS";
+    case 015:
+      error_append("Error: Strange type PI/PS/NS.\n");
+      return "PI/PS/NS";
+    case 016:
+      return "PO/PS/NS";
+    case 017:
+      error_append("Error: Strange type PI/PO/PS/NS.\n");
+      return "PI/PO/PS/NS";
+    default: 
+      fail("Strange type in VarTypeDecode().\n");
+      return NIL(char); /* not reached */
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Duplicates an array of strings.]
+
+  Description [Duplicates an array of strings. Strings themselves are also
+  copied over to the new array.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static array_t *
+_VarStringArrayDup(array_t *array)
+{
+  int i;
+  char *symbol,*newSymbol;
+  array_t *newArray;
+
+  newArray = array_alloc(char *,0);
+  for (i=0; i < array_n(array); i++) {
+    symbol = array_fetch(char *, array, i);
+    newSymbol = util_strsav(symbol);
+    array_insert_last(char *,newArray,newSymbol);
+  }
+  return newArray;
+}
+
+/**Function********************************************************************
+
+  Synopsis    [Frees an array of strings.]
+
+  Description [Frees an array of strings. Strings themselves are also
+  freed.]
+
+  SideEffects []
+
+  SeeAlso     []
+
+******************************************************************************/
+static void
+_VarStringArrayFree(array_t *array)
+{
+  int i;
+  char *symbol;
+
+  for (i=0; i < array_n(array); i++) {
+    symbol = array_fetch(char *, array, i);
+    FREE(symbol);
+  }
+  array_free(array);
+}
Index: vis_dev/vis-2.3/src/vm/vm.h
===================================================================
--- vis_dev/vis-2.3/src/vm/vm.h	(revision 14)
+++ vis_dev/vis-2.3/src/vm/vm.h	(revision 14)
@@ -0,0 +1,93 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [vm.h]
+
+  PackageName [vm]
+
+  Synopsis    ["Main" package of VIS ("vm" = VIS main).]
+
+  Author      [Originated from SIS]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: vm.h,v 1.5 2005/05/14 02:15:39 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _VM
+#define _VM
+
+/*---------------------------------------------------------------------------*/
+/* Nested includes                                                           */
+/*---------------------------------------------------------------------------*/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <unistd.h>
+#include "util.h"
+#include "error.h"
+#include "avl.h"
+#include "var_set.h"
+#include "array.h"
+#include "st.h"
+#include "list.h"
+#include "graph.h"
+#include "bdd.h"
+#include "mdd.h"
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+
+#define VIS_INFINITY	(1 << 30)
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+extern FILE *vis_stderr;
+extern FILE *vis_stdout;
+extern FILE *vis_historyFile;
+extern FILE *vis_stdpipe;
+extern array_t *vm_commandHistoryArray;
+extern char *vm_programName;
+
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations                                                        */
+/*---------------------------------------------------------------------------*/
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN char * Vm_VisReadVersion(void);
+EXTERN char * Vm_VisObtainLibrary(void);
+EXTERN void Vm_VisInitPrintMore(void);
+EXTERN int Vm_VisEndPrintMore(void);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _VM */
+
+
+
+
Index: vis_dev/vis-2.3/src/vm/vm.make
===================================================================
--- vis_dev/vis-2.3/src/vm/vm.make	(revision 14)
+++ vis_dev/vis-2.3/src/vm/vm.make	(revision 14)
@@ -0,0 +1,4 @@
+CSRC += vmInit.c vmMain.c vmVers.c
+HEADERS += vm.h vmInt.h
+
+DEPENDENCYFILES = $(CSRC)
Index: vis_dev/vis-2.3/src/vm/vmInit.c
===================================================================
--- vis_dev/vis-2.3/src/vm/vmInit.c	(revision 14)
+++ vis_dev/vis-2.3/src/vm/vmInit.c	(revision 14)
@@ -0,0 +1,175 @@
+/**CFile***********************************************************************
+
+  FileName    [vmInit.c]
+
+  PackageName [vm]
+
+  Synopsis    [Initializes and ends VIS.]
+
+  Author      [Originated from SIS]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "vmInt.h"
+
+static char rcsid[] UNUSED = "$Id: vmInit.c,v 1.17 2004/12/27 00:25:32 bli Exp $";
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Calls the initialization routines of all the packages.]
+
+  SideEffects [Sets the global variables vis_stdout, vis_stderr,
+  vis_historyFile.]
+
+  SeeAlso     [VmEnd]
+
+******************************************************************************/
+void
+VmInit(void)
+{
+  vis_stdout      = stdout; 
+  vis_stderr      = stderr;
+  vis_historyFile = NIL(FILE);
+  
+  Cmd_Init();
+  Tst_Init();
+  Tbl_Init();
+  Io_Init();
+  Hrc_Init();
+  Rst_Init();
+  Ntk_Init();
+  Ord_Init();
+  Ntm_Init();
+  Ctlp_Init();
+  Ctlsp_Init();  
+  Fsm_Init();
+  Ltl_Init();    
+  Grab_Init();   
+  Sim_Init();
+  Part_Init();
+  Mvf_Init();
+  Img_Init();
+  Mc_Init();
+  Eqv_Init();
+  Amc_Init();
+  Res_Init();
+  Synth_Init();
+  Abs_Init();
+  Restr_Init();
+  Imc_Init();
+  Spfd_Init();
+  Truesim_Init();
+  Rt_Init();
+  bAig_Init();
+  mAig_Init();
+  MvfAig_Init();
+  ntmaig_Init();
+  Bmc_Init();
+  PureSat_Init();
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Calls the end routines of all the packages.]
+
+  SideEffects [Closes the output files if not the standard ones.]
+
+  SeeAlso     [VmInit]
+
+******************************************************************************/
+void
+VmEnd(void)
+{
+  Synth_End();
+  Amc_End();
+  Eqv_End();
+  Mc_End();
+  Img_End();
+  Mvf_End();
+  Part_End();
+  Sim_End();
+  Fsm_End();
+  Grab_End();
+  Ltl_End();   
+  Ctlp_End();
+  Ctlsp_End(); 
+  Ntm_End();
+  Ord_End();
+  Ntk_End();
+  Rst_End();
+  Hrc_End();
+  Tbl_End();
+  Io_End();
+  Res_End();
+  Tst_End();
+  Cmd_End();
+  Abs_End();
+  Restr_End();
+  Imc_End();
+  Spfd_End();
+  Truesim_End();
+  Rt_End();
+  bAig_End();
+  mAig_End();
+  MvfAig_End();
+  ntmaig_End();
+  Bmc_End();
+
+  if (vis_stdout != stdout) {  
+    (void) fclose(vis_stdout);
+  } 
+  if (vis_stderr != stderr) {
+    (void) fclose(vis_stderr);
+  }
+  if (vis_historyFile != NIL(FILE)) {
+    (void) fclose(vis_historyFile);
+  }
+  
+  vis_stdout      = stdout;
+  vis_stderr      = stderr;
+  vis_historyFile = NIL(FILE);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
Index: vis_dev/vis-2.3/src/vm/vmInt.h
===================================================================
--- vis_dev/vis-2.3/src/vm/vmInt.h	(revision 14)
+++ vis_dev/vis-2.3/src/vm/vmInt.h	(revision 14)
@@ -0,0 +1,89 @@
+/**CHeaderFile*****************************************************************
+
+  FileName    [vmInt.h]
+
+  PackageName [vm]
+
+  Synopsis    [Internal declarations for the main package.]
+
+  Author      [Originated from SIS]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+  Revision    [$Id: vmInt.h,v 1.11 2005/04/25 19:08:57 fabio Exp $]
+
+******************************************************************************/
+
+#ifndef _VMINT
+#define _VMINT
+#include "abs.h"
+#include "amc.h"
+#include "bmc.h"
+#include "cmd.h"
+#include "ctlp.h"
+#include "ctlsp.h"
+#include "eqv.h"
+#include "fsm.h"
+#include "hrc.h"
+#include "imc.h"
+#include "img.h"
+#include "io.h"
+#include "ltl.h"
+#include "mc.h"
+#include "mvf.h"
+#include "ntk.h"
+#include "ntm.h"
+#include "ntmaig.h"
+#include "ord.h"
+#include "part.h"
+#include "res.h"
+#include "restr.h"
+#include "rst.h"
+#include "rt.h"
+#include "sim.h"
+#include "spfd.h"
+#include "synth.h"
+#include "tbl.h"
+#include "truesim.h"
+#include "tst.h"
+#include "vm.h"
+#include "grab.h"
+#include "puresat.h"
+
+#if STDC_HEADERS
+#  include <stdlib.h>
+#else
+char * getenv(const char *);
+#endif
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Function prototypes                                                       */
+/*---------------------------------------------------------------------------*/
+
+EXTERN void VmInit(void);
+EXTERN void VmEnd(void);
+EXTERN int main(int argc, char ** argv);
+
+/**AutomaticEnd***************************************************************/
+
+#endif /* _VMINT */
Index: vis_dev/vis-2.3/src/vm/vmMain.c
===================================================================
--- vis_dev/vis-2.3/src/vm/vmMain.c	(revision 14)
+++ vis_dev/vis-2.3/src/vm/vmMain.c	(revision 14)
@@ -0,0 +1,409 @@
+/**CFile***********************************************************************
+
+  FileName    [vmMain.c]
+
+  PackageName [vm]
+
+  Synopsis    [Main VIS routine. Parses command line at invocation of VIS.]
+
+  Author      [Originated from SIS]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "vmInt.h"
+
+static char rcsid[] UNUSED = "$Id: vmMain.c,v 1.6 2004/07/16 00:09:59 wangc Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations                                                     */
+/*---------------------------------------------------------------------------*/
+FILE *vis_stderr;
+FILE *vis_stdout;
+FILE *vis_historyFile;
+FILE *vis_stdpipe;
+array_t *vm_commandHistoryArray;
+char *vm_programName;
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static int VisrcSource(Hrc_Manager_t ** hmgr);
+static void UsagePrint(char * program);
+static int TypeCheck(char * s);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [required]
+
+  Description [optional]
+
+  SideEffects [Sets vm_programName to the name of the excutable.]
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+int
+main(
+  int  argc,
+  char ** argv)
+{
+  int c,
+    status,
+    batch,          /* 0 iff we have an interactive run (-c or -f) */
+    initial_source, /* 1 iff we have to read .visrc                */
+    initial_read,
+    final_write;
+  int quit_flag;
+  char readcmd[20],
+    writecmd[20];
+  char *dummy,
+    *cmdline,
+    *cmdline1,
+    *infile,        /* where to read input */
+    *outfile;       /* where to write output */
+  Hrc_Manager_t *globalHmgr;
+  
+  vm_programName = argv[0];
+  quit_flag = -1;     /* Quick quit */
+
+  VmInit();
+  globalHmgr = Hrc_ManagerAlloc();
+
+  cmdline = util_strsav("");
+  (void) strcpy(readcmd, "read_blif_mv");
+  (void) strcpy(writecmd, "write_blif_mv");
+  infile = "-";
+  outfile = "-";
+  vm_commandHistoryArray = array_alloc(char *, 0);
+  initial_source = 1;
+  initial_read = 1;
+  final_write = 1;
+  batch = 0;
+  util_getopt_reset();
+  while ((c = util_getopt(argc, argv, "c:hf:o:st:T:x")) != EOF) {
+    switch(c) {
+	case 'c':
+          FREE(cmdline);
+          cmdline = util_strsav(util_optarg);
+          batch = 1;
+          break;
+
+	case 'f':
+          FREE(cmdline);
+          cmdline = ALLOC(char, strlen(util_optarg) + 20);
+          (void) sprintf(cmdline, "source %s", util_optarg);
+          batch = 1;
+          break;
+          
+	case 'h':
+            UsagePrint(argv[0]);
+            break;
+             
+	case 'o':
+          outfile = util_optarg;
+          break;
+
+	case 's':
+          initial_source = 0;
+          break;
+
+	case 't':
+          if (TypeCheck(util_optarg)) {
+            if (strcmp(util_optarg, "none") == 0) {
+              initial_read = 0;
+            }
+            else {
+              (void) sprintf(readcmd, "read_%s", util_optarg);
+            }
+          }
+          else {
+            UsagePrint(argv[0]);
+          }
+          batch = 1;
+          break;
+
+	case 'T':
+          if (TypeCheck(util_optarg)) {
+            if (strcmp(util_optarg, "none") == 0) {
+              final_write = 0;
+            }
+            else {
+              (void) sprintf(writecmd, "write_%s", util_optarg);
+            }
+          }
+          else {
+            UsagePrint(argv[0]);
+          }
+          batch = 1;
+          break;
+
+	case 'x':
+          final_write = 0;
+          initial_read = 0;
+          batch = 1;
+          break;
+
+	default:
+          UsagePrint(argv[0]);
+    }
+  }
+
+  if (! batch) {
+    /* interactive use ... */
+    if (argc - util_optind != 0) {
+      (void) fprintf(vis_stderr, "warning -- trailing arguments ignored\n");
+    }
+
+    (void) fprintf(vis_stdout, "%s\n", Vm_VisReadVersion());
+    if (initial_source) {
+      (void) VisrcSource(&globalHmgr);
+    }
+    while ((quit_flag = Cmd_CommandExecute(&globalHmgr, "source -ip -")) >= 0)
+      ;
+    status = 0;
+
+  } else {
+
+    if (argc - util_optind == 0) {
+      infile = "-";
+    }
+    else if (argc - util_optind == 1) {
+      infile = argv[util_optind];
+    }
+    else {
+      UsagePrint(argv[0]);
+    }
+
+    if (initial_source) {
+      (void) VisrcSource(&globalHmgr);
+    }
+
+    status = 0;
+    if (initial_read) {
+      cmdline1 = ALLOC(char, strlen(infile) + 20);
+      (void) sprintf(cmdline1, "%s %s", readcmd, infile);
+      status = Cmd_CommandExecute(&globalHmgr, cmdline1);
+      FREE(cmdline1);
+    }
+
+    if (status == 0) {
+      /* cmd line contains `source <file>' */
+      status = Cmd_CommandExecute(&globalHmgr, cmdline);
+      if ((status == 0 || status == -1) && final_write) {
+        cmdline1 = ALLOC(char, strlen(outfile) + 20);
+        (void) sprintf(cmdline1, "%s %s", writecmd, outfile);
+        status = Cmd_CommandExecute(&globalHmgr, cmdline1);
+        FREE(cmdline1);
+      }
+    }
+    
+    /* FIX: RB, allows a clean quit from a script */
+    quit_flag = status;
+    
+
+  }
+
+  FREE(cmdline);
+  for (c = array_n(vm_commandHistoryArray); c-- > 0; ){
+    dummy = array_fetch(char *, vm_commandHistoryArray, c);
+    FREE(dummy);
+  }
+
+  array_free(vm_commandHistoryArray);
+  /* Value of "quit_flag" is determined by the "quit" command */
+  if (quit_flag == -1 || quit_flag == -2) {
+    status = 0;
+  }
+  if (quit_flag == -2) {
+    Hrc_ManagerFree(globalHmgr);
+    VmEnd();
+  }
+  return(status);
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Sources the .visrc file.]
+
+  Description [Sources the .visrc file.  Always sources the .visrc from
+  library.  Then source the .visrc from the home directory.  If there is none
+  in the home directory, then execute the one in the current directory if one
+  is present.  Returns 1 if scripts were successfully executed, else return 0.]
+
+  SideEffects []
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static int
+VisrcSource(
+  Hrc_Manager_t ** hmgr)
+{
+  char *commandLine;
+  char *libraryName;
+  char *homeFile;
+  struct stat home;
+  struct stat cur;
+  int s1;
+  int s2;			/* flags for checking the stat() call */
+  int status0;
+  int status1 = TRUE;
+  int status2 = TRUE;
+
+  /*
+   * First execute the standard .visrc.
+   */
+  libraryName = Vm_VisObtainLibrary();
+  commandLine = ALLOC(char, strlen(libraryName) + 25);
+  (void) sprintf(commandLine, "source -s %s/master.visrc", libraryName);
+  FREE(libraryName);
+  status0 = Cmd_CommandExecute(hmgr, commandLine);
+  FREE(commandLine);
+
+  /*
+   * Look in home directory and current directory for .visrc.
+   */
+  homeFile = util_tilde_expand("~/.visrc");
+  s1 = stat(homeFile, &home);
+  FREE(homeFile);
+  s2 = stat(".visrc", &cur);
+
+  /*
+   * If .visrc is present in both the home and current directories, then read
+   * it from the home directory.  Otherwise, read it from wherever it's
+   * located.
+   */
+  if ((s1 == 0) && (s2 == 0) && (home.st_ino == cur.st_ino)){
+    /* ~/.visrc == .visrc : Source the file only once */
+    status1 = Cmd_CommandExecute(hmgr, "source -s ~/.visrc");
+  }
+  else {
+    if (s1 == 0) {
+      status1 = Cmd_CommandExecute(hmgr, "source -s ~/.visrc");
+    }
+    if (s2 == 0) {
+      status2 = Cmd_CommandExecute(hmgr, "source -s .visrc");
+    }
+  }
+
+  return (status0 && status1 && status2);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Prints the usage of the VIS shell interface.]
+
+  SideEffects []
+
+  SeeAlso     [optional]
+
+******************************************************************************/
+static void
+UsagePrint(
+  char * program)
+{
+  char *libraryName;
+  
+  (void) fprintf(vis_stderr,
+                 "%s\n", Vm_VisReadVersion());
+  (void) fprintf(vis_stderr,
+                 "usage: %s [-c cmd] [-f script] [-h] [-o file] [-s] [-t type] [-T type] [-x] [file]\n", 
+                 program);
+  (void) fprintf(vis_stderr,
+                 "    -c cmd\texecute VIS commands `cmd'\n");
+  (void) fprintf(vis_stderr,
+                 "    -f file\texecute VIS commands from a file\n");
+  (void) fprintf(vis_stderr,
+                 "    -h\t\tprint the command usage\n");
+  (void) fprintf(vis_stderr,
+                 "    -o file\tspecify output filename (default is -)\n");
+  (void) fprintf(vis_stderr,
+                 "    -s\t\tdo not read any initialization file\n");
+  libraryName = Vm_VisObtainLibrary();
+  (void) fprintf(vis_stderr,
+                 "      \t\t(%s/master.visrc, ~/.visrc)\n", libraryName);
+  FREE(libraryName);
+  (void) fprintf(vis_stderr,
+                 "    -t type\tspecify input type (blif_mv (default), blif, or none)\n");
+  (void) fprintf(vis_stderr,
+                 "    -T type\tspecify output type (blif_mv (default), blif, smv, or none)\n");
+  (void) fprintf(vis_stderr,
+                 "    -x\t\tequivalent to '-t none -T none'\n");
+
+  exit(2);
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns 1 if s is a file type recognized by VIS, else returns 0.]
+
+  Description [Returns 1 if s is a file type recognized by VIS, else returns
+  0. Recognized types are "blif", "blif_mv", and "none".]
+
+  SideEffects []
+
+******************************************************************************/
+static int
+TypeCheck(
+  char * s)
+{
+  if (strcmp(s, "blif") == 0) {
+    return 1;
+  }
+  else if (strcmp(s, "blif_mv") == 0) {
+    return 1;
+  }
+  else if (strcmp(s, "smv") == 0) {
+    return 1;
+  }
+  else if (strcmp(s, "none") == 0) {
+    return 1;
+  }
+  else {
+    (void) fprintf(vis_stderr, "unknown type %s\n", s);
+    return 0;
+  }
+}
Index: vis_dev/vis-2.3/src/vm/vmVers.c
===================================================================
--- vis_dev/vis-2.3/src/vm/vmVers.c	(revision 14)
+++ vis_dev/vis-2.3/src/vm/vmVers.c	(revision 14)
@@ -0,0 +1,218 @@
+/**CFile***********************************************************************
+
+  FileName    [vmVers.c]
+
+  PackageName [vm]
+
+  Synopsis    [Supplies the compile date and version information.]
+
+  Author      [Originated from SIS]
+
+  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
+  All rights reserved.
+
+  Permission is hereby granted, without written agreement and without license
+  or royalty fees, to use, copy, modify, and distribute this software and its
+  documentation for any purpose, provided that the above copyright notice and
+  the following two paragraphs appear in all copies of this software.
+
+  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
+  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
+  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
+
+******************************************************************************/
+
+#include "vmInt.h"
+
+static char rcsid[] UNUSED = "$Id: vmVers.c,v 1.3 2002/09/08 21:47:31 fabio Exp $";
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations                                                     */
+/*---------------------------------------------------------------------------*/
+#ifndef CUR_DATE
+#define CUR_DATE	"<compile date not supplied>"
+#endif
+
+#ifndef CUR_VER
+#define CUR_VER         "UC Berkeley, VIS Release 1.0"
+#endif
+
+#ifndef LIBRARY
+#define LIBRARY		"/projects/vis/vis/common/vis_lib"
+#endif
+
+
+/**AutomaticStart*************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes                                                */
+/*---------------------------------------------------------------------------*/
+
+static char * DateReadFromDateString(char * datestr);
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the current VIS version.]
+
+  Description [Returns a static string giving the VIS version and compile
+  timestamp.  The user should not free this string.]
+  
+  SideEffects []
+
+  SeeAlso     [Vm_VisObtainLibrary]
+
+******************************************************************************/
+char *
+Vm_VisReadVersion(void)
+{
+  static char version[1024];
+
+  (void) sprintf(version, "%s (compiled %s)", CUR_VER, DateReadFromDateString(CUR_DATE));
+  return version;
+}
+
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the VIS library path.]
+
+  Description [Returns a string giving the directory which contains the
+  standard VIS library.  Used to find things like the default .visrc, the
+  on-line help files, etc. It is the responsibility of the user to free the
+  returned string.]
+
+  SideEffects []
+
+  SeeAlso     [Vm_VisReadVersion]
+
+******************************************************************************/
+char *
+Vm_VisObtainLibrary(void)
+{
+  char * vis_lib_path;
+
+  vis_lib_path = getenv("VIS_LIBRARY_PATH");
+  if (vis_lib_path) {
+    return util_tilde_expand(vis_lib_path);
+  } else {
+    return util_tilde_expand(LIBRARY);
+  }
+}
+
+/**Function********************************************************************
+
+  Synopsis           [Start piping stdout through the "more" command]
+
+  Description        [This function is  called to initialize piping
+  stdout through "more". It is important to call Vm_VisEndPrintMore before
+  returning from your function and after
+  calling Vm_VisInitPrintMore (preferably at the end of your printing;
+  failing to do so will cause the stdin lines not to appear).]
+
+  SideEffects        []
+
+  SeeAlso            [ Vm_VisEndPrintMore]
+
+******************************************************************************/
+void
+Vm_VisInitPrintMore(void)
+{
+    fflush(vis_stdout);
+    vis_stdpipe = popen("more","w"); 
+}
+/**Function********************************************************************
+
+  Synopsis           [Stop piping stdout through the "more" command]
+
+  Description        [This function is  called to terminate piping
+  stdout through "more". It is important to call Vm_VisEndPrintMore  before exiting
+  your function (preferably at the end of your printing; failing to do so will cause
+  the stdin lines not to appear). The function returns a 0 if it fails.]
+
+  SideEffects        []
+
+  SeeAlso            [ Vm_VisInitPrintMore]
+
+******************************************************************************/
+int
+Vm_VisEndPrintMore(void)
+{
+    if (vis_stdpipe != NIL(FILE)) {  
+    (void) pclose(vis_stdpipe);
+    return 1;
+    }
+    return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions                                          */
+/*---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static functions                                            */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+  Synopsis    [Returns the date in a brief format assuming its coming from
+  the program `date'.]
+
+  Description [optional]
+
+  SideEffects []
+
+******************************************************************************/
+static char *
+DateReadFromDateString(
+  char * datestr)
+{
+  static char result[25];
+  char        day[10];
+  char        month[10];
+  char        zone[10];
+  char       *at;
+  int         date;
+  int         hour;
+  int         minute;
+  int         second;
+  int         year;
+
+  if (sscanf(datestr, "%s %s %2d %2d:%2d:%2d %s %4d",
+             day, month, &date, &hour, &minute, &second, zone, &year) == 8) {
+    if (hour >= 12) {
+      if (hour >= 13) hour -= 12;
+      at = "PM";
+    }
+    else {
+      if (hour == 0) hour = 12;
+      at = "AM";
+    }
+    (void) sprintf(result, "%d-%3s-%02d at %d:%02d %s", 
+                   date, month, year % 100, hour, minute, at);
+    return result;
+  }
+  else {
+    return datestr;
+  }
+}
+
+
+
+
+
Index: vis_dev/vis-2.3/vis.1
===================================================================
--- vis_dev/vis-2.3/vis.1	(revision 14)
+++ vis_dev/vis-2.3/vis.1	(revision 14)
@@ -0,0 +1,121 @@
+.\" $Id: vis.1,v 1.3 2001/04/13 20:45:04 rbloem Exp $
+.\"
+.TH vis 1 "April 11, 2001" "Release 1.4"
+.LO 1
+.SH NAME
+Vis \- Verification Interacting with Synthesis
+.SH SYNOPSIS
+.B vis  
+[\-c cmd] [\-f 
+.I script
+] [\-h] [\-o 
+.I file
+] [\-s] [\-t type] [\-T type] [\-x] [
+.I file
+]
+.SH DESCRIPTION
+.B Vis
+is a system for formal verification, synthesis, and simulation of finite state
+systems. It has been developed jointly at the University of California at
+Berkeley and the University of Colorado at Boulder.
+.PP
+Vis is primarily used interactively, using a prompt system.  Most help on its
+commands is given within vis: type
+.B help 
+at the vis command prompt.  The 
+.I examples 
+directory gives some examples of how
+to use vis.  The definitive documentation resides at the Vis Home Page.  This
+man page concentrates on the command options.
+.PP
+Vis works interactively if invoked without any options.  Vis can also be called
+in batch mode, using 
+.B -c 
+or
+.B -f.
+In this case, either 
+.B -x
+needs to be specified, or the last argument needs to denote a file. 
+.PP
+The case in which 
+.B -x 
+is not specified is only used in practice for synthesis.
+.I File
+is read before the script is executed, and after execution another file is
+written.  The details are determined by the
+.B -t, -T, 
+and
+.B -o
+flags.  It is probably easier to incorporate the reading and writing
+of the file in the script.
+.SH OPTIONS
+.TP
+.B  \-\^c cmd 
+ Execute VIS commands `cmd'.
+.TP
+.BR  "\-\^f " file
+Execute script containing vis commands
+.TP
+.B  \-\^h          
+Print the command usage
+.TP 
+.BR "-\^o  " file
+Specify output filename (default is -)
+.TP
+.B \-\^s 
+Do not read any initialization file.  If not specified, the files 
+.I $VIS_LIBRARY_PATH/master.visrc, 
+and 
+.I $HOME/.visrc
+are executed in that order.
+.TP 
+.B \-\^t type
+ specify input type (blif_mv (default), blif, or none)
+.TP
+.B \-\^x
+Equivalent to '-t none -T none'
+.\"
+.SH EXAMPLES
+.TP
+.B vis\^
+Calls vis interactively
+.TP
+.BI "vis -x -f " file\^
+Executes the named vis script.
+.\"
+.SH FILES
+The scripts
+.I $VIS_LIBRARY_PATH/master.visrc, 
+and 
+.I $HOME/.visrc
+are read in that order before any other script executes.  They are used to
+define aliases and the like.
+.\"
+.SH ENVIRONMENT
+.B $VIS_LIBRARY_PATH
+determines the location of the master visrc file and the help files.
+.\"
+.SH NOTES
+Vis will produce line-buffered output if you set vis_stdout and
+vis_stderr from the vis prompt.  In any case, you can force vis to
+flush the output by sending it a USR1 signal, using kill.
+.\"
+.SH BUGS
+For optimum performance, set the 
+.B datasize limit 
+to a reasonable size (such as something less than the amount of RAM
+you have).
+.\"
+.SH "SEE ALSO"
+The Vis Home Page: 
+.UR http://vlsi.colorado.edu/~vis
+http://vlsi.colorado.edu/~vis
+.UE
+.PP
+R. K. Brayton et al, 
+.I VIS:  A system for verification and synthesis, 
+Eighth Conference on Computer Aided Verification (CAV'96), pp. 428-432, 1996.
+.PP
+.BR limit (1),
+.BR kill(1).
+
Index: vis_dev/vis-2.3/xsimv
===================================================================
--- vis_dev/vis-2.3/xsimv	(revision 14)
+++ vis_dev/vis-2.3/xsimv	(revision 14)
@@ -0,0 +1,993 @@
+#!/bin/sh
+# The next line restarts using expectk \
+exec expectk "$0" "$@"
+
+#***********
+#  The comments with the code here are meant to address the details of the
+#  code itself, not the functionality of XsimView.  Refer to the XsimView's 
+#  man page for a discussion of functionality.
+#
+#  The overall algorithm of XsimView is described at the bottom of the code
+#  below where the "main" of XsimView is given.  The anciliary procedures 
+#  are desribed in turn below.
+#-----------
+
+
+#**********
+# source     fileSelect.src
+#
+# why:       fileSelect provides the ability to save files.  Here, it
+#            is used to allow the user to select a filename so that in.simv,
+#            the temporary file used for output, can be saved to whatever
+#            name they desire.
+
+# All from fileSelect.src
+# Begins the file loading process.  Can take one argument, fileName
+# which would specify the file being loaded, in which case,
+# fileSelect process is skipped and the file is directly loaded.
+proc loadFile {{file {}} {type {}}} {
+	global globals
+	set globals(optList) {}
+	# if file is empty, ask user for new file, if still empty, exit
+	# since they must have hit cancel or something else went wrong
+	if {$file == {}} {set file [fileSelect Load]}
+	if {$file == {}} {return}
+
+	# if type is nil, then 
+	# find the final letters after last . to get file type
+	if {$type == {}} {
+		set type [string range [file extension $file] 1 end]
+	}
+	if {$globals(options)} {
+		switch -- $type {
+			mv		{set globals(optList) \
+						[optionRead $globals(read_blif_mvOptions)]}
+			blif	{set globals(optList) \
+						[optionRead $globals(read_blifOptions)]}
+			vl		{set globals(optList) \
+						[optionRead $globals(read_verilogOptions)]}
+			fair	{set globals(optList) \
+						[optionRead $globals(read_fairnessOptions)]}
+			ctl	{set globals(optList) \
+						[optionRead $globals(model_checkOptions)]}
+		}
+	}
+	switch -- $type {
+		mv		{Send "rlmv $globals(optList) $file"}
+		blif	{Send "read_blif $file"}
+		vl		{Send "read_verilog $file"}
+		fair	{Send "read_fairness $file"}
+		ctl	{Send "model_check $file"}
+		default	{loadFile "$file [giveFileType $file]"}
+	}
+}
+
+proc writeFile {{file {}} {type {}}} {
+	global globals
+	set globals(optList) {}
+	# if file is empty, ask user for filename to write to.
+	# If still empty, then they must have hit cancel or something
+	if {$file == {}} {set file [fileSelect Write]}
+	if {$file == {}} {return}
+
+	# find the final letters after last . to get file type
+	set type [string range [file extension $file] 1 end]
+	if {$globals(options)} {
+		switch -- $type {
+			mv		{set globals(optList) \
+						[optionRead $globals(write_blif_mvOptions)]}
+			blif	{set globals(optList) \
+						[optionRead $globals(austin_write_blifOptions)]}
+		}
+	}
+	switch -- $type {
+			mv		{Send "write_blif_mv $globals(optList) $file"}
+			blif	{Send "austin_write_blif $globals(optList) $file"}
+			default	{writeFile "$file.[giveFileType $file]"}
+	}
+}
+
+proc giveFileType {file} {
+	global temp globals
+	toplevel .q
+	set gFTDone 0
+
+	wm title .q "What type of file?"
+	set short [string range $file [expr [string last / $file] + 1] end]
+	message .q.msg -text "What type is $short ?"
+	pack .q.msg -side top
+	bind .q <Return> {set gFTDone 1}
+
+	# Set up radio buttons for type of file to load
+	frame .q.radio
+	foreach type {{blif blif} {blif_mv mv}  {verilog vl} {fairness fair}} {
+		radiobutton .q.radio.[lindex $type 1] -variable temp \
+			-text [lindex $type 0] -value [lindex $type 1]
+		pack .q.radio.[lindex $type 1] -side top
+	}
+	pack .q.radio -side top
+
+	# Create the OK button
+	# The OK button has a rim to indicate it is the default
+	frame .q.button -bd 10
+	frame .q.button.ok -bd 2 -relief sunken
+	button .q.button.ok.b -text OK -command {set gFTDone 1}
+	pack .q.button.ok.b
+	pack .q.button.ok -side top
+	pack .q.button -side top
+
+	tkwait variable gFTDone
+	destroy .q
+	return $temp
+}
+
+proc fileSelect {why {default {}}} {
+	global fileSelect globals
+	set globals(options) 0
+	set fileSelect(why) $why
+	catch {destroy .fileSelect}
+	set t [toplevel .fileSelect -bd 4]
+
+	wm title $t $why
+	message $t.msg -aspect 1000 -text $why
+	pack $t.msg -side top -fill x
+
+	# Create a read_only entry for the current pwd
+	set fileSelect(dirEnt) [entry $t.dir -width 15 \
+		-relief flat -state disabled]
+	pack $t.dir -side top -fill x
+
+	# Create an entry for the pathname
+	# The value is kept in the fileSelect(path)
+	frame $t.top
+	label $t.top.l -text "File:" -padx 0
+	set e [entry $t.top.path -relief sunken -textvariable fileSelect(path)]
+	pack $t.top -side top -fill x
+	pack $t.top.l -side left
+	pack $t.top.path -side right -fill x -expand true
+	set fileSelect(pathEnt) $e
+
+	# Use $e to set up bindings for entry widget
+	bind $e <Return> fileSelectOK
+	bind $e <Control-c> fileSelectCancel
+	bind $e <space> fileSelectComplete
+	focus $e
+
+	# Create a listbox to hold the directory contents
+	listbox $t.list -yscrollcommand [list $t.scroll set]
+	scrollbar $t.scroll -command [list $t.list yview]
+	# A single click copies the name into the entry
+	# A double-click selects the name
+	bind $t.list <Button-1> {fileSelectClick %y}
+	bind $t.list <Double-Button-1> {
+		fileSelectClick %y;
+		fileSelectOK
+	}
+
+	# Create the OK and cancel buttons and options button
+	# The OK button has a rim to indicate it is the default
+	frame $t.buttons -bd 10
+	frame $t.buttons.ok -bd 2 -relief sunken
+	button $t.buttons.ok.b -text OK -command fileSelectOK
+	button $t.buttons.cancel -text Cancel -command fileSelectCancel
+	checkbutton $t.buttons.options -text "Choose Options" \
+		-variable globals(options)
+
+	# Pack the list, scrollbar and button box
+	# in a horizontal stack below the upper widgets
+	pack $t.list -side left -fill both -expand true
+	pack $t.scroll -side left -fill both
+	pack $t.buttons -side left -fill both
+	pack $t.buttons.ok $t.buttons.cancel $t.buttons.options -side top \
+		-padx 10 -pady 5
+	pack $t.buttons.ok.b -padx 4 -pady 4
+
+	# Initialize variables in the directory
+	set fileSelect(path) {}
+	set dir [pwd]
+
+	set fileSelect(dir) {}
+	set fileSelect(done) 0
+
+	# Wait for the listbox to be visible so we
+	# can provide feedback during the listing
+	tkwait visibility .fileSelect.list
+	fileSelectList $dir
+
+	tkwait variable fileSelect(done)
+	destroy .fileSelect
+	return $fileSelect(path)
+}
+
+# Creates the list of dirs and files to put into the listbox, if not given
+proc fileSelectList { dir {files {}} } {
+	global fileSelect
+
+	# Update the directory
+	set e $fileSelect(dirEnt)
+	$e config -state normal
+	$e delete 0 end
+	$e insert 0 $dir
+	$e config -state disabled
+
+	# Give the user some feedback
+	set fileSelect(dir) $dir
+	.fileSelect.list delete 0 end
+	.fileSelect.list insert 0 Listing...
+
+	.fileSelect.list delete 0
+	# If files is undefined, then match all files in current dir
+	if {[string length $files] == 0} {
+		# List the directory and add an entry for the parent dir.
+		set files [glob -nocomplain $fileSelect(dir)/*]
+		.fileSelect.list insert end ../
+	}
+
+	# Take files, and sort all dirs to front
+	set dirs {}
+	set others {}
+	foreach f [lsort $files] {
+		if [file isdirectory $f] {
+			lappend dirs [file tail $f]/
+		} else {
+			lappend others [file tail $f]
+		}
+	}
+
+	# Insert all dirs and files into the listbox
+	foreach f [concat $dirs $others] {
+		.fileSelect.list insert end $f
+	}
+}
+
+
+# Checks files specified, and whether or not to return a value, or
+# make a new listbox.  Basically, first check if command is to go to 
+# parent directory.  If not, check if fileSelect(path) is a directory.
+# If so, create new list.  If not, check if is a file.  If so, return
+# the file, else, try some magic to go somewhere else. (also known
+# as file name completion.
+proc fileSelectOK {} {
+	global fileSelect
+
+	# Handle the special case of the parent directory
+	if {[regexp {\.\./} $fileSelect(path)]} {
+		set fileSelect(path) {}
+		fileSelectList [file dirname $fileSelect(dir)]
+		return
+	}
+
+	# create a full path from fileSelect(dir) and fileSelect(path)
+	set path $fileSelect(dir)/$fileSelect(path)
+	if [file isdirectory $path] {
+		set fileSelect(path) {}
+		fileSelectList $path
+		return
+	}
+	if [file exists $path] {
+		set fileSelect(path) $path
+		set fileSelect(done) 1
+		return
+	}
+
+	# Neither a file nor a directory
+	# See if a glob will find something
+	# catch returns true if something goes wrong
+	if [catch {glob $path} files] {
+		# Okay, maybe they typed in a new absolute pathname and we
+		# should try fileSelect(path) as the ENTIRE path name
+		if [catch {glob $fileSelect(path)} path] {
+			# Okay, nothing there, if we're writing, then accept as 
+			# as new filename, else try filename completion.
+			if {[string match $fileSelect(why) Write]} {
+				set fileSelect(done) 1
+				return
+			} else {
+				# Try file name completion
+				fileSelectComplete
+				return
+			}
+		} else {
+		# OK - there are files there, so let's reassign the dir and path
+		set fileSelect(dir) [file dirname $fileSelect(path)]
+		set fileSelect(path) [file tail $fileSelect(path)]
+		fileSelectOK
+		return
+		}
+	} else {
+		# Current directory has stuff in it, catch returned no error
+		# Ok - current directory is ok, select file or list 'em.
+		if {[llength [split $files]] == 1} {
+			set fileSelect(path) $files
+			fileSelectOK
+		} else {
+			set fileSelect(dir) [file dirname [lindex $files 0]]
+			fileSelectList $fileSelect(dir) $files
+		}
+	}
+}
+
+# Quits out of fileSelection and moves on.
+proc fileSelectCancel {} {
+	global fileSelect
+	set fileSelect(done) 1
+	set fileSelect(path) {}
+}
+
+# Find the file the user clicked on.
+proc fileSelectClick { y } {
+	# Take the item the user clicked on
+	global fileSelect
+	set l .fileSelect.list
+	set fileSelect(path) [$l get [$l nearest $y]]
+	focus $fileSelect(pathEnt)
+}
+
+# Big nasty routine to do file name completion
+proc fileSelectComplete {} {
+	global fileSelect
+
+	# Do name completion, Nuke something.
+	set fileSelect(path) [string trim $fileSelect(path) \t\ ]
+
+	# Figure out what directory we are looking at,
+	# dir is directory, tail is partial name
+	if {[string match /* $fileSelect(path)]} {
+		set dir [file dirname $fileSelect(path)]
+		set tail [file tail $fileSelect(path)]
+	} elseif [string match ~* $fileSelect(path)] {
+		if [catch {file dirname $fileSelect(path)} dir] {
+			return;		# Bad user
+		}
+		set tail [file tail $fileSelect(path)]
+	} else {
+		set path $fileSelect(dir)/$fileSelect(path)
+		set dir [file dirname $path]
+		set tail [file tail $path]
+	}
+
+	# See what files are there
+	set files [glob -nocomplain $dir/$tail*]
+	if {[llength [split $files]] == 1} {
+		# Matched a single file
+		set fileSelect(dir) $dir
+		set fileSelect(path) [file tail $files]
+	} else {
+		if {[llength [split $files]] > 1} {
+			# Find the longest common prefix
+			set l [expr [string length $tail]-1]
+			set miss 0
+			# remember that files has absolute paths
+			set file1 [file tail [lindex $files 0]]
+			while {$miss == 0} {
+				incr l
+				if {$l == [string length $file1]} {
+					# file1 is a prefix of all others
+					break
+				}
+				set new [string range $file1 0 $l]
+				foreach f $files {
+					if ![string match $new* [file tail $f]] {
+						set miss 1
+						incr l -1
+						break
+					}
+				}
+			}
+			set fileSelect(path) [string range $file1 0 $l]
+		}
+		fileSelectList $dir $files
+	}
+}
+
+
+#**********
+# procedure match
+#
+# input:     string       is a string of characters
+#            file         is a string of characters that holds a file name.
+#
+# function:  open the file given by input "file" and iteratively look for
+#            a text line in "file" that a) does not start with a "#", and 
+#            b) whose first word (text string) matches input "string".  Upon
+#            finding such a line that meets this criteria, procedure match
+#            returns a 1.  If EOF is reached before a line meeting the said
+#            criteria is found, then procedure match returns a 0.
+#            
+proc match {string file} {
+
+    set f [open $file r]
+
+    while {1} {
+
+	set cnt [gets $f inline]
+	if {$cnt ==  -1} {
+	    close $f
+	    return 0
+	}
+	set y [split $inline {}]
+	set y1 [lindex $y 0]
+	if {$y1 != "#"} {
+	    if {$string ==  $inline} {
+		close $f
+		return 1
+	    }
+	}
+    }
+}
+ 
+
+#********************
+#  procedure parse
+#
+#  input     sf       string that holds name of sim output file.
+#  
+#  output    none
+#
+#  function  described with the code below.
+proc parse {sf} {
+ 
+
+# the following are globals.
+# observe                 is to hold all of the variables eligible for display.
+# ninps, nlats, nouts     are to hold the number of inputs, latches, outputs.
+# cy                      is to hold the variable values for each cycle.
+# ncy                     is to hold the number of cycles 
+# what                    is to hold the identity of each variable (input, latch, output).
+ 
+	global observe ninps nlats nouts
+	global cy ncy
+	global what
+
+# the following globals are the display preference variables.
+# see the man page for a discussion of these variables.
+	global bgtop bg1 bg2
+	global fgtop fg1 fg2
+	global fonttop font1 font2
+	global hlinescolor vlinescolor
+	global cybarbg cybarfg
+ 
+# open the sim output file for parsing.
+	set f [open $sf r]
+ 
+# find the .inputs, .latches, .outputs, and .initial lines in the sim output file
+# and make lists out of them.
+	set finps 0
+	set flats 0
+	set fouts 0
+	set finit 0
+	while {$finps == 0 || $flats == 0 || $fouts == 0 || $finit == 0}  {
+	    set cnt [gets $f inline]
+	    if {$cnt == -1} {break}
+	    split $inline
+	    set first [lindex $inline 0]
+	    switch $first {
+		".inputs" {
+		    set inps [lreplace $inline 0 0]
+		    set ninps [llength $inps]
+		    set finps 1
+		    for {set j 0} {$j < $ninps} {incr j} {
+			lappend what (I)
+		    }
+		}
+		".latches" {
+		    set lats [lreplace $inline 0 0]
+		    set nlats [llength $lats]
+		    set flats 1
+		    for {set j 0} {$j < $nlats} {incr j} {
+			lappend what (L)
+		    }
+		}
+		".outputs" {
+		    set outs [lreplace $inline 0 0]
+		    set nouts [llength $outs]
+		    set fouts 1
+		    for {set j 0} {$j < $nouts} {incr j} {
+			lappend what (O)
+		    }
+		}
+		".initial" {
+			set finit 1
+		}
+	    }
+	}
+ 
+# if any of the .inputs, .latches, .outputs, or .initial lines are not
+# found, exit with an Error.
+	if {$finps ==  0} {
+		puts "ERROR: No .inputs line was found!"
+		return -1
+	}
+	if {$flats ==  0} {
+		puts "ERROR: No .latches line was found!"
+		return -1
+	}
+	if {$fouts ==  0} { 
+		puts "ERROR: No .outputs line was found!"
+		return -1
+	}
+	if {$finit ==  0} {
+		puts "ERROR: No .initial line was found!"
+		return -1
+	}
+ 
+# list observe holds all the variables eligible to be viewed.
+# here the list of variables is dumped to the strike file (strk.simv)
+# so user can later access and select variables to strike.
+	set observe [concat $inps $lats $outs]
+	set ff [open strk.simv w]
+	foreach i $observe {
+	    puts $ff $i
+	}
+	close $ff
+
+# Set defaults for the display preferences.
+#
+	set bgtop Grey 
+	set bg1 White
+	set bg2 Black
+	set fgtop Black
+	set fg1 Black
+	set fg2 White 
+	set fonttop -adobe-courier-bold-r-normal--12-120-75-75-m-70-iso8859-1 
+	set font1 -adobe-courier-bold-r-normal--12-120-75-75-m-70-iso8859-1 
+	set font2 -adobe-courier-bold-r-normal--12-120-75-75-m-70-iso8859-1 
+	set hlinescolor White 
+	set vlinescolor Yellow 
+	set cybarbg Blue 
+	set cybarfg White 
+
+# And put them in the preferences file.
+#
+	set ff [open prefs.simv w]
+
+	puts $ff "bgtop $bgtop"
+	puts $ff "bg1 $bg1"
+	puts $ff "bg2 $bg2"
+	puts $ff "fgtop $fgtop"
+	puts $ff "fg1 $fg1"
+	puts $ff "fg2 $fg2"
+	puts $ff "fonttop $fonttop"
+	puts $ff "font1 $font1"
+	puts $ff "font2 $font2"
+	puts $ff "hlinescolor $hlinescolor"
+	puts $ff "vlinescolor $vlinescolor"
+	puts $ff "cybarbg $cybarbg"
+	puts $ff "cybarfg $cybarfg"
+
+	close $ff
+ 
+# the following lines of code look for the beginning of the portion of
+# the sim output file that contains the cycle information and upon 
+# finding it stores it in "array" for further processing.
+	set i 0
+	while {1} {
+		set cnt [gets $f inline]
+		if {$cnt ==  -1} {break}
+		set y [split $inline {}]
+		set y1 [lindex $y 0]
+		if {$y1 ==  {} || $y1 ==  "#" || $y1 ==  "."} {continue}
+		set array($i) $inline
+		incr i 1
+	}
+	set ncy $i
+	close $f
+
+# if no cycle lines were found, exit with an Error.
+	if {$cnt ==  -1 && $i ==  0} {
+		puts "ERROR: No simulation results found!"
+		return -1
+	}
+
+# the following lines of code parse the contents of "array" into
+# "cy".  each list in "array" is itself a list of strings, this step turns
+# the cycle information so that each element in "cy" is a simple list of 
+# strings. 
+	for {set j 0} {$j < $i} {incr j} {
+	    set z [split $array($j) \;]
+	    set p [lindex $z 0]
+	    set q [lindex $z 1]
+	    set r [lindex $z 2]
+	    set cy($j) [concat $p $q $r]
+	}
+ 
+}
+ 
+#*************
+# procedure strike
+#
+# inputs      sf      string that holds file name
+# 
+# outputs     none
+#
+# function    Reads the contents of the file pointed to by input "sf" and
+#             based on its contents generates an array of flags that indicate
+#             whether a given variable should be displayed.  The array of 
+#             flags is in one-to-one correspondence with the array of variables
+#             that are eligible to be displayed.
+proc strike {} {
+ 
+    global observe
+    global show nshow
+ 
+    set nshow 0
+ 
+    set nobvs [llength $observe]
+    set j 0
+    for {set i 0} {$i < $nobvs} {incr i} {
+	set m [match [lindex $observe $i] strk.simv]
+	if {$m ==  0} {
+	    lappend show 0
+	} else {
+	    lappend show 1
+	    incr nshow
+	}
+    }
+}
+ 
+#*************
+# procedure readprefs
+#
+# inputs      pf       string that holds file name
+#
+# outputs     none
+#
+# function    Reads the contents of the file pointed to by input "pf" and
+#             sets the values of the preferences accordingly.  See the "man"
+#             page for description of the preferences currently supported.
+#
+proc readprefs {} {
+ 
+    global bgtop bg1 bg2
+    global fgtop fg1 fg2
+    global fonttop font1 font2
+    global hlinescolor vlinescolor
+    global cybarbg cybarfg
+    global run
+
+    set bgtop 0
+    set bg1 0
+    set bg2 0
+    set fgtop 0
+    set fg1 0
+    set fg2 0
+    set fonttop 0
+    set font1 0
+    set font2 0
+    set hlinescolor 0
+    set vlinescolor 0
+    set cybarbg 0
+    set cybarfg 0
+ 
+    set f [open prefs.simv r]
+ 
+    while {1} {
+
+	set cnt [gets $f inline]
+	if {$cnt ==  -1} {break}
+	set first [lindex $inline 0]
+ 
+	switch $first {
+	    bgtop { set bgtop [lindex $inline 1] }
+	    bg1 { set bg1 [lindex $inline 1] }
+	    bg2 { set bg2 [lindex $inline 1] }
+	    fgtop { set fgtop [lindex $inline 1] }
+	    fg1 { set fg1 [lindex $inline 1] }
+	    fg2 { set fg2 [lindex $inline 1] }
+	    fonttop { set fonttop [lindex $inline 1] }
+	    font1 { set font1 [lindex $inline 1] }
+	    font2 { set font2 [lindex $inline 1] }
+	    hlinescolor { set hlinescolor [lindex $inline 1] }
+	    vlinescolor { set vlinescolor [lindex $inline 1] }
+	    cybarbg { set cybarbg [lindex $inline 1] }
+	    cybarfg { set cybarfg [lindex $inline 1] }
+	}
+    }
+
+    close $f
+
+}
+
+#****************
+# procedure findlongestvar
+#
+# input        none
+#
+# output       none
+#
+# function     This procedure operates on the parsed lists of variables names and
+#              values for each cycle to find a) the longest variable name, and b) 
+#              the longest value of any given variable.  These values are then used
+#              to set the corresponding field widths in the display.
+#
+proc findlongestvar {} {
+    
+    global observe
+    global show
+    global cywidth varwidth
+    global cy ncy
+
+    set nobvs [llength $observe]
+
+    set maxlen 0
+    for {set i 0} {$i < $nobvs} {incr i} {
+	set active [lindex $show $i]
+	if {$active == 1} {
+	    set str [lindex $observe $i]
+	    set len [string length $str]
+	    if {$len > $maxlen} {set maxlen $len}
+	}
+    }
+    set varwidth [expr ($maxlen+2)*0.25]
+
+    set maxlen 0
+    for {set i 0} {$i < $ncy} {incr i} {
+	for {set j 0} {$j < $nobvs} {incr j} {
+	    set active [lindex $show $j]
+	    if {$active == 1} {
+		set str [lindex $cy($i) $j]
+		set len [string length $str]
+		if {$len > $maxlen} {set maxlen $len}
+	    }
+	}
+    }
+# Takes care of finding the maximum width for cycle width
+    set cywidth_cycleInfo [expr (log($ncy)+2)*0.25]
+    set cywidth_dataInfo [expr ($maxlen+2)*0.25]
+
+    if {$cywidth_cycleInfo > $cywidth_dataInfo} {
+        set cywidth $cywidth_cycleInfo
+    } else {
+        set cywidth $cywidth_dataInfo
+    }
+
+}
+
+#***************
+# procedure drawcanvas
+#
+# input       none
+# 
+# output      none
+#
+# function    This procedure carries out the actual displaying.  It is described alongside
+#             with the code below.
+#
+proc drawcanvas {} {
+
+#---------
+# these globals are the display preferences, they are read
+# from file dprefs by procedure readprefs:
+#
+# varwidth	holds the width of the left-most column that
+#		lists the variables under observation
+# cywidth	holds the width of the cycle columns that
+#		lists the value of the variables for each
+#		cycle.
+#
+
+    global varwidth
+    global cywidth
+ 
+#---------
+# the following globals hold the items to be
+# displayed:
+#
+# cy 		is the array of lists, each element is a list 
+#    		of the value of the items for that cycle,
+# ncy 	        is the number of elements in cy,
+# show 	        is an array that marks those elements in cy and
+#    		observe that are to be displayed, (i.e. after
+#		some of the elements in observe are striken based
+#		on the contents of the strike file.
+# nshow 	is the number of "1" elements in show,
+# observe 	is a list of _all_ the items that _can_ be displayed.
+# what          is an array that identifies a variable as either an input, latch, or output.
+#
+    global cy ncy
+    global show nshow
+    global observe
+    global what
+ 
+
+#-------------
+# the following globals are the prefrences variables.
+#
+    global bgtop bg1 bg2
+    global fgtop fg1 fg2
+    global fonttop font1 font2
+    global hlinescolor vlinescolor
+    global cybarbg cybarfg
+
+#------------
+# here the top level widget that holds the results display is
+# created and the two canvases that will be used to construct
+# the display are defined.
+
+# this width and height is a good start for a workstation monitor,
+# of course, the window can be resized in the usual way.
+#
+    set wwidth 800
+    set wheight 500
+
+    global infile
+    global t
+    set t .top
+    toplevel $t 
+    wm geometry $t ${wwidth}x${wheight}
+    wm title $t "XsimView 0.1"
+    set c1 $t.canvas1
+    set c2 $t.canvas2
+
+# the top of the display holds generic information.
+#
+    text $t.text -font $fonttop -bg $bgtop -fg $fgtop
+    text $t.text1 -font $fonttop -bg $bgtop -fg $fgtop
+    $t.text insert 1.0 "XSimView Rev. 0.1 (April 1996)\n"
+    $t.text insert 2.0 "by J.S. Duran\n"
+    $t.text insert 3.0 "ECE Department\n"
+    $t.text insert 4.0 "UT Austin\n"
+    $t.text1 insert 1.0 "Displaying file: $infile"
+    place $t.text -x 0 -y 0 -relwidth 1.0
+    place $t.text1 -relx 0.5 -y 0
+ 
+#---------------
+# build the higher level canvas (holds the variable names at the left-most
+# of the display and also holds the lower level canvas).
+#
+    set c1w [expr $wwidth]
+    set c1h [expr $nshow+1]
+    set c1dims [list 0 0 ${c1w} ${c1h}c]
+    canvas $c1 -relief sunken -borderwidth 2 -scrollregion $c1dims -yscrollcommand "$t.vscroll set" -bg ${bg1}
+    scrollbar $t.vscroll -command "$c1 yview"
+    place $t.vscroll -relx 0.98 -rely 0.15 -relheight 0.85 -width 0.5c
+    place $c1 -x 0 -rely 0.15 -relheight 0.85 -relwidth 1.0
+ 
+    set f $c1.frame
+    frame $f -relief sunken -borderwidth 2 
+    $c1 create window ${varwidth}c 0 -anchor nw -height ${c1h}c -width ${wwidth} -window $f
+
+#------------
+# build the lower level canvas (holds the per cycle variable value information).
+#
+    set c2xlen [expr $ncy*$cywidth*1.25]
+    set c2scrl [list 0 0 ${c2xlen}c ${c1h}c]
+    set hsw [expr $wwidth-$varwidth*40]
+    canvas $f.c2 -relief sunken -borderwidth 2 -scrollregion $c2scrl -xscrollcommand "$t.hscroll set" -bg ${bg2}
+    place $f.c2 -x 0 -y 0 -relheight 1.0 -relwidth 1.0
+    scrollbar $t.hscroll -orient horiz -command "$f.c2 xview"
+    place $t.hscroll -x 0 -rely 0.125 -height 0.5c -relwidth 1.0
+
+#------------
+# place the variable names on the higher level canvas.  also draw the horizontal grid
+# lines in the lower level canvas.
+#
+    set q [llength $show]
+    set v 1
+    for {set i 0} {$i < $q} {incr i} {
+	set sh [lindex $show $i]
+	if {$sh ==  1} {
+	    set item1 [lindex $observe $i]
+	    set item2 [lindex $what $i]
+	    set item $item1$item2    
+	    $c1 create text ${varwidth}c ${v}c -text $item -anchor ne -fill $fg1 -font $font1
+	    $f.c2 create line 0 [expr $v+0.4]c ${c2xlen}c [expr $v+0.4]c -fill $hlinescolor
+	    incr v
+	}
+    }
+
+#-----------
+# place the per cycle data on the lower level canvas.  also draw the vertical grid lines on the
+# lower level canvas and generate the cycle number bar at the top of the lower level canvas.
+#
+    set over1 [expr $cywidth*0.5]
+    set over2 $cywidth
+    set xtx $over1
+    set xln $over2
+    set xrc1 0
+    set xrc2 $over2
+    for {set i 0} {$i < $ncy} {incr i} {
+	$f.c2 create rectangle ${xrc1}c 0 ${xrc2}c 0.5c -fill $cybarbg -outline $vlinescolor
+	set cylabel "CY$i"
+	$f.c2 create text ${xtx}c 0.25c -width ${cywidth}c -text $cylabel -fill $cybarfg -justify center -font $font2
+	$f.c2 create line ${xln}c 0 ${xln}c ${c1h}c -fill $vlinescolor
+	set v 1
+	for {set k 0} {$k < $q} {incr k} {
+	    set sh [lindex $show $k]
+	    if {$sh ==  1} {
+		set item [lindex $cy($i) $k]
+		$f.c2 create text ${xtx}c ${v}c -width ${cywidth}c -text $item -fill $fg2 -justify center -font $font2
+		incr v
+	    }
+	}
+	set xtx [expr $xtx+$cywidth]
+	set xln [expr $xln+$cywidth]
+	set xrc1 [expr $xrc1+$cywidth]
+	set xrc2 [expr $xrc2+$cywidth]
+    }
+
+    unset show
+
+}
+
+
+#############################################
+# main body of XsimView
+#
+
+#-------
+# parse the command line (either one argument -- sim output file name --
+# or none.
+#
+
+global infile
+global t
+
+if {$argc == 0} {
+    set infile "in.simv"
+    puts "setting input file to in.simv\n"
+} elseif {$argc == 1} {
+    set infile [lindex $argv 0]
+} else {
+    puts "syntax is:  xsimview <filename>\n"
+    exit
+}
+
+######################################################
+##### FILES NECESSARY FOR SAVING
+######################################################
+
+proc doSave {} {
+	set file [fileSelect Write]
+	catch {exec cp in.simv $file}
+}
+
+####################################################
+##### END FILES NECESSARY FOR SAVING
+####################################################
+
+#------------------
+# initialization sequence.
+# 
+# parse the sim output file (only needs to be done once).
+# open the main window for XsimView
+# 
+parse $infile
+wm title . "XsimView 0.1"
+button .go -text GO -command {
+    strike
+    findlongestvar
+    readprefs
+    drawcanvas
+}
+button .redraw -text ReDraw -command {
+    destroy $t
+    strike
+    findlongestvar
+    readprefs
+    drawcanvas
+}
+button .save -text Save -command {doSave}
+button .quit -text Quit -command {destroy .}
+
+pack .go -side left -padx 2m -pady 2m
+pack .redraw -side left -padx 2m -pady 2m
+pack .save -side left -padx 2m -pady 2m
+pack .quit -side left -padx 2m -pady 2m
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
